From 0d44d83e619f6c45597c11b37f3e36e942d22cc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89lo=C3=AFs?= Date: Wed, 29 Sep 2021 22:10:12 +0200 Subject: [PATCH 001/695] add feature wasmtime-jitdump (#9871) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add feature wasmtime-jitdump * remove unwrap * always enable wasmtime/jitdump feature * env WASMTIME_PROFILING_STRATEGY: retun an error for unknown value * Add doc for env var WASMTIME_PROFILING_STRATEGY * Update client/executor/wasmtime/Cargo.toml Co-authored-by: Sergei Shulepov * warning instead of error * Update client/executor/wasmtime/src/runtime.rs Co-authored-by: Bastian Köcher * update doc: unknown value cause warning instead of error * log warning only once * static right next to the usage Co-authored-by: Sergei Shulepov Co-authored-by: Bastian Köcher --- Cargo.lock | 23 +++++++++++++++++++++++ client/executor/wasmtime/Cargo.toml | 6 +++++- client/executor/wasmtime/src/lib.rs | 12 +++++++++++- client/executor/wasmtime/src/runtime.rs | 22 +++++++++++++++++++++- 4 files changed, 60 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cdde83426187..0e3f3399dbf6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8691,6 +8691,26 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "scroll" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fda28d4b4830b807a8b43f7b0e6b5df875311b3e7621d84577188c175b6ec1ec" +dependencies = [ + "scroll_derive", +] + +[[package]] +name = "scroll_derive" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aaaae8f38bb311444cfb7f1979af0bc9240d95795f75f9ceddf6a59b79ceffa0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "sct" version = "0.6.0" @@ -11609,8 +11629,11 @@ checksum = "21486cfb5255c2069666c1f116f9e949d4e35c9a494f11112fa407879e42198d" dependencies = [ "anyhow", "cfg-if 1.0.0", + "gimli 0.25.0", "lazy_static", "libc", + "object 0.26.0", + "scroll", "serde", "target-lexicon 0.12.0", "wasmtime-environ", diff --git a/client/executor/wasmtime/Cargo.toml b/client/executor/wasmtime/Cargo.toml index edf174752426..c122b3ab0e69 100644 --- a/client/executor/wasmtime/Cargo.toml +++ b/client/executor/wasmtime/Cargo.toml @@ -23,7 +23,11 @@ sp-wasm-interface = { version = "4.0.0-dev", path = "../../../primitives/wasm-in sp-runtime-interface = { version = "4.0.0-dev", path = "../../../primitives/runtime-interface" } sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" } sc-allocator = { version = "4.0.0-dev", path = "../../allocator" } -wasmtime = { version = "0.29.0", default-features = false, features = ["cache", "parallel-compilation"] } +wasmtime = { version = "0.29.0", default-features = false, features = [ + "cache", + "jitdump", + "parallel-compilation", +] } [dev-dependencies] sc-runtime-test = { version = "2.0.0", path = "../runtime-test" } diff --git a/client/executor/wasmtime/src/lib.rs b/client/executor/wasmtime/src/lib.rs index 8d7f93fecb30..e0d6a262afda 100644 --- a/client/executor/wasmtime/src/lib.rs +++ b/client/executor/wasmtime/src/lib.rs @@ -16,7 +16,17 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -/// ! Defines a `WasmRuntime` that uses the Wasmtime JIT to execute. +//! Defines a `WasmRuntime` that uses the Wasmtime JIT to execute. +//! +//! You can choose a profiling strategy at runtime with +//! environment variable `WASMTIME_PROFILING_STRATEGY`: +//! +//! | `WASMTIME_PROFILING_STRATEGY` | Effect | +//! |-------------|-------------------------| +//! | undefined | No profiling | +//! | `"jitdump"` | jitdump profiling | +//! | other value | No profiling (warning) | + mod host; mod imports; mod instance_wrapper; diff --git a/client/executor/wasmtime/src/runtime.rs b/client/executor/wasmtime/src/runtime.rs index 006f102926ec..a62356357b1f 100644 --- a/client/executor/wasmtime/src/runtime.rs +++ b/client/executor/wasmtime/src/runtime.rs @@ -38,7 +38,10 @@ use sp_wasm_interface::{Function, Pointer, Value, WordSize}; use std::{ path::{Path, PathBuf}, rc::Rc, - sync::Arc, + sync::{ + atomic::{AtomicBool, Ordering}, + Arc, + }, }; use wasmtime::{AsContext, AsContextMut, Engine, StoreLimits}; @@ -322,6 +325,23 @@ fn common_config(semantics: &Semantics) -> std::result::Result wasmtime::ProfilingStrategy::JitDump, + None => wasmtime::ProfilingStrategy::None, + Some(_) => { + // Remember if we have already logged a warning due to an unknown profiling strategy. + static UNKNOWN_PROFILING_STRATEGY: AtomicBool = AtomicBool::new(false); + // Make sure that the warning will not be relogged regularly. + if !UNKNOWN_PROFILING_STRATEGY.swap(true, Ordering::Relaxed) { + log::warn!("WASMTIME_PROFILING_STRATEGY is set to unknown value, ignored."); + } + wasmtime::ProfilingStrategy::None + }, + }; + config + .profiler(profiler) + .map_err(|e| WasmError::Instantiation(format!("fail to set profiler: {}", e)))?; + if let Some(DeterministicStackLimit { native_stack_max, .. }) = semantics.deterministic_stack_limit { From 1e28e61daf6c7687bb1899adfb1ea88ce9ab166d Mon Sep 17 00:00:00 2001 From: Dan Shields <35669742+NukeManDan@users.noreply.github.com> Date: Wed, 29 Sep 2021 21:54:45 -0600 Subject: [PATCH 002/695] subkey readme update on install (#9900) Instructions are more detailed on devhub, ported to the README. --- bin/utils/subkey/README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/bin/utils/subkey/README.md b/bin/utils/subkey/README.md index fbb486247a77..2494bff3bc9a 100644 --- a/bin/utils/subkey/README.md +++ b/bin/utils/subkey/README.md @@ -18,6 +18,19 @@ If you save any output of `subkey` into a file, make sure to apply proper permis The following guide explains *some* of the `subkey` commands. For the full list and the most up to date documentation, make sure to check the integrated help with `subkey --help`. +### Install with Cargo + +You will need to have the Substrate build dependencies to install Subkey. Use the following two commands to install the dependencies and Subkey, respectively: + +Command: + +```bash +# Use the `--fast` flag to get the dependencies without needing to install the Substrate and Subkey binary +curl https://getsubstrate.io -sSf | bash -s -- --fast +# Install only `subkey`, at a specific version of the this subkey crate +cargo install --force subkey --git https://github.com/paritytech/substrate --version --locked +``` + ### Generate a random account Generating a new key is as simple as running: From 0bc873d571cacd96959f652b27e6f5735720e305 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Thu, 30 Sep 2021 09:12:25 +0100 Subject: [PATCH 003/695] contracts: Add event field names (#9896) * Add struct variant fields to contract Event * Update comments and usages * Fmt --- frame/contracts/src/exec.rs | 25 ++++++++----- frame/contracts/src/lib.rs | 49 ++++++++++++-------------- frame/contracts/src/tests.rs | 24 ++++++++----- frame/contracts/src/wasm/code_cache.rs | 4 +-- 4 files changed, 57 insertions(+), 45 deletions(-) diff --git a/frame/contracts/src/exec.rs b/frame/contracts/src/exec.rs index cc468466c292..7fa0b0b27444 100644 --- a/frame/contracts/src/exec.rs +++ b/frame/contracts/src/exec.rs @@ -660,7 +660,10 @@ where } // Deposit an instantiation event. - deposit_event::(vec![], Event::Instantiated(self.caller().clone(), account_id)); + deposit_event::( + vec![], + Event::Instantiated { deployer: self.caller().clone(), contract: account_id }, + ); } Ok(output) @@ -942,10 +945,10 @@ where )?; ContractInfoOf::::remove(&frame.account_id); E::remove_user(info.code_hash, &mut frame.nested_meter)?; - Contracts::::deposit_event(Event::Terminated( - frame.account_id.clone(), - beneficiary.clone(), - )); + Contracts::::deposit_event(Event::Terminated { + contract: frame.account_id.clone(), + beneficiary: beneficiary.clone(), + }); Ok(()) } @@ -997,7 +1000,7 @@ where fn deposit_event(&mut self, topics: Vec, data: Vec) { deposit_event::( topics, - Event::ContractEmitted(self.top_frame().account_id.clone(), data), + Event::ContractEmitted { contract: self.top_frame().account_id.clone(), data }, ); } @@ -1662,7 +1665,10 @@ mod tests { Storage::::code_hash(&instantiated_contract_address).unwrap(), dummy_ch ); - assert_eq!(&events(), &[Event::Instantiated(ALICE, instantiated_contract_address)]); + assert_eq!( + &events(), + &[Event::Instantiated { deployer: ALICE, contract: instantiated_contract_address }] + ); }); } @@ -1751,7 +1757,10 @@ mod tests { Storage::::code_hash(&instantiated_contract_address).unwrap(), dummy_ch ); - assert_eq!(&events(), &[Event::Instantiated(BOB, instantiated_contract_address)]); + assert_eq!( + &events(), + &[Event::Instantiated { deployer: BOB, contract: instantiated_contract_address }] + ); }); } diff --git a/frame/contracts/src/lib.rs b/frame/contracts/src/lib.rs index 0d7e4cbf5647..62b74b9b7b95 100644 --- a/frame/contracts/src/lib.rs +++ b/frame/contracts/src/lib.rs @@ -369,49 +369,44 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { - /// Contract deployed by address at the specified address. \[deployer, contract\] - Instantiated(T::AccountId, T::AccountId), + /// Contract deployed by address at the specified address. + Instantiated { deployer: T::AccountId, contract: T::AccountId }, /// Contract has been removed. - /// \[contract, beneficiary\] - /// - /// # Params - /// - /// - `contract`: The contract that was terminated. - /// - `beneficiary`: The account that received the contracts remaining balance. /// /// # Note /// /// The only way for a contract to be removed and emitting this event is by calling /// `seal_terminate`. - Terminated(T::AccountId, T::AccountId), + Terminated { + /// The contract that was terminated. + contract: T::AccountId, + /// The account that received the contracts remaining balance + beneficiary: T::AccountId, + }, - /// Code with the specified hash has been stored. \[code_hash\] - CodeStored(T::Hash), + /// Code with the specified hash has been stored. + CodeStored { code_hash: T::Hash }, /// Triggered when the current schedule is updated. - /// \[version\] - /// - /// # Params - /// - /// - `version`: The version of the newly set schedule. - ScheduleUpdated(u32), + ScheduleUpdated { + /// The version of the newly set schedule. + version: u32, + }, /// A custom event emitted by the contract. - /// \[contract, data\] - /// - /// # Params - /// - /// - `contract`: The contract that emitted the event. - /// - `data`: Data supplied by the contract. Metadata generated during contract compilation - /// is needed to decode it. - ContractEmitted(T::AccountId, Vec), + ContractEmitted { + /// The contract that emitted the event. + contract: T::AccountId, + /// Data supplied by the contract. Metadata generated during contract compilation + /// is needed to decode it. + data: Vec, + }, /// A code with the specified hash was removed. - /// \[code_hash\] /// /// This happens when the last contract that uses this code hash was removed. - CodeRemoved(T::Hash), + CodeRemoved { code_hash: T::Hash }, } #[pallet::error] diff --git a/frame/contracts/src/tests.rs b/frame/contracts/src/tests.rs index f5b95c192c42..b2141ca18b0b 100644 --- a/frame/contracts/src/tests.rs +++ b/frame/contracts/src/tests.rs @@ -478,20 +478,25 @@ fn instantiate_and_call_and_deposit_event() { }, EventRecord { phase: Phase::Initialization, - event: Event::Contracts(crate::Event::CodeStored(code_hash.into())), + event: Event::Contracts(crate::Event::CodeStored { + code_hash: code_hash.into() + }), topics: vec![], }, EventRecord { phase: Phase::Initialization, - event: Event::Contracts(crate::Event::ContractEmitted( - addr.clone(), - vec![1, 2, 3, 4] - )), + event: Event::Contracts(crate::Event::ContractEmitted { + contract: addr.clone(), + data: vec![1, 2, 3, 4] + }), topics: vec![], }, EventRecord { phase: Phase::Initialization, - event: Event::Contracts(crate::Event::Instantiated(ALICE, addr.clone())), + event: Event::Contracts(crate::Event::Instantiated { + deployer: ALICE, + contract: addr.clone() + }), topics: vec![], }, ] @@ -764,12 +769,15 @@ fn self_destruct_works() { }, EventRecord { phase: Phase::Initialization, - event: Event::Contracts(crate::Event::CodeRemoved(code_hash)), + event: Event::Contracts(crate::Event::CodeRemoved { code_hash }), topics: vec![], }, EventRecord { phase: Phase::Initialization, - event: Event::Contracts(crate::Event::Terminated(addr.clone(), DJANGO)), + event: Event::Contracts(crate::Event::Terminated { + contract: addr.clone(), + beneficiary: DJANGO + }), topics: vec![], }, ], diff --git a/frame/contracts/src/wasm/code_cache.rs b/frame/contracts/src/wasm/code_cache.rs index 08a7449683ed..afb68d4d8117 100644 --- a/frame/contracts/src/wasm/code_cache.rs +++ b/frame/contracts/src/wasm/code_cache.rs @@ -59,7 +59,7 @@ where Some(module) => increment_64(&mut module.refcount), None => { *existing = Some(prefab_module); - Contracts::::deposit_event(Event::CodeStored(code_hash)) + Contracts::::deposit_event(Event::CodeStored { code_hash }) }, }); } @@ -170,7 +170,7 @@ where T::AccountId: UncheckedFrom + AsRef<[u8]>, { >::remove(code_hash); - Contracts::::deposit_event(Event::CodeRemoved(code_hash)) + Contracts::::deposit_event(Event::CodeRemoved { code_hash }) } /// Increment the refcount panicking if it should ever overflow (which will not happen). From fb443761341790f1c6a2aca41088bef2daa33258 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Thu, 30 Sep 2021 14:58:28 +0200 Subject: [PATCH 004/695] Fix basic authorship flaky test (#9906) The test is flaky because sometimes we hit the 9 seconds deadline when the CI was probably on high load. To "solve" this we just use an huge deadline that should never be triggered. The deadline isn't required anyway. --- client/basic-authorship/src/basic_authorship.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/basic-authorship/src/basic_authorship.rs b/client/basic-authorship/src/basic_authorship.rs index 144a3ab6850f..e38bb11688f8 100644 --- a/client/basic-authorship/src/basic_authorship.rs +++ b/client/basic-authorship/src/basic_authorship.rs @@ -718,7 +718,7 @@ mod tests { ); // when - let deadline = time::Duration::from_secs(9); + let deadline = time::Duration::from_secs(900); let block = block_on(proposer.propose(Default::default(), Default::default(), deadline, None)) .map(|r| r.block) From e6b015062e60cc713ed5b0158d8c540c231852dc Mon Sep 17 00:00:00 2001 From: zjb0807 Date: Thu, 30 Sep 2021 21:22:54 +0800 Subject: [PATCH 005/695] Fix democracy on-initialize weight (#9890) * fix democracy on-initialize weight * fix tests * add base weight on LaunchPeriod * fix fmt check * trigger GitHub actions * trigger GitHub actions * update weights --- frame/democracy/src/benchmarking.rs | 34 ++++- frame/democracy/src/lib.rs | 25 +-- frame/democracy/src/weights.rs | 227 +++++++++++++++------------- 3 files changed, 173 insertions(+), 113 deletions(-) diff --git a/frame/democracy/src/benchmarking.rs b/frame/democracy/src/benchmarking.rs index a00e6f4686fd..63d409dac25a 100644 --- a/frame/democracy/src/benchmarking.rs +++ b/frame/democracy/src/benchmarking.rs @@ -422,7 +422,39 @@ benchmarks! { assert_eq!(Democracy::::referendum_count(), r, "referenda not created"); assert_eq!(Democracy::::lowest_unbaked(), 0, "invalid referenda init"); - }: { Democracy::::on_initialize(0u32.into()) } + }: { Democracy::::on_initialize(1u32.into()) } + verify { + // All should be on going + for i in 0 .. r { + if let Some(value) = ReferendumInfoOf::::get(i) { + match value { + ReferendumInfo::Finished { .. } => return Err("Referendum has been finished".into()), + ReferendumInfo::Ongoing(_) => (), + } + } + } + } + + on_initialize_base_with_launch_period { + let r in 1 .. MAX_REFERENDUMS; + + for i in 0..r { + add_referendum::(i)?; + } + + for (key, mut info) in ReferendumInfoOf::::iter() { + if let ReferendumInfo::Ongoing(ref mut status) = info { + status.end += 100u32.into(); + } + ReferendumInfoOf::::insert(key, info); + } + + assert_eq!(Democracy::::referendum_count(), r, "referenda not created"); + assert_eq!(Democracy::::lowest_unbaked(), 0, "invalid referenda init"); + + let block_number = T::LaunchPeriod::get(); + + }: { Democracy::::on_initialize(block_number) } verify { // All should be on going for i in 0 .. r { diff --git a/frame/democracy/src/lib.rs b/frame/democracy/src/lib.rs index 8bc6921c4f8a..24f823a17e10 100644 --- a/frame/democracy/src/lib.rs +++ b/frame/democracy/src/lib.rs @@ -1726,7 +1726,8 @@ impl Pallet { /// /// /// # - /// If a referendum is launched or maturing, this will take full block weight. Otherwise: + /// If a referendum is launched or maturing, this will take full block weight if queue is not + /// empty. Otherwise: /// - Complexity: `O(R)` where `R` is the number of unbaked referenda. /// - Db reads: `LastTabledWasExternal`, `NextExternal`, `PublicProps`, `account`, /// `ReferendumCount`, `LowestUnbaked` @@ -1737,18 +1738,24 @@ impl Pallet { let max_block_weight = T::BlockWeights::get().max_block; let mut weight = 0; + let next = Self::lowest_unbaked(); + let last = Self::referendum_count(); + let r = last.saturating_sub(next); + // pick out another public referendum if it's time. if (now % T::LaunchPeriod::get()).is_zero() { - // Errors come from the queue being empty. we don't really care about that, and even if - // we did, there is nothing we can do here. - let _ = Self::launch_next(now); - weight = max_block_weight; + // Errors come from the queue being empty. If the queue is not empty, it will take + // full block weight. + if Self::launch_next(now).is_ok() { + weight = max_block_weight; + } else { + weight = + weight.saturating_add(T::WeightInfo::on_initialize_base_with_launch_period(r)); + } + } else { + weight = weight.saturating_add(T::WeightInfo::on_initialize_base(r)); } - let next = Self::lowest_unbaked(); - let last = Self::referendum_count(); - let r = last.saturating_sub(next); - weight = weight.saturating_add(T::WeightInfo::on_initialize_base(r)); // tally up votes for any expiring referenda. for (index, info) in Self::maturing_referenda_at_inner(now, next..last).into_iter() { let approved = Self::bake_referendum(now, index, info)?; diff --git a/frame/democracy/src/weights.rs b/frame/democracy/src/weights.rs index e3f22f4fc0ab..638852d3c7e1 100644 --- a/frame/democracy/src/weights.rs +++ b/frame/democracy/src/weights.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_democracy //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-08-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2021-09-30, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 // Executed Command: @@ -60,6 +60,7 @@ pub trait WeightInfo { fn cancel_referendum() -> Weight; fn cancel_queued(r: u32, ) -> Weight; fn on_initialize_base(r: u32, ) -> Weight; + fn on_initialize_base_with_launch_period(r: u32, ) -> Weight; fn delegate(r: u32, ) -> Weight; fn undelegate(r: u32, ) -> Weight; fn clear_public_proposals() -> Weight; @@ -80,15 +81,15 @@ impl WeightInfo for SubstrateWeight { // Storage: Democracy Blacklist (r:1 w:0) // Storage: Democracy DepositOf (r:0 w:1) fn propose() -> Weight { - (65_665_000 as Weight) + (67_388_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Democracy DepositOf (r:1 w:1) fn second(s: u32, ) -> Weight { - (40_003_000 as Weight) - // Standard Error: 1_000 - .saturating_add((180_000 as Weight).saturating_mul(s as Weight)) + (41_157_000 as Weight) + // Standard Error: 0 + .saturating_add((157_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -96,9 +97,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Democracy VotingOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_new(r: u32, ) -> Weight { - (45_465_000 as Weight) + (46_406_000 as Weight) // Standard Error: 1_000 - .saturating_add((220_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((170_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -106,16 +107,16 @@ impl WeightInfo for SubstrateWeight { // Storage: Democracy VotingOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_existing(r: u32, ) -> Weight { - (45_112_000 as Weight) + (46_071_000 as Weight) // Standard Error: 1_000 - .saturating_add((222_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((166_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy Cancellations (r:1 w:1) fn emergency_cancel() -> Weight { - (26_651_000 as Weight) + (27_699_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -126,45 +127,45 @@ impl WeightInfo for SubstrateWeight { // Storage: Democracy DepositOf (r:1 w:1) // Storage: System Account (r:1 w:1) fn blacklist(p: u32, ) -> Weight { - (77_737_000 as Weight) + (82_703_000 as Weight) // Standard Error: 4_000 - .saturating_add((512_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((500_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy Blacklist (r:1 w:0) fn external_propose(v: u32, ) -> Weight { - (13_126_000 as Weight) + (13_747_000 as Weight) // Standard Error: 0 - .saturating_add((89_000 as Weight).saturating_mul(v as Weight)) + .saturating_add((76_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Democracy NextExternal (r:0 w:1) fn external_propose_majority() -> Weight { - (2_923_000 as Weight) + (3_070_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Democracy NextExternal (r:0 w:1) fn external_propose_default() -> Weight { - (2_889_000 as Weight) + (3_080_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy ReferendumCount (r:1 w:1) // Storage: Democracy ReferendumInfoOf (r:0 w:1) fn fast_track() -> Weight { - (27_598_000 as Weight) + (29_129_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy Blacklist (r:1 w:1) fn veto_external(v: u32, ) -> Weight { - (28_416_000 as Weight) + (30_105_000 as Weight) // Standard Error: 0 - .saturating_add((132_000 as Weight).saturating_mul(v as Weight)) + .saturating_add((104_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -172,36 +173,46 @@ impl WeightInfo for SubstrateWeight { // Storage: Democracy DepositOf (r:1 w:1) // Storage: System Account (r:1 w:1) fn cancel_proposal(p: u32, ) -> Weight { - (52_836_000 as Weight) - // Standard Error: 2_000 - .saturating_add((478_000 as Weight).saturating_mul(p as Weight)) + (55_228_000 as Weight) + // Standard Error: 1_000 + .saturating_add((457_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Democracy ReferendumInfoOf (r:0 w:1) fn cancel_referendum() -> Weight { - (16_891_000 as Weight) + (17_319_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Scheduler Lookup (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) fn cancel_queued(r: u32, ) -> Weight { - (30_504_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_480_000 as Weight).saturating_mul(r as Weight)) + (29_738_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_153_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } - // Storage: Democracy LastTabledWasExternal (r:1 w:0) - // Storage: Democracy NextExternal (r:1 w:0) - // Storage: Democracy PublicProps (r:1 w:0) // Storage: Democracy LowestUnbaked (r:1 w:0) // Storage: Democracy ReferendumCount (r:1 w:0) // Storage: Democracy ReferendumInfoOf (r:1 w:0) fn on_initialize_base(r: u32, ) -> Weight { - (6_259_000 as Weight) + (2_165_000 as Weight) + // Standard Error: 3_000 + .saturating_add((5_577_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(r as Weight))) + } + // Storage: Democracy LowestUnbaked (r:1 w:0) + // Storage: Democracy ReferendumCount (r:1 w:0) + // Storage: Democracy LastTabledWasExternal (r:1 w:0) + // Storage: Democracy NextExternal (r:1 w:0) + // Storage: Democracy PublicProps (r:1 w:0) + // Storage: Democracy ReferendumInfoOf (r:1 w:0) + fn on_initialize_base_with_launch_period(r: u32, ) -> Weight { + (9_396_000 as Weight) // Standard Error: 4_000 - .saturating_add((5_032_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((5_604_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(r as Weight))) } @@ -209,9 +220,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn delegate(r: u32, ) -> Weight { - (51_719_000 as Weight) - // Standard Error: 5_000 - .saturating_add((7_210_000 as Weight).saturating_mul(r as Weight)) + (57_783_000 as Weight) + // Standard Error: 4_000 + .saturating_add((7_623_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(4 as Weight)) @@ -220,9 +231,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Democracy VotingOf (r:2 w:2) // Storage: Democracy ReferendumInfoOf (r:1 w:1) fn undelegate(r: u32, ) -> Weight { - (23_203_000 as Weight) - // Standard Error: 5_000 - .saturating_add((7_206_000 as Weight).saturating_mul(r as Weight)) + (26_027_000 as Weight) + // Standard Error: 4_000 + .saturating_add((7_593_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -230,31 +241,31 @@ impl WeightInfo for SubstrateWeight { } // Storage: Democracy PublicProps (r:0 w:1) fn clear_public_proposals() -> Weight { - (3_127_000 as Weight) + (2_780_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Democracy Preimages (r:1 w:1) fn note_preimage(b: u32, ) -> Weight { - (44_130_000 as Weight) + (46_416_000 as Weight) // Standard Error: 0 - .saturating_add((3_000 as Weight).saturating_mul(b as Weight)) + .saturating_add((2_000 as Weight).saturating_mul(b as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Democracy Preimages (r:1 w:1) fn note_imminent_preimage(b: u32, ) -> Weight { - (28_756_000 as Weight) + (29_735_000 as Weight) // Standard Error: 0 - .saturating_add((3_000 as Weight).saturating_mul(b as Weight)) + .saturating_add((2_000 as Weight).saturating_mul(b as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Democracy Preimages (r:1 w:1) // Storage: System Account (r:1 w:0) fn reap_preimage(b: u32, ) -> Weight { - (39_922_000 as Weight) + (41_276_000 as Weight) // Standard Error: 0 - .saturating_add((2_000 as Weight).saturating_mul(b as Weight)) + .saturating_add((1_000 as Weight).saturating_mul(b as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -262,9 +273,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn unlock_remove(r: u32, ) -> Weight { - (38_621_000 as Weight) + (40_348_000 as Weight) // Standard Error: 1_000 - .saturating_add((110_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((60_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -272,27 +283,27 @@ impl WeightInfo for SubstrateWeight { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn unlock_set(r: u32, ) -> Weight { - (36_631_000 as Weight) + (37_475_000 as Weight) // Standard Error: 1_000 - .saturating_add((214_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((151_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy VotingOf (r:1 w:1) fn remove_vote(r: u32, ) -> Weight { - (21_025_000 as Weight) + (19_970_000 as Weight) // Standard Error: 1_000 - .saturating_add((195_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((153_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy VotingOf (r:1 w:1) fn remove_other_vote(r: u32, ) -> Weight { - (20_628_000 as Weight) + (20_094_000 as Weight) // Standard Error: 1_000 - .saturating_add((214_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((157_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -305,15 +316,15 @@ impl WeightInfo for () { // Storage: Democracy Blacklist (r:1 w:0) // Storage: Democracy DepositOf (r:0 w:1) fn propose() -> Weight { - (65_665_000 as Weight) + (67_388_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } // Storage: Democracy DepositOf (r:1 w:1) fn second(s: u32, ) -> Weight { - (40_003_000 as Weight) - // Standard Error: 1_000 - .saturating_add((180_000 as Weight).saturating_mul(s as Weight)) + (41_157_000 as Weight) + // Standard Error: 0 + .saturating_add((157_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -321,9 +332,9 @@ impl WeightInfo for () { // Storage: Democracy VotingOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_new(r: u32, ) -> Weight { - (45_465_000 as Weight) + (46_406_000 as Weight) // Standard Error: 1_000 - .saturating_add((220_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((170_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -331,16 +342,16 @@ impl WeightInfo for () { // Storage: Democracy VotingOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_existing(r: u32, ) -> Weight { - (45_112_000 as Weight) + (46_071_000 as Weight) // Standard Error: 1_000 - .saturating_add((222_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((166_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy Cancellations (r:1 w:1) fn emergency_cancel() -> Weight { - (26_651_000 as Weight) + (27_699_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -351,45 +362,45 @@ impl WeightInfo for () { // Storage: Democracy DepositOf (r:1 w:1) // Storage: System Account (r:1 w:1) fn blacklist(p: u32, ) -> Weight { - (77_737_000 as Weight) + (82_703_000 as Weight) // Standard Error: 4_000 - .saturating_add((512_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((500_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy Blacklist (r:1 w:0) fn external_propose(v: u32, ) -> Weight { - (13_126_000 as Weight) + (13_747_000 as Weight) // Standard Error: 0 - .saturating_add((89_000 as Weight).saturating_mul(v as Weight)) + .saturating_add((76_000 as Weight).saturating_mul(v as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Democracy NextExternal (r:0 w:1) fn external_propose_majority() -> Weight { - (2_923_000 as Weight) + (3_070_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Democracy NextExternal (r:0 w:1) fn external_propose_default() -> Weight { - (2_889_000 as Weight) + (3_080_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy ReferendumCount (r:1 w:1) // Storage: Democracy ReferendumInfoOf (r:0 w:1) fn fast_track() -> Weight { - (27_598_000 as Weight) + (29_129_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy Blacklist (r:1 w:1) fn veto_external(v: u32, ) -> Weight { - (28_416_000 as Weight) + (30_105_000 as Weight) // Standard Error: 0 - .saturating_add((132_000 as Weight).saturating_mul(v as Weight)) + .saturating_add((104_000 as Weight).saturating_mul(v as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -397,36 +408,46 @@ impl WeightInfo for () { // Storage: Democracy DepositOf (r:1 w:1) // Storage: System Account (r:1 w:1) fn cancel_proposal(p: u32, ) -> Weight { - (52_836_000 as Weight) - // Standard Error: 2_000 - .saturating_add((478_000 as Weight).saturating_mul(p as Weight)) + (55_228_000 as Weight) + // Standard Error: 1_000 + .saturating_add((457_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } // Storage: Democracy ReferendumInfoOf (r:0 w:1) fn cancel_referendum() -> Weight { - (16_891_000 as Weight) + (17_319_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Scheduler Lookup (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) fn cancel_queued(r: u32, ) -> Weight { - (30_504_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_480_000 as Weight).saturating_mul(r as Weight)) + (29_738_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_153_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } - // Storage: Democracy LastTabledWasExternal (r:1 w:0) - // Storage: Democracy NextExternal (r:1 w:0) - // Storage: Democracy PublicProps (r:1 w:0) // Storage: Democracy LowestUnbaked (r:1 w:0) // Storage: Democracy ReferendumCount (r:1 w:0) // Storage: Democracy ReferendumInfoOf (r:1 w:0) fn on_initialize_base(r: u32, ) -> Weight { - (6_259_000 as Weight) + (2_165_000 as Weight) + // Standard Error: 3_000 + .saturating_add((5_577_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(RocksDbWeight::get().reads(2 as Weight)) + .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(r as Weight))) + } + // Storage: Democracy LowestUnbaked (r:1 w:0) + // Storage: Democracy ReferendumCount (r:1 w:0) + // Storage: Democracy LastTabledWasExternal (r:1 w:0) + // Storage: Democracy NextExternal (r:1 w:0) + // Storage: Democracy PublicProps (r:1 w:0) + // Storage: Democracy ReferendumInfoOf (r:1 w:0) + fn on_initialize_base_with_launch_period(r: u32, ) -> Weight { + (9_396_000 as Weight) // Standard Error: 4_000 - .saturating_add((5_032_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((5_604_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(r as Weight))) } @@ -434,9 +455,9 @@ impl WeightInfo for () { // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn delegate(r: u32, ) -> Weight { - (51_719_000 as Weight) - // Standard Error: 5_000 - .saturating_add((7_210_000 as Weight).saturating_mul(r as Weight)) + (57_783_000 as Weight) + // Standard Error: 4_000 + .saturating_add((7_623_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) @@ -445,9 +466,9 @@ impl WeightInfo for () { // Storage: Democracy VotingOf (r:2 w:2) // Storage: Democracy ReferendumInfoOf (r:1 w:1) fn undelegate(r: u32, ) -> Weight { - (23_203_000 as Weight) - // Standard Error: 5_000 - .saturating_add((7_206_000 as Weight).saturating_mul(r as Weight)) + (26_027_000 as Weight) + // Standard Error: 4_000 + .saturating_add((7_593_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) @@ -455,31 +476,31 @@ impl WeightInfo for () { } // Storage: Democracy PublicProps (r:0 w:1) fn clear_public_proposals() -> Weight { - (3_127_000 as Weight) + (2_780_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Democracy Preimages (r:1 w:1) fn note_preimage(b: u32, ) -> Weight { - (44_130_000 as Weight) + (46_416_000 as Weight) // Standard Error: 0 - .saturating_add((3_000 as Weight).saturating_mul(b as Weight)) + .saturating_add((2_000 as Weight).saturating_mul(b as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Democracy Preimages (r:1 w:1) fn note_imminent_preimage(b: u32, ) -> Weight { - (28_756_000 as Weight) + (29_735_000 as Weight) // Standard Error: 0 - .saturating_add((3_000 as Weight).saturating_mul(b as Weight)) + .saturating_add((2_000 as Weight).saturating_mul(b as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Democracy Preimages (r:1 w:1) // Storage: System Account (r:1 w:0) fn reap_preimage(b: u32, ) -> Weight { - (39_922_000 as Weight) + (41_276_000 as Weight) // Standard Error: 0 - .saturating_add((2_000 as Weight).saturating_mul(b as Weight)) + .saturating_add((1_000 as Weight).saturating_mul(b as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -487,9 +508,9 @@ impl WeightInfo for () { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn unlock_remove(r: u32, ) -> Weight { - (38_621_000 as Weight) + (40_348_000 as Weight) // Standard Error: 1_000 - .saturating_add((110_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((60_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -497,27 +518,27 @@ impl WeightInfo for () { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn unlock_set(r: u32, ) -> Weight { - (36_631_000 as Weight) + (37_475_000 as Weight) // Standard Error: 1_000 - .saturating_add((214_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((151_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy VotingOf (r:1 w:1) fn remove_vote(r: u32, ) -> Weight { - (21_025_000 as Weight) + (19_970_000 as Weight) // Standard Error: 1_000 - .saturating_add((195_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((153_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy VotingOf (r:1 w:1) fn remove_other_vote(r: u32, ) -> Weight { - (20_628_000 as Weight) + (20_094_000 as Weight) // Standard Error: 1_000 - .saturating_add((214_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((157_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } From 70b4a8af2007a5ab6bb0f501cac393e343debb1e Mon Sep 17 00:00:00 2001 From: Robert Klotzner Date: Thu, 30 Sep 2021 16:42:08 +0200 Subject: [PATCH 006/695] Silence alert about large-statement-fetcher (#9882) * Silence alert about large-statement-fetcher That task is not continuous and behaving exactly as desired. * Get rid of rule completely - Pierre thinks it does not add any value - Basti rightly complains that Polkadot specific exceptions make little sense in the Substrate repo. --- .../monitoring/alerting-rules/alerting-rules.yaml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/.maintain/monitoring/alerting-rules/alerting-rules.yaml b/.maintain/monitoring/alerting-rules/alerting-rules.yaml index 7a69cba66c3f..271161002433 100644 --- a/.maintain/monitoring/alerting-rules/alerting-rules.yaml +++ b/.maintain/monitoring/alerting-rules/alerting-rules.yaml @@ -133,16 +133,6 @@ groups: # Others ############################################################################## - - alert: ContinuousTaskEnded - expr: '(polkadot_tasks_spawned_total{task_name != "basic-authorship-proposer", task_name != "substrate-rpc-subscription"} == 1) - - on(instance, task_name) group_left() (polkadot_tasks_ended_total == 1)' - for: 5m - labels: - severity: warning - annotations: - message: 'Continuous task {{ $labels.task_name }} on node - {{ $labels.instance }} ended unexpectedly.' - - alert: AuthorityDiscoveryDiscoveryFailureHigh expr: 'polkadot_authority_discovery_handle_value_found_event_failure / ignoring(name) From 8b95e236582c209a1676d75a1db61a4916faabf5 Mon Sep 17 00:00:00 2001 From: Denis Pisarev Date: Thu, 30 Sep 2021 17:12:28 +0200 Subject: [PATCH 007/695] doc: subkey usage (#9905) * CI: md styling * CI: add container usage --- bin/utils/subkey/README.md | 101 ++++++++++++++++++++++++++----------- 1 file changed, 72 insertions(+), 29 deletions(-) diff --git a/bin/utils/subkey/README.md b/bin/utils/subkey/README.md index 2494bff3bc9a..2310c59f4a28 100644 --- a/bin/utils/subkey/README.md +++ b/bin/utils/subkey/README.md @@ -27,19 +27,28 @@ Command: ```bash # Use the `--fast` flag to get the dependencies without needing to install the Substrate and Subkey binary curl https://getsubstrate.io -sSf | bash -s -- --fast -# Install only `subkey`, at a specific version of the this subkey crate +# Install only `subkey`, at a specific version of the subkey crate cargo install --force subkey --git https://github.com/paritytech/substrate --version --locked ``` +### Run in a container + +```bash +# Use `--pull=always` with the `latest` tag, or specify a version in a tag +docker run -it --pull=always docker.io/parity/subkey:latest +``` + ### Generate a random account Generating a new key is as simple as running: - subkey generate +```bash +subkey generate +``` The output looks similar to: -``` +```text Secret phrase `hotel forest jar hover kite book view eight stuff angle legend defense` is account: Secret seed: 0xa05c75731970cc7868a2fb7cb577353cd5b31f62dccced92c441acd8fee0c92d Public key (hex): 0xfec70cfbf1977c6965b5af10a4534a6a35d548eb14580594d0bc543286892515 @@ -63,6 +72,7 @@ The **SS58 address** (or **Public Address**) of a new account is a reprensentati You can read more about the SS58 format in the [substrate wiki](https://github.com/paritytech/substrate/wiki/External-Address-Format-(SS58)) and see the list of reserved prefixes in the [Polkadot wiki](https://wiki.polkadot.network/docs/build-ss58-registry). For instance, considering the previous seed `0xa05c75731970cc7868a2fb7cb577353cd5b31f62dccced92c441acd8fee0c92d` the SS58 addresses are: + - Polkadot: `16m4J167Mptt8UXL8aGSAi7U2FnPpPxZHPrCgMG9KJzVoFqM` - Kusama: `JLNozAv8QeLSbLFwe2UvWeKKE4yvmDbfGxTuiYkF2BUMx4M` @@ -71,12 +81,14 @@ For instance, considering the previous seed `0xa05c75731970cc7868a2fb7cb577353cd `subkey` can calso generate the output as *json*. This is useful for automation. command: -``` + +```bash subkey generate --output-type json ``` output: -``` + +```json { "accountId": "0xfec70cfbf1977c6965b5af10a4534a6a35d548eb14580594d0bc543286892515", "publicKey": "0xfec70cfbf1977c6965b5af10a4534a6a35d548eb14580594d0bc543286892515", @@ -89,12 +101,14 @@ output: So if you only want to get the `secretSeed` for instance, you can use: command: -``` + +```bash subkey generate --output-type json | jq -r .secretSeed ``` output: -``` + +```text 0xa05c75731970cc7868a2fb7cb577353cd5b31f62dccced92c441acd8fee0c92d ``` @@ -102,10 +116,13 @@ output: `subkey` supports an additional user-defined secret that will be appended to the seed. Let's see the following example: - subkey generate --password extra_secret +```bash +subkey generate --password extra_secret +``` output: -``` + +```text Secret phrase `soup lyrics media market way crouch elevator put moon useful question wide` is account: Secret seed: 0xe7cfd179d6537a676cb94bac3b5c5c9cb1550e846ac4541040d077dfbac2e7fd Public key (hex): 0xf6a233c3e1de1a2ae0486100b460b3ce3d7231ddfe9dadabbd35ab968c70905d @@ -115,11 +132,15 @@ Secret phrase `soup lyrics media market way crouch elevator put moon useful ques Using the `inspect` command (see more details below), we see that knowning only the **secret seed** is no longer sufficient to recover the account: - subkey inspect "soup lyrics media market way crouch elevator put moon useful question wide" +```bash +subkey inspect "soup lyrics media market way crouch elevator put moon useful question wide" +``` which recovers the account `5Fe4sqj2K4fRuzEGvToi4KATqZfiDU7TqynjXG6PZE2dxwyh` and not `5He5pZpc7AJ8evPuab37vJF6KkFDqq9uDq2WXh877Qw6iaVC` as we expected. The additional user-defined **password** (`extra_secret` in our example) is now required to fully recover the account. Let's inspect the the previous mnemonic, this time passing also the required `password` as shown below: - subkey inspect --password extra_secret "soup lyrics media market way crouch elevator put moon useful question wide" +```bash +subkey inspect --password extra_secret "soup lyrics media market way crouch elevator put moon useful question wide" +``` This time, we properly recovered `5He5pZpc7AJ8evPuab37vJF6KkFDqq9uDq2WXh877Qw6iaVC`. @@ -129,23 +150,29 @@ If you have *some data* about a key, `subkey inpsect` will help you discover mor If you have **secrets** that you would like to verify for instance, you can use: - subkey inspect < mnemonic | seed > +```bash +subkey inspect < mnemonic | seed > +``` If you have only **public data**, you can see a subset of the information: - subkey inspect --public < pubkey | address > +```bash +subkey inspect --public < pubkey | address > +``` **NOTE**: While you will be able to recover the secret seed from the mnemonic, the opposite is not possible. **NOTE**: For obvious reasons, the **secrets** cannot be recovered from passing **public data** such as `pubkey` or `address` as input. command: -``` + +```bash subkey inspect 0xa05c75731970cc7868a2fb7cb577353cd5b31f62dccced92c441acd8fee0c92d ``` output: -``` + +```text Secret Key URI `0xa05c75731970cc7868a2fb7cb577353cd5b31f62dccced92c441acd8fee0c92d` is account: Secret seed: 0xa05c75731970cc7868a2fb7cb577353cd5b31f62dccced92c441acd8fee0c92d Public key (hex): 0xfec70cfbf1977c6965b5af10a4534a6a35d548eb14580594d0bc543286892515 @@ -157,17 +184,23 @@ Secret Key URI `0xa05c75731970cc7868a2fb7cb577353cd5b31f62dccced92c441acd8fee0c9 `subkey` allows using a **secret key** to sign a random message. The signature can then be verified by anyone using your **public key**: - echo -n | subkey sign --suri +```bash +echo -n | subkey sign --suri +``` example: - MESSAGE=hello - SURI=0xa05c75731970cc7868a2fb7cb577353cd5b31f62dccced92c441acd8fee0c92d - echo -n $MESSAGE | subkey sign --suri $SURI +```text +MESSAGE=hello +SURI=0xa05c75731970cc7868a2fb7cb577353cd5b31f62dccced92c441acd8fee0c92d +echo -n $MESSAGE | subkey sign --suri $SURI +``` output: - 9201af3788ad4f986b800853c79da47155f2e08fde2070d866be4c27ab060466fea0623dc2b51f4392f4c61f25381a62848dd66c5d8217fae3858e469ebd668c +```text +9201af3788ad4f986b800853c79da47155f2e08fde2070d866be4c27ab060466fea0623dc2b51f4392f4c61f25381a62848dd66c5d8217fae3858e469ebd668c +``` **NOTE**: Each run of the `sign` command will yield a different output. While each signature is different, they are all valid. @@ -175,34 +208,44 @@ output: Given a message, a signature and an address, `subkey` can verify whether the **message** has been digitally signed by the holder (or one of the holders) of the **private key** for the given **address**: - echo -n | subkey verify
+```bash +echo -n | subkey verify
+``` example: - MESSAGE=hello - URI=0xfec70cfbf1977c6965b5af10a4534a6a35d548eb14580594d0bc543286892515 - SIGNATURE=9201af3788ad4f986b800853c79da47155f2e08fde2070d866be4c27ab060466fea0623dc2b51f4392f4c61f25381a62848dd66c5d8217fae3858e469ebd668c - echo -n $MESSAGE | subkey verify $SIGNATURE $URI +```bash +MESSAGE=hello +URI=0xfec70cfbf1977c6965b5af10a4534a6a35d548eb14580594d0bc543286892515 +SIGNATURE=9201af3788ad4f986b800853c79da47155f2e08fde2070d866be4c27ab060466fea0623dc2b51f4392f4c61f25381a62848dd66c5d8217fae3858e469ebd668c +echo -n $MESSAGE | subkey verify $SIGNATURE $URI +``` output: - Signature verifies correctly. +```text +Signature verifies correctly. +``` A failure looks like: - Error: SignatureInvalid +```text +Error: SignatureInvalid +``` ### Using the vanity generator You can use the included vanity generator to find a seed that provides an address which includes the desired pattern. Be warned, depending on your hardware this may take a while. command: -``` + +```bash subkey vanity --network polkadot --pattern bob ``` output: -``` + +```text Generating key containing pattern 'bob' best: 190 == top: 189 Secret Key URI `0x8c9a73097f235b84021a446bc2826a00c690ea0be3e0d81a84931cb4146d6691` is account: From 3302199c6c8acdfbb4a5858b907048c2cec502d0 Mon Sep 17 00:00:00 2001 From: Vincent Geddes Date: Thu, 30 Sep 2021 18:32:29 +0200 Subject: [PATCH 008/695] Pallet Assets: Create new asset classes from genesis config (#9742) * Pallet Assets: Allow creating asset classes from genesis config * Add accounts and metadata to genesis config * whitespace fixes * Update more chainspecs * Run rustfmt over code * More formatting fixes * Update frame/assets/src/lib.rs Improve error message Co-authored-by: Shawn Tabrizi * Update frame/assets/src/lib.rs Improve error message Co-authored-by: Shawn Tabrizi Co-authored-by: Shawn Tabrizi --- bin/node/cli/src/chain_spec.rs | 1 + bin/node/runtime/src/lib.rs | 2 +- bin/node/testing/src/genesis.rs | 1 + frame/assets/src/lib.rs | 102 +++++++++++++++++++++++++++++++- frame/assets/src/mock.rs | 23 ++++++- frame/assets/src/tests.rs | 10 ++++ 6 files changed, 133 insertions(+), 6 deletions(-) diff --git a/bin/node/cli/src/chain_spec.rs b/bin/node/cli/src/chain_spec.rs index 5e727afa304b..b5e36d9b5362 100644 --- a/bin/node/cli/src/chain_spec.rs +++ b/bin/node/cli/src/chain_spec.rs @@ -361,6 +361,7 @@ pub fn testnet_genesis( max_members: 999, }, vesting: Default::default(), + assets: Default::default(), gilt: Default::default(), transaction_storage: Default::default(), } diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 587a54ebd0d9..881641e15136 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -1280,7 +1280,7 @@ construct_runtime!( Multisig: pallet_multisig::{Pallet, Call, Storage, Event}, Bounties: pallet_bounties::{Pallet, Call, Storage, Event}, Tips: pallet_tips::{Pallet, Call, Storage, Event}, - Assets: pallet_assets::{Pallet, Call, Storage, Event}, + Assets: pallet_assets::{Pallet, Call, Storage, Event, Config}, Mmr: pallet_mmr::{Pallet, Storage}, Lottery: pallet_lottery::{Pallet, Call, Storage, Event}, Gilt: pallet_gilt::{Pallet, Call, Storage, Event, Config}, diff --git a/bin/node/testing/src/genesis.rs b/bin/node/testing/src/genesis.rs index 50c1e6f9d20b..845227c5acee 100644 --- a/bin/node/testing/src/genesis.rs +++ b/bin/node/testing/src/genesis.rs @@ -98,6 +98,7 @@ pub fn config_endowed( treasury: Default::default(), society: SocietyConfig { members: vec![alice(), bob()], pot: 0, max_members: 999 }, vesting: Default::default(), + assets: Default::default(), gilt: Default::default(), transaction_storage: Default::default(), } diff --git a/frame/assets/src/lib.rs b/frame/assets/src/lib.rs index 2c9f994b3fef..c6f24e10a89f 100644 --- a/frame/assets/src/lib.rs +++ b/frame/assets/src/lib.rs @@ -159,6 +159,9 @@ use sp_runtime::{ }; use sp_std::{borrow::Borrow, convert::TryInto, prelude::*}; +#[cfg(feature = "std")] +use frame_support::traits::GenesisBuild; + pub use pallet::*; pub use weights::WeightInfo; @@ -180,10 +183,22 @@ pub mod pallet { type Event: From> + IsType<::Event>; /// The units in which we record balances. - type Balance: Member + Parameter + AtLeast32BitUnsigned + Default + Copy + MaxEncodedLen; + type Balance: Member + + Parameter + + AtLeast32BitUnsigned + + Default + + Copy + + MaybeSerializeDeserialize + + MaxEncodedLen; /// Identifier for the class of asset. - type AssetId: Member + Parameter + Default + Copy + HasCompact + MaxEncodedLen; + type AssetId: Member + + Parameter + + Default + + Copy + + HasCompact + + MaybeSerializeDeserialize + + MaxEncodedLen; /// The currency mechanism. type Currency: ReservableCurrency; @@ -276,6 +291,89 @@ pub mod pallet { ConstU32<300_000>, >; + #[pallet::genesis_config] + pub struct GenesisConfig, I: 'static = ()> { + /// Genesis assets: id, owner, is_sufficient, min_balance + pub assets: Vec<(T::AssetId, T::AccountId, bool, T::Balance)>, + /// Genesis metadata: id, name, symbol, decimals + pub metadata: Vec<(T::AssetId, Vec, Vec, u8)>, + /// Genesis accounts: id, account_id, balance + pub accounts: Vec<(T::AssetId, T::AccountId, T::Balance)>, + } + + #[cfg(feature = "std")] + impl, I: 'static> Default for GenesisConfig { + fn default() -> Self { + Self { + assets: Default::default(), + metadata: Default::default(), + accounts: Default::default(), + } + } + } + + #[pallet::genesis_build] + impl, I: 'static> GenesisBuild for GenesisConfig { + fn build(&self) { + for (id, owner, is_sufficient, min_balance) in &self.assets { + assert!(!Asset::::contains_key(id), "Asset id already in use"); + assert!(!min_balance.is_zero(), "Min balance should not be zero"); + Asset::::insert( + id, + AssetDetails { + owner: owner.clone(), + issuer: owner.clone(), + admin: owner.clone(), + freezer: owner.clone(), + supply: Zero::zero(), + deposit: Zero::zero(), + min_balance: *min_balance, + is_sufficient: *is_sufficient, + accounts: 0, + sufficients: 0, + approvals: 0, + is_frozen: false, + }, + ); + } + + for (id, name, symbol, decimals) in &self.metadata { + assert!(Asset::::contains_key(id), "Asset does not exist"); + + let bounded_name: BoundedVec = + name.clone().try_into().expect("asset name is too long"); + let bounded_symbol: BoundedVec = + symbol.clone().try_into().expect("asset symbol is too long"); + + let metadata = AssetMetadata { + deposit: Zero::zero(), + name: bounded_name, + symbol: bounded_symbol, + decimals: *decimals, + is_frozen: false, + }; + Metadata::::insert(id, metadata); + } + + for (id, account_id, amount) in &self.accounts { + let result = >::increase_balance( + *id, + account_id, + *amount, + |details| -> DispatchResult { + debug_assert!( + T::Balance::max_value() - details.supply >= *amount, + "checked in prep; qed" + ); + details.supply = details.supply.saturating_add(*amount); + Ok(()) + }, + ); + assert!(result.is_ok()); + } + } + } + #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event, I: 'static = ()> { diff --git a/frame/assets/src/mock.rs b/frame/assets/src/mock.rs index 1b2602792d84..1e1ea8ba9a96 100644 --- a/frame/assets/src/mock.rs +++ b/frame/assets/src/mock.rs @@ -144,9 +144,26 @@ pub(crate) fn hooks() -> Vec { } pub(crate) fn new_test_ext() -> sp_io::TestExternalities { - let t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - - let mut ext = sp_io::TestExternalities::new(t); + let mut storage = frame_system::GenesisConfig::default().build_storage::().unwrap(); + + let config: pallet_assets::GenesisConfig = pallet_assets::GenesisConfig { + assets: vec![ + // id, owner, is_sufficient, min_balance + (999, 0, true, 1), + ], + metadata: vec![ + // id, name, symbol, decimals + (999, "Token Name".into(), "TOKEN".into(), 10), + ], + accounts: vec![ + // id, account_id, balance + (999, 1, 100), + ], + }; + + config.assimilate_storage(&mut storage).unwrap(); + + let mut ext: sp_io::TestExternalities = storage.into(); ext.execute_with(|| System::set_block_number(1)); ext } diff --git a/frame/assets/src/tests.rs b/frame/assets/src/tests.rs index aab534a6e4ef..872bd7290133 100644 --- a/frame/assets/src/tests.rs +++ b/frame/assets/src/tests.rs @@ -784,3 +784,13 @@ fn balance_conversion_should_work() { ); }); } + +#[test] +fn assets_from_genesis_should_exist() { + new_test_ext().execute_with(|| { + assert!(Asset::::contains_key(999)); + assert!(Metadata::::contains_key(999)); + assert_eq!(Assets::balance(999, 1), 100); + assert_eq!(Assets::total_supply(999), 100); + }); +} From bf9683eee40f82cc4e01a05cd375b0e8bba3c8ef Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Thu, 30 Sep 2021 12:46:48 -0400 Subject: [PATCH 009/695] Simple Trait to Inspect Metadata (#9893) * simple trait to inspect metadata * import vec --- frame/assets/src/impl_fungibles.rs | 19 +++++++++++++++++++ frame/support/src/traits/tokens/fungibles.rs | 13 +++++++++++++ 2 files changed, 32 insertions(+) diff --git a/frame/assets/src/impl_fungibles.rs b/frame/assets/src/impl_fungibles.rs index 25e18bfd437b..2e16a0910a4f 100644 --- a/frame/assets/src/impl_fungibles.rs +++ b/frame/assets/src/impl_fungibles.rs @@ -60,6 +60,25 @@ impl, I: 'static> fungibles::Inspect<::AccountId } } +impl, I: 'static> fungibles::InspectMetadata<::AccountId> + for Pallet +{ + /// Return the name of an asset. + fn name(asset: &Self::AssetId) -> Vec { + Metadata::::get(asset).name.to_vec() + } + + /// Return the symbol of an asset. + fn symbol(asset: &Self::AssetId) -> Vec { + Metadata::::get(asset).symbol.to_vec() + } + + /// Return the decimals of an asset. + fn decimals(asset: &Self::AssetId) -> u8 { + Metadata::::get(asset).decimals + } +} + impl, I: 'static> fungibles::Mutate<::AccountId> for Pallet { fn mint_into( asset: Self::AssetId, diff --git a/frame/support/src/traits/tokens/fungibles.rs b/frame/support/src/traits/tokens/fungibles.rs index 457ec4e8bf20..2930853201d2 100644 --- a/frame/support/src/traits/tokens/fungibles.rs +++ b/frame/support/src/traits/tokens/fungibles.rs @@ -23,6 +23,7 @@ use super::{ }; use crate::dispatch::{DispatchError, DispatchResult}; use sp_runtime::traits::Saturating; +use sp_std::vec::Vec; mod balanced; pub use balanced::{Balanced, Unbalanced}; @@ -65,6 +66,18 @@ pub trait Inspect { ) -> WithdrawConsequence; } +/// Trait for reading metadata from a fungible asset. +pub trait InspectMetadata: Inspect { + /// Return the name of an asset. + fn name(asset: &Self::AssetId) -> Vec; + + /// Return the symbol of an asset. + fn symbol(asset: &Self::AssetId) -> Vec; + + /// Return the decimals of an asset. + fn decimals(asset: &Self::AssetId) -> u8; +} + /// Trait for providing a set of named fungible assets which can be created and destroyed. pub trait Mutate: Inspect { /// Attempt to increase the `asset` balance of `who` by `amount`. From a2e7ae3ae8bf58f899c2c8f57597d2694b8c6fae Mon Sep 17 00:00:00 2001 From: Alexander Samusev <41779041+alvicsam@users.noreply.github.com> Date: Fri, 1 Oct 2021 05:54:41 +0200 Subject: [PATCH 010/695] Add build with docker section to README (#9792) Co-authored-by: Shawn Tabrizi --- docs/README.adoc | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/README.adoc b/docs/README.adoc index 71052420b1aa..05f81442d4ca 100644 --- a/docs/README.adoc +++ b/docs/README.adoc @@ -250,6 +250,20 @@ If you are trying to set up Substrate on Windows, you should do the following: 7. Finally, you need to install `cmake`: https://cmake.org/download/ +==== Docker + +You can use https://github.com/paritytech/scripts/tree/master/dockerfiles/ci-linux[Parity CI docker image] with all necessary dependencies to build Substrate: + +[source, shell] +---- +#run it in the folder with the Substrate source code +docker run --rm -it -w /shellhere/substrate \ + -v $(pwd):/shellhere/substrate \ + paritytech/ci-linux:production +---- + +You can find necessary cargo commands in <> + ==== Shared Steps Then, grab the Substrate source code: From 3d0a91789a32087b29660496593533253c88460d Mon Sep 17 00:00:00 2001 From: ucover <91202993+ucover@users.noreply.github.com> Date: Fri, 1 Oct 2021 10:17:26 +0200 Subject: [PATCH 011/695] Test each benchmark case in own #[test] (#9860) * Generate one #[test] fn per bench case. * Update benchmark macro syntax in frame pallets. * Explain new benchmark macro syntax in example pallet. * support with and without a semicolon * update pallets to use individual tests * migrate staking too * migrate more pallets * fix up democracy and use individual tests * Fix comment * Put println message in panic * Remove `another_set_dummy` from doc `another_set_dummy` is not present in the benchmarking.rs (anymore). * Update doc for benchmarks macro * Update doc for impl_benchmark_test_suite macro Co-authored-by: Shawn Tabrizi --- .../pallets/template/src/benchmarking.rs | 6 +- frame/assets/src/benchmarking.rs | 7 +- frame/babe/src/benchmarking.rs | 12 +- frame/bags-list/src/benchmarks.rs | 13 +- frame/balances/src/benchmarking.rs | 16 +- frame/benchmarking/src/lib.rs | 348 +++++++++++++++++- frame/benchmarking/src/tests_instance.rs | 12 +- frame/bounties/src/benchmarking.rs | 6 +- frame/collective/src/benchmarking.rs | 8 +- frame/contracts/src/benchmarking/mod.rs | 14 +- frame/democracy/src/benchmarking.rs | 12 +- frame/democracy/src/lib.rs | 2 +- .../src/benchmarking.rs | 14 +- frame/elections-phragmen/src/benchmarking.rs | 18 +- frame/example/src/benchmarking.rs | 20 +- frame/gilt/src/benchmarking.rs | 6 +- frame/grandpa/src/benchmarking.rs | 12 +- frame/identity/src/benchmarking.rs | 5 +- frame/im-online/src/benchmarking.rs | 6 +- frame/indices/src/benchmarking.rs | 6 +- frame/lottery/src/benchmarking.rs | 6 +- frame/membership/src/lib.rs | 8 +- .../merkle-mountain-range/src/benchmarking.rs | 6 +- frame/multisig/src/benchmarking.rs | 6 +- frame/offences/benchmarking/src/lib.rs | 6 +- frame/proxy/Cargo.toml | 1 + frame/proxy/src/benchmarking.rs | 6 +- frame/scheduler/src/benchmarking.rs | 6 +- frame/session/benchmarking/src/lib.rs | 6 +- frame/staking/src/benchmarking.rs | 14 +- frame/staking/src/lib.rs | 1 + frame/system/benchmarking/src/lib.rs | 6 +- frame/timestamp/src/benchmarking.rs | 6 +- frame/tips/src/benchmarking.rs | 6 +- frame/transaction-storage/src/benchmarking.rs | 6 +- frame/treasury/src/benchmarking.rs | 6 +- frame/uniques/src/benchmarking.rs | 7 +- frame/utility/src/benchmarking.rs | 6 +- frame/vesting/src/benchmarking.rs | 14 +- 39 files changed, 496 insertions(+), 170 deletions(-) diff --git a/bin/node-template/pallets/template/src/benchmarking.rs b/bin/node-template/pallets/template/src/benchmarking.rs index 2117c048cfbd..d496a9fc89b1 100644 --- a/bin/node-template/pallets/template/src/benchmarking.rs +++ b/bin/node-template/pallets/template/src/benchmarking.rs @@ -4,7 +4,7 @@ use super::*; #[allow(unused)] use crate::Pallet as Template; -use frame_benchmarking::{benchmarks, impl_benchmark_test_suite, whitelisted_caller}; +use frame_benchmarking::{benchmarks, whitelisted_caller}; use frame_system::RawOrigin; benchmarks! { @@ -15,6 +15,6 @@ benchmarks! { verify { assert_eq!(Something::::get(), Some(s)); } -} -impl_benchmark_test_suite!(Template, crate::mock::new_test_ext(), crate::mock::Test); + impl_benchmark_test_suite!(Template, crate::mock::new_test_ext(), crate::mock::Test); +} diff --git a/frame/assets/src/benchmarking.rs b/frame/assets/src/benchmarking.rs index 43eadffbe849..d9de9ed3dedd 100644 --- a/frame/assets/src/benchmarking.rs +++ b/frame/assets/src/benchmarking.rs @@ -21,8 +21,7 @@ use super::*; use frame_benchmarking::{ - account, benchmarks_instance_pallet, impl_benchmark_test_suite, whitelist_account, - whitelisted_caller, + account, benchmarks_instance_pallet, whitelist_account, whitelisted_caller, }; use frame_support::{ dispatch::UnfilteredDispatchable, @@ -438,6 +437,6 @@ benchmarks_instance_pallet! { verify { assert_last_event::(Event::ApprovalCancelled(id, caller, delegate).into()); } -} -impl_benchmark_test_suite!(Assets, crate::mock::new_test_ext(), crate::mock::Test); + impl_benchmark_test_suite!(Assets, crate::mock::new_test_ext(), crate::mock::Test) +} diff --git a/frame/babe/src/benchmarking.rs b/frame/babe/src/benchmarking.rs index 372dfa532a89..7747c9bd1fc8 100644 --- a/frame/babe/src/benchmarking.rs +++ b/frame/babe/src/benchmarking.rs @@ -63,6 +63,12 @@ benchmarks! { } verify { assert!(sp_consensus_babe::check_equivocation_proof::
(equivocation_proof2)); } + + impl_benchmark_test_suite!( + Pallet, + crate::mock::new_test_ext(3), + crate::mock::Test, + ) } #[cfg(test)] @@ -70,12 +76,6 @@ mod tests { use super::*; use crate::mock::*; - frame_benchmarking::impl_benchmark_test_suite!( - Pallet, - crate::mock::new_test_ext(3), - crate::mock::Test, - ); - #[test] fn test_generate_equivocation_report_blob() { let (pairs, mut ext) = new_test_ext_with_pairs(3); diff --git a/frame/bags-list/src/benchmarks.rs b/frame/bags-list/src/benchmarks.rs index a820eeba13b1..d86adc674c44 100644 --- a/frame/bags-list/src/benchmarks.rs +++ b/frame/bags-list/src/benchmarks.rs @@ -134,11 +134,10 @@ frame_benchmarking::benchmarks! { ] ); } -} -use frame_benchmarking::impl_benchmark_test_suite; -impl_benchmark_test_suite!( - Pallet, - crate::mock::ExtBuilder::default().build(), - crate::mock::Runtime, -); + impl_benchmark_test_suite!( + Pallet, + crate::mock::ExtBuilder::default().build(), + crate::mock::Runtime, + ) +} diff --git a/frame/balances/src/benchmarking.rs b/frame/balances/src/benchmarking.rs index 06d202ea3700..1c4882009418 100644 --- a/frame/balances/src/benchmarking.rs +++ b/frame/balances/src/benchmarking.rs @@ -21,9 +21,7 @@ use super::*; -use frame_benchmarking::{ - account, benchmarks_instance_pallet, impl_benchmark_test_suite, whitelisted_caller, -}; +use frame_benchmarking::{account, benchmarks_instance_pallet, whitelisted_caller}; use frame_system::RawOrigin; use sp_runtime::traits::Bounded; @@ -215,10 +213,10 @@ benchmarks_instance_pallet! { assert!(Balances::::reserved_balance(&user).is_zero()); assert_eq!(Balances::::free_balance(&user), balance); } -} -impl_benchmark_test_suite!( - Balances, - crate::tests_composite::ExtBuilder::default().build(), - crate::tests_composite::Test, -); + impl_benchmark_test_suite!( + Balances, + crate::tests_composite::ExtBuilder::default().build(), + crate::tests_composite::Test, + ) +} diff --git a/frame/benchmarking/src/lib.rs b/frame/benchmarking/src/lib.rs index 4a6c5e15ae20..1805424426f6 100644 --- a/frame/benchmarking/src/lib.rs +++ b/frame/benchmarking/src/lib.rs @@ -155,6 +155,12 @@ macro_rules! whitelist { /// benchmark just like a regular benchmark, but only testing at the lowest and highest values for /// each component. The function will return `Ok(())` if the benchmarks return no errors. /// +/// It is also possible to generate one #[test] function per benchmark by calling the +/// `impl_benchmark_test_suite` macro inside the `benchmarks` block. The functions will be named +/// `bench_` and can be run via `cargo test`. +/// You will see one line of output per benchmark. This approach will give you more understandable +/// error messages and allows for parallel benchmark execution. +/// /// You can optionally add a `verify` code block at the end of a benchmark to test any final state /// of your benchmark in a unit test. For example: /// @@ -174,7 +180,8 @@ macro_rules! whitelist { /// /// These `verify` blocks will not affect your benchmark results! /// -/// You can construct benchmark tests like so: +/// You can construct benchmark by using the `impl_benchmark_test_suite` macro or +/// by manually implementing them like so: /// /// ```ignore /// #[test] @@ -193,6 +200,7 @@ macro_rules! benchmarks { $( $rest:tt )* ) => { $crate::benchmarks_iter!( + { } { } { } ( ) @@ -212,6 +220,7 @@ macro_rules! benchmarks_instance { $( $rest:tt )* ) => { $crate::benchmarks_iter!( + { } { I: Instance } { } ( ) @@ -231,6 +240,7 @@ macro_rules! benchmarks_instance_pallet { $( $rest:tt )* ) => { $crate::benchmarks_iter!( + { } { I: 'static } { } ( ) @@ -244,8 +254,60 @@ macro_rules! benchmarks_instance_pallet { #[macro_export] #[doc(hidden)] macro_rules! benchmarks_iter { + // detect and extract `impl_benchmark_test_suite` call: + // - with a semi-colon + ( + { } + { $( $instance:ident: $instance_bound:tt )? } + { $( $where_clause:tt )* } + ( $( $names:tt )* ) + ( $( $names_extra:tt )* ) + ( $( $names_skip_meta:tt )* ) + impl_benchmark_test_suite!( + $bench_module:ident, + $new_test_ext:expr, + $test:path + $(, $( $args:tt )* )?); + $( $rest:tt )* + ) => { + $crate::benchmarks_iter! { + { $bench_module, $new_test_ext, $test $(, $( $args )* )? } + { $( $instance: $instance_bound )? } + { $( $where_clause )* } + ( $( $names )* ) + ( $( $names_extra )* ) + ( $( $names_skip_meta )* ) + $( $rest )* + } + }; + // - without a semicolon + ( + { } + { $( $instance:ident: $instance_bound:tt )? } + { $( $where_clause:tt )* } + ( $( $names:tt )* ) + ( $( $names_extra:tt )* ) + ( $( $names_skip_meta:tt )* ) + impl_benchmark_test_suite!( + $bench_module:ident, + $new_test_ext:expr, + $test:path + $(, $( $args:tt )* )?) + $( $rest:tt )* + ) => { + $crate::benchmarks_iter! { + { $bench_module, $new_test_ext, $test $(, $( $args )* )? } + { $( $instance: $instance_bound )? } + { $( $where_clause )* } + ( $( $names )* ) + ( $( $names_extra )* ) + ( $( $names_skip_meta )* ) + $( $rest )* + } + }; // detect and extract where clause: ( + { $($bench_module:ident, $new_test_ext:expr, $test:path $(, $( $args:tt )* )?)? } { $( $instance:ident: $instance_bound:tt )? } { $( $where_clause:tt )* } ( $( $names:tt )* ) @@ -255,6 +317,7 @@ macro_rules! benchmarks_iter { $( $rest:tt )* ) => { $crate::benchmarks_iter! { + { $($bench_module, $new_test_ext, $test $(, $( $args )* )?)? } { $( $instance: $instance_bound)? } { $( $where_bound )* } ( $( $names )* ) @@ -265,6 +328,7 @@ macro_rules! benchmarks_iter { }; // detect and extract `#[skip_meta]` tag: ( + { $($bench_module:ident, $new_test_ext:expr, $test:path $(, $( $args:tt )* )?)? } { $( $instance:ident: $instance_bound:tt )? } { $( $where_clause:tt )* } ( $( $names:tt )* ) @@ -275,6 +339,7 @@ macro_rules! benchmarks_iter { $( $rest:tt )* ) => { $crate::benchmarks_iter! { + { $($bench_module, $new_test_ext, $test $(, $( $args )* )?)? } { $( $instance: $instance_bound )? } { $( $where_clause )* } ( $( $names )* ) @@ -284,8 +349,9 @@ macro_rules! benchmarks_iter { $( $rest )* } }; - // detect and extract `#[extra] tag: + // detect and extract `#[extra]` tag: ( + { $($bench_module:ident, $new_test_ext:expr, $test:path $(, $( $args:tt )* )?)? } { $( $instance:ident: $instance_bound:tt )? } { $( $where_clause:tt )* } ( $( $names:tt )* ) @@ -296,6 +362,7 @@ macro_rules! benchmarks_iter { $( $rest:tt )* ) => { $crate::benchmarks_iter! { + { $($bench_module, $new_test_ext, $test $(, $( $args )* )?)? } { $( $instance: $instance_bound )? } { $( $where_clause )* } ( $( $names )* ) @@ -307,6 +374,7 @@ macro_rules! benchmarks_iter { }; // mutation arm: ( + { $($bench_module:ident, $new_test_ext:expr, $test:path $(, $( $args:tt )* )?)? } { $( $instance:ident: $instance_bound:tt )? } { $( $where_clause:tt )* } ( $( $names:tt )* ) // This contains $( $( { $instance } )? $name:ident )* @@ -317,6 +385,7 @@ macro_rules! benchmarks_iter { $( $rest:tt )* ) => { $crate::benchmarks_iter! { + { $($bench_module, $new_test_ext, $test $(, $( $args )* )?)? } { $( $instance: $instance_bound )? } { $( $where_clause )* } ( $( $names )* ) @@ -329,6 +398,7 @@ macro_rules! benchmarks_iter { }; // mutation arm: ( + { $($bench_module:ident, $new_test_ext:expr, $test:path $(, $( $args:tt )* )?)? } { $( $instance:ident: $instance_bound:tt )? } { $( $where_clause:tt )* } ( $( $names:tt )* ) @@ -340,6 +410,7 @@ macro_rules! benchmarks_iter { ) => { $crate::paste::paste! { $crate::benchmarks_iter! { + { $($bench_module, $new_test_ext, $test $(, $( $args )* )?)? } { $( $instance: $instance_bound )? } { $( $where_clause )* } ( $( $names )* ) @@ -373,6 +444,7 @@ macro_rules! benchmarks_iter { }; // iteration arm: ( + { $($bench_module:ident, $new_test_ext:expr, $test:path $(, $( $args:tt )* )?)? } { $( $instance:ident: $instance_bound:tt )? } { $( $where_clause:tt )* } ( $( $names:tt )* ) @@ -400,6 +472,7 @@ macro_rules! benchmarks_iter { ); $crate::benchmarks_iter!( + { $($bench_module, $new_test_ext, $test $(, $( $args )* )?)? } { $( $instance: $instance_bound )? } { $( $where_clause )* } ( $( $names )* { $( $instance )? } $name ) @@ -408,8 +481,40 @@ macro_rules! benchmarks_iter { $( $rest )* ); }; - // iteration-exit arm + // iteration-exit arm which generates a #[test] function for each case. ( + { $bench_module:ident, $new_test_ext:expr, $test:path $(, $( $args:tt )* )? } + { $( $instance:ident: $instance_bound:tt )? } + { $( $where_clause:tt )* } + ( $( $names:tt )* ) + ( $( $names_extra:tt )* ) + ( $( $names_skip_meta:tt )* ) + ) => { + $crate::selected_benchmark!( + { $( $where_clause)* } + { $( $instance: $instance_bound )? } + $( $names )* + ); + $crate::impl_benchmark!( + { $( $where_clause )* } + { $( $instance: $instance_bound )? } + ( $( $names )* ) + ( $( $names_extra ),* ) + ( $( $names_skip_meta ),* ) + ); + $crate::impl_test_function!( + ( $( $names )* ) + ( $( $names_extra )* ) + ( $( $names_skip_meta )* ) + $bench_module, + $new_test_ext, + $test + $(, $( $args )* )? + ); + }; + // iteration-exit arm which doesn't generate a #[test] function for all cases. + ( + { } { $( $instance:ident: $instance_bound:tt )? } { $( $where_clause:tt )* } ( $( $names:tt )* ) @@ -431,6 +536,7 @@ macro_rules! benchmarks_iter { }; // add verify block to _() format ( + { $($bench_module:ident, $new_test_ext:expr, $test:path $(, $( $args:tt )* )?)? } { $( $instance:ident: $instance_bound:tt )? } { $( $where_clause:tt )* } ( $( $names:tt )* ) @@ -440,6 +546,7 @@ macro_rules! benchmarks_iter { $( $rest:tt )* ) => { $crate::benchmarks_iter! { + { $($bench_module, $new_test_ext, $test $(, $( $args )* )?)? } { $( $instance: $instance_bound )? } { $( $where_clause )* } ( $( $names )* ) @@ -452,6 +559,7 @@ macro_rules! benchmarks_iter { }; // add verify block to name() format ( + { $($bench_module:ident, $new_test_ext:expr, $test:path $(, $( $args:tt )* )?)? } { $( $instance:ident: $instance_bound:tt )? } { $( $where_clause:tt )* } ( $( $names:tt )* ) @@ -461,6 +569,7 @@ macro_rules! benchmarks_iter { $( $rest:tt )* ) => { $crate::benchmarks_iter! { + { $($bench_module, $new_test_ext, $test $(, $( $args )* )?)? } { $( $instance: $instance_bound )? } { $( $where_clause )* } ( $( $names )* ) @@ -473,6 +582,7 @@ macro_rules! benchmarks_iter { }; // add verify block to {} format ( + { $($bench_module:ident, $new_test_ext:expr, $test:path $(, $( $args:tt )* )?)? } { $( $instance:ident: $instance_bound:tt )? } { $( $where_clause:tt )* } ( $( $names:tt )* ) @@ -482,6 +592,7 @@ macro_rules! benchmarks_iter { $( $rest:tt )* ) => { $crate::benchmarks_iter!( + { $($bench_module, $new_test_ext, $test $(, $( $args )* )?)? } { $( $instance: $instance_bound )? } { $( $where_clause )* } ( $( $names )* ) @@ -695,6 +806,100 @@ macro_rules! benchmark_backend { }; } +// Creates #[test] functions for the given bench cases. +#[macro_export] +#[doc(hidden)] +macro_rules! impl_bench_case_tests { + ( + { $module:ident, $new_test_exec:expr, $exec_name:ident, $test:path, $extra:expr } + { $( $names_extra:tt )* } + $( { $( $bench_inst:ident )? } $bench:ident )* + ) + => { + $crate::impl_bench_name_tests!( + $module, $new_test_exec, $exec_name, $test, $extra, + { $( $names_extra )* }, + $( { $bench } )+ + ); + } +} + +// Creates a #[test] function for the given bench name. +#[macro_export] +#[doc(hidden)] +macro_rules! impl_bench_name_tests { + // recursion anchor + ( + $module:ident, $new_test_exec:expr, $exec_name:ident, $test:path, $extra:expr, + { $( $names_extra:tt )* }, + { $name:ident } + ) => { + $crate::paste::paste! { + #[test] + fn [] () { + $new_test_exec.$exec_name(|| { + // Skip all #[extra] benchmarks if $extra is false. + if !($extra) { + let disabled = $crate::vec![ $( stringify!($names_extra).as_ref() ),* ]; + if disabled.contains(&stringify!($name)) { + $crate::log::error!( + "INFO: extra benchmark skipped - {}", + stringify!($name), + ); + return (); + } + } + + // Same per-case logic as when all cases are run in the + // same function. + match std::panic::catch_unwind(|| { + $module::<$test>::[< test_benchmark_ $name >] () + }) { + Err(err) => { + panic!("{}: {:?}", stringify!($name), err); + }, + Ok(Err(err)) => { + match err { + $crate::BenchmarkError::Stop(err) => { + panic!("{}: {:?}", stringify!($name), err); + }, + $crate::BenchmarkError::Override(_) => { + // This is still considered a success condition. + $crate::log::error!( + "WARNING: benchmark error overrided - {}", + stringify!($name), + ); + }, + $crate::BenchmarkError::Skip => { + // This is considered a success condition. + $crate::log::error!( + "WARNING: benchmark error skipped - {}", + stringify!($name), + ); + } + } + }, + Ok(Ok(())) => (), + } + }); + } + } + }; + // recursion tail + ( + $module:ident, $new_test_exec:expr, $exec_name:ident, $test:path, $extra:expr, + { $( $names_extra:tt )* }, + { $name:ident } $( { $rest:ident } )+ + ) => { + // car + $crate::impl_bench_name_tests!($module, $new_test_exec, $exec_name, $test, $extra, + { $( $names_extra )* }, { $name }); + // cdr + $crate::impl_bench_name_tests!($module, $new_test_exec, $exec_name, $test, $extra, + { $( $names_extra )* }, $( { $rest } )+); + }; +} + // Creates a `SelectedBenchmark` enum implementing `BenchmarkingSetup`. // // Every variant must implement [`BenchmarkingSetup`]. @@ -1030,13 +1235,54 @@ macro_rules! impl_benchmark_test { /// new_test_ext().execute_with(|| { /// assert_ok!(test_benchmark_accumulate_dummy::()); /// assert_ok!(test_benchmark_set_dummy::()); -/// assert_ok!(test_benchmark_another_set_dummy::()); /// assert_ok!(test_benchmark_sort_vector::()); /// }); /// } /// } /// ``` /// +/// When called inside the `benchmarks` macro of the `pallet_example` as +/// +/// ```rust,ignore +/// benchmarks! { +/// // Benchmarks omitted for brevity +/// +/// impl_benchmark_test_suite!(Pallet, crate::tests::new_test_ext(), crate::tests::Test); +/// } +/// ``` +/// +/// It expands to the equivalent of: +/// +/// ```rust,ignore +/// #[cfg(test)] +/// mod benchmarking { +/// use super::*; +/// use crate::tests::{new_test_ext, Test}; +/// use frame_support::assert_ok; +/// +/// #[test] +/// fn bench_accumulate_dummy() { +/// new_test_ext().execute_with(|| { +/// assert_ok!(test_benchmark_accumulate_dummy::()); +/// } +/// } +/// +/// #[test] +/// fn bench_set_dummy() { +/// new_test_ext().execute_with(|| { +/// assert_ok!(test_benchmark_set_dummy::()); +/// } +/// } +/// +/// #[test] +/// fn bench_sort_vector() { +/// new_test_ext().execute_with(|| { +/// assert_ok!(test_benchmark_sort_vector::()); +/// } +/// } +/// } +/// ``` +/// /// ## Arguments /// /// The first argument, `module`, must be the path to this crate's module. @@ -1109,16 +1355,50 @@ macro_rules! impl_benchmark_test { // just iterate over the `Benchmarking::benchmarks` list to run the actual implementations. #[macro_export] macro_rules! impl_benchmark_test_suite { + ( + $bench_module:ident, + $new_test_ext:expr, + $test:path + $(, $( $rest:tt )* )? + ) => { + $crate::impl_test_function!( + () + () + () + $bench_module, + $new_test_ext, + $test + $(, $( $rest )* )? + ); + } +} + +// Takes all arguments from `impl_benchmark_test_suite` and three additional arguments. +// +// Can be configured to generate one #[test] fn per bench case or +// one #[test] fn for all bench cases. +// This depends on whether or not the first argument contains a non-empty list of bench names. +#[macro_export] +#[doc(hidden)] +macro_rules! impl_test_function { // user might or might not have set some keyword arguments; set the defaults // // The weird syntax indicates that `rest` comes only after a comma, which is otherwise optional ( + ( $( $names:tt )* ) + ( $( $names_extra:tt )* ) + ( $( $names_skip_meta:tt )* ) + $bench_module:ident, $new_test_ext:expr, $test:path $(, $( $rest:tt )* )? ) => { - $crate::impl_benchmark_test_suite!( + $crate::impl_test_function!( + @cases: + ( $( $names )* ) + ( $( $names_extra )* ) + ( $( $names_skip_meta )* ) @selected: $bench_module, $new_test_ext, @@ -1132,6 +1412,10 @@ macro_rules! impl_benchmark_test_suite { }; // pick off the benchmarks_path keyword argument ( + @cases: + ( $( $names:tt )* ) + ( $( $names_extra:tt )* ) + ( $( $names_skip_meta:tt )* ) @selected: $bench_module:ident, $new_test_ext:expr, @@ -1143,7 +1427,11 @@ macro_rules! impl_benchmark_test_suite { benchmarks_path = $benchmarks_path:ident $(, $( $rest:tt )* )? ) => { - $crate::impl_benchmark_test_suite!( + $crate::impl_test_function!( + @cases: + ( $( $names )* ) + ( $( $names_extra )* ) + ( $( $names_skip_meta )* ) @selected: $bench_module, $new_test_ext, @@ -1157,6 +1445,10 @@ macro_rules! impl_benchmark_test_suite { }; // pick off the extra keyword argument ( + @cases: + ( $( $names:tt )* ) + ( $( $names_extra:tt )* ) + ( $( $names_skip_meta:tt )* ) @selected: $bench_module:ident, $new_test_ext:expr, @@ -1168,7 +1460,11 @@ macro_rules! impl_benchmark_test_suite { extra = $extra:expr $(, $( $rest:tt )* )? ) => { - $crate::impl_benchmark_test_suite!( + $crate::impl_test_function!( + @cases: + ( $( $names )* ) + ( $( $names_extra )* ) + ( $( $names_skip_meta )* ) @selected: $bench_module, $new_test_ext, @@ -1182,6 +1478,10 @@ macro_rules! impl_benchmark_test_suite { }; // pick off the exec_name keyword argument ( + @cases: + ( $( $names:tt )* ) + ( $( $names_extra:tt )* ) + ( $( $names_skip_meta:tt )* ) @selected: $bench_module:ident, $new_test_ext:expr, @@ -1193,7 +1493,11 @@ macro_rules! impl_benchmark_test_suite { exec_name = $exec_name:ident $(, $( $rest:tt )* )? ) => { - $crate::impl_benchmark_test_suite!( + $crate::impl_test_function!( + @cases: + ( $( $names )* ) + ( $( $names_extra )* ) + ( $( $names_skip_meta )* ) @selected: $bench_module, $new_test_ext, @@ -1205,8 +1509,34 @@ macro_rules! impl_benchmark_test_suite { $( $( $rest )* )? ); }; - // all options set; nothing else in user-provided keyword arguments + // iteration-exit arm which generates a #[test] function for each case. + ( + @cases: + ( $( $names:tt )+ ) + ( $( $names_extra:tt )* ) + ( $( $names_skip_meta:tt )* ) + @selected: + $bench_module:ident, + $new_test_ext:expr, + $test:path, + benchmarks_path = $path_to_benchmarks_invocation:ident, + extra = $extra:expr, + exec_name = $exec_name:ident, + @user: + $(,)? + ) => { + $crate::impl_bench_case_tests!( + { $bench_module, $new_test_ext, $exec_name, $test, $extra } + { $( $names_extra:tt )* } + $($names)+ + ); + }; + // iteration-exit arm which generates one #[test] function for all cases. ( + @cases: + () + () + () @selected: $bench_module:ident, $new_test_ext:expr, diff --git a/frame/benchmarking/src/tests_instance.rs b/frame/benchmarking/src/tests_instance.rs index caccebd39c70..0ad156ce5a88 100644 --- a/frame/benchmarking/src/tests_instance.rs +++ b/frame/benchmarking/src/tests_instance.rs @@ -173,11 +173,11 @@ mod benchmarks { } verify { ensure!(m[0] == 0, "You forgot to sort!") } - } - crate::impl_benchmark_test_suite!( - Pallet, - crate::tests_instance::new_test_ext(), - crate::tests_instance::Test - ); + impl_benchmark_test_suite!( + Pallet, + crate::tests_instance::new_test_ext(), + crate::tests_instance::Test + ) + } } diff --git a/frame/bounties/src/benchmarking.rs b/frame/bounties/src/benchmarking.rs index 1aa1eabdb517..33af02fbb9ea 100644 --- a/frame/bounties/src/benchmarking.rs +++ b/frame/bounties/src/benchmarking.rs @@ -21,7 +21,7 @@ use super::*; -use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite, whitelisted_caller}; +use frame_benchmarking::{account, benchmarks, whitelisted_caller}; use frame_system::RawOrigin; use sp_runtime::traits::Bounded; @@ -209,6 +209,6 @@ benchmarks! { ensure!(missed_any == false, "Missed some"); assert_last_event::(Event::BountyBecameActive(b - 1).into()) } -} -impl_benchmark_test_suite!(Bounties, crate::tests::new_test_ext(), crate::tests::Test); + impl_benchmark_test_suite!(Bounties, crate::tests::new_test_ext(), crate::tests::Test) +} diff --git a/frame/collective/src/benchmarking.rs b/frame/collective/src/benchmarking.rs index c7e695babf27..c26a2b43f5b7 100644 --- a/frame/collective/src/benchmarking.rs +++ b/frame/collective/src/benchmarking.rs @@ -23,9 +23,7 @@ use crate::Pallet as Collective; use sp_runtime::traits::Bounded; use sp_std::mem::size_of; -use frame_benchmarking::{ - account, benchmarks_instance_pallet, impl_benchmark_test_suite, whitelisted_caller, -}; +use frame_benchmarking::{account, benchmarks_instance_pallet, whitelisted_caller}; use frame_system::{Call as SystemCall, Pallet as System, RawOrigin as SystemOrigin}; const SEED: u32 = 0; @@ -638,6 +636,6 @@ benchmarks_instance_pallet! { assert_eq!(Collective::::proposals().len(), (p - 1) as usize); assert_last_event::(Event::Disapproved(last_hash).into()); } -} -impl_benchmark_test_suite!(Collective, crate::tests::new_test_ext(), crate::tests::Test); + impl_benchmark_test_suite!(Collective, crate::tests::new_test_ext(), crate::tests::Test); +} diff --git a/frame/contracts/src/benchmarking/mod.rs b/frame/contracts/src/benchmarking/mod.rs index 981af218ea5a..e382e616f27f 100644 --- a/frame/contracts/src/benchmarking/mod.rs +++ b/frame/contracts/src/benchmarking/mod.rs @@ -36,7 +36,7 @@ use crate::{ Pallet as Contracts, *, }; use codec::Encode; -use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite, whitelisted_caller}; +use frame_benchmarking::{account, benchmarks, whitelisted_caller}; use frame_support::weights::Weight; use frame_system::RawOrigin; use pwasm_utils::parity_wasm::elements::{BlockType, BrTableData, Instruction, ValueType}; @@ -2325,10 +2325,10 @@ benchmarks! { ) .result?; } -} -impl_benchmark_test_suite!( - Contracts, - crate::tests::ExtBuilder::default().build(), - crate::tests::Test, -); + impl_benchmark_test_suite!( + Contracts, + crate::tests::ExtBuilder::default().build(), + crate::tests::Test, + ) +} diff --git a/frame/democracy/src/benchmarking.rs b/frame/democracy/src/benchmarking.rs index 63d409dac25a..34bcb0da301e 100644 --- a/frame/democracy/src/benchmarking.rs +++ b/frame/democracy/src/benchmarking.rs @@ -19,7 +19,7 @@ use super::*; -use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite, whitelist_account}; +use frame_benchmarking::{account, benchmarks, whitelist_account}; use frame_support::{ assert_noop, assert_ok, codec::Decode, @@ -70,7 +70,7 @@ fn add_referendum(n: u32) -> Result { let referendum_index: ReferendumIndex = ReferendumCount::::get() - 1; T::Scheduler::schedule_named( (DEMOCRACY_ID, referendum_index).encode(), - DispatchTime::At(1u32.into()), + DispatchTime::At(2u32.into()), None, 63, frame_system::RawOrigin::Root.into(), @@ -802,6 +802,10 @@ benchmarks! { Err(Error::::PreimageInvalid.into()) ); } -} -impl_benchmark_test_suite!(Democracy, crate::tests::new_test_ext(), crate::tests::Test); + impl_benchmark_test_suite!( + Democracy, + crate::tests::new_test_ext(), + crate::tests::Test + ); +} diff --git a/frame/democracy/src/lib.rs b/frame/democracy/src/lib.rs index 24f823a17e10..50b245006fa2 100644 --- a/frame/democracy/src/lib.rs +++ b/frame/democracy/src/lib.rs @@ -149,7 +149,7 @@ //! - `cancel_queued` - Cancels a proposal that is queued for enactment. //! - `clear_public_proposal` - Removes all public proposals. -#![recursion_limit = "128"] +#![recursion_limit = "256"] #![cfg_attr(not(feature = "std"), no_std)] use codec::{Decode, Encode, Input}; diff --git a/frame/election-provider-multi-phase/src/benchmarking.rs b/frame/election-provider-multi-phase/src/benchmarking.rs index b8d7bc45c448..9648b8e0f246 100644 --- a/frame/election-provider-multi-phase/src/benchmarking.rs +++ b/frame/election-provider-multi-phase/src/benchmarking.rs @@ -19,7 +19,7 @@ use super::*; use crate::{unsigned::IndexAssignmentOf, Pallet as MultiPhase}; -use frame_benchmarking::{account, impl_benchmark_test_suite}; +use frame_benchmarking::account; use frame_support::{assert_ok, traits::Hooks}; use frame_system::RawOrigin; use rand::{prelude::SliceRandom, rngs::SmallRng, SeedableRng}; @@ -497,10 +497,10 @@ frame_benchmarking::benchmarks! { log!(trace, "actual encoded size = {}", encoding.len()); assert!(encoding.len() <= desired_size); } -} -impl_benchmark_test_suite!( - MultiPhase, - crate::mock::ExtBuilder::default().build_offchainify(10).0, - crate::mock::Runtime, -); + impl_benchmark_test_suite!( + MultiPhase, + crate::mock::ExtBuilder::default().build_offchainify(10).0, + crate::mock::Runtime, + ); +} diff --git a/frame/elections-phragmen/src/benchmarking.rs b/frame/elections-phragmen/src/benchmarking.rs index 6e3ce0234c4f..9bc63848607a 100644 --- a/frame/elections-phragmen/src/benchmarking.rs +++ b/frame/elections-phragmen/src/benchmarking.rs @@ -21,9 +21,7 @@ use super::*; -use frame_benchmarking::{ - account, benchmarks, impl_benchmark_test_suite, whitelist, BenchmarkError, BenchmarkResult, -}; +use frame_benchmarking::{account, benchmarks, whitelist, BenchmarkError, BenchmarkResult}; use frame_support::{ dispatch::{DispatchResultWithPostInfo, UnfilteredDispatchable}, traits::OnInitialize, @@ -549,11 +547,11 @@ benchmarks! { MEMBERS.with(|m| *m.borrow_mut() = vec![]); } } -} -impl_benchmark_test_suite!( - Elections, - crate::tests::ExtBuilder::default().desired_members(13).desired_runners_up(7), - crate::tests::Test, - exec_name = build_and_execute, -); + impl_benchmark_test_suite!( + Elections, + crate::tests::ExtBuilder::default().desired_members(13).desired_runners_up(7), + crate::tests::Test, + exec_name = build_and_execute, + ); +} diff --git a/frame/example/src/benchmarking.rs b/frame/example/src/benchmarking.rs index cdf6c152a488..9f2bb20fe63a 100644 --- a/frame/example/src/benchmarking.rs +++ b/frame/example/src/benchmarking.rs @@ -20,7 +20,7 @@ #![cfg(feature = "runtime-benchmarks")] use crate::*; -use frame_benchmarking::{benchmarks, impl_benchmark_test_suite, whitelisted_caller}; +use frame_benchmarking::{benchmarks, whitelisted_caller}; use frame_system::RawOrigin; // To actually run this benchmark on pallet-example, we need to put this pallet into the @@ -65,12 +65,14 @@ benchmarks! { // The benchmark execution phase could also be a closure with custom code m.sort(); } -} -// This line generates test cases for benchmarking, and could be run by: -// `cargo test -p pallet-example --all-features`, you will see an additional line of: -// `test benchmarking::benchmark_tests::test_benchmarks ... ok` in the result. -// -// The line generates three steps per benchmark, with repeat=1 and the three steps are -// [low, mid, high] of the range. -impl_benchmark_test_suite!(Pallet, crate::tests::new_test_ext(), crate::tests::Test); + // This line generates test cases for benchmarking, and could be run by: + // `cargo test -p pallet-example --all-features`, you will see one line per case: + // `test benchmarking::bench_sort_vector ... ok` + // `test benchmarking::bench_accumulate_dummy ... ok` + // `test benchmarking::bench_set_dummy_benchmark ... ok` in the result. + // + // The line generates three steps per benchmark, with repeat=1 and the three steps are + // [low, mid, high] of the range. + impl_benchmark_test_suite!(Pallet, crate::tests::new_test_ext(), crate::tests::Test) +} diff --git a/frame/gilt/src/benchmarking.rs b/frame/gilt/src/benchmarking.rs index cfc503cf897b..9c6d22a48398 100644 --- a/frame/gilt/src/benchmarking.rs +++ b/frame/gilt/src/benchmarking.rs @@ -20,7 +20,7 @@ #![cfg(feature = "runtime-benchmarks")] use super::*; -use frame_benchmarking::{benchmarks, impl_benchmark_test_suite, whitelisted_caller}; +use frame_benchmarking::{benchmarks, whitelisted_caller}; use frame_support::{ dispatch::UnfilteredDispatchable, traits::{Currency, EnsureOrigin, Get}, @@ -126,6 +126,6 @@ benchmarks! { .dispatch_bypass_filter(T::AdminOrigin::successful_origin())?; }: { Gilt::::pursue_target(q) } -} -impl_benchmark_test_suite!(Gilt, crate::mock::new_test_ext(), crate::mock::Test); + impl_benchmark_test_suite!(Gilt, crate::mock::new_test_ext(), crate::mock::Test); +} diff --git a/frame/grandpa/src/benchmarking.rs b/frame/grandpa/src/benchmarking.rs index 815a18d13531..1e6be01ce8db 100644 --- a/frame/grandpa/src/benchmarking.rs +++ b/frame/grandpa/src/benchmarking.rs @@ -68,6 +68,12 @@ benchmarks! { verify { assert!(Grandpa::::stalled().is_some()); } + + impl_benchmark_test_suite!( + Pallet, + crate::mock::new_test_ext(vec![(1, 1), (2, 1), (3, 1)]), + crate::mock::Test, + ); } #[cfg(test)] @@ -75,12 +81,6 @@ mod tests { use super::*; use crate::mock::*; - frame_benchmarking::impl_benchmark_test_suite!( - Pallet, - crate::mock::new_test_ext(vec![(1, 1), (2, 1), (3, 1)]), - crate::mock::Test, - ); - #[test] fn test_generate_equivocation_report_blob() { let authorities = crate::tests::test_authorities(); diff --git a/frame/identity/src/benchmarking.rs b/frame/identity/src/benchmarking.rs index 8bda24ddc73e..68869a43992f 100644 --- a/frame/identity/src/benchmarking.rs +++ b/frame/identity/src/benchmarking.rs @@ -22,7 +22,7 @@ use super::*; use crate::Pallet as Identity; -use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite, whitelisted_caller}; +use frame_benchmarking::{account, benchmarks, whitelisted_caller}; use frame_support::{ensure, traits::Get}; use frame_system::RawOrigin; use sp_runtime::traits::Bounded; @@ -411,6 +411,5 @@ benchmarks! { ensure!(!SuperOf::::contains_key(&caller), "Sub not removed"); } + impl_benchmark_test_suite!(Identity, crate::tests::new_test_ext(), crate::tests::Test); } - -impl_benchmark_test_suite!(Identity, crate::tests::new_test_ext(), crate::tests::Test); diff --git a/frame/im-online/src/benchmarking.rs b/frame/im-online/src/benchmarking.rs index b39b0057c48e..012da53a183e 100644 --- a/frame/im-online/src/benchmarking.rs +++ b/frame/im-online/src/benchmarking.rs @@ -21,7 +21,7 @@ use super::*; -use frame_benchmarking::{benchmarks, impl_benchmark_test_suite}; +use frame_benchmarking::benchmarks; use frame_support::{traits::UnfilteredDispatchable, WeakBoundedVec}; use frame_system::RawOrigin; use sp_core::{offchain::OpaqueMultiaddr, OpaquePeerId}; @@ -100,6 +100,6 @@ benchmarks! { .expect("call is encoded above, encoding must be correct") .dispatch_bypass_filter(RawOrigin::None.into())?; } -} -impl_benchmark_test_suite!(ImOnline, crate::mock::new_test_ext(), crate::mock::Runtime); + impl_benchmark_test_suite!(ImOnline, crate::mock::new_test_ext(), crate::mock::Runtime); +} diff --git a/frame/indices/src/benchmarking.rs b/frame/indices/src/benchmarking.rs index ba0152008c41..873dc18b2026 100644 --- a/frame/indices/src/benchmarking.rs +++ b/frame/indices/src/benchmarking.rs @@ -20,7 +20,7 @@ #![cfg(feature = "runtime-benchmarks")] use super::*; -use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite, whitelisted_caller}; +use frame_benchmarking::{account, benchmarks, whitelisted_caller}; use frame_system::RawOrigin; use sp_runtime::traits::Bounded; @@ -91,6 +91,6 @@ benchmarks! { } // TODO in another PR: lookup and unlookup trait weights (not critical) -} -impl_benchmark_test_suite!(Indices, crate::mock::new_test_ext(), crate::mock::Test); + impl_benchmark_test_suite!(Indices, crate::mock::new_test_ext(), crate::mock::Test); +} diff --git a/frame/lottery/src/benchmarking.rs b/frame/lottery/src/benchmarking.rs index 7af20bbb0e11..5407e16cd633 100644 --- a/frame/lottery/src/benchmarking.rs +++ b/frame/lottery/src/benchmarking.rs @@ -21,7 +21,7 @@ use super::*; -use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite, whitelisted_caller}; +use frame_benchmarking::{account, benchmarks, whitelisted_caller}; use frame_support::traits::{EnsureOrigin, OnInitialize}; use frame_system::RawOrigin; use sp_runtime::traits::{Bounded, Zero}; @@ -163,6 +163,6 @@ benchmarks! { assert_eq!(Lottery::::pot().1, 0u32.into()); assert!(!T::Currency::free_balance(&winner).is_zero()) } -} -impl_benchmark_test_suite!(Lottery, crate::mock::new_test_ext(), crate::mock::Test); + impl_benchmark_test_suite!(Lottery, crate::mock::new_test_ext(), crate::mock::Test); +} diff --git a/frame/membership/src/lib.rs b/frame/membership/src/lib.rs index 57a12c7c8a45..8fa2abb0ad3f 100644 --- a/frame/membership/src/lib.rs +++ b/frame/membership/src/lib.rs @@ -357,9 +357,7 @@ impl, I: 'static> SortedMembers for Pallet { #[cfg(feature = "runtime-benchmarks")] mod benchmark { use super::{Pallet as Membership, *}; - use frame_benchmarking::{ - account, benchmarks_instance_pallet, impl_benchmark_test_suite, whitelist, - }; + use frame_benchmarking::{account, benchmarks_instance_pallet, whitelist}; use frame_support::{assert_ok, traits::EnsureOrigin}; use frame_system::RawOrigin; @@ -494,9 +492,9 @@ mod benchmark { assert!(::get_prime().is_none()); #[cfg(test)] crate::tests::clean(); } - } - impl_benchmark_test_suite!(Membership, crate::tests::new_bench_ext(), crate::tests::Test); + impl_benchmark_test_suite!(Membership, crate::tests::new_bench_ext(), crate::tests::Test); + } } #[cfg(test)] diff --git a/frame/merkle-mountain-range/src/benchmarking.rs b/frame/merkle-mountain-range/src/benchmarking.rs index c269afb75855..d6ef76d01ac3 100644 --- a/frame/merkle-mountain-range/src/benchmarking.rs +++ b/frame/merkle-mountain-range/src/benchmarking.rs @@ -18,7 +18,7 @@ //! Benchmarks for the MMR pallet. use crate::*; -use frame_benchmarking::{benchmarks_instance_pallet, impl_benchmark_test_suite}; +use frame_benchmarking::benchmarks_instance_pallet; use frame_support::traits::OnInitialize; benchmarks_instance_pallet! { @@ -33,6 +33,6 @@ benchmarks_instance_pallet! { } verify { assert_eq!(crate::NumberOfLeaves::::get(), leaves); } -} -impl_benchmark_test_suite!(Pallet, crate::tests::new_test_ext(), crate::mock::Test); + impl_benchmark_test_suite!(Pallet, crate::tests::new_test_ext(), crate::mock::Test); +} diff --git a/frame/multisig/src/benchmarking.rs b/frame/multisig/src/benchmarking.rs index 2e23dff156e0..edfeba253e5f 100644 --- a/frame/multisig/src/benchmarking.rs +++ b/frame/multisig/src/benchmarking.rs @@ -21,7 +21,7 @@ use super::*; use core::convert::TryInto; -use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite}; +use frame_benchmarking::{account, benchmarks}; use frame_system::RawOrigin; use sp_runtime::traits::Bounded; @@ -297,6 +297,6 @@ benchmarks! { assert!(!Multisigs::::contains_key(multi_account_id, call_hash)); assert!(!Calls::::contains_key(call_hash)); } -} -impl_benchmark_test_suite!(Multisig, crate::tests::new_test_ext(), crate::tests::Test); + impl_benchmark_test_suite!(Multisig, crate::tests::new_test_ext(), crate::tests::Test); +} diff --git a/frame/offences/benchmarking/src/lib.rs b/frame/offences/benchmarking/src/lib.rs index 35e3c1aec940..dde8aa92c240 100644 --- a/frame/offences/benchmarking/src/lib.rs +++ b/frame/offences/benchmarking/src/lib.rs @@ -23,7 +23,7 @@ mod mock; use sp_std::{prelude::*, vec}; -use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite}; +use frame_benchmarking::{account, benchmarks}; use frame_support::traits::{Currency, ValidatorSet, ValidatorSetWithIdentification}; use frame_system::{Config as SystemConfig, Pallet as System, RawOrigin}; @@ -399,6 +399,6 @@ benchmarks! { + n // nominators slashed ); } -} -impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test); + impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test); +} diff --git a/frame/proxy/Cargo.toml b/frame/proxy/Cargo.toml index 83db82990d10..4da712dadf27 100644 --- a/frame/proxy/Cargo.toml +++ b/frame/proxy/Cargo.toml @@ -42,5 +42,6 @@ std = [ runtime-benchmarks = [ "frame-benchmarking", "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", ] try-runtime = ["frame-support/try-runtime"] diff --git a/frame/proxy/src/benchmarking.rs b/frame/proxy/src/benchmarking.rs index e66f6782c19e..1eb3ec577054 100644 --- a/frame/proxy/src/benchmarking.rs +++ b/frame/proxy/src/benchmarking.rs @@ -21,7 +21,7 @@ use super::*; use crate::Pallet as Proxy; -use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite, whitelisted_caller}; +use frame_benchmarking::{account, benchmarks, whitelisted_caller}; use frame_system::RawOrigin; use sp_runtime::traits::Bounded; @@ -245,6 +245,6 @@ benchmarks! { verify { assert!(!Proxies::::contains_key(&anon)); } -} -impl_benchmark_test_suite!(Proxy, crate::tests::new_test_ext(), crate::tests::Test); + impl_benchmark_test_suite!(Proxy, crate::tests::new_test_ext(), crate::tests::Test); +} diff --git a/frame/scheduler/src/benchmarking.rs b/frame/scheduler/src/benchmarking.rs index 2c164eaede22..1065f1702774 100644 --- a/frame/scheduler/src/benchmarking.rs +++ b/frame/scheduler/src/benchmarking.rs @@ -20,7 +20,7 @@ #![cfg(feature = "runtime-benchmarks")] use super::*; -use frame_benchmarking::{benchmarks, impl_benchmark_test_suite}; +use frame_benchmarking::benchmarks; use frame_support::{ensure, traits::OnInitialize}; use frame_system::RawOrigin; use sp_std::{prelude::*, vec}; @@ -139,6 +139,6 @@ benchmarks! { "didn't append schedule" ); } -} -impl_benchmark_test_suite!(Scheduler, crate::tests::new_test_ext(), crate::tests::Test); + impl_benchmark_test_suite!(Scheduler, crate::tests::new_test_ext(), crate::tests::Test); +} diff --git a/frame/session/benchmarking/src/lib.rs b/frame/session/benchmarking/src/lib.rs index c0131957c873..8ca713b1bbf6 100644 --- a/frame/session/benchmarking/src/lib.rs +++ b/frame/session/benchmarking/src/lib.rs @@ -24,7 +24,7 @@ mod mock; use sp_std::{prelude::*, vec}; -use frame_benchmarking::{benchmarks, impl_benchmark_test_suite}; +use frame_benchmarking::benchmarks; use frame_support::{ codec::Decode, traits::{KeyOwnerProofSystem, OnInitialize}, @@ -115,6 +115,8 @@ benchmarks! { verify { assert!(Historical::::check_proof(key, key_owner_proof2).is_some()); } + + impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test, extra = false); } /// Sets up the benchmark for checking a membership proof. It creates the given @@ -161,5 +163,3 @@ fn check_membership_proof_setup( (key, Historical::::prove(key).unwrap()) } - -impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test, extra = false); diff --git a/frame/staking/src/benchmarking.rs b/frame/staking/src/benchmarking.rs index fe60d516e144..220e8f1e6a24 100644 --- a/frame/staking/src/benchmarking.rs +++ b/frame/staking/src/benchmarking.rs @@ -887,6 +887,13 @@ benchmarks! { verify { assert!(!T::SortedListProvider::contains(&stash)); } + + impl_benchmark_test_suite!( + Staking, + crate::mock::ExtBuilder::default().has_stakers(true), + crate::mock::Test, + exec_name = build_and_execute + ); } #[cfg(test)] @@ -1001,10 +1008,3 @@ mod tests { }); } } - -impl_benchmark_test_suite!( - Staking, - crate::mock::ExtBuilder::default().has_stakers(true), - crate::mock::Test, - exec_name = build_and_execute -); diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index d8e72e267ea9..582e9e49bd35 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -272,6 +272,7 @@ //! validators is stored in the Session pallet's `Validators` at the end of each era. #![cfg_attr(not(feature = "std"), no_std)] +#![recursion_limit = "256"] #[cfg(feature = "runtime-benchmarks")] pub mod benchmarking; diff --git a/frame/system/benchmarking/src/lib.rs b/frame/system/benchmarking/src/lib.rs index beb61829bce3..e7371b1099e5 100644 --- a/frame/system/benchmarking/src/lib.rs +++ b/frame/system/benchmarking/src/lib.rs @@ -20,7 +20,7 @@ #![cfg_attr(not(feature = "std"), no_std)] use codec::Encode; -use frame_benchmarking::{benchmarks, impl_benchmark_test_suite, whitelisted_caller}; +use frame_benchmarking::{benchmarks, whitelisted_caller}; use frame_support::{storage, traits::Get, weights::DispatchClass}; use frame_system::{Call, DigestItemOf, Pallet as System, RawOrigin}; use sp_core::{storage::well_known_keys, ChangesTrieConfiguration}; @@ -140,6 +140,6 @@ benchmarks! { verify { assert_eq!(storage::unhashed::get_raw(&last_key), None); } -} -impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test); + impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test); +} diff --git a/frame/timestamp/src/benchmarking.rs b/frame/timestamp/src/benchmarking.rs index 97ddd4cddd63..98e05439df72 100644 --- a/frame/timestamp/src/benchmarking.rs +++ b/frame/timestamp/src/benchmarking.rs @@ -20,7 +20,7 @@ #![cfg(feature = "runtime-benchmarks")] use super::*; -use frame_benchmarking::{benchmarks, impl_benchmark_test_suite, TrackedStorageKey}; +use frame_benchmarking::{benchmarks, TrackedStorageKey}; use frame_support::{ensure, traits::OnFinalize}; use frame_system::RawOrigin; @@ -55,6 +55,6 @@ benchmarks! { verify { ensure!(!DidUpdate::::exists(), "Time was not removed."); } -} -impl_benchmark_test_suite!(Timestamp, crate::tests::new_test_ext(), crate::tests::Test); + impl_benchmark_test_suite!(Timestamp, crate::tests::new_test_ext(), crate::tests::Test); +} diff --git a/frame/tips/src/benchmarking.rs b/frame/tips/src/benchmarking.rs index 5e0812185521..d8227332bb33 100644 --- a/frame/tips/src/benchmarking.rs +++ b/frame/tips/src/benchmarking.rs @@ -19,7 +19,7 @@ #![cfg(feature = "runtime-benchmarks")] -use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite, whitelisted_caller}; +use frame_benchmarking::{account, benchmarks, whitelisted_caller}; use frame_support::ensure; use frame_system::RawOrigin; use sp_runtime::traits::Saturating; @@ -190,6 +190,6 @@ benchmarks! { let hash = T::Hashing::hash_of(&(&reason_hash, &beneficiary)); ensure!(Tips::::contains_key(hash), "tip does not exist"); }: _(RawOrigin::Root, hash) -} -impl_benchmark_test_suite!(TipsMod, crate::tests::new_test_ext(), crate::tests::Test); + impl_benchmark_test_suite!(TipsMod, crate::tests::new_test_ext(), crate::tests::Test); +} diff --git a/frame/transaction-storage/src/benchmarking.rs b/frame/transaction-storage/src/benchmarking.rs index d5da6a42b46f..6ca9b247f022 100644 --- a/frame/transaction-storage/src/benchmarking.rs +++ b/frame/transaction-storage/src/benchmarking.rs @@ -20,7 +20,7 @@ #![cfg(feature = "runtime-benchmarks")] use super::*; -use frame_benchmarking::{benchmarks, impl_benchmark_test_suite, whitelisted_caller}; +use frame_benchmarking::{benchmarks, whitelisted_caller}; use frame_support::traits::{Currency, OnFinalize, OnInitialize}; use frame_system::{EventRecord, Pallet as System, RawOrigin}; use sp_runtime::traits::{Bounded, One, Zero}; @@ -143,6 +143,6 @@ benchmarks! { verify { assert_last_event::(Event::ProofChecked.into()); } -} -impl_benchmark_test_suite!(TransactionStorage, crate::mock::new_test_ext(), crate::mock::Test); + impl_benchmark_test_suite!(TransactionStorage, crate::mock::new_test_ext(), crate::mock::Test); +} diff --git a/frame/treasury/src/benchmarking.rs b/frame/treasury/src/benchmarking.rs index 2fe0bad704f2..8570b0efdb94 100644 --- a/frame/treasury/src/benchmarking.rs +++ b/frame/treasury/src/benchmarking.rs @@ -21,7 +21,7 @@ use super::{Pallet as Treasury, *}; -use frame_benchmarking::{account, benchmarks_instance_pallet, impl_benchmark_test_suite}; +use frame_benchmarking::{account, benchmarks_instance_pallet}; use frame_support::{ensure, traits::OnInitialize}; use frame_system::RawOrigin; @@ -94,6 +94,6 @@ benchmarks_instance_pallet! { }: { Treasury::::on_initialize(T::BlockNumber::zero()); } -} -impl_benchmark_test_suite!(Treasury, crate::tests::new_test_ext(), crate::tests::Test); + impl_benchmark_test_suite!(Treasury, crate::tests::new_test_ext(), crate::tests::Test); +} diff --git a/frame/uniques/src/benchmarking.rs b/frame/uniques/src/benchmarking.rs index 5c777dc961e9..0e161bf7bfe8 100644 --- a/frame/uniques/src/benchmarking.rs +++ b/frame/uniques/src/benchmarking.rs @@ -21,8 +21,7 @@ use super::*; use frame_benchmarking::{ - account, benchmarks_instance_pallet, impl_benchmark_test_suite, whitelist_account, - whitelisted_caller, + account, benchmarks_instance_pallet, whitelist_account, whitelisted_caller, }; use frame_support::{ dispatch::UnfilteredDispatchable, @@ -379,6 +378,6 @@ benchmarks_instance_pallet! { verify { assert_last_event::(Event::ApprovalCancelled(class, instance, caller, delegate).into()); } -} -impl_benchmark_test_suite!(Uniques, crate::mock::new_test_ext(), crate::mock::Test); + impl_benchmark_test_suite!(Uniques, crate::mock::new_test_ext(), crate::mock::Test); +} diff --git a/frame/utility/src/benchmarking.rs b/frame/utility/src/benchmarking.rs index 210a6156499c..70cc61f87b9c 100644 --- a/frame/utility/src/benchmarking.rs +++ b/frame/utility/src/benchmarking.rs @@ -20,7 +20,7 @@ #![cfg(feature = "runtime-benchmarks")] use super::*; -use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite, whitelisted_caller}; +use frame_benchmarking::{account, benchmarks, whitelisted_caller}; use frame_system::RawOrigin; const SEED: u32 = 0; @@ -63,6 +63,6 @@ benchmarks! { verify { assert_last_event::(Event::BatchCompleted.into()) } -} -impl_benchmark_test_suite!(Pallet, crate::tests::new_test_ext(), crate::tests::Test); + impl_benchmark_test_suite!(Pallet, crate::tests::new_test_ext(), crate::tests::Test); +} diff --git a/frame/vesting/src/benchmarking.rs b/frame/vesting/src/benchmarking.rs index 5cdc14c8fdac..b52ddac3e885 100644 --- a/frame/vesting/src/benchmarking.rs +++ b/frame/vesting/src/benchmarking.rs @@ -19,7 +19,7 @@ #![cfg(feature = "runtime-benchmarks")] -use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite, whitelisted_caller}; +use frame_benchmarking::{account, benchmarks, whitelisted_caller}; use frame_support::assert_ok; use frame_system::{Pallet as System, RawOrigin}; use sp_runtime::traits::{Bounded, CheckedDiv, CheckedMul}; @@ -374,10 +374,10 @@ benchmarks! { T::Currency::transfer(&caller, &test_dest, expected_balance, ExistenceRequirement::AllowDeath) ); } -} -impl_benchmark_test_suite!( - Vesting, - crate::mock::ExtBuilder::default().existential_deposit(256).build(), - crate::mock::Test, -); + impl_benchmark_test_suite!( + Vesting, + crate::mock::ExtBuilder::default().existential_deposit(256).build(), + crate::mock::Test, + ); +} From c1e45a62103ce7f0b3db4926f40c38b4b1283fa9 Mon Sep 17 00:00:00 2001 From: Liu-Cheng Xu Date: Fri, 1 Oct 2021 17:43:55 +0800 Subject: [PATCH 012/695] Clean up sc-peerset (#9806) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Clean up sc-peerset * cargo +nightly fmt --all * Nit * Nit * . * Nit * . * Apply suggestions from code review * . * Update client/peerset/src/peersstate.rs Co-authored-by: Bastian Köcher --- client/network/src/config.rs | 10 ++-- .../src/protocol/notifications/behaviour.rs | 4 +- client/network/src/transactions.rs | 17 +++--- client/peerset/Cargo.toml | 1 - client/peerset/src/lib.rs | 49 +++++++++-------- client/peerset/src/peersstate.rs | 53 +++++++++---------- 6 files changed, 62 insertions(+), 72 deletions(-) diff --git a/client/network/src/config.rs b/client/network/src/config.rs index d08e29ef8589..76c806ccbf7b 100644 --- a/client/network/src/config.rs +++ b/client/network/src/config.rs @@ -155,14 +155,14 @@ pub enum Role { } impl Role { - /// True for `Role::Authority` + /// True for [`Role::Authority`]. pub fn is_authority(&self) -> bool { - matches!(self, Role::Authority { .. }) + matches!(self, Self::Authority { .. }) } - /// True for `Role::Light` + /// True for [`Role::Light`]. pub fn is_light(&self) -> bool { - matches!(self, Role::Light { .. }) + matches!(self, Self::Light { .. }) } } @@ -329,7 +329,7 @@ impl FromStr for MultiaddrWithPeerId { fn from_str(s: &str) -> Result { let (peer_id, multiaddr) = parse_str_addr(s)?; - Ok(MultiaddrWithPeerId { peer_id, multiaddr }) + Ok(Self { peer_id, multiaddr }) } } diff --git a/client/network/src/protocol/notifications/behaviour.rs b/client/network/src/protocol/notifications/behaviour.rs index da2967d6f26e..01138e320757 100644 --- a/client/network/src/protocol/notifications/behaviour.rs +++ b/client/network/src/protocol/notifications/behaviour.rs @@ -417,7 +417,7 @@ impl Notifications { /// Returns true if we have an open substream to the given peer. pub fn is_open(&self, peer_id: &PeerId, set_id: sc_peerset::SetId) -> bool { - self.peers.get(&(peer_id.clone(), set_id)).map(|p| p.is_open()).unwrap_or(false) + self.peers.get(&(*peer_id, set_id)).map(|p| p.is_open()).unwrap_or(false) } /// Disconnects the given peer if we are connected to it. @@ -1777,7 +1777,7 @@ impl NetworkBehaviour for Notifications { "Handler({}, {:?}) => CloseResult({:?})", source, connection, set_id); - match self.peers.get_mut(&(source.clone(), set_id)) { + match self.peers.get_mut(&(source, set_id)) { // Move the connection from `Closing` to `Closed`. Some(PeerState::Incoming { connections, .. }) | Some(PeerState::DisabledPendingEnable { connections, .. }) | diff --git a/client/network/src/transactions.rs b/client/network/src/transactions.rs index 82e7e8fe1714..9565466ea1c0 100644 --- a/client/network/src/transactions.rs +++ b/client/network/src/transactions.rs @@ -92,7 +92,7 @@ struct Metrics { impl Metrics { fn register(r: &Registry) -> Result { - Ok(Metrics { + Ok(Self { propagated_transactions: register( Counter::new( "sync_propagated_transactions", @@ -133,7 +133,7 @@ pub struct TransactionsHandlerPrototype { impl TransactionsHandlerPrototype { /// Create a new instance. pub fn new(protocol_id: ProtocolId) -> Self { - TransactionsHandlerPrototype { + Self { protocol_name: Cow::from({ let mut proto = String::new(); proto.push_str("/"); @@ -401,7 +401,7 @@ impl TransactionsHandler { let hash = self.transaction_pool.hash_of(&t); peer.known_transactions.insert(hash.clone()); - self.service.report_peer(who.clone(), rep::ANY_TRANSACTION); + self.service.report_peer(who, rep::ANY_TRANSACTION); match self.pending_transactions_peers.entry(hash.clone()) { Entry::Vacant(entry) => { @@ -409,10 +409,10 @@ impl TransactionsHandler { validation: self.transaction_pool.import(t), tx_hash: hash, }); - entry.insert(vec![who.clone()]); + entry.insert(vec![who]); }, Entry::Occupied(mut entry) => { - entry.get_mut().push(who.clone()); + entry.get_mut().push(who); }, } } @@ -468,11 +468,8 @@ impl TransactionsHandler { propagated_to.entry(hash).or_default().push(who.to_base58()); } trace!(target: "sync", "Sending {} transactions to {}", to_send.len(), who); - self.service.write_notification( - who.clone(), - self.protocol_name.clone(), - to_send.encode(), - ); + self.service + .write_notification(*who, self.protocol_name.clone(), to_send.encode()); } } diff --git a/client/peerset/Cargo.toml b/client/peerset/Cargo.toml index 5962620d6e06..a7e9130cfff1 100644 --- a/client/peerset/Cargo.toml +++ b/client/peerset/Cargo.toml @@ -13,7 +13,6 @@ readme = "README.md" [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] - [dependencies] futures = "0.3.9" libp2p = { version = "0.39.1", default-features = false } diff --git a/client/peerset/src/lib.rs b/client/peerset/src/lib.rs index 0775354befee..7fbda1ba7b7f 100644 --- a/client/peerset/src/lib.rs +++ b/client/peerset/src/lib.rs @@ -79,13 +79,13 @@ pub struct SetId(usize); impl SetId { pub const fn from(id: usize) -> Self { - SetId(id) + Self(id) } } impl From for SetId { fn from(id: usize) -> Self { - SetId(id) + Self(id) } } @@ -107,12 +107,12 @@ pub struct ReputationChange { impl ReputationChange { /// New reputation change with given delta and reason. pub const fn new(value: i32, reason: &'static str) -> ReputationChange { - ReputationChange { value, reason } + Self { value, reason } } /// New reputation change that forces minimum possible reputation. pub const fn new_fatal(reason: &'static str) -> ReputationChange { - ReputationChange { value: i32::MIN, reason } + Self { value: i32::MIN, reason } } } @@ -208,8 +208,8 @@ pub enum Message { pub struct IncomingIndex(pub u64); impl From for IncomingIndex { - fn from(val: u64) -> IncomingIndex { - IncomingIndex(val) + fn from(val: u64) -> Self { + Self(val) } } @@ -274,7 +274,7 @@ pub struct Peerset { impl Peerset { /// Builds a new peerset from the given configuration. - pub fn from_config(config: PeersetConfig) -> (Peerset, PeersetHandle) { + pub fn from_config(config: PeersetConfig) -> (Self, PeersetHandle) { let (tx, rx) = tracing_unbounded("mpsc_peerset_messages"); let handle = PeersetHandle { tx: tx.clone() }; @@ -282,7 +282,7 @@ impl Peerset { let mut peerset = { let now = Instant::now(); - Peerset { + Self { data: peersstate::PeersState::new(config.sets.iter().map(|set| { peersstate::SetConfig { in_peers: set.in_peers, out_peers: set.out_peers } })), @@ -322,7 +322,7 @@ impl Peerset { } fn on_add_reserved_peer(&mut self, set_id: SetId, peer_id: PeerId) { - let newly_inserted = self.reserved_nodes[set_id.0].0.insert(peer_id.clone()); + let newly_inserted = self.reserved_nodes[set_id.0].0.insert(peer_id); if !newly_inserted { return } @@ -422,8 +422,7 @@ impl Peerset { match self.data.peer(set_id.0, &peer_id) { peersstate::Peer::Connected(peer) => { - self.message_queue - .push_back(Message::Drop { set_id, peer_id: peer.peer_id().clone() }); + self.message_queue.push_back(Message::Drop { set_id, peer_id: *peer.peer_id() }); peer.disconnect().forget_peer(); }, peersstate::Peer::NotConnected(peer) => { @@ -819,8 +818,8 @@ mod tests { }; let (peerset, handle) = Peerset::from_config(config); - handle.add_reserved_peer(SetId::from(0), reserved_peer.clone()); - handle.add_reserved_peer(SetId::from(0), reserved_peer2.clone()); + handle.add_reserved_peer(SetId::from(0), reserved_peer); + handle.add_reserved_peer(SetId::from(0), reserved_peer2); assert_messages( peerset, @@ -845,22 +844,22 @@ mod tests { sets: vec![SetConfig { in_peers: 2, out_peers: 1, - bootnodes: vec![bootnode.clone()], + bootnodes: vec![bootnode], reserved_nodes: Default::default(), reserved_only: false, }], }; let (mut peerset, _handle) = Peerset::from_config(config); - peerset.incoming(SetId::from(0), incoming.clone(), ii); - peerset.incoming(SetId::from(0), incoming.clone(), ii4); - peerset.incoming(SetId::from(0), incoming2.clone(), ii2); - peerset.incoming(SetId::from(0), incoming3.clone(), ii3); + peerset.incoming(SetId::from(0), incoming, ii); + peerset.incoming(SetId::from(0), incoming, ii4); + peerset.incoming(SetId::from(0), incoming2, ii2); + peerset.incoming(SetId::from(0), incoming3, ii3); assert_messages( peerset, vec![ - Message::Connect { set_id: SetId::from(0), peer_id: bootnode.clone() }, + Message::Connect { set_id: SetId::from(0), peer_id: bootnode }, Message::Accept(ii), Message::Accept(ii2), Message::Reject(ii3), @@ -883,7 +882,7 @@ mod tests { }; let (mut peerset, _) = Peerset::from_config(config); - peerset.incoming(SetId::from(0), incoming.clone(), ii); + peerset.incoming(SetId::from(0), incoming, ii); assert_messages(peerset, vec![Message::Reject(ii)]); } @@ -897,15 +896,15 @@ mod tests { sets: vec![SetConfig { in_peers: 0, out_peers: 2, - bootnodes: vec![bootnode.clone()], + bootnodes: vec![bootnode], reserved_nodes: Default::default(), reserved_only: false, }], }; let (mut peerset, _handle) = Peerset::from_config(config); - peerset.add_to_peers_set(SetId::from(0), discovered.clone()); - peerset.add_to_peers_set(SetId::from(0), discovered.clone()); + peerset.add_to_peers_set(SetId::from(0), discovered); + peerset.add_to_peers_set(SetId::from(0), discovered); peerset.add_to_peers_set(SetId::from(0), discovered2); assert_messages( @@ -931,7 +930,7 @@ mod tests { // We ban a node by setting its reputation under the threshold. let peer_id = PeerId::random(); - handle.report_peer(peer_id.clone(), ReputationChange::new(BANNED_THRESHOLD - 1, "")); + handle.report_peer(peer_id, ReputationChange::new(BANNED_THRESHOLD - 1, "")); let fut = futures::future::poll_fn(move |cx| { // We need one polling for the message to be processed. @@ -974,7 +973,7 @@ mod tests { // We ban a node by setting its reputation under the threshold. let peer_id = PeerId::random(); - handle.report_peer(peer_id.clone(), ReputationChange::new(BANNED_THRESHOLD - 1, "")); + handle.report_peer(peer_id, ReputationChange::new(BANNED_THRESHOLD - 1, "")); let fut = futures::future::poll_fn(move |cx| { // We need one polling for the message to be processed. diff --git a/client/peerset/src/peersstate.rs b/client/peerset/src/peersstate.rs index 7717620eae3a..d7a9ef913587 100644 --- a/client/peerset/src/peersstate.rs +++ b/client/peerset/src/peersstate.rs @@ -105,8 +105,8 @@ struct Node { } impl Node { - fn new(num_sets: usize) -> Node { - Node { sets: (0..num_sets).map(|_| MembershipState::NotMember).collect(), reputation: 0 } + fn new(num_sets: usize) -> Self { + Self { sets: (0..num_sets).map(|_| MembershipState::NotMember).collect(), reputation: 0 } } } @@ -128,21 +128,24 @@ enum MembershipState { } impl MembershipState { - /// Returns `true` for `In` and `Out`. + /// Returns `true` for [`MembershipState::In`] and [`MembershipState::Out`]. fn is_connected(self) -> bool { match self { - MembershipState::NotMember => false, - MembershipState::In => true, - MembershipState::Out => true, - MembershipState::NotConnected { .. } => false, + Self::In | Self::Out => true, + Self::NotMember | Self::NotConnected { .. } => false, } } + + /// Returns `true` for [`MembershipState::NotConnected`]. + fn is_not_connected(self) -> bool { + matches!(self, Self::NotConnected { .. }) + } } impl PeersState { - /// Builds a new empty `PeersState`. + /// Builds a new empty [`PeersState`]. pub fn new(sets: impl IntoIterator) -> Self { - PeersState { + Self { nodes: HashMap::new(), sets: sets .into_iter() @@ -242,12 +245,7 @@ impl PeersState { let outcome = self .nodes .iter_mut() - .filter(|(_, Node { sets, .. })| match sets[set] { - MembershipState::NotMember => false, - MembershipState::In => false, - MembershipState::Out => false, - MembershipState::NotConnected { .. } => true, - }) + .filter(|(_, Node { sets, .. })| sets[set].is_not_connected()) .fold(None::<(&PeerId, &mut Node)>, |mut cur_node, to_try| { if let Some(cur_node) = cur_node.take() { if cur_node.1.reputation >= to_try.1.reputation { @@ -318,35 +316,32 @@ pub enum Peer<'a> { } impl<'a> Peer<'a> { - /// If we are the `Connected` variant, returns the inner `ConnectedPeer`. Returns `None` + /// If we are the `Connected` variant, returns the inner [`ConnectedPeer`]. Returns `None` /// otherwise. pub fn into_connected(self) -> Option> { match self { - Peer::Connected(peer) => Some(peer), - Peer::NotConnected(_) => None, - Peer::Unknown(_) => None, + Self::Connected(peer) => Some(peer), + Self::NotConnected(..) | Self::Unknown(..) => None, } } - /// If we are the `Unknown` variant, returns the inner `ConnectedPeer`. Returns `None` + /// If we are the `NotConnected` variant, returns the inner [`NotConnectedPeer`]. Returns `None` /// otherwise. #[cfg(test)] // Feel free to remove this if this function is needed outside of tests pub fn into_not_connected(self) -> Option> { match self { - Peer::Connected(_) => None, - Peer::NotConnected(peer) => Some(peer), - Peer::Unknown(_) => None, + Self::NotConnected(peer) => Some(peer), + Self::Connected(..) | Self::Unknown(..) => None, } } - /// If we are the `Unknown` variant, returns the inner `ConnectedPeer`. Returns `None` + /// If we are the `Unknown` variant, returns the inner [`UnknownPeer`]. Returns `None` /// otherwise. #[cfg(test)] // Feel free to remove this if this function is needed outside of tests pub fn into_unknown(self) -> Option> { match self { - Peer::Connected(_) => None, - Peer::NotConnected(_) => None, - Peer::Unknown(peer) => Some(peer), + Self::Unknown(peer) => Some(peer), + Self::Connected(..) | Self::NotConnected(..) => None, } } } @@ -473,7 +468,7 @@ impl<'a> NotConnectedPeer<'a> { /// the slots are full, the node stays "not connected" and we return `Err`. /// /// Non-slot-occupying nodes don't count towards the number of slots. - pub fn try_outgoing(self) -> Result, NotConnectedPeer<'a>> { + pub fn try_outgoing(self) -> Result, Self> { let is_no_slot_occupy = self.state.sets[self.set].no_slot_nodes.contains(&*self.peer_id); // Note that it is possible for num_out to be strictly superior to the max, in case we were @@ -500,7 +495,7 @@ impl<'a> NotConnectedPeer<'a> { /// the slots are full, the node stays "not connected" and we return `Err`. /// /// Non-slot-occupying nodes don't count towards the number of slots. - pub fn try_accept_incoming(self) -> Result, NotConnectedPeer<'a>> { + pub fn try_accept_incoming(self) -> Result, Self> { let is_no_slot_occupy = self.state.sets[self.set].no_slot_nodes.contains(&*self.peer_id); // Note that it is possible for num_in to be strictly superior to the max, in case we were From 540b4fd0f6bf8157f5402f0095f78f0ed893c57b Mon Sep 17 00:00:00 2001 From: RyuH1 <79819095+RyuH1@users.noreply.github.com> Date: Fri, 1 Oct 2021 19:22:13 +0800 Subject: [PATCH 013/695] Add SS58 prefix for Automata (#9805) --- primitives/core/src/crypto.rs | 4 ++++ ss58-registry.json | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/primitives/core/src/crypto.rs b/primitives/core/src/crypto.rs index cf7be5f2166e..a9f3e904a2a8 100644 --- a/primitives/core/src/crypto.rs +++ b/primitives/core/src/crypto.rs @@ -617,8 +617,12 @@ ss58_address_format!( (1284, "moonbeam", "Moonbeam, session key (*25519).") Moonriver => (1285, "moonriver", "Moonriver, session key (*25519).") + Automata => + (2349, "automata", "Automata mainnet standard account (*25519).") BasiliskAccount => (10041, "basilisk", "Basilisk standard account (*25519).") + ContextFree => + (11820, "contextfree", "Automata ContextFree standard account (*25519).") // Note: 16384 and above are reserved. ); diff --git a/ss58-registry.json b/ss58-registry.json index 7c95f421586a..62602d829f6b 100644 --- a/ss58-registry.json +++ b/ss58-registry.json @@ -640,6 +640,15 @@ "standardAccount": "secp256k1", "website": "https://moonbeam.network" }, + { + "prefix": 2349, + "network": "automata", + "displayName": "Automata Mainnet", + "symbols": ["ATA"], + "decimals": [18], + "standardAccount": "*25519", + "website": "https://ata.network" + }, { "prefix": 10041, "network": "basilisk", @@ -648,6 +657,15 @@ "decimals": [12], "standardAccount": "*25519", "website": "https://bsx.fi" + }, + { + "prefix": 11820, + "network": "contextfree", + "displayName": "Automata ContextFree", + "symbols": ["CTX"], + "decimals": [18], + "standardAccount": "*25519", + "website": "https://ata.network" } ] } From c60ccc0719ea2036d3878b94bd9257c9332f5606 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 1 Oct 2021 16:25:13 +0200 Subject: [PATCH 014/695] Quickly skip invalid transactions during block authorship. (#9789) * Support skipping invalid transactions in the iterator. * Expose concrete iterator. * cargo +nightly fmt --all * More consistent placement. * Update Cargo.lock * Pass transaction to 'report_invalid' --- bin/node/bench/src/construct.rs | 28 +++-- .../basic-authorship/src/basic_authorship.rs | 8 +- client/transaction-pool/api/src/lib.rs | 28 ++++- client/transaction-pool/graph/Cargo.toml | 39 ------ .../transaction-pool/src/graph/base_pool.rs | 4 +- client/transaction-pool/src/graph/ready.rs | 114 +++++++++++++++--- .../src/graph/validated_pool.rs | 4 +- client/transaction-pool/src/lib.rs | 5 +- 8 files changed, 159 insertions(+), 71 deletions(-) delete mode 100644 client/transaction-pool/graph/Cargo.toml diff --git a/bin/node/bench/src/construct.rs b/bin/node/bench/src/construct.rs index 1532e02bd3ef..ca1a1c18f9ea 100644 --- a/bin/node/bench/src/construct.rs +++ b/bin/node/bench/src/construct.rs @@ -30,8 +30,8 @@ use std::{borrow::Cow, collections::HashMap, pin::Pin, sync::Arc}; use node_primitives::Block; use node_testing::bench::{BenchDb, BlockType, DatabaseType, KeyTypes, Profile}; use sc_transaction_pool_api::{ - ImportNotificationStream, PoolFuture, PoolStatus, TransactionFor, TransactionSource, - TransactionStatusStreamFor, TxHash, + ImportNotificationStream, PoolFuture, PoolStatus, ReadyTransactions, TransactionFor, + TransactionSource, TransactionStatusStreamFor, TxHash, }; use sp_consensus::{Environment, Proposer}; use sp_inherents::InherentDataProvider; @@ -216,6 +216,19 @@ impl sc_transaction_pool_api::InPoolTransaction for PoolTransaction { #[derive(Clone, Debug)] pub struct Transactions(Vec>); +pub struct TransactionsIterator(std::vec::IntoIter>); + +impl Iterator for TransactionsIterator { + type Item = Arc; + + fn next(&mut self) -> Option { + self.0.next() + } +} + +impl ReadyTransactions for TransactionsIterator { + fn report_invalid(&mut self, _tx: &Self::Item) {} +} impl sc_transaction_pool_api::TransactionPool for Transactions { type Block = Block; @@ -257,16 +270,17 @@ impl sc_transaction_pool_api::TransactionPool for Transactions { _at: NumberFor, ) -> Pin< Box< - dyn Future> + Send>> - + Send, + dyn Future< + Output = Box> + Send>, + > + Send, >, > { - let iter: Box> + Send> = - Box::new(self.0.clone().into_iter()); + let iter: Box> + Send> = + Box::new(TransactionsIterator(self.0.clone().into_iter())); Box::pin(futures::future::ready(iter)) } - fn ready(&self) -> Box> + Send> { + fn ready(&self) -> Box> + Send> { unimplemented!() } diff --git a/client/basic-authorship/src/basic_authorship.rs b/client/basic-authorship/src/basic_authorship.rs index e38bb11688f8..bbee60ae98dc 100644 --- a/client/basic-authorship/src/basic_authorship.rs +++ b/client/basic-authorship/src/basic_authorship.rs @@ -344,7 +344,7 @@ where let mut t2 = futures_timer::Delay::new(deadline.saturating_duration_since((self.now)()) / 8).fuse(); - let pending_iterator = select! { + let mut pending_iterator = select! { res = t1 => res, _ = t2 => { log::warn!( @@ -363,7 +363,7 @@ where let mut transaction_pushed = false; let mut hit_block_size_limit = false; - for pending_tx in pending_iterator { + while let Some(pending_tx) = pending_iterator.next() { if (self.now)() > deadline { debug!( "Consensus deadline reached when pushing block transactions, \ @@ -378,6 +378,7 @@ where let block_size = block_builder.estimate_block_size(self.include_proof_in_block_size_estimation); if block_size + pending_tx_data.encoded_size() > block_size_limit { + pending_iterator.report_invalid(&pending_tx); if skipped < MAX_SKIPPED_TRANSACTIONS { skipped += 1; debug!( @@ -400,6 +401,7 @@ where debug!("[{:?}] Pushed to the block.", pending_tx_hash); }, Err(ApplyExtrinsicFailed(Validity(e))) if e.exhausted_resources() => { + pending_iterator.report_invalid(&pending_tx); if skipped < MAX_SKIPPED_TRANSACTIONS { skipped += 1; debug!( @@ -412,6 +414,7 @@ where } }, Err(e) if skipped > 0 => { + pending_iterator.report_invalid(&pending_tx); trace!( "[{:?}] Ignoring invalid transaction when skipping: {}", pending_tx_hash, @@ -419,6 +422,7 @@ where ); }, Err(e) => { + pending_iterator.report_invalid(&pending_tx); debug!("[{:?}] Invalid transaction: {}", pending_tx_hash, e); unqueue_invalid.push(pending_tx_hash); }, diff --git a/client/transaction-pool/api/src/lib.rs b/client/transaction-pool/api/src/lib.rs index a6252f1373c5..cd8784bfc83e 100644 --- a/client/transaction-pool/api/src/lib.rs +++ b/client/transaction-pool/api/src/lib.rs @@ -223,13 +223,14 @@ pub trait TransactionPool: Send + Sync { at: NumberFor, ) -> Pin< Box< - dyn Future> + Send>> - + Send, + dyn Future< + Output = Box> + Send>, + > + Send, >, >; /// Get an iterator for ready transactions ordered by priority. - fn ready(&self) -> Box> + Send>; + fn ready(&self) -> Box> + Send>; // *** Block production /// Remove transactions identified by given hashes (and dependent transactions) from the pool. @@ -254,6 +255,27 @@ pub trait TransactionPool: Send + Sync { fn ready_transaction(&self, hash: &TxHash) -> Option>; } +/// An iterator of ready transactions. +/// +/// The trait extends regular [`std::iter::Iterator`] trait and allows reporting +/// last-returned element as invalid. +/// +/// The implementation is then allowed, for performance reasons, to change the elements +/// returned next, by e.g. skipping elements that are known to depend on the reported +/// transaction, which yields them invalid as well. +pub trait ReadyTransactions: Iterator { + /// Report given transaction as invalid. + /// + /// This might affect subsequent elements returned by the iterator, so dependent transactions + /// are skipped for performance reasons. + fn report_invalid(&mut self, _tx: &Self::Item); +} + +/// A no-op implementation for an empty iterator. +impl ReadyTransactions for std::iter::Empty { + fn report_invalid(&mut self, _tx: &T) {} +} + /// Events that the transaction pool listens for. pub enum ChainEvent { /// New best block have been added to the chain diff --git a/client/transaction-pool/graph/Cargo.toml b/client/transaction-pool/graph/Cargo.toml deleted file mode 100644 index b49cadc51c33..000000000000 --- a/client/transaction-pool/graph/Cargo.toml +++ /dev/null @@ -1,39 +0,0 @@ -[package] -name = "sc-transaction-graph" -version = "4.0.0-dev" -authors = ["Parity Technologies "] -edition = "2018" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -homepage = "https://substrate.dev" -repository = "https://github.com/paritytech/substrate/" -description = "Generic Transaction Pool" -readme = "README.md" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[dependencies] -derive_more = "0.99.2" -thiserror = "1.0.21" -futures = "0.3.9" -log = "0.4.8" -parking_lot = "0.11.1" -serde = { version = "1.0.101", features = ["derive"] } -sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sc-utils = { version = "4.0.0-dev", path = "../../utils" } -sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" } -sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } -sp-transaction-pool = { version = "4.0.0-dev", path = "../../../primitives/transaction-pool" } -parity-util-mem = { version = "0.10.0", default-features = false, features = ["primitive-types"] } -linked-hash-map = "0.5.4" -retain_mut = "0.1.3" - -[dev-dependencies] -assert_matches = "1.3.0" -codec = { package = "parity-scale-codec", version = "2.0.0" } -substrate-test-runtime = { version = "2.0.0", path = "../../../test-utils/runtime" } -criterion = "0.3" - -[[bench]] -name = "basics" -harness = false diff --git a/client/transaction-pool/src/graph/base_pool.rs b/client/transaction-pool/src/graph/base_pool.rs index 890a87e82929..2c8becdfb2f0 100644 --- a/client/transaction-pool/src/graph/base_pool.rs +++ b/client/transaction-pool/src/graph/base_pool.rs @@ -36,7 +36,7 @@ use sp_runtime::{ use super::{ future::{FutureTransactions, WaitingTransaction}, - ready::ReadyTransactions, + ready::{BestIterator, ReadyTransactions}, }; /// Successful import result. @@ -355,7 +355,7 @@ impl BasePool impl Iterator>> { + pub fn ready(&self) -> BestIterator { self.ready.get() } diff --git a/client/transaction-pool/src/graph/ready.rs b/client/transaction-pool/src/graph/ready.rs index 03689aeb32e6..99a034689ccd 100644 --- a/client/transaction-pool/src/graph/ready.rs +++ b/client/transaction-pool/src/graph/ready.rs @@ -23,7 +23,7 @@ use std::{ sync::Arc, }; -use log::trace; +use log::{debug, trace}; use sc_transaction_pool_api::error; use serde::Serialize; use sp_runtime::{traits::Member, transaction_validity::TransactionTag as Tag}; @@ -156,11 +156,16 @@ impl ReadyTransactions { /// - transactions that are valid for a shorter time go first /// 4. Lastly we sort by the time in the queue /// - transactions that are longer in the queue go first - pub fn get(&self) -> impl Iterator>> { + /// + /// The iterator is providing a way to report transactions that the receiver considers invalid. + /// In such case the entire subgraph of transactions that depend on the reported one will be + /// skipped. + pub fn get(&self) -> BestIterator { BestIterator { all: self.ready.clone(), best: self.best.clone(), awaiting: Default::default(), + invalid: Default::default(), } } @@ -482,6 +487,7 @@ pub struct BestIterator { all: ReadOnlyTrackedMap>, awaiting: HashMap)>, best: BTreeSet>, + invalid: HashSet, } impl BestIterator { @@ -498,6 +504,34 @@ impl BestIterator { } } +impl sc_transaction_pool_api::ReadyTransactions + for BestIterator +{ + fn report_invalid(&mut self, tx: &Self::Item) { + BestIterator::report_invalid(self, tx) + } +} + +impl BestIterator { + /// Report given transaction as invalid. + /// + /// As a consequence, all values that depend on the invalid one will be skipped. + /// When given transaction is not in the pool it has no effect. + /// When invoked on a fully drained iterator it has no effect either. + pub fn report_invalid(&mut self, tx: &Arc>) { + if let Some(to_report) = self.all.read().get(&tx.hash) { + debug!( + target: "txpool", + "[{:?}] Reported as invalid. Will skip sub-chains while iterating.", + to_report.transaction.transaction.hash + ); + for hash in &to_report.unlocks { + self.invalid.insert(hash.clone()); + } + } + } +} + impl Iterator for BestIterator { type Item = Arc>; @@ -505,8 +539,19 @@ impl Iterator for BestIterator { loop { let best = self.best.iter().next_back()?.clone(); let best = self.best.take(&best)?; + let hash = &best.transaction.hash; + + // Check if the transaction was marked invalid. + if self.invalid.contains(hash) { + debug!( + target: "txpool", + "[{:?}] Skipping invalid child transaction while iterating.", + hash + ); + continue + } - let next = self.all.read().get(&best.transaction.hash).cloned(); + let next = self.all.read().get(hash).cloned(); let ready = match next { Some(ready) => ready, // The transaction is not in all, maybe it was removed in the meantime? @@ -635,10 +680,13 @@ mod tests { assert_eq!(ready.get().count(), 3); } - #[test] - fn should_return_best_transactions_in_correct_order() { - // given - let mut ready = ReadyTransactions::default(); + /// Populate the pool, with a graph that looks like so: + /// + /// tx1 -> tx2 \ + /// -> -> tx3 + /// -> tx4 -> tx5 -> tx6 + /// -> tx7 + fn populate_pool(ready: &mut ReadyTransactions>) { let mut tx1 = tx(1); tx1.requires.clear(); let mut tx2 = tx(2); @@ -649,11 +697,17 @@ mod tests { tx3.provides = vec![]; let mut tx4 = tx(4); tx4.requires = vec![tx1.provides[0].clone()]; - tx4.provides = vec![]; - let tx5 = Transaction { - data: vec![5], + tx4.provides = vec![vec![107]]; + let mut tx5 = tx(5); + tx5.requires = vec![tx4.provides[0].clone()]; + tx5.provides = vec![vec![108]]; + let mut tx6 = tx(6); + tx6.requires = vec![tx5.provides[0].clone()]; + tx6.provides = vec![]; + let tx7 = Transaction { + data: vec![7], bytes: 1, - hash: 5, + hash: 7, priority: 1, valid_till: u64::MAX, // use the max here for testing. requires: vec![tx1.provides[0].clone()], @@ -663,20 +717,30 @@ mod tests { }; // when - for tx in vec![tx1, tx2, tx3, tx4, tx5] { - import(&mut ready, tx).unwrap(); + for tx in vec![tx1, tx2, tx3, tx7, tx4, tx5, tx6] { + import(ready, tx).unwrap(); } - // then assert_eq!(ready.best.len(), 1); + } + + #[test] + fn should_return_best_transactions_in_correct_order() { + // given + let mut ready = ReadyTransactions::default(); + populate_pool(&mut ready); + // when let mut it = ready.get().map(|tx| tx.data[0]); + // then assert_eq!(it.next(), Some(1)); assert_eq!(it.next(), Some(2)); assert_eq!(it.next(), Some(3)); assert_eq!(it.next(), Some(4)); assert_eq!(it.next(), Some(5)); + assert_eq!(it.next(), Some(6)); + assert_eq!(it.next(), Some(7)); assert_eq!(it.next(), None); } @@ -725,4 +789,26 @@ mod tests { TransactionRef { transaction: Arc::new(with_priority(3, 3)), insertion_id: 2 } ); } + + #[test] + fn should_skip_invalid_transactions_while_iterating() { + // given + let mut ready = ReadyTransactions::default(); + populate_pool(&mut ready); + + // when + let mut it = ready.get(); + let data = |tx: &Arc>>| tx.data[0]; + + // then + assert_eq!(it.next().as_ref().map(data), Some(1)); + assert_eq!(it.next().as_ref().map(data), Some(2)); + assert_eq!(it.next().as_ref().map(data), Some(3)); + let tx4 = it.next(); + assert_eq!(tx4.as_ref().map(data), Some(4)); + // report 4 as invalid, which should skip 5 & 6. + it.report_invalid(&tx4.unwrap()); + assert_eq!(it.next().as_ref().map(data), Some(7)); + assert_eq!(it.next().as_ref().map(data), None); + } } diff --git a/client/transaction-pool/src/graph/validated_pool.rs b/client/transaction-pool/src/graph/validated_pool.rs index e4aad7f342b5..dba586adc846 100644 --- a/client/transaction-pool/src/graph/validated_pool.rs +++ b/client/transaction-pool/src/graph/validated_pool.rs @@ -25,7 +25,7 @@ use std::{ use futures::channel::mpsc::{channel, Sender}; use parking_lot::{Mutex, RwLock}; use retain_mut::RetainMut; -use sc_transaction_pool_api::{error, PoolStatus}; +use sc_transaction_pool_api::{error, PoolStatus, ReadyTransactions}; use serde::Serialize; use sp_runtime::{ generic::BlockId, @@ -630,7 +630,7 @@ impl ValidatedPool { } /// Get an iterator for ready transactions ordered by priority - pub fn ready(&self) -> impl Iterator> + Send { + pub fn ready(&self) -> impl ReadyTransactions> + Send { self.pool.read().ready() } diff --git a/client/transaction-pool/src/lib.rs b/client/transaction-pool/src/lib.rs index 6eb5bd2f332e..4d355df22d82 100644 --- a/client/transaction-pool/src/lib.rs +++ b/client/transaction-pool/src/lib.rs @@ -56,7 +56,8 @@ use std::{ use graph::{ExtrinsicHash, IsValidator}; use sc_transaction_pool_api::{ ChainEvent, ImportNotificationStream, MaintainedTransactionPool, PoolFuture, PoolStatus, - TransactionFor, TransactionPool, TransactionSource, TransactionStatusStreamFor, TxHash, + ReadyTransactions, TransactionFor, TransactionPool, TransactionSource, + TransactionStatusStreamFor, TxHash, }; use sp_core::traits::SpawnEssentialNamed; use sp_runtime::{ @@ -69,7 +70,7 @@ use crate::metrics::MetricsLink as PrometheusMetrics; use prometheus_endpoint::Registry as PrometheusRegistry; type BoxedReadyIterator = - Box>> + Send>; + Box>> + Send>; type ReadyIteratorFor = BoxedReadyIterator, graph::ExtrinsicFor>; From fdce20c70e0e12f1e9011f6d253a47421014131b Mon Sep 17 00:00:00 2001 From: Jay Pavlina Date: Sat, 2 Oct 2021 03:11:37 -0500 Subject: [PATCH 015/695] Implement core::fmt::Debug for BoundedVec (#9914) --- frame/support/src/storage/bounded_vec.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/frame/support/src/storage/bounded_vec.rs b/frame/support/src/storage/bounded_vec.rs index 44eaab905423..f353127969c5 100644 --- a/frame/support/src/storage/bounded_vec.rs +++ b/frame/support/src/storage/bounded_vec.rs @@ -200,13 +200,12 @@ impl Default for BoundedVec { } } -#[cfg(feature = "std")] -impl std::fmt::Debug for BoundedVec +impl sp_std::fmt::Debug for BoundedVec where - T: std::fmt::Debug, + T: sp_std::fmt::Debug, S: Get, { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut sp_std::fmt::Formatter<'_>) -> sp_std::fmt::Result { f.debug_tuple("BoundedVec").field(&self.0).field(&Self::bound()).finish() } } From df6a1ad92a066a8af0f6a1b327cbb26b3f0c89c1 Mon Sep 17 00:00:00 2001 From: Dan Shields <35669742+NukeManDan@users.noreply.github.com> Date: Sat, 2 Oct 2021 02:27:06 -0600 Subject: [PATCH 016/695] Downstream `node-template` pull (#9915) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * downstream node template pull: README updated, add shell.nix * consistant cargo.toml style * Update bin/node-template/shell.nix Co-authored-by: Bastian Köcher --- .maintain/node-template-release/Cargo.lock | 616 ++++++++++++++++++ bin/node-template/README.md | 113 ++-- bin/node-template/node/Cargo.toml | 8 +- bin/node-template/pallets/template/Cargo.toml | 11 +- bin/node-template/runtime/Cargo.toml | 5 +- bin/node-template/shell.nix | 35 + 6 files changed, 729 insertions(+), 59 deletions(-) create mode 100644 .maintain/node-template-release/Cargo.lock create mode 100644 bin/node-template/shell.nix diff --git a/.maintain/node-template-release/Cargo.lock b/.maintain/node-template-release/Cargo.lock new file mode 100644 index 000000000000..ee562498c811 --- /dev/null +++ b/.maintain/node-template-release/Cargo.lock @@ -0,0 +1,616 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "ansi_term" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +dependencies = [ + "winapi", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "cc" +version = "1.0.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26a6ce4b6a484fa3edb70f7efa6fc430fd2b87285fe8b84304fd0936faa0dc0" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clap" +version = "2.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" +dependencies = [ + "ansi_term", + "atty", + "bitflags", + "strsim", + "textwrap", + "unicode-width", + "vec_map", +] + +[[package]] +name = "crc32fast" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "curl-sys" +version = "0.4.48+curl-7.79.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a77a741f832116da66aeb126b4f19190ecf46144a74a9bde43c2086f38da0e" +dependencies = [ + "cc", + "libc", + "libz-sys", + "openssl-sys", + "pkg-config", + "vcpkg", + "winapi", +] + +[[package]] +name = "filetime" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "975ccf83d8d9d0d84682850a38c8169027be83368805971cc4f238c2b245bc98" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "winapi", +] + +[[package]] +name = "flate2" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" +dependencies = [ + "cfg-if", + "crc32fast", + "libc", + "miniz_oxide", +] + +[[package]] +name = "fs_extra" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394" + +[[package]] +name = "getrandom" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "git2" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7339329bfa14a00223244311560d11f8f489b453fb90092af97f267a6090ab0" +dependencies = [ + "bitflags", + "libc", + "libgit2-sys", + "log", + "openssl-probe", + "openssl-sys", + "url", +] + +[[package]] +name = "glob" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "idna" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6" + +[[package]] +name = "libgit2-sys" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48441cb35dc255da8ae72825689a95368bf510659ae1ad55dc4aa88cb1789bf1" +dependencies = [ + "cc", + "curl-sys", + "libc", + "libssh2-sys", + "libz-sys", + "openssl-sys", + "pkg-config", +] + +[[package]] +name = "libssh2-sys" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0186af0d8f171ae6b9c4c90ec51898bad5d08a2d5e470903a50d9ad8959cbee" +dependencies = [ + "cc", + "libc", + "libz-sys", + "openssl-sys", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "libz-sys" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de5435b8549c16d423ed0c03dbaafe57cf6c3344744f1242520d59c9d8ecec66" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "log" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "matches" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" + +[[package]] +name = "miniz_oxide" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +dependencies = [ + "adler", + "autocfg", +] + +[[package]] +name = "node-template-release" +version = "3.0.0" +dependencies = [ + "flate2", + "fs_extra", + "git2", + "glob", + "structopt", + "tar", + "tempfile", + "toml", +] + +[[package]] +name = "openssl-probe" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a" + +[[package]] +name = "openssl-sys" +version = "0.9.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69df2d8dfc6ce3aaf44b40dec6f487d5a886516cf6879c49e98e0710f310a058" +dependencies = [ + "autocfg", + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "percent-encoding" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" + +[[package]] +name = "pkg-config" +version = "0.3.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c9b1041b4387893b91ee6746cddfc28516aff326a3519fb2adf820932c5e6cb" + +[[package]] +name = "ppv-lite86" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9f5105d4fdaab20335ca9565e106a5d9b82b6219b5ba735731124ac6711d23d" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", + "rand_hc", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" +dependencies = [ + "rand_core", +] + +[[package]] +name = "redox_syscall" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +dependencies = [ + "bitflags", +] + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + +[[package]] +name = "serde" +version = "1.0.130" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" + +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + +[[package]] +name = "structopt" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf9d950ef167e25e0bdb073cf1d68e9ad2795ac826f2f3f59647817cf23c0bfa" +dependencies = [ + "clap", + "lazy_static", + "structopt-derive", +] + +[[package]] +name = "structopt-derive" +version = "0.4.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "134d838a2c9943ac3125cf6df165eda53493451b719f3255b2a26b85f772d0ba" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "1.0.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5239bc68e0fef57495900cfea4e8dc75596d9a319d7e16b1e0a440d24e6fe0a0" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "tar" +version = "0.4.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f5515d3add52e0bbdcad7b83c388bb36ba7b754dda3b5f5bc2d38640cdba5c" +dependencies = [ + "filetime", + "libc", + "xattr", +] + +[[package]] +name = "tempfile" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" +dependencies = [ + "cfg-if", + "libc", + "rand", + "redox_syscall", + "remove_dir_all", + "winapi", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "tinyvec" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83b2a3d4d9091d0abd7eba4dc2710b1718583bd4d8992e2190720ea38f391f7" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" + +[[package]] +name = "toml" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" +dependencies = [ + "serde", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "246f4c42e67e7a4e3c6106ff716a5d067d4132a642840b242e357e468a2a0085" + +[[package]] +name = "unicode-normalization" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" + +[[package]] +name = "unicode-width" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "url" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" +dependencies = [ + "idna", + "matches", + "percent-encoding", +] + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + +[[package]] +name = "version_check" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "xattr" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c" +dependencies = [ + "libc", +] diff --git a/bin/node-template/README.md b/bin/node-template/README.md index cd977fac8449..e618b13c2a2f 100644 --- a/bin/node-template/README.md +++ b/bin/node-template/README.md @@ -1,10 +1,21 @@ # Substrate Node Template +[![Try on playground](https://img.shields.io/badge/Playground-Node_Template-brightgreen?logo=Parity%20Substrate)](https://playground.substrate.dev/?deploy=node-template) [![Matrix](https://img.shields.io/matrix/substrate-technical:matrix.org)](https://matrix.to/#/#substrate-technical:matrix.org) + A fresh FRAME-based [Substrate](https://www.substrate.io/) node, ready for hacking :rocket: ## Getting Started -Follow these steps to get started with the Node Template :hammer_and_wrench: +Follow the steps below to get started with the Node Template, or get it up and running right from +your browser in just a few clicks using [Playground](https://playground.substrate.dev/) +:hammer_and_wrench: + +### Using Nix + +Install [nix](https://nixos.org/) and optionally [direnv](https://github.com/direnv/direnv) and +[lorri](https://github.com/target/lorri) for a fully plug and play experience for setting up the +development environment. To get all the correct dependencies activate direnv `direnv allow` and +lorri `lorri shell`. ### Rust Setup @@ -62,10 +73,17 @@ Start the development chain with detailed logging: RUST_BACKTRACE=1 ./target/release/node-template -ldebug --dev ``` +### Connect with Polkadot-JS Apps Front-end + +Once the node template is running locally, you can connect it with **Polkadot-JS Apps** front-end +to interact with your chain. [Click +here](https://polkadot.js.org/apps/#/explorer?rpc=ws://localhost:9944) connecting the Apps to your +local node template. + ### Multi-Node Local Testnet -If you want to see the multi-node consensus algorithm in action, refer to -[our Start a Private Network tutorial](https://substrate.dev/docs/en/tutorials/start-a-private-network/). +If you want to see the multi-node consensus algorithm in action, refer to our +[Start a Private Network tutorial](https://substrate.dev/docs/en/tutorials/start-a-private-network/). ## Template Structure @@ -77,34 +95,34 @@ directories. A blockchain node is an application that allows users to participate in a blockchain network. Substrate-based blockchain nodes expose a number of capabilities: -- Networking: Substrate nodes use the [`libp2p`](https://libp2p.io/) networking stack to allow the - nodes in the network to communicate with one another. -- Consensus: Blockchains must have a way to come to - [consensus](https://substrate.dev/docs/en/knowledgebase/advanced/consensus) on the state of the - network. Substrate makes it possible to supply custom consensus engines and also ships with - several consensus mechanisms that have been built on top of - [Web3 Foundation research](https://research.web3.foundation/en/latest/polkadot/NPoS/index.html). -- RPC Server: A remote procedure call (RPC) server is used to interact with Substrate nodes. +- Networking: Substrate nodes use the [`libp2p`](https://libp2p.io/) networking stack to allow the + nodes in the network to communicate with one another. +- Consensus: Blockchains must have a way to come to + [consensus](https://substrate.dev/docs/en/knowledgebase/advanced/consensus) on the state of the + network. Substrate makes it possible to supply custom consensus engines and also ships with + several consensus mechanisms that have been built on top of + [Web3 Foundation research](https://research.web3.foundation/en/latest/polkadot/NPoS/index.html). +- RPC Server: A remote procedure call (RPC) server is used to interact with Substrate nodes. There are several files in the `node` directory - take special note of the following: -- [`chain_spec.rs`](./node/src/chain_spec.rs): A - [chain specification](https://substrate.dev/docs/en/knowledgebase/integrate/chain-spec) is a - source code file that defines a Substrate chain's initial (genesis) state. Chain specifications - are useful for development and testing, and critical when architecting the launch of a - production chain. Take note of the `development_config` and `testnet_genesis` functions, which - are used to define the genesis state for the local development chain configuration. These - functions identify some - [well-known accounts](https://substrate.dev/docs/en/knowledgebase/integrate/subkey#well-known-keys) - and use them to configure the blockchain's initial state. -- [`service.rs`](./node/src/service.rs): This file defines the node implementation. Take note of - the libraries that this file imports and the names of the functions it invokes. In particular, - there are references to consensus-related topics, such as the - [longest chain rule](https://substrate.dev/docs/en/knowledgebase/advanced/consensus#longest-chain-rule), - the [Aura](https://substrate.dev/docs/en/knowledgebase/advanced/consensus#aura) block authoring - mechanism and the - [GRANDPA](https://substrate.dev/docs/en/knowledgebase/advanced/consensus#grandpa) finality - gadget. +- [`chain_spec.rs`](./node/src/chain_spec.rs): A + [chain specification](https://substrate.dev/docs/en/knowledgebase/integrate/chain-spec) is a + source code file that defines a Substrate chain's initial (genesis) state. Chain specifications + are useful for development and testing, and critical when architecting the launch of a + production chain. Take note of the `development_config` and `testnet_genesis` functions, which + are used to define the genesis state for the local development chain configuration. These + functions identify some + [well-known accounts](https://substrate.dev/docs/en/knowledgebase/integrate/subkey#well-known-keys) + and use them to configure the blockchain's initial state. +- [`service.rs`](./node/src/service.rs): This file defines the node implementation. Take note of + the libraries that this file imports and the names of the functions it invokes. In particular, + there are references to consensus-related topics, such as the + [longest chain rule](https://substrate.dev/docs/en/knowledgebase/advanced/consensus#longest-chain-rule), + the [Aura](https://substrate.dev/docs/en/knowledgebase/advanced/consensus#aura) block authoring + mechanism and the + [GRANDPA](https://substrate.dev/docs/en/knowledgebase/advanced/consensus#grandpa) finality + gadget. After the node has been [built](#build), refer to the embedded documentation to learn more about the capabilities and configuration parameters that it exposes: @@ -130,13 +148,13 @@ create pallets and flexibly compose them to create blockchains that can address Review the [FRAME runtime implementation](./runtime/src/lib.rs) included in this template and note the following: -- This file configures several pallets to include in the runtime. Each pallet configuration is - defined by a code block that begins with `impl $PALLET_NAME::Config for Runtime`. -- The pallets are composed into a single runtime by way of the - [`construct_runtime!`](https://crates.parity.io/frame_support/macro.construct_runtime.html) - macro, which is part of the core - [FRAME Support](https://substrate.dev/docs/en/knowledgebase/runtime/frame#support-library) - library. +- This file configures several pallets to include in the runtime. Each pallet configuration is + defined by a code block that begins with `impl $PALLET_NAME::Config for Runtime`. +- The pallets are composed into a single runtime by way of the + [`construct_runtime!`](https://crates.parity.io/frame_support/macro.construct_runtime.html) + macro, which is part of the core + [FRAME Support](https://substrate.dev/docs/en/knowledgebase/runtime/frame#support-library) + library. ### Pallets @@ -146,17 +164,17 @@ template pallet that is [defined in the `pallets`](./pallets/template/src/lib.rs A FRAME pallet is compromised of a number of blockchain primitives: -- Storage: FRAME defines a rich set of powerful - [storage abstractions](https://substrate.dev/docs/en/knowledgebase/runtime/storage) that makes - it easy to use Substrate's efficient key-value database to manage the evolving state of a - blockchain. -- Dispatchables: FRAME pallets define special types of functions that can be invoked (dispatched) - from outside of the runtime in order to update its state. -- Events: Substrate uses [events](https://substrate.dev/docs/en/knowledgebase/runtime/events) to - notify users of important changes in the runtime. -- Errors: When a dispatchable fails, it returns an error. -- Config: The `Config` configuration interface is used to define the types and parameters upon - which a FRAME pallet depends. +- Storage: FRAME defines a rich set of powerful + [storage abstractions](https://substrate.dev/docs/en/knowledgebase/runtime/storage) that makes + it easy to use Substrate's efficient key-value database to manage the evolving state of a + blockchain. +- Dispatchables: FRAME pallets define special types of functions that can be invoked (dispatched) + from outside of the runtime in order to update its state. +- Events: Substrate uses [events](https://substrate.dev/docs/en/knowledgebase/runtime/events) to + notify users of important changes in the runtime. +- Errors: When a dispatchable fails, it returns an error. +- Config: The `Config` configuration interface is used to define the types and parameters upon + which a FRAME pallet depends. ### Run in Docker @@ -170,7 +188,8 @@ Then run the following command to start a single node development chain. ``` This command will firstly compile your code, and then start a local development network. You can -also replace the default command (`cargo build --release && ./target/release/node-template --dev --ws-external`) +also replace the default command +(`cargo build --release && ./target/release/node-template --dev --ws-external`) by appending your own. A few useful ones are as follow. ```bash diff --git a/bin/node-template/node/Cargo.toml b/bin/node-template/node/Cargo.toml index 04d70b338ac0..c8f2b52f112f 100644 --- a/bin/node-template/node/Cargo.toml +++ b/bin/node-template/node/Cargo.toml @@ -1,14 +1,14 @@ [package] name = "node-template" version = "3.0.0" -authors = ["Substrate DevHub "] description = "A fresh FRAME-based Substrate node, ready for hacking." +authors = ["Substrate DevHub "] +homepage = "https://substrate.dev" edition = "2018" license = "Unlicense" -build = "build.rs" -homepage = "https://substrate.dev" -repository = "https://github.com/substrate-developer-hub/substrate-node-template/" publish = false +repository = "https://github.com/substrate-developer-hub/substrate-node-template/" +build = "build.rs" [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] diff --git a/bin/node-template/pallets/template/Cargo.toml b/bin/node-template/pallets/template/Cargo.toml index b3eb747625b4..dccb37c6540c 100644 --- a/bin/node-template/pallets/template/Cargo.toml +++ b/bin/node-template/pallets/template/Cargo.toml @@ -1,14 +1,13 @@ [package] -authors = ['Substrate DevHub '] -edition = '2018' name = 'pallet-template' version = "3.0.0" -license = "Unlicense" -homepage = "https://substrate.dev" -repository = "https://github.com/substrate-developer-hub/substrate-node-template/" description = "FRAME pallet template for defining custom runtime logic." -readme = "README.md" +authors = ['Substrate DevHub '] +homepage = "https://substrate.dev" +edition = '2018' +license = "Unlicense" publish = false +repository = "https://github.com/substrate-developer-hub/substrate-node-template/" [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] diff --git a/bin/node-template/runtime/Cargo.toml b/bin/node-template/runtime/Cargo.toml index 47e67af2b9ae..081e458b18e0 100644 --- a/bin/node-template/runtime/Cargo.toml +++ b/bin/node-template/runtime/Cargo.toml @@ -1,12 +1,13 @@ [package] name = "node-template-runtime" version = "3.0.0" +description = 'A fresh FRAME-based Substrate runtime, ready for hacking.' authors = ["Substrate DevHub "] +homepage = "https://substrate.dev" edition = "2018" license = "Unlicense" -homepage = "https://substrate.dev" -repository = "https://github.com/substrate-developer-hub/substrate-node-template/" publish = false +repository = "https://github.com/substrate-developer-hub/substrate-node-template/" [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] diff --git a/bin/node-template/shell.nix b/bin/node-template/shell.nix new file mode 100644 index 000000000000..c08005c1630e --- /dev/null +++ b/bin/node-template/shell.nix @@ -0,0 +1,35 @@ +let + mozillaOverlay = + import (builtins.fetchGit { + url = "https://github.com/mozilla/nixpkgs-mozilla.git"; + rev = "57c8084c7ef41366993909c20491e359bbb90f54"; + }); + pinned = builtins.fetchGit { + # Descriptive name to make the store path easier to identify + url = "https://github.com/nixos/nixpkgs/"; + # Commit hash for nixos-unstable as of 2020-04-26 + # `git ls-remote https://github.com/nixos/nixpkgs nixos-unstable` + ref = "refs/heads/nixos-unstable"; + rev = "1fe6ed37fd9beb92afe90671c0c2a662a03463dd"; + }; + nixpkgs = import pinned { overlays = [ mozillaOverlay ]; }; + toolchain = with nixpkgs; (rustChannelOf { date = "2021-09-14"; channel = "nightly"; }); + rust-wasm = toolchain.rust.override { + targets = [ "wasm32-unknown-unknown" ]; + }; +in +with nixpkgs; pkgs.mkShell { + buildInputs = [ + clang + pkg-config + rust-wasm + ] ++ stdenv.lib.optionals stdenv.isDarwin [ + darwin.apple_sdk.frameworks.Security + ]; + + LIBCLANG_PATH = "${llvmPackages.libclang}/lib"; + PROTOC = "${protobuf}/bin/protoc"; + RUST_SRC_PATH = "${toolchain.rust-src}/lib/rustlib/src/rust/library/"; + ROCKSDB_LIB_DIR = "${rocksdb}/lib"; + +} From c775344b5a27ccdb5b1f17ef553a195411f7ae83 Mon Sep 17 00:00:00 2001 From: Dan Shields <35669742+NukeManDan@users.noreply.github.com> Date: Sat, 2 Oct 2021 13:01:07 -0600 Subject: [PATCH 017/695] rm `.maintain` lock (#9919) * rm maintain lock * ignore template gen lockfile --- .gitignore | 1 + .maintain/node-template-release/Cargo.lock | 616 --------------------- 2 files changed, 1 insertion(+), 616 deletions(-) delete mode 100644 .maintain/node-template-release/Cargo.lock diff --git a/.gitignore b/.gitignore index 0486a1a716e5..07aa596f6df2 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,4 @@ rls*.log .cargo-remote.toml *.bin *.iml +.maintain/node-template-release/Cargo.lock diff --git a/.maintain/node-template-release/Cargo.lock b/.maintain/node-template-release/Cargo.lock deleted file mode 100644 index ee562498c811..000000000000 --- a/.maintain/node-template-release/Cargo.lock +++ /dev/null @@ -1,616 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "ansi_term" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -dependencies = [ - "winapi", -] - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi", -] - -[[package]] -name = "autocfg" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "cc" -version = "1.0.70" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26a6ce4b6a484fa3edb70f7efa6fc430fd2b87285fe8b84304fd0936faa0dc0" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "clap" -version = "2.33.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" -dependencies = [ - "ansi_term", - "atty", - "bitflags", - "strsim", - "textwrap", - "unicode-width", - "vec_map", -] - -[[package]] -name = "crc32fast" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "curl-sys" -version = "0.4.48+curl-7.79.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a77a741f832116da66aeb126b4f19190ecf46144a74a9bde43c2086f38da0e" -dependencies = [ - "cc", - "libc", - "libz-sys", - "openssl-sys", - "pkg-config", - "vcpkg", - "winapi", -] - -[[package]] -name = "filetime" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "975ccf83d8d9d0d84682850a38c8169027be83368805971cc4f238c2b245bc98" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "winapi", -] - -[[package]] -name = "flate2" -version = "1.0.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" -dependencies = [ - "cfg-if", - "crc32fast", - "libc", - "miniz_oxide", -] - -[[package]] -name = "fs_extra" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394" - -[[package]] -name = "getrandom" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "git2" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7339329bfa14a00223244311560d11f8f489b453fb90092af97f267a6090ab0" -dependencies = [ - "bitflags", - "libc", - "libgit2-sys", - "log", - "openssl-probe", - "openssl-sys", - "url", -] - -[[package]] -name = "glob" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" - -[[package]] -name = "heck" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "idna" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" -dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.103" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6" - -[[package]] -name = "libgit2-sys" -version = "0.7.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48441cb35dc255da8ae72825689a95368bf510659ae1ad55dc4aa88cb1789bf1" -dependencies = [ - "cc", - "curl-sys", - "libc", - "libssh2-sys", - "libz-sys", - "openssl-sys", - "pkg-config", -] - -[[package]] -name = "libssh2-sys" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0186af0d8f171ae6b9c4c90ec51898bad5d08a2d5e470903a50d9ad8959cbee" -dependencies = [ - "cc", - "libc", - "libz-sys", - "openssl-sys", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "libz-sys" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de5435b8549c16d423ed0c03dbaafe57cf6c3344744f1242520d59c9d8ecec66" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "log" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "matches" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" - -[[package]] -name = "miniz_oxide" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" -dependencies = [ - "adler", - "autocfg", -] - -[[package]] -name = "node-template-release" -version = "3.0.0" -dependencies = [ - "flate2", - "fs_extra", - "git2", - "glob", - "structopt", - "tar", - "tempfile", - "toml", -] - -[[package]] -name = "openssl-probe" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a" - -[[package]] -name = "openssl-sys" -version = "0.9.67" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69df2d8dfc6ce3aaf44b40dec6f487d5a886516cf6879c49e98e0710f310a058" -dependencies = [ - "autocfg", - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "percent-encoding" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" - -[[package]] -name = "pkg-config" -version = "0.3.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c9b1041b4387893b91ee6746cddfc28516aff326a3519fb2adf820932c5e6cb" - -[[package]] -name = "ppv-lite86" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro2" -version = "1.0.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f5105d4fdaab20335ca9565e106a5d9b82b6219b5ba735731124ac6711d23d" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "quote" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", - "rand_hc", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rand_hc" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" -dependencies = [ - "rand_core", -] - -[[package]] -name = "redox_syscall" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" -dependencies = [ - "bitflags", -] - -[[package]] -name = "remove_dir_all" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi", -] - -[[package]] -name = "serde" -version = "1.0.130" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" - -[[package]] -name = "strsim" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" - -[[package]] -name = "structopt" -version = "0.3.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf9d950ef167e25e0bdb073cf1d68e9ad2795ac826f2f3f59647817cf23c0bfa" -dependencies = [ - "clap", - "lazy_static", - "structopt-derive", -] - -[[package]] -name = "structopt-derive" -version = "0.4.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134d838a2c9943ac3125cf6df165eda53493451b719f3255b2a26b85f772d0ba" -dependencies = [ - "heck", - "proc-macro-error", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "syn" -version = "1.0.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5239bc68e0fef57495900cfea4e8dc75596d9a319d7e16b1e0a440d24e6fe0a0" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "tar" -version = "0.4.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6f5515d3add52e0bbdcad7b83c388bb36ba7b754dda3b5f5bc2d38640cdba5c" -dependencies = [ - "filetime", - "libc", - "xattr", -] - -[[package]] -name = "tempfile" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" -dependencies = [ - "cfg-if", - "libc", - "rand", - "redox_syscall", - "remove_dir_all", - "winapi", -] - -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - -[[package]] -name = "tinyvec" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83b2a3d4d9091d0abd7eba4dc2710b1718583bd4d8992e2190720ea38f391f7" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" - -[[package]] -name = "toml" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" -dependencies = [ - "serde", -] - -[[package]] -name = "unicode-bidi" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "246f4c42e67e7a4e3c6106ff716a5d067d4132a642840b242e357e468a2a0085" - -[[package]] -name = "unicode-normalization" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "unicode-segmentation" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" - -[[package]] -name = "unicode-width" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" - -[[package]] -name = "unicode-xid" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" - -[[package]] -name = "url" -version = "1.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" -dependencies = [ - "idna", - "matches", - "percent-encoding", -] - -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - -[[package]] -name = "version_check" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" - -[[package]] -name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "xattr" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c" -dependencies = [ - "libc", -] From 9be8fdd36a70e19cd286bec00df740331b637546 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Sun, 3 Oct 2021 15:15:30 +0200 Subject: [PATCH 018/695] Ensure BeforeBestBlockBy voting rule accounts for base (#9920) * Ensure BeforeBestBlockBy voting rule accounts for base * fmt Co-authored-by: Andronik Ordian --- client/finality-grandpa/src/voting_rule.rs | 48 ++++++++++++++++++++-- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/client/finality-grandpa/src/voting_rule.rs b/client/finality-grandpa/src/voting_rule.rs index b974afe0d352..7c8d94d970f8 100644 --- a/client/finality-grandpa/src/voting_rule.rs +++ b/client/finality-grandpa/src/voting_rule.rs @@ -80,8 +80,14 @@ where } /// A custom voting rule that guarantees that our vote is always behind the best -/// block by at least N blocks. In the best case our vote is exactly N blocks -/// behind the best block. +/// block by at least N blocks, unless the base number is < N blocks behind the +/// best, in which case it votes for the base. +/// +/// In the best case our vote is exactly N blocks +/// behind the best block, but if there is a scenario where either +/// >34% of validators run without this rule or the fork-choice rule +/// can prioritize shorter chains over longer ones, the vote may be +/// closer to the best block than N. #[derive(Clone)] pub struct BeforeBestBlockBy(N); impl VotingRule for BeforeBestBlockBy> @@ -92,7 +98,7 @@ where fn restrict_vote( &self, backend: Arc, - _base: &Block::Header, + base: &Block::Header, best_target: &Block::Header, current_target: &Block::Header, ) -> VotingRuleResult { @@ -102,6 +108,12 @@ where return Box::pin(async { None }) } + // Constrain to the base number, if that's the minimal + // vote that can be placed. + if *base.number() + self.0 > *best_target.number() { + return Box::pin(std::future::ready(Some((base.hash(), *base.number())))) + } + // find the target number restricted by this rule let target_number = best_target.number().saturating_sub(self.0); @@ -393,4 +405,34 @@ mod tests { // only one of the rules is applied. assert_eq!(number, 150); } + + #[test] + fn before_best_by_has_cutoff_at_base() { + let rule = BeforeBestBlockBy(2); + + let mut client = Arc::new(TestClientBuilder::new().build()); + + for _ in 0..5 { + let block = client.new_block(Default::default()).unwrap().build().unwrap().block; + + futures::executor::block_on(client.import(BlockOrigin::Own, block)).unwrap(); + } + + let best = client.header(&BlockId::Hash(client.info().best_hash)).unwrap().unwrap(); + let best_number = best.number().clone(); + + for i in 0u32..5 { + let base = client.header(&BlockId::Number(i.into())).unwrap().unwrap(); + let (_, number) = futures::executor::block_on(rule.restrict_vote( + client.clone(), + &base, + &best, + &best, + )) + .unwrap(); + + let expected = std::cmp::max(best_number - 2, *base.number()); + assert_eq!(number, expected, "best = {}, lag = 2, base = {}", best_number, i); + } + } } From 5413a1f0d996874b97032fafd3284854df14b4d1 Mon Sep 17 00:00:00 2001 From: Squirrel Date: Sun, 3 Oct 2021 17:09:26 +0100 Subject: [PATCH 019/695] add clippy to CI (#9694) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Focus on correctness lints. This relies on a compiler patch that landed 8th July 2021. If people are using an earlier version of the compiler everything will still work unless they try and run clippy. Co-authored-by: Bastian Köcher Co-authored-by: Denis Pisarev --- .cargo/config.toml | 14 ++++++++++++++ .gitignore | 1 - .gitlab-ci.yml | 9 ++++++++- client/executor/src/wasm_runtime.rs | 2 +- client/network/src/block_request_handler.rs | 3 ++- client/network/src/state_request_handler.rs | 1 + frame/support/src/traits/metadata.rs | 17 ++++++++++------- 7 files changed, 36 insertions(+), 11 deletions(-) create mode 100644 .cargo/config.toml diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 000000000000..06328af71459 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,14 @@ +# +# An auto defined `clippy` feature was introduced, +# but it was found to clash with user defined features, +# so was renamed to `cargo-clippy`. +# +# If you want standard clippy run: +# RUSTFLAGS= cargo clippy +[target.'cfg(feature = "cargo-clippy")'] +rustflags = [ + "-Aclippy::all", + "-Dclippy::correctness", + "-Aclippy::if-same-then-else", + "-Aclippy::clone-double-ref" +] diff --git a/.gitignore b/.gitignore index 07aa596f6df2..f1103fdab93a 100644 --- a/.gitignore +++ b/.gitignore @@ -21,7 +21,6 @@ rls*.log .local **/hfuzz_target/ **/hfuzz_workspace/ -.cargo/ .cargo-remote.toml *.bin *.iml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index fa986923708d..0d150d96deed 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -311,7 +311,7 @@ cargo-deny: when: always paths: - deny.log - # FIXME: Temorarily allow to fail. + # FIXME: Temporarily allow to fail. allow_failure: true cargo-fmt: @@ -321,6 +321,13 @@ cargo-fmt: script: - cargo +nightly fmt --all -- --check +cargo-clippy: + stage: test + <<: *docker-env + <<: *test-refs + script: + - SKIP_WASM_BUILD=1 env -u RUSTFLAGS cargo +nightly clippy + cargo-check-benches: stage: test <<: *docker-env diff --git a/client/executor/src/wasm_runtime.rs b/client/executor/src/wasm_runtime.rs index b3a981d9e082..4c768b7f9c61 100644 --- a/client/executor/src/wasm_runtime.rs +++ b/client/executor/src/wasm_runtime.rs @@ -304,7 +304,7 @@ pub fn create_wasm_runtime_with_code( // // We drop the cache_path here to silence warnings that cache_path is not used if // compiling without the `wasmtime` flag. - drop(cache_path); + let _ = cache_path; sc_executor_wasmi::create_runtime( blob, diff --git a/client/network/src/block_request_handler.rs b/client/network/src/block_request_handler.rs index 9411ca71fd00..3ea7833970d9 100644 --- a/client/network/src/block_request_handler.rs +++ b/client/network/src/block_request_handler.rs @@ -85,13 +85,14 @@ struct SeenRequestsKey { support_multiple_justifications: bool, } +#[allow(clippy::derive_hash_xor_eq)] impl Hash for SeenRequestsKey { fn hash(&self, state: &mut H) { self.peer.hash(state); self.max_blocks.hash(state); self.direction.hash(state); self.attributes.hash(state); - + self.support_multiple_justifications.hash(state); match self.from { BlockId::Hash(h) => h.hash(state), BlockId::Number(n) => n.hash(state), diff --git a/client/network/src/state_request_handler.rs b/client/network/src/state_request_handler.rs index b4e5320ebfda..d2e58ce95519 100644 --- a/client/network/src/state_request_handler.rs +++ b/client/network/src/state_request_handler.rs @@ -78,6 +78,7 @@ struct SeenRequestsKey { start: Vec, } +#[allow(clippy::derive_hash_xor_eq)] impl Hash for SeenRequestsKey { fn hash(&self, state: &mut H) { self.peer.hash(state); diff --git a/frame/support/src/traits/metadata.rs b/frame/support/src/traits/metadata.rs index 14b7e6d7355e..e60cf8be8a41 100644 --- a/frame/support/src/traits/metadata.rs +++ b/frame/support/src/traits/metadata.rs @@ -78,7 +78,7 @@ pub trait GetCallMetadata { } /// The version of a crate. -#[derive(RuntimeDebug, Eq, PartialEq, Encode, Decode, Ord, Clone, Copy, Default)] +#[derive(RuntimeDebug, Eq, PartialEq, Encode, Decode, Clone, Copy, Default)] pub struct CrateVersion { /// The major version of the crate. pub major: u16, @@ -94,14 +94,17 @@ impl CrateVersion { } } -impl sp_std::cmp::PartialOrd for CrateVersion { - fn partial_cmp(&self, other: &Self) -> Option { - let res = self - .major +impl sp_std::cmp::Ord for CrateVersion { + fn cmp(&self, other: &Self) -> sp_std::cmp::Ordering { + self.major .cmp(&other.major) - .then_with(|| self.minor.cmp(&other.minor).then_with(|| self.patch.cmp(&other.patch))); + .then_with(|| self.minor.cmp(&other.minor).then_with(|| self.patch.cmp(&other.patch))) + } +} - Some(res) +impl sp_std::cmp::PartialOrd for CrateVersion { + fn partial_cmp(&self, other: &Self) -> Option { + Some(::cmp(&self, other)) } } From ca90ea736c049798868055e2a6ad9ccdd737da23 Mon Sep 17 00:00:00 2001 From: Jaco Date: Mon, 4 Oct 2021 14:56:06 +0300 Subject: [PATCH 020/695] Small quoting comment fix (#9927) Tiny quotes fix that snuck in lately (something I picked up elsewhere in document generation) --- frame/im-online/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frame/im-online/src/lib.rs b/frame/im-online/src/lib.rs index 2fcaed1820ff..559c5edcf4d1 100644 --- a/frame/im-online/src/lib.rs +++ b/frame/im-online/src/lib.rs @@ -412,7 +412,7 @@ pub mod pallet { pub(crate) type Keys = StorageValue<_, WeakBoundedVec, ValueQuery>; - /// For each session index, we keep a mapping of 'SessionIndex` and `AuthIndex` to + /// For each session index, we keep a mapping of `SessionIndex` and `AuthIndex` to /// `WrapperOpaque`. #[pallet::storage] #[pallet::getter(fn received_heartbeats)] From 6c0c9c9aaaa3ebe4ccc4dfb3d61f721723885ac7 Mon Sep 17 00:00:00 2001 From: Koute Date: Mon, 4 Oct 2021 22:28:51 +0900 Subject: [PATCH 021/695] Do not propagate host RUSTFLAGS when checking for WASM toolchain (#9926) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Do not propagate host RUSTFLAGS when checking for WASM toolchain * Update utils/wasm-builder/src/prerequisites.rs * Update utils/wasm-builder/src/prerequisites.rs Co-authored-by: Bastian Köcher --- utils/wasm-builder/src/prerequisites.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/utils/wasm-builder/src/prerequisites.rs b/utils/wasm-builder/src/prerequisites.rs index 0dad8b781ae5..c45f7933a1de 100644 --- a/utils/wasm-builder/src/prerequisites.rs +++ b/utils/wasm-builder/src/prerequisites.rs @@ -138,6 +138,13 @@ fn check_wasm_toolchain_installed( build_cmd.env_remove("CARGO_TARGET_DIR"); run_cmd.env_remove("CARGO_TARGET_DIR"); + // Make sure the host's flags aren't used here, e.g. if an alternative linker is specified + // in the RUSTFLAGS then the check we do here will break unless we clear these. + build_cmd.env_remove("CARGO_ENCODED_RUSTFLAGS"); + run_cmd.env_remove("CARGO_ENCODED_RUSTFLAGS"); + build_cmd.env_remove("RUSTFLAGS"); + run_cmd.env_remove("RUSTFLAGS"); + build_cmd.output().map_err(|_| err_msg.clone()).and_then(|s| { if s.status.success() { let version = run_cmd.output().ok().and_then(|o| String::from_utf8(o.stdout).ok()); From a30e1b2206b0ff23ebf21b24cad8595342e96b72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 4 Oct 2021 16:25:18 +0200 Subject: [PATCH 022/695] Rework Transaction Priority calculation (#9834) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add transaction validity docs. * Re-work priority calculation. * Fix tests. * Update frame/transaction-payment/src/lib.rs Co-authored-by: Alexander Popiak * cargo +nightly fmt --all * Fix an obvious mistake :) * Re-work again. * Fix test. * cargo +nightly fmt --all * Make VirtualTip dependent on the transaction size. * cargo +nightly fmt --all * Update frame/transaction-payment/src/lib.rs Co-authored-by: Alexander Popiak * Fix compilation. * Update bin/node/runtime/src/lib.rs Co-authored-by: Bastian Köcher Co-authored-by: Alexander Popiak Co-authored-by: Bastian Köcher --- Cargo.lock | 8 +- bin/node-template/runtime/src/lib.rs | 2 + bin/node/runtime/src/lib.rs | 2 + frame/balances/src/tests_composite.rs | 2 + frame/balances/src/tests_local.rs | 2 + frame/balances/src/tests_reentrancy.rs | 2 + frame/executive/src/lib.rs | 6 +- frame/support/src/weights.rs | 24 --- frame/system/src/extensions/check_genesis.rs | 5 + .../system/src/extensions/check_mortality.rs | 4 + frame/system/src/extensions/check_nonce.rs | 7 +- .../src/extensions/check_spec_version.rs | 5 + .../system/src/extensions/check_tx_version.rs | 5 + frame/system/src/extensions/check_weight.rs | 63 +----- frame/transaction-payment/src/lib.rs | 193 ++++++++++++++++-- 15 files changed, 225 insertions(+), 105 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0e3f3399dbf6..5e8932fd5652 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2473,9 +2473,9 @@ dependencies = [ [[package]] name = "git2" -version = "0.13.21" +version = "0.13.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "659cd14835e75b64d9dba5b660463506763cf0aa6cb640aeeb0e98d841093490" +checksum = "9c1cbbfc9a1996c6af82c2b4caf828d2c653af4fcdbb0e5674cc966eee5a4197" dependencies = [ "bitflags", "libc", @@ -3294,9 +3294,9 @@ checksum = "789da6d93f1b866ffe175afc5322a4d76c038605a1c3319bb57b06967ca98a36" [[package]] name = "libgit2-sys" -version = "0.12.22+1.1.0" +version = "0.12.23+1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89c53ac117c44f7042ad8d8f5681378dfbc6010e49ec2c0d1f11dfedc7a4a1c3" +checksum = "29730a445bae719db3107078b46808cc45a5b7a6bae3f31272923af969453356" dependencies = [ "cc", "libc", diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index ca6e6b1822d4..5d3ea603265f 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -258,11 +258,13 @@ impl pallet_balances::Config for Runtime { parameter_types! { pub const TransactionByteFee: Balance = 1; + pub OperationalFeeMultiplier: u8 = 5; } impl pallet_transaction_payment::Config for Runtime { type OnChargeTransaction = CurrencyAdapter; type TransactionByteFee = TransactionByteFee; + type OperationalFeeMultiplier = OperationalFeeMultiplier; type WeightToFee = IdentityFee; type FeeMultiplierUpdate = (); } diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 881641e15136..f2d3175f094d 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -413,6 +413,7 @@ impl pallet_balances::Config for Runtime { parameter_types! { pub const TransactionByteFee: Balance = 10 * MILLICENTS; + pub const OperationalFeeMultiplier: u8 = 5; pub const TargetBlockFullness: Perquintill = Perquintill::from_percent(25); pub AdjustmentVariable: Multiplier = Multiplier::saturating_from_rational(1, 100_000); pub MinimumMultiplier: Multiplier = Multiplier::saturating_from_rational(1, 1_000_000_000u128); @@ -421,6 +422,7 @@ parameter_types! { impl pallet_transaction_payment::Config for Runtime { type OnChargeTransaction = CurrencyAdapter; type TransactionByteFee = TransactionByteFee; + type OperationalFeeMultiplier = OperationalFeeMultiplier; type WeightToFee = IdentityFee; type FeeMultiplierUpdate = TargetedFeeAdjustment; diff --git a/frame/balances/src/tests_composite.rs b/frame/balances/src/tests_composite.rs index f6faebed3931..60feedb326d8 100644 --- a/frame/balances/src/tests_composite.rs +++ b/frame/balances/src/tests_composite.rs @@ -76,10 +76,12 @@ impl frame_system::Config for Test { } parameter_types! { pub const TransactionByteFee: u64 = 1; + pub const OperationalFeeMultiplier: u8 = 5; } impl pallet_transaction_payment::Config for Test { type OnChargeTransaction = CurrencyAdapter, ()>; type TransactionByteFee = TransactionByteFee; + type OperationalFeeMultiplier = OperationalFeeMultiplier; type WeightToFee = IdentityFee; type FeeMultiplierUpdate = (); } diff --git a/frame/balances/src/tests_local.rs b/frame/balances/src/tests_local.rs index d8c07aa9c42e..1d758ce4e980 100644 --- a/frame/balances/src/tests_local.rs +++ b/frame/balances/src/tests_local.rs @@ -78,10 +78,12 @@ impl frame_system::Config for Test { } parameter_types! { pub const TransactionByteFee: u64 = 1; + pub const OperationalFeeMultiplier: u8 = 5; } impl pallet_transaction_payment::Config for Test { type OnChargeTransaction = CurrencyAdapter, ()>; type TransactionByteFee = TransactionByteFee; + type OperationalFeeMultiplier = OperationalFeeMultiplier; type WeightToFee = IdentityFee; type FeeMultiplierUpdate = (); } diff --git a/frame/balances/src/tests_reentrancy.rs b/frame/balances/src/tests_reentrancy.rs index 9c7ba3e1ec82..25b8fb34f20b 100644 --- a/frame/balances/src/tests_reentrancy.rs +++ b/frame/balances/src/tests_reentrancy.rs @@ -80,10 +80,12 @@ impl frame_system::Config for Test { } parameter_types! { pub const TransactionByteFee: u64 = 1; + pub const OperationalFeeMultiplier: u8 = 5; } impl pallet_transaction_payment::Config for Test { type OnChargeTransaction = CurrencyAdapter, ()>; type TransactionByteFee = TransactionByteFee; + type OperationalFeeMultiplier = OperationalFeeMultiplier; type WeightToFee = IdentityFee; type FeeMultiplierUpdate = (); } diff --git a/frame/executive/src/lib.rs b/frame/executive/src/lib.rs index 41f679909e6f..b1bdf357ec07 100644 --- a/frame/executive/src/lib.rs +++ b/frame/executive/src/lib.rs @@ -800,10 +800,12 @@ mod tests { parameter_types! { pub const TransactionByteFee: Balance = 0; + pub const OperationalFeeMultiplier: u8 = 5; } impl pallet_transaction_payment::Config for Runtime { type OnChargeTransaction = CurrencyAdapter; type TransactionByteFee = TransactionByteFee; + type OperationalFeeMultiplier = OperationalFeeMultiplier; type WeightToFee = IdentityFee; type FeeMultiplierUpdate = (); } @@ -1110,8 +1112,6 @@ mod tests { let invalid = TestXt::new(Call::Custom(custom::Call::unallowed_unsigned {}), None); let mut t = new_test_ext(1); - let mut default_with_prio_3 = ValidTransaction::default(); - default_with_prio_3.priority = 3; t.execute_with(|| { assert_eq!( Executive::validate_transaction( @@ -1119,7 +1119,7 @@ mod tests { valid.clone(), Default::default(), ), - Ok(default_with_prio_3), + Ok(ValidTransaction::default()), ); assert_eq!( Executive::validate_transaction( diff --git a/frame/support/src/weights.rs b/frame/support/src/weights.rs index 115470a9bf03..ec5f37823ad4 100644 --- a/frame/support/src/weights.rs +++ b/frame/support/src/weights.rs @@ -287,30 +287,6 @@ impl<'a> OneOrMany for &'a [DispatchClass] { } } -/// Primitives related to priority management of Frame. -pub mod priority { - /// The starting point of all Operational transactions. 3/4 of u64::MAX. - pub const LIMIT: u64 = 13_835_058_055_282_163_711_u64; - - /// Wrapper for priority of different dispatch classes. - /// - /// This only makes sure that any value created for the operational dispatch class is - /// incremented by [`LIMIT`]. - pub enum FrameTransactionPriority { - Normal(u64), - Operational(u64), - } - - impl From for u64 { - fn from(priority: FrameTransactionPriority) -> Self { - match priority { - FrameTransactionPriority::Normal(inner) => inner, - FrameTransactionPriority::Operational(inner) => inner.saturating_add(LIMIT), - } - } - } -} - /// A bundle of static information collected from the `#[weight = $x]` attributes. #[derive(Clone, Copy, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode, TypeInfo)] pub struct DispatchInfo { diff --git a/frame/system/src/extensions/check_genesis.rs b/frame/system/src/extensions/check_genesis.rs index 6f409d5d3d4a..9c5c890ee609 100644 --- a/frame/system/src/extensions/check_genesis.rs +++ b/frame/system/src/extensions/check_genesis.rs @@ -24,6 +24,11 @@ use sp_runtime::{ }; /// Genesis hash check to provide replay protection between different networks. +/// +/// # Transaction Validity +/// +/// Note that while a transaction with invalid `genesis_hash` will fail to be decoded, +/// the extension does not affect any other fields of `TransactionValidity` directly. #[derive(Encode, Decode, Clone, Eq, PartialEq, TypeInfo)] #[scale_info(skip_type_params(T))] pub struct CheckGenesis(sp_std::marker::PhantomData); diff --git a/frame/system/src/extensions/check_mortality.rs b/frame/system/src/extensions/check_mortality.rs index 69cca765efea..941f28dc6fc6 100644 --- a/frame/system/src/extensions/check_mortality.rs +++ b/frame/system/src/extensions/check_mortality.rs @@ -27,6 +27,10 @@ use sp_runtime::{ }; /// Check for transaction mortality. +/// +/// # Transaction Validity +/// +/// The extension affects `longevity` of the transaction according to the [`Era`] definition. #[derive(Encode, Decode, Clone, Eq, PartialEq, TypeInfo)] #[scale_info(skip_type_params(T))] pub struct CheckMortality(Era, sp_std::marker::PhantomData); diff --git a/frame/system/src/extensions/check_nonce.rs b/frame/system/src/extensions/check_nonce.rs index 74be83398421..3c6f9a1b4dbd 100644 --- a/frame/system/src/extensions/check_nonce.rs +++ b/frame/system/src/extensions/check_nonce.rs @@ -30,8 +30,11 @@ use sp_std::vec; /// Nonce check and increment to give replay protection for transactions. /// -/// Note that this does not set any priority by default. Make sure that AT LEAST one of the signed -/// extension sets some kind of priority upon validating transactions. +/// # Transaction Validity +/// +/// This extension affects `requires` and `provides` tags of validity, but DOES NOT +/// set the `priority` field. Make sure that AT LEAST one of the signed extension sets +/// some kind of priority upon validating transactions. #[derive(Encode, Decode, Clone, Eq, PartialEq, TypeInfo)] #[scale_info(skip_type_params(T))] pub struct CheckNonce(#[codec(compact)] pub T::Index); diff --git a/frame/system/src/extensions/check_spec_version.rs b/frame/system/src/extensions/check_spec_version.rs index 0217aefae6b9..688abe99763a 100644 --- a/frame/system/src/extensions/check_spec_version.rs +++ b/frame/system/src/extensions/check_spec_version.rs @@ -21,6 +21,11 @@ use scale_info::TypeInfo; use sp_runtime::{traits::SignedExtension, transaction_validity::TransactionValidityError}; /// Ensure the runtime version registered in the transaction is the same as at present. +/// +/// # Transaction Validity +/// +/// The transaction with incorrect `spec_version` are considered invalid. The validity +/// is not affected in any other way. #[derive(Encode, Decode, Clone, Eq, PartialEq, TypeInfo)] #[scale_info(skip_type_params(T))] pub struct CheckSpecVersion(sp_std::marker::PhantomData); diff --git a/frame/system/src/extensions/check_tx_version.rs b/frame/system/src/extensions/check_tx_version.rs index 9418d3ff5d93..f6bb53e1cba3 100644 --- a/frame/system/src/extensions/check_tx_version.rs +++ b/frame/system/src/extensions/check_tx_version.rs @@ -21,6 +21,11 @@ use scale_info::TypeInfo; use sp_runtime::{traits::SignedExtension, transaction_validity::TransactionValidityError}; /// Ensure the transaction version registered in the transaction is the same as at present. +/// +/// # Transaction Validity +/// +/// The transaction with incorrect `transaction_version` are considered invalid. The validity +/// is not affected in any other way. #[derive(Encode, Decode, Clone, Eq, PartialEq, TypeInfo)] #[scale_info(skip_type_params(T))] pub struct CheckTxVersion(sp_std::marker::PhantomData); diff --git a/frame/system/src/extensions/check_weight.rs b/frame/system/src/extensions/check_weight.rs index 92dc7382fa2d..ca885accd660 100644 --- a/frame/system/src/extensions/check_weight.rs +++ b/frame/system/src/extensions/check_weight.rs @@ -19,19 +19,21 @@ use crate::{limits::BlockWeights, Config, Pallet}; use codec::{Decode, Encode}; use frame_support::{ traits::Get, - weights::{priority::FrameTransactionPriority, DispatchClass, DispatchInfo, PostDispatchInfo}, + weights::{DispatchClass, DispatchInfo, PostDispatchInfo}, }; use scale_info::TypeInfo; use sp_runtime::{ traits::{DispatchInfoOf, Dispatchable, PostDispatchInfoOf, SignedExtension}, - transaction_validity::{ - InvalidTransaction, TransactionPriority, TransactionValidity, TransactionValidityError, - ValidTransaction, - }, + transaction_validity::{InvalidTransaction, TransactionValidity, TransactionValidityError}, DispatchResult, }; /// Block resource (weight) limit check. +/// +/// # Transaction Validity +/// +/// This extension does not influence any fields of `TransactionValidity` in case the +/// transaction is valid. #[derive(Encode, Decode, Clone, Eq, PartialEq, Default, TypeInfo)] #[scale_info(skip_type_params(T))] pub struct CheckWeight(sp_std::marker::PhantomData); @@ -81,23 +83,6 @@ where } } - /// Get the priority of an extrinsic denoted by `info`. - /// - /// Operational transaction will be given a fixed initial amount to be fairly distinguished from - /// the normal ones. - fn get_priority(info: &DispatchInfoOf) -> TransactionPriority { - match info.class { - // Normal transaction. - DispatchClass::Normal => FrameTransactionPriority::Normal(info.weight.into()).into(), - // Don't use up the whole priority space, to allow things like `tip` to be taken into - // account as well. - DispatchClass::Operational => - FrameTransactionPriority::Operational(info.weight.into()).into(), - // Mandatory extrinsics are only for inherents; never transactions. - DispatchClass::Mandatory => TransactionPriority::min_value(), - } - } - /// Creates new `SignedExtension` to check weight of the extrinsic. pub fn new() -> Self { Self(Default::default()) @@ -130,7 +115,7 @@ where // consumption from causing false negatives. Self::check_extrinsic_weight(info)?; - Ok(ValidTransaction { priority: Self::get_priority(info), ..Default::default() }) + Ok(Default::default()) } } @@ -368,13 +353,7 @@ mod tests { }; let len = 0_usize; - assert_eq!( - CheckWeight::::do_validate(&okay, len), - Ok(ValidTransaction { - priority: CheckWeight::::get_priority(&okay), - ..Default::default() - }) - ); + assert_eq!(CheckWeight::::do_validate(&okay, len), Ok(Default::default())); assert_err!( CheckWeight::::do_validate(&max, len), InvalidTransaction::ExhaustsResources @@ -506,30 +485,6 @@ mod tests { }) } - #[test] - fn signed_ext_check_weight_works() { - new_test_ext().execute_with(|| { - let normal = - DispatchInfo { weight: 100, class: DispatchClass::Normal, pays_fee: Pays::Yes }; - let op = DispatchInfo { - weight: 100, - class: DispatchClass::Operational, - pays_fee: Pays::Yes, - }; - let len = 0_usize; - - let priority = CheckWeight::(PhantomData) - .validate(&1, CALL, &normal, len) - .unwrap() - .priority; - assert_eq!(priority, 100); - - let priority = - CheckWeight::(PhantomData).validate(&1, CALL, &op, len).unwrap().priority; - assert_eq!(priority, frame_support::weights::priority::LIMIT + 100); - }) - } - #[test] fn signed_ext_check_weight_block_size_works() { new_test_ext().execute_with(|| { diff --git a/frame/transaction-payment/src/lib.rs b/frame/transaction-payment/src/lib.rs index 11dbcc010f67..28200bee7054 100644 --- a/frame/transaction-payment/src/lib.rs +++ b/frame/transaction-payment/src/lib.rs @@ -264,6 +264,30 @@ pub mod pallet { #[pallet::constant] type TransactionByteFee: Get>; + /// A fee mulitplier for `Operational` extrinsics to compute "virtual tip" to boost their + /// `priority` + /// + /// This value is multipled by the `final_fee` to obtain a "virtual tip" that is later + /// added to a tip component in regular `priority` calculations. + /// It means that a `Normal` transaction can front-run a similarly-sized `Operational` + /// extrinsic (with no tip), by including a tip value greater than the virtual tip. + /// + /// ```rust,ignore + /// // For `Normal` + /// let priority = priority_calc(tip); + /// + /// // For `Operational` + /// let virtual_tip = (inclusion_fee + tip) * OperationalFeeMultiplier; + /// let priority = priority_calc(tip + virtual_tip); + /// ``` + /// + /// Note that since we use `final_fee` the multiplier applies also to the regular `tip` + /// sent with the transaction. So, not only does the transaction get a priority bump based + /// on the `inclusion_fee`, but we also amplify the impact of tips applied to `Operational` + /// transactions. + #[pallet::constant] + type OperationalFeeMultiplier: Get; + /// Convert a weight value into a deductible fee based on the currency type. type WeightToFee: WeightToFeePolynomial>; @@ -525,6 +549,14 @@ where /// Require the transactor pay for themselves and maybe include a tip to gain additional priority /// in the queue. +/// +/// # Transaction Validity +/// +/// This extension sets the `priority` field of `TransactionValidity` depending on the amount +/// of tip being paid per weight unit. +/// +/// Operational transactions will receive an additional priority bump, so that they are normally +/// considered before regular transactions. #[derive(Encode, Decode, Clone, Eq, PartialEq, TypeInfo)] #[scale_info(skip_type_params(T))] pub struct ChargeTransactionPayment(#[codec(compact)] BalanceOf); @@ -566,27 +598,73 @@ where .map(|i| (fee, i)) } - /// Get an appropriate priority for a transaction with the given length and info. + /// Get an appropriate priority for a transaction with the given `DispatchInfo`, encoded length + /// and user-included tip. /// - /// This will try and optimise the `fee/weight` `fee/length`, whichever is consuming more of the - /// maximum corresponding limit. + /// The priority is based on the amount of `tip` the user is willing to pay per unit of either + /// `weight` or `length`, depending which one is more limitting. For `Operational` extrinsics + /// we add a "virtual tip" to the calculations. /// - /// For example, if a transaction consumed 1/4th of the block length and half of the weight, its - /// final priority is `fee * min(2, 4) = fee * 2`. If it consumed `1/4th` of the block length - /// and the entire block weight `(1/1)`, its priority is `fee * min(1, 4) = fee * 1`. This means - /// that the transaction which consumes more resources (either length or weight) with the same - /// `fee` ends up having lower priority. - fn get_priority( - len: usize, + /// The formula should simply be `tip / bounded_{weight|length}`, but since we are using + /// integer division, we have no guarantees it's going to give results in any reasonable + /// range (might simply end up being zero). Hence we use a scaling factor: + /// `tip * (max_block_{weight|length} / bounded_{weight|length})`, since given current + /// state of-the-art blockchains, number of per-block transactions is expected to be in a + /// range reasonable enough to not saturate the `Balance` type while multiplying by the tip. + pub fn get_priority( info: &DispatchInfoOf, + len: usize, + tip: BalanceOf, final_fee: BalanceOf, ) -> TransactionPriority { - let weight_saturation = T::BlockWeights::get().max_block / info.weight.max(1); - let max_block_length = *T::BlockLength::get().max.get(DispatchClass::Normal); - let len_saturation = max_block_length as u64 / (len as u64).max(1); - let coefficient: BalanceOf = - weight_saturation.min(len_saturation).saturated_into::>(); - final_fee.saturating_mul(coefficient).saturated_into::() + // Calculate how many such extrinsics we could fit into an empty block and take + // the limitting factor. + let max_block_weight = T::BlockWeights::get().max_block; + let max_block_length = *T::BlockLength::get().max.get(info.class) as u64; + + let bounded_weight = info.weight.max(1).min(max_block_weight); + let bounded_length = (len as u64).max(1).min(max_block_length); + + let max_tx_per_block_weight = max_block_weight / bounded_weight; + let max_tx_per_block_length = max_block_length / bounded_length; + // Given our current knowledge this value is going to be in a reasonable range - i.e. + // less than 10^9 (2^30), so multiplying by the `tip` value is unlikely to overflow the + // balance type. We still use saturating ops obviously, but the point is to end up with some + // `priority` distribution instead of having all transactions saturate the priority. + let max_tx_per_block = max_tx_per_block_length + .min(max_tx_per_block_weight) + .saturated_into::>(); + let max_reward = |val: BalanceOf| val.saturating_mul(max_tx_per_block); + + // To distribute no-tip transactions a little bit, we set the minimal tip as `1`. + // This means that given two transactions without a tip, smaller one will be preferred. + let tip = tip.max(1.saturated_into()); + let scaled_tip = max_reward(tip); + + match info.class { + DispatchClass::Normal => { + // For normal class we simply take the `tip_per_weight`. + scaled_tip + }, + DispatchClass::Mandatory => { + // Mandatory extrinsics should be prohibited (e.g. by the [`CheckWeight`] + // extensions), but just to be safe let's return the same priority as `Normal` here. + scaled_tip + }, + DispatchClass::Operational => { + // A "virtual tip" value added to an `Operational` extrinsic. + // This value should be kept high enough to allow `Operational` extrinsics + // to get in even during congestion period, but at the same time low + // enough to prevent a possible spam attack by sending invalid operational + // extrinsics which push away regular transactions from the pool. + let fee_multiplier = T::OperationalFeeMultiplier::get().saturated_into(); + let virtual_tip = final_fee.saturating_mul(fee_multiplier); + let scaled_virtual_tip = max_reward(virtual_tip); + + scaled_tip.saturating_add(scaled_virtual_tip) + }, + } + .saturated_into::() } } @@ -629,8 +707,12 @@ where info: &DispatchInfoOf, len: usize, ) -> TransactionValidity { - let (fee, _) = self.withdraw_fee(who, call, info, len)?; - Ok(ValidTransaction { priority: Self::get_priority(len, info, fee), ..Default::default() }) + let (final_fee, _) = self.withdraw_fee(who, call, info, len)?; + let tip = self.0; + Ok(ValidTransaction { + priority: Self::get_priority(info, len, tip, final_fee), + ..Default::default() + }) } fn pre_dispatch( @@ -743,6 +825,7 @@ mod tests { pub const BlockHashCount: u64 = 250; pub static TransactionByteFee: u64 = 1; pub static WeightToFee: u64 = 1; + pub static OperationalFeeMultiplier: u8 = 5; } impl frame_system::Config for Runtime { @@ -822,6 +905,7 @@ mod tests { impl Config for Runtime { type OnChargeTransaction = CurrencyAdapter; type TransactionByteFee = TransactionByteFee; + type OperationalFeeMultiplier = OperationalFeeMultiplier; type WeightToFee = WeightToFee; type FeeMultiplierUpdate = (); } @@ -1335,6 +1419,79 @@ mod tests { }); } + #[test] + fn should_alter_operational_priority() { + let tip = 5; + let len = 10; + + ExtBuilder::default().balance_factor(100).build().execute_with(|| { + let normal = + DispatchInfo { weight: 100, class: DispatchClass::Normal, pays_fee: Pays::Yes }; + let priority = ChargeTransactionPayment::(tip) + .validate(&2, CALL, &normal, len) + .unwrap() + .priority; + + assert_eq!(priority, 50); + + let priority = ChargeTransactionPayment::(2 * tip) + .validate(&2, CALL, &normal, len) + .unwrap() + .priority; + + assert_eq!(priority, 100); + }); + + ExtBuilder::default().balance_factor(100).build().execute_with(|| { + let op = DispatchInfo { + weight: 100, + class: DispatchClass::Operational, + pays_fee: Pays::Yes, + }; + let priority = ChargeTransactionPayment::(tip) + .validate(&2, CALL, &op, len) + .unwrap() + .priority; + assert_eq!(priority, 5800); + + let priority = ChargeTransactionPayment::(2 * tip) + .validate(&2, CALL, &op, len) + .unwrap() + .priority; + assert_eq!(priority, 6100); + }); + } + + #[test] + fn no_tip_has_some_priority() { + let tip = 0; + let len = 10; + + ExtBuilder::default().balance_factor(100).build().execute_with(|| { + let normal = + DispatchInfo { weight: 100, class: DispatchClass::Normal, pays_fee: Pays::Yes }; + let priority = ChargeTransactionPayment::(tip) + .validate(&2, CALL, &normal, len) + .unwrap() + .priority; + + assert_eq!(priority, 10); + }); + + ExtBuilder::default().balance_factor(100).build().execute_with(|| { + let op = DispatchInfo { + weight: 100, + class: DispatchClass::Operational, + pays_fee: Pays::Yes, + }; + let priority = ChargeTransactionPayment::(tip) + .validate(&2, CALL, &op, len) + .unwrap() + .priority; + assert_eq!(priority, 5510); + }); + } + #[test] fn post_info_can_change_pays_fee() { ExtBuilder::default() From 125092f355c11166c57deeef0e1841301a351889 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 4 Oct 2021 16:30:46 +0200 Subject: [PATCH 023/695] Introduce block authorship soft deadline (#9663) * Soft limit. * Add soft deadline tests. * cargo +nightly fmt --all * Fix sc-service test. * Improving tests --- Cargo.lock | 1 + .../basic-authorship/src/basic_authorship.rs | 186 +++++++++++++++++- client/service/test/Cargo.toml | 1 + client/service/test/src/client/mod.rs | 41 ++-- primitives/keyring/src/sr25519.rs | 11 ++ test-utils/runtime/client/src/lib.rs | 16 +- 6 files changed, 231 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5e8932fd5652..622b52591b90 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8449,6 +8449,7 @@ version = "2.0.0" dependencies = [ "fdlimit", "futures 0.3.16", + "hex", "hex-literal", "log 0.4.14", "parity-scale-codec", diff --git a/client/basic-authorship/src/basic_authorship.rs b/client/basic-authorship/src/basic_authorship.rs index bbee60ae98dc..0055254b6709 100644 --- a/client/basic-authorship/src/basic_authorship.rs +++ b/client/basic-authorship/src/basic_authorship.rs @@ -286,6 +286,11 @@ where } } +/// If the block is full we will attempt to push at most +/// this number of transactions before quitting for real. +/// It allows us to increase block utilization. +const MAX_SKIPPED_TRANSACTIONS: usize = 8; + impl Proposer where A: TransactionPool, @@ -309,11 +314,6 @@ where block_size_limit: Option, ) -> Result, PR::Proof>, sp_blockchain::Error> { - /// If the block is full we will attempt to push at most - /// this number of transactions before quitting for real. - /// It allows us to increase block utilization. - const MAX_SKIPPED_TRANSACTIONS: usize = 8; - let mut block_builder = self.client.new_block_at(&self.parent_id, inherent_digests, PR::ENABLED)?; @@ -336,6 +336,9 @@ where } // proceed with transactions + // We calculate soft deadline used only in case we start skipping transactions. + let now = (self.now)(); + let soft_deadline = now + deadline.saturating_duration_since(now) / 2; let block_timer = time::Instant::now(); let mut skipped = 0; let mut unqueue_invalid = Vec::new(); @@ -364,7 +367,8 @@ where let mut hit_block_size_limit = false; while let Some(pending_tx) = pending_iterator.next() { - if (self.now)() > deadline { + let now = (self.now)(); + if now > deadline { debug!( "Consensus deadline reached when pushing block transactions, \ proceeding with proposing." @@ -387,6 +391,13 @@ where MAX_SKIPPED_TRANSACTIONS - skipped, ); continue + } else if now < soft_deadline { + debug!( + "Transaction would overflow the block size limit, \ + but we still have time before the soft deadline, so \ + we will try a bit more." + ); + continue } else { debug!("Reached block size limit, proceeding with proposing."); hit_block_size_limit = true; @@ -408,6 +419,11 @@ where "Block seems full, but will try {} more transactions before quitting.", MAX_SKIPPED_TRANSACTIONS - skipped, ); + } else if (self.now)() < soft_deadline { + debug!( + "Block seems full, but we still have time before the soft deadline, \ + so we will try a bit more before quitting." + ); } else { debug!("Block is full, proceed with proposing."); break @@ -493,6 +509,7 @@ mod tests { use sp_api::Core; use sp_blockchain::HeaderBackend; use sp_consensus::{BlockOrigin, Environment, Proposer}; + use sp_core::Pair; use sp_runtime::traits::NumberFor; use substrate_test_runtime_client::{ prelude::*, @@ -512,6 +529,19 @@ mod tests { .into_signed_tx() } + fn exhausts_resources_extrinsic_from(who: usize) -> Extrinsic { + let pair = AccountKeyring::numeric(who); + let transfer = Transfer { + // increase the amount to bump priority + amount: 1, + nonce: 0, + from: pair.public(), + to: Default::default(), + }; + let signature = pair.sign(&transfer.encode()).into(); + Extrinsic::Transfer { transfer, signature, exhaust_resources_when_not_first: true } + } + fn chain_event(header: B::Header) -> ChainEvent where NumberFor: From, @@ -557,7 +587,7 @@ mod tests { return value.1 } let old = value.1; - let new = old + time::Duration::from_secs(2); + let new = old + time::Duration::from_secs(1); *value = (true, new); old }), @@ -730,8 +760,8 @@ mod tests { // then // block should have some extrinsics although we have some more in the pool. - assert_eq!(block.extrinsics().len(), expected_block_extrinsics); assert_eq!(txpool.ready().count(), expected_pool_transactions); + assert_eq!(block.extrinsics().len(), expected_block_extrinsics); block }; @@ -744,6 +774,7 @@ mod tests { .expect("there should be header"), )), ); + assert_eq!(txpool.ready().count(), 7); // let's create one block and import it let block = propose_block(&client, 0, 2, 7); @@ -757,6 +788,7 @@ mod tests { .expect("there should be header"), )), ); + assert_eq!(txpool.ready().count(), 5); // now let's make sure that we can still make some progress let block = propose_block(&client, 1, 2, 5); @@ -849,4 +881,142 @@ mod tests { // block size and thus, one less transaction should fit into the limit. assert_eq!(block.extrinsics().len(), extrinsics_num - 2); } + + #[test] + fn should_keep_adding_transactions_after_exhausts_resources_before_soft_deadline() { + // given + let client = Arc::new(substrate_test_runtime_client::new()); + let spawner = sp_core::testing::TaskExecutor::new(); + let txpool = BasicPool::new_full( + Default::default(), + true.into(), + None, + spawner.clone(), + client.clone(), + ); + + block_on( + txpool.submit_at( + &BlockId::number(0), + SOURCE, + // add 2 * MAX_SKIPPED_TRANSACTIONS that exhaust resources + (0..MAX_SKIPPED_TRANSACTIONS * 2) + .into_iter() + .map(|i| exhausts_resources_extrinsic_from(i)) + // and some transactions that are okay. + .chain((0..MAX_SKIPPED_TRANSACTIONS).into_iter().map(|i| extrinsic(i as _))) + .collect(), + ), + ) + .unwrap(); + + block_on( + txpool.maintain(chain_event( + client + .header(&BlockId::Number(0u64)) + .expect("header get error") + .expect("there should be header"), + )), + ); + assert_eq!(txpool.ready().count(), MAX_SKIPPED_TRANSACTIONS * 3); + + let mut proposer_factory = + ProposerFactory::new(spawner.clone(), client.clone(), txpool.clone(), None, None); + + let cell = Mutex::new(time::Instant::now()); + let proposer = proposer_factory.init_with_now( + &client.header(&BlockId::number(0)).unwrap().unwrap(), + Box::new(move || { + let mut value = cell.lock(); + let old = *value; + *value = old + time::Duration::from_secs(1); + old + }), + ); + + // when + // give it enough time so that deadline is never triggered. + let deadline = time::Duration::from_secs(900); + let block = + block_on(proposer.propose(Default::default(), Default::default(), deadline, None)) + .map(|r| r.block) + .unwrap(); + + // then block should have all non-exhaust resources extrinsics (+ the first one). + assert_eq!(block.extrinsics().len(), MAX_SKIPPED_TRANSACTIONS + 1); + } + + #[test] + fn should_only_skip_up_to_some_limit_after_soft_deadline() { + // given + let client = Arc::new(substrate_test_runtime_client::new()); + let spawner = sp_core::testing::TaskExecutor::new(); + let txpool = BasicPool::new_full( + Default::default(), + true.into(), + None, + spawner.clone(), + client.clone(), + ); + + block_on( + txpool.submit_at( + &BlockId::number(0), + SOURCE, + (0..MAX_SKIPPED_TRANSACTIONS + 2) + .into_iter() + .map(|i| exhausts_resources_extrinsic_from(i)) + // and some transactions that are okay. + .chain((0..MAX_SKIPPED_TRANSACTIONS).into_iter().map(|i| extrinsic(i as _))) + .collect(), + ), + ) + .unwrap(); + + block_on( + txpool.maintain(chain_event( + client + .header(&BlockId::Number(0u64)) + .expect("header get error") + .expect("there should be header"), + )), + ); + assert_eq!(txpool.ready().count(), MAX_SKIPPED_TRANSACTIONS * 2 + 2); + + let mut proposer_factory = + ProposerFactory::new(spawner.clone(), client.clone(), txpool.clone(), None, None); + + let deadline = time::Duration::from_secs(600); + let cell = Arc::new(Mutex::new((0, time::Instant::now()))); + let cell2 = cell.clone(); + let proposer = proposer_factory.init_with_now( + &client.header(&BlockId::number(0)).unwrap().unwrap(), + Box::new(move || { + let mut value = cell.lock(); + let (called, old) = *value; + // add time after deadline is calculated internally (hence 1) + let increase = if called == 1 { + // we start after the soft_deadline should have already been reached. + deadline / 2 + } else { + // but we make sure to never reach the actual deadline + time::Duration::from_millis(0) + }; + *value = (called + 1, old + increase); + old + }), + ); + + let block = + block_on(proposer.propose(Default::default(), Default::default(), deadline, None)) + .map(|r| r.block) + .unwrap(); + + // then the block should have no transactions despite some in the pool + assert_eq!(block.extrinsics().len(), 1); + assert!( + cell2.lock().0 > MAX_SKIPPED_TRANSACTIONS, + "Not enough calls to current time, which indicates the test might have ended because of deadline, not soft deadline" + ); + } } diff --git a/client/service/test/Cargo.toml b/client/service/test/Cargo.toml index 85a6dcc9e8b2..9e66e9ca381d 100644 --- a/client/service/test/Cargo.toml +++ b/client/service/test/Cargo.toml @@ -12,6 +12,7 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] +hex = "0.4" hex-literal = "0.3.1" tempfile = "3.1.0" tokio = { version = "1.10.0", features = ["time"] } diff --git a/client/service/test/src/client/mod.rs b/client/service/test/src/client/mod.rs index d82a839936d7..8ea605c0ea5b 100644 --- a/client/service/test/src/client/mod.rs +++ b/client/service/test/src/client/mod.rs @@ -1759,12 +1759,21 @@ fn storage_keys_iter_works() { let res: Vec<_> = client .storage_keys_iter(&BlockId::Number(0), Some(&prefix), None) .unwrap() - .take(2) - .map(|x| x.0) + .take(8) + .map(|x| hex::encode(&x.0)) .collect(); assert_eq!( res, - [hex!("0befda6e1ca4ef40219d588a727f1271").to_vec(), hex!("3a636f6465").to_vec()] + [ + "00c232cf4e70a5e343317016dc805bf80a6a8cd8ad39958d56f99891b07851e0", + "085b2407916e53a86efeb8b72dbe338c4b341dab135252f96b6ed8022209b6cb", + "0befda6e1ca4ef40219d588a727f1271", + "1a560ecfd2a62c2b8521ef149d0804eb621050e3988ed97dca55f0d7c3e6aa34", + "1d66850d32002979d67dd29dc583af5b2ae2a1f71c1f35ad90fff122be7a3824", + "237498b98d8803334286e9f0483ef513098dd3c1c22ca21c4dc155b4ef6cc204", + "29b9db10ec5bf7907d8f74b5e60aa8140c4fbdd8127a1ee5600cb98e5ec01729", + "3a636f6465", + ] ); let res: Vec<_> = client @@ -1774,15 +1783,19 @@ fn storage_keys_iter_works() { Some(&StorageKey(hex!("3a636f6465").to_vec())), ) .unwrap() - .take(3) - .map(|x| x.0) + .take(7) + .map(|x| hex::encode(&x.0)) .collect(); assert_eq!( res, [ - hex!("3a686561707061676573").to_vec(), - hex!("6644b9b8bc315888ac8e41a7968dc2b4141a5403c58acdf70b7e8f7e07bf5081").to_vec(), - hex!("79c07e2b1d2e2abfd4855b936617eeff5e0621c4869aa60c02be9adcc98a0d1d").to_vec(), + "3a686561707061676573", + "52008686cc27f6e5ed83a216929942f8bcd32a396f09664a5698f81371934b56", + "5348d72ac6cc66e5d8cbecc27b0e0677503b845fe2382d819f83001781788fd5", + "5c2d5fda66373dabf970e4fb13d277ce91c5233473321129d32b5a8085fa8133", + "6644b9b8bc315888ac8e41a7968dc2b4141a5403c58acdf70b7e8f7e07bf5081", + "66484000ed3f75c95fc7b03f39c20ca1e1011e5999278247d3b2f5e3c3273808", + "79c07e2b1d2e2abfd4855b936617eeff5e0621c4869aa60c02be9adcc98a0d1d", ] ); @@ -1795,12 +1808,18 @@ fn storage_keys_iter_works() { )), ) .unwrap() - .take(1) - .map(|x| x.0) + .take(5) + .map(|x| hex::encode(x.0)) .collect(); assert_eq!( res, - [hex!("cf722c0832b5231d35e29f319ff27389f5032bfc7bfc3ba5ed7839f2042fb99f").to_vec()] + [ + "7d5007603a7f5dd729d51d93cf695d6465789443bb967c0d1fe270e388c96eaa", + "811ecfaadcf5f2ee1d67393247e2f71a1662d433e8ce7ff89fb0d4aa9561820b", + "a93d74caa7ec34ea1b04ce1e5c090245f867d333f0f88278a451e45299654dc5", + "a9ee1403384afbfc13f13be91ff70bfac057436212e53b9733914382ac942892", + "cf722c0832b5231d35e29f319ff27389f5032bfc7bfc3ba5ed7839f2042fb99f", + ] ); } diff --git a/primitives/keyring/src/sr25519.rs b/primitives/keyring/src/sr25519.rs index 6a7aa3635a43..604c330b1ea1 100644 --- a/primitives/keyring/src/sr25519.rs +++ b/primitives/keyring/src/sr25519.rs @@ -89,9 +89,20 @@ impl Keyring { pub fn public(self) -> Public { self.pair().public() } + pub fn to_seed(self) -> String { format!("//{}", self) } + + /// Create a crypto `Pair` from a numeric value. + pub fn numeric(idx: usize) -> Pair { + Pair::from_string(&format!("//{}", idx), None).expect("numeric values are known good; qed") + } + + /// Get account id of a `numeric` account. + pub fn numeric_id(idx: usize) -> AccountId32 { + (*Self::numeric(idx).public().as_array_ref()).into() + } } impl From for &'static str { diff --git a/test-utils/runtime/client/src/lib.rs b/test-utils/runtime/client/src/lib.rs index dc5ccadc4574..bcfe93b6f797 100644 --- a/test-utils/runtime/client/src/lib.rs +++ b/test-utils/runtime/client/src/lib.rs @@ -37,7 +37,7 @@ use sc_client_api::light::{ use sp_core::{ sr25519, storage::{ChildInfo, Storage, StorageChild}, - ChangesTrieConfiguration, + ChangesTrieConfiguration, Pair, }; use sp_runtime::traits::{Block as BlockT, Hash as HashT, HashFor, Header as HeaderT, NumberFor}; use substrate_test_runtime::genesismap::{additional_storage_with_genesis, GenesisConfig}; @@ -118,11 +118,15 @@ impl GenesisParameters { sr25519::Public::from(Sr25519Keyring::Bob).into(), sr25519::Public::from(Sr25519Keyring::Charlie).into(), ], - vec![ - AccountKeyring::Alice.into(), - AccountKeyring::Bob.into(), - AccountKeyring::Charlie.into(), - ], + (0..16_usize) + .into_iter() + .map(|i| AccountKeyring::numeric(i).public()) + .chain(vec![ + AccountKeyring::Alice.into(), + AccountKeyring::Bob.into(), + AccountKeyring::Charlie.into(), + ]) + .collect(), 1000, self.heap_pages_override, self.extra_storage.clone(), From ddc2c6e7efa16f9820944cb052be94dc38d55e26 Mon Sep 17 00:00:00 2001 From: Chevdor Date: Mon, 4 Oct 2021 21:19:17 +0200 Subject: [PATCH 024/695] chore: refresh of the substrate_builder image (#9808) * chore: refresh of the substrate_builder image fix #9715 * chore: renaming + build script * Fix spaces/tabs * Add doc * Remove non binary * Update docker/substrate_builder.Dockerfile Co-authored-by: Denis Pisarev --- .dockerignore | 1 + .maintain/Dockerfile | 59 ----------------------------- docker/README.md | 22 +++++++++++ docker/build.sh | 24 ++++++++++++ docker/substrate_builder.Dockerfile | 35 +++++++++++++++++ 5 files changed, 82 insertions(+), 59 deletions(-) delete mode 100644 .maintain/Dockerfile create mode 100644 docker/README.md create mode 100755 docker/build.sh create mode 100644 docker/substrate_builder.Dockerfile diff --git a/.dockerignore b/.dockerignore index 39dbc05c97e1..c58599e3fb72 100644 --- a/.dockerignore +++ b/.dockerignore @@ -4,3 +4,4 @@ doc Dockerfile .dockerignore .local +.env* diff --git a/.maintain/Dockerfile b/.maintain/Dockerfile deleted file mode 100644 index 21a41720f7d6..000000000000 --- a/.maintain/Dockerfile +++ /dev/null @@ -1,59 +0,0 @@ -# Note: We don't use Alpine and its packaged Rust/Cargo because they're too often out of date, -# preventing them from being used to build Substrate/Polkadot. - -FROM phusion/baseimage:0.11 as builder -LABEL maintainer="chevdor@gmail.com" -LABEL description="This is the build stage for Substrate. Here we create the binary." - -ENV DEBIAN_FRONTEND=noninteractive - -ARG PROFILE=release -WORKDIR /substrate - -COPY . /substrate - -RUN apt-get update && \ - apt-get dist-upgrade -y -o Dpkg::Options::="--force-confold" && \ - apt-get install -y cmake pkg-config libssl-dev git clang - -RUN curl https://sh.rustup.rs -sSf | sh -s -- -y && \ - export PATH="$PATH:$HOME/.cargo/bin" && \ - rustup toolchain install nightly && \ - rustup target add wasm32-unknown-unknown --toolchain nightly && \ - rustup default stable && \ - cargo build "--$PROFILE" - -# ===== SECOND STAGE ====== - -FROM phusion/baseimage:0.11 -LABEL maintainer="chevdor@gmail.com" -LABEL description="This is the 2nd stage: a very small image where we copy the Substrate binary." -ARG PROFILE=release - -RUN mv /usr/share/ca* /tmp && \ - rm -rf /usr/share/* && \ - mv /tmp/ca-certificates /usr/share/ && \ - useradd -m -u 1000 -U -s /bin/sh -d /substrate substrate && \ - mkdir -p /substrate/.local/share/substrate && \ - chown -R substrate:substrate /substrate/.local && \ - ln -s /substrate/.local/share/substrate /data - -COPY --from=builder /substrate/target/$PROFILE/substrate /usr/local/bin -COPY --from=builder /substrate/target/$PROFILE/subkey /usr/local/bin -COPY --from=builder /substrate/target/$PROFILE/node-rpc-client /usr/local/bin -COPY --from=builder /substrate/target/$PROFILE/node-template /usr/local/bin -COPY --from=builder /substrate/target/$PROFILE/chain-spec-builder /usr/local/bin - -# checks -RUN ldd /usr/local/bin/substrate && \ - /usr/local/bin/substrate --version - -# Shrinking -RUN rm -rf /usr/lib/python* && \ - rm -rf /usr/bin /usr/sbin /usr/share/man - -USER substrate -EXPOSE 30333 9933 9944 9615 -VOLUME ["/data"] - -CMD ["/usr/local/bin/substrate"] diff --git a/docker/README.md b/docker/README.md new file mode 100644 index 000000000000..ca3c1bde4e32 --- /dev/null +++ b/docker/README.md @@ -0,0 +1,22 @@ +# Substrate Builder Docker Image + +The Docker image in this folder is a `builder` image. It is self contained and allow users to build the binaries themselves. +There is no requirement on having Rust or any other toolchain installed but a working Docker environment. + +Unlike the `parity/polkadot` image which contains a single binary (`polkadot`!) used by default, the image in this folder builds and contains several binaries and you need to provide the name of the binary to be called. + +You should refer to the .Dockerfile for the actual list. At the time of editing, the list of included binaries is: + +- substrate +- subkey +- node-template +- chain-spec-builder + +The image can be used by passing the selected binary followed by the appropriate tags for this binary. + +Your best guess to get started is to pass the `--help flag`. Here are a few examples: + +- `docker run --rm -it parity/substrate substrate --version` +- `docker run --rm -it parity/substrate subkey --help` +- `docker run --rm -it parity/substrate node-template --version` +- `docker run --rm -it parity/substrate chain-spec-builder --help` diff --git a/docker/build.sh b/docker/build.sh new file mode 100755 index 000000000000..f0a4560ff8fe --- /dev/null +++ b/docker/build.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +set -e + +pushd . + +# The following line ensure we run from the project root +PROJECT_ROOT=`git rev-parse --show-toplevel` +cd $PROJECT_ROOT + +# Find the current version from Cargo.toml +VERSION=`grep "^version" ./bin/node/cli/Cargo.toml | egrep -o "([0-9\.]+)"` +GITUSER=parity +GITREPO=substrate + +# Build the image +echo "Building ${GITUSER}/${GITREPO}:latest docker image, hang on!" +time docker build -f ./docker/substrate_builder.Dockerfile -t ${GITUSER}/${GITREPO}:latest . +docker tag ${GITUSER}/${GITREPO}:latest ${GITUSER}/${GITREPO}:v${VERSION} + +# Show the list of available images for this repo +echo "Image is ready" +docker images | grep ${GITREPO} + +popd diff --git a/docker/substrate_builder.Dockerfile b/docker/substrate_builder.Dockerfile new file mode 100644 index 000000000000..d0812c1a80c4 --- /dev/null +++ b/docker/substrate_builder.Dockerfile @@ -0,0 +1,35 @@ +# This is the build stage for Substrate. Here we create the binary. +FROM docker.io/paritytech/ci-linux:production as builder + +WORKDIR /substrate +COPY . /substrate +RUN cargo build --locked --release + +# This is the 2nd stage: a very small image where we copy the Substrate binary." +FROM docker.io/library/ubuntu:20.04 +LABEL description="Multistage Docker image for Substrate: a platform for web3" \ + io.parity.image.type="builder" \ + io.parity.image.authors="chevdor@gmail.com, devops-team@parity.io" \ + io.parity.image.vendor="Parity Technologies" \ + io.parity.image.description="Substrate is a next-generation framework for blockchain innovation 🚀" \ + io.parity.image.source="https://github.com/paritytech/polkadot/blob/${VCS_REF}/docker/substrate_builder.Dockerfile" \ + io.parity.image.documentation="https://github.com/paritytech/polkadot/" + +COPY --from=builder /substrate/target/release/substrate /usr/local/bin +COPY --from=builder /substrate/target/release/subkey /usr/local/bin +COPY --from=builder /substrate/target/release/node-template /usr/local/bin +COPY --from=builder /substrate/target/release/chain-spec-builder /usr/local/bin + +RUN useradd -m -u 1000 -U -s /bin/sh -d /substrate substrate && \ + mkdir -p /data /substrate/.local/share/substrate && \ + chown -R substrate:substrate /data && \ + ln -s /data /substrate/.local/share/substrate && \ +# unclutter and minimize the attack surface + rm -rf /usr/bin /usr/sbin && \ +# Sanity checks + ldd /usr/local/bin/substrate && \ + /usr/local/bin/substrate --version + +USER substrate +EXPOSE 30333 9933 9944 9615 +VOLUME ["/data"] From 1d356ce61f12fbb35ea471c48c1b3fea6ef0795c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Mon, 4 Oct 2021 22:55:36 +0200 Subject: [PATCH 025/695] Require crypto scheme for `insert-key` (#9909) * Require crypto scheme for `insert-key` We should not "guess" the scheme as this can depend on the implementation of the runtime etc. * FMT --- client/cli/src/commands/insert_key.rs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/client/cli/src/commands/insert_key.rs b/client/cli/src/commands/insert_key.rs index 05055dc53c1e..081c31908160 100644 --- a/client/cli/src/commands/insert_key.rs +++ b/client/cli/src/commands/insert_key.rs @@ -18,7 +18,7 @@ //! Implementation of the `insert` subcommand use crate::{ - utils, with_crypto_scheme, CryptoSchemeFlag, Error, KeystoreParams, SharedParams, SubstrateCli, + utils, with_crypto_scheme, CryptoScheme, Error, KeystoreParams, SharedParams, SubstrateCli, }; use sc_keystore::LocalKeystore; use sc_service::config::{BasePath, KeystoreConfig}; @@ -49,9 +49,14 @@ pub struct InsertKeyCmd { #[structopt(flatten)] pub keystore_params: KeystoreParams, - #[allow(missing_docs)] - #[structopt(flatten)] - pub crypto_scheme: CryptoSchemeFlag, + /// The cryptography scheme that should be used to generate the key out of the given URI. + #[structopt( + long, + value_name = "SCHEME", + possible_values = &CryptoScheme::variants(), + case_insensitive = true, + )] + pub scheme: CryptoScheme, } impl InsertKeyCmd { @@ -68,10 +73,7 @@ impl InsertKeyCmd { let (keystore, public) = match self.keystore_params.keystore_config(&config_dir)? { (_, KeystoreConfig::Path { path, password }) => { - let public = with_crypto_scheme!( - self.crypto_scheme.scheme, - to_vec(&suri, password.clone()) - )?; + let public = with_crypto_scheme!(self.scheme, to_vec(&suri, password.clone()))?; let keystore: SyncCryptoStorePtr = Arc::new(LocalKeystore::open(path, password)?); (keystore, public) }, @@ -161,6 +163,7 @@ mod tests { "test", "--suri", &uri, + "--scheme=sr25519", ]); assert!(inspect.run(&Cli).is_ok()); From 1c2e9a8c6d073d924f867cd883138630c9dff9f7 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Mon, 4 Oct 2021 18:19:21 -0400 Subject: [PATCH 026/695] Remove incorrect sanity check (#9924) * causes issue * remove the bad error check --- bin/node-template/runtime/src/lib.rs | 1 - bin/node/runtime/src/lib.rs | 1 - 2 files changed, 2 deletions(-) diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index 5d3ea603265f..e11840b5813d 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -508,7 +508,6 @@ impl_runtime_apis! { add_benchmark!(params, batches, pallet_timestamp, Timestamp); add_benchmark!(params, batches, pallet_template, TemplateModule); - if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } Ok(batches) } } diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index f2d3175f094d..b115087d514d 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -1728,7 +1728,6 @@ impl_runtime_apis! { add_benchmark!(params, batches, pallet_utility, Utility); add_benchmark!(params, batches, pallet_vesting, Vesting); - if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } Ok(batches) } } From 8f5b446ee4c1cff407a2888985178cf692166428 Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Tue, 5 Oct 2021 08:23:09 +0200 Subject: [PATCH 027/695] don't read events in elections anymore. (#9898) * dont read events in elections anymore. * Update frame/election-provider-multi-phase/src/lib.rs * Fix test for Substrate#9898 (#9907) Co-authored-by: Shawn Tabrizi Co-authored-by: Zeke Mostov <32168567+emostov@users.noreply.github.com> --- .../election-provider-multi-phase/src/lib.rs | 22 ++------ .../src/unsigned.rs | 55 ++++++++++++++----- 2 files changed, 47 insertions(+), 30 deletions(-) diff --git a/frame/election-provider-multi-phase/src/lib.rs b/frame/election-provider-multi-phase/src/lib.rs index 6b0329afc0d7..9508b3a7c83f 100644 --- a/frame/election-provider-multi-phase/src/lib.rs +++ b/frame/election-provider-multi-phase/src/lib.rs @@ -1201,8 +1201,12 @@ impl Pallet { match current_phase { Phase::Unsigned((true, opened)) if opened == now => { // Mine a new solution, cache it, and attempt to submit it - let initial_output = Self::ensure_offchain_repeat_frequency(now) - .and_then(|_| Self::mine_check_save_submit()); + let initial_output = Self::ensure_offchain_repeat_frequency(now).and_then(|_| { + // This is executed at the beginning of each round. Any cache is now invalid. + // Clear it. + unsigned::kill_ocw_solution::(); + Self::mine_check_save_submit() + }); log!(debug, "initial offchain thread output: {:?}", initial_output); }, Phase::Unsigned((true, opened)) if opened < now => { @@ -1214,20 +1218,6 @@ impl Pallet { }, _ => {}, } - - // After election finalization, clear OCW solution storage. - // - // We can read the events here because offchain worker doesn't affect PoV. - if >::read_events_no_consensus() - .into_iter() - .filter_map(|event_record| { - let local_event = ::Event::from(event_record.event); - local_event.try_into().ok() - }) - .any(|event| matches!(event, Event::ElectionFinalized(_))) - { - unsigned::kill_ocw_solution::(); - } } /// Logic for [`::on_initialize`] when signed phase is being opened. diff --git a/frame/election-provider-multi-phase/src/unsigned.rs b/frame/election-provider-multi-phase/src/unsigned.rs index 31ad502ac076..0ed9b5427b1e 100644 --- a/frame/election-provider-multi-phase/src/unsigned.rs +++ b/frame/election-provider-multi-phase/src/unsigned.rs @@ -1241,35 +1241,62 @@ mod tests { } #[test] - fn ocw_clears_cache_after_election() { - let (mut ext, _pool) = ExtBuilder::default().build_offchainify(0); + fn ocw_clears_cache_on_unsigned_phase_open() { + let (mut ext, pool) = ExtBuilder::default().build_offchainify(0); ext.execute_with(|| { - roll_to(25); - assert_eq!(MultiPhase::current_phase(), Phase::Unsigned((true, 25))); + const BLOCK: u64 = 25; + let block_plus = |delta: u64| BLOCK + delta; + let offchain_repeat = ::OffchainRepeat::get(); - // we must clear the offchain storage to ensure the offchain execution check doesn't get - // in the way. - let mut storage = StorageValueRef::persistent(&OFFCHAIN_LAST_BLOCK); - storage.clear(); + roll_to(BLOCK); + // we are on the first block of the unsigned phase + assert_eq!(MultiPhase::current_phase(), Phase::Unsigned((true, BLOCK))); assert!( !ocw_solution_exists::(), "no solution should be present before we mine one", ); - // creates and cache a solution - MultiPhase::offchain_worker(25); + // create and cache a solution on the first block of the unsigned phase + MultiPhase::offchain_worker(BLOCK); assert!( ocw_solution_exists::(), "a solution must be cached after running the worker", ); - // after an election, the solution must be cleared + // record the submitted tx, + let tx_cache_1 = pool.read().transactions[0].clone(); + // and assume it has been processed. + pool.try_write().unwrap().transactions.clear(); + + // after an election, the solution is not cleared // we don't actually care about the result of the election - roll_to(26); let _ = MultiPhase::do_elect(); - MultiPhase::offchain_worker(26); - assert!(!ocw_solution_exists::(), "elections must clear the ocw cache"); + MultiPhase::offchain_worker(block_plus(1)); + assert!(ocw_solution_exists::(), "elections does not clear the ocw cache"); + + // submit a solution with the offchain worker after the repeat interval + MultiPhase::offchain_worker(block_plus(offchain_repeat + 1)); + + // record the submitted tx, + let tx_cache_2 = pool.read().transactions[0].clone(); + // and assume it has been processed. + pool.try_write().unwrap().transactions.clear(); + + // the OCW submitted the same solution twice since the cache was not cleared. + assert_eq!(tx_cache_1, tx_cache_2); + + let current_block = block_plus(offchain_repeat * 2 + 2); + // force the unsigned phase to start on the current block. + CurrentPhase::::set(Phase::Unsigned((true, current_block))); + + // clear the cache and create a solution since we are on the first block of the unsigned + // phase. + MultiPhase::offchain_worker(current_block); + let tx_cache_3 = pool.read().transactions[0].clone(); + + // the submitted solution changes because the cache was cleared. + assert_eq!(tx_cache_1, tx_cache_3); }) } From 9379b2368469b4214ae44e4b3bdc374dd3eb0f28 Mon Sep 17 00:00:00 2001 From: Squirrel Date: Tue, 5 Oct 2021 09:42:33 +0100 Subject: [PATCH 028/695] Improved file not found error message (#9931) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Say where you looked for the file Co-authored-by: Bastian Köcher --- client/chain-spec/src/chain_spec.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/client/chain-spec/src/chain_spec.rs b/client/chain-spec/src/chain_spec.rs index ff3a99760bd2..c4db6158125b 100644 --- a/client/chain-spec/src/chain_spec.rs +++ b/client/chain-spec/src/chain_spec.rs @@ -58,8 +58,9 @@ impl GenesisSource { match self { Self::File(path) => { - let file = - File::open(path).map_err(|e| format!("Error opening spec file: {}", e))?; + let file = File::open(path).map_err(|e| { + format!("Error opening spec file at `{}`: {}", path.display(), e) + })?; let genesis: GenesisContainer = json::from_reader(file) .map_err(|e| format!("Error parsing spec file: {}", e))?; Ok(genesis.genesis) @@ -284,7 +285,8 @@ impl ChainSpec { /// Parse json file into a `ChainSpec` pub fn from_json_file(path: PathBuf) -> Result { - let file = File::open(&path).map_err(|e| format!("Error opening spec file: {}", e))?; + let file = File::open(&path) + .map_err(|e| format!("Error opening spec file `{}`: {}", path.display(), e))?; let client_spec = json::from_reader(file).map_err(|e| format!("Error parsing spec file: {}", e))?; Ok(ChainSpec { client_spec, genesis: GenesisSource::File(path) }) From a30f0d1ca2efca6d13340d5f7fd480d9646cca3d Mon Sep 17 00:00:00 2001 From: Squirrel Date: Tue, 5 Oct 2021 12:26:34 +0100 Subject: [PATCH 029/695] First word should be Substrate not Polkadot (#9935) (if we want something put in the substrate PR.) --- docs/CONTRIBUTING.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/CONTRIBUTING.adoc b/docs/CONTRIBUTING.adoc index 0a9a7ebacff5..103b318a169d 100644 --- a/docs/CONTRIBUTING.adoc +++ b/docs/CONTRIBUTING.adoc @@ -79,7 +79,7 @@ To create a Polkadot companion PR: . Override substrate deps to point to your local path or branch using https://github.com/bkchr/diener. (E.g. from the polkadot clone dir run `diener patch --crates-to-patch ../substrate --substrate` assuming substrate clone is in a sibling dir. If you do use diener, ensure that you _do not_ commit the changes diener makes to the Cargo.tomls.) . Make the changes required and build polkadot locally. . Submit all this as a PR against the Polkadot Repo. -. Link to your Polkadot PR in the _description_ of your _Substrate_ PR as "polkadot companion: [URL]" +. In the _description_ of your _Substrate_ PR add "polkadot companion: [Polkadot_PR_URL]" . Now you should see that the `check_polkadot` CI job will build your Substrate PR agains the mentioned Polkadot branch in your PR description. . Someone will need to approve the Polkadot PR before the Substrate CI will go green. (The Polkadot CI failing can be ignored as long as the polkadot job in the _substrate_ PR is green). . Wait for reviews on both the Substrate and the Polkadot PRs. From ddf89923133ed1a7cbb33dfb84c3ed86efd18239 Mon Sep 17 00:00:00 2001 From: Koute Date: Tue, 5 Oct 2021 21:15:18 +0900 Subject: [PATCH 030/695] Speed up timestamp generation when logging (#9933) * Speed up timestamp generation when logging * Align to review comments. * Correct a typo --- Cargo.lock | 2 + client/tracing/Cargo.toml | 8 + client/tracing/benches/bench.rs | 49 ++++++ client/tracing/src/logging/directives.rs | 5 +- client/tracing/src/logging/event_format.rs | 8 +- client/tracing/src/logging/fast_local_time.rs | 160 ++++++++++++++++++ client/tracing/src/logging/mod.rs | 19 +-- 7 files changed, 230 insertions(+), 21 deletions(-) create mode 100644 client/tracing/benches/bench.rs create mode 100644 client/tracing/src/logging/fast_local_time.rs diff --git a/Cargo.lock b/Cargo.lock index 622b52591b90..1d23e8814bb0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8537,6 +8537,8 @@ version = "4.0.0-dev" dependencies = [ "ansi_term 0.12.1", "atty", + "chrono", + "criterion", "lazy_static", "log 0.4.14", "once_cell", diff --git a/client/tracing/Cargo.toml b/client/tracing/Cargo.toml index 3e314a82aa58..445718d6306f 100644 --- a/client/tracing/Cargo.toml +++ b/client/tracing/Cargo.toml @@ -15,6 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] ansi_term = "0.12.1" atty = "0.2.13" +chrono = "0.4.19" lazy_static = "1.4.0" log = { version = "0.4.8" } once_cell = "1.4.1" @@ -35,3 +36,10 @@ sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } sc-client-api = { version = "4.0.0-dev", path = "../api" } sc-tracing-proc-macro = { version = "4.0.0-dev", path = "./proc-macro" } sc-rpc-server = { version = "4.0.0-dev", path = "../rpc-servers" } + +[dev-dependencies] +criterion = "0.3" + +[[bench]] +name = "bench" +harness = false diff --git a/client/tracing/benches/bench.rs b/client/tracing/benches/bench.rs new file mode 100644 index 000000000000..ee218958be9b --- /dev/null +++ b/client/tracing/benches/bench.rs @@ -0,0 +1,49 @@ +// This file is part of Substrate. + +// Copyright (C) 2021 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. + +use criterion::{criterion_group, criterion_main, Criterion}; +use tracing_subscriber::fmt::time::{ChronoLocal, FormatTime}; + +fn bench_fast_local_time(c: &mut Criterion) { + c.bench_function("fast_local_time", |b| { + let mut buffer = String::new(); + let t = sc_tracing::logging::FastLocalTime { with_fractional: true }; + b.iter(|| { + buffer.clear(); + t.format_time(&mut buffer).unwrap(); + }) + }); +} + +// This is here just as a point of comparison. +fn bench_chrono_local(c: &mut Criterion) { + c.bench_function("chrono_local", |b| { + let mut buffer = String::new(); + let t = ChronoLocal::with_format("%Y-%m-%d %H:%M:%S%.3f".to_string()); + b.iter(|| { + buffer.clear(); + t.format_time(&mut buffer).unwrap(); + }) + }); +} + +criterion_group! { + name = benches; + config = Criterion::default(); + targets = bench_fast_local_time, bench_chrono_local +} +criterion_main!(benches); diff --git a/client/tracing/src/logging/directives.rs b/client/tracing/src/logging/directives.rs index 5aaeb4d17e7d..16f68654de1e 100644 --- a/client/tracing/src/logging/directives.rs +++ b/client/tracing/src/logging/directives.rs @@ -17,8 +17,7 @@ use once_cell::sync::OnceCell; use parking_lot::Mutex; use tracing_subscriber::{ - filter::Directive, fmt as tracing_fmt, fmt::time::ChronoLocal, layer, reload::Handle, - EnvFilter, Registry, + filter::Directive, fmt as tracing_fmt, layer, reload::Handle, EnvFilter, Registry, }; // Handle to reload the tracing log filter @@ -109,6 +108,6 @@ pub(crate) fn set_reload_handle(handle: Handle) { // Used in the reload `Handle`. type SCSubscriber< N = tracing_fmt::format::DefaultFields, - E = crate::logging::EventFormat, + E = crate::logging::EventFormat, W = fn() -> std::io::Stderr, > = layer::Layered, Registry>; diff --git a/client/tracing/src/logging/event_format.rs b/client/tracing/src/logging/event_format.rs index 61d7fe77aec6..5a21192d69c4 100644 --- a/client/tracing/src/logging/event_format.rs +++ b/client/tracing/src/logging/event_format.rs @@ -16,6 +16,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +use crate::logging::fast_local_time::FastLocalTime; use ansi_term::Colour; use regex::Regex; use std::fmt::{self, Write}; @@ -23,16 +24,13 @@ use tracing::{Event, Level, Subscriber}; use tracing_log::NormalizeEvent; use tracing_subscriber::{ field::RecordFields, - fmt::{ - time::{FormatTime, SystemTime}, - FmtContext, FormatEvent, FormatFields, - }, + fmt::{time::FormatTime, FmtContext, FormatEvent, FormatFields}, layer::Context, registry::{LookupSpan, SpanRef}, }; /// A pre-configured event formatter. -pub struct EventFormat { +pub struct EventFormat { /// Use the given timer for log message timestamps. pub timer: T, /// Sets whether or not an event's target is displayed. diff --git a/client/tracing/src/logging/fast_local_time.rs b/client/tracing/src/logging/fast_local_time.rs new file mode 100644 index 000000000000..288e44aa5e3a --- /dev/null +++ b/client/tracing/src/logging/fast_local_time.rs @@ -0,0 +1,160 @@ +// This file is part of Substrate. + +// Copyright (C) 2021 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 . + +use chrono::{Datelike, Timelike}; +use std::{cell::RefCell, fmt::Write, time::SystemTime}; +use tracing_subscriber::fmt::time::FormatTime; + +/// A structure which, when `Display`d, will print out the current local time. +#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)] +pub struct FastLocalTime { + /// Decides whenever the fractional timestamp with be included in the output. + /// + /// If `false` the output will match the following `chrono` format string: + /// `%Y-%m-%d %H:%M:%S` + /// + /// If `true` the output will match the following `chrono` format string: + /// `%Y-%m-%d %H:%M:%S%.3f` + pub with_fractional: bool, +} + +// This is deliberately slightly larger than we actually need, just in case. +const TIMESTAMP_MAXIMUM_LENGTH: usize = 32; + +#[derive(Default)] +struct InlineString { + buffer: [u8; TIMESTAMP_MAXIMUM_LENGTH], + length: usize, +} + +impl Write for InlineString { + fn write_str(&mut self, s: &str) -> std::fmt::Result { + let new_length = self.length + s.len(); + assert!( + new_length <= TIMESTAMP_MAXIMUM_LENGTH, + "buffer overflow when formatting the current timestamp" + ); + + self.buffer[self.length..new_length].copy_from_slice(s.as_bytes()); + self.length = new_length; + Ok(()) + } +} + +impl InlineString { + fn as_str(&self) -> &str { + // SAFETY: this is safe since the only place we append to the buffer + // is in `write_str` from an `&str` + unsafe { std::str::from_utf8_unchecked(&self.buffer[..self.length]) } + } +} + +#[derive(Default)] +struct CachedTimestamp { + buffer: InlineString, + last_regenerated_at: u64, + last_fractional: u32, +} + +thread_local! { + static TIMESTAMP: RefCell = Default::default(); +} + +impl FormatTime for FastLocalTime { + fn format_time(&self, w: &mut dyn Write) -> std::fmt::Result { + const TIMESTAMP_PARTIAL_LENGTH: usize = "0000-00-00 00:00:00".len(); + + let elapsed = SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) + .expect("system time is never before UNIX epoch; qed"); + let unix_time = elapsed.as_secs(); + + TIMESTAMP.with(|cache| { + let mut cache = cache.borrow_mut(); + + // Regenerate the timestamp only at most once each second. + if cache.last_regenerated_at != unix_time { + let ts = chrono::Local::now(); + let fractional = (ts.nanosecond() % 1_000_000_000) / 1_000_000; + cache.last_regenerated_at = unix_time; + cache.last_fractional = fractional; + cache.buffer.length = 0; + + write!( + &mut cache.buffer, + "{:04}-{:02}-{:02} {:02}:{:02}:{:02}.{:03}", + ts.year(), + ts.month(), + ts.day(), + ts.hour(), + ts.minute(), + ts.second(), + fractional + )?; + } else if self.with_fractional { + let fractional = elapsed.subsec_millis(); + + // Regenerate the fractional part at most once each millisecond. + if cache.last_fractional != fractional { + cache.last_fractional = fractional; + cache.buffer.length = TIMESTAMP_PARTIAL_LENGTH + 1; + write!(&mut cache.buffer, "{:03}", fractional)?; + } + } + + let mut slice = cache.buffer.as_str(); + if !self.with_fractional { + slice = &slice[..TIMESTAMP_PARTIAL_LENGTH]; + } + + w.write_str(slice) + }) + } +} + +impl std::fmt::Display for FastLocalTime { + fn fmt(&self, w: &mut std::fmt::Formatter) -> std::fmt::Result { + self.format_time(w) + } +} + +#[test] +fn test_format_fast_local_time() { + assert_eq!( + chrono::Local::now().format("%Y-%m-%d %H:%M:%S").to_string().len(), + FastLocalTime { with_fractional: false }.to_string().len() + ); + assert_eq!( + chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f").to_string().len(), + FastLocalTime { with_fractional: true }.to_string().len() + ); + + // A simple trick to make sure this test won't randomly fail if we so happen + // to land on the exact moment when we tick over to the next second. + let now_1 = FastLocalTime { with_fractional: false }.to_string(); + let expected = chrono::Local::now().format("%Y-%m-%d %H:%M:%S").to_string(); + let now_2 = FastLocalTime { with_fractional: false }.to_string(); + + assert!( + now_1 == expected || now_2 == expected, + "'{}' or '{}' should have been equal to '{}'", + now_1, + now_2, + expected + ); +} diff --git a/client/tracing/src/logging/mod.rs b/client/tracing/src/logging/mod.rs index dd4830fe8975..dd0f7a5d8ae4 100644 --- a/client/tracing/src/logging/mod.rs +++ b/client/tracing/src/logging/mod.rs @@ -24,6 +24,7 @@ mod directives; mod event_format; +mod fast_local_time; mod layers; pub use directives::*; @@ -34,8 +35,8 @@ use tracing::Subscriber; use tracing_subscriber::{ filter::LevelFilter, fmt::{ - format, time::ChronoLocal, FormatEvent, FormatFields, Formatter, Layer as FmtLayer, - MakeWriter, SubscriberBuilder, + format, FormatEvent, FormatFields, Formatter, Layer as FmtLayer, MakeWriter, + SubscriberBuilder, }, layer::{self, SubscriberExt}, registry::LookupSpan, @@ -43,6 +44,7 @@ use tracing_subscriber::{ }; pub use event_format::*; +pub use fast_local_time::FastLocalTime; pub use layers::*; /// Logging Result typedef. @@ -89,12 +91,7 @@ fn prepare_subscriber( profiling_targets: Option<&str>, force_colors: Option, builder_hook: impl Fn( - SubscriberBuilder< - format::DefaultFields, - EventFormat, - EnvFilter, - fn() -> std::io::Stderr, - >, + SubscriberBuilder std::io::Stderr>, ) -> SubscriberBuilder, ) -> Result LookupSpan<'a>> where @@ -161,11 +158,7 @@ where }; let enable_color = force_colors.unwrap_or_else(|| atty::is(atty::Stream::Stderr)); - let timer = ChronoLocal::with_format(if simple { - "%Y-%m-%d %H:%M:%S".to_string() - } else { - "%Y-%m-%d %H:%M:%S%.3f".to_string() - }); + let timer = fast_local_time::FastLocalTime { with_fractional: !simple }; let event_format = EventFormat { timer, From 4930977ae1ecc23030cf86466e1960defc2f0a30 Mon Sep 17 00:00:00 2001 From: Koute Date: Tue, 5 Oct 2021 23:22:28 +0900 Subject: [PATCH 031/695] Update multiple dependencies (#9936) --- Cargo.lock | 51 +++++++++++++++++++------------------- client/cli/Cargo.toml | 2 +- client/network/Cargo.toml | 2 +- client/tracing/Cargo.toml | 2 +- primitives/core/Cargo.toml | 6 ++--- 5 files changed, 31 insertions(+), 32 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1d23e8814bb0..d47ef8a2cac5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -292,7 +292,7 @@ dependencies = [ "async-io", "async-lock", "async-process", - "crossbeam-utils 0.8.3", + "crossbeam-utils 0.8.5", "futures-channel", "futures-core", "futures-io", @@ -1260,28 +1260,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775" dependencies = [ "cfg-if 1.0.0", - "crossbeam-utils 0.8.3", + "crossbeam-utils 0.8.5", ] [[package]] name = "crossbeam-deque" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9" +checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" dependencies = [ "cfg-if 1.0.0", "crossbeam-epoch", - "crossbeam-utils 0.8.3", + "crossbeam-utils 0.8.5", ] [[package]] name = "crossbeam-epoch" -version = "0.9.3" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2584f639eb95fea8c798496315b297cf81b9b58b6d30ab066a75455333cf4b12" +checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd" dependencies = [ "cfg-if 1.0.0", - "crossbeam-utils 0.8.3", + "crossbeam-utils 0.8.5", "lazy_static", "memoffset", "scopeguard", @@ -1300,11 +1300,10 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49" +checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" dependencies = [ - "autocfg 1.0.1", "cfg-if 1.0.0", "lazy_static", ] @@ -2422,8 +2421,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" dependencies = [ "cfg-if 1.0.0", + "js-sys", "libc", "wasi 0.9.0+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] @@ -4998,12 +4999,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.7.2" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3" -dependencies = [ - "parking_lot 0.11.1", -] +checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" [[package]] name = "oorandom" @@ -7161,7 +7159,7 @@ checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a" dependencies = [ "crossbeam-channel", "crossbeam-deque", - "crossbeam-utils 0.8.3", + "crossbeam-utils 0.8.5", "lazy_static", "num_cpus", ] @@ -10434,9 +10432,9 @@ dependencies = [ [[package]] name = "tiny-bip39" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9e44c4759bae7f1032e286a7ef990bd9ed23fe831b7eeba0beb97484c2e59b8" +checksum = "ffc59cb9dfc85bb312c3a78fd6aa8a8582e310b0fa885d5bb877f6dcc601839d" dependencies = [ "anyhow", "hmac 0.8.1", @@ -10447,6 +10445,7 @@ dependencies = [ "sha2 0.9.3", "thiserror", "unicode-normalization", + "wasm-bindgen", "zeroize", ] @@ -10897,11 +10896,11 @@ dependencies = [ [[package]] name = "twox-hash" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04f8ab788026715fa63b31960869617cba39117e520eb415b0139543e325ab59" +checksum = "1f559b464de2e2bdabcac6a210d12e9b5a5973c251e102c44c585c71d51bd78e" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "rand 0.7.3", "static_assertions", ] @@ -11875,18 +11874,18 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "377db0846015f7ae377174787dd452e1c5f5a9050bc6f954911d01f116daa0cd" +checksum = "bf68b08513768deaa790264a7fac27a58cbf2705cfcdc9448362229217d7e970" dependencies = [ "zeroize_derive", ] [[package]] name = "zeroize_derive" -version = "1.0.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3f369ddb18862aba61aa49bf31e74d29f0f162dec753063200e1dc084345d16" +checksum = "bdff2024a851a322b08f179173ae2ba620445aef1e838f0c196820eade4ae0c7" dependencies = [ "proc-macro2", "quote", diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index e7a0330e76e0..963d5b3d0a90 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -22,7 +22,7 @@ libp2p = "0.39.1" parity-scale-codec = "2.0.0" hex = "0.4.2" rand = "0.7.3" -tiny-bip39 = "0.8.0" +tiny-bip39 = "0.8.2" serde_json = "1.0.68" sc-keystore = { version = "4.0.0-dev", path = "../keystore" } sp-panic-handler = { version = "3.0.0", path = "../../primitives/panic-handler" } diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index 68b9595ae190..1725e4f5abcf 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -63,7 +63,7 @@ unsigned-varint = { version = "0.6.0", features = [ "asynchronous_codec", ] } void = "1.0.2" -zeroize = "1.4.1" +zeroize = "1.4.2" libp2p = "0.39.1" [dev-dependencies] diff --git a/client/tracing/Cargo.toml b/client/tracing/Cargo.toml index 445718d6306f..5cac4dccfd6e 100644 --- a/client/tracing/Cargo.toml +++ b/client/tracing/Cargo.toml @@ -18,7 +18,7 @@ atty = "0.2.13" chrono = "0.4.19" lazy_static = "1.4.0" log = { version = "0.4.8" } -once_cell = "1.4.1" +once_cell = "1.8.0" parking_lot = "0.11.1" regex = "1.4.2" rustc-hash = "1.1.0" diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index 73c3d454ed58..4e6d6e996011 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -33,10 +33,10 @@ hash256-std-hasher = { version = "0.15.2", default-features = false } base58 = { version = "0.1.0", optional = true } rand = { version = "0.7.3", optional = true, features = ["small_rng"] } substrate-bip39 = { version = "0.4.2", optional = true } -tiny-bip39 = { version = "0.8", optional = true } +tiny-bip39 = { version = "0.8.2", optional = true } regex = { version = "1.4.2", optional = true } num-traits = { version = "0.2.8", default-features = false } -zeroize = { version = "1.4.1", default-features = false } +zeroize = { version = "1.4.2", default-features = false } secrecy = { version = "0.7.0", default-features = false } lazy_static = { version = "1.4.0", default-features = false, optional = true } parking_lot = { version = "0.11.1", optional = true } @@ -63,7 +63,7 @@ schnorrkel = { version = "0.9.1", features = [ ], default-features = false, optional = true } sha2 = { version = "0.9.2", default-features = false, optional = true } hex = { version = "0.4", default-features = false, optional = true } -twox-hash = { version = "1.5.0", default-features = false, optional = true } +twox-hash = { version = "1.6.1", default-features = false, optional = true } libsecp256k1 = { version = "0.6", default-features = false, features = ["hmac", "static-context"], optional = true } merlin = { version = "2.0", default-features = false, optional = true } From d6a636f5752a0520bc4d4d2325c1d85f8e892ca3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Tue, 5 Oct 2021 23:10:25 +0200 Subject: [PATCH 032/695] Remove `IgnoredIssuance` from metadata constants (#9937) This value is not really meant to be "constant". --- frame/gilt/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/frame/gilt/src/lib.rs b/frame/gilt/src/lib.rs index de114e4bb87d..393b3acb41a3 100644 --- a/frame/gilt/src/lib.rs +++ b/frame/gilt/src/lib.rs @@ -128,7 +128,6 @@ pub mod pallet { /// The issuance to ignore. This is subtracted from the `Currency`'s `total_issuance` to get /// the issuance by which we inflate or deflate the gilt. - #[pallet::constant] type IgnoredIssuance: Get>; /// Number of duration queues in total. This sets the maximum duration supported, which is From 2a6e82650e6b9dbac4cde6183fb3816193049135 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Oct 2021 21:16:37 +0000 Subject: [PATCH 033/695] Bump secrecy from 0.7.0 to 0.8.0 (#9897) Bumps [secrecy](https://github.com/iqlusioninc/crates) from 0.7.0 to 0.8.0. - [Release notes](https://github.com/iqlusioninc/crates/releases) - [Commits](https://github.com/iqlusioninc/crates/compare/secrecy/v0.7.0...secrecy/v0.8.0) --- updated-dependencies: - dependency-name: secrecy dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 6 +++--- primitives/core/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d47ef8a2cac5..1beacc1313a7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8724,9 +8724,9 @@ dependencies = [ [[package]] name = "secrecy" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0673d6a6449f5e7d12a1caf424fd9363e2af3a4953023ed455e3c4beef4597c0" +checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" dependencies = [ "zeroize", ] @@ -10901,7 +10901,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f559b464de2e2bdabcac6a210d12e9b5a5973c251e102c44c585c71d51bd78e" dependencies = [ "cfg-if 1.0.0", - "rand 0.7.3", + "rand 0.8.4", "static_assertions", ] diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index 4e6d6e996011..ab7d8e3df19a 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -37,7 +37,7 @@ tiny-bip39 = { version = "0.8.2", optional = true } regex = { version = "1.4.2", optional = true } num-traits = { version = "0.2.8", default-features = false } zeroize = { version = "1.4.2", default-features = false } -secrecy = { version = "0.7.0", default-features = false } +secrecy = { version = "0.8.0", default-features = false } lazy_static = { version = "1.4.0", default-features = false, optional = true } parking_lot = { version = "0.11.1", optional = true } sp-debug-derive = { version = "3.0.0", path = "../debug-derive" } From 669045f6e47249b9c83b81b9432603430cd8109d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Wed, 6 Oct 2021 11:20:21 +0200 Subject: [PATCH 034/695] `--dev` implies `--tmp` (#9938) * `--dev` implies `--tmp` This changes `--dev` to imply `--tmp` when no explicit `--base-path` is provided. * Update client/cli/src/commands/run_cmd.rs Co-authored-by: Alexander Popiak --- client/cli/src/commands/run_cmd.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/client/cli/src/commands/run_cmd.rs b/client/cli/src/commands/run_cmd.rs index 98f2090c6f44..b43135f10973 100644 --- a/client/cli/src/commands/run_cmd.rs +++ b/client/cli/src/commands/run_cmd.rs @@ -241,6 +241,8 @@ pub struct RunCmd { /// /// Note: the directory is random per process execution. This directory is used as base path /// which includes: database, node key and keystore. + /// + /// When `--dev` is given and no explicit `--base-path`, this option is implied. #[structopt(long, conflicts_with = "base-path")] pub tmp: bool, } @@ -444,7 +446,12 @@ impl CliConfiguration for RunCmd { Ok(if self.tmp { Some(BasePath::new_temp_dir()?) } else { - self.shared_params().base_path() + match self.shared_params().base_path() { + Some(r) => Some(r), + // If `dev` is enabled, we use the temp base path. + None if self.shared_params().is_dev() => Some(BasePath::new_temp_dir()?), + None => None, + } }) } } From b15a15e74b60ce19d8ac94da6dfeeef671a0a49d Mon Sep 17 00:00:00 2001 From: Albrecht <14820950+weichweich@users.noreply.github.com> Date: Wed, 6 Oct 2021 11:22:49 +0200 Subject: [PATCH 035/695] disambiguate Config trait in #[pallet::constant] (#9942) * fix: use fully qualified syntax to disambiguate * add instance generic * line length < 100 --- frame/support/procedural/src/pallet/expand/constants.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frame/support/procedural/src/pallet/expand/constants.rs b/frame/support/procedural/src/pallet/expand/constants.rs index 7cc245e8089d..db47bf552ac1 100644 --- a/frame/support/procedural/src/pallet/expand/constants.rs +++ b/frame/support/procedural/src/pallet/expand/constants.rs @@ -35,6 +35,7 @@ pub fn expand_constants(def: &mut Def) -> proc_macro2::TokenStream { let type_impl_gen = &def.type_impl_generics(proc_macro2::Span::call_site()); let type_use_gen = &def.type_use_generics(proc_macro2::Span::call_site()); let pallet_ident = &def.pallet_struct.pallet; + let trait_use_gen = &def.trait_use_generics(proc_macro2::Span::call_site()); let mut where_clauses = vec![&def.config.where_clause]; where_clauses.extend(def.extra_constants.iter().map(|d| &d.where_clause)); @@ -49,7 +50,8 @@ pub fn expand_constants(def: &mut Def) -> proc_macro2::TokenStream { type_: const_.type_.clone(), doc: const_.doc.clone(), default_byte_impl: quote::quote!( - let value = >::get(); + let value = <::#ident as + #frame_support::traits::Get<#const_type>>::get(); #frame_support::codec::Encode::encode(&value) ), } From 4e5b971771eb9b8a10a95c5540292b1b47874ce9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Silva?= <123550+andresilva@users.noreply.github.com> Date: Wed, 6 Oct 2021 17:22:34 +0100 Subject: [PATCH 036/695] staking: only disable slashed validators and keep them disabled for whole era (#9448) * session: remove disabled validators threshold logic * staking: add logic to track offending validators * staking: disable validators for the whole era * frame: fix tests * staking: add tests for disabling validators handling * staking: fix adding offending validator when already slashed in era * address review comments * session, staking: add comments about sorted vecs Co-authored-by: Andronik Ordian --- bin/node/runtime/src/lib.rs | 7 +- frame/aura/src/lib.rs | 2 +- frame/authority-discovery/src/lib.rs | 5 +- frame/babe/src/lib.rs | 4 +- frame/babe/src/mock.rs | 4 +- frame/beefy-mmr/src/mock.rs | 3 - frame/beefy/src/lib.rs | 2 +- frame/beefy/src/mock.rs | 1 - frame/grandpa/src/lib.rs | 2 +- frame/grandpa/src/mock.rs | 4 +- frame/im-online/src/lib.rs | 2 +- frame/im-online/src/mock.rs | 7 +- frame/offences/benchmarking/src/mock.rs | 4 +- frame/session/benchmarking/src/mock.rs | 4 +- frame/session/src/lib.rs | 58 ++++------ frame/session/src/mock.rs | 8 +- frame/session/src/tests.rs | 7 +- frame/staking/fuzzer/src/mock.rs | 2 +- frame/staking/src/lib.rs | 13 +-- frame/staking/src/mock.rs | 34 ++---- frame/staking/src/pallet/impls.rs | 10 ++ frame/staking/src/pallet/mod.rs | 17 +++ frame/staking/src/slashing.rs | 62 ++++++++-- frame/staking/src/tests.rs | 146 ++++++++++++++++++++++-- frame/support/src/traits/validation.rs | 2 +- 25 files changed, 279 insertions(+), 131 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index b115087d514d..9fac468519a0 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -459,10 +459,6 @@ impl_opaque_keys! { } } -parameter_types! { - pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(17); -} - impl pallet_session::Config for Runtime { type Event = Event; type ValidatorId = ::AccountId; @@ -472,7 +468,6 @@ impl pallet_session::Config for Runtime { type SessionManager = pallet_session::historical::NoteHistoricalRoot; type SessionHandler = ::KeyTypeIdProviders; type Keys = SessionKeys; - type DisabledValidatorsThreshold = DisabledValidatorsThreshold; type WeightInfo = pallet_session::weights::SubstrateWeight; } @@ -498,6 +493,7 @@ parameter_types! { pub const SlashDeferDuration: pallet_staking::EraIndex = 24 * 7; // 1/4 the bonding duration. pub const RewardCurve: &'static PiecewiseLinear<'static> = &REWARD_CURVE; pub const MaxNominatorRewardedPerValidator: u32 = 256; + pub const OffendingValidatorsThreshold: Perbill = Perbill::from_percent(17); pub OffchainRepeat: BlockNumber = 5; } @@ -529,6 +525,7 @@ impl pallet_staking::Config for Runtime { type EraPayout = pallet_staking::ConvertCurve; type NextNewSession = Session; type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator; + type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type ElectionProvider = ElectionProviderMultiPhase; type GenesisElectionProvider = onchain::OnChainSequentialPhragmen; // Alternatively, use pallet_staking::UseNominatorsMap to just use the nominators map. diff --git a/frame/aura/src/lib.rs b/frame/aura/src/lib.rs index e8b68f928e08..4b5294835403 100644 --- a/frame/aura/src/lib.rs +++ b/frame/aura/src/lib.rs @@ -221,7 +221,7 @@ impl OneSessionHandler for Pallet { } } - fn on_disabled(i: usize) { + fn on_disabled(i: u32) { let log: DigestItem = DigestItem::Consensus( AURA_ENGINE_ID, ConsensusLog::::OnDisabled(i as AuthorityIndex).encode(), diff --git a/frame/authority-discovery/src/lib.rs b/frame/authority-discovery/src/lib.rs index d093b1533c69..8fced0d18cff 100644 --- a/frame/authority-discovery/src/lib.rs +++ b/frame/authority-discovery/src/lib.rs @@ -166,7 +166,7 @@ impl OneSessionHandler for Pallet { } } - fn on_disabled(_i: usize) { + fn on_disabled(_i: u32) { // ignore } } @@ -218,7 +218,6 @@ mod tests { type Event = Event; type ValidatorId = AuthorityId; type ValidatorIdOf = ConvertInto; - type DisabledValidatorsThreshold = DisabledValidatorsThreshold; type NextSessionRotation = pallet_session::PeriodicSessions; type WeightInfo = (); } @@ -276,7 +275,7 @@ mod tests { ) { } - fn on_disabled(_validator_index: usize) {} + fn on_disabled(_validator_index: u32) {} fn on_genesis_session(_validators: &[(AuthorityId, Ks)]) {} } diff --git a/frame/babe/src/lib.rs b/frame/babe/src/lib.rs index 4ccfdf6c13fe..9c755eea6c44 100644 --- a/frame/babe/src/lib.rs +++ b/frame/babe/src/lib.rs @@ -926,8 +926,8 @@ impl OneSessionHandler for Pallet { Self::enact_epoch_change(bounded_authorities, next_bounded_authorities) } - fn on_disabled(i: usize) { - Self::deposit_consensus(ConsensusLog::OnDisabled(i as u32)) + fn on_disabled(i: u32) { + Self::deposit_consensus(ConsensusLog::OnDisabled(i)) } } diff --git a/frame/babe/src/mock.rs b/frame/babe/src/mock.rs index b504a26f6042..e7ec69268903 100644 --- a/frame/babe/src/mock.rs +++ b/frame/babe/src/mock.rs @@ -68,7 +68,6 @@ frame_support::construct_runtime!( parameter_types! { pub const BlockHashCount: u64 = 250; - pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(16); pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max(1024); } @@ -122,7 +121,6 @@ impl pallet_session::Config for Test { type SessionManager = pallet_session::historical::NoteHistoricalRoot; type SessionHandler = ::KeyTypeIdProviders; type Keys = MockSessionKeys; - type DisabledValidatorsThreshold = DisabledValidatorsThreshold; type WeightInfo = (); } @@ -189,6 +187,7 @@ parameter_types! { pub const MaxNominatorRewardedPerValidator: u32 = 64; pub const ElectionLookahead: u64 = 0; pub const StakingUnsignedPriority: u64 = u64::MAX / 2; + pub const OffendingValidatorsThreshold: Perbill = Perbill::from_percent(16); } impl onchain::Config for Test { @@ -212,6 +211,7 @@ impl pallet_staking::Config for Test { type UnixTime = pallet_timestamp::Pallet; type EraPayout = pallet_staking::ConvertCurve; type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator; + type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type NextNewSession = Session; type ElectionProvider = onchain::OnChainSequentialPhragmen; type GenesisElectionProvider = Self::ElectionProvider; diff --git a/frame/beefy-mmr/src/mock.rs b/frame/beefy-mmr/src/mock.rs index 4c9e103eb7b8..95b87c360510 100644 --- a/frame/beefy-mmr/src/mock.rs +++ b/frame/beefy-mmr/src/mock.rs @@ -28,7 +28,6 @@ use sp_runtime::{ impl_opaque_keys, testing::Header, traits::{BlakeTwo256, ConvertInto, IdentityLookup, Keccak256, OpaqueKeys}, - Perbill, }; use crate as pallet_beefy_mmr; @@ -92,7 +91,6 @@ impl frame_system::Config for Test { parameter_types! { pub const Period: u64 = 1; pub const Offset: u64 = 0; - pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(33); } impl pallet_session::Config for Test { @@ -104,7 +102,6 @@ impl pallet_session::Config for Test { type SessionManager = MockSessionManager; type SessionHandler = ::KeyTypeIdProviders; type Keys = MockSessionKeys; - type DisabledValidatorsThreshold = DisabledValidatorsThreshold; type WeightInfo = (); } diff --git a/frame/beefy/src/lib.rs b/frame/beefy/src/lib.rs index 32f313337343..3b28d454849c 100644 --- a/frame/beefy/src/lib.rs +++ b/frame/beefy/src/lib.rs @@ -162,7 +162,7 @@ impl OneSessionHandler for Pallet { } } - fn on_disabled(i: usize) { + fn on_disabled(i: u32) { let log: DigestItem = DigestItem::Consensus( BEEFY_ENGINE_ID, ConsensusLog::::OnDisabled(i as AuthorityIndex).encode(), diff --git a/frame/beefy/src/mock.rs b/frame/beefy/src/mock.rs index baa2fae746fe..a1fbeda4ab35 100644 --- a/frame/beefy/src/mock.rs +++ b/frame/beefy/src/mock.rs @@ -105,7 +105,6 @@ impl pallet_session::Config for Test { type SessionManager = MockSessionManager; type SessionHandler = ::KeyTypeIdProviders; type Keys = MockSessionKeys; - type DisabledValidatorsThreshold = DisabledValidatorsThreshold; type WeightInfo = (); } diff --git a/frame/grandpa/src/lib.rs b/frame/grandpa/src/lib.rs index 687207151f4f..9f6967a7d3c8 100644 --- a/frame/grandpa/src/lib.rs +++ b/frame/grandpa/src/lib.rs @@ -674,7 +674,7 @@ where SetIdSession::::insert(current_set_id, &session_index); } - fn on_disabled(i: usize) { + fn on_disabled(i: u32) { Self::deposit_log(ConsensusLog::OnDisabled(i as u64)) } } diff --git a/frame/grandpa/src/mock.rs b/frame/grandpa/src/mock.rs index 4e5e44ce36e7..f1996553f02e 100644 --- a/frame/grandpa/src/mock.rs +++ b/frame/grandpa/src/mock.rs @@ -111,7 +111,6 @@ where parameter_types! { pub const Period: u64 = 1; pub const Offset: u64 = 0; - pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(17); } /// Custom `SessionHandler` since we use `TestSessionKeys` as `Keys`. @@ -124,7 +123,6 @@ impl pallet_session::Config for Test { type SessionManager = pallet_session::historical::NoteHistoricalRoot; type SessionHandler = ::KeyTypeIdProviders; type Keys = TestSessionKeys; - type DisabledValidatorsThreshold = DisabledValidatorsThreshold; type WeightInfo = (); } @@ -191,6 +189,7 @@ parameter_types! { pub const MaxNominatorRewardedPerValidator: u32 = 64; pub const ElectionLookahead: u64 = 0; pub const StakingUnsignedPriority: u64 = u64::MAX / 2; + pub const OffendingValidatorsThreshold: Perbill = Perbill::from_percent(17); } impl onchain::Config for Test { @@ -214,6 +213,7 @@ impl pallet_staking::Config for Test { type UnixTime = pallet_timestamp::Pallet; type EraPayout = pallet_staking::ConvertCurve; type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator; + type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type NextNewSession = Session; type ElectionProvider = onchain::OnChainSequentialPhragmen; type GenesisElectionProvider = Self::ElectionProvider; diff --git a/frame/im-online/src/lib.rs b/frame/im-online/src/lib.rs index 559c5edcf4d1..d76bbaaa2fd1 100644 --- a/frame/im-online/src/lib.rs +++ b/frame/im-online/src/lib.rs @@ -919,7 +919,7 @@ impl OneSessionHandler for Pallet { } } - fn on_disabled(_i: usize) { + fn on_disabled(_i: u32) { // ignore } } diff --git a/frame/im-online/src/mock.rs b/frame/im-online/src/mock.rs index 92d1fe8e3f8b..1e4d4b43d578 100644 --- a/frame/im-online/src/mock.rs +++ b/frame/im-online/src/mock.rs @@ -27,7 +27,7 @@ use sp_core::H256; use sp_runtime::{ testing::{Header, TestXt, UintAuthorityId}, traits::{BlakeTwo256, ConvertInto, IdentityLookup}, - Perbill, Permill, + Permill, }; use sp_staking::{ offence::{OffenceError, ReportOffence}, @@ -146,10 +146,6 @@ parameter_types! { pub const Offset: u64 = 0; } -parameter_types! { - pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(33); -} - impl pallet_session::Config for Runtime { type ShouldEndSession = pallet_session::PeriodicSessions; type SessionManager = @@ -159,7 +155,6 @@ impl pallet_session::Config for Runtime { type ValidatorIdOf = ConvertInto; type Keys = UintAuthorityId; type Event = Event; - type DisabledValidatorsThreshold = DisabledValidatorsThreshold; type NextSessionRotation = pallet_session::PeriodicSessions; type WeightInfo = (); } diff --git a/frame/offences/benchmarking/src/mock.rs b/frame/offences/benchmarking/src/mock.rs index 6973e25371d4..3097f9b95be3 100644 --- a/frame/offences/benchmarking/src/mock.rs +++ b/frame/offences/benchmarking/src/mock.rs @@ -112,7 +112,7 @@ impl pallet_session::SessionHandler for TestSessionHandler { ) { } - fn on_disabled(_: usize) {} + fn on_disabled(_: u32) {} } parameter_types! { @@ -129,7 +129,6 @@ impl pallet_session::Config for Test { type Event = Event; type ValidatorId = AccountId; type ValidatorIdOf = pallet_staking::StashOf; - type DisabledValidatorsThreshold = (); type WeightInfo = (); } @@ -175,6 +174,7 @@ impl pallet_staking::Config for Test { type EraPayout = pallet_staking::ConvertCurve; type NextNewSession = Session; type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator; + type OffendingValidatorsThreshold = (); type ElectionProvider = onchain::OnChainSequentialPhragmen; type GenesisElectionProvider = Self::ElectionProvider; type SortedListProvider = pallet_staking::UseNominatorsMap; diff --git a/frame/session/benchmarking/src/mock.rs b/frame/session/benchmarking/src/mock.rs index 4d3a1a2d8689..f534cc097e8a 100644 --- a/frame/session/benchmarking/src/mock.rs +++ b/frame/session/benchmarking/src/mock.rs @@ -117,7 +117,7 @@ impl pallet_session::SessionHandler for TestSessionHandler { ) { } - fn on_disabled(_: usize) {} + fn on_disabled(_: u32) {} } impl pallet_session::Config for Test { @@ -129,7 +129,6 @@ impl pallet_session::Config for Test { type Event = Event; type ValidatorId = AccountId; type ValidatorIdOf = pallet_staking::StashOf; - type DisabledValidatorsThreshold = (); type WeightInfo = (); } pallet_staking_reward_curve::build! { @@ -180,6 +179,7 @@ impl pallet_staking::Config for Test { type EraPayout = pallet_staking::ConvertCurve; type NextNewSession = Session; type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator; + type OffendingValidatorsThreshold = (); type ElectionProvider = onchain::OnChainSequentialPhragmen; type GenesisElectionProvider = Self::ElectionProvider; type SortedListProvider = pallet_staking::UseNominatorsMap; diff --git a/frame/session/src/lib.rs b/frame/session/src/lib.rs index 2742d302ce43..10c7ea42b3e9 100644 --- a/frame/session/src/lib.rs +++ b/frame/session/src/lib.rs @@ -116,7 +116,7 @@ pub mod weights; use sp_runtime::{ traits::{AtLeast32BitUnsigned, Convert, Member, One, OpaqueKeys, Zero}, - ConsensusEngineId, KeyTypeId, Perbill, Permill, RuntimeAppPublic, + ConsensusEngineId, KeyTypeId, Permill, RuntimeAppPublic, }; use sp_staking::SessionIndex; use sp_std::{ @@ -298,7 +298,7 @@ pub trait SessionHandler { fn on_before_session_ending() {} /// A validator got disabled. Act accordingly until a new session begins. - fn on_disabled(validator_index: usize); + fn on_disabled(validator_index: u32); } #[impl_trait_for_tuples::impl_for_tuples(1, 30)] @@ -342,7 +342,7 @@ impl SessionHandler for Tuple { for_tuples!( #( Tuple::on_before_session_ending(); )* ) } - fn on_disabled(i: usize) { + fn on_disabled(i: u32) { for_tuples!( #( Tuple::on_disabled(i); )* ) } } @@ -354,7 +354,7 @@ impl SessionHandler for TestSessionHandler { fn on_genesis_session(_: &[(AId, Ks)]) {} fn on_new_session(_: bool, _: &[(AId, Ks)], _: &[(AId, Ks)]) {} fn on_before_session_ending() {} - fn on_disabled(_: usize) {} + fn on_disabled(_: u32) {} } #[frame_support::pallet] @@ -401,12 +401,6 @@ pub mod pallet { /// The keys. type Keys: OpaqueKeys + Member + Parameter + Default + MaybeSerializeDeserialize; - /// The fraction of validators set that is safe to be disabled. - /// - /// After the threshold is reached `disabled` method starts to return true, - /// which in combination with `pallet_staking` forces a new era. - type DisabledValidatorsThreshold: Get; - /// Weight information for extrinsics in this pallet. type WeightInfo: WeightInfo; } @@ -514,7 +508,9 @@ pub mod pallet { /// Indices of disabled validators. /// - /// The set is cleared when `on_session_ending` returns a new set of identities. + /// The vec is always kept sorted so that we can find whether a given validator is + /// disabled using binary search. It gets cleared when `on_session_ending` returns + /// a new set of identities. #[pallet::storage] #[pallet::getter(fn disabled_validators)] pub type DisabledValidators = StorageValue<_, Vec, ValueQuery>; @@ -705,42 +701,34 @@ impl Pallet { T::SessionHandler::on_new_session::(changed, &session_keys, &queued_amalgamated); } - /// Disable the validator of index `i`. - /// - /// Returns `true` if this causes a `DisabledValidatorsThreshold` of validators - /// to be already disabled. - pub fn disable_index(i: usize) -> bool { - let (fire_event, threshold_reached) = >::mutate(|disabled| { - let i = i as u32; + /// Disable the validator of index `i`, returns `false` if the validator was already disabled. + pub fn disable_index(i: u32) -> bool { + if i >= Validators::::decode_len().unwrap_or(0) as u32 { + return false + } + + >::mutate(|disabled| { if let Err(index) = disabled.binary_search(&i) { - let count = >::decode_len().unwrap_or(0) as u32; - let threshold = T::DisabledValidatorsThreshold::get() * count; disabled.insert(index, i); - (true, disabled.len() as u32 > threshold) - } else { - (false, false) + T::SessionHandler::on_disabled(i); + return true } - }); - - if fire_event { - T::SessionHandler::on_disabled(i); - } - threshold_reached + false + }) } /// Disable the validator identified by `c`. (If using with the staking pallet, /// this would be their *stash* account.) /// - /// Returns `Ok(true)` if more than `DisabledValidatorsThreshold` validators in current - /// session is already disabled. - /// If used with the staking pallet it allows to force a new era in such case. - pub fn disable(c: &T::ValidatorId) -> sp_std::result::Result { + /// Returns `false` either if the validator could not be found or it was already + /// disabled. + pub fn disable(c: &T::ValidatorId) -> bool { Self::validators() .iter() .position(|i| i == c) - .map(Self::disable_index) - .ok_or(()) + .map(|i| Self::disable_index(i as u32)) + .unwrap_or(false) } /// Upgrade the key type from some old type to a new type. Supports adding diff --git a/frame/session/src/mock.rs b/frame/session/src/mock.rs index c6b5f6444811..277dec610659 100644 --- a/frame/session/src/mock.rs +++ b/frame/session/src/mock.rs @@ -29,7 +29,6 @@ use sp_runtime::{ impl_opaque_keys, testing::{Header, UintAuthorityId}, traits::{BlakeTwo256, ConvertInto, IdentityLookup}, - Perbill, }; use sp_staking::SessionIndex; @@ -144,7 +143,7 @@ impl SessionHandler for TestSessionHandler { .collect() }); } - fn on_disabled(_validator_index: usize) { + fn on_disabled(_validator_index: u32) { DISABLED.with(|l| *l.borrow_mut() = true) } fn on_before_session_ending() { @@ -269,10 +268,6 @@ impl pallet_timestamp::Config for Test { type WeightInfo = (); } -parameter_types! { - pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(33); -} - impl Config for Test { type ShouldEndSession = TestShouldEndSession; #[cfg(feature = "historical")] @@ -284,7 +279,6 @@ impl Config for Test { type ValidatorIdOf = ConvertInto; type Keys = MockSessionKeys; type Event = Event; - type DisabledValidatorsThreshold = DisabledValidatorsThreshold; type NextSessionRotation = (); type WeightInfo = (); } diff --git a/frame/session/src/tests.rs b/frame/session/src/tests.rs index 47152042d204..42a2dd74fd96 100644 --- a/frame/session/src/tests.rs +++ b/frame/session/src/tests.rs @@ -338,7 +338,7 @@ fn session_keys_generate_output_works_as_set_keys_input() { } #[test] -fn return_true_if_more_than_third_is_disabled() { +fn disable_index_returns_false_if_already_disabled() { new_test_ext().execute_with(|| { set_next_validators(vec![1, 2, 3, 4, 5, 6, 7]); force_new_session(); @@ -347,10 +347,9 @@ fn return_true_if_more_than_third_is_disabled() { force_new_session(); initialize_block(2); + assert_eq!(Session::disable_index(0), true); assert_eq!(Session::disable_index(0), false); - assert_eq!(Session::disable_index(1), false); - assert_eq!(Session::disable_index(2), true); - assert_eq!(Session::disable_index(3), true); + assert_eq!(Session::disable_index(1), true); }); } diff --git a/frame/staking/fuzzer/src/mock.rs b/frame/staking/fuzzer/src/mock.rs index 921e0d3b48d7..d5ca78193b0c 100644 --- a/frame/staking/fuzzer/src/mock.rs +++ b/frame/staking/fuzzer/src/mock.rs @@ -119,7 +119,7 @@ impl pallet_session::SessionHandler for TestSessionHandler { _: &[(AccountId, Ks)], ) {} - fn on_disabled(_: usize) {} + fn on_disabled(_: u32) {} } impl pallet_session::Config for Test { diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 582e9e49bd35..be02e8d91d32 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -619,12 +619,9 @@ pub struct UnappliedSlash { /// /// This is needed because `Staking` sets the `ValidatorIdOf` of the `pallet_session::Config` pub trait SessionInterface: frame_system::Config { - /// Disable a given validator by stash ID. - /// - /// Returns `true` if new era should be forced at the end of this session. - /// This allows preventing a situation where there is too many validators - /// disabled and block production stalls. - fn disable_validator(validator: &AccountId) -> Result; + /// Disable the validator at the given index, returns `false` if the validator was already + /// disabled or the index is out of bounds. + fn disable_validator(validator_index: u32) -> bool; /// Get the validators from session. fn validators() -> Vec; /// Prune historical session tries up to but not including the given index. @@ -645,8 +642,8 @@ where Option<::AccountId>, >, { - fn disable_validator(validator: &::AccountId) -> Result { - >::disable(validator) + fn disable_validator(validator_index: u32) -> bool { + >::disable_index(validator_index) } fn validators() -> Vec<::AccountId> { diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index 06c9be9c01e1..95d397359f8d 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -34,7 +34,7 @@ use sp_runtime::{ traits::{IdentityLookup, Zero}, }; use sp_staking::offence::{OffenceDetails, OnOffenceHandler}; -use std::{cell::RefCell, collections::HashSet}; +use std::cell::RefCell; pub const INIT_TIMESTAMP: u64 = 30_000; pub const BLOCK_TIME: u64 = 1000; @@ -45,10 +45,6 @@ pub(crate) type AccountIndex = u64; pub(crate) type BlockNumber = u64; pub(crate) type Balance = u128; -thread_local! { - static SESSION: RefCell<(Vec, HashSet)> = RefCell::new(Default::default()); -} - /// Another session handler struct to test on_disabled. pub struct OtherSessionHandler; impl OneSessionHandler for OtherSessionHandler { @@ -61,23 +57,14 @@ impl OneSessionHandler for OtherSessionHandler { { } - fn on_new_session<'a, I: 'a>(_: bool, validators: I, _: I) + fn on_new_session<'a, I: 'a>(_: bool, _: I, _: I) where I: Iterator, AccountId: 'a, { - SESSION.with(|x| { - *x.borrow_mut() = (validators.map(|x| x.0.clone()).collect(), HashSet::new()) - }); } - fn on_disabled(validator_index: usize) { - SESSION.with(|d| { - let mut d = d.borrow_mut(); - let value = d.0[validator_index]; - d.1.insert(value); - }) - } + fn on_disabled(_validator_index: u32) {} } impl sp_runtime::BoundToRuntimeAppPublic for OtherSessionHandler { @@ -86,7 +73,12 @@ impl sp_runtime::BoundToRuntimeAppPublic for OtherSessionHandler { pub fn is_disabled(controller: AccountId) -> bool { let stash = Staking::ledger(&controller).unwrap().stash; - SESSION.with(|d| d.borrow().1.contains(&stash)) + let validator_index = match Session::validators().iter().position(|v| *v == stash) { + Some(index) => index as u32, + None => return false, + }; + + Session::disabled_validators().contains(&validator_index) } type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; @@ -171,7 +163,6 @@ impl pallet_balances::Config for Test { } parameter_types! { pub const UncleGenerations: u64 = 0; - pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(25); } sp_runtime::impl_opaque_keys! { pub struct SessionKeys { @@ -186,7 +177,6 @@ impl pallet_session::Config for Test { type Event = Event; type ValidatorId = AccountId; type ValidatorIdOf = crate::StashOf; - type DisabledValidatorsThreshold = DisabledValidatorsThreshold; type NextSessionRotation = pallet_session::PeriodicSessions; type WeightInfo = (); } @@ -224,6 +214,7 @@ parameter_types! { pub const BondingDuration: EraIndex = 3; pub const RewardCurve: &'static PiecewiseLinear<'static> = &I_NPOS; pub const MaxNominatorRewardedPerValidator: u32 = 64; + pub const OffendingValidatorsThreshold: Perbill = Perbill::from_percent(75); } thread_local! { @@ -277,6 +268,7 @@ impl crate::pallet::pallet::Config for Test { type EraPayout = ConvertCurve; type NextNewSession = Session; type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator; + type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type ElectionProvider = onchain::OnChainSequentialPhragmen; type GenesisElectionProvider = Self::ElectionProvider; type WeightInfo = (); @@ -510,10 +502,6 @@ impl ExtBuilder { .assimilate_storage(&mut storage); let mut ext = sp_io::TestExternalities::from(storage); - ext.execute_with(|| { - let validators = Session::validators(); - SESSION.with(|x| *x.borrow_mut() = (validators.clone(), HashSet::new())); - }); if self.initialize_first_session { // We consider all test to start after timestamp is initialized This must be ensured by diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 3ae520872f27..02099d8543d4 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -302,6 +302,13 @@ impl Pallet { Self::start_era(start_session); } } + + // disable all offending validators that have been disabled for the whole era + for (index, disabled) in >::get() { + if disabled { + T::SessionInterface::disable_validator(index); + } + } } /// End a session potentially ending an era. @@ -374,6 +381,9 @@ impl Pallet { // Set ending era reward. >::insert(&active_era.index, validator_payout); T::RewardRemainder::on_unbalanced(T::Currency::issue(rest)); + + // Clear offending validators. + >::kill(); } } diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index dad958ccaea2..8e97a90e0754 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -141,6 +141,10 @@ pub mod pallet { #[pallet::constant] type MaxNominatorRewardedPerValidator: Get; + /// The fraction of the validator set that is safe to be offending. + /// After the threshold is reached a new era will be forced. + type OffendingValidatorsThreshold: Get; + /// Something that can provide a sorted list of voters in a somewhat sorted way. The /// original use case for this was designed with [`pallet_bags_list::Pallet`] in mind. If /// the bags-list is not desired, [`impls::UseNominatorsMap`] is likely the desired option. @@ -437,6 +441,19 @@ pub mod pallet { #[pallet::getter(fn current_planned_session)] pub type CurrentPlannedSession = StorageValue<_, SessionIndex, ValueQuery>; + /// Indices of validators that have offended in the active era and whether they are currently + /// disabled. + /// + /// This value should be a superset of disabled validators since not all offences lead to the + /// validator being disabled (if there was no slash). This is needed to track the percentage of + /// validators that have offended in the current era, ensuring a new era is forced if + /// `OffendingValidatorsThreshold` is reached. The vec is always kept sorted so that we can find + /// whether a given validator has previously offended using binary search. It gets cleared when + /// the era ends. + #[pallet::storage] + #[pallet::getter(fn offending_validators)] + pub type OffendingValidators = StorageValue<_, Vec<(u32, bool)>, ValueQuery>; + /// True if network has been upgraded to this version. /// Storage version of the pallet. /// diff --git a/frame/staking/src/slashing.rs b/frame/staking/src/slashing.rs index 15ca85b4d046..68088d0e0d77 100644 --- a/frame/staking/src/slashing.rs +++ b/frame/staking/src/slashing.rs @@ -56,7 +56,7 @@ use crate::{ use codec::{Decode, Encode}; use frame_support::{ ensure, - traits::{Currency, Imbalance, OnUnbalanced}, + traits::{Currency, Get, Imbalance, OnUnbalanced}, }; use scale_info::TypeInfo; use sp_runtime::{ @@ -278,15 +278,13 @@ pub(crate) fn compute_slash( // not continue in the next election. also end the slashing span. spans.end_span(now); >::chill_stash(stash); - - // make sure to disable validator till the end of this session - if T::SessionInterface::disable_validator(stash).unwrap_or(false) { - // force a new era, to select a new validator set - >::ensure_new_era() - } } } + // add the validator to the offenders list and make sure it is disabled for + // the duration of the era + add_offending_validator::(params.stash, true); + let mut nominators_slashed = Vec::new(); reward_payout += slash_nominators::(params, prior_slash_p, &mut nominators_slashed); @@ -316,13 +314,53 @@ fn kick_out_if_recent(params: SlashParams) { if spans.era_span(params.slash_era).map(|s| s.index) == Some(spans.span_index()) { spans.end_span(params.now); >::chill_stash(params.stash); + } + + // add the validator to the offenders list but since there's no slash being + // applied there's no need to disable the validator + add_offending_validator::(params.stash, false); +} + +/// Add the given validator to the offenders list and optionally disable it. +/// If after adding the validator `OffendingValidatorsThreshold` is reached +/// a new era will be forced. +fn add_offending_validator(stash: &T::AccountId, disable: bool) { + as Store>::OffendingValidators::mutate(|offending| { + let validators = T::SessionInterface::validators(); + let validator_index = match validators.iter().position(|i| i == stash) { + Some(index) => index, + None => return, + }; - // make sure to disable validator till the end of this session - if T::SessionInterface::disable_validator(params.stash).unwrap_or(false) { - // force a new era, to select a new validator set - >::ensure_new_era() + let validator_index_u32 = validator_index as u32; + + match offending.binary_search_by_key(&validator_index_u32, |(index, _)| *index) { + // this is a new offending validator + Err(index) => { + offending.insert(index, (validator_index_u32, disable)); + + let offending_threshold = + T::OffendingValidatorsThreshold::get() * validators.len() as u32; + + if offending.len() >= offending_threshold as usize { + // force a new era, to select a new validator set + >::ensure_new_era() + } + + if disable { + T::SessionInterface::disable_validator(validator_index_u32); + } + }, + Ok(index) => { + if disable && !offending[index].1 { + // the validator had previously offended without being disabled, + // let's make sure we disable it now + offending[index].1 = true; + T::SessionInterface::disable_validator(validator_index_u32); + } + }, } - } + }); } /// Slash nominators. Accepts general parameters and the prior slash percentage of the validator. diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 6f024eb1e6b0..d6d92d5bd57f 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -2318,10 +2318,11 @@ fn slash_in_old_span_does_not_deselect() { 1, ); - // not forcing for zero-slash and previous span. - assert_eq!(Staking::force_era(), Forcing::NotForcing); - assert!(>::contains_key(11)); - assert!(Session::validators().contains(&11)); + // the validator doesn't get chilled again + assert!(::Validators::iter().find(|(stash, _)| *stash == 11).is_some()); + + // but we are still forcing a new era + assert_eq!(Staking::force_era(), Forcing::ForceNew); on_offence_in_era( &[OffenceDetails { @@ -2333,10 +2334,13 @@ fn slash_in_old_span_does_not_deselect() { 1, ); - // or non-zero. - assert_eq!(Staking::force_era(), Forcing::NotForcing); - assert!(>::contains_key(11)); - assert!(Session::validators().contains(&11)); + // the validator doesn't get chilled again + assert!(::Validators::iter().find(|(stash, _)| *stash == 11).is_some()); + + // but it's disabled + assert!(is_disabled(10)); + // and we are still forcing a new era + assert_eq!(Staking::force_era(), Forcing::ForceNew); }); } @@ -2967,6 +2971,132 @@ fn slash_kicks_validators_not_nominators_and_disables_nominator_for_kicked_valid }); } +#[test] +fn non_slashable_offence_doesnt_disable_validator() { + ExtBuilder::default().build_and_execute(|| { + mock::start_active_era(1); + assert_eq_uvec!(Session::validators(), vec![11, 21]); + + let exposure_11 = Staking::eras_stakers(Staking::active_era().unwrap().index, &11); + let exposure_21 = Staking::eras_stakers(Staking::active_era().unwrap().index, &21); + + // offence with no slash associated + on_offence_now( + &[OffenceDetails { offender: (11, exposure_11.clone()), reporters: vec![] }], + &[Perbill::zero()], + ); + + // offence that slashes 25% of the bond + on_offence_now( + &[OffenceDetails { offender: (21, exposure_21.clone()), reporters: vec![] }], + &[Perbill::from_percent(25)], + ); + + // the offence for validator 10 wasn't slashable so it wasn't disabled + assert!(!is_disabled(10)); + // whereas validator 20 gets disabled + assert!(is_disabled(20)); + }); +} + +#[test] +fn offence_threshold_triggers_new_era() { + ExtBuilder::default() + .validator_count(4) + .set_status(41, StakerStatus::Validator) + .build_and_execute(|| { + mock::start_active_era(1); + assert_eq_uvec!(Session::validators(), vec![11, 21, 31, 41]); + + assert_eq!( + ::OffendingValidatorsThreshold::get(), + Perbill::from_percent(75), + ); + + // we have 4 validators and an offending validator threshold of 75%, + // once the third validator commits an offence a new era should be forced + + let exposure_11 = Staking::eras_stakers(Staking::active_era().unwrap().index, &11); + let exposure_21 = Staking::eras_stakers(Staking::active_era().unwrap().index, &21); + let exposure_31 = Staking::eras_stakers(Staking::active_era().unwrap().index, &31); + + on_offence_now( + &[OffenceDetails { offender: (11, exposure_11.clone()), reporters: vec![] }], + &[Perbill::zero()], + ); + + assert_eq!(ForceEra::::get(), Forcing::NotForcing); + + on_offence_now( + &[OffenceDetails { offender: (21, exposure_21.clone()), reporters: vec![] }], + &[Perbill::zero()], + ); + + assert_eq!(ForceEra::::get(), Forcing::NotForcing); + + on_offence_now( + &[OffenceDetails { offender: (31, exposure_31.clone()), reporters: vec![] }], + &[Perbill::zero()], + ); + + assert_eq!(ForceEra::::get(), Forcing::ForceNew); + }); +} + +#[test] +fn disabled_validators_are_kept_disabled_for_whole_era() { + ExtBuilder::default() + .validator_count(4) + .set_status(41, StakerStatus::Validator) + .build_and_execute(|| { + mock::start_active_era(1); + assert_eq_uvec!(Session::validators(), vec![11, 21, 31, 41]); + assert_eq!(::SessionsPerEra::get(), 3); + + let exposure_11 = Staking::eras_stakers(Staking::active_era().unwrap().index, &11); + let exposure_21 = Staking::eras_stakers(Staking::active_era().unwrap().index, &21); + + on_offence_now( + &[OffenceDetails { offender: (11, exposure_11.clone()), reporters: vec![] }], + &[Perbill::zero()], + ); + + on_offence_now( + &[OffenceDetails { offender: (21, exposure_21.clone()), reporters: vec![] }], + &[Perbill::from_percent(25)], + ); + + // validator 10 should not be disabled since the offence wasn't slashable + assert!(!is_disabled(10)); + // validator 20 gets disabled since it got slashed + assert!(is_disabled(20)); + + advance_session(); + + // disabled validators should carry-on through all sessions in the era + assert!(!is_disabled(10)); + assert!(is_disabled(20)); + + // validator 10 should now get disabled + on_offence_now( + &[OffenceDetails { offender: (11, exposure_11.clone()), reporters: vec![] }], + &[Perbill::from_percent(25)], + ); + + advance_session(); + + // and both are disabled in the last session of the era + assert!(is_disabled(10)); + assert!(is_disabled(20)); + + mock::start_active_era(2); + + // when a new era starts disabled validators get cleared + assert!(!is_disabled(10)); + assert!(!is_disabled(20)); + }); +} + #[test] fn claim_reward_at_the_last_era_and_no_double_claim_and_invalid_claim() { // should check that: diff --git a/frame/support/src/traits/validation.rs b/frame/support/src/traits/validation.rs index 11ea5a79f67b..674f2d718fff 100644 --- a/frame/support/src/traits/validation.rs +++ b/frame/support/src/traits/validation.rs @@ -109,7 +109,7 @@ pub trait OneSessionHandler: BoundToRuntimeAppPublic { fn on_before_session_ending() {} /// A validator got disabled. Act accordingly until a new session begins. - fn on_disabled(_validator_index: usize); + fn on_disabled(_validator_index: u32); } /// Something that can estimate at which block the next session rotation will happen (i.e. a new From e904d2ad151670f3d84d98bec1a4d45df8460b2e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Oct 2021 18:45:25 +0200 Subject: [PATCH 037/695] Bump parity-db from 0.3.1 to 0.3.2 (#9944) Bumps [parity-db](https://github.com/paritytech/parity-db) from 0.3.1 to 0.3.2. - [Release notes](https://github.com/paritytech/parity-db/releases) - [Commits](https://github.com/paritytech/parity-db/commits) --- updated-dependencies: - dependency-name: parity-db dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- client/db/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1beacc1313a7..f5ae40784281 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6174,9 +6174,9 @@ dependencies = [ [[package]] name = "parity-db" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241f9c5d25063080f2c02846221f13e1d0e5e18fa00c32c234aad585b744ee55" +checksum = "91b679c6acc14fac74382942e2b73bea441686a33430b951ea03b5aeb6a7f254" dependencies = [ "blake2-rfc", "crc32fast", diff --git a/client/db/Cargo.toml b/client/db/Cargo.toml index 1d3d76ee7a55..f9a81d6ce7ea 100644 --- a/client/db/Cargo.toml +++ b/client/db/Cargo.toml @@ -33,7 +33,7 @@ sc-state-db = { version = "0.10.0-dev", path = "../state-db" } sp-trie = { version = "4.0.0-dev", path = "../../primitives/trie" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-database = { version = "4.0.0-dev", path = "../../primitives/database" } -parity-db = { version = "0.3.1", optional = true } +parity-db = { version = "0.3.2", optional = true } [dev-dependencies] sp-tracing = { version = "4.0.0-dev", path = "../../primitives/tracing" } From 56e513364ddef0317c019cdf1251ba251e9cae0b Mon Sep 17 00:00:00 2001 From: Squirrel Date: Wed, 6 Oct 2021 17:56:37 +0100 Subject: [PATCH 038/695] remove dep on unmaintained difference crate (#9946) --- Cargo.lock | 41 +++++++++++------------------ bin/node/cli/Cargo.toml | 2 +- frame/contracts/Cargo.toml | 2 +- frame/support/Cargo.toml | 2 +- frame/support/test/Cargo.toml | 2 +- primitives/state-machine/Cargo.toml | 2 +- 6 files changed, 20 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f5ae40784281..c3de1d3f7414 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -156,9 +156,9 @@ checksum = "9d6e24d2cce90c53b948c46271bfb053e4bdc2db9b5d3f65e20f8cf28a1b7fc3" [[package]] name = "assert_cmd" -version = "1.0.3" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2475b58cd94eb4f70159f4fd8844ba3b807532fe3131b3373fae060bbe30396" +checksum = "b800c4403e8105d959595e1f88119e78bc12bc874c4336973658b648a746ba93" dependencies = [ "bstr", "doc-comment", @@ -1500,10 +1500,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499" [[package]] -name = "difference" -version = "2.0.0" +name = "difflib" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" +checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" [[package]] name = "digest" @@ -2048,7 +2048,7 @@ dependencies = [ "parity-scale-codec", "parity-util-mem", "paste 1.0.4", - "pretty_assertions 0.6.1", + "pretty_assertions", "scale-info", "serde", "smallvec 1.7.0", @@ -2102,7 +2102,7 @@ dependencies = [ "frame-support-test-pallet", "frame-system", "parity-scale-codec", - "pretty_assertions 0.6.1", + "pretty_assertions", "rustversion", "scale-info", "serde", @@ -5315,7 +5315,7 @@ dependencies = [ "pallet-timestamp", "pallet-utility", "parity-scale-codec", - "pretty_assertions 0.7.2", + "pretty_assertions", "pwasm-utils", "rand 0.7.3", "rand_pcg 0.2.1", @@ -6635,11 +6635,12 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "predicates" -version = "1.0.7" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eeb433456c1a57cc93554dea3ce40b4c19c4057e41c55d4a0f3d84ea71c325aa" +checksum = "c143348f141cc87aab5b950021bac6145d0e5ae754b0591de23244cee42c9308" dependencies = [ - "difference", + "difflib", + "itertools 0.10.0", "predicates-core", ] @@ -6661,21 +6662,9 @@ dependencies = [ [[package]] name = "pretty_assertions" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427" -dependencies = [ - "ansi_term 0.11.0", - "ctor", - "difference", - "output_vt100", -] - -[[package]] -name = "pretty_assertions" -version = "0.7.2" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cab0e7c02cf376875e9335e0ba1da535775beb5450d21e1dffca068818ed98b" +checksum = "ec0cfe1b2403f172ba0f234e500906ee0a3e493fb81092dac23ebefe129301cc" dependencies = [ "ansi_term 0.12.1", "ctor", @@ -9701,7 +9690,7 @@ dependencies = [ "num-traits", "parity-scale-codec", "parking_lot 0.11.1", - "pretty_assertions 0.6.1", + "pretty_assertions", "rand 0.7.3", "smallvec 1.7.0", "sp-core", diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index 1fc7a38b23ca..42bc48e824c6 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -117,7 +117,7 @@ sc-service-test = { version = "2.0.0", path = "../../../client/service/test" } sp-tracing = { version = "4.0.0-dev", path = "../../../primitives/tracing" } futures = "0.3.16" tempfile = "3.1.0" -assert_cmd = "1.0" +assert_cmd = "2.0.1" nix = "0.19" serde_json = "1.0" regex = "1" diff --git a/frame/contracts/Cargo.toml b/frame/contracts/Cargo.toml index 80dc0b05e751..08fd41649689 100644 --- a/frame/contracts/Cargo.toml +++ b/frame/contracts/Cargo.toml @@ -47,7 +47,7 @@ sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primit [dev-dependencies] assert_matches = "1" hex-literal = "0.3" -pretty_assertions = "0.7" +pretty_assertions = "1.0.0" wat = "1" # Substrate Dependencies diff --git a/frame/support/Cargo.toml b/frame/support/Cargo.toml index f4af38db54e2..5f1b24d90a49 100644 --- a/frame/support/Cargo.toml +++ b/frame/support/Cargo.toml @@ -36,7 +36,7 @@ log = { version = "0.4.14", default-features = false } [dev-dependencies] assert_matches = "1.3.0" -pretty_assertions = "0.6.1" +pretty_assertions = "1.0.0" frame-system = { version = "4.0.0-dev", path = "../system" } parity-util-mem = { version = "0.10.0", default-features = false, features = ["primitive-types"] } diff --git a/frame/support/test/Cargo.toml b/frame/support/test/Cargo.toml index 863afceac4a9..594ed6349e74 100644 --- a/frame/support/test/Cargo.toml +++ b/frame/support/test/Cargo.toml @@ -24,7 +24,7 @@ sp-core = { version = "4.0.0-dev", default-features = false, path = "../../../pr sp-std = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/std" } sp-version = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/version" } trybuild = "1.0.43" -pretty_assertions = "0.6.1" +pretty_assertions = "1.0.0" rustversion = "1.0.0" frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" } # The "std" feature for this pallet is never activated on purpose, in order to test construct_runtime error message diff --git a/primitives/state-machine/Cargo.toml b/primitives/state-machine/Cargo.toml index e444ae223a74..903db18a38ca 100644 --- a/primitives/state-machine/Cargo.toml +++ b/primitives/state-machine/Cargo.toml @@ -34,7 +34,7 @@ tracing = { version = "0.1.22", optional = true } [dev-dependencies] hex-literal = "0.3.1" sp-runtime = { version = "4.0.0-dev", path = "../runtime" } -pretty_assertions = "0.6.1" +pretty_assertions = "1.0.0" rand = "0.7.2" [features] From aed8d689c861c9b26e3eb59621320f43e0875cb3 Mon Sep 17 00:00:00 2001 From: Squirrel Date: Thu, 7 Oct 2021 07:15:33 +0100 Subject: [PATCH 039/695] Less deps: Stop using old version of libsecp256k1 (#9947) (Moving further to 0.7 would require upgrading rand first) --- Cargo.lock | 33 +++---------------------- frame/contracts/Cargo.toml | 2 +- frame/contracts/src/benchmarking/mod.rs | 2 +- 3 files changed, 5 insertions(+), 32 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c3de1d3f7414..0a502439b725 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2623,17 +2623,6 @@ dependencies = [ "digest 0.9.0", ] -[[package]] -name = "hmac-drbg" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6e570451493f10f6581b48cdd530413b63ea9e780f544bfd3bdcaa0d89d1a7b" -dependencies = [ - "digest 0.8.1", - "generic-array 0.12.4", - "hmac 0.7.1", -] - [[package]] name = "hmac-drbg" version = "0.3.0" @@ -3787,22 +3776,6 @@ dependencies = [ "libc", ] -[[package]] -name = "libsecp256k1" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc1e2c808481a63dc6da2074752fdd4336a3c8fcc68b83db6f1fd5224ae7962" -dependencies = [ - "arrayref", - "crunchy", - "digest 0.8.1", - "hmac-drbg 0.2.0", - "rand 0.7.3", - "sha2 0.8.2", - "subtle 2.4.0", - "typenum", -] - [[package]] name = "libsecp256k1" version = "0.5.0" @@ -3812,7 +3785,7 @@ dependencies = [ "arrayref", "base64 0.12.3", "digest 0.9.0", - "hmac-drbg 0.3.0", + "hmac-drbg", "libsecp256k1-core 0.2.2", "libsecp256k1-gen-ecmult 0.2.1", "libsecp256k1-gen-genmult 0.2.1", @@ -3831,7 +3804,7 @@ dependencies = [ "arrayref", "base64 0.12.3", "digest 0.9.0", - "hmac-drbg 0.3.0", + "hmac-drbg", "libsecp256k1-core 0.2.2", "libsecp256k1-gen-ecmult 0.2.1", "libsecp256k1-gen-genmult 0.2.1", @@ -5306,7 +5279,7 @@ dependencies = [ "frame-support", "frame-system", "hex-literal", - "libsecp256k1 0.3.5", + "libsecp256k1 0.6.0", "log 0.4.14", "pallet-balances", "pallet-contracts-primitives", diff --git a/frame/contracts/Cargo.toml b/frame/contracts/Cargo.toml index 08fd41649689..c094e0150771 100644 --- a/frame/contracts/Cargo.toml +++ b/frame/contracts/Cargo.toml @@ -28,7 +28,7 @@ smallvec = { version = "1", default-features = false, features = [ wasmi-validation = { version = "0.4", default-features = false } # Only used in benchmarking to generate random contract code -libsecp256k1 = { version = "0.3.5", optional = true, default-features = false, features = ["hmac"] } +libsecp256k1 = { version = "0.6.0", optional = true, default-features = false, features = ["hmac", "static-context"] } rand = { version = "0.7.3", optional = true, default-features = false } rand_pcg = { version = "0.2", optional = true } diff --git a/frame/contracts/src/benchmarking/mod.rs b/frame/contracts/src/benchmarking/mod.rs index e382e616f27f..5c753c2d9555 100644 --- a/frame/contracts/src/benchmarking/mod.rs +++ b/frame/contracts/src/benchmarking/mod.rs @@ -1425,7 +1425,7 @@ benchmarks! { let message_hash = sp_io::hashing::blake2_256("Hello world".as_bytes()); let signatures = (0..r * API_BENCHMARK_BATCH_SIZE) .map(|i| { - use secp256k1::{SecretKey, Message, sign}; + use libsecp256k1::{SecretKey, Message, sign}; let private_key = SecretKey::random(&mut rng); let (signature, recovery_id) = sign(&Message::parse(&message_hash), &private_key); From f494bf62d1af52c04bbb2b53aa03f726b42998e0 Mon Sep 17 00:00:00 2001 From: Squirrel Date: Thu, 7 Oct 2021 10:08:57 +0100 Subject: [PATCH 040/695] Avoid hangs in tests (#9949) * Avoid hangs in tests * set timeout for 10 mins. --- client/network/test/src/lib.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/client/network/test/src/lib.rs b/client/network/test/src/lib.rs index bb49cef8c642..e547fa376b3f 100644 --- a/client/network/test/src/lib.rs +++ b/client/network/test/src/lib.rs @@ -28,8 +28,10 @@ use std::{ pin::Pin, sync::Arc, task::{Context as FutureContext, Poll}, + time::Duration, }; +use async_std::future::timeout; use futures::{future::BoxFuture, prelude::*}; use libp2p::{build_multiaddr, PeerId}; use log::trace; @@ -1017,10 +1019,13 @@ where /// Blocks the current thread until we are sync'ed. /// /// Calls `poll_until_sync` repeatedly. + /// (If we've not synced within 10 mins then panic rather than hang.) fn block_until_sync(&mut self) { - futures::executor::block_on(futures::future::poll_fn::<(), _>(|cx| { - self.poll_until_sync(cx) - })); + futures::executor::block_on(timeout( + Duration::from_secs(10 * 60), + futures::future::poll_fn::<(), _>(|cx| self.poll_until_sync(cx)), + )) + .expect("sync didn't happen within 10 mins"); } /// Blocks the current thread until there are no pending packets. From 97818e44c6d3f829fa65e8ab5fc06a8ca9d266c0 Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Thu, 7 Oct 2021 11:31:39 +0200 Subject: [PATCH 041/695] Warp sync part II (#9284) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Gap sync * Gap epoch test * Simplified network requests * Update client/db/src/utils.rs Co-authored-by: cheme * Fixed v1 migration and added some comments * Next epoch is always regular * Removed fork tree change * Apply suggestions from code review Co-authored-by: Bastian Köcher * Added a comment and converted assert to error Co-authored-by: cheme Co-authored-by: Bastian Köcher --- bin/node-template/node/src/service.rs | 2 + bin/node/cli/src/service.rs | 2 + client/api/src/in_mem.rs | 1 + .../authority-discovery/src/worker/tests.rs | 1 + client/cli/src/commands/check_block_cmd.rs | 4 +- client/cli/src/commands/import_blocks_cmd.rs | 4 +- client/consensus/babe/src/aux_schema.rs | 22 +- client/consensus/babe/src/lib.rs | 11 +- client/consensus/epochs/src/lib.rs | 326 ++++++++++++++++-- client/consensus/epochs/src/migration.rs | 27 +- client/db/src/lib.rs | 49 ++- client/db/src/light.rs | 1 + client/db/src/utils.rs | 12 +- client/finality-grandpa/src/authorities.rs | 25 +- client/finality-grandpa/src/import.rs | 26 ++ client/finality-grandpa/src/warp_proof.rs | 62 ++-- client/informant/src/display.rs | 12 +- client/network/src/lib.rs | 2 +- client/network/src/protocol.rs | 8 +- client/network/src/protocol/sync.rs | 222 +++++++++--- client/network/src/protocol/sync/state.rs | 6 +- client/network/src/protocol/sync/warp.rs | 29 +- client/network/src/warp_request_handler.rs | 5 +- client/network/test/src/lib.rs | 43 ++- client/network/test/src/sync.rs | 32 ++ client/service/src/chain_ops/check_block.rs | 4 +- client/service/src/chain_ops/import_blocks.rs | 8 +- client/service/src/client/client.rs | 23 +- primitives/blockchain/src/backend.rs | 2 + 29 files changed, 801 insertions(+), 170 deletions(-) diff --git a/bin/node-template/node/src/service.rs b/bin/node-template/node/src/service.rs index 0f09ef436aca..a70dd877ff35 100644 --- a/bin/node-template/node/src/service.rs +++ b/bin/node-template/node/src/service.rs @@ -179,6 +179,7 @@ pub fn new_full(mut config: Configuration) -> Result let warp_sync = Arc::new(sc_finality_grandpa::warp_proof::NetworkProvider::new( backend.clone(), grandpa_link.shared_authority_set().clone(), + Vec::default(), )); let (network, system_rpc_tx, network_starter) = @@ -409,6 +410,7 @@ pub fn new_light(mut config: Configuration) -> Result let warp_sync = Arc::new(sc_finality_grandpa::warp_proof::NetworkProvider::new( backend.clone(), grandpa_link.shared_authority_set().clone(), + Vec::default(), )); let (network, system_rpc_tx, network_starter) = diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index b1a3bd472259..ec5497ab47d9 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -244,6 +244,7 @@ pub fn new_full_base( let warp_sync = Arc::new(grandpa::warp_proof::NetworkProvider::new( backend.clone(), import_setup.1.shared_authority_set().clone(), + Vec::default(), )); let (network, system_rpc_tx, network_starter) = @@ -531,6 +532,7 @@ pub fn new_light_base( let warp_sync = Arc::new(grandpa::warp_proof::NetworkProvider::new( backend.clone(), grandpa_link.shared_authority_set().clone(), + Vec::default(), )); let (network, system_rpc_tx, network_starter) = diff --git a/client/api/src/in_mem.rs b/client/api/src/in_mem.rs index e8fce19f8124..2f4327dfc4e4 100644 --- a/client/api/src/in_mem.rs +++ b/client/api/src/in_mem.rs @@ -369,6 +369,7 @@ impl HeaderBackend for Blockchain { None }, number_leaves: storage.leaves.count(), + block_gap: None, } } diff --git a/client/authority-discovery/src/worker/tests.rs b/client/authority-discovery/src/worker/tests.rs index f10d2751ccd3..3c1610256f5b 100644 --- a/client/authority-discovery/src/worker/tests.rs +++ b/client/authority-discovery/src/worker/tests.rs @@ -73,6 +73,7 @@ impl HeaderBackend for TestApi { genesis_hash: Default::default(), number_leaves: Default::default(), finalized_state: None, + block_gap: None, } } diff --git a/client/cli/src/commands/check_block_cmd.rs b/client/cli/src/commands/check_block_cmd.rs index 07a76319dca3..de0d1132ce8b 100644 --- a/client/cli/src/commands/check_block_cmd.rs +++ b/client/cli/src/commands/check_block_cmd.rs @@ -21,7 +21,7 @@ use crate::{ params::{BlockNumberOrHash, ImportParams, SharedParams}, CliConfiguration, }; -use sc_client_api::{BlockBackend, UsageProvider}; +use sc_client_api::{BlockBackend, HeaderBackend}; use sp_runtime::traits::{Block as BlockT, Header as HeaderT}; use std::{fmt::Debug, str::FromStr, sync::Arc}; use structopt::StructOpt; @@ -53,7 +53,7 @@ impl CheckBlockCmd { pub async fn run(&self, client: Arc, import_queue: IQ) -> error::Result<()> where B: BlockT + for<'de> serde::Deserialize<'de>, - C: BlockBackend + UsageProvider + Send + Sync + 'static, + C: BlockBackend + HeaderBackend + Send + Sync + 'static, IQ: sc_service::ImportQueue + 'static, B::Hash: FromStr, ::Err: Debug, diff --git a/client/cli/src/commands/import_blocks_cmd.rs b/client/cli/src/commands/import_blocks_cmd.rs index 9b211b88d556..19187f285962 100644 --- a/client/cli/src/commands/import_blocks_cmd.rs +++ b/client/cli/src/commands/import_blocks_cmd.rs @@ -21,7 +21,7 @@ use crate::{ params::{ImportParams, SharedParams}, CliConfiguration, }; -use sc_client_api::UsageProvider; +use sc_client_api::HeaderBackend; use sc_service::chain_ops::import_blocks; use sp_runtime::traits::Block as BlockT; use std::{ @@ -68,7 +68,7 @@ impl ImportBlocksCmd { /// Run the import-blocks command pub async fn run(&self, client: Arc, import_queue: IQ) -> error::Result<()> where - C: UsageProvider + Send + Sync + 'static, + C: HeaderBackend + Send + Sync + 'static, B: BlockT + for<'de> serde::Deserialize<'de>, IQ: sc_service::ImportQueue + 'static, { diff --git a/client/consensus/babe/src/aux_schema.rs b/client/consensus/babe/src/aux_schema.rs index b18220c3e360..d5b8a218a5a3 100644 --- a/client/consensus/babe/src/aux_schema.rs +++ b/client/consensus/babe/src/aux_schema.rs @@ -23,14 +23,17 @@ use log::info; use crate::{migration::EpochV0, Epoch}; use sc_client_api::backend::AuxStore; -use sc_consensus_epochs::{migration::EpochChangesForV0, EpochChangesFor, SharedEpochChanges}; +use sc_consensus_epochs::{ + migration::{EpochChangesV0For, EpochChangesV1For}, + EpochChangesFor, SharedEpochChanges, +}; use sp_blockchain::{Error as ClientError, Result as ClientResult}; use sp_consensus_babe::{BabeBlockWeight, BabeGenesisConfiguration}; use sp_runtime::traits::Block as BlockT; const BABE_EPOCH_CHANGES_VERSION: &[u8] = b"babe_epoch_changes_version"; const BABE_EPOCH_CHANGES_KEY: &[u8] = b"babe_epoch_changes"; -const BABE_EPOCH_CHANGES_CURRENT_VERSION: u32 = 2; +const BABE_EPOCH_CHANGES_CURRENT_VERSION: u32 = 3; /// The aux storage key used to store the block weight of the given block hash. pub fn block_weight_key(block_hash: H) -> Vec { @@ -60,11 +63,16 @@ pub fn load_epoch_changes( let maybe_epoch_changes = match version { None => - load_decode::<_, EpochChangesForV0>(backend, BABE_EPOCH_CHANGES_KEY)? + load_decode::<_, EpochChangesV0For>(backend, BABE_EPOCH_CHANGES_KEY)? .map(|v0| v0.migrate().map(|_, _, epoch| epoch.migrate(config))), Some(1) => - load_decode::<_, EpochChangesFor>(backend, BABE_EPOCH_CHANGES_KEY)? - .map(|v1| v1.map(|_, _, epoch| epoch.migrate(config))), + load_decode::<_, EpochChangesV1For>(backend, BABE_EPOCH_CHANGES_KEY)? + .map(|v1| v1.migrate().map(|_, _, epoch| epoch.migrate(config))), + Some(2) => { + // v2 still uses `EpochChanges` v1 format but with a different `Epoch` type. + load_decode::<_, EpochChangesV1For>(backend, BABE_EPOCH_CHANGES_KEY)? + .map(|v2| v2.migrate()) + }, Some(BABE_EPOCH_CHANGES_CURRENT_VERSION) => load_decode::<_, EpochChangesFor>(backend, BABE_EPOCH_CHANGES_KEY)?, Some(other) => @@ -164,7 +172,7 @@ mod test { .insert_aux( &[( BABE_EPOCH_CHANGES_KEY, - &EpochChangesForV0::::from_raw(v0_tree).encode()[..], + &EpochChangesV0For::::from_raw(v0_tree).encode()[..], )], &[], ) @@ -202,6 +210,6 @@ mod test { client.insert_aux(values, &[]).unwrap(); }); - assert_eq!(load_decode::<_, u32>(&client, BABE_EPOCH_CHANGES_VERSION).unwrap(), Some(2)); + assert_eq!(load_decode::<_, u32>(&client, BABE_EPOCH_CHANGES_VERSION).unwrap(), Some(3)); } } diff --git a/client/consensus/babe/src/lib.rs b/client/consensus/babe/src/lib.rs index a0b6bde025b3..1fde78804115 100644 --- a/client/consensus/babe/src/lib.rs +++ b/client/consensus/babe/src/lib.rs @@ -1578,8 +1578,12 @@ where *block.header.parent_hash(), next_epoch, ) - .map_err(|e| ConsensusError::ClientImport(format!("{:?}", e)))?; - + .map_err(|e| { + ConsensusError::ClientImport(format!( + "Error importing epoch changes: {:?}", + e + )) + })?; Ok(()) }; @@ -1667,6 +1671,9 @@ where Client: HeaderBackend + HeaderMetadata, { let info = client.info(); + if info.block_gap.is_none() { + epoch_changes.clear_gap(); + } let finalized_slot = { let finalized_header = client diff --git a/client/consensus/epochs/src/lib.rs b/client/consensus/epochs/src/lib.rs index f3cfc55bae69..661cb900ae6e 100644 --- a/client/consensus/epochs/src/lib.rs +++ b/client/consensus/epochs/src/lib.rs @@ -78,11 +78,11 @@ where /// /// Once an epoch is created, it must have a known `start_slot` and `end_slot`, which cannot be /// changed. Consensus engine may modify any other data in the epoch, if needed. -pub trait Epoch { +pub trait Epoch: std::fmt::Debug { /// Descriptor for the next epoch. type NextEpochDescriptor; /// Type of the slot number. - type Slot: Ord + Copy; + type Slot: Ord + Copy + std::fmt::Debug; /// The starting slot of the epoch. fn start_slot(&self) -> Self::Slot; @@ -228,7 +228,7 @@ impl ViableEpochDescriptor { } /// Persisted epoch stored in EpochChanges. -#[derive(Clone, Encode, Decode)] +#[derive(Clone, Encode, Decode, Debug)] pub enum PersistedEpoch { /// Genesis persisted epoch data. epoch_0, epoch_1. Genesis(E, E), @@ -246,8 +246,23 @@ impl<'a, E: Epoch> From<&'a PersistedEpoch> for PersistedEpochHeader { } } +impl PersistedEpoch { + /// Map the epoch to a different type using a conversion function. + pub fn map(self, h: &Hash, n: &Number, f: &mut F) -> PersistedEpoch + where + B: Epoch, + F: FnMut(&Hash, &Number, E) -> B, + { + match self { + PersistedEpoch::Genesis(epoch_0, epoch_1) => + PersistedEpoch::Genesis(f(h, n, epoch_0), f(h, n, epoch_1)), + PersistedEpoch::Regular(epoch_n) => PersistedEpoch::Regular(f(h, n, epoch_n)), + } + } +} + /// Persisted epoch header stored in ForkTree. -#[derive(Encode, Decode, PartialEq, Eq)] +#[derive(Encode, Decode, PartialEq, Eq, Debug)] pub enum PersistedEpochHeader { /// Genesis persisted epoch header. epoch_0, epoch_1. Genesis(EpochHeader, EpochHeader), @@ -264,6 +279,25 @@ impl Clone for PersistedEpochHeader { } } +impl PersistedEpochHeader { + /// Map the epoch header to a different type. + pub fn map(self) -> PersistedEpochHeader + where + B: Epoch, + { + match self { + PersistedEpochHeader::Genesis(epoch_0, epoch_1) => PersistedEpochHeader::Genesis( + EpochHeader { start_slot: epoch_0.start_slot, end_slot: epoch_0.end_slot }, + EpochHeader { start_slot: epoch_1.start_slot, end_slot: epoch_1.end_slot }, + ), + PersistedEpochHeader::Regular(epoch_n) => PersistedEpochHeader::Regular(EpochHeader { + start_slot: epoch_n.start_slot, + end_slot: epoch_n.end_slot, + }), + } + } +} + /// A fresh, incremented epoch to import into the underlying fork-tree. /// /// Create this with `ViableEpoch::increment`. @@ -279,6 +313,106 @@ impl AsRef for IncrementedEpoch { } } +/// A pair of epochs for the gap block download validation. +/// Block gap is created after the warp sync is complete. Blocks +/// are imported both at the tip of the chain and at the start of the gap. +/// This holds a pair of epochs that are required to validate headers +/// at the start of the gap. Since gap download does not allow forks we don't +/// need to keep a tree of epochs. +#[derive(Clone, Encode, Decode, Debug)] +pub struct GapEpochs { + current: (Hash, Number, PersistedEpoch), + next: Option<(Hash, Number, E)>, +} + +impl GapEpochs +where + Hash: Copy + PartialEq + std::fmt::Debug, + Number: Copy + PartialEq + std::fmt::Debug, + E: Epoch, +{ + /// Check if given slot matches one of the gap epochs. + /// Returns epoch identifier if it does. + fn matches( + &self, + slot: E::Slot, + ) -> Option<(Hash, Number, EpochHeader, EpochIdentifierPosition)> { + match &self.current { + (_, _, PersistedEpoch::Genesis(epoch_0, _)) + if slot >= epoch_0.start_slot() && slot < epoch_0.end_slot() => + return Some(( + self.current.0, + self.current.1, + epoch_0.into(), + EpochIdentifierPosition::Genesis0, + )), + (_, _, PersistedEpoch::Genesis(_, epoch_1)) + if slot >= epoch_1.start_slot() && slot < epoch_1.end_slot() => + return Some(( + self.current.0, + self.current.1, + epoch_1.into(), + EpochIdentifierPosition::Genesis1, + )), + (_, _, PersistedEpoch::Regular(epoch_n)) + if slot >= epoch_n.start_slot() && slot < epoch_n.end_slot() => + return Some(( + self.current.0, + self.current.1, + epoch_n.into(), + EpochIdentifierPosition::Regular, + )), + _ => {}, + }; + match &self.next { + Some((h, n, epoch_n)) if slot >= epoch_n.start_slot() && slot < epoch_n.end_slot() => + Some((*h, *n, epoch_n.into(), EpochIdentifierPosition::Regular)), + _ => None, + } + } + + /// Returns epoch data if it matches given identifier. + pub fn epoch(&self, id: &EpochIdentifier) -> Option<&E> { + match (&self.current, &self.next) { + ((h, n, e), _) if h == &id.hash && n == &id.number => match e { + PersistedEpoch::Genesis(ref epoch_0, _) + if id.position == EpochIdentifierPosition::Genesis0 => + Some(epoch_0), + PersistedEpoch::Genesis(_, ref epoch_1) + if id.position == EpochIdentifierPosition::Genesis1 => + Some(epoch_1), + PersistedEpoch::Regular(ref epoch_n) + if id.position == EpochIdentifierPosition::Regular => + Some(epoch_n), + _ => None, + }, + (_, Some((h, n, e))) + if h == &id.hash && + n == &id.number && id.position == EpochIdentifierPosition::Regular => + Some(e), + _ => None, + } + } + + /// Import a new gap epoch, potentially replacing an old epoch. + fn import(&mut self, slot: E::Slot, hash: Hash, number: Number, epoch: E) -> Result<(), E> { + match (&mut self.current, &mut self.next) { + ((_, _, PersistedEpoch::Genesis(_, epoch_1)), _) if slot == epoch_1.end_slot() => { + self.next = Some((hash, number, epoch)); + Ok(()) + }, + (_, Some((_, _, epoch_n))) if slot == epoch_n.end_slot() => { + let (cur_h, cur_n, cur_epoch) = + self.next.take().expect("Already matched as `Some`"); + self.current = (cur_h, cur_n, PersistedEpoch::Regular(cur_epoch)); + self.next = Some((hash, number, epoch)); + Ok(()) + }, + _ => Err(epoch), + } + } +} + /// Tree of all epoch changes across all *seen* forks. Data stored in tree is /// the hash and block number of the block signaling the epoch change, and the /// epoch that was signalled at that block. @@ -294,10 +428,14 @@ impl AsRef for IncrementedEpoch { /// same DAG entry, pinned to a specific block #1. /// /// Further epochs (epoch_2, ..., epoch_n) each get their own entry. -#[derive(Clone, Encode, Decode)] +/// +/// Also maintains a pair of epochs for the start of the gap, +/// as long as there's an active gap download after a warp sync. +#[derive(Clone, Encode, Decode, Debug)] pub struct EpochChanges { inner: ForkTree>, epochs: BTreeMap<(Hash, Number), PersistedEpoch>, + gap: Option>, } // create a fake header hash which hasn't been included in the chain. @@ -315,14 +453,14 @@ where Number: Ord, { fn default() -> Self { - EpochChanges { inner: ForkTree::new(), epochs: BTreeMap::new() } + EpochChanges { inner: ForkTree::new(), epochs: BTreeMap::new(), gap: None } } } impl EpochChanges where - Hash: PartialEq + Ord + AsRef<[u8]> + AsMut<[u8]> + Copy, - Number: Ord + One + Zero + Add + Sub + Copy, + Hash: PartialEq + Ord + AsRef<[u8]> + AsMut<[u8]> + Copy + std::fmt::Debug, + Number: Ord + One + Zero + Add + Sub + Copy + std::fmt::Debug, { /// Create a new epoch change. pub fn new() -> Self { @@ -335,6 +473,11 @@ where self.inner.rebalance() } + /// Clear gap epochs if any. + pub fn clear_gap(&mut self) { + self.gap = None; + } + /// Map the epoch changes from one storing data to a different one. pub fn map(self, mut f: F) -> EpochChanges where @@ -342,31 +485,15 @@ where F: FnMut(&Hash, &Number, E) -> B, { EpochChanges { - inner: self.inner.map(&mut |_, _, header| match header { - PersistedEpochHeader::Genesis(epoch_0, epoch_1) => PersistedEpochHeader::Genesis( - EpochHeader { start_slot: epoch_0.start_slot, end_slot: epoch_0.end_slot }, - EpochHeader { start_slot: epoch_1.start_slot, end_slot: epoch_1.end_slot }, - ), - PersistedEpochHeader::Regular(epoch_n) => - PersistedEpochHeader::Regular(EpochHeader { - start_slot: epoch_n.start_slot, - end_slot: epoch_n.end_slot, - }), + inner: self.inner.map(&mut |_, _, header: PersistedEpochHeader| header.map()), + gap: self.gap.map(|GapEpochs { current: (h, n, header), next }| GapEpochs { + current: (h, n, header.map(&h, &n, &mut f)), + next: next.map(|(h, n, e)| (h, n, f(&h, &n, e))), }), epochs: self .epochs .into_iter() - .map(|((hash, number), epoch)| { - let bepoch = match epoch { - PersistedEpoch::Genesis(epoch_0, epoch_1) => PersistedEpoch::Genesis( - f(&hash, &number, epoch_0), - f(&hash, &number, epoch_1), - ), - PersistedEpoch::Regular(epoch_n) => - PersistedEpoch::Regular(f(&hash, &number, epoch_n)), - }; - ((hash, number), bepoch) - }) + .map(|((hash, number), epoch)| ((hash, number), epoch.map(&hash, &number, &mut f))) .collect(), } } @@ -402,6 +529,9 @@ where /// Get a reference to an epoch with given identifier. pub fn epoch(&self, id: &EpochIdentifier) -> Option<&E> { + if let Some(e) = &self.gap.as_ref().and_then(|gap| gap.epoch(id)) { + return Some(e) + } self.epochs.get(&(id.hash, id.number)).and_then(|v| match v { PersistedEpoch::Genesis(ref epoch_0, _) if id.position == EpochIdentifierPosition::Genesis0 => @@ -537,6 +667,15 @@ where return Ok(Some(ViableEpochDescriptor::UnimportedGenesis(slot))) } + if let Some(gap) = &self.gap { + if let Some((hash, number, hdr, position)) = gap.matches(slot) { + return Ok(Some(ViableEpochDescriptor::Signaled( + EpochIdentifier { position, hash, number }, + hdr, + ))) + } + } + // We want to find the deepest node in the tree which is an ancestor // of our block and where the start slot of the epoch was before the // slot of our block. The genesis special-case doesn't need to look @@ -598,13 +737,30 @@ where ) -> Result<(), fork_tree::Error> { let is_descendent_of = descendent_of_builder.build_is_descendent_of(Some((hash, parent_hash))); - let header = PersistedEpochHeader::::from(&epoch.0); + let slot = epoch.as_ref().start_slot(); + let IncrementedEpoch(mut epoch) = epoch; + let header = PersistedEpochHeader::::from(&epoch); + + if let Some(gap) = &mut self.gap { + if let PersistedEpoch::Regular(e) = epoch { + epoch = match gap.import(slot, hash.clone(), number.clone(), e) { + Ok(()) => return Ok(()), + Err(e) => PersistedEpoch::Regular(e), + } + } + } else if !self.epochs.is_empty() && matches!(epoch, PersistedEpoch::Genesis(_, _)) { + // There's a genesis epoch imported when we already have an active epoch. + // This happens after the warp sync as the ancient blocks download start. + // We need to start tracking gap epochs here. + self.gap = Some(GapEpochs { current: (hash, number, epoch), next: None }); + return Ok(()) + } let res = self.inner.import(hash, number, header, &is_descendent_of); match res { Ok(_) | Err(fork_tree::Error::Duplicate) => { - self.epochs.insert((hash, number), epoch.0); + self.epochs.insert((hash, number), epoch); Ok(()) }, Err(e) => Err(e), @@ -916,4 +1072,112 @@ mod tests { assert!(epoch_for_x_child_before_genesis.is_none()); } } + + #[test] + fn gap_epochs_advance() { + // 0 - 1 - 2 - 3 - .... 42 - 43 + let is_descendent_of = |base: &Hash, block: &Hash| -> Result { + match (base, *block) { + (b"0", _) => Ok(true), + (b"1", b) => Ok(b == *b"0"), + (b"2", b) => Ok(b == *b"1"), + (b"3", b) => Ok(b == *b"2"), + _ => Ok(false), + } + }; + + let duration = 100; + + let make_genesis = |slot| Epoch { start_slot: slot, duration }; + + let mut epoch_changes = EpochChanges::new(); + let next_descriptor = (); + + let epoch42 = Epoch { start_slot: 42, duration: 100 }; + let epoch43 = Epoch { start_slot: 43, duration: 100 }; + epoch_changes.reset(*b"0", *b"1", 4200, epoch42, epoch43); + assert!(epoch_changes.gap.is_none()); + + // Import a new genesis epoch, this should crate the gap. + let genesis_epoch_a_descriptor = epoch_changes + .epoch_descriptor_for_child_of(&is_descendent_of, b"0", 0, 100) + .unwrap() + .unwrap(); + + let incremented_epoch = epoch_changes + .viable_epoch(&genesis_epoch_a_descriptor, &make_genesis) + .unwrap() + .increment(next_descriptor.clone()); + + epoch_changes + .import(&is_descendent_of, *b"1", 1, *b"0", incremented_epoch) + .unwrap(); + assert!(epoch_changes.gap.is_some()); + + let genesis_epoch = epoch_changes + .epoch_descriptor_for_child_of(&is_descendent_of, b"0", 0, 100) + .unwrap() + .unwrap(); + + assert_eq!(genesis_epoch, ViableEpochDescriptor::UnimportedGenesis(100)); + + // Import more epochs and check that gap advances. + let import_epoch_1 = + epoch_changes.viable_epoch(&genesis_epoch, &make_genesis).unwrap().increment(()); + + let epoch_1 = import_epoch_1.as_ref().clone(); + epoch_changes + .import(&is_descendent_of, *b"1", 1, *b"0", import_epoch_1) + .unwrap(); + let genesis_epoch_data = epoch_changes.epoch_data(&genesis_epoch, &make_genesis).unwrap(); + let end_slot = genesis_epoch_data.end_slot(); + let x = epoch_changes + .epoch_data_for_child_of(&is_descendent_of, b"1", 1, end_slot, &make_genesis) + .unwrap() + .unwrap(); + + assert_eq!(x, epoch_1); + assert_eq!(epoch_changes.gap.as_ref().unwrap().current.0, *b"1"); + assert!(epoch_changes.gap.as_ref().unwrap().next.is_none()); + + let epoch_1_desriptor = epoch_changes + .epoch_descriptor_for_child_of(&is_descendent_of, b"1", 1, end_slot) + .unwrap() + .unwrap(); + let epoch_1 = epoch_changes.epoch_data(&epoch_1_desriptor, &make_genesis).unwrap(); + let import_epoch_2 = epoch_changes + .viable_epoch(&epoch_1_desriptor, &make_genesis) + .unwrap() + .increment(()); + let epoch_2 = import_epoch_2.as_ref().clone(); + epoch_changes + .import(&is_descendent_of, *b"2", 2, *b"1", import_epoch_2) + .unwrap(); + + let end_slot = epoch_1.end_slot(); + let x = epoch_changes + .epoch_data_for_child_of(&is_descendent_of, b"2", 2, end_slot, &make_genesis) + .unwrap() + .unwrap(); + assert_eq!(epoch_changes.gap.as_ref().unwrap().current.0, *b"1"); + assert_eq!(epoch_changes.gap.as_ref().unwrap().next.as_ref().unwrap().0, *b"2"); + assert_eq!(x, epoch_2); + + let epoch_2_desriptor = epoch_changes + .epoch_descriptor_for_child_of(&is_descendent_of, b"2", 2, end_slot) + .unwrap() + .unwrap(); + let import_epoch_3 = epoch_changes + .viable_epoch(&epoch_2_desriptor, &make_genesis) + .unwrap() + .increment(()); + epoch_changes + .import(&is_descendent_of, *b"3", 3, *b"2", import_epoch_3) + .unwrap(); + + assert_eq!(epoch_changes.gap.as_ref().unwrap().current.0, *b"2"); + + epoch_changes.clear_gap(); + assert!(epoch_changes.gap.is_none()); + } } diff --git a/client/consensus/epochs/src/migration.rs b/client/consensus/epochs/src/migration.rs index 49e08240df8c..e4b685c6ffb1 100644 --- a/client/consensus/epochs/src/migration.rs +++ b/client/consensus/epochs/src/migration.rs @@ -30,9 +30,19 @@ pub struct EpochChangesV0 { inner: ForkTree>, } -/// Type alias for legacy definition of epoch changes. -pub type EpochChangesForV0 = +/// Legacy definition of epoch changes. +#[derive(Clone, Encode, Decode)] +pub struct EpochChangesV1 { + inner: ForkTree>, + epochs: BTreeMap<(Hash, Number), PersistedEpoch>, +} + +/// Type alias for v0 definition of epoch changes. +pub type EpochChangesV0For = EpochChangesV0<::Hash, NumberFor, Epoch>; +/// Type alias for v1 and v2 definition of epoch changes. +pub type EpochChangesV1For = + EpochChangesV1<::Hash, NumberFor, Epoch>; impl EpochChangesV0 where @@ -54,6 +64,17 @@ where header }); - EpochChanges { inner, epochs } + EpochChanges { inner, epochs, gap: None } + } +} + +impl EpochChangesV1 +where + Hash: PartialEq + Ord + Copy, + Number: Ord + Copy, +{ + /// Migrate the type into current epoch changes definition. + pub fn migrate(self) -> EpochChanges { + EpochChanges { inner: self.inner, epochs: self.epochs, gap: None } } } diff --git a/client/db/src/lib.rs b/client/db/src/lib.rs index 66adb64c0109..549ef4012a73 100644 --- a/client/db/src/lib.rs +++ b/client/db/src/lib.rs @@ -502,6 +502,11 @@ impl BlockchainDb { } } + fn update_block_gap(&self, gap: Option<(NumberFor, NumberFor)>) { + let mut meta = self.meta.write(); + meta.block_gap = gap; + } + // Get block changes trie root, if available. fn changes_trie_root(&self, block: BlockId) -> ClientResult> { self.header(block).map(|header| { @@ -538,6 +543,7 @@ impl sc_client_api::blockchain::HeaderBackend for Blockcha finalized_number: meta.finalized_number, finalized_state: meta.finalized_state.clone(), number_leaves: self.leaves.read().count(), + block_gap: meta.block_gap, } } @@ -1388,9 +1394,10 @@ impl Backend { operation.apply_offchain(&mut transaction); let mut meta_updates = Vec::with_capacity(operation.finalized_blocks.len()); - let mut last_finalized_hash = self.blockchain.meta.read().finalized_hash; - let mut last_finalized_num = self.blockchain.meta.read().finalized_number; - let best_num = self.blockchain.meta.read().best_number; + let (best_num, mut last_finalized_hash, mut last_finalized_num, mut block_gap) = { + let meta = self.blockchain.meta.read(); + (meta.best_number, meta.finalized_hash, meta.finalized_number, meta.block_gap.clone()) + }; let mut changes_trie_cache_ops = None; for (block, justification) in operation.finalized_blocks { @@ -1639,6 +1646,41 @@ impl Backend { children, ); } + + if let Some((mut start, end)) = block_gap { + if number == start { + start += One::one(); + utils::insert_number_to_key_mapping( + &mut transaction, + columns::KEY_LOOKUP, + number, + hash, + )?; + } + if start > end { + transaction.remove(columns::META, meta_keys::BLOCK_GAP); + block_gap = None; + debug!(target: "db", "Removed block gap."); + } else { + block_gap = Some((start, end)); + debug!(target: "db", "Update block gap. {:?}", block_gap); + transaction.set( + columns::META, + meta_keys::BLOCK_GAP, + &(start, end).encode(), + ); + } + } else if number > best_num + One::one() && + number > One::one() && self + .blockchain + .header(BlockId::hash(parent_hash))? + .is_none() + { + let gap = (best_num + One::one(), number - One::one()); + transaction.set(columns::META, meta_keys::BLOCK_GAP, &gap.encode()); + block_gap = Some(gap); + debug!(target: "db", "Detected block gap {:?}", block_gap); + } } meta_updates.push(MetaUpdate { @@ -1716,6 +1758,7 @@ impl Backend { for m in meta_updates { self.blockchain.update_meta(m); } + self.blockchain.update_block_gap(block_gap); Ok(()) } diff --git a/client/db/src/light.rs b/client/db/src/light.rs index bf2da5c61d05..48cf0489cf2a 100644 --- a/client/db/src/light.rs +++ b/client/db/src/light.rs @@ -157,6 +157,7 @@ where None }, number_leaves: 1, + block_gap: None, } } diff --git a/client/db/src/utils.rs b/client/db/src/utils.rs index ea22c774f463..0e895eaaf385 100644 --- a/client/db/src/utils.rs +++ b/client/db/src/utils.rs @@ -54,6 +54,8 @@ pub mod meta_keys { pub const FINALIZED_BLOCK: &[u8; 5] = b"final"; /// Last finalized state key. pub const FINALIZED_STATE: &[u8; 6] = b"fstate"; + /// Block gap. + pub const BLOCK_GAP: &[u8; 3] = b"gap"; /// Meta information prefix for list-based caches. pub const CACHE_META_PREFIX: &[u8; 5] = b"cache"; /// Meta information for changes tries key. @@ -81,6 +83,8 @@ pub struct Meta { pub genesis_hash: H, /// Finalized state, if any pub finalized_state: Option<(H, N)>, + /// Block gap, start and end inclusive, if any. + pub block_gap: Option<(N, N)>, } /// A block lookup key: used for canonical lookup from block number to hash @@ -527,6 +531,7 @@ where finalized_number: Zero::zero(), genesis_hash: Default::default(), finalized_state: None, + block_gap: None, }), }; @@ -541,7 +546,7 @@ where "Opened blockchain db, fetched {} = {:?} ({})", desc, hash, - header.number() + header.number(), ); Ok((hash, *header.number())) } else { @@ -558,6 +563,10 @@ where } else { None }; + let block_gap = db + .get(COLUMN_META, meta_keys::BLOCK_GAP) + .and_then(|d| Decode::decode(&mut d.as_slice()).ok()); + debug!(target: "db", "block_gap={:?}", block_gap); Ok(Meta { best_hash, @@ -566,6 +575,7 @@ where finalized_number, genesis_hash, finalized_state, + block_gap, }) } diff --git a/client/finality-grandpa/src/authorities.rs b/client/finality-grandpa/src/authorities.rs index 6e5dfdd05e62..6eb13099aa20 100644 --- a/client/finality-grandpa/src/authorities.rs +++ b/client/finality-grandpa/src/authorities.rs @@ -168,7 +168,7 @@ pub struct AuthoritySet { /// Track at which blocks the set id changed. This is useful when we need to prove finality for /// a given block since we can figure out what set the block belongs to and when the set /// started/ended. - authority_set_changes: AuthoritySetChanges, + pub(crate) authority_set_changes: AuthoritySetChanges, } impl AuthoritySet @@ -714,6 +714,17 @@ impl AuthoritySetChanges { } } + pub(crate) fn insert(&mut self, block_number: N) { + let idx = self + .0 + .binary_search_by_key(&block_number, |(_, n)| n.clone()) + .unwrap_or_else(|b| b); + + let set_id = if idx == 0 { 0 } else { self.0[idx - 1].0 + 1 }; + assert!(idx == self.0.len() || self.0[idx].0 != set_id); + self.0.insert(idx, (set_id, block_number)); + } + /// Returns an iterator over all historical authority set changes starting at the given block /// number (excluded). The iterator yields a tuple representing the set id and the block number /// of the last block in that set. @@ -1632,6 +1643,18 @@ mod tests { assert_eq!(authorities.pending_forced_changes.first().unwrap().canon_hash, "D"); } + #[test] + fn authority_set_changes_insert() { + let mut authority_set_changes = AuthoritySetChanges::empty(); + authority_set_changes.append(0, 41); + authority_set_changes.append(1, 81); + authority_set_changes.append(4, 121); + + authority_set_changes.insert(101); + assert_eq!(authority_set_changes.get_set_id(100), AuthoritySetChangeId::Set(2, 101)); + assert_eq!(authority_set_changes.get_set_id(101), AuthoritySetChangeId::Set(2, 101)); + } + #[test] fn authority_set_changes_for_complete_data() { let mut authority_set_changes = AuthoritySetChanges::empty(); diff --git a/client/finality-grandpa/src/import.rs b/client/finality-grandpa/src/import.rs index 1c4d1b4e97b8..d54f7234b44b 100644 --- a/client/finality-grandpa/src/import.rs +++ b/client/finality-grandpa/src/import.rs @@ -551,6 +551,32 @@ where return self.import_state(block, new_cache).await } + if number <= self.inner.info().finalized_number { + // Importing an old block. Just save justifications and authority set changes + if self.check_new_change(&block.header, hash).is_some() { + if block.justifications.is_none() { + return Err(ConsensusError::ClientImport( + "Justification required when importing \ + an old block with authority set change." + .into(), + )) + } + assert!(block.justifications.is_some()); + let mut authority_set = self.authority_set.inner_locked(); + authority_set.authority_set_changes.insert(number); + crate::aux_schema::update_authority_set::( + &authority_set, + None, + |insert| { + block + .auxiliary + .extend(insert.iter().map(|(k, v)| (k.to_vec(), Some(v.to_vec())))) + }, + ); + } + return (&*self.inner).import_block(block, new_cache).await + } + // on initial sync we will restrict logging under info to avoid spam. let initial_sync = block.origin == BlockOrigin::NetworkInitialSync; diff --git a/client/finality-grandpa/src/warp_proof.rs b/client/finality-grandpa/src/warp_proof.rs index 34eaa49cdf36..3c1fa4892f8a 100644 --- a/client/finality-grandpa/src/warp_proof.rs +++ b/client/finality-grandpa/src/warp_proof.rs @@ -31,7 +31,7 @@ use sp_runtime::{ traits::{Block as BlockT, Header as HeaderT, NumberFor, One}, }; -use std::sync::Arc; +use std::{collections::HashMap, sync::Arc}; /// Warp proof processing error. #[derive(Debug, derive_more::Display, derive_more::From)] @@ -194,6 +194,7 @@ impl WarpSyncProof { &self, set_id: SetId, authorities: AuthorityList, + hard_forks: &HashMap<(Block::Hash, NumberFor), (SetId, AuthorityList)>, ) -> Result<(SetId, AuthorityList), Error> where NumberFor: BlockNumberOps, @@ -202,26 +203,34 @@ impl WarpSyncProof { let mut current_authorities = authorities; for (fragment_num, proof) in self.proofs.iter().enumerate() { - proof - .justification - .verify(current_set_id, ¤t_authorities) - .map_err(|err| Error::InvalidProof(err.to_string()))?; - - if proof.justification.target().1 != proof.header.hash() { - return Err(Error::InvalidProof( - "Mismatch between header and justification".to_owned(), - )) - } + let hash = proof.header.hash(); + let number = *proof.header.number(); + + if let Some((set_id, list)) = hard_forks.get(&(hash.clone(), number)) { + current_set_id = *set_id; + current_authorities = list.clone(); + } else { + proof + .justification + .verify(current_set_id, ¤t_authorities) + .map_err(|err| Error::InvalidProof(err.to_string()))?; + + if proof.justification.target().1 != hash { + return Err(Error::InvalidProof( + "Mismatch between header and justification".to_owned(), + )) + } - if let Some(scheduled_change) = find_scheduled_change::(&proof.header) { - current_authorities = scheduled_change.next_authorities; - current_set_id += 1; - } else if fragment_num != self.proofs.len() - 1 || !self.is_finished { - // Only the last fragment of the last proof message is allowed to be missing - // the authority set change. - return Err(Error::InvalidProof( - "Header is missing authority set change digest".to_string(), - )) + if let Some(scheduled_change) = find_scheduled_change::(&proof.header) { + current_authorities = scheduled_change.next_authorities; + current_set_id += 1; + } else if fragment_num != self.proofs.len() - 1 || !self.is_finished { + // Only the last fragment of the last proof message is allowed to be missing the + // authority set change. + return Err(Error::InvalidProof( + "Header is missing authority set change digest".to_string(), + )) + } } } Ok((current_set_id, current_authorities)) @@ -235,6 +244,7 @@ where { backend: Arc, authority_set: SharedAuthoritySet>, + hard_forks: HashMap<(Block::Hash, NumberFor), (SetId, AuthorityList)>, } impl> NetworkProvider @@ -245,8 +255,13 @@ where pub fn new( backend: Arc, authority_set: SharedAuthoritySet>, + hard_forks: Vec<(SetId, (Block::Hash, NumberFor), AuthorityList)>, ) -> Self { - NetworkProvider { backend, authority_set } + NetworkProvider { + backend, + authority_set, + hard_forks: hard_forks.into_iter().map(|(s, hn, list)| (hn, (s, list))).collect(), + } } } @@ -283,7 +298,7 @@ where .map(|p| p.header.clone()) .ok_or_else(|| "Empty proof".to_string())?; let (next_set_id, next_authorities) = - proof.verify(set_id, authorities).map_err(Box::new)?; + proof.verify(set_id, authorities, &self.hard_forks).map_err(Box::new)?; if proof.is_finished { Ok(VerificationResult::::Complete(next_set_id, next_authorities, last_header)) } else { @@ -417,7 +432,8 @@ mod tests { WarpSyncProof::generate(&*backend, genesis_hash, &authority_set_changes).unwrap(); // verifying the proof should yield the last set id and authorities - let (new_set_id, new_authorities) = warp_sync_proof.verify(0, genesis_authorities).unwrap(); + let (new_set_id, new_authorities) = + warp_sync_proof.verify(0, genesis_authorities, &Default::default()).unwrap(); let expected_authorities = current_authorities .iter() diff --git a/client/informant/src/display.rs b/client/informant/src/display.rs index 1f23856101aa..6496172b8089 100644 --- a/client/informant/src/display.rs +++ b/client/informant/src/display.rs @@ -20,7 +20,7 @@ use crate::OutputFormat; use ansi_term::Colour; use log::info; use sc_client_api::ClientInfo; -use sc_network::{NetworkStatus, SyncState}; +use sc_network::{NetworkStatus, SyncState, WarpSyncPhase, WarpSyncProgress}; use sp_runtime::traits::{Block as BlockT, CheckedDiv, NumberFor, Saturating, Zero}; use std::{ convert::{TryFrom, TryInto}, @@ -97,11 +97,17 @@ impl InformantDisplay { net_status.state_sync, net_status.warp_sync, ) { + ( + _, + _, + _, + Some(WarpSyncProgress { phase: WarpSyncPhase::DownloadingBlocks(n), .. }), + ) => ("⏩", "Block history".into(), format!(", #{}", n)), (_, _, _, Some(warp)) => ( "⏩", "Warping".into(), format!( - ", {}, ({:.2}) Mib", + ", {}, {:.2} Mib", warp.phase, (warp.total_bytes as f32) / (1024f32 * 1024f32) ), @@ -110,7 +116,7 @@ impl InformantDisplay { "⚙️ ", "Downloading state".into(), format!( - ", {}%, ({:.2}) Mib", + ", {}%, {:.2} Mib", state.percentage, (state.size as f32) / (1024f32 * 1024f32) ), diff --git a/client/network/src/lib.rs b/client/network/src/lib.rs index 51bc370265ef..2f81ddfa1fb1 100644 --- a/client/network/src/lib.rs +++ b/client/network/src/lib.rs @@ -328,5 +328,5 @@ pub struct NetworkStatus { /// State sync in progress. pub state_sync: Option, /// Warp sync in progress. - pub warp_sync: Option, + pub warp_sync: Option>, } diff --git a/client/network/src/protocol.rs b/client/network/src/protocol.rs index e22d96f32aeb..70a17dc44b16 100644 --- a/client/network/src/protocol.rs +++ b/client/network/src/protocol.rs @@ -710,8 +710,7 @@ impl Protocol { match self.sync.on_state_data(&peer_id, response) { Ok(sync::OnStateData::Import(origin, block)) => CustomMessageOutcome::BlockImport(origin, vec![block]), - Ok(sync::OnStateData::Request(peer, req)) => - prepare_state_request::(&mut self.peers, peer, req), + Ok(sync::OnStateData::Continue) => CustomMessageOutcome::None, Err(sync::BadPeer(id, repu)) => { self.behaviour.disconnect_peer(&id, HARDCODED_PEERSETS_SYNC); self.peerset_handle.report_peer(id, repu); @@ -728,10 +727,7 @@ impl Protocol { response: crate::warp_request_handler::EncodedProof, ) -> CustomMessageOutcome { match self.sync.on_warp_sync_data(&peer_id, response) { - Ok(sync::OnWarpSyncData::WarpProofRequest(peer, req)) => - prepare_warp_sync_request::(&mut self.peers, peer, req), - Ok(sync::OnWarpSyncData::StateRequest(peer, req)) => - prepare_state_request::(&mut self.peers, peer, req), + Ok(()) => CustomMessageOutcome::None, Err(sync::BadPeer(id, repu)) => { self.behaviour.disconnect_peer(&id, HARDCODED_PEERSETS_SYNC); self.peerset_handle.report_peer(id, repu); diff --git a/client/network/src/protocol/sync.rs b/client/network/src/protocol/sync.rs index 07f5f76fce7f..7f85c2b63782 100644 --- a/client/network/src/protocol/sync.rs +++ b/client/network/src/protocol/sync.rs @@ -182,6 +182,12 @@ impl Default for PendingRequests { } } +struct GapSync { + blocks: BlockCollection, + best_queued_number: NumberFor, + target: NumberFor, +} + /// The main data structure which contains all the state for a chains /// active syncing strategy. pub struct ChainSync { @@ -226,6 +232,8 @@ pub struct ChainSync { /// Enable importing existing blocks. This is used used after the state download to /// catch up to the latest state while re-importing blocks. import_existing: bool, + /// Gap download process. + gap_sync: Option>, } /// All the data we have about a Peer that we are trying to sync with @@ -298,6 +306,8 @@ pub enum PeerSyncState { DownloadingState, /// Downloading warp proof. DownloadingWarpProof, + /// Actively downloading block history after warp sync. + DownloadingGap(NumberFor), } impl PeerSyncState { @@ -326,7 +336,7 @@ pub struct StateDownloadProgress { /// Reported warp sync phase. #[derive(Clone, Eq, PartialEq, Debug)] -pub enum WarpSyncPhase { +pub enum WarpSyncPhase { /// Waiting for peers to connect. AwaitingPeers, /// Downloading and verifying grandpa warp proofs. @@ -335,24 +345,27 @@ pub enum WarpSyncPhase { DownloadingState, /// Importing state. ImportingState, + /// Downloading block history. + DownloadingBlocks(NumberFor), } -impl fmt::Display for WarpSyncPhase { +impl fmt::Display for WarpSyncPhase { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { Self::AwaitingPeers => write!(f, "Waiting for peers"), Self::DownloadingWarpProofs => write!(f, "Downloading finality proofs"), Self::DownloadingState => write!(f, "Downloading state"), Self::ImportingState => write!(f, "Importing state"), + Self::DownloadingBlocks(n) => write!(f, "Downloading block history (#{})", n), } } } /// Reported warp sync progress. #[derive(Clone, Eq, PartialEq, Debug)] -pub struct WarpSyncProgress { +pub struct WarpSyncProgress { /// Estimated download percentage. - pub phase: WarpSyncPhase, + pub phase: WarpSyncPhase, /// Total bytes downloaded so far. pub total_bytes: u64, } @@ -371,7 +384,7 @@ pub struct Status { /// State sync status in progress, if any. pub state_sync: Option, /// Warp sync in progress, if any. - pub warp_sync: Option, + pub warp_sync: Option>, } /// A peer did not behave as expected and should be reported. @@ -413,16 +426,7 @@ pub enum OnStateData { /// The block and state that should be imported. Import(BlockOrigin, IncomingBlock), /// A new state request needs to be made to the given peer. - Request(PeerId, StateRequest), -} - -/// Result of [`ChainSync::on_warp_sync_data`]. -#[derive(Debug)] -pub enum OnWarpSyncData { - /// Warp proof request is issued. - WarpProofRequest(PeerId, warp::WarpProofRequest), - /// A new state request needs to be made to the given peer. - StateRequest(PeerId, StateRequest), + Continue, } /// Result of [`ChainSync::poll_block_announce_validation`]. @@ -555,6 +559,7 @@ impl ChainSync { warp_sync: None, warp_sync_provider, import_existing: false, + gap_sync: None, }; sync.reset_sync_start_point()?; Ok(sync) @@ -608,10 +613,14 @@ impl ChainSync { SyncState::Idle }; - let warp_sync_progress = match (&self.warp_sync, &self.mode) { - (None, SyncMode::Warp) => + let warp_sync_progress = match (&self.warp_sync, &self.mode, &self.gap_sync) { + (_, _, Some(gap_sync)) => Some(WarpSyncProgress { + phase: WarpSyncPhase::DownloadingBlocks(gap_sync.best_queued_number), + total_bytes: 0, + }), + (None, SyncMode::Warp, _) => Some(WarpSyncProgress { phase: WarpSyncPhase::AwaitingPeers, total_bytes: 0 }), - (Some(sync), _) => Some(sync.progress()), + (Some(sync), _, _) => Some(sync.progress()), _ => None, }; @@ -686,17 +695,6 @@ impl ChainSync { return Ok(None) } - if let SyncMode::Warp = &self.mode { - if self.peers.len() >= MIN_PEERS_TO_START_WARP_SYNC && self.warp_sync.is_none() - { - log::debug!(target: "sync", "Starting warp state sync."); - if let Some(provider) = &self.warp_sync_provider { - self.warp_sync = - Some(WarpSync::new(self.client.clone(), provider.clone())); - } - } - } - // If we are at genesis, just start downloading. let (state, req) = if self.best_queued_number.is_zero() { debug!( @@ -739,6 +737,17 @@ impl ChainSync { }, ); + if let SyncMode::Warp = &self.mode { + if self.peers.len() >= MIN_PEERS_TO_START_WARP_SYNC && self.warp_sync.is_none() + { + log::debug!(target: "sync", "Starting warp state sync."); + if let Some(provider) = &self.warp_sync_provider { + self.warp_sync = + Some(WarpSync::new(self.client.clone(), provider.clone())); + } + } + } + Ok(req) }, Ok(BlockStatus::Queued) | @@ -869,10 +878,13 @@ impl ChainSync { /// Get an iterator over all block requests of all peers. pub fn block_requests(&mut self) -> impl Iterator)> + '_ { - if self.pending_requests.is_empty() || self.state_sync.is_some() || self.warp_sync.is_some() + if self.pending_requests.is_empty() || + self.state_sync.is_some() || + self.mode == SyncMode::Warp { return Either::Left(std::iter::empty()) } + if self.queue_blocks.len() > MAX_IMPORTING_BLOCKS { trace!(target: "sync", "Too many blocks in the queue."); return Either::Left(std::iter::empty()) @@ -888,6 +900,7 @@ impl ChainSync { let queue = &self.queue_blocks; let pending_requests = self.pending_requests.take(); let max_parallel = if major_sync { 1 } else { self.max_parallel_downloads }; + let gap_sync = &mut self.gap_sync; let iter = self.peers.iter_mut().filter_map(move |(id, peer)| { if !peer.state.is_available() || !pending_requests.contains(id) { return None @@ -947,6 +960,26 @@ impl ChainSync { trace!(target: "sync", "Downloading fork {:?} from {}", hash, id); peer.state = PeerSyncState::DownloadingStale(hash); Some((id, req)) + } else if let Some((range, req)) = gap_sync.as_mut().and_then(|sync| { + peer_gap_block_request( + id, + peer, + &mut sync.blocks, + attrs, + sync.target, + sync.best_queued_number, + ) + }) { + peer.state = PeerSyncState::DownloadingGap(range.start); + trace!( + target: "sync", + "New gap block request for {}, (best:{}, common:{}) {:?}", + id, + peer.best_number, + peer.common_number, + req, + ); + Some((id, req)) } else { None } @@ -966,9 +999,9 @@ impl ChainSync { } for (id, peer) in self.peers.iter_mut() { if peer.state.is_available() && peer.common_number >= sync.target_block_num() { - trace!(target: "sync", "New StateRequest for {}", id); peer.state = PeerSyncState::DownloadingState; let request = sync.next_request(); + trace!(target: "sync", "New StateRequest for {}: {:?}", id, request); return Some((*id, request)) } } @@ -982,7 +1015,7 @@ impl ChainSync { { for (id, peer) in self.peers.iter_mut() { if peer.state.is_available() && peer.best_number >= target { - trace!(target: "sync", "New StateRequest for {}", id); + trace!(target: "sync", "New StateRequest for {}: {:?}", id, request); peer.state = PeerSyncState::DownloadingState; return Some((*id, request)) } @@ -1039,6 +1072,7 @@ impl ChainSync { response: BlockResponse, ) -> Result, BadPeer> { self.downloaded_blocks += response.blocks.len(); + let mut gap = false; let new_blocks: Vec> = if let Some(peer) = self.peers.get_mut(who) { let mut blocks = response.blocks; if request @@ -1061,6 +1095,43 @@ impl ChainSync { } self.drain_blocks() }, + PeerSyncState::DownloadingGap(start_block) => { + let start_block = *start_block; + peer.state = PeerSyncState::Available; + if let Some(gap_sync) = &mut self.gap_sync { + gap_sync.blocks.clear_peer_download(who); + validate_blocks::(&blocks, who, Some(request))?; + gap_sync.blocks.insert(start_block, blocks, who.clone()); + gap = true; + gap_sync + .blocks + .drain(gap_sync.best_queued_number + One::one()) + .into_iter() + .map(|block_data| { + let justifications = block_data.block.justifications.or( + legacy_justification_mapping( + block_data.block.justification, + ), + ); + IncomingBlock { + hash: block_data.block.hash, + header: block_data.block.header, + body: block_data.block.body, + indexed_body: block_data.block.indexed_body, + justifications, + origin: block_data.origin, + allow_missing_state: true, + import_existing: self.import_existing, + skip_execution: true, + state: None, + } + }) + .collect() + } else { + debug!(target: "sync", "Unexpected gap block response from {}", who); + return Err(BadPeer(who.clone(), rep::NO_BLOCK)) + } + }, PeerSyncState::DownloadingStale(_) => { peer.state = PeerSyncState::Available; if blocks.is_empty() { @@ -1212,7 +1283,7 @@ impl ChainSync { return Err(BadPeer(*who, rep::NOT_REQUESTED)) }; - Ok(self.validate_and_queue_blocks(new_blocks)) + Ok(self.validate_and_queue_blocks(new_blocks, gap)) } /// Handle a response from the remote to a state request that we made. @@ -1223,6 +1294,11 @@ impl ChainSync { who: &PeerId, response: StateResponse, ) -> Result, BadPeer> { + if let Some(peer) = self.peers.get_mut(&who) { + if let PeerSyncState::DownloadingState = peer.state { + peer.state = PeerSyncState::Available; + } + } let import_result = if let Some(sync) = &mut self.state_sync { debug!( target: "sync", @@ -1261,11 +1337,10 @@ impl ChainSync { skip_execution: self.skip_execution(), state: Some(state), }; - debug!(target: "sync", "State sync is complete. Import is queued"); + debug!(target: "sync", "State download is complete. Import is queued"); Ok(OnStateData::Import(origin, block)) }, - state::ImportResult::Continue(request) => - Ok(OnStateData::Request(who.clone(), request)), + state::ImportResult::Continue => Ok(OnStateData::Continue), state::ImportResult::BadResponse => { debug!(target: "sync", "Bad state data received from {}", who); Err(BadPeer(*who, rep::BAD_BLOCK)) @@ -1280,7 +1355,12 @@ impl ChainSync { &mut self, who: &PeerId, response: warp::EncodedProof, - ) -> Result, BadPeer> { + ) -> Result<(), BadPeer> { + if let Some(peer) = self.peers.get_mut(&who) { + if let PeerSyncState::DownloadingWarpProof = peer.state { + peer.state = PeerSyncState::Available; + } + } let import_result = if let Some(sync) = &mut self.warp_sync { debug!( target: "sync", @@ -1295,10 +1375,7 @@ impl ChainSync { }; match import_result { - warp::WarpProofImportResult::StateRequest(request) => - Ok(OnWarpSyncData::StateRequest(*who, request)), - warp::WarpProofImportResult::WarpProofRequest(request) => - Ok(OnWarpSyncData::WarpProofRequest(*who, request)), + warp::WarpProofImportResult::Success => Ok(()), warp::WarpProofImportResult::BadResponse => { debug!(target: "sync", "Bad proof data received from {}", who); Err(BadPeer(*who, rep::BAD_BLOCK)) @@ -1309,6 +1386,7 @@ impl ChainSync { fn validate_and_queue_blocks( &mut self, mut new_blocks: Vec>, + gap: bool, ) -> OnBlockData { let orig_len = new_blocks.len(); new_blocks.retain(|b| !self.queue_blocks.contains(&b.hash)); @@ -1320,7 +1398,7 @@ impl ChainSync { ); } - let origin = if self.status().state != SyncState::Downloading { + let origin = if !gap && self.status().state != SyncState::Downloading { BlockOrigin::NetworkBroadcast } else { BlockOrigin::NetworkInitialSync @@ -1494,6 +1572,15 @@ impl ChainSync { self.mode = SyncMode::Full; output.extend(self.restart()); } + let gap_sync_complete = + self.gap_sync.as_ref().map_or(false, |s| s.target == number); + if gap_sync_complete { + info!( + target: "sync", + "Block history download is complete." + ); + self.gap_sync = None; + } }, Err(BlockImportError::IncompleteHeader(who)) => if let Some(peer) = who { @@ -1601,6 +1688,11 @@ impl ChainSync { if self.fork_targets.remove(&hash).is_some() { trace!(target: "sync", "Completed fork sync {:?}", hash); } + if let Some(gap_sync) = &mut self.gap_sync { + if number > gap_sync.best_queued_number && number <= gap_sync.target { + gap_sync.best_queued_number = number; + } + } if number > self.best_queued_number { self.best_queued_number = number; self.best_queued_hash = *hash; @@ -1954,6 +2046,9 @@ impl ChainSync { /// import, so this functions checks for such blocks and returns them. pub fn peer_disconnected(&mut self, who: &PeerId) -> Option> { self.blocks.clear_peer_download(who); + if let Some(gap_sync) = &mut self.gap_sync { + gap_sync.blocks.clear_peer_download(who) + } self.peers.remove(who); self.extra_justifications.peer_disconnected(who); self.pending_requests.set_all(); @@ -1963,7 +2058,7 @@ impl ChainSync { }); let blocks = self.drain_blocks(); if !blocks.is_empty() { - Some(self.validate_and_queue_blocks(blocks)) + Some(self.validate_and_queue_blocks(blocks, false)) } else { None } @@ -2043,6 +2138,14 @@ impl ChainSync { } } } + if let Some((start, end)) = info.block_gap { + debug!(target: "sync", "Starting gap sync #{} - #{}", start, end); + self.gap_sync = Some(GapSync { + best_queued_number: start - One::one(), + target: end, + blocks: BlockCollection::new(), + }); + } trace!(target: "sync", "Restarted sync at #{} ({:?})", self.best_queued_number, self.best_queued_hash); Ok(()) } @@ -2250,6 +2353,39 @@ fn peer_block_request( Some((range, request)) } +/// Get a new block request for the peer if any. +fn peer_gap_block_request( + id: &PeerId, + peer: &PeerSync, + blocks: &mut BlockCollection, + attrs: message::BlockAttributes, + target: NumberFor, + common_number: NumberFor, +) -> Option<(Range>, BlockRequest)> { + let range = blocks.needed_blocks( + id.clone(), + MAX_BLOCKS_TO_REQUEST, + std::cmp::min(peer.best_number, target), + common_number, + 1, + MAX_DOWNLOAD_AHEAD, + )?; + + // The end is not part of the range. + let last = range.end.saturating_sub(One::one()); + let from = message::FromBlock::Number(last); + + let request = message::generic::BlockRequest { + id: 0, + fields: attrs.clone(), + from, + to: None, + direction: message::Direction::Descending, + max: Some((range.end - range.start).saturated_into::()), + }; + Some((range, request)) +} + /// Get pending fork sync targets for a peer. fn fork_sync_request( id: &PeerId, diff --git a/client/network/src/protocol/sync/state.rs b/client/network/src/protocol/sync/state.rs index d2e4463f9891..e644ba1013e4 100644 --- a/client/network/src/protocol/sync/state.rs +++ b/client/network/src/protocol/sync/state.rs @@ -47,8 +47,8 @@ pub struct StateSync { pub enum ImportResult { /// State is complete and ready for import. Import(B::Hash, B::Header, ImportedState), - /// Continue dowloading. - Continue(StateRequest), + /// Continue downloading. + Continue, /// Bad state chunk. BadResponse, } @@ -134,7 +134,7 @@ impl StateSync { ImportedState { block: self.target_block, state: std::mem::take(&mut self.state) }, ) } else { - ImportResult::Continue(self.next_request()) + ImportResult::Continue } } diff --git a/client/network/src/protocol/sync/warp.rs b/client/network/src/protocol/sync/warp.rs index 32bd5cb9ed79..bbf8a28da14a 100644 --- a/client/network/src/protocol/sync/warp.rs +++ b/client/network/src/protocol/sync/warp.rs @@ -37,11 +37,9 @@ enum Phase { } /// Import warp proof result. -pub enum WarpProofImportResult { - /// Start downloading state data. - StateRequest(StateRequest), - /// Continue dowloading warp sync proofs. - WarpProofRequest(WarpProofRequest), +pub enum WarpProofImportResult { + /// Import was successful. + Success, /// Bad proof. BadResponse, } @@ -69,7 +67,7 @@ impl WarpSync { Self { client, warp_sync_provider, phase, total_proof_bytes: 0 } } - /// Validate and import a state reponse. + /// Validate and import a state response. pub fn import_state(&mut self, response: StateResponse) -> ImportResult { match &mut self.phase { Phase::WarpProof { .. } => { @@ -80,19 +78,15 @@ impl WarpSync { } } - /// Validate and import a warp proof reponse. - pub fn import_warp_proof(&mut self, response: EncodedProof) -> WarpProofImportResult { + /// Validate and import a warp proof response. + pub fn import_warp_proof(&mut self, response: EncodedProof) -> WarpProofImportResult { match &mut self.phase { Phase::State(_) => { log::debug!(target: "sync", "Unexpected warp proof response"); WarpProofImportResult::BadResponse }, Phase::WarpProof { set_id, authorities, last_hash } => { - match self.warp_sync_provider.verify( - &response, - *set_id, - std::mem::take(authorities), - ) { + match self.warp_sync_provider.verify(&response, *set_id, authorities.clone()) { Err(e) => { log::debug!(target: "sync", "Bad warp proof response: {:?}", e); return WarpProofImportResult::BadResponse @@ -103,17 +97,14 @@ impl WarpSync { *authorities = new_authorities; *last_hash = new_last_hash.clone(); self.total_proof_bytes += response.0.len() as u64; - WarpProofImportResult::WarpProofRequest(WarpProofRequest { - begin: new_last_hash, - }) + WarpProofImportResult::Success }, Ok(VerificationResult::Complete(new_set_id, _, header)) => { log::debug!(target: "sync", "Verified complete proof, set_id={:?}", new_set_id); self.total_proof_bytes += response.0.len() as u64; let state_sync = StateSync::new(self.client.clone(), header, false); - let request = state_sync.next_request(); self.phase = Phase::State(state_sync); - WarpProofImportResult::StateRequest(request) + WarpProofImportResult::Success }, } }, @@ -161,7 +152,7 @@ impl WarpSync { } /// Returns state sync estimated progress (percentage, bytes) - pub fn progress(&self) -> WarpSyncProgress { + pub fn progress(&self) -> WarpSyncProgress { match &self.phase { Phase::WarpProof { .. } => WarpSyncProgress { phase: WarpSyncPhase::DownloadingWarpProofs, diff --git a/client/network/src/warp_request_handler.rs b/client/network/src/warp_request_handler.rs index 2ab95bb3853b..ca5a93b752b6 100644 --- a/client/network/src/warp_request_handler.rs +++ b/client/network/src/warp_request_handler.rs @@ -23,10 +23,11 @@ use futures::{ stream::StreamExt, }; use log::debug; -use sp_finality_grandpa::{AuthorityList, SetId}; use sp_runtime::traits::Block as BlockT; use std::{sync::Arc, time::Duration}; +pub use sp_finality_grandpa::{AuthorityList, SetId}; + /// Scale-encoded warp sync proof response. pub struct EncodedProof(pub Vec); @@ -55,7 +56,7 @@ pub trait WarpSyncProvider: Send + Sync { &self, start: B::Hash, ) -> Result>; - /// Verify warp proof agains current set of authorities. + /// Verify warp proof against current set of authorities. fn verify( &self, proof: &EncodedProof, diff --git a/client/network/test/src/lib.rs b/client/network/test/src/lib.rs index e547fa376b3f..fb0012aaf5ba 100644 --- a/client/network/test/src/lib.rs +++ b/client/network/test/src/lib.rs @@ -55,7 +55,7 @@ use sc_network::{ }, light_client_requests::{self, handler::LightClientRequestHandler}, state_request_handler::{self, StateRequestHandler}, - Multiaddr, NetworkService, NetworkWorker, + warp_request_handler, Multiaddr, NetworkService, NetworkWorker, }; use sc_service::client::Client; use sp_blockchain::{ @@ -68,6 +68,7 @@ use sp_consensus::{ }; use sp_core::H256; use sp_runtime::{ + codec::{Decode, Encode}, generic::{BlockId, OpaqueDigestItemId}, traits::{Block as BlockT, Header as HeaderT, NumberFor}, Justification, Justifications, @@ -652,6 +653,33 @@ impl VerifierAdapter { } } +struct TestWarpSyncProvider(Arc>); + +impl warp_request_handler::WarpSyncProvider for TestWarpSyncProvider { + fn generate( + &self, + _start: B::Hash, + ) -> Result> { + let info = self.0.info(); + let best_header = self.0.header(BlockId::hash(info.best_hash)).unwrap().unwrap(); + Ok(warp_request_handler::EncodedProof(best_header.encode())) + } + fn verify( + &self, + proof: &warp_request_handler::EncodedProof, + _set_id: warp_request_handler::SetId, + _authorities: warp_request_handler::AuthorityList, + ) -> Result, Box> + { + let warp_request_handler::EncodedProof(encoded) = proof; + let header = B::Header::decode(&mut encoded.as_slice()).unwrap(); + Ok(warp_request_handler::VerificationResult::Complete(0, Default::default(), header)) + } + fn current_authorities(&self) -> warp_request_handler::AuthorityList { + Default::default() + } +} + /// Configuration for a full peer. #[derive(Default)] pub struct FullPeerConfig { @@ -737,7 +765,7 @@ where (Some(keep_blocks), false) => TestClientBuilder::with_pruning_window(keep_blocks), (None, false) => TestClientBuilder::with_default_backend(), }; - if matches!(config.sync_mode, SyncMode::Fast { .. }) { + if matches!(config.sync_mode, SyncMode::Fast { .. } | SyncMode::Warp) { test_client_builder = test_client_builder.set_no_genesis(); } let backend = test_client_builder.backend(); @@ -816,6 +844,15 @@ where protocol_config }; + let warp_sync = Arc::new(TestWarpSyncProvider(client.clone())); + + let warp_protocol_config = { + let (handler, protocol_config) = + warp_request_handler::RequestHandler::new(protocol_id.clone(), warp_sync.clone()); + self.spawn_task(handler.run().boxed()); + protocol_config + }; + let network = NetworkWorker::new(sc_network::config::Params { role: if config.is_authority { Role::Authority } else { Role::Full }, executor: None, @@ -835,7 +872,7 @@ where block_request_protocol_config, state_request_protocol_config, light_client_request_protocol_config, - warp_sync: None, + warp_sync: Some((warp_sync, warp_protocol_config)), }) .unwrap(); diff --git a/client/network/test/src/sync.rs b/client/network/test/src/sync.rs index f413b705e52c..f3af7f8ff6fc 100644 --- a/client/network/test/src/sync.rs +++ b/client/network/test/src/sync.rs @@ -1202,6 +1202,38 @@ fn syncs_indexed_blocks() { .is_some()); } +#[test] +fn warp_sync() { + sp_tracing::try_init_simple(); + let mut net = TestNet::new(0); + // Create 3 synced peers and 1 peer trying to warp sync. + net.add_full_peer_with_config(Default::default()); + net.add_full_peer_with_config(Default::default()); + net.add_full_peer_with_config(Default::default()); + net.add_full_peer_with_config(FullPeerConfig { + sync_mode: SyncMode::Warp, + ..Default::default() + }); + let gap_end = net.peer(0).push_blocks(63, false); + net.peer(0).push_blocks(1, false); + net.peer(1).push_blocks(64, false); + net.peer(2).push_blocks(64, false); + // Wait for peer 1 to sync state. + net.block_until_sync(); + assert!(!net.peer(3).client().has_state_at(&BlockId::Number(1))); + assert!(net.peer(3).client().has_state_at(&BlockId::Number(64))); + + // Wait for peer 1 download block history + block_on(futures::future::poll_fn::<(), _>(|cx| { + net.poll(cx); + if net.peer(3).has_block(&gap_end) { + Poll::Ready(()) + } else { + Poll::Pending + } + })); +} + #[test] fn syncs_huge_blocks() { use sp_core::storage::well_known_keys::HEAP_PAGES; diff --git a/client/service/src/chain_ops/check_block.rs b/client/service/src/chain_ops/check_block.rs index 4728e014540e..5e2a9faaf0c4 100644 --- a/client/service/src/chain_ops/check_block.rs +++ b/client/service/src/chain_ops/check_block.rs @@ -19,7 +19,7 @@ use crate::error::Error; use codec::Encode; use futures::{future, prelude::*}; -use sc_client_api::{BlockBackend, UsageProvider}; +use sc_client_api::{BlockBackend, HeaderBackend}; use sc_consensus::import_queue::ImportQueue; use sp_runtime::{generic::BlockId, traits::Block as BlockT}; @@ -33,7 +33,7 @@ pub fn check_block( block_id: BlockId, ) -> Pin> + Send>> where - C: BlockBackend + UsageProvider + Send + Sync + 'static, + C: BlockBackend + HeaderBackend + Send + Sync + 'static, B: BlockT + for<'de> serde::Deserialize<'de>, IQ: ImportQueue + 'static, { diff --git a/client/service/src/chain_ops/import_blocks.rs b/client/service/src/chain_ops/import_blocks.rs index 1ba9e0bd6144..a408a06a8170 100644 --- a/client/service/src/chain_ops/import_blocks.rs +++ b/client/service/src/chain_ops/import_blocks.rs @@ -22,7 +22,7 @@ use futures::{future, prelude::*}; use futures_timer::Delay; use log::{info, warn}; use sc_chain_spec::ChainSpec; -use sc_client_api::UsageProvider; +use sc_client_api::HeaderBackend; use sc_consensus::import_queue::{ BlockImportError, BlockImportStatus, ImportQueue, IncomingBlock, Link, }; @@ -296,7 +296,7 @@ pub fn import_blocks( binary: bool, ) -> Pin> + Send>> where - C: UsageProvider + Send + Sync + 'static, + C: HeaderBackend + Send + Sync + 'static, B: BlockT + for<'de> serde::Deserialize<'de>, IQ: ImportQueue + 'static, { @@ -438,7 +438,7 @@ where info!( "🎉 Imported {} blocks. Best: #{}", read_block_count, - client.usage_info().chain.best_number + client.info().best_number ); return Poll::Ready(Ok(())) } else { @@ -469,7 +469,7 @@ where queue.poll_actions(cx, &mut link); - let best_number = client.usage_info().chain.best_number; + let best_number = client.info().best_number; speedometer.notify_user(best_number); if link.has_error { diff --git a/client/service/src/client/client.rs b/client/service/src/client/client.rs index f7d93d036a3f..d35c0462b8b0 100644 --- a/client/service/src/client/client.rs +++ b/client/service/src/client/client.rs @@ -684,8 +684,6 @@ where .. } = import_block; - assert!(justifications.is_some() && finalized || justifications.is_none()); - if !intermediates.is_empty() { return Err(Error::IncompletePipeline) } @@ -779,11 +777,17 @@ where } let info = self.backend.blockchain().info(); + let gap_block = info + .block_gap + .map_or(false, |(start, _)| *import_headers.post().number() == start); + + assert!(justifications.is_some() && finalized || justifications.is_none() || gap_block); // the block is lower than our last finalized block so it must revert // finality, refusing import. if status == blockchain::BlockStatus::Unknown && - *import_headers.post().number() <= info.finalized_number + *import_headers.post().number() <= info.finalized_number && + !gap_block { return Err(sp_blockchain::Error::NotInFinalizedChain) } @@ -854,12 +858,13 @@ where None => None, }; - let is_new_best = finalized || - match fork_choice { - ForkChoiceStrategy::LongestChain => - import_headers.post().number() > &info.best_number, - ForkChoiceStrategy::Custom(v) => v, - }; + let is_new_best = !gap_block && + (finalized || + match fork_choice { + ForkChoiceStrategy::LongestChain => + import_headers.post().number() > &info.best_number, + ForkChoiceStrategy::Custom(v) => v, + }); let leaf_state = if finalized { NewBlockState::Final diff --git a/primitives/blockchain/src/backend.rs b/primitives/blockchain/src/backend.rs index bb34a0449b5f..fc70ce845dc9 100644 --- a/primitives/blockchain/src/backend.rs +++ b/primitives/blockchain/src/backend.rs @@ -281,6 +281,8 @@ pub struct Info { pub finalized_state: Option<(Block::Hash, <::Header as HeaderT>::Number)>, /// Number of concurrent leave forks. pub number_leaves: usize, + /// Missing blocks after warp sync. (start, end). + pub block_gap: Option<(NumberFor, NumberFor)>, } /// Block status. From 53558132826db8572bc142685ed0b8b615cf8bd1 Mon Sep 17 00:00:00 2001 From: Davide Gessa Date: Thu, 7 Oct 2021 11:51:01 +0200 Subject: [PATCH 042/695] Replace is_global to is_private, maybe fixing #9922 (#9943) * replace is_global to is_private, maybe fixing #9922 * use of ip_network for private_ipv4 filtering * check is_global for both ip4 and ip6 * fix for rustfmt --- client/network/src/discovery.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/client/network/src/discovery.rs b/client/network/src/discovery.rs index 431de50c0f19..1ed08cd671d4 100644 --- a/client/network/src/discovery.rs +++ b/client/network/src/discovery.rs @@ -512,14 +512,10 @@ impl NetworkBehaviour for DiscoveryBehaviour { list_to_filter.extend(self.mdns.addresses_of_peer(peer_id)); if !self.allow_private_ipv4 { - list_to_filter.retain(|addr| { - if let Some(Protocol::Ip4(addr)) = addr.iter().next() { - if addr.is_private() { - return false - } - } - - true + list_to_filter.retain(|addr| match addr.iter().next() { + Some(Protocol::Ip4(addr)) if !IpNetwork::from(addr).is_global() => false, + Some(Protocol::Ip6(addr)) if !IpNetwork::from(addr).is_global() => false, + _ => true, }); } From 5636a44a8edd029f25f1549148e02a1866b71d1d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 7 Oct 2021 10:19:37 +0000 Subject: [PATCH 043/695] Bump sha2 from 0.9.3 to 0.9.5 (#9955) Bumps [sha2](https://github.com/RustCrypto/hashes) from 0.9.3 to 0.9.5. - [Release notes](https://github.com/RustCrypto/hashes/releases) - [Commits](https://github.com/RustCrypto/hashes/compare/sha2-v0.9.3...sha2-v0.9.5) --- updated-dependencies: - dependency-name: sha2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 34 +++++++++++++++++----------------- primitives/core/Cargo.toml | 2 +- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0a502439b725..77f257fad4db 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1664,7 +1664,7 @@ dependencies = [ "ed25519", "rand 0.7.3", "serde", - "sha2 0.9.3", + "sha2 0.9.5", "zeroize", ] @@ -3395,7 +3395,7 @@ dependencies = [ "rand 0.7.3", "ring", "rw-stream-sink", - "sha2 0.9.3", + "sha2 0.9.5", "smallvec 1.7.0", "thiserror", "unsigned-varint 0.7.0", @@ -3466,7 +3466,7 @@ dependencies = [ "prost-build", "rand 0.7.3", "regex", - "sha2 0.9.3", + "sha2 0.9.5", "smallvec 1.7.0", "unsigned-varint 0.7.0", "wasm-timer", @@ -3506,7 +3506,7 @@ dependencies = [ "prost", "prost-build", "rand 0.7.3", - "sha2 0.9.3", + "sha2 0.9.5", "smallvec 1.7.0", "uint", "unsigned-varint 0.7.0", @@ -3568,7 +3568,7 @@ dependencies = [ "prost", "prost-build", "rand 0.8.4", - "sha2 0.9.3", + "sha2 0.9.5", "snow", "static_assertions", "x25519-dalek", @@ -3791,7 +3791,7 @@ dependencies = [ "libsecp256k1-gen-genmult 0.2.1", "rand 0.7.3", "serde", - "sha2 0.9.3", + "sha2 0.9.5", "typenum", ] @@ -3810,7 +3810,7 @@ dependencies = [ "libsecp256k1-gen-genmult 0.2.1", "rand 0.7.3", "serde", - "sha2 0.9.3", + "sha2 0.9.5", "typenum", ] @@ -3828,7 +3828,7 @@ dependencies = [ "libsecp256k1-gen-genmult 0.3.0", "rand 0.8.4", "serde", - "sha2 0.9.3", + "sha2 0.9.5", ] [[package]] @@ -4285,7 +4285,7 @@ dependencies = [ "digest 0.9.0", "generic-array 0.14.4", "multihash-derive", - "sha2 0.9.3", + "sha2 0.9.5", "sha3", "unsigned-varint 0.5.1", ] @@ -4299,7 +4299,7 @@ dependencies = [ "digest 0.9.0", "generic-array 0.14.4", "multihash-derive", - "sha2 0.9.3", + "sha2 0.9.5", "unsigned-varint 0.7.0", ] @@ -8854,13 +8854,13 @@ dependencies = [ [[package]] name = "sha2" -version = "0.9.3" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa827a14b29ab7f44778d14a88d3cb76e949c45083f7dbfa507d0cb699dc12de" +checksum = "b362ae5752fd2137731f9fa25fd4d9058af34666ca1966fb969119cc35719f12" dependencies = [ "block-buffer 0.9.0", "cfg-if 1.0.0", - "cpuid-bool", + "cpufeatures", "digest 0.9.0", "opaque-debug 0.3.0", ] @@ -8978,7 +8978,7 @@ dependencies = [ "rand_core 0.6.2", "ring", "rustc_version 0.3.3", - "sha2 0.9.3", + "sha2 0.9.5", "subtle 2.4.0", "x25519-dalek", ] @@ -9308,7 +9308,7 @@ dependencies = [ "secrecy", "serde", "serde_json", - "sha2 0.9.3", + "sha2 0.9.5", "sp-debug-derive", "sp-externalities", "sp-runtime-interface", @@ -10404,7 +10404,7 @@ dependencies = [ "pbkdf2 0.4.0", "rand 0.7.3", "rustc-hash", - "sha2 0.9.3", + "sha2 0.9.5", "thiserror", "unicode-normalization", "wasm-bindgen", @@ -11482,7 +11482,7 @@ dependencies = [ "libc", "log 0.4.14", "serde", - "sha2 0.9.3", + "sha2 0.9.5", "toml", "winapi 0.3.9", "zstd", diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index ab7d8e3df19a..9727d1e4f278 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -61,7 +61,7 @@ schnorrkel = { version = "0.9.1", features = [ "preaudit_deprecated", "u64_backend", ], default-features = false, optional = true } -sha2 = { version = "0.9.2", default-features = false, optional = true } +sha2 = { version = "0.9.5", default-features = false, optional = true } hex = { version = "0.4", default-features = false, optional = true } twox-hash = { version = "1.6.1", default-features = false, optional = true } libsecp256k1 = { version = "0.6", default-features = false, features = ["hmac", "static-context"], optional = true } From 4b6635cf136a9fe2226f3152b4633afc6269912c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 7 Oct 2021 12:13:29 +0000 Subject: [PATCH 044/695] Bump prometheus from 0.11.0 to 0.12.0 (#9454) Bumps [prometheus](https://github.com/tikv/rust-prometheus) from 0.11.0 to 0.12.0. - [Release notes](https://github.com/tikv/rust-prometheus/releases) - [Changelog](https://github.com/tikv/rust-prometheus/blob/master/CHANGELOG.md) - [Commits](https://github.com/tikv/rust-prometheus/compare/v0.11.0...v0.12.0) --- updated-dependencies: - dependency-name: prometheus dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 6 +++--- client/utils/Cargo.toml | 2 +- utils/prometheus/Cargo.toml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 77f257fad4db..44d285b232b8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6750,15 +6750,15 @@ dependencies = [ [[package]] name = "prometheus" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8425533e7122f0c3cc7a37e6244b16ad3a2cc32ae7ac6276e2a75da0d9c200d" +checksum = "5986aa8d62380092d2f50f8b1cdba9cb9b6731ffd4b25b51fd126b6c3e05b99c" dependencies = [ "cfg-if 1.0.0", "fnv", "lazy_static", + "memchr", "parking_lot 0.11.1", - "regex", "thiserror", ] diff --git a/client/utils/Cargo.toml b/client/utils/Cargo.toml index 99765dd501dd..9b3c54974a76 100644 --- a/client/utils/Cargo.toml +++ b/client/utils/Cargo.toml @@ -12,7 +12,7 @@ readme = "README.md" [dependencies] futures = "0.3.9" lazy_static = "1.4.0" -prometheus = { version = "0.11.0", default-features = false } +prometheus = { version = "0.12.0", default-features = false } futures-timer = "3.0.2" [features] diff --git a/utils/prometheus/Cargo.toml b/utils/prometheus/Cargo.toml index 8b647d6282fb..43de76eee212 100644 --- a/utils/prometheus/Cargo.toml +++ b/utils/prometheus/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] log = "0.4.8" -prometheus = { version = "0.11.0", default-features = false } +prometheus = { version = "0.12.0", default-features = false } futures-util = { version = "0.3.17", default-features = false, features = ["io"] } derive_more = "0.99" async-std = { version = "1.10.0", features = ["unstable"] } From 5e2b0f041c8a10c3ceb06721389e1d5c95380e65 Mon Sep 17 00:00:00 2001 From: Robert Klotzner Date: Thu, 7 Oct 2021 16:03:47 +0200 Subject: [PATCH 045/695] Expose `set_reserved_peers` (#9960) --- client/network/src/protocol.rs | 20 +++++++++++++--- client/network/src/service.rs | 44 ++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/client/network/src/protocol.rs b/client/network/src/protocol.rs index 70a17dc44b16..a0c52d14fa62 100644 --- a/client/network/src/protocol.rs +++ b/client/network/src/protocol.rs @@ -1102,7 +1102,7 @@ impl Protocol { /// Removes a `PeerId` from the list of reserved peers for syncing purposes. pub fn remove_reserved_peer(&self, peer: PeerId) { - self.peerset_handle.remove_reserved_peer(HARDCODED_PEERSETS_SYNC, peer.clone()); + self.peerset_handle.remove_reserved_peer(HARDCODED_PEERSETS_SYNC, peer); } /// Returns the list of reserved peers. @@ -1112,12 +1112,26 @@ impl Protocol { /// Adds a `PeerId` to the list of reserved peers for syncing purposes. pub fn add_reserved_peer(&self, peer: PeerId) { - self.peerset_handle.add_reserved_peer(HARDCODED_PEERSETS_SYNC, peer.clone()); + self.peerset_handle.add_reserved_peer(HARDCODED_PEERSETS_SYNC, peer); } /// Sets the list of reserved peers for syncing purposes. pub fn set_reserved_peers(&self, peers: HashSet) { - self.peerset_handle.set_reserved_peers(HARDCODED_PEERSETS_SYNC, peers.clone()); + self.peerset_handle.set_reserved_peers(HARDCODED_PEERSETS_SYNC, peers); + } + + /// Sets the list of reserved peers for the given protocol/peerset. + pub fn set_reserved_peerset_peers(&self, protocol: Cow<'static, str>, peers: HashSet) { + if let Some(index) = self.notification_protocols.iter().position(|p| *p == protocol) { + self.peerset_handle + .set_reserved_peers(sc_peerset::SetId::from(index + NUM_HARDCODED_PEERSETS), peers); + } else { + error!( + target: "sub-libp2p", + "set_reserved_peerset_peers with unknown protocol: {}", + protocol + ); + } } /// Removes a `PeerId` from the list of reserved peers. diff --git a/client/network/src/service.rs b/client/network/src/service.rs index 23f9c614d906..72b382c99054 100644 --- a/client/network/src/service.rs +++ b/client/network/src/service.rs @@ -1092,6 +1092,44 @@ impl NetworkService { let _ = self.to_worker.unbounded_send(ServiceToWorkerMsg::RemoveReserved(peer_id)); } + /// Sets the reserved set of a protocol to the given set of peers. + /// + /// Each `Multiaddr` must end with a `/p2p/` component containing the `PeerId`. It can also + /// consist of only `/p2p/`. + /// + /// Returns an `Err` if one of the given addresses is invalid or contains an + /// invalid peer ID (which includes the local peer ID). + pub fn set_reserved_peers( + &self, + protocol: Cow<'static, str>, + peers: HashSet, + ) -> Result<(), String> { + let peers_addrs = self.split_multiaddr_and_peer_id(peers)?; + + let mut peers: HashSet = HashSet::with_capacity(peers_addrs.len()); + + for (peer_id, addr) in peers_addrs.into_iter() { + // Make sure the local peer ID is never added to the PSM. + if peer_id == self.local_peer_id { + return Err("Local peer ID cannot be added as a reserved peer.".to_string()) + } + + peers.insert(peer_id); + + if !addr.is_empty() { + let _ = self + .to_worker + .unbounded_send(ServiceToWorkerMsg::AddKnownAddress(peer_id, addr)); + } + } + + let _ = self + .to_worker + .unbounded_send(ServiceToWorkerMsg::SetPeersetReserved(protocol, peers)); + + Ok(()) + } + /// Add peers to a peer set. /// /// Each `Multiaddr` must end with a `/p2p/` component containing the `PeerId`. It can also @@ -1400,6 +1438,7 @@ enum ServiceToWorkerMsg { AddReserved(PeerId), RemoveReserved(PeerId), SetReserved(HashSet), + SetPeersetReserved(Cow<'static, str>, HashSet), AddSetReserved(Cow<'static, str>, PeerId), RemoveSetReserved(Cow<'static, str>, PeerId), AddToPeersSet(Cow<'static, str>, PeerId), @@ -1541,6 +1580,11 @@ impl Future for NetworkWorker { .behaviour_mut() .user_protocol_mut() .set_reserved_peers(peers), + ServiceToWorkerMsg::SetPeersetReserved(protocol, peers) => this + .network_service + .behaviour_mut() + .user_protocol_mut() + .set_reserved_peerset_peers(protocol, peers), ServiceToWorkerMsg::AddReserved(peer_id) => this .network_service .behaviour_mut() From 62f011ca8d0491f6be77b3dbe0074eb060245d08 Mon Sep 17 00:00:00 2001 From: girazoki Date: Thu, 7 Oct 2021 16:29:48 +0200 Subject: [PATCH 046/695] Add low level traits to retrieve name, symbol, decimals and allowance in pallet-assets (#9757) * Add ERC20 compatible trait to retrieve name, symbol, decimals and allowance * delegate instead of spender * Remove erc20 trait and divide it into lower level traits * add import * approvals and metadata depend on fungibles Co-authored-by: Shawn Tabrizi --- frame/assets/src/functions.rs | 125 ++++++++++++++++++ frame/assets/src/impl_fungibles.rs | 69 ++++++++++ frame/assets/src/lib.rs | 96 +------------- frame/assets/src/tests.rs | 34 +++++ frame/support/src/traits/tokens/fungibles.rs | 2 + .../src/traits/tokens/fungibles/approvals.rs | 43 ++++++ .../src/traits/tokens/fungibles/metadata.rs | 41 ++++++ 7 files changed, 317 insertions(+), 93 deletions(-) create mode 100644 frame/support/src/traits/tokens/fungibles/approvals.rs create mode 100644 frame/support/src/traits/tokens/fungibles/metadata.rs diff --git a/frame/assets/src/functions.rs b/frame/assets/src/functions.rs index ae31b8e39519..a4685d88d049 100644 --- a/frame/assets/src/functions.rs +++ b/frame/assets/src/functions.rs @@ -18,6 +18,7 @@ //! Functions for the Assets pallet. use super::*; +use frame_support::{traits::Get, BoundedVec}; // The main implementation block for the module. impl, I: 'static> Pallet { @@ -562,4 +563,128 @@ impl, I: 'static> Pallet { }) }) } + + /// Creates an approval from `owner` to spend `amount` of asset `id` tokens by 'delegate' + /// while reserving `T::ApprovalDeposit` from owner + /// + /// If an approval already exists, the new amount is added to such existing approval + pub(super) fn do_approve_transfer( + id: T::AssetId, + owner: &T::AccountId, + delegate: &T::AccountId, + amount: T::Balance, + ) -> DispatchResult { + let mut d = Asset::::get(id).ok_or(Error::::Unknown)?; + ensure!(!d.is_frozen, Error::::Frozen); + Approvals::::try_mutate( + (id, &owner, &delegate), + |maybe_approved| -> DispatchResult { + let mut approved = match maybe_approved.take() { + // an approval already exists and is being updated + Some(a) => a, + // a new approval is created + None => { + d.approvals.saturating_inc(); + Default::default() + }, + }; + let deposit_required = T::ApprovalDeposit::get(); + if approved.deposit < deposit_required { + T::Currency::reserve(&owner, deposit_required - approved.deposit)?; + approved.deposit = deposit_required; + } + approved.amount = approved.amount.saturating_add(amount); + *maybe_approved = Some(approved); + Ok(()) + }, + )?; + Asset::::insert(id, d); + Self::deposit_event(Event::ApprovedTransfer(id, owner.clone(), delegate.clone(), amount)); + + Ok(()) + } + + /// Reduces the asset `id` balance of `owner` by some `amount` and increases the balance of + /// `dest` by (similar) amount, checking that 'delegate' has an existing approval from `owner` + /// to spend`amount`. + /// + /// Will fail if `amount` is greater than the approval from `owner` to 'delegate' + /// Will unreserve the deposit from `owner` if the entire approved `amount` is spent by + /// 'delegate' + pub(super) fn do_transfer_approved( + id: T::AssetId, + owner: &T::AccountId, + delegate: &T::AccountId, + destination: &T::AccountId, + amount: T::Balance, + ) -> DispatchResult { + Approvals::::try_mutate_exists( + (id, &owner, delegate), + |maybe_approved| -> DispatchResult { + let mut approved = maybe_approved.take().ok_or(Error::::Unapproved)?; + let remaining = + approved.amount.checked_sub(&amount).ok_or(Error::::Unapproved)?; + + let f = TransferFlags { keep_alive: false, best_effort: false, burn_dust: false }; + Self::do_transfer(id, &owner, &destination, amount, None, f)?; + + if remaining.is_zero() { + T::Currency::unreserve(&owner, approved.deposit); + Asset::::mutate(id, |maybe_details| { + if let Some(details) = maybe_details { + details.approvals.saturating_dec(); + } + }); + } else { + approved.amount = remaining; + *maybe_approved = Some(approved); + } + Ok(()) + }, + )?; + Ok(()) + } + + /// Do set metadata + pub(super) fn do_set_metadata( + id: T::AssetId, + from: &T::AccountId, + name: Vec, + symbol: Vec, + decimals: u8, + ) -> DispatchResult { + let bounded_name: BoundedVec = + name.clone().try_into().map_err(|_| Error::::BadMetadata)?; + let bounded_symbol: BoundedVec = + symbol.clone().try_into().map_err(|_| Error::::BadMetadata)?; + + let d = Asset::::get(id).ok_or(Error::::Unknown)?; + ensure!(from == &d.owner, Error::::NoPermission); + + Metadata::::try_mutate_exists(id, |metadata| { + ensure!(metadata.as_ref().map_or(true, |m| !m.is_frozen), Error::::NoPermission); + + let old_deposit = metadata.take().map_or(Zero::zero(), |m| m.deposit); + let new_deposit = T::MetadataDepositPerByte::get() + .saturating_mul(((name.len() + symbol.len()) as u32).into()) + .saturating_add(T::MetadataDepositBase::get()); + + if new_deposit > old_deposit { + T::Currency::reserve(from, new_deposit - old_deposit)?; + } else { + T::Currency::unreserve(from, old_deposit - new_deposit); + } + + *metadata = Some(AssetMetadata { + deposit: new_deposit, + name: bounded_name, + symbol: bounded_symbol, + decimals, + is_frozen: false, + }); + + Self::deposit_event(Event::MetadataSet(id, name, symbol, decimals, false)); + Ok(()) + }) + } } diff --git a/frame/assets/src/impl_fungibles.rs b/frame/assets/src/impl_fungibles.rs index 2e16a0910a4f..be534bfad57a 100644 --- a/frame/assets/src/impl_fungibles.rs +++ b/frame/assets/src/impl_fungibles.rs @@ -193,3 +193,72 @@ impl, I: 'static> fungibles::Destroy for Pallet Self::do_destroy(id, witness, maybe_check_owner) } } + +impl, I: 'static> fungibles::metadata::Inspect<::AccountId> + for Pallet +{ + fn name(asset: T::AssetId) -> Vec { + Metadata::::get(asset).name.to_vec() + } + + fn symbol(asset: T::AssetId) -> Vec { + Metadata::::get(asset).symbol.to_vec() + } + + fn decimals(asset: T::AssetId) -> u8 { + Metadata::::get(asset).decimals + } +} + +impl, I: 'static> fungibles::metadata::Mutate<::AccountId> + for Pallet +{ + fn set( + asset: T::AssetId, + from: &::AccountId, + name: Vec, + symbol: Vec, + decimals: u8, + ) -> DispatchResult { + Self::do_set_metadata(asset, from, name, symbol, decimals) + } +} + +impl, I: 'static> fungibles::approvals::Inspect<::AccountId> + for Pallet +{ + // Check the amount approved to be spent by an owner to a delegate + fn allowance( + asset: T::AssetId, + owner: &::AccountId, + delegate: &::AccountId, + ) -> T::Balance { + Approvals::::get((asset, &owner, &delegate)) + .map(|x| x.amount) + .unwrap_or_else(Zero::zero) + } +} + +impl, I: 'static> fungibles::approvals::Mutate<::AccountId> + for Pallet +{ + fn approve( + asset: T::AssetId, + owner: &::AccountId, + delegate: &::AccountId, + amount: T::Balance, + ) -> DispatchResult { + Self::do_approve_transfer(asset, owner, delegate, amount) + } + + // Aprove spending tokens from a given account + fn transfer_from( + asset: T::AssetId, + owner: &::AccountId, + delegate: &::AccountId, + dest: &::AccountId, + amount: T::Balance, + ) -> DispatchResult { + Self::do_transfer_approved(asset, owner, delegate, dest, amount) + } +} diff --git a/frame/assets/src/lib.rs b/frame/assets/src/lib.rs index c6f24e10a89f..1ae729d7774d 100644 --- a/frame/assets/src/lib.rs +++ b/frame/assets/src/lib.rs @@ -948,43 +948,7 @@ pub mod pallet { decimals: u8, ) -> DispatchResult { let origin = ensure_signed(origin)?; - - let bounded_name: BoundedVec = - name.clone().try_into().map_err(|_| Error::::BadMetadata)?; - let bounded_symbol: BoundedVec = - symbol.clone().try_into().map_err(|_| Error::::BadMetadata)?; - - let d = Asset::::get(id).ok_or(Error::::Unknown)?; - ensure!(&origin == &d.owner, Error::::NoPermission); - - Metadata::::try_mutate_exists(id, |metadata| { - ensure!( - metadata.as_ref().map_or(true, |m| !m.is_frozen), - Error::::NoPermission - ); - - let old_deposit = metadata.take().map_or(Zero::zero(), |m| m.deposit); - let new_deposit = T::MetadataDepositPerByte::get() - .saturating_mul(((name.len() + symbol.len()) as u32).into()) - .saturating_add(T::MetadataDepositBase::get()); - - if new_deposit > old_deposit { - T::Currency::reserve(&origin, new_deposit - old_deposit)?; - } else { - T::Currency::unreserve(&origin, old_deposit - new_deposit); - } - - *metadata = Some(AssetMetadata { - deposit: new_deposit, - name: bounded_name, - symbol: bounded_symbol, - decimals, - is_frozen: false, - }); - - Self::deposit_event(Event::MetadataSet(id, name, symbol, decimals, false)); - Ok(()) - }) + Self::do_set_metadata(id, &origin, name, symbol, decimals) } /// Clear the metadata for an asset. @@ -1171,35 +1135,7 @@ pub mod pallet { ) -> DispatchResult { let owner = ensure_signed(origin)?; let delegate = T::Lookup::lookup(delegate)?; - - let mut d = Asset::::get(id).ok_or(Error::::Unknown)?; - ensure!(!d.is_frozen, Error::::Frozen); - Approvals::::try_mutate( - (id, &owner, &delegate), - |maybe_approved| -> DispatchResult { - let mut approved = match maybe_approved.take() { - // an approval already exists and is being updated - Some(a) => a, - // a new approval is created - None => { - d.approvals.saturating_inc(); - Default::default() - }, - }; - let deposit_required = T::ApprovalDeposit::get(); - if approved.deposit < deposit_required { - T::Currency::reserve(&owner, deposit_required - approved.deposit)?; - approved.deposit = deposit_required; - } - approved.amount = approved.amount.saturating_add(amount); - *maybe_approved = Some(approved); - Ok(()) - }, - )?; - Asset::::insert(id, d); - Self::deposit_event(Event::ApprovedTransfer(id, owner, delegate, amount)); - - Ok(()) + Self::do_approve_transfer(id, &owner, &delegate, amount) } /// Cancel all of some asset approved for delegated transfer by a third-party account. @@ -1306,33 +1242,7 @@ pub mod pallet { let delegate = ensure_signed(origin)?; let owner = T::Lookup::lookup(owner)?; let destination = T::Lookup::lookup(destination)?; - - Approvals::::try_mutate_exists( - (id, &owner, delegate), - |maybe_approved| -> DispatchResult { - let mut approved = maybe_approved.take().ok_or(Error::::Unapproved)?; - let remaining = - approved.amount.checked_sub(&amount).ok_or(Error::::Unapproved)?; - - let f = - TransferFlags { keep_alive: false, best_effort: false, burn_dust: false }; - Self::do_transfer(id, &owner, &destination, amount, None, f)?; - - if remaining.is_zero() { - T::Currency::unreserve(&owner, approved.deposit); - Asset::::mutate(id, |maybe_details| { - if let Some(details) = maybe_details { - details.approvals.saturating_dec(); - } - }); - } else { - approved.amount = remaining; - *maybe_approved = Some(approved); - } - Ok(()) - }, - )?; - Ok(()) + Self::do_transfer_approved(id, &owner, &delegate, &destination, amount) } } } diff --git a/frame/assets/src/tests.rs b/frame/assets/src/tests.rs index 872bd7290133..5250fafaa8f9 100644 --- a/frame/assets/src/tests.rs +++ b/frame/assets/src/tests.rs @@ -794,3 +794,37 @@ fn assets_from_genesis_should_exist() { assert_eq!(Assets::total_supply(999), 100); }); } + +#[test] +fn querying_name_symbol_and_decimals_should_work() { + new_test_ext().execute_with(|| { + use frame_support::traits::tokens::fungibles::metadata::Inspect; + assert_ok!(Assets::force_create(Origin::root(), 0, 1, true, 1)); + assert_ok!(Assets::force_set_metadata( + Origin::root(), + 0, + vec![0u8; 10], + vec![1u8; 10], + 12, + false + )); + assert_eq!(Assets::name(0), vec![0u8; 10]); + assert_eq!(Assets::symbol(0), vec![1u8; 10]); + assert_eq!(Assets::decimals(0), 12); + }); +} + +#[test] +fn querying_allowance_should_work() { + new_test_ext().execute_with(|| { + use frame_support::traits::tokens::fungibles::approvals::{Inspect, Mutate}; + assert_ok!(Assets::force_create(Origin::root(), 0, 1, true, 1)); + assert_ok!(Assets::mint(Origin::signed(1), 0, 1, 100)); + Balances::make_free_balance_be(&1, 1); + assert_ok!(Assets::approve(0, &1, &2, 50)); + assert_eq!(Assets::allowance(0, &1, &2), 50); + // Transfer asset 0, from owner 1 and delegate 2 to destination 3 + assert_ok!(Assets::transfer_from(0, &1, &2, &3, 50)); + assert_eq!(Assets::allowance(0, &1, &2), 0); + }); +} diff --git a/frame/support/src/traits/tokens/fungibles.rs b/frame/support/src/traits/tokens/fungibles.rs index 2930853201d2..b164a9967165 100644 --- a/frame/support/src/traits/tokens/fungibles.rs +++ b/frame/support/src/traits/tokens/fungibles.rs @@ -25,7 +25,9 @@ use crate::dispatch::{DispatchError, DispatchResult}; use sp_runtime::traits::Saturating; use sp_std::vec::Vec; +pub mod approvals; mod balanced; +pub mod metadata; pub use balanced::{Balanced, Unbalanced}; mod imbalance; pub use imbalance::{CreditOf, DebtOf, HandleImbalanceDrop, Imbalance}; diff --git a/frame/support/src/traits/tokens/fungibles/approvals.rs b/frame/support/src/traits/tokens/fungibles/approvals.rs new file mode 100644 index 000000000000..06e81b8591a8 --- /dev/null +++ b/frame/support/src/traits/tokens/fungibles/approvals.rs @@ -0,0 +1,43 @@ +// This file is part of Substrate. + +// Copyright (C) 2019-2021 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. + +//! Inspect and Mutate traits for Asset approvals + +use crate::dispatch::DispatchResult; +pub trait Inspect: super::Inspect { + // Check the amount approved by an owner to be spent by a delegate + fn allowance(asset: Self::AssetId, owner: &AccountId, delegate: &AccountId) -> Self::Balance; +} + +pub trait Mutate: Inspect { + // Aprove a delegate account to spend an amount of tokens owned by an owner + fn approve( + asset: Self::AssetId, + owner: &AccountId, + delegate: &AccountId, + amount: Self::Balance, + ) -> DispatchResult; + + // Transfer from a delegate account an amount approved by the owner of the asset + fn transfer_from( + asset: Self::AssetId, + owner: &AccountId, + delegate: &AccountId, + dest: &AccountId, + amount: Self::Balance, + ) -> DispatchResult; +} diff --git a/frame/support/src/traits/tokens/fungibles/metadata.rs b/frame/support/src/traits/tokens/fungibles/metadata.rs new file mode 100644 index 000000000000..08bf5c4710a7 --- /dev/null +++ b/frame/support/src/traits/tokens/fungibles/metadata.rs @@ -0,0 +1,41 @@ +// This file is part of Substrate. + +// Copyright (C) 2019-2021 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. + +//! Inspect and Mutate traits for Asset metadata + +use crate::dispatch::DispatchResult; +use sp_std::vec::Vec; + +pub trait Inspect: super::Inspect { + // Get name for an AssetId. + fn name(asset: Self::AssetId) -> Vec; + // Get symbol for an AssetId. + fn symbol(asset: Self::AssetId) -> Vec; + // Get decimals for an AssetId. + fn decimals(asset: Self::AssetId) -> u8; +} + +pub trait Mutate: Inspect { + // Set name, symbol and decimals for a given assetId. + fn set( + asset: Self::AssetId, + from: &AccountId, + name: Vec, + symbol: Vec, + decimals: u8, + ) -> DispatchResult; +} From eb5cba0ce4d300b5c202819c38fbde4ecce25281 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 7 Oct 2021 17:18:13 +0200 Subject: [PATCH 047/695] Bump tracing from 0.1.25 to 0.1.29 (#9956) Bumps [tracing](https://github.com/tokio-rs/tracing) from 0.1.25 to 0.1.29. - [Release notes](https://github.com/tokio-rs/tracing/releases) - [Commits](https://github.com/tokio-rs/tracing/compare/tracing-0.1.25...tracing-0.1.29) --- updated-dependencies: - dependency-name: tracing dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 12 ++++++------ client/executor/Cargo.toml | 2 +- client/network-gossip/Cargo.toml | 2 +- client/service/Cargo.toml | 2 +- client/tracing/Cargo.toml | 2 +- primitives/io/Cargo.toml | 2 +- primitives/runtime-interface/test/Cargo.toml | 2 +- primitives/state-machine/Cargo.toml | 2 +- primitives/tracing/Cargo.toml | 2 +- 9 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 44d285b232b8..1c518cd06489 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10626,9 +10626,9 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" [[package]] name = "tracing" -version = "0.1.25" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01ebdc2bb4498ab1ab5f5b73c5803825e60199229ccba0698170e3be0e7f959f" +checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" dependencies = [ "cfg-if 1.0.0", "pin-project-lite 0.2.6", @@ -10638,9 +10638,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.15" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42e6fa53307c8a17e4ccd4dc81cf5ec38db9209f59b222210375b54ee40d1e2" +checksum = "f4f480b8f81512e825f337ad51e94c1eb5d3bbdf2b363dcd01e2b19a9ffe3f8e" dependencies = [ "proc-macro2", "quote", @@ -10649,9 +10649,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.17" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f50de3927f93d202783f4513cda820ab47ef17f624b03c096e86ef00c67e6b5f" +checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4" dependencies = [ "lazy_static", ] diff --git a/client/executor/Cargo.toml b/client/executor/Cargo.toml index b7e2595b8e16..b7eb31a37593 100644 --- a/client/executor/Cargo.toml +++ b/client/executor/Cargo.toml @@ -43,7 +43,7 @@ sp-state-machine = { version = "0.10.0-dev", path = "../../primitives/state-mach sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } sp-maybe-compressed-blob = { version = "4.0.0-dev", path = "../../primitives/maybe-compressed-blob" } sc-tracing = { version = "4.0.0-dev", path = "../tracing" } -tracing = "0.1.25" +tracing = "0.1.29" tracing-subscriber = "0.2.19" paste = "1.0" regex = "1" diff --git a/client/network-gossip/Cargo.toml b/client/network-gossip/Cargo.toml index b5fdcfd43430..a73bfb0c2657 100644 --- a/client/network-gossip/Cargo.toml +++ b/client/network-gossip/Cargo.toml @@ -23,7 +23,7 @@ lru = "0.6.6" prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.9.0", path = "../../utils/prometheus" } sc-network = { version = "0.10.0-dev", path = "../network" } sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } -tracing = "0.1.25" +tracing = "0.1.29" [dev-dependencies] async-std = "1.10.0" diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index 735f215c82b3..6f63a249a7c8 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -73,7 +73,7 @@ sc-offchain = { version = "4.0.0-dev", path = "../offchain" } prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.9.0" } sc-tracing = { version = "4.0.0-dev", path = "../tracing" } sp-tracing = { version = "4.0.0-dev", path = "../../primitives/tracing" } -tracing = "0.1.25" +tracing = "0.1.29" tracing-futures = { version = "0.2.4" } parity-util-mem = { version = "0.10.0", default-features = false, features = [ "primitive-types", diff --git a/client/tracing/Cargo.toml b/client/tracing/Cargo.toml index 5cac4dccfd6e..2d05f80be42b 100644 --- a/client/tracing/Cargo.toml +++ b/client/tracing/Cargo.toml @@ -24,7 +24,7 @@ regex = "1.4.2" rustc-hash = "1.1.0" serde = "1.0.126" thiserror = "1.0.21" -tracing = "0.1.25" +tracing = "0.1.29" tracing-log = "0.1.2" tracing-subscriber = "0.2.19" sp-tracing = { version = "4.0.0-dev", path = "../../primitives/tracing" } diff --git a/primitives/io/Cargo.toml b/primitives/io/Cargo.toml index 5a8c1c4af4f9..2323b5281d59 100644 --- a/primitives/io/Cargo.toml +++ b/primitives/io/Cargo.toml @@ -30,7 +30,7 @@ sp-tracing = { version = "4.0.0-dev", default-features = false, path = "../traci log = { version = "0.4.8", optional = true } futures = { version = "0.3.1", features = ["thread-pool"], optional = true } parking_lot = { version = "0.11.1", optional = true } -tracing = { version = "0.1.25", default-features = false } +tracing = { version = "0.1.29", default-features = false } tracing-core = { version = "0.1.17", default-features = false} [features] diff --git a/primitives/runtime-interface/test/Cargo.toml b/primitives/runtime-interface/test/Cargo.toml index 377729521fcf..383df494120a 100644 --- a/primitives/runtime-interface/test/Cargo.toml +++ b/primitives/runtime-interface/test/Cargo.toml @@ -20,5 +20,5 @@ sp-runtime-interface-test-wasm-deprecated = { version = "2.0.0", path = "../test sp-state-machine = { version = "0.10.0-dev", path = "../../state-machine" } sp-runtime = { version = "4.0.0-dev", path = "../../runtime" } sp-io = { version = "4.0.0-dev", path = "../../io" } -tracing = "0.1.25" +tracing = "0.1.29" tracing-core = "0.1.17" diff --git a/primitives/state-machine/Cargo.toml b/primitives/state-machine/Cargo.toml index 903db18a38ca..d62b598fdc3a 100644 --- a/primitives/state-machine/Cargo.toml +++ b/primitives/state-machine/Cargo.toml @@ -29,7 +29,7 @@ rand = { version = "0.7.2", optional = true } sp-externalities = { version = "0.10.0-dev", path = "../externalities", default-features = false } smallvec = "1.7.0" sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" } -tracing = { version = "0.1.22", optional = true } +tracing = { version = "0.1.29", optional = true } [dev-dependencies] hex-literal = "0.3.1" diff --git a/primitives/tracing/Cargo.toml b/primitives/tracing/Cargo.toml index 3be09dcd576d..ebcddb1477d3 100644 --- a/primitives/tracing/Cargo.toml +++ b/primitives/tracing/Cargo.toml @@ -22,7 +22,7 @@ sp-std = { version = "4.0.0-dev", path = "../std", default-features = false } codec = { version = "2.0.0", package = "parity-scale-codec", default-features = false, features = [ "derive", ] } -tracing = { version = "0.1.25", default-features = false } +tracing = { version = "0.1.29", default-features = false } tracing-core = { version = "0.1.17", default-features = false } log = { version = "0.4.8", optional = true } tracing-subscriber = { version = "0.2.19", optional = true, features = [ From 7dbcd4f4418dd8287fbc822c444076ead6c91564 Mon Sep 17 00:00:00 2001 From: Guillaume Thiolliere Date: Thu, 7 Oct 2021 17:46:06 +0200 Subject: [PATCH 048/695] Root origin always bypass all filter, other origin cannot bypass BaseCallFilter even when constructed from Root origin (#9948) * improve root filter bypass * improve doc * fmt * refactor test for more understandable flow * Update frame/support/procedural/src/construct_runtime/expand/origin.rs Co-authored-by: Keith Yeung * match Co-authored-by: Keith Yeung --- .../src/construct_runtime/expand/origin.rs | 27 +++++++++---------- frame/support/src/traits/dispatch.rs | 11 +++++--- frame/support/test/tests/construct_runtime.rs | 18 ++++++++++--- 3 files changed, 35 insertions(+), 21 deletions(-) diff --git a/frame/support/procedural/src/construct_runtime/expand/origin.rs b/frame/support/procedural/src/construct_runtime/expand/origin.rs index a65ad78527ff..57adf86a9fe1 100644 --- a/frame/support/procedural/src/construct_runtime/expand/origin.rs +++ b/frame/support/procedural/src/construct_runtime/expand/origin.rs @@ -82,8 +82,9 @@ pub fn expand_outer_origin( Ok(quote! { #( #query_origin_part_macros )* - // WARNING: All instance must hold the filter `frame_system::Config::BaseCallFilter`, except - // when caller is system Root. One can use `OriginTrait::reset_filter` to do so. + /// The runtime origin type represanting the origin of a call. + /// + /// Origin is always created with the base filter configured in `frame_system::Config::BaseCallFilter`. #[derive(Clone)] pub struct Origin { caller: OriginCaller, @@ -140,7 +141,11 @@ pub fn expand_outer_origin( } fn filter_call(&self, call: &Self::Call) -> bool { - (self.filter)(call) + match self.caller { + // Root bypasses all filters + OriginCaller::system(#system_path::Origin::<#runtime>::Root) => true, + _ => (self.filter)(call), + } } fn caller(&self) -> &Self::PalletsOrigin { @@ -157,15 +162,14 @@ pub fn expand_outer_origin( } } - /// Create with system none origin and `frame-system::Config::BaseCallFilter`. fn none() -> Self { #system_path::RawOrigin::None.into() } - /// Create with system root origin and no filter. + fn root() -> Self { #system_path::RawOrigin::Root.into() } - /// Create with system signed origin and `frame-system::Config::BaseCallFilter`. + fn signed(by: <#runtime as #system_path::Config>::AccountId) -> Self { #system_path::RawOrigin::Signed(by).into() } @@ -191,7 +195,7 @@ pub fn expand_outer_origin( pub fn none() -> Self { ::none() } - /// Create with system root origin and no filter. + /// Create with system root origin and `frame-system::Config::BaseCallFilter`. pub fn root() -> Self { ::root() } @@ -221,9 +225,7 @@ pub fn expand_outer_origin( } impl From<#system_path::Origin<#runtime>> for Origin { - /// Convert to runtime origin: - /// * root origin is built with no filter - /// * others use `frame-system::Config::BaseCallFilter` + /// Convert to runtime origin, using as filter: `frame-system::Config::BaseCallFilter`. fn from(x: #system_path::Origin<#runtime>) -> Self { let o: OriginCaller = x.into(); o.into() @@ -237,10 +239,7 @@ pub fn expand_outer_origin( filter: #scrate::sp_std::rc::Rc::new(Box::new(|_| true)), }; - // Root has no filter - if !matches!(o.caller, OriginCaller::system(#system_path::Origin::<#runtime>::Root)) { - #scrate::traits::OriginTrait::reset_filter(&mut o); - } + #scrate::traits::OriginTrait::reset_filter(&mut o); o } diff --git a/frame/support/src/traits/dispatch.rs b/frame/support/src/traits/dispatch.rs index f82628ede18c..92b832ba3296 100644 --- a/frame/support/src/traits/dispatch.rs +++ b/frame/support/src/traits/dispatch.rs @@ -70,7 +70,10 @@ pub trait OriginTrait: Sized { /// Replace the caller with caller from the other origin fn set_caller_from(&mut self, other: impl Into); - /// Filter the call, if false then call is filtered out. + /// Filter the call if caller is not root, if false is returned then the call must be filtered + /// out. + /// + /// For root origin caller, the filters are bypassed and true is returned. fn filter_call(&self, call: &Self::Call) -> bool; /// Get the caller. @@ -82,12 +85,12 @@ pub trait OriginTrait: Sized { f: impl FnOnce(Self::PalletsOrigin) -> Result, ) -> Result; - /// Create with system none origin and `frame-system::Config::BaseCallFilter`. + /// Create with system none origin and `frame_system::Config::BaseCallFilter`. fn none() -> Self; - /// Create with system root origin and no filter. + /// Create with system root origin and `frame_system::Config::BaseCallFilter`. fn root() -> Self; - /// Create with system signed origin and `frame-system::Config::BaseCallFilter`. + /// Create with system signed origin and `frame_system::Config::BaseCallFilter`. fn signed(by: Self::AccountId) -> Self; } diff --git a/frame/support/test/tests/construct_runtime.rs b/frame/support/test/tests/construct_runtime.rs index dd5538370449..2d14da04f64b 100644 --- a/frame/support/test/tests/construct_runtime.rs +++ b/frame/support/test/tests/construct_runtime.rs @@ -327,19 +327,31 @@ mod origin_test { assert_eq!(Origin::from(super::nested::module3::Origin).filter_call(&rejected_call), false); let mut origin = Origin::from(Some(0)); - origin.add_filter(|c| matches!(c, Call::Module3(_))); assert_eq!(origin.filter_call(&accepted_call), false); assert_eq!(origin.filter_call(&rejected_call), false); + // Now test for root origin and filters: + let mut origin = Origin::from(Some(0)); origin.set_caller_from(Origin::root()); assert!(matches!(origin.caller, OriginCaller::system(super::system::RawOrigin::Root))); - assert_eq!(origin.filter_call(&accepted_call), false); + + // Root origin bypass all filter. + assert_eq!(origin.filter_call(&accepted_call), true); + assert_eq!(origin.filter_call(&rejected_call), true); + + origin.set_caller_from(Origin::from(Some(0))); + + // Back to another signed origin, the filtered are now effective again + assert_eq!(origin.filter_call(&accepted_call), true); assert_eq!(origin.filter_call(&rejected_call), false); + origin.set_caller_from(Origin::root()); origin.reset_filter(); + + // Root origin bypass all filter, even when they are reset. assert_eq!(origin.filter_call(&accepted_call), true); - assert_eq!(origin.filter_call(&rejected_call), false); + assert_eq!(origin.filter_call(&rejected_call), true); } } From 48f3cdd8f9720efd488a0f44cf6d923feb17ef03 Mon Sep 17 00:00:00 2001 From: Eric Miller Date: Thu, 7 Oct 2021 19:02:09 -0400 Subject: [PATCH 049/695] Support extra constant renaming (#9814) * Rebased with master. Resolved merge conflict in frame/support/test/tests/pallet.rs * Switching Account ID to SomeType1, as SomeType3 was giving me conversion error. * Wrong indent config. Fixed. * These tabs look fine locally, but look different on Github. Trying to get the style config right. * Parsing pallet::constant_name. Passing unit tests, which is confusing because I didn't change `ident` in the ExtraConstantDef initialization. * Finalized parsing of extra constant name by adding optional metadata field. Added expansion logic that replaces respective `idents` where they exist. * Erasing this to try to keep the format the same across the source code. * Another formatting change for consistency. * Update frame/support/procedural/src/pallet/expand/constants.rs strictly more idiomatic. Co-authored-by: Guillaume Thiolliere * Update frame/support/procedural/src/pallet/parse/extra_constants.rs strictly idiomatic change. Co-authored-by: Guillaume Thiolliere * Fixing formatting and CI warnings. * switched to nightly compiler to use rustfmt.toml Co-authored-by: Eric Miller Co-authored-by: Guillaume Thiolliere --- .../procedural/src/pallet/expand/constants.rs | 8 +++- .../src/pallet/parse/extra_constants.rs | 42 ++++++++++++++++++- .../procedural/src/pallet/parse/helper.rs | 6 +++ frame/support/test/tests/pallet.rs | 12 ++++++ 4 files changed, 65 insertions(+), 3 deletions(-) diff --git a/frame/support/procedural/src/pallet/expand/constants.rs b/frame/support/procedural/src/pallet/expand/constants.rs index db47bf552ac1..20106c71cbf0 100644 --- a/frame/support/procedural/src/pallet/expand/constants.rs +++ b/frame/support/procedural/src/pallet/expand/constants.rs @@ -26,6 +26,8 @@ struct ConstDef { pub doc: Vec, /// default_byte implementation pub default_byte_impl: proc_macro2::TokenStream, + /// Constant name for Metadata (optional) + pub metadata_name: Option, } /// @@ -54,6 +56,7 @@ pub fn expand_constants(def: &mut Def) -> proc_macro2::TokenStream { #frame_support::traits::Get<#const_type>>::get(); #frame_support::codec::Encode::encode(&value) ), + metadata_name: None, } }); @@ -68,13 +71,14 @@ pub fn expand_constants(def: &mut Def) -> proc_macro2::TokenStream { let value = >::#ident(); #frame_support::codec::Encode::encode(&value) ), + metadata_name: const_.metadata_name.clone(), } }); let consts = config_consts.chain(extra_consts).map(|const_| { let const_type = &const_.type_; - let ident = &const_.ident; - let ident_str = format!("{}", ident); + let ident_str = format!("{}", const_.metadata_name.unwrap_or(const_.ident)); + let doc = const_.doc.clone().into_iter(); let default_byte_impl = &const_.default_byte_impl; diff --git a/frame/support/procedural/src/pallet/parse/extra_constants.rs b/frame/support/procedural/src/pallet/parse/extra_constants.rs index c1324df6c22f..a5f3c0a8c2da 100644 --- a/frame/support/procedural/src/pallet/parse/extra_constants.rs +++ b/frame/support/procedural/src/pallet/parse/extra_constants.rs @@ -28,6 +28,7 @@ mod keyword { syn::custom_keyword!(compact); syn::custom_keyword!(T); syn::custom_keyword!(pallet); + syn::custom_keyword!(constant_name); } /// Definition of extra constants typically `impl Pallet { ... }` @@ -50,6 +51,29 @@ pub struct ExtraConstantDef { pub type_: syn::Type, /// The doc associated pub doc: Vec, + /// Optional MetaData Name + pub metadata_name: Option, +} + +/// Attributes for functions in extra_constants impl block. +/// Parse for `#[pallet::constant_name(ConstantName)]` +pub struct ExtraConstAttr { + metadata_name: syn::Ident, +} + +impl syn::parse::Parse for ExtraConstAttr { + fn parse(input: syn::parse::ParseStream) -> syn::Result { + input.parse::()?; + let content; + syn::bracketed!(content in input); + content.parse::()?; + content.parse::()?; + content.parse::()?; + + let metadata_name; + syn::parenthesized!(metadata_name in content); + Ok(ExtraConstAttr { metadata_name: metadata_name.parse::()? }) + } } impl ExtraConstantsDef { @@ -57,7 +81,10 @@ impl ExtraConstantsDef { let item = if let syn::Item::Impl(item) = item { item } else { - return Err(syn::Error::new(item.span(), "Invalid pallet::call, expected item impl")) + return Err(syn::Error::new( + item.span(), + "Invalid pallet::extra_constants, expected item impl", + )) }; let mut instances = vec![]; @@ -102,10 +129,23 @@ impl ExtraConstantsDef { syn::ReturnType::Type(_, type_) => *type_.clone(), }; + // parse metadata_name + let mut extra_constant_attrs: Vec = + helper::take_item_pallet_attrs(method)?; + + if extra_constant_attrs.len() > 1 { + let msg = + "Invalid attribute in pallet::constant_name, only one attribute is expected"; + return Err(syn::Error::new(extra_constant_attrs[1].metadata_name.span(), msg)) + } + + let metadata_name = extra_constant_attrs.pop().map(|attr| attr.metadata_name); + extra_constants.push(ExtraConstantDef { ident: method.sig.ident.clone(), type_, doc: get_doc_literals(&method.attrs), + metadata_name, }); } diff --git a/frame/support/procedural/src/pallet/parse/helper.rs b/frame/support/procedural/src/pallet/parse/helper.rs index 2590e86b58b0..f5a7dc233cac 100644 --- a/frame/support/procedural/src/pallet/parse/helper.rs +++ b/frame/support/procedural/src/pallet/parse/helper.rs @@ -139,6 +139,12 @@ impl MutItemAttrs for syn::ItemMod { } } +impl MutItemAttrs for syn::ImplItemMethod { + fn mut_item_attrs(&mut self) -> Option<&mut Vec> { + Some(&mut self.attrs) + } +} + /// Parse for `()` struct Unit; impl syn::parse::Parse for Unit { diff --git a/frame/support/test/tests/pallet.rs b/frame/support/test/tests/pallet.rs index 25fc2d46d256..dc72be3ebdd4 100644 --- a/frame/support/test/tests/pallet.rs +++ b/frame/support/test/tests/pallet.rs @@ -146,6 +146,12 @@ pub mod pallet { fn some_extra_extra() -> T::AccountId { SomeType1.into() } + + /// Some doc + #[pallet::constant_name(SomeExtraRename)] + fn some_extra_rename() -> T::AccountId { + SomeType1.into() + } } #[pallet::pallet] @@ -1220,6 +1226,12 @@ fn metadata() { value: vec![0, 0, 0, 0, 0, 0, 0, 0], docs: vec![" Some doc"], }, + PalletConstantMetadata { + name: "SomeExtraRename", + ty: meta_type::(), + value: vec![0, 0, 0, 0, 0, 0, 0, 0], + docs: vec![" Some doc"], + }, ], error: Some(PalletErrorMetadata { ty: meta_type::>() }), }, From 4a9b8d1977ff5844ef07be76337de7034d1d50d3 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Fri, 8 Oct 2021 04:44:24 +0200 Subject: [PATCH 050/695] Remove unnecessary mut reference in `handle_justification` (#9968) --- client/consensus/common/src/block_import.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/consensus/common/src/block_import.rs b/client/consensus/common/src/block_import.rs index 6d411dd9afbf..d828e54bc7e3 100644 --- a/client/consensus/common/src/block_import.rs +++ b/client/consensus/common/src/block_import.rs @@ -74,7 +74,7 @@ impl ImportResult { &self, hash: &B::Hash, number: NumberFor, - justification_sync_link: &mut dyn JustificationSyncLink, + justification_sync_link: &dyn JustificationSyncLink, ) where B: BlockT, { From 911c1889ce8bb4d6ec88def60496b1c651a554d9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Oct 2021 09:38:58 +0200 Subject: [PATCH 051/695] Bump jsonrpsee-proc-macros from 0.3.0 to 0.3.1 (#9957) Bumps [jsonrpsee-proc-macros](https://github.com/paritytech/jsonrpsee) from 0.3.0 to 0.3.1. - [Release notes](https://github.com/paritytech/jsonrpsee/releases) - [Changelog](https://github.com/paritytech/jsonrpsee/blob/master/CHANGELOG.md) - [Commits](https://github.com/paritytech/jsonrpsee/compare/v0.3.0...v0.3.1) --- updated-dependencies: - dependency-name: jsonrpsee-proc-macros dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- utils/frame/remote-externalities/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1c518cd06489..ce65894b13ae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3123,9 +3123,9 @@ dependencies = [ [[package]] name = "jsonrpsee-proc-macros" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f37924e16300e249a52a22cabb5632f846dc9760b39355f5e8bc70cd23dc6300" +checksum = "8edb341d35279b59c79d7fe9e060a51aec29d45af99cc7c72ea7caa350fa71a4" dependencies = [ "Inflector", "bae", diff --git a/utils/frame/remote-externalities/Cargo.toml b/utils/frame/remote-externalities/Cargo.toml index ce774679f94c..1fbe1a7ea1d8 100644 --- a/utils/frame/remote-externalities/Cargo.toml +++ b/utils/frame/remote-externalities/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] jsonrpsee-ws-client = { version = "0.3.0", default-features = false, features = [ "tokio1", ]} -jsonrpsee-proc-macros = "0.3.0" +jsonrpsee-proc-macros = "0.3.1" env_logger = "0.9" log = "0.4.11" From d9944b0a9aa62c2ebc1953fc7d7725f0bbc48de0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Fri, 8 Oct 2021 10:02:25 +0200 Subject: [PATCH 052/695] Transaction pool: Adds benchmark and improves performance (#9958) * Yep * Make it compile * Make the benchmark work * Some stuff * Optimize transaction pool `BestIterator` * Some docs * Fix more warnings * Fix compilation * FMT --- Cargo.lock | 65 ++--- bin/node/cli/Cargo.toml | 10 +- bin/node/cli/benches/transaction_pool.rs | 274 ++++++++++++++++++ bin/node/cli/src/lib.rs | 2 +- bin/node/cli/src/service.rs | 92 +++++- bin/node/runtime/src/lib.rs | 2 + client/transaction-pool/src/graph/ready.rs | 12 +- .../transaction-pool/src/graph/tracked_map.rs | 21 +- client/transaction-pool/src/lib.rs | 2 +- 9 files changed, 415 insertions(+), 65 deletions(-) create mode 100644 bin/node/cli/benches/transaction_pool.rs diff --git a/Cargo.lock b/Cargo.lock index ce65894b13ae..8194c0a1b12d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1200,7 +1200,7 @@ dependencies = [ "cranelift-codegen 0.76.0", "cranelift-entity 0.76.0", "cranelift-frontend 0.76.0", - "itertools 0.10.0", + "itertools", "log 0.4.14", "serde", "smallvec 1.7.0", @@ -1219,16 +1219,17 @@ dependencies = [ [[package]] name = "criterion" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab327ed7354547cc2ef43cbe20ef68b988e70b4b593cbd66a2a61733123a3d23" +checksum = "1604dafd25fba2fe2d5895a9da139f8dc9b319a5fe5354ca137cbbce4e178d10" dependencies = [ "atty", "cast", "clap", "criterion-plot", "csv", - "itertools 0.10.0", + "futures 0.3.16", + "itertools", "lazy_static", "num-traits", "oorandom", @@ -1240,17 +1241,18 @@ dependencies = [ "serde_derive", "serde_json", "tinytemplate", + "tokio", "walkdir", ] [[package]] name = "criterion-plot" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e022feadec601fba1649cfa83586381a4ad31c6bf3a9ab7d408118b05dd9889d" +checksum = "d00996de9f2f7559f7f4dc286073197f83e92256a59ed395f9aac01fe717da57" dependencies = [ "cast", - "itertools 0.9.0", + "itertools", ] [[package]] @@ -2943,15 +2945,6 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47be2f14c678be2fdcab04ab1171db51b2762ce6f0a8ee87c8dd4a04ed216135" -[[package]] -name = "itertools" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.10.0" @@ -2978,9 +2971,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.50" +version = "0.3.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d99f9e3e84b8f67f846ef5b4cbbc3b1c29f6c759fcbce6f01aa0e73d932a24c" +checksum = "1866b355d9c878e5e607473cbe3f63282c0b7aad2db1dbebf55076c686918254" dependencies = [ "wasm-bindgen", ] @@ -4469,8 +4462,10 @@ version = "3.0.0-dev" dependencies = [ "assert_cmd", "async-std", + "criterion", "frame-benchmarking-cli", "frame-system", + "frame-system-rpc-runtime-api", "futures 0.3.16", "hex-literal", "jsonrpsee-ws-client", @@ -4481,6 +4476,7 @@ dependencies = [ "node-primitives", "node-rpc", "node-runtime", + "pallet-balances", "pallet-im-online", "pallet-transaction-payment", "parity-scale-codec", @@ -4513,6 +4509,7 @@ dependencies = [ "serde", "serde_json", "soketto 0.4.2", + "sp-api", "sp-authority-discovery", "sp-authorship", "sp-consensus", @@ -6538,9 +6535,9 @@ checksum = "989d43012e2ca1c4a02507c67282691a0a3207f9dc67cec596b43fe925b3d325" [[package]] name = "plotters" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45ca0ae5f169d0917a7c7f5a9c1a3d3d9598f18f529dd2b8373ed988efea307a" +checksum = "32a3fd9ec30b9749ce28cd91f255d569591cdf937fe280c312143e3c4bad6f2a" dependencies = [ "num-traits", "plotters-backend", @@ -6780,7 +6777,7 @@ checksum = "355f634b43cdd80724ee7848f95770e7e70eefa6dcf14fea676216573b8fd603" dependencies = [ "bytes 1.0.1", "heck", - "itertools 0.10.0", + "itertools", "log 0.4.14", "multimap", "petgraph", @@ -6797,7 +6794,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "600d2f334aa05acb02a755e217ef1ab6dea4d51b58b7846588b747edec04efba" dependencies = [ "anyhow", - "itertools 0.10.0", + "itertools", "proc-macro2", "quote", "syn", @@ -11115,9 +11112,9 @@ checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" [[package]] name = "wasm-bindgen" -version = "0.2.73" +version = "0.2.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83240549659d187488f91f33c0f8547cbfef0b2088bc470c116d1d260ef623d9" +checksum = "5e68338db6becec24d3c7977b5bf8a48be992c934b5d07177e3931f5dc9b076c" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -11125,9 +11122,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.73" +version = "0.2.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae70622411ca953215ca6d06d3ebeb1e915f0f6613e3b495122878d7ebec7dae" +checksum = "f34c405b4f0658583dba0c1c7c9b694f3cac32655db463b56c254a1c75269523" dependencies = [ "bumpalo", "lazy_static", @@ -11152,9 +11149,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.73" +version = "0.2.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e734d91443f177bfdb41969de821e15c516931c3c3db3d318fa1b68975d0f6f" +checksum = "b9d5a6580be83b19dc570a8f9c324251687ab2184e57086f71625feb57ec77c8" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -11162,9 +11159,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.73" +version = "0.2.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53739ff08c8a68b0fdbcd54c372b8ab800b1449ab3c9d706503bc7dd1621b2c" +checksum = "e3775a030dc6f5a0afd8a84981a21cc92a781eb429acef9ecce476d0c9113e92" dependencies = [ "proc-macro2", "quote", @@ -11175,9 +11172,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.73" +version = "0.2.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9a543ae66aa233d14bb765ed9af4a33e81b8b58d1584cf1b47ff8cd0b9e4489" +checksum = "c279e376c7a8e8752a8f1eaa35b7b0bee6bb9fb0cdacfa97cc3f1f289c87e2b4" [[package]] name = "wasm-gc-api" @@ -11648,9 +11645,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.47" +version = "0.3.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c40dc691fc48003eba817c38da7113c15698142da971298003cac3ef175680b3" +checksum = "0a84d70d1ec7d2da2d26a5bd78f4bca1b8c3254805363ce743b7a05bc30d195a" dependencies = [ "js-sys", "wasm-bindgen", diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index 42bc48e824c6..8b14f1cbeeb8 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -46,6 +46,7 @@ structopt = { version = "0.3.8", optional = true } sp-authority-discovery = { version = "4.0.0-dev", path = "../../../primitives/authority-discovery" } sp-consensus-babe = { version = "0.10.0-dev", path = "../../../primitives/consensus/babe" } grandpa-primitives = { version = "4.0.0-dev", package = "sp-finality-grandpa", path = "../../../primitives/finality-grandpa" } +sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" } sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } sp-timestamp = { version = "4.0.0-dev", path = "../../../primitives/timestamp" } @@ -78,6 +79,7 @@ sc-sync-state-rpc = { version = "0.10.0-dev", path = "../../../client/sync-state # frame dependencies frame-system = { version = "4.0.0-dev", path = "../../../frame/system" } +frame-system-rpc-runtime-api = { version = "4.0.0-dev", path = "../../../frame/system/rpc/runtime-api" } pallet-transaction-payment = { version = "4.0.0-dev", path = "../../../frame/transaction-payment" } pallet-im-online = { version = "4.0.0-dev", default-features = false, path = "../../../frame/im-online" } @@ -124,8 +126,9 @@ regex = "1" platforms = "1.1" async-std = { version = "1.10.0", features = ["attributes"] } soketto = "0.4.2" -jsonrpsee-ws-client = { version = "0.3.0", default-features = false, features = ["tokio1"] } +criterion = { version = "0.3.5", features = [ "async_tokio" ] } tokio = { version = "1.10", features = ["macros", "time"] } +jsonrpsee-ws-client = { version = "0.3.0", default-features = false, features = ["tokio1"] } wait-timeout = "0.2" remote-externalities = { path = "../../../utils/frame/remote-externalities" } @@ -137,6 +140,7 @@ substrate-build-script-utils = { version = "3.0.0", optional = true, path = "../ substrate-frame-cli = { version = "4.0.0-dev", optional = true, path = "../../../utils/frame/frame-utilities-cli" } try-runtime-cli = { version = "0.10.0-dev", optional = true, path = "../../../utils/frame/try-runtime/cli" } sc-cli = { version = "0.10.0-dev", path = "../../../client/cli", optional = true } +pallet-balances = { version = "4.0.0-dev", path = "../../../frame/balances" } [features] default = ["cli"] @@ -158,3 +162,7 @@ runtime-benchmarks = [ # Enable features that allow the runtime to be tried and debugged. Name might be subject to change # in the near future. try-runtime = ["node-runtime/try-runtime", "try-runtime-cli"] + +[[bench]] +name = "transaction_pool" +harness = false diff --git a/bin/node/cli/benches/transaction_pool.rs b/bin/node/cli/benches/transaction_pool.rs new file mode 100644 index 000000000000..c435012e9f86 --- /dev/null +++ b/bin/node/cli/benches/transaction_pool.rs @@ -0,0 +1,274 @@ +// This file is part of Substrate. + +// Copyright (C) 2021 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 . + +use criterion::{criterion_group, criterion_main, BatchSize, Criterion, Throughput}; +use futures::{future, StreamExt}; +use node_cli::service::{create_extrinsic, fetch_nonce, FullClient, TransactionPool}; +use node_primitives::AccountId; +use node_runtime::{constants::currency::*, BalancesCall, SudoCall}; +use sc_client_api::execution_extensions::ExecutionStrategies; +use sc_service::{ + config::{ + DatabaseSource, KeepBlocks, KeystoreConfig, NetworkConfiguration, OffchainWorkerConfig, + PruningMode, TransactionPoolOptions, TransactionStorageMode, WasmExecutionMethod, + }, + BasePath, Configuration, Role, +}; +use sc_transaction_pool::PoolLimit; +use sc_transaction_pool_api::{TransactionPool as _, TransactionSource, TransactionStatus}; +use sp_core::{crypto::Pair, sr25519}; +use sp_keyring::Sr25519Keyring; +use sp_runtime::{generic::BlockId, OpaqueExtrinsic}; +use tokio::runtime::Handle; + +fn new_node(tokio_handle: Handle) -> node_cli::service::NewFullBase { + let base_path = BasePath::new_temp_dir().expect("Creates base path"); + let root = base_path.path().to_path_buf(); + + let network_config = NetworkConfiguration::new( + Sr25519Keyring::Alice.to_seed(), + "network/test/0.1", + Default::default(), + None, + ); + + let spec = Box::new(node_cli::chain_spec::development_config()); + + let config = Configuration { + impl_name: "BenchmarkImpl".into(), + impl_version: "1.0".into(), + role: Role::Authority, + tokio_handle, + transaction_pool: TransactionPoolOptions { + ready: PoolLimit { count: 100_000, total_bytes: 100 * 1024 * 1024 }, + future: PoolLimit { count: 100_000, total_bytes: 100 * 1024 * 1024 }, + reject_future_transactions: false, + }, + network: network_config, + keystore: KeystoreConfig::InMemory, + keystore_remote: Default::default(), + database: DatabaseSource::RocksDb { path: root.join("db"), cache_size: 128 }, + state_cache_size: 67108864, + state_cache_child_ratio: None, + state_pruning: PruningMode::ArchiveAll, + keep_blocks: KeepBlocks::All, + transaction_storage: TransactionStorageMode::BlockBody, + chain_spec: spec, + wasm_method: WasmExecutionMethod::Interpreted, + // NOTE: we enforce the use of the native runtime to make the errors more debuggable + execution_strategies: ExecutionStrategies { + syncing: sc_client_api::ExecutionStrategy::NativeWhenPossible, + importing: sc_client_api::ExecutionStrategy::NativeWhenPossible, + block_construction: sc_client_api::ExecutionStrategy::NativeWhenPossible, + offchain_worker: sc_client_api::ExecutionStrategy::NativeWhenPossible, + other: sc_client_api::ExecutionStrategy::NativeWhenPossible, + }, + rpc_http: None, + rpc_ws: None, + rpc_ipc: None, + rpc_ws_max_connections: None, + rpc_cors: None, + rpc_methods: Default::default(), + rpc_max_payload: None, + prometheus_config: None, + telemetry_endpoints: None, + default_heap_pages: None, + offchain_worker: OffchainWorkerConfig { enabled: true, indexing_enabled: false }, + force_authoring: false, + disable_grandpa: false, + dev_key_seed: Some(Sr25519Keyring::Alice.to_seed()), + tracing_targets: None, + tracing_receiver: Default::default(), + max_runtime_instances: 8, + announce_block: true, + base_path: Some(base_path), + informant_output_format: Default::default(), + wasm_runtime_overrides: None, + disable_log_reloading: false, + }; + + node_cli::service::new_full_base(config, |_, _| ()).expect("Creates node") +} + +fn create_accounts(num: usize) -> Vec { + (0..num) + .map(|i| { + Pair::from_string(&format!("{}/{}", Sr25519Keyring::Alice.to_seed(), i), None) + .expect("Creates account pair") + }) + .collect() +} + +/// Create the extrinsics that will initialize the accounts from the sudo account (Alice). +/// +/// `start_nonce` is the current nonce of Alice. +fn create_account_extrinsics( + client: &FullClient, + accounts: &[sr25519::Pair], +) -> Vec { + let start_nonce = fetch_nonce(client, Sr25519Keyring::Alice.pair()); + + accounts + .iter() + .enumerate() + .map(|(i, a)| { + vec![ + // Reset the nonce by removing any funds + create_extrinsic( + client, + Sr25519Keyring::Alice.pair(), + SudoCall::sudo { + call: Box::new( + BalancesCall::set_balance { + who: AccountId::from(a.public()).into(), + new_free: 0, + new_reserved: 0, + } + .into(), + ), + }, + Some(start_nonce + (i as u32) * 2), + ), + // Give back funds + create_extrinsic( + client, + Sr25519Keyring::Alice.pair(), + SudoCall::sudo { + call: Box::new( + BalancesCall::set_balance { + who: AccountId::from(a.public()).into(), + new_free: 1_000_000 * DOLLARS, + new_reserved: 0, + } + .into(), + ), + }, + Some(start_nonce + (i as u32) * 2 + 1), + ), + ] + }) + .flatten() + .map(OpaqueExtrinsic::from) + .collect() +} + +fn create_benchmark_extrinsics( + client: &FullClient, + accounts: &[sr25519::Pair], + extrinsics_per_account: usize, +) -> Vec { + accounts + .iter() + .map(|account| { + (0..extrinsics_per_account).map(move |nonce| { + create_extrinsic( + client, + account.clone(), + BalancesCall::transfer { + dest: Sr25519Keyring::Bob.to_account_id().into(), + value: 1 * DOLLARS, + }, + Some(nonce as u32), + ) + }) + }) + .flatten() + .map(OpaqueExtrinsic::from) + .collect() +} + +async fn submit_tx_and_wait_for_inclusion( + tx_pool: &TransactionPool, + tx: OpaqueExtrinsic, + client: &FullClient, + wait_for_finalized: bool, +) { + let best_hash = client.chain_info().best_hash; + + let mut watch = tx_pool + .submit_and_watch(&BlockId::Hash(best_hash), TransactionSource::External, tx.clone()) + .await + .expect("Submits tx to pool") + .fuse(); + + loop { + match watch.select_next_some().await { + TransactionStatus::Finalized(_) => break, + TransactionStatus::InBlock(_) if !wait_for_finalized => break, + _ => {}, + } + } +} + +fn transaction_pool_benchmarks(c: &mut Criterion) { + sp_tracing::try_init_simple(); + + let runtime = tokio::runtime::Runtime::new().expect("Creates tokio runtime"); + let tokio_handle = runtime.handle().clone(); + + let node = new_node(tokio_handle.clone()); + + let account_num = 10; + let extrinsics_per_account = 2000; + let accounts = create_accounts(account_num); + + let mut group = c.benchmark_group("Transaction pool"); + + group.sample_size(10); + group.throughput(Throughput::Elements(account_num as u64 * extrinsics_per_account as u64)); + + let mut counter = 1; + group.bench_function( + format!("{} transfers from {} accounts", account_num * extrinsics_per_account, account_num), + move |b| { + b.iter_batched( + || { + let prepare_extrinsics = create_account_extrinsics(&*node.client, &accounts); + + runtime.block_on(future::join_all(prepare_extrinsics.into_iter().map(|tx| { + submit_tx_and_wait_for_inclusion( + &node.transaction_pool, + tx, + &*node.client, + true, + ) + }))); + + create_benchmark_extrinsics(&*node.client, &accounts, extrinsics_per_account) + }, + |extrinsics| { + runtime.block_on(future::join_all(extrinsics.into_iter().map(|tx| { + submit_tx_and_wait_for_inclusion( + &node.transaction_pool, + tx, + &*node.client, + false, + ) + }))); + + println!("Finished {}", counter); + counter += 1; + }, + BatchSize::SmallInput, + ) + }, + ); +} + +criterion_group!(benches, transaction_pool_benchmarks); +criterion_main!(benches); diff --git a/bin/node/cli/src/lib.rs b/bin/node/cli/src/lib.rs index 1a4c1b0eab8d..ae851c6cdf62 100644 --- a/bin/node/cli/src/lib.rs +++ b/bin/node/cli/src/lib.rs @@ -33,7 +33,7 @@ pub mod chain_spec; #[macro_use] -mod service; +pub mod service; #[cfg(feature = "cli")] mod cli; #[cfg(feature = "cli")] diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index ec5497ab47d9..938f35936818 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -20,20 +20,25 @@ //! Service implementation. Specialized wrapper over substrate service. +use codec::Encode; +use frame_system_rpc_runtime_api::AccountNonceApi; use futures::prelude::*; use node_executor::ExecutorDispatch; use node_primitives::Block; use node_runtime::RuntimeApi; -use sc_client_api::{ExecutorProvider, RemoteBackend}; +use sc_client_api::{BlockBackend, ExecutorProvider, RemoteBackend}; use sc_consensus_babe::{self, SlotProportion}; use sc_executor::NativeElseWasmExecutor; use sc_network::{Event, NetworkService}; use sc_service::{config::Configuration, error::Error as ServiceError, RpcHandlers, TaskManager}; use sc_telemetry::{Telemetry, TelemetryWorker}; -use sp_runtime::traits::Block as BlockT; +use sp_api::ProvideRuntimeApi; +use sp_core::crypto::Pair; +use sp_runtime::{generic, traits::Block as BlockT, SaturatedConversion}; use std::sync::Arc; -type FullClient = +/// The full client type definition. +pub type FullClient = sc_service::TFullClient>; type FullBackend = sc_service::TFullBackend; type FullSelectChain = sc_consensus::LongestChain; @@ -41,7 +46,80 @@ type FullGrandpaBlockImport = grandpa::GrandpaBlockImport; type LightClient = sc_service::TLightClient>; +/// The transaction pool type defintion. +pub type TransactionPool = sc_transaction_pool::FullPool; + +/// Fetch the nonce of the given `account` from the chain state. +/// +/// Note: Should only be used for tests. +pub fn fetch_nonce(client: &FullClient, account: sp_core::sr25519::Pair) -> u32 { + let best_hash = client.chain_info().best_hash; + client + .runtime_api() + .account_nonce(&generic::BlockId::Hash(best_hash), account.public().into()) + .expect("Fetching account nonce works; qed") +} + +/// Create a transaction using the given `call`. +/// +/// The transaction will be signed by `sender`. If `nonce` is `None` it will be fetched from the +/// state of the best block. +/// +/// Note: Should only be used for tests. +pub fn create_extrinsic( + client: &FullClient, + sender: sp_core::sr25519::Pair, + function: impl Into, + nonce: Option, +) -> node_runtime::UncheckedExtrinsic { + let function = function.into(); + let genesis_hash = client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"); + let best_hash = client.chain_info().best_hash; + let best_block = client.chain_info().best_number; + let nonce = nonce.unwrap_or_else(|| fetch_nonce(client, sender.clone())); + + let period = node_runtime::BlockHashCount::get() + .checked_next_power_of_two() + .map(|c| c / 2) + .unwrap_or(2) as u64; + let tip = 0; + let extra: node_runtime::SignedExtra = ( + frame_system::CheckSpecVersion::::new(), + frame_system::CheckTxVersion::::new(), + frame_system::CheckGenesis::::new(), + frame_system::CheckEra::::from(generic::Era::mortal( + period, + best_block.saturated_into(), + )), + frame_system::CheckNonce::::from(nonce), + frame_system::CheckWeight::::new(), + pallet_transaction_payment::ChargeTransactionPayment::::from(tip), + ); + + let raw_payload = node_runtime::SignedPayload::from_raw( + function.clone(), + extra.clone(), + ( + node_runtime::VERSION.spec_version, + node_runtime::VERSION.transaction_version, + genesis_hash, + best_hash, + (), + (), + (), + ), + ); + let signature = raw_payload.using_encoded(|e| sender.sign(e)); + + node_runtime::UncheckedExtrinsic::new_signed( + function.clone(), + sp_runtime::AccountId32::from(sender.public()).into(), + node_runtime::Signature::Sr25519(signature.clone()), + extra.clone(), + ) +} +/// Creates a new partial node. pub fn new_partial( config: &Configuration, ) -> Result< @@ -211,11 +289,16 @@ pub fn new_partial( }) } +/// Result of [`new_full_base`]. pub struct NewFullBase { + /// The task manager of the node. pub task_manager: TaskManager, + /// The client instance of the node. pub client: Arc, + /// The networking service of the node. pub network: Arc::Hash>>, - pub transaction_pool: Arc>, + /// The transaction pool of the node. + pub transaction_pool: Arc, } /// Creates a full service from the configuration. @@ -433,6 +516,7 @@ pub fn new_full(config: Configuration) -> Result { new_full_base(config, |_, _| ()).map(|NewFullBase { task_manager, .. }| task_manager) } +/// Creates a light service from the configuration. pub fn new_light_base( mut config: Configuration, ) -> Result< diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 9fac468519a0..4f620976c3ab 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -81,6 +81,8 @@ pub use pallet_balances::Call as BalancesCall; #[cfg(any(feature = "std", test))] pub use pallet_staking::StakerStatus; #[cfg(any(feature = "std", test))] +pub use pallet_sudo::Call as SudoCall; +#[cfg(any(feature = "std", test))] pub use sp_runtime::BuildStorage; /// Implementations of some helper traits passed into runtime modules as associated types. diff --git a/client/transaction-pool/src/graph/ready.rs b/client/transaction-pool/src/graph/ready.rs index 99a034689ccd..92adf2e62d62 100644 --- a/client/transaction-pool/src/graph/ready.rs +++ b/client/transaction-pool/src/graph/ready.rs @@ -31,7 +31,7 @@ use sp_runtime::{traits::Member, transaction_validity::TransactionTag as Tag}; use super::{ base_pool::Transaction, future::WaitingTransaction, - tracked_map::{self, ReadOnlyTrackedMap, TrackedMap}, + tracked_map::{self, TrackedMap}, }; /// An in-pool transaction reference. @@ -162,7 +162,7 @@ impl ReadyTransactions { /// skipped. pub fn get(&self) -> BestIterator { BestIterator { - all: self.ready.clone(), + all: self.ready.clone_map(), best: self.best.clone(), awaiting: Default::default(), invalid: Default::default(), @@ -484,7 +484,7 @@ impl ReadyTransactions { /// Iterator of ready transactions ordered by priority. pub struct BestIterator { - all: ReadOnlyTrackedMap>, + all: HashMap>, awaiting: HashMap)>, best: BTreeSet>, invalid: HashSet, @@ -519,7 +519,7 @@ impl BestIterator { /// When given transaction is not in the pool it has no effect. /// When invoked on a fully drained iterator it has no effect either. pub fn report_invalid(&mut self, tx: &Arc>) { - if let Some(to_report) = self.all.read().get(&tx.hash) { + if let Some(to_report) = self.all.get(&tx.hash) { debug!( target: "txpool", "[{:?}] Reported as invalid. Will skip sub-chains while iterating.", @@ -551,8 +551,7 @@ impl Iterator for BestIterator { continue } - let next = self.all.read().get(hash).cloned(); - let ready = match next { + let ready = match self.all.get(&hash).cloned() { Some(ready) => ready, // The transaction is not in all, maybe it was removed in the meantime? None => continue, @@ -567,7 +566,6 @@ impl Iterator for BestIterator { // then get from the pool } else { self.all - .read() .get(hash) .map(|next| (next.requires_offset + 1, next.transaction.clone())) }; diff --git a/client/transaction-pool/src/graph/tracked_map.rs b/client/transaction-pool/src/graph/tracked_map.rs index c1fdda227c6a..2f560d1c5624 100644 --- a/client/transaction-pool/src/graph/tracked_map.rs +++ b/client/transaction-pool/src/graph/tracked_map.rs @@ -57,11 +57,6 @@ impl TrackedMap { std::cmp::max(self.bytes.load(AtomicOrdering::Relaxed), 0) as usize } - /// Read-only clone of the interior. - pub fn clone(&self) -> ReadOnlyTrackedMap { - ReadOnlyTrackedMap(self.index.clone()) - } - /// Lock map for read. pub fn read(&self) -> TrackedMapReadAccess { TrackedMapReadAccess { inner_guard: self.index.read() } @@ -77,18 +72,10 @@ impl TrackedMap { } } -/// Read-only access to map. -/// -/// The only thing can be done is .read(). -pub struct ReadOnlyTrackedMap(Arc>>); - -impl ReadOnlyTrackedMap -where - K: Eq + std::hash::Hash, -{ - /// Lock map for read. - pub fn read(&self) -> TrackedMapReadAccess { - TrackedMapReadAccess { inner_guard: self.0.read() } +impl TrackedMap { + /// Clone the inner map. + pub fn clone_map(&self) -> HashMap { + self.index.read().clone() } } diff --git a/client/transaction-pool/src/lib.rs b/client/transaction-pool/src/lib.rs index 4d355df22d82..8af73c3fe5b4 100644 --- a/client/transaction-pool/src/lib.rs +++ b/client/transaction-pool/src/lib.rs @@ -44,7 +44,7 @@ use futures::{ future::{self, ready}, prelude::*, }; -pub use graph::{ChainApi, Options, Pool, Transaction}; +pub use graph::{base_pool::Limit as PoolLimit, ChainApi, Options, Pool, Transaction}; use parking_lot::Mutex; use std::{ collections::{HashMap, HashSet}, From 89cf23d5240d6d8fec3469b985e55ba30652775d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Oct 2021 09:01:04 +0000 Subject: [PATCH 053/695] Bump jsonrpsee-ws-client from 0.3.0 to 0.3.1 (#9963) Bumps [jsonrpsee-ws-client](https://github.com/paritytech/jsonrpsee) from 0.3.0 to 0.3.1. - [Release notes](https://github.com/paritytech/jsonrpsee/releases) - [Changelog](https://github.com/paritytech/jsonrpsee/blob/master/CHANGELOG.md) - [Commits](https://github.com/paritytech/jsonrpsee/compare/v0.3.0...v0.3.1) --- updated-dependencies: - dependency-name: jsonrpsee-ws-client dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 10 +++++----- bin/node/cli/Cargo.toml | 2 +- utils/frame/remote-externalities/Cargo.toml | 2 +- utils/frame/try-runtime/cli/Cargo.toml | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8194c0a1b12d..2bae84429d19 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3130,9 +3130,9 @@ dependencies = [ [[package]] name = "jsonrpsee-types" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d67724d368c59e08b557a516cf8fcc51100e7a708850f502e1044b151fe89788" +checksum = "4cc738fd55b676ada3271ef7c383a14a0867a2a88b0fa941311bf5fc0a29d498" dependencies = [ "async-trait", "beef", @@ -3148,9 +3148,9 @@ dependencies = [ [[package]] name = "jsonrpsee-ws-client" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e2834b6e7f57ce9a4412ed4d6dc95125d2c8612e68f86b9d9a07369164e4198" +checksum = "9841352dbecf4c2ed5dc71698df9f1660262ae4e0b610e968602529bdbcf7b30" dependencies = [ "async-trait", "fnv", @@ -6610,7 +6610,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c143348f141cc87aab5b950021bac6145d0e5ae754b0591de23244cee42c9308" dependencies = [ "difflib", - "itertools 0.10.0", + "itertools", "predicates-core", ] diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index 8b14f1cbeeb8..a241719fb70f 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -128,7 +128,7 @@ async-std = { version = "1.10.0", features = ["attributes"] } soketto = "0.4.2" criterion = { version = "0.3.5", features = [ "async_tokio" ] } tokio = { version = "1.10", features = ["macros", "time"] } -jsonrpsee-ws-client = { version = "0.3.0", default-features = false, features = ["tokio1"] } +jsonrpsee-ws-client = { version = "0.3.1", default-features = false, features = ["tokio1"] } wait-timeout = "0.2" remote-externalities = { path = "../../../utils/frame/remote-externalities" } diff --git a/utils/frame/remote-externalities/Cargo.toml b/utils/frame/remote-externalities/Cargo.toml index 1fbe1a7ea1d8..e1fffcfd567a 100644 --- a/utils/frame/remote-externalities/Cargo.toml +++ b/utils/frame/remote-externalities/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -jsonrpsee-ws-client = { version = "0.3.0", default-features = false, features = [ +jsonrpsee-ws-client = { version = "0.3.1", default-features = false, features = [ "tokio1", ]} jsonrpsee-proc-macros = "0.3.1" diff --git a/utils/frame/try-runtime/cli/Cargo.toml b/utils/frame/try-runtime/cli/Cargo.toml index 11b899db4ca4..b20915335b97 100644 --- a/utils/frame/try-runtime/cli/Cargo.toml +++ b/utils/frame/try-runtime/cli/Cargo.toml @@ -31,6 +31,6 @@ sp-externalities = { version = "0.10.0-dev", path = "../../../../primitives/exte sp-version = { version = "4.0.0-dev", path = "../../../../primitives/version" } remote-externalities = { version = "0.10.0-dev", path = "../../remote-externalities" } -jsonrpsee-ws-client = { version = "0.3.0", default-features = false, features = [ +jsonrpsee-ws-client = { version = "0.3.1", default-features = false, features = [ "tokio1", ]} From d0f6c1c60da22e04dd25c2eca46ebfe6f1571af0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Oct 2021 09:40:16 +0000 Subject: [PATCH 054/695] Bump regex from 1.4.3 to 1.5.4 (#9969) Bumps [regex](https://github.com/rust-lang/regex) from 1.4.3 to 1.5.4. - [Release notes](https://github.com/rust-lang/regex/releases) - [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/regex/compare/1.4.3...1.5.4) --- updated-dependencies: - dependency-name: regex dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 13 ++++++------- client/cli/Cargo.toml | 2 +- client/tracing/Cargo.toml | 2 +- primitives/core/Cargo.toml | 2 +- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2bae84429d19..1e71c25da9ac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -75,9 +75,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.7.15" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" dependencies = [ "memchr", ] @@ -7191,14 +7191,13 @@ dependencies = [ [[package]] name = "regex" -version = "1.4.3" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a" +checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" dependencies = [ "aho-corasick", "memchr", "regex-syntax", - "thread_local", ] [[package]] @@ -7213,9 +7212,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.22" +version = "0.6.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" [[package]] name = "region" diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index 963d5b3d0a90..ee72958f74d8 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] log = "0.4.11" -regex = "1.4.2" +regex = "1.5.4" tokio = { version = "1.10", features = [ "signal", "rt-multi-thread" ] } futures = "0.3.9" fdlimit = "0.2.1" diff --git a/client/tracing/Cargo.toml b/client/tracing/Cargo.toml index 2d05f80be42b..5dfa3efa779e 100644 --- a/client/tracing/Cargo.toml +++ b/client/tracing/Cargo.toml @@ -20,7 +20,7 @@ lazy_static = "1.4.0" log = { version = "0.4.8" } once_cell = "1.8.0" parking_lot = "0.11.1" -regex = "1.4.2" +regex = "1.5.4" rustc-hash = "1.1.0" serde = "1.0.126" thiserror = "1.0.21" diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index 9727d1e4f278..902aa2f655e2 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -34,7 +34,7 @@ base58 = { version = "0.1.0", optional = true } rand = { version = "0.7.3", optional = true, features = ["small_rng"] } substrate-bip39 = { version = "0.4.2", optional = true } tiny-bip39 = { version = "0.8.2", optional = true } -regex = { version = "1.4.2", optional = true } +regex = { version = "1.5.4", optional = true } num-traits = { version = "0.2.8", default-features = false } zeroize = { version = "1.4.2", default-features = false } secrecy = { version = "0.8.0", default-features = false } From 0e220090f61233db76bb2f705849e1773b62498c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Fri, 8 Oct 2021 12:05:07 +0200 Subject: [PATCH 055/695] Use correct db path for parity-db (#9971) This was overseen in: https://github.com/paritytech/substrate/pull/9500 --- client/cli/src/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cli/src/config.rs b/client/cli/src/config.rs index 59fc6bd438a1..e83cf07449e2 100644 --- a/client/cli/src/config.rs +++ b/client/cli/src/config.rs @@ -229,7 +229,7 @@ pub trait CliConfiguration: Sized { let paritydb_path = base_path.join("paritydb").join(role_dir); Ok(match database { Database::RocksDb => DatabaseSource::RocksDb { path: rocksdb_path, cache_size }, - Database::ParityDb => DatabaseSource::ParityDb { path: rocksdb_path }, + Database::ParityDb => DatabaseSource::ParityDb { path: paritydb_path }, Database::Auto => DatabaseSource::Auto { paritydb_path, rocksdb_path, cache_size }, }) } From 829133f5510e95fe7a9b235fa0f439114d84f1bf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Oct 2021 11:18:05 +0000 Subject: [PATCH 056/695] Bump assert_cmd from 2.0.1 to 2.0.2 (#9972) Bumps [assert_cmd](https://github.com/assert-rs/assert_cmd) from 2.0.1 to 2.0.2. - [Release notes](https://github.com/assert-rs/assert_cmd/releases) - [Changelog](https://github.com/assert-rs/assert_cmd/blob/master/CHANGELOG.md) - [Commits](https://github.com/assert-rs/assert_cmd/compare/v2.0.1...v2.0.2) --- updated-dependencies: - dependency-name: assert_cmd dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- bin/node/cli/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1e71c25da9ac..a3cc547dfa4e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -156,9 +156,9 @@ checksum = "9d6e24d2cce90c53b948c46271bfb053e4bdc2db9b5d3f65e20f8cf28a1b7fc3" [[package]] name = "assert_cmd" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b800c4403e8105d959595e1f88119e78bc12bc874c4336973658b648a746ba93" +checksum = "e996dc7940838b7ef1096b882e29ec30a3149a3a443cdc8dba19ed382eca1fe2" dependencies = [ "bstr", "doc-comment", diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index a241719fb70f..f08d94c0399a 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -119,7 +119,7 @@ sc-service-test = { version = "2.0.0", path = "../../../client/service/test" } sp-tracing = { version = "4.0.0-dev", path = "../../../primitives/tracing" } futures = "0.3.16" tempfile = "3.1.0" -assert_cmd = "2.0.1" +assert_cmd = "2.0.2" nix = "0.19" serde_json = "1.0" regex = "1" From b535922ae71c8cd68741ed26d042ba159725fddd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Fri, 8 Oct 2021 13:46:08 +0200 Subject: [PATCH 057/695] Disable log reloading by default (#9966) * Disable log reloading by default This disables the log reloading that was enabled by default. The problem is that the log reload implementation of `tracing` is using a lock to make the layer replaceable. This lock needs to be locked every time we need to check if a particular target is enabled (assuming the log level is high enough). This kills the performance when for example `sometarget=trace` logging is enabled. * :facepalm: * Remove unused parameter * Fix test * Fix --- bin/node/cli/benches/transaction_pool.rs | 1 - client/cli/src/config.rs | 9 ++++----- client/cli/src/params/shared_params.rs | 18 ++++++++++-------- client/rpc/src/system/tests.rs | 5 ++++- client/service/src/config.rs | 2 -- client/service/test/src/lib.rs | 1 - client/tracing/src/logging/mod.rs | 2 +- test-utils/test-runner/src/utils.rs | 1 - 8 files changed, 19 insertions(+), 20 deletions(-) diff --git a/bin/node/cli/benches/transaction_pool.rs b/bin/node/cli/benches/transaction_pool.rs index c435012e9f86..3b0ee26d7d59 100644 --- a/bin/node/cli/benches/transaction_pool.rs +++ b/bin/node/cli/benches/transaction_pool.rs @@ -99,7 +99,6 @@ fn new_node(tokio_handle: Handle) -> node_cli::service::NewFullBase { base_path: Some(base_path), informant_output_format: Default::default(), wasm_runtime_overrides: None, - disable_log_reloading: false, }; node_cli::service::new_full_base(config, |_, _| ()).expect("Creates node") diff --git a/client/cli/src/config.rs b/client/cli/src/config.rs index e83cf07449e2..f79405bd6132 100644 --- a/client/cli/src/config.rs +++ b/client/cli/src/config.rs @@ -522,7 +522,6 @@ pub trait CliConfiguration: Sized { dev_key_seed: self.dev_key_seed(is_dev)?, tracing_targets: self.tracing_targets()?, tracing_receiver: self.tracing_receiver()?, - disable_log_reloading: self.is_log_filter_reloading_disabled()?, chain_spec, max_runtime_instances, announce_block: self.announce_block()?, @@ -542,9 +541,9 @@ pub trait CliConfiguration: Sized { Ok(self.shared_params().log_filters().join(",")) } - /// Is log reloading disabled (enabled by default) - fn is_log_filter_reloading_disabled(&self) -> Result { - Ok(self.shared_params().is_log_filter_reloading_disabled()) + /// Is log reloading enabled? + fn enable_log_reloading(&self) -> Result { + Ok(self.shared_params().enable_log_reloading()) } /// Should the log color output be disabled? @@ -563,7 +562,7 @@ pub trait CliConfiguration: Sized { sp_panic_handler::set(&C::support_url(), &C::impl_version()); let mut logger = LoggerBuilder::new(self.log_filters()?); - logger.with_log_reloading(!self.is_log_filter_reloading_disabled()?); + logger.with_log_reloading(self.enable_log_reloading()?); if let Some(tracing_targets) = self.tracing_targets()? { let tracing_receiver = self.tracing_receiver()?; diff --git a/client/cli/src/params/shared_params.rs b/client/cli/src/params/shared_params.rs index 41472387d263..8f22070800fc 100644 --- a/client/cli/src/params/shared_params.rs +++ b/client/cli/src/params/shared_params.rs @@ -50,13 +50,15 @@ pub struct SharedParams { #[structopt(long)] pub disable_log_color: bool, - /// Disable feature to dynamically update and reload the log filter. + /// Enable feature to dynamically update and reload the log filter. + /// + /// Be aware that enabling this feature can lead to a performance decrease up to factor six or + /// more. Depending on the global logging level the performance decrease changes. /// - /// By default this feature is enabled, however it leads to a small performance decrease. /// The `system_addLogFilter` and `system_resetLogFilter` RPCs will have no effect with this - /// option set. - #[structopt(long = "disable-log-reloading")] - pub disable_log_reloading: bool, + /// option not being set. + #[structopt(long)] + pub enable_log_reloading: bool, /// Sets a custom profiling filter. Syntax is the same as for logging: = #[structopt(long = "tracing-targets", value_name = "TARGETS")] @@ -107,9 +109,9 @@ impl SharedParams { self.disable_log_color } - /// Is log reloading disabled - pub fn is_log_filter_reloading_disabled(&self) -> bool { - self.disable_log_reloading + /// Is log reloading enabled + pub fn enable_log_reloading(&self) -> bool { + self.enable_log_reloading } /// Receiver to process tracing messages. diff --git a/client/rpc/src/system/tests.rs b/client/rpc/src/system/tests.rs index 14997545031d..c64449ff13aa 100644 --- a/client/rpc/src/system/tests.rs +++ b/client/rpc/src/system/tests.rs @@ -308,7 +308,10 @@ fn test_add_reset_log_filter() { // Enter log generation / filter reload if std::env::var("TEST_LOG_FILTER").is_ok() { - sc_tracing::logging::LoggerBuilder::new("test_before_add=debug").init().unwrap(); + let mut builder = sc_tracing::logging::LoggerBuilder::new("test_before_add=debug"); + builder.with_log_reloading(true); + builder.init().unwrap(); + for line in std::io::stdin().lock().lines() { let line = line.expect("Failed to read bytes"); if line.contains("add_reload") { diff --git a/client/service/src/config.rs b/client/service/src/config.rs index a98a34b473ce..b4f6bf70e05b 100644 --- a/client/service/src/config.rs +++ b/client/service/src/config.rs @@ -118,8 +118,6 @@ pub struct Configuration { pub dev_key_seed: Option, /// Tracing targets pub tracing_targets: Option, - /// Is log filter reloading disabled - pub disable_log_reloading: bool, /// Tracing receiver pub tracing_receiver: sc_tracing::TracingReceiver, /// The size of the instances cache. diff --git a/client/service/test/src/lib.rs b/client/service/test/src/lib.rs index 8000c536cdf9..d85ad8d36111 100644 --- a/client/service/test/src/lib.rs +++ b/client/service/test/src/lib.rs @@ -274,7 +274,6 @@ fn node_config< announce_block: true, base_path: Some(BasePath::new(root)), informant_output_format: Default::default(), - disable_log_reloading: false, } } diff --git a/client/tracing/src/logging/mod.rs b/client/tracing/src/logging/mod.rs index dd0f7a5d8ae4..c6a4f070176e 100644 --- a/client/tracing/src/logging/mod.rs +++ b/client/tracing/src/logging/mod.rs @@ -197,7 +197,7 @@ impl LoggerBuilder { Self { directives: directives.into(), profiling: None, - log_reloading: true, + log_reloading: false, force_colors: None, } } diff --git a/test-utils/test-runner/src/utils.rs b/test-utils/test-runner/src/utils.rs index 8e8c84e6b4f8..3ab77af96c16 100644 --- a/test-utils/test-runner/src/utils.rs +++ b/test-utils/test-runner/src/utils.rs @@ -108,7 +108,6 @@ pub fn default_config(tokio_handle: Handle, mut chain_spec: Box) base_path: Some(base_path), wasm_runtime_overrides: None, informant_output_format, - disable_log_reloading: false, keystore_remote: None, keep_blocks: KeepBlocks::All, state_pruning: Default::default(), From 66fd76181742a1fa27b4ab5c41eb15d9765e6774 Mon Sep 17 00:00:00 2001 From: Andronik Ordian Date: Fri, 8 Oct 2021 17:31:18 +0200 Subject: [PATCH 058/695] NetworkService: change `remove_from_peers_set` to accept `PeerId`s (#9964) * NetworkService: expose split_multiaddr_and_peer_id * Revert "NetworkService: expose split_multiaddr_and_peer_id" This reverts commit 47b9a0d57c3617e64d01c449afca8896bd4bb6b6. * change remove_from_peer_set to accets PeerIds * fixes * try fixing it * try fixing it again * FMT * revert me * Revert "revert me" This reverts commit 1ea34f473f1aedc8b3e6e888d1ad2e1b45eaa1e0. --- client/network-gossip/src/lib.rs | 11 +--------- client/network/src/service.rs | 34 ++++-------------------------- client/network/src/transactions.rs | 9 ++------ 3 files changed, 7 insertions(+), 47 deletions(-) diff --git a/client/network-gossip/src/lib.rs b/client/network-gossip/src/lib.rs index 55c2fc820637..5dc40471f138 100644 --- a/client/network-gossip/src/lib.rs +++ b/client/network-gossip/src/lib.rs @@ -123,16 +123,7 @@ impl Network for Arc> { } fn remove_set_reserved(&self, who: PeerId, protocol: Cow<'static, str>) { - let addr = - iter::once(multiaddr::Protocol::P2p(who.into())).collect::(); - let result = NetworkService::remove_peers_from_reserved_set( - self, - protocol, - iter::once(addr).collect(), - ); - if let Err(err) = result { - log::error!(target: "gossip", "remove_set_reserved failed: {}", err); - } + NetworkService::remove_peers_from_reserved_set(self, protocol, iter::once(who).collect()); } fn disconnect_peer(&self, who: PeerId, protocol: Cow<'static, str>) { diff --git a/client/network/src/service.rs b/client/network/src/service.rs index 72b382c99054..be19b44f3a59 100644 --- a/client/network/src/service.rs +++ b/client/network/src/service.rs @@ -1164,25 +1164,12 @@ impl NetworkService { } /// Remove peers from a peer set. - /// - /// Each `Multiaddr` must end with a `/p2p/` component containing the `PeerId`. - /// - /// Returns an `Err` if one of the given addresses is invalid or contains an - /// invalid peer ID (which includes the local peer ID). - // NOTE: technically, this function only needs `Vec`, but we use `Multiaddr` here for - // convenience. - pub fn remove_peers_from_reserved_set( - &self, - protocol: Cow<'static, str>, - peers: HashSet, - ) -> Result<(), String> { - let peers = self.split_multiaddr_and_peer_id(peers)?; - for (peer_id, _) in peers.into_iter() { + pub fn remove_peers_from_reserved_set(&self, protocol: Cow<'static, str>, peers: Vec) { + for peer_id in peers.into_iter() { let _ = self .to_worker .unbounded_send(ServiceToWorkerMsg::RemoveSetReserved(protocol.clone(), peer_id)); } - Ok(()) } /// Configure an explicit fork sync request. @@ -1233,25 +1220,12 @@ impl NetworkService { /// Remove peers from a peer set. /// /// If we currently have an open substream with this peer, it will soon be closed. - /// - /// Each `Multiaddr` must end with a `/p2p/` component containing the `PeerId`. - /// - /// Returns an `Err` if one of the given addresses is invalid or contains an - /// invalid peer ID (which includes the local peer ID). - // NOTE: technically, this function only needs `Vec`, but we use `Multiaddr` here for - // convenience. - pub fn remove_from_peers_set( - &self, - protocol: Cow<'static, str>, - peers: HashSet, - ) -> Result<(), String> { - let peers = self.split_multiaddr_and_peer_id(peers)?; - for (peer_id, _) in peers.into_iter() { + pub fn remove_from_peers_set(&self, protocol: Cow<'static, str>, peers: Vec) { + for peer_id in peers.into_iter() { let _ = self .to_worker .unbounded_send(ServiceToWorkerMsg::RemoveFromPeersSet(protocol.clone(), peer_id)); } - Ok(()) } /// Returns the number of peers we're connected to. diff --git a/client/network/src/transactions.rs b/client/network/src/transactions.rs index 9565466ea1c0..99350f603a37 100644 --- a/client/network/src/transactions.rs +++ b/client/network/src/transactions.rs @@ -317,15 +317,10 @@ impl TransactionsHandler { } }, Event::SyncDisconnected { remote } => { - let addr = iter::once(multiaddr::Protocol::P2p(remote.into())) - .collect::(); - let result = self.service.remove_peers_from_reserved_set( + self.service.remove_peers_from_reserved_set( self.protocol_name.clone(), - iter::once(addr).collect(), + iter::once(remote).collect(), ); - if let Err(err) = result { - log::error!(target: "sync", "Removing reserved peer failed: {}", err); - } }, Event::NotificationStreamOpened { remote, protocol, role, .. } From efd3f7f301b526c59a616a59fe1139fe7bfb210e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Fri, 8 Oct 2021 23:54:46 +0200 Subject: [PATCH 059/695] Remove unused deps from `sp-tracing` (#9979) --- Cargo.lock | 48 ----------------------------------- primitives/tracing/Cargo.toml | 12 --------- 2 files changed, 60 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a3cc547dfa4e..320501b0585e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1771,15 +1771,6 @@ version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68b91989ae21441195d7d9b9993a2f9295c7e1a8c96255d8b729accddc124797" -[[package]] -name = "erased-serde" -version = "0.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0465971a8cc1fa2455c8465aaa377131e1f1cf4983280f474a13e68793aa770c" -dependencies = [ - "serde", -] - [[package]] name = "errno" version = "0.2.7" @@ -6284,16 +6275,6 @@ dependencies = [ "rustc_version 0.2.3", ] -[[package]] -name = "parking_lot" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e" -dependencies = [ - "lock_api 0.3.4", - "parking_lot_core 0.7.2", -] - [[package]] name = "parking_lot" version = "0.11.1" @@ -6320,20 +6301,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "parking_lot_core" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3" -dependencies = [ - "cfg-if 0.1.10", - "cloudabi", - "libc", - "redox_syscall 0.1.57", - "smallvec 1.7.0", - "winapi 0.3.9", -] - [[package]] name = "parking_lot_core" version = "0.8.3" @@ -8931,15 +8898,6 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" -[[package]] -name = "slog" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8347046d4ebd943127157b94d63abb990fcf729dc4e9978927fdf4ac3c998d06" -dependencies = [ - "erased-serde", -] - [[package]] name = "smallvec" version = "0.6.14" @@ -9734,13 +9692,7 @@ dependencies = [ name = "sp-tracing" version = "4.0.0-dev" dependencies = [ - "erased-serde", - "log 0.4.14", "parity-scale-codec", - "parking_lot 0.10.2", - "serde", - "serde_json", - "slog", "sp-std", "tracing", "tracing-core", diff --git a/primitives/tracing/Cargo.toml b/primitives/tracing/Cargo.toml index ebcddb1477d3..806205dae8dd 100644 --- a/primitives/tracing/Cargo.toml +++ b/primitives/tracing/Cargo.toml @@ -24,15 +24,9 @@ codec = { version = "2.0.0", package = "parity-scale-codec", default-features = ] } tracing = { version = "0.1.29", default-features = false } tracing-core = { version = "0.1.17", default-features = false } -log = { version = "0.4.8", optional = true } tracing-subscriber = { version = "0.2.19", optional = true, features = [ "tracing-log", ] } -parking_lot = { version = "0.10.0", optional = true } -erased-serde = { version = "0.3.9", optional = true } -serde = { version = "1.0.126", optional = true } -serde_json = { version = "1.0.68", optional = true } -slog = { version = "2.5.2", features = ["nested-values"], optional = true } [features] default = ["std"] @@ -43,11 +37,5 @@ std = [ "tracing-core/std", "codec/std", "sp-std/std", - "log", "tracing-subscriber", - "parking_lot", - "erased-serde", - "serde", - "serde_json", - "slog", ] From 0e0cdd84227bde26aa2825cc315e3c1317775a8d Mon Sep 17 00:00:00 2001 From: Dan Shields <35669742+NukeManDan@users.noreply.github.com> Date: Sat, 9 Oct 2021 00:16:27 -0600 Subject: [PATCH 060/695] add note on `--dev` behavior (#9953) * add note on `--dev` behavior * Update client/cli/src/params/shared_params.rs * Update client/cli/src/params/shared_params.rs * clippy fmt * Update client/cli/src/params/shared_params.rs Co-authored-by: Alexander Popiak * Update client/cli/src/params/shared_params.rs Co-authored-by: adoerr <0xad@gmx.net> Co-authored-by: Alexander Popiak --- client/cli/src/params/shared_params.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/cli/src/params/shared_params.rs b/client/cli/src/params/shared_params.rs index 8f22070800fc..58aabb3148dd 100644 --- a/client/cli/src/params/shared_params.rs +++ b/client/cli/src/params/shared_params.rs @@ -32,6 +32,9 @@ pub struct SharedParams { pub chain: Option, /// Specify the development chain. + /// + /// This flag sets `--chain=dev`, `--force-authoring`, `--rpc-cors=all`, + /// `--alice`, and `--tmp` flags, unless explicitly overridden. #[structopt(long, conflicts_with_all = &["chain"])] pub dev: bool, From bdf1788e9f37a51da97f7a1df2359a54022e85f0 Mon Sep 17 00:00:00 2001 From: zjb0807 Date: Sat, 9 Oct 2021 21:42:15 +0800 Subject: [PATCH 061/695] add TypeInfo for DispatchTime (#9987) --- frame/support/src/traits/schedule.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frame/support/src/traits/schedule.rs b/frame/support/src/traits/schedule.rs index a4a4f9c03ab1..19f50a93c068 100644 --- a/frame/support/src/traits/schedule.rs +++ b/frame/support/src/traits/schedule.rs @@ -18,6 +18,7 @@ //! Traits and associated utilities for scheduling dispatchables in FRAME. use codec::{Codec, Decode, Encode, EncodeLike}; +use scale_info::TypeInfo; use sp_runtime::{DispatchError, RuntimeDebug}; use sp_std::{fmt::Debug, prelude::*}; @@ -31,7 +32,7 @@ pub type Period = (BlockNumber, u32); pub type Priority = u8; /// The dispatch time of a scheduled task. -#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug)] +#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] pub enum DispatchTime { /// At specified block. At(BlockNumber), From 13c30b92fdfe3d04c0e1ef517458939767780967 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 9 Oct 2021 14:23:57 +0000 Subject: [PATCH 062/695] Bump hex-literal from 0.3.1 to 0.3.3 (#9974) Bumps [hex-literal](https://github.com/RustCrypto/utils) from 0.3.1 to 0.3.3. - [Release notes](https://github.com/RustCrypto/utils/releases) - [Commits](https://github.com/RustCrypto/utils/compare/hex-literal-v0.3.1...hex-literal-v0.3.3) --- updated-dependencies: - dependency-name: hex-literal dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- bin/node-template/runtime/Cargo.toml | 2 +- bin/node/cli/Cargo.toml | 2 +- bin/node/runtime/Cargo.toml | 2 +- client/executor/Cargo.toml | 2 +- client/service/test/Cargo.toml | 2 +- frame/benchmarking/Cargo.toml | 2 +- frame/executive/Cargo.toml | 2 +- frame/transaction-storage/Cargo.toml | 2 +- primitives/core/Cargo.toml | 2 +- primitives/state-machine/Cargo.toml | 2 +- primitives/trie/Cargo.toml | 2 +- 12 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 320501b0585e..a1610fa57bc2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2586,9 +2586,9 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hex-literal" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5af1f635ef1bc545d78392b136bfe1c9809e029023c84a3638a864a10b8819c8" +checksum = "21e4590e13640f19f249fe3e4eca5113bc4289f2497710378190e7f4bd96f45b" [[package]] name = "hex_fmt" diff --git a/bin/node-template/runtime/Cargo.toml b/bin/node-template/runtime/Cargo.toml index 081e458b18e0..3179a2cc4ff5 100644 --- a/bin/node-template/runtime/Cargo.toml +++ b/bin/node-template/runtime/Cargo.toml @@ -45,7 +45,7 @@ pallet-transaction-payment-rpc-runtime-api = { version = "4.0.0-dev", default-fe # Used for runtime benchmarking frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../../../frame/benchmarking", optional = true } frame-system-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../../../frame/system/benchmarking", optional = true } -hex-literal = { version = "0.3.1", optional = true } +hex-literal = { version = "0.3.3", optional = true } pallet-template = { version = "3.0.0", default-features = false, path = "../pallets/template" } diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index f08d94c0399a..a92c7a185b7a 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -37,7 +37,7 @@ crate-type = ["cdylib", "rlib"] codec = { package = "parity-scale-codec", version = "2.0.0" } serde = { version = "1.0.126", features = ["derive"] } futures = "0.3.16" -hex-literal = "0.3.1" +hex-literal = "0.3.3" log = "0.4.8" rand = "0.7.2" structopt = { version = "0.3.8", optional = true } diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index d434be8f3c60..b4e84aafec13 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -20,7 +20,7 @@ codec = { package = "parity-scale-codec", version = "2.2.0", default-features = ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } static_assertions = "1.1.0" -hex-literal = { version = "0.3.1", optional = true } +hex-literal = { version = "0.3.3", optional = true } log = { version = "0.4.14", default-features = false } # primitives diff --git a/client/executor/Cargo.toml b/client/executor/Cargo.toml index b7eb31a37593..eeea57d83980 100644 --- a/client/executor/Cargo.toml +++ b/client/executor/Cargo.toml @@ -36,7 +36,7 @@ libsecp256k1 = "0.6" [dev-dependencies] wat = "1.0" -hex-literal = "0.3.1" +hex-literal = "0.3.3" sc-runtime-test = { version = "2.0.0", path = "runtime-test" } substrate-test-runtime = { version = "2.0.0", path = "../../test-utils/runtime" } sp-state-machine = { version = "0.10.0-dev", path = "../../primitives/state-machine" } diff --git a/client/service/test/Cargo.toml b/client/service/test/Cargo.toml index 9e66e9ca381d..d267d2535f8c 100644 --- a/client/service/test/Cargo.toml +++ b/client/service/test/Cargo.toml @@ -13,7 +13,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] hex = "0.4" -hex-literal = "0.3.1" +hex-literal = "0.3.3" tempfile = "3.1.0" tokio = { version = "1.10.0", features = ["time"] } log = "0.4.8" diff --git a/frame/benchmarking/Cargo.toml b/frame/benchmarking/Cargo.toml index ea690d966c97..6a605707caa8 100644 --- a/frame/benchmarking/Cargo.toml +++ b/frame/benchmarking/Cargo.toml @@ -28,7 +28,7 @@ frame-system = { version = "4.0.0-dev", default-features = false, path = "../sys log = { version = "0.4.14", default-features = false } [dev-dependencies] -hex-literal = "0.3.1" +hex-literal = "0.3.3" [features] default = ["std"] diff --git a/frame/executive/Cargo.toml b/frame/executive/Cargo.toml index 1abbf50e6a4c..15c8a1bd14f1 100644 --- a/frame/executive/Cargo.toml +++ b/frame/executive/Cargo.toml @@ -26,7 +26,7 @@ sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primiti sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" } [dev-dependencies] -hex-literal = "0.3.1" +hex-literal = "0.3.3" sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } diff --git a/frame/transaction-storage/Cargo.toml b/frame/transaction-storage/Cargo.toml index a4ebd5cfbc87..9daf706b0ce3 100644 --- a/frame/transaction-storage/Cargo.toml +++ b/frame/transaction-storage/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.126", optional = true } -hex-literal = { version = "0.3.1", optional = true } +hex-literal = { version = "0.3.3", optional = true } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index 902aa2f655e2..31223ff1ccf7 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -71,7 +71,7 @@ sp-runtime-interface = { version = "4.0.0-dev", default-features = false, path = [dev-dependencies] sp-serializer = { version = "3.0.0", path = "../serializer" } -hex-literal = "0.3.1" +hex-literal = "0.3.3" rand = "0.7.2" criterion = "0.3.3" serde_json = "1.0" diff --git a/primitives/state-machine/Cargo.toml b/primitives/state-machine/Cargo.toml index d62b598fdc3a..bafe34bbd5af 100644 --- a/primitives/state-machine/Cargo.toml +++ b/primitives/state-machine/Cargo.toml @@ -32,7 +32,7 @@ sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" } tracing = { version = "0.1.29", optional = true } [dev-dependencies] -hex-literal = "0.3.1" +hex-literal = "0.3.3" sp-runtime = { version = "4.0.0-dev", path = "../runtime" } pretty_assertions = "1.0.0" rand = "0.7.2" diff --git a/primitives/trie/Cargo.toml b/primitives/trie/Cargo.toml index 5a2de4f16f9a..297040d09eec 100644 --- a/primitives/trie/Cargo.toml +++ b/primitives/trie/Cargo.toml @@ -31,7 +31,7 @@ sp-core = { version = "4.0.0-dev", default-features = false, path = "../core" } trie-bench = "0.28.0" trie-standardmap = "0.15.2" criterion = "0.3.3" -hex-literal = "0.3.1" +hex-literal = "0.3.3" sp-runtime = { version = "4.0.0-dev", path = "../runtime" } [features] From ecc14d87afde4bf59bbc7c57945d7f8293a4bfee Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Oct 2021 04:25:52 +0000 Subject: [PATCH 063/695] Bump quote from 1.0.9 to 1.0.10 (#9980) Bumps [quote](https://github.com/dtolnay/quote) from 1.0.9 to 1.0.10. - [Release notes](https://github.com/dtolnay/quote/releases) - [Commits](https://github.com/dtolnay/quote/compare/1.0.9...1.0.10) --- updated-dependencies: - dependency-name: quote dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- client/chain-spec/derive/Cargo.toml | 2 +- client/tracing/proc-macro/Cargo.toml | 2 +- frame/staking/reward-curve/Cargo.toml | 2 +- frame/support/procedural/Cargo.toml | 2 +- frame/support/procedural/tools/Cargo.toml | 2 +- frame/support/procedural/tools/derive/Cargo.toml | 2 +- primitives/api/proc-macro/Cargo.toml | 2 +- primitives/debug-derive/Cargo.toml | 2 +- primitives/runtime-interface/proc-macro/Cargo.toml | 2 +- primitives/version/proc-macro/Cargo.toml | 2 +- test-utils/derive/Cargo.toml | 2 +- 12 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a1610fa57bc2..93635b79c86c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6833,9 +6833,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" dependencies = [ "proc-macro2", ] diff --git a/client/chain-spec/derive/Cargo.toml b/client/chain-spec/derive/Cargo.toml index b210fa1320e0..76525ebf462a 100644 --- a/client/chain-spec/derive/Cargo.toml +++ b/client/chain-spec/derive/Cargo.toml @@ -17,7 +17,7 @@ proc-macro = true [dependencies] proc-macro-crate = "1.0.0" proc-macro2 = "1.0.29" -quote = "1.0.3" +quote = "1.0.10" syn = "1.0.58" [dev-dependencies] diff --git a/client/tracing/proc-macro/Cargo.toml b/client/tracing/proc-macro/Cargo.toml index 002370b515f2..e13efdfcc587 100644 --- a/client/tracing/proc-macro/Cargo.toml +++ b/client/tracing/proc-macro/Cargo.toml @@ -17,5 +17,5 @@ proc-macro = true [dependencies] proc-macro-crate = "1.0.0" proc-macro2 = "1.0.29" -quote = { version = "1.0.3", features = ["proc-macro"] } +quote = { version = "1.0.10", features = ["proc-macro"] } syn = { version = "1.0.58", features = ["proc-macro", "full", "extra-traits", "parsing"] } diff --git a/frame/staking/reward-curve/Cargo.toml b/frame/staking/reward-curve/Cargo.toml index 4cbc2473cb52..d7f00d4f70f9 100644 --- a/frame/staking/reward-curve/Cargo.toml +++ b/frame/staking/reward-curve/Cargo.toml @@ -16,7 +16,7 @@ proc-macro = true [dependencies] syn = { version = "1.0.58", features = ["full", "visit"] } -quote = "1.0.3" +quote = "1.0.10" proc-macro2 = "1.0.29" proc-macro-crate = "1.0.0" diff --git a/frame/support/procedural/Cargo.toml b/frame/support/procedural/Cargo.toml index e1ff6dcf39b7..ce2e9907add5 100644 --- a/frame/support/procedural/Cargo.toml +++ b/frame/support/procedural/Cargo.toml @@ -17,7 +17,7 @@ proc-macro = true [dependencies] frame-support-procedural-tools = { version = "4.0.0-dev", path = "./tools" } proc-macro2 = "1.0.29" -quote = "1.0.3" +quote = "1.0.10" Inflector = "0.11.4" syn = { version = "1.0.58", features = ["full"] } diff --git a/frame/support/procedural/tools/Cargo.toml b/frame/support/procedural/tools/Cargo.toml index ee59f53287ef..106d552b177a 100644 --- a/frame/support/procedural/tools/Cargo.toml +++ b/frame/support/procedural/tools/Cargo.toml @@ -14,6 +14,6 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] frame-support-procedural-tools-derive = { version = "3.0.0", path = "./derive" } proc-macro2 = "1.0.29" -quote = "1.0.3" +quote = "1.0.10" syn = { version = "1.0.58", features = ["full", "visit", "extra-traits"] } proc-macro-crate = "1.0.0" diff --git a/frame/support/procedural/tools/derive/Cargo.toml b/frame/support/procedural/tools/derive/Cargo.toml index 12ec6a69f396..4e15519c6ed5 100644 --- a/frame/support/procedural/tools/derive/Cargo.toml +++ b/frame/support/procedural/tools/derive/Cargo.toml @@ -16,5 +16,5 @@ proc-macro = true [dependencies] proc-macro2 = "1.0.29" -quote = { version = "1.0.3", features = ["proc-macro"] } +quote = { version = "1.0.10", features = ["proc-macro"] } syn = { version = "1.0.58", features = ["proc-macro" ,"full", "extra-traits", "parsing"] } diff --git a/primitives/api/proc-macro/Cargo.toml b/primitives/api/proc-macro/Cargo.toml index d5909967ac5a..1066b38b55a2 100644 --- a/primitives/api/proc-macro/Cargo.toml +++ b/primitives/api/proc-macro/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] proc-macro = true [dependencies] -quote = "1.0.3" +quote = "1.0.10" syn = { version = "1.0.58", features = ["full", "fold", "extra-traits", "visit"] } proc-macro2 = "1.0.29" blake2-rfc = { version = "0.2.18", default-features = false } diff --git a/primitives/debug-derive/Cargo.toml b/primitives/debug-derive/Cargo.toml index 0d3ba805100c..0f180dade025 100644 --- a/primitives/debug-derive/Cargo.toml +++ b/primitives/debug-derive/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] proc-macro = true [dependencies] -quote = "1.0.3" +quote = "1.0.10" syn = "1.0.58" proc-macro2 = "1.0" diff --git a/primitives/runtime-interface/proc-macro/Cargo.toml b/primitives/runtime-interface/proc-macro/Cargo.toml index 1eb3bdd9039d..0cd709083e36 100644 --- a/primitives/runtime-interface/proc-macro/Cargo.toml +++ b/primitives/runtime-interface/proc-macro/Cargo.toml @@ -17,7 +17,7 @@ proc-macro = true [dependencies] syn = { version = "1.0.58", features = ["full", "visit", "fold", "extra-traits"] } -quote = "1.0.3" +quote = "1.0.10" proc-macro2 = "1.0.29" Inflector = "0.11.4" proc-macro-crate = "1.0.0" diff --git a/primitives/version/proc-macro/Cargo.toml b/primitives/version/proc-macro/Cargo.toml index c3c801431434..33f780169fae 100644 --- a/primitives/version/proc-macro/Cargo.toml +++ b/primitives/version/proc-macro/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] proc-macro = true [dependencies] -quote = "1.0.3" +quote = "1.0.10" syn = { version = "1.0.58", features = ["full", "fold", "extra-traits", "visit"] } proc-macro2 = "1.0.29" codec = { package = "parity-scale-codec", version = "2.0.0", features = [ "derive" ] } diff --git a/test-utils/derive/Cargo.toml b/test-utils/derive/Cargo.toml index 545e8cf33261..49eaca4cd982 100644 --- a/test-utils/derive/Cargo.toml +++ b/test-utils/derive/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/paritytech/substrate/" description = "Substrate test utilities macros" [dependencies] -quote = "1.0.6" +quote = "1.0.10" syn = { version = "1.0.58", features = ["full"] } proc-macro-crate = "1.0.0" proc-macro2 = "1.0.29" From 582db90ce647d888af62c7c96772f3305a36ee74 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Oct 2021 12:23:02 +0000 Subject: [PATCH 064/695] Bump syn from 1.0.76 to 1.0.80 (#9995) Bumps [syn](https://github.com/dtolnay/syn) from 1.0.76 to 1.0.80. - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/1.0.76...1.0.80) --- updated-dependencies: - dependency-name: syn dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- client/chain-spec/derive/Cargo.toml | 2 +- client/tracing/proc-macro/Cargo.toml | 2 +- frame/staking/reward-curve/Cargo.toml | 2 +- frame/support/procedural/Cargo.toml | 2 +- frame/support/procedural/tools/Cargo.toml | 2 +- frame/support/procedural/tools/derive/Cargo.toml | 2 +- primitives/api/proc-macro/Cargo.toml | 2 +- primitives/debug-derive/Cargo.toml | 2 +- primitives/npos-elections/solution-type/Cargo.toml | 2 +- primitives/runtime-interface/proc-macro/Cargo.toml | 2 +- primitives/version/proc-macro/Cargo.toml | 2 +- test-utils/derive/Cargo.toml | 2 +- 13 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 93635b79c86c..7af65c8bcf79 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10143,9 +10143,9 @@ checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2" [[package]] name = "syn" -version = "1.0.76" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6f107db402c2c2055242dbf4d2af0e69197202e9faacbef9571bbe47f5a1b84" +checksum = "d010a1623fbd906d51d650a9916aaefc05ffa0e4053ff7fe601167f3e715d194" dependencies = [ "proc-macro2", "quote", diff --git a/client/chain-spec/derive/Cargo.toml b/client/chain-spec/derive/Cargo.toml index 76525ebf462a..89a51d95079a 100644 --- a/client/chain-spec/derive/Cargo.toml +++ b/client/chain-spec/derive/Cargo.toml @@ -18,6 +18,6 @@ proc-macro = true proc-macro-crate = "1.0.0" proc-macro2 = "1.0.29" quote = "1.0.10" -syn = "1.0.58" +syn = "1.0.80" [dev-dependencies] diff --git a/client/tracing/proc-macro/Cargo.toml b/client/tracing/proc-macro/Cargo.toml index e13efdfcc587..42a0c739cd52 100644 --- a/client/tracing/proc-macro/Cargo.toml +++ b/client/tracing/proc-macro/Cargo.toml @@ -18,4 +18,4 @@ proc-macro = true proc-macro-crate = "1.0.0" proc-macro2 = "1.0.29" quote = { version = "1.0.10", features = ["proc-macro"] } -syn = { version = "1.0.58", features = ["proc-macro", "full", "extra-traits", "parsing"] } +syn = { version = "1.0.80", features = ["proc-macro", "full", "extra-traits", "parsing"] } diff --git a/frame/staking/reward-curve/Cargo.toml b/frame/staking/reward-curve/Cargo.toml index d7f00d4f70f9..aaa45e623109 100644 --- a/frame/staking/reward-curve/Cargo.toml +++ b/frame/staking/reward-curve/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] proc-macro = true [dependencies] -syn = { version = "1.0.58", features = ["full", "visit"] } +syn = { version = "1.0.80", features = ["full", "visit"] } quote = "1.0.10" proc-macro2 = "1.0.29" proc-macro-crate = "1.0.0" diff --git a/frame/support/procedural/Cargo.toml b/frame/support/procedural/Cargo.toml index ce2e9907add5..6113c6613be0 100644 --- a/frame/support/procedural/Cargo.toml +++ b/frame/support/procedural/Cargo.toml @@ -19,7 +19,7 @@ frame-support-procedural-tools = { version = "4.0.0-dev", path = "./tools" } proc-macro2 = "1.0.29" quote = "1.0.10" Inflector = "0.11.4" -syn = { version = "1.0.58", features = ["full"] } +syn = { version = "1.0.80", features = ["full"] } [features] default = ["std"] diff --git a/frame/support/procedural/tools/Cargo.toml b/frame/support/procedural/tools/Cargo.toml index 106d552b177a..d6894b78133e 100644 --- a/frame/support/procedural/tools/Cargo.toml +++ b/frame/support/procedural/tools/Cargo.toml @@ -15,5 +15,5 @@ targets = ["x86_64-unknown-linux-gnu"] frame-support-procedural-tools-derive = { version = "3.0.0", path = "./derive" } proc-macro2 = "1.0.29" quote = "1.0.10" -syn = { version = "1.0.58", features = ["full", "visit", "extra-traits"] } +syn = { version = "1.0.80", features = ["full", "visit", "extra-traits"] } proc-macro-crate = "1.0.0" diff --git a/frame/support/procedural/tools/derive/Cargo.toml b/frame/support/procedural/tools/derive/Cargo.toml index 4e15519c6ed5..14c56b1b819a 100644 --- a/frame/support/procedural/tools/derive/Cargo.toml +++ b/frame/support/procedural/tools/derive/Cargo.toml @@ -17,4 +17,4 @@ proc-macro = true [dependencies] proc-macro2 = "1.0.29" quote = { version = "1.0.10", features = ["proc-macro"] } -syn = { version = "1.0.58", features = ["proc-macro" ,"full", "extra-traits", "parsing"] } +syn = { version = "1.0.80", features = ["proc-macro" ,"full", "extra-traits", "parsing"] } diff --git a/primitives/api/proc-macro/Cargo.toml b/primitives/api/proc-macro/Cargo.toml index 1066b38b55a2..dc0f2bd98d46 100644 --- a/primitives/api/proc-macro/Cargo.toml +++ b/primitives/api/proc-macro/Cargo.toml @@ -17,7 +17,7 @@ proc-macro = true [dependencies] quote = "1.0.10" -syn = { version = "1.0.58", features = ["full", "fold", "extra-traits", "visit"] } +syn = { version = "1.0.80", features = ["full", "fold", "extra-traits", "visit"] } proc-macro2 = "1.0.29" blake2-rfc = { version = "0.2.18", default-features = false } proc-macro-crate = "1.0.0" diff --git a/primitives/debug-derive/Cargo.toml b/primitives/debug-derive/Cargo.toml index 0f180dade025..2e5ef93e41f5 100644 --- a/primitives/debug-derive/Cargo.toml +++ b/primitives/debug-derive/Cargo.toml @@ -18,7 +18,7 @@ proc-macro = true [dependencies] quote = "1.0.10" -syn = "1.0.58" +syn = "1.0.80" proc-macro2 = "1.0" [features] diff --git a/primitives/npos-elections/solution-type/Cargo.toml b/primitives/npos-elections/solution-type/Cargo.toml index cbe6750266f0..5cbf0b648181 100644 --- a/primitives/npos-elections/solution-type/Cargo.toml +++ b/primitives/npos-elections/solution-type/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] proc-macro = true [dependencies] -syn = { version = "1.0.58", features = ["full", "visit"] } +syn = { version = "1.0.80", features = ["full", "visit"] } quote = "1.0" proc-macro2 = "1.0.29" proc-macro-crate = "1.0.0" diff --git a/primitives/runtime-interface/proc-macro/Cargo.toml b/primitives/runtime-interface/proc-macro/Cargo.toml index 0cd709083e36..1f77caf7e416 100644 --- a/primitives/runtime-interface/proc-macro/Cargo.toml +++ b/primitives/runtime-interface/proc-macro/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] proc-macro = true [dependencies] -syn = { version = "1.0.58", features = ["full", "visit", "fold", "extra-traits"] } +syn = { version = "1.0.80", features = ["full", "visit", "fold", "extra-traits"] } quote = "1.0.10" proc-macro2 = "1.0.29" Inflector = "0.11.4" diff --git a/primitives/version/proc-macro/Cargo.toml b/primitives/version/proc-macro/Cargo.toml index 33f780169fae..4984961fb9f7 100644 --- a/primitives/version/proc-macro/Cargo.toml +++ b/primitives/version/proc-macro/Cargo.toml @@ -17,7 +17,7 @@ proc-macro = true [dependencies] quote = "1.0.10" -syn = { version = "1.0.58", features = ["full", "fold", "extra-traits", "visit"] } +syn = { version = "1.0.80", features = ["full", "fold", "extra-traits", "visit"] } proc-macro2 = "1.0.29" codec = { package = "parity-scale-codec", version = "2.0.0", features = [ "derive" ] } diff --git a/test-utils/derive/Cargo.toml b/test-utils/derive/Cargo.toml index 49eaca4cd982..68bcbdaa4700 100644 --- a/test-utils/derive/Cargo.toml +++ b/test-utils/derive/Cargo.toml @@ -10,7 +10,7 @@ description = "Substrate test utilities macros" [dependencies] quote = "1.0.10" -syn = { version = "1.0.58", features = ["full"] } +syn = { version = "1.0.80", features = ["full"] } proc-macro-crate = "1.0.0" proc-macro2 = "1.0.29" From 85d881bfc28a6926c2f7c1d0fa3a7b84d2cac06d Mon Sep 17 00:00:00 2001 From: Alexander Samusev <41779041+alvicsam@users.noreply.github.com> Date: Mon, 11 Oct 2021 15:46:31 +0200 Subject: [PATCH 065/695] Add quick simnet tests to .gitlab-ci.yml (#9959) * remove spaces * add simnet quick test * debug simnet test * add jobs for quick simnet tests * fix typo * test simnet-quick * remove debug * fix ci * change tag for simnet tests * Add new line to readme --- .gitlab-ci.yml | 69 +++++++++++++++++++++++++++++++++++++++++++++++--- README.md | 1 + 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0d150d96deed..ae6a81611f2d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -45,6 +45,7 @@ variables: &default-vars VAULT_SERVER_URL: "https://vault.parity-mgmt-vault.parity.io" VAULT_AUTH_PATH: "gitlab-parity-io-jwt" VAULT_AUTH_ROLE: "cicd_gitlab_parity_${CI_PROJECT_NAME}" + SIMNET_FEATURES_PATH: "simnet_tests/tests" default: cache: {} @@ -57,6 +58,14 @@ default: paths: - artifacts/ +.collect-artifacts-short: &collect-artifacts-short + artifacts: + name: "${CI_JOB_NAME}_${CI_COMMIT_REF_NAME}" + when: on_success + expire_in: 3 hours + paths: + - artifacts/ + .kubernetes-env: &kubernetes-env retry: max: 2 @@ -188,13 +197,13 @@ default: file: false AWX_TOKEN: vault: cicd/gitlab/$CI_PROJECT_PATH/AWX_TOKEN@kv - file: false + file: false CRATES_TOKEN: vault: cicd/gitlab/$CI_PROJECT_PATH/CRATES_TOKEN@kv file: false DOCKER_CHAOS_TOKEN: vault: cicd/gitlab/$CI_PROJECT_PATH/DOCKER_CHAOS_TOKEN@kv - file: false + file: false DOCKER_CHAOS_USER: vault: cicd/gitlab/$CI_PROJECT_PATH/DOCKER_CHAOS_USER@kv file: false @@ -580,6 +589,12 @@ build-linux-substrate: &build-binary - cp -r .maintain/docker/substrate.Dockerfile ./artifacts/substrate/ - sccache -s +#Build binary for simnet quick tests. +build-linux-substrate-simnet: + <<: *build-binary + <<: *collect-artifacts-short + <<: *test-refs-no-trigger-prs-only + build-linux-subkey: &build-subkey stage: build <<: *collect-artifacts @@ -689,6 +704,25 @@ publish-docker-substrate: # https://docs.gitlab.com/ee/ci/multi_project_pipelines.html#with-variable-inheritance dotenv: ./artifacts/substrate/build.env +#publish artifact for quick simnet tests +publish-docker-substrate-simnet: + stage: publish + <<: *build-push-docker-image + <<: *test-refs-no-trigger-prs-only + needs: + - job: build-linux-substrate-simnet + artifacts: true + variables: + <<: *default-vars + GIT_STRATEGY: none + DOCKERFILE: $PRODUCT.Dockerfile + PRODUCT: substrate + IMAGE_NAME: docker.io/paritypr/$PRODUCT + artifacts: + reports: + # this artifact is used in simnet-tests-quick job + dotenv: ./artifacts/substrate/build.env + publish-docker-subkey: stage: publish <<: *build-push-docker-image @@ -871,7 +905,7 @@ simnet-tests: before_script: - echo "Simnet Tests Config docker.io/paritytech/simnet:${SIMNET_REF} - ${SUBSTRATE_IMAGE_NAME} ${SUBSTRATE_IAMGE_TAG}" + ${SUBSTRATE_IMAGE_NAME} ${SUBSTRATE_IMAGE_TAG}" script: - /home/nonroot/simnet/gurke/scripts/run-test-environment-manager.sh --github-remote-dir="https://github.com/paritytech/substrate/tree/master/simnet_tests" @@ -879,4 +913,31 @@ simnet-tests: --image="${SUBSTRATE_IMAGE_NAME}:${SUBSTRATE_IMAGE_TAG}" retry: 2 tags: - - parity-simnet + - substrate-simnet + +#run quick simnet-tests for each PR +simnet-tests-quick: + stage: deploy + image: docker.io/paritytech/simnet:${SIMNET_REF} + <<: *kubernetes-env + <<: *vault-secrets + <<: *test-refs-no-trigger-prs-only + variables: + SIMNET_FEATURES: "${SIMNET_FEATURES_PATH}/quick" + needs: + - job: publish-docker-substrate-simnet + before_script: + - echo "Simnet Tests Config + docker.io/paritytech/simnet:${SIMNET_REF} + ${SUBSTRATE_IMAGE_NAME} ${SUBSTRATE_IMAGE_TAG}" + script: + - echo "Image=${SUBSTRATE_IMAGE_NAME}:${SUBSTRATE_IMAGE_TAG}" + - echo "Features=${SIMNET_FEATURES}" + - /home/nonroot/simnet/gurke/scripts/run-test-environment-manager.sh + --github-remote-dir="https://github.com/paritytech/substrate/tree/master/simnet_tests" + --config="simnet_tests/configs/default_local_testnet.toml" + --image="${SUBSTRATE_IMAGE_NAME}:${SUBSTRATE_IMAGE_TAG}" + --features="${SIMNET_FEATURES}" + tags: + - substrate-simnet + diff --git a/README.md b/README.md index 6288540548a0..a4d0b9c68357 100644 --- a/README.md +++ b/README.md @@ -28,3 +28,4 @@ The security policy and procedures can be found in [`docs/SECURITY.md`](docs/SEC The reason for the split-licensing is to ensure that for the vast majority of teams using Substrate to create feature-chains, then all changes can be made entirely in Apache2-licensed code, allowing teams full freedom over what and how they release and giving licensing clarity to commercial teams. In the interests of the community, we require any deeper improvements made to Substrate's core logic (e.g. Substrate's internal consensus, crypto or database code) to be contributed back so everyone can benefit. + From 12b6441ef138303f50fa2fb20895fbf57c8e4735 Mon Sep 17 00:00:00 2001 From: Alexander Popiak Date: Mon, 11 Oct 2021 16:23:10 +0200 Subject: [PATCH 066/695] Add Deposit and Withdraw Events to Balances Pallet (#9425) * add Deposit and Withdraw events to balances + add deposit_event() calls where appropriate to signal fund movement + adjust and extend tests * line length * move events to the end to avoid changing indices * bump spec_version * cargo fmt * adjust block import bench to new event count * fix node executor tests * adjust import bench comment * fix typo and formatting * adjust event number * fix copy pasta * fix contracts pallets tests * cargo fmt * WIP fix events in tests * fix offences tests * fix tests * cargo +nightly fmt * fix contracts pallets tests * cargo +nightly fmt * fix offences tests * formatting and compile fixes Co-authored-by: Shawn Tabrizi --- bin/node/bench/src/import.rs | 18 +-- bin/node/executor/tests/basic.rs | 39 +++++++ bin/node/runtime/src/lib.rs | 4 +- frame/balances/src/lib.rs | 38 ++++++- frame/balances/src/tests.rs | 20 +++- frame/balances/src/tests_local.rs | 3 +- frame/balances/src/tests_reentrancy.rs | 15 ++- frame/contracts/src/tests.rs | 5 + frame/offences/benchmarking/src/lib.rs | 152 ++++++++++++++++--------- 9 files changed, 218 insertions(+), 76 deletions(-) diff --git a/bin/node/bench/src/import.rs b/bin/node/bench/src/import.rs index 5bbf1ddf3b73..da9d0cdaf85b 100644 --- a/bin/node/bench/src/import.rs +++ b/bin/node/bench/src/import.rs @@ -135,18 +135,20 @@ impl core::Benchmark for ImportBenchmark { .inspect_state(|| { match self.block_type { BlockType::RandomTransfersKeepAlive => { - // should be 5 per signed extrinsic + 1 per unsigned + // should be 7 per signed extrinsic + 1 per unsigned // we have 1 unsigned and the rest are signed in the block - // those 5 events per signed are: - // - new account (RawEvent::NewAccount) as we always transfer fund to - // non-existant account - // - endowed (RawEvent::Endowed) for this new account - // - successful transfer (RawEvent::Transfer) for this transfer operation - // - deposit event for charging transaction fee + // those 7 events per signed are: + // - withdraw (Balances::Withdraw) for charging the transaction fee + // - new account (System::NewAccount) as we always transfer fund to + // non-existent account + // - endowed (Balances::Endowed) for this new account + // - successful transfer (Event::Transfer) for this transfer operation + // - 2x deposit (Balances::Deposit and Treasury::Deposit) for depositing + // the transaction fee into the treasury // - extrinsic success assert_eq!( node_runtime::System::events().len(), - (self.block.extrinsics.len() - 1) * 5 + 1, + (self.block.extrinsics.len() - 1) * 7 + 1, ); }, BlockType::Noop => { diff --git a/bin/node/executor/tests/basic.rs b/bin/node/executor/tests/basic.rs index c1ab5e5a0fe1..bbb9339189b0 100644 --- a/bin/node/executor/tests/basic.rs +++ b/bin/node/executor/tests/basic.rs @@ -385,6 +385,11 @@ fn full_native_block_import_works() { })), topics: vec![], }, + EventRecord { + phase: Phase::ApplyExtrinsic(1), + event: Event::Balances(pallet_balances::Event::Withdraw(alice().into(), fees)), + topics: vec![], + }, EventRecord { phase: Phase::ApplyExtrinsic(1), event: Event::Balances(pallet_balances::Event::Transfer( @@ -394,6 +399,14 @@ fn full_native_block_import_works() { )), topics: vec![], }, + EventRecord { + phase: Phase::ApplyExtrinsic(1), + event: Event::Balances(pallet_balances::Event::Deposit( + pallet_treasury::Pallet::::account_id(), + fees * 8 / 10, + )), + topics: vec![], + }, EventRecord { phase: Phase::ApplyExtrinsic(1), event: Event::Treasury(pallet_treasury::Event::Deposit(fees * 8 / 10)), @@ -439,6 +452,11 @@ fn full_native_block_import_works() { })), topics: vec![], }, + EventRecord { + phase: Phase::ApplyExtrinsic(1), + event: Event::Balances(pallet_balances::Event::Withdraw(bob().into(), fees)), + topics: vec![], + }, EventRecord { phase: Phase::ApplyExtrinsic(1), event: Event::Balances(pallet_balances::Event::Transfer( @@ -448,6 +466,14 @@ fn full_native_block_import_works() { )), topics: vec![], }, + EventRecord { + phase: Phase::ApplyExtrinsic(1), + event: Event::Balances(pallet_balances::Event::Deposit( + pallet_treasury::Pallet::::account_id(), + fees * 8 / 10, + )), + topics: vec![], + }, EventRecord { phase: Phase::ApplyExtrinsic(1), event: Event::Treasury(pallet_treasury::Event::Deposit(fees * 8 / 10)), @@ -461,6 +487,11 @@ fn full_native_block_import_works() { })), topics: vec![], }, + EventRecord { + phase: Phase::ApplyExtrinsic(2), + event: Event::Balances(pallet_balances::Event::Withdraw(alice().into(), fees)), + topics: vec![], + }, EventRecord { phase: Phase::ApplyExtrinsic(2), event: Event::Balances(pallet_balances::Event::Transfer( @@ -470,6 +501,14 @@ fn full_native_block_import_works() { )), topics: vec![], }, + EventRecord { + phase: Phase::ApplyExtrinsic(2), + event: Event::Balances(pallet_balances::Event::Deposit( + pallet_treasury::Pallet::::account_id(), + fees * 8 / 10, + )), + topics: vec![], + }, EventRecord { phase: Phase::ApplyExtrinsic(2), event: Event::Treasury(pallet_treasury::Event::Deposit(fees * 8 / 10)), diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 4f620976c3ab..c7920629bf35 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -121,8 +121,8 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // and set impl_version to 0. If only runtime // implementation changes and behavior does not, then leave spec_version as // is and increment impl_version. - spec_version: 267, - impl_version: 1, + spec_version: 268, + impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 2, }; diff --git a/frame/balances/src/lib.rs b/frame/balances/src/lib.rs index afd2331c8e3c..da8019583c3b 100644 --- a/frame/balances/src/lib.rs +++ b/frame/balances/src/lib.rs @@ -463,8 +463,6 @@ pub mod pallet { Transfer(T::AccountId, T::AccountId, T::Balance), /// A balance was set by root. \[who, free, reserved\] BalanceSet(T::AccountId, T::Balance, T::Balance), - /// Some amount was deposited (e.g. for transaction fees). \[who, deposit\] - Deposit(T::AccountId, T::Balance), /// Some balance was reserved (moved from free to reserved). \[who, value\] Reserved(T::AccountId, T::Balance), /// Some balance was unreserved (moved from reserved to free). \[who, value\] @@ -473,6 +471,14 @@ pub mod pallet { /// Final argument indicates the destination balance type. /// \[from, to, balance, destination_status\] ReserveRepatriated(T::AccountId, T::AccountId, T::Balance, Status), + /// Some amount was deposited into the account (e.g. for transaction fees). \[who, + /// deposit\] + Deposit(T::AccountId, T::Balance), + /// Some amount was withdrawn from the account (e.g. for transaction fees). \[who, value\] + Withdraw(T::AccountId, T::Balance), + /// Some amount was removed from the account (e.g. for misbehavior). \[who, + /// amount_slashed\] + Slashed(T::AccountId, T::Balance), } /// Old name generated by `decl_event`. @@ -1103,6 +1109,7 @@ impl, I: 'static> fungible::Mutate for Pallet { Ok(()) })?; TotalIssuance::::mutate(|t| *t += amount); + Self::deposit_event(Event::Deposit(who.clone(), amount)); Ok(()) } @@ -1123,6 +1130,7 @@ impl, I: 'static> fungible::Mutate for Pallet { }, )?; TotalIssuance::::mutate(|t| *t -= actual); + Self::deposit_event(Event::Withdraw(who.clone(), amount)); Ok(actual) } } @@ -1141,7 +1149,10 @@ impl, I: 'static> fungible::Transfer for Pallet impl, I: 'static> fungible::Unbalanced for Pallet { fn set_balance(who: &T::AccountId, amount: Self::Balance) -> DispatchResult { - Self::mutate_account(who, |account| account.free = amount)?; + Self::mutate_account(who, |account| { + account.free = amount; + Self::deposit_event(Event::BalanceSet(who.clone(), account.free, account.reserved)); + })?; Ok(()) } @@ -1583,7 +1594,13 @@ where } }, ) { - Ok(r) => return r, + Ok((imbalance, not_slashed)) => { + Self::deposit_event(Event::Slashed( + who.clone(), + value.saturating_sub(not_slashed), + )); + return (imbalance, not_slashed) + }, Err(_) => (), } } @@ -1608,6 +1625,7 @@ where |account, is_new| -> Result { ensure!(!is_new, Error::::DeadAccount); account.free = account.free.checked_add(&value).ok_or(ArithmeticError::Overflow)?; + Self::deposit_event(Event::Deposit(who.clone(), value)); Ok(PositiveImbalance::new(value)) }, ) @@ -1640,6 +1658,7 @@ where None => return Ok(Self::PositiveImbalance::zero()), }; + Self::deposit_event(Event::Deposit(who.clone(), value)); Ok(PositiveImbalance::new(value)) }, ) @@ -1677,6 +1696,7 @@ where account.free = new_free_account; + Self::deposit_event(Event::Withdraw(who.clone(), value)); Ok(NegativeImbalance::new(value)) }, ) @@ -1709,6 +1729,7 @@ where SignedImbalance::Negative(NegativeImbalance::new(account.free - value)) }; account.free = value; + Self::deposit_event(Event::BalanceSet(who.clone(), account.free, account.reserved)); Ok(imbalance) }, ) @@ -1824,7 +1845,13 @@ where // underflow should never happen, but it if does, there's nothing to be done here. (NegativeImbalance::new(actual), value - actual) }) { - Ok(r) => return r, + Ok((imbalance, not_slashed)) => { + Self::deposit_event(Event::Slashed( + who.clone(), + value.saturating_sub(not_slashed), + )); + return (imbalance, not_slashed) + }, Err(_) => (), } } @@ -1965,6 +1992,7 @@ where // `actual <= to_change` and `to_change <= amount`; qed; reserves[index].amount -= actual; + Self::deposit_event(Event::Slashed(who.clone(), actual)); (imb, value - actual) }, Err(_) => (NegativeImbalance::zero(), value), diff --git a/frame/balances/src/tests.rs b/frame/balances/src/tests.rs index a08643821eba..6a6ebc692c34 100644 --- a/frame/balances/src/tests.rs +++ b/frame/balances/src/tests.rs @@ -314,6 +314,7 @@ macro_rules! decl_tests { <$ext_builder>::default().monied(true).build().execute_with(|| { assert_eq!(Balances::total_balance(&1), 10); assert_ok!(Balances::deposit_into_existing(&1, 10).map(drop)); + System::assert_last_event(Event::Balances(crate::Event::Deposit(1, 10))); assert_eq!(Balances::total_balance(&1), 20); assert_eq!(>::get(), 120); }); @@ -341,6 +342,7 @@ macro_rules! decl_tests { fn balance_works() { <$ext_builder>::default().build().execute_with(|| { let _ = Balances::deposit_creating(&1, 42); + System::assert_has_event(Event::Balances(crate::Event::Deposit(1, 42))); assert_eq!(Balances::free_balance(1), 42); assert_eq!(Balances::reserved_balance(1), 0); assert_eq!(Balances::total_balance(&1), 42); @@ -435,6 +437,19 @@ macro_rules! decl_tests { }); } + #[test] + fn withdrawing_balance_should_work() { + <$ext_builder>::default().build().execute_with(|| { + let _ = Balances::deposit_creating(&2, 111); + let _ = Balances::withdraw( + &2, 11, WithdrawReasons::TRANSFER, ExistenceRequirement::KeepAlive + ); + System::assert_last_event(Event::Balances(crate::Event::Withdraw(2, 11))); + assert_eq!(Balances::free_balance(2), 100); + assert_eq!(>::get(), 100); + }); + } + #[test] fn slashing_incomplete_balance_should_work() { <$ext_builder>::default().build().execute_with(|| { @@ -749,6 +764,7 @@ macro_rules! decl_tests { [ Event::System(system::Event::KilledAccount(1)), Event::Balances(crate::Event::DustLost(1, 99)), + Event::Balances(crate::Event::Slashed(1, 1)), ] ); }); @@ -777,7 +793,8 @@ macro_rules! decl_tests { assert_eq!( events(), [ - Event::System(system::Event::KilledAccount(1)) + Event::System(system::Event::KilledAccount(1)), + Event::Balances(crate::Event::Slashed(1, 100)), ] ); }); @@ -797,6 +814,7 @@ macro_rules! decl_tests { assert_eq!(Balances::slash(&1, 900), (NegativeImbalance::new(900), 0)); // Account is still alive assert!(System::account_exists(&1)); + System::assert_last_event(Event::Balances(crate::Event::Slashed(1, 900))); // SCENARIO: Slash will kill account because not enough balance left. assert_ok!(Balances::set_balance(Origin::root(), 1, 1_000, 0)); diff --git a/frame/balances/src/tests_local.rs b/frame/balances/src/tests_local.rs index 1d758ce4e980..b2113a916caa 100644 --- a/frame/balances/src/tests_local.rs +++ b/frame/balances/src/tests_local.rs @@ -173,7 +173,7 @@ fn emit_events_with_no_existential_deposit_suicide_with_dust() { assert_eq!(res, (NegativeImbalance::new(98), 0)); // no events - assert_eq!(events(), []); + assert_eq!(events(), [Event::Balances(crate::Event::Slashed(1, 98))]); let res = Balances::slash(&1, 1); assert_eq!(res, (NegativeImbalance::new(1), 0)); @@ -183,6 +183,7 @@ fn emit_events_with_no_existential_deposit_suicide_with_dust() { [ Event::System(system::Event::KilledAccount(1)), Event::Balances(crate::Event::DustLost(1, 1)), + Event::Balances(crate::Event::Slashed(1, 1)), ] ); }); diff --git a/frame/balances/src/tests_reentrancy.rs b/frame/balances/src/tests_reentrancy.rs index 25b8fb34f20b..9a5ebb003af2 100644 --- a/frame/balances/src/tests_reentrancy.rs +++ b/frame/balances/src/tests_reentrancy.rs @@ -167,11 +167,11 @@ fn transfer_dust_removal_tst1_should_work() { assert_eq!(Balances::free_balance(&1), 1050); // Verify the events - // Number of events expected is 8 - assert_eq!(System::events().len(), 11); + assert_eq!(System::events().len(), 12); System::assert_has_event(Event::Balances(crate::Event::Transfer(2, 3, 450))); System::assert_has_event(Event::Balances(crate::Event::DustLost(2, 50))); + System::assert_has_event(Event::Balances(crate::Event::Deposit(1, 50))); }); } @@ -195,11 +195,11 @@ fn transfer_dust_removal_tst2_should_work() { assert_eq!(Balances::free_balance(&1), 1500); // Verify the events - // Number of events expected is 8 - assert_eq!(System::events().len(), 9); + assert_eq!(System::events().len(), 10); System::assert_has_event(Event::Balances(crate::Event::Transfer(2, 1, 450))); System::assert_has_event(Event::Balances(crate::Event::DustLost(2, 50))); + System::assert_has_event(Event::Balances(crate::Event::Deposit(1, 50))); }); } @@ -232,8 +232,7 @@ fn repatriating_reserved_balance_dust_removal_should_work() { assert_eq!(Balances::free_balance(1), 1500); // Verify the events - // Number of events expected is 10 - assert_eq!(System::events().len(), 10); + assert_eq!(System::events().len(), 11); System::assert_has_event(Event::Balances(crate::Event::ReserveRepatriated( 2, @@ -241,7 +240,7 @@ fn repatriating_reserved_balance_dust_removal_should_work() { 450, Status::Free, ))); - - System::assert_last_event(Event::Balances(crate::Event::DustLost(2, 50))); + System::assert_has_event(Event::Balances(crate::Event::DustLost(2, 50))); + System::assert_last_event(Event::Balances(crate::Event::Deposit(1, 50))); }); } diff --git a/frame/contracts/src/tests.rs b/frame/contracts/src/tests.rs index b2141ca18b0b..310c1d4cb2dd 100644 --- a/frame/contracts/src/tests.rs +++ b/frame/contracts/src/tests.rs @@ -444,6 +444,11 @@ fn instantiate_and_call_and_deposit_event() { assert_eq!( System::events(), vec![ + EventRecord { + phase: Phase::Initialization, + event: Event::Balances(pallet_balances::Event::Deposit(ALICE, 1_000_000)), + topics: vec![], + }, EventRecord { phase: Phase::Initialization, event: Event::System(frame_system::Event::NewAccount(ALICE.clone())), diff --git a/frame/offences/benchmarking/src/lib.rs b/frame/offences/benchmarking/src/lib.rs index dde8aa92c240..c920b0b900df 100644 --- a/frame/offences/benchmarking/src/lib.rs +++ b/frame/offences/benchmarking/src/lib.rs @@ -224,27 +224,49 @@ fn check_events::Event>>(expec .map(|frame_system::EventRecord { event, .. }| event) .collect::>(); let expected = expected.collect::>(); - let lengths = (events.len(), expected.len()); - let length_mismatch = if lengths.0 != lengths.1 { - fn pretty(header: &str, ev: &[D]) { - println!("{}", header); - for (idx, ev) in ev.iter().enumerate() { - println!("\t[{:04}] {:?}", idx, ev); - } + + fn pretty(header: &str, ev: &[D], offset: usize) { + println!("{}", header); + for (idx, ev) in ev.iter().enumerate() { + println!("\t[{:04}] {:?}", idx + offset, ev); } - pretty("--Got:", &events); - pretty("--Expected:", &expected); - format!("Mismatching length. Got: {}, expected: {}", lengths.0, lengths.1) - } else { - Default::default() - }; + } + fn print_events(idx: usize, events: &[D], expected: &[D]) { + let window = 10; + let start = idx.saturating_sub(window / 2); + let end_got = (idx + window / 2).min(events.len()); + pretty("Got(window):", &events[start..end_got], start); + let end_expected = (idx + window / 2).min(expected.len()); + pretty("Expected(window):", &expected[start..end_expected], start); + println!("---------------"); + let start_got = events.len().saturating_sub(window); + pretty("Got(end):", &events[start_got..], start_got); + let start_expected = expected.len().saturating_sub(window); + pretty("Expected(end):", &expected[start_expected..], start_expected); + } + let events_copy = events.clone(); + let expected_copy = expected.clone(); for (idx, (a, b)) in events.into_iter().zip(expected).enumerate() { - assert_eq!(a, b, "Mismatch at: {}. {}", idx, length_mismatch); + if a != b { + print_events(idx, &events_copy, &expected_copy); + println!("Mismatch at: {}", idx); + println!(" Got: {:?}", b); + println!("Expected: {:?}", a); + if events_copy.len() != expected_copy.len() { + println!( + "Mismatching lengths. Got: {}, Expected: {}", + events_copy.len(), + expected_copy.len() + ) + } + panic!("Mismatching events."); + } } - if !length_mismatch.is_empty() { - panic!("{}", length_mismatch); + if events_copy.len() != expected_copy.len() { + print_events(0, &events_copy, &expected_copy); + panic!("Mismatching lengths. Got: {}, Expected: {}", events_copy.len(), expected_copy.len()) } } @@ -288,46 +310,74 @@ benchmarks! { let bond_amount: u32 = UniqueSaturatedInto::::unique_saturated_into(bond_amount::()); let slash_amount = slash_fraction * bond_amount; let reward_amount = slash_amount * (1 + n) / 2; + let reward = reward_amount / r; let slash = |id| core::iter::once( ::Event::from(StakingEvent::::Slashed(id, BalanceOf::::from(slash_amount))) ); + let balance_slash = |id| core::iter::once( + ::Event::from(pallet_balances::Event::::Slashed(id, slash_amount.into())) + ); let chill = |id| core::iter::once( ::Event::from(StakingEvent::::Chilled(id)) ); - let mut slash_events = raw_offenders.into_iter() + let balance_deposit = |id, amount: u32| + ::Event::from(pallet_balances::Event::::Deposit(id, amount.into())); + let mut first = true; + let slash_events = raw_offenders.into_iter() .flat_map(|offender| { - let nom_slashes = offender.nominator_stashes.into_iter().flat_map(|nom| slash(nom)); - chill(offender.stash.clone()) - .chain(slash(offender.stash)) - .chain(nom_slashes) + let nom_slashes = offender.nominator_stashes.into_iter().flat_map(|nom| { + balance_slash(nom.clone()).map(Into::into) + .chain(slash(nom.clone()).map(Into::into)) + }).collect::>(); + + let mut events = chill(offender.stash.clone()).map(Into::into) + .chain(balance_slash(offender.stash.clone()).map(Into::into)) + .chain(slash(offender.stash.clone()).map(Into::into)) + .chain(nom_slashes.into_iter()) + .collect::>(); + + // the first deposit creates endowed events, see `endowed_reward_events` + if first { + first = false; + let mut reward_events = reporters.clone().into_iter() + .flat_map(|reporter| vec![ + balance_deposit(reporter.clone(), reward.into()).into(), + frame_system::Event::::NewAccount(reporter.clone()).into(), + ::Event::from( + pallet_balances::Event::::Endowed(reporter.clone(), reward.into()) + ).into(), + ]) + .collect::>(); + events.append(&mut reward_events); + events.into_iter() + } else { + let mut reward_events = reporters.clone().into_iter() + .map(|reporter| balance_deposit(reporter, reward.into()).into()) + .collect::>(); + events.append(&mut reward_events); + events.into_iter() + } }) .collect::>(); - let reward_events = reporters.into_iter() - .flat_map(|reporter| vec![ - frame_system::Event::::NewAccount(reporter.clone()).into(), - ::Event::from( - pallet_balances::Event::::Endowed(reporter, (reward_amount / r).into()) - ).into() - ]); - - // Rewards are applied after first offender and it's nominators. - // We split after: offender slash + offender chill + nominator slashes. - let slash_rest = slash_events.split_off(2 + n as usize); - // make sure that all slashes have been applied + + #[cfg(test)] - check_events::( - std::iter::empty() - .chain(slash_events.into_iter().map(Into::into)) - .chain(reward_events) - .chain(slash_rest.into_iter().map(Into::into)) - .chain(std::iter::once(::Event::from( - pallet_offences::Event::Offence( - UnresponsivenessOffence::::ID, - 0_u32.to_le_bytes().to_vec(), - ) - ).into())) - ); + { + // In case of error it's useful to see the inputs + println!("Inputs: r: {}, o: {}, n: {}", r, o, n); + // make sure that all slashes have been applied + check_events::( + std::iter::empty() + .chain(slash_events.into_iter().map(Into::into)) + .chain(std::iter::once(::Event::from( + pallet_offences::Event::Offence( + UnresponsivenessOffence::::ID, + 0_u32.to_le_bytes().to_vec(), + ) + ).into())) + ); + } } report_offence_grandpa { @@ -358,10 +408,10 @@ benchmarks! { assert_eq!( System::::event_count(), 0 + 1 // offence - + 2 // reporter (reward + endowment) - + 1 // offenders slashed + + 3 // reporter (reward + endowment) + + 2 // offenders slashed + 1 // offenders chilled - + n // nominators slashed + + 2 * n // nominators slashed ); } @@ -393,10 +443,10 @@ benchmarks! { assert_eq!( System::::event_count(), 0 + 1 // offence - + 2 // reporter (reward + endowment) - + 1 // offenders slashed + + 3 // reporter (reward + endowment) + + 2 // offenders slashed + 1 // offenders chilled - + n // nominators slashed + + 2 * n // nominators slashed ); } From d6a095ad3149b76e8a8cba340d9c295790aa3354 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Oct 2021 15:24:24 +0000 Subject: [PATCH 067/695] Bump pin-project from 1.0.5 to 1.0.8 (#9999) Bumps [pin-project](https://github.com/taiki-e/pin-project) from 1.0.5 to 1.0.8. - [Release notes](https://github.com/taiki-e/pin-project/releases) - [Changelog](https://github.com/taiki-e/pin-project/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/pin-project/compare/v1.0.5...v1.0.8) --- updated-dependencies: - dependency-name: pin-project dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 30 +++++++++++++++--------------- client/network/Cargo.toml | 2 +- client/service/Cargo.toml | 2 +- client/telemetry/Cargo.toml | 2 +- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7af65c8bcf79..74c0cfe68df6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3148,7 +3148,7 @@ dependencies = [ "futures 0.3.16", "jsonrpsee-types", "log 0.4.14", - "pin-project 1.0.5", + "pin-project 1.0.8", "rustls", "rustls-native-certs", "serde", @@ -3348,7 +3348,7 @@ dependencies = [ "libp2p-yamux", "multiaddr", "parking_lot 0.11.1", - "pin-project 1.0.5", + "pin-project 1.0.8", "smallvec 1.7.0", "wasm-timer", ] @@ -3373,7 +3373,7 @@ dependencies = [ "multihash 0.14.0", "multistream-select", "parking_lot 0.11.1", - "pin-project 1.0.5", + "pin-project 1.0.8", "prost", "prost-build", "rand 0.7.3", @@ -3599,7 +3599,7 @@ checksum = "07cb4dd4b917e5b40ddefe49b96b07adcd8d342e0317011d175b7b2bb1dcc974" dependencies = [ "futures 0.3.16", "log 0.4.14", - "pin-project 1.0.5", + "pin-project 1.0.8", "rand 0.7.3", "salsa20", "sha3", @@ -3618,7 +3618,7 @@ dependencies = [ "libp2p-core", "libp2p-swarm", "log 0.4.14", - "pin-project 1.0.5", + "pin-project 1.0.8", "prost", "prost-build", "rand 0.7.3", @@ -4316,7 +4316,7 @@ dependencies = [ "bytes 1.0.1", "futures 0.3.16", "log 0.4.14", - "pin-project 1.0.5", + "pin-project 1.0.8", "smallvec 1.7.0", "unsigned-varint 0.7.0", ] @@ -6441,11 +6441,11 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.0.5" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96fa8ebb90271c4477f144354485b8068bd8f6b78b428b01ba892ca26caf0b63" +checksum = "576bc800220cc65dac09e99e97b08b358cfab6e17078de8dc5fee223bd2d0c08" dependencies = [ - "pin-project-internal 1.0.5", + "pin-project-internal 1.0.8", ] [[package]] @@ -6461,9 +6461,9 @@ dependencies = [ [[package]] name = "pin-project-internal" -version = "1.0.5" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "758669ae3558c6f74bd2a18b41f7ac0b5a195aea6639d6a9b5e5d1ad5ba24c0b" +checksum = "6e8fe8163d14ce7f0cdac2e040116f22eac817edabff0be91e8aff7e9accf389" dependencies = [ "proc-macro2", "quote", @@ -8077,7 +8077,7 @@ dependencies = [ "lru", "parity-scale-codec", "parking_lot 0.11.1", - "pin-project 1.0.5", + "pin-project 1.0.8", "prost", "prost-build", "quickcheck", @@ -8316,7 +8316,7 @@ dependencies = [ "parity-scale-codec", "parity-util-mem", "parking_lot 0.11.1", - "pin-project 1.0.5", + "pin-project 1.0.8", "rand 0.7.3", "sc-block-builder", "sc-chain-spec", @@ -8446,7 +8446,7 @@ dependencies = [ "libp2p", "log 0.4.14", "parking_lot 0.11.1", - "pin-project 1.0.5", + "pin-project 1.0.8", "rand 0.7.3", "serde", "serde_json", @@ -10610,7 +10610,7 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" dependencies = [ - "pin-project 1.0.5", + "pin-project 1.0.8", "tracing", ] diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index 1725e4f5abcf..319bce4d0e6b 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -39,7 +39,7 @@ linked_hash_set = "0.1.3" lru = "0.6.6" log = "0.4.8" parking_lot = "0.11.1" -pin-project = "1.0.4" +pin-project = "1.0.8" prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.9.0", path = "../../utils/prometheus" } prost = "0.8" rand = "0.7.2" diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index 6f63a249a7c8..0a496a55adc4 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -31,7 +31,7 @@ parking_lot = "0.11.1" log = "0.4.11" futures-timer = "3.0.1" exit-future = "0.2.0" -pin-project = "1.0.4" +pin-project = "1.0.8" hash-db = "0.15.2" serde = "1.0.126" serde_json = "1.0.68" diff --git a/client/telemetry/Cargo.toml b/client/telemetry/Cargo.toml index f115017f0970..0c5e2db6c776 100644 --- a/client/telemetry/Cargo.toml +++ b/client/telemetry/Cargo.toml @@ -20,7 +20,7 @@ futures = "0.3.9" wasm-timer = "0.2.5" libp2p = { version = "0.39.1", default-features = false, features = ["dns-async-std", "tcp-async-io", "wasm-ext", "websocket"] } log = "0.4.8" -pin-project = "1.0.4" +pin-project = "1.0.8" rand = "0.7.2" serde = { version = "1.0.126", features = ["derive"] } serde_json = "1.0.68" From 66ba332eb34a82c60332a3f713375601df4e4f27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Mon, 11 Oct 2021 19:50:12 +0200 Subject: [PATCH 068/695] sc-offchain: Fix flaky http tests (#10000) --- client/offchain/src/api/http.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/client/offchain/src/api/http.rs b/client/offchain/src/api/http.rs index ce9fb298d1b0..31f7d60e34ff 100644 --- a/client/offchain/src/api/http.rs +++ b/client/offchain/src/api/http.rs @@ -700,7 +700,7 @@ mod tests { use super::{http, SharedClient}; use crate::api::timestamp; use core::convert::Infallible; - use futures::future; + use futures::{future, StreamExt}; use lazy_static::lazy_static; use sp_core::offchain::{Duration, HttpError, HttpRequestId, HttpRequestStatus}; @@ -725,7 +725,11 @@ mod tests { let server = hyper::Server::bind(&"127.0.0.1:0".parse().unwrap()).serve( hyper::service::make_service_fn(|_| async move { Ok::<_, Infallible>(hyper::service::service_fn( - move |_req| async move { + move |req: hyper::Request| async move { + // Wait until the complete request was received and processed, + // otherwise the tests are flaky. + let _ = req.into_body().collect::>().await; + Ok::<_, Infallible>(hyper::Response::new(hyper::Body::from( "Hello World!", ))) From e308d0fdc0acb8ec76eeef2c02e09bcafc5e46c2 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Tue, 12 Oct 2021 05:50:21 +0200 Subject: [PATCH 069/695] pow: add Version for quick-check of metadata state and refactor lock handling (#9698) * pow: add Version for quick-check of metadata state and refactor lock handling * typo: mut self -> self * Run rustfmt * typo: grammar --- client/consensus/pow/src/lib.rs | 18 +-- client/consensus/pow/src/worker.rs | 210 ++++++++++++++++++++--------- 2 files changed, 152 insertions(+), 76 deletions(-) diff --git a/client/consensus/pow/src/lib.rs b/client/consensus/pow/src/lib.rs index 1f5781434ef7..7b1012888e86 100644 --- a/client/consensus/pow/src/lib.rs +++ b/client/consensus/pow/src/lib.rs @@ -41,13 +41,12 @@ mod worker; -pub use crate::worker::{MiningBuild, MiningMetadata, MiningWorker}; +pub use crate::worker::{MiningBuild, MiningHandle, MiningMetadata}; use crate::worker::UntilImportedOrTimeout; use codec::{Decode, Encode}; use futures::{Future, StreamExt}; use log::*; -use parking_lot::Mutex; use prometheus_endpoint::Registry; use sc_client_api::{self, backend::AuxStore, BlockOf, BlockchainEvents}; use sc_consensus::{ @@ -525,7 +524,7 @@ pub fn start_mining_worker( build_time: Duration, can_author_with: CAW, ) -> ( - Arc>::Proof>>>, + MiningHandle>::Proof>, impl Future, ) where @@ -543,12 +542,7 @@ where CAW: CanAuthorWith + Clone + Send + 'static, { let mut timer = UntilImportedOrTimeout::new(client.import_notification_stream(), timeout); - let worker = Arc::new(Mutex::new(MiningWorker { - build: None, - algorithm: algorithm.clone(), - block_import, - justification_sync_link, - })); + let worker = MiningHandle::new(algorithm.clone(), block_import, justification_sync_link); let worker_ret = worker.clone(); let task = async move { @@ -559,7 +553,7 @@ where if sync_oracle.is_major_syncing() { debug!(target: "pow", "Skipping proposal due to sync."); - worker.lock().on_major_syncing(); + worker.on_major_syncing(); continue } @@ -587,7 +581,7 @@ where continue } - if worker.lock().best_hash() == Some(best_hash) { + if worker.best_hash() == Some(best_hash) { continue } @@ -682,7 +676,7 @@ where proposal, }; - worker.lock().on_build(build); + worker.on_build(build); } }; diff --git a/client/consensus/pow/src/worker.rs b/client/consensus/pow/src/worker.rs index c0ca16ccad3a..3faa18ece318 100644 --- a/client/consensus/pow/src/worker.rs +++ b/client/consensus/pow/src/worker.rs @@ -22,6 +22,7 @@ use futures::{ }; use futures_timer::Delay; use log::*; +use parking_lot::Mutex; use sc_client_api::ImportNotifications; use sc_consensus::{BlockImportParams, BoxBlockImport, StateAction, StorageChanges}; use sp_consensus::{BlockOrigin, Proposal}; @@ -30,7 +31,16 @@ use sp_runtime::{ traits::{Block as BlockT, Header as HeaderT}, DigestItem, }; -use std::{borrow::Cow, collections::HashMap, pin::Pin, time::Duration}; +use std::{ + borrow::Cow, + collections::HashMap, + pin::Pin, + sync::{ + atomic::{AtomicUsize, Ordering}, + Arc, + }, + time::Duration, +}; use crate::{PowAlgorithm, PowIntermediate, Seal, INTERMEDIATE_KEY, POW_ENGINE_ID}; @@ -60,21 +70,26 @@ pub struct MiningBuild< pub proposal: Proposal, Proof>, } +/// Version of the mining worker. +#[derive(Eq, PartialEq, Clone, Copy)] +pub struct Version(usize); + /// Mining worker that exposes structs to query the current mining build and submit mined blocks. -pub struct MiningWorker< +pub struct MiningHandle< Block: BlockT, Algorithm: PowAlgorithm, C: sp_api::ProvideRuntimeApi, L: sc_consensus::JustificationSyncLink, Proof, > { - pub(crate) build: Option>, - pub(crate) algorithm: Algorithm, - pub(crate) block_import: BoxBlockImport>, - pub(crate) justification_sync_link: L, + version: Arc, + algorithm: Arc, + justification_sync_link: Arc, + build: Arc>>>, + block_import: Arc>>>, } -impl MiningWorker +impl MiningHandle where Block: BlockT, C: sp_api::ProvideRuntimeApi, @@ -83,35 +98,65 @@ where L: sc_consensus::JustificationSyncLink, sp_api::TransactionFor: Send + 'static, { - /// Get the current best hash. `None` if the worker has just started or the client is doing - /// major syncing. - pub fn best_hash(&self) -> Option { - self.build.as_ref().map(|b| b.metadata.best_hash) + fn increment_version(&self) { + self.version.fetch_add(1, Ordering::SeqCst); } - pub(crate) fn on_major_syncing(&mut self) { - self.build = None; + pub(crate) fn new( + algorithm: Algorithm, + block_import: BoxBlockImport>, + justification_sync_link: L, + ) -> Self { + Self { + version: Arc::new(AtomicUsize::new(0)), + algorithm: Arc::new(algorithm), + justification_sync_link: Arc::new(justification_sync_link), + build: Arc::new(Mutex::new(None)), + block_import: Arc::new(Mutex::new(block_import)), + } } - pub(crate) fn on_build(&mut self, build: MiningBuild) { - self.build = Some(build); + pub(crate) fn on_major_syncing(&self) { + let mut build = self.build.lock(); + *build = None; + self.increment_version(); + } + + pub(crate) fn on_build(&self, value: MiningBuild) { + let mut build = self.build.lock(); + *build = Some(value); + self.increment_version(); + } + + /// Get the version of the mining worker. + /// + /// This returns type `Version` which can only compare equality. If `Version` is unchanged, then + /// it can be certain that `best_hash` and `metadata` were not changed. + pub fn version(&self) -> Version { + Version(self.version.load(Ordering::SeqCst)) + } + + /// Get the current best hash. `None` if the worker has just started or the client is doing + /// major syncing. + pub fn best_hash(&self) -> Option { + self.build.lock().as_ref().map(|b| b.metadata.best_hash) } /// Get a copy of the current mining metadata, if available. pub fn metadata(&self) -> Option> { - self.build.as_ref().map(|b| b.metadata.clone()) + self.build.lock().as_ref().map(|b| b.metadata.clone()) } /// Submit a mined seal. The seal will be validated again. Returns true if the submission is /// successful. - pub async fn submit(&mut self, seal: Seal) -> bool { - if let Some(build) = self.build.take() { + pub async fn submit(&self, seal: Seal) -> bool { + if let Some(metadata) = self.metadata() { match self.algorithm.verify( - &BlockId::Hash(build.metadata.best_hash), - &build.metadata.pre_hash, - build.metadata.pre_runtime.as_ref().map(|v| &v[..]), + &BlockId::Hash(metadata.best_hash), + &metadata.pre_hash, + metadata.pre_runtime.as_ref().map(|v| &v[..]), &seal, - build.metadata.difficulty, + metadata.difficulty, ) { Ok(true) => (), Ok(false) => { @@ -130,55 +175,92 @@ where return false }, } + } else { + warn!( + target: "pow", + "Unable to import mined block: metadata does not exist", + ); + return false + } - let seal = DigestItem::Seal(POW_ENGINE_ID, seal); - let (header, body) = build.proposal.block.deconstruct(); - - let mut import_block = BlockImportParams::new(BlockOrigin::Own, header); - import_block.post_digests.push(seal); - import_block.body = Some(body); - import_block.state_action = - StateAction::ApplyChanges(StorageChanges::Changes(build.proposal.storage_changes)); - - let intermediate = PowIntermediate:: { - difficulty: Some(build.metadata.difficulty), - }; - - import_block - .intermediates - .insert(Cow::from(INTERMEDIATE_KEY), Box::new(intermediate) as Box<_>); - - let header = import_block.post_header(); - match self.block_import.import_block(import_block, HashMap::default()).await { - Ok(res) => { - res.handle_justification( - &header.hash(), - *header.number(), - &mut self.justification_sync_link, - ); - - info!( - target: "pow", - "✅ Successfully mined block on top of: {}", - build.metadata.best_hash - ); - true - }, - Err(err) => { - warn!( - target: "pow", - "Unable to import mined block: {:?}", - err, - ); - false - }, + let build = if let Some(build) = { + let mut build = self.build.lock(); + let value = build.take(); + if value.is_some() { + self.increment_version(); } + value + } { + build } else { warn!( target: "pow", "Unable to import mined block: build does not exist", ); - false + return false + }; + + let seal = DigestItem::Seal(POW_ENGINE_ID, seal); + let (header, body) = build.proposal.block.deconstruct(); + + let mut import_block = BlockImportParams::new(BlockOrigin::Own, header); + import_block.post_digests.push(seal); + import_block.body = Some(body); + import_block.state_action = + StateAction::ApplyChanges(StorageChanges::Changes(build.proposal.storage_changes)); + + let intermediate = PowIntermediate:: { + difficulty: Some(build.metadata.difficulty), + }; + + import_block + .intermediates + .insert(Cow::from(INTERMEDIATE_KEY), Box::new(intermediate) as Box<_>); + + let header = import_block.post_header(); + let mut block_import = self.block_import.lock(); + + match block_import.import_block(import_block, HashMap::default()).await { + Ok(res) => { + res.handle_justification( + &header.hash(), + *header.number(), + &self.justification_sync_link, + ); + + info!( + target: "pow", + "✅ Successfully mined block on top of: {}", + build.metadata.best_hash + ); + true + }, + Err(err) => { + warn!( + target: "pow", + "Unable to import mined block: {:?}", + err, + ); + false + }, + } + } +} + +impl Clone for MiningHandle +where + Block: BlockT, + Algorithm: PowAlgorithm, + C: sp_api::ProvideRuntimeApi, + L: sc_consensus::JustificationSyncLink, +{ + fn clone(&self) -> Self { + Self { + version: self.version.clone(), + algorithm: self.algorithm.clone(), + justification_sync_link: self.justification_sync_link.clone(), + build: self.build.clone(), + block_import: self.block_import.clone(), } } } From 1403b3793fa48f68fb81aef11fb2b4500aa096db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Tue, 12 Oct 2021 06:12:29 +0200 Subject: [PATCH 070/695] node-template: Do not provide benchmarking host functions by default (#10005) --- bin/node-template/node/src/service.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/bin/node-template/node/src/service.rs b/bin/node-template/node/src/service.rs index a70dd877ff35..2286ad3bd654 100644 --- a/bin/node-template/node/src/service.rs +++ b/bin/node-template/node/src/service.rs @@ -16,7 +16,12 @@ use std::{sync::Arc, time::Duration}; pub struct ExecutorDispatch; impl sc_executor::NativeExecutionDispatch for ExecutorDispatch { + /// Only enable the benchmarking host functions when we actually want to benchmark. + #[cfg(feature = "runtime-benchmarks")] type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions; + /// Otherwise we only use the default Substrate host functions. + #[cfg(not(feature = "runtime-benchmarks"))] + type ExtendHostFunctions = (); fn dispatch(method: &str, data: &[u8]) -> Option> { node_template_runtime::api::dispatch(method, data) From cafe12e7785bf92e5dc04780c10e7f8330a15a4c Mon Sep 17 00:00:00 2001 From: Squirrel Date: Tue, 12 Oct 2021 09:54:40 +0100 Subject: [PATCH 071/695] Switch to using ss58-registry crate (#9755) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Switch to using ss58-registry crate * Custom(42) is now eq to Substrate Co-authored-by: Bastian Köcher Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> --- Cargo.lock | 15 + client/cli/src/commands/utils.rs | 11 +- client/cli/src/commands/vanity.rs | 20 +- primitives/core/Cargo.toml | 2 +- primitives/core/src/crypto.rs | 305 ++---------------- primitives/core/src/ecdsa.rs | 17 +- .../frame-utilities-cli/src/pallet_id.rs | 4 +- 7 files changed, 72 insertions(+), 302 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 74c0cfe68df6..7fdb4cf6fe19 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9269,6 +9269,7 @@ dependencies = [ "sp-serializer", "sp-std", "sp-storage", + "ss58-registry", "substrate-bip39", "thiserror", "tiny-bip39", @@ -9783,6 +9784,20 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "ss58-registry" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef2413ecc7946ca99368862851dc1359f1477bc654ecfb135cf3efcb85ceca5f" +dependencies = [ + "Inflector", + "proc-macro2", + "quote", + "serde", + "serde_json", + "unicode-xid", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" diff --git a/client/cli/src/commands/utils.rs b/client/cli/src/commands/utils.rs index 864d7e920f81..39e5149404b2 100644 --- a/client/cli/src/commands/utils.rs +++ b/client/cli/src/commands/utils.rs @@ -23,7 +23,10 @@ use crate::{ }; use serde_json::json; use sp_core::{ - crypto::{ExposeSecret, SecretString, Ss58AddressFormat, Ss58Codec, Zeroize}, + crypto::{ + unwrap_or_default_ss58_version, ExposeSecret, SecretString, Ss58AddressFormat, Ss58Codec, + Zeroize, + }, hexdisplay::HexDisplay, Pair, }; @@ -72,7 +75,7 @@ pub fn print_from_uri( let password = password.as_ref().map(|s| s.expose_secret().as_str()); if let Ok((pair, seed)) = Pair::from_phrase(uri, password.clone()) { let public_key = pair.public(); - let network_override = network_override.unwrap_or_default(); + let network_override = unwrap_or_default_ss58_version(network_override); match output { OutputType::Json => { @@ -108,7 +111,7 @@ pub fn print_from_uri( } } else if let Ok((pair, seed)) = Pair::from_string_with_seed(uri, password.clone()) { let public_key = pair.public(); - let network_override = network_override.unwrap_or_default(); + let network_override = unwrap_or_default_ss58_version(network_override); match output { OutputType::Json => { @@ -198,7 +201,7 @@ where let public_key = Pair::Public::try_from(&public) .map_err(|_| "Failed to construct public key from given hex")?; - let network_override = network_override.unwrap_or_default(); + let network_override = unwrap_or_default_ss58_version(network_override); match output { OutputType::Json => { diff --git a/client/cli/src/commands/vanity.rs b/client/cli/src/commands/vanity.rs index daeb81e86a1a..d2953c839607 100644 --- a/client/cli/src/commands/vanity.rs +++ b/client/cli/src/commands/vanity.rs @@ -22,7 +22,7 @@ use crate::{ error, utils, with_crypto_scheme, CryptoSchemeFlag, NetworkSchemeFlag, OutputTypeFlag, }; use rand::{rngs::OsRng, RngCore}; -use sp_core::crypto::{Ss58AddressFormat, Ss58Codec}; +use sp_core::crypto::{unwrap_or_default_ss58_version, Ss58AddressFormat, Ss58Codec}; use sp_runtime::traits::IdentifyAccount; use structopt::StructOpt; use utils::print_from_uri; @@ -53,7 +53,10 @@ impl VanityCmd { pub fn run(&self) -> error::Result<()> { let formated_seed = with_crypto_scheme!( self.crypto_scheme.scheme, - generate_key(&self.pattern, self.network_scheme.network.clone().unwrap_or_default()), + generate_key( + &self.pattern, + unwrap_or_default_ss58_version(self.network_scheme.network) + ), )?; with_crypto_scheme!( @@ -159,7 +162,10 @@ fn assert_non_empty_string(pattern: &str) -> Result { #[cfg(test)] mod tests { use super::*; - use sp_core::{crypto::Ss58Codec, sr25519, Pair}; + use sp_core::{ + crypto::{default_ss58_version, Ss58AddressFormatRegistry, Ss58Codec}, + sr25519, Pair, + }; use structopt::StructOpt; #[cfg(feature = "bench")] use test::Bencher; @@ -172,7 +178,7 @@ mod tests { #[test] fn test_generation_with_single_char() { - let seed = generate_key::("ab", Default::default()).unwrap(); + let seed = generate_key::("ab", default_ss58_version()).unwrap(); assert!(sr25519::Pair::from_seed_slice(&hex::decode(&seed[2..]).unwrap()) .unwrap() .public() @@ -182,11 +188,13 @@ mod tests { #[test] fn generate_key_respects_network_override() { - let seed = generate_key::("ab", Ss58AddressFormat::PolkadotAccount).unwrap(); + let seed = + generate_key::("ab", Ss58AddressFormatRegistry::PolkadotAccount.into()) + .unwrap(); assert!(sr25519::Pair::from_seed_slice(&hex::decode(&seed[2..]).unwrap()) .unwrap() .public() - .to_ss58check_with_version(Ss58AddressFormat::PolkadotAccount) + .to_ss58check_with_version(Ss58AddressFormatRegistry::PolkadotAccount.into()) .contains("ab")); } diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index 31223ff1ccf7..f063b65c97e0 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -66,7 +66,7 @@ hex = { version = "0.4", default-features = false, optional = true } twox-hash = { version = "1.6.1", default-features = false, optional = true } libsecp256k1 = { version = "0.6", default-features = false, features = ["hmac", "static-context"], optional = true } merlin = { version = "2.0", default-features = false, optional = true } - +ss58-registry = "1.0.0" sp-runtime-interface = { version = "4.0.0-dev", default-features = false, path = "../runtime-interface" } [dev-dependencies] diff --git a/primitives/core/src/crypto.rs b/primitives/core/src/crypto.rs index a9f3e904a2a8..21b8520c7780 100644 --- a/primitives/core/src/crypto.rs +++ b/primitives/core/src/crypto.rs @@ -26,8 +26,6 @@ use crate::{ed25519, sr25519}; use base58::{FromBase58, ToBase58}; use codec::{Decode, Encode, MaxEncodedLen}; #[cfg(feature = "std")] -use parking_lot::Mutex; -#[cfg(feature = "std")] use rand::{rngs::OsRng, RngCore}; #[cfg(feature = "std")] use regex::Regex; @@ -38,14 +36,15 @@ pub use secrecy::ExposeSecret; #[cfg(feature = "std")] pub use secrecy::SecretString; use sp_runtime_interface::pass_by::PassByInner; -#[cfg(feature = "std")] -use sp_std::convert::TryInto; #[doc(hidden)] pub use sp_std::ops::Deref; use sp_std::{convert::TryFrom, hash::Hash, str, vec::Vec}; /// Trait to zeroize a memory buffer. pub use zeroize::Zeroize; +#[cfg(feature = "full_crypto")] +pub use ss58_registry::{from_known_address_format, Ss58AddressFormat, Ss58AddressFormatRegistry}; + /// The root phrase for our publicly known keys. pub const DEV_PHRASE: &str = "bottom drive obey lake curtain smoke basket hold race lonely fit walk"; @@ -227,7 +226,7 @@ pub trait Ss58Codec: Sized + AsMut<[u8]> + AsRef<[u8]> + Default { /// A format filterer, can be used to ensure that `from_ss58check` family only decode for /// allowed identifiers. By default just refuses the two reserved identifiers. fn format_is_allowed(f: Ss58AddressFormat) -> bool { - !matches!(f, Ss58AddressFormat::Reserved46 | Ss58AddressFormat::Reserved47) + !f.is_reserved() } /// Some if the string is a properly encoded SS58Check address. @@ -235,7 +234,7 @@ pub trait Ss58Codec: Sized + AsMut<[u8]> + AsRef<[u8]> + Default { fn from_ss58check(s: &str) -> Result { Self::from_ss58check_with_version(s).and_then(|(r, v)| match v { v if !v.is_custom() => Ok(r), - v if v == *DEFAULT_VERSION.lock() => Ok(r), + v if v == default_ss58_version() => Ok(r), _ => Err(PublicError::UnknownVersion), }) } @@ -270,7 +269,7 @@ pub trait Ss58Codec: Sized + AsMut<[u8]> + AsRef<[u8]> + Default { if data.len() != prefix_len + body_len + CHECKSUM_LEN { return Err(PublicError::BadLength) } - let format = ident.try_into().map_err(|_: ()| PublicError::UnknownVersion)?; + let format = ident.into(); if !Self::format_is_allowed(format) { return Err(PublicError::FormatNotAllowed) } @@ -291,7 +290,7 @@ pub trait Ss58Codec: Sized + AsMut<[u8]> + AsRef<[u8]> + Default { fn from_string(s: &str) -> Result { Self::from_string_with_version(s).and_then(|(r, v)| match v { v if !v.is_custom() => Ok(r), - v if v == *DEFAULT_VERSION.lock() => Ok(r), + v if v == default_ss58_version() => Ok(r), _ => Err(PublicError::UnknownVersion), }) } @@ -322,7 +321,7 @@ pub trait Ss58Codec: Sized + AsMut<[u8]> + AsRef<[u8]> + Default { /// Return the ss58-check string for this key. #[cfg(feature = "std")] fn to_ss58check(&self) -> String { - self.to_ss58check_with_version(*DEFAULT_VERSION.lock()) + self.to_ss58check_with_version(default_ss58_version()) } /// Some if the string is a properly encoded SS58Check address, optionally with @@ -355,286 +354,30 @@ fn ss58hash(data: &[u8]) -> blake2_rfc::blake2b::Blake2bResult { context.finalize() } +/// Default prefix number #[cfg(feature = "std")] -lazy_static::lazy_static! { - static ref DEFAULT_VERSION: Mutex - = Mutex::new(Ss58AddressFormat::SubstrateAccount); -} - -#[cfg(feature = "full_crypto")] -macro_rules! ss58_address_format { - ( $( $identifier:tt => ($number:expr, $name:expr, $desc:tt) )* ) => ( - /// A known address (sub)format/network ID for SS58. - #[derive(Copy, Clone, PartialEq, Eq, crate::RuntimeDebug)] - pub enum Ss58AddressFormat { - $(#[doc = $desc] $identifier),*, - /// Use a manually provided numeric value as a standard identifier - Custom(u16), - } - - #[cfg(feature = "std")] - impl std::fmt::Display for Ss58AddressFormat { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - match self { - $( - Ss58AddressFormat::$identifier => write!(f, "{}", $name), - )* - Ss58AddressFormat::Custom(x) => write!(f, "{}", x), - } - - } - } - - static ALL_SS58_ADDRESS_FORMATS: [Ss58AddressFormat; 0 $(+ { let _ = $number; 1})*] = [ - $(Ss58AddressFormat::$identifier),*, - ]; - - impl Ss58AddressFormat { - /// names of all address formats - pub fn all_names() -> &'static [&'static str] { - &[ - $($name),*, - ] - } - /// All known address formats. - pub fn all() -> &'static [Ss58AddressFormat] { - &ALL_SS58_ADDRESS_FORMATS - } - - /// Whether the address is custom. - pub fn is_custom(&self) -> bool { - matches!(self, Self::Custom(_)) - } - } - - impl TryFrom for Ss58AddressFormat { - type Error = (); - - fn try_from(x: u8) -> Result { - Ss58AddressFormat::try_from(x as u16) - } - } - - impl From for u16 { - fn from(x: Ss58AddressFormat) -> u16 { - match x { - $(Ss58AddressFormat::$identifier => $number),*, - Ss58AddressFormat::Custom(n) => n, - } - } - } - - impl TryFrom for Ss58AddressFormat { - type Error = (); - - fn try_from(x: u16) -> Result { - match x { - $($number => Ok(Ss58AddressFormat::$identifier)),*, - _ => Ok(Ss58AddressFormat::Custom(x)), - } - } - } - - /// Error encountered while parsing `Ss58AddressFormat` from &'_ str - /// unit struct for now. - #[derive(Copy, Clone, PartialEq, Eq, crate::RuntimeDebug)] - pub struct ParseError; - - impl<'a> TryFrom<&'a str> for Ss58AddressFormat { - type Error = ParseError; - - fn try_from(x: &'a str) -> Result { - match x { - $($name => Ok(Ss58AddressFormat::$identifier)),*, - a => a.parse::().map(Ss58AddressFormat::Custom).map_err(|_| ParseError), - } - } - } - - #[cfg(feature = "std")] - impl std::str::FromStr for Ss58AddressFormat { - type Err = ParseError; - - fn from_str(data: &str) -> Result { - Self::try_from(data) - } - } - - #[cfg(feature = "std")] - impl std::fmt::Display for ParseError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "failed to parse network value as u8") - } - } - - #[cfg(feature = "std")] - impl Default for Ss58AddressFormat { - fn default() -> Self { - *DEFAULT_VERSION.lock() - } - } +static DEFAULT_VERSION: core::sync::atomic::AtomicU16 = std::sync::atomic::AtomicU16::new( + from_known_address_format(Ss58AddressFormatRegistry::SubstrateAccount), +); - #[cfg(feature = "std")] - impl From for String { - fn from(x: Ss58AddressFormat) -> String { - x.to_string() - } - } - ) +/// Returns default ss58 format used by the current active process. +#[cfg(feature = "std")] +pub fn default_ss58_version() -> Ss58AddressFormat { + DEFAULT_VERSION.load(std::sync::atomic::Ordering::Relaxed).into() } -#[cfg(feature = "full_crypto")] -ss58_address_format!( - PolkadotAccount => - (0, "polkadot", "Polkadot Relay-chain, standard account (*25519).") - BareSr25519 => - (1, "sr25519", "Bare 32-bit Schnorr/Ristretto 25519 (S/R 25519) key.") - KusamaAccount => - (2, "kusama", "Kusama Relay-chain, standard account (*25519).") - BareEd25519 => - (3, "ed25519", "Bare 32-bit Edwards Ed25519 key.") - KatalChainAccount => - (4, "katalchain", "Katal Chain, standard account (*25519).") - PlasmAccount => - (5, "plasm", "Plasm Network, standard account (*25519).") - BifrostAccount => - (6, "bifrost", "Bifrost mainnet, direct checksum, standard account (*25519).") - EdgewareAccount => - (7, "edgeware", "Edgeware mainnet, standard account (*25519).") - KaruraAccount => - (8, "karura", "Acala Karura canary network, standard account (*25519).") - ReynoldsAccount => - (9, "reynolds", "Laminar Reynolds canary network, standard account (*25519).") - AcalaAccount => - (10, "acala", "Acala mainnet, standard account (*25519).") - LaminarAccount => - (11, "laminar", "Laminar mainnet, standard account (*25519).") - PolymathAccount => - (12, "polymath", "Polymath network, standard account (*25519).") - SubstraTeeAccount => - (13, "substratee", "Any SubstraTEE off-chain network private account (*25519).") - TotemAccount => - (14, "totem", "Any Totem Live Accounting network standard account (*25519).") - SynesthesiaAccount => - (15, "synesthesia", "Synesthesia mainnet, standard account (*25519).") - KulupuAccount => - (16, "kulupu", "Kulupu mainnet, standard account (*25519).") - DarkAccount => - (17, "dark", "Dark mainnet, standard account (*25519).") - DarwiniaAccount => - (18, "darwinia", "Darwinia Chain mainnet, standard account (*25519).") - GeekAccount => - (19, "geek", "GeekCash mainnet, standard account (*25519).") - StafiAccount => - (20, "stafi", "Stafi mainnet, standard account (*25519).") - DockTestAccount => - (21, "dock-testnet", "Dock testnet, standard account (*25519).") - DockMainAccount => - (22, "dock-mainnet", "Dock mainnet, standard account (*25519).") - ShiftNrg => - (23, "shift", "ShiftNrg mainnet, standard account (*25519).") - ZeroAccount => - (24, "zero", "ZERO mainnet, standard account (*25519).") - AlphavilleAccount => - (25, "alphaville", "ZERO testnet, standard account (*25519).") - JupiterAccount => - (26, "jupiter", "Jupiter testnet, standard account (*25519).") - SubsocialAccount => - (28, "subsocial", "Subsocial network, standard account (*25519).") - DhiwayAccount => - (29, "cord", "Dhiway CORD network, standard account (*25519).") - PhalaAccount => - (30, "phala", "Phala Network, standard account (*25519).") - LitentryAccount => - (31, "litentry", "Litentry Network, standard account (*25519).") - RobonomicsAccount => - (32, "robonomics", "Any Robonomics network standard account (*25519).") - DataHighwayAccount => - (33, "datahighway", "DataHighway mainnet, standard account (*25519).") - AresAccount => - (34, "ares", "Ares Protocol, standard account (*25519).") - ValiuAccount => - (35, "vln", "Valiu Liquidity Network mainnet, standard account (*25519).") - CentrifugeAccount => - (36, "centrifuge", "Centrifuge Chain mainnet, standard account (*25519).") - NodleAccount => - (37, "nodle", "Nodle Chain mainnet, standard account (*25519).") - KiltAccount => - (38, "kilt", "KILT Chain mainnet, standard account (*25519).") - PolimecAccount => - (41, "poli", "Polimec Chain mainnet, standard account (*25519).") - SubstrateAccount => - (42, "substrate", "Any Substrate network, standard account (*25519).") - BareSecp256k1 => - (43, "secp256k1", "Bare ECDSA SECP256k1 key.") - ChainXAccount => - (44, "chainx", "ChainX mainnet, standard account (*25519).") - UniartsAccount => - (45, "uniarts", "UniArts Chain mainnet, standard account (*25519).") - Reserved46 => - (46, "reserved46", "Reserved for future use (46).") - Reserved47 => - (47, "reserved47", "Reserved for future use (47).") - NeatcoinAccount => - (48, "neatcoin", "Neatcoin mainnet, standard account (*25519).") - PicassoAccount => - (49, "picasso", "Composable Canary Network, standard account (*25519).") - ComposableAccount => - (50, "composable", "Composable mainnet, standard account (*25519).") - HydraDXAccount => - (63, "hydradx", "HydraDX standard account (*25519).") - AventusAccount => - (65, "aventus", "Aventus Chain mainnet, standard account (*25519).") - CrustAccount => - (66, "crust", "Crust Network, standard account (*25519).") - EquilibriumAccount => - (67, "equilibrium", "Equilibrium Network, standard account (*25519).") - SoraAccount => - (69, "sora", "SORA Network, standard account (*25519).") - ZeitgeistAccount => - (73, "zeitgeist", "Zeitgeist network, standard account (*25519).") - MantaAccount => - (77, "manta", "Manta Network, standard account (*25519).") - CalamariAccount => - (78, "calamari", "Manta Canary Network, standard account (*25519).") - Polkadex => - (88, "polkadex", "Polkadex Mainnet, standard account (*25519).") - PolkaSmith => - (98, "polkasmith", "PolkaSmith Canary Network, standard account (*25519).") - PolkaFoundry => - (99, "polkafoundry", "PolkaFoundry Network, standard account (*25519).") - OriginTrailAccount => - (101, "origintrail-parachain", "OriginTrail Parachain, ethereumm account (ECDSA).") - HeikoAccount => - (110, "heiko", "Heiko, session key (*25519).") - CloverAccount => - (128, "clover", "Clover Finance, standard account (*25519).") - ParallelAccount => - (172, "parallel", "Parallel, session key (*25519).") - SocialAccount => - (252, "social-network", "Social Network, standard account (*25519).") - Moonbeam => - (1284, "moonbeam", "Moonbeam, session key (*25519).") - Moonriver => - (1285, "moonriver", "Moonriver, session key (*25519).") - Automata => - (2349, "automata", "Automata mainnet standard account (*25519).") - BasiliskAccount => - (10041, "basilisk", "Basilisk standard account (*25519).") - ContextFree => - (11820, "contextfree", "Automata ContextFree standard account (*25519).") - - // Note: 16384 and above are reserved. -); +/// Returns either the input address format or the default. +#[cfg(feature = "std")] +pub fn unwrap_or_default_ss58_version(network: Option) -> Ss58AddressFormat { + network.unwrap_or_else(default_ss58_version) +} /// Set the default "version" (actually, this is a bit of a misnomer and the version byte is /// typically used not just to encode format/version but also network identity) that is used for -/// encoding and decoding SS58 addresses. If an unknown version is provided then it fails. -/// -/// See `ss58_address_format!` for all current known "versions". +/// encoding and decoding SS58 addresses. #[cfg(feature = "std")] -pub fn set_default_ss58_version(version: Ss58AddressFormat) { - *DEFAULT_VERSION.lock() = version +pub fn set_default_ss58_version(new_default: Ss58AddressFormat) { + DEFAULT_VERSION.store(new_default.into(), std::sync::atomic::Ordering::Relaxed); } #[cfg(feature = "std")] diff --git a/primitives/core/src/ecdsa.rs b/primitives/core/src/ecdsa.rs index 11e9b9d71d80..2751a0c40e3e 100644 --- a/primitives/core/src/ecdsa.rs +++ b/primitives/core/src/ecdsa.rs @@ -640,7 +640,10 @@ impl CryptoType for Pair { mod test { use super::*; use crate::{ - crypto::{set_default_ss58_version, PublicError, DEV_PHRASE}, + crypto::{ + set_default_ss58_version, PublicError, Ss58AddressFormat, Ss58AddressFormatRegistry, + DEV_PHRASE, + }, keccak_256, }; use hex_literal::hex; @@ -772,26 +775,24 @@ mod test { #[test] fn ss58check_format_check_works() { - use crate::crypto::Ss58AddressFormat; let pair = Pair::from_seed(b"12345678901234567890123456789012"); let public = pair.public(); - let format = Ss58AddressFormat::Reserved46; + let format = Ss58AddressFormatRegistry::Reserved46Account.into(); let s = public.to_ss58check_with_version(format); assert_eq!(Public::from_ss58check_with_version(&s), Err(PublicError::FormatNotAllowed)); } #[test] fn ss58check_full_roundtrip_works() { - use crate::crypto::Ss58AddressFormat; let pair = Pair::from_seed(b"12345678901234567890123456789012"); let public = pair.public(); - let format = Ss58AddressFormat::PolkadotAccount; + let format = Ss58AddressFormatRegistry::PolkadotAccount.into(); let s = public.to_ss58check_with_version(format); let (k, f) = Public::from_ss58check_with_version(&s).unwrap(); assert_eq!(k, public); assert_eq!(f, format); - let format = Ss58AddressFormat::Custom(64); + let format = Ss58AddressFormat::custom(64); let s = public.to_ss58check_with_version(format); let (k, f) = Public::from_ss58check_with_version(&s).unwrap(); assert_eq!(k, public); @@ -805,10 +806,10 @@ mod test { if std::env::var("RUN_CUSTOM_FORMAT_TEST") == Ok("1".into()) { use crate::crypto::Ss58AddressFormat; // temp save default format version - let default_format = Ss58AddressFormat::default(); + let default_format = crate::crypto::default_ss58_version(); // set current ss58 version is custom "200" `Ss58AddressFormat::Custom(200)` - set_default_ss58_version(Ss58AddressFormat::Custom(200)); + set_default_ss58_version(Ss58AddressFormat::custom(200)); // custom addr encoded by version 200 let addr = "4pbsSkWcBaYoFHrKJZp5fDVUKbqSYD9dhZZGvpp3vQ5ysVs5ybV"; Public::from_ss58check(&addr).unwrap(); diff --git a/utils/frame/frame-utilities-cli/src/pallet_id.rs b/utils/frame/frame-utilities-cli/src/pallet_id.rs index 2caac7db588a..d173f52b39cd 100644 --- a/utils/frame/frame-utilities-cli/src/pallet_id.rs +++ b/utils/frame/frame-utilities-cli/src/pallet_id.rs @@ -22,7 +22,7 @@ use sc_cli::{ utils::print_from_uri, with_crypto_scheme, CryptoSchemeFlag, Error, KeystoreParams, OutputTypeFlag, }; -use sp_core::crypto::{Ss58AddressFormat, Ss58Codec}; +use sp_core::crypto::{unwrap_or_default_ss58_version, Ss58AddressFormat, Ss58Codec}; use sp_runtime::traits::AccountIdConversion; use std::convert::{TryFrom, TryInto}; use structopt::StructOpt; @@ -78,7 +78,7 @@ impl PalletIdCmd { with_crypto_scheme!( self.crypto_scheme.scheme, print_from_uri( - &account_id.to_ss58check_with_version(self.network.clone().unwrap_or_default()), + &account_id.to_ss58check_with_version(unwrap_or_default_ss58_version(self.network)), password, self.network, self.output_scheme.output_type.clone() From 98ef7691c37e2638c8ca93586d14d2b102d4e43d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Tue, 12 Oct 2021 12:33:43 +0200 Subject: [PATCH 072/695] sp-debug-derive: Add `force-debug` feature (#9996) * sp-debug-derive: Add `force-debug` feature Sometimes users want to have proper debug information even inside the wasm runtime, when they use `RuntimeDebug`. To not fork Substrate to change a type to a normal `Debug` derive, this pr introduces the `force-debug` feature. This feature can be enabled by the user in their runtime and then the types will use the normal Debug derive instead of printing `wasm:stripped`. * Fixes --- primitives/core/Cargo.toml | 2 +- primitives/debug-derive/Cargo.toml | 6 ++++++ primitives/debug-derive/src/impls.rs | 4 ++-- primitives/storage/Cargo.toml | 4 ++-- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index f063b65c97e0..631bf3fc122e 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -40,7 +40,7 @@ zeroize = { version = "1.4.2", default-features = false } secrecy = { version = "0.8.0", default-features = false } lazy_static = { version = "1.4.0", default-features = false, optional = true } parking_lot = { version = "0.11.1", optional = true } -sp-debug-derive = { version = "3.0.0", path = "../debug-derive" } +sp-debug-derive = { version = "3.0.0", default-features = false, path = "../debug-derive" } sp-externalities = { version = "0.10.0-dev", optional = true, path = "../externalities" } sp-storage = { version = "4.0.0-dev", default-features = false, path = "../storage" } parity-util-mem = { version = "0.10.0", default-features = false, features = [ diff --git a/primitives/debug-derive/Cargo.toml b/primitives/debug-derive/Cargo.toml index 2e5ef93e41f5..ce49c54b46fb 100644 --- a/primitives/debug-derive/Cargo.toml +++ b/primitives/debug-derive/Cargo.toml @@ -22,6 +22,12 @@ syn = "1.0.80" proc-macro2 = "1.0" [features] +default = [ "std" ] std = [] +# By default `RuntimeDebug` implements `Debug` that outputs `` when `std` is +# disabled. However, sometimes downstream users need to have the real `Debug` implementation for +# debugging purposes. If this is required, a user only needs to add this crate as a dependency of +# their runtime and enable the `force-debug` feature. +force-debug = [] [dev-dependencies] diff --git a/primitives/debug-derive/src/impls.rs b/primitives/debug-derive/src/impls.rs index 4d79ee988016..0e67ef81bc85 100644 --- a/primitives/debug-derive/src/impls.rs +++ b/primitives/debug-derive/src/impls.rs @@ -43,7 +43,7 @@ pub fn debug_derive(ast: DeriveInput) -> proc_macro::TokenStream { gen.into() } -#[cfg(not(feature = "std"))] +#[cfg(all(not(feature = "std"), not(feature = "force-debug")))] mod implementation { use super::*; @@ -58,7 +58,7 @@ mod implementation { } } -#[cfg(feature = "std")] +#[cfg(any(feature = "std", feature = "force-debug"))] mod implementation { use super::*; use proc_macro2::Span; diff --git a/primitives/storage/Cargo.toml b/primitives/storage/Cargo.toml index 1a05fb996919..078e0fff12ef 100644 --- a/primitives/storage/Cargo.toml +++ b/primitives/storage/Cargo.toml @@ -18,9 +18,9 @@ sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" } serde = { version = "1.0.126", optional = true, features = ["derive"] } impl-serde = { version = "0.3.1", optional = true } ref-cast = "1.0.0" -sp-debug-derive = { version = "3.0.0", path = "../debug-derive" } +sp-debug-derive = { version = "3.0.0", default-features = false, path = "../debug-derive" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } [features] default = [ "std" ] -std = [ "sp-std/std", "serde", "impl-serde", "codec/std" ] +std = [ "sp-std/std", "serde", "impl-serde", "codec/std", "sp-debug-derive/std" ] From 508c5a746ae7eedd9170b213ca98e3ce857f5790 Mon Sep 17 00:00:00 2001 From: Squirrel Date: Tue, 12 Oct 2021 11:36:09 +0100 Subject: [PATCH 073/695] hint what to do if you didn't use bot merge (#10009) --- docs/CONTRIBUTING.adoc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/CONTRIBUTING.adoc b/docs/CONTRIBUTING.adoc index 103b318a169d..5b1920e775bb 100644 --- a/docs/CONTRIBUTING.adoc +++ b/docs/CONTRIBUTING.adoc @@ -85,10 +85,11 @@ To create a Polkadot companion PR: . Wait for reviews on both the Substrate and the Polkadot PRs. . Once the Substrate PR runs green, a member of the `parity` github group can comment on the Substrate PR with `bot merge` which will: - Merge the Substrate PR. - - The bot will push a commit to the Polkadot PR updating its Substrate reference. + - The bot will push a commit to the Polkadot PR updating its Substrate reference. (effecively doing `cargo update -p sp-io`) - If the polkadot PR origins from a fork then a project member may need to press `approve run` on the polkadot PR. - The bot will merge the Polkadot PR once all its CI `{"build_allow_failure":false}` checks are green. Note: The merge-bot currently doesn't work with forks on org accounts, only individual accounts. + (Hint: it's recommended to use `bot merge` to merge all substrate PRs, not just ones with a polkadot companion.) If your PR is reviewed well, but a Polkadot PR is missing, signal it with https://github.com/paritytech/substrate/labels/A7-needspolkadotpr[`A7-needspolkadotpr`] to prevent it from getting automatically merged. From f92e9780372b777b743d3a1dc50f4248b70abfb1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Oct 2021 12:15:12 +0100 Subject: [PATCH 074/695] Bump sha2 from 0.9.5 to 0.9.8 (#10008) Bumps [sha2](https://github.com/RustCrypto/hashes) from 0.9.5 to 0.9.8. - [Release notes](https://github.com/RustCrypto/hashes/releases) - [Commits](https://github.com/RustCrypto/hashes/compare/sha2-v0.9.5...sha2-v0.9.8) --- updated-dependencies: - dependency-name: sha2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 55 ++++++++++++++++++++++---------------- primitives/core/Cargo.toml | 2 +- 2 files changed, 33 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7fdb4cf6fe19..868ed2b46a77 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -44,7 +44,7 @@ checksum = "495ee669413bfbe9e8cace80f4d3d78e6d8c8d99579f97fb93bde351b185f2d4" dependencies = [ "cfg-if 1.0.0", "cipher", - "cpufeatures", + "cpufeatures 0.1.5", "opaque-debug 0.3.0", ] @@ -884,7 +884,7 @@ checksum = "fee7ad89dc1128635074c268ee661f90c3f7e83d9fd12910608c36b47d6c3412" dependencies = [ "cfg-if 1.0.0", "cipher", - "cpufeatures", + "cpufeatures 0.1.5", "zeroize", ] @@ -1042,6 +1042,15 @@ dependencies = [ "libc", ] +[[package]] +name = "cpufeatures" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469" +dependencies = [ + "libc", +] + [[package]] name = "cpuid-bool" version = "0.1.2" @@ -1666,7 +1675,7 @@ dependencies = [ "ed25519", "rand 0.7.3", "serde", - "sha2 0.9.5", + "sha2 0.9.8", "zeroize", ] @@ -3262,9 +3271,9 @@ checksum = "3576a87f2ba00f6f106fdfcd16db1d698d648a26ad8e0573cad8537c3c362d2a" [[package]] name = "libc" -version = "0.2.95" +version = "0.2.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "789da6d93f1b866ffe175afc5322a4d76c038605a1c3319bb57b06967ca98a36" +checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6" [[package]] name = "libgit2-sys" @@ -3379,7 +3388,7 @@ dependencies = [ "rand 0.7.3", "ring", "rw-stream-sink", - "sha2 0.9.5", + "sha2 0.9.8", "smallvec 1.7.0", "thiserror", "unsigned-varint 0.7.0", @@ -3450,7 +3459,7 @@ dependencies = [ "prost-build", "rand 0.7.3", "regex", - "sha2 0.9.5", + "sha2 0.9.8", "smallvec 1.7.0", "unsigned-varint 0.7.0", "wasm-timer", @@ -3490,7 +3499,7 @@ dependencies = [ "prost", "prost-build", "rand 0.7.3", - "sha2 0.9.5", + "sha2 0.9.8", "smallvec 1.7.0", "uint", "unsigned-varint 0.7.0", @@ -3552,7 +3561,7 @@ dependencies = [ "prost", "prost-build", "rand 0.8.4", - "sha2 0.9.5", + "sha2 0.9.8", "snow", "static_assertions", "x25519-dalek", @@ -3775,7 +3784,7 @@ dependencies = [ "libsecp256k1-gen-genmult 0.2.1", "rand 0.7.3", "serde", - "sha2 0.9.5", + "sha2 0.9.8", "typenum", ] @@ -3794,7 +3803,7 @@ dependencies = [ "libsecp256k1-gen-genmult 0.2.1", "rand 0.7.3", "serde", - "sha2 0.9.5", + "sha2 0.9.8", "typenum", ] @@ -3812,7 +3821,7 @@ dependencies = [ "libsecp256k1-gen-genmult 0.3.0", "rand 0.8.4", "serde", - "sha2 0.9.5", + "sha2 0.9.8", ] [[package]] @@ -4269,7 +4278,7 @@ dependencies = [ "digest 0.9.0", "generic-array 0.14.4", "multihash-derive", - "sha2 0.9.5", + "sha2 0.9.8", "sha3", "unsigned-varint 0.5.1", ] @@ -4283,7 +4292,7 @@ dependencies = [ "digest 0.9.0", "generic-array 0.14.4", "multihash-derive", - "sha2 0.9.5", + "sha2 0.9.8", "unsigned-varint 0.7.0", ] @@ -6547,7 +6556,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fcffab1f78ebbdf4b93b68c1ffebc24037eedf271edaca795732b24e5e4e349" dependencies = [ - "cpufeatures", + "cpufeatures 0.1.5", "opaque-debug 0.3.0", "universal-hash", ] @@ -6559,7 +6568,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6ba6a405ef63530d6cb12802014b22f9c5751bd17cdcddbe9e46d5c8ae83287" dependencies = [ "cfg-if 1.0.0", - "cpufeatures", + "cpufeatures 0.1.5", "opaque-debug 0.3.0", "universal-hash", ] @@ -8817,13 +8826,13 @@ dependencies = [ [[package]] name = "sha2" -version = "0.9.5" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b362ae5752fd2137731f9fa25fd4d9058af34666ca1966fb969119cc35719f12" +checksum = "b69f9a4c9740d74c5baa3fd2e547f9525fa8088a8a958e0ca2409a514e33f5fa" dependencies = [ "block-buffer 0.9.0", "cfg-if 1.0.0", - "cpufeatures", + "cpufeatures 0.2.1", "digest 0.9.0", "opaque-debug 0.3.0", ] @@ -8932,7 +8941,7 @@ dependencies = [ "rand_core 0.6.2", "ring", "rustc_version 0.3.3", - "sha2 0.9.5", + "sha2 0.9.8", "subtle 2.4.0", "x25519-dalek", ] @@ -9262,7 +9271,7 @@ dependencies = [ "secrecy", "serde", "serde_json", - "sha2 0.9.5", + "sha2 0.9.8", "sp-debug-derive", "sp-externalities", "sp-runtime-interface", @@ -10367,7 +10376,7 @@ dependencies = [ "pbkdf2 0.4.0", "rand 0.7.3", "rustc-hash", - "sha2 0.9.5", + "sha2 0.9.8", "thiserror", "unicode-normalization", "wasm-bindgen", @@ -11445,7 +11454,7 @@ dependencies = [ "libc", "log 0.4.14", "serde", - "sha2 0.9.5", + "sha2 0.9.8", "toml", "winapi 0.3.9", "zstd", diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index 631bf3fc122e..0944fbef2334 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -61,7 +61,7 @@ schnorrkel = { version = "0.9.1", features = [ "preaudit_deprecated", "u64_backend", ], default-features = false, optional = true } -sha2 = { version = "0.9.5", default-features = false, optional = true } +sha2 = { version = "0.9.8", default-features = false, optional = true } hex = { version = "0.4", default-features = false, optional = true } twox-hash = { version = "1.6.1", default-features = false, optional = true } libsecp256k1 = { version = "0.6", default-features = false, features = ["hmac", "static-context"], optional = true } From 66f0008af39054d1457ad7eac78a47efa6bc39a3 Mon Sep 17 00:00:00 2001 From: Chris Sosnin <48099298+slumber@users.noreply.github.com> Date: Tue, 12 Oct 2021 18:15:23 +0300 Subject: [PATCH 075/695] sc-executor-wasmtime: upgrade wasmtime to 0.30.0 (#10003) * sc-executor-wasmtime: upgrade wasmtime to 0.30.0 Changes related to memory64 proposal implementation, for additional details see bytecodealliance/wasmtime#3153 * sc-executor-wasmtime: introduce parallel_compilation flag * typos --- Cargo.lock | 212 +++++++----------- client/executor/src/wasm_runtime.rs | 5 +- client/executor/wasmtime/Cargo.toml | 3 +- client/executor/wasmtime/src/imports.rs | 35 ++- .../executor/wasmtime/src/instance_wrapper.rs | 2 +- client/executor/wasmtime/src/runtime.rs | 36 +-- client/executor/wasmtime/src/tests.rs | 29 +-- 7 files changed, 145 insertions(+), 177 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 868ed2b46a77..d9f733958874 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1068,11 +1068,11 @@ dependencies = [ [[package]] name = "cranelift-bforest" -version = "0.76.0" +version = "0.77.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e6bea67967505247f54fa2c85cf4f6e0e31c4e5692c9b70e4ae58e339067333" +checksum = "15013642ddda44eebcf61365b2052a23fd8b7314f90ba44aa059ec02643c5139" dependencies = [ - "cranelift-entity 0.76.0", + "cranelift-entity 0.77.0", ] [[package]] @@ -1096,18 +1096,17 @@ dependencies = [ [[package]] name = "cranelift-codegen" -version = "0.76.0" +version = "0.77.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48194035d2752bdd5bdae429e3ab88676e95f52a2b1355a5d4e809f9e39b1d74" +checksum = "298f2a7ed5fdcb062d8e78b7496b0f4b95265d20245f2d0ca88f846dd192a3a3" dependencies = [ - "cranelift-bforest 0.76.0", - "cranelift-codegen-meta 0.76.0", - "cranelift-codegen-shared 0.76.0", - "cranelift-entity 0.76.0", + "cranelift-bforest 0.77.0", + "cranelift-codegen-meta 0.77.0", + "cranelift-codegen-shared 0.77.0", + "cranelift-entity 0.77.0", "gimli 0.25.0", "log 0.4.14", "regalloc", - "serde", "smallvec 1.7.0", "target-lexicon 0.12.0", ] @@ -1124,12 +1123,12 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.76.0" +version = "0.77.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "976efb22fcab4f2cd6bd4e9913764616a54d895c1a23530128d04e03633c555f" +checksum = "5cf504261ac62dfaf4ffb3f41d88fd885e81aba947c1241275043885bc5f0bac" dependencies = [ - "cranelift-codegen-shared 0.76.0", - "cranelift-entity 0.76.0", + "cranelift-codegen-shared 0.77.0", + "cranelift-entity 0.77.0", ] [[package]] @@ -1140,12 +1139,9 @@ checksum = "6759012d6d19c4caec95793f052613e9d4113e925e7f14154defbac0f1d4c938" [[package]] name = "cranelift-codegen-shared" -version = "0.76.0" +version = "0.77.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dabb5fe66e04d4652e434195b45ae65b5c8172d520247b8f66d8df42b2b45dc" -dependencies = [ - "serde", -] +checksum = "1cd2a72db4301dbe7e5a4499035eedc1e82720009fb60603e20504d8691fa9cd" [[package]] name = "cranelift-entity" @@ -1158,9 +1154,9 @@ dependencies = [ [[package]] name = "cranelift-entity" -version = "0.76.0" +version = "0.77.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3329733e4d4b8e91c809efcaa4faee80bf66f20164e3dd16d707346bd3494799" +checksum = "48868faa07cacf948dc4a1773648813c0e453ff9467e800ff10f6a78c021b546" dependencies = [ "serde", ] @@ -1179,11 +1175,11 @@ dependencies = [ [[package]] name = "cranelift-frontend" -version = "0.76.0" +version = "0.77.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "279afcc0d3e651b773f94837c3d581177b348c8d69e928104b2e9fccb226f921" +checksum = "351c9d13b4ecd1a536215ec2fd1c3ee9ee8bc31af172abf1e45ed0adb7a931df" dependencies = [ - "cranelift-codegen 0.76.0", + "cranelift-codegen 0.77.0", "log 0.4.14", "smallvec 1.7.0", "target-lexicon 0.12.0", @@ -1191,30 +1187,29 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.76.0" +version = "0.77.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c04d1fe6a5abb5bb0edc78baa8ef238370fb8e389cc88b6d153f7c3e9680425" +checksum = "6df8b556663d7611b137b24db7f6c8d9a8a27d7f29c7ea7835795152c94c1b75" dependencies = [ - "cranelift-codegen 0.76.0", + "cranelift-codegen 0.77.0", "libc", "target-lexicon 0.12.0", ] [[package]] name = "cranelift-wasm" -version = "0.76.0" +version = "0.77.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0d260ad44f6fd2c91f7f5097191a2a9e3edcbb36df1fb787b600dad5ea148ec" +checksum = "7a69816d90db694fa79aa39b89dda7208a4ac74b6f2b8f3c4da26ee1c8bdfc5e" dependencies = [ - "cranelift-codegen 0.76.0", - "cranelift-entity 0.76.0", - "cranelift-frontend 0.76.0", + "cranelift-codegen 0.77.0", + "cranelift-entity 0.77.0", + "cranelift-frontend 0.77.0", "itertools", "log 0.4.14", - "serde", "smallvec 1.7.0", - "thiserror", - "wasmparser 0.79.0", + "wasmparser 0.80.2", + "wasmtime-types", ] [[package]] @@ -7161,7 +7156,6 @@ checksum = "571f7f397d61c4755285cd37853fe8e03271c243424a907415909379659381c5" dependencies = [ "log 0.4.14", "rustc-hash", - "serde", "smallvec 1.7.0", ] @@ -8626,26 +8620,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" -[[package]] -name = "scroll" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda28d4b4830b807a8b43f7b0e6b5df875311b3e7621d84577188c175b6ec1ec" -dependencies = [ - "scroll_derive", -] - -[[package]] -name = "scroll_derive" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaaae8f38bb311444cfb7f1979af0bc9240d95795f75f9ceddf6a59b79ceffa0" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "sct" version = "0.6.0" @@ -11404,15 +11378,15 @@ checksum = "87cc2fe6350834b4e528ba0901e7aa405d78b89dc1fa3145359eb4de0e323fcf" [[package]] name = "wasmparser" -version = "0.79.0" +version = "0.80.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b5894be15a559c85779254700e1d35f02f843b5a69152e5c82c626d9fd66c0e" +checksum = "449167e2832691a1bff24cde28d2804e90e09586a448c8e76984792c44334a6b" [[package]] name = "wasmtime" -version = "0.29.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bbb8a082a8ef50f7eeb8b82dda9709ef1e68963ea3c94e45581644dd4041835" +checksum = "899b1e5261e3d3420860dacfb952871ace9d7ba9f953b314f67aaf9f8e2a4d89" dependencies = [ "anyhow", "backtrace", @@ -11423,27 +11397,28 @@ dependencies = [ "lazy_static", "libc", "log 0.4.14", + "object 0.26.0", "paste 1.0.4", "psm", + "rayon", "region", "rustc-demangle", "serde", - "smallvec 1.7.0", "target-lexicon 0.12.0", - "wasmparser 0.79.0", + "wasmparser 0.80.2", "wasmtime-cache", + "wasmtime-cranelift", "wasmtime-environ", "wasmtime-jit", - "wasmtime-profiling", "wasmtime-runtime", "winapi 0.3.9", ] [[package]] name = "wasmtime-cache" -version = "0.29.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d73391579ca7f24573138ef768b73b2aed5f9d542385c64979b65d60d0912399" +checksum = "e2493b81d7a9935f7af15e06beec806f256bc974a90a843685f3d61f2fc97058" dependencies = [ "anyhow", "base64 0.13.0", @@ -11462,125 +11437,76 @@ dependencies = [ [[package]] name = "wasmtime-cranelift" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81c6f5ae9205382345c7cd7454932a906186836999a2161c385e38a15f52e1fe" -dependencies = [ - "cranelift-codegen 0.76.0", - "cranelift-entity 0.76.0", - "cranelift-frontend 0.76.0", - "cranelift-wasm", - "target-lexicon 0.12.0", - "wasmparser 0.79.0", - "wasmtime-environ", -] - -[[package]] -name = "wasmtime-debug" -version = "0.29.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c69e08f55e12f15f50b1b533bc3626723e7224254a065de6576934c86258c9e8" +checksum = "99706bacdf5143f7f967d417f0437cce83a724cf4518cb1a3ff40e519d793021" dependencies = [ "anyhow", + "cranelift-codegen 0.77.0", + "cranelift-entity 0.77.0", + "cranelift-frontend 0.77.0", + "cranelift-native", + "cranelift-wasm", "gimli 0.25.0", "more-asserts", "object 0.26.0", "target-lexicon 0.12.0", "thiserror", - "wasmparser 0.79.0", + "wasmparser 0.80.2", "wasmtime-environ", ] [[package]] name = "wasmtime-environ" -version = "0.29.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "005d93174040af37fb8625f891cd9827afdad314261f7ec4ee61ec497d6e9d3c" +checksum = "ac42cb562a2f98163857605f02581d719a410c5abe93606128c59a10e84de85b" dependencies = [ + "anyhow", "cfg-if 1.0.0", - "cranelift-codegen 0.76.0", - "cranelift-entity 0.76.0", - "cranelift-wasm", + "cranelift-entity 0.77.0", "gimli 0.25.0", "indexmap", "log 0.4.14", "more-asserts", + "object 0.26.0", "serde", + "target-lexicon 0.12.0", "thiserror", - "wasmparser 0.79.0", + "wasmparser 0.80.2", + "wasmtime-types", ] [[package]] name = "wasmtime-jit" -version = "0.29.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0bf1dfb213a35d8f21aefae40e597fe72778a907011ffdff7affb029a02af9a" +checksum = "24f46dd757225f29a419be415ea6fb8558df9b0194f07e3a6a9c99d0e14dd534" dependencies = [ "addr2line", "anyhow", + "bincode", "cfg-if 1.0.0", - "cranelift-codegen 0.76.0", - "cranelift-entity 0.76.0", - "cranelift-frontend 0.76.0", - "cranelift-native", - "cranelift-wasm", "gimli 0.25.0", + "libc", "log 0.4.14", "more-asserts", "object 0.26.0", - "rayon", "region", "serde", "target-lexicon 0.12.0", "thiserror", - "wasmparser 0.79.0", - "wasmtime-cranelift", - "wasmtime-debug", + "wasmparser 0.80.2", "wasmtime-environ", - "wasmtime-obj", - "wasmtime-profiling", "wasmtime-runtime", "winapi 0.3.9", ] -[[package]] -name = "wasmtime-obj" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231491878e710c68015228c9f9fc5955fe5c96dbf1485c15f7bed55b622c83c" -dependencies = [ - "anyhow", - "more-asserts", - "object 0.26.0", - "target-lexicon 0.12.0", - "wasmtime-debug", - "wasmtime-environ", -] - -[[package]] -name = "wasmtime-profiling" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21486cfb5255c2069666c1f116f9e949d4e35c9a494f11112fa407879e42198d" -dependencies = [ - "anyhow", - "cfg-if 1.0.0", - "gimli 0.25.0", - "lazy_static", - "libc", - "object 0.26.0", - "scroll", - "serde", - "target-lexicon 0.12.0", - "wasmtime-environ", - "wasmtime-runtime", -] - [[package]] name = "wasmtime-runtime" -version = "0.29.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7ddfdf32e0a20d81f48be9dacd31612bc61de5a174d1356fef806d300f507de" +checksum = "0122215a44923f395487048cb0a1d60b5b32c73aab15cf9364b798dbaff0996f" dependencies = [ "anyhow", "backtrace", @@ -11600,6 +11526,18 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "wasmtime-types" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9b01caf8a204ef634ebac99700e77ba716d3ebbb68a1abbc2ceb6b16dbec9e4" +dependencies = [ + "cranelift-entity 0.77.0", + "serde", + "thiserror", + "wasmparser 0.80.2", +] + [[package]] name = "wast" version = "38.0.0" diff --git a/client/executor/src/wasm_runtime.rs b/client/executor/src/wasm_runtime.rs index 4c768b7f9c61..c7aa1200719d 100644 --- a/client/executor/src/wasm_runtime.rs +++ b/client/executor/src/wasm_runtime.rs @@ -318,14 +318,15 @@ pub fn create_wasm_runtime_with_code( WasmExecutionMethod::Compiled => sc_executor_wasmtime::create_runtime( blob, sc_executor_wasmtime::Config { - heap_pages: heap_pages as u32, - max_memory_pages: None, + heap_pages, + max_memory_size: None, allow_missing_func_imports, cache_path: cache_path.map(ToOwned::to_owned), semantics: sc_executor_wasmtime::Semantics { fast_instance_reuse: true, deterministic_stack_limit: None, canonicalize_nans: false, + parallel_compilation: true, }, }, host_functions, diff --git a/client/executor/wasmtime/Cargo.toml b/client/executor/wasmtime/Cargo.toml index c122b3ab0e69..a8ed01c203e3 100644 --- a/client/executor/wasmtime/Cargo.toml +++ b/client/executor/wasmtime/Cargo.toml @@ -23,8 +23,9 @@ sp-wasm-interface = { version = "4.0.0-dev", path = "../../../primitives/wasm-in sp-runtime-interface = { version = "4.0.0-dev", path = "../../../primitives/runtime-interface" } sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" } sc-allocator = { version = "4.0.0-dev", path = "../../allocator" } -wasmtime = { version = "0.29.0", default-features = false, features = [ +wasmtime = { version = "0.30.0", default-features = false, features = [ "cache", + "cranelift", "jitdump", "parallel-compilation", ] } diff --git a/client/executor/wasmtime/src/imports.rs b/client/executor/wasmtime/src/imports.rs index a9ef6e1f58a7..a00ab14263e7 100644 --- a/client/executor/wasmtime/src/imports.rs +++ b/client/executor/wasmtime/src/imports.rs @@ -22,10 +22,9 @@ use crate::{ }; use sc_executor_common::error::WasmError; use sp_wasm_interface::{Function, ValueType}; -use std::any::Any; +use std::{any::Any, convert::TryInto}; use wasmtime::{ - Caller, Extern, ExternType, Func, FuncType, ImportType, Limits, Memory, MemoryType, Module, - Trap, Val, + Caller, Extern, ExternType, Func, FuncType, ImportType, Memory, MemoryType, Module, Trap, Val, }; pub struct Imports { @@ -41,7 +40,7 @@ pub(crate) fn resolve_imports( store: &mut Store, module: &Module, host_functions: &[&'static dyn Function], - heap_pages: u32, + heap_pages: u64, allow_missing_func_imports: bool, ) -> Result { let mut externs = vec![]; @@ -83,7 +82,7 @@ fn import_name<'a, 'b: 'a>(import: &'a ImportType<'b>) -> Result<&'a str, WasmEr fn resolve_memory_import( store: &mut Store, import_ty: &ImportType, - heap_pages: u32, + heap_pages: u64, ) -> Result { let requested_memory_ty = match import_ty.ty() { ExternType::Memory(memory_ty) => memory_ty, @@ -97,8 +96,8 @@ fn resolve_memory_import( // Increment the min (a.k.a initial) number of pages by `heap_pages` and check if it exceeds the // maximum specified by the import. - let initial = requested_memory_ty.limits().min().saturating_add(heap_pages); - if let Some(max) = requested_memory_ty.limits().max() { + let initial = requested_memory_ty.minimum().saturating_add(heap_pages); + if let Some(max) = requested_memory_ty.maximum() { if initial > max { return Err(WasmError::Other(format!( "incremented number of pages by heap_pages (total={}) is more than maximum requested\ @@ -109,7 +108,27 @@ fn resolve_memory_import( } } - let memory_ty = MemoryType::new(Limits::new(initial, requested_memory_ty.limits().max())); + // Note that the return value of `maximum` and `minimum`, while a u64, + // will always fit into a u32 for 32-bit memories. + // 64-bit memories are part of the memory64 proposal for WebAssembly which is not standardized + // yet. + let minimum: u32 = initial.try_into().map_err(|_| { + WasmError::Other(format!( + "minimum number of memory pages ({}) doesn't fit into u32", + initial + )) + })?; + let maximum: Option = match requested_memory_ty.maximum() { + Some(max) => Some(max.try_into().map_err(|_| { + WasmError::Other(format!( + "maximum number of memory pages ({}) doesn't fit into u32", + max + )) + })?), + None => None, + }; + + let memory_ty = MemoryType::new(minimum, maximum); let memory = Memory::new(store, memory_ty).map_err(|e| { WasmError::Other(format!( "failed to create a memory during resolving of memory import: {}", diff --git a/client/executor/wasmtime/src/instance_wrapper.rs b/client/executor/wasmtime/src/instance_wrapper.rs index ccfbb912b9a6..2b8508ee2b07 100644 --- a/client/executor/wasmtime/src/instance_wrapper.rs +++ b/client/executor/wasmtime/src/instance_wrapper.rs @@ -154,7 +154,7 @@ impl InstanceWrapper { pub fn new( module: &Module, imports: &Imports, - heap_pages: u32, + heap_pages: u64, mut ctx: impl AsContextMut, ) -> Result { let instance = Instance::new(&mut ctx, module, &imports.externs) diff --git a/client/executor/wasmtime/src/runtime.rs b/client/executor/wasmtime/src/runtime.rs index a62356357b1f..bd113c338383 100644 --- a/client/executor/wasmtime/src/runtime.rs +++ b/client/executor/wasmtime/src/runtime.rs @@ -77,7 +77,7 @@ struct InstanceCreator { store: Store, module: Arc, imports: Arc, - heap_pages: u32, + heap_pages: u64, } impl InstanceCreator { @@ -130,15 +130,15 @@ pub struct WasmtimeRuntime { impl WasmtimeRuntime { /// Creates the store respecting the set limits. fn new_store(&self) -> Store { - let limits = if let Some(max_memory_pages) = self.config.max_memory_pages { - wasmtime::StoreLimitsBuilder::new().memory_pages(max_memory_pages).build() + let limits = if let Some(max_memory_size) = self.config.max_memory_size { + wasmtime::StoreLimitsBuilder::new().memory_size(max_memory_size).build() } else { Default::default() }; let mut store = Store::new(&self.engine, StoreData { limits, host_state: None }); - if self.config.max_memory_pages.is_some() { + if self.config.max_memory_size.is_some() { store.limiter(|s| &mut s.limits); } @@ -350,6 +350,8 @@ fn common_config(semantics: &Semantics) -> std::result::Result std::result::Result, + pub max_memory_size: Option, /// The WebAssembly standard requires all imports of an instantiated module to be resolved, - /// othewise, the instantiation fails. If this option is set to `true`, then this behavior is + /// otherwise, the instantiation fails. If this option is set to `true`, then this behavior is /// overriden and imports that are requested by the module and not provided by the host /// functions will be resolved using stubs. These stubs will trap upon a call. pub allow_missing_func_imports: bool, diff --git a/client/executor/wasmtime/src/tests.rs b/client/executor/wasmtime/src/tests.rs index 2a8bcc0b01b0..261afba0c6bc 100644 --- a/client/executor/wasmtime/src/tests.rs +++ b/client/executor/wasmtime/src/tests.rs @@ -28,8 +28,8 @@ struct RuntimeBuilder { fast_instance_reuse: bool, canonicalize_nans: bool, deterministic_stack: bool, - heap_pages: u32, - max_memory_pages: Option, + heap_pages: u64, + max_memory_size: Option, } impl RuntimeBuilder { @@ -42,7 +42,7 @@ impl RuntimeBuilder { canonicalize_nans: false, deterministic_stack: false, heap_pages: 1024, - max_memory_pages: None, + max_memory_size: None, } } @@ -58,8 +58,8 @@ impl RuntimeBuilder { self.deterministic_stack = deterministic_stack; } - fn max_memory_pages(&mut self, max_memory_pages: Option) { - self.max_memory_pages = max_memory_pages; + fn max_memory_size(&mut self, max_memory_size: Option) { + self.max_memory_size = max_memory_size; } fn build(self) -> Arc { @@ -82,7 +82,7 @@ impl RuntimeBuilder { blob, crate::Config { heap_pages: self.heap_pages, - max_memory_pages: self.max_memory_pages, + max_memory_size: self.max_memory_size, allow_missing_func_imports: true, cache_path: None, semantics: crate::Semantics { @@ -95,6 +95,7 @@ impl RuntimeBuilder { false => None, }, canonicalize_nans: self.canonicalize_nans, + parallel_compilation: true, }, }, { @@ -171,13 +172,13 @@ fn test_stack_depth_reaching() { #[test] fn test_max_memory_pages() { fn try_instantiate( - max_memory_pages: Option, + max_memory_size: Option, wat: &'static str, ) -> Result<(), Box> { let runtime = { let mut builder = RuntimeBuilder::new_on_demand(); builder.use_wat(wat); - builder.max_memory_pages(max_memory_pages); + builder.max_memory_size(max_memory_size); builder.build() }; let mut instance = runtime.new_instance()?; @@ -185,6 +186,8 @@ fn test_max_memory_pages() { Ok(()) } + const WASM_PAGE_SIZE: usize = 65536; + // check the old behavior if preserved. That is, if no limit is set we allow 4 GiB of memory. try_instantiate( None, @@ -213,9 +216,9 @@ fn test_max_memory_pages() { // max is not specified, therefore it's implied to be 65536 pages (4 GiB). // - // max_memory_pages = 1 (initial) + 1024 (heap_pages) + // max_memory_size = (1 (initial) + 1024 (heap_pages)) * WASM_PAGE_SIZE try_instantiate( - Some(1 + 1024), + Some((1 + 1024) * WASM_PAGE_SIZE), r#" (module @@ -233,7 +236,7 @@ fn test_max_memory_pages() { // max is specified explicitly to 2048 pages. try_instantiate( - Some(1 + 1024), + Some((1 + 1024) * WASM_PAGE_SIZE), r#" (module @@ -251,7 +254,7 @@ fn test_max_memory_pages() { // memory grow should work as long as it doesn't exceed 1025 pages in total. try_instantiate( - Some(0 + 1024 + 25), + Some((0 + 1024 + 25) * WASM_PAGE_SIZE), r#" (module (import "env" "memory" (memory 0)) ;; <- zero starting pages. @@ -280,7 +283,7 @@ fn test_max_memory_pages() { // We start with 1025 pages and try to grow at least one. try_instantiate( - Some(1 + 1024), + Some((1 + 1024) * WASM_PAGE_SIZE), r#" (module (import "env" "memory" (memory 1)) ;; <- initial=1, meaning after heap pages mount the From 90dd23e78851605180f3dc3bfcf43e2800354f79 Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Tue, 12 Oct 2021 20:28:11 +0100 Subject: [PATCH 076/695] documentation for recovery of emergency phase (#9989) * documentation for recovery of emergency phase * Update frame/election-provider-multi-phase/src/lib.rs Co-authored-by: Alexander Popiak * Update frame/election-provider-multi-phase/src/lib.rs Co-authored-by: Alexander Popiak Co-authored-by: Alexander Popiak --- .../election-provider-multi-phase/src/lib.rs | 51 +++++++++++++------ 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/frame/election-provider-multi-phase/src/lib.rs b/frame/election-provider-multi-phase/src/lib.rs index 9508b3a7c83f..a7863fafa774 100644 --- a/frame/election-provider-multi-phase/src/lib.rs +++ b/frame/election-provider-multi-phase/src/lib.rs @@ -67,11 +67,11 @@ //! origin can not bail out in any way, if their solution is queued. //! //! Upon the end of the signed phase, the solutions are examined from best to worse (i.e. `pop()`ed -//! until drained). Each solution undergoes an expensive `Pallet::feasibility_check`, which -//! ensures the score claimed by this score was correct, and it is valid based on the election data -//! (i.e. votes and candidates). At each step, if the current best solution passes the feasibility -//! check, it is considered to be the best one. The sender of the origin is rewarded, and the rest -//! of the queued solutions get their deposit back and are discarded, without being checked. +//! until drained). Each solution undergoes an expensive `Pallet::feasibility_check`, which ensures +//! the score claimed by this score was correct, and it is valid based on the election data (i.e. +//! votes and candidates). At each step, if the current best solution passes the feasibility check, +//! it is considered to be the best one. The sender of the origin is rewarded, and the rest of the +//! queued solutions get their deposit back and are discarded, without being checked. //! //! The following example covers all of the cases at the end of the signed phase: //! @@ -121,17 +121,35 @@ //! //! If, for any of the below reasons: //! -//! 1. No signed or unsigned solution submitted & Fallback is `None` or failed -//! 2. Internal error +//! 1. No **signed** or **unsigned** solution submitted, and no successful [`Config::Fallback`] is +//! provided +//! 2. Any other unforeseen internal error //! //! A call to `T::ElectionProvider::elect` is made, and `Ok(_)` cannot be returned, then the pallet //! proceeds to the [`Phase::Emergency`]. During this phase, any solution can be submitted from -//! [`Config::ForceOrigin`], without any checking. Once submitted, the forced solution is kept in -//! [`QueuedSolution`] until the next call to `T::ElectionProvider::elect`, where it is returned and -//! [`Phase`] goes back to `Off`. +//! [`Config::ForceOrigin`], without any checking, via [`Pallet::set_emergency_election_result`] +//! transaction. Hence, `[`Config::ForceOrigin`]` should only be set to a trusted origin, such as +//! the council or root. Once submitted, the forced solution is kept in [`QueuedSolution`] until the +//! next call to `T::ElectionProvider::elect`, where it is returned and [`Phase`] goes back to +//! `Off`. //! //! This implies that the user of this pallet (i.e. a staking pallet) should re-try calling -//! `T::ElectionProvider::elect` in case of error until `OK(_)` is returned. +//! `T::ElectionProvider::elect` in case of error, until `OK(_)` is returned. +//! +//! To generate an emergency solution, one must only provide one argument: [`Supports`]. This is +//! essentially a collection of elected winners for the election, and voters who support them. The +//! supports can be generated by any means. In the simplest case, it could be manual. For example, +//! in the case of massive network failure or misbehaviour, [`Config::ForceOrigin`] might decide to +//! select only a small number of emergency winners (which would greatly restrict the next validator +//! set, if this pallet is used with `pallet-staking`). If the failure is for other technical +//! reasons, then a simple and safe way to generate supports is using the staking-miner binary +//! provided in the Polkadot repository. This binary has a subcommand named `emergency-solution` +//! which is capable of connecting to a live network, and generating appropriate `supports` using a +//! standard algorithm, and outputting the `supports` in hex format, ready for submission. Note that +//! while this binary lives in the Polkadot repository, this particular subcommand of it can work +//! against any substrate based-chain. +//! +//! See the `staking-miner` documentation in the Polkadot repository for more information. //! //! ## Feasible Solution (correct solution) //! @@ -146,16 +164,16 @@ //! //! ## Accuracy //! -//! The accuracy of the election is configured via -//! [`SolutionAccuracyOf`] which is the accuracy that the submitted solutions must adhere to. +//! The accuracy of the election is configured via [`SolutionAccuracyOf`] which is the accuracy that +//! the submitted solutions must adhere to. //! //! Note that the accuracy is of great importance. The offchain solution should be as small as //! possible, reducing solutions size/weight. //! //! ## Error types //! -//! This pallet provides a verbose error system to ease future debugging and debugging. The -//! overall hierarchy of errors is as follows: +//! This pallet provides a verbose error system to ease future debugging and debugging. The overall +//! hierarchy of errors is as follows: //! //! 1. [`pallet::Error`]: These are the errors that can be returned in the dispatchables of the //! pallet, either signed or unsigned. Since decomposition with nested enums is not possible @@ -173,6 +191,9 @@ //! //! ## Future Plans //! +//! **Emergency-phase recovery script**: This script should be taken out of staking-miner in +//! polkadot and ideally live in `substrate/utils/frame/elections`. +//! //! **Challenge Phase**. We plan on adding a third phase to the pallet, called the challenge phase. //! This is a phase in which no further solutions are processed, and the current best solution might //! be challenged by anyone (signed or unsigned). The main plan here is to enforce the solution to From 51361fd3ef16f5df28e8af9ba04078246f13fbfe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Oct 2021 06:49:17 +0000 Subject: [PATCH 077/695] Bump parity-scale-codec from 2.2.0 to 2.3.1 (#9998) * Bump parity-scale-codec from 2.2.0 to 2.3.1 Bumps [parity-scale-codec](https://github.com/paritytech/parity-scale-codec) from 2.2.0 to 2.3.1. - [Release notes](https://github.com/paritytech/parity-scale-codec/releases) - [Changelog](https://github.com/paritytech/parity-scale-codec/blob/master/CHANGELOG.md) - [Commits](https://github.com/paritytech/parity-scale-codec/compare/v2.2...parity-scale-codec-v2.3.1) --- updated-dependencies: - dependency-name: parity-scale-codec dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Update UI test expectations * Update UI test expectations Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Keith Yeung --- Cargo.lock | 8 +++--- client/cli/Cargo.toml | 2 +- client/finality-grandpa/Cargo.toml | 2 +- client/service/test/Cargo.toml | 2 +- .../call_argument_invalid_bound_2.stderr | 27 +++++++++++++------ .../npos-elections/solution-type/Cargo.toml | 2 +- utils/frame/try-runtime/cli/Cargo.toml | 2 +- 7 files changed, 28 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d9f733958874..50a962983f28 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6158,9 +6158,9 @@ dependencies = [ [[package]] name = "parity-scale-codec" -version = "2.2.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8975095a2a03bbbdc70a74ab11a4f76a6d0b84680d87c68d722531b0ac28e8a9" +checksum = "373b1a4c1338d9cd3d1fa53b3a11bdab5ab6bd80a20f7f7becd76953ae2be909" dependencies = [ "arrayvec 0.7.0", "bitvec 0.20.2", @@ -6172,9 +6172,9 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "2.2.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40dbbfef7f0a1143c5b06e0d76a6278e25dac0bc1af4be51a0fbb73f07e7ad09" +checksum = "1557010476e0595c9b568d16dcfb81b93cdeb157612726f5170d31aa707bed27" dependencies = [ "proc-macro-crate 1.0.0", "proc-macro2", diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index ee72958f74d8..b32e985b518c 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -19,7 +19,7 @@ tokio = { version = "1.10", features = [ "signal", "rt-multi-thread" ] } futures = "0.3.9" fdlimit = "0.2.1" libp2p = "0.39.1" -parity-scale-codec = "2.0.0" +parity-scale-codec = "2.3.1" hex = "0.4.2" rand = "0.7.3" tiny-bip39 = "0.8.2" diff --git a/client/finality-grandpa/Cargo.toml b/client/finality-grandpa/Cargo.toml index 7fdd91e557ab..45f85f46ddff 100644 --- a/client/finality-grandpa/Cargo.toml +++ b/client/finality-grandpa/Cargo.toml @@ -23,7 +23,7 @@ futures-timer = "3.0.1" log = "0.4.8" parking_lot = "0.11.1" rand = "0.8.4" -parity-scale-codec = { version = "2.0.0", features = ["derive"] } +parity-scale-codec = { version = "2.3.1", features = ["derive"] } sp-application-crypto = { version = "4.0.0-dev", path = "../../primitives/application-crypto" } sp-arithmetic = { version = "4.0.0-dev", path = "../../primitives/arithmetic" } sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } diff --git a/client/service/test/Cargo.toml b/client/service/test/Cargo.toml index d267d2535f8c..fc42368a10ae 100644 --- a/client/service/test/Cargo.toml +++ b/client/service/test/Cargo.toml @@ -41,5 +41,5 @@ sc-client-api = { version = "4.0.0-dev", path = "../../api" } sc-block-builder = { version = "0.10.0-dev", path = "../../block-builder" } sc-executor = { version = "0.10.0-dev", path = "../../executor" } sp-panic-handler = { version = "3.0.0", path = "../../../primitives/panic-handler" } -parity-scale-codec = "2.0.0" +parity-scale-codec = "2.3.1" sp-tracing = { version = "4.0.0-dev", path = "../../../primitives/tracing" } diff --git a/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr b/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr index c9ff843103b3..15c611f4918d 100644 --- a/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr +++ b/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr @@ -32,17 +32,28 @@ help: consider further restricting this bound | ^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `::Bar: WrapperTypeEncode` is not satisfied - --> $DIR/call_argument_invalid_bound_2.rs:20:36 + --> $DIR/call_argument_invalid_bound_2.rs:1:1 | -20 | pub fn foo(origin: OriginFor, bar: T::Bar) -> DispatchResultWithPostInfo { - | ^^^ the trait `WrapperTypeEncode` is not implemented for `::Bar` +1 | #[frame_support::pallet] + | ^----------------------- + | | + | _in this procedural macro expansion + | | +2 | | mod pallet { +3 | | use frame_support::pallet_prelude::{Hooks, DispatchResultWithPostInfo}; +4 | | use frame_system::pallet_prelude::{BlockNumberFor, OriginFor}; +... | +16 | | +17 | | #[pallet::call] + | |__________________^ the trait `WrapperTypeEncode` is not implemented for `::Bar` | - ::: $CARGO/parity-scale-codec-2.2.0/src/codec.rs + ::: $CARGO/parity-scale-codec-2.3.1/src/codec.rs | - | fn encode_to(&self, dest: &mut T) { - | ------ required by this bound in `encode_to` + | fn encode_to(&self, dest: &mut T) { + | ------ required by this bound in `encode_to` | = note: required because of the requirements on the impl of `Encode` for `::Bar` + = note: this error originates in the derive macro `frame_support::codec::Encode` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `::Bar: WrapperTypeDecode` is not satisfied --> $DIR/call_argument_invalid_bound_2.rs:20:36 @@ -50,9 +61,9 @@ error[E0277]: the trait bound `::Bar: WrapperTypeDecode` is 20 | pub fn foo(origin: OriginFor, bar: T::Bar) -> DispatchResultWithPostInfo { | ^^^ the trait `WrapperTypeDecode` is not implemented for `::Bar` | - ::: $CARGO/parity-scale-codec-2.2.0/src/codec.rs + ::: $CARGO/parity-scale-codec-2.3.1/src/codec.rs | | fn decode(input: &mut I) -> Result; - | ----- required by this bound in `pallet::_::_parity_scale_codec::Decode::decode` + | ----- required by this bound in `parity_scale_codec::Decode::decode` | = note: required because of the requirements on the impl of `Decode` for `::Bar` diff --git a/primitives/npos-elections/solution-type/Cargo.toml b/primitives/npos-elections/solution-type/Cargo.toml index 5cbf0b648181..8eb9c26564f5 100644 --- a/primitives/npos-elections/solution-type/Cargo.toml +++ b/primitives/npos-elections/solution-type/Cargo.toml @@ -21,7 +21,7 @@ proc-macro2 = "1.0.29" proc-macro-crate = "1.0.0" [dev-dependencies] -parity-scale-codec = "2.0.1" +parity-scale-codec = "2.3.1" scale-info = "1.0" sp-arithmetic = { path = "../../arithmetic", version = "4.0.0-dev" } # used by generate_solution_type: diff --git a/utils/frame/try-runtime/cli/Cargo.toml b/utils/frame/try-runtime/cli/Cargo.toml index b20915335b97..6f4fd91126fb 100644 --- a/utils/frame/try-runtime/cli/Cargo.toml +++ b/utils/frame/try-runtime/cli/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] log = "0.4.8" -parity-scale-codec = { version = "2.0.0" } +parity-scale-codec = { version = "2.3.1" } serde = "1.0.126" structopt = "0.3.8" From dc887374ba3c3d4acfd35cd7fa10263acadd3333 Mon Sep 17 00:00:00 2001 From: zjb0807 Date: Wed, 13 Oct 2021 18:49:34 +0800 Subject: [PATCH 078/695] Add TypeInfo (#10010) * add TypeInfo for DispatchTime * add TypeInfo for BoundedBTreeSet * add skip_type_params * add TypeInfo for BoundedSlice * add skip_type_params --- frame/support/src/storage/bounded_btree_set.rs | 3 ++- frame/support/src/storage/bounded_vec.rs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/frame/support/src/storage/bounded_btree_set.rs b/frame/support/src/storage/bounded_btree_set.rs index f74ff12854a5..ecfb0bdbd261 100644 --- a/frame/support/src/storage/bounded_btree_set.rs +++ b/frame/support/src/storage/bounded_btree_set.rs @@ -31,7 +31,8 @@ use sp_std::{ /// /// Unlike a standard `BTreeSet`, there is an enforced upper limit to the number of items in the /// set. All internal operations ensure this bound is respected. -#[derive(Encode)] +#[derive(Encode, scale_info::TypeInfo)] +#[scale_info(skip_type_params(S))] pub struct BoundedBTreeSet(BTreeSet, PhantomData); impl Decode for BoundedBTreeSet diff --git a/frame/support/src/storage/bounded_vec.rs b/frame/support/src/storage/bounded_vec.rs index f353127969c5..a60ed57cf2b9 100644 --- a/frame/support/src/storage/bounded_vec.rs +++ b/frame/support/src/storage/bounded_vec.rs @@ -44,7 +44,8 @@ pub struct BoundedVec(Vec, PhantomData); /// A bounded slice. /// /// Similar to a `BoundedVec`, but not owned and cannot be decoded. -#[derive(Encode)] +#[derive(Encode, scale_info::TypeInfo)] +#[scale_info(skip_type_params(S))] pub struct BoundedSlice<'a, T, S>(&'a [T], PhantomData); // `BoundedSlice`s encode to something which will always decode into a `BoundedVec`, From c5c908795c80b223c7190d4c6f1bbdf3a9a10cbc Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Wed, 13 Oct 2021 12:12:26 +0100 Subject: [PATCH 079/695] allow remote-ext to exclude some keys (#10020) * allow remote-ext to exclude some keys * don't use deprecated, just remove. * rename --- utils/frame/remote-externalities/src/lib.rs | 90 +++++++++++++++---- .../cli/src/commands/execute_block.rs | 2 +- .../cli/src/commands/follow_chain.rs | 6 +- .../cli/src/commands/offchain_worker.rs | 2 +- .../cli/src/commands/on_runtime_upgrade.rs | 2 +- 5 files changed, 80 insertions(+), 22 deletions(-) diff --git a/utils/frame/remote-externalities/src/lib.rs b/utils/frame/remote-externalities/src/lib.rs index 2052780286c6..733ec7c3200a 100644 --- a/utils/frame/remote-externalities/src/lib.rs +++ b/utils/frame/remote-externalities/src/lib.rs @@ -160,13 +160,16 @@ impl Default for SnapshotConfig { /// Builder for remote-externalities. pub struct Builder { - /// Custom key-pairs to be injected into the externalities. - inject: Vec, + /// Custom key-pairs to be injected into the externalities. The *hashed* keys and values must + /// be given. + hashed_key_values: Vec, /// Storage entry key prefixes to be injected into the externalities. The *hashed* prefix must /// be given. hashed_prefixes: Vec>, /// Storage entry keys to be injected into the externalities. The *hashed* key must be given. hashed_keys: Vec>, + /// The keys that will be excluded from the final externality. The *hashed* key must be given. + hashed_blacklist: Vec>, /// connectivity mode, online or offline. mode: Mode, } @@ -176,10 +179,11 @@ pub struct Builder { impl Default for Builder { fn default() -> Self { Self { - inject: Default::default(), mode: Default::default(), + hashed_key_values: Default::default(), hashed_prefixes: Default::default(), hashed_keys: Default::default(), + hashed_blacklist: Default::default(), } } } @@ -435,12 +439,26 @@ impl Builder { }, }; - debug!( - target: LOG_TARGET, - "extending externalities with {} manually injected key-values", - self.inject.len() - ); - base_kv.extend(self.inject.clone()); + // inject manual key values. + if !self.hashed_key_values.is_empty() { + debug!( + target: LOG_TARGET, + "extending externalities with {} manually injected key-values", + self.hashed_key_values.len() + ); + base_kv.extend(self.hashed_key_values.clone()); + } + + // exclude manual key values. + if !self.hashed_blacklist.is_empty() { + debug!( + target: LOG_TARGET, + "excluding externalities from {} keys", + self.hashed_blacklist.len() + ); + base_kv.retain(|(k, _)| !self.hashed_blacklist.contains(&k.0)) + } + Ok(base_kv) } } @@ -453,13 +471,12 @@ impl Builder { } /// Inject a manual list of key and values to the storage. - pub fn inject_key_value(mut self, injections: &[KeyPair]) -> Self { + pub fn inject_hashed_key_value(mut self, injections: &[KeyPair]) -> Self { for i in injections { - self.inject.push(i.clone()); + self.hashed_key_values.push(i.clone()); } self } - /// Inject a hashed prefix. This is treated as-is, and should be pre-hashed. /// /// This should be used to inject a "PREFIX", like a storage (double) map. @@ -476,6 +493,13 @@ impl Builder { self } + /// Blacklist this hashed key from the final externalities. This is treated as-is, and should be + /// pre-hashed. + pub fn blacklist_hashed_key(mut self, hashed: &[u8]) -> Self { + self.hashed_blacklist.push(hashed.to_vec()); + self + } + /// Configure a state snapshot to be used. pub fn mode(mut self, mode: Mode) -> Self { self.mode = mode; @@ -541,12 +565,44 @@ mod tests { .expect("Can't read state snapshot file") .execute_with(|| {}); } + + #[tokio::test] + async fn can_exclude_from_cache() { + init_logger(); + + // get the first key from the cache file. + let some_key = Builder::::new() + .mode(Mode::Offline(OfflineConfig { + state_snapshot: SnapshotConfig::new("test_data/proxy_test"), + })) + .build() + .await + .expect("Can't read state snapshot file") + .execute_with(|| { + let key = + sp_io::storage::next_key(&[]).expect("some key must exist in the snapshot"); + assert!(sp_io::storage::get(&key).is_some()); + key + }); + + Builder::::new() + .mode(Mode::Offline(OfflineConfig { + state_snapshot: SnapshotConfig::new("test_data/proxy_test"), + })) + .blacklist_hashed_key(&some_key) + .build() + .await + .expect("Can't read state snapshot file") + .execute_with(|| assert!(sp_io::storage::get(&some_key).is_none())); + } } #[cfg(all(test, feature = "remote-test"))] mod remote_tests { use super::test_prelude::*; + const REMOTE_INACCESSIBLE: &'static str = "Can't reach the remote node. Is it running?"; + #[tokio::test] async fn can_build_one_pallet() { init_logger(); @@ -557,7 +613,7 @@ mod remote_tests { })) .build() .await - .expect("Can't reach the remote node. Is it running?") + .expect(REMOTE_INACCESSIBLE) .execute_with(|| {}); } @@ -575,7 +631,7 @@ mod remote_tests { })) .build() .await - .expect("Can't reach the remote node. Is it running?") + .expect(REMOTE_INACCESSIBLE) .execute_with(|| {}); } @@ -599,7 +655,7 @@ mod remote_tests { })) .build() .await - .expect("Can't reach the remote node. Is it running?") + .expect(REMOTE_INACCESSIBLE) .execute_with(|| { // Gav's polkadot account. 99% this will be in the council. let gav_polkadot = @@ -625,7 +681,7 @@ mod remote_tests { })) .build() .await - .expect("Can't reach the remote node. Is it running?") + .expect(REMOTE_INACCESSIBLE) .execute_with(|| {}); let to_delete = std::fs::read_dir(SnapshotConfig::default().path) @@ -648,7 +704,7 @@ mod remote_tests { Builder::::new() .build() .await - .expect("Can't reach the remote node. Is it running?") + .expect(REMOTE_INACCESSIBLE) .execute_with(|| {}); } } diff --git a/utils/frame/try-runtime/cli/src/commands/execute_block.rs b/utils/frame/try-runtime/cli/src/commands/execute_block.rs index 19422db90119..216c63d00525 100644 --- a/utils/frame/try-runtime/cli/src/commands/execute_block.rs +++ b/utils/frame/try-runtime/cli/src/commands/execute_block.rs @@ -143,7 +143,7 @@ where let builder = if command.overwrite_wasm_code { let (code_key, code) = extract_code(&config.chain_spec)?; - builder.inject_key_value(&[(code_key, code)]) + builder.inject_hashed_key_value(&[(code_key, code)]) } else { builder.inject_hashed_key(well_known_keys::CODE) }; diff --git a/utils/frame/try-runtime/cli/src/commands/follow_chain.rs b/utils/frame/try-runtime/cli/src/commands/follow_chain.rs index 0526f5d327fb..9125db13c78f 100644 --- a/utils/frame/try-runtime/cli/src/commands/follow_chain.rs +++ b/utils/frame/try-runtime/cli/src/commands/follow_chain.rs @@ -112,8 +112,10 @@ where ..Default::default() })); - let new_ext = - builder.inject_key_value(&[(code_key.clone(), code.clone())]).build().await?; + let new_ext = builder + .inject_hashed_key_value(&[(code_key.clone(), code.clone())]) + .build() + .await?; log::info!( target: LOG_TARGET, "initialized state externalities at {:?}, storage root {:?}", diff --git a/utils/frame/try-runtime/cli/src/commands/offchain_worker.rs b/utils/frame/try-runtime/cli/src/commands/offchain_worker.rs index 6f37e4b3849f..22120ef4b5fe 100644 --- a/utils/frame/try-runtime/cli/src/commands/offchain_worker.rs +++ b/utils/frame/try-runtime/cli/src/commands/offchain_worker.rs @@ -132,7 +132,7 @@ where let builder = if command.overwrite_wasm_code { let (code_key, code) = extract_code(&config.chain_spec)?; - builder.inject_key_value(&[(code_key, code)]) + builder.inject_hashed_key_value(&[(code_key, code)]) } else { builder.inject_hashed_key(well_known_keys::CODE) }; diff --git a/utils/frame/try-runtime/cli/src/commands/on_runtime_upgrade.rs b/utils/frame/try-runtime/cli/src/commands/on_runtime_upgrade.rs index 86f5548b8aaf..8de3cb3a3200 100644 --- a/utils/frame/try-runtime/cli/src/commands/on_runtime_upgrade.rs +++ b/utils/frame/try-runtime/cli/src/commands/on_runtime_upgrade.rs @@ -54,7 +54,7 @@ where let ext = { let builder = command.state.builder::()?; let (code_key, code) = extract_code(&config.chain_spec)?; - builder.inject_key_value(&[(code_key, code)]).build().await? + builder.inject_hashed_key_value(&[(code_key, code)]).build().await? }; if let Some(uri) = command.state.live_uri() { From 9689a131a595b99e60f134d7634f5f4d71969410 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Wed, 13 Oct 2021 13:31:36 +0200 Subject: [PATCH 080/695] Ensure we don't create gap epochs when importing multiple genesis epochs (#10019) The babe `authoring_blocks` test was flaky because it could happen that we imported the first block multiple times. This lead to import the genesis epoch multiples times. `EpochChanges` was assuming that importing a genesis epoch while there was already an imported epoch means that there is a "gap". However, this wasn't true as we just imported 2 genesis epochs. The bug is solved by checking that the already imported epochs are not all genesis epochs. --- client/consensus/epochs/src/lib.rs | 81 +++++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 2 deletions(-) diff --git a/client/consensus/epochs/src/lib.rs b/client/consensus/epochs/src/lib.rs index 661cb900ae6e..c1d0bd1d0405 100644 --- a/client/consensus/epochs/src/lib.rs +++ b/client/consensus/epochs/src/lib.rs @@ -229,13 +229,20 @@ impl ViableEpochDescriptor { /// Persisted epoch stored in EpochChanges. #[derive(Clone, Encode, Decode, Debug)] -pub enum PersistedEpoch { +pub enum PersistedEpoch { /// Genesis persisted epoch data. epoch_0, epoch_1. Genesis(E, E), /// Regular persisted epoch data. epoch_n. Regular(E), } +impl PersistedEpoch { + /// Returns if this is a genesis epoch. + pub fn is_genesis(&self) -> bool { + matches!(self, Self::Genesis(_, _)) + } +} + impl<'a, E: Epoch> From<&'a PersistedEpoch> for PersistedEpochHeader { fn from(epoch: &'a PersistedEpoch) -> Self { match epoch { @@ -748,7 +755,7 @@ where Err(e) => PersistedEpoch::Regular(e), } } - } else if !self.epochs.is_empty() && matches!(epoch, PersistedEpoch::Genesis(_, _)) { + } else if epoch.is_genesis() && !self.epochs.values().all(|e| e.is_genesis()) { // There's a genesis epoch imported when we already have an active epoch. // This happens after the warp sync as the ancient blocks download start. // We need to start tracking gap epochs here. @@ -1073,6 +1080,76 @@ mod tests { } } + /// Test that ensures that the gap is not enabled when we import multiple genesis blocks. + #[test] + fn gap_is_not_enabled_when_multiple_genesis_epochs_are_imported() { + // X + // / + // 0 - A + // + let is_descendent_of = |base: &Hash, block: &Hash| -> Result { + match (base, *block) { + (b"0", _) => Ok(true), + _ => Ok(false), + } + }; + + let duration = 100; + + let make_genesis = |slot| Epoch { start_slot: slot, duration }; + + let mut epoch_changes = EpochChanges::new(); + let next_descriptor = (); + + // insert genesis epoch for A + { + let genesis_epoch_a_descriptor = epoch_changes + .epoch_descriptor_for_child_of(&is_descendent_of, b"0", 0, 100) + .unwrap() + .unwrap(); + + let incremented_epoch = epoch_changes + .viable_epoch(&genesis_epoch_a_descriptor, &make_genesis) + .unwrap() + .increment(next_descriptor.clone()); + + epoch_changes + .import(&is_descendent_of, *b"A", 1, *b"0", incremented_epoch) + .unwrap(); + } + + // insert genesis epoch for X + { + let genesis_epoch_x_descriptor = epoch_changes + .epoch_descriptor_for_child_of(&is_descendent_of, b"0", 0, 1000) + .unwrap() + .unwrap(); + + let incremented_epoch = epoch_changes + .viable_epoch(&genesis_epoch_x_descriptor, &make_genesis) + .unwrap() + .increment(next_descriptor.clone()); + + epoch_changes + .import(&is_descendent_of, *b"X", 1, *b"0", incremented_epoch) + .unwrap(); + } + + // Clearing the gap should be a no-op. + epoch_changes.clear_gap(); + + // Check that both epochs are available. + epoch_changes + .epoch_data_for_child_of(&is_descendent_of, b"A", 1, 101, &make_genesis) + .unwrap() + .unwrap(); + + epoch_changes + .epoch_data_for_child_of(&is_descendent_of, b"X", 1, 1001, &make_genesis) + .unwrap() + .unwrap(); + } + #[test] fn gap_epochs_advance() { // 0 - 1 - 2 - 3 - .... 42 - 43 From 9d01cac45bb4db09f60eef98a26e28a408f5e0ca Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Oct 2021 19:17:15 +0200 Subject: [PATCH 081/695] Bump retain_mut from 0.1.3 to 0.1.4 (#10021) Bumps [retain_mut](https://github.com/upsuper/retain_mut) from 0.1.3 to 0.1.4. - [Release notes](https://github.com/upsuper/retain_mut/releases) - [Commits](https://github.com/upsuper/retain_mut/commits) --- updated-dependencies: - dependency-name: retain_mut dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- client/consensus/babe/Cargo.toml | 2 +- client/transaction-pool/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 50a962983f28..74aa1e23a171 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7238,9 +7238,9 @@ dependencies = [ [[package]] name = "retain_mut" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9c17925a9027d298a4603d286befe3f9dc0e8ed02523141914eb628798d6e5b" +checksum = "448296241d034b96c11173591deaa1302f2c17b56092106c1f92c1bc0183a8c9" [[package]] name = "ring" diff --git a/client/consensus/babe/Cargo.toml b/client/consensus/babe/Cargo.toml index 65dfc5713320..dc937f1e3dbc 100644 --- a/client/consensus/babe/Cargo.toml +++ b/client/consensus/babe/Cargo.toml @@ -50,7 +50,7 @@ schnorrkel = { version = "0.9.1", features = ["preaudit_deprecated"] } rand = "0.7.2" merlin = "2.0" derive_more = "0.99.2" -retain_mut = "0.1.3" +retain_mut = "0.1.4" async-trait = "0.1.50" [dev-dependencies] diff --git a/client/transaction-pool/Cargo.toml b/client/transaction-pool/Cargo.toml index 2184af819adf..0871cadd5a02 100644 --- a/client/transaction-pool/Cargo.toml +++ b/client/transaction-pool/Cargo.toml @@ -32,7 +32,7 @@ sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sc-utils = { version = "4.0.0-dev", path = "../utils" } serde = { version = "1.0.126", features = ["derive"] } linked-hash-map = "0.5.4" -retain_mut = "0.1.3" +retain_mut = "0.1.4" [dev-dependencies] assert_matches = "1.3.0" From 30ee840367cae0b965ad9f3d0714cfafbe8d8511 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Oct 2021 18:36:29 +0000 Subject: [PATCH 082/695] Bump base58 from 0.1.0 to 0.2.0 (#10018) Bumps [base58](https://github.com/debris/base58) from 0.1.0 to 0.2.0. - [Release notes](https://github.com/debris/base58/releases) - [Commits](https://github.com/debris/base58/commits) --- updated-dependencies: - dependency-name: base58 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- primitives/core/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 74aa1e23a171..f15e363bfd6a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -440,9 +440,9 @@ checksum = "a4521f3e3d031370679b3b140beb36dfe4801b09ac77e30c61941f97df3ef28b" [[package]] name = "base58" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5024ee8015f02155eee35c711107ddd9a9bf3cb689cf2a9089c97e79b6e1ae83" +checksum = "6107fe1be6682a68940da878d9e9f5e90ca5745b3dec9fd1bb393c8777d4f581" [[package]] name = "base64" diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index 0944fbef2334..4071dab71be5 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -30,7 +30,7 @@ impl-serde = { version = "0.3.0", optional = true } wasmi = { version = "0.9.0", optional = true } hash-db = { version = "0.15.2", default-features = false } hash256-std-hasher = { version = "0.15.2", default-features = false } -base58 = { version = "0.1.0", optional = true } +base58 = { version = "0.2.0", optional = true } rand = { version = "0.7.3", optional = true, features = ["small_rng"] } substrate-bip39 = { version = "0.4.2", optional = true } tiny-bip39 = { version = "0.8.2", optional = true } From 383a26c15058efcb6c0fe27fdd101efebefd3860 Mon Sep 17 00:00:00 2001 From: Dan Shields <35669742+NukeManDan@users.noreply.github.com> Date: Wed, 13 Oct 2021 12:55:51 -0600 Subject: [PATCH 083/695] Move template to `homepage = "https://substrate.io/"` , correct links (#10006) * move to https://docs.substrate.io/ * cargo to https://docs.substrate.io/ homepage * Update bin/node-template/pallets/template/src/lib.rs Co-authored-by: Squirrel * homepage = "https://docs.substrate.io/" Co-authored-by: Squirrel --- bin/node-template/README.md | 38 +++++++++---------- bin/node-template/docs/rust-setup.md | 5 ++- bin/node-template/node/Cargo.toml | 2 +- bin/node-template/pallets/template/Cargo.toml | 2 +- bin/node-template/pallets/template/src/lib.rs | 10 ++--- bin/node-template/runtime/Cargo.toml | 2 +- bin/node-template/runtime/src/lib.rs | 2 +- 7 files changed, 31 insertions(+), 30 deletions(-) diff --git a/bin/node-template/README.md b/bin/node-template/README.md index e618b13c2a2f..2397c57363b7 100644 --- a/bin/node-template/README.md +++ b/bin/node-template/README.md @@ -1,14 +1,14 @@ # Substrate Node Template -[![Try on playground](https://img.shields.io/badge/Playground-Node_Template-brightgreen?logo=Parity%20Substrate)](https://playground.substrate.dev/?deploy=node-template) [![Matrix](https://img.shields.io/matrix/substrate-technical:matrix.org)](https://matrix.to/#/#substrate-technical:matrix.org) +[![Try on playground](https://img.shields.io/badge/Playground-Node_Template-brightgreen?logo=Parity%20Substrate)](https://docs.substrate.io/playground/) [![Matrix](https://img.shields.io/matrix/substrate-technical:matrix.org)](https://matrix.to/#/#substrate-technical:matrix.org) A fresh FRAME-based [Substrate](https://www.substrate.io/) node, ready for hacking :rocket: ## Getting Started Follow the steps below to get started with the Node Template, or get it up and running right from -your browser in just a few clicks using [Playground](https://playground.substrate.dev/) -:hammer_and_wrench: +your browser in just a few clicks using +the [Substrate Playground](https://docs.substrate.io/playground/) :hammer_and_wrench: ### Using Nix @@ -19,7 +19,7 @@ lorri `lorri shell`. ### Rust Setup -First, complete the [basic Rust setup instructions](./doc/rust-setup.md). +First, complete the [basic Rust setup instructions](./docs/rust-setup.md). ### Run @@ -83,7 +83,7 @@ local node template. ### Multi-Node Local Testnet If you want to see the multi-node consensus algorithm in action, refer to our -[Start a Private Network tutorial](https://substrate.dev/docs/en/tutorials/start-a-private-network/). +[Start a Private Network tutorial](https://docs.substrate.io/tutorials/v3/private-network). ## Template Structure @@ -98,7 +98,7 @@ Substrate-based blockchain nodes expose a number of capabilities: - Networking: Substrate nodes use the [`libp2p`](https://libp2p.io/) networking stack to allow the nodes in the network to communicate with one another. - Consensus: Blockchains must have a way to come to - [consensus](https://substrate.dev/docs/en/knowledgebase/advanced/consensus) on the state of the + [consensus](https://docs.substrate.io/v3/advanced/consensus) on the state of the network. Substrate makes it possible to supply custom consensus engines and also ships with several consensus mechanisms that have been built on top of [Web3 Foundation research](https://research.web3.foundation/en/latest/polkadot/NPoS/index.html). @@ -107,21 +107,21 @@ Substrate-based blockchain nodes expose a number of capabilities: There are several files in the `node` directory - take special note of the following: - [`chain_spec.rs`](./node/src/chain_spec.rs): A - [chain specification](https://substrate.dev/docs/en/knowledgebase/integrate/chain-spec) is a + [chain specification](https://docs.substrate.io/v3/runtime/chain-specs) is a source code file that defines a Substrate chain's initial (genesis) state. Chain specifications are useful for development and testing, and critical when architecting the launch of a production chain. Take note of the `development_config` and `testnet_genesis` functions, which are used to define the genesis state for the local development chain configuration. These functions identify some - [well-known accounts](https://substrate.dev/docs/en/knowledgebase/integrate/subkey#well-known-keys) + [well-known accounts](https://docs.substrate.io/v3/tools/subkey#well-known-keys) and use them to configure the blockchain's initial state. - [`service.rs`](./node/src/service.rs): This file defines the node implementation. Take note of the libraries that this file imports and the names of the functions it invokes. In particular, there are references to consensus-related topics, such as the - [longest chain rule](https://substrate.dev/docs/en/knowledgebase/advanced/consensus#longest-chain-rule), - the [Aura](https://substrate.dev/docs/en/knowledgebase/advanced/consensus#aura) block authoring + [longest chain rule](https://docs.substrate.io/v3/advanced/consensus#longest-chain-rule), + the [Aura](https://docs.substrate.io/v3/advanced/consensus#aura) block authoring mechanism and the - [GRANDPA](https://substrate.dev/docs/en/knowledgebase/advanced/consensus#grandpa) finality + [GRANDPA](https://docs.substrate.io/v3/advanced/consensus#grandpa) finality gadget. After the node has been [built](#build), refer to the embedded documentation to learn more about the @@ -134,14 +134,14 @@ capabilities and configuration parameters that it exposes: ### Runtime In Substrate, the terms -"[runtime](https://substrate.dev/docs/en/knowledgebase/getting-started/glossary#runtime)" and -"[state transition function](https://substrate.dev/docs/en/knowledgebase/getting-started/glossary#stf-state-transition-function)" +"[runtime](https://docs.substrate.io/v3/getting-started/glossary#runtime)" and +"[state transition function](https://docs.substrate.io/v3/getting-started/glossary#state-transition-function-stf)" are analogous - they refer to the core logic of the blockchain that is responsible for validating blocks and executing the state changes they define. The Substrate project in this repository uses -the [FRAME](https://substrate.dev/docs/en/knowledgebase/runtime/frame) framework to construct a +the [FRAME](https://docs.substrate.io/v3/runtime/frame) framework to construct a blockchain runtime. FRAME allows runtime developers to declare domain-specific logic in modules called "pallets". At the heart of FRAME is a helpful -[macro language](https://substrate.dev/docs/en/knowledgebase/runtime/macros) that makes it easy to +[macro language](https://docs.substrate.io/v3/runtime/macros) that makes it easy to create pallets and flexibly compose them to create blockchains that can address [a variety of needs](https://www.substrate.io/substrate-users/). @@ -153,7 +153,7 @@ the following: - The pallets are composed into a single runtime by way of the [`construct_runtime!`](https://crates.parity.io/frame_support/macro.construct_runtime.html) macro, which is part of the core - [FRAME Support](https://substrate.dev/docs/en/knowledgebase/runtime/frame#support-library) + [FRAME Support](https://docs.substrate.io/v3/runtime/frame#support-crate) library. ### Pallets @@ -165,13 +165,13 @@ template pallet that is [defined in the `pallets`](./pallets/template/src/lib.rs A FRAME pallet is compromised of a number of blockchain primitives: - Storage: FRAME defines a rich set of powerful - [storage abstractions](https://substrate.dev/docs/en/knowledgebase/runtime/storage) that makes + [storage abstractions](https://docs.substrate.io/v3/runtime/storage) that makes it easy to use Substrate's efficient key-value database to manage the evolving state of a blockchain. - Dispatchables: FRAME pallets define special types of functions that can be invoked (dispatched) from outside of the runtime in order to update its state. -- Events: Substrate uses [events](https://substrate.dev/docs/en/knowledgebase/runtime/events) to - notify users of important changes in the runtime. +- Events: Substrate uses [events and errors](https://docs.substrate.io/v3/runtime/events-and-errors) + to notify users of important changes in the runtime. - Errors: When a dispatchable fails, it returns an error. - Config: The `Config` configuration interface is used to define the types and parameters upon which a FRAME pallet depends. diff --git a/bin/node-template/docs/rust-setup.md b/bin/node-template/docs/rust-setup.md index 34f6e43e7f0d..4b96da1146b8 100644 --- a/bin/node-template/docs/rust-setup.md +++ b/bin/node-template/docs/rust-setup.md @@ -12,8 +12,9 @@ commands for Rust's toolchains will be the same for all supported, Unix-based op ## Unix-Based Operating Systems Substrate development is easiest on Unix-based operating systems like macOS or Linux. The examples -in the Substrate [Tutorials](https://substrate.dev/tutorials) and [Recipes](https://substrate.dev/recipes/) -use Unix-style terminals to demonstrate how to interact with Substrate from the command line. +in the Substrate [Tutorials](https://docs.substrate.io/tutorials/v3) and +[How-to Guides](https://docs.substrate.io/how-to-guides/v3) use Unix-style terminals to demonstrate +how to interact with Substrate from the command line. ### macOS diff --git a/bin/node-template/node/Cargo.toml b/bin/node-template/node/Cargo.toml index c8f2b52f112f..57d9c5f3f71e 100644 --- a/bin/node-template/node/Cargo.toml +++ b/bin/node-template/node/Cargo.toml @@ -3,7 +3,7 @@ name = "node-template" version = "3.0.0" description = "A fresh FRAME-based Substrate node, ready for hacking." authors = ["Substrate DevHub "] -homepage = "https://substrate.dev" +homepage = "https://substrate.io/" edition = "2018" license = "Unlicense" publish = false diff --git a/bin/node-template/pallets/template/Cargo.toml b/bin/node-template/pallets/template/Cargo.toml index dccb37c6540c..7ea5628b97c1 100644 --- a/bin/node-template/pallets/template/Cargo.toml +++ b/bin/node-template/pallets/template/Cargo.toml @@ -3,7 +3,7 @@ name = 'pallet-template' version = "3.0.0" description = "FRAME pallet template for defining custom runtime logic." authors = ['Substrate DevHub '] -homepage = "https://substrate.dev" +homepage = "https://substrate.io/" edition = '2018' license = "Unlicense" publish = false diff --git a/bin/node-template/pallets/template/src/lib.rs b/bin/node-template/pallets/template/src/lib.rs index ee3ca695b64d..18599168f1a6 100644 --- a/bin/node-template/pallets/template/src/lib.rs +++ b/bin/node-template/pallets/template/src/lib.rs @@ -2,7 +2,7 @@ /// Edit this file to define custom logic or remove it if it is not needed. /// Learn more about FRAME and the core library of Substrate FRAME pallets: -/// +/// pub use pallet::*; #[cfg(test)] @@ -31,15 +31,15 @@ pub mod pallet { pub struct Pallet(_); // The pallet's runtime storage items. - // https://substrate.dev/docs/en/knowledgebase/runtime/storage + // https://docs.substrate.io/v3/runtime/storage #[pallet::storage] #[pallet::getter(fn something)] // Learn more about declaring storage items: - // https://substrate.dev/docs/en/knowledgebase/runtime/storage#declaring-storage-items + // https://docs.substrate.io/v3/runtime/storage#declaring-storage-items pub type Something = StorageValue<_, u32>; // Pallets use events to inform users when important changes are made. - // https://substrate.dev/docs/en/knowledgebase/runtime/events + // https://docs.substrate.io/v3/runtime/events-and-errors #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { @@ -68,7 +68,7 @@ pub mod pallet { pub fn do_something(origin: OriginFor, something: u32) -> DispatchResult { // Check that the extrinsic was signed and get the signer. // This function will return an error if the extrinsic is not signed. - // https://substrate.dev/docs/en/knowledgebase/runtime/origin + // https://docs.substrate.io/v3/runtime/origins let who = ensure_signed(origin)?; // Update storage. diff --git a/bin/node-template/runtime/Cargo.toml b/bin/node-template/runtime/Cargo.toml index 3179a2cc4ff5..e9f557f3fb5a 100644 --- a/bin/node-template/runtime/Cargo.toml +++ b/bin/node-template/runtime/Cargo.toml @@ -3,7 +3,7 @@ name = "node-template-runtime" version = "3.0.0" description = 'A fresh FRAME-based Substrate runtime, ready for hacking.' authors = ["Substrate DevHub "] -homepage = "https://substrate.dev" +homepage = "https://substrate.io/" edition = "2018" license = "Unlicense" publish = false diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index e11840b5813d..4b49cb48ef35 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -87,7 +87,7 @@ pub mod opaque { } // To learn more about runtime versioning and what each of the following value means: -// https://substrate.dev/docs/en/knowledgebase/runtime/upgrades#runtime-versioning +// https://docs.substrate.io/v3/runtime/upgrades#runtime-versioning #[sp_version::runtime_version] pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("node-template"), From 66296a0af0aede07c27104e6174a3534b15f14aa Mon Sep 17 00:00:00 2001 From: Dan Shields <35669742+NukeManDan@users.noreply.github.com> Date: Wed, 13 Oct 2021 12:56:56 -0600 Subject: [PATCH 084/695] Migrate to `docs.substrate.io` throughout (#10007) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * all reverences of substrate.dev replaced with *correct* docs.substrate.io links * fix links in non-cargo files, errors in replace * homepage https://substrate.io * cargo +nightly fmt * FMT Co-authored-by: Bastian Köcher --- README.md | 6 +++--- bin/node/cli/Cargo.toml | 2 +- bin/node/executor/Cargo.toml | 2 +- bin/node/inspect/Cargo.toml | 2 +- bin/node/primitives/Cargo.toml | 2 +- bin/node/rpc-client/Cargo.toml | 2 +- bin/node/rpc/Cargo.toml | 2 +- bin/node/runtime/Cargo.toml | 2 +- bin/node/testing/Cargo.toml | 2 +- bin/utils/chain-spec-builder/Cargo.toml | 2 +- bin/utils/subkey/Cargo.toml | 2 +- client/allocator/Cargo.toml | 2 +- client/api/Cargo.toml | 2 +- client/authority-discovery/Cargo.toml | 2 +- client/basic-authorship/Cargo.toml | 2 +- client/block-builder/Cargo.toml | 2 +- client/chain-spec/Cargo.toml | 2 +- client/chain-spec/derive/Cargo.toml | 2 +- client/cli/Cargo.toml | 2 +- client/consensus/aura/Cargo.toml | 2 +- client/consensus/babe/Cargo.toml | 2 +- client/consensus/babe/rpc/Cargo.toml | 2 +- client/consensus/common/Cargo.toml | 2 +- client/consensus/epochs/Cargo.toml | 2 +- client/consensus/manual-seal/Cargo.toml | 2 +- client/consensus/pow/Cargo.toml | 2 +- client/consensus/slots/Cargo.toml | 2 +- client/consensus/uncles/Cargo.toml | 2 +- client/db/Cargo.toml | 2 +- client/executor/Cargo.toml | 2 +- client/executor/common/Cargo.toml | 2 +- client/executor/runtime-test/Cargo.toml | 2 +- client/executor/wasmi/Cargo.toml | 2 +- client/executor/wasmtime/Cargo.toml | 2 +- client/finality-grandpa-warp-sync/Cargo.toml | 2 +- client/finality-grandpa/Cargo.toml | 2 +- client/informant/Cargo.toml | 2 +- client/keystore/Cargo.toml | 2 +- client/light/Cargo.toml | 2 +- client/network-gossip/Cargo.toml | 2 +- client/network/Cargo.toml | 2 +- client/network/src/service.rs | 5 +++-- client/network/test/Cargo.toml | 2 +- client/offchain/Cargo.toml | 2 +- client/proposer-metrics/Cargo.toml | 2 +- client/rpc-api/Cargo.toml | 2 +- client/rpc-api/src/state/mod.rs | 2 +- client/rpc-servers/Cargo.toml | 2 +- client/rpc/Cargo.toml | 2 +- client/service/Cargo.toml | 2 +- client/service/test/Cargo.toml | 2 +- client/state-db/Cargo.toml | 2 +- client/sync-state-rpc/Cargo.toml | 2 +- client/telemetry/Cargo.toml | 2 +- client/tracing/Cargo.toml | 2 +- client/tracing/proc-macro/Cargo.toml | 2 +- client/transaction-pool/Cargo.toml | 2 +- client/transaction-pool/api/Cargo.toml | 2 +- client/utils/Cargo.toml | 2 +- frame/assets/Cargo.toml | 2 +- frame/atomic-swap/Cargo.toml | 2 +- frame/aura/Cargo.toml | 2 +- frame/authority-discovery/Cargo.toml | 2 +- frame/authorship/Cargo.toml | 2 +- frame/babe/Cargo.toml | 2 +- frame/bags-list/Cargo.toml | 2 +- frame/balances/Cargo.toml | 2 +- frame/benchmarking/Cargo.toml | 2 +- frame/bounties/Cargo.toml | 2 +- frame/collective/Cargo.toml | 2 +- frame/contracts/Cargo.toml | 2 +- frame/contracts/README.md | 2 +- frame/contracts/common/Cargo.toml | 2 +- frame/contracts/proc-macro/Cargo.toml | 2 +- frame/contracts/rpc/Cargo.toml | 2 +- frame/contracts/rpc/runtime-api/Cargo.toml | 2 +- frame/democracy/Cargo.toml | 2 +- frame/election-provider-multi-phase/Cargo.toml | 2 +- frame/election-provider-support/Cargo.toml | 2 +- frame/elections-phragmen/Cargo.toml | 2 +- frame/elections/Cargo.toml | 2 +- frame/example-offchain-worker/Cargo.toml | 2 +- frame/example-parallel/Cargo.toml | 2 +- frame/example/Cargo.toml | 2 +- frame/example/src/benchmarking.rs | 4 ++-- frame/example/src/lib.rs | 6 +++--- frame/executive/Cargo.toml | 2 +- frame/gilt/Cargo.toml | 2 +- frame/grandpa/Cargo.toml | 2 +- frame/identity/Cargo.toml | 2 +- frame/im-online/Cargo.toml | 2 +- frame/indices/Cargo.toml | 2 +- frame/lottery/Cargo.toml | 2 +- frame/membership/Cargo.toml | 2 +- frame/merkle-mountain-range/Cargo.toml | 2 +- frame/merkle-mountain-range/primitives/Cargo.toml | 2 +- frame/merkle-mountain-range/rpc/Cargo.toml | 2 +- frame/multisig/Cargo.toml | 2 +- frame/nicks/Cargo.toml | 2 +- frame/node-authorization/Cargo.toml | 2 +- frame/offences/Cargo.toml | 2 +- frame/offences/benchmarking/Cargo.toml | 2 +- frame/proxy/Cargo.toml | 2 +- frame/randomness-collective-flip/Cargo.toml | 2 +- frame/recovery/Cargo.toml | 2 +- frame/scheduler/Cargo.toml | 2 +- frame/scored-pool/Cargo.toml | 2 +- frame/session/Cargo.toml | 2 +- frame/session/benchmarking/Cargo.toml | 2 +- frame/society/Cargo.toml | 2 +- frame/staking/Cargo.toml | 2 +- frame/staking/reward-curve/Cargo.toml | 2 +- frame/staking/reward-fn/Cargo.toml | 2 +- frame/sudo/Cargo.toml | 2 +- frame/sudo/README.md | 2 +- frame/sudo/src/lib.rs | 2 +- frame/support/Cargo.toml | 2 +- frame/support/procedural/Cargo.toml | 2 +- frame/support/procedural/src/pallet/expand/error.rs | 2 +- frame/support/procedural/src/pallet/expand/event.rs | 2 +- .../support/procedural/src/pallet/expand/genesis_config.rs | 2 +- frame/support/procedural/src/pallet/expand/mod.rs | 4 ++-- frame/support/procedural/src/pallet/expand/pallet_struct.rs | 2 +- frame/support/procedural/tools/Cargo.toml | 2 +- frame/support/procedural/tools/derive/Cargo.toml | 2 +- frame/support/src/dispatch.rs | 2 +- frame/support/src/storage/bounded_vec.rs | 2 +- frame/support/src/storage/weak_bounded_vec.rs | 2 +- frame/support/src/traits/misc.rs | 2 +- frame/support/test/Cargo.toml | 2 +- frame/support/test/pallet/Cargo.toml | 2 +- frame/system/Cargo.toml | 2 +- frame/system/benchmarking/Cargo.toml | 2 +- frame/system/rpc/runtime-api/Cargo.toml | 2 +- frame/timestamp/Cargo.toml | 2 +- frame/tips/Cargo.toml | 2 +- frame/transaction-payment/Cargo.toml | 2 +- frame/transaction-payment/rpc/Cargo.toml | 2 +- frame/transaction-payment/rpc/runtime-api/Cargo.toml | 2 +- frame/transaction-storage/Cargo.toml | 2 +- frame/treasury/Cargo.toml | 2 +- frame/try-runtime/Cargo.toml | 2 +- frame/uniques/Cargo.toml | 2 +- frame/utility/Cargo.toml | 2 +- frame/vesting/Cargo.toml | 2 +- primitives/api/Cargo.toml | 2 +- primitives/api/proc-macro/Cargo.toml | 2 +- primitives/api/test/Cargo.toml | 2 +- primitives/application-crypto/Cargo.toml | 2 +- primitives/application-crypto/test/Cargo.toml | 2 +- primitives/arithmetic/Cargo.toml | 2 +- primitives/arithmetic/fuzzer/Cargo.toml | 2 +- primitives/authority-discovery/Cargo.toml | 2 +- primitives/authorship/Cargo.toml | 2 +- primitives/block-builder/Cargo.toml | 2 +- primitives/blockchain/Cargo.toml | 2 +- primitives/consensus/aura/Cargo.toml | 2 +- primitives/consensus/babe/Cargo.toml | 2 +- primitives/consensus/common/Cargo.toml | 2 +- primitives/consensus/pow/Cargo.toml | 2 +- primitives/consensus/slots/Cargo.toml | 2 +- primitives/consensus/vrf/Cargo.toml | 2 +- primitives/core/Cargo.toml | 2 +- primitives/database/Cargo.toml | 2 +- primitives/debug-derive/Cargo.toml | 2 +- primitives/externalities/Cargo.toml | 2 +- primitives/finality-grandpa/Cargo.toml | 2 +- primitives/inherents/Cargo.toml | 2 +- primitives/io/Cargo.toml | 2 +- primitives/keyring/Cargo.toml | 2 +- primitives/keystore/Cargo.toml | 2 +- primitives/maybe-compressed-blob/Cargo.toml | 2 +- primitives/npos-elections/Cargo.toml | 2 +- primitives/npos-elections/fuzzer/Cargo.toml | 2 +- primitives/npos-elections/solution-type/Cargo.toml | 2 +- primitives/offchain/Cargo.toml | 2 +- primitives/panic-handler/Cargo.toml | 2 +- primitives/rpc/Cargo.toml | 2 +- primitives/runtime-interface/Cargo.toml | 2 +- primitives/runtime-interface/proc-macro/Cargo.toml | 2 +- .../runtime-interface/test-wasm-deprecated/Cargo.toml | 2 +- primitives/runtime-interface/test-wasm/Cargo.toml | 2 +- primitives/runtime-interface/test/Cargo.toml | 2 +- primitives/runtime/Cargo.toml | 2 +- primitives/sandbox/Cargo.toml | 2 +- primitives/serializer/Cargo.toml | 2 +- primitives/session/Cargo.toml | 2 +- primitives/staking/Cargo.toml | 2 +- primitives/state-machine/Cargo.toml | 2 +- primitives/std/Cargo.toml | 2 +- primitives/storage/Cargo.toml | 2 +- primitives/tasks/Cargo.toml | 2 +- primitives/test-primitives/Cargo.toml | 2 +- primitives/timestamp/Cargo.toml | 2 +- primitives/tracing/Cargo.toml | 2 +- primitives/transaction-pool/Cargo.toml | 2 +- primitives/transaction-storage-proof/Cargo.toml | 2 +- primitives/trie/Cargo.toml | 2 +- primitives/version/Cargo.toml | 2 +- primitives/version/proc-macro/Cargo.toml | 2 +- primitives/wasm-interface/Cargo.toml | 2 +- ss58-registry.json | 2 +- test-utils/Cargo.toml | 2 +- test-utils/client/Cargo.toml | 2 +- test-utils/derive/Cargo.toml | 2 +- test-utils/runtime/Cargo.toml | 2 +- test-utils/runtime/client/Cargo.toml | 2 +- test-utils/runtime/transaction-pool/Cargo.toml | 2 +- test-utils/test-crate/Cargo.toml | 2 +- utils/build-script-utils/Cargo.toml | 2 +- utils/fork-tree/Cargo.toml | 2 +- utils/frame/benchmarking-cli/Cargo.toml | 2 +- utils/frame/frame-utilities-cli/Cargo.toml | 2 +- utils/frame/generate-bags/Cargo.toml | 2 +- utils/frame/generate-bags/node-runtime/Cargo.toml | 2 +- utils/frame/remote-externalities/Cargo.toml | 2 +- utils/frame/rpc/support/Cargo.toml | 2 +- utils/frame/rpc/system/Cargo.toml | 2 +- utils/frame/try-runtime/cli/Cargo.toml | 2 +- utils/frame/try-runtime/cli/src/lib.rs | 4 ++-- utils/prometheus/Cargo.toml | 2 +- utils/wasm-builder/Cargo.toml | 2 +- 222 files changed, 231 insertions(+), 230 deletions(-) diff --git a/README.md b/README.md index a4d0b9c68357..b716794428a0 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,9 @@ Substrate is a next-generation framework for blockchain innovation 🚀. ## Trying it out -Simply go to [substrate.dev](https://substrate.dev) and follow the -[installation](https://substrate.dev/docs/en/knowledgebase/getting-started/) instructions. You can -also try out one of the [tutorials](https://substrate.dev/en/tutorials). +Simply go to [docs.substrate.io](https://docs.substrate.io) and follow the +[installation](https://docs.substrate.io/v3/getting-started/overview) instructions. You can +also try out one of the [tutorials](https://docs.substrate.io/tutorials/). ## Contributions & Code of Conduct diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index a92c7a185b7a..1d394dd952db 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -7,7 +7,7 @@ build = "build.rs" edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" default-run = "substrate" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" [package.metadata.wasm-pack.profile.release] diff --git a/bin/node/executor/Cargo.toml b/bin/node/executor/Cargo.toml index f283a913915f..462bb034610e 100644 --- a/bin/node/executor/Cargo.toml +++ b/bin/node/executor/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] description = "Substrate node implementation in Rust." edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" [package.metadata.docs.rs] diff --git a/bin/node/inspect/Cargo.toml b/bin/node/inspect/Cargo.toml index 1570e5dbf8e4..6f526b896ba7 100644 --- a/bin/node/inspect/Cargo.toml +++ b/bin/node/inspect/Cargo.toml @@ -4,7 +4,7 @@ version = "0.9.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" [package.metadata.docs.rs] diff --git a/bin/node/primitives/Cargo.toml b/bin/node/primitives/Cargo.toml index 12ec57e4d55b..07c3aca6059f 100644 --- a/bin/node/primitives/Cargo.toml +++ b/bin/node/primitives/Cargo.toml @@ -4,7 +4,7 @@ version = "2.0.0" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" [package.metadata.docs.rs] diff --git a/bin/node/rpc-client/Cargo.toml b/bin/node/rpc-client/Cargo.toml index a5255769158a..59695edb6fa2 100644 --- a/bin/node/rpc-client/Cargo.toml +++ b/bin/node/rpc-client/Cargo.toml @@ -4,7 +4,7 @@ version = "2.0.0" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" [package.metadata.docs.rs] diff --git a/bin/node/rpc/Cargo.toml b/bin/node/rpc/Cargo.toml index 0cb606f79f08..4c7b15459cea 100644 --- a/bin/node/rpc/Cargo.toml +++ b/bin/node/rpc/Cargo.toml @@ -4,7 +4,7 @@ version = "3.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" [package.metadata.docs.rs] diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index b4e84aafec13..22ff0954e245 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] edition = "2018" build = "build.rs" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" [package.metadata.docs.rs] diff --git a/bin/node/testing/Cargo.toml b/bin/node/testing/Cargo.toml index d05d815121f8..e5d13189ac2f 100644 --- a/bin/node/testing/Cargo.toml +++ b/bin/node/testing/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] description = "Test utilities for Substrate node." edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" publish = true diff --git a/bin/utils/chain-spec-builder/Cargo.toml b/bin/utils/chain-spec-builder/Cargo.toml index 5bdf01badc3f..bfbf2da57a6a 100644 --- a/bin/utils/chain-spec-builder/Cargo.toml +++ b/bin/utils/chain-spec-builder/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] edition = "2018" build = "build.rs" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" readme = "README.md" publish = false diff --git a/bin/utils/subkey/Cargo.toml b/bin/utils/subkey/Cargo.toml index 9bd38a21a664..5e7615f60d62 100644 --- a/bin/utils/subkey/Cargo.toml +++ b/bin/utils/subkey/Cargo.toml @@ -4,7 +4,7 @@ version = "2.0.1" authors = ["Parity Technologies "] edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" readme = "README.md" publish = false diff --git a/client/allocator/Cargo.toml b/client/allocator/Cargo.toml index 5ebab6cf9d61..9383b88f756c 100644 --- a/client/allocator/Cargo.toml +++ b/client/allocator/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Collection of allocator implementations." documentation = "https://docs.rs/sc-allocator" diff --git a/client/api/Cargo.toml b/client/api/Cargo.toml index 772f22e822eb..af8704058b66 100644 --- a/client/api/Cargo.toml +++ b/client/api/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Substrate client interfaces." documentation = "https://docs.rs/sc-client-api" diff --git a/client/authority-discovery/Cargo.toml b/client/authority-discovery/Cargo.toml index 8d5ed20730f0..cee35a43df2f 100644 --- a/client/authority-discovery/Cargo.toml +++ b/client/authority-discovery/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] edition = "2018" build = "build.rs" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Substrate authority discovery." readme = "README.md" diff --git a/client/basic-authorship/Cargo.toml b/client/basic-authorship/Cargo.toml index 469df55cf023..1ecdb08eba48 100644 --- a/client/basic-authorship/Cargo.toml +++ b/client/basic-authorship/Cargo.toml @@ -4,7 +4,7 @@ version = "0.10.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Basic implementation of block-authoring logic." readme = "README.md" diff --git a/client/block-builder/Cargo.toml b/client/block-builder/Cargo.toml index 6fef8498134e..9d2703fc2ed2 100644 --- a/client/block-builder/Cargo.toml +++ b/client/block-builder/Cargo.toml @@ -4,7 +4,7 @@ version = "0.10.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Substrate block builder" readme = "README.md" diff --git a/client/chain-spec/Cargo.toml b/client/chain-spec/Cargo.toml index 8af2996e968d..78062e600c3f 100644 --- a/client/chain-spec/Cargo.toml +++ b/client/chain-spec/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Substrate chain configurations." readme = "README.md" diff --git a/client/chain-spec/derive/Cargo.toml b/client/chain-spec/derive/Cargo.toml index 89a51d95079a..73083e4a6e0b 100644 --- a/client/chain-spec/derive/Cargo.toml +++ b/client/chain-spec/derive/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Macros to derive chain spec extension traits implementation." diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index b32e985b518c..0cee37f25e79 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] description = "Substrate CLI interface." edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" readme = "README.md" diff --git a/client/consensus/aura/Cargo.toml b/client/consensus/aura/Cargo.toml index 75595779427b..1c767319b122 100644 --- a/client/consensus/aura/Cargo.toml +++ b/client/consensus/aura/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] description = "Aura consensus algorithm for substrate" edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" readme = "README.md" diff --git a/client/consensus/babe/Cargo.toml b/client/consensus/babe/Cargo.toml index dc937f1e3dbc..66ad6287f40d 100644 --- a/client/consensus/babe/Cargo.toml +++ b/client/consensus/babe/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] description = "BABE consensus algorithm for substrate" edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" documentation = "https://docs.rs/sc-consensus-babe" readme = "README.md" diff --git a/client/consensus/babe/rpc/Cargo.toml b/client/consensus/babe/rpc/Cargo.toml index 8d5625705a48..7ef9b1c1de3c 100644 --- a/client/consensus/babe/rpc/Cargo.toml +++ b/client/consensus/babe/rpc/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] description = "RPC extensions for the BABE consensus algorithm" edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" readme = "README.md" diff --git a/client/consensus/common/Cargo.toml b/client/consensus/common/Cargo.toml index 6829bd2c6d8b..30840a974f9a 100644 --- a/client/consensus/common/Cargo.toml +++ b/client/consensus/common/Cargo.toml @@ -4,7 +4,7 @@ version = "0.10.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Collection of common consensus specific imlementations for Substrate (client)" readme = "README.md" diff --git a/client/consensus/epochs/Cargo.toml b/client/consensus/epochs/Cargo.toml index 78e5cc31ea07..90a708d07e2a 100644 --- a/client/consensus/epochs/Cargo.toml +++ b/client/consensus/epochs/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] description = "Generic epochs-based utilities for consensus" edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" readme = "README.md" diff --git a/client/consensus/manual-seal/Cargo.toml b/client/consensus/manual-seal/Cargo.toml index d9ae8521c12f..9b29bb3dc71c 100644 --- a/client/consensus/manual-seal/Cargo.toml +++ b/client/consensus/manual-seal/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] description = "Manual sealing engine for Substrate" edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" readme = "README.md" diff --git a/client/consensus/pow/Cargo.toml b/client/consensus/pow/Cargo.toml index c71e11aef275..c570c1ccbad2 100644 --- a/client/consensus/pow/Cargo.toml +++ b/client/consensus/pow/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] description = "PoW consensus algorithm for substrate" edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" readme = "README.md" diff --git a/client/consensus/slots/Cargo.toml b/client/consensus/slots/Cargo.toml index 4c0142829bb5..6c1f865c62cb 100644 --- a/client/consensus/slots/Cargo.toml +++ b/client/consensus/slots/Cargo.toml @@ -6,7 +6,7 @@ description = "Generic slots-based utilities for consensus" edition = "2018" build = "build.rs" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" readme = "README.md" diff --git a/client/consensus/uncles/Cargo.toml b/client/consensus/uncles/Cargo.toml index 7e821db197b3..73768f0d0941 100644 --- a/client/consensus/uncles/Cargo.toml +++ b/client/consensus/uncles/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] description = "Generic uncle inclusion utilities for consensus" edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" readme = "README.md" diff --git a/client/db/Cargo.toml b/client/db/Cargo.toml index f9a81d6ce7ea..53af082d3b91 100644 --- a/client/db/Cargo.toml +++ b/client/db/Cargo.toml @@ -4,7 +4,7 @@ version = "0.10.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Client backend that uses RocksDB database as storage." readme = "README.md" diff --git a/client/executor/Cargo.toml b/client/executor/Cargo.toml index eeea57d83980..c8246d43a0f8 100644 --- a/client/executor/Cargo.toml +++ b/client/executor/Cargo.toml @@ -4,7 +4,7 @@ version = "0.10.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "A crate that provides means of executing/dispatching calls into the runtime." documentation = "https://docs.rs/sc-executor" diff --git a/client/executor/common/Cargo.toml b/client/executor/common/Cargo.toml index c4fc8c27f754..622baa6c0dca 100644 --- a/client/executor/common/Cargo.toml +++ b/client/executor/common/Cargo.toml @@ -4,7 +4,7 @@ version = "0.10.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "A set of common definitions that are needed for defining execution engines." documentation = "https://docs.rs/sc-executor-common/" diff --git a/client/executor/runtime-test/Cargo.toml b/client/executor/runtime-test/Cargo.toml index a4fbc88cf566..ac1e3413491d 100644 --- a/client/executor/runtime-test/Cargo.toml +++ b/client/executor/runtime-test/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" build = "build.rs" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" publish = false -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" [package.metadata.docs.rs] diff --git a/client/executor/wasmi/Cargo.toml b/client/executor/wasmi/Cargo.toml index 324b2bdd0bae..307ba908e23b 100644 --- a/client/executor/wasmi/Cargo.toml +++ b/client/executor/wasmi/Cargo.toml @@ -4,7 +4,7 @@ version = "0.10.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "This crate provides an implementation of `WasmRuntime` that is baked by wasmi." documentation = "https://docs.rs/sc-executor-wasmi" diff --git a/client/executor/wasmtime/Cargo.toml b/client/executor/wasmtime/Cargo.toml index a8ed01c203e3..9fb76ed08fd9 100644 --- a/client/executor/wasmtime/Cargo.toml +++ b/client/executor/wasmtime/Cargo.toml @@ -4,7 +4,7 @@ version = "0.10.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Defines a `WasmRuntime` that uses the Wasmtime JIT to execute." readme = "README.md" diff --git a/client/finality-grandpa-warp-sync/Cargo.toml b/client/finality-grandpa-warp-sync/Cargo.toml index a444125fdfa1..9736b25ccac5 100644 --- a/client/finality-grandpa-warp-sync/Cargo.toml +++ b/client/finality-grandpa-warp-sync/Cargo.toml @@ -5,7 +5,7 @@ version = "0.10.0-dev" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" authors = ["Parity Technologies "] edition = "2018" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" [package.metadata.docs.rs] diff --git a/client/finality-grandpa/Cargo.toml b/client/finality-grandpa/Cargo.toml index 45f85f46ddff..2d45fa100f79 100644 --- a/client/finality-grandpa/Cargo.toml +++ b/client/finality-grandpa/Cargo.toml @@ -4,7 +4,7 @@ version = "0.10.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Integration of the GRANDPA finality gadget into substrate." documentation = "https://docs.rs/sc-finality-grandpa" diff --git a/client/informant/Cargo.toml b/client/informant/Cargo.toml index 88d02f81ad5b..c28dd4e01194 100644 --- a/client/informant/Cargo.toml +++ b/client/informant/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] description = "Substrate informant." edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" readme = "README.md" diff --git a/client/keystore/Cargo.toml b/client/keystore/Cargo.toml index 17c651a91dec..74fd85c184c6 100644 --- a/client/keystore/Cargo.toml +++ b/client/keystore/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Keystore (and session key management) for ed25519 based chains like Polkadot." documentation = "https://docs.rs/sc-keystore" diff --git a/client/light/Cargo.toml b/client/light/Cargo.toml index b10f7646bf9b..cc567c60524a 100644 --- a/client/light/Cargo.toml +++ b/client/light/Cargo.toml @@ -5,7 +5,7 @@ version = "4.0.0-dev" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" authors = ["Parity Technologies "] edition = "2018" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" documentation = "https://docs.rs/sc-light" readme = "README.md" diff --git a/client/network-gossip/Cargo.toml b/client/network-gossip/Cargo.toml index a73bfb0c2657..b4907ade834a 100644 --- a/client/network-gossip/Cargo.toml +++ b/client/network-gossip/Cargo.toml @@ -5,7 +5,7 @@ version = "0.10.0-dev" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" authors = ["Parity Technologies "] edition = "2018" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" documentation = "https://docs.rs/sc-network-gossip" readme = "README.md" diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index 319bce4d0e6b..d6d054504369 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -5,7 +5,7 @@ version = "0.10.0-dev" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" authors = ["Parity Technologies "] edition = "2018" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" documentation = "https://docs.rs/sc-network" readme = "README.md" diff --git a/client/network/src/service.rs b/client/network/src/service.rs index be19b44f3a59..9b6e54f37a66 100644 --- a/client/network/src/service.rs +++ b/client/network/src/service.rs @@ -2023,8 +2023,9 @@ impl Future for NetworkWorker { .inc(); } }, - Poll::Ready(SwarmEvent::UnknownPeerUnreachableAddr { address, error }) => - trace!(target: "sub-libp2p", "Libp2p => UnknownPeerUnreachableAddr({}): {}", address, error), + Poll::Ready(SwarmEvent::UnknownPeerUnreachableAddr { address, error }) => { + trace!(target: "sub-libp2p", "Libp2p => UnknownPeerUnreachableAddr({}): {}", address, error) + }, Poll::Ready(SwarmEvent::ListenerClosed { reason, addresses, .. }) => { if let Some(metrics) = this.metrics.as_ref() { metrics.listeners_local_addresses.sub(addresses.len() as u64); diff --git a/client/network/test/Cargo.toml b/client/network/test/Cargo.toml index b4c3a74607f6..13555952cffd 100644 --- a/client/network/test/Cargo.toml +++ b/client/network/test/Cargo.toml @@ -6,7 +6,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" authors = ["Parity Technologies "] edition = "2018" publish = false -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" [package.metadata.docs.rs] diff --git a/client/offchain/Cargo.toml b/client/offchain/Cargo.toml index 641a1e55063d..146ce07e1303 100644 --- a/client/offchain/Cargo.toml +++ b/client/offchain/Cargo.toml @@ -5,7 +5,7 @@ version = "4.0.0-dev" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" authors = ["Parity Technologies "] edition = "2018" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" readme = "README.md" diff --git a/client/proposer-metrics/Cargo.toml b/client/proposer-metrics/Cargo.toml index ffe5045461f7..296329a5fda7 100644 --- a/client/proposer-metrics/Cargo.toml +++ b/client/proposer-metrics/Cargo.toml @@ -4,7 +4,7 @@ version = "0.9.0" authors = ["Parity Technologies "] edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Basic metrics for block production." readme = "README.md" diff --git a/client/rpc-api/Cargo.toml b/client/rpc-api/Cargo.toml index 6342abb1a3c4..192cf02e7ce1 100644 --- a/client/rpc-api/Cargo.toml +++ b/client/rpc-api/Cargo.toml @@ -4,7 +4,7 @@ version = "0.10.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Substrate RPC interfaces." readme = "README.md" diff --git a/client/rpc-api/src/state/mod.rs b/client/rpc-api/src/state/mod.rs index 620a000c500f..1cc191197232 100644 --- a/client/rpc-api/src/state/mod.rs +++ b/client/rpc-api/src/state/mod.rs @@ -301,7 +301,7 @@ pub trait StateApi { /// [substrate storage][1], [transparent keys in substrate][2], /// [querying substrate storage via rpc][3]. /// - /// [1]: https://substrate.dev/docs/en/knowledgebase/advanced/storage#storage-map-key + /// [1]: https://docs.substrate.io/v3/advanced/storage#storage-map-keys /// [2]: https://www.shawntabrizi.com/substrate/transparent-keys-in-substrate/ /// [3]: https://www.shawntabrizi.com/substrate/querying-substrate-storage-via-rpc/ /// diff --git a/client/rpc-servers/Cargo.toml b/client/rpc-servers/Cargo.toml index 26a05a8263dc..cbbea00d6f57 100644 --- a/client/rpc-servers/Cargo.toml +++ b/client/rpc-servers/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Substrate RPC servers." readme = "README.md" diff --git a/client/rpc/Cargo.toml b/client/rpc/Cargo.toml index 427800f74ddf..f5c7f99ff743 100644 --- a/client/rpc/Cargo.toml +++ b/client/rpc/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Substrate Client RPC" readme = "README.md" diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index 0a496a55adc4..589d7848a5b2 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -4,7 +4,7 @@ version = "0.10.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Substrate service. Starts a thread that spins up the network, client, and extrinsic pool. Manages communication between them." readme = "README.md" diff --git a/client/service/test/Cargo.toml b/client/service/test/Cargo.toml index fc42368a10ae..aeee4a5f9072 100644 --- a/client/service/test/Cargo.toml +++ b/client/service/test/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" publish = false -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" [package.metadata.docs.rs] diff --git a/client/state-db/Cargo.toml b/client/state-db/Cargo.toml index 93d5e1464b39..136fe7a199f0 100644 --- a/client/state-db/Cargo.toml +++ b/client/state-db/Cargo.toml @@ -4,7 +4,7 @@ version = "0.10.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "State database maintenance. Handles canonicalization and pruning in the database." readme = "README.md" diff --git a/client/sync-state-rpc/Cargo.toml b/client/sync-state-rpc/Cargo.toml index b81fd1fd5c61..4166929ff031 100644 --- a/client/sync-state-rpc/Cargo.toml +++ b/client/sync-state-rpc/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] description = "A RPC handler to create sync states for light clients." edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" readme = "README.md" diff --git a/client/telemetry/Cargo.toml b/client/telemetry/Cargo.toml index 0c5e2db6c776..502c7fc20781 100644 --- a/client/telemetry/Cargo.toml +++ b/client/telemetry/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] description = "Telemetry utils" edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" documentation = "https://docs.rs/sc-telemetry" readme = "README.md" diff --git a/client/tracing/Cargo.toml b/client/tracing/Cargo.toml index 5dfa3efa779e..b4049fa097ff 100644 --- a/client/tracing/Cargo.toml +++ b/client/tracing/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" authors = ["Parity Technologies "] edition = "2018" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Instrumentation implementation for substrate." readme = "README.md" diff --git a/client/tracing/proc-macro/Cargo.toml b/client/tracing/proc-macro/Cargo.toml index 42a0c739cd52..5cc2d836dcad 100644 --- a/client/tracing/proc-macro/Cargo.toml +++ b/client/tracing/proc-macro/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Helper macros for Substrate's client CLI" diff --git a/client/transaction-pool/Cargo.toml b/client/transaction-pool/Cargo.toml index 0871cadd5a02..12642559a3b8 100644 --- a/client/transaction-pool/Cargo.toml +++ b/client/transaction-pool/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Substrate transaction pool implementation." readme = "README.md" diff --git a/client/transaction-pool/api/Cargo.toml b/client/transaction-pool/api/Cargo.toml index efef36071f08..7dd1a6724ce5 100644 --- a/client/transaction-pool/api/Cargo.toml +++ b/client/transaction-pool/api/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Transaction pool client facing API." diff --git a/client/utils/Cargo.toml b/client/utils/Cargo.toml index 9b3c54974a76..546232cf6070 100644 --- a/client/utils/Cargo.toml +++ b/client/utils/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "I/O for Substrate runtimes" readme = "README.md" diff --git a/frame/assets/Cargo.toml b/frame/assets/Cargo.toml index 05e7912dd07c..65162430a2ac 100644 --- a/frame/assets/Cargo.toml +++ b/frame/assets/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME asset management pallet" readme = "README.md" diff --git a/frame/atomic-swap/Cargo.toml b/frame/atomic-swap/Cargo.toml index 53a8c3a81165..60e8fa613f06 100644 --- a/frame/atomic-swap/Cargo.toml +++ b/frame/atomic-swap/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME atomic swap pallet" readme = "README.md" diff --git a/frame/aura/Cargo.toml b/frame/aura/Cargo.toml index 8f5c42bc3c46..1761f78edeca 100644 --- a/frame/aura/Cargo.toml +++ b/frame/aura/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME AURA consensus pallet" readme = "README.md" diff --git a/frame/authority-discovery/Cargo.toml b/frame/authority-discovery/Cargo.toml index 80a320c31e77..7e64509ce6b4 100644 --- a/frame/authority-discovery/Cargo.toml +++ b/frame/authority-discovery/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet for authority discovery" readme = "README.md" diff --git a/frame/authorship/Cargo.toml b/frame/authorship/Cargo.toml index 120b72f8e651..6ac91970712d 100644 --- a/frame/authorship/Cargo.toml +++ b/frame/authorship/Cargo.toml @@ -5,7 +5,7 @@ description = "Block and Uncle Author tracking for the FRAME" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" readme = "README.md" diff --git a/frame/babe/Cargo.toml b/frame/babe/Cargo.toml index d95f1419fd03..6b0dc71b5e29 100644 --- a/frame/babe/Cargo.toml +++ b/frame/babe/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Consensus extension module for BABE consensus. Collects on-chain randomness from VRF outputs and manages epoch transitions." readme = "README.md" diff --git a/frame/bags-list/Cargo.toml b/frame/bags-list/Cargo.toml index 860a6edc4214..cd06ce4a6998 100644 --- a/frame/bags-list/Cargo.toml +++ b/frame/bags-list/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet bags list" readme = "README.md" diff --git a/frame/balances/Cargo.toml b/frame/balances/Cargo.toml index 2263387d6d8e..f6e6e97850a7 100644 --- a/frame/balances/Cargo.toml +++ b/frame/balances/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet to manage balances" readme = "README.md" diff --git a/frame/benchmarking/Cargo.toml b/frame/benchmarking/Cargo.toml index 6a605707caa8..0600b934d44e 100644 --- a/frame/benchmarking/Cargo.toml +++ b/frame/benchmarking/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Macro for benchmarking a FRAME runtime." readme = "README.md" diff --git a/frame/bounties/Cargo.toml b/frame/bounties/Cargo.toml index 93a7ababb2eb..d949d0fb1d58 100644 --- a/frame/bounties/Cargo.toml +++ b/frame/bounties/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet to manage bounties" readme = "README.md" diff --git a/frame/collective/Cargo.toml b/frame/collective/Cargo.toml index e88f28d41773..3e3d167522e8 100644 --- a/frame/collective/Cargo.toml +++ b/frame/collective/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Collective system: Members of a set of account IDs can make their collective feelings known through dispatched calls from one of two specialized origins." readme = "README.md" diff --git a/frame/contracts/Cargo.toml b/frame/contracts/Cargo.toml index c094e0150771..5967600bf68f 100644 --- a/frame/contracts/Cargo.toml +++ b/frame/contracts/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet for WASM contracts" readme = "README.md" diff --git a/frame/contracts/README.md b/frame/contracts/README.md index f3a8d13f6e77..978ee25fcb10 100644 --- a/frame/contracts/README.md +++ b/frame/contracts/README.md @@ -34,7 +34,7 @@ reverted at the current call's contract level. For example, if contract A calls then all of B's calls are reverted. Assuming correct error handling by contract A, A's other calls and state changes still persist. -One gas is equivalent to one [weight](https://substrate.dev/docs/en/knowledgebase/learn-substrate/weight) +One gas is equivalent to one [weight](https://docs.substrate.io/v3/runtime/weights-and-fees) which is defined as one picosecond of execution time on the runtime's reference machine. ### Notable Scenarios diff --git a/frame/contracts/common/Cargo.toml b/frame/contracts/common/Cargo.toml index b441d88453ae..48baf23d3aee 100644 --- a/frame/contracts/common/Cargo.toml +++ b/frame/contracts/common/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "A crate that hosts a common definitions that are relevant for the pallet-contracts." readme = "README.md" diff --git a/frame/contracts/proc-macro/Cargo.toml b/frame/contracts/proc-macro/Cargo.toml index 605c69fe73e2..63d05bcc2f05 100644 --- a/frame/contracts/proc-macro/Cargo.toml +++ b/frame/contracts/proc-macro/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Procedural macros used in pallet_contracts" diff --git a/frame/contracts/rpc/Cargo.toml b/frame/contracts/rpc/Cargo.toml index b73039ba7191..eec02b03aaa0 100644 --- a/frame/contracts/rpc/Cargo.toml +++ b/frame/contracts/rpc/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Node-specific RPC methods for interaction with contracts." readme = "README.md" diff --git a/frame/contracts/rpc/runtime-api/Cargo.toml b/frame/contracts/rpc/runtime-api/Cargo.toml index e5f6d1ec7eb8..e41aa5aaec9b 100644 --- a/frame/contracts/rpc/runtime-api/Cargo.toml +++ b/frame/contracts/rpc/runtime-api/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Runtime API definition required by Contracts RPC extensions." readme = "README.md" diff --git a/frame/democracy/Cargo.toml b/frame/democracy/Cargo.toml index 94719553e28a..f0bf2109be06 100644 --- a/frame/democracy/Cargo.toml +++ b/frame/democracy/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet for democracy" readme = "README.md" diff --git a/frame/election-provider-multi-phase/Cargo.toml b/frame/election-provider-multi-phase/Cargo.toml index b2d50321e8cd..3c6b405c331f 100644 --- a/frame/election-provider-multi-phase/Cargo.toml +++ b/frame/election-provider-multi-phase/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "PALLET two phase election providers" readme = "README.md" diff --git a/frame/election-provider-support/Cargo.toml b/frame/election-provider-support/Cargo.toml index dfe2b1102433..46e6500cac33 100644 --- a/frame/election-provider-support/Cargo.toml +++ b/frame/election-provider-support/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "election provider supporting traits" readme = "README.md" diff --git a/frame/elections-phragmen/Cargo.toml b/frame/elections-phragmen/Cargo.toml index f2771a9f7278..80afc3f5d8b0 100644 --- a/frame/elections-phragmen/Cargo.toml +++ b/frame/elections-phragmen/Cargo.toml @@ -4,7 +4,7 @@ version = "5.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet based on seq-Phragmén election method." readme = "README.md" diff --git a/frame/elections/Cargo.toml b/frame/elections/Cargo.toml index 8557cfba6b58..f5c7acb1cd5d 100644 --- a/frame/elections/Cargo.toml +++ b/frame/elections/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet for elections" readme = "README.md" diff --git a/frame/example-offchain-worker/Cargo.toml b/frame/example-offchain-worker/Cargo.toml index 1ccd9f33f031..2759664d6e65 100644 --- a/frame/example-offchain-worker/Cargo.toml +++ b/frame/example-offchain-worker/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Unlicense" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME example pallet for offchain worker" readme = "README.md" diff --git a/frame/example-parallel/Cargo.toml b/frame/example-parallel/Cargo.toml index 5e0f6d4bc255..6511a1cd369b 100644 --- a/frame/example-parallel/Cargo.toml +++ b/frame/example-parallel/Cargo.toml @@ -4,7 +4,7 @@ version = "3.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Unlicense" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME example pallet using runtime worker threads" diff --git a/frame/example/Cargo.toml b/frame/example/Cargo.toml index 58daaf1c7555..e144f1e927d3 100644 --- a/frame/example/Cargo.toml +++ b/frame/example/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Unlicense" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME example pallet" readme = "README.md" diff --git a/frame/example/src/benchmarking.rs b/frame/example/src/benchmarking.rs index 9f2bb20fe63a..e89c646e03f1 100644 --- a/frame/example/src/benchmarking.rs +++ b/frame/example/src/benchmarking.rs @@ -26,13 +26,13 @@ use frame_system::RawOrigin; // To actually run this benchmark on pallet-example, we need to put this pallet into the // runtime and compile it with `runtime-benchmarks` feature. The detail procedures are // documented at: -// https://substrate.dev/docs/en/knowledgebase/runtime/benchmarking#how-to-benchmark +// https://docs.substrate.io/v3/runtime/benchmarking#how-to-benchmark // // The auto-generated weight estimate of this pallet is copied over to the `weights.rs` file. // The exact command of how the estimate generated is printed at the top of the file. // Details on using the benchmarks macro can be seen at: -// https://substrate.dev/rustdocs/v3.0.0/frame_benchmarking/macro.benchmarks.html +// https://paritytech.github.io/substrate/master/frame_benchmarking/trait.Benchmarking.html#tymethod.benchmarks benchmarks! { // This will measure the execution time of `set_dummy` for b in [1..1000] range. set_dummy_benchmark { diff --git a/frame/example/src/lib.rs b/frame/example/src/lib.rs index 23c4951c1a60..f0b58e9aec15 100644 --- a/frame/example/src/lib.rs +++ b/frame/example/src/lib.rs @@ -316,8 +316,7 @@ const MILLICENTS: u32 = 1_000_000_000; // - assigns a dispatch class `operational` if the argument of the call is more than 1000. // // More information can be read at: -// - https://substrate.dev/docs/en/knowledgebase/learn-substrate/weight -// - https://substrate.dev/docs/en/knowledgebase/runtime/fees#default-weight-annotations +// - https://docs.substrate.io/v3/runtime/weights-and-fees // // Manually configuring weight is an advanced operation and what you really need may well be // fulfilled by running the benchmarking toolchain. Refer to `benchmarking.rs` file. @@ -548,7 +547,8 @@ pub mod pallet { // Print out log or debug message in the console via log::{error, warn, info, debug, // trace}, accepting format strings similar to `println!`. - // https://substrate.dev/rustdocs/v3.0.0/log/index.html + // https://paritytech.github.io/substrate/master/sp_io/logging/fn.log.html + // https://paritytech.github.io/substrate/master/frame_support/constant.LOG_TARGET.html info!("New value is now: {:?}", new_value); // Put the new value into storage. diff --git a/frame/executive/Cargo.toml b/frame/executive/Cargo.toml index 15c8a1bd14f1..44b4dbcf2bd3 100644 --- a/frame/executive/Cargo.toml +++ b/frame/executive/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME executives engine" readme = "README.md" diff --git a/frame/gilt/Cargo.toml b/frame/gilt/Cargo.toml index c275b693d8f2..c7dc384662f9 100644 --- a/frame/gilt/Cargo.toml +++ b/frame/gilt/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet for rewarding account freezing." readme = "README.md" diff --git a/frame/grandpa/Cargo.toml b/frame/grandpa/Cargo.toml index 53ab443783e5..36cc43fc3443 100644 --- a/frame/grandpa/Cargo.toml +++ b/frame/grandpa/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet for GRANDPA finality gadget" readme = "README.md" diff --git a/frame/identity/Cargo.toml b/frame/identity/Cargo.toml index 598be25c5ef3..e6d1fa3e9dfb 100644 --- a/frame/identity/Cargo.toml +++ b/frame/identity/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME identity management pallet" readme = "README.md" diff --git a/frame/im-online/Cargo.toml b/frame/im-online/Cargo.toml index a1efd626c069..ef2fe54a8cee 100644 --- a/frame/im-online/Cargo.toml +++ b/frame/im-online/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME's I'm online pallet" readme = "README.md" diff --git a/frame/indices/Cargo.toml b/frame/indices/Cargo.toml index 17d04c43fa5d..bf5a82fbb1da 100644 --- a/frame/indices/Cargo.toml +++ b/frame/indices/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME indices management pallet" readme = "README.md" diff --git a/frame/lottery/Cargo.toml b/frame/lottery/Cargo.toml index f14d65310cc7..854b6f52470d 100644 --- a/frame/lottery/Cargo.toml +++ b/frame/lottery/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME Participation Lottery Pallet" readme = "README.md" diff --git a/frame/membership/Cargo.toml b/frame/membership/Cargo.toml index acc82f7678de..9fdfaa473172 100644 --- a/frame/membership/Cargo.toml +++ b/frame/membership/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME membership management pallet" readme = "README.md" diff --git a/frame/merkle-mountain-range/Cargo.toml b/frame/merkle-mountain-range/Cargo.toml index 02b4be182ef8..942067ebde3e 100644 --- a/frame/merkle-mountain-range/Cargo.toml +++ b/frame/merkle-mountain-range/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME Merkle Mountain Range pallet." diff --git a/frame/merkle-mountain-range/primitives/Cargo.toml b/frame/merkle-mountain-range/primitives/Cargo.toml index 07b2f8ae3a3a..bbf55a2b7089 100644 --- a/frame/merkle-mountain-range/primitives/Cargo.toml +++ b/frame/merkle-mountain-range/primitives/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME Merkle Mountain Range primitives." diff --git a/frame/merkle-mountain-range/rpc/Cargo.toml b/frame/merkle-mountain-range/rpc/Cargo.toml index 5a0f114e5017..926cfd602f67 100644 --- a/frame/merkle-mountain-range/rpc/Cargo.toml +++ b/frame/merkle-mountain-range/rpc/Cargo.toml @@ -4,7 +4,7 @@ version = "3.0.0" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Node-specific RPC methods for interaction with Merkle Mountain Range pallet." publish = false diff --git a/frame/multisig/Cargo.toml b/frame/multisig/Cargo.toml index 177334d4ccf8..d1bd23dcab58 100644 --- a/frame/multisig/Cargo.toml +++ b/frame/multisig/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME multi-signature dispatch pallet" readme = "README.md" diff --git a/frame/nicks/Cargo.toml b/frame/nicks/Cargo.toml index 431ee2c84157..dacec5567ede 100644 --- a/frame/nicks/Cargo.toml +++ b/frame/nicks/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet for nick management" readme = "README.md" diff --git a/frame/node-authorization/Cargo.toml b/frame/node-authorization/Cargo.toml index 635e72e3a8b8..960f7e04688d 100644 --- a/frame/node-authorization/Cargo.toml +++ b/frame/node-authorization/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet for node authorization" diff --git a/frame/offences/Cargo.toml b/frame/offences/Cargo.toml index 8fdcbf46fa3e..97f4644a83ca 100644 --- a/frame/offences/Cargo.toml +++ b/frame/offences/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME offences pallet" readme = "README.md" diff --git a/frame/offences/benchmarking/Cargo.toml b/frame/offences/benchmarking/Cargo.toml index b21e6cf9b7e1..f8459087cb7f 100644 --- a/frame/offences/benchmarking/Cargo.toml +++ b/frame/offences/benchmarking/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME offences pallet benchmarking" readme = "README.md" diff --git a/frame/proxy/Cargo.toml b/frame/proxy/Cargo.toml index 4da712dadf27..4f4cf2bf9d56 100644 --- a/frame/proxy/Cargo.toml +++ b/frame/proxy/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME proxying pallet" readme = "README.md" diff --git a/frame/randomness-collective-flip/Cargo.toml b/frame/randomness-collective-flip/Cargo.toml index 5e8eb6b08287..ba7731269917 100644 --- a/frame/randomness-collective-flip/Cargo.toml +++ b/frame/randomness-collective-flip/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME randomness collective flip pallet" readme = "README.md" diff --git a/frame/recovery/Cargo.toml b/frame/recovery/Cargo.toml index 40a89e9b59f8..092940f5173f 100644 --- a/frame/recovery/Cargo.toml +++ b/frame/recovery/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME account recovery pallet" readme = "README.md" diff --git a/frame/scheduler/Cargo.toml b/frame/scheduler/Cargo.toml index 62b21fe04c9d..862321dfa6f2 100644 --- a/frame/scheduler/Cargo.toml +++ b/frame/scheduler/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Unlicense" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME example pallet" readme = "README.md" diff --git a/frame/scored-pool/Cargo.toml b/frame/scored-pool/Cargo.toml index 9d5f156c175d..a7d75ccacb96 100644 --- a/frame/scored-pool/Cargo.toml +++ b/frame/scored-pool/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet for scored pools" readme = "README.md" diff --git a/frame/session/Cargo.toml b/frame/session/Cargo.toml index 3d2de5339543..32d298d3917c 100644 --- a/frame/session/Cargo.toml +++ b/frame/session/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME sessions pallet" readme = "README.md" diff --git a/frame/session/benchmarking/Cargo.toml b/frame/session/benchmarking/Cargo.toml index a24d4a1173ab..0d0868d43921 100644 --- a/frame/session/benchmarking/Cargo.toml +++ b/frame/session/benchmarking/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME sessions pallet benchmarking" readme = "README.md" diff --git a/frame/society/Cargo.toml b/frame/society/Cargo.toml index 942b2844195f..ab2c379c51b5 100644 --- a/frame/society/Cargo.toml +++ b/frame/society/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME society pallet" readme = "README.md" diff --git a/frame/staking/Cargo.toml b/frame/staking/Cargo.toml index 70637bcd7726..4b608bd91dc7 100644 --- a/frame/staking/Cargo.toml +++ b/frame/staking/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet staking" readme = "README.md" diff --git a/frame/staking/reward-curve/Cargo.toml b/frame/staking/reward-curve/Cargo.toml index aaa45e623109..e44188bf7894 100644 --- a/frame/staking/reward-curve/Cargo.toml +++ b/frame/staking/reward-curve/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Reward Curve for FRAME staking pallet" diff --git a/frame/staking/reward-fn/Cargo.toml b/frame/staking/reward-fn/Cargo.toml index 076e05bf2a61..ae0b7f50c994 100644 --- a/frame/staking/reward-fn/Cargo.toml +++ b/frame/staking/reward-fn/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Reward function for FRAME staking pallet" diff --git a/frame/sudo/Cargo.toml b/frame/sudo/Cargo.toml index baacb66d5c75..3587a234566e 100644 --- a/frame/sudo/Cargo.toml +++ b/frame/sudo/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet for sudo" readme = "README.md" diff --git a/frame/sudo/README.md b/frame/sudo/README.md index ac7de01615f3..60090db46a4f 100644 --- a/frame/sudo/README.md +++ b/frame/sudo/README.md @@ -65,6 +65,6 @@ You need to set an initial superuser account as the sudo `key`. [`Call`]: ./enum.Call.html [`Config`]: ./trait.Config.html -[`Origin`]: https://docs.substrate.dev/docs/substrate-types +[`Origin`]: https://docs.substrate.io/v3/runtime/origins License: Apache-2.0 diff --git a/frame/sudo/src/lib.rs b/frame/sudo/src/lib.rs index bab93ffcee16..427455849bb0 100644 --- a/frame/sudo/src/lib.rs +++ b/frame/sudo/src/lib.rs @@ -89,7 +89,7 @@ //! //! * [Democracy](../pallet_democracy/index.html) //! -//! [`Origin`]: https://docs.substrate.dev/docs/substrate-types +//! [`Origin`]: https://docs.substrate.io/v3/runtime/origins #![cfg_attr(not(feature = "std"), no_std)] diff --git a/frame/support/Cargo.toml b/frame/support/Cargo.toml index 5f1b24d90a49..edb0ecd6442e 100644 --- a/frame/support/Cargo.toml +++ b/frame/support/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Support code for the runtime." readme = "README.md" diff --git a/frame/support/procedural/Cargo.toml b/frame/support/procedural/Cargo.toml index 6113c6613be0..ed152c25fc3b 100644 --- a/frame/support/procedural/Cargo.toml +++ b/frame/support/procedural/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Proc macro of Support code for the runtime." diff --git a/frame/support/procedural/src/pallet/expand/error.rs b/frame/support/procedural/src/pallet/expand/error.rs index 7a058bb32c92..c6925db07a26 100644 --- a/frame/support/procedural/src/pallet/expand/error.rs +++ b/frame/support/procedural/src/pallet/expand/error.rs @@ -69,7 +69,7 @@ pub fn expand_error(def: &mut Def) -> proc_macro2::TokenStream { if get_doc_literals(&error_item.attrs).is_empty() { error_item.attrs.push(syn::parse_quote!( #[doc = r" - Custom [dispatch errors](https://substrate.dev/docs/en/knowledgebase/runtime/errors) + Custom [dispatch errors](https://docs.substrate.io/v3/runtime/events-and-errors) of this pallet. "] )); diff --git a/frame/support/procedural/src/pallet/expand/event.rs b/frame/support/procedural/src/pallet/expand/event.rs index ebd2d7aeabaf..625c2d98baac 100644 --- a/frame/support/procedural/src/pallet/expand/event.rs +++ b/frame/support/procedural/src/pallet/expand/event.rs @@ -98,7 +98,7 @@ pub fn expand_event(def: &mut Def) -> proc_macro2::TokenStream { if get_doc_literals(&event_item.attrs).is_empty() { event_item.attrs.push(syn::parse_quote!( #[doc = r" - The [event](https://substrate.dev/docs/en/knowledgebase/runtime/events) emitted + The [event](https://docs.substrate.io/v3/runtime/events-and-errors) emitted by this pallet. "] )); diff --git a/frame/support/procedural/src/pallet/expand/genesis_config.rs b/frame/support/procedural/src/pallet/expand/genesis_config.rs index 4bbba2c05908..b2eb2166165c 100644 --- a/frame/support/procedural/src/pallet/expand/genesis_config.rs +++ b/frame/support/procedural/src/pallet/expand/genesis_config.rs @@ -89,7 +89,7 @@ pub fn expand_genesis_config(def: &mut Def) -> proc_macro2::TokenStream { attrs.push(syn::parse_quote!( #[doc = r" Can be used to configure the - [genesis state](https://substrate.dev/docs/en/knowledgebase/integrate/chain-spec#the-genesis-state) + [genesis state](https://docs.substrate.io/v3/runtime/chain-specs#the-genesis-state) of this pallet. "] )); diff --git a/frame/support/procedural/src/pallet/expand/mod.rs b/frame/support/procedural/src/pallet/expand/mod.rs index 1c8883977c76..083ad61fc523 100644 --- a/frame/support/procedural/src/pallet/expand/mod.rs +++ b/frame/support/procedural/src/pallet/expand/mod.rs @@ -72,9 +72,9 @@ pub fn expand(mut def: Def) -> proc_macro2::TokenStream { def.item.attrs.push(syn::parse_quote!( #[doc = r" The module that hosts all the - [FRAME](https://substrate.dev/docs/en/knowledgebase/runtime/frame) + [FRAME](https://docs.substrate.io/v3/runtime/frame) types needed to add this pallet to a - [runtime](https://substrate.dev/docs/en/knowledgebase/runtime/). + runtime. "] )); } diff --git a/frame/support/procedural/src/pallet/expand/pallet_struct.rs b/frame/support/procedural/src/pallet/expand/pallet_struct.rs index ea601f138ea0..57e814b6b843 100644 --- a/frame/support/procedural/src/pallet/expand/pallet_struct.rs +++ b/frame/support/procedural/src/pallet/expand/pallet_struct.rs @@ -62,7 +62,7 @@ pub fn expand_pallet_struct(def: &mut Def) -> proc_macro2::TokenStream { if get_doc_literals(&pallet_item.attrs).is_empty() { pallet_item.attrs.push(syn::parse_quote!( #[doc = r" - The [pallet](https://substrate.dev/docs/en/knowledgebase/runtime/pallets) implementing + The [pallet](https://docs.substrate.io/v3/runtime/frame#pallets) implementing the on-chain logic. "] )); diff --git a/frame/support/procedural/tools/Cargo.toml b/frame/support/procedural/tools/Cargo.toml index d6894b78133e..6a8fb57b39bd 100644 --- a/frame/support/procedural/tools/Cargo.toml +++ b/frame/support/procedural/tools/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Proc macro helpers for procedural macros" diff --git a/frame/support/procedural/tools/derive/Cargo.toml b/frame/support/procedural/tools/derive/Cargo.toml index 14c56b1b819a..9f4e2d9dca2a 100644 --- a/frame/support/procedural/tools/derive/Cargo.toml +++ b/frame/support/procedural/tools/derive/Cargo.toml @@ -4,7 +4,7 @@ version = "3.0.0" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Use to derive parsing for parsing struct." diff --git a/frame/support/src/dispatch.rs b/frame/support/src/dispatch.rs index b4e9071e361a..6dc7fb8a94ca 100644 --- a/frame/support/src/dispatch.rs +++ b/frame/support/src/dispatch.rs @@ -280,7 +280,7 @@ impl Parameter for T where T: Codec + EncodeLike + Clone + Eq + fmt::Debug + /// /// The following are reserved function signatures: /// -/// * `deposit_event`: Helper function for depositing an [event](https://docs.substrate.dev/docs/event-enum). +/// * `deposit_event`: Helper function for depositing an [event](https://docs.substrate.io/v3/runtime/events-and-errors). /// The default behavior is to call `deposit_event` from the [System /// module](../frame_system/index.html). However, you can write your own implementation for events /// in your runtime. To use the default behavior, add `fn deposit_event() = default;` to your diff --git a/frame/support/src/storage/bounded_vec.rs b/frame/support/src/storage/bounded_vec.rs index a60ed57cf2b9..e51c6cd73411 100644 --- a/frame/support/src/storage/bounded_vec.rs +++ b/frame/support/src/storage/bounded_vec.rs @@ -337,7 +337,7 @@ where fn max_encoded_len() -> usize { // BoundedVec encodes like Vec which encodes like [T], which is a compact u32 // plus each item in the slice: - // https://substrate.dev/rustdocs/v3.0.0/src/parity_scale_codec/codec.rs.html#798-808 + // https://docs.substrate.io/v3/advanced/scale-codec codec::Compact(S::get()) .encoded_size() .saturating_add(Self::bound().saturating_mul(T::max_encoded_len())) diff --git a/frame/support/src/storage/weak_bounded_vec.rs b/frame/support/src/storage/weak_bounded_vec.rs index 4655c809e014..823c50c55d0b 100644 --- a/frame/support/src/storage/weak_bounded_vec.rs +++ b/frame/support/src/storage/weak_bounded_vec.rs @@ -307,7 +307,7 @@ where fn max_encoded_len() -> usize { // WeakBoundedVec encodes like Vec which encodes like [T], which is a compact u32 // plus each item in the slice: - // https://substrate.dev/rustdocs/v3.0.0/src/parity_scale_codec/codec.rs.html#798-808 + // https://docs.substrate.io/v3/advanced/scale-codec codec::Compact(S::get()) .encoded_size() .saturating_add(Self::bound().saturating_mul(T::max_encoded_len())) diff --git a/frame/support/src/traits/misc.rs b/frame/support/src/traits/misc.rs index db6e0321005a..9109bfeeae72 100644 --- a/frame/support/src/traits/misc.rs +++ b/frame/support/src/traits/misc.rs @@ -429,7 +429,7 @@ impl MaxEncodedLen for WrapperOpaque { fn max_encoded_len() -> usize { let t_max_len = T::max_encoded_len(); - // See scale encoding https://substrate.dev/docs/en/knowledgebase/advanced/codec + // See scale encoding https://docs.substrate.io/v3/advanced/scale-codec if t_max_len < 64 { t_max_len + 1 } else if t_max_len < 2usize.pow(14) { diff --git a/frame/support/test/Cargo.toml b/frame/support/test/Cargo.toml index 594ed6349e74..77fd4f562096 100644 --- a/frame/support/test/Cargo.toml +++ b/frame/support/test/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" publish = false -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" [package.metadata.docs.rs] diff --git a/frame/support/test/pallet/Cargo.toml b/frame/support/test/pallet/Cargo.toml index 35eb4f34acae..a3d101967ae6 100644 --- a/frame/support/test/pallet/Cargo.toml +++ b/frame/support/test/pallet/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" publish = false -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" [package.metadata.docs.rs] diff --git a/frame/system/Cargo.toml b/frame/system/Cargo.toml index 389730107b43..dc69bd2d5e85 100644 --- a/frame/system/Cargo.toml +++ b/frame/system/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME system module" readme = "README.md" diff --git a/frame/system/benchmarking/Cargo.toml b/frame/system/benchmarking/Cargo.toml index 29bcccfd7d83..6aa2251f287d 100644 --- a/frame/system/benchmarking/Cargo.toml +++ b/frame/system/benchmarking/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME System benchmarking" readme = "README.md" diff --git a/frame/system/rpc/runtime-api/Cargo.toml b/frame/system/rpc/runtime-api/Cargo.toml index fce29612b4d8..b5e569e1298c 100644 --- a/frame/system/rpc/runtime-api/Cargo.toml +++ b/frame/system/rpc/runtime-api/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Runtime API definition required by System RPC extensions." readme = "README.md" diff --git a/frame/timestamp/Cargo.toml b/frame/timestamp/Cargo.toml index 1c95c4782b5c..cd636ec6c23b 100644 --- a/frame/timestamp/Cargo.toml +++ b/frame/timestamp/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME Timestamp Module" documentation = "https://docs.rs/pallet-timestamp" diff --git a/frame/tips/Cargo.toml b/frame/tips/Cargo.toml index 8ca395e1c541..a3f268169b78 100644 --- a/frame/tips/Cargo.toml +++ b/frame/tips/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet to manage tips" readme = "README.md" diff --git a/frame/transaction-payment/Cargo.toml b/frame/transaction-payment/Cargo.toml index 1dfeb0c2baa4..bea263cbef6f 100644 --- a/frame/transaction-payment/Cargo.toml +++ b/frame/transaction-payment/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet to manage transaction payments" readme = "README.md" diff --git a/frame/transaction-payment/rpc/Cargo.toml b/frame/transaction-payment/rpc/Cargo.toml index 3858c41a3876..1a2c68227c11 100644 --- a/frame/transaction-payment/rpc/Cargo.toml +++ b/frame/transaction-payment/rpc/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "RPC interface for the transaction payment pallet." readme = "README.md" diff --git a/frame/transaction-payment/rpc/runtime-api/Cargo.toml b/frame/transaction-payment/rpc/runtime-api/Cargo.toml index 2f78f2439c60..7bdca2f65829 100644 --- a/frame/transaction-payment/rpc/runtime-api/Cargo.toml +++ b/frame/transaction-payment/rpc/runtime-api/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "RPC runtime API for transaction payment FRAME pallet" readme = "README.md" diff --git a/frame/transaction-storage/Cargo.toml b/frame/transaction-storage/Cargo.toml index 9daf706b0ce3..bcd3fd145f57 100644 --- a/frame/transaction-storage/Cargo.toml +++ b/frame/transaction-storage/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Unlicense" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Storage chain pallet" readme = "README.md" diff --git a/frame/treasury/Cargo.toml b/frame/treasury/Cargo.toml index b2991f3febca..bcbe41985c65 100644 --- a/frame/treasury/Cargo.toml +++ b/frame/treasury/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet to manage treasury" readme = "README.md" diff --git a/frame/try-runtime/Cargo.toml b/frame/try-runtime/Cargo.toml index 0ff534767607..611a84427826 100644 --- a/frame/try-runtime/Cargo.toml +++ b/frame/try-runtime/Cargo.toml @@ -4,7 +4,7 @@ version = "0.10.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet for democracy" readme = "README.md" diff --git a/frame/uniques/Cargo.toml b/frame/uniques/Cargo.toml index 4f664ecc2b6a..f240bb98afab 100644 --- a/frame/uniques/Cargo.toml +++ b/frame/uniques/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME NFT asset management pallet" readme = "README.md" diff --git a/frame/utility/Cargo.toml b/frame/utility/Cargo.toml index b5b8eab9cdbf..0a0a9eafd845 100644 --- a/frame/utility/Cargo.toml +++ b/frame/utility/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME utilities pallet" readme = "README.md" diff --git a/frame/vesting/Cargo.toml b/frame/vesting/Cargo.toml index 806e0e603686..3179607b3f6d 100644 --- a/frame/vesting/Cargo.toml +++ b/frame/vesting/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet for manage vesting" readme = "README.md" diff --git a/primitives/api/Cargo.toml b/primitives/api/Cargo.toml index 7e751232acb5..c57c3730fc7b 100644 --- a/primitives/api/Cargo.toml +++ b/primitives/api/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Substrate runtime api primitives" readme = "README.md" diff --git a/primitives/api/proc-macro/Cargo.toml b/primitives/api/proc-macro/Cargo.toml index dc0f2bd98d46..d9dd0bf9020c 100644 --- a/primitives/api/proc-macro/Cargo.toml +++ b/primitives/api/proc-macro/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Macros for declaring and implementing runtime apis." documentation = "https://docs.rs/sp-api-proc-macro" diff --git a/primitives/api/test/Cargo.toml b/primitives/api/test/Cargo.toml index b78c9abb80dc..faee5ebdc77d 100644 --- a/primitives/api/test/Cargo.toml +++ b/primitives/api/test/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" publish = false -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" [package.metadata.docs.rs] diff --git a/primitives/application-crypto/Cargo.toml b/primitives/application-crypto/Cargo.toml index 6849dc25f856..88411d86392a 100644 --- a/primitives/application-crypto/Cargo.toml +++ b/primitives/application-crypto/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] edition = "2018" description = "Provides facilities for generating application specific crypto wrapper types." license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" documentation = "https://docs.rs/sp-application-crypto" readme = "README.md" diff --git a/primitives/application-crypto/test/Cargo.toml b/primitives/application-crypto/test/Cargo.toml index 468bfee3cc01..d10f011c4c60 100644 --- a/primitives/application-crypto/test/Cargo.toml +++ b/primitives/application-crypto/test/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" description = "Integration tests for application-crypto" license = "Apache-2.0" publish = false -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" [package.metadata.docs.rs] diff --git a/primitives/arithmetic/Cargo.toml b/primitives/arithmetic/Cargo.toml index abdbd4e60d04..92b16b895e3b 100644 --- a/primitives/arithmetic/Cargo.toml +++ b/primitives/arithmetic/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Minimal fixed point arithmetic primitives and types for runtime." documentation = "https://docs.rs/sp-arithmetic" diff --git a/primitives/arithmetic/fuzzer/Cargo.toml b/primitives/arithmetic/fuzzer/Cargo.toml index d10eccfc7c74..5f2d5801ff99 100644 --- a/primitives/arithmetic/fuzzer/Cargo.toml +++ b/primitives/arithmetic/fuzzer/Cargo.toml @@ -4,7 +4,7 @@ version = "2.0.0" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Fuzzer for fixed point arithmetic primitives." documentation = "https://docs.rs/sp-arithmetic-fuzzer" diff --git a/primitives/authority-discovery/Cargo.toml b/primitives/authority-discovery/Cargo.toml index 6638e478b4cd..d4c75dda352c 100644 --- a/primitives/authority-discovery/Cargo.toml +++ b/primitives/authority-discovery/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] description = "Authority discovery primitives" edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" readme = "README.md" diff --git a/primitives/authorship/Cargo.toml b/primitives/authorship/Cargo.toml index 15e4dc57ff5a..cee82ca77c37 100644 --- a/primitives/authorship/Cargo.toml +++ b/primitives/authorship/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] description = "Authorship primitives" edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" readme = "README.md" diff --git a/primitives/block-builder/Cargo.toml b/primitives/block-builder/Cargo.toml index d7fa0f2ef85c..8499bdf8e1c7 100644 --- a/primitives/block-builder/Cargo.toml +++ b/primitives/block-builder/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "The block builder runtime api." readme = "README.md" diff --git a/primitives/blockchain/Cargo.toml b/primitives/blockchain/Cargo.toml index 66d9152c230d..93daef5fa1a2 100644 --- a/primitives/blockchain/Cargo.toml +++ b/primitives/blockchain/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Substrate blockchain traits and primitives." documentation = "https://docs.rs/sp-blockchain" diff --git a/primitives/consensus/aura/Cargo.toml b/primitives/consensus/aura/Cargo.toml index c228b88fd657..ca73cf206de0 100644 --- a/primitives/consensus/aura/Cargo.toml +++ b/primitives/consensus/aura/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] description = "Primitives for Aura consensus" edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" readme = "README.md" diff --git a/primitives/consensus/babe/Cargo.toml b/primitives/consensus/babe/Cargo.toml index 5f6bfec21973..1690b7c9a02d 100644 --- a/primitives/consensus/babe/Cargo.toml +++ b/primitives/consensus/babe/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] description = "Primitives for BABE consensus" edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" readme = "README.md" diff --git a/primitives/consensus/common/Cargo.toml b/primitives/consensus/common/Cargo.toml index ecfc1c1b3182..9a5488abba65 100644 --- a/primitives/consensus/common/Cargo.toml +++ b/primitives/consensus/common/Cargo.toml @@ -4,7 +4,7 @@ version = "0.10.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Common utilities for building and using consensus engines in substrate." documentation = "https://docs.rs/sp-consensus/" diff --git a/primitives/consensus/pow/Cargo.toml b/primitives/consensus/pow/Cargo.toml index f93eeca2fb24..406ed3dea46a 100644 --- a/primitives/consensus/pow/Cargo.toml +++ b/primitives/consensus/pow/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] description = "Primitives for Aura consensus" edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" readme = "README.md" diff --git a/primitives/consensus/slots/Cargo.toml b/primitives/consensus/slots/Cargo.toml index 3ad204f97396..014ee9b93e6e 100644 --- a/primitives/consensus/slots/Cargo.toml +++ b/primitives/consensus/slots/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] description = "Primitives for slots-based consensus" edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" readme = "README.md" diff --git a/primitives/consensus/vrf/Cargo.toml b/primitives/consensus/vrf/Cargo.toml index 124cbf423f06..c103e68eb66b 100644 --- a/primitives/consensus/vrf/Cargo.toml +++ b/primitives/consensus/vrf/Cargo.toml @@ -6,7 +6,7 @@ description = "Primitives for VRF based consensus" edition = "2018" license = "Apache-2.0" repository = "https://github.com/paritytech/substrate/" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" readme = "README.md" [package.metadata.docs.rs] diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index 4071dab71be5..dd721d744f57 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Shareable Substrate types." documentation = "https://docs.rs/sp-core" diff --git a/primitives/database/Cargo.toml b/primitives/database/Cargo.toml index c99651d4ef04..c3d2d8ce99df 100644 --- a/primitives/database/Cargo.toml +++ b/primitives/database/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Substrate database trait." documentation = "https://docs.rs/sp-database" diff --git a/primitives/debug-derive/Cargo.toml b/primitives/debug-derive/Cargo.toml index ce49c54b46fb..954d0f89663f 100644 --- a/primitives/debug-derive/Cargo.toml +++ b/primitives/debug-derive/Cargo.toml @@ -4,7 +4,7 @@ version = "3.0.0" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Macros to derive runtime debug implementation." documentation = "https://docs.rs/sp-debug-derive" diff --git a/primitives/externalities/Cargo.toml b/primitives/externalities/Cargo.toml index 52a6300688cd..5a1b6b5e7373 100644 --- a/primitives/externalities/Cargo.toml +++ b/primitives/externalities/Cargo.toml @@ -4,7 +4,7 @@ version = "0.10.0-dev" license = "Apache-2.0" authors = ["Parity Technologies "] edition = "2018" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Substrate externalities abstraction" documentation = "https://docs.rs/sp-externalities" diff --git a/primitives/finality-grandpa/Cargo.toml b/primitives/finality-grandpa/Cargo.toml index c0c2a654270f..5cf7ac6711a7 100644 --- a/primitives/finality-grandpa/Cargo.toml +++ b/primitives/finality-grandpa/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Primitives for GRANDPA integration, suitable for WASM compilation." documentation = "https://docs.rs/sp-finality-grandpa" diff --git a/primitives/inherents/Cargo.toml b/primitives/inherents/Cargo.toml index 23558750b5cf..04b662fb059f 100644 --- a/primitives/inherents/Cargo.toml +++ b/primitives/inherents/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Provides types and traits for creating and checking inherents." documentation = "https://docs.rs/sp-inherents" diff --git a/primitives/io/Cargo.toml b/primitives/io/Cargo.toml index 2323b5281d59..df9a496a914b 100644 --- a/primitives/io/Cargo.toml +++ b/primitives/io/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "I/O for Substrate runtimes" documentation = "https://docs.rs/sp-io" diff --git a/primitives/keyring/Cargo.toml b/primitives/keyring/Cargo.toml index a14e98d3d805..464abdb6cb1a 100644 --- a/primitives/keyring/Cargo.toml +++ b/primitives/keyring/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Keyring support code for the runtime. A set of test accounts." documentation = "https://docs.rs/sp-keyring" diff --git a/primitives/keystore/Cargo.toml b/primitives/keystore/Cargo.toml index 35c66ef93f7a..3a0532f1db31 100644 --- a/primitives/keystore/Cargo.toml +++ b/primitives/keystore/Cargo.toml @@ -4,7 +4,7 @@ version = "0.10.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Keystore primitives." documentation = "https://docs.rs/sp-core" diff --git a/primitives/maybe-compressed-blob/Cargo.toml b/primitives/maybe-compressed-blob/Cargo.toml index 6994ccf5486b..cd124580ef19 100644 --- a/primitives/maybe-compressed-blob/Cargo.toml +++ b/primitives/maybe-compressed-blob/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Handling of blobs, usually Wasm code, which may be compresed" documentation = "https://docs.rs/sp-maybe-compressed-blob" diff --git a/primitives/npos-elections/Cargo.toml b/primitives/npos-elections/Cargo.toml index b277df8f58f1..5ffaf76379bd 100644 --- a/primitives/npos-elections/Cargo.toml +++ b/primitives/npos-elections/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "NPoS election algorithm primitives" readme = "README.md" diff --git a/primitives/npos-elections/fuzzer/Cargo.toml b/primitives/npos-elections/fuzzer/Cargo.toml index d6fcc09c8b58..1d13d33a35e8 100644 --- a/primitives/npos-elections/fuzzer/Cargo.toml +++ b/primitives/npos-elections/fuzzer/Cargo.toml @@ -4,7 +4,7 @@ version = "2.0.0-alpha.5" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Fuzzer for phragmén implementation." documentation = "https://docs.rs/sp-npos-elections-fuzzer" diff --git a/primitives/npos-elections/solution-type/Cargo.toml b/primitives/npos-elections/solution-type/Cargo.toml index 8eb9c26564f5..27d5d0bb1231 100644 --- a/primitives/npos-elections/solution-type/Cargo.toml +++ b/primitives/npos-elections/solution-type/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "NPoS Solution Type" diff --git a/primitives/offchain/Cargo.toml b/primitives/offchain/Cargo.toml index dd54147b6c62..c1e891acba95 100644 --- a/primitives/offchain/Cargo.toml +++ b/primitives/offchain/Cargo.toml @@ -5,7 +5,7 @@ version = "4.0.0-dev" license = "Apache-2.0" authors = ["Parity Technologies "] edition = "2018" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" readme = "README.md" diff --git a/primitives/panic-handler/Cargo.toml b/primitives/panic-handler/Cargo.toml index ad03baca24eb..c961d5b089ab 100644 --- a/primitives/panic-handler/Cargo.toml +++ b/primitives/panic-handler/Cargo.toml @@ -4,7 +4,7 @@ version = "3.0.0" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Custom panic hook with bug report link" documentation = "https://docs.rs/sp-panic-handler" diff --git a/primitives/rpc/Cargo.toml b/primitives/rpc/Cargo.toml index 8e1b91a9acb2..af883e219941 100644 --- a/primitives/rpc/Cargo.toml +++ b/primitives/rpc/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Substrate RPC primitives and utilities." readme = "README.md" diff --git a/primitives/runtime-interface/Cargo.toml b/primitives/runtime-interface/Cargo.toml index dd1b84eabfe9..fc8923cdb80a 100644 --- a/primitives/runtime-interface/Cargo.toml +++ b/primitives/runtime-interface/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Substrate runtime interface" documentation = "https://docs.rs/sp-runtime-interface/" diff --git a/primitives/runtime-interface/proc-macro/Cargo.toml b/primitives/runtime-interface/proc-macro/Cargo.toml index 1f77caf7e416..dd08d0331339 100644 --- a/primitives/runtime-interface/proc-macro/Cargo.toml +++ b/primitives/runtime-interface/proc-macro/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "This crate provides procedural macros for usage within the context of the Substrate runtime interface." documentation = "https://docs.rs/sp-runtime-interface-proc-macro" diff --git a/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml b/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml index 3ae5d78b0ef9..a3c82de473ab 100644 --- a/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml +++ b/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] edition = "2018" build = "build.rs" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" publish = false diff --git a/primitives/runtime-interface/test-wasm/Cargo.toml b/primitives/runtime-interface/test-wasm/Cargo.toml index 7c7d3e10b2d0..557b5b9bee89 100644 --- a/primitives/runtime-interface/test-wasm/Cargo.toml +++ b/primitives/runtime-interface/test-wasm/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] edition = "2018" build = "build.rs" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" publish = false diff --git a/primitives/runtime-interface/test/Cargo.toml b/primitives/runtime-interface/test/Cargo.toml index 383df494120a..26884d5cb729 100644 --- a/primitives/runtime-interface/test/Cargo.toml +++ b/primitives/runtime-interface/test/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" publish = false -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" [package.metadata.docs.rs] diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 5ac5bcf1963e..475d2b769de3 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Runtime Modules shared primitive types." documentation = "https://docs.rs/sp-runtime" diff --git a/primitives/sandbox/Cargo.toml b/primitives/sandbox/Cargo.toml index a4d4a4d5d031..80cd195c6f40 100755 --- a/primitives/sandbox/Cargo.toml +++ b/primitives/sandbox/Cargo.toml @@ -4,7 +4,7 @@ version = "0.10.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "This crate provides means to instantiate and execute wasm modules." readme = "README.md" diff --git a/primitives/serializer/Cargo.toml b/primitives/serializer/Cargo.toml index 2200274e0628..cc438e9a1c14 100644 --- a/primitives/serializer/Cargo.toml +++ b/primitives/serializer/Cargo.toml @@ -4,7 +4,7 @@ version = "3.0.0" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Substrate customizable serde serializer." documentation = "https://docs.rs/sp-serializer" diff --git a/primitives/session/Cargo.toml b/primitives/session/Cargo.toml index 8e1e2464e49e..1e9ed6ec9b65 100644 --- a/primitives/session/Cargo.toml +++ b/primitives/session/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Primitives for sessions" readme = "README.md" diff --git a/primitives/staking/Cargo.toml b/primitives/staking/Cargo.toml index 9e852319ede4..8ea24760e2b8 100644 --- a/primitives/staking/Cargo.toml +++ b/primitives/staking/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "A crate which contains primitives that are useful for implementation that uses staking approaches in general. Definitions related to sessions, slashing, etc go here." readme = "README.md" diff --git a/primitives/state-machine/Cargo.toml b/primitives/state-machine/Cargo.toml index bafe34bbd5af..bbe9728befd8 100644 --- a/primitives/state-machine/Cargo.toml +++ b/primitives/state-machine/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] description = "Substrate State Machine" edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" documentation = "https://docs.rs/sp-state-machine" readme = "README.md" diff --git a/primitives/std/Cargo.toml b/primitives/std/Cargo.toml index bf815c1c80c5..e4cacf60cc36 100644 --- a/primitives/std/Cargo.toml +++ b/primitives/std/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Lowest-abstraction level for the Substrate runtime: just exports useful primitives from std or client/alloc to be used with any code that depends on the runtime." diff --git a/primitives/storage/Cargo.toml b/primitives/storage/Cargo.toml index 078e0fff12ef..c7d23fcf7010 100644 --- a/primitives/storage/Cargo.toml +++ b/primitives/storage/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] edition = "2018" description = "Storage related primitives" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" documentation = "https://docs.rs/sp-storage/" readme = "README.md" diff --git a/primitives/tasks/Cargo.toml b/primitives/tasks/Cargo.toml index ee503ae9b855..f91d15d2d40b 100644 --- a/primitives/tasks/Cargo.toml +++ b/primitives/tasks/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Runtime asynchronous, pure computational tasks" documentation = "https://docs.rs/sp-tasks" diff --git a/primitives/test-primitives/Cargo.toml b/primitives/test-primitives/Cargo.toml index 5aed5d679dd4..75ce8b752d3c 100644 --- a/primitives/test-primitives/Cargo.toml +++ b/primitives/test-primitives/Cargo.toml @@ -4,7 +4,7 @@ version = "2.0.0" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" publish = false diff --git a/primitives/timestamp/Cargo.toml b/primitives/timestamp/Cargo.toml index 60daf9642df6..32f4c5308343 100644 --- a/primitives/timestamp/Cargo.toml +++ b/primitives/timestamp/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Substrate core types and inherents for timestamps." readme = "README.md" diff --git a/primitives/tracing/Cargo.toml b/primitives/tracing/Cargo.toml index 806205dae8dd..85eb22d6df07 100644 --- a/primitives/tracing/Cargo.toml +++ b/primitives/tracing/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" license = "Apache-2.0" authors = ["Parity Technologies "] edition = "2018" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Instrumentation primitives and macros for Substrate." readme = "README.md" diff --git a/primitives/transaction-pool/Cargo.toml b/primitives/transaction-pool/Cargo.toml index 3f77014ac53b..f74fcb44fee2 100644 --- a/primitives/transaction-pool/Cargo.toml +++ b/primitives/transaction-pool/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Transaction pool runtime facing API." documentation = "https://docs.rs/sp-transaction-pool" diff --git a/primitives/transaction-storage-proof/Cargo.toml b/primitives/transaction-storage-proof/Cargo.toml index 8a41105b20b7..536e2f201a10 100644 --- a/primitives/transaction-storage-proof/Cargo.toml +++ b/primitives/transaction-storage-proof/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] description = "Transaction storage proof primitives" edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" readme = "README.md" diff --git a/primitives/trie/Cargo.toml b/primitives/trie/Cargo.toml index 297040d09eec..66d8a1e47276 100644 --- a/primitives/trie/Cargo.toml +++ b/primitives/trie/Cargo.toml @@ -6,7 +6,7 @@ description = "Patricia trie stuff using a parity-scale-codec node format" repository = "https://github.com/paritytech/substrate/" license = "Apache-2.0" edition = "2018" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" documentation = "https://docs.rs/sp-trie" readme = "README.md" diff --git a/primitives/version/Cargo.toml b/primitives/version/Cargo.toml index fcab1eeabcaf..2a2c2698c74c 100644 --- a/primitives/version/Cargo.toml +++ b/primitives/version/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Version module for the Substrate runtime; Provides a function that returns the runtime version." documentation = "https://docs.rs/sp-version" diff --git a/primitives/version/proc-macro/Cargo.toml b/primitives/version/proc-macro/Cargo.toml index 4984961fb9f7..587ca06bdc17 100644 --- a/primitives/version/proc-macro/Cargo.toml +++ b/primitives/version/proc-macro/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Macro for defining a runtime version." documentation = "https://docs.rs/sp-api-proc-macro" diff --git a/primitives/wasm-interface/Cargo.toml b/primitives/wasm-interface/Cargo.toml index ba8a7b4e4b46..73b47e563a5b 100644 --- a/primitives/wasm-interface/Cargo.toml +++ b/primitives/wasm-interface/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Types and traits for interfacing between the host and the wasm runtime." documentation = "https://docs.rs/sp-wasm-interface" diff --git a/ss58-registry.json b/ss58-registry.json index 62602d829f6b..fdae23a5a6f2 100644 --- a/ss58-registry.json +++ b/ss58-registry.json @@ -386,7 +386,7 @@ "symbols": null, "decimals": null, "standardAccount": "*25519", - "website": "https://substrate.dev/" + "website": "https://docs.substrate.io/" }, { "prefix": 43, diff --git a/test-utils/Cargo.toml b/test-utils/Cargo.toml index 4eed6e5e2913..a9ffefa05df7 100644 --- a/test-utils/Cargo.toml +++ b/test-utils/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Substrate test utilities" diff --git a/test-utils/client/Cargo.toml b/test-utils/client/Cargo.toml index 34238872cad8..204b6ac435e0 100644 --- a/test-utils/client/Cargo.toml +++ b/test-utils/client/Cargo.toml @@ -4,7 +4,7 @@ version = "2.0.1" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" publish = false diff --git a/test-utils/derive/Cargo.toml b/test-utils/derive/Cargo.toml index 68bcbdaa4700..2a1f52346840 100644 --- a/test-utils/derive/Cargo.toml +++ b/test-utils/derive/Cargo.toml @@ -4,7 +4,7 @@ version = "0.10.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Substrate test utilities macros" diff --git a/test-utils/runtime/Cargo.toml b/test-utils/runtime/Cargo.toml index 24f4d404c18b..eb6ca51ce2e5 100644 --- a/test-utils/runtime/Cargo.toml +++ b/test-utils/runtime/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] edition = "2018" build = "build.rs" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" publish = false diff --git a/test-utils/runtime/client/Cargo.toml b/test-utils/runtime/client/Cargo.toml index 3561697042f2..75ebb8f23326 100644 --- a/test-utils/runtime/client/Cargo.toml +++ b/test-utils/runtime/client/Cargo.toml @@ -4,7 +4,7 @@ version = "2.0.0" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" publish = false diff --git a/test-utils/runtime/transaction-pool/Cargo.toml b/test-utils/runtime/transaction-pool/Cargo.toml index 09839ebae6ff..5a2983b058b0 100644 --- a/test-utils/runtime/transaction-pool/Cargo.toml +++ b/test-utils/runtime/transaction-pool/Cargo.toml @@ -4,7 +4,7 @@ version = "2.0.0" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" publish = false diff --git a/test-utils/test-crate/Cargo.toml b/test-utils/test-crate/Cargo.toml index fff39c3964ad..9c9672fe8f5d 100644 --- a/test-utils/test-crate/Cargo.toml +++ b/test-utils/test-crate/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" publish = false diff --git a/utils/build-script-utils/Cargo.toml b/utils/build-script-utils/Cargo.toml index fbef70db93bf..786e6f900291 100644 --- a/utils/build-script-utils/Cargo.toml +++ b/utils/build-script-utils/Cargo.toml @@ -4,7 +4,7 @@ version = "3.0.0" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Crate with utility functions for `build.rs` scripts." readme = "README.md" diff --git a/utils/fork-tree/Cargo.toml b/utils/fork-tree/Cargo.toml index 11c269bc3cba..81fa1747a84d 100644 --- a/utils/fork-tree/Cargo.toml +++ b/utils/fork-tree/Cargo.toml @@ -4,7 +4,7 @@ version = "3.0.0" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Utility library for managing tree-like ordered data with logic for pruning the tree while finalizing nodes." documentation = "https://docs.rs/fork-tree" diff --git a/utils/frame/benchmarking-cli/Cargo.toml b/utils/frame/benchmarking-cli/Cargo.toml index 93616b590f61..ccca30849f91 100644 --- a/utils/frame/benchmarking-cli/Cargo.toml +++ b/utils/frame/benchmarking-cli/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "CLI for benchmarking FRAME" readme = "README.md" diff --git a/utils/frame/frame-utilities-cli/Cargo.toml b/utils/frame/frame-utilities-cli/Cargo.toml index 1b6597fc9f2f..fcdbb215f91b 100644 --- a/utils/frame/frame-utilities-cli/Cargo.toml +++ b/utils/frame/frame-utilities-cli/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "cli interface for FRAME" documentation = "https://docs.rs/substrate-frame-cli" diff --git a/utils/frame/generate-bags/Cargo.toml b/utils/frame/generate-bags/Cargo.toml index 384307fbec9e..1bb53207f7d4 100644 --- a/utils/frame/generate-bags/Cargo.toml +++ b/utils/frame/generate-bags/Cargo.toml @@ -4,7 +4,7 @@ version = "3.0.0" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Bag threshold generation script for pallet-bag-list" readme = "README.md" diff --git a/utils/frame/generate-bags/node-runtime/Cargo.toml b/utils/frame/generate-bags/node-runtime/Cargo.toml index 7fcd981a6bbd..68d3cad16de4 100644 --- a/utils/frame/generate-bags/node-runtime/Cargo.toml +++ b/utils/frame/generate-bags/node-runtime/Cargo.toml @@ -4,7 +4,7 @@ version = "3.0.0" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Bag threshold generation script for pallet-bag-list and node-runtime." readme = "README.md" diff --git a/utils/frame/remote-externalities/Cargo.toml b/utils/frame/remote-externalities/Cargo.toml index e1fffcfd567a..2b35402f8f63 100644 --- a/utils/frame/remote-externalities/Cargo.toml +++ b/utils/frame/remote-externalities/Cargo.toml @@ -4,7 +4,7 @@ version = "0.10.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "An externalities provided environemnt that can load itself from remote nodes or cache files" readme = "README.md" diff --git a/utils/frame/rpc/support/Cargo.toml b/utils/frame/rpc/support/Cargo.toml index a94f18d0e892..2010d1e02f73 100644 --- a/utils/frame/rpc/support/Cargo.toml +++ b/utils/frame/rpc/support/Cargo.toml @@ -7,7 +7,7 @@ authors = [ ] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Substrate RPC for FRAME's support" diff --git a/utils/frame/rpc/system/Cargo.toml b/utils/frame/rpc/system/Cargo.toml index e9ae506ef6b0..85868836f045 100644 --- a/utils/frame/rpc/system/Cargo.toml +++ b/utils/frame/rpc/system/Cargo.toml @@ -4,7 +4,7 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "FRAME's system exposed over Substrate RPC" readme = "README.md" diff --git a/utils/frame/try-runtime/cli/Cargo.toml b/utils/frame/try-runtime/cli/Cargo.toml index 6f4fd91126fb..e922af971044 100644 --- a/utils/frame/try-runtime/cli/Cargo.toml +++ b/utils/frame/try-runtime/cli/Cargo.toml @@ -4,7 +4,7 @@ version = "0.10.0-dev" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Cli command runtime testing and dry-running" readme = "README.md" diff --git a/utils/frame/try-runtime/cli/src/lib.rs b/utils/frame/try-runtime/cli/src/lib.rs index d5ccca956025..28e51b38f2ac 100644 --- a/utils/frame/try-runtime/cli/src/lib.rs +++ b/utils/frame/try-runtime/cli/src/lib.rs @@ -29,9 +29,9 @@ //! //! Some resources about the above: //! -//! 1. +//! 1. //! 2. -//! 3. +//! 3. //! //! --- //! diff --git a/utils/prometheus/Cargo.toml b/utils/prometheus/Cargo.toml index 43de76eee212..4d218e233bcb 100644 --- a/utils/prometheus/Cargo.toml +++ b/utils/prometheus/Cargo.toml @@ -5,7 +5,7 @@ version = "0.9.0" license = "Apache-2.0" authors = ["Parity Technologies "] edition = "2018" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" readme = "README.md" diff --git a/utils/wasm-builder/Cargo.toml b/utils/wasm-builder/Cargo.toml index 721f332e130f..92b1af753ef6 100644 --- a/utils/wasm-builder/Cargo.toml +++ b/utils/wasm-builder/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" readme = "README.md" repository = "https://github.com/paritytech/substrate/" license = "Apache-2.0" -homepage = "https://substrate.dev" +homepage = "https://substrate.io" [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] From 00629de9b7aae97e041b21b081f469eb834169a7 Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Thu, 14 Oct 2021 12:44:07 +0100 Subject: [PATCH 085/695] make the ws buffer size configurable (#10013) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * make the ws buffer size configurable * Update client/cli/src/commands/run_cmd.rs Co-authored-by: Tomasz Drwięga * Update client/cli/src/commands/run_cmd.rs Co-authored-by: Tomasz Drwięga * Update client/cli/src/commands/run_cmd.rs Co-authored-by: Bastian Köcher * Final touches * Apply suggestions from code review * fix bench * remove in buffer * Apply suggestions from code review Co-authored-by: Tomasz Drwięga Co-authored-by: Tomasz Drwięga Co-authored-by: Bastian Köcher --- bin/node/cli/benches/transaction_pool.rs | 1 + client/cli/src/commands/run_cmd.rs | 8 ++++++++ client/cli/src/config.rs | 6 ++++++ client/rpc-servers/src/lib.rs | 21 +++++++++++++++++++-- client/service/src/config.rs | 2 ++ client/service/src/lib.rs | 1 + client/service/test/src/lib.rs | 1 + test-utils/test-runner/src/utils.rs | 1 + 8 files changed, 39 insertions(+), 2 deletions(-) diff --git a/bin/node/cli/benches/transaction_pool.rs b/bin/node/cli/benches/transaction_pool.rs index 3b0ee26d7d59..4f5ccd6ea912 100644 --- a/bin/node/cli/benches/transaction_pool.rs +++ b/bin/node/cli/benches/transaction_pool.rs @@ -85,6 +85,7 @@ fn new_node(tokio_handle: Handle) -> node_cli::service::NewFullBase { rpc_cors: None, rpc_methods: Default::default(), rpc_max_payload: None, + ws_max_out_buffer_capacity: None, prometheus_config: None, telemetry_endpoints: None, default_heap_pages: None, diff --git a/client/cli/src/commands/run_cmd.rs b/client/cli/src/commands/run_cmd.rs index b43135f10973..d6c0133a7c14 100644 --- a/client/cli/src/commands/run_cmd.rs +++ b/client/cli/src/commands/run_cmd.rs @@ -127,6 +127,10 @@ pub struct RunCmd { #[structopt(long = "ws-max-connections", value_name = "COUNT")] pub ws_max_connections: Option, + /// Set the the maximum WebSocket output buffer size in MiB. Default is 16. + #[structopt(long = "ws-max-out-buffer-capacity")] + pub ws_max_out_buffer_capacity: Option, + /// Specify browser Origins allowed to access the HTTP & WS RPC servers. /// /// A comma-separated list of origins (protocol://domain or special `null` @@ -434,6 +438,10 @@ impl CliConfiguration for RunCmd { Ok(self.rpc_max_payload) } + fn ws_max_out_buffer_capacity(&self) -> Result> { + Ok(self.ws_max_out_buffer_capacity) + } + fn transaction_pool(&self) -> Result { Ok(self.pool_config.transaction_pool()) } diff --git a/client/cli/src/config.rs b/client/cli/src/config.rs index f79405bd6132..86eeed5b4023 100644 --- a/client/cli/src/config.rs +++ b/client/cli/src/config.rs @@ -360,6 +360,11 @@ pub trait CliConfiguration: Sized { Ok(None) } + /// Get maximum WS output buffer capacity. + fn ws_max_out_buffer_capacity(&self) -> Result> { + Ok(None) + } + /// Get the prometheus configuration (`None` if disabled) /// /// By default this is `None`. @@ -513,6 +518,7 @@ pub trait CliConfiguration: Sized { rpc_ws_max_connections: self.rpc_ws_max_connections()?, rpc_cors: self.rpc_cors(is_dev)?, rpc_max_payload: self.rpc_max_payload()?, + ws_max_out_buffer_capacity: self.ws_max_out_buffer_capacity()?, prometheus_config: self.prometheus_config(DCV::prometheus_listen_port())?, telemetry_endpoints, default_heap_pages: self.default_heap_pages()?, diff --git a/client/rpc-servers/src/lib.rs b/client/rpc-servers/src/lib.rs index 65ed6a914b19..1ac409d6ba89 100644 --- a/client/rpc-servers/src/lib.rs +++ b/client/rpc-servers/src/lib.rs @@ -33,6 +33,9 @@ const MEGABYTE: usize = 1024 * 1024; /// Maximal payload accepted by RPC servers. pub const RPC_MAX_PAYLOAD_DEFAULT: usize = 15 * MEGABYTE; +/// Maximal buffer size in WS server. +pub const WS_MAX_BUFFER_CAPACITY_DEFAULT: usize = 16 * MEGABYTE; + /// Default maximum number of connections for WS RPC servers. const WS_MAX_CONNECTIONS: usize = 100; @@ -172,18 +175,32 @@ pub fn start_ws< cors: Option<&Vec>, io: RpcHandler, maybe_max_payload_mb: Option, + maybe_max_out_buffer_capacity_mb: Option, server_metrics: ServerMetrics, tokio_handle: tokio::runtime::Handle, ) -> io::Result { - let rpc_max_payload = maybe_max_payload_mb + let max_payload = maybe_max_payload_mb .map(|mb| mb.saturating_mul(MEGABYTE)) .unwrap_or(RPC_MAX_PAYLOAD_DEFAULT); + let max_out_buffer_capacity = maybe_max_out_buffer_capacity_mb + .map(|mb| mb.saturating_mul(MEGABYTE)) + .unwrap_or(WS_MAX_BUFFER_CAPACITY_DEFAULT); + + if max_payload > max_out_buffer_capacity { + log::warn!( + "maximum payload ({}) is more than maximum output buffer ({}) size in ws server, the payload will actually be limited by the buffer size", + max_payload, + max_out_buffer_capacity, + ) + } + ws::ServerBuilder::with_meta_extractor(io, |context: &ws::RequestContext| { context.sender().into() }) .event_loop_executor(tokio_handle) - .max_payload(rpc_max_payload) + .max_payload(max_payload) .max_connections(max_connections.unwrap_or(WS_MAX_CONNECTIONS)) + .max_out_buffer_capacity(max_out_buffer_capacity) .allowed_origins(map_cors(cors)) .allowed_hosts(hosts_filtering(cors.is_some())) .session_stats(server_metrics) diff --git a/client/service/src/config.rs b/client/service/src/config.rs index b4f6bf70e05b..d3bd4e4e4879 100644 --- a/client/service/src/config.rs +++ b/client/service/src/config.rs @@ -97,6 +97,8 @@ pub struct Configuration { pub rpc_methods: RpcMethods, /// Maximum payload of rpc request/responses. pub rpc_max_payload: Option, + /// Maximum size of the output buffer capacity for websocket connections. + pub ws_max_out_buffer_capacity: Option, /// Prometheus endpoint configuration. `None` if disabled. pub prometheus_config: Option, /// Telemetry service URL. `None` if disabled. diff --git a/client/service/src/lib.rs b/client/service/src/lib.rs index 7284747424aa..8d8c54cc25f2 100644 --- a/client/service/src/lib.rs +++ b/client/service/src/lib.rs @@ -424,6 +424,7 @@ fn start_rpc_servers< ), )?, config.rpc_max_payload, + config.ws_max_out_buffer_capacity, server_metrics.clone(), config.tokio_handle.clone(), ) diff --git a/client/service/test/src/lib.rs b/client/service/test/src/lib.rs index d85ad8d36111..a4e740aabc18 100644 --- a/client/service/test/src/lib.rs +++ b/client/service/test/src/lib.rs @@ -261,6 +261,7 @@ fn node_config< rpc_cors: None, rpc_methods: Default::default(), rpc_max_payload: None, + ws_max_out_buffer_capacity: None, prometheus_config: None, telemetry_endpoints: None, default_heap_pages: None, diff --git a/test-utils/test-runner/src/utils.rs b/test-utils/test-runner/src/utils.rs index 3ab77af96c16..a4c45c25f969 100644 --- a/test-utils/test-runner/src/utils.rs +++ b/test-utils/test-runner/src/utils.rs @@ -94,6 +94,7 @@ pub fn default_config(tokio_handle: Handle, mut chain_spec: Box) rpc_cors: None, rpc_methods: Default::default(), rpc_max_payload: None, + ws_max_out_buffer_capacity: None, prometheus_config: None, telemetry_endpoints: None, default_heap_pages: None, From f87ea7d934f76afba458c75efb6dde9d636a2a97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Paulo=20Silva=20de=20Souza?= <77391175+joao-paulo-parity@users.noreply.github.com> Date: Thu, 14 Oct 2021 09:29:50 -0300 Subject: [PATCH 086/695] use pipeline-scripts for dependent projects script (#9749) --- .gitlab-ci.yml | 47 ++++---- .../gitlab/check_polkadot_companion_build.sh | 99 ----------------- .../gitlab/check_polkadot_companion_status.sh | 102 ------------------ 3 files changed, 28 insertions(+), 220 deletions(-) delete mode 100755 .maintain/gitlab/check_polkadot_companion_build.sh delete mode 100755 .maintain/gitlab/check_polkadot_companion_status.sh diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ae6a81611f2d..d36fe2b57add 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -46,6 +46,7 @@ variables: &default-vars VAULT_AUTH_PATH: "gitlab-parity-io-jwt" VAULT_AUTH_ROLE: "cicd_gitlab_parity_${CI_PROJECT_NAME}" SIMNET_FEATURES_PATH: "simnet_tests/tests" + PIPELINE_SCRIPTS_TAG: "v0.1" default: cache: {} @@ -538,29 +539,37 @@ cargo-check-macos: #### stage: build -check-polkadot-companion-status: - stage: build - image: paritytech/tools:latest - <<: *kubernetes-env - <<: *vault-secrets - rules: - - if: $CI_COMMIT_REF_NAME =~ /^[0-9]+$/ # PRs - script: - - ./.maintain/gitlab/check_polkadot_companion_status.sh - -check-polkadot-companion-build: +.check-dependent-project: &check-dependent-project stage: build <<: *docker-env <<: *test-refs-no-trigger <<: *vault-secrets - needs: - - job: test-linux-stable-int - artifacts: false script: - - ./.maintain/gitlab/check_polkadot_companion_build.sh - after_script: - - cd polkadot && git rev-parse --abbrev-ref HEAD - allow_failure: true + - git clone + --depth=1 + "--branch=$PIPELINE_SCRIPTS_TAG" + https://github.com/paritytech/pipeline-scripts + - ./pipeline-scripts/check_dependent_project.sh + paritytech + substrate + --substrate + "$DEPENDENT_REPO" + "$GITHUB_PR_TOKEN" + - cd "$DEPENDENT_REPO" && git rev-parse --abbrev-ref HEAD + +# Individual jobs are set up for each dependent project so that they can be ran in parallel. +# Arguably we could generate a job for each companion in the PR's description using Gitlab's +# parent-child pipelines but that's more complicated. + +check-dependent-polkadot: + <<: *check-dependent-project + variables: + DEPENDENT_REPO: polkadot + +check-dependent-cumulus: + <<: *check-dependent-project + variables: + DEPENDENT_REPO: cumulus build-linux-substrate: &build-binary stage: build @@ -884,7 +893,7 @@ deploy-prometheus-alerting-rules: # Runs "quick" and "long" tests on nightly schedule and on commit / merge to master # A "quick" test is a smoke test where basic check-expect tests run by # checking values from metrics exposed by the app. -# A "long" test is the load testing where we send 50K transactions into the +# A "long" test is the load testing where we send 50K transactions into the # network and check if all completed successfully simnet-tests: stage: deploy diff --git a/.maintain/gitlab/check_polkadot_companion_build.sh b/.maintain/gitlab/check_polkadot_companion_build.sh deleted file mode 100755 index 72bfaf715152..000000000000 --- a/.maintain/gitlab/check_polkadot_companion_build.sh +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env sh -# -# check if a pr is compatible with polkadot companion pr or master if not -# available -# -# to override one that was just mentioned mark companion pr in the body of the -# polkadot pr like -# -# polkadot companion: paritytech/polkadot#567 -# - -set -e - -github_api_substrate_pull_url="https://api.github.com/repos/paritytech/substrate/pulls" -# use github api v3 in order to access the data without authentication -github_header="Authorization: token ${GITHUB_PR_TOKEN}" - -boldprint () { printf "|\n| \033[1m${@}\033[0m\n|\n" ; } -boldcat () { printf "|\n"; while read l; do printf "| \033[1m${l}\033[0m\n"; done; printf "|\n" ; } - - - -boldcat <<-EOT - - -check_polkadot_companion_build -============================== - -this job checks if there is a string in the description of the pr like - -polkadot companion: paritytech/polkadot#567 - - -it will then run cargo check from this polkadot's branch with substrate code -from this pull request. otherwise, it will uses master instead - - -EOT - -# Set the user name and email to make merging work -git config --global user.name 'CI system' -git config --global user.email '<>' - -# Merge master into our branch before building Polkadot to make sure we don't miss -# any commits that are required by Polkadot. -git fetch --depth 100 origin -git merge origin/master - -# Clone the current Polkadot master branch into ./polkadot. -# NOTE: we need to pull enough commits to be able to find a common -# ancestor for successfully performing merges below. -git clone --depth 20 https://github.com/paritytech/polkadot.git - -cd polkadot - -# either it's a pull request then check for a companion otherwise use -# polkadot:master -if expr match "${CI_COMMIT_REF_NAME}" '^[0-9]\+$' >/dev/null -then - boldprint "this is pull request no ${CI_COMMIT_REF_NAME}" - - pr_data_file="$(mktemp)" - # get the last reference to a pr in polkadot - curl -sSL -H "${github_header}" -o "${pr_data_file}" \ - "${github_api_substrate_pull_url}/${CI_COMMIT_REF_NAME}" - - pr_body="$(sed -n -r 's/^[[:space:]]+"body": (".*")[^"]+$/\1/p' "${pr_data_file}")" - - pr_companion="$(echo "${pr_body}" | sed -n -r \ - -e 's;^.*[Cc]ompanion.*paritytech/polkadot#([0-9]+).*$;\1;p' \ - -e 's;^.*[Cc]ompanion.*https://github.com/paritytech/polkadot/pull/([0-9]+).*$;\1;p' \ - | tail -n 1)" - - if [ "${pr_companion}" ] - then - boldprint "companion pr specified/detected: #${pr_companion}" - git fetch origin refs/pull/${pr_companion}/head:pr/${pr_companion} - git checkout pr/${pr_companion} - git merge origin/master - else - boldprint "no companion branch found - building polkadot:master" - fi - rm -f "${pr_data_file}" -else - boldprint "this is not a pull request - building polkadot:master" -fi - -# Patch all Substrate crates in Polkadot -diener patch --crates-to-patch ../ --substrate --path Cargo.toml - -# We need to update specifically our patched Substrate crates so that other -# crates that depend on them (e.g. Polkadot, BEEFY) use this unified version -# NOTE: There's no way to only update patched crates, so we use a heuristic -# of updating a crucial Substrate crate (`sp-core`) to minimize the impact of -# updating unrelated dependencies -cargo update -p sp-core - -# Test Polkadot pr or master branch with this Substrate commit. -time cargo test --workspace --release --verbose --features=runtime-benchmarks diff --git a/.maintain/gitlab/check_polkadot_companion_status.sh b/.maintain/gitlab/check_polkadot_companion_status.sh deleted file mode 100755 index e0412c7b7bec..000000000000 --- a/.maintain/gitlab/check_polkadot_companion_status.sh +++ /dev/null @@ -1,102 +0,0 @@ -#!/bin/sh -# -# check for a polkadot companion pr and ensure it has approvals and is -# mergeable -# - -github_api_substrate_pull_url="https://api.github.com/repos/paritytech/substrate/pulls" -github_api_polkadot_pull_url="https://api.github.com/repos/paritytech/polkadot/pulls" -# use github api v3 in order to access the data without authentication -github_header="Authorization: token ${GITHUB_PR_TOKEN}" - -boldprint () { printf "|\n| \033[1m${@}\033[0m\n|\n" ; } -boldcat () { printf "|\n"; while read l; do printf "| \033[1m${l}\033[0m\n"; done; printf "|\n" ; } - - - -boldcat <<-EOT - - -check_polkadot_companion_status -=============================== - -this job checks if there is a string in the description of the pr like - -polkadot companion: paritytech/polkadot#567 - -and checks its status. - - -EOT - - -if ! [ "${CI_COMMIT_REF_NAME}" -gt 0 2>/dev/null ] -then - boldprint "this doesn't seem to be a pull request" - exit 1 -fi - -boldprint "this is pull request no ${CI_COMMIT_REF_NAME}" - -pr_body="$(curl -H "${github_header}" -s ${github_api_substrate_pull_url}/${CI_COMMIT_REF_NAME} \ - | sed -n -r 's/^[[:space:]]+"body": (".*")[^"]+$/\1/p')" - -# get companion if explicitly specified -pr_companion="$(echo "${pr_body}" | sed -n -r \ - -e 's;^.*[Cc]ompanion.*paritytech/polkadot#([0-9]+).*$;\1;p' \ - -e 's;^.*[Cc]ompanion.*https://github.com/paritytech/polkadot/pull/([0-9]+).*$;\1;p' \ - | tail -n 1)" - -if [ -z "${pr_companion}" ] -then - boldprint "no companion pr found" - exit 0 -fi - -boldprint "companion pr: #${pr_companion}" - -# check the status of that pull request - needs to be -# approved and mergable - -curl -H "${github_header}" -sS -o companion_pr.json \ - ${github_api_polkadot_pull_url}/${pr_companion} - -pr_head_sha=$(jq -r -e '.head.sha' < companion_pr.json) -boldprint "Polkadot PR's HEAD SHA: $pr_head_sha" - -curl -H "${github_header}" -sS -o companion_pr_reviews.json \ - ${github_api_polkadot_pull_url}/${pr_companion}/reviews - -# If there are any 'CHANGES_REQUESTED' reviews for the *current* review -jq -r -e '.[] | select(.state == "CHANGES_REQUESTED").commit_id' \ - < companion_pr_reviews.json > companion_pr_reviews_current.json -while IFS= read -r line; do - if [ "$line" = "$pr_head_sha" ]; then - boldprint "polkadot pr #${pr_companion} has CHANGES_REQUESTED for the latest commit" - exit 1 - fi -done < companion_pr_reviews_current.json - -# Then we check for at least 1 APPROVED -if [ -z "$(jq -r -e '.[].state | select(. == "APPROVED")' < companion_pr_reviews.json)" ]; then - boldprint "polkadot pr #${pr_companion} not APPROVED" - exit 1 -fi - -boldprint "polkadot pr #${pr_companion} state APPROVED" - -if jq -e .merged < companion_pr.json >/dev/null -then - boldprint "polkadot pr #${pr_companion} already merged" - exit 0 -fi - -if jq -e '.mergeable' < companion_pr.json >/dev/null -then - boldprint "polkadot pr #${pr_companion} mergeable" -else - boldprint "polkadot pr #${pr_companion} not mergeable" - exit 1 -fi - -exit 0 From f70b1ca1f7249d557b622be2640a6bc9d7ec4f84 Mon Sep 17 00:00:00 2001 From: Gavin Wood Date: Thu, 14 Oct 2021 16:45:49 +0200 Subject: [PATCH 087/695] More lenient mechanism for identifying stash accounts in purge_keys (#10004) * More lenient StashOf finder * Slightly safer version of the change * Slightly safer version of the change * Tests * Formatting --- frame/session/src/lib.rs | 38 +++++++++++++++++++++++++------------- frame/session/src/mock.rs | 23 ++++++++++++++++++++--- frame/session/src/tests.rs | 29 ++++++++++++++++++++++++++++- 3 files changed, 73 insertions(+), 17 deletions(-) diff --git a/frame/session/src/lib.rs b/frame/session/src/lib.rs index 10c7ea42b3e9..7fe163e0dfea 100644 --- a/frame/session/src/lib.rs +++ b/frame/session/src/lib.rs @@ -114,17 +114,6 @@ mod mock; mod tests; pub mod weights; -use sp_runtime::{ - traits::{AtLeast32BitUnsigned, Convert, Member, One, OpaqueKeys, Zero}, - ConsensusEngineId, KeyTypeId, Permill, RuntimeAppPublic, -}; -use sp_staking::SessionIndex; -use sp_std::{ - marker::PhantomData, - ops::{Rem, Sub}, - prelude::*, -}; - use frame_support::{ codec::{Decode, MaxEncodedLen}, dispatch::{DispatchError, DispatchResult}, @@ -136,6 +125,17 @@ use frame_support::{ weights::Weight, Parameter, }; +use sp_runtime::{ + traits::{AtLeast32BitUnsigned, Convert, Member, One, OpaqueKeys, Zero}, + ConsensusEngineId, KeyTypeId, Permill, RuntimeAppPublic, +}; +use sp_staking::SessionIndex; +use sp_std::{ + convert::TryFrom, + marker::PhantomData, + ops::{Rem, Sub}, + prelude::*, +}; pub use pallet::*; pub use weights::WeightInfo; @@ -377,7 +377,11 @@ pub mod pallet { type Event: From + IsType<::Event>; /// A stable ID for a validator. - type ValidatorId: Member + Parameter + MaybeSerializeDeserialize + MaxEncodedLen; + type ValidatorId: Member + + Parameter + + MaybeSerializeDeserialize + + MaxEncodedLen + + TryFrom; /// A conversion from account ID to validator ID. /// @@ -595,9 +599,13 @@ pub mod pallet { } /// Removes any session key(s) of the function caller. + /// /// This doesn't take effect until the next session. /// - /// The dispatch origin of this function must be signed. + /// The dispatch origin of this function must be Signed and the account must be either be + /// convertible to a validator ID using the chain's typical addressing system (this usually + /// means being a controller account) or directly convertible into a validator ID (which + /// usually means being a stash account). /// /// # /// - Complexity: `O(1)` in number of key types. Actual cost depends on the number of length @@ -841,6 +849,10 @@ impl Pallet { fn do_purge_keys(account: &T::AccountId) -> DispatchResult { let who = T::ValidatorIdOf::convert(account.clone()) + // `purge_keys` may not have a controller-stash pair any more. If so then we expect the + // stash account to be passed in directly and convert that to a `ValidatorId` using the + // `TryFrom` trait if supported. + .or_else(|| T::ValidatorId::try_from(account.clone()).ok()) .ok_or(Error::::NoAssociatedValidatorId)?; let old_keys = Self::take_keys(&who).ok_or(Error::::NoKeys)?; diff --git a/frame/session/src/mock.rs b/frame/session/src/mock.rs index 277dec610659..6db7727fa539 100644 --- a/frame/session/src/mock.rs +++ b/frame/session/src/mock.rs @@ -22,13 +22,13 @@ use crate as pallet_session; #[cfg(feature = "historical")] use crate::historical as pallet_session_historical; -use std::cell::RefCell; +use std::{cell::RefCell, collections::BTreeMap}; use sp_core::{crypto::key_types::DUMMY, H256}; use sp_runtime::{ impl_opaque_keys, testing::{Header, UintAuthorityId}, - traits::{BlakeTwo256, ConvertInto, IdentityLookup}, + traits::{BlakeTwo256, IdentityLookup}, }; use sp_staking::SessionIndex; @@ -111,6 +111,7 @@ thread_local! { pub static DISABLED: RefCell = RefCell::new(false); // Stores if `on_before_session_end` was called pub static BEFORE_SESSION_END_CALLED: RefCell = RefCell::new(false); + pub static VALIDATOR_ACCOUNTS: RefCell> = RefCell::new(BTreeMap::new()); } pub struct TestShouldEndSession; @@ -225,6 +226,10 @@ pub fn new_test_ext() -> sp_io::TestExternalities { pallet_session::GenesisConfig:: { keys } .assimilate_storage(&mut t) .unwrap(); + NEXT_VALIDATORS.with(|l| { + let v = l.borrow().iter().map(|&i| (i, i)).collect(); + VALIDATOR_ACCOUNTS.with(|m| *m.borrow_mut() = v); + }); sp_io::TestExternalities::new(t) } @@ -268,6 +273,18 @@ impl pallet_timestamp::Config for Test { type WeightInfo = (); } +pub struct TestValidatorIdOf; +impl TestValidatorIdOf { + pub fn set(v: BTreeMap) { + VALIDATOR_ACCOUNTS.with(|m| *m.borrow_mut() = v); + } +} +impl Convert> for TestValidatorIdOf { + fn convert(x: u64) -> Option { + VALIDATOR_ACCOUNTS.with(|m| m.borrow().get(&x).cloned()) + } +} + impl Config for Test { type ShouldEndSession = TestShouldEndSession; #[cfg(feature = "historical")] @@ -276,7 +293,7 @@ impl Config for Test { type SessionManager = TestSessionManager; type SessionHandler = TestSessionHandler; type ValidatorId = u64; - type ValidatorIdOf = ConvertInto; + type ValidatorIdOf = TestValidatorIdOf; type Keys = MockSessionKeys; type Event = Event; type NextSessionRotation = (); diff --git a/frame/session/src/tests.rs b/frame/session/src/tests.rs index 42a2dd74fd96..308ed7c5e548 100644 --- a/frame/session/src/tests.rs +++ b/frame/session/src/tests.rs @@ -21,7 +21,7 @@ use super::*; use crate::mock::{ authorities, before_session_end_called, force_new_session, new_test_ext, reset_before_session_end_called, session_changed, set_next_validators, set_session_length, - Origin, PreUpgradeMockSessionKeys, Session, System, Test, SESSION_CHANGED, + Origin, PreUpgradeMockSessionKeys, Session, System, Test, TestValidatorIdOf, SESSION_CHANGED, TEST_SESSION_CHANGED, }; @@ -72,11 +72,35 @@ fn keys_cleared_on_kill() { }) } +#[test] +fn purge_keys_works_for_stash_id() { + let mut ext = new_test_ext(); + ext.execute_with(|| { + assert_eq!(Session::validators(), vec![1, 2, 3]); + TestValidatorIdOf::set(vec![(10, 1), (20, 2), (3, 3)].into_iter().collect()); + assert_eq!(Session::load_keys(&1), Some(UintAuthorityId(1).into())); + assert_eq!(Session::load_keys(&2), Some(UintAuthorityId(2).into())); + + let id = DUMMY; + assert_eq!(Session::key_owner(id, UintAuthorityId(1).get_raw(id)), Some(1)); + + assert_ok!(Session::purge_keys(Origin::signed(10))); + assert_ok!(Session::purge_keys(Origin::signed(2))); + + assert_eq!(Session::load_keys(&10), None); + assert_eq!(Session::load_keys(&20), None); + assert_eq!(Session::key_owner(id, UintAuthorityId(10).get_raw(id)), None); + assert_eq!(Session::key_owner(id, UintAuthorityId(20).get_raw(id)), None); + }) +} + #[test] fn authorities_should_track_validators() { reset_before_session_end_called(); new_test_ext().execute_with(|| { + TestValidatorIdOf::set(vec![(1, 1), (2, 2), (3, 3), (4, 4)].into_iter().collect()); + set_next_validators(vec![1, 2]); force_new_session(); initialize_block(1); @@ -187,6 +211,8 @@ fn session_change_should_work() { #[test] fn duplicates_are_not_allowed() { new_test_ext().execute_with(|| { + TestValidatorIdOf::set(vec![(1, 1), (2, 2), (3, 3), (4, 4)].into_iter().collect()); + System::set_block_number(1); Session::on_initialize(1); assert_noop!( @@ -205,6 +231,7 @@ fn session_changed_flag_works() { reset_before_session_end_called(); new_test_ext().execute_with(|| { + TestValidatorIdOf::set(vec![(1, 1), (2, 2), (3, 3), (69, 69)].into_iter().collect()); TEST_SESSION_CHANGED.with(|l| *l.borrow_mut() = true); force_new_session(); From afd572f208b25312f984987b7bb752e71fbf86d7 Mon Sep 17 00:00:00 2001 From: Cheng JIANG Date: Fri, 15 Oct 2021 18:22:51 +0800 Subject: [PATCH 088/695] add TypeInfo trait bound (#10031) --- frame/assets/src/lib.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/frame/assets/src/lib.rs b/frame/assets/src/lib.rs index 1ae729d7774d..4176242c8394 100644 --- a/frame/assets/src/lib.rs +++ b/frame/assets/src/lib.rs @@ -170,6 +170,7 @@ pub mod pallet { use super::*; use frame_support::{dispatch::DispatchResult, pallet_prelude::*}; use frame_system::pallet_prelude::*; + use scale_info::TypeInfo; #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] @@ -189,7 +190,8 @@ pub mod pallet { + Default + Copy + MaybeSerializeDeserialize - + MaxEncodedLen; + + MaxEncodedLen + + TypeInfo; /// Identifier for the class of asset. type AssetId: Member @@ -198,7 +200,8 @@ pub mod pallet { + Copy + HasCompact + MaybeSerializeDeserialize - + MaxEncodedLen; + + MaxEncodedLen + + TypeInfo; /// The currency mechanism. type Currency: ReservableCurrency; From 09c916c6272abde6ada166a8838d450038ec1284 Mon Sep 17 00:00:00 2001 From: Cheng JIANG Date: Mon, 18 Oct 2021 14:37:22 +0800 Subject: [PATCH 089/695] AssetId trait should also contain TypeInfo bound (#10038) --- frame/support/src/traits/tokens/misc.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frame/support/src/traits/tokens/misc.rs b/frame/support/src/traits/tokens/misc.rs index 214c28708a19..100138171abe 100644 --- a/frame/support/src/traits/tokens/misc.rs +++ b/frame/support/src/traits/tokens/misc.rs @@ -161,8 +161,8 @@ impl WithdrawReasons { } /// Simple amalgamation trait to collect together properties for an AssetId under one roof. -pub trait AssetId: FullCodec + Copy + Eq + PartialEq + Debug {} -impl AssetId for T {} +pub trait AssetId: FullCodec + Copy + Eq + PartialEq + Debug + scale_info::TypeInfo {} +impl AssetId for T {} /// Simple amalgamation trait to collect together properties for a Balance under one roof. pub trait Balance: From 129c16b294f9bb904ce04da78ada98bf168421be Mon Sep 17 00:00:00 2001 From: Alexander Samusev <41779041+alvicsam@users.noreply.github.com> Date: Mon, 18 Oct 2021 09:12:22 +0200 Subject: [PATCH 090/695] CI: remove node-template from build-linux-substrate-simnet job (#10034) * ci: remove node-template from build-linux-substrate-simnet * build-linux-substrate job impovements * small fix --- .gitlab-ci.yml | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d36fe2b57add..6d4362ea9362 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -178,6 +178,21 @@ default: | tee artifacts/benches/$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA/::trie::read::small.json' - sccache -s +.build-linux-substrate-script: &build-linux-substrate-script + - WASM_BUILD_NO_COLOR=1 time cargo build --release --verbose + - mv ./target/release/substrate ./artifacts/substrate/. + - echo -n "Substrate version = " + - if [ "${CI_COMMIT_TAG}" ]; then + echo "${CI_COMMIT_TAG}" | tee ./artifacts/substrate/VERSION; + else + ./artifacts/substrate/substrate --version | + sed -n -E 's/^substrate ([0-9.]+.*-[0-9a-f]{7,13})-.*$/\1/p' | + tee ./artifacts/substrate/VERSION; + fi + - sha256sum ./artifacts/substrate/substrate | tee ./artifacts/substrate/substrate.sha256 + - cp -r .maintain/docker/substrate.Dockerfile ./artifacts/substrate/ + - sccache -s + #### Vault secrets .vault-secrets: &vault-secrets secrets: @@ -571,7 +586,8 @@ check-dependent-cumulus: variables: DEPENDENT_REPO: cumulus -build-linux-substrate: &build-binary + +build-linux-substrate: stage: build <<: *collect-artifacts <<: *docker-env @@ -582,27 +598,21 @@ build-linux-substrate: &build-binary before_script: - mkdir -p ./artifacts/substrate/ script: - - WASM_BUILD_NO_COLOR=1 time cargo build --release --verbose - - mv ./target/release/substrate ./artifacts/substrate/. - - echo -n "Substrate version = " - - if [ "${CI_COMMIT_TAG}" ]; then - echo "${CI_COMMIT_TAG}" | tee ./artifacts/substrate/VERSION; - else - ./artifacts/substrate/substrate --version | - sed -n -E 's/^substrate ([0-9.]+.*-[0-9a-f]{7,13})-.*$/\1/p' | - tee ./artifacts/substrate/VERSION; - fi - - sha256sum ./artifacts/substrate/substrate | tee ./artifacts/substrate/substrate.sha256 + - *build-linux-substrate-script - printf '\n# building node-template\n\n' - ./.maintain/node-template-release.sh ./artifacts/substrate/substrate-node-template.tar.gz - - cp -r .maintain/docker/substrate.Dockerfile ./artifacts/substrate/ - - sccache -s + #Build binary for simnet quick tests. build-linux-substrate-simnet: - <<: *build-binary + stage: build <<: *collect-artifacts-short + <<: *docker-env <<: *test-refs-no-trigger-prs-only + before_script: + - mkdir -p ./artifacts/substrate/ + script: + - *build-linux-substrate-script build-linux-subkey: &build-subkey stage: build From 4a99c091a97bf829e17a53e1a22a87ddc7b4df22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Mon, 18 Oct 2021 10:18:13 +0200 Subject: [PATCH 091/695] Make duration calculation robust against clock drift (#10042) It is possible that `Instant::now()` is returning an earlier clock time when being called a second time. To guard against this, we should use `saturating_duration_since`. --- client/db/src/lib.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/client/db/src/lib.rs b/client/db/src/lib.rs index 549ef4012a73..3b8936c0f7ba 100644 --- a/client/db/src/lib.rs +++ b/client/db/src/lib.rs @@ -1076,13 +1076,14 @@ impl FrozenForDuration { F: FnOnce() -> T, { let mut lock = self.value.lock(); - if lock.at.elapsed() > self.duration || lock.value.is_none() { + let now = std::time::Instant::now(); + if now.saturating_duration_since(lock.at) > self.duration || lock.value.is_none() { let new_value = f(); - lock.at = std::time::Instant::now(); + lock.at = now; lock.value = Some(new_value.clone()); new_value } else { - lock.value.as_ref().expect("checked with lock above").clone() + lock.value.as_ref().expect("Checked with in branch above; qed").clone() } } } From abeea6d04d72eddb136ec494298035977c9cdbe4 Mon Sep 17 00:00:00 2001 From: Guillaume Thiolliere Date: Mon, 18 Oct 2021 11:19:35 +0200 Subject: [PATCH 092/695] Update lowest unbaked storage. (#9750) * update lowest unbaked * fix format * add note * fmt --- frame/democracy/src/lib.rs | 32 ++++++++++++----- frame/democracy/src/tests.rs | 2 +- frame/democracy/src/tests/cancellation.rs | 4 +++ frame/democracy/src/tests/scheduling.rs | 44 +++++++++++++++++++++++ 4 files changed, 72 insertions(+), 10 deletions(-) diff --git a/frame/democracy/src/lib.rs b/frame/democracy/src/lib.rs index 50b245006fa2..893e4676bef7 100644 --- a/frame/democracy/src/lib.rs +++ b/frame/democracy/src/lib.rs @@ -613,10 +613,7 @@ pub mod pallet { impl Hooks> for Pallet { /// Weight: see `begin_block` fn on_initialize(n: T::BlockNumber) -> Weight { - Self::begin_block(n).unwrap_or_else(|e| { - sp_runtime::print(e); - 0 - }) + Self::begin_block(n) } } @@ -1682,7 +1679,7 @@ impl Pallet { now: T::BlockNumber, index: ReferendumIndex, status: ReferendumStatus>, - ) -> Result { + ) -> bool { let total_issuance = T::Currency::total_issuance(); let approved = status.threshold.approved(status.tally, total_issuance); @@ -1719,7 +1716,7 @@ impl Pallet { Self::deposit_event(Event::::NotPassed(index)); } - Ok(approved) + approved } /// Current era is ending; we should finish up any proposals. @@ -1734,7 +1731,7 @@ impl Pallet { /// - Db writes: `PublicProps`, `account`, `ReferendumCount`, `DepositOf`, `ReferendumInfoOf` /// - Db reads per R: `DepositOf`, `ReferendumInfoOf` /// # - fn begin_block(now: T::BlockNumber) -> Result { + fn begin_block(now: T::BlockNumber) -> Weight { let max_block_weight = T::BlockWeights::get().max_block; let mut weight = 0; @@ -1758,12 +1755,29 @@ impl Pallet { // tally up votes for any expiring referenda. for (index, info) in Self::maturing_referenda_at_inner(now, next..last).into_iter() { - let approved = Self::bake_referendum(now, index, info)?; + let approved = Self::bake_referendum(now, index, info); ReferendumInfoOf::::insert(index, ReferendumInfo::Finished { end: now, approved }); weight = max_block_weight; } - Ok(weight) + // Notes: + // * We don't consider the lowest unbaked to be the last maturing in case some refendum have + // longer voting period than others. + // * The iteration here shouldn't trigger any storage read that are not in cache, due to + // `maturing_referenda_at_inner` having already read them. + // * We shouldn't iterate more than `LaunchPeriod/VotingPeriod + 1` times because the number + // of unbaked referendum is bounded by this number. In case those number have changed in a + // runtime upgrade the formula should be adjusted but the bound should still be sensible. + >::mutate(|ref_index| { + while *ref_index < last && + Self::referendum_info(*ref_index) + .map_or(true, |info| matches!(info, ReferendumInfo::Finished { .. })) + { + *ref_index += 1 + } + }); + + weight } /// Reads the length of account in DepositOf without getting the complete value in the runtime. diff --git a/frame/democracy/src/tests.rs b/frame/democracy/src/tests.rs index 75104db51b97..f56667e9094b 100644 --- a/frame/democracy/src/tests.rs +++ b/frame/democracy/src/tests.rs @@ -264,7 +264,7 @@ fn propose_set_balance_and_note(who: u64, value: u64, delay: u64) -> DispatchRes fn next_block() { System::set_block_number(System::block_number() + 1); Scheduler::on_initialize(System::block_number()); - assert!(Democracy::begin_block(System::block_number()).is_ok()); + Democracy::begin_block(System::block_number()); } fn fast_forward_to(n: u64) { diff --git a/frame/democracy/src/tests/cancellation.rs b/frame/democracy/src/tests/cancellation.rs index c2bd725ce934..83822bf51829 100644 --- a/frame/democracy/src/tests/cancellation.rs +++ b/frame/democracy/src/tests/cancellation.rs @@ -30,10 +30,14 @@ fn cancel_referendum_should_work() { ); assert_ok!(Democracy::vote(Origin::signed(1), r, aye(1))); assert_ok!(Democracy::cancel_referendum(Origin::root(), r.into())); + assert_eq!(Democracy::lowest_unbaked(), 0); next_block(); + next_block(); + assert_eq!(Democracy::lowest_unbaked(), 1); + assert_eq!(Democracy::lowest_unbaked(), Democracy::referendum_count()); assert_eq!(Balances::free_balance(42), 0); }); } diff --git a/frame/democracy/src/tests/scheduling.rs b/frame/democracy/src/tests/scheduling.rs index 06b492bc6093..5c857a632b97 100644 --- a/frame/democracy/src/tests/scheduling.rs +++ b/frame/democracy/src/tests/scheduling.rs @@ -30,8 +30,10 @@ fn simple_passing_should_work() { ); assert_ok!(Democracy::vote(Origin::signed(1), r, aye(1))); assert_eq!(tally(r), Tally { ayes: 1, nays: 0, turnout: 10 }); + assert_eq!(Democracy::lowest_unbaked(), 0); next_block(); next_block(); + assert_eq!(Democracy::lowest_unbaked(), 1); assert_eq!(Balances::free_balance(42), 2); }); } @@ -110,3 +112,45 @@ fn delayed_enactment_should_work() { assert_eq!(Balances::free_balance(42), 2); }); } + +#[test] +fn lowest_unbaked_should_be_sensible() { + new_test_ext().execute_with(|| { + let r1 = Democracy::inject_referendum( + 3, + set_balance_proposal_hash_and_note(1), + VoteThreshold::SuperMajorityApprove, + 0, + ); + let r2 = Democracy::inject_referendum( + 2, + set_balance_proposal_hash_and_note(2), + VoteThreshold::SuperMajorityApprove, + 0, + ); + let r3 = Democracy::inject_referendum( + 10, + set_balance_proposal_hash_and_note(3), + VoteThreshold::SuperMajorityApprove, + 0, + ); + assert_ok!(Democracy::vote(Origin::signed(1), r1, aye(1))); + assert_ok!(Democracy::vote(Origin::signed(1), r2, aye(1))); + // r3 is canceled + assert_ok!(Democracy::cancel_referendum(Origin::root(), r3.into())); + assert_eq!(Democracy::lowest_unbaked(), 0); + + next_block(); + + // r2 is approved + assert_eq!(Balances::free_balance(42), 2); + assert_eq!(Democracy::lowest_unbaked(), 0); + + next_block(); + + // r1 is approved + assert_eq!(Balances::free_balance(42), 1); + assert_eq!(Democracy::lowest_unbaked(), 3); + assert_eq!(Democracy::lowest_unbaked(), Democracy::referendum_count()); + }); +} From d1ec40b49847fdb6dae8f00ab7ab08cef7dd10fc Mon Sep 17 00:00:00 2001 From: Dan Shields <35669742+NukeManDan@users.noreply.github.com> Date: Mon, 18 Oct 2021 04:42:56 -0600 Subject: [PATCH 093/695] Clarify wieght traits needed to impl in example (#9842) * Clarify wieght traits needed to impl in example * Update frame/example/src/lib.rs * Update frame/example/src/lib.rs Co-authored-by: Guillaume Thiolliere * fmt Co-authored-by: Squirrel Co-authored-by: Guillaume Thiolliere --- frame/example/src/lib.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/frame/example/src/lib.rs b/frame/example/src/lib.rs index f0b58e9aec15..981274b1ba73 100644 --- a/frame/example/src/lib.rs +++ b/frame/example/src/lib.rs @@ -486,11 +486,12 @@ pub mod pallet { // the chain in a moderate rate. // // The parenthesized value of the `#[pallet::weight(..)]` attribute can be any type that - // implements a set of traits, namely [`WeighData`] and [`ClassifyDispatch`]. - // The former conveys the weight (a numeric representation of pure execution time and - // difficulty) of the transaction and the latter demonstrates the [`DispatchClass`] of the - // call. A higher weight means a larger transaction (less of which can be placed in a - // single block). + // implements a set of traits, namely [`WeighData`], [`ClassifyDispatch`], and + // [`PaysFee`]. The first conveys the weight (a numeric representation of pure + // execution time and difficulty) of the transaction and the second demonstrates the + // [`DispatchClass`] of the call, the third gives whereas extrinsic must pay fees or not. + // A higher weight means a larger transaction (less of which can be placed in a single + // block). // // The weight for this extrinsic we rely on the auto-generated `WeightInfo` from the // benchmark toolchain. From 781454d981a144d31f6cd1628cccd233b34d468a Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Tue, 19 Oct 2021 13:56:09 +0200 Subject: [PATCH 094/695] Don't print "Discovered new external" line for private IPs (#10055) --- client/network/src/discovery.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/client/network/src/discovery.rs b/client/network/src/discovery.rs index 1ed08cd671d4..2a4b25a621e0 100644 --- a/client/network/src/discovery.rs +++ b/client/network/src/discovery.rs @@ -599,14 +599,16 @@ impl NetworkBehaviour for DiscoveryBehaviour { fn inject_new_external_addr(&mut self, addr: &Multiaddr) { let new_addr = addr.clone().with(Protocol::P2p(self.local_peer_id.into())); - // NOTE: we might re-discover the same address multiple times - // in which case we just want to refrain from logging. - if self.known_external_addresses.insert(new_addr.clone()) { - info!( - target: "sub-libp2p", - "🔍 Discovered new external address for our node: {}", - new_addr, - ); + if self.can_add_to_dht(addr) { + // NOTE: we might re-discover the same address multiple times + // in which case we just want to refrain from logging. + if self.known_external_addresses.insert(new_addr.clone()) { + info!( + target: "sub-libp2p", + "🔍 Discovered new external address for our node: {}", + new_addr, + ); + } } for k in self.kademlias.values_mut() { From 29938120830e13a7a9f0f4daa71ca96e03c3002a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Paulo=20Silva=20de=20Souza?= <77391175+joao-paulo-parity@users.noreply.github.com> Date: Tue, 19 Oct 2021 14:05:05 -0300 Subject: [PATCH 095/695] remove hardcoded pipeline scripts tag (#10061) the tag will be moved to Gitlab CI/CD variables --- .gitlab-ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6d4362ea9362..75fdf024d5bd 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -46,7 +46,6 @@ variables: &default-vars VAULT_AUTH_PATH: "gitlab-parity-io-jwt" VAULT_AUTH_ROLE: "cicd_gitlab_parity_${CI_PROJECT_NAME}" SIMNET_FEATURES_PATH: "simnet_tests/tests" - PIPELINE_SCRIPTS_TAG: "v0.1" default: cache: {} From 72a8f9fc6e25a82636b7d4b35ce98f79ec29ec38 Mon Sep 17 00:00:00 2001 From: Robert Klotzner Date: Tue, 19 Oct 2021 19:52:50 +0200 Subject: [PATCH 096/695] Slightly improved documentation. (#9976) Co-authored-by: Pierre Krieger Co-authored-by: Giles Cope --- client/network/src/service.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/client/network/src/service.rs b/client/network/src/service.rs index 9b6e54f37a66..90e647505fa1 100644 --- a/client/network/src/service.rs +++ b/client/network/src/service.rs @@ -1097,6 +1097,15 @@ impl NetworkService { /// Each `Multiaddr` must end with a `/p2p/` component containing the `PeerId`. It can also /// consist of only `/p2p/`. /// + /// The node will start establishing/accepting connections and substreams to/from peers in this + /// set, if it doesn't have any substream open with them yet. + /// + /// Note however, if a call to this function results in less peers on the reserved set, they + /// will not necessarily get disconnected (depending on available free slots in the peer set). + /// If you want to also disconnect those removed peers, you will have to call + /// `remove_from_peers_set` on those in addition to updating the reserved set. You can omit + /// this step if the peer set is in reserved only mode. + /// /// Returns an `Err` if one of the given addresses is invalid or contains an /// invalid peer ID (which includes the local peer ID). pub fn set_reserved_peers( From dcad42f9b51130621e24c3a93ca1075cd1bb9d15 Mon Sep 17 00:00:00 2001 From: Jay Pavlina Date: Tue, 19 Oct 2021 17:30:46 -0500 Subject: [PATCH 097/695] Derive Encode/Decode for BlockId (#10063) --- primitives/runtime/src/generic/block.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/primitives/runtime/src/generic/block.rs b/primitives/runtime/src/generic/block.rs index 21a01933bc69..68959cc514d9 100644 --- a/primitives/runtime/src/generic/block.rs +++ b/primitives/runtime/src/generic/block.rs @@ -35,7 +35,7 @@ use sp_core::RuntimeDebug; use sp_std::prelude::*; /// Something to identify a block. -#[derive(PartialEq, Eq, Clone, RuntimeDebug)] +#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)] #[cfg_attr(feature = "std", derive(Serialize))] #[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] #[cfg_attr(feature = "std", serde(deny_unknown_fields))] From 11754462c426c782bd7eb0416b4eddee5c475439 Mon Sep 17 00:00:00 2001 From: Gavin Wood Date: Thu, 21 Oct 2021 10:29:10 +0200 Subject: [PATCH 098/695] Allow pallet's info to be enumerated (#10053) * Allow pallet's info to be enumerated * Fixes * Formatting * Flat tuple for getting all pallet instances * Renaming and fixing reversedness * Formatting * Fixes * Back to nesting * Back to nestingx * Revert executive lib * Reversions * Reversions * Fixes * Fixes * Formatting * Fixes * Spelling * Comments --- frame/executive/README.md | 17 +++- .../procedural/src/construct_runtime/mod.rs | 1 + .../src/pallet/expand/pallet_struct.rs | 19 ++++ frame/support/src/dispatch.rs | 16 ++++ frame/support/src/lib.rs | 4 +- frame/support/src/migrations.rs | 4 +- frame/support/src/traits.rs | 3 +- frame/support/src/traits/metadata.rs | 88 +++++++++++++++++++ frame/support/test/tests/pallet_instance.rs | 42 +++++++++ 9 files changed, 187 insertions(+), 7 deletions(-) diff --git a/frame/executive/README.md b/frame/executive/README.md index ae3bbf1a9d99..e96d07b0843f 100644 --- a/frame/executive/README.md +++ b/frame/executive/README.md @@ -35,7 +35,13 @@ The default Substrate node template declares the [`Executive`](https://docs.rs/f ```rust # /// Executive: handles dispatch to the various modules. -pub type Executive = executive::Executive; +pub type Executive = executive::Executive< + Runtime, + Block, + Context, + Runtime, + AllPallets, +>; ``` ### Custom `OnRuntimeUpgrade` logic @@ -54,7 +60,14 @@ impl frame_support::traits::OnRuntimeUpgrade for CustomOnRuntimeUpgrade { } } -pub type Executive = executive::Executive; +pub type Executive = executive::Executive< + Runtime, + Block, + Context, + Runtime, + AllPallets, + CustomOnRuntimeUpgrade, +>; ``` License: Apache-2.0 diff --git a/frame/support/procedural/src/construct_runtime/mod.rs b/frame/support/procedural/src/construct_runtime/mod.rs index 04bb2ead645d..863df3426659 100644 --- a/frame/support/procedural/src/construct_runtime/mod.rs +++ b/frame/support/procedural/src/construct_runtime/mod.rs @@ -217,6 +217,7 @@ fn decl_all_pallets<'a>( quote!( #types + /// All pallets included in the runtime as a nested tuple of types. /// Excludes the System pallet. pub type AllPallets = ( #all_pallets ); diff --git a/frame/support/procedural/src/pallet/expand/pallet_struct.rs b/frame/support/procedural/src/pallet/expand/pallet_struct.rs index 57e814b6b843..96dfdbb4b6f2 100644 --- a/frame/support/procedural/src/pallet/expand/pallet_struct.rs +++ b/frame/support/procedural/src/pallet/expand/pallet_struct.rs @@ -233,6 +233,25 @@ pub fn expand_pallet_struct(def: &mut Def) -> proc_macro2::TokenStream { } } + impl<#type_impl_gen> #frame_support::traits::PalletsInfoAccess + for #pallet_ident<#type_use_gen> + #config_where_clause + { + fn count() -> usize { 1 } + fn accumulate( + acc: &mut #frame_support::sp_std::vec::Vec<#frame_support::traits::PalletInfoData> + ) { + use #frame_support::traits::PalletInfoAccess; + let item = #frame_support::traits::PalletInfoData { + index: Self::index(), + name: Self::name(), + module_name: Self::module_name(), + crate_version: Self::crate_version(), + }; + acc.push(item); + } + } + #storage_info ) } diff --git a/frame/support/src/dispatch.rs b/frame/support/src/dispatch.rs index 6dc7fb8a94ca..a492bc12f6a3 100644 --- a/frame/support/src/dispatch.rs +++ b/frame/support/src/dispatch.rs @@ -2165,6 +2165,22 @@ macro_rules! decl_module { } } + impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $crate::traits::PalletsInfoAccess + for $mod_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )* + { + fn count() -> usize { 1 } + fn accumulate(acc: &mut $crate::sp_std::vec::Vec<$crate::traits::PalletInfoData>) { + use $crate::traits::PalletInfoAccess; + let item = $crate::traits::PalletInfoData { + index: Self::index(), + name: Self::name(), + module_name: Self::module_name(), + crate_version: Self::crate_version(), + }; + acc.push(item); + } + } + // Implement GetCallName for the Call. impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $crate::dispatch::GetCallName for $call_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )* diff --git a/frame/support/src/lib.rs b/frame/support/src/lib.rs index f3b00c764bb3..1b93b5fb5975 100644 --- a/frame/support/src/lib.rs +++ b/frame/support/src/lib.rs @@ -1476,11 +1476,11 @@ pub mod pallet_prelude { /// * [`traits::OnGenesis`]: contains some logic to write pallet version into storage. /// * `PalletErrorTypeInfo`: provides the type information for the pallet error, if defined. /// -/// It declare `type Module` type alias for `Pallet`, used by [`construct_runtime`]. +/// It declares `type Module` type alias for `Pallet`, used by [`construct_runtime`]. /// /// It implements [`traits::PalletInfoAccess`] on `Pallet` to ease access to pallet /// informations given by [`frame_support::traits::PalletInfo`]. -/// (The implementation use the associated type `frame_system::Config::PalletInfo`). +/// (The implementation uses the associated type `frame_system::Config::PalletInfo`). /// /// It implements [`traits::StorageInfoTrait`] on `Pallet` which give information about all /// storages. diff --git a/frame/support/src/migrations.rs b/frame/support/src/migrations.rs index dc3402440fdd..c61cbac62a16 100644 --- a/frame/support/src/migrations.rs +++ b/frame/support/src/migrations.rs @@ -58,9 +58,9 @@ impl PalletVersionToStorageVersionHelper for T { /// /// This will remove all `PalletVersion's` from the state and insert the current storage version. pub fn migrate_from_pallet_version_to_storage_version< - AllPallets: PalletVersionToStorageVersionHelper, + Pallets: PalletVersionToStorageVersionHelper, >( db_weight: &RuntimeDbWeight, ) -> Weight { - AllPallets::migrate(db_weight) + Pallets::migrate(db_weight) } diff --git a/frame/support/src/traits.rs b/frame/support/src/traits.rs index 5ac0208dc203..513267c5c8ba 100644 --- a/frame/support/src/traits.rs +++ b/frame/support/src/traits.rs @@ -63,7 +63,8 @@ pub use randomness::Randomness; mod metadata; pub use metadata::{ CallMetadata, CrateVersion, GetCallMetadata, GetCallName, GetStorageVersion, PalletInfo, - PalletInfoAccess, StorageVersion, STORAGE_VERSION_STORAGE_KEY_POSTFIX, + PalletInfoAccess, PalletInfoData, PalletsInfoAccess, StorageVersion, + STORAGE_VERSION_STORAGE_KEY_POSTFIX, }; mod hooks; diff --git a/frame/support/src/traits/metadata.rs b/frame/support/src/traits/metadata.rs index e60cf8be8a41..0da76f7585ac 100644 --- a/frame/support/src/traits/metadata.rs +++ b/frame/support/src/traits/metadata.rs @@ -19,6 +19,7 @@ use codec::{Decode, Encode}; use sp_runtime::RuntimeDebug; +use sp_std::prelude::*; /// Provides information about the pallet itself and its setup in the runtime. /// @@ -35,6 +36,19 @@ pub trait PalletInfo { fn crate_version() -> Option; } +/// Information regarding an instance of a pallet. +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug)] +pub struct PalletInfoData { + /// Index of the pallet as configured in the runtime. + pub index: usize, + /// Name of the pallet as configured in the runtime. + pub name: &'static str, + /// Name of the Rust module containing the pallet. + pub module_name: &'static str, + /// Version of the crate containing the pallet. + pub crate_version: CrateVersion, +} + /// Provides information about the pallet itself and its setup in the runtime. /// /// Declare some information and access the information provided by [`PalletInfo`] for a specific @@ -50,6 +64,49 @@ pub trait PalletInfoAccess { fn crate_version() -> CrateVersion; } +/// Provide information about a bunch of pallets. +pub trait PalletsInfoAccess { + /// The number of pallets' information that this type represents. + /// + /// You probably don't want this function but `infos()` instead. + fn count() -> usize { + 0 + } + + /// Extend the given vector by all of the pallets' information that this type represents. + /// + /// You probably don't want this function but `infos()` instead. + fn accumulate(_accumulator: &mut Vec) {} + + /// All of the pallets' information that this type represents. + fn infos() -> Vec { + let mut result = Vec::with_capacity(Self::count()); + Self::accumulate(&mut result); + result + } +} + +impl PalletsInfoAccess for () {} +impl PalletsInfoAccess for (T,) { + fn count() -> usize { + T::count() + } + fn accumulate(acc: &mut Vec) { + T::accumulate(acc) + } +} + +impl PalletsInfoAccess for (T1, T2) { + fn count() -> usize { + T1::count() + T2::count() + } + fn accumulate(acc: &mut Vec) { + // The AllPallets type tuplises the pallets in reverse order, so we unreverse them here. + T2::accumulate(acc); + T1::accumulate(acc); + } +} + /// The function and pallet name of the Call. #[derive(Clone, Eq, PartialEq, Default, RuntimeDebug)] pub struct CallMetadata { @@ -206,6 +263,37 @@ pub trait GetStorageVersion { mod tests { use super::*; + struct Pallet1; + impl PalletInfoAccess for Pallet1 { + fn index() -> usize { + 1 + } + fn name() -> &'static str { + "Pallet1" + } + fn module_name() -> &'static str { + "pallet1" + } + fn crate_version() -> CrateVersion { + CrateVersion::new(1, 0, 0) + } + } + struct Pallet2; + impl PalletInfoAccess for Pallet2 { + fn index() -> usize { + 2 + } + fn name() -> &'static str { + "Pallet2" + } + fn module_name() -> &'static str { + "pallet2" + } + fn crate_version() -> CrateVersion { + CrateVersion::new(1, 0, 0) + } + } + #[test] fn check_storage_version_ordering() { let version = StorageVersion::new(1); diff --git a/frame/support/test/tests/pallet_instance.rs b/frame/support/test/tests/pallet_instance.rs index 34586e841421..3a1009402d6f 100644 --- a/frame/support/test/tests/pallet_instance.rs +++ b/frame/support/test/tests/pallet_instance.rs @@ -505,6 +505,48 @@ fn storage_expand() { }); } +#[test] +fn pallet_metadata_expands() { + use frame_support::traits::{CrateVersion, PalletInfoData, PalletsInfoAccess}; + let mut infos = AllPalletsWithSystem::infos(); + infos.sort_by_key(|x| x.index); + assert_eq!( + infos, + vec![ + PalletInfoData { + index: 0, + name: "System", + module_name: "frame_system", + crate_version: CrateVersion { major: 4, minor: 0, patch: 0 }, + }, + PalletInfoData { + index: 1, + name: "Example", + module_name: "pallet", + crate_version: CrateVersion { major: 3, minor: 0, patch: 0 }, + }, + PalletInfoData { + index: 2, + name: "Instance1Example", + module_name: "pallet", + crate_version: CrateVersion { major: 3, minor: 0, patch: 0 }, + }, + PalletInfoData { + index: 3, + name: "Example2", + module_name: "pallet2", + crate_version: CrateVersion { major: 3, minor: 0, patch: 0 }, + }, + PalletInfoData { + index: 4, + name: "Instance1Example2", + module_name: "pallet2", + crate_version: CrateVersion { major: 3, minor: 0, patch: 0 }, + }, + ] + ); +} + #[test] fn pallet_hooks_expand() { TestExternalities::default().execute_with(|| { From 05af3c2c06caa85485e0c8eaa1c829da1a379c84 Mon Sep 17 00:00:00 2001 From: Vladimir Istyufeev Date: Thu, 21 Oct 2021 15:44:46 +0300 Subject: [PATCH 099/695] Temporarily disable `node-bench-regression-guard` (#10075) --- .gitlab-ci.yml | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 75fdf024d5bd..f49211c238c0 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -364,28 +364,29 @@ cargo-check-benches: script: - *cargo-check-benches-script -node-bench-regression-guard: - # it's not belong to `build` semantically, but dag jobs can't depend on each other - # within the single stage - https://gitlab.com/gitlab-org/gitlab/-/issues/30632 - # more: https://github.com/paritytech/substrate/pull/8519#discussion_r608012402 - stage: build - <<: *docker-env - <<: *test-refs-no-trigger-prs-only - needs: - # this is a DAG - - job: cargo-check-benches - artifacts: true - # this does not like a DAG, just polls the artifact - - project: $CI_PROJECT_PATH - job: cargo-check-benches - ref: master - artifacts: true - variables: - CI_IMAGE: "paritytech/node-bench-regression-guard:latest" - before_script: [""] - script: - - 'node-bench-regression-guard --reference artifacts/benches/master-* - --compare-with artifacts/benches/$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA' +# TODO: re-enable after dedicated bench hosts provisioning +# node-bench-regression-guard: +# # it's not belong to `build` semantically, but dag jobs can't depend on each other +# # within the single stage - https://gitlab.com/gitlab-org/gitlab/-/issues/30632 +# # more: https://github.com/paritytech/substrate/pull/8519#discussion_r608012402 +# stage: build +# <<: *docker-env +# <<: *test-refs-no-trigger-prs-only +# needs: +# # this is a DAG +# - job: cargo-check-benches +# artifacts: true +# # this does not like a DAG, just polls the artifact +# - project: $CI_PROJECT_PATH +# job: cargo-check-benches +# ref: master +# artifacts: true +# variables: +# CI_IMAGE: "paritytech/node-bench-regression-guard:latest" +# before_script: [""] +# script: +# - 'node-bench-regression-guard --reference artifacts/benches/master-* +# --compare-with artifacts/benches/$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA' cargo-check-subkey: stage: test From 485e592ee2ef4db499134e9a903c02574d731593 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Paulo=20Silva=20de=20Souza?= <77391175+joao-paulo-parity@users.noreply.github.com> Date: Thu, 21 Oct 2021 10:03:50 -0300 Subject: [PATCH 100/695] remove logging from the check-dependent-* job (#10076) such command should belong to the script rather than the job --- .gitlab-ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f49211c238c0..6ad2ff1a46d8 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -570,7 +570,6 @@ cargo-check-macos: --substrate "$DEPENDENT_REPO" "$GITHUB_PR_TOKEN" - - cd "$DEPENDENT_REPO" && git rev-parse --abbrev-ref HEAD # Individual jobs are set up for each dependent project so that they can be ran in parallel. # Arguably we could generate a job for each companion in the PR's description using Gitlab's From 632b32300eb9376767c2ae7b38e79b3f7f5329b1 Mon Sep 17 00:00:00 2001 From: Koute Date: Fri, 22 Oct 2021 01:54:15 +0900 Subject: [PATCH 101/695] Speed up logging once again (#9981) * Update `tracing`-related dependencies * Enable `parking_lot` feature in `tracing-subscriber` * Add an asynchronous stderr logger * Make clippy happy * Add an integration test for the logger * Refactor `test_logger_filters`'s subprocess machinery into a separate function * Use a child process instead of hooking into stderr for the test * Add a doc comment for `MakeStderrWriter` * Move the initialization into the `MakeStderrWriter`'s constructor * Add an extra test case to trigger the logger's emergency flush mechanism * Use the buffer's mutex for asynchronous flushes * Remove vestigial `nix` dependency from one of the previous commits --- Cargo.lock | 10 +- client/tracing/Cargo.toml | 3 +- client/tracing/src/logging/directives.rs | 2 +- client/tracing/src/logging/mod.rs | 147 +++++++++++-- client/tracing/src/logging/stderr_writer.rs | 228 ++++++++++++++++++++ primitives/tracing/Cargo.toml | 4 +- 6 files changed, 373 insertions(+), 21 deletions(-) create mode 100644 client/tracing/src/logging/stderr_writer.rs diff --git a/Cargo.lock b/Cargo.lock index f15e363bfd6a..6325304bfcee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4085,9 +4085,9 @@ dependencies = [ [[package]] name = "memoffset" -version = "0.6.1" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87" +checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9" dependencies = [ "autocfg 1.0.1", ] @@ -8466,6 +8466,7 @@ dependencies = [ "chrono", "criterion", "lazy_static", + "libc", "log 0.4.14", "once_cell", "parking_lot 0.11.1", @@ -10635,14 +10636,15 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.2.19" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab69019741fca4d98be3c62d2b75254528b5432233fd8a4d2739fec20278de48" +checksum = "0e0d2eaa99c3c2e41547cfa109e910a68ea03823cccad4a0525dcbc9b01e8c71" dependencies = [ "ansi_term 0.12.1", "chrono", "lazy_static", "matchers", + "parking_lot 0.11.1", "regex", "serde", "serde_json", diff --git a/client/tracing/Cargo.toml b/client/tracing/Cargo.toml index b4049fa097ff..4939e6a73110 100644 --- a/client/tracing/Cargo.toml +++ b/client/tracing/Cargo.toml @@ -17,6 +17,7 @@ ansi_term = "0.12.1" atty = "0.2.13" chrono = "0.4.19" lazy_static = "1.4.0" +libc = "0.2.95" log = { version = "0.4.8" } once_cell = "1.8.0" parking_lot = "0.11.1" @@ -26,7 +27,7 @@ serde = "1.0.126" thiserror = "1.0.21" tracing = "0.1.29" tracing-log = "0.1.2" -tracing-subscriber = "0.2.19" +tracing-subscriber = { version = "0.2.25", features = ["parking_lot"] } sp-tracing = { version = "4.0.0-dev", path = "../../primitives/tracing" } sp-rpc = { version = "4.0.0-dev", path = "../../primitives/rpc" } sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } diff --git a/client/tracing/src/logging/directives.rs b/client/tracing/src/logging/directives.rs index 16f68654de1e..fe7d6a780dbf 100644 --- a/client/tracing/src/logging/directives.rs +++ b/client/tracing/src/logging/directives.rs @@ -109,5 +109,5 @@ pub(crate) fn set_reload_handle(handle: Handle) { type SCSubscriber< N = tracing_fmt::format::DefaultFields, E = crate::logging::EventFormat, - W = fn() -> std::io::Stderr, + W = crate::logging::DefaultLogger, > = layer::Layered, Registry>; diff --git a/client/tracing/src/logging/mod.rs b/client/tracing/src/logging/mod.rs index c6a4f070176e..7f995615a223 100644 --- a/client/tracing/src/logging/mod.rs +++ b/client/tracing/src/logging/mod.rs @@ -26,6 +26,9 @@ mod directives; mod event_format; mod fast_local_time; mod layers; +mod stderr_writer; + +pub(crate) type DefaultLogger = stderr_writer::MakeStderrWriter; pub use directives::*; pub use sc_tracing_proc_macro::*; @@ -47,6 +50,8 @@ pub use event_format::*; pub use fast_local_time::FastLocalTime; pub use layers::*; +use stderr_writer::MakeStderrWriter; + /// Logging Result typedef. pub type Result = std::result::Result; @@ -91,7 +96,7 @@ fn prepare_subscriber( profiling_targets: Option<&str>, force_colors: Option, builder_hook: impl Fn( - SubscriberBuilder std::io::Stderr>, + SubscriberBuilder, ) -> SubscriberBuilder, ) -> Result LookupSpan<'a>> where @@ -172,7 +177,7 @@ where let builder = builder.with_span_events(format::FmtSpan::NONE); - let builder = builder.with_writer(std::io::stderr as _); + let builder = builder.with_writer(MakeStderrWriter::default()); let builder = builder.event_format(event_format); @@ -282,7 +287,16 @@ impl LoggerBuilder { mod tests { use super::*; use crate as sc_tracing; - use std::{env, process::Command}; + use log::info; + use std::{ + collections::BTreeMap, + env, + process::Command, + sync::{ + atomic::{AtomicBool, AtomicUsize, Ordering}, + Arc, + }, + }; use tracing::{metadata::Kind, subscriber::Interest, Callsite, Level, Metadata}; const EXPECTED_LOG_MESSAGE: &'static str = "yeah logging works as expected"; @@ -292,9 +306,28 @@ mod tests { let _ = LoggerBuilder::new(directives).init().unwrap(); } + fn run_test_in_another_process( + test_name: &str, + test_body: impl FnOnce(), + ) -> Option { + if env::var("RUN_FORKED_TEST").is_ok() { + test_body(); + None + } else { + let output = Command::new(env::current_exe().unwrap()) + .arg(test_name) + .env("RUN_FORKED_TEST", "1") + .output() + .unwrap(); + + assert!(output.status.success()); + Some(output) + } + } + #[test] fn test_logger_filters() { - if env::var("RUN_TEST_LOGGER_FILTERS").is_ok() { + run_test_in_another_process("test_logger_filters", || { let test_directives = "afg=debug,sync=trace,client=warn,telemetry,something-with-dash=error"; init_logger(&test_directives); @@ -331,15 +364,7 @@ mod tests { assert!(test_filter("telemetry", Level::TRACE)); assert!(test_filter("something-with-dash", Level::ERROR)); }); - } else { - let status = Command::new(env::current_exe().unwrap()) - .arg("test_logger_filters") - .env("RUN_TEST_LOGGER_FILTERS", "1") - .output() - .unwrap() - .status; - assert!(status.success()); - } + }); } /// This test ensures that using dash (`-`) in the target name in logs and directives actually @@ -474,4 +499,100 @@ mod tests { assert_eq!("MAX_LOG_LEVEL=Trace", run_test(None, Some("test=info".into()))); } } + + // This creates a bunch of threads and makes sure they start executing + // a given callback almost exactly at the same time. + fn run_on_many_threads(thread_count: usize, callback: impl Fn(usize) + 'static + Send + Clone) { + let started_count = Arc::new(AtomicUsize::new(0)); + let barrier = Arc::new(AtomicBool::new(false)); + let threads: Vec<_> = (0..thread_count) + .map(|nth_thread| { + let started_count = started_count.clone(); + let barrier = barrier.clone(); + let callback = callback.clone(); + + std::thread::spawn(move || { + started_count.fetch_add(1, Ordering::SeqCst); + while !barrier.load(Ordering::SeqCst) { + std::thread::yield_now(); + } + + callback(nth_thread); + }) + }) + .collect(); + + while started_count.load(Ordering::SeqCst) != thread_count { + std::thread::yield_now(); + } + barrier.store(true, Ordering::SeqCst); + + for thread in threads { + if let Err(error) = thread.join() { + println!("error: failed to join thread: {:?}", error); + unsafe { libc::abort() } + } + } + } + + #[test] + fn parallel_logs_from_multiple_threads_are_properly_gathered() { + const THREAD_COUNT: usize = 128; + const LOGS_PER_THREAD: usize = 1024; + + let output = run_test_in_another_process( + "parallel_logs_from_multiple_threads_are_properly_gathered", + || { + let builder = LoggerBuilder::new(""); + builder.init().unwrap(); + + run_on_many_threads(THREAD_COUNT, |nth_thread| { + for _ in 0..LOGS_PER_THREAD { + info!("Thread <<{}>>", nth_thread); + } + }); + }, + ); + + if let Some(output) = output { + let stderr = String::from_utf8(output.stderr).unwrap(); + let mut count_per_thread = BTreeMap::new(); + for line in stderr.split("\n") { + if let Some(index_s) = line.find("Thread <<") { + let index_s = index_s + "Thread <<".len(); + let index_e = line.find(">>").unwrap(); + let nth_thread: usize = line[index_s..index_e].parse().unwrap(); + *count_per_thread.entry(nth_thread).or_insert(0) += 1; + } + } + + assert_eq!(count_per_thread.len(), THREAD_COUNT); + for (_, count) in count_per_thread { + assert_eq!(count, LOGS_PER_THREAD); + } + } + } + + #[test] + fn huge_single_line_log_is_properly_printed_out() { + let mut line = String::new(); + line.push_str("$$START$$"); + for n in 0..16 * 1024 * 1024 { + let ch = b'a' + (n as u8 % (b'z' - b'a')); + line.push(char::from(ch)); + } + line.push_str("$$END$$"); + + let output = + run_test_in_another_process("huge_single_line_log_is_properly_printed_out", || { + let builder = LoggerBuilder::new(""); + builder.init().unwrap(); + info!("{}", line); + }); + + if let Some(output) = output { + let stderr = String::from_utf8(output.stderr).unwrap(); + assert!(stderr.contains(&line)); + } + } } diff --git a/client/tracing/src/logging/stderr_writer.rs b/client/tracing/src/logging/stderr_writer.rs new file mode 100644 index 000000000000..9aab2491fb87 --- /dev/null +++ b/client/tracing/src/logging/stderr_writer.rs @@ -0,0 +1,228 @@ +// This file is part of Substrate. + +// Copyright (C) 2021 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 . + +//! This module contains a buffered semi-asynchronous stderr writer. +//! +//! Depending on how we were started writing to stderr can take a surprisingly long time. +//! +//! If the other side takes their sweet sweet time reading whatever we send them then writing +//! to stderr might block for a long time, since it is effectively a synchronous operation. +//! And every time we write to stderr we need to grab a global lock, which affects every thread +//! which also tries to log something at the same time. +//! +//! Of course we *will* be ultimately limited by how fast the recipient can ingest our logs, +//! but it's not like logging is the only thing we're doing. And we still can't entirely +//! avoid the problem of multiple threads contending for the same lock. (Well, technically +//! we could employ something like a lock-free circular buffer, but that might be like +//! killing a fly with a sledgehammer considering the complexity involved; this is only +//! a logger after all.) +//! +//! But we can try to make things a little better. We can offload actually writing to stderr +//! to another thread and flush the logs in bulk instead of doing it per-line, which should +//! reduce the amount of CPU time we waste on making syscalls and on spinning waiting for locks. +//! +//! How much this helps depends on a multitude of factors, including the hardware we're running on, +//! how much we're logging, from how many threads, which exact set of threads are logging, to what +//! stderr is actually connected to (is it a terminal emulator? a file? an UDP socket?), etc. +//! +//! In general this can reduce the real time execution time as much as 75% in certain cases, or it +//! can make absolutely no difference in others. + +use parking_lot::{Condvar, Mutex, Once}; +use std::{ + io::Write, + sync::atomic::{AtomicBool, Ordering}, + time::Duration, +}; +use tracing::{Level, Metadata}; + +/// How many bytes of buffered logs will trigger an async flush on another thread? +const ASYNC_FLUSH_THRESHOLD: usize = 16 * 1024; + +/// How many bytes of buffered logs will trigger a sync flush on the current thread? +const SYNC_FLUSH_THRESHOLD: usize = 768 * 1024; + +/// How many bytes can be buffered at maximum? +const EMERGENCY_FLUSH_THRESHOLD: usize = 2 * 1024 * 1024; + +/// If there isn't enough printed out this is how often the logs will be automatically flushed. +const AUTOFLUSH_EVERY: Duration = Duration::from_millis(50); + +/// The least serious level at which a synchronous flush will be triggered. +const SYNC_FLUSH_LEVEL_THRESHOLD: Level = Level::ERROR; + +/// The amount of time we'll block until the buffer is fully flushed on exit. +/// +/// This should be completely unnecessary in normal circumstances. +const ON_EXIT_FLUSH_TIMEOUT: Duration = Duration::from_secs(5); + +/// A global buffer to which we'll append all of our logs before flushing them out to stderr. +static BUFFER: Mutex> = parking_lot::const_mutex(Vec::new()); + +/// A spare buffer which we'll swap with the main buffer on each flush to minimize lock contention. +static SPARE_BUFFER: Mutex> = parking_lot::const_mutex(Vec::new()); + +/// A conditional variable used to forcefully trigger asynchronous flushes. +static ASYNC_FLUSH_CONDVAR: Condvar = Condvar::new(); + +static ENABLE_ASYNC_LOGGING: AtomicBool = AtomicBool::new(true); + +fn flush_logs(mut buffer: parking_lot::lock_api::MutexGuard>) { + let mut spare_buffer = SPARE_BUFFER.lock(); + std::mem::swap(&mut *spare_buffer, &mut *buffer); + std::mem::drop(buffer); + + let stderr = std::io::stderr(); + let mut stderr_lock = stderr.lock(); + let _ = stderr_lock.write_all(&*spare_buffer); + std::mem::drop(stderr_lock); + + spare_buffer.clear(); +} + +fn log_autoflush_thread() { + let mut buffer = BUFFER.lock(); + loop { + ASYNC_FLUSH_CONDVAR.wait_for(&mut buffer, AUTOFLUSH_EVERY); + loop { + flush_logs(buffer); + + buffer = BUFFER.lock(); + if buffer.len() >= ASYNC_FLUSH_THRESHOLD { + // While we were busy flushing we picked up enough logs to do another flush. + continue + } else { + break + } + } + } +} + +#[cold] +fn initialize() { + std::thread::Builder::new() + .name("log-autoflush".to_owned()) + .spawn(log_autoflush_thread) + .expect("thread spawning doesn't normally fail; qed"); + + // SAFETY: This is safe since we pass a valid pointer to `atexit`. + let errcode = unsafe { libc::atexit(on_exit) }; + assert_eq!(errcode, 0, "atexit failed while setting up the logger: {}", errcode); +} + +extern "C" fn on_exit() { + ENABLE_ASYNC_LOGGING.store(false, Ordering::SeqCst); + + if let Some(buffer) = BUFFER.try_lock_for(ON_EXIT_FLUSH_TIMEOUT) { + flush_logs(buffer); + } +} + +/// A drop-in replacement for [`std::io::stderr`] for use anywhere +/// a [`tracing_subscriber::fmt::MakeWriter`] is accepted. +pub struct MakeStderrWriter { + // A dummy field so that the structure is not publicly constructible. + _dummy: (), +} + +impl Default for MakeStderrWriter { + fn default() -> Self { + static ONCE: Once = Once::new(); + ONCE.call_once(initialize); + MakeStderrWriter { _dummy: () } + } +} + +impl tracing_subscriber::fmt::MakeWriter for MakeStderrWriter { + type Writer = StderrWriter; + + fn make_writer(&self) -> Self::Writer { + StderrWriter::new(false) + } + + // The `tracing-subscriber` crate calls this for every line logged. + fn make_writer_for(&self, meta: &Metadata<'_>) -> Self::Writer { + StderrWriter::new(*meta.level() <= SYNC_FLUSH_LEVEL_THRESHOLD) + } +} + +pub struct StderrWriter { + buffer: Option>>, + sync_flush_on_drop: bool, + original_len: usize, +} + +impl StderrWriter { + fn new(mut sync_flush_on_drop: bool) -> Self { + if !ENABLE_ASYNC_LOGGING.load(Ordering::Relaxed) { + sync_flush_on_drop = true; + } + + // This lock isn't as expensive as it might look, since this is only called once the full + // line to be logged is already serialized into a thread-local buffer inside of the + // `tracing-subscriber` crate, and basically the only thing we'll do when holding this lock + // is to copy that over to our global shared buffer in one go in `Write::write_all` and be + // immediately dropped. + let buffer = BUFFER.lock(); + StderrWriter { original_len: buffer.len(), buffer: Some(buffer), sync_flush_on_drop } + } +} + +#[cold] +fn emergency_flush(buffer: &mut Vec, input: &[u8]) { + let stderr = std::io::stderr(); + let mut stderr_lock = stderr.lock(); + let _ = stderr_lock.write_all(buffer); + buffer.clear(); + + let _ = stderr_lock.write_all(input); +} + +impl Write for StderrWriter { + fn write(&mut self, input: &[u8]) -> Result { + let buffer = self.buffer.as_mut().expect("buffer is only None after `drop`; qed"); + if buffer.len() + input.len() >= EMERGENCY_FLUSH_THRESHOLD { + // Make sure we don't blow our memory budget. Normally this should never happen, + // but there are cases where we directly print out untrusted user input which + // can potentially be megabytes in size. + emergency_flush(buffer, input); + } else { + buffer.extend_from_slice(input); + } + Ok(input.len()) + } + + fn write_all(&mut self, input: &[u8]) -> Result<(), std::io::Error> { + self.write(input).map(|_| ()) + } + + fn flush(&mut self) -> Result<(), std::io::Error> { + Ok(()) + } +} + +impl Drop for StderrWriter { + fn drop(&mut self) { + let buf = self.buffer.take().expect("buffer is only None after `drop`; qed"); + if self.sync_flush_on_drop || buf.len() >= SYNC_FLUSH_THRESHOLD { + flush_logs(buf); + } else if self.original_len < ASYNC_FLUSH_THRESHOLD && buf.len() >= ASYNC_FLUSH_THRESHOLD { + ASYNC_FLUSH_CONDVAR.notify_one(); + } + } +} diff --git a/primitives/tracing/Cargo.toml b/primitives/tracing/Cargo.toml index 85eb22d6df07..46930a674f2c 100644 --- a/primitives/tracing/Cargo.toml +++ b/primitives/tracing/Cargo.toml @@ -23,8 +23,8 @@ codec = { version = "2.0.0", package = "parity-scale-codec", default-features = "derive", ] } tracing = { version = "0.1.29", default-features = false } -tracing-core = { version = "0.1.17", default-features = false } -tracing-subscriber = { version = "0.2.19", optional = true, features = [ +tracing-core = { version = "0.1.21", default-features = false } +tracing-subscriber = { version = "0.2.25", optional = true, features = [ "tracing-log", ] } From 6725823035c7926000e0a44055126977d868560b Mon Sep 17 00:00:00 2001 From: Grachev Mikhail Date: Fri, 22 Oct 2021 22:27:09 +0300 Subject: [PATCH 102/695] Remove broken links in Nicks Pallet (#10086) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix broken links in Nicks Pallet * Update frame/nicks/src/lib.rs * Update frame/nicks/src/lib.rs Co-authored-by: Bastian Köcher --- frame/nicks/src/lib.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/frame/nicks/src/lib.rs b/frame/nicks/src/lib.rs index 16c7e2042dda..f502a683f633 100644 --- a/frame/nicks/src/lib.rs +++ b/frame/nicks/src/lib.rs @@ -35,9 +35,6 @@ //! taken. //! * `clear_name` - Remove an account's associated name; the deposit is returned. //! * `kill_name` - Forcibly remove the associated name; the deposit is lost. -//! -//! [`Call`]: ./enum.Call.html -//! [`Config`]: ./trait.Config.html #![cfg_attr(not(feature = "std"), no_std)] From 969a70d1864fc5d5f6c378bcfd03f1b3ea434049 Mon Sep 17 00:00:00 2001 From: Vladimir Istyufeev Date: Sat, 23 Oct 2021 00:54:12 +0300 Subject: [PATCH 103/695] Introduce `linux-docker-benches` (#10085) * Introduce `linux-docker-benches` * Add additional info to `node-bench-regression-guard` job's run --- .gitlab-ci.yml | 50 +++++++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6ad2ff1a46d8..87efc43af289 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -363,30 +363,34 @@ cargo-check-benches: - *rust-info-script script: - *cargo-check-benches-script + tags: + - linux-docker-benches -# TODO: re-enable after dedicated bench hosts provisioning -# node-bench-regression-guard: -# # it's not belong to `build` semantically, but dag jobs can't depend on each other -# # within the single stage - https://gitlab.com/gitlab-org/gitlab/-/issues/30632 -# # more: https://github.com/paritytech/substrate/pull/8519#discussion_r608012402 -# stage: build -# <<: *docker-env -# <<: *test-refs-no-trigger-prs-only -# needs: -# # this is a DAG -# - job: cargo-check-benches -# artifacts: true -# # this does not like a DAG, just polls the artifact -# - project: $CI_PROJECT_PATH -# job: cargo-check-benches -# ref: master -# artifacts: true -# variables: -# CI_IMAGE: "paritytech/node-bench-regression-guard:latest" -# before_script: [""] -# script: -# - 'node-bench-regression-guard --reference artifacts/benches/master-* -# --compare-with artifacts/benches/$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA' +node-bench-regression-guard: + # it's not belong to `build` semantically, but dag jobs can't depend on each other + # within the single stage - https://gitlab.com/gitlab-org/gitlab/-/issues/30632 + # more: https://github.com/paritytech/substrate/pull/8519#discussion_r608012402 + stage: build + <<: *docker-env + <<: *test-refs-no-trigger-prs-only + needs: + # this is a DAG + - job: cargo-check-benches + artifacts: true + # this does not like a DAG, just polls the artifact + - project: $CI_PROJECT_PATH + job: cargo-check-benches + ref: master + artifacts: true + variables: + CI_IMAGE: "paritytech/node-bench-regression-guard:latest" + before_script: [""] + script: + - echo "------- IMPORTANT -------" + - echo "node-bench-regression-guard depends on the results of a cargo-check-benches job" + - echo "In case of this job failure, check your pipeline's cargo-check-benches" + - 'node-bench-regression-guard --reference artifacts/benches/master-* + --compare-with artifacts/benches/$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA' cargo-check-subkey: stage: test From 456509d038c9535dfe6b4fc829ed1004af25a47b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Mon, 25 Oct 2021 13:29:38 +0200 Subject: [PATCH 104/695] pallet-multisig: Improve opaque call handling (#10060) * pallet-multisig: Improve opaque call handling Before the opaque call was just a type redefinition of `Vec`. With metadata v14 that was breaking external tools, as they stopped looking at the type name. To improve the situation the `WrapperKeepOpaque` type is introduced that communicates to the outside the correct type info. * Cleanup * Fix benchmarks * FMT --- frame/multisig/src/benchmarking.rs | 25 +++--- frame/multisig/src/lib.rs | 44 +++++----- frame/multisig/src/tests.rs | 129 ++++++++++++++++++++++------- frame/support/src/traits.rs | 3 +- frame/support/src/traits/misc.rs | 103 ++++++++++++++++++++++- 5 files changed, 241 insertions(+), 63 deletions(-) diff --git a/frame/multisig/src/benchmarking.rs b/frame/multisig/src/benchmarking.rs index edfeba253e5f..1390b6eebbe3 100644 --- a/frame/multisig/src/benchmarking.rs +++ b/frame/multisig/src/benchmarking.rs @@ -29,7 +29,10 @@ use crate::Pallet as Multisig; const SEED: u32 = 0; -fn setup_multi(s: u32, z: u32) -> Result<(Vec, Vec), &'static str> { +fn setup_multi( + s: u32, + z: u32, +) -> Result<(Vec, OpaqueCall), &'static str> { let mut signatories: Vec = Vec::new(); for i in 0..s { let signatory = account("signatory", i, SEED); @@ -42,7 +45,7 @@ fn setup_multi(s: u32, z: u32) -> Result<(Vec, Vec) // Must first convert to outer call type. let call: ::Call = frame_system::Call::::remark { remark: vec![0; z as usize] }.into(); - let call_data = call.encode(); + let call_data = OpaqueCall::::from_encoded(call.encode()); return Ok((signatories, call_data)) } @@ -72,7 +75,7 @@ benchmarks! { // Transaction Length let z in 0 .. 10_000; let (mut signatories, call) = setup_multi::(s, z)?; - let call_hash = blake2_256(&call); + let call_hash = blake2_256(&call.encoded()); let multi_account_id = Multisig::::multi_account_id(&signatories, s.try_into().unwrap()); let caller = signatories.pop().ok_or("signatories should have len 2 or more")?; // Whitelist caller account from further DB operations. @@ -90,7 +93,7 @@ benchmarks! { // Transaction Length let z in 0 .. 10_000; let (mut signatories, call) = setup_multi::(s, z)?; - let call_hash = blake2_256(&call); + let call_hash = blake2_256(&call.encoded()); let multi_account_id = Multisig::::multi_account_id(&signatories, s.try_into().unwrap()); let caller = signatories.pop().ok_or("signatories should have len 2 or more")?; T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); @@ -109,7 +112,7 @@ benchmarks! { // Transaction Length let z in 0 .. 10_000; let (mut signatories, call) = setup_multi::(s, z)?; - let call_hash = blake2_256(&call); + let call_hash = blake2_256(&call.encoded()); let multi_account_id = Multisig::::multi_account_id(&signatories, s.try_into().unwrap()); let mut signatories2 = signatories.clone(); let caller = signatories.pop().ok_or("signatories should have len 2 or more")?; @@ -134,7 +137,7 @@ benchmarks! { // Transaction Length let z in 0 .. 10_000; let (mut signatories, call) = setup_multi::(s, z)?; - let call_hash = blake2_256(&call); + let call_hash = blake2_256(&call.encoded()); let multi_account_id = Multisig::::multi_account_id(&signatories, s.try_into().unwrap()); let mut signatories2 = signatories.clone(); let caller = signatories.pop().ok_or("signatories should have len 2 or more")?; @@ -160,7 +163,7 @@ benchmarks! { // Transaction Length let z in 0 .. 10_000; let (mut signatories, call) = setup_multi::(s, z)?; - let call_hash = blake2_256(&call); + let call_hash = blake2_256(&call.encoded()); let multi_account_id = Multisig::::multi_account_id(&signatories, s.try_into().unwrap()); let mut signatories2 = signatories.clone(); let caller = signatories.pop().ok_or("signatories should have len 2 or more")?; @@ -193,7 +196,7 @@ benchmarks! { let (mut signatories, call) = setup_multi::(s, z)?; let multi_account_id = Multisig::::multi_account_id(&signatories, s.try_into().unwrap()); let caller = signatories.pop().ok_or("signatories should have len 2 or more")?; - let call_hash = blake2_256(&call); + let call_hash = blake2_256(&call.encoded()); // Whitelist caller account from further DB operations. let caller_key = frame_system::Account::::hashed_key_for(&caller); frame_benchmarking::benchmarking::add_to_whitelist(caller_key.into()); @@ -212,7 +215,7 @@ benchmarks! { let mut signatories2 = signatories.clone(); let multi_account_id = Multisig::::multi_account_id(&signatories, s.try_into().unwrap()); let caller = signatories.pop().ok_or("signatories should have len 2 or more")?; - let call_hash = blake2_256(&call); + let call_hash = blake2_256(&call.encoded()); // before the call, get the timepoint let timepoint = Multisig::::timepoint(); // Create the multi @@ -245,7 +248,7 @@ benchmarks! { let mut signatories2 = signatories.clone(); let caller = signatories.pop().ok_or("signatories should have len 2 or more")?; T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); - let call_hash = blake2_256(&call); + let call_hash = blake2_256(&call.encoded()); // before the call, get the timepoint let timepoint = Multisig::::timepoint(); // Create the multi @@ -282,7 +285,7 @@ benchmarks! { let (mut signatories, call) = setup_multi::(s, z)?; let multi_account_id = Multisig::::multi_account_id(&signatories, s.try_into().unwrap()); let caller = signatories.pop().ok_or("signatories should have len 2 or more")?; - let call_hash = blake2_256(&call); + let call_hash = blake2_256(&call.encoded()); let timepoint = Multisig::::timepoint(); // Create the multi let o = RawOrigin::Signed(caller.clone()).into(); diff --git a/frame/multisig/src/lib.rs b/frame/multisig/src/lib.rs index 43040ada45a9..53567cc212af 100644 --- a/frame/multisig/src/lib.rs +++ b/frame/multisig/src/lib.rs @@ -56,7 +56,7 @@ use frame_support::{ DispatchErrorWithPostInfo, DispatchResult, DispatchResultWithPostInfo, PostDispatchInfo, }, ensure, - traits::{Currency, Get, ReservableCurrency}, + traits::{Currency, Get, ReservableCurrency, WrapperKeepOpaque}, weights::{GetDispatchInfo, Weight}, RuntimeDebug, }; @@ -74,8 +74,6 @@ pub use pallet::*; type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; -/// Just a bunch of bytes, but they should decode to a valid `Call`. -pub type OpaqueCall = Vec; /// A global extrinsic index, formed as the extrinsic index within a block, together with that /// block's height. This allows a transaction in which a multisig operation of a particular @@ -101,10 +99,12 @@ pub struct Multisig { approvals: Vec, } +type OpaqueCall = WrapperKeepOpaque<::Call>; + type CallHash = [u8; 32]; -enum CallOrHash { - Call(OpaqueCall, bool), +enum CallOrHash { + Call(OpaqueCall, bool), Hash([u8; 32]), } @@ -168,7 +168,7 @@ pub mod pallet { #[pallet::storage] pub type Calls = - StorageMap<_, Identity, [u8; 32], (OpaqueCall, T::AccountId, BalanceOf)>; + StorageMap<_, Identity, [u8; 32], (OpaqueCall, T::AccountId, BalanceOf)>; #[pallet::error] pub enum Error { @@ -339,7 +339,7 @@ pub mod pallet { /// # #[pallet::weight({ let s = other_signatories.len() as u32; - let z = call.len() as u32; + let z = call.encoded_len() as u32; T::WeightInfo::as_multi_create(s, z) .max(T::WeightInfo::as_multi_create_store(s, z)) @@ -352,7 +352,7 @@ pub mod pallet { threshold: u16, other_signatories: Vec, maybe_timepoint: Option>, - call: OpaqueCall, + call: OpaqueCall, store_call: bool, max_weight: Weight, ) -> DispatchResultWithPostInfo { @@ -406,9 +406,9 @@ pub mod pallet { let s = other_signatories.len() as u32; T::WeightInfo::approve_as_multi_create(s) - .max(T::WeightInfo::approve_as_multi_approve(s)) - .max(T::WeightInfo::approve_as_multi_complete(s)) - .saturating_add(*max_weight) + .max(T::WeightInfo::approve_as_multi_approve(s)) + .max(T::WeightInfo::approve_as_multi_complete(s)) + .saturating_add(*max_weight) })] pub fn approve_as_multi( origin: OriginFor, @@ -502,7 +502,7 @@ impl Pallet { threshold: u16, other_signatories: Vec, maybe_timepoint: Option>, - call_or_hash: CallOrHash, + call_or_hash: CallOrHash, max_weight: Weight, ) -> DispatchResultWithPostInfo { ensure!(threshold >= 2, Error::::MinimumThreshold); @@ -517,8 +517,8 @@ impl Pallet { // Threshold > 1; this means it's a multi-step operation. We extract the `call_hash`. let (call_hash, call_len, maybe_call, store) = match call_or_hash { CallOrHash::Call(call, should_store) => { - let call_hash = blake2_256(&call); - let call_len = call.len(); + let call_hash = blake2_256(call.encoded()); + let call_len = call.encoded_len(); (call_hash, call_len, Some(call), should_store) }, CallOrHash::Hash(h) => (h, 0, None, false), @@ -541,7 +541,7 @@ impl Pallet { // We only bother fetching/decoding call if we know that we're ready to execute. let maybe_approved_call = if approvals >= threshold { - Self::get_call(&call_hash, maybe_call.as_ref().map(|c| c.as_ref())) + Self::get_call(&call_hash, maybe_call.as_ref()) } else { None }; @@ -658,13 +658,14 @@ impl Pallet { fn store_call_and_reserve( who: T::AccountId, hash: &[u8; 32], - data: OpaqueCall, + data: OpaqueCall, other_deposit: BalanceOf, ) -> DispatchResult { ensure!(!Calls::::contains_key(hash), Error::::AlreadyStored); let deposit = other_deposit + T::DepositBase::get() + - T::DepositFactor::get() * BalanceOf::::from(((data.len() + 31) / 32) as u32); + T::DepositFactor::get() * + BalanceOf::::from(((data.encoded_len() + 31) / 32) as u32); T::Currency::reserve(&who, deposit)?; Calls::::insert(&hash, (data, who, deposit)); Ok(()) @@ -673,15 +674,14 @@ impl Pallet { /// Attempt to decode and return the call, provided by the user or from storage. fn get_call( hash: &[u8; 32], - maybe_known: Option<&[u8]>, + maybe_known: Option<&OpaqueCall>, ) -> Option<(::Call, usize)> { maybe_known.map_or_else( || { - Calls::::get(hash).and_then(|(data, ..)| { - Decode::decode(&mut &data[..]).ok().map(|d| (d, data.len())) - }) + Calls::::get(hash) + .and_then(|(data, ..)| Some((data.try_decode()?, data.encoded_len()))) }, - |data| Decode::decode(&mut &data[..]).ok().map(|d| (d, data.len())), + |data| Some((data.try_decode()?, data.encoded_len())), ) } diff --git a/frame/multisig/src/tests.rs b/frame/multisig/src/tests.rs index 3d311cf5d3dc..d46c22ec73d0 100644 --- a/frame/multisig/src/tests.rs +++ b/frame/multisig/src/tests.rs @@ -31,6 +31,7 @@ use sp_runtime::{ type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; type Block = frame_system::mocking::MockBlock; +type OpaqueCall = super::OpaqueCall; frame_support::construct_runtime!( pub enum Test where @@ -152,7 +153,7 @@ fn multisig_deposit_is_taken_and_returned() { 2, vec![2, 3], None, - data.clone(), + OpaqueCall::from_encoded(data.clone()), false, 0 )); @@ -164,7 +165,7 @@ fn multisig_deposit_is_taken_and_returned() { 2, vec![1, 3], Some(now()), - data, + OpaqueCall::from_encoded(data), false, call_weight )); @@ -185,7 +186,15 @@ fn multisig_deposit_is_taken_and_returned_with_call_storage() { let call_weight = call.get_dispatch_info().weight; let data = call.encode(); let hash = blake2_256(&data); - assert_ok!(Multisig::as_multi(Origin::signed(1), 2, vec![2, 3], None, data, true, 0)); + assert_ok!(Multisig::as_multi( + Origin::signed(1), + 2, + vec![2, 3], + None, + OpaqueCall::from_encoded(data), + true, + 0 + )); assert_eq!(Balances::free_balance(1), 0); assert_eq!(Balances::reserved_balance(1), 5); @@ -231,7 +240,7 @@ fn multisig_deposit_is_taken_and_returned_with_alt_call_storage() { 3, vec![1, 3], Some(now()), - data, + OpaqueCall::from_encoded(data), true, 0 )); @@ -316,7 +325,15 @@ fn timepoint_checking_works() { assert_ok!(Multisig::approve_as_multi(Origin::signed(1), 2, vec![2, 3], None, hash, 0)); assert_noop!( - Multisig::as_multi(Origin::signed(2), 2, vec![1, 3], None, call.clone(), false, 0), + Multisig::as_multi( + Origin::signed(2), + 2, + vec![1, 3], + None, + OpaqueCall::from_encoded(call.clone()), + false, + 0 + ), Error::::NoTimepoint, ); let later = Timepoint { index: 1, ..now() }; @@ -326,7 +343,7 @@ fn timepoint_checking_works() { 2, vec![1, 3], Some(later), - call.clone(), + OpaqueCall::from_encoded(call), false, 0 ), @@ -347,7 +364,15 @@ fn multisig_2_of_3_works_with_call_storing() { let call_weight = call.get_dispatch_info().weight; let data = call.encode(); let hash = blake2_256(&data); - assert_ok!(Multisig::as_multi(Origin::signed(1), 2, vec![2, 3], None, data, true, 0)); + assert_ok!(Multisig::as_multi( + Origin::signed(1), + 2, + vec![2, 3], + None, + OpaqueCall::from_encoded(data), + true, + 0 + )); assert_eq!(Balances::free_balance(6), 0); assert_ok!(Multisig::approve_as_multi( @@ -382,7 +407,7 @@ fn multisig_2_of_3_works() { 2, vec![1, 3], Some(now()), - data, + OpaqueCall::from_encoded(data), false, call_weight )); @@ -425,7 +450,7 @@ fn multisig_3_of_3_works() { 3, vec![1, 2], Some(now()), - data, + OpaqueCall::from_encoded(data), false, call_weight )); @@ -473,7 +498,15 @@ fn cancel_multisig_with_call_storage_works() { new_test_ext().execute_with(|| { let call = call_transfer(6, 15).encode(); let hash = blake2_256(&call); - assert_ok!(Multisig::as_multi(Origin::signed(1), 3, vec![2, 3], None, call, true, 0)); + assert_ok!(Multisig::as_multi( + Origin::signed(1), + 3, + vec![2, 3], + None, + OpaqueCall::from_encoded(call), + true, + 0 + )); assert_eq!(Balances::free_balance(1), 4); assert_ok!(Multisig::approve_as_multi( Origin::signed(2), @@ -517,7 +550,7 @@ fn cancel_multisig_with_alt_call_storage_works() { 3, vec![1, 3], Some(now()), - call, + OpaqueCall::from_encoded(call), true, 0 )); @@ -544,7 +577,7 @@ fn multisig_2_of_3_as_multi_works() { 2, vec![2, 3], None, - data.clone(), + OpaqueCall::from_encoded(data.clone()), false, 0 )); @@ -555,7 +588,7 @@ fn multisig_2_of_3_as_multi_works() { 2, vec![1, 3], Some(now()), - data, + OpaqueCall::from_encoded(data), false, call_weight )); @@ -583,7 +616,7 @@ fn multisig_2_of_3_as_multi_with_many_calls_works() { 2, vec![2, 3], None, - data1.clone(), + OpaqueCall::from_encoded(data1.clone()), false, 0 )); @@ -592,7 +625,7 @@ fn multisig_2_of_3_as_multi_with_many_calls_works() { 2, vec![1, 3], None, - data2.clone(), + OpaqueCall::from_encoded(data2.clone()), false, 0 )); @@ -601,7 +634,7 @@ fn multisig_2_of_3_as_multi_with_many_calls_works() { 2, vec![1, 2], Some(now()), - data1, + OpaqueCall::from_encoded(data1), false, call1_weight )); @@ -610,7 +643,7 @@ fn multisig_2_of_3_as_multi_with_many_calls_works() { 2, vec![1, 2], Some(now()), - data2, + OpaqueCall::from_encoded(data2), false, call2_weight )); @@ -637,7 +670,7 @@ fn multisig_2_of_3_cannot_reissue_same_call() { 2, vec![2, 3], None, - data.clone(), + OpaqueCall::from_encoded(data.clone()), false, 0 )); @@ -646,7 +679,7 @@ fn multisig_2_of_3_cannot_reissue_same_call() { 2, vec![1, 3], Some(now()), - data.clone(), + OpaqueCall::from_encoded(data.clone()), false, call_weight )); @@ -657,7 +690,7 @@ fn multisig_2_of_3_cannot_reissue_same_call() { 2, vec![2, 3], None, - data.clone(), + OpaqueCall::from_encoded(data.clone()), false, 0 )); @@ -666,7 +699,7 @@ fn multisig_2_of_3_cannot_reissue_same_call() { 2, vec![1, 2], Some(now()), - data.clone(), + OpaqueCall::from_encoded(data), false, call_weight )); @@ -683,11 +716,27 @@ fn minimum_threshold_check_works() { new_test_ext().execute_with(|| { let call = call_transfer(6, 15).encode(); assert_noop!( - Multisig::as_multi(Origin::signed(1), 0, vec![2], None, call.clone(), false, 0), + Multisig::as_multi( + Origin::signed(1), + 0, + vec![2], + None, + OpaqueCall::from_encoded(call.clone()), + false, + 0 + ), Error::::MinimumThreshold, ); assert_noop!( - Multisig::as_multi(Origin::signed(1), 1, vec![2], None, call.clone(), false, 0), + Multisig::as_multi( + Origin::signed(1), + 1, + vec![2], + None, + OpaqueCall::from_encoded(call.clone()), + false, + 0 + ), Error::::MinimumThreshold, ); }); @@ -698,7 +747,15 @@ fn too_many_signatories_fails() { new_test_ext().execute_with(|| { let call = call_transfer(6, 15).encode(); assert_noop!( - Multisig::as_multi(Origin::signed(1), 2, vec![2, 3, 4], None, call.clone(), false, 0), + Multisig::as_multi( + Origin::signed(1), + 2, + vec![2, 3, 4], + None, + OpaqueCall::from_encoded(call), + false, + 0 + ), Error::::TooManySignatories, ); }); @@ -765,7 +822,15 @@ fn multisig_1_of_3_works() { Error::::MinimumThreshold, ); assert_noop!( - Multisig::as_multi(Origin::signed(1), 1, vec![2, 3], None, call.clone(), false, 0), + Multisig::as_multi( + Origin::signed(1), + 1, + vec![2, 3], + None, + OpaqueCall::from_encoded(call), + false, + 0 + ), Error::::MinimumThreshold, ); let boxed_call = Box::new(call_transfer(6, 15)); @@ -801,14 +866,22 @@ fn weight_check_works() { 2, vec![2, 3], None, - data.clone(), + OpaqueCall::from_encoded(data.clone()), false, 0 )); assert_eq!(Balances::free_balance(6), 0); assert_noop!( - Multisig::as_multi(Origin::signed(2), 2, vec![1, 3], Some(now()), data, false, 0), + Multisig::as_multi( + Origin::signed(2), + 2, + vec![1, 3], + Some(now()), + OpaqueCall::from_encoded(data), + false, + 0 + ), Error::::MaxWeightTooLow, ); }); @@ -860,7 +933,7 @@ fn multisig_handles_no_preimage_after_all_approve() { 3, vec![1, 2], Some(now()), - data, + OpaqueCall::from_encoded(data), false, call_weight )); diff --git a/frame/support/src/traits.rs b/frame/support/src/traits.rs index 513267c5c8ba..43eadb3a0507 100644 --- a/frame/support/src/traits.rs +++ b/frame/support/src/traits.rs @@ -52,7 +52,8 @@ mod misc; pub use misc::{ Backing, ConstU32, EnsureInherentsAreFirst, EstimateCallFee, ExecuteBlock, ExtrinsicCall, Get, GetBacking, GetDefault, HandleLifetime, IsSubType, IsType, Len, OffchainWorker, - OnKilledAccount, OnNewAccount, SameOrOther, Time, TryDrop, UnixTime, WrapperOpaque, + OnKilledAccount, OnNewAccount, SameOrOther, Time, TryDrop, UnixTime, WrapperKeepOpaque, + WrapperOpaque, }; mod stored_map; diff --git a/frame/support/src/traits/misc.rs b/frame/support/src/traits/misc.rs index 9109bfeeae72..6587945604d0 100644 --- a/frame/support/src/traits/misc.rs +++ b/frame/support/src/traits/misc.rs @@ -18,7 +18,7 @@ //! Smaller traits used in FRAME which don't need their own file. use crate::dispatch::Parameter; -use codec::{Decode, Encode, EncodeLike, Input, MaxEncodedLen}; +use codec::{CompactLen, Decode, DecodeAll, Encode, EncodeLike, Input, MaxEncodedLen}; use scale_info::{build::Fields, meta_type, Path, Type, TypeInfo, TypeParameter}; use sp_runtime::{traits::Block as BlockT, DispatchError}; use sp_std::prelude::*; @@ -390,6 +390,7 @@ impl, const T: u32> EstimateCallFee for pub struct WrapperOpaque(pub T); impl EncodeLike for WrapperOpaque {} +impl EncodeLike> for WrapperOpaque {} impl Encode for WrapperOpaque { fn size_hint(&self) -> usize { @@ -456,6 +457,93 @@ impl TypeInfo for WrapperOpaque { } } +/// A wrapper for any type `T` which implement encode/decode in a way compatible with `Vec`. +/// +/// This type is similar to [`WrapperOpaque`], but it differs in the way it stores the type `T`. +/// While [`WrapperOpaque`] stores the decoded type, the [`WrapperKeepOpaque`] stores the type only +/// in its opaque format, aka as a `Vec`. To access the real type `T` [`Self::try_decode`] needs +/// to be used. +#[derive(Debug, Eq, PartialEq, Default, Clone)] +pub struct WrapperKeepOpaque { + data: Vec, + _phantom: sp_std::marker::PhantomData, +} + +impl WrapperKeepOpaque { + /// Try to decode the wrapped type from the inner `data`. + /// + /// Returns `None` if the decoding failed. + pub fn try_decode(&self) -> Option { + T::decode_all(&mut &self.data[..]).ok() + } + + /// Returns the length of the encoded `T`. + pub fn encoded_len(&self) -> usize { + self.data.len() + } + + /// Returns the encoded data. + pub fn encoded(&self) -> &[u8] { + &self.data + } + + /// Create from the given encoded `data`. + pub fn from_encoded(data: Vec) -> Self { + Self { data, _phantom: sp_std::marker::PhantomData } + } +} + +impl EncodeLike for WrapperKeepOpaque {} +impl EncodeLike> for WrapperKeepOpaque {} + +impl Encode for WrapperKeepOpaque { + fn size_hint(&self) -> usize { + self.data.len() + codec::Compact::::compact_len(&(self.data.len() as u32)) + } + + fn encode_to(&self, dest: &mut O) { + self.data.encode_to(dest); + } + + fn encode(&self) -> Vec { + self.data.encode() + } + + fn using_encoded R>(&self, f: F) -> R { + self.data.using_encoded(f) + } +} + +impl Decode for WrapperKeepOpaque { + fn decode(input: &mut I) -> Result { + Ok(Self { data: Vec::::decode(input)?, _phantom: sp_std::marker::PhantomData }) + } + + fn skip(input: &mut I) -> Result<(), codec::Error> { + >::skip(input) + } +} + +impl MaxEncodedLen for WrapperKeepOpaque { + fn max_encoded_len() -> usize { + WrapperOpaque::::max_encoded_len() + } +} + +impl TypeInfo for WrapperKeepOpaque { + type Identity = Self; + fn type_info() -> Type { + Type::builder() + .path(Path::new("WrapperKeepOpaque", module_path!())) + .type_params(vec![TypeParameter::new("T", Some(meta_type::()))]) + .composite( + Fields::unnamed() + .field(|f| f.compact::()) + .field(|f| f.ty::().type_name("T")), + ) + } +} + #[cfg(test)] mod test { use super::*; @@ -488,4 +576,17 @@ mod test { ); assert_eq!(>::max_encoded_len(), 2usize.pow(14) + 4); } + + #[test] + fn test_keep_opaque_wrapper() { + let data = 3u32.encode().encode(); + + let keep_opaque = WrapperKeepOpaque::::decode(&mut &data[..]).unwrap(); + keep_opaque.try_decode().unwrap(); + + let data = WrapperOpaque(50u32).encode(); + let decoded = WrapperKeepOpaque::::decode(&mut &data[..]).unwrap(); + let data = decoded.encode(); + WrapperOpaque::::decode(&mut &data[..]).unwrap(); + } } From 732f0371c2d4da7b0ec326c681e0c1d360fc1bd8 Mon Sep 17 00:00:00 2001 From: Luke Schoen Date: Mon, 25 Oct 2021 23:49:43 +1100 Subject: [PATCH 105/695] Offchain-worker: Update example-offchain-worker with implementation for TestAuthId (#10096) * Update example-offchain-worker to include missing implementation for TestAuthId i tried to incorporate the off-chain worker callback demo as a custom pallet of my own Substrate-based blockchain implementation that's provided at the following links * https://www.parity.io/blog/substrate-off-chain-workers-secure-and-efficient-computing-intensive-tasks/ * https://gnunicorn.github.io/substrate-offchain-cb/ but when i build the code with `cargo build --release`, it gave me an error: ``` error[E0277]: the trait bound `AuthorityId: AppCrypto` is not satisfied --> /Users/me/my_repo/node/runtime/src/lib.rs:1172:5 | 1172 | type AuthorityId = AuthorityId; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AppCrypto` is not implemented for `AuthorityId` | note: required by a bound in `offchaincb::Config::AuthorityId` --> /Users/me/my_repo/node/pallets/offchaincb/src/lib.rs:169:21 | 169 | type AuthorityId: AppCrypto; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `offchaincb::Config::AuthorityId` ``` where in my custom pallet i have: pallets/offchaincb/src/lib.rs ``` ... use offchaincb::{ crypto::{ TestAuthId, }, }; ... parameter_types! { pub const GracePeriod: BlockNumber = 1 * MINUTES; pub const UnsignedInterval: BlockNumber = 1 * MINUTES; pub const UnsignedPriority: BlockNumber = 1 * MINUTES; } impl offchaincb::Config for Runtime { type AuthorityId = TestAuthId; type Call = Call; type Currency = Balances; type Event = Event; type GracePeriod = GracePeriod; type UnsignedInterval = UnsignedInterval; type UnsignedPriority = UnsignedPriority; } ... ``` then i found another different off-chain workers Substrate Recipe demo from Jimmy Chu https://github.com/jimmychu0807/recipes/blob/master/pallets/ocw-demo/src/lib.rs#L73 which had an extra implementation for TestAuthId here https://github.com/jimmychu0807/recipes/blob/master/pallets/ocw-demo/src/lib.rs#L73, and when i added that it overcame the error. so i think this change should be included in the Substrate repository * Fix indentation * Fix formatting * Swap order --- frame/example-offchain-worker/src/lib.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/frame/example-offchain-worker/src/lib.rs b/frame/example-offchain-worker/src/lib.rs index 644e1ca299a3..9b63ffa663ee 100644 --- a/frame/example-offchain-worker/src/lib.rs +++ b/frame/example-offchain-worker/src/lib.rs @@ -86,10 +86,19 @@ pub mod crypto { use sp_runtime::{ app_crypto::{app_crypto, sr25519}, traits::Verify, + MultiSignature, MultiSigner, }; app_crypto!(sr25519, KEY_TYPE); pub struct TestAuthId; + + impl frame_system::offchain::AppCrypto for TestAuthId { + type RuntimeAppPublic = Public; + type GenericSignature = sp_core::sr25519::Signature; + type GenericPublic = sp_core::sr25519::Public; + } + + // implemented for mock runtime in test impl frame_system::offchain::AppCrypto<::Signer, Sr25519Signature> for TestAuthId { From f37f1c84fd22e3ae91f19e09367d4f44f47a65d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Tue, 26 Oct 2021 19:10:45 +0200 Subject: [PATCH 106/695] Remove `ss58-registry.json` (#10094) This file shouldn't exist anymore, maybe it was added accidentally by some pr. People should move over to https://github.com/paritytech/ss58-registry now. --- ss58-registry.json | 671 --------------------------------------------- 1 file changed, 671 deletions(-) delete mode 100644 ss58-registry.json diff --git a/ss58-registry.json b/ss58-registry.json deleted file mode 100644 index fdae23a5a6f2..000000000000 --- a/ss58-registry.json +++ /dev/null @@ -1,671 +0,0 @@ -{ - "specification": "https://github.com/paritytech/substrate/wiki/External-Address-Format-(SS58)", - "schema": { - "prefix": "The address prefix. Must be an integer and unique.", - "network": "Unique identifier for the network that will use this prefix, string, no spaces. To integrate with CLI tools, e.g. `--network polkadot`.", - "displayName": "The name of the network that will use this prefix, in a format friendly for display.", - "symbols": "Array of symbols of any tokens the chain uses, usually 2-5 characters. Most chains will only have one. Chains that have multiple instances of the Balances pallet should order the array by instance.", - "decimals": "Array of integers representing the number of decimals that represent a single unit to the end user. Must be same length as `symbols` to represent each token's denomination.", - "standardAccount": "Signing curve for standard account. Substrate supports ed25519, sr25519, and secp256k1.", - "website": "A website or Github repo associated with the network." - }, - "registry": [ - { - "prefix": 0, - "network": "polkadot", - "displayName": "Polkadot Relay Chain", - "symbols": ["DOT"], - "decimals": [10], - "standardAccount": "*25519", - "website": "https://polkadot.network" - }, - { - "prefix": 1, - "network": null, - "displayName": "Bare 32-bit Schnorr/Ristretto (S/R 25519) public key.", - "symbols": null, - "decimals": null, - "standardAccount": null, - "website": null - }, - { - "prefix": 2, - "network": "kusama", - "displayName": "Kusama Relay Chain", - "symbols": ["KSM"], - "decimals": [12], - "standardAccount": "*25519", - "website": "https://kusama.network" - }, - { - "prefix": 3, - "network": null, - "displayName": "Bare 32-bit Ed25519 public key.", - "symbols": null, - "decimals": null, - "standardAccount": null, - "website": null - }, - { - "prefix": 4, - "network": "katalchain", - "displayName": "Katal Chain", - "symbols": null, - "decimals": null, - "standardAccount": "*25519", - "website": null - }, - { - "prefix": 5, - "network": "plasm", - "displayName": "Plasm Network", - "symbols": ["PLM"], - "decimals": [15], - "standardAccount": "*25519", - "website": "https://plasmnet.io" - }, - { - "prefix": 6, - "network": "bifrost", - "displayName": "Bifrost", - "symbols": ["BNC"], - "decimals": [12], - "standardAccount": "*25519", - "website": "https://bifrost.finance/" - }, - { - "prefix": 7, - "network": "edgeware", - "displayName": "Edgeware", - "symbols": ["EDG"], - "decimals": [18], - "standardAccount": "*25519", - "website": "https://edgewa.re" - }, - { - "prefix": 8, - "network": "karura", - "displayName": "Karura", - "symbols": ["KAR"], - "decimals": [12], - "standardAccount": "*25519", - "website": "https://karura.network/" - }, - { - "prefix": 9, - "network": "reynolds", - "displayName": "Laminar Reynolds Canary", - "symbols": ["REY"], - "decimals": [18], - "standardAccount": "*25519", - "website": "http://laminar.network/" - }, - { - "prefix": 10, - "network": "acala", - "displayName": "Acala", - "symbols": ["ACA"], - "decimals": [12], - "standardAccount": "*25519", - "website": "https://acala.network/" - }, - { - "prefix": 11, - "network": "laminar", - "displayName": "Laminar", - "symbols": ["LAMI"], - "decimals": [18], - "standardAccount": "*25519", - "website": "http://laminar.network/" - }, - { - "prefix": 12, - "network": "polymesh", - "displayName": "Polymesh", - "symbols": ["POLYX"], - "decimals": [6], - "standardAccount": "*25519", - "website": "https://polymath.network/" - }, - { - "prefix": 13, - "network": "integritee", - "displayName": "Integritee", - "symbols": ["TEER"], - "decimals": [12], - "standardAccount": "*25519", - "website": "https://integritee.network" - }, - { - "prefix": 14, - "network": "totem", - "displayName": "Totem", - "symbols": ["XTX"], - "decimals": [0], - "standardAccount": "*25519", - "website": "https://totemaccounting.com" - }, - { - "prefix": 15, - "network": "synesthesia", - "displayName": "Synesthesia", - "symbols": ["SYN"], - "decimals": [12], - "standardAccount": "*25519", - "website": "https://synesthesia.network/" - }, - { - "prefix": 16, - "network": "kulupu", - "displayName": "Kulupu", - "symbols": ["KLP"], - "decimals": [12], - "standardAccount": "*25519", - "website": "https://kulupu.network/" - }, - { - "prefix": 17, - "network": "dark", - "displayName": "Dark Mainnet", - "symbols": null, - "decimals": null, - "standardAccount": "*25519", - "website": null - }, - { - "prefix": 18, - "network": "darwinia", - "displayName": "Darwinia Network", - "symbols": ["RING", "KTON"], - "decimals": [9, 9], - "standardAccount": "*25519", - "website": "https://darwinia.network/" - }, - { - "prefix": 19, - "network": "geek", - "displayName": "GeekCash", - "symbols": ["GEEK"], - "decimals": [12], - "standardAccount": "*25519", - "website": "https://geekcash.org" - }, - { - "prefix": 20, - "network": "stafi", - "displayName": "Stafi", - "symbols": ["FIS"], - "decimals": [12], - "standardAccount": "*25519", - "website": "https://stafi.io" - }, - { - "prefix": 21, - "network": "dock-testnet", - "displayName": "Dock Testnet", - "symbols": ["DCK"], - "decimals": [6], - "standardAccount": "*25519", - "website": "https://dock.io" - }, - { - "prefix": 22, - "network": "dock-mainnet", - "displayName": "Dock Mainnet", - "symbols": ["DCK"], - "decimals": [6], - "standardAccount": "*25519", - "website": "https://dock.io" - }, - { - "prefix": 23, - "network": "shift", - "displayName": "ShiftNrg", - "symbols": null, - "decimals": null, - "standardAccount": "*25519", - "website": null - }, - { - "prefix": 24, - "network": "zero", - "displayName": "ZERO", - "symbols": ["PLAY"], - "decimals": [18], - "standardAccount": "*25519", - "website": "https://zero.io" - }, - { - "prefix": 25, - "network": "zero-alphaville", - "displayName": "ZERO Alphaville", - "symbols": ["PLAY"], - "decimals": [18], - "standardAccount": "*25519", - "website": "https://zero.io" - }, - { - "prefix": 26, - "network": "jupiter", - "displayName": "Jupiter", - "symbols": ["jDOT"], - "decimals": [10], - "standardAccount": "*25519", - "website": "https://jupiter.patract.io" - }, - { - "prefix": 28, - "network": "subsocial", - "displayName": "Subsocial", - "symbols": null, - "decimals": null, - "standardAccount": "*25519", - "website": null - }, - { - "prefix": 29, - "network": "cord", - "displayName": "Dhiway CORD Network", - "symbols": ["DCU"], - "decimals": [18], - "standardAccount": "*25519", - "website": "https://dhiway.com/" - }, - { - "prefix": 30, - "network": "phala", - "displayName": "Phala Network", - "symbols": ["PHA"], - "decimals": [12], - "standardAccount": "*25519", - "website": "https://phala.network" - }, - { - "prefix": 31, - "network": "litentry", - "displayName": "Litentry Network", - "symbols": ["LIT"], - "decimals": [12], - "standardAccount": "*25519", - "website": "https://litentry.com/" - }, - { - "prefix": 32, - "network": "robonomics", - "displayName": "Robonomics", - "symbols": ["XRT"], - "decimals": [9], - "standardAccount": "*25519", - "website": "https://robonomics.network" - }, - { - "prefix": 33, - "network": "datahighway", - "displayName": "DataHighway", - "symbols": null, - "decimals": null, - "standardAccount": "*25519", - "website": null - }, - { - "prefix": 34, - "network": "ares", - "displayName": "Ares Protocol", - "symbols": ["ARES"], - "decimals": [12], - "standardAccount": "*25519", - "website": "https://www.aresprotocol.com/" - }, - { - "prefix": 35, - "network": "vln", - "displayName": "Valiu Liquidity Network", - "symbols": ["USDv"], - "decimals": [15], - "standardAccount": "*25519", - "website": "https://valiu.com/" - }, - { - "prefix": 36, - "network": "centrifuge", - "displayName": "Centrifuge Chain", - "symbols": ["CFG"], - "decimals": [18], - "standardAccount": "*25519", - "website": "https://centrifuge.io/" - }, - { - "prefix": 37, - "network": "nodle", - "displayName": "Nodle Chain", - "symbols": ["NODL"], - "decimals": [18], - "standardAccount": "*25519", - "website": "https://nodle.io/" - }, - { - "prefix": 38, - "network": "kilt", - "displayName": "KILT Chain", - "symbols": ["KILT"], - "decimals": [18], - "standardAccount": "*25519", - "website": "https://kilt.io/" - }, - { - "prefix": 39, - "network": "mathchain", - "displayName": "MathChain mainnet", - "symbols": ["MATH"], - "decimals": [18], - "standardAccount": "*25519", - "website": "https://mathwallet.org" - }, - { - "prefix": 40, - "network": "mathchain-testnet", - "displayName": "MathChain testnet", - "symbols": ["MATH"], - "decimals": [18], - "standardAccount": "*25519", - "website": "https://mathwallet.org" - }, - { - "prefix": 41, - "network": "poli", - "displayName": "Polimec Chain", - "symbols": null, - "decimals": null, - "standardAccount": "*25519", - "website": "https://polimec.io/" - }, - { - "prefix": 42, - "network": "substrate", - "displayName": "Substrate", - "symbols": null, - "decimals": null, - "standardAccount": "*25519", - "website": "https://docs.substrate.io/" - }, - { - "prefix": 43, - "network": null, - "displayName": "Bare 32-bit ECDSA SECP-256k1 public key.", - "symbols": null, - "decimals": null, - "standardAccount": null, - "website": null - }, - { - "prefix": 44, - "network": "chainx", - "displayName": "ChainX", - "symbols": ["PCX"], - "decimals": [8], - "standardAccount": "*25519", - "website": "https://chainx.org/" - }, - { - "prefix": 45, - "network": "uniarts", - "displayName": "UniArts Network", - "symbols": ["UART", "UINK"], - "decimals": [12, 12], - "standardAccount": "*25519", - "website": "https://uniarts.me" - }, - { - "prefix": 46, - "network": "reserved46", - "displayName": "This prefix is reserved.", - "symbols": null, - "decimals": null, - "standardAccount": null, - "website": null - }, - { - "prefix": 47, - "network": "reserved47", - "displayName": "This prefix is reserved.", - "symbols": null, - "decimals": null, - "standardAccount": null, - "website": null - }, - { - "prefix": 48, - "network": "neatcoin", - "displayName": "Neatcoin Mainnet", - "symbols": ["NEAT"], - "decimals": [12], - "standardAccount": "*25519", - "website": "https://neatcoin.org" - }, - { - "prefix": 49, - "network": "picasso", - "displayName": "Picasso", - "symbols": ["PICA"], - "decimals": [12], - "standardAccount": "*25519", - "website": "https://picasso.composable.finance" - }, - { - "prefix": 50, - "network": "composable", - "displayName": "Composable", - "symbols": ["LAYR"], - "decimals": [12], - "standardAccount": "*25519", - "website": "https://composable.finance" - }, - { - "prefix": 63, - "network": "hydradx", - "displayName": "HydraDX", - "symbols": ["HDX"], - "decimals": [12], - "standardAccount": "*25519", - "website": "https://hydradx.io" - }, - { - "prefix": 65, - "network": "aventus", - "displayName": "AvN Mainnet", - "symbols": ["AVT"], - "decimals": [18], - "standardAccount": "*25519", - "website": "https://aventus.io" - }, - { - "prefix": 66, - "network": "crust", - "displayName": "Crust Network", - "symbols": ["CRU"], - "decimals": [12], - "standardAccount": "*25519", - "website": "https://crust.network" - }, - { - "prefix": 67, - "network": "equilibrium", - "displayName": "Equilibrium Network", - "symbols": ["Unknown", "USD", "EQ", "ETH", "BTC", "EOS", "DOT", "CRV"], - "decimals": [0,9,9,9,9,9,9,9], - "standardAccount": "*25519", - "website": "https://equilibrium.io" - }, - { - "prefix": 69, - "network": "sora", - "displayName": "SORA Network", - "symbols": ["XOR"], - "decimals": [18], - "standardAccount": "*25519", - "website": "https://sora.org" - }, - { - "prefix": 73, - "network": "zeitgeist", - "displayName": "Zeitgeist", - "symbols": ["ZTG"], - "decimals": [10], - "standardAccount": "*25519", - "website": "https://zeitgeist.pm" - }, - { - "prefix": 77, - "network": "manta", - "displayName": "Manta network", - "symbols": ["MA"], - "decimals": [12], - "standardAccount": "*25519", - "website": "https://manta.network" - }, - { - "prefix": 78, - "network": "calamari", - "displayName": "Calamari: Manta Canary Network", - "symbols": ["KMA"], - "decimals": [12], - "standardAccount": "*25519", - "website": "https://manta.network" - }, - { - "prefix": 88, - "network": "polkadex", - "displayName": "Polkadex Mainnet", - "symbols": ["PDEX"], - "decimals": [12], - "standardAccount": "*25519", - "website": "https://polkadex.trade" - }, - { - "prefix": 98, - "network": "polkasmith", - "displayName": "PolkaSmith Canary Network", - "symbols": ["PKS"], - "decimals": [18], - "standardAccount": "*25519", - "website": "https://polkafoundry.com" - }, - { - "prefix": 99, - "network": "polkafoundry", - "displayName": "PolkaFoundry Network", - "symbols": ["PKF"], - "decimals": [18], - "standardAccount": "*25519", - "website": "https://polkafoundry.com" - }, - { - "prefix": 101, - "network": "origintrail-parachain", - "displayName": "OriginTrail Parachain", - "symbols": ["TRAC"], - "decimals": [18], - "standardAccount": "secp256k1", - "website": "https://origintrail.io" - }, - { - "prefix": 110, - "network": "heiko", - "displayName": "Heiko", - "symbols": ["HKO"], - "decimals": [12], - "standardAccount": "*25519", - "website": "https://parallel.fi/" - }, - { - "prefix": 113, - "network": "integritee-incognito", - "displayName": "Integritee Incognito", - "symbols": null, - "decimals": null, - "standardAccount": "*25519", - "website": "https://integritee.network" - }, - { - "prefix": 128, - "network": "clover", - "displayName": "Clover Finance", - "symbols": ["CLV"], - "decimals": [18], - "standardAccount": "*25519", - "website": "https://clover.finance" - }, - { - "prefix": 136, - "network": "altair", - "displayName": "Altair", - "symbols": ["AIR"], - "decimals": [18], - "standardAccount": "*25519", - "website": "https://centrifuge.io/" - }, - { - "prefix": 172, - "network": "parallel", - "displayName": "Parallel", - "symbols": ["PARA"], - "decimals": [12], - "standardAccount": "*25519", - "website": "https://parallel.fi/" - }, - { - "prefix": 252, - "network": "social-network", - "displayName": "Social Network", - "symbols": ["NET"], - "decimals": [18], - "standardAccount": "*25519", - "website": "https://social.network" - }, - { - "prefix": 1284, - "network": "moonbeam", - "displayName": "Moonbeam", - "symbols": ["GLMR"], - "decimals": [18], - "standardAccount": "secp256k1", - "website": "https://moonbeam.network" - }, - { - "prefix": 1285, - "network": "moonriver", - "displayName": "Moonriver", - "symbols": ["MOVR"], - "decimals": [18], - "standardAccount": "secp256k1", - "website": "https://moonbeam.network" - }, - { - "prefix": 2349, - "network": "automata", - "displayName": "Automata Mainnet", - "symbols": ["ATA"], - "decimals": [18], - "standardAccount": "*25519", - "website": "https://ata.network" - }, - { - "prefix": 10041, - "network": "basilisk", - "displayName": "Basilisk", - "symbols": ["BSX"], - "decimals": [12], - "standardAccount": "*25519", - "website": "https://bsx.fi" - }, - { - "prefix": 11820, - "network": "contextfree", - "displayName": "Automata ContextFree", - "symbols": ["CTX"], - "decimals": [18], - "standardAccount": "*25519", - "website": "https://ata.network" - } - ] -} From c5450ed3d85b150ddc7fb40a68d683887dac43c4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 29 Oct 2021 10:18:33 +0000 Subject: [PATCH 107/695] Bump libc from 0.2.103 to 0.2.105 (#10115) Bumps [libc](https://github.com/rust-lang/libc) from 0.2.103 to 0.2.105. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.103...0.2.105) --- updated-dependencies: - dependency-name: libc dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- client/executor/wasmtime/Cargo.toml | 2 +- client/tracing/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6325304bfcee..ed10002bd548 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3266,9 +3266,9 @@ checksum = "3576a87f2ba00f6f106fdfcd16db1d698d648a26ad8e0573cad8537c3c362d2a" [[package]] name = "libc" -version = "0.2.103" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6" +checksum = "869d572136620d55835903746bcb5cdc54cb2851fd0aeec53220b4bb65ef3013" [[package]] name = "libgit2-sys" diff --git a/client/executor/wasmtime/Cargo.toml b/client/executor/wasmtime/Cargo.toml index 9fb76ed08fd9..7a877bd9578f 100644 --- a/client/executor/wasmtime/Cargo.toml +++ b/client/executor/wasmtime/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -libc = "0.2.90" +libc = "0.2.105" cfg-if = "1.0" log = "0.4.8" parity-wasm = "0.42.0" diff --git a/client/tracing/Cargo.toml b/client/tracing/Cargo.toml index 4939e6a73110..8093420dc5b9 100644 --- a/client/tracing/Cargo.toml +++ b/client/tracing/Cargo.toml @@ -17,7 +17,7 @@ ansi_term = "0.12.1" atty = "0.2.13" chrono = "0.4.19" lazy_static = "1.4.0" -libc = "0.2.95" +libc = "0.2.105" log = { version = "0.4.8" } once_cell = "1.8.0" parking_lot = "0.11.1" From 69fa67d0a7647f3b33f679494684859e56161197 Mon Sep 17 00:00:00 2001 From: Liu-Cheng Xu Date: Fri, 29 Oct 2021 20:42:51 +0800 Subject: [PATCH 108/695] Remove useless WeightInfo in pallet-offences (#10114) --- frame/offences/src/lib.rs | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/frame/offences/src/lib.rs b/frame/offences/src/lib.rs index 3392cd6e4a88..d50bc55f8835 100644 --- a/frame/offences/src/lib.rs +++ b/frame/offences/src/lib.rs @@ -43,28 +43,6 @@ type OpaqueTimeSlot = Vec; /// A type alias for a report identifier. type ReportIdOf = ::Hash; -pub trait WeightInfo { - fn report_offence_im_online(r: u32, o: u32, n: u32) -> Weight; - fn report_offence_grandpa(r: u32, n: u32) -> Weight; - fn report_offence_babe(r: u32, n: u32) -> Weight; - fn on_initialize(d: u32) -> Weight; -} - -impl WeightInfo for () { - fn report_offence_im_online(_r: u32, _o: u32, _n: u32) -> Weight { - 1_000_000_000 - } - fn report_offence_grandpa(_r: u32, _n: u32) -> Weight { - 1_000_000_000 - } - fn report_offence_babe(_r: u32, _n: u32) -> Weight { - 1_000_000_000 - } - fn on_initialize(_d: u32) -> Weight { - 1_000_000_000 - } -} - #[frame_support::pallet] pub mod pallet { use super::*; From 945377f35fd6ba265d6bd2b808e97749471dec0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Fri, 29 Oct 2021 18:00:49 +0200 Subject: [PATCH 109/695] pallet-scheduler: Introduce `OriginPrivilegeCmp` (#10078) * pallet-scheduler: Introduce `OriginPrivilegeCmp` When a scheduled task should be canceled, the origin that tries to cancel the task is compared to the origin the task should be executed with. Before this pr this check only allowed that both origins are equal. However, this is problematic as this means that for example a council origin it needs to be have the same amount of yes votes to cancel the scheduled task. While a council origin with more yes votes should be able to cancel this task. This happened recently on Kusama and lead to a failed cancelation of a scheduled task. With this pr the two origins are compared and the cancelling origin needs to have greater or equal privileges as the origin that scheduled the task. What a greater, equal or less privilege is, can be configured in the runtime. For simplicity, a `EqualPrivilegeOnly` implementation is provided that only checks if two origins are equal. So, this mimics the old behaviour. * FMT * fix import * Small optimizations Co-authored-by: Shawn Tabrizi --- bin/node/runtime/src/lib.rs | 5 +++-- frame/democracy/src/tests.rs | 3 ++- frame/scheduler/src/lib.rs | 26 +++++++++++++++++++++----- frame/support/src/traits.rs | 8 ++++---- frame/support/src/traits/misc.rs | 22 +++++++++++++++++++++- 5 files changed, 51 insertions(+), 13 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index c7920629bf35..0638e62faa36 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -26,8 +26,8 @@ use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::{ construct_runtime, parameter_types, traits::{ - Currency, Everything, Imbalance, InstanceFilter, KeyOwnerProofSystem, LockIdentifier, - Nothing, OnUnbalanced, U128CurrencyToVote, + Currency, EqualPrivilegeOnly, Everything, Imbalance, InstanceFilter, KeyOwnerProofSystem, + LockIdentifier, Nothing, OnUnbalanced, U128CurrencyToVote, }, weights::{ constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND}, @@ -345,6 +345,7 @@ impl pallet_scheduler::Config for Runtime { type ScheduleOrigin = EnsureRoot; type MaxScheduledPerBlock = MaxScheduledPerBlock; type WeightInfo = pallet_scheduler::weights::SubstrateWeight; + type OriginPrivilegeCmp = EqualPrivilegeOnly; } parameter_types! { diff --git a/frame/democracy/src/tests.rs b/frame/democracy/src/tests.rs index f56667e9094b..06c4ac666cfb 100644 --- a/frame/democracy/src/tests.rs +++ b/frame/democracy/src/tests.rs @@ -22,7 +22,7 @@ use crate as pallet_democracy; use codec::Encode; use frame_support::{ assert_noop, assert_ok, ord_parameter_types, parameter_types, - traits::{Contains, GenesisBuild, OnInitialize, SortedMembers}, + traits::{Contains, EqualPrivilegeOnly, GenesisBuild, OnInitialize, SortedMembers}, weights::Weight, }; use frame_system::{EnsureRoot, EnsureSignedBy}; @@ -118,6 +118,7 @@ impl pallet_scheduler::Config for Test { type ScheduleOrigin = EnsureRoot; type MaxScheduledPerBlock = (); type WeightInfo = (); + type OriginPrivilegeCmp = EqualPrivilegeOnly; } parameter_types! { pub const ExistentialDeposit: u64 = 1; diff --git a/frame/scheduler/src/lib.rs b/frame/scheduler/src/lib.rs index ca9e15812a76..d59c42cc850d 100644 --- a/frame/scheduler/src/lib.rs +++ b/frame/scheduler/src/lib.rs @@ -58,7 +58,7 @@ use frame_support::{ dispatch::{DispatchError, DispatchResult, Dispatchable, Parameter}, traits::{ schedule::{self, DispatchTime}, - EnsureOrigin, Get, IsType, OriginTrait, + EnsureOrigin, Get, IsType, OriginTrait, PrivilegeCmp, }, weights::{GetDispatchInfo, Weight}, }; @@ -69,7 +69,7 @@ use sp_runtime::{ traits::{BadOrigin, One, Saturating, Zero}, RuntimeDebug, }; -use sp_std::{borrow::Borrow, marker::PhantomData, prelude::*}; +use sp_std::{borrow::Borrow, cmp::Ordering, marker::PhantomData, prelude::*}; pub use weights::WeightInfo; /// Just a simple index for naming period tasks. @@ -160,6 +160,15 @@ pub mod pallet { /// Required origin to schedule or cancel calls. type ScheduleOrigin: EnsureOrigin<::Origin>; + /// Compare the privileges of origins. + /// + /// This will be used when canceling a task, to ensure that the origin that tries + /// to cancel has greater or equal privileges as the origin that created the scheduled task. + /// + /// For simplicity the [`EqualPrivilegeOnly`](frame_support::traits::EqualPrivilegeOnly) can + /// be used. This will only check if two given origins are equal. + type OriginPrivilegeCmp: PrivilegeCmp; + /// The maximum number of scheduled calls in the queue for a single block. /// Not strictly enforced, but used for weight estimation. #[pallet::constant] @@ -614,7 +623,10 @@ impl Pallet { Ok(None), |s| -> Result>, DispatchError> { if let (Some(ref o), Some(ref s)) = (origin, s.borrow()) { - if *o != s.origin { + if matches!( + T::OriginPrivilegeCmp::cmp_privilege(o, &s.origin), + Some(Ordering::Less) | None + ) { return Err(BadOrigin.into()) } }; @@ -709,7 +721,10 @@ impl Pallet { Agenda::::try_mutate(when, |agenda| -> DispatchResult { if let Some(s) = agenda.get_mut(i) { if let (Some(ref o), Some(ref s)) = (origin, s.borrow()) { - if *o != s.origin { + if matches!( + T::OriginPrivilegeCmp::cmp_privilege(o, &s.origin), + Some(Ordering::Less) | None + ) { return Err(BadOrigin.into()) } } @@ -832,7 +847,7 @@ mod tests { use crate as scheduler; use frame_support::{ assert_err, assert_noop, assert_ok, ord_parameter_types, parameter_types, - traits::{Contains, OnFinalize, OnInitialize}, + traits::{Contains, EqualPrivilegeOnly, OnFinalize, OnInitialize}, weights::constants::RocksDbWeight, Hashable, }; @@ -980,6 +995,7 @@ mod tests { type ScheduleOrigin = EnsureOneOf, EnsureSignedBy>; type MaxScheduledPerBlock = MaxScheduledPerBlock; type WeightInfo = (); + type OriginPrivilegeCmp = EqualPrivilegeOnly; } pub type LoggerCall = logger::Call; diff --git a/frame/support/src/traits.rs b/frame/support/src/traits.rs index 43eadb3a0507..bb990e25646d 100644 --- a/frame/support/src/traits.rs +++ b/frame/support/src/traits.rs @@ -50,10 +50,10 @@ pub use filter::{ClearFilterGuard, FilterStack, FilterStackGuard, InstanceFilter mod misc; pub use misc::{ - Backing, ConstU32, EnsureInherentsAreFirst, EstimateCallFee, ExecuteBlock, ExtrinsicCall, Get, - GetBacking, GetDefault, HandleLifetime, IsSubType, IsType, Len, OffchainWorker, - OnKilledAccount, OnNewAccount, SameOrOther, Time, TryDrop, UnixTime, WrapperKeepOpaque, - WrapperOpaque, + Backing, ConstU32, EnsureInherentsAreFirst, EqualPrivilegeOnly, EstimateCallFee, ExecuteBlock, + ExtrinsicCall, Get, GetBacking, GetDefault, HandleLifetime, IsSubType, IsType, Len, + OffchainWorker, OnKilledAccount, OnNewAccount, PrivilegeCmp, SameOrOther, Time, TryDrop, + UnixTime, WrapperKeepOpaque, WrapperOpaque, }; mod stored_map; diff --git a/frame/support/src/traits/misc.rs b/frame/support/src/traits/misc.rs index 6587945604d0..0a3fb045d6c1 100644 --- a/frame/support/src/traits/misc.rs +++ b/frame/support/src/traits/misc.rs @@ -21,7 +21,7 @@ use crate::dispatch::Parameter; use codec::{CompactLen, Decode, DecodeAll, Encode, EncodeLike, Input, MaxEncodedLen}; use scale_info::{build::Fields, meta_type, Path, Type, TypeInfo, TypeParameter}; use sp_runtime::{traits::Block as BlockT, DispatchError}; -use sp_std::prelude::*; +use sp_std::{cmp::Ordering, prelude::*}; /// Anything that can have a `::len()` method. pub trait Len { @@ -289,6 +289,26 @@ pub trait ExecuteBlock { fn execute_block(block: Block); } +/// Something that can compare privileges of two origins. +pub trait PrivilegeCmp { + /// Compare the `left` to the `right` origin. + /// + /// The returned ordering should be from the pov of the `left` origin. + /// + /// Should return `None` when it can not compare the given origins. + fn cmp_privilege(left: &Origin, right: &Origin) -> Option; +} + +/// Implementation of [`PrivilegeCmp`] that only checks for equal origins. +/// +/// This means it will either return [`Origin::Equal`] or `None`. +pub struct EqualPrivilegeOnly; +impl PrivilegeCmp for EqualPrivilegeOnly { + fn cmp_privilege(left: &Origin, right: &Origin) -> Option { + (left == right).then(|| Ordering::Equal) + } +} + /// Off-chain computation trait. /// /// Implementing this trait on a module allows you to perform long-running tasks From a7cc69f386eaf567fbf667b8c930da87cac1ce7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Sat, 30 Oct 2021 11:13:18 +0200 Subject: [PATCH 110/695] contracts: Fix account counter isn't persisted (#10112) * Add test to check account counter persistence * Fix bug that account counter wasn't properly persited * cargo run --quiet --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_contracts --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/contracts/src/weights.rs --template=./.maintain/frame-weight-template.hbs Co-authored-by: Parity Bot --- frame/contracts/src/exec.rs | 107 +++- frame/contracts/src/weights.rs | 1090 ++++++++++++++++---------------- 2 files changed, 643 insertions(+), 554 deletions(-) diff --git a/frame/contracts/src/exec.rs b/frame/contracts/src/exec.rs index 7fa0b0b27444..c28490dfaccc 100644 --- a/frame/contracts/src/exec.rs +++ b/frame/contracts/src/exec.rs @@ -538,14 +538,15 @@ where value: BalanceOf, debug_message: Option<&'a mut Vec>, ) -> Result<(Self, E), ExecError> { - let (first_frame, executable) = Self::new_frame(args, value, gas_meter, 0, &schedule)?; + let (first_frame, executable, account_counter) = + Self::new_frame(args, value, gas_meter, 0, &schedule)?; let stack = Self { origin, schedule, gas_meter, timestamp: T::Time::now(), block_number: >::block_number(), - account_counter: None, + account_counter, first_frame, frames: Default::default(), debug_message, @@ -565,8 +566,9 @@ where gas_meter: &mut GasMeter, gas_limit: Weight, schedule: &Schedule, - ) -> Result<(Frame, E), ExecError> { - let (account_id, contract_info, executable, entry_point) = match frame_args { + ) -> Result<(Frame, E, Option), ExecError> { + let (account_id, contract_info, executable, entry_point, account_counter) = match frame_args + { FrameArgs::Call { dest, cached_info } => { let contract = if let Some(contract) = cached_info { contract @@ -576,7 +578,7 @@ where let executable = E::from_storage(contract.code_hash, schedule, gas_meter)?; - (dest, contract, executable, ExportedFunction::Call) + (dest, contract, executable, ExportedFunction::Call, None) }, FrameArgs::Instantiate { sender, trie_seed, executable, salt } => { let account_id = @@ -587,7 +589,7 @@ where trie_id, executable.code_hash().clone(), )?; - (account_id, contract, executable, ExportedFunction::Constructor) + (account_id, contract, executable, ExportedFunction::Constructor, Some(trie_seed)) }, }; @@ -600,7 +602,7 @@ where allows_reentry: true, }; - Ok((frame, executable)) + Ok((frame, executable, account_counter)) } /// Create a subsequent nested frame. @@ -629,7 +631,7 @@ where let nested_meter = &mut self.frames.last_mut().unwrap_or(&mut self.first_frame).nested_meter; - let (frame, executable) = + let (frame, executable, _) = Self::new_frame(frame_args, value_transferred, nested_meter, gas_limit, self.schedule)?; self.frames.push(frame); Ok(executable) @@ -842,7 +844,7 @@ where /// Increments the cached account id and returns the value to be used for the trie_id. fn next_trie_seed(&mut self) -> u64 { let next = if let Some(current) = self.account_counter { - current + 1 + current.wrapping_add(1) } else { Self::initial_trie_seed() }; @@ -2165,4 +2167,91 @@ mod tests { ); }); } + + #[test] + fn account_counter() { + let fail_code = MockLoader::insert(Constructor, |_, _| exec_trapped()); + let success_code = MockLoader::insert(Constructor, |_, _| exec_success()); + let succ_fail_code = MockLoader::insert(Constructor, move |ctx, _| { + ctx.ext + .instantiate(0, fail_code, ctx.ext.minimum_balance() * 100, vec![], &[]) + .ok(); + exec_success() + }); + let succ_succ_code = MockLoader::insert(Constructor, move |ctx, _| { + let (account_id, _) = ctx + .ext + .instantiate(0, success_code, ctx.ext.minimum_balance() * 100, vec![], &[]) + .unwrap(); + + // a plain call should not influence the account counter + ctx.ext.call(0, account_id, 0, vec![], false).unwrap(); + + exec_success() + }); + + ExtBuilder::default().build().execute_with(|| { + let schedule = ::Schedule::get(); + let min_balance = ::Currency::minimum_balance(); + let mut gas_meter = GasMeter::::new(GAS_LIMIT); + let fail_executable = + MockExecutable::from_storage(fail_code, &schedule, &mut gas_meter).unwrap(); + let success_executable = + MockExecutable::from_storage(success_code, &schedule, &mut gas_meter).unwrap(); + let succ_fail_executable = + MockExecutable::from_storage(succ_fail_code, &schedule, &mut gas_meter).unwrap(); + let succ_succ_executable = + MockExecutable::from_storage(succ_succ_code, &schedule, &mut gas_meter).unwrap(); + set_balance(&ALICE, min_balance * 1000); + + MockStack::run_instantiate( + ALICE, + fail_executable, + &mut gas_meter, + &schedule, + min_balance * 100, + vec![], + &[], + None, + ) + .ok(); + assert_eq!(>::get(), 0); + + assert_ok!(MockStack::run_instantiate( + ALICE, + success_executable, + &mut gas_meter, + &schedule, + min_balance * 100, + vec![], + &[], + None, + )); + assert_eq!(>::get(), 1); + + assert_ok!(MockStack::run_instantiate( + ALICE, + succ_fail_executable, + &mut gas_meter, + &schedule, + min_balance * 200, + vec![], + &[], + None, + )); + assert_eq!(>::get(), 2); + + assert_ok!(MockStack::run_instantiate( + ALICE, + succ_succ_executable, + &mut gas_meter, + &schedule, + min_balance * 200, + vec![], + &[], + None, + )); + assert_eq!(>::get(), 4); + }); + } } diff --git a/frame/contracts/src/weights.rs b/frame/contracts/src/weights.rs index 1cebcb3b5d9a..4b6c40764ad0 100644 --- a/frame/contracts/src/weights.rs +++ b/frame/contracts/src/weights.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_contracts //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-09-09, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2021-10-28, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 // Executed Command: @@ -151,83 +151,83 @@ pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize() -> Weight { - (3_226_000 as Weight) + (2_987_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn on_initialize_per_trie_key(k: u32, ) -> Weight { (0 as Weight) // Standard Error: 2_000 - .saturating_add((2_178_000 as Weight).saturating_mul(k as Weight)) + .saturating_add((2_201_000 as Weight).saturating_mul(k as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) } // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize_per_queue_item(q: u32, ) -> Weight { - (78_329_000 as Weight) - // Standard Error: 1_000 - .saturating_add((353_000 as Weight).saturating_mul(q as Weight)) + (97_470_000 as Weight) + // Standard Error: 2_000 + .saturating_add((322_000 as Weight).saturating_mul(q as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Contracts PristineCode (r:1 w:0) // Storage: Contracts CodeStorage (r:0 w:1) fn instrument(c: u32, ) -> Weight { - (37_190_000 as Weight) - // Standard Error: 80_000 - .saturating_add((72_791_000 as Weight).saturating_mul(c as Weight)) + (28_804_000 as Weight) + // Standard Error: 84_000 + .saturating_add((71_838_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Contracts CodeStorage (r:1 w:0) fn code_load(c: u32, ) -> Weight { - (6_191_000 as Weight) + (5_658_000 as Weight) // Standard Error: 0 - .saturating_add((1_426_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((1_425_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) } // Storage: Contracts CodeStorage (r:1 w:1) fn code_refcount(c: u32, ) -> Weight { - (10_333_000 as Weight) + (9_001_000 as Weight) // Standard Error: 1_000 - .saturating_add((2_275_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((2_281_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - // Storage: Contracts AccountCounter (r:1 w:0) + // Storage: Contracts AccountCounter (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:1) // Storage: Contracts PristineCode (r:0 w:1) fn instantiate_with_code(c: u32, s: u32, ) -> Weight { - (438_556_000 as Weight) - // Standard Error: 147_000 - .saturating_add((179_307_000 as Weight).saturating_mul(c as Weight)) - // Standard Error: 9_000 - .saturating_add((2_159_000 as Weight).saturating_mul(s as Weight)) + (499_349_000 as Weight) + // Standard Error: 199_000 + .saturating_add((174_439_000 as Weight).saturating_mul(c as Weight)) + // Standard Error: 13_000 + .saturating_add((2_096_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) - .saturating_add(T::DbWeight::get().writes(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(5 as Weight)) } // Storage: Contracts CodeStorage (r:1 w:1) - // Storage: Contracts AccountCounter (r:1 w:0) + // Storage: Contracts AccountCounter (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn instantiate(s: u32, ) -> Weight { - (186_776_000 as Weight) - // Standard Error: 1_000 - .saturating_add((2_033_000 as Weight).saturating_mul(s as Weight)) + (181_151_000 as Weight) + // Standard Error: 2_000 + .saturating_add((2_025_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) - .saturating_add(T::DbWeight::get().writes(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(4 as Weight)) } // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call() -> Weight { - (159_247_000 as Weight) + (153_830_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -235,9 +235,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_caller(r: u32, ) -> Weight { - (422_263_000 as Weight) - // Standard Error: 159_000 - .saturating_add((125_490_000 as Weight).saturating_mul(r as Weight)) + (423_222_000 as Weight) + // Standard Error: 169_000 + .saturating_add((114_763_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -245,9 +245,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_address(r: u32, ) -> Weight { - (423_009_000 as Weight) - // Standard Error: 183_000 - .saturating_add((125_795_000 as Weight).saturating_mul(r as Weight)) + (420_731_000 as Weight) + // Standard Error: 165_000 + .saturating_add((115_213_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -255,9 +255,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas_left(r: u32, ) -> Weight { - (429_297_000 as Weight) - // Standard Error: 164_000 - .saturating_add((124_324_000 as Weight).saturating_mul(r as Weight)) + (422_407_000 as Weight) + // Standard Error: 176_000 + .saturating_add((113_935_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -266,9 +266,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:0) fn seal_balance(r: u32, ) -> Weight { - (442_330_000 as Weight) - // Standard Error: 187_000 - .saturating_add((354_665_000 as Weight).saturating_mul(r as Weight)) + (425_698_000 as Weight) + // Standard Error: 210_000 + .saturating_add((335_171_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -276,9 +276,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_value_transferred(r: u32, ) -> Weight { - (411_893_000 as Weight) - // Standard Error: 178_000 - .saturating_add((125_971_000 as Weight).saturating_mul(r as Weight)) + (410_218_000 as Weight) + // Standard Error: 187_000 + .saturating_add((115_360_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -286,9 +286,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_minimum_balance(r: u32, ) -> Weight { - (413_273_000 as Weight) - // Standard Error: 180_000 - .saturating_add((125_103_000 as Weight).saturating_mul(r as Weight)) + (402_765_000 as Weight) + // Standard Error: 169_000 + .saturating_add((116_553_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -296,9 +296,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_tombstone_deposit(r: u32, ) -> Weight { - (415_613_000 as Weight) - // Standard Error: 192_000 - .saturating_add((126_106_000 as Weight).saturating_mul(r as Weight)) + (404_817_000 as Weight) + // Standard Error: 173_000 + .saturating_add((115_894_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -306,9 +306,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_block_number(r: u32, ) -> Weight { - (414_718_000 as Weight) - // Standard Error: 170_000 - .saturating_add((124_962_000 as Weight).saturating_mul(r as Weight)) + (405_604_000 as Weight) + // Standard Error: 193_000 + .saturating_add((115_757_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -316,9 +316,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_now(r: u32, ) -> Weight { - (419_120_000 as Weight) - // Standard Error: 178_000 - .saturating_add((125_188_000 as Weight).saturating_mul(r as Weight)) + (413_577_000 as Weight) + // Standard Error: 166_000 + .saturating_add((115_115_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -327,9 +327,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0) fn seal_weight_to_fee(r: u32, ) -> Weight { - (419_125_000 as Weight) - // Standard Error: 216_000 - .saturating_add((290_592_000 as Weight).saturating_mul(r as Weight)) + (413_932_000 as Weight) + // Standard Error: 201_000 + .saturating_add((272_742_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -337,9 +337,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas(r: u32, ) -> Weight { - (149_609_000 as Weight) - // Standard Error: 117_000 - .saturating_add((56_860_000 as Weight).saturating_mul(r as Weight)) + (144_109_000 as Weight) + // Standard Error: 96_000 + .saturating_add((52_461_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -347,9 +347,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input(r: u32, ) -> Weight { - (423_570_000 as Weight) - // Standard Error: 151_000 - .saturating_add((106_985_000 as Weight).saturating_mul(r as Weight)) + (422_584_000 as Weight) + // Standard Error: 158_000 + .saturating_add((98_316_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -357,9 +357,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input_per_kb(n: u32, ) -> Weight { - (566_496_000 as Weight) - // Standard Error: 6_000 - .saturating_add((38_091_000 as Weight).saturating_mul(n as Weight)) + (549_530_000 as Weight) + // Standard Error: 8_000 + .saturating_add((38_025_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -367,9 +367,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return(r: u32, ) -> Weight { - (406_811_000 as Weight) - // Standard Error: 1_833_000 - .saturating_add((6_551_000 as Weight).saturating_mul(r as Weight)) + (403_711_000 as Weight) + // Standard Error: 114_000 + .saturating_add((2_996_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -377,9 +377,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return_per_kb(n: u32, ) -> Weight { - (412_094_000 as Weight) + (408_252_000 as Weight) // Standard Error: 1_000 - .saturating_add((631_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((630_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -389,9 +389,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts DeletionQueue (r:1 w:1) // Storage: System Account (r:2 w:2) fn seal_terminate(r: u32, ) -> Weight { - (415_716_000 as Weight) - // Standard Error: 1_608_000 - .saturating_add((72_648_000 as Weight).saturating_mul(r as Weight)) + (412_619_000 as Weight) + // Standard Error: 896_000 + .saturating_add((66_155_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -402,9 +402,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) fn seal_random(r: u32, ) -> Weight { - (421_387_000 as Weight) - // Standard Error: 275_000 - .saturating_add((393_452_000 as Weight).saturating_mul(r as Weight)) + (416_604_000 as Weight) + // Standard Error: 274_000 + .saturating_add((366_304_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -412,9 +412,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_deposit_event(r: u32, ) -> Weight { - (428_591_000 as Weight) - // Standard Error: 293_000 - .saturating_add((690_833_000 as Weight).saturating_mul(r as Weight)) + (417_326_000 as Weight) + // Standard Error: 457_000 + .saturating_add((640_211_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -423,11 +423,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: System EventTopics (r:100 w:100) fn seal_deposit_event_per_topic_and_kb(t: u32, n: u32, ) -> Weight { - (1_245_676_000 as Weight) - // Standard Error: 2_636_000 - .saturating_add((484_691_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 519_000 - .saturating_add((165_836_000 as Weight).saturating_mul(n as Weight)) + (1_121_348_000 as Weight) + // Standard Error: 2_483_000 + .saturating_add((463_498_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 489_000 + .saturating_add((167_147_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(t as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -437,17 +437,17 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_debug_message(r: u32, ) -> Weight { - (162_162_000 as Weight) - // Standard Error: 127_000 - .saturating_add((72_828_000 as Weight).saturating_mul(r as Weight)) + (159_880_000 as Weight) + // Standard Error: 138_000 + .saturating_add((67_837_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage(r: u32, ) -> Weight { - (399_301_000 as Weight) - // Standard Error: 221_000 - .saturating_add((245_222_000 as Weight).saturating_mul(r as Weight)) + (389_400_000 as Weight) + // Standard Error: 239_000 + .saturating_add((238_933_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) .saturating_add(T::DbWeight::get().writes((100 as Weight).saturating_mul(r as Weight))) @@ -457,26 +457,26 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: unknown [0x7afa01283080ef247df84e0ba38ea5a587d25ce6633a6bfbba02068c14023441] (r:0 w:1) fn seal_set_storage_per_kb(n: u32, ) -> Weight { - (623_011_000 as Weight) - // Standard Error: 246_000 - .saturating_add((72_051_000 as Weight).saturating_mul(n as Weight)) + (611_980_000 as Weight) + // Standard Error: 234_000 + .saturating_add((72_047_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage(r: u32, ) -> Weight { - (445_102_000 as Weight) - // Standard Error: 247_000 - .saturating_add((224_384_000 as Weight).saturating_mul(r as Weight)) + (436_588_000 as Weight) + // Standard Error: 222_000 + .saturating_add((209_734_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) .saturating_add(T::DbWeight::get().writes((100 as Weight).saturating_mul(r as Weight))) } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage(r: u32, ) -> Weight { - (290_227_000 as Weight) - // Standard Error: 694_000 - .saturating_add((547_193_000 as Weight).saturating_mul(r as Weight)) + (285_689_000 as Weight) + // Standard Error: 742_000 + .saturating_add((496_745_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -486,9 +486,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: unknown [0x7afa01283080ef247df84e0ba38ea5a587d25ce6633a6bfbba02068c14023441] (r:1 w:0) fn seal_get_storage_per_kb(n: u32, ) -> Weight { - (737_772_000 as Weight) - // Standard Error: 267_000 - .saturating_add((112_216_000 as Weight).saturating_mul(n as Weight)) + (693_967_000 as Weight) + // Standard Error: 226_000 + .saturating_add((111_370_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -497,9 +497,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:101 w:101) fn seal_transfer(r: u32, ) -> Weight { - (383_402_000 as Weight) - // Standard Error: 2_184_000 - .saturating_add((4_335_681_000 as Weight).saturating_mul(r as Weight)) + (332_032_000 as Weight) + // Standard Error: 2_537_000 + .saturating_add((4_071_041_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -510,8 +510,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) fn seal_call(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 11_019_000 - .saturating_add((39_806_777_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 10_806_000 + .saturating_add((39_442_275_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -522,13 +522,13 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:101 w:101) fn seal_call_per_transfer_input_output_kb(t: u32, i: u32, o: u32, ) -> Weight { - (38_662_592_000 as Weight) - // Standard Error: 52_762_000 - .saturating_add((3_888_801_000 as Weight).saturating_mul(t as Weight)) + (38_600_435_000 as Weight) + // Standard Error: 53_014_000 + .saturating_add((3_392_887_000 as Weight).saturating_mul(t as Weight)) // Standard Error: 18_000 - .saturating_add((63_571_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((63_348_000 as Weight).saturating_mul(i as Weight)) // Standard Error: 20_000 - .saturating_add((101_610_000 as Weight).saturating_mul(o as Weight)) + .saturating_add((101_366_000 as Weight).saturating_mul(o as Weight)) .saturating_add(T::DbWeight::get().reads(104 as Weight)) .saturating_add(T::DbWeight::get().reads((101 as Weight).saturating_mul(t as Weight))) .saturating_add(T::DbWeight::get().writes(101 as Weight)) @@ -540,9 +540,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts AccountCounter (r:1 w:1) // Storage: System Account (r:101 w:101) fn seal_instantiate(r: u32, ) -> Weight { - (626_132_000 as Weight) - // Standard Error: 39_245_000 - .saturating_add((46_398_859_000 as Weight).saturating_mul(r as Weight)) + (643_999_000 as Weight) + // Standard Error: 37_244_000 + .saturating_add((45_559_839_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((300 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -554,13 +554,13 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts AccountCounter (r:1 w:1) // Storage: System Account (r:101 w:101) fn seal_instantiate_per_input_output_salt_kb(i: u32, o: u32, s: u32, ) -> Weight { - (46_649_369_000 as Weight) - // Standard Error: 26_000 - .saturating_add((63_469_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 26_000 - .saturating_add((100_694_000 as Weight).saturating_mul(o as Weight)) - // Standard Error: 26_000 - .saturating_add((201_705_000 as Weight).saturating_mul(s as Weight)) + (45_415_035_000 as Weight) + // Standard Error: 30_000 + .saturating_add((63_567_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 30_000 + .saturating_add((100_900_000 as Weight).saturating_mul(o as Weight)) + // Standard Error: 30_000 + .saturating_add((201_139_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(206 as Weight)) .saturating_add(T::DbWeight::get().writes(204 as Weight)) } @@ -568,9 +568,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256(r: u32, ) -> Weight { - (417_820_000 as Weight) - // Standard Error: 160_000 - .saturating_add((133_795_000 as Weight).saturating_mul(r as Weight)) + (417_335_000 as Weight) + // Standard Error: 174_000 + .saturating_add((126_268_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -578,9 +578,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256_per_kb(n: u32, ) -> Weight { - (609_012_000 as Weight) - // Standard Error: 23_000 - .saturating_add((499_227_000 as Weight).saturating_mul(n as Weight)) + (700_565_000 as Weight) + // Standard Error: 68_000 + .saturating_add((499_898_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -588,9 +588,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256(r: u32, ) -> Weight { - (419_043_000 as Weight) - // Standard Error: 177_000 - .saturating_add((140_704_000 as Weight).saturating_mul(r as Weight)) + (416_014_000 as Weight) + // Standard Error: 168_000 + .saturating_add((134_320_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -598,9 +598,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256_per_kb(n: u32, ) -> Weight { - (564_451_000 as Weight) + (534_466_000 as Weight) // Standard Error: 19_000 - .saturating_add((346_948_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((346_588_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -608,9 +608,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256(r: u32, ) -> Weight { - (420_951_000 as Weight) - // Standard Error: 163_000 - .saturating_add((113_596_000 as Weight).saturating_mul(r as Weight)) + (414_278_000 as Weight) + // Standard Error: 164_000 + .saturating_add((106_210_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -618,9 +618,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256_per_kb(n: u32, ) -> Weight { - (563_168_000 as Weight) - // Standard Error: 17_000 - .saturating_add((164_114_000 as Weight).saturating_mul(n as Weight)) + (569_659_000 as Weight) + // Standard Error: 16_000 + .saturating_add((163_989_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -628,9 +628,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128(r: u32, ) -> Weight { - (418_794_000 as Weight) - // Standard Error: 167_000 - .saturating_add((113_205_000 as Weight).saturating_mul(r as Weight)) + (421_251_000 as Weight) + // Standard Error: 166_000 + .saturating_add((104_678_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -638,9 +638,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128_per_kb(n: u32, ) -> Weight { - (584_668_000 as Weight) - // Standard Error: 15_000 - .saturating_add((164_127_000 as Weight).saturating_mul(n as Weight)) + (568_490_000 as Weight) + // Standard Error: 21_000 + .saturating_add((163_999_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -648,264 +648,264 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_ecdsa_recover(r: u32, ) -> Weight { - (435_443_000 as Weight) - // Standard Error: 1_408_000 - .saturating_add((15_624_877_000 as Weight).saturating_mul(r as Weight)) + (361_122_000 as Weight) + // Standard Error: 1_172_000 + .saturating_add((15_591_590_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn instr_i64const(r: u32, ) -> Weight { - (45_937_000 as Weight) + (46_003_000 as Weight) // Standard Error: 10_000 - .saturating_add((1_108_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_185_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64load(r: u32, ) -> Weight { - (44_001_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_412_000 as Weight).saturating_mul(r as Weight)) + (42_908_000 as Weight) + // Standard Error: 13_000 + .saturating_add((2_570_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64store(r: u32, ) -> Weight { - (43_157_000 as Weight) - // Standard Error: 12_000 - .saturating_add((2_677_000 as Weight).saturating_mul(r as Weight)) + (42_739_000 as Weight) + // Standard Error: 13_000 + .saturating_add((2_791_000 as Weight).saturating_mul(r as Weight)) } fn instr_select(r: u32, ) -> Weight { - (48_475_000 as Weight) + (47_543_000 as Weight) // Standard Error: 8_000 - .saturating_add((2_604_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_834_000 as Weight).saturating_mul(r as Weight)) } fn instr_if(r: u32, ) -> Weight { - (50_649_000 as Weight) - // Standard Error: 12_000 - .saturating_add((2_553_000 as Weight).saturating_mul(r as Weight)) + (50_540_000 as Weight) + // Standard Error: 13_000 + .saturating_add((2_663_000 as Weight).saturating_mul(r as Weight)) } fn instr_br(r: u32, ) -> Weight { - (48_433_000 as Weight) + (47_732_000 as Weight) // Standard Error: 8_000 - .saturating_add((1_670_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_771_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_if(r: u32, ) -> Weight { - (49_244_000 as Weight) - // Standard Error: 16_000 - .saturating_add((1_946_000 as Weight).saturating_mul(r as Weight)) + (49_005_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_072_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table(r: u32, ) -> Weight { - (46_117_000 as Weight) + (45_975_000 as Weight) // Standard Error: 17_000 - .saturating_add((2_387_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_492_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table_per_entry(_e: u32, ) -> Weight { - (55_204_000 as Weight) + (55_461_000 as Weight) } fn instr_call(r: u32, ) -> Weight { - (43_651_000 as Weight) - // Standard Error: 26_000 - .saturating_add((19_163_000 as Weight).saturating_mul(r as Weight)) + (41_932_000 as Weight) + // Standard Error: 29_000 + .saturating_add((19_800_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect(r: u32, ) -> Weight { - (54_063_000 as Weight) - // Standard Error: 32_000 - .saturating_add((27_970_000 as Weight).saturating_mul(r as Weight)) + (56_550_000 as Weight) + // Standard Error: 34_000 + .saturating_add((28_414_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect_per_param(p: u32, ) -> Weight { - (88_527_000 as Weight) + (93_172_000 as Weight) // Standard Error: 6_000 - .saturating_add((958_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((1_018_000 as Weight).saturating_mul(p as Weight)) } fn instr_local_get(r: u32, ) -> Weight { - (55_066_000 as Weight) - // Standard Error: 12_000 - .saturating_add((682_000 as Weight).saturating_mul(r as Weight)) + (54_603_000 as Weight) + // Standard Error: 14_000 + .saturating_add((764_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_set(r: u32, ) -> Weight { - (55_298_000 as Weight) - // Standard Error: 13_000 - .saturating_add((778_000 as Weight).saturating_mul(r as Weight)) + (54_763_000 as Weight) + // Standard Error: 14_000 + .saturating_add((878_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_tee(r: u32, ) -> Weight { - (56_302_000 as Weight) + (56_137_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_079_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_194_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_get(r: u32, ) -> Weight { - (71_567_000 as Weight) + (69_513_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_107_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_125_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_set(r: u32, ) -> Weight { - (71_186_000 as Weight) + (69_120_000 as Weight) // Standard Error: 12_000 - .saturating_add((1_151_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_215_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_current(r: u32, ) -> Weight { - (46_240_000 as Weight) + (46_021_000 as Weight) // Standard Error: 10_000 - .saturating_add((1_044_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_103_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_grow(r: u32, ) -> Weight { - (52_369_000 as Weight) - // Standard Error: 2_508_000 - .saturating_add((615_448_000 as Weight).saturating_mul(r as Weight)) + (52_245_000 as Weight) + // Standard Error: 4_119_000 + .saturating_add((619_498_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64clz(r: u32, ) -> Weight { - (47_623_000 as Weight) + (47_314_000 as Weight) // Standard Error: 9_000 - .saturating_add((1_583_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_720_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ctz(r: u32, ) -> Weight { - (47_670_000 as Weight) + (47_855_000 as Weight) // Standard Error: 9_000 - .saturating_add((1_583_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_701_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64popcnt(r: u32, ) -> Weight { - (47_508_000 as Weight) - // Standard Error: 9_000 - .saturating_add((1_583_000 as Weight).saturating_mul(r as Weight)) + (47_704_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_708_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eqz(r: u32, ) -> Weight { - (48_109_000 as Weight) + (47_656_000 as Weight) // Standard Error: 9_000 - .saturating_add((1_580_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_705_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendsi32(r: u32, ) -> Weight { - (55_270_000 as Weight) - // Standard Error: 9_000 - .saturating_add((1_102_000 as Weight).saturating_mul(r as Weight)) + (55_202_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_229_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendui32(r: u32, ) -> Weight { - (55_093_000 as Weight) + (55_193_000 as Weight) // Standard Error: 9_000 - .saturating_add((1_108_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_223_000 as Weight).saturating_mul(r as Weight)) } fn instr_i32wrapi64(r: u32, ) -> Weight { - (48_265_000 as Weight) + (48_125_000 as Weight) // Standard Error: 10_000 - .saturating_add((1_573_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_704_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eq(r: u32, ) -> Weight { - (48_733_000 as Weight) + (49_162_000 as Weight) // Standard Error: 7_000 - .saturating_add((2_088_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_241_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ne(r: u32, ) -> Weight { - (48_831_000 as Weight) - // Standard Error: 6_000 - .saturating_add((2_085_000 as Weight).saturating_mul(r as Weight)) + (48_635_000 as Weight) + // Standard Error: 7_000 + .saturating_add((2_262_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64lts(r: u32, ) -> Weight { - (49_147_000 as Weight) - // Standard Error: 6_000 - .saturating_add((2_056_000 as Weight).saturating_mul(r as Weight)) + (48_550_000 as Weight) + // Standard Error: 9_000 + .saturating_add((2_267_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ltu(r: u32, ) -> Weight { - (49_596_000 as Weight) + (49_135_000 as Weight) // Standard Error: 7_000 - .saturating_add((2_049_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_219_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gts(r: u32, ) -> Weight { - (49_872_000 as Weight) + (49_638_000 as Weight) // Standard Error: 7_000 - .saturating_add((2_038_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_206_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gtu(r: u32, ) -> Weight { - (48_843_000 as Weight) - // Standard Error: 6_000 - .saturating_add((2_081_000 as Weight).saturating_mul(r as Weight)) + (49_889_000 as Weight) + // Standard Error: 7_000 + .saturating_add((2_201_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64les(r: u32, ) -> Weight { - (48_765_000 as Weight) - // Standard Error: 6_000 - .saturating_add((2_089_000 as Weight).saturating_mul(r as Weight)) + (49_763_000 as Weight) + // Standard Error: 9_000 + .saturating_add((2_210_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64leu(r: u32, ) -> Weight { - (48_720_000 as Weight) - // Standard Error: 6_000 - .saturating_add((2_083_000 as Weight).saturating_mul(r as Weight)) + (49_607_000 as Weight) + // Standard Error: 7_000 + .saturating_add((2_207_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ges(r: u32, ) -> Weight { - (48_736_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_097_000 as Weight).saturating_mul(r as Weight)) + (49_664_000 as Weight) + // Standard Error: 9_000 + .saturating_add((2_213_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64geu(r: u32, ) -> Weight { - (48_772_000 as Weight) + (49_718_000 as Weight) // Standard Error: 7_000 - .saturating_add((2_093_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_206_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64add(r: u32, ) -> Weight { - (48_827_000 as Weight) - // Standard Error: 6_000 - .saturating_add((2_082_000 as Weight).saturating_mul(r as Weight)) + (49_513_000 as Weight) + // Standard Error: 7_000 + .saturating_add((2_208_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64sub(r: u32, ) -> Weight { - (48_961_000 as Weight) + (49_837_000 as Weight) // Standard Error: 7_000 - .saturating_add((2_072_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_201_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64mul(r: u32, ) -> Weight { - (49_069_000 as Weight) + (49_684_000 as Weight) // Standard Error: 7_000 - .saturating_add((2_067_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_210_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divs(r: u32, ) -> Weight { - (49_035_000 as Weight) + (48_749_000 as Weight) // Standard Error: 7_000 - .saturating_add((2_677_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_872_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divu(r: u32, ) -> Weight { - (48_842_000 as Weight) - // Standard Error: 6_000 - .saturating_add((2_449_000 as Weight).saturating_mul(r as Weight)) + (49_134_000 as Weight) + // Standard Error: 7_000 + .saturating_add((2_630_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rems(r: u32, ) -> Weight { - (48_536_000 as Weight) - // Standard Error: 6_000 - .saturating_add((2_723_000 as Weight).saturating_mul(r as Weight)) + (48_981_000 as Weight) + // Standard Error: 7_000 + .saturating_add((2_861_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64remu(r: u32, ) -> Weight { - (48_851_000 as Weight) - // Standard Error: 6_000 - .saturating_add((2_432_000 as Weight).saturating_mul(r as Weight)) + (49_195_000 as Weight) + // Standard Error: 8_000 + .saturating_add((2_593_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64and(r: u32, ) -> Weight { - (48_624_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_093_000 as Weight).saturating_mul(r as Weight)) + (49_304_000 as Weight) + // Standard Error: 8_000 + .saturating_add((2_238_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64or(r: u32, ) -> Weight { - (49_348_000 as Weight) - // Standard Error: 8_000 - .saturating_add((2_073_000 as Weight).saturating_mul(r as Weight)) + (48_636_000 as Weight) + // Standard Error: 7_000 + .saturating_add((2_259_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64xor(r: u32, ) -> Weight { - (49_112_000 as Weight) - // Standard Error: 6_000 - .saturating_add((2_055_000 as Weight).saturating_mul(r as Weight)) + (48_761_000 as Weight) + // Standard Error: 8_000 + .saturating_add((2_262_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shl(r: u32, ) -> Weight { - (49_654_000 as Weight) + (48_492_000 as Weight) // Standard Error: 7_000 - .saturating_add((2_051_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_263_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shrs(r: u32, ) -> Weight { - (48_848_000 as Weight) + (48_736_000 as Weight) // Standard Error: 8_000 - .saturating_add((2_089_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_256_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shru(r: u32, ) -> Weight { - (49_455_000 as Weight) + (48_675_000 as Weight) // Standard Error: 7_000 - .saturating_add((2_054_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_256_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotl(r: u32, ) -> Weight { - (49_640_000 as Weight) + (48_703_000 as Weight) // Standard Error: 7_000 - .saturating_add((2_048_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_257_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotr(r: u32, ) -> Weight { - (49_498_000 as Weight) + (48_758_000 as Weight) // Standard Error: 7_000 - .saturating_add((2_068_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_259_000 as Weight).saturating_mul(r as Weight)) } } @@ -913,83 +913,83 @@ impl WeightInfo for SubstrateWeight { impl WeightInfo for () { // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize() -> Weight { - (3_226_000 as Weight) + (2_987_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn on_initialize_per_trie_key(k: u32, ) -> Weight { (0 as Weight) // Standard Error: 2_000 - .saturating_add((2_178_000 as Weight).saturating_mul(k as Weight)) + .saturating_add((2_201_000 as Weight).saturating_mul(k as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) } // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize_per_queue_item(q: u32, ) -> Weight { - (78_329_000 as Weight) - // Standard Error: 1_000 - .saturating_add((353_000 as Weight).saturating_mul(q as Weight)) + (97_470_000 as Weight) + // Standard Error: 2_000 + .saturating_add((322_000 as Weight).saturating_mul(q as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Contracts PristineCode (r:1 w:0) // Storage: Contracts CodeStorage (r:0 w:1) fn instrument(c: u32, ) -> Weight { - (37_190_000 as Weight) - // Standard Error: 80_000 - .saturating_add((72_791_000 as Weight).saturating_mul(c as Weight)) + (28_804_000 as Weight) + // Standard Error: 84_000 + .saturating_add((71_838_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Contracts CodeStorage (r:1 w:0) fn code_load(c: u32, ) -> Weight { - (6_191_000 as Weight) + (5_658_000 as Weight) // Standard Error: 0 - .saturating_add((1_426_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((1_425_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) } // Storage: Contracts CodeStorage (r:1 w:1) fn code_refcount(c: u32, ) -> Weight { - (10_333_000 as Weight) + (9_001_000 as Weight) // Standard Error: 1_000 - .saturating_add((2_275_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((2_281_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } - // Storage: Contracts AccountCounter (r:1 w:0) + // Storage: Contracts AccountCounter (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:1) // Storage: Contracts PristineCode (r:0 w:1) fn instantiate_with_code(c: u32, s: u32, ) -> Weight { - (438_556_000 as Weight) - // Standard Error: 147_000 - .saturating_add((179_307_000 as Weight).saturating_mul(c as Weight)) - // Standard Error: 9_000 - .saturating_add((2_159_000 as Weight).saturating_mul(s as Weight)) + (499_349_000 as Weight) + // Standard Error: 199_000 + .saturating_add((174_439_000 as Weight).saturating_mul(c as Weight)) + // Standard Error: 13_000 + .saturating_add((2_096_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) - .saturating_add(RocksDbWeight::get().writes(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } // Storage: Contracts CodeStorage (r:1 w:1) - // Storage: Contracts AccountCounter (r:1 w:0) + // Storage: Contracts AccountCounter (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn instantiate(s: u32, ) -> Weight { - (186_776_000 as Weight) - // Standard Error: 1_000 - .saturating_add((2_033_000 as Weight).saturating_mul(s as Weight)) + (181_151_000 as Weight) + // Standard Error: 2_000 + .saturating_add((2_025_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) - .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call() -> Weight { - (159_247_000 as Weight) + (153_830_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -997,9 +997,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_caller(r: u32, ) -> Weight { - (422_263_000 as Weight) - // Standard Error: 159_000 - .saturating_add((125_490_000 as Weight).saturating_mul(r as Weight)) + (423_222_000 as Weight) + // Standard Error: 169_000 + .saturating_add((114_763_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1007,9 +1007,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_address(r: u32, ) -> Weight { - (423_009_000 as Weight) - // Standard Error: 183_000 - .saturating_add((125_795_000 as Weight).saturating_mul(r as Weight)) + (420_731_000 as Weight) + // Standard Error: 165_000 + .saturating_add((115_213_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1017,9 +1017,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas_left(r: u32, ) -> Weight { - (429_297_000 as Weight) - // Standard Error: 164_000 - .saturating_add((124_324_000 as Weight).saturating_mul(r as Weight)) + (422_407_000 as Weight) + // Standard Error: 176_000 + .saturating_add((113_935_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1028,9 +1028,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:0) fn seal_balance(r: u32, ) -> Weight { - (442_330_000 as Weight) - // Standard Error: 187_000 - .saturating_add((354_665_000 as Weight).saturating_mul(r as Weight)) + (425_698_000 as Weight) + // Standard Error: 210_000 + .saturating_add((335_171_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1038,9 +1038,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_value_transferred(r: u32, ) -> Weight { - (411_893_000 as Weight) - // Standard Error: 178_000 - .saturating_add((125_971_000 as Weight).saturating_mul(r as Weight)) + (410_218_000 as Weight) + // Standard Error: 187_000 + .saturating_add((115_360_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1048,9 +1048,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_minimum_balance(r: u32, ) -> Weight { - (413_273_000 as Weight) - // Standard Error: 180_000 - .saturating_add((125_103_000 as Weight).saturating_mul(r as Weight)) + (402_765_000 as Weight) + // Standard Error: 169_000 + .saturating_add((116_553_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1058,9 +1058,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_tombstone_deposit(r: u32, ) -> Weight { - (415_613_000 as Weight) - // Standard Error: 192_000 - .saturating_add((126_106_000 as Weight).saturating_mul(r as Weight)) + (404_817_000 as Weight) + // Standard Error: 173_000 + .saturating_add((115_894_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1068,9 +1068,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_block_number(r: u32, ) -> Weight { - (414_718_000 as Weight) - // Standard Error: 170_000 - .saturating_add((124_962_000 as Weight).saturating_mul(r as Weight)) + (405_604_000 as Weight) + // Standard Error: 193_000 + .saturating_add((115_757_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1078,9 +1078,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_now(r: u32, ) -> Weight { - (419_120_000 as Weight) - // Standard Error: 178_000 - .saturating_add((125_188_000 as Weight).saturating_mul(r as Weight)) + (413_577_000 as Weight) + // Standard Error: 166_000 + .saturating_add((115_115_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1089,9 +1089,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0) fn seal_weight_to_fee(r: u32, ) -> Weight { - (419_125_000 as Weight) - // Standard Error: 216_000 - .saturating_add((290_592_000 as Weight).saturating_mul(r as Weight)) + (413_932_000 as Weight) + // Standard Error: 201_000 + .saturating_add((272_742_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1099,9 +1099,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas(r: u32, ) -> Weight { - (149_609_000 as Weight) - // Standard Error: 117_000 - .saturating_add((56_860_000 as Weight).saturating_mul(r as Weight)) + (144_109_000 as Weight) + // Standard Error: 96_000 + .saturating_add((52_461_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1109,9 +1109,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input(r: u32, ) -> Weight { - (423_570_000 as Weight) - // Standard Error: 151_000 - .saturating_add((106_985_000 as Weight).saturating_mul(r as Weight)) + (422_584_000 as Weight) + // Standard Error: 158_000 + .saturating_add((98_316_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1119,9 +1119,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input_per_kb(n: u32, ) -> Weight { - (566_496_000 as Weight) - // Standard Error: 6_000 - .saturating_add((38_091_000 as Weight).saturating_mul(n as Weight)) + (549_530_000 as Weight) + // Standard Error: 8_000 + .saturating_add((38_025_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1129,9 +1129,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return(r: u32, ) -> Weight { - (406_811_000 as Weight) - // Standard Error: 1_833_000 - .saturating_add((6_551_000 as Weight).saturating_mul(r as Weight)) + (403_711_000 as Weight) + // Standard Error: 114_000 + .saturating_add((2_996_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1139,9 +1139,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return_per_kb(n: u32, ) -> Weight { - (412_094_000 as Weight) + (408_252_000 as Weight) // Standard Error: 1_000 - .saturating_add((631_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((630_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1151,9 +1151,9 @@ impl WeightInfo for () { // Storage: Contracts DeletionQueue (r:1 w:1) // Storage: System Account (r:2 w:2) fn seal_terminate(r: u32, ) -> Weight { - (415_716_000 as Weight) - // Standard Error: 1_608_000 - .saturating_add((72_648_000 as Weight).saturating_mul(r as Weight)) + (412_619_000 as Weight) + // Standard Error: 896_000 + .saturating_add((66_155_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1164,9 +1164,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) fn seal_random(r: u32, ) -> Weight { - (421_387_000 as Weight) - // Standard Error: 275_000 - .saturating_add((393_452_000 as Weight).saturating_mul(r as Weight)) + (416_604_000 as Weight) + // Standard Error: 274_000 + .saturating_add((366_304_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1174,9 +1174,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_deposit_event(r: u32, ) -> Weight { - (428_591_000 as Weight) - // Standard Error: 293_000 - .saturating_add((690_833_000 as Weight).saturating_mul(r as Weight)) + (417_326_000 as Weight) + // Standard Error: 457_000 + .saturating_add((640_211_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1185,11 +1185,11 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: System EventTopics (r:100 w:100) fn seal_deposit_event_per_topic_and_kb(t: u32, n: u32, ) -> Weight { - (1_245_676_000 as Weight) - // Standard Error: 2_636_000 - .saturating_add((484_691_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 519_000 - .saturating_add((165_836_000 as Weight).saturating_mul(n as Weight)) + (1_121_348_000 as Weight) + // Standard Error: 2_483_000 + .saturating_add((463_498_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 489_000 + .saturating_add((167_147_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(t as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1199,17 +1199,17 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_debug_message(r: u32, ) -> Weight { - (162_162_000 as Weight) - // Standard Error: 127_000 - .saturating_add((72_828_000 as Weight).saturating_mul(r as Weight)) + (159_880_000 as Weight) + // Standard Error: 138_000 + .saturating_add((67_837_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage(r: u32, ) -> Weight { - (399_301_000 as Weight) - // Standard Error: 221_000 - .saturating_add((245_222_000 as Weight).saturating_mul(r as Weight)) + (389_400_000 as Weight) + // Standard Error: 239_000 + .saturating_add((238_933_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) .saturating_add(RocksDbWeight::get().writes((100 as Weight).saturating_mul(r as Weight))) @@ -1219,26 +1219,26 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: unknown [0x7afa01283080ef247df84e0ba38ea5a587d25ce6633a6bfbba02068c14023441] (r:0 w:1) fn seal_set_storage_per_kb(n: u32, ) -> Weight { - (623_011_000 as Weight) - // Standard Error: 246_000 - .saturating_add((72_051_000 as Weight).saturating_mul(n as Weight)) + (611_980_000 as Weight) + // Standard Error: 234_000 + .saturating_add((72_047_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage(r: u32, ) -> Weight { - (445_102_000 as Weight) - // Standard Error: 247_000 - .saturating_add((224_384_000 as Weight).saturating_mul(r as Weight)) + (436_588_000 as Weight) + // Standard Error: 222_000 + .saturating_add((209_734_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) .saturating_add(RocksDbWeight::get().writes((100 as Weight).saturating_mul(r as Weight))) } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage(r: u32, ) -> Weight { - (290_227_000 as Weight) - // Standard Error: 694_000 - .saturating_add((547_193_000 as Weight).saturating_mul(r as Weight)) + (285_689_000 as Weight) + // Standard Error: 742_000 + .saturating_add((496_745_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1248,9 +1248,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: unknown [0x7afa01283080ef247df84e0ba38ea5a587d25ce6633a6bfbba02068c14023441] (r:1 w:0) fn seal_get_storage_per_kb(n: u32, ) -> Weight { - (737_772_000 as Weight) - // Standard Error: 267_000 - .saturating_add((112_216_000 as Weight).saturating_mul(n as Weight)) + (693_967_000 as Weight) + // Standard Error: 226_000 + .saturating_add((111_370_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1259,9 +1259,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:101 w:101) fn seal_transfer(r: u32, ) -> Weight { - (383_402_000 as Weight) - // Standard Error: 2_184_000 - .saturating_add((4_335_681_000 as Weight).saturating_mul(r as Weight)) + (332_032_000 as Weight) + // Standard Error: 2_537_000 + .saturating_add((4_071_041_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) @@ -1272,8 +1272,8 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) fn seal_call(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 11_019_000 - .saturating_add((39_806_777_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 10_806_000 + .saturating_add((39_442_275_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1284,13 +1284,13 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:101 w:101) fn seal_call_per_transfer_input_output_kb(t: u32, i: u32, o: u32, ) -> Weight { - (38_662_592_000 as Weight) - // Standard Error: 52_762_000 - .saturating_add((3_888_801_000 as Weight).saturating_mul(t as Weight)) + (38_600_435_000 as Weight) + // Standard Error: 53_014_000 + .saturating_add((3_392_887_000 as Weight).saturating_mul(t as Weight)) // Standard Error: 18_000 - .saturating_add((63_571_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((63_348_000 as Weight).saturating_mul(i as Weight)) // Standard Error: 20_000 - .saturating_add((101_610_000 as Weight).saturating_mul(o as Weight)) + .saturating_add((101_366_000 as Weight).saturating_mul(o as Weight)) .saturating_add(RocksDbWeight::get().reads(104 as Weight)) .saturating_add(RocksDbWeight::get().reads((101 as Weight).saturating_mul(t as Weight))) .saturating_add(RocksDbWeight::get().writes(101 as Weight)) @@ -1302,9 +1302,9 @@ impl WeightInfo for () { // Storage: Contracts AccountCounter (r:1 w:1) // Storage: System Account (r:101 w:101) fn seal_instantiate(r: u32, ) -> Weight { - (626_132_000 as Weight) - // Standard Error: 39_245_000 - .saturating_add((46_398_859_000 as Weight).saturating_mul(r as Weight)) + (643_999_000 as Weight) + // Standard Error: 37_244_000 + .saturating_add((45_559_839_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((300 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -1316,13 +1316,13 @@ impl WeightInfo for () { // Storage: Contracts AccountCounter (r:1 w:1) // Storage: System Account (r:101 w:101) fn seal_instantiate_per_input_output_salt_kb(i: u32, o: u32, s: u32, ) -> Weight { - (46_649_369_000 as Weight) - // Standard Error: 26_000 - .saturating_add((63_469_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 26_000 - .saturating_add((100_694_000 as Weight).saturating_mul(o as Weight)) - // Standard Error: 26_000 - .saturating_add((201_705_000 as Weight).saturating_mul(s as Weight)) + (45_415_035_000 as Weight) + // Standard Error: 30_000 + .saturating_add((63_567_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 30_000 + .saturating_add((100_900_000 as Weight).saturating_mul(o as Weight)) + // Standard Error: 30_000 + .saturating_add((201_139_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(206 as Weight)) .saturating_add(RocksDbWeight::get().writes(204 as Weight)) } @@ -1330,9 +1330,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256(r: u32, ) -> Weight { - (417_820_000 as Weight) - // Standard Error: 160_000 - .saturating_add((133_795_000 as Weight).saturating_mul(r as Weight)) + (417_335_000 as Weight) + // Standard Error: 174_000 + .saturating_add((126_268_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1340,9 +1340,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256_per_kb(n: u32, ) -> Weight { - (609_012_000 as Weight) - // Standard Error: 23_000 - .saturating_add((499_227_000 as Weight).saturating_mul(n as Weight)) + (700_565_000 as Weight) + // Standard Error: 68_000 + .saturating_add((499_898_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1350,9 +1350,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256(r: u32, ) -> Weight { - (419_043_000 as Weight) - // Standard Error: 177_000 - .saturating_add((140_704_000 as Weight).saturating_mul(r as Weight)) + (416_014_000 as Weight) + // Standard Error: 168_000 + .saturating_add((134_320_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1360,9 +1360,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256_per_kb(n: u32, ) -> Weight { - (564_451_000 as Weight) + (534_466_000 as Weight) // Standard Error: 19_000 - .saturating_add((346_948_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((346_588_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1370,9 +1370,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256(r: u32, ) -> Weight { - (420_951_000 as Weight) - // Standard Error: 163_000 - .saturating_add((113_596_000 as Weight).saturating_mul(r as Weight)) + (414_278_000 as Weight) + // Standard Error: 164_000 + .saturating_add((106_210_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1380,9 +1380,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256_per_kb(n: u32, ) -> Weight { - (563_168_000 as Weight) - // Standard Error: 17_000 - .saturating_add((164_114_000 as Weight).saturating_mul(n as Weight)) + (569_659_000 as Weight) + // Standard Error: 16_000 + .saturating_add((163_989_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1390,9 +1390,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128(r: u32, ) -> Weight { - (418_794_000 as Weight) - // Standard Error: 167_000 - .saturating_add((113_205_000 as Weight).saturating_mul(r as Weight)) + (421_251_000 as Weight) + // Standard Error: 166_000 + .saturating_add((104_678_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1400,9 +1400,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128_per_kb(n: u32, ) -> Weight { - (584_668_000 as Weight) - // Standard Error: 15_000 - .saturating_add((164_127_000 as Weight).saturating_mul(n as Weight)) + (568_490_000 as Weight) + // Standard Error: 21_000 + .saturating_add((163_999_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1410,263 +1410,263 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_ecdsa_recover(r: u32, ) -> Weight { - (435_443_000 as Weight) - // Standard Error: 1_408_000 - .saturating_add((15_624_877_000 as Weight).saturating_mul(r as Weight)) + (361_122_000 as Weight) + // Standard Error: 1_172_000 + .saturating_add((15_591_590_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn instr_i64const(r: u32, ) -> Weight { - (45_937_000 as Weight) + (46_003_000 as Weight) // Standard Error: 10_000 - .saturating_add((1_108_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_185_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64load(r: u32, ) -> Weight { - (44_001_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_412_000 as Weight).saturating_mul(r as Weight)) + (42_908_000 as Weight) + // Standard Error: 13_000 + .saturating_add((2_570_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64store(r: u32, ) -> Weight { - (43_157_000 as Weight) - // Standard Error: 12_000 - .saturating_add((2_677_000 as Weight).saturating_mul(r as Weight)) + (42_739_000 as Weight) + // Standard Error: 13_000 + .saturating_add((2_791_000 as Weight).saturating_mul(r as Weight)) } fn instr_select(r: u32, ) -> Weight { - (48_475_000 as Weight) + (47_543_000 as Weight) // Standard Error: 8_000 - .saturating_add((2_604_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_834_000 as Weight).saturating_mul(r as Weight)) } fn instr_if(r: u32, ) -> Weight { - (50_649_000 as Weight) - // Standard Error: 12_000 - .saturating_add((2_553_000 as Weight).saturating_mul(r as Weight)) + (50_540_000 as Weight) + // Standard Error: 13_000 + .saturating_add((2_663_000 as Weight).saturating_mul(r as Weight)) } fn instr_br(r: u32, ) -> Weight { - (48_433_000 as Weight) + (47_732_000 as Weight) // Standard Error: 8_000 - .saturating_add((1_670_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_771_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_if(r: u32, ) -> Weight { - (49_244_000 as Weight) - // Standard Error: 16_000 - .saturating_add((1_946_000 as Weight).saturating_mul(r as Weight)) + (49_005_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_072_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table(r: u32, ) -> Weight { - (46_117_000 as Weight) + (45_975_000 as Weight) // Standard Error: 17_000 - .saturating_add((2_387_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_492_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table_per_entry(_e: u32, ) -> Weight { - (55_204_000 as Weight) + (55_461_000 as Weight) } fn instr_call(r: u32, ) -> Weight { - (43_651_000 as Weight) - // Standard Error: 26_000 - .saturating_add((19_163_000 as Weight).saturating_mul(r as Weight)) + (41_932_000 as Weight) + // Standard Error: 29_000 + .saturating_add((19_800_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect(r: u32, ) -> Weight { - (54_063_000 as Weight) - // Standard Error: 32_000 - .saturating_add((27_970_000 as Weight).saturating_mul(r as Weight)) + (56_550_000 as Weight) + // Standard Error: 34_000 + .saturating_add((28_414_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect_per_param(p: u32, ) -> Weight { - (88_527_000 as Weight) + (93_172_000 as Weight) // Standard Error: 6_000 - .saturating_add((958_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((1_018_000 as Weight).saturating_mul(p as Weight)) } fn instr_local_get(r: u32, ) -> Weight { - (55_066_000 as Weight) - // Standard Error: 12_000 - .saturating_add((682_000 as Weight).saturating_mul(r as Weight)) + (54_603_000 as Weight) + // Standard Error: 14_000 + .saturating_add((764_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_set(r: u32, ) -> Weight { - (55_298_000 as Weight) - // Standard Error: 13_000 - .saturating_add((778_000 as Weight).saturating_mul(r as Weight)) + (54_763_000 as Weight) + // Standard Error: 14_000 + .saturating_add((878_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_tee(r: u32, ) -> Weight { - (56_302_000 as Weight) + (56_137_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_079_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_194_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_get(r: u32, ) -> Weight { - (71_567_000 as Weight) + (69_513_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_107_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_125_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_set(r: u32, ) -> Weight { - (71_186_000 as Weight) + (69_120_000 as Weight) // Standard Error: 12_000 - .saturating_add((1_151_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_215_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_current(r: u32, ) -> Weight { - (46_240_000 as Weight) + (46_021_000 as Weight) // Standard Error: 10_000 - .saturating_add((1_044_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_103_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_grow(r: u32, ) -> Weight { - (52_369_000 as Weight) - // Standard Error: 2_508_000 - .saturating_add((615_448_000 as Weight).saturating_mul(r as Weight)) + (52_245_000 as Weight) + // Standard Error: 4_119_000 + .saturating_add((619_498_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64clz(r: u32, ) -> Weight { - (47_623_000 as Weight) + (47_314_000 as Weight) // Standard Error: 9_000 - .saturating_add((1_583_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_720_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ctz(r: u32, ) -> Weight { - (47_670_000 as Weight) + (47_855_000 as Weight) // Standard Error: 9_000 - .saturating_add((1_583_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_701_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64popcnt(r: u32, ) -> Weight { - (47_508_000 as Weight) - // Standard Error: 9_000 - .saturating_add((1_583_000 as Weight).saturating_mul(r as Weight)) + (47_704_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_708_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eqz(r: u32, ) -> Weight { - (48_109_000 as Weight) + (47_656_000 as Weight) // Standard Error: 9_000 - .saturating_add((1_580_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_705_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendsi32(r: u32, ) -> Weight { - (55_270_000 as Weight) - // Standard Error: 9_000 - .saturating_add((1_102_000 as Weight).saturating_mul(r as Weight)) + (55_202_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_229_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendui32(r: u32, ) -> Weight { - (55_093_000 as Weight) + (55_193_000 as Weight) // Standard Error: 9_000 - .saturating_add((1_108_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_223_000 as Weight).saturating_mul(r as Weight)) } fn instr_i32wrapi64(r: u32, ) -> Weight { - (48_265_000 as Weight) + (48_125_000 as Weight) // Standard Error: 10_000 - .saturating_add((1_573_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_704_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eq(r: u32, ) -> Weight { - (48_733_000 as Weight) + (49_162_000 as Weight) // Standard Error: 7_000 - .saturating_add((2_088_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_241_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ne(r: u32, ) -> Weight { - (48_831_000 as Weight) - // Standard Error: 6_000 - .saturating_add((2_085_000 as Weight).saturating_mul(r as Weight)) + (48_635_000 as Weight) + // Standard Error: 7_000 + .saturating_add((2_262_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64lts(r: u32, ) -> Weight { - (49_147_000 as Weight) - // Standard Error: 6_000 - .saturating_add((2_056_000 as Weight).saturating_mul(r as Weight)) + (48_550_000 as Weight) + // Standard Error: 9_000 + .saturating_add((2_267_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ltu(r: u32, ) -> Weight { - (49_596_000 as Weight) + (49_135_000 as Weight) // Standard Error: 7_000 - .saturating_add((2_049_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_219_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gts(r: u32, ) -> Weight { - (49_872_000 as Weight) + (49_638_000 as Weight) // Standard Error: 7_000 - .saturating_add((2_038_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_206_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gtu(r: u32, ) -> Weight { - (48_843_000 as Weight) - // Standard Error: 6_000 - .saturating_add((2_081_000 as Weight).saturating_mul(r as Weight)) + (49_889_000 as Weight) + // Standard Error: 7_000 + .saturating_add((2_201_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64les(r: u32, ) -> Weight { - (48_765_000 as Weight) - // Standard Error: 6_000 - .saturating_add((2_089_000 as Weight).saturating_mul(r as Weight)) + (49_763_000 as Weight) + // Standard Error: 9_000 + .saturating_add((2_210_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64leu(r: u32, ) -> Weight { - (48_720_000 as Weight) - // Standard Error: 6_000 - .saturating_add((2_083_000 as Weight).saturating_mul(r as Weight)) + (49_607_000 as Weight) + // Standard Error: 7_000 + .saturating_add((2_207_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ges(r: u32, ) -> Weight { - (48_736_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_097_000 as Weight).saturating_mul(r as Weight)) + (49_664_000 as Weight) + // Standard Error: 9_000 + .saturating_add((2_213_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64geu(r: u32, ) -> Weight { - (48_772_000 as Weight) + (49_718_000 as Weight) // Standard Error: 7_000 - .saturating_add((2_093_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_206_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64add(r: u32, ) -> Weight { - (48_827_000 as Weight) - // Standard Error: 6_000 - .saturating_add((2_082_000 as Weight).saturating_mul(r as Weight)) + (49_513_000 as Weight) + // Standard Error: 7_000 + .saturating_add((2_208_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64sub(r: u32, ) -> Weight { - (48_961_000 as Weight) + (49_837_000 as Weight) // Standard Error: 7_000 - .saturating_add((2_072_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_201_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64mul(r: u32, ) -> Weight { - (49_069_000 as Weight) + (49_684_000 as Weight) // Standard Error: 7_000 - .saturating_add((2_067_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_210_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divs(r: u32, ) -> Weight { - (49_035_000 as Weight) + (48_749_000 as Weight) // Standard Error: 7_000 - .saturating_add((2_677_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_872_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divu(r: u32, ) -> Weight { - (48_842_000 as Weight) - // Standard Error: 6_000 - .saturating_add((2_449_000 as Weight).saturating_mul(r as Weight)) + (49_134_000 as Weight) + // Standard Error: 7_000 + .saturating_add((2_630_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rems(r: u32, ) -> Weight { - (48_536_000 as Weight) - // Standard Error: 6_000 - .saturating_add((2_723_000 as Weight).saturating_mul(r as Weight)) + (48_981_000 as Weight) + // Standard Error: 7_000 + .saturating_add((2_861_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64remu(r: u32, ) -> Weight { - (48_851_000 as Weight) - // Standard Error: 6_000 - .saturating_add((2_432_000 as Weight).saturating_mul(r as Weight)) + (49_195_000 as Weight) + // Standard Error: 8_000 + .saturating_add((2_593_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64and(r: u32, ) -> Weight { - (48_624_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_093_000 as Weight).saturating_mul(r as Weight)) + (49_304_000 as Weight) + // Standard Error: 8_000 + .saturating_add((2_238_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64or(r: u32, ) -> Weight { - (49_348_000 as Weight) - // Standard Error: 8_000 - .saturating_add((2_073_000 as Weight).saturating_mul(r as Weight)) + (48_636_000 as Weight) + // Standard Error: 7_000 + .saturating_add((2_259_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64xor(r: u32, ) -> Weight { - (49_112_000 as Weight) - // Standard Error: 6_000 - .saturating_add((2_055_000 as Weight).saturating_mul(r as Weight)) + (48_761_000 as Weight) + // Standard Error: 8_000 + .saturating_add((2_262_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shl(r: u32, ) -> Weight { - (49_654_000 as Weight) + (48_492_000 as Weight) // Standard Error: 7_000 - .saturating_add((2_051_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_263_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shrs(r: u32, ) -> Weight { - (48_848_000 as Weight) + (48_736_000 as Weight) // Standard Error: 8_000 - .saturating_add((2_089_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_256_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shru(r: u32, ) -> Weight { - (49_455_000 as Weight) + (48_675_000 as Weight) // Standard Error: 7_000 - .saturating_add((2_054_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_256_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotl(r: u32, ) -> Weight { - (49_640_000 as Weight) + (48_703_000 as Weight) // Standard Error: 7_000 - .saturating_add((2_048_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_257_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotr(r: u32, ) -> Weight { - (49_498_000 as Weight) + (48_758_000 as Weight) // Standard Error: 7_000 - .saturating_add((2_068_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_259_000 as Weight).saturating_mul(r as Weight)) } } From 1d818f38a3198f21b4ae68bac3dc98219fccc669 Mon Sep 17 00:00:00 2001 From: Squirrel Date: Sat, 30 Oct 2021 14:38:27 +0200 Subject: [PATCH 111/695] Removal of light client from substrate (#9684) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Removal of light client from substrate * add missing import * These tests relate to there being light and non light clients. * removing lightnodes from test * cargo fmt * not needed * LightDataChecker not needed any longer * cargo fmt * Update client/service/test/src/lib.rs Co-authored-by: Bastian Köcher * Update client/service/test/src/lib.rs Co-authored-by: Bastian Köcher * cargo fmt Co-authored-by: Bastian Köcher --- Cargo.lock | 1 - bin/node-template/node/src/command.rs | 8 +- bin/node-template/node/src/service.rs | 143 +-- bin/node/cli/src/chain_spec.rs | 34 +- bin/node/cli/src/command.rs | 8 +- bin/node/cli/src/service.rs | 204 +--- .../tests/database_role_subdir_migration.rs | 116 --- client/light/src/blockchain.rs | 2 +- client/light/src/fetcher.rs | 366 ------- client/light/src/lib.rs | 20 +- client/rpc/src/state/mod.rs | 41 - client/rpc/src/state/state_light.rs | 873 ---------------- client/service/Cargo.toml | 1 - client/service/src/builder.rs | 136 +-- client/service/src/client/client.rs | 2 +- client/service/src/client/light.rs | 82 -- client/service/src/client/mod.rs | 1 - client/service/src/lib.rs | 7 +- client/service/test/src/client/db.rs | 1 + client/service/test/src/client/light.rs | 981 ------------------ client/service/test/src/client/mod.rs | 3 - client/service/test/src/lib.rs | 194 +--- 22 files changed, 83 insertions(+), 3141 deletions(-) delete mode 100644 bin/node/cli/tests/database_role_subdir_migration.rs delete mode 100644 client/light/src/fetcher.rs delete mode 100644 client/rpc/src/state/state_light.rs delete mode 100644 client/service/src/client/light.rs delete mode 100644 client/service/test/src/client/light.rs diff --git a/Cargo.lock b/Cargo.lock index ed10002bd548..c3cfaec19532 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8329,7 +8329,6 @@ dependencies = [ "sc-executor", "sc-informant", "sc-keystore", - "sc-light", "sc-network", "sc-offchain", "sc-rpc", diff --git a/bin/node-template/node/src/command.rs b/bin/node-template/node/src/command.rs index e948c3f53b71..e1cfeaeb801e 100644 --- a/bin/node-template/node/src/command.rs +++ b/bin/node-template/node/src/command.rs @@ -4,7 +4,7 @@ use crate::{ service, }; use node_template_runtime::Block; -use sc_cli::{ChainSpec, Role, RuntimeVersion, SubstrateCli}; +use sc_cli::{ChainSpec, RuntimeVersion, SubstrateCli}; use sc_service::PartialComponents; impl SubstrateCli for Cli { @@ -111,11 +111,7 @@ pub fn run() -> sc_cli::Result<()> { None => { let runner = cli.create_runner(&cli.run)?; runner.run_node_until_exit(|config| async move { - match config.role { - Role::Light => service::new_light(config), - _ => service::new_full(config), - } - .map_err(sc_cli::Error::Service) + service::new_full(config).map_err(sc_cli::Error::Service) }) }, } diff --git a/bin/node-template/node/src/service.rs b/bin/node-template/node/src/service.rs index 2286ad3bd654..d673a54a9488 100644 --- a/bin/node-template/node/src/service.rs +++ b/bin/node-template/node/src/service.rs @@ -1,7 +1,7 @@ //! Service and ServiceFactory implementation. Specialized wrapper over substrate service. use node_template_runtime::{self, opaque::Block, RuntimeApi}; -use sc_client_api::{ExecutorProvider, RemoteBackend}; +use sc_client_api::ExecutorProvider; use sc_consensus_aura::{ImportQueueParams, SlotProportion, StartAuraParams}; pub use sc_executor::NativeElseWasmExecutor; use sc_finality_grandpa::SharedVoterState; @@ -336,144 +336,3 @@ pub fn new_full(mut config: Configuration) -> Result network_starter.start_network(); Ok(task_manager) } - -/// Builds a new service for a light client. -pub fn new_light(mut config: Configuration) -> Result { - let telemetry = config - .telemetry_endpoints - .clone() - .filter(|x| !x.is_empty()) - .map(|endpoints| -> Result<_, sc_telemetry::Error> { - let worker = TelemetryWorker::new(16)?; - let telemetry = worker.handle().new_telemetry(endpoints); - Ok((worker, telemetry)) - }) - .transpose()?; - - let executor = NativeElseWasmExecutor::::new( - config.wasm_method, - config.default_heap_pages, - config.max_runtime_instances, - ); - - let (client, backend, keystore_container, mut task_manager, on_demand) = - sc_service::new_light_parts::( - &config, - telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), - executor, - )?; - - let mut telemetry = telemetry.map(|(worker, telemetry)| { - task_manager.spawn_handle().spawn("telemetry", worker.run()); - telemetry - }); - - config.network.extra_sets.push(sc_finality_grandpa::grandpa_peers_set_config()); - - let select_chain = sc_consensus::LongestChain::new(backend.clone()); - - let transaction_pool = Arc::new(sc_transaction_pool::BasicPool::new_light( - config.transaction_pool.clone(), - config.prometheus_registry(), - task_manager.spawn_essential_handle(), - client.clone(), - on_demand.clone(), - )); - - let (grandpa_block_import, grandpa_link) = sc_finality_grandpa::block_import( - client.clone(), - &(client.clone() as Arc<_>), - select_chain.clone(), - telemetry.as_ref().map(|x| x.handle()), - )?; - - let slot_duration = sc_consensus_aura::slot_duration(&*client)?.slot_duration(); - - let import_queue = - sc_consensus_aura::import_queue::(ImportQueueParams { - block_import: grandpa_block_import.clone(), - justification_import: Some(Box::new(grandpa_block_import.clone())), - client: client.clone(), - create_inherent_data_providers: move |_, ()| async move { - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - - let slot = - sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( - *timestamp, - slot_duration, - ); - - Ok((timestamp, slot)) - }, - spawner: &task_manager.spawn_essential_handle(), - can_author_with: sp_consensus::NeverCanAuthor, - registry: config.prometheus_registry(), - check_for_equivocation: Default::default(), - telemetry: telemetry.as_ref().map(|x| x.handle()), - })?; - - let warp_sync = Arc::new(sc_finality_grandpa::warp_proof::NetworkProvider::new( - backend.clone(), - grandpa_link.shared_authority_set().clone(), - Vec::default(), - )); - - let (network, system_rpc_tx, network_starter) = - sc_service::build_network(sc_service::BuildNetworkParams { - config: &config, - client: client.clone(), - transaction_pool: transaction_pool.clone(), - spawn_handle: task_manager.spawn_handle(), - import_queue, - on_demand: Some(on_demand.clone()), - block_announce_validator_builder: None, - warp_sync: Some(warp_sync), - })?; - - if config.offchain_worker.enabled { - sc_service::build_offchain_workers( - &config, - task_manager.spawn_handle(), - client.clone(), - network.clone(), - ); - } - - let enable_grandpa = !config.disable_grandpa; - if enable_grandpa { - let name = config.network.node_name.clone(); - - let config = sc_finality_grandpa::Config { - gossip_duration: std::time::Duration::from_millis(333), - justification_period: 512, - name: Some(name), - observer_enabled: false, - keystore: None, - local_role: config.role.clone(), - telemetry: telemetry.as_ref().map(|x| x.handle()), - }; - - task_manager.spawn_handle().spawn_blocking( - "grandpa-observer", - sc_finality_grandpa::run_grandpa_observer(config, grandpa_link, network.clone())?, - ); - } - - sc_service::spawn_tasks(sc_service::SpawnTasksParams { - remote_blockchain: Some(backend.remote_blockchain()), - transaction_pool, - task_manager: &mut task_manager, - on_demand: Some(on_demand), - rpc_extensions_builder: Box::new(|_, _| Ok(())), - config, - client, - keystore: keystore_container.sync_keystore(), - backend, - network, - system_rpc_tx, - telemetry: telemetry.as_mut(), - })?; - - network_starter.start_network(); - Ok(task_manager) -} diff --git a/bin/node/cli/src/chain_spec.rs b/bin/node/cli/src/chain_spec.rs index b5e36d9b5362..8499c66e0c9d 100644 --- a/bin/node/cli/src/chain_spec.rs +++ b/bin/node/cli/src/chain_spec.rs @@ -418,7 +418,7 @@ pub fn local_testnet_config() -> ChainSpec { #[cfg(test)] pub(crate) mod tests { use super::*; - use crate::service::{new_full_base, new_light_base, NewFullBase}; + use crate::service::{new_full_base, NewFullBase}; use sc_service_test; use sp_runtime::BuildStorage; @@ -466,28 +466,16 @@ pub(crate) mod tests { fn test_connectivity() { sp_tracing::try_init_simple(); - sc_service_test::connectivity( - integration_test_config_with_two_authorities(), - |config| { - let NewFullBase { task_manager, client, network, transaction_pool, .. } = - new_full_base(config, |_, _| ())?; - Ok(sc_service_test::TestNetComponents::new( - task_manager, - client, - network, - transaction_pool, - )) - }, - |config| { - let (keep_alive, _, client, network, transaction_pool) = new_light_base(config)?; - Ok(sc_service_test::TestNetComponents::new( - keep_alive, - client, - network, - transaction_pool, - )) - }, - ); + sc_service_test::connectivity(integration_test_config_with_two_authorities(), |config| { + let NewFullBase { task_manager, client, network, transaction_pool, .. } = + new_full_base(config, |_, _| ())?; + Ok(sc_service_test::TestNetComponents::new( + task_manager, + client, + network, + transaction_pool, + )) + }); } #[test] diff --git a/bin/node/cli/src/command.rs b/bin/node/cli/src/command.rs index 17375094f2a1..dd8202eb71aa 100644 --- a/bin/node/cli/src/command.rs +++ b/bin/node/cli/src/command.rs @@ -19,7 +19,7 @@ use crate::{chain_spec, service, service::new_partial, Cli, Subcommand}; use node_executor::ExecutorDispatch; use node_runtime::{Block, RuntimeApi}; -use sc_cli::{ChainSpec, Result, Role, RuntimeVersion, SubstrateCli}; +use sc_cli::{ChainSpec, Result, RuntimeVersion, SubstrateCli}; use sc_service::PartialComponents; impl SubstrateCli for Cli { @@ -77,11 +77,7 @@ pub fn run() -> Result<()> { None => { let runner = cli.create_runner(&cli.run)?; runner.run_node_until_exit(|config| async move { - match config.role { - Role::Light => service::new_light(config), - _ => service::new_full(config), - } - .map_err(sc_cli::Error::Service) + service::new_full(config).map_err(sc_cli::Error::Service) }) }, Some(Subcommand::Inspect(cmd)) => { diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index 938f35936818..2220614ebaf2 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -26,11 +26,11 @@ use futures::prelude::*; use node_executor::ExecutorDispatch; use node_primitives::Block; use node_runtime::RuntimeApi; -use sc_client_api::{BlockBackend, ExecutorProvider, RemoteBackend}; +use sc_client_api::{BlockBackend, ExecutorProvider}; use sc_consensus_babe::{self, SlotProportion}; use sc_executor::NativeElseWasmExecutor; use sc_network::{Event, NetworkService}; -use sc_service::{config::Configuration, error::Error as ServiceError, RpcHandlers, TaskManager}; +use sc_service::{config::Configuration, error::Error as ServiceError, TaskManager}; use sc_telemetry::{Telemetry, TelemetryWorker}; use sp_api::ProvideRuntimeApi; use sp_core::crypto::Pair; @@ -44,8 +44,7 @@ type FullBackend = sc_service::TFullBackend; type FullSelectChain = sc_consensus::LongestChain; type FullGrandpaBlockImport = grandpa::GrandpaBlockImport; -type LightClient = - sc_service::TLightClient>; + /// The transaction pool type defintion. pub type TransactionPool = sc_transaction_pool::FullPool; @@ -516,186 +515,9 @@ pub fn new_full(config: Configuration) -> Result { new_full_base(config, |_, _| ()).map(|NewFullBase { task_manager, .. }| task_manager) } -/// Creates a light service from the configuration. -pub fn new_light_base( - mut config: Configuration, -) -> Result< - ( - TaskManager, - RpcHandlers, - Arc, - Arc::Hash>>, - Arc< - sc_transaction_pool::LightPool>, - >, - ), - ServiceError, -> { - let telemetry = config - .telemetry_endpoints - .clone() - .filter(|x| !x.is_empty()) - .map(|endpoints| -> Result<_, sc_telemetry::Error> { - let worker = TelemetryWorker::new(16)?; - let telemetry = worker.handle().new_telemetry(endpoints); - Ok((worker, telemetry)) - }) - .transpose()?; - - let executor = NativeElseWasmExecutor::::new( - config.wasm_method, - config.default_heap_pages, - config.max_runtime_instances, - ); - - let (client, backend, keystore_container, mut task_manager, on_demand) = - sc_service::new_light_parts::( - &config, - telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), - executor, - )?; - - let mut telemetry = telemetry.map(|(worker, telemetry)| { - task_manager.spawn_handle().spawn("telemetry", worker.run()); - telemetry - }); - - config.network.extra_sets.push(grandpa::grandpa_peers_set_config()); - - let select_chain = sc_consensus::LongestChain::new(backend.clone()); - - let transaction_pool = Arc::new(sc_transaction_pool::BasicPool::new_light( - config.transaction_pool.clone(), - config.prometheus_registry(), - task_manager.spawn_essential_handle(), - client.clone(), - on_demand.clone(), - )); - - let (grandpa_block_import, grandpa_link) = grandpa::block_import( - client.clone(), - &(client.clone() as Arc<_>), - select_chain.clone(), - telemetry.as_ref().map(|x| x.handle()), - )?; - let justification_import = grandpa_block_import.clone(); - - let (babe_block_import, babe_link) = sc_consensus_babe::block_import( - sc_consensus_babe::Config::get_or_compute(&*client)?, - grandpa_block_import, - client.clone(), - )?; - - let slot_duration = babe_link.config().slot_duration(); - let import_queue = sc_consensus_babe::import_queue( - babe_link, - babe_block_import, - Some(Box::new(justification_import)), - client.clone(), - select_chain, - move |_, ()| async move { - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - - let slot = - sp_consensus_babe::inherents::InherentDataProvider::from_timestamp_and_duration( - *timestamp, - slot_duration, - ); - - let uncles = - sp_authorship::InherentDataProvider::<::Header>::check_inherents(); - - Ok((timestamp, slot, uncles)) - }, - &task_manager.spawn_essential_handle(), - config.prometheus_registry(), - sp_consensus::NeverCanAuthor, - telemetry.as_ref().map(|x| x.handle()), - )?; - - let warp_sync = Arc::new(grandpa::warp_proof::NetworkProvider::new( - backend.clone(), - grandpa_link.shared_authority_set().clone(), - Vec::default(), - )); - - let (network, system_rpc_tx, network_starter) = - sc_service::build_network(sc_service::BuildNetworkParams { - config: &config, - client: client.clone(), - transaction_pool: transaction_pool.clone(), - spawn_handle: task_manager.spawn_handle(), - import_queue, - on_demand: Some(on_demand.clone()), - block_announce_validator_builder: None, - warp_sync: Some(warp_sync), - })?; - - let enable_grandpa = !config.disable_grandpa; - if enable_grandpa { - let name = config.network.node_name.clone(); - - let config = grandpa::Config { - gossip_duration: std::time::Duration::from_millis(333), - justification_period: 512, - name: Some(name), - observer_enabled: false, - keystore: None, - local_role: config.role.clone(), - telemetry: telemetry.as_ref().map(|x| x.handle()), - }; - - task_manager.spawn_handle().spawn_blocking( - "grandpa-observer", - grandpa::run_grandpa_observer(config, grandpa_link, network.clone())?, - ); - } - - if config.offchain_worker.enabled { - sc_service::build_offchain_workers( - &config, - task_manager.spawn_handle(), - client.clone(), - network.clone(), - ); - } - - let light_deps = node_rpc::LightDeps { - remote_blockchain: backend.remote_blockchain(), - fetcher: on_demand.clone(), - client: client.clone(), - pool: transaction_pool.clone(), - }; - - let rpc_extensions = node_rpc::create_light(light_deps); - - let rpc_handlers = sc_service::spawn_tasks(sc_service::SpawnTasksParams { - on_demand: Some(on_demand), - remote_blockchain: Some(backend.remote_blockchain()), - rpc_extensions_builder: Box::new(sc_service::NoopRpcExtensionBuilder(rpc_extensions)), - client: client.clone(), - transaction_pool: transaction_pool.clone(), - keystore: keystore_container.sync_keystore(), - config, - backend, - system_rpc_tx, - network: network.clone(), - task_manager: &mut task_manager, - telemetry: telemetry.as_mut(), - })?; - - network_starter.start_network(); - Ok((task_manager, rpc_handlers, client, network, transaction_pool)) -} - -/// Builds a new service for a light client. -pub fn new_light(config: Configuration) -> Result { - new_light_base(config).map(|(task_manager, _, _, _, _)| task_manager) -} - #[cfg(test)] mod tests { - use crate::service::{new_full_base, new_light_base, NewFullBase}; + use crate::service::{new_full_base, NewFullBase}; use codec::Encode; use node_primitives::{Block, DigestItem, Signature}; use node_runtime::{ @@ -771,15 +593,6 @@ mod tests { ); Ok((node, setup_handles.unwrap())) }, - |config| { - let (keep_alive, _, client, network, transaction_pool) = new_light_base(config)?; - Ok(sc_service_test::TestNetComponents::new( - keep_alive, - client, - network, - transaction_pool, - )) - }, |service, &mut (ref mut block_import, ref babe_link)| { let parent_id = BlockId::number(service.client().chain_info().best_number); let parent_header = service.client().header(&parent_id).unwrap().unwrap(); @@ -946,15 +759,6 @@ mod tests { transaction_pool, )) }, - |config| { - let (keep_alive, _, client, network, transaction_pool) = new_light_base(config)?; - Ok(sc_service_test::TestNetComponents::new( - keep_alive, - client, - network, - transaction_pool, - )) - }, vec!["//Alice".into(), "//Bob".into()], ) } diff --git a/bin/node/cli/tests/database_role_subdir_migration.rs b/bin/node/cli/tests/database_role_subdir_migration.rs deleted file mode 100644 index 9338d8a8e4f4..000000000000 --- a/bin/node/cli/tests/database_role_subdir_migration.rs +++ /dev/null @@ -1,116 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2020-2021 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 . - -use sc_client_db::{ - light::LightStorage, DatabaseSettings, DatabaseSource, KeepBlocks, PruningMode, - TransactionStorageMode, -}; -use sp_runtime::testing::{Block as RawBlock, ExtrinsicWrapper}; -use tempfile::tempdir; - -pub mod common; - -#[tokio::test] -#[cfg(unix)] -async fn database_role_subdir_migration() { - type Block = RawBlock>; - - let base_path = tempdir().expect("could not create a temp dir"); - let path = base_path.path().join("chains/dev/db"); - // create a dummy database dir - { - let _old_db = LightStorage::::new(DatabaseSettings { - state_cache_size: 0, - state_cache_child_ratio: None, - state_pruning: PruningMode::ArchiveAll, - source: DatabaseSource::RocksDb { path: path.to_path_buf(), cache_size: 128 }, - keep_blocks: KeepBlocks::All, - transaction_storage: TransactionStorageMode::BlockBody, - }) - .unwrap(); - } - - assert!(path.join("db_version").exists()); - assert!(!path.join("light").exists()); - - // start a light client - common::run_node_for_a_while( - base_path.path(), - &[ - "--dev", - "--light", - "--port", - "30335", - "--rpc-port", - "44444", - "--ws-port", - "44445", - "--no-prometheus", - ], - ) - .await; - - // check if the database dir had been migrated - assert!(!path.join("db_version").exists()); - assert!(path.join("light/db_version").exists()); -} - -#[test] -#[cfg(unix)] -fn database_role_subdir_migration_fail_on_different_role() { - type Block = RawBlock>; - - let base_path = tempdir().expect("could not create a temp dir"); - let path = base_path.path().join("chains/dev/db"); - - // create a database with the old layout - { - let _old_db = LightStorage::::new(DatabaseSettings { - state_cache_size: 0, - state_cache_child_ratio: None, - state_pruning: PruningMode::ArchiveAll, - source: DatabaseSource::RocksDb { path: path.to_path_buf(), cache_size: 128 }, - keep_blocks: KeepBlocks::All, - transaction_storage: TransactionStorageMode::BlockBody, - }) - .unwrap(); - } - - assert!(path.join("db_version").exists()); - assert!(!path.join("light/db_version").exists()); - - // start a client with a different role (full), it should fail and not change any files on disk - common::run_node_assert_fail( - &base_path.path(), - &[ - "--dev", - "--port", - "30334", - "--rpc-port", - "44446", - "--ws-port", - "44447", - "--no-prometheus", - ], - ); - - // check if the files are unchanged - assert!(path.join("db_version").exists()); - assert!(!path.join("light/db_version").exists()); - assert!(!path.join("full/db_version").exists()); -} diff --git a/client/light/src/blockchain.rs b/client/light/src/blockchain.rs index e88c72419369..24d9ef4fd4b9 100644 --- a/client/light/src/blockchain.rs +++ b/client/light/src/blockchain.rs @@ -27,7 +27,7 @@ use sp_runtime::{ Justifications, }; -use crate::fetcher::RemoteHeaderRequest; +use sc_client_api::light::RemoteHeaderRequest; pub use sc_client_api::{ backend::{AuxStore, NewBlockState, ProvideChtRoots}, blockchain::{ diff --git a/client/light/src/fetcher.rs b/client/light/src/fetcher.rs deleted file mode 100644 index 5740e407a5e8..000000000000 --- a/client/light/src/fetcher.rs +++ /dev/null @@ -1,366 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2017-2021 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 . - -//! Light client data fetcher. Fetches requested data from remote full nodes. - -use std::{ - collections::{BTreeMap, HashMap}, - marker::PhantomData, - sync::Arc, -}; - -use codec::{Decode, Encode}; -use hash_db::{HashDB, Hasher, EMPTY_PREFIX}; -use sp_blockchain::{Error as ClientError, Result as ClientResult}; -use sp_core::{ - convert_hash, - storage::{ChildInfo, ChildType}, - traits::{CodeExecutor, SpawnNamed}, -}; -use sp_runtime::traits::{ - AtLeast32Bit, Block as BlockT, CheckedConversion, Hash, HashFor, Header as HeaderT, NumberFor, -}; -pub use sp_state_machine::StorageProof; -use sp_state_machine::{ - key_changes_proof_check_with_db, read_child_proof_check, read_proof_check, - ChangesTrieAnchorBlockId, ChangesTrieConfigurationRange, ChangesTrieRootsStorage, - InMemoryChangesTrieStorage, TrieBackend, -}; - -use crate::{blockchain::Blockchain, call_executor::check_execution_proof}; -pub use sc_client_api::{ - cht, - light::{ - ChangesProof, FetchChecker, Fetcher, RemoteBodyRequest, RemoteCallRequest, - RemoteChangesRequest, RemoteHeaderRequest, RemoteReadChildRequest, RemoteReadRequest, - Storage as BlockchainStorage, - }, -}; - -/// Remote data checker. -pub struct LightDataChecker> { - blockchain: Arc>, - executor: E, - spawn_handle: Box, - _marker: PhantomData, -} - -impl> LightDataChecker { - /// Create new light data checker. - pub fn new( - blockchain: Arc>, - executor: E, - spawn_handle: Box, - ) -> Self { - Self { blockchain, executor, spawn_handle, _marker: PhantomData } - } - - /// Check remote changes query proof assuming that CHT-s are of given size. - pub fn check_changes_proof_with_cht_size( - &self, - request: &RemoteChangesRequest, - remote_proof: ChangesProof, - cht_size: NumberFor, - ) -> ClientResult, u32)>> { - // since we need roots of all changes tries for the range begin..max - // => remote node can't use max block greater that one that we have passed - if remote_proof.max_block > request.max_block.0 || - remote_proof.max_block < request.last_block.0 - { - return Err(ClientError::ChangesTrieAccessFailed(format!( - "Invalid max_block used by the remote node: {}. Local: {}..{}..{}", - remote_proof.max_block, - request.first_block.0, - request.last_block.0, - request.max_block.0, - )) - .into()) - } - - // check if remote node has responded with extra changes trie roots proofs - // all changes tries roots must be in range [request.first_block.0; request.tries_roots.0) - let is_extra_first_root = remote_proof - .roots - .keys() - .next() - .map(|first_root| { - *first_root < request.first_block.0 || *first_root >= request.tries_roots.0 - }) - .unwrap_or(false); - let is_extra_last_root = remote_proof - .roots - .keys() - .next_back() - .map(|last_root| *last_root >= request.tries_roots.0) - .unwrap_or(false); - if is_extra_first_root || is_extra_last_root { - return Err(ClientError::ChangesTrieAccessFailed(format!( - "Extra changes tries roots proofs provided by the remote node: [{:?}..{:?}]. Expected in range: [{}; {})", - remote_proof.roots.keys().next(), remote_proof.roots.keys().next_back(), - request.first_block.0, request.tries_roots.0, - )).into()); - } - - // if request has been composed when some required headers were already pruned - // => remote node has sent us CHT-based proof of required changes tries roots - // => check that this proof is correct before proceeding with changes proof - let remote_max_block = remote_proof.max_block; - let remote_roots = remote_proof.roots; - let remote_roots_proof = remote_proof.roots_proof; - let remote_proof = remote_proof.proof; - if !remote_roots.is_empty() { - self.check_changes_tries_proof(cht_size, &remote_roots, remote_roots_proof)?; - } - - // and now check the key changes proof + get the changes - let mut result = Vec::new(); - let proof_storage = InMemoryChangesTrieStorage::with_proof(remote_proof); - for config_range in &request.changes_trie_configs { - let result_range = key_changes_proof_check_with_db::, _>( - ChangesTrieConfigurationRange { - config: config_range - .config - .as_ref() - .ok_or(ClientError::ChangesTriesNotSupported)?, - zero: config_range.zero.0, - end: config_range.end.map(|(n, _)| n), - }, - &RootsStorage { - roots: (request.tries_roots.0, &request.tries_roots.2), - prev_roots: &remote_roots, - }, - &proof_storage, - request.first_block.0, - &ChangesTrieAnchorBlockId { - hash: convert_hash(&request.last_block.1), - number: request.last_block.0, - }, - remote_max_block, - request.storage_key.as_ref(), - &request.key, - ) - .map_err(|err| ClientError::ChangesTrieAccessFailed(err))?; - result.extend(result_range); - } - - Ok(result) - } - - /// Check CHT-based proof for changes tries roots. - pub fn check_changes_tries_proof( - &self, - cht_size: NumberFor, - remote_roots: &BTreeMap, B::Hash>, - remote_roots_proof: StorageProof, - ) -> ClientResult<()> { - // all the checks are sharing the same storage - let storage = remote_roots_proof.into_memory_db(); - - // remote_roots.keys() are sorted => we can use this to group changes tries roots - // that are belongs to the same CHT - let blocks = remote_roots.keys().cloned(); - cht::for_each_cht_group::( - cht_size, - blocks, - |mut storage, _, cht_blocks| { - // get local changes trie CHT root for given CHT - // it should be there, because it is never pruned AND request has been composed - // when required header has been pruned (=> replaced with CHT) - let first_block = cht_blocks - .first() - .cloned() - .expect("for_each_cht_group never calls callback with empty groups"); - let local_cht_root = self - .blockchain - .storage() - .changes_trie_cht_root(cht_size, first_block)? - .ok_or(ClientError::InvalidCHTProof)?; - - // check changes trie root for every block within CHT range - for block in cht_blocks { - // check if the proofs storage contains the root - // normally this happens in when the proving backend is created, but since - // we share the storage for multiple checks, do it here - if !storage.contains(&local_cht_root, EMPTY_PREFIX) { - return Err(ClientError::InvalidCHTProof.into()) - } - - // check proof for single changes trie root - let proving_backend = TrieBackend::new(storage, local_cht_root); - let remote_changes_trie_root = remote_roots[&block]; - cht::check_proof_on_proving_backend::>( - local_cht_root, - block, - remote_changes_trie_root, - &proving_backend, - )?; - - // and return the storage to use in following checks - storage = proving_backend.into_storage(); - } - - Ok(storage) - }, - storage, - ) - } -} - -impl FetchChecker for LightDataChecker -where - Block: BlockT, - E: CodeExecutor + Clone + 'static, - S: BlockchainStorage, -{ - fn check_header_proof( - &self, - request: &RemoteHeaderRequest, - remote_header: Option, - remote_proof: StorageProof, - ) -> ClientResult { - let remote_header = - remote_header.ok_or_else(|| ClientError::from(ClientError::InvalidCHTProof))?; - let remote_header_hash = remote_header.hash(); - cht::check_proof::>( - request.cht_root, - request.block, - remote_header_hash, - remote_proof, - ) - .map(|_| remote_header) - } - - fn check_read_proof( - &self, - request: &RemoteReadRequest, - remote_proof: StorageProof, - ) -> ClientResult, Option>>> { - read_proof_check::, _>( - convert_hash(request.header.state_root()), - remote_proof, - request.keys.iter(), - ) - .map_err(|e| ClientError::from(e)) - } - - fn check_read_child_proof( - &self, - request: &RemoteReadChildRequest, - remote_proof: StorageProof, - ) -> ClientResult, Option>>> { - let child_info = match ChildType::from_prefixed_key(&request.storage_key) { - Some((ChildType::ParentKeyId, storage_key)) => ChildInfo::new_default(storage_key), - None => return Err(ClientError::InvalidChildType), - }; - read_child_proof_check::, _>( - convert_hash(request.header.state_root()), - remote_proof, - &child_info, - request.keys.iter(), - ) - .map_err(|e| ClientError::from(e)) - } - - fn check_execution_proof( - &self, - request: &RemoteCallRequest, - remote_proof: StorageProof, - ) -> ClientResult> { - check_execution_proof::<_, _, HashFor>( - &self.executor, - self.spawn_handle.clone(), - request, - remote_proof, - ) - } - - fn check_changes_proof( - &self, - request: &RemoteChangesRequest, - remote_proof: ChangesProof, - ) -> ClientResult, u32)>> { - self.check_changes_proof_with_cht_size(request, remote_proof, cht::size()) - } - - fn check_body_proof( - &self, - request: &RemoteBodyRequest, - body: Vec, - ) -> ClientResult> { - // TODO: #2621 - let extrinsics_root = - HashFor::::ordered_trie_root(body.iter().map(Encode::encode).collect()); - if *request.header.extrinsics_root() == extrinsics_root { - Ok(body) - } else { - Err(ClientError::ExtrinsicRootInvalid { - received: request.header.extrinsics_root().to_string(), - expected: extrinsics_root.to_string(), - }) - } - } -} - -/// A view of BTreeMap as a changes trie roots storage. -struct RootsStorage<'a, Number: AtLeast32Bit, Hash: 'a> { - roots: (Number, &'a [Hash]), - prev_roots: &'a BTreeMap, -} - -impl<'a, H, Number, Hash> ChangesTrieRootsStorage for RootsStorage<'a, Number, Hash> -where - H: Hasher, - Number: std::fmt::Display - + std::hash::Hash - + Clone - + AtLeast32Bit - + Encode - + Decode - + Send - + Sync - + 'static, - Hash: 'a + Send + Sync + Clone + AsRef<[u8]>, -{ - fn build_anchor( - &self, - _hash: H::Out, - ) -> Result, String> { - Err("build_anchor is only called when building block".into()) - } - - fn root( - &self, - _anchor: &ChangesTrieAnchorBlockId, - block: Number, - ) -> Result, String> { - // we can't ask for roots from parallel forks here => ignore anchor - let root = if block < self.roots.0 { - self.prev_roots.get(&Number::unique_saturated_from(block)).cloned() - } else { - let index: Option = - block.checked_sub(&self.roots.0).and_then(|index| index.checked_into()); - index.and_then(|index| self.roots.1.get(index as usize).cloned()) - }; - - Ok(root.map(|root| { - let mut hasher_root: H::Out = Default::default(); - hasher_root.as_mut().copy_from_slice(root.as_ref()); - hasher_root - })) - } -} diff --git a/client/light/src/lib.rs b/client/light/src/lib.rs index 0c874326ef2e..4b084cda0f8b 100644 --- a/client/light/src/lib.rs +++ b/client/light/src/lib.rs @@ -18,36 +18,18 @@ //! Light client components. -use sp_core::traits::{CodeExecutor, SpawnNamed}; use sp_runtime::traits::{Block as BlockT, HashFor}; use std::sync::Arc; pub mod backend; pub mod blockchain; pub mod call_executor; -pub mod fetcher; pub use backend::*; pub use blockchain::*; pub use call_executor::*; -pub use fetcher::*; - -/// Create an instance of fetch data checker. -pub fn new_fetch_checker>( - blockchain: Arc>, - executor: E, - spawn_handle: Box, -) -> LightDataChecker -where - E: CodeExecutor, -{ - LightDataChecker::new(blockchain, executor, spawn_handle) -} -/// Create an instance of light client blockchain backend. -pub fn new_light_blockchain>(storage: S) -> Arc> { - Arc::new(Blockchain::new(storage)) -} +use sc_client_api::light::Storage as BlockchainStorage; /// Create an instance of light client backend. pub fn new_light_backend(blockchain: Arc>) -> Arc>> diff --git a/client/rpc/src/state/mod.rs b/client/rpc/src/state/mod.rs index 80eccc2c97de..bacf39124abc 100644 --- a/client/rpc/src/state/mod.rs +++ b/client/rpc/src/state/mod.rs @@ -19,7 +19,6 @@ //! Substrate state API. mod state_full; -mod state_light; #[cfg(test)] mod tests; @@ -29,7 +28,6 @@ use jsonrpc_pubsub::{manager::SubscriptionManager, typed::Subscriber, Subscripti use rpc::Result as RpcResult; use std::sync::Arc; -use sc_client_api::light::{Fetcher, RemoteBlockchain}; use sc_rpc_api::{state::ReadProof, DenyUnsafe}; use sp_core::{ storage::{PrefixedStorageKey, StorageChangeSet, StorageData, StorageKey}, @@ -217,45 +215,6 @@ where (State { backend, deny_unsafe }, ChildState { backend: child_backend }) } -/// Create new state API that works on light node. -pub fn new_light>( - client: Arc, - subscriptions: SubscriptionManager, - remote_blockchain: Arc>, - fetcher: Arc, - deny_unsafe: DenyUnsafe, -) -> (State, ChildState) -where - Block: BlockT + 'static, - Block::Hash: Unpin, - BE: Backend + 'static, - Client: ExecutorProvider - + StorageProvider - + HeaderMetadata - + ProvideRuntimeApi - + HeaderBackend - + BlockchainEvents - + Send - + Sync - + 'static, - F: Send + Sync + 'static, -{ - let child_backend = Box::new(self::state_light::LightState::new( - client.clone(), - subscriptions.clone(), - remote_blockchain.clone(), - fetcher.clone(), - )); - - let backend = Box::new(self::state_light::LightState::new( - client, - subscriptions, - remote_blockchain, - fetcher, - )); - (State { backend, deny_unsafe }, ChildState { backend: child_backend }) -} - /// State API with subscriptions support. pub struct State { backend: Box>, diff --git a/client/rpc/src/state/state_light.rs b/client/rpc/src/state/state_light.rs deleted file mode 100644 index 749e57c365cc..000000000000 --- a/client/rpc/src/state/state_light.rs +++ /dev/null @@ -1,873 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2019-2021 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 . - -//! State API backend for light nodes. - -use codec::Decode; -use futures::{ - channel::oneshot::{channel, Sender}, - future::{ready, Either}, - Future, FutureExt, SinkExt, Stream, StreamExt as _, TryFutureExt, TryStreamExt as _, -}; -use hash_db::Hasher; -use jsonrpc_pubsub::{manager::SubscriptionManager, typed::Subscriber, SubscriptionId}; -use log::warn; -use parking_lot::Mutex; -use rpc::Result as RpcResult; -use std::{ - collections::{hash_map::Entry, HashMap, HashSet}, - sync::Arc, -}; - -use sc_client_api::{ - light::{ - future_header, Fetcher, RemoteBlockchain, RemoteCallRequest, RemoteReadChildRequest, - RemoteReadRequest, - }, - BlockchainEvents, -}; -use sc_rpc_api::state::ReadProof; -use sp_blockchain::{Error as ClientError, HeaderBackend}; -use sp_core::{ - storage::{PrefixedStorageKey, StorageChangeSet, StorageData, StorageKey}, - Bytes, OpaqueMetadata, -}; -use sp_runtime::{ - generic::BlockId, - traits::{Block as BlockT, HashFor}, -}; -use sp_version::RuntimeVersion; - -use super::{ - client_err, - error::{Error, FutureResult}, - ChildStateBackend, StateBackend, -}; - -/// Storage data map of storage keys => (optional) storage value. -type StorageMap = HashMap>; - -/// State API backend for light nodes. -#[derive(Clone)] -pub struct LightState, Client> { - client: Arc, - subscriptions: SubscriptionManager, - version_subscriptions: SimpleSubscriptions, - storage_subscriptions: Arc>>, - remote_blockchain: Arc>, - fetcher: Arc, -} - -/// Shared requests container. -trait SharedRequests: Clone + Send + Sync { - /// Tries to listen for already issued request, or issues request. - /// - /// Returns true if requests has been issued. - fn listen_request(&self, block: Hash, sender: Sender>) -> bool; - - /// Returns (and forgets) all listeners for given request. - fn on_response_received(&self, block: Hash) -> Vec>>; -} - -/// Storage subscriptions data. -struct StorageSubscriptions { - /// Active storage requests. - active_requests: HashMap>>>, - /// Map of subscription => keys that this subscription watch for. - keys_by_subscription: HashMap>, - /// Map of key => set of subscriptions that watch this key. - subscriptions_by_key: HashMap>, -} - -impl SharedRequests - for Arc>> -{ - fn listen_request(&self, block: Block::Hash, sender: Sender>) -> bool { - let mut subscriptions = self.lock(); - let active_requests_at = subscriptions.active_requests.entry(block).or_default(); - active_requests_at.push(sender); - active_requests_at.len() == 1 - } - - fn on_response_received(&self, block: Block::Hash) -> Vec>> { - self.lock().active_requests.remove(&block).unwrap_or_default() - } -} - -/// Simple, maybe shared, subscription data that shares per block requests. -type SimpleSubscriptions = Arc>>>>>; - -impl SharedRequests for SimpleSubscriptions -where - Hash: Send + Eq + std::hash::Hash, - V: Send, -{ - fn listen_request(&self, block: Hash, sender: Sender>) -> bool { - let mut subscriptions = self.lock(); - let active_requests_at = subscriptions.entry(block).or_default(); - active_requests_at.push(sender); - active_requests_at.len() == 1 - } - - fn on_response_received(&self, block: Hash) -> Vec>> { - self.lock().remove(&block).unwrap_or_default() - } -} - -impl + 'static, Client> LightState -where - Block: BlockT, - Client: HeaderBackend + Send + Sync + 'static, -{ - /// Create new state API backend for light nodes. - pub fn new( - client: Arc, - subscriptions: SubscriptionManager, - remote_blockchain: Arc>, - fetcher: Arc, - ) -> Self { - Self { - client, - subscriptions, - version_subscriptions: Arc::new(Mutex::new(HashMap::new())), - storage_subscriptions: Arc::new(Mutex::new(StorageSubscriptions { - active_requests: HashMap::new(), - keys_by_subscription: HashMap::new(), - subscriptions_by_key: HashMap::new(), - })), - remote_blockchain, - fetcher, - } - } - - /// Returns given block hash or best block hash if None is passed. - fn block_or_best(&self, hash: Option) -> Block::Hash { - hash.unwrap_or_else(|| self.client.info().best_hash) - } -} - -impl StateBackend for LightState -where - Block: BlockT, - Block::Hash: Unpin, - Client: BlockchainEvents + HeaderBackend + Send + Sync + 'static, - F: Fetcher + 'static, -{ - fn call( - &self, - block: Option, - method: String, - call_data: Bytes, - ) -> FutureResult { - call( - &*self.remote_blockchain, - self.fetcher.clone(), - self.block_or_best(block), - method, - call_data, - ) - .boxed() - } - - fn storage_keys( - &self, - _block: Option, - _prefix: StorageKey, - ) -> FutureResult> { - async move { Err(client_err(ClientError::NotAvailableOnLightClient)) }.boxed() - } - - fn storage_pairs( - &self, - _block: Option, - _prefix: StorageKey, - ) -> FutureResult> { - async move { Err(client_err(ClientError::NotAvailableOnLightClient)) }.boxed() - } - - fn storage_keys_paged( - &self, - _block: Option, - _prefix: Option, - _count: u32, - _start_key: Option, - ) -> FutureResult> { - async move { Err(client_err(ClientError::NotAvailableOnLightClient)) }.boxed() - } - - fn storage_size(&self, _: Option, _: StorageKey) -> FutureResult> { - async move { Err(client_err(ClientError::NotAvailableOnLightClient)) }.boxed() - } - - fn storage( - &self, - block: Option, - key: StorageKey, - ) -> FutureResult> { - storage( - &*self.remote_blockchain, - self.fetcher.clone(), - self.block_or_best(block), - vec![key.0.clone()], - ) - .map_ok(move |mut values| { - values - .remove(&key) - .expect("successful request has entries for all requested keys; qed") - }) - .boxed() - } - - fn storage_hash( - &self, - block: Option, - key: StorageKey, - ) -> FutureResult> { - let res = StateBackend::storage(self, block, key); - async move { res.await.map(|r| r.map(|s| HashFor::::hash(&s.0))) }.boxed() - } - - fn metadata(&self, block: Option) -> FutureResult { - self.call(block, "Metadata_metadata".into(), Bytes(Vec::new())) - .and_then(|metadata| async move { - OpaqueMetadata::decode(&mut &metadata.0[..]) - .map(Into::into) - .map_err(|decode_err| { - client_err(ClientError::CallResultDecode( - "Unable to decode metadata", - decode_err, - )) - }) - }) - .boxed() - } - - fn runtime_version(&self, block: Option) -> FutureResult { - runtime_version(&*self.remote_blockchain, self.fetcher.clone(), self.block_or_best(block)) - .boxed() - } - - fn query_storage( - &self, - _from: Block::Hash, - _to: Option, - _keys: Vec, - ) -> FutureResult>> { - async move { Err(client_err(ClientError::NotAvailableOnLightClient)) }.boxed() - } - - fn query_storage_at( - &self, - _keys: Vec, - _at: Option, - ) -> FutureResult>> { - async move { Err(client_err(ClientError::NotAvailableOnLightClient)) }.boxed() - } - - fn read_proof( - &self, - _block: Option, - _keys: Vec, - ) -> FutureResult> { - async move { Err(client_err(ClientError::NotAvailableOnLightClient)) }.boxed() - } - - fn subscribe_storage( - &self, - _meta: crate::Metadata, - subscriber: Subscriber>, - keys: Option>, - ) { - let keys = match keys { - Some(keys) if !keys.is_empty() => keys, - _ => { - warn!("Cannot subscribe to all keys on light client. Subscription rejected."); - return - }, - }; - - let keys = keys.iter().cloned().collect::>(); - let keys_to_check = keys.iter().map(|k| k.0.clone()).collect::>(); - let subscription_id = self.subscriptions.add(subscriber, move |sink| { - let fetcher = self.fetcher.clone(); - let remote_blockchain = self.remote_blockchain.clone(); - let storage_subscriptions = self.storage_subscriptions.clone(); - let initial_block = self.block_or_best(None); - let initial_keys = keys_to_check.iter().cloned().collect::>(); - - let changes_stream = subscription_stream::( - storage_subscriptions.clone(), - self.client.import_notification_stream().map(|notification| notification.hash), - display_error( - storage(&*remote_blockchain, fetcher.clone(), initial_block, initial_keys) - .map(move |r| r.map(|r| (initial_block, r))), - ), - move |block| { - // there'll be single request per block for all active subscriptions - // with all subscribed keys - let keys = storage_subscriptions - .lock() - .subscriptions_by_key - .keys() - .map(|k| k.0.clone()) - .collect(); - - storage(&*remote_blockchain, fetcher.clone(), block, keys) - }, - move |block, old_value, new_value| { - // let's only select keys which are valid for this subscription - let new_value = new_value - .iter() - .filter(|(k, _)| keys_to_check.contains(&k.0)) - .map(|(k, v)| (k.clone(), v.clone())) - .collect::>(); - let value_differs = old_value - .as_ref() - .map(|old_value| **old_value != new_value) - .unwrap_or(true); - - value_differs.then(|| StorageChangeSet { - block, - changes: new_value.iter().map(|(k, v)| (k.clone(), v.clone())).collect(), - }) - }, - ); - - changes_stream - .map_ok(Ok) - .forward(sink.sink_map_err(|e| warn!("Error sending notifications: {:?}", e))) - // we ignore the resulting Stream (if the first stream is over we are unsubscribed) - .map(|_| ()) - }); - - // remember keys associated with this subscription - let mut storage_subscriptions = self.storage_subscriptions.lock(); - storage_subscriptions - .keys_by_subscription - .insert(subscription_id.clone(), keys.clone()); - for key in keys { - storage_subscriptions - .subscriptions_by_key - .entry(key) - .or_default() - .insert(subscription_id.clone()); - } - } - - fn unsubscribe_storage( - &self, - _meta: Option, - id: SubscriptionId, - ) -> RpcResult { - if !self.subscriptions.cancel(id.clone()) { - return Ok(false) - } - - // forget subscription keys - let mut storage_subscriptions = self.storage_subscriptions.lock(); - let keys = storage_subscriptions.keys_by_subscription.remove(&id); - for key in keys.into_iter().flat_map(|keys| keys.into_iter()) { - match storage_subscriptions.subscriptions_by_key.entry(key) { - Entry::Vacant(_) => unreachable!( - "every key from keys_by_subscription has\ - corresponding entry in subscriptions_by_key; qed" - ), - Entry::Occupied(mut entry) => { - entry.get_mut().remove(&id); - if entry.get().is_empty() { - entry.remove(); - } - }, - } - } - - Ok(true) - } - - fn subscribe_runtime_version( - &self, - _meta: crate::Metadata, - subscriber: Subscriber, - ) { - self.subscriptions.add(subscriber, move |sink| { - let fetcher = self.fetcher.clone(); - let remote_blockchain = self.remote_blockchain.clone(); - let version_subscriptions = self.version_subscriptions.clone(); - let initial_block = self.block_or_best(None); - - let versions_stream = subscription_stream::( - version_subscriptions, - self.client.import_notification_stream().map(|notification| notification.hash), - display_error( - runtime_version(&*remote_blockchain, fetcher.clone(), initial_block) - .map(move |r| r.map(|r| (initial_block, r))), - ), - move |block| runtime_version(&*remote_blockchain, fetcher.clone(), block), - |_, old_version, new_version| { - let version_differs = old_version - .as_ref() - .map(|old_version| *old_version != new_version) - .unwrap_or(true); - - version_differs.then(|| new_version.clone()) - }, - ); - - versions_stream - .map_ok(Ok) - .forward(sink.sink_map_err(|e| warn!("Error sending notifications: {:?}", e))) - // we ignore the resulting Stream (if the first stream is over we are unsubscribed) - .map(|_| ()) - }); - } - - fn unsubscribe_runtime_version( - &self, - _meta: Option, - id: SubscriptionId, - ) -> RpcResult { - Ok(self.subscriptions.cancel(id)) - } - - fn trace_block( - &self, - _block: Block::Hash, - _targets: Option, - _storage_keys: Option, - _methods: Option, - ) -> FutureResult { - async move { Err(client_err(ClientError::NotAvailableOnLightClient)) }.boxed() - } -} - -impl ChildStateBackend for LightState -where - Block: BlockT, - Client: BlockchainEvents + HeaderBackend + Send + Sync + 'static, - F: Fetcher + 'static, -{ - fn read_child_proof( - &self, - _block: Option, - _storage_key: PrefixedStorageKey, - _keys: Vec, - ) -> FutureResult> { - async move { Err(client_err(ClientError::NotAvailableOnLightClient)) }.boxed() - } - - fn storage_keys( - &self, - _block: Option, - _storage_key: PrefixedStorageKey, - _prefix: StorageKey, - ) -> FutureResult> { - async move { Err(client_err(ClientError::NotAvailableOnLightClient)) }.boxed() - } - - fn storage_keys_paged( - &self, - _block: Option, - _storage_key: PrefixedStorageKey, - _prefix: Option, - _count: u32, - _start_key: Option, - ) -> FutureResult> { - async move { Err(client_err(ClientError::NotAvailableOnLightClient)) }.boxed() - } - - fn storage( - &self, - block: Option, - storage_key: PrefixedStorageKey, - key: StorageKey, - ) -> FutureResult> { - let block = self.block_or_best(block); - let fetcher = self.fetcher.clone(); - let child_storage = - resolve_header(&*self.remote_blockchain, &*self.fetcher, block).then(move |result| { - match result { - Ok(header) => Either::Left( - fetcher - .remote_read_child(RemoteReadChildRequest { - block, - header, - storage_key, - keys: vec![key.0.clone()], - retry_count: Default::default(), - }) - .then(move |result| { - ready( - result - .map(|mut data| { - data.remove(&key.0) - .expect( - "successful result has entry for all keys; qed", - ) - .map(StorageData) - }) - .map_err(client_err), - ) - }), - ), - Err(error) => Either::Right(ready(Err(error))), - } - }); - - child_storage.boxed() - } - - fn storage_entries( - &self, - block: Option, - storage_key: PrefixedStorageKey, - keys: Vec, - ) -> FutureResult>> { - let block = self.block_or_best(block); - let fetcher = self.fetcher.clone(); - let keys = keys.iter().map(|k| k.0.clone()).collect::>(); - let child_storage = - resolve_header(&*self.remote_blockchain, &*self.fetcher, block).then(move |result| { - match result { - Ok(header) => Either::Left( - fetcher - .remote_read_child(RemoteReadChildRequest { - block, - header, - storage_key, - keys: keys.clone(), - retry_count: Default::default(), - }) - .then(move |result| { - ready( - result - .map(|data| { - data.iter() - .filter_map(|(k, d)| { - keys.contains(k).then(|| { - d.as_ref().map(|v| StorageData(v.to_vec())) - }) - }) - .collect::>() - }) - .map_err(client_err), - ) - }), - ), - Err(error) => Either::Right(ready(Err(error))), - } - }); - - child_storage.boxed() - } - - fn storage_hash( - &self, - block: Option, - storage_key: PrefixedStorageKey, - key: StorageKey, - ) -> FutureResult> { - let child_storage = ChildStateBackend::storage(self, block, storage_key, key); - - async move { child_storage.await.map(|r| r.map(|s| HashFor::::hash(&s.0))) }.boxed() - } -} - -/// Resolve header by hash. -fn resolve_header>( - remote_blockchain: &dyn RemoteBlockchain, - fetcher: &F, - block: Block::Hash, -) -> impl std::future::Future> { - let maybe_header = future_header(remote_blockchain, fetcher, BlockId::Hash(block)); - - maybe_header.then(move |result| { - ready( - result - .and_then(|maybe_header| { - maybe_header.ok_or_else(|| ClientError::UnknownBlock(format!("{}", block))) - }) - .map_err(client_err), - ) - }) -} - -/// Call runtime method at given block -fn call>( - remote_blockchain: &dyn RemoteBlockchain, - fetcher: Arc, - block: Block::Hash, - method: String, - call_data: Bytes, -) -> impl std::future::Future> { - resolve_header(remote_blockchain, &*fetcher, block).then(move |result| match result { - Ok(header) => Either::Left( - fetcher - .remote_call(RemoteCallRequest { - block, - header, - method, - call_data: call_data.0, - retry_count: Default::default(), - }) - .then(|result| ready(result.map(Bytes).map_err(client_err))), - ), - Err(error) => Either::Right(ready(Err(error))), - }) -} - -/// Get runtime version at given block. -fn runtime_version>( - remote_blockchain: &dyn RemoteBlockchain, - fetcher: Arc, - block: Block::Hash, -) -> impl std::future::Future> { - call(remote_blockchain, fetcher, block, "Core_version".into(), Bytes(Vec::new())).then( - |version| { - ready(version.and_then(|version| { - Decode::decode(&mut &version.0[..]) - .map_err(|e| client_err(ClientError::VersionInvalid(e.to_string()))) - })) - }, - ) -} - -/// Get storage value at given key at given block. -fn storage>( - remote_blockchain: &dyn RemoteBlockchain, - fetcher: Arc, - block: Block::Hash, - keys: Vec>, -) -> impl std::future::Future>, Error>> { - resolve_header(remote_blockchain, &*fetcher, block).then(move |result| match result { - Ok(header) => Either::Left( - fetcher - .remote_read(RemoteReadRequest { - block, - header, - keys, - retry_count: Default::default(), - }) - .then(|result| { - ready( - result - .map(|result| { - result - .into_iter() - .map(|(key, value)| (StorageKey(key), value.map(StorageData))) - .collect() - }) - .map_err(client_err), - ) - }), - ), - Err(error) => Either::Right(ready(Err(error))), - }) -} - -/// Returns subscription stream that issues request on every imported block and -/// if value has changed from previous block, emits (stream) item. -fn subscription_stream< - Block, - Requests, - FutureBlocksStream, - V, - N, - InitialRequestFuture, - IssueRequest, - IssueRequestFuture, - CompareValues, ->( - shared_requests: Requests, - future_blocks_stream: FutureBlocksStream, - initial_request: InitialRequestFuture, - issue_request: IssueRequest, - compare_values: CompareValues, -) -> impl Stream> -where - Block: BlockT, - Requests: 'static + SharedRequests, - FutureBlocksStream: Stream, - V: Send + 'static + Clone, - InitialRequestFuture: Future> + Send + 'static, - IssueRequest: 'static + Fn(Block::Hash) -> IssueRequestFuture, - IssueRequestFuture: Future> + Send + 'static, - CompareValues: Fn(Block::Hash, Option<&V>, &V) -> Option, -{ - // we need to send initial value first, then we'll only be sending if value has changed - let previous_value = Arc::new(Mutex::new(None)); - - // prepare 'stream' of initial values - let initial_value_stream = initial_request.into_stream(); - - // prepare stream of future values - // - // we do not want to stop stream if single request fails - // (the warning should have been already issued by the request issuer) - let future_values_stream = future_blocks_stream - .then(move |block| { - maybe_share_remote_request::( - shared_requests.clone(), - block, - &issue_request, - ) - .map(move |r| r.map(|v| (block, v))) - }) - .filter(|r| ready(r.is_ok())); - - // now let's return changed values for selected blocks - initial_value_stream - .chain(future_values_stream) - .try_filter_map(move |(block, new_value)| { - let mut previous_value = previous_value.lock(); - let res = compare_values(block, previous_value.as_ref(), &new_value).map( - |notification_value| { - *previous_value = Some(new_value); - notification_value - }, - ); - async move { Ok(res) } - }) - .map_err(|_| ()) -} - -/// Request some data from remote node, probably reusing response from already -/// (in-progress) existing request. -fn maybe_share_remote_request( - shared_requests: Requests, - block: Block::Hash, - issue_request: &IssueRequest, -) -> impl std::future::Future> -where - V: Clone, - Requests: SharedRequests, - IssueRequest: Fn(Block::Hash) -> IssueRequestFuture, - IssueRequestFuture: std::future::Future>, -{ - let (sender, receiver) = channel(); - let need_issue_request = shared_requests.listen_request(block, sender); - - // if that isn't the first request - just listen for existing request' response - if !need_issue_request { - return Either::Right(receiver.then(|r| ready(r.unwrap_or(Err(()))))) - } - - // that is the first request - issue remote request + notify all listeners on - // completion - Either::Left(display_error(issue_request(block)).then(move |remote_result| { - let listeners = shared_requests.on_response_received(block); - // skip first element, because this future is the first element - for receiver in listeners.into_iter().skip(1) { - if let Err(_) = receiver.send(remote_result.clone()) { - // we don't care if receiver has been dropped already - } - } - - ready(remote_result) - })) -} - -/// Convert successful future result into Ok(result) and error into Err(()), -/// displaying warning. -fn display_error(future: F) -> impl std::future::Future> -where - F: std::future::Future>, -{ - future.then(|result| { - ready(result.or_else(|err| { - warn!("Remote request for subscription data has failed with: {:?}", err); - Err(()) - })) - }) -} - -#[cfg(test)] -mod tests { - use super::*; - use futures::{executor, stream}; - use sp_core::H256; - use substrate_test_runtime_client::runtime::Block; - - #[test] - fn subscription_stream_works() { - let stream = subscription_stream::( - SimpleSubscriptions::default(), - stream::iter(vec![H256::from([2; 32]), H256::from([3; 32])]), - ready(Ok((H256::from([1; 32]), 100))), - |block| match block[0] { - 2 => ready(Ok(100)), - 3 => ready(Ok(200)), - _ => unreachable!("should not issue additional requests"), - }, - |_, old_value, new_value| match old_value == Some(new_value) { - true => None, - false => Some(new_value.clone()), - }, - ); - - assert_eq!(executor::block_on(stream.collect::>()), vec![Ok(100), Ok(200)]); - } - - #[test] - fn subscription_stream_ignores_failed_requests() { - let stream = subscription_stream::( - SimpleSubscriptions::default(), - stream::iter(vec![H256::from([2; 32]), H256::from([3; 32])]), - ready(Ok((H256::from([1; 32]), 100))), - |block| match block[0] { - 2 => ready(Err(client_err(ClientError::NotAvailableOnLightClient))), - 3 => ready(Ok(200)), - _ => unreachable!("should not issue additional requests"), - }, - |_, old_value, new_value| match old_value == Some(new_value) { - true => None, - false => Some(new_value.clone()), - }, - ); - - assert_eq!(executor::block_on(stream.collect::>()), vec![Ok(100), Ok(200)]); - } - - #[test] - fn maybe_share_remote_request_shares_request() { - type UnreachableFuture = futures::future::Ready>; - - let shared_requests = SimpleSubscriptions::default(); - - // let's 'issue' requests for B1 - shared_requests.lock().insert(H256::from([1; 32]), vec![channel().0]); - - // make sure that no additional requests are issued when we're asking for B1 - let _ = maybe_share_remote_request::( - shared_requests.clone(), - H256::from([1; 32]), - &|_| unreachable!("no duplicate requests issued"), - ); - - // make sure that additional requests is issued when we're asking for B2 - let request_issued = Arc::new(Mutex::new(false)); - let _ = maybe_share_remote_request::( - shared_requests.clone(), - H256::from([2; 32]), - &|_| { - *request_issued.lock() = true; - ready(Ok(Default::default())) - }, - ); - assert!(*request_issued.lock()); - } -} diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index 589d7848a5b2..c3ae1452042f 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -53,7 +53,6 @@ sp-inherents = { version = "4.0.0-dev", path = "../../primitives/inherents" } sp-storage = { version = "4.0.0-dev", path = "../../primitives/storage" } sc-network = { version = "0.10.0-dev", path = "../network" } sc-chain-spec = { version = "4.0.0-dev", path = "../chain-spec" } -sc-light = { version = "4.0.0-dev", path = "../light" } sc-client-api = { version = "4.0.0-dev", path = "../api" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } sc-client-db = { version = "0.10.0-dev", default-features = false, path = "../db" } diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index e01a85878817..bcb05ce74370 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -18,7 +18,7 @@ use crate::{ build_network_future, - client::{light, Client, ClientConfig}, + client::{Client, ClientConfig}, config::{Configuration, KeystoreConfig, PrometheusConfig, TransactionStorageMode}, error::Error, metrics::MetricsService, @@ -58,7 +58,7 @@ use sp_core::traits::{CodeExecutor, SpawnNamed}; use sp_keystore::{CryptoStore, SyncCryptoStore, SyncCryptoStorePtr}; use sp_runtime::{ generic::BlockId, - traits::{Block as BlockT, BlockIdTo, HashFor, Zero}, + traits::{Block as BlockT, BlockIdTo, Zero}, BuildStorage, }; use std::{str::FromStr, sync::Arc, time::SystemTime}; @@ -137,47 +137,9 @@ pub type TFullBackend = sc_client_db::Backend; pub type TFullCallExecutor = crate::client::LocalCallExecutor, TExec>; -/// Light client type. -pub type TLightClient = - TLightClientWithBackend>; - -/// Light client backend type. -pub type TLightBackend = - sc_light::Backend, HashFor>; - -/// Light call executor type. -pub type TLightCallExecutor = sc_light::GenesisCallExecutor< - sc_light::Backend, HashFor>, - crate::client::LocalCallExecutor< - TBl, - sc_light::Backend, HashFor>, - TExec, - >, ->; - type TFullParts = (TFullClient, Arc>, KeystoreContainer, TaskManager); -type TLightParts = ( - Arc>, - Arc>, - KeystoreContainer, - TaskManager, - Arc>, -); - -/// Light client backend type with a specific hash type. -pub type TLightBackendWithHash = - sc_light::Backend, THash>; - -/// Light client type with a specific backend. -pub type TLightClientWithBackend = Client< - TBackend, - sc_light::GenesisCallExecutor>, - TBl, - TRtApi, ->; - trait AsCryptoStoreRef { fn keystore_ref(&self) -> Arc; fn sync_keystore_ref(&self) -> Arc; @@ -359,53 +321,6 @@ where Ok((client, backend, keystore_container, task_manager)) } -/// Create the initial parts of a light node. -pub fn new_light_parts( - config: &Configuration, - telemetry: Option, - executor: TExec, -) -> Result, Error> -where - TBl: BlockT, - TExec: CodeExecutor + RuntimeVersionOf + Clone, -{ - let keystore_container = KeystoreContainer::new(&config.keystore)?; - let task_manager = { - let registry = config.prometheus_config.as_ref().map(|cfg| &cfg.registry); - TaskManager::new(config.tokio_handle.clone(), registry)? - }; - - let db_storage = { - let db_settings = sc_client_db::DatabaseSettings { - state_cache_size: config.state_cache_size, - state_cache_child_ratio: config.state_cache_child_ratio.map(|v| (v, 100)), - state_pruning: config.state_pruning.clone(), - source: config.database.clone(), - keep_blocks: config.keep_blocks.clone(), - transaction_storage: config.transaction_storage.clone(), - }; - sc_client_db::light::LightStorage::new(db_settings)? - }; - let light_blockchain = sc_light::new_light_blockchain(db_storage); - let fetch_checker = Arc::new(sc_light::new_fetch_checker::<_, TBl, _>( - light_blockchain.clone(), - executor.clone(), - Box::new(task_manager.spawn_handle()), - )); - let on_demand = Arc::new(sc_network::config::OnDemand::new(fetch_checker)); - let backend = sc_light::new_light_backend(light_blockchain); - let client = Arc::new(light::new_light( - backend.clone(), - config.chain_spec.as_storage_builder(), - executor, - Box::new(task_manager.spawn_handle()), - config.prometheus_config.as_ref().map(|config| config.registry.clone()), - telemetry, - )?); - - Ok((client, backend, keystore_container, task_manager, on_demand)) -} - /// Create an instance of default DB-backend backend. pub fn new_db_backend( settings: DatabaseSettings, @@ -559,12 +474,12 @@ where mut config, task_manager, client, - on_demand, + on_demand: _, backend, keystore, transaction_pool, rpc_extensions_builder, - remote_blockchain, + remote_blockchain: _, network, system_rpc_tx, telemetry, @@ -630,8 +545,6 @@ where client.clone(), transaction_pool.clone(), keystore.clone(), - on_demand.clone(), - remote_blockchain.clone(), &*rpc_extensions_builder, backend.offchain_storage(), system_rpc_tx.clone(), @@ -729,8 +642,6 @@ fn gen_handler( client: Arc, transaction_pool: Arc, keystore: SyncCryptoStorePtr, - on_demand: Option>>, - remote_blockchain: Option>>, rpc_extensions_builder: &(dyn RpcExtensionBuilder + Send), offchain_storage: Option<>::OffchainStorage>, system_rpc_tx: TracingUnboundedSender>, @@ -769,34 +680,17 @@ where let task_executor = sc_rpc::SubscriptionTaskExecutor::new(spawn_handle); let subscriptions = SubscriptionManager::new(Arc::new(task_executor.clone())); - let (chain, state, child_state) = - if let (Some(remote_blockchain), Some(on_demand)) = (remote_blockchain, on_demand) { - // Light clients - let chain = sc_rpc::chain::new_light( - client.clone(), - subscriptions.clone(), - remote_blockchain.clone(), - on_demand.clone(), - ); - let (state, child_state) = sc_rpc::state::new_light( - client.clone(), - subscriptions.clone(), - remote_blockchain.clone(), - on_demand, - deny_unsafe, - ); - (chain, state, child_state) - } else { - // Full nodes - let chain = sc_rpc::chain::new_full(client.clone(), subscriptions.clone()); - let (state, child_state) = sc_rpc::state::new_full( - client.clone(), - subscriptions.clone(), - deny_unsafe, - config.rpc_max_payload, - ); - (chain, state, child_state) - }; + let (chain, state, child_state) = { + // Full nodes + let chain = sc_rpc::chain::new_full(client.clone(), subscriptions.clone()); + let (state, child_state) = sc_rpc::state::new_full( + client.clone(), + subscriptions.clone(), + deny_unsafe, + config.rpc_max_payload, + ); + (chain, state, child_state) + }; let author = sc_rpc::author::Author::new(client, transaction_pool, subscriptions, keystore, deny_unsafe); diff --git a/client/service/src/client/client.rs b/client/service/src/client/client.rs index d35c0462b8b0..4e3cb0aaf234 100644 --- a/client/service/src/client/client.rs +++ b/client/service/src/client/client.rs @@ -42,6 +42,7 @@ use sc_client_api::{ ProvideUncles, }, execution_extensions::ExecutionExtensions, + light::ChangesProof, notifications::{StorageEventStream, StorageNotifications}, CallExecutor, ExecutorProvider, KeyIterator, ProofProvider, UsageProvider, }; @@ -49,7 +50,6 @@ use sc_consensus::{ BlockCheckParams, BlockImportParams, ForkChoiceStrategy, ImportResult, StateAction, }; use sc_executor::RuntimeVersion; -use sc_light::fetcher::ChangesProof; use sc_telemetry::{telemetry, TelemetryHandle, SUBSTRATE_INFO}; use sp_api::{ ApiExt, ApiRef, CallApiAt, CallApiAtParams, ConstructRuntimeApi, Core as CoreApi, diff --git a/client/service/src/client/light.rs b/client/service/src/client/light.rs deleted file mode 100644 index 7c13b98843e0..000000000000 --- a/client/service/src/client/light.rs +++ /dev/null @@ -1,82 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2017-2021 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 . - -//! Light client utilities. - -use std::sync::Arc; - -use prometheus_endpoint::Registry; -use sc_executor::RuntimeVersionOf; -use sc_telemetry::TelemetryHandle; -use sp_blockchain::Result as ClientResult; -use sp_core::traits::{CodeExecutor, SpawnNamed}; -use sp_runtime::{ - traits::{Block as BlockT, HashFor}, - BuildStorage, -}; - -use super::{ - call_executor::LocalCallExecutor, - client::{Client, ClientConfig}, -}; -use sc_client_api::light::Storage as BlockchainStorage; -use sc_light::{Backend, GenesisCallExecutor}; - -/// Create an instance of light client. -pub fn new_light( - backend: Arc>>, - genesis_storage: &dyn BuildStorage, - code_executor: E, - spawn_handle: Box, - prometheus_registry: Option, - telemetry: Option, -) -> ClientResult< - Client< - Backend>, - GenesisCallExecutor< - Backend>, - LocalCallExecutor>, E>, - >, - B, - RA, - >, -> -where - B: BlockT, - S: BlockchainStorage + 'static, - E: CodeExecutor + RuntimeVersionOf + Clone + 'static, -{ - let local_executor = LocalCallExecutor::new( - backend.clone(), - code_executor, - spawn_handle.clone(), - ClientConfig::default(), - )?; - let executor = GenesisCallExecutor::new(backend.clone(), local_executor); - Client::new( - backend, - executor, - genesis_storage, - Default::default(), - Default::default(), - Default::default(), - prometheus_registry, - telemetry, - ClientConfig::default(), - ) -} diff --git a/client/service/src/client/mod.rs b/client/service/src/client/mod.rs index 754309e864eb..7743f479a171 100644 --- a/client/service/src/client/mod.rs +++ b/client/service/src/client/mod.rs @@ -49,7 +49,6 @@ mod block_rules; mod call_executor; mod client; pub mod genesis; -pub mod light; mod wasm_override; mod wasm_substitutes; diff --git a/client/service/src/lib.rs b/client/service/src/lib.rs index 8d8c54cc25f2..a1ff8da4085c 100644 --- a/client/service/src/lib.rs +++ b/client/service/src/lib.rs @@ -49,10 +49,9 @@ use sp_runtime::{ pub use self::{ builder::{ build_network, build_offchain_workers, new_client, new_db_backend, new_full_client, - new_full_parts, new_light_parts, spawn_tasks, BuildNetworkParams, KeystoreContainer, - NetworkStarter, NoopRpcExtensionBuilder, RpcExtensionBuilder, SpawnTasksParams, - TFullBackend, TFullCallExecutor, TFullClient, TLightBackend, TLightBackendWithHash, - TLightCallExecutor, TLightClient, TLightClientWithBackend, + new_full_parts, spawn_tasks, BuildNetworkParams, KeystoreContainer, NetworkStarter, + NoopRpcExtensionBuilder, RpcExtensionBuilder, SpawnTasksParams, TFullBackend, + TFullCallExecutor, TFullClient, }, client::{ClientConfig, LocalCallExecutor}, error::Error, diff --git a/client/service/test/src/client/db.rs b/client/service/test/src/client/db.rs index 5278c9a13a4d..772fdcada72e 100644 --- a/client/service/test/src/client/db.rs +++ b/client/service/test/src/client/db.rs @@ -21,6 +21,7 @@ use std::sync::Arc; type TestBackend = sc_client_api::in_mem::Backend; + #[test] fn test_leaves_with_complex_block_tree() { let backend = Arc::new(TestBackend::new()); diff --git a/client/service/test/src/client/light.rs b/client/service/test/src/client/light.rs deleted file mode 100644 index fb9566d208f7..000000000000 --- a/client/service/test/src/client/light.rs +++ /dev/null @@ -1,981 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2018-2021 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 . - -use super::prepare_client_with_key_changes; -use parity_scale_codec::{Decode, Encode}; -use parking_lot::Mutex; -use sc_block_builder::BlockBuilderProvider; -use sc_client_api::{ - backend::NewBlockState, - blockchain::Info, - cht, - in_mem::{Backend as InMemBackend, Blockchain as InMemoryBlockchain}, - AuxStore, Backend as ClientBackend, BlockBackend, BlockImportOperation, CallExecutor, - ChangesProof, ExecutionStrategy, FetchChecker, ProofProvider, ProvideChtRoots, - RemoteBodyRequest, RemoteCallRequest, RemoteChangesRequest, RemoteHeaderRequest, - RemoteReadChildRequest, RemoteReadRequest, Storage, StorageProof, StorageProvider, -}; -use sc_executor::{NativeElseWasmExecutor, RuntimeVersion, WasmExecutionMethod}; -use sc_light::{ - backend::{Backend, GenesisOrUnavailableState}, - blockchain::{Blockchain, BlockchainCache}, - call_executor::{check_execution_proof, GenesisCallExecutor}, - fetcher::LightDataChecker, -}; -use sp_api::{ProofRecorder, StorageTransactionCache}; -use sp_blockchain::{ - well_known_cache_keys, BlockStatus, CachedHeaderMetadata, Error as ClientError, HeaderBackend, - Result as ClientResult, -}; -use sp_consensus::BlockOrigin; -use sp_core::{testing::TaskExecutor, NativeOrEncoded, H256}; -use sp_externalities::Extensions; -use sp_runtime::{ - generic::BlockId, - traits::{BlakeTwo256, Block as _, Header as HeaderT, NumberFor}, - Digest, Justifications, -}; -use sp_state_machine::{ExecutionManager, OverlayedChanges}; -use std::{cell::RefCell, collections::HashMap, panic::UnwindSafe, sync::Arc}; -use substrate_test_runtime_client::{ - runtime::{self, Block, Extrinsic, Hash, Header}, - AccountKeyring, ClientBlockImportExt, TestClient, -}; - -use sp_core::{ - blake2_256, - storage::{well_known_keys, ChildInfo, StorageKey}, - ChangesTrieConfiguration, -}; -use sp_state_machine::Backend as _; - -pub type DummyBlockchain = Blockchain; - -pub struct DummyStorage { - pub changes_tries_cht_roots: HashMap, - pub aux_store: Mutex, Vec>>, -} - -impl DummyStorage { - pub fn new() -> Self { - DummyStorage { - changes_tries_cht_roots: HashMap::new(), - aux_store: Mutex::new(HashMap::new()), - } - } -} - -impl sp_blockchain::HeaderBackend for DummyStorage { - fn header(&self, _id: BlockId) -> ClientResult> { - Err(ClientError::Backend("Test error".into())) - } - - fn info(&self) -> Info { - panic!("Test error") - } - - fn status(&self, _id: BlockId) -> ClientResult { - Err(ClientError::Backend("Test error".into())) - } - - fn number(&self, hash: Hash) -> ClientResult>> { - if hash == Default::default() { - Ok(Some(Default::default())) - } else { - Err(ClientError::Backend("Test error".into())) - } - } - - fn hash(&self, number: u64) -> ClientResult> { - if number == 0 { - Ok(Some(Default::default())) - } else { - Err(ClientError::Backend("Test error".into())) - } - } -} - -impl sp_blockchain::HeaderMetadata for DummyStorage { - type Error = ClientError; - - fn header_metadata(&self, hash: Hash) -> Result, Self::Error> { - self.header(BlockId::hash(hash))? - .map(|header| CachedHeaderMetadata::from(&header)) - .ok_or(ClientError::UnknownBlock("header not found".to_owned())) - } - fn insert_header_metadata(&self, _hash: Hash, _metadata: CachedHeaderMetadata) {} - fn remove_header_metadata(&self, _hash: Hash) {} -} - -impl AuxStore for DummyStorage { - fn insert_aux< - 'a, - 'b: 'a, - 'c: 'a, - I: IntoIterator, - D: IntoIterator, - >( - &self, - insert: I, - _delete: D, - ) -> ClientResult<()> { - for (k, v) in insert.into_iter() { - self.aux_store.lock().insert(k.to_vec(), v.to_vec()); - } - Ok(()) - } - - fn get_aux(&self, key: &[u8]) -> ClientResult>> { - Ok(self.aux_store.lock().get(key).cloned()) - } -} - -impl Storage for DummyStorage { - fn import_header( - &self, - _header: Header, - _cache: HashMap>, - _state: NewBlockState, - _aux_ops: Vec<(Vec, Option>)>, - ) -> ClientResult<()> { - Ok(()) - } - - fn set_head(&self, _block: BlockId) -> ClientResult<()> { - Err(ClientError::Backend("Test error".into())) - } - - fn finalize_header(&self, _block: BlockId) -> ClientResult<()> { - Err(ClientError::Backend("Test error".into())) - } - - fn last_finalized(&self) -> ClientResult { - Err(ClientError::Backend("Test error".into())) - } - - fn cache(&self) -> Option>> { - None - } - - fn usage_info(&self) -> Option { - None - } -} - -impl ProvideChtRoots for DummyStorage { - fn header_cht_root(&self, _cht_size: u64, _block: u64) -> ClientResult> { - Err(ClientError::Backend("Test error".into())) - } - - fn changes_trie_cht_root(&self, cht_size: u64, block: u64) -> ClientResult> { - cht::block_to_cht_number(cht_size, block) - .and_then(|cht_num| self.changes_tries_cht_roots.get(&cht_num)) - .cloned() - .ok_or_else(|| { - ClientError::Backend(format!("Test error: CHT for block #{} not found", block)) - .into() - }) - .map(Some) - } -} - -struct DummyCallExecutor; - -impl CallExecutor for DummyCallExecutor { - type Error = ClientError; - - type Backend = substrate_test_runtime_client::Backend; - - fn call( - &self, - _id: &BlockId, - _method: &str, - _call_data: &[u8], - _strategy: ExecutionStrategy, - _extensions: Option, - ) -> Result, ClientError> { - Ok(vec![42]) - } - - fn contextual_call< - EM: Fn( - Result, Self::Error>, - Result, Self::Error>, - ) -> Result, Self::Error>, - R: Encode + Decode + PartialEq, - NC: FnOnce() -> Result + UnwindSafe, - >( - &self, - _at: &BlockId, - _method: &str, - _call_data: &[u8], - _changes: &RefCell, - _storage_transaction_cache: Option< - &RefCell< - StorageTransactionCache< - Block, - >::State, - >, - >, - >, - _execution_manager: ExecutionManager, - _native_call: Option, - _proof_recorder: &Option>, - _extensions: Option, - ) -> ClientResult> - where - ExecutionManager: Clone, - { - unreachable!() - } - - fn runtime_version(&self, _id: &BlockId) -> Result { - unreachable!() - } - - fn prove_execution( - &self, - _: &BlockId, - _: &str, - _: &[u8], - ) -> Result<(Vec, StorageProof), ClientError> { - unreachable!() - } -} - -fn local_executor() -> NativeElseWasmExecutor -{ - NativeElseWasmExecutor::new(WasmExecutionMethod::Interpreted, None, 8) -} - -#[test] -fn local_state_is_created_when_genesis_state_is_available() { - let def = Default::default(); - let header0 = - substrate_test_runtime_client::runtime::Header::new(0, def, def, def, Default::default()); - - let backend: Backend<_, BlakeTwo256> = - Backend::new(Arc::new(DummyBlockchain::new(DummyStorage::new()))); - let mut op = backend.begin_operation().unwrap(); - op.set_block_data(header0, None, None, None, NewBlockState::Final).unwrap(); - op.set_genesis_state(Default::default(), true).unwrap(); - backend.commit_operation(op).unwrap(); - - match backend.state_at(BlockId::Number(0)).unwrap() { - GenesisOrUnavailableState::Genesis(_) => (), - _ => panic!("unexpected state"), - } -} - -#[test] -fn unavailable_state_is_created_when_genesis_state_is_unavailable() { - let backend: Backend<_, BlakeTwo256> = - Backend::new(Arc::new(DummyBlockchain::new(DummyStorage::new()))); - - match backend.state_at(BlockId::Number(0)).unwrap() { - GenesisOrUnavailableState::Unavailable => (), - _ => panic!("unexpected state"), - } -} - -#[test] -fn light_aux_store_is_updated_via_non_importing_op() { - let backend = Backend::new(Arc::new(DummyBlockchain::new(DummyStorage::new()))); - let mut op = ClientBackend::::begin_operation(&backend).unwrap(); - BlockImportOperation::::insert_aux(&mut op, vec![(vec![1], Some(vec![2]))]).unwrap(); - ClientBackend::::commit_operation(&backend, op).unwrap(); - - assert_eq!(AuxStore::get_aux(&backend, &[1]).unwrap(), Some(vec![2])); -} - -#[test] -fn execution_proof_is_generated_and_checked() { - fn execute(remote_client: &TestClient, at: u64, method: &'static str) -> (Vec, Vec) { - let remote_block_id = BlockId::Number(at); - let remote_header = remote_client.header(&remote_block_id).unwrap().unwrap(); - - // 'fetch' execution proof from remote node - let (remote_result, remote_execution_proof) = - remote_client.execution_proof(&remote_block_id, method, &[]).unwrap(); - - // check remote execution proof locally - let local_result = check_execution_proof::<_, _, BlakeTwo256>( - &local_executor(), - Box::new(TaskExecutor::new()), - &RemoteCallRequest { - block: substrate_test_runtime_client::runtime::Hash::default(), - header: remote_header, - method: method.into(), - call_data: vec![], - retry_count: None, - }, - remote_execution_proof, - ) - .unwrap(); - - (remote_result, local_result) - } - - fn execute_with_proof_failure(remote_client: &TestClient, at: u64) { - let remote_block_id = BlockId::Number(at); - let remote_header = remote_client.header(&remote_block_id).unwrap().unwrap(); - - // 'fetch' execution proof from remote node - let (_, remote_execution_proof) = remote_client - .execution_proof( - &remote_block_id, - "Core_initialize_block", - &Header::new( - at, - Default::default(), - Default::default(), - Default::default(), - Default::default(), - ) - .encode(), - ) - .unwrap(); - - // check remote execution proof locally - let execution_result = check_execution_proof::<_, _, BlakeTwo256>( - &local_executor(), - Box::new(TaskExecutor::new()), - &RemoteCallRequest { - block: substrate_test_runtime_client::runtime::Hash::default(), - header: remote_header.clone(), - method: "Core_initialize_block".into(), - call_data: Header::new( - at + 1, - Default::default(), - Default::default(), - remote_header.hash(), - remote_header.digest().clone(), // this makes next header wrong - ) - .encode(), - retry_count: None, - }, - remote_execution_proof, - ); - match execution_result { - Err(sp_blockchain::Error::Execution(_)) => (), - _ => panic!("Unexpected execution result: {:?}", execution_result), - } - } - - // prepare remote client - let mut remote_client = substrate_test_runtime_client::new(); - for i in 1u32..3u32 { - let mut digest = Digest::default(); - digest.push(sp_runtime::generic::DigestItem::Other::(i.to_le_bytes().to_vec())); - futures::executor::block_on(remote_client.import_justified( - BlockOrigin::Own, - remote_client.new_block(digest).unwrap().build().unwrap().block, - Justifications::from((*b"TEST", Default::default())), - )) - .unwrap(); - } - - // check method that doesn't requires environment - let (remote, local) = execute(&remote_client, 0, "Core_version"); - assert_eq!(remote, local); - - let (remote, local) = execute(&remote_client, 2, "Core_version"); - assert_eq!(remote, local); - - // check that proof check doesn't panic even if proof is incorrect AND no panic handler is set - execute_with_proof_failure(&remote_client, 2); - - // check that proof check doesn't panic even if proof is incorrect AND panic handler is set - sp_panic_handler::set("TEST", "1.2.3"); - execute_with_proof_failure(&remote_client, 2); -} - -#[test] -fn code_is_executed_at_genesis_only() { - let backend = Arc::new(InMemBackend::::new()); - let def = H256::default(); - let header0 = - substrate_test_runtime_client::runtime::Header::new(0, def, def, def, Default::default()); - let hash0 = header0.hash(); - let header1 = - substrate_test_runtime_client::runtime::Header::new(1, def, def, hash0, Default::default()); - let hash1 = header1.hash(); - backend - .blockchain() - .insert(hash0, header0, None, None, NewBlockState::Final) - .unwrap(); - backend - .blockchain() - .insert(hash1, header1, None, None, NewBlockState::Final) - .unwrap(); - - let genesis_executor = GenesisCallExecutor::new(backend, DummyCallExecutor); - assert_eq!( - genesis_executor - .call(&BlockId::Number(0), "test_method", &[], ExecutionStrategy::NativeElseWasm, None,) - .unwrap(), - vec![42], - ); - - let call_on_unavailable = genesis_executor.call( - &BlockId::Number(1), - "test_method", - &[], - ExecutionStrategy::NativeElseWasm, - None, - ); - - match call_on_unavailable { - Err(ClientError::NotAvailableOnLightClient) => (), - _ => unreachable!("unexpected result: {:?}", call_on_unavailable), - } -} - -type TestChecker = LightDataChecker< - NativeElseWasmExecutor, - Block, - DummyStorage, ->; - -fn prepare_for_read_proof_check() -> (TestChecker, Header, StorageProof, u32) { - // prepare remote client - let remote_client = substrate_test_runtime_client::new(); - let remote_block_id = BlockId::Number(0); - let remote_block_hash = remote_client.block_hash(0).unwrap().unwrap(); - let mut remote_block_header = remote_client.header(&remote_block_id).unwrap().unwrap(); - remote_block_header.state_root = remote_client - .state_at(&remote_block_id) - .unwrap() - .storage_root(::std::iter::empty()) - .0 - .into(); - - // 'fetch' read proof from remote node - let heap_pages = remote_client - .storage(&remote_block_id, &StorageKey(well_known_keys::HEAP_PAGES.to_vec())) - .unwrap() - .and_then(|v| Decode::decode(&mut &v.0[..]).ok()) - .unwrap(); - let remote_read_proof = remote_client - .read_proof(&remote_block_id, &mut std::iter::once(well_known_keys::HEAP_PAGES)) - .unwrap(); - - // check remote read proof locally - let local_storage = InMemoryBlockchain::::new(); - local_storage - .insert(remote_block_hash, remote_block_header.clone(), None, None, NewBlockState::Final) - .unwrap(); - let local_checker = LightDataChecker::new( - Arc::new(DummyBlockchain::new(DummyStorage::new())), - local_executor(), - Box::new(TaskExecutor::new()), - ); - (local_checker, remote_block_header, remote_read_proof, heap_pages) -} - -fn prepare_for_read_child_proof_check() -> (TestChecker, Header, StorageProof, Vec) { - use substrate_test_runtime_client::{DefaultTestClientBuilderExt, TestClientBuilderExt}; - let child_info = ChildInfo::new_default(b"child1"); - let child_info = &child_info; - // prepare remote client - let remote_client = substrate_test_runtime_client::TestClientBuilder::new() - .add_extra_child_storage(child_info, b"key1".to_vec(), b"value1".to_vec()) - .build(); - let remote_block_id = BlockId::Number(0); - let remote_block_hash = remote_client.block_hash(0).unwrap().unwrap(); - let mut remote_block_header = remote_client.header(&remote_block_id).unwrap().unwrap(); - remote_block_header.state_root = remote_client - .state_at(&remote_block_id) - .unwrap() - .storage_root(::std::iter::empty()) - .0 - .into(); - - // 'fetch' child read proof from remote node - let child_value = remote_client - .child_storage(&remote_block_id, child_info, &StorageKey(b"key1".to_vec())) - .unwrap() - .unwrap() - .0; - assert_eq!(b"value1"[..], child_value[..]); - let remote_read_proof = remote_client - .read_child_proof(&remote_block_id, child_info, &mut std::iter::once("key1".as_bytes())) - .unwrap(); - - // check locally - let local_storage = InMemoryBlockchain::::new(); - local_storage - .insert(remote_block_hash, remote_block_header.clone(), None, None, NewBlockState::Final) - .unwrap(); - let local_checker = LightDataChecker::new( - Arc::new(DummyBlockchain::new(DummyStorage::new())), - local_executor(), - Box::new(TaskExecutor::new()), - ); - (local_checker, remote_block_header, remote_read_proof, child_value) -} - -fn prepare_for_header_proof_check(insert_cht: bool) -> (TestChecker, Hash, Header, StorageProof) { - // prepare remote client - let mut remote_client = substrate_test_runtime_client::new(); - let mut local_headers_hashes = Vec::new(); - for i in 0..4 { - let block = remote_client.new_block(Default::default()).unwrap().build().unwrap().block; - futures::executor::block_on(remote_client.import(BlockOrigin::Own, block)).unwrap(); - local_headers_hashes.push( - remote_client - .block_hash(i + 1) - .map_err(|_| ClientError::Backend("TestError".into())), - ); - } - - // 'fetch' header proof from remote node - let remote_block_id = BlockId::Number(1); - let (remote_block_header, remote_header_proof) = - remote_client.header_proof_with_cht_size(&remote_block_id, 4).unwrap(); - - // check remote read proof locally - let local_storage = InMemoryBlockchain::::new(); - let local_cht_root = - cht::compute_root::(4, 0, local_headers_hashes).unwrap(); - if insert_cht { - local_storage.insert_cht_root(1, local_cht_root); - } - let local_checker = LightDataChecker::new( - Arc::new(DummyBlockchain::new(DummyStorage::new())), - local_executor(), - Box::new(TaskExecutor::new()), - ); - (local_checker, local_cht_root, remote_block_header, remote_header_proof) -} - -fn header_with_computed_extrinsics_root(extrinsics: Vec) -> Header { - use sp_trie::{trie_types::Layout, TrieConfiguration}; - let iter = extrinsics.iter().map(Encode::encode); - let extrinsics_root = Layout::::ordered_trie_root(iter); - - // only care about `extrinsics_root` - Header::new(0, extrinsics_root, H256::zero(), H256::zero(), Default::default()) -} - -#[test] -fn storage_read_proof_is_generated_and_checked() { - let (local_checker, remote_block_header, remote_read_proof, heap_pages) = - prepare_for_read_proof_check(); - assert_eq!( - (&local_checker as &dyn FetchChecker) - .check_read_proof( - &RemoteReadRequest::
{ - block: remote_block_header.hash(), - header: remote_block_header, - keys: vec![well_known_keys::HEAP_PAGES.to_vec()], - retry_count: None, - }, - remote_read_proof - ) - .unwrap() - .remove(well_known_keys::HEAP_PAGES) - .unwrap() - .unwrap()[0], - heap_pages as u8 - ); -} - -#[test] -fn storage_child_read_proof_is_generated_and_checked() { - let child_info = ChildInfo::new_default(&b"child1"[..]); - let (local_checker, remote_block_header, remote_read_proof, result) = - prepare_for_read_child_proof_check(); - assert_eq!( - (&local_checker as &dyn FetchChecker) - .check_read_child_proof( - &RemoteReadChildRequest::
{ - block: remote_block_header.hash(), - header: remote_block_header, - storage_key: child_info.prefixed_storage_key(), - keys: vec![b"key1".to_vec()], - retry_count: None, - }, - remote_read_proof - ) - .unwrap() - .remove(b"key1".as_ref()) - .unwrap() - .unwrap(), - result - ); -} - -#[test] -fn header_proof_is_generated_and_checked() { - let (local_checker, local_cht_root, remote_block_header, remote_header_proof) = - prepare_for_header_proof_check(true); - assert_eq!( - (&local_checker as &dyn FetchChecker) - .check_header_proof( - &RemoteHeaderRequest::
{ - cht_root: local_cht_root, - block: 1, - retry_count: None, - }, - Some(remote_block_header.clone()), - remote_header_proof - ) - .unwrap(), - remote_block_header - ); -} - -#[test] -fn check_header_proof_fails_if_cht_root_is_invalid() { - let (local_checker, _, mut remote_block_header, remote_header_proof) = - prepare_for_header_proof_check(true); - remote_block_header.number = 100; - assert!((&local_checker as &dyn FetchChecker) - .check_header_proof( - &RemoteHeaderRequest::
{ - cht_root: Default::default(), - block: 1, - retry_count: None, - }, - Some(remote_block_header.clone()), - remote_header_proof - ) - .is_err()); -} - -#[test] -fn check_header_proof_fails_if_invalid_header_provided() { - let (local_checker, local_cht_root, mut remote_block_header, remote_header_proof) = - prepare_for_header_proof_check(true); - remote_block_header.number = 100; - assert!((&local_checker as &dyn FetchChecker) - .check_header_proof( - &RemoteHeaderRequest::
{ - cht_root: local_cht_root, - block: 1, - retry_count: None, - }, - Some(remote_block_header.clone()), - remote_header_proof - ) - .is_err()); -} - -#[test] -fn changes_proof_is_generated_and_checked_when_headers_are_not_pruned() { - let (remote_client, local_roots, test_cases) = prepare_client_with_key_changes(); - let local_checker = TestChecker::new( - Arc::new(DummyBlockchain::new(DummyStorage::new())), - local_executor(), - Box::new(TaskExecutor::new()), - ); - let local_checker = &local_checker as &dyn FetchChecker; - let max = remote_client.chain_info().best_number; - let max_hash = remote_client.chain_info().best_hash; - - for (index, (begin, end, key, expected_result)) in test_cases.into_iter().enumerate() { - let begin_hash = remote_client.block_hash(begin).unwrap().unwrap(); - let end_hash = remote_client.block_hash(end).unwrap().unwrap(); - - // 'fetch' changes proof from remote node - let key = StorageKey(key); - let remote_proof = remote_client - .key_changes_proof(begin_hash, end_hash, begin_hash, max_hash, None, &key) - .unwrap(); - - // check proof on local client - let local_roots_range = local_roots.clone()[(begin - 1) as usize..].to_vec(); - let config = ChangesTrieConfiguration::new(4, 2); - let request = RemoteChangesRequest::
{ - changes_trie_configs: vec![sp_core::ChangesTrieConfigurationRange { - zero: (0, Default::default()), - end: None, - config: Some(config), - }], - first_block: (begin, begin_hash), - last_block: (end, end_hash), - max_block: (max, max_hash), - tries_roots: (begin, begin_hash, local_roots_range), - key: key.0, - storage_key: None, - retry_count: None, - }; - let local_result = local_checker - .check_changes_proof( - &request, - ChangesProof { - max_block: remote_proof.max_block, - proof: remote_proof.proof, - roots: remote_proof.roots, - roots_proof: remote_proof.roots_proof, - }, - ) - .unwrap(); - - // ..and ensure that result is the same as on remote node - if local_result != expected_result { - panic!( - "Failed test {}: local = {:?}, expected = {:?}", - index, local_result, expected_result, - ); - } - } -} - -#[test] -fn changes_proof_is_generated_and_checked_when_headers_are_pruned() { - // we're testing this test case here: - // (1, 4, dave.clone(), vec![(4, 0), (1, 1), (1, 0)]), - let (remote_client, remote_roots, _) = prepare_client_with_key_changes(); - let dave = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Dave.into())).to_vec(); - let dave = StorageKey(dave); - - // 'fetch' changes proof from remote node: - // we're fetching changes for range b1..b4 - // we do not know changes trie roots before b3 (i.e. we only know b3+b4) - // but we have changes trie CHT root for b1...b4 - let b1 = remote_client.block_hash_from_id(&BlockId::Number(1)).unwrap().unwrap(); - let b3 = remote_client.block_hash_from_id(&BlockId::Number(3)).unwrap().unwrap(); - let b4 = remote_client.block_hash_from_id(&BlockId::Number(4)).unwrap().unwrap(); - let remote_proof = remote_client - .key_changes_proof_with_cht_size(b1, b4, b3, b4, None, &dave, 4) - .unwrap(); - - // prepare local checker, having a root of changes trie CHT#0 - let local_cht_root = cht::compute_root::( - 4, - 0, - remote_roots.iter().cloned().map(|ct| Ok(Some(ct))), - ) - .unwrap(); - let mut local_storage = DummyStorage::new(); - local_storage.changes_tries_cht_roots.insert(0, local_cht_root); - let local_checker = TestChecker::new( - Arc::new(DummyBlockchain::new(local_storage)), - local_executor(), - Box::new(TaskExecutor::new()), - ); - - // check proof on local client - let config = ChangesTrieConfiguration::new(4, 2); - let request = RemoteChangesRequest::
{ - changes_trie_configs: vec![sp_core::ChangesTrieConfigurationRange { - zero: (0, Default::default()), - end: None, - config: Some(config), - }], - first_block: (1, b1), - last_block: (4, b4), - max_block: (4, b4), - tries_roots: (3, b3, vec![remote_roots[2].clone(), remote_roots[3].clone()]), - storage_key: None, - key: dave.0, - retry_count: None, - }; - let local_result = local_checker - .check_changes_proof_with_cht_size( - &request, - ChangesProof { - max_block: remote_proof.max_block, - proof: remote_proof.proof, - roots: remote_proof.roots, - roots_proof: remote_proof.roots_proof, - }, - 4, - ) - .unwrap(); - - assert_eq!(local_result, vec![(4, 0), (1, 1), (1, 0)]); -} - -#[test] -fn check_changes_proof_fails_if_proof_is_wrong() { - let (remote_client, local_roots, test_cases) = prepare_client_with_key_changes(); - let local_checker = TestChecker::new( - Arc::new(DummyBlockchain::new(DummyStorage::new())), - local_executor(), - Box::new(TaskExecutor::new()), - ); - let local_checker = &local_checker as &dyn FetchChecker; - let max = remote_client.chain_info().best_number; - let max_hash = remote_client.chain_info().best_hash; - - let (begin, end, key, _) = test_cases[0].clone(); - let begin_hash = remote_client.block_hash(begin).unwrap().unwrap(); - let end_hash = remote_client.block_hash(end).unwrap().unwrap(); - - // 'fetch' changes proof from remote node - let key = StorageKey(key); - let remote_proof = remote_client - .key_changes_proof(begin_hash, end_hash, begin_hash, max_hash, None, &key) - .unwrap(); - - let local_roots_range = local_roots.clone()[(begin - 1) as usize..].to_vec(); - let config = ChangesTrieConfiguration::new(4, 2); - let request = RemoteChangesRequest::
{ - changes_trie_configs: vec![sp_core::ChangesTrieConfigurationRange { - zero: (0, Default::default()), - end: None, - config: Some(config), - }], - first_block: (begin, begin_hash), - last_block: (end, end_hash), - max_block: (max, max_hash), - tries_roots: (begin, begin_hash, local_roots_range.clone()), - storage_key: None, - key: key.0, - retry_count: None, - }; - - // check proof on local client using max from the future - assert!(local_checker - .check_changes_proof( - &request, - ChangesProof { - max_block: remote_proof.max_block + 1, - proof: remote_proof.proof.clone(), - roots: remote_proof.roots.clone(), - roots_proof: remote_proof.roots_proof.clone(), - } - ) - .is_err()); - - // check proof on local client using broken proof - assert!(local_checker - .check_changes_proof( - &request, - ChangesProof { - max_block: remote_proof.max_block, - proof: local_roots_range.clone().into_iter().map(|v| v.as_ref().to_vec()).collect(), - roots: remote_proof.roots, - roots_proof: remote_proof.roots_proof, - } - ) - .is_err()); - - // extra roots proofs are provided - assert!(local_checker - .check_changes_proof( - &request, - ChangesProof { - max_block: remote_proof.max_block, - proof: remote_proof.proof.clone(), - roots: vec![(begin - 1, Default::default())].into_iter().collect(), - roots_proof: StorageProof::empty(), - } - ) - .is_err()); - assert!(local_checker - .check_changes_proof( - &request, - ChangesProof { - max_block: remote_proof.max_block, - proof: remote_proof.proof.clone(), - roots: vec![(end + 1, Default::default())].into_iter().collect(), - roots_proof: StorageProof::empty(), - } - ) - .is_err()); -} - -#[test] -fn check_changes_tries_proof_fails_if_proof_is_wrong() { - // we're testing this test case here: - // (1, 4, dave.clone(), vec![(4, 0), (1, 1), (1, 0)]), - let (remote_client, remote_roots, _) = prepare_client_with_key_changes(); - let local_cht_root = cht::compute_root::( - 4, - 0, - remote_roots.iter().cloned().map(|ct| Ok(Some(ct))), - ) - .unwrap(); - let dave = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Dave.into())).to_vec(); - let dave = StorageKey(dave); - - // 'fetch' changes proof from remote node: - // we're fetching changes for range b1..b4 - // we do not know changes trie roots before b3 (i.e. we only know b3+b4) - // but we have changes trie CHT root for b1...b4 - let b1 = remote_client.block_hash_from_id(&BlockId::Number(1)).unwrap().unwrap(); - let b3 = remote_client.block_hash_from_id(&BlockId::Number(3)).unwrap().unwrap(); - let b4 = remote_client.block_hash_from_id(&BlockId::Number(4)).unwrap().unwrap(); - let remote_proof = remote_client - .key_changes_proof_with_cht_size(b1, b4, b3, b4, None, &dave, 4) - .unwrap(); - - // fails when changes trie CHT is missing from the local db - let local_checker = TestChecker::new( - Arc::new(DummyBlockchain::new(DummyStorage::new())), - local_executor(), - Box::new(TaskExecutor::new()), - ); - assert!(local_checker - .check_changes_tries_proof(4, &remote_proof.roots, remote_proof.roots_proof.clone()) - .is_err()); - - // fails when proof is broken - let mut local_storage = DummyStorage::new(); - local_storage.changes_tries_cht_roots.insert(0, local_cht_root); - let local_checker = TestChecker::new( - Arc::new(DummyBlockchain::new(local_storage)), - local_executor(), - Box::new(TaskExecutor::new()), - ); - let result = - local_checker.check_changes_tries_proof(4, &remote_proof.roots, StorageProof::empty()); - assert!(result.is_err()); -} - -#[test] -fn check_body_proof_faulty() { - let header = - header_with_computed_extrinsics_root(vec![Extrinsic::IncludeData(vec![1, 2, 3, 4])]); - let block = Block::new(header.clone(), Vec::new()); - - let local_checker = TestChecker::new( - Arc::new(DummyBlockchain::new(DummyStorage::new())), - local_executor(), - Box::new(TaskExecutor::new()), - ); - - let body_request = RemoteBodyRequest { header: header.clone(), retry_count: None }; - - assert!( - local_checker.check_body_proof(&body_request, block.extrinsics).is_err(), - "vec![1, 2, 3, 4] != vec![]" - ); -} - -#[test] -fn check_body_proof_of_same_data_should_succeed() { - let extrinsics = vec![Extrinsic::IncludeData(vec![1, 2, 3, 4, 5, 6, 7, 8, 255])]; - - let header = header_with_computed_extrinsics_root(extrinsics.clone()); - let block = Block::new(header.clone(), extrinsics); - - let local_checker = TestChecker::new( - Arc::new(DummyBlockchain::new(DummyStorage::new())), - local_executor(), - Box::new(TaskExecutor::new()), - ); - - let body_request = RemoteBodyRequest { header: header.clone(), retry_count: None }; - - assert!(local_checker.check_body_proof(&body_request, block.extrinsics).is_ok()); -} diff --git a/client/service/test/src/client/mod.rs b/client/service/test/src/client/mod.rs index 8ea605c0ea5b..33cbefbb06a9 100644 --- a/client/service/test/src/client/mod.rs +++ b/client/service/test/src/client/mod.rs @@ -57,9 +57,6 @@ use substrate_test_runtime_client::{ Sr25519Keyring, TestClientBuilder, TestClientBuilderExt, }; -mod db; -mod light; - const TEST_ENGINE_ID: ConsensusEngineId = *b"TEST"; pub struct ExecutorDispatch; diff --git a/client/service/test/src/lib.rs b/client/service/test/src/lib.rs index a4e740aabc18..c44a5cdb9743 100644 --- a/client/service/test/src/lib.rs +++ b/client/service/test/src/lib.rs @@ -33,8 +33,9 @@ use sc_service::{ SpawnTaskHandle, TaskManager, TransactionStorageMode, }; use sc_transaction_pool_api::TransactionPool; +use sp_api::BlockId; use sp_blockchain::HeaderBackend; -use sp_runtime::{generic::BlockId, traits::Block as BlockT}; +use sp_runtime::traits::Block as BlockT; use std::{iter, net::Ipv4Addr, pin::Pin, sync::Arc, task::Context, time::Duration}; use tempfile::TempDir; use tokio::{runtime::Runtime, time}; @@ -45,22 +46,20 @@ mod client; /// Maximum duration of single wait call. const MAX_WAIT_TIME: Duration = Duration::from_secs(60 * 3); -struct TestNet { +struct TestNet { runtime: Runtime, authority_nodes: Vec<(usize, F, U, Multiaddr)>, full_nodes: Vec<(usize, F, U, Multiaddr)>, - light_nodes: Vec<(usize, L, Multiaddr)>, chain_spec: GenericChainSpec, base_port: u16, nodes: usize, } -impl Drop for TestNet { +impl Drop for TestNet { fn drop(&mut self) { // Drop the nodes before dropping the runtime, as the runtime otherwise waits for all // futures to be ended and we run into a dead lock. self.full_nodes.drain(..); - self.light_nodes.drain(..); self.authority_nodes.drain(..); } } @@ -156,39 +155,26 @@ where } } -impl TestNet +impl TestNet where F: Clone + Send + 'static, - L: Clone + Send + 'static, U: Clone + Send + 'static, { - pub fn run_until_all_full(&mut self, full_predicate: FP, light_predicate: LP) + pub fn run_until_all_full(&mut self, full_predicate: FP) where FP: Send + Fn(usize, &F) -> bool + 'static, - LP: Send + Fn(usize, &L) -> bool + 'static, { let full_nodes = self.full_nodes.clone(); - let light_nodes = self.light_nodes.clone(); let future = async move { let mut interval = time::interval(Duration::from_millis(100)); - loop { interval.tick().await; - let full_ready = full_nodes + if full_nodes .iter() - .all(|&(ref id, ref service, _, _)| full_predicate(*id, service)); - - if !full_ready { - continue - } - - let light_ready = light_nodes - .iter() - .all(|&(ref id, ref service, _)| light_predicate(*id, service)); - - if light_ready { - return + .all(|&(ref id, ref service, _, _)| full_predicate(*id, service)) + { + break } } }; @@ -278,10 +264,9 @@ fn node_config< } } -impl TestNet +impl TestNet where F: TestNetNode, - L: TestNetNode, E: ChainSpecExtension + Clone + 'static + Send + Sync, G: RuntimeGenesis + 'static, { @@ -289,10 +274,9 @@ where temp: &TempDir, spec: GenericChainSpec, full: impl Iterator Result<(F, U), Error>>, - light: impl Iterator Result>, authorities: impl Iterator Result<(F, U), Error>)>, base_port: u16, - ) -> TestNet { + ) -> TestNet { sp_tracing::try_init_simple(); fdlimit::raise_fd_limit(); let runtime = Runtime::new().expect("Error creating tokio runtime"); @@ -300,12 +284,11 @@ where runtime, authority_nodes: Default::default(), full_nodes: Default::default(), - light_nodes: Default::default(), chain_spec: spec, base_port, nodes: 0, }; - net.insert_nodes(temp, full, light, authorities); + net.insert_nodes(temp, full, authorities); net } @@ -313,7 +296,6 @@ where &mut self, temp: &TempDir, full: impl Iterator Result<(F, U), Error>>, - light: impl Iterator Result>, authorities: impl Iterator Result<(F, U), Error>)>, ) { let handle = self.runtime.handle().clone(); @@ -358,26 +340,6 @@ where self.full_nodes.push((self.nodes, service, user_data, addr)); self.nodes += 1; } - - for light in light { - let node_config = node_config( - self.nodes, - &self.chain_spec, - Role::Light, - handle.clone(), - None, - self.base_port, - &temp, - ); - let addr = node_config.network.listen_addresses.iter().next().unwrap().clone(); - let service = light(node_config).expect("Error creating test node service"); - - handle.spawn(service.clone().map_err(|_| ())); - let addr = addr - .with(multiaddr::Protocol::P2p(service.network().local_peer_id().clone().into())); - self.light_nodes.push((self.nodes, service, addr)); - self.nodes += 1; - } } } @@ -388,23 +350,16 @@ fn tempdir_with_prefix(prefix: &str) -> TempDir { .expect("Error creating test dir") } -pub fn connectivity( - spec: GenericChainSpec, - full_builder: Fb, - light_builder: Lb, -) where +pub fn connectivity(spec: GenericChainSpec, full_builder: Fb) +where E: ChainSpecExtension + Clone + 'static + Send + Sync, G: RuntimeGenesis + 'static, Fb: Fn(Configuration) -> Result, F: TestNetNode, - Lb: Fn(Configuration) -> Result, - L: TestNetNode, { const NUM_FULL_NODES: usize = 5; - const NUM_LIGHT_NODES: usize = 5; - let expected_full_connections = NUM_FULL_NODES - 1 + NUM_LIGHT_NODES; - let expected_light_connections = NUM_FULL_NODES; + let expected_full_connections = NUM_FULL_NODES - 1; { let temp = tempdir_with_prefix("substrate-connectivity-test"); @@ -413,7 +368,6 @@ pub fn connectivity( &temp, spec.clone(), (0..NUM_FULL_NODES).map(|_| |cfg| full_builder(cfg).map(|s| (s, ()))), - (0..NUM_LIGHT_NODES).map(|_| |cfg| light_builder(cfg)), // Note: this iterator is empty but we can't just use `iter::empty()`, otherwise // the type of the closure cannot be inferred. (0..0).map(|_| (String::new(), { |cfg| full_builder(cfg).map(|s| (s, ())) })), @@ -427,25 +381,12 @@ pub fn connectivity( .add_reserved_peer(first_address.to_string()) .expect("Error adding reserved peer"); } - for (_, service, _) in network.light_nodes.iter() { - service - .network() - .add_reserved_peer(first_address.to_string()) - .expect("Error adding reserved peer"); - } - network.run_until_all_full( - move |_index, service| { - let connected = service.network().num_connected(); - debug!("Got {}/{} full connections...", connected, expected_full_connections); - connected == expected_full_connections - }, - move |_index, service| { - let connected = service.network().num_connected(); - debug!("Got {}/{} light connections...", connected, expected_light_connections); - connected == expected_light_connections - }, - ); + network.run_until_all_full(move |_index, service| { + let connected = service.network().num_connected(); + debug!("Got {}/{} full connections...", connected, expected_full_connections); + connected == expected_full_connections + }); }; temp.close().expect("Error removing temp dir"); @@ -457,7 +398,6 @@ pub fn connectivity( &temp, spec, (0..NUM_FULL_NODES).map(|_| |cfg| full_builder(cfg).map(|s| (s, ()))), - (0..NUM_LIGHT_NODES).map(|_| |cfg| light_builder(cfg)), // Note: this iterator is empty but we can't just use `iter::empty()`, otherwise // the type of the closure cannot be inferred. (0..0).map(|_| (String::new(), { |cfg| full_builder(cfg).map(|s| (s, ())) })), @@ -465,8 +405,7 @@ pub fn connectivity( ); info!("Checking linked topology"); let mut address = network.full_nodes[0].3.clone(); - let max_nodes = std::cmp::max(NUM_FULL_NODES, NUM_LIGHT_NODES); - for i in 0..max_nodes { + for i in 0..NUM_FULL_NODES { if i != 0 { if let Some((_, service, _, node_id)) = network.full_nodes.get(i) { service @@ -476,44 +415,26 @@ pub fn connectivity( address = node_id.clone(); } } - - if let Some((_, service, node_id)) = network.light_nodes.get(i) { - service - .network() - .add_reserved_peer(address.to_string()) - .expect("Error adding reserved peer"); - address = node_id.clone(); - } } - network.run_until_all_full( - move |_index, service| { - let connected = service.network().num_connected(); - debug!("Got {}/{} full connections...", connected, expected_full_connections); - connected == expected_full_connections - }, - move |_index, service| { - let connected = service.network().num_connected(); - debug!("Got {}/{} light connections...", connected, expected_light_connections); - connected == expected_light_connections - }, - ); + network.run_until_all_full(move |_index, service| { + let connected = service.network().num_connected(); + debug!("Got {}/{} full connections...", connected, expected_full_connections); + connected == expected_full_connections + }); } temp.close().expect("Error removing temp dir"); } } -pub fn sync( +pub fn sync( spec: GenericChainSpec, full_builder: Fb, - light_builder: Lb, mut make_block_and_import: B, mut extrinsic_factory: ExF, ) where Fb: Fn(Configuration) -> Result<(F, U), Error>, F: TestNetNode, - Lb: Fn(Configuration) -> Result, - L: TestNetNode, B: FnMut(&F, &mut U), ExF: FnMut(&F, &U) -> ::Extrinsic, U: Clone + Send + 'static, @@ -521,15 +442,12 @@ pub fn sync( G: RuntimeGenesis + 'static, { const NUM_FULL_NODES: usize = 10; - // FIXME: BABE light client support is currently not working. - const NUM_LIGHT_NODES: usize = 10; const NUM_BLOCKS: usize = 512; let temp = tempdir_with_prefix("substrate-sync-test"); let mut network = TestNet::new( &temp, spec, (0..NUM_FULL_NODES).map(|_| |cfg| full_builder(cfg)), - (0..NUM_LIGHT_NODES).map(|_| |cfg| light_builder(cfg)), // Note: this iterator is empty but we can't just use `iter::empty()`, otherwise // the type of the closure cannot be inferred. (0..0).map(|_| (String::new(), { |cfg| full_builder(cfg) })), @@ -560,16 +478,10 @@ pub fn sync( .add_reserved_peer(first_address.to_string()) .expect("Error adding reserved peer"); } - for (_, service, _) in network.light_nodes.iter() { - service - .network() - .add_reserved_peer(first_address.to_string()) - .expect("Error adding reserved peer"); - } - network.run_until_all_full( - |_index, service| service.client().info().best_number == (NUM_BLOCKS as u32).into(), - |_index, service| service.client().info().best_number == (NUM_BLOCKS as u32).into(), - ); + + network.run_until_all_full(|_index, service| { + service.client().info().best_number == (NUM_BLOCKS as u32).into() + }); info!("Checking extrinsic propagation"); let first_service = network.full_nodes[0].1.clone(); @@ -585,34 +497,26 @@ pub fn sync( )) .expect("failed to submit extrinsic"); - network.run_until_all_full( - |_index, service| service.transaction_pool().ready().count() == 1, - |_index, _service| true, - ); + network.run_until_all_full(|_index, service| service.transaction_pool().ready().count() == 1); } -pub fn consensus( +pub fn consensus( spec: GenericChainSpec, full_builder: Fb, - light_builder: Lb, authorities: impl IntoIterator, ) where Fb: Fn(Configuration) -> Result, F: TestNetNode, - Lb: Fn(Configuration) -> Result, - L: TestNetNode, E: ChainSpecExtension + Clone + 'static + Send + Sync, G: RuntimeGenesis + 'static, { const NUM_FULL_NODES: usize = 10; - const NUM_LIGHT_NODES: usize = 10; const NUM_BLOCKS: usize = 10; // 10 * 2 sec block production time = ~20 seconds let temp = tempdir_with_prefix("substrate-consensus-test"); let mut network = TestNet::new( &temp, spec, (0..NUM_FULL_NODES / 2).map(|_| |cfg| full_builder(cfg).map(|s| (s, ()))), - (0..NUM_LIGHT_NODES / 2).map(|_| |cfg| light_builder(cfg)), authorities .into_iter() .map(|key| (key, { |cfg| full_builder(cfg).map(|s| (s, ())) })), @@ -627,30 +531,20 @@ pub fn consensus( .add_reserved_peer(first_address.to_string()) .expect("Error adding reserved peer"); } - for (_, service, _) in network.light_nodes.iter() { - service - .network() - .add_reserved_peer(first_address.to_string()) - .expect("Error adding reserved peer"); - } for (_, service, _, _) in network.authority_nodes.iter().skip(1) { service .network() .add_reserved_peer(first_address.to_string()) .expect("Error adding reserved peer"); } - network.run_until_all_full( - |_index, service| { - service.client().info().finalized_number >= (NUM_BLOCKS as u32 / 2).into() - }, - |_index, service| service.client().info().best_number >= (NUM_BLOCKS as u32 / 2).into(), - ); + network.run_until_all_full(|_index, service| { + service.client().info().finalized_number >= (NUM_BLOCKS as u32 / 2).into() + }); info!("Adding more peers"); network.insert_nodes( &temp, (0..NUM_FULL_NODES / 2).map(|_| |cfg| full_builder(cfg).map(|s| (s, ()))), - (0..NUM_LIGHT_NODES / 2).map(|_| |cfg| light_builder(cfg)), // Note: this iterator is empty but we can't just use `iter::empty()`, otherwise // the type of the closure cannot be inferred. (0..0).map(|_| (String::new(), { |cfg| full_builder(cfg).map(|s| (s, ())) })), @@ -661,14 +555,8 @@ pub fn consensus( .add_reserved_peer(first_address.to_string()) .expect("Error adding reserved peer"); } - for (_, service, _) in network.light_nodes.iter() { - service - .network() - .add_reserved_peer(first_address.to_string()) - .expect("Error adding reserved peer"); - } - network.run_until_all_full( - |_index, service| service.client().info().finalized_number >= (NUM_BLOCKS as u32).into(), - |_index, service| service.client().info().best_number >= (NUM_BLOCKS as u32).into(), - ); + + network.run_until_all_full(|_index, service| { + service.client().info().finalized_number >= (NUM_BLOCKS as u32).into() + }); } From 040ab4027e40fdeb607a31cf4d30eefd10f1aa0f Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Sat, 30 Oct 2021 15:02:09 +0200 Subject: [PATCH 112/695] Add Baseline FRAME Benchmarks (#9691) * create and add baseline * fix import * try a different name * cargo run --quiet --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=frame_benchmarking --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/benchmarking/src/weights.rs --template=./.maintain/frame-weight-template.hbs * cargo run --quiet --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=frame_benchmarking --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/benchmarking/src/weights.rs --template=./.maintain/frame-weight-template.hbs * cargo run --quiet --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=frame_benchmarking --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/benchmarking/src/weights.rs --template=./.maintain/frame-weight-template.hbs * increase repeats * cargo run --quiet --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=frame_benchmarking --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/benchmarking/src/weights.rs --template=./.maintain/frame-weight-template.hbs * Update baseline.rs * Update baseline.rs * cargo run --quiet --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=frame_benchmarking --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/benchmarking/src/weights.rs --template=./.maintain/frame-weight-template.hbs * cargo run --quiet --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=frame_benchmarking --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/benchmarking/src/weights.rs --template=./.maintain/frame-weight-template.hbs * cargo run --quiet --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=frame_benchmarking --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/benchmarking/src/weights.rs --template=./.maintain/frame-weight-template.hbs * cargo run --quiet --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=frame_benchmarking --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/benchmarking/src/weights.rs --template=./.maintain/frame-weight-template.hbs * improve hash benchmark * cargo run --quiet --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=frame_benchmarking --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/benchmarking/src/weights.rs --template=./.maintain/frame-weight-template.hbs * cargo run --quiet --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=frame_benchmarking --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/benchmarking/src/weights.rs --template=./.maintain/frame-weight-template.hbs * cargo run --quiet --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=frame_benchmarking --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/benchmarking/src/weights.rs --template=./.maintain/frame-weight-template.hbs * cargo run --quiet --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=frame_benchmarking --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/benchmarking/src/weights.rs --template=./.maintain/frame-weight-template.hbs Co-authored-by: Parity Bot --- bin/node-template/runtime/src/lib.rs | 10 +- bin/node/runtime/src/lib.rs | 9 +- frame/benchmarking/src/baseline.rs | 173 +++++++++++++++++++++++++++ frame/benchmarking/src/lib.rs | 2 + frame/benchmarking/src/weights.rs | 122 +++++++++++++++++++ 5 files changed, 312 insertions(+), 4 deletions(-) create mode 100644 frame/benchmarking/src/baseline.rs create mode 100644 frame/benchmarking/src/weights.rs diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index 4b49cb48ef35..dbea698002c6 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -463,12 +463,14 @@ impl_runtime_apis! { Vec, Vec, ) { - use frame_benchmarking::{list_benchmark, Benchmarking, BenchmarkList}; + use frame_benchmarking::{list_benchmark, baseline, Benchmarking, BenchmarkList}; use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; + use baseline::Pallet as BaselineBench; let mut list = Vec::::new(); + list_benchmark!(list, extra, frame_benchmarking, BaselineBench::); list_benchmark!(list, extra, frame_system, SystemBench::); list_benchmark!(list, extra, pallet_balances, Balances); list_benchmark!(list, extra, pallet_timestamp, Timestamp); @@ -482,10 +484,13 @@ impl_runtime_apis! { fn dispatch_benchmark( config: frame_benchmarking::BenchmarkConfig ) -> Result, sp_runtime::RuntimeString> { - use frame_benchmarking::{Benchmarking, BenchmarkBatch, add_benchmark, TrackedStorageKey}; + use frame_benchmarking::{baseline, Benchmarking, BenchmarkBatch, add_benchmark, TrackedStorageKey}; use frame_system_benchmarking::Pallet as SystemBench; + use baseline::Pallet as BaselineBench; + impl frame_system_benchmarking::Config for Runtime {} + impl baseline::Config for Runtime {} let whitelist: Vec = vec![ // Block Number @@ -503,6 +508,7 @@ impl_runtime_apis! { let mut batches = Vec::::new(); let params = (&config, &whitelist); + add_benchmark!(params, batches, frame_benchmarking, BaselineBench::); add_benchmark!(params, batches, frame_system, SystemBench::); add_benchmark!(params, batches, pallet_balances, Balances); add_benchmark!(params, batches, pallet_timestamp, Timestamp); diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 0638e62faa36..9154ef6ca53d 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -1609,7 +1609,7 @@ impl_runtime_apis! { Vec, Vec, ) { - use frame_benchmarking::{list_benchmark, Benchmarking, BenchmarkList}; + use frame_benchmarking::{list_benchmark, baseline, Benchmarking, BenchmarkList}; use frame_support::traits::StorageInfoTrait; // Trying to add benchmarks directly to the Session Pallet caused cyclic dependency @@ -1618,9 +1618,11 @@ impl_runtime_apis! { use pallet_session_benchmarking::Pallet as SessionBench; use pallet_offences_benchmarking::Pallet as OffencesBench; use frame_system_benchmarking::Pallet as SystemBench; + use baseline::Pallet as BaselineBench; let mut list = Vec::::new(); + list_benchmark!(list, extra, frame_benchmarking, BaselineBench::); list_benchmark!(list, extra, pallet_assets, Assets); list_benchmark!(list, extra, pallet_babe, Babe); list_benchmark!(list, extra, pallet_bags_list, BagsList); @@ -1662,7 +1664,7 @@ impl_runtime_apis! { fn dispatch_benchmark( config: frame_benchmarking::BenchmarkConfig ) -> Result, sp_runtime::RuntimeString> { - use frame_benchmarking::{Benchmarking, BenchmarkBatch, add_benchmark, TrackedStorageKey}; + use frame_benchmarking::{baseline, Benchmarking, BenchmarkBatch, add_benchmark, TrackedStorageKey}; // Trying to add benchmarks directly to the Session Pallet caused cyclic dependency // issues. To get around that, we separated the Session benchmarks into its own crate, @@ -1670,10 +1672,12 @@ impl_runtime_apis! { use pallet_session_benchmarking::Pallet as SessionBench; use pallet_offences_benchmarking::Pallet as OffencesBench; use frame_system_benchmarking::Pallet as SystemBench; + use baseline::Pallet as BaselineBench; impl pallet_session_benchmarking::Config for Runtime {} impl pallet_offences_benchmarking::Config for Runtime {} impl frame_system_benchmarking::Config for Runtime {} + impl baseline::Config for Runtime {} let whitelist: Vec = vec![ // Block Number @@ -1695,6 +1699,7 @@ impl_runtime_apis! { let mut batches = Vec::::new(); let params = (&config, &whitelist); + add_benchmark!(params, batches, frame_benchmarking, BaselineBench::); add_benchmark!(params, batches, pallet_assets, Assets); add_benchmark!(params, batches, pallet_babe, Babe); add_benchmark!(params, batches, pallet_balances, Balances); diff --git a/frame/benchmarking/src/baseline.rs b/frame/benchmarking/src/baseline.rs new file mode 100644 index 000000000000..a2ffca60c5cf --- /dev/null +++ b/frame/benchmarking/src/baseline.rs @@ -0,0 +1,173 @@ +// This file is part of Substrate. + +// Copyright (C) 2020-2021 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. + +//! A set of benchmarks which can establish a global baseline for all other +//! benchmarking. + +use crate::benchmarks; +use codec::Encode; +use frame_system::Pallet as System; +use sp_runtime::traits::Hash; +use sp_std::prelude::*; + +pub struct Pallet(System); +pub trait Config: frame_system::Config {} + +benchmarks! { + addition { + let i in 0 .. 1_000_000; + let mut start = 0; + }: { + (0..i).for_each(|_| start += 1); + } verify { + assert_eq!(start, i); + } + + subtraction { + let i in 0 .. 1_000_000; + let mut start = u32::MAX; + }: { + (0..i).for_each(|_| start -= 1); + } verify { + assert_eq!(start, u32::MAX - i); + } + + multiplication { + let i in 0 .. 1_000_000; + let mut out = 0; + }: { + (1..=i).for_each(|j| out = 2 * j); + } verify { + assert_eq!(out, 2 * i); + } + + division { + let i in 0 .. 1_000_000; + let mut out = 0; + }: { + (0..=i).for_each(|j| out = j / 2); + } verify { + assert_eq!(out, i / 2); + } + + hashing { + let i in 0 .. 100; + let mut hash = T::Hash::default(); + }: { + (0..=100_000u32).for_each(|j| hash = T::Hashing::hash(&j.to_be_bytes())); + } verify { + assert!(hash != T::Hash::default()); + } + + #[skip_meta] + storage_read { + let i in 0 .. 1_000; + let mut people = Vec::new(); + (0..i).for_each(|j| { + let hash = T::Hashing::hash(&j.to_be_bytes()).encode(); + frame_support::storage::unhashed::put(&hash, &hash); + people.push(hash); + }); + }: { + people.iter().for_each(|hash| { + // This does a storage read + let value = frame_support::storage::unhashed::get(hash); + assert_eq!(value, Some(hash.to_vec())); + }); + } + + #[skip_meta] + storage_write { + let i in 0 .. 1_000; + let mut hashes = Vec::new(); + (0..i).for_each(|j| { + let hash = T::Hashing::hash(&j.to_be_bytes()); + hashes.push(hash.encode()); + }); + }: { + hashes.iter().for_each(|hash| { + // This does a storage write + frame_support::storage::unhashed::put(hash, hash); + }); + } verify { + hashes.iter().for_each(|hash| { + let value = frame_support::storage::unhashed::get(hash); + assert_eq!(value, Some(hash.to_vec())); + }); + } + + impl_benchmark_test_suite!( + Pallet, + crate::baseline::mock::new_test_ext(), + crate::baseline::mock::Test, + ); +} + +#[cfg(test)] +pub mod mock { + use sp_runtime::{testing::H256, traits::IdentityLookup}; + + type AccountId = u64; + type AccountIndex = u32; + type BlockNumber = u64; + + type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; + type Block = frame_system::mocking::MockBlock; + + frame_support::construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + } + ); + + impl frame_system::Config for Test { + type BaseCallFilter = frame_support::traits::Everything; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type Origin = Origin; + type Index = AccountIndex; + type BlockNumber = BlockNumber; + type Call = Call; + type Hash = H256; + type Hashing = ::sp_runtime::traits::BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type Header = sp_runtime::testing::Header; + type Event = Event; + type BlockHashCount = (); + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + } + + impl super::Config for Test {} + + pub fn new_test_ext() -> sp_io::TestExternalities { + let t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + sp_io::TestExternalities::new(t) + } +} diff --git a/frame/benchmarking/src/lib.rs b/frame/benchmarking/src/lib.rs index 1805424426f6..258b40cbe6f0 100644 --- a/frame/benchmarking/src/lib.rs +++ b/frame/benchmarking/src/lib.rs @@ -27,6 +27,8 @@ mod tests; mod tests_instance; mod utils; +pub mod baseline; + #[cfg(feature = "std")] pub use analysis::{Analysis, AnalysisChoice, BenchmarkSelector, RegressionModel}; #[doc(hidden)] diff --git a/frame/benchmarking/src/weights.rs b/frame/benchmarking/src/weights.rs new file mode 100644 index 000000000000..807ff697fdca --- /dev/null +++ b/frame/benchmarking/src/weights.rs @@ -0,0 +1,122 @@ +// This file is part of Substrate. + +// Copyright (C) 2021 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. + +//! Autogenerated weights for frame_benchmarking +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2021-10-30, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 + +// Executed Command: +// target/release/substrate +// benchmark +// --chain=dev +// --steps=50 +// --repeat=20 +// --pallet=frame_benchmarking +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 +// --output=./frame/benchmarking/src/weights.rs +// --template=./.maintain/frame-weight-template.hbs + + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +/// Weight functions needed for frame_benchmarking. +pub trait WeightInfo { + fn addition(i: u32, ) -> Weight; + fn subtraction(i: u32, ) -> Weight; + fn multiplication(i: u32, ) -> Weight; + fn division(i: u32, ) -> Weight; + fn hashing(i: u32, ) -> Weight; + fn storage_read(i: u32, ) -> Weight; + fn storage_write(i: u32, ) -> Weight; +} + +/// Weights for frame_benchmarking using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + fn addition(_i: u32, ) -> Weight { + (337_000 as Weight) + } + fn subtraction(_i: u32, ) -> Weight { + (343_000 as Weight) + } + fn multiplication(_i: u32, ) -> Weight { + (340_000 as Weight) + } + fn division(_i: u32, ) -> Weight { + (346_000 as Weight) + } + fn hashing(_i: u32, ) -> Weight { + (35_449_143_000 as Weight) + } + // Storage: Skipped Metadata (r:0 w:0) + fn storage_read(i: u32, ) -> Weight { + (0 as Weight) + // Standard Error: 3_000 + .saturating_add((2_851_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) + } + // Storage: Skipped Metadata (r:0 w:0) + fn storage_write(i: u32, ) -> Weight { + (0 as Weight) + // Standard Error: 0 + .saturating_add((662_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(i as Weight))) + } +} + +// For backwards compatibility and tests +impl WeightInfo for () { + fn addition(_i: u32, ) -> Weight { + (337_000 as Weight) + } + fn subtraction(_i: u32, ) -> Weight { + (343_000 as Weight) + } + fn multiplication(_i: u32, ) -> Weight { + (340_000 as Weight) + } + fn division(_i: u32, ) -> Weight { + (346_000 as Weight) + } + fn hashing(_i: u32, ) -> Weight { + (35_449_143_000 as Weight) + } + // Storage: Skipped Metadata (r:0 w:0) + fn storage_read(i: u32, ) -> Weight { + (0 as Weight) + // Standard Error: 3_000 + .saturating_add((2_851_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) + } + // Storage: Skipped Metadata (r:0 w:0) + fn storage_write(i: u32, ) -> Weight { + (0 as Weight) + // Standard Error: 0 + .saturating_add((662_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(i as Weight))) + } +} From e11a670b0310130c329ab32a6e16608f5712113d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Sat, 30 Oct 2021 15:09:56 +0200 Subject: [PATCH 113/695] pallet-utility: Fix possible mismatch between native/wasm (#10121) * pallet-utility: Fix possible mismatch between native/wasm The `batched_calls_limit` constant value includes the `size_of` of the runtime `Call`. As we compile the runtime for native/wasm, we need to align the call size to ensure that it is the same on wasm/native. This also solves the problem of different metadata outputs for the same runtime. * Review feedback --- frame/utility/src/lib.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/frame/utility/src/lib.rs b/frame/utility/src/lib.rs index 54de87c4740c..8712cf74f451 100644 --- a/frame/utility/src/lib.rs +++ b/frame/utility/src/lib.rs @@ -112,12 +112,19 @@ pub mod pallet { ItemCompleted, } + // Align the call size to 1KB. As we are currently compiling the runtime for native/wasm + // the `size_of` of the `Call` can be different. To ensure that this don't leads to + // mismatches between native/wasm or to different metadata for the same runtime, we + // algin the call size. The value is choosen big enough to hopefully never reach it. + const CALL_ALIGN: u32 = 1024; + #[pallet::extra_constants] impl Pallet { /// The limit on the number of batched calls. fn batched_calls_limit() -> u32 { let allocator_limit = sp_core::MAX_POSSIBLE_ALLOCATION; - let call_size = core::mem::size_of::<::Call>() as u32; + let call_size = ((sp_std::mem::size_of::<::Call>() as u32 + CALL_ALIGN - + 1) / CALL_ALIGN) * CALL_ALIGN; // The margin to take into account vec doubling capacity. let margin_factor = 3; @@ -125,6 +132,18 @@ pub mod pallet { } } + #[pallet::hooks] + impl Hooks> for Pallet { + fn integrity_test() { + // If you hit this error, you need to try to `Box` big dispatchable parameters. + assert!( + sp_std::mem::size_of::<::Call>() as u32 <= CALL_ALIGN, + "Call enum size should be smaller than {} bytes.", + CALL_ALIGN, + ); + } + } + #[pallet::error] pub enum Error { /// Too many calls batched. From 794e9a91927dda5ffa6b29b1771ccdde947af7a2 Mon Sep 17 00:00:00 2001 From: Guillaume Thiolliere Date: Sun, 31 Oct 2021 11:36:26 +0100 Subject: [PATCH 114/695] fix query details (#10107) --- frame/transaction-payment/src/lib.rs | 59 ++++++++++++++++++++++++---- 1 file changed, 52 insertions(+), 7 deletions(-) diff --git a/frame/transaction-payment/src/lib.rs b/frame/transaction-payment/src/lib.rs index 28200bee7054..59d94a823723 100644 --- a/frame/transaction-payment/src/lib.rs +++ b/frame/transaction-payment/src/lib.rs @@ -403,7 +403,7 @@ where /// /// All dispatchables must be annotated with weight and will have some fee info. This function /// always returns. - pub fn query_info( + pub fn query_info( unchecked_extrinsic: Extrinsic, len: u32, ) -> RuntimeDispatchInfo> @@ -417,14 +417,20 @@ where // a very very little potential gain in the future. let dispatch_info = ::get_dispatch_info(&unchecked_extrinsic); - let partial_fee = Self::compute_fee(len, &dispatch_info, 0u32.into()); + let partial_fee = if unchecked_extrinsic.is_signed().unwrap_or(false) { + Self::compute_fee(len, &dispatch_info, 0u32.into()) + } else { + // Unsigned extrinsics have no partial fee. + 0u32.into() + }; + let DispatchInfo { weight, class, .. } = dispatch_info; RuntimeDispatchInfo { weight, class, partial_fee } } /// Query the detailed fee of a given `call`. - pub fn query_fee_details( + pub fn query_fee_details( unchecked_extrinsic: Extrinsic, len: u32, ) -> FeeDetails> @@ -432,7 +438,15 @@ where T::Call: Dispatchable, { let dispatch_info = ::get_dispatch_info(&unchecked_extrinsic); - Self::compute_fee_details(len, &dispatch_info, 0u32.into()) + + let tip = 0u32.into(); + + if unchecked_extrinsic.is_signed().unwrap_or(false) { + Self::compute_fee_details(len, &dispatch_info, tip) + } else { + // Unsigned extrinsics have no inclusion fee. + FeeDetails { inclusion_fee: None, tip } + } } /// Compute the final fee value for a particular transaction. @@ -1141,20 +1155,24 @@ mod tests { } #[test] - fn query_info_works() { + fn query_info_and_fee_details_works() { let call = Call::Balances(BalancesCall::transfer { dest: 2, value: 69 }); let origin = 111111; let extra = (); - let xt = TestXt::new(call, Some((origin, extra))); + let xt = TestXt::new(call.clone(), Some((origin, extra))); let info = xt.get_dispatch_info(); let ext = xt.encode(); let len = ext.len() as u32; + + let unsigned_xt = TestXt::<_, ()>::new(call, None); + let unsigned_xt_info = unsigned_xt.get_dispatch_info(); + ExtBuilder::default().base_weight(5).weight_fee(2).build().execute_with(|| { // all fees should be x1.5 >::put(Multiplier::saturating_from_rational(3, 2)); assert_eq!( - TransactionPayment::query_info(xt, len), + TransactionPayment::query_info(xt.clone(), len), RuntimeDispatchInfo { weight: info.weight, class: info.class, @@ -1163,6 +1181,33 @@ mod tests { + info.weight.min(BlockWeights::get().max_block) as u64 * 2 * 3 / 2 /* weight */ }, ); + + assert_eq!( + TransactionPayment::query_info(unsigned_xt.clone(), len), + RuntimeDispatchInfo { + weight: unsigned_xt_info.weight, + class: unsigned_xt_info.class, + partial_fee: 0, + }, + ); + + assert_eq!( + TransactionPayment::query_fee_details(xt, len), + FeeDetails { + inclusion_fee: Some(InclusionFee { + base_fee: 5 * 2, + len_fee: len as u64, + adjusted_weight_fee: info.weight.min(BlockWeights::get().max_block) as u64 * + 2 * 3 / 2 + }), + tip: 0, + }, + ); + + assert_eq!( + TransactionPayment::query_fee_details(unsigned_xt, len), + FeeDetails { inclusion_fee: None, tip: 0 }, + ); }); } From 1f1fc455d17f3640be562fc4639a6b74da71f655 Mon Sep 17 00:00:00 2001 From: Guillaume Thiolliere Date: Sun, 31 Oct 2021 14:55:10 +0100 Subject: [PATCH 115/695] Automatic pallet parts in construct_runtime (#9681) * implement automatic parts * ui tests * rename * remove unnecessary exclude * better doc * better doc * fix genesis config * fix UI tests * fix UI test * Revert "fix UI test" This reverts commit a910351c0b24cfe42195cfd97d83a416640e3259. * implemented used_parts * Update frame/support/procedural/src/construct_runtime/mod.rs Co-authored-by: Keith Yeung * doc + fmt * Update frame/support/procedural/src/construct_runtime/parse.rs Co-authored-by: Keith Yeung * add doc in the macro * remove yet some more parts * fix ui test * more determnistic error message + fix ui tests * fix ui test * Apply suggestions from code review Co-authored-by: Keith Yeung * do refactor + fix ui tests * fmt * fix test * fix test * fix ui test * Apply suggestions from code review Co-authored-by: Keith Yeung * refactor * remove even more part in node-runtime * fix test * Add flow chart for the construct_runtime! execution flow * Fix typo * Ignore snippets that don't contain code * Refactor some code in expand_after * Rename expand_after to match_and_insert * cargo fmt * Fix rename * Remove frame_support argument to construct_runtime_parts * Make use of tt-call to simplify intermediate expansions * cargo fmt * Update match_and_insert documentation * Reset cursor to 0 when no matching patterns are found * Reorder struct fields on MatchAndInsertDef * Add test for dependency renames and fix frame-support import * Add more doc comments * Update frame/support/test/compile_pass/src/lib.rs Co-authored-by: Guillaume Thiolliere Co-authored-by: Keith Yeung Co-authored-by: Shawn Tabrizi --- Cargo.lock | 20 + Cargo.toml | 3 +- bin/node/cli/src/chain_spec.rs | 2 + bin/node/runtime/src/lib.rs | 80 ++-- bin/node/testing/src/genesis.rs | 2 + frame/support/Cargo.toml | 1 + .../procedural/src/construct_runtime/mod.rs | 262 +++++++++----- .../procedural/src/construct_runtime/parse.rs | 341 ++++++++++++++++-- frame/support/procedural/src/lib.rs | 128 +++++-- .../procedural/src/match_and_insert.rs | 159 ++++++++ .../procedural/src/pallet/expand/mod.rs | 3 + .../src/pallet/expand/tt_default_parts.rs | 82 +++++ frame/support/src/lib.rs | 4 +- frame/support/test/compile_pass/Cargo.toml | 30 ++ frame/support/test/compile_pass/src/lib.rs | 92 +++++ .../both_use_and_excluded_parts.rs | 33 ++ .../both_use_and_excluded_parts.stderr | 28 ++ .../construct_runtime_ui/duplicate_exclude.rs | 13 + .../duplicate_exclude.stderr | 5 + .../construct_runtime_ui/exclude_missspell.rs | 13 + .../exclude_missspell.stderr | 5 + .../exclude_undefined_part.rs | 38 ++ .../exclude_undefined_part.stderr | 28 ++ .../invalid_module_details.stderr | 6 +- .../invalid_token_after_module.stderr | 2 +- .../old_unsupported_pallet_decl.rs | 26 ++ .../old_unsupported_pallet_decl.stderr | 31 ++ .../use_undefined_part.rs | 38 ++ .../use_undefined_part.stderr | 28 ++ frame/support/test/tests/pallet.rs | 35 +- frame/support/test/tests/pallet_instance.rs | 15 +- 31 files changed, 1335 insertions(+), 218 deletions(-) create mode 100644 frame/support/procedural/src/match_and_insert.rs create mode 100644 frame/support/procedural/src/pallet/expand/tt_default_parts.rs create mode 100644 frame/support/test/compile_pass/Cargo.toml create mode 100644 frame/support/test/compile_pass/src/lib.rs create mode 100644 frame/support/test/tests/construct_runtime_ui/both_use_and_excluded_parts.rs create mode 100644 frame/support/test/tests/construct_runtime_ui/both_use_and_excluded_parts.stderr create mode 100644 frame/support/test/tests/construct_runtime_ui/duplicate_exclude.rs create mode 100644 frame/support/test/tests/construct_runtime_ui/duplicate_exclude.stderr create mode 100644 frame/support/test/tests/construct_runtime_ui/exclude_missspell.rs create mode 100644 frame/support/test/tests/construct_runtime_ui/exclude_missspell.stderr create mode 100644 frame/support/test/tests/construct_runtime_ui/exclude_undefined_part.rs create mode 100644 frame/support/test/tests/construct_runtime_ui/exclude_undefined_part.stderr create mode 100644 frame/support/test/tests/construct_runtime_ui/old_unsupported_pallet_decl.rs create mode 100644 frame/support/test/tests/construct_runtime_ui/old_unsupported_pallet_decl.stderr create mode 100644 frame/support/test/tests/construct_runtime_ui/use_undefined_part.rs create mode 100644 frame/support/test/tests/construct_runtime_ui/use_undefined_part.stderr diff --git a/Cargo.lock b/Cargo.lock index c3cfaec19532..84ad0c0a563c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2058,6 +2058,7 @@ dependencies = [ "sp-state-machine", "sp-std", "sp-tracing", + "tt-call", ] [[package]] @@ -2113,6 +2114,19 @@ dependencies = [ "trybuild", ] +[[package]] +name = "frame-support-test-compile-pass" +version = "4.0.0-dev" +dependencies = [ + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-runtime", + "sp-version", +] + [[package]] name = "frame-support-test-pallet" version = "4.0.0-dev" @@ -10803,6 +10817,12 @@ dependencies = [ "toml", ] +[[package]] +name = "tt-call" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e66dcbec4290c69dd03c57e76c2469ea5c7ce109c6dd4351c13055cf71ea055" + [[package]] name = "twox-hash" version = "1.6.1" diff --git a/Cargo.toml b/Cargo.toml index 71473a4bc568..4a228203159e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -120,6 +120,7 @@ members = [ "frame/support/procedural/tools", "frame/support/procedural/tools/derive", "frame/support/test", + "frame/support/test/compile_pass", "frame/system", "frame/system/benchmarking", "frame/system/rpc/runtime-api", @@ -271,4 +272,4 @@ yamux = { opt-level = 3 } zeroize = { opt-level = 3 } [profile.release] # Substrate runtime requires unwinding. -panic = "unwind" \ No newline at end of file +panic = "unwind" diff --git a/bin/node/cli/src/chain_spec.rs b/bin/node/cli/src/chain_spec.rs index 8499c66e0c9d..7b1ed90017c3 100644 --- a/bin/node/cli/src/chain_spec.rs +++ b/bin/node/cli/src/chain_spec.rs @@ -364,6 +364,8 @@ pub fn testnet_genesis( assets: Default::default(), gilt: Default::default(), transaction_storage: Default::default(), + scheduler: Default::default(), + transaction_payment: Default::default(), } } diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 9154ef6ca53d..c0ad9bb006c9 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -1248,47 +1248,47 @@ construct_runtime!( NodeBlock = node_primitives::Block, UncheckedExtrinsic = UncheckedExtrinsic { - System: frame_system::{Pallet, Call, Config, Storage, Event}, - Utility: pallet_utility::{Pallet, Call, Event}, - Babe: pallet_babe::{Pallet, Call, Storage, Config, ValidateUnsigned}, - Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, - Authorship: pallet_authorship::{Pallet, Call, Storage, Inherent}, - Indices: pallet_indices::{Pallet, Call, Storage, Config, Event}, - Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, - TransactionPayment: pallet_transaction_payment::{Pallet, Storage}, - ElectionProviderMultiPhase: pallet_election_provider_multi_phase::{Pallet, Call, Storage, Event, ValidateUnsigned}, - Staking: pallet_staking::{Pallet, Call, Config, Storage, Event}, - Session: pallet_session::{Pallet, Call, Storage, Event, Config}, - Democracy: pallet_democracy::{Pallet, Call, Storage, Config, Event}, - Council: pallet_collective::::{Pallet, Call, Storage, Origin, Event, Config}, - TechnicalCommittee: pallet_collective::::{Pallet, Call, Storage, Origin, Event, Config}, - Elections: pallet_elections_phragmen::{Pallet, Call, Storage, Event, Config}, - TechnicalMembership: pallet_membership::::{Pallet, Call, Storage, Event, Config}, - Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event, ValidateUnsigned}, - Treasury: pallet_treasury::{Pallet, Call, Storage, Config, Event}, - Contracts: pallet_contracts::{Pallet, Call, Storage, Event}, - Sudo: pallet_sudo::{Pallet, Call, Config, Storage, Event}, - ImOnline: pallet_im_online::{Pallet, Call, Storage, Event, ValidateUnsigned, Config}, - AuthorityDiscovery: pallet_authority_discovery::{Pallet, Config}, - Offences: pallet_offences::{Pallet, Storage, Event}, + System: frame_system, + Utility: pallet_utility, + Babe: pallet_babe, + Timestamp: pallet_timestamp, + Authorship: pallet_authorship, + Indices: pallet_indices, + Balances: pallet_balances, + TransactionPayment: pallet_transaction_payment, + ElectionProviderMultiPhase: pallet_election_provider_multi_phase, + Staking: pallet_staking, + Session: pallet_session, + Democracy: pallet_democracy, + Council: pallet_collective::, + TechnicalCommittee: pallet_collective::, + Elections: pallet_elections_phragmen, + TechnicalMembership: pallet_membership::, + Grandpa: pallet_grandpa, + Treasury: pallet_treasury, + Contracts: pallet_contracts, + Sudo: pallet_sudo, + ImOnline: pallet_im_online, + AuthorityDiscovery: pallet_authority_discovery, + Offences: pallet_offences, Historical: pallet_session_historical::{Pallet}, - RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage}, - Identity: pallet_identity::{Pallet, Call, Storage, Event}, - Society: pallet_society::{Pallet, Call, Storage, Event, Config}, - Recovery: pallet_recovery::{Pallet, Call, Storage, Event}, - Vesting: pallet_vesting::{Pallet, Call, Storage, Event, Config}, - Scheduler: pallet_scheduler::{Pallet, Call, Storage, Event}, - Proxy: pallet_proxy::{Pallet, Call, Storage, Event}, - Multisig: pallet_multisig::{Pallet, Call, Storage, Event}, - Bounties: pallet_bounties::{Pallet, Call, Storage, Event}, - Tips: pallet_tips::{Pallet, Call, Storage, Event}, - Assets: pallet_assets::{Pallet, Call, Storage, Event, Config}, - Mmr: pallet_mmr::{Pallet, Storage}, - Lottery: pallet_lottery::{Pallet, Call, Storage, Event}, - Gilt: pallet_gilt::{Pallet, Call, Storage, Event, Config}, - Uniques: pallet_uniques::{Pallet, Call, Storage, Event}, - TransactionStorage: pallet_transaction_storage::{Pallet, Call, Storage, Inherent, Config, Event}, - BagsList: pallet_bags_list::{Pallet, Call, Storage, Event}, + RandomnessCollectiveFlip: pallet_randomness_collective_flip, + Identity: pallet_identity, + Society: pallet_society, + Recovery: pallet_recovery, + Vesting: pallet_vesting, + Scheduler: pallet_scheduler, + Proxy: pallet_proxy, + Multisig: pallet_multisig, + Bounties: pallet_bounties, + Tips: pallet_tips, + Assets: pallet_assets, + Mmr: pallet_mmr, + Lottery: pallet_lottery, + Gilt: pallet_gilt, + Uniques: pallet_uniques, + TransactionStorage: pallet_transaction_storage, + BagsList: pallet_bags_list, } ); diff --git a/bin/node/testing/src/genesis.rs b/bin/node/testing/src/genesis.rs index 845227c5acee..80399a6670e8 100644 --- a/bin/node/testing/src/genesis.rs +++ b/bin/node/testing/src/genesis.rs @@ -101,5 +101,7 @@ pub fn config_endowed( assets: Default::default(), gilt: Default::default(), transaction_storage: Default::default(), + scheduler: Default::default(), + transaction_payment: Default::default(), } } diff --git a/frame/support/Cargo.toml b/frame/support/Cargo.toml index edb0ecd6442e..4bc64d8b8e73 100644 --- a/frame/support/Cargo.toml +++ b/frame/support/Cargo.toml @@ -25,6 +25,7 @@ sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primi sp-arithmetic = { version = "4.0.0-dev", default-features = false, path = "../../primitives/arithmetic" } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../primitives/inherents" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" } +tt-call = "1.0.8" frame-support-procedural = { version = "4.0.0-dev", default-features = false, path = "./procedural" } paste = "1.0" once_cell = { version = "1", default-features = false, optional = true } diff --git a/frame/support/procedural/src/construct_runtime/mod.rs b/frame/support/procedural/src/construct_runtime/mod.rs index 863df3426659..4315d4278183 100644 --- a/frame/support/procedural/src/construct_runtime/mod.rs +++ b/frame/support/procedural/src/construct_runtime/mod.rs @@ -15,115 +15,205 @@ // See the License for the specific language governing permissions and // limitations under the License. +//! Implementation of `construct_runtime`. +//! +//! `construct_runtime` implementation is recursive and can generate code which will call itself in +//! order to get all the pallet parts for each pallet. +//! +//! Pallets define their parts (`Call`, `Storage`, ..) either explicitly with the syntax +//! `::{Call, ...}` or implicitly. +//! +//! In case a pallet defines its parts implicitly, then the pallet must provide the +//! `tt_default_parts` macro. `construct_rutime` will generate some code which utilizes `tt_call` +//! to call the `tt_default_parts` macro of the pallet. `tt_default_parts` will then return the +//! default pallet parts as input tokens to the `match_and_replace` macro, which ultimately +//! generates a call to `construct_runtime` again, this time with all the pallet parts explicitly +//! defined. +//! +//! E.g. +//! ```ignore +//! construct_runtime!( +//! //... +//! { +//! System: frame_system = 0, // Implicit definition of parts +//! Balances: pallet_balances = 1, // Implicit definition of parts +//! } +//! ); +//! ``` +//! This call has some implicit pallet parts, thus it will expand to: +//! ```ignore +//! frame_support::tt_call! { +//! macro = [{ pallet_balances::tt_default_parts }] +//! ~~> frame_support::match_and_insert! { +//! target = [{ +//! frame_support::tt_call! { +//! macro = [{ frame_system::tt_default_parts }] +//! ~~> frame_support::match_and_insert! { +//! target = [{ +//! construct_runtime!( +//! //... +//! { +//! System: frame_system = 0, +//! Balances: pallet_balances = 1, +//! } +//! ); +//! }] +//! pattern = [{ System: frame_system }] +//! } +//! } +//! }] +//! pattern = [{ Balances: pallet_balances }] +//! } +//! } +//! ``` +//! `tt_default_parts` must be defined. It returns the pallet parts inside some tokens, and +//! then `tt_call` will pipe the returned pallet parts into the input of `match_and_insert`. +//! Thus `match_and_insert` will initially receive the following inputs: +//! ```ignore +//! frame_support::match_and_insert! { +//! target = [{ +//! frame_support::match_and_insert! { +//! target = [{ +//! construct_runtime!( +//! //... +//! { +//! System: frame_system = 0, +//! Balances: pallet_balances = 1, +//! } +//! ) +//! }] +//! pattern = [{ System: frame_system }] +//! tokens = [{ ::{Pallet, Call} }] +//! }] +//! pattern = [{ Balances: pallet_balances }] +//! tokens = [{ ::{Pallet, Call} }] +//! } +//! ``` +//! After dealing with `pallet_balances`, the inner `match_and_insert` will expand to: +//! ```ignore +//! frame_support::match_and_insert! { +//! target = [{ +//! construct_runtime!( +//! //... +//! { +//! System: frame_system = 0, // Implicit definition of parts +//! Balances: pallet_balances::{Pallet, Call} = 1, // Explicit definition of parts +//! } +//! ) +//! }] +//! pattern = [{ System: frame_system }] +//! tokens = [{ ::{Pallet, Call} }] +//! } +//! ``` +//! Which will then finally expand to the following: +//! ```ignore +//! construct_runtime!( +//! //... +//! { +//! System: frame_system::{Pallet, Call}, +//! Balances: pallet_balances::{Pallet, Call}, +//! } +//! ) +//! ``` +//! This call has no implicit pallet parts, thus it will expand to the runtime construction: +//! ```ignore +//! pub struct Runtime { ... } +//! pub struct Call { ... } +//! impl Call ... +//! pub enum Origin { ... } +//! ... +//! ``` +//! +//! Visualizing the entire flow of `construct_runtime!`, it would look like the following: +//! +//! ```ignore +//! +--------------------+ +---------------------+ +-------------------+ +//! | | | (defined in pallet) | | | +//! | construct_runtime! | --> | tt_default_parts! | --> | match_and_insert! | +//! | w/ no pallet parts | | | | | +//! +--------------------+ +---------------------+ +-------------------+ +//! +//! +--------------------+ +//! | | +//! --> | construct_runtime! | +//! | w/ pallet parts | +//! +--------------------+ +//! ``` + mod expand; mod parse; use frame_support_procedural_tools::{ - generate_crate_access, generate_hidden_includes, syn_ext as ext, + generate_crate_access, generate_crate_access_2018, generate_hidden_includes, +}; +use parse::{ + ExplicitRuntimeDeclaration, ImplicitRuntimeDeclaration, Pallet, RuntimeDeclaration, + WhereSection, }; -use parse::{PalletDeclaration, PalletPart, PalletPath, RuntimeDefinition, WhereSection}; use proc_macro::TokenStream; use proc_macro2::TokenStream as TokenStream2; use quote::quote; -use std::collections::HashMap; use syn::{Ident, Result}; /// The fixed name of the system pallet. const SYSTEM_PALLET_NAME: &str = "System"; -/// The complete definition of a pallet with the resulting fixed index. -#[derive(Debug, Clone)] -pub struct Pallet { - pub name: Ident, - pub index: u8, - pub path: PalletPath, - pub instance: Option, - pub pallet_parts: Vec, -} - -impl Pallet { - /// Get resolved pallet parts - fn pallet_parts(&self) -> &[PalletPart] { - &self.pallet_parts - } +/// Implementation of `construct_runtime` macro. Either expand to some code which will call +/// `construct_runtime` again, or expand to the final runtime definition. +pub fn construct_runtime(input: TokenStream) -> TokenStream { + let input_copy = input.clone(); + let definition = syn::parse_macro_input!(input as RuntimeDeclaration); - /// Find matching parts - fn find_part(&self, name: &str) -> Option<&PalletPart> { - self.pallet_parts.iter().find(|part| part.name() == name) - } + let res = match definition { + RuntimeDeclaration::Implicit(implicit_def) => + construct_runtime_intermediary_expansion(input_copy.into(), implicit_def), + RuntimeDeclaration::Explicit(explicit_decl) => + construct_runtime_final_expansion(explicit_decl), + }; - /// Return whether pallet contains part - fn exists_part(&self, name: &str) -> bool { - self.find_part(name).is_some() - } + res.unwrap_or_else(|e| e.to_compile_error()).into() } -/// Convert from the parsed pallet to their final information. -/// Assign index to each pallet using same rules as rust for fieldless enum. -/// I.e. implicit are assigned number incrementedly from last explicit or 0. -fn complete_pallets(decl: impl Iterator) -> syn::Result> { - let mut indices = HashMap::new(); - let mut last_index: Option = None; - let mut names = HashMap::new(); - - decl.map(|pallet| { - let final_index = match pallet.index { - Some(i) => i, - None => last_index.map_or(Some(0), |i| i.checked_add(1)).ok_or_else(|| { - let msg = "Pallet index doesn't fit into u8, index is 256"; - syn::Error::new(pallet.name.span(), msg) - })?, - }; - - last_index = Some(final_index); - - if let Some(used_pallet) = indices.insert(final_index, pallet.name.clone()) { - let msg = format!( - "Pallet indices are conflicting: Both pallets {} and {} are at index {}", - used_pallet, pallet.name, final_index, - ); - let mut err = syn::Error::new(used_pallet.span(), &msg); - err.combine(syn::Error::new(pallet.name.span(), msg)); - return Err(err) - } - - if let Some(used_pallet) = names.insert(pallet.name.clone(), pallet.name.span()) { - let msg = "Two pallets with the same name!"; - - let mut err = syn::Error::new(used_pallet, &msg); - err.combine(syn::Error::new(pallet.name.span(), &msg)); - return Err(err) - } - - Ok(Pallet { - name: pallet.name, - index: final_index, - path: pallet.path, - instance: pallet.instance, - pallet_parts: pallet.pallet_parts, - }) - }) - .collect() -} +/// When some pallet have implicit parts definition then the macro will expand into a macro call to +/// `construct_runtime_args` of each pallets, see root documentation. +fn construct_runtime_intermediary_expansion( + input: TokenStream2, + definition: ImplicitRuntimeDeclaration, +) -> Result { + let frame_support = generate_crate_access_2018("frame-support")?; + let mut expansion = quote::quote!( + #frame_support::construct_runtime! { #input } + ); + for pallet in definition.pallets.iter().filter(|pallet| pallet.pallet_parts.is_none()) { + let pallet_path = &pallet.path; + let pallet_name = &pallet.name; + let pallet_instance = pallet.instance.as_ref().map(|instance| quote::quote!(::<#instance>)); + expansion = quote::quote!( + #frame_support::tt_call! { + macro = [{ #pallet_path::tt_default_parts }] + frame_support = [{ #frame_support }] + ~~> #frame_support::match_and_insert! { + target = [{ #expansion }] + pattern = [{ #pallet_name: #pallet_path #pallet_instance }] + } + } + ); + } -pub fn construct_runtime(input: TokenStream) -> TokenStream { - let definition = syn::parse_macro_input!(input as RuntimeDefinition); - construct_runtime_parsed(definition) - .unwrap_or_else(|e| e.to_compile_error()) - .into() + Ok(expansion.into()) } -fn construct_runtime_parsed(definition: RuntimeDefinition) -> Result { - let RuntimeDefinition { +/// All pallets have explicit definition of parts, this will expand to the runtime declaration. +fn construct_runtime_final_expansion( + definition: ExplicitRuntimeDeclaration, +) -> Result { + let ExplicitRuntimeDeclaration { name, - where_section: WhereSection { block, node_block, unchecked_extrinsic, .. }, - pallets: - ext::Braces { content: ext::Punctuated { inner: pallets, .. }, token: pallets_token }, - .. + where_section: WhereSection { block, node_block, unchecked_extrinsic }, + pallets, + pallets_token, } = definition; - let pallets = complete_pallets(pallets.into_iter())?; - let hidden_crate_name = "construct_runtime"; let scrate = generate_crate_access(&hidden_crate_name, "frame-support"); let scrate_decl = generate_hidden_includes(&hidden_crate_name, "frame-support"); diff --git a/frame/support/procedural/src/construct_runtime/parse.rs b/frame/support/procedural/src/construct_runtime/parse.rs index a0ec6dfa5803..f80b7b1ac554 100644 --- a/frame/support/procedural/src/construct_runtime/parse.rs +++ b/frame/support/procedural/src/construct_runtime/parse.rs @@ -17,13 +17,13 @@ use frame_support_procedural_tools::syn_ext as ext; use proc_macro2::{Span, TokenStream}; -use std::collections::HashSet; +use std::collections::{HashMap, HashSet}; use syn::{ ext::IdentExt, parse::{Parse, ParseStream}, punctuated::Punctuated, spanned::Spanned, - token, Error, Ident, Path, PathArguments, PathSegment, Result, Token, + token, Error, Ident, Path, Result, Token, }; mod keyword { @@ -38,26 +38,63 @@ mod keyword { syn::custom_keyword!(Origin); syn::custom_keyword!(Inherent); syn::custom_keyword!(ValidateUnsigned); + syn::custom_keyword!(exclude_parts); + syn::custom_keyword!(use_parts); } +/// Declaration of a runtime. +/// +/// Pallet declare their part either explicitly or implicitly (using no part declaration) +/// If all pallet have explicit parts then the runtime declaration is explicit, otherwise it is +/// implicit. +#[derive(Debug)] +pub enum RuntimeDeclaration { + Implicit(ImplicitRuntimeDeclaration), + Explicit(ExplicitRuntimeDeclaration), +} + +/// Declaration of a runtime with some pallet with implicit declaration of parts. +#[derive(Debug)] +pub struct ImplicitRuntimeDeclaration { + pub name: Ident, + pub where_section: WhereSection, + pub pallets: Vec, +} + +/// Declaration of a runtime with all pallet having explicit declaration of parts. #[derive(Debug)] -pub struct RuntimeDefinition { - pub visibility_token: Token![pub], - pub enum_token: Token![enum], +pub struct ExplicitRuntimeDeclaration { pub name: Ident, pub where_section: WhereSection, - pub pallets: ext::Braces>, + pub pallets: Vec, + pub pallets_token: token::Brace, } -impl Parse for RuntimeDefinition { +impl Parse for RuntimeDeclaration { fn parse(input: ParseStream) -> Result { - Ok(Self { - visibility_token: input.parse()?, - enum_token: input.parse()?, - name: input.parse()?, - where_section: input.parse()?, - pallets: input.parse()?, - }) + input.parse::()?; + input.parse::()?; + let name = input.parse::()?; + let where_section = input.parse()?; + let pallets = + input.parse::>>()?; + let pallets_token = pallets.token; + + match convert_pallets(pallets.content.inner.into_iter().collect())? { + PalletsConversion::Implicit(pallets) => + Ok(RuntimeDeclaration::Implicit(ImplicitRuntimeDeclaration { + name, + where_section, + pallets, + })), + PalletsConversion::Explicit(pallets) => + Ok(RuntimeDeclaration::Explicit(ExplicitRuntimeDeclaration { + name, + where_section, + pallets, + pallets_token, + })), + } } } @@ -136,14 +173,34 @@ impl Parse for WhereDefinition { } } +/// The declaration of a pallet. #[derive(Debug, Clone)] pub struct PalletDeclaration { + /// The name of the pallet, e.g.`System` in `System: frame_system`. pub name: Ident, - /// Optional fixed index (e.g. `MyPallet ... = 3,`) + /// Optional fixed index, e.g. `MyPallet ... = 3,`. pub index: Option, + /// The path of the pallet, e.g. `frame_system` in `System: frame_system`. pub path: PalletPath, + /// The instance of the pallet, e.g. `Instance1` in `Council: pallet_collective::`. pub instance: Option, - pub pallet_parts: Vec, + /// The declared pallet parts, + /// e.g. `Some([Pallet, Call])` for `System: system::{Pallet, Call}` + /// or `None` for `System: system`. + pub pallet_parts: Option>, + /// The specified parts, either use_parts or exclude_parts. + pub specified_parts: SpecifiedParts, +} + +/// The possible declaration of pallet parts to use. +#[derive(Debug, Clone)] +pub enum SpecifiedParts { + /// Use all the pallet parts except those specified. + Exclude(Vec), + /// Use only the specified pallet parts. + Use(Vec), + /// Use the all the pallet parts. + All, } impl Parse for PalletDeclaration { @@ -151,38 +208,78 @@ impl Parse for PalletDeclaration { let name = input.parse()?; let _: Token![:] = input.parse()?; let path = input.parse()?; - let instance = if input.peek(Token![<]) { + + // Parse for instance. + let instance = if input.peek(Token![::]) && input.peek3(Token![<]) { + let _: Token![::] = input.parse()?; let _: Token![<] = input.parse()?; let res = Some(input.parse()?); let _: Token![>] = input.parse()?; - let _: Token![::] = input.parse()?; res + } else if !(input.peek(Token![::]) && input.peek3(token::Brace)) && + !input.peek(keyword::exclude_parts) && + !input.peek(keyword::use_parts) && + !input.peek(Token![=]) && + !input.peek(Token![,]) && + !input.is_empty() + { + return Err(input.error( + "Unexpected tokens, expected one of `::$ident` `::{`, `exclude_parts`, `use_parts`, `=`, `,`", + )) } else { None }; - let pallet_parts = parse_pallet_parts(input)?; + // Parse for explicit parts + let pallet_parts = if input.peek(Token![::]) && input.peek3(token::Brace) { + let _: Token![::] = input.parse()?; + Some(parse_pallet_parts(input)?) + } else if !input.peek(keyword::exclude_parts) && + !input.peek(keyword::use_parts) && + !input.peek(Token![=]) && + !input.peek(Token![,]) && + !input.is_empty() + { + return Err(input.error( + "Unexpected tokens, expected one of `::{`, `exclude_parts`, `use_parts`, `=`, `,`", + )) + } else { + None + }; + + // Parse for specified parts + let specified_parts = if input.peek(keyword::exclude_parts) { + let _: keyword::exclude_parts = input.parse()?; + SpecifiedParts::Exclude(parse_pallet_parts_no_generic(input)?) + } else if input.peek(keyword::use_parts) { + let _: keyword::use_parts = input.parse()?; + SpecifiedParts::Use(parse_pallet_parts_no_generic(input)?) + } else if !input.peek(Token![=]) && !input.peek(Token![,]) && !input.is_empty() { + return Err(input.error("Unexpected tokens, expected one of `exclude_parts`, `=`, `,`")) + } else { + SpecifiedParts::All + }; + // Parse for pallet index let index = if input.peek(Token![=]) { input.parse::()?; let index = input.parse::()?; let index = index.base10_parse::()?; Some(index) + } else if !input.peek(Token![,]) && !input.is_empty() { + return Err(input.error("Unexpected tokens, expected one of `=`, `,`")) } else { None }; - let parsed = Self { name, path, instance, pallet_parts, index }; - - Ok(parsed) + Ok(Self { name, path, instance, pallet_parts, specified_parts, index }) } } /// A struct representing a path to a pallet. `PalletPath` is almost identical to the standard /// Rust path with a few restrictions: /// - No leading colons allowed -/// - Path segments can only consist of identifers; angle-bracketed or parenthesized segments will -/// result in a parsing error (except when specifying instances) +/// - Path segments can only consist of identifers separated by colons #[derive(Debug, Clone)] pub struct PalletPath { pub inner: Path, @@ -202,34 +299,27 @@ impl PalletPath { impl Parse for PalletPath { fn parse(input: ParseStream) -> Result { - let mut lookahead = input.lookahead1(); - let mut segments = Punctuated::new(); + let mut res = + PalletPath { inner: Path { leading_colon: None, segments: Punctuated::new() } }; + let lookahead = input.lookahead1(); if lookahead.peek(Token![crate]) || lookahead.peek(Token![self]) || lookahead.peek(Token![super]) || lookahead.peek(Ident) { let ident = input.call(Ident::parse_any)?; - segments.push(PathSegment { ident, arguments: PathArguments::None }); - let _: Token![::] = input.parse()?; - lookahead = input.lookahead1(); + res.inner.segments.push(ident.into()); } else { return Err(lookahead.error()) } - while lookahead.peek(Ident) { - let ident = input.parse()?; - segments.push(PathSegment { ident, arguments: PathArguments::None }); - let _: Token![::] = input.parse()?; - lookahead = input.lookahead1(); - } - - if !lookahead.peek(token::Brace) && !lookahead.peek(Token![<]) { - return Err(lookahead.error()) + while input.peek(Token![::]) && input.peek3(Ident) { + input.parse::()?; + let ident = input.parse::()?; + res.inner.segments.push(ident.into()); } - - Ok(Self { inner: Path { leading_colon: None, segments } }) + Ok(res) } } @@ -391,3 +481,174 @@ fn remove_kind( Err(input.error(msg)) } } + +/// The declaration of a part without its generics +#[derive(Debug, Clone)] +pub struct PalletPartNoGeneric { + keyword: PalletPartKeyword, +} + +impl Parse for PalletPartNoGeneric { + fn parse(input: ParseStream) -> Result { + Ok(Self { keyword: input.parse()? }) + } +} + +/// Parse [`PalletPartNoGeneric`]'s from a braces enclosed list that is split by commas, e.g. +/// +/// `{ Call, Event }` +fn parse_pallet_parts_no_generic(input: ParseStream) -> Result> { + let pallet_parts: ext::Braces> = + input.parse()?; + + let mut resolved = HashSet::new(); + for part in pallet_parts.content.inner.iter() { + if !resolved.insert(part.keyword.name()) { + let msg = format!( + "`{}` was already declared before. Please remove the duplicate declaration", + part.keyword.name(), + ); + return Err(Error::new(part.keyword.span(), msg)) + } + } + + Ok(pallet_parts.content.inner.into_iter().collect()) +} + +/// The final definition of a pallet with the resulting fixed index and explicit parts. +#[derive(Debug, Clone)] +pub struct Pallet { + /// The name of the pallet, e.g.`System` in `System: frame_system`. + pub name: Ident, + /// Either automatically infered, or defined (e.g. `MyPallet ... = 3,`). + pub index: u8, + /// The path of the pallet, e.g. `frame_system` in `System: frame_system`. + pub path: PalletPath, + /// The instance of the pallet, e.g. `Instance1` in `Council: pallet_collective::`. + pub instance: Option, + /// The pallet parts to use for the pallet. + pub pallet_parts: Vec, +} + +impl Pallet { + /// Get resolved pallet parts + pub fn pallet_parts(&self) -> &[PalletPart] { + &self.pallet_parts + } + + /// Find matching parts + pub fn find_part(&self, name: &str) -> Option<&PalletPart> { + self.pallet_parts.iter().find(|part| part.name() == name) + } + + /// Return whether pallet contains part + pub fn exists_part(&self, name: &str) -> bool { + self.find_part(name).is_some() + } +} + +/// Result of a conversion of a declaration of pallets. +enum PalletsConversion { + Implicit(Vec), + Explicit(Vec), +} + +/// Convert from the parsed pallet declaration to their final information. +/// +/// Check if all pallet have explicit declaration of their parts, if so then assign index to each +/// pallet using same rules as rust for fieldless enum. I.e. implicit are assigned number +/// incrementedly from last explicit or 0. +fn convert_pallets(pallets: Vec) -> syn::Result { + if pallets.iter().any(|pallet| pallet.pallet_parts.is_none()) { + return Ok(PalletsConversion::Implicit(pallets)) + } + + let mut indices = HashMap::new(); + let mut last_index: Option = None; + let mut names = HashMap::new(); + + let pallets = pallets + .into_iter() + .map(|pallet| { + let final_index = match pallet.index { + Some(i) => i, + None => last_index.map_or(Some(0), |i| i.checked_add(1)).ok_or_else(|| { + let msg = "Pallet index doesn't fit into u8, index is 256"; + syn::Error::new(pallet.name.span(), msg) + })?, + }; + + last_index = Some(final_index); + + if let Some(used_pallet) = indices.insert(final_index, pallet.name.clone()) { + let msg = format!( + "Pallet indices are conflicting: Both pallets {} and {} are at index {}", + used_pallet, pallet.name, final_index, + ); + let mut err = syn::Error::new(used_pallet.span(), &msg); + err.combine(syn::Error::new(pallet.name.span(), msg)); + return Err(err) + } + + if let Some(used_pallet) = names.insert(pallet.name.clone(), pallet.name.span()) { + let msg = "Two pallets with the same name!"; + + let mut err = syn::Error::new(used_pallet, &msg); + err.combine(syn::Error::new(pallet.name.span(), &msg)); + return Err(err) + } + + let mut pallet_parts = pallet.pallet_parts.expect("Checked above"); + + let available_parts = + pallet_parts.iter().map(|part| part.keyword.name()).collect::>(); + + // Check parts are correctly specified + match &pallet.specified_parts { + SpecifiedParts::Exclude(parts) | SpecifiedParts::Use(parts) => + for part in parts { + if !available_parts.contains(part.keyword.name()) { + let msg = format!( + "Invalid pallet part specified, the pallet `{}` doesn't have the \ + `{}` part. Available parts are: {}.", + pallet.name, + part.keyword.name(), + pallet_parts.iter().fold(String::new(), |fold, part| { + if fold.is_empty() { + format!("`{}`", part.keyword.name()) + } else { + format!("{}, `{}`", fold, part.keyword.name()) + } + }) + ); + return Err(syn::Error::new(part.keyword.span(), msg)) + } + }, + SpecifiedParts::All => (), + } + + // Set only specified parts. + match pallet.specified_parts { + SpecifiedParts::Exclude(excluded_parts) => pallet_parts.retain(|part| { + !excluded_parts + .iter() + .any(|excluded_part| excluded_part.keyword.name() == part.keyword.name()) + }), + SpecifiedParts::Use(used_parts) => pallet_parts.retain(|part| { + used_parts.iter().any(|use_part| use_part.keyword.name() == part.keyword.name()) + }), + SpecifiedParts::All => (), + } + + Ok(Pallet { + name: pallet.name, + index: final_index, + path: pallet.path, + instance: pallet.instance, + pallet_parts, + }) + }) + .collect::>>()?; + + Ok(PalletsConversion::Explicit(pallets)) +} diff --git a/frame/support/procedural/src/lib.rs b/frame/support/procedural/src/lib.rs index 6987fc49b9a8..d01bbf6ace52 100644 --- a/frame/support/procedural/src/lib.rs +++ b/frame/support/procedural/src/lib.rs @@ -26,6 +26,7 @@ mod debug_no_bound; mod default_no_bound; mod dummy_part_checker; mod key_prefix; +mod match_and_insert; mod pallet; mod partial_eq_no_bound; mod storage; @@ -297,52 +298,91 @@ pub fn decl_storage(input: TokenStream) -> TokenStream { /// /// # Example: /// -/// ```nocompile +/// ```ignore /// construct_runtime!( /// pub enum Runtime where /// Block = Block, /// NodeBlock = node::Block, /// UncheckedExtrinsic = UncheckedExtrinsic /// { -/// System: system::{Pallet, Call, Event, Config} = 0, -/// Test: test::{Pallet, Call} = 1, -/// Test2: test_with_long_module::{Pallet, Event}, +/// System: frame_system::{Pallet, Call, Event, Config} = 0, +/// Test: path::to::test::{Pallet, Call} = 1, /// /// // Pallets with instances -/// Test3_Instance1: test3::::{Pallet, Call, Storage, Event, Config, Origin}, -/// Test3_DefaultInstance: test3::{Pallet, Call, Storage, Event, Config, Origin} = 4, +/// Test2_Instance1: test2::::{Pallet, Call, Storage, Event, Config, Origin}, +/// Test2_DefaultInstance: test2::{Pallet, Call, Storage, Event, Config, Origin} = 4, +/// +/// // Pallets declared with `pallet` attribute macro: no need to define the parts +/// Test3_Instance1: test3::, +/// Test3_DefaultInstance: test3, +/// +/// // with `exclude_parts` keyword some part can be excluded. +/// Test4_Instance1: test4:: exclude_parts { Call, Origin }, +/// Test4_DefaultInstance: test4 exclude_parts { Storage }, +/// +/// // with `use_parts` keyword, a subset of the pallet parts can be specified. +/// Test4_Instance1: test4:: use_parts { Pallet, Call}, +/// Test4_DefaultInstance: test4 use_parts { Pallet }, /// } /// ) /// ``` /// -/// The identifier `System` is the name of the pallet and the lower case identifier `system` is the -/// name of the Rust module/crate for this Substrate pallet. The identifiers between the braces are -/// the pallet parts provided by the pallet. It is important to list these parts here to export -/// them correctly in the metadata or to make the pallet usable in the runtime. +/// Each pallet is declared as such: +/// * `Identifier`: name given to the pallet that uniquely identifies it. /// -/// We provide support for the following module parts in a pallet: +/// * `:`: colon separator /// -/// - `Pallet` - Required for all pallets -/// - `Call` - If the pallet has callable functions -/// - `Storage` - If the pallet uses storage -/// - `Event` or `Event` (if the event is generic) - If the pallet emits events -/// - `Origin` or `Origin` (if the origin is generic) - If the pallet has instanciable origins -/// - `Config` or `Config` (if the config is generic) - If the pallet builds the genesis storage -/// with `GenesisConfig` -/// - `Inherent` - If the pallet provides/can check inherents. -/// - `ValidateUnsigned` - If the pallet validates unsigned extrinsics. +/// * `path::to::pallet`: identifiers separated by colons which declare the path to a pallet +/// definition. /// -/// `= $n` is an optional part allowing to define at which index the pallet variants in -/// `OriginCaller`, `Call` and `Event` are encoded, and to define the ModuleToIndex value. +/// * `::` optional: specify the instance of the pallet to use. If not specified it will +/// use the default instance (or the only instance in case of non-instantiable pallets). /// -/// if `= $n` is not given, then index is resolved same as fieldless enum in Rust -/// (i.e. incrementedly from previous index): -/// ```nocompile -/// pallet1 .. = 2, -/// pallet2 .., // Here pallet2 is given index 3 -/// pallet3 .. = 0, -/// pallet4 .., // Here pallet4 is given index 1 -/// ``` +/// * `::{ Part1, Part2, .. }` optional if pallet declared with `frame_support::pallet`: Comma +/// separated parts declared with their generic. If a pallet is declared with +/// `frame_support::pallet` macro then the parts can be automatically derived if not explicitly +/// provided. We provide support for the following module parts in a pallet: +/// +/// - `Pallet` - Required for all pallets +/// - `Call` - If the pallet has callable functions +/// - `Storage` - If the pallet uses storage +/// - `Event` or `Event` (if the event is generic) - If the pallet emits events +/// - `Origin` or `Origin` (if the origin is generic) - If the pallet has instanciable origins +/// - `Config` or `Config` (if the config is generic) - If the pallet builds the genesis +/// storage with `GenesisConfig` +/// - `Inherent` - If the pallet provides/can check inherents. +/// - `ValidateUnsigned` - If the pallet validates unsigned extrinsics. +/// +/// It is important to list these parts here to export them correctly in the metadata or to make +/// the pallet usable in the runtime. +/// +/// * `exclude_parts { Part1, Part2 }` optional: comma separated parts without generics. I.e. one of +/// `Pallet`, `Call`, `Storage`, `Event`, `Origin`, `Config`, `Inherent`, `ValidateUnsigned`. It +/// is incompatible with `use_parts`. This specifies the part to exclude. In order to select +/// subset of the pallet parts. +/// +/// For example excluding the part `Call` can be useful if the runtime doesn't want to make the +/// pallet calls available. +/// +/// * `use_parts { Part1, Part2 }` optional: comma separated parts without generics. I.e. one of +/// `Pallet`, `Call`, `Storage`, `Event`, `Origin`, `Config`, `Inherent`, `ValidateUnsigned`. It +/// is incompatible with `exclude_parts`. This specifies the part to use. In order to select a +/// subset of the pallet parts. +/// +/// For example not using the part `Call` can be useful if the runtime doesn't want to make the +/// pallet calls available. +/// +/// * `= $n` optional: number to define at which index the pallet variants in `OriginCaller`, `Call` +/// and `Event` are encoded, and to define the ModuleToIndex value. +/// +/// if `= $n` is not given, then index is resolved in the same way as fieldless enum in Rust +/// (i.e. incrementedly from previous index): +/// ```nocompile +/// pallet1 .. = 2, +/// pallet2 .., // Here pallet2 is given index 3 +/// pallet3 .. = 0, +/// pallet4 .., // Here pallet4 is given index 1 +/// ``` /// /// # Note /// @@ -352,8 +392,8 @@ pub fn decl_storage(input: TokenStream) -> TokenStream { /// /// # Type definitions /// -/// * The macro generates a type alias for each pallet to their `Module` (or `Pallet`). E.g. `type -/// System = frame_system::Pallet` +/// * The macro generates a type alias for each pallet to their `Pallet`. E.g. `type System = +/// frame_system::Pallet` #[proc_macro] pub fn construct_runtime(input: TokenStream) -> TokenStream { construct_runtime::construct_runtime(input) @@ -498,3 +538,27 @@ pub fn impl_key_prefix_for_tuples(input: TokenStream) -> TokenStream { pub fn __generate_dummy_part_checker(input: TokenStream) -> TokenStream { dummy_part_checker::generate_dummy_part_checker(input) } + +/// Macro that inserts some tokens after the first match of some pattern. +/// +/// # Example: +/// +/// ```nocompile +/// match_and_insert!( +/// target = [{ Some content with { at some point match pattern } other match pattern are ignored }] +/// pattern = [{ match pattern }] // the match pattern cannot contain any group: `[]`, `()`, `{}` +/// // can relax this constraint, but will require modifying the match logic in code +/// tokens = [{ expansion tokens }] // content inside braces can be anything including groups +/// ); +/// ``` +/// +/// will generate: +/// +/// ```nocompile +/// Some content with { at some point match pattern expansion tokens } other match patterns are +/// ignored +/// ``` +#[proc_macro] +pub fn match_and_insert(input: TokenStream) -> TokenStream { + match_and_insert::match_and_insert(input) +} diff --git a/frame/support/procedural/src/match_and_insert.rs b/frame/support/procedural/src/match_and_insert.rs new file mode 100644 index 000000000000..4ffc596e6dca --- /dev/null +++ b/frame/support/procedural/src/match_and_insert.rs @@ -0,0 +1,159 @@ +// This file is part of Substrate. + +// Copyright (C) 2021 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. + +//! Implementation of the `match_and_insert` macro. + +use proc_macro2::{Group, Span, TokenStream, TokenTree}; +use std::iter::once; +use syn::spanned::Spanned; + +mod keyword { + syn::custom_keyword!(target); + syn::custom_keyword!(pattern); + syn::custom_keyword!(tokens); +} + +pub fn match_and_insert(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + let MatchAndInsertDef { pattern, tokens, target } = + syn::parse_macro_input!(input as MatchAndInsertDef); + + match expand_in_stream(&pattern, &mut Some(tokens), target) { + Ok(stream) => stream.into(), + Err(err) => err.to_compile_error().into(), + } +} + +struct MatchAndInsertDef { + // Token stream to search and insert tokens into. + target: TokenStream, + // Pattern to match against, this is ensured to have no TokenTree::Group nor TokenTree::Literal + // (i.e. contains only Punct or Ident), and not being empty. + pattern: Vec, + // Token stream to insert after the match pattern. + tokens: TokenStream, +} + +impl syn::parse::Parse for MatchAndInsertDef { + fn parse(input: syn::parse::ParseStream) -> syn::Result { + let mut target; + let _ = input.parse::()?; + let _ = input.parse::()?; + let _replace_with_bracket: syn::token::Bracket = syn::bracketed!(target in input); + let _replace_with_brace: syn::token::Brace = syn::braced!(target in target); + let target = target.parse()?; + + let mut pattern; + let _ = input.parse::()?; + let _ = input.parse::()?; + let _replace_with_bracket: syn::token::Bracket = syn::bracketed!(pattern in input); + let _replace_with_brace: syn::token::Brace = syn::braced!(pattern in pattern); + let pattern = pattern.parse::()?.into_iter().collect::>(); + + if let Some(t) = pattern.iter().find(|t| matches!(t, TokenTree::Group(_))) { + return Err(syn::Error::new(t.span(), "Unexpected group token tree")) + } + if let Some(t) = pattern.iter().find(|t| matches!(t, TokenTree::Literal(_))) { + return Err(syn::Error::new(t.span(), "Unexpected literal token tree")) + } + + if pattern.is_empty() { + return Err(syn::Error::new(Span::call_site(), "empty match pattern is invalid")) + } + + let mut tokens; + let _ = input.parse::()?; + let _ = input.parse::()?; + let _replace_with_bracket: syn::token::Bracket = syn::bracketed!(tokens in input); + let _replace_with_brace: syn::token::Brace = syn::braced!(tokens in tokens); + let tokens = tokens.parse()?; + + Ok(Self { tokens, pattern, target }) + } +} + +// Insert `tokens` after the first matching `pattern`. +// `tokens` must be some (Option is used for internal simplification). +// `pattern` must not be empty and should only contain Ident or Punct. +fn expand_in_stream( + pattern: &[TokenTree], + tokens: &mut Option, + stream: TokenStream, +) -> syn::Result { + assert!( + tokens.is_some(), + "`tokens` must be some, Option is used because `tokens` is used only once" + ); + assert!( + !pattern.is_empty(), + "`pattern` must not be empty, otherwise there is nothing to match against" + ); + + let stream_span = stream.span(); + let mut stream = stream.into_iter(); + let mut extended = TokenStream::new(); + let mut match_cursor = 0; + + while let Some(token) = stream.next() { + match token { + TokenTree::Group(group) => { + match_cursor = 0; + let group_stream = group.stream(); + match expand_in_stream(pattern, tokens, group_stream) { + Ok(s) => { + extended.extend(once(TokenTree::Group(Group::new(group.delimiter(), s)))); + extended.extend(stream); + return Ok(extended) + }, + Err(_) => { + extended.extend(once(TokenTree::Group(group))); + }, + } + }, + other => { + advance_match_cursor(&other, pattern, &mut match_cursor); + + extended.extend(once(other)); + + if match_cursor == pattern.len() { + extended + .extend(once(tokens.take().expect("tokens is used to replace only once"))); + extended.extend(stream); + return Ok(extended) + } + }, + } + } + // if we reach this point, it means the stream is empty and we haven't found a matching pattern + let msg = format!("Cannot find pattern `{:?}` in given token stream", pattern); + Err(syn::Error::new(stream_span, msg)) +} + +fn advance_match_cursor(other: &TokenTree, pattern: &[TokenTree], match_cursor: &mut usize) { + use TokenTree::{Ident, Punct}; + + let does_match_other_pattern = match (other, &pattern[*match_cursor]) { + (Ident(i1), Ident(i2)) => i1 == i2, + (Punct(p1), Punct(p2)) => p1.as_char() == p2.as_char(), + _ => false, + }; + + if does_match_other_pattern { + *match_cursor += 1; + } else { + *match_cursor = 0; + } +} diff --git a/frame/support/procedural/src/pallet/expand/mod.rs b/frame/support/procedural/src/pallet/expand/mod.rs index 083ad61fc523..21acd3c0dd32 100644 --- a/frame/support/procedural/src/pallet/expand/mod.rs +++ b/frame/support/procedural/src/pallet/expand/mod.rs @@ -29,6 +29,7 @@ mod origin; mod pallet_struct; mod storage; mod store_trait; +mod tt_default_parts; mod type_value; mod validate_unsigned; @@ -67,6 +68,7 @@ pub fn expand(mut def: Def) -> proc_macro2::TokenStream { let type_values = type_value::expand_type_values(&mut def); let origins = origin::expand_origins(&mut def); let validate_unsigned = validate_unsigned::expand_validate_unsigned(&mut def); + let tt_default_parts = tt_default_parts::expand_tt_default_parts(&mut def); if get_doc_literals(&def.item.attrs).is_empty() { def.item.attrs.push(syn::parse_quote!( @@ -96,6 +98,7 @@ pub fn expand(mut def: Def) -> proc_macro2::TokenStream { #type_values #origins #validate_unsigned + #tt_default_parts ); def.item diff --git a/frame/support/procedural/src/pallet/expand/tt_default_parts.rs b/frame/support/procedural/src/pallet/expand/tt_default_parts.rs new file mode 100644 index 000000000000..cfab7982bfdc --- /dev/null +++ b/frame/support/procedural/src/pallet/expand/tt_default_parts.rs @@ -0,0 +1,82 @@ +// This file is part of Substrate. + +// Copyright (C) 2021 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. + +use crate::{pallet::Def, COUNTER}; +use syn::spanned::Spanned; + +/// Generate the `tt_default_parts` macro. +pub fn expand_tt_default_parts(def: &mut Def) -> proc_macro2::TokenStream { + let count = COUNTER.with(|counter| counter.borrow_mut().inc()); + let default_parts_unique_id = + syn::Ident::new(&format!("__tt_default_parts_{}", count), def.item.span()); + + let call_part = def.call.as_ref().map(|_| quote::quote!(Call,)); + + let storage_part = (!def.storages.is_empty()).then(|| quote::quote!(Storage,)); + + let event_part = def.event.as_ref().map(|event| { + let gen = event.gen_kind.is_generic().then(|| quote::quote!( )); + quote::quote!( Event #gen , ) + }); + + let origin_part = def.origin.as_ref().map(|origin| { + let gen = origin.is_generic.then(|| quote::quote!( )); + quote::quote!( Origin #gen , ) + }); + + let config_part = def.genesis_config.as_ref().map(|genesis_config| { + let gen = genesis_config.gen_kind.is_generic().then(|| quote::quote!( )); + quote::quote!( Config #gen , ) + }); + + let inherent_part = def.inherent.as_ref().map(|_| quote::quote!(Inherent,)); + + let validate_unsigned_part = + def.validate_unsigned.as_ref().map(|_| quote::quote!(ValidateUnsigned,)); + + quote::quote!( + // This macro follows the conventions as laid out by the `tt-call` crate. It does not + // accept any arguments and simply returns the pallet parts, separated by commas, then + // wrapped inside of braces and finally prepended with double colons, to the caller inside + // of a key named `tokens`. + // + // We need to accept a frame_support argument here, because this macro gets expanded on the + // crate that called the `construct_runtime!` macro, and said crate may have renamed + // frame-support, and so we need to pass in the frame-support path that said crate + // recognizes. + #[macro_export] + #[doc(hidden)] + macro_rules! #default_parts_unique_id { + { + $caller:tt + frame_support = [{ $($frame_support:ident)::* }] + } => { + $($frame_support)*::tt_return! { + $caller + tokens = [{ + ::{ + Pallet, #call_part #storage_part #event_part #origin_part #config_part + #inherent_part #validate_unsigned_part + } + }] + } + }; + } + + pub use #default_parts_unique_id as tt_default_parts; + ) +} diff --git a/frame/support/src/lib.rs b/frame/support/src/lib.rs index 1b93b5fb5975..d81300a404c4 100644 --- a/frame/support/src/lib.rs +++ b/frame/support/src/lib.rs @@ -50,6 +50,8 @@ pub use sp_runtime::RuntimeDebug; pub use sp_state_machine::BasicExternalities; #[doc(hidden)] pub use sp_std; +#[doc(hidden)] +pub use tt_call::*; #[macro_use] pub mod dispatch; @@ -573,7 +575,7 @@ pub fn debug(data: &impl sp_std::fmt::Debug) { #[doc(inline)] pub use frame_support_procedural::{ - construct_runtime, decl_storage, transactional, RuntimeDebugNoBound, + construct_runtime, decl_storage, match_and_insert, transactional, RuntimeDebugNoBound, }; #[doc(hidden)] diff --git a/frame/support/test/compile_pass/Cargo.toml b/frame/support/test/compile_pass/Cargo.toml new file mode 100644 index 000000000000..bca833200d44 --- /dev/null +++ b/frame/support/test/compile_pass/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "frame-support-test-compile-pass" +version = "4.0.0-dev" +authors = ["Parity Technologies "] +edition = "2018" +license = "Apache-2.0" +publish = false +homepage = "https://substrate.dev" +repository = "https://github.com/paritytech/substrate/" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } +sp-core = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/core" } +sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/runtime" } +sp-version = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/version" } +support = { package = "frame-support", version = "4.0.0-dev", default-features = false, path = "../../" } +system = { package = "frame-system", version = "4.0.0-dev", default-features = false, path = "../../../system" } + +[features] +default = ["std"] +std = [ + "codec/std", + "scale-info/std", + "support/std", + "system/std", +] diff --git a/frame/support/test/compile_pass/src/lib.rs b/frame/support/test/compile_pass/src/lib.rs new file mode 100644 index 000000000000..17ba40574adf --- /dev/null +++ b/frame/support/test/compile_pass/src/lib.rs @@ -0,0 +1,92 @@ +// This file is part of Substrate. + +// Copyright (C) 2018-2021 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 . + +#![cfg_attr(not(feature = "std"), no_std)] +// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. +#![recursion_limit = "256"] +//! This crate tests that `construct_runtime!` expands the pallet parts +//! correctly even when frame-support is renamed in Cargo.toml + +use sp_core::{sr25519, H256}; +use sp_runtime::{ + create_runtime_str, generic, + traits::{BlakeTwo256, IdentityLookup, Verify}, +}; +use sp_version::RuntimeVersion; +use support::{construct_runtime, parameter_types}; + +pub const VERSION: RuntimeVersion = RuntimeVersion { + spec_name: create_runtime_str!("frame-support-test-compile-pass"), + impl_name: create_runtime_str!("substrate-frame-support-test-compile-pass-runtime"), + authoring_version: 0, + spec_version: 0, + impl_version: 0, + apis: sp_version::create_apis_vec!([]), + transaction_version: 0, +}; + +pub type Signature = sr25519::Signature; +pub type AccountId = ::Signer; +pub type BlockNumber = u64; +pub type Index = u64; + +parameter_types! { + pub const BlockHashCount: BlockNumber = 2400; + pub const Version: RuntimeVersion = VERSION; + pub const SS58Prefix: u8 = 0; +} + +impl system::Config for Runtime { + type BaseCallFilter = support::traits::Everything; + type BlockWeights = (); + type BlockLength = (); + type Index = u128; + type Hash = H256; + type Hashing = BlakeTwo256; + type Header = Header; + type Lookup = IdentityLookup; + type BlockHashCount = BlockHashCount; + type Version = Version; + type AccountData = (); + type Origin = Origin; + type BlockNumber = BlockNumber; + type AccountId = AccountId; + type Event = Event; + type PalletInfo = PalletInfo; + type Call = Call; + type DbWeight = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type OnSetCode = (); + type SystemWeightInfo = (); + type SS58Prefix = SS58Prefix; +} + +pub type Header = generic::Header; +pub type Block = generic::Block; +pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; + +construct_runtime!( + pub enum Runtime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + System: system, + } +); diff --git a/frame/support/test/tests/construct_runtime_ui/both_use_and_excluded_parts.rs b/frame/support/test/tests/construct_runtime_ui/both_use_and_excluded_parts.rs new file mode 100644 index 000000000000..98cd1f197f61 --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/both_use_and_excluded_parts.rs @@ -0,0 +1,33 @@ +use frame_support::construct_runtime; +use sp_runtime::{generic, traits::BlakeTwo256}; +use sp_core::sr25519; + +#[frame_support::pallet] +mod pallet { + #[pallet::config] + pub trait Config: frame_system::Config {} + + #[pallet::pallet] + pub struct Pallet(_); +} + +pub type Signature = sr25519::Signature; +pub type BlockNumber = u64; +pub type Header = generic::Header; +pub type Block = generic::Block; +pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; + +impl pallet::Config for Runtime {} + +construct_runtime! { + pub enum Runtime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + System: system::{Pallet, Call, Storage, Config, Event}, + Pallet: pallet exclude_parts { Pallet } use_parts { Pallet }, + } +} + +fn main() {} diff --git a/frame/support/test/tests/construct_runtime_ui/both_use_and_excluded_parts.stderr b/frame/support/test/tests/construct_runtime_ui/both_use_and_excluded_parts.stderr new file mode 100644 index 000000000000..608d57d6a97f --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/both_use_and_excluded_parts.stderr @@ -0,0 +1,28 @@ +error: Unexpected tokens, expected one of `=`, `,` + --> $DIR/both_use_and_excluded_parts.rs:29:43 + | +29 | Pallet: pallet exclude_parts { Pallet } use_parts { Pallet }, + | ^^^^^^^^^ + +error[E0412]: cannot find type `Call` in this scope + --> $DIR/both_use_and_excluded_parts.rs:18:64 + | +18 | pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; + | ^^^^ not found in this scope + | +help: consider importing one of these items + | +1 | use crate::pallet::Call; + | +1 | use frame_support_test::Call; + | +1 | use frame_system::Call; + | +1 | use test_pallet::Call; + | + +error[E0412]: cannot find type `Runtime` in this scope + --> $DIR/both_use_and_excluded_parts.rs:20:25 + | +20 | impl pallet::Config for Runtime {} + | ^^^^^^^ not found in this scope diff --git a/frame/support/test/tests/construct_runtime_ui/duplicate_exclude.rs b/frame/support/test/tests/construct_runtime_ui/duplicate_exclude.rs new file mode 100644 index 000000000000..6d21c2a6e170 --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/duplicate_exclude.rs @@ -0,0 +1,13 @@ +use frame_support::construct_runtime; + +construct_runtime! { + pub enum Runtime where + UncheckedExtrinsic = UncheckedExtrinsic, + Block = Block, + NodeBlock = Block, + { + System: frame_system exclude_parts { Call, Call }, + } +} + +fn main() {} diff --git a/frame/support/test/tests/construct_runtime_ui/duplicate_exclude.stderr b/frame/support/test/tests/construct_runtime_ui/duplicate_exclude.stderr new file mode 100644 index 000000000000..75de56076528 --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/duplicate_exclude.stderr @@ -0,0 +1,5 @@ +error: `Call` was already declared before. Please remove the duplicate declaration + --> $DIR/duplicate_exclude.rs:9:46 + | +9 | System: frame_system exclude_parts { Call, Call }, + | ^^^^ diff --git a/frame/support/test/tests/construct_runtime_ui/exclude_missspell.rs b/frame/support/test/tests/construct_runtime_ui/exclude_missspell.rs new file mode 100644 index 000000000000..16cbf1e82cf8 --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/exclude_missspell.rs @@ -0,0 +1,13 @@ +use frame_support::construct_runtime; + +construct_runtime! { + pub enum Runtime where + UncheckedExtrinsic = UncheckedExtrinsic, + Block = Block, + NodeBlock = Block, + { + System: frame_system exclude_part { Call }, + } +} + +fn main() {} diff --git a/frame/support/test/tests/construct_runtime_ui/exclude_missspell.stderr b/frame/support/test/tests/construct_runtime_ui/exclude_missspell.stderr new file mode 100644 index 000000000000..82e6aa6c8e30 --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/exclude_missspell.stderr @@ -0,0 +1,5 @@ +error: Unexpected tokens, expected one of `::$ident` `::{`, `exclude_parts`, `use_parts`, `=`, `,` + --> $DIR/exclude_missspell.rs:9:24 + | +9 | System: frame_system exclude_part { Call }, + | ^^^^^^^^^^^^ diff --git a/frame/support/test/tests/construct_runtime_ui/exclude_undefined_part.rs b/frame/support/test/tests/construct_runtime_ui/exclude_undefined_part.rs new file mode 100644 index 000000000000..51be7e30bd3e --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/exclude_undefined_part.rs @@ -0,0 +1,38 @@ +use frame_support::construct_runtime; +use sp_runtime::{generic, traits::BlakeTwo256}; +use sp_core::sr25519; + +#[frame_support::pallet] +mod pallet { + use frame_support::pallet_prelude::*; + + #[pallet::config] + pub trait Config: frame_system::Config {} + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::storage] + type Foo = StorageValue; +} + +pub type Signature = sr25519::Signature; +pub type BlockNumber = u64; +pub type Header = generic::Header; +pub type Block = generic::Block; +pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; + +impl pallet::Config for Runtime {} + +construct_runtime! { + pub enum Runtime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + System: system::{Pallet, Call, Storage, Config, Event}, + Pallet: pallet exclude_parts { Call }, + } +} + +fn main() {} diff --git a/frame/support/test/tests/construct_runtime_ui/exclude_undefined_part.stderr b/frame/support/test/tests/construct_runtime_ui/exclude_undefined_part.stderr new file mode 100644 index 000000000000..4e31cfb75c07 --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/exclude_undefined_part.stderr @@ -0,0 +1,28 @@ +error: Invalid pallet part specified, the pallet `Pallet` doesn't have the `Call` part. Available parts are: `Pallet`, `Storage`. + --> $DIR/exclude_undefined_part.rs:34:34 + | +34 | Pallet: pallet exclude_parts { Call }, + | ^^^^ + +error[E0412]: cannot find type `Call` in this scope + --> $DIR/exclude_undefined_part.rs:23:64 + | +23 | pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; + | ^^^^ not found in this scope + | +help: consider importing one of these items + | +1 | use crate::pallet::Call; + | +1 | use frame_support_test::Call; + | +1 | use frame_system::Call; + | +1 | use test_pallet::Call; + | + +error[E0412]: cannot find type `Runtime` in this scope + --> $DIR/exclude_undefined_part.rs:25:25 + | +25 | impl pallet::Config for Runtime {} + | ^^^^^^^ not found in this scope diff --git a/frame/support/test/tests/construct_runtime_ui/invalid_module_details.stderr b/frame/support/test/tests/construct_runtime_ui/invalid_module_details.stderr index 50505b9130cb..db96b8749ca1 100644 --- a/frame/support/test/tests/construct_runtime_ui/invalid_module_details.stderr +++ b/frame/support/test/tests/construct_runtime_ui/invalid_module_details.stderr @@ -1,5 +1,5 @@ -error: expected one of: identifier, curly braces, `<` - --> $DIR/invalid_module_details.rs:9:19 +error: Unexpected tokens, expected one of `::$ident` `::{`, `exclude_parts`, `use_parts`, `=`, `,` + --> $DIR/invalid_module_details.rs:9:17 | 9 | system: System::(), - | ^^ + | ^^ diff --git a/frame/support/test/tests/construct_runtime_ui/invalid_token_after_module.stderr b/frame/support/test/tests/construct_runtime_ui/invalid_token_after_module.stderr index 3b967f96d7b4..6025de82bd20 100644 --- a/frame/support/test/tests/construct_runtime_ui/invalid_token_after_module.stderr +++ b/frame/support/test/tests/construct_runtime_ui/invalid_token_after_module.stderr @@ -1,4 +1,4 @@ -error: expected `::` +error: Unexpected tokens, expected one of `::$ident` `::{`, `exclude_parts`, `use_parts`, `=`, `,` --> $DIR/invalid_token_after_module.rs:9:18 | 9 | system: System ? diff --git a/frame/support/test/tests/construct_runtime_ui/old_unsupported_pallet_decl.rs b/frame/support/test/tests/construct_runtime_ui/old_unsupported_pallet_decl.rs new file mode 100644 index 000000000000..706d444f2359 --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/old_unsupported_pallet_decl.rs @@ -0,0 +1,26 @@ +use frame_support::construct_runtime; + +mod pallet_old { + pub trait Config: frame_system::Config {} + + decl_storage! { + trait Store for Module as Example {} + } + + decl_module! { + pub struct Module for enum Call where origin: T::Origin {} + } + +} +construct_runtime! { + pub enum Runtime where + UncheckedExtrinsic = UncheckedExtrinsic, + Block = Block, + NodeBlock = Block, + { + System: frame_system, + OldPallet: pallet_old, + } +} + +fn main() {} diff --git a/frame/support/test/tests/construct_runtime_ui/old_unsupported_pallet_decl.stderr b/frame/support/test/tests/construct_runtime_ui/old_unsupported_pallet_decl.stderr new file mode 100644 index 000000000000..f8ec07e00106 --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/old_unsupported_pallet_decl.stderr @@ -0,0 +1,31 @@ +error[E0433]: failed to resolve: could not find `tt_default_parts` in `pallet_old` + --> $DIR/old_unsupported_pallet_decl.rs:15:1 + | +15 | / construct_runtime! { +16 | | pub enum Runtime where +17 | | UncheckedExtrinsic = UncheckedExtrinsic, +18 | | Block = Block, +... | +23 | | } +24 | | } + | |_^ could not find `tt_default_parts` in `pallet_old` + | + = note: this error originates in the macro `construct_runtime` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: cannot find macro `decl_storage` in this scope + --> $DIR/old_unsupported_pallet_decl.rs:6:2 + | +6 | decl_storage! { + | ^^^^^^^^^^^^ + | + = note: consider importing this macro: + frame_support::decl_storage + +error: cannot find macro `decl_module` in this scope + --> $DIR/old_unsupported_pallet_decl.rs:10:2 + | +10 | decl_module! { + | ^^^^^^^^^^^ + | + = note: consider importing this macro: + frame_support::decl_module diff --git a/frame/support/test/tests/construct_runtime_ui/use_undefined_part.rs b/frame/support/test/tests/construct_runtime_ui/use_undefined_part.rs new file mode 100644 index 000000000000..1664dcc42b75 --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/use_undefined_part.rs @@ -0,0 +1,38 @@ +use frame_support::construct_runtime; +use sp_runtime::{generic, traits::BlakeTwo256}; +use sp_core::sr25519; + +#[frame_support::pallet] +mod pallet { + use frame_support::pallet_prelude::*; + + #[pallet::config] + pub trait Config: frame_system::Config {} + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::storage] + type Foo = StorageValue; +} + +pub type Signature = sr25519::Signature; +pub type BlockNumber = u64; +pub type Header = generic::Header; +pub type Block = generic::Block; +pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; + +impl pallet::Config for Runtime {} + +construct_runtime! { + pub enum Runtime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + System: system::{Pallet, Call, Storage, Config, Event}, + Pallet: pallet use_parts { Call }, + } +} + +fn main() {} diff --git a/frame/support/test/tests/construct_runtime_ui/use_undefined_part.stderr b/frame/support/test/tests/construct_runtime_ui/use_undefined_part.stderr new file mode 100644 index 000000000000..ed41f0ce673a --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/use_undefined_part.stderr @@ -0,0 +1,28 @@ +error: Invalid pallet part specified, the pallet `Pallet` doesn't have the `Call` part. Available parts are: `Pallet`, `Storage`. + --> $DIR/use_undefined_part.rs:34:30 + | +34 | Pallet: pallet use_parts { Call }, + | ^^^^ + +error[E0412]: cannot find type `Call` in this scope + --> $DIR/use_undefined_part.rs:23:64 + | +23 | pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; + | ^^^^ not found in this scope + | +help: consider importing one of these items + | +1 | use crate::pallet::Call; + | +1 | use frame_support_test::Call; + | +1 | use frame_system::Call; + | +1 | use test_pallet::Call; + | + +error[E0412]: cannot find type `Runtime` in this scope + --> $DIR/use_undefined_part.rs:25:25 + | +25 | impl pallet::Config for Runtime {} + | ^^^^^^^ not found in this scope diff --git a/frame/support/test/tests/pallet.rs b/frame/support/test/tests/pallet.rs index dc72be3ebdd4..a314f576187d 100644 --- a/frame/support/test/tests/pallet.rs +++ b/frame/support/test/tests/pallet.rs @@ -509,6 +509,18 @@ pub mod pallet3 { pub struct Pallet(_); } +#[frame_support::pallet] +pub mod pallet4 { + #[pallet::config] + pub trait Config: frame_system::Config {} + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::call] + impl Pallet {} +} + frame_support::parameter_types!( pub const MyGetParam: u32 = 10; pub const MyGetParam2: u32 = 11; @@ -553,6 +565,8 @@ impl pallet2::Config for Runtime { type Event = Event; } +impl pallet4::Config for Runtime {} + pub type Header = sp_runtime::generic::Header; pub type Block = sp_runtime::generic::Block; pub type UncheckedExtrinsic = sp_runtime::generic::UncheckedExtrinsic; @@ -563,12 +577,21 @@ frame_support::construct_runtime!( NodeBlock = Block, UncheckedExtrinsic = UncheckedExtrinsic { - System: frame_system::{Call, Event}, - Example: pallet::{Pallet, Call, Event, Config, Storage, Inherent, Origin, ValidateUnsigned}, - Example2: pallet2::{Pallet, Call, Event, Config, Storage}, + // Exclude part `Storage` in order not to check its metadata in tests. + System: frame_system exclude_parts { Pallet, Storage }, + Example: pallet, + Example2: pallet2 exclude_parts { Call }, + Example4: pallet4 use_parts { Call }, } ); +// Test that the part `Call` is excluded from Example2 and included in Example4. +fn _ensure_call_is_correctly_excluded_and_included(call: Call) { + match call { + Call::System(_) | Call::Example(_) | Call::Example4(_) => (), + } +} + #[test] fn transactional_works() { TestExternalities::default().execute_with(|| { @@ -995,8 +1018,8 @@ fn migrate_from_pallet_version_to_storage_version() { AllPalletsWithSystem, >(&db_weight); - // 3 pallets, 2 writes and every write costs 5 weight. - assert_eq!(3 * 2 * 5, weight); + // 4 pallets, 2 writes and every write costs 5 weight. + assert_eq!(4 * 2 * 5, weight); // All pallet versions should be removed assert!(sp_io::storage::get(&pallet_version_key(Example::name())).is_none()); @@ -1268,7 +1291,7 @@ fn metadata() { }, ], }), - calls: Some(meta_type::>().into()), + calls: None, event: Some(PalletEventMetadata { ty: meta_type::() }), constants: vec![], error: None, diff --git a/frame/support/test/tests/pallet_instance.rs b/frame/support/test/tests/pallet_instance.rs index 3a1009402d6f..c031ac9fe1bf 100644 --- a/frame/support/test/tests/pallet_instance.rs +++ b/frame/support/test/tests/pallet_instance.rs @@ -302,13 +302,12 @@ frame_support::construct_runtime!( NodeBlock = Block, UncheckedExtrinsic = UncheckedExtrinsic { - System: frame_system::{Pallet, Call, Event}, - Example: pallet::{Pallet, Call, Event, Config, Storage, Inherent, Origin, ValidateUnsigned}, - Instance1Example: pallet::::{ - Pallet, Call, Event, Config, Storage, Inherent, Origin, ValidateUnsigned - }, - Example2: pallet2::{Pallet, Event, Config, Storage}, - Instance1Example2: pallet2::::{Pallet, Event, Config, Storage}, + // Exclude part `Storage` in order not to check its metadata in tests. + System: frame_system exclude_parts { Storage }, + Example: pallet, + Instance1Example: pallet::, + Example2: pallet2, + Instance1Example2: pallet2::, } ); @@ -601,7 +600,7 @@ fn metadata() { let system_pallet_metadata = PalletMetadata { index: 0, name: "System", - storage: None, + storage: None, // The storage metadatas have been excluded. calls: Some(scale_info::meta_type::>().into()), event: Some(PalletEventMetadata { ty: scale_info::meta_type::>(), From b63e1c525baa33097ceccbd2ca828acbd36b0262 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Sun, 31 Oct 2021 19:13:19 +0100 Subject: [PATCH 116/695] Offchain-worker: Make it possible to disable http support (#10087) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Offchain-worker: Make it possible to disable http support If a chain doesn't require http support in its offchain workers, this pr enables them to disable the http support. * Switch to bitflags * Use Capabilities * Update client/offchain/src/lib.rs Co-authored-by: Tomasz Drwięga * Fix test * Update client/offchain/src/lib.rs Co-authored-by: Tomasz Drwięga Co-authored-by: Tomasz Drwięga --- Cargo.lock | 2 + client/api/src/execution_extensions.rs | 10 +- client/offchain/Cargo.toml | 1 + client/offchain/src/api.rs | 12 +-- client/offchain/src/api/http.rs | 49 +++++++++- client/offchain/src/lib.rs | 43 ++++++--- primitives/core/Cargo.toml | 1 + primitives/core/src/lib.rs | 12 +-- primitives/core/src/offchain/mod.rs | 128 ++++++++++--------------- 9 files changed, 144 insertions(+), 114 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 84ad0c0a563c..666fe6e45183 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8184,6 +8184,7 @@ dependencies = [ "lazy_static", "log 0.4.14", "num_cpus", + "once_cell", "parity-scale-codec", "parking_lot 0.11.1", "rand 0.7.3", @@ -9232,6 +9233,7 @@ name = "sp-core" version = "4.0.0-dev" dependencies = [ "base58", + "bitflags", "blake2-rfc", "byteorder", "criterion", diff --git a/client/api/src/execution_extensions.rs b/client/api/src/execution_extensions.rs index ec44294b8a96..56e70cc2b6a6 100644 --- a/client/api/src/execution_extensions.rs +++ b/client/api/src/execution_extensions.rs @@ -161,13 +161,13 @@ impl ExecutionExtensions { let mut extensions = self.extensions_factory.read().extensions_for(capabilities); - if capabilities.has(offchain::Capability::Keystore) { + if capabilities.contains(offchain::Capabilities::KEYSTORE) { if let Some(ref keystore) = self.keystore { extensions.register(KeystoreExt(keystore.clone())); } } - if capabilities.has(offchain::Capability::TransactionPool) { + if capabilities.contains(offchain::Capabilities::TRANSACTION_POOL) { if let Some(pool) = self.transaction_pool.read().as_ref().and_then(|x| x.upgrade()) { extensions .register(TransactionPoolExt( @@ -176,8 +176,8 @@ impl ExecutionExtensions { } } - if capabilities.has(offchain::Capability::OffchainDbRead) || - capabilities.has(offchain::Capability::OffchainDbWrite) + if capabilities.contains(offchain::Capabilities::OFFCHAIN_DB_READ) || + capabilities.contains(offchain::Capabilities::OFFCHAIN_DB_WRITE) { if let Some(offchain_db) = self.offchain_db.as_ref() { extensions.register(OffchainDbExt::new(offchain::LimitedExternalities::new( @@ -210,7 +210,7 @@ impl ExecutionExtensions { ExecutionContext::BlockConstruction => self.strategies.block_construction.get_manager(), ExecutionContext::Syncing => self.strategies.syncing.get_manager(), ExecutionContext::Importing => self.strategies.importing.get_manager(), - ExecutionContext::OffchainCall(Some((_, capabilities))) if capabilities.has_all() => + ExecutionContext::OffchainCall(Some((_, capabilities))) if capabilities.is_all() => self.strategies.offchain_worker.get_manager(), ExecutionContext::OffchainCall(_) => self.strategies.other.get_manager(), }; diff --git a/client/offchain/Cargo.toml b/client/offchain/Cargo.toml index 146ce07e1303..104a0e61f318 100644 --- a/client/offchain/Cargo.toml +++ b/client/offchain/Cargo.toml @@ -33,6 +33,7 @@ sc-utils = { version = "4.0.0-dev", path = "../utils" } threadpool = "1.7" hyper = "0.14.11" hyper-rustls = "0.22.1" +once_cell = "1.8" [dev-dependencies] sc-client-db = { version = "0.10.0-dev", default-features = true, path = "../db" } diff --git a/client/offchain/src/api.rs b/client/offchain/src/api.rs index b2276a852372..07136d1815b9 100644 --- a/client/offchain/src/api.rs +++ b/client/offchain/src/api.rs @@ -298,9 +298,9 @@ impl AsyncApi { pub fn new( network_provider: Arc, is_validator: bool, - shared_client: SharedClient, + shared_http_client: SharedClient, ) -> (Api, Self) { - let (http_api, http_worker) = http::http(shared_client); + let (http_api, http_worker) = http::http(shared_http_client); let api = Api { network_provider, is_validator, http: http_api }; @@ -310,10 +310,8 @@ impl AsyncApi { } /// Run a processing task for the API - pub fn process(mut self) -> impl Future { - let http = self.http.take().expect("Take invoked only once."); - - http + pub fn process(self) -> impl Future { + self.http.expect("`process` is only called once; qed") } } @@ -328,7 +326,7 @@ mod tests { time::SystemTime, }; - struct TestNetwork(); + pub(super) struct TestNetwork(); impl NetworkProvider for TestNetwork { fn set_authorized_peers(&self, _peers: HashSet) { diff --git a/client/offchain/src/api/http.rs b/client/offchain/src/api/http.rs index 31f7d60e34ff..a2975bad1652 100644 --- a/client/offchain/src/api/http.rs +++ b/client/offchain/src/api/http.rs @@ -34,6 +34,7 @@ use futures::{channel::mpsc, future, prelude::*}; use hyper::{client, Body, Client as HyperClient}; use hyper_rustls::HttpsConnector; use log::error; +use once_cell::sync::Lazy; use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender}; use sp_core::offchain::{HttpError, HttpRequestId, HttpRequestStatus, Timestamp}; use std::{ @@ -47,11 +48,13 @@ use std::{ /// Wrapper struct used for keeping the hyper_rustls client running. #[derive(Clone)] -pub struct SharedClient(Arc, Body>>); +pub struct SharedClient(Arc, Body>>>); impl SharedClient { pub fn new() -> Self { - Self(Arc::new(HyperClient::builder().build(HttpsConnector::with_native_roots()))) + Self(Arc::new(Lazy::new(|| { + HyperClient::builder().build(HttpsConnector::with_native_roots()) + }))) } } @@ -567,7 +570,7 @@ pub struct HttpWorker { /// Used to receive messages from the `HttpApi`. from_api: TracingUnboundedReceiver, /// The engine that runs HTTP requests. - http_client: Arc, Body>>, + http_client: Arc, Body>>>, /// HTTP requests that are being worked on by the engine. requests: Vec<(HttpRequestId, HttpWorkerRequest)>, } @@ -697,12 +700,15 @@ impl fmt::Debug for HttpWorkerRequest { #[cfg(test)] mod tests { - use super::{http, SharedClient}; + use super::{ + super::{tests::TestNetwork, AsyncApi}, + *, + }; use crate::api::timestamp; use core::convert::Infallible; use futures::{future, StreamExt}; use lazy_static::lazy_static; - use sp_core::offchain::{Duration, HttpError, HttpRequestId, HttpRequestStatus}; + use sp_core::offchain::{Duration, Externalities, HttpError, HttpRequestId, HttpRequestStatus}; // Using lazy_static to avoid spawning lots of different SharedClients, // as spawning a SharedClient is CPU-intensive and opens lots of fds. @@ -1006,4 +1012,37 @@ mod tests { } } } + + #[test] + fn shared_http_client_is_only_initialized_on_access() { + let shared_client = SharedClient::new(); + + { + let mock = Arc::new(TestNetwork()); + let (mut api, async_api) = AsyncApi::new(mock, false, shared_client.clone()); + api.timestamp(); + + futures::executor::block_on(async move { + assert!(futures::poll!(async_api.process()).is_pending()); + }); + } + + // Check that the http client wasn't initialized, because it wasn't used. + assert!(Lazy::into_value(Arc::try_unwrap(shared_client.0).unwrap()).is_err()); + + let shared_client = SharedClient::new(); + + { + let mock = Arc::new(TestNetwork()); + let (mut api, async_api) = AsyncApi::new(mock, false, shared_client.clone()); + let id = api.http_request_start("lol", "nope", &[]).unwrap(); + api.http_request_write_body(id, &[], None).unwrap(); + futures::executor::block_on(async move { + assert!(futures::poll!(async_api.process()).is_pending()); + }); + } + + // Check that the http client initialized, because it was used. + assert!(Lazy::into_value(Arc::try_unwrap(shared_client.0).unwrap()).is_ok()); + } } diff --git a/client/offchain/src/lib.rs b/client/offchain/src/lib.rs index be6e4238ca5f..a77fd17a2c8b 100644 --- a/client/offchain/src/lib.rs +++ b/client/offchain/src/lib.rs @@ -81,18 +81,31 @@ where } } +/// Options for [`OffchainWorkers`] +pub struct OffchainWorkerOptions { + /// Enable http requests from offchain workers? + /// + /// If not enabled, any http request will panic. + pub enable_http_requests: bool, +} + /// An offchain workers manager. pub struct OffchainWorkers { client: Arc, _block: PhantomData, thread_pool: Mutex, - shared_client: api::SharedClient, + shared_http_client: api::SharedClient, + enable_http: bool, } impl OffchainWorkers { - /// Creates new `OffchainWorkers`. + /// Creates new [`OffchainWorkers`]. pub fn new(client: Arc) -> Self { - let shared_client = api::SharedClient::new(); + Self::new_with_options(client, OffchainWorkerOptions { enable_http_requests: true }) + } + + /// Creates new [`OffchainWorkers`] using the given `options`. + pub fn new_with_options(client: Arc, options: OffchainWorkerOptions) -> Self { Self { client, _block: PhantomData, @@ -100,7 +113,8 @@ impl OffchainWorkers { "offchain-worker".into(), num_cpus::get(), )), - shared_client, + shared_http_client: api::SharedClient::new(), + enable_http: options.enable_http_requests, } } } @@ -140,18 +154,22 @@ where }, }; debug!("Checking offchain workers at {:?}: version:{}", at, version); - if version > 0 { + let process = (version > 0).then(|| { let (api, runner) = - api::AsyncApi::new(network_provider, is_validator, self.shared_client.clone()); + api::AsyncApi::new(network_provider, is_validator, self.shared_http_client.clone()); debug!("Spawning offchain workers at {:?}", at); let header = header.clone(); let client = self.client.clone(); + + let mut capabilities = offchain::Capabilities::all(); + + capabilities.set(offchain::Capabilities::HTTP, self.enable_http); self.spawn_worker(move || { let runtime = client.runtime_api(); let api = Box::new(api); debug!("Running offchain workers at {:?}", at); - let context = - ExecutionContext::OffchainCall(Some((api, offchain::Capabilities::all()))); + + let context = ExecutionContext::OffchainCall(Some((api, capabilities))); let run = if version == 2 { runtime.offchain_worker_with_context(&at, context, &header) } else { @@ -166,9 +184,12 @@ where log::error!("Error running offchain workers at {:?}: {:?}", at, e); } }); - futures::future::Either::Left(runner.process()) - } else { - futures::future::Either::Right(futures::future::ready(())) + + runner.process() + }); + + async move { + futures::future::OptionFuture::from(process).await; } } diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index dd721d744f57..14a76e248244 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -49,6 +49,7 @@ parity-util-mem = { version = "0.10.0", default-features = false, features = [ futures = { version = "0.3.1", optional = true } dyn-clonable = { version = "0.9.0", optional = true } thiserror = { version = "1.0.21", optional = true } +bitflags = "1.3" # full crypto ed25519-dalek = { version = "1.0.1", default-features = false, features = [ diff --git a/primitives/core/src/lib.rs b/primitives/core/src/lib.rs index a6229fe43a1a..fd752397cd9a 100644 --- a/primitives/core/src/lib.rs +++ b/primitives/core/src/lib.rs @@ -118,15 +118,13 @@ impl ExecutionContext { use ExecutionContext::*; match self { - Importing | Syncing | BlockConstruction => offchain::Capabilities::none(), + Importing | Syncing | BlockConstruction => offchain::Capabilities::empty(), // Enable keystore, transaction pool and Offchain DB reads by default for offchain // calls. - OffchainCall(None) => [ - offchain::Capability::Keystore, - offchain::Capability::OffchainDbRead, - offchain::Capability::TransactionPool, - ][..] - .into(), + OffchainCall(None) => + offchain::Capabilities::KEYSTORE | + offchain::Capabilities::OFFCHAIN_DB_READ | + offchain::Capabilities::TRANSACTION_POOL, OffchainCall(Some((_, capabilities))) => *capabilities, } } diff --git a/primitives/core/src/offchain/mod.rs b/primitives/core/src/offchain/mod.rs index 640f4d2583b7..dfe23c1ff8f1 100644 --- a/primitives/core/src/offchain/mod.rs +++ b/primitives/core/src/offchain/mod.rs @@ -258,65 +258,35 @@ impl Timestamp { } } -/// Execution context extra capabilities. -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -#[repr(u8)] -pub enum Capability { - /// Access to transaction pool. - TransactionPool = 1, - /// External http calls. - Http = 2, - /// Keystore access. - Keystore = 4, - /// Randomness source. - Randomness = 8, - /// Access to opaque network state. - NetworkState = 16, - /// Access to offchain worker DB (read only). - OffchainDbRead = 32, - /// Access to offchain worker DB (writes). - OffchainDbWrite = 64, - /// Manage the authorized nodes - NodeAuthorization = 128, -} - -/// A set of capabilities -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub struct Capabilities(u8); - -impl Capabilities { - /// Return an object representing an empty set of capabilities. - pub fn none() -> Self { - Self(0) - } - - /// Return an object representing all capabilities enabled. - pub fn all() -> Self { - Self(u8::MAX) +bitflags::bitflags! { + /// Execution context extra capabilities. + pub struct Capabilities: u32 { + /// Access to transaction pool. + const TRANSACTION_POOL = 0b0000_0001; + /// External http calls. + const HTTP = 0b0000_0010; + /// Keystore access. + const KEYSTORE = 0b0000_0100; + /// Randomness source. + const RANDOMNESS = 0b0000_1000; + /// Access to opaque network state. + const NETWORK_STATE = 0b0001_0000; + /// Access to offchain worker DB (read only). + const OFFCHAIN_DB_READ = 0b0010_0000; + /// Access to offchain worker DB (writes). + const OFFCHAIN_DB_WRITE = 0b0100_0000; + /// Manage the authorized nodes + const NODE_AUTHORIZATION = 0b1000_0000; } +} +impl Capabilities { /// Return capabilities for rich offchain calls. /// /// Those calls should be allowed to sign and submit transactions /// and access offchain workers database (but read only!). pub fn rich_offchain_call() -> Self { - [Capability::TransactionPool, Capability::Keystore, Capability::OffchainDbRead][..].into() - } - - /// Check if particular capability is enabled. - pub fn has(&self, capability: Capability) -> bool { - self.0 & capability as u8 != 0 - } - - /// Check if this capability object represents all capabilities. - pub fn has_all(&self) -> bool { - self == &Capabilities::all() - } -} - -impl<'a> From<&'a [Capability]> for Capabilities { - fn from(list: &'a [Capability]) -> Self { - Capabilities(list.iter().fold(0_u8, |a, b| a | *b as u8)) + Capabilities::TRANSACTION_POOL | Capabilities::KEYSTORE | Capabilities::OFFCHAIN_DB_READ } } @@ -552,8 +522,8 @@ impl LimitedExternalities { /// Check if given capability is allowed. /// /// Panics in case it is not. - fn check(&self, capability: Capability, name: &'static str) { - if !self.capabilities.has(capability) { + fn check(&self, capability: Capabilities, name: &'static str) { + if !self.capabilities.contains(capability) { panic!("Accessing a forbidden API: {}. No: {:?} capability.", name, capability); } } @@ -561,27 +531,27 @@ impl LimitedExternalities { impl Externalities for LimitedExternalities { fn is_validator(&self) -> bool { - self.check(Capability::Keystore, "is_validator"); + self.check(Capabilities::KEYSTORE, "is_validator"); self.externalities.is_validator() } fn network_state(&self) -> Result { - self.check(Capability::NetworkState, "network_state"); + self.check(Capabilities::NETWORK_STATE, "network_state"); self.externalities.network_state() } fn timestamp(&mut self) -> Timestamp { - self.check(Capability::Http, "timestamp"); + self.check(Capabilities::HTTP, "timestamp"); self.externalities.timestamp() } fn sleep_until(&mut self, deadline: Timestamp) { - self.check(Capability::Http, "sleep_until"); + self.check(Capabilities::HTTP, "sleep_until"); self.externalities.sleep_until(deadline) } fn random_seed(&mut self) -> [u8; 32] { - self.check(Capability::Randomness, "random_seed"); + self.check(Capabilities::RANDOMNESS, "random_seed"); self.externalities.random_seed() } @@ -591,7 +561,7 @@ impl Externalities for LimitedExternalities { uri: &str, meta: &[u8], ) -> Result { - self.check(Capability::Http, "http_request_start"); + self.check(Capabilities::HTTP, "http_request_start"); self.externalities.http_request_start(method, uri, meta) } @@ -601,7 +571,7 @@ impl Externalities for LimitedExternalities { name: &str, value: &str, ) -> Result<(), ()> { - self.check(Capability::Http, "http_request_add_header"); + self.check(Capabilities::HTTP, "http_request_add_header"); self.externalities.http_request_add_header(request_id, name, value) } @@ -611,7 +581,7 @@ impl Externalities for LimitedExternalities { chunk: &[u8], deadline: Option, ) -> Result<(), HttpError> { - self.check(Capability::Http, "http_request_write_body"); + self.check(Capabilities::HTTP, "http_request_write_body"); self.externalities.http_request_write_body(request_id, chunk, deadline) } @@ -620,12 +590,12 @@ impl Externalities for LimitedExternalities { ids: &[HttpRequestId], deadline: Option, ) -> Vec { - self.check(Capability::Http, "http_response_wait"); + self.check(Capabilities::HTTP, "http_response_wait"); self.externalities.http_response_wait(ids, deadline) } fn http_response_headers(&mut self, request_id: HttpRequestId) -> Vec<(Vec, Vec)> { - self.check(Capability::Http, "http_response_headers"); + self.check(Capabilities::HTTP, "http_response_headers"); self.externalities.http_response_headers(request_id) } @@ -635,12 +605,12 @@ impl Externalities for LimitedExternalities { buffer: &mut [u8], deadline: Option, ) -> Result { - self.check(Capability::Http, "http_response_read_body"); + self.check(Capabilities::HTTP, "http_response_read_body"); self.externalities.http_response_read_body(request_id, buffer, deadline) } fn set_authorized_nodes(&mut self, nodes: Vec, authorized_only: bool) { - self.check(Capability::NodeAuthorization, "set_authorized_nodes"); + self.check(Capabilities::NODE_AUTHORIZATION, "set_authorized_nodes"); self.externalities.set_authorized_nodes(nodes, authorized_only) } } @@ -724,12 +694,12 @@ impl DbExternalities for Box { impl DbExternalities for LimitedExternalities { fn local_storage_set(&mut self, kind: StorageKind, key: &[u8], value: &[u8]) { - self.check(Capability::OffchainDbWrite, "local_storage_set"); + self.check(Capabilities::OFFCHAIN_DB_WRITE, "local_storage_set"); self.externalities.local_storage_set(kind, key, value) } fn local_storage_clear(&mut self, kind: StorageKind, key: &[u8]) { - self.check(Capability::OffchainDbWrite, "local_storage_clear"); + self.check(Capabilities::OFFCHAIN_DB_WRITE, "local_storage_clear"); self.externalities.local_storage_clear(kind, key) } @@ -740,13 +710,13 @@ impl DbExternalities for LimitedExternalities { old_value: Option<&[u8]>, new_value: &[u8], ) -> bool { - self.check(Capability::OffchainDbWrite, "local_storage_compare_and_set"); + self.check(Capabilities::OFFCHAIN_DB_WRITE, "local_storage_compare_and_set"); self.externalities .local_storage_compare_and_set(kind, key, old_value, new_value) } fn local_storage_get(&mut self, kind: StorageKind, key: &[u8]) -> Option> { - self.check(Capability::OffchainDbRead, "local_storage_get"); + self.check(Capabilities::OFFCHAIN_DB_READ, "local_storage_get"); self.externalities.local_storage_get(kind, key) } } @@ -815,15 +785,15 @@ mod tests { #[test] fn capabilities() { - let none = Capabilities::none(); + let none = Capabilities::empty(); let all = Capabilities::all(); - let some = Capabilities::from(&[Capability::Keystore, Capability::Randomness][..]); - - assert!(!none.has(Capability::Keystore)); - assert!(all.has(Capability::Keystore)); - assert!(some.has(Capability::Keystore)); - assert!(!none.has(Capability::TransactionPool)); - assert!(all.has(Capability::TransactionPool)); - assert!(!some.has(Capability::TransactionPool)); + let some = Capabilities::KEYSTORE | Capabilities::RANDOMNESS; + + assert!(!none.contains(Capabilities::KEYSTORE)); + assert!(all.contains(Capabilities::KEYSTORE)); + assert!(some.contains(Capabilities::KEYSTORE)); + assert!(!none.contains(Capabilities::TRANSACTION_POOL)); + assert!(all.contains(Capabilities::TRANSACTION_POOL)); + assert!(!some.contains(Capabilities::TRANSACTION_POOL)); } } From 26d69bcbe26f6b463e9374e1b1c54c3067fb6131 Mon Sep 17 00:00:00 2001 From: Zeke Mostov <32168567+emostov@users.noreply.github.com> Date: Sun, 31 Oct 2021 22:10:13 +0100 Subject: [PATCH 117/695] Fuzzer for Pallet Bags List (#9851) * Fuzzer for Pallet Bags List * Some small updates * Fuzzer for Pallet Bags List This PR adds a fuzzer for the `SortedListProvider` API exposed by pallet-bags-list. * Feature gate code NOT used by fuzz feature * Create Enum for list actions * fix some small mistakes * try and make CI happy * fmt * Do not insert before updating * clean up some misc. comments * marginally improve Node::sanity_check * Change ID_RANGE to 25_000 * comma * try improve correct feature gating so no unused code Co-authored-by: thiolliere --- Cargo.lock | 10 ++++ Cargo.toml | 1 + frame/bags-list/Cargo.toml | 6 ++ frame/bags-list/fuzzer/.gitignore | 2 + frame/bags-list/fuzzer/Cargo.toml | 22 ++++++++ frame/bags-list/fuzzer/src/main.rs | 88 ++++++++++++++++++++++++++++++ frame/bags-list/src/lib.rs | 4 +- frame/bags-list/src/list/mod.rs | 14 +++-- frame/bags-list/src/mock.rs | 7 ++- 9 files changed, 144 insertions(+), 10 deletions(-) create mode 100644 frame/bags-list/fuzzer/.gitignore create mode 100644 frame/bags-list/fuzzer/Cargo.toml create mode 100644 frame/bags-list/fuzzer/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 666fe6e45183..3434e01d13cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5180,6 +5180,16 @@ dependencies = [ "sp-tracing", ] +[[package]] +name = "pallet-bags-list-fuzzer" +version = "4.0.0-dev" +dependencies = [ + "frame-election-provider-support", + "honggfuzz", + "pallet-bags-list", + "rand 0.8.4", +] + [[package]] name = "pallet-balances" version = "4.0.0-dev" diff --git a/Cargo.toml b/Cargo.toml index 4a228203159e..743e0f706664 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -135,6 +135,7 @@ members = [ "frame/utility", "frame/vesting", "frame/bags-list", + "frame/bags-list/fuzzer", "primitives/api", "primitives/api/proc-macro", "primitives/api/test", diff --git a/frame/bags-list/Cargo.toml b/frame/bags-list/Cargo.toml index cd06ce4a6998..372dc87e212e 100644 --- a/frame/bags-list/Cargo.toml +++ b/frame/bags-list/Cargo.toml @@ -63,4 +63,10 @@ runtime-benchmarks = [ "sp-tracing", "frame-election-provider-support/runtime-benchmarks", ] +fuzz = [ + "sp-core", + "sp-io", + "pallet-balances", + "sp-tracing", +] diff --git a/frame/bags-list/fuzzer/.gitignore b/frame/bags-list/fuzzer/.gitignore new file mode 100644 index 000000000000..3ebcb104d4a5 --- /dev/null +++ b/frame/bags-list/fuzzer/.gitignore @@ -0,0 +1,2 @@ +hfuzz_target +hfuzz_workspace diff --git a/frame/bags-list/fuzzer/Cargo.toml b/frame/bags-list/fuzzer/Cargo.toml new file mode 100644 index 000000000000..171e0e7af70c --- /dev/null +++ b/frame/bags-list/fuzzer/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "pallet-bags-list-fuzzer" +version = "4.0.0-dev" +authors = ["Parity Technologies "] +edition = "2018" +license = "Apache-2.0" +homepage = "https://substrate.dev" +repository = "https://github.com/paritytech/substrate/" +description = "Fuzzer for FRAME pallet bags list" +readme = "README.md" +publish = false + +[dependencies] +honggfuzz = "0.5" +rand = { version = "0.8", features = ["std", "small_rng"] } + +pallet-bags-list = { version = "4.0.0-dev", features = ["fuzz"], path = ".." } +frame-election-provider-support = { version = "4.0.0-dev", path = "../../election-provider-support", features = ["runtime-benchmarks"] } + +[[bin]] +name = "bags-list" +path = "src/main.rs" diff --git a/frame/bags-list/fuzzer/src/main.rs b/frame/bags-list/fuzzer/src/main.rs new file mode 100644 index 000000000000..02a2003b9a71 --- /dev/null +++ b/frame/bags-list/fuzzer/src/main.rs @@ -0,0 +1,88 @@ +// This file is part of Substrate. + +// Copyright (C) 2021 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. + +//! # Running +//! Running this fuzzer can be done with `cargo hfuzz run bags-list`. `honggfuzz` CLI options can +//! be used by setting `HFUZZ_RUN_ARGS`, such as `-n 4` to use 4 threads. +//! +//! # Debugging a panic +//! Once a panic is found, it can be debugged with +//! `cargo hfuzz run-debug fixed_point hfuzz_workspace/bags_list/*.fuzz`. +//! +//! # More information +//! More information about `honggfuzz` can be found +//! [here](https://docs.rs/honggfuzz/). + +use frame_election_provider_support::{SortedListProvider, VoteWeight}; +use honggfuzz::fuzz; +use pallet_bags_list::mock::{AccountId, BagsList, ExtBuilder}; +use std::convert::From; + +const ID_RANGE: AccountId = 25_000; + +/// Actions of a `SortedListProvider` that we fuzz. +enum Action { + Insert, + Update, + Remove, +} + +impl From for Action { + fn from(v: u32) -> Self { + let num_variants = Self::Remove as u32 + 1; + match v % num_variants { + _x if _x == Action::Insert as u32 => Action::Insert, + _x if _x == Action::Update as u32 => Action::Update, + _x if _x == Action::Remove as u32 => Action::Remove, + _ => unreachable!(), + } + } +} + +fn main() { + ExtBuilder::default().build_and_execute(|| loop { + fuzz!(|data: (AccountId, VoteWeight, u32)| { + let (account_id_seed, vote_weight, action_seed) = data; + + let id = account_id_seed % ID_RANGE; + let action = Action::from(action_seed); + + match action { + Action::Insert => { + if BagsList::on_insert(id.clone(), vote_weight).is_err() { + // this was a duplicate id, which is ok. We can just update it. + BagsList::on_update(&id, vote_weight); + } + assert!(BagsList::contains(&id)); + }, + Action::Update => { + let already_contains = BagsList::contains(&id); + BagsList::on_update(&id, vote_weight); + if already_contains { + assert!(BagsList::contains(&id)); + } + }, + Action::Remove => { + BagsList::on_remove(&id); + assert!(!BagsList::contains(&id)); + }, + } + + assert!(BagsList::sanity_check().is_ok()); + }) + }); +} diff --git a/frame/bags-list/src/lib.rs b/frame/bags-list/src/lib.rs index 4202a4d49989..10a692e8b3f9 100644 --- a/frame/bags-list/src/lib.rs +++ b/frame/bags-list/src/lib.rs @@ -59,8 +59,8 @@ use sp_std::prelude::*; mod benchmarks; mod list; -#[cfg(test)] -mod mock; +#[cfg(any(test, feature = "fuzz"))] +pub mod mock; #[cfg(test)] mod tests; pub mod weights; diff --git a/frame/bags-list/src/list/mod.rs b/frame/bags-list/src/list/mod.rs index 3f55f2227191..057565e645f9 100644 --- a/frame/bags-list/src/list/mod.rs +++ b/frame/bags-list/src/list/mod.rs @@ -391,8 +391,8 @@ impl List { /// /// * there are no duplicate ids, /// * length of this list is in sync with `CounterForListNodes`, - /// * and sanity-checks all bags. This will cascade down all the checks and makes sure all bags - /// are checked per *any* update to `List`. + /// * and sanity-checks all bags and nodes. This will cascade down all the checks and makes sure + /// all bags and nodes are checked per *any* update to `List`. #[cfg(feature = "std")] pub(crate) fn sanity_check() -> Result<(), &'static str> { use frame_support::ensure; @@ -414,7 +414,6 @@ impl List { let thresholds = T::BagThresholds::get().iter().copied(); let thresholds: Vec = if thresholds.clone().last() == Some(VoteWeight::MAX) { // in the event that they included it, we don't need to make any changes - // Box::new(thresholds.collect() thresholds.collect() } else { // otherwise, insert it here. @@ -774,10 +773,13 @@ impl Node { "node does not exist in the expected bag" ); + let non_terminal_check = !self.is_terminal() && + expected_bag.head.as_ref() != Some(id) && + expected_bag.tail.as_ref() != Some(id); + let terminal_check = + expected_bag.head.as_ref() == Some(id) || expected_bag.tail.as_ref() == Some(id); frame_support::ensure!( - !self.is_terminal() || - expected_bag.head.as_ref() == Some(id) || - expected_bag.tail.as_ref() == Some(id), + non_terminal_check || terminal_check, "a terminal node is neither its bag head or tail" ); diff --git a/frame/bags-list/src/mock.rs b/frame/bags-list/src/mock.rs index a6ab35896b1e..45eb1d85abe3 100644 --- a/frame/bags-list/src/mock.rs +++ b/frame/bags-list/src/mock.rs @@ -101,12 +101,13 @@ pub(crate) const GENESIS_IDS: [(AccountId, VoteWeight); 4] = [(1, 10), (2, 1_000), (3, 1_000), (4, 1_000)]; #[derive(Default)] -pub(crate) struct ExtBuilder { +pub struct ExtBuilder { ids: Vec<(AccountId, VoteWeight)>, } impl ExtBuilder { /// Add some AccountIds to insert into `List`. + #[cfg(test)] pub(crate) fn add_ids(mut self, ids: Vec<(AccountId, VoteWeight)>) -> Self { self.ids = ids; self @@ -126,18 +127,20 @@ impl ExtBuilder { ext } - pub(crate) fn build_and_execute(self, test: impl FnOnce() -> ()) { + pub fn build_and_execute(self, test: impl FnOnce() -> ()) { self.build().execute_with(|| { test(); List::::sanity_check().expect("Sanity check post condition failed") }) } + #[cfg(test)] pub(crate) fn build_and_execute_no_post_check(self, test: impl FnOnce() -> ()) { self.build().execute_with(test) } } +#[cfg(test)] pub(crate) mod test_utils { use super::*; use list::Bag; From dc29596e7c90e84e90198dee24c296e930b58c33 Mon Sep 17 00:00:00 2001 From: Koute Date: Mon, 1 Nov 2021 17:46:32 +0900 Subject: [PATCH 118/695] Strip out control codes from the logged messages (#10081) * Strip out control codes from the logged messages * Also strip away C1 control codes * Add extra comments * Clear the buffer after flushing; rename `write` to `flush` * Move control code stripping into its own function * Also strip out control codes from panic messages * Also strip out Unicode left-to-right/right-to-left control codes --- Cargo.lock | 2 + client/tracing/src/logging/event_format.rs | 65 +++++++++++++++------- client/tracing/src/logging/mod.rs | 32 +++++++++++ primitives/panic-handler/Cargo.toml | 2 + primitives/panic-handler/src/lib.rs | 61 ++++++++++++++++++++ 5 files changed, 142 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3434e01d13cd..1ddf355c890d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9462,6 +9462,8 @@ name = "sp-panic-handler" version = "3.0.0" dependencies = [ "backtrace", + "lazy_static", + "regex", ] [[package]] diff --git a/client/tracing/src/logging/event_format.rs b/client/tracing/src/logging/event_format.rs index 5a21192d69c4..944901d803bd 100644 --- a/client/tracing/src/logging/event_format.rs +++ b/client/tracing/src/logging/event_format.rs @@ -62,7 +62,7 @@ where S: Subscriber + for<'a> LookupSpan<'a>, N: for<'a> FormatFields<'a> + 'static, { - let writer = &mut MaybeColorWriter::new(self.enable_color, writer); + let writer = &mut ControlCodeSanitizer::new(!self.enable_color, writer); let normalized_meta = event.normalized_metadata(); let meta = normalized_meta.as_ref().unwrap_or_else(|| event.metadata()); time::write(&self.timer, writer, self.enable_color)?; @@ -100,10 +100,18 @@ where } } + // The writer only sanitizes its output once it's flushed, so if we don't actually need + // to sanitize everything we need to flush out what was already buffered as-is and only + // force-sanitize what follows. + if !writer.sanitize { + writer.flush()?; + writer.sanitize = true; + } + ctx.format_fields(writer, event)?; writeln!(writer)?; - writer.write() + writer.flush() } } @@ -294,43 +302,60 @@ where } } -/// A writer that may write to `inner_writer` with colors. +/// A writer which (optionally) strips out terminal control codes from the logs. /// -/// This is used by [`EventFormat`] to kill colors when `enable_color` is `false`. +/// This is used by [`EventFormat`] to sanitize the log messages. /// -/// It is required to call [`MaybeColorWriter::write`] after all writes are done, +/// It is required to call [`ControlCodeSanitizer::flush`] after all writes are done, /// because the content of these writes is buffered and will only be written to the /// `inner_writer` at that point. -struct MaybeColorWriter<'a> { - enable_color: bool, +struct ControlCodeSanitizer<'a> { + sanitize: bool, buffer: String, inner_writer: &'a mut dyn fmt::Write, } -impl<'a> fmt::Write for MaybeColorWriter<'a> { +impl<'a> fmt::Write for ControlCodeSanitizer<'a> { fn write_str(&mut self, buf: &str) -> fmt::Result { self.buffer.push_str(buf); Ok(()) } } -impl<'a> MaybeColorWriter<'a> { +// NOTE: When making any changes here make sure to also change this function in `sp-panic-handler`. +fn strip_control_codes(input: &str) -> std::borrow::Cow { + lazy_static::lazy_static! { + static ref RE: Regex = Regex::new(r#"(?x) + \x1b\[[^m]+m| # VT100 escape codes + [ + \x00-\x09\x0B-\x1F # ASCII control codes / Unicode C0 control codes, except \n + \x7F # ASCII delete + \u{80}-\u{9F} # Unicode C1 control codes + \u{202A}-\u{202E} # Unicode left-to-right / right-to-left control characters + \u{2066}-\u{2069} # Same as above + ] + "#).expect("regex parsing doesn't fail; qed"); + } + + RE.replace_all(input, "") +} + +impl<'a> ControlCodeSanitizer<'a> { /// Creates a new instance. - fn new(enable_color: bool, inner_writer: &'a mut dyn fmt::Write) -> Self { - Self { enable_color, inner_writer, buffer: String::new() } + fn new(sanitize: bool, inner_writer: &'a mut dyn fmt::Write) -> Self { + Self { sanitize, inner_writer, buffer: String::new() } } /// Write the buffered content to the `inner_writer`. - fn write(&mut self) -> fmt::Result { - lazy_static::lazy_static! { - static ref RE: Regex = Regex::new("\x1b\\[[^m]+m").expect("Error initializing color regex"); - } - - if !self.enable_color { - let replaced = RE.replace_all(&self.buffer, ""); - self.inner_writer.write_str(&replaced) + fn flush(&mut self) -> fmt::Result { + if self.sanitize { + let replaced = strip_control_codes(&self.buffer); + self.inner_writer.write_str(&replaced)? } else { - self.inner_writer.write_str(&self.buffer) + self.inner_writer.write_str(&self.buffer)? } + + self.buffer.clear(); + Ok(()) } } diff --git a/client/tracing/src/logging/mod.rs b/client/tracing/src/logging/mod.rs index 7f995615a223..49807098d1cf 100644 --- a/client/tracing/src/logging/mod.rs +++ b/client/tracing/src/logging/mod.rs @@ -595,4 +595,36 @@ mod tests { assert!(stderr.contains(&line)); } } + + #[test] + fn control_characters_are_always_stripped_out_from_the_log_messages() { + const RAW_LINE: &str = "$$START$$\x1B[1;32mIn\u{202a}\u{202e}\u{2066}\u{2069}ner\n\r\x7ftext!\u{80}\u{9f}\x1B[0m$$END$$"; + const SANITIZED_LINE: &str = "$$START$$Inner\ntext!$$END$$"; + + let output = run_test_in_another_process( + "control_characters_are_always_stripped_out_from_the_log_messages", + || { + std::env::set_var("RUST_LOG", "trace"); + let mut builder = LoggerBuilder::new(""); + builder.with_colors(true); + builder.init().unwrap(); + log::error!("{}", RAW_LINE); + }, + ); + + if let Some(output) = output { + let stderr = String::from_utf8(output.stderr).unwrap(); + // The log messages should always be sanitized. + assert!(!stderr.contains(RAW_LINE)); + assert!(stderr.contains(SANITIZED_LINE)); + + // The part where the timestamp, the logging level, etc. is printed out doesn't + // always have to be sanitized unless it's necessary, and here it shouldn't be. + assert!(stderr.contains("\x1B[31mERROR\x1B[0m")); + + // Make sure the logs aren't being duplicated. + assert_eq!(stderr.find("ERROR"), stderr.rfind("ERROR")); + assert_eq!(stderr.find(SANITIZED_LINE), stderr.rfind(SANITIZED_LINE)); + } + } } diff --git a/primitives/panic-handler/Cargo.toml b/primitives/panic-handler/Cargo.toml index c961d5b089ab..890cc277bd84 100644 --- a/primitives/panic-handler/Cargo.toml +++ b/primitives/panic-handler/Cargo.toml @@ -15,3 +15,5 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] backtrace = "0.3.38" +regex = "1.5.4" +lazy_static = "1.4.0" diff --git a/primitives/panic-handler/src/lib.rs b/primitives/panic-handler/src/lib.rs index 75b057cebf3e..eddb31a7f22f 100644 --- a/primitives/panic-handler/src/lib.rs +++ b/primitives/panic-handler/src/lib.rs @@ -25,6 +25,7 @@ //! temporarily be disabled by using an [`AbortGuard`]. use backtrace::Backtrace; +use regex::Regex; use std::{ cell::Cell, io::{self, Write}, @@ -125,6 +126,24 @@ impl Drop for AbortGuard { } } +// NOTE: When making any changes here make sure to also change this function in `sc-tracing`. +fn strip_control_codes(input: &str) -> std::borrow::Cow { + lazy_static::lazy_static! { + static ref RE: Regex = Regex::new(r#"(?x) + \x1b\[[^m]+m| # VT100 escape codes + [ + \x00-\x09\x0B-\x1F # ASCII control codes / Unicode C0 control codes, except \n + \x7F # ASCII delete + \u{80}-\u{9F} # Unicode C1 control codes + \u{202A}-\u{202E} # Unicode left-to-right / right-to-left control characters + \u{2066}-\u{2069} # Same as above + ] + "#).expect("regex parsing doesn't fail; qed"); + } + + RE.replace_all(input, "") +} + /// Function being called when a panic happens. fn panic_hook(info: &PanicInfo, report_url: &str, version: &str) { let location = info.location(); @@ -139,6 +158,8 @@ fn panic_hook(info: &PanicInfo, report_url: &str, version: &str) { }, }; + let msg = strip_control_codes(&msg); + let thread = thread::current(); let name = thread.name().unwrap_or(""); @@ -181,4 +202,44 @@ mod tests { let _guard = AbortGuard::force_abort(); std::panic::catch_unwind(|| panic!()).ok(); } + + fn run_test_in_another_process( + test_name: &str, + test_body: impl FnOnce(), + ) -> Option { + if std::env::var("RUN_FORKED_TEST").is_ok() { + test_body(); + None + } else { + let output = std::process::Command::new(std::env::current_exe().unwrap()) + .arg(test_name) + .env("RUN_FORKED_TEST", "1") + .output() + .unwrap(); + + assert!(output.status.success()); + Some(output) + } + } + + #[test] + fn control_characters_are_always_stripped_out_from_the_panic_messages() { + const RAW_LINE: &str = "$$START$$\x1B[1;32mIn\u{202a}\u{202e}\u{2066}\u{2069}ner\n\r\x7ftext!\u{80}\u{9f}\x1B[0m$$END$$"; + const SANITIZED_LINE: &str = "$$START$$Inner\ntext!$$END$$"; + + let output = run_test_in_another_process( + "control_characters_are_always_stripped_out_from_the_panic_messages", + || { + set("test", "1.2.3"); + let _guard = AbortGuard::force_unwind(); + let _ = std::panic::catch_unwind(|| panic!("{}", RAW_LINE)); + }, + ); + + if let Some(output) = output { + let stderr = String::from_utf8(output.stderr).unwrap(); + assert!(!stderr.contains(RAW_LINE)); + assert!(stderr.contains(SANITIZED_LINE)); + } + } } From efb72f6306e693ef3b653a52a354e048409baa26 Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Mon, 1 Nov 2021 10:17:50 +0100 Subject: [PATCH 119/695] Fix transaction pool rejection (#10138) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix transaction rejection * Update client/service/src/lib.rs Co-authored-by: Bastian Köcher --- client/service/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/service/src/lib.rs b/client/service/src/lib.rs index a1ff8da4085c..ce77be5a7c1d 100644 --- a/client/service/src/lib.rs +++ b/client/service/src/lib.rs @@ -498,7 +498,7 @@ where fn import(&self, transaction: B::Extrinsic) -> TransactionImportFuture { if !self.imports_external_transactions { debug!("Transaction rejected"); - Box::pin(futures::future::ready(TransactionImport::None)); + return Box::pin(futures::future::ready(TransactionImport::None)) } let encoded = transaction.encode(); From 5fa8dc0f126a4e3c9d5bf02db0fd4206f953403d Mon Sep 17 00:00:00 2001 From: icodezjb <8869892+icodezjb@users.noreply.github.com> Date: Mon, 1 Nov 2021 20:58:18 +0800 Subject: [PATCH 120/695] Speed up big chainspec json(~1.5 GB) load (#10137) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Speed up chainspec json load * Update client/chain-spec/src/chain_spec.rs * Update client/chain-spec/src/chain_spec.rs * Update client/chain-spec/src/chain_spec.rs * Load the chainspec through `mmap` Co-authored-by: icodezjb Co-authored-by: Bastian Köcher Co-authored-by: Jan Bujak --- Cargo.lock | 16 +++++++++++++--- client/chain-spec/Cargo.toml | 1 + client/chain-spec/src/chain_spec.rs | 12 +++++++++++- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1ddf355c890d..4774bfda1f7a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1648,7 +1648,7 @@ checksum = "42276e3f205fe63887cca255aa9a65a63fb72764c30b9a6252a7c7e46994f689" dependencies = [ "byteorder", "dynasm", - "memmap2", + "memmap2 0.2.1", ] [[package]] @@ -4097,6 +4097,15 @@ dependencies = [ "libc", ] +[[package]] +name = "memmap2" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4647a11b578fead29cdbb34d4adef8dd3dc35b876c9c6d5240d83f205abfe96e" +dependencies = [ + "libc", +] + [[package]] name = "memoffset" version = "0.6.4" @@ -6174,7 +6183,7 @@ dependencies = [ "libc", "log 0.4.14", "lz4", - "memmap2", + "memmap2 0.2.1", "parking_lot 0.11.1", "rand 0.8.4", "snap", @@ -7503,6 +7512,7 @@ name = "sc-chain-spec" version = "4.0.0-dev" dependencies = [ "impl-trait-for-tuples", + "memmap2 0.5.0", "parity-scale-codec", "sc-chain-spec-derive", "sc-network", @@ -11285,7 +11295,7 @@ dependencies = [ "backtrace", "bincode", "lazy_static", - "memmap2", + "memmap2 0.2.1", "more-asserts", "rustc-demangle", "serde", diff --git a/client/chain-spec/Cargo.toml b/client/chain-spec/Cargo.toml index 78062e600c3f..ba9655261923 100644 --- a/client/chain-spec/Cargo.toml +++ b/client/chain-spec/Cargo.toml @@ -22,3 +22,4 @@ serde_json = "1.0.68" sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } sc-telemetry = { version = "4.0.0-dev", path = "../telemetry" } codec = { package = "parity-scale-codec", version = "2.0.0" } +memmap2 = "0.5.0" diff --git a/client/chain-spec/src/chain_spec.rs b/client/chain-spec/src/chain_spec.rs index c4db6158125b..2ddb56a0df84 100644 --- a/client/chain-spec/src/chain_spec.rs +++ b/client/chain-spec/src/chain_spec.rs @@ -285,10 +285,20 @@ impl ChainSpec { /// Parse json file into a `ChainSpec` pub fn from_json_file(path: PathBuf) -> Result { + // We mmap the file into memory first, as this is *a lot* faster than using + // `serde_json::from_reader`. See https://github.com/serde-rs/json/issues/160 let file = File::open(&path) .map_err(|e| format!("Error opening spec file `{}`: {}", path.display(), e))?; + + // SAFETY: `mmap` is fundamentally unsafe since technically the file can change + // underneath us while it is mapped; in practice it's unlikely to be a problem + let bytes = unsafe { + memmap2::Mmap::map(&file) + .map_err(|e| format!("Error mmaping spec file `{}`: {}", path.display(), e))? + }; + let client_spec = - json::from_reader(file).map_err(|e| format!("Error parsing spec file: {}", e))?; + json::from_slice(&bytes).map_err(|e| format!("Error parsing spec file: {}", e))?; Ok(ChainSpec { client_spec, genesis: GenesisSource::File(path) }) } } From 4b40c2aa05930a0aae5a7eb0c50a596a44eb6fb1 Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Mon, 1 Nov 2021 14:41:38 +0000 Subject: [PATCH 121/695] introduce remote-tests for pallet-bags-list (#10036) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * make a few primitives in bags-list public * push new stuff * update * update log target * bring remote tests here * revert pub * Update frame/bags-list/remote-tests/Cargo.toml Co-authored-by: Bastian Köcher * some rev commnets * Fix * cleanup * Update Cargo.lock Co-authored-by: Bastian Köcher Co-authored-by: Shawn Tabrizi --- Cargo.lock | 29 +++- Cargo.toml | 1 + frame/bags-list/remote-tests/Cargo.toml | 37 +++++ frame/bags-list/remote-tests/src/lib.rs | 134 ++++++++++++++++++ frame/bags-list/remote-tests/src/migration.rs | 65 +++++++++ .../remote-tests/src/sanity_check.rs | 54 +++++++ frame/bags-list/remote-tests/src/snapshot.rs | 86 +++++++++++ frame/bags-list/src/lib.rs | 6 +- frame/bags-list/src/list/mod.rs | 6 +- frame/staking/src/pallet/impls.rs | 13 +- utils/frame/remote-externalities/src/lib.rs | 4 +- 11 files changed, 420 insertions(+), 15 deletions(-) create mode 100644 frame/bags-list/remote-tests/Cargo.toml create mode 100644 frame/bags-list/remote-tests/src/lib.rs create mode 100644 frame/bags-list/remote-tests/src/migration.rs create mode 100644 frame/bags-list/remote-tests/src/sanity_check.rs create mode 100644 frame/bags-list/remote-tests/src/snapshot.rs diff --git a/Cargo.lock b/Cargo.lock index 4774bfda1f7a..9686bf426fd2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5199,6 +5199,27 @@ dependencies = [ "rand 0.8.4", ] +[[package]] +name = "pallet-bags-list-remote-tests" +version = "4.0.0-dev" +dependencies = [ + "clap", + "frame-election-provider-support", + "frame-support", + "frame-system", + "log 0.4.14", + "pallet-bags-list", + "pallet-staking", + "remote-externalities", + "sp-core", + "sp-runtime", + "sp-std", + "sp-storage", + "sp-tracing", + "structopt", + "tokio", +] + [[package]] name = "pallet-balances" version = "4.0.0-dev" @@ -9858,9 +9879,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "structopt" -version = "0.3.21" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5277acd7ee46e63e5168a80734c9f6ee81b1367a7d8772a2d765df2a3705d28c" +checksum = "bf9d950ef167e25e0bdb073cf1d68e9ad2795ac826f2f3f59647817cf23c0bfa" dependencies = [ "clap", "lazy_static", @@ -9869,9 +9890,9 @@ dependencies = [ [[package]] name = "structopt-derive" -version = "0.4.14" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ba9cdfda491b814720b6b06e0cac513d922fc407582032e8706e9f137976f90" +checksum = "134d838a2c9943ac3125cf6df165eda53493451b719f3255b2a26b85f772d0ba" dependencies = [ "heck", "proc-macro-error 1.0.4", diff --git a/Cargo.toml b/Cargo.toml index 743e0f706664..197b156dea2e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -135,6 +135,7 @@ members = [ "frame/utility", "frame/vesting", "frame/bags-list", + "frame/bags-list/remote-tests", "frame/bags-list/fuzzer", "primitives/api", "primitives/api/proc-macro", diff --git a/frame/bags-list/remote-tests/Cargo.toml b/frame/bags-list/remote-tests/Cargo.toml new file mode 100644 index 000000000000..c670178c6188 --- /dev/null +++ b/frame/bags-list/remote-tests/Cargo.toml @@ -0,0 +1,37 @@ +[package] +name = "pallet-bags-list-remote-tests" +version = "4.0.0-dev" +authors = ["Parity Technologies "] +edition = "2018" +license = "Apache-2.0" +homepage = "https://substrate.io" +repository = "https://github.com/paritytech/substrate/" +description = "FRAME pallet bags list remote test" +readme = "README.md" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +# frame +pallet-staking = { path = "../../staking" } +pallet-bags-list = { path = "../../bags-list" } +frame-election-provider-support = { path = "../../election-provider-support" } +frame-system = { path = "../../system" } +frame-support = { path = "../../support" } + +# core +sp-storage = { path = "../../../primitives/storage" } +sp-core = { path = "../../../primitives/core" } +sp-tracing = { path = "../../../primitives/tracing" } +sp-runtime = { path = "../../../primitives/runtime" } +sp-std = { path = "../../../primitives/std" } + +# utils +remote-externalities = { path = "../../../utils/frame/remote-externalities" } + +# others +tokio = { version = "1", features = ["macros"] } +log = "0.4.14" +structopt = "0.3.23" +clap = "2.33.3" diff --git a/frame/bags-list/remote-tests/src/lib.rs b/frame/bags-list/remote-tests/src/lib.rs new file mode 100644 index 000000000000..e471c4c95bdb --- /dev/null +++ b/frame/bags-list/remote-tests/src/lib.rs @@ -0,0 +1,134 @@ +// This file is part of Substrate. + +// Copyright (C) 2021 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. + +//! Utilities for remote-testing pallet-bags-list. + +use sp_std::convert::TryInto; + +/// A common log target to use. +pub const LOG_TARGET: &'static str = "runtime::bags-list::remote-tests"; + +pub mod migration; +pub mod sanity_check; +pub mod snapshot; + +/// A wrapper for a runtime that the functions of this crate expect. +/// +/// For example, this can be the `Runtime` type of the Polkadot runtime. +pub trait RuntimeT: + pallet_staking::Config + pallet_bags_list::Config + frame_system::Config +{ +} +impl RuntimeT for T {} + +fn percent(portion: u32, total: u32) -> f64 { + (portion as f64 / total as f64) * 100f64 +} + +/// Display the number of nodes in each bag, while identifying those that need a rebag. +pub fn display_and_check_bags(currency_unit: u64, currency_name: &'static str) { + use frame_election_provider_support::SortedListProvider; + use frame_support::traits::Get; + + let min_nominator_bond = >::get(); + log::info!(target: LOG_TARGET, "min nominator bond is {:?}", min_nominator_bond); + + let voter_list_count = ::SortedListProvider::count(); + + // go through every bag to track the total number of voters within bags and log some info about + // how voters are distributed within the bags. + let mut seen_in_bags = 0; + let mut rebaggable = 0; + let mut active_bags = 0; + for vote_weight_thresh in ::BagThresholds::get() { + // threshold in terms of UNITS (e.g. KSM, DOT etc) + let vote_weight_thresh_as_unit = *vote_weight_thresh as f64 / currency_unit as f64; + let pretty_thresh = format!("Threshold: {}. {}", vote_weight_thresh_as_unit, currency_name); + + let bag = match pallet_bags_list::Pallet::::list_bags_get(*vote_weight_thresh) { + Some(bag) => bag, + None => { + log::info!(target: LOG_TARGET, "{} NO VOTERS.", pretty_thresh); + continue + }, + }; + + active_bags += 1; + + for id in bag.std_iter().map(|node| node.std_id().clone()) { + let vote_weight = pallet_staking::Pallet::::weight_of(&id); + let vote_weight_as_balance: pallet_staking::BalanceOf = + vote_weight.try_into().map_err(|_| "can't convert").unwrap(); + + if vote_weight_as_balance < min_nominator_bond { + log::trace!( + target: LOG_TARGET, + "⚠️ {} Account found below min bond: {:?}.", + pretty_thresh, + id + ); + } + + let node = + pallet_bags_list::Node::::get(&id).expect("node in bag must exist."); + if node.is_misplaced(vote_weight) { + rebaggable += 1; + log::trace!( + target: LOG_TARGET, + "Account {:?} can be rebagged from {:?} to {:?}", + id, + vote_weight_thresh_as_unit, + pallet_bags_list::notional_bag_for::(vote_weight) as f64 / + currency_unit as f64 + ); + } + } + + // update our overall counter + let voters_in_bag = bag.std_iter().count() as u32; + seen_in_bags += voters_in_bag; + + // percentage of all nominators + let percent_of_voters = percent(voters_in_bag, voter_list_count); + + log::info!( + target: LOG_TARGET, + "{} Nominators: {} [%{:.3}]", + pretty_thresh, + voters_in_bag, + percent_of_voters, + ); + } + + if seen_in_bags != voter_list_count { + log::error!( + target: LOG_TARGET, + "bags list population ({}) not on par whoever is voter_list ({})", + seen_in_bags, + voter_list_count, + ) + } + + log::info!( + target: LOG_TARGET, + "a total of {} nodes are in {} active bags [{} total bags], {} of which can be rebagged.", + voter_list_count, + active_bags, + ::BagThresholds::get().len(), + rebaggable, + ); +} diff --git a/frame/bags-list/remote-tests/src/migration.rs b/frame/bags-list/remote-tests/src/migration.rs new file mode 100644 index 000000000000..1e977011f143 --- /dev/null +++ b/frame/bags-list/remote-tests/src/migration.rs @@ -0,0 +1,65 @@ +// Copyright 2021 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! Test to check the migration of the voter bag. + +use crate::{RuntimeT, LOG_TARGET}; +use frame_election_provider_support::SortedListProvider; +use frame_support::traits::PalletInfoAccess; +use pallet_staking::Nominators; +use remote_externalities::{Builder, Mode, OnlineConfig}; +use sp_runtime::traits::Block as BlockT; + +/// Test voter bags migration. `currency_unit` is the number of planks per the the runtimes `UNITS` +/// (i.e. number of decimal places per DOT, KSM etc) +pub async fn execute( + currency_unit: u64, + currency_name: &'static str, + ws_url: String, +) { + let mut ext = Builder::::new() + .mode(Mode::Online(OnlineConfig { + transport: ws_url.to_string().into(), + pallets: vec![pallet_staking::Pallet::::name().to_string()], + at: None, + state_snapshot: None, + })) + .build() + .await + .unwrap(); + + ext.execute_with(|| { + // get the nominator & validator count prior to migrating; these should be invariant. + let pre_migrate_nominator_count = >::iter().count() as u32; + log::info!(target: LOG_TARGET, "Nominator count: {}", pre_migrate_nominator_count); + + // run the actual migration, + let moved = ::SortedListProvider::regenerate( + pallet_staking::Nominators::::iter().map(|(n, _)| n), + pallet_staking::Pallet::::weight_of_fn(), + ); + log::info!(target: LOG_TARGET, "Moved {} nominators", moved); + + let voter_list_len = + ::SortedListProvider::iter().count() as u32; + let voter_list_count = ::SortedListProvider::count(); + // and confirm it is equal to the length of the `VoterList`. + assert_eq!(pre_migrate_nominator_count, voter_list_len); + assert_eq!(pre_migrate_nominator_count, voter_list_count); + + crate::display_and_check_bags::(currency_unit, currency_name); + }); +} diff --git a/frame/bags-list/remote-tests/src/sanity_check.rs b/frame/bags-list/remote-tests/src/sanity_check.rs new file mode 100644 index 000000000000..e5e9f45bac5f --- /dev/null +++ b/frame/bags-list/remote-tests/src/sanity_check.rs @@ -0,0 +1,54 @@ +// Copyright 2021 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! Test to execute the sanity-check of the voter bag. + +use frame_election_provider_support::SortedListProvider; +use frame_support::{ + storage::generator::StorageMap, + traits::{Get, PalletInfoAccess}, +}; +use remote_externalities::{Builder, Mode, OnlineConfig}; +use sp_runtime::traits::Block as BlockT; +use sp_std::convert::TryInto; + +/// Execute the sanity check of the bags-list. +pub async fn execute( + currency_unit: u64, + currency_name: &'static str, + ws_url: String, +) { + let mut ext = Builder::::new() + .mode(Mode::Online(OnlineConfig { + transport: ws_url.to_string().into(), + pallets: vec![pallet_bags_list::Pallet::::name().to_string()], + at: None, + state_snapshot: None, + })) + .inject_hashed_prefix(&>::prefix_hash()) + .inject_hashed_prefix(&>::prefix_hash()) + .build() + .await + .unwrap(); + + ext.execute_with(|| { + sp_core::crypto::set_default_ss58_version(Runtime::SS58Prefix::get().try_into().unwrap()); + pallet_bags_list::Pallet::::sanity_check().unwrap(); + log::info!(target: crate::LOG_TARGET, "executed bags-list sanity check with no errors."); + + crate::display_and_check_bags::(currency_unit, currency_name); + }); +} diff --git a/frame/bags-list/remote-tests/src/snapshot.rs b/frame/bags-list/remote-tests/src/snapshot.rs new file mode 100644 index 000000000000..6e186a65cb2b --- /dev/null +++ b/frame/bags-list/remote-tests/src/snapshot.rs @@ -0,0 +1,86 @@ +// Copyright 2021 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! Test to execute the snapshot using the voter bag. + +use frame_support::traits::PalletInfoAccess; +use remote_externalities::{Builder, Mode, OnlineConfig}; +use sp_runtime::traits::Block as BlockT; + +/// Execute create a snapshot from pallet-staking. +pub async fn execute( + voter_limit: Option, + currency_unit: u64, + ws_url: String, +) { + use frame_support::storage::generator::StorageMap; + let mut ext = Builder::::new() + .mode(Mode::Online(OnlineConfig { + transport: ws_url.to_string().into(), + // NOTE: we don't scrape pallet-staking, this kinda ensures that the source of the data + // is bags-list. + pallets: vec![pallet_bags_list::Pallet::::name().to_string()], + at: None, + state_snapshot: None, + })) + .inject_hashed_prefix(&>::prefix_hash()) + .inject_hashed_prefix(&>::prefix_hash()) + .inject_hashed_prefix(&>::prefix_hash()) + .inject_hashed_prefix(&>::prefix_hash()) + .inject_hashed_key(&>::hashed_key()) + .inject_hashed_key(&>::hashed_key()) + .build() + .await + .unwrap(); + + ext.execute_with(|| { + use frame_election_provider_support::{ElectionDataProvider, SortedListProvider}; + log::info!( + target: crate::LOG_TARGET, + "{} nodes in bags list.", + ::SortedListProvider::count(), + ); + + let voters = as ElectionDataProvider< + Runtime::AccountId, + Runtime::BlockNumber, + >>::voters(voter_limit) + .unwrap(); + + let mut voters_nominator_only = voters + .iter() + .filter(|(v, _, _)| pallet_staking::Nominators::::contains_key(v)) + .cloned() + .collect::>(); + voters_nominator_only.sort_by_key(|(_, w, _)| *w); + + let currency_unit = currency_unit as f64; + let min_voter = voters_nominator_only + .first() + .map(|(x, y, _)| (x.clone(), *y as f64 / currency_unit)); + let max_voter = voters_nominator_only + .last() + .map(|(x, y, _)| (x.clone(), *y as f64 / currency_unit)); + log::info!( + target: crate::LOG_TARGET, + "a snapshot with limit {:?} has been created, {} voters are taken. min nominator: {:?}, max: {:?}", + voter_limit, + voters.len(), + min_voter, + max_voter + ); + }); +} diff --git a/frame/bags-list/src/lib.rs b/frame/bags-list/src/lib.rs index 10a692e8b3f9..b7f96799e459 100644 --- a/frame/bags-list/src/lib.rs +++ b/frame/bags-list/src/lib.rs @@ -65,12 +65,10 @@ pub mod mock; mod tests; pub mod weights; +pub use list::{notional_bag_for, Bag, Error, List, Node}; pub use pallet::*; pub use weights::WeightInfo; -pub use list::Error; -use list::List; - pub(crate) const LOG_TARGET: &'static str = "runtime::bags_list"; // syntactic sugar for logging. @@ -155,7 +153,7 @@ pub mod pallet { /// How many ids are registered. // NOTE: This is merely a counter for `ListNodes`. It should someday be replaced by the - // `CountedMaop` storage. + // `CountedMap` storage. #[pallet::storage] pub(crate) type CounterForListNodes = StorageValue<_, u32, ValueQuery>; diff --git a/frame/bags-list/src/list/mod.rs b/frame/bags-list/src/list/mod.rs index 057565e645f9..4efc3163816f 100644 --- a/frame/bags-list/src/list/mod.rs +++ b/frame/bags-list/src/list/mod.rs @@ -53,7 +53,7 @@ mod tests; /// /// Note that even if the thresholds list does not have `VoteWeight::MAX` as its final member, this /// function behaves as if it does. -pub(crate) fn notional_bag_for(weight: VoteWeight) -> VoteWeight { +pub fn notional_bag_for(weight: VoteWeight) -> VoteWeight { let thresholds = T::BagThresholds::get(); let idx = thresholds.partition_point(|&threshold| weight > threshold); thresholds.get(idx).copied().unwrap_or(VoteWeight::MAX) @@ -690,7 +690,7 @@ pub struct Node { impl Node { /// Get a node by id. - pub(crate) fn get(id: &T::AccountId) -> Option> { + pub fn get(id: &T::AccountId) -> Option> { crate::ListNodes::::try_get(id).ok() } @@ -734,7 +734,7 @@ impl Node { } /// `true` when this voter is in the wrong bag. - pub(crate) fn is_misplaced(&self, current_weight: VoteWeight) -> bool { + pub fn is_misplaced(&self, current_weight: VoteWeight) -> bool { notional_bag_for::(current_weight) != self.bag_upper } diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 02099d8543d4..ec34efe397f5 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -692,6 +692,9 @@ impl Pallet { // track every nominator iterated over, but not necessarily added to `all_voters` let mut nominators_seen = 0u32; + // cache the total-issuance once in this function + let weight_of = Self::weight_of_fn(); + let mut nominators_iter = T::SortedListProvider::iter(); while nominators_taken < nominators_quota && nominators_seen < nominators_quota * 2 { let nominator = match nominators_iter.next() { @@ -705,17 +708,23 @@ impl Pallet { if let Some(Nominations { submitted_in, mut targets, suppressed: _ }) = >::get(&nominator) { + log!( + trace, + "fetched nominator {:?} with weight {:?}", + nominator, + weight_of(&nominator) + ); targets.retain(|stash| { slashing_spans .get(stash) .map_or(true, |spans| submitted_in >= spans.last_nonzero_slash()) }); if !targets.len().is_zero() { - all_voters.push((nominator.clone(), Self::weight_of(&nominator), targets)); + all_voters.push((nominator.clone(), weight_of(&nominator), targets)); nominators_taken.saturating_inc(); } } else { - log!(error, "invalid item in `SortedListProvider`: {:?}", nominator) + log!(error, "DEFENSIVE: invalid item in `SortedListProvider`: {:?}", nominator) } } diff --git a/utils/frame/remote-externalities/src/lib.rs b/utils/frame/remote-externalities/src/lib.rs index 733ec7c3200a..3b9e08f75da8 100644 --- a/utils/frame/remote-externalities/src/lib.rs +++ b/utils/frame/remote-externalities/src/lib.rs @@ -385,7 +385,7 @@ impl Builder { }; for prefix in &self.hashed_prefixes { - debug!( + info!( target: LOG_TARGET, "adding data for hashed prefix: {:?}", HexDisplay::from(prefix) @@ -397,7 +397,7 @@ impl Builder { for key in &self.hashed_keys { let key = StorageKey(key.to_vec()); - debug!(target: LOG_TARGET, "adding data for hashed key: {:?}", HexDisplay::from(&key)); + info!(target: LOG_TARGET, "adding data for hashed key: {:?}", HexDisplay::from(&key)); let value = self.rpc_get_storage(key.clone(), Some(at)).await?; keys_and_values.push((key, value)); } From 0210ea04921021fea86f441ecad5275c487f6a78 Mon Sep 17 00:00:00 2001 From: Albrecht <14820950+weichweich@users.noreply.github.com> Date: Tue, 2 Nov 2021 10:27:44 +0100 Subject: [PATCH 122/695] don't panic if already migrated (#10141) * don't panic if already migrated * remove condition --- frame/vesting/src/lib.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/frame/vesting/src/lib.rs b/frame/vesting/src/lib.rs index 27862a5ca4b7..654723d009fa 100644 --- a/frame/vesting/src/lib.rs +++ b/frame/vesting/src/lib.rs @@ -181,7 +181,11 @@ pub mod pallet { impl Hooks> for Pallet { #[cfg(feature = "try-runtime")] fn pre_upgrade() -> Result<(), &'static str> { - migrations::v1::pre_migrate::() + if StorageVersion::::get() == Releases::V0 { + migrations::v1::pre_migrate::() + } else { + Ok(()) + } } fn on_runtime_upgrade() -> Weight { From 0465b0bb407fe36ea03ae35d5138633e23119aac Mon Sep 17 00:00:00 2001 From: cheme Date: Tue, 2 Nov 2021 10:35:23 +0100 Subject: [PATCH 123/695] Hashing proc macro utils (#9875) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * hashing macro * fmt * use in easy place, and fix blake sizes * fix * Fixes, docs. Allow ident as input. * fix doc tests * update error in test (nmapkey and key are same type). * hashing crates under sp_core * Doc updates and format. * use all existing hashing functions. * return array of u8 * Update primitives/core/hashing/proc-macro/src/impls.rs Co-authored-by: Bastian Köcher * ToTokeen for an array of u8 * fix * re * Improve impls * complete doc tests * fmt * fix doctest format * fix ui test (nmap key type alias) Co-authored-by: Bastian Köcher Co-authored-by: Bastian Köcher --- Cargo.lock | 26 +++ Cargo.toml | 2 + client/executor/Cargo.toml | 1 + client/executor/src/wasm_runtime.rs | 2 +- frame/support/Cargo.toml | 1 + frame/support/src/lib.rs | 6 +- .../storage_info_unsatisfied_nmap.stderr | 4 +- primitives/core/Cargo.toml | 4 + primitives/core/hashing/Cargo.toml | 31 +++ primitives/core/hashing/proc-macro/Cargo.toml | 22 +++ .../core/hashing/proc-macro/src/impls.rs | 124 ++++++++++++ primitives/core/hashing/proc-macro/src/lib.rs | 129 ++++++++++++ primitives/core/hashing/src/lib.rs | 166 ++++++++++++++++ primitives/core/src/hashing.rs | 184 ++++-------------- 14 files changed, 553 insertions(+), 149 deletions(-) create mode 100644 primitives/core/hashing/Cargo.toml create mode 100644 primitives/core/hashing/proc-macro/Cargo.toml create mode 100644 primitives/core/hashing/proc-macro/src/impls.rs create mode 100644 primitives/core/hashing/proc-macro/src/lib.rs create mode 100644 primitives/core/hashing/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 9686bf426fd2..20499facb5b7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2051,6 +2051,7 @@ dependencies = [ "smallvec 1.7.0", "sp-arithmetic", "sp-core", + "sp-core-hashing-proc-macro", "sp-inherents", "sp-io", "sp-runtime", @@ -7919,6 +7920,7 @@ dependencies = [ "sc-tracing", "sp-api", "sp-core", + "sp-core-hashing-proc-macro", "sp-externalities", "sp-io", "sp-maybe-compressed-blob", @@ -9303,6 +9305,8 @@ dependencies = [ "serde", "serde_json", "sha2 0.9.8", + "sp-core-hashing", + "sp-core-hashing-proc-macro", "sp-debug-derive", "sp-externalities", "sp-runtime-interface", @@ -9319,6 +9323,28 @@ dependencies = [ "zeroize", ] +[[package]] +name = "sp-core-hashing" +version = "4.0.0-dev" +dependencies = [ + "blake2-rfc", + "byteorder", + "sha2 0.9.8", + "sp-std", + "tiny-keccak", + "twox-hash", +] + +[[package]] +name = "sp-core-hashing-proc-macro" +version = "4.0.0-dev" +dependencies = [ + "proc-macro2", + "quote", + "sp-core-hashing", + "syn", +] + [[package]] name = "sp-database" version = "4.0.0-dev" diff --git a/Cargo.toml b/Cargo.toml index 197b156dea2e..32d10ca8978d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -155,6 +155,8 @@ members = [ "primitives/consensus/pow", "primitives/consensus/vrf", "primitives/core", + "primitives/core/hashing", + "primitives/core/hashing/proc-macro", "primitives/database", "primitives/debug-derive", "primitives/externalities", diff --git a/client/executor/Cargo.toml b/client/executor/Cargo.toml index c8246d43a0f8..bc55172bc33e 100644 --- a/client/executor/Cargo.toml +++ b/client/executor/Cargo.toml @@ -33,6 +33,7 @@ sc-executor-wasmtime = { version = "0.10.0-dev", path = "wasmtime", optional = t parking_lot = "0.11.1" log = "0.4.8" libsecp256k1 = "0.6" +sp-core-hashing-proc-macro = { version = "4.0.0-dev", path = "../../primitives/core/hashing/proc-macro" } [dev-dependencies] wat = "1.0" diff --git a/client/executor/src/wasm_runtime.rs b/client/executor/src/wasm_runtime.rs index c7aa1200719d..204a095717fc 100644 --- a/client/executor/src/wasm_runtime.rs +++ b/client/executor/src/wasm_runtime.rs @@ -344,7 +344,7 @@ fn decode_version(mut version: &[u8]) -> Result { })? .into(); - let core_api_id = sp_core::hashing::blake2_64(b"Core"); + let core_api_id = sp_core_hashing_proc_macro::blake2b_64!(b"Core"); if v.has_api_with(&core_api_id, |v| v >= 3) { sp_api::RuntimeVersion::decode(&mut version).map_err(|_| { WasmError::Instantiation("failed to decode \"Core_version\" result".into()) diff --git a/frame/support/Cargo.toml b/frame/support/Cargo.toml index 4bc64d8b8e73..b62ae3384fe4 100644 --- a/frame/support/Cargo.toml +++ b/frame/support/Cargo.toml @@ -34,6 +34,7 @@ bitflags = "1.3" impl-trait-for-tuples = "0.2.1" smallvec = "1.7.0" log = { version = "0.4.14", default-features = false } +sp-core-hashing-proc-macro = { version = "4.0.0-dev", path = "../../primitives/core/hashing/proc-macro" } [dev-dependencies] assert_matches = "1.3.0" diff --git a/frame/support/src/lib.rs b/frame/support/src/lib.rs index d81300a404c4..6e60988a4ca2 100644 --- a/frame/support/src/lib.rs +++ b/frame/support/src/lib.rs @@ -42,6 +42,8 @@ pub use scale_info; pub use serde; pub use sp_core::Void; #[doc(hidden)] +pub use sp_core_hashing_proc_macro; +#[doc(hidden)] pub use sp_io::{self, storage::root as storage_root}; #[doc(hidden)] pub use sp_runtime::RuntimeDebug; @@ -427,9 +429,7 @@ macro_rules! parameter_types { /// Returns the key for this parameter type. #[allow(unused)] pub fn key() -> [u8; 16] { - $crate::sp_io::hashing::twox_128( - concat!(":", stringify!($name), ":").as_bytes() - ) + $crate::sp_core_hashing_proc_macro::twox_128!(b":", $name, b":") } /// Set the value of this parameter type in the storage. diff --git a/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr b/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr index 2b70102fdac2..ffbc5aeea6b4 100644 --- a/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr +++ b/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr @@ -4,8 +4,8 @@ error[E0277]: the trait bound `Bar: MaxEncodedLen` is not satisfied 10 | #[pallet::generate_storage_info] | ^^^^^^^^^^^^^^^^^^^^^ the trait `MaxEncodedLen` is not implemented for `Bar` | - = note: required because of the requirements on the impl of `KeyGeneratorMaxEncodedLen` for `Key` - = note: required because of the requirements on the impl of `StorageInfoTrait` for `frame_support::pallet_prelude::StorageNMap<_GeneratedPrefixForStorageFoo, Key, u32>` + = note: required because of the requirements on the impl of `KeyGeneratorMaxEncodedLen` for `NMapKey` + = note: required because of the requirements on the impl of `StorageInfoTrait` for `frame_support::pallet_prelude::StorageNMap<_GeneratedPrefixForStorageFoo, NMapKey, u32>` note: required by `storage_info` --> $DIR/storage.rs:71:2 | diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index 14a76e248244..148f2343ee2b 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -66,6 +66,7 @@ sha2 = { version = "0.9.8", default-features = false, optional = true } hex = { version = "0.4", default-features = false, optional = true } twox-hash = { version = "1.6.1", default-features = false, optional = true } libsecp256k1 = { version = "0.6", default-features = false, features = ["hmac", "static-context"], optional = true } +sp-core-hashing = { version = "4.0.0-dev", path = "./hashing", default-features = false, optional = true } merlin = { version = "2.0", default-features = false, optional = true } ss58-registry = "1.0.0" sp-runtime-interface = { version = "4.0.0-dev", default-features = false, path = "../runtime-interface" } @@ -76,6 +77,7 @@ hex-literal = "0.3.3" rand = "0.7.2" criterion = "0.3.3" serde_json = "1.0" +sp-core-hashing-proc-macro = { version = "4.0.0-dev", path = "./hashing/proc-macro" } [[bench]] name = "bench" @@ -118,6 +120,7 @@ std = [ "regex", "num-traits/std", "tiny-keccak", + "sp-core-hashing/std", "sp-debug-derive/std", "sp-externalities", "sp-storage/std", @@ -142,6 +145,7 @@ full_crypto = [ "sha2", "twox-hash", "libsecp256k1", + "sp-core-hashing", "sp-runtime-interface/disable_target_static_assertions", "merlin", ] diff --git a/primitives/core/hashing/Cargo.toml b/primitives/core/hashing/Cargo.toml new file mode 100644 index 000000000000..43c670b59b0a --- /dev/null +++ b/primitives/core/hashing/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "sp-core-hashing" +version = "4.0.0-dev" +authors = ["Parity Technologies "] +edition = "2018" +license = "Apache-2.0" +homepage = "https://substrate.dev" +repository = "https://github.com/paritytech/substrate/" +description = "Primitive core crate hashing implementation." +documentation = "https://docs.rs/sp-core-hashing" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +sp-std = { version = "4.0.0-dev", default-features = false, path = "../../std" } +byteorder = { version = "1.3.2", default-features = false } + +blake2-rfc = { version = "0.2.18", default-features = false } +tiny-keccak = { version = "2.0.1", features = ["keccak"] } +sha2 = { version = "0.9.2", default-features = false } +twox-hash = { version = "1.5.0", default-features = false } + +[features] +default = ["std"] +std = [ + "blake2-rfc/std", + "sha2/std", + "sp-std/std", + "twox-hash/std", +] diff --git a/primitives/core/hashing/proc-macro/Cargo.toml b/primitives/core/hashing/proc-macro/Cargo.toml new file mode 100644 index 000000000000..6d83b50b8a29 --- /dev/null +++ b/primitives/core/hashing/proc-macro/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "sp-core-hashing-proc-macro" +version = "4.0.0-dev" +authors = ["Parity Technologies "] +edition = "2018" +license = "Apache-2.0" +homepage = "https://substrate.dev" +repository = "https://github.com/paritytech/substrate/" +description = "This crate provides procedural macros for calculating static hash." +documentation = "https://docs.rs/sp-core-hashing-proc-macro" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +proc-macro = true + +[dependencies] +syn = { version = "1.0.77", features = ["full", "parsing"] } +quote = "1.0.6" +proc-macro2 = "1.0.29" +sp-core-hashing = { version = "4.0.0-dev", path = "../", default-features = false } diff --git a/primitives/core/hashing/proc-macro/src/impls.rs b/primitives/core/hashing/proc-macro/src/impls.rs new file mode 100644 index 000000000000..0ce388762aa3 --- /dev/null +++ b/primitives/core/hashing/proc-macro/src/impls.rs @@ -0,0 +1,124 @@ +// This file is part of Substrate. + +// Copyright (C) 2021 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. + +use quote::quote; +use syn::parse::{Parse, ParseStream}; + +use proc_macro::TokenStream; + +pub(super) struct InputBytes(pub Vec); + +pub(super) struct MultipleInputBytes(pub Vec>); + +impl MultipleInputBytes { + pub(super) fn concatenated(mut self) -> Vec { + if self.0.len() == 0 { + Vec::new() + } else { + let mut result = core::mem::take(&mut self.0[0]); + for other in self.0[1..].iter_mut() { + result.append(other); + } + result + } + } +} + +impl Parse for InputBytes { + fn parse(input: ParseStream) -> syn::Result { + match syn::ExprArray::parse(input) { + Ok(array) => { + let mut bytes = Vec::::new(); + for expr in array.elems.iter() { + match expr { + syn::Expr::Lit(lit) => match &lit.lit { + syn::Lit::Int(b) => bytes.push(b.base10_parse()?), + syn::Lit::Byte(b) => bytes.push(b.value()), + _ => + return Err(syn::Error::new( + input.span(), + "Expected array of u8 elements.".to_string(), + )), + }, + _ => + return Err(syn::Error::new( + input.span(), + "Expected array of u8 elements.".to_string(), + )), + } + } + return Ok(InputBytes(bytes)) + }, + Err(_e) => (), + } + // use rust names as a vec of their utf8 bytecode. + match syn::Ident::parse(input) { + Ok(ident) => return Ok(InputBytes(ident.to_string().as_bytes().to_vec())), + Err(_e) => (), + } + Ok(InputBytes(syn::LitByteStr::parse(input)?.value())) + } +} + +impl Parse for MultipleInputBytes { + fn parse(input: ParseStream) -> syn::Result { + let elts = + syn::punctuated::Punctuated::::parse_terminated(input)?; + Ok(MultipleInputBytes(elts.into_iter().map(|elt| elt.0).collect())) + } +} + +pub(super) fn twox_64(bytes: Vec) -> TokenStream { + bytes_to_array(sp_core_hashing::twox_64(bytes.as_slice())) +} + +pub(super) fn twox_128(bytes: Vec) -> TokenStream { + bytes_to_array(sp_core_hashing::twox_128(bytes.as_slice())) +} + +pub(super) fn blake2b_512(bytes: Vec) -> TokenStream { + bytes_to_array(sp_core_hashing::blake2_512(bytes.as_slice())) +} + +pub(super) fn blake2b_256(bytes: Vec) -> TokenStream { + bytes_to_array(sp_core_hashing::blake2_256(bytes.as_slice())) +} + +pub(super) fn blake2b_64(bytes: Vec) -> TokenStream { + bytes_to_array(sp_core_hashing::blake2_64(bytes.as_slice())) +} + +pub(super) fn keccak_256(bytes: Vec) -> TokenStream { + bytes_to_array(sp_core_hashing::keccak_256(bytes.as_slice())) +} + +pub(super) fn keccak_512(bytes: Vec) -> TokenStream { + bytes_to_array(sp_core_hashing::keccak_512(bytes.as_slice())) +} + +pub(super) fn sha2_256(bytes: Vec) -> TokenStream { + bytes_to_array(sp_core_hashing::sha2_256(bytes.as_slice())) +} + +fn bytes_to_array(bytes: impl IntoIterator) -> TokenStream { + let bytes = bytes.into_iter(); + + quote!( + [ #( #bytes ),* ] + ) + .into() +} diff --git a/primitives/core/hashing/proc-macro/src/lib.rs b/primitives/core/hashing/proc-macro/src/lib.rs new file mode 100644 index 000000000000..2af8554f4ece --- /dev/null +++ b/primitives/core/hashing/proc-macro/src/lib.rs @@ -0,0 +1,129 @@ +// This file is part of Substrate. + +// Copyright (C) 2021 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. + +//! Macros to calculate constant hash bytes result. +//! +//! Macros from this crate does apply a specific hash function on input. +//! Input can be literal byte array as `b"content"` or array of bytes +//! as `[1, 2, 3]`. +//! Rust identifier can also be use, in this case we use their utf8 string +//! byte representation, for instance if the ident is `MyStruct`, then +//! `b"MyStruct"` will be hashed. +//! If multiple arguments comma separated are passed, they are concatenated +//! then hashed. +//! +//! Examples: +//! +//! ```rust +//! assert_eq!( +//! sp_core_hashing_proc_macro::blake2b_256!(b"test"), +//! sp_core_hashing::blake2_256(b"test"), +//! ); +//! assert_eq!( +//! sp_core_hashing_proc_macro::blake2b_256!([1u8]), +//! sp_core_hashing::blake2_256(&[1u8]), +//! ); +//! assert_eq!( +//! sp_core_hashing_proc_macro::blake2b_256!([1, 2, 3]), +//! sp_core_hashing::blake2_256(&[1, 2, 3]), +//! ); +//! assert_eq!( +//! sp_core_hashing_proc_macro::blake2b_256!(identifier), +//! sp_core_hashing::blake2_256(b"identifier"), +//! ); +//! assert_eq!( +//! sp_core_hashing_proc_macro::blake2b_256!(identifier, b"/string"), +//! sp_core_hashing::blake2_256(b"identifier/string"), +//! ); +//! ``` + +mod impls; + +use impls::MultipleInputBytes; +use proc_macro::TokenStream; + +/// Process a Blake2 64-bit hash of bytes parameter outputs a `[u8; 8]`. +/// Multiple inputs are concatenated before hashing. +/// Input can be identifier (name of identifier as bytes is used), byte string or +/// array of bytes. +#[proc_macro] +pub fn blake2b_64(input: TokenStream) -> TokenStream { + impls::blake2b_64(syn::parse_macro_input!(input as MultipleInputBytes).concatenated()) +} + +/// Apply a Blake2 256-bit hash of bytes parameter, outputs a `[u8; 32]`. +/// Multiple inputs are concatenated before hashing. +/// Input can be identifier (name of identifier as bytes is used), byte string or +/// array of bytes. +#[proc_macro] +pub fn blake2b_256(input: TokenStream) -> TokenStream { + impls::blake2b_256(syn::parse_macro_input!(input as MultipleInputBytes).concatenated()) +} + +/// Apply a Blake2 512-bit hash of bytes parameter, outputs a `[u8; 64]`. +/// Multiple inputs are concatenated before hashing. +/// Input can be identifier (name of identifier as bytes is used), byte string or +/// array of bytes. +#[proc_macro] +pub fn blake2b_512(input: TokenStream) -> TokenStream { + impls::blake2b_512(syn::parse_macro_input!(input as MultipleInputBytes).concatenated()) +} + +/// Apply a XX 64-bit hash on its bytes parameter, outputs a `[u8; 8]`. +/// Multiple inputs are concatenated before hashing. +/// Input can be identifier (name of identifier as bytes is used), byte string or +/// array of bytes. +#[proc_macro] +pub fn twox_64(input: TokenStream) -> TokenStream { + impls::twox_64(syn::parse_macro_input!(input as MultipleInputBytes).concatenated()) +} + +/// Apply a XX 128-bit hash on its bytes parameter, outputs a `[u8; 16]`. +/// Multiple inputs are concatenated before hashing. +/// Input can be identifier (name of identifier as bytes is used), byte string or +/// array of bytes. +#[proc_macro] +pub fn twox_128(input: TokenStream) -> TokenStream { + impls::twox_128(syn::parse_macro_input!(input as MultipleInputBytes).concatenated()) +} + +/// Apply a keccak 256-bit hash on its bytes parameter, outputs a `[u8; 32]`. +/// Multiple inputs are concatenated before hashing. +/// Input can be identifier (name of identifier as bytes is used), byte string or +/// array of bytes. +#[proc_macro] +pub fn keccak_256(input: TokenStream) -> TokenStream { + impls::keccak_256(syn::parse_macro_input!(input as MultipleInputBytes).concatenated()) +} + +/// Apply a keccak 512-bit hash on its bytes parameter, outputs a `[u8; 64]`. +/// Multiple inputs are concatenated before hashing. +/// Input can be identifier (name of identifier as bytes is used), byte string or +/// array of bytes. +#[proc_macro] +pub fn keccak_512(input: TokenStream) -> TokenStream { + impls::keccak_512(syn::parse_macro_input!(input as MultipleInputBytes).concatenated()) +} + +/// Apply a sha2 256-bit hash on its bytes parameter, outputs a `[u8; 32]`. +/// Multiple inputs are concatenated before hashing. +/// Input can be identifier (name of identifier as bytes is used), byte string or +/// array of bytes. +#[proc_macro] +pub fn sha2_256(input: TokenStream) -> TokenStream { + impls::sha2_256(syn::parse_macro_input!(input as MultipleInputBytes).concatenated()) +} diff --git a/primitives/core/hashing/src/lib.rs b/primitives/core/hashing/src/lib.rs new file mode 100644 index 000000000000..f806613c5b54 --- /dev/null +++ b/primitives/core/hashing/src/lib.rs @@ -0,0 +1,166 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2021 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. + +//! Hashing Functions. + +#![warn(missing_docs)] +#![cfg_attr(not(feature = "std"), no_std)] + +use sha2::{Digest, Sha256}; +use tiny_keccak::{Hasher, Keccak}; + +/// Do a Blake2 512-bit hash and place result in `dest`. +pub fn blake2_512_into(data: &[u8], dest: &mut [u8; 64]) { + dest.copy_from_slice(blake2_rfc::blake2b::blake2b(64, &[], data).as_bytes()); +} + +/// Do a Blake2 512-bit hash and return result. +pub fn blake2_512(data: &[u8]) -> [u8; 64] { + let mut r = [0; 64]; + blake2_512_into(data, &mut r); + r +} + +/// Do a Blake2 256-bit hash and place result in `dest`. +pub fn blake2_256_into(data: &[u8], dest: &mut [u8; 32]) { + dest.copy_from_slice(blake2_rfc::blake2b::blake2b(32, &[], data).as_bytes()); +} + +/// Do a Blake2 256-bit hash and return result. +pub fn blake2_256(data: &[u8]) -> [u8; 32] { + let mut r = [0; 32]; + blake2_256_into(data, &mut r); + r +} + +/// Do a Blake2 128-bit hash and place result in `dest`. +pub fn blake2_128_into(data: &[u8], dest: &mut [u8; 16]) { + dest.copy_from_slice(blake2_rfc::blake2b::blake2b(16, &[], data).as_bytes()); +} + +/// Do a Blake2 128-bit hash and return result. +pub fn blake2_128(data: &[u8]) -> [u8; 16] { + let mut r = [0; 16]; + blake2_128_into(data, &mut r); + r +} + +/// Do a Blake2 64-bit hash and place result in `dest`. +pub fn blake2_64_into(data: &[u8], dest: &mut [u8; 8]) { + dest.copy_from_slice(blake2_rfc::blake2b::blake2b(8, &[], data).as_bytes()); +} + +/// Do a Blake2 64-bit hash and return result. +pub fn blake2_64(data: &[u8]) -> [u8; 8] { + let mut r = [0; 8]; + blake2_64_into(data, &mut r); + r +} + +/// Do a XX 64-bit hash and place result in `dest`. +pub fn twox_64_into(data: &[u8], dest: &mut [u8; 8]) { + use core::hash::Hasher; + let mut h0 = twox_hash::XxHash::with_seed(0); + h0.write(data); + let r0 = h0.finish(); + use byteorder::{ByteOrder, LittleEndian}; + LittleEndian::write_u64(&mut dest[0..8], r0); +} + +/// Do a XX 64-bit hash and return result. +pub fn twox_64(data: &[u8]) -> [u8; 8] { + let mut r: [u8; 8] = [0; 8]; + twox_64_into(data, &mut r); + r +} + +/// Do a XX 128-bit hash and place result in `dest`. +pub fn twox_128_into(data: &[u8], dest: &mut [u8; 16]) { + use core::hash::Hasher; + let mut h0 = twox_hash::XxHash::with_seed(0); + let mut h1 = twox_hash::XxHash::with_seed(1); + h0.write(data); + h1.write(data); + let r0 = h0.finish(); + let r1 = h1.finish(); + use byteorder::{ByteOrder, LittleEndian}; + LittleEndian::write_u64(&mut dest[0..8], r0); + LittleEndian::write_u64(&mut dest[8..16], r1); +} + +/// Do a XX 128-bit hash and return result. +pub fn twox_128(data: &[u8]) -> [u8; 16] { + let mut r: [u8; 16] = [0; 16]; + twox_128_into(data, &mut r); + r +} + +/// Do a XX 256-bit hash and place result in `dest`. +pub fn twox_256_into(data: &[u8], dest: &mut [u8; 32]) { + use ::core::hash::Hasher; + use byteorder::{ByteOrder, LittleEndian}; + let mut h0 = twox_hash::XxHash::with_seed(0); + let mut h1 = twox_hash::XxHash::with_seed(1); + let mut h2 = twox_hash::XxHash::with_seed(2); + let mut h3 = twox_hash::XxHash::with_seed(3); + h0.write(data); + h1.write(data); + h2.write(data); + h3.write(data); + let r0 = h0.finish(); + let r1 = h1.finish(); + let r2 = h2.finish(); + let r3 = h3.finish(); + LittleEndian::write_u64(&mut dest[0..8], r0); + LittleEndian::write_u64(&mut dest[8..16], r1); + LittleEndian::write_u64(&mut dest[16..24], r2); + LittleEndian::write_u64(&mut dest[24..32], r3); +} + +/// Do a XX 256-bit hash and return result. +pub fn twox_256(data: &[u8]) -> [u8; 32] { + let mut r: [u8; 32] = [0; 32]; + twox_256_into(data, &mut r); + r +} + +/// Do a keccak 256-bit hash and return result. +pub fn keccak_256(data: &[u8]) -> [u8; 32] { + let mut keccak = Keccak::v256(); + keccak.update(data); + let mut output = [0u8; 32]; + keccak.finalize(&mut output); + output +} + +/// Do a keccak 512-bit hash and return result. +pub fn keccak_512(data: &[u8]) -> [u8; 64] { + let mut keccak = Keccak::v512(); + keccak.update(data); + let mut output = [0u8; 64]; + keccak.finalize(&mut output); + output +} + +/// Do a sha2 256-bit hash and return result. +pub fn sha2_256(data: &[u8]) -> [u8; 32] { + let mut hasher = Sha256::new(); + hasher.update(data); + let mut output = [0u8; 32]; + output.copy_from_slice(&hasher.finalize()); + output +} diff --git a/primitives/core/src/hashing.rs b/primitives/core/src/hashing.rs index 4c719f7c6983..092cfc51b950 100644 --- a/primitives/core/src/hashing.rs +++ b/primitives/core/src/hashing.rs @@ -22,147 +22,45 @@ //! unless you know what you're doing. Using `sp_io` will be more performant, since instead of //! computing the hash in WASM it delegates that computation to the host client. -use sha2::{Digest, Sha256}; -use tiny_keccak::{Hasher, Keccak}; - -/// Do a Blake2 512-bit hash and place result in `dest`. -pub fn blake2_512_into(data: &[u8], dest: &mut [u8; 64]) { - dest.copy_from_slice(blake2_rfc::blake2b::blake2b(64, &[], data).as_bytes()); -} - -/// Do a Blake2 512-bit hash and return result. -pub fn blake2_512(data: &[u8]) -> [u8; 64] { - let mut r = [0; 64]; - blake2_512_into(data, &mut r); - r -} - -/// Do a Blake2 256-bit hash and place result in `dest`. -pub fn blake2_256_into(data: &[u8], dest: &mut [u8; 32]) { - dest.copy_from_slice(blake2_rfc::blake2b::blake2b(32, &[], data).as_bytes()); -} - -/// Do a Blake2 256-bit hash and return result. -pub fn blake2_256(data: &[u8]) -> [u8; 32] { - let mut r = [0; 32]; - blake2_256_into(data, &mut r); - r -} - -/// Do a Blake2 128-bit hash and place result in `dest`. -pub fn blake2_128_into(data: &[u8], dest: &mut [u8; 16]) { - dest.copy_from_slice(blake2_rfc::blake2b::blake2b(16, &[], data).as_bytes()); -} - -/// Do a Blake2 128-bit hash and return result. -pub fn blake2_128(data: &[u8]) -> [u8; 16] { - let mut r = [0; 16]; - blake2_128_into(data, &mut r); - r -} - -/// Do a Blake2 64-bit hash and place result in `dest`. -pub fn blake2_64_into(data: &[u8], dest: &mut [u8; 8]) { - dest.copy_from_slice(blake2_rfc::blake2b::blake2b(8, &[], data).as_bytes()); -} - -/// Do a Blake2 64-bit hash and return result. -pub fn blake2_64(data: &[u8]) -> [u8; 8] { - let mut r = [0; 8]; - blake2_64_into(data, &mut r); - r -} - -/// Do a XX 64-bit hash and place result in `dest`. -pub fn twox_64_into(data: &[u8], dest: &mut [u8; 8]) { - use core::hash::Hasher; - let mut h0 = twox_hash::XxHash::with_seed(0); - h0.write(data); - let r0 = h0.finish(); - use byteorder::{ByteOrder, LittleEndian}; - LittleEndian::write_u64(&mut dest[0..8], r0); -} - -/// Do a XX 64-bit hash and return result. -pub fn twox_64(data: &[u8]) -> [u8; 8] { - let mut r: [u8; 8] = [0; 8]; - twox_64_into(data, &mut r); - r -} - -/// Do a XX 128-bit hash and place result in `dest`. -pub fn twox_128_into(data: &[u8], dest: &mut [u8; 16]) { - use core::hash::Hasher; - let mut h0 = twox_hash::XxHash::with_seed(0); - let mut h1 = twox_hash::XxHash::with_seed(1); - h0.write(data); - h1.write(data); - let r0 = h0.finish(); - let r1 = h1.finish(); - use byteorder::{ByteOrder, LittleEndian}; - LittleEndian::write_u64(&mut dest[0..8], r0); - LittleEndian::write_u64(&mut dest[8..16], r1); -} - -/// Do a XX 128-bit hash and return result. -pub fn twox_128(data: &[u8]) -> [u8; 16] { - let mut r: [u8; 16] = [0; 16]; - twox_128_into(data, &mut r); - r -} - -/// Do a XX 256-bit hash and place result in `dest`. -pub fn twox_256_into(data: &[u8], dest: &mut [u8; 32]) { - use ::core::hash::Hasher; - use byteorder::{ByteOrder, LittleEndian}; - let mut h0 = twox_hash::XxHash::with_seed(0); - let mut h1 = twox_hash::XxHash::with_seed(1); - let mut h2 = twox_hash::XxHash::with_seed(2); - let mut h3 = twox_hash::XxHash::with_seed(3); - h0.write(data); - h1.write(data); - h2.write(data); - h3.write(data); - let r0 = h0.finish(); - let r1 = h1.finish(); - let r2 = h2.finish(); - let r3 = h3.finish(); - LittleEndian::write_u64(&mut dest[0..8], r0); - LittleEndian::write_u64(&mut dest[8..16], r1); - LittleEndian::write_u64(&mut dest[16..24], r2); - LittleEndian::write_u64(&mut dest[24..32], r3); -} - -/// Do a XX 256-bit hash and return result. -pub fn twox_256(data: &[u8]) -> [u8; 32] { - let mut r: [u8; 32] = [0; 32]; - twox_256_into(data, &mut r); - r -} - -/// Do a keccak 256-bit hash and return result. -pub fn keccak_256(data: &[u8]) -> [u8; 32] { - let mut keccak = Keccak::v256(); - keccak.update(data); - let mut output = [0u8; 32]; - keccak.finalize(&mut output); - output -} - -/// Do a keccak 512-bit hash and return result. -pub fn keccak_512(data: &[u8]) -> [u8; 64] { - let mut keccak = Keccak::v512(); - keccak.update(data); - let mut output = [0u8; 64]; - keccak.finalize(&mut output); - output -} - -/// Do a sha2 256-bit hash and return result. -pub fn sha2_256(data: &[u8]) -> [u8; 32] { - let mut hasher = Sha256::new(); - hasher.update(data); - let mut output = [0u8; 32]; - output.copy_from_slice(&hasher.finalize()); - output +pub use sp_core_hashing::*; + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn blake2b() { + assert_eq!(sp_core_hashing_proc_macro::blake2b_64!(b""), blake2_64(b"")[..]); + assert_eq!(sp_core_hashing_proc_macro::blake2b_256!(b"test"), blake2_256(b"test")[..]); + assert_eq!(sp_core_hashing_proc_macro::blake2b_512!(b""), blake2_512(b"")[..]); + } + + #[test] + fn keccak() { + assert_eq!(sp_core_hashing_proc_macro::keccak_256!(b"test"), keccak_256(b"test")[..]); + assert_eq!(sp_core_hashing_proc_macro::keccak_512!(b"test"), keccak_512(b"test")[..]); + } + + #[test] + fn sha2() { + assert_eq!(sp_core_hashing_proc_macro::sha2_256!(b"test"), sha2_256(b"test")[..]); + } + + #[test] + fn twox() { + assert_eq!(sp_core_hashing_proc_macro::twox_128!(b"test"), twox_128(b"test")[..]); + assert_eq!(sp_core_hashing_proc_macro::twox_64!(b""), twox_64(b"")[..]); + } + + #[test] + fn twox_concats() { + assert_eq!( + sp_core_hashing_proc_macro::twox_128!(b"test", b"123", b"45", b"", b"67890"), + super::twox_128(&b"test1234567890"[..]), + ); + assert_eq!( + sp_core_hashing_proc_macro::twox_128!(b"test", test, b"45", b"", b"67890"), + super::twox_128(&b"testtest4567890"[..]), + ); + } } From 9d8e5c468e252f0773c7bae60a631a139969b046 Mon Sep 17 00:00:00 2001 From: Gavin Wood Date: Tue, 2 Nov 2021 15:09:40 +0100 Subject: [PATCH 124/695] Spelling (#10154) --- docs/STYLE_GUIDE.md | 4 ++-- frame/babe/src/lib.rs | 2 +- frame/multisig/src/lib.rs | 2 +- primitives/state-machine/src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/STYLE_GUIDE.md b/docs/STYLE_GUIDE.md index ea070cdbc59f..8854f885a4b2 100644 --- a/docs/STYLE_GUIDE.md +++ b/docs/STYLE_GUIDE.md @@ -140,8 +140,8 @@ let mut target_path = ``` - Unsafe code requires explicit proofs just as panickers do. When introducing unsafe code, - consider tradeoffs between efficiency on one hand and reliability, maintenance costs, and - security on the other. Here is a list of questions that may help evaluating the tradeoff while + consider trade-offs between efficiency on one hand and reliability, maintenance costs, and + security on the other. Here is a list of questions that may help evaluating the trade-off while preparing or reviewing a PR: - how much more performant or compact the resulting code will be using unsafe code, - how likely is it that invariants could be violated, diff --git a/frame/babe/src/lib.rs b/frame/babe/src/lib.rs index 9c755eea6c44..c74bbf897ac7 100644 --- a/frame/babe/src/lib.rs +++ b/frame/babe/src/lib.rs @@ -248,7 +248,7 @@ pub mod pallet { /// Randomness under construction. /// - /// We make a tradeoff between storage accesses and list length. + /// We make a trade-off between storage accesses and list length. /// We store the under-construction randomness in segments of up to /// `UNDER_CONSTRUCTION_SEGMENT_LENGTH`. /// diff --git a/frame/multisig/src/lib.rs b/frame/multisig/src/lib.rs index 53567cc212af..c38ddf1793ee 100644 --- a/frame/multisig/src/lib.rs +++ b/frame/multisig/src/lib.rs @@ -218,7 +218,7 @@ pub mod pallet { CallHash, DispatchResult, ), - /// A multisig operation has been cancelled. \[cancelling, timepoint, multisig, call_hash\] + /// A multisig operation has been cancelled. \[canceling, timepoint, multisig, call_hash\] MultisigCancelled(T::AccountId, Timepoint, T::AccountId, CallHash), } diff --git a/primitives/state-machine/src/lib.rs b/primitives/state-machine/src/lib.rs index 7bd0c645f3c0..a724cf5c9a0b 100644 --- a/primitives/state-machine/src/lib.rs +++ b/primitives/state-machine/src/lib.rs @@ -1496,7 +1496,7 @@ mod tests { } overlay.start_transaction(); - // Then only initlaization item and second (commited) item should persist. + // Then only initlaization item and second (committed) item should persist. { let ext = Ext::new( &mut overlay, From 635c187e8f92a239772ffd70d7a445e073f8920f Mon Sep 17 00:00:00 2001 From: Guillaume Thiolliere Date: Tue, 2 Nov 2021 15:20:00 +0100 Subject: [PATCH 125/695] Better error for when origin filter prevent the call to be dispatched (#10134) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * better error * Apply suggestions from code review Co-authored-by: Bastian Köcher * remove unused * fix error * fmt * fix tests * fmt * Update frame/contracts/src/exec.rs Co-authored-by: Alexander Theißen * fix typo Co-authored-by: Bastian Köcher Co-authored-by: Alexander Theißen --- frame/contracts/src/exec.rs | 12 +++--- frame/multisig/src/tests.rs | 2 +- frame/proxy/src/tests.rs | 42 ++++++++++++++----- .../src/construct_runtime/expand/call.rs | 6 ++- .../src/construct_runtime/expand/origin.rs | 13 +----- .../procedural/src/construct_runtime/mod.rs | 13 +++++- frame/support/test/tests/system.rs | 4 +- frame/system/src/lib.rs | 2 + frame/utility/src/tests.rs | 10 +++-- 9 files changed, 67 insertions(+), 37 deletions(-) diff --git a/frame/contracts/src/exec.rs b/frame/contracts/src/exec.rs index c28490dfaccc..7ef1aec2dfc6 100644 --- a/frame/contracts/src/exec.rs +++ b/frame/contracts/src/exec.rs @@ -1094,10 +1094,7 @@ mod tests { use pallet_contracts_primitives::ReturnFlags; use pretty_assertions::assert_eq; use sp_core::Bytes; - use sp_runtime::{ - traits::{BadOrigin, Hash}, - DispatchError, - }; + use sp_runtime::{traits::Hash, DispatchError}; use std::{cell::RefCell, collections::HashMap, rc::Rc}; type System = frame_system::Pallet; @@ -2114,7 +2111,10 @@ mod tests { let forbidden_call = Call::Balances(BalanceCall::transfer { dest: CHARLIE, value: 22 }); // simple cases: direct call - assert_err!(ctx.ext.call_runtime(forbidden_call.clone()), BadOrigin); + assert_err!( + ctx.ext.call_runtime(forbidden_call.clone()), + frame_system::Error::::CallFiltered + ); // as part of a patch: return is OK (but it interrupted the batch) assert_ok!(ctx.ext.call_runtime(Call::Utility(UtilCall::batch { @@ -2159,7 +2159,7 @@ mod tests { phase: Phase::Initialization, event: MetaEvent::Utility(pallet_utility::Event::BatchInterrupted( 1, - BadOrigin.into() + frame_system::Error::::CallFiltered.into() ),), topics: vec![], }, diff --git a/frame/multisig/src/tests.rs b/frame/multisig/src/tests.rs index d46c22ec73d0..c5607c80abce 100644 --- a/frame/multisig/src/tests.rs +++ b/frame/multisig/src/tests.rs @@ -846,7 +846,7 @@ fn multisig_filters() { let call = Box::new(Call::System(frame_system::Call::set_code { code: vec![] })); assert_noop!( Multisig::as_multi_threshold_1(Origin::signed(1), vec![2], call.clone()), - DispatchError::BadOrigin, + DispatchError::from(frame_system::Error::::CallFiltered), ); }); } diff --git a/frame/proxy/src/tests.rs b/frame/proxy/src/tests.rs index d319ebb1a5ab..20efd085fe88 100644 --- a/frame/proxy/src/tests.rs +++ b/frame/proxy/src/tests.rs @@ -174,6 +174,8 @@ use frame_system::Call as SystemCall; use pallet_balances::{Call as BalancesCall, Error as BalancesError, Event as BalancesEvent}; use pallet_utility::{Call as UtilityCall, Event as UtilityEvent}; +type SystemError = frame_system::Error; + pub fn new_test_ext() -> sp_io::TestExternalities { let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); pallet_balances::GenesisConfig:: { @@ -333,7 +335,9 @@ fn filtering_works() { assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone())); System::assert_last_event(ProxyEvent::ProxyExecuted(Ok(())).into()); assert_ok!(Proxy::proxy(Origin::signed(4), 1, None, call.clone())); - System::assert_last_event(ProxyEvent::ProxyExecuted(Err(DispatchError::BadOrigin)).into()); + System::assert_last_event( + ProxyEvent::ProxyExecuted(Err(SystemError::CallFiltered.into())).into(), + ); let derivative_id = Utility::derivative_account_id(1, 0); assert!(Balances::mutate_account(&derivative_id, |a| a.free = 1000).is_ok()); @@ -344,9 +348,13 @@ fn filtering_works() { assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, call.clone())); System::assert_last_event(ProxyEvent::ProxyExecuted(Ok(())).into()); assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone())); - System::assert_last_event(ProxyEvent::ProxyExecuted(Err(DispatchError::BadOrigin)).into()); + System::assert_last_event( + ProxyEvent::ProxyExecuted(Err(SystemError::CallFiltered.into())).into(), + ); assert_ok!(Proxy::proxy(Origin::signed(4), 1, None, call.clone())); - System::assert_last_event(ProxyEvent::ProxyExecuted(Err(DispatchError::BadOrigin)).into()); + System::assert_last_event( + ProxyEvent::ProxyExecuted(Err(SystemError::CallFiltered.into())).into(), + ); let call = Box::new(Call::Utility(UtilityCall::batch { calls: vec![*inner] })); assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, call.clone())); @@ -355,10 +363,12 @@ fn filtering_works() { ProxyEvent::ProxyExecuted(Ok(())).into(), ]); assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone())); - System::assert_last_event(ProxyEvent::ProxyExecuted(Err(DispatchError::BadOrigin)).into()); + System::assert_last_event( + ProxyEvent::ProxyExecuted(Err(SystemError::CallFiltered.into())).into(), + ); assert_ok!(Proxy::proxy(Origin::signed(4), 1, None, call.clone())); expect_events(vec![ - UtilityEvent::BatchInterrupted(0, DispatchError::BadOrigin).into(), + UtilityEvent::BatchInterrupted(0, SystemError::CallFiltered.into()).into(), ProxyEvent::ProxyExecuted(Ok(())).into(), ]); @@ -371,18 +381,24 @@ fn filtering_works() { ProxyEvent::ProxyExecuted(Ok(())).into(), ]); assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone())); - System::assert_last_event(ProxyEvent::ProxyExecuted(Err(DispatchError::BadOrigin)).into()); + System::assert_last_event( + ProxyEvent::ProxyExecuted(Err(SystemError::CallFiltered.into())).into(), + ); assert_ok!(Proxy::proxy(Origin::signed(4), 1, None, call.clone())); expect_events(vec![ - UtilityEvent::BatchInterrupted(0, DispatchError::BadOrigin).into(), + UtilityEvent::BatchInterrupted(0, SystemError::CallFiltered.into()).into(), ProxyEvent::ProxyExecuted(Ok(())).into(), ]); let call = Box::new(Call::Proxy(ProxyCall::remove_proxies {})); assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone())); - System::assert_last_event(ProxyEvent::ProxyExecuted(Err(DispatchError::BadOrigin)).into()); + System::assert_last_event( + ProxyEvent::ProxyExecuted(Err(SystemError::CallFiltered.into())).into(), + ); assert_ok!(Proxy::proxy(Origin::signed(4), 1, None, call.clone())); - System::assert_last_event(ProxyEvent::ProxyExecuted(Err(DispatchError::BadOrigin)).into()); + System::assert_last_event( + ProxyEvent::ProxyExecuted(Err(SystemError::CallFiltered.into())).into(), + ); assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, call.clone())); expect_events(vec![ BalancesEvent::::Unreserved(1, 5).into(), @@ -462,13 +478,17 @@ fn proxying_works() { let call = Box::new(Call::System(SystemCall::set_code { code: vec![] })); assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone())); - System::assert_last_event(ProxyEvent::ProxyExecuted(Err(DispatchError::BadOrigin)).into()); + System::assert_last_event( + ProxyEvent::ProxyExecuted(Err(SystemError::CallFiltered.into())).into(), + ); let call = Box::new(Call::Balances(BalancesCall::transfer_keep_alive { dest: 6, value: 1 })); assert_ok!(Call::Proxy(super::Call::new_call_variant_proxy(1, None, call.clone())) .dispatch(Origin::signed(2))); - System::assert_last_event(ProxyEvent::ProxyExecuted(Err(DispatchError::BadOrigin)).into()); + System::assert_last_event( + ProxyEvent::ProxyExecuted(Err(SystemError::CallFiltered.into())).into(), + ); assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone())); System::assert_last_event(ProxyEvent::ProxyExecuted(Ok(())).into()); assert_eq!(Balances::free_balance(6), 2); diff --git a/frame/support/procedural/src/construct_runtime/expand/call.rs b/frame/support/procedural/src/construct_runtime/expand/call.rs index 2532a680e21b..5658ec045433 100644 --- a/frame/support/procedural/src/construct_runtime/expand/call.rs +++ b/frame/support/procedural/src/construct_runtime/expand/call.rs @@ -22,6 +22,7 @@ use syn::Ident; pub fn expand_outer_dispatch( runtime: &Ident, + system_pallet: &Pallet, pallet_decls: &[Pallet], scrate: &TokenStream, ) -> TokenStream { @@ -29,6 +30,7 @@ pub fn expand_outer_dispatch( let mut variant_patterns = Vec::new(); let mut query_call_part_macros = Vec::new(); let mut pallet_names = Vec::new(); + let system_path = &system_pallet.path; let pallets_with_call = pallet_decls.iter().filter(|decl| decl.exists_part("Call")); @@ -106,7 +108,9 @@ pub fn expand_outer_dispatch( type PostInfo = #scrate::weights::PostDispatchInfo; fn dispatch(self, origin: Origin) -> #scrate::dispatch::DispatchResultWithPostInfo { if !::filter_call(&origin, &self) { - return #scrate::sp_std::result::Result::Err(#scrate::dispatch::DispatchError::BadOrigin.into()); + return #scrate::sp_std::result::Result::Err( + #system_path::Error::<#runtime>::CallFiltered.into() + ); } #scrate::traits::UnfilteredDispatchable::dispatch_bypass_filter(self, origin) diff --git a/frame/support/procedural/src/construct_runtime/expand/origin.rs b/frame/support/procedural/src/construct_runtime/expand/origin.rs index 57adf86a9fe1..eb0212c3efee 100644 --- a/frame/support/procedural/src/construct_runtime/expand/origin.rs +++ b/frame/support/procedural/src/construct_runtime/expand/origin.rs @@ -18,23 +18,14 @@ use crate::construct_runtime::{Pallet, SYSTEM_PALLET_NAME}; use proc_macro2::TokenStream; use quote::quote; -use syn::{token, Generics, Ident}; +use syn::{Generics, Ident}; pub fn expand_outer_origin( runtime: &Ident, + system_pallet: &Pallet, pallets: &[Pallet], - pallets_token: token::Brace, scrate: &TokenStream, ) -> syn::Result { - let system_pallet = - pallets.iter().find(|decl| decl.name == SYSTEM_PALLET_NAME).ok_or_else(|| { - syn::Error::new( - pallets_token.span, - "`System` pallet declaration is missing. \ - Please add this line: `System: frame_system::{Pallet, Call, Storage, Config, Event},`", - ) - })?; - let mut caller_variants = TokenStream::new(); let mut pallet_conversions = TokenStream::new(); let mut query_origin_part_macros = Vec::new(); diff --git a/frame/support/procedural/src/construct_runtime/mod.rs b/frame/support/procedural/src/construct_runtime/mod.rs index 4315d4278183..f54fa79ce609 100644 --- a/frame/support/procedural/src/construct_runtime/mod.rs +++ b/frame/support/procedural/src/construct_runtime/mod.rs @@ -214,17 +214,26 @@ fn construct_runtime_final_expansion( pallets_token, } = definition; + let system_pallet = + pallets.iter().find(|decl| decl.name == SYSTEM_PALLET_NAME).ok_or_else(|| { + syn::Error::new( + pallets_token.span, + "`System` pallet declaration is missing. \ + Please add this line: `System: frame_system::{Pallet, Call, Storage, Config, Event},`", + ) + })?; + let hidden_crate_name = "construct_runtime"; let scrate = generate_crate_access(&hidden_crate_name, "frame-support"); let scrate_decl = generate_hidden_includes(&hidden_crate_name, "frame-support"); let outer_event = expand::expand_outer_event(&name, &pallets, &scrate)?; - let outer_origin = expand::expand_outer_origin(&name, &pallets, pallets_token, &scrate)?; + let outer_origin = expand::expand_outer_origin(&name, &system_pallet, &pallets, &scrate)?; let all_pallets = decl_all_pallets(&name, pallets.iter()); let pallet_to_index = decl_pallet_runtime_setup(&name, &pallets, &scrate); - let dispatch = expand::expand_outer_dispatch(&name, &pallets, &scrate); + let dispatch = expand::expand_outer_dispatch(&name, &system_pallet, &pallets, &scrate); let metadata = expand::expand_runtime_metadata(&name, &pallets, &scrate, &unchecked_extrinsic); let outer_config = expand::expand_outer_config(&name, &pallets, &scrate); let inherent = diff --git a/frame/support/test/tests/system.rs b/frame/support/test/tests/system.rs index 4acc248d25f2..9def12131dd1 100644 --- a/frame/support/test/tests/system.rs +++ b/frame/support/test/tests/system.rs @@ -63,7 +63,9 @@ frame_support::decl_error! { TestError, /// Error documentation /// with multiple lines - AnotherError + AnotherError, + // Required by construct_runtime + CallFiltered, } } diff --git a/frame/system/src/lib.rs b/frame/system/src/lib.rs index 2e7f26eef16f..41e1738c034f 100644 --- a/frame/system/src/lib.rs +++ b/frame/system/src/lib.rs @@ -560,6 +560,8 @@ pub mod pallet { NonDefaultComposite, /// There is a non-zero reference count preventing the account from being purged. NonZeroRefCount, + /// The origin filter prevent the call to be dispatched. + CallFiltered, } /// Exposed trait-generic origin type. diff --git a/frame/utility/src/tests.rs b/frame/utility/src/tests.rs index bbfbb417e23d..cb7a3d9a21e2 100644 --- a/frame/utility/src/tests.rs +++ b/frame/utility/src/tests.rs @@ -288,7 +288,7 @@ fn as_derivative_filters() { value: 1 })), ), - DispatchError::BadOrigin + DispatchError::from(frame_system::Error::::CallFiltered), ); }); } @@ -338,7 +338,8 @@ fn batch_with_signed_filters() { vec![Call::Balances(pallet_balances::Call::transfer_keep_alive { dest: 2, value: 1 })] ),); System::assert_last_event( - utility::Event::BatchInterrupted(0, DispatchError::BadOrigin).into(), + utility::Event::BatchInterrupted(0, frame_system::Error::::CallFiltered.into()) + .into(), ); }); } @@ -573,7 +574,7 @@ fn batch_all_does_not_nest() { actual_weight: Some(::WeightInfo::batch_all(1) + info.weight), pays_fee: Pays::Yes }, - error: DispatchError::BadOrigin, + error: frame_system::Error::::CallFiltered.into(), } ); @@ -585,7 +586,8 @@ fn batch_all_does_not_nest() { // and balances. assert_ok!(Utility::batch_all(Origin::signed(1), vec![batch_nested])); System::assert_has_event( - utility::Event::BatchInterrupted(0, DispatchError::BadOrigin).into(), + utility::Event::BatchInterrupted(0, frame_system::Error::::CallFiltered.into()) + .into(), ); assert_eq!(Balances::free_balance(1), 10); assert_eq!(Balances::free_balance(2), 10); From 079889e54ddd18c16e0ff90221fbf8b5b76e5275 Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Tue, 2 Nov 2021 20:24:00 +0000 Subject: [PATCH 126/695] add missing version to dependencies (#10148) --- frame/bags-list/remote-tests/Cargo.toml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/frame/bags-list/remote-tests/Cargo.toml b/frame/bags-list/remote-tests/Cargo.toml index c670178c6188..ee5b8c7c3f6e 100644 --- a/frame/bags-list/remote-tests/Cargo.toml +++ b/frame/bags-list/remote-tests/Cargo.toml @@ -14,21 +14,21 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] # frame -pallet-staking = { path = "../../staking" } -pallet-bags-list = { path = "../../bags-list" } -frame-election-provider-support = { path = "../../election-provider-support" } -frame-system = { path = "../../system" } -frame-support = { path = "../../support" } +pallet-staking = { path = "../../staking", version = "4.0.0-dev" } +pallet-bags-list = { path = "../../bags-list", version = "4.0.0-dev" } +frame-election-provider-support = { path = "../../election-provider-support", version = "4.0.0-dev" } +frame-system = { path = "../../system", version = "4.0.0-dev" } +frame-support = { path = "../../support", version = "4.0.0-dev" } # core -sp-storage = { path = "../../../primitives/storage" } -sp-core = { path = "../../../primitives/core" } -sp-tracing = { path = "../../../primitives/tracing" } -sp-runtime = { path = "../../../primitives/runtime" } -sp-std = { path = "../../../primitives/std" } +sp-storage = { path = "../../../primitives/storage", version = "4.0.0-dev" } +sp-core = { path = "../../../primitives/core", version = "4.0.0-dev" } +sp-tracing = { path = "../../../primitives/tracing", version = "4.0.0-dev" } +sp-runtime = { path = "../../../primitives/runtime", version = "4.0.0-dev" } +sp-std = { path = "../../../primitives/std", version = "4.0.0-dev" } # utils -remote-externalities = { path = "../../../utils/frame/remote-externalities" } +remote-externalities = { path = "../../../utils/frame/remote-externalities", version = "0.10.0-dev" } # others tokio = { version = "1", features = ["macros"] } From 7e42d7788002eadd94d3ce7782986a3fc6924e19 Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Tue, 2 Nov 2021 22:21:39 +0100 Subject: [PATCH 127/695] Bump parity-db (#10151) --- Cargo.lock | 4 ++-- client/db/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 20499facb5b7..a6f808ac00f0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6194,9 +6194,9 @@ dependencies = [ [[package]] name = "parity-db" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91b679c6acc14fac74382942e2b73bea441686a33430b951ea03b5aeb6a7f254" +checksum = "e7ccc4a8687027deb53d45c5434a1f1b330c9d1069a59cfe80a62aa9a1da25ae" dependencies = [ "blake2-rfc", "crc32fast", diff --git a/client/db/Cargo.toml b/client/db/Cargo.toml index 53af082d3b91..165d01d55511 100644 --- a/client/db/Cargo.toml +++ b/client/db/Cargo.toml @@ -33,7 +33,7 @@ sc-state-db = { version = "0.10.0-dev", path = "../state-db" } sp-trie = { version = "4.0.0-dev", path = "../../primitives/trie" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-database = { version = "4.0.0-dev", path = "../../primitives/database" } -parity-db = { version = "0.3.2", optional = true } +parity-db = { version = "0.3.3", optional = true } [dev-dependencies] sp-tracing = { version = "4.0.0-dev", path = "../../primitives/tracing" } From 85a2a7a2820c0d1032903ac5584eda81461bad30 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Wed, 3 Nov 2021 10:12:50 +0100 Subject: [PATCH 128/695] Add a `trie_root_hash` variant for chain specs genesis (#10140) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add a `hash` variant for chain specs * Add doc * Rename to TrieRootHash * Apply suggestions from code review Co-authored-by: Bastian Köcher * Rustfmt * More cargo fmt I guess * Ok I have to use nightly cargo fmt Co-authored-by: Bastian Köcher --- client/chain-spec/src/chain_spec.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/client/chain-spec/src/chain_spec.rs b/client/chain-spec/src/chain_spec.rs index 2ddb56a0df84..4aa0aa74630e 100644 --- a/client/chain-spec/src/chain_spec.rs +++ b/client/chain-spec/src/chain_spec.rs @@ -119,6 +119,10 @@ impl BuildStorage for ChainSpec { }) .collect(), }), + // The `StateRootHash` variant exists as a way to keep note that other clients support + // it, but Substrate itself isn't capable of loading chain specs with just a hash at the + // moment. + Genesis::StateRootHash(_) => Err("Genesis storage in hash format not supported".into()), } } @@ -144,6 +148,8 @@ pub struct RawGenesis { enum Genesis { Runtime(G), Raw(RawGenesis), + /// State root hash of the genesis storage. + StateRootHash(StorageData), } /// A configuration of a client. Does not include runtime storage initialization. From 26e5f5f526ced19dfe649010e8f19e2c3f957b12 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Nov 2021 10:29:16 +0000 Subject: [PATCH 129/695] Bump prost-build from 0.8.0 to 0.9.0 (#10162) Bumps [prost-build](https://github.com/tokio-rs/prost) from 0.8.0 to 0.9.0. - [Release notes](https://github.com/tokio-rs/prost/releases) - [Commits](https://github.com/tokio-rs/prost/compare/v0.8.0...v0.9.0) --- updated-dependencies: - dependency-name: prost-build dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 121 ++++++++++++++++++++------ client/authority-discovery/Cargo.toml | 2 +- client/network/Cargo.toml | 2 +- 3 files changed, 97 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a6f808ac00f0..39dedb31839d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1886,6 +1886,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" +[[package]] +name = "fixedbitset" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "398ea4fabe40b9b0d885340a2a991a44c8a645624075ad966d21f88688e2b69e" + [[package]] name = "flate2" version = "1.0.20" @@ -3393,8 +3399,8 @@ dependencies = [ "multistream-select", "parking_lot 0.11.1", "pin-project 1.0.8", - "prost", - "prost-build", + "prost 0.8.0", + "prost-build 0.8.0", "rand 0.7.3", "ring", "rw-stream-sink", @@ -3443,8 +3449,8 @@ dependencies = [ "libp2p-core", "libp2p-swarm", "log 0.4.14", - "prost", - "prost-build", + "prost 0.8.0", + "prost-build 0.8.0", "rand 0.7.3", "smallvec 1.7.0", ] @@ -3465,8 +3471,8 @@ dependencies = [ "libp2p-core", "libp2p-swarm", "log 0.4.14", - "prost", - "prost-build", + "prost 0.8.0", + "prost-build 0.8.0", "rand 0.7.3", "regex", "sha2 0.9.8", @@ -3485,8 +3491,8 @@ dependencies = [ "libp2p-core", "libp2p-swarm", "log 0.4.14", - "prost", - "prost-build", + "prost 0.8.0", + "prost-build 0.8.0", "smallvec 1.7.0", "wasm-timer", ] @@ -3506,8 +3512,8 @@ dependencies = [ "libp2p-core", "libp2p-swarm", "log 0.4.14", - "prost", - "prost-build", + "prost 0.8.0", + "prost-build 0.8.0", "rand 0.7.3", "sha2 0.9.8", "smallvec 1.7.0", @@ -3568,8 +3574,8 @@ dependencies = [ "lazy_static", "libp2p-core", "log 0.4.14", - "prost", - "prost-build", + "prost 0.8.0", + "prost-build 0.8.0", "rand 0.8.4", "sha2 0.9.8", "snow", @@ -3604,8 +3610,8 @@ dependencies = [ "futures 0.3.16", "libp2p-core", "log 0.4.14", - "prost", - "prost-build", + "prost 0.8.0", + "prost-build 0.8.0", "unsigned-varint 0.7.0", "void", ] @@ -3638,8 +3644,8 @@ dependencies = [ "libp2p-swarm", "log 0.4.14", "pin-project 1.0.8", - "prost", - "prost-build", + "prost 0.8.0", + "prost-build 0.8.0", "rand 0.7.3", "smallvec 1.7.0", "unsigned-varint 0.7.0", @@ -6485,7 +6491,17 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7" dependencies = [ - "fixedbitset", + "fixedbitset 0.2.0", + "indexmap", +] + +[[package]] +name = "petgraph" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a13a2fa9d0b63e5f22328828741e523766fff0ee9e779316902290dff3f824f" +dependencies = [ + "fixedbitset 0.4.0", "indexmap", ] @@ -6792,7 +6808,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de5e2533f59d08fcf364fd374ebda0692a70bd6d7e66ef97f306f45c6c5d8020" dependencies = [ "bytes 1.0.1", - "prost-derive", + "prost-derive 0.8.0", +] + +[[package]] +name = "prost" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001" +dependencies = [ + "bytes 1.0.1", + "prost-derive 0.9.0", ] [[package]] @@ -6806,9 +6832,29 @@ dependencies = [ "itertools", "log 0.4.14", "multimap", - "petgraph", - "prost", - "prost-types", + "petgraph 0.5.1", + "prost 0.8.0", + "prost-types 0.8.0", + "tempfile", + "which", +] + +[[package]] +name = "prost-build" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62941722fb675d463659e49c4f3fe1fe792ff24fe5bbaa9c08cd3b98a1c354f5" +dependencies = [ + "bytes 1.0.1", + "heck", + "itertools", + "lazy_static", + "log 0.4.14", + "multimap", + "petgraph 0.6.0", + "prost 0.9.0", + "prost-types 0.9.0", + "regex", "tempfile", "which", ] @@ -6826,6 +6872,19 @@ dependencies = [ "syn", ] +[[package]] +name = "prost-derive" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9cc1a3263e07e0bf68e96268f37665207b49560d98739662cdfaae215c720fe" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "prost-types" version = "0.8.0" @@ -6833,7 +6892,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "603bbd6394701d13f3f25aada59c7de9d35a6a5887cfc156181234a44002771b" dependencies = [ "bytes 1.0.1", - "prost", + "prost 0.8.0", +] + +[[package]] +name = "prost-types" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534b7a0e836e3c482d2693070f982e39e7611da9695d4d1f5a4b186b51faef0a" +dependencies = [ + "bytes 1.0.1", + "prost 0.9.0", ] [[package]] @@ -7471,8 +7540,8 @@ dependencies = [ "libp2p", "log 0.4.14", "parity-scale-codec", - "prost", - "prost-build", + "prost 0.8.0", + "prost-build 0.9.0", "quickcheck", "rand 0.7.3", "sc-client-api", @@ -8138,8 +8207,8 @@ dependencies = [ "parity-scale-codec", "parking_lot 0.11.1", "pin-project 1.0.8", - "prost", - "prost-build", + "prost 0.8.0", + "prost-build 0.9.0", "quickcheck", "rand 0.7.3", "sc-block-builder", diff --git a/client/authority-discovery/Cargo.toml b/client/authority-discovery/Cargo.toml index cee35a43df2f..dca365981984 100644 --- a/client/authority-discovery/Cargo.toml +++ b/client/authority-discovery/Cargo.toml @@ -14,7 +14,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [build-dependencies] -prost-build = "0.8" +prost-build = "0.9" [dependencies] async-trait = "0.1" diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index d6d054504369..7b4b30c59385 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -14,7 +14,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [build-dependencies] -prost-build = "0.8" +prost-build = "0.9" [dependencies] async-trait = "0.1" From bdf97a350054b882dbe0c1cdcb377b3a9bf2e411 Mon Sep 17 00:00:00 2001 From: Alexander Samusev <41779041+alvicsam@users.noreply.github.com> Date: Wed, 3 Nov 2021 13:23:32 +0100 Subject: [PATCH 130/695] Update CI image to the latest rustc (#10142) * Update CI image to the latest rustc * Update rustc error messages * whitespace * update test output * updating compiler errors * kid's finally learning to read and spots the TRYBUILD=overwrite message. * undoing a little blessing * imperfect error msg * revert ci image to production Co-authored-by: gilescope --- .../no_std_genesis_config.stderr | 7 +- .../undefined_call_part.stderr | 9 +- .../undefined_event_part.stderr | 9 +- .../undefined_genesis_config_part.stderr | 9 +- .../undefined_inherent_part.stderr | 9 +- .../undefined_origin_part.stderr | 9 +- .../undefined_validate_unsigned_part.stderr | 9 +- .../test/tests/derive_no_bound_ui/eq.stderr | 10 +- .../call_argument_invalid_bound.stderr | 2 +- .../call_argument_invalid_bound_2.stderr | 22 ++--- .../pallet_ui/event_field_not_member.stderr | 2 +- .../genesis_default_not_satisfied.stderr | 7 +- .../tests/pallet_ui/hooks_invalid_item.stderr | 2 +- ...age_ensure_span_are_ok_on_wrong_gen.stderr | 92 +++++++++---------- ...re_span_are_ok_on_wrong_gen_unnamed.stderr | 92 +++++++++---------- .../type_value_forgotten_where_clause.stderr | 42 +++++---- ...reference_in_impl_runtime_apis_call.stderr | 11 ++- 17 files changed, 186 insertions(+), 157 deletions(-) diff --git a/frame/support/test/tests/construct_runtime_ui/no_std_genesis_config.stderr b/frame/support/test/tests/construct_runtime_ui/no_std_genesis_config.stderr index 3dc7fcda9f18..e458265a07ca 100644 --- a/frame/support/test/tests/construct_runtime_ui/no_std_genesis_config.stderr +++ b/frame/support/test/tests/construct_runtime_ui/no_std_genesis_config.stderr @@ -82,7 +82,8 @@ error[E0277]: the trait bound `Runtime: frame_system::pallet::Config` is not sat 11 | impl test_pallet::Config for Runtime {} | ^^^^^^^^^^^^^^^^^^^ the trait `frame_system::pallet::Config` is not implemented for `Runtime` | - ::: $WORKSPACE/frame/support/test/pallet/src/lib.rs +note: required by a bound in `Config` + --> $DIR/lib.rs:30:20 | - | pub trait Config: frame_system::Config {} - | -------------------- required by this bound in `Config` +30 | pub trait Config: frame_system::Config {} + | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `Config` diff --git a/frame/support/test/tests/construct_runtime_ui/undefined_call_part.stderr b/frame/support/test/tests/construct_runtime_ui/undefined_call_part.stderr index 2629cf410192..c4e567102a89 100644 --- a/frame/support/test/tests/construct_runtime_ui/undefined_call_part.stderr +++ b/frame/support/test/tests/construct_runtime_ui/undefined_call_part.stderr @@ -66,8 +66,11 @@ help: consider importing one of these items error[E0277]: the trait bound `Runtime: frame_system::Config` is not satisfied --> $DIR/undefined_call_part.rs:20:6 | -8 | pub trait Config: frame_system::Config {} - | -------------------- required by this bound in `pallet::Config` -... 20 | impl pallet::Config for Runtime {} | ^^^^^^^^^^^^^^ the trait `frame_system::Config` is not implemented for `Runtime` + | +note: required by a bound in `pallet::Config` + --> $DIR/undefined_call_part.rs:8:20 + | +8 | pub trait Config: frame_system::Config {} + | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `pallet::Config` diff --git a/frame/support/test/tests/construct_runtime_ui/undefined_event_part.stderr b/frame/support/test/tests/construct_runtime_ui/undefined_event_part.stderr index af69b79ed1a6..da972f6f4b2f 100644 --- a/frame/support/test/tests/construct_runtime_ui/undefined_event_part.stderr +++ b/frame/support/test/tests/construct_runtime_ui/undefined_event_part.stderr @@ -104,8 +104,11 @@ help: consider importing one of these items error[E0277]: the trait bound `Runtime: frame_system::Config` is not satisfied --> $DIR/undefined_event_part.rs:20:6 | -8 | pub trait Config: frame_system::Config {} - | -------------------- required by this bound in `pallet::Config` -... 20 | impl pallet::Config for Runtime {} | ^^^^^^^^^^^^^^ the trait `frame_system::Config` is not implemented for `Runtime` + | +note: required by a bound in `pallet::Config` + --> $DIR/undefined_event_part.rs:8:20 + | +8 | pub trait Config: frame_system::Config {} + | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `pallet::Config` diff --git a/frame/support/test/tests/construct_runtime_ui/undefined_genesis_config_part.stderr b/frame/support/test/tests/construct_runtime_ui/undefined_genesis_config_part.stderr index bfedb921bca4..8e40773b6573 100644 --- a/frame/support/test/tests/construct_runtime_ui/undefined_genesis_config_part.stderr +++ b/frame/support/test/tests/construct_runtime_ui/undefined_genesis_config_part.stderr @@ -84,8 +84,11 @@ help: consider importing this struct error[E0277]: the trait bound `Runtime: frame_system::Config` is not satisfied --> $DIR/undefined_genesis_config_part.rs:20:6 | -8 | pub trait Config: frame_system::Config {} - | -------------------- required by this bound in `pallet::Config` -... 20 | impl pallet::Config for Runtime {} | ^^^^^^^^^^^^^^ the trait `frame_system::Config` is not implemented for `Runtime` + | +note: required by a bound in `pallet::Config` + --> $DIR/undefined_genesis_config_part.rs:8:20 + | +8 | pub trait Config: frame_system::Config {} + | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `pallet::Config` diff --git a/frame/support/test/tests/construct_runtime_ui/undefined_inherent_part.stderr b/frame/support/test/tests/construct_runtime_ui/undefined_inherent_part.stderr index 50dde1108263..ae461473c3b1 100644 --- a/frame/support/test/tests/construct_runtime_ui/undefined_inherent_part.stderr +++ b/frame/support/test/tests/construct_runtime_ui/undefined_inherent_part.stderr @@ -66,8 +66,11 @@ help: consider importing one of these items error[E0277]: the trait bound `Runtime: frame_system::Config` is not satisfied --> $DIR/undefined_inherent_part.rs:20:6 | -8 | pub trait Config: frame_system::Config {} - | -------------------- required by this bound in `pallet::Config` -... 20 | impl pallet::Config for Runtime {} | ^^^^^^^^^^^^^^ the trait `frame_system::Config` is not implemented for `Runtime` + | +note: required by a bound in `pallet::Config` + --> $DIR/undefined_inherent_part.rs:8:20 + | +8 | pub trait Config: frame_system::Config {} + | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `pallet::Config` diff --git a/frame/support/test/tests/construct_runtime_ui/undefined_origin_part.stderr b/frame/support/test/tests/construct_runtime_ui/undefined_origin_part.stderr index b5f3ec4d381b..dbdd9f869a2e 100644 --- a/frame/support/test/tests/construct_runtime_ui/undefined_origin_part.stderr +++ b/frame/support/test/tests/construct_runtime_ui/undefined_origin_part.stderr @@ -104,8 +104,11 @@ help: consider importing one of these items error[E0277]: the trait bound `Runtime: frame_system::Config` is not satisfied --> $DIR/undefined_origin_part.rs:20:6 | -8 | pub trait Config: frame_system::Config {} - | -------------------- required by this bound in `pallet::Config` -... 20 | impl pallet::Config for Runtime {} | ^^^^^^^^^^^^^^ the trait `frame_system::Config` is not implemented for `Runtime` + | +note: required by a bound in `pallet::Config` + --> $DIR/undefined_origin_part.rs:8:20 + | +8 | pub trait Config: frame_system::Config {} + | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `pallet::Config` diff --git a/frame/support/test/tests/construct_runtime_ui/undefined_validate_unsigned_part.stderr b/frame/support/test/tests/construct_runtime_ui/undefined_validate_unsigned_part.stderr index 12bdce67cf03..8126d2f9a3e0 100644 --- a/frame/support/test/tests/construct_runtime_ui/undefined_validate_unsigned_part.stderr +++ b/frame/support/test/tests/construct_runtime_ui/undefined_validate_unsigned_part.stderr @@ -66,8 +66,11 @@ help: consider importing one of these items error[E0277]: the trait bound `Runtime: frame_system::Config` is not satisfied --> $DIR/undefined_validate_unsigned_part.rs:20:6 | -8 | pub trait Config: frame_system::Config {} - | -------------------- required by this bound in `pallet::Config` -... 20 | impl pallet::Config for Runtime {} | ^^^^^^^^^^^^^^ the trait `frame_system::Config` is not implemented for `Runtime` + | +note: required by a bound in `pallet::Config` + --> $DIR/undefined_validate_unsigned_part.rs:8:20 + | +8 | pub trait Config: frame_system::Config {} + | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `pallet::Config` diff --git a/frame/support/test/tests/derive_no_bound_ui/eq.stderr b/frame/support/test/tests/derive_no_bound_ui/eq.stderr index fce13d6f17f0..19fb3ac248b8 100644 --- a/frame/support/test/tests/derive_no_bound_ui/eq.stderr +++ b/frame/support/test/tests/derive_no_bound_ui/eq.stderr @@ -4,9 +4,9 @@ error[E0277]: can't compare `Foo` with `Foo` 6 | struct Foo { | ^^^ no implementation for `Foo == Foo` | - ::: $RUST/core/src/cmp.rs - | - | pub trait Eq: PartialEq { - | --------------- required by this bound in `std::cmp::Eq` - | = help: the trait `PartialEq` is not implemented for `Foo` +note: required by a bound in `std::cmp::Eq` + --> $DIR/cmp.rs:272:15 + | +272 | pub trait Eq: PartialEq { + | ^^^^^^^^^^^^^^^ required by this bound in `std::cmp::Eq` diff --git a/frame/support/test/tests/pallet_ui/call_argument_invalid_bound.stderr b/frame/support/test/tests/pallet_ui/call_argument_invalid_bound.stderr index 3d1ea1adc986..b7a8e40e69a1 100644 --- a/frame/support/test/tests/pallet_ui/call_argument_invalid_bound.stderr +++ b/frame/support/test/tests/pallet_ui/call_argument_invalid_bound.stderr @@ -29,4 +29,4 @@ error[E0369]: binary operation `==` cannot be applied to type `&::Bar: WrapperTypeEncode` is not satisfied --> $DIR/call_argument_invalid_bound_2.rs:1:1 @@ -47,12 +47,12 @@ error[E0277]: the trait bound `::Bar: WrapperTypeEncode` is 17 | | #[pallet::call] | |__________________^ the trait `WrapperTypeEncode` is not implemented for `::Bar` | - ::: $CARGO/parity-scale-codec-2.3.1/src/codec.rs - | - | fn encode_to(&self, dest: &mut T) { - | ------ required by this bound in `encode_to` - | = note: required because of the requirements on the impl of `Encode` for `::Bar` +note: required by a bound in `encode_to` + --> $DIR/codec.rs:223:18 + | +223 | fn encode_to(&self, dest: &mut T) { + | ^^^^^^ required by this bound in `encode_to` = note: this error originates in the derive macro `frame_support::codec::Encode` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `::Bar: WrapperTypeDecode` is not satisfied @@ -61,9 +61,9 @@ error[E0277]: the trait bound `::Bar: WrapperTypeDecode` is 20 | pub fn foo(origin: OriginFor, bar: T::Bar) -> DispatchResultWithPostInfo { | ^^^ the trait `WrapperTypeDecode` is not implemented for `::Bar` | - ::: $CARGO/parity-scale-codec-2.3.1/src/codec.rs - | - | fn decode(input: &mut I) -> Result; - | ----- required by this bound in `parity_scale_codec::Decode::decode` - | = note: required because of the requirements on the impl of `Decode` for `::Bar` +note: required by a bound in `parity_scale_codec::Decode::decode` + --> $DIR/codec.rs:284:15 + | +284 | fn decode(input: &mut I) -> Result; + | ^^^^^ required by this bound in `parity_scale_codec::Decode::decode` diff --git a/frame/support/test/tests/pallet_ui/event_field_not_member.stderr b/frame/support/test/tests/pallet_ui/event_field_not_member.stderr index bf4c05bb4e5b..06384b0b66b8 100644 --- a/frame/support/test/tests/pallet_ui/event_field_not_member.stderr +++ b/frame/support/test/tests/pallet_ui/event_field_not_member.stderr @@ -19,7 +19,7 @@ error[E0369]: binary operation `==` cannot be applied to type `& { - | ^^^^^^^^^^^^^^^^^^^^^ + | +++++++++++++++++++++ error[E0277]: `::Bar` doesn't implement `std::fmt::Debug` --> $DIR/event_field_not_member.rs:23:7 diff --git a/frame/support/test/tests/pallet_ui/genesis_default_not_satisfied.stderr b/frame/support/test/tests/pallet_ui/genesis_default_not_satisfied.stderr index ad8300b8d89b..057611367fe5 100644 --- a/frame/support/test/tests/pallet_ui/genesis_default_not_satisfied.stderr +++ b/frame/support/test/tests/pallet_ui/genesis_default_not_satisfied.stderr @@ -4,7 +4,8 @@ error[E0277]: the trait bound `pallet::GenesisConfig: std::default::Default` is 22 | impl GenesisBuild for GenesisConfig {} | ^^^^^^^^^^^^^^^ the trait `std::default::Default` is not implemented for `pallet::GenesisConfig` | - ::: $WORKSPACE/frame/support/src/traits/hooks.rs +note: required by a bound in `GenesisBuild` + --> $DIR/hooks.rs:297:36 | - | pub trait GenesisBuild: Default + sp_runtime::traits::MaybeSerializeDeserialize { - | ------- required by this bound in `GenesisBuild` +297 | pub trait GenesisBuild: Default + sp_runtime::traits::MaybeSerializeDeserialize { + | ^^^^^^^ required by this bound in `GenesisBuild` diff --git a/frame/support/test/tests/pallet_ui/hooks_invalid_item.stderr b/frame/support/test/tests/pallet_ui/hooks_invalid_item.stderr index ecb57bec37a7..d1a89fbb850e 100644 --- a/frame/support/test/tests/pallet_ui/hooks_invalid_item.stderr +++ b/frame/support/test/tests/pallet_ui/hooks_invalid_item.stderr @@ -12,4 +12,4 @@ note: trait defined here, with 1 generic parameter: `BlockNumber` help: add missing generic argument | 12 | impl Hooks for Pallet {} - | ^^^^^^^^^^^^^^^^^^ + | ~~~~~~~~~~~~~~~~~~ diff --git a/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.stderr b/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.stderr index cd3032c49735..82fd3ad884f9 100644 --- a/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.stderr +++ b/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.stderr @@ -1,3 +1,49 @@ +error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied + --> $DIR/storage_ensure_span_are_ok_on_wrong_gen.rs:9:12 + | +9 | #[pallet::pallet] + | ^^^^^^ the trait `WrapperTypeDecode` is not implemented for `Bar` + | + = note: required because of the requirements on the impl of `Decode` for `Bar` + = note: required because of the requirements on the impl of `FullCodec` for `Bar` + = note: required because of the requirements on the impl of `PartialStorageInfoTrait` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` +note: required by `partial_storage_info` + --> $DIR/storage.rs:88:2 + | +88 | fn partial_storage_info() -> Vec; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: the trait bound `Bar: EncodeLike` is not satisfied + --> $DIR/storage_ensure_span_are_ok_on_wrong_gen.rs:9:12 + | +9 | #[pallet::pallet] + | ^^^^^^ the trait `EncodeLike` is not implemented for `Bar` + | + = note: required because of the requirements on the impl of `FullEncode` for `Bar` + = note: required because of the requirements on the impl of `FullCodec` for `Bar` + = note: required because of the requirements on the impl of `PartialStorageInfoTrait` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` +note: required by `partial_storage_info` + --> $DIR/storage.rs:88:2 + | +88 | fn partial_storage_info() -> Vec; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied + --> $DIR/storage_ensure_span_are_ok_on_wrong_gen.rs:9:12 + | +9 | #[pallet::pallet] + | ^^^^^^ the trait `WrapperTypeEncode` is not implemented for `Bar` + | + = note: required because of the requirements on the impl of `Encode` for `Bar` + = note: required because of the requirements on the impl of `FullEncode` for `Bar` + = note: required because of the requirements on the impl of `FullCodec` for `Bar` + = note: required because of the requirements on the impl of `PartialStorageInfoTrait` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` +note: required by `partial_storage_info` + --> $DIR/storage.rs:88:2 + | +88 | fn partial_storage_info() -> Vec; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error[E0277]: the trait bound `Bar: TypeInfo` is not satisfied --> $DIR/storage_ensure_span_are_ok_on_wrong_gen.rs:20:12 | @@ -57,49 +103,3 @@ note: required by `build_metadata` | 113 | fn build_metadata(doc: Vec<&'static str>, entries: &mut Vec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied - --> $DIR/storage_ensure_span_are_ok_on_wrong_gen.rs:9:12 - | -9 | #[pallet::pallet] - | ^^^^^^ the trait `WrapperTypeDecode` is not implemented for `Bar` - | - = note: required because of the requirements on the impl of `Decode` for `Bar` - = note: required because of the requirements on the impl of `FullCodec` for `Bar` - = note: required because of the requirements on the impl of `PartialStorageInfoTrait` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` -note: required by `partial_storage_info` - --> $DIR/storage.rs:88:2 - | -88 | fn partial_storage_info() -> Vec; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0277]: the trait bound `Bar: EncodeLike` is not satisfied - --> $DIR/storage_ensure_span_are_ok_on_wrong_gen.rs:9:12 - | -9 | #[pallet::pallet] - | ^^^^^^ the trait `EncodeLike` is not implemented for `Bar` - | - = note: required because of the requirements on the impl of `FullEncode` for `Bar` - = note: required because of the requirements on the impl of `FullCodec` for `Bar` - = note: required because of the requirements on the impl of `PartialStorageInfoTrait` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` -note: required by `partial_storage_info` - --> $DIR/storage.rs:88:2 - | -88 | fn partial_storage_info() -> Vec; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied - --> $DIR/storage_ensure_span_are_ok_on_wrong_gen.rs:9:12 - | -9 | #[pallet::pallet] - | ^^^^^^ the trait `WrapperTypeEncode` is not implemented for `Bar` - | - = note: required because of the requirements on the impl of `Encode` for `Bar` - = note: required because of the requirements on the impl of `FullEncode` for `Bar` - = note: required because of the requirements on the impl of `FullCodec` for `Bar` - = note: required because of the requirements on the impl of `PartialStorageInfoTrait` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` -note: required by `partial_storage_info` - --> $DIR/storage.rs:88:2 - | -88 | fn partial_storage_info() -> Vec; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.stderr b/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.stderr index 3d03af836986..eb1404fc62c3 100644 --- a/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.stderr +++ b/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.stderr @@ -1,3 +1,49 @@ +error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied + --> $DIR/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs:9:12 + | +9 | #[pallet::pallet] + | ^^^^^^ the trait `WrapperTypeDecode` is not implemented for `Bar` + | + = note: required because of the requirements on the impl of `Decode` for `Bar` + = note: required because of the requirements on the impl of `FullCodec` for `Bar` + = note: required because of the requirements on the impl of `PartialStorageInfoTrait` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` +note: required by `partial_storage_info` + --> $DIR/storage.rs:88:2 + | +88 | fn partial_storage_info() -> Vec; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: the trait bound `Bar: EncodeLike` is not satisfied + --> $DIR/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs:9:12 + | +9 | #[pallet::pallet] + | ^^^^^^ the trait `EncodeLike` is not implemented for `Bar` + | + = note: required because of the requirements on the impl of `FullEncode` for `Bar` + = note: required because of the requirements on the impl of `FullCodec` for `Bar` + = note: required because of the requirements on the impl of `PartialStorageInfoTrait` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` +note: required by `partial_storage_info` + --> $DIR/storage.rs:88:2 + | +88 | fn partial_storage_info() -> Vec; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied + --> $DIR/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs:9:12 + | +9 | #[pallet::pallet] + | ^^^^^^ the trait `WrapperTypeEncode` is not implemented for `Bar` + | + = note: required because of the requirements on the impl of `Encode` for `Bar` + = note: required because of the requirements on the impl of `FullEncode` for `Bar` + = note: required because of the requirements on the impl of `FullCodec` for `Bar` + = note: required because of the requirements on the impl of `PartialStorageInfoTrait` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` +note: required by `partial_storage_info` + --> $DIR/storage.rs:88:2 + | +88 | fn partial_storage_info() -> Vec; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error[E0277]: the trait bound `Bar: TypeInfo` is not satisfied --> $DIR/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs:20:12 | @@ -57,49 +103,3 @@ note: required by `build_metadata` | 113 | fn build_metadata(doc: Vec<&'static str>, entries: &mut Vec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied - --> $DIR/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs:9:12 - | -9 | #[pallet::pallet] - | ^^^^^^ the trait `WrapperTypeDecode` is not implemented for `Bar` - | - = note: required because of the requirements on the impl of `Decode` for `Bar` - = note: required because of the requirements on the impl of `FullCodec` for `Bar` - = note: required because of the requirements on the impl of `PartialStorageInfoTrait` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` -note: required by `partial_storage_info` - --> $DIR/storage.rs:88:2 - | -88 | fn partial_storage_info() -> Vec; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0277]: the trait bound `Bar: EncodeLike` is not satisfied - --> $DIR/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs:9:12 - | -9 | #[pallet::pallet] - | ^^^^^^ the trait `EncodeLike` is not implemented for `Bar` - | - = note: required because of the requirements on the impl of `FullEncode` for `Bar` - = note: required because of the requirements on the impl of `FullCodec` for `Bar` - = note: required because of the requirements on the impl of `PartialStorageInfoTrait` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` -note: required by `partial_storage_info` - --> $DIR/storage.rs:88:2 - | -88 | fn partial_storage_info() -> Vec; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied - --> $DIR/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs:9:12 - | -9 | #[pallet::pallet] - | ^^^^^^ the trait `WrapperTypeEncode` is not implemented for `Bar` - | - = note: required because of the requirements on the impl of `Encode` for `Bar` - = note: required because of the requirements on the impl of `FullEncode` for `Bar` - = note: required because of the requirements on the impl of `FullCodec` for `Bar` - = note: required because of the requirements on the impl of `PartialStorageInfoTrait` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` -note: required by `partial_storage_info` - --> $DIR/storage.rs:88:2 - | -88 | fn partial_storage_info() -> Vec; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/frame/support/test/tests/pallet_ui/type_value_forgotten_where_clause.stderr b/frame/support/test/tests/pallet_ui/type_value_forgotten_where_clause.stderr index 85d7342b253d..6288dcd534b6 100644 --- a/frame/support/test/tests/pallet_ui/type_value_forgotten_where_clause.stderr +++ b/frame/support/test/tests/pallet_ui/type_value_forgotten_where_clause.stderr @@ -1,47 +1,53 @@ error[E0277]: the trait bound `::AccountId: From` is not satisfied --> $DIR/type_value_forgotten_where_clause.rs:24:34 | -7 | pub trait Config: frame_system::Config - | ------ required by a bound in this -8 | where ::AccountId: From - | --------- required by this bound in `pallet::Config` -... 24 | #[pallet::type_value] fn Foo() -> u32 { 3u32 } | ^^^^^^ the trait `From` is not implemented for `::AccountId` | +note: required by a bound in `pallet::Config` + --> $DIR/type_value_forgotten_where_clause.rs:8:51 + | +7 | pub trait Config: frame_system::Config + | ------ required by a bound in this +8 | where ::AccountId: From + | ^^^^^^^^^ required by this bound in `pallet::Config` help: consider further restricting the associated type | 24 | #[pallet::type_value] fn Foo() -> u32 where ::AccountId: From { 3u32 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++ error[E0277]: the trait bound `::AccountId: From` is not satisfied --> $DIR/type_value_forgotten_where_clause.rs:24:12 | -7 | pub trait Config: frame_system::Config - | ------ required by a bound in this -8 | where ::AccountId: From - | --------- required by this bound in `pallet::Config` -... 24 | #[pallet::type_value] fn Foo() -> u32 { 3u32 } | ^^^^^^^^^^ the trait `From` is not implemented for `::AccountId` | +note: required by a bound in `pallet::Config` + --> $DIR/type_value_forgotten_where_clause.rs:8:51 + | +7 | pub trait Config: frame_system::Config + | ------ required by a bound in this +8 | where ::AccountId: From + | ^^^^^^^^^ required by this bound in `pallet::Config` help: consider further restricting the associated type | 24 | #[pallet::type_value where ::AccountId: From] fn Foo() -> u32 { 3u32 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++ error[E0277]: the trait bound `::AccountId: From` is not satisfied --> $DIR/type_value_forgotten_where_clause.rs:24:12 | -7 | pub trait Config: frame_system::Config - | ------ required by a bound in this -8 | where ::AccountId: From - | --------- required by this bound in `pallet::Config` -... 24 | #[pallet::type_value] fn Foo() -> u32 { 3u32 } | ^^^^^^^^^^ the trait `From` is not implemented for `::AccountId` | +note: required by a bound in `pallet::Config` + --> $DIR/type_value_forgotten_where_clause.rs:8:51 + | +7 | pub trait Config: frame_system::Config + | ------ required by a bound in this +8 | where ::AccountId: From + | ^^^^^^^^^ required by this bound in `pallet::Config` help: consider further restricting the associated type | 24 | #[pallet::type_value] fn Foo() -> u32 where ::AccountId: From { 3u32 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++ diff --git a/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.stderr b/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.stderr index 063cbff60f81..d11aebbf149b 100644 --- a/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.stderr +++ b/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.stderr @@ -58,7 +58,10 @@ error[E0308]: mismatched types --> $DIR/type_reference_in_impl_runtime_apis_call.rs:19:11 | 19 | fn test(data: &u64) { - | ^^^^^^^ - | | - | expected `u64`, found `&u64` - | help: consider removing the borrow: `data` + | ^^^^^^^ expected `u64`, found `&u64` + | +help: consider removing the borrow + | +19 - fn test(data: &u64) { +19 + fn test(data: &u64) { + | From 45f0007c262b4e51f82d02f13aece1a0401028b7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Nov 2021 19:52:41 +0000 Subject: [PATCH 131/695] Bump directories from 3.0.2 to 4.0.1 (#10163) Bumps [directories](https://github.com/soc/directories-rs) from 3.0.2 to 4.0.1. - [Release notes](https://github.com/soc/directories-rs/releases) - [Commits](https://github.com/soc/directories-rs/commits) --- updated-dependencies: - dependency-name: directories dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- client/service/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 39dedb31839d..307274395cc3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1531,9 +1531,9 @@ dependencies = [ [[package]] name = "directories" -version = "3.0.2" +version = "4.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e69600ff1703123957937708eb27f7a564e48885c537782722ed0ba3189ce1d7" +checksum = "f51c5d4ddabd36886dd3e1438cb358cdcb0d7c499cb99cb4ac2e38e18b5cb210" dependencies = [ "dirs-sys", ] diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index c3ae1452042f..bb8c9ecf6a0c 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -80,7 +80,7 @@ parity-util-mem = { version = "0.10.0", default-features = false, features = [ async-trait = "0.1.50" tokio = { version = "1.10", features = ["time", "rt-multi-thread"] } tempfile = "3.1.0" -directories = "3.0.2" +directories = "4.0.1" [dev-dependencies] substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } From 4f3b9c318551ecd88d3af6074bc05a20b060fe1c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Nov 2021 22:43:23 +0000 Subject: [PATCH 132/695] Bump linregress from 0.4.3 to 0.4.4 (#10124) Bumps [linregress](https://github.com/n1m3/linregress) from 0.4.3 to 0.4.4. - [Release notes](https://github.com/n1m3/linregress/releases) - [Changelog](https://github.com/n1m3/linregress/blob/master/CHANGELOG.md) - [Commits](https://github.com/n1m3/linregress/compare/0.4.3...0.4.4) --- updated-dependencies: - dependency-name: linregress dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- frame/benchmarking/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 307274395cc3..7ade00bc4004 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3927,9 +3927,9 @@ dependencies = [ [[package]] name = "linregress" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e6e407dadb4ca4b31bc69c27aff00e7ca4534fdcee855159b039a7cebb5f395" +checksum = "d6c601a85f5ecd1aba625247bca0031585fb1c446461b142878a16f8245ddeb8" dependencies = [ "nalgebra", "statrs", diff --git a/frame/benchmarking/Cargo.toml b/frame/benchmarking/Cargo.toml index 0600b934d44e..dffada428248 100644 --- a/frame/benchmarking/Cargo.toml +++ b/frame/benchmarking/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -linregress = { version = "0.4.3", optional = true } +linregress = { version = "0.4.4", optional = true } paste = "1.0" codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } From e40710abffde7dffcd30eb51756a7a1e9eb0e249 Mon Sep 17 00:00:00 2001 From: Guillaume Thiolliere Date: Thu, 4 Nov 2021 11:11:39 +0100 Subject: [PATCH 133/695] handle doc on type_value (#10132) --- .../procedural/src/pallet/expand/type_value.rs | 3 +++ .../procedural/src/pallet/parse/type_value.rs | 18 +++++++++++++++--- frame/support/test/tests/pallet.rs | 1 + 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/frame/support/procedural/src/pallet/expand/type_value.rs b/frame/support/procedural/src/pallet/expand/type_value.rs index 535a18777380..af4f0b3a6794 100644 --- a/frame/support/procedural/src/pallet/expand/type_value.rs +++ b/frame/support/procedural/src/pallet/expand/type_value.rs @@ -59,7 +59,10 @@ pub fn expand_type_values(def: &mut Def) -> proc_macro2::TokenStream { (Default::default(), Default::default()) }; + let docs = &type_value.docs; + expand.extend(quote::quote_spanned!(type_value.attr_span => + #( #[doc = #docs] )* #vis struct #ident<#struct_use_gen>(core::marker::PhantomData<((), #struct_use_gen)>); impl<#struct_impl_gen> #frame_support::traits::Get<#type_> for #ident<#struct_use_gen> #where_clause diff --git a/frame/support/procedural/src/pallet/parse/type_value.rs b/frame/support/procedural/src/pallet/parse/type_value.rs index 7b9d57472db4..d6cd4d02df8b 100644 --- a/frame/support/procedural/src/pallet/parse/type_value.rs +++ b/frame/support/procedural/src/pallet/parse/type_value.rs @@ -38,6 +38,8 @@ pub struct TypeValueDef { pub where_clause: Option, /// The span of the pallet::type_value attribute. pub attr_span: proc_macro2::Span, + /// Docs on the item. + pub docs: Vec, } impl TypeValueDef { @@ -53,9 +55,18 @@ impl TypeValueDef { return Err(syn::Error::new(item.span(), msg)) }; - if !item.attrs.is_empty() { - let msg = "Invalid pallet::type_value, unexpected attribute"; - return Err(syn::Error::new(item.attrs[0].span(), msg)) + let mut docs = vec![]; + for attr in &item.attrs { + if let Ok(syn::Meta::NameValue(meta)) = attr.parse_meta() { + if meta.path.get_ident().map_or(false, |ident| ident == "doc") { + docs.push(meta.lit); + continue + } + } + + let msg = "Invalid pallet::type_value, unexpected attribute, only doc attribute are \ + allowed"; + return Err(syn::Error::new(attr.span(), msg)) } if let Some(span) = item @@ -106,6 +117,7 @@ impl TypeValueDef { type_, instances, where_clause, + docs, }) } } diff --git a/frame/support/test/tests/pallet.rs b/frame/support/test/tests/pallet.rs index a314f576187d..dd171c5b12ec 100644 --- a/frame/support/test/tests/pallet.rs +++ b/frame/support/test/tests/pallet.rs @@ -262,6 +262,7 @@ pub mod pallet { #[pallet::storage_prefix = "Value2"] pub type RenamedValue = StorageValue; + /// Test some doc #[pallet::type_value] pub fn MyDefault() -> u16 where From 6af19fdc47f16bee2901908e34b70d6d7ba80c59 Mon Sep 17 00:00:00 2001 From: Dan Shields <35669742+NukeManDan@users.noreply.github.com> Date: Thu, 4 Nov 2021 14:37:26 +0100 Subject: [PATCH 134/695] Update node-template `construct_runtime!` syntax (#10155) * update `construct_runtime!` syntax * fix build --- bin/node-template/node/src/chain_spec.rs | 1 + bin/node-template/runtime/src/lib.rs | 18 +++++++++--------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/bin/node-template/node/src/chain_spec.rs b/bin/node-template/node/src/chain_spec.rs index 7009b3be5c27..baf5e5d41ab8 100644 --- a/bin/node-template/node/src/chain_spec.rs +++ b/bin/node-template/node/src/chain_spec.rs @@ -150,5 +150,6 @@ fn testnet_genesis( // Assign network admin rights. key: root_key, }, + transaction_payment: Default::default(), } } diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index dbea698002c6..8ecb2199dda7 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -286,16 +286,16 @@ construct_runtime!( NodeBlock = opaque::Block, UncheckedExtrinsic = UncheckedExtrinsic { - System: frame_system::{Pallet, Call, Config, Storage, Event}, - RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage}, - Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, - Aura: pallet_aura::{Pallet, Config}, - Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event}, - Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, - TransactionPayment: pallet_transaction_payment::{Pallet, Storage}, - Sudo: pallet_sudo::{Pallet, Call, Config, Storage, Event}, + System: frame_system, + RandomnessCollectiveFlip: pallet_randomness_collective_flip, + Timestamp: pallet_timestamp, + Aura: pallet_aura, + Grandpa: pallet_grandpa, + Balances: pallet_balances, + TransactionPayment: pallet_transaction_payment, + Sudo: pallet_sudo, // Include the custom logic from the pallet-template in the runtime. - TemplateModule: pallet_template::{Pallet, Call, Storage, Event}, + TemplateModule: pallet_template, } ); From a9465729e2c5d2ef8d87ac404da27e5e10adde8a Mon Sep 17 00:00:00 2001 From: Xiliang Chen Date: Fri, 5 Nov 2021 03:34:29 +1300 Subject: [PATCH 135/695] implement dispatch_as (#9934) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * implement dispatch_as * fix * fix * weight for dispatch_as * cargo run --quiet --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_utility --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/utility/src/weights.rs --template=./.maintain/frame-weight-template.hbs * fix * Update frame/utility/src/benchmarking.rs Co-authored-by: Alexander Theißen * fix issues Co-authored-by: Parity Bot Co-authored-by: Alexander Theißen Co-authored-by: Shawn Tabrizi --- bin/node/runtime/src/lib.rs | 1 + frame/contracts/src/tests.rs | 1 + frame/proxy/src/tests.rs | 1 + frame/utility/src/benchmarking.rs | 9 ++++++++ frame/utility/src/lib.rs | 38 +++++++++++++++++++++++++++++++ frame/utility/src/tests.rs | 1 + frame/utility/src/weights.rs | 33 ++++++++++++++++----------- 7 files changed, 71 insertions(+), 13 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index c0ad9bb006c9..570abe53ed01 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -226,6 +226,7 @@ impl pallet_randomness_collective_flip::Config for Runtime {} impl pallet_utility::Config for Runtime { type Event = Event; type Call = Call; + type PalletsOrigin = OriginCaller; type WeightInfo = pallet_utility::weights::SubstrateWeight; } diff --git a/frame/contracts/src/tests.rs b/frame/contracts/src/tests.rs index 310c1d4cb2dd..bd5dbae5b34a 100644 --- a/frame/contracts/src/tests.rs +++ b/frame/contracts/src/tests.rs @@ -244,6 +244,7 @@ impl pallet_timestamp::Config for Test { impl pallet_utility::Config for Test { type Event = Event; type Call = Call; + type PalletsOrigin = OriginCaller; type WeightInfo = (); } parameter_types! { diff --git a/frame/proxy/src/tests.rs b/frame/proxy/src/tests.rs index 20efd085fe88..93a0e4ce7d62 100644 --- a/frame/proxy/src/tests.rs +++ b/frame/proxy/src/tests.rs @@ -96,6 +96,7 @@ impl pallet_balances::Config for Test { impl pallet_utility::Config for Test { type Event = Event; type Call = Call; + type PalletsOrigin = OriginCaller; type WeightInfo = (); } parameter_types! { diff --git a/frame/utility/src/benchmarking.rs b/frame/utility/src/benchmarking.rs index 70cc61f87b9c..ce59d7e898eb 100644 --- a/frame/utility/src/benchmarking.rs +++ b/frame/utility/src/benchmarking.rs @@ -30,6 +30,7 @@ fn assert_last_event(generic_event: ::Event) { } benchmarks! { + where_clause { where ::PalletsOrigin: Clone } batch { let c in 0 .. 1000; let mut calls: Vec<::Call> = Vec::new(); @@ -64,5 +65,13 @@ benchmarks! { assert_last_event::(Event::BatchCompleted.into()) } + dispatch_as { + let caller = account("caller", SEED, SEED); + let call = Box::new(frame_system::Call::remark { remark: vec![] }.into()); + let origin: T::Origin = RawOrigin::Signed(caller).into(); + let pallets_origin: ::PalletsOrigin = origin.caller().clone(); + let pallets_origin = Into::::into(pallets_origin.clone()); + }: _(RawOrigin::Root, Box::new(pallets_origin), call) + impl_benchmark_test_suite!(Pallet, crate::tests::new_test_ext(), crate::tests::Test); } diff --git a/frame/utility/src/lib.rs b/frame/utility/src/lib.rs index 8712cf74f451..241526cef223 100644 --- a/frame/utility/src/lib.rs +++ b/frame/utility/src/lib.rs @@ -96,6 +96,11 @@ pub mod pallet { + IsSubType> + IsType<::Call>; + /// The caller origin, overarching type of all pallets origins. + type PalletsOrigin: Parameter + + Into<::Origin> + + IsType<<::Origin as frame_support::traits::OriginTrait>::PalletsOrigin>; + /// Weight information for extrinsics in this pallet. type WeightInfo: WeightInfo; } @@ -110,6 +115,8 @@ pub mod pallet { BatchCompleted, /// A single item within a Batch of dispatches has completed with no error. ItemCompleted, + /// A call was dispatched. \[result\] + DispatchedAs(DispatchResult), } // Align the call size to 1KB. As we are currently compiling the runtime for native/wasm @@ -342,6 +349,37 @@ pub mod pallet { let base_weight = T::WeightInfo::batch_all(calls_len as u32); Ok(Some(base_weight + weight).into()) } + + /// Dispatches a function call with a provided origin. + /// + /// The dispatch origin for this call must be _Root_. + /// + /// # + /// - O(1). + /// - Limited storage reads. + /// - One DB write (event). + /// - Weight of derivative `call` execution + T::WeightInfo::dispatch_as(). + /// # + #[pallet::weight({ + let dispatch_info = call.get_dispatch_info(); + ( + T::WeightInfo::dispatch_as() + .saturating_add(dispatch_info.weight), + dispatch_info.class, + ) + })] + pub fn dispatch_as( + origin: OriginFor, + as_origin: Box, + call: Box<::Call>, + ) -> DispatchResult { + ensure_root(origin)?; + + let res = call.dispatch_bypass_filter((*as_origin).into()); + + Self::deposit_event(Event::DispatchedAs(res.map(|_| ()).map_err(|e| e.error))); + Ok(()) + } } } diff --git a/frame/utility/src/tests.rs b/frame/utility/src/tests.rs index cb7a3d9a21e2..f4d09a30ec07 100644 --- a/frame/utility/src/tests.rs +++ b/frame/utility/src/tests.rs @@ -168,6 +168,7 @@ impl Contains for TestBaseCallFilter { impl Config for Test { type Event = Event; type Call = Call; + type PalletsOrigin = OriginCaller; type WeightInfo = (); } diff --git a/frame/utility/src/weights.rs b/frame/utility/src/weights.rs index 6ac23419e3ef..bce18271684b 100644 --- a/frame/utility/src/weights.rs +++ b/frame/utility/src/weights.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_utility //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-08-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2021-10-30, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 // Executed Command: @@ -48,39 +48,46 @@ pub trait WeightInfo { fn batch(c: u32, ) -> Weight; fn as_derivative() -> Weight; fn batch_all(c: u32, ) -> Weight; + fn dispatch_as() -> Weight; } /// Weights for pallet_utility using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { fn batch(c: u32, ) -> Weight { - (30_319_000 as Weight) + (18_293_000 as Weight) // Standard Error: 3_000 - .saturating_add((6_759_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((5_530_000 as Weight).saturating_mul(c as Weight)) } fn as_derivative() -> Weight { - (4_030_000 as Weight) + (3_387_000 as Weight) } fn batch_all(c: u32, ) -> Weight { - (26_621_000 as Weight) - // Standard Error: 3_000 - .saturating_add((7_251_000 as Weight).saturating_mul(c as Weight)) + (19_223_000 as Weight) + // Standard Error: 4_000 + .saturating_add((5_998_000 as Weight).saturating_mul(c as Weight)) + } + fn dispatch_as() -> Weight { + (14_340_000 as Weight) } } // For backwards compatibility and tests impl WeightInfo for () { fn batch(c: u32, ) -> Weight { - (30_319_000 as Weight) + (18_293_000 as Weight) // Standard Error: 3_000 - .saturating_add((6_759_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((5_530_000 as Weight).saturating_mul(c as Weight)) } fn as_derivative() -> Weight { - (4_030_000 as Weight) + (3_387_000 as Weight) } fn batch_all(c: u32, ) -> Weight { - (26_621_000 as Weight) - // Standard Error: 3_000 - .saturating_add((7_251_000 as Weight).saturating_mul(c as Weight)) + (19_223_000 as Weight) + // Standard Error: 4_000 + .saturating_add((5_998_000 as Weight).saturating_mul(c as Weight)) + } + fn dispatch_as() -> Weight { + (14_340_000 as Weight) } } From b89bb4c969895738ee7d76dca8811e12317a7f52 Mon Sep 17 00:00:00 2001 From: Dan Shields <35669742+NukeManDan@users.noreply.github.com> Date: Thu, 4 Nov 2021 19:54:31 +0100 Subject: [PATCH 136/695] rm broken rustdoc-header.html (#10091) --- .gitlab-ci.yml | 3 +-- .maintain/rustdoc-header.html | 10 ---------- 2 files changed, 1 insertion(+), 12 deletions(-) delete mode 100644 .maintain/rustdoc-header.html diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 87efc43af289..5e406b36c5c5 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -661,8 +661,7 @@ build-rustdoc: - ./crate-docs/ script: # FIXME: it fails with `RUSTDOCFLAGS="-Dwarnings"` - - RUSTDOCFLAGS="--html-in-header $(pwd)/.maintain/rustdoc-header.html" - time cargo +nightly doc --no-deps --workspace --all-features --verbose + - time cargo +nightly doc --no-deps --workspace --all-features --verbose - rm -f ./target/doc/.lock - mv ./target/doc ./crate-docs # FIXME: remove me after CI image gets nonroot diff --git a/.maintain/rustdoc-header.html b/.maintain/rustdoc-header.html deleted file mode 100644 index a679d5e299da..000000000000 --- a/.maintain/rustdoc-header.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - From 75458291756cad3b51346cd098a3dfcd53b5d475 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Thu, 4 Nov 2021 19:54:48 +0100 Subject: [PATCH 137/695] Switch to Rust 2021 (#10170) * Switch to Rust 2021 * Update trybuild to fix errors --- .maintain/node-template-release/Cargo.toml | 2 +- Cargo.lock | 4 +-- bin/node-template/node/Cargo.toml | 2 +- bin/node-template/runtime/Cargo.toml | 2 +- bin/node/bench/Cargo.toml | 2 +- bin/node/cli/Cargo.toml | 2 +- bin/node/executor/Cargo.toml | 2 +- bin/node/inspect/Cargo.toml | 2 +- bin/node/primitives/Cargo.toml | 2 +- bin/node/rpc-client/Cargo.toml | 2 +- bin/node/rpc/Cargo.toml | 2 +- bin/node/runtime/Cargo.toml | 2 +- bin/node/test-runner-example/Cargo.toml | 2 +- bin/node/testing/Cargo.toml | 2 +- bin/utils/chain-spec-builder/Cargo.toml | 2 +- bin/utils/subkey/Cargo.toml | 2 +- client/allocator/Cargo.toml | 2 +- client/api/Cargo.toml | 2 +- client/authority-discovery/Cargo.toml | 2 +- client/basic-authorship/Cargo.toml | 2 +- client/beefy/Cargo.toml | 2 +- client/beefy/rpc/Cargo.toml | 2 +- client/block-builder/Cargo.toml | 2 +- client/chain-spec/Cargo.toml | 2 +- client/chain-spec/derive/Cargo.toml | 2 +- client/chain-spec/derive/src/impls.rs | 2 +- client/cli/Cargo.toml | 2 +- client/consensus/aura/Cargo.toml | 2 +- client/consensus/babe/Cargo.toml | 2 +- client/consensus/babe/rpc/Cargo.toml | 2 +- client/consensus/common/Cargo.toml | 2 +- client/consensus/epochs/Cargo.toml | 2 +- client/consensus/manual-seal/Cargo.toml | 2 +- client/consensus/pow/Cargo.toml | 2 +- client/consensus/slots/Cargo.toml | 2 +- client/consensus/uncles/Cargo.toml | 2 +- client/db/Cargo.toml | 2 +- client/executor/Cargo.toml | 2 +- client/executor/common/Cargo.toml | 2 +- client/executor/runtime-test/Cargo.toml | 2 +- client/executor/src/wasm_runtime.rs | 1 - client/executor/wasmi/Cargo.toml | 2 +- client/executor/wasmtime/Cargo.toml | 2 +- client/finality-grandpa-warp-sync/Cargo.toml | 2 +- client/finality-grandpa/Cargo.toml | 2 +- client/finality-grandpa/rpc/Cargo.toml | 2 +- client/finality-grandpa/rpc/src/report.rs | 4 --- client/informant/Cargo.toml | 2 +- client/keystore/Cargo.toml | 2 +- client/light/Cargo.toml | 2 +- client/network-gossip/Cargo.toml | 2 +- client/network/Cargo.toml | 2 +- client/network/src/protocol/sync.rs | 1 - .../src/protocol/sync/extra_requests.rs | 1 - client/network/test/Cargo.toml | 2 +- client/offchain/Cargo.toml | 2 +- client/peerset/Cargo.toml | 2 +- client/proposer-metrics/Cargo.toml | 2 +- client/rpc-api/Cargo.toml | 2 +- client/rpc-servers/Cargo.toml | 2 +- client/rpc/Cargo.toml | 2 +- client/rpc/src/chain/mod.rs | 2 -- client/service/Cargo.toml | 2 +- client/service/test/Cargo.toml | 2 +- client/state-db/Cargo.toml | 2 +- client/sync-state-rpc/Cargo.toml | 2 +- client/telemetry/Cargo.toml | 2 +- client/tracing/Cargo.toml | 2 +- client/tracing/proc-macro/Cargo.toml | 2 +- client/transaction-pool/Cargo.toml | 2 +- client/transaction-pool/api/Cargo.toml | 2 +- client/utils/Cargo.toml | 2 +- frame/assets/Cargo.toml | 2 +- frame/atomic-swap/Cargo.toml | 2 +- frame/aura/Cargo.toml | 2 +- frame/authority-discovery/Cargo.toml | 2 +- frame/authorship/Cargo.toml | 2 +- frame/babe/Cargo.toml | 2 +- frame/bags-list/Cargo.toml | 2 +- frame/bags-list/fuzzer/Cargo.toml | 2 +- frame/bags-list/remote-tests/Cargo.toml | 2 +- frame/balances/Cargo.toml | 2 +- frame/beefy-mmr/Cargo.toml | 2 +- frame/beefy-mmr/primitives/Cargo.toml | 2 +- frame/beefy/Cargo.toml | 2 +- frame/benchmarking/Cargo.toml | 2 +- frame/bounties/Cargo.toml | 2 +- frame/collective/Cargo.toml | 2 +- frame/contracts/Cargo.toml | 2 +- frame/contracts/common/Cargo.toml | 2 +- frame/contracts/proc-macro/Cargo.toml | 2 +- frame/contracts/rpc/Cargo.toml | 2 +- frame/contracts/rpc/runtime-api/Cargo.toml | 2 +- frame/democracy/Cargo.toml | 2 +- .../election-provider-multi-phase/Cargo.toml | 2 +- frame/election-provider-support/Cargo.toml | 2 +- frame/elections-phragmen/Cargo.toml | 2 +- frame/elections/Cargo.toml | 2 +- frame/example-offchain-worker/Cargo.toml | 2 +- frame/example-parallel/Cargo.toml | 2 +- frame/example-parallel/src/lib.rs | 1 - frame/example/Cargo.toml | 2 +- frame/executive/Cargo.toml | 2 +- frame/gilt/Cargo.toml | 2 +- frame/grandpa/Cargo.toml | 2 +- frame/identity/Cargo.toml | 2 +- frame/im-online/Cargo.toml | 2 +- frame/indices/Cargo.toml | 2 +- frame/lottery/Cargo.toml | 2 +- frame/membership/Cargo.toml | 2 +- frame/merkle-mountain-range/Cargo.toml | 2 +- .../primitives/Cargo.toml | 2 +- frame/merkle-mountain-range/rpc/Cargo.toml | 2 +- frame/multisig/Cargo.toml | 2 +- frame/nicks/Cargo.toml | 2 +- frame/node-authorization/Cargo.toml | 2 +- frame/offences/Cargo.toml | 2 +- frame/offences/benchmarking/Cargo.toml | 2 +- frame/proxy/Cargo.toml | 2 +- frame/randomness-collective-flip/Cargo.toml | 2 +- frame/recovery/Cargo.toml | 2 +- frame/scheduler/Cargo.toml | 2 +- frame/scored-pool/Cargo.toml | 2 +- frame/session/Cargo.toml | 2 +- frame/session/benchmarking/Cargo.toml | 2 +- frame/society/Cargo.toml | 2 +- frame/staking/Cargo.toml | 2 +- frame/staking/reward-curve/Cargo.toml | 2 +- frame/staking/reward-fn/Cargo.toml | 2 +- frame/staking/src/pallet/impls.rs | 3 -- frame/sudo/Cargo.toml | 2 +- frame/support/Cargo.toml | 2 +- frame/support/procedural/Cargo.toml | 2 +- .../procedural/src/pallet/expand/constants.rs | 2 +- .../procedural/src/pallet/expand/event.rs | 4 +-- .../src/storage/genesis_config/mod.rs | 8 ++--- .../support/procedural/src/storage/getters.rs | 2 +- .../procedural/src/storage/metadata.rs | 2 +- .../procedural/src/storage/storage_info.rs | 2 +- .../procedural/src/storage/store_trait.rs | 2 +- frame/support/procedural/tools/Cargo.toml | 2 +- .../procedural/tools/derive/Cargo.toml | 2 +- .../procedural/tools/derive/src/lib.rs | 2 +- frame/support/src/traits/members.rs | 2 +- frame/support/test/Cargo.toml | 8 +++-- frame/support/test/compile_pass/Cargo.toml | 2 +- frame/support/test/pallet/Cargo.toml | 2 +- frame/support/test/tests/pallet.rs | 34 +++++++++---------- frame/system/Cargo.toml | 2 +- frame/system/benchmarking/Cargo.toml | 2 +- frame/system/rpc/runtime-api/Cargo.toml | 2 +- frame/timestamp/Cargo.toml | 2 +- frame/tips/Cargo.toml | 2 +- frame/transaction-payment/Cargo.toml | 2 +- frame/transaction-payment/rpc/Cargo.toml | 2 +- .../rpc/runtime-api/Cargo.toml | 2 +- frame/transaction-storage/Cargo.toml | 2 +- frame/treasury/Cargo.toml | 2 +- frame/try-runtime/Cargo.toml | 2 +- frame/uniques/Cargo.toml | 2 +- frame/utility/Cargo.toml | 2 +- frame/vesting/Cargo.toml | 2 +- primitives/api/Cargo.toml | 2 +- primitives/api/proc-macro/Cargo.toml | 2 +- .../api/proc-macro/src/decl_runtime_apis.rs | 2 +- primitives/api/src/lib.rs | 2 -- primitives/api/test/Cargo.toml | 4 +-- primitives/application-crypto/Cargo.toml | 2 +- primitives/application-crypto/test/Cargo.toml | 2 +- primitives/arithmetic/Cargo.toml | 2 +- primitives/arithmetic/fuzzer/Cargo.toml | 2 +- primitives/authority-discovery/Cargo.toml | 2 +- primitives/authorship/Cargo.toml | 2 +- primitives/beefy/Cargo.toml | 2 +- primitives/block-builder/Cargo.toml | 2 +- primitives/blockchain/Cargo.toml | 2 +- primitives/consensus/aura/Cargo.toml | 2 +- primitives/consensus/babe/Cargo.toml | 2 +- primitives/consensus/common/Cargo.toml | 2 +- primitives/consensus/pow/Cargo.toml | 2 +- primitives/consensus/slots/Cargo.toml | 2 +- primitives/consensus/vrf/Cargo.toml | 2 +- primitives/core/Cargo.toml | 2 +- primitives/core/hashing/Cargo.toml | 2 +- primitives/core/hashing/proc-macro/Cargo.toml | 2 +- primitives/database/Cargo.toml | 2 +- primitives/debug-derive/Cargo.toml | 2 +- primitives/externalities/Cargo.toml | 2 +- primitives/finality-grandpa/Cargo.toml | 2 +- primitives/finality-grandpa/src/lib.rs | 1 - primitives/inherents/Cargo.toml | 2 +- primitives/io/Cargo.toml | 2 +- primitives/keyring/Cargo.toml | 2 +- primitives/keystore/Cargo.toml | 2 +- primitives/maybe-compressed-blob/Cargo.toml | 2 +- primitives/npos-elections/Cargo.toml | 2 +- primitives/npos-elections/fuzzer/Cargo.toml | 2 +- .../npos-elections/solution-type/Cargo.toml | 4 +-- primitives/offchain/Cargo.toml | 2 +- primitives/panic-handler/Cargo.toml | 2 +- primitives/rpc/Cargo.toml | 2 +- primitives/runtime-interface/Cargo.toml | 4 +-- .../runtime-interface/proc-macro/Cargo.toml | 2 +- .../test-wasm-deprecated/Cargo.toml | 2 +- .../runtime-interface/test-wasm/Cargo.toml | 2 +- primitives/runtime-interface/test/Cargo.toml | 2 +- primitives/runtime/Cargo.toml | 2 +- primitives/sandbox/Cargo.toml | 2 +- primitives/serializer/Cargo.toml | 2 +- primitives/session/Cargo.toml | 2 +- primitives/staking/Cargo.toml | 2 +- primitives/state-machine/Cargo.toml | 2 +- primitives/std/Cargo.toml | 2 +- primitives/storage/Cargo.toml | 2 +- primitives/tasks/Cargo.toml | 2 +- primitives/test-primitives/Cargo.toml | 2 +- primitives/timestamp/Cargo.toml | 2 +- primitives/tracing/Cargo.toml | 2 +- primitives/transaction-pool/Cargo.toml | 2 +- .../transaction-storage-proof/Cargo.toml | 2 +- primitives/trie/Cargo.toml | 2 +- primitives/version/Cargo.toml | 2 +- primitives/version/proc-macro/Cargo.toml | 2 +- primitives/wasm-interface/Cargo.toml | 2 +- test-utils/Cargo.toml | 4 +-- test-utils/client/Cargo.toml | 2 +- test-utils/derive/Cargo.toml | 2 +- test-utils/runtime/Cargo.toml | 2 +- test-utils/runtime/client/Cargo.toml | 2 +- .../runtime/transaction-pool/Cargo.toml | 2 +- test-utils/test-crate/Cargo.toml | 2 +- test-utils/test-runner/Cargo.toml | 2 +- utils/build-script-utils/Cargo.toml | 2 +- utils/fork-tree/Cargo.toml | 2 +- utils/frame/benchmarking-cli/Cargo.toml | 2 +- utils/frame/frame-utilities-cli/Cargo.toml | 2 +- utils/frame/generate-bags/Cargo.toml | 2 +- .../generate-bags/node-runtime/Cargo.toml | 2 +- utils/frame/generate-bags/src/lib.rs | 1 - utils/frame/remote-externalities/Cargo.toml | 2 +- utils/frame/rpc/support/Cargo.toml | 2 +- utils/frame/rpc/system/Cargo.toml | 2 +- utils/frame/try-runtime/cli/Cargo.toml | 2 +- utils/prometheus/Cargo.toml | 2 +- utils/wasm-builder/Cargo.toml | 2 +- 245 files changed, 264 insertions(+), 279 deletions(-) diff --git a/.maintain/node-template-release/Cargo.toml b/.maintain/node-template-release/Cargo.toml index c1d9f2da7fae..26256e836330 100644 --- a/.maintain/node-template-release/Cargo.toml +++ b/.maintain/node-template-release/Cargo.toml @@ -2,7 +2,7 @@ name = "node-template-release" version = "3.0.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0" [dependencies] diff --git a/Cargo.lock b/Cargo.lock index 7ade00bc4004..4a50fe356571 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10944,9 +10944,9 @@ dependencies = [ [[package]] name = "trybuild" -version = "1.0.43" +version = "1.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02c413315329fc96167f922b46fd0caa3a43f4697b7a7896b183c7142635832" +checksum = "150e726dc059e6fbd4fce3288f5bb3cf70128cf63b0dde23b938a3cad810fb23" dependencies = [ "dissimilar", "glob", diff --git a/bin/node-template/node/Cargo.toml b/bin/node-template/node/Cargo.toml index 57d9c5f3f71e..1d8abad406a1 100644 --- a/bin/node-template/node/Cargo.toml +++ b/bin/node-template/node/Cargo.toml @@ -4,7 +4,7 @@ version = "3.0.0" description = "A fresh FRAME-based Substrate node, ready for hacking." authors = ["Substrate DevHub "] homepage = "https://substrate.io/" -edition = "2018" +edition = "2021" license = "Unlicense" publish = false repository = "https://github.com/substrate-developer-hub/substrate-node-template/" diff --git a/bin/node-template/runtime/Cargo.toml b/bin/node-template/runtime/Cargo.toml index e9f557f3fb5a..e4e2039866b4 100644 --- a/bin/node-template/runtime/Cargo.toml +++ b/bin/node-template/runtime/Cargo.toml @@ -4,7 +4,7 @@ version = "3.0.0" description = 'A fresh FRAME-based Substrate runtime, ready for hacking.' authors = ["Substrate DevHub "] homepage = "https://substrate.io/" -edition = "2018" +edition = "2021" license = "Unlicense" publish = false repository = "https://github.com/substrate-developer-hub/substrate-node-template/" diff --git a/bin/node/bench/Cargo.toml b/bin/node/bench/Cargo.toml index b19a71966fb8..f59ea2361186 100644 --- a/bin/node/bench/Cargo.toml +++ b/bin/node/bench/Cargo.toml @@ -3,7 +3,7 @@ name = "node-bench" version = "0.9.0-dev" authors = ["Parity Technologies "] description = "Substrate node integration benchmarks." -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index 1d394dd952db..38c161a81ef0 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -4,7 +4,7 @@ version = "3.0.0-dev" authors = ["Parity Technologies "] description = "Generic Substrate node implementation in Rust." build = "build.rs" -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" default-run = "substrate" homepage = "https://substrate.io" diff --git a/bin/node/executor/Cargo.toml b/bin/node/executor/Cargo.toml index 462bb034610e..21785079c6c5 100644 --- a/bin/node/executor/Cargo.toml +++ b/bin/node/executor/Cargo.toml @@ -3,7 +3,7 @@ name = "node-executor" version = "3.0.0-dev" authors = ["Parity Technologies "] description = "Substrate node implementation in Rust." -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/bin/node/inspect/Cargo.toml b/bin/node/inspect/Cargo.toml index 6f526b896ba7..6504f39a0582 100644 --- a/bin/node/inspect/Cargo.toml +++ b/bin/node/inspect/Cargo.toml @@ -2,7 +2,7 @@ name = "node-inspect" version = "0.9.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/bin/node/primitives/Cargo.toml b/bin/node/primitives/Cargo.toml index 07c3aca6059f..2c8185d5c9c4 100644 --- a/bin/node/primitives/Cargo.toml +++ b/bin/node/primitives/Cargo.toml @@ -2,7 +2,7 @@ name = "node-primitives" version = "2.0.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/bin/node/rpc-client/Cargo.toml b/bin/node/rpc-client/Cargo.toml index 59695edb6fa2..5c822ef3ad31 100644 --- a/bin/node/rpc-client/Cargo.toml +++ b/bin/node/rpc-client/Cargo.toml @@ -2,7 +2,7 @@ name = "node-rpc-client" version = "2.0.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/bin/node/rpc/Cargo.toml b/bin/node/rpc/Cargo.toml index 4c7b15459cea..ef111e3f1949 100644 --- a/bin/node/rpc/Cargo.toml +++ b/bin/node/rpc/Cargo.toml @@ -2,7 +2,7 @@ name = "node-rpc" version = "3.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 22ff0954e245..c0b888e55b1f 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -2,7 +2,7 @@ name = "node-runtime" version = "3.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" build = "build.rs" license = "Apache-2.0" homepage = "https://substrate.io" diff --git a/bin/node/test-runner-example/Cargo.toml b/bin/node/test-runner-example/Cargo.toml index 96c4c2047ac4..b664cdb8e50e 100644 --- a/bin/node/test-runner-example/Cargo.toml +++ b/bin/node/test-runner-example/Cargo.toml @@ -2,7 +2,7 @@ name = "test-runner-example" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" publish = false [dependencies] diff --git a/bin/node/testing/Cargo.toml b/bin/node/testing/Cargo.toml index e5d13189ac2f..1854029b0709 100644 --- a/bin/node/testing/Cargo.toml +++ b/bin/node/testing/Cargo.toml @@ -3,7 +3,7 @@ name = "node-testing" version = "3.0.0-dev" authors = ["Parity Technologies "] description = "Test utilities for Substrate node." -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/bin/utils/chain-spec-builder/Cargo.toml b/bin/utils/chain-spec-builder/Cargo.toml index bfbf2da57a6a..a35fbba5cdc4 100644 --- a/bin/utils/chain-spec-builder/Cargo.toml +++ b/bin/utils/chain-spec-builder/Cargo.toml @@ -2,7 +2,7 @@ name = "chain-spec-builder" version = "2.0.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" build = "build.rs" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.io" diff --git a/bin/utils/subkey/Cargo.toml b/bin/utils/subkey/Cargo.toml index 5e7615f60d62..14ba673b33be 100644 --- a/bin/utils/subkey/Cargo.toml +++ b/bin/utils/subkey/Cargo.toml @@ -2,7 +2,7 @@ name = "subkey" version = "2.0.1" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/client/allocator/Cargo.toml b/client/allocator/Cargo.toml index 9383b88f756c..2b37c192c6e3 100644 --- a/client/allocator/Cargo.toml +++ b/client/allocator/Cargo.toml @@ -2,7 +2,7 @@ name = "sc-allocator" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/client/api/Cargo.toml b/client/api/Cargo.toml index af8704058b66..7b2952552a3d 100644 --- a/client/api/Cargo.toml +++ b/client/api/Cargo.toml @@ -2,7 +2,7 @@ name = "sc-client-api" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/client/authority-discovery/Cargo.toml b/client/authority-discovery/Cargo.toml index dca365981984..dc4b92975681 100644 --- a/client/authority-discovery/Cargo.toml +++ b/client/authority-discovery/Cargo.toml @@ -2,7 +2,7 @@ name = "sc-authority-discovery" version = "0.10.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" build = "build.rs" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.io" diff --git a/client/basic-authorship/Cargo.toml b/client/basic-authorship/Cargo.toml index 1ecdb08eba48..96ab698f3621 100644 --- a/client/basic-authorship/Cargo.toml +++ b/client/basic-authorship/Cargo.toml @@ -2,7 +2,7 @@ name = "sc-basic-authorship" version = "0.10.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/client/beefy/Cargo.toml b/client/beefy/Cargo.toml index d4541288a628..37dc4491e21d 100644 --- a/client/beefy/Cargo.toml +++ b/client/beefy/Cargo.toml @@ -2,7 +2,7 @@ name = "beefy-gadget" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] diff --git a/client/beefy/rpc/Cargo.toml b/client/beefy/rpc/Cargo.toml index 8af2fa3eac86..47fd2b740370 100644 --- a/client/beefy/rpc/Cargo.toml +++ b/client/beefy/rpc/Cargo.toml @@ -2,7 +2,7 @@ name = "beefy-gadget-rpc" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] diff --git a/client/block-builder/Cargo.toml b/client/block-builder/Cargo.toml index 9d2703fc2ed2..25950a9e9061 100644 --- a/client/block-builder/Cargo.toml +++ b/client/block-builder/Cargo.toml @@ -2,7 +2,7 @@ name = "sc-block-builder" version = "0.10.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/client/chain-spec/Cargo.toml b/client/chain-spec/Cargo.toml index ba9655261923..d7557e2062ac 100644 --- a/client/chain-spec/Cargo.toml +++ b/client/chain-spec/Cargo.toml @@ -2,7 +2,7 @@ name = "sc-chain-spec" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/client/chain-spec/derive/Cargo.toml b/client/chain-spec/derive/Cargo.toml index 73083e4a6e0b..386137d0667a 100644 --- a/client/chain-spec/derive/Cargo.toml +++ b/client/chain-spec/derive/Cargo.toml @@ -2,7 +2,7 @@ name = "sc-chain-spec-derive" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/client/chain-spec/derive/src/impls.rs b/client/chain-spec/derive/src/impls.rs index 8c56430e81d0..87a3db063c78 100644 --- a/client/chain-spec/derive/src/impls.rs +++ b/client/chain-spec/derive/src/impls.rs @@ -52,7 +52,7 @@ pub fn extension_derive(ast: &DeriveInput) -> proc_macro::TokenStream { use std::any::{Any, TypeId}; match TypeId::of::() { - #( x if x == TypeId::of::<#field_types>() => Any::downcast_ref(&self.#field_names) ),*, + #( x if x == TypeId::of::<#field_types>() => ::downcast_ref(&self.#field_names) ),*, _ => None, } } diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index 0cee37f25e79..4b6ef3bab950 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -3,7 +3,7 @@ name = "sc-cli" version = "0.10.0-dev" authors = ["Parity Technologies "] description = "Substrate CLI interface." -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/client/consensus/aura/Cargo.toml b/client/consensus/aura/Cargo.toml index 1c767319b122..62d7b3d5327a 100644 --- a/client/consensus/aura/Cargo.toml +++ b/client/consensus/aura/Cargo.toml @@ -3,7 +3,7 @@ name = "sc-consensus-aura" version = "0.10.0-dev" authors = ["Parity Technologies "] description = "Aura consensus algorithm for substrate" -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/client/consensus/babe/Cargo.toml b/client/consensus/babe/Cargo.toml index 66ad6287f40d..8430ca39c9cb 100644 --- a/client/consensus/babe/Cargo.toml +++ b/client/consensus/babe/Cargo.toml @@ -3,7 +3,7 @@ name = "sc-consensus-babe" version = "0.10.0-dev" authors = ["Parity Technologies "] description = "BABE consensus algorithm for substrate" -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/client/consensus/babe/rpc/Cargo.toml b/client/consensus/babe/rpc/Cargo.toml index 7ef9b1c1de3c..bc57092d3400 100644 --- a/client/consensus/babe/rpc/Cargo.toml +++ b/client/consensus/babe/rpc/Cargo.toml @@ -3,7 +3,7 @@ name = "sc-consensus-babe-rpc" version = "0.10.0-dev" authors = ["Parity Technologies "] description = "RPC extensions for the BABE consensus algorithm" -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/client/consensus/common/Cargo.toml b/client/consensus/common/Cargo.toml index 30840a974f9a..d63d124ed60e 100644 --- a/client/consensus/common/Cargo.toml +++ b/client/consensus/common/Cargo.toml @@ -2,7 +2,7 @@ name = "sc-consensus" version = "0.10.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/client/consensus/epochs/Cargo.toml b/client/consensus/epochs/Cargo.toml index 90a708d07e2a..4cac4a24d187 100644 --- a/client/consensus/epochs/Cargo.toml +++ b/client/consensus/epochs/Cargo.toml @@ -3,7 +3,7 @@ name = "sc-consensus-epochs" version = "0.10.0-dev" authors = ["Parity Technologies "] description = "Generic epochs-based utilities for consensus" -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/client/consensus/manual-seal/Cargo.toml b/client/consensus/manual-seal/Cargo.toml index 9b29bb3dc71c..a662ebf01011 100644 --- a/client/consensus/manual-seal/Cargo.toml +++ b/client/consensus/manual-seal/Cargo.toml @@ -3,7 +3,7 @@ name = "sc-consensus-manual-seal" version = "0.10.0-dev" authors = ["Parity Technologies "] description = "Manual sealing engine for Substrate" -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/client/consensus/pow/Cargo.toml b/client/consensus/pow/Cargo.toml index c570c1ccbad2..bc7c01181e41 100644 --- a/client/consensus/pow/Cargo.toml +++ b/client/consensus/pow/Cargo.toml @@ -3,7 +3,7 @@ name = "sc-consensus-pow" version = "0.10.0-dev" authors = ["Parity Technologies "] description = "PoW consensus algorithm for substrate" -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/client/consensus/slots/Cargo.toml b/client/consensus/slots/Cargo.toml index 6c1f865c62cb..5c5f1bdfa68c 100644 --- a/client/consensus/slots/Cargo.toml +++ b/client/consensus/slots/Cargo.toml @@ -3,7 +3,7 @@ name = "sc-consensus-slots" version = "0.10.0-dev" authors = ["Parity Technologies "] description = "Generic slots-based utilities for consensus" -edition = "2018" +edition = "2021" build = "build.rs" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.io" diff --git a/client/consensus/uncles/Cargo.toml b/client/consensus/uncles/Cargo.toml index 73768f0d0941..f644d64c7bbe 100644 --- a/client/consensus/uncles/Cargo.toml +++ b/client/consensus/uncles/Cargo.toml @@ -3,7 +3,7 @@ name = "sc-consensus-uncles" version = "0.10.0-dev" authors = ["Parity Technologies "] description = "Generic uncle inclusion utilities for consensus" -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/client/db/Cargo.toml b/client/db/Cargo.toml index 165d01d55511..19bf7ad248fe 100644 --- a/client/db/Cargo.toml +++ b/client/db/Cargo.toml @@ -2,7 +2,7 @@ name = "sc-client-db" version = "0.10.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/client/executor/Cargo.toml b/client/executor/Cargo.toml index bc55172bc33e..028854992a09 100644 --- a/client/executor/Cargo.toml +++ b/client/executor/Cargo.toml @@ -2,7 +2,7 @@ name = "sc-executor" version = "0.10.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/client/executor/common/Cargo.toml b/client/executor/common/Cargo.toml index 622baa6c0dca..fc7d5a152847 100644 --- a/client/executor/common/Cargo.toml +++ b/client/executor/common/Cargo.toml @@ -2,7 +2,7 @@ name = "sc-executor-common" version = "0.10.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/client/executor/runtime-test/Cargo.toml b/client/executor/runtime-test/Cargo.toml index ac1e3413491d..1e3b5e926b96 100644 --- a/client/executor/runtime-test/Cargo.toml +++ b/client/executor/runtime-test/Cargo.toml @@ -2,7 +2,7 @@ name = "sc-runtime-test" version = "2.0.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" build = "build.rs" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" publish = false diff --git a/client/executor/src/wasm_runtime.rs b/client/executor/src/wasm_runtime.rs index 204a095717fc..88c033814ed6 100644 --- a/client/executor/src/wasm_runtime.rs +++ b/client/executor/src/wasm_runtime.rs @@ -356,7 +356,6 @@ fn decode_version(mut version: &[u8]) -> Result { fn decode_runtime_apis(apis: &[u8]) -> Result, WasmError> { use sp_api::RUNTIME_API_INFO_SIZE; - use std::convert::TryFrom; apis.chunks(RUNTIME_API_INFO_SIZE) .map(|chunk| { diff --git a/client/executor/wasmi/Cargo.toml b/client/executor/wasmi/Cargo.toml index 307ba908e23b..6311b0234866 100644 --- a/client/executor/wasmi/Cargo.toml +++ b/client/executor/wasmi/Cargo.toml @@ -2,7 +2,7 @@ name = "sc-executor-wasmi" version = "0.10.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/client/executor/wasmtime/Cargo.toml b/client/executor/wasmtime/Cargo.toml index 7a877bd9578f..741898b8282c 100644 --- a/client/executor/wasmtime/Cargo.toml +++ b/client/executor/wasmtime/Cargo.toml @@ -2,7 +2,7 @@ name = "sc-executor-wasmtime" version = "0.10.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/client/finality-grandpa-warp-sync/Cargo.toml b/client/finality-grandpa-warp-sync/Cargo.toml index 9736b25ccac5..6280add27562 100644 --- a/client/finality-grandpa-warp-sync/Cargo.toml +++ b/client/finality-grandpa-warp-sync/Cargo.toml @@ -4,7 +4,7 @@ name = "sc-finality-grandpa-warp-sync" version = "0.10.0-dev" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/client/finality-grandpa/Cargo.toml b/client/finality-grandpa/Cargo.toml index 2d45fa100f79..fd0b52cd1f70 100644 --- a/client/finality-grandpa/Cargo.toml +++ b/client/finality-grandpa/Cargo.toml @@ -2,7 +2,7 @@ name = "sc-finality-grandpa" version = "0.10.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/client/finality-grandpa/rpc/Cargo.toml b/client/finality-grandpa/rpc/Cargo.toml index d2976ee71275..ad39ad6ba95b 100644 --- a/client/finality-grandpa/rpc/Cargo.toml +++ b/client/finality-grandpa/rpc/Cargo.toml @@ -4,7 +4,7 @@ version = "0.10.0-dev" authors = ["Parity Technologies "] description = "RPC extensions for the GRANDPA finality gadget" repository = "https://github.com/paritytech/substrate/" -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" readme = "README.md" diff --git a/client/finality-grandpa/rpc/src/report.rs b/client/finality-grandpa/rpc/src/report.rs index fef8f2265995..fc97c176f34f 100644 --- a/client/finality-grandpa/rpc/src/report.rs +++ b/client/finality-grandpa/rpc/src/report.rs @@ -87,8 +87,6 @@ impl RoundState { round_state: &report::RoundState, voters: &HashSet, ) -> Result { - use std::convert::TryInto; - let prevotes = &round_state.prevote_ids; let missing_prevotes = voters.difference(&prevotes).cloned().collect(); @@ -130,8 +128,6 @@ impl ReportedRoundStates { AuthoritySet: ReportAuthoritySet, VoterState: ReportVoterState, { - use std::convert::TryFrom; - let voter_state = voter_state.get().ok_or(Error::EndpointNotReady)?; let (set_id, current_voters) = authority_set.get(); diff --git a/client/informant/Cargo.toml b/client/informant/Cargo.toml index c28dd4e01194..7d92e14e5d47 100644 --- a/client/informant/Cargo.toml +++ b/client/informant/Cargo.toml @@ -3,7 +3,7 @@ name = "sc-informant" version = "0.10.0-dev" authors = ["Parity Technologies "] description = "Substrate informant." -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/client/keystore/Cargo.toml b/client/keystore/Cargo.toml index 74fd85c184c6..bd158091e747 100644 --- a/client/keystore/Cargo.toml +++ b/client/keystore/Cargo.toml @@ -2,7 +2,7 @@ name = "sc-keystore" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/client/light/Cargo.toml b/client/light/Cargo.toml index cc567c60524a..1b83bf5be42f 100644 --- a/client/light/Cargo.toml +++ b/client/light/Cargo.toml @@ -4,7 +4,7 @@ name = "sc-light" version = "4.0.0-dev" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" documentation = "https://docs.rs/sc-light" diff --git a/client/network-gossip/Cargo.toml b/client/network-gossip/Cargo.toml index b4907ade834a..1f0b5c313294 100644 --- a/client/network-gossip/Cargo.toml +++ b/client/network-gossip/Cargo.toml @@ -4,7 +4,7 @@ name = "sc-network-gossip" version = "0.10.0-dev" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" documentation = "https://docs.rs/sc-network-gossip" diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index 7b4b30c59385..7c2905d5fe03 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -4,7 +4,7 @@ name = "sc-network" version = "0.10.0-dev" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" documentation = "https://docs.rs/sc-network" diff --git a/client/network/src/protocol/sync.rs b/client/network/src/protocol/sync.rs index 7f85c2b63782..37646875e3b1 100644 --- a/client/network/src/protocol/sync.rs +++ b/client/network/src/protocol/sync.rs @@ -2172,7 +2172,6 @@ impl ChainSync { /// Return some key metrics. pub(crate) fn metrics(&self) -> Metrics { - use std::convert::TryInto; Metrics { queued_blocks: self.queue_blocks.len().try_into().unwrap_or(std::u32::MAX), fork_targets: self.fork_targets.len().try_into().unwrap_or(std::u32::MAX), diff --git a/client/network/src/protocol/sync/extra_requests.rs b/client/network/src/protocol/sync/extra_requests.rs index 226762b9658d..c00837169598 100644 --- a/client/network/src/protocol/sync/extra_requests.rs +++ b/client/network/src/protocol/sync/extra_requests.rs @@ -255,7 +255,6 @@ impl ExtraRequests { /// Get some key metrics. pub(crate) fn metrics(&self) -> Metrics { - use std::convert::TryInto; Metrics { pending_requests: self.pending_requests.len().try_into().unwrap_or(std::u32::MAX), active_requests: self.active_requests.len().try_into().unwrap_or(std::u32::MAX), diff --git a/client/network/test/Cargo.toml b/client/network/test/Cargo.toml index 13555952cffd..539c57fe4cb9 100644 --- a/client/network/test/Cargo.toml +++ b/client/network/test/Cargo.toml @@ -4,7 +4,7 @@ name = "sc-network-test" version = "0.8.0" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" publish = false homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/client/offchain/Cargo.toml b/client/offchain/Cargo.toml index 104a0e61f318..ee697b32e1e4 100644 --- a/client/offchain/Cargo.toml +++ b/client/offchain/Cargo.toml @@ -4,7 +4,7 @@ name = "sc-offchain" version = "4.0.0-dev" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" readme = "README.md" diff --git a/client/peerset/Cargo.toml b/client/peerset/Cargo.toml index a7e9130cfff1..01b75f1094ff 100644 --- a/client/peerset/Cargo.toml +++ b/client/peerset/Cargo.toml @@ -5,7 +5,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" name = "sc-peerset" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" repository = "https://github.com/paritytech/substrate/" documentation = "https://docs.rs/sc-peerset" readme = "README.md" diff --git a/client/proposer-metrics/Cargo.toml b/client/proposer-metrics/Cargo.toml index 296329a5fda7..93c4cce93ca6 100644 --- a/client/proposer-metrics/Cargo.toml +++ b/client/proposer-metrics/Cargo.toml @@ -2,7 +2,7 @@ name = "sc-proposer-metrics" version = "0.9.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/client/rpc-api/Cargo.toml b/client/rpc-api/Cargo.toml index 192cf02e7ce1..532a5cf6294c 100644 --- a/client/rpc-api/Cargo.toml +++ b/client/rpc-api/Cargo.toml @@ -2,7 +2,7 @@ name = "sc-rpc-api" version = "0.10.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/client/rpc-servers/Cargo.toml b/client/rpc-servers/Cargo.toml index cbbea00d6f57..b3f408cc5980 100644 --- a/client/rpc-servers/Cargo.toml +++ b/client/rpc-servers/Cargo.toml @@ -2,7 +2,7 @@ name = "sc-rpc-server" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/client/rpc/Cargo.toml b/client/rpc/Cargo.toml index f5c7f99ff743..d8aecfe9fd35 100644 --- a/client/rpc/Cargo.toml +++ b/client/rpc/Cargo.toml @@ -2,7 +2,7 @@ name = "sc-rpc" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/client/rpc/src/chain/mod.rs b/client/rpc/src/chain/mod.rs index a06c3a094b40..9428ac3248f3 100644 --- a/client/rpc/src/chain/mod.rs +++ b/client/rpc/src/chain/mod.rs @@ -83,8 +83,6 @@ where match number { None => Ok(Some(self.client().info().best_hash)), Some(num_or_hex) => { - use std::convert::TryInto; - // FIXME <2329>: Database seems to limit the block number to u32 for no reason let block_num: u32 = num_or_hex.try_into().map_err(|_| { Error::Other(format!( diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index bb8c9ecf6a0c..5c22c1e4fca1 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -2,7 +2,7 @@ name = "sc-service" version = "0.10.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/client/service/test/Cargo.toml b/client/service/test/Cargo.toml index aeee4a5f9072..49eca272ac75 100644 --- a/client/service/test/Cargo.toml +++ b/client/service/test/Cargo.toml @@ -2,7 +2,7 @@ name = "sc-service-test" version = "2.0.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" publish = false homepage = "https://substrate.io" diff --git a/client/state-db/Cargo.toml b/client/state-db/Cargo.toml index 136fe7a199f0..abd378c6fff3 100644 --- a/client/state-db/Cargo.toml +++ b/client/state-db/Cargo.toml @@ -2,7 +2,7 @@ name = "sc-state-db" version = "0.10.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/client/sync-state-rpc/Cargo.toml b/client/sync-state-rpc/Cargo.toml index 4166929ff031..a9503b992ab3 100644 --- a/client/sync-state-rpc/Cargo.toml +++ b/client/sync-state-rpc/Cargo.toml @@ -3,7 +3,7 @@ name = "sc-sync-state-rpc" version = "0.10.0-dev" authors = ["Parity Technologies "] description = "A RPC handler to create sync states for light clients." -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/client/telemetry/Cargo.toml b/client/telemetry/Cargo.toml index 502c7fc20781..5a25aca29b60 100644 --- a/client/telemetry/Cargo.toml +++ b/client/telemetry/Cargo.toml @@ -3,7 +3,7 @@ name = "sc-telemetry" version = "4.0.0-dev" authors = ["Parity Technologies "] description = "Telemetry utils" -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/client/tracing/Cargo.toml b/client/tracing/Cargo.toml index 8093420dc5b9..8640208ad342 100644 --- a/client/tracing/Cargo.toml +++ b/client/tracing/Cargo.toml @@ -3,7 +3,7 @@ name = "sc-tracing" version = "4.0.0-dev" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Instrumentation implementation for substrate." diff --git a/client/tracing/proc-macro/Cargo.toml b/client/tracing/proc-macro/Cargo.toml index 5cc2d836dcad..9c8579ee66a4 100644 --- a/client/tracing/proc-macro/Cargo.toml +++ b/client/tracing/proc-macro/Cargo.toml @@ -2,7 +2,7 @@ name = "sc-tracing-proc-macro" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/client/transaction-pool/Cargo.toml b/client/transaction-pool/Cargo.toml index 12642559a3b8..6d05125002f2 100644 --- a/client/transaction-pool/Cargo.toml +++ b/client/transaction-pool/Cargo.toml @@ -2,7 +2,7 @@ name = "sc-transaction-pool" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/client/transaction-pool/api/Cargo.toml b/client/transaction-pool/api/Cargo.toml index 7dd1a6724ce5..176624611fbf 100644 --- a/client/transaction-pool/api/Cargo.toml +++ b/client/transaction-pool/api/Cargo.toml @@ -2,7 +2,7 @@ name = "sc-transaction-pool-api" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/client/utils/Cargo.toml b/client/utils/Cargo.toml index 546232cf6070..6d04fd4e9acd 100644 --- a/client/utils/Cargo.toml +++ b/client/utils/Cargo.toml @@ -2,7 +2,7 @@ name = "sc-utils" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/assets/Cargo.toml b/frame/assets/Cargo.toml index 65162430a2ac..08cadb527750 100644 --- a/frame/assets/Cargo.toml +++ b/frame/assets/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-assets" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/atomic-swap/Cargo.toml b/frame/atomic-swap/Cargo.toml index 60e8fa613f06..303116161a2d 100644 --- a/frame/atomic-swap/Cargo.toml +++ b/frame/atomic-swap/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-atomic-swap" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/aura/Cargo.toml b/frame/aura/Cargo.toml index 1761f78edeca..cb5903048ff8 100644 --- a/frame/aura/Cargo.toml +++ b/frame/aura/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-aura" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/authority-discovery/Cargo.toml b/frame/authority-discovery/Cargo.toml index 7e64509ce6b4..06a4e92270b2 100644 --- a/frame/authority-discovery/Cargo.toml +++ b/frame/authority-discovery/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-authority-discovery" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/authorship/Cargo.toml b/frame/authorship/Cargo.toml index 6ac91970712d..a24b578fc250 100644 --- a/frame/authorship/Cargo.toml +++ b/frame/authorship/Cargo.toml @@ -3,7 +3,7 @@ name = "pallet-authorship" version = "4.0.0-dev" description = "Block and Uncle Author tracking for the FRAME" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/babe/Cargo.toml b/frame/babe/Cargo.toml index 6b0dc71b5e29..9ae942486d62 100644 --- a/frame/babe/Cargo.toml +++ b/frame/babe/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-babe" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/bags-list/Cargo.toml b/frame/bags-list/Cargo.toml index 372dc87e212e..fa47b9bad569 100644 --- a/frame/bags-list/Cargo.toml +++ b/frame/bags-list/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-bags-list" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/bags-list/fuzzer/Cargo.toml b/frame/bags-list/fuzzer/Cargo.toml index 171e0e7af70c..510000f631ad 100644 --- a/frame/bags-list/fuzzer/Cargo.toml +++ b/frame/bags-list/fuzzer/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-bags-list-fuzzer" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/bags-list/remote-tests/Cargo.toml b/frame/bags-list/remote-tests/Cargo.toml index ee5b8c7c3f6e..37f351f0d27e 100644 --- a/frame/bags-list/remote-tests/Cargo.toml +++ b/frame/bags-list/remote-tests/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-bags-list-remote-tests" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/balances/Cargo.toml b/frame/balances/Cargo.toml index f6e6e97850a7..4ea2e9cbe8a3 100644 --- a/frame/balances/Cargo.toml +++ b/frame/balances/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-balances" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/beefy-mmr/Cargo.toml b/frame/beefy-mmr/Cargo.toml index 3d4a9a72ddf8..0a72ee193b3a 100644 --- a/frame/beefy-mmr/Cargo.toml +++ b/frame/beefy-mmr/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-beefy-mmr" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" description = "BEEFY + MMR runtime utilities" diff --git a/frame/beefy-mmr/primitives/Cargo.toml b/frame/beefy-mmr/primitives/Cargo.toml index d5dcc0eed335..3669ba4c2286 100644 --- a/frame/beefy-mmr/primitives/Cargo.toml +++ b/frame/beefy-mmr/primitives/Cargo.toml @@ -2,7 +2,7 @@ name = "beefy-merkle-tree" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" description = "A no-std/Substrate compatible library to construct binary merkle tree." diff --git a/frame/beefy/Cargo.toml b/frame/beefy/Cargo.toml index e5af666e7ca5..a8b516aac66c 100644 --- a/frame/beefy/Cargo.toml +++ b/frame/beefy/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-beefy" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" [dependencies] diff --git a/frame/benchmarking/Cargo.toml b/frame/benchmarking/Cargo.toml index dffada428248..fdc386978dee 100644 --- a/frame/benchmarking/Cargo.toml +++ b/frame/benchmarking/Cargo.toml @@ -2,7 +2,7 @@ name = "frame-benchmarking" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/bounties/Cargo.toml b/frame/bounties/Cargo.toml index d949d0fb1d58..cce6ed69a25b 100644 --- a/frame/bounties/Cargo.toml +++ b/frame/bounties/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-bounties" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/collective/Cargo.toml b/frame/collective/Cargo.toml index 3e3d167522e8..6d4567a7851e 100644 --- a/frame/collective/Cargo.toml +++ b/frame/collective/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-collective" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/contracts/Cargo.toml b/frame/contracts/Cargo.toml index 5967600bf68f..dec33768a042 100644 --- a/frame/contracts/Cargo.toml +++ b/frame/contracts/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-contracts" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/contracts/common/Cargo.toml b/frame/contracts/common/Cargo.toml index 48baf23d3aee..c30efc686940 100644 --- a/frame/contracts/common/Cargo.toml +++ b/frame/contracts/common/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-contracts-primitives" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/contracts/proc-macro/Cargo.toml b/frame/contracts/proc-macro/Cargo.toml index 63d05bcc2f05..db3c62039777 100644 --- a/frame/contracts/proc-macro/Cargo.toml +++ b/frame/contracts/proc-macro/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-contracts-proc-macro" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/contracts/rpc/Cargo.toml b/frame/contracts/rpc/Cargo.toml index eec02b03aaa0..82ce4bedb498 100644 --- a/frame/contracts/rpc/Cargo.toml +++ b/frame/contracts/rpc/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-contracts-rpc" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/contracts/rpc/runtime-api/Cargo.toml b/frame/contracts/rpc/runtime-api/Cargo.toml index e41aa5aaec9b..b65fbf9aba0c 100644 --- a/frame/contracts/rpc/runtime-api/Cargo.toml +++ b/frame/contracts/rpc/runtime-api/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-contracts-rpc-runtime-api" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/democracy/Cargo.toml b/frame/democracy/Cargo.toml index f0bf2109be06..1973677531e9 100644 --- a/frame/democracy/Cargo.toml +++ b/frame/democracy/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-democracy" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/election-provider-multi-phase/Cargo.toml b/frame/election-provider-multi-phase/Cargo.toml index 3c6b405c331f..8a0f80da1082 100644 --- a/frame/election-provider-multi-phase/Cargo.toml +++ b/frame/election-provider-multi-phase/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-election-provider-multi-phase" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/election-provider-support/Cargo.toml b/frame/election-provider-support/Cargo.toml index 46e6500cac33..e22338f456c4 100644 --- a/frame/election-provider-support/Cargo.toml +++ b/frame/election-provider-support/Cargo.toml @@ -2,7 +2,7 @@ name = "frame-election-provider-support" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/elections-phragmen/Cargo.toml b/frame/elections-phragmen/Cargo.toml index 80afc3f5d8b0..6c87be7b6d58 100644 --- a/frame/elections-phragmen/Cargo.toml +++ b/frame/elections-phragmen/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-elections-phragmen" version = "5.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/elections/Cargo.toml b/frame/elections/Cargo.toml index f5c7acb1cd5d..2ca2e584d2f4 100644 --- a/frame/elections/Cargo.toml +++ b/frame/elections/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-elections" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/example-offchain-worker/Cargo.toml b/frame/example-offchain-worker/Cargo.toml index 2759664d6e65..ffcadca26e11 100644 --- a/frame/example-offchain-worker/Cargo.toml +++ b/frame/example-offchain-worker/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-example-offchain-worker" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Unlicense" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/example-parallel/Cargo.toml b/frame/example-parallel/Cargo.toml index 6511a1cd369b..169db35e65f1 100644 --- a/frame/example-parallel/Cargo.toml +++ b/frame/example-parallel/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-example-parallel" version = "3.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Unlicense" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/example-parallel/src/lib.rs b/frame/example-parallel/src/lib.rs index c86cac429568..9d191525f631 100644 --- a/frame/example-parallel/src/lib.rs +++ b/frame/example-parallel/src/lib.rs @@ -105,7 +105,6 @@ impl EnlistedParticipant { fn verify(&self, event_id: &[u8]) -> bool { use sp_core::Public; use sp_runtime::traits::Verify; - use std::convert::TryFrom; match sp_core::sr25519::Signature::try_from(&self.signature[..]) { Ok(signature) => { diff --git a/frame/example/Cargo.toml b/frame/example/Cargo.toml index e144f1e927d3..0b3a742de0dd 100644 --- a/frame/example/Cargo.toml +++ b/frame/example/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-example" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Unlicense" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/executive/Cargo.toml b/frame/executive/Cargo.toml index 44b4dbcf2bd3..52d2f41cb1e3 100644 --- a/frame/executive/Cargo.toml +++ b/frame/executive/Cargo.toml @@ -2,7 +2,7 @@ name = "frame-executive" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/gilt/Cargo.toml b/frame/gilt/Cargo.toml index c7dc384662f9..6b2eae1156a8 100644 --- a/frame/gilt/Cargo.toml +++ b/frame/gilt/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-gilt" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/grandpa/Cargo.toml b/frame/grandpa/Cargo.toml index 36cc43fc3443..af125d64ea21 100644 --- a/frame/grandpa/Cargo.toml +++ b/frame/grandpa/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-grandpa" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/identity/Cargo.toml b/frame/identity/Cargo.toml index e6d1fa3e9dfb..9a370674e587 100644 --- a/frame/identity/Cargo.toml +++ b/frame/identity/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-identity" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/im-online/Cargo.toml b/frame/im-online/Cargo.toml index ef2fe54a8cee..f4cf5a9077c9 100644 --- a/frame/im-online/Cargo.toml +++ b/frame/im-online/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-im-online" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/indices/Cargo.toml b/frame/indices/Cargo.toml index bf5a82fbb1da..f1913d4138be 100644 --- a/frame/indices/Cargo.toml +++ b/frame/indices/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-indices" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/lottery/Cargo.toml b/frame/lottery/Cargo.toml index 854b6f52470d..d4ee5b8008f1 100644 --- a/frame/lottery/Cargo.toml +++ b/frame/lottery/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-lottery" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/membership/Cargo.toml b/frame/membership/Cargo.toml index 9fdfaa473172..a3747ca0576f 100644 --- a/frame/membership/Cargo.toml +++ b/frame/membership/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-membership" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/merkle-mountain-range/Cargo.toml b/frame/merkle-mountain-range/Cargo.toml index 942067ebde3e..ca09725769ab 100644 --- a/frame/merkle-mountain-range/Cargo.toml +++ b/frame/merkle-mountain-range/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-mmr" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/merkle-mountain-range/primitives/Cargo.toml b/frame/merkle-mountain-range/primitives/Cargo.toml index bbf55a2b7089..0531a295fafe 100644 --- a/frame/merkle-mountain-range/primitives/Cargo.toml +++ b/frame/merkle-mountain-range/primitives/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-mmr-primitives" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/merkle-mountain-range/rpc/Cargo.toml b/frame/merkle-mountain-range/rpc/Cargo.toml index 926cfd602f67..881cbb3c8ebf 100644 --- a/frame/merkle-mountain-range/rpc/Cargo.toml +++ b/frame/merkle-mountain-range/rpc/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-mmr-rpc" version = "3.0.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/multisig/Cargo.toml b/frame/multisig/Cargo.toml index d1bd23dcab58..2b0d8f5cee79 100644 --- a/frame/multisig/Cargo.toml +++ b/frame/multisig/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-multisig" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/nicks/Cargo.toml b/frame/nicks/Cargo.toml index dacec5567ede..039fd7f97c85 100644 --- a/frame/nicks/Cargo.toml +++ b/frame/nicks/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-nicks" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/node-authorization/Cargo.toml b/frame/node-authorization/Cargo.toml index 960f7e04688d..450da1325f67 100644 --- a/frame/node-authorization/Cargo.toml +++ b/frame/node-authorization/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-node-authorization" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/offences/Cargo.toml b/frame/offences/Cargo.toml index 97f4644a83ca..15939027d3be 100644 --- a/frame/offences/Cargo.toml +++ b/frame/offences/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-offences" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/offences/benchmarking/Cargo.toml b/frame/offences/benchmarking/Cargo.toml index f8459087cb7f..cf628b6967ce 100644 --- a/frame/offences/benchmarking/Cargo.toml +++ b/frame/offences/benchmarking/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-offences-benchmarking" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/proxy/Cargo.toml b/frame/proxy/Cargo.toml index 4f4cf2bf9d56..030209b83cc6 100644 --- a/frame/proxy/Cargo.toml +++ b/frame/proxy/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-proxy" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/randomness-collective-flip/Cargo.toml b/frame/randomness-collective-flip/Cargo.toml index ba7731269917..38fe2f73bc71 100644 --- a/frame/randomness-collective-flip/Cargo.toml +++ b/frame/randomness-collective-flip/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-randomness-collective-flip" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/recovery/Cargo.toml b/frame/recovery/Cargo.toml index 092940f5173f..12198c135e53 100644 --- a/frame/recovery/Cargo.toml +++ b/frame/recovery/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-recovery" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/scheduler/Cargo.toml b/frame/scheduler/Cargo.toml index 862321dfa6f2..fab2bc2c635c 100644 --- a/frame/scheduler/Cargo.toml +++ b/frame/scheduler/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-scheduler" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Unlicense" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/scored-pool/Cargo.toml b/frame/scored-pool/Cargo.toml index a7d75ccacb96..d60e55ae9896 100644 --- a/frame/scored-pool/Cargo.toml +++ b/frame/scored-pool/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-scored-pool" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/session/Cargo.toml b/frame/session/Cargo.toml index 32d298d3917c..90de15632a0e 100644 --- a/frame/session/Cargo.toml +++ b/frame/session/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-session" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/session/benchmarking/Cargo.toml b/frame/session/benchmarking/Cargo.toml index 0d0868d43921..31a028679cfb 100644 --- a/frame/session/benchmarking/Cargo.toml +++ b/frame/session/benchmarking/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-session-benchmarking" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/society/Cargo.toml b/frame/society/Cargo.toml index ab2c379c51b5..8a817f7e0060 100644 --- a/frame/society/Cargo.toml +++ b/frame/society/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-society" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/staking/Cargo.toml b/frame/staking/Cargo.toml index 4b608bd91dc7..d9461ab454f3 100644 --- a/frame/staking/Cargo.toml +++ b/frame/staking/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-staking" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/staking/reward-curve/Cargo.toml b/frame/staking/reward-curve/Cargo.toml index e44188bf7894..15ff3a872730 100644 --- a/frame/staking/reward-curve/Cargo.toml +++ b/frame/staking/reward-curve/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-staking-reward-curve" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/staking/reward-fn/Cargo.toml b/frame/staking/reward-fn/Cargo.toml index ae0b7f50c994..4e3be2a1bc71 100644 --- a/frame/staking/reward-fn/Cargo.toml +++ b/frame/staking/reward-fn/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-staking-reward-fn" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index ec34efe397f5..7ca1cb1a4a61 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -926,7 +926,6 @@ impl ElectionDataProvider> for Pallet #[cfg(feature = "runtime-benchmarks")] fn add_voter(voter: T::AccountId, weight: VoteWeight, targets: Vec) { - use sp_std::convert::TryFrom; let stake = >::try_from(weight).unwrap_or_else(|_| { panic!("cannot convert a VoteWeight into BalanceOf, benchmark needs reconfiguring.") }); @@ -981,7 +980,6 @@ impl ElectionDataProvider> for Pallet targets: Vec, target_stake: Option, ) { - use sp_std::convert::TryFrom; targets.into_iter().for_each(|v| { let stake: BalanceOf = target_stake .and_then(|w| >::try_from(w).ok()) @@ -1256,7 +1254,6 @@ impl VoteWeightProvider for Pallet { fn set_vote_weight_of(who: &T::AccountId, weight: VoteWeight) { // this will clearly results in an inconsistent state, but it should not matter for a // benchmark. - use sp_std::convert::TryInto; let active: BalanceOf = weight.try_into().map_err(|_| ()).unwrap(); let mut ledger = Self::ledger(who).unwrap_or_default(); ledger.active = active; diff --git a/frame/sudo/Cargo.toml b/frame/sudo/Cargo.toml index 3587a234566e..969dc11dbb6c 100644 --- a/frame/sudo/Cargo.toml +++ b/frame/sudo/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-sudo" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/support/Cargo.toml b/frame/support/Cargo.toml index b62ae3384fe4..42981dc160a4 100644 --- a/frame/support/Cargo.toml +++ b/frame/support/Cargo.toml @@ -2,7 +2,7 @@ name = "frame-support" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/support/procedural/Cargo.toml b/frame/support/procedural/Cargo.toml index ed152c25fc3b..17128388874a 100644 --- a/frame/support/procedural/Cargo.toml +++ b/frame/support/procedural/Cargo.toml @@ -2,7 +2,7 @@ name = "frame-support-procedural" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/support/procedural/src/pallet/expand/constants.rs b/frame/support/procedural/src/pallet/expand/constants.rs index 20106c71cbf0..0fe8e467c10d 100644 --- a/frame/support/procedural/src/pallet/expand/constants.rs +++ b/frame/support/procedural/src/pallet/expand/constants.rs @@ -52,7 +52,7 @@ pub fn expand_constants(def: &mut Def) -> proc_macro2::TokenStream { type_: const_.type_.clone(), doc: const_.doc.clone(), default_byte_impl: quote::quote!( - let value = <::#ident as + let value = <::#ident as #frame_support::traits::Get<#const_type>>::get(); #frame_support::codec::Encode::encode(&value) ), diff --git a/frame/support/procedural/src/pallet/expand/event.rs b/frame/support/procedural/src/pallet/expand/event.rs index 625c2d98baac..69d6b461206c 100644 --- a/frame/support/procedural/src/pallet/expand/event.rs +++ b/frame/support/procedural/src/pallet/expand/event.rs @@ -134,12 +134,12 @@ pub fn expand_event(def: &mut Def) -> proc_macro2::TokenStream { impl<#type_impl_gen> Pallet<#type_use_gen> #completed_where_clause { #fn_vis fn deposit_event(event: Event<#event_use_gen>) { let event = < - ::Event as + ::Event as From> >::from(event); let event = < - ::Event as + ::Event as Into<::Event> >::into(event); diff --git a/frame/support/procedural/src/storage/genesis_config/mod.rs b/frame/support/procedural/src/storage/genesis_config/mod.rs index d2d1afb01773..daff8848364e 100644 --- a/frame/support/procedural/src/storage/genesis_config/mod.rs +++ b/frame/support/procedural/src/storage/genesis_config/mod.rs @@ -75,12 +75,12 @@ fn decl_genesis_config_and_impl_default( #[serde(deny_unknown_fields)] #[serde(crate = #serde_crate)] #serde_bug_bound - pub struct GenesisConfig#genesis_struct_decl #genesis_where_clause { + pub struct GenesisConfig #genesis_struct_decl #genesis_where_clause { #( #config_fields )* } #[cfg(feature = "std")] - impl#genesis_impl Default for GenesisConfig#genesis_struct #genesis_where_clause { + impl #genesis_impl Default for GenesisConfig #genesis_struct #genesis_where_clause { fn default() -> Self { GenesisConfig { #( #config_field_defaults )* @@ -137,7 +137,7 @@ fn impl_build_storage( quote! { #[cfg(feature = "std")] - impl#genesis_impl GenesisConfig#genesis_struct #genesis_where_clause { + impl #genesis_impl GenesisConfig #genesis_struct #genesis_where_clause { /// Build the storage for this module. pub fn build_storage #fn_generic (&self) -> std::result::Result< #scrate::sp_runtime::Storage, @@ -161,7 +161,7 @@ fn impl_build_storage( } #[cfg(feature = "std")] - impl#build_storage_impl #build_storage_impl_trait for GenesisConfig#genesis_struct + impl #build_storage_impl #build_storage_impl_trait for GenesisConfig #genesis_struct #where_clause { fn build_module_genesis_storage( diff --git a/frame/support/procedural/src/storage/getters.rs b/frame/support/procedural/src/storage/getters.rs index 988e6fa09624..d877969232f8 100644 --- a/frame/support/procedural/src/storage/getters.rs +++ b/frame/support/procedural/src/storage/getters.rs @@ -92,7 +92,7 @@ pub fn impl_getters(def: &DeclStorageDefExt) -> TokenStream { let where_clause = &def.where_clause; quote!( - impl#module_impl #module_struct #where_clause { + impl #module_impl #module_struct #where_clause { #getters } ) diff --git a/frame/support/procedural/src/storage/metadata.rs b/frame/support/procedural/src/storage/metadata.rs index a90e5051c5b2..c49a0dafdf5d 100644 --- a/frame/support/procedural/src/storage/metadata.rs +++ b/frame/support/procedural/src/storage/metadata.rs @@ -207,7 +207,7 @@ pub fn impl_metadata(def: &DeclStorageDefExt) -> TokenStream { quote!( #default_byte_getter_struct_defs - impl#module_impl #module_struct #where_clause { + impl #module_impl #module_struct #where_clause { #[doc(hidden)] pub fn storage_metadata() -> #scrate::metadata::PalletStorageMetadata { #store_metadata diff --git a/frame/support/procedural/src/storage/storage_info.rs b/frame/support/procedural/src/storage/storage_info.rs index 844896409f85..4b1d3347b4a4 100644 --- a/frame/support/procedural/src/storage/storage_info.rs +++ b/frame/support/procedural/src/storage/storage_info.rs @@ -48,7 +48,7 @@ pub fn impl_storage_info(def: &DeclStorageDefExt) -> TokenStream { let where_clause = &def.where_clause; quote!( - impl#module_impl #scrate::traits::StorageInfoTrait for #module_struct #where_clause { + impl #module_impl #scrate::traits::StorageInfoTrait for #module_struct #where_clause { fn storage_info() -> #scrate::sp_std::vec::Vec<#scrate::traits::StorageInfo> { let mut res = #scrate::sp_std::vec![]; #res_append_storage diff --git a/frame/support/procedural/src/storage/store_trait.rs b/frame/support/procedural/src/storage/store_trait.rs index 7dde92cf9a75..5794c72d22c8 100644 --- a/frame/support/procedural/src/storage/store_trait.rs +++ b/frame/support/procedural/src/storage/store_trait.rs @@ -48,7 +48,7 @@ pub fn decl_and_impl(def: &DeclStorageDefExt) -> TokenStream { #visibility trait #store_trait { #decl_store_items } - impl#module_impl #store_trait for #module_struct #where_clause { + impl #module_impl #store_trait for #module_struct #where_clause { #impl_store_items } ) diff --git a/frame/support/procedural/tools/Cargo.toml b/frame/support/procedural/tools/Cargo.toml index 6a8fb57b39bd..1207d06e6d59 100644 --- a/frame/support/procedural/tools/Cargo.toml +++ b/frame/support/procedural/tools/Cargo.toml @@ -2,7 +2,7 @@ name = "frame-support-procedural-tools" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/support/procedural/tools/derive/Cargo.toml b/frame/support/procedural/tools/derive/Cargo.toml index 9f4e2d9dca2a..f0c27b5397d5 100644 --- a/frame/support/procedural/tools/derive/Cargo.toml +++ b/frame/support/procedural/tools/derive/Cargo.toml @@ -2,7 +2,7 @@ name = "frame-support-procedural-tools-derive" version = "3.0.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/support/procedural/tools/derive/src/lib.rs b/frame/support/procedural/tools/derive/src/lib.rs index 792210589560..9ce88e7c4793 100644 --- a/frame/support/procedural/tools/derive/src/lib.rs +++ b/frame/support/procedural/tools/derive/src/lib.rs @@ -131,7 +131,7 @@ fn derive_totokens_enum(input: syn::ItemEnum) -> TokenStream { }; let field = fields_idents(v.fields.iter().map(Clone::clone)); quote! { - #ident::#v_ident#fields_build => { + #ident::#v_ident #fields_build => { #( #field.to_tokens(tokens); )* diff --git a/frame/support/src/traits/members.rs b/frame/support/src/traits/members.rs index a59869c2fc9a..06a4c759c46d 100644 --- a/frame/support/src/traits/members.rs +++ b/frame/support/src/traits/members.rs @@ -70,7 +70,7 @@ impl Contains for Tuple { /// to `matches!`. #[macro_export] macro_rules! match_type { - ( pub type $n:ident: impl Contains<$t:ty> = { $phead:pat $( | $ptail:pat )* } ; ) => { + ( pub type $n:ident: impl Contains<$t:ty> = { $phead:pat_param $( | $ptail:pat )* } ; ) => { pub struct $n; impl $crate::traits::Contains<$t> for $n { fn contains(l: &$t) -> bool { diff --git a/frame/support/test/Cargo.toml b/frame/support/test/Cargo.toml index 77fd4f562096..762c85f75c36 100644 --- a/frame/support/test/Cargo.toml +++ b/frame/support/test/Cargo.toml @@ -2,7 +2,7 @@ name = "frame-support-test" version = "3.0.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" publish = false homepage = "https://substrate.io" @@ -23,7 +23,7 @@ sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../.. sp-core = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/core" } sp-std = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/std" } sp-version = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/version" } -trybuild = "1.0.43" +trybuild = "1.0.52" pretty_assertions = "1.0.0" rustversion = "1.0.0" frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" } @@ -36,13 +36,15 @@ std = [ "serde/std", "codec/std", "scale-info/std", - "sp-io/std", "frame-support/std", "frame-system/std", "sp-core/std", "sp-std/std", + "sp-io/std", "sp-runtime/std", "sp-state-machine", + "sp-arithmetic/std", + "sp-version/std", ] try-runtime = ["frame-support/try-runtime"] # WARNING: CI only execute pallet test with this feature, diff --git a/frame/support/test/compile_pass/Cargo.toml b/frame/support/test/compile_pass/Cargo.toml index bca833200d44..b8a64f4e7022 100644 --- a/frame/support/test/compile_pass/Cargo.toml +++ b/frame/support/test/compile_pass/Cargo.toml @@ -2,7 +2,7 @@ name = "frame-support-test-compile-pass" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" publish = false homepage = "https://substrate.dev" diff --git a/frame/support/test/pallet/Cargo.toml b/frame/support/test/pallet/Cargo.toml index a3d101967ae6..c26fdda4e962 100644 --- a/frame/support/test/pallet/Cargo.toml +++ b/frame/support/test/pallet/Cargo.toml @@ -2,7 +2,7 @@ name = "frame-support-test-pallet" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" publish = false homepage = "https://substrate.io" diff --git a/frame/support/test/tests/pallet.rs b/frame/support/test/tests/pallet.rs index dd171c5b12ec..dcf739af614b 100644 --- a/frame/support/test/tests/pallet.rs +++ b/frame/support/test/tests/pallet.rs @@ -166,25 +166,25 @@ pub mod pallet { T::AccountId: From + From + SomeAssociation1, { fn on_initialize(_: BlockNumberFor) -> Weight { - T::AccountId::from(SomeType1); // Test for where clause - T::AccountId::from(SomeType2); // Test for where clause + let _ = T::AccountId::from(SomeType1); // Test for where clause + let _ = T::AccountId::from(SomeType2); // Test for where clause Self::deposit_event(Event::Something(10)); 10 } fn on_finalize(_: BlockNumberFor) { - T::AccountId::from(SomeType1); // Test for where clause - T::AccountId::from(SomeType2); // Test for where clause + let _ = T::AccountId::from(SomeType1); // Test for where clause + let _ = T::AccountId::from(SomeType2); // Test for where clause Self::deposit_event(Event::Something(20)); } fn on_runtime_upgrade() -> Weight { - T::AccountId::from(SomeType1); // Test for where clause - T::AccountId::from(SomeType2); // Test for where clause + let _ = T::AccountId::from(SomeType1); // Test for where clause + let _ = T::AccountId::from(SomeType2); // Test for where clause Self::deposit_event(Event::Something(30)); 30 } fn integrity_test() { - T::AccountId::from(SomeType1); // Test for where clause - T::AccountId::from(SomeType2); // Test for where clause + let _ = T::AccountId::from(SomeType1); // Test for where clause + let _ = T::AccountId::from(SomeType2); // Test for where clause } } @@ -200,8 +200,8 @@ pub mod pallet { #[pallet::compact] _foo: u32, _bar: u32, ) -> DispatchResultWithPostInfo { - T::AccountId::from(SomeType1); // Test for where clause - T::AccountId::from(SomeType3); // Test for where clause + let _ = T::AccountId::from(SomeType1); // Test for where clause + let _ = T::AccountId::from(SomeType3); // Test for where clause let _ = origin; Self::deposit_event(Event::Something(3)); Ok(().into()) @@ -268,7 +268,7 @@ pub mod pallet { where T::AccountId: From + From + SomeAssociation1, { - T::AccountId::from(SomeType7); // Test where clause works + let _ = T::AccountId::from(SomeType7); // Test where clause works 4u16 } @@ -352,8 +352,8 @@ pub mod pallet { T::AccountId: From + SomeAssociation1 + From, { fn build(&self) { - T::AccountId::from(SomeType1); // Test for where clause - T::AccountId::from(SomeType4); // Test for where clause + let _ = T::AccountId::from(SomeType1); // Test for where clause + let _ = T::AccountId::from(SomeType4); // Test for where clause } } @@ -370,8 +370,8 @@ pub mod pallet { { type Call = Call; fn validate_unsigned(_source: TransactionSource, call: &Self::Call) -> TransactionValidity { - T::AccountId::from(SomeType1); // Test for where clause - T::AccountId::from(SomeType5); // Test for where clause + let _ = T::AccountId::from(SomeType1); // Test for where clause + let _ = T::AccountId::from(SomeType5); // Test for where clause if matches!(call, Call::foo_transactional { .. }) { return Ok(ValidTransaction::default()) } @@ -390,8 +390,8 @@ pub mod pallet { const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER; fn create_inherent(_data: &InherentData) -> Option { - T::AccountId::from(SomeType1); // Test for where clause - T::AccountId::from(SomeType6); // Test for where clause + let _ = T::AccountId::from(SomeType1); // Test for where clause + let _ = T::AccountId::from(SomeType6); // Test for where clause Some(Call::foo_no_post_info {}) } diff --git a/frame/system/Cargo.toml b/frame/system/Cargo.toml index dc69bd2d5e85..c5d2144e28dd 100644 --- a/frame/system/Cargo.toml +++ b/frame/system/Cargo.toml @@ -2,7 +2,7 @@ name = "frame-system" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/system/benchmarking/Cargo.toml b/frame/system/benchmarking/Cargo.toml index 6aa2251f287d..7e7c2f6e69f2 100644 --- a/frame/system/benchmarking/Cargo.toml +++ b/frame/system/benchmarking/Cargo.toml @@ -2,7 +2,7 @@ name = "frame-system-benchmarking" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/system/rpc/runtime-api/Cargo.toml b/frame/system/rpc/runtime-api/Cargo.toml index b5e569e1298c..67e627f7dcf9 100644 --- a/frame/system/rpc/runtime-api/Cargo.toml +++ b/frame/system/rpc/runtime-api/Cargo.toml @@ -2,7 +2,7 @@ name = "frame-system-rpc-runtime-api" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/timestamp/Cargo.toml b/frame/timestamp/Cargo.toml index cd636ec6c23b..2f07b2a0975a 100644 --- a/frame/timestamp/Cargo.toml +++ b/frame/timestamp/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-timestamp" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/tips/Cargo.toml b/frame/tips/Cargo.toml index a3f268169b78..805f1663d1ae 100644 --- a/frame/tips/Cargo.toml +++ b/frame/tips/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-tips" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/transaction-payment/Cargo.toml b/frame/transaction-payment/Cargo.toml index bea263cbef6f..1d3066e39fbd 100644 --- a/frame/transaction-payment/Cargo.toml +++ b/frame/transaction-payment/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-transaction-payment" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/transaction-payment/rpc/Cargo.toml b/frame/transaction-payment/rpc/Cargo.toml index 1a2c68227c11..8ce2e4991568 100644 --- a/frame/transaction-payment/rpc/Cargo.toml +++ b/frame/transaction-payment/rpc/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-transaction-payment-rpc" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/transaction-payment/rpc/runtime-api/Cargo.toml b/frame/transaction-payment/rpc/runtime-api/Cargo.toml index 7bdca2f65829..315f140fc4f2 100644 --- a/frame/transaction-payment/rpc/runtime-api/Cargo.toml +++ b/frame/transaction-payment/rpc/runtime-api/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-transaction-payment-rpc-runtime-api" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/transaction-storage/Cargo.toml b/frame/transaction-storage/Cargo.toml index bcd3fd145f57..7167ae742457 100644 --- a/frame/transaction-storage/Cargo.toml +++ b/frame/transaction-storage/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-transaction-storage" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Unlicense" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/treasury/Cargo.toml b/frame/treasury/Cargo.toml index bcbe41985c65..d375e22df949 100644 --- a/frame/treasury/Cargo.toml +++ b/frame/treasury/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-treasury" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/try-runtime/Cargo.toml b/frame/try-runtime/Cargo.toml index 611a84427826..c94771795319 100644 --- a/frame/try-runtime/Cargo.toml +++ b/frame/try-runtime/Cargo.toml @@ -2,7 +2,7 @@ name = "frame-try-runtime" version = "0.10.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/uniques/Cargo.toml b/frame/uniques/Cargo.toml index f240bb98afab..4b6d0485567c 100644 --- a/frame/uniques/Cargo.toml +++ b/frame/uniques/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-uniques" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/utility/Cargo.toml b/frame/utility/Cargo.toml index 0a0a9eafd845..c55b20df2785 100644 --- a/frame/utility/Cargo.toml +++ b/frame/utility/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-utility" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/vesting/Cargo.toml b/frame/vesting/Cargo.toml index 3179607b3f6d..035124f7d0de 100644 --- a/frame/vesting/Cargo.toml +++ b/frame/vesting/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-vesting" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/api/Cargo.toml b/primitives/api/Cargo.toml index c57c3730fc7b..65da54b87753 100644 --- a/primitives/api/Cargo.toml +++ b/primitives/api/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-api" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/api/proc-macro/Cargo.toml b/primitives/api/proc-macro/Cargo.toml index d9dd0bf9020c..7b0b55c8c3b5 100644 --- a/primitives/api/proc-macro/Cargo.toml +++ b/primitives/api/proc-macro/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-api-proc-macro" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/api/proc-macro/src/decl_runtime_apis.rs b/primitives/api/proc-macro/src/decl_runtime_apis.rs index 510a2eeaa530..34907d619728 100644 --- a/primitives/api/proc-macro/src/decl_runtime_apis.rs +++ b/primitives/api/proc-macro/src/decl_runtime_apis.rs @@ -786,7 +786,7 @@ fn generate_runtime_info_impl(trait_: &ItemTrait, version: u64) -> TokenStream { quote!( #[cfg(any(feature = "std", test))] impl < #( #impl_generics, )* > #crate_::RuntimeApiInfo - for #trait_name < #( #ty_generics, )* > + for dyn #trait_name < #( #ty_generics, )* > { #id #version diff --git a/primitives/api/src/lib.rs b/primitives/api/src/lib.rs index 82954d193e60..cb74f95d21b0 100644 --- a/primitives/api/src/lib.rs +++ b/primitives/api/src/lib.rs @@ -644,8 +644,6 @@ pub const fn serialize_runtime_api_info(id: [u8; 8], version: u32) -> [u8; RUNTI /// Deserialize the runtime API info serialized by [`serialize_runtime_api_info`]. pub fn deserialize_runtime_api_info(bytes: [u8; RUNTIME_API_INFO_SIZE]) -> ([u8; 8], u32) { - use sp_std::convert::TryInto; - let id: [u8; 8] = bytes[0..8] .try_into() .expect("the source slice size is equal to the dest array length; qed"); diff --git a/primitives/api/test/Cargo.toml b/primitives/api/test/Cargo.toml index faee5ebdc77d..8c274b386470 100644 --- a/primitives/api/test/Cargo.toml +++ b/primitives/api/test/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-api-test" version = "2.0.1" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" publish = false homepage = "https://substrate.io" @@ -21,7 +21,7 @@ sp-consensus = { version = "0.10.0-dev", path = "../../consensus/common" } sc-block-builder = { version = "0.10.0-dev", path = "../../../client/block-builder" } codec = { package = "parity-scale-codec", version = "2.0.0" } sp-state-machine = { version = "0.10.0-dev", path = "../../state-machine" } -trybuild = "1.0.43" +trybuild = "1.0.52" rustversion = "1.0.0" [dev-dependencies] diff --git a/primitives/application-crypto/Cargo.toml b/primitives/application-crypto/Cargo.toml index 88411d86392a..e715d2ed3d31 100644 --- a/primitives/application-crypto/Cargo.toml +++ b/primitives/application-crypto/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-application-crypto" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" description = "Provides facilities for generating application specific crypto wrapper types." license = "Apache-2.0" homepage = "https://substrate.io" diff --git a/primitives/application-crypto/test/Cargo.toml b/primitives/application-crypto/test/Cargo.toml index d10f011c4c60..f59f5d9a249c 100644 --- a/primitives/application-crypto/test/Cargo.toml +++ b/primitives/application-crypto/test/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-application-crypto-test" version = "2.0.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" description = "Integration tests for application-crypto" license = "Apache-2.0" publish = false diff --git a/primitives/arithmetic/Cargo.toml b/primitives/arithmetic/Cargo.toml index 92b16b895e3b..e6fa1759774e 100644 --- a/primitives/arithmetic/Cargo.toml +++ b/primitives/arithmetic/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-arithmetic" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/arithmetic/fuzzer/Cargo.toml b/primitives/arithmetic/fuzzer/Cargo.toml index 5f2d5801ff99..d6b208852377 100644 --- a/primitives/arithmetic/fuzzer/Cargo.toml +++ b/primitives/arithmetic/fuzzer/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-arithmetic-fuzzer" version = "2.0.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/authority-discovery/Cargo.toml b/primitives/authority-discovery/Cargo.toml index d4c75dda352c..22f3884b5502 100644 --- a/primitives/authority-discovery/Cargo.toml +++ b/primitives/authority-discovery/Cargo.toml @@ -3,7 +3,7 @@ name = "sp-authority-discovery" version = "4.0.0-dev" authors = ["Parity Technologies "] description = "Authority discovery primitives" -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/authorship/Cargo.toml b/primitives/authorship/Cargo.toml index cee82ca77c37..a31a34961116 100644 --- a/primitives/authorship/Cargo.toml +++ b/primitives/authorship/Cargo.toml @@ -3,7 +3,7 @@ name = "sp-authorship" version = "4.0.0-dev" authors = ["Parity Technologies "] description = "Authorship primitives" -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/beefy/Cargo.toml b/primitives/beefy/Cargo.toml index 633ac0e8fbcd..83472f54c513 100644 --- a/primitives/beefy/Cargo.toml +++ b/primitives/beefy/Cargo.toml @@ -2,7 +2,7 @@ name = "beefy-primitives" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" [dependencies] diff --git a/primitives/block-builder/Cargo.toml b/primitives/block-builder/Cargo.toml index 8499bdf8e1c7..6c6579c35329 100644 --- a/primitives/block-builder/Cargo.toml +++ b/primitives/block-builder/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-block-builder" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/blockchain/Cargo.toml b/primitives/blockchain/Cargo.toml index 93daef5fa1a2..7af7807954ef 100644 --- a/primitives/blockchain/Cargo.toml +++ b/primitives/blockchain/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-blockchain" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/consensus/aura/Cargo.toml b/primitives/consensus/aura/Cargo.toml index ca73cf206de0..361095c6218f 100644 --- a/primitives/consensus/aura/Cargo.toml +++ b/primitives/consensus/aura/Cargo.toml @@ -3,7 +3,7 @@ name = "sp-consensus-aura" version = "0.10.0-dev" authors = ["Parity Technologies "] description = "Primitives for Aura consensus" -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/consensus/babe/Cargo.toml b/primitives/consensus/babe/Cargo.toml index 1690b7c9a02d..d942f7290945 100644 --- a/primitives/consensus/babe/Cargo.toml +++ b/primitives/consensus/babe/Cargo.toml @@ -3,7 +3,7 @@ name = "sp-consensus-babe" version = "0.10.0-dev" authors = ["Parity Technologies "] description = "Primitives for BABE consensus" -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/consensus/common/Cargo.toml b/primitives/consensus/common/Cargo.toml index 9a5488abba65..735b1e8eb095 100644 --- a/primitives/consensus/common/Cargo.toml +++ b/primitives/consensus/common/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-consensus" version = "0.10.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/consensus/pow/Cargo.toml b/primitives/consensus/pow/Cargo.toml index 406ed3dea46a..07863850a8f8 100644 --- a/primitives/consensus/pow/Cargo.toml +++ b/primitives/consensus/pow/Cargo.toml @@ -3,7 +3,7 @@ name = "sp-consensus-pow" version = "0.10.0-dev" authors = ["Parity Technologies "] description = "Primitives for Aura consensus" -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/consensus/slots/Cargo.toml b/primitives/consensus/slots/Cargo.toml index 014ee9b93e6e..ad83835e0270 100644 --- a/primitives/consensus/slots/Cargo.toml +++ b/primitives/consensus/slots/Cargo.toml @@ -3,7 +3,7 @@ name = "sp-consensus-slots" version = "0.10.0-dev" authors = ["Parity Technologies "] description = "Primitives for slots-based consensus" -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/consensus/vrf/Cargo.toml b/primitives/consensus/vrf/Cargo.toml index c103e68eb66b..8a99dc9432a0 100644 --- a/primitives/consensus/vrf/Cargo.toml +++ b/primitives/consensus/vrf/Cargo.toml @@ -3,7 +3,7 @@ name = "sp-consensus-vrf" version = "0.10.0-dev" authors = ["Parity Technologies "] description = "Primitives for VRF based consensus" -edition = "2018" +edition = "2021" license = "Apache-2.0" repository = "https://github.com/paritytech/substrate/" homepage = "https://substrate.io" diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index 148f2343ee2b..63ca358e6810 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-core" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/core/hashing/Cargo.toml b/primitives/core/hashing/Cargo.toml index 43c670b59b0a..eeee40405344 100644 --- a/primitives/core/hashing/Cargo.toml +++ b/primitives/core/hashing/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-core-hashing" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/core/hashing/proc-macro/Cargo.toml b/primitives/core/hashing/proc-macro/Cargo.toml index 6d83b50b8a29..452165b31cb9 100644 --- a/primitives/core/hashing/proc-macro/Cargo.toml +++ b/primitives/core/hashing/proc-macro/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-core-hashing-proc-macro" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/database/Cargo.toml b/primitives/database/Cargo.toml index c3d2d8ce99df..94e16f3cfb3d 100644 --- a/primitives/database/Cargo.toml +++ b/primitives/database/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-database" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/debug-derive/Cargo.toml b/primitives/debug-derive/Cargo.toml index 954d0f89663f..d1f1f81a9f14 100644 --- a/primitives/debug-derive/Cargo.toml +++ b/primitives/debug-derive/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-debug-derive" version = "3.0.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/externalities/Cargo.toml b/primitives/externalities/Cargo.toml index 5a1b6b5e7373..96199c5b4d22 100644 --- a/primitives/externalities/Cargo.toml +++ b/primitives/externalities/Cargo.toml @@ -3,7 +3,7 @@ name = "sp-externalities" version = "0.10.0-dev" license = "Apache-2.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Substrate externalities abstraction" diff --git a/primitives/finality-grandpa/Cargo.toml b/primitives/finality-grandpa/Cargo.toml index 5cf7ac6711a7..4b9fde85147e 100644 --- a/primitives/finality-grandpa/Cargo.toml +++ b/primitives/finality-grandpa/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-finality-grandpa" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/finality-grandpa/src/lib.rs b/primitives/finality-grandpa/src/lib.rs index d99a4c188222..b762a1596bf8 100644 --- a/primitives/finality-grandpa/src/lib.rs +++ b/primitives/finality-grandpa/src/lib.rs @@ -389,7 +389,6 @@ where { use sp_application_crypto::AppKey; use sp_core::crypto::Public; - use sp_std::convert::TryInto; let encoded = localized_payload(round, set_id, &message); let signature = SyncCryptoStore::sign_with( diff --git a/primitives/inherents/Cargo.toml b/primitives/inherents/Cargo.toml index 04b662fb059f..d52140d94ed3 100644 --- a/primitives/inherents/Cargo.toml +++ b/primitives/inherents/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-inherents" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/io/Cargo.toml b/primitives/io/Cargo.toml index df9a496a914b..2d7c50bdc25e 100644 --- a/primitives/io/Cargo.toml +++ b/primitives/io/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-io" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/keyring/Cargo.toml b/primitives/keyring/Cargo.toml index 464abdb6cb1a..3b5d916b47b6 100644 --- a/primitives/keyring/Cargo.toml +++ b/primitives/keyring/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-keyring" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/keystore/Cargo.toml b/primitives/keystore/Cargo.toml index 3a0532f1db31..e16ff4676c3b 100644 --- a/primitives/keystore/Cargo.toml +++ b/primitives/keystore/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-keystore" version = "0.10.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/maybe-compressed-blob/Cargo.toml b/primitives/maybe-compressed-blob/Cargo.toml index cd124580ef19..95ba9b332412 100644 --- a/primitives/maybe-compressed-blob/Cargo.toml +++ b/primitives/maybe-compressed-blob/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-maybe-compressed-blob" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/npos-elections/Cargo.toml b/primitives/npos-elections/Cargo.toml index 5ffaf76379bd..95f303a38252 100644 --- a/primitives/npos-elections/Cargo.toml +++ b/primitives/npos-elections/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-npos-elections" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/npos-elections/fuzzer/Cargo.toml b/primitives/npos-elections/fuzzer/Cargo.toml index 1d13d33a35e8..f9fce9d8744d 100644 --- a/primitives/npos-elections/fuzzer/Cargo.toml +++ b/primitives/npos-elections/fuzzer/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-npos-elections-fuzzer" version = "2.0.0-alpha.5" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/npos-elections/solution-type/Cargo.toml b/primitives/npos-elections/solution-type/Cargo.toml index 27d5d0bb1231..f50150bdbd58 100644 --- a/primitives/npos-elections/solution-type/Cargo.toml +++ b/primitives/npos-elections/solution-type/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-npos-elections-solution-type" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" @@ -26,4 +26,4 @@ scale-info = "1.0" sp-arithmetic = { path = "../../arithmetic", version = "4.0.0-dev" } # used by generate_solution_type: sp-npos-elections = { path = "..", version = "4.0.0-dev" } -trybuild = "1.0.43" +trybuild = "1.0.52" diff --git a/primitives/offchain/Cargo.toml b/primitives/offchain/Cargo.toml index c1e891acba95..c4da2b4f8892 100644 --- a/primitives/offchain/Cargo.toml +++ b/primitives/offchain/Cargo.toml @@ -4,7 +4,7 @@ name = "sp-offchain" version = "4.0.0-dev" license = "Apache-2.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" readme = "README.md" diff --git a/primitives/panic-handler/Cargo.toml b/primitives/panic-handler/Cargo.toml index 890cc277bd84..0845e175c237 100644 --- a/primitives/panic-handler/Cargo.toml +++ b/primitives/panic-handler/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-panic-handler" version = "3.0.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/rpc/Cargo.toml b/primitives/rpc/Cargo.toml index af883e219941..15f7aa2b3b89 100644 --- a/primitives/rpc/Cargo.toml +++ b/primitives/rpc/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-rpc" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/runtime-interface/Cargo.toml b/primitives/runtime-interface/Cargo.toml index fc8923cdb80a..c640f02824f2 100644 --- a/primitives/runtime-interface/Cargo.toml +++ b/primitives/runtime-interface/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-runtime-interface" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" @@ -31,7 +31,7 @@ sp-state-machine = { version = "0.10.0-dev", path = "../state-machine" } sp-core = { version = "4.0.0-dev", path = "../core" } sp-io = { version = "4.0.0-dev", path = "../io" } rustversion = "1.0.0" -trybuild = "1.0.43" +trybuild = "1.0.52" [features] default = [ "std" ] diff --git a/primitives/runtime-interface/proc-macro/Cargo.toml b/primitives/runtime-interface/proc-macro/Cargo.toml index dd08d0331339..958a95ceb3fc 100644 --- a/primitives/runtime-interface/proc-macro/Cargo.toml +++ b/primitives/runtime-interface/proc-macro/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-runtime-interface-proc-macro" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml b/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml index a3c82de473ab..60ece9d78795 100644 --- a/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml +++ b/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-runtime-interface-test-wasm-deprecated" version = "2.0.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" build = "build.rs" license = "Apache-2.0" homepage = "https://substrate.io" diff --git a/primitives/runtime-interface/test-wasm/Cargo.toml b/primitives/runtime-interface/test-wasm/Cargo.toml index 557b5b9bee89..d8dcc8a47053 100644 --- a/primitives/runtime-interface/test-wasm/Cargo.toml +++ b/primitives/runtime-interface/test-wasm/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-runtime-interface-test-wasm" version = "2.0.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" build = "build.rs" license = "Apache-2.0" homepage = "https://substrate.io" diff --git a/primitives/runtime-interface/test/Cargo.toml b/primitives/runtime-interface/test/Cargo.toml index 26884d5cb729..4c88438f08c6 100644 --- a/primitives/runtime-interface/test/Cargo.toml +++ b/primitives/runtime-interface/test/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-runtime-interface-test" version = "2.0.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" publish = false homepage = "https://substrate.io" diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 475d2b769de3..9d2957e7aed1 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-runtime" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/sandbox/Cargo.toml b/primitives/sandbox/Cargo.toml index 80cd195c6f40..b1ee431042e7 100755 --- a/primitives/sandbox/Cargo.toml +++ b/primitives/sandbox/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-sandbox" version = "0.10.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/serializer/Cargo.toml b/primitives/serializer/Cargo.toml index cc438e9a1c14..5b2d499279a4 100644 --- a/primitives/serializer/Cargo.toml +++ b/primitives/serializer/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-serializer" version = "3.0.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/session/Cargo.toml b/primitives/session/Cargo.toml index 1e9ed6ec9b65..01b299091ed1 100644 --- a/primitives/session/Cargo.toml +++ b/primitives/session/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-session" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/staking/Cargo.toml b/primitives/staking/Cargo.toml index 8ea24760e2b8..3be8f4aba142 100644 --- a/primitives/staking/Cargo.toml +++ b/primitives/staking/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-staking" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/state-machine/Cargo.toml b/primitives/state-machine/Cargo.toml index bbe9728befd8..343151a50a92 100644 --- a/primitives/state-machine/Cargo.toml +++ b/primitives/state-machine/Cargo.toml @@ -3,7 +3,7 @@ name = "sp-state-machine" version = "0.10.0-dev" authors = ["Parity Technologies "] description = "Substrate State Machine" -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/std/Cargo.toml b/primitives/std/Cargo.toml index e4cacf60cc36..34f27ae7256d 100644 --- a/primitives/std/Cargo.toml +++ b/primitives/std/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-std" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/storage/Cargo.toml b/primitives/storage/Cargo.toml index c7d23fcf7010..2413c45a7312 100644 --- a/primitives/storage/Cargo.toml +++ b/primitives/storage/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-storage" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" description = "Storage related primitives" license = "Apache-2.0" homepage = "https://substrate.io" diff --git a/primitives/tasks/Cargo.toml b/primitives/tasks/Cargo.toml index f91d15d2d40b..f472ec88ea18 100644 --- a/primitives/tasks/Cargo.toml +++ b/primitives/tasks/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-tasks" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/test-primitives/Cargo.toml b/primitives/test-primitives/Cargo.toml index 75ce8b752d3c..4d184c7d02e7 100644 --- a/primitives/test-primitives/Cargo.toml +++ b/primitives/test-primitives/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-test-primitives" version = "2.0.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/timestamp/Cargo.toml b/primitives/timestamp/Cargo.toml index 32f4c5308343..552a3cb5e8d6 100644 --- a/primitives/timestamp/Cargo.toml +++ b/primitives/timestamp/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-timestamp" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/tracing/Cargo.toml b/primitives/tracing/Cargo.toml index 46930a674f2c..f4bfb1f15dad 100644 --- a/primitives/tracing/Cargo.toml +++ b/primitives/tracing/Cargo.toml @@ -3,7 +3,7 @@ name = "sp-tracing" version = "4.0.0-dev" license = "Apache-2.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" description = "Instrumentation primitives and macros for Substrate." diff --git a/primitives/transaction-pool/Cargo.toml b/primitives/transaction-pool/Cargo.toml index f74fcb44fee2..e4a407547971 100644 --- a/primitives/transaction-pool/Cargo.toml +++ b/primitives/transaction-pool/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-transaction-pool" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/transaction-storage-proof/Cargo.toml b/primitives/transaction-storage-proof/Cargo.toml index 536e2f201a10..c967497f4ff9 100644 --- a/primitives/transaction-storage-proof/Cargo.toml +++ b/primitives/transaction-storage-proof/Cargo.toml @@ -3,7 +3,7 @@ name = "sp-transaction-storage-proof" version = "4.0.0-dev" authors = ["Parity Technologies "] description = "Transaction storage proof primitives" -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/trie/Cargo.toml b/primitives/trie/Cargo.toml index 66d8a1e47276..6190df210403 100644 --- a/primitives/trie/Cargo.toml +++ b/primitives/trie/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] description = "Patricia trie stuff using a parity-scale-codec node format" repository = "https://github.com/paritytech/substrate/" license = "Apache-2.0" -edition = "2018" +edition = "2021" homepage = "https://substrate.io" documentation = "https://docs.rs/sp-trie" readme = "README.md" diff --git a/primitives/version/Cargo.toml b/primitives/version/Cargo.toml index 2a2c2698c74c..af44aed6c5b2 100644 --- a/primitives/version/Cargo.toml +++ b/primitives/version/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-version" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/version/proc-macro/Cargo.toml b/primitives/version/proc-macro/Cargo.toml index 587ca06bdc17..bf6e0bdec7a6 100644 --- a/primitives/version/proc-macro/Cargo.toml +++ b/primitives/version/proc-macro/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-version-proc-macro" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/primitives/wasm-interface/Cargo.toml b/primitives/wasm-interface/Cargo.toml index 73b47e563a5b..339c4cf8bc8b 100644 --- a/primitives/wasm-interface/Cargo.toml +++ b/primitives/wasm-interface/Cargo.toml @@ -2,7 +2,7 @@ name = "sp-wasm-interface" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/test-utils/Cargo.toml b/test-utils/Cargo.toml index a9ffefa05df7..6cb91bb589c6 100644 --- a/test-utils/Cargo.toml +++ b/test-utils/Cargo.toml @@ -2,7 +2,7 @@ name = "substrate-test-utils" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" @@ -18,4 +18,4 @@ tokio = { version = "1.10", features = ["macros", "time"] } [dev-dependencies] sc-service = { version = "0.10.0-dev", path = "../client/service" } -trybuild = { version = "1.0.43", features = [ "diff" ] } +trybuild = { version = "1.0.52", features = [ "diff" ] } diff --git a/test-utils/client/Cargo.toml b/test-utils/client/Cargo.toml index 204b6ac435e0..a8b2e8f57ac5 100644 --- a/test-utils/client/Cargo.toml +++ b/test-utils/client/Cargo.toml @@ -2,7 +2,7 @@ name = "substrate-test-client" version = "2.0.1" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/test-utils/derive/Cargo.toml b/test-utils/derive/Cargo.toml index 2a1f52346840..f195c0e419ea 100644 --- a/test-utils/derive/Cargo.toml +++ b/test-utils/derive/Cargo.toml @@ -2,7 +2,7 @@ name = "substrate-test-utils-derive" version = "0.10.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/test-utils/runtime/Cargo.toml b/test-utils/runtime/Cargo.toml index eb6ca51ce2e5..f02e07904633 100644 --- a/test-utils/runtime/Cargo.toml +++ b/test-utils/runtime/Cargo.toml @@ -2,7 +2,7 @@ name = "substrate-test-runtime" version = "2.0.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" build = "build.rs" license = "Apache-2.0" homepage = "https://substrate.io" diff --git a/test-utils/runtime/client/Cargo.toml b/test-utils/runtime/client/Cargo.toml index 75ebb8f23326..fbc6aefdb850 100644 --- a/test-utils/runtime/client/Cargo.toml +++ b/test-utils/runtime/client/Cargo.toml @@ -2,7 +2,7 @@ name = "substrate-test-runtime-client" version = "2.0.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/test-utils/runtime/transaction-pool/Cargo.toml b/test-utils/runtime/transaction-pool/Cargo.toml index 5a2983b058b0..402caa93d10d 100644 --- a/test-utils/runtime/transaction-pool/Cargo.toml +++ b/test-utils/runtime/transaction-pool/Cargo.toml @@ -2,7 +2,7 @@ name = "substrate-test-runtime-transaction-pool" version = "2.0.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/test-utils/test-crate/Cargo.toml b/test-utils/test-crate/Cargo.toml index 9c9672fe8f5d..071a82f3c769 100644 --- a/test-utils/test-crate/Cargo.toml +++ b/test-utils/test-crate/Cargo.toml @@ -2,7 +2,7 @@ name = "substrate-test-utils-test-crate" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/test-utils/test-runner/Cargo.toml b/test-utils/test-runner/Cargo.toml index b5b115771b53..9299076bb1f6 100644 --- a/test-utils/test-runner/Cargo.toml +++ b/test-utils/test-runner/Cargo.toml @@ -2,7 +2,7 @@ name = "test-runner" version = "0.9.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" publish = false [dependencies] diff --git a/utils/build-script-utils/Cargo.toml b/utils/build-script-utils/Cargo.toml index 786e6f900291..93611c7b5b01 100644 --- a/utils/build-script-utils/Cargo.toml +++ b/utils/build-script-utils/Cargo.toml @@ -2,7 +2,7 @@ name = "substrate-build-script-utils" version = "3.0.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/utils/fork-tree/Cargo.toml b/utils/fork-tree/Cargo.toml index 81fa1747a84d..cdfce5592f2f 100644 --- a/utils/fork-tree/Cargo.toml +++ b/utils/fork-tree/Cargo.toml @@ -2,7 +2,7 @@ name = "fork-tree" version = "3.0.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/utils/frame/benchmarking-cli/Cargo.toml b/utils/frame/benchmarking-cli/Cargo.toml index ccca30849f91..605a14e3adff 100644 --- a/utils/frame/benchmarking-cli/Cargo.toml +++ b/utils/frame/benchmarking-cli/Cargo.toml @@ -2,7 +2,7 @@ name = "frame-benchmarking-cli" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/utils/frame/frame-utilities-cli/Cargo.toml b/utils/frame/frame-utilities-cli/Cargo.toml index fcdbb215f91b..9d1481933741 100644 --- a/utils/frame/frame-utilities-cli/Cargo.toml +++ b/utils/frame/frame-utilities-cli/Cargo.toml @@ -2,7 +2,7 @@ name = "substrate-frame-cli" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/utils/frame/generate-bags/Cargo.toml b/utils/frame/generate-bags/Cargo.toml index 1bb53207f7d4..03382878710b 100644 --- a/utils/frame/generate-bags/Cargo.toml +++ b/utils/frame/generate-bags/Cargo.toml @@ -2,7 +2,7 @@ name = "generate-bags" version = "3.0.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/utils/frame/generate-bags/node-runtime/Cargo.toml b/utils/frame/generate-bags/node-runtime/Cargo.toml index 68d3cad16de4..5029e049361c 100644 --- a/utils/frame/generate-bags/node-runtime/Cargo.toml +++ b/utils/frame/generate-bags/node-runtime/Cargo.toml @@ -2,7 +2,7 @@ name = "node-runtime-generate-bags" version = "3.0.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/utils/frame/generate-bags/src/lib.rs b/utils/frame/generate-bags/src/lib.rs index af9df4435bca..540412ef04c4 100644 --- a/utils/frame/generate-bags/src/lib.rs +++ b/utils/frame/generate-bags/src/lib.rs @@ -71,7 +71,6 @@ fn existential_weight( minimum_balance: u128, ) -> VoteWeight { use frame_support::traits::CurrencyToVote; - use std::convert::TryInto; T::CurrencyToVote::to_vote( minimum_balance diff --git a/utils/frame/remote-externalities/Cargo.toml b/utils/frame/remote-externalities/Cargo.toml index 2b35402f8f63..3e7c229ec4d6 100644 --- a/utils/frame/remote-externalities/Cargo.toml +++ b/utils/frame/remote-externalities/Cargo.toml @@ -2,7 +2,7 @@ name = "remote-externalities" version = "0.10.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/utils/frame/rpc/support/Cargo.toml b/utils/frame/rpc/support/Cargo.toml index 2010d1e02f73..0d21bdd6c018 100644 --- a/utils/frame/rpc/support/Cargo.toml +++ b/utils/frame/rpc/support/Cargo.toml @@ -5,7 +5,7 @@ authors = [ "Parity Technologies ", "Andrew Dirksen ", ] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/utils/frame/rpc/system/Cargo.toml b/utils/frame/rpc/system/Cargo.toml index 85868836f045..31a46b390210 100644 --- a/utils/frame/rpc/system/Cargo.toml +++ b/utils/frame/rpc/system/Cargo.toml @@ -2,7 +2,7 @@ name = "substrate-frame-rpc-system" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/utils/frame/try-runtime/cli/Cargo.toml b/utils/frame/try-runtime/cli/Cargo.toml index e922af971044..154c522c1dfd 100644 --- a/utils/frame/try-runtime/cli/Cargo.toml +++ b/utils/frame/try-runtime/cli/Cargo.toml @@ -2,7 +2,7 @@ name = "try-runtime-cli" version = "0.10.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/utils/prometheus/Cargo.toml b/utils/prometheus/Cargo.toml index 4d218e233bcb..78bd68ac9e3a 100644 --- a/utils/prometheus/Cargo.toml +++ b/utils/prometheus/Cargo.toml @@ -4,7 +4,7 @@ name = "substrate-prometheus-endpoint" version = "0.9.0" license = "Apache-2.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" readme = "README.md" diff --git a/utils/wasm-builder/Cargo.toml b/utils/wasm-builder/Cargo.toml index 92b1af753ef6..d8802c432f55 100644 --- a/utils/wasm-builder/Cargo.toml +++ b/utils/wasm-builder/Cargo.toml @@ -3,7 +3,7 @@ name = "substrate-wasm-builder" version = "5.0.0-dev" authors = ["Parity Technologies "] description = "Utility for building WASM binaries" -edition = "2018" +edition = "2021" readme = "README.md" repository = "https://github.com/paritytech/substrate/" license = "Apache-2.0" From 3524f6e692d568fae60c26ec8156f3fb585532ec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Nov 2021 19:58:49 +0000 Subject: [PATCH 138/695] Bump strum from 0.21.0 to 0.22.0 (#10045) Bumps [strum](https://github.com/Peternator7/strum) from 0.21.0 to 0.22.0. - [Release notes](https://github.com/Peternator7/strum/releases) - [Changelog](https://github.com/Peternator7/strum/blob/master/CHANGELOG.md) - [Commits](https://github.com/Peternator7/strum/commits) --- updated-dependencies: - dependency-name: strum dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 29 +++++++------------ client/beefy/Cargo.toml | 2 +- .../election-provider-multi-phase/Cargo.toml | 2 +- primitives/keyring/Cargo.toml | 2 +- 4 files changed, 13 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4a50fe356571..ea54adf99e45 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -507,7 +507,7 @@ dependencies = [ "sp-core", "sp-keystore", "sp-runtime", - "strum 0.21.0", + "strum", "substrate-prometheus-endpoint", "thiserror", "wasm-timer", @@ -5450,7 +5450,7 @@ dependencies = [ "sp-std", "sp-tracing", "static_assertions", - "strum 0.21.0", + "strum", "strum_macros 0.21.1", ] @@ -9502,7 +9502,7 @@ dependencies = [ "lazy_static", "sp-core", "sp-runtime", - "strum 0.20.0", + "strum", ] [[package]] @@ -9998,27 +9998,18 @@ dependencies = [ [[package]] name = "strum" -version = "0.20.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7318c509b5ba57f18533982607f24070a55d353e90d4cae30c467cdb2ad5ac5c" +checksum = "f7ac893c7d471c8a21f31cfe213ec4f6d9afeed25537c772e08ef3f005f8729e" dependencies = [ - "strum_macros 0.20.1", -] - -[[package]] -name = "strum" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaf86bbcfd1fa9670b7a129f64fc0c9fcbbfe4f1bc4210e9e98fe71ffc12cde2" -dependencies = [ - "strum_macros 0.21.1", + "strum_macros 0.22.0", ] [[package]] name = "strum_macros" -version = "0.20.1" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee8bc6b87a5112aeeab1f4a9f7ab634fe6cbefc4850006df31267f4cfb9e3149" +checksum = "d06aaeeee809dbc59eb4556183dd927df67db1540de5be8d3ec0b6636358a5ec" dependencies = [ "heck", "proc-macro2", @@ -10028,9 +10019,9 @@ dependencies = [ [[package]] name = "strum_macros" -version = "0.21.1" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d06aaeeee809dbc59eb4556183dd927df67db1540de5be8d3ec0b6636358a5ec" +checksum = "339f799d8b549e3744c7ac7feb216383e4005d94bdb22561b3ab8f3b808ae9fb" dependencies = [ "heck", "proc-macro2", diff --git a/client/beefy/Cargo.toml b/client/beefy/Cargo.toml index 37dc4491e21d..60f9fde03080 100644 --- a/client/beefy/Cargo.toml +++ b/client/beefy/Cargo.toml @@ -35,4 +35,4 @@ beefy-primitives = { version = "4.0.0-dev", path = "../../primitives/beefy" } [dev-dependencies] sc-network-test = { version = "0.8.0", path = "../network/test" } -strum = { version = "0.21", features = ["derive"] } +strum = { version = "0.22", features = ["derive"] } diff --git a/frame/election-provider-multi-phase/Cargo.toml b/frame/election-provider-multi-phase/Cargo.toml index 8a0f80da1082..63111f89e5d3 100644 --- a/frame/election-provider-multi-phase/Cargo.toml +++ b/frame/election-provider-multi-phase/Cargo.toml @@ -37,7 +37,7 @@ rand = { version = "0.7.3", default-features = false, optional = true, features "alloc", "small_rng", ] } -strum = { optional = true, version = "0.21.0" } +strum = { optional = true, version = "0.22.0" } strum_macros = { optional = true, version = "0.21.1" } [dev-dependencies] diff --git a/primitives/keyring/Cargo.toml b/primitives/keyring/Cargo.toml index 3b5d916b47b6..249e7d766e39 100644 --- a/primitives/keyring/Cargo.toml +++ b/primitives/keyring/Cargo.toml @@ -18,4 +18,4 @@ targets = ["x86_64-unknown-linux-gnu"] sp-core = { version = "4.0.0-dev", path = "../core" } sp-runtime = { version = "4.0.0-dev", path = "../runtime" } lazy_static = "1.4.0" -strum = { version = "0.20.0", features = ["derive"] } +strum = { version = "0.22.0", features = ["derive"] } From 5ba810c93203487ac58cffc6e0d34cdda18e362c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Nov 2021 11:11:28 +0000 Subject: [PATCH 139/695] Bump wasmi from 0.9.0 to 0.9.1 (#10116) Bumps [wasmi](https://github.com/paritytech/wasmi) from 0.9.0 to 0.9.1. - [Release notes](https://github.com/paritytech/wasmi/releases) - [Commits](https://github.com/paritytech/wasmi/compare/v0.9.0...v0.9.1) --- updated-dependencies: - dependency-name: wasmi dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- client/executor/Cargo.toml | 2 +- client/executor/common/Cargo.toml | 2 +- client/executor/wasmi/Cargo.toml | 2 +- primitives/core/Cargo.toml | 2 +- primitives/sandbox/Cargo.toml | 2 +- primitives/wasm-interface/Cargo.toml | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) mode change 100755 => 100644 primitives/sandbox/Cargo.toml diff --git a/Cargo.lock b/Cargo.lock index ea54adf99e45..2257fa0a5b00 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11498,9 +11498,9 @@ dependencies = [ [[package]] name = "wasmi" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2ee05bba3d1d994652079893941a2ef9324d2b58a63c31b40678fb7eddd7a5a" +checksum = "ca00c5147c319a8ec91ec1a0edbec31e566ce2c9cc93b3f9bb86a9efd0eb795d" dependencies = [ "downcast-rs", "errno", diff --git a/client/executor/Cargo.toml b/client/executor/Cargo.toml index 028854992a09..ef66d8072b53 100644 --- a/client/executor/Cargo.toml +++ b/client/executor/Cargo.toml @@ -21,7 +21,7 @@ sp-tasks = { version = "4.0.0-dev", path = "../../primitives/tasks" } sp-trie = { version = "4.0.0-dev", path = "../../primitives/trie" } sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } sp-panic-handler = { version = "3.0.0", path = "../../primitives/panic-handler" } -wasmi = "0.9.0" +wasmi = "0.9.1" lazy_static = "1.4.0" sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } sp-wasm-interface = { version = "4.0.0-dev", path = "../../primitives/wasm-interface" } diff --git a/client/executor/common/Cargo.toml b/client/executor/common/Cargo.toml index fc7d5a152847..7ac747bf967b 100644 --- a/client/executor/common/Cargo.toml +++ b/client/executor/common/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] derive_more = "0.99.2" pwasm-utils = "0.18.0" codec = { package = "parity-scale-codec", version = "2.0.0" } -wasmi = "0.9.0" +wasmi = "0.9.1" sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" } sc-allocator = { version = "4.0.0-dev", path = "../../allocator" } sp-wasm-interface = { version = "4.0.0-dev", path = "../../../primitives/wasm-interface" } diff --git a/client/executor/wasmi/Cargo.toml b/client/executor/wasmi/Cargo.toml index 6311b0234866..255a470b374d 100644 --- a/client/executor/wasmi/Cargo.toml +++ b/client/executor/wasmi/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] log = "0.4.8" -wasmi = "0.9.0" +wasmi = "0.9.1" codec = { package = "parity-scale-codec", version = "2.0.0" } sc-executor-common = { version = "0.10.0-dev", path = "../common" } sc-allocator = { version = "4.0.0-dev", path = "../../allocator" } diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index 63ca358e6810..8262393e653f 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -27,7 +27,7 @@ primitive-types = { version = "0.10.1", default-features = false, features = [ "scale-info" ] } impl-serde = { version = "0.3.0", optional = true } -wasmi = { version = "0.9.0", optional = true } +wasmi = { version = "0.9.1", optional = true } hash-db = { version = "0.15.2", default-features = false } hash256-std-hasher = { version = "0.15.2", default-features = false } base58 = { version = "0.2.0", optional = true } diff --git a/primitives/sandbox/Cargo.toml b/primitives/sandbox/Cargo.toml old mode 100755 new mode 100644 index b1ee431042e7..8e7acff4ff7e --- a/primitives/sandbox/Cargo.toml +++ b/primitives/sandbox/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [target.'cfg(target_arch = "wasm32")'.dependencies] -wasmi = { version = "0.9.0", default-features = false, features = ["core"] } +wasmi = { version = "0.9.1", default-features = false, features = ["core"] } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] wasmi = "0.9.0" diff --git a/primitives/wasm-interface/Cargo.toml b/primitives/wasm-interface/Cargo.toml index 339c4cf8bc8b..c378b185e392 100644 --- a/primitives/wasm-interface/Cargo.toml +++ b/primitives/wasm-interface/Cargo.toml @@ -14,7 +14,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -wasmi = { version = "0.9.0", optional = true } +wasmi = { version = "0.9.1", optional = true } impl-trait-for-tuples = "0.2.1" sp-std = { version = "4.0.0-dev", path = "../std", default-features = false } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } From 6873fc69e2140f554b75242b7e66a5d6a846e772 Mon Sep 17 00:00:00 2001 From: Florian Franzen Date: Fri, 5 Nov 2021 12:26:49 +0100 Subject: [PATCH 140/695] Remove old Cargo.toml (#10188) --- client/finality-grandpa-warp-sync/Cargo.toml | 35 -------------------- 1 file changed, 35 deletions(-) delete mode 100644 client/finality-grandpa-warp-sync/Cargo.toml diff --git a/client/finality-grandpa-warp-sync/Cargo.toml b/client/finality-grandpa-warp-sync/Cargo.toml deleted file mode 100644 index 6280add27562..000000000000 --- a/client/finality-grandpa-warp-sync/Cargo.toml +++ /dev/null @@ -1,35 +0,0 @@ -[package] -description = "A request-response protocol for handling grandpa warp sync requests" -name = "sc-finality-grandpa-warp-sync" -version = "0.10.0-dev" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -authors = ["Parity Technologies "] -edition = "2021" -homepage = "https://substrate.io" -repository = "https://github.com/paritytech/substrate/" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0" } -derive_more = "0.99.11" -futures = "0.3.8" -log = "0.4.11" -prost = "0.8" -sc-client-api = { version = "4.0.0-dev", path = "../api" } -sc-finality-grandpa = { version = "0.10.0-dev", path = "../finality-grandpa" } -sc-network = { version = "0.10.0-dev", path = "../network" } -sc-service = { version = "0.10.0-dev", path = "../service" } -sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } -sp-finality-grandpa = { version = "4.0.0-dev", path = "../../primitives/finality-grandpa" } -sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } - -[dev-dependencies] -finality-grandpa = { version = "0.14.4" } -rand = "0.8" -sc-block-builder = { version = "0.10.0-dev", path = "../block-builder" } -sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } -sc-consensus = { version = "0.10.0-dev", path = "../../client/consensus/common" } -sp-keyring = { version = "4.0.0-dev", path = "../../primitives/keyring" } -substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } From 8439a0bba4aeb69669510061e6aeeb106da9d651 Mon Sep 17 00:00:00 2001 From: Koute Date: Fri, 5 Nov 2021 21:52:34 +0900 Subject: [PATCH 141/695] Remove unnecessary allocations when crossing WASM FFI boundary (#10191) --- primitives/runtime-interface/src/impls.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/primitives/runtime-interface/src/impls.rs b/primitives/runtime-interface/src/impls.rs index 40f8e90479f9..0b9cdc26f465 100644 --- a/primitives/runtime-interface/src/impls.rs +++ b/primitives/runtime-interface/src/impls.rs @@ -318,9 +318,8 @@ macro_rules! impl_traits_for_arrays { type SelfInstance = [u8; $n]; fn from_ffi_value(context: &mut dyn FunctionContext, arg: u32) -> Result<[u8; $n]> { - let data = context.read_memory(Pointer::new(arg), $n)?; let mut res = [0u8; $n]; - res.copy_from_slice(&data); + context.read_memory_into(Pointer::new(arg), &mut res)?; Ok(res) } } @@ -514,10 +513,8 @@ macro_rules! for_u128_i128 { type SelfInstance = $type; fn from_ffi_value(context: &mut dyn FunctionContext, arg: u32) -> Result<$type> { - let data = - context.read_memory(Pointer::new(arg), mem::size_of::<$type>() as u32)?; let mut res = [0u8; mem::size_of::<$type>()]; - res.copy_from_slice(&data); + context.read_memory_into(Pointer::new(arg), &mut res)?; Ok(<$type>::from_le_bytes(res)) } } From 7b8f8efde025c6ac8daed492d4d96dea3c563334 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Nov 2021 15:51:54 +0100 Subject: [PATCH 142/695] Bump syn from 1.0.80 to 1.0.81 (#10182) Bumps [syn](https://github.com/dtolnay/syn) from 1.0.80 to 1.0.81. - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/1.0.80...1.0.81) --- updated-dependencies: - dependency-name: syn dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- client/chain-spec/derive/Cargo.toml | 2 +- client/tracing/proc-macro/Cargo.toml | 2 +- frame/staking/reward-curve/Cargo.toml | 2 +- frame/support/procedural/Cargo.toml | 2 +- frame/support/procedural/tools/Cargo.toml | 2 +- frame/support/procedural/tools/derive/Cargo.toml | 2 +- primitives/api/proc-macro/Cargo.toml | 2 +- primitives/core/hashing/proc-macro/Cargo.toml | 2 +- primitives/debug-derive/Cargo.toml | 2 +- primitives/npos-elections/solution-type/Cargo.toml | 2 +- primitives/runtime-interface/proc-macro/Cargo.toml | 2 +- primitives/version/proc-macro/Cargo.toml | 2 +- test-utils/derive/Cargo.toml | 2 +- 14 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2257fa0a5b00..8d168230b528 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6780,9 +6780,9 @@ checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" [[package]] name = "proc-macro2" -version = "1.0.29" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f5105d4fdaab20335ca9565e106a5d9b82b6219b5ba735731124ac6711d23d" +checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43" dependencies = [ "unicode-xid", ] @@ -10286,9 +10286,9 @@ checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2" [[package]] name = "syn" -version = "1.0.80" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d010a1623fbd906d51d650a9916aaefc05ffa0e4053ff7fe601167f3e715d194" +checksum = "f2afee18b8beb5a596ecb4a2dce128c719b4ba399d34126b9e4396e3f9860966" dependencies = [ "proc-macro2", "quote", diff --git a/client/chain-spec/derive/Cargo.toml b/client/chain-spec/derive/Cargo.toml index 386137d0667a..25339eea14f1 100644 --- a/client/chain-spec/derive/Cargo.toml +++ b/client/chain-spec/derive/Cargo.toml @@ -18,6 +18,6 @@ proc-macro = true proc-macro-crate = "1.0.0" proc-macro2 = "1.0.29" quote = "1.0.10" -syn = "1.0.80" +syn = "1.0.81" [dev-dependencies] diff --git a/client/tracing/proc-macro/Cargo.toml b/client/tracing/proc-macro/Cargo.toml index 9c8579ee66a4..c51c8764e677 100644 --- a/client/tracing/proc-macro/Cargo.toml +++ b/client/tracing/proc-macro/Cargo.toml @@ -18,4 +18,4 @@ proc-macro = true proc-macro-crate = "1.0.0" proc-macro2 = "1.0.29" quote = { version = "1.0.10", features = ["proc-macro"] } -syn = { version = "1.0.80", features = ["proc-macro", "full", "extra-traits", "parsing"] } +syn = { version = "1.0.81", features = ["proc-macro", "full", "extra-traits", "parsing"] } diff --git a/frame/staking/reward-curve/Cargo.toml b/frame/staking/reward-curve/Cargo.toml index 15ff3a872730..1250bbcd3905 100644 --- a/frame/staking/reward-curve/Cargo.toml +++ b/frame/staking/reward-curve/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] proc-macro = true [dependencies] -syn = { version = "1.0.80", features = ["full", "visit"] } +syn = { version = "1.0.81", features = ["full", "visit"] } quote = "1.0.10" proc-macro2 = "1.0.29" proc-macro-crate = "1.0.0" diff --git a/frame/support/procedural/Cargo.toml b/frame/support/procedural/Cargo.toml index 17128388874a..b47cf7f97956 100644 --- a/frame/support/procedural/Cargo.toml +++ b/frame/support/procedural/Cargo.toml @@ -19,7 +19,7 @@ frame-support-procedural-tools = { version = "4.0.0-dev", path = "./tools" } proc-macro2 = "1.0.29" quote = "1.0.10" Inflector = "0.11.4" -syn = { version = "1.0.80", features = ["full"] } +syn = { version = "1.0.81", features = ["full"] } [features] default = ["std"] diff --git a/frame/support/procedural/tools/Cargo.toml b/frame/support/procedural/tools/Cargo.toml index 1207d06e6d59..7b957be18401 100644 --- a/frame/support/procedural/tools/Cargo.toml +++ b/frame/support/procedural/tools/Cargo.toml @@ -15,5 +15,5 @@ targets = ["x86_64-unknown-linux-gnu"] frame-support-procedural-tools-derive = { version = "3.0.0", path = "./derive" } proc-macro2 = "1.0.29" quote = "1.0.10" -syn = { version = "1.0.80", features = ["full", "visit", "extra-traits"] } +syn = { version = "1.0.81", features = ["full", "visit", "extra-traits"] } proc-macro-crate = "1.0.0" diff --git a/frame/support/procedural/tools/derive/Cargo.toml b/frame/support/procedural/tools/derive/Cargo.toml index f0c27b5397d5..8327134b3fb4 100644 --- a/frame/support/procedural/tools/derive/Cargo.toml +++ b/frame/support/procedural/tools/derive/Cargo.toml @@ -17,4 +17,4 @@ proc-macro = true [dependencies] proc-macro2 = "1.0.29" quote = { version = "1.0.10", features = ["proc-macro"] } -syn = { version = "1.0.80", features = ["proc-macro" ,"full", "extra-traits", "parsing"] } +syn = { version = "1.0.81", features = ["proc-macro" ,"full", "extra-traits", "parsing"] } diff --git a/primitives/api/proc-macro/Cargo.toml b/primitives/api/proc-macro/Cargo.toml index 7b0b55c8c3b5..a5df7aef322a 100644 --- a/primitives/api/proc-macro/Cargo.toml +++ b/primitives/api/proc-macro/Cargo.toml @@ -17,7 +17,7 @@ proc-macro = true [dependencies] quote = "1.0.10" -syn = { version = "1.0.80", features = ["full", "fold", "extra-traits", "visit"] } +syn = { version = "1.0.81", features = ["full", "fold", "extra-traits", "visit"] } proc-macro2 = "1.0.29" blake2-rfc = { version = "0.2.18", default-features = false } proc-macro-crate = "1.0.0" diff --git a/primitives/core/hashing/proc-macro/Cargo.toml b/primitives/core/hashing/proc-macro/Cargo.toml index 452165b31cb9..89b225e6aaa5 100644 --- a/primitives/core/hashing/proc-macro/Cargo.toml +++ b/primitives/core/hashing/proc-macro/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] proc-macro = true [dependencies] -syn = { version = "1.0.77", features = ["full", "parsing"] } +syn = { version = "1.0.81", features = ["full", "parsing"] } quote = "1.0.6" proc-macro2 = "1.0.29" sp-core-hashing = { version = "4.0.0-dev", path = "../", default-features = false } diff --git a/primitives/debug-derive/Cargo.toml b/primitives/debug-derive/Cargo.toml index d1f1f81a9f14..a2f77b7591fe 100644 --- a/primitives/debug-derive/Cargo.toml +++ b/primitives/debug-derive/Cargo.toml @@ -18,7 +18,7 @@ proc-macro = true [dependencies] quote = "1.0.10" -syn = "1.0.80" +syn = "1.0.81" proc-macro2 = "1.0" [features] diff --git a/primitives/npos-elections/solution-type/Cargo.toml b/primitives/npos-elections/solution-type/Cargo.toml index f50150bdbd58..5d8d3890577a 100644 --- a/primitives/npos-elections/solution-type/Cargo.toml +++ b/primitives/npos-elections/solution-type/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] proc-macro = true [dependencies] -syn = { version = "1.0.80", features = ["full", "visit"] } +syn = { version = "1.0.81", features = ["full", "visit"] } quote = "1.0" proc-macro2 = "1.0.29" proc-macro-crate = "1.0.0" diff --git a/primitives/runtime-interface/proc-macro/Cargo.toml b/primitives/runtime-interface/proc-macro/Cargo.toml index 958a95ceb3fc..cc5daa695bb0 100644 --- a/primitives/runtime-interface/proc-macro/Cargo.toml +++ b/primitives/runtime-interface/proc-macro/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] proc-macro = true [dependencies] -syn = { version = "1.0.80", features = ["full", "visit", "fold", "extra-traits"] } +syn = { version = "1.0.81", features = ["full", "visit", "fold", "extra-traits"] } quote = "1.0.10" proc-macro2 = "1.0.29" Inflector = "0.11.4" diff --git a/primitives/version/proc-macro/Cargo.toml b/primitives/version/proc-macro/Cargo.toml index bf6e0bdec7a6..79fb9b18a238 100644 --- a/primitives/version/proc-macro/Cargo.toml +++ b/primitives/version/proc-macro/Cargo.toml @@ -17,7 +17,7 @@ proc-macro = true [dependencies] quote = "1.0.10" -syn = { version = "1.0.80", features = ["full", "fold", "extra-traits", "visit"] } +syn = { version = "1.0.81", features = ["full", "fold", "extra-traits", "visit"] } proc-macro2 = "1.0.29" codec = { package = "parity-scale-codec", version = "2.0.0", features = [ "derive" ] } diff --git a/test-utils/derive/Cargo.toml b/test-utils/derive/Cargo.toml index f195c0e419ea..967fc1e87a36 100644 --- a/test-utils/derive/Cargo.toml +++ b/test-utils/derive/Cargo.toml @@ -10,7 +10,7 @@ description = "Substrate test utilities macros" [dependencies] quote = "1.0.10" -syn = { version = "1.0.80", features = ["full"] } +syn = { version = "1.0.81", features = ["full"] } proc-macro-crate = "1.0.0" proc-macro2 = "1.0.29" From abca10f32a1844d4d05884c92ea2e08b17c6b8c3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 6 Nov 2021 05:48:41 +0000 Subject: [PATCH 143/695] Bump strum_macros from 0.21.1 to 0.22.0 (#10200) Bumps [strum_macros](https://github.com/Peternator7/strum) from 0.21.1 to 0.22.0. - [Release notes](https://github.com/Peternator7/strum/releases) - [Changelog](https://github.com/Peternator7/strum/blob/master/CHANGELOG.md) - [Commits](https://github.com/Peternator7/strum/commits) --- updated-dependencies: - dependency-name: strum_macros dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 16 ++-------------- frame/election-provider-multi-phase/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8d168230b528..eeb1012b1d1d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5451,7 +5451,7 @@ dependencies = [ "sp-tracing", "static_assertions", "strum", - "strum_macros 0.21.1", + "strum_macros", ] [[package]] @@ -10002,19 +10002,7 @@ version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7ac893c7d471c8a21f31cfe213ec4f6d9afeed25537c772e08ef3f005f8729e" dependencies = [ - "strum_macros 0.22.0", -] - -[[package]] -name = "strum_macros" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d06aaeeee809dbc59eb4556183dd927df67db1540de5be8d3ec0b6636358a5ec" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn", + "strum_macros", ] [[package]] diff --git a/frame/election-provider-multi-phase/Cargo.toml b/frame/election-provider-multi-phase/Cargo.toml index 63111f89e5d3..b37054a7bbdd 100644 --- a/frame/election-provider-multi-phase/Cargo.toml +++ b/frame/election-provider-multi-phase/Cargo.toml @@ -38,7 +38,7 @@ rand = { version = "0.7.3", default-features = false, optional = true, features "small_rng", ] } strum = { optional = true, version = "0.22.0" } -strum_macros = { optional = true, version = "0.21.1" } +strum_macros = { optional = true, version = "0.22.0" } [dev-dependencies] parking_lot = "0.11.0" From 0397c5bd745574c587ea853ae9472e8dd0a2d9fe Mon Sep 17 00:00:00 2001 From: Alan Sapede Date: Sat, 6 Nov 2021 12:49:53 -0400 Subject: [PATCH 144/695] Adds block production time in logs (#10205) --- client/basic-authorship/src/basic_authorship.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/basic-authorship/src/basic_authorship.rs b/client/basic-authorship/src/basic_authorship.rs index 0055254b6709..573601a9102c 100644 --- a/client/basic-authorship/src/basic_authorship.rs +++ b/client/basic-authorship/src/basic_authorship.rs @@ -462,8 +462,9 @@ where }); info!( - "🎁 Prepared block for proposing at {} [hash: {:?}; parent_hash: {}; extrinsics ({}): [{}]]", + "🎁 Prepared block for proposing at {} ({} ms) [hash: {:?}; parent_hash: {}; extrinsics ({}): [{}]]", block.header().number(), + block_timer.elapsed().as_millis(), ::Hash::from(block.header().hash()), block.header().parent_hash(), block.extrinsics().len(), From 702fd839917f7b197770917ae5a64df0fc9593eb Mon Sep 17 00:00:00 2001 From: cheme Date: Sun, 7 Nov 2021 14:13:02 +0100 Subject: [PATCH 145/695] Fast sync child trie support. (#9239) * state machine proofs. * initial implementation * Remove todo. * Extend test and fix import. * fix no proof, with proof ko. * fix start at logic. * Restore response size. * Rework comments. * Add explicit ref * Use compact proof. * ref change * elaborato on empty change set condition. * KeyValueState renaming. * Do not add two time child trie with same root to sync reply. * rust format * Fix merge. * fix warnings and fmt * fmt * update protocol id to V2 --- client/api/src/backend.rs | 2 +- client/api/src/lib.rs | 2 +- client/api/src/proof_provider.rs | 37 +- client/consensus/common/src/block_import.rs | 2 +- client/network/src/protocol/sync/state.rs | 158 +++++-- client/network/src/schema/api.v1.proto | 20 +- client/network/src/state_request_handler.rs | 49 +- client/network/test/src/lib.rs | 7 + client/network/test/src/sync.rs | 43 +- client/service/src/client/client.rs | 216 +++++++-- primitives/state-machine/src/lib.rs | 448 ++++++++++++++++++- primitives/state-machine/src/trie_backend.rs | 6 +- test-utils/runtime/client/src/lib.rs | 5 + 13 files changed, 855 insertions(+), 140 deletions(-) diff --git a/client/api/src/backend.rs b/client/api/src/backend.rs index 8b5bd50ffa61..9dfe82a57ab3 100644 --- a/client/api/src/backend.rs +++ b/client/api/src/backend.rs @@ -42,7 +42,7 @@ use std::{ sync::Arc, }; -pub use sp_state_machine::Backend as StateBackend; +pub use sp_state_machine::{Backend as StateBackend, KeyValueStates}; use std::marker::PhantomData; /// Extracts the state backend type for the given backend. diff --git a/client/api/src/lib.rs b/client/api/src/lib.rs index 16935b1e846c..f1c78f6603eb 100644 --- a/client/api/src/lib.rs +++ b/client/api/src/lib.rs @@ -39,7 +39,7 @@ pub use proof_provider::*; pub use sp_blockchain as blockchain; pub use sp_blockchain::HeaderBackend; -pub use sp_state_machine::{ExecutionStrategy, StorageProof}; +pub use sp_state_machine::{CompactProof, ExecutionStrategy, StorageProof}; pub use sp_storage::{ChildInfo, PrefixedStorageKey, StorageData, StorageKey}; /// Usage Information Provider interface diff --git a/client/api/src/proof_provider.rs b/client/api/src/proof_provider.rs index 79444f006923..75f9c55e134d 100644 --- a/client/api/src/proof_provider.rs +++ b/client/api/src/proof_provider.rs @@ -17,8 +17,9 @@ // along with this program. If not, see . //! Proof utilities -use crate::{ChangesProof, StorageProof}; +use crate::{ChangesProof, CompactProof, StorageProof}; use sp_runtime::{generic::BlockId, traits::Block as BlockT}; +use sp_state_machine::{KeyValueStates, KeyValueStorageLevel}; use sp_storage::{ChildInfo, PrefixedStorageKey, StorageKey}; /// Interface for providing block proving utilities. @@ -71,31 +72,43 @@ pub trait ProofProvider { key: &StorageKey, ) -> sp_blockchain::Result>; - /// Given a `BlockId` iterate over all storage values starting at `start_key` exclusively, - /// building proofs until size limit is reached. Returns combined proof and the number of - /// collected keys. + /// Given a `BlockId` iterate over all storage values starting at `start_keys`. + /// Last `start_keys` element contains last accessed key value. + /// With multiple `start_keys`, first `start_keys` element is + /// the current storage key of of the last accessed child trie. + /// at last level the value to start at exclusively. + /// Proofs is build until size limit is reached and always include at + /// least one key following `start_keys`. + /// Returns combined proof and the numbers of collected keys. fn read_proof_collection( &self, id: &BlockId, - start_key: &[u8], + start_keys: &[Vec], size_limit: usize, - ) -> sp_blockchain::Result<(StorageProof, u32)>; + ) -> sp_blockchain::Result<(CompactProof, u32)>; /// Given a `BlockId` iterate over all storage values starting at `start_key`. /// Returns collected keys and values. + /// Returns the collected keys values content of the top trie followed by the + /// collected keys values of child tries. + /// Only child tries with their root part of the collected content or + /// related to `start_key` are attached. + /// For each collected state a boolean indicates if state reach + /// end. fn storage_collection( &self, id: &BlockId, - start_key: &[u8], + start_key: &[Vec], size_limit: usize, - ) -> sp_blockchain::Result, Vec)>>; + ) -> sp_blockchain::Result>; /// Verify read storage proof for a set of keys. - /// Returns collected key-value pairs and a flag indicating if iteration is complete. + /// Returns collected key-value pairs and a the nested state + /// depth of current iteration or 0 if completed. fn verify_range_proof( &self, root: Block::Hash, - proof: StorageProof, - start_key: &[u8], - ) -> sp_blockchain::Result<(Vec<(Vec, Vec)>, bool)>; + proof: CompactProof, + start_keys: &[Vec], + ) -> sp_blockchain::Result<(KeyValueStates, usize)>; } diff --git a/client/consensus/common/src/block_import.rs b/client/consensus/common/src/block_import.rs index d828e54bc7e3..5294db239604 100644 --- a/client/consensus/common/src/block_import.rs +++ b/client/consensus/common/src/block_import.rs @@ -133,7 +133,7 @@ pub struct ImportedState { /// Target block hash. pub block: B::Hash, /// State keys and values. - pub state: Vec<(Vec, Vec)>, + pub state: sp_state_machine::KeyValueStates, } impl std::fmt::Debug for ImportedState { diff --git a/client/network/src/protocol/sync/state.rs b/client/network/src/protocol/sync/state.rs index e644ba1013e4..43aa1c4629f0 100644 --- a/client/network/src/protocol/sync/state.rs +++ b/client/network/src/protocol/sync/state.rs @@ -23,9 +23,11 @@ use crate::{ }; use codec::{Decode, Encode}; use log::debug; -use sc_client_api::StorageProof; +use sc_client_api::CompactProof; +use smallvec::SmallVec; +use sp_core::storage::well_known_keys; use sp_runtime::traits::{Block as BlockT, Header, NumberFor}; -use std::sync::Arc; +use std::{collections::HashMap, sync::Arc}; /// State sync support. @@ -35,8 +37,8 @@ pub struct StateSync { target_block: B::Hash, target_header: B::Header, target_root: B::Hash, - last_key: Vec, - state: Vec<(Vec, Vec)>, + last_key: SmallVec<[Vec; 2]>, + state: HashMap, (Vec<(Vec, Vec)>, Vec>)>, complete: bool, client: Arc>, imported_bytes: u64, @@ -61,8 +63,8 @@ impl StateSync { target_block: target.hash(), target_root: target.state_root().clone(), target_header: target, - last_key: Vec::default(), - state: Vec::default(), + last_key: SmallVec::default(), + state: HashMap::default(), complete: false, imported_bytes: 0, skip_proof, @@ -71,7 +73,7 @@ impl StateSync { /// Validate and import a state reponse. pub fn import(&mut self, response: StateResponse) -> ImportResult { - if response.entries.is_empty() && response.proof.is_empty() && !response.complete { + if response.entries.is_empty() && response.proof.is_empty() { debug!(target: "sync", "Bad state response"); return ImportResult::BadResponse } @@ -82,56 +84,135 @@ impl StateSync { let complete = if !self.skip_proof { debug!(target: "sync", "Importing state from {} trie nodes", response.proof.len()); let proof_size = response.proof.len() as u64; - let proof = match StorageProof::decode(&mut response.proof.as_ref()) { + let proof = match CompactProof::decode(&mut response.proof.as_ref()) { Ok(proof) => proof, Err(e) => { debug!(target: "sync", "Error decoding proof: {:?}", e); return ImportResult::BadResponse }, }; - let (values, complete) = - match self.client.verify_range_proof(self.target_root, proof, &self.last_key) { - Err(e) => { - debug!(target: "sync", "StateResponse failed proof verification: {:?}", e); - return ImportResult::BadResponse - }, - Ok(values) => values, - }; + let (values, completed) = match self.client.verify_range_proof( + self.target_root, + proof, + self.last_key.as_slice(), + ) { + Err(e) => { + debug!( + target: "sync", + "StateResponse failed proof verification: {:?}", + e, + ); + return ImportResult::BadResponse + }, + Ok(values) => values, + }; debug!(target: "sync", "Imported with {} keys", values.len()); - if let Some(last) = values.last().map(|(k, _)| k) { - self.last_key = last.clone(); - } + let complete = completed == 0; + if !complete && !values.update_last_key(completed, &mut self.last_key) { + debug!(target: "sync", "Error updating key cursor, depth: {}", completed); + }; - for (key, value) in values { - self.imported_bytes += key.len() as u64; - self.state.push((key, value)) + for values in values.0 { + let key_values = if values.state_root.is_empty() { + // Read child trie roots. + values + .key_values + .into_iter() + .filter(|key_value| { + if well_known_keys::is_child_storage_key(key_value.0.as_slice()) { + self.state + .entry(key_value.1.clone()) + .or_default() + .1 + .push(key_value.0.clone()); + false + } else { + true + } + }) + .collect() + } else { + values.key_values + }; + let mut entry = self.state.entry(values.state_root).or_default(); + if entry.0.len() > 0 && entry.1.len() > 1 { + // Already imported child_trie with same root. + // Warning this will not work with parallel download. + } else { + if entry.0.is_empty() { + for (key, _value) in key_values.iter() { + self.imported_bytes += key.len() as u64; + } + + entry.0 = key_values; + } else { + for (key, value) in key_values { + self.imported_bytes += key.len() as u64; + entry.0.push((key, value)) + } + } + } } self.imported_bytes += proof_size; complete } else { - debug!( - target: "sync", - "Importing state from {:?} to {:?}", - response.entries.last().map(|e| sp_core::hexdisplay::HexDisplay::from(&e.key)), - response.entries.first().map(|e| sp_core::hexdisplay::HexDisplay::from(&e.key)), - ); - - if let Some(e) = response.entries.last() { - self.last_key = e.key.clone(); + let mut complete = true; + // if the trie is a child trie and one of its parent trie is empty, + // the parent cursor stays valid. + // Empty parent trie content only happens when all the response content + // is part of a single child trie. + if self.last_key.len() == 2 && response.entries[0].entries.len() == 0 { + // Do not remove the parent trie position. + self.last_key.pop(); + } else { + self.last_key.clear(); } - for StateEntry { key, value } in response.entries { - self.imported_bytes += (key.len() + value.len()) as u64; - self.state.push((key, value)) + for state in response.entries { + debug!( + target: "sync", + "Importing state from {:?} to {:?}", + state.entries.last().map(|e| sp_core::hexdisplay::HexDisplay::from(&e.key)), + state.entries.first().map(|e| sp_core::hexdisplay::HexDisplay::from(&e.key)), + ); + + if !state.complete { + if let Some(e) = state.entries.last() { + self.last_key.push(e.key.clone()); + } + complete = false; + } + let is_top = state.state_root.is_empty(); + let entry = self.state.entry(state.state_root).or_default(); + if entry.0.len() > 0 && entry.1.len() > 1 { + // Already imported child trie with same root. + } else { + let mut child_roots = Vec::new(); + for StateEntry { key, value } in state.entries { + // Skip all child key root (will be recalculated on import). + if is_top && well_known_keys::is_child_storage_key(key.as_slice()) { + child_roots.push((value, key)); + } else { + self.imported_bytes += key.len() as u64; + entry.0.push((key, value)) + } + } + for (root, storage_key) in child_roots { + self.state.entry(root).or_default().1.push(storage_key); + } + } } - response.complete + complete }; if complete { self.complete = true; ImportResult::Import( self.target_block, self.target_header.clone(), - ImportedState { block: self.target_block, state: std::mem::take(&mut self.state) }, + ImportedState { + block: self.target_block.clone(), + state: std::mem::take(&mut self.state).into(), + }, ) } else { ImportResult::Continue @@ -142,7 +223,7 @@ impl StateSync { pub fn next_request(&self) -> StateRequest { StateRequest { block: self.target_block.encode(), - start: self.last_key.clone(), + start: self.last_key.clone().into_vec(), no_proof: self.skip_proof, } } @@ -164,7 +245,8 @@ impl StateSync { /// Returns state sync estimated progress. pub fn progress(&self) -> StateDownloadProgress { - let percent_done = (*self.last_key.get(0).unwrap_or(&0u8) as u32) * 100 / 256; + let cursor = *self.last_key.get(0).and_then(|last| last.get(0)).unwrap_or(&0u8); + let percent_done = cursor as u32 * 100 / 256; StateDownloadProgress { percentage: percent_done, size: self.imported_bytes } } } diff --git a/client/network/src/schema/api.v1.proto b/client/network/src/schema/api.v1.proto index c5333c7dcdbf..b51137d1d51d 100644 --- a/client/network/src/schema/api.v1.proto +++ b/client/network/src/schema/api.v1.proto @@ -74,22 +74,32 @@ message BlockData { message StateRequest { // Block header hash. bytes block = 1; - // Start from this key. Equivalent to if omitted. - bytes start = 2; // optional + // Start from this key. + // Multiple keys used for nested state start. + repeated bytes start = 2; // optional // if 'true' indicates that response should contain raw key-values, rather than proof. bool no_proof = 3; } message StateResponse { - // A collection of keys-values. Only populated if `no_proof` is `true` - repeated StateEntry entries = 1; + // A collection of keys-values states. Only populated if `no_proof` is `true` + repeated KeyValueStateEntry entries = 1; // If `no_proof` is false in request, this contains proof nodes. bytes proof = 2; +} + +// A key value state. +message KeyValueStateEntry { + // Root of for this level, empty length bytes + // if top level. + bytes state_root = 1; + // A collection of keys-values. + repeated StateEntry entries = 2; // Set to true when there are no more keys to return. bool complete = 3; } -// A key-value pair +// A key-value pair. message StateEntry { bytes key = 1; bytes value = 2; diff --git a/client/network/src/state_request_handler.rs b/client/network/src/state_request_handler.rs index d2e58ce95519..0d710c13af60 100644 --- a/client/network/src/state_request_handler.rs +++ b/client/network/src/state_request_handler.rs @@ -21,7 +21,7 @@ use crate::{ chain::Client, config::ProtocolId, request_responses::{IncomingRequest, OutgoingResponse, ProtocolConfig}, - schema::v1::{StateEntry, StateRequest, StateResponse}, + schema::v1::{KeyValueStateEntry, StateEntry, StateRequest, StateResponse}, PeerId, ReputationChange, }; use codec::{Decode, Encode}; @@ -66,7 +66,7 @@ fn generate_protocol_name(protocol_id: &ProtocolId) -> String { let mut s = String::new(); s.push_str("/"); s.push_str(protocol_id.as_ref()); - s.push_str("/state/1"); + s.push_str("/state/2"); s } @@ -75,7 +75,7 @@ fn generate_protocol_name(protocol_id: &ProtocolId) -> String { struct SeenRequestsKey { peer: PeerId, block: B::Hash, - start: Vec, + start: Vec>, } #[allow(clippy::derive_hash_xor_eq)] @@ -169,10 +169,10 @@ impl StateRequestHandler { trace!( target: LOG_TARGET, - "Handling state request from {}: Block {:?}, Starting at {:?}, no_proof={}", + "Handling state request from {}: Block {:?}, Starting at {:x?}, no_proof={}", peer, request.block, - sp_core::hexdisplay::HexDisplay::from(&request.start), + &request.start, request.no_proof, ); @@ -180,36 +180,45 @@ impl StateRequestHandler { let mut response = StateResponse::default(); if !request.no_proof { - let (proof, count) = self.client.read_proof_collection( + let (proof, _count) = self.client.read_proof_collection( &BlockId::hash(block), - &request.start, + request.start.as_slice(), MAX_RESPONSE_BYTES, )?; response.proof = proof.encode(); - if count == 0 { - response.complete = true; - } } else { let entries = self.client.storage_collection( &BlockId::hash(block), - &request.start, + request.start.as_slice(), MAX_RESPONSE_BYTES, )?; - response.entries = - entries.into_iter().map(|(key, value)| StateEntry { key, value }).collect(); - if response.entries.is_empty() { - response.complete = true; - } + response.entries = entries + .into_iter() + .map(|(state, complete)| KeyValueStateEntry { + state_root: state.state_root, + entries: state + .key_values + .into_iter() + .map(|(key, value)| StateEntry { key, value }) + .collect(), + complete, + }) + .collect(); } trace!( target: LOG_TARGET, - "StateResponse contains {} keys, {}, proof nodes, complete={}, from {:?} to {:?}", + "StateResponse contains {} keys, {}, proof nodes, from {:?} to {:?}", response.entries.len(), response.proof.len(), - response.complete, - response.entries.first().map(|e| sp_core::hexdisplay::HexDisplay::from(&e.key)), - response.entries.last().map(|e| sp_core::hexdisplay::HexDisplay::from(&e.key)), + response.entries.get(0).and_then(|top| top + .entries + .first() + .map(|e| sp_core::hexdisplay::HexDisplay::from(&e.key))), + response.entries.get(0).and_then(|top| top + .entries + .last() + .map(|e| sp_core::hexdisplay::HexDisplay::from(&e.key))), ); if let Some(value) = self.seen_requests.get_mut(&key) { // If this is the first time we have processed this request, we need to change diff --git a/client/network/test/src/lib.rs b/client/network/test/src/lib.rs index fb0012aaf5ba..084b09fd65f8 100644 --- a/client/network/test/src/lib.rs +++ b/client/network/test/src/lib.rs @@ -697,6 +697,8 @@ pub struct FullPeerConfig { pub is_authority: bool, /// Syncing mode pub sync_mode: SyncMode, + /// Extra genesis storage. + pub extra_storage: Option, /// Enable transaction indexing. pub storage_chain: bool, } @@ -765,6 +767,11 @@ where (Some(keep_blocks), false) => TestClientBuilder::with_pruning_window(keep_blocks), (None, false) => TestClientBuilder::with_default_backend(), }; + if let Some(storage) = config.extra_storage { + let genesis_extra_storage = test_client_builder.genesis_init_mut().extra_storage(); + *genesis_extra_storage = storage; + } + if matches!(config.sync_mode, SyncMode::Fast { .. } | SyncMode::Warp) { test_client_builder = test_client_builder.set_no_genesis(); } diff --git a/client/network/test/src/sync.rs b/client/network/test/src/sync.rs index f3af7f8ff6fc..ff62b5476d1e 100644 --- a/client/network/test/src/sync.rs +++ b/client/network/test/src/sync.rs @@ -1110,11 +1110,44 @@ fn syncs_state() { sp_tracing::try_init_simple(); for skip_proofs in &[false, true] { let mut net = TestNet::new(0); - net.add_full_peer_with_config(Default::default()); - net.add_full_peer_with_config(FullPeerConfig { - sync_mode: SyncMode::Fast { skip_proofs: *skip_proofs, storage_chain_mode: false }, - ..Default::default() - }); + let mut genesis_storage: sp_core::storage::Storage = Default::default(); + genesis_storage.top.insert(b"additional_key".to_vec(), vec![1]); + let mut child_data: std::collections::BTreeMap, Vec> = Default::default(); + for i in 0u8..16 { + child_data.insert(vec![i; 5], vec![i; 33]); + } + let child1 = sp_core::storage::StorageChild { + data: child_data.clone(), + child_info: sp_core::storage::ChildInfo::new_default(b"child1"), + }; + let child3 = sp_core::storage::StorageChild { + data: child_data.clone(), + child_info: sp_core::storage::ChildInfo::new_default(b"child3"), + }; + for i in 22u8..33 { + child_data.insert(vec![i; 5], vec![i; 33]); + } + let child2 = sp_core::storage::StorageChild { + data: child_data.clone(), + child_info: sp_core::storage::ChildInfo::new_default(b"child2"), + }; + genesis_storage + .children_default + .insert(child1.child_info.storage_key().to_vec(), child1); + genesis_storage + .children_default + .insert(child2.child_info.storage_key().to_vec(), child2); + genesis_storage + .children_default + .insert(child3.child_info.storage_key().to_vec(), child3); + let mut config_one = FullPeerConfig::default(); + config_one.extra_storage = Some(genesis_storage.clone()); + net.add_full_peer_with_config(config_one); + let mut config_two = FullPeerConfig::default(); + config_two.extra_storage = Some(genesis_storage); + config_two.sync_mode = + SyncMode::Fast { skip_proofs: *skip_proofs, storage_chain_mode: false }; + net.add_full_peer_with_config(config_two); net.peer(0).push_blocks(64, false); // Wait for peer 1 to sync header chain. net.block_until_sync(); diff --git a/client/service/src/client/client.rs b/client/service/src/client/client.rs index 4e3cb0aaf234..6ce2feb05075 100644 --- a/client/service/src/client/client.rs +++ b/client/service/src/client/client.rs @@ -64,7 +64,10 @@ use sp_consensus::{BlockOrigin, BlockStatus, Error as ConsensusError}; use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedSender}; use sp_core::{ convert_hash, - storage::{well_known_keys, ChildInfo, PrefixedStorageKey, StorageData, StorageKey}, + storage::{ + well_known_keys, ChildInfo, ChildType, PrefixedStorageKey, StorageChild, StorageData, + StorageKey, + }, ChangesTrieConfiguration, NativeOrEncoded, }; #[cfg(feature = "test-helpers")] @@ -78,11 +81,12 @@ use sp_runtime::{ BuildStorage, Justification, Justifications, }; use sp_state_machine::{ - key_changes, key_changes_proof, prove_child_read, prove_range_read_with_size, prove_read, - read_range_proof_check, Backend as StateBackend, ChangesTrieAnchorBlockId, - ChangesTrieConfigurationRange, ChangesTrieRootsStorage, ChangesTrieStorage, DBValue, + key_changes, key_changes_proof, prove_child_read, prove_range_read_with_child_with_size, + prove_read, read_range_proof_check_with_child_on_proving_backend, Backend as StateBackend, + ChangesTrieAnchorBlockId, ChangesTrieConfigurationRange, ChangesTrieRootsStorage, + ChangesTrieStorage, DBValue, KeyValueStates, KeyValueStorageLevel, MAX_NESTED_TRIE_DEPTH, }; -use sp_trie::StorageProof; +use sp_trie::{CompactProof, StorageProof}; use std::{ collections::{BTreeMap, HashMap, HashSet}, marker::PhantomData, @@ -824,10 +828,37 @@ where Some((main_sc, child_sc)) }, sc_consensus::StorageChanges::Import(changes) => { - let storage = sp_storage::Storage { - top: changes.state.into_iter().collect(), - children_default: Default::default(), - }; + let mut storage = sp_storage::Storage::default(); + for state in changes.state.0.into_iter() { + if state.parent_storage_keys.len() == 0 && state.state_root.len() == 0 { + for (key, value) in state.key_values.into_iter() { + storage.top.insert(key, value); + } + } else { + for parent_storage in state.parent_storage_keys { + let storage_key = PrefixedStorageKey::new_ref(&parent_storage); + let storage_key = + match ChildType::from_prefixed_key(&storage_key) { + Some((ChildType::ParentKeyId, storage_key)) => + storage_key, + None => + return Err(Error::Backend( + "Invalid child storage key.".to_string(), + )), + }; + let entry = storage + .children_default + .entry(storage_key.to_vec()) + .or_insert_with(|| StorageChild { + data: Default::default(), + child_info: ChildInfo::new_default(storage_key), + }); + for (key, value) in state.key_values.iter() { + entry.data.insert(key.clone(), value.clone()); + } + } + } + } let state_root = operation.op.reset_storage(storage)?; if state_root != *import_headers.post().state_root() { @@ -1347,62 +1378,153 @@ where fn read_proof_collection( &self, id: &BlockId, - start_key: &[u8], + start_key: &[Vec], size_limit: usize, - ) -> sp_blockchain::Result<(StorageProof, u32)> { + ) -> sp_blockchain::Result<(CompactProof, u32)> { let state = self.state_at(id)?; - Ok(prove_range_read_with_size::<_, HashFor>( - state, - None, - None, - size_limit, - Some(start_key), - )?) + let root = state.storage_root(std::iter::empty()).0; + + let (proof, count) = prove_range_read_with_child_with_size::<_, HashFor>( + state, size_limit, start_key, + )?; + let proof = sp_trie::encode_compact::>>(proof, root) + .map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))?; + Ok((proof, count)) } fn storage_collection( &self, id: &BlockId, - start_key: &[u8], + start_key: &[Vec], size_limit: usize, - ) -> sp_blockchain::Result, Vec)>> { + ) -> sp_blockchain::Result> { + if start_key.len() > MAX_NESTED_TRIE_DEPTH { + return Err(Error::Backend("Invalid start key.".to_string())) + } let state = self.state_at(id)?; - let mut current_key = start_key.to_vec(); - let mut total_size = 0; - let mut entries = Vec::new(); - while let Some(next_key) = state - .next_storage_key(¤t_key) - .map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))? - { - let value = state - .storage(next_key.as_ref()) + let child_info = |storage_key: &Vec| -> sp_blockchain::Result { + let storage_key = PrefixedStorageKey::new_ref(&storage_key); + match ChildType::from_prefixed_key(&storage_key) { + Some((ChildType::ParentKeyId, storage_key)) => + Ok(ChildInfo::new_default(storage_key)), + None => Err(Error::Backend("Invalid child storage key.".to_string())), + } + }; + let mut current_child = if start_key.len() == 2 { + let start_key = start_key.get(0).expect("checked len"); + if let Some(child_root) = state + .storage(&start_key) .map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))? - .unwrap_or_default(); - let size = value.len() + next_key.len(); - if total_size + size > size_limit && !entries.is_empty() { + { + Some((child_info(start_key)?, child_root)) + } else { + return Err(Error::Backend("Invalid root start key.".to_string())) + } + } else { + None + }; + let mut current_key = start_key.last().map(Clone::clone).unwrap_or(Vec::new()); + let mut total_size = 0; + let mut result = vec![( + KeyValueStorageLevel { + state_root: Vec::new(), + key_values: Vec::new(), + parent_storage_keys: Vec::new(), + }, + false, + )]; + + let mut child_roots = HashSet::new(); + loop { + let mut entries = Vec::new(); + let mut complete = true; + let mut switch_child_key = None; + while let Some(next_key) = if let Some(child) = current_child.as_ref() { + state + .next_child_storage_key(&child.0, ¤t_key) + .map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))? + } else { + state + .next_storage_key(¤t_key) + .map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))? + } { + let value = if let Some(child) = current_child.as_ref() { + state + .child_storage(&child.0, next_key.as_ref()) + .map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))? + .unwrap_or_default() + } else { + state + .storage(next_key.as_ref()) + .map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))? + .unwrap_or_default() + }; + let size = value.len() + next_key.len(); + if total_size + size > size_limit && !entries.is_empty() { + complete = false; + break + } + total_size += size; + + if current_child.is_none() && + sp_core::storage::well_known_keys::is_child_storage_key(next_key.as_slice()) + { + if !child_roots.contains(value.as_slice()) { + child_roots.insert(value.clone()); + switch_child_key = Some((next_key.clone(), value.clone())); + entries.push((next_key.clone(), value)); + break + } + } + entries.push((next_key.clone(), value)); + current_key = next_key; + } + if let Some((child, child_root)) = switch_child_key.take() { + result[0].0.key_values.extend(entries.into_iter()); + current_child = Some((child_info(&child)?, child_root)); + current_key = Vec::new(); + } else if let Some((child, child_root)) = current_child.take() { + current_key = child.into_prefixed_storage_key().into_inner(); + result.push(( + KeyValueStorageLevel { + state_root: child_root, + key_values: entries, + parent_storage_keys: Vec::new(), + }, + complete, + )); + if !complete { + break + } + } else { + result[0].0.key_values.extend(entries.into_iter()); + result[0].1 = complete; break } - total_size += size; - entries.push((next_key.clone(), value)); - current_key = next_key; } - Ok(entries) + Ok(result) } fn verify_range_proof( &self, root: Block::Hash, - proof: StorageProof, - start_key: &[u8], - ) -> sp_blockchain::Result<(Vec<(Vec, Vec)>, bool)> { - Ok(read_range_proof_check::>( - root, - proof, - None, - None, - None, - Some(start_key), - )?) + proof: CompactProof, + start_key: &[Vec], + ) -> sp_blockchain::Result<(KeyValueStates, usize)> { + let mut db = sp_state_machine::MemoryDB::>::new(&[]); + let _ = sp_trie::decode_compact::>, _, _>( + &mut db, + proof.iter_compact_encoded_nodes(), + Some(&root), + ) + .map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))?; + let proving_backend = sp_state_machine::TrieBackend::new(db, root); + let state = read_range_proof_check_with_child_on_proving_backend::>( + &proving_backend, + start_key, + )?; + + Ok(state) } } diff --git a/primitives/state-machine/src/lib.rs b/primitives/state-machine/src/lib.rs index a724cf5c9a0b..b0178021f313 100644 --- a/primitives/state-machine/src/lib.rs +++ b/primitives/state-machine/src/lib.rs @@ -172,7 +172,7 @@ mod std_reexport { }; pub use sp_trie::{ trie_types::{Layout, TrieDBMut}, - DBValue, MemoryDB, StorageProof, TrieMut, + CompactProof, DBValue, MemoryDB, StorageProof, TrieMut, }; } @@ -181,15 +181,20 @@ mod execution { use super::*; use codec::{Codec, Decode, Encode}; use hash_db::Hasher; + use smallvec::SmallVec; use sp_core::{ hexdisplay::HexDisplay, - storage::ChildInfo, + storage::{ChildInfo, ChildType, PrefixedStorageKey}, traits::{CodeExecutor, ReadRuntimeVersionExt, RuntimeCode, SpawnNamed}, NativeOrEncoded, NeverNativeValue, }; use sp_externalities::Extensions; - use std::{collections::HashMap, fmt, panic::UnwindSafe, result}; - use tracing::{trace, warn}; + use std::{ + collections::{HashMap, HashSet}, + fmt, + panic::UnwindSafe, + result, + }; const PROOF_CLOSE_TRANSACTION: &str = "\ Closing a transaction that was started in this function. Client initiated transactions @@ -742,6 +747,254 @@ mod execution { prove_read_on_trie_backend(trie_backend, keys) } + /// State machine only allows a single level + /// of child trie. + pub const MAX_NESTED_TRIE_DEPTH: usize = 2; + + /// Multiple key value state. + /// States are ordered by root storage key. + #[derive(PartialEq, Eq, Clone)] + pub struct KeyValueStates(pub Vec); + + /// A key value state at any storage level. + #[derive(PartialEq, Eq, Clone)] + pub struct KeyValueStorageLevel { + /// State root of the level, for + /// top trie it is as an empty byte array. + pub state_root: Vec, + /// Storage of parents, empty for top root or + /// when exporting (building proof). + pub parent_storage_keys: Vec>, + /// Pair of key and values from this state. + pub key_values: Vec<(Vec, Vec)>, + } + + impl From for KeyValueStates + where + I: IntoIterator, (Vec<(Vec, Vec)>, Vec>))>, + { + fn from(b: I) -> Self { + let mut result = Vec::new(); + for (state_root, (key_values, storage_paths)) in b.into_iter() { + result.push(KeyValueStorageLevel { + state_root, + key_values, + parent_storage_keys: storage_paths, + }) + } + KeyValueStates(result) + } + } + + impl KeyValueStates { + /// Return total number of key values in states. + pub fn len(&self) -> usize { + self.0.iter().fold(0, |nb, state| nb + state.key_values.len()) + } + + /// Update last keys accessed from this state. + pub fn update_last_key( + &self, + stopped_at: usize, + last: &mut SmallVec<[Vec; 2]>, + ) -> bool { + if stopped_at == 0 || stopped_at > MAX_NESTED_TRIE_DEPTH { + return false + } + match stopped_at { + 1 => { + let top_last = + self.0.get(0).and_then(|s| s.key_values.last().map(|kv| kv.0.clone())); + if let Some(top_last) = top_last { + match last.len() { + 0 => { + last.push(top_last); + return true + }, + 2 => { + last.pop(); + }, + _ => (), + } + // update top trie access. + last[0] = top_last; + return true + } else { + // No change in top trie accesses. + // Indicates end of reading of a child trie. + last.truncate(1); + return true + } + }, + 2 => { + let top_last = + self.0.get(0).and_then(|s| s.key_values.last().map(|kv| kv.0.clone())); + let child_last = + self.0.last().and_then(|s| s.key_values.last().map(|kv| kv.0.clone())); + + if let Some(child_last) = child_last { + if last.len() == 0 { + if let Some(top_last) = top_last { + last.push(top_last) + } else { + return false + } + } else if let Some(top_last) = top_last { + last[0] = top_last; + } + if last.len() == 2 { + last.pop(); + } + last.push(child_last); + return true + } else { + // stopped at level 2 so child last is define. + return false + } + }, + _ => (), + } + false + } + } + + /// Generate range storage read proof, with child tries + /// content. + /// A size limit is applied to the proof with the + /// exception that `start_at` and its following element + /// are always part of the proof. + /// If a key different than `start_at` is a child trie root, + /// the child trie content will be included in the proof. + pub fn prove_range_read_with_child_with_size( + backend: B, + size_limit: usize, + start_at: &[Vec], + ) -> Result<(StorageProof, u32), Box> + where + B: Backend, + H: Hasher, + H::Out: Ord + Codec, + { + let trie_backend = backend + .as_trie_backend() + .ok_or_else(|| Box::new(ExecutionError::UnableToGenerateProof) as Box)?; + prove_range_read_with_child_with_size_on_trie_backend(trie_backend, size_limit, start_at) + } + + /// Generate range storage read proof, with child tries + /// content. + /// See `prove_range_read_with_child_with_size`. + pub fn prove_range_read_with_child_with_size_on_trie_backend( + trie_backend: &TrieBackend, + size_limit: usize, + start_at: &[Vec], + ) -> Result<(StorageProof, u32), Box> + where + S: trie_backend_essence::TrieBackendStorage, + H: Hasher, + H::Out: Ord + Codec, + { + if start_at.len() > MAX_NESTED_TRIE_DEPTH { + return Err(Box::new("Invalid start of range.")) + } + + let proving_backend = proving_backend::ProvingBackend::::new(trie_backend); + let mut count = 0; + + let mut child_roots = HashSet::new(); + let (mut child_key, mut start_at) = if start_at.len() == 2 { + let storage_key = start_at.get(0).expect("Checked length.").clone(); + if let Some(state_root) = proving_backend + .storage(&storage_key) + .map_err(|e| Box::new(e) as Box)? + { + child_roots.insert(state_root.clone()); + } else { + return Err(Box::new("Invalid range start child trie key.")) + } + + (Some(storage_key), start_at.get(1).cloned()) + } else { + (None, start_at.get(0).cloned()) + }; + + loop { + let (child_info, depth) = if let Some(storage_key) = child_key.as_ref() { + let storage_key = PrefixedStorageKey::new_ref(storage_key); + ( + Some(match ChildType::from_prefixed_key(&storage_key) { + Some((ChildType::ParentKeyId, storage_key)) => + ChildInfo::new_default(storage_key), + None => return Err(Box::new("Invalid range start child trie key.")), + }), + 2, + ) + } else { + (None, 1) + }; + + let start_at_ref = start_at.as_ref().map(AsRef::as_ref); + let mut switch_child_key = None; + let mut first = start_at.is_some(); + let completed = proving_backend + .apply_to_key_values_while( + child_info.as_ref(), + None, + start_at_ref, + |key, value| { + if first { + if start_at_ref + .as_ref() + .map(|start| &key.as_slice() > start) + .unwrap_or(true) + { + first = false; + } + } + if first { + true + } else if depth < MAX_NESTED_TRIE_DEPTH && + sp_core::storage::well_known_keys::is_child_storage_key( + key.as_slice(), + ) { + count += 1; + if !child_roots.contains(value.as_slice()) { + child_roots.insert(value); + switch_child_key = Some(key); + false + } else { + // do not add two child trie with same root + true + } + } else if proving_backend.estimate_encoded_size() <= size_limit { + count += 1; + true + } else { + false + } + }, + false, + ) + .map_err(|e| Box::new(e) as Box)?; + + if switch_child_key.is_none() { + if depth == 1 { + break + } else { + if completed { + start_at = child_key.take(); + } else { + break + } + } + } else { + child_key = switch_child_key; + start_at = None; + } + } + Ok((proving_backend.extract_proof(), count)) + } + /// Generate range storage read proof. pub fn prove_range_read_with_size( backend: B, @@ -884,7 +1137,25 @@ mod execution { Ok(result) } - /// Check child storage range proof, generated by `prove_range_read` call. + /// Check storage range proof with child trie included, generated by + /// `prove_range_read_with_child_with_size` call. + /// + /// Returns key values contents and the depth of the pending state iteration + /// (0 if completed). + pub fn read_range_proof_check_with_child( + root: H::Out, + proof: StorageProof, + start_at: &[Vec], + ) -> Result<(KeyValueStates, usize), Box> + where + H: Hasher, + H::Out: Ord + Codec, + { + let proving_backend = create_proof_check_backend::(root, proof)?; + read_range_proof_check_with_child_on_proving_backend(&proving_backend, start_at) + } + + /// Check child storage range proof, generated by `prove_range_read_with_size` call. pub fn read_range_proof_check( root: H::Out, proof: StorageProof, @@ -991,6 +1262,130 @@ mod execution { Err(e) => Err(Box::new(e) as Box), } } + + /// Check storage range proof on pre-created proving backend. + /// + /// See `read_range_proof_check_with_child`. + pub fn read_range_proof_check_with_child_on_proving_backend( + proving_backend: &TrieBackend, H>, + start_at: &[Vec], + ) -> Result<(KeyValueStates, usize), Box> + where + H: Hasher, + H::Out: Ord + Codec, + { + let mut result = vec![KeyValueStorageLevel { + state_root: Default::default(), + key_values: Default::default(), + parent_storage_keys: Default::default(), + }]; + if start_at.len() > MAX_NESTED_TRIE_DEPTH { + return Err(Box::new("Invalid start of range.")) + } + + let mut child_roots = HashSet::new(); + let (mut child_key, mut start_at) = if start_at.len() == 2 { + let storage_key = start_at.get(0).expect("Checked length.").clone(); + let child_key = if let Some(state_root) = proving_backend + .storage(&storage_key) + .map_err(|e| Box::new(e) as Box)? + { + child_roots.insert(state_root.clone()); + Some((storage_key, state_root)) + } else { + return Err(Box::new("Invalid range start child trie key.")) + }; + + (child_key, start_at.get(1).cloned()) + } else { + (None, start_at.get(0).cloned()) + }; + + let completed = loop { + let (child_info, depth) = if let Some((storage_key, state_root)) = child_key.as_ref() { + result.push(KeyValueStorageLevel { + state_root: state_root.clone(), + key_values: Default::default(), + parent_storage_keys: Default::default(), + }); + + let storage_key = PrefixedStorageKey::new_ref(storage_key); + ( + Some(match ChildType::from_prefixed_key(&storage_key) { + Some((ChildType::ParentKeyId, storage_key)) => + ChildInfo::new_default(storage_key), + None => return Err(Box::new("Invalid range start child trie key.")), + }), + 2, + ) + } else { + (None, 1) + }; + + let values = if child_info.is_some() { + &mut result.last_mut().expect("Added above").key_values + } else { + &mut result[0].key_values + }; + let start_at_ref = start_at.as_ref().map(AsRef::as_ref); + let mut switch_child_key = None; + let mut first = start_at.is_some(); + let completed = proving_backend + .apply_to_key_values_while( + child_info.as_ref(), + None, + start_at_ref, + |key, value| { + if first { + if start_at_ref + .as_ref() + .map(|start| &key.as_slice() > start) + .unwrap_or(true) + { + first = false; + } + } + if !first { + values.push((key.to_vec(), value.to_vec())); + } + if first { + true + } else if depth < MAX_NESTED_TRIE_DEPTH && + sp_core::storage::well_known_keys::is_child_storage_key( + key.as_slice(), + ) { + if child_roots.contains(value.as_slice()) { + // Do not add two chid trie with same root. + true + } else { + child_roots.insert(value.clone()); + switch_child_key = Some((key, value)); + false + } + } else { + true + } + }, + true, + ) + .map_err(|e| Box::new(e) as Box)?; + + if switch_child_key.is_none() { + if !completed { + break depth + } + if depth == 1 { + break 0 + } else { + start_at = child_key.take().map(|entry| entry.0); + } + } else { + child_key = switch_child_key; + start_at = None; + } + }; + Ok((KeyValueStates(result), completed)) + } } #[cfg(test)] @@ -1574,7 +1969,7 @@ mod tests { assert_eq!( local_result1.into_iter().collect::>(), - vec![(b"value3".to_vec(), Some(vec![142]))], + vec![(b"value3".to_vec(), Some(vec![142; 33]))], ); assert_eq!(local_result2.into_iter().collect::>(), vec![(b"value2".to_vec(), None)]); assert_eq!(local_result3.into_iter().collect::>(), vec![(b"dummy".to_vec(), None)]); @@ -1678,7 +2073,7 @@ mod tests { let remote_root = remote_backend.storage_root(::std::iter::empty()).0; let (proof, count) = prove_range_read_with_size(remote_backend, None, None, 0, None).unwrap(); - // Alwasys contains at least some nodes. + // Always contains at least some nodes. assert_eq!(proof.into_memory_db::().drain().len(), 3); assert_eq!(count, 1); @@ -1723,6 +2118,45 @@ mod tests { assert_eq!(completed, true); } + #[test] + fn prove_range_with_child_works() { + let remote_backend = trie_backend::tests::test_trie(); + let remote_root = remote_backend.storage_root(::std::iter::empty()).0; + let mut start_at = smallvec::SmallVec::<[Vec; 2]>::new(); + let trie_backend = remote_backend.as_trie_backend().unwrap(); + let max_iter = 1000; + let mut nb_loop = 0; + loop { + nb_loop += 1; + if max_iter == nb_loop { + panic!("Too many loop in prove range"); + } + let (proof, count) = prove_range_read_with_child_with_size_on_trie_backend( + trie_backend, + 1, + start_at.as_slice(), + ) + .unwrap(); + // Always contains at least some nodes. + assert!(proof.clone().into_memory_db::().drain().len() > 0); + assert!(count < 3); // when doing child we include parent and first child key. + + let (result, completed_depth) = read_range_proof_check_with_child::( + remote_root, + proof.clone(), + start_at.as_slice(), + ) + .unwrap(); + + if completed_depth == 0 { + break + } + assert!(result.update_last_key(completed_depth, &mut start_at)); + } + + assert_eq!(nb_loop, 10); + } + #[test] fn compact_multiple_child_trie() { // this root will be queried diff --git a/primitives/state-machine/src/trie_backend.rs b/primitives/state-machine/src/trie_backend.rs index 7cb725a80503..7f9a02e05525 100644 --- a/primitives/state-machine/src/trie_backend.rs +++ b/primitives/state-machine/src/trie_backend.rs @@ -281,8 +281,8 @@ pub mod tests { { let mut mdb = KeySpacedDBMut::new(&mut mdb, child_info.keyspace()); let mut trie = TrieDBMut::new(&mut mdb, &mut root); - trie.insert(b"value3", &[142]).expect("insert failed"); - trie.insert(b"value4", &[124]).expect("insert failed"); + trie.insert(b"value3", &[142; 33]).expect("insert failed"); + trie.insert(b"value4", &[124; 33]).expect("insert failed"); }; { @@ -319,7 +319,7 @@ pub mod tests { test_trie .child_storage(&ChildInfo::new_default(CHILD_KEY_1), b"value3") .unwrap(), - Some(vec![142u8]), + Some(vec![142u8; 33]), ); // Change cache entry to check that caching is active. test_trie diff --git a/test-utils/runtime/client/src/lib.rs b/test-utils/runtime/client/src/lib.rs index bcfe93b6f797..da92e0f37983 100644 --- a/test-utils/runtime/client/src/lib.rs +++ b/test-utils/runtime/client/src/lib.rs @@ -137,6 +137,11 @@ impl GenesisParameters { pub fn set_wasm_code(&mut self, code: Vec) { self.wasm_code = Some(code); } + + /// Access extra genesis storage. + pub fn extra_storage(&mut self) -> &mut Storage { + &mut self.extra_storage + } } impl substrate_test_client::GenesisInit for GenesisParameters { From 2e8bb09da2dfbc1a21c159e777dc1cf0bceba56d Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Sun, 7 Nov 2021 23:24:53 +0000 Subject: [PATCH 146/695] put `TryInto` and `TryFrom` in `sp_std::prelude` (#10183) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Switch to Rust 2021 * Update trybuild to fix errors * half baked * fix * remove unused import * remove more warnings Co-authored-by: Bastian Köcher --- frame/assets/src/lib.rs | 2 +- frame/aura/src/lib.rs | 2 +- frame/authority-discovery/src/lib.rs | 2 -- frame/babe/src/lib.rs | 2 +- frame/bags-list/remote-tests/src/lib.rs | 2 +- frame/bags-list/remote-tests/src/sanity_check.rs | 2 +- frame/benchmarking/src/analysis.rs | 1 - frame/contracts/rpc/src/lib.rs | 1 - frame/contracts/src/benchmarking/code.rs | 2 +- frame/contracts/src/benchmarking/mod.rs | 2 +- frame/contracts/src/wasm/mod.rs | 1 - frame/democracy/src/conviction.rs | 2 +- frame/democracy/src/tests/lock_voting.rs | 1 - frame/democracy/src/vote.rs | 2 +- frame/election-provider-multi-phase/src/benchmarking.rs | 4 ---- frame/election-provider-multi-phase/src/helpers.rs | 2 +- frame/election-provider-multi-phase/src/lib.rs | 2 +- frame/election-provider-multi-phase/src/mock.rs | 2 +- frame/election-provider-multi-phase/src/unsigned.rs | 2 +- frame/identity/src/lib.rs | 2 +- frame/im-online/src/lib.rs | 1 - frame/multisig/src/benchmarking.rs | 1 - frame/randomness-collective-flip/src/lib.rs | 2 +- frame/session/src/lib.rs | 1 - frame/staking/reward-curve/src/log.rs | 2 -- frame/staking/reward-fn/src/lib.rs | 1 - frame/staking/src/benchmarking.rs | 1 - frame/support/procedural/src/pallet/parse/config.rs | 1 - frame/support/src/storage/bounded_btree_map.rs | 1 - frame/support/src/storage/bounded_vec.rs | 3 +-- frame/support/src/storage/mod.rs | 1 - frame/system/src/offchain.rs | 6 +----- frame/transaction-payment/rpc/src/lib.rs | 2 +- frame/transaction-payment/src/lib.rs | 1 - frame/uniques/src/impl_nonfungibles.rs | 2 +- frame/uniques/src/tests.rs | 2 +- primitives/std/src/lib.rs | 2 ++ utils/frame/benchmarking-cli/src/writer.rs | 1 - utils/frame/frame-utilities-cli/src/pallet_id.rs | 1 - 39 files changed, 22 insertions(+), 48 deletions(-) diff --git a/frame/assets/src/lib.rs b/frame/assets/src/lib.rs index 4176242c8394..dfc81eadeb53 100644 --- a/frame/assets/src/lib.rs +++ b/frame/assets/src/lib.rs @@ -157,7 +157,7 @@ use sp_runtime::{ }, ArithmeticError, TokenError, }; -use sp_std::{borrow::Borrow, convert::TryInto, prelude::*}; +use sp_std::{borrow::Borrow, prelude::*}; #[cfg(feature = "std")] use frame_support::traits::GenesisBuild; diff --git a/frame/aura/src/lib.rs b/frame/aura/src/lib.rs index 4b5294835403..a4e55f25df5f 100644 --- a/frame/aura/src/lib.rs +++ b/frame/aura/src/lib.rs @@ -49,7 +49,7 @@ use sp_runtime::{ traits::{IsMember, Member, SaturatedConversion, Saturating, Zero}, RuntimeAppPublic, }; -use sp_std::{convert::TryFrom, vec::Vec}; +use sp_std::prelude::*; pub mod migrations; mod mock; diff --git a/frame/authority-discovery/src/lib.rs b/frame/authority-discovery/src/lib.rs index 8fced0d18cff..a6609860d7cf 100644 --- a/frame/authority-discovery/src/lib.rs +++ b/frame/authority-discovery/src/lib.rs @@ -30,8 +30,6 @@ use frame_support::{ use sp_authority_discovery::AuthorityId; use sp_std::prelude::*; -use core::convert::TryFrom; - pub use pallet::*; #[frame_support::pallet] diff --git a/frame/babe/src/lib.rs b/frame/babe/src/lib.rs index c74bbf897ac7..033d993f4e26 100644 --- a/frame/babe/src/lib.rs +++ b/frame/babe/src/lib.rs @@ -31,7 +31,7 @@ use frame_support::{ weights::{Pays, Weight}, BoundedVec, WeakBoundedVec, }; -use sp_application_crypto::{Public, TryFrom}; +use sp_application_crypto::Public; use sp_runtime::{ generic::DigestItem, traits::{IsMember, One, SaturatedConversion, Saturating, Zero}, diff --git a/frame/bags-list/remote-tests/src/lib.rs b/frame/bags-list/remote-tests/src/lib.rs index e471c4c95bdb..3d555eb1f1e3 100644 --- a/frame/bags-list/remote-tests/src/lib.rs +++ b/frame/bags-list/remote-tests/src/lib.rs @@ -17,7 +17,7 @@ //! Utilities for remote-testing pallet-bags-list. -use sp_std::convert::TryInto; +use sp_std::prelude::*; /// A common log target to use. pub const LOG_TARGET: &'static str = "runtime::bags-list::remote-tests"; diff --git a/frame/bags-list/remote-tests/src/sanity_check.rs b/frame/bags-list/remote-tests/src/sanity_check.rs index e5e9f45bac5f..7282e7bad5e3 100644 --- a/frame/bags-list/remote-tests/src/sanity_check.rs +++ b/frame/bags-list/remote-tests/src/sanity_check.rs @@ -23,7 +23,7 @@ use frame_support::{ }; use remote_externalities::{Builder, Mode, OnlineConfig}; use sp_runtime::traits::Block as BlockT; -use sp_std::convert::TryInto; +use sp_std::prelude::*; /// Execute the sanity check of the bags-list. pub async fn execute( diff --git a/frame/benchmarking/src/analysis.rs b/frame/benchmarking/src/analysis.rs index 2bb20ebe2e7f..5ffb6e93c8fc 100644 --- a/frame/benchmarking/src/analysis.rs +++ b/frame/benchmarking/src/analysis.rs @@ -18,7 +18,6 @@ //! Tools for analyzing the benchmark results. use crate::BenchmarkResult; -use core::convert::TryFrom; use linregress::{FormulaRegressionBuilder, RegressionDataBuilder}; use std::collections::BTreeMap; diff --git a/frame/contracts/rpc/src/lib.rs b/frame/contracts/rpc/src/lib.rs index e0796af05654..c82cf44d97c7 100644 --- a/frame/contracts/rpc/src/lib.rs +++ b/frame/contracts/rpc/src/lib.rs @@ -32,7 +32,6 @@ use sp_runtime::{ generic::BlockId, traits::{Block as BlockT, Header as HeaderT}, }; -use std::convert::{TryFrom, TryInto}; pub use pallet_contracts_rpc_runtime_api::ContractsApi as ContractsRuntimeApi; diff --git a/frame/contracts/src/benchmarking/code.rs b/frame/contracts/src/benchmarking/code.rs index b24005ec5869..6b90381e7d35 100644 --- a/frame/contracts/src/benchmarking/code.rs +++ b/frame/contracts/src/benchmarking/code.rs @@ -36,7 +36,7 @@ use pwasm_utils::parity_wasm::{ use sp_core::crypto::UncheckedFrom; use sp_runtime::traits::Hash; use sp_sandbox::{EnvironmentDefinitionBuilder, Memory}; -use sp_std::{borrow::ToOwned, convert::TryFrom, prelude::*}; +use sp_std::{borrow::ToOwned, prelude::*}; /// Pass to `create_code` in order to create a compiled `WasmModule`. /// diff --git a/frame/contracts/src/benchmarking/mod.rs b/frame/contracts/src/benchmarking/mod.rs index 5c753c2d9555..665ec565c8e6 100644 --- a/frame/contracts/src/benchmarking/mod.rs +++ b/frame/contracts/src/benchmarking/mod.rs @@ -44,7 +44,7 @@ use sp_runtime::{ traits::{Bounded, Hash}, Perbill, }; -use sp_std::{convert::TryInto, default::Default, vec, vec::Vec}; +use sp_std::prelude::*; /// How many batches we do per API benchmark. const API_BENCHMARK_BATCHES: u32 = 20; diff --git a/frame/contracts/src/wasm/mod.rs b/frame/contracts/src/wasm/mod.rs index 855cb6e45091..565a424323ac 100644 --- a/frame/contracts/src/wasm/mod.rs +++ b/frame/contracts/src/wasm/mod.rs @@ -1967,7 +1967,6 @@ mod tests { #[test] #[cfg(feature = "unstable-interface")] fn call_runtime_works() { - use std::convert::TryInto; let call = Call::System(frame_system::Call::remark { remark: b"Hello World".to_vec() }); let mut ext = MockExt::default(); let result = execute(CODE_CALL_RUNTIME, call.encode(), &mut ext).unwrap(); diff --git a/frame/democracy/src/conviction.rs b/frame/democracy/src/conviction.rs index b4f24c93bb40..59a5eccc616c 100644 --- a/frame/democracy/src/conviction.rs +++ b/frame/democracy/src/conviction.rs @@ -24,7 +24,7 @@ use sp_runtime::{ traits::{Bounded, CheckedDiv, CheckedMul, Zero}, RuntimeDebug, }; -use sp_std::{convert::TryFrom, result::Result}; +use sp_std::{prelude::*, result::Result}; /// A value denoting the strength of conviction of a vote. #[derive(Encode, Decode, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, RuntimeDebug, TypeInfo)] diff --git a/frame/democracy/src/tests/lock_voting.rs b/frame/democracy/src/tests/lock_voting.rs index 8b80b39c14aa..2e1440d8f44b 100644 --- a/frame/democracy/src/tests/lock_voting.rs +++ b/frame/democracy/src/tests/lock_voting.rs @@ -18,7 +18,6 @@ //! The tests for functionality concerning locking and lock-voting. use super::*; -use std::convert::TryFrom; fn aye(x: u8, balance: u64) -> AccountVote { AccountVote::Standard { diff --git a/frame/democracy/src/vote.rs b/frame/democracy/src/vote.rs index 03ca020ca094..da74f7bd2fb6 100644 --- a/frame/democracy/src/vote.rs +++ b/frame/democracy/src/vote.rs @@ -24,7 +24,7 @@ use sp_runtime::{ traits::{Saturating, Zero}, RuntimeDebug, }; -use sp_std::{convert::TryFrom, prelude::*, result::Result}; +use sp_std::prelude::*; /// A number of lock periods, plus a vote, one way or the other. #[derive(Copy, Clone, Eq, PartialEq, Default, RuntimeDebug)] diff --git a/frame/election-provider-multi-phase/src/benchmarking.rs b/frame/election-provider-multi-phase/src/benchmarking.rs index 9648b8e0f246..d9db6c309099 100644 --- a/frame/election-provider-multi-phase/src/benchmarking.rs +++ b/frame/election-provider-multi-phase/src/benchmarking.rs @@ -26,10 +26,6 @@ use rand::{prelude::SliceRandom, rngs::SmallRng, SeedableRng}; use sp_arithmetic::{per_things::Percent, traits::One}; use sp_npos_elections::IndexAssignment; use sp_runtime::InnerOf; -use sp_std::{ - boxed::Box, - convert::{TryFrom, TryInto}, -}; const SEED: u32 = 999; diff --git a/frame/election-provider-multi-phase/src/helpers.rs b/frame/election-provider-multi-phase/src/helpers.rs index 72b1b23f27f3..98a14a93a25e 100644 --- a/frame/election-provider-multi-phase/src/helpers.rs +++ b/frame/election-provider-multi-phase/src/helpers.rs @@ -18,7 +18,7 @@ //! Some helper functions/macros for this crate. use super::{Config, SolutionTargetIndexOf, SolutionVoterIndexOf, VoteWeight}; -use sp_std::{collections::btree_map::BTreeMap, convert::TryInto, prelude::*}; +use sp_std::{collections::btree_map::BTreeMap, prelude::*}; #[macro_export] macro_rules! log { diff --git a/frame/election-provider-multi-phase/src/lib.rs b/frame/election-provider-multi-phase/src/lib.rs index a7863fafa774..80a13aa99fb7 100644 --- a/frame/election-provider-multi-phase/src/lib.rs +++ b/frame/election-provider-multi-phase/src/lib.rs @@ -255,7 +255,7 @@ use sp_runtime::{ }, DispatchError, PerThing, Perbill, RuntimeDebug, SaturatedConversion, }; -use sp_std::{convert::TryInto, prelude::*}; +use sp_std::prelude::*; #[cfg(feature = "runtime-benchmarks")] mod benchmarking; diff --git a/frame/election-provider-multi-phase/src/mock.rs b/frame/election-provider-multi-phase/src/mock.rs index 1a65316be1f1..fbde6ad99170 100644 --- a/frame/election-provider-multi-phase/src/mock.rs +++ b/frame/election-provider-multi-phase/src/mock.rs @@ -40,7 +40,7 @@ use sp_runtime::{ traits::{BlakeTwo256, IdentityLookup}, PerU16, }; -use std::{convert::TryFrom, sync::Arc}; +use std::sync::Arc; pub type Block = sp_runtime::generic::Block; pub type UncheckedExtrinsic = sp_runtime::generic::UncheckedExtrinsic; diff --git a/frame/election-provider-multi-phase/src/unsigned.rs b/frame/election-provider-multi-phase/src/unsigned.rs index 0ed9b5427b1e..1770f4343a0a 100644 --- a/frame/election-provider-multi-phase/src/unsigned.rs +++ b/frame/election-provider-multi-phase/src/unsigned.rs @@ -35,7 +35,7 @@ use sp_runtime::{ offchain::storage::{MutateStorageError, StorageValueRef}, DispatchError, SaturatedConversion, }; -use sp_std::{boxed::Box, cmp::Ordering, convert::TryFrom, vec::Vec}; +use sp_std::{cmp::Ordering, prelude::*}; /// Storage key used to store the last block number at which offchain worker ran. pub(crate) const OFFCHAIN_LAST_BLOCK: &[u8] = b"parity/multi-phase-unsigned-election"; diff --git a/frame/identity/src/lib.rs b/frame/identity/src/lib.rs index a91381f1edd8..4d86efd27e53 100644 --- a/frame/identity/src/lib.rs +++ b/frame/identity/src/lib.rs @@ -80,7 +80,7 @@ pub mod weights; use frame_support::traits::{BalanceStatus, Currency, OnUnbalanced, ReservableCurrency}; use sp_runtime::traits::{AppendZerosInput, Saturating, StaticLookup, Zero}; -use sp_std::{convert::TryInto, prelude::*}; +use sp_std::prelude::*; pub use weights::WeightInfo; pub use pallet::*; diff --git a/frame/im-online/src/lib.rs b/frame/im-online/src/lib.rs index d76bbaaa2fd1..2c5a7633c3b4 100644 --- a/frame/im-online/src/lib.rs +++ b/frame/im-online/src/lib.rs @@ -75,7 +75,6 @@ mod tests; pub mod weights; use codec::{Decode, Encode, MaxEncodedLen}; -use core::convert::TryFrom; use frame_support::{ traits::{ EstimateNextSessionRotation, Get, OneSessionHandler, ValidatorSet, diff --git a/frame/multisig/src/benchmarking.rs b/frame/multisig/src/benchmarking.rs index 1390b6eebbe3..cb98d8954030 100644 --- a/frame/multisig/src/benchmarking.rs +++ b/frame/multisig/src/benchmarking.rs @@ -20,7 +20,6 @@ #![cfg(feature = "runtime-benchmarks")] use super::*; -use core::convert::TryInto; use frame_benchmarking::{account, benchmarks}; use frame_system::RawOrigin; use sp_runtime::traits::Bounded; diff --git a/frame/randomness-collective-flip/src/lib.rs b/frame/randomness-collective-flip/src/lib.rs index 1b1d5cb5cd82..a9abb2c9564d 100644 --- a/frame/randomness-collective-flip/src/lib.rs +++ b/frame/randomness-collective-flip/src/lib.rs @@ -71,7 +71,7 @@ use safe_mix::TripletMix; use codec::Encode; use frame_support::traits::Randomness; use sp_runtime::traits::{Hash, Saturating}; -use sp_std::{convert::TryInto, prelude::*}; +use sp_std::prelude::*; const RANDOM_MATERIAL_LEN: u32 = 81; diff --git a/frame/session/src/lib.rs b/frame/session/src/lib.rs index 7fe163e0dfea..6779285ee318 100644 --- a/frame/session/src/lib.rs +++ b/frame/session/src/lib.rs @@ -131,7 +131,6 @@ use sp_runtime::{ }; use sp_staking::SessionIndex; use sp_std::{ - convert::TryFrom, marker::PhantomData, ops::{Rem, Sub}, prelude::*, diff --git a/frame/staking/reward-curve/src/log.rs b/frame/staking/reward-curve/src/log.rs index c196aaaa31a9..248a1e3c36a6 100644 --- a/frame/staking/reward-curve/src/log.rs +++ b/frame/staking/reward-curve/src/log.rs @@ -1,5 +1,3 @@ -use std::convert::TryInto; - /// Simple u32 power of 2 function - simply uses a bit shift macro_rules! pow2 { ($n:expr) => { diff --git a/frame/staking/reward-fn/src/lib.rs b/frame/staking/reward-fn/src/lib.rs index dd5e629b3984..25e52051effa 100644 --- a/frame/staking/reward-fn/src/lib.rs +++ b/frame/staking/reward-fn/src/lib.rs @@ -19,7 +19,6 @@ //! Useful function for inflation for nominated proof of stake. -use core::convert::TryFrom; use sp_arithmetic::{ biguint::BigUint, traits::{SaturatedConversion, Zero}, diff --git a/frame/staking/src/benchmarking.rs b/frame/staking/src/benchmarking.rs index 220e8f1e6a24..80630818de7e 100644 --- a/frame/staking/src/benchmarking.rs +++ b/frame/staking/src/benchmarking.rs @@ -256,7 +256,6 @@ benchmarks! { } unbond { - use sp_std::convert::TryFrom; // clean up any existing state. clear_validators_and_nominators::(); diff --git a/frame/support/procedural/src/pallet/parse/config.rs b/frame/support/procedural/src/pallet/parse/config.rs index 712c20ffc7b4..9e0a0fd52cbf 100644 --- a/frame/support/procedural/src/pallet/parse/config.rs +++ b/frame/support/procedural/src/pallet/parse/config.rs @@ -16,7 +16,6 @@ // limitations under the License. use super::helper; -use core::convert::TryFrom; use frame_support_procedural_tools::get_doc_literals; use quote::ToTokens; use syn::spanned::Spanned; diff --git a/frame/support/src/storage/bounded_btree_map.rs b/frame/support/src/storage/bounded_btree_map.rs index 404814cb8169..7a59206aeba0 100644 --- a/frame/support/src/storage/bounded_btree_map.rs +++ b/frame/support/src/storage/bounded_btree_map.rs @@ -307,7 +307,6 @@ pub mod test { use super::*; use crate::Twox128; use sp_io::TestExternalities; - use sp_std::convert::TryInto; crate::parameter_types! { pub const Seven: u32 = 7; diff --git a/frame/support/src/storage/bounded_vec.rs b/frame/support/src/storage/bounded_vec.rs index e51c6cd73411..3b5e7bda1651 100644 --- a/frame/support/src/storage/bounded_vec.rs +++ b/frame/support/src/storage/bounded_vec.rs @@ -28,7 +28,7 @@ use core::{ ops::{Deref, Index, IndexMut}, slice::SliceIndex, }; -use sp_std::{convert::TryFrom, marker::PhantomData, prelude::*}; +use sp_std::{marker::PhantomData, prelude::*}; /// A bounded vector. /// @@ -349,7 +349,6 @@ pub mod test { use super::*; use crate::Twox128; use sp_io::TestExternalities; - use sp_std::convert::TryInto; crate::parameter_types! { pub const Seven: u32 = 7; diff --git a/frame/support/src/storage/mod.rs b/frame/support/src/storage/mod.rs index 35552e08fef1..69445932b869 100644 --- a/frame/support/src/storage/mod.rs +++ b/frame/support/src/storage/mod.rs @@ -1400,7 +1400,6 @@ mod test { use super::*; use crate::{assert_ok, hash::Identity, Twox128}; use bounded_vec::BoundedVec; - use core::convert::{TryFrom, TryInto}; use generator::StorageValue as _; use sp_core::hashing::twox_128; use sp_io::TestExternalities; diff --git a/frame/system/src/offchain.rs b/frame/system/src/offchain.rs index ed758a2556b7..c4986e67319f 100644 --- a/frame/system/src/offchain.rs +++ b/frame/system/src/offchain.rs @@ -62,11 +62,7 @@ use sp_runtime::{ app_crypto::RuntimeAppPublic, traits::{Extrinsic as ExtrinsicT, IdentifyAccount, One}, }; -use sp_std::{ - collections::btree_set::BTreeSet, - convert::{TryFrom, TryInto}, - prelude::{Box, Vec}, -}; +use sp_std::{collections::btree_set::BTreeSet, prelude::*}; /// Marker struct used to flag using all supported keys to sign a payload. pub struct ForAll {} diff --git a/frame/transaction-payment/rpc/src/lib.rs b/frame/transaction-payment/rpc/src/lib.rs index 945156d12a6a..78230ee6e468 100644 --- a/frame/transaction-payment/rpc/src/lib.rs +++ b/frame/transaction-payment/rpc/src/lib.rs @@ -31,7 +31,7 @@ use sp_runtime::{ generic::BlockId, traits::{Block as BlockT, MaybeDisplay}, }; -use std::{convert::TryInto, sync::Arc}; +use std::sync::Arc; #[rpc] pub trait TransactionPaymentApi { diff --git a/frame/transaction-payment/src/lib.rs b/frame/transaction-payment/src/lib.rs index 59d94a823723..64cd5d529063 100644 --- a/frame/transaction-payment/src/lib.rs +++ b/frame/transaction-payment/src/lib.rs @@ -347,7 +347,6 @@ pub mod pallet { // given weight == u64, we build multipliers from `diff` of two weight values, which can // at most be maximum block weight. Make sure that this can fit in a multiplier without // loss. - use sp_std::convert::TryInto; assert!( ::max_value() >= Multiplier::checked_from_integer( diff --git a/frame/uniques/src/impl_nonfungibles.rs b/frame/uniques/src/impl_nonfungibles.rs index e68d2d4deecd..5394f02160e3 100644 --- a/frame/uniques/src/impl_nonfungibles.rs +++ b/frame/uniques/src/impl_nonfungibles.rs @@ -23,7 +23,7 @@ use frame_support::{ BoundedSlice, }; use sp_runtime::{DispatchError, DispatchResult}; -use sp_std::convert::TryFrom; +use sp_std::prelude::*; impl, I: 'static> Inspect<::AccountId> for Pallet { type InstanceId = T::InstanceId; diff --git a/frame/uniques/src/tests.rs b/frame/uniques/src/tests.rs index 8a4f978b7f4f..d23d694e949e 100644 --- a/frame/uniques/src/tests.rs +++ b/frame/uniques/src/tests.rs @@ -21,7 +21,7 @@ use super::*; use crate::mock::*; use frame_support::{assert_noop, assert_ok, traits::Currency}; use pallet_balances::Error as BalancesError; -use sp_std::convert::TryInto; +use sp_std::prelude::*; fn assets() -> Vec<(u64, u32, u32)> { let mut r: Vec<_> = Account::::iter().map(|x| x.0).collect(); diff --git a/primitives/std/src/lib.rs b/primitives/std/src/lib.rs index 3af4d07ac629..3d112a18edd0 100644 --- a/primitives/std/src/lib.rs +++ b/primitives/std/src/lib.rs @@ -98,6 +98,8 @@ pub mod prelude { boxed::Box, clone::Clone, cmp::{Eq, PartialEq, Reverse}, + convert::{TryFrom, TryInto}, + iter::IntoIterator, vec::Vec, }; diff --git a/utils/frame/benchmarking-cli/src/writer.rs b/utils/frame/benchmarking-cli/src/writer.rs index ede5b2d1355a..e7e8b42fd8a6 100644 --- a/utils/frame/benchmarking-cli/src/writer.rs +++ b/utils/frame/benchmarking-cli/src/writer.rs @@ -17,7 +17,6 @@ // Outputs benchmark results to Rust files that can be ingested by the runtime. -use core::convert::TryInto; use std::{ collections::{HashMap, HashSet}, fs, diff --git a/utils/frame/frame-utilities-cli/src/pallet_id.rs b/utils/frame/frame-utilities-cli/src/pallet_id.rs index d173f52b39cd..e4acdb2182f0 100644 --- a/utils/frame/frame-utilities-cli/src/pallet_id.rs +++ b/utils/frame/frame-utilities-cli/src/pallet_id.rs @@ -24,7 +24,6 @@ use sc_cli::{ }; use sp_core::crypto::{unwrap_or_default_ss58_version, Ss58AddressFormat, Ss58Codec}; use sp_runtime::traits::AccountIdConversion; -use std::convert::{TryFrom, TryInto}; use structopt::StructOpt; /// The `palletid` command From 2cc0e23254acaa81c0890dd3fee734131aa7da82 Mon Sep 17 00:00:00 2001 From: Liu-Cheng Xu Date: Mon, 8 Nov 2021 07:29:51 +0800 Subject: [PATCH 147/695] Add serde support for `Slot` type (#10204) Add serde support for the `Slot` type as we'd like to use it directly in our RPC. --- Cargo.lock | 1 + primitives/consensus/slots/Cargo.toml | 2 ++ primitives/consensus/slots/src/lib.rs | 1 + 3 files changed, 4 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index eeb1012b1d1d..63a2d26db34e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9325,6 +9325,7 @@ version = "0.10.0-dev" dependencies = [ "parity-scale-codec", "scale-info", + "serde", "sp-arithmetic", "sp-runtime", ] diff --git a/primitives/consensus/slots/Cargo.toml b/primitives/consensus/slots/Cargo.toml index ad83835e0270..9177157bd5ed 100644 --- a/primitives/consensus/slots/Cargo.toml +++ b/primitives/consensus/slots/Cargo.toml @@ -15,6 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } +serde = { version = "1.0", features = ["derive"], optional = true } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../runtime" } sp-arithmetic = { version = "4.0.0-dev", default-features = false, path = "../../arithmetic" } @@ -23,6 +24,7 @@ default = ["std"] std = [ "codec/std", "scale-info/std", + "serde", "sp-runtime/std", "sp-arithmetic/std", ] diff --git a/primitives/consensus/slots/src/lib.rs b/primitives/consensus/slots/src/lib.rs index 89b57dca8308..72b3c95068e3 100644 --- a/primitives/consensus/slots/src/lib.rs +++ b/primitives/consensus/slots/src/lib.rs @@ -24,6 +24,7 @@ use scale_info::TypeInfo; /// Unit type wrapper that represents a slot. #[derive(Debug, Encode, MaxEncodedLen, Decode, Eq, Clone, Copy, Default, Ord, TypeInfo)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] pub struct Slot(u64); impl core::ops::Deref for Slot { From a524cfd579b5cfa00ee7aea475a3a08cb42dc160 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Nov 2021 00:31:11 +0100 Subject: [PATCH 148/695] Bump lru from 0.6.6 to 0.7.0 (#10194) Bumps [lru](https://github.com/jeromefroe/lru-rs) from 0.6.6 to 0.7.0. - [Release notes](https://github.com/jeromefroe/lru-rs/releases) - [Changelog](https://github.com/jeromefroe/lru-rs/blob/master/CHANGELOG.md) - [Commits](https://github.com/jeromefroe/lru-rs/compare/0.6.6...0.7.0) --- updated-dependencies: - dependency-name: lru dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 17 +++++++++++++---- client/network-gossip/Cargo.toml | 2 +- client/network/Cargo.toml | 2 +- primitives/blockchain/Cargo.toml | 2 +- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 63a2d26db34e..4794c1c0f5c4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3665,7 +3665,7 @@ dependencies = [ "libp2p-core", "libp2p-swarm", "log 0.4.14", - "lru", + "lru 0.6.6", "minicbor", "rand 0.7.3", "smallvec 1.7.0", @@ -3999,6 +3999,15 @@ dependencies = [ "hashbrown 0.11.2", ] +[[package]] +name = "lru" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c748cfe47cb8da225c37595b3108bea1c198c84aaae8ea0ba76d01dda9fc803" +dependencies = [ + "hashbrown 0.11.2", +] + [[package]] name = "lru-cache" version = "0.1.2" @@ -8203,7 +8212,7 @@ dependencies = [ "linked-hash-map", "linked_hash_set", "log 0.4.14", - "lru", + "lru 0.7.0", "parity-scale-codec", "parking_lot 0.11.1", "pin-project 1.0.8", @@ -8246,7 +8255,7 @@ dependencies = [ "futures-timer 3.0.2", "libp2p", "log 0.4.14", - "lru", + "lru 0.7.0", "quickcheck", "sc-network", "sp-runtime", @@ -9239,7 +9248,7 @@ version = "4.0.0-dev" dependencies = [ "futures 0.3.16", "log 0.4.14", - "lru", + "lru 0.7.0", "parity-scale-codec", "parking_lot 0.11.1", "sp-api", diff --git a/client/network-gossip/Cargo.toml b/client/network-gossip/Cargo.toml index 1f0b5c313294..e17d9601eafc 100644 --- a/client/network-gossip/Cargo.toml +++ b/client/network-gossip/Cargo.toml @@ -19,7 +19,7 @@ futures = "0.3.9" futures-timer = "3.0.1" libp2p = { version = "0.39.1", default-features = false } log = "0.4.8" -lru = "0.6.6" +lru = "0.7.0" prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.9.0", path = "../../utils/prometheus" } sc-network = { version = "0.10.0-dev", path = "../network" } sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index 7c2905d5fe03..19ae5dd97e42 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -36,7 +36,7 @@ hex = "0.4.0" ip_network = "0.4.0" linked-hash-map = "0.5.4" linked_hash_set = "0.1.3" -lru = "0.6.6" +lru = "0.7.0" log = "0.4.8" parking_lot = "0.11.1" pin-project = "1.0.8" diff --git a/primitives/blockchain/Cargo.toml b/primitives/blockchain/Cargo.toml index 7af7807954ef..de73af10966e 100644 --- a/primitives/blockchain/Cargo.toml +++ b/primitives/blockchain/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] log = "0.4.11" -lru = "0.6.6" +lru = "0.7.0" parking_lot = "0.11.1" thiserror = "1.0.21" futures = "0.3.9" From e1c30d92f5bda94a44ba461d914fd4b21fa7c07e Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Mon, 8 Nov 2021 10:42:48 +0100 Subject: [PATCH 149/695] Speedup block import (#10211) --- client/service/src/chain_ops/import_blocks.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/service/src/chain_ops/import_blocks.rs b/client/service/src/chain_ops/import_blocks.rs index a408a06a8170..e4096afacdd3 100644 --- a/client/service/src/chain_ops/import_blocks.rs +++ b/client/service/src/chain_ops/import_blocks.rs @@ -43,10 +43,10 @@ use std::{ }; /// Number of blocks we will add to the queue before waiting for the queue to catch up. -const MAX_PENDING_BLOCKS: u64 = 1_024; +const MAX_PENDING_BLOCKS: u64 = 10_000; /// Number of milliseconds to wait until next poll. -const DELAY_TIME: u64 = 2_000; +const DELAY_TIME: u64 = 200; /// Number of milliseconds that must have passed between two updates. const TIME_BETWEEN_UPDATES: u64 = 3_000; From 3b2ce548c6e00183ab12ab086859325164263584 Mon Sep 17 00:00:00 2001 From: Koute Date: Mon, 8 Nov 2021 21:52:11 +0900 Subject: [PATCH 150/695] Refactor `sp-sandbox`; make sure both sandbox executors are always tested (#10173) * sp-sandbox: convert executors into normal `mod`s instead of using `include!` * sp-sandbox: run `cargo fmt` on `host_executor.rs` * sp-sandbox: abstract away the executors behind traits * sp_sandbox: always compile both executors when possible * sc-executor: make sure all sandbox tests run on both sandbox executors * sc-executor: fix brainfart: actually call into the sandbox through the trait * sc-runtime-test: fix cargo fmt * sc-runtime-test: deduplicate executor-specific sandbox test entrypoints * sc-executor: test each sandbox executor in a separate test * cargo fmt (Github's conflict resolving thingy broke indentation) --- Cargo.lock | 1 + client/executor/runtime-test/Cargo.toml | 1 + client/executor/runtime-test/src/lib.rs | 172 +++++++++++------- client/executor/src/integration_tests/mod.rs | 47 +++++ .../executor/src/integration_tests/sandbox.rs | 108 +++++++---- frame/contracts/src/benchmarking/code.rs | 5 +- frame/contracts/src/benchmarking/sandbox.rs | 5 +- frame/contracts/src/wasm/mod.rs | 9 +- frame/contracts/src/wasm/runtime.rs | 9 +- .../sandbox/{ => src}/embedded_executor.rs | 40 ++-- primitives/sandbox/{ => src}/host_executor.rs | 91 +++++---- primitives/sandbox/src/lib.rs | 89 ++++----- 12 files changed, 350 insertions(+), 227 deletions(-) rename primitives/sandbox/{ => src}/embedded_executor.rs (90%) rename primitives/sandbox/{ => src}/host_executor.rs (78%) diff --git a/Cargo.lock b/Cargo.lock index 4794c1c0f5c4..4b6cc99426b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8429,6 +8429,7 @@ dependencies = [ name = "sc-runtime-test" version = "2.0.0" dependencies = [ + "paste 1.0.4", "sp-core", "sp-io", "sp-runtime", diff --git a/client/executor/runtime-test/Cargo.toml b/client/executor/runtime-test/Cargo.toml index 1e3b5e926b96..2c82a9705cee 100644 --- a/client/executor/runtime-test/Cargo.toml +++ b/client/executor/runtime-test/Cargo.toml @@ -19,6 +19,7 @@ sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../.. sp-sandbox = { version = "0.10.0-dev", default-features = false, path = "../../../primitives/sandbox" } sp-std = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/std" } sp-tasks = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/tasks" } +paste = "1.0.4" [build-dependencies] substrate-wasm-builder = { version = "5.0.0-dev", path = "../../../utils/wasm-builder" } diff --git a/client/executor/runtime-test/src/lib.rs b/client/executor/runtime-test/src/lib.rs index 2b5699fa3f77..3ea6e2d7ed1a 100644 --- a/client/executor/runtime-test/src/lib.rs +++ b/client/executor/runtime-test/src/lib.rs @@ -30,7 +30,7 @@ use sp_runtime::{ traits::{BlakeTwo256, Hash}, }; #[cfg(not(feature = "std"))] -use sp_sandbox::Value; +use sp_sandbox::{SandboxEnvironmentBuilder, SandboxInstance, SandboxMemory, Value}; extern "C" { #[allow(dead_code)] @@ -183,61 +183,6 @@ sp_core::wasm_export_functions! { ).as_ref().to_vec() } - fn test_sandbox(code: Vec) -> bool { - execute_sandboxed(&code, &[]).is_ok() - } - - fn test_sandbox_args(code: Vec) -> bool { - execute_sandboxed( - &code, - &[ - Value::I32(0x12345678), - Value::I64(0x1234567887654321), - ], - ).is_ok() - } - - fn test_sandbox_return_val(code: Vec) -> bool { - let ok = match execute_sandboxed( - &code, - &[ - Value::I32(0x1336), - ] - ) { - Ok(sp_sandbox::ReturnValue::Value(Value::I32(0x1337))) => true, - _ => false, - }; - - ok - } - - fn test_sandbox_instantiate(code: Vec) -> u8 { - let env_builder = sp_sandbox::EnvironmentDefinitionBuilder::new(); - let code = match sp_sandbox::Instance::new(&code, &env_builder, &mut ()) { - Ok(_) => 0, - Err(sp_sandbox::Error::Module) => 1, - Err(sp_sandbox::Error::Execution) => 2, - Err(sp_sandbox::Error::OutOfBounds) => 3, - }; - - code - } - - fn test_sandbox_get_global_val(code: Vec) -> i64 { - let env_builder = sp_sandbox::EnvironmentDefinitionBuilder::new(); - let instance = if let Ok(i) = sp_sandbox::Instance::new(&code, &env_builder, &mut ()) { - i - } else { - return 20; - }; - - match instance.get_global_val("test_global") { - Some(sp_sandbox::Value::I64(val)) => val, - None => 30, - _ => 40, - } - } - fn test_offchain_index_set() { sp_io::offchain_index::set(b"k", b"v"); } @@ -408,15 +353,112 @@ mod tasks { } } +/// A macro to define a test entrypoint for each available sandbox executor. +macro_rules! wasm_export_sandbox_test_functions { + ( + $( + fn $name:ident( + $( $arg_name:ident: $arg_ty:ty ),* $(,)? + ) $( -> $ret_ty:ty )? where T: SandboxInstance<$state:ty> $(,)? + { $( $fn_impl:tt )* } + )* + ) => { + $( + #[cfg(not(feature = "std"))] + fn $name( $($arg_name: $arg_ty),* ) $( -> $ret_ty )? where T: SandboxInstance<$state> { + $( $fn_impl )* + } + + paste::paste! { + sp_core::wasm_export_functions! { + fn [<$name _host>]( $($arg_name: $arg_ty),* ) $( -> $ret_ty )? { + $name::>( $( $arg_name ),* ) + } + + fn [<$name _embedded>]( $($arg_name: $arg_ty),* ) $( -> $ret_ty )? { + $name::>( $( $arg_name ),* ) + } + } + } + )* + }; +} + +wasm_export_sandbox_test_functions! { + fn test_sandbox(code: Vec) -> bool + where + T: SandboxInstance, + { + execute_sandboxed::(&code, &[]).is_ok() + } + + fn test_sandbox_args(code: Vec) -> bool + where + T: SandboxInstance, + { + execute_sandboxed::(&code, &[Value::I32(0x12345678), Value::I64(0x1234567887654321)]) + .is_ok() + } + + fn test_sandbox_return_val(code: Vec) -> bool + where + T: SandboxInstance, + { + let ok = match execute_sandboxed::(&code, &[Value::I32(0x1336)]) { + Ok(sp_sandbox::ReturnValue::Value(Value::I32(0x1337))) => true, + _ => false, + }; + + ok + } + + fn test_sandbox_instantiate(code: Vec) -> u8 + where + T: SandboxInstance<()>, + { + let env_builder = T::EnvironmentBuilder::new(); + let code = match T::new(&code, &env_builder, &mut ()) { + Ok(_) => 0, + Err(sp_sandbox::Error::Module) => 1, + Err(sp_sandbox::Error::Execution) => 2, + Err(sp_sandbox::Error::OutOfBounds) => 3, + }; + + code + } + + fn test_sandbox_get_global_val(code: Vec) -> i64 + where + T: SandboxInstance<()>, + { + let env_builder = T::EnvironmentBuilder::new(); + let instance = if let Ok(i) = T::new(&code, &env_builder, &mut ()) { + i + } else { + return 20 + }; + + match instance.get_global_val("test_global") { + Some(sp_sandbox::Value::I64(val)) => val, + None => 30, + _ => 40, + } + } +} + #[cfg(not(feature = "std"))] -fn execute_sandboxed( +struct State { + counter: u32, +} + +#[cfg(not(feature = "std"))] +fn execute_sandboxed( code: &[u8], args: &[Value], -) -> Result { - struct State { - counter: u32, - } - +) -> Result +where + T: sp_sandbox::SandboxInstance, +{ fn env_assert( _e: &mut State, args: &[Value], @@ -446,10 +488,10 @@ fn execute_sandboxed( let mut state = State { counter: 0 }; let env_builder = { - let mut env_builder = sp_sandbox::EnvironmentDefinitionBuilder::new(); + let mut env_builder = T::EnvironmentBuilder::new(); env_builder.add_host_func("env", "assert", env_assert); env_builder.add_host_func("env", "inc_counter", env_inc_counter); - let memory = match sp_sandbox::Memory::new(1, Some(16)) { + let memory = match T::Memory::new(1, Some(16)) { Ok(m) => m, Err(_) => unreachable!( " @@ -462,7 +504,7 @@ fn execute_sandboxed( env_builder }; - let mut instance = sp_sandbox::Instance::new(code, &env_builder, &mut state)?; + let mut instance = T::new(code, &env_builder, &mut state)?; let result = instance.invoke("call", args, &mut state); result.map_err(|_| sp_sandbox::HostError) diff --git a/client/executor/src/integration_tests/mod.rs b/client/executor/src/integration_tests/mod.rs index fe964f47ba37..1cded769c685 100644 --- a/client/executor/src/integration_tests/mod.rs +++ b/client/executor/src/integration_tests/mod.rs @@ -71,6 +71,53 @@ macro_rules! test_wasm_execution { }; } +/// A macro to run a given test for each available WASM execution method *and* for each +/// sandbox execution method. +#[macro_export] +macro_rules! test_wasm_execution_sandbox { + ($method_name:ident) => { + paste::item! { + #[test] + fn [<$method_name _interpreted_host_executor>]() { + $method_name(WasmExecutionMethod::Interpreted, "_host"); + } + + #[test] + fn [<$method_name _interpreted_embedded_executor>]() { + $method_name(WasmExecutionMethod::Interpreted, "_embedded"); + } + + #[test] + #[cfg(feature = "wasmtime")] + fn [<$method_name _compiled_host_executor>]() { + $method_name(WasmExecutionMethod::Compiled, "_host"); + } + + #[test] + #[cfg(feature = "wasmtime")] + fn [<$method_name _compiled_embedded_executor>]() { + $method_name(WasmExecutionMethod::Compiled, "_embedded"); + } + } + }; + + (interpreted_only $method_name:ident) => { + paste::item! { + #[test] + fn [<$method_name _interpreted_host_executor>]() { + $method_name(WasmExecutionMethod::Interpreted, "_host"); + } + } + + paste::item! { + #[test] + fn [<$method_name _interpreted_embedded_executor>]() { + $method_name(WasmExecutionMethod::Interpreted, "_embedded"); + } + } + }; +} + fn call_in_wasm( function: &str, call_data: &[u8], diff --git a/client/executor/src/integration_tests/sandbox.rs b/client/executor/src/integration_tests/sandbox.rs index aacd493297cc..2b536f541f08 100644 --- a/client/executor/src/integration_tests/sandbox.rs +++ b/client/executor/src/integration_tests/sandbox.rs @@ -17,12 +17,12 @@ // along with this program. If not, see . use super::{call_in_wasm, TestExternalities}; -use crate::{test_wasm_execution, WasmExecutionMethod}; +use crate::{test_wasm_execution_sandbox, WasmExecutionMethod}; use codec::Encode; -test_wasm_execution!(sandbox_should_work); -fn sandbox_should_work(wasm_method: WasmExecutionMethod) { +test_wasm_execution_sandbox!(sandbox_should_work); +fn sandbox_should_work(wasm_method: WasmExecutionMethod, fn_suffix: &str) { let mut ext = TestExternalities::default(); let mut ext = ext.ext(); @@ -51,11 +51,14 @@ fn sandbox_should_work(wasm_method: WasmExecutionMethod) { .unwrap() .encode(); - assert_eq!(call_in_wasm("test_sandbox", &code, wasm_method, &mut ext).unwrap(), true.encode()); + assert_eq!( + call_in_wasm(&format!("test_sandbox{}", fn_suffix), &code, wasm_method, &mut ext).unwrap(), + true.encode() + ); } -test_wasm_execution!(sandbox_trap); -fn sandbox_trap(wasm_method: WasmExecutionMethod) { +test_wasm_execution_sandbox!(sandbox_trap); +fn sandbox_trap(wasm_method: WasmExecutionMethod, fn_suffix: &str) { let mut ext = TestExternalities::default(); let mut ext = ext.ext(); @@ -72,11 +75,14 @@ fn sandbox_trap(wasm_method: WasmExecutionMethod) { ) .unwrap(); - assert_eq!(call_in_wasm("test_sandbox", &code, wasm_method, &mut ext).unwrap(), vec![0]); + assert_eq!( + call_in_wasm(&format!("test_sandbox{}", fn_suffix), &code, wasm_method, &mut ext).unwrap(), + vec![0] + ); } -test_wasm_execution!(start_called); -fn start_called(wasm_method: WasmExecutionMethod) { +test_wasm_execution_sandbox!(start_called); +fn start_called(wasm_method: WasmExecutionMethod, fn_suffix: &str) { let mut ext = TestExternalities::default(); let mut ext = ext.ext(); @@ -111,11 +117,14 @@ fn start_called(wasm_method: WasmExecutionMethod) { .unwrap() .encode(); - assert_eq!(call_in_wasm("test_sandbox", &code, wasm_method, &mut ext).unwrap(), true.encode()); + assert_eq!( + call_in_wasm(&format!("test_sandbox{}", fn_suffix), &code, wasm_method, &mut ext).unwrap(), + true.encode() + ); } -test_wasm_execution!(invoke_args); -fn invoke_args(wasm_method: WasmExecutionMethod) { +test_wasm_execution_sandbox!(invoke_args); +fn invoke_args(wasm_method: WasmExecutionMethod, fn_suffix: &str) { let mut ext = TestExternalities::default(); let mut ext = ext.ext(); @@ -147,13 +156,14 @@ fn invoke_args(wasm_method: WasmExecutionMethod) { .encode(); assert_eq!( - call_in_wasm("test_sandbox_args", &code, wasm_method, &mut ext,).unwrap(), + call_in_wasm(&format!("test_sandbox_args{}", fn_suffix), &code, wasm_method, &mut ext,) + .unwrap(), true.encode(), ); } -test_wasm_execution!(return_val); -fn return_val(wasm_method: WasmExecutionMethod) { +test_wasm_execution_sandbox!(return_val); +fn return_val(wasm_method: WasmExecutionMethod, fn_suffix: &str) { let mut ext = TestExternalities::default(); let mut ext = ext.ext(); @@ -173,13 +183,19 @@ fn return_val(wasm_method: WasmExecutionMethod) { .encode(); assert_eq!( - call_in_wasm("test_sandbox_return_val", &code, wasm_method, &mut ext,).unwrap(), + call_in_wasm( + &format!("test_sandbox_return_val{}", fn_suffix), + &code, + wasm_method, + &mut ext, + ) + .unwrap(), true.encode(), ); } -test_wasm_execution!(unlinkable_module); -fn unlinkable_module(wasm_method: WasmExecutionMethod) { +test_wasm_execution_sandbox!(unlinkable_module); +fn unlinkable_module(wasm_method: WasmExecutionMethod, fn_suffix: &str) { let mut ext = TestExternalities::default(); let mut ext = ext.ext(); @@ -197,13 +213,19 @@ fn unlinkable_module(wasm_method: WasmExecutionMethod) { .encode(); assert_eq!( - call_in_wasm("test_sandbox_instantiate", &code, wasm_method, &mut ext,).unwrap(), + call_in_wasm( + &format!("test_sandbox_instantiate{}", fn_suffix), + &code, + wasm_method, + &mut ext, + ) + .unwrap(), 1u8.encode(), ); } -test_wasm_execution!(corrupted_module); -fn corrupted_module(wasm_method: WasmExecutionMethod) { +test_wasm_execution_sandbox!(corrupted_module); +fn corrupted_module(wasm_method: WasmExecutionMethod, fn_suffix: &str) { let mut ext = TestExternalities::default(); let mut ext = ext.ext(); @@ -211,13 +233,19 @@ fn corrupted_module(wasm_method: WasmExecutionMethod) { let code = vec![0u8, 0, 0, 0, 1, 0, 0, 0].encode(); assert_eq!( - call_in_wasm("test_sandbox_instantiate", &code, wasm_method, &mut ext,).unwrap(), + call_in_wasm( + &format!("test_sandbox_instantiate{}", fn_suffix), + &code, + wasm_method, + &mut ext, + ) + .unwrap(), 1u8.encode(), ); } -test_wasm_execution!(start_fn_ok); -fn start_fn_ok(wasm_method: WasmExecutionMethod) { +test_wasm_execution_sandbox!(start_fn_ok); +fn start_fn_ok(wasm_method: WasmExecutionMethod, fn_suffix: &str) { let mut ext = TestExternalities::default(); let mut ext = ext.ext(); @@ -238,13 +266,19 @@ fn start_fn_ok(wasm_method: WasmExecutionMethod) { .encode(); assert_eq!( - call_in_wasm("test_sandbox_instantiate", &code, wasm_method, &mut ext,).unwrap(), + call_in_wasm( + &format!("test_sandbox_instantiate{}", fn_suffix), + &code, + wasm_method, + &mut ext, + ) + .unwrap(), 0u8.encode(), ); } -test_wasm_execution!(start_fn_traps); -fn start_fn_traps(wasm_method: WasmExecutionMethod) { +test_wasm_execution_sandbox!(start_fn_traps); +fn start_fn_traps(wasm_method: WasmExecutionMethod, fn_suffix: &str) { let mut ext = TestExternalities::default(); let mut ext = ext.ext(); @@ -266,13 +300,19 @@ fn start_fn_traps(wasm_method: WasmExecutionMethod) { .encode(); assert_eq!( - call_in_wasm("test_sandbox_instantiate", &code, wasm_method, &mut ext,).unwrap(), + call_in_wasm( + &format!("test_sandbox_instantiate{}", fn_suffix), + &code, + wasm_method, + &mut ext, + ) + .unwrap(), 2u8.encode(), ); } -test_wasm_execution!(get_global_val_works); -fn get_global_val_works(wasm_method: WasmExecutionMethod) { +test_wasm_execution_sandbox!(get_global_val_works); +fn get_global_val_works(wasm_method: WasmExecutionMethod, fn_suffix: &str) { let mut ext = TestExternalities::default(); let mut ext = ext.ext(); @@ -287,7 +327,13 @@ fn get_global_val_works(wasm_method: WasmExecutionMethod) { .encode(); assert_eq!( - call_in_wasm("test_sandbox_get_global_val", &code, wasm_method, &mut ext,).unwrap(), + call_in_wasm( + &format!("test_sandbox_get_global_val{}", fn_suffix), + &code, + wasm_method, + &mut ext, + ) + .unwrap(), 500i64.encode(), ); } diff --git a/frame/contracts/src/benchmarking/code.rs b/frame/contracts/src/benchmarking/code.rs index 6b90381e7d35..98f52f4719a6 100644 --- a/frame/contracts/src/benchmarking/code.rs +++ b/frame/contracts/src/benchmarking/code.rs @@ -35,7 +35,10 @@ use pwasm_utils::parity_wasm::{ }; use sp_core::crypto::UncheckedFrom; use sp_runtime::traits::Hash; -use sp_sandbox::{EnvironmentDefinitionBuilder, Memory}; +use sp_sandbox::{ + default_executor::{EnvironmentDefinitionBuilder, Memory}, + SandboxEnvironmentBuilder, SandboxMemory, +}; use sp_std::{borrow::ToOwned, prelude::*}; /// Pass to `create_code` in order to create a compiled `WasmModule`. diff --git a/frame/contracts/src/benchmarking/sandbox.rs b/frame/contracts/src/benchmarking/sandbox.rs index 320ac90cce64..4412542b547d 100644 --- a/frame/contracts/src/benchmarking/sandbox.rs +++ b/frame/contracts/src/benchmarking/sandbox.rs @@ -20,7 +20,10 @@ /// ! environment that provides the seal interface as imported functions. use super::{code::WasmModule, Config}; use sp_core::crypto::UncheckedFrom; -use sp_sandbox::{EnvironmentDefinitionBuilder, Instance, Memory}; +use sp_sandbox::{ + default_executor::{EnvironmentDefinitionBuilder, Instance, Memory}, + SandboxEnvironmentBuilder, SandboxInstance, +}; /// Minimal execution environment without any exported functions. pub struct Sandbox { diff --git a/frame/contracts/src/wasm/mod.rs b/frame/contracts/src/wasm/mod.rs index 565a424323ac..10aa0d19a04f 100644 --- a/frame/contracts/src/wasm/mod.rs +++ b/frame/contracts/src/wasm/mod.rs @@ -36,6 +36,7 @@ use crate::{ use codec::{Decode, Encode}; use frame_support::dispatch::DispatchError; use sp_core::crypto::UncheckedFrom; +use sp_sandbox::{SandboxEnvironmentBuilder, SandboxInstance, SandboxMemory}; use sp_std::prelude::*; #[cfg(test)] pub use tests::MockExt; @@ -182,8 +183,8 @@ where function: &ExportedFunction, input_data: Vec, ) -> ExecResult { - let memory = - sp_sandbox::Memory::new(self.initial, Some(self.maximum)).unwrap_or_else(|_| { + let memory = sp_sandbox::default_executor::Memory::new(self.initial, Some(self.maximum)) + .unwrap_or_else(|_| { // unlike `.expect`, explicit panic preserves the source location. // Needed as we can't use `RUST_BACKTRACE` in here. panic!( @@ -193,7 +194,7 @@ where ) }); - let mut imports = sp_sandbox::EnvironmentDefinitionBuilder::new(); + let mut imports = sp_sandbox::default_executor::EnvironmentDefinitionBuilder::new(); imports.add_memory(self::prepare::IMPORT_MODULE_MEMORY, "memory", memory.clone()); runtime::Env::impls(&mut |module, name, func_ptr| { imports.add_host_func(module, name, func_ptr); @@ -209,7 +210,7 @@ where // Instantiate the instance from the instrumented module code and invoke the contract // entrypoint. - let result = sp_sandbox::Instance::new(&code, &imports, &mut runtime) + let result = sp_sandbox::default_executor::Instance::new(&code, &imports, &mut runtime) .and_then(|mut instance| instance.invoke(function.identifier(), &[], &mut runtime)); runtime.to_execution_result(result) diff --git a/frame/contracts/src/wasm/runtime.rs b/frame/contracts/src/wasm/runtime.rs index 52b864bf18ea..883dfd080248 100644 --- a/frame/contracts/src/wasm/runtime.rs +++ b/frame/contracts/src/wasm/runtime.rs @@ -32,6 +32,7 @@ use pwasm_utils::parity_wasm::elements::ValueType; use sp_core::{crypto::UncheckedFrom, Bytes}; use sp_io::hashing::{blake2_128, blake2_256, keccak_256, sha2_256}; use sp_runtime::traits::Bounded; +use sp_sandbox::SandboxMemory; use sp_std::prelude::*; /// Every error that can be returned to a contract when it calls any of the host functions. @@ -357,7 +358,7 @@ fn already_charged(_: u32) -> Option { pub struct Runtime<'a, E: Ext + 'a> { ext: &'a mut E, input_data: Option>, - memory: sp_sandbox::Memory, + memory: sp_sandbox::default_executor::Memory, trap_reason: Option, } @@ -367,7 +368,11 @@ where ::AccountId: UncheckedFrom<::Hash> + AsRef<[u8]>, { - pub fn new(ext: &'a mut E, input_data: Vec, memory: sp_sandbox::Memory) -> Self { + pub fn new( + ext: &'a mut E, + input_data: Vec, + memory: sp_sandbox::default_executor::Memory, + ) -> Self { Runtime { ext, input_data: Some(input_data), memory, trap_reason: None } } diff --git a/primitives/sandbox/embedded_executor.rs b/primitives/sandbox/src/embedded_executor.rs similarity index 90% rename from primitives/sandbox/embedded_executor.rs rename to primitives/sandbox/src/embedded_executor.rs index 678da3c3aeaf..c521ff2cb63f 100755 --- a/primitives/sandbox/embedded_executor.rs +++ b/primitives/sandbox/src/embedded_executor.rs @@ -15,6 +15,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +//! An embedded WASM executor utilizing `wasmi`. + use super::{Error, HostError, HostFuncType, ReturnValue, Value, TARGET}; use alloc::string::String; use log::debug; @@ -27,13 +29,14 @@ use wasmi::{ RuntimeArgs, RuntimeValue, Signature, TableDescriptor, TableRef, Trap, TrapKind, }; +/// The linear memory used by the sandbox. #[derive(Clone)] pub struct Memory { memref: MemoryRef, } -impl Memory { - pub fn new(initial: u32, maximum: Option) -> Result { +impl super::SandboxMemory for Memory { + fn new(initial: u32, maximum: Option) -> Result { Ok(Memory { memref: MemoryInstance::alloc( Pages(initial as usize), @@ -43,12 +46,12 @@ impl Memory { }) } - pub fn get(&self, ptr: u32, buf: &mut [u8]) -> Result<(), Error> { + fn get(&self, ptr: u32, buf: &mut [u8]) -> Result<(), Error> { self.memref.get_into(ptr, buf).map_err(|_| Error::OutOfBounds)?; Ok(()) } - pub fn set(&self, ptr: u32, value: &[u8]) -> Result<(), Error> { + fn set(&self, ptr: u32, value: &[u8]) -> Result<(), Error> { self.memref.set(ptr, value).map_err(|_| Error::OutOfBounds)?; Ok(()) } @@ -118,20 +121,21 @@ enum ExternVal { Memory(Memory), } +/// A builder for the environment of the sandboxed WASM module. pub struct EnvironmentDefinitionBuilder { map: BTreeMap<(Vec, Vec), ExternVal>, defined_host_functions: DefinedHostFunctions, } -impl EnvironmentDefinitionBuilder { - pub fn new() -> EnvironmentDefinitionBuilder { +impl super::SandboxEnvironmentBuilder for EnvironmentDefinitionBuilder { + fn new() -> EnvironmentDefinitionBuilder { EnvironmentDefinitionBuilder { map: BTreeMap::new(), defined_host_functions: DefinedHostFunctions::new(), } } - pub fn add_host_func(&mut self, module: N1, field: N2, f: HostFuncType) + fn add_host_func(&mut self, module: N1, field: N2, f: HostFuncType) where N1: Into>, N2: Into>, @@ -140,7 +144,7 @@ impl EnvironmentDefinitionBuilder { self.map.insert((module.into(), field.into()), ExternVal::HostFunc(idx)); } - pub fn add_memory(&mut self, module: N1, field: N2, mem: Memory) + fn add_memory(&mut self, module: N1, field: N2, mem: Memory) where N1: Into>, N2: Into>, @@ -213,14 +217,18 @@ impl ImportResolver for EnvironmentDefinitionBuilder { } } +/// Sandboxed instance of a WASM module. pub struct Instance { instance: ModuleRef, defined_host_functions: DefinedHostFunctions, _marker: PhantomData, } -impl Instance { - pub fn new( +impl super::SandboxInstance for Instance { + type Memory = Memory; + type EnvironmentBuilder = EnvironmentDefinitionBuilder; + + fn new( code: &[u8], env_def_builder: &EnvironmentDefinitionBuilder, state: &mut T, @@ -241,12 +249,7 @@ impl Instance { Ok(Instance { instance, defined_host_functions, _marker: PhantomData:: }) } - pub fn invoke( - &mut self, - name: &str, - args: &[Value], - state: &mut T, - ) -> Result { + fn invoke(&mut self, name: &str, args: &[Value], state: &mut T) -> Result { let args = args.iter().cloned().map(to_wasmi).collect::>(); let mut externals = @@ -260,7 +263,7 @@ impl Instance { } } - pub fn get_global_val(&self, name: &str) -> Option { + fn get_global_val(&self, name: &str) -> Option { let global = self.instance.export_by_name(name)?.as_global()?.get(); Some(to_interface(global)) @@ -289,7 +292,8 @@ fn to_interface(value: RuntimeValue) -> Value { #[cfg(test)] mod tests { - use crate::{EnvironmentDefinitionBuilder, Error, HostError, Instance, ReturnValue, Value}; + use super::{EnvironmentDefinitionBuilder, Instance}; + use crate::{Error, HostError, ReturnValue, SandboxEnvironmentBuilder, SandboxInstance, Value}; use assert_matches::assert_matches; fn execute_sandboxed(code: &[u8], args: &[Value]) -> Result { diff --git a/primitives/sandbox/host_executor.rs b/primitives/sandbox/src/host_executor.rs similarity index 78% rename from primitives/sandbox/host_executor.rs rename to primitives/sandbox/src/host_executor.rs index d2836e2ffd1e..43484dd66a00 100755 --- a/primitives/sandbox/host_executor.rs +++ b/primitives/sandbox/src/host_executor.rs @@ -15,15 +15,17 @@ // See the License for the specific language governing permissions and // limitations under the License. +//! A WASM executor utilizing the sandbox runtime interface of the host. + +use super::{Error, HostFuncType, ReturnValue, Value}; use codec::{Decode, Encode}; use sp_core::sandbox as sandbox_primitives; use sp_io::sandbox; -use sp_std::{prelude::*, slice, marker, mem, vec, rc::Rc}; -use super::{Error, Value, ReturnValue, HostFuncType}; +use sp_std::{marker, mem, prelude::*, rc::Rc, slice, vec}; mod ffi { - use sp_std::mem; use super::HostFuncType; + use sp_std::mem; /// Index into the default table that points to a `HostFuncType`. pub type HostFuncIndex = usize; @@ -38,8 +40,9 @@ mod ffi { pub unsafe fn coerce_host_index_to_func(idx: HostFuncIndex) -> HostFuncType { // We need to ensure that sizes of a callable function pointer and host function index is // indeed equal. - // We can't use `static_assertions` create because it makes compiler panic, fallback to runtime assert. - // const_assert!(mem::size_of::() == mem::size_of::>()); + // We can't use `static_assertions` create because it makes compiler panic, fallback to + // runtime assert. const_assert!(mem::size_of::() == + // mem::size_of::>()); assert!(mem::size_of::() == mem::size_of::>()); mem::transmute::>(idx) } @@ -55,6 +58,7 @@ impl Drop for MemoryHandle { } } +/// The linear memory used by the sandbox. #[derive(Clone)] pub struct Memory { // Handle to memory instance is wrapped to add reference-counting semantics @@ -62,29 +66,20 @@ pub struct Memory { handle: Rc, } -impl Memory { - pub fn new(initial: u32, maximum: Option) -> Result { - let maximum = if let Some(maximum) = maximum { - maximum - } else { - sandbox_primitives::MEM_UNLIMITED - }; +impl super::SandboxMemory for Memory { + fn new(initial: u32, maximum: Option) -> Result { + let maximum = + if let Some(maximum) = maximum { maximum } else { sandbox_primitives::MEM_UNLIMITED }; match sandbox::memory_new(initial, maximum) { sandbox_primitives::ERR_MODULE => Err(Error::Module), - memory_idx => Ok(Memory { - handle: Rc::new(MemoryHandle { memory_idx, }), - }), + memory_idx => Ok(Memory { handle: Rc::new(MemoryHandle { memory_idx }) }), } } - pub fn get(&self, offset: u32, buf: &mut [u8]) -> Result<(), Error> { - let result = sandbox::memory_get( - self.handle.memory_idx, - offset, - buf.as_mut_ptr(), - buf.len() as u32, - ); + fn get(&self, offset: u32, buf: &mut [u8]) -> Result<(), Error> { + let result = + sandbox::memory_get(self.handle.memory_idx, offset, buf.as_mut_ptr(), buf.len() as u32); match result { sandbox_primitives::ERR_OK => Ok(()), sandbox_primitives::ERR_OUT_OF_BOUNDS => Err(Error::OutOfBounds), @@ -92,11 +87,11 @@ impl Memory { } } - pub fn set(&self, offset: u32, val: &[u8]) -> Result<(), Error> { + fn set(&self, offset: u32, val: &[u8]) -> Result<(), Error> { let result = sandbox::memory_set( self.handle.memory_idx, offset, - val.as_ptr() as _ , + val.as_ptr() as _, val.len() as u32, ); match result { @@ -107,6 +102,7 @@ impl Memory { } } +/// A builder for the environment of the sandboxed WASM module. pub struct EnvironmentDefinitionBuilder { env_def: sandbox_primitives::EnvironmentDefinition, retained_memories: Vec, @@ -114,16 +110,6 @@ pub struct EnvironmentDefinitionBuilder { } impl EnvironmentDefinitionBuilder { - pub fn new() -> EnvironmentDefinitionBuilder { - EnvironmentDefinitionBuilder { - env_def: sandbox_primitives::EnvironmentDefinition { - entries: Vec::new(), - }, - retained_memories: Vec::new(), - _marker: marker::PhantomData::, - } - } - fn add_entry( &mut self, module: N1, @@ -140,8 +126,18 @@ impl EnvironmentDefinitionBuilder { }; self.env_def.entries.push(entry); } +} - pub fn add_host_func(&mut self, module: N1, field: N2, f: HostFuncType) +impl super::SandboxEnvironmentBuilder for EnvironmentDefinitionBuilder { + fn new() -> EnvironmentDefinitionBuilder { + EnvironmentDefinitionBuilder { + env_def: sandbox_primitives::EnvironmentDefinition { entries: Vec::new() }, + retained_memories: Vec::new(), + _marker: marker::PhantomData::, + } + } + + fn add_host_func(&mut self, module: N1, field: N2, f: HostFuncType) where N1: Into>, N2: Into>, @@ -150,7 +146,7 @@ impl EnvironmentDefinitionBuilder { self.add_entry(module, field, f); } - pub fn add_memory(&mut self, module: N1, field: N2, mem: Memory) + fn add_memory(&mut self, module: N1, field: N2, mem: Memory) where N1: Into>, N2: Into>, @@ -163,6 +159,7 @@ impl EnvironmentDefinitionBuilder { } } +/// Sandboxed instance of a WASM module. pub struct Instance { instance_idx: u32, _retained_memories: Vec, @@ -211,8 +208,11 @@ extern "C" fn dispatch_thunk( } } -impl Instance { - pub fn new( +impl super::SandboxInstance for Instance { + type Memory = Memory; + type EnvironmentBuilder = EnvironmentDefinitionBuilder; + + fn new( code: &[u8], env_def_builder: &EnvironmentDefinitionBuilder, state: &mut T, @@ -242,12 +242,7 @@ impl Instance { }) } - pub fn invoke( - &mut self, - name: &str, - args: &[Value], - state: &mut T, - ) -> Result { + fn invoke(&mut self, name: &str, args: &[Value], state: &mut T) -> Result { let serialized_args = args.to_vec().encode(); let mut return_val = vec![0u8; ReturnValue::ENCODED_MAX_SIZE]; @@ -262,16 +257,16 @@ impl Instance { match result { sandbox_primitives::ERR_OK => { - let return_val = ReturnValue::decode(&mut &return_val[..]) - .map_err(|_| Error::Execution)?; + let return_val = + ReturnValue::decode(&mut &return_val[..]).map_err(|_| Error::Execution)?; Ok(return_val) - } + }, sandbox_primitives::ERR_EXECUTION => Err(Error::Execution), _ => unreachable!(), } } - pub fn get_global_val(&self, name: &str) -> Option { + fn get_global_val(&self, name: &str) -> Option { sandbox::get_global_val(self.instance_idx, name) } } diff --git a/primitives/sandbox/src/lib.rs b/primitives/sandbox/src/lib.rs index 1724b4152ff3..f1a24732b7a0 100755 --- a/primitives/sandbox/src/lib.rs +++ b/primitives/sandbox/src/lib.rs @@ -48,13 +48,15 @@ pub use sp_wasm_interface::{ReturnValue, Value}; /// The target used for logging. const TARGET: &str = "runtime::sandbox"; -mod imp { - #[cfg(all(feature = "wasmer-sandbox", not(feature = "std")))] - include!("../host_executor.rs"); +pub mod embedded_executor; +#[cfg(not(feature = "std"))] +pub mod host_executor; - #[cfg(not(all(feature = "wasmer-sandbox", not(feature = "std"))))] - include!("../embedded_executor.rs"); -} +#[cfg(all(feature = "wasmer-sandbox", not(feature = "std")))] +pub use host_executor as default_executor; + +#[cfg(not(all(feature = "wasmer-sandbox", not(feature = "std"))))] +pub use embedded_executor as default_executor; /// Error that can occur while using this crate. #[derive(sp_core::RuntimeDebug)] @@ -88,12 +90,7 @@ pub type HostFuncType = fn(&mut T, &[Value]) -> Result) -> Result { - Ok(Memory { inner: imp::Memory::new(initial, maximum)? }) - } + fn new(initial: u32, maximum: Option) -> Result; /// Read a memory area at the address `ptr` with the size of the provided slice `buf`. /// /// Returns `Err` if the range is out-of-bounds. - pub fn get(&self, ptr: u32, buf: &mut [u8]) -> Result<(), Error> { - self.inner.get(ptr, buf) - } + fn get(&self, ptr: u32, buf: &mut [u8]) -> Result<(), Error>; /// Write a memory area at the address `ptr` with contents of the provided slice `buf`. /// /// Returns `Err` if the range is out-of-bounds. - pub fn set(&self, ptr: u32, value: &[u8]) -> Result<(), Error> { - self.inner.set(ptr, value) - } + fn set(&self, ptr: u32, value: &[u8]) -> Result<(), Error>; } /// Struct that can be used for defining an environment for a sandboxed module. /// /// The sandboxed module can access only the entities which were defined and passed /// to the module at the instantiation time. -pub struct EnvironmentDefinitionBuilder { - inner: imp::EnvironmentDefinitionBuilder, -} - -impl EnvironmentDefinitionBuilder { +pub trait SandboxEnvironmentBuilder: Sized { /// Construct a new `EnvironmentDefinitionBuilder`. - pub fn new() -> EnvironmentDefinitionBuilder { - EnvironmentDefinitionBuilder { inner: imp::EnvironmentDefinitionBuilder::new() } - } + fn new() -> Self; /// Register a host function in this environment definition. /// @@ -143,32 +128,28 @@ impl EnvironmentDefinitionBuilder { /// can import function passed here with any signature it wants. It can even import /// the same function (i.e. with same `module` and `field`) several times. It's up to /// the user code to check or constrain the types of signatures. - pub fn add_host_func(&mut self, module: N1, field: N2, f: HostFuncType) + fn add_host_func(&mut self, module: N1, field: N2, f: HostFuncType) where N1: Into>, - N2: Into>, - { - self.inner.add_host_func(module, field, f); - } + N2: Into>; /// Register a memory in this environment definition. - pub fn add_memory(&mut self, module: N1, field: N2, mem: Memory) + fn add_memory(&mut self, module: N1, field: N2, mem: Memory) where N1: Into>, - N2: Into>, - { - self.inner.add_memory(module, field, mem.inner); - } + N2: Into>; } /// Sandboxed instance of a wasm module. /// /// This instance can be used for invoking exported functions. -pub struct Instance { - inner: imp::Instance, -} +pub trait SandboxInstance: Sized { + /// The memory type used for this sandbox. + type Memory: SandboxMemory; + + /// The environment builder used to construct this sandbox. + type EnvironmentBuilder: SandboxEnvironmentBuilder; -impl Instance { /// Instantiate a module with the given [`EnvironmentDefinitionBuilder`]. It will /// run the `start` function (if it is present in the module) with the given `state`. /// @@ -177,13 +158,11 @@ impl Instance { /// will be returned. /// /// [`EnvironmentDefinitionBuilder`]: struct.EnvironmentDefinitionBuilder.html - pub fn new( + fn new( code: &[u8], - env_def_builder: &EnvironmentDefinitionBuilder, - state: &mut T, - ) -> Result, Error> { - Ok(Instance { inner: imp::Instance::new(code, &env_def_builder.inner, state)? }) - } + env_def_builder: &Self::EnvironmentBuilder, + state: &mut State, + ) -> Result; /// Invoke an exported function with the given name. /// @@ -196,19 +175,15 @@ impl Instance { /// - If types of the arguments passed to the function doesn't match function signature then /// trap occurs (as if the exported function was called via call_indirect), /// - Trap occurred at the execution time. - pub fn invoke( + fn invoke( &mut self, name: &str, args: &[Value], - state: &mut T, - ) -> Result { - self.inner.invoke(name, args, state) - } + state: &mut State, + ) -> Result; /// Get the value from a global with the given `name`. /// /// Returns `Some(_)` if the global could be found. - pub fn get_global_val(&self, name: &str) -> Option { - self.inner.get_global_val(name) - } + fn get_global_val(&self, name: &str) -> Option; } From c6a9f648cfb432193c5df09e89ac06176c318971 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Mon, 8 Nov 2021 22:03:37 +0100 Subject: [PATCH 151/695] Offchain-worker: Accessing time is not HTTP (#10220) Accessing time related functionality is clearly not related to HTTP. So, this pr introduces a `TIME` capability. --- primitives/core/src/offchain/mod.rs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/primitives/core/src/offchain/mod.rs b/primitives/core/src/offchain/mod.rs index dfe23c1ff8f1..8058d4d05d6a 100644 --- a/primitives/core/src/offchain/mod.rs +++ b/primitives/core/src/offchain/mod.rs @@ -262,21 +262,23 @@ bitflags::bitflags! { /// Execution context extra capabilities. pub struct Capabilities: u32 { /// Access to transaction pool. - const TRANSACTION_POOL = 0b0000_0001; + const TRANSACTION_POOL = 0b0000_0000_0001; /// External http calls. - const HTTP = 0b0000_0010; + const HTTP = 0b0000_0000_0010; /// Keystore access. - const KEYSTORE = 0b0000_0100; + const KEYSTORE = 0b0000_0000_0100; /// Randomness source. - const RANDOMNESS = 0b0000_1000; + const RANDOMNESS = 0b0000_0000_1000; /// Access to opaque network state. - const NETWORK_STATE = 0b0001_0000; + const NETWORK_STATE = 0b0000_0001_0000; /// Access to offchain worker DB (read only). - const OFFCHAIN_DB_READ = 0b0010_0000; + const OFFCHAIN_DB_READ = 0b0000_0010_0000; /// Access to offchain worker DB (writes). - const OFFCHAIN_DB_WRITE = 0b0100_0000; + const OFFCHAIN_DB_WRITE = 0b0000_0100_0000; /// Manage the authorized nodes - const NODE_AUTHORIZATION = 0b1000_0000; + const NODE_AUTHORIZATION = 0b0000_1000_0000; + /// Access time related functionality + const TIME = 0b0001_0000_0000; } } @@ -541,12 +543,12 @@ impl Externalities for LimitedExternalities { } fn timestamp(&mut self) -> Timestamp { - self.check(Capabilities::HTTP, "timestamp"); + self.check(Capabilities::TIME, "timestamp"); self.externalities.timestamp() } fn sleep_until(&mut self, deadline: Timestamp) { - self.check(Capabilities::HTTP, "sleep_until"); + self.check(Capabilities::TIME, "sleep_until"); self.externalities.sleep_until(deadline) } From 2a601506cd4c53c3c526c61745c8887116e491be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Mon, 8 Nov 2021 22:05:39 +0100 Subject: [PATCH 152/695] Fix polkadot companion label CI check (#10198) * Fix polkadot companion label CI check * Update .github/workflows/polkadot-companion-labels.yml --- .github/workflows/polkadot-companion-labels.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/polkadot-companion-labels.yml b/.github/workflows/polkadot-companion-labels.yml index 3c3987b5f4d5..0a5af0935852 100644 --- a/.github/workflows/polkadot-companion-labels.yml +++ b/.github/workflows/polkadot-companion-labels.yml @@ -14,7 +14,7 @@ jobs: with: authToken: ${{ secrets.GITHUB_TOKEN }} ref: ${{ github.event.pull_request.head.sha }} - contexts: 'continuous-integration/gitlab-check-polkadot-companion-build' + contexts: 'continuous-integration/gitlab-check-dependent-polkadot' timeout: 1800 notPresentTimeout: 3600 # It can take quite a while before the job starts on Gitlab when the CI queue is large failureStates: failure From 60b51e3f0365799e5ae0d4f8a89c7b0126a5f905 Mon Sep 17 00:00:00 2001 From: David Date: Mon, 8 Nov 2021 22:06:53 +0100 Subject: [PATCH 153/695] Remove the RPC client example (#10217) * Remove the RPC client example Might be slightly contentious but I think we want to migrate this example to `subxt` and redirect the community to use that for things like this. * Remove rpc-client example code from workspace --- Cargo.lock | 11 ------ Cargo.toml | 1 - bin/node/rpc-client/Cargo.toml | 20 ----------- bin/node/rpc-client/src/main.rs | 63 --------------------------------- 4 files changed, 95 deletions(-) delete mode 100644 bin/node/rpc-client/Cargo.toml delete mode 100644 bin/node/rpc-client/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 4b6cc99426b1..ae8216ae3c72 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4657,17 +4657,6 @@ dependencies = [ "substrate-frame-rpc-system", ] -[[package]] -name = "node-rpc-client" -version = "2.0.0" -dependencies = [ - "futures 0.3.16", - "jsonrpc-core-client", - "node-primitives", - "sc-rpc", - "sp-tracing", -] - [[package]] name = "node-runtime" version = "3.0.0-dev" diff --git a/Cargo.toml b/Cargo.toml index 32d10ca8978d..07053a0ef316 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,6 @@ members = [ "bin/node/executor", "bin/node/primitives", "bin/node/rpc", - "bin/node/rpc-client", "bin/node/runtime", "bin/node/testing", "bin/utils/chain-spec-builder", diff --git a/bin/node/rpc-client/Cargo.toml b/bin/node/rpc-client/Cargo.toml deleted file mode 100644 index 5c822ef3ad31..000000000000 --- a/bin/node/rpc-client/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "node-rpc-client" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2021" -license = "Apache-2.0" -homepage = "https://substrate.io" -repository = "https://github.com/paritytech/substrate/" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[dependencies] -futures = "0.3.16" -jsonrpc-core-client = { version = "18.0.0", default-features = false, features = [ - "http", -] } -node-primitives = { version = "2.0.0", path = "../primitives" } -sp-tracing = { version = "4.0.0-dev", path = "../../../primitives/tracing" } -sc-rpc = { version = "4.0.0-dev", path = "../../../client/rpc" } diff --git a/bin/node/rpc-client/src/main.rs b/bin/node/rpc-client/src/main.rs deleted file mode 100644 index 6d0b88799f54..000000000000 --- a/bin/node/rpc-client/src/main.rs +++ /dev/null @@ -1,63 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2019-2021 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. - -#![warn(missing_docs)] - -//! Example substrate RPC client code. -//! -//! This module shows how you can write a Rust RPC client that connects to a running -//! substrate node and use statically typed RPC wrappers. - -use futures::{Future, TryFutureExt}; -use jsonrpc_core_client::{transports::http, RpcError}; -use node_primitives::Hash; -use sc_rpc::author::{hash::ExtrinsicOrHash, AuthorClient}; - -fn main() -> Result<(), RpcError> { - sp_tracing::try_init_simple(); - - futures::executor::block_on(async { - let uri = "http://localhost:9933"; - - http::connect(uri) - .and_then(|client: AuthorClient| remove_all_extrinsics(client)) - .await - }) -} - -/// Remove all pending extrinsics from the node. -/// -/// The example code takes `AuthorClient` and first: -/// 1. Calls the `pending_extrinsics` method to get all extrinsics in the pool. -/// 2. Then calls `remove_extrinsic` passing the obtained raw extrinsics. -/// -/// As the result of running the code the entire content of the transaction pool is going -/// to be removed and the extrinsics are going to be temporarily banned. -fn remove_all_extrinsics( - client: AuthorClient, -) -> impl Future> { - client - .pending_extrinsics() - .and_then(move |pending| { - client.remove_extrinsic( - pending.into_iter().map(|tx| ExtrinsicOrHash::Extrinsic(tx.into())).collect(), - ) - }) - .map_ok(|removed| { - println!("Removed extrinsics: {:?}", removed); - }) -} From fae2ac6a92656a0006da3aca4bf19e4a0545946f Mon Sep 17 00:00:00 2001 From: Qinxuan Chen Date: Tue, 9 Nov 2021 19:59:55 +0800 Subject: [PATCH 154/695] frame_support::pallet_prelude: Add scale_info::TypeInfo (#10221) Signed-off-by: koushiro --- frame/assets/src/lib.rs | 1 - frame/assets/src/types.rs | 8 ++++---- frame/gilt/src/lib.rs | 1 - frame/support/src/lib.rs | 1 + 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/frame/assets/src/lib.rs b/frame/assets/src/lib.rs index dfc81eadeb53..b89d411e41db 100644 --- a/frame/assets/src/lib.rs +++ b/frame/assets/src/lib.rs @@ -170,7 +170,6 @@ pub mod pallet { use super::*; use frame_support::{dispatch::DispatchResult, pallet_prelude::*}; use frame_system::pallet_prelude::*; - use scale_info::TypeInfo; #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] diff --git a/frame/assets/src/types.rs b/frame/assets/src/types.rs index bc2edce848a6..879e9d5cdcb9 100644 --- a/frame/assets/src/types.rs +++ b/frame/assets/src/types.rs @@ -18,10 +18,10 @@ //! Various basic types for use in the assets pallet. use super::*; -use frame_support::pallet_prelude::*; -use scale_info::TypeInfo; - -use frame_support::traits::{fungible, tokens::BalanceConversion}; +use frame_support::{ + pallet_prelude::*, + traits::{fungible, tokens::BalanceConversion}, +}; use sp_runtime::{traits::Convert, FixedPointNumber, FixedPointOperand, FixedU128}; pub(super) type DepositBalanceOf = diff --git a/frame/gilt/src/lib.rs b/frame/gilt/src/lib.rs index 393b3acb41a3..1594601b457c 100644 --- a/frame/gilt/src/lib.rs +++ b/frame/gilt/src/lib.rs @@ -82,7 +82,6 @@ pub mod pallet { traits::{Currency, OnUnbalanced, ReservableCurrency}, }; use frame_system::pallet_prelude::*; - use scale_info::TypeInfo; use sp_arithmetic::{PerThing, Perquintill}; use sp_runtime::traits::{Saturating, Zero}; use sp_std::prelude::*; diff --git a/frame/support/src/lib.rs b/frame/support/src/lib.rs index 6e60988a4ca2..af9192f6ea83 100644 --- a/frame/support/src/lib.rs +++ b/frame/support/src/lib.rs @@ -1330,6 +1330,7 @@ pub mod pallet_prelude { PartialEqNoBound, RuntimeDebug, RuntimeDebugNoBound, Twox128, Twox256, Twox64Concat, }; pub use codec::{Decode, Encode, MaxEncodedLen}; + pub use scale_info::TypeInfo; pub use sp_runtime::{ traits::{MaybeSerializeDeserialize, Member, ValidateUnsigned}, transaction_validity::{ From 5cb8a6d1e0b5a542667ce9220ec6c7cace76aeb8 Mon Sep 17 00:00:00 2001 From: Koute Date: Tue, 9 Nov 2021 21:08:02 +0900 Subject: [PATCH 155/695] Bump `wasmtime` to 0.31.0 (#10149) * Bump `wasmtime` to 0.31.0 * Bump `itoa` to 0.4.8 * sc-executor-wasmtime: fix `SandboxContext::invoke` which I've broke * sc-executor-wasmtime: cargo fmt --- Cargo.lock | 209 ++++++++++++++++++--------- client/executor/wasmtime/Cargo.toml | 2 +- client/executor/wasmtime/src/host.rs | 19 +-- 3 files changed, 145 insertions(+), 85 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ae8216ae3c72..8170b096de9d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -848,9 +848,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.67" +version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd" +checksum = "79c2681d6594606957bbb8631c4b90a7fcaaa72cdb714743a437b156d6a7eedd" dependencies = [ "jobserver", ] @@ -1068,11 +1068,11 @@ dependencies = [ [[package]] name = "cranelift-bforest" -version = "0.77.0" +version = "0.78.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15013642ddda44eebcf61365b2052a23fd8b7314f90ba44aa059ec02643c5139" +checksum = "cc0cb7df82c8cf8f2e6a8dd394a0932a71369c160cc9b027dca414fced242513" dependencies = [ - "cranelift-entity 0.77.0", + "cranelift-entity 0.78.0", ] [[package]] @@ -1088,7 +1088,7 @@ dependencies = [ "cranelift-entity 0.68.0", "gimli 0.22.0", "log 0.4.14", - "regalloc", + "regalloc 0.0.31", "smallvec 1.7.0", "target-lexicon 0.11.2", "thiserror", @@ -1096,17 +1096,17 @@ dependencies = [ [[package]] name = "cranelift-codegen" -version = "0.77.0" +version = "0.78.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298f2a7ed5fdcb062d8e78b7496b0f4b95265d20245f2d0ca88f846dd192a3a3" +checksum = "fe4463c15fa42eee909e61e5eac4866b7c6d22d0d8c621e57a0c5380753bfa8c" dependencies = [ - "cranelift-bforest 0.77.0", - "cranelift-codegen-meta 0.77.0", - "cranelift-codegen-shared 0.77.0", - "cranelift-entity 0.77.0", + "cranelift-bforest 0.78.0", + "cranelift-codegen-meta 0.78.0", + "cranelift-codegen-shared 0.78.0", + "cranelift-entity 0.78.0", "gimli 0.25.0", "log 0.4.14", - "regalloc", + "regalloc 0.0.32", "smallvec 1.7.0", "target-lexicon 0.12.0", ] @@ -1123,12 +1123,12 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.77.0" +version = "0.78.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cf504261ac62dfaf4ffb3f41d88fd885e81aba947c1241275043885bc5f0bac" +checksum = "793f6a94a053a55404ea16e1700202a88101672b8cd6b4df63e13cde950852bf" dependencies = [ - "cranelift-codegen-shared 0.77.0", - "cranelift-entity 0.77.0", + "cranelift-codegen-shared 0.78.0", + "cranelift-entity 0.78.0", ] [[package]] @@ -1139,9 +1139,9 @@ checksum = "6759012d6d19c4caec95793f052613e9d4113e925e7f14154defbac0f1d4c938" [[package]] name = "cranelift-codegen-shared" -version = "0.77.0" +version = "0.78.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd2a72db4301dbe7e5a4499035eedc1e82720009fb60603e20504d8691fa9cd" +checksum = "44aa1846df275bce5eb30379d65964c7afc63c05a117076e62a119c25fe174be" [[package]] name = "cranelift-entity" @@ -1154,9 +1154,9 @@ dependencies = [ [[package]] name = "cranelift-entity" -version = "0.77.0" +version = "0.78.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48868faa07cacf948dc4a1773648813c0e453ff9467e800ff10f6a78c021b546" +checksum = "a3a45d8d6318bf8fc518154d9298eab2a8154ec068a8885ff113f6db8d69bb3a" dependencies = [ "serde", ] @@ -1175,11 +1175,11 @@ dependencies = [ [[package]] name = "cranelift-frontend" -version = "0.77.0" +version = "0.78.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "351c9d13b4ecd1a536215ec2fd1c3ee9ee8bc31af172abf1e45ed0adb7a931df" +checksum = "e07339bd461766deb7605169de039e01954768ff730fa1254e149001884a8525" dependencies = [ - "cranelift-codegen 0.77.0", + "cranelift-codegen 0.78.0", "log 0.4.14", "smallvec 1.7.0", "target-lexicon 0.12.0", @@ -1187,28 +1187,28 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.77.0" +version = "0.78.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6df8b556663d7611b137b24db7f6c8d9a8a27d7f29c7ea7835795152c94c1b75" +checksum = "03e2fca76ff57e0532936a71e3fc267eae6a19a86656716479c66e7f912e3d7b" dependencies = [ - "cranelift-codegen 0.77.0", + "cranelift-codegen 0.78.0", "libc", "target-lexicon 0.12.0", ] [[package]] name = "cranelift-wasm" -version = "0.77.0" +version = "0.78.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a69816d90db694fa79aa39b89dda7208a4ac74b6f2b8f3c4da26ee1c8bdfc5e" +checksum = "1f46fec547a1f8a32c54ea61c28be4f4ad234ad95342b718a9a9adcaadb0c778" dependencies = [ - "cranelift-codegen 0.77.0", - "cranelift-entity 0.77.0", - "cranelift-frontend 0.77.0", + "cranelift-codegen 0.78.0", + "cranelift-entity 0.78.0", + "cranelift-frontend 0.78.0", "itertools", "log 0.4.14", "smallvec 1.7.0", - "wasmparser 0.80.2", + "wasmparser 0.81.0", "wasmtime-types", ] @@ -2928,6 +2928,16 @@ dependencies = [ "futures-timer 2.0.2", ] +[[package]] +name = "io-lifetimes" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47f5ce4afb9bf504b9f496a3307676bc232122f91a93c4da6d540aa99a0a0e0b" +dependencies = [ + "rustc_version 0.4.0", + "winapi 0.3.9", +] + [[package]] name = "iovec" version = "0.1.4" @@ -2972,9 +2982,9 @@ dependencies = [ [[package]] name = "itoa" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "jobserver" @@ -3935,6 +3945,12 @@ dependencies = [ "statrs", ] +[[package]] +name = "linux-raw-sys" +version = "0.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "687387ff42ec7ea4f2149035a5675fedb675d26f98db90a1846ac63d3addb5f5" + [[package]] name = "lite-json" version = "0.1.3" @@ -4090,9 +4106,9 @@ checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" [[package]] name = "memchr" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" [[package]] name = "memmap" @@ -4984,6 +5000,15 @@ name = "object" version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c55827317fb4c08822499848a14237d2874d6f139828893017237e7ab93eb386" +dependencies = [ + "memchr", +] + +[[package]] +name = "object" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9" dependencies = [ "crc32fast", "indexmap", @@ -7281,6 +7306,17 @@ dependencies = [ "smallvec 1.7.0", ] +[[package]] +name = "regalloc" +version = "0.0.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6304468554ed921da3d32c355ea107b8d13d7b8996c3adfb7aab48d3bc321f4" +dependencies = [ + "log 0.4.14", + "rustc-hash", + "smallvec 1.7.0", +] + [[package]] name = "regex" version = "1.5.4" @@ -7399,6 +7435,23 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "rsix" +version = "0.23.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f64c5788d5aab8b75441499d99576a24eb09f76fb267b36fec7e3d970c66431" +dependencies = [ + "bitflags", + "cc", + "errno", + "io-lifetimes", + "itoa", + "libc", + "linux-raw-sys", + "once_cell", + "rustc_version 0.4.0", +] + [[package]] name = "rustc-demangle" version = "0.1.18" @@ -7435,6 +7488,15 @@ dependencies = [ "semver 0.11.0", ] +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver 1.0.4", +] + [[package]] name = "rustls" version = "0.19.1" @@ -8816,6 +8878,12 @@ dependencies = [ "serde", ] +[[package]] +name = "semver" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012" + [[package]] name = "semver-parser" version = "0.7.0" @@ -11518,15 +11586,15 @@ checksum = "87cc2fe6350834b4e528ba0901e7aa405d78b89dc1fa3145359eb4de0e323fcf" [[package]] name = "wasmparser" -version = "0.80.2" +version = "0.81.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "449167e2832691a1bff24cde28d2804e90e09586a448c8e76984792c44334a6b" +checksum = "98930446519f63d00a836efdc22f67766ceae8dbcc1571379f2bcabc6b2b9abc" [[package]] name = "wasmtime" -version = "0.30.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "899b1e5261e3d3420860dacfb952871ace9d7ba9f953b314f67aaf9f8e2a4d89" +checksum = "311d06b0c49346d1fbf48a17052e844036b95a7753c1afb34e8c0af3f6b5bb13" dependencies = [ "anyhow", "backtrace", @@ -11537,7 +11605,7 @@ dependencies = [ "lazy_static", "libc", "log 0.4.14", - "object 0.26.0", + "object 0.27.1", "paste 1.0.4", "psm", "rayon", @@ -11545,7 +11613,7 @@ dependencies = [ "rustc-demangle", "serde", "target-lexicon 0.12.0", - "wasmparser 0.80.2", + "wasmparser 0.81.0", "wasmtime-cache", "wasmtime-cranelift", "wasmtime-environ", @@ -11556,18 +11624,17 @@ dependencies = [ [[package]] name = "wasmtime-cache" -version = "0.30.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2493b81d7a9935f7af15e06beec806f256bc974a90a843685f3d61f2fc97058" +checksum = "36147930a4995137dc096e5b17a573b446799be2bbaea433e821ce6a80abe2c5" dependencies = [ "anyhow", "base64 0.13.0", "bincode", "directories-next", - "errno", "file-per-thread-logger", - "libc", "log 0.4.14", + "rsix", "serde", "sha2 0.9.8", "toml", @@ -11577,66 +11644,67 @@ dependencies = [ [[package]] name = "wasmtime-cranelift" -version = "0.30.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99706bacdf5143f7f967d417f0437cce83a724cf4518cb1a3ff40e519d793021" +checksum = "ab3083a47e1ede38aac06a1d9831640d673f9aeda0b82a64e4ce002f3432e2e7" dependencies = [ "anyhow", - "cranelift-codegen 0.77.0", - "cranelift-entity 0.77.0", - "cranelift-frontend 0.77.0", + "cranelift-codegen 0.78.0", + "cranelift-entity 0.78.0", + "cranelift-frontend 0.78.0", "cranelift-native", "cranelift-wasm", "gimli 0.25.0", + "log 0.4.14", "more-asserts", - "object 0.26.0", + "object 0.27.1", "target-lexicon 0.12.0", "thiserror", - "wasmparser 0.80.2", + "wasmparser 0.81.0", "wasmtime-environ", ] [[package]] name = "wasmtime-environ" -version = "0.30.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac42cb562a2f98163857605f02581d719a410c5abe93606128c59a10e84de85b" +checksum = "1c2d194b655321053bc4111a1aa4ead552655c8a17d17264bc97766e70073510" dependencies = [ "anyhow", "cfg-if 1.0.0", - "cranelift-entity 0.77.0", + "cranelift-entity 0.78.0", "gimli 0.25.0", "indexmap", "log 0.4.14", "more-asserts", - "object 0.26.0", + "object 0.27.1", "serde", "target-lexicon 0.12.0", "thiserror", - "wasmparser 0.80.2", + "wasmparser 0.81.0", "wasmtime-types", ] [[package]] name = "wasmtime-jit" -version = "0.30.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24f46dd757225f29a419be415ea6fb8558df9b0194f07e3a6a9c99d0e14dd534" +checksum = "864ac8dfe4ce310ac59f16fdbd560c257389cb009ee5d030ac6e30523b023d11" dependencies = [ "addr2line", "anyhow", "bincode", "cfg-if 1.0.0", "gimli 0.25.0", - "libc", "log 0.4.14", "more-asserts", - "object 0.26.0", + "object 0.27.1", "region", + "rsix", "serde", "target-lexicon 0.12.0", "thiserror", - "wasmparser 0.80.2", + "wasmparser 0.81.0", "wasmtime-environ", "wasmtime-runtime", "winapi 0.3.9", @@ -11644,9 +11712,9 @@ dependencies = [ [[package]] name = "wasmtime-runtime" -version = "0.30.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0122215a44923f395487048cb0a1d60b5b32c73aab15cf9364b798dbaff0996f" +checksum = "ab97da813a26b98c9abfd3b0c2d99e42f6b78b749c0646344e2e262d212d8c8b" dependencies = [ "anyhow", "backtrace", @@ -11661,6 +11729,7 @@ dependencies = [ "more-asserts", "rand 0.8.4", "region", + "rsix", "thiserror", "wasmtime-environ", "winapi 0.3.9", @@ -11668,14 +11737,14 @@ dependencies = [ [[package]] name = "wasmtime-types" -version = "0.30.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9b01caf8a204ef634ebac99700e77ba716d3ebbb68a1abbc2ceb6b16dbec9e4" +checksum = "ff94409cc3557bfbbcce6b14520ccd6bd3727e965c0fe68d63ef2c185bf379c6" dependencies = [ - "cranelift-entity 0.77.0", + "cranelift-entity 0.78.0", "serde", "thiserror", - "wasmparser 0.80.2", + "wasmparser 0.81.0", ] [[package]] diff --git a/client/executor/wasmtime/Cargo.toml b/client/executor/wasmtime/Cargo.toml index 741898b8282c..e52a53f71c06 100644 --- a/client/executor/wasmtime/Cargo.toml +++ b/client/executor/wasmtime/Cargo.toml @@ -23,7 +23,7 @@ sp-wasm-interface = { version = "4.0.0-dev", path = "../../../primitives/wasm-in sp-runtime-interface = { version = "4.0.0-dev", path = "../../../primitives/runtime-interface" } sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" } sc-allocator = { version = "4.0.0-dev", path = "../../allocator" } -wasmtime = { version = "0.30.0", default-features = false, features = [ +wasmtime = { version = "0.31.0", default-features = false, features = [ "cache", "cranelift", "jitdump", diff --git a/client/executor/wasmtime/src/host.rs b/client/executor/wasmtime/src/host.rs index 4edb9f9c423f..fcb4c4cae3b8 100644 --- a/client/executor/wasmtime/src/host.rs +++ b/client/executor/wasmtime/src/host.rs @@ -333,6 +333,7 @@ impl<'a, 'b, 'c, 'd> sandbox::SandboxContext for SandboxContext<'a, 'b, 'c, 'd> state: u32, func_idx: SupervisorFuncIndex, ) -> Result { + let mut ret_vals = [Val::null()]; let result = self.dispatch_thunk.call( &mut self.host_context.caller, &[ @@ -341,26 +342,16 @@ impl<'a, 'b, 'c, 'd> sandbox::SandboxContext for SandboxContext<'a, 'b, 'c, 'd> Val::I32(state as i32), Val::I32(usize::from(func_idx) as i32), ], + &mut ret_vals, ); match result { - Ok(ret_vals) => { - let ret_val = if ret_vals.len() != 1 { - return Err(format!( - "Supervisor function returned {} results, expected 1", - ret_vals.len() - ) - .into()) - } else { - &ret_vals[0] - }; - - if let Some(ret_val) = ret_val.i64() { + Ok(()) => + if let Some(ret_val) = ret_vals[0].i64() { Ok(ret_val) } else { return Err("Supervisor function returned unexpected result!".into()) - } - }, + }, Err(err) => Err(err.to_string().into()), } } From 7adee13ddc48a9d715eb2f9caa37d99713fa0102 Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Tue, 9 Nov 2021 13:08:34 +0100 Subject: [PATCH 156/695] Bump parity-db (#10218) * Bump parity-db * Update cargo.lock --- Cargo.lock | 4 ++-- client/db/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8170b096de9d..8985b5fb8933 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6223,9 +6223,9 @@ dependencies = [ [[package]] name = "parity-db" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ccc4a8687027deb53d45c5434a1f1b330c9d1069a59cfe80a62aa9a1da25ae" +checksum = "7cb5195cb862b13055cf7f7a76c55073dc73885c2a61511e322b8c1666be7332" dependencies = [ "blake2-rfc", "crc32fast", diff --git a/client/db/Cargo.toml b/client/db/Cargo.toml index 19bf7ad248fe..437431a50883 100644 --- a/client/db/Cargo.toml +++ b/client/db/Cargo.toml @@ -33,7 +33,7 @@ sc-state-db = { version = "0.10.0-dev", path = "../state-db" } sp-trie = { version = "4.0.0-dev", path = "../../primitives/trie" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-database = { version = "4.0.0-dev", path = "../../primitives/database" } -parity-db = { version = "0.3.3", optional = true } +parity-db = { version = "0.3.4", optional = true } [dev-dependencies] sp-tracing = { version = "4.0.0-dev", path = "../../primitives/tracing" } From 800fac14306a77c3dd7fa178c8d4a6a77d52d3bd Mon Sep 17 00:00:00 2001 From: Koute Date: Tue, 9 Nov 2021 22:38:31 +0900 Subject: [PATCH 157/695] Add a block production benchmark (#10104) * Add a block production benchmark * Simplify the block production benchmark * Cleanups; switch execution strategy to WASM * Switch WASM execution to `Compiled` * Reduce the setup cost of the benchmark Creating all of those extrinsics takes up *a lot* of time, up to the point where the majority of the time is actually spent *outside* of the code which we want to benchmark here. So let's only do it once. * Add a variant of the block production benchmark with proof recording --- Cargo.lock | 3 + bin/node/cli/Cargo.toml | 7 + bin/node/cli/benches/block_production.rs | 237 +++++++++++++++++++++++ 3 files changed, 247 insertions(+) create mode 100644 bin/node/cli/benches/block_production.rs diff --git a/Cargo.lock b/Cargo.lock index 8985b5fb8933..b164a74f94a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4528,6 +4528,7 @@ dependencies = [ "node-runtime", "pallet-balances", "pallet-im-online", + "pallet-timestamp", "pallet-transaction-payment", "parity-scale-codec", "platforms", @@ -4536,6 +4537,7 @@ dependencies = [ "remote-externalities", "sc-authority-discovery", "sc-basic-authorship", + "sc-block-builder", "sc-chain-spec", "sc-cli", "sc-client-api", @@ -4562,6 +4564,7 @@ dependencies = [ "sp-api", "sp-authority-discovery", "sp-authorship", + "sp-blockchain", "sp-consensus", "sp-consensus-babe", "sp-core", diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index 38c161a81ef0..15760c5a9abb 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -116,7 +116,9 @@ sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/commo sc-consensus-babe = { version = "0.10.0-dev", path = "../../../client/consensus/babe" } sc-consensus-epochs = { version = "0.10.0-dev", path = "../../../client/consensus/epochs" } sc-service-test = { version = "2.0.0", path = "../../../client/service/test" } +sc-block-builder = { version = "0.10.0-dev", path = "../../../client/block-builder" } sp-tracing = { version = "4.0.0-dev", path = "../../../primitives/tracing" } +sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } futures = "0.3.16" tempfile = "3.1.0" assert_cmd = "2.0.2" @@ -131,6 +133,7 @@ tokio = { version = "1.10", features = ["macros", "time"] } jsonrpsee-ws-client = { version = "0.3.1", default-features = false, features = ["tokio1"] } wait-timeout = "0.2" remote-externalities = { path = "../../../utils/frame/remote-externalities" } +pallet-timestamp = { version = "4.0.0-dev", path = "../../../frame/timestamp" } [build-dependencies] structopt = { version = "0.3.8", optional = true } @@ -166,3 +169,7 @@ try-runtime = ["node-runtime/try-runtime", "try-runtime-cli"] [[bench]] name = "transaction_pool" harness = false + +[[bench]] +name = "block_production" +harness = false diff --git a/bin/node/cli/benches/block_production.rs b/bin/node/cli/benches/block_production.rs new file mode 100644 index 000000000000..5a520e7b6339 --- /dev/null +++ b/bin/node/cli/benches/block_production.rs @@ -0,0 +1,237 @@ +// This file is part of Substrate. + +// Copyright (C) 2021 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 . + +use criterion::{criterion_group, criterion_main, BatchSize, Criterion, Throughput}; + +use node_cli::service::{create_extrinsic, FullClient}; +use node_runtime::{constants::currency::*, BalancesCall}; +use sc_block_builder::{BlockBuilderProvider, BuiltBlock, RecordProof}; +use sc_client_api::execution_extensions::ExecutionStrategies; +use sc_consensus::{ + block_import::{BlockImportParams, ForkChoiceStrategy}, + BlockImport, StateAction, +}; +use sc_service::{ + config::{ + DatabaseSource, KeepBlocks, KeystoreConfig, NetworkConfiguration, OffchainWorkerConfig, + PruningMode, TransactionStorageMode, WasmExecutionMethod, + }, + BasePath, Configuration, Role, +}; +use sp_blockchain::{ApplyExtrinsicFailed::Validity, Error::ApplyExtrinsicFailed}; +use sp_consensus::BlockOrigin; +use sp_keyring::Sr25519Keyring; +use sp_runtime::{ + generic::BlockId, + transaction_validity::{InvalidTransaction, TransactionValidityError}, + AccountId32, MultiAddress, OpaqueExtrinsic, +}; +use tokio::runtime::Handle; + +fn new_node(tokio_handle: Handle) -> node_cli::service::NewFullBase { + let base_path = BasePath::new_temp_dir() + .expect("getting the base path of a temporary path doesn't fail; qed"); + let root = base_path.path().to_path_buf(); + + let network_config = NetworkConfiguration::new( + Sr25519Keyring::Alice.to_seed(), + "network/test/0.1", + Default::default(), + None, + ); + + let spec = Box::new(node_cli::chain_spec::development_config()); + + // NOTE: We enforce the use of the WASM runtime to benchmark block production using WASM. + let execution_strategy = sc_client_api::ExecutionStrategy::AlwaysWasm; + + let config = Configuration { + impl_name: "BenchmarkImpl".into(), + impl_version: "1.0".into(), + // We don't use the authority role since that would start producing blocks + // in the background which would mess with our benchmark. + role: Role::Full, + tokio_handle, + transaction_pool: Default::default(), + network: network_config, + keystore: KeystoreConfig::InMemory, + keystore_remote: Default::default(), + database: DatabaseSource::RocksDb { path: root.join("db"), cache_size: 128 }, + state_cache_size: 67108864, + state_cache_child_ratio: None, + state_pruning: PruningMode::ArchiveAll, + keep_blocks: KeepBlocks::All, + transaction_storage: TransactionStorageMode::BlockBody, + chain_spec: spec, + wasm_method: WasmExecutionMethod::Compiled, + execution_strategies: ExecutionStrategies { + syncing: execution_strategy, + importing: execution_strategy, + block_construction: execution_strategy, + offchain_worker: execution_strategy, + other: execution_strategy, + }, + rpc_http: None, + rpc_ws: None, + rpc_ipc: None, + rpc_ws_max_connections: None, + rpc_cors: None, + rpc_methods: Default::default(), + rpc_max_payload: None, + ws_max_out_buffer_capacity: None, + prometheus_config: None, + telemetry_endpoints: None, + default_heap_pages: None, + offchain_worker: OffchainWorkerConfig { enabled: true, indexing_enabled: false }, + force_authoring: false, + disable_grandpa: false, + dev_key_seed: Some(Sr25519Keyring::Alice.to_seed()), + tracing_targets: None, + tracing_receiver: Default::default(), + max_runtime_instances: 8, + announce_block: true, + base_path: Some(base_path), + informant_output_format: Default::default(), + wasm_runtime_overrides: None, + }; + + node_cli::service::new_full_base(config, |_, _| ()).expect("creating a full node doesn't fail") +} + +fn extrinsic_set_time(now: u64) -> OpaqueExtrinsic { + node_runtime::UncheckedExtrinsic { + signature: None, + function: node_runtime::Call::Timestamp(pallet_timestamp::Call::set { now }), + } + .into() +} + +fn import_block( + mut client: &FullClient, + built: BuiltBlock< + node_primitives::Block, + >::StateBackend, + >, +) { + let mut params = BlockImportParams::new(BlockOrigin::File, built.block.header); + params.state_action = + StateAction::ApplyChanges(sc_consensus::StorageChanges::Changes(built.storage_changes)); + params.fork_choice = Some(ForkChoiceStrategy::LongestChain); + futures::executor::block_on(client.import_block(params, Default::default())) + .expect("importing a block doesn't fail"); +} + +fn prepare_benchmark(client: &FullClient) -> (usize, Vec) { + const MINIMUM_PERIOD_FOR_BLOCKS: u64 = 1500; + + let mut max_transfer_count = 0; + let mut extrinsics = Vec::new(); + let mut block_builder = client.new_block(Default::default()).unwrap(); + + // Every block needs one timestamp extrinsic. + let extrinsic_set_time = extrinsic_set_time(1 + MINIMUM_PERIOD_FOR_BLOCKS); + block_builder.push(extrinsic_set_time.clone()).unwrap(); + extrinsics.push(extrinsic_set_time); + + // Creating those is surprisingly costly, so let's only do it once and later just `clone` them. + let src = Sr25519Keyring::Alice.pair(); + let dst: MultiAddress = Sr25519Keyring::Bob.to_account_id().into(); + + // Add as many tranfer extrinsics as possible into a single block. + for nonce in 0.. { + let extrinsic: OpaqueExtrinsic = create_extrinsic( + client, + src.clone(), + BalancesCall::transfer { dest: dst.clone(), value: 1 * DOLLARS }, + Some(nonce), + ) + .into(); + + match block_builder.push(extrinsic.clone()) { + Ok(_) => {}, + Err(ApplyExtrinsicFailed(Validity(TransactionValidityError::Invalid( + InvalidTransaction::ExhaustsResources, + )))) => break, + Err(error) => panic!("{}", error), + } + + extrinsics.push(extrinsic); + max_transfer_count += 1; + } + + (max_transfer_count, extrinsics) +} + +fn block_production(c: &mut Criterion) { + sp_tracing::try_init_simple(); + + let runtime = tokio::runtime::Runtime::new().expect("creating tokio runtime doesn't fail; qed"); + let tokio_handle = runtime.handle().clone(); + + let node = new_node(tokio_handle.clone()); + let client = &*node.client; + + // Buliding the very first block is around ~30x slower than any subsequent one, + // so let's make sure it's built and imported before we benchmark anything. + let mut block_builder = client.new_block(Default::default()).unwrap(); + block_builder.push(extrinsic_set_time(1)).unwrap(); + import_block(client, block_builder.build().unwrap()); + + let (max_transfer_count, extrinsics) = prepare_benchmark(&client); + log::info!("Maximum transfer count: {}", max_transfer_count); + + let mut group = c.benchmark_group("Block production"); + + group.sample_size(10); + group.throughput(Throughput::Elements(max_transfer_count as u64)); + + let block_id = BlockId::Hash(client.chain_info().best_hash); + + group.bench_function(format!("{} transfers (no proof)", max_transfer_count), |b| { + b.iter_batched( + || extrinsics.clone(), + |extrinsics| { + let mut block_builder = + client.new_block_at(&block_id, Default::default(), RecordProof::No).unwrap(); + for extrinsic in extrinsics { + block_builder.push(extrinsic).unwrap(); + } + block_builder.build().unwrap() + }, + BatchSize::SmallInput, + ) + }); + + group.bench_function(format!("{} transfers (with proof)", max_transfer_count), |b| { + b.iter_batched( + || extrinsics.clone(), + |extrinsics| { + let mut block_builder = + client.new_block_at(&block_id, Default::default(), RecordProof::Yes).unwrap(); + for extrinsic in extrinsics { + block_builder.push(extrinsic).unwrap(); + } + block_builder.build().unwrap() + }, + BatchSize::SmallInput, + ) + }); +} + +criterion_group!(benches, block_production); +criterion_main!(benches); From dfe12bf772bfae862884af5ed4dd0b73011f5c84 Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Tue, 9 Nov 2021 21:26:39 +0000 Subject: [PATCH 158/695] new remote-ext mode: (#10192) --- Cargo.lock | 1 + utils/frame/remote-externalities/Cargo.toml | 1 + utils/frame/remote-externalities/src/lib.rs | 122 +++++++++++++++----- 3 files changed, 94 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b164a74f94a5..b72f8ece09a4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7364,6 +7364,7 @@ name = "remote-externalities" version = "0.10.0-dev" dependencies = [ "env_logger 0.9.0", + "frame-support", "jsonrpsee-proc-macros", "jsonrpsee-ws-client", "log 0.4.14", diff --git a/utils/frame/remote-externalities/Cargo.toml b/utils/frame/remote-externalities/Cargo.toml index 3e7c229ec4d6..9c9025d934aa 100644 --- a/utils/frame/remote-externalities/Cargo.toml +++ b/utils/frame/remote-externalities/Cargo.toml @@ -32,6 +32,7 @@ sp-version = { version = "4.0.0-dev", path = "../../../primitives/version" } [dev-dependencies] tokio = { version = "1.10", features = ["macros", "rt-multi-thread"] } pallet-elections-phragmen = { path = "../../../frame/elections-phragmen", version = "5.0.0-dev" } +frame-support = { path = "../../../frame/support", version = "4.0.0-dev" } [features] remote-test = [] diff --git a/utils/frame/remote-externalities/src/lib.rs b/utils/frame/remote-externalities/src/lib.rs index 3b9e08f75da8..bf8c57ae14ee 100644 --- a/utils/frame/remote-externalities/src/lib.rs +++ b/utils/frame/remote-externalities/src/lib.rs @@ -22,7 +22,6 @@ use codec::{Decode, Encode}; use jsonrpsee_ws_client::{types::v2::params::JsonRpcParams, WsClient, WsClientBuilder}; -use log::*; use sp_core::{ hashing::twox_128, hexdisplay::HexDisplay, @@ -62,10 +61,12 @@ jsonrpsee_proc_macros::rpc_client_api! { /// The execution mode. #[derive(Clone)] pub enum Mode { - /// Online. + /// Online. Potentially writes to a cache file. Online(OnlineConfig), /// Offline. Uses a state snapshot file and needs not any client config. Offline(OfflineConfig), + /// Prefer using a cache file if it exists, else use a remote server. + OfflineOrElseOnline(OfflineConfig, OnlineConfig), } impl Default for Mode { @@ -83,6 +84,12 @@ pub struct OfflineConfig { pub state_snapshot: SnapshotConfig, } +impl> From

for SnapshotConfig { + fn from(p: P) -> Self { + Self { path: p.into() } + } +} + /// Description of the transport protocol (for online execution). #[derive(Debug)] pub struct Transport { @@ -193,6 +200,7 @@ impl Builder { fn as_online(&self) -> &OnlineConfig { match &self.mode { Mode::Online(config) => &config, + Mode::OfflineOrElseOnline(_, config) => &config, _ => panic!("Unexpected mode: Online"), } } @@ -200,6 +208,7 @@ impl Builder { fn as_online_mut(&mut self) -> &mut OnlineConfig { match &mut self.mode { Mode::Online(config) => config, + Mode::OfflineOrElseOnline(_, config) => config, _ => panic!("Unexpected mode: Online"), } } @@ -212,19 +221,19 @@ impl Builder { key: StorageKey, maybe_at: Option, ) -> Result { - trace!(target: LOG_TARGET, "rpc: get_storage"); + log::trace!(target: LOG_TARGET, "rpc: get_storage"); RpcApi::::get_storage(self.as_online().rpc_client(), key, maybe_at) .await .map_err(|e| { - error!("Error = {:?}", e); + log::error!(target: LOG_TARGET, "Error = {:?}", e); "rpc get_storage failed." }) } /// Get the latest finalized head. async fn rpc_get_head(&self) -> Result { - trace!(target: LOG_TARGET, "rpc: finalized_head"); + log::trace!(target: LOG_TARGET, "rpc: finalized_head"); RpcApi::::finalized_head(self.as_online().rpc_client()).await.map_err(|e| { - error!("Error = {:?}", e); + log::error!(target: LOG_TARGET, "Error = {:?}", e); "rpc finalized_head failed." }) } @@ -248,19 +257,19 @@ impl Builder { ) .await .map_err(|e| { - error!(target: LOG_TARGET, "Error = {:?}", e); + log::error!(target: LOG_TARGET, "Error = {:?}", e); "rpc get_keys failed" })?; let page_len = page.len(); all_keys.extend(page); if page_len < PAGE as usize { - debug!(target: LOG_TARGET, "last page received: {}", page_len); + log::debug!(target: LOG_TARGET, "last page received: {}", page_len); break all_keys } else { let new_last_key = all_keys.last().expect("all_keys is populated; has .last(); qed"); - debug!( + log::debug!( target: LOG_TARGET, "new total = {}, full page received: {:?}", all_keys.len(), @@ -286,7 +295,7 @@ impl Builder { use serde_json::to_value; let keys = self.get_keys_paged(prefix, at).await?; let keys_count = keys.len(); - debug!(target: LOG_TARGET, "Querying a total of {} keys", keys.len()); + log::debug!(target: LOG_TARGET, "Querying a total of {} keys", keys.len()); let mut key_values: Vec = vec![]; let client = self.as_online().rpc_client(); @@ -323,7 +332,7 @@ impl Builder { key_values.push((key.clone(), value)); if key_values.len() % (10 * BATCH_SIZE) == 0 { let ratio: f64 = key_values.len() as f64 / keys_count as f64; - debug!( + log::debug!( target: LOG_TARGET, "progress = {:.2} [{} / {}]", ratio, @@ -342,14 +351,14 @@ impl Builder { impl Builder { /// Save the given data as state snapshot. fn save_state_snapshot(&self, data: &[KeyPair], path: &Path) -> Result<(), &'static str> { - debug!(target: LOG_TARGET, "writing to state snapshot file {:?}", path); + log::debug!(target: LOG_TARGET, "writing to state snapshot file {:?}", path); fs::write(path, data.encode()).map_err(|_| "fs::write failed.")?; Ok(()) } /// initialize `Self` from state snapshot. Panics if the file does not exist. fn load_state_snapshot(&self, path: &Path) -> Result, &'static str> { - info!(target: LOG_TARGET, "scraping key-pairs from state snapshot {:?}", path); + log::info!(target: LOG_TARGET, "scraping key-pairs from state snapshot {:?}", path); let bytes = fs::read(path).map_err(|_| "fs::read failed.")?; Decode::decode(&mut &*bytes).map_err(|_| "decode failed") } @@ -362,14 +371,14 @@ impl Builder { .at .expect("online config must be initialized by this point; qed.") .clone(); - info!(target: LOG_TARGET, "scraping key-pairs from remote @ {:?}", at); + log::info!(target: LOG_TARGET, "scraping key-pairs from remote @ {:?}", at); let mut keys_and_values = if config.pallets.len() > 0 { let mut filtered_kv = vec![]; for f in config.pallets.iter() { let hashed_prefix = StorageKey(twox_128(f.as_bytes()).to_vec()); let module_kv = self.rpc_get_pairs_paged(hashed_prefix.clone(), at).await?; - info!( + log::info!( target: LOG_TARGET, "downloaded data for module {} (count: {} / prefix: {:?}).", f, @@ -380,12 +389,12 @@ impl Builder { } filtered_kv } else { - info!(target: LOG_TARGET, "downloading data for all pallets."); + log::info!(target: LOG_TARGET, "downloading data for all pallets."); self.rpc_get_pairs_paged(StorageKey(vec![]), at).await? }; for prefix in &self.hashed_prefixes { - info!( + log::info!( target: LOG_TARGET, "adding data for hashed prefix: {:?}", HexDisplay::from(prefix) @@ -397,7 +406,11 @@ impl Builder { for key in &self.hashed_keys { let key = StorageKey(key.to_vec()); - info!(target: LOG_TARGET, "adding data for hashed key: {:?}", HexDisplay::from(&key)); + log::info!( + target: LOG_TARGET, + "adding data for hashed key: {:?}", + HexDisplay::from(&key) + ); let value = self.rpc_get_storage(key.clone(), Some(at)).await?; keys_and_values.push((key, value)); } @@ -407,7 +420,7 @@ impl Builder { pub(crate) async fn init_remote_client(&mut self) -> Result<(), &'static str> { let mut online = self.as_online_mut(); - debug!(target: LOG_TARGET, "initializing remote client to {:?}", online.transport.uri); + log::debug!(target: LOG_TARGET, "initializing remote client to {:?}", online.transport.uri); // First, initialize the ws client. let ws_client = WsClientBuilder::default() @@ -437,11 +450,23 @@ impl Builder { } kp }, + Mode::OfflineOrElseOnline(offline_config, online_config) => { + if let Ok(kv) = self.load_state_snapshot(&offline_config.state_snapshot.path) { + kv + } else { + self.init_remote_client().await?; + let kp = self.load_remote().await?; + if let Some(c) = online_config.state_snapshot { + self.save_state_snapshot(&kp, &c.path)?; + } + kp + } + }, }; // inject manual key values. if !self.hashed_key_values.is_empty() { - debug!( + log::debug!( target: LOG_TARGET, "extending externalities with {} manually injected key-values", self.hashed_key_values.len() @@ -451,7 +476,7 @@ impl Builder { // exclude manual key values. if !self.hashed_blacklist.is_empty() { - debug!( + log::debug!( target: LOG_TARGET, "excluding externalities from {} keys", self.hashed_blacklist.len() @@ -522,7 +547,7 @@ impl Builder { let kv = self.pre_build().await?; let mut ext = TestExternalities::new_empty(); - info!(target: LOG_TARGET, "injecting a total of {} keys", kv.len()); + log::info!(target: LOG_TARGET, "injecting a total of {} keys", kv.len()); for (k, v) in kv { let (k, v) = (k.0, v.0); // Insert the key,value pair into the test trie backend @@ -603,12 +628,51 @@ mod remote_tests { const REMOTE_INACCESSIBLE: &'static str = "Can't reach the remote node. Is it running?"; + #[tokio::test] + async fn offline_else_online_works() { + init_logger(); + // this shows that in the second run, we use the remote and create a cache. + Builder::::new() + .mode(Mode::OfflineOrElseOnline( + OfflineConfig { + state_snapshot: SnapshotConfig::new("test_snapshot_to_remove.bin"), + }, + OnlineConfig { + pallets: vec!["Proxy".to_owned()], + state_snapshot: Some(SnapshotConfig::new("test_snapshot_to_remove.bin")), + ..Default::default() + }, + )) + .build() + .await + .expect(REMOTE_INACCESSIBLE) + .execute_with(|| {}); + + // this shows that in the second run, we are not using the remote + Builder::::new() + .mode(Mode::OfflineOrElseOnline( + OfflineConfig { + state_snapshot: SnapshotConfig::new("test_snapshot_to_remove.bin"), + }, + OnlineConfig { + pallets: vec!["Proxy".to_owned()], + state_snapshot: Some(SnapshotConfig::new("test_snapshot_to_remove.bin")), + transport: "ws://non-existent:666".to_owned().into(), + ..Default::default() + }, + )) + .build() + .await + .expect(REMOTE_INACCESSIBLE) + .execute_with(|| {}); + } + #[tokio::test] async fn can_build_one_pallet() { init_logger(); Builder::::new() .mode(Mode::Online(OnlineConfig { - pallets: vec!["System".to_owned()], + pallets: vec!["Proxy".to_owned()], ..Default::default() })) .build() @@ -622,11 +686,7 @@ mod remote_tests { init_logger(); Builder::::new() .mode(Mode::Online(OnlineConfig { - pallets: vec![ - "Proxy".to_owned(), - "Multisig".to_owned(), - "PhragmenElection".to_owned(), - ], + pallets: vec!["Proxy".to_owned(), "Multisig".to_owned()], ..Default::default() })) .build() @@ -639,6 +699,7 @@ mod remote_tests { async fn sanity_check_decoding() { use pallet_elections_phragmen::SeatHolder; use sp_core::crypto::Ss58Codec; + type AccountId = sp_runtime::AccountId32; type Balance = u128; frame_support::generate_storage_alias!( @@ -676,7 +737,7 @@ mod remote_tests { Builder::::new() .mode(Mode::Online(OnlineConfig { state_snapshot: Some(SnapshotConfig::new("test_snapshot_to_remove.bin")), - pallets: vec!["Balances".to_owned()], + pallets: vec!["Proxy".to_owned()], ..Default::default() })) .build() @@ -684,7 +745,7 @@ mod remote_tests { .expect(REMOTE_INACCESSIBLE) .execute_with(|| {}); - let to_delete = std::fs::read_dir(SnapshotConfig::default().path) + let to_delete = std::fs::read_dir(Path::new(".")) .unwrap() .into_iter() .map(|d| d.unwrap()) @@ -699,6 +760,7 @@ mod remote_tests { } #[tokio::test] + #[ignore = "takes too much time on average."] async fn can_fetch_all() { init_logger(); Builder::::new() From 5111c72d3d611c0a643d89a305b2c9a4fdaa9134 Mon Sep 17 00:00:00 2001 From: Dan Shields <35669742+NukeManDan@users.noreply.github.com> Date: Tue, 9 Nov 2021 14:27:40 -0700 Subject: [PATCH 159/695] move wiki -> docs (#10225) Co-authored-by: Dan Shields --- bin/utils/subkey/README.md | 2 +- client/cli/src/commands/run_cmd.rs | 4 ++-- primitives/core/src/crypto.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bin/utils/subkey/README.md b/bin/utils/subkey/README.md index 2310c59f4a28..e762a42c3e79 100644 --- a/bin/utils/subkey/README.md +++ b/bin/utils/subkey/README.md @@ -69,7 +69,7 @@ The output above also show the **public key** and the **Account ID**. Those are The **SS58 address** (or **Public Address**) of a new account is a reprensentation of the public keys of an account for a given network (for instance Kusama or Polkadot). -You can read more about the SS58 format in the [substrate wiki](https://github.com/paritytech/substrate/wiki/External-Address-Format-(SS58)) and see the list of reserved prefixes in the [Polkadot wiki](https://wiki.polkadot.network/docs/build-ss58-registry). +You can read more about the SS58 format in the [Substrate Docs](https://docs.substrate.io/v3/advanced/ss58/) and see the list of reserved prefixes in the [SS58 Registry](https://github.com/paritytech/ss58-registry). For instance, considering the previous seed `0xa05c75731970cc7868a2fb7cb577353cd5b31f62dccced92c441acd8fee0c92d` the SS58 addresses are: diff --git a/client/cli/src/commands/run_cmd.rs b/client/cli/src/commands/run_cmd.rs index d6c0133a7c14..ad2f04583c10 100644 --- a/client/cli/src/commands/run_cmd.rs +++ b/client/cli/src/commands/run_cmd.rs @@ -58,7 +58,7 @@ pub struct RunCmd { /// /// Default is local. Note: not all RPC methods are safe to be exposed publicly. Use an RPC /// proxy server to filter out dangerous methods. More details: - /// . + /// . /// Use `--unsafe-rpc-external` to suppress the warning if you understand the risks. #[structopt(long = "rpc-external")] pub rpc_external: bool, @@ -89,7 +89,7 @@ pub struct RunCmd { /// /// Default is local. Note: not all RPC methods are safe to be exposed publicly. Use an RPC /// proxy server to filter out dangerous methods. More details: - /// . + /// . /// Use `--unsafe-ws-external` to suppress the warning if you understand the risks. #[structopt(long = "ws-external")] pub ws_external: bool, diff --git a/primitives/core/src/crypto.rs b/primitives/core/src/crypto.rs index 21b8520c7780..4f21d62f5850 100644 --- a/primitives/core/src/crypto.rs +++ b/primitives/core/src/crypto.rs @@ -219,7 +219,7 @@ pub enum PublicError { /// Key that can be encoded to/from SS58. /// -/// See +/// See /// for information on the codec. #[cfg(feature = "full_crypto")] pub trait Ss58Codec: Sized + AsMut<[u8]> + AsRef<[u8]> + Default { From 5fe5974173b3f4edb83cb4f58c4af2a02685a364 Mon Sep 17 00:00:00 2001 From: Squirrel Date: Tue, 9 Nov 2021 22:33:21 +0000 Subject: [PATCH 160/695] upgrade ss58-registry with additional networks. (#10224) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * upgrade ss58-registry with additional networks. * adding cargo lock * Update primitives/core/Cargo.toml Co-authored-by: Bastian Köcher * turn on std Co-authored-by: Bastian Köcher --- Cargo.lock | 4 ++-- primitives/core/Cargo.toml | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b72f8ece09a4..5e940b93f65f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9995,9 +9995,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "ss58-registry" -version = "1.0.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef2413ecc7946ca99368862851dc1359f1477bc654ecfb135cf3efcb85ceca5f" +checksum = "c66cd4c4bb7ee41dc5b0c13d600574ae825d3a02e8f31326b17ac71558f2c836" dependencies = [ "Inflector", "proc-macro2", diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index 8262393e653f..9948b2e968c2 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -68,7 +68,7 @@ twox-hash = { version = "1.6.1", default-features = false, optional = true } libsecp256k1 = { version = "0.6", default-features = false, features = ["hmac", "static-context"], optional = true } sp-core-hashing = { version = "4.0.0-dev", path = "./hashing", default-features = false, optional = true } merlin = { version = "2.0", default-features = false, optional = true } -ss58-registry = "1.0.0" +ss58-registry = { version = "1.5.0", default-features = false } sp-runtime-interface = { version = "4.0.0-dev", default-features = false, path = "../runtime-interface" } [dev-dependencies] @@ -125,6 +125,7 @@ std = [ "sp-externalities", "sp-storage/std", "sp-runtime-interface/std", + "ss58-registry/std", "zeroize/alloc", "secrecy/alloc", "futures", From 1a6631117fdc66a65f3d484d5c8c015c4207f7c7 Mon Sep 17 00:00:00 2001 From: zjb0807 Date: Wed, 10 Nov 2021 16:03:52 +0800 Subject: [PATCH 161/695] Upgrade wasm builder (#10226) * add TypeInfo for DispatchTime * upgrade wasm-builder to Rust 2021 * remove resolver * revert resolver in virtual workspace --- utils/wasm-builder/src/prerequisites.rs | 2 +- utils/wasm-builder/src/wasm_project.rs | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/utils/wasm-builder/src/prerequisites.rs b/utils/wasm-builder/src/prerequisites.rs index c45f7933a1de..7236b8169bcb 100644 --- a/utils/wasm-builder/src/prerequisites.rs +++ b/utils/wasm-builder/src/prerequisites.rs @@ -58,7 +58,7 @@ fn create_check_toolchain_project(project_dir: &Path) { [package] name = "wasm-test" version = "1.0.0" - edition = "2018" + edition = "2021" build = "build.rs" [lib] diff --git a/utils/wasm-builder/src/wasm_project.rs b/utils/wasm-builder/src/wasm_project.rs index 3806a890a106..59214ab483c6 100644 --- a/utils/wasm-builder/src/wasm_project.rs +++ b/utils/wasm-builder/src/wasm_project.rs @@ -266,8 +266,7 @@ fn create_project_cargo_toml( let mut package = Table::new(); package.insert("name".into(), format!("{}-wasm", crate_name).into()); package.insert("version".into(), "1.0.0".into()); - package.insert("edition".into(), "2018".into()); - package.insert("resolver".into(), "2".into()); + package.insert("edition".into(), "2021".into()); wasm_workspace_toml.insert("package".into(), package.into()); From 7b24a94cb065ca1018019c825e6dfc21327b47c3 Mon Sep 17 00:00:00 2001 From: Jimmy Chu Date: Wed, 10 Nov 2021 16:11:28 +0800 Subject: [PATCH 162/695] Move all example pallets under `examples` folder. (#10215) * Put all examples under one folder Signed-off-by: Jimmy Chu * Updated Cargo.toml Signed-off-by: Jimmy Chu * updated for ci script Signed-off-by: Jimmy Chu * update Signed-off-by: Jimmy Chu * Added notes that example pallets are not meant to be used in production. Signed-off-by: Jimmy Chu * updated Signed-off-by: Jimmy Chu --- .gitlab-ci.yml | 6 +++--- Cargo.lock | 2 +- Cargo.toml | 6 +++--- frame/benchmarking/src/lib.rs | 4 ++-- frame/{example => examples/basic}/Cargo.toml | 21 ++++++++++--------- frame/{example => examples/basic}/README.md | 14 +++++++------ .../basic}/src/benchmarking.rs | 6 +++--- frame/{example => examples/basic}/src/lib.rs | 8 ++++--- .../{example => examples/basic}/src/tests.rs | 14 ++++++------- .../basic}/src/weights.rs | 8 +++---- .../offchain-worker}/Cargo.toml | 17 ++++++++------- .../offchain-worker}/README.md | 4 +++- .../offchain-worker}/src/lib.rs | 3 +++ .../offchain-worker}/src/tests.rs | 0 .../parallel}/Cargo.toml | 15 ++++++------- frame/examples/parallel/README.md | 7 +++++++ .../parallel}/src/lib.rs | 6 ++++-- .../parallel}/src/tests.rs | 0 18 files changed, 81 insertions(+), 60 deletions(-) rename frame/{example => examples/basic}/Cargo.toml (78%) rename frame/{example => examples/basic}/README.md (94%) rename frame/{example => examples/basic}/src/benchmarking.rs (93%) rename frame/{example => examples/basic}/src/lib.rs (99%) rename frame/{example => examples/basic}/src/tests.rs (92%) rename frame/{example => examples/basic}/src/weights.rs (93%) rename frame/{example-offchain-worker => examples/offchain-worker}/Cargo.toml (82%) rename frame/{example-offchain-worker => examples/offchain-worker}/README.md (87%) rename frame/{example-offchain-worker => examples/offchain-worker}/src/lib.rs (99%) rename frame/{example-offchain-worker => examples/offchain-worker}/src/tests.rs (100%) rename frame/{example-parallel => examples/parallel}/Cargo.toml (84%) create mode 100644 frame/examples/parallel/README.md rename frame/{example-parallel => examples/parallel}/src/lib.rs (95%) rename frame/{example-parallel => examples/parallel}/src/tests.rs (100%) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5e406b36c5c5..210bb447e4c7 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -41,7 +41,7 @@ variables: &default-vars CI_IMAGE: "paritytech/ci-linux:production" # FIXME set to release CARGO_UNLEASH_INSTALL_PARAMS: "--version 1.0.0-alpha.12" - CARGO_UNLEASH_PKG_DEF: "--skip node node-* pallet-template pallet-example pallet-example-* subkey chain-spec-builder" + CARGO_UNLEASH_PKG_DEF: "--skip node node-* pallet-template pallet-example-* subkey chain-spec-builder" VAULT_SERVER_URL: "https://vault.parity-mgmt-vault.parity.io" VAULT_AUTH_PATH: "gitlab-parity-io-jwt" VAULT_AUTH_ROLE: "cicd_gitlab_parity_${CI_PROJECT_NAME}" @@ -482,9 +482,9 @@ test-frame-examples-compile-to-wasm: RUSTFLAGS: "-Cdebug-assertions=y" RUST_BACKTRACE: 1 script: - - cd frame/example-offchain-worker/ + - cd frame/examples/offchain-worker/ - cargo +nightly build --target=wasm32-unknown-unknown --no-default-features - - cd ../example + - cd ../basic - cargo +nightly build --target=wasm32-unknown-unknown --no-default-features - sccache -s diff --git a/Cargo.lock b/Cargo.lock index 5e940b93f65f..a7bb471f90d8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5515,7 +5515,7 @@ dependencies = [ ] [[package]] -name = "pallet-example" +name = "pallet-example-basic" version = "4.0.0-dev" dependencies = [ "frame-benchmarking", diff --git a/Cargo.toml b/Cargo.toml index 07053a0ef316..ca60af692497 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -84,9 +84,9 @@ members = [ "frame/elections", "frame/election-provider-multi-phase", "frame/election-provider-support", - "frame/example", - "frame/example-offchain-worker", - "frame/example-parallel", + "frame/examples/basic", + "frame/examples/offchain-worker", + "frame/examples/parallel", "frame/executive", "frame/gilt", "frame/grandpa", diff --git a/frame/benchmarking/src/lib.rs b/frame/benchmarking/src/lib.rs index 258b40cbe6f0..088dbeb0bb78 100644 --- a/frame/benchmarking/src/lib.rs +++ b/frame/benchmarking/src/lib.rs @@ -1217,7 +1217,7 @@ macro_rules! impl_benchmark_test { /// This creates a test suite which runs the module's benchmarks. /// -/// When called in `pallet_example` as +/// When called in `pallet_example_basic` as /// /// ```rust,ignore /// impl_benchmark_test_suite!(Pallet, crate::tests::new_test_ext(), crate::tests::Test); @@ -1243,7 +1243,7 @@ macro_rules! impl_benchmark_test { /// } /// ``` /// -/// When called inside the `benchmarks` macro of the `pallet_example` as +/// When called inside the `benchmarks` macro of the `pallet_example_basic` as /// /// ```rust,ignore /// benchmarks! { diff --git a/frame/example/Cargo.toml b/frame/examples/basic/Cargo.toml similarity index 78% rename from frame/example/Cargo.toml rename to frame/examples/basic/Cargo.toml index 0b3a742de0dd..a4e8ffe3261c 100644 --- a/frame/example/Cargo.toml +++ b/frame/examples/basic/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "pallet-example" +name = "pallet-example-basic" version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2021" @@ -14,18 +14,19 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } -frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } -pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../balances" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } log = { version = "0.4.14", default-features = false } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } + +frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../../benchmarking", optional = true } +frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" } +frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" } +pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../../balances" } +sp-io = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/io" } +sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } +sp-std = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/std" } [dev-dependencies] -sp-core = { version = "4.0.0-dev", path = "../../primitives/core", default-features = false } +sp-core = { version = "4.0.0-dev", path = "../../../primitives/core", default-features = false } [features] default = ["std"] diff --git a/frame/example/README.md b/frame/examples/basic/README.md similarity index 94% rename from frame/example/README.md rename to frame/examples/basic/README.md index e06dee78c3f8..358829192f11 100644 --- a/frame/example/README.md +++ b/frame/examples/basic/README.md @@ -1,11 +1,13 @@ -# Example Pallet +# Basic Example Pallet The Example: A simple example of a FRAME pallet demonstrating concepts, APIs and structures common to most FRAME runtimes. -Run `cargo doc --package pallet-example --open` to view this pallet's documentation. +Run `cargo doc --package pallet-example-basic --open` to view this pallet's documentation. + +**This pallet serves as an example and is not meant to be used in production.** ### Documentation Guidelines: @@ -34,7 +36,7 @@ Run `cargo doc --package pallet-example --open` to view this pallet's documentat ### Documentation Template:
-Copy and paste this template from frame/example/src/lib.rs into file +Copy and paste this template from frame/examples/basic/src/lib.rs into file `frame//src/lib.rs` of your own custom pallet and complete it.

 // Add heading with custom pallet name
@@ -46,9 +48,9 @@ Copy and paste this template from frame/example/src/lib.rs into file
 // Include the following links that shows what trait needs to be implemented to use the pallet
 // and the supported dispatchables that are documented in the Call enum.
 
-- \[`::Config`](https://docs.rs/pallet-example/latest/pallet_example/trait.Config.html)
-- \[`Call`](https://docs.rs/pallet-example/latest/pallet_example/enum.Call.html)
-- \[`Module`](https://docs.rs/pallet-example/latest/pallet_example/struct.Module.html)
+- \[`::Config`](https://docs.rs/pallet-example-basic/latest/pallet_example_basic/trait.Config.html)
+- \[`Call`](https://docs.rs/pallet-example-basic/latest/pallet_example_basic/enum.Call.html)
+- \[`Module`](https://docs.rs/pallet-example-basic/latest/pallet_example_basic/struct.Module.html)
 
 \## Overview
 
diff --git a/frame/example/src/benchmarking.rs b/frame/examples/basic/src/benchmarking.rs
similarity index 93%
rename from frame/example/src/benchmarking.rs
rename to frame/examples/basic/src/benchmarking.rs
index e89c646e03f1..a031b15834d6 100644
--- a/frame/example/src/benchmarking.rs
+++ b/frame/examples/basic/src/benchmarking.rs
@@ -15,7 +15,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-//! Benchmarking for pallet-example.
+//! Benchmarking for pallet-example-basic.
 
 #![cfg(feature = "runtime-benchmarks")]
 
@@ -23,7 +23,7 @@ use crate::*;
 use frame_benchmarking::{benchmarks, whitelisted_caller};
 use frame_system::RawOrigin;
 
-// To actually run this benchmark on pallet-example, we need to put this pallet into the
+// To actually run this benchmark on pallet-example-basic, we need to put this pallet into the
 //   runtime and compile it with `runtime-benchmarks` feature. The detail procedures are
 //   documented at:
 //   https://docs.substrate.io/v3/runtime/benchmarking#how-to-benchmark
@@ -67,7 +67,7 @@ benchmarks! {
 	}
 
 	// This line generates test cases for benchmarking, and could be run by:
-	//   `cargo test -p pallet-example --all-features`, you will see one line per case:
+	//   `cargo test -p pallet-example-basic --all-features`, you will see one line per case:
 	//   `test benchmarking::bench_sort_vector ... ok`
 	//   `test benchmarking::bench_accumulate_dummy ... ok`
 	//   `test benchmarking::bench_set_dummy_benchmark ... ok` in the result.
diff --git a/frame/example/src/lib.rs b/frame/examples/basic/src/lib.rs
similarity index 99%
rename from frame/example/src/lib.rs
rename to frame/examples/basic/src/lib.rs
index 981274b1ba73..b172acb66d32 100644
--- a/frame/example/src/lib.rs
+++ b/frame/examples/basic/src/lib.rs
@@ -16,13 +16,15 @@
 // limitations under the License.
 
 //! 
-//! # Example Pallet
+//! # Basic Example Pallet
 //!
 //! 
 //! The Example: A simple example of a FRAME pallet demonstrating
 //! concepts, APIs and structures common to most FRAME runtimes.
 //!
-//! Run `cargo doc --package pallet-example --open` to view this pallet's documentation.
+//! Run `cargo doc --package pallet-example-basic --open` to view this pallet's documentation.
+//!
+//! **This pallet serves as an example and is not meant to be used in production.**
 //!
 //! ### Documentation Guidelines:
 //!
@@ -59,7 +61,7 @@
 //!
 //! ### Documentation Template:
//! -//! Copy and paste this template from frame/example/src/lib.rs into file +//! Copy and paste this template from frame/examples/basic/src/lib.rs into file //! `frame//src/lib.rs` of your own custom pallet and complete it. //!

 //! // Add heading with custom pallet name
diff --git a/frame/example/src/tests.rs b/frame/examples/basic/src/tests.rs
similarity index 92%
rename from frame/example/src/tests.rs
rename to frame/examples/basic/src/tests.rs
index 4c2274572db8..e069cccf8d80 100644
--- a/frame/example/src/tests.rs
+++ b/frame/examples/basic/src/tests.rs
@@ -15,7 +15,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-//! Tests for pallet-example.
+//! Tests for pallet-example-basic.
 
 use crate::*;
 use frame_support::{
@@ -32,7 +32,7 @@ use sp_runtime::{
 	BuildStorage,
 };
 // Reexport crate as its pallet name for construct_runtime.
-use crate as pallet_example;
+use crate as pallet_example_basic;
 
 type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic;
 type Block = frame_system::mocking::MockBlock;
@@ -46,7 +46,7 @@ frame_support::construct_runtime!(
 	{
 		System: frame_system::{Pallet, Call, Config, Storage, Event},
 		Balances: pallet_balances::{Pallet, Call, Storage, Config, Event},
-		Example: pallet_example::{Pallet, Call, Storage, Config, Event},
+		Example: pallet_example_basic::{Pallet, Call, Storage, Config, Event},
 	}
 );
 
@@ -111,7 +111,7 @@ pub fn new_test_ext() -> sp_io::TestExternalities {
 		// We use default for brevity, but you can configure as desired if needed.
 		system: Default::default(),
 		balances: Default::default(),
-		example: pallet_example::GenesisConfig {
+		example: pallet_example_basic::GenesisConfig {
 			dummy: 42,
 			// we configure the map with (key, value) pairs.
 			bar: vec![(1, 2), (2, 3)],
@@ -163,7 +163,7 @@ fn set_dummy_works() {
 #[test]
 fn signed_ext_watch_dummy_works() {
 	new_test_ext().execute_with(|| {
-		let call = pallet_example::Call::set_dummy { new_value: 10 }.into();
+		let call = pallet_example_basic::Call::set_dummy { new_value: 10 }.into();
 		let info = DispatchInfo::default();
 
 		assert_eq!(
@@ -192,14 +192,14 @@ fn counted_map_works() {
 #[test]
 fn weights_work() {
 	// must have a defined weight.
-	let default_call = pallet_example::Call::::accumulate_dummy { increase_by: 10 };
+	let default_call = pallet_example_basic::Call::::accumulate_dummy { increase_by: 10 };
 	let info1 = default_call.get_dispatch_info();
 	// aka. `let info =  as GetDispatchInfo>::get_dispatch_info(&default_call);`
 	assert!(info1.weight > 0);
 
 	// `set_dummy` is simpler than `accumulate_dummy`, and the weight
 	//   should be less.
-	let custom_call = pallet_example::Call::::set_dummy { new_value: 20 };
+	let custom_call = pallet_example_basic::Call::::set_dummy { new_value: 20 };
 	let info2 = custom_call.get_dispatch_info();
 	assert!(info1.weight > info2.weight);
 }
diff --git a/frame/example/src/weights.rs b/frame/examples/basic/src/weights.rs
similarity index 93%
rename from frame/example/src/weights.rs
rename to frame/examples/basic/src/weights.rs
index efcfdc6729b5..048f7f5a8b8e 100644
--- a/frame/example/src/weights.rs
+++ b/frame/examples/basic/src/weights.rs
@@ -15,7 +15,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-//! Autogenerated weights for pallet_example
+//! Autogenerated weights for pallet_example_basic
 //!
 //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0
 //! DATE: 2021-03-15, STEPS: `[100, ]`, REPEAT: 10, LOW RANGE: `[]`, HIGH RANGE: `[]`
@@ -31,7 +31,7 @@
 // --wasm-execution
 // compiled
 // --pallet
-// pallet_example
+// pallet_example_basic
 // --extrinsic
 // *
 // --steps
@@ -52,14 +52,14 @@
 use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
 use sp_std::marker::PhantomData;
 
-/// Weight functions needed for pallet_example.
+/// Weight functions needed for pallet_example_basic.
 pub trait WeightInfo {
 	fn set_dummy_benchmark(b: u32, ) -> Weight;
 	fn accumulate_dummy(b: u32, ) -> Weight;
 	fn sort_vector(x: u32, ) -> Weight;
 }
 
-/// Weights for pallet_example using the Substrate node and recommended hardware.
+/// Weights for pallet_example_basic using the Substrate node and recommended hardware.
 pub struct SubstrateWeight(PhantomData);
 impl WeightInfo for SubstrateWeight {
 	fn set_dummy_benchmark(b: u32, ) -> Weight {
diff --git a/frame/example-offchain-worker/Cargo.toml b/frame/examples/offchain-worker/Cargo.toml
similarity index 82%
rename from frame/example-offchain-worker/Cargo.toml
rename to frame/examples/offchain-worker/Cargo.toml
index ffcadca26e11..cb505ad42f25 100644
--- a/frame/example-offchain-worker/Cargo.toml
+++ b/frame/examples/offchain-worker/Cargo.toml
@@ -14,16 +14,17 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false }
-scale-info = { version = "1.0", default-features = false, features = ["derive"] }
-frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" }
-frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" }
-sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" }
-sp-keystore = { version = "0.10.0-dev", path = "../../primitives/keystore", optional = true }
-sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" }
-sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" }
-sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" }
 lite-json = { version = "0.1", default-features = false }
 log = { version = "0.4.14", default-features = false }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
+
+frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" }
+frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" }
+sp-core = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/core" }
+sp-io = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/io" }
+sp-keystore = { version = "0.10.0-dev", path = "../../../primitives/keystore", optional = true }
+sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" }
+sp-std = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/std" }
 
 [features]
 default = ["std"]
diff --git a/frame/example-offchain-worker/README.md b/frame/examples/offchain-worker/README.md
similarity index 87%
rename from frame/example-offchain-worker/README.md
rename to frame/examples/offchain-worker/README.md
index 5299027f3925..587431c92c0e 100644
--- a/frame/example-offchain-worker/README.md
+++ b/frame/examples/offchain-worker/README.md
@@ -1,5 +1,5 @@
 
-# Offchain Worker Example Module
+# Offchain Worker Example Pallet
 
 The Offchain Worker Example: A simple pallet demonstrating
 concepts, APIs and structures common to most offchain workers.
@@ -11,6 +11,8 @@ documentation.
 - [`Call`](./enum.Call.html)
 - [`Module`](./struct.Module.html)
 
+**This pallet serves as an example showcasing Substrate off-chain worker and is not meant to be
+used in production.**
 
 ## Overview
 
diff --git a/frame/example-offchain-worker/src/lib.rs b/frame/examples/offchain-worker/src/lib.rs
similarity index 99%
rename from frame/example-offchain-worker/src/lib.rs
rename to frame/examples/offchain-worker/src/lib.rs
index 9b63ffa663ee..e5f2e00d9a34 100644
--- a/frame/example-offchain-worker/src/lib.rs
+++ b/frame/examples/offchain-worker/src/lib.rs
@@ -28,6 +28,8 @@
 //! - [`Call`]
 //! - [`Pallet`]
 //!
+//! **This pallet serves as an example showcasing Substrate off-chain worker and is not meant to
+//! be used in production.**
 //!
 //! ## Overview
 //!
@@ -40,6 +42,7 @@
 //! Additional logic in OCW is put in place to prevent spamming the network with both signed
 //! and unsigned transactions, and custom `UnsignedValidator` makes sure that there is only
 //! one unsigned transaction floating in the network.
+
 #![cfg_attr(not(feature = "std"), no_std)]
 
 use codec::{Decode, Encode};
diff --git a/frame/example-offchain-worker/src/tests.rs b/frame/examples/offchain-worker/src/tests.rs
similarity index 100%
rename from frame/example-offchain-worker/src/tests.rs
rename to frame/examples/offchain-worker/src/tests.rs
diff --git a/frame/example-parallel/Cargo.toml b/frame/examples/parallel/Cargo.toml
similarity index 84%
rename from frame/example-parallel/Cargo.toml
rename to frame/examples/parallel/Cargo.toml
index 169db35e65f1..cf7f46b23224 100644
--- a/frame/example-parallel/Cargo.toml
+++ b/frame/examples/parallel/Cargo.toml
@@ -14,13 +14,14 @@ targets = ["x86_64-unknown-linux-gnu"]
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false }
 scale-info = { version = "1.0", default-features = false, features = ["derive"] }
-frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" }
-frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" }
-sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" }
-sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" }
-sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" }
-sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" }
-sp-tasks = { version = "4.0.0-dev", default-features = false, path = "../../primitives/tasks" }
+
+frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" }
+frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" }
+sp-core = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/core" }
+sp-io = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/io" }
+sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" }
+sp-std = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/std" }
+sp-tasks = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/tasks" }
 
 [features]
 default = ["std"]
diff --git a/frame/examples/parallel/README.md b/frame/examples/parallel/README.md
new file mode 100644
index 000000000000..44b39a41507d
--- /dev/null
+++ b/frame/examples/parallel/README.md
@@ -0,0 +1,7 @@
+
+# Parallel Tasks Example Pallet
+
+This example pallet demonstrates parallelizing validation of the enlisted participants (see
+`enlist_participants` dispatch).
+
+**This pallet serves as an example and is not meant to be used in production.**
diff --git a/frame/example-parallel/src/lib.rs b/frame/examples/parallel/src/lib.rs
similarity index 95%
rename from frame/example-parallel/src/lib.rs
rename to frame/examples/parallel/src/lib.rs
index 9d191525f631..51e022bed08b 100644
--- a/frame/example-parallel/src/lib.rs
+++ b/frame/examples/parallel/src/lib.rs
@@ -15,10 +15,12 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-//! Parallel tasks example
+//! # Parallel Tasks Example Pallet
 //!
-//! This example pallet parallelizes validation of the enlisted participants
+//! This example pallet demonstrates parallelizing validation of the enlisted participants
 //! (see `enlist_participants` dispatch).
+//!
+//! **This pallet serves as an example and is not meant to be used in production.**
 
 #![cfg_attr(not(feature = "std"), no_std)]
 
diff --git a/frame/example-parallel/src/tests.rs b/frame/examples/parallel/src/tests.rs
similarity index 100%
rename from frame/example-parallel/src/tests.rs
rename to frame/examples/parallel/src/tests.rs

From 6ec26dfc9268ab0a43fa41db84386261ed000d9b Mon Sep 17 00:00:00 2001
From: Kian Paimani <5588131+kianenigma@users.noreply.github.com>
Date: Wed, 10 Nov 2021 09:33:14 +0000
Subject: [PATCH 163/695] use CountedMap in pallet-bags-list (#10179)

* use CountedMap in pallet-bags-list

* Fix build

* Update frame/bags-list/src/list/mod.rs

Co-authored-by: Keith Yeung 

* add a check as well

Co-authored-by: Keith Yeung 
---
 bin/node/runtime/src/lib.rs                   |  2 +-
 frame/bags-list/Cargo.toml                    |  5 +-
 frame/bags-list/src/lib.rs                    | 12 ++---
 frame/bags-list/src/list/mod.rs               | 33 +++++--------
 frame/bags-list/src/list/tests.rs             | 23 ++++++---
 frame/bags-list/src/migrations.rs             | 49 +++++++++++++++++++
 frame/bags-list/src/tests.rs                  |  2 +-
 .../support/src/storage/types/counted_map.rs  | 12 +++--
 8 files changed, 94 insertions(+), 44 deletions(-)
 create mode 100644 frame/bags-list/src/migrations.rs

diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs
index 570abe53ed01..6d04ca8fdca8 100644
--- a/bin/node/runtime/src/lib.rs
+++ b/bin/node/runtime/src/lib.rs
@@ -1330,7 +1330,7 @@ pub type Executive = frame_executive::Executive<
 	frame_system::ChainContext,
 	Runtime,
 	AllPallets,
-	(),
+	pallet_bags_list::migrations::CheckCounterPrefix,
 >;
 
 /// MMR helper types.
diff --git a/frame/bags-list/Cargo.toml b/frame/bags-list/Cargo.toml
index fa47b9bad569..6d4cf2363c4f 100644
--- a/frame/bags-list/Cargo.toml
+++ b/frame/bags-list/Cargo.toml
@@ -64,9 +64,10 @@ runtime-benchmarks = [
 	"frame-election-provider-support/runtime-benchmarks",
 ]
 fuzz = [
-  "sp-core",
+	"sp-core",
 	"sp-io",
-  "pallet-balances",
+	"pallet-balances",
 	"sp-tracing",
 ]
+try-runtime = [ "frame-support/try-runtime" ]
 
diff --git a/frame/bags-list/src/lib.rs b/frame/bags-list/src/lib.rs
index b7f96799e459..8d74ecc9bd2d 100644
--- a/frame/bags-list/src/lib.rs
+++ b/frame/bags-list/src/lib.rs
@@ -59,6 +59,7 @@ use sp_std::prelude::*;
 mod benchmarks;
 
 mod list;
+pub mod migrations;
 #[cfg(any(test, feature = "fuzz"))]
 pub mod mock;
 #[cfg(test)]
@@ -151,17 +152,12 @@ pub mod pallet {
 		type BagThresholds: Get<&'static [VoteWeight]>;
 	}
 
-	/// How many ids are registered.
-	// NOTE: This is merely a counter for `ListNodes`. It should someday be replaced by the
-	// `CountedMap` storage.
-	#[pallet::storage]
-	pub(crate) type CounterForListNodes = StorageValue<_, u32, ValueQuery>;
-
 	/// A single node, within some bag.
 	///
 	/// Nodes store links forward and back within their respective bags.
 	#[pallet::storage]
-	pub(crate) type ListNodes = StorageMap<_, Twox64Concat, T::AccountId, list::Node>;
+	pub(crate) type ListNodes =
+		CountedStorageMap<_, Twox64Concat, T::AccountId, list::Node>;
 
 	/// A bag stored in storage.
 	///
@@ -240,7 +236,7 @@ impl SortedListProvider for Pallet {
 	}
 
 	fn count() -> u32 {
-		CounterForListNodes::::get()
+		ListNodes::::count()
 	}
 
 	fn contains(id: &T::AccountId) -> bool {
diff --git a/frame/bags-list/src/list/mod.rs b/frame/bags-list/src/list/mod.rs
index 4efc3163816f..df966eea80ce 100644
--- a/frame/bags-list/src/list/mod.rs
+++ b/frame/bags-list/src/list/mod.rs
@@ -18,7 +18,7 @@
 //! Implementation of a "bags list": a semi-sorted list where ordering granularity is dictated by
 //! configurable thresholds that delineate the boundaries of bags. It uses a pattern of composite
 //! data structures, where multiple storage items are masked by one outer API. See [`ListNodes`],
-//! [`CounterForListNodes`] and [`ListBags`] for more information.
+//! [`ListBags`] for more information.
 //!
 //! The outer API of this module is the [`List`] struct. It wraps all acceptable operations on top
 //! of the aggregate linked list. All operations with the bags list should happen through this
@@ -77,17 +77,18 @@ pub struct List(PhantomData);
 
 impl List {
 	/// Remove all data associated with the list from storage. Parameter `items` is the number of
-	/// items to clear from the list. WARNING: `None` will clear all items and should generally not
-	/// be used in production as it could lead to an infinite number of storage accesses.
+	/// items to clear from the list.
+	///
+	/// ## WARNING
+	///
+	/// `None` will clear all items and should generally not be used in production as it could lead
+	/// to a very large number of storage accesses.
 	pub(crate) fn clear(maybe_count: Option) -> u32 {
 		crate::ListBags::::remove_all(maybe_count);
+		let pre = crate::ListNodes::::count();
 		crate::ListNodes::::remove_all(maybe_count);
-		if let Some(count) = maybe_count {
-			crate::CounterForListNodes::::mutate(|items| *items - count);
-			count
-		} else {
-			crate::CounterForListNodes::::take()
-		}
+		let post = crate::ListNodes::::count();
+		pre.saturating_sub(post)
 	}
 
 	/// Regenerate all of the data from the given ids.
@@ -274,17 +275,13 @@ impl List {
 		// new inserts are always the tail, so we must write the bag.
 		bag.put();
 
-		crate::CounterForListNodes::::mutate(|prev_count| {
-			*prev_count = prev_count.saturating_add(1)
-		});
-
 		crate::log!(
 			debug,
 			"inserted {:?} with weight {} into bag {:?}, new count is {}",
 			id,
 			weight,
 			bag_weight,
-			crate::CounterForListNodes::::get(),
+			crate::ListNodes::::count(),
 		);
 
 		Ok(())
@@ -331,10 +328,6 @@ impl List {
 			bag.put();
 		}
 
-		crate::CounterForListNodes::::mutate(|prev_count| {
-			*prev_count = prev_count.saturating_sub(count)
-		});
-
 		count
 	}
 
@@ -390,7 +383,7 @@ impl List {
 	/// is being used, after all other staking data (such as counter) has been updated. It checks:
 	///
 	/// * there are no duplicate ids,
-	/// * length of this list is in sync with `CounterForListNodes`,
+	/// * length of this list is in sync with `ListNodes::count()`,
 	/// * and sanity-checks all bags and nodes. This will cascade down all the checks and makes sure
 	/// all bags and nodes are checked per *any* update to `List`.
 	#[cfg(feature = "std")]
@@ -403,7 +396,7 @@ impl List {
 		);
 
 		let iter_count = Self::iter().count() as u32;
-		let stored_count = crate::CounterForListNodes::::get();
+		let stored_count = crate::ListNodes::::count();
 		let nodes_count = crate::ListNodes::::iter().count() as u32;
 		ensure!(iter_count == stored_count, "iter_count != stored_count");
 		ensure!(stored_count == nodes_count, "stored_count != nodes_count");
diff --git a/frame/bags-list/src/list/tests.rs b/frame/bags-list/src/list/tests.rs
index 14802bac9d1d..1c345df9a2fb 100644
--- a/frame/bags-list/src/list/tests.rs
+++ b/frame/bags-list/src/list/tests.rs
@@ -18,7 +18,7 @@
 use super::*;
 use crate::{
 	mock::{test_utils::*, *},
-	CounterForListNodes, ListBags, ListNodes,
+	ListBags, ListNodes,
 };
 use frame_election_provider_support::SortedListProvider;
 use frame_support::{assert_ok, assert_storage_noop};
@@ -29,7 +29,7 @@ fn basic_setup_works() {
 		// syntactic sugar to create a raw node
 		let node = |id, prev, next, bag_upper| Node:: { id, prev, next, bag_upper };
 
-		assert_eq!(CounterForListNodes::::get(), 4);
+		assert_eq!(ListNodes::::count(), 4);
 		assert_eq!(ListNodes::::iter().count(), 4);
 		assert_eq!(ListBags::::iter().count(), 2);
 
@@ -249,10 +249,10 @@ mod list {
 
 	#[test]
 	fn remove_works() {
-		use crate::{CounterForListNodes, ListBags, ListNodes};
+		use crate::{ListBags, ListNodes};
 		let ensure_left = |id, counter| {
 			assert!(!ListNodes::::contains_key(id));
-			assert_eq!(CounterForListNodes::::get(), counter);
+			assert_eq!(ListNodes::::count(), counter);
 			assert_eq!(ListNodes::::iter().count() as u32, counter);
 		};
 
@@ -357,10 +357,19 @@ mod list {
 			assert_eq!(List::::sanity_check(), Err("duplicate identified"));
 		});
 
-		// ensure count is in sync with `CounterForListNodes`.
+		// ensure count is in sync with `ListNodes::count()`.
 		ExtBuilder::default().build_and_execute_no_post_check(|| {
-			crate::CounterForListNodes::::mutate(|counter| *counter += 1);
-			assert_eq!(crate::CounterForListNodes::::get(), 5);
+			assert_eq!(crate::ListNodes::::count(), 4);
+			// we do some wacky stuff here to get access to the counter, since it is (reasonably)
+			// not exposed as mutable in any sense.
+			frame_support::generate_storage_alias!(
+				BagsList,
+				CounterForListNodes
+				=> Value
+			);
+			CounterForListNodes::mutate(|counter| *counter += 1);
+			assert_eq!(crate::ListNodes::::count(), 5);
+
 			assert_eq!(List::::sanity_check(), Err("iter_count != stored_count"));
 		});
 	}
diff --git a/frame/bags-list/src/migrations.rs b/frame/bags-list/src/migrations.rs
new file mode 100644
index 000000000000..8c907539c05f
--- /dev/null
+++ b/frame/bags-list/src/migrations.rs
@@ -0,0 +1,49 @@
+// This file is part of Substrate.
+
+// Copyright (C) 2021 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.
+
+//! The migrations of this pallet.
+
+use frame_support::traits::OnRuntimeUpgrade;
+
+/// A struct that does not migration, but only checks that the counter prefix exists and is correct.
+pub struct CheckCounterPrefix(sp_std::marker::PhantomData);
+impl OnRuntimeUpgrade for CheckCounterPrefix {
+	fn on_runtime_upgrade() -> frame_support::weights::Weight {
+		0
+	}
+
+	#[cfg(feature = "try-runtime")]
+	fn pre_upgrade() -> Result<(), &'static str> {
+		use frame_support::ensure;
+		// The old explicit storage item.
+		frame_support::generate_storage_alias!(BagsList, CounterForListNodes => Value);
+
+		// ensure that a value exists in the counter struct.
+		ensure!(
+			crate::ListNodes::::count() == CounterForListNodes::get().unwrap(),
+			"wrong list node counter"
+		);
+
+		crate::log!(
+			info,
+			"checked bags-list prefix to be correct and have {} nodes",
+			crate::ListNodes::::count()
+		);
+
+		Ok(())
+	}
+}
diff --git a/frame/bags-list/src/tests.rs b/frame/bags-list/src/tests.rs
index e94017730668..270d25855ccd 100644
--- a/frame/bags-list/src/tests.rs
+++ b/frame/bags-list/src/tests.rs
@@ -340,7 +340,7 @@ mod sorted_list_provider {
 		let ensure_left = |id, counter| {
 			assert!(!ListNodes::::contains_key(id));
 			assert_eq!(BagsList::count(), counter);
-			assert_eq!(CounterForListNodes::::get(), counter);
+			assert_eq!(ListNodes::::count(), counter);
 			assert_eq!(ListNodes::::iter().count() as u32, counter);
 		};
 
diff --git a/frame/support/src/storage/types/counted_map.rs b/frame/support/src/storage/types/counted_map.rs
index 0860a4ed541c..51edf1089026 100644
--- a/frame/support/src/storage/types/counted_map.rs
+++ b/frame/support/src/storage/types/counted_map.rs
@@ -31,6 +31,7 @@ use crate::{
 	Never,
 };
 use codec::{Decode, Encode, EncodeLike, FullCodec, MaxEncodedLen, Ref};
+use sp_arithmetic::traits::Bounded;
 use sp_runtime::traits::Saturating;
 use sp_std::prelude::*;
 
@@ -262,9 +263,10 @@ where
 	}
 
 	/// Remove all value of the storage.
-	pub fn remove_all() {
-		CounterFor::::set(0u32);
-		::Map::remove_all(None);
+	pub fn remove_all(maybe_limit: Option) {
+		let leftover = Self::count().saturating_sub(maybe_limit.unwrap_or_else(Bounded::max_value));
+		CounterFor::::set(leftover);
+		::Map::remove_all(maybe_limit);
 	}
 
 	/// Iter over all value of the storage.
@@ -676,7 +678,7 @@ mod test {
 			assert_eq!(A::count(), 2);
 
 			// Remove all.
-			A::remove_all();
+			A::remove_all(None);
 
 			assert_eq!(A::count(), 0);
 			assert_eq!(A::initialize_counter(), 0);
@@ -907,7 +909,7 @@ mod test {
 			assert_eq!(B::count(), 2);
 
 			// Remove all.
-			B::remove_all();
+			B::remove_all(None);
 
 			assert_eq!(B::count(), 0);
 			assert_eq!(B::initialize_counter(), 0);

From 755569d202b4007179cc250279bad55df45b5f7d Mon Sep 17 00:00:00 2001
From: Denis Pisarev 
Date: Wed, 10 Nov 2021 11:39:30 +0100
Subject: [PATCH 164/695] CI: build docs with deps (#9884)

---
 .gitlab-ci.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 210bb447e4c7..8826b29de978 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -661,7 +661,7 @@ build-rustdoc:
     - ./crate-docs/
   script:
     # FIXME: it fails with `RUSTDOCFLAGS="-Dwarnings"`
-    - time cargo +nightly doc --no-deps --workspace --all-features --verbose
+    - time cargo +nightly doc --workspace --all-features --verbose
     - rm -f ./target/doc/.lock
     - mv ./target/doc ./crate-docs
     # FIXME: remove me after CI image gets nonroot

From 3374a73c9824638b8270062b104906a714ea14f9 Mon Sep 17 00:00:00 2001
From: Benjamin Kampmann 
Date: Wed, 10 Nov 2021 17:30:24 +0100
Subject: [PATCH 165/695] Intend to reactivate cargo-unleash check (#10167)

* Intend to reactivate cargo-unleash check

It appears the bug it was deactivated for has been resolved a while ago. Trying to reactivate the checks.

* adding missing cargo.toml metadata for BEEFY crates

* fix wrong version reference

* matching up versions

* disable faulty cache

* switching more versions to prerelease

* Revert "disable faulty cache"

This reverts commit 411a12ae444a9695a8bfea4458a868438d870b06.

* bump minor of sc-allocator to fix already-published-issue

* fixup another pre-released dependency problem

* temp switch to latest unleash

* fixing dependency version and features

* prometheus endpoint has also been changed

* fixing proposer metrics versioning

* fixing hex feature for beefy

* fix generate-bags feature selection

* fixup Cargo.lock

* upgrade prometheus dependencies

* missed one

* switch to latest release
---
 .gitlab-ci.yml                                | 28 ++++++-------
 Cargo.lock                                    | 42 +++++++++----------
 client/allocator/Cargo.toml                   |  2 +-
 client/api/Cargo.toml                         |  2 +-
 client/authority-discovery/Cargo.toml         |  2 +-
 client/basic-authorship/Cargo.toml            |  4 +-
 client/beefy/Cargo.toml                       |  4 +-
 client/beefy/rpc/Cargo.toml                   |  2 +
 client/cli/Cargo.toml                         |  2 +-
 client/consensus/aura/Cargo.toml              |  2 +-
 client/consensus/babe/Cargo.toml              |  2 +-
 client/consensus/common/Cargo.toml            |  2 +-
 client/consensus/manual-seal/Cargo.toml       |  2 +-
 client/consensus/pow/Cargo.toml               |  2 +-
 client/executor/Cargo.toml                    |  4 +-
 client/executor/common/Cargo.toml             |  6 +--
 client/executor/wasmi/Cargo.toml              |  2 +-
 client/executor/wasmtime/Cargo.toml           |  2 +-
 client/finality-grandpa/Cargo.toml            |  2 +-
 client/network-gossip/Cargo.toml              |  2 +-
 client/network/Cargo.toml                     |  2 +-
 client/offchain/Cargo.toml                    |  6 +--
 client/proposer-metrics/Cargo.toml            |  4 +-
 client/rpc-servers/Cargo.toml                 |  2 +-
 client/service/Cargo.toml                     |  2 +-
 client/service/test/Cargo.toml                |  2 +-
 client/transaction-pool/Cargo.toml            |  2 +-
 client/utils/Cargo.toml                       |  2 +-
 frame/beefy-mmr/Cargo.toml                    |  1 +
 frame/beefy-mmr/primitives/Cargo.toml         |  3 +-
 frame/beefy/Cargo.toml                        |  2 +
 primitives/arithmetic/Cargo.toml              |  2 +-
 primitives/beefy/Cargo.toml                   |  2 +
 primitives/core/Cargo.toml                    |  4 +-
 primitives/debug-derive/Cargo.toml            |  2 +-
 primitives/maybe-compressed-blob/Cargo.toml   |  2 +-
 primitives/panic-handler/Cargo.toml           |  2 +-
 primitives/serializer/Cargo.toml              |  2 +-
 primitives/state-machine/Cargo.toml           |  2 +-
 primitives/storage/Cargo.toml                 |  2 +-
 utils/frame/generate-bags/Cargo.toml          | 10 ++---
 .../generate-bags/node-runtime/Cargo.toml     |  2 +-
 utils/prometheus/Cargo.toml                   |  8 ++--
 utils/wasm-builder/Cargo.toml                 |  2 +-
 44 files changed, 97 insertions(+), 89 deletions(-)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 8826b29de978..aa275061088d 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -40,7 +40,7 @@ variables:                         &default-vars
   ARCH:                            "x86_64"
   CI_IMAGE:                        "paritytech/ci-linux:production"
   # FIXME set to release
-  CARGO_UNLEASH_INSTALL_PARAMS:    "--version 1.0.0-alpha.12"
+  CARGO_UNLEASH_INSTALL_PARAMS:    "--version 1.0.0-alpha.13"
   CARGO_UNLEASH_PKG_DEF:           "--skip node node-* pallet-template pallet-example-* subkey chain-spec-builder"
   VAULT_SERVER_URL:                "https://vault.parity-mgmt-vault.parity.io"
   VAULT_AUTH_PATH:                 "gitlab-parity-io-jwt"
@@ -455,20 +455,20 @@ test-linux-stable:                 &test-linux
     - SUBSTRATE_TEST_TIMEOUT=1 time cargo test -p substrate-test-utils --release --verbose --locked -- --ignored timeout
     - sccache -s
 
-#unleash-check:
-  #stage:                           test
-  #<<:                              *docker-env
-  #<<:                              *test-refs-no-trigger
-  #script:
-    #- cargo install cargo-unleash ${CARGO_UNLEASH_INSTALL_PARAMS}
-    #- cargo unleash de-dev-deps
+unleash-check:
+  stage:                           test
+  <<:                              *docker-env
+  <<:                              *test-refs-no-trigger
+  script:
+    - cargo install cargo-unleash ${CARGO_UNLEASH_INSTALL_PARAMS}
+    - cargo unleash de-dev-deps
     # Reuse build artifacts when running checks (cuts down check time by 3x)
     # TODO: Implement this optimization in cargo-unleash rather than here
-    #- mkdir -p target/unleash
-    #- export CARGO_TARGET_DIR=target/unleash
-    #- cargo unleash check ${CARGO_UNLEASH_PKG_DEF}
+    - mkdir -p target/unleash
+    - export CARGO_TARGET_DIR=target/unleash
+    - cargo unleash check ${CARGO_UNLEASH_PKG_DEF}
   # FIXME: this job must not fail, or unleash-to-crates-io will publish broken stuff
-  #allow_failure:                   true
+  allow_failure:                   true
 
 test-frame-examples-compile-to-wasm:
   # into one job
@@ -872,9 +872,7 @@ unleash-to-crates-io:
   <<:                              *vault-secrets
   rules:
     - if: $CI_COMMIT_REF_NAME =~ /^ci-release-.*$/
-    # FIXME: wait until https://github.com/paritytech/cargo-unleash/issues/50 is fixed, also
-    # remove allow_failure: true on the check job
-    # - if: $CI_COMMIT_REF_NAME =~ /^v[0-9]+\.[0-9]+.*$/              # i.e. v1.0, v2.1rc1
+    - if: $CI_COMMIT_REF_NAME =~ /^v[0-9]+\.[0-9]+.*$/              # i.e. v1.0, v2.1rc1
   script:
     - cargo install cargo-unleash ${CARGO_UNLEASH_INSTALL_PARAMS}
     - cargo unleash em-dragons --no-check --owner github:paritytech:core-devs ${CARGO_UNLEASH_PKG_DEF}
diff --git a/Cargo.lock b/Cargo.lock
index a7bb471f90d8..69cd80e292f8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2400,7 +2400,7 @@ checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2"
 
 [[package]]
 name = "generate-bags"
-version = "3.0.0"
+version = "4.0.0-dev"
 dependencies = [
  "chrono",
  "frame-election-provider-support",
@@ -2698,9 +2698,9 @@ dependencies = [
 
 [[package]]
 name = "httparse"
-version = "1.4.1"
+version = "1.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f3a87b616e37e93c22fb19bcd386f02f3af5ea98a25670ad0fce773de23c5e68"
+checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503"
 
 [[package]]
 name = "httpdate"
@@ -2744,9 +2744,9 @@ dependencies = [
 
 [[package]]
 name = "hyper"
-version = "0.14.11"
+version = "0.14.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b61cf2d1aebcf6e6352c97b81dc2244ca29194be1b276f5d8ad5c6330fffb11"
+checksum = "2b91bb1f221b6ea1f1e4371216b70f40748774c2fb5971b450c07773fb92d26b"
 dependencies = [
  "bytes 1.0.1",
  "futures-channel",
@@ -2773,7 +2773,7 @@ checksum = "5f9f7a97316d44c0af9b0301e65010573a853a9fc97046d7331d7f6bc0fd5a64"
 dependencies = [
  "ct-logs",
  "futures-util",
- "hyper 0.14.11",
+ "hyper 0.14.14",
  "log 0.4.14",
  "rustls",
  "rustls-native-certs",
@@ -2789,7 +2789,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
 dependencies = [
  "bytes 1.0.1",
- "hyper 0.14.11",
+ "hyper 0.14.14",
  "native-tls",
  "tokio",
  "tokio-native-tls",
@@ -3012,7 +3012,7 @@ checksum = "d2b99d4207e2a04fb4581746903c2bb7eb376f88de9c699d0f3e10feeac0cd3a"
 dependencies = [
  "derive_more",
  "futures 0.3.16",
- "hyper 0.14.11",
+ "hyper 0.14.14",
  "hyper-tls",
  "jsonrpc-core",
  "jsonrpc-pubsub",
@@ -3068,7 +3068,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e1dea6e07251d9ce6a552abfb5d7ad6bc290a4596c8dcc3d795fae2bbdc1f3ff"
 dependencies = [
  "futures 0.3.16",
- "hyper 0.14.11",
+ "hyper 0.14.14",
  "jsonrpc-core",
  "jsonrpc-server-utils",
  "log 0.4.14",
@@ -3164,7 +3164,7 @@ dependencies = [
  "beef",
  "futures-channel",
  "futures-util",
- "hyper 0.14.11",
+ "hyper 0.14.14",
  "log 0.4.14",
  "serde",
  "serde_json",
@@ -6815,9 +6815,9 @@ dependencies = [
 
 [[package]]
 name = "prometheus"
-version = "0.12.0"
+version = "0.13.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5986aa8d62380092d2f50f8b1cdba9cb9b6731ffd4b25b51fd126b6c3e05b99c"
+checksum = "b7f64969ffd5dd8f39bd57a68ac53c163a095ed9d0fb707146da1b27025a3504"
 dependencies = [
  "cfg-if 1.0.0",
  "fnv",
@@ -7584,7 +7584,7 @@ dependencies = [
 
 [[package]]
 name = "sc-allocator"
-version = "4.0.0-dev"
+version = "4.1.0-dev"
 dependencies = [
  "log 0.4.14",
  "sp-core",
@@ -8355,7 +8355,7 @@ dependencies = [
  "futures 0.3.16",
  "futures-timer 3.0.2",
  "hex",
- "hyper 0.14.11",
+ "hyper 0.14.14",
  "hyper-rustls",
  "lazy_static",
  "log 0.4.14",
@@ -8397,7 +8397,7 @@ dependencies = [
 
 [[package]]
 name = "sc-proposer-metrics"
-version = "0.9.0"
+version = "0.10.0-dev"
 dependencies = [
  "log 0.4.14",
  "substrate-prometheus-endpoint",
@@ -9496,7 +9496,7 @@ dependencies = [
 
 [[package]]
 name = "sp-debug-derive"
-version = "3.0.0"
+version = "4.0.0-dev"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -9597,7 +9597,7 @@ dependencies = [
 
 [[package]]
 name = "sp-maybe-compressed-blob"
-version = "4.0.0-dev"
+version = "4.1.0-dev"
 dependencies = [
  "zstd",
 ]
@@ -9657,7 +9657,7 @@ dependencies = [
 
 [[package]]
 name = "sp-panic-handler"
-version = "3.0.0"
+version = "4.0.0-dev"
 dependencies = [
  "backtrace",
  "lazy_static",
@@ -9788,7 +9788,7 @@ dependencies = [
 
 [[package]]
 name = "sp-serializer"
-version = "3.0.0"
+version = "4.0.0-dev"
 dependencies = [
  "serde",
  "serde_json",
@@ -10171,12 +10171,12 @@ dependencies = [
 
 [[package]]
 name = "substrate-prometheus-endpoint"
-version = "0.9.0"
+version = "0.10.0-dev"
 dependencies = [
  "async-std",
  "derive_more",
  "futures-util",
- "hyper 0.14.11",
+ "hyper 0.14.14",
  "log 0.4.14",
  "prometheus",
  "tokio",
diff --git a/client/allocator/Cargo.toml b/client/allocator/Cargo.toml
index 2b37c192c6e3..6d324b09acde 100644
--- a/client/allocator/Cargo.toml
+++ b/client/allocator/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sc-allocator"
-version = "4.0.0-dev"
+version = "4.1.0-dev"
 authors = ["Parity Technologies "]
 edition = "2021"
 license = "Apache-2.0"
diff --git a/client/api/Cargo.toml b/client/api/Cargo.toml
index 7b2952552a3d..431d6e2fb015 100644
--- a/client/api/Cargo.toml
+++ b/client/api/Cargo.toml
@@ -36,7 +36,7 @@ sp-state-machine = { version = "0.10.0-dev", path = "../../primitives/state-mach
 sp-trie = { version = "4.0.0-dev", path = "../../primitives/trie" }
 sp-storage = { version = "4.0.0-dev", path = "../../primitives/storage" }
 sc-transaction-pool-api = { version = "4.0.0-dev", path = "../transaction-pool/api" }
-prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.9.0", path = "../../utils/prometheus" }
+prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.10.0-dev", path = "../../utils/prometheus" }
 
 [dev-dependencies]
 sp-test-primitives = { version = "2.0.0", path = "../../primitives/test-primitives" }
diff --git a/client/authority-discovery/Cargo.toml b/client/authority-discovery/Cargo.toml
index dc4b92975681..b1d9d4ebd393 100644
--- a/client/authority-discovery/Cargo.toml
+++ b/client/authority-discovery/Cargo.toml
@@ -25,7 +25,7 @@ futures-timer = "3.0.1"
 ip_network = "0.4.0"
 libp2p = { version = "0.39.1", default-features = false, features = ["kad"] }
 log = "0.4.8"
-prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.9.0" }
+prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.10.0-dev" }
 prost = "0.8"
 rand = "0.7.2"
 sc-client-api = { version = "4.0.0-dev", path = "../api" }
diff --git a/client/basic-authorship/Cargo.toml b/client/basic-authorship/Cargo.toml
index 96ab698f3621..4bfc3ca50c83 100644
--- a/client/basic-authorship/Cargo.toml
+++ b/client/basic-authorship/Cargo.toml
@@ -17,7 +17,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0" }
 futures = "0.3.9"
 futures-timer = "3.0.1"
 log = "0.4.8"
-prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.9.0"}
+prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.10.0-dev"}
 sp-api = { version = "4.0.0-dev", path = "../../primitives/api" }
 sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" }
 sp-core = { version = "4.0.0-dev", path = "../../primitives/core" }
@@ -28,7 +28,7 @@ sp-inherents = { version = "4.0.0-dev", path = "../../primitives/inherents" }
 sc-telemetry = { version = "4.0.0-dev", path = "../telemetry" }
 sc-transaction-pool-api = { version = "4.0.0-dev", path = "../../client/transaction-pool/api" }
 sc-block-builder = { version = "0.10.0-dev", path = "../block-builder" }
-sc-proposer-metrics = { version = "0.9.0", path = "../proposer-metrics" }
+sc-proposer-metrics = { version = "0.10.0-dev", path = "../proposer-metrics" }
 
 [dev-dependencies]
 sc-transaction-pool = { version = "4.0.0-dev", path = "../transaction-pool" }
diff --git a/client/beefy/Cargo.toml b/client/beefy/Cargo.toml
index 60f9fde03080..96e5bc4ffbf3 100644
--- a/client/beefy/Cargo.toml
+++ b/client/beefy/Cargo.toml
@@ -4,6 +4,8 @@ version = "4.0.0-dev"
 authors = ["Parity Technologies "]
 edition = "2021"
 license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
+repository = "https://github.com/paritytech/substrate"
+description = "BEEFY Client gadget for substrate"
 
 [dependencies]
 fnv = "1.0.6"
@@ -14,7 +16,7 @@ thiserror = "1.0"
 wasm-timer = "0.2.5"
 
 codec = { version = "2.2.0", package = "parity-scale-codec", features = ["derive"] }
-prometheus = { version = "0.9.0", package = "substrate-prometheus-endpoint", path = "../../utils/prometheus" }
+prometheus = { version = "0.10.0-dev", package = "substrate-prometheus-endpoint", path = "../../utils/prometheus" }
 
 sp-api = { version = "4.0.0-dev", path = "../../primitives/api" }
 sp-application-crypto = { version = "4.0.0-dev", path = "../../primitives/application-crypto" }
diff --git a/client/beefy/rpc/Cargo.toml b/client/beefy/rpc/Cargo.toml
index 47fd2b740370..594736841ed2 100644
--- a/client/beefy/rpc/Cargo.toml
+++ b/client/beefy/rpc/Cargo.toml
@@ -4,6 +4,8 @@ version = "4.0.0-dev"
 authors = ["Parity Technologies "]
 edition = "2021"
 license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
+repository = "https://github.com/paritytech/substrate"
+description = "RPC for the BEEFY Client gadget for substrate"
 
 [dependencies]
 futures = "0.3.16"
diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml
index 4b6ef3bab950..6107206be34e 100644
--- a/client/cli/Cargo.toml
+++ b/client/cli/Cargo.toml
@@ -25,7 +25,7 @@ rand = "0.7.3"
 tiny-bip39 = "0.8.2"
 serde_json = "1.0.68"
 sc-keystore = { version = "4.0.0-dev", path = "../keystore" }
-sp-panic-handler = { version = "3.0.0", path = "../../primitives/panic-handler" }
+sp-panic-handler = { version = "4.0.0-dev", path = "../../primitives/panic-handler" }
 sc-client-api = { version = "4.0.0-dev", path = "../api" }
 sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" }
 sc-network = { version = "0.10.0-dev", path = "../network" }
diff --git a/client/consensus/aura/Cargo.toml b/client/consensus/aura/Cargo.toml
index 62d7b3d5327a..152c40f78f9d 100644
--- a/client/consensus/aura/Cargo.toml
+++ b/client/consensus/aura/Cargo.toml
@@ -33,7 +33,7 @@ sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" }
 sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" }
 sp-keystore = { version = "0.10.0-dev", path = "../../../primitives/keystore" }
 sc-telemetry = { version = "4.0.0-dev", path = "../../telemetry" }
-prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.9.0" }
+prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.10.0-dev" }
 async-trait = "0.1.50"
 # We enable it only for web-wasm check
 # See https://docs.rs/getrandom/0.2.1/getrandom/#webassembly-support
diff --git a/client/consensus/babe/Cargo.toml b/client/consensus/babe/Cargo.toml
index 8430ca39c9cb..7945ecc4ec79 100644
--- a/client/consensus/babe/Cargo.toml
+++ b/client/consensus/babe/Cargo.toml
@@ -42,7 +42,7 @@ sp-consensus-vrf = { version = "0.10.0-dev", path = "../../../primitives/consens
 sc-consensus-slots = { version = "0.10.0-dev", path = "../slots" }
 sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" }
 fork-tree = { version = "3.0.0", path = "../../../utils/fork-tree" }
-prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.9.0" }
+prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.10.0-dev" }
 futures = "0.3.9"
 parking_lot = "0.11.1"
 log = "0.4.8"
diff --git a/client/consensus/common/Cargo.toml b/client/consensus/common/Cargo.toml
index d63d124ed60e..3f8380d3f81b 100644
--- a/client/consensus/common/Cargo.toml
+++ b/client/consensus/common/Cargo.toml
@@ -28,7 +28,7 @@ sc-utils = { version = "4.0.0-dev", path = "../../utils" }
 sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" }
 parking_lot = "0.11.1"
 serde = { version = "1.0", features = ["derive"] }
-prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.9.0" }
+prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.10.0-dev" }
 async-trait = "0.1.42"
 
 [dev-dependencies]
diff --git a/client/consensus/manual-seal/Cargo.toml b/client/consensus/manual-seal/Cargo.toml
index a662ebf01011..a7679f53ea9e 100644
--- a/client/consensus/manual-seal/Cargo.toml
+++ b/client/consensus/manual-seal/Cargo.toml
@@ -42,7 +42,7 @@ sp-api = { path = "../../../primitives/api", version = "4.0.0-dev" }
 sc-transaction-pool-api = { path = "../../../client/transaction-pool/api", version = "4.0.0-dev" }
 sp-timestamp = { path = "../../../primitives/timestamp", version = "4.0.0-dev" }
 
-prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.9.0" }
+prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.10.0-dev" }
 
 [dev-dependencies]
 tokio = { version = "1.10.0", features = ["rt-multi-thread", "macros"] }
diff --git a/client/consensus/pow/Cargo.toml b/client/consensus/pow/Cargo.toml
index bc7c01181e41..841631fce7cc 100644
--- a/client/consensus/pow/Cargo.toml
+++ b/client/consensus/pow/Cargo.toml
@@ -29,5 +29,5 @@ futures = "0.3.16"
 futures-timer = "3.0.1"
 parking_lot = "0.11.1"
 derive_more = "0.99.2"
-prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.9.0"}
+prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.10.0-dev"}
 async-trait = "0.1.50"
diff --git a/client/executor/Cargo.toml b/client/executor/Cargo.toml
index ef66d8072b53..54c4a91d7280 100644
--- a/client/executor/Cargo.toml
+++ b/client/executor/Cargo.toml
@@ -20,7 +20,7 @@ sp-core = { version = "4.0.0-dev", path = "../../primitives/core" }
 sp-tasks = { version = "4.0.0-dev", path = "../../primitives/tasks" }
 sp-trie = { version = "4.0.0-dev", path = "../../primitives/trie" }
 sp-version = { version = "4.0.0-dev", path = "../../primitives/version" }
-sp-panic-handler = { version = "3.0.0", path = "../../primitives/panic-handler" }
+sp-panic-handler = { version = "4.0.0-dev", path = "../../primitives/panic-handler" }
 wasmi = "0.9.1"
 lazy_static = "1.4.0"
 sp-api = { version = "4.0.0-dev", path = "../../primitives/api" }
@@ -42,7 +42,7 @@ sc-runtime-test = { version = "2.0.0", path = "runtime-test" }
 substrate-test-runtime = { version = "2.0.0", path = "../../test-utils/runtime" }
 sp-state-machine = { version = "0.10.0-dev", path = "../../primitives/state-machine" }
 sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" }
-sp-maybe-compressed-blob = { version = "4.0.0-dev", path = "../../primitives/maybe-compressed-blob" }
+sp-maybe-compressed-blob = { version = "4.1.0-dev", path = "../../primitives/maybe-compressed-blob" }
 sc-tracing = { version = "4.0.0-dev", path = "../tracing" }
 tracing = "0.1.29"
 tracing-subscriber = "0.2.19"
diff --git a/client/executor/common/Cargo.toml b/client/executor/common/Cargo.toml
index 7ac747bf967b..2d9f4672768e 100644
--- a/client/executor/common/Cargo.toml
+++ b/client/executor/common/Cargo.toml
@@ -19,10 +19,10 @@ pwasm-utils = "0.18.0"
 codec = { package = "parity-scale-codec", version = "2.0.0" }
 wasmi = "0.9.1"
 sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" }
-sc-allocator = { version = "4.0.0-dev", path = "../../allocator" }
+sc-allocator = { version = "4.1.0-dev", path = "../../allocator" }
 sp-wasm-interface = { version = "4.0.0-dev", path = "../../../primitives/wasm-interface" }
-sp-maybe-compressed-blob = { version = "4.0.0-dev", path = "../../../primitives/maybe-compressed-blob" }
-sp-serializer = { version = "3.0.0", path = "../../../primitives/serializer" }
+sp-maybe-compressed-blob = { version = "4.1.0-dev", path = "../../../primitives/maybe-compressed-blob" }
+sp-serializer = { version = "4.0.0-dev", path = "../../../primitives/serializer" }
 thiserror = "1.0.21"
 environmental = "1.1.3"
 
diff --git a/client/executor/wasmi/Cargo.toml b/client/executor/wasmi/Cargo.toml
index 255a470b374d..871a8aa68b62 100644
--- a/client/executor/wasmi/Cargo.toml
+++ b/client/executor/wasmi/Cargo.toml
@@ -18,7 +18,7 @@ log = "0.4.8"
 wasmi = "0.9.1"
 codec = { package = "parity-scale-codec", version = "2.0.0" }
 sc-executor-common = { version = "0.10.0-dev", path = "../common" }
-sc-allocator = { version = "4.0.0-dev", path = "../../allocator" }
+sc-allocator = { version = "4.1.0-dev", path = "../../allocator" }
 sp-wasm-interface = { version = "4.0.0-dev", path = "../../../primitives/wasm-interface" }
 sp-runtime-interface = { version = "4.0.0-dev", path = "../../../primitives/runtime-interface" }
 sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" }
diff --git a/client/executor/wasmtime/Cargo.toml b/client/executor/wasmtime/Cargo.toml
index e52a53f71c06..006415869c92 100644
--- a/client/executor/wasmtime/Cargo.toml
+++ b/client/executor/wasmtime/Cargo.toml
@@ -22,7 +22,7 @@ sc-executor-common = { version = "0.10.0-dev", path = "../common" }
 sp-wasm-interface = { version = "4.0.0-dev", path = "../../../primitives/wasm-interface" }
 sp-runtime-interface = { version = "4.0.0-dev", path = "../../../primitives/runtime-interface" }
 sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" }
-sc-allocator = { version = "4.0.0-dev", path = "../../allocator" }
+sc-allocator = { version = "4.1.0-dev", path = "../../allocator" }
 wasmtime = { version = "0.31.0", default-features = false, features = [
     "cache",
     "cranelift",
diff --git a/client/finality-grandpa/Cargo.toml b/client/finality-grandpa/Cargo.toml
index fd0b52cd1f70..43511ea59f14 100644
--- a/client/finality-grandpa/Cargo.toml
+++ b/client/finality-grandpa/Cargo.toml
@@ -41,7 +41,7 @@ sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" }
 sc-network = { version = "0.10.0-dev", path = "../network" }
 sc-network-gossip = { version = "0.10.0-dev", path = "../network-gossip" }
 sp-finality-grandpa = { version = "4.0.0-dev", path = "../../primitives/finality-grandpa" }
-prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.9.0" }
+prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.10.0-dev" }
 sc-block-builder = { version = "0.10.0-dev", path = "../block-builder" }
 finality-grandpa = { version = "0.14.4", features = ["derive-codec"] }
 async-trait = "0.1.50"
diff --git a/client/network-gossip/Cargo.toml b/client/network-gossip/Cargo.toml
index e17d9601eafc..e11cb8dbe85d 100644
--- a/client/network-gossip/Cargo.toml
+++ b/client/network-gossip/Cargo.toml
@@ -20,7 +20,7 @@ futures-timer = "3.0.1"
 libp2p = { version = "0.39.1", default-features = false }
 log = "0.4.8"
 lru = "0.7.0"
-prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.9.0", path = "../../utils/prometheus" }
+prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.10.0-dev", path = "../../utils/prometheus" }
 sc-network = { version = "0.10.0-dev", path = "../network" }
 sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" }
 tracing = "0.1.29"
diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml
index 19ae5dd97e42..eb91dd145e54 100644
--- a/client/network/Cargo.toml
+++ b/client/network/Cargo.toml
@@ -40,7 +40,7 @@ lru = "0.7.0"
 log = "0.4.8"
 parking_lot = "0.11.1"
 pin-project = "1.0.8"
-prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.9.0", path = "../../utils/prometheus" }
+prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.10.0-dev", path = "../../utils/prometheus" }
 prost = "0.8"
 rand = "0.7.2"
 sc-block-builder = { version = "0.10.0-dev", path = "../block-builder" }
diff --git a/client/offchain/Cargo.toml b/client/offchain/Cargo.toml
index ee697b32e1e4..c93eec85888d 100644
--- a/client/offchain/Cargo.toml
+++ b/client/offchain/Cargo.toml
@@ -17,8 +17,8 @@ bytes = "1.0"
 codec = { package = "parity-scale-codec", version = "2.0.0", features = ["derive"] }
 hex = "0.4"
 fnv = "1.0.6"
-futures = "0.3.9"
-futures-timer = "3.0.1"
+futures = "0.3.16"
+futures-timer = "3.0.2"
 log = "0.4.8"
 num_cpus = "1.10"
 parking_lot = "0.11.1"
@@ -31,7 +31,7 @@ sp-offchain = { version = "4.0.0-dev", path = "../../primitives/offchain" }
 sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" }
 sc-utils = { version = "4.0.0-dev", path = "../utils" }
 threadpool = "1.7"
-hyper = "0.14.11"
+hyper = { version = "0.14.14", features = ["stream"] }
 hyper-rustls = "0.22.1"
 once_cell = "1.8"
 
diff --git a/client/proposer-metrics/Cargo.toml b/client/proposer-metrics/Cargo.toml
index 93c4cce93ca6..1a4b1fd4ce2c 100644
--- a/client/proposer-metrics/Cargo.toml
+++ b/client/proposer-metrics/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sc-proposer-metrics"
-version = "0.9.0"
+version = "0.10.0-dev"
 authors = ["Parity Technologies "]
 edition = "2021"
 license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
@@ -14,4 +14,4 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 log = "0.4.8"
-prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.9.0"}
+prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.10.0-dev"}
diff --git a/client/rpc-servers/Cargo.toml b/client/rpc-servers/Cargo.toml
index b3f408cc5980..f0ae6172d6d9 100644
--- a/client/rpc-servers/Cargo.toml
+++ b/client/rpc-servers/Cargo.toml
@@ -17,7 +17,7 @@ futures = "0.3.16"
 jsonrpc-core = "18.0.0"
 pubsub = { package = "jsonrpc-pubsub", version = "18.0.0" }
 log = "0.4.8"
-prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.9.0"}
+prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.10.0-dev"}
 serde_json = "1.0.68"
 tokio = "1.10"
 http = { package = "jsonrpc-http-server", version = "18.0.0" }
diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml
index 5c22c1e4fca1..97b0f4e461c8 100644
--- a/client/service/Cargo.toml
+++ b/client/service/Cargo.toml
@@ -69,7 +69,7 @@ sp-block-builder = { version = "4.0.0-dev", path = "../../primitives/block-build
 sc-informant = { version = "0.10.0-dev", path = "../informant" }
 sc-telemetry = { version = "4.0.0-dev", path = "../telemetry" }
 sc-offchain = { version = "4.0.0-dev", path = "../offchain" }
-prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.9.0" }
+prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.10.0-dev" }
 sc-tracing = { version = "4.0.0-dev", path = "../tracing" }
 sp-tracing = { version = "4.0.0-dev", path = "../../primitives/tracing" }
 tracing = "0.1.29"
diff --git a/client/service/test/Cargo.toml b/client/service/test/Cargo.toml
index 49eca272ac75..03967db15f67 100644
--- a/client/service/test/Cargo.toml
+++ b/client/service/test/Cargo.toml
@@ -40,6 +40,6 @@ substrate-test-runtime-client = { version = "2.0.0", path = "../../../test-utils
 sc-client-api = { version = "4.0.0-dev", path = "../../api" }
 sc-block-builder = { version = "0.10.0-dev", path = "../../block-builder" }
 sc-executor = { version = "0.10.0-dev", path = "../../executor" }
-sp-panic-handler = { version = "3.0.0", path = "../../../primitives/panic-handler" }
+sp-panic-handler = { version = "4.0.0-dev", path = "../../../primitives/panic-handler" }
 parity-scale-codec = "2.3.1"
 sp-tracing = { version = "4.0.0-dev", path = "../../../primitives/tracing" }
diff --git a/client/transaction-pool/Cargo.toml b/client/transaction-pool/Cargo.toml
index 6d05125002f2..99f1f3788ec0 100644
--- a/client/transaction-pool/Cargo.toml
+++ b/client/transaction-pool/Cargo.toml
@@ -20,7 +20,7 @@ intervalier = "0.4.0"
 log = "0.4.8"
 parity-util-mem = { version = "0.10.0", default-features = false, features = ["primitive-types"] }
 parking_lot = "0.11.1"
-prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.9.0"}
+prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.10.0-dev"}
 sc-client-api = { version = "4.0.0-dev", path = "../api" }
 sp-api = { version = "4.0.0-dev", path = "../../primitives/api" }
 sp-core = { version = "4.0.0-dev", path = "../../primitives/core" }
diff --git a/client/utils/Cargo.toml b/client/utils/Cargo.toml
index 6d04fd4e9acd..827164b702c6 100644
--- a/client/utils/Cargo.toml
+++ b/client/utils/Cargo.toml
@@ -12,7 +12,7 @@ readme = "README.md"
 [dependencies]
 futures = "0.3.9"
 lazy_static = "1.4.0"
-prometheus = { version = "0.12.0", default-features = false }
+prometheus = { version = "0.13.0", default-features = false }
 futures-timer = "3.0.2"
 
 [features]
diff --git a/frame/beefy-mmr/Cargo.toml b/frame/beefy-mmr/Cargo.toml
index 0a72ee193b3a..b99b6f7e9fea 100644
--- a/frame/beefy-mmr/Cargo.toml
+++ b/frame/beefy-mmr/Cargo.toml
@@ -5,6 +5,7 @@ authors = ["Parity Technologies "]
 edition = "2021"
 license = "Apache-2.0"
 description = "BEEFY + MMR runtime utilities"
+repository = "https://github.com/paritytech/substrate"
 
 [dependencies]
 hex = { version = "0.4", optional = true }
diff --git a/frame/beefy-mmr/primitives/Cargo.toml b/frame/beefy-mmr/primitives/Cargo.toml
index 3669ba4c2286..b54ac225e781 100644
--- a/frame/beefy-mmr/primitives/Cargo.toml
+++ b/frame/beefy-mmr/primitives/Cargo.toml
@@ -4,6 +4,7 @@ version = "4.0.0-dev"
 authors = ["Parity Technologies "]
 edition = "2021"
 license = "Apache-2.0"
+repository = "https://github.com/paritytech/substrate"
 description = "A no-std/Substrate compatible library to construct binary merkle tree."
 
 [dependencies]
@@ -17,7 +18,7 @@ hex = "0.4"
 hex-literal = "0.3"
 
 [features]
-debug = ["hex", "log"]
+debug = ["hex", "hex/std", "log"]
 default = ["std", "debug", "keccak"]
 keccak = ["tiny-keccak"]
 std = []
diff --git a/frame/beefy/Cargo.toml b/frame/beefy/Cargo.toml
index a8b516aac66c..7e1cec9d438e 100644
--- a/frame/beefy/Cargo.toml
+++ b/frame/beefy/Cargo.toml
@@ -4,6 +4,8 @@ version = "4.0.0-dev"
 authors = ["Parity Technologies "]
 edition = "2021"
 license = "Apache-2.0"
+repository = "https://github.com/paritytech/substrate"
+description = "BEEFY FRAME pallet"
 
 [dependencies]
 codec = { version = "2.2.0", package = "parity-scale-codec", default-features = false, features = ["derive"] }
diff --git a/primitives/arithmetic/Cargo.toml b/primitives/arithmetic/Cargo.toml
index e6fa1759774e..139a04180828 100644
--- a/primitives/arithmetic/Cargo.toml
+++ b/primitives/arithmetic/Cargo.toml
@@ -24,7 +24,7 @@ static_assertions = "1.1.0"
 num-traits = { version = "0.2.8", default-features = false }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" }
 serde = { version = "1.0.126", optional = true, features = ["derive"] }
-sp-debug-derive = { version = "3.0.0", default-features = false, path = "../debug-derive" }
+sp-debug-derive = { version = "4.0.0-dev", default-features = false, path = "../debug-derive" }
 
 [dev-dependencies]
 rand = "0.7.2"
diff --git a/primitives/beefy/Cargo.toml b/primitives/beefy/Cargo.toml
index 83472f54c513..23e98012027c 100644
--- a/primitives/beefy/Cargo.toml
+++ b/primitives/beefy/Cargo.toml
@@ -4,6 +4,8 @@ version = "4.0.0-dev"
 authors = ["Parity Technologies "]
 edition = "2021"
 license = "Apache-2.0"
+repository = "https://github.com/paritytech/substrate"
+description = "Primitives for BEEFY protocol."
 
 [dependencies]
 codec = { version = "2.2.0", package = "parity-scale-codec", default-features = false, features = ["derive"] }
diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml
index 9948b2e968c2..9e31ba644c25 100644
--- a/primitives/core/Cargo.toml
+++ b/primitives/core/Cargo.toml
@@ -40,7 +40,7 @@ zeroize = { version = "1.4.2", default-features = false }
 secrecy = { version = "0.8.0", default-features = false }
 lazy_static = { version = "1.4.0", default-features = false, optional = true }
 parking_lot = { version = "0.11.1", optional = true }
-sp-debug-derive = { version = "3.0.0", default-features = false, path = "../debug-derive" }
+sp-debug-derive = { version = "4.0.0-dev", default-features = false, path = "../debug-derive" }
 sp-externalities = { version = "0.10.0-dev", optional = true, path = "../externalities" }
 sp-storage = { version = "4.0.0-dev", default-features = false, path = "../storage" }
 parity-util-mem = { version = "0.10.0", default-features = false, features = [
@@ -72,7 +72,7 @@ ss58-registry = { version = "1.5.0", default-features = false }
 sp-runtime-interface = { version = "4.0.0-dev", default-features = false, path = "../runtime-interface" }
 
 [dev-dependencies]
-sp-serializer = { version = "3.0.0", path = "../serializer" }
+sp-serializer = { version = "4.0.0-dev", path = "../serializer" }
 hex-literal = "0.3.3"
 rand = "0.7.2"
 criterion = "0.3.3"
diff --git a/primitives/debug-derive/Cargo.toml b/primitives/debug-derive/Cargo.toml
index a2f77b7591fe..49b8ac832cf0 100644
--- a/primitives/debug-derive/Cargo.toml
+++ b/primitives/debug-derive/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sp-debug-derive"
-version = "3.0.0"
+version = "4.0.0-dev"
 authors = ["Parity Technologies "]
 edition = "2021"
 license = "Apache-2.0"
diff --git a/primitives/maybe-compressed-blob/Cargo.toml b/primitives/maybe-compressed-blob/Cargo.toml
index 95ba9b332412..dbed41571b14 100644
--- a/primitives/maybe-compressed-blob/Cargo.toml
+++ b/primitives/maybe-compressed-blob/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sp-maybe-compressed-blob"
-version = "4.0.0-dev"
+version = "4.1.0-dev"
 authors = ["Parity Technologies "]
 edition = "2021"
 license = "Apache-2.0"
diff --git a/primitives/panic-handler/Cargo.toml b/primitives/panic-handler/Cargo.toml
index 0845e175c237..b7f3b6b5cb4d 100644
--- a/primitives/panic-handler/Cargo.toml
+++ b/primitives/panic-handler/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sp-panic-handler"
-version = "3.0.0"
+version = "4.0.0-dev"
 authors = ["Parity Technologies "]
 edition = "2021"
 license = "Apache-2.0"
diff --git a/primitives/serializer/Cargo.toml b/primitives/serializer/Cargo.toml
index 5b2d499279a4..2b2acb8dbc37 100644
--- a/primitives/serializer/Cargo.toml
+++ b/primitives/serializer/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sp-serializer"
-version = "3.0.0"
+version = "4.0.0-dev"
 authors = ["Parity Technologies "]
 edition = "2021"
 license = "Apache-2.0"
diff --git a/primitives/state-machine/Cargo.toml b/primitives/state-machine/Cargo.toml
index 343151a50a92..c919d7fbef6a 100644
--- a/primitives/state-machine/Cargo.toml
+++ b/primitives/state-machine/Cargo.toml
@@ -22,7 +22,7 @@ trie-db = { version = "0.22.6", default-features = false }
 trie-root = { version = "0.16.0", default-features = false }
 sp-trie = { version = "4.0.0-dev", path = "../trie", default-features = false }
 sp-core = { version = "4.0.0-dev", path = "../core", default-features = false }
-sp-panic-handler = { version = "3.0.0", path = "../panic-handler", optional = true }
+sp-panic-handler = { version = "4.0.0-dev", path = "../panic-handler", optional = true }
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false }
 num-traits = { version = "0.2.8", default-features = false }
 rand = { version = "0.7.2", optional = true }
diff --git a/primitives/storage/Cargo.toml b/primitives/storage/Cargo.toml
index 2413c45a7312..c9166a5bbba0 100644
--- a/primitives/storage/Cargo.toml
+++ b/primitives/storage/Cargo.toml
@@ -18,7 +18,7 @@ sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" }
 serde = { version = "1.0.126", optional = true, features = ["derive"] }
 impl-serde = { version = "0.3.1", optional = true }
 ref-cast = "1.0.0"
-sp-debug-derive = { version = "3.0.0", default-features = false, path = "../debug-derive" }
+sp-debug-derive = { version = "4.0.0-dev", default-features = false, path = "../debug-derive" }
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
 
 [features]
diff --git a/utils/frame/generate-bags/Cargo.toml b/utils/frame/generate-bags/Cargo.toml
index 03382878710b..225584b69069 100644
--- a/utils/frame/generate-bags/Cargo.toml
+++ b/utils/frame/generate-bags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "generate-bags"
-version = "3.0.0"
+version = "4.0.0-dev"
 authors = ["Parity Technologies "]
 edition = "2021"
 license = "Apache-2.0"
@@ -11,13 +11,13 @@ readme = "README.md"
 
 [dependencies]
 # FRAME
-frame-support = { version = "4.0.0-dev", default-features = false, path = "../../../frame/support" }
+frame-support = { version = "4.0.0-dev", path = "../../../frame/support" }
 frame-election-provider-support = { version = "4.0.0-dev", path = "../../../frame/election-provider-support", features = ["runtime-benchmarks"] }
-frame-system = { version = "4.0.0-dev", default-features = false, path = "../../../frame/system" }
-pallet-staking = { version = "4.0.0-dev", default-features = false, path = "../../../frame/staking" }
+frame-system = { version = "4.0.0-dev", path = "../../../frame/system" }
+pallet-staking = { version = "4.0.0-dev", path = "../../../frame/staking" }
 
 # primitives
-sp-io = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/io" }
+sp-io = { version = "4.0.0-dev", path = "../../../primitives/io" }
 
 # third party
 chrono = { version = "0.4.19" }
diff --git a/utils/frame/generate-bags/node-runtime/Cargo.toml b/utils/frame/generate-bags/node-runtime/Cargo.toml
index 5029e049361c..b0256722f466 100644
--- a/utils/frame/generate-bags/node-runtime/Cargo.toml
+++ b/utils/frame/generate-bags/node-runtime/Cargo.toml
@@ -11,7 +11,7 @@ readme = "README.md"
 
 [dependencies]
 node-runtime = { version = "3.0.0-dev", path = "../../../../bin/node/runtime" }
-generate-bags = { version = "3.0.0", path = "../" }
+generate-bags = { version = "4.0.0-dev", path = "../" }
 
 # third-party
 structopt = "0.3.21"
diff --git a/utils/prometheus/Cargo.toml b/utils/prometheus/Cargo.toml
index 78bd68ac9e3a..390a1c733cbd 100644
--- a/utils/prometheus/Cargo.toml
+++ b/utils/prometheus/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 description = "Endpoint to expose Prometheus metrics"
 name = "substrate-prometheus-endpoint"
-version = "0.9.0"
+version = "0.10.0-dev"
 license = "Apache-2.0"
 authors = ["Parity Technologies "]
 edition = "2021"
@@ -14,13 +14,13 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 log = "0.4.8"
-prometheus = { version = "0.12.0", default-features = false }
+prometheus = { version = "0.13.0", default-features = false }
 futures-util = { version = "0.3.17", default-features = false, features = ["io"] }
 derive_more = "0.99"
 async-std = { version = "1.10.0", features = ["unstable"] }
 tokio = "1.10"
-hyper = { version = "0.14.11", default-features = false, features = ["http1", "server", "tcp"] }
+hyper = { version = "0.14.14", default-features = false, features = ["http1", "server", "tcp"] }
 
 [dev-dependencies]
-hyper = { version = "0.14.11", features = ["client"] }
+hyper = { version = "0.14.14", features = ["client"] }
 tokio = { version = "1.10", features = ["rt-multi-thread"] }
diff --git a/utils/wasm-builder/Cargo.toml b/utils/wasm-builder/Cargo.toml
index d8802c432f55..88318f4f0d54 100644
--- a/utils/wasm-builder/Cargo.toml
+++ b/utils/wasm-builder/Cargo.toml
@@ -20,4 +20,4 @@ toml = "0.5.4"
 walkdir = "2.3.2"
 wasm-gc-api = "0.1.11"
 ansi_term = "0.12.1"
-sp-maybe-compressed-blob = { version = "4.0.0-dev", path = "../../primitives/maybe-compressed-blob" }
+sp-maybe-compressed-blob = { version = "4.1.0-dev", path = "../../primitives/maybe-compressed-blob" }

From 2ab769819e8a3ee869459b78cbb98cc749728cc3 Mon Sep 17 00:00:00 2001
From: sander2 
Date: Thu, 11 Nov 2021 09:23:34 +0100
Subject: [PATCH 166/695] expose substrate-cli service (#10229)

* expose substrate-cli service

* chore: undo change to new_full (since new_full_base is exposed already)
---
 bin/node/cli/src/service.rs | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs
index 2220614ebaf2..a022d501d015 100644
--- a/bin/node/cli/src/service.rs
+++ b/bin/node/cli/src/service.rs
@@ -30,7 +30,7 @@ use sc_client_api::{BlockBackend, ExecutorProvider};
 use sc_consensus_babe::{self, SlotProportion};
 use sc_executor::NativeElseWasmExecutor;
 use sc_network::{Event, NetworkService};
-use sc_service::{config::Configuration, error::Error as ServiceError, TaskManager};
+use sc_service::{config::Configuration, error::Error as ServiceError, RpcHandlers, TaskManager};
 use sc_telemetry::{Telemetry, TelemetryWorker};
 use sp_api::ProvideRuntimeApi;
 use sp_core::crypto::Pair;
@@ -298,6 +298,8 @@ pub struct NewFullBase {
 	pub network: Arc::Hash>>,
 	/// The transaction pool of the node.
 	pub transaction_pool: Arc,
+	/// The rpc handlers of the node.
+	pub rpc_handlers: RpcHandlers,
 }
 
 /// Creates a full service from the configuration.
@@ -358,7 +360,7 @@ pub fn new_full_base(
 	let enable_grandpa = !config.disable_grandpa;
 	let prometheus_registry = config.prometheus_registry().cloned();
 
-	let _rpc_handlers = sc_service::spawn_tasks(sc_service::SpawnTasksParams {
+	let rpc_handlers = sc_service::spawn_tasks(sc_service::SpawnTasksParams {
 		config,
 		backend,
 		client: client.clone(),
@@ -507,7 +509,7 @@ pub fn new_full_base(
 	}
 
 	network_starter.start_network();
-	Ok(NewFullBase { task_manager, client, network, transaction_pool })
+	Ok(NewFullBase { task_manager, client, network, transaction_pool, rpc_handlers })
 }
 
 /// Builds a new service for a full client.

From 7b1c81f5b4966548fc281d3d164e317e338ef2d6 Mon Sep 17 00:00:00 2001
From: David 
Date: Thu, 11 Nov 2021 12:29:28 +0100
Subject: [PATCH 167/695] Upgrade jsonrpsee to v0.4.1 (#10022)

* Upgrade jsonrpsee to v0.4.1

* remove needless BlockT trait bound

* use default wss port in URL

* Fix try_runtime build

* Partially fix for "remote-tests" feature

* Review feedback

* fmt

* Sort out trait bounds for benches

* Fmt

* fmt again?

* fmt with nightly-2021-09-13

* Upgrade try-runtime as well

* fmt

Co-authored-by: Niklas Adolfsson 
---
 Cargo.lock                                    | 126 +++++++-----------
 bin/node/cli/Cargo.toml                       |   2 +-
 frame/bags-list/remote-tests/src/migration.rs |   4 +-
 .../remote-tests/src/sanity_check.rs          |   4 +-
 frame/bags-list/remote-tests/src/snapshot.rs  |   4 +-
 .../procedural/src/construct_runtime/parse.rs |   2 +-
 utils/frame/remote-externalities/Cargo.toml   |   5 +-
 utils/frame/remote-externalities/src/lib.rs   | 109 ++++++++-------
 .../frame/remote-externalities/src/rpc_api.rs |  27 ++--
 utils/frame/try-runtime/cli/Cargo.toml        |   4 +-
 .../cli/src/commands/follow_chain.rs          |   8 +-
 utils/frame/try-runtime/cli/src/lib.rs        |   7 +-
 12 files changed, 128 insertions(+), 174 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 69cd80e292f8..5ae937ad22d4 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -144,9 +144,9 @@ checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
 
 [[package]]
 name = "arrayvec"
-version = "0.7.0"
+version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a2f58b0bb10c380af2b26e57212856b8c9a59e0925b4c20f4a174a49734eaf7"
+checksum = "be4dc07131ffa69b8072d35f5007352af944213cde02545e2103680baed38fcd"
 
 [[package]]
 name = "asn1_der"
@@ -419,19 +419,6 @@ dependencies = [
  "rustc-demangle",
 ]
 
-[[package]]
-name = "bae"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec107f431ee3d8a8e45e6dd117adab769556ef463959e77bf6a4888d5fd500cf"
-dependencies = [
- "heck",
- "proc-macro-error 0.4.12",
- "proc-macro2",
- "quote",
- "syn",
-]
-
 [[package]]
 name = "base-x"
 version = "0.2.8"
@@ -477,9 +464,9 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
 
 [[package]]
 name = "beef"
-version = "0.5.0"
+version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6736e2428df2ca2848d846c43e88745121a6654696e349ce0054a420815a7409"
+checksum = "bed554bd50246729a1ec158d08aa3235d1b69d94ad120ebe187e28894787e736"
 dependencies = [
  "serde",
 ]
@@ -1634,7 +1621,7 @@ dependencies = [
  "bitflags",
  "byteorder",
  "lazy_static",
- "proc-macro-error 1.0.4",
+ "proc-macro-error",
  "proc-macro2",
  "quote",
  "syn",
@@ -3140,14 +3127,25 @@ dependencies = [
  "slab",
 ]
 
+[[package]]
+name = "jsonrpsee"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6373a33d987866ccfe1af4bc11b089dce941764313f9fd8b7cf13fcb51b72dc5"
+dependencies = [
+ "jsonrpsee-proc-macros",
+ "jsonrpsee-types",
+ "jsonrpsee-utils",
+ "jsonrpsee-ws-client",
+]
+
 [[package]]
 name = "jsonrpsee-proc-macros"
-version = "0.3.1"
+version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8edb341d35279b59c79d7fe9e060a51aec29d45af99cc7c72ea7caa350fa71a4"
+checksum = "d802063f7a3c867456955f9d2f15eb3ee0edb5ec9ec2b5526324756759221c0f"
 dependencies = [
- "Inflector",
- "bae",
+ "log 0.4.14",
  "proc-macro-crate 1.0.0",
  "proc-macro2",
  "quote",
@@ -3156,10 +3154,11 @@ dependencies = [
 
 [[package]]
 name = "jsonrpsee-types"
-version = "0.3.1"
+version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4cc738fd55b676ada3271ef7c383a14a0867a2a88b0fa941311bf5fc0a29d498"
+checksum = "62f778cf245158fbd8f5d50823a2e9e4c708a40be164766bd35e9fb1d86715b2"
 dependencies = [
+ "anyhow",
  "async-trait",
  "beef",
  "futures-channel",
@@ -3168,32 +3167,43 @@ dependencies = [
  "log 0.4.14",
  "serde",
  "serde_json",
- "soketto 0.6.0",
+ "soketto 0.7.0",
  "thiserror",
 ]
 
+[[package]]
+name = "jsonrpsee-utils"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0109c4f972058f3b1925b73a17210aff7b63b65967264d0045d15ee88fe84f0c"
+dependencies = [
+ "arrayvec 0.7.1",
+ "beef",
+ "jsonrpsee-types",
+]
+
 [[package]]
 name = "jsonrpsee-ws-client"
-version = "0.3.1"
+version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9841352dbecf4c2ed5dc71698df9f1660262ae4e0b610e968602529bdbcf7b30"
+checksum = "559aa56fc402af206c00fc913dc2be1d9d788dcde045d14df141a535245d35ef"
 dependencies = [
+ "arrayvec 0.7.1",
  "async-trait",
  "fnv",
  "futures 0.3.16",
+ "http",
  "jsonrpsee-types",
  "log 0.4.14",
  "pin-project 1.0.8",
- "rustls",
  "rustls-native-certs",
  "serde",
  "serde_json",
- "soketto 0.6.0",
+ "soketto 0.7.0",
  "thiserror",
  "tokio",
  "tokio-rustls",
  "tokio-util",
- "url 2.2.1",
 ]
 
 [[package]]
@@ -4353,7 +4363,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "424f6e86263cd5294cbd7f1e95746b95aca0e0d66bff31e5a40d6baa87b4aa99"
 dependencies = [
  "proc-macro-crate 1.0.0",
- "proc-macro-error 1.0.4",
+ "proc-macro-error",
  "proc-macro2",
  "quote",
  "syn",
@@ -6249,7 +6259,7 @@ version = "2.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "373b1a4c1338d9cd3d1fa53b3a11bdab5ab6bd80a20f7f7becd76953ae2be909"
 dependencies = [
- "arrayvec 0.7.0",
+ "arrayvec 0.7.1",
  "bitvec 0.20.2",
  "byte-slice-cast",
  "impl-trait-for-tuples",
@@ -6742,45 +6752,19 @@ dependencies = [
  "toml",
 ]
 
-[[package]]
-name = "proc-macro-error"
-version = "0.4.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18f33027081eba0a6d8aba6d1b1c3a3be58cbb12106341c2d5759fcd9b5277e7"
-dependencies = [
- "proc-macro-error-attr 0.4.12",
- "proc-macro2",
- "quote",
- "syn",
- "version_check 0.9.2",
-]
-
 [[package]]
 name = "proc-macro-error"
 version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
 dependencies = [
- "proc-macro-error-attr 1.0.4",
+ "proc-macro-error-attr",
  "proc-macro2",
  "quote",
  "syn",
  "version_check 0.9.2",
 ]
 
-[[package]]
-name = "proc-macro-error-attr"
-version = "0.4.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a5b4b77fdb63c1eca72173d68d24501c54ab1269409f6b672c85deb18af69de"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "syn-mid",
- "version_check 0.9.2",
-]
-
 [[package]]
 name = "proc-macro-error-attr"
 version = "1.0.4"
@@ -7365,8 +7349,7 @@ version = "0.10.0-dev"
 dependencies = [
  "env_logger 0.9.0",
  "frame-support",
- "jsonrpsee-proc-macros",
- "jsonrpsee-ws-client",
+ "jsonrpsee",
  "log 0.4.14",
  "pallet-elections-phragmen",
  "parity-scale-codec",
@@ -9157,9 +9140,9 @@ dependencies = [
 
 [[package]]
 name = "soketto"
-version = "0.6.0"
+version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a74e48087dbeed4833785c2f3352b59140095dc192dce966a3bfc155020a439f"
+checksum = "083624472e8817d44d02c0e55df043737ff11f279af924abdf93845717c2b75c"
 dependencies = [
  "base64 0.13.0",
  "bytes 1.0.1",
@@ -10062,7 +10045,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "134d838a2c9943ac3125cf6df165eda53493451b719f3255b2a26b85f772d0ba"
 dependencies = [
  "heck",
- "proc-macro-error 1.0.4",
+ "proc-macro-error",
  "proc-macro2",
  "quote",
  "syn",
@@ -10355,17 +10338,6 @@ dependencies = [
  "unicode-xid",
 ]
 
-[[package]]
-name = "syn-mid"
-version = "0.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "baa8e7560a164edb1621a55d18a0c59abf49d360f47aa7b821061dd7eea7fac9"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
 [[package]]
 name = "synstructure"
 version = "0.12.4"
@@ -10974,7 +10946,7 @@ checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
 name = "try-runtime-cli"
 version = "0.10.0-dev"
 dependencies = [
- "jsonrpsee-ws-client",
+ "jsonrpsee",
  "log 0.4.14",
  "parity-scale-codec",
  "remote-externalities",
@@ -11447,7 +11419,7 @@ version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d8b86dcd2c3efdb8390728a2b56f762db07789aaa5aa872a9dc776ba3a7912ed"
 dependencies = [
- "proc-macro-error 1.0.4",
+ "proc-macro-error",
  "proc-macro2",
  "quote",
  "syn",
diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml
index 15760c5a9abb..fc39e47ce411 100644
--- a/bin/node/cli/Cargo.toml
+++ b/bin/node/cli/Cargo.toml
@@ -130,7 +130,7 @@ async-std = { version = "1.10.0", features = ["attributes"] }
 soketto = "0.4.2"
 criterion = { version = "0.3.5", features = [ "async_tokio" ] }
 tokio = { version = "1.10", features = ["macros", "time"] }
-jsonrpsee-ws-client = { version = "0.3.1", default-features = false, features = ["tokio1"] }
+jsonrpsee-ws-client = "0.4.1"
 wait-timeout = "0.2"
 remote-externalities = { path = "../../../utils/frame/remote-externalities" }
 pallet-timestamp = { version = "4.0.0-dev", path = "../../../frame/timestamp" }
diff --git a/frame/bags-list/remote-tests/src/migration.rs b/frame/bags-list/remote-tests/src/migration.rs
index 1e977011f143..86595c7feba9 100644
--- a/frame/bags-list/remote-tests/src/migration.rs
+++ b/frame/bags-list/remote-tests/src/migration.rs
@@ -21,11 +21,11 @@ use frame_election_provider_support::SortedListProvider;
 use frame_support::traits::PalletInfoAccess;
 use pallet_staking::Nominators;
 use remote_externalities::{Builder, Mode, OnlineConfig};
-use sp_runtime::traits::Block as BlockT;
+use sp_runtime::{traits::Block as BlockT, DeserializeOwned};
 
 /// Test voter bags migration. `currency_unit` is the number of planks per the the runtimes `UNITS`
 /// (i.e. number of decimal places per DOT, KSM etc)
-pub async fn execute(
+pub async fn execute(
 	currency_unit: u64,
 	currency_name: &'static str,
 	ws_url: String,
diff --git a/frame/bags-list/remote-tests/src/sanity_check.rs b/frame/bags-list/remote-tests/src/sanity_check.rs
index 7282e7bad5e3..adab1ae5477e 100644
--- a/frame/bags-list/remote-tests/src/sanity_check.rs
+++ b/frame/bags-list/remote-tests/src/sanity_check.rs
@@ -22,11 +22,11 @@ use frame_support::{
 	traits::{Get, PalletInfoAccess},
 };
 use remote_externalities::{Builder, Mode, OnlineConfig};
-use sp_runtime::traits::Block as BlockT;
+use sp_runtime::{traits::Block as BlockT, DeserializeOwned};
 use sp_std::prelude::*;
 
 /// Execute the sanity check of the bags-list.
-pub async fn execute(
+pub async fn execute(
 	currency_unit: u64,
 	currency_name: &'static str,
 	ws_url: String,
diff --git a/frame/bags-list/remote-tests/src/snapshot.rs b/frame/bags-list/remote-tests/src/snapshot.rs
index 6e186a65cb2b..0e68a4495edf 100644
--- a/frame/bags-list/remote-tests/src/snapshot.rs
+++ b/frame/bags-list/remote-tests/src/snapshot.rs
@@ -18,10 +18,10 @@
 
 use frame_support::traits::PalletInfoAccess;
 use remote_externalities::{Builder, Mode, OnlineConfig};
-use sp_runtime::traits::Block as BlockT;
+use sp_runtime::{traits::Block as BlockT, DeserializeOwned};
 
 /// Execute create a snapshot from pallet-staking.
-pub async fn execute(
+pub async fn execute(
 	voter_limit: Option,
 	currency_unit: u64,
 	ws_url: String,
diff --git a/frame/support/procedural/src/construct_runtime/parse.rs b/frame/support/procedural/src/construct_runtime/parse.rs
index f80b7b1ac554..44db2c10fff6 100644
--- a/frame/support/procedural/src/construct_runtime/parse.rs
+++ b/frame/support/procedural/src/construct_runtime/parse.rs
@@ -225,7 +225,7 @@ impl Parse for PalletDeclaration {
 		{
 			return Err(input.error(
 				"Unexpected tokens, expected one of `::$ident` `::{`, `exclude_parts`, `use_parts`, `=`, `,`",
-			))
+			));
 		} else {
 			None
 		};
diff --git a/utils/frame/remote-externalities/Cargo.toml b/utils/frame/remote-externalities/Cargo.toml
index 9c9025d934aa..f2482f9c423d 100644
--- a/utils/frame/remote-externalities/Cargo.toml
+++ b/utils/frame/remote-externalities/Cargo.toml
@@ -13,10 +13,7 @@ readme = "README.md"
 targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
-jsonrpsee-ws-client = { version = "0.3.1", default-features = false, features = [
-    "tokio1",
-]}
-jsonrpsee-proc-macros = "0.3.1"
+jsonrpsee = { version = "0.4.1", features = ["ws-client", "macros"] }
 
 env_logger = "0.9"
 log = "0.4.11"
diff --git a/utils/frame/remote-externalities/src/lib.rs b/utils/frame/remote-externalities/src/lib.rs
index bf8c57ae14ee..da715be6b4be 100644
--- a/utils/frame/remote-externalities/src/lib.rs
+++ b/utils/frame/remote-externalities/src/lib.rs
@@ -21,7 +21,16 @@
 //! based chain, or a local state snapshot file.
 
 use codec::{Decode, Encode};
-use jsonrpsee_ws_client::{types::v2::params::JsonRpcParams, WsClient, WsClientBuilder};
+
+use jsonrpsee::{
+	proc_macros::rpc,
+	rpc_params,
+	types::{traits::Client, Error as RpcError},
+	ws_client::{WsClient, WsClientBuilder},
+};
+
+use log::*;
+use serde::de::DeserializeOwned;
 use sp_core::{
 	hashing::twox_128,
 	hexdisplay::HexDisplay,
@@ -39,23 +48,25 @@ pub mod rpc_api;
 type KeyPair = (StorageKey, StorageData);
 
 const LOG_TARGET: &str = "remote-ext";
-const DEFAULT_TARGET: &str = "wss://rpc.polkadot.io";
+const DEFAULT_TARGET: &str = "wss://rpc.polkadot.io:443";
 const BATCH_SIZE: usize = 1000;
 
-jsonrpsee_proc_macros::rpc_client_api! {
-	RpcApi {
-		#[rpc(method = "state_getStorage", positional_params)]
-		fn get_storage(prefix: StorageKey, hash: Option) -> StorageData;
-		#[rpc(method = "state_getKeysPaged", positional_params)]
-		fn get_keys_paged(
-			prefix: Option,
-			count: u32,
-			start_key: Option,
-			hash: Option,
-		) -> Vec;
-		#[rpc(method = "chain_getFinalizedHead", positional_params)]
-		fn finalized_head() -> B::Hash;
-	}
+#[rpc(client)]
+pub trait RpcApi {
+	#[method(name = "state_getStorage")]
+	fn get_storage(&self, prefix: StorageKey, hash: Option) -> Result;
+
+	#[method(name = "state_getKeysPaged")]
+	fn get_keys_paged(
+		&self,
+		prefix: Option,
+		count: u32,
+		start_key: Option,
+		hash: Option,
+	) -> Result, RpcError>;
+
+	#[method(name = "chain_getFinalizedHead")]
+	fn finalized_head(&self) -> Result;
 }
 
 /// The execution mode.
@@ -183,7 +194,7 @@ pub struct Builder {
 
 // NOTE: ideally we would use `DefaultNoBound` here, but not worth bringing in frame-support for
 // that.
-impl Default for Builder {
+impl Default for Builder {
 	fn default() -> Self {
 		Self {
 			mode: Default::default(),
@@ -196,7 +207,7 @@ impl Default for Builder {
 }
 
 // Mode methods
-impl Builder {
+impl Builder {
 	fn as_online(&self) -> &OnlineConfig {
 		match &self.mode {
 			Mode::Online(config) => &config,
@@ -215,25 +226,23 @@ impl Builder {
 }
 
 // RPC methods
-impl Builder {
+impl Builder {
 	async fn rpc_get_storage(
 		&self,
 		key: StorageKey,
 		maybe_at: Option,
 	) -> Result {
-		log::trace!(target: LOG_TARGET, "rpc: get_storage");
-		RpcApi::::get_storage(self.as_online().rpc_client(), key, maybe_at)
-			.await
-			.map_err(|e| {
-				log::error!(target: LOG_TARGET, "Error = {:?}", e);
-				"rpc get_storage failed."
-			})
+		trace!(target: LOG_TARGET, "rpc: get_storage");
+		self.as_online().rpc_client().get_storage(key, maybe_at).await.map_err(|e| {
+			error!("Error = {:?}", e);
+			"rpc get_storage failed."
+		})
 	}
 	/// Get the latest finalized head.
 	async fn rpc_get_head(&self) -> Result {
-		log::trace!(target: LOG_TARGET, "rpc: finalized_head");
-		RpcApi::::finalized_head(self.as_online().rpc_client()).await.map_err(|e| {
-			log::error!(target: LOG_TARGET, "Error = {:?}", e);
+		trace!(target: LOG_TARGET, "rpc: finalized_head");
+		self.as_online().rpc_client().finalized_head().await.map_err(|e| {
+			error!("Error = {:?}", e);
 			"rpc finalized_head failed."
 		})
 	}
@@ -248,18 +257,15 @@ impl Builder {
 		let mut last_key: Option = None;
 		let mut all_keys: Vec = vec![];
 		let keys = loop {
-			let page = RpcApi::::get_keys_paged(
-				self.as_online().rpc_client(),
-				Some(prefix.clone()),
-				PAGE,
-				last_key.clone(),
-				Some(at),
-			)
-			.await
-			.map_err(|e| {
-				log::error!(target: LOG_TARGET, "Error = {:?}", e);
-				"rpc get_keys failed"
-			})?;
+			let page = self
+				.as_online()
+				.rpc_client()
+				.get_keys_paged(Some(prefix.clone()), PAGE, last_key.clone(), Some(at))
+				.await
+				.map_err(|e| {
+					error!(target: LOG_TARGET, "Error = {:?}", e);
+					"rpc get_keys failed"
+				})?;
 			let page_len = page.len();
 			all_keys.extend(page);
 
@@ -291,8 +297,6 @@ impl Builder {
 		prefix: StorageKey,
 		at: B::Hash,
 	) -> Result, &'static str> {
-		use jsonrpsee_ws_client::types::traits::Client;
-		use serde_json::to_value;
 		let keys = self.get_keys_paged(prefix, at).await?;
 		let keys_count = keys.len();
 		log::debug!(target: LOG_TARGET, "Querying a total of {} keys", keys.len());
@@ -303,15 +307,7 @@ impl Builder {
 			let batch = chunk_keys
 				.iter()
 				.cloned()
-				.map(|key| {
-					(
-						"state_getStorage",
-						JsonRpcParams::Array(vec![
-							to_value(key).expect("json serialization will work; qed."),
-							to_value(at).expect("json serialization will work; qed."),
-						]),
-					)
-				})
+				.map(|key| ("state_getStorage", rpc_params![key, at]))
 				.collect::>();
 			let values = client.batch_request::>(batch).await.map_err(|e| {
 				log::error!(
@@ -348,7 +344,7 @@ impl Builder {
 }
 
 // Internal methods
-impl Builder {
+impl Builder {
 	/// Save the given data as state snapshot.
 	fn save_state_snapshot(&self, data: &[KeyPair], path: &Path) -> Result<(), &'static str> {
 		log::debug!(target: LOG_TARGET, "writing to state snapshot file {:?}", path);
@@ -489,7 +485,7 @@ impl Builder {
 }
 
 // Public methods
-impl Builder {
+impl Builder {
 	/// Create a new builder.
 	pub fn new() -> Self {
 		Default::default()
@@ -625,7 +621,7 @@ mod tests {
 #[cfg(all(test, feature = "remote-test"))]
 mod remote_tests {
 	use super::test_prelude::*;
-
+	use pallet_elections_phragmen::Members;
 	const REMOTE_INACCESSIBLE: &'static str = "Can't reach the remote node. Is it running?";
 
 	#[tokio::test]
@@ -697,7 +693,6 @@ mod remote_tests {
 
 	#[tokio::test]
 	async fn sanity_check_decoding() {
-		use pallet_elections_phragmen::SeatHolder;
 		use sp_core::crypto::Ss58Codec;
 
 		type AccountId = sp_runtime::AccountId32;
@@ -722,7 +717,7 @@ mod remote_tests {
 				let gav_polkadot =
 					AccountId::from_ss58check("13RDY9nrJpyTDBSUdBw12dGwhk19sGwsrVZ2bxkzYHBSagP2")
 						.unwrap();
-				let members = Members::get().unwrap();
+				let members = Members::get();
 				assert!(members
 					.iter()
 					.map(|s| s.who.clone())
diff --git a/utils/frame/remote-externalities/src/rpc_api.rs b/utils/frame/remote-externalities/src/rpc_api.rs
index 24050856a96a..024cbad3ca55 100644
--- a/utils/frame/remote-externalities/src/rpc_api.rs
+++ b/utils/frame/remote-externalities/src/rpc_api.rs
@@ -18,9 +18,10 @@
 //! WS RPC API for one off RPC calls to a substrate node.
 // TODO: Consolidate one off RPC calls https://github.com/paritytech/substrate/issues/8988
 
-use jsonrpsee_ws_client::{
-	types::{traits::Client, v2::params::JsonRpcParams},
-	WsClient, WsClientBuilder,
+use jsonrpsee::{
+	rpc_params,
+	types::traits::Client,
+	ws_client::{WsClient, WsClientBuilder},
 };
 use sp_runtime::{
 	generic::SignedBlock,
@@ -34,11 +35,10 @@ where
 	Block::Header: serde::de::DeserializeOwned,
 	S: AsRef,
 {
-	let params = vec![hash_to_json::(at)?];
 	let client = build_client(from).await?;
 
 	client
-		.request::("chain_getHeader", JsonRpcParams::Array(params))
+		.request::("chain_getHeader", rpc_params!(at))
 		.await
 		.map_err(|e| format!("chain_getHeader request failed: {:?}", e))
 }
@@ -52,7 +52,7 @@ where
 	let client = build_client(from).await?;
 
 	client
-		.request::("chain_getFinalizedHead", JsonRpcParams::NoParams)
+		.request::("chain_getFinalizedHead", None)
 		.await
 		.map_err(|e| format!("chain_getFinalizedHead request failed: {:?}", e))
 }
@@ -64,22 +64,15 @@ where
 	Block: BlockT + serde::de::DeserializeOwned,
 	Block::Header: HeaderT,
 {
-	let params = vec![hash_to_json::(at)?];
 	let client = build_client(from).await?;
 	let signed_block = client
-		.request::>("chain_getBlock", JsonRpcParams::Array(params))
+		.request::>("chain_getBlock", rpc_params!(at))
 		.await
 		.map_err(|e| format!("chain_getBlock request failed: {:?}", e))?;
 
 	Ok(signed_block.block)
 }
 
-/// Convert a block hash to a serde json value.
-fn hash_to_json(hash: Block::Hash) -> Result {
-	serde_json::to_value(hash)
-		.map_err(|e| format!("Block hash could not be converted to JSON: {:?}", e))
-}
-
 /// Build a website client that connects to `from`.
 async fn build_client>(from: S) -> Result {
 	WsClientBuilder::default()
@@ -99,13 +92,9 @@ where
 	Block: BlockT + serde::de::DeserializeOwned,
 	Block::Header: HeaderT,
 {
-	let params = if let Some(at) = at { vec![hash_to_json::(at)?] } else { vec![] };
 	let client = build_client(from).await?;
 	client
-		.request::(
-			"state_getRuntimeVersion",
-			JsonRpcParams::Array(params),
-		)
+		.request::("state_getRuntimeVersion", rpc_params!(at))
 		.await
 		.map_err(|e| format!("state_getRuntimeVersion request failed: {:?}", e))
 }
diff --git a/utils/frame/try-runtime/cli/Cargo.toml b/utils/frame/try-runtime/cli/Cargo.toml
index 154c522c1dfd..a89a625bbd9e 100644
--- a/utils/frame/try-runtime/cli/Cargo.toml
+++ b/utils/frame/try-runtime/cli/Cargo.toml
@@ -31,6 +31,4 @@ sp-externalities = { version = "0.10.0-dev", path = "../../../../primitives/exte
 sp-version = { version = "4.0.0-dev", path = "../../../../primitives/version" }
 
 remote-externalities = { version = "0.10.0-dev", path = "../../remote-externalities" }
-jsonrpsee-ws-client = { version = "0.3.1", default-features = false, features = [
-    "tokio1",
-]}
+jsonrpsee = { version = "0.4.1", default-features = false, features = ["ws-client"]}
diff --git a/utils/frame/try-runtime/cli/src/commands/follow_chain.rs b/utils/frame/try-runtime/cli/src/commands/follow_chain.rs
index 9125db13c78f..27fb35dd7a46 100644
--- a/utils/frame/try-runtime/cli/src/commands/follow_chain.rs
+++ b/utils/frame/try-runtime/cli/src/commands/follow_chain.rs
@@ -19,9 +19,9 @@ use crate::{
 	build_executor, ensure_matching_spec, extract_code, full_extensions, local_spec, parse,
 	state_machine_call, SharedParams, LOG_TARGET,
 };
-use jsonrpsee_ws_client::{
-	types::{traits::SubscriptionClient, v2::params::JsonRpcParams, Subscription},
-	WsClientBuilder,
+use jsonrpsee::{
+	types::{traits::SubscriptionClient, Subscription},
+	ws_client::WsClientBuilder,
 };
 use parity_scale_codec::Decode;
 use remote_externalities::{rpc_api, Builder, Mode, OnlineConfig};
@@ -72,7 +72,7 @@ where
 
 	log::info!(target: LOG_TARGET, "subscribing to {:?} / {:?}", SUB, UN_SUB);
 	let mut subscription: Subscription =
-		client.subscribe(&SUB, JsonRpcParams::NoParams, &UN_SUB).await.unwrap();
+		client.subscribe(&SUB, None, &UN_SUB).await.unwrap();
 
 	let (code_key, code) = extract_code(&config.chain_spec)?;
 	let executor = build_executor::(&shared, &config);
diff --git a/utils/frame/try-runtime/cli/src/lib.rs b/utils/frame/try-runtime/cli/src/lib.rs
index 28e51b38f2ac..a74625492bb1 100644
--- a/utils/frame/try-runtime/cli/src/lib.rs
+++ b/utils/frame/try-runtime/cli/src/lib.rs
@@ -281,7 +281,10 @@ use sp_core::{
 };
 use sp_externalities::Extensions;
 use sp_keystore::{testing::KeyStore, KeystoreExt};
-use sp_runtime::traits::{Block as BlockT, NumberFor};
+use sp_runtime::{
+	traits::{Block as BlockT, NumberFor},
+	DeserializeOwned,
+};
 use sp_state_machine::{OverlayedChanges, StateMachine};
 use std::{fmt::Debug, path::PathBuf, str::FromStr};
 
@@ -464,7 +467,7 @@ pub enum State {
 
 impl State {
 	/// Create the [`remote_externalities::Builder`] from self.
-	pub(crate) fn builder(&self) -> sc_cli::Result>
+	pub(crate) fn builder(&self) -> sc_cli::Result>
 	where
 		Block::Hash: FromStr,
 		::Err: Debug,

From 8d7898923c8287df6f2014c31940d7b5a2df9323 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 11 Nov 2021 13:56:46 +0000
Subject: [PATCH 168/695] Bump substrate-bip39 from 0.4.2 to 0.4.4 (#10213)

Bumps [substrate-bip39](https://github.com/paritytech/substrate-bip39) from 0.4.2 to 0.4.4.
- [Release notes](https://github.com/paritytech/substrate-bip39/releases)
- [Commits](https://github.com/paritytech/substrate-bip39/commits)

---
updated-dependencies:
- dependency-name: substrate-bip39
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] 

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 Cargo.lock                 | 73 +++++++++++++++++---------------------
 primitives/core/Cargo.toml |  2 +-
 2 files changed, 34 insertions(+), 41 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 5ae937ad22d4..51eb96d6989f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
  "cipher",
  "ctr",
  "ghash",
- "subtle 2.4.0",
+ "subtle",
 ]
 
 [[package]]
@@ -1309,22 +1309,22 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
 
 [[package]]
 name = "crypto-mac"
-version = "0.7.0"
+version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5"
+checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab"
 dependencies = [
- "generic-array 0.12.4",
- "subtle 1.0.0",
+ "generic-array 0.14.4",
+ "subtle",
 ]
 
 [[package]]
 name = "crypto-mac"
-version = "0.8.0"
+version = "0.11.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab"
+checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714"
 dependencies = [
  "generic-array 0.14.4",
- "subtle 2.4.0",
+ "subtle",
 ]
 
 [[package]]
@@ -1397,7 +1397,7 @@ dependencies = [
  "byteorder",
  "digest 0.8.1",
  "rand_core 0.5.1",
- "subtle 2.4.0",
+ "subtle",
  "zeroize",
 ]
 
@@ -1410,7 +1410,7 @@ dependencies = [
  "byteorder",
  "digest 0.9.0",
  "rand_core 0.5.1",
- "subtle 2.4.0",
+ "subtle",
  "zeroize",
 ]
 
@@ -2610,21 +2610,21 @@ checksum = "b07f60793ff0a4d9cef0f18e63b5357e06209987153a64648c972c1e5aff336f"
 
 [[package]]
 name = "hmac"
-version = "0.7.1"
+version = "0.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695"
+checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840"
 dependencies = [
- "crypto-mac 0.7.0",
- "digest 0.8.1",
+ "crypto-mac 0.8.0",
+ "digest 0.9.0",
 ]
 
 [[package]]
 name = "hmac"
-version = "0.8.1"
+version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840"
+checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b"
 dependencies = [
- "crypto-mac 0.8.0",
+ "crypto-mac 0.11.1",
  "digest 0.9.0",
 ]
 
@@ -3868,7 +3868,7 @@ checksum = "d0f6ab710cec28cef759c5f18671a27dae2a5f952cdaaee1d8e2908cb2478a80"
 dependencies = [
  "crunchy",
  "digest 0.9.0",
- "subtle 2.4.0",
+ "subtle",
 ]
 
 [[package]]
@@ -3879,7 +3879,7 @@ checksum = "5be9b9bb642d8522a44d533eab56c16c738301965504753b03ad1de3425d5451"
 dependencies = [
  "crunchy",
  "digest 0.9.0",
- "subtle 2.4.0",
+ "subtle",
 ]
 
 [[package]]
@@ -6443,21 +6443,20 @@ dependencies = [
 
 [[package]]
 name = "pbkdf2"
-version = "0.3.0"
+version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9"
+checksum = "216eaa586a190f0a738f2f918511eecfa90f13295abec0e457cdebcceda80cbd"
 dependencies = [
- "byteorder",
- "crypto-mac 0.7.0",
+ "crypto-mac 0.8.0",
 ]
 
 [[package]]
 name = "pbkdf2"
-version = "0.4.0"
+version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "216eaa586a190f0a738f2f918511eecfa90f13295abec0e457cdebcceda80cbd"
+checksum = "d95f5254224e617595d2cc3cc73ff0a5eaf2637519e25f03388154e9378b6ffa"
 dependencies = [
- "crypto-mac 0.8.0",
+ "crypto-mac 0.11.1",
 ]
 
 [[package]]
@@ -8779,7 +8778,7 @@ dependencies = [
  "rand 0.7.3",
  "rand_core 0.5.1",
  "sha2 0.8.2",
- "subtle 2.4.0",
+ "subtle",
  "zeroize",
 ]
 
@@ -9097,7 +9096,7 @@ dependencies = [
  "ring",
  "rustc_version 0.3.3",
  "sha2 0.9.8",
- "subtle 2.4.0",
+ "subtle",
  "x25519-dalek",
 ]
 
@@ -10082,14 +10081,14 @@ dependencies = [
 
 [[package]]
 name = "substrate-bip39"
-version = "0.4.2"
+version = "0.4.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bed6646a0159b9935b5d045611560eeef842b78d7adc3ba36f5ca325a13a0236"
+checksum = "49eee6965196b32f882dd2ee85a92b1dbead41b04e53907f269de3b0dc04733c"
 dependencies = [
- "hmac 0.7.1",
- "pbkdf2 0.3.0",
+ "hmac 0.11.0",
+ "pbkdf2 0.8.0",
  "schnorrkel",
- "sha2 0.8.2",
+ "sha2 0.9.8",
  "zeroize",
 ]
 
@@ -10315,12 +10314,6 @@ dependencies = [
  "wasm-gc-api",
 ]
 
-[[package]]
-name = "subtle"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee"
-
 [[package]]
 name = "subtle"
 version = "2.4.0"
@@ -11088,7 +11081,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8326b2c654932e3e4f9196e69d08fdf7cfd718e1dc6f66b347e6024a0c961402"
 dependencies = [
  "generic-array 0.14.4",
- "subtle 2.4.0",
+ "subtle",
 ]
 
 [[package]]
diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml
index 9e31ba644c25..26acd44c7cbd 100644
--- a/primitives/core/Cargo.toml
+++ b/primitives/core/Cargo.toml
@@ -32,7 +32,7 @@ hash-db = { version = "0.15.2", default-features = false }
 hash256-std-hasher = { version = "0.15.2", default-features = false }
 base58 = { version = "0.2.0", optional = true }
 rand = { version = "0.7.3", optional = true, features = ["small_rng"] }
-substrate-bip39 = { version = "0.4.2", optional = true }
+substrate-bip39 = { version = "0.4.4", optional = true }
 tiny-bip39 = { version = "0.8.2", optional = true }
 regex = { version = "1.5.4", optional = true }
 num-traits = { version = "0.2.8", default-features = false }

From 083d0ce1386e4b9d87692ce0d30199073ffd02fd Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 11 Nov 2021 12:02:39 -0300
Subject: [PATCH 169/695] Bump parity-util-mem from 0.10.0 to 0.10.2 (#10236)

Bumps [parity-util-mem](https://github.com/paritytech/parity-common) from 0.10.0 to 0.10.2.
- [Release notes](https://github.com/paritytech/parity-common/releases)
- [Commits](https://github.com/paritytech/parity-common/compare/parity-util-mem-v0.10.0...parity-util-mem-v0.10.2)

---
updated-dependencies:
- dependency-name: parity-util-mem
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] 

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 Cargo.lock                            | 4 ++--
 bin/node/bench/Cargo.toml             | 2 +-
 client/informant/Cargo.toml           | 2 +-
 client/service/Cargo.toml             | 2 +-
 client/state-db/Cargo.toml            | 2 +-
 client/transaction-pool/Cargo.toml    | 2 +-
 frame/support/Cargo.toml              | 2 +-
 primitives/core/Cargo.toml            | 2 +-
 primitives/runtime/Cargo.toml         | 2 +-
 primitives/test-primitives/Cargo.toml | 2 +-
 test-utils/runtime/Cargo.toml         | 2 +-
 11 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 51eb96d6989f..8ad1560b85aa 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -6301,9 +6301,9 @@ dependencies = [
 
 [[package]]
 name = "parity-util-mem"
-version = "0.10.0"
+version = "0.10.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ad6f1acec69b95caf435bbd158d486e5a0a44fcf51531e84922c59ff09e8457"
+checksum = "6f4cb4e169446179cbc6b8b6320cc9fca49bd2e94e8db25f25f200a8ea774770"
 dependencies = [
  "cfg-if 1.0.0",
  "hashbrown 0.11.2",
diff --git a/bin/node/bench/Cargo.toml b/bin/node/bench/Cargo.toml
index f59ea2361186..66a14a123ee5 100644
--- a/bin/node/bench/Cargo.toml
+++ b/bin/node/bench/Cargo.toml
@@ -35,7 +35,7 @@ fs_extra = "1"
 hex = "0.4.0"
 rand = { version = "0.7.2", features = ["small_rng"] }
 lazy_static = "1.4.0"
-parity-util-mem = { version = "0.10.0", default-features = false, features = [
+parity-util-mem = { version = "0.10.2", default-features = false, features = [
     "primitive-types",
 ] }
 parity-db = { version = "0.3" }
diff --git a/client/informant/Cargo.toml b/client/informant/Cargo.toml
index 7d92e14e5d47..5eba3ecaeb2a 100644
--- a/client/informant/Cargo.toml
+++ b/client/informant/Cargo.toml
@@ -17,7 +17,7 @@ ansi_term = "0.12.1"
 futures = "0.3.9"
 futures-timer = "3.0.1"
 log = "0.4.8"
-parity-util-mem = { version = "0.10.0", default-features = false, features = ["primitive-types"] }
+parity-util-mem = { version = "0.10.2", default-features = false, features = ["primitive-types"] }
 sc-client-api = { version = "4.0.0-dev", path = "../api" }
 sc-network = { version = "0.10.0-dev", path = "../network" }
 sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" }
diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml
index 97b0f4e461c8..c090495fe04e 100644
--- a/client/service/Cargo.toml
+++ b/client/service/Cargo.toml
@@ -74,7 +74,7 @@ sc-tracing = { version = "4.0.0-dev", path = "../tracing" }
 sp-tracing = { version = "4.0.0-dev", path = "../../primitives/tracing" }
 tracing = "0.1.29"
 tracing-futures = { version = "0.2.4" }
-parity-util-mem = { version = "0.10.0", default-features = false, features = [
+parity-util-mem = { version = "0.10.2", default-features = false, features = [
 	"primitive-types",
 ] }
 async-trait = "0.1.50"
diff --git a/client/state-db/Cargo.toml b/client/state-db/Cargo.toml
index abd378c6fff3..cd14038cb77b 100644
--- a/client/state-db/Cargo.toml
+++ b/client/state-db/Cargo.toml
@@ -18,5 +18,5 @@ log = "0.4.11"
 sc-client-api = { version = "4.0.0-dev", path = "../api" }
 sp-core = { version = "4.0.0-dev", path = "../../primitives/core" }
 codec = { package = "parity-scale-codec", version = "2.0.0", features = ["derive"] }
-parity-util-mem = { version = "0.10.0", default-features = false, features = ["primitive-types"] }
+parity-util-mem = { version = "0.10.2", default-features = false, features = ["primitive-types"] }
 parity-util-mem-derive = "0.1.0"
diff --git a/client/transaction-pool/Cargo.toml b/client/transaction-pool/Cargo.toml
index 99f1f3788ec0..d26969cf1e09 100644
--- a/client/transaction-pool/Cargo.toml
+++ b/client/transaction-pool/Cargo.toml
@@ -18,7 +18,7 @@ thiserror = "1.0.21"
 futures = "0.3.16"
 intervalier = "0.4.0"
 log = "0.4.8"
-parity-util-mem = { version = "0.10.0", default-features = false, features = ["primitive-types"] }
+parity-util-mem = { version = "0.10.2", default-features = false, features = ["primitive-types"] }
 parking_lot = "0.11.1"
 prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.10.0-dev"}
 sc-client-api = { version = "4.0.0-dev", path = "../api" }
diff --git a/frame/support/Cargo.toml b/frame/support/Cargo.toml
index 42981dc160a4..1f48dadc2987 100644
--- a/frame/support/Cargo.toml
+++ b/frame/support/Cargo.toml
@@ -40,7 +40,7 @@ sp-core-hashing-proc-macro = { version = "4.0.0-dev", path = "../../primitives/c
 assert_matches = "1.3.0"
 pretty_assertions = "1.0.0"
 frame-system = { version = "4.0.0-dev", path = "../system" }
-parity-util-mem = { version = "0.10.0", default-features = false, features = ["primitive-types"] }
+parity-util-mem = { version = "0.10.2", default-features = false, features = ["primitive-types"] }
 
 [features]
 default = ["std"]
diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml
index 26acd44c7cbd..48749904763f 100644
--- a/primitives/core/Cargo.toml
+++ b/primitives/core/Cargo.toml
@@ -43,7 +43,7 @@ parking_lot = { version = "0.11.1", optional = true }
 sp-debug-derive = { version = "4.0.0-dev", default-features = false, path = "../debug-derive" }
 sp-externalities = { version = "0.10.0-dev", optional = true, path = "../externalities" }
 sp-storage = { version = "4.0.0-dev", default-features = false, path = "../storage" }
-parity-util-mem = { version = "0.10.0", default-features = false, features = [
+parity-util-mem = { version = "0.10.2", default-features = false, features = [
 	"primitive-types",
 ] }
 futures = { version = "0.3.1", optional = true }
diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml
index 9d2957e7aed1..8e466bf4a1e8 100644
--- a/primitives/runtime/Cargo.toml
+++ b/primitives/runtime/Cargo.toml
@@ -27,7 +27,7 @@ log = { version = "0.4.14", default-features = false }
 paste = "1.0"
 rand = { version = "0.7.2", optional = true }
 impl-trait-for-tuples = "0.2.1"
-parity-util-mem = { version = "0.10.0", default-features = false, features = ["primitive-types"] }
+parity-util-mem = { version = "0.10.2", default-features = false, features = ["primitive-types"] }
 hash256-std-hasher = { version = "0.15.2", default-features = false }
 either = { version = "1.5", default-features = false }
 
diff --git a/primitives/test-primitives/Cargo.toml b/primitives/test-primitives/Cargo.toml
index 4d184c7d02e7..b95c88626996 100644
--- a/primitives/test-primitives/Cargo.toml
+++ b/primitives/test-primitives/Cargo.toml
@@ -17,7 +17,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features =
 sp-core = { version = "4.0.0-dev", default-features = false, path = "../core" }
 serde = { version = "1.0.126", optional = true, features = ["derive"] }
 sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../runtime" }
-parity-util-mem = { version = "0.10.0", default-features = false, features = ["primitive-types"] }
+parity-util-mem = { version = "0.10.2", default-features = false, features = ["primitive-types"] }
 
 [features]
 default = [
diff --git a/test-utils/runtime/Cargo.toml b/test-utils/runtime/Cargo.toml
index f02e07904633..d0d85029738e 100644
--- a/test-utils/runtime/Cargo.toml
+++ b/test-utils/runtime/Cargo.toml
@@ -40,7 +40,7 @@ sp-finality-grandpa = { version = "4.0.0-dev", default-features = false, path =
 sp-trie = { version = "4.0.0-dev", default-features = false, path = "../../primitives/trie" }
 sp-transaction-pool = { version = "4.0.0-dev", default-features = false, path = "../../primitives/transaction-pool" }
 trie-db = { version = "0.22.6", default-features = false }
-parity-util-mem = { version = "0.10.0", default-features = false, features = ["primitive-types"] }
+parity-util-mem = { version = "0.10.2", default-features = false, features = ["primitive-types"] }
 sc-service = { version = "0.10.0-dev", default-features = false, optional = true, features = ["test-helpers"], path = "../../client/service" }
 sp-state-machine = { version = "0.10.0-dev", default-features = false, path = "../../primitives/state-machine" }
 sp-externalities = { version = "0.10.0-dev", default-features = false, path = "../../primitives/externalities" }

From c2afe155d4239480795e4d27f9ebb75f1a584ecc Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 11 Nov 2021 16:58:14 +0100
Subject: [PATCH 170/695] Bump proc-macro-crate from 1.0.0 to 1.1.0 (#10237)

Bumps [proc-macro-crate](https://github.com/bkchr/proc-macro-crate) from 1.0.0 to 1.1.0.
- [Release notes](https://github.com/bkchr/proc-macro-crate/releases)
- [Commits](https://github.com/bkchr/proc-macro-crate/commits)

---
updated-dependencies:
- dependency-name: proc-macro-crate
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] 

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 Cargo.lock                                    | 28 +++++++++----------
 client/chain-spec/derive/Cargo.toml           |  2 +-
 client/tracing/proc-macro/Cargo.toml          |  2 +-
 frame/staking/reward-curve/Cargo.toml         |  2 +-
 frame/support/procedural/tools/Cargo.toml     |  2 +-
 primitives/api/proc-macro/Cargo.toml          |  2 +-
 .../npos-elections/solution-type/Cargo.toml   |  2 +-
 .../runtime-interface/proc-macro/Cargo.toml   |  2 +-
 test-utils/derive/Cargo.toml                  |  2 +-
 9 files changed, 22 insertions(+), 22 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 8ad1560b85aa..423ec1de4e7d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2071,7 +2071,7 @@ name = "frame-support-procedural-tools"
 version = "4.0.0-dev"
 dependencies = [
  "frame-support-procedural-tools-derive",
- "proc-macro-crate 1.0.0",
+ "proc-macro-crate 1.1.0",
  "proc-macro2",
  "quote",
  "syn",
@@ -3146,7 +3146,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d802063f7a3c867456955f9d2f15eb3ee0edb5ec9ec2b5526324756759221c0f"
 dependencies = [
  "log 0.4.14",
- "proc-macro-crate 1.0.0",
+ "proc-macro-crate 1.1.0",
  "proc-macro2",
  "quote",
  "syn",
@@ -4362,7 +4362,7 @@ version = "0.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "424f6e86263cd5294cbd7f1e95746b95aca0e0d66bff31e5a40d6baa87b4aa99"
 dependencies = [
- "proc-macro-crate 1.0.0",
+ "proc-macro-crate 1.1.0",
  "proc-macro-error",
  "proc-macro2",
  "quote",
@@ -6022,7 +6022,7 @@ dependencies = [
 name = "pallet-staking-reward-curve"
 version = "4.0.0-dev"
 dependencies = [
- "proc-macro-crate 1.0.0",
+ "proc-macro-crate 1.1.0",
  "proc-macro2",
  "quote",
  "sp-runtime",
@@ -6273,7 +6273,7 @@ version = "2.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1557010476e0595c9b568d16dcfb81b93cdeb157612726f5170d31aa707bed27"
 dependencies = [
- "proc-macro-crate 1.0.0",
+ "proc-macro-crate 1.1.0",
  "proc-macro2",
  "quote",
  "syn",
@@ -6743,9 +6743,9 @@ dependencies = [
 
 [[package]]
 name = "proc-macro-crate"
-version = "1.0.0"
+version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41fdbd1df62156fbc5945f4762632564d7d038153091c3fcf1067f6aef7cff92"
+checksum = "1ebace6889caf889b4d3f76becee12e90353f2b8c7d875534a71e5742f8f6f83"
 dependencies = [
  "thiserror",
  "toml",
@@ -7664,7 +7664,7 @@ dependencies = [
 name = "sc-chain-spec-derive"
 version = "4.0.0-dev"
 dependencies = [
- "proc-macro-crate 1.0.0",
+ "proc-macro-crate 1.1.0",
  "proc-macro2",
  "quote",
  "syn",
@@ -8665,7 +8665,7 @@ dependencies = [
 name = "sc-tracing-proc-macro"
 version = "4.0.0-dev"
 dependencies = [
- "proc-macro-crate 1.0.0",
+ "proc-macro-crate 1.1.0",
  "proc-macro2",
  "quote",
  "syn",
@@ -8748,7 +8748,7 @@ version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "baeb2780690380592f86205aa4ee49815feb2acad8c2f59e6dd207148c3f1fcd"
 dependencies = [
- "proc-macro-crate 1.0.0",
+ "proc-macro-crate 1.1.0",
  "proc-macro2",
  "quote",
  "syn",
@@ -9174,7 +9174,7 @@ name = "sp-api-proc-macro"
 version = "4.0.0-dev"
 dependencies = [
  "blake2-rfc",
- "proc-macro-crate 1.0.0",
+ "proc-macro-crate 1.1.0",
  "proc-macro2",
  "quote",
  "syn",
@@ -9618,7 +9618,7 @@ name = "sp-npos-elections-solution-type"
 version = "4.0.0-dev"
 dependencies = [
  "parity-scale-codec",
- "proc-macro-crate 1.0.0",
+ "proc-macro-crate 1.1.0",
  "proc-macro2",
  "quote",
  "scale-info",
@@ -9709,7 +9709,7 @@ name = "sp-runtime-interface-proc-macro"
 version = "4.0.0-dev"
 dependencies = [
  "Inflector",
- "proc-macro-crate 1.0.0",
+ "proc-macro-crate 1.1.0",
  "proc-macro2",
  "quote",
  "syn",
@@ -10285,7 +10285,7 @@ dependencies = [
 name = "substrate-test-utils-derive"
 version = "0.10.0-dev"
 dependencies = [
- "proc-macro-crate 1.0.0",
+ "proc-macro-crate 1.1.0",
  "proc-macro2",
  "quote",
  "syn",
diff --git a/client/chain-spec/derive/Cargo.toml b/client/chain-spec/derive/Cargo.toml
index 25339eea14f1..3ffb70d50ef5 100644
--- a/client/chain-spec/derive/Cargo.toml
+++ b/client/chain-spec/derive/Cargo.toml
@@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 proc-macro = true
 
 [dependencies]
-proc-macro-crate = "1.0.0"
+proc-macro-crate = "1.1.0"
 proc-macro2 = "1.0.29"
 quote = "1.0.10"
 syn = "1.0.81"
diff --git a/client/tracing/proc-macro/Cargo.toml b/client/tracing/proc-macro/Cargo.toml
index c51c8764e677..39c22bf856b2 100644
--- a/client/tracing/proc-macro/Cargo.toml
+++ b/client/tracing/proc-macro/Cargo.toml
@@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 proc-macro = true
 
 [dependencies]
-proc-macro-crate = "1.0.0"
+proc-macro-crate = "1.1.0"
 proc-macro2 = "1.0.29"
 quote = { version = "1.0.10", features = ["proc-macro"] }
 syn = { version = "1.0.81", features = ["proc-macro", "full", "extra-traits", "parsing"] }
diff --git a/frame/staking/reward-curve/Cargo.toml b/frame/staking/reward-curve/Cargo.toml
index 1250bbcd3905..fd306eb08572 100644
--- a/frame/staking/reward-curve/Cargo.toml
+++ b/frame/staking/reward-curve/Cargo.toml
@@ -18,7 +18,7 @@ proc-macro = true
 syn = { version = "1.0.81", features = ["full", "visit"] }
 quote = "1.0.10"
 proc-macro2 = "1.0.29"
-proc-macro-crate = "1.0.0"
+proc-macro-crate = "1.1.0"
 
 [dev-dependencies]
 sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" }
diff --git a/frame/support/procedural/tools/Cargo.toml b/frame/support/procedural/tools/Cargo.toml
index 7b957be18401..c0a3b98632f5 100644
--- a/frame/support/procedural/tools/Cargo.toml
+++ b/frame/support/procedural/tools/Cargo.toml
@@ -16,4 +16,4 @@ frame-support-procedural-tools-derive = { version = "3.0.0", path = "./derive" }
 proc-macro2 = "1.0.29"
 quote = "1.0.10"
 syn = { version = "1.0.81", features = ["full", "visit", "extra-traits"] }
-proc-macro-crate = "1.0.0"
+proc-macro-crate = "1.1.0"
diff --git a/primitives/api/proc-macro/Cargo.toml b/primitives/api/proc-macro/Cargo.toml
index a5df7aef322a..c8eaae7c02ab 100644
--- a/primitives/api/proc-macro/Cargo.toml
+++ b/primitives/api/proc-macro/Cargo.toml
@@ -20,7 +20,7 @@ quote = "1.0.10"
 syn = { version = "1.0.81", features = ["full", "fold", "extra-traits", "visit"] }
 proc-macro2 = "1.0.29"
 blake2-rfc = { version = "0.2.18", default-features = false }
-proc-macro-crate = "1.0.0"
+proc-macro-crate = "1.1.0"
 
 # Required for the doc tests
 [features]
diff --git a/primitives/npos-elections/solution-type/Cargo.toml b/primitives/npos-elections/solution-type/Cargo.toml
index 5d8d3890577a..a64ca45ce842 100644
--- a/primitives/npos-elections/solution-type/Cargo.toml
+++ b/primitives/npos-elections/solution-type/Cargo.toml
@@ -18,7 +18,7 @@ proc-macro = true
 syn = { version = "1.0.81", features = ["full", "visit"] }
 quote = "1.0"
 proc-macro2 = "1.0.29"
-proc-macro-crate = "1.0.0"
+proc-macro-crate = "1.1.0"
 
 [dev-dependencies]
 parity-scale-codec = "2.3.1"
diff --git a/primitives/runtime-interface/proc-macro/Cargo.toml b/primitives/runtime-interface/proc-macro/Cargo.toml
index cc5daa695bb0..0be33c2c55ad 100644
--- a/primitives/runtime-interface/proc-macro/Cargo.toml
+++ b/primitives/runtime-interface/proc-macro/Cargo.toml
@@ -20,4 +20,4 @@ syn = { version = "1.0.81", features = ["full", "visit", "fold", "extra-traits"]
 quote = "1.0.10"
 proc-macro2 = "1.0.29"
 Inflector = "0.11.4"
-proc-macro-crate = "1.0.0"
+proc-macro-crate = "1.1.0"
diff --git a/test-utils/derive/Cargo.toml b/test-utils/derive/Cargo.toml
index 967fc1e87a36..0b894d92b2bc 100644
--- a/test-utils/derive/Cargo.toml
+++ b/test-utils/derive/Cargo.toml
@@ -11,7 +11,7 @@ description = "Substrate test utilities macros"
 [dependencies]
 quote = "1.0.10"
 syn = { version = "1.0.81", features = ["full"] }
-proc-macro-crate = "1.0.0"
+proc-macro-crate = "1.1.0"
 proc-macro2 = "1.0.29"
 
 [lib]

From f78549161b9827ddde2519a12d1a279b83634f41 Mon Sep 17 00:00:00 2001
From: sandreim <54316454+sandreim@users.noreply.github.com>
Date: Thu, 11 Nov 2021 19:15:09 +0200
Subject: [PATCH 171/695] Add group name in task metrics  (#10196)

* SpawnNamed: add new trait methods

Signed-off-by: Andrei Sandu 

* Implement new methods

Signed-off-by: Andrei Sandu 

* cargo fmt

Signed-off-by: Andrei Sandu 

* SpawnNamed: add new trait methods

Signed-off-by: Andrei Sandu 

* Implement new methods

Signed-off-by: Andrei Sandu 

* cargo fmt

Signed-off-by: Andrei Sandu 

* New approach - spaw() group param

Signed-off-by: Andrei Sandu 

* Update traits: SpawnNamed and SpawnNamed

Signed-off-by: Andrei Sandu 

* Update TaskManager tests

Signed-off-by: Andrei Sandu 

* Update test TaskExecutor

Signed-off-by: Andrei Sandu 

* Fix typo

Signed-off-by: Andrei Sandu 

* grunt work: fix spawn() calls

Signed-off-by: Andrei Sandu 

* cargo fmt

Signed-off-by: Andrei Sandu 

* remove old code

Signed-off-by: Andrei Sandu 

* cargo fmt - the right version

Signed-off-by: Andrei Sandu 

* Implement review feedback

- use Option group name in SpawnNamed methods
- switch to kebab case
- implement default group name
- add group name to some tasks

Signed-off-by: Andrei Sandu 
---
 bin/node-template/node/src/service.rs         |   7 +-
 bin/node/cli/src/service.rs                   |  24 +++--
 bin/node/testing/src/bench.rs                 |  14 ++-
 .../basic-authorship/src/basic_authorship.rs  |   1 +
 .../common/src/import_queue/basic_queue.rs    |   6 +-
 client/executor/src/native_executor.rs        |   1 +
 client/offchain/src/lib.rs                    |   1 +
 client/rpc/src/lib.rs                         |   3 +-
 client/service/src/builder.rs                 |  20 ++--
 client/service/src/lib.rs                     |   2 +-
 client/service/src/task_manager/mod.rs        | 100 ++++++++++++------
 client/service/src/task_manager/tests.rs      |  52 ++++-----
 client/transaction-pool/src/api.rs            |   1 +
 client/transaction-pool/src/lib.rs            |   2 +-
 primitives/core/src/testing.rs                |  22 +++-
 primitives/core/src/traits.rs                 |  67 +++++++++---
 primitives/io/src/batch_verifier.rs           |   4 +-
 primitives/tasks/src/lib.rs                   |   1 +
 test-utils/test-runner/src/client.rs          |   4 +-
 19 files changed, 232 insertions(+), 100 deletions(-)

diff --git a/bin/node-template/node/src/service.rs b/bin/node-template/node/src/service.rs
index d673a54a9488..c71336c33088 100644
--- a/bin/node-template/node/src/service.rs
+++ b/bin/node-template/node/src/service.rs
@@ -89,7 +89,7 @@ pub fn new_partial(
 	let client = Arc::new(client);
 
 	let telemetry = telemetry.map(|(worker, telemetry)| {
-		task_manager.spawn_handle().spawn("telemetry", worker.run());
+		task_manager.spawn_handle().spawn("telemetry", None, worker.run());
 		telemetry
 	});
 
@@ -289,7 +289,9 @@ pub fn new_full(mut config: Configuration) -> Result
 
 		// the AURA authoring task is considered essential, i.e. if it
 		// fails we take down the service with it.
-		task_manager.spawn_essential_handle().spawn_blocking("aura", aura);
+		task_manager
+			.spawn_essential_handle()
+			.spawn_blocking("aura", Some("block-authoring"), aura);
 	}
 
 	// if the node isn't actively participating in consensus then it doesn't
@@ -329,6 +331,7 @@ pub fn new_full(mut config: Configuration) -> Result
 		// if it fails we take down the service with it.
 		task_manager.spawn_essential_handle().spawn_blocking(
 			"grandpa-voter",
+			None,
 			sc_finality_grandpa::run_grandpa_voter(grandpa_config)?,
 		);
 	}
diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs
index a022d501d015..dee546bf0700 100644
--- a/bin/node/cli/src/service.rs
+++ b/bin/node/cli/src/service.rs
@@ -170,7 +170,7 @@ pub fn new_partial(
 	let client = Arc::new(client);
 
 	let telemetry = telemetry.map(|(worker, telemetry)| {
-		task_manager.spawn_handle().spawn("telemetry", worker.run());
+		task_manager.spawn_handle().spawn("telemetry", None, worker.run());
 		telemetry
 	});
 
@@ -436,7 +436,11 @@ pub fn new_full_base(
 		};
 
 		let babe = sc_consensus_babe::start_babe(babe_config)?;
-		task_manager.spawn_essential_handle().spawn_blocking("babe-proposer", babe);
+		task_manager.spawn_essential_handle().spawn_blocking(
+			"babe-proposer",
+			Some("block-authoring"),
+			babe,
+		);
 	}
 
 	// Spawn authority discovery module.
@@ -463,9 +467,11 @@ pub fn new_full_base(
 				prometheus_registry.clone(),
 			);
 
-		task_manager
-			.spawn_handle()
-			.spawn("authority-discovery-worker", authority_discovery_worker.run());
+		task_manager.spawn_handle().spawn(
+			"authority-discovery-worker",
+			Some("networking"),
+			authority_discovery_worker.run(),
+		);
 	}
 
 	// if the node isn't actively participating in consensus then it doesn't
@@ -503,9 +509,11 @@ pub fn new_full_base(
 
 		// the GRANDPA voter task is considered infallible, i.e.
 		// if it fails we take down the service with it.
-		task_manager
-			.spawn_essential_handle()
-			.spawn_blocking("grandpa-voter", grandpa::run_grandpa_voter(grandpa_config)?);
+		task_manager.spawn_essential_handle().spawn_blocking(
+			"grandpa-voter",
+			None,
+			grandpa::run_grandpa_voter(grandpa_config)?,
+		);
 	}
 
 	network_starter.start_network();
diff --git a/bin/node/testing/src/bench.rs b/bin/node/testing/src/bench.rs
index cf0a463cc3e9..5ee1ec998be4 100644
--- a/bin/node/testing/src/bench.rs
+++ b/bin/node/testing/src/bench.rs
@@ -243,11 +243,21 @@ impl TaskExecutor {
 }
 
 impl SpawnNamed for TaskExecutor {
-	fn spawn(&self, _: &'static str, future: futures::future::BoxFuture<'static, ()>) {
+	fn spawn(
+		&self,
+		_: &'static str,
+		_: Option<&'static str>,
+		future: futures::future::BoxFuture<'static, ()>,
+	) {
 		self.pool.spawn_ok(future);
 	}
 
-	fn spawn_blocking(&self, _: &'static str, future: futures::future::BoxFuture<'static, ()>) {
+	fn spawn_blocking(
+		&self,
+		_: &'static str,
+		_: Option<&'static str>,
+		future: futures::future::BoxFuture<'static, ()>,
+	) {
 		self.pool.spawn_ok(future);
 	}
 }
diff --git a/client/basic-authorship/src/basic_authorship.rs b/client/basic-authorship/src/basic_authorship.rs
index 573601a9102c..305c4d753c1e 100644
--- a/client/basic-authorship/src/basic_authorship.rs
+++ b/client/basic-authorship/src/basic_authorship.rs
@@ -270,6 +270,7 @@ where
 
 		spawn_handle.spawn_blocking(
 			"basic-authorship-proposer",
+			None,
 			Box::pin(async move {
 				// leave some time for evaluation and block finalization (33%)
 				let deadline = (self.now)() + max_duration - max_duration / 3;
diff --git a/client/consensus/common/src/import_queue/basic_queue.rs b/client/consensus/common/src/import_queue/basic_queue.rs
index 9042c8798be4..0461d7cf954c 100644
--- a/client/consensus/common/src/import_queue/basic_queue.rs
+++ b/client/consensus/common/src/import_queue/basic_queue.rs
@@ -89,7 +89,11 @@ impl BasicQueue {
 			metrics,
 		);
 
-		spawner.spawn_essential_blocking("basic-block-import-worker", future.boxed());
+		spawner.spawn_essential_blocking(
+			"basic-block-import-worker",
+			Some("block-import"),
+			future.boxed(),
+		);
 
 		Self { justification_sender, block_import_sender, result_port, _phantom: PhantomData }
 	}
diff --git a/client/executor/src/native_executor.rs b/client/executor/src/native_executor.rs
index d912fc0fd13c..62e76d559c0f 100644
--- a/client/executor/src/native_executor.rs
+++ b/client/executor/src/native_executor.rs
@@ -399,6 +399,7 @@ impl RuntimeSpawn for RuntimeInstanceSpawn {
 		let scheduler = self.scheduler.clone();
 		self.scheduler.spawn(
 			"executor-extra-runtime-instance",
+			None,
 			Box::pin(async move {
 				let module = AssertUnwindSafe(module);
 
diff --git a/client/offchain/src/lib.rs b/client/offchain/src/lib.rs
index a77fd17a2c8b..2de24e10d927 100644
--- a/client/offchain/src/lib.rs
+++ b/client/offchain/src/lib.rs
@@ -226,6 +226,7 @@ pub async fn notification_future(
 			if n.is_new_best {
 				spawner.spawn(
 					"offchain-on-block",
+					Some("offchain-worker"),
 					offchain
 						.on_block_imported(&n.header, network_provider.clone(), is_validator)
 						.boxed(),
diff --git a/client/rpc/src/lib.rs b/client/rpc/src/lib.rs
index 832585db4854..8f951632698f 100644
--- a/client/rpc/src/lib.rs
+++ b/client/rpc/src/lib.rs
@@ -54,7 +54,8 @@ impl SubscriptionTaskExecutor {
 
 impl Spawn for SubscriptionTaskExecutor {
 	fn spawn_obj(&self, future: FutureObj<'static, ()>) -> Result<(), SpawnError> {
-		self.0.spawn("substrate-rpc-subscription", future.map(drop).boxed());
+		self.0
+			.spawn("substrate-rpc-subscription", Some("rpc"), future.map(drop).boxed());
 		Ok(())
 	}
 
diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs
index bcb05ce74370..88ba6282b5f4 100644
--- a/client/service/src/builder.rs
+++ b/client/service/src/builder.rs
@@ -424,6 +424,7 @@ where
 	if let Some(offchain) = offchain_workers.clone() {
 		spawn_handle.spawn(
 			"offchain-notifications",
+			Some("offchain-worker"),
 			sc_offchain::notification_future(
 				config.role.is_authority(),
 				client.clone(),
@@ -505,11 +506,13 @@ where
 	// Inform the tx pool about imported and finalized blocks.
 	spawn_handle.spawn(
 		"txpool-notifications",
+		Some("transaction-pool"),
 		sc_transaction_pool::notification_future(client.clone(), transaction_pool.clone()),
 	);
 
 	spawn_handle.spawn(
 		"on-transaction-imported",
+		Some("transaction-pool"),
 		transaction_notifications(transaction_pool.clone(), network.clone(), telemetry.clone()),
 	);
 
@@ -520,6 +523,7 @@ where
 			let metrics = MetricsService::with_prometheus(telemetry.clone(), ®istry, &config)?;
 			spawn_handle.spawn(
 				"prometheus-endpoint",
+				None,
 				prometheus_endpoint::init_prometheus(port, registry).map(drop),
 			);
 
@@ -531,6 +535,7 @@ where
 	// Periodically updated metrics and telemetry updates.
 	spawn_handle.spawn(
 		"telemetry-periodic-send",
+		None,
 		metrics_service.run(client.clone(), transaction_pool.clone(), network.clone()),
 	);
 
@@ -567,6 +572,7 @@ where
 	// Spawn informant task
 	spawn_handle.spawn(
 		"informant",
+		None,
 		sc_informant::build(
 			client.clone(),
 			network.clone(),
@@ -798,7 +804,7 @@ where
 				config.network.default_peers_set.in_peers as usize +
 					config.network.default_peers_set.out_peers as usize,
 			);
-			spawn_handle.spawn("block_request_handler", handler.run());
+			spawn_handle.spawn("block-request-handler", Some("networking"), handler.run());
 			protocol_config
 		}
 	};
@@ -815,7 +821,7 @@ where
 				config.network.default_peers_set.in_peers as usize +
 					config.network.default_peers_set.out_peers as usize,
 			);
-			spawn_handle.spawn("state_request_handler", handler.run());
+			spawn_handle.spawn("state-request-handler", Some("networking"), handler.run());
 			protocol_config
 		}
 	};
@@ -828,7 +834,7 @@ where
 			// Allow both outgoing and incoming requests.
 			let (handler, protocol_config) =
 				WarpSyncRequestHandler::new(protocol_id.clone(), provider.clone());
-			spawn_handle.spawn("warp_sync_request_handler", handler.run());
+			spawn_handle.spawn("warp-sync-request-handler", Some("networking"), handler.run());
 			protocol_config
 		};
 		(provider, protocol_config)
@@ -842,7 +848,7 @@ where
 			// Allow both outgoing and incoming requests.
 			let (handler, protocol_config) =
 				LightClientRequestHandler::new(&protocol_id, client.clone());
-			spawn_handle.spawn("light_client_request_handler", handler.run());
+			spawn_handle.spawn("light-client-request-handler", Some("networking"), handler.run());
 			protocol_config
 		}
 	};
@@ -852,13 +858,13 @@ where
 		executor: {
 			let spawn_handle = Clone::clone(&spawn_handle);
 			Some(Box::new(move |fut| {
-				spawn_handle.spawn("libp2p-node", fut);
+				spawn_handle.spawn("libp2p-node", Some("networking"), fut);
 			}))
 		},
 		transactions_handler_executor: {
 			let spawn_handle = Clone::clone(&spawn_handle);
 			Box::new(move |fut| {
-				spawn_handle.spawn("network-transactions-handler", fut);
+				spawn_handle.spawn("network-transactions-handler", Some("networking"), fut);
 			})
 		},
 		network_config: config.network.clone(),
@@ -920,7 +926,7 @@ where
 	// issue, and ideally we would like to fix the network future to take as little time as
 	// possible, but we also take the extra harm-prevention measure to execute the networking
 	// future using `spawn_blocking`.
-	spawn_handle.spawn_blocking("network-worker", async move {
+	spawn_handle.spawn_blocking("network-worker", Some("networking"), async move {
 		if network_start_rx.await.is_err() {
 			log::warn!(
 				"The NetworkStart returned as part of `build_network` has been silently dropped"
diff --git a/client/service/src/lib.rs b/client/service/src/lib.rs
index ce77be5a7c1d..bd43d4c464ea 100644
--- a/client/service/src/lib.rs
+++ b/client/service/src/lib.rs
@@ -75,7 +75,7 @@ pub use sc_transaction_pool::Options as TransactionPoolOptions;
 pub use sc_transaction_pool_api::{error::IntoPoolError, InPoolTransaction, TransactionPool};
 #[doc(hidden)]
 pub use std::{ops::Deref, result::Result, sync::Arc};
-pub use task_manager::{SpawnTaskHandle, TaskManager};
+pub use task_manager::{SpawnTaskHandle, TaskManager, DEFAULT_GROUP_NAME};
 
 const DEFAULT_PROTOCOL_ID: &str = "sup";
 
diff --git a/client/service/src/task_manager/mod.rs b/client/service/src/task_manager/mod.rs
index c827aa71dac2..64c00226073c 100644
--- a/client/service/src/task_manager/mod.rs
+++ b/client/service/src/task_manager/mod.rs
@@ -38,6 +38,9 @@ mod prometheus_future;
 #[cfg(test)]
 mod tests;
 
+/// Default task group name.
+pub const DEFAULT_GROUP_NAME: &'static str = "default";
+
 /// An handle for spawning tasks in the service.
 #[derive(Clone)]
 pub struct SpawnTaskHandle {
@@ -48,31 +51,39 @@ pub struct SpawnTaskHandle {
 }
 
 impl SpawnTaskHandle {
-	/// Spawns the given task with the given name.
+	/// Spawns the given task with the given name and an optional group name.
+	/// If group is not specified `DEFAULT_GROUP_NAME` will be used.
 	///
-	/// Note that the `name` is a `&'static str`. The reason for this choice is that statistics
-	/// about this task are getting reported to the Prometheus endpoint (if enabled), and that
-	/// therefore the set of possible task names must be bounded.
+	/// Note that the `name`/`group` is a `&'static str`. The reason for this choice is that
+	/// statistics about this task are getting reported to the Prometheus endpoint (if enabled), and
+	/// that therefore the set of possible task names must be bounded.
 	///
 	/// In other words, it would be a bad idea for someone to do for example
 	/// `spawn(format!("{:?}", some_public_key))`.
-	pub fn spawn(&self, name: &'static str, task: impl Future + Send + 'static) {
-		self.spawn_inner(name, task, TaskType::Async)
+	pub fn spawn(
+		&self,
+		name: &'static str,
+		group: Option<&'static str>,
+		task: impl Future + Send + 'static,
+	) {
+		self.spawn_inner(name, group, task, TaskType::Async)
 	}
 
 	/// Spawns the blocking task with the given name. See also `spawn`.
 	pub fn spawn_blocking(
 		&self,
 		name: &'static str,
+		group: Option<&'static str>,
 		task: impl Future + Send + 'static,
 	) {
-		self.spawn_inner(name, task, TaskType::Blocking)
+		self.spawn_inner(name, group, task, TaskType::Blocking)
 	}
 
 	/// Helper function that implements the spawning logic. See `spawn` and `spawn_blocking`.
 	fn spawn_inner(
 		&self,
 		name: &'static str,
+		group: Option<&'static str>,
 		task: impl Future + Send + 'static,
 		task_type: TaskType,
 	) {
@@ -83,21 +94,23 @@ impl SpawnTaskHandle {
 
 		let on_exit = self.on_exit.clone();
 		let metrics = self.metrics.clone();
+		// If no group is specified use default.
+		let group = group.unwrap_or(DEFAULT_GROUP_NAME);
 
 		// Note that we increase the started counter here and not within the future. This way,
 		// we could properly visualize on Prometheus situations where the spawning doesn't work.
 		if let Some(metrics) = &self.metrics {
-			metrics.tasks_spawned.with_label_values(&[name]).inc();
+			metrics.tasks_spawned.with_label_values(&[name, group]).inc();
 			// We do a dummy increase in order for the task to show up in metrics.
-			metrics.tasks_ended.with_label_values(&[name, "finished"]).inc_by(0);
+			metrics.tasks_ended.with_label_values(&[name, "finished", group]).inc_by(0);
 		}
 
 		let future = async move {
 			if let Some(metrics) = metrics {
 				// Add some wrappers around `task`.
 				let task = {
-					let poll_duration = metrics.poll_duration.with_label_values(&[name]);
-					let poll_start = metrics.poll_start.with_label_values(&[name]);
+					let poll_duration = metrics.poll_duration.with_label_values(&[name, group]);
+					let poll_start = metrics.poll_start.with_label_values(&[name, group]);
 					let inner =
 						prometheus_future::with_poll_durations(poll_duration, poll_start, task);
 					// The logic of `AssertUnwindSafe` here is ok considering that we throw
@@ -108,15 +121,15 @@ impl SpawnTaskHandle {
 
 				match select(on_exit, task).await {
 					Either::Right((Err(payload), _)) => {
-						metrics.tasks_ended.with_label_values(&[name, "panic"]).inc();
+						metrics.tasks_ended.with_label_values(&[name, "panic", group]).inc();
 						panic::resume_unwind(payload)
 					},
 					Either::Right((Ok(()), _)) => {
-						metrics.tasks_ended.with_label_values(&[name, "finished"]).inc();
+						metrics.tasks_ended.with_label_values(&[name, "finished", group]).inc();
 					},
 					Either::Left(((), _)) => {
 						// The `on_exit` has triggered.
-						metrics.tasks_ended.with_label_values(&[name, "interrupted"]).inc();
+						metrics.tasks_ended.with_label_values(&[name, "interrupted", group]).inc();
 					},
 				}
 			} else {
@@ -141,12 +154,22 @@ impl SpawnTaskHandle {
 }
 
 impl sp_core::traits::SpawnNamed for SpawnTaskHandle {
-	fn spawn_blocking(&self, name: &'static str, future: BoxFuture<'static, ()>) {
-		self.spawn_blocking(name, future);
+	fn spawn_blocking(
+		&self,
+		name: &'static str,
+		group: Option<&'static str>,
+		future: BoxFuture<'static, ()>,
+	) {
+		self.spawn_inner(name, group, future, TaskType::Blocking)
 	}
 
-	fn spawn(&self, name: &'static str, future: BoxFuture<'static, ()>) {
-		self.spawn(name, future);
+	fn spawn(
+		&self,
+		name: &'static str,
+		group: Option<&'static str>,
+		future: BoxFuture<'static, ()>,
+	) {
+		self.spawn_inner(name, group, future, TaskType::Async)
 	}
 }
 
@@ -172,8 +195,13 @@ impl SpawnEssentialTaskHandle {
 	/// Spawns the given task with the given name.
 	///
 	/// See also [`SpawnTaskHandle::spawn`].
-	pub fn spawn(&self, name: &'static str, task: impl Future + Send + 'static) {
-		self.spawn_inner(name, task, TaskType::Async)
+	pub fn spawn(
+		&self,
+		name: &'static str,
+		group: Option<&'static str>,
+		task: impl Future + Send + 'static,
+	) {
+		self.spawn_inner(name, group, task, TaskType::Async)
 	}
 
 	/// Spawns the blocking task with the given name.
@@ -182,14 +210,16 @@ impl SpawnEssentialTaskHandle {
 	pub fn spawn_blocking(
 		&self,
 		name: &'static str,
+		group: Option<&'static str>,
 		task: impl Future + Send + 'static,
 	) {
-		self.spawn_inner(name, task, TaskType::Blocking)
+		self.spawn_inner(name, group, task, TaskType::Blocking)
 	}
 
 	fn spawn_inner(
 		&self,
 		name: &'static str,
+		group: Option<&'static str>,
 		task: impl Future + Send + 'static,
 		task_type: TaskType,
 	) {
@@ -199,17 +229,27 @@ impl SpawnEssentialTaskHandle {
 			let _ = essential_failed.close_channel();
 		});
 
-		let _ = self.inner.spawn_inner(name, essential_task, task_type);
+		let _ = self.inner.spawn_inner(name, group, essential_task, task_type);
 	}
 }
 
 impl sp_core::traits::SpawnEssentialNamed for SpawnEssentialTaskHandle {
-	fn spawn_essential_blocking(&self, name: &'static str, future: BoxFuture<'static, ()>) {
-		self.spawn_blocking(name, future);
+	fn spawn_essential_blocking(
+		&self,
+		name: &'static str,
+		group: Option<&'static str>,
+		future: BoxFuture<'static, ()>,
+	) {
+		self.spawn_blocking(name, group, future);
 	}
 
-	fn spawn_essential(&self, name: &'static str, future: BoxFuture<'static, ()>) {
-		self.spawn(name, future);
+	fn spawn_essential(
+		&self,
+		name: &'static str,
+		group: Option<&'static str>,
+		future: BoxFuture<'static, ()>,
+	) {
+		self.spawn(name, group, future);
 	}
 }
 
@@ -396,28 +436,28 @@ impl Metrics {
 					buckets: exponential_buckets(0.001, 4.0, 9)
 						.expect("function parameters are constant and always valid; qed"),
 				},
-				&["task_name"]
+				&["task_name", "task_group"]
 			)?, registry)?,
 			poll_start: register(CounterVec::new(
 				Opts::new(
 					"tasks_polling_started_total",
 					"Total number of times we started invoking Future::poll"
 				),
-				&["task_name"]
+				&["task_name", "task_group"]
 			)?, registry)?,
 			tasks_spawned: register(CounterVec::new(
 				Opts::new(
 					"tasks_spawned_total",
 					"Total number of tasks that have been spawned on the Service"
 				),
-				&["task_name"]
+				&["task_name", "task_group"]
 			)?, registry)?,
 			tasks_ended: register(CounterVec::new(
 				Opts::new(
 					"tasks_ended_total",
 					"Total number of tasks for which Future::poll has returned Ready(()) or panicked"
 				),
-				&["task_name", "reason"]
+				&["task_name", "reason", "task_group"]
 			)?, registry)?,
 		})
 	}
diff --git a/client/service/src/task_manager/tests.rs b/client/service/src/task_manager/tests.rs
index 291d71ebaf03..75092ff2ae62 100644
--- a/client/service/src/task_manager/tests.rs
+++ b/client/service/src/task_manager/tests.rs
@@ -96,8 +96,8 @@ fn ensure_tasks_are_awaited_on_shutdown() {
 	let task_manager = new_task_manager(handle);
 	let spawn_handle = task_manager.spawn_handle();
 	let drop_tester = DropTester::new();
-	spawn_handle.spawn("task1", run_background_task(drop_tester.new_ref()));
-	spawn_handle.spawn("task2", run_background_task(drop_tester.new_ref()));
+	spawn_handle.spawn("task1", None, run_background_task(drop_tester.new_ref()));
+	spawn_handle.spawn("task2", None, run_background_task(drop_tester.new_ref()));
 	assert_eq!(drop_tester, 2);
 	// allow the tasks to even start
 	runtime.block_on(async { tokio::time::sleep(Duration::from_secs(1)).await });
@@ -115,7 +115,7 @@ fn ensure_keep_alive_during_shutdown() {
 	let spawn_handle = task_manager.spawn_handle();
 	let drop_tester = DropTester::new();
 	task_manager.keep_alive(drop_tester.new_ref());
-	spawn_handle.spawn("task1", run_background_task(()));
+	spawn_handle.spawn("task1", None, run_background_task(()));
 	assert_eq!(drop_tester, 1);
 	// allow the tasks to even start
 	runtime.block_on(async { tokio::time::sleep(Duration::from_secs(1)).await });
@@ -134,10 +134,12 @@ fn ensure_blocking_futures_are_awaited_on_shutdown() {
 	let drop_tester = DropTester::new();
 	spawn_handle.spawn(
 		"task1",
+		None,
 		run_background_task_blocking(Duration::from_secs(3), drop_tester.new_ref()),
 	);
 	spawn_handle.spawn(
 		"task2",
+		None,
 		run_background_task_blocking(Duration::from_secs(3), drop_tester.new_ref()),
 	);
 	assert_eq!(drop_tester, 2);
@@ -156,14 +158,14 @@ fn ensure_no_task_can_be_spawn_after_terminate() {
 	let mut task_manager = new_task_manager(handle);
 	let spawn_handle = task_manager.spawn_handle();
 	let drop_tester = DropTester::new();
-	spawn_handle.spawn("task1", run_background_task(drop_tester.new_ref()));
-	spawn_handle.spawn("task2", run_background_task(drop_tester.new_ref()));
+	spawn_handle.spawn("task1", None, run_background_task(drop_tester.new_ref()));
+	spawn_handle.spawn("task2", None, run_background_task(drop_tester.new_ref()));
 	assert_eq!(drop_tester, 2);
 	// allow the tasks to even start
 	runtime.block_on(async { tokio::time::sleep(Duration::from_secs(1)).await });
 	assert_eq!(drop_tester, 2);
 	task_manager.terminate();
-	spawn_handle.spawn("task3", run_background_task(drop_tester.new_ref()));
+	spawn_handle.spawn("task3", None, run_background_task(drop_tester.new_ref()));
 	runtime.block_on(task_manager.clean_shutdown());
 	drop_tester.wait_on_drop();
 }
@@ -176,8 +178,8 @@ fn ensure_task_manager_future_ends_when_task_manager_terminated() {
 	let mut task_manager = new_task_manager(handle);
 	let spawn_handle = task_manager.spawn_handle();
 	let drop_tester = DropTester::new();
-	spawn_handle.spawn("task1", run_background_task(drop_tester.new_ref()));
-	spawn_handle.spawn("task2", run_background_task(drop_tester.new_ref()));
+	spawn_handle.spawn("task1", None, run_background_task(drop_tester.new_ref()));
+	spawn_handle.spawn("task2", None, run_background_task(drop_tester.new_ref()));
 	assert_eq!(drop_tester, 2);
 	// allow the tasks to even start
 	runtime.block_on(async { tokio::time::sleep(Duration::from_secs(1)).await });
@@ -197,13 +199,13 @@ fn ensure_task_manager_future_ends_with_error_when_essential_task_fails() {
 	let spawn_handle = task_manager.spawn_handle();
 	let spawn_essential_handle = task_manager.spawn_essential_handle();
 	let drop_tester = DropTester::new();
-	spawn_handle.spawn("task1", run_background_task(drop_tester.new_ref()));
-	spawn_handle.spawn("task2", run_background_task(drop_tester.new_ref()));
+	spawn_handle.spawn("task1", None, run_background_task(drop_tester.new_ref()));
+	spawn_handle.spawn("task2", None, run_background_task(drop_tester.new_ref()));
 	assert_eq!(drop_tester, 2);
 	// allow the tasks to even start
 	runtime.block_on(async { tokio::time::sleep(Duration::from_secs(1)).await });
 	assert_eq!(drop_tester, 2);
-	spawn_essential_handle.spawn("task3", async { panic!("task failed") });
+	spawn_essential_handle.spawn("task3", None, async { panic!("task failed") });
 	runtime
 		.block_on(task_manager.future())
 		.expect_err("future()'s Result must be Err");
@@ -226,10 +228,10 @@ fn ensure_children_tasks_ends_when_task_manager_terminated() {
 	task_manager.add_child(child_2);
 	let spawn_handle = task_manager.spawn_handle();
 	let drop_tester = DropTester::new();
-	spawn_handle.spawn("task1", run_background_task(drop_tester.new_ref()));
-	spawn_handle.spawn("task2", run_background_task(drop_tester.new_ref()));
-	spawn_handle_child_1.spawn("task3", run_background_task(drop_tester.new_ref()));
-	spawn_handle_child_2.spawn("task4", run_background_task(drop_tester.new_ref()));
+	spawn_handle.spawn("task1", None, run_background_task(drop_tester.new_ref()));
+	spawn_handle.spawn("task2", None, run_background_task(drop_tester.new_ref()));
+	spawn_handle_child_1.spawn("task3", None, run_background_task(drop_tester.new_ref()));
+	spawn_handle_child_2.spawn("task4", None, run_background_task(drop_tester.new_ref()));
 	assert_eq!(drop_tester, 4);
 	// allow the tasks to even start
 	runtime.block_on(async { tokio::time::sleep(Duration::from_secs(1)).await });
@@ -255,15 +257,15 @@ fn ensure_task_manager_future_ends_with_error_when_childs_essential_task_fails()
 	task_manager.add_child(child_2);
 	let spawn_handle = task_manager.spawn_handle();
 	let drop_tester = DropTester::new();
-	spawn_handle.spawn("task1", run_background_task(drop_tester.new_ref()));
-	spawn_handle.spawn("task2", run_background_task(drop_tester.new_ref()));
-	spawn_handle_child_1.spawn("task3", run_background_task(drop_tester.new_ref()));
-	spawn_handle_child_2.spawn("task4", run_background_task(drop_tester.new_ref()));
+	spawn_handle.spawn("task1", None, run_background_task(drop_tester.new_ref()));
+	spawn_handle.spawn("task2", None, run_background_task(drop_tester.new_ref()));
+	spawn_handle_child_1.spawn("task3", None, run_background_task(drop_tester.new_ref()));
+	spawn_handle_child_2.spawn("task4", None, run_background_task(drop_tester.new_ref()));
 	assert_eq!(drop_tester, 4);
 	// allow the tasks to even start
 	runtime.block_on(async { tokio::time::sleep(Duration::from_secs(1)).await });
 	assert_eq!(drop_tester, 4);
-	spawn_essential_handle_child_1.spawn("task5", async { panic!("task failed") });
+	spawn_essential_handle_child_1.spawn("task5", None, async { panic!("task failed") });
 	runtime
 		.block_on(task_manager.future())
 		.expect_err("future()'s Result must be Err");
@@ -286,15 +288,15 @@ fn ensure_task_manager_future_continues_when_childs_not_essential_task_fails() {
 	task_manager.add_child(child_2);
 	let spawn_handle = task_manager.spawn_handle();
 	let drop_tester = DropTester::new();
-	spawn_handle.spawn("task1", run_background_task(drop_tester.new_ref()));
-	spawn_handle.spawn("task2", run_background_task(drop_tester.new_ref()));
-	spawn_handle_child_1.spawn("task3", run_background_task(drop_tester.new_ref()));
-	spawn_handle_child_2.spawn("task4", run_background_task(drop_tester.new_ref()));
+	spawn_handle.spawn("task1", None, run_background_task(drop_tester.new_ref()));
+	spawn_handle.spawn("task2", None, run_background_task(drop_tester.new_ref()));
+	spawn_handle_child_1.spawn("task3", None, run_background_task(drop_tester.new_ref()));
+	spawn_handle_child_2.spawn("task4", None, run_background_task(drop_tester.new_ref()));
 	assert_eq!(drop_tester, 4);
 	// allow the tasks to even start
 	runtime.block_on(async { tokio::time::sleep(Duration::from_secs(1)).await });
 	assert_eq!(drop_tester, 4);
-	spawn_handle_child_1.spawn("task5", async { panic!("task failed") });
+	spawn_handle_child_1.spawn("task5", None, async { panic!("task failed") });
 	runtime.block_on(async {
 		let t1 = task_manager.future().fuse();
 		let t2 = tokio::time::sleep(Duration::from_secs(3)).fuse();
diff --git a/client/transaction-pool/src/api.rs b/client/transaction-pool/src/api.rs
index a735c67d846c..8af0ea98f810 100644
--- a/client/transaction-pool/src/api.rs
+++ b/client/transaction-pool/src/api.rs
@@ -64,6 +64,7 @@ fn spawn_validation_pool_task(
 ) {
 	spawner.spawn_essential_blocking(
 		name,
+		Some("transaction-pool"),
 		async move {
 			loop {
 				let task = receiver.lock().await.next().await;
diff --git a/client/transaction-pool/src/lib.rs b/client/transaction-pool/src/lib.rs
index 8af73c3fe5b4..3565cb52ad87 100644
--- a/client/transaction-pool/src/lib.rs
+++ b/client/transaction-pool/src/lib.rs
@@ -217,7 +217,7 @@ where
 		};
 
 		if let Some(background_task) = background_task {
-			spawner.spawn_essential("txpool-background", background_task);
+			spawner.spawn_essential("txpool-background", Some("transaction-pool"), background_task);
 		}
 
 		Self {
diff --git a/primitives/core/src/testing.rs b/primitives/core/src/testing.rs
index a7fff0def83f..a40a37804c03 100644
--- a/primitives/core/src/testing.rs
+++ b/primitives/core/src/testing.rs
@@ -152,10 +152,20 @@ impl Default for TaskExecutor {
 
 #[cfg(feature = "std")]
 impl crate::traits::SpawnNamed for TaskExecutor {
-	fn spawn_blocking(&self, _: &'static str, future: futures::future::BoxFuture<'static, ()>) {
+	fn spawn_blocking(
+		&self,
+		_name: &'static str,
+		_group: Option<&'static str>,
+		future: futures::future::BoxFuture<'static, ()>,
+	) {
 		self.0.spawn_ok(future);
 	}
-	fn spawn(&self, _: &'static str, future: futures::future::BoxFuture<'static, ()>) {
+	fn spawn(
+		&self,
+		_name: &'static str,
+		_group: Option<&'static str>,
+		future: futures::future::BoxFuture<'static, ()>,
+	) {
 		self.0.spawn_ok(future);
 	}
 }
@@ -165,11 +175,17 @@ impl crate::traits::SpawnEssentialNamed for TaskExecutor {
 	fn spawn_essential_blocking(
 		&self,
 		_: &'static str,
+		_: Option<&'static str>,
 		future: futures::future::BoxFuture<'static, ()>,
 	) {
 		self.0.spawn_ok(future);
 	}
-	fn spawn_essential(&self, _: &'static str, future: futures::future::BoxFuture<'static, ()>) {
+	fn spawn_essential(
+		&self,
+		_: &'static str,
+		_: Option<&'static str>,
+		future: futures::future::BoxFuture<'static, ()>,
+	) {
 		self.0.spawn_ok(future);
 	}
 }
diff --git a/primitives/core/src/traits.rs b/primitives/core/src/traits.rs
index 47639f9d87ba..e3d7d8e283e2 100644
--- a/primitives/core/src/traits.rs
+++ b/primitives/core/src/traits.rs
@@ -190,58 +190,91 @@ sp_externalities::decl_extension! {
 	pub struct RuntimeSpawnExt(Box);
 }
 
-/// Something that can spawn tasks (blocking and non-blocking) with an assigned name.
+/// Something that can spawn tasks (blocking and non-blocking) with an assigned name
+/// and optional group.
 #[dyn_clonable::clonable]
 pub trait SpawnNamed: Clone + Send + Sync {
 	/// Spawn the given blocking future.
 	///
-	/// The given `name` is used to identify the future in tracing.
-	fn spawn_blocking(&self, name: &'static str, future: futures::future::BoxFuture<'static, ()>);
+	/// The given `group` and `name` is used to identify the future in tracing.
+	fn spawn_blocking(
+		&self,
+		name: &'static str,
+		group: Option<&'static str>,
+		future: futures::future::BoxFuture<'static, ()>,
+	);
 	/// Spawn the given non-blocking future.
 	///
-	/// The given `name` is used to identify the future in tracing.
-	fn spawn(&self, name: &'static str, future: futures::future::BoxFuture<'static, ()>);
+	/// The given `group` and `name` is used to identify the future in tracing.
+	fn spawn(
+		&self,
+		name: &'static str,
+		group: Option<&'static str>,
+		future: futures::future::BoxFuture<'static, ()>,
+	);
 }
 
 impl SpawnNamed for Box {
-	fn spawn_blocking(&self, name: &'static str, future: futures::future::BoxFuture<'static, ()>) {
-		(**self).spawn_blocking(name, future)
+	fn spawn_blocking(
+		&self,
+		name: &'static str,
+		group: Option<&'static str>,
+		future: futures::future::BoxFuture<'static, ()>,
+	) {
+		(**self).spawn_blocking(name, group, future)
 	}
-
-	fn spawn(&self, name: &'static str, future: futures::future::BoxFuture<'static, ()>) {
-		(**self).spawn(name, future)
+	fn spawn(
+		&self,
+		name: &'static str,
+		group: Option<&'static str>,
+		future: futures::future::BoxFuture<'static, ()>,
+	) {
+		(**self).spawn(name, group, future)
 	}
 }
 
-/// Something that can spawn essential tasks (blocking and non-blocking) with an assigned name.
+/// Something that can spawn essential tasks (blocking and non-blocking) with an assigned name
+/// and optional group.
 ///
 /// Essential tasks are special tasks that should take down the node when they end.
 #[dyn_clonable::clonable]
 pub trait SpawnEssentialNamed: Clone + Send + Sync {
 	/// Spawn the given blocking future.
 	///
-	/// The given `name` is used to identify the future in tracing.
+	/// The given `group` and `name` is used to identify the future in tracing.
 	fn spawn_essential_blocking(
 		&self,
 		name: &'static str,
+		group: Option<&'static str>,
 		future: futures::future::BoxFuture<'static, ()>,
 	);
 	/// Spawn the given non-blocking future.
 	///
-	/// The given `name` is used to identify the future in tracing.
-	fn spawn_essential(&self, name: &'static str, future: futures::future::BoxFuture<'static, ()>);
+	/// The given `group` and `name` is used to identify the future in tracing.
+	fn spawn_essential(
+		&self,
+		name: &'static str,
+		group: Option<&'static str>,
+		future: futures::future::BoxFuture<'static, ()>,
+	);
 }
 
 impl SpawnEssentialNamed for Box {
 	fn spawn_essential_blocking(
 		&self,
 		name: &'static str,
+		group: Option<&'static str>,
 		future: futures::future::BoxFuture<'static, ()>,
 	) {
-		(**self).spawn_essential_blocking(name, future)
+		(**self).spawn_essential_blocking(name, group, future)
 	}
 
-	fn spawn_essential(&self, name: &'static str, future: futures::future::BoxFuture<'static, ()>) {
-		(**self).spawn_essential(name, future)
+	fn spawn_essential(
+		&self,
+		name: &'static str,
+		group: Option<&'static str>,
+		future: futures::future::BoxFuture<'static, ()>,
+	) {
+		(**self).spawn_essential(name, group, future)
 	}
 }
diff --git a/primitives/io/src/batch_verifier.rs b/primitives/io/src/batch_verifier.rs
index b6da1d85907b..05c8a63694eb 100644
--- a/primitives/io/src/batch_verifier.rs
+++ b/primitives/io/src/batch_verifier.rs
@@ -74,6 +74,7 @@ impl BatchVerifier {
 
 		self.scheduler.spawn(
 			name,
+			None,
 			async move {
 				if !f() {
 					invalid_clone.store(true, AtomicOrdering::Relaxed);
@@ -177,7 +178,8 @@ impl BatchVerifier {
 		if pending.len() > 0 {
 			let (sender, receiver) = std::sync::mpsc::channel();
 			self.scheduler.spawn(
-				"substrate_batch_verify_join",
+				"substrate-batch-verify-join",
+				None,
 				async move {
 					futures::future::join_all(pending).await;
 					sender.send(()).expect(
diff --git a/primitives/tasks/src/lib.rs b/primitives/tasks/src/lib.rs
index e9c80ae5ff4c..c874bb98e1ae 100644
--- a/primitives/tasks/src/lib.rs
+++ b/primitives/tasks/src/lib.rs
@@ -95,6 +95,7 @@ mod inner {
 		let extra_scheduler = scheduler.clone();
 		scheduler.spawn(
 			"parallel-runtime-spawn",
+			Some("substrate-runtime"),
 			Box::pin(async move {
 				let result = match crate::new_async_externalities(extra_scheduler) {
 					Ok(mut ext) => {
diff --git a/test-utils/test-runner/src/client.rs b/test-utils/test-runner/src/client.rs
index 58c4cf6503a9..27c04c40fe6f 100644
--- a/test-utils/test-runner/src/client.rs
+++ b/test-utils/test-runner/src/client.rs
@@ -235,7 +235,9 @@ where
 	});
 
 	// spawn the authorship task as an essential task.
-	task_manager.spawn_essential_handle().spawn("manual-seal", authorship_future);
+	task_manager
+		.spawn_essential_handle()
+		.spawn("manual-seal", None, authorship_future);
 
 	network_starter.start_network();
 	let rpc_handler = rpc_handlers.io_handler();

From dc899259640256c0c545b262dd3388b126d52b01 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 11 Nov 2021 19:43:04 +0100
Subject: [PATCH 172/695] Bump git2 from 0.13.22 to 0.13.23 (#10238)

Bumps [git2](https://github.com/rust-lang/git2-rs) from 0.13.22 to 0.13.23.
- [Release notes](https://github.com/rust-lang/git2-rs/releases)
- [Commits](https://github.com/rust-lang/git2-rs/compare/0.13.22...0.13.23)

---
updated-dependencies:
- dependency-name: git2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] 

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 Cargo.lock                           | 8 ++++----
 utils/frame/generate-bags/Cargo.toml | 2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 423ec1de4e7d..5d0251bca631 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2479,9 +2479,9 @@ dependencies = [
 
 [[package]]
 name = "git2"
-version = "0.13.22"
+version = "0.13.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c1cbbfc9a1996c6af82c2b4caf828d2c653af4fcdbb0e5674cc966eee5a4197"
+checksum = "2a8057932925d3a9d9e4434ea016570d37420ddb1ceed45a174d577f24ed6700"
 dependencies = [
  "bitflags",
  "libc",
@@ -3313,9 +3313,9 @@ checksum = "869d572136620d55835903746bcb5cdc54cb2851fd0aeec53220b4bb65ef3013"
 
 [[package]]
 name = "libgit2-sys"
-version = "0.12.23+1.2.0"
+version = "0.12.24+1.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "29730a445bae719db3107078b46808cc45a5b7a6bae3f31272923af969453356"
+checksum = "ddbd6021eef06fb289a8f54b3c2acfdd85ff2a585dfbb24b8576325373d2152c"
 dependencies = [
  "cc",
  "libc",
diff --git a/utils/frame/generate-bags/Cargo.toml b/utils/frame/generate-bags/Cargo.toml
index 225584b69069..4bc27021b4c5 100644
--- a/utils/frame/generate-bags/Cargo.toml
+++ b/utils/frame/generate-bags/Cargo.toml
@@ -21,6 +21,6 @@ sp-io = { version = "4.0.0-dev", path = "../../../primitives/io" }
 
 # third party
 chrono = { version = "0.4.19" }
-git2 = { version = "0.13.20", default-features = false }
+git2 = { version = "0.13.23", default-features = false }
 num-format = { version = "0.4.0" }
 structopt = "0.3.21"

From e5abe5566e5a76b3deb9b6c2766e88d32ac07eb0 Mon Sep 17 00:00:00 2001
From: Guillaume Thiolliere 
Date: Thu, 11 Nov 2021 23:53:43 +0100
Subject: [PATCH 173/695] Warn about usage of pallet collective set members
 call. (#10156)

* warn

* Apply suggestions from code review

Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* fmt

Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>
---
 frame/collective/src/lib.rs | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/frame/collective/src/lib.rs b/frame/collective/src/lib.rs
index 89d4c8a150c3..2797d01ffcdb 100644
--- a/frame/collective/src/lib.rs
+++ b/frame/collective/src/lib.rs
@@ -345,6 +345,13 @@ pub mod pallet {
 		/// NOTE: Does not enforce the expected `MaxMembers` limit on the amount of members, but
 		///       the weight estimations rely on it to estimate dispatchable weight.
 		///
+		/// # WARNING:
+		///
+		/// The `pallet-collective` can also be managed by logic outside of the pallet through the
+		/// implementation of the trait [`ChangeMembers`].
+		/// Any call to `set_members` must be careful that the member set doesn't get out of sync
+		/// with other logic managing the member set.
+		///
 		/// # 
 		/// ## Weight
 		/// - `O(MP + N)` where:

From 2208ac43327d4869b3fd3fcfa44eb1a9ba11bb01 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 11 Nov 2021 23:32:27 +0000
Subject: [PATCH 174/695] Bump thiserror from 1.0.26 to 1.0.30 (#10240)

Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.26 to 1.0.30.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.26...1.0.30)

---
updated-dependencies:
- dependency-name: thiserror
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] 

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 Cargo.lock                             | 8 ++++----
 client/allocator/Cargo.toml            | 2 +-
 client/api/Cargo.toml                  | 2 +-
 client/cli/Cargo.toml                  | 2 +-
 client/consensus/common/Cargo.toml     | 2 +-
 client/consensus/slots/Cargo.toml      | 2 +-
 client/consensus/uncles/Cargo.toml     | 2 +-
 client/executor/common/Cargo.toml      | 2 +-
 client/service/Cargo.toml              | 2 +-
 client/sync-state-rpc/Cargo.toml       | 2 +-
 client/telemetry/Cargo.toml            | 2 +-
 client/tracing/Cargo.toml              | 2 +-
 client/transaction-pool/Cargo.toml     | 2 +-
 client/transaction-pool/api/Cargo.toml | 2 +-
 primitives/api/Cargo.toml              | 2 +-
 primitives/blockchain/Cargo.toml       | 2 +-
 primitives/consensus/common/Cargo.toml | 2 +-
 primitives/core/Cargo.toml             | 2 +-
 primitives/inherents/Cargo.toml        | 2 +-
 primitives/state-machine/Cargo.toml    | 2 +-
 primitives/timestamp/Cargo.toml        | 2 +-
 primitives/version/Cargo.toml          | 2 +-
 22 files changed, 25 insertions(+), 25 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 5d0251bca631..5d2fa99ca55a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -10461,18 +10461,18 @@ dependencies = [
 
 [[package]]
 name = "thiserror"
-version = "1.0.26"
+version = "1.0.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93119e4feac1cbe6c798c34d3a53ea0026b0b1de6a120deef895137c0529bfe2"
+checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
 dependencies = [
  "thiserror-impl",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.26"
+version = "1.0.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "060d69a0afe7796bf42e9e2ff91f5ee691fb15c53d38b4b62a9a53eb23164745"
+checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
 dependencies = [
  "proc-macro2",
  "quote",
diff --git a/client/allocator/Cargo.toml b/client/allocator/Cargo.toml
index 6d324b09acde..44facf0ad889 100644
--- a/client/allocator/Cargo.toml
+++ b/client/allocator/Cargo.toml
@@ -17,4 +17,4 @@ targets = ["x86_64-unknown-linux-gnu"]
 sp-core = { version = "4.0.0-dev", path = "../../primitives/core" }
 sp-wasm-interface = { version = "4.0.0-dev", path = "../../primitives/wasm-interface" }
 log = "0.4.11"
-thiserror = "1.0.21"
+thiserror = "1.0.30"
diff --git a/client/api/Cargo.toml b/client/api/Cargo.toml
index 431d6e2fb015..39fe804a1415 100644
--- a/client/api/Cargo.toml
+++ b/client/api/Cargo.toml
@@ -41,4 +41,4 @@ prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.
 [dev-dependencies]
 sp-test-primitives = { version = "2.0.0", path = "../../primitives/test-primitives" }
 substrate-test-runtime = { version = "2.0.0", path = "../../test-utils/runtime" }
-thiserror = "1.0.21"
+thiserror = "1.0.30"
diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml
index 6107206be34e..9dc7ff730600 100644
--- a/client/cli/Cargo.toml
+++ b/client/cli/Cargo.toml
@@ -42,7 +42,7 @@ structopt = "0.3.8"
 sc-tracing = { version = "4.0.0-dev", path = "../tracing" }
 chrono = "0.4.10"
 serde = "1.0.126"
-thiserror = "1.0.21"
+thiserror = "1.0.30"
 rpassword = "5.0.0"
 
 [dev-dependencies]
diff --git a/client/consensus/common/Cargo.toml b/client/consensus/common/Cargo.toml
index 3f8380d3f81b..c26e250edf24 100644
--- a/client/consensus/common/Cargo.toml
+++ b/client/consensus/common/Cargo.toml
@@ -13,7 +13,7 @@ readme = "README.md"
 targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
-thiserror = "1.0.21"
+thiserror = "1.0.30"
 libp2p = { version = "0.39.1", default-features = false }
 log = "0.4.8"
 futures = { version = "0.3.1", features = ["thread-pool"] }
diff --git a/client/consensus/slots/Cargo.toml b/client/consensus/slots/Cargo.toml
index 5c5f1bdfa68c..ff4fdf041b4f 100644
--- a/client/consensus/slots/Cargo.toml
+++ b/client/consensus/slots/Cargo.toml
@@ -31,7 +31,7 @@ sp-timestamp = { version = "4.0.0-dev", path = "../../../primitives/timestamp" }
 futures = "0.3.9"
 futures-timer = "3.0.1"
 log = "0.4.11"
-thiserror = "1.0.21"
+thiserror = "1.0.30"
 async-trait = "0.1.50"
 
 [dev-dependencies]
diff --git a/client/consensus/uncles/Cargo.toml b/client/consensus/uncles/Cargo.toml
index f644d64c7bbe..bc5f1f25838c 100644
--- a/client/consensus/uncles/Cargo.toml
+++ b/client/consensus/uncles/Cargo.toml
@@ -16,4 +16,4 @@ targets = ["x86_64-unknown-linux-gnu"]
 sc-client-api = { version = "4.0.0-dev", path = "../../api" }
 sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" }
 sp-authorship = { version = "4.0.0-dev", path = "../../../primitives/authorship" }
-thiserror = "1.0.21"
+thiserror = "1.0.30"
diff --git a/client/executor/common/Cargo.toml b/client/executor/common/Cargo.toml
index 2d9f4672768e..276fe9a8380b 100644
--- a/client/executor/common/Cargo.toml
+++ b/client/executor/common/Cargo.toml
@@ -23,7 +23,7 @@ sc-allocator = { version = "4.1.0-dev", path = "../../allocator" }
 sp-wasm-interface = { version = "4.0.0-dev", path = "../../../primitives/wasm-interface" }
 sp-maybe-compressed-blob = { version = "4.1.0-dev", path = "../../../primitives/maybe-compressed-blob" }
 sp-serializer = { version = "4.0.0-dev", path = "../../../primitives/serializer" }
-thiserror = "1.0.21"
+thiserror = "1.0.30"
 environmental = "1.1.3"
 
 wasmer = { version = "1.0", optional = true }
diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml
index c090495fe04e..38729fd4ba5c 100644
--- a/client/service/Cargo.toml
+++ b/client/service/Cargo.toml
@@ -22,7 +22,7 @@ wasmtime = ["sc-executor/wasmtime"]
 test-helpers = []
 
 [dependencies]
-thiserror = "1.0.21"
+thiserror = "1.0.30"
 futures = "0.3.16"
 jsonrpc-pubsub = "18.0"
 jsonrpc-core = "18.0"
diff --git a/client/sync-state-rpc/Cargo.toml b/client/sync-state-rpc/Cargo.toml
index a9503b992ab3..6d8d95954629 100644
--- a/client/sync-state-rpc/Cargo.toml
+++ b/client/sync-state-rpc/Cargo.toml
@@ -13,7 +13,7 @@ readme = "README.md"
 targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
-thiserror = "1.0.21"
+thiserror = "1.0.30"
 jsonrpc-core = "18.0.0"
 jsonrpc-core-client = "18.0.0"
 jsonrpc-derive = "18.0.0"
diff --git a/client/telemetry/Cargo.toml b/client/telemetry/Cargo.toml
index 5a25aca29b60..744a0610a07e 100644
--- a/client/telemetry/Cargo.toml
+++ b/client/telemetry/Cargo.toml
@@ -25,4 +25,4 @@ rand = "0.7.2"
 serde = { version = "1.0.126", features = ["derive"] }
 serde_json = "1.0.68"
 chrono = "0.4.19"
-thiserror = "1.0.21"
+thiserror = "1.0.30"
diff --git a/client/tracing/Cargo.toml b/client/tracing/Cargo.toml
index 8640208ad342..6a969b33deb1 100644
--- a/client/tracing/Cargo.toml
+++ b/client/tracing/Cargo.toml
@@ -24,7 +24,7 @@ parking_lot = "0.11.1"
 regex = "1.5.4"
 rustc-hash = "1.1.0"
 serde = "1.0.126"
-thiserror = "1.0.21"
+thiserror = "1.0.30"
 tracing = "0.1.29"
 tracing-log = "0.1.2"
 tracing-subscriber = { version = "0.2.25", features = ["parking_lot"] }
diff --git a/client/transaction-pool/Cargo.toml b/client/transaction-pool/Cargo.toml
index d26969cf1e09..3d2a450c4101 100644
--- a/client/transaction-pool/Cargo.toml
+++ b/client/transaction-pool/Cargo.toml
@@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.0.0" }
-thiserror = "1.0.21"
+thiserror = "1.0.30"
 futures = "0.3.16"
 intervalier = "0.4.0"
 log = "0.4.8"
diff --git a/client/transaction-pool/api/Cargo.toml b/client/transaction-pool/api/Cargo.toml
index 176624611fbf..1ab1ef5bb4a1 100644
--- a/client/transaction-pool/api/Cargo.toml
+++ b/client/transaction-pool/api/Cargo.toml
@@ -12,7 +12,7 @@ description = "Transaction pool client facing API."
 futures = { version = "0.3.1"  }
 log = { version = "0.4.8" }
 serde = { version = "1.0.126", features = ["derive"] }
-thiserror = { version = "1.0.21" }
+thiserror = { version = "1.0.30" }
 sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" }
 
 derive_more = { version = "0.99.11" }
diff --git a/primitives/api/Cargo.toml b/primitives/api/Cargo.toml
index 65da54b87753..5723f9cf11b5 100644
--- a/primitives/api/Cargo.toml
+++ b/primitives/api/Cargo.toml
@@ -21,7 +21,7 @@ sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../runti
 sp-version = { version = "4.0.0-dev", default-features = false, path = "../version" }
 sp-state-machine = { version = "0.10.0-dev", optional = true, path = "../state-machine" }
 hash-db = { version = "0.15.2", optional = true }
-thiserror = { version = "1.0.21", optional = true }
+thiserror = { version = "1.0.30", optional = true }
 
 log = { version = "0.4.14", default-features = false }
 
diff --git a/primitives/blockchain/Cargo.toml b/primitives/blockchain/Cargo.toml
index de73af10966e..02e74a63d959 100644
--- a/primitives/blockchain/Cargo.toml
+++ b/primitives/blockchain/Cargo.toml
@@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 log = "0.4.11"
 lru = "0.7.0"
 parking_lot = "0.11.1"
-thiserror = "1.0.21"
+thiserror = "1.0.30"
 futures = "0.3.9"
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
 sp-consensus = { version = "0.10.0-dev", path = "../consensus/common" }
diff --git a/primitives/consensus/common/Cargo.toml b/primitives/consensus/common/Cargo.toml
index 735b1e8eb095..08e50a954288 100644
--- a/primitives/consensus/common/Cargo.toml
+++ b/primitives/consensus/common/Cargo.toml
@@ -27,7 +27,7 @@ futures-timer = "3.0.1"
 sp-std = { version = "4.0.0-dev", path = "../../std" }
 sp-version = { version = "4.0.0-dev", path = "../../version" }
 sp-runtime = { version = "4.0.0-dev", path = "../../runtime" }
-thiserror = "1.0.21"
+thiserror = "1.0.30"
 
 [dev-dependencies]
 futures = "0.3.9"
diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml
index 48749904763f..eaf1d26c2898 100644
--- a/primitives/core/Cargo.toml
+++ b/primitives/core/Cargo.toml
@@ -48,7 +48,7 @@ parity-util-mem = { version = "0.10.2", default-features = false, features = [
 ] }
 futures = { version = "0.3.1", optional = true }
 dyn-clonable = { version = "0.9.0", optional = true }
-thiserror = { version = "1.0.21", optional = true }
+thiserror = { version = "1.0.30", optional = true }
 bitflags = "1.3"
 
 # full crypto
diff --git a/primitives/inherents/Cargo.toml b/primitives/inherents/Cargo.toml
index d52140d94ed3..3efd6ab03213 100644
--- a/primitives/inherents/Cargo.toml
+++ b/primitives/inherents/Cargo.toml
@@ -19,7 +19,7 @@ sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" }
 sp-core = { version = "4.0.0-dev", default-features = false, path = "../core" }
 sp-runtime = { version = "4.0.0-dev", path = "../runtime", optional = true }
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
-thiserror = { version = "1.0.21", optional = true }
+thiserror = { version = "1.0.30", optional = true }
 impl-trait-for-tuples = "0.2.0"
 async-trait = { version = "0.1.50", optional = true }
 
diff --git a/primitives/state-machine/Cargo.toml b/primitives/state-machine/Cargo.toml
index c919d7fbef6a..783837a6442b 100644
--- a/primitives/state-machine/Cargo.toml
+++ b/primitives/state-machine/Cargo.toml
@@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 log = { version = "0.4.11", optional = true }
-thiserror = { version = "1.0.21", optional = true }
+thiserror = { version = "1.0.30", optional = true }
 parking_lot = { version = "0.11.1", optional = true }
 hash-db = { version = "0.15.2", default-features = false }
 trie-db = { version = "0.22.6", default-features = false }
diff --git a/primitives/timestamp/Cargo.toml b/primitives/timestamp/Cargo.toml
index 552a3cb5e8d6..609ecd0d3192 100644
--- a/primitives/timestamp/Cargo.toml
+++ b/primitives/timestamp/Cargo.toml
@@ -18,7 +18,7 @@ sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" }
 sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../runtime" }
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
 sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../inherents" }
-thiserror = { version = "1.0.21", optional = true }
+thiserror = { version = "1.0.30", optional = true }
 log = { version = "0.4.8", optional = true }
 futures-timer = { version = "3.0.2", optional = true }
 async-trait = { version = "0.1.50", optional = true }
diff --git a/primitives/version/Cargo.toml b/primitives/version/Cargo.toml
index af44aed6c5b2..bbdaf9c1cab1 100644
--- a/primitives/version/Cargo.toml
+++ b/primitives/version/Cargo.toml
@@ -23,7 +23,7 @@ sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" }
 sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../runtime" }
 sp-version-proc-macro = { version = "4.0.0-dev", default-features = false, path = "proc-macro" }
 parity-wasm = { version = "0.42.2", optional = true }
-thiserror = { version = "1.0.21", optional = true }
+thiserror = { version = "1.0.30", optional = true }
 
 [features]
 default = ["std"]

From 5d22361ebbd9b5ccafd87f3f50d2646ad59b6c0b Mon Sep 17 00:00:00 2001
From: Doordashcon <90750465+Doordashcon@users.noreply.github.com>
Date: Fri, 12 Nov 2021 00:48:37 +0100
Subject: [PATCH 175/695] tuple to struct event variants (#10206)

* update sudo pallet

* Update mock.rs

* cargo +nightly fmt

* frame-support remote-externalities

* AFNPEV tips

* AFNPEV bin & update sudo

* cargo +nightly fmt

* optional dependency remote-test feature

* fmt

Co-authored-by: Shawn Tabrizi 
---
 bin/node/executor/tests/fees.rs             |  9 ++++--
 frame/sudo/src/lib.rs                       | 16 +++++----
 frame/sudo/src/mock.rs                      |  8 ++---
 frame/sudo/src/tests.rs                     | 10 +++---
 frame/tips/src/lib.rs                       | 36 ++++++++++++---------
 frame/tips/src/tests.rs                     | 10 +++---
 utils/frame/remote-externalities/Cargo.toml |  3 +-
 7 files changed, 51 insertions(+), 41 deletions(-)

diff --git a/bin/node/executor/tests/fees.rs b/bin/node/executor/tests/fees.rs
index 379cdda5b76a..4c7593bdb3ab 100644
--- a/bin/node/executor/tests/fees.rs
+++ b/bin/node/executor/tests/fees.rs
@@ -241,7 +241,10 @@ fn block_weight_capacity_report() {
 		let mut xts = (0..num_transfers)
 			.map(|i| CheckedExtrinsic {
 				signed: Some((charlie(), signed_extra(nonce + i as Index, 0))),
-				function: Call::Balances(pallet_balances::Call::transfer(bob().into(), 0)),
+				function: Call::Balances(pallet_balances::Call::transfer {
+					dest: bob().into(),
+					value: 0,
+				}),
 			})
 			.collect::>();
 
@@ -249,7 +252,7 @@ fn block_weight_capacity_report() {
 			0,
 			CheckedExtrinsic {
 				signed: None,
-				function: Call::Timestamp(pallet_timestamp::Call::set(time * 1000)),
+				function: Call::Timestamp(pallet_timestamp::Call::set { now: time * 1000 }),
 			},
 		);
 
@@ -319,7 +322,7 @@ fn block_length_capacity_report() {
 			vec![
 				CheckedExtrinsic {
 					signed: None,
-					function: Call::Timestamp(pallet_timestamp::Call::set(time * 1000)),
+					function: Call::Timestamp(pallet_timestamp::Call::set { now: time * 1000 }),
 				},
 				CheckedExtrinsic {
 					signed: Some((charlie(), signed_extra(nonce, 0))),
diff --git a/frame/sudo/src/lib.rs b/frame/sudo/src/lib.rs
index 427455849bb0..5f8e6fc0cc13 100644
--- a/frame/sudo/src/lib.rs
+++ b/frame/sudo/src/lib.rs
@@ -150,7 +150,7 @@ pub mod pallet {
 			ensure!(sender == Self::key(), Error::::RequireSudo);
 
 			let res = call.dispatch_bypass_filter(frame_system::RawOrigin::Root.into());
-			Self::deposit_event(Event::Sudid(res.map(|_| ()).map_err(|e| e.error)));
+			Self::deposit_event(Event::Sudid { sudo_result: res.map(|_| ()).map_err(|e| e.error) });
 			// Sudo user does not pay a fee.
 			Ok(Pays::No.into())
 		}
@@ -176,7 +176,7 @@ pub mod pallet {
 			ensure!(sender == Self::key(), Error::::RequireSudo);
 
 			let res = call.dispatch_bypass_filter(frame_system::RawOrigin::Root.into());
-			Self::deposit_event(Event::Sudid(res.map(|_| ()).map_err(|e| e.error)));
+			Self::deposit_event(Event::Sudid { sudo_result: res.map(|_| ()).map_err(|e| e.error) });
 			// Sudo user does not pay a fee.
 			Ok(Pays::No.into())
 		}
@@ -201,7 +201,7 @@ pub mod pallet {
 			ensure!(sender == Self::key(), Error::::RequireSudo);
 			let new = T::Lookup::lookup(new)?;
 
-			Self::deposit_event(Event::KeyChanged(Self::key()));
+			Self::deposit_event(Event::KeyChanged { new_sudoer: Self::key() });
 			>::put(new);
 			// Sudo user does not pay a fee.
 			Ok(Pays::No.into())
@@ -241,7 +241,9 @@ pub mod pallet {
 
 			let res = call.dispatch_bypass_filter(frame_system::RawOrigin::Signed(who).into());
 
-			Self::deposit_event(Event::SudoAsDone(res.map(|_| ()).map_err(|e| e.error)));
+			Self::deposit_event(Event::SudoAsDone {
+				sudo_result: res.map(|_| ()).map_err(|e| e.error),
+			});
 			// Sudo user does not pay a fee.
 			Ok(Pays::No.into())
 		}
@@ -251,11 +253,11 @@ pub mod pallet {
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
 	pub enum Event {
 		/// A sudo just took place. \[result\]
-		Sudid(DispatchResult),
+		Sudid { sudo_result: DispatchResult },
 		/// The \[sudoer\] just switched identity; the old key is supplied.
-		KeyChanged(T::AccountId),
+		KeyChanged { new_sudoer: T::AccountId },
 		/// A sudo just took place. \[result\]
-		SudoAsDone(DispatchResult),
+		SudoAsDone { sudo_result: DispatchResult },
 	}
 
 	#[pallet::error]
diff --git a/frame/sudo/src/mock.rs b/frame/sudo/src/mock.rs
index dad17384d560..bfbed0d38ab3 100644
--- a/frame/sudo/src/mock.rs
+++ b/frame/sudo/src/mock.rs
@@ -58,7 +58,7 @@ pub mod logger {
 			// Ensure that the `origin` is `Root`.
 			ensure_root(origin)?;
 			>::append(i);
-			Self::deposit_event(Event::AppendI32(i, weight));
+			Self::deposit_event(Event::AppendI32 { value: i, weight });
 			Ok(().into())
 		}
 
@@ -72,7 +72,7 @@ pub mod logger {
 			let sender = ensure_signed(origin)?;
 			>::append(i);
 			>::append(sender.clone());
-			Self::deposit_event(Event::AppendI32AndAccount(sender, i, weight));
+			Self::deposit_event(Event::AppendI32AndAccount { sender, value: i, weight });
 			Ok(().into())
 		}
 	}
@@ -80,8 +80,8 @@ pub mod logger {
 	#[pallet::event]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
 	pub enum Event {
-		AppendI32(i32, Weight),
-		AppendI32AndAccount(T::AccountId, i32, Weight),
+		AppendI32 { value: i32, weight: Weight },
+		AppendI32AndAccount { sender: T::AccountId, value: i32, weight: Weight },
 	}
 
 	#[pallet::storage]
diff --git a/frame/sudo/src/tests.rs b/frame/sudo/src/tests.rs
index 2eb558e9471c..3fd199a1c8ca 100644
--- a/frame/sudo/src/tests.rs
+++ b/frame/sudo/src/tests.rs
@@ -58,7 +58,7 @@ fn sudo_emits_events_correctly() {
 		// Should emit event to indicate success when called with the root `key` and `call` is `Ok`.
 		let call = Box::new(Call::Logger(LoggerCall::privileged_i32_log { i: 42, weight: 1 }));
 		assert_ok!(Sudo::sudo(Origin::signed(1), call));
-		System::assert_has_event(TestEvent::Sudo(Event::Sudid(Ok(()))));
+		System::assert_has_event(TestEvent::Sudo(Event::Sudid { sudo_result: Ok(()) }));
 	})
 }
 
@@ -96,7 +96,7 @@ fn sudo_unchecked_weight_emits_events_correctly() {
 		// Should emit event to indicate success when called with the root `key` and `call` is `Ok`.
 		let call = Box::new(Call::Logger(LoggerCall::privileged_i32_log { i: 42, weight: 1 }));
 		assert_ok!(Sudo::sudo_unchecked_weight(Origin::signed(1), call, 1_000));
-		System::assert_has_event(TestEvent::Sudo(Event::Sudid(Ok(()))));
+		System::assert_has_event(TestEvent::Sudo(Event::Sudid { sudo_result: Ok(()) }));
 	})
 }
 
@@ -123,10 +123,10 @@ fn set_key_emits_events_correctly() {
 
 		// A root `key` can change the root `key`.
 		assert_ok!(Sudo::set_key(Origin::signed(1), 2));
-		System::assert_has_event(TestEvent::Sudo(Event::KeyChanged(1)));
+		System::assert_has_event(TestEvent::Sudo(Event::KeyChanged { new_sudoer: 1 }));
 		// Double check.
 		assert_ok!(Sudo::set_key(Origin::signed(2), 4));
-		System::assert_has_event(TestEvent::Sudo(Event::KeyChanged(2)));
+		System::assert_has_event(TestEvent::Sudo(Event::KeyChanged { new_sudoer: 2 }));
 	});
 }
 
@@ -161,6 +161,6 @@ fn sudo_as_emits_events_correctly() {
 		// A non-privileged function will work when passed to `sudo_as` with the root `key`.
 		let call = Box::new(Call::Logger(LoggerCall::non_privileged_log { i: 42, weight: 1 }));
 		assert_ok!(Sudo::sudo_as(Origin::signed(1), 2, call));
-		System::assert_has_event(TestEvent::Sudo(Event::SudoAsDone(Ok(()))));
+		System::assert_has_event(TestEvent::Sudo(Event::SudoAsDone { sudo_result: Ok(()) }));
 	});
 }
diff --git a/frame/tips/src/lib.rs b/frame/tips/src/lib.rs
index f4a4edb7b399..5aad9af34660 100644
--- a/frame/tips/src/lib.rs
+++ b/frame/tips/src/lib.rs
@@ -179,16 +179,16 @@ pub mod pallet {
 	#[pallet::event]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
 	pub enum Event {
-		/// A new tip suggestion has been opened. \[tip_hash\]
-		NewTip(T::Hash),
-		/// A tip suggestion has reached threshold and is closing. \[tip_hash\]
-		TipClosing(T::Hash),
-		/// A tip suggestion has been closed. \[tip_hash, who, payout\]
-		TipClosed(T::Hash, T::AccountId, BalanceOf),
-		/// A tip suggestion has been retracted. \[tip_hash\]
-		TipRetracted(T::Hash),
-		/// A tip suggestion has been slashed. \[tip_hash, finder, deposit\]
-		TipSlashed(T::Hash, T::AccountId, BalanceOf),
+		/// A new tip suggestion has been opened.
+		NewTip { tip_hash: T::Hash },
+		/// A tip suggestion has reached threshold and is closing.
+		TipClosing { tip_hash: T::Hash },
+		/// A tip suggestion has been closed.
+		TipClosed { tip_hash: T::Hash, who: T::AccountId, payout: BalanceOf },
+		/// A tip suggestion has been retracted.
+		TipRetracted { tip_hash: T::Hash },
+		/// A tip suggestion has been slashed.
+		TipSlashed { tip_hash: T::Hash, finder: T::AccountId, deposit: BalanceOf },
 	}
 
 	/// Old name generated by `decl_event`.
@@ -265,7 +265,7 @@ pub mod pallet {
 				finders_fee: true,
 			};
 			Tips::::insert(&hash, tip);
-			Self::deposit_event(Event::NewTip(hash));
+			Self::deposit_event(Event::NewTip { tip_hash: hash });
 			Ok(())
 		}
 
@@ -300,7 +300,7 @@ pub mod pallet {
 				let err_amount = T::Currency::unreserve(&who, tip.deposit);
 				debug_assert!(err_amount.is_zero());
 			}
-			Self::deposit_event(Event::TipRetracted(hash));
+			Self::deposit_event(Event::TipRetracted { tip_hash: hash });
 			Ok(())
 		}
 
@@ -340,7 +340,7 @@ pub mod pallet {
 			let hash = T::Hashing::hash_of(&(&reason_hash, &who));
 
 			Reasons::::insert(&reason_hash, &reason);
-			Self::deposit_event(Event::NewTip(hash.clone()));
+			Self::deposit_event(Event::NewTip { tip_hash: hash.clone() });
 			let tips = vec![(tipper.clone(), tip_value)];
 			let tip = OpenTip {
 				reason: reason_hash,
@@ -390,7 +390,7 @@ pub mod pallet {
 
 			let mut tip = Tips::::get(hash).ok_or(Error::::UnknownTip)?;
 			if Self::insert_tip_and_check_closing(&mut tip, tipper, tip_value) {
-				Self::deposit_event(Event::TipClosing(hash.clone()));
+				Self::deposit_event(Event::TipClosing { tip_hash: hash.clone() });
 			}
 			Tips::::insert(&hash, tip);
 			Ok(())
@@ -449,7 +449,11 @@ pub mod pallet {
 				T::OnSlash::on_unbalanced(imbalance);
 			}
 			Reasons::::remove(&tip.reason);
-			Self::deposit_event(Event::TipSlashed(hash, tip.finder, tip.deposit));
+			Self::deposit_event(Event::TipSlashed {
+				tip_hash: hash,
+				finder: tip.finder,
+				deposit: tip.deposit,
+			});
 			Ok(())
 		}
 	}
@@ -544,7 +548,7 @@ impl Pallet {
 		// same as above: best-effort only.
 		let res = T::Currency::transfer(&treasury, &tip.who, payout, KeepAlive);
 		debug_assert!(res.is_ok());
-		Self::deposit_event(Event::TipClosed(hash, tip.who, payout));
+		Self::deposit_event(Event::TipClosed { tip_hash: hash, who: tip.who, payout });
 	}
 
 	pub fn migrate_retract_tip_for_tip_new(module: &[u8], item: &[u8]) {
diff --git a/frame/tips/src/tests.rs b/frame/tips/src/tests.rs
index 7ea80d78c553..2aac22ffe18c 100644
--- a/frame/tips/src/tests.rs
+++ b/frame/tips/src/tests.rs
@@ -267,7 +267,7 @@ fn close_tip_works() {
 
 		let h = tip_hash();
 
-		assert_eq!(last_event(), TipEvent::NewTip(h));
+		assert_eq!(last_event(), TipEvent::NewTip { tip_hash: h });
 
 		assert_ok!(Tips::tip(Origin::signed(11), h.clone(), 10));
 
@@ -275,7 +275,7 @@ fn close_tip_works() {
 
 		assert_ok!(Tips::tip(Origin::signed(12), h.clone(), 10));
 
-		assert_eq!(last_event(), TipEvent::TipClosing(h));
+		assert_eq!(last_event(), TipEvent::TipClosing { tip_hash: h });
 
 		assert_noop!(Tips::close_tip(Origin::signed(0), h.into()), Error::::Premature);
 
@@ -284,7 +284,7 @@ fn close_tip_works() {
 		assert_ok!(Tips::close_tip(Origin::signed(0), h.into()));
 		assert_eq!(Balances::free_balance(3), 10);
 
-		assert_eq!(last_event(), TipEvent::TipClosed(h, 3, 10));
+		assert_eq!(last_event(), TipEvent::TipClosed { tip_hash: h, who: 3, payout: 10 });
 
 		assert_noop!(Tips::close_tip(Origin::signed(100), h.into()), Error::::UnknownTip);
 	});
@@ -306,14 +306,14 @@ fn slash_tip_works() {
 		assert_eq!(Balances::free_balance(0), 88);
 
 		let h = tip_hash();
-		assert_eq!(last_event(), TipEvent::NewTip(h));
+		assert_eq!(last_event(), TipEvent::NewTip { tip_hash: h });
 
 		// can't remove from any origin
 		assert_noop!(Tips::slash_tip(Origin::signed(0), h.clone()), BadOrigin);
 
 		// can remove from root.
 		assert_ok!(Tips::slash_tip(Origin::root(), h.clone()));
-		assert_eq!(last_event(), TipEvent::TipSlashed(h, 0, 12));
+		assert_eq!(last_event(), TipEvent::TipSlashed { tip_hash: h, finder: 0, deposit: 12 });
 
 		// tipper slashed
 		assert_eq!(Balances::reserved_balance(0), 0);
diff --git a/utils/frame/remote-externalities/Cargo.toml b/utils/frame/remote-externalities/Cargo.toml
index f2482f9c423d..56f797343c0f 100644
--- a/utils/frame/remote-externalities/Cargo.toml
+++ b/utils/frame/remote-externalities/Cargo.toml
@@ -16,6 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 jsonrpsee = { version = "0.4.1", features = ["ws-client", "macros"] }
 
 env_logger = "0.9"
+frame-support = { path = "../../../frame/support", optional = true }
 log = "0.4.11"
 codec = { package = "parity-scale-codec", version = "2.0.0" }
 serde_json = "1.0"
@@ -32,4 +33,4 @@ pallet-elections-phragmen = { path = "../../../frame/elections-phragmen", versio
 frame-support = { path = "../../../frame/support", version = "4.0.0-dev" }
 
 [features]
-remote-test = []
+remote-test = ["frame-support"]

From c45c1cbfde0037e6ef650146789a0aa0190fdefb Mon Sep 17 00:00:00 2001
From: Arkadiy Paronyan 
Date: Fri, 12 Nov 2021 14:15:01 +0100
Subject: [PATCH 176/695] Kill the light client, CHTs and change tries.
 (#10080)

* Remove light client, change tries and CHTs

* Update tests

* fmt

* Restore changes_root

* Fixed benches

* Cargo fmt

* fmt

* fmt
---
 Cargo.lock                                    |   20 -
 Cargo.toml                                    |    1 -
 bin/node-template/node/src/chain_spec.rs      |    1 -
 bin/node-template/node/src/service.rs         |    3 -
 bin/node/cli/src/chain_spec.rs                |    5 +-
 bin/node/cli/src/service.rs                   |    7 +-
 bin/node/executor/benches/bench.rs            |    4 +-
 bin/node/executor/tests/basic.rs              |   72 +-
 bin/node/executor/tests/common.rs             |   11 +-
 bin/node/executor/tests/fees.rs               |   14 +-
 bin/node/executor/tests/submit_transaction.rs |   12 +-
 bin/node/primitives/src/lib.rs                |    2 +-
 bin/node/rpc/src/lib.rs                       |   35 -
 bin/node/testing/src/bench.rs                 |    1 -
 bin/node/testing/src/client.rs                |    6 +-
 bin/node/testing/src/genesis.rs               |   16 +-
 client/api/src/backend.rs                     |  109 +-
 client/api/src/cht.rs                         |  474 ----
 client/api/src/in_mem.rs                      |  123 +-
 client/api/src/lib.rs                         |    3 -
 client/api/src/light.rs                       |  372 ---
 client/api/src/proof_provider.rs              |   25 +-
 .../basic-authorship/src/basic_authorship.rs  |   14 +-
 client/block-builder/src/lib.rs               |   15 +-
 client/consensus/aura/src/import_queue.rs     |   18 +-
 client/consensus/aura/src/lib.rs              |   78 +-
 client/consensus/babe/src/lib.rs              |   41 +-
 client/consensus/babe/src/tests.rs            |   22 +-
 client/consensus/babe/src/verification.rs     |   13 +-
 client/consensus/common/src/block_import.rs   |    8 +-
 client/consensus/manual-seal/src/consensus.rs |    8 +-
 .../manual-seal/src/consensus/babe.rs         |   17 +-
 client/consensus/pow/src/lib.rs               |   18 +-
 client/consensus/slots/src/lib.rs             |   10 +-
 client/db/src/cache/list_cache.rs             | 2351 -----------------
 client/db/src/cache/list_entry.rs             |  187 --
 client/db/src/cache/list_storage.rs           |  441 ----
 client/db/src/cache/mod.rs                    |  413 ---
 client/db/src/changes_tries_storage.rs        | 1168 --------
 client/db/src/lib.rs                          |  273 +-
 client/db/src/light.rs                        | 1329 ----------
 client/db/src/parity_db.rs                    |    6 +-
 client/db/src/utils.rs                        |   79 +-
 client/executor/src/integration_tests/mod.rs  |    2 +-
 client/finality-grandpa/src/import.rs         |    7 +-
 client/finality-grandpa/src/lib.rs            |    5 +-
 client/finality-grandpa/src/tests.rs          |   47 +-
 client/light/Cargo.toml                       |   27 -
 client/light/README.md                        |    3 -
 client/light/src/backend.rs                   |  578 ----
 client/light/src/blockchain.rs                |  219 --
 client/light/src/call_executor.rs             |  206 --
 client/light/src/lib.rs                       |   41 -
 client/network/src/behaviour.rs               |   50 +-
 client/network/src/config.rs                  |    6 -
 client/network/src/lib.rs                     |    1 -
 client/network/src/light_client_requests.rs   |  268 --
 .../src/light_client_requests/handler.rs      |  119 +-
 .../src/light_client_requests/sender.rs       | 1294 ---------
 client/network/src/on_demand_layer.rs         |  241 --
 client/network/src/service.rs                 |   37 -
 client/network/src/service/tests.rs           |    1 -
 client/network/test/src/lib.rs                |  185 +-
 client/network/test/src/sync.rs               |  105 +-
 client/rpc/src/chain/chain_light.rs           |  114 -
 client/rpc/src/chain/mod.rs                   |   29 +-
 client/rpc/src/state/state_full.rs            |  125 +-
 client/rpc/src/state/tests.rs                 |   34 +-
 client/service/src/builder.rs                 |   27 +-
 client/service/src/client/call_executor.rs    |   18 +-
 client/service/src/client/client.rs           |  401 +--
 client/service/src/lib.rs                     |    2 +-
 client/service/test/Cargo.toml                |    1 -
 client/service/test/src/client/db.rs          |    1 -
 client/service/test/src/client/mod.rs         |  274 +-
 client/transaction-pool/src/api.rs            |  134 +-
 client/transaction-pool/src/lib.rs            |   32 +-
 frame/aura/src/lib.rs                         |    4 +-
 frame/babe/src/lib.rs                         |    2 +-
 frame/beefy-mmr/src/tests.rs                  |    2 +-
 frame/beefy/src/lib.rs                        |    4 +-
 frame/beefy/src/tests.rs                      |    3 +-
 frame/executive/src/lib.rs                    |    7 +-
 frame/grandpa/src/lib.rs                      |    2 +-
 frame/grandpa/src/mock.rs                     |    2 +-
 frame/support/src/storage/mod.rs              |   17 +-
 frame/system/benchmarking/src/lib.rs          |   21 +-
 frame/system/src/lib.rs                       |   64 +-
 .../api/proc-macro/src/impl_runtime_apis.rs   |    5 -
 .../proc-macro/src/mock_impl_runtime_apis.rs  |    4 -
 primitives/api/src/lib.rs                     |    5 +-
 primitives/api/test/tests/runtime_calls.rs    |    2 +-
 primitives/blockchain/src/backend.rs          |   31 -
 primitives/consensus/aura/src/digests.rs      |    4 +-
 primitives/consensus/babe/src/digests.rs      |    7 +-
 primitives/consensus/common/src/lib.rs        |    8 +-
 primitives/core/src/changes_trie.rs           |  321 ---
 primitives/core/src/lib.rs                    |    2 -
 primitives/externalities/src/lib.rs           |    7 -
 primitives/io/src/lib.rs                      |   15 +-
 primitives/runtime-interface/test/src/lib.rs  |    2 +-
 primitives/runtime/src/generic/digest.rs      |  248 +-
 primitives/runtime/src/generic/header.rs      |   26 +-
 primitives/runtime/src/generic/mod.rs         |    2 +-
 primitives/runtime/src/generic/tests.rs       |   15 +-
 primitives/runtime/src/testing.rs             |    4 +-
 primitives/runtime/src/traits.rs              |   16 +-
 primitives/state-machine/src/backend.rs       |   26 -
 primitives/state-machine/src/basic.rs         |    4 -
 .../state-machine/src/changes_trie/build.rs   | 1083 --------
 .../src/changes_trie/build_cache.rs           |  278 --
 .../src/changes_trie/build_iterator.rs        |  487 ----
 .../src/changes_trie/changes_iterator.rs      |  748 ------
 .../state-machine/src/changes_trie/input.rs   |  207 --
 .../state-machine/src/changes_trie/mod.rs     |  428 ---
 .../state-machine/src/changes_trie/prune.rs   |  204 --
 .../state-machine/src/changes_trie/storage.rs |  214 --
 .../src/changes_trie/surface_iterator.rs      |  326 ---
 primitives/state-machine/src/ext.rs           |  195 +-
 primitives/state-machine/src/lib.rs           |  210 +-
 .../src/overlayed_changes/changeset.rs        |    1 -
 .../src/overlayed_changes/mod.rs              |  146 +-
 primitives/state-machine/src/read_only.rs     |    4 -
 primitives/state-machine/src/testing.rs       |   73 +-
 primitives/storage/src/lib.rs                 |    3 -
 primitives/tasks/src/async_externalities.rs   |    4 -
 primitives/test-primitives/src/lib.rs         |    9 +-
 test-utils/client/Cargo.toml                  |    1 -
 test-utils/client/src/lib.rs                  |   10 +-
 test-utils/runtime/client/Cargo.toml          |    1 -
 .../runtime/client/src/block_builder_ext.rs   |   13 -
 test-utils/runtime/client/src/lib.rs          |  169 +-
 test-utils/runtime/src/genesismap.rs          |    7 -
 test-utils/runtime/src/lib.rs                 |   13 +-
 test-utils/runtime/src/system.rs              |   36 +-
 test-utils/test-runner/src/client.rs          |    3 -
 test-utils/test-runner/src/node.rs            |   16 +-
 utils/frame/benchmarking-cli/src/command.rs   |   14 +-
 utils/frame/rpc/system/src/lib.rs             |   89 +-
 .../cli/src/commands/follow_chain.rs          |    7 +-
 utils/frame/try-runtime/cli/src/lib.rs        |    3 +-
 141 files changed, 534 insertions(+), 17809 deletions(-)
 delete mode 100644 client/api/src/cht.rs
 delete mode 100644 client/api/src/light.rs
 delete mode 100644 client/db/src/cache/list_cache.rs
 delete mode 100644 client/db/src/cache/list_entry.rs
 delete mode 100644 client/db/src/cache/list_storage.rs
 delete mode 100644 client/db/src/cache/mod.rs
 delete mode 100644 client/db/src/changes_tries_storage.rs
 delete mode 100644 client/db/src/light.rs
 delete mode 100644 client/light/Cargo.toml
 delete mode 100644 client/light/README.md
 delete mode 100644 client/light/src/backend.rs
 delete mode 100644 client/light/src/blockchain.rs
 delete mode 100644 client/light/src/call_executor.rs
 delete mode 100644 client/light/src/lib.rs
 delete mode 100644 client/network/src/light_client_requests/sender.rs
 delete mode 100644 client/network/src/on_demand_layer.rs
 delete mode 100644 client/rpc/src/chain/chain_light.rs
 delete mode 100644 primitives/core/src/changes_trie.rs
 delete mode 100644 primitives/state-machine/src/changes_trie/build.rs
 delete mode 100644 primitives/state-machine/src/changes_trie/build_cache.rs
 delete mode 100644 primitives/state-machine/src/changes_trie/build_iterator.rs
 delete mode 100644 primitives/state-machine/src/changes_trie/changes_iterator.rs
 delete mode 100644 primitives/state-machine/src/changes_trie/input.rs
 delete mode 100644 primitives/state-machine/src/changes_trie/mod.rs
 delete mode 100644 primitives/state-machine/src/changes_trie/prune.rs
 delete mode 100644 primitives/state-machine/src/changes_trie/storage.rs
 delete mode 100644 primitives/state-machine/src/changes_trie/surface_iterator.rs

diff --git a/Cargo.lock b/Cargo.lock
index 5d2fa99ca55a..74504d5f1547 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -8209,23 +8209,6 @@ dependencies = [
  "tempfile",
 ]
 
-[[package]]
-name = "sc-light"
-version = "4.0.0-dev"
-dependencies = [
- "hash-db",
- "parity-scale-codec",
- "parking_lot 0.11.1",
- "sc-client-api",
- "sc-executor",
- "sp-api",
- "sp-blockchain",
- "sp-core",
- "sp-externalities",
- "sp-runtime",
- "sp-state-machine",
-]
-
 [[package]]
 name = "sc-network"
 version = "0.10.0-dev"
@@ -8558,7 +8541,6 @@ dependencies = [
  "sc-client-db",
  "sc-consensus",
  "sc-executor",
- "sc-light",
  "sc-network",
  "sc-service",
  "sc-transaction-pool-api",
@@ -10176,7 +10158,6 @@ dependencies = [
  "sc-client-db",
  "sc-consensus",
  "sc-executor",
- "sc-light",
  "sc-offchain",
  "sc-service",
  "serde",
@@ -10245,7 +10226,6 @@ dependencies = [
  "sc-block-builder",
  "sc-client-api",
  "sc-consensus",
- "sc-light",
  "sp-api",
  "sp-blockchain",
  "sp-consensus",
diff --git a/Cargo.toml b/Cargo.toml
index ca60af692497..e03f33a4d27d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -42,7 +42,6 @@ members = [
 	"client/finality-grandpa",
 	"client/informant",
 	"client/keystore",
-	"client/light",
 	"client/network",
 	"client/network-gossip",
 	"client/network/test",
diff --git a/bin/node-template/node/src/chain_spec.rs b/bin/node-template/node/src/chain_spec.rs
index baf5e5d41ab8..d32a0dcb29d0 100644
--- a/bin/node-template/node/src/chain_spec.rs
+++ b/bin/node-template/node/src/chain_spec.rs
@@ -134,7 +134,6 @@ fn testnet_genesis(
 		system: SystemConfig {
 			// Add Wasm runtime to storage.
 			code: wasm_binary.to_vec(),
-			changes_trie_config: Default::default(),
 		},
 		balances: BalancesConfig {
 			// Configure endowed accounts with initial balance of 1 << 60.
diff --git a/bin/node-template/node/src/service.rs b/bin/node-template/node/src/service.rs
index c71336c33088..82b1c5625373 100644
--- a/bin/node-template/node/src/service.rs
+++ b/bin/node-template/node/src/service.rs
@@ -194,7 +194,6 @@ pub fn new_full(mut config: Configuration) -> Result
 			transaction_pool: transaction_pool.clone(),
 			spawn_handle: task_manager.spawn_handle(),
 			import_queue,
-			on_demand: None,
 			block_announce_validator_builder: None,
 			warp_sync: Some(warp_sync),
 		})?;
@@ -234,8 +233,6 @@ pub fn new_full(mut config: Configuration) -> Result
 		task_manager: &mut task_manager,
 		transaction_pool: transaction_pool.clone(),
 		rpc_extensions_builder,
-		on_demand: None,
-		remote_blockchain: None,
 		backend,
 		system_rpc_tx,
 		config,
diff --git a/bin/node/cli/src/chain_spec.rs b/bin/node/cli/src/chain_spec.rs
index 7b1ed90017c3..6d11722081e3 100644
--- a/bin/node/cli/src/chain_spec.rs
+++ b/bin/node/cli/src/chain_spec.rs
@@ -295,10 +295,7 @@ pub fn testnet_genesis(
 	const STASH: Balance = ENDOWMENT / 1000;
 
 	GenesisConfig {
-		system: SystemConfig {
-			code: wasm_binary_unwrap().to_vec(),
-			changes_trie_config: Default::default(),
-		},
+		system: SystemConfig { code: wasm_binary_unwrap().to_vec() },
 		balances: BalancesConfig {
 			balances: endowed_accounts.iter().cloned().map(|x| (x, ENDOWMENT)).collect(),
 		},
diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs
index dee546bf0700..e73b69153d1d 100644
--- a/bin/node/cli/src/service.rs
+++ b/bin/node/cli/src/service.rs
@@ -338,7 +338,6 @@ pub fn new_full_base(
 			transaction_pool: transaction_pool.clone(),
 			spawn_handle: task_manager.spawn_handle(),
 			import_queue,
-			on_demand: None,
 			block_announce_validator_builder: None,
 			warp_sync: Some(warp_sync),
 		})?;
@@ -369,8 +368,6 @@ pub fn new_full_base(
 		rpc_extensions_builder: Box::new(rpc_extensions_builder),
 		transaction_pool: transaction_pool.clone(),
 		task_manager: &mut task_manager,
-		on_demand: None,
-		remote_blockchain: None,
 		system_rpc_tx,
 		telemetry: telemetry.as_mut(),
 	})?;
@@ -542,7 +539,7 @@ mod tests {
 	use sc_service_test::TestNetNode;
 	use sc_transaction_pool_api::{ChainEvent, MaintainedTransactionPool};
 	use sp_consensus::{BlockOrigin, Environment, Proposer};
-	use sp_core::{crypto::Pair as CryptoPair, Public, H256};
+	use sp_core::{crypto::Pair as CryptoPair, Public};
 	use sp_inherents::InherentDataProvider;
 	use sp_keyring::AccountKeyring;
 	use sp_keystore::{SyncCryptoStore, SyncCryptoStorePtr};
@@ -621,7 +618,7 @@ mod tests {
 					None,
 				);
 
-				let mut digest = Digest::::default();
+				let mut digest = Digest::default();
 
 				// even though there's only one authority some slots might be empty,
 				// so we must keep trying the next slots until we can claim one.
diff --git a/bin/node/executor/benches/bench.rs b/bin/node/executor/benches/bench.rs
index 1a39c9decb32..03c3eb53e23f 100644
--- a/bin/node/executor/benches/bench.rs
+++ b/bin/node/executor/benches/bench.rs
@@ -53,7 +53,7 @@ const SPEC_VERSION: u32 = node_runtime::VERSION.spec_version;
 
 const HEAP_PAGES: u64 = 20;
 
-type TestExternalities = CoreTestExternalities;
+type TestExternalities = CoreTestExternalities;
 
 #[derive(Debug)]
 enum ExecutionMethod {
@@ -188,7 +188,7 @@ fn bench_execute_block(c: &mut Criterion) {
 
 	for strategy in execution_methods {
 		group.bench_function(format!("{:?}", strategy), |b| {
-			let genesis_config = node_testing::genesis::config(false, Some(compact_code_unwrap()));
+			let genesis_config = node_testing::genesis::config(Some(compact_code_unwrap()));
 			let (use_native, wasm_method) = match strategy {
 				ExecutionMethod::Native => (true, WasmExecutionMethod::Interpreted),
 				ExecutionMethod::Wasm(wasm_method) => (false, wasm_method),
diff --git a/bin/node/executor/tests/basic.rs b/bin/node/executor/tests/basic.rs
index bbb9339189b0..b7df7bf0bd41 100644
--- a/bin/node/executor/tests/basic.rs
+++ b/bin/node/executor/tests/basic.rs
@@ -29,7 +29,7 @@ use sp_runtime::{
 use node_primitives::{Balance, Hash};
 use node_runtime::{
 	constants::{currency::*, time::SLOT_DURATION},
-	Balances, Block, Call, CheckedExtrinsic, Event, Header, Runtime, System, TransactionPayment,
+	Balances, Call, CheckedExtrinsic, Event, Header, Runtime, System, TransactionPayment,
 	UncheckedExtrinsic,
 };
 use node_testing::keyring::*;
@@ -78,7 +78,7 @@ fn set_heap_pages(ext: &mut E, heap_pages: u64) {
 fn changes_trie_block() -> (Vec, Hash) {
 	let time = 42 * 1000;
 	construct_block(
-		&mut new_test_ext(compact_code_unwrap(), true),
+		&mut new_test_ext(compact_code_unwrap()),
 		1,
 		GENESIS_HASH.into(),
 		vec![
@@ -102,7 +102,7 @@ fn changes_trie_block() -> (Vec, Hash) {
 /// are not guaranteed to be deterministic) and to ensure that the correct state is propagated
 /// from block1's execution to block2 to derive the correct storage_root.
 fn blocks() -> ((Vec, Hash), (Vec, Hash)) {
-	let mut t = new_test_ext(compact_code_unwrap(), false);
+	let mut t = new_test_ext(compact_code_unwrap());
 	let time1 = 42 * 1000;
 	let block1 = construct_block(
 		&mut t,
@@ -160,7 +160,7 @@ fn blocks() -> ((Vec, Hash), (Vec, Hash)) {
 
 fn block_with_size(time: u64, nonce: u32, size: usize) -> (Vec, Hash) {
 	construct_block(
-		&mut new_test_ext(compact_code_unwrap(), false),
+		&mut new_test_ext(compact_code_unwrap()),
 		1,
 		GENESIS_HASH.into(),
 		vec![
@@ -179,7 +179,7 @@ fn block_with_size(time: u64, nonce: u32, size: usize) -> (Vec, Hash) {
 
 #[test]
 fn panic_execution_with_foreign_code_gives_error() {
-	let mut t = new_test_ext(bloaty_code_unwrap(), false);
+	let mut t = new_test_ext(bloaty_code_unwrap());
 	t.insert(
 		>::hashed_key_for(alice()),
 		(69u128, 0u32, 0u128, 0u128, 0u128).encode(),
@@ -211,7 +211,7 @@ fn panic_execution_with_foreign_code_gives_error() {
 
 #[test]
 fn bad_extrinsic_with_native_equivalent_code_gives_error() {
-	let mut t = new_test_ext(compact_code_unwrap(), false);
+	let mut t = new_test_ext(compact_code_unwrap());
 	t.insert(
 		>::hashed_key_for(alice()),
 		(0u32, 0u32, 0u32, 69u128, 0u128, 0u128, 0u128).encode(),
@@ -243,7 +243,7 @@ fn bad_extrinsic_with_native_equivalent_code_gives_error() {
 
 #[test]
 fn successful_execution_with_native_equivalent_code_gives_ok() {
-	let mut t = new_test_ext(compact_code_unwrap(), false);
+	let mut t = new_test_ext(compact_code_unwrap());
 	t.insert(
 		>::hashed_key_for(alice()),
 		AccountInfo::<::Index, _> {
@@ -296,7 +296,7 @@ fn successful_execution_with_native_equivalent_code_gives_ok() {
 
 #[test]
 fn successful_execution_with_foreign_code_gives_ok() {
-	let mut t = new_test_ext(bloaty_code_unwrap(), false);
+	let mut t = new_test_ext(bloaty_code_unwrap());
 	t.insert(
 		>::hashed_key_for(alice()),
 		AccountInfo::<::Index, _> {
@@ -349,7 +349,7 @@ fn successful_execution_with_foreign_code_gives_ok() {
 
 #[test]
 fn full_native_block_import_works() {
-	let mut t = new_test_ext(compact_code_unwrap(), false);
+	let mut t = new_test_ext(compact_code_unwrap());
 
 	let (block1, block2) = blocks();
 
@@ -529,7 +529,7 @@ fn full_native_block_import_works() {
 
 #[test]
 fn full_wasm_block_import_works() {
-	let mut t = new_test_ext(compact_code_unwrap(), false);
+	let mut t = new_test_ext(compact_code_unwrap());
 
 	let (block1, block2) = blocks();
 
@@ -679,7 +679,7 @@ fn deploying_wasm_contract_should_work() {
 
 	let time = 42 * 1000;
 	let b = construct_block(
-		&mut new_test_ext(compact_code_unwrap(), false),
+		&mut new_test_ext(compact_code_unwrap()),
 		1,
 		GENESIS_HASH.into(),
 		vec![
@@ -712,7 +712,7 @@ fn deploying_wasm_contract_should_work() {
 		(time / SLOT_DURATION).into(),
 	);
 
-	let mut t = new_test_ext(compact_code_unwrap(), false);
+	let mut t = new_test_ext(compact_code_unwrap());
 
 	executor_call:: _>(&mut t, "Core_execute_block", &b.0, false, None)
 		.0
@@ -727,7 +727,7 @@ fn deploying_wasm_contract_should_work() {
 
 #[test]
 fn wasm_big_block_import_fails() {
-	let mut t = new_test_ext(compact_code_unwrap(), false);
+	let mut t = new_test_ext(compact_code_unwrap());
 
 	set_heap_pages(&mut t.ext(), 4);
 
@@ -744,7 +744,7 @@ fn wasm_big_block_import_fails() {
 
 #[test]
 fn native_big_block_import_succeeds() {
-	let mut t = new_test_ext(compact_code_unwrap(), false);
+	let mut t = new_test_ext(compact_code_unwrap());
 
 	executor_call:: _>(
 		&mut t,
@@ -759,7 +759,7 @@ fn native_big_block_import_succeeds() {
 
 #[test]
 fn native_big_block_import_fails_on_fallback() {
-	let mut t = new_test_ext(compact_code_unwrap(), false);
+	let mut t = new_test_ext(compact_code_unwrap());
 
 	// We set the heap pages to 8 because we know that should give an OOM in WASM with the given
 	// block.
@@ -778,7 +778,7 @@ fn native_big_block_import_fails_on_fallback() {
 
 #[test]
 fn panic_execution_gives_error() {
-	let mut t = new_test_ext(bloaty_code_unwrap(), false);
+	let mut t = new_test_ext(bloaty_code_unwrap());
 	t.insert(
 		>::hashed_key_for(alice()),
 		AccountInfo::<::Index, _> {
@@ -815,7 +815,7 @@ fn panic_execution_gives_error() {
 
 #[test]
 fn successful_execution_gives_ok() {
-	let mut t = new_test_ext(compact_code_unwrap(), false);
+	let mut t = new_test_ext(compact_code_unwrap());
 	t.insert(
 		>::hashed_key_for(alice()),
 		AccountInfo::<::Index, _> {
@@ -874,44 +874,6 @@ fn successful_execution_gives_ok() {
 	});
 }
 
-#[test]
-fn full_native_block_import_works_with_changes_trie() {
-	let block1 = changes_trie_block();
-	let block_data = block1.0;
-	let block = Block::decode(&mut &block_data[..]).unwrap();
-
-	let mut t = new_test_ext(compact_code_unwrap(), true);
-	executor_call:: _>(
-		&mut t,
-		"Core_execute_block",
-		&block.encode(),
-		true,
-		None,
-	)
-	.0
-	.unwrap();
-
-	assert!(t.ext().storage_changes_root(&GENESIS_HASH).unwrap().is_some());
-}
-
-#[test]
-fn full_wasm_block_import_works_with_changes_trie() {
-	let block1 = changes_trie_block();
-
-	let mut t = new_test_ext(compact_code_unwrap(), true);
-	executor_call:: _>(
-		&mut t,
-		"Core_execute_block",
-		&block1.0,
-		false,
-		None,
-	)
-	.0
-	.unwrap();
-
-	assert!(t.ext().storage_changes_root(&GENESIS_HASH).unwrap().is_some());
-}
-
 #[test]
 fn should_import_block_with_test_client() {
 	use node_testing::client::{
diff --git a/bin/node/executor/tests/common.rs b/bin/node/executor/tests/common.rs
index d1c24c83c836..c81d6b7c14e0 100644
--- a/bin/node/executor/tests/common.rs
+++ b/bin/node/executor/tests/common.rs
@@ -81,7 +81,7 @@ pub const SPEC_VERSION: u32 = node_runtime::VERSION.spec_version;
 
 pub const TRANSACTION_VERSION: u32 = node_runtime::VERSION.transaction_version;
 
-pub type TestExternalities = CoreTestExternalities;
+pub type TestExternalities = CoreTestExternalities;
 
 pub fn sign(xt: CheckedExtrinsic) -> UncheckedExtrinsic {
 	node_testing::keyring::sign(xt, SPEC_VERSION, TRANSACTION_VERSION, GENESIS_HASH)
@@ -123,14 +123,11 @@ pub fn executor_call<
 	executor().call::(&mut t, &runtime_code, method, data, use_native, native_call)
 }
 
-pub fn new_test_ext(code: &[u8], support_changes_trie: bool) -> TestExternalities {
-	let mut ext = TestExternalities::new_with_code(
+pub fn new_test_ext(code: &[u8]) -> TestExternalities {
+	let ext = TestExternalities::new_with_code(
 		code,
-		node_testing::genesis::config(support_changes_trie, Some(code))
-			.build_storage()
-			.unwrap(),
+		node_testing::genesis::config(Some(code)).build_storage().unwrap(),
 	);
-	ext.changes_trie_storage().insert(0, GENESIS_HASH.into(), Default::default());
 	ext
 }
 
diff --git a/bin/node/executor/tests/fees.rs b/bin/node/executor/tests/fees.rs
index 4c7593bdb3ab..4767c1bda1fc 100644
--- a/bin/node/executor/tests/fees.rs
+++ b/bin/node/executor/tests/fees.rs
@@ -36,7 +36,7 @@ use self::common::{sign, *};
 
 #[test]
 fn fee_multiplier_increases_and_decreases_on_big_weight() {
-	let mut t = new_test_ext(compact_code_unwrap(), false);
+	let mut t = new_test_ext(compact_code_unwrap());
 
 	// initial fee multiplier must be one.
 	let mut prev_multiplier = Multiplier::one();
@@ -45,7 +45,7 @@ fn fee_multiplier_increases_and_decreases_on_big_weight() {
 		assert_eq!(TransactionPayment::next_fee_multiplier(), prev_multiplier);
 	});
 
-	let mut tt = new_test_ext(compact_code_unwrap(), false);
+	let mut tt = new_test_ext(compact_code_unwrap());
 
 	let time1 = 42 * 1000;
 	// big one in terms of weight.
@@ -151,7 +151,7 @@ fn transaction_fee_is_correct() {
 	//   - 1 MILLICENTS in substrate node.
 	//   - 1 milli-dot based on current polkadot runtime.
 	// (this baed on assigning 0.1 CENT to the cheapest tx with `weight = 100`)
-	let mut t = new_test_ext(compact_code_unwrap(), false);
+	let mut t = new_test_ext(compact_code_unwrap());
 	t.insert(>::hashed_key_for(alice()), new_account_info(100));
 	t.insert(>::hashed_key_for(bob()), new_account_info(10));
 	t.insert(
@@ -226,9 +226,9 @@ fn block_weight_capacity_report() {
 	use node_primitives::Index;
 
 	// execution ext.
-	let mut t = new_test_ext(compact_code_unwrap(), false);
+	let mut t = new_test_ext(compact_code_unwrap());
 	// setup ext.
-	let mut tt = new_test_ext(compact_code_unwrap(), false);
+	let mut tt = new_test_ext(compact_code_unwrap());
 
 	let factor = 50;
 	let mut time = 10;
@@ -303,9 +303,9 @@ fn block_length_capacity_report() {
 	use node_primitives::Index;
 
 	// execution ext.
-	let mut t = new_test_ext(compact_code_unwrap(), false);
+	let mut t = new_test_ext(compact_code_unwrap());
 	// setup ext.
-	let mut tt = new_test_ext(compact_code_unwrap(), false);
+	let mut tt = new_test_ext(compact_code_unwrap());
 
 	let factor = 256 * 1024;
 	let mut time = 10;
diff --git a/bin/node/executor/tests/submit_transaction.rs b/bin/node/executor/tests/submit_transaction.rs
index 19ca8e5677c4..f047c6a44a66 100644
--- a/bin/node/executor/tests/submit_transaction.rs
+++ b/bin/node/executor/tests/submit_transaction.rs
@@ -28,7 +28,7 @@ use self::common::*;
 
 #[test]
 fn should_submit_unsigned_transaction() {
-	let mut t = new_test_ext(compact_code_unwrap(), false);
+	let mut t = new_test_ext(compact_code_unwrap());
 	let (pool, state) = TestTransactionPoolExt::new();
 	t.register_extension(TransactionPoolExt::new(pool));
 
@@ -56,7 +56,7 @@ const PHRASE: &str = "news slush supreme milk chapter athlete soap sausage put c
 
 #[test]
 fn should_submit_signed_transaction() {
-	let mut t = new_test_ext(compact_code_unwrap(), false);
+	let mut t = new_test_ext(compact_code_unwrap());
 	let (pool, state) = TestTransactionPoolExt::new();
 	t.register_extension(TransactionPoolExt::new(pool));
 
@@ -99,7 +99,7 @@ fn should_submit_signed_transaction() {
 
 #[test]
 fn should_submit_signed_twice_from_the_same_account() {
-	let mut t = new_test_ext(compact_code_unwrap(), false);
+	let mut t = new_test_ext(compact_code_unwrap());
 	let (pool, state) = TestTransactionPoolExt::new();
 	t.register_extension(TransactionPoolExt::new(pool));
 
@@ -156,7 +156,7 @@ fn should_submit_signed_twice_from_the_same_account() {
 
 #[test]
 fn should_submit_signed_twice_from_all_accounts() {
-	let mut t = new_test_ext(compact_code_unwrap(), false);
+	let mut t = new_test_ext(compact_code_unwrap());
 	let (pool, state) = TestTransactionPoolExt::new();
 	t.register_extension(TransactionPoolExt::new(pool));
 
@@ -220,7 +220,7 @@ fn submitted_transaction_should_be_valid() {
 		transaction_validity::{TransactionSource, TransactionTag},
 	};
 
-	let mut t = new_test_ext(compact_code_unwrap(), false);
+	let mut t = new_test_ext(compact_code_unwrap());
 	let (pool, state) = TestTransactionPoolExt::new();
 	t.register_extension(TransactionPoolExt::new(pool));
 
@@ -249,7 +249,7 @@ fn submitted_transaction_should_be_valid() {
 	// check that transaction is valid, but reset environment storage,
 	// since CreateTransaction increments the nonce
 	let tx0 = state.read().transactions[0].clone();
-	let mut t = new_test_ext(compact_code_unwrap(), false);
+	let mut t = new_test_ext(compact_code_unwrap());
 	t.execute_with(|| {
 		let source = TransactionSource::External;
 		let extrinsic = UncheckedExtrinsic::decode(&mut &*tx0).unwrap();
diff --git a/bin/node/primitives/src/lib.rs b/bin/node/primitives/src/lib.rs
index dade598c704d..fc3bd5f5114e 100644
--- a/bin/node/primitives/src/lib.rs
+++ b/bin/node/primitives/src/lib.rs
@@ -57,7 +57,7 @@ pub type Hash = sp_core::H256;
 pub type Timestamp = u64;
 
 /// Digest item type.
-pub type DigestItem = generic::DigestItem;
+pub type DigestItem = generic::DigestItem;
 /// Header type.
 pub type Header = generic::Header;
 /// Block type.
diff --git a/bin/node/rpc/src/lib.rs b/bin/node/rpc/src/lib.rs
index 2f7862d3d264..51ab191d5e9a 100644
--- a/bin/node/rpc/src/lib.rs
+++ b/bin/node/rpc/src/lib.rs
@@ -51,18 +51,6 @@ use sp_consensus::SelectChain;
 use sp_consensus_babe::BabeApi;
 use sp_keystore::SyncCryptoStorePtr;
 
-/// Light client extra dependencies.
-pub struct LightDeps {
-	/// The client instance to use.
-	pub client: Arc,
-	/// Transaction pool instance.
-	pub pool: Arc

, - /// Remote access to the blockchain (async). - pub remote_blockchain: Arc>, - /// Fetcher instance. - pub fetcher: Arc, -} - /// Extra dependencies for BABE. pub struct BabeDeps { /// BABE protocol config. @@ -183,26 +171,3 @@ where Ok(io) } - -/// Instantiate all Light RPC extensions. -pub fn create_light(deps: LightDeps) -> jsonrpc_core::IoHandler -where - C: sp_blockchain::HeaderBackend, - C: Send + Sync + 'static, - F: sc_client_api::light::Fetcher + 'static, - P: TransactionPool + 'static, - M: jsonrpc_core::Metadata + Default, -{ - use substrate_frame_rpc_system::{LightSystem, SystemApi}; - - let LightDeps { client, pool, remote_blockchain, fetcher } = deps; - let mut io = jsonrpc_core::IoHandler::default(); - io.extend_with(SystemApi::::to_delegate(LightSystem::new( - client, - remote_blockchain, - fetcher, - pool, - ))); - - io -} diff --git a/bin/node/testing/src/bench.rs b/bin/node/testing/src/bench.rs index 5ee1ec998be4..3240497a9d62 100644 --- a/bin/node/testing/src/bench.rs +++ b/bin/node/testing/src/bench.rs @@ -591,7 +591,6 @@ impl BenchKeyring { /// Generate genesis with accounts from this keyring endowed with some balance. pub fn generate_genesis(&self) -> node_runtime::GenesisConfig { crate::genesis::config_endowed( - false, Some(node_runtime::wasm_binary_unwrap()), self.collect_account_ids(), ) diff --git a/bin/node/testing/src/client.rs b/bin/node/testing/src/client.rs index 8bd75834c549..4852e33de607 100644 --- a/bin/node/testing/src/client.rs +++ b/bin/node/testing/src/client.rs @@ -42,13 +42,11 @@ pub type Transaction = sc_client_api::backend::TransactionFor Storage { - crate::genesis::config(self.support_changes_trie, None).build_storage().unwrap() + crate::genesis::config(None).build_storage().unwrap() } } diff --git a/bin/node/testing/src/genesis.rs b/bin/node/testing/src/genesis.rs index 80399a6670e8..fa0dd22c9c99 100644 --- a/bin/node/testing/src/genesis.rs +++ b/bin/node/testing/src/genesis.rs @@ -24,22 +24,17 @@ use node_runtime::{ GenesisConfig, GrandpaConfig, IndicesConfig, SessionConfig, SocietyConfig, StakerStatus, StakingConfig, SystemConfig, BABE_GENESIS_EPOCH_CONFIG, }; -use sp_core::ChangesTrieConfiguration; use sp_keyring::{Ed25519Keyring, Sr25519Keyring}; use sp_runtime::Perbill; /// Create genesis runtime configuration for tests. -pub fn config(support_changes_trie: bool, code: Option<&[u8]>) -> GenesisConfig { - config_endowed(support_changes_trie, code, Default::default()) +pub fn config(code: Option<&[u8]>) -> GenesisConfig { + config_endowed(code, Default::default()) } /// Create genesis runtime configuration for tests with some extra /// endowed accounts. -pub fn config_endowed( - support_changes_trie: bool, - code: Option<&[u8]>, - extra_endowed: Vec, -) -> GenesisConfig { +pub fn config_endowed(code: Option<&[u8]>, extra_endowed: Vec) -> GenesisConfig { let mut endowed = vec![ (alice(), 111 * DOLLARS), (bob(), 100 * DOLLARS), @@ -53,11 +48,6 @@ pub fn config_endowed( GenesisConfig { system: SystemConfig { - changes_trie_config: if support_changes_trie { - Some(ChangesTrieConfiguration { digest_interval: 2, digest_levels: 2 }) - } else { - None - }, code: code.map(|x| x.to_vec()).unwrap_or_else(|| wasm_binary_unwrap().to_vec()), }, indices: IndicesConfig { indices: vec![] }, diff --git a/client/api/src/backend.rs b/client/api/src/backend.rs index 9dfe82a57ab3..a681d75fe9af 100644 --- a/client/api/src/backend.rs +++ b/client/api/src/backend.rs @@ -20,27 +20,22 @@ use crate::{ blockchain::{well_known_cache_keys, Backend as BlockchainBackend}, - light::RemoteBlockchain, UsageInfo, }; use parking_lot::RwLock; use sp_blockchain; use sp_consensus::BlockOrigin; -use sp_core::{offchain::OffchainStorage, ChangesTrieConfigurationRange}; +use sp_core::offchain::OffchainStorage; use sp_runtime::{ generic::BlockId, traits::{Block as BlockT, HashFor, NumberFor}, Justification, Justifications, Storage, }; use sp_state_machine::{ - ChangesTrieState, ChangesTrieStorage as StateChangesTrieStorage, ChangesTrieTransaction, ChildStorageCollection, IndexOperation, OffchainChangesCollection, StorageCollection, }; -use sp_storage::{ChildInfo, PrefixedStorageKey, StorageData, StorageKey}; -use std::{ - collections::{HashMap, HashSet}, - sync::Arc, -}; +use sp_storage::{ChildInfo, StorageData, StorageKey}; +use std::collections::{HashMap, HashSet}; pub use sp_state_machine::{Backend as StateBackend, KeyValueStates}; use std::marker::PhantomData; @@ -191,12 +186,6 @@ pub trait BlockImportOperation { Ok(()) } - /// Inject changes trie data into the database. - fn update_changes_trie( - &mut self, - update: ChangesTrieTransaction, NumberFor>, - ) -> sp_blockchain::Result<()>; - /// Insert auxiliary keys. /// /// Values are `None` if should be deleted. @@ -418,28 +407,6 @@ pub trait StorageProvider> { child_info: &ChildInfo, key: &StorageKey, ) -> sp_blockchain::Result>; - - /// Get longest range within [first; last] that is possible to use in `key_changes` - /// and `key_changes_proof` calls. - /// Range could be shortened from the beginning if some changes tries have been pruned. - /// Returns Ok(None) if changes tries are not supported. - fn max_key_changes_range( - &self, - first: NumberFor, - last: BlockId, - ) -> sp_blockchain::Result, BlockId)>>; - - /// Get pairs of (block, extrinsic) where key has been changed at given blocks range. - /// Works only for runtimes that are supporting changes tries. - /// - /// Changes are returned in descending order (i.e. last block comes first). - fn key_changes( - &self, - first: NumberFor, - last: BlockId, - storage_key: Option<&PrefixedStorageKey>, - key: &StorageKey, - ) -> sp_blockchain::Result, u32)>>; } /// Client backend. @@ -504,9 +471,6 @@ pub trait Backend: AuxStore + Send + Sync { /// Returns current usage statistics. fn usage_info(&self) -> Option; - /// Returns reference to changes trie storage. - fn changes_trie_storage(&self) -> Option<&dyn PrunableStateChangesTrieStorage>; - /// Returns a handle to offchain storage. fn offchain_storage(&self) -> Option; @@ -561,72 +525,5 @@ pub trait Backend: AuxStore + Send + Sync { fn get_import_lock(&self) -> &RwLock<()>; } -/// Changes trie storage that supports pruning. -pub trait PrunableStateChangesTrieStorage: - StateChangesTrieStorage, NumberFor> -{ - /// Get reference to StateChangesTrieStorage. - fn storage(&self) -> &dyn StateChangesTrieStorage, NumberFor>; - /// Get configuration at given block. - fn configuration_at( - &self, - at: &BlockId, - ) -> sp_blockchain::Result, Block::Hash>>; - /// Get end block (inclusive) of oldest pruned max-level (or skewed) digest trie blocks range. - /// It is guaranteed that we have no any changes tries before (and including) this block. - /// It is guaranteed that all existing changes tries after this block are not yet pruned (if - /// created). - fn oldest_pruned_digest_range_end(&self) -> NumberFor; -} - /// Mark for all Backend implementations, that are making use of state data, stored locally. pub trait LocalBackend: Backend {} - -/// Mark for all Backend implementations, that are fetching required state data from remote nodes. -pub trait RemoteBackend: Backend { - /// Returns true if the state for given block is available locally. - fn is_local_state_available(&self, block: &BlockId) -> bool; - - /// Returns reference to blockchain backend. - /// - /// Returned backend either resolves blockchain data - /// locally, or prepares request to fetch that data from remote node. - fn remote_blockchain(&self) -> Arc>; -} - -/// Return changes tries state at given block. -pub fn changes_tries_state_at_block<'a, Block: BlockT>( - block: &BlockId, - maybe_storage: Option<&'a dyn PrunableStateChangesTrieStorage>, -) -> sp_blockchain::Result, NumberFor>>> { - let storage = match maybe_storage { - Some(storage) => storage, - None => return Ok(None), - }; - - let config_range = storage.configuration_at(block)?; - match config_range.config { - Some(config) => - Ok(Some(ChangesTrieState::new(config, config_range.zero.0, storage.storage()))), - None => Ok(None), - } -} - -/// Provide CHT roots. These are stored on a light client and generated dynamically on a full -/// client. -pub trait ProvideChtRoots { - /// Get headers CHT root for given block. Returns None if the block is not a part of any CHT. - fn header_cht_root( - &self, - cht_size: NumberFor, - block: NumberFor, - ) -> sp_blockchain::Result>; - - /// Get changes trie CHT root for given block. Returns None if the block is not a part of any - /// CHT. - fn changes_trie_cht_root( - &self, - cht_size: NumberFor, - block: NumberFor, - ) -> sp_blockchain::Result>; -} diff --git a/client/api/src/cht.rs b/client/api/src/cht.rs deleted file mode 100644 index ee7854b5d829..000000000000 --- a/client/api/src/cht.rs +++ /dev/null @@ -1,474 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2017-2021 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 . - -//! Canonical hash trie definitions and helper functions. -//! -//! Each CHT is a trie mapping block numbers to canonical hash. -//! One is generated for every `SIZE` blocks, allowing us to discard those blocks in -//! favor of the trie root. When the "ancient" blocks need to be accessed, we simply -//! request an inclusion proof of a specific block number against the trie with the -//! root hash. A correct proof implies that the claimed block is identical to the one -//! we discarded. - -use codec::Encode; -use hash_db; -use sp_trie; - -use sp_core::{convert_hash, H256}; -use sp_runtime::traits::{AtLeast32Bit, Header as HeaderT, One, Zero}; -use sp_state_machine::{ - prove_read_on_trie_backend, read_proof_check, read_proof_check_on_proving_backend, - Backend as StateBackend, InMemoryBackend, MemoryDB, StorageProof, TrieBackend, -}; - -use sp_blockchain::{Error as ClientError, Result as ClientResult}; - -/// The size of each CHT. This value is passed to every CHT-related function from -/// production code. Other values are passed from tests. -const SIZE: u32 = 2048; - -/// Gets default CHT size. -pub fn size>() -> N { - SIZE.into() -} - -/// Returns Some(cht_number) if CHT is need to be built when the block with given number is -/// canonized. -pub fn is_build_required(cht_size: N, block_num: N) -> Option -where - N: Clone + AtLeast32Bit, -{ - let block_cht_num = block_to_cht_number(cht_size.clone(), block_num.clone())?; - let two = N::one() + N::one(); - if block_cht_num < two { - return None - } - let cht_start = start_number(cht_size, block_cht_num.clone()); - if cht_start != block_num { - return None - } - - Some(block_cht_num - two) -} - -/// Returns Some(max_cht_number) if CHT has ever been built given maximal canonical block number. -pub fn max_cht_number(cht_size: N, max_canonical_block: N) -> Option -where - N: Clone + AtLeast32Bit, -{ - let max_cht_number = block_to_cht_number(cht_size, max_canonical_block)?; - let two = N::one() + N::one(); - if max_cht_number < two { - return None - } - Some(max_cht_number - two) -} - -/// Compute a CHT root from an iterator of block hashes. Fails if shorter than -/// SIZE items. The items are assumed to proceed sequentially from `start_number(cht_num)`. -/// Discards the trie's nodes. -pub fn compute_root( - cht_size: Header::Number, - cht_num: Header::Number, - hashes: I, -) -> ClientResult -where - Header: HeaderT, - Hasher: hash_db::Hasher, - Hasher::Out: Ord, - I: IntoIterator>>, -{ - use sp_trie::TrieConfiguration; - Ok(sp_trie::trie_types::Layout::::trie_root(build_pairs::( - cht_size, cht_num, hashes, - )?)) -} - -/// Build CHT-based header proof. -pub fn build_proof( - cht_size: Header::Number, - cht_num: Header::Number, - blocks: BlocksI, - hashes: HashesI, -) -> ClientResult -where - Header: HeaderT, - Hasher: hash_db::Hasher, - Hasher::Out: Ord + codec::Codec, - BlocksI: IntoIterator, - HashesI: IntoIterator>>, -{ - let transaction = build_pairs::(cht_size, cht_num, hashes)? - .into_iter() - .map(|(k, v)| (k, Some(v))) - .collect::>(); - let storage = InMemoryBackend::::default().update(vec![(None, transaction)]); - let trie_storage = storage - .as_trie_backend() - .expect("InMemoryState::as_trie_backend always returns Some; qed"); - prove_read_on_trie_backend( - trie_storage, - blocks.into_iter().map(|number| encode_cht_key(number)), - ) - .map_err(ClientError::from_state) -} - -/// Check CHT-based header proof. -pub fn check_proof( - local_root: Header::Hash, - local_number: Header::Number, - remote_hash: Header::Hash, - remote_proof: StorageProof, -) -> ClientResult<()> -where - Header: HeaderT, - Hasher: hash_db::Hasher, - Hasher::Out: Ord + codec::Codec, -{ - do_check_proof::( - local_root, - local_number, - remote_hash, - move |local_root, local_cht_key| { - read_proof_check::( - local_root, - remote_proof, - ::std::iter::once(local_cht_key), - ) - .map(|mut map| map.remove(local_cht_key).expect("checked proof of local_cht_key; qed")) - .map_err(ClientError::from_state) - }, - ) -} - -/// Check CHT-based header proof on pre-created proving backend. -pub fn check_proof_on_proving_backend( - local_root: Header::Hash, - local_number: Header::Number, - remote_hash: Header::Hash, - proving_backend: &TrieBackend, Hasher>, -) -> ClientResult<()> -where - Header: HeaderT, - Hasher: hash_db::Hasher, - Hasher::Out: Ord + codec::Codec, -{ - do_check_proof::( - local_root, - local_number, - remote_hash, - |_, local_cht_key| { - read_proof_check_on_proving_backend::(proving_backend, local_cht_key) - .map_err(ClientError::from_state) - }, - ) -} - -/// Check CHT-based header proof using passed checker function. -fn do_check_proof( - local_root: Header::Hash, - local_number: Header::Number, - remote_hash: Header::Hash, - checker: F, -) -> ClientResult<()> -where - Header: HeaderT, - Hasher: hash_db::Hasher, - Hasher::Out: Ord, - F: FnOnce(Hasher::Out, &[u8]) -> ClientResult>>, -{ - let root: Hasher::Out = convert_hash(&local_root); - let local_cht_key = encode_cht_key(local_number); - let local_cht_value = checker(root, &local_cht_key)?; - let local_cht_value = local_cht_value.ok_or_else(|| ClientError::InvalidCHTProof)?; - let local_hash = - decode_cht_value(&local_cht_value).ok_or_else(|| ClientError::InvalidCHTProof)?; - match &local_hash[..] == remote_hash.as_ref() { - true => Ok(()), - false => Err(ClientError::InvalidCHTProof.into()), - } -} - -/// Group ordered blocks by CHT number and call functor with blocks of each group. -pub fn for_each_cht_group( - cht_size: Header::Number, - blocks: I, - mut functor: F, - mut functor_param: P, -) -> ClientResult<()> -where - Header: HeaderT, - I: IntoIterator, - F: FnMut(P, Header::Number, Vec) -> ClientResult

, -{ - let mut current_cht_num = None; - let mut current_cht_blocks = Vec::new(); - for block in blocks { - let new_cht_num = block_to_cht_number(cht_size, block).ok_or_else(|| { - ClientError::Backend(format!("Cannot compute CHT root for the block #{}", block)) - })?; - - let advance_to_next_cht = current_cht_num.is_some() && current_cht_num != Some(new_cht_num); - if advance_to_next_cht { - let current_cht_num = current_cht_num.expect( - "advance_to_next_cht is true; - it is true only when current_cht_num is Some; qed", - ); - assert!( - new_cht_num > current_cht_num, - "for_each_cht_group only supports ordered iterators" - ); - - functor_param = - functor(functor_param, current_cht_num, std::mem::take(&mut current_cht_blocks))?; - } - - current_cht_blocks.push(block); - current_cht_num = Some(new_cht_num); - } - - if let Some(current_cht_num) = current_cht_num { - functor(functor_param, current_cht_num, std::mem::take(&mut current_cht_blocks))?; - } - - Ok(()) -} - -/// Build pairs for computing CHT. -fn build_pairs( - cht_size: Header::Number, - cht_num: Header::Number, - hashes: I, -) -> ClientResult, Vec)>> -where - Header: HeaderT, - I: IntoIterator>>, -{ - let start_num = start_number(cht_size, cht_num); - let mut pairs = Vec::new(); - let mut hash_index = Header::Number::zero(); - for hash in hashes.into_iter() { - let hash = - hash?.ok_or_else(|| ClientError::from(ClientError::MissingHashRequiredForCHT))?; - pairs.push((encode_cht_key(start_num + hash_index).to_vec(), encode_cht_value(hash))); - hash_index += Header::Number::one(); - if hash_index == cht_size { - break - } - } - - if hash_index == cht_size { - Ok(pairs) - } else { - Err(ClientError::MissingHashRequiredForCHT) - } -} - -/// Get the starting block of a given CHT. -/// CHT 0 includes block 1...SIZE, -/// CHT 1 includes block SIZE + 1 ... 2*SIZE -/// More generally: CHT N includes block (1 + N*SIZE)...((N+1)*SIZE). -/// This is because the genesis hash is assumed to be known -/// and including it would be redundant. -pub fn start_number(cht_size: N, cht_num: N) -> N { - (cht_num * cht_size) + N::one() -} - -/// Get the ending block of a given CHT. -pub fn end_number(cht_size: N, cht_num: N) -> N { - (cht_num + N::one()) * cht_size -} - -/// Convert a block number to a CHT number. -/// Returns `None` for `block_num` == 0, `Some` otherwise. -pub fn block_to_cht_number(cht_size: N, block_num: N) -> Option { - if block_num == N::zero() { - None - } else { - Some((block_num - N::one()) / cht_size) - } -} - -/// Convert header number into CHT key. -pub fn encode_cht_key(number: N) -> Vec { - number.encode() -} - -/// Convert header hash into CHT value. -fn encode_cht_value>(hash: Hash) -> Vec { - hash.as_ref().to_vec() -} - -/// Convert CHT value into block header hash. -pub fn decode_cht_value(value: &[u8]) -> Option { - match value.len() { - 32 => Some(H256::from_slice(&value[0..32])), - _ => None, - } -} - -#[cfg(test)] -mod tests { - use super::*; - use sp_runtime::{generic, traits::BlakeTwo256}; - - type Header = generic::Header; - - #[test] - fn is_build_required_works() { - assert_eq!(is_build_required(SIZE, 0u32.into()), None); - assert_eq!(is_build_required(SIZE, 1u32.into()), None); - assert_eq!(is_build_required(SIZE, SIZE), None); - assert_eq!(is_build_required(SIZE, SIZE + 1), None); - assert_eq!(is_build_required(SIZE, 2 * SIZE), None); - assert_eq!(is_build_required(SIZE, 2 * SIZE + 1), Some(0)); - assert_eq!(is_build_required(SIZE, 2 * SIZE + 2), None); - assert_eq!(is_build_required(SIZE, 3 * SIZE), None); - assert_eq!(is_build_required(SIZE, 3 * SIZE + 1), Some(1)); - assert_eq!(is_build_required(SIZE, 3 * SIZE + 2), None); - } - - #[test] - fn max_cht_number_works() { - assert_eq!(max_cht_number(SIZE, 0u32.into()), None); - assert_eq!(max_cht_number(SIZE, 1u32.into()), None); - assert_eq!(max_cht_number(SIZE, SIZE), None); - assert_eq!(max_cht_number(SIZE, SIZE + 1), None); - assert_eq!(max_cht_number(SIZE, 2 * SIZE), None); - assert_eq!(max_cht_number(SIZE, 2 * SIZE + 1), Some(0)); - assert_eq!(max_cht_number(SIZE, 2 * SIZE + 2), Some(0)); - assert_eq!(max_cht_number(SIZE, 3 * SIZE), Some(0)); - assert_eq!(max_cht_number(SIZE, 3 * SIZE + 1), Some(1)); - assert_eq!(max_cht_number(SIZE, 3 * SIZE + 2), Some(1)); - } - - #[test] - fn start_number_works() { - assert_eq!(start_number(SIZE, 0u32), 1u32); - assert_eq!(start_number(SIZE, 1u32), SIZE + 1); - assert_eq!(start_number(SIZE, 2u32), SIZE + SIZE + 1); - } - - #[test] - fn end_number_works() { - assert_eq!(end_number(SIZE, 0u32), SIZE); - assert_eq!(end_number(SIZE, 1u32), SIZE + SIZE); - assert_eq!(end_number(SIZE, 2u32), SIZE + SIZE + SIZE); - } - - #[test] - fn build_pairs_fails_when_no_enough_blocks() { - assert!(build_pairs::( - SIZE as _, - 0, - ::std::iter::repeat_with(|| Ok(Some(H256::from_low_u64_be(1)))).take(SIZE as usize / 2) - ) - .is_err()); - } - - #[test] - fn build_pairs_fails_when_missing_block() { - assert!(build_pairs::( - SIZE as _, - 0, - ::std::iter::repeat_with(|| Ok(Some(H256::from_low_u64_be(1)))) - .take(SIZE as usize / 2) - .chain(::std::iter::once(Ok(None))) - .chain( - ::std::iter::repeat_with(|| Ok(Some(H256::from_low_u64_be(2)))) - .take(SIZE as usize / 2 - 1) - ) - ) - .is_err()); - } - - #[test] - fn compute_root_works() { - assert!(compute_root::( - SIZE as _, - 42, - ::std::iter::repeat_with(|| Ok(Some(H256::from_low_u64_be(1)))).take(SIZE as usize) - ) - .is_ok()); - } - - #[test] - #[should_panic] - fn build_proof_panics_when_querying_wrong_block() { - assert!(build_proof::( - SIZE as _, - 0, - vec![(SIZE * 1000) as u64], - ::std::iter::repeat_with(|| Ok(Some(H256::from_low_u64_be(1)))).take(SIZE as usize) - ) - .is_err()); - } - - #[test] - fn build_proof_works() { - assert!(build_proof::( - SIZE as _, - 0, - vec![(SIZE / 2) as u64], - ::std::iter::repeat_with(|| Ok(Some(H256::from_low_u64_be(1)))).take(SIZE as usize) - ) - .is_ok()); - } - - #[test] - #[should_panic] - fn for_each_cht_group_panics() { - let cht_size = SIZE as u64; - let _ = for_each_cht_group::( - cht_size, - vec![cht_size * 5, cht_size * 2], - |_, _, _| Ok(()), - (), - ); - } - - #[test] - fn for_each_cht_group_works() { - let cht_size = SIZE as u64; - let _ = for_each_cht_group::( - cht_size, - vec![ - cht_size * 2 + 1, - cht_size * 2 + 2, - cht_size * 2 + 5, - cht_size * 4 + 1, - cht_size * 4 + 7, - cht_size * 6 + 1, - ], - |_, cht_num, blocks| { - match cht_num { - 2 => assert_eq!( - blocks, - vec![cht_size * 2 + 1, cht_size * 2 + 2, cht_size * 2 + 5] - ), - 4 => assert_eq!(blocks, vec![cht_size * 4 + 1, cht_size * 4 + 7]), - 6 => assert_eq!(blocks, vec![cht_size * 6 + 1]), - _ => unreachable!(), - } - - Ok(()) - }, - (), - ); - } -} diff --git a/client/api/src/in_mem.rs b/client/api/src/in_mem.rs index 2f4327dfc4e4..39fe9e063d20 100644 --- a/client/api/src/in_mem.rs +++ b/client/api/src/in_mem.rs @@ -29,8 +29,8 @@ use sp_runtime::{ Justification, Justifications, Storage, }; use sp_state_machine::{ - Backend as StateBackend, ChangesTrieTransaction, ChildStorageCollection, InMemoryBackend, - IndexOperation, StorageCollection, + Backend as StateBackend, ChildStorageCollection, InMemoryBackend, IndexOperation, + StorageCollection, }; use std::{ collections::{HashMap, HashSet}, @@ -39,10 +39,10 @@ use std::{ }; use crate::{ - backend::{self, NewBlockState, ProvideChtRoots}, + backend::{self, NewBlockState}, blockchain::{self, well_known_cache_keys::Id as CacheKeyId, BlockStatus, HeaderBackend}, leaves::LeafSet, - light, UsageInfo, + UsageInfo, }; struct PendingBlock { @@ -109,7 +109,6 @@ struct BlockchainStorage { finalized_number: NumberFor, genesis_hash: Block::Hash, header_cht_roots: HashMap, Block::Hash>, - changes_trie_cht_roots: HashMap, Block::Hash>, leaves: LeafSet>, aux: HashMap, Vec>, } @@ -152,7 +151,6 @@ impl Blockchain { finalized_number: Zero::zero(), genesis_hash: Default::default(), header_cht_roots: HashMap::new(), - changes_trie_cht_roots: HashMap::new(), leaves: LeafSet::new(), aux: HashMap::new(), })); @@ -442,10 +440,6 @@ impl blockchain::Backend for Blockchain { Ok(self.storage.read().finalized_hash.clone()) } - fn cache(&self) -> Option>> { - None - } - fn leaves(&self) -> sp_blockchain::Result> { Ok(self.storage.read().leaves.hashes()) } @@ -466,12 +460,6 @@ impl blockchain::Backend for Blockchain { } } -impl blockchain::ProvideCache for Blockchain { - fn cache(&self) -> Option>> { - None - } -} - impl backend::AuxStore for Blockchain { fn insert_aux< 'a, @@ -499,82 +487,6 @@ impl backend::AuxStore for Blockchain { } } -impl light::Storage for Blockchain -where - Block::Hash: From<[u8; 32]>, -{ - fn import_header( - &self, - header: Block::Header, - _cache: HashMap>, - state: NewBlockState, - aux_ops: Vec<(Vec, Option>)>, - ) -> sp_blockchain::Result<()> { - let hash = header.hash(); - self.insert(hash, header, None, None, state)?; - - self.write_aux(aux_ops); - Ok(()) - } - - fn set_head(&self, id: BlockId) -> sp_blockchain::Result<()> { - Blockchain::set_head(self, id) - } - - fn last_finalized(&self) -> sp_blockchain::Result { - Ok(self.storage.read().finalized_hash.clone()) - } - - fn finalize_header(&self, id: BlockId) -> sp_blockchain::Result<()> { - Blockchain::finalize_header(self, id, None) - } - - fn cache(&self) -> Option>> { - None - } - - fn usage_info(&self) -> Option { - None - } -} - -impl ProvideChtRoots for Blockchain { - fn header_cht_root( - &self, - _cht_size: NumberFor, - block: NumberFor, - ) -> sp_blockchain::Result> { - self.storage - .read() - .header_cht_roots - .get(&block) - .cloned() - .ok_or_else(|| { - sp_blockchain::Error::Backend(format!("Header CHT for block {} not exists", block)) - }) - .map(Some) - } - - fn changes_trie_cht_root( - &self, - _cht_size: NumberFor, - block: NumberFor, - ) -> sp_blockchain::Result> { - self.storage - .read() - .changes_trie_cht_roots - .get(&block) - .cloned() - .ok_or_else(|| { - sp_blockchain::Error::Backend(format!( - "Changes trie CHT for block {} not exists", - block - )) - }) - .map(Some) - } -} - /// In-memory operation. pub struct BlockImportOperation { pending_block: Option>, @@ -650,13 +562,6 @@ where Ok(()) } - fn update_changes_trie( - &mut self, - _update: ChangesTrieTransaction, NumberFor>, - ) -> sp_blockchain::Result<()> { - Ok(()) - } - fn set_genesis_state( &mut self, storage: Storage, @@ -846,10 +751,6 @@ where None } - fn changes_trie_storage(&self) -> Option<&dyn backend::PrunableStateChangesTrieStorage> { - None - } - fn offchain_storage(&self) -> Option { None } @@ -885,22 +786,6 @@ where impl backend::LocalBackend for Backend where Block::Hash: Ord {} -impl backend::RemoteBackend for Backend -where - Block::Hash: Ord, -{ - fn is_local_state_available(&self, block: &BlockId) -> bool { - self.blockchain - .expect_block_number_from_id(block) - .map(|num| num.is_zero()) - .unwrap_or(false) - } - - fn remote_blockchain(&self) -> Arc> { - unimplemented!() - } -} - /// Check that genesis storage is valid. pub fn check_genesis_storage(storage: &Storage) -> sp_blockchain::Result<()> { if storage.top.iter().any(|(k, _)| well_known_keys::is_child_storage_key(k)) { diff --git a/client/api/src/lib.rs b/client/api/src/lib.rs index f1c78f6603eb..a7029d02cbd4 100644 --- a/client/api/src/lib.rs +++ b/client/api/src/lib.rs @@ -21,19 +21,16 @@ pub mod backend; pub mod call_executor; -pub mod cht; pub mod client; pub mod execution_extensions; pub mod in_mem; pub mod leaves; -pub mod light; pub mod notifications; pub mod proof_provider; pub use backend::*; pub use call_executor::*; pub use client::*; -pub use light::*; pub use notifications::*; pub use proof_provider::*; pub use sp_blockchain as blockchain; diff --git a/client/api/src/light.rs b/client/api/src/light.rs deleted file mode 100644 index 8638ddf741f3..000000000000 --- a/client/api/src/light.rs +++ /dev/null @@ -1,372 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2019-2021 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 . - -//! Substrate light client interfaces - -use std::{ - collections::{BTreeMap, HashMap}, - future::Future, - sync::Arc, -}; - -use crate::{ - backend::{AuxStore, NewBlockState}, - ProvideChtRoots, UsageInfo, -}; -use sp_blockchain::{ - well_known_cache_keys, Cache as BlockchainCache, Error as ClientError, HeaderBackend, - HeaderMetadata, Result as ClientResult, -}; -use sp_core::{storage::PrefixedStorageKey, ChangesTrieConfigurationRange}; -use sp_runtime::{ - generic::BlockId, - traits::{Block as BlockT, Header as HeaderT, NumberFor}, -}; -use sp_state_machine::StorageProof; - -/// Remote call request. -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct RemoteCallRequest { - /// Call at state of given block. - pub block: Header::Hash, - /// Header of block at which call is performed. - pub header: Header, - /// Method to call. - pub method: String, - /// Call data. - pub call_data: Vec, - /// Number of times to retry request. None means that default RETRY_COUNT is used. - pub retry_count: Option, -} - -/// Remote canonical header request. -#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] -pub struct RemoteHeaderRequest { - /// The root of CHT this block is included in. - pub cht_root: Header::Hash, - /// Number of the header to query. - pub block: Header::Number, - /// Number of times to retry request. None means that default RETRY_COUNT is used. - pub retry_count: Option, -} - -/// Remote storage read request. -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct RemoteReadRequest { - /// Read at state of given block. - pub block: Header::Hash, - /// Header of block at which read is performed. - pub header: Header, - /// Storage key to read. - pub keys: Vec>, - /// Number of times to retry request. None means that default RETRY_COUNT is used. - pub retry_count: Option, -} - -/// Remote storage read child request. -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct RemoteReadChildRequest { - /// Read at state of given block. - pub block: Header::Hash, - /// Header of block at which read is performed. - pub header: Header, - /// Storage key for child. - pub storage_key: PrefixedStorageKey, - /// Child storage key to read. - pub keys: Vec>, - /// Number of times to retry request. None means that default RETRY_COUNT is used. - pub retry_count: Option, -} - -/// Remote key changes read request. -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct RemoteChangesRequest { - /// All changes trie configurations that are valid within [first_block; last_block]. - pub changes_trie_configs: Vec>, - /// Query changes from range of blocks, starting (and including) with this hash... - pub first_block: (Header::Number, Header::Hash), - /// ...ending (and including) with this hash. Should come after first_block and - /// be the part of the same fork. - pub last_block: (Header::Number, Header::Hash), - /// Only use digests from blocks up to this hash. Should be last_block OR come - /// after this block and be the part of the same fork. - pub max_block: (Header::Number, Header::Hash), - /// Known changes trie roots for the range of blocks [tries_roots.0..max_block]. - /// Proofs for roots of ascendants of tries_roots.0 are provided by the remote node. - pub tries_roots: (Header::Number, Header::Hash, Vec), - /// Optional Child Storage key to read. - pub storage_key: Option, - /// Storage key to read. - pub key: Vec, - /// Number of times to retry request. None means that default RETRY_COUNT is used. - pub retry_count: Option, -} - -/// Key changes read proof. -#[derive(Debug, PartialEq, Eq)] -pub struct ChangesProof { - /// Max block that has been used in changes query. - pub max_block: Header::Number, - /// All touched nodes of all changes tries. - pub proof: Vec>, - /// All changes tries roots that have been touched AND are missing from - /// the requester' node. It is a map of block number => changes trie root. - pub roots: BTreeMap, - /// The proofs for all changes tries roots that have been touched AND are - /// missing from the requester' node. It is a map of CHT number => proof. - pub roots_proof: StorageProof, -} - -/// Remote block body request -#[derive(Clone, Default, Debug, PartialEq, Eq, Hash)] -pub struct RemoteBodyRequest { - /// Header of the requested block body - pub header: Header, - /// Number of times to retry request. None means that default RETRY_COUNT is used. - pub retry_count: Option, -} - -/// Light client data fetcher. Implementations of this trait must check if remote data -/// is correct (see FetchedDataChecker) and return already checked data. -pub trait Fetcher: Send + Sync { - /// Remote header future. - type RemoteHeaderResult: Future> - + Unpin - + Send - + 'static; - /// Remote storage read future. - type RemoteReadResult: Future, Option>>, ClientError>> - + Unpin - + Send - + 'static; - /// Remote call result future. - type RemoteCallResult: Future, ClientError>> + Unpin + Send + 'static; - /// Remote changes result future. - type RemoteChangesResult: Future, u32)>, ClientError>> - + Unpin - + Send - + 'static; - /// Remote block body result future. - type RemoteBodyResult: Future, ClientError>> - + Unpin - + Send - + 'static; - - /// Fetch remote header. - fn remote_header( - &self, - request: RemoteHeaderRequest, - ) -> Self::RemoteHeaderResult; - /// Fetch remote storage value. - fn remote_read(&self, request: RemoteReadRequest) -> Self::RemoteReadResult; - /// Fetch remote storage child value. - fn remote_read_child( - &self, - request: RemoteReadChildRequest, - ) -> Self::RemoteReadResult; - /// Fetch remote call result. - fn remote_call(&self, request: RemoteCallRequest) -> Self::RemoteCallResult; - /// Fetch remote changes ((block number, extrinsic index)) where given key has been changed - /// at a given blocks range. - fn remote_changes( - &self, - request: RemoteChangesRequest, - ) -> Self::RemoteChangesResult; - /// Fetch remote block body - fn remote_body(&self, request: RemoteBodyRequest) -> Self::RemoteBodyResult; -} - -/// Light client remote data checker. -/// -/// Implementations of this trait should not use any prunable blockchain data -/// except that is passed to its methods. -pub trait FetchChecker: Send + Sync { - /// Check remote header proof. - fn check_header_proof( - &self, - request: &RemoteHeaderRequest, - header: Option, - remote_proof: StorageProof, - ) -> ClientResult; - /// Check remote storage read proof. - fn check_read_proof( - &self, - request: &RemoteReadRequest, - remote_proof: StorageProof, - ) -> ClientResult, Option>>>; - /// Check remote storage read proof. - fn check_read_child_proof( - &self, - request: &RemoteReadChildRequest, - remote_proof: StorageProof, - ) -> ClientResult, Option>>>; - /// Check remote method execution proof. - fn check_execution_proof( - &self, - request: &RemoteCallRequest, - remote_proof: StorageProof, - ) -> ClientResult>; - /// Check remote changes query proof. - fn check_changes_proof( - &self, - request: &RemoteChangesRequest, - proof: ChangesProof, - ) -> ClientResult, u32)>>; - /// Check remote body proof. - fn check_body_proof( - &self, - request: &RemoteBodyRequest, - body: Vec, - ) -> ClientResult>; -} - -/// Light client blockchain storage. -pub trait Storage: - AuxStore - + HeaderBackend - + HeaderMetadata - + ProvideChtRoots -{ - /// Store new header. Should refuse to revert any finalized blocks. - /// - /// Takes new authorities, the leaf state of the new block, and - /// any auxiliary storage updates to place in the same operation. - fn import_header( - &self, - header: Block::Header, - cache: HashMap>, - state: NewBlockState, - aux_ops: Vec<(Vec, Option>)>, - ) -> ClientResult<()>; - - /// Set an existing block as new best block. - fn set_head(&self, block: BlockId) -> ClientResult<()>; - - /// Mark historic header as finalized. - fn finalize_header(&self, block: BlockId) -> ClientResult<()>; - - /// Get last finalized header. - fn last_finalized(&self) -> ClientResult; - - /// Get storage cache. - fn cache(&self) -> Option>>; - - /// Get storage usage statistics. - fn usage_info(&self) -> Option; -} - -/// Remote header. -#[derive(Debug)] -pub enum LocalOrRemote { - /// When data is available locally, it is returned. - Local(Data), - /// When data is unavailable locally, the request to fetch it from remote node is returned. - Remote(Request), - /// When data is unknown. - Unknown, -} - -/// Futures-based blockchain backend that either resolves blockchain data -/// locally, or fetches required data from remote node. -pub trait RemoteBlockchain: Send + Sync { - /// Get block header. - fn header( - &self, - id: BlockId, - ) -> ClientResult>>; -} - -/// Returns future that resolves header either locally, or remotely. -pub fn future_header>( - blockchain: &dyn RemoteBlockchain, - fetcher: &F, - id: BlockId, -) -> impl Future, ClientError>> { - use futures::future::{ready, Either, FutureExt}; - - match blockchain.header(id) { - Ok(LocalOrRemote::Remote(request)) => - Either::Left(fetcher.remote_header(request).then(|header| ready(header.map(Some)))), - Ok(LocalOrRemote::Unknown) => Either::Right(ready(Ok(None))), - Ok(LocalOrRemote::Local(local_header)) => Either::Right(ready(Ok(Some(local_header)))), - Err(err) => Either::Right(ready(Err(err))), - } -} - -#[cfg(test)] -pub mod tests { - use super::*; - use futures::future::Ready; - use parking_lot::Mutex; - use sp_blockchain::Error as ClientError; - use sp_test_primitives::{Block, Extrinsic, Header}; - - #[derive(Debug, thiserror::Error)] - #[error("Not implemented on test node")] - struct MockError; - - impl Into for MockError { - fn into(self) -> ClientError { - ClientError::Application(Box::new(self)) - } - } - - pub type OkCallFetcher = Mutex>; - - fn not_implemented_in_tests() -> Ready> { - futures::future::ready(Err(MockError.into())) - } - - impl Fetcher for OkCallFetcher { - type RemoteHeaderResult = Ready>; - type RemoteReadResult = Ready, Option>>, ClientError>>; - type RemoteCallResult = Ready, ClientError>>; - type RemoteChangesResult = Ready, u32)>, ClientError>>; - type RemoteBodyResult = Ready, ClientError>>; - - fn remote_header(&self, _request: RemoteHeaderRequest

) -> Self::RemoteHeaderResult { - not_implemented_in_tests() - } - - fn remote_read(&self, _request: RemoteReadRequest
) -> Self::RemoteReadResult { - not_implemented_in_tests() - } - - fn remote_read_child( - &self, - _request: RemoteReadChildRequest
, - ) -> Self::RemoteReadResult { - not_implemented_in_tests() - } - - fn remote_call(&self, _request: RemoteCallRequest
) -> Self::RemoteCallResult { - futures::future::ready(Ok((*self.lock()).clone())) - } - - fn remote_changes( - &self, - _request: RemoteChangesRequest
, - ) -> Self::RemoteChangesResult { - not_implemented_in_tests() - } - - fn remote_body(&self, _request: RemoteBodyRequest
) -> Self::RemoteBodyResult { - not_implemented_in_tests() - } - } -} diff --git a/client/api/src/proof_provider.rs b/client/api/src/proof_provider.rs index 75f9c55e134d..6207139f9758 100644 --- a/client/api/src/proof_provider.rs +++ b/client/api/src/proof_provider.rs @@ -17,10 +17,10 @@ // along with this program. If not, see . //! Proof utilities -use crate::{ChangesProof, CompactProof, StorageProof}; +use crate::{CompactProof, StorageProof}; use sp_runtime::{generic::BlockId, traits::Block as BlockT}; use sp_state_machine::{KeyValueStates, KeyValueStorageLevel}; -use sp_storage::{ChildInfo, PrefixedStorageKey, StorageKey}; +use sp_storage::ChildInfo; /// Interface for providing block proving utilities. pub trait ProofProvider { @@ -50,27 +50,6 @@ pub trait ProofProvider { method: &str, call_data: &[u8], ) -> sp_blockchain::Result<(Vec, StorageProof)>; - /// Reads given header and generates CHT-based header proof. - fn header_proof( - &self, - id: &BlockId, - ) -> sp_blockchain::Result<(Block::Header, StorageProof)>; - - /// Get proof for computation of (block, extrinsic) pairs where key has been changed at given - /// blocks range. `min` is the hash of the first block, which changes trie root is known to the - /// requester - when we're using changes tries from ascendants of this block, we should provide - /// proofs for changes tries roots `max` is the hash of the last block known to the requester - - /// we can't use changes tries from descendants of this block. - /// Works only for runtimes that are supporting changes tries. - fn key_changes_proof( - &self, - first: Block::Hash, - last: Block::Hash, - min: Block::Hash, - max: Block::Hash, - storage_key: Option<&PrefixedStorageKey>, - key: &StorageKey, - ) -> sp_blockchain::Result>; /// Given a `BlockId` iterate over all storage values starting at `start_keys`. /// Last `start_keys` element contains last accessed key value. diff --git a/client/basic-authorship/src/basic_authorship.rs b/client/basic-authorship/src/basic_authorship.rs index 305c4d753c1e..4c7f6c856ec8 100644 --- a/client/basic-authorship/src/basic_authorship.rs +++ b/client/basic-authorship/src/basic_authorship.rs @@ -41,7 +41,8 @@ use sp_core::traits::SpawnNamed; use sp_inherents::InherentData; use sp_runtime::{ generic::BlockId, - traits::{BlakeTwo256, Block as BlockT, DigestFor, Hash as HashT, Header as HeaderT}, + traits::{BlakeTwo256, Block as BlockT, Hash as HashT, Header as HeaderT}, + Digest, }; use std::{marker::PhantomData, pin::Pin, sync::Arc, time}; @@ -261,7 +262,7 @@ where fn propose( self, inherent_data: InherentData, - inherent_digests: DigestFor, + inherent_digests: Digest, max_duration: time::Duration, block_size_limit: Option, ) -> Self::Proposal { @@ -310,7 +311,7 @@ where async fn propose_with( self, inherent_data: InherentData, - inherent_digests: DigestFor, + inherent_digests: Digest, deadline: time::Instant, block_size_limit: Option, ) -> Result, PR::Proof>, sp_blockchain::Error> @@ -690,13 +691,8 @@ mod tests { api.execute_block(&block_id, proposal.block).unwrap(); let state = backend.state_at(block_id).unwrap(); - let changes_trie_state = - backend::changes_tries_state_at_block(&block_id, backend.changes_trie_storage()) - .unwrap(); - let storage_changes = api - .into_storage_changes(&state, changes_trie_state.as_ref(), genesis_hash) - .unwrap(); + let storage_changes = api.into_storage_changes(&state, genesis_hash).unwrap(); assert_eq!( proposal.storage_changes.transaction_storage_root, diff --git a/client/block-builder/src/lib.rs b/client/block-builder/src/lib.rs index e89421edfb16..01afaca0cacf 100644 --- a/client/block-builder/src/lib.rs +++ b/client/block-builder/src/lib.rs @@ -35,7 +35,8 @@ use sp_blockchain::{ApplyExtrinsicFailed, Error}; use sp_core::ExecutionContext; use sp_runtime::{ generic::BlockId, - traits::{Block as BlockT, DigestFor, Hash, HashFor, Header as HeaderT, NumberFor, One}, + traits::{Block as BlockT, Hash, HashFor, Header as HeaderT, NumberFor, One}, + Digest, }; pub use sp_block_builder::BlockBuilder as BlockBuilderApi; @@ -119,14 +120,14 @@ where fn new_block_at>( &self, parent: &BlockId, - inherent_digests: DigestFor, + inherent_digests: Digest, record_proof: R, ) -> sp_blockchain::Result>; /// Create a new block, built on the head of the chain. fn new_block( &self, - inherent_digests: DigestFor, + inherent_digests: Digest, ) -> sp_blockchain::Result>; } @@ -159,7 +160,7 @@ where parent_hash: Block::Hash, parent_number: NumberFor, record_proof: RecordProof, - inherent_digests: DigestFor, + inherent_digests: Digest, backend: &'a B, ) -> Result { let header = <::Header as HeaderT>::new( @@ -237,15 +238,11 @@ where let proof = self.api.extract_proof(); let state = self.backend.state_at(self.block_id)?; - let changes_trie_state = backend::changes_tries_state_at_block( - &self.block_id, - self.backend.changes_trie_storage(), - )?; let parent_hash = self.parent_hash; let storage_changes = self .api - .into_storage_changes(&state, changes_trie_state.as_ref(), parent_hash) + .into_storage_changes(&state, parent_hash) .map_err(|e| sp_blockchain::Error::StorageChanges(e))?; Ok(BuiltBlock { diff --git a/client/consensus/aura/src/import_queue.rs b/client/consensus/aura/src/import_queue.rs index a4dbe5012ea1..d2c4ad4498d5 100644 --- a/client/consensus/aura/src/import_queue.rs +++ b/client/consensus/aura/src/import_queue.rs @@ -33,7 +33,7 @@ use sp_api::{ApiExt, ProvideRuntimeApi}; use sp_block_builder::BlockBuilder as BlockBuilderApi; use sp_blockchain::{ well_known_cache_keys::{self, Id as CacheKeyId}, - HeaderBackend, ProvideCache, + HeaderBackend, }; use sp_consensus::{CanAuthorWith, Error as ConsensusError}; use sp_consensus_aura::{ @@ -45,7 +45,8 @@ use sp_core::{crypto::Pair, ExecutionContext}; use sp_inherents::{CreateInherentDataProviders, InherentDataProvider as _}; use sp_runtime::{ generic::{BlockId, OpaqueDigestItemId}, - traits::{Block as BlockT, DigestItemFor, Header}, + traits::{Block as BlockT, Header}, + DigestItem, }; use std::{fmt::Debug, hash::Hash, marker::PhantomData, sync::Arc}; @@ -61,9 +62,8 @@ fn check_header( hash: B::Hash, authorities: &[AuthorityId

], check_for_equivocation: CheckForEquivocation, -) -> Result)>, Error> +) -> Result, Error> where - DigestItemFor: CompatibleDigestItem, P::Signature: Codec, C: sc_client_api::backend::AuxStore, P::Public: Encode + Decode + PartialEq + Clone, @@ -189,14 +189,8 @@ where #[async_trait::async_trait] impl Verifier for AuraVerifier where - C: ProvideRuntimeApi - + Send - + Sync - + sc_client_api::backend::AuxStore - + ProvideCache - + BlockOf, + C: ProvideRuntimeApi + Send + Sync + sc_client_api::backend::AuxStore + BlockOf, C::Api: BlockBuilderApi + AuraApi> + ApiExt, - DigestItemFor: CompatibleDigestItem, P: Pair + Send + Sync + 'static, P::Public: Send + Sync + Hash + Eq + Clone + Decode + Encode + Debug + 'static, P::Signature: Encode + Decode, @@ -385,7 +379,6 @@ where C: 'static + ProvideRuntimeApi + BlockOf - + ProvideCache + Send + Sync + AuxStore @@ -395,7 +388,6 @@ where + Send + Sync + 'static, - DigestItemFor: CompatibleDigestItem, P: Pair + Send + Sync + 'static, P::Public: Clone + Eq + Send + Sync + Hash + Debug + Encode + Decode, P::Signature: Encode + Decode, diff --git a/client/consensus/aura/src/lib.rs b/client/consensus/aura/src/lib.rs index 946e0b90c4dd..16880ae188ad 100644 --- a/client/consensus/aura/src/lib.rs +++ b/client/consensus/aura/src/lib.rs @@ -52,7 +52,7 @@ use sc_consensus_slots::{ use sc_telemetry::TelemetryHandle; use sp_api::ProvideRuntimeApi; use sp_application_crypto::{AppKey, AppPublic}; -use sp_blockchain::{HeaderBackend, ProvideCache, Result as CResult}; +use sp_blockchain::{HeaderBackend, Result as CResult}; use sp_consensus::{ BlockOrigin, CanAuthorWith, Environment, Error as ConsensusError, Proposer, SelectChain, }; @@ -62,7 +62,8 @@ use sp_inherents::CreateInherentDataProviders; use sp_keystore::{SyncCryptoStore, SyncCryptoStorePtr}; use sp_runtime::{ generic::BlockId, - traits::{Block as BlockT, DigestItemFor, Header, Member, NumberFor, Zero}, + traits::{Block as BlockT, Header, Member, NumberFor, Zero}, + DigestItem, }; mod import_queue; @@ -178,7 +179,7 @@ where P::Public: AppPublic + Hash + Member + Encode + Decode, P::Signature: TryFrom> + Hash + Member + Encode + Decode, B: BlockT, - C: ProvideRuntimeApi + BlockOf + ProvideCache + AuxStore + HeaderBackend + Send + Sync, + C: ProvideRuntimeApi + BlockOf + AuxStore + HeaderBackend + Send + Sync, C::Api: AuraApi>, SC: SelectChain, I: BlockImport> + Send + Sync + 'static, @@ -267,7 +268,7 @@ pub fn build_aura_worker( ) -> impl sc_consensus_slots::SlotWorker>::Proof> where B: BlockT, - C: ProvideRuntimeApi + BlockOf + ProvideCache + AuxStore + HeaderBackend + Send + Sync, + C: ProvideRuntimeApi + BlockOf + AuxStore + HeaderBackend + Send + Sync, C::Api: AuraApi>, PF: Environment + Send + Sync + 'static, PF::Proposer: Proposer>, @@ -316,7 +317,7 @@ impl sc_consensus_slots::SimpleSlotWorker for AuraWorker where B: BlockT, - C: ProvideRuntimeApi + BlockOf + ProvideCache + HeaderBackend + Sync, + C: ProvideRuntimeApi + BlockOf + HeaderBackend + Sync, C::Api: AuraApi>, E: Environment + Send + Sync, E::Proposer: Proposer>, @@ -377,12 +378,8 @@ where }) } - fn pre_digest_data( - &self, - slot: Slot, - _claim: &Self::Claim, - ) -> Vec> { - vec![ as CompatibleDigestItem>::aura_pre_digest(slot)] + fn pre_digest_data(&self, slot: Slot, _claim: &Self::Claim) -> Vec { + vec![>::aura_pre_digest(slot)] } fn block_import_params( @@ -426,7 +423,7 @@ where .map_err(|_| sp_consensus::Error::InvalidSignature(signature, public))?; let signature_digest_item = - as CompatibleDigestItem>::aura_seal(signature); + >::aura_seal(signature); let mut import_block = BlockImportParams::new(BlockOrigin::Own, header); import_block.post_digests.push(signature_digest_item); @@ -545,7 +542,7 @@ fn authorities(client: &C, at: &BlockId) -> Result, Consensus where A: Codec + Debug, B: BlockT, - C: ProvideRuntimeApi + BlockOf + ProvideCache, + C: ProvideRuntimeApi + BlockOf, C::Api: AuraApi, { client @@ -574,7 +571,10 @@ mod tests { use sp_consensus_aura::sr25519::AuthorityPair; use sp_inherents::InherentData; use sp_keyring::sr25519::Keyring; - use sp_runtime::traits::{Block as BlockT, DigestFor, Header as _}; + use sp_runtime::{ + traits::{Block as BlockT, Header as _}, + Digest, + }; use sp_timestamp::InherentDataProvider as TimestampInherentDataProvider; use std::{ task::Poll, @@ -611,7 +611,7 @@ mod tests { fn propose( self, _: InherentData, - digests: DigestFor, + digests: Digest, _: Duration, _: Option, ) -> Self::Proposal { @@ -661,29 +661,25 @@ mod tests { _cfg: &ProtocolConfig, _peer_data: &(), ) -> Self::Verifier { - match client { - PeersClient::Full(client, _) => { - let slot_duration = slot_duration(&*client).expect("slot duration available"); - - assert_eq!(slot_duration.slot_duration().as_millis() as u64, SLOT_DURATION); - import_queue::AuraVerifier::new( - client, - Box::new(|_, _| async { - let timestamp = TimestampInherentDataProvider::from_system_time(); - let slot = InherentDataProvider::from_timestamp_and_duration( - *timestamp, - Duration::from_secs(6), - ); - - Ok((timestamp, slot)) - }), - AlwaysCanAuthor, - CheckForEquivocation::Yes, - None, - ) - }, - PeersClient::Light(_, _) => unreachable!("No (yet) tests for light client + Aura"), - } + let client = client.as_client(); + let slot_duration = slot_duration(&*client).expect("slot duration available"); + + assert_eq!(slot_duration.slot_duration().as_millis() as u64, SLOT_DURATION); + import_queue::AuraVerifier::new( + client, + Box::new(|_, _| async { + let timestamp = TimestampInherentDataProvider::from_system_time(); + let slot = InherentDataProvider::from_timestamp_and_duration( + *timestamp, + Duration::from_secs(6), + ); + + Ok((timestamp, slot)) + }), + AlwaysCanAuthor, + CheckForEquivocation::Yes, + None, + ) } fn make_block_import( @@ -724,7 +720,7 @@ mod tests { for (peer_id, key) in peers { let mut net = net.lock(); let peer = net.peer(*peer_id); - let client = peer.client().as_full().expect("full clients are created").clone(); + let client = peer.client().as_client(); let select_chain = peer.select_chain().expect("full client has a select chain"); let keystore_path = tempfile::tempdir().expect("Creates keystore path"); let keystore = Arc::new( @@ -823,7 +819,7 @@ mod tests { let mut net = net.lock(); let peer = net.peer(3); - let client = peer.client().as_full().expect("full clients are created").clone(); + let client = peer.client().as_client(); let environ = DummyFactory(client.clone()); let worker = AuraWorker { @@ -875,7 +871,7 @@ mod tests { let mut net = net.lock(); let peer = net.peer(3); - let client = peer.client().as_full().expect("full clients are created").clone(); + let client = peer.client().as_client(); let environ = DummyFactory(client.clone()); let mut worker = AuraWorker { diff --git a/client/consensus/babe/src/lib.rs b/client/consensus/babe/src/lib.rs index 1fde78804115..4fb9f750004c 100644 --- a/client/consensus/babe/src/lib.rs +++ b/client/consensus/babe/src/lib.rs @@ -103,9 +103,7 @@ use sc_telemetry::{telemetry, TelemetryHandle, CONSENSUS_DEBUG, CONSENSUS_TRACE} use sp_api::{ApiExt, NumberFor, ProvideRuntimeApi}; use sp_application_crypto::AppKey; use sp_block_builder::BlockBuilder as BlockBuilderApi; -use sp_blockchain::{ - Error as ClientError, HeaderBackend, HeaderMetadata, ProvideCache, Result as ClientResult, -}; +use sp_blockchain::{Error as ClientError, HeaderBackend, HeaderMetadata, Result as ClientResult}; use sp_consensus::{ BlockOrigin, CacheKeyId, CanAuthorWith, Environment, Error as ConsensusError, Proposer, SelectChain, SlotData, @@ -117,7 +115,8 @@ use sp_inherents::{CreateInherentDataProviders, InherentData, InherentDataProvid use sp_keystore::{SyncCryptoStore, SyncCryptoStorePtr}; use sp_runtime::{ generic::{BlockId, OpaqueDigestItemId}, - traits::{Block as BlockT, DigestItemFor, Header, Zero}, + traits::{Block as BlockT, Header, Zero}, + DigestItem, }; pub use sc_consensus_slots::SlotProportion; @@ -465,7 +464,6 @@ pub fn start_babe( where B: BlockT, C: ProvideRuntimeApi - + ProvideCache + ProvideUncles + BlockchainEvents + HeaderBackend @@ -539,7 +537,6 @@ async fn answer_requests( epoch_changes: SharedEpochChanges, ) where C: ProvideRuntimeApi - + ProvideCache + ProvideUncles + BlockchainEvents + HeaderBackend @@ -677,10 +674,7 @@ impl sc_consensus_slots::SimpleSlotWorker for BabeSlotWorker where B: BlockT, - C: ProvideRuntimeApi - + ProvideCache - + HeaderBackend - + HeaderMetadata, + C: ProvideRuntimeApi + HeaderBackend + HeaderMetadata, C::Api: BabeApi, E: Environment + Sync, E::Proposer: Proposer>, @@ -774,12 +768,8 @@ where }); } - fn pre_digest_data( - &self, - _slot: Slot, - claim: &Self::Claim, - ) -> Vec> { - vec![ as CompatibleDigestItem>::babe_pre_digest(claim.0.clone())] + fn pre_digest_data(&self, _slot: Slot, claim: &Self::Claim) -> Vec { + vec![::babe_pre_digest(claim.0.clone())] } fn block_import_params( @@ -820,8 +810,7 @@ where .clone() .try_into() .map_err(|_| sp_consensus::Error::InvalidSignature(signature, public))?; - let digest_item = - as CompatibleDigestItem>::babe_seal(signature.into()); + let digest_item = ::babe_seal(signature.into()); let mut import_block = BlockImportParams::new(BlockOrigin::Own, header); import_block.post_digests.push(digest_item); @@ -921,10 +910,7 @@ pub fn find_pre_digest(header: &B::Header) -> Result( header: &B::Header, -) -> Result, Error> -where - DigestItemFor: CompatibleDigestItem, -{ +) -> Result, Error> { let mut epoch_digest: Option<_> = None; for log in header.digest().logs() { trace!(target: "babe", "Checking log {:?}, looking for epoch change digest.", log); @@ -943,10 +929,7 @@ where /// Extract the BABE config change digest from the given header, if it exists. fn find_next_config_digest( header: &B::Header, -) -> Result, Error> -where - DigestItemFor: CompatibleDigestItem, -{ +) -> Result, Error> { let mut config_digest: Option<_> = None; for log in header.digest().logs() { trace!(target: "babe", "Checking log {:?}, looking for epoch change digest.", log); @@ -1132,8 +1115,7 @@ where + ProvideRuntimeApi + Send + Sync - + AuxStore - + ProvideCache, + + AuxStore, Client::Api: BlockBuilderApi + BabeApi, SelectChain: sp_consensus::SelectChain, CAW: CanAuthorWith + Send + Sync, @@ -1332,7 +1314,6 @@ where + HeaderMetadata + AuxStore + ProvideRuntimeApi - + ProvideCache + Send + Sync, Client::Api: BabeApi + ApiExt, @@ -1399,7 +1380,6 @@ where + HeaderMetadata + AuxStore + ProvideRuntimeApi - + ProvideCache + Send + Sync, Client::Api: BabeApi + ApiExt, @@ -1756,7 +1736,6 @@ where + Sync + 'static, Client: ProvideRuntimeApi - + ProvideCache + HeaderBackend + HeaderMetadata + AuxStore diff --git a/client/consensus/babe/src/tests.rs b/client/consensus/babe/src/tests.rs index c033f4535be0..73cc453812ea 100644 --- a/client/consensus/babe/src/tests.rs +++ b/client/consensus/babe/src/tests.rs @@ -43,13 +43,13 @@ use sp_consensus_babe::{ use sp_core::crypto::Pair; use sp_keystore::{vrf::make_transcript as transcript_from_data, SyncCryptoStore}; use sp_runtime::{ - generic::DigestItem, - traits::{Block as BlockT, DigestFor}, + generic::{Digest, DigestItem}, + traits::Block as BlockT, }; use sp_timestamp::InherentDataProvider as TimestampInherentDataProvider; use std::{cell::RefCell, task::Poll, time::Duration}; -type Item = DigestItem; +type Item = DigestItem; type Error = sp_blockchain::Error; @@ -108,7 +108,7 @@ impl Environment for DummyFactory { impl DummyProposer { fn propose_with( &mut self, - pre_digests: DigestFor, + pre_digests: Digest, ) -> future::Ready< Result< Proposal< @@ -181,7 +181,7 @@ impl Proposer for DummyProposer { fn propose( mut self, _: InherentData, - pre_digests: DigestFor, + pre_digests: Digest, _: Duration, _: Option, ) -> Self::Proposal { @@ -295,7 +295,7 @@ impl TestNetFactory for BabeTestNet { Option>, Option, ) { - let client = client.as_full().expect("only full clients are tested"); + let client = client.as_client(); let config = Config::get_or_compute(&*client).expect("config available"); let (block_import, link) = crate::block_import(config, client.clone(), client.clone()) @@ -320,7 +320,7 @@ impl TestNetFactory for BabeTestNet { ) -> Self::Verifier { use substrate_test_runtime_client::DefaultTestClientBuilderExt; - let client = client.as_full().expect("only full clients are used in test"); + let client = client.as_client(); trace!(target: "babe", "Creating a verifier"); // ensure block import and verifier are linked correctly. @@ -395,7 +395,7 @@ fn run_one_test(mutator: impl Fn(&mut TestHeader, Stage) + Send + Sync + 'static for (peer_id, seed) in peers { let mut net = net.lock(); let peer = net.peer(*peer_id); - let client = peer.client().as_full().expect("Only full clients are used in tests").clone(); + let client = peer.client().as_client(); let select_chain = peer.select_chain().expect("Full client has select_chain"); let keystore_path = tempfile::tempdir().expect("Creates keystore path"); @@ -679,7 +679,7 @@ fn importing_block_one_sets_genesis_epoch() { let peer = net.peer(0); let data = peer.data.as_ref().expect("babe link set up during initialization"); - let client = peer.client().as_full().expect("Only full clients are used in tests").clone(); + let client = peer.client().as_client(); let mut proposer_factory = DummyFactory { client: client.clone(), @@ -721,7 +721,7 @@ fn importing_epoch_change_block_prunes_tree() { let peer = net.peer(0); let data = peer.data.as_ref().expect("babe link set up during initialization"); - let client = peer.client().as_full().expect("Only full clients are used in tests").clone(); + let client = peer.client().as_client(); let mut block_import = data.block_import.lock().take().expect("import set up during init"); let epoch_changes = data.link.epoch_changes.clone(); @@ -836,7 +836,7 @@ fn verify_slots_are_strictly_increasing() { let peer = net.peer(0); let data = peer.data.as_ref().expect("babe link set up during initialization"); - let client = peer.client().as_full().expect("Only full clients are used in tests").clone(); + let client = peer.client().as_client(); let mut block_import = data.block_import.lock().take().expect("import set up during init"); let mut proposer_factory = DummyFactory { diff --git a/client/consensus/babe/src/verification.rs b/client/consensus/babe/src/verification.rs index af118312dd07..174b2d03c6ef 100644 --- a/client/consensus/babe/src/verification.rs +++ b/client/consensus/babe/src/verification.rs @@ -32,7 +32,7 @@ use sp_consensus_babe::{ }; use sp_consensus_slots::Slot; use sp_core::{Pair, Public}; -use sp_runtime::traits::{DigestItemFor, Header}; +use sp_runtime::{traits::Header, DigestItem}; /// BABE verification parameters pub(super) struct VerificationParams<'a, B: 'a + BlockT> { @@ -61,10 +61,7 @@ pub(super) struct VerificationParams<'a, B: 'a + BlockT> { /// with each having different validation logic. pub(super) fn check_header( params: VerificationParams, -) -> Result>, Error> -where - DigestItemFor: CompatibleDigestItem, -{ +) -> Result, Error> { let VerificationParams { mut header, pre_digest, slot_now, epoch } = params; let authorities = &epoch.authorities; @@ -137,9 +134,9 @@ where Ok(CheckedHeader::Checked(header, info)) } -pub(super) struct VerifiedHeaderInfo { - pub(super) pre_digest: DigestItemFor, - pub(super) seal: DigestItemFor, +pub(super) struct VerifiedHeaderInfo { + pub(super) pre_digest: DigestItem, + pub(super) seal: DigestItem, pub(super) author: AuthorityId, } diff --git a/client/consensus/common/src/block_import.rs b/client/consensus/common/src/block_import.rs index 5294db239604..03fde159736c 100644 --- a/client/consensus/common/src/block_import.rs +++ b/client/consensus/common/src/block_import.rs @@ -20,8 +20,8 @@ use serde::{Deserialize, Serialize}; use sp_runtime::{ - traits::{Block as BlockT, DigestItemFor, HashFor, Header as HeaderT, NumberFor}, - Justification, Justifications, + traits::{Block as BlockT, HashFor, Header as HeaderT, NumberFor}, + DigestItem, Justification, Justifications, }; use std::{any::Any, borrow::Cow, collections::HashMap, sync::Arc}; @@ -122,7 +122,7 @@ pub struct BlockCheckParams { /// Precomputed storage. pub enum StorageChanges { /// Changes coming from block execution. - Changes(sp_state_machine::StorageChanges, NumberFor>), + Changes(sp_state_machine::StorageChanges>), /// Whole new state. Import(ImportedState), } @@ -175,7 +175,7 @@ pub struct BlockImportParams { pub justifications: Option, /// Digest items that have been added after the runtime for external /// work, like a consensus signature. - pub post_digests: Vec>, + pub post_digests: Vec, /// The body of the block. pub body: Option>, /// Indexed transaction body of the block. diff --git a/client/consensus/manual-seal/src/consensus.rs b/client/consensus/manual-seal/src/consensus.rs index 33a4c8616f6d..4284d40179d2 100644 --- a/client/consensus/manual-seal/src/consensus.rs +++ b/client/consensus/manual-seal/src/consensus.rs @@ -21,7 +21,7 @@ use super::Error; use sc_consensus::BlockImportParams; use sp_inherents::InherentData; -use sp_runtime::traits::{Block as BlockT, DigestFor}; +use sp_runtime::{traits::Block as BlockT, Digest}; pub mod babe; @@ -32,11 +32,7 @@ pub trait ConsensusDataProvider: Send + Sync { type Transaction; /// Attempt to create a consensus digest. - fn create_digest( - &self, - parent: &B::Header, - inherents: &InherentData, - ) -> Result, Error>; + fn create_digest(&self, parent: &B::Header, inherents: &InherentData) -> Result; /// set up the neccessary import params. fn append_block_import( diff --git a/client/consensus/manual-seal/src/consensus/babe.rs b/client/consensus/manual-seal/src/consensus/babe.rs index 1d3afe392d62..e06c544aaedc 100644 --- a/client/consensus/manual-seal/src/consensus/babe.rs +++ b/client/consensus/manual-seal/src/consensus/babe.rs @@ -49,7 +49,8 @@ use sp_consensus_slots::Slot; use sp_inherents::{InherentData, InherentDataProvider, InherentIdentifier}; use sp_runtime::{ generic::{BlockId, Digest}, - traits::{Block as BlockT, DigestFor, DigestItemFor, Header, Zero}, + traits::{Block as BlockT, Header, Zero}, + DigestItem, }; use sp_timestamp::{InherentType, TimestampInherentData, INHERENT_IDENTIFIER}; @@ -193,11 +194,7 @@ where { type Transaction = TransactionFor; - fn create_digest( - &self, - parent: &B::Header, - inherents: &InherentData, - ) -> Result, Error> { + fn create_digest(&self, parent: &B::Header, inherents: &InherentData) -> Result { let slot = inherents .babe_inherent_data()? .ok_or_else(|| Error::StringError("No babe inherent data".into()))?; @@ -207,7 +204,7 @@ where let logs = if let Some((predigest, _)) = authorship::claim_slot(slot, &epoch, &self.keystore) { - vec![ as CompatibleDigestItem>::babe_pre_digest(predigest)] + vec![::babe_pre_digest(predigest)] } else { // well we couldn't claim a slot because this is an existing chain and we're not in the // authorities. we need to tell BabeBlockImport that the epoch has changed, and we put @@ -244,13 +241,13 @@ where }); vec![ - DigestItemFor::::PreRuntime(BABE_ENGINE_ID, predigest.encode()), - DigestItemFor::::Consensus(BABE_ENGINE_ID, next_epoch.encode()), + DigestItem::PreRuntime(BABE_ENGINE_ID, predigest.encode()), + DigestItem::Consensus(BABE_ENGINE_ID, next_epoch.encode()), ] }, ViableEpochDescriptor::UnimportedGenesis(_) => { // since this is the genesis, secondary predigest works for now. - vec![DigestItemFor::::PreRuntime(BABE_ENGINE_ID, predigest.encode())] + vec![DigestItem::PreRuntime(BABE_ENGINE_ID, predigest.encode())] }, } }; diff --git a/client/consensus/pow/src/lib.rs b/client/consensus/pow/src/lib.rs index 7b1012888e86..3ab0b977255e 100644 --- a/client/consensus/pow/src/lib.rs +++ b/client/consensus/pow/src/lib.rs @@ -55,7 +55,7 @@ use sc_consensus::{ }; use sp_api::ProvideRuntimeApi; use sp_block_builder::BlockBuilder as BlockBuilderApi; -use sp_blockchain::{well_known_cache_keys::Id as CacheKeyId, HeaderBackend, ProvideCache}; +use sp_blockchain::{well_known_cache_keys::Id as CacheKeyId, HeaderBackend}; use sp_consensus::{ CanAuthorWith, Environment, Error as ConsensusError, Proposer, SelectChain, SyncOracle, }; @@ -240,7 +240,7 @@ where B: BlockT, I: BlockImport> + Send + Sync, I::Error: Into, - C: ProvideRuntimeApi + Send + Sync + HeaderBackend + AuxStore + ProvideCache + BlockOf, + C: ProvideRuntimeApi + Send + Sync + HeaderBackend + AuxStore + BlockOf, C::Api: BlockBuilderApi, Algorithm: PowAlgorithm, CAW: CanAuthorWith, @@ -319,7 +319,7 @@ where I: BlockImport> + Send + Sync, I::Error: Into, S: SelectChain, - C: ProvideRuntimeApi + Send + Sync + HeaderBackend + AuxStore + ProvideCache + BlockOf, + C: ProvideRuntimeApi + Send + Sync + HeaderBackend + AuxStore + BlockOf, C::Api: BlockBuilderApi, Algorithm: PowAlgorithm + Send + Sync, Algorithm::Difficulty: 'static + Send, @@ -425,10 +425,7 @@ impl PowVerifier { Self { algorithm, _marker: PhantomData } } - fn check_header( - &self, - mut header: B::Header, - ) -> Result<(B::Header, DigestItem), Error> + fn check_header(&self, mut header: B::Header) -> Result<(B::Header, DigestItem), Error> where Algorithm: PowAlgorithm, { @@ -630,7 +627,7 @@ where }, }; - let mut inherent_digest = Digest::::default(); + let mut inherent_digest = Digest::default(); if let Some(pre_runtime) = &pre_runtime { inherent_digest.push(DigestItem::PreRuntime(POW_ENGINE_ID, pre_runtime.to_vec())); } @@ -702,10 +699,7 @@ fn find_pre_digest(header: &B::Header) -> Result>, Err } /// Fetch PoW seal. -fn fetch_seal( - digest: Option<&DigestItem>, - hash: B::Hash, -) -> Result, Error> { +fn fetch_seal(digest: Option<&DigestItem>, hash: B::Hash) -> Result, Error> { match digest { Some(DigestItem::Seal(id, seal)) => if id == &POW_ENGINE_ID { diff --git a/client/consensus/slots/src/lib.rs b/client/consensus/slots/src/lib.rs index bfaa388014ef..ead209ef86a6 100644 --- a/client/consensus/slots/src/lib.rs +++ b/client/consensus/slots/src/lib.rs @@ -45,7 +45,7 @@ use sp_consensus_slots::Slot; use sp_inherents::CreateInherentDataProviders; use sp_runtime::{ generic::BlockId, - traits::{Block as BlockT, HashFor, Header as HeaderT, NumberFor}, + traits::{Block as BlockT, HashFor, Header as HeaderT}, }; use sp_timestamp::Timestamp; use std::{fmt::Debug, ops::Deref, time::Duration}; @@ -54,7 +54,7 @@ use std::{fmt::Debug, ops::Deref, time::Duration}; /// /// See [`sp_state_machine::StorageChanges`] for more information. pub type StorageChanges = - sp_state_machine::StorageChanges, NumberFor>; + sp_state_machine::StorageChanges>; /// The result of [`SlotWorker::on_slot`]. #[derive(Debug, Clone)] @@ -141,11 +141,7 @@ pub trait SimpleSlotWorker { fn notify_slot(&self, _header: &B::Header, _slot: Slot, _epoch_data: &Self::EpochData) {} /// Return the pre digest data to include in a block authored with the given claim. - fn pre_digest_data( - &self, - slot: Slot, - claim: &Self::Claim, - ) -> Vec>; + fn pre_digest_data(&self, slot: Slot, claim: &Self::Claim) -> Vec; /// Returns a function which produces a `BlockImportParams`. fn block_import_params( diff --git a/client/db/src/cache/list_cache.rs b/client/db/src/cache/list_cache.rs deleted file mode 100644 index 795cb8f90118..000000000000 --- a/client/db/src/cache/list_cache.rs +++ /dev/null @@ -1,2351 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2017-2021 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 . - -//! List-based cache. -//! -//! Maintains several lists, containing nodes that are inserted whenever -//! cached value at new block differs from the value at previous block. -//! Example: -//! B1(a) <--- B2(b) <--- B3(b) <--- B4(c) -//! N1(b) <-------------- N2(c) -//! -//! There's single list for all finalized blocks and >= 0 lists for unfinalized -//! blocks. -//! When new non-final block is inserted (with value that differs from the value -//! at parent), it starts new unfinalized fork. -//! When new final block is inserted (with value that differs from the value at -//! parent), new entry is appended to the finalized fork. -//! When existing non-final block is finalized (with value that differs from the -//! value at parent), new entry is appended to the finalized fork AND unfinalized -//! fork is dropped. -//! -//! Entries from abandoned unfinalized forks (forks that are forking from block B -//! which is ascendant of the best finalized block) are deleted when block F with -//! number B.number (i.e. 'parallel' canon block) is finalized. -//! -//! Finalized entry E1 is pruned when block B is finalized so that: -//! EntryAt(B.number - prune_depth).points_to(E1) - -use std::collections::{BTreeMap, BTreeSet}; - -use log::warn; - -use sp_blockchain::{Error as ClientError, Result as ClientResult}; -use sp_runtime::traits::{Block as BlockT, Bounded, CheckedSub, NumberFor, Zero}; - -use crate::cache::{ - list_entry::{Entry, StorageEntry}, - list_storage::{Metadata, Storage, StorageTransaction}, - CacheItemT, ComplexBlockId, EntryType, -}; - -/// Pruning strategy. -#[derive(Debug, Clone, Copy)] -pub enum PruningStrategy { - /// Prune entries when they're too far behind best finalized block. - ByDepth(N), - /// Do not prune old entries at all. - NeverPrune, -} - -/// List-based cache. -pub struct ListCache> { - /// Cache storage. - storage: S, - /// Pruning strategy. - pruning_strategy: PruningStrategy>, - /// Best finalized block. - best_finalized_block: ComplexBlockId, - /// Best finalized entry (if exists). - best_finalized_entry: Option>, - /// All unfinalized 'forks'. - unfinalized: Vec>, -} - -/// All possible list cache operations that could be performed after transaction is committed. -#[derive(Debug)] -#[cfg_attr(test, derive(PartialEq))] -pub enum CommitOperation { - /// New block is appended to the fork without changing the cached value. - AppendNewBlock(usize, ComplexBlockId), - /// New block is appended to the fork with the different value. - AppendNewEntry(usize, Entry), - /// New fork is added with the given head entry. - AddNewFork(Entry), - /// New block is finalized and possibly: - /// - new entry is finalized AND/OR - /// - some forks are destroyed - BlockFinalized(ComplexBlockId, Option>, BTreeSet), - /// When best block is reverted - contains the forks that have to be updated - /// (they're either destroyed, or their best entry is updated to earlier block). - BlockReverted(BTreeMap>>), -} - -/// A set of commit operations. -#[derive(Debug)] -pub struct CommitOperations { - operations: Vec>, -} - -/// Single fork of list-based cache. -#[derive(Debug)] -#[cfg_attr(test, derive(PartialEq))] -pub struct Fork { - /// The best block of this fork. We do not save this field in the database to avoid - /// extra updates => it could be None after restart. It will be either filled when - /// the block is appended to this fork, or the whole fork will be abandoned when the - /// block from the other fork is finalized - best_block: Option>, - /// The head entry of this fork. - head: Entry, -} - -/// Outcome of Fork::try_append_or_fork. -#[derive(Debug)] -#[cfg_attr(test, derive(PartialEq))] -pub enum ForkAppendResult { - /// New entry should be appended to the end of the fork. - Append, - /// New entry should be forked from the fork, starting with entry at given block. - Fork(ComplexBlockId), -} - -impl> ListCache { - /// Create new db list cache entry. - pub fn new( - storage: S, - pruning_strategy: PruningStrategy>, - best_finalized_block: ComplexBlockId, - ) -> ClientResult { - let (best_finalized_entry, unfinalized) = - storage.read_meta().and_then(|meta| read_forks(&storage, meta))?; - - Ok(ListCache { - storage, - pruning_strategy, - best_finalized_block, - best_finalized_entry, - unfinalized, - }) - } - - /// Get reference to the storage. - pub fn storage(&self) -> &S { - &self.storage - } - - /// Get unfinalized forks reference. - #[cfg(test)] - pub fn unfinalized(&self) -> &[Fork] { - &self.unfinalized - } - - /// Get value valid at block. - pub fn value_at_block( - &self, - at: &ComplexBlockId, - ) -> ClientResult, Option>, T)>> { - let head = if at.number <= self.best_finalized_block.number { - // if the block is older than the best known finalized block - // => we're should search for the finalized value - - // BUT since we're not guaranteeing to provide correct values for forks - // behind the finalized block, check if the block is finalized first - if !chain::is_finalized_block(&self.storage, &at, Bounded::max_value())? { - return Err(ClientError::NotInFinalizedChain) - } - - self.best_finalized_entry.as_ref() - } else if self.unfinalized.is_empty() { - // there are no unfinalized entries - // => we should search for the finalized value - self.best_finalized_entry.as_ref() - } else { - // there are unfinalized entries - // => find the fork containing given block and read from this fork - // IF there's no matching fork, ensure that this isn't a block from a fork that has - // forked behind the best finalized block and search at finalized fork - - match self.find_unfinalized_fork(&at)? { - Some(fork) => Some(&fork.head), - None => match self.best_finalized_entry.as_ref() { - Some(best_finalized_entry) - if chain::is_connected_to_block( - &self.storage, - &at, - &best_finalized_entry.valid_from, - )? => - Some(best_finalized_entry), - _ => None, - }, - } - }; - - match head { - Some(head) => head - .search_best_before(&self.storage, at.number) - .map(|e| e.map(|e| (e.0.valid_from, e.1, e.0.value))), - None => Ok(None), - } - } - - /// When new block is inserted into database. - /// - /// None passed as value means that the value has not changed since previous block. - pub fn on_block_insert>( - &self, - tx: &mut Tx, - parent: ComplexBlockId, - block: ComplexBlockId, - value: Option, - entry_type: EntryType, - operations: &mut CommitOperations, - ) -> ClientResult<()> { - Ok(operations - .append(self.do_on_block_insert(tx, parent, block, value, entry_type, operations)?)) - } - - /// When previously inserted block is finalized. - pub fn on_block_finalize>( - &self, - tx: &mut Tx, - parent: ComplexBlockId, - block: ComplexBlockId, - operations: &mut CommitOperations, - ) -> ClientResult<()> { - Ok(operations.append(self.do_on_block_finalize(tx, parent, block, operations)?)) - } - - /// When block is reverted. - pub fn on_block_revert>( - &self, - tx: &mut Tx, - reverted_block: &ComplexBlockId, - operations: &mut CommitOperations, - ) -> ClientResult<()> { - Ok(operations.append(Some(self.do_on_block_revert(tx, reverted_block)?))) - } - - /// When transaction is committed. - pub fn on_transaction_commit(&mut self, ops: CommitOperations) { - for op in ops.operations { - match op { - CommitOperation::AppendNewBlock(index, best_block) => { - let mut fork = self.unfinalized.get_mut(index).expect( - "ListCache is a crate-private type; - internal clients of ListCache are committing transaction while cache is locked; - CommitOperation holds valid references while cache is locked; qed", - ); - fork.best_block = Some(best_block); - }, - CommitOperation::AppendNewEntry(index, entry) => { - let mut fork = self.unfinalized.get_mut(index).expect( - "ListCache is a crate-private type; - internal clients of ListCache are committing transaction while cache is locked; - CommitOperation holds valid references while cache is locked; qed", - ); - fork.best_block = Some(entry.valid_from.clone()); - fork.head = entry; - }, - CommitOperation::AddNewFork(entry) => { - self.unfinalized - .push(Fork { best_block: Some(entry.valid_from.clone()), head: entry }); - }, - CommitOperation::BlockFinalized(block, finalizing_entry, forks) => { - self.best_finalized_block = block; - if let Some(finalizing_entry) = finalizing_entry { - self.best_finalized_entry = Some(finalizing_entry); - } - for fork_index in forks.iter().rev() { - self.unfinalized.remove(*fork_index); - } - }, - CommitOperation::BlockReverted(forks) => { - for (fork_index, updated_fork) in forks.into_iter().rev() { - match updated_fork { - Some(updated_fork) => self.unfinalized[fork_index] = updated_fork, - None => { - self.unfinalized.remove(fork_index); - }, - } - } - }, - } - } - } - - fn do_on_block_insert>( - &self, - tx: &mut Tx, - parent: ComplexBlockId, - block: ComplexBlockId, - value: Option, - entry_type: EntryType, - operations: &CommitOperations, - ) -> ClientResult>> { - // this guarantee is currently provided by LightStorage && we're relying on it here - let prev_operation = operations.operations.last(); - debug_assert!( - entry_type != EntryType::Final || - self.unfinalized.is_empty() || - self.best_finalized_block.hash == parent.hash || - match prev_operation { - Some(&CommitOperation::BlockFinalized(ref best_finalized_block, _, _)) => - best_finalized_block.hash == parent.hash, - _ => false, - } - ); - - // we do not store any values behind finalized - if block.number != Zero::zero() && self.best_finalized_block.number >= block.number { - return Ok(None) - } - - // if the block is not final, it is possibly appended to/forking from existing unfinalized - // fork - let is_final = entry_type == EntryType::Final || entry_type == EntryType::Genesis; - if !is_final { - let mut fork_and_action = None; - - // when value hasn't changed and block isn't final, there's nothing we need to do - if value.is_none() { - return Ok(None) - } - - // first: try to find fork that is known to has the best block we're appending to - for (index, fork) in self.unfinalized.iter().enumerate() { - if fork.try_append(&parent) { - fork_and_action = Some((index, ForkAppendResult::Append)); - break - } - } - - // if not found, check cases: - // - we're appending to the fork for the first time after restart; - // - we're forking existing unfinalized fork from the middle; - if fork_and_action.is_none() { - let best_finalized_entry_block = - self.best_finalized_entry.as_ref().map(|f| f.valid_from.number); - for (index, fork) in self.unfinalized.iter().enumerate() { - if let Some(action) = - fork.try_append_or_fork(&self.storage, &parent, best_finalized_entry_block)? - { - fork_and_action = Some((index, action)); - break - } - } - } - - // if we have found matching unfinalized fork => early exit - match fork_and_action { - // append to unfinalized fork - Some((index, ForkAppendResult::Append)) => { - let new_storage_entry = match self.unfinalized[index].head.try_update(value) { - Some(new_storage_entry) => new_storage_entry, - None => return Ok(Some(CommitOperation::AppendNewBlock(index, block))), - }; - - tx.insert_storage_entry(&block, &new_storage_entry); - let operation = - CommitOperation::AppendNewEntry(index, new_storage_entry.into_entry(block)); - tx.update_meta( - self.best_finalized_entry.as_ref(), - &self.unfinalized, - &operation, - ); - return Ok(Some(operation)) - }, - // fork from the middle of unfinalized fork - Some((_, ForkAppendResult::Fork(prev_valid_from))) => { - // it is possible that we're inserting extra (but still required) fork here - let new_storage_entry = StorageEntry { - prev_valid_from: Some(prev_valid_from), - value: value.expect("checked above that !value.is_none(); qed"), - }; - - tx.insert_storage_entry(&block, &new_storage_entry); - let operation = - CommitOperation::AddNewFork(new_storage_entry.into_entry(block)); - tx.update_meta( - self.best_finalized_entry.as_ref(), - &self.unfinalized, - &operation, - ); - return Ok(Some(operation)) - }, - None => (), - } - } - - // if we're here, then one of following is true: - // - either we're inserting final block => all ancestors are already finalized AND the only - // thing we can do is to try to update last finalized entry - // - either we're inserting non-final blocks that has no ancestors in any known unfinalized - // forks - - let new_storage_entry = match self.best_finalized_entry.as_ref() { - Some(best_finalized_entry) => best_finalized_entry.try_update(value), - None if value.is_some() => Some(StorageEntry { - prev_valid_from: None, - value: value.expect("value.is_some(); qed"), - }), - None => None, - }; - - if !is_final { - return Ok(match new_storage_entry { - Some(new_storage_entry) => { - tx.insert_storage_entry(&block, &new_storage_entry); - let operation = - CommitOperation::AddNewFork(new_storage_entry.into_entry(block)); - tx.update_meta( - self.best_finalized_entry.as_ref(), - &self.unfinalized, - &operation, - ); - Some(operation) - }, - None => None, - }) - } - - // cleanup database from abandoned unfinalized forks and obsolete finalized entries - let abandoned_forks = self.destroy_abandoned_forks(tx, &block, prev_operation); - self.prune_finalized_entries(tx, &block); - - match new_storage_entry { - Some(new_storage_entry) => { - tx.insert_storage_entry(&block, &new_storage_entry); - let operation = CommitOperation::BlockFinalized( - block.clone(), - Some(new_storage_entry.into_entry(block)), - abandoned_forks, - ); - tx.update_meta(self.best_finalized_entry.as_ref(), &self.unfinalized, &operation); - Ok(Some(operation)) - }, - None => Ok(Some(CommitOperation::BlockFinalized(block, None, abandoned_forks))), - } - } - - fn do_on_block_finalize>( - &self, - tx: &mut Tx, - parent: ComplexBlockId, - block: ComplexBlockId, - operations: &CommitOperations, - ) -> ClientResult>> { - // this guarantee is currently provided by db backend && we're relying on it here - let prev_operation = operations.operations.last(); - debug_assert!( - self.best_finalized_block.hash == parent.hash || - match prev_operation { - Some(&CommitOperation::BlockFinalized(ref best_finalized_block, _, _)) => - best_finalized_block.hash == parent.hash, - _ => false, - } - ); - - // there could be at most one entry that is finalizing - let finalizing_entry = - self.storage.read_entry(&block)?.map(|entry| entry.into_entry(block.clone())); - - // cleanup database from abandoned unfinalized forks and obsolete finalized entries - let abandoned_forks = self.destroy_abandoned_forks(tx, &block, prev_operation); - self.prune_finalized_entries(tx, &block); - - let operation = CommitOperation::BlockFinalized(block, finalizing_entry, abandoned_forks); - tx.update_meta(self.best_finalized_entry.as_ref(), &self.unfinalized, &operation); - - Ok(Some(operation)) - } - - fn do_on_block_revert>( - &self, - tx: &mut Tx, - reverted_block: &ComplexBlockId, - ) -> ClientResult> { - // can't revert finalized blocks - debug_assert!(self.best_finalized_block.number < reverted_block.number); - - // iterate all unfinalized forks and truncate/destroy if required - let mut updated = BTreeMap::new(); - for (index, fork) in self.unfinalized.iter().enumerate() { - // we only need to truncate fork if its head is ancestor of truncated block - if fork.head.valid_from.number < reverted_block.number { - continue - } - - // we only need to truncate fork if its head is connected to truncated block - if !chain::is_connected_to_block(&self.storage, reverted_block, &fork.head.valid_from)? - { - continue - } - - let updated_fork = fork.truncate( - &self.storage, - tx, - reverted_block.number, - self.best_finalized_block.number, - )?; - updated.insert(index, updated_fork); - } - - // schedule commit operation and update meta - let operation = CommitOperation::BlockReverted(updated); - tx.update_meta(self.best_finalized_entry.as_ref(), &self.unfinalized, &operation); - - Ok(operation) - } - - /// Prune old finalized entries. - fn prune_finalized_entries>( - &self, - tx: &mut Tx, - block: &ComplexBlockId, - ) { - let prune_depth = match self.pruning_strategy { - PruningStrategy::ByDepth(prune_depth) => prune_depth, - PruningStrategy::NeverPrune => return, - }; - - let mut do_pruning = || -> ClientResult<()> { - // calculate last ancient block number - let ancient_block = match block.number.checked_sub(&prune_depth) { - Some(number) => match self.storage.read_id(number)? { - Some(hash) => ComplexBlockId::new(hash, number), - None => return Ok(()), - }, - None => return Ok(()), - }; - - // if there's an entry at this block: - // - remove reference from this entry to the previous entry - // - destroy fork starting with previous entry - let current_entry = match self.storage.read_entry(&ancient_block)? { - Some(current_entry) => current_entry, - None => return Ok(()), - }; - let first_entry_to_truncate = match current_entry.prev_valid_from { - Some(prev_valid_from) => prev_valid_from, - None => return Ok(()), - }; - - // truncate ancient entry - tx.insert_storage_entry( - &ancient_block, - &StorageEntry { prev_valid_from: None, value: current_entry.value }, - ); - - // destroy 'fork' ending with previous entry - destroy_fork(first_entry_to_truncate, &self.storage, tx, None) - }; - - if let Err(error) = do_pruning() { - warn!(target: "db", "Failed to prune ancient cache entries: {}", error); - } - } - - /// Try to destroy abandoned forks (forked before best finalized block) when block is finalized. - fn destroy_abandoned_forks>( - &self, - tx: &mut Tx, - block: &ComplexBlockId, - prev_operation: Option<&CommitOperation>, - ) -> BTreeSet { - // if some block has been finalized already => take it into account - let prev_abandoned_forks = match prev_operation { - Some(&CommitOperation::BlockFinalized(_, _, ref abandoned_forks)) => - Some(abandoned_forks), - _ => None, - }; - - let mut destroyed = prev_abandoned_forks.cloned().unwrap_or_else(|| BTreeSet::new()); - let live_unfinalized = self.unfinalized.iter().enumerate().filter(|(idx, _)| { - prev_abandoned_forks - .map(|prev_abandoned_forks| !prev_abandoned_forks.contains(idx)) - .unwrap_or(true) - }); - for (index, fork) in live_unfinalized { - if fork.head.valid_from.number == block.number { - destroyed.insert(index); - if fork.head.valid_from.hash != block.hash { - if let Err(error) = fork.destroy(&self.storage, tx, Some(block.number)) { - warn!(target: "db", "Failed to destroy abandoned unfinalized cache fork: {}", error); - } - } - } - } - - destroyed - } - - /// Search unfinalized fork where given block belongs. - fn find_unfinalized_fork( - &self, - block: &ComplexBlockId, - ) -> ClientResult>> { - for unfinalized in &self.unfinalized { - if unfinalized.matches(&self.storage, block)? { - return Ok(Some(&unfinalized)) - } - } - - Ok(None) - } -} - -impl Fork { - /// Get reference to the head entry of this fork. - pub fn head(&self) -> &Entry { - &self.head - } - - /// Check if the block is the part of the fork. - pub fn matches>( - &self, - storage: &S, - block: &ComplexBlockId, - ) -> ClientResult { - let range = self.head.search_best_range_before(storage, block.number)?; - match range { - None => Ok(false), - Some((begin, end)) => - chain::is_connected_to_range(storage, block, (&begin, end.as_ref())), - } - } - - /// Try to append NEW block to the fork. This method will only 'work' (return true) when block - /// is actually appended to the fork AND the best known block of the fork is known (i.e. some - /// block has been already appended to this fork after last restart). - pub fn try_append(&self, parent: &ComplexBlockId) -> bool { - // when the best block of the fork is known, the check is trivial - // - // most of calls will hopefully end here, because best_block is only unknown - // after restart and until new block is appended to the fork - self.best_block.as_ref() == Some(parent) - } - - /// Try to append new block to the fork OR fork it. - pub fn try_append_or_fork>( - &self, - storage: &S, - parent: &ComplexBlockId, - best_finalized_entry_block: Option>, - ) -> ClientResult>> { - // try to find entries that are (possibly) surrounding the parent block - let range = self.head.search_best_range_before(storage, parent.number)?; - let begin = match range { - Some((begin, _)) => begin, - None => return Ok(None), - }; - - // check if the parent is connected to the beginning of the range - if !chain::is_connected_to_block(storage, parent, &begin)? { - return Ok(None) - } - - // the block is connected to the begin-entry. If begin is the head entry - // => we need to append new block to the fork - if begin == self.head.valid_from { - return Ok(Some(ForkAppendResult::Append)) - } - - // the parent block belongs to this fork AND it is located after last finalized entry - // => we need to make a new fork - if best_finalized_entry_block.map(|f| begin.number > f).unwrap_or(true) { - return Ok(Some(ForkAppendResult::Fork(begin))) - } - - Ok(None) - } - - /// Destroy fork by deleting all unfinalized entries. - pub fn destroy, Tx: StorageTransaction>( - &self, - storage: &S, - tx: &mut Tx, - best_finalized_block: Option>, - ) -> ClientResult<()> { - destroy_fork(self.head.valid_from.clone(), storage, tx, best_finalized_block) - } - - /// Truncate fork by deleting all entries that are descendants of given block. - pub fn truncate, Tx: StorageTransaction>( - &self, - storage: &S, - tx: &mut Tx, - reverting_block: NumberFor, - best_finalized_block: NumberFor, - ) -> ClientResult>> { - let mut current = self.head.valid_from.clone(); - loop { - // read pointer to previous entry - let entry = storage.require_entry(¤t)?; - - // truncation stops when we have reached the ancestor of truncated block - if current.number < reverting_block { - // if we have reached finalized block => destroy fork - if chain::is_finalized_block(storage, ¤t, best_finalized_block)? { - return Ok(None) - } - - // else fork needs to be updated - return Ok(Some(Fork { best_block: None, head: entry.into_entry(current) })) - } - - tx.remove_storage_entry(¤t); - - // truncation also stops when there are no more entries in the list - current = match entry.prev_valid_from { - Some(prev_valid_from) => prev_valid_from, - None => return Ok(None), - }; - } - } -} - -impl Default for CommitOperations { - fn default() -> Self { - CommitOperations { operations: Vec::new() } - } -} - -// This should never be allowed for non-test code to avoid revealing its internals. -#[cfg(test)] -impl From>> - for CommitOperations -{ - fn from(operations: Vec>) -> Self { - CommitOperations { operations } - } -} - -impl CommitOperations { - /// Append operation to the set. - fn append(&mut self, new_operation: Option>) { - let new_operation = match new_operation { - Some(new_operation) => new_operation, - None => return, - }; - - let last_operation = match self.operations.pop() { - Some(last_operation) => last_operation, - None => { - self.operations.push(new_operation); - return - }, - }; - - // we are able (and obliged to) to merge two consequent block finalization operations - match last_operation { - CommitOperation::BlockFinalized( - old_finalized_block, - old_finalized_entry, - old_abandoned_forks, - ) => match new_operation { - CommitOperation::BlockFinalized( - new_finalized_block, - new_finalized_entry, - new_abandoned_forks, - ) => { - self.operations.push(CommitOperation::BlockFinalized( - new_finalized_block, - new_finalized_entry, - new_abandoned_forks, - )); - }, - _ => { - self.operations.push(CommitOperation::BlockFinalized( - old_finalized_block, - old_finalized_entry, - old_abandoned_forks, - )); - self.operations.push(new_operation); - }, - }, - _ => { - self.operations.push(last_operation); - self.operations.push(new_operation); - }, - } - } -} - -/// Destroy fork by deleting all unfinalized entries. -pub fn destroy_fork< - Block: BlockT, - T: CacheItemT, - S: Storage, - Tx: StorageTransaction, ->( - head_valid_from: ComplexBlockId, - storage: &S, - tx: &mut Tx, - best_finalized_block: Option>, -) -> ClientResult<()> { - let mut current = head_valid_from; - loop { - // optionally: deletion stops when we found entry at finalized block - if let Some(best_finalized_block) = best_finalized_block { - if chain::is_finalized_block(storage, ¤t, best_finalized_block)? { - return Ok(()) - } - } - - // read pointer to previous entry - let entry = storage.require_entry(¤t)?; - tx.remove_storage_entry(¤t); - - // deletion stops when there are no more entries in the list - current = match entry.prev_valid_from { - Some(prev_valid_from) => prev_valid_from, - None => return Ok(()), - }; - } -} - -/// Blockchain related functions. -mod chain { - use super::*; - use sp_runtime::traits::Header as HeaderT; - - /// Is the block1 connected both ends of the range. - pub fn is_connected_to_range>( - storage: &S, - block: &ComplexBlockId, - range: (&ComplexBlockId, Option<&ComplexBlockId>), - ) -> ClientResult { - let (begin, end) = range; - Ok(is_connected_to_block(storage, block, begin)? && - match end { - Some(end) => is_connected_to_block(storage, block, end)?, - None => true, - }) - } - - /// Is the block1 directly connected (i.e. part of the same fork) to block2? - pub fn is_connected_to_block>( - storage: &S, - block1: &ComplexBlockId, - block2: &ComplexBlockId, - ) -> ClientResult { - let (begin, end) = if *block1 > *block2 { (block2, block1) } else { (block1, block2) }; - let mut current = storage - .read_header(&end.hash)? - .ok_or_else(|| ClientError::UnknownBlock(format!("{}", end.hash)))?; - while *current.number() > begin.number { - current = storage - .read_header(current.parent_hash())? - .ok_or_else(|| ClientError::UnknownBlock(format!("{}", current.parent_hash())))?; - } - - Ok(begin.hash == current.hash()) - } - - /// Returns true if the given block is finalized. - pub fn is_finalized_block>( - storage: &S, - block: &ComplexBlockId, - best_finalized_block: NumberFor, - ) -> ClientResult { - if block.number > best_finalized_block { - return Ok(false) - } - - storage.read_id(block.number).map(|hash| hash.as_ref() == Some(&block.hash)) - } -} - -/// Read list cache forks at blocks IDs. -fn read_forks>( - storage: &S, - meta: Metadata, -) -> ClientResult<(Option>, Vec>)> { - let finalized = match meta.finalized { - Some(finalized) => Some(storage.require_entry(&finalized)?.into_entry(finalized)), - None => None, - }; - - let unfinalized = meta - .unfinalized - .into_iter() - .map(|unfinalized| { - storage.require_entry(&unfinalized).map(|storage_entry| Fork { - best_block: None, - head: storage_entry.into_entry(unfinalized), - }) - }) - .collect::>()?; - - Ok((finalized, unfinalized)) -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::cache::list_storage::tests::{DummyStorage, DummyTransaction, FaultyStorage}; - use sp_runtime::testing::{Block as RawBlock, ExtrinsicWrapper, Header}; - use substrate_test_runtime_client::runtime::H256; - - type Block = RawBlock>; - - fn test_id(number: u64) -> ComplexBlockId { - ComplexBlockId::new(H256::from_low_u64_be(number), number) - } - - fn correct_id(number: u64) -> ComplexBlockId { - ComplexBlockId::new(test_header(number).hash(), number) - } - - fn fork_id(fork_nonce: u64, fork_from: u64, number: u64) -> ComplexBlockId { - ComplexBlockId::new(fork_header(fork_nonce, fork_from, number).hash(), number) - } - - fn test_header(number: u64) -> Header { - Header { - parent_hash: if number == 0 { - Default::default() - } else { - test_header(number - 1).hash() - }, - number, - state_root: Default::default(), - extrinsics_root: Default::default(), - digest: Default::default(), - } - } - - fn fork_header(fork_nonce: u64, fork_from: u64, number: u64) -> Header { - if fork_from == number { - test_header(number) - } else { - Header { - parent_hash: fork_header(fork_nonce, fork_from, number - 1).hash(), - number, - state_root: H256::from_low_u64_be(1 + fork_nonce), - extrinsics_root: Default::default(), - digest: Default::default(), - } - } - } - - #[test] - fn list_value_at_block_works() { - // when block is earlier than best finalized block AND it is not finalized - // --- 50 --- - // ----------> [100] - assert!(ListCache::<_, u64, _>::new( - DummyStorage::new(), - PruningStrategy::ByDepth(1024), - test_id(100) - ) - .unwrap() - .value_at_block(&test_id(50)) - .is_err()); - // when block is earlier than best finalized block AND it is finalized AND value is some - // [30] ---- 50 ---> [100] - assert_eq!( - ListCache::new( - DummyStorage::new() - .with_meta(Some(test_id(100)), Vec::new()) - .with_id(50, H256::from_low_u64_be(50)) - .with_entry( - test_id(100), - StorageEntry { prev_valid_from: Some(test_id(30)), value: 100 } - ) - .with_entry(test_id(30), StorageEntry { prev_valid_from: None, value: 30 }), - PruningStrategy::ByDepth(1024), - test_id(100) - ) - .unwrap() - .value_at_block(&test_id(50)) - .unwrap(), - Some((test_id(30), Some(test_id(100)), 30)) - ); - // when block is the best finalized block AND value is some - // ---> [100] - assert_eq!( - ListCache::new( - DummyStorage::new() - .with_meta(Some(test_id(100)), Vec::new()) - .with_id(100, H256::from_low_u64_be(100)) - .with_entry( - test_id(100), - StorageEntry { prev_valid_from: Some(test_id(30)), value: 100 } - ) - .with_entry(test_id(30), StorageEntry { prev_valid_from: None, value: 30 }), - PruningStrategy::ByDepth(1024), - test_id(100) - ) - .unwrap() - .value_at_block(&test_id(100)) - .unwrap(), - Some((test_id(100), None, 100)) - ); - // when block is parallel to the best finalized block - // ---- 100 - // ---> [100] - assert!(ListCache::new( - DummyStorage::new() - .with_meta(Some(test_id(100)), Vec::new()) - .with_id(50, H256::from_low_u64_be(50)) - .with_entry( - test_id(100), - StorageEntry { prev_valid_from: Some(test_id(30)), value: 100 } - ) - .with_entry(test_id(30), StorageEntry { prev_valid_from: None, value: 30 }), - PruningStrategy::ByDepth(1024), - test_id(100) - ) - .unwrap() - .value_at_block(&ComplexBlockId::new(H256::from_low_u64_be(2), 100)) - .is_err()); - - // when block is later than last finalized block AND there are no forks AND finalized value - // is Some ---> [100] --- 200 - assert_eq!( - ListCache::new( - DummyStorage::new() - .with_meta(Some(test_id(100)), Vec::new()) - .with_id(50, H256::from_low_u64_be(50)) - .with_entry( - test_id(100), - StorageEntry { prev_valid_from: Some(test_id(30)), value: 100 } - ), - PruningStrategy::ByDepth(1024), - test_id(100) - ) - .unwrap() - .value_at_block(&test_id(200)) - .unwrap(), - Some((test_id(100), None, 100)) - ); - - // when block is later than last finalized block AND there are no matching forks - // AND block is connected to finalized block AND finalized value is Some - // --- 3 - // ---> [2] /---------> [4] - assert_eq!( - ListCache::new( - DummyStorage::new() - .with_meta(Some(correct_id(2)), vec![correct_id(4)]) - .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: 2 }) - .with_entry( - correct_id(4), - StorageEntry { prev_valid_from: Some(correct_id(2)), value: 4 } - ) - .with_header(test_header(2)) - .with_header(test_header(3)) - .with_header(test_header(4)) - .with_header(fork_header(0, 2, 3)), - PruningStrategy::ByDepth(1024), - test_id(2) - ) - .unwrap() - .value_at_block(&fork_id(0, 2, 3)) - .unwrap(), - Some((correct_id(2), None, 2)) - ); - // when block is later than last finalized block AND there are no matching forks - // AND block is not connected to finalized block - // --- 2 --- 3 - // 1 /---> [2] ---------> [4] - assert_eq!( - ListCache::new( - DummyStorage::new() - .with_meta(Some(correct_id(2)), vec![correct_id(4)]) - .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: 2 }) - .with_entry( - correct_id(4), - StorageEntry { prev_valid_from: Some(correct_id(2)), value: 4 } - ) - .with_header(test_header(1)) - .with_header(test_header(2)) - .with_header(test_header(3)) - .with_header(test_header(4)) - .with_header(fork_header(0, 1, 3)) - .with_header(fork_header(0, 1, 2)), - PruningStrategy::ByDepth(1024), - test_id(2) - ) - .unwrap() - .value_at_block(&fork_id(0, 1, 3)) - .unwrap(), - None - ); - - // when block is later than last finalized block AND it appends to unfinalized fork from the - // end AND unfinalized value is Some - // ---> [2] ---> [4] ---> 5 - assert_eq!( - ListCache::new( - DummyStorage::new() - .with_meta(Some(correct_id(2)), vec![correct_id(4)]) - .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: 2 }) - .with_entry( - correct_id(4), - StorageEntry { prev_valid_from: Some(correct_id(2)), value: 4 } - ) - .with_header(test_header(4)) - .with_header(test_header(5)), - PruningStrategy::ByDepth(1024), - test_id(2) - ) - .unwrap() - .value_at_block(&correct_id(5)) - .unwrap(), - Some((correct_id(4), None, 4)) - ); - // when block is later than last finalized block AND it does not fits unfinalized fork - // AND it is connected to the finalized block AND finalized value is Some - // ---> [2] ----------> [4] - // \--- 3 - assert_eq!( - ListCache::new( - DummyStorage::new() - .with_meta(Some(correct_id(2)), vec![correct_id(4)]) - .with_entry( - correct_id(4), - StorageEntry { prev_valid_from: Some(correct_id(2)), value: 4 } - ) - .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: 2 }) - .with_header(test_header(2)) - .with_header(test_header(3)) - .with_header(test_header(4)) - .with_header(fork_header(0, 2, 3)), - PruningStrategy::ByDepth(1024), - test_id(2) - ) - .unwrap() - .value_at_block(&fork_id(0, 2, 3)) - .unwrap(), - Some((correct_id(2), None, 2)) - ); - } - - #[test] - fn list_on_block_insert_works() { - let nfin = EntryType::NonFinal; - let fin = EntryType::Final; - - // when trying to insert block < finalized number - let mut ops = Default::default(); - assert!(ListCache::new(DummyStorage::new(), PruningStrategy::ByDepth(1024), test_id(100)) - .unwrap() - .do_on_block_insert( - &mut DummyTransaction::new(), - test_id(49), - test_id(50), - Some(50), - nfin, - &mut ops, - ) - .unwrap() - .is_none()); - // when trying to insert block @ finalized number - assert!(ListCache::new(DummyStorage::new(), PruningStrategy::ByDepth(1024), test_id(100)) - .unwrap() - .do_on_block_insert( - &mut DummyTransaction::new(), - test_id(99), - test_id(100), - Some(100), - nfin, - &Default::default(), - ) - .unwrap() - .is_none()); - - // when trying to insert non-final block AND it appends to the best block of unfinalized - // fork AND new value is the same as in the fork' best block - let mut cache = ListCache::new( - DummyStorage::new() - .with_meta(None, vec![test_id(4)]) - .with_entry(test_id(4), StorageEntry { prev_valid_from: None, value: 4 }), - PruningStrategy::ByDepth(1024), - test_id(2), - ) - .unwrap(); - cache.unfinalized[0].best_block = Some(test_id(4)); - let mut tx = DummyTransaction::new(); - assert_eq!( - cache - .do_on_block_insert( - &mut tx, - test_id(4), - test_id(5), - Some(4), - nfin, - &Default::default() - ) - .unwrap(), - Some(CommitOperation::AppendNewBlock(0, test_id(5))), - ); - assert!(tx.inserted_entries().is_empty()); - assert!(tx.removed_entries().is_empty()); - assert!(tx.updated_meta().is_none()); - // when trying to insert non-final block AND it appends to the best block of unfinalized - // fork AND new value is the same as in the fork' best block - let mut tx = DummyTransaction::new(); - assert_eq!( - cache - .do_on_block_insert( - &mut tx, - test_id(4), - test_id(5), - Some(5), - nfin, - &Default::default() - ) - .unwrap(), - Some(CommitOperation::AppendNewEntry(0, Entry { valid_from: test_id(5), value: 5 })), - ); - assert_eq!(*tx.inserted_entries(), vec![test_id(5).hash].into_iter().collect()); - assert!(tx.removed_entries().is_empty()); - assert_eq!( - *tx.updated_meta(), - Some(Metadata { finalized: None, unfinalized: vec![test_id(5)] }) - ); - - // when trying to insert non-final block AND it is the first block that appends to the best - // block of unfinalized fork AND new value is the same as in the fork' best block - let cache = ListCache::new( - DummyStorage::new() - .with_meta(None, vec![correct_id(4)]) - .with_entry(correct_id(4), StorageEntry { prev_valid_from: None, value: 4 }) - .with_header(test_header(4)), - PruningStrategy::ByDepth(1024), - test_id(2), - ) - .unwrap(); - let mut tx = DummyTransaction::new(); - assert_eq!( - cache - .do_on_block_insert( - &mut tx, - correct_id(4), - correct_id(5), - Some(4), - nfin, - &Default::default(), - ) - .unwrap(), - Some(CommitOperation::AppendNewBlock(0, correct_id(5))), - ); - assert!(tx.inserted_entries().is_empty()); - assert!(tx.removed_entries().is_empty()); - assert!(tx.updated_meta().is_none()); - // when trying to insert non-final block AND it is the first block that appends to the best - // block of unfinalized fork AND new value is the same as in the fork' best block - let mut tx = DummyTransaction::new(); - assert_eq!( - cache - .do_on_block_insert( - &mut tx, - correct_id(4), - correct_id(5), - Some(5), - nfin, - &Default::default(), - ) - .unwrap(), - Some(CommitOperation::AppendNewEntry(0, Entry { valid_from: correct_id(5), value: 5 })), - ); - assert_eq!(*tx.inserted_entries(), vec![correct_id(5).hash].into_iter().collect()); - assert!(tx.removed_entries().is_empty()); - assert_eq!( - *tx.updated_meta(), - Some(Metadata { finalized: None, unfinalized: vec![correct_id(5)] }) - ); - - // when trying to insert non-final block AND it forks unfinalized fork - let cache = ListCache::new( - DummyStorage::new() - .with_meta(Some(correct_id(2)), vec![correct_id(4)]) - .with_entry( - correct_id(4), - StorageEntry { prev_valid_from: Some(correct_id(2)), value: 4 }, - ) - .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: 2 }) - .with_header(test_header(2)) - .with_header(test_header(3)) - .with_header(test_header(4)), - PruningStrategy::ByDepth(1024), - correct_id(2), - ) - .unwrap(); - let mut tx = DummyTransaction::new(); - assert_eq!( - cache - .do_on_block_insert( - &mut tx, - correct_id(3), - fork_id(0, 3, 4), - Some(14), - nfin, - &Default::default() - ) - .unwrap(), - Some(CommitOperation::AddNewFork(Entry { valid_from: fork_id(0, 3, 4), value: 14 })), - ); - assert_eq!(*tx.inserted_entries(), vec![fork_id(0, 3, 4).hash].into_iter().collect()); - assert!(tx.removed_entries().is_empty()); - assert_eq!( - *tx.updated_meta(), - Some(Metadata { - finalized: Some(correct_id(2)), - unfinalized: vec![correct_id(4), fork_id(0, 3, 4)] - }) - ); - - // when trying to insert non-final block AND there are no unfinalized forks - // AND value is the same as last finalized - let cache = ListCache::new( - DummyStorage::new() - .with_meta(Some(correct_id(2)), vec![]) - .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: 2 }), - PruningStrategy::ByDepth(1024), - correct_id(2), - ) - .unwrap(); - let mut tx = DummyTransaction::new(); - assert_eq!( - cache - .do_on_block_insert( - &mut tx, - correct_id(2), - correct_id(3), - Some(2), - nfin, - &Default::default() - ) - .unwrap(), - None, - ); - assert!(tx.inserted_entries().is_empty()); - assert!(tx.removed_entries().is_empty()); - assert!(tx.updated_meta().is_none()); - // when trying to insert non-final block AND there are no unfinalized forks - // AND value differs from last finalized - let cache = ListCache::new( - DummyStorage::new() - .with_meta(Some(correct_id(2)), vec![]) - .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: 2 }), - PruningStrategy::ByDepth(1024), - correct_id(2), - ) - .unwrap(); - let mut tx = DummyTransaction::new(); - assert_eq!( - cache - .do_on_block_insert( - &mut tx, - correct_id(2), - correct_id(3), - Some(3), - nfin, - &Default::default() - ) - .unwrap(), - Some(CommitOperation::AddNewFork(Entry { valid_from: correct_id(3), value: 3 })), - ); - assert_eq!(*tx.inserted_entries(), vec![correct_id(3).hash].into_iter().collect()); - assert!(tx.removed_entries().is_empty()); - assert_eq!( - *tx.updated_meta(), - Some(Metadata { finalized: Some(correct_id(2)), unfinalized: vec![correct_id(3)] }) - ); - - // when inserting finalized entry AND there are no previous finalized entries - let cache = - ListCache::new(DummyStorage::new(), PruningStrategy::ByDepth(1024), correct_id(2)) - .unwrap(); - let mut tx = DummyTransaction::new(); - assert_eq!( - cache - .do_on_block_insert( - &mut tx, - correct_id(2), - correct_id(3), - Some(3), - fin, - &Default::default() - ) - .unwrap(), - Some(CommitOperation::BlockFinalized( - correct_id(3), - Some(Entry { valid_from: correct_id(3), value: 3 }), - Default::default(), - )), - ); - assert_eq!(*tx.inserted_entries(), vec![correct_id(3).hash].into_iter().collect()); - assert!(tx.removed_entries().is_empty()); - assert_eq!( - *tx.updated_meta(), - Some(Metadata { finalized: Some(correct_id(3)), unfinalized: vec![] }) - ); - // when inserting finalized entry AND value is the same as in previous finalized - let cache = ListCache::new( - DummyStorage::new() - .with_meta(Some(correct_id(2)), vec![]) - .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: 2 }), - PruningStrategy::ByDepth(1024), - correct_id(2), - ) - .unwrap(); - let mut tx = DummyTransaction::new(); - assert_eq!( - cache - .do_on_block_insert( - &mut tx, - correct_id(2), - correct_id(3), - Some(2), - fin, - &Default::default() - ) - .unwrap(), - Some(CommitOperation::BlockFinalized(correct_id(3), None, Default::default())), - ); - assert!(tx.inserted_entries().is_empty()); - assert!(tx.removed_entries().is_empty()); - assert!(tx.updated_meta().is_none()); - // when inserting finalized entry AND value differs from previous finalized - let mut tx = DummyTransaction::new(); - assert_eq!( - cache - .do_on_block_insert( - &mut tx, - correct_id(2), - correct_id(3), - Some(3), - fin, - &Default::default() - ) - .unwrap(), - Some(CommitOperation::BlockFinalized( - correct_id(3), - Some(Entry { valid_from: correct_id(3), value: 3 }), - Default::default(), - )), - ); - assert_eq!(*tx.inserted_entries(), vec![correct_id(3).hash].into_iter().collect()); - assert!(tx.removed_entries().is_empty()); - assert_eq!( - *tx.updated_meta(), - Some(Metadata { finalized: Some(correct_id(3)), unfinalized: vec![] }) - ); - - // inserting finalized entry removes abandoned fork EVEN if new entry is not inserted - let cache = ListCache::new( - DummyStorage::new() - .with_meta(Some(correct_id(2)), vec![fork_id(0, 1, 3)]) - .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: 2 }) - .with_entry(fork_id(0, 1, 3), StorageEntry { prev_valid_from: None, value: 13 }), - PruningStrategy::ByDepth(1024), - correct_id(2), - ) - .unwrap(); - let mut tx = DummyTransaction::new(); - assert_eq!( - cache - .do_on_block_insert( - &mut tx, - correct_id(2), - correct_id(3), - Some(2), - fin, - &Default::default() - ) - .unwrap(), - Some(CommitOperation::BlockFinalized( - correct_id(3), - None, - vec![0].into_iter().collect() - )), - ); - } - - #[test] - fn list_on_block_finalized_works() { - // finalization does not finalizes entry if it does not exists - let cache = ListCache::new( - DummyStorage::new() - .with_meta(Some(correct_id(2)), vec![correct_id(5)]) - .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: 2 }) - .with_entry( - correct_id(5), - StorageEntry { prev_valid_from: Some(correct_id(2)), value: 5 }, - ), - PruningStrategy::ByDepth(1024), - correct_id(2), - ) - .unwrap(); - let mut tx = DummyTransaction::new(); - assert_eq!( - cache - .do_on_block_finalize(&mut tx, correct_id(2), correct_id(3), &Default::default()) - .unwrap(), - Some(CommitOperation::BlockFinalized(correct_id(3), None, Default::default())), - ); - assert!(tx.inserted_entries().is_empty()); - assert!(tx.removed_entries().is_empty()); - assert_eq!( - *tx.updated_meta(), - Some(Metadata { finalized: Some(correct_id(2)), unfinalized: vec![correct_id(5)] }), - ); - // finalization finalizes entry - let cache = ListCache::new( - DummyStorage::new() - .with_meta(Some(correct_id(2)), vec![correct_id(5)]) - .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: 2 }) - .with_entry( - correct_id(5), - StorageEntry { prev_valid_from: Some(correct_id(2)), value: 5 }, - ), - PruningStrategy::ByDepth(1024), - correct_id(4), - ) - .unwrap(); - let mut tx = DummyTransaction::new(); - assert_eq!( - cache - .do_on_block_finalize(&mut tx, correct_id(4), correct_id(5), &Default::default()) - .unwrap(), - Some(CommitOperation::BlockFinalized( - correct_id(5), - Some(Entry { valid_from: correct_id(5), value: 5 }), - vec![0].into_iter().collect(), - )), - ); - assert!(tx.inserted_entries().is_empty()); - assert!(tx.removed_entries().is_empty()); - assert_eq!( - *tx.updated_meta(), - Some(Metadata { finalized: Some(correct_id(5)), unfinalized: vec![] }) - ); - // finalization removes abandoned forks - let cache = ListCache::new( - DummyStorage::new() - .with_meta(Some(correct_id(2)), vec![fork_id(0, 1, 3)]) - .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: 2 }) - .with_entry(fork_id(0, 1, 3), StorageEntry { prev_valid_from: None, value: 13 }), - PruningStrategy::ByDepth(1024), - correct_id(2), - ) - .unwrap(); - let mut tx = DummyTransaction::new(); - assert_eq!( - cache - .do_on_block_finalize(&mut tx, correct_id(2), correct_id(3), &Default::default()) - .unwrap(), - Some(CommitOperation::BlockFinalized( - correct_id(3), - None, - vec![0].into_iter().collect() - )), - ); - } - - #[test] - fn list_transaction_commit_works() { - let mut cache = ListCache::new( - DummyStorage::new() - .with_meta(Some(correct_id(2)), vec![correct_id(5), correct_id(6)]) - .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: 2 }) - .with_entry( - correct_id(5), - StorageEntry { prev_valid_from: Some(correct_id(2)), value: 5 }, - ) - .with_entry( - correct_id(6), - StorageEntry { prev_valid_from: Some(correct_id(5)), value: 6 }, - ), - PruningStrategy::ByDepth(1024), - correct_id(2), - ) - .unwrap(); - - // when new block is appended to unfinalized fork - cache.on_transaction_commit(vec![CommitOperation::AppendNewBlock(0, correct_id(6))].into()); - assert_eq!(cache.unfinalized[0].best_block, Some(correct_id(6))); - // when new entry is appended to unfinalized fork - cache.on_transaction_commit( - vec![CommitOperation::AppendNewEntry(0, Entry { valid_from: correct_id(7), value: 7 })] - .into(), - ); - assert_eq!(cache.unfinalized[0].best_block, Some(correct_id(7))); - assert_eq!(cache.unfinalized[0].head, Entry { valid_from: correct_id(7), value: 7 }); - // when new fork is added - cache.on_transaction_commit( - vec![CommitOperation::AddNewFork(Entry { valid_from: correct_id(10), value: 10 })] - .into(), - ); - assert_eq!(cache.unfinalized[2].best_block, Some(correct_id(10))); - assert_eq!(cache.unfinalized[2].head, Entry { valid_from: correct_id(10), value: 10 }); - // when block is finalized + entry is finalized + unfinalized forks are deleted - cache.on_transaction_commit( - vec![CommitOperation::BlockFinalized( - correct_id(20), - Some(Entry { valid_from: correct_id(20), value: 20 }), - vec![0, 1, 2].into_iter().collect(), - )] - .into(), - ); - assert_eq!(cache.best_finalized_block, correct_id(20)); - assert_eq!( - cache.best_finalized_entry, - Some(Entry { valid_from: correct_id(20), value: 20 }) - ); - assert!(cache.unfinalized.is_empty()); - } - - #[test] - fn list_find_unfinalized_fork_works() { - // ----------> [3] - // --- [2] ---------> 4 ---> [5] - assert_eq!( - ListCache::new( - DummyStorage::new() - .with_meta(None, vec![fork_id(0, 1, 3), correct_id(5)]) - .with_entry( - fork_id(0, 1, 3), - StorageEntry { prev_valid_from: Some(correct_id(1)), value: 13 } - ) - .with_entry( - correct_id(5), - StorageEntry { prev_valid_from: Some(correct_id(2)), value: 5 } - ) - .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: 2 }) - .with_header(test_header(2)) - .with_header(test_header(3)) - .with_header(test_header(4)) - .with_header(test_header(5)), - PruningStrategy::ByDepth(1024), - correct_id(0) - ) - .unwrap() - .find_unfinalized_fork((&correct_id(4)).into()) - .unwrap() - .unwrap() - .head - .valid_from, - correct_id(5) - ); - // --- [2] ---------------> [5] - // ----------> [3] ---> 4 - assert_eq!( - ListCache::new( - DummyStorage::new() - .with_meta(None, vec![correct_id(5), fork_id(0, 1, 3)]) - .with_entry( - fork_id(0, 1, 3), - StorageEntry { prev_valid_from: Some(correct_id(1)), value: 13 } - ) - .with_entry( - correct_id(5), - StorageEntry { prev_valid_from: Some(correct_id(2)), value: 5 } - ) - .with_entry( - correct_id(2), - StorageEntry { prev_valid_from: Some(correct_id(1)), value: 2 } - ) - .with_header(test_header(2)) - .with_header(test_header(3)) - .with_header(test_header(4)) - .with_header(test_header(5)) - .with_header(fork_header(0, 1, 2)) - .with_header(fork_header(0, 1, 3)) - .with_header(fork_header(0, 1, 4)), - PruningStrategy::ByDepth(1024), - correct_id(0) - ) - .unwrap() - .find_unfinalized_fork((&fork_id(0, 1, 4)).into()) - .unwrap() - .unwrap() - .head - .valid_from, - fork_id(0, 1, 3) - ); - // --- [2] ---------------> [5] - // ----------> [3] - // -----------------> 4 - assert!(ListCache::new( - DummyStorage::new() - .with_meta(None, vec![correct_id(5), fork_id(0, 1, 3)]) - .with_entry( - fork_id(0, 1, 3), - StorageEntry { prev_valid_from: Some(correct_id(1)), value: 13 } - ) - .with_entry( - correct_id(5), - StorageEntry { prev_valid_from: Some(correct_id(2)), value: 5 } - ) - .with_entry( - correct_id(2), - StorageEntry { prev_valid_from: Some(correct_id(1)), value: 2 } - ) - .with_header(test_header(2)) - .with_header(test_header(3)) - .with_header(test_header(4)) - .with_header(test_header(5)) - .with_header(fork_header(0, 1, 3)) - .with_header(fork_header(0, 1, 4)) - .with_header(fork_header(1, 1, 2)) - .with_header(fork_header(1, 1, 3)) - .with_header(fork_header(1, 1, 4)), - PruningStrategy::ByDepth(1024), - correct_id(0) - ) - .unwrap() - .find_unfinalized_fork((&fork_id(1, 1, 4)).into()) - .unwrap() - .is_none()); - } - - #[test] - fn fork_matches_works() { - // when block is not within list range - let storage = DummyStorage::new() - .with_entry( - test_id(100), - StorageEntry { prev_valid_from: Some(test_id(50)), value: 100 }, - ) - .with_entry(test_id(50), StorageEntry { prev_valid_from: None, value: 50 }); - assert_eq!( - Fork::<_, u64> { best_block: None, head: Entry { valid_from: test_id(100), value: 0 } } - .matches(&storage, (&test_id(20)).into()) - .unwrap(), - false - ); - // when block is not connected to the begin block - let storage = DummyStorage::new() - .with_entry( - correct_id(5), - StorageEntry { prev_valid_from: Some(correct_id(3)), value: 100 }, - ) - .with_entry(correct_id(3), StorageEntry { prev_valid_from: None, value: 200 }) - .with_header(test_header(5)) - .with_header(test_header(4)) - .with_header(test_header(3)) - .with_header(fork_header(0, 2, 4)) - .with_header(fork_header(0, 2, 3)); - assert_eq!( - Fork::<_, u64> { - best_block: None, - head: Entry { valid_from: correct_id(5), value: 100 } - } - .matches(&storage, (&fork_id(0, 2, 4)).into()) - .unwrap(), - false - ); - // when block is not connected to the end block - let storage = DummyStorage::new() - .with_entry( - correct_id(5), - StorageEntry { prev_valid_from: Some(correct_id(3)), value: 100 }, - ) - .with_entry(correct_id(3), StorageEntry { prev_valid_from: None, value: 200 }) - .with_header(test_header(5)) - .with_header(test_header(4)) - .with_header(test_header(3)) - .with_header(fork_header(0, 3, 4)); - assert_eq!( - Fork::<_, u64> { - best_block: None, - head: Entry { valid_from: correct_id(5), value: 100 } - } - .matches(&storage, (&fork_id(0, 3, 4)).into()) - .unwrap(), - false - ); - // when block is connected to the begin block AND end is open - let storage = DummyStorage::new() - .with_entry(correct_id(5), StorageEntry { prev_valid_from: None, value: 100 }) - .with_header(test_header(5)) - .with_header(test_header(6)); - assert_eq!( - Fork::<_, u64> { - best_block: None, - head: Entry { valid_from: correct_id(5), value: 100 } - } - .matches(&storage, (&correct_id(6)).into()) - .unwrap(), - true - ); - // when block is connected to the begin block AND to the end block - let storage = DummyStorage::new() - .with_entry( - correct_id(5), - StorageEntry { prev_valid_from: Some(correct_id(3)), value: 100 }, - ) - .with_entry(correct_id(3), StorageEntry { prev_valid_from: None, value: 200 }) - .with_header(test_header(5)) - .with_header(test_header(4)) - .with_header(test_header(3)); - assert_eq!( - Fork::<_, u64> { - best_block: None, - head: Entry { valid_from: correct_id(5), value: 100 } - } - .matches(&storage, (&correct_id(4)).into()) - .unwrap(), - true - ); - } - - #[test] - fn fork_try_append_works() { - // when best block is unknown - assert_eq!( - Fork::<_, u64> { best_block: None, head: Entry { valid_from: test_id(100), value: 0 } } - .try_append(&test_id(100)), - false - ); - // when best block is known but different - assert_eq!( - Fork::<_, u64> { best_block: None, head: Entry { valid_from: test_id(100), value: 0 } } - .try_append(&test_id(101)), - false - ); - // when best block is known and the same - assert_eq!( - Fork::<_, u64> { - best_block: Some(test_id(100)), - head: Entry { valid_from: test_id(100), value: 0 } - } - .try_append(&test_id(100)), - true - ); - } - - #[test] - fn fork_try_append_or_fork_works() { - // when there's no entry before parent - let storage = DummyStorage::new() - .with_entry( - test_id(100), - StorageEntry { prev_valid_from: Some(test_id(50)), value: 100 }, - ) - .with_entry(test_id(50), StorageEntry { prev_valid_from: None, value: 50 }); - assert_eq!( - Fork::<_, u64> { best_block: None, head: Entry { valid_from: test_id(100), value: 0 } } - .try_append_or_fork(&storage, &test_id(30), None) - .unwrap(), - None - ); - // when parent does not belong to the fork - let storage = DummyStorage::new() - .with_entry( - correct_id(5), - StorageEntry { prev_valid_from: Some(correct_id(3)), value: 100 }, - ) - .with_entry(correct_id(3), StorageEntry { prev_valid_from: None, value: 200 }) - .with_header(test_header(5)) - .with_header(test_header(4)) - .with_header(test_header(3)) - .with_header(fork_header(0, 2, 4)) - .with_header(fork_header(0, 2, 3)); - assert_eq!( - Fork::<_, u64> { - best_block: None, - head: Entry { valid_from: correct_id(5), value: 100 } - } - .try_append_or_fork(&storage, &fork_id(0, 2, 4), None) - .unwrap(), - None - ); - // when the entry before parent is the head entry - let storage = DummyStorage::new() - .with_entry( - ComplexBlockId::new(test_header(5).hash(), 5), - StorageEntry { prev_valid_from: Some(correct_id(3)), value: 100 }, - ) - .with_header(test_header(6)) - .with_header(test_header(5)); - assert_eq!( - Fork::<_, u64> { - best_block: None, - head: Entry { valid_from: correct_id(5), value: 100 } - } - .try_append_or_fork(&storage, &correct_id(6), None) - .unwrap(), - Some(ForkAppendResult::Append) - ); - // when the parent located after last finalized entry - let storage = DummyStorage::new() - .with_entry( - correct_id(6), - StorageEntry { prev_valid_from: Some(correct_id(3)), value: 100 }, - ) - .with_entry(correct_id(3), StorageEntry { prev_valid_from: None, value: 200 }) - .with_header(test_header(6)) - .with_header(test_header(5)) - .with_header(test_header(4)) - .with_header(test_header(3)) - .with_header(fork_header(0, 4, 5)); - assert_eq!( - Fork::<_, u64> { - best_block: None, - head: Entry { valid_from: correct_id(6), value: 100 } - } - .try_append_or_fork(&storage, &fork_id(0, 4, 5), None) - .unwrap(), - Some(ForkAppendResult::Fork(ComplexBlockId::new(test_header(3).hash(), 3))) - ); - // when the parent located before last finalized entry - let storage = DummyStorage::new() - .with_entry( - correct_id(6), - StorageEntry { prev_valid_from: Some(correct_id(3)), value: 100 }, - ) - .with_entry(correct_id(3), StorageEntry { prev_valid_from: None, value: 200 }) - .with_header(test_header(6)) - .with_header(test_header(5)) - .with_header(test_header(4)) - .with_header(test_header(3)) - .with_header(fork_header(0, 4, 5)); - assert_eq!( - Fork::<_, u64> { - best_block: None, - head: Entry { valid_from: correct_id(6), value: 100 } - } - .try_append_or_fork(&storage, &fork_id(0, 4, 5), Some(3)) - .unwrap(), - None - ); - } - - #[test] - fn fork_destroy_works() { - // when we reached finalized entry without iterations - let storage = DummyStorage::new().with_id(100, H256::from_low_u64_be(100)); - let mut tx = DummyTransaction::new(); - Fork::<_, u64> { best_block: None, head: Entry { valid_from: test_id(100), value: 0 } } - .destroy(&storage, &mut tx, Some(200)) - .unwrap(); - assert!(tx.removed_entries().is_empty()); - // when we reach finalized entry with iterations - let storage = DummyStorage::new() - .with_id(10, H256::from_low_u64_be(10)) - .with_entry( - test_id(100), - StorageEntry { prev_valid_from: Some(test_id(50)), value: 100 }, - ) - .with_entry(test_id(50), StorageEntry { prev_valid_from: Some(test_id(20)), value: 50 }) - .with_entry(test_id(20), StorageEntry { prev_valid_from: Some(test_id(10)), value: 20 }) - .with_entry(test_id(10), StorageEntry { prev_valid_from: Some(test_id(5)), value: 10 }) - .with_entry(test_id(5), StorageEntry { prev_valid_from: Some(test_id(3)), value: 5 }) - .with_entry(test_id(3), StorageEntry { prev_valid_from: None, value: 0 }); - let mut tx = DummyTransaction::new(); - Fork::<_, u64> { best_block: None, head: Entry { valid_from: test_id(100), value: 0 } } - .destroy(&storage, &mut tx, Some(200)) - .unwrap(); - assert_eq!( - *tx.removed_entries(), - vec![test_id(100).hash, test_id(50).hash, test_id(20).hash] - .into_iter() - .collect() - ); - // when we reach beginning of fork before finalized block - let storage = DummyStorage::new() - .with_id(10, H256::from_low_u64_be(10)) - .with_entry( - test_id(100), - StorageEntry { prev_valid_from: Some(test_id(50)), value: 100 }, - ) - .with_entry(test_id(50), StorageEntry { prev_valid_from: None, value: 50 }); - let mut tx = DummyTransaction::new(); - Fork::<_, u64> { best_block: None, head: Entry { valid_from: test_id(100), value: 0 } } - .destroy(&storage, &mut tx, Some(200)) - .unwrap(); - assert_eq!( - *tx.removed_entries(), - vec![test_id(100).hash, test_id(50).hash].into_iter().collect() - ); - } - - #[test] - fn is_connected_to_block_fails() { - // when storage returns error - assert!(chain::is_connected_to_block::<_, u64, _>( - &FaultyStorage, - (&test_id(1)).into(), - &test_id(100), - ) - .is_err(),); - // when there's no header in the storage - assert!(chain::is_connected_to_block::<_, u64, _>( - &DummyStorage::new(), - (&test_id(1)).into(), - &test_id(100), - ) - .is_err(),); - } - - #[test] - fn is_connected_to_block_works() { - // when without iterations we end up with different block - assert_eq!( - chain::is_connected_to_block::<_, u64, _>( - &DummyStorage::new().with_header(test_header(1)), - (&test_id(1)).into(), - &correct_id(1) - ) - .unwrap(), - false - ); - // when with ASC iterations we end up with different block - assert_eq!( - chain::is_connected_to_block::<_, u64, _>( - &DummyStorage::new() - .with_header(test_header(0)) - .with_header(test_header(1)) - .with_header(test_header(2)), - (&test_id(0)).into(), - &correct_id(2) - ) - .unwrap(), - false - ); - // when with DESC iterations we end up with different block - assert_eq!( - chain::is_connected_to_block::<_, u64, _>( - &DummyStorage::new() - .with_header(test_header(0)) - .with_header(test_header(1)) - .with_header(test_header(2)), - (&correct_id(2)).into(), - &test_id(0) - ) - .unwrap(), - false - ); - // when without iterations we end up with the same block - assert_eq!( - chain::is_connected_to_block::<_, u64, _>( - &DummyStorage::new().with_header(test_header(1)), - (&correct_id(1)).into(), - &correct_id(1) - ) - .unwrap(), - true - ); - // when with ASC iterations we end up with the same block - assert_eq!( - chain::is_connected_to_block::<_, u64, _>( - &DummyStorage::new() - .with_header(test_header(0)) - .with_header(test_header(1)) - .with_header(test_header(2)), - (&correct_id(0)).into(), - &correct_id(2) - ) - .unwrap(), - true - ); - // when with DESC iterations we end up with the same block - assert_eq!( - chain::is_connected_to_block::<_, u64, _>( - &DummyStorage::new() - .with_header(test_header(0)) - .with_header(test_header(1)) - .with_header(test_header(2)), - (&correct_id(2)).into(), - &correct_id(0) - ) - .unwrap(), - true - ); - } - - #[test] - fn is_finalized_block_fails() { - // when storage returns error - assert!(chain::is_finalized_block::<_, u64, _>(&FaultyStorage, &test_id(1), 100).is_err()); - } - - #[test] - fn is_finalized_block_works() { - // when number of block is larger than last finalized block - assert_eq!( - chain::is_finalized_block::<_, u64, _>(&DummyStorage::new(), &test_id(100), 1).unwrap(), - false - ); - // when there's no hash for this block number in the database - assert_eq!( - chain::is_finalized_block::<_, u64, _>(&DummyStorage::new(), &test_id(1), 100).unwrap(), - false - ); - // when there's different hash for this block number in the database - assert_eq!( - chain::is_finalized_block::<_, u64, _>( - &DummyStorage::new().with_id(1, H256::from_low_u64_be(2)), - &test_id(1), - 100 - ) - .unwrap(), - false - ); - // when there's the same hash for this block number in the database - assert_eq!( - chain::is_finalized_block::<_, u64, _>( - &DummyStorage::new().with_id(1, H256::from_low_u64_be(1)), - &test_id(1), - 100 - ) - .unwrap(), - true - ); - } - - #[test] - fn read_forks_fails() { - // when storage returns error during finalized entry read - assert!(read_forks::( - &FaultyStorage, - Metadata { finalized: Some(test_id(1)), unfinalized: vec![] } - ) - .is_err()); - // when storage returns error during unfinalized entry read - assert!(read_forks::( - &FaultyStorage, - Metadata { finalized: None, unfinalized: vec![test_id(1)] } - ) - .is_err()); - // when finalized entry is not found - assert!(read_forks::( - &DummyStorage::new(), - Metadata { finalized: Some(test_id(1)), unfinalized: vec![] } - ) - .is_err()); - // when unfinalized entry is not found - assert!(read_forks::( - &DummyStorage::new(), - Metadata { finalized: None, unfinalized: vec![test_id(1)] } - ) - .is_err()); - } - - #[test] - fn read_forks_works() { - let storage = DummyStorage::new() - .with_entry(test_id(10), StorageEntry { prev_valid_from: Some(test_id(1)), value: 11 }) - .with_entry(test_id(20), StorageEntry { prev_valid_from: Some(test_id(2)), value: 0 }) - .with_entry(test_id(30), StorageEntry { prev_valid_from: None, value: 33 }); - let expected = ( - Some(Entry { valid_from: test_id(10), value: 11 }), - vec![ - Fork { best_block: None, head: Entry { valid_from: test_id(20), value: 0 } }, - Fork { best_block: None, head: Entry { valid_from: test_id(30), value: 33 } }, - ], - ); - - assert_eq!( - expected, - read_forks( - &storage, - Metadata { - finalized: Some(test_id(10)), - unfinalized: vec![test_id(20), test_id(30)], - } - ) - .unwrap() - ); - } - - #[test] - fn ancient_entries_are_pruned_when_pruning_enabled() { - fn do_test(strategy: PruningStrategy) { - let cache = ListCache::new( - DummyStorage::new() - .with_id(10, H256::from_low_u64_be(10)) - .with_id(20, H256::from_low_u64_be(20)) - .with_id(30, H256::from_low_u64_be(30)) - .with_entry(test_id(10), StorageEntry { prev_valid_from: None, value: 10 }) - .with_entry( - test_id(20), - StorageEntry { prev_valid_from: Some(test_id(10)), value: 20 }, - ) - .with_entry( - test_id(30), - StorageEntry { prev_valid_from: Some(test_id(20)), value: 30 }, - ), - strategy, - test_id(9), - ) - .unwrap(); - let mut tx = DummyTransaction::new(); - - // when finalizing entry #10: no entries pruned - cache.prune_finalized_entries(&mut tx, &test_id(10)); - assert!(tx.removed_entries().is_empty()); - assert!(tx.inserted_entries().is_empty()); - // when finalizing entry #19: no entries pruned - cache.prune_finalized_entries(&mut tx, &test_id(19)); - assert!(tx.removed_entries().is_empty()); - assert!(tx.inserted_entries().is_empty()); - // when finalizing entry #20: no entries pruned - cache.prune_finalized_entries(&mut tx, &test_id(20)); - assert!(tx.removed_entries().is_empty()); - assert!(tx.inserted_entries().is_empty()); - // when finalizing entry #30: entry 10 pruned + entry 20 is truncated (if pruning is - // enabled) - cache.prune_finalized_entries(&mut tx, &test_id(30)); - match strategy { - PruningStrategy::NeverPrune => { - assert!(tx.removed_entries().is_empty()); - assert!(tx.inserted_entries().is_empty()); - }, - PruningStrategy::ByDepth(_) => { - assert_eq!(*tx.removed_entries(), vec![test_id(10).hash].into_iter().collect()); - assert_eq!( - *tx.inserted_entries(), - vec![test_id(20).hash].into_iter().collect() - ); - }, - } - } - - do_test(PruningStrategy::ByDepth(10)); - do_test(PruningStrategy::NeverPrune) - } - - #[test] - fn revert_block_works() { - // 1 -> (2) -> 3 -> 4 -> 5 - // \ - // -> 5'' - // \ - // -> (3') -> 4' -> 5' - let mut cache = ListCache::new( - DummyStorage::new() - .with_meta( - Some(correct_id(1)), - vec![correct_id(5), fork_id(1, 2, 5), fork_id(2, 4, 5)], - ) - .with_id(1, correct_id(1).hash) - .with_entry(correct_id(1), StorageEntry { prev_valid_from: None, value: 1 }) - .with_entry( - correct_id(3), - StorageEntry { prev_valid_from: Some(correct_id(1)), value: 3 }, - ) - .with_entry( - correct_id(4), - StorageEntry { prev_valid_from: Some(correct_id(3)), value: 4 }, - ) - .with_entry( - correct_id(5), - StorageEntry { prev_valid_from: Some(correct_id(4)), value: 5 }, - ) - .with_entry( - fork_id(1, 2, 4), - StorageEntry { prev_valid_from: Some(correct_id(1)), value: 14 }, - ) - .with_entry( - fork_id(1, 2, 5), - StorageEntry { prev_valid_from: Some(fork_id(1, 2, 4)), value: 15 }, - ) - .with_entry( - fork_id(2, 4, 5), - StorageEntry { prev_valid_from: Some(correct_id(4)), value: 25 }, - ) - .with_header(test_header(1)) - .with_header(test_header(2)) - .with_header(test_header(3)) - .with_header(test_header(4)) - .with_header(test_header(5)) - .with_header(fork_header(1, 2, 3)) - .with_header(fork_header(1, 2, 4)) - .with_header(fork_header(1, 2, 5)) - .with_header(fork_header(2, 4, 5)), - PruningStrategy::ByDepth(1024), - correct_id(1), - ) - .unwrap(); - - // when 5 is reverted: entry 5 is truncated - let op = cache.do_on_block_revert(&mut DummyTransaction::new(), &correct_id(5)).unwrap(); - assert_eq!( - op, - CommitOperation::BlockReverted( - vec![( - 0, - Some(Fork { - best_block: None, - head: Entry { valid_from: correct_id(4), value: 4 } - }) - ),] - .into_iter() - .collect() - ) - ); - cache.on_transaction_commit(vec![op].into()); - - // when 3 is reverted: entries 4+5' are truncated - let op = cache.do_on_block_revert(&mut DummyTransaction::new(), &correct_id(3)).unwrap(); - assert_eq!( - op, - CommitOperation::BlockReverted(vec![(0, None), (2, None),].into_iter().collect()) - ); - cache.on_transaction_commit(vec![op].into()); - - // when 2 is reverted: entries 4'+5' are truncated - let op = cache.do_on_block_revert(&mut DummyTransaction::new(), &correct_id(2)).unwrap(); - assert_eq!(op, CommitOperation::BlockReverted(vec![(0, None),].into_iter().collect())); - cache.on_transaction_commit(vec![op].into()); - } - - #[test] - fn append_commit_operation_works() { - let mut ops = CommitOperations::default(); - ops.append(None); - assert_eq!(ops.operations, Vec::new()); - - ops.append(Some(CommitOperation::BlockFinalized( - test_id(10), - Some(Entry { valid_from: test_id(10), value: 10 }), - vec![5].into_iter().collect(), - ))); - assert_eq!( - ops.operations, - vec![CommitOperation::BlockFinalized( - test_id(10), - Some(Entry { valid_from: test_id(10), value: 10 }), - vec![5].into_iter().collect(), - )], - ); - - ops.append(Some(CommitOperation::BlockFinalized( - test_id(20), - Some(Entry { valid_from: test_id(20), value: 20 }), - vec![5, 6].into_iter().collect(), - ))); - - assert_eq!( - ops.operations, - vec![CommitOperation::BlockFinalized( - test_id(20), - Some(Entry { valid_from: test_id(20), value: 20 }), - vec![5, 6].into_iter().collect(), - )], - ); - } -} diff --git a/client/db/src/cache/list_entry.rs b/client/db/src/cache/list_entry.rs deleted file mode 100644 index 7cee7a514626..000000000000 --- a/client/db/src/cache/list_entry.rs +++ /dev/null @@ -1,187 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2017-2021 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 . - -//! List-cache storage entries. - -use codec::{Decode, Encode}; -use sp_blockchain::Result as ClientResult; -use sp_runtime::traits::{Block as BlockT, NumberFor}; - -use crate::cache::{list_storage::Storage, CacheItemT, ComplexBlockId}; - -/// Single list-based cache entry. -#[derive(Debug)] -#[cfg_attr(test, derive(PartialEq))] -pub struct Entry { - /// first block, when this value became actual. - pub valid_from: ComplexBlockId, - /// Value stored at this entry. - pub value: T, -} - -/// Internal representation of the single list-based cache entry. The entry points to the -/// previous entry in the cache, allowing us to traverse back in time in list-style. -#[derive(Debug, Encode, Decode)] -#[cfg_attr(test, derive(Clone, PartialEq))] -pub struct StorageEntry { - /// None if valid from the beginning. - pub prev_valid_from: Option>, - /// Value stored at this entry. - pub value: T, -} - -impl Entry { - /// Returns Some if the entry should be updated with the new value. - pub fn try_update(&self, value: Option) -> Option> { - match value { - Some(value) => match self.value == value { - true => None, - false => - Some(StorageEntry { prev_valid_from: Some(self.valid_from.clone()), value }), - }, - None => None, - } - } - - /// Wrapper that calls search_before to get range where the given block fits. - pub fn search_best_range_before>( - &self, - storage: &S, - block: NumberFor, - ) -> ClientResult, Option>)>> { - Ok(self - .search_best_before(storage, block)? - .map(|(entry, next)| (entry.valid_from, next))) - } - - /// Searches the list, ending with THIS entry for the best entry preceding (or at) - /// given block number. - /// If the entry is found, result is the entry and the block id of next entry (if exists). - /// NOTE that this function does not check that the passed block is actually linked to - /// the blocks it found. - pub fn search_best_before>( - &self, - storage: &S, - block: NumberFor, - ) -> ClientResult, Option>)>> { - // we're looking for the best value - let mut next = None; - let mut current = self.valid_from.clone(); - if block >= self.valid_from.number { - let value = self.value.clone(); - return Ok(Some((Entry { valid_from: current, value }, next))) - } - - // else - travel back in time - loop { - let entry = storage.require_entry(¤t)?; - if block >= current.number { - return Ok(Some((Entry { valid_from: current, value: entry.value }, next))) - } - - next = Some(current); - current = match entry.prev_valid_from { - Some(prev_valid_from) => prev_valid_from, - None => return Ok(None), - }; - } - } -} - -impl StorageEntry { - /// Converts storage entry into an entry, valid from given block. - pub fn into_entry(self, valid_from: ComplexBlockId) -> Entry { - Entry { valid_from, value: self.value } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::cache::list_storage::tests::{DummyStorage, FaultyStorage}; - use substrate_test_runtime_client::runtime::{Block, H256}; - - fn test_id(number: u64) -> ComplexBlockId { - ComplexBlockId::new(H256::from_low_u64_be(number), number) - } - - #[test] - fn entry_try_update_works() { - // when trying to update with None value - assert_eq!(Entry::<_, u64> { valid_from: test_id(1), value: 42 }.try_update(None), None); - // when trying to update with the same Some value - assert_eq!(Entry { valid_from: test_id(1), value: 1 }.try_update(Some(1)), None); - // when trying to update with different Some value - assert_eq!( - Entry { valid_from: test_id(1), value: 1 }.try_update(Some(2)), - Some(StorageEntry { prev_valid_from: Some(test_id(1)), value: 2 }) - ); - } - - #[test] - fn entry_search_best_before_fails() { - // when storage returns error - assert!(Entry::<_, u64> { valid_from: test_id(100), value: 42 } - .search_best_before(&FaultyStorage, 50) - .is_err()); - } - - #[test] - fn entry_search_best_before_works() { - // when block is better than our best block - assert_eq!( - Entry::<_, u64> { valid_from: test_id(100), value: 100 } - .search_best_before(&DummyStorage::new(), 150) - .unwrap(), - Some((Entry::<_, u64> { valid_from: test_id(100), value: 100 }, None)) - ); - // when block is found between two entries - assert_eq!( - Entry::<_, u64> { valid_from: test_id(100), value: 100 } - .search_best_before( - &DummyStorage::new() - .with_entry( - test_id(100), - StorageEntry { prev_valid_from: Some(test_id(50)), value: 100 } - ) - .with_entry( - test_id(50), - StorageEntry { prev_valid_from: Some(test_id(30)), value: 50 } - ), - 75 - ) - .unwrap(), - Some((Entry::<_, u64> { valid_from: test_id(50), value: 50 }, Some(test_id(100)))) - ); - // when block is not found - assert_eq!( - Entry::<_, u64> { valid_from: test_id(100), value: 100 } - .search_best_before( - &DummyStorage::new() - .with_entry( - test_id(100), - StorageEntry { prev_valid_from: Some(test_id(50)), value: 100 } - ) - .with_entry(test_id(50), StorageEntry { prev_valid_from: None, value: 50 }), - 30 - ) - .unwrap(), - None - ); - } -} diff --git a/client/db/src/cache/list_storage.rs b/client/db/src/cache/list_storage.rs deleted file mode 100644 index bb47b8dab5a7..000000000000 --- a/client/db/src/cache/list_storage.rs +++ /dev/null @@ -1,441 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2017-2021 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 . - -//! List-cache storage definition and implementation. - -use std::sync::Arc; - -use crate::utils::{self, meta_keys}; -use codec::{Decode, Encode}; -use sp_blockchain::{Error as ClientError, Result as ClientResult}; -use sp_database::{Database, Transaction}; -use sp_runtime::{ - generic::BlockId, - traits::{Block as BlockT, Header as HeaderT, NumberFor}, -}; - -use crate::{ - cache::{ - list_cache::{CommitOperation, Fork}, - list_entry::{Entry, StorageEntry}, - CacheItemT, ComplexBlockId, - }, - DbHash, -}; - -/// Single list-cache metadata. -#[derive(Debug)] -#[cfg_attr(test, derive(Clone, PartialEq))] -pub struct Metadata { - /// Block at which best finalized entry is stored. - pub finalized: Option>, - /// A set of blocks at which best unfinalized entries are stored. - pub unfinalized: Vec>, -} - -/// Readonly list-cache storage trait. -pub trait Storage { - /// Reads hash of the block at given number. - fn read_id(&self, at: NumberFor) -> ClientResult>; - - /// Reads header of the block with given hash. - fn read_header(&self, at: &Block::Hash) -> ClientResult>; - - /// Reads cache metadata: best finalized entry (if some) and the list. - fn read_meta(&self) -> ClientResult>; - - /// Reads cache entry from the storage. - fn read_entry( - &self, - at: &ComplexBlockId, - ) -> ClientResult>>; - - /// Reads referenced (and thus existing) cache entry from the storage. - fn require_entry(&self, at: &ComplexBlockId) -> ClientResult> { - self.read_entry(at).and_then(|entry| { - entry.ok_or_else(|| { - ClientError::from(ClientError::Backend(format!( - "Referenced cache entry at {:?} is not found", - at - ))) - }) - }) - } -} - -/// List-cache storage transaction. -pub trait StorageTransaction { - /// Insert storage entry at given block. - fn insert_storage_entry(&mut self, at: &ComplexBlockId, entry: &StorageEntry); - - /// Delete storage entry at given block. - fn remove_storage_entry(&mut self, at: &ComplexBlockId); - - /// Update metadata of the cache. - fn update_meta( - &mut self, - best_finalized_entry: Option<&Entry>, - unfinalized: &[Fork], - operation: &CommitOperation, - ); -} - -/// A set of columns used by the DbStorage. -#[derive(Debug)] -pub struct DbColumns { - /// Column holding cache meta. - pub meta: u32, - /// Column holding the mapping of { block number => block hash } for blocks of the best chain. - pub key_lookup: u32, - /// Column holding the mapping of { block hash => block header }. - pub header: u32, - /// Column holding cache entries. - pub cache: u32, -} - -/// Database-backed list cache storage. -pub struct DbStorage { - name: Vec, - meta_key: Vec, - db: Arc>, - columns: DbColumns, -} - -impl DbStorage { - /// Create new database-backed list cache storage. - pub fn new(name: Vec, db: Arc>, columns: DbColumns) -> Self { - let meta_key = meta::key(&name); - DbStorage { name, meta_key, db, columns } - } - - /// Get reference to the database. - pub fn db(&self) -> &Arc> { - &self.db - } - - /// Get reference to the database columns. - pub fn columns(&self) -> &DbColumns { - &self.columns - } - - /// Encode block id for storing as a key in cache column. - /// We append prefix to the actual encoding to allow several caches - /// store entries in the same column. - pub fn encode_block_id(&self, block: &ComplexBlockId) -> Vec { - let mut encoded = self.name.clone(); - encoded.extend(block.hash.as_ref()); - encoded - } -} - -impl Storage for DbStorage { - fn read_id(&self, at: NumberFor) -> ClientResult> { - utils::read_header::( - &*self.db, - self.columns.key_lookup, - self.columns.header, - BlockId::Number(at), - ) - .map(|maybe_header| maybe_header.map(|header| header.hash())) - } - - fn read_header(&self, at: &Block::Hash) -> ClientResult> { - utils::read_header::( - &*self.db, - self.columns.key_lookup, - self.columns.header, - BlockId::Hash(*at), - ) - } - - fn read_meta(&self) -> ClientResult> { - match self.db.get(self.columns.meta, &self.meta_key) { - Some(meta) => meta::decode(&*meta), - None => Ok(Metadata { finalized: None, unfinalized: Vec::new() }), - } - } - - fn read_entry( - &self, - at: &ComplexBlockId, - ) -> ClientResult>> { - match self.db.get(self.columns.cache, &self.encode_block_id(at)) { - Some(entry) => StorageEntry::::decode(&mut &entry[..]) - .map_err(|_| ClientError::Backend("Failed to decode cache entry".into())) - .map(Some), - None => Ok(None), - } - } -} - -/// Database-backed list cache storage transaction. -pub struct DbStorageTransaction<'a> { - storage: &'a DbStorage, - tx: &'a mut Transaction, -} - -impl<'a> DbStorageTransaction<'a> { - /// Create new database transaction. - pub fn new(storage: &'a DbStorage, tx: &'a mut Transaction) -> Self { - DbStorageTransaction { storage, tx } - } -} - -impl<'a, Block: BlockT, T: CacheItemT> StorageTransaction for DbStorageTransaction<'a> { - fn insert_storage_entry(&mut self, at: &ComplexBlockId, entry: &StorageEntry) { - self.tx.set_from_vec( - self.storage.columns.cache, - &self.storage.encode_block_id(at), - entry.encode(), - ); - } - - fn remove_storage_entry(&mut self, at: &ComplexBlockId) { - self.tx.remove(self.storage.columns.cache, &self.storage.encode_block_id(at)); - } - - fn update_meta( - &mut self, - best_finalized_entry: Option<&Entry>, - unfinalized: &[Fork], - operation: &CommitOperation, - ) { - self.tx.set_from_vec( - self.storage.columns.meta, - &self.storage.meta_key, - meta::encode(best_finalized_entry, unfinalized, operation), - ); - } -} - -/// Metadata related functions. -mod meta { - use super::*; - - /// Convert cache name into cache metadata key. - pub fn key(name: &[u8]) -> Vec { - let mut key_name = meta_keys::CACHE_META_PREFIX.to_vec(); - key_name.extend_from_slice(name); - key_name - } - - /// Encode cache metadata 'applying' commit operation before encoding. - pub fn encode( - best_finalized_entry: Option<&Entry>, - unfinalized: &[Fork], - op: &CommitOperation, - ) -> Vec { - let mut finalized = best_finalized_entry.as_ref().map(|entry| &entry.valid_from); - let mut unfinalized = - unfinalized.iter().map(|fork| &fork.head().valid_from).collect::>(); - - match op { - CommitOperation::AppendNewBlock(_, _) => (), - CommitOperation::AppendNewEntry(index, ref entry) => { - unfinalized[*index] = &entry.valid_from; - }, - CommitOperation::AddNewFork(ref entry) => { - unfinalized.push(&entry.valid_from); - }, - CommitOperation::BlockFinalized(_, ref finalizing_entry, ref forks) => { - if let Some(finalizing_entry) = finalizing_entry.as_ref() { - finalized = Some(&finalizing_entry.valid_from); - } - for fork_index in forks.iter().rev() { - unfinalized.remove(*fork_index); - } - }, - CommitOperation::BlockReverted(ref forks) => { - for (fork_index, updated_fork) in forks.iter().rev() { - match updated_fork { - Some(updated_fork) => - unfinalized[*fork_index] = &updated_fork.head().valid_from, - None => { - unfinalized.remove(*fork_index); - }, - } - } - }, - } - - (finalized, unfinalized).encode() - } - - /// Decode meta information. - pub fn decode(encoded: &[u8]) -> ClientResult> { - let input = &mut &*encoded; - let finalized: Option> = Decode::decode(input).map_err(|_| { - ClientError::from(ClientError::Backend("Error decoding cache meta".into())) - })?; - let unfinalized: Vec> = Decode::decode(input).map_err(|_| { - ClientError::from(ClientError::Backend("Error decoding cache meta".into())) - })?; - - Ok(Metadata { finalized, unfinalized }) - } -} - -#[cfg(test)] -pub mod tests { - use super::*; - use std::collections::{HashMap, HashSet}; - - pub struct FaultyStorage; - - impl Storage for FaultyStorage { - fn read_id(&self, _at: NumberFor) -> ClientResult> { - Err(ClientError::Backend("TestError".into())) - } - - fn read_header(&self, _at: &Block::Hash) -> ClientResult> { - Err(ClientError::Backend("TestError".into())) - } - - fn read_meta(&self) -> ClientResult> { - Err(ClientError::Backend("TestError".into())) - } - - fn read_entry( - &self, - _at: &ComplexBlockId, - ) -> ClientResult>> { - Err(ClientError::Backend("TestError".into())) - } - } - - pub struct DummyStorage { - meta: Metadata, - ids: HashMap, Block::Hash>, - headers: HashMap, - entries: HashMap>, - } - - impl DummyStorage { - pub fn new() -> Self { - DummyStorage { - meta: Metadata { finalized: None, unfinalized: Vec::new() }, - ids: HashMap::new(), - headers: HashMap::new(), - entries: HashMap::new(), - } - } - - pub fn with_meta( - mut self, - finalized: Option>, - unfinalized: Vec>, - ) -> Self { - self.meta.finalized = finalized; - self.meta.unfinalized = unfinalized; - self - } - - pub fn with_id(mut self, at: NumberFor, id: Block::Hash) -> Self { - self.ids.insert(at, id); - self - } - - pub fn with_header(mut self, header: Block::Header) -> Self { - self.headers.insert(header.hash(), header); - self - } - - pub fn with_entry( - mut self, - at: ComplexBlockId, - entry: StorageEntry, - ) -> Self { - self.entries.insert(at.hash, entry); - self - } - } - - impl Storage for DummyStorage { - fn read_id(&self, at: NumberFor) -> ClientResult> { - Ok(self.ids.get(&at).cloned()) - } - - fn read_header(&self, at: &Block::Hash) -> ClientResult> { - Ok(self.headers.get(&at).cloned()) - } - - fn read_meta(&self) -> ClientResult> { - Ok(self.meta.clone()) - } - - fn read_entry( - &self, - at: &ComplexBlockId, - ) -> ClientResult>> { - Ok(self.entries.get(&at.hash).cloned()) - } - } - - pub struct DummyTransaction { - updated_meta: Option>, - inserted_entries: HashSet, - removed_entries: HashSet, - } - - impl DummyTransaction { - pub fn new() -> Self { - DummyTransaction { - updated_meta: None, - inserted_entries: HashSet::new(), - removed_entries: HashSet::new(), - } - } - - pub fn inserted_entries(&self) -> &HashSet { - &self.inserted_entries - } - - pub fn removed_entries(&self) -> &HashSet { - &self.removed_entries - } - - pub fn updated_meta(&self) -> &Option> { - &self.updated_meta - } - } - - impl StorageTransaction for DummyTransaction { - fn insert_storage_entry( - &mut self, - at: &ComplexBlockId, - _entry: &StorageEntry, - ) { - self.inserted_entries.insert(at.hash); - } - - fn remove_storage_entry(&mut self, at: &ComplexBlockId) { - self.removed_entries.insert(at.hash); - } - - fn update_meta( - &mut self, - best_finalized_entry: Option<&Entry>, - unfinalized: &[Fork], - operation: &CommitOperation, - ) { - self.updated_meta = Some( - meta::decode(&meta::encode(best_finalized_entry, unfinalized, operation)).unwrap(), - ); - } - } -} diff --git a/client/db/src/cache/mod.rs b/client/db/src/cache/mod.rs deleted file mode 100644 index 5502896aced2..000000000000 --- a/client/db/src/cache/mod.rs +++ /dev/null @@ -1,413 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2017-2021 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 . - -//! DB-backed cache of blockchain data. - -use parking_lot::RwLock; -use std::{ - collections::{hash_map::Entry, HashMap}, - sync::Arc, -}; - -use crate::{ - utils::{self, COLUMN_META}, - DbHash, -}; -use codec::{Decode, Encode}; -use sc_client_api::blockchain::{ - well_known_cache_keys::{self, Id as CacheKeyId}, - Cache as BlockchainCache, -}; -use sp_blockchain::{HeaderMetadataCache, Result as ClientResult}; -use sp_database::{Database, Transaction}; -use sp_runtime::{ - generic::BlockId, - traits::{Block as BlockT, Header as HeaderT, NumberFor, Zero}, -}; - -use self::list_cache::{ListCache, PruningStrategy}; - -mod list_cache; -mod list_entry; -mod list_storage; - -/// Minimal post-finalization age of finalized blocks before they'll pruned. -const PRUNE_DEPTH: u32 = 1024; - -/// The type of entry that is inserted to the cache. -#[derive(Clone, Copy, Debug, PartialEq)] -pub enum EntryType { - /// Non-final entry. - NonFinal, - /// Final entry. - Final, - /// Genesis entry (inserted during cache initialization). - Genesis, -} - -/// Block identifier that holds both hash and number. -#[derive(Clone, Debug, Encode, Decode, PartialEq)] -pub struct ComplexBlockId { - /// Hash of the block. - pub(crate) hash: Block::Hash, - /// Number of the block. - pub(crate) number: NumberFor, -} - -impl ComplexBlockId { - /// Create new complex block id. - pub fn new(hash: Block::Hash, number: NumberFor) -> Self { - ComplexBlockId { hash, number } - } -} - -impl ::std::cmp::PartialOrd for ComplexBlockId { - fn partial_cmp(&self, other: &ComplexBlockId) -> Option<::std::cmp::Ordering> { - self.number.partial_cmp(&other.number) - } -} - -/// All cache items must implement this trait. -pub trait CacheItemT: Clone + Decode + Encode + PartialEq {} - -impl CacheItemT for T where T: Clone + Decode + Encode + PartialEq {} - -/// Database-backed blockchain data cache. -pub struct DbCache { - cache_at: HashMap, self::list_storage::DbStorage>>, - header_metadata_cache: Arc>, - db: Arc>, - key_lookup_column: u32, - header_column: u32, - cache_column: u32, - genesis_hash: Block::Hash, - best_finalized_block: ComplexBlockId, -} - -impl DbCache { - /// Create new cache. - pub fn new( - db: Arc>, - header_metadata_cache: Arc>, - key_lookup_column: u32, - header_column: u32, - cache_column: u32, - genesis_hash: Block::Hash, - best_finalized_block: ComplexBlockId, - ) -> Self { - Self { - cache_at: HashMap::new(), - db, - header_metadata_cache, - key_lookup_column, - header_column, - cache_column, - genesis_hash, - best_finalized_block, - } - } - - /// Set genesis block hash. - pub fn set_genesis_hash(&mut self, genesis_hash: Block::Hash) { - self.genesis_hash = genesis_hash; - } - - /// Begin cache transaction. - pub fn transaction<'a>( - &'a mut self, - tx: &'a mut Transaction, - ) -> DbCacheTransaction<'a, Block> { - DbCacheTransaction { - cache: self, - tx, - cache_at_ops: HashMap::new(), - best_finalized_block: None, - } - } - - /// Begin cache transaction with given ops. - pub fn transaction_with_ops<'a>( - &'a mut self, - tx: &'a mut Transaction, - ops: DbCacheTransactionOps, - ) -> DbCacheTransaction<'a, Block> { - DbCacheTransaction { - cache: self, - tx, - cache_at_ops: ops.cache_at_ops, - best_finalized_block: ops.best_finalized_block, - } - } - - /// Run post-commit cache operations. - pub fn commit(&mut self, ops: DbCacheTransactionOps) -> ClientResult<()> { - for (name, ops) in ops.cache_at_ops.into_iter() { - self.get_cache(name)?.on_transaction_commit(ops); - } - if let Some(best_finalized_block) = ops.best_finalized_block { - self.best_finalized_block = best_finalized_block; - } - Ok(()) - } - - /// Creates `ListCache` with the given name or returns a reference to the existing. - pub(crate) fn get_cache( - &mut self, - name: CacheKeyId, - ) -> ClientResult<&mut ListCache, self::list_storage::DbStorage>> { - get_cache_helper( - &mut self.cache_at, - name, - &self.db, - self.key_lookup_column, - self.header_column, - self.cache_column, - &self.best_finalized_block, - ) - } -} - -// This helper is needed because otherwise the borrow checker will require to -// clone all parameters outside of the closure. -fn get_cache_helper<'a, Block: BlockT>( - cache_at: &'a mut HashMap, self::list_storage::DbStorage>>, - name: CacheKeyId, - db: &Arc>, - key_lookup: u32, - header: u32, - cache: u32, - best_finalized_block: &ComplexBlockId, -) -> ClientResult<&'a mut ListCache, self::list_storage::DbStorage>> { - match cache_at.entry(name) { - Entry::Occupied(entry) => Ok(entry.into_mut()), - Entry::Vacant(entry) => { - let cache = ListCache::new( - self::list_storage::DbStorage::new( - name.to_vec(), - db.clone(), - self::list_storage::DbColumns { meta: COLUMN_META, key_lookup, header, cache }, - ), - cache_pruning_strategy(name), - best_finalized_block.clone(), - )?; - Ok(entry.insert(cache)) - }, - } -} - -/// Cache operations that are to be committed after database transaction is committed. -#[derive(Default)] -pub struct DbCacheTransactionOps { - cache_at_ops: HashMap>>, - best_finalized_block: Option>, -} - -impl DbCacheTransactionOps { - /// Empty transaction ops. - pub fn empty() -> DbCacheTransactionOps { - DbCacheTransactionOps { cache_at_ops: HashMap::new(), best_finalized_block: None } - } -} - -/// Database-backed blockchain data cache transaction valid for single block import. -pub struct DbCacheTransaction<'a, Block: BlockT> { - cache: &'a mut DbCache, - tx: &'a mut Transaction, - cache_at_ops: HashMap>>, - best_finalized_block: Option>, -} - -impl<'a, Block: BlockT> DbCacheTransaction<'a, Block> { - /// Convert transaction into post-commit operations set. - pub fn into_ops(self) -> DbCacheTransactionOps { - DbCacheTransactionOps { - cache_at_ops: self.cache_at_ops, - best_finalized_block: self.best_finalized_block, - } - } - - /// When new block is inserted into database. - pub fn on_block_insert( - mut self, - parent: ComplexBlockId, - block: ComplexBlockId, - data_at: HashMap>, - entry_type: EntryType, - ) -> ClientResult { - // prepare list of caches that are not update - // (we might still need to do some cache maintenance in this case) - let missed_caches = self - .cache - .cache_at - .keys() - .filter(|cache| !data_at.contains_key(*cache)) - .cloned() - .collect::>(); - - let mut insert_op = |name: CacheKeyId, - value: Option>| - -> Result<(), sp_blockchain::Error> { - let cache = self.cache.get_cache(name)?; - let cache_ops = self.cache_at_ops.entry(name).or_default(); - cache.on_block_insert( - &mut self::list_storage::DbStorageTransaction::new(cache.storage(), &mut self.tx), - parent.clone(), - block.clone(), - value, - entry_type, - cache_ops, - )?; - - Ok(()) - }; - - data_at.into_iter().try_for_each(|(name, data)| insert_op(name, Some(data)))?; - missed_caches.into_iter().try_for_each(|name| insert_op(name, None))?; - - match entry_type { - EntryType::Final | EntryType::Genesis => self.best_finalized_block = Some(block), - EntryType::NonFinal => (), - } - - Ok(self) - } - - /// When previously inserted block is finalized. - pub fn on_block_finalize( - mut self, - parent: ComplexBlockId, - block: ComplexBlockId, - ) -> ClientResult { - for (name, cache) in self.cache.cache_at.iter() { - let cache_ops = self.cache_at_ops.entry(*name).or_default(); - cache.on_block_finalize( - &mut self::list_storage::DbStorageTransaction::new(cache.storage(), &mut self.tx), - parent.clone(), - block.clone(), - cache_ops, - )?; - } - - self.best_finalized_block = Some(block); - - Ok(self) - } - - /// When block is reverted. - pub fn on_block_revert(mut self, reverted_block: &ComplexBlockId) -> ClientResult { - for (name, cache) in self.cache.cache_at.iter() { - let cache_ops = self.cache_at_ops.entry(*name).or_default(); - cache.on_block_revert( - &mut self::list_storage::DbStorageTransaction::new(cache.storage(), &mut self.tx), - reverted_block, - cache_ops, - )?; - } - - Ok(self) - } -} - -/// Synchronous implementation of database-backed blockchain data cache. -pub struct DbCacheSync(pub RwLock>); - -impl BlockchainCache for DbCacheSync { - fn initialize(&self, key: &CacheKeyId, data: Vec) -> ClientResult<()> { - let mut cache = self.0.write(); - let genesis_hash = cache.genesis_hash; - let cache_contents = vec![(*key, data)].into_iter().collect(); - let db = cache.db.clone(); - let mut dbtx = Transaction::new(); - let tx = cache.transaction(&mut dbtx); - let tx = tx.on_block_insert( - ComplexBlockId::new(Default::default(), Zero::zero()), - ComplexBlockId::new(genesis_hash, Zero::zero()), - cache_contents, - EntryType::Genesis, - )?; - let tx_ops = tx.into_ops(); - db.commit(dbtx)?; - cache.commit(tx_ops)?; - - Ok(()) - } - - fn get_at( - &self, - key: &CacheKeyId, - at: &BlockId, - ) -> ClientResult< - Option<((NumberFor, Block::Hash), Option<(NumberFor, Block::Hash)>, Vec)>, - > { - let mut cache = self.0.write(); - let header_metadata_cache = cache.header_metadata_cache.clone(); - let cache = cache.get_cache(*key)?; - let storage = cache.storage(); - let db = storage.db(); - let columns = storage.columns(); - let at = match *at { - BlockId::Hash(hash) => match header_metadata_cache.header_metadata(hash) { - Some(metadata) => ComplexBlockId::new(hash, metadata.number), - None => { - let header = utils::require_header::( - &**db, - columns.key_lookup, - columns.header, - BlockId::Hash(hash.clone()), - )?; - ComplexBlockId::new(hash, *header.number()) - }, - }, - BlockId::Number(number) => { - let hash = utils::require_header::( - &**db, - columns.key_lookup, - columns.header, - BlockId::Number(number.clone()), - )? - .hash(); - ComplexBlockId::new(hash, number) - }, - }; - - cache.value_at_block(&at).map(|block_and_value| { - block_and_value.map(|(begin_block, end_block, value)| { - ( - (begin_block.number, begin_block.hash), - end_block.map(|end_block| (end_block.number, end_block.hash)), - value, - ) - }) - }) - } -} - -/// Get pruning strategy for given cache. -fn cache_pruning_strategy>(cache: CacheKeyId) -> PruningStrategy { - // the cache is mostly used to store data from consensus engines - // this kind of data is only required for non-finalized blocks - // => by default we prune finalized cached entries - - match cache { - // we need to keep changes tries configurations forever (or at least until changes tries, - // that were built using this configuration, are pruned) to make it possible to refer - // to old changes tries - well_known_cache_keys::CHANGES_TRIE_CONFIG => PruningStrategy::NeverPrune, - _ => PruningStrategy::ByDepth(PRUNE_DEPTH.into()), - } -} diff --git a/client/db/src/changes_tries_storage.rs b/client/db/src/changes_tries_storage.rs deleted file mode 100644 index 3a3c5918535f..000000000000 --- a/client/db/src/changes_tries_storage.rs +++ /dev/null @@ -1,1168 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2019-2021 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 . - -//! DB-backed changes tries storage. - -use crate::{ - cache::{ - ComplexBlockId, DbCache, DbCacheSync, DbCacheTransactionOps, EntryType as CacheEntryType, - }, - utils::{self, meta_keys, Meta}, - Database, DbHash, -}; -use codec::{Decode, Encode}; -use hash_db::Prefix; -use parking_lot::RwLock; -use sc_client_api::backend::PrunableStateChangesTrieStorage; -use sp_blockchain::{ - well_known_cache_keys, Cache as BlockchainCache, Error as ClientError, HeaderMetadataCache, - Result as ClientResult, -}; -use sp_core::{ - convert_hash, storage::PrefixedStorageKey, ChangesTrieConfiguration, - ChangesTrieConfigurationRange, -}; -use sp_database::Transaction; -use sp_runtime::{ - generic::{BlockId, ChangesTrieSignal, DigestItem}, - traits::{Block as BlockT, CheckedSub, HashFor, Header as HeaderT, NumberFor, One, Zero}, -}; -use sp_state_machine::{ChangesTrieBuildCache, ChangesTrieCacheAction}; -use sp_trie::MemoryDB; -use std::{ - collections::{HashMap, HashSet}, - sync::Arc, -}; - -/// Extract new changes trie configuration (if available) from the header. -pub fn extract_new_configuration( - header: &Header, -) -> Option<&Option> { - header - .digest() - .log(DigestItem::as_changes_trie_signal) - .and_then(ChangesTrieSignal::as_new_configuration) -} - -/// Opaque configuration cache transaction. During its lifetime, no-one should modify cache. This is -/// currently guaranteed because import lock is held during block import/finalization. -pub struct DbChangesTrieStorageTransaction { - /// Cache operations that must be performed after db transaction is committed. - cache_ops: DbCacheTransactionOps, - /// New configuration (if changed at current block). - new_config: Option>, -} - -impl DbChangesTrieStorageTransaction { - /// Consume self and return transaction with given new configuration. - pub fn with_new_config(mut self, new_config: Option>) -> Self { - self.new_config = new_config; - self - } -} - -impl From> for DbChangesTrieStorageTransaction { - fn from(cache_ops: DbCacheTransactionOps) -> Self { - DbChangesTrieStorageTransaction { cache_ops, new_config: None } - } -} - -/// Changes tries storage. -/// -/// Stores all tries in separate DB column. -/// Lock order: meta, tries_meta, cache, build_cache. -pub struct DbChangesTrieStorage { - db: Arc>, - meta_column: u32, - changes_tries_column: u32, - key_lookup_column: u32, - header_column: u32, - meta: Arc, Block::Hash>>>, - tries_meta: RwLock>, - min_blocks_to_keep: Option, - /// The cache stores all ever existing changes tries configurations. - cache: DbCacheSync, - /// Build cache is a map of block => set of storage keys changed at this block. - /// They're used to build digest blocks - instead of reading+parsing tries from db - /// we just use keys sets from the cache. - build_cache: RwLock>>, -} - -/// Persistent struct that contains all the changes tries metadata. -#[derive(Decode, Encode, Debug)] -struct ChangesTriesMeta { - /// Oldest unpruned max-level (or skewed) digest trie blocks range. - /// The range is inclusive from both sides. - /// Is None only if: - /// 1) we haven't yet finalized any blocks (except genesis) - /// 2) if best_finalized_block - min_blocks_to_keep points to the range where changes tries are - /// disabled 3) changes tries pruning is disabled - pub oldest_digest_range: Option<(NumberFor, NumberFor)>, - /// End block (inclusive) of oldest pruned max-level (or skewed) digest trie blocks range. - /// It is guaranteed that we have no any changes tries before (and including) this block. - /// It is guaranteed that all existing changes tries after this block are not yet pruned (if - /// created). - pub oldest_pruned_digest_range_end: NumberFor, -} - -impl DbChangesTrieStorage { - /// Create new changes trie storage. - pub fn new( - db: Arc>, - header_metadata_cache: Arc>, - meta_column: u32, - changes_tries_column: u32, - key_lookup_column: u32, - header_column: u32, - cache_column: u32, - meta: Arc, Block::Hash>>>, - min_blocks_to_keep: Option, - ) -> ClientResult { - let (finalized_hash, finalized_number, genesis_hash) = { - let meta = meta.read(); - (meta.finalized_hash, meta.finalized_number, meta.genesis_hash) - }; - let tries_meta = read_tries_meta(&*db, meta_column)?; - Ok(Self { - db: db.clone(), - meta_column, - changes_tries_column, - key_lookup_column, - header_column, - meta, - min_blocks_to_keep, - cache: DbCacheSync(RwLock::new(DbCache::new( - db.clone(), - header_metadata_cache, - key_lookup_column, - header_column, - cache_column, - genesis_hash, - ComplexBlockId::new(finalized_hash, finalized_number), - ))), - build_cache: RwLock::new(ChangesTrieBuildCache::new()), - tries_meta: RwLock::new(tries_meta), - }) - } - - /// Commit new changes trie. - pub fn commit( - &self, - tx: &mut Transaction, - mut changes_trie: MemoryDB>, - parent_block: ComplexBlockId, - block: ComplexBlockId, - new_header: &Block::Header, - finalized: bool, - new_configuration: Option>, - cache_tx: Option>, - ) -> ClientResult> { - // insert changes trie, associated with block, into DB - for (key, (val, _)) in changes_trie.drain() { - tx.set(self.changes_tries_column, key.as_ref(), &val); - } - - // if configuration has not been changed AND block is not finalized => nothing to do here - let new_configuration = match new_configuration { - Some(new_configuration) => new_configuration, - None if !finalized => return Ok(DbCacheTransactionOps::empty().into()), - None => - return self.finalize( - tx, - parent_block.hash, - block.hash, - block.number, - Some(new_header), - cache_tx, - ), - }; - - // update configuration cache - let mut cache_at = HashMap::new(); - cache_at.insert(well_known_cache_keys::CHANGES_TRIE_CONFIG, new_configuration.encode()); - Ok(DbChangesTrieStorageTransaction::from(match cache_tx { - Some(cache_tx) => self - .cache - .0 - .write() - .transaction_with_ops(tx, cache_tx.cache_ops) - .on_block_insert( - parent_block, - block, - cache_at, - if finalized { CacheEntryType::Final } else { CacheEntryType::NonFinal }, - )? - .into_ops(), - None => self - .cache - .0 - .write() - .transaction(tx) - .on_block_insert( - parent_block, - block, - cache_at, - if finalized { CacheEntryType::Final } else { CacheEntryType::NonFinal }, - )? - .into_ops(), - }) - .with_new_config(Some(new_configuration))) - } - - /// Called when block is finalized. - pub fn finalize( - &self, - tx: &mut Transaction, - parent_block_hash: Block::Hash, - block_hash: Block::Hash, - block_num: NumberFor, - new_header: Option<&Block::Header>, - cache_tx: Option>, - ) -> ClientResult> { - // prune obsolete changes tries - self.prune(tx, block_hash, block_num, new_header.clone(), cache_tx.as_ref())?; - - // if we have inserted the block that we're finalizing in the same transaction - // => then we have already finalized it from the commit() call - if cache_tx.is_some() { - if let Some(new_header) = new_header { - if new_header.hash() == block_hash { - return Ok(cache_tx.expect("guarded by cache_tx.is_some(); qed")) - } - } - } - - // and finalize configuration cache entries - let block = ComplexBlockId::new(block_hash, block_num); - let parent_block_num = block_num.checked_sub(&One::one()).unwrap_or_else(|| Zero::zero()); - let parent_block = ComplexBlockId::new(parent_block_hash, parent_block_num); - Ok(match cache_tx { - Some(cache_tx) => DbChangesTrieStorageTransaction::from( - self.cache - .0 - .write() - .transaction_with_ops(tx, cache_tx.cache_ops) - .on_block_finalize(parent_block, block)? - .into_ops(), - ) - .with_new_config(cache_tx.new_config), - None => DbChangesTrieStorageTransaction::from( - self.cache - .0 - .write() - .transaction(tx) - .on_block_finalize(parent_block, block)? - .into_ops(), - ), - }) - } - - /// When block is reverted. - pub fn revert( - &self, - tx: &mut Transaction, - block: &ComplexBlockId, - ) -> ClientResult> { - Ok(self.cache.0.write().transaction(tx).on_block_revert(block)?.into_ops().into()) - } - - /// When transaction has been committed. - pub fn post_commit(&self, tx: Option>) { - if let Some(tx) = tx { - self.cache.0.write().commit(tx.cache_ops).expect( - "only fails if cache with given name isn't loaded yet; cache is already loaded \ - because there is tx; qed", - ); - } - } - - /// Commit changes into changes trie build cache. - pub fn commit_build_cache( - &self, - cache_update: ChangesTrieCacheAction>, - ) { - self.build_cache.write().perform(cache_update); - } - - /// Prune obsolete changes tries. - fn prune( - &self, - tx: &mut Transaction, - block_hash: Block::Hash, - block_num: NumberFor, - new_header: Option<&Block::Header>, - cache_tx: Option<&DbChangesTrieStorageTransaction>, - ) -> ClientResult<()> { - // never prune on archive nodes - let min_blocks_to_keep = match self.min_blocks_to_keep { - Some(min_blocks_to_keep) => min_blocks_to_keep, - None => return Ok(()), - }; - - let mut tries_meta = self.tries_meta.write(); - let mut next_digest_range_start = block_num; - loop { - // prune oldest digest if it is known - // it could be unknown if: - // 1) either we're finalizing block#1 - // 2) or we are (or were) in period where changes tries are disabled - if let Some((begin, end)) = tries_meta.oldest_digest_range { - if block_num <= end || block_num - end <= min_blocks_to_keep.into() { - break - } - - tries_meta.oldest_pruned_digest_range_end = end; - sp_state_machine::prune_changes_tries( - &*self, - begin, - end, - &sp_state_machine::ChangesTrieAnchorBlockId { - hash: convert_hash(&block_hash), - number: block_num, - }, - |node| tx.remove(self.changes_tries_column, node.as_ref()), - ); - - next_digest_range_start = end + One::one(); - } - - // proceed to the next configuration range - let next_digest_range_start_hash = match block_num == next_digest_range_start { - true => block_hash, - false => utils::require_header::( - &*self.db, - self.key_lookup_column, - self.header_column, - BlockId::Number(next_digest_range_start), - )? - .hash(), - }; - - let config_for_new_block = new_header - .map(|header| *header.number() == next_digest_range_start) - .unwrap_or(false); - let next_config = match cache_tx { - Some(cache_tx) if config_for_new_block && cache_tx.new_config.is_some() => { - let config = cache_tx.new_config.clone().expect("guarded by is_some(); qed"); - Ok(ChangesTrieConfigurationRange { - zero: (block_num, block_hash), - end: None, - config, - }) - }, - _ if config_for_new_block => self.configuration_at(&BlockId::Hash( - *new_header - .expect("config_for_new_block is only true when new_header is passed; qed") - .parent_hash(), - )), - _ => self.configuration_at(&BlockId::Hash(next_digest_range_start_hash)), - }; - let next_config = match next_config { - Ok(next_config) => next_config, - Err(ClientError::UnknownBlock(_)) => break, // No block means nothing to prune. - Err(e) => return Err(e), - }; - if let Some(config) = next_config.config { - let mut oldest_digest_range = config - .next_max_level_digest_range(next_config.zero.0, next_digest_range_start) - .unwrap_or_else(|| (next_digest_range_start, next_digest_range_start)); - - if let Some(end) = next_config.end { - if end.0 < oldest_digest_range.1 { - oldest_digest_range.1 = end.0; - } - } - - tries_meta.oldest_digest_range = Some(oldest_digest_range); - continue - } - - tries_meta.oldest_digest_range = None; - break - } - - write_tries_meta(tx, self.meta_column, &*tries_meta); - Ok(()) - } -} - -impl PrunableStateChangesTrieStorage for DbChangesTrieStorage { - fn storage( - &self, - ) -> &dyn sp_state_machine::ChangesTrieStorage, NumberFor> { - self - } - - fn configuration_at( - &self, - at: &BlockId, - ) -> ClientResult, Block::Hash>> { - self.cache - .get_at(&well_known_cache_keys::CHANGES_TRIE_CONFIG, at)? - .and_then(|(zero, end, encoded)| { - Decode::decode(&mut &encoded[..]) - .ok() - .map(|config| ChangesTrieConfigurationRange { zero, end, config }) - }) - .ok_or_else(|| ClientError::ErrorReadingChangesTriesConfig) - } - - fn oldest_pruned_digest_range_end(&self) -> NumberFor { - self.tries_meta.read().oldest_pruned_digest_range_end - } -} - -impl sp_state_machine::ChangesTrieRootsStorage, NumberFor> - for DbChangesTrieStorage -{ - fn build_anchor( - &self, - hash: Block::Hash, - ) -> Result>, String> { - utils::read_header::( - &*self.db, - self.key_lookup_column, - self.header_column, - BlockId::Hash(hash), - ) - .map_err(|e| e.to_string()) - .and_then(|maybe_header| { - maybe_header - .map(|header| sp_state_machine::ChangesTrieAnchorBlockId { - hash, - number: *header.number(), - }) - .ok_or_else(|| format!("Unknown header: {}", hash)) - }) - } - - fn root( - &self, - anchor: &sp_state_machine::ChangesTrieAnchorBlockId>, - block: NumberFor, - ) -> Result, String> { - // check API requirement: we can't get NEXT block(s) based on anchor - if block > anchor.number { - return Err(format!( - "Can't get changes trie root at {} using anchor at {}", - block, anchor.number - )) - } - - // we need to get hash of the block to resolve changes trie root - let block_id = if block <= self.meta.read().finalized_number { - // if block is finalized, we could just read canonical hash - BlockId::Number(block) - } else { - // the block is not finalized - let mut current_num = anchor.number; - let mut current_hash: Block::Hash = convert_hash(&anchor.hash); - let maybe_anchor_header: Block::Header = utils::require_header::( - &*self.db, - self.key_lookup_column, - self.header_column, - BlockId::Number(current_num), - ) - .map_err(|e| e.to_string())?; - if maybe_anchor_header.hash() == current_hash { - // if anchor is canonicalized, then the block is also canonicalized - BlockId::Number(block) - } else { - // else (block is not finalized + anchor is not canonicalized): - // => we should find the required block hash by traversing - // back from the anchor to the block with given number - while current_num != block { - let current_header: Block::Header = utils::require_header::( - &*self.db, - self.key_lookup_column, - self.header_column, - BlockId::Hash(current_hash), - ) - .map_err(|e| e.to_string())?; - - current_hash = *current_header.parent_hash(); - current_num = current_num - One::one(); - } - - BlockId::Hash(current_hash) - } - }; - - Ok(utils::require_header::( - &*self.db, - self.key_lookup_column, - self.header_column, - block_id, - ) - .map_err(|e| e.to_string())? - .digest() - .log(DigestItem::as_changes_trie_root) - .cloned()) - } -} - -impl sp_state_machine::ChangesTrieStorage, NumberFor> - for DbChangesTrieStorage -where - Block: BlockT, -{ - fn as_roots_storage( - &self, - ) -> &dyn sp_state_machine::ChangesTrieRootsStorage, NumberFor> { - self - } - - fn with_cached_changed_keys( - &self, - root: &Block::Hash, - functor: &mut dyn FnMut(&HashMap, HashSet>>), - ) -> bool { - self.build_cache.read().with_changed_keys(root, functor) - } - - fn get(&self, key: &Block::Hash, _prefix: Prefix) -> Result>, String> { - Ok(self.db.get(self.changes_tries_column, key.as_ref())) - } -} - -/// Read changes tries metadata from database. -fn read_tries_meta( - db: &dyn Database, - meta_column: u32, -) -> ClientResult> { - match db.get(meta_column, meta_keys::CHANGES_TRIES_META) { - Some(h) => Decode::decode(&mut &h[..]).map_err(|err| { - ClientError::Backend(format!("Error decoding changes tries metadata: {}", err)) - }), - None => Ok(ChangesTriesMeta { - oldest_digest_range: None, - oldest_pruned_digest_range_end: Zero::zero(), - }), - } -} - -/// Write changes tries metadata from database. -fn write_tries_meta( - tx: &mut Transaction, - meta_column: u32, - meta: &ChangesTriesMeta, -) { - tx.set_from_vec(meta_column, meta_keys::CHANGES_TRIES_META, meta.encode()); -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::{ - tests::{insert_header, prepare_changes, Block}, - Backend, - }; - use hash_db::EMPTY_PREFIX; - use sc_client_api::backend::{ - Backend as ClientBackend, BlockImportOperation, NewBlockState, - PrunableStateChangesTrieStorage, - }; - use sp_blockchain::HeaderBackend as BlockchainHeaderBackend; - use sp_core::H256; - use sp_runtime::{ - testing::{Digest, Header}, - traits::{BlakeTwo256, Hash}, - }; - use sp_state_machine::{ChangesTrieRootsStorage, ChangesTrieStorage}; - - fn changes(number: u64) -> Option, Vec)>> { - Some(vec![(number.to_le_bytes().to_vec(), number.to_le_bytes().to_vec())]) - } - - fn insert_header_with_configuration_change( - backend: &Backend, - number: u64, - parent_hash: H256, - changes: Option, Vec)>>, - new_configuration: Option, - ) -> H256 { - let mut digest = Digest::default(); - let mut changes_trie_update = Default::default(); - if let Some(changes) = changes { - let (root, update) = prepare_changes(changes); - digest.push(DigestItem::ChangesTrieRoot(root)); - changes_trie_update = update; - } - digest.push(DigestItem::ChangesTrieSignal(ChangesTrieSignal::NewConfiguration( - new_configuration, - ))); - - let header = Header { - number, - parent_hash, - state_root: BlakeTwo256::trie_root(Vec::new()), - digest, - extrinsics_root: Default::default(), - }; - let header_hash = header.hash(); - - let block_id = if number == 0 { - BlockId::Hash(Default::default()) - } else { - BlockId::Number(number - 1) - }; - let mut op = backend.begin_operation().unwrap(); - backend.begin_state_operation(&mut op, block_id).unwrap(); - op.set_block_data(header, None, None, None, NewBlockState::Best).unwrap(); - op.update_changes_trie((changes_trie_update, ChangesTrieCacheAction::Clear)) - .unwrap(); - backend.commit_operation(op).unwrap(); - - header_hash - } - - #[test] - fn changes_trie_storage_works() { - let backend = Backend::::new_test(1000, 100); - backend.changes_tries_storage.meta.write().finalized_number = 1000; - - let check_changes = |backend: &Backend, - block: u64, - changes: Vec<(Vec, Vec)>| { - let (changes_root, mut changes_trie_update) = prepare_changes(changes); - let anchor = sp_state_machine::ChangesTrieAnchorBlockId { - hash: backend.blockchain().header(BlockId::Number(block)).unwrap().unwrap().hash(), - number: block, - }; - assert_eq!(backend.changes_tries_storage.root(&anchor, block), Ok(Some(changes_root))); - - let storage = backend.changes_tries_storage.storage(); - for (key, (val, _)) in changes_trie_update.drain() { - assert_eq!(storage.get(&key, EMPTY_PREFIX), Ok(Some(val))); - } - }; - - let changes0 = vec![(b"key_at_0".to_vec(), b"val_at_0".to_vec())]; - let changes1 = vec![ - (b"key_at_1".to_vec(), b"val_at_1".to_vec()), - (b"another_key_at_1".to_vec(), b"another_val_at_1".to_vec()), - ]; - let changes2 = vec![(b"key_at_2".to_vec(), b"val_at_2".to_vec())]; - - let block0 = insert_header( - &backend, - 0, - Default::default(), - Some(changes0.clone()), - Default::default(), - ); - let block1 = insert_header(&backend, 1, block0, Some(changes1.clone()), Default::default()); - let _ = insert_header(&backend, 2, block1, Some(changes2.clone()), Default::default()); - - // check that the storage contains tries for all blocks - check_changes(&backend, 0, changes0); - check_changes(&backend, 1, changes1); - check_changes(&backend, 2, changes2); - } - - #[test] - fn changes_trie_storage_works_with_forks() { - let backend = Backend::::new_test(1000, 100); - - let changes0 = vec![(b"k0".to_vec(), b"v0".to_vec())]; - let changes1 = vec![(b"k1".to_vec(), b"v1".to_vec())]; - let changes2 = vec![(b"k2".to_vec(), b"v2".to_vec())]; - let block0 = insert_header( - &backend, - 0, - Default::default(), - Some(changes0.clone()), - Default::default(), - ); - let block1 = insert_header(&backend, 1, block0, Some(changes1.clone()), Default::default()); - let block2 = insert_header(&backend, 2, block1, Some(changes2.clone()), Default::default()); - - let changes2_1_0 = vec![(b"k3".to_vec(), b"v3".to_vec())]; - let changes2_1_1 = vec![(b"k4".to_vec(), b"v4".to_vec())]; - let block2_1_0 = - insert_header(&backend, 3, block2, Some(changes2_1_0.clone()), Default::default()); - let block2_1_1 = - insert_header(&backend, 4, block2_1_0, Some(changes2_1_1.clone()), Default::default()); - - let changes2_2_0 = vec![(b"k5".to_vec(), b"v5".to_vec())]; - let changes2_2_1 = vec![(b"k6".to_vec(), b"v6".to_vec())]; - let block2_2_0 = - insert_header(&backend, 3, block2, Some(changes2_2_0.clone()), Default::default()); - let block2_2_1 = - insert_header(&backend, 4, block2_2_0, Some(changes2_2_1.clone()), Default::default()); - - // finalize block1 - backend.changes_tries_storage.meta.write().finalized_number = 1; - - // branch1: when asking for finalized block hash - let (changes1_root, _) = prepare_changes(changes1); - let anchor = sp_state_machine::ChangesTrieAnchorBlockId { hash: block2_1_1, number: 4 }; - assert_eq!(backend.changes_tries_storage.root(&anchor, 1), Ok(Some(changes1_root))); - - // branch2: when asking for finalized block hash - let anchor = sp_state_machine::ChangesTrieAnchorBlockId { hash: block2_2_1, number: 4 }; - assert_eq!(backend.changes_tries_storage.root(&anchor, 1), Ok(Some(changes1_root))); - - // branch1: when asking for non-finalized block hash (search by traversal) - let (changes2_1_0_root, _) = prepare_changes(changes2_1_0); - let anchor = sp_state_machine::ChangesTrieAnchorBlockId { hash: block2_1_1, number: 4 }; - assert_eq!(backend.changes_tries_storage.root(&anchor, 3), Ok(Some(changes2_1_0_root))); - - // branch2: when asking for non-finalized block hash (search using canonicalized hint) - let (changes2_2_0_root, _) = prepare_changes(changes2_2_0); - let anchor = sp_state_machine::ChangesTrieAnchorBlockId { hash: block2_2_1, number: 4 }; - assert_eq!(backend.changes_tries_storage.root(&anchor, 3), Ok(Some(changes2_2_0_root))); - - // finalize first block of branch2 (block2_2_0) - backend.changes_tries_storage.meta.write().finalized_number = 3; - - // branch2: when asking for finalized block of this branch - assert_eq!(backend.changes_tries_storage.root(&anchor, 3), Ok(Some(changes2_2_0_root))); - - // branch1: when asking for finalized block of other branch - // => result is incorrect (returned for the block of branch1), but this is expected, - // because the other fork is abandoned (forked before finalized header) - let anchor = sp_state_machine::ChangesTrieAnchorBlockId { hash: block2_1_1, number: 4 }; - assert_eq!(backend.changes_tries_storage.root(&anchor, 3), Ok(Some(changes2_2_0_root))); - } - - #[test] - fn changes_tries_are_pruned_on_finalization() { - let mut backend = Backend::::new_test(1000, 100); - backend.changes_tries_storage.min_blocks_to_keep = Some(8); - - let parent_hash = |number| { - if number == 0 { - Default::default() - } else { - backend - .blockchain() - .header(BlockId::Number(number - 1)) - .unwrap() - .unwrap() - .hash() - } - }; - - let insert_regular_header = |with_changes, number| { - insert_header( - &backend, - number, - parent_hash(number), - if with_changes { changes(number) } else { None }, - Default::default(), - ); - }; - - let is_pruned = |number| { - let trie_root = backend - .blockchain() - .header(BlockId::Number(number)) - .unwrap() - .unwrap() - .digest() - .log(DigestItem::as_changes_trie_root) - .cloned(); - match trie_root { - Some(trie_root) => - backend.changes_tries_storage.get(&trie_root, EMPTY_PREFIX).unwrap().is_none(), - None => true, - } - }; - - let finalize_block = |number| { - let header = backend.blockchain().header(BlockId::Number(number)).unwrap().unwrap(); - let mut tx = Transaction::new(); - let cache_ops = backend - .changes_tries_storage - .finalize(&mut tx, *header.parent_hash(), header.hash(), number, None, None) - .unwrap(); - backend.storage.db.commit(tx).unwrap(); - backend.changes_tries_storage.post_commit(Some(cache_ops)); - }; - - // configuration ranges: - // (0; 6] - None - // [7; 17] - Some(2^2): D2 is built at #10, #14; SD is built at #17 - // [18; 21] - None - // [22; 32] - Some(8^1): D1 is built at #29; SD is built at #32 - // [33; ... - Some(1) - let config_at_6 = Some(ChangesTrieConfiguration::new(2, 2)); - let config_at_17 = None; - let config_at_21 = Some(ChangesTrieConfiguration::new(8, 1)); - let config_at_32 = Some(ChangesTrieConfiguration::new(1, 0)); - - (0..6).for_each(|number| insert_regular_header(false, number)); - insert_header_with_configuration_change(&backend, 6, parent_hash(6), None, config_at_6); - (7..17).for_each(|number| insert_regular_header(true, number)); - insert_header_with_configuration_change( - &backend, - 17, - parent_hash(17), - changes(17), - config_at_17, - ); - (18..21).for_each(|number| insert_regular_header(false, number)); - insert_header_with_configuration_change(&backend, 21, parent_hash(21), None, config_at_21); - (22..32).for_each(|number| insert_regular_header(true, number)); - insert_header_with_configuration_change( - &backend, - 32, - parent_hash(32), - changes(32), - config_at_32, - ); - (33..50).for_each(|number| insert_regular_header(true, number)); - - // when only genesis is finalized, nothing is pruned - (0..=6).for_each(|number| assert!(is_pruned(number))); - (7..=17).for_each(|number| assert!(!is_pruned(number))); - (18..=21).for_each(|number| assert!(is_pruned(number))); - (22..50).for_each(|number| assert!(!is_pruned(number))); - - // when blocks [1; 18] are finalized, nothing is pruned - (1..=18).for_each(|number| finalize_block(number)); - (0..=6).for_each(|number| assert!(is_pruned(number))); - (7..=17).for_each(|number| assert!(!is_pruned(number))); - (18..=21).for_each(|number| assert!(is_pruned(number))); - (22..50).for_each(|number| assert!(!is_pruned(number))); - - // when block 19 is finalized, changes tries for blocks [7; 10] are pruned - finalize_block(19); - (0..=10).for_each(|number| assert!(is_pruned(number))); - (11..=17).for_each(|number| assert!(!is_pruned(number))); - (18..=21).for_each(|number| assert!(is_pruned(number))); - (22..50).for_each(|number| assert!(!is_pruned(number))); - - // when blocks [20; 22] are finalized, nothing is pruned - (20..=22).for_each(|number| finalize_block(number)); - (0..=10).for_each(|number| assert!(is_pruned(number))); - (11..=17).for_each(|number| assert!(!is_pruned(number))); - (18..=21).for_each(|number| assert!(is_pruned(number))); - (22..50).for_each(|number| assert!(!is_pruned(number))); - - // when block 23 is finalized, changes tries for blocks [11; 14] are pruned - finalize_block(23); - (0..=14).for_each(|number| assert!(is_pruned(number))); - (15..=17).for_each(|number| assert!(!is_pruned(number))); - (18..=21).for_each(|number| assert!(is_pruned(number))); - (22..50).for_each(|number| assert!(!is_pruned(number))); - - // when blocks [24; 25] are finalized, nothing is pruned - (24..=25).for_each(|number| finalize_block(number)); - (0..=14).for_each(|number| assert!(is_pruned(number))); - (15..=17).for_each(|number| assert!(!is_pruned(number))); - (18..=21).for_each(|number| assert!(is_pruned(number))); - (22..50).for_each(|number| assert!(!is_pruned(number))); - - // when block 26 is finalized, changes tries for blocks [15; 17] are pruned - finalize_block(26); - (0..=21).for_each(|number| assert!(is_pruned(number))); - (22..50).for_each(|number| assert!(!is_pruned(number))); - - // when blocks [27; 37] are finalized, nothing is pruned - (27..=37).for_each(|number| finalize_block(number)); - (0..=21).for_each(|number| assert!(is_pruned(number))); - (22..50).for_each(|number| assert!(!is_pruned(number))); - - // when block 38 is finalized, changes tries for blocks [22; 29] are pruned - finalize_block(38); - (0..=29).for_each(|number| assert!(is_pruned(number))); - (30..50).for_each(|number| assert!(!is_pruned(number))); - - // when blocks [39; 40] are finalized, nothing is pruned - (39..=40).for_each(|number| finalize_block(number)); - (0..=29).for_each(|number| assert!(is_pruned(number))); - (30..50).for_each(|number| assert!(!is_pruned(number))); - - // when block 41 is finalized, changes tries for blocks [30; 32] are pruned - finalize_block(41); - (0..=32).for_each(|number| assert!(is_pruned(number))); - (33..50).for_each(|number| assert!(!is_pruned(number))); - - // when block 42 is finalized, changes trie for block 33 is pruned - finalize_block(42); - (0..=33).for_each(|number| assert!(is_pruned(number))); - (34..50).for_each(|number| assert!(!is_pruned(number))); - - // when block 43 is finalized, changes trie for block 34 is pruned - finalize_block(43); - (0..=34).for_each(|number| assert!(is_pruned(number))); - (35..50).for_each(|number| assert!(!is_pruned(number))); - } - - #[test] - fn changes_tries_configuration_is_updated_on_block_insert() { - let backend = Backend::::new_test(1000, 100); - - // configurations at blocks - let config_at_1 = Some(ChangesTrieConfiguration { digest_interval: 4, digest_levels: 2 }); - let config_at_3 = Some(ChangesTrieConfiguration { digest_interval: 8, digest_levels: 1 }); - let config_at_5 = None; - let config_at_7 = Some(ChangesTrieConfiguration { digest_interval: 8, digest_levels: 1 }); - - // insert some blocks - let block0 = insert_header(&backend, 0, Default::default(), None, Default::default()); - let block1 = - insert_header_with_configuration_change(&backend, 1, block0, None, config_at_1.clone()); - let block2 = insert_header(&backend, 2, block1, None, Default::default()); - let block3 = - insert_header_with_configuration_change(&backend, 3, block2, None, config_at_3.clone()); - let block4 = insert_header(&backend, 4, block3, None, Default::default()); - let block5 = - insert_header_with_configuration_change(&backend, 5, block4, None, config_at_5.clone()); - let block6 = insert_header(&backend, 6, block5, None, Default::default()); - let block7 = - insert_header_with_configuration_change(&backend, 7, block6, None, config_at_7.clone()); - - // test configuration cache - let storage = &backend.changes_tries_storage; - assert_eq!( - storage.configuration_at(&BlockId::Hash(block1)).unwrap().config, - config_at_1.clone(), - ); - assert_eq!( - storage.configuration_at(&BlockId::Hash(block2)).unwrap().config, - config_at_1.clone(), - ); - assert_eq!( - storage.configuration_at(&BlockId::Hash(block3)).unwrap().config, - config_at_3.clone(), - ); - assert_eq!( - storage.configuration_at(&BlockId::Hash(block4)).unwrap().config, - config_at_3.clone(), - ); - assert_eq!( - storage.configuration_at(&BlockId::Hash(block5)).unwrap().config, - config_at_5.clone(), - ); - assert_eq!( - storage.configuration_at(&BlockId::Hash(block6)).unwrap().config, - config_at_5.clone(), - ); - assert_eq!( - storage.configuration_at(&BlockId::Hash(block7)).unwrap().config, - config_at_7.clone(), - ); - } - - #[test] - fn test_finalize_several_configuration_change_blocks_in_single_operation() { - let mut backend = Backend::::new_test(10, 10); - backend.changes_tries_storage.min_blocks_to_keep = Some(8); - - let configs = - (0..=7).map(|i| Some(ChangesTrieConfiguration::new(2, i))).collect::>(); - - // insert unfinalized headers - let block0 = insert_header_with_configuration_change( - &backend, - 0, - Default::default(), - None, - configs[0].clone(), - ); - let block1 = insert_header_with_configuration_change( - &backend, - 1, - block0, - changes(1), - configs[1].clone(), - ); - let block2 = insert_header_with_configuration_change( - &backend, - 2, - block1, - changes(2), - configs[2].clone(), - ); - - let side_config2_1 = Some(ChangesTrieConfiguration::new(3, 2)); - let side_config2_2 = Some(ChangesTrieConfiguration::new(3, 3)); - let block2_1 = insert_header_with_configuration_change( - &backend, - 2, - block1, - changes(8), - side_config2_1.clone(), - ); - let _ = insert_header_with_configuration_change( - &backend, - 3, - block2_1, - changes(9), - side_config2_2.clone(), - ); - - // insert finalized header => 4 headers are finalized at once - let header3 = Header { - number: 3, - parent_hash: block2, - state_root: Default::default(), - digest: Digest { - logs: vec![DigestItem::ChangesTrieSignal(ChangesTrieSignal::NewConfiguration( - configs[3].clone(), - ))], - }, - extrinsics_root: Default::default(), - }; - let block3 = header3.hash(); - let mut op = backend.begin_operation().unwrap(); - backend.begin_state_operation(&mut op, BlockId::Hash(block2)).unwrap(); - op.mark_finalized(BlockId::Hash(block1), None).unwrap(); - op.mark_finalized(BlockId::Hash(block2), None).unwrap(); - op.set_block_data(header3, None, None, None, NewBlockState::Final).unwrap(); - backend.commit_operation(op).unwrap(); - - // insert more unfinalized headers - let block4 = insert_header_with_configuration_change( - &backend, - 4, - block3, - changes(4), - configs[4].clone(), - ); - let block5 = insert_header_with_configuration_change( - &backend, - 5, - block4, - changes(5), - configs[5].clone(), - ); - let block6 = insert_header_with_configuration_change( - &backend, - 6, - block5, - changes(6), - configs[6].clone(), - ); - - // insert finalized header => 4 headers are finalized at once - let header7 = Header { - number: 7, - parent_hash: block6, - state_root: Default::default(), - digest: Digest { - logs: vec![DigestItem::ChangesTrieSignal(ChangesTrieSignal::NewConfiguration( - configs[7].clone(), - ))], - }, - extrinsics_root: Default::default(), - }; - let mut op = backend.begin_operation().unwrap(); - backend.begin_state_operation(&mut op, BlockId::Hash(block6)).unwrap(); - op.mark_finalized(BlockId::Hash(block4), None).unwrap(); - op.mark_finalized(BlockId::Hash(block5), None).unwrap(); - op.mark_finalized(BlockId::Hash(block6), None).unwrap(); - op.set_block_data(header7, None, None, None, NewBlockState::Final).unwrap(); - backend.commit_operation(op).unwrap(); - } - - #[test] - fn changes_tries_configuration_is_reverted() { - let backend = Backend::::new_test(10, 10); - - let config0 = Some(ChangesTrieConfiguration::new(2, 5)); - let block0 = - insert_header_with_configuration_change(&backend, 0, Default::default(), None, config0); - let config1 = Some(ChangesTrieConfiguration::new(2, 6)); - let block1 = - insert_header_with_configuration_change(&backend, 1, block0, changes(0), config1); - let just1 = Some((*b"TEST", vec![42])); - backend.finalize_block(BlockId::Number(1), just1).unwrap(); - let config2 = Some(ChangesTrieConfiguration::new(2, 7)); - let block2 = - insert_header_with_configuration_change(&backend, 2, block1, changes(1), config2); - let config2_1 = Some(ChangesTrieConfiguration::new(2, 8)); - let _ = - insert_header_with_configuration_change(&backend, 3, block2, changes(10), config2_1); - let config2_2 = Some(ChangesTrieConfiguration::new(2, 9)); - let block2_2 = - insert_header_with_configuration_change(&backend, 3, block2, changes(20), config2_2); - let config2_3 = Some(ChangesTrieConfiguration::new(2, 10)); - let _ = - insert_header_with_configuration_change(&backend, 4, block2_2, changes(30), config2_3); - - // before truncate there are 2 unfinalized forks - block2_1+block2_3 - assert_eq!( - backend - .changes_tries_storage - .cache - .0 - .write() - .get_cache(well_known_cache_keys::CHANGES_TRIE_CONFIG) - .unwrap() - .unfinalized() - .iter() - .map(|fork| fork.head().valid_from.number) - .collect::>(), - vec![3, 4], - ); - - // after truncating block2_3 - there are 2 unfinalized forks - block2_1+block2_2 - backend.revert(1, false).unwrap(); - assert_eq!( - backend - .changes_tries_storage - .cache - .0 - .write() - .get_cache(well_known_cache_keys::CHANGES_TRIE_CONFIG) - .unwrap() - .unfinalized() - .iter() - .map(|fork| fork.head().valid_from.number) - .collect::>(), - vec![3, 3], - ); - - // after truncating block2_1 && block2_2 - there are still two unfinalized forks (cache impl - // specifics), the 1st one points to the block #3 because it isn't truncated - backend.revert(1, false).unwrap(); - assert_eq!( - backend - .changes_tries_storage - .cache - .0 - .write() - .get_cache(well_known_cache_keys::CHANGES_TRIE_CONFIG) - .unwrap() - .unfinalized() - .iter() - .map(|fork| fork.head().valid_from.number) - .collect::>(), - vec![3, 2], - ); - - // after truncating block2 - there are no unfinalized forks - backend.revert(1, false).unwrap(); - assert!(backend - .changes_tries_storage - .cache - .0 - .write() - .get_cache(well_known_cache_keys::CHANGES_TRIE_CONFIG) - .unwrap() - .unfinalized() - .iter() - .map(|fork| fork.head().valid_from.number) - .collect::>() - .is_empty(),); - } -} diff --git a/client/db/src/lib.rs b/client/db/src/lib.rs index 3b8936c0f7ba..7d46b63da5bb 100644 --- a/client/db/src/lib.rs +++ b/client/db/src/lib.rs @@ -28,14 +28,11 @@ #![warn(missing_docs)] -pub mod light; pub mod offchain; #[cfg(any(feature = "with-kvdb-rocksdb", test))] pub mod bench; -mod cache; -mod changes_tries_storage; mod children; #[cfg(feature = "with-parity-db")] mod parity_db; @@ -56,7 +53,6 @@ use std::{ }; use crate::{ - changes_tries_storage::{DbChangesTrieStorage, DbChangesTrieStorageTransaction}, stats::StateUsageStats, storage_cache::{new_shared_cache, CachingState, SharedCache, SyncingCachingState}, utils::{meta_keys, read_db, read_meta, DatabaseType, Meta}, @@ -64,8 +60,7 @@ use crate::{ use codec::{Decode, Encode}; use hash_db::Prefix; use sc_client_api::{ - backend::{NewBlockState, ProvideChtRoots, PrunableStateChangesTrieStorage}, - cht, + backend::NewBlockState, leaves::{FinalizationDisplaced, LeafSet}, utils::is_descendent_of, IoInfo, MemoryInfo, MemorySize, UsageInfo, @@ -79,11 +74,10 @@ use sp_blockchain::{ use sp_core::{ offchain::OffchainOverlayedChange, storage::{well_known_keys, ChildInfo}, - ChangesTrieConfiguration, }; use sp_database::Transaction; use sp_runtime::{ - generic::{BlockId, DigestItem}, + generic::BlockId, traits::{ Block as BlockT, Hash, HashFor, Header as HeaderT, NumberFor, One, SaturatedConversion, Zero, @@ -91,9 +85,8 @@ use sp_runtime::{ Justification, Justifications, Storage, }; use sp_state_machine::{ - backend::Backend as StateBackend, ChangesTrieCacheAction, ChangesTrieTransaction, - ChildStorageCollection, DBValue, IndexOperation, OffchainChangesCollection, StateMachineStats, - StorageCollection, UsageInfo as StateUsageInfo, + backend::Backend as StateBackend, ChildStorageCollection, DBValue, IndexOperation, + OffchainChangesCollection, StateMachineStats, StorageCollection, UsageInfo as StateUsageInfo, }; use sp_trie::{prefixed_key, MemoryDB, PrefixedMemoryDB}; @@ -104,7 +97,6 @@ pub use sp_database::Database; #[cfg(any(feature = "with-kvdb-rocksdb", test))] pub use bench::BenchmarkingState; -const MIN_BLOCKS_TO_KEEP_CHANGES_TRIES_FOR: u32 = 32768; const CACHE_HEADERS: usize = 8; /// Default value for storage cache child ratio. @@ -406,11 +398,9 @@ pub(crate) mod columns { pub const HEADER: u32 = 4; pub const BODY: u32 = 5; pub const JUSTIFICATIONS: u32 = 6; - pub const CHANGES_TRIE: u32 = 7; pub const AUX: u32 = 8; /// Offchain workers local storage pub const OFFCHAIN: u32 = 9; - pub const CACHE: u32 = 10; /// Transactions pub const TRANSACTION: u32 = 11; } @@ -506,13 +496,6 @@ impl BlockchainDb { let mut meta = self.meta.write(); meta.block_gap = gap; } - - // Get block changes trie root, if available. - fn changes_trie_root(&self, block: BlockId) -> ClientResult> { - self.header(block).map(|header| { - header.and_then(|header| header.digest().log(DigestItem::as_changes_trie_root).cloned()) - }) - } } impl sc_client_api::blockchain::HeaderBackend for BlockchainDb { @@ -646,10 +629,6 @@ impl sc_client_api::blockchain::Backend for BlockchainDb Option>> { - None - } - fn leaves(&self) -> ClientResult> { Ok(self.leaves.read().hashes()) } @@ -702,12 +681,6 @@ impl sc_client_api::blockchain::Backend for BlockchainDb sc_client_api::blockchain::ProvideCache for BlockchainDb { - fn cache(&self) -> Option>> { - None - } -} - impl HeaderMetadata for BlockchainDb { type Error = sp_blockchain::Error; @@ -745,62 +718,6 @@ impl HeaderMetadata for BlockchainDb { } } -impl ProvideChtRoots for BlockchainDb { - fn header_cht_root( - &self, - cht_size: NumberFor, - block: NumberFor, - ) -> sp_blockchain::Result> { - let cht_number = match cht::block_to_cht_number(cht_size, block) { - Some(number) => number, - None => return Ok(None), - }; - - let cht_start: NumberFor = cht::start_number(cht::size(), cht_number); - - let mut current_num = cht_start; - let cht_range = ::std::iter::from_fn(|| { - let old_current_num = current_num; - current_num = current_num + One::one(); - Some(old_current_num) - }); - - cht::compute_root::, _>( - cht::size(), - cht_number, - cht_range.map(|num| self.hash(num)), - ) - .map(Some) - } - - fn changes_trie_cht_root( - &self, - cht_size: NumberFor, - block: NumberFor, - ) -> sp_blockchain::Result> { - let cht_number = match cht::block_to_cht_number(cht_size, block) { - Some(number) => number, - None => return Ok(None), - }; - - let cht_start: NumberFor = cht::start_number(cht::size(), cht_number); - - let mut current_num = cht_start; - let cht_range = ::std::iter::from_fn(|| { - let old_current_num = current_num; - current_num = current_num + One::one(); - Some(old_current_num) - }); - - cht::compute_root::, _>( - cht::size(), - cht_number, - cht_range.map(|num| self.changes_trie_root(BlockId::Number(num))), - ) - .map(Some) - } -} - /// Database transaction pub struct BlockImportOperation { old_state: SyncingCachingState, Block>, @@ -808,9 +725,6 @@ pub struct BlockImportOperation { storage_updates: StorageCollection, child_storage_updates: ChildStorageCollection, offchain_storage_updates: OffchainChangesCollection, - changes_trie_updates: MemoryDB>, - changes_trie_build_cache_update: Option>>, - changes_trie_config_update: Option>, pending_block: Option>, aux_ops: Vec<(Vec, Option>)>, finalized_blocks: Vec<(BlockId, Option)>, @@ -858,25 +772,12 @@ impl BlockImportOperation { ) }); - let mut changes_trie_config = None; let (root, transaction) = self.old_state.full_storage_root( - storage.top.iter().map(|(k, v)| { - if &k[..] == well_known_keys::CHANGES_TRIE_CONFIG { - changes_trie_config = Some(Decode::decode(&mut &v[..])); - } - (&k[..], Some(&v[..])) - }), + storage.top.iter().map(|(k, v)| (&k[..], Some(&v[..]))), child_delta, ); - let changes_trie_config = match changes_trie_config { - Some(Ok(c)) => Some(c), - Some(Err(_)) => return Err(sp_blockchain::Error::InvalidState.into()), - None => None, - }; - self.db_updates = transaction; - self.changes_trie_config_update = Some(changes_trie_config); Ok(root) } } @@ -899,11 +800,6 @@ impl sc_client_api::backend::BlockImportOperation leaf_state: NewBlockState, ) -> ClientResult<()> { assert!(self.pending_block.is_none(), "Only one block per operation is allowed"); - if let Some(changes_trie_config_update) = - changes_tries_storage::extract_new_configuration(&header) - { - self.changes_trie_config_update = Some(changes_trie_config_update.clone()); - } self.pending_block = Some(PendingBlock { header, body, indexed_body, justifications, leaf_state }); Ok(()) @@ -930,15 +826,6 @@ impl sc_client_api::backend::BlockImportOperation Ok(root) } - fn update_changes_trie( - &mut self, - update: ChangesTrieTransaction, NumberFor>, - ) -> ClientResult<()> { - self.changes_trie_updates = update.0; - self.changes_trie_build_cache_update = Some(update.1); - Ok(()) - } - fn insert_aux(&mut self, ops: I) -> ClientResult<()> where I: IntoIterator, Option>)>, @@ -1095,7 +982,6 @@ impl FrozenForDuration { pub struct Backend { storage: Arc>, offchain_storage: offchain::LocalStorage, - changes_tries_storage: DbChangesTrieStorage, blockchain: BlockchainDb, canonicalization_delay: u64, shared_cache: SharedCache, @@ -1155,7 +1041,6 @@ impl Backend { ) -> ClientResult { let is_archive_pruning = config.state_pruning.is_archive(); let blockchain = BlockchainDb::new(db.clone(), config.transaction_storage.clone())?; - let meta = blockchain.meta.clone(); let map_e = |e: sc_state_db::Error| sp_blockchain::Error::from_state_db(e); let state_db: StateDb<_, _> = StateDb::new( config.state_pruning.clone(), @@ -1166,22 +1051,10 @@ impl Backend { let storage_db = StorageDb { db: db.clone(), state_db, prefix_keys: !db.supports_ref_counting() }; let offchain_storage = offchain::LocalStorage::new(db.clone()); - let changes_tries_storage = DbChangesTrieStorage::new( - db, - blockchain.header_metadata_cache.clone(), - columns::META, - columns::CHANGES_TRIE, - columns::KEY_LOOKUP, - columns::HEADER, - columns::CACHE, - meta, - if is_archive_pruning { None } else { Some(MIN_BLOCKS_TO_KEEP_CHANGES_TRIES_FOR) }, - )?; let backend = Backend { storage: Arc::new(storage_db), offchain_storage, - changes_tries_storage, blockchain, canonicalization_delay, shared_cache: new_shared_cache( @@ -1318,7 +1191,6 @@ impl Backend { header: &Block::Header, last_finalized: Option, justification: Option, - changes_trie_cache_ops: &mut Option>, finalization_displaced: &mut Option>>, ) -> ClientResult> { // TODO: ensure best chain contains this block. @@ -1326,15 +1198,7 @@ impl Backend { self.ensure_sequential_finalization(header, last_finalized)?; let with_state = sc_client_api::Backend::have_state_at(self, &hash, number); - self.note_finalized( - transaction, - false, - header, - *hash, - changes_trie_cache_ops, - finalization_displaced, - with_state, - )?; + self.note_finalized(transaction, header, *hash, finalization_displaced, with_state)?; if let Some(justification) = justification { transaction.set_from_vec( @@ -1400,7 +1264,6 @@ impl Backend { (meta.best_number, meta.finalized_hash, meta.finalized_number, meta.block_gap.clone()) }; - let mut changes_trie_cache_ops = None; for (block, justification) in operation.finalized_blocks { let block_hash = self.blockchain.expect_block_hash_from_id(&block)?; let block_header = self.blockchain.expect_header(BlockId::Hash(block_hash))?; @@ -1410,7 +1273,6 @@ impl Backend { &block_header, Some(last_finalized_hash), justification, - &mut changes_trie_cache_ops, &mut finalization_displaced_leaves, )?); last_finalized_hash = block_hash; @@ -1475,11 +1337,6 @@ impl Backend { ); transaction.set(columns::META, meta_keys::GENESIS_HASH, hash.as_ref()); - // for tests, because config is set from within the reset_storage - if operation.changes_trie_config_update.is_none() { - operation.changes_trie_config_update = Some(None); - } - if operation.commit_state { transaction.set_from_vec(columns::META, meta_keys::FINALIZED_STATE, lookup_key); } else { @@ -1578,7 +1435,6 @@ impl Backend { let header = &pending_block.header; let is_best = pending_block.leaf_state.is_best(); - let changes_trie_updates = operation.changes_trie_updates; debug!(target: "db", "DB Commit {:?} ({}), best={}, state={}, existing={}", hash, number, is_best, operation.commit_state, existing_header, @@ -1593,10 +1449,8 @@ impl Backend { self.ensure_sequential_finalization(header, Some(last_finalized_hash))?; self.note_finalized( &mut transaction, - true, header, hash, - &mut changes_trie_cache_ops, &mut finalization_displaced_leaves, operation.commit_state, )?; @@ -1606,21 +1460,6 @@ impl Backend { } if !existing_header { - let changes_trie_config_update = operation.changes_trie_config_update; - changes_trie_cache_ops = Some(self.changes_tries_storage.commit( - &mut transaction, - changes_trie_updates, - cache::ComplexBlockId::new( - *header.parent_hash(), - if number.is_zero() { Zero::zero() } else { number - One::one() }, - ), - cache::ComplexBlockId::new(hash, number), - header, - finalized, - changes_trie_config_update, - changes_trie_cache_ops, - )?); - { let mut leaves = self.blockchain.leaves.write(); leaves.import(hash, number, parent_hash); @@ -1747,11 +1586,6 @@ impl Backend { ); } - if let Some(changes_trie_build_cache_update) = operation.changes_trie_build_cache_update { - self.changes_tries_storage.commit_build_cache(changes_trie_build_cache_update); - } - self.changes_tries_storage.post_commit(changes_trie_cache_ops); - if let Some((enacted, retracted)) = cache_update { self.shared_cache.write().sync(&enacted, &retracted); } @@ -1770,10 +1604,8 @@ impl Backend { fn note_finalized( &self, transaction: &mut Transaction, - is_inserted: bool, f_header: &Block::Header, f_hash: Block::Hash, - changes_trie_cache_ops: &mut Option>, displaced: &mut Option>>, with_state: bool, ) -> ClientResult<()> { @@ -1798,18 +1630,6 @@ impl Backend { apply_state_commit(transaction, commit); } - if !f_num.is_zero() { - let new_changes_trie_cache_ops = self.changes_tries_storage.finalize( - transaction, - *f_header.parent_hash(), - f_hash, - f_num, - if is_inserted { Some(&f_header) } else { None }, - changes_trie_cache_ops.take(), - )?; - *changes_trie_cache_ops = Some(new_changes_trie_cache_ops); - } - let new_displaced = self.blockchain.leaves.write().finalize_height(f_num); self.prune_blocks(transaction, f_num, &new_displaced)?; match displaced { @@ -2036,9 +1856,6 @@ impl sc_client_api::backend::Backend for Backend { storage_updates: Default::default(), child_storage_updates: Default::default(), offchain_storage_updates: Default::default(), - changes_trie_config_update: None, - changes_trie_updates: MemoryDB::default(), - changes_trie_build_cache_update: None, aux_ops: Vec::new(), finalized_blocks: Vec::new(), set_head: None, @@ -2089,19 +1906,16 @@ impl sc_client_api::backend::Backend for Backend { let header = self.blockchain.expect_header(block)?; let mut displaced = None; - let mut changes_trie_cache_ops = None; let m = self.finalize_block_with_transaction( &mut transaction, &hash, &header, None, justification, - &mut changes_trie_cache_ops, &mut displaced, )?; self.storage.db.commit(transaction)?; self.blockchain.update_meta(m); - self.changes_tries_storage.post_commit(changes_trie_cache_ops); Ok(()) } @@ -2148,10 +1962,6 @@ impl sc_client_api::backend::Backend for Backend { Ok(()) } - fn changes_trie_storage(&self) -> Option<&dyn PrunableStateChangesTrieStorage> { - Some(&self.changes_tries_storage) - } - fn offchain_storage(&self) -> Option { Some(self.offchain_storage.clone()) } @@ -2208,7 +2018,6 @@ impl sc_client_api::backend::Backend for Backend { return Ok(c.saturated_into::>()) } let mut transaction = Transaction::new(); - let removed_number = best_number; let removed = self.blockchain.header(BlockId::Number(best_number))?.ok_or_else(|| { sp_blockchain::Error::UnknownBlock(format!( @@ -2241,10 +2050,6 @@ impl sc_client_api::backend::Backend for Backend { let key = utils::number_and_hash_to_lookup_key(best_number.clone(), &best_hash)?; - let changes_trie_cache_ops = self.changes_tries_storage.revert( - &mut transaction, - &cache::ComplexBlockId::new(removed.hash(), removed_number), - )?; if update_finalized { transaction.set_from_vec( columns::META, @@ -2283,7 +2088,6 @@ impl sc_client_api::backend::Backend for Backend { best_hash, ); self.storage.db.commit(transaction)?; - self.changes_tries_storage.post_commit(Some(changes_trie_cache_ops)); self.blockchain.update_meta(MetaUpdate { hash: best_hash, number: best_number, @@ -2345,11 +2149,6 @@ impl sc_client_api::backend::Backend for Backend { apply_state_commit(&mut transaction, commit); } transaction.remove(columns::KEY_LOOKUP, hash.as_ref()); - let changes_trie_cache_ops = self - .changes_tries_storage - .revert(&mut transaction, &cache::ComplexBlockId::new(*hash, hdr.number))?; - - self.changes_tries_storage.post_commit(Some(changes_trie_cache_ops)); leaves.revert(hash.clone(), hdr.number); leaves.prepare_transaction(&mut transaction, columns::META, meta_keys::LEAF_PREFIX); self.storage.db.commit(transaction)?; @@ -2461,32 +2260,16 @@ pub(crate) mod tests { use sp_blockchain::{lowest_common_ancestor, tree_route}; use sp_core::H256; use sp_runtime::{ - generic::DigestItem, testing::{Block as RawBlock, ExtrinsicWrapper, Header}, traits::{BlakeTwo256, Hash}, ConsensusEngineId, }; - use sp_state_machine::{TrieDBMut, TrieMut}; const CONS0_ENGINE_ID: ConsensusEngineId = *b"CON0"; const CONS1_ENGINE_ID: ConsensusEngineId = *b"CON1"; pub(crate) type Block = RawBlock>; - pub fn prepare_changes(changes: Vec<(Vec, Vec)>) -> (H256, MemoryDB) { - let mut changes_root = H256::default(); - let mut changes_trie_update = MemoryDB::::default(); - { - let mut trie = - TrieDBMut::::new(&mut changes_trie_update, &mut changes_root); - for (key, value) in changes { - trie.insert(&key, &value).unwrap(); - } - } - - (changes_root, changes_trie_update) - } - pub fn insert_header( backend: &Backend, number: u64, @@ -2501,20 +2284,14 @@ pub(crate) mod tests { backend: &Backend, number: u64, parent_hash: H256, - changes: Option, Vec)>>, + _changes: Option, Vec)>>, extrinsics_root: H256, body: Vec>, transaction_index: Option>, ) -> H256 { use sp_runtime::testing::Digest; - let mut digest = Digest::default(); - let mut changes_trie_update = Default::default(); - if let Some(changes) = changes { - let (root, update) = prepare_changes(changes); - digest.push(DigestItem::ChangesTrieRoot(root)); - changes_trie_update = update; - } + let digest = Digest::default(); let header = Header { number, parent_hash, @@ -2535,8 +2312,6 @@ pub(crate) mod tests { if let Some(index) = transaction_index { op.update_transaction_index(index).unwrap(); } - op.update_changes_trie((changes_trie_update, ChangesTrieCacheAction::Clear)) - .unwrap(); backend.commit_operation(op).unwrap(); header_hash @@ -3241,38 +3016,6 @@ pub(crate) mod tests { } } - #[test] - fn header_cht_root_works() { - use sc_client_api::ProvideChtRoots; - - let backend = Backend::::new_test(10, 10); - - // insert 1 + SIZE + SIZE + 1 blocks so that CHT#0 is created - let mut prev_hash = - insert_header(&backend, 0, Default::default(), None, Default::default()); - let cht_size: u64 = cht::size(); - for i in 1..1 + cht_size + cht_size + 1 { - prev_hash = insert_header(&backend, i, prev_hash, None, Default::default()); - } - - let blockchain = backend.blockchain(); - - let cht_root_1 = blockchain - .header_cht_root(cht_size, cht::start_number(cht_size, 0)) - .unwrap() - .unwrap(); - let cht_root_2 = blockchain - .header_cht_root(cht_size, cht::start_number(cht_size, 0) + cht_size / 2) - .unwrap() - .unwrap(); - let cht_root_3 = blockchain - .header_cht_root(cht_size, cht::end_number(cht_size, 0)) - .unwrap() - .unwrap(); - assert_eq!(cht_root_1, cht_root_2); - assert_eq!(cht_root_2, cht_root_3); - } - #[test] fn prune_blocks_on_finalize() { for storage in &[TransactionStorageMode::BlockBody, TransactionStorageMode::StorageChain] { diff --git a/client/db/src/light.rs b/client/db/src/light.rs deleted file mode 100644 index 48cf0489cf2a..000000000000 --- a/client/db/src/light.rs +++ /dev/null @@ -1,1329 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2017-2021 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 . - -//! RocksDB-based light client blockchain storage. - -use parking_lot::RwLock; -use std::{collections::HashMap, convert::TryInto, sync::Arc}; - -use crate::{ - cache::{ComplexBlockId, DbCache, DbCacheSync, EntryType as CacheEntryType}, - utils::{self, block_id_to_lookup_key, meta_keys, read_db, read_meta, DatabaseType, Meta}, - DatabaseSettings, DbHash, FrozenForDuration, -}; -use codec::{Decode, Encode}; -use log::{debug, trace, warn}; -use sc_client_api::{ - backend::{AuxStore, NewBlockState, ProvideChtRoots}, - blockchain::{BlockStatus, Cache as BlockchainCache, Info as BlockchainInfo}, - cht, Storage, UsageInfo, -}; -use sp_blockchain::{ - well_known_cache_keys, CachedHeaderMetadata, Error as ClientError, - HeaderBackend as BlockchainHeaderBackend, HeaderMetadata, HeaderMetadataCache, - Result as ClientResult, -}; -use sp_database::{Database, Transaction}; -use sp_runtime::{ - generic::{BlockId, DigestItem}, - traits::{Block as BlockT, HashFor, Header as HeaderT, NumberFor, One, Zero}, -}; - -pub(crate) mod columns { - pub const META: u32 = crate::utils::COLUMN_META; - pub const KEY_LOOKUP: u32 = 1; - pub const HEADER: u32 = 2; - pub const CACHE: u32 = 3; - pub const CHT: u32 = 4; - pub const AUX: u32 = 5; -} - -/// Prefix for headers CHT. -const HEADER_CHT_PREFIX: u8 = 0; -/// Prefix for changes tries roots CHT. -const CHANGES_TRIE_CHT_PREFIX: u8 = 1; - -/// Light blockchain storage. Stores most recent headers + CHTs for older headers. -/// Locks order: meta, cache. -pub struct LightStorage { - db: Arc>, - meta: RwLock, Block::Hash>>, - cache: Arc>, - header_metadata_cache: Arc>, - io_stats: FrozenForDuration, -} - -impl LightStorage { - /// Create new storage with given settings. - pub fn new(config: DatabaseSettings) -> ClientResult { - let db = crate::utils::open_database::(&config, DatabaseType::Light)?; - Self::from_kvdb(db as Arc<_>) - } - - /// Create new memory-backed `LightStorage` for tests. - #[cfg(any(test, feature = "test-helpers"))] - pub fn new_test() -> Self { - let db = Arc::new(sp_database::MemDb::default()); - Self::from_kvdb(db as Arc<_>).expect("failed to create test-db") - } - - fn from_kvdb(db: Arc>) -> ClientResult { - let meta = read_meta::(&*db, columns::HEADER)?; - let header_metadata_cache = Arc::new(HeaderMetadataCache::default()); - let cache = DbCache::new( - db.clone(), - header_metadata_cache.clone(), - columns::KEY_LOOKUP, - columns::HEADER, - columns::CACHE, - meta.genesis_hash, - ComplexBlockId::new(meta.finalized_hash, meta.finalized_number), - ); - - Ok(LightStorage { - db, - meta: RwLock::new(meta), - cache: Arc::new(DbCacheSync(RwLock::new(cache))), - header_metadata_cache, - io_stats: FrozenForDuration::new(std::time::Duration::from_secs(1)), - }) - } - - #[cfg(test)] - pub(crate) fn cache(&self) -> &DbCacheSync { - &self.cache - } - - fn update_meta( - &self, - hash: Block::Hash, - number: NumberFor, - is_best: bool, - is_finalized: bool, - ) { - let mut meta = self.meta.write(); - - if number.is_zero() { - meta.genesis_hash = hash; - meta.finalized_hash = hash; - } - - if is_best { - meta.best_number = number; - meta.best_hash = hash; - } - - if is_finalized { - meta.finalized_number = number; - meta.finalized_hash = hash; - } - } -} - -impl BlockchainHeaderBackend for LightStorage -where - Block: BlockT, -{ - fn header(&self, id: BlockId) -> ClientResult> { - utils::read_header(&*self.db, columns::KEY_LOOKUP, columns::HEADER, id) - } - - fn info(&self) -> BlockchainInfo { - let meta = self.meta.read(); - BlockchainInfo { - best_hash: meta.best_hash, - best_number: meta.best_number, - genesis_hash: meta.genesis_hash.clone(), - finalized_hash: meta.finalized_hash, - finalized_number: meta.finalized_number, - finalized_state: if meta.finalized_hash != Default::default() { - Some((meta.genesis_hash, Zero::zero())) - } else { - None - }, - number_leaves: 1, - block_gap: None, - } - } - - fn status(&self, id: BlockId) -> ClientResult { - let exists = match id { - BlockId::Hash(_) => - read_db(&*self.db, columns::KEY_LOOKUP, columns::HEADER, id)?.is_some(), - BlockId::Number(n) => n <= self.meta.read().best_number, - }; - match exists { - true => Ok(BlockStatus::InChain), - false => Ok(BlockStatus::Unknown), - } - } - - fn number(&self, hash: Block::Hash) -> ClientResult>> { - if let Some(lookup_key) = - block_id_to_lookup_key::(&*self.db, columns::KEY_LOOKUP, BlockId::Hash(hash))? - { - let number = utils::lookup_key_to_number(&lookup_key)?; - Ok(Some(number)) - } else { - Ok(None) - } - } - - fn hash(&self, number: NumberFor) -> ClientResult> { - Ok(self.header(BlockId::Number(number))?.map(|header| header.hash().clone())) - } -} - -impl HeaderMetadata for LightStorage { - type Error = ClientError; - - fn header_metadata( - &self, - hash: Block::Hash, - ) -> Result, Self::Error> { - self.header_metadata_cache.header_metadata(hash).map_or_else( - || { - self.header(BlockId::hash(hash))? - .map(|header| { - let header_metadata = CachedHeaderMetadata::from(&header); - self.header_metadata_cache - .insert_header_metadata(header_metadata.hash, header_metadata.clone()); - header_metadata - }) - .ok_or_else(|| { - ClientError::UnknownBlock(format!("header not found in db: {}", hash)) - }) - }, - Ok, - ) - } - - fn insert_header_metadata(&self, hash: Block::Hash, metadata: CachedHeaderMetadata) { - self.header_metadata_cache.insert_header_metadata(hash, metadata) - } - - fn remove_header_metadata(&self, hash: Block::Hash) { - self.header_metadata_cache.remove_header_metadata(hash); - } -} - -impl LightStorage { - // Get block changes trie root, if available. - fn changes_trie_root(&self, block: BlockId) -> ClientResult> { - self.header(block).map(|header| { - header.and_then(|header| header.digest().log(DigestItem::as_changes_trie_root).cloned()) - }) - } - - /// Handle setting head within a transaction. `route_to` should be the last - /// block that existed in the database. `best_to` should be the best block - /// to be set. - /// - /// In the case where the new best block is a block to be imported, `route_to` - /// should be the parent of `best_to`. In the case where we set an existing block - /// to be best, `route_to` should equal to `best_to`. - fn set_head_with_transaction( - &self, - transaction: &mut Transaction, - route_to: Block::Hash, - best_to: (NumberFor, Block::Hash), - ) -> ClientResult<()> { - let lookup_key = utils::number_and_hash_to_lookup_key(best_to.0, &best_to.1)?; - - // handle reorg. - let meta = self.meta.read(); - if meta.best_hash != Default::default() { - let tree_route = sp_blockchain::tree_route(self, meta.best_hash, route_to)?; - - // update block number to hash lookup entries. - for retracted in tree_route.retracted() { - if retracted.hash == meta.finalized_hash { - // TODO: can we recover here? - warn!( - "Safety failure: reverting finalized block {:?}", - (&retracted.number, &retracted.hash) - ); - } - - utils::remove_number_to_key_mapping( - transaction, - columns::KEY_LOOKUP, - retracted.number, - )?; - } - - for enacted in tree_route.enacted() { - utils::insert_number_to_key_mapping( - transaction, - columns::KEY_LOOKUP, - enacted.number, - enacted.hash, - )?; - } - } - - transaction.set_from_vec(columns::META, meta_keys::BEST_BLOCK, lookup_key); - utils::insert_number_to_key_mapping( - transaction, - columns::KEY_LOOKUP, - best_to.0, - best_to.1, - )?; - - Ok(()) - } - - // Note that a block is finalized. Only call with child of last finalized block. - fn note_finalized( - &self, - transaction: &mut Transaction, - header: &Block::Header, - hash: Block::Hash, - ) -> ClientResult<()> { - let meta = self.meta.read(); - if &meta.finalized_hash != header.parent_hash() { - return Err(::sp_blockchain::Error::NonSequentialFinalization(format!( - "Last finalized {:?} not parent of {:?}", - meta.finalized_hash, hash - )) - .into()) - } - - let lookup_key = utils::number_and_hash_to_lookup_key(header.number().clone(), hash)?; - transaction.set_from_vec(columns::META, meta_keys::FINALIZED_BLOCK, lookup_key); - - // build new CHT(s) if required - if let Some(new_cht_number) = cht::is_build_required(cht::size(), *header.number()) { - let new_cht_start: NumberFor = cht::start_number(cht::size(), new_cht_number); - - let mut current_num = new_cht_start; - let cht_range = ::std::iter::from_fn(|| { - let old_current_num = current_num; - current_num = current_num + One::one(); - Some(old_current_num) - }); - - let new_header_cht_root = cht::compute_root::, _>( - cht::size(), - new_cht_number, - cht_range.map(|num| self.hash(num)), - )?; - transaction.set( - columns::CHT, - &cht_key(HEADER_CHT_PREFIX, new_cht_start)?, - new_header_cht_root.as_ref(), - ); - - // if the header includes changes trie root, let's build a changes tries roots CHT - if header.digest().log(DigestItem::as_changes_trie_root).is_some() { - let mut current_num = new_cht_start; - let cht_range = std::iter::from_fn(|| { - let old_current_num = current_num; - current_num = current_num + One::one(); - Some(old_current_num) - }); - let new_changes_trie_cht_root = - cht::compute_root::, _>( - cht::size(), - new_cht_number, - cht_range.map(|num| self.changes_trie_root(BlockId::Number(num))), - )?; - transaction.set( - columns::CHT, - &cht_key(CHANGES_TRIE_CHT_PREFIX, new_cht_start)?, - new_changes_trie_cht_root.as_ref(), - ); - } - - // prune headers that are replaced with CHT - let mut prune_block = new_cht_start; - let new_cht_end = cht::end_number(cht::size(), new_cht_number); - trace!(target: "db", "Replacing blocks [{}..{}] with CHT#{}", - new_cht_start, new_cht_end, new_cht_number); - - while prune_block <= new_cht_end { - if let Some(hash) = self.hash(prune_block)? { - let lookup_key = block_id_to_lookup_key::(&*self.db, columns::KEY_LOOKUP, BlockId::Number(prune_block))? - .expect("retrieved hash for `prune_block` right above. therefore retrieving lookup key must succeed. q.e.d."); - utils::remove_key_mappings( - transaction, - columns::KEY_LOOKUP, - prune_block, - hash, - )?; - transaction.remove(columns::HEADER, &lookup_key); - } - prune_block += One::one(); - } - } - - Ok(()) - } - - /// Read CHT root of given type for the block. - fn read_cht_root( - &self, - cht_type: u8, - cht_size: NumberFor, - block: NumberFor, - ) -> ClientResult> { - let no_cht_for_block = || ClientError::Backend(format!("Missing CHT for block {}", block)); - - let meta = self.meta.read(); - let max_cht_number = cht::max_cht_number(cht_size, meta.finalized_number); - let cht_number = cht::block_to_cht_number(cht_size, block).ok_or_else(no_cht_for_block)?; - match max_cht_number { - Some(max_cht_number) if cht_number <= max_cht_number => (), - _ => return Ok(None), - } - - let cht_start = cht::start_number(cht_size, cht_number); - self.db - .get(columns::CHT, &cht_key(cht_type, cht_start)?) - .ok_or_else(no_cht_for_block) - .and_then(|hash| Block::Hash::decode(&mut &*hash).map_err(|_| no_cht_for_block())) - .map(Some) - } -} - -impl AuxStore for LightStorage -where - Block: BlockT, -{ - fn insert_aux< - 'a, - 'b: 'a, - 'c: 'a, - I: IntoIterator, - D: IntoIterator, - >( - &self, - insert: I, - delete: D, - ) -> ClientResult<()> { - let mut transaction = Transaction::new(); - for (k, v) in insert { - transaction.set(columns::AUX, k, v); - } - for k in delete { - transaction.remove(columns::AUX, k); - } - self.db.commit(transaction)?; - - Ok(()) - } - - fn get_aux(&self, key: &[u8]) -> ClientResult>> { - Ok(self.db.get(columns::AUX, key)) - } -} - -impl Storage for LightStorage -where - Block: BlockT, -{ - fn import_header( - &self, - header: Block::Header, - mut cache_at: HashMap>, - leaf_state: NewBlockState, - aux_ops: Vec<(Vec, Option>)>, - ) -> ClientResult<()> { - let mut transaction = Transaction::new(); - - let hash = header.hash(); - let number = *header.number(); - let parent_hash = *header.parent_hash(); - - for (key, maybe_val) in aux_ops { - match maybe_val { - Some(val) => transaction.set_from_vec(columns::AUX, &key, val), - None => transaction.remove(columns::AUX, &key), - } - } - - // blocks are keyed by number + hash. - let lookup_key = utils::number_and_hash_to_lookup_key(number, &hash)?; - - if leaf_state.is_best() { - self.set_head_with_transaction(&mut transaction, parent_hash, (number, hash))?; - } - - utils::insert_hash_to_key_mapping(&mut transaction, columns::KEY_LOOKUP, number, hash)?; - transaction.set_from_vec(columns::HEADER, &lookup_key, header.encode()); - - let header_metadata = CachedHeaderMetadata::from(&header); - self.header_metadata_cache - .insert_header_metadata(header.hash().clone(), header_metadata); - - let is_genesis = number.is_zero(); - if is_genesis { - self.cache.0.write().set_genesis_hash(hash); - transaction.set(columns::META, meta_keys::GENESIS_HASH, hash.as_ref()); - } - - let finalized = match leaf_state { - _ if is_genesis => true, - NewBlockState::Final => true, - _ => false, - }; - - if finalized { - self.note_finalized(&mut transaction, &header, hash)?; - } - - // update changes trie configuration cache - if !cache_at.contains_key(&well_known_cache_keys::CHANGES_TRIE_CONFIG) { - if let Some(new_configuration) = - crate::changes_tries_storage::extract_new_configuration(&header) - { - cache_at - .insert(well_known_cache_keys::CHANGES_TRIE_CONFIG, new_configuration.encode()); - } - } - - { - let mut cache = self.cache.0.write(); - let cache_ops = cache - .transaction(&mut transaction) - .on_block_insert( - ComplexBlockId::new( - *header.parent_hash(), - if number.is_zero() { Zero::zero() } else { number - One::one() }, - ), - ComplexBlockId::new(hash, number), - cache_at, - if finalized { CacheEntryType::Final } else { CacheEntryType::NonFinal }, - )? - .into_ops(); - - debug!("Light DB Commit {:?} ({})", hash, number); - - self.db.commit(transaction)?; - cache.commit(cache_ops).expect( - "only fails if cache with given name isn't loaded yet; cache is already loaded \ - because there are cache_ops; qed", - ); - } - - self.update_meta(hash, number, leaf_state.is_best(), finalized); - - Ok(()) - } - - fn set_head(&self, id: BlockId) -> ClientResult<()> { - if let Some(header) = self.header(id)? { - let hash = header.hash(); - let number = header.number(); - - let mut transaction = Transaction::new(); - self.set_head_with_transaction( - &mut transaction, - hash.clone(), - (number.clone(), hash.clone()), - )?; - self.db.commit(transaction)?; - self.update_meta(hash, header.number().clone(), true, false); - - Ok(()) - } else { - Err(ClientError::UnknownBlock(format!("Cannot set head {:?}", id))) - } - } - - fn finalize_header(&self, id: BlockId) -> ClientResult<()> { - if let Some(header) = self.header(id)? { - let mut transaction = Transaction::new(); - let hash = header.hash(); - let number = *header.number(); - self.note_finalized(&mut transaction, &header, hash.clone())?; - { - let mut cache = self.cache.0.write(); - let cache_ops = cache - .transaction(&mut transaction) - .on_block_finalize( - ComplexBlockId::new( - *header.parent_hash(), - if number.is_zero() { Zero::zero() } else { number - One::one() }, - ), - ComplexBlockId::new(hash, number), - )? - .into_ops(); - - self.db.commit(transaction)?; - cache.commit(cache_ops).expect( - "only fails if cache with given name isn't loaded yet; cache is already loaded \ - because there are cache_ops; qed", - ); - } - self.update_meta(hash, header.number().clone(), false, true); - - Ok(()) - } else { - Err(ClientError::UnknownBlock(format!("Cannot finalize block {:?}", id))) - } - } - - fn last_finalized(&self) -> ClientResult { - Ok(self.meta.read().finalized_hash.clone()) - } - - fn cache(&self) -> Option>> { - Some(self.cache.clone()) - } - - fn usage_info(&self) -> Option { - use sc_client_api::{IoInfo, MemoryInfo, MemorySize}; - - // TODO: reimplement IO stats - let database_cache = MemorySize::from_bytes(0); - let io_stats = self.io_stats.take_or_else(|| kvdb::IoStats::empty()); - - Some(UsageInfo { - memory: MemoryInfo { - database_cache, - state_cache: Default::default(), - state_db: Default::default(), - }, - io: IoInfo { - transactions: io_stats.transactions, - bytes_read: io_stats.bytes_read, - bytes_written: io_stats.bytes_written, - writes: io_stats.writes, - reads: io_stats.reads, - average_transaction_size: io_stats.avg_transaction_size() as u64, - // Light client does not track those - state_reads: 0, - state_writes: 0, - state_reads_cache: 0, - state_writes_cache: 0, - state_writes_nodes: 0, - }, - }) - } -} - -impl ProvideChtRoots for LightStorage -where - Block: BlockT, -{ - fn header_cht_root( - &self, - cht_size: NumberFor, - block: NumberFor, - ) -> ClientResult> { - self.read_cht_root(HEADER_CHT_PREFIX, cht_size, block) - } - - fn changes_trie_cht_root( - &self, - cht_size: NumberFor, - block: NumberFor, - ) -> ClientResult> { - self.read_cht_root(CHANGES_TRIE_CHT_PREFIX, cht_size, block) - } -} - -/// Build the key for inserting header-CHT at given block. -fn cht_key>(cht_type: u8, block: N) -> ClientResult<[u8; 5]> { - let mut key = [cht_type; 5]; - key[1..].copy_from_slice(&utils::number_index_key(block)?); - Ok(key) -} - -#[cfg(test)] -pub(crate) mod tests { - use super::*; - use sc_client_api::cht; - use sp_blockchain::{lowest_common_ancestor, tree_route}; - use sp_core::ChangesTrieConfiguration; - use sp_runtime::{ - generic::{ChangesTrieSignal, DigestItem}, - testing::{Block as RawBlock, ExtrinsicWrapper, Header, H256 as Hash}, - }; - - type Block = RawBlock>; - type AuthorityId = sp_core::ed25519::Public; - - pub fn default_header(parent: &Hash, number: u64) -> Header { - Header { - number: number.into(), - parent_hash: *parent, - state_root: Hash::random(), - digest: Default::default(), - extrinsics_root: Default::default(), - } - } - - fn header_with_changes_trie(parent: &Hash, number: u64) -> Header { - let mut header = default_header(parent, number); - header - .digest - .logs - .push(DigestItem::ChangesTrieRoot([(number % 256) as u8; 32].into())); - header - } - - fn header_with_extrinsics_root(parent: &Hash, number: u64, extrinsics_root: Hash) -> Header { - let mut header = default_header(parent, number); - header.extrinsics_root = extrinsics_root; - header - } - - pub fn insert_block Header>( - db: &LightStorage, - cache: HashMap>, - mut header: F, - ) -> Hash { - let header = header(); - let hash = header.hash(); - db.import_header(header, cache, NewBlockState::Best, Vec::new()).unwrap(); - hash - } - - fn insert_final_block Header>( - db: &LightStorage, - cache: HashMap>, - header: F, - ) -> Hash { - let header = header(); - let hash = header.hash(); - db.import_header(header, cache, NewBlockState::Final, Vec::new()).unwrap(); - hash - } - - fn insert_non_best_block Header>( - db: &LightStorage, - cache: HashMap>, - header: F, - ) -> Hash { - let header = header(); - let hash = header.hash(); - db.import_header(header, cache, NewBlockState::Normal, Vec::new()).unwrap(); - hash - } - - #[test] - fn returns_known_header() { - let db = LightStorage::new_test(); - let known_hash = - insert_block(&db, HashMap::new(), || default_header(&Default::default(), 0)); - let header_by_hash = db.header(BlockId::Hash(known_hash)).unwrap().unwrap(); - let header_by_number = db.header(BlockId::Number(0)).unwrap().unwrap(); - assert_eq!(header_by_hash, header_by_number); - } - - #[test] - fn does_not_return_unknown_header() { - let db = LightStorage::::new_test(); - assert!(db.header(BlockId::Hash(Hash::from_low_u64_be(1))).unwrap().is_none()); - assert!(db.header(BlockId::Number(0)).unwrap().is_none()); - } - - #[test] - fn returns_info() { - let db = LightStorage::new_test(); - let genesis_hash = - insert_block(&db, HashMap::new(), || default_header(&Default::default(), 0)); - let info = db.info(); - assert_eq!(info.best_hash, genesis_hash); - assert_eq!(info.best_number, 0); - assert_eq!(info.genesis_hash, genesis_hash); - let best_hash = insert_block(&db, HashMap::new(), || default_header(&genesis_hash, 1)); - let info = db.info(); - assert_eq!(info.best_hash, best_hash); - assert_eq!(info.best_number, 1); - assert_eq!(info.genesis_hash, genesis_hash); - } - - #[test] - fn returns_block_status() { - let db = LightStorage::new_test(); - let genesis_hash = - insert_block(&db, HashMap::new(), || default_header(&Default::default(), 0)); - assert_eq!(db.status(BlockId::Hash(genesis_hash)).unwrap(), BlockStatus::InChain); - assert_eq!(db.status(BlockId::Number(0)).unwrap(), BlockStatus::InChain); - assert_eq!( - db.status(BlockId::Hash(Hash::from_low_u64_be(1))).unwrap(), - BlockStatus::Unknown - ); - assert_eq!(db.status(BlockId::Number(1)).unwrap(), BlockStatus::Unknown); - } - - #[test] - fn returns_block_hash() { - let db = LightStorage::new_test(); - let genesis_hash = - insert_block(&db, HashMap::new(), || default_header(&Default::default(), 0)); - assert_eq!(db.hash(0).unwrap(), Some(genesis_hash)); - assert_eq!(db.hash(1).unwrap(), None); - } - - #[test] - fn import_header_works() { - let raw_db = Arc::new(sp_database::MemDb::default()); - let db = LightStorage::from_kvdb(raw_db.clone()).unwrap(); - - let genesis_hash = - insert_block(&db, HashMap::new(), || default_header(&Default::default(), 0)); - assert_eq!(raw_db.count(columns::HEADER), 1); - assert_eq!(raw_db.count(columns::KEY_LOOKUP), 2); - - let _ = insert_block(&db, HashMap::new(), || default_header(&genesis_hash, 1)); - assert_eq!(raw_db.count(columns::HEADER), 2); - assert_eq!(raw_db.count(columns::KEY_LOOKUP), 4); - } - - #[test] - fn finalized_ancient_headers_are_replaced_with_cht() { - fn insert_headers Header>( - header_producer: F, - ) -> (Arc, LightStorage) { - let raw_db = Arc::new(sp_database::MemDb::default()); - let db = LightStorage::from_kvdb(raw_db.clone()).unwrap(); - let cht_size: u64 = cht::size(); - let ucht_size: usize = cht_size as _; - - // insert genesis block header (never pruned) - let mut prev_hash = - insert_final_block(&db, HashMap::new(), || header_producer(&Default::default(), 0)); - - // insert SIZE blocks && ensure that nothing is pruned - - for number in 0..cht::size() { - prev_hash = - insert_block(&db, HashMap::new(), || header_producer(&prev_hash, 1 + number)); - } - assert_eq!(raw_db.count(columns::HEADER), 1 + ucht_size); - assert_eq!(raw_db.count(columns::CHT), 0); - - // insert next SIZE blocks && ensure that nothing is pruned - for number in 0..(cht_size as _) { - prev_hash = insert_block(&db, HashMap::new(), || { - header_producer(&prev_hash, 1 + cht_size + number) - }); - } - assert_eq!(raw_db.count(columns::HEADER), 1 + ucht_size + ucht_size); - assert_eq!(raw_db.count(columns::CHT), 0); - - // insert block #{2 * cht::size() + 1} && check that new CHT is created + headers of - // this CHT are pruned nothing is yet finalized, so nothing is pruned. - prev_hash = insert_block(&db, HashMap::new(), || { - header_producer(&prev_hash, 1 + cht_size + cht_size) - }); - assert_eq!(raw_db.count(columns::HEADER), 2 + ucht_size + ucht_size); - assert_eq!(raw_db.count(columns::CHT), 0); - - // now finalize the block. - for i in (0..(ucht_size + ucht_size)).map(|i| i + 1) { - db.finalize_header(BlockId::Number(i as _)).unwrap(); - } - db.finalize_header(BlockId::Hash(prev_hash)).unwrap(); - (raw_db, db) - } - - // when headers are created without changes tries roots - let (raw_db, db) = insert_headers(default_header); - let cht_size: u64 = cht::size(); - assert_eq!(raw_db.count(columns::HEADER), (1 + cht_size + 1) as usize); - assert_eq!(raw_db.count(columns::KEY_LOOKUP), (2 * (1 + cht_size + 1)) as usize); - assert_eq!(raw_db.count(columns::CHT), 1); - assert!((0..cht_size as _).all(|i| db.header(BlockId::Number(1 + i)).unwrap().is_none())); - assert!(db.header_cht_root(cht_size, cht_size / 2).unwrap().is_some()); - assert!(db.header_cht_root(cht_size, cht_size + cht_size / 2).unwrap().is_none()); - assert!(db.changes_trie_cht_root(cht_size, cht_size / 2).is_err()); - assert!(db.changes_trie_cht_root(cht_size, cht_size + cht_size / 2).unwrap().is_none()); - - // when headers are created with changes tries roots - let (raw_db, db) = insert_headers(header_with_changes_trie); - assert_eq!(raw_db.count(columns::HEADER), (1 + cht_size + 1) as usize); - assert_eq!(raw_db.count(columns::CHT), 2); - assert!((0..cht_size as _).all(|i| db.header(BlockId::Number(1 + i)).unwrap().is_none())); - assert!(db.header_cht_root(cht_size, cht_size / 2).unwrap().is_some()); - assert!(db.header_cht_root(cht_size, cht_size + cht_size / 2).unwrap().is_none()); - assert!(db.changes_trie_cht_root(cht_size, cht_size / 2).unwrap().is_some()); - assert!(db.changes_trie_cht_root(cht_size, cht_size + cht_size / 2).unwrap().is_none()); - } - - #[test] - fn get_cht_fails_for_genesis_block() { - assert!(LightStorage::::new_test().header_cht_root(cht::size(), 0).is_err()); - } - - #[test] - fn get_cht_fails_for_non_existent_cht() { - let cht_size: u64 = cht::size(); - assert!(LightStorage::::new_test() - .header_cht_root(cht_size, cht_size / 2) - .unwrap() - .is_none()); - } - - #[test] - fn get_cht_works() { - let db = LightStorage::new_test(); - - // insert 1 + SIZE + SIZE + 1 blocks so that CHT#0 is created - let mut prev_hash = insert_final_block(&db, HashMap::new(), || { - header_with_changes_trie(&Default::default(), 0) - }); - let cht_size: u64 = cht::size(); - let ucht_size: usize = cht_size as _; - for i in 1..1 + ucht_size + ucht_size + 1 { - prev_hash = insert_block(&db, HashMap::new(), || { - header_with_changes_trie(&prev_hash, i as u64) - }); - db.finalize_header(BlockId::Hash(prev_hash)).unwrap(); - } - - let cht_root_1 = - db.header_cht_root(cht_size, cht::start_number(cht_size, 0)).unwrap().unwrap(); - let cht_root_2 = db - .header_cht_root(cht_size, cht::start_number(cht_size, 0) + cht_size / 2) - .unwrap() - .unwrap(); - let cht_root_3 = - db.header_cht_root(cht_size, cht::end_number(cht_size, 0)).unwrap().unwrap(); - assert_eq!(cht_root_1, cht_root_2); - assert_eq!(cht_root_2, cht_root_3); - - let cht_root_1 = db - .changes_trie_cht_root(cht_size, cht::start_number(cht_size, 0)) - .unwrap() - .unwrap(); - let cht_root_2 = db - .changes_trie_cht_root(cht_size, cht::start_number(cht_size, 0) + cht_size / 2) - .unwrap() - .unwrap(); - let cht_root_3 = db - .changes_trie_cht_root(cht_size, cht::end_number(cht_size, 0)) - .unwrap() - .unwrap(); - assert_eq!(cht_root_1, cht_root_2); - assert_eq!(cht_root_2, cht_root_3); - } - - #[test] - fn tree_route_works() { - let db = LightStorage::new_test(); - let block0 = insert_block(&db, HashMap::new(), || default_header(&Default::default(), 0)); - - // fork from genesis: 3 prong. - let a1 = insert_block(&db, HashMap::new(), || default_header(&block0, 1)); - let a2 = insert_block(&db, HashMap::new(), || default_header(&a1, 2)); - let a3 = insert_block(&db, HashMap::new(), || default_header(&a2, 3)); - - // fork from genesis: 2 prong. - let b1 = insert_block(&db, HashMap::new(), || { - header_with_extrinsics_root(&block0, 1, Hash::from([1; 32])) - }); - let b2 = insert_block(&db, HashMap::new(), || default_header(&b1, 2)); - - { - let tree_route = tree_route(&db, a3, b2).unwrap(); - - assert_eq!(tree_route.common_block().hash, block0); - assert_eq!( - tree_route.retracted().iter().map(|r| r.hash).collect::>(), - vec![a3, a2, a1] - ); - assert_eq!( - tree_route.enacted().iter().map(|r| r.hash).collect::>(), - vec![b1, b2] - ); - } - - { - let tree_route = tree_route(&db, a1, a3).unwrap(); - - assert_eq!(tree_route.common_block().hash, a1); - assert!(tree_route.retracted().is_empty()); - assert_eq!( - tree_route.enacted().iter().map(|r| r.hash).collect::>(), - vec![a2, a3] - ); - } - - { - let tree_route = tree_route(&db, a3, a1).unwrap(); - - assert_eq!(tree_route.common_block().hash, a1); - assert_eq!( - tree_route.retracted().iter().map(|r| r.hash).collect::>(), - vec![a3, a2] - ); - assert!(tree_route.enacted().is_empty()); - } - - { - let tree_route = tree_route(&db, a2, a2).unwrap(); - - assert_eq!(tree_route.common_block().hash, a2); - assert!(tree_route.retracted().is_empty()); - assert!(tree_route.enacted().is_empty()); - } - } - - #[test] - fn lowest_common_ancestor_works() { - let db = LightStorage::new_test(); - let block0 = insert_block(&db, HashMap::new(), || default_header(&Default::default(), 0)); - - // fork from genesis: 3 prong. - let a1 = insert_block(&db, HashMap::new(), || default_header(&block0, 1)); - let a2 = insert_block(&db, HashMap::new(), || default_header(&a1, 2)); - let a3 = insert_block(&db, HashMap::new(), || default_header(&a2, 3)); - - // fork from genesis: 2 prong. - let b1 = insert_block(&db, HashMap::new(), || { - header_with_extrinsics_root(&block0, 1, Hash::from([1; 32])) - }); - let b2 = insert_block(&db, HashMap::new(), || default_header(&b1, 2)); - - { - let lca = lowest_common_ancestor(&db, a3, b2).unwrap(); - - assert_eq!(lca.hash, block0); - assert_eq!(lca.number, 0); - } - - { - let lca = lowest_common_ancestor(&db, a1, a3).unwrap(); - - assert_eq!(lca.hash, a1); - assert_eq!(lca.number, 1); - } - - { - let lca = lowest_common_ancestor(&db, a3, a1).unwrap(); - - assert_eq!(lca.hash, a1); - assert_eq!(lca.number, 1); - } - - { - let lca = lowest_common_ancestor(&db, a2, a3).unwrap(); - - assert_eq!(lca.hash, a2); - assert_eq!(lca.number, 2); - } - - { - let lca = lowest_common_ancestor(&db, a2, a1).unwrap(); - - assert_eq!(lca.hash, a1); - assert_eq!(lca.number, 1); - } - - { - let lca = lowest_common_ancestor(&db, a2, a2).unwrap(); - - assert_eq!(lca.hash, a2); - assert_eq!(lca.number, 2); - } - } - - #[test] - fn authorities_are_cached() { - let db = LightStorage::new_test(); - - fn run_checks( - db: &LightStorage, - max: u64, - checks: &[(u64, Option>)], - ) { - for (at, expected) in checks.iter().take_while(|(at, _)| *at <= max) { - let actual = authorities(db.cache(), BlockId::Number(*at)); - assert_eq!(*expected, actual); - } - } - - fn same_authorities() -> HashMap> { - HashMap::new() - } - - fn make_authorities( - authorities: Vec, - ) -> HashMap> { - let mut map = HashMap::new(); - map.insert(well_known_cache_keys::AUTHORITIES, authorities.encode()); - map - } - - fn authorities( - cache: &dyn BlockchainCache, - at: BlockId, - ) -> Option> { - cache - .get_at(&well_known_cache_keys::AUTHORITIES, &at) - .unwrap_or(None) - .and_then(|(_, _, val)| Decode::decode(&mut &val[..]).ok()) - } - - let auth1 = || AuthorityId::from_raw([1u8; 32]); - let auth2 = || AuthorityId::from_raw([2u8; 32]); - let auth3 = || AuthorityId::from_raw([3u8; 32]); - let auth4 = || AuthorityId::from_raw([4u8; 32]); - let auth5 = || AuthorityId::from_raw([5u8; 32]); - let auth6 = || AuthorityId::from_raw([6u8; 32]); - - let (hash2, hash6) = { - // first few blocks are instantly finalized - // B0(None) -> B1(None) -> B2(1) -> B3(1) -> B4(1, 2) -> B5(1, 2) -> B6(1, 2) - let checks = vec![ - (0, None), - (1, None), - (2, Some(vec![auth1()])), - (3, Some(vec![auth1()])), - (4, Some(vec![auth1(), auth2()])), - (5, Some(vec![auth1(), auth2()])), - (6, Some(vec![auth1(), auth2()])), - ]; - - let hash0 = insert_final_block(&db, same_authorities(), || { - default_header(&Default::default(), 0) - }); - run_checks(&db, 0, &checks); - let hash1 = insert_final_block(&db, same_authorities(), || default_header(&hash0, 1)); - run_checks(&db, 1, &checks); - let hash2 = insert_final_block(&db, make_authorities(vec![auth1()]), || { - default_header(&hash1, 2) - }); - run_checks(&db, 2, &checks); - let hash3 = insert_final_block(&db, make_authorities(vec![auth1()]), || { - default_header(&hash2, 3) - }); - run_checks(&db, 3, &checks); - let hash4 = insert_final_block(&db, make_authorities(vec![auth1(), auth2()]), || { - default_header(&hash3, 4) - }); - run_checks(&db, 4, &checks); - let hash5 = insert_final_block(&db, make_authorities(vec![auth1(), auth2()]), || { - default_header(&hash4, 5) - }); - run_checks(&db, 5, &checks); - let hash6 = insert_final_block(&db, same_authorities(), || default_header(&hash5, 6)); - run_checks(&db, 6, &checks); - - (hash2, hash6) - }; - - { - // some older non-best blocks are inserted - // ... -> B2(1) -> B2_1(1) -> B2_2(2) - // => the cache ignores all writes before best finalized block - let hash2_1 = insert_non_best_block(&db, make_authorities(vec![auth1()]), || { - default_header(&hash2, 3) - }); - assert_eq!(None, authorities(db.cache(), BlockId::Hash(hash2_1))); - let hash2_2 = - insert_non_best_block(&db, make_authorities(vec![auth1(), auth2()]), || { - default_header(&hash2_1, 4) - }); - assert_eq!(None, authorities(db.cache(), BlockId::Hash(hash2_2))); - } - - let (hash7, hash8, hash6_1, hash6_2, hash6_1_1, hash6_1_2) = { - // inserting non-finalized blocks - // B6(None) -> B7(3) -> B8(3) - // \> B6_1(4) -> B6_2(4) - // \> B6_1_1(5) - // \> B6_1_2(6) -> B6_1_3(7) - - let hash7 = - insert_block(&db, make_authorities(vec![auth3()]), || default_header(&hash6, 7)); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash6)), Some(vec![auth1(), auth2()])); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash7)), Some(vec![auth3()])); - let hash8 = - insert_block(&db, make_authorities(vec![auth3()]), || default_header(&hash7, 8)); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash6)), Some(vec![auth1(), auth2()])); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash7)), Some(vec![auth3()])); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash8)), Some(vec![auth3()])); - let hash6_1 = - insert_block(&db, make_authorities(vec![auth4()]), || default_header(&hash6, 7)); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash6)), Some(vec![auth1(), auth2()])); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash7)), Some(vec![auth3()])); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash8)), Some(vec![auth3()])); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash6_1)), Some(vec![auth4()])); - let hash6_1_1 = insert_non_best_block(&db, make_authorities(vec![auth5()]), || { - default_header(&hash6_1, 8) - }); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash6)), Some(vec![auth1(), auth2()])); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash7)), Some(vec![auth3()])); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash8)), Some(vec![auth3()])); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash6_1)), Some(vec![auth4()])); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash6_1_1)), Some(vec![auth5()])); - let hash6_1_2 = insert_non_best_block(&db, make_authorities(vec![auth6()]), || { - default_header(&hash6_1, 8) - }); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash6)), Some(vec![auth1(), auth2()])); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash7)), Some(vec![auth3()])); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash8)), Some(vec![auth3()])); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash6_1)), Some(vec![auth4()])); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash6_1_1)), Some(vec![auth5()])); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash6_1_2)), Some(vec![auth6()])); - let hash6_2 = - insert_block(&db, make_authorities(vec![auth4()]), || default_header(&hash6_1, 8)); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash6)), Some(vec![auth1(), auth2()])); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash7)), Some(vec![auth3()])); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash8)), Some(vec![auth3()])); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash6_1)), Some(vec![auth4()])); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash6_1_1)), Some(vec![auth5()])); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash6_1_2)), Some(vec![auth6()])); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash6_2)), Some(vec![auth4()])); - - (hash7, hash8, hash6_1, hash6_2, hash6_1_1, hash6_1_2) - }; - - { - // finalize block hash6_1 - db.finalize_header(BlockId::Hash(hash6_1)).unwrap(); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash6)), Some(vec![auth1(), auth2()])); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash7)), None); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash8)), None); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash6_1)), Some(vec![auth4()])); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash6_1_1)), Some(vec![auth5()])); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash6_1_2)), Some(vec![auth6()])); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash6_2)), Some(vec![auth4()])); - // finalize block hash6_2 - db.finalize_header(BlockId::Hash(hash6_2)).unwrap(); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash6)), Some(vec![auth1(), auth2()])); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash7)), None); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash8)), None); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash6_1)), Some(vec![auth4()])); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash6_1_1)), None); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash6_1_2)), None); - assert_eq!(authorities(db.cache(), BlockId::Hash(hash6_2)), Some(vec![auth4()])); - } - } - - #[test] - fn database_is_reopened() { - let db = LightStorage::new_test(); - let hash0 = - insert_final_block(&db, HashMap::new(), || default_header(&Default::default(), 0)); - assert_eq!(db.info().best_hash, hash0); - assert_eq!(db.header(BlockId::Hash(hash0)).unwrap().unwrap().hash(), hash0); - - let db = db.db; - let db = LightStorage::from_kvdb(db).unwrap(); - assert_eq!(db.info().best_hash, hash0); - assert_eq!(db.header(BlockId::Hash::(hash0)).unwrap().unwrap().hash(), hash0); - } - - #[test] - fn aux_store_works() { - let db = LightStorage::::new_test(); - - // insert aux1 + aux2 using direct store access - db.insert_aux(&[(&[1][..], &[101][..]), (&[2][..], &[102][..])], ::std::iter::empty()) - .unwrap(); - - // check aux values - assert_eq!(db.get_aux(&[1]).unwrap(), Some(vec![101])); - assert_eq!(db.get_aux(&[2]).unwrap(), Some(vec![102])); - assert_eq!(db.get_aux(&[3]).unwrap(), None); - - // delete aux1 + insert aux3 using import operation - db.import_header( - default_header(&Default::default(), 0), - HashMap::new(), - NewBlockState::Best, - vec![(vec![3], Some(vec![103])), (vec![1], None)], - ) - .unwrap(); - - // check aux values - assert_eq!(db.get_aux(&[1]).unwrap(), None); - assert_eq!(db.get_aux(&[2]).unwrap(), Some(vec![102])); - assert_eq!(db.get_aux(&[3]).unwrap(), Some(vec![103])); - } - - #[test] - fn cache_can_be_initialized_after_genesis_inserted() { - let (genesis_hash, storage) = { - let db = LightStorage::::new_test(); - - // before cache is initialized => Err - assert!(db.cache().get_at(b"test", &BlockId::Number(0)).is_err()); - - // insert genesis block (no value for cache is provided) - let mut genesis_hash = None; - insert_block(&db, HashMap::new(), || { - let header = default_header(&Default::default(), 0); - genesis_hash = Some(header.hash()); - header - }); - - // after genesis is inserted => None - assert_eq!(db.cache().get_at(b"test", &BlockId::Number(0)).unwrap(), None); - - // initialize cache - db.cache().initialize(b"test", vec![42]).unwrap(); - - // after genesis is inserted + cache is initialized => Some - assert_eq!( - db.cache().get_at(b"test", &BlockId::Number(0)).unwrap(), - Some(((0, genesis_hash.unwrap()), None, vec![42])), - ); - - (genesis_hash, db.db) - }; - - // restart && check that after restart value is read from the cache - let db = - LightStorage::::from_kvdb(storage as Arc<_>).expect("failed to create test-db"); - assert_eq!( - db.cache().get_at(b"test", &BlockId::Number(0)).unwrap(), - Some(((0, genesis_hash.unwrap()), None, vec![42])), - ); - } - - #[test] - fn changes_trie_configuration_is_tracked_on_light_client() { - let db = LightStorage::::new_test(); - - let new_config = Some(ChangesTrieConfiguration::new(2, 2)); - - // insert block#0 && block#1 (no value for cache is provided) - let hash0 = insert_block(&db, HashMap::new(), || default_header(&Default::default(), 0)); - assert_eq!( - db.cache() - .get_at(&well_known_cache_keys::CHANGES_TRIE_CONFIG, &BlockId::Number(0)) - .unwrap() - .map(|(_, _, v)| ChangesTrieConfiguration::decode(&mut &v[..]).unwrap()), - None, - ); - - // insert configuration at block#1 (starts from block#2) - insert_block(&db, HashMap::new(), || { - let mut header = default_header(&hash0, 1); - header.digest_mut().push(DigestItem::ChangesTrieSignal( - ChangesTrieSignal::NewConfiguration(new_config.clone()), - )); - header - }); - assert_eq!( - db.cache() - .get_at(&well_known_cache_keys::CHANGES_TRIE_CONFIG, &BlockId::Number(1)) - .unwrap() - .map(|(_, _, v)| Option::::decode(&mut &v[..]).unwrap()), - Some(new_config), - ); - } -} diff --git a/client/db/src/parity_db.rs b/client/db/src/parity_db.rs index 1b645ca9fb2b..61c0b94dc701 100644 --- a/client/db/src/parity_db.rs +++ b/client/db/src/parity_db.rs @@ -16,7 +16,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . use crate::{ - columns, light, + columns, utils::{DatabaseType, NUM_COLUMNS}, }; /// A `Database` adapter for parity-db. @@ -61,10 +61,6 @@ pub fn open>( state_col.preimage = true; state_col.uniform = true; }, - DatabaseType::Light => { - config.columns[light::columns::HEADER as usize].compression = - parity_db::CompressionType::Lz4; - }, } let db = if create { diff --git a/client/db/src/utils.rs b/client/db/src/utils.rs index 0e895eaaf385..b098a7864baf 100644 --- a/client/db/src/utils.rs +++ b/client/db/src/utils.rs @@ -56,10 +56,6 @@ pub mod meta_keys { pub const FINALIZED_STATE: &[u8; 6] = b"fstate"; /// Block gap. pub const BLOCK_GAP: &[u8; 3] = b"gap"; - /// Meta information prefix for list-based caches. - pub const CACHE_META_PREFIX: &[u8; 5] = b"cache"; - /// Meta information for changes tries key. - pub const CHANGES_TRIES_META: &[u8; 5] = b"ctrie"; /// Genesis block hash. pub const GENESIS_HASH: &[u8; 3] = b"gen"; /// Leaves prefix list key. @@ -95,8 +91,6 @@ pub type NumberIndexKey = [u8; 4]; pub enum DatabaseType { /// Full node database. Full, - /// Light node database. - Light, } /// Convert block number into short lookup key (LE representation) for @@ -124,19 +118,6 @@ where Ok(lookup_key) } -/// Convert block lookup key into block number. -/// all block lookup keys start with the block number. -pub fn lookup_key_to_number(key: &[u8]) -> sp_blockchain::Result -where - N: From, -{ - if key.len() < 4 { - return Err(sp_blockchain::Error::Backend("Invalid block key".into())) - } - Ok((key[0] as u32) << 24 | (key[1] as u32) << 16 | (key[2] as u32) << 8 | (key[3] as u32)) - .map(Into::into) -} - /// Delete number to hash mapping in DB transaction. pub fn remove_number_to_key_mapping>( transaction: &mut Transaction, @@ -147,18 +128,6 @@ pub fn remove_number_to_key_mapping>( Ok(()) } -/// Remove key mappings. -pub fn remove_key_mappings, H: AsRef<[u8]>>( - transaction: &mut Transaction, - key_lookup_col: u32, - number: N, - hash: H, -) -> sp_blockchain::Result<()> { - remove_number_to_key_mapping(transaction, key_lookup_col, number)?; - transaction.remove(key_lookup_col, hash.as_ref()); - Ok(()) -} - /// Place a number mapping into the database. This maps number to current perceived /// block hash at that position. pub fn insert_number_to_key_mapping + Clone, H: AsRef<[u8]>>( @@ -357,18 +326,6 @@ fn open_kvdb_rocksdb( other_col_budget, ); }, - DatabaseType::Light => { - let col_budget = cache_size / (NUM_COLUMNS as usize); - for i in 0..NUM_COLUMNS { - memory_budget.insert(i, col_budget); - } - log::trace!( - target: "db", - "Open RocksDB light database at {:?}, column cache: {} MiB", - path, - col_budget, - ); - }, } db_config.memory_budget = memory_budget; @@ -424,8 +381,7 @@ fn maybe_migrate_to_type_subdir( // See if there's a file identifying a rocksdb or paritydb folder in the parent dir and // the target path ends in a role specific directory if (basedir.join("db_version").exists() || basedir.join("metadata").exists()) && - (p.ends_with(DatabaseType::Full.as_str()) || - p.ends_with(DatabaseType::Light.as_str())) + (p.ends_with(DatabaseType::Full.as_str())) { // Try to open the database to check if the current `DatabaseType` matches the type of // database stored in the target directory and close the database on success. @@ -501,18 +457,6 @@ pub fn read_header( } } -/// Required header from the database. -pub fn require_header( - db: &dyn Database, - col_index: u32, - col: u32, - id: BlockId, -) -> sp_blockchain::Result { - read_header(db, col_index, col, id).and_then(|header| { - header.ok_or_else(|| sp_blockchain::Error::UnknownBlock(format!("Require header: {}", id))) - }) -} - /// Read meta from the database. pub fn read_meta( db: &dyn Database, @@ -598,7 +542,6 @@ impl DatabaseType { pub fn as_str(&self) -> &'static str { match *self { DatabaseType::Full => "full", - DatabaseType::Light => "light", } } } @@ -669,23 +612,12 @@ mod tests { assert!(old_db_path.join(db_type.as_str()).join(db_check_file).exists()); } - check_dir_for_db_type( - DatabaseType::Light, - DatabaseSource::RocksDb { path: PathBuf::new(), cache_size: 128 }, - "db_version", - ); check_dir_for_db_type( DatabaseType::Full, DatabaseSource::RocksDb { path: PathBuf::new(), cache_size: 128 }, "db_version", ); - #[cfg(feature = "with-parity-db")] - check_dir_for_db_type( - DatabaseType::Light, - DatabaseSource::ParityDb { path: PathBuf::new() }, - "metadata", - ); #[cfg(feature = "with-parity-db")] check_dir_for_db_type( DatabaseType::Full, @@ -709,16 +641,8 @@ mod tests { assert!(!old_db_path.join("light/db_version").exists()); assert!(!old_db_path.join("full/db_version").exists()); } - let source = DatabaseSource::RocksDb { - path: old_db_path.join(DatabaseType::Light.as_str()), - cache_size: 128, - }; - let settings = db_settings(source); - let db_res = open_database::(&settings, DatabaseType::Light); - assert!(db_res.is_err(), "Opening a light database in full role should fail"); // assert nothing was changed assert!(old_db_path.join("db_version").exists()); - assert!(!old_db_path.join("light/db_version").exists()); assert!(!old_db_path.join("full/db_version").exists()); } } @@ -735,7 +659,6 @@ mod tests { #[test] fn database_type_as_str_works() { assert_eq!(DatabaseType::Full.as_str(), "full"); - assert_eq!(DatabaseType::Light.as_str(), "light"); } #[test] diff --git a/client/executor/src/integration_tests/mod.rs b/client/executor/src/integration_tests/mod.rs index 1cded769c685..7aa02a61dba1 100644 --- a/client/executor/src/integration_tests/mod.rs +++ b/client/executor/src/integration_tests/mod.rs @@ -40,7 +40,7 @@ use tracing_subscriber::layer::SubscriberExt; use crate::WasmExecutionMethod; -pub type TestExternalities = CoreTestExternalities; +pub type TestExternalities = CoreTestExternalities; type HostFunctions = sp_io::SubstrateHostFunctions; /// Simple macro that runs a given method as test with the available wasm execution methods. diff --git a/client/finality-grandpa/src/import.rs b/client/finality-grandpa/src/import.rs index d54f7234b44b..000f7397ac9d 100644 --- a/client/finality-grandpa/src/import.rs +++ b/client/finality-grandpa/src/import.rs @@ -19,7 +19,7 @@ use std::{collections::HashMap, marker::PhantomData, sync::Arc}; use log::debug; -use parity_scale_codec::{Decode, Encode}; +use parity_scale_codec::Decode; use sc_client_api::{backend::Backend, utils::is_descendent_of}; use sc_consensus::{ @@ -35,7 +35,7 @@ use sp_core::hashing::twox_128; use sp_finality_grandpa::{ConsensusLog, GrandpaApi, ScheduledChange, SetId, GRANDPA_ENGINE_ID}; use sp_runtime::{ generic::{BlockId, OpaqueDigestItemId}, - traits::{Block as BlockT, DigestFor, Header as HeaderT, NumberFor, Zero}, + traits::{Block as BlockT, Header as HeaderT, NumberFor, Zero}, Justification, }; @@ -89,7 +89,6 @@ impl JustificationImport for GrandpaBlockImport where NumberFor: finality_grandpa::BlockNumberOps, - DigestFor: Encode, BE: Backend, Client: ClientForGrandpa, SC: SelectChain, @@ -229,7 +228,6 @@ pub fn find_forced_change( impl GrandpaBlockImport where NumberFor: finality_grandpa::BlockNumberOps, - DigestFor: Encode, BE: Backend, Client: ClientForGrandpa, Client::Api: GrandpaApi, @@ -515,7 +513,6 @@ where impl BlockImport for GrandpaBlockImport where NumberFor: finality_grandpa::BlockNumberOps, - DigestFor: Encode, BE: Backend, Client: ClientForGrandpa, Client::Api: GrandpaApi, diff --git a/client/finality-grandpa/src/lib.rs b/client/finality-grandpa/src/lib.rs index 452659ced6a7..e7618929fd08 100644 --- a/client/finality-grandpa/src/lib.rs +++ b/client/finality-grandpa/src/lib.rs @@ -58,7 +58,7 @@ use futures::{prelude::*, StreamExt}; use log::{debug, error, info}; -use parity_scale_codec::{Decode, Encode}; +use parity_scale_codec::Decode; use parking_lot::RwLock; use prometheus_endpoint::{PrometheusError, Registry}; use sc_client_api::{ @@ -77,7 +77,7 @@ use sp_core::crypto::Public; use sp_keystore::{SyncCryptoStore, SyncCryptoStorePtr}; use sp_runtime::{ generic::BlockId, - traits::{Block as BlockT, DigestFor, NumberFor, Zero}, + traits::{Block as BlockT, NumberFor, Zero}, }; pub use finality_grandpa::BlockNumberOps; @@ -718,7 +718,6 @@ where SC: SelectChain + 'static, VR: VotingRule + Clone + 'static, NumberFor: BlockNumberOps, - DigestFor: Encode, C: ClientForGrandpa + 'static, C::Api: GrandpaApi, { diff --git a/client/finality-grandpa/src/tests.rs b/client/finality-grandpa/src/tests.rs index 1aef7cd1b017..8439bf6963d0 100644 --- a/client/finality-grandpa/src/tests.rs +++ b/client/finality-grandpa/src/tests.rs @@ -43,6 +43,7 @@ use sp_finality_grandpa::{ use sp_keyring::Ed25519Keyring; use sp_keystore::{SyncCryptoStore, SyncCryptoStorePtr}; use sp_runtime::{ + codec::Encode, generic::{BlockId, DigestItem}, traits::{Block as BlockT, Header as HeaderT}, Justifications, @@ -139,26 +140,16 @@ impl TestNetFactory for GrandpaTestNet { &self, client: PeersClient, ) -> (BlockImportAdapter, Option>, PeerData) { - match client { - PeersClient::Full(ref client, ref backend) => { - let (import, link) = block_import( - client.clone(), - &self.test_config, - LongestChain::new(backend.clone()), - None, - ) - .expect("Could not create block import for fresh peer."); - let justification_import = Box::new(import.clone()); - ( - BlockImportAdapter::new(import), - Some(justification_import), - Mutex::new(Some(link)), - ) - }, - PeersClient::Light(..) => { - panic!("Light client is not used in tests."); - }, - } + let (client, backend) = (client.as_client(), client.as_backend()); + let (import, link) = block_import( + client.clone(), + &self.test_config, + LongestChain::new(backend.clone()), + None, + ) + .expect("Could not create block import for fresh peer."); + let justification_import = Box::new(import.clone()); + (BlockImportAdapter::new(import), Some(justification_import), Mutex::new(Some(link))) } fn peer(&mut self, i: usize) -> &mut GrandpaPeer { @@ -466,7 +457,7 @@ fn finalize_3_voters_1_full_observer() { // all peers should have stored the justification for the best finalized block #20 for peer_id in 0..4 { - let client = net.lock().peers[peer_id].client().as_full().unwrap(); + let client = net.lock().peers[peer_id].client().as_client(); let justification = crate::aux_schema::best_justification::<_, Block>(&*client).unwrap().unwrap(); @@ -539,7 +530,7 @@ fn transition_3_voters_twice_1_full_observer() { net.lock().block_until_sync(); for (i, peer) in net.lock().peers().iter().enumerate() { - let full_client = peer.client().as_full().expect("only full clients are used in test"); + let full_client = peer.client().as_client(); assert_eq!(full_client.chain_info().best_number, 1, "Peer #{} failed to sync", i); let set: AuthoritySet = @@ -614,7 +605,7 @@ fn transition_3_voters_twice_1_full_observer() { .take_while(|n| future::ready(n.header.number() < &30)) .for_each(move |_| future::ready(())) .map(move |()| { - let full_client = client.as_full().expect("only full clients are used in test"); + let full_client = client.as_client(); let set: AuthoritySet = crate::aux_schema::load_authorities(&*full_client).unwrap(); @@ -835,7 +826,7 @@ fn force_change_to_new_set() { for (i, peer) in net.lock().peers().iter().enumerate() { assert_eq!(peer.client().info().best_number, 26, "Peer #{} failed to sync", i); - let full_client = peer.client().as_full().expect("only full clients are used in test"); + let full_client = peer.client().as_client(); let set: AuthoritySet = crate::aux_schema::load_authorities(&*full_client).unwrap(); @@ -861,7 +852,7 @@ fn allows_reimporting_change_blocks() { let client = net.peer(0).client().clone(); let (mut block_import, ..) = net.make_block_import(client.clone()); - let full_client = client.as_full().unwrap(); + let full_client = client.as_client(); let builder = full_client .new_block_at(&BlockId::Number(0), Default::default(), false) .unwrap(); @@ -908,7 +899,7 @@ fn test_bad_justification() { let client = net.peer(0).client().clone(); let (mut block_import, ..) = net.make_block_import(client.clone()); - let full_client = client.as_full().expect("only full clients are used in test"); + let full_client = client.as_client(); let builder = full_client .new_block_at(&BlockId::Number(0), Default::default(), false) .unwrap(); @@ -1148,7 +1139,7 @@ fn voter_persists_its_votes() { .await; let block_30_hash = - net.lock().peer(0).client().as_full().unwrap().hash(30).unwrap().unwrap(); + net.lock().peer(0).client().as_client().hash(30).unwrap().unwrap(); // we restart alice's voter abort.abort(); @@ -1581,7 +1572,7 @@ fn imports_justification_for_regular_blocks_on_import() { let client = net.peer(0).client().clone(); let (mut block_import, ..) = net.make_block_import(client.clone()); - let full_client = client.as_full().expect("only full clients are used in test"); + let full_client = client.as_client(); let builder = full_client .new_block_at(&BlockId::Number(0), Default::default(), false) .unwrap(); diff --git a/client/light/Cargo.toml b/client/light/Cargo.toml deleted file mode 100644 index 1b83bf5be42f..000000000000 --- a/client/light/Cargo.toml +++ /dev/null @@ -1,27 +0,0 @@ -[package] -description = "components for a light client" -name = "sc-light" -version = "4.0.0-dev" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -authors = ["Parity Technologies "] -edition = "2021" -homepage = "https://substrate.io" -repository = "https://github.com/paritytech/substrate/" -documentation = "https://docs.rs/sc-light" -readme = "README.md" - -[dependencies] -parking_lot = "0.11.1" -hash-db = "0.15.2" -sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } -sp-externalities = { version = "0.10.0-dev", path = "../../primitives/externalities" } -sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } -sp-state-machine = { version = "0.10.0-dev", path = "../../primitives/state-machine" } -sc-client-api = { version = "4.0.0-dev", path = "../api" } -sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } -codec = { package = "parity-scale-codec", version = "2.0.0" } -sc-executor = { version = "0.10.0-dev", path = "../executor" } - -[features] -default = [] diff --git a/client/light/README.md b/client/light/README.md deleted file mode 100644 index 1ba1f155b165..000000000000 --- a/client/light/README.md +++ /dev/null @@ -1,3 +0,0 @@ -Light client components. - -License: GPL-3.0-or-later WITH Classpath-exception-2.0 \ No newline at end of file diff --git a/client/light/src/backend.rs b/client/light/src/backend.rs deleted file mode 100644 index 3091dce625a3..000000000000 --- a/client/light/src/backend.rs +++ /dev/null @@ -1,578 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2017-2021 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 . - -//! Light client backend. Only stores headers and justifications of blocks. -//! Everything else is requested from full nodes on demand. - -use parking_lot::RwLock; -use std::{ - collections::{HashMap, HashSet}, - sync::Arc, -}; - -use codec::{Decode, Encode}; - -use super::blockchain::Blockchain; -use hash_db::Hasher; -use sc_client_api::{ - backend::{ - AuxStore, Backend as ClientBackend, BlockImportOperation, NewBlockState, - PrunableStateChangesTrieStorage, RemoteBackend, - }, - blockchain::{well_known_cache_keys, HeaderBackend as BlockchainHeaderBackend}, - in_mem::check_genesis_storage, - light::Storage as BlockchainStorage, - UsageInfo, -}; -use sp_blockchain::{Error as ClientError, Result as ClientResult}; -use sp_core::{ - offchain::storage::InMemOffchainStorage, - storage::{well_known_keys, ChildInfo}, - ChangesTrieConfiguration, -}; -use sp_runtime::{ - generic::BlockId, - traits::{Block as BlockT, HashFor, Header, NumberFor, Zero}, - Justification, Justifications, Storage, -}; -use sp_state_machine::{ - Backend as StateBackend, ChangesTrieTransaction, ChildStorageCollection, InMemoryBackend, - IndexOperation, StorageCollection, TrieBackend, -}; - -const IN_MEMORY_EXPECT_PROOF: &str = - "InMemory state backend has Void error type and always succeeds; qed"; - -/// Light client backend. -pub struct Backend { - blockchain: Arc>, - genesis_state: RwLock>>, - import_lock: RwLock<()>, -} - -/// Light block (header and justification) import operation. -pub struct ImportOperation { - header: Option, - cache: HashMap>, - leaf_state: NewBlockState, - aux_ops: Vec<(Vec, Option>)>, - finalized_blocks: Vec>, - set_head: Option>, - storage_update: Option>>, - changes_trie_config_update: Option>, - _phantom: std::marker::PhantomData, -} - -/// Either in-memory genesis state, or locally-unavailable state. -pub enum GenesisOrUnavailableState { - /// Genesis state - storage values are stored in-memory. - Genesis(InMemoryBackend), - /// We know that state exists, but all calls will fail with error, because it - /// isn't locally available. - Unavailable, -} - -impl Backend { - /// Create new light backend. - pub fn new(blockchain: Arc>) -> Self { - Self { blockchain, genesis_state: RwLock::new(None), import_lock: Default::default() } - } - - /// Get shared blockchain reference. - pub fn blockchain(&self) -> &Arc> { - &self.blockchain - } -} - -impl AuxStore for Backend { - fn insert_aux< - 'a, - 'b: 'a, - 'c: 'a, - I: IntoIterator, - D: IntoIterator, - >( - &self, - insert: I, - delete: D, - ) -> ClientResult<()> { - self.blockchain.storage().insert_aux(insert, delete) - } - - fn get_aux(&self, key: &[u8]) -> ClientResult>> { - self.blockchain.storage().get_aux(key) - } -} - -impl ClientBackend for Backend> -where - Block: BlockT, - S: BlockchainStorage, - Block::Hash: Ord, -{ - type BlockImportOperation = ImportOperation; - type Blockchain = Blockchain; - type State = GenesisOrUnavailableState>; - type OffchainStorage = InMemOffchainStorage; - - fn begin_operation(&self) -> ClientResult { - Ok(ImportOperation { - header: None, - cache: Default::default(), - leaf_state: NewBlockState::Normal, - aux_ops: Vec::new(), - finalized_blocks: Vec::new(), - set_head: None, - storage_update: None, - changes_trie_config_update: None, - _phantom: Default::default(), - }) - } - - fn begin_state_operation( - &self, - _operation: &mut Self::BlockImportOperation, - _block: BlockId, - ) -> ClientResult<()> { - Ok(()) - } - - fn commit_operation(&self, mut operation: Self::BlockImportOperation) -> ClientResult<()> { - if !operation.finalized_blocks.is_empty() { - for block in operation.finalized_blocks { - self.blockchain.storage().finalize_header(block)?; - } - } - - if let Some(header) = operation.header { - let is_genesis_import = header.number().is_zero(); - if let Some(new_config) = operation.changes_trie_config_update { - operation - .cache - .insert(well_known_cache_keys::CHANGES_TRIE_CONFIG, new_config.encode()); - } - self.blockchain.storage().import_header( - header, - operation.cache, - operation.leaf_state, - operation.aux_ops, - )?; - - // when importing genesis block => remember its state - if is_genesis_import { - *self.genesis_state.write() = operation.storage_update.take(); - } - } else { - for (key, maybe_val) in operation.aux_ops { - match maybe_val { - Some(val) => self - .blockchain - .storage() - .insert_aux(&[(&key[..], &val[..])], std::iter::empty())?, - None => - self.blockchain.storage().insert_aux(std::iter::empty(), &[&key[..]])?, - } - } - } - - if let Some(set_head) = operation.set_head { - self.blockchain.storage().set_head(set_head)?; - } - - Ok(()) - } - - fn finalize_block( - &self, - block: BlockId, - _justification: Option, - ) -> ClientResult<()> { - self.blockchain.storage().finalize_header(block) - } - - fn append_justification( - &self, - _block: BlockId, - _justification: Justification, - ) -> ClientResult<()> { - Ok(()) - } - - fn blockchain(&self) -> &Blockchain { - &self.blockchain - } - - fn usage_info(&self) -> Option { - self.blockchain.storage().usage_info() - } - - fn changes_trie_storage(&self) -> Option<&dyn PrunableStateChangesTrieStorage> { - None - } - - fn offchain_storage(&self) -> Option { - None - } - - fn state_at(&self, block: BlockId) -> ClientResult { - let block_number = self.blockchain.expect_block_number_from_id(&block)?; - - // special case for genesis block - if block_number.is_zero() { - if let Some(genesis_state) = self.genesis_state.read().clone() { - return Ok(GenesisOrUnavailableState::Genesis(genesis_state)) - } - } - - // else return unavailable state. We do not return error here, because error - // would mean that we do not know this state at all. But we know that it exists - Ok(GenesisOrUnavailableState::Unavailable) - } - - fn revert( - &self, - _n: NumberFor, - _revert_finalized: bool, - ) -> ClientResult<(NumberFor, HashSet)> { - Err(ClientError::NotAvailableOnLightClient) - } - - fn remove_leaf_block(&self, _hash: &Block::Hash) -> ClientResult<()> { - Err(ClientError::NotAvailableOnLightClient) - } - - fn get_import_lock(&self) -> &RwLock<()> { - &self.import_lock - } -} - -impl RemoteBackend for Backend> -where - Block: BlockT, - S: BlockchainStorage + 'static, - Block::Hash: Ord, -{ - fn is_local_state_available(&self, block: &BlockId) -> bool { - self.genesis_state.read().is_some() && - self.blockchain - .expect_block_number_from_id(block) - .map(|num| num.is_zero()) - .unwrap_or(false) - } - - fn remote_blockchain(&self) -> Arc> { - self.blockchain.clone() - } -} - -impl BlockImportOperation for ImportOperation -where - Block: BlockT, - S: BlockchainStorage, - Block::Hash: Ord, -{ - type State = GenesisOrUnavailableState>; - - fn state(&self) -> ClientResult> { - // None means 'locally-stateless' backend - Ok(None) - } - - fn set_block_data( - &mut self, - header: Block::Header, - _body: Option>, - _indexed_body: Option>>, - _justifications: Option, - state: NewBlockState, - ) -> ClientResult<()> { - self.leaf_state = state; - self.header = Some(header); - Ok(()) - } - - fn update_cache(&mut self, cache: HashMap>) { - self.cache = cache; - } - - fn update_db_storage( - &mut self, - _update: >>::Transaction, - ) -> ClientResult<()> { - // we're not storing anything locally => ignore changes - Ok(()) - } - - fn update_changes_trie( - &mut self, - _update: ChangesTrieTransaction, NumberFor>, - ) -> ClientResult<()> { - // we're not storing anything locally => ignore changes - Ok(()) - } - - fn set_genesis_state(&mut self, input: Storage, commit: bool) -> ClientResult { - check_genesis_storage(&input)?; - - // changes trie configuration - let changes_trie_config = input - .top - .iter() - .find(|(k, _)| &k[..] == well_known_keys::CHANGES_TRIE_CONFIG) - .map(|(_, v)| { - Decode::decode(&mut &v[..]) - .expect("changes trie configuration is encoded properly at genesis") - }); - self.changes_trie_config_update = Some(changes_trie_config); - - // this is only called when genesis block is imported => shouldn't be performance bottleneck - let mut storage: HashMap, _> = HashMap::new(); - storage.insert(None, input.top); - - // create a list of children keys to re-compute roots for - let child_delta = input - .children_default - .iter() - .map(|(_storage_key, storage_child)| (&storage_child.child_info, std::iter::empty())); - - // make sure to persist the child storage - for (_child_key, storage_child) in input.children_default.clone() { - storage.insert(Some(storage_child.child_info), storage_child.data); - } - - let storage_update = InMemoryBackend::from(storage); - let (storage_root, _) = storage_update.full_storage_root(std::iter::empty(), child_delta); - if commit { - self.storage_update = Some(storage_update); - } - - Ok(storage_root) - } - - fn reset_storage(&mut self, _input: Storage) -> ClientResult { - Err(ClientError::NotAvailableOnLightClient) - } - - fn insert_aux(&mut self, ops: I) -> ClientResult<()> - where - I: IntoIterator, Option>)>, - { - self.aux_ops.append(&mut ops.into_iter().collect()); - Ok(()) - } - - fn update_storage( - &mut self, - _update: StorageCollection, - _child_update: ChildStorageCollection, - ) -> ClientResult<()> { - // we're not storing anything locally => ignore changes - Ok(()) - } - - fn mark_finalized( - &mut self, - block: BlockId, - _justifications: Option, - ) -> ClientResult<()> { - self.finalized_blocks.push(block); - Ok(()) - } - - fn mark_head(&mut self, block: BlockId) -> ClientResult<()> { - self.set_head = Some(block); - Ok(()) - } - - fn update_transaction_index( - &mut self, - _index: Vec, - ) -> sp_blockchain::Result<()> { - // noop for the light client - Ok(()) - } -} - -impl std::fmt::Debug for GenesisOrUnavailableState { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match *self { - GenesisOrUnavailableState::Genesis(ref state) => state.fmt(f), - GenesisOrUnavailableState::Unavailable => write!(f, "Unavailable"), - } - } -} - -impl StateBackend for GenesisOrUnavailableState -where - H::Out: Ord + codec::Codec, -{ - type Error = ClientError; - type Transaction = as StateBackend>::Transaction; - type TrieBackendStorage = as StateBackend>::TrieBackendStorage; - - fn storage(&self, key: &[u8]) -> ClientResult>> { - match *self { - GenesisOrUnavailableState::Genesis(ref state) => - Ok(state.storage(key).expect(IN_MEMORY_EXPECT_PROOF)), - GenesisOrUnavailableState::Unavailable => Err(ClientError::NotAvailableOnLightClient), - } - } - - fn child_storage(&self, child_info: &ChildInfo, key: &[u8]) -> ClientResult>> { - match *self { - GenesisOrUnavailableState::Genesis(ref state) => - Ok(state.child_storage(child_info, key).expect(IN_MEMORY_EXPECT_PROOF)), - GenesisOrUnavailableState::Unavailable => Err(ClientError::NotAvailableOnLightClient), - } - } - - fn next_storage_key(&self, key: &[u8]) -> Result>, Self::Error> { - match *self { - GenesisOrUnavailableState::Genesis(ref state) => - Ok(state.next_storage_key(key).expect(IN_MEMORY_EXPECT_PROOF)), - GenesisOrUnavailableState::Unavailable => Err(ClientError::NotAvailableOnLightClient), - } - } - - fn next_child_storage_key( - &self, - child_info: &ChildInfo, - key: &[u8], - ) -> Result>, Self::Error> { - match *self { - GenesisOrUnavailableState::Genesis(ref state) => - Ok(state.next_child_storage_key(child_info, key).expect(IN_MEMORY_EXPECT_PROOF)), - GenesisOrUnavailableState::Unavailable => Err(ClientError::NotAvailableOnLightClient), - } - } - - fn for_keys_with_prefix(&self, prefix: &[u8], action: A) { - match *self { - GenesisOrUnavailableState::Genesis(ref state) => - state.for_keys_with_prefix(prefix, action), - GenesisOrUnavailableState::Unavailable => (), - } - } - - fn for_key_values_with_prefix(&self, prefix: &[u8], action: A) { - match *self { - GenesisOrUnavailableState::Genesis(ref state) => - state.for_key_values_with_prefix(prefix, action), - GenesisOrUnavailableState::Unavailable => (), - } - } - - fn apply_to_key_values_while, Vec) -> bool>( - &self, - child_info: Option<&ChildInfo>, - prefix: Option<&[u8]>, - start_at: Option<&[u8]>, - action: A, - allow_missing: bool, - ) -> ClientResult { - match *self { - GenesisOrUnavailableState::Genesis(ref state) => Ok(state - .apply_to_key_values_while(child_info, prefix, start_at, action, allow_missing) - .expect(IN_MEMORY_EXPECT_PROOF)), - GenesisOrUnavailableState::Unavailable => Err(ClientError::NotAvailableOnLightClient), - } - } - - fn apply_to_keys_while bool>( - &self, - child_info: Option<&ChildInfo>, - prefix: Option<&[u8]>, - action: A, - ) { - match *self { - GenesisOrUnavailableState::Genesis(ref state) => - state.apply_to_keys_while(child_info, prefix, action), - GenesisOrUnavailableState::Unavailable => (), - } - } - - fn for_child_keys_with_prefix( - &self, - child_info: &ChildInfo, - prefix: &[u8], - action: A, - ) { - match *self { - GenesisOrUnavailableState::Genesis(ref state) => - state.for_child_keys_with_prefix(child_info, prefix, action), - GenesisOrUnavailableState::Unavailable => (), - } - } - - fn storage_root<'a>( - &self, - delta: impl Iterator)>, - ) -> (H::Out, Self::Transaction) - where - H::Out: Ord, - { - match *self { - GenesisOrUnavailableState::Genesis(ref state) => state.storage_root(delta), - GenesisOrUnavailableState::Unavailable => Default::default(), - } - } - - fn child_storage_root<'a>( - &self, - child_info: &ChildInfo, - delta: impl Iterator)>, - ) -> (H::Out, bool, Self::Transaction) - where - H::Out: Ord, - { - match *self { - GenesisOrUnavailableState::Genesis(ref state) => { - let (root, is_equal, _) = state.child_storage_root(child_info, delta); - (root, is_equal, Default::default()) - }, - GenesisOrUnavailableState::Unavailable => (H::Out::default(), true, Default::default()), - } - } - - fn pairs(&self) -> Vec<(Vec, Vec)> { - match *self { - GenesisOrUnavailableState::Genesis(ref state) => state.pairs(), - GenesisOrUnavailableState::Unavailable => Vec::new(), - } - } - - fn keys(&self, prefix: &[u8]) -> Vec> { - match *self { - GenesisOrUnavailableState::Genesis(ref state) => state.keys(prefix), - GenesisOrUnavailableState::Unavailable => Vec::new(), - } - } - - fn register_overlay_stats(&self, _stats: &sp_state_machine::StateMachineStats) {} - - fn usage_info(&self) -> sp_state_machine::UsageInfo { - sp_state_machine::UsageInfo::empty() - } - - fn as_trie_backend(&self) -> Option<&TrieBackend> { - match self { - GenesisOrUnavailableState::Genesis(ref state) => state.as_trie_backend(), - GenesisOrUnavailableState::Unavailable => None, - } - } -} diff --git a/client/light/src/blockchain.rs b/client/light/src/blockchain.rs deleted file mode 100644 index 24d9ef4fd4b9..000000000000 --- a/client/light/src/blockchain.rs +++ /dev/null @@ -1,219 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2017-2021 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 . - -//! Light client blockchain backend. Only stores headers and justifications of recent -//! blocks. CHT roots are stored for headers of ancient blocks. - -use std::sync::Arc; - -use sp_runtime::{ - generic::BlockId, - traits::{Block as BlockT, Header as HeaderT, NumberFor, Zero}, - Justifications, -}; - -use sc_client_api::light::RemoteHeaderRequest; -pub use sc_client_api::{ - backend::{AuxStore, NewBlockState, ProvideChtRoots}, - blockchain::{ - well_known_cache_keys, Backend as BlockchainBackend, BlockStatus, Cache as BlockchainCache, - HeaderBackend as BlockchainHeaderBackend, Info as BlockchainInfo, ProvideCache, - }, - cht, - light::{LocalOrRemote, RemoteBlockchain, Storage}, -}; -use sp_blockchain::{ - CachedHeaderMetadata, Error as ClientError, HeaderMetadata, Result as ClientResult, -}; - -/// Light client blockchain. -pub struct Blockchain { - storage: S, -} - -impl Blockchain { - /// Create new light blockchain backed with given storage. - pub fn new(storage: S) -> Self { - Self { storage } - } - - /// Get storage reference. - pub fn storage(&self) -> &S { - &self.storage - } -} - -impl BlockchainHeaderBackend for Blockchain -where - Block: BlockT, - S: Storage, -{ - fn header(&self, id: BlockId) -> ClientResult> { - match RemoteBlockchain::header(self, id)? { - LocalOrRemote::Local(header) => Ok(Some(header)), - LocalOrRemote::Remote(_) => Err(ClientError::NotAvailableOnLightClient), - LocalOrRemote::Unknown => Ok(None), - } - } - - fn info(&self) -> BlockchainInfo { - self.storage.info() - } - - fn status(&self, id: BlockId) -> ClientResult { - self.storage.status(id) - } - - fn number(&self, hash: Block::Hash) -> ClientResult>> { - self.storage.number(hash) - } - - fn hash( - &self, - number: <::Header as HeaderT>::Number, - ) -> ClientResult> { - self.storage.hash(number) - } -} - -impl HeaderMetadata for Blockchain -where - Block: BlockT, - S: Storage, -{ - type Error = ClientError; - - fn header_metadata( - &self, - hash: Block::Hash, - ) -> Result, Self::Error> { - self.storage.header_metadata(hash) - } - - fn insert_header_metadata(&self, hash: Block::Hash, metadata: CachedHeaderMetadata) { - self.storage.insert_header_metadata(hash, metadata) - } - - fn remove_header_metadata(&self, hash: Block::Hash) { - self.storage.remove_header_metadata(hash) - } -} - -impl BlockchainBackend for Blockchain -where - Block: BlockT, - S: Storage, -{ - fn body(&self, _id: BlockId) -> ClientResult>> { - Err(ClientError::NotAvailableOnLightClient) - } - - fn justifications(&self, _id: BlockId) -> ClientResult> { - Err(ClientError::NotAvailableOnLightClient) - } - - fn last_finalized(&self) -> ClientResult { - self.storage.last_finalized() - } - - fn cache(&self) -> Option>> { - self.storage.cache() - } - - fn leaves(&self) -> ClientResult> { - Err(ClientError::NotAvailableOnLightClient) - } - - fn children(&self, _parent_hash: Block::Hash) -> ClientResult> { - Err(ClientError::NotAvailableOnLightClient) - } - - fn indexed_transaction(&self, _hash: &Block::Hash) -> ClientResult>> { - Err(ClientError::NotAvailableOnLightClient) - } - - fn block_indexed_body( - &self, - _id: BlockId, - ) -> sp_blockchain::Result>>> { - Err(ClientError::NotAvailableOnLightClient) - } -} - -impl, Block: BlockT> ProvideCache for Blockchain { - fn cache(&self) -> Option>> { - self.storage.cache() - } -} - -impl RemoteBlockchain for Blockchain -where - S: Storage, -{ - fn header( - &self, - id: BlockId, - ) -> ClientResult>> { - // first, try to read header from local storage - if let Some(local_header) = self.storage.header(id)? { - return Ok(LocalOrRemote::Local(local_header)) - } - - // we need to know block number to check if it's a part of CHT - let number = match id { - BlockId::Hash(hash) => match self.storage.number(hash)? { - Some(number) => number, - None => return Ok(LocalOrRemote::Unknown), - }, - BlockId::Number(number) => number, - }; - - // if the header is genesis (never pruned), non-canonical, or from future => return - if number.is_zero() || self.storage.status(BlockId::Number(number))? == BlockStatus::Unknown - { - return Ok(LocalOrRemote::Unknown) - } - - Ok(LocalOrRemote::Remote(RemoteHeaderRequest { - cht_root: match self.storage.header_cht_root(cht::size(), number)? { - Some(cht_root) => cht_root, - None => return Ok(LocalOrRemote::Unknown), - }, - block: number, - retry_count: None, - })) - } -} - -impl, Block: BlockT> ProvideChtRoots for Blockchain { - fn header_cht_root( - &self, - cht_size: NumberFor, - block: NumberFor, - ) -> sp_blockchain::Result> { - self.storage().header_cht_root(cht_size, block) - } - - fn changes_trie_cht_root( - &self, - cht_size: NumberFor, - block: NumberFor, - ) -> sp_blockchain::Result> { - self.storage().changes_trie_cht_root(cht_size, block) - } -} diff --git a/client/light/src/call_executor.rs b/client/light/src/call_executor.rs deleted file mode 100644 index a0776131e406..000000000000 --- a/client/light/src/call_executor.rs +++ /dev/null @@ -1,206 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2017-2021 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 . - -//! Methods that light client could use to execute runtime calls. - -use std::{cell::RefCell, panic::UnwindSafe, result, sync::Arc}; - -use codec::{Decode, Encode}; -use hash_db::Hasher; -use sp_core::{ - convert_hash, - traits::{CodeExecutor, SpawnNamed}, - NativeOrEncoded, -}; -use sp_externalities::Extensions; -use sp_runtime::{ - generic::BlockId, - traits::{Block as BlockT, Header as HeaderT}, -}; -use sp_state_machine::{ - create_proof_check_backend, execution_proof_check_on_trie_backend, ExecutionManager, - ExecutionStrategy, OverlayedChanges, StorageProof, -}; - -use sp_api::{ProofRecorder, StorageTransactionCache}; - -use sp_blockchain::{Error as ClientError, Result as ClientResult}; - -use sc_client_api::{ - backend::RemoteBackend, call_executor::CallExecutor, light::RemoteCallRequest, -}; -use sc_executor::RuntimeVersion; - -/// Call executor that is able to execute calls only on genesis state. -/// -/// Trying to execute call on non-genesis state leads to error. -pub struct GenesisCallExecutor { - backend: Arc, - local: L, -} - -impl GenesisCallExecutor { - /// Create new genesis call executor. - pub fn new(backend: Arc, local: L) -> Self { - Self { backend, local } - } -} - -impl Clone for GenesisCallExecutor { - fn clone(&self) -> Self { - GenesisCallExecutor { backend: self.backend.clone(), local: self.local.clone() } - } -} - -impl CallExecutor for GenesisCallExecutor -where - Block: BlockT, - B: RemoteBackend, - Local: CallExecutor, -{ - type Error = ClientError; - - type Backend = B; - - fn call( - &self, - id: &BlockId, - method: &str, - call_data: &[u8], - strategy: ExecutionStrategy, - extensions: Option, - ) -> ClientResult> { - if self.backend.is_local_state_available(id) { - self.local.call(id, method, call_data, strategy, extensions) - } else { - Err(ClientError::NotAvailableOnLightClient) - } - } - - fn contextual_call< - EM: Fn( - Result, Self::Error>, - Result, Self::Error>, - ) -> Result, Self::Error>, - R: Encode + Decode + PartialEq, - NC: FnOnce() -> result::Result + UnwindSafe, - >( - &self, - at: &BlockId, - method: &str, - call_data: &[u8], - changes: &RefCell, - _: Option<&RefCell>>, - _manager: ExecutionManager, - native_call: Option, - recorder: &Option>, - extensions: Option, - ) -> ClientResult> - where - ExecutionManager: Clone, - { - // there's no actual way/need to specify native/wasm execution strategy on light node - // => we can safely ignore passed values - - if self.backend.is_local_state_available(at) { - CallExecutor::contextual_call::< - fn( - Result, Local::Error>, - Result, Local::Error>, - ) -> Result, Local::Error>, - _, - NC, - >( - &self.local, - at, - method, - call_data, - changes, - None, - ExecutionManager::NativeWhenPossible, - native_call, - recorder, - extensions, - ) - } else { - Err(ClientError::NotAvailableOnLightClient) - } - } - - fn prove_execution( - &self, - at: &BlockId, - method: &str, - call_data: &[u8], - ) -> ClientResult<(Vec, StorageProof)> { - if self.backend.is_local_state_available(at) { - self.local.prove_execution(at, method, call_data) - } else { - Err(ClientError::NotAvailableOnLightClient) - } - } - - fn runtime_version(&self, id: &BlockId) -> ClientResult { - if self.backend.is_local_state_available(id) { - self.local.runtime_version(id) - } else { - Err(ClientError::NotAvailableOnLightClient) - } - } -} - -/// Check remote contextual execution proof using given backend. -/// -/// Proof should include the method execution proof. -pub fn check_execution_proof( - executor: &E, - spawn_handle: Box, - request: &RemoteCallRequest

, - remote_proof: StorageProof, -) -> ClientResult> -where - Header: HeaderT, - E: CodeExecutor + Clone + 'static, - H: Hasher, - H::Out: Ord + codec::Codec + 'static, -{ - let local_state_root = request.header.state_root(); - let root: H::Out = convert_hash(&local_state_root); - - // prepare execution environment - let mut changes = OverlayedChanges::default(); - let trie_backend = create_proof_check_backend(root, remote_proof)?; - - // TODO: Remove when solved: https://github.com/paritytech/substrate/issues/5047 - let backend_runtime_code = sp_state_machine::backend::BackendRuntimeCode::new(&trie_backend); - let runtime_code = backend_runtime_code - .runtime_code() - .map_err(|_e| ClientError::RuntimeCodeMissing)?; - - // execute method - execution_proof_check_on_trie_backend::( - &trie_backend, - &mut changes, - executor, - spawn_handle, - &request.method, - &request.call_data, - &runtime_code, - ) - .map_err(Into::into) -} diff --git a/client/light/src/lib.rs b/client/light/src/lib.rs deleted file mode 100644 index 4b084cda0f8b..000000000000 --- a/client/light/src/lib.rs +++ /dev/null @@ -1,41 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2017-2021 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 . - -//! Light client components. - -use sp_runtime::traits::{Block as BlockT, HashFor}; -use std::sync::Arc; - -pub mod backend; -pub mod blockchain; -pub mod call_executor; - -pub use backend::*; -pub use blockchain::*; -pub use call_executor::*; - -use sc_client_api::light::Storage as BlockchainStorage; - -/// Create an instance of light client backend. -pub fn new_light_backend(blockchain: Arc>) -> Arc>> -where - B: BlockT, - S: BlockchainStorage, -{ - Arc::new(Backend::new(blockchain)) -} diff --git a/client/network/src/behaviour.rs b/client/network/src/behaviour.rs index 7b334175a280..e2b950cf67e8 100644 --- a/client/network/src/behaviour.rs +++ b/client/network/src/behaviour.rs @@ -20,14 +20,14 @@ use crate::{ bitswap::Bitswap, config::ProtocolId, discovery::{DiscoveryBehaviour, DiscoveryConfig, DiscoveryOut}, - light_client_requests, peer_info, + peer_info, protocol::{message::Roles, CustomMessageOutcome, NotificationsSink, Protocol}, request_responses, DhtEvent, ObservedRole, }; use bytes::Bytes; use codec::Encode; -use futures::{channel::oneshot, stream::StreamExt}; +use futures::channel::oneshot; use libp2p::{ core::{Multiaddr, PeerId, PublicKey}, identify::IdentifyInfo, @@ -76,10 +76,6 @@ pub struct Behaviour { #[behaviour(ignore)] events: VecDeque>, - /// Light client request handling. - #[behaviour(ignore)] - light_client_request_sender: light_client_requests::sender::LightClientRequestSender, - /// Protocol name used to send out block requests via /// [`request_responses::RequestResponsesBehaviour`]. #[behaviour(ignore)] @@ -198,7 +194,6 @@ impl Behaviour { substrate: Protocol, user_agent: String, local_public_key: PublicKey, - light_client_request_sender: light_client_requests::sender::LightClientRequestSender, disco_config: DiscoveryConfig, block_request_protocol_config: request_responses::ProtocolConfig, state_request_protocol_config: request_responses::ProtocolConfig, @@ -233,7 +228,6 @@ impl Behaviour { request_response_protocols.into_iter(), peerset, )?, - light_client_request_sender, events: VecDeque::new(), block_request_protocol_name, state_request_protocol_name, @@ -316,14 +310,6 @@ impl Behaviour { pub fn put_value(&mut self, key: record::Key, value: Vec) { self.discovery.put_value(key, value); } - - /// Issue a light client request. - pub fn light_client_request( - &mut self, - r: light_client_requests::sender::Request, - ) -> Result<(), light_client_requests::sender::SendRequestError> { - self.light_client_request_sender.request(r) - } } fn reported_roles_to_observed_role(roles: Roles) -> ObservedRole { @@ -436,17 +422,11 @@ impl NetworkBehaviourEventProcess> for Behavi CustomMessageOutcome::NotificationsReceived { remote, messages } => { self.events.push_back(BehaviourOut::NotificationsReceived { remote, messages }); }, - CustomMessageOutcome::PeerNewBest(peer_id, number) => { - self.light_client_request_sender.update_best_block(&peer_id, number); - }, - CustomMessageOutcome::SyncConnected(peer_id) => { - self.light_client_request_sender.inject_connected(peer_id); - self.events.push_back(BehaviourOut::SyncConnected(peer_id)) - }, - CustomMessageOutcome::SyncDisconnected(peer_id) => { - self.light_client_request_sender.inject_disconnected(peer_id); - self.events.push_back(BehaviourOut::SyncDisconnected(peer_id)) - }, + CustomMessageOutcome::PeerNewBest(_peer_id, _number) => {}, + CustomMessageOutcome::SyncConnected(peer_id) => + self.events.push_back(BehaviourOut::SyncConnected(peer_id)), + CustomMessageOutcome::SyncDisconnected(peer_id) => + self.events.push_back(BehaviourOut::SyncDisconnected(peer_id)), CustomMessageOutcome::None => {}, } } @@ -534,23 +514,9 @@ impl NetworkBehaviourEventProcess for Behaviour { impl Behaviour { fn poll( &mut self, - cx: &mut Context, + _cx: &mut Context, _: &mut impl PollParameters, ) -> Poll>> { - use light_client_requests::sender::OutEvent; - while let Poll::Ready(Some(event)) = self.light_client_request_sender.poll_next_unpin(cx) { - match event { - OutEvent::SendRequest { target, request, pending_response, protocol_name } => - self.request_responses.send_request( - &target, - &protocol_name, - request, - pending_response, - IfDisconnected::ImmediateError, - ), - } - } - if let Some(event) = self.events.pop_front() { return Poll::Ready(NetworkBehaviourAction::GenerateEvent(event)) } diff --git a/client/network/src/config.rs b/client/network/src/config.rs index 76c806ccbf7b..8ef52e46fd07 100644 --- a/client/network/src/config.rs +++ b/client/network/src/config.rs @@ -23,7 +23,6 @@ pub use crate::{ chain::Client, - on_demand_layer::{AlwaysBadChecker, OnDemand}, request_responses::{ IncomingRequest, OutgoingResponse, ProtocolConfig as RequestResponseConfig, }, @@ -83,11 +82,6 @@ pub struct Params { /// Client that contains the blockchain. pub chain: Arc>, - /// The `OnDemand` object acts as a "receiver" for block data requests from the client. - /// If `Some`, the network worker will process these requests and answer them. - /// Normally used only for light clients. - pub on_demand: Option>>, - /// Pool of transactions. /// /// The network worker will fetch transactions from this object in order to propagate them on diff --git a/client/network/src/lib.rs b/client/network/src/lib.rs index 2f81ddfa1fb1..cb16eb163ee4 100644 --- a/client/network/src/lib.rs +++ b/client/network/src/lib.rs @@ -247,7 +247,6 @@ mod behaviour; mod chain; mod discovery; -mod on_demand_layer; mod peer_info; mod protocol; mod request_responses; diff --git a/client/network/src/light_client_requests.rs b/client/network/src/light_client_requests.rs index e18b783f219b..b1793ce9384e 100644 --- a/client/network/src/light_client_requests.rs +++ b/client/network/src/light_client_requests.rs @@ -20,8 +20,6 @@ /// For incoming light client requests. pub mod handler; -/// For outgoing light client requests. -pub mod sender; use crate::{config::ProtocolId, request_responses::ProtocolConfig}; @@ -47,269 +45,3 @@ pub fn generate_protocol_config(protocol_id: &ProtocolId) -> ProtocolConfig { inbound_queue: None, } } - -#[cfg(test)] -mod tests { - use super::*; - use crate::{config::ProtocolId, request_responses::IncomingRequest}; - - use assert_matches::assert_matches; - use futures::{ - channel::oneshot, - executor::{block_on, LocalPool}, - prelude::*, - task::Spawn, - }; - use libp2p::PeerId; - use sc_client_api::{ - light::{ - self, ChangesProof, RemoteBodyRequest, RemoteCallRequest, RemoteChangesRequest, - RemoteHeaderRequest, RemoteReadRequest, - }, - FetchChecker, RemoteReadChildRequest, StorageProof, - }; - use sp_blockchain::Error as ClientError; - use sp_core::storage::ChildInfo; - use sp_runtime::{ - generic::Header, - traits::{BlakeTwo256, Block as BlockT, NumberFor}, - }; - use std::{collections::HashMap, sync::Arc}; - - pub struct DummyFetchChecker { - pub ok: bool, - pub _mark: std::marker::PhantomData, - } - - impl FetchChecker for DummyFetchChecker { - fn check_header_proof( - &self, - _request: &RemoteHeaderRequest, - header: Option, - _remote_proof: StorageProof, - ) -> Result { - match self.ok { - true if header.is_some() => Ok(header.unwrap()), - _ => Err(ClientError::Backend("Test error".into())), - } - } - - fn check_read_proof( - &self, - request: &RemoteReadRequest, - _: StorageProof, - ) -> Result, Option>>, ClientError> { - match self.ok { - true => Ok(request.keys.iter().cloned().map(|k| (k, Some(vec![42]))).collect()), - false => Err(ClientError::Backend("Test error".into())), - } - } - - fn check_read_child_proof( - &self, - request: &RemoteReadChildRequest, - _: StorageProof, - ) -> Result, Option>>, ClientError> { - match self.ok { - true => Ok(request.keys.iter().cloned().map(|k| (k, Some(vec![42]))).collect()), - false => Err(ClientError::Backend("Test error".into())), - } - } - - fn check_execution_proof( - &self, - _: &RemoteCallRequest, - _: StorageProof, - ) -> Result, ClientError> { - match self.ok { - true => Ok(vec![42]), - false => Err(ClientError::Backend("Test error".into())), - } - } - - fn check_changes_proof( - &self, - _: &RemoteChangesRequest, - _: ChangesProof, - ) -> Result, u32)>, ClientError> { - match self.ok { - true => Ok(vec![(100u32.into(), 2)]), - false => Err(ClientError::Backend("Test error".into())), - } - } - - fn check_body_proof( - &self, - _: &RemoteBodyRequest, - body: Vec, - ) -> Result, ClientError> { - match self.ok { - true => Ok(body), - false => Err(ClientError::Backend("Test error".into())), - } - } - } - - pub fn protocol_id() -> ProtocolId { - ProtocolId::from("test") - } - - pub fn peerset() -> (sc_peerset::Peerset, sc_peerset::PeersetHandle) { - let cfg = sc_peerset::SetConfig { - in_peers: 128, - out_peers: 128, - bootnodes: Default::default(), - reserved_only: false, - reserved_nodes: Default::default(), - }; - sc_peerset::Peerset::from_config(sc_peerset::PeersetConfig { sets: vec![cfg] }) - } - - pub fn dummy_header() -> sp_test_primitives::Header { - sp_test_primitives::Header { - parent_hash: Default::default(), - number: 0, - state_root: Default::default(), - extrinsics_root: Default::default(), - digest: Default::default(), - } - } - - type Block = - sp_runtime::generic::Block, substrate_test_runtime::Extrinsic>; - - fn send_receive(request: sender::Request, pool: &LocalPool) { - let client = Arc::new(substrate_test_runtime_client::new()); - let (handler, protocol_config) = - handler::LightClientRequestHandler::new(&protocol_id(), client); - pool.spawner().spawn_obj(handler.run().boxed().into()).unwrap(); - - let (_peer_set, peer_set_handle) = peerset(); - let mut sender = sender::LightClientRequestSender::::new( - &protocol_id(), - Arc::new(crate::light_client_requests::tests::DummyFetchChecker { - ok: true, - _mark: std::marker::PhantomData, - }), - peer_set_handle, - ); - sender.inject_connected(PeerId::random()); - - sender.request(request).unwrap(); - let sender::OutEvent::SendRequest { pending_response, request, .. } = - block_on(sender.next()).unwrap(); - let (tx, rx) = oneshot::channel(); - block_on(protocol_config.inbound_queue.unwrap().send(IncomingRequest { - peer: PeerId::random(), - payload: request, - pending_response: tx, - })) - .unwrap(); - pool.spawner() - .spawn_obj( - async move { - pending_response.send(Ok(rx.await.unwrap().result.unwrap())).unwrap(); - } - .boxed() - .into(), - ) - .unwrap(); - - pool.spawner() - .spawn_obj(sender.for_each(|_| future::ready(())).boxed().into()) - .unwrap(); - } - - #[test] - fn send_receive_call() { - let chan = oneshot::channel(); - let request = light::RemoteCallRequest { - block: Default::default(), - header: dummy_header(), - method: "test".into(), - call_data: vec![], - retry_count: None, - }; - - let mut pool = LocalPool::new(); - send_receive(sender::Request::Call { request, sender: chan.0 }, &pool); - assert_eq!(vec![42], pool.run_until(chan.1).unwrap().unwrap()); - // ^--- from `DummyFetchChecker::check_execution_proof` - } - - #[test] - fn send_receive_read() { - let chan = oneshot::channel(); - let request = light::RemoteReadRequest { - header: dummy_header(), - block: Default::default(), - keys: vec![b":key".to_vec()], - retry_count: None, - }; - let mut pool = LocalPool::new(); - send_receive(sender::Request::Read { request, sender: chan.0 }, &pool); - assert_eq!( - Some(vec![42]), - pool.run_until(chan.1).unwrap().unwrap().remove(&b":key"[..]).unwrap() - ); - // ^--- from `DummyFetchChecker::check_read_proof` - } - - #[test] - fn send_receive_read_child() { - let chan = oneshot::channel(); - let child_info = ChildInfo::new_default(&b":child_storage:default:sub"[..]); - let request = light::RemoteReadChildRequest { - header: dummy_header(), - block: Default::default(), - storage_key: child_info.prefixed_storage_key(), - keys: vec![b":key".to_vec()], - retry_count: None, - }; - let mut pool = LocalPool::new(); - send_receive(sender::Request::ReadChild { request, sender: chan.0 }, &pool); - assert_eq!( - Some(vec![42]), - pool.run_until(chan.1).unwrap().unwrap().remove(&b":key"[..]).unwrap() - ); - // ^--- from `DummyFetchChecker::check_read_child_proof` - } - - #[test] - fn send_receive_header() { - sp_tracing::try_init_simple(); - let chan = oneshot::channel(); - let request = light::RemoteHeaderRequest { - cht_root: Default::default(), - block: 1, - retry_count: None, - }; - let mut pool = LocalPool::new(); - send_receive(sender::Request::Header { request, sender: chan.0 }, &pool); - // The remote does not know block 1: - assert_matches!(pool.run_until(chan.1).unwrap(), Err(ClientError::RemoteFetchFailed)); - } - - #[test] - fn send_receive_changes() { - let chan = oneshot::channel(); - let request = light::RemoteChangesRequest { - changes_trie_configs: vec![sp_core::ChangesTrieConfigurationRange { - zero: (0, Default::default()), - end: None, - config: Some(sp_core::ChangesTrieConfiguration::new(4, 2)), - }], - first_block: (1, Default::default()), - last_block: (100, Default::default()), - max_block: (100, Default::default()), - tries_roots: (1, Default::default(), Vec::new()), - key: Vec::new(), - storage_key: None, - retry_count: None, - }; - let mut pool = LocalPool::new(); - send_receive(sender::Request::Changes { request, sender: chan.0 }, &pool); - assert_eq!(vec![(100, 2)], pool.run_until(chan.1).unwrap().unwrap()); - // ^--- from `DummyFetchChecker::check_changes_proof` - } -} diff --git a/client/network/src/light_client_requests/handler.rs b/client/network/src/light_client_requests/handler.rs index 43504edddd73..a04c5e310a67 100644 --- a/client/network/src/light_client_requests/handler.rs +++ b/client/network/src/light_client_requests/handler.rs @@ -32,17 +32,14 @@ use codec::{self, Decode, Encode}; use futures::{channel::mpsc, prelude::*}; use log::{debug, trace}; use prost::Message; -use sc_client_api::{light, StorageProof}; +use sc_client_api::StorageProof; use sc_peerset::ReputationChange; use sp_core::{ hexdisplay::HexDisplay, - storage::{ChildInfo, ChildType, PrefixedStorageKey, StorageKey}, + storage::{ChildInfo, ChildType, PrefixedStorageKey}, }; -use sp_runtime::{ - generic::BlockId, - traits::{Block, Zero}, -}; -use std::{collections::BTreeMap, sync::Arc}; +use sp_runtime::{generic::BlockId, traits::Block}; +use std::sync::Arc; const LOG_TARGET: &str = "light-client-request-handler"; @@ -137,12 +134,12 @@ impl LightClientRequestHandler { self.on_remote_call_request(&peer, r)?, Some(schema::v1::light::request::Request::RemoteReadRequest(r)) => self.on_remote_read_request(&peer, r)?, - Some(schema::v1::light::request::Request::RemoteHeaderRequest(r)) => - self.on_remote_header_request(&peer, r)?, + Some(schema::v1::light::request::Request::RemoteHeaderRequest(_r)) => + return Err(HandleRequestError::BadRequest("Not supported.")), Some(schema::v1::light::request::Request::RemoteReadChildRequest(r)) => self.on_remote_read_child_request(&peer, r)?, - Some(schema::v1::light::request::Request::RemoteChangesRequest(r)) => - self.on_remote_changes_request(&peer, r)?, + Some(schema::v1::light::request::Request::RemoteChangesRequest(_r)) => + return Err(HandleRequestError::BadRequest("Not supported.")), None => return Err(HandleRequestError::BadRequest("Remote request without request data.")), }; @@ -285,106 +282,6 @@ impl LightClientRequestHandler { Ok(schema::v1::light::Response { response: Some(response) }) } - - fn on_remote_header_request( - &mut self, - peer: &PeerId, - request: &schema::v1::light::RemoteHeaderRequest, - ) -> Result { - trace!("Remote header proof request from {} ({:?}).", peer, request.block); - - let block = Decode::decode(&mut request.block.as_ref())?; - let (header, proof) = match self.client.header_proof(&BlockId::Number(block)) { - Ok((header, proof)) => (header.encode(), proof), - Err(error) => { - trace!( - "Remote header proof request from {} ({:?}) failed with: {}.", - peer, - request.block, - error - ); - (Default::default(), StorageProof::empty()) - }, - }; - - let response = { - let r = schema::v1::light::RemoteHeaderResponse { header, proof: proof.encode() }; - schema::v1::light::response::Response::RemoteHeaderResponse(r) - }; - - Ok(schema::v1::light::Response { response: Some(response) }) - } - - fn on_remote_changes_request( - &mut self, - peer: &PeerId, - request: &schema::v1::light::RemoteChangesRequest, - ) -> Result { - trace!( - "Remote changes proof request from {} for key {} ({:?}..{:?}).", - peer, - if !request.storage_key.is_empty() { - format!( - "{} : {}", - HexDisplay::from(&request.storage_key), - HexDisplay::from(&request.key) - ) - } else { - HexDisplay::from(&request.key).to_string() - }, - request.first, - request.last, - ); - - let first = Decode::decode(&mut request.first.as_ref())?; - let last = Decode::decode(&mut request.last.as_ref())?; - let min = Decode::decode(&mut request.min.as_ref())?; - let max = Decode::decode(&mut request.max.as_ref())?; - let key = StorageKey(request.key.clone()); - let storage_key = if request.storage_key.is_empty() { - None - } else { - Some(PrefixedStorageKey::new_ref(&request.storage_key)) - }; - - let proof = - match self.client.key_changes_proof(first, last, min, max, storage_key, &key) { - Ok(proof) => proof, - Err(error) => { - trace!( - "Remote changes proof request from {} for key {} ({:?}..{:?}) failed with: {}.", - peer, - format!("{} : {}", HexDisplay::from(&request.storage_key), HexDisplay::from(&key.0)), - request.first, - request.last, - error, - ); - - light::ChangesProof:: { - max_block: Zero::zero(), - proof: Vec::new(), - roots: BTreeMap::new(), - roots_proof: StorageProof::empty(), - } - }, - }; - - let response = { - let r = schema::v1::light::RemoteChangesResponse { - max: proof.max_block.encode(), - proof: proof.proof, - roots: proof - .roots - .into_iter() - .map(|(k, v)| schema::v1::light::Pair { fst: k.encode(), snd: v.encode() }) - .collect(), - roots_proof: proof.roots_proof.encode(), - }; - schema::v1::light::response::Response::RemoteChangesResponse(r) - }; - - Ok(schema::v1::light::Response { response: Some(response) }) - } } #[derive(derive_more::Display, derive_more::From)] diff --git a/client/network/src/light_client_requests/sender.rs b/client/network/src/light_client_requests/sender.rs deleted file mode 100644 index 284db827594b..000000000000 --- a/client/network/src/light_client_requests/sender.rs +++ /dev/null @@ -1,1294 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2020-2021 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 . - -//! Helper for outgoing light client requests. -//! -//! Call [`LightClientRequestSender::request`](sender::LightClientRequestSender::request) -//! to send out light client requests. It will: -//! -//! 1. Build the request. -//! -//! 2. Forward the request to [`crate::request_responses::RequestResponsesBehaviour`] via -//! [`OutEvent::SendRequest`](sender::OutEvent::SendRequest). -//! -//! 3. Wait for the response and forward the response via the [`futures::channel::oneshot::Sender`] -//! provided earlier with [`LightClientRequestSender::request`](sender::LightClientRequestSender:: -//! request). - -use crate::{ - config::ProtocolId, - protocol::message::BlockAttributes, - request_responses::{OutboundFailure, RequestFailure}, - schema, PeerId, -}; -use codec::{self, Decode, Encode}; -use futures::{channel::oneshot, future::BoxFuture, prelude::*, stream::FuturesUnordered}; -use prost::Message; -use sc_client_api::light::{self, RemoteBodyRequest}; -use sc_peerset::ReputationChange; -use sp_blockchain::Error as ClientError; -use sp_runtime::traits::{Block, Header, NumberFor}; -use std::{ - collections::{BTreeMap, HashMap, VecDeque}, - pin::Pin, - sync::Arc, - task::{Context, Poll}, -}; - -mod rep { - use super::*; - - /// Reputation change for a peer when a request timed out. - pub const TIMEOUT: ReputationChange = - ReputationChange::new(-(1 << 8), "light client request timeout"); - /// Reputation change for a peer when a request is refused. - pub const REFUSED: ReputationChange = - ReputationChange::new(-(1 << 8), "light client request refused"); -} - -/// Configuration options for [`LightClientRequestSender`]. -#[derive(Debug, Clone)] -struct Config { - max_pending_requests: usize, - light_protocol: String, - block_protocol: String, -} - -impl Config { - /// Create a new [`LightClientRequestSender`] configuration. - pub fn new(id: &ProtocolId) -> Self { - Self { - max_pending_requests: 128, - light_protocol: super::generate_protocol_name(id), - block_protocol: crate::block_request_handler::generate_protocol_name(id), - } - } -} - -/// State machine helping to send out light client requests. -pub struct LightClientRequestSender { - /// This behaviour's configuration. - config: Config, - /// Verifies that received responses are correct. - checker: Arc>, - /// Peer information (addresses, their best block, etc.) - peers: HashMap>, - /// Pending (local) requests. - pending_requests: VecDeque>, - /// Requests on their way to remote peers. - sent_requests: FuturesUnordered< - BoxFuture< - 'static, - (SentRequest, Result, RequestFailure>, oneshot::Canceled>), - >, - >, - /// Handle to use for reporting misbehaviour of peers. - peerset: sc_peerset::PeersetHandle, -} - -/// Augments a pending light client request with metadata. -#[derive(Debug)] -struct PendingRequest { - /// Remaining attempts. - attempts_left: usize, - /// The actual request. - request: Request, -} - -impl PendingRequest { - fn new(req: Request) -> Self { - Self { - // Number of retries + one for the initial attempt. - attempts_left: req.retries() + 1, - request: req, - } - } - - fn into_sent(self, peer_id: PeerId) -> SentRequest { - SentRequest { attempts_left: self.attempts_left, request: self.request, peer: peer_id } - } -} - -/// Augments a light client request with metadata that is currently being send to a remote. -#[derive(Debug)] -struct SentRequest { - /// Remaining attempts. - attempts_left: usize, - /// The actual request. - request: Request, - /// The peer that the request is send to. - peer: PeerId, -} - -impl SentRequest { - fn into_pending(self) -> PendingRequest { - PendingRequest { attempts_left: self.attempts_left, request: self.request } - } -} - -impl Unpin for LightClientRequestSender {} - -impl LightClientRequestSender -where - B: Block, -{ - /// Construct a new light client handler. - pub fn new( - id: &ProtocolId, - checker: Arc>, - peerset: sc_peerset::PeersetHandle, - ) -> Self { - Self { - config: Config::new(id), - checker, - peers: Default::default(), - pending_requests: Default::default(), - sent_requests: Default::default(), - peerset, - } - } - - /// We rely on external information about peers best blocks as we lack the - /// means to determine it ourselves. - pub fn update_best_block(&mut self, peer: &PeerId, num: NumberFor) { - if let Some(info) = self.peers.get_mut(peer) { - log::trace!("new best block for {:?}: {:?}", peer, num); - info.best_block = Some(num) - } - } - - /// Issue a new light client request. - pub fn request(&mut self, req: Request) -> Result<(), SendRequestError> { - if self.pending_requests.len() >= self.config.max_pending_requests { - return Err(SendRequestError::TooManyRequests) - } - self.pending_requests.push_back(PendingRequest::new(req)); - Ok(()) - } - - /// Remove the given peer. - /// - /// In-flight requests to the given peer might fail and be retried. See - /// [`::poll_next`]. - fn remove_peer(&mut self, peer: PeerId) { - self.peers.remove(&peer); - } - - /// Process a local request's response from remote. - /// - /// If successful, this will give us the actual, checked data we should be - /// sending back to the client, otherwise an error. - fn on_response( - &mut self, - peer: PeerId, - request: &Request, - response: Response, - ) -> Result, Error> { - log::trace!("response from {}", peer); - match response { - Response::Light(r) => self.on_response_light(request, r), - Response::Block(r) => self.on_response_block(request, r), - } - } - - fn on_response_light( - &mut self, - request: &Request, - response: schema::v1::light::Response, - ) -> Result, Error> { - use schema::v1::light::response::Response; - match response.response { - Some(Response::RemoteCallResponse(response)) => { - if let Request::Call { request, .. } = request { - let proof = Decode::decode(&mut response.proof.as_ref())?; - let reply = self.checker.check_execution_proof(request, proof)?; - Ok(Reply::VecU8(reply)) - } else { - Err(Error::UnexpectedResponse) - } - }, - Some(Response::RemoteReadResponse(response)) => match request { - Request::Read { request, .. } => { - let proof = Decode::decode(&mut response.proof.as_ref())?; - let reply = self.checker.check_read_proof(&request, proof)?; - Ok(Reply::MapVecU8OptVecU8(reply)) - }, - Request::ReadChild { request, .. } => { - let proof = Decode::decode(&mut response.proof.as_ref())?; - let reply = self.checker.check_read_child_proof(&request, proof)?; - Ok(Reply::MapVecU8OptVecU8(reply)) - }, - _ => Err(Error::UnexpectedResponse), - }, - Some(Response::RemoteChangesResponse(response)) => { - if let Request::Changes { request, .. } = request { - let max_block = Decode::decode(&mut response.max.as_ref())?; - let roots_proof = Decode::decode(&mut response.roots_proof.as_ref())?; - let roots = { - let mut r = BTreeMap::new(); - for pair in response.roots { - let k = Decode::decode(&mut pair.fst.as_ref())?; - let v = Decode::decode(&mut pair.snd.as_ref())?; - r.insert(k, v); - } - r - }; - let reply = self.checker.check_changes_proof( - &request, - light::ChangesProof { - max_block, - proof: response.proof, - roots, - roots_proof, - }, - )?; - Ok(Reply::VecNumberU32(reply)) - } else { - Err(Error::UnexpectedResponse) - } - }, - Some(Response::RemoteHeaderResponse(response)) => { - if let Request::Header { request, .. } = request { - let header = if response.header.is_empty() { - None - } else { - Some(Decode::decode(&mut response.header.as_ref())?) - }; - let proof = Decode::decode(&mut response.proof.as_ref())?; - let reply = self.checker.check_header_proof(&request, header, proof)?; - Ok(Reply::Header(reply)) - } else { - Err(Error::UnexpectedResponse) - } - }, - None => Err(Error::UnexpectedResponse), - } - } - - fn on_response_block( - &mut self, - request: &Request, - response: schema::v1::BlockResponse, - ) -> Result, Error> { - let request = if let Request::Body { request, .. } = &request { - request - } else { - return Err(Error::UnexpectedResponse) - }; - - let body: Vec<_> = match response.blocks.into_iter().next() { - Some(b) => b.body, - None => return Err(Error::UnexpectedResponse), - }; - - let body = body - .into_iter() - .map(|extrinsic| B::Extrinsic::decode(&mut &extrinsic[..])) - .collect::>()?; - - let body = self.checker.check_body_proof(&request, body)?; - Ok(Reply::Extrinsics(body)) - } - - /// Signal that the node is connected to the given peer. - pub fn inject_connected(&mut self, peer: PeerId) { - let prev_entry = self.peers.insert(peer, Default::default()); - debug_assert!( - prev_entry.is_none(), - "Expect `inject_connected` to be called for disconnected peer.", - ); - } - - /// Signal that the node disconnected from the given peer. - pub fn inject_disconnected(&mut self, peer: PeerId) { - self.remove_peer(peer) - } -} - -impl Stream for LightClientRequestSender { - type Item = OutEvent; - - fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { - // If we have received responses to previously sent requests, check them and pass them on. - while let Poll::Ready(Some((sent_request, request_result))) = - self.sent_requests.poll_next_unpin(cx) - { - if let Some(info) = self.peers.get_mut(&sent_request.peer) { - if info.status != PeerStatus::Busy { - // If we get here, something is wrong with our internal handling of peer status - // information. At any time, a single peer processes at most one request from - // us. A malicious peer should not be able to get us here. It is our own fault - // and must be fixed! - panic!("unexpected peer status {:?} for {}", info.status, sent_request.peer); - } - - info.status = PeerStatus::Idle; // Make peer available again. - } - - let request_result = match request_result { - Ok(r) => r, - Err(oneshot::Canceled) => { - log::debug!("Oneshot for request to peer {} was canceled.", sent_request.peer); - self.remove_peer(sent_request.peer); - self.peerset.report_peer( - sent_request.peer, - ReputationChange::new_fatal("no response from peer"), - ); - self.pending_requests.push_back(sent_request.into_pending()); - continue - }, - }; - - let decoded_request_result = request_result.map(|response| { - if sent_request.request.is_block_request() { - schema::v1::BlockResponse::decode(&response[..]).map(|r| Response::Block(r)) - } else { - schema::v1::light::Response::decode(&response[..]).map(|r| Response::Light(r)) - } - }); - - let response = match decoded_request_result { - Ok(Ok(response)) => response, - Ok(Err(e)) => { - log::debug!( - "Failed to decode response from peer {}: {:?}.", - sent_request.peer, - e - ); - self.remove_peer(sent_request.peer); - self.peerset.report_peer( - sent_request.peer, - ReputationChange::new_fatal("invalid response from peer"), - ); - self.pending_requests.push_back(sent_request.into_pending()); - continue - }, - Err(e) => { - log::debug!("Request to peer {} failed with {:?}.", sent_request.peer, e); - - match e { - RequestFailure::NotConnected => { - self.remove_peer(sent_request.peer); - self.pending_requests.push_back(sent_request.into_pending()); - }, - RequestFailure::UnknownProtocol => { - debug_assert!( - false, - "Light client and block request protocol should be known when \ - sending requests.", - ); - }, - RequestFailure::Refused => { - self.remove_peer(sent_request.peer); - self.peerset.report_peer(sent_request.peer, rep::REFUSED); - self.pending_requests.push_back(sent_request.into_pending()); - }, - RequestFailure::Obsolete => { - debug_assert!( - false, - "Can not receive `RequestFailure::Obsolete` after dropping the \ - response receiver.", - ); - self.pending_requests.push_back(sent_request.into_pending()); - }, - RequestFailure::Network(OutboundFailure::Timeout) => { - self.remove_peer(sent_request.peer); - self.peerset.report_peer(sent_request.peer, rep::TIMEOUT); - self.pending_requests.push_back(sent_request.into_pending()); - }, - RequestFailure::Network(OutboundFailure::UnsupportedProtocols) => { - self.remove_peer(sent_request.peer); - self.peerset.report_peer( - sent_request.peer, - ReputationChange::new_fatal( - "peer does not support light client or block request protocol", - ), - ); - self.pending_requests.push_back(sent_request.into_pending()); - }, - RequestFailure::Network(OutboundFailure::DialFailure) => { - self.remove_peer(sent_request.peer); - self.peerset.report_peer( - sent_request.peer, - ReputationChange::new_fatal("failed to dial peer"), - ); - self.pending_requests.push_back(sent_request.into_pending()); - }, - RequestFailure::Network(OutboundFailure::ConnectionClosed) => { - self.remove_peer(sent_request.peer); - self.peerset.report_peer( - sent_request.peer, - ReputationChange::new_fatal("connection to peer closed"), - ); - self.pending_requests.push_back(sent_request.into_pending()); - }, - } - - continue - }, - }; - - match self.on_response(sent_request.peer, &sent_request.request, response) { - Ok(reply) => sent_request.request.return_reply(Ok(reply)), - Err(Error::UnexpectedResponse) => { - log::debug!("Unexpected response from peer {}.", sent_request.peer); - self.remove_peer(sent_request.peer); - self.peerset.report_peer( - sent_request.peer, - ReputationChange::new_fatal("unexpected response from peer"), - ); - self.pending_requests.push_back(sent_request.into_pending()); - }, - Err(other) => { - log::debug!( - "error handling response from peer {}: {}", - sent_request.peer, - other - ); - self.remove_peer(sent_request.peer); - self.peerset.report_peer( - sent_request.peer, - ReputationChange::new_fatal("invalid response from peer"), - ); - self.pending_requests.push_back(sent_request.into_pending()) - }, - } - } - - // If we have a pending request to send, try to find an available peer and send it. - while let Some(mut pending_request) = self.pending_requests.pop_front() { - if pending_request.attempts_left == 0 { - pending_request.request.return_reply(Err(ClientError::RemoteFetchFailed)); - continue - } - - let protocol = if pending_request.request.is_block_request() { - self.config.block_protocol.clone() - } else { - self.config.light_protocol.clone() - }; - - // Out of all idle peers, find one who's best block is high enough, choose any idle peer - // if none exists. - let mut peer = None; - for (peer_id, peer_info) in self.peers.iter_mut() { - if peer_info.status == PeerStatus::Idle { - match peer_info.best_block { - Some(n) if n >= pending_request.request.required_block() => { - peer = Some((*peer_id, peer_info)); - break - }, - _ => peer = Some((*peer_id, peer_info)), - } - } - } - - // Break in case there is no idle peer. - let (peer_id, peer_info) = match peer { - Some((peer_id, peer_info)) => (peer_id, peer_info), - None => { - self.pending_requests.push_front(pending_request); - log::debug!("No peer available to send request to."); - - break - }, - }; - - let request_bytes = match pending_request.request.serialize_request() { - Ok(bytes) => bytes, - Err(error) => { - log::debug!("failed to serialize request: {}", error); - pending_request.request.return_reply(Err(ClientError::RemoteFetchFailed)); - continue - }, - }; - - let (tx, rx) = oneshot::channel(); - - peer_info.status = PeerStatus::Busy; - - pending_request.attempts_left -= 1; - - self.sent_requests - .push(async move { (pending_request.into_sent(peer_id), rx.await) }.boxed()); - - return Poll::Ready(Some(OutEvent::SendRequest { - target: peer_id, - request: request_bytes, - pending_response: tx, - protocol_name: protocol, - })) - } - - Poll::Pending - } -} - -/// Events returned by [`LightClientRequestSender`]. -#[derive(Debug)] -pub enum OutEvent { - /// Emit a request to be send out on the network e.g. via [`crate::request_responses`]. - SendRequest { - /// The remote peer to send the request to. - target: PeerId, - /// The encoded request. - request: Vec, - /// The [`oneshot::Sender`] channel to pass the response to. - pending_response: oneshot::Sender, RequestFailure>>, - /// The name of the protocol to use to send the request. - protocol_name: String, - }, -} - -/// Incoming response from remote. -#[derive(Debug, Clone)] -pub enum Response { - /// Incoming light response from remote. - Light(schema::v1::light::Response), - /// Incoming block response from remote. - Block(schema::v1::BlockResponse), -} - -/// Error returned by [`LightClientRequestSender::request`]. -#[derive(Debug, derive_more::Display, derive_more::From)] -pub enum SendRequestError { - /// There are currently too many pending request. - #[display(fmt = "too many pending requests")] - TooManyRequests, -} - -/// Error type to propagate errors internally. -#[derive(Debug, derive_more::Display, derive_more::From)] -enum Error { - /// The response type does not correspond to the issued request. - #[display(fmt = "unexpected response")] - UnexpectedResponse, - /// Encoding or decoding of some data failed. - #[display(fmt = "codec error: {}", _0)] - Codec(codec::Error), - /// The chain client errored. - #[display(fmt = "client error: {}", _0)] - Client(ClientError), -} - -/// The data to send back to the light client over the oneshot channel. -// It is unified here in order to be able to return it as a function -// result instead of delivering it to the client as a side effect of -// response processing. -#[derive(Debug)] -enum Reply { - VecU8(Vec), - VecNumberU32(Vec<(::Number, u32)>), - MapVecU8OptVecU8(HashMap, Option>>), - Header(B::Header), - Extrinsics(Vec), -} - -/// Information we have about some peer. -#[derive(Debug)] -struct PeerInfo { - best_block: Option>, - status: PeerStatus, -} - -impl Default for PeerInfo { - fn default() -> Self { - PeerInfo { best_block: None, status: PeerStatus::Idle } - } -} - -/// A peer is either idle or busy processing a request from us. -#[derive(Debug, Clone, PartialEq, Eq)] -enum PeerStatus { - /// The peer is available. - Idle, - /// We wait for the peer to return us a response for the given request ID. - Busy, -} - -/// The possible light client requests we support. -/// -/// The associated `oneshot::Sender` will be used to convey the result of -/// their request back to them (cf. `Reply`). -// This is modeled after light_dispatch.rs's `RequestData` which is not -// used because we currently only support a subset of those. -#[derive(Debug)] -pub enum Request { - /// Remote body request. - Body { - /// Request. - request: RemoteBodyRequest, - /// [`oneshot::Sender`] to return response. - sender: oneshot::Sender, ClientError>>, - }, - /// Remote header request. - Header { - /// Request. - request: light::RemoteHeaderRequest, - /// [`oneshot::Sender`] to return response. - sender: oneshot::Sender>, - }, - /// Remote read request. - Read { - /// Request. - request: light::RemoteReadRequest, - /// [`oneshot::Sender`] to return response. - sender: oneshot::Sender, Option>>, ClientError>>, - }, - /// Remote read child request. - ReadChild { - /// Request. - request: light::RemoteReadChildRequest, - /// [`oneshot::Sender`] to return response. - sender: oneshot::Sender, Option>>, ClientError>>, - }, - /// Remote call request. - Call { - /// Request. - request: light::RemoteCallRequest, - /// [`oneshot::Sender`] to return response. - sender: oneshot::Sender, ClientError>>, - }, - /// Remote changes request. - Changes { - /// Request. - request: light::RemoteChangesRequest, - /// [`oneshot::Sender`] to return response. - sender: oneshot::Sender, u32)>, ClientError>>, - }, -} - -impl Request { - fn is_block_request(&self) -> bool { - matches!(self, Request::Body { .. }) - } - - fn required_block(&self) -> NumberFor { - match self { - Request::Body { request, .. } => *request.header.number(), - Request::Header { request, .. } => request.block, - Request::Read { request, .. } => *request.header.number(), - Request::ReadChild { request, .. } => *request.header.number(), - Request::Call { request, .. } => *request.header.number(), - Request::Changes { request, .. } => request.max_block.0, - } - } - - fn retries(&self) -> usize { - let rc = match self { - Request::Body { request, .. } => request.retry_count, - Request::Header { request, .. } => request.retry_count, - Request::Read { request, .. } => request.retry_count, - Request::ReadChild { request, .. } => request.retry_count, - Request::Call { request, .. } => request.retry_count, - Request::Changes { request, .. } => request.retry_count, - }; - rc.unwrap_or(0) - } - - fn serialize_request(&self) -> Result, prost::EncodeError> { - let request = match self { - Request::Body { request, .. } => { - let rq = schema::v1::BlockRequest { - fields: BlockAttributes::BODY.to_be_u32(), - from_block: Some(schema::v1::block_request::FromBlock::Hash( - request.header.hash().encode(), - )), - to_block: Default::default(), - direction: schema::v1::Direction::Ascending as i32, - max_blocks: 1, - support_multiple_justifications: true, - }; - - let mut buf = Vec::with_capacity(rq.encoded_len()); - rq.encode(&mut buf)?; - return Ok(buf) - }, - Request::Header { request, .. } => { - let r = schema::v1::light::RemoteHeaderRequest { block: request.block.encode() }; - schema::v1::light::request::Request::RemoteHeaderRequest(r) - }, - Request::Read { request, .. } => { - let r = schema::v1::light::RemoteReadRequest { - block: request.block.encode(), - keys: request.keys.clone(), - }; - schema::v1::light::request::Request::RemoteReadRequest(r) - }, - Request::ReadChild { request, .. } => { - let r = schema::v1::light::RemoteReadChildRequest { - block: request.block.encode(), - storage_key: request.storage_key.clone().into_inner(), - keys: request.keys.clone(), - }; - schema::v1::light::request::Request::RemoteReadChildRequest(r) - }, - Request::Call { request, .. } => { - let r = schema::v1::light::RemoteCallRequest { - block: request.block.encode(), - method: request.method.clone(), - data: request.call_data.clone(), - }; - schema::v1::light::request::Request::RemoteCallRequest(r) - }, - Request::Changes { request, .. } => { - let r = schema::v1::light::RemoteChangesRequest { - first: request.first_block.1.encode(), - last: request.last_block.1.encode(), - min: request.tries_roots.1.encode(), - max: request.max_block.1.encode(), - storage_key: request - .storage_key - .clone() - .map(|s| s.into_inner()) - .unwrap_or_default(), - key: request.key.clone(), - }; - schema::v1::light::request::Request::RemoteChangesRequest(r) - }, - }; - - let rq = schema::v1::light::Request { request: Some(request) }; - let mut buf = Vec::with_capacity(rq.encoded_len()); - rq.encode(&mut buf)?; - Ok(buf) - } - - fn return_reply(self, result: Result, ClientError>) { - fn send(item: T, sender: oneshot::Sender) { - let _ = sender.send(item); // It is okay if the other end already hung up. - } - match self { - Request::Body { request, sender } => match result { - Err(e) => send(Err(e), sender), - Ok(Reply::Extrinsics(x)) => send(Ok(x), sender), - reply => log::error!("invalid reply for body request: {:?}, {:?}", reply, request), - }, - Request::Header { request, sender } => match result { - Err(e) => send(Err(e), sender), - Ok(Reply::Header(x)) => send(Ok(x), sender), - reply => { - log::error!("invalid reply for header request: {:?}, {:?}", reply, request) - }, - }, - Request::Read { request, sender } => match result { - Err(e) => send(Err(e), sender), - Ok(Reply::MapVecU8OptVecU8(x)) => send(Ok(x), sender), - reply => log::error!("invalid reply for read request: {:?}, {:?}", reply, request), - }, - Request::ReadChild { request, sender } => match result { - Err(e) => send(Err(e), sender), - Ok(Reply::MapVecU8OptVecU8(x)) => send(Ok(x), sender), - reply => { - log::error!("invalid reply for read child request: {:?}, {:?}", reply, request) - }, - }, - Request::Call { request, sender } => match result { - Err(e) => send(Err(e), sender), - Ok(Reply::VecU8(x)) => send(Ok(x), sender), - reply => log::error!("invalid reply for call request: {:?}, {:?}", reply, request), - }, - Request::Changes { request, sender } => match result { - Err(e) => send(Err(e), sender), - Ok(Reply::VecNumberU32(x)) => send(Ok(x), sender), - reply => { - log::error!("invalid reply for changes request: {:?}, {:?}", reply, request) - }, - }, - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::{ - light_client_requests::tests::{dummy_header, peerset, protocol_id, DummyFetchChecker}, - request_responses::OutboundFailure, - }; - - use assert_matches::assert_matches; - use futures::{channel::oneshot, executor::block_on, poll}; - use sc_client_api::StorageProof; - use sp_core::storage::ChildInfo; - use sp_runtime::{generic::Header, traits::BlakeTwo256}; - use std::{collections::HashSet, iter::FromIterator}; - - fn empty_proof() -> Vec { - StorageProof::empty().encode() - } - - #[test] - fn removes_peer_if_told() { - let peer = PeerId::random(); - let (_peer_set, peer_set_handle) = peerset(); - let mut sender = LightClientRequestSender::::new( - &protocol_id(), - Arc::new(DummyFetchChecker { ok: true, _mark: std::marker::PhantomData }), - peer_set_handle, - ); - - sender.inject_connected(peer); - assert_eq!(1, sender.peers.len()); - - sender.inject_disconnected(peer); - assert_eq!(0, sender.peers.len()); - } - - type Block = - sp_runtime::generic::Block, substrate_test_runtime::Extrinsic>; - - #[test] - fn body_request_fields_encoded_properly() { - let (sender, _receiver) = oneshot::channel(); - let request = Request::::Body { - request: RemoteBodyRequest { header: dummy_header(), retry_count: None }, - sender, - }; - let serialized_request = request.serialize_request().unwrap(); - let deserialized_request = - schema::v1::BlockRequest::decode(&serialized_request[..]).unwrap(); - assert!(BlockAttributes::from_be_u32(deserialized_request.fields) - .unwrap() - .contains(BlockAttributes::BODY)); - } - - #[test] - fn disconnects_from_peer_if_request_times_out() { - let peer0 = PeerId::random(); - let peer1 = PeerId::random(); - - let (_peer_set, peer_set_handle) = peerset(); - let mut sender = LightClientRequestSender::::new( - &protocol_id(), - Arc::new(crate::light_client_requests::tests::DummyFetchChecker { - ok: true, - _mark: std::marker::PhantomData, - }), - peer_set_handle, - ); - - sender.inject_connected(peer0); - sender.inject_connected(peer1); - - assert_eq!( - HashSet::from_iter(&[peer0.clone(), peer1.clone()]), - sender.peers.keys().collect::>(), - "Expect knowledge of two peers." - ); - - assert!(sender.pending_requests.is_empty(), "Expect no pending request."); - assert!(sender.sent_requests.is_empty(), "Expect no sent request."); - - // Issue a request! - let chan = oneshot::channel(); - let request = light::RemoteCallRequest { - block: Default::default(), - header: dummy_header(), - method: "test".into(), - call_data: vec![], - retry_count: Some(1), - }; - sender.request(Request::Call { request, sender: chan.0 }).unwrap(); - assert_eq!(1, sender.pending_requests.len(), "Expect one pending request."); - - let OutEvent::SendRequest { target, pending_response, .. } = - block_on(sender.next()).unwrap(); - assert!(target == peer0 || target == peer1, "Expect request to originate from known peer."); - - // And we should have one busy peer. - assert!({ - let (idle, busy): (Vec<_>, Vec<_>) = - sender.peers.iter().partition(|(_, info)| info.status == PeerStatus::Idle); - idle.len() == 1 && - busy.len() == 1 && (idle[0].0 == &peer0 || busy[0].0 == &peer0) && - (idle[0].0 == &peer1 || busy[0].0 == &peer1) - }); - - assert_eq!(0, sender.pending_requests.len(), "Expect no pending request."); - assert_eq!(1, sender.sent_requests.len(), "Expect one request to be sent."); - - // Report first attempt as timed out. - pending_response - .send(Err(RequestFailure::Network(OutboundFailure::Timeout))) - .unwrap(); - - // Expect a new request to be issued. - let OutEvent::SendRequest { pending_response, .. } = block_on(sender.next()).unwrap(); - - assert_eq!(1, sender.peers.len(), "Expect peer to be removed."); - assert_eq!(0, sender.pending_requests.len(), "Expect no request to be pending."); - assert_eq!(1, sender.sent_requests.len(), "Expect new request to be issued."); - - // Report second attempt as timed out. - pending_response - .send(Err(RequestFailure::Network(OutboundFailure::Timeout))) - .unwrap(); - assert_matches!( - block_on(async { poll!(sender.next()) }), - Poll::Pending, - "Expect sender to not issue another attempt.", - ); - assert_matches!( - block_on(chan.1).unwrap(), - Err(ClientError::RemoteFetchFailed), - "Expect request failure to be reported.", - ); - assert_eq!(0, sender.peers.len(), "Expect no peer to be left"); - assert_eq!(0, sender.pending_requests.len(), "Expect no request to be pending."); - assert_eq!(0, sender.sent_requests.len(), "Expect no other request to be in progress."); - } - - #[test] - fn disconnects_from_peer_on_incorrect_response() { - let peer = PeerId::random(); - - let (_peer_set, peer_set_handle) = peerset(); - let mut sender = LightClientRequestSender::::new( - &protocol_id(), - Arc::new(crate::light_client_requests::tests::DummyFetchChecker { - ok: false, - // ^--- Making sure the response data check fails. - _mark: std::marker::PhantomData, - }), - peer_set_handle, - ); - - sender.inject_connected(peer); - assert_eq!(1, sender.peers.len(), "Expect one peer."); - - let chan = oneshot::channel(); - let request = light::RemoteCallRequest { - block: Default::default(), - header: dummy_header(), - method: "test".into(), - call_data: vec![], - retry_count: Some(1), - }; - sender.request(Request::Call { request, sender: chan.0 }).unwrap(); - - assert_eq!(1, sender.pending_requests.len(), "Expect one pending request."); - assert_eq!(0, sender.sent_requests.len(), "Expect zero sent requests."); - - let OutEvent::SendRequest { pending_response, .. } = block_on(sender.next()).unwrap(); - assert_eq!(0, sender.pending_requests.len(), "Expect zero pending requests."); - assert_eq!(1, sender.sent_requests.len(), "Expect one sent request."); - - let response = { - let r = schema::v1::light::RemoteCallResponse { proof: empty_proof() }; - let response = schema::v1::light::Response { - response: Some(schema::v1::light::response::Response::RemoteCallResponse(r)), - }; - let mut data = Vec::new(); - response.encode(&mut data).unwrap(); - data - }; - - pending_response.send(Ok(response)).unwrap(); - - assert_matches!( - block_on(async { poll!(sender.next()) }), - Poll::Pending, - "Expect sender to not issue another attempt, given that there is no peer left.", - ); - - assert!(sender.peers.is_empty(), "Expect no peers to be left."); - assert_eq!(1, sender.pending_requests.len(), "Expect request to be pending again."); - assert_eq!(0, sender.sent_requests.len(), "Expect no request to be sent."); - } - - #[test] - fn disconnects_from_peer_on_wrong_response_type() { - let peer = PeerId::random(); - let (_peer_set, peer_set_handle) = peerset(); - let mut sender = LightClientRequestSender::::new( - &protocol_id(), - Arc::new(crate::light_client_requests::tests::DummyFetchChecker { - ok: true, - _mark: std::marker::PhantomData, - }), - peer_set_handle, - ); - - sender.inject_connected(peer); - assert_eq!(1, sender.peers.len(), "Expect one peer."); - - let chan = oneshot::channel(); - let request = light::RemoteCallRequest { - block: Default::default(), - header: dummy_header(), - method: "test".into(), - call_data: vec![], - retry_count: Some(1), - }; - sender.request(Request::Call { request, sender: chan.0 }).unwrap(); - - assert_eq!(1, sender.pending_requests.len()); - assert_eq!(0, sender.sent_requests.len()); - let OutEvent::SendRequest { pending_response, .. } = block_on(sender.next()).unwrap(); - assert_eq!(0, sender.pending_requests.len(), "Expect zero pending requests."); - assert_eq!(1, sender.sent_requests.len(), "Expect one sent request."); - - let response = { - let r = schema::v1::light::RemoteReadResponse { proof: empty_proof() }; // Not a RemoteCallResponse! - let response = schema::v1::light::Response { - response: Some(schema::v1::light::response::Response::RemoteReadResponse(r)), - }; - let mut data = Vec::new(); - response.encode(&mut data).unwrap(); - data - }; - - pending_response.send(Ok(response)).unwrap(); - assert_matches!( - block_on(async { poll!(sender.next()) }), - Poll::Pending, - "Expect sender to not issue another attempt, given that there is no peer left.", - ); - - assert!(sender.peers.is_empty(), "Expect no peers to be left."); - assert_eq!(1, sender.pending_requests.len(), "Expect request to be pending again."); - assert_eq!(0, sender.sent_requests.len(), "Expect no request to be sent."); - } - - #[test] - fn receives_remote_failure_after_retry_count_failures() { - let peers = (0..4).map(|_| PeerId::random()).collect::>(); - - let (_peer_set, peer_set_handle) = peerset(); - let mut sender = LightClientRequestSender::::new( - &protocol_id(), - Arc::new(crate::light_client_requests::tests::DummyFetchChecker { - ok: false, - // ^--- Making sure the response data check fails. - _mark: std::marker::PhantomData, - }), - peer_set_handle, - ); - - for peer in &peers { - sender.inject_connected(*peer); - } - assert_eq!(4, sender.peers.len(), "Expect four peers."); - - let mut chan = oneshot::channel(); - let request = light::RemoteCallRequest { - block: Default::default(), - header: dummy_header(), - method: "test".into(), - call_data: vec![], - retry_count: Some(3), // Attempt up to three retries. - }; - sender.request(Request::Call { request, sender: chan.0 }).unwrap(); - - assert_eq!(1, sender.pending_requests.len()); - assert_eq!(0, sender.sent_requests.len()); - let mut pending_response = match block_on(sender.next()).unwrap() { - OutEvent::SendRequest { pending_response, .. } => Some(pending_response), - }; - assert_eq!(0, sender.pending_requests.len(), "Expect zero pending requests."); - assert_eq!(1, sender.sent_requests.len(), "Expect one sent request."); - - for (i, _peer) in peers.iter().enumerate() { - // Construct an invalid response - let response = { - let r = schema::v1::light::RemoteCallResponse { proof: empty_proof() }; - let response = schema::v1::light::Response { - response: Some(schema::v1::light::response::Response::RemoteCallResponse(r)), - }; - let mut data = Vec::new(); - response.encode(&mut data).unwrap(); - data - }; - pending_response.take().unwrap().send(Ok(response)).unwrap(); - - if i < 3 { - pending_response = match block_on(sender.next()).unwrap() { - OutEvent::SendRequest { pending_response, .. } => Some(pending_response), - }; - assert_matches!(chan.1.try_recv(), Ok(None)) - } else { - // Last peer and last attempt. - assert_matches!( - block_on(async { poll!(sender.next()) }), - Poll::Pending, - "Expect sender to not issue another attempt, given that there is no peer left.", - ); - assert_matches!(chan.1.try_recv(), Ok(Some(Err(ClientError::RemoteFetchFailed)))) - } - } - } - - fn issue_request(request: Request) { - let peer = PeerId::random(); - - let (_peer_set, peer_set_handle) = peerset(); - let mut sender = LightClientRequestSender::::new( - &protocol_id(), - Arc::new(crate::light_client_requests::tests::DummyFetchChecker { - ok: true, - _mark: std::marker::PhantomData, - }), - peer_set_handle, - ); - - sender.inject_connected(peer); - assert_eq!(1, sender.peers.len(), "Expect one peer."); - - let response = match request { - Request::Body { .. } => unimplemented!(), - Request::Header { .. } => { - let r = schema::v1::light::RemoteHeaderResponse { - header: dummy_header().encode(), - proof: empty_proof(), - }; - schema::v1::light::Response { - response: Some(schema::v1::light::response::Response::RemoteHeaderResponse(r)), - } - }, - Request::Read { .. } => { - let r = schema::v1::light::RemoteReadResponse { proof: empty_proof() }; - schema::v1::light::Response { - response: Some(schema::v1::light::response::Response::RemoteReadResponse(r)), - } - }, - Request::ReadChild { .. } => { - let r = schema::v1::light::RemoteReadResponse { proof: empty_proof() }; - schema::v1::light::Response { - response: Some(schema::v1::light::response::Response::RemoteReadResponse(r)), - } - }, - Request::Call { .. } => { - let r = schema::v1::light::RemoteCallResponse { proof: empty_proof() }; - schema::v1::light::Response { - response: Some(schema::v1::light::response::Response::RemoteCallResponse(r)), - } - }, - Request::Changes { .. } => { - let r = schema::v1::light::RemoteChangesResponse { - max: std::iter::repeat(1).take(32).collect(), - proof: Vec::new(), - roots: Vec::new(), - roots_proof: empty_proof(), - }; - schema::v1::light::Response { - response: Some(schema::v1::light::response::Response::RemoteChangesResponse(r)), - } - }, - }; - - let response = { - let mut data = Vec::new(); - response.encode(&mut data).unwrap(); - data - }; - - sender.request(request).unwrap(); - - assert_eq!(1, sender.pending_requests.len()); - assert_eq!(0, sender.sent_requests.len()); - let OutEvent::SendRequest { pending_response, .. } = block_on(sender.next()).unwrap(); - assert_eq!(0, sender.pending_requests.len()); - assert_eq!(1, sender.sent_requests.len()); - - pending_response.send(Ok(response)).unwrap(); - assert_matches!( - block_on(async { poll!(sender.next()) }), - Poll::Pending, - "Expect sender to not issue another attempt, given that there is no peer left.", - ); - - assert_eq!(0, sender.pending_requests.len()); - assert_eq!(0, sender.sent_requests.len()) - } - - #[test] - fn receives_remote_call_response() { - let mut chan = oneshot::channel(); - let request = light::RemoteCallRequest { - block: Default::default(), - header: dummy_header(), - method: "test".into(), - call_data: vec![], - retry_count: None, - }; - issue_request(Request::Call { request, sender: chan.0 }); - assert_matches!(chan.1.try_recv(), Ok(Some(Ok(_)))) - } - - #[test] - fn receives_remote_read_response() { - let mut chan = oneshot::channel(); - let request = light::RemoteReadRequest { - header: dummy_header(), - block: Default::default(), - keys: vec![b":key".to_vec()], - retry_count: None, - }; - issue_request(Request::Read { request, sender: chan.0 }); - assert_matches!(chan.1.try_recv(), Ok(Some(Ok(_)))) - } - - #[test] - fn receives_remote_read_child_response() { - let mut chan = oneshot::channel(); - let child_info = ChildInfo::new_default(&b":child_storage:default:sub"[..]); - let request = light::RemoteReadChildRequest { - header: dummy_header(), - block: Default::default(), - storage_key: child_info.prefixed_storage_key(), - keys: vec![b":key".to_vec()], - retry_count: None, - }; - issue_request(Request::ReadChild { request, sender: chan.0 }); - assert_matches!(chan.1.try_recv(), Ok(Some(Ok(_)))) - } - - #[test] - fn receives_remote_header_response() { - let mut chan = oneshot::channel(); - let request = light::RemoteHeaderRequest { - cht_root: Default::default(), - block: 1, - retry_count: None, - }; - issue_request(Request::Header { request, sender: chan.0 }); - assert_matches!(chan.1.try_recv(), Ok(Some(Ok(_)))) - } - - #[test] - fn receives_remote_changes_response() { - let mut chan = oneshot::channel(); - let request = light::RemoteChangesRequest { - changes_trie_configs: vec![sp_core::ChangesTrieConfigurationRange { - zero: (0, Default::default()), - end: None, - config: Some(sp_core::ChangesTrieConfiguration::new(4, 2)), - }], - first_block: (1, Default::default()), - last_block: (100, Default::default()), - max_block: (100, Default::default()), - tries_roots: (1, Default::default(), Vec::new()), - key: Vec::new(), - storage_key: None, - retry_count: None, - }; - issue_request(Request::Changes { request, sender: chan.0 }); - assert_matches!(chan.1.try_recv(), Ok(Some(Ok(_)))) - } -} diff --git a/client/network/src/on_demand_layer.rs b/client/network/src/on_demand_layer.rs deleted file mode 100644 index eaeb0bee98f2..000000000000 --- a/client/network/src/on_demand_layer.rs +++ /dev/null @@ -1,241 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2017-2021 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 . - -//! On-demand requests service. - -use crate::light_client_requests; - -use futures::{channel::oneshot, prelude::*}; -use parking_lot::Mutex; -use sc_client_api::{ - ChangesProof, FetchChecker, Fetcher, RemoteBodyRequest, RemoteCallRequest, - RemoteChangesRequest, RemoteHeaderRequest, RemoteReadChildRequest, RemoteReadRequest, - StorageProof, -}; -use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender}; -use sp_blockchain::Error as ClientError; -use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor}; -use std::{ - collections::HashMap, - pin::Pin, - sync::Arc, - task::{Context, Poll}, -}; - -/// Implements the `Fetcher` trait of the client. Makes it possible for the light client to perform -/// network requests for some state. -/// -/// This implementation stores all the requests in a queue. The network, in parallel, is then -/// responsible for pulling elements out of that queue and fulfilling them. -pub struct OnDemand { - /// Objects that checks whether what has been retrieved is correct. - checker: Arc>, - - /// Queue of requests. Set to `Some` at initialization, then extracted by the network. - /// - /// Note that a better alternative would be to use a MPMC queue here, and add a `poll` method - /// from the `OnDemand`. However there exists no popular implementation of MPMC channels in - /// asynchronous Rust at the moment - requests_queue: - Mutex>>>, - - /// Sending side of `requests_queue`. - requests_send: TracingUnboundedSender>, -} - -#[derive(Debug, thiserror::Error)] -#[error("AlwaysBadChecker")] -struct ErrorAlwaysBadChecker; - -impl Into for ErrorAlwaysBadChecker { - fn into(self) -> ClientError { - ClientError::Application(Box::new(self)) - } -} - -/// Dummy implementation of `FetchChecker` that always assumes that responses are bad. -/// -/// Considering that it is the responsibility of the client to build the fetcher, it can use this -/// implementation if it knows that it will never perform any request. -#[derive(Default, Clone)] -pub struct AlwaysBadChecker; - -impl FetchChecker for AlwaysBadChecker { - fn check_header_proof( - &self, - _request: &RemoteHeaderRequest, - _remote_header: Option, - _remote_proof: StorageProof, - ) -> Result { - Err(ErrorAlwaysBadChecker.into()) - } - - fn check_read_proof( - &self, - _request: &RemoteReadRequest, - _remote_proof: StorageProof, - ) -> Result, Option>>, ClientError> { - Err(ErrorAlwaysBadChecker.into()) - } - - fn check_read_child_proof( - &self, - _request: &RemoteReadChildRequest, - _remote_proof: StorageProof, - ) -> Result, Option>>, ClientError> { - Err(ErrorAlwaysBadChecker.into()) - } - - fn check_execution_proof( - &self, - _request: &RemoteCallRequest, - _remote_proof: StorageProof, - ) -> Result, ClientError> { - Err(ErrorAlwaysBadChecker.into()) - } - - fn check_changes_proof( - &self, - _request: &RemoteChangesRequest, - _remote_proof: ChangesProof, - ) -> Result, u32)>, ClientError> { - Err(ErrorAlwaysBadChecker.into()) - } - - fn check_body_proof( - &self, - _request: &RemoteBodyRequest, - _body: Vec, - ) -> Result, ClientError> { - Err(ErrorAlwaysBadChecker.into()) - } -} - -impl OnDemand -where - B::Header: HeaderT, -{ - /// Creates new on-demand service. - pub fn new(checker: Arc>) -> Self { - let (requests_send, requests_queue) = tracing_unbounded("mpsc_ondemand"); - let requests_queue = Mutex::new(Some(requests_queue)); - - Self { checker, requests_queue, requests_send } - } - - /// Get checker reference. - pub fn checker(&self) -> &Arc> { - &self.checker - } - - /// Extracts the queue of requests. - /// - /// Whenever one of the methods of the `Fetcher` trait is called, an element is pushed on this - /// channel. - /// - /// If this function returns `None`, that means that the receiver has already been extracted in - /// the past, and therefore that something already handles the requests. - pub(crate) fn extract_receiver( - &self, - ) -> Option>> { - self.requests_queue.lock().take() - } -} - -impl Fetcher for OnDemand -where - B: BlockT, - B::Header: HeaderT, -{ - type RemoteHeaderResult = RemoteResponse; - type RemoteReadResult = RemoteResponse, Option>>>; - type RemoteCallResult = RemoteResponse>; - type RemoteChangesResult = RemoteResponse, u32)>>; - type RemoteBodyResult = RemoteResponse>; - - fn remote_header(&self, request: RemoteHeaderRequest) -> Self::RemoteHeaderResult { - let (sender, receiver) = oneshot::channel(); - let _ = self - .requests_send - .unbounded_send(light_client_requests::sender::Request::Header { request, sender }); - RemoteResponse { receiver } - } - - fn remote_read(&self, request: RemoteReadRequest) -> Self::RemoteReadResult { - let (sender, receiver) = oneshot::channel(); - let _ = self - .requests_send - .unbounded_send(light_client_requests::sender::Request::Read { request, sender }); - RemoteResponse { receiver } - } - - fn remote_read_child( - &self, - request: RemoteReadChildRequest, - ) -> Self::RemoteReadResult { - let (sender, receiver) = oneshot::channel(); - let _ = self - .requests_send - .unbounded_send(light_client_requests::sender::Request::ReadChild { request, sender }); - RemoteResponse { receiver } - } - - fn remote_call(&self, request: RemoteCallRequest) -> Self::RemoteCallResult { - let (sender, receiver) = oneshot::channel(); - let _ = self - .requests_send - .unbounded_send(light_client_requests::sender::Request::Call { request, sender }); - RemoteResponse { receiver } - } - - fn remote_changes( - &self, - request: RemoteChangesRequest, - ) -> Self::RemoteChangesResult { - let (sender, receiver) = oneshot::channel(); - let _ = self - .requests_send - .unbounded_send(light_client_requests::sender::Request::Changes { request, sender }); - RemoteResponse { receiver } - } - - fn remote_body(&self, request: RemoteBodyRequest) -> Self::RemoteBodyResult { - let (sender, receiver) = oneshot::channel(); - let _ = self - .requests_send - .unbounded_send(light_client_requests::sender::Request::Body { request, sender }); - RemoteResponse { receiver } - } -} - -/// Future for an on-demand remote call response. -pub struct RemoteResponse { - receiver: oneshot::Receiver>, -} - -impl Future for RemoteResponse { - type Output = Result; - - fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll { - match self.receiver.poll_unpin(cx) { - Poll::Ready(Ok(res)) => Poll::Ready(res), - Poll::Ready(Err(_)) => Poll::Ready(Err(ClientError::RemoteFetchCancelled)), - Poll::Pending => Poll::Pending, - } - } -} diff --git a/client/network/src/service.rs b/client/network/src/service.rs index 90e647505fa1..caf4db89f653 100644 --- a/client/network/src/service.rs +++ b/client/network/src/service.rs @@ -33,11 +33,9 @@ use crate::{ config::{parse_str_addr, Params, TransportConfig}, discovery::DiscoveryConfig, error::Error, - light_client_requests, network_state::{ NetworkState, NotConnectedPeer as NetworkStateNotConnectedPeer, Peer as NetworkStatePeer, }, - on_demand_layer::AlwaysBadChecker, protocol::{ self, event::Event, @@ -238,12 +236,6 @@ impl NetworkWorker { } })?; - let checker = params - .on_demand - .as_ref() - .map(|od| od.checker().clone()) - .unwrap_or_else(|| Arc::new(AlwaysBadChecker)); - let num_connected = Arc::new(AtomicUsize::new(0)); let is_major_syncing = Arc::new(AtomicBool::new(false)); @@ -255,14 +247,6 @@ impl NetworkWorker { params.network_config.client_version, params.network_config.node_name ); - let light_client_request_sender = { - light_client_requests::sender::LightClientRequestSender::new( - ¶ms.protocol_id, - checker, - peerset_handle.clone(), - ) - }; - let discovery_config = { let mut config = DiscoveryConfig::new(local_public.clone()); config.with_permanent_addresses(known_addresses); @@ -347,7 +331,6 @@ impl NetworkWorker { protocol, user_agent, local_public, - light_client_request_sender, discovery_config, params.block_request_protocol_config, params.state_request_protocol_config, @@ -447,7 +430,6 @@ impl NetworkWorker { service, import_queue: params.import_queue, from_service, - light_client_rqs: params.on_demand.and_then(|od| od.extract_receiver()), event_streams: out_events::OutChannels::new(params.metrics_registry.as_ref())?, peers_notifications_sinks, tx_handler_controller, @@ -1464,8 +1446,6 @@ pub struct NetworkWorker { import_queue: Box>, /// Messages from the [`NetworkService`] that must be processed. from_service: TracingUnboundedReceiver>, - /// Receiver for queries from the light client that must be processed. - light_client_rqs: Option>>, /// Senders for events that happen on the network. event_streams: out_events::OutChannels, /// Prometheus network metrics. @@ -1489,23 +1469,6 @@ impl Future for NetworkWorker { this.import_queue .poll_actions(cx, &mut NetworkLink { protocol: &mut this.network_service }); - // Check for new incoming light client requests. - if let Some(light_client_rqs) = this.light_client_rqs.as_mut() { - while let Poll::Ready(Some(rq)) = light_client_rqs.poll_next_unpin(cx) { - let result = this.network_service.behaviour_mut().light_client_request(rq); - match result { - Ok(()) => {}, - Err(light_client_requests::sender::SendRequestError::TooManyRequests) => { - warn!("Couldn't start light client request: too many pending requests"); - }, - } - - if let Some(metrics) = this.metrics.as_ref() { - metrics.issued_light_requests.inc(); - } - } - } - // At the time of writing of this comment, due to a high volume of messages, the network // worker sometimes takes a long time to process the loop below. When that happens, the // rest of the polling is frozen. In order to avoid negative side-effects caused by this diff --git a/client/network/src/service/tests.rs b/client/network/src/service/tests.rs index 69b172d07edf..1c66986e422f 100644 --- a/client/network/src/service/tests.rs +++ b/client/network/src/service/tests.rs @@ -116,7 +116,6 @@ fn build_test_full_node( }), network_config: config, chain: client.clone(), - on_demand: None, transaction_pool: Arc::new(crate::config::EmptyTransactionPool), protocol_id, import_queue, diff --git a/client/network/test/src/lib.rs b/client/network/test/src/lib.rs index 084b09fd65f8..cfd42327b600 100644 --- a/client/network/test/src/lib.rs +++ b/client/network/test/src/lib.rs @@ -48,13 +48,13 @@ use sc_consensus::{ }; pub use sc_network::config::EmptyTransactionPool; use sc_network::{ - block_request_handler::{self, BlockRequestHandler}, + block_request_handler::BlockRequestHandler, config::{ MultiaddrWithPeerId, NetworkConfiguration, NonDefaultSetConfig, NonReservedPeerMode, ProtocolConfig, ProtocolId, Role, SyncMode, TransportConfig, }, - light_client_requests::{self, handler::LightClientRequestHandler}, - state_request_handler::{self, StateRequestHandler}, + light_client_requests::handler::LightClientRequestHandler, + state_request_handler::StateRequestHandler, warp_request_handler, Multiaddr, NetworkService, NetworkWorker, }; use sc_service::client::Client; @@ -133,25 +133,20 @@ pub type PeersFullClient = Client< Block, substrate_test_runtime_client::runtime::RuntimeApi, >; -pub type PeersLightClient = Client< - substrate_test_runtime_client::LightBackend, - substrate_test_runtime_client::LightExecutor, - Block, - substrate_test_runtime_client::runtime::RuntimeApi, ->; #[derive(Clone)] -pub enum PeersClient { - Full(Arc, Arc), - Light(Arc, Arc), +pub struct PeersClient { + client: Arc, + backend: Arc, } impl PeersClient { - pub fn as_full(&self) -> Option> { - match *self { - PeersClient::Full(ref client, _) => Some(client.clone()), - _ => None, - } + pub fn as_client(&self) -> Arc { + self.client.clone() + } + + pub fn as_backend(&self) -> Arc { + self.backend.clone() } pub fn as_block_import(&self) -> BlockImportAdapter { @@ -159,27 +154,18 @@ impl PeersClient { } pub fn get_aux(&self, key: &[u8]) -> ClientResult>> { - match *self { - PeersClient::Full(ref client, _) => client.get_aux(key), - PeersClient::Light(ref client, _) => client.get_aux(key), - } + self.client.get_aux(key) } pub fn info(&self) -> BlockchainInfo { - match *self { - PeersClient::Full(ref client, _) => client.chain_info(), - PeersClient::Light(ref client, _) => client.chain_info(), - } + self.client.info() } pub fn header( &self, block: &BlockId, ) -> ClientResult::Header>> { - match *self { - PeersClient::Full(ref client, _) => client.header(block), - PeersClient::Light(ref client, _) => client.header(block), - } + self.client.header(block) } pub fn has_state_at(&self, block: &BlockId) -> bool { @@ -187,33 +173,19 @@ impl PeersClient { Some(header) => header, None => return false, }; - match self { - PeersClient::Full(_client, backend) => - backend.have_state_at(&header.hash(), *header.number()), - PeersClient::Light(_client, backend) => - backend.have_state_at(&header.hash(), *header.number()), - } + self.backend.have_state_at(&header.hash(), *header.number()) } pub fn justifications(&self, block: &BlockId) -> ClientResult> { - match *self { - PeersClient::Full(ref client, _) => client.justifications(block), - PeersClient::Light(ref client, _) => client.justifications(block), - } + self.client.justifications(block) } pub fn finality_notification_stream(&self) -> FinalityNotifications { - match *self { - PeersClient::Full(ref client, _) => client.finality_notification_stream(), - PeersClient::Light(ref client, _) => client.finality_notification_stream(), - } + self.client.finality_notification_stream() } pub fn import_notification_stream(&self) -> ImportNotifications { - match *self { - PeersClient::Full(ref client, _) => client.import_notification_stream(), - PeersClient::Light(ref client, _) => client.import_notification_stream(), - } + self.client.import_notification_stream() } pub fn finalize_block( @@ -222,12 +194,7 @@ impl PeersClient { justification: Option, notify: bool, ) -> ClientResult<()> { - match *self { - PeersClient::Full(ref client, ref _backend) => - client.finalize_block(id, justification, notify), - PeersClient::Light(ref client, ref _backend) => - client.finalize_block(id, justification, notify), - } + self.client.finalize_block(id, justification, notify) } } @@ -240,10 +207,7 @@ impl BlockImport for PeersClient { &mut self, block: BlockCheckParams, ) -> Result { - match self { - PeersClient::Full(client, _) => client.check_block(block).await, - PeersClient::Light(client, _) => client.check_block(block).await, - } + self.client.check_block(block).await } async fn import_block( @@ -251,12 +215,7 @@ impl BlockImport for PeersClient { block: BlockImportParams, cache: HashMap>, ) -> Result { - match self { - PeersClient::Full(client, _) => - client.import_block(block.clear_storage_changes_and_mutate(), cache).await, - PeersClient::Light(client, _) => - client.import_block(block.clear_storage_changes_and_mutate(), cache).await, - } + self.client.import_block(block.clear_storage_changes_and_mutate(), cache).await } } @@ -370,8 +329,7 @@ where BlockBuilder, ) -> Block, { - let full_client = - self.client.as_full().expect("blocks could only be generated by full clients"); + let full_client = self.client.as_client(); let mut at = full_client.header(&at).unwrap().unwrap().hash(); for _ in 0..count { let builder = @@ -779,11 +737,11 @@ where let (c, longest_chain) = test_client_builder.build_with_longest_chain(); let client = Arc::new(c); - let (block_import, justification_import, data) = - self.make_block_import(PeersClient::Full(client.clone(), backend.clone())); + let (block_import, justification_import, data) = self + .make_block_import(PeersClient { client: client.clone(), backend: backend.clone() }); let verifier = self.make_verifier( - PeersClient::Full(client.clone(), backend.clone()), + PeersClient { client: client.clone(), backend: backend.clone() }, &Default::default(), &data, ); @@ -868,7 +826,6 @@ where }), network_config, chain: client.clone(), - on_demand: None, transaction_pool: Arc::new(EmptyTransactionPool), protocol_id, import_queue, @@ -899,7 +856,7 @@ where peers.push(Peer { data, - client: PeersClient::Full(client.clone(), backend.clone()), + client: PeersClient { client: client.clone(), backend: backend.clone() }, select_chain: Some(longest_chain), backend: Some(backend), imported_blocks_stream, @@ -912,94 +869,6 @@ where }); } - /// Add a light peer. - fn add_light_peer(&mut self) { - let (c, backend) = substrate_test_runtime_client::new_light(); - let client = Arc::new(c); - let (block_import, justification_import, data) = - self.make_block_import(PeersClient::Light(client.clone(), backend.clone())); - - let verifier = self.make_verifier( - PeersClient::Light(client.clone(), backend.clone()), - &Default::default(), - &data, - ); - let verifier = VerifierAdapter::new(verifier); - - let import_queue = Box::new(BasicQueue::new( - verifier.clone(), - Box::new(block_import.clone()), - justification_import, - &sp_core::testing::TaskExecutor::new(), - None, - )); - - let listen_addr = build_multiaddr![Memory(rand::random::())]; - - let mut network_config = - NetworkConfiguration::new("test-node", "test-client", Default::default(), None); - network_config.transport = TransportConfig::MemoryOnly; - network_config.listen_addresses = vec![listen_addr.clone()]; - network_config.allow_non_globals_in_dht = true; - - let protocol_id = ProtocolId::from("test-protocol-name"); - - let block_request_protocol_config = - block_request_handler::generate_protocol_config(&protocol_id); - let state_request_protocol_config = - state_request_handler::generate_protocol_config(&protocol_id); - - let light_client_request_protocol_config = - light_client_requests::generate_protocol_config(&protocol_id); - - let network = NetworkWorker::new(sc_network::config::Params { - role: Role::Light, - executor: None, - transactions_handler_executor: Box::new(|task| { - async_std::task::spawn(task); - }), - network_config, - chain: client.clone(), - on_demand: None, - transaction_pool: Arc::new(EmptyTransactionPool), - protocol_id, - import_queue, - block_announce_validator: Box::new(DefaultBlockAnnounceValidator), - metrics_registry: None, - block_request_protocol_config, - state_request_protocol_config, - light_client_request_protocol_config, - warp_sync: None, - }) - .unwrap(); - - self.mut_peers(|peers| { - for peer in peers.iter_mut() { - peer.network.add_known_address( - network.service().local_peer_id().clone(), - listen_addr.clone(), - ); - } - - let imported_blocks_stream = Box::pin(client.import_notification_stream().fuse()); - let finality_notification_stream = - Box::pin(client.finality_notification_stream().fuse()); - - peers.push(Peer { - data, - verifier, - select_chain: None, - backend: None, - block_import, - client: PeersClient::Light(client, backend), - imported_blocks_stream, - finality_notification_stream, - network, - listen_addr, - }); - }); - } - /// Used to spawn background tasks, e.g. the block request protocol handler. fn spawn_task(&self, f: BoxFuture<'static, ()>) { async_std::task::spawn(f); diff --git a/client/network/test/src/sync.rs b/client/network/test/src/sync.rs index ff62b5476d1e..4828cae84221 100644 --- a/client/network/test/src/sync.rs +++ b/client/network/test/src/sync.rs @@ -20,7 +20,6 @@ use super::*; use futures::{executor::block_on, Future}; use sp_consensus::{block_validation::Validation, BlockOrigin}; use sp_runtime::Justifications; -use std::time::Duration; use substrate_test_runtime::Header; fn test_ancestor_search_when_common_is(n: usize) { @@ -391,35 +390,6 @@ fn own_blocks_are_announced() { (net.peers()[2].blockchain_canon_equals(peer0)); } -#[test] -fn blocks_are_not_announced_by_light_nodes() { - sp_tracing::try_init_simple(); - let mut net = TestNet::new(0); - - // full peer0 is connected to light peer - // light peer1 is connected to full peer2 - net.add_full_peer(); - net.add_light_peer(); - - // Sync between 0 and 1. - net.peer(0).push_blocks(1, false); - assert_eq!(net.peer(0).client.info().best_number, 1); - net.block_until_sync(); - assert_eq!(net.peer(1).client.info().best_number, 1); - - // Add another node and remove node 0. - net.add_full_peer(); - net.peers.remove(0); - - // Poll for a few seconds and make sure 1 and 2 (now 0 and 1) don't sync together. - let mut delay = futures_timer::Delay::new(Duration::from_secs(5)); - block_on(futures::future::poll_fn::<(), _>(|cx| { - net.poll(cx); - Pin::new(&mut delay).poll(cx) - })); - assert_eq!(net.peer(1).client.info().best_number, 0); -} - #[test] fn can_sync_small_non_best_forks() { sp_tracing::try_init_simple(); @@ -483,72 +453,6 @@ fn can_sync_small_non_best_forks() { })); } -#[test] -fn can_not_sync_from_light_peer() { - sp_tracing::try_init_simple(); - - // given the network with 1 full nodes (#0) and 1 light node (#1) - let mut net = TestNet::new(1); - net.add_light_peer(); - - // generate some blocks on #0 - net.peer(0).push_blocks(1, false); - - // and let the light client sync from this node - net.block_until_sync(); - - // ensure #0 && #1 have the same best block - let full0_info = net.peer(0).client.info(); - let light_info = net.peer(1).client.info(); - assert_eq!(full0_info.best_number, 1); - assert_eq!(light_info.best_number, 1); - assert_eq!(light_info.best_hash, full0_info.best_hash); - - // add new full client (#2) && remove #0 - net.add_full_peer(); - net.peers.remove(0); - - // ensure that the #2 (now #1) fails to sync block #1 even after 5 seconds - let mut test_finished = futures_timer::Delay::new(Duration::from_secs(5)); - block_on(futures::future::poll_fn::<(), _>(|cx| { - net.poll(cx); - Pin::new(&mut test_finished).poll(cx) - })); -} - -#[test] -fn light_peer_imports_header_from_announce() { - sp_tracing::try_init_simple(); - - fn import_with_announce(net: &mut TestNet, hash: H256) { - net.peer(0).announce_block(hash, None); - - block_on(futures::future::poll_fn::<(), _>(|cx| { - net.poll(cx); - if net.peer(1).client().header(&BlockId::Hash(hash)).unwrap().is_some() { - Poll::Ready(()) - } else { - Poll::Pending - } - })); - } - - // given the network with 1 full nodes (#0) and 1 light node (#1) - let mut net = TestNet::new(1); - net.add_light_peer(); - - // let them connect to each other - net.block_until_sync(); - - // check that NEW block is imported from announce message - let new_hash = net.peer(0).push_blocks(1, false); - import_with_announce(&mut net, new_hash); - - // check that KNOWN STALE block is imported from announce message - let known_stale_hash = net.peer(0).push_blocks_at(BlockId::Number(0), 1, true); - import_with_announce(&mut net, known_stale_hash); -} - #[test] fn can_sync_explicit_forks() { sp_tracing::try_init_simple(); @@ -1210,16 +1114,14 @@ fn syncs_indexed_blocks() { assert!(net .peer(0) .client() - .as_full() - .unwrap() + .as_client() .indexed_transaction(&indexed_key) .unwrap() .is_some()); assert!(net .peer(1) .client() - .as_full() - .unwrap() + .as_client() .indexed_transaction(&indexed_key) .unwrap() .is_none()); @@ -1228,8 +1130,7 @@ fn syncs_indexed_blocks() { assert!(net .peer(1) .client() - .as_full() - .unwrap() + .as_client() .indexed_transaction(&indexed_key) .unwrap() .is_some()); diff --git a/client/rpc/src/chain/chain_light.rs b/client/rpc/src/chain/chain_light.rs deleted file mode 100644 index 2d15c819e1da..000000000000 --- a/client/rpc/src/chain/chain_light.rs +++ /dev/null @@ -1,114 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2019-2021 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 . - -//! Blockchain API backend for light nodes. - -use futures::{future::ready, FutureExt, TryFutureExt}; -use jsonrpc_pubsub::manager::SubscriptionManager; -use std::sync::Arc; - -use sc_client_api::light::{Fetcher, RemoteBlockchain, RemoteBodyRequest}; -use sp_runtime::{ - generic::{BlockId, SignedBlock}, - traits::Block as BlockT, -}; - -use super::{client_err, error::FutureResult, ChainBackend}; -use sc_client_api::BlockchainEvents; -use sp_blockchain::HeaderBackend; - -/// Blockchain API backend for light nodes. Reads all the data from local -/// database, if available, or fetches it from remote node otherwise. -pub struct LightChain { - /// Substrate client. - client: Arc, - /// Current subscriptions. - subscriptions: SubscriptionManager, - /// Remote blockchain reference - remote_blockchain: Arc>, - /// Remote fetcher reference. - fetcher: Arc, -} - -impl> LightChain { - /// Create new Chain API RPC handler. - pub fn new( - client: Arc, - subscriptions: SubscriptionManager, - remote_blockchain: Arc>, - fetcher: Arc, - ) -> Self { - Self { client, subscriptions, remote_blockchain, fetcher } - } -} - -impl ChainBackend for LightChain -where - Block: BlockT + 'static, - Block::Header: Unpin, - Client: BlockchainEvents + HeaderBackend + Send + Sync + 'static, - F: Fetcher + Send + Sync + 'static, -{ - fn client(&self) -> &Arc { - &self.client - } - - fn subscriptions(&self) -> &SubscriptionManager { - &self.subscriptions - } - - fn header(&self, hash: Option) -> FutureResult> { - let hash = self.unwrap_or_best(hash); - - let fetcher = self.fetcher.clone(); - let maybe_header = sc_client_api::light::future_header( - &*self.remote_blockchain, - &*fetcher, - BlockId::Hash(hash), - ); - - maybe_header.then(move |result| ready(result.map_err(client_err))).boxed() - } - - fn block(&self, hash: Option) -> FutureResult>> { - let fetcher = self.fetcher.clone(); - self.header(hash) - .and_then(move |header| async move { - match header { - Some(header) => { - let body = fetcher - .remote_body(RemoteBodyRequest { - header: header.clone(), - retry_count: Default::default(), - }) - .await; - - body.map(|body| { - Some(SignedBlock { - block: Block::new(header, body), - justifications: None, - }) - }) - .map_err(client_err) - }, - None => Ok(None), - } - }) - .boxed() - } -} diff --git a/client/rpc/src/chain/mod.rs b/client/rpc/src/chain/mod.rs index 9428ac3248f3..c2f512c338b1 100644 --- a/client/rpc/src/chain/mod.rs +++ b/client/rpc/src/chain/mod.rs @@ -19,7 +19,6 @@ //! Substrate blockchain API. mod chain_full; -mod chain_light; #[cfg(test)] mod tests; @@ -33,10 +32,7 @@ use rpc::{ use std::sync::Arc; use jsonrpc_pubsub::{manager::SubscriptionManager, typed::Subscriber, SubscriptionId}; -use sc_client_api::{ - light::{Fetcher, RemoteBlockchain}, - BlockchainEvents, -}; +use sc_client_api::BlockchainEvents; use sp_rpc::{list::ListOrValue, number::NumberOrHex}; use sp_runtime::{ generic::{BlockId, SignedBlock}, @@ -204,29 +200,6 @@ where Chain { backend: Box::new(self::chain_full::FullChain::new(client, subscriptions)) } } -/// Create new state API that works on light node. -pub fn new_light>( - client: Arc, - subscriptions: SubscriptionManager, - remote_blockchain: Arc>, - fetcher: Arc, -) -> Chain -where - Block: BlockT + 'static, - Block::Header: Unpin, - Client: BlockBackend + HeaderBackend + BlockchainEvents + 'static, - F: Send + Sync + 'static, -{ - Chain { - backend: Box::new(self::chain_light::LightChain::new( - client, - subscriptions, - remote_blockchain, - fetcher, - )), - } -} - /// Chain API with subscriptions support. pub struct Chain { backend: Box>, diff --git a/client/rpc/src/state/state_full.rs b/client/rpc/src/state/state_full.rs index 97f77a407796..d3b41d2f1827 100644 --- a/client/rpc/src/state/state_full.rs +++ b/client/rpc/src/state/state_full.rs @@ -26,11 +26,7 @@ use futures::{ use jsonrpc_pubsub::{manager::SubscriptionManager, typed::Subscriber, SubscriptionId}; use log::warn; use rpc::Result as RpcResult; -use std::{ - collections::{BTreeMap, HashMap}, - ops::Range, - sync::Arc, -}; +use std::{collections::HashMap, sync::Arc}; use sc_rpc_api::state::ReadProof; use sp_blockchain::{ @@ -43,10 +39,7 @@ use sp_core::{ }, Bytes, }; -use sp_runtime::{ - generic::BlockId, - traits::{Block as BlockT, CheckedSub, NumberFor, SaturatedConversion}, -}; +use sp_runtime::{generic::BlockId, traits::Block as BlockT}; use sp_version::RuntimeVersion; use sp_api::{CallApiAt, Metadata, ProvideRuntimeApi}; @@ -66,14 +59,6 @@ use std::marker::PhantomData; struct QueryStorageRange { /// Hashes of all the blocks in the range. pub hashes: Vec, - /// Number of the first block in the range. - pub first_number: NumberFor, - /// Blocks subrange ([begin; end) indices within `hashes`) where we should read keys at - /// each state to get changes. - pub unfiltered_range: Range, - /// Blocks subrange ([begin; end) indices within `hashes`) where we could pre-filter - /// blocks-with-changes by using changes tries. - pub filtered_range: Option>, } /// State API backend for full nodes. @@ -107,10 +92,8 @@ where Ok(hash.unwrap_or_else(|| self.client.info().best_hash)) } - /// Splits the `query_storage` block range into 'filtered' and 'unfiltered' subranges. - /// Blocks that contain changes within filtered subrange could be filtered using changes tries. - /// Blocks that contain changes within unfiltered subrange must be filtered manually. - fn split_query_storage_range( + /// Validates block range. + fn query_storage_range( &self, from: Block::Hash, to: Option, @@ -156,23 +139,7 @@ where hashes }; - // check if we can filter blocks-with-changes from some (sub)range using changes tries - let changes_trie_range = self - .client - .max_key_changes_range(from_number, BlockId::Hash(to_meta.hash)) - .map_err(client_err)?; - let filtered_range_begin = changes_trie_range.and_then(|(begin, _)| { - // avoids a corner case where begin < from_number (happens when querying genesis) - begin.checked_sub(&from_number).map(|x| x.saturated_into::()) - }); - let (unfiltered_range, filtered_range) = split_range(hashes.len(), filtered_range_begin); - - Ok(QueryStorageRange { - hashes, - first_number: from_number, - unfiltered_range, - filtered_range, - }) + Ok(QueryStorageRange { hashes }) } /// Iterates through range.unfiltered_range and check each block for changes of keys' values. @@ -183,8 +150,8 @@ where last_values: &mut HashMap>, changes: &mut Vec>, ) -> Result<()> { - for block in range.unfiltered_range.start..range.unfiltered_range.end { - let block_hash = range.hashes[block].clone(); + for block_hash in &range.hashes { + let block_hash = block_hash.clone(); let mut block_changes = StorageChangeSet { block: block_hash.clone(), changes: Vec::new() }; let id = BlockId::hash(block_hash); @@ -207,57 +174,6 @@ where } Ok(()) } - - /// Iterates through all blocks that are changing keys within range.filtered_range and collects - /// these changes. - fn query_storage_filtered( - &self, - range: &QueryStorageRange, - keys: &[StorageKey], - last_values: &HashMap>, - changes: &mut Vec>, - ) -> Result<()> { - let (begin, end) = match range.filtered_range { - Some(ref filtered_range) => ( - range.first_number + filtered_range.start.saturated_into(), - BlockId::Hash(range.hashes[filtered_range.end - 1].clone()), - ), - None => return Ok(()), - }; - let mut changes_map: BTreeMap, StorageChangeSet> = - BTreeMap::new(); - for key in keys { - let mut last_block = None; - let mut last_value = last_values.get(key).cloned().unwrap_or_default(); - let key_changes = self.client.key_changes(begin, end, None, key).map_err(client_err)?; - for (block, _) in key_changes.into_iter().rev() { - if last_block == Some(block) { - continue - } - - let block_hash = - range.hashes[(block - range.first_number).saturated_into::()].clone(); - let id = BlockId::Hash(block_hash); - let value_at_block = self.client.storage(&id, key).map_err(client_err)?; - if last_value == value_at_block { - continue - } - - changes_map - .entry(block) - .or_insert_with(|| StorageChangeSet { block: block_hash, changes: Vec::new() }) - .changes - .push((key.clone(), value_at_block.clone())); - last_block = Some(block); - last_value = value_at_block; - } - } - if let Some(additional_capacity) = changes_map.len().checked_sub(changes.len()) { - changes.reserve(additional_capacity); - } - changes.extend(changes_map.into_iter().map(|(_, cs)| cs)); - Ok(()) - } } impl StateBackend for FullState @@ -430,11 +346,10 @@ where keys: Vec, ) -> FutureResult>> { let call_fn = move || { - let range = self.split_query_storage_range(from, to)?; + let range = self.query_storage_range(from, to)?; let mut changes = Vec::new(); let mut last_values = HashMap::new(); self.query_storage_unfiltered(&range, &keys, &mut last_values, &mut changes)?; - self.query_storage_filtered(&range, &keys, &last_values, &mut changes)?; Ok(changes) }; @@ -768,30 +683,6 @@ where } } -/// Splits passed range into two subranges where: -/// - first range has at least one element in it; -/// - second range (optionally) starts at given `middle` element. -pub(crate) fn split_range( - size: usize, - middle: Option, -) -> (Range, Option>) { - // check if we can filter blocks-with-changes from some (sub)range using changes tries - let range2_begin = match middle { - // some of required changes tries are pruned => use available tries - Some(middle) if middle != 0 => Some(middle), - // all required changes tries are available, but we still want values at first block - // => do 'unfiltered' read for the first block and 'filtered' for the rest - Some(_) if size > 1 => Some(1), - // range contains single element => do not use changes tries - Some(_) => None, - // changes tries are not available => do 'unfiltered' read for the whole range - None => None, - }; - let range1 = 0..range2_begin.unwrap_or(size); - let range2 = range2_begin.map(|begin| begin..size); - (range1, range2) -} - fn invalid_block_range( from: &CachedHeaderMetadata, to: &CachedHeaderMetadata, diff --git a/client/rpc/src/state/tests.rs b/client/rpc/src/state/tests.rs index 712fe00c5438..d360701c88b2 100644 --- a/client/rpc/src/state/tests.rs +++ b/client/rpc/src/state/tests.rs @@ -17,16 +17,15 @@ // along with this program. If not, see . use self::error::Error; -use super::{state_full::split_range, *}; +use super::*; use crate::testing::TaskExecutor; use assert_matches::assert_matches; use futures::{executor, StreamExt}; use sc_block_builder::BlockBuilderProvider; use sc_rpc_api::DenyUnsafe; use sp_consensus::BlockOrigin; -use sp_core::{hash::H256, storage::ChildInfo, ChangesTrieConfiguration}; +use sp_core::{hash::H256, storage::ChildInfo}; use sp_io::hashing::blake2_256; -use sp_runtime::generic::BlockId; use std::sync::Arc; use substrate_test_runtime_client::{prelude::*, runtime}; @@ -336,7 +335,7 @@ fn should_send_initial_storage_changes_and_notifications() { #[test] fn should_query_storage() { - fn run_tests(mut client: Arc, has_changes_trie_config: bool) { + fn run_tests(mut client: Arc) { let (api, _child) = new_full( client.clone(), SubscriptionManager::new(Arc::new(TaskExecutor)), @@ -369,13 +368,6 @@ fn should_query_storage() { let block2_hash = add_block(1); let genesis_hash = client.genesis_hash(); - if has_changes_trie_config { - assert_eq!( - client.max_key_changes_range(1, BlockId::Hash(block1_hash)).unwrap(), - Some((0, BlockId::Hash(block1_hash))), - ); - } - let mut expected = vec![ StorageChangeSet { block: genesis_hash, @@ -519,24 +511,8 @@ fn should_query_storage() { ); } - run_tests(Arc::new(substrate_test_runtime_client::new()), false); - run_tests( - Arc::new( - TestClientBuilder::new() - .changes_trie_config(Some(ChangesTrieConfiguration::new(4, 2))) - .build(), - ), - true, - ); -} - -#[test] -fn should_split_ranges() { - assert_eq!(split_range(1, None), (0..1, None)); - assert_eq!(split_range(100, None), (0..100, None)); - assert_eq!(split_range(1, Some(0)), (0..1, None)); - assert_eq!(split_range(100, Some(50)), (0..50, Some(50..100))); - assert_eq!(split_range(100, Some(99)), (0..99, Some(99..100))); + run_tests(Arc::new(substrate_test_runtime_client::new())); + run_tests(Arc::new(TestClientBuilder::new().build())); } #[test] diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index 88ba6282b5f4..718cfce981f1 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -30,9 +30,8 @@ use log::info; use prometheus_endpoint::Registry; use sc_chain_spec::get_extension; use sc_client_api::{ - execution_extensions::ExecutionExtensions, light::RemoteBlockchain, - proof_provider::ProofProvider, BadBlocks, BlockBackend, BlockchainEvents, ExecutorProvider, - ForkBlocks, StorageProvider, UsageProvider, + execution_extensions::ExecutionExtensions, proof_provider::ProofProvider, BadBlocks, + BlockBackend, BlockchainEvents, ExecutorProvider, ForkBlocks, StorageProvider, UsageProvider, }; use sc_client_db::{Backend, DatabaseSettings}; use sc_consensus::import_queue::ImportQueue; @@ -40,7 +39,7 @@ use sc_executor::RuntimeVersionOf; use sc_keystore::LocalKeystore; use sc_network::{ block_request_handler::{self, BlockRequestHandler}, - config::{OnDemand, Role, SyncMode}, + config::{Role, SyncMode}, light_client_requests::{self, handler::LightClientRequestHandler}, state_request_handler::{self, StateRequestHandler}, warp_request_handler::{self, RequestHandler as WarpSyncRequestHandler, WarpSyncProvider}, @@ -381,23 +380,19 @@ where pub struct SpawnTasksParams<'a, TBl: BlockT, TCl, TExPool, TRpc, Backend> { /// The service configuration. pub config: Configuration, - /// A shared client returned by `new_full_parts`/`new_light_parts`. + /// A shared client returned by `new_full_parts`. pub client: Arc, - /// A shared backend returned by `new_full_parts`/`new_light_parts`. + /// A shared backend returned by `new_full_parts`. pub backend: Arc, - /// A task manager returned by `new_full_parts`/`new_light_parts`. + /// A task manager returned by `new_full_parts`. pub task_manager: &'a mut TaskManager, - /// A shared keystore returned by `new_full_parts`/`new_light_parts`. + /// A shared keystore returned by `new_full_parts`. pub keystore: SyncCryptoStorePtr, - /// An optional, shared data fetcher for light clients. - pub on_demand: Option>>, /// A shared transaction pool. pub transaction_pool: Arc, /// A RPC extension builder. Use `NoopRpcExtensionBuilder` if you just want to pass in the /// extensions directly. pub rpc_extensions_builder: Box + Send>, - /// An optional, shared remote blockchain instance. Used for light clients. - pub remote_blockchain: Option>>, /// A shared network instance. pub network: Arc::Hash>>, /// A Sender for RPC requests. @@ -475,12 +470,10 @@ where mut config, task_manager, client, - on_demand: _, backend, keystore, transaction_pool, rpc_extensions_builder, - remote_blockchain: _, network, system_rpc_tx, telemetry, @@ -725,7 +718,7 @@ where pub struct BuildNetworkParams<'a, TBl: BlockT, TExPool, TImpQu, TCl> { /// The service configuration. pub config: &'a Configuration, - /// A shared client returned by `new_full_parts`/`new_light_parts`. + /// A shared client returned by `new_full_parts`. pub client: Arc, /// A shared transaction pool. pub transaction_pool: Arc, @@ -733,8 +726,6 @@ pub struct BuildNetworkParams<'a, TBl: BlockT, TExPool, TImpQu, TCl> { pub spawn_handle: SpawnTaskHandle, /// An import queue. pub import_queue: TImpQu, - /// An optional, shared data fetcher for light clients. - pub on_demand: Option>>, /// A block announce validator builder. pub block_announce_validator_builder: Option) -> Box + Send> + Send>>, @@ -773,7 +764,6 @@ where transaction_pool, spawn_handle, import_queue, - on_demand, block_announce_validator_builder, warp_sync, } = params; @@ -869,7 +859,6 @@ where }, network_config: config.network.clone(), chain: client.clone(), - on_demand, transaction_pool: transaction_pool_adapter as _, import_queue: Box::new(import_queue), protocol_id, diff --git a/client/service/src/client/call_executor.rs b/client/service/src/client/call_executor.rs index d7a8b6f227e8..be871cc371ed 100644 --- a/client/service/src/client/call_executor.rs +++ b/client/service/src/client/call_executor.rs @@ -26,10 +26,7 @@ use sp_core::{ NativeOrEncoded, NeverNativeValue, }; use sp_externalities::Extensions; -use sp_runtime::{ - generic::BlockId, - traits::{Block as BlockT, NumberFor}, -}; +use sp_runtime::{generic::BlockId, traits::Block as BlockT}; use sp_state_machine::{ self, backend::Backend as _, ExecutionManager, ExecutionStrategy, Ext, OverlayedChanges, StateMachine, StorageProof, @@ -153,8 +150,6 @@ where extensions: Option, ) -> sp_blockchain::Result> { let mut changes = OverlayedChanges::default(); - let changes_trie = - backend::changes_tries_state_at_block(at, self.backend.changes_trie_storage())?; let state = self.backend.state_at(*at)?; let state_runtime_code = sp_state_machine::backend::BackendRuntimeCode::new(&state); let runtime_code = @@ -168,7 +163,6 @@ where let return_data = StateMachine::new( &state, - changes_trie, &mut changes, &self.executor, method, @@ -208,8 +202,6 @@ where where ExecutionManager: Clone, { - let changes_trie_state = - backend::changes_tries_state_at_block(at, self.backend.changes_trie_storage())?; let mut storage_transaction_cache = storage_transaction_cache.map(|c| c.borrow_mut()); let state = self.backend.state_at(*at)?; @@ -243,7 +235,6 @@ where let mut state_machine = StateMachine::new( &backend, - changes_trie_state, changes, &self.executor, method, @@ -262,7 +253,6 @@ where None => { let mut state_machine = StateMachine::new( &state, - changes_trie_state, changes, &self.executor, method, @@ -286,11 +276,9 @@ where fn runtime_version(&self, id: &BlockId) -> sp_blockchain::Result { let mut overlay = OverlayedChanges::default(); - let changes_trie_state = - backend::changes_tries_state_at_block(id, self.backend.changes_trie_storage())?; let state = self.backend.state_at(*id)?; let mut cache = StorageTransactionCache::::default(); - let mut ext = Ext::new(&mut overlay, &mut cache, &state, changes_trie_state, None); + let mut ext = Ext::new(&mut overlay, &mut cache, &state, None); let state_runtime_code = sp_state_machine::backend::BackendRuntimeCode::new(&state); let runtime_code = state_runtime_code.runtime_code().map_err(sp_blockchain::Error::RuntimeCode)?; @@ -317,7 +305,7 @@ where state_runtime_code.runtime_code().map_err(sp_blockchain::Error::RuntimeCode)?; let runtime_code = self.check_override(runtime_code, at)?; - sp_state_machine::prove_execution_on_trie_backend::<_, _, NumberFor, _, _>( + sp_state_machine::prove_execution_on_trie_backend( &trie_backend, &mut Default::default(), &self.executor, diff --git a/client/service/src/client/client.rs b/client/service/src/client/client.rs index 6ce2feb05075..b46c6b99b9a9 100644 --- a/client/service/src/client/client.rs +++ b/client/service/src/client/client.rs @@ -23,7 +23,6 @@ use super::{ genesis, }; use codec::{Decode, Encode}; -use hash_db::Prefix; use log::{info, trace, warn}; use parking_lot::{Mutex, RwLock}; use prometheus_endpoint::Registry; @@ -31,18 +30,15 @@ use rand::Rng; use sc_block_builder::{BlockBuilderApi, BlockBuilderProvider, RecordProof}; use sc_client_api::{ backend::{ - self, apply_aux, changes_tries_state_at_block, BlockImportOperation, ClientImportOperation, - Finalizer, ImportSummary, LockImportRun, NewBlockState, PrunableStateChangesTrieStorage, - StorageProvider, + self, apply_aux, BlockImportOperation, ClientImportOperation, Finalizer, ImportSummary, + LockImportRun, NewBlockState, StorageProvider, }, - cht, client::{ BadBlocks, BlockBackend, BlockImportNotification, BlockOf, BlockchainEvents, ClientInfo, FinalityNotification, FinalityNotifications, ForkBlocks, ImportNotifications, ProvideUncles, }, execution_extensions::ExecutionExtensions, - light::ChangesProof, notifications::{StorageEventStream, StorageNotifications}, CallExecutor, ExecutorProvider, KeyIterator, ProofProvider, UsageProvider, }; @@ -56,39 +52,36 @@ use sp_api::{ ProvideRuntimeApi, }; use sp_blockchain::{ - self as blockchain, well_known_cache_keys::Id as CacheKeyId, Backend as ChainBackend, Cache, - CachedHeaderMetadata, Error, HeaderBackend as ChainHeaderBackend, HeaderMetadata, ProvideCache, + self as blockchain, well_known_cache_keys::Id as CacheKeyId, Backend as ChainBackend, + CachedHeaderMetadata, Error, HeaderBackend as ChainHeaderBackend, HeaderMetadata, }; use sp_consensus::{BlockOrigin, BlockStatus, Error as ConsensusError}; use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedSender}; use sp_core::{ - convert_hash, storage::{ well_known_keys, ChildInfo, ChildType, PrefixedStorageKey, StorageChild, StorageData, StorageKey, }, - ChangesTrieConfiguration, NativeOrEncoded, + NativeOrEncoded, }; #[cfg(feature = "test-helpers")] use sp_keystore::SyncCryptoStorePtr; use sp_runtime::{ - generic::{BlockId, DigestItem, SignedBlock}, + generic::{BlockId, SignedBlock}, traits::{ - Block as BlockT, DigestFor, HashFor, Header as HeaderT, NumberFor, One, - SaturatedConversion, Zero, + Block as BlockT, HashFor, Header as HeaderT, NumberFor, One, SaturatedConversion, Zero, }, - BuildStorage, Justification, Justifications, + BuildStorage, Digest, Justification, Justifications, }; use sp_state_machine::{ - key_changes, key_changes_proof, prove_child_read, prove_range_read_with_child_with_size, - prove_read, read_range_proof_check_with_child_on_proving_backend, Backend as StateBackend, - ChangesTrieAnchorBlockId, ChangesTrieConfigurationRange, ChangesTrieRootsStorage, - ChangesTrieStorage, DBValue, KeyValueStates, KeyValueStorageLevel, MAX_NESTED_TRIE_DEPTH, + prove_child_read, prove_range_read_with_child_with_size, prove_read, + read_range_proof_check_with_child_on_proving_backend, Backend as StateBackend, KeyValueStates, + KeyValueStorageLevel, MAX_NESTED_TRIE_DEPTH, }; use sp_trie::{CompactProof, StorageProof}; use std::{ - collections::{BTreeMap, HashMap, HashSet}, + collections::{HashMap, HashSet}, marker::PhantomData, panic::UnwindSafe, path::PathBuf, @@ -413,250 +406,6 @@ where self.executor.runtime_version(id) } - /// Reads given header and generates CHT-based header proof for CHT of given size. - pub fn header_proof_with_cht_size( - &self, - id: &BlockId, - cht_size: NumberFor, - ) -> sp_blockchain::Result<(Block::Header, StorageProof)> { - let proof_error = || { - sp_blockchain::Error::Backend(format!("Failed to generate header proof for {:?}", id)) - }; - let header = self.backend.blockchain().expect_header(*id)?; - let block_num = *header.number(); - let cht_num = cht::block_to_cht_number(cht_size, block_num).ok_or_else(proof_error)?; - let cht_start = cht::start_number(cht_size, cht_num); - let mut current_num = cht_start; - let cht_range = ::std::iter::from_fn(|| { - let old_current_num = current_num; - current_num = current_num + One::one(); - Some(old_current_num) - }); - let headers = cht_range.map(|num| self.block_hash(num)); - let proof = cht::build_proof::, _, _>( - cht_size, - cht_num, - std::iter::once(block_num), - headers, - )?; - Ok((header, proof)) - } - - /// Does the same work as `key_changes_proof`, but assumes that CHTs are of passed size. - pub fn key_changes_proof_with_cht_size( - &self, - first: Block::Hash, - last: Block::Hash, - min: Block::Hash, - max: Block::Hash, - storage_key: Option<&PrefixedStorageKey>, - key: &StorageKey, - cht_size: NumberFor, - ) -> sp_blockchain::Result> { - struct AccessedRootsRecorder<'a, Block: BlockT> { - storage: &'a dyn ChangesTrieStorage, NumberFor>, - min: NumberFor, - required_roots_proofs: Mutex, Block::Hash>>, - } - - impl<'a, Block: BlockT> ChangesTrieRootsStorage, NumberFor> - for AccessedRootsRecorder<'a, Block> - { - fn build_anchor( - &self, - hash: Block::Hash, - ) -> Result>, String> { - self.storage.build_anchor(hash) - } - - fn root( - &self, - anchor: &ChangesTrieAnchorBlockId>, - block: NumberFor, - ) -> Result, String> { - let root = self.storage.root(anchor, block)?; - if block < self.min { - if let Some(ref root) = root { - self.required_roots_proofs.lock().insert(block, root.clone()); - } - } - Ok(root) - } - } - - impl<'a, Block: BlockT> ChangesTrieStorage, NumberFor> - for AccessedRootsRecorder<'a, Block> - { - fn as_roots_storage( - &self, - ) -> &dyn sp_state_machine::ChangesTrieRootsStorage, NumberFor> { - self - } - - fn with_cached_changed_keys( - &self, - root: &Block::Hash, - functor: &mut dyn FnMut(&HashMap, HashSet>>), - ) -> bool { - self.storage.with_cached_changed_keys(root, functor) - } - - fn get(&self, key: &Block::Hash, prefix: Prefix) -> Result, String> { - self.storage.get(key, prefix) - } - } - - let first_number = - self.backend.blockchain().expect_block_number_from_id(&BlockId::Hash(first))?; - let (storage, configs) = self.require_changes_trie(first_number, last, true)?; - let min_number = - self.backend.blockchain().expect_block_number_from_id(&BlockId::Hash(min))?; - - let recording_storage = AccessedRootsRecorder:: { - storage: storage.storage(), - min: min_number, - required_roots_proofs: Mutex::new(BTreeMap::new()), - }; - - let max_number = std::cmp::min( - self.backend.blockchain().info().best_number, - self.backend.blockchain().expect_block_number_from_id(&BlockId::Hash(max))?, - ); - - // fetch key changes proof - let mut proof = Vec::new(); - for (config_zero, config_end, config) in configs { - let last_number = - self.backend.blockchain().expect_block_number_from_id(&BlockId::Hash(last))?; - let config_range = ChangesTrieConfigurationRange { - config: &config, - zero: config_zero, - end: config_end.map(|(config_end_number, _)| config_end_number), - }; - let proof_range = key_changes_proof::, _>( - config_range, - &recording_storage, - first_number, - &ChangesTrieAnchorBlockId { hash: convert_hash(&last), number: last_number }, - max_number, - storage_key, - &key.0, - ) - .map_err(|err| sp_blockchain::Error::ChangesTrieAccessFailed(err))?; - proof.extend(proof_range); - } - - // now gather proofs for all changes tries roots that were touched during key_changes_proof - // execution AND are unknown (i.e. replaced with CHT) to the requester - let roots = recording_storage.required_roots_proofs.into_inner(); - let roots_proof = self.changes_trie_roots_proof(cht_size, roots.keys().cloned())?; - - Ok(ChangesProof { - max_block: max_number, - proof, - roots: roots.into_iter().map(|(n, h)| (n, convert_hash(&h))).collect(), - roots_proof, - }) - } - - /// Generate CHT-based proof for roots of changes tries at given blocks. - fn changes_trie_roots_proof>>( - &self, - cht_size: NumberFor, - blocks: I, - ) -> sp_blockchain::Result { - // most probably we have touched several changes tries that are parts of the single CHT - // => GroupBy changes tries by CHT number and then gather proof for the whole group at once - let mut proofs = Vec::new(); - - cht::for_each_cht_group::( - cht_size, - blocks, - |_, cht_num, cht_blocks| { - let cht_proof = - self.changes_trie_roots_proof_at_cht(cht_size, cht_num, cht_blocks)?; - proofs.push(cht_proof); - Ok(()) - }, - (), - )?; - - Ok(StorageProof::merge(proofs)) - } - - /// Generates CHT-based proof for roots of changes tries at given blocks - /// (that are part of single CHT). - fn changes_trie_roots_proof_at_cht( - &self, - cht_size: NumberFor, - cht_num: NumberFor, - blocks: Vec>, - ) -> sp_blockchain::Result { - let cht_start = cht::start_number(cht_size, cht_num); - let mut current_num = cht_start; - let cht_range = ::std::iter::from_fn(|| { - let old_current_num = current_num; - current_num = current_num + One::one(); - Some(old_current_num) - }); - let roots = cht_range.map(|num| { - self.header(&BlockId::Number(num)).map(|block| { - block - .and_then(|block| block.digest().log(DigestItem::as_changes_trie_root).cloned()) - }) - }); - let proof = cht::build_proof::, _, _>( - cht_size, cht_num, blocks, roots, - )?; - Ok(proof) - } - - /// Returns changes trie storage and all configurations that have been active - /// in the range [first; last]. - /// - /// Configurations are returned in descending order (and obviously never overlap). - /// If fail_if_disabled is false, returns maximal consequent configurations ranges, - /// starting from last and stopping on either first, or when CT have been disabled. - /// If fail_if_disabled is true, fails when there's a subrange where CT have been disabled - /// inside first..last blocks range. - fn require_changes_trie( - &self, - first: NumberFor, - last: Block::Hash, - fail_if_disabled: bool, - ) -> sp_blockchain::Result<( - &dyn PrunableStateChangesTrieStorage, - Vec<(NumberFor, Option<(NumberFor, Block::Hash)>, ChangesTrieConfiguration)>, - )> { - let storage = self - .backend - .changes_trie_storage() - .ok_or_else(|| sp_blockchain::Error::ChangesTriesNotSupported)?; - - let mut configs = Vec::with_capacity(1); - let mut current = last; - loop { - let config_range = storage.configuration_at(&BlockId::Hash(current))?; - match config_range.config { - Some(config) => configs.push((config_range.zero.0, config_range.end, config)), - None if !fail_if_disabled => return Ok((storage, configs)), - None => return Err(sp_blockchain::Error::ChangesTriesNotSupported), - } - - if config_range.zero.0 < first { - break - } - - current = *self - .backend - .blockchain() - .expect_header(BlockId::Hash(config_range.zero.1))? - .parent_hash(); - } - - Ok((storage, configs)) - } - /// Apply a checked and validated block to an operation. If a justification is provided /// then `finalized` *must* be true. fn apply_block( @@ -811,7 +560,7 @@ where sc_consensus::StorageChanges::Changes(storage_changes) => { self.backend .begin_state_operation(&mut operation.op, BlockId::Hash(parent_hash))?; - let (main_sc, child_sc, offchain_sc, tx, _, changes_trie_tx, tx_index) = + let (main_sc, child_sc, offchain_sc, tx, _, tx_index) = storage_changes.into_inner(); if self.config.offchain_indexing_api { @@ -822,9 +571,6 @@ where operation.op.update_storage(main_sc.clone(), child_sc.clone())?; operation.op.update_transaction_index(tx_index)?; - if let Some(changes_trie_transaction) = changes_trie_tx { - operation.op.update_changes_trie(changes_trie_transaction)?; - } Some((main_sc, child_sc)) }, sc_consensus::StorageChanges::Import(changes) => { @@ -1003,11 +749,8 @@ where )?; let state = self.backend.state_at(at)?; - let changes_trie_state = - changes_tries_state_at_block(&at, self.backend.changes_trie_storage())?; - let gen_storage_changes = runtime_api - .into_storage_changes(&state, changes_trie_state.as_ref(), *parent_hash) + .into_storage_changes(&state, *parent_hash) .map_err(sp_blockchain::Error::Storage)?; if import_block.header.state_root() != &gen_storage_changes.transaction_storage_root @@ -1356,25 +1099,6 @@ where .map(|(r, p)| (r, StorageProof::merge(vec![p, code_proof]))) } - fn header_proof( - &self, - id: &BlockId, - ) -> sp_blockchain::Result<(Block::Header, StorageProof)> { - self.header_proof_with_cht_size(id, cht::size()) - } - - fn key_changes_proof( - &self, - first: Block::Hash, - last: Block::Hash, - min: Block::Hash, - max: Block::Hash, - storage_key: Option<&PrefixedStorageKey>, - key: &StorageKey, - ) -> sp_blockchain::Result> { - self.key_changes_proof_with_cht_size(first, last, min, max, storage_key, key, cht::size()) - } - fn read_proof_collection( &self, id: &BlockId, @@ -1540,7 +1264,7 @@ where fn new_block_at>( &self, parent: &BlockId, - inherent_digests: DigestFor, + inherent_digests: Digest, record_proof: R, ) -> sp_blockchain::Result> { sc_block_builder::BlockBuilder::new( @@ -1555,7 +1279,7 @@ where fn new_block( &self, - inherent_digests: DigestFor, + inherent_digests: Digest, ) -> sp_blockchain::Result> { let info = self.chain_info(); sc_block_builder::BlockBuilder::new( @@ -1703,89 +1427,6 @@ where .child_storage_hash(child_info, &key.0) .map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))?) } - - fn max_key_changes_range( - &self, - first: NumberFor, - last: BlockId, - ) -> sp_blockchain::Result, BlockId)>> { - let last_number = self.backend.blockchain().expect_block_number_from_id(&last)?; - let last_hash = self.backend.blockchain().expect_block_hash_from_id(&last)?; - if first > last_number { - return Err(sp_blockchain::Error::ChangesTrieAccessFailed( - "Invalid changes trie range".into(), - )) - } - - let (storage, configs) = match self.require_changes_trie(first, last_hash, false).ok() { - Some((storage, configs)) => (storage, configs), - None => return Ok(None), - }; - - let first_available_changes_trie = configs.last().map(|config| config.0); - match first_available_changes_trie { - Some(first_available_changes_trie) => { - let oldest_unpruned = storage.oldest_pruned_digest_range_end(); - let first = std::cmp::max(first_available_changes_trie, oldest_unpruned); - Ok(Some((first, last))) - }, - None => Ok(None), - } - } - - fn key_changes( - &self, - first: NumberFor, - last: BlockId, - storage_key: Option<&PrefixedStorageKey>, - key: &StorageKey, - ) -> sp_blockchain::Result, u32)>> { - let last_number = self.backend.blockchain().expect_block_number_from_id(&last)?; - let last_hash = self.backend.blockchain().expect_block_hash_from_id(&last)?; - let (storage, configs) = self.require_changes_trie(first, last_hash, true)?; - - let mut result = Vec::new(); - let best_number = self.backend.blockchain().info().best_number; - for (config_zero, config_end, config) in configs { - let range_first = ::std::cmp::max(first, config_zero + One::one()); - let range_anchor = match config_end { - Some((config_end_number, config_end_hash)) => - if last_number > config_end_number { - ChangesTrieAnchorBlockId { - hash: config_end_hash, - number: config_end_number, - } - } else { - ChangesTrieAnchorBlockId { - hash: convert_hash(&last_hash), - number: last_number, - } - }, - None => - ChangesTrieAnchorBlockId { hash: convert_hash(&last_hash), number: last_number }, - }; - - let config_range = ChangesTrieConfigurationRange { - config: &config, - zero: config_zero.clone(), - end: config_end.map(|(config_end_number, _)| config_end_number), - }; - let result_range: Vec<(NumberFor, u32)> = key_changes::, _>( - config_range, - storage.storage(), - range_first, - &range_anchor, - best_number, - storage_key, - &key.0, - ) - .and_then(|r| r.map(|r| r.map(|(block, tx)| (block, tx))).collect::>()) - .map_err(|err| sp_blockchain::Error::ChangesTrieAccessFailed(err))?; - result.extend(result_range); - } - - Ok(result) - } } impl HeaderMetadata for Client @@ -1913,16 +1554,6 @@ where } } -impl ProvideCache for Client -where - B: backend::Backend, - Block: BlockT, -{ - fn cache(&self) -> Option>> { - self.backend.blockchain().cache() - } -} - impl ProvideRuntimeApi for Client where B: backend::Backend, diff --git a/client/service/src/lib.rs b/client/service/src/lib.rs index bd43d4c464ea..563846c75d89 100644 --- a/client/service/src/lib.rs +++ b/client/service/src/lib.rs @@ -68,7 +68,7 @@ use sc_client_api::{blockchain::HeaderBackend, BlockchainEvents}; pub use sc_consensus::ImportQueue; pub use sc_executor::NativeExecutionDispatch; #[doc(hidden)] -pub use sc_network::config::{OnDemand, TransactionImport, TransactionImportFuture}; +pub use sc_network::config::{TransactionImport, TransactionImportFuture}; pub use sc_rpc::Metadata as RpcMetadata; pub use sc_tracing::TracingReceiver; pub use sc_transaction_pool::Options as TransactionPoolOptions; diff --git a/client/service/test/Cargo.toml b/client/service/test/Cargo.toml index 03967db15f67..7694e0f6893d 100644 --- a/client/service/test/Cargo.toml +++ b/client/service/test/Cargo.toml @@ -19,7 +19,6 @@ tokio = { version = "1.10.0", features = ["time"] } log = "0.4.8" fdlimit = "0.2.1" parking_lot = "0.11.1" -sc-light = { version = "4.0.0-dev", path = "../../light" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-state-machine = { version = "0.10.0-dev", path = "../../../primitives/state-machine" } diff --git a/client/service/test/src/client/db.rs b/client/service/test/src/client/db.rs index 772fdcada72e..5278c9a13a4d 100644 --- a/client/service/test/src/client/db.rs +++ b/client/service/test/src/client/db.rs @@ -21,7 +21,6 @@ use std::sync::Arc; type TestBackend = sc_client_api::in_mem::Backend; - #[test] fn test_leaves_with_complex_block_tree() { let backend = Arc::new(TestBackend::new()); diff --git a/client/service/test/src/client/mod.rs b/client/service/test/src/client/mod.rs index 33cbefbb06a9..d5e23d319e83 100644 --- a/client/service/test/src/client/mod.rs +++ b/client/service/test/src/client/mod.rs @@ -27,29 +27,25 @@ use sc_client_db::{ use sc_consensus::{ BlockCheckParams, BlockImport, BlockImportParams, ForkChoiceStrategy, ImportResult, }; -use sc_service::client::{self, new_in_mem, Client, LocalCallExecutor}; +use sc_service::client::{new_in_mem, Client, LocalCallExecutor}; use sp_api::ProvideRuntimeApi; use sp_consensus::{BlockOrigin, BlockStatus, Error as ConsensusError, SelectChain}; -use sp_core::{blake2_256, testing::TaskExecutor, ChangesTrieConfiguration, H256}; +use sp_core::{testing::TaskExecutor, H256}; use sp_runtime::{ generic::BlockId, traits::{BlakeTwo256, Block as BlockT, Header as HeaderT}, - ConsensusEngineId, DigestItem, Justifications, + ConsensusEngineId, Justifications, }; use sp_state_machine::{ backend::Backend as _, ExecutionStrategy, InMemoryBackend, OverlayedChanges, StateMachine, }; use sp_storage::{ChildInfo, StorageKey}; use sp_trie::{trie_types::Layout, TrieConfiguration}; -use std::{ - collections::{HashMap, HashSet}, - sync::Arc, -}; +use std::{collections::HashSet, sync::Arc}; use substrate_test_runtime::TestAPI; use substrate_test_runtime_client::{ prelude::*, runtime::{ - self, genesismap::{insert_genesis_block, GenesisConfig}, Block, BlockNumber, Digest, Hash, Header, RuntimeApi, Transfer, }, @@ -57,6 +53,8 @@ use substrate_test_runtime_client::{ Sr25519Keyring, TestClientBuilder, TestClientBuilderExt, }; +mod db; + const TEST_ENGINE_ID: ConsensusEngineId = *b"TEST"; pub struct ExecutorDispatch; @@ -77,86 +75,6 @@ fn executor() -> sc_executor::NativeElseWasmExecutor { sc_executor::NativeElseWasmExecutor::new(sc_executor::WasmExecutionMethod::Interpreted, None, 8) } -pub fn prepare_client_with_key_changes() -> ( - client::Client< - substrate_test_runtime_client::Backend, - substrate_test_runtime_client::ExecutorDispatch, - Block, - RuntimeApi, - >, - Vec, - Vec<(u64, u64, Vec, Vec<(u64, u32)>)>, -) { - // prepare block structure - let blocks_transfers = vec![ - vec![ - (AccountKeyring::Alice, AccountKeyring::Dave), - (AccountKeyring::Bob, AccountKeyring::Dave), - ], - vec![(AccountKeyring::Charlie, AccountKeyring::Eve)], - vec![], - vec![(AccountKeyring::Alice, AccountKeyring::Dave)], - ]; - - // prepare client ang import blocks - let mut local_roots = Vec::new(); - let config = Some(ChangesTrieConfiguration::new(4, 2)); - let mut remote_client = TestClientBuilder::new().changes_trie_config(config).build(); - let mut nonces: HashMap<_, u64> = Default::default(); - for (i, block_transfers) in blocks_transfers.into_iter().enumerate() { - let mut builder = remote_client.new_block(Default::default()).unwrap(); - for (from, to) in block_transfers { - builder - .push_transfer(Transfer { - from: from.into(), - to: to.into(), - amount: 1, - nonce: *nonces.entry(from).and_modify(|n| *n = *n + 1).or_default(), - }) - .unwrap(); - } - let block = builder.build().unwrap().block; - block_on(remote_client.import(BlockOrigin::Own, block)).unwrap(); - - let header = remote_client.header(&BlockId::Number(i as u64 + 1)).unwrap().unwrap(); - let trie_root = header - .digest() - .log(DigestItem::as_changes_trie_root) - .map(|root| H256::from_slice(root.as_ref())) - .unwrap(); - local_roots.push(trie_root); - } - - // prepare test cases - let alice = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Alice.into())).to_vec(); - let bob = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Bob.into())).to_vec(); - let charlie = - blake2_256(&runtime::system::balance_of_key(AccountKeyring::Charlie.into())).to_vec(); - let dave = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Dave.into())).to_vec(); - let eve = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Eve.into())).to_vec(); - let ferdie = - blake2_256(&runtime::system::balance_of_key(AccountKeyring::Ferdie.into())).to_vec(); - let test_cases = vec![ - (1, 4, alice.clone(), vec![(4, 0), (1, 0)]), - (1, 3, alice.clone(), vec![(1, 0)]), - (2, 4, alice.clone(), vec![(4, 0)]), - (2, 3, alice.clone(), vec![]), - (1, 4, bob.clone(), vec![(1, 1)]), - (1, 1, bob.clone(), vec![(1, 1)]), - (2, 4, bob.clone(), vec![]), - (1, 4, charlie.clone(), vec![(2, 0)]), - (1, 4, dave.clone(), vec![(4, 0), (1, 1), (1, 0)]), - (1, 1, dave.clone(), vec![(1, 1), (1, 0)]), - (3, 4, dave.clone(), vec![(4, 0)]), - (1, 4, eve.clone(), vec![(2, 0)]), - (1, 1, eve.clone(), vec![]), - (3, 4, eve.clone(), vec![]), - (1, 4, ferdie.clone(), vec![]), - ]; - - (remote_client, local_roots, test_cases) -} - fn construct_block( backend: &InMemoryBackend, number: BlockNumber, @@ -184,7 +102,6 @@ fn construct_block( StateMachine::new( backend, - sp_state_machine::disabled_changes_trie_state::<_, u64>(), &mut overlay, &executor(), "Core_initialize_block", @@ -199,7 +116,6 @@ fn construct_block( for tx in transactions.iter() { StateMachine::new( backend, - sp_state_machine::disabled_changes_trie_state::<_, u64>(), &mut overlay, &executor(), "BlockBuilder_apply_extrinsic", @@ -214,7 +130,6 @@ fn construct_block( let ret_data = StateMachine::new( backend, - sp_state_machine::disabled_changes_trie_state::<_, u64>(), &mut overlay, &executor(), "BlockBuilder_finalize_block", @@ -248,7 +163,6 @@ fn block1(genesis_hash: Hash, backend: &InMemoryBackend) -> (Vec(), &mut overlay, &executor(), "Core_execute_block", @@ -283,7 +196,6 @@ fn construct_genesis_should_work_with_native() { #[test] fn construct_genesis_should_work_with_wasm() { let mut storage = GenesisConfig::new( - None, vec![Sr25519Keyring::One.public().into(), Sr25519Keyring::Two.public().into()], vec![AccountKeyring::One.into(), AccountKeyring::Two.into()], 1000, @@ -302,7 +214,6 @@ fn construct_genesis_should_work_with_wasm() { let _ = StateMachine::new( &backend, - sp_state_machine::disabled_changes_trie_state::<_, u64>(), &mut overlay, &executor(), "Core_execute_block", @@ -318,7 +229,6 @@ fn construct_genesis_should_work_with_wasm() { #[test] fn construct_genesis_with_bad_transaction_should_panic() { let mut storage = GenesisConfig::new( - None, vec![Sr25519Keyring::One.public().into(), Sr25519Keyring::Two.public().into()], vec![AccountKeyring::One.into(), AccountKeyring::Two.into()], 68, @@ -337,7 +247,6 @@ fn construct_genesis_with_bad_transaction_should_panic() { let r = StateMachine::new( &backend, - sp_state_machine::disabled_changes_trie_state::<_, u64>(), &mut overlay, &executor(), "Core_execute_block", @@ -906,23 +815,6 @@ fn best_containing_on_longest_chain_with_max_depth_higher_than_best() { ); } -#[test] -fn key_changes_works() { - let (client, _, test_cases) = prepare_client_with_key_changes(); - - for (index, (begin, end, key, expected_result)) in test_cases.into_iter().enumerate() { - let end = client.block_hash(end).unwrap().unwrap(); - let actual_result = - client.key_changes(begin, BlockId::Hash(end), None, &StorageKey(key)).unwrap(); - if actual_result != expected_result { - panic!( - "Failed test {}: actual = {:?}, expected = {:?}", - index, actual_result, expected_result, - ); - } - } -} - #[test] fn import_with_justification() { let mut client = substrate_test_runtime_client::new(); @@ -1229,12 +1121,8 @@ fn doesnt_import_blocks_that_revert_finality() { ClientExt::finalize_block(&client, BlockId::Hash(a2.hash()), None).unwrap(); let import_err = block_on(client.import(BlockOrigin::Own, b3)).err().unwrap(); - let expected_err = ConsensusError::ClientImport( - sp_blockchain::Error::RuntimeApiError(sp_api::ApiError::Application(Box::new( - sp_blockchain::Error::NotInFinalizedChain, - ))) - .to_string(), - ); + let expected_err = + ConsensusError::ClientImport(sp_blockchain::Error::NotInFinalizedChain.to_string()); assert_eq!(import_err.to_string(), expected_err.to_string()); @@ -1536,152 +1424,6 @@ fn returns_status_for_pruned_blocks() { ); } -#[test] -fn imports_blocks_with_changes_tries_config_change() { - // create client with initial 4^2 configuration - let mut client = TestClientBuilder::with_default_backend() - .changes_trie_config(Some(ChangesTrieConfiguration { - digest_interval: 4, - digest_levels: 2, - })) - .build(); - - // =================================================================== - // blocks 1,2,3,4,5,6,7,8,9,10 are empty - // block 11 changes the key - // block 12 is the L1 digest that covers this change - // blocks 13,14,15,16,17,18,19,20,21,22 are empty - // block 23 changes the configuration to 5^1 AND is skewed digest - // =================================================================== - // blocks 24,25 are changing the key - // block 26 is empty - // block 27 changes the key - // block 28 is the L1 digest (NOT SKEWED!!!) that covers changes AND changes configuration to - // `3^1` - // =================================================================== - // block 29 is empty - // block 30 changes the key - // block 31 is L1 digest that covers this change - // =================================================================== - (1..11).for_each(|number| { - let block = client - .new_block_at(&BlockId::Number(number - 1), Default::default(), false) - .unwrap() - .build() - .unwrap() - .block; - block_on(client.import(BlockOrigin::Own, block)).unwrap(); - }); - (11..12).for_each(|number| { - let mut block = client - .new_block_at(&BlockId::Number(number - 1), Default::default(), false) - .unwrap(); - block - .push_storage_change(vec![42], Some(number.to_le_bytes().to_vec())) - .unwrap(); - let block = block.build().unwrap().block; - block_on(client.import(BlockOrigin::Own, block)).unwrap(); - }); - (12..23).for_each(|number| { - let block = client - .new_block_at(&BlockId::Number(number - 1), Default::default(), false) - .unwrap() - .build() - .unwrap() - .block; - block_on(client.import(BlockOrigin::Own, block)).unwrap(); - }); - (23..24).for_each(|number| { - let mut block = client - .new_block_at(&BlockId::Number(number - 1), Default::default(), false) - .unwrap(); - block - .push_changes_trie_configuration_update(Some(ChangesTrieConfiguration { - digest_interval: 5, - digest_levels: 1, - })) - .unwrap(); - let block = block.build().unwrap().block; - block_on(client.import(BlockOrigin::Own, block)).unwrap(); - }); - (24..26).for_each(|number| { - let mut block = client - .new_block_at(&BlockId::Number(number - 1), Default::default(), false) - .unwrap(); - block - .push_storage_change(vec![42], Some(number.to_le_bytes().to_vec())) - .unwrap(); - let block = block.build().unwrap().block; - block_on(client.import(BlockOrigin::Own, block)).unwrap(); - }); - (26..27).for_each(|number| { - let block = client - .new_block_at(&BlockId::Number(number - 1), Default::default(), false) - .unwrap() - .build() - .unwrap() - .block; - block_on(client.import(BlockOrigin::Own, block)).unwrap(); - }); - (27..28).for_each(|number| { - let mut block = client - .new_block_at(&BlockId::Number(number - 1), Default::default(), false) - .unwrap(); - block - .push_storage_change(vec![42], Some(number.to_le_bytes().to_vec())) - .unwrap(); - let block = block.build().unwrap().block; - block_on(client.import(BlockOrigin::Own, block)).unwrap(); - }); - (28..29).for_each(|number| { - let mut block = client - .new_block_at(&BlockId::Number(number - 1), Default::default(), false) - .unwrap(); - block - .push_changes_trie_configuration_update(Some(ChangesTrieConfiguration { - digest_interval: 3, - digest_levels: 1, - })) - .unwrap(); - let block = block.build().unwrap().block; - block_on(client.import(BlockOrigin::Own, block)).unwrap(); - }); - (29..30).for_each(|number| { - let block = client - .new_block_at(&BlockId::Number(number - 1), Default::default(), false) - .unwrap() - .build() - .unwrap() - .block; - block_on(client.import(BlockOrigin::Own, block)).unwrap(); - }); - (30..31).for_each(|number| { - let mut block = client - .new_block_at(&BlockId::Number(number - 1), Default::default(), false) - .unwrap(); - block - .push_storage_change(vec![42], Some(number.to_le_bytes().to_vec())) - .unwrap(); - let block = block.build().unwrap().block; - block_on(client.import(BlockOrigin::Own, block)).unwrap(); - }); - (31..32).for_each(|number| { - let block = client - .new_block_at(&BlockId::Number(number - 1), Default::default(), false) - .unwrap() - .build() - .unwrap() - .block; - block_on(client.import(BlockOrigin::Own, block)).unwrap(); - }); - - // now check that configuration cache works - assert_eq!( - client.key_changes(1, BlockId::Number(31), None, &StorageKey(vec![42])).unwrap(), - vec![(30, 0), (27, 0), (25, 0), (24, 0), (11, 0)] - ); -} - #[test] fn storage_keys_iter_prefix_and_start_key_works() { let child_info = ChildInfo::new_default(b"child"); diff --git a/client/transaction-pool/src/api.rs b/client/transaction-pool/src/api.rs index 8af0ea98f810..08fe1e34edb8 100644 --- a/client/transaction-pool/src/api.rs +++ b/client/transaction-pool/src/api.rs @@ -18,7 +18,7 @@ //! Chain api required for the transaction pool. -use codec::{Decode, Encode}; +use codec::Encode; use futures::{ channel::{mpsc, oneshot}, future::{ready, Future, FutureExt, Ready}, @@ -28,16 +28,12 @@ use futures::{ use std::{marker::PhantomData, pin::Pin, sync::Arc}; use prometheus_endpoint::Registry as PrometheusRegistry; -use sc_client_api::{ - blockchain::HeaderBackend, - light::{Fetcher, RemoteBodyRequest, RemoteCallRequest}, - BlockBackend, -}; +use sc_client_api::{blockchain::HeaderBackend, BlockBackend}; use sp_api::{ApiExt, ProvideRuntimeApi}; use sp_core::traits::SpawnEssentialNamed; use sp_runtime::{ generic::BlockId, - traits::{self, Block as BlockT, BlockIdTo, Hash as HashT, Header as HeaderT}, + traits::{self, Block as BlockT, BlockIdTo}, transaction_validity::{TransactionSource, TransactionValidity}, }; use sp_transaction_pool::runtime_api::TaggedTransactionQueue; @@ -290,127 +286,3 @@ where validate_transaction_blocking(&*self.client, at, source, uxt) } } - -/// The transaction pool logic for light client. -pub struct LightChainApi { - client: Arc, - fetcher: Arc, - _phantom: PhantomData, -} - -impl LightChainApi { - /// Create new transaction pool logic. - pub fn new(client: Arc, fetcher: Arc) -> Self { - LightChainApi { client, fetcher, _phantom: Default::default() } - } -} - -impl graph::ChainApi for LightChainApi -where - Block: BlockT, - Client: HeaderBackend + 'static, - F: Fetcher + 'static, -{ - type Block = Block; - type Error = error::Error; - type ValidationFuture = - Box> + Send + Unpin>; - type BodyFuture = Pin< - Box< - dyn Future::Extrinsic>>>> - + Send, - >, - >; - - fn validate_transaction( - &self, - at: &BlockId, - source: TransactionSource, - uxt: graph::ExtrinsicFor, - ) -> Self::ValidationFuture { - let header_hash = self.client.expect_block_hash_from_id(at); - let header_and_hash = header_hash.and_then(|header_hash| { - self.client - .expect_header(BlockId::Hash(header_hash)) - .map(|header| (header_hash, header)) - }); - let (block, header) = match header_and_hash { - Ok((header_hash, header)) => (header_hash, header), - Err(err) => return Box::new(ready(Err(err.into()))), - }; - let remote_validation_request = self.fetcher.remote_call(RemoteCallRequest { - block, - header, - method: "TaggedTransactionQueue_validate_transaction".into(), - call_data: (source, uxt, block).encode(), - retry_count: None, - }); - let remote_validation_request = remote_validation_request.then(move |result| { - let result: error::Result = - result.map_err(Into::into).and_then(|result| { - Decode::decode(&mut &result[..]).map_err(|e| { - Error::RuntimeApi(format!("Error decoding tx validation result: {:?}", e)) - }) - }); - ready(result) - }); - - Box::new(remote_validation_request) - } - - fn block_id_to_number( - &self, - at: &BlockId, - ) -> error::Result>> { - Ok(self.client.block_number_from_id(at)?) - } - - fn block_id_to_hash( - &self, - at: &BlockId, - ) -> error::Result>> { - Ok(self.client.block_hash_from_id(at)?) - } - - fn hash_and_length( - &self, - ex: &graph::ExtrinsicFor, - ) -> (graph::ExtrinsicHash, usize) { - ex.using_encoded(|x| (<::Hashing as HashT>::hash(x), x.len())) - } - - fn block_body(&self, id: &BlockId) -> Self::BodyFuture { - let header = self - .client - .header(*id) - .and_then(|h| h.ok_or_else(|| sp_blockchain::Error::UnknownBlock(format!("{}", id)))); - let header = match header { - Ok(header) => header, - Err(err) => { - log::warn!(target: "txpool", "Failed to query header: {:?}", err); - return Box::pin(ready(Ok(None))) - }, - }; - - let fetcher = self.fetcher.clone(); - async move { - let transactions = fetcher - .remote_body(RemoteBodyRequest { header, retry_count: None }) - .await - .unwrap_or_else(|e| { - log::warn!(target: "txpool", "Failed to fetch block body: {:?}", e); - Vec::new() - }); - - Ok(Some(transactions)) - } - .boxed() - } - - fn block_header( - &self, - at: &BlockId, - ) -> Result::Header>, Self::Error> { - self.client.header(*at).map_err(Into::into) - } -} diff --git a/client/transaction-pool/src/lib.rs b/client/transaction-pool/src/lib.rs index 3565cb52ad87..85af4f89d72b 100644 --- a/client/transaction-pool/src/lib.rs +++ b/client/transaction-pool/src/lib.rs @@ -38,7 +38,7 @@ pub mod test_helpers { }; } -pub use crate::api::{FullChainApi, LightChainApi}; +pub use crate::api::FullChainApi; use futures::{ channel::oneshot, future::{self, ready}, @@ -79,9 +79,6 @@ type PolledIterator = Pin = BasicPool, Block>; -/// A transaction pool for a light node. -pub type LightPool = - BasicPool, Block>; /// Basic implementation of transaction pool that can be customized by providing PoolApi. pub struct BasicPool @@ -364,33 +361,6 @@ where } } -impl LightPool -where - Block: BlockT, - Client: sp_blockchain::HeaderBackend + sc_client_api::UsageProvider + 'static, - Fetcher: sc_client_api::Fetcher + 'static, -{ - /// Create new basic transaction pool for a light node with the provided api. - pub fn new_light( - options: graph::Options, - prometheus: Option<&PrometheusRegistry>, - spawner: impl SpawnEssentialNamed, - client: Arc, - fetcher: Arc, - ) -> Self { - let pool_api = Arc::new(LightChainApi::new(client.clone(), fetcher)); - Self::with_revalidation_type( - options, - false.into(), - pool_api, - prometheus, - RevalidationType::Light, - spawner, - client.usage_info().chain.best_number, - ) - } -} - impl FullPool where Block: BlockT, diff --git a/frame/aura/src/lib.rs b/frame/aura/src/lib.rs index a4e55f25df5f..887bb359ed3d 100644 --- a/frame/aura/src/lib.rs +++ b/frame/aura/src/lib.rs @@ -151,7 +151,7 @@ impl Pallet { fn change_authorities(new: WeakBoundedVec) { >::put(&new); - let log: DigestItem = DigestItem::Consensus( + let log = DigestItem::Consensus( AURA_ENGINE_ID, ConsensusLog::AuthoritiesChange(new.into_inner()).encode(), ); @@ -222,7 +222,7 @@ impl OneSessionHandler for Pallet { } fn on_disabled(i: u32) { - let log: DigestItem = DigestItem::Consensus( + let log = DigestItem::Consensus( AURA_ENGINE_ID, ConsensusLog::::OnDisabled(i as AuthorityIndex).encode(), ); diff --git a/frame/babe/src/lib.rs b/frame/babe/src/lib.rs index 033d993f4e26..569722ca38ce 100644 --- a/frame/babe/src/lib.rs +++ b/frame/babe/src/lib.rs @@ -633,7 +633,7 @@ impl Pallet { } fn deposit_consensus(new: U) { - let log: DigestItem = DigestItem::Consensus(BABE_ENGINE_ID, new.encode()); + let log = DigestItem::Consensus(BABE_ENGINE_ID, new.encode()); >::deposit_log(log.into()) } diff --git a/frame/beefy-mmr/src/tests.rs b/frame/beefy-mmr/src/tests.rs index 7c70766623b4..f27bc450ad14 100644 --- a/frame/beefy-mmr/src/tests.rs +++ b/frame/beefy-mmr/src/tests.rs @@ -40,7 +40,7 @@ fn init_block(block: u64) { BeefyMmr::on_initialize(block); } -pub fn beefy_log(log: ConsensusLog) -> DigestItem { +pub fn beefy_log(log: ConsensusLog) -> DigestItem { DigestItem::Consensus(BEEFY_ENGINE_ID, log.encode()) } diff --git a/frame/beefy/src/lib.rs b/frame/beefy/src/lib.rs index 3b28d454849c..6a7118c1f5c9 100644 --- a/frame/beefy/src/lib.rs +++ b/frame/beefy/src/lib.rs @@ -110,7 +110,7 @@ impl Pallet { let next_id = Self::validator_set_id() + 1u64; >::put(next_id); - let log: DigestItem = DigestItem::Consensus( + let log = DigestItem::Consensus( BEEFY_ENGINE_ID, ConsensusLog::AuthoritiesChange(ValidatorSet { validators: new, id: next_id }) .encode(), @@ -163,7 +163,7 @@ impl OneSessionHandler for Pallet { } fn on_disabled(i: u32) { - let log: DigestItem = DigestItem::Consensus( + let log = DigestItem::Consensus( BEEFY_ENGINE_ID, ConsensusLog::::OnDisabled(i as AuthorityIndex).encode(), ); diff --git a/frame/beefy/src/tests.rs b/frame/beefy/src/tests.rs index 24f9acaf76bf..252c03efb54a 100644 --- a/frame/beefy/src/tests.rs +++ b/frame/beefy/src/tests.rs @@ -20,7 +20,6 @@ use std::vec; use beefy_primitives::ValidatorSet; use codec::Encode; -use sp_core::H256; use sp_runtime::DigestItem; use frame_support::traits::OnInitialize; @@ -32,7 +31,7 @@ fn init_block(block: u64) { Session::on_initialize(block); } -pub fn beefy_log(log: ConsensusLog) -> DigestItem { +pub fn beefy_log(log: ConsensusLog) -> DigestItem { DigestItem::Consensus(BEEFY_ENGINE_ID, log.encode()) } diff --git a/frame/executive/src/lib.rs b/frame/executive/src/lib.rs index b1bdf357ec07..e77c811a35e2 100644 --- a/frame/executive/src/lib.rs +++ b/frame/executive/src/lib.rs @@ -125,7 +125,6 @@ use frame_support::{ }, weights::{DispatchClass, DispatchInfo, GetDispatchInfo}, }; -use frame_system::DigestOf; use sp_runtime::{ generic::Digest, traits::{ @@ -281,8 +280,8 @@ where Self::initialize_block_impl(header.number(), header.parent_hash(), &digests); } - fn extract_pre_digest(header: &System::Header) -> DigestOf { - let mut digest = >::default(); + fn extract_pre_digest(header: &System::Header) -> Digest { + let mut digest = ::default(); header.digest().logs().iter().for_each(|d| { if d.as_pre_runtime().is_some() { digest.push(d.clone()) @@ -294,7 +293,7 @@ where fn initialize_block_impl( block_number: &System::BlockNumber, parent_hash: &System::Hash, - digest: &Digest, + digest: &Digest, ) { let mut weight = 0; if Self::runtime_upgraded() { diff --git a/frame/grandpa/src/lib.rs b/frame/grandpa/src/lib.rs index 9f6967a7d3c8..0e7d885649cc 100644 --- a/frame/grandpa/src/lib.rs +++ b/frame/grandpa/src/lib.rs @@ -508,7 +508,7 @@ impl Pallet { /// Deposit one of this module's logs. fn deposit_log(log: ConsensusLog) { - let log: DigestItem = DigestItem::Consensus(GRANDPA_ENGINE_ID, log.encode()); + let log = DigestItem::Consensus(GRANDPA_ENGINE_ID, log.encode()); >::deposit_log(log.into()); } diff --git a/frame/grandpa/src/mock.rs b/frame/grandpa/src/mock.rs index f1996553f02e..49e4022a4aae 100644 --- a/frame/grandpa/src/mock.rs +++ b/frame/grandpa/src/mock.rs @@ -254,7 +254,7 @@ impl Config for Test { type MaxAuthorities = MaxAuthorities; } -pub fn grandpa_log(log: ConsensusLog) -> DigestItem { +pub fn grandpa_log(log: ConsensusLog) -> DigestItem { DigestItem::Consensus(GRANDPA_ENGINE_ID, log.encode()) } diff --git a/frame/support/src/storage/mod.rs b/frame/support/src/storage/mod.rs index 69445932b869..81f98f2c23d4 100644 --- a/frame/support/src/storage/mod.rs +++ b/frame/support/src/storage/mod.rs @@ -1223,7 +1223,7 @@ mod private { pub trait Sealed {} impl Sealed for Vec {} - impl Sealed for Digest {} + impl Sealed for Digest {} impl Sealed for BoundedVec {} impl Sealed for WeakBoundedVec {} impl Sealed for bounded_btree_map::BoundedBTreeMap {} @@ -1263,7 +1263,7 @@ impl StorageDecodeLength for Vec {} /// We abuse the fact that SCALE does not put any marker into the encoding, i.e. we only encode the /// internal vec and we can append to this vec. We have a test that ensures that if the `Digest` /// format ever changes, we need to remove this here. -impl StorageAppend> for Digest {} +impl StorageAppend for Digest {} /// Marker trait that is implemented for types that support the `storage::append` api with a limit /// on the number of element. @@ -1484,8 +1484,8 @@ mod test { fn digest_storage_append_works_as_expected() { TestExternalities::default().execute_with(|| { struct Storage; - impl generator::StorageValue> for Storage { - type Query = Digest; + impl generator::StorageValue for Storage { + type Query = Digest; fn module_prefix() -> &'static [u8] { b"MyModule" @@ -1495,23 +1495,20 @@ mod test { b"Storage" } - fn from_optional_value_to_query(v: Option>) -> Self::Query { + fn from_optional_value_to_query(v: Option) -> Self::Query { v.unwrap() } - fn from_query_to_optional_value(v: Self::Query) -> Option> { + fn from_query_to_optional_value(v: Self::Query) -> Option { Some(v) } } - Storage::append(DigestItem::ChangesTrieRoot(1)); Storage::append(DigestItem::Other(Vec::new())); let value = unhashed::get_raw(&Storage::storage_value_final_key()).unwrap(); - let expected = Digest { - logs: vec![DigestItem::ChangesTrieRoot(1), DigestItem::Other(Vec::new())], - }; + let expected = Digest { logs: vec![DigestItem::Other(Vec::new())] }; assert_eq!(Digest::decode(&mut &value[..]).unwrap(), expected); }); } diff --git a/frame/system/benchmarking/src/lib.rs b/frame/system/benchmarking/src/lib.rs index e7371b1099e5..eddf78ce6b25 100644 --- a/frame/system/benchmarking/src/lib.rs +++ b/frame/system/benchmarking/src/lib.rs @@ -22,8 +22,8 @@ use codec::Encode; use frame_benchmarking::{benchmarks, whitelisted_caller}; use frame_support::{storage, traits::Get, weights::DispatchClass}; -use frame_system::{Call, DigestItemOf, Pallet as System, RawOrigin}; -use sp_core::{storage::well_known_keys, ChangesTrieConfiguration}; +use frame_system::{Call, Pallet as System, RawOrigin}; +use sp_core::storage::well_known_keys; use sp_runtime::traits::Hash; use sp_std::{prelude::*, vec}; @@ -62,23 +62,6 @@ benchmarks! { assert_eq!(current_code.len(), 4_000_000 as usize); } - set_changes_trie_config { - let d = 1000; - - let digest_item = DigestItemOf::::Other(vec![]); - - for i in 0 .. d { - System::::deposit_log(digest_item.clone()); - } - let changes_trie_config = ChangesTrieConfiguration { - digest_interval: d, - digest_levels: d, - }; - }: _(RawOrigin::Root, Some(changes_trie_config)) - verify { - assert_eq!(System::::digest().logs.len(), (d + 1) as usize) - } - #[skip_meta] set_storage { let i in 1 .. 1000; diff --git a/frame/system/src/lib.rs b/frame/system/src/lib.rs index 41e1738c034f..d5b930fa165e 100644 --- a/frame/system/src/lib.rs +++ b/frame/system/src/lib.rs @@ -95,7 +95,7 @@ use frame_support::{ Parameter, }; use scale_info::TypeInfo; -use sp_core::{storage::well_known_keys, ChangesTrieConfiguration}; +use sp_core::storage::well_known_keys; #[cfg(feature = "std")] use frame_support::traits::GenesisBuild; @@ -405,37 +405,6 @@ pub mod pallet { Ok(().into()) } - /// Set the new changes trie configuration. - /// - /// # - /// - `O(1)` - /// - 1 storage write or delete (codec `O(1)`). - /// - 1 call to `deposit_log`: Uses `append` API, so O(1) - /// - Base Weight: 7.218 µs - /// - DB Weight: - /// - Writes: Changes Trie, System Digest - /// # - #[pallet::weight((T::SystemWeightInfo::set_changes_trie_config(), DispatchClass::Operational))] - pub fn set_changes_trie_config( - origin: OriginFor, - changes_trie_config: Option, - ) -> DispatchResultWithPostInfo { - ensure_root(origin)?; - match changes_trie_config.clone() { - Some(changes_trie_config) => storage::unhashed::put_raw( - well_known_keys::CHANGES_TRIE_CONFIG, - &changes_trie_config.encode(), - ), - None => storage::unhashed::kill(well_known_keys::CHANGES_TRIE_CONFIG), - } - - let log = generic::DigestItem::ChangesTrieSignal( - generic::ChangesTrieSignal::NewConfiguration(changes_trie_config), - ); - Self::deposit_log(log.into()); - Ok(().into()) - } - /// Set some items of storage. /// /// # @@ -617,7 +586,7 @@ pub mod pallet { /// Digest of the current block, also part of the block header. #[pallet::storage] #[pallet::getter(fn digest)] - pub(super) type Digest = StorageValue<_, DigestOf, ValueQuery>; + pub(super) type Digest = StorageValue<_, generic::Digest, ValueQuery>; /// Events deposited for the current block. /// @@ -666,7 +635,6 @@ pub mod pallet { #[pallet::genesis_config] pub struct GenesisConfig { - pub changes_trie_config: Option, #[serde(with = "sp_core::bytes")] pub code: Vec, } @@ -674,7 +642,7 @@ pub mod pallet { #[cfg(feature = "std")] impl Default for GenesisConfig { fn default() -> Self { - Self { changes_trie_config: Default::default(), code: Default::default() } + Self { code: Default::default() } } } @@ -689,12 +657,6 @@ pub mod pallet { sp_io::storage::set(well_known_keys::CODE, &self.code); sp_io::storage::set(well_known_keys::EXTRINSIC_INDEX, &0u32.encode()); - if let Some(ref changes_trie_config) = self.changes_trie_config { - sp_io::storage::set( - well_known_keys::CHANGES_TRIE_CONFIG, - &changes_trie_config.encode(), - ); - } } } } @@ -759,9 +721,6 @@ impl GenesisConfig { } } -pub type DigestOf = generic::Digest<::Hash>; -pub type DigestItemOf = generic::DigestItem<::Hash>; - pub type Key = Vec; pub type KeyValue = (Vec, Vec); @@ -1369,7 +1328,7 @@ impl Pallet { pub fn initialize( number: &T::BlockNumber, parent_hash: &T::Hash, - digest: &DigestOf, + digest: &generic::Digest, kind: InitKind, ) { // populate environment @@ -1409,7 +1368,7 @@ impl Pallet { // stay to be inspected by the client and will be cleared by `Self::initialize`. let number = >::get(); let parent_hash = >::get(); - let mut digest = >::get(); + let digest = >::get(); let extrinsics = (0..ExtrinsicCount::::take().unwrap_or_default()) .map(ExtrinsicData::::take) @@ -1427,17 +1386,6 @@ impl Pallet { let storage_root = T::Hash::decode(&mut &sp_io::storage::root()[..]) .expect("Node is configured to use the same hash; qed"); - let storage_changes_root = sp_io::storage::changes_root(&parent_hash.encode()); - - // we can't compute changes trie root earlier && put it to the Digest - // because it will include all currently existing temporaries. - if let Some(storage_changes_root) = storage_changes_root { - let item = generic::DigestItem::ChangesTrieRoot( - T::Hash::decode(&mut &storage_changes_root[..]) - .expect("Node is configured to use the same hash; qed"), - ); - digest.push(item); - } ::new( number, @@ -1454,7 +1402,7 @@ impl Pallet { /// - `O(1)` /// - 1 storage write (codec `O(1)`) /// # - pub fn deposit_log(item: DigestItemOf) { + pub fn deposit_log(item: generic::DigestItem) { >::append(item); } diff --git a/primitives/api/proc-macro/src/impl_runtime_apis.rs b/primitives/api/proc-macro/src/impl_runtime_apis.rs index bc0f027e1efa..dd2a7f6c1490 100644 --- a/primitives/api/proc-macro/src/impl_runtime_apis.rs +++ b/primitives/api/proc-macro/src/impl_runtime_apis.rs @@ -288,10 +288,6 @@ fn generate_runtime_api_base_structures() -> Result { fn into_storage_changes( &self, backend: &Self::StateBackend, - changes_trie_state: Option<&#crate_::ChangesTrieState< - #crate_::HashFor, - #crate_::NumberFor, - >>, parent_hash: Block::Hash, ) -> std::result::Result< #crate_::StorageChanges, @@ -299,7 +295,6 @@ fn generate_runtime_api_base_structures() -> Result { > where Self: Sized { self.changes.replace(Default::default()).into_storage_changes( backend, - changes_trie_state, parent_hash, self.storage_transaction_cache.replace(Default::default()), ) diff --git a/primitives/api/proc-macro/src/mock_impl_runtime_apis.rs b/primitives/api/proc-macro/src/mock_impl_runtime_apis.rs index 77f8a07f85c4..9483d018c4a4 100644 --- a/primitives/api/proc-macro/src/mock_impl_runtime_apis.rs +++ b/primitives/api/proc-macro/src/mock_impl_runtime_apis.rs @@ -116,10 +116,6 @@ fn implement_common_api_traits(block_type: TypePath, self_ty: Type) -> Result, - #crate_::NumberFor<#block_type>, - >>, _: <#block_type as #crate_::BlockT>::Hash, ) -> std::result::Result< #crate_::StorageChanges, diff --git a/primitives/api/src/lib.rs b/primitives/api/src/lib.rs index cb74f95d21b0..7f64e191941f 100644 --- a/primitives/api/src/lib.rs +++ b/primitives/api/src/lib.rs @@ -97,7 +97,7 @@ pub use sp_runtime::{ #[doc(hidden)] #[cfg(feature = "std")] pub use sp_state_machine::{ - Backend as StateBackend, ChangesTrieState, InMemoryBackend, OverlayedChanges, StorageProof, + Backend as StateBackend, InMemoryBackend, OverlayedChanges, StorageProof, }; #[cfg(feature = "std")] use sp_std::result; @@ -394,14 +394,12 @@ pub type ProofRecorder = sp_state_machine::ProofRecorder<::Hash> pub type StorageTransactionCache = sp_state_machine::StorageTransactionCache< >>::Transaction, HashFor, - NumberFor, >; #[cfg(feature = "std")] pub type StorageChanges = sp_state_machine::StorageChanges< >>::Transaction, HashFor, - NumberFor, >; /// Extract the state backend type for a type that implements `ProvideRuntimeApi`. @@ -514,7 +512,6 @@ pub trait ApiExt { fn into_storage_changes( &self, backend: &Self::StateBackend, - changes_trie_state: Option<&ChangesTrieState, NumberFor>>, parent_hash: Block::Hash, ) -> Result, String> where diff --git a/primitives/api/test/tests/runtime_calls.rs b/primitives/api/test/tests/runtime_calls.rs index 101f92fd6c7d..e32290b12a59 100644 --- a/primitives/api/test/tests/runtime_calls.rs +++ b/primitives/api/test/tests/runtime_calls.rs @@ -211,7 +211,7 @@ fn record_proof_works() { None, 8, ); - execution_proof_check_on_trie_backend::<_, u64, _, _>( + execution_proof_check_on_trie_backend( &backend, &mut overlay, &executor, diff --git a/primitives/blockchain/src/backend.rs b/primitives/blockchain/src/backend.rs index fc70ce845dc9..71c3f36a161b 100644 --- a/primitives/blockchain/src/backend.rs +++ b/primitives/blockchain/src/backend.rs @@ -17,8 +17,6 @@ //! Substrate blockchain trait -use std::sync::Arc; - use log::warn; use parking_lot::RwLock; use sp_runtime::{ @@ -96,8 +94,6 @@ pub trait Backend: fn justifications(&self, id: BlockId) -> Result>; /// Get last finalized block hash. fn last_finalized(&self) -> Result; - /// Returns data cache reference, if it is enabled on this backend. - fn cache(&self) -> Option>>; /// Returns hashes of all blocks that are leaves of the block tree. /// in other words, that have no children, are chain heads. @@ -237,33 +233,6 @@ pub trait Backend: fn block_indexed_body(&self, id: BlockId) -> Result>>>; } -/// Provides access to the optional cache. -pub trait ProvideCache { - /// Returns data cache reference, if it is enabled on this backend. - fn cache(&self) -> Option>>; -} - -/// Blockchain optional data cache. -pub trait Cache: Send + Sync { - /// Initialize genesis value for the given cache. - /// - /// The operation should be performed once before anything else is inserted in the cache. - /// Otherwise cache may end up in inconsistent state. - fn initialize(&self, key: &well_known_cache_keys::Id, value_at_genesis: Vec) -> Result<()>; - /// Returns cached value by the given key. - /// - /// Returned tuple is the range where value has been active and the value itself. - /// Fails if read from cache storage fails or if the value for block is discarded - /// (i.e. if block is earlier that best finalized, but it is not in canonical chain). - fn get_at( - &self, - key: &well_known_cache_keys::Id, - block: &BlockId, - ) -> Result< - Option<((NumberFor, Block::Hash), Option<(NumberFor, Block::Hash)>, Vec)>, - >; -} - /// Blockchain info #[derive(Debug, Eq, PartialEq)] pub struct Info { diff --git a/primitives/consensus/aura/src/digests.rs b/primitives/consensus/aura/src/digests.rs index eaa29036d98a..6925862d0ce9 100644 --- a/primitives/consensus/aura/src/digests.rs +++ b/primitives/consensus/aura/src/digests.rs @@ -25,7 +25,6 @@ use crate::AURA_ENGINE_ID; use codec::{Codec, Encode}; use sp_consensus_slots::Slot; use sp_runtime::generic::DigestItem; -use sp_std::fmt::Debug; /// A digest item which is usable with aura consensus. pub trait CompatibleDigestItem: Sized { @@ -42,10 +41,9 @@ pub trait CompatibleDigestItem: Sized { fn as_aura_pre_digest(&self) -> Option; } -impl CompatibleDigestItem for DigestItem +impl CompatibleDigestItem for DigestItem where Signature: Codec, - Hash: Debug + Send + Sync + Eq + Clone + Codec + 'static, { fn aura_seal(signature: Signature) -> Self { DigestItem::Seal(AURA_ENGINE_ID, signature.encode()) diff --git a/primitives/consensus/babe/src/digests.rs b/primitives/consensus/babe/src/digests.rs index 1c908fe61fc0..4847adec37f1 100644 --- a/primitives/consensus/babe/src/digests.rs +++ b/primitives/consensus/babe/src/digests.rs @@ -21,7 +21,7 @@ use super::{ AllowedSlots, AuthorityId, AuthorityIndex, AuthoritySignature, BabeAuthorityWeight, BabeEpochConfiguration, Slot, BABE_ENGINE_ID, }; -use codec::{Codec, Decode, Encode, MaxEncodedLen}; +use codec::{Decode, Encode, MaxEncodedLen}; use sp_runtime::{DigestItem, RuntimeDebug}; use sp_std::vec::Vec; @@ -177,10 +177,7 @@ pub trait CompatibleDigestItem: Sized { fn as_next_config_descriptor(&self) -> Option; } -impl CompatibleDigestItem for DigestItem -where - Hash: Send + Sync + Eq + Clone + Codec + 'static, -{ +impl CompatibleDigestItem for DigestItem { fn babe_pre_digest(digest: PreDigest) -> Self { DigestItem::PreRuntime(BABE_ENGINE_ID, digest.encode()) } diff --git a/primitives/consensus/common/src/lib.rs b/primitives/consensus/common/src/lib.rs index d7979baf47c1..ce834fd0a47f 100644 --- a/primitives/consensus/common/src/lib.rs +++ b/primitives/consensus/common/src/lib.rs @@ -26,7 +26,8 @@ use std::{sync::Arc, time::Duration}; use futures::prelude::*; use sp_runtime::{ generic::BlockId, - traits::{Block as BlockT, DigestFor, HashFor, NumberFor}, + traits::{Block as BlockT, HashFor}, + Digest, }; use sp_state_machine::StorageProof; @@ -111,8 +112,7 @@ pub struct Proposal { /// Proof that was recorded while building the block. pub proof: Proof, /// The storage changes while building this block. - pub storage_changes: - sp_state_machine::StorageChanges, NumberFor>, + pub storage_changes: sp_state_machine::StorageChanges>, } /// Error that is returned when [`ProofRecording`] requested to record a proof, @@ -224,7 +224,7 @@ pub trait Proposer { fn propose( self, inherent_data: InherentData, - inherent_digests: DigestFor, + inherent_digests: Digest, max_duration: Duration, block_size_limit: Option, ) -> Self::Proposal; diff --git a/primitives/core/src/changes_trie.rs b/primitives/core/src/changes_trie.rs deleted file mode 100644 index f4ce83dc2c87..000000000000 --- a/primitives/core/src/changes_trie.rs +++ /dev/null @@ -1,321 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2018-2021 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. - -//! Substrate changes trie configuration. - -use codec::{Decode, Encode}; -use num_traits::Zero; -#[cfg(any(feature = "std", test))] -use serde::{Deserialize, Serialize}; - -/// Substrate changes trie configuration. -#[cfg_attr( - any(feature = "std", test), - derive(Serialize, Deserialize, parity_util_mem::MallocSizeOf) -)] -#[derive(Debug, Clone, PartialEq, Eq, Default, Encode, Decode, scale_info::TypeInfo)] -pub struct ChangesTrieConfiguration { - /// Interval (in blocks) at which level1-digests are created. Digests are not - /// created when this is less or equal to 1. - pub digest_interval: u32, - /// Maximal number of digest levels in hierarchy. 0 means that digests are not - /// created at all (even level1 digests). 1 means only level1-digests are created. - /// 2 means that every digest_interval^2 there will be a level2-digest, and so on. - /// Please ensure that maximum digest interval (i.e. digest_interval^digest_levels) - /// is within `u32` limits. Otherwise you'll never see digests covering such intervals - /// && maximal digests interval will be truncated to the last interval that fits - /// `u32` limits. - pub digest_levels: u32, -} - -/// Substrate changes trie configuration range. -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct ChangesTrieConfigurationRange { - /// Zero block of configuration. - pub zero: (Number, Hash), - /// Last block of configuration (if configuration has been deactivated at some point). - pub end: Option<(Number, Hash)>, - /// The configuration itself. None if changes tries were disabled in this range. - pub config: Option, -} - -impl ChangesTrieConfiguration { - /// Create new configuration given digest interval and levels. - pub fn new(digest_interval: u32, digest_levels: u32) -> Self { - Self { digest_interval, digest_levels } - } - - /// Is digest build enabled? - pub fn is_digest_build_enabled(&self) -> bool { - self.digest_interval > 1 && self.digest_levels > 0 - } - - /// Do we need to build digest at given block? - pub fn is_digest_build_required_at_block(&self, zero: Number, block: Number) -> bool - where - Number: From - + PartialEq - + ::sp_std::ops::Rem - + ::sp_std::ops::Sub - + ::sp_std::cmp::PartialOrd - + Zero, - { - block > zero && - self.is_digest_build_enabled() && - ((block - zero) % self.digest_interval.into()).is_zero() - } - - /// Returns max digest interval. One if digests are not created at all. - pub fn max_digest_interval(&self) -> u32 { - if !self.is_digest_build_enabled() { - return 1 - } - - // we'll get >1 loop iteration only when bad configuration parameters are selected - let mut current_level = self.digest_levels; - loop { - if let Some(max_digest_interval) = self.digest_interval.checked_pow(current_level) { - return max_digest_interval - } - - current_level -= 1; - } - } - - /// Returns max level digest block number that has been created at block <= passed block number. - /// - /// Returns None if digests are not created at all. - pub fn prev_max_level_digest_block(&self, zero: Number, block: Number) -> Option - where - Number: Clone - + From - + PartialOrd - + PartialEq - + ::sp_std::ops::Add - + ::sp_std::ops::Sub - + ::sp_std::ops::Div - + ::sp_std::ops::Mul - + Zero, - { - if block <= zero { - return None - } - - let (next_begin, next_end) = - self.next_max_level_digest_range(zero.clone(), block.clone())?; - - // if 'next' digest includes our block, then it is a also a previous digest - if next_end == block { - return Some(block) - } - - // if previous digest ends at zero block, then there are no previous digest - let prev_end = next_begin - 1.into(); - if prev_end == zero { - None - } else { - Some(prev_end) - } - } - - /// Returns max level digest blocks range (inclusive) which includes passed block. - /// - /// Returns None if digests are not created at all. - /// It will return the first max-level digest if block is <= zero. - pub fn next_max_level_digest_range( - &self, - zero: Number, - mut block: Number, - ) -> Option<(Number, Number)> - where - Number: Clone - + From - + PartialOrd - + PartialEq - + ::sp_std::ops::Add - + ::sp_std::ops::Sub - + ::sp_std::ops::Div - + ::sp_std::ops::Mul, - { - if !self.is_digest_build_enabled() { - return None - } - - if block <= zero { - block = zero.clone() + 1.into(); - } - - let max_digest_interval: Number = self.max_digest_interval().into(); - let max_digests_since_zero = (block.clone() - zero.clone()) / max_digest_interval.clone(); - if max_digests_since_zero == 0.into() { - return Some((zero.clone() + 1.into(), zero + max_digest_interval)) - } - let last_max_digest_block = zero + max_digests_since_zero * max_digest_interval.clone(); - Some(if block == last_max_digest_block { - (block.clone() - max_digest_interval + 1.into(), block) - } else { - (last_max_digest_block.clone() + 1.into(), last_max_digest_block + max_digest_interval) - }) - } - - /// Returns Some if digest must be built at given block number. - /// The tuple is: - /// ( - /// digest level - /// digest interval (in blocks) - /// step between blocks we're interested in when digest is built - /// ) - pub fn digest_level_at_block( - &self, - zero: Number, - block: Number, - ) -> Option<(u32, u32, u32)> - where - Number: Clone - + From - + PartialEq - + ::sp_std::ops::Rem - + ::sp_std::ops::Sub - + ::sp_std::cmp::PartialOrd - + Zero, - { - if !self.is_digest_build_required_at_block(zero.clone(), block.clone()) { - return None - } - - let relative_block = block - zero; - let mut digest_interval = self.digest_interval; - let mut current_level = 1u32; - let mut digest_step = 1u32; - while current_level < self.digest_levels { - let new_digest_interval = match digest_interval.checked_mul(self.digest_interval) { - Some(new_digest_interval) - if (relative_block.clone() % new_digest_interval.into()).is_zero() => - new_digest_interval, - _ => break, - }; - - digest_step = digest_interval; - digest_interval = new_digest_interval; - current_level += 1; - } - - Some((current_level, digest_interval, digest_step)) - } -} - -#[cfg(test)] -mod tests { - use super::ChangesTrieConfiguration; - - fn config(interval: u32, levels: u32) -> ChangesTrieConfiguration { - ChangesTrieConfiguration { digest_interval: interval, digest_levels: levels } - } - - #[test] - fn is_digest_build_enabled_works() { - assert!(!config(0, 100).is_digest_build_enabled()); - assert!(!config(1, 100).is_digest_build_enabled()); - assert!(config(2, 100).is_digest_build_enabled()); - assert!(!config(100, 0).is_digest_build_enabled()); - assert!(config(100, 1).is_digest_build_enabled()); - } - - #[test] - fn is_digest_build_required_at_block_works() { - fn test_with_zero(zero: u64) { - assert!(!config(8, 4).is_digest_build_required_at_block(zero, zero)); - assert!(!config(8, 4).is_digest_build_required_at_block(zero, zero + 1u64)); - assert!(!config(8, 4).is_digest_build_required_at_block(zero, zero + 2u64)); - assert!(!config(8, 4).is_digest_build_required_at_block(zero, zero + 4u64)); - assert!(config(8, 4).is_digest_build_required_at_block(zero, zero + 8u64)); - assert!(!config(8, 4).is_digest_build_required_at_block(zero, zero + 9u64)); - assert!(config(8, 4).is_digest_build_required_at_block(zero, zero + 64u64)); - assert!(config(8, 4).is_digest_build_required_at_block(zero, zero + 64u64)); - assert!(config(8, 4).is_digest_build_required_at_block(zero, zero + 512u64)); - assert!(config(8, 4).is_digest_build_required_at_block(zero, zero + 4096u64)); - assert!(!config(8, 4).is_digest_build_required_at_block(zero, zero + 4103u64)); - assert!(config(8, 4).is_digest_build_required_at_block(zero, zero + 4104u64)); - assert!(!config(8, 4).is_digest_build_required_at_block(zero, zero + 4108u64)); - } - - test_with_zero(0); - test_with_zero(8); - test_with_zero(17); - } - - #[test] - fn digest_level_at_block_works() { - fn test_with_zero(zero: u64) { - assert_eq!(config(8, 4).digest_level_at_block(zero, zero), None); - assert_eq!(config(8, 4).digest_level_at_block(zero, zero + 7u64), None); - assert_eq!(config(8, 4).digest_level_at_block(zero, zero + 63u64), None); - assert_eq!(config(8, 4).digest_level_at_block(zero, zero + 8u64), Some((1, 8, 1))); - assert_eq!(config(8, 4).digest_level_at_block(zero, zero + 64u64), Some((2, 64, 8))); - assert_eq!(config(8, 4).digest_level_at_block(zero, zero + 512u64), Some((3, 512, 64))); - assert_eq!( - config(8, 4).digest_level_at_block(zero, zero + 4096u64), - Some((4, 4096, 512)) - ); - assert_eq!(config(8, 4).digest_level_at_block(zero, zero + 4112u64), Some((1, 8, 1))); - } - - test_with_zero(0); - test_with_zero(8); - test_with_zero(17); - } - - #[test] - fn max_digest_interval_works() { - assert_eq!(config(0, 0).max_digest_interval(), 1); - assert_eq!(config(2, 2).max_digest_interval(), 4); - assert_eq!(config(8, 4).max_digest_interval(), 4096); - assert_eq!(config(::std::u32::MAX, 1024).max_digest_interval(), ::std::u32::MAX); - } - - #[test] - fn next_max_level_digest_range_works() { - assert_eq!(config(0, 0).next_max_level_digest_range(0u64, 16), None); - assert_eq!(config(1, 1).next_max_level_digest_range(0u64, 16), None); - assert_eq!(config(2, 1).next_max_level_digest_range(0u64, 16), Some((15, 16))); - assert_eq!(config(4, 1).next_max_level_digest_range(0u64, 16), Some((13, 16))); - assert_eq!(config(32, 1).next_max_level_digest_range(0u64, 16), Some((1, 32))); - assert_eq!(config(2, 3).next_max_level_digest_range(0u64, 10), Some((9, 16))); - assert_eq!(config(2, 3).next_max_level_digest_range(0u64, 8), Some((1, 8))); - assert_eq!(config(2, 1).next_max_level_digest_range(1u64, 1), Some((2, 3))); - assert_eq!(config(2, 2).next_max_level_digest_range(7u64, 9), Some((8, 11))); - - assert_eq!(config(2, 2).next_max_level_digest_range(7u64, 5), Some((8, 11))); - } - - #[test] - fn prev_max_level_digest_block_works() { - assert_eq!(config(0, 0).prev_max_level_digest_block(0u64, 16), None); - assert_eq!(config(1, 1).prev_max_level_digest_block(0u64, 16), None); - assert_eq!(config(2, 1).prev_max_level_digest_block(0u64, 16), Some(16)); - assert_eq!(config(4, 1).prev_max_level_digest_block(0u64, 16), Some(16)); - assert_eq!(config(4, 2).prev_max_level_digest_block(0u64, 16), Some(16)); - assert_eq!(config(4, 2).prev_max_level_digest_block(0u64, 17), Some(16)); - assert_eq!(config(4, 2).prev_max_level_digest_block(0u64, 33), Some(32)); - assert_eq!(config(32, 1).prev_max_level_digest_block(0u64, 16), None); - assert_eq!(config(2, 3).prev_max_level_digest_block(0u64, 10), Some(8)); - assert_eq!(config(2, 3).prev_max_level_digest_block(0u64, 8), Some(8)); - assert_eq!(config(2, 2).prev_max_level_digest_block(7u64, 8), None); - - assert_eq!(config(2, 2).prev_max_level_digest_block(7u64, 5), None); - } -} diff --git a/primitives/core/src/lib.rs b/primitives/core/src/lib.rs index fd752397cd9a..3983f7cc155d 100644 --- a/primitives/core/src/lib.rs +++ b/primitives/core/src/lib.rs @@ -58,7 +58,6 @@ pub mod hexdisplay; pub mod u32_trait; -mod changes_trie; pub mod ecdsa; pub mod ed25519; pub mod hash; @@ -76,7 +75,6 @@ pub use self::{ hash::{convert_hash, H160, H256, H512}, uint::{U256, U512}, }; -pub use changes_trie::{ChangesTrieConfiguration, ChangesTrieConfigurationRange}; #[cfg(feature = "full_crypto")] pub use crypto::{DeriveJunction, Pair, Public}; diff --git a/primitives/externalities/src/lib.rs b/primitives/externalities/src/lib.rs index e6a8f8caa8d3..aac45234dead 100644 --- a/primitives/externalities/src/lib.rs +++ b/primitives/externalities/src/lib.rs @@ -173,13 +173,6 @@ pub trait Externalities: ExtensionStore { /// operation. fn storage_append(&mut self, key: Vec, value: Vec); - /// Get the changes trie root of the current storage overlay at a block with given `parent`. - /// - /// `parent` expects a SCALE encoded hash. - /// - /// The returned hash is defined by the `Block` and is SCALE encoded. - fn storage_changes_root(&mut self, parent: &[u8]) -> Result>, ()>; - /// Start a new nested transaction. /// /// This allows to either commit or roll back all changes made after this call to the diff --git a/primitives/io/src/lib.rs b/primitives/io/src/lib.rs index 78e6f0c84795..e4f52fd4e0e2 100644 --- a/primitives/io/src/lib.rs +++ b/primitives/io/src/lib.rs @@ -195,16 +195,9 @@ pub trait Storage { self.storage_root() } - /// "Commit" all existing operations and get the resulting storage change root. - /// `parent_hash` is a SCALE encoded hash. - /// - /// The hashing algorithm is defined by the `Block`. - /// - /// Returns `Some(Vec)` which holds the SCALE encoded hash or `None` when - /// changes trie is disabled. - fn changes_root(&mut self, parent_hash: &[u8]) -> Option> { - self.storage_changes_root(parent_hash) - .expect("Invalid `parent_hash` given to `changes_root`.") + /// Always returns `None`. This function exists for compatibility reasons. + fn changes_root(&mut self, _parent_hash: &[u8]) -> Option> { + None } /// Get the next key in storage after the given one in lexicographic order. @@ -1497,7 +1490,7 @@ pub fn oom(_: core::alloc::Layout) -> ! { /// Type alias for Externalities implementation used in tests. #[cfg(feature = "std")] -pub type TestExternalities = sp_state_machine::TestExternalities; +pub type TestExternalities = sp_state_machine::TestExternalities; /// The host functions Substrate provides for the Wasm runtime environment. /// diff --git a/primitives/runtime-interface/test/src/lib.rs b/primitives/runtime-interface/test/src/lib.rs index 82c50fffeb8d..1749cc485367 100644 --- a/primitives/runtime-interface/test/src/lib.rs +++ b/primitives/runtime-interface/test/src/lib.rs @@ -31,7 +31,7 @@ use std::{ sync::{Arc, Mutex}, }; -type TestExternalities = sp_state_machine::TestExternalities; +type TestExternalities = sp_state_machine::TestExternalities; fn call_wasm_method_with_result( binary: &[u8], diff --git a/primitives/runtime/src/generic/digest.rs b/primitives/runtime/src/generic/digest.rs index 87af9bc77a5f..978653efb93d 100644 --- a/primitives/runtime/src/generic/digest.rs +++ b/primitives/runtime/src/generic/digest.rs @@ -26,59 +26,49 @@ use crate::{ codec::{Decode, Encode, Error, Input}, scale_info::{ build::{Fields, Variants}, - meta_type, Path, Type, TypeInfo, TypeParameter, + Path, Type, TypeInfo, }, ConsensusEngineId, }; -use sp_core::{ChangesTrieConfiguration, RuntimeDebug}; +use sp_core::RuntimeDebug; /// Generic header digest. #[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, parity_util_mem::MallocSizeOf))] -pub struct Digest { +pub struct Digest { /// A list of logs in the digest. - #[cfg_attr( - feature = "std", - serde(bound(serialize = "Hash: codec::Codec", deserialize = "Hash: codec::Codec")) - )] - pub logs: Vec>, + pub logs: Vec, } -impl Default for Digest { +impl Default for Digest { fn default() -> Self { Self { logs: Vec::new() } } } -impl Digest { +impl Digest { /// Get reference to all digest items. - pub fn logs(&self) -> &[DigestItem] { + pub fn logs(&self) -> &[DigestItem] { &self.logs } /// Push new digest item. - pub fn push(&mut self, item: DigestItem) { + pub fn push(&mut self, item: DigestItem) { self.logs.push(item); } /// Pop a digest item. - pub fn pop(&mut self) -> Option> { + pub fn pop(&mut self) -> Option { self.logs.pop() } /// Get reference to the first digest item that matches the passed predicate. - pub fn log) -> Option<&T>>( - &self, - predicate: F, - ) -> Option<&T> { + pub fn log Option<&T>>(&self, predicate: F) -> Option<&T> { self.logs().iter().find_map(predicate) } /// Get a conversion of the first digest item that successfully converts using the function. - pub fn convert_first) -> Option>( - &self, - predicate: F, - ) -> Option { + pub fn convert_first Option>(&self, predicate: F) -> Option { self.logs().iter().find_map(predicate) } } @@ -87,12 +77,7 @@ impl Digest { /// provide opaque access to other items. #[derive(PartialEq, Eq, Clone, RuntimeDebug)] #[cfg_attr(feature = "std", derive(parity_util_mem::MallocSizeOf))] -pub enum DigestItem { - /// System digest item that contains the root of changes trie at given - /// block. It is created for every block iff runtime supports changes - /// trie creation. - ChangesTrieRoot(Hash), - +pub enum DigestItem { /// A pre-runtime digest. /// /// These are messages from the consensus engine to the runtime, although @@ -116,10 +101,6 @@ pub enum DigestItem { /// by runtimes. Seal(ConsensusEngineId, Vec), - /// Digest item that contains signal from changes tries manager to the - /// native code. - ChangesTrieSignal(ChangesTrieSignal), - /// Some other thing. Unsupported and experimental. Other(Vec), @@ -132,25 +113,8 @@ pub enum DigestItem { RuntimeEnvironmentUpdated, } -/// Available changes trie signals. -#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo)] -#[cfg_attr(feature = "std", derive(Debug, parity_util_mem::MallocSizeOf))] -pub enum ChangesTrieSignal { - /// New changes trie configuration is enacted, starting from **next block**. - /// - /// The block that emits this signal will contain changes trie (CT) that covers - /// blocks range [BEGIN; current block], where BEGIN is (order matters): - /// - LAST_TOP_LEVEL_DIGEST_BLOCK+1 if top level digest CT has ever been created using current - /// configuration AND the last top level digest CT has been created at block - /// LAST_TOP_LEVEL_DIGEST_BLOCK; - /// - LAST_CONFIGURATION_CHANGE_BLOCK+1 if there has been CT configuration change before and - /// the last configuration change happened at block LAST_CONFIGURATION_CHANGE_BLOCK; - /// - 1 otherwise. - NewConfiguration(Option), -} - #[cfg(feature = "std")] -impl serde::Serialize for DigestItem { +impl serde::Serialize for DigestItem { fn serialize(&self, seq: S) -> Result where S: serde::Serializer, @@ -160,7 +124,7 @@ impl serde::Serialize for DigestItem { } #[cfg(feature = "std")] -impl<'a, Hash: Decode> serde::Deserialize<'a> for DigestItem { +impl<'a> serde::Deserialize<'a> for DigestItem { fn deserialize(de: D) -> Result where D: serde::Deserializer<'a>, @@ -171,75 +135,48 @@ impl<'a, Hash: Decode> serde::Deserialize<'a> for DigestItem { } } -impl TypeInfo for DigestItem -where - Hash: TypeInfo + 'static, -{ +impl TypeInfo for DigestItem { type Identity = Self; fn type_info() -> Type { - Type::builder() - .path(Path::new("DigestItem", module_path!())) - .type_params(vec![TypeParameter::new("Hash", Some(meta_type::()))]) - .variant( - Variants::new() - .variant("ChangesTrieRoot", |v| { - v.index(DigestItemType::ChangesTrieRoot as u8) - .fields(Fields::unnamed().field(|f| f.ty::().type_name("Hash"))) - }) - .variant("PreRuntime", |v| { - v.index(DigestItemType::PreRuntime as u8).fields( - Fields::unnamed() - .field(|f| { - f.ty::().type_name("ConsensusEngineId") - }) - .field(|f| f.ty::>().type_name("Vec")), - ) - }) - .variant("Consensus", |v| { - v.index(DigestItemType::Consensus as u8).fields( - Fields::unnamed() - .field(|f| { - f.ty::().type_name("ConsensusEngineId") - }) - .field(|f| f.ty::>().type_name("Vec")), - ) - }) - .variant("Seal", |v| { - v.index(DigestItemType::Seal as u8).fields( - Fields::unnamed() - .field(|f| { - f.ty::().type_name("ConsensusEngineId") - }) - .field(|f| f.ty::>().type_name("Vec")), - ) - }) - .variant("ChangesTrieSignal", |v| { - v.index(DigestItemType::ChangesTrieSignal as u8).fields( - Fields::unnamed().field(|f| { - f.ty::().type_name("ChangesTrieSignal") - }), - ) - }) - .variant("Other", |v| { - v.index(DigestItemType::Other as u8).fields( - Fields::unnamed().field(|f| f.ty::>().type_name("Vec")), - ) - }) - .variant("RuntimeEnvironmentUpdated", |v| { - v.index(DigestItemType::RuntimeEnvironmentUpdated as u8) - .fields(Fields::unit()) - }), - ) + Type::builder().path(Path::new("DigestItem", module_path!())).variant( + Variants::new() + .variant("PreRuntime", |v| { + v.index(DigestItemType::PreRuntime as u8).fields( + Fields::unnamed() + .field(|f| f.ty::().type_name("ConsensusEngineId")) + .field(|f| f.ty::>().type_name("Vec")), + ) + }) + .variant("Consensus", |v| { + v.index(DigestItemType::Consensus as u8).fields( + Fields::unnamed() + .field(|f| f.ty::().type_name("ConsensusEngineId")) + .field(|f| f.ty::>().type_name("Vec")), + ) + }) + .variant("Seal", |v| { + v.index(DigestItemType::Seal as u8).fields( + Fields::unnamed() + .field(|f| f.ty::().type_name("ConsensusEngineId")) + .field(|f| f.ty::>().type_name("Vec")), + ) + }) + .variant("Other", |v| { + v.index(DigestItemType::Other as u8) + .fields(Fields::unnamed().field(|f| f.ty::>().type_name("Vec"))) + }) + .variant("RuntimeEnvironmentUpdated", |v| { + v.index(DigestItemType::RuntimeEnvironmentUpdated as u8).fields(Fields::unit()) + }), + ) } } /// A 'referencing view' for digest item. Does not own its contents. Used by /// final runtime implementations for encoding/decoding its log items. #[derive(PartialEq, Eq, Clone, RuntimeDebug)] -pub enum DigestItemRef<'a, Hash: 'a> { - /// Reference to `DigestItem::ChangesTrieRoot`. - ChangesTrieRoot(&'a Hash), +pub enum DigestItemRef<'a> { /// A pre-runtime digest. /// /// These are messages from the consensus engine to the runtime, although @@ -254,9 +191,6 @@ pub enum DigestItemRef<'a, Hash: 'a> { /// Put a Seal on it. This is only used by native code, and is never seen /// by runtimes. Seal(&'a ConsensusEngineId, &'a Vec), - /// Digest item that contains signal from changes tries manager to the - /// native code. - ChangesTrieSignal(&'a ChangesTrieSignal), /// Any 'non-system' digest item, opaque to the native code. Other(&'a Vec), /// Runtime code or heap pages updated. @@ -271,11 +205,9 @@ pub enum DigestItemRef<'a, Hash: 'a> { #[derive(Encode, Decode)] pub enum DigestItemType { Other = 0, - ChangesTrieRoot = 2, Consensus = 4, Seal = 5, PreRuntime = 6, - ChangesTrieSignal = 7, RuntimeEnvironmentUpdated = 8, } @@ -293,25 +225,18 @@ pub enum OpaqueDigestItemId<'a> { Other, } -impl DigestItem { +impl DigestItem { /// Returns a 'referencing view' for this digest item. - pub fn dref(&self) -> DigestItemRef { + pub fn dref(&self) -> DigestItemRef { match *self { - Self::ChangesTrieRoot(ref v) => DigestItemRef::ChangesTrieRoot(v), Self::PreRuntime(ref v, ref s) => DigestItemRef::PreRuntime(v, s), Self::Consensus(ref v, ref s) => DigestItemRef::Consensus(v, s), Self::Seal(ref v, ref s) => DigestItemRef::Seal(v, s), - Self::ChangesTrieSignal(ref s) => DigestItemRef::ChangesTrieSignal(s), Self::Other(ref v) => DigestItemRef::Other(v), Self::RuntimeEnvironmentUpdated => DigestItemRef::RuntimeEnvironmentUpdated, } } - /// Returns `Some` if the entry is the `ChangesTrieRoot` entry. - pub fn as_changes_trie_root(&self) -> Option<&Hash> { - self.dref().as_changes_trie_root() - } - /// Returns `Some` if this entry is the `PreRuntime` entry. pub fn as_pre_runtime(&self) -> Option<(ConsensusEngineId, &[u8])> { self.dref().as_pre_runtime() @@ -327,11 +252,6 @@ impl DigestItem { self.dref().as_seal() } - /// Returns `Some` if the entry is the `ChangesTrieSignal` entry. - pub fn as_changes_trie_signal(&self) -> Option<&ChangesTrieSignal> { - self.dref().as_changes_trie_signal() - } - /// Returns Some if `self` is a `DigestItem::Other`. pub fn as_other(&self) -> Option<&[u8]> { self.dref().as_other() @@ -372,20 +292,19 @@ impl DigestItem { } } -impl Encode for DigestItem { +impl Encode for DigestItem { fn encode(&self) -> Vec { self.dref().encode() } } -impl codec::EncodeLike for DigestItem {} +impl codec::EncodeLike for DigestItem {} -impl Decode for DigestItem { +impl Decode for DigestItem { #[allow(deprecated)] fn decode(input: &mut I) -> Result { let item_type: DigestItemType = Decode::decode(input)?; match item_type { - DigestItemType::ChangesTrieRoot => Ok(Self::ChangesTrieRoot(Decode::decode(input)?)), DigestItemType::PreRuntime => { let vals: (ConsensusEngineId, Vec) = Decode::decode(input)?; Ok(Self::PreRuntime(vals.0, vals.1)) @@ -398,23 +317,13 @@ impl Decode for DigestItem { let vals: (ConsensusEngineId, Vec) = Decode::decode(input)?; Ok(Self::Seal(vals.0, vals.1)) }, - DigestItemType::ChangesTrieSignal => - Ok(Self::ChangesTrieSignal(Decode::decode(input)?)), DigestItemType::Other => Ok(Self::Other(Decode::decode(input)?)), DigestItemType::RuntimeEnvironmentUpdated => Ok(Self::RuntimeEnvironmentUpdated), } } } -impl<'a, Hash> DigestItemRef<'a, Hash> { - /// Cast this digest item into `ChangesTrieRoot`. - pub fn as_changes_trie_root(&self) -> Option<&'a Hash> { - match *self { - Self::ChangesTrieRoot(ref changes_trie_root) => Some(changes_trie_root), - _ => None, - } - } - +impl<'a> DigestItemRef<'a> { /// Cast this digest item into `PreRuntime` pub fn as_pre_runtime(&self) -> Option<(ConsensusEngineId, &'a [u8])> { match *self { @@ -439,14 +348,6 @@ impl<'a, Hash> DigestItemRef<'a, Hash> { } } - /// Cast this digest item into `ChangesTrieSignal`. - pub fn as_changes_trie_signal(&self) -> Option<&'a ChangesTrieSignal> { - match *self { - Self::ChangesTrieSignal(ref changes_trie_signal) => Some(changes_trie_signal), - _ => None, - } - } - /// Cast this digest item into `PreRuntime` pub fn as_other(&self) -> Option<&'a [u8]> { match *self { @@ -508,15 +409,11 @@ impl<'a, Hash> DigestItemRef<'a, Hash> { } } -impl<'a, Hash: Encode> Encode for DigestItemRef<'a, Hash> { +impl<'a> Encode for DigestItemRef<'a> { fn encode(&self) -> Vec { let mut v = Vec::new(); match *self { - Self::ChangesTrieRoot(changes_trie_root) => { - DigestItemType::ChangesTrieRoot.encode_to(&mut v); - changes_trie_root.encode_to(&mut v); - }, Self::Consensus(val, data) => { DigestItemType::Consensus.encode_to(&mut v); (val, data).encode_to(&mut v); @@ -529,10 +426,6 @@ impl<'a, Hash: Encode> Encode for DigestItemRef<'a, Hash> { DigestItemType::PreRuntime.encode_to(&mut v); (val, data).encode_to(&mut v); }, - Self::ChangesTrieSignal(changes_trie_signal) => { - DigestItemType::ChangesTrieSignal.encode_to(&mut v); - changes_trie_signal.encode_to(&mut v); - }, Self::Other(val) => { DigestItemType::Other.encode_to(&mut v); val.encode_to(&mut v); @@ -546,16 +439,7 @@ impl<'a, Hash: Encode> Encode for DigestItemRef<'a, Hash> { } } -impl ChangesTrieSignal { - /// Try to cast this signal to NewConfiguration. - pub fn as_new_configuration(&self) -> Option<&Option> { - match self { - Self::NewConfiguration(config) => Some(config), - } - } -} - -impl<'a, Hash: Encode> codec::EncodeLike for DigestItemRef<'a, Hash> {} +impl<'a> codec::EncodeLike for DigestItemRef<'a> {} #[cfg(test)] mod tests { @@ -564,22 +448,18 @@ mod tests { #[test] fn should_serialize_digest() { let digest = Digest { - logs: vec![ - DigestItem::ChangesTrieRoot(4), - DigestItem::Other(vec![1, 2, 3]), - DigestItem::Seal(*b"test", vec![1, 2, 3]), - ], + logs: vec![DigestItem::Other(vec![1, 2, 3]), DigestItem::Seal(*b"test", vec![1, 2, 3])], }; assert_eq!( serde_json::to_string(&digest).unwrap(), - r#"{"logs":["0x0204000000","0x000c010203","0x05746573740c010203"]}"# + r#"{"logs":["0x000c010203","0x05746573740c010203"]}"# ); } #[test] fn digest_item_type_info() { - let type_info = DigestItem::::type_info(); + let type_info = DigestItem::type_info(); let variants = if let scale_info::TypeDef::Variant(variant) = type_info.type_def() { variant.variants() } else { @@ -589,21 +469,13 @@ mod tests { // ensure that all variants are covered by manual TypeInfo impl let check = |digest_item_type: DigestItemType| { let (variant_name, digest_item) = match digest_item_type { - DigestItemType::Other => ("Other", DigestItem::::Other(Default::default())), - DigestItemType::ChangesTrieRoot => - ("ChangesTrieRoot", DigestItem::ChangesTrieRoot(Default::default())), + DigestItemType::Other => ("Other", DigestItem::Other(Default::default())), DigestItemType::Consensus => ("Consensus", DigestItem::Consensus(Default::default(), Default::default())), DigestItemType::Seal => ("Seal", DigestItem::Seal(Default::default(), Default::default())), DigestItemType::PreRuntime => ("PreRuntime", DigestItem::PreRuntime(Default::default(), Default::default())), - DigestItemType::ChangesTrieSignal => ( - "ChangesTrieSignal", - DigestItem::ChangesTrieSignal(ChangesTrieSignal::NewConfiguration( - Default::default(), - )), - ), DigestItemType::RuntimeEnvironmentUpdated => ("RuntimeEnvironmentUpdated", DigestItem::RuntimeEnvironmentUpdated), }; @@ -617,11 +489,9 @@ mod tests { }; check(DigestItemType::Other); - check(DigestItemType::ChangesTrieRoot); check(DigestItemType::Consensus); check(DigestItemType::Seal); check(DigestItemType::PreRuntime); - check(DigestItemType::ChangesTrieSignal); check(DigestItemType::RuntimeEnvironmentUpdated); } } diff --git a/primitives/runtime/src/generic/header.rs b/primitives/runtime/src/generic/header.rs index 82f081c0d70b..21c2a6eef73a 100644 --- a/primitives/runtime/src/generic/header.rs +++ b/primitives/runtime/src/generic/header.rs @@ -51,7 +51,7 @@ pub struct Header + TryFrom, Hash: HashT> { /// The merkle root of the extrinsics. pub extrinsics_root: Hash::Output, /// A chain-specific digest of data useful for light clients or referencing auxiliary data. - pub digest: Digest, + pub digest: Digest, } #[cfg(feature = "std")] @@ -150,11 +150,11 @@ where self.parent_hash = hash } - fn digest(&self) -> &Digest { + fn digest(&self) -> &Digest { &self.digest } - fn digest_mut(&mut self) -> &mut Digest { + fn digest_mut(&mut self) -> &mut Digest { #[cfg(feature = "std")] log::debug!(target: "header", "Retrieving mutable reference to digest"); &mut self.digest @@ -165,7 +165,7 @@ where extrinsics_root: Self::Hash, state_root: Self::Hash, parent_hash: Self::Hash, - digest: Digest, + digest: Digest, ) -> Self { Self { number, extrinsics_root, state_root, parent_hash, digest } } @@ -235,10 +235,7 @@ mod tests { state_root: BlakeTwo256::hash(b"3"), extrinsics_root: BlakeTwo256::hash(b"4"), digest: crate::generic::Digest { - logs: vec![ - crate::generic::DigestItem::ChangesTrieRoot(BlakeTwo256::hash(b"5")), - crate::generic::DigestItem::Other(b"6".to_vec()), - ], + logs: vec![crate::generic::DigestItem::Other(b"6".to_vec())], }, }; @@ -251,9 +248,7 @@ mod tests { 72, 51, 123, 15, 62, 20, 134, 32, 23, 61, 170, 165, 249, 77, 0, 216, 129, 112, 93, 203, 240, 170, 131, 239, 218, 186, 97, 210, 237, 225, 235, 134, 73, 33, 73, 151, 87, 78, 32, 196, 100, 56, 138, 23, 36, 32, 210, 84, 3, 104, 43, 187, 184, 12, 73, - 104, 49, 200, 204, 31, 143, 13, 8, 2, 112, 178, 1, 53, 47, 36, 191, 28, 151, 112, - 185, 159, 143, 113, 32, 24, 33, 65, 28, 244, 20, 55, 124, 155, 140, 45, 188, 238, - 97, 219, 135, 214, 0, 4, 54 + 104, 49, 200, 204, 31, 143, 13, 4, 0, 4, 54 ], ); assert_eq!(header, Header::::decode(&mut &header_encoded[..]).unwrap()); @@ -264,10 +259,7 @@ mod tests { state_root: BlakeTwo256::hash(b"3000"), extrinsics_root: BlakeTwo256::hash(b"4000"), digest: crate::generic::Digest { - logs: vec![ - crate::generic::DigestItem::Other(b"5000".to_vec()), - crate::generic::DigestItem::ChangesTrieRoot(BlakeTwo256::hash(b"6000")), - ], + logs: vec![crate::generic::DigestItem::Other(b"5000".to_vec())], }, }; @@ -280,9 +272,7 @@ mod tests { 47, 12, 107, 88, 153, 146, 55, 21, 226, 186, 110, 48, 167, 187, 67, 183, 228, 232, 118, 136, 30, 254, 11, 87, 48, 112, 7, 97, 31, 82, 146, 110, 96, 87, 152, 68, 98, 162, 227, 222, 78, 14, 244, 194, 120, 154, 112, 97, 222, 144, 174, 101, 220, 44, - 111, 126, 54, 34, 155, 220, 253, 124, 8, 0, 16, 53, 48, 48, 48, 2, 42, 105, 109, - 150, 206, 223, 24, 44, 164, 77, 27, 137, 177, 220, 25, 170, 140, 35, 156, 246, 233, - 112, 26, 23, 192, 61, 226, 14, 84, 219, 144, 252 + 111, 126, 54, 34, 155, 220, 253, 124, 4, 0, 16, 53, 48, 48, 48 ], ); assert_eq!(header, Header::::decode(&mut &header_encoded[..]).unwrap()); diff --git a/primitives/runtime/src/generic/mod.rs b/primitives/runtime/src/generic/mod.rs index 71127e88ec32..3d8e8a0ce7fa 100644 --- a/primitives/runtime/src/generic/mod.rs +++ b/primitives/runtime/src/generic/mod.rs @@ -31,7 +31,7 @@ mod unchecked_extrinsic; pub use self::{ block::{Block, BlockId, SignedBlock}, checked_extrinsic::CheckedExtrinsic, - digest::{ChangesTrieSignal, Digest, DigestItem, DigestItemRef, OpaqueDigestItemId}, + digest::{Digest, DigestItem, DigestItemRef, OpaqueDigestItemId}, era::{Era, Phase}, header::Header, unchecked_extrinsic::{SignedPayload, UncheckedExtrinsic}, diff --git a/primitives/runtime/src/generic/tests.rs b/primitives/runtime/src/generic/tests.rs index 095bcb717bb1..a65e212bf07e 100644 --- a/primitives/runtime/src/generic/tests.rs +++ b/primitives/runtime/src/generic/tests.rs @@ -19,29 +19,26 @@ use super::DigestItem; use crate::codec::{Decode, Encode}; -use sp_core::H256; #[test] fn system_digest_item_encoding() { - let item = DigestItem::ChangesTrieRoot::(H256::default()); + let item = DigestItem::Consensus([1, 2, 3, 4], vec![5, 6, 7, 8]); let encoded = item.encode(); assert_eq!( encoded, vec![ - // type = DigestItemType::ChangesTrieRoot - 2, // trie root - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, + 4, // type = DigestItemType::Consensus + 1, 2, 3, 4, 16, 5, 6, 7, 8, ] ); - let decoded: DigestItem = Decode::decode(&mut &encoded[..]).unwrap(); + let decoded: DigestItem = Decode::decode(&mut &encoded[..]).unwrap(); assert_eq!(item, decoded); } #[test] fn non_system_digest_item_encoding() { - let item = DigestItem::Other::(vec![10, 20, 30]); + let item = DigestItem::Other(vec![10, 20, 30]); let encoded = item.encode(); assert_eq!( encoded, @@ -53,6 +50,6 @@ fn non_system_digest_item_encoding() { ] ); - let decoded: DigestItem = Decode::decode(&mut &encoded[..]).unwrap(); + let decoded: DigestItem = Decode::decode(&mut &encoded[..]).unwrap(); assert_eq!(item, decoded); } diff --git a/primitives/runtime/src/testing.rs b/primitives/runtime/src/testing.rs index fe9ba588adb8..4573bc84473a 100644 --- a/primitives/runtime/src/testing.rs +++ b/primitives/runtime/src/testing.rs @@ -182,10 +182,10 @@ impl traits::Verify for TestSignature { } /// Digest item -pub type DigestItem = generic::DigestItem; +pub type DigestItem = generic::DigestItem; /// Header Digest -pub type Digest = generic::Digest; +pub type Digest = generic::Digest; /// Block Header pub type Header = generic::Header; diff --git a/primitives/runtime/src/traits.rs b/primitives/runtime/src/traits.rs index 6d79d740dc4e..f61de70e3519 100644 --- a/primitives/runtime/src/traits.rs +++ b/primitives/runtime/src/traits.rs @@ -19,7 +19,7 @@ use crate::{ codec::{Codec, Decode, Encode, MaxEncodedLen}, - generic::{Digest, DigestItem}, + generic::Digest, scale_info::{MetaType, StaticTypeInfo, TypeInfo}, transaction_validity::{ TransactionSource, TransactionValidity, TransactionValidityError, UnknownTransaction, @@ -548,10 +548,7 @@ impl CheckEqual for sp_core::H256 { } } -impl CheckEqual for super::generic::DigestItem -where - H: Encode, -{ +impl CheckEqual for super::generic::DigestItem { #[cfg(feature = "std")] fn check_equal(&self, other: &Self) { if self != other { @@ -642,7 +639,7 @@ pub trait Header: extrinsics_root: Self::Hash, state_root: Self::Hash, parent_hash: Self::Hash, - digest: Digest, + digest: Digest, ) -> Self; /// Returns a reference to the header number. @@ -666,9 +663,9 @@ pub trait Header: fn set_parent_hash(&mut self, hash: Self::Hash); /// Returns a reference to the digest. - fn digest(&self) -> &Digest; + fn digest(&self) -> &Digest; /// Get a mutable reference to the digest. - fn digest_mut(&mut self) -> &mut Digest; + fn digest_mut(&mut self) -> &mut Digest; /// Returns the hash of the header. fn hash(&self) -> Self::Hash { @@ -763,9 +760,6 @@ pub type HashFor = <::Header as Header>::Hashing; /// Extract the number type for a block. pub type NumberFor = <::Header as Header>::Number; /// Extract the digest type for a block. -pub type DigestFor = Digest<<::Header as Header>::Hash>; -/// Extract the digest item type for a block. -pub type DigestItemFor = DigestItem<<::Header as Header>::Hash>; /// A "checkable" piece of information, used by the standard Substrate Executive in order to /// check the validity of a piece of extrinsic information, usually by verifying the signature. diff --git a/primitives/state-machine/src/backend.rs b/primitives/state-machine/src/backend.rs index 7dcf92b06de0..eb6e2939b83f 100644 --- a/primitives/state-machine/src/backend.rs +++ b/primitives/state-machine/src/backend.rs @@ -292,32 +292,6 @@ impl> Consolidate for sp_trie::GenericMem } } -/// Insert input pairs into memory db. -#[cfg(test)] -pub(crate) fn insert_into_memory_db( - mdb: &mut sp_trie::MemoryDB, - input: I, -) -> Option -where - H: Hasher, - I: IntoIterator, -{ - use sp_trie::{trie_types::TrieDBMut, TrieMut}; - - let mut root = ::Out::default(); - { - let mut trie = TrieDBMut::::new(mdb, &mut root); - for (key, value) in input { - if let Err(e) = trie.insert(&key, &value) { - log::warn!(target: "trie", "Failed to write to trie: {}", e); - return None - } - } - } - - Some(root) -} - /// Wrapper to create a [`RuntimeCode`] from a type that implements [`Backend`]. #[cfg(feature = "std")] pub struct BackendRuntimeCode<'a, B, H> { diff --git a/primitives/state-machine/src/basic.rs b/primitives/state-machine/src/basic.rs index 0bbd2d0a8e8e..3774adc5b036 100644 --- a/primitives/state-machine/src/basic.rs +++ b/primitives/state-machine/src/basic.rs @@ -309,10 +309,6 @@ impl Externalities for BasicExternalities { .encode() } - fn storage_changes_root(&mut self, _parent: &[u8]) -> Result>, ()> { - Ok(None) - } - fn storage_start_transaction(&mut self) { unimplemented!("Transactions are not supported by BasicExternalities"); } diff --git a/primitives/state-machine/src/changes_trie/build.rs b/primitives/state-machine/src/changes_trie/build.rs deleted file mode 100644 index d3c6c12122c4..000000000000 --- a/primitives/state-machine/src/changes_trie/build.rs +++ /dev/null @@ -1,1083 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2017-2021 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. - -//! Structures and functions required to build changes trie for given block. - -use crate::{ - backend::Backend, - changes_trie::{ - build_iterator::digest_build_iterator, - input::{ChildIndex, DigestIndex, ExtrinsicIndex, InputKey, InputPair}, - AnchorBlockId, BlockNumber, ConfigurationRange, Storage, - }, - overlayed_changes::{OverlayedChanges, OverlayedValue}, - trie_backend_essence::TrieBackendEssence, - StorageKey, -}; -use codec::{Decode, Encode}; -use hash_db::Hasher; -use num_traits::One; -use sp_core::storage::{ChildInfo, PrefixedStorageKey}; -use std::collections::{btree_map::Entry, BTreeMap}; - -/// Prepare input pairs for building a changes trie of given block. -/// -/// Returns Err if storage error has occurred OR if storage haven't returned -/// required data. -pub(crate) fn prepare_input<'a, B, H, Number>( - backend: &'a B, - storage: &'a dyn Storage, - config: ConfigurationRange<'a, Number>, - overlay: &'a OverlayedChanges, - parent: &'a AnchorBlockId, -) -> Result< - ( - impl Iterator> + 'a, - Vec<(ChildIndex, impl Iterator> + 'a)>, - Vec, - ), - String, -> -where - B: Backend, - H: Hasher + 'a, - H::Out: Encode, - Number: BlockNumber, -{ - let number = parent.number.clone() + One::one(); - let (extrinsics_input, children_extrinsics_input) = - prepare_extrinsics_input(backend, &number, overlay)?; - let (digest_input, mut children_digest_input, digest_input_blocks) = - prepare_digest_input::(parent, config, number, storage)?; - - let mut children_digest = Vec::with_capacity(children_extrinsics_input.len()); - for (child_index, ext_iter) in children_extrinsics_input.into_iter() { - let dig_iter = children_digest_input.remove(&child_index); - children_digest.push(( - child_index, - Some(ext_iter).into_iter().flatten().chain(dig_iter.into_iter().flatten()), - )); - } - for (child_index, dig_iter) in children_digest_input.into_iter() { - children_digest.push(( - child_index, - None.into_iter().flatten().chain(Some(dig_iter).into_iter().flatten()), - )); - } - - Ok((extrinsics_input.chain(digest_input), children_digest, digest_input_blocks)) -} -/// Prepare ExtrinsicIndex input pairs. -fn prepare_extrinsics_input<'a, B, H, Number>( - backend: &'a B, - block: &Number, - overlay: &'a OverlayedChanges, -) -> Result< - ( - impl Iterator> + 'a, - BTreeMap, impl Iterator> + 'a>, - ), - String, -> -where - B: Backend, - H: Hasher + 'a, - Number: BlockNumber, -{ - let mut children_result = BTreeMap::new(); - - for (child_changes, child_info) in overlay.children() { - let child_index = ChildIndex:: { - block: block.clone(), - storage_key: child_info.prefixed_storage_key(), - }; - - let iter = prepare_extrinsics_input_inner( - backend, - block, - overlay, - Some(child_info.clone()), - child_changes, - )?; - children_result.insert(child_index, iter); - } - - let top = prepare_extrinsics_input_inner(backend, block, overlay, None, overlay.changes())?; - - Ok((top, children_result)) -} - -fn prepare_extrinsics_input_inner<'a, B, H, Number>( - backend: &'a B, - block: &Number, - overlay: &'a OverlayedChanges, - child_info: Option, - changes: impl Iterator, -) -> Result> + 'a, String> -where - B: Backend, - H: Hasher, - Number: BlockNumber, -{ - changes - .filter_map(|(k, v)| { - let extrinsics = v.extrinsics(); - if !extrinsics.is_empty() { - Some((k, extrinsics)) - } else { - None - } - }) - .try_fold( - BTreeMap::new(), - |mut map: BTreeMap<&[u8], (ExtrinsicIndex, Vec)>, (k, extrinsics)| { - match map.entry(k) { - Entry::Vacant(entry) => { - // ignore temporary values (values that have null value at the end of - // operation AND are not in storage at the beginning of operation - if let Some(child_info) = child_info.as_ref() { - if !overlay - .child_storage(child_info, k) - .map(|v| v.is_some()) - .unwrap_or_default() - { - if !backend - .exists_child_storage(&child_info, k) - .map_err(|e| format!("{}", e))? - { - return Ok(map) - } - } - } else { - if !overlay.storage(k).map(|v| v.is_some()).unwrap_or_default() { - if !backend.exists_storage(k).map_err(|e| format!("{}", e))? { - return Ok(map) - } - } - }; - - let extrinsics = extrinsics.into_iter().collect(); - entry.insert(( - ExtrinsicIndex { block: block.clone(), key: k.to_vec() }, - extrinsics, - )); - }, - Entry::Occupied(mut entry) => { - // we do not need to check for temporary values here, because entry is - // Occupied AND we are checking it before insertion - let entry_extrinsics = &mut entry.get_mut().1; - entry_extrinsics.extend(extrinsics.into_iter()); - entry_extrinsics.sort(); - }, - } - - Ok(map) - }, - ) - .map(|pairs| pairs.into_iter().map(|(_, (k, v))| InputPair::ExtrinsicIndex(k, v))) -} - -/// Prepare DigestIndex input pairs. -fn prepare_digest_input<'a, H, Number>( - parent: &'a AnchorBlockId, - config: ConfigurationRange, - block: Number, - storage: &'a dyn Storage, -) -> Result< - ( - impl Iterator> + 'a, - BTreeMap, impl Iterator> + 'a>, - Vec, - ), - String, -> -where - H: Hasher, - H::Out: 'a + Encode, - Number: BlockNumber, -{ - let build_skewed_digest = config.end.as_ref() == Some(&block); - let block_for_digest = if build_skewed_digest { - config - .config - .next_max_level_digest_range(config.zero.clone(), block.clone()) - .map(|(_, end)| end) - .unwrap_or_else(|| block.clone()) - } else { - block.clone() - }; - - let digest_input_blocks = digest_build_iterator(config, block_for_digest).collect::>(); - digest_input_blocks - .clone() - .into_iter() - .try_fold( - (BTreeMap::new(), BTreeMap::new()), - move |(mut map, mut child_map), digest_build_block| { - let extrinsic_prefix = - ExtrinsicIndex::key_neutral_prefix(digest_build_block.clone()); - let digest_prefix = DigestIndex::key_neutral_prefix(digest_build_block.clone()); - let child_prefix = ChildIndex::key_neutral_prefix(digest_build_block.clone()); - let trie_root = storage.root(parent, digest_build_block.clone())?; - let trie_root = trie_root.ok_or_else(|| { - format!("No changes trie root for block {}", digest_build_block.clone()) - })?; - - let insert_to_map = |map: &mut BTreeMap<_, _>, key: StorageKey| { - match map.entry(key.clone()) { - Entry::Vacant(entry) => { - entry.insert(( - DigestIndex { block: block.clone(), key }, - vec![digest_build_block.clone()], - )); - }, - Entry::Occupied(mut entry) => { - // DigestIndexValue must be sorted. Here we are relying on the fact that - // digest_build_iterator() returns blocks in ascending order => we only - // need to check for duplicates - // - // is_dup_block could be true when key has been changed in both digest - // block AND other blocks that it covers - let is_dup_block = entry.get().1.last() == Some(&digest_build_block); - if !is_dup_block { - entry.get_mut().1.push(digest_build_block.clone()); - } - }, - } - }; - - // try to get all updated keys from cache - let populated_from_cache = - storage.with_cached_changed_keys(&trie_root, &mut |changed_keys| { - for (storage_key, changed_keys) in changed_keys { - let map = match storage_key { - Some(storage_key) => child_map - .entry(ChildIndex:: { - block: block.clone(), - storage_key: storage_key.clone(), - }) - .or_default(), - None => &mut map, - }; - for changed_key in changed_keys.iter().cloned() { - insert_to_map(map, changed_key); - } - } - }); - if populated_from_cache { - return Ok((map, child_map)) - } - - let mut children_roots = BTreeMap::::new(); - { - let trie_storage = TrieBackendEssence::<_, H>::new( - crate::changes_trie::TrieBackendStorageAdapter(storage), - trie_root, - ); - - trie_storage.for_key_values_with_prefix(&child_prefix, |mut key, mut value| { - if let Ok(InputKey::ChildIndex::(trie_key)) = - Decode::decode(&mut key) - { - if let Ok(value) = >::decode(&mut value) { - let mut trie_root = ::Out::default(); - trie_root.as_mut().copy_from_slice(&value[..]); - children_roots.insert(trie_key.storage_key, trie_root); - } - } - }); - - trie_storage.for_keys_with_prefix(&extrinsic_prefix, |mut key| { - if let Ok(InputKey::ExtrinsicIndex::(trie_key)) = - Decode::decode(&mut key) - { - insert_to_map(&mut map, trie_key.key); - } - }); - - trie_storage.for_keys_with_prefix(&digest_prefix, |mut key| { - if let Ok(InputKey::DigestIndex::(trie_key)) = - Decode::decode(&mut key) - { - insert_to_map(&mut map, trie_key.key); - } - }); - } - - for (storage_key, trie_root) in children_roots.into_iter() { - let child_index = ChildIndex:: { block: block.clone(), storage_key }; - - let mut map = child_map.entry(child_index).or_default(); - let trie_storage = TrieBackendEssence::<_, H>::new( - crate::changes_trie::TrieBackendStorageAdapter(storage), - trie_root, - ); - trie_storage.for_keys_with_prefix(&extrinsic_prefix, |mut key| { - if let Ok(InputKey::ExtrinsicIndex::(trie_key)) = - Decode::decode(&mut key) - { - insert_to_map(&mut map, trie_key.key); - } - }); - - trie_storage.for_keys_with_prefix(&digest_prefix, |mut key| { - if let Ok(InputKey::DigestIndex::(trie_key)) = - Decode::decode(&mut key) - { - insert_to_map(&mut map, trie_key.key); - } - }); - } - Ok((map, child_map)) - }, - ) - .map(|(pairs, child_pairs)| { - ( - pairs.into_iter().map(|(_, (k, v))| InputPair::DigestIndex(k, v)), - child_pairs - .into_iter() - .map(|(sk, pairs)| { - (sk, pairs.into_iter().map(|(_, (k, v))| InputPair::DigestIndex(k, v))) - }) - .collect(), - digest_input_blocks, - ) - }) -} - -#[cfg(test)] -mod test { - use super::*; - use crate::{ - changes_trie::{ - build_cache::{IncompleteCacheAction, IncompleteCachedBuildData}, - storage::InMemoryStorage, - Configuration, RootsStorage, - }, - InMemoryBackend, - }; - use sp_core::Blake2Hasher; - - fn prepare_for_build( - zero: u64, - ) -> ( - InMemoryBackend, - InMemoryStorage, - OverlayedChanges, - Configuration, - ) { - let child_info_1 = ChildInfo::new_default(b"storage_key1"); - let child_info_2 = ChildInfo::new_default(b"storage_key2"); - let backend: InMemoryBackend<_> = vec![ - (vec![100], vec![255]), - (vec![101], vec![255]), - (vec![102], vec![255]), - (vec![103], vec![255]), - (vec![104], vec![255]), - (vec![105], vec![255]), - ] - .into_iter() - .collect::>() - .into(); - let prefixed_child_trie_key1 = child_info_1.prefixed_storage_key(); - let storage = InMemoryStorage::with_inputs( - vec![ - ( - zero + 1, - vec![ - InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 1, key: vec![100] }, - vec![1, 3], - ), - InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 1, key: vec![101] }, - vec![0, 2], - ), - InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 1, key: vec![105] }, - vec![0, 2, 4], - ), - ], - ), - ( - zero + 2, - vec![InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 2, key: vec![102] }, - vec![0], - )], - ), - ( - zero + 3, - vec![ - InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 3, key: vec![100] }, - vec![0], - ), - InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 3, key: vec![105] }, - vec![1], - ), - ], - ), - ( - zero + 4, - vec![ - InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 4, key: vec![100] }, - vec![0, 2, 3], - ), - InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 4, key: vec![101] }, - vec![1], - ), - InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 4, key: vec![103] }, - vec![0, 1], - ), - InputPair::DigestIndex( - DigestIndex { block: zero + 4, key: vec![100] }, - vec![zero + 1, zero + 3], - ), - InputPair::DigestIndex( - DigestIndex { block: zero + 4, key: vec![101] }, - vec![zero + 1], - ), - InputPair::DigestIndex( - DigestIndex { block: zero + 4, key: vec![102] }, - vec![zero + 2], - ), - InputPair::DigestIndex( - DigestIndex { block: zero + 4, key: vec![105] }, - vec![zero + 1, zero + 3], - ), - ], - ), - (zero + 5, Vec::new()), - ( - zero + 6, - vec![InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 6, key: vec![105] }, - vec![2], - )], - ), - (zero + 7, Vec::new()), - ( - zero + 8, - vec![InputPair::DigestIndex( - DigestIndex { block: zero + 8, key: vec![105] }, - vec![zero + 6], - )], - ), - (zero + 9, Vec::new()), - (zero + 10, Vec::new()), - (zero + 11, Vec::new()), - (zero + 12, Vec::new()), - (zero + 13, Vec::new()), - (zero + 14, Vec::new()), - (zero + 15, Vec::new()), - ], - vec![( - prefixed_child_trie_key1.clone(), - vec![ - ( - zero + 1, - vec![ - InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 1, key: vec![100] }, - vec![1, 3], - ), - InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 1, key: vec![101] }, - vec![0, 2], - ), - InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 1, key: vec![105] }, - vec![0, 2, 4], - ), - ], - ), - ( - zero + 2, - vec![InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 2, key: vec![102] }, - vec![0], - )], - ), - ( - zero + 4, - vec![ - InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 2, key: vec![102] }, - vec![0, 3], - ), - InputPair::DigestIndex( - DigestIndex { block: zero + 4, key: vec![102] }, - vec![zero + 2], - ), - ], - ), - ], - )], - ); - - let mut changes = OverlayedChanges::default(); - changes.set_collect_extrinsics(true); - - changes.start_transaction(); - - changes.set_extrinsic_index(1); - changes.set_storage(vec![101], Some(vec![203])); - - changes.set_extrinsic_index(3); - changes.set_storage(vec![100], Some(vec![202])); - changes.set_child_storage(&child_info_1, vec![100], Some(vec![202])); - - changes.commit_transaction().unwrap(); - - changes.set_extrinsic_index(0); - changes.set_storage(vec![100], Some(vec![0])); - changes.set_extrinsic_index(2); - changes.set_storage(vec![100], Some(vec![200])); - - changes.set_extrinsic_index(0); - changes.set_storage(vec![103], Some(vec![0])); - changes.set_extrinsic_index(1); - changes.set_storage(vec![103], None); - - changes.set_extrinsic_index(0); - changes.set_child_storage(&child_info_1, vec![100], Some(vec![0])); - changes.set_extrinsic_index(2); - changes.set_child_storage(&child_info_1, vec![100], Some(vec![200])); - - changes.set_extrinsic_index(0); - changes.set_child_storage(&child_info_2, vec![100], Some(vec![0])); - changes.set_extrinsic_index(2); - changes.set_child_storage(&child_info_2, vec![100], Some(vec![200])); - - changes.set_extrinsic_index(1); - - let config = Configuration { digest_interval: 4, digest_levels: 2 }; - - (backend, storage, changes, config) - } - - fn configuration_range<'a>( - config: &'a Configuration, - zero: u64, - ) -> ConfigurationRange<'a, u64> { - ConfigurationRange { config, zero, end: None } - } - - #[test] - fn build_changes_trie_nodes_on_non_digest_block() { - fn test_with_zero(zero: u64) { - let child_trie_key1 = ChildInfo::new_default(b"storage_key1").prefixed_storage_key(); - let child_trie_key2 = ChildInfo::new_default(b"storage_key2").prefixed_storage_key(); - let (backend, storage, changes, config) = prepare_for_build(zero); - let parent = AnchorBlockId { hash: Default::default(), number: zero + 4 }; - let changes_trie_nodes = prepare_input( - &backend, - &storage, - configuration_range(&config, zero), - &changes, - &parent, - ) - .unwrap(); - assert_eq!( - changes_trie_nodes.0.collect::>>(), - vec![ - InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 5, key: vec![100] }, - vec![0, 2, 3] - ), - InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 5, key: vec![101] }, - vec![1] - ), - InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 5, key: vec![103] }, - vec![0, 1] - ), - ] - ); - assert_eq!( - changes_trie_nodes - .1 - .into_iter() - .map(|(k, v)| (k, v.collect::>())) - .collect::>(), - vec![ - ( - ChildIndex { block: zero + 5u64, storage_key: child_trie_key1 }, - vec![InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 5u64, key: vec![100] }, - vec![0, 2, 3] - ),] - ), - ( - ChildIndex { block: zero + 5, storage_key: child_trie_key2 }, - vec![InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 5, key: vec![100] }, - vec![0, 2] - ),] - ), - ] - ); - } - - test_with_zero(0); - test_with_zero(16); - test_with_zero(17); - } - - #[test] - fn build_changes_trie_nodes_on_digest_block_l1() { - fn test_with_zero(zero: u64) { - let child_trie_key1 = ChildInfo::new_default(b"storage_key1").prefixed_storage_key(); - let child_trie_key2 = ChildInfo::new_default(b"storage_key2").prefixed_storage_key(); - let (backend, storage, changes, config) = prepare_for_build(zero); - let parent = AnchorBlockId { hash: Default::default(), number: zero + 3 }; - let changes_trie_nodes = prepare_input( - &backend, - &storage, - configuration_range(&config, zero), - &changes, - &parent, - ) - .unwrap(); - assert_eq!( - changes_trie_nodes.0.collect::>>(), - vec![ - InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 4, key: vec![100] }, - vec![0, 2, 3] - ), - InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 4, key: vec![101] }, - vec![1] - ), - InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 4, key: vec![103] }, - vec![0, 1] - ), - InputPair::DigestIndex( - DigestIndex { block: zero + 4, key: vec![100] }, - vec![zero + 1, zero + 3] - ), - InputPair::DigestIndex( - DigestIndex { block: zero + 4, key: vec![101] }, - vec![zero + 1] - ), - InputPair::DigestIndex( - DigestIndex { block: zero + 4, key: vec![102] }, - vec![zero + 2] - ), - InputPair::DigestIndex( - DigestIndex { block: zero + 4, key: vec![105] }, - vec![zero + 1, zero + 3] - ), - ] - ); - assert_eq!( - changes_trie_nodes - .1 - .into_iter() - .map(|(k, v)| (k, v.collect::>())) - .collect::>(), - vec![ - ( - ChildIndex { block: zero + 4u64, storage_key: child_trie_key1.clone() }, - vec![ - InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 4u64, key: vec![100] }, - vec![0, 2, 3] - ), - InputPair::DigestIndex( - DigestIndex { block: zero + 4, key: vec![100] }, - vec![zero + 1] - ), - InputPair::DigestIndex( - DigestIndex { block: zero + 4, key: vec![101] }, - vec![zero + 1] - ), - InputPair::DigestIndex( - DigestIndex { block: zero + 4, key: vec![102] }, - vec![zero + 2] - ), - InputPair::DigestIndex( - DigestIndex { block: zero + 4, key: vec![105] }, - vec![zero + 1] - ), - ] - ), - ( - ChildIndex { block: zero + 4, storage_key: child_trie_key2.clone() }, - vec![InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 4, key: vec![100] }, - vec![0, 2] - ),] - ), - ] - ); - } - - test_with_zero(0); - test_with_zero(16); - test_with_zero(17); - } - - #[test] - fn build_changes_trie_nodes_on_digest_block_l2() { - fn test_with_zero(zero: u64) { - let child_trie_key1 = ChildInfo::new_default(b"storage_key1").prefixed_storage_key(); - let child_trie_key2 = ChildInfo::new_default(b"storage_key2").prefixed_storage_key(); - let (backend, storage, changes, config) = prepare_for_build(zero); - let parent = AnchorBlockId { hash: Default::default(), number: zero + 15 }; - let changes_trie_nodes = prepare_input( - &backend, - &storage, - configuration_range(&config, zero), - &changes, - &parent, - ) - .unwrap(); - assert_eq!( - changes_trie_nodes.0.collect::>>(), - vec![ - InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 16, key: vec![100] }, - vec![0, 2, 3] - ), - InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 16, key: vec![101] }, - vec![1] - ), - InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 16, key: vec![103] }, - vec![0, 1] - ), - InputPair::DigestIndex( - DigestIndex { block: zero + 16, key: vec![100] }, - vec![zero + 4] - ), - InputPair::DigestIndex( - DigestIndex { block: zero + 16, key: vec![101] }, - vec![zero + 4] - ), - InputPair::DigestIndex( - DigestIndex { block: zero + 16, key: vec![102] }, - vec![zero + 4] - ), - InputPair::DigestIndex( - DigestIndex { block: zero + 16, key: vec![103] }, - vec![zero + 4] - ), - InputPair::DigestIndex( - DigestIndex { block: zero + 16, key: vec![105] }, - vec![zero + 4, zero + 8] - ), - ] - ); - assert_eq!( - changes_trie_nodes - .1 - .into_iter() - .map(|(k, v)| (k, v.collect::>())) - .collect::>(), - vec![ - ( - ChildIndex { block: zero + 16u64, storage_key: child_trie_key1.clone() }, - vec![ - InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 16u64, key: vec![100] }, - vec![0, 2, 3] - ), - InputPair::DigestIndex( - DigestIndex { block: zero + 16, key: vec![102] }, - vec![zero + 4] - ), - ] - ), - ( - ChildIndex { block: zero + 16, storage_key: child_trie_key2.clone() }, - vec![InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 16, key: vec![100] }, - vec![0, 2] - ),] - ), - ] - ); - } - - test_with_zero(0); - test_with_zero(16); - test_with_zero(17); - } - - #[test] - fn build_changes_trie_nodes_on_skewed_digest_block() { - fn test_with_zero(zero: u64) { - let (backend, storage, changes, config) = prepare_for_build(zero); - let parent = AnchorBlockId { hash: Default::default(), number: zero + 10 }; - - let mut configuration_range = configuration_range(&config, zero); - let changes_trie_nodes = - prepare_input(&backend, &storage, configuration_range.clone(), &changes, &parent) - .unwrap(); - assert_eq!( - changes_trie_nodes.0.collect::>>(), - vec![ - InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 11, key: vec![100] }, - vec![0, 2, 3] - ), - InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 11, key: vec![101] }, - vec![1] - ), - InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 11, key: vec![103] }, - vec![0, 1] - ), - ] - ); - - configuration_range.end = Some(zero + 11); - let changes_trie_nodes = - prepare_input(&backend, &storage, configuration_range, &changes, &parent).unwrap(); - assert_eq!( - changes_trie_nodes.0.collect::>>(), - vec![ - InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 11, key: vec![100] }, - vec![0, 2, 3] - ), - InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 11, key: vec![101] }, - vec![1] - ), - InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 11, key: vec![103] }, - vec![0, 1] - ), - InputPair::DigestIndex( - DigestIndex { block: zero + 11, key: vec![100] }, - vec![zero + 4] - ), - InputPair::DigestIndex( - DigestIndex { block: zero + 11, key: vec![101] }, - vec![zero + 4] - ), - InputPair::DigestIndex( - DigestIndex { block: zero + 11, key: vec![102] }, - vec![zero + 4] - ), - InputPair::DigestIndex( - DigestIndex { block: zero + 11, key: vec![103] }, - vec![zero + 4] - ), - InputPair::DigestIndex( - DigestIndex { block: zero + 11, key: vec![105] }, - vec![zero + 4, zero + 8] - ), - ] - ); - } - - test_with_zero(0); - test_with_zero(16); - test_with_zero(17); - } - - #[test] - fn build_changes_trie_nodes_ignores_temporary_storage_values() { - fn test_with_zero(zero: u64) { - let child_trie_key1 = ChildInfo::new_default(b"storage_key1").prefixed_storage_key(); - let child_trie_key2 = ChildInfo::new_default(b"storage_key2").prefixed_storage_key(); - let (backend, storage, mut changes, config) = prepare_for_build(zero); - - // 110: missing from backend, set to None in overlay - changes.set_storage(vec![110], None); - - let parent = AnchorBlockId { hash: Default::default(), number: zero + 3 }; - let changes_trie_nodes = prepare_input( - &backend, - &storage, - configuration_range(&config, zero), - &changes, - &parent, - ) - .unwrap(); - assert_eq!( - changes_trie_nodes.0.collect::>>(), - vec![ - InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 4, key: vec![100] }, - vec![0, 2, 3] - ), - InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 4, key: vec![101] }, - vec![1] - ), - InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 4, key: vec![103] }, - vec![0, 1] - ), - InputPair::DigestIndex( - DigestIndex { block: zero + 4, key: vec![100] }, - vec![zero + 1, zero + 3] - ), - InputPair::DigestIndex( - DigestIndex { block: zero + 4, key: vec![101] }, - vec![zero + 1] - ), - InputPair::DigestIndex( - DigestIndex { block: zero + 4, key: vec![102] }, - vec![zero + 2] - ), - InputPair::DigestIndex( - DigestIndex { block: zero + 4, key: vec![105] }, - vec![zero + 1, zero + 3] - ), - ] - ); - assert_eq!( - changes_trie_nodes - .1 - .into_iter() - .map(|(k, v)| (k, v.collect::>())) - .collect::>(), - vec![ - ( - ChildIndex { block: zero + 4u64, storage_key: child_trie_key1.clone() }, - vec![ - InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 4u64, key: vec![100] }, - vec![0, 2, 3] - ), - InputPair::DigestIndex( - DigestIndex { block: zero + 4, key: vec![100] }, - vec![zero + 1] - ), - InputPair::DigestIndex( - DigestIndex { block: zero + 4, key: vec![101] }, - vec![zero + 1] - ), - InputPair::DigestIndex( - DigestIndex { block: zero + 4, key: vec![102] }, - vec![zero + 2] - ), - InputPair::DigestIndex( - DigestIndex { block: zero + 4, key: vec![105] }, - vec![zero + 1] - ), - ] - ), - ( - ChildIndex { block: zero + 4, storage_key: child_trie_key2.clone() }, - vec![InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: zero + 4, key: vec![100] }, - vec![0, 2] - ),] - ), - ] - ); - } - - test_with_zero(0); - test_with_zero(16); - test_with_zero(17); - } - - #[test] - fn cache_is_used_when_changes_trie_is_built() { - let child_trie_key1 = ChildInfo::new_default(b"storage_key1").prefixed_storage_key(); - let child_trie_key2 = ChildInfo::new_default(b"storage_key2").prefixed_storage_key(); - let (backend, mut storage, changes, config) = prepare_for_build(0); - let parent = AnchorBlockId { hash: Default::default(), number: 15 }; - - // override some actual values from storage with values from the cache - // - // top-level storage: - // (keys 100, 101, 103, 105 are now missing from block#4 => they do not appear - // in l2 digest at block 16) - // - // "1" child storage: - // key 102 is now missing from block#4 => it doesn't appear in l2 digest at block 16 - // (keys 103, 104) are now added to block#4 => they appear in l2 digest at block 16 - // - // "2" child storage: - // (keys 105, 106) are now added to block#4 => they appear in l2 digest at block 16 - let trie_root4 = storage.root(&parent, 4).unwrap().unwrap(); - let cached_data4 = IncompleteCacheAction::CacheBuildData(IncompleteCachedBuildData::new()) - .set_digest_input_blocks(vec![1, 2, 3]) - .insert(None, vec![vec![100], vec![102]].into_iter().collect()) - .insert(Some(child_trie_key1.clone()), vec![vec![103], vec![104]].into_iter().collect()) - .insert(Some(child_trie_key2.clone()), vec![vec![105], vec![106]].into_iter().collect()) - .complete(4, &trie_root4); - storage.cache_mut().perform(cached_data4); - - let (root_changes_trie_nodes, child_changes_tries_nodes, _) = - prepare_input(&backend, &storage, configuration_range(&config, 0), &changes, &parent) - .unwrap(); - assert_eq!( - root_changes_trie_nodes.collect::>>(), - vec![ - InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: 16, key: vec![100] }, - vec![0, 2, 3] - ), - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: 16, key: vec![101] }, vec![1]), - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: 16, key: vec![103] }, vec![0, 1]), - InputPair::DigestIndex(DigestIndex { block: 16, key: vec![100] }, vec![4]), - InputPair::DigestIndex(DigestIndex { block: 16, key: vec![102] }, vec![4]), - InputPair::DigestIndex(DigestIndex { block: 16, key: vec![105] }, vec![8]), - ] - ); - - let child_changes_tries_nodes = child_changes_tries_nodes - .into_iter() - .map(|(k, i)| (k, i.collect::>())) - .collect::>(); - assert_eq!( - child_changes_tries_nodes - .get(&ChildIndex { block: 16u64, storage_key: child_trie_key1.clone() }) - .unwrap(), - &vec![ - InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: 16u64, key: vec![100] }, - vec![0, 2, 3] - ), - InputPair::DigestIndex(DigestIndex { block: 16u64, key: vec![103] }, vec![4]), - InputPair::DigestIndex(DigestIndex { block: 16u64, key: vec![104] }, vec![4]), - ], - ); - assert_eq!( - child_changes_tries_nodes - .get(&ChildIndex { block: 16u64, storage_key: child_trie_key2.clone() }) - .unwrap(), - &vec![ - InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: 16u64, key: vec![100] }, - vec![0, 2] - ), - InputPair::DigestIndex(DigestIndex { block: 16u64, key: vec![105] }, vec![4]), - InputPair::DigestIndex(DigestIndex { block: 16u64, key: vec![106] }, vec![4]), - ], - ); - } -} diff --git a/primitives/state-machine/src/changes_trie/build_cache.rs b/primitives/state-machine/src/changes_trie/build_cache.rs deleted file mode 100644 index 04820242d9d0..000000000000 --- a/primitives/state-machine/src/changes_trie/build_cache.rs +++ /dev/null @@ -1,278 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2019-2021 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. - -//! Changes tries build cache. - -use std::collections::{HashMap, HashSet}; - -use crate::StorageKey; -use sp_core::storage::PrefixedStorageKey; - -/// Changes trie build cache. -/// -/// Helps to avoid read of changes tries from the database when digest trie -/// is built. It holds changed keys for every block (indexed by changes trie -/// root) that could be referenced by future digest items. For digest entries -/// it also holds keys covered by this digest. Entries for top level digests -/// are never created, because they'll never be used to build other digests. -/// -/// Entries are pruned from the cache once digest block that is using this entry -/// is inserted (because digest block will includes all keys from this entry). -/// When there's a fork, entries are pruned when first changes trie is inserted. -pub struct BuildCache { - /// Map of block (implies changes trie) number => changes trie root. - roots_by_number: HashMap, - /// Map of changes trie root => set of storage keys that are in this trie. - /// The `Option>` in inner `HashMap` stands for the child storage key. - /// If it is `None`, then the `HashSet` contains keys changed in top-level storage. - /// If it is `Some`, then the `HashSet` contains keys changed in child storage, identified by - /// the key. - changed_keys: HashMap, HashSet>>, -} - -/// The action to perform when block-with-changes-trie is imported. -#[derive(Debug, PartialEq)] -pub enum CacheAction { - /// Cache data that has been collected when CT has been built. - CacheBuildData(CachedBuildData), - /// Clear cache from all existing entries. - Clear, -} - -/// The data that has been cached during changes trie building. -#[derive(Debug, PartialEq)] -pub struct CachedBuildData { - block: N, - trie_root: H, - digest_input_blocks: Vec, - changed_keys: HashMap, HashSet>, -} - -/// The action to perform when block-with-changes-trie is imported. -#[derive(Debug, PartialEq)] -pub(crate) enum IncompleteCacheAction { - /// Cache data that has been collected when CT has been built. - CacheBuildData(IncompleteCachedBuildData), - /// Clear cache from all existing entries. - Clear, -} - -/// The data (without changes trie root) that has been cached during changes trie building. -#[derive(Debug, PartialEq)] -pub(crate) struct IncompleteCachedBuildData { - digest_input_blocks: Vec, - changed_keys: HashMap, HashSet>, -} - -impl BuildCache -where - N: Eq + ::std::hash::Hash, - H: Eq + ::std::hash::Hash + Clone, -{ - /// Create new changes trie build cache. - pub fn new() -> Self { - BuildCache { roots_by_number: HashMap::new(), changed_keys: HashMap::new() } - } - - /// Get cached changed keys for changes trie with given root. - pub fn get( - &self, - root: &H, - ) -> Option<&HashMap, HashSet>> { - self.changed_keys.get(&root) - } - - /// Execute given functor with cached entry for given block. - /// Returns true if the functor has been called and false otherwise. - pub fn with_changed_keys( - &self, - root: &H, - functor: &mut dyn FnMut(&HashMap, HashSet>), - ) -> bool { - match self.changed_keys.get(&root) { - Some(changed_keys) => { - functor(changed_keys); - true - }, - None => false, - } - } - - /// Insert data into cache. - pub fn perform(&mut self, action: CacheAction) { - match action { - CacheAction::CacheBuildData(data) => { - self.roots_by_number.insert(data.block, data.trie_root.clone()); - self.changed_keys.insert(data.trie_root, data.changed_keys); - - for digest_input_block in data.digest_input_blocks { - let digest_input_block_hash = self.roots_by_number.remove(&digest_input_block); - if let Some(digest_input_block_hash) = digest_input_block_hash { - self.changed_keys.remove(&digest_input_block_hash); - } - } - }, - CacheAction::Clear => { - self.roots_by_number.clear(); - self.changed_keys.clear(); - }, - } - } -} - -impl IncompleteCacheAction { - /// Returns true if we need to collect changed keys for this action. - pub fn collects_changed_keys(&self) -> bool { - match *self { - IncompleteCacheAction::CacheBuildData(_) => true, - IncompleteCacheAction::Clear => false, - } - } - - /// Complete cache action with computed changes trie root. - pub(crate) fn complete(self, block: N, trie_root: &H) -> CacheAction { - match self { - IncompleteCacheAction::CacheBuildData(build_data) => - CacheAction::CacheBuildData(build_data.complete(block, trie_root.clone())), - IncompleteCacheAction::Clear => CacheAction::Clear, - } - } - - /// Set numbers of blocks that are superseded by this new entry. - /// - /// If/when this build data is committed to the cache, entries for these blocks - /// will be removed from the cache. - pub(crate) fn set_digest_input_blocks(self, digest_input_blocks: Vec) -> Self { - match self { - IncompleteCacheAction::CacheBuildData(build_data) => - IncompleteCacheAction::CacheBuildData( - build_data.set_digest_input_blocks(digest_input_blocks), - ), - IncompleteCacheAction::Clear => IncompleteCacheAction::Clear, - } - } - - /// Insert changed keys of given storage into cached data. - pub(crate) fn insert( - self, - storage_key: Option, - changed_keys: HashSet, - ) -> Self { - match self { - IncompleteCacheAction::CacheBuildData(build_data) => - IncompleteCacheAction::CacheBuildData(build_data.insert(storage_key, changed_keys)), - IncompleteCacheAction::Clear => IncompleteCacheAction::Clear, - } - } -} - -impl IncompleteCachedBuildData { - /// Create new cached data. - pub(crate) fn new() -> Self { - IncompleteCachedBuildData { digest_input_blocks: Vec::new(), changed_keys: HashMap::new() } - } - - fn complete(self, block: N, trie_root: H) -> CachedBuildData { - CachedBuildData { - block, - trie_root, - digest_input_blocks: self.digest_input_blocks, - changed_keys: self.changed_keys, - } - } - - fn set_digest_input_blocks(mut self, digest_input_blocks: Vec) -> Self { - self.digest_input_blocks = digest_input_blocks; - self - } - - fn insert( - mut self, - storage_key: Option, - changed_keys: HashSet, - ) -> Self { - self.changed_keys.insert(storage_key, changed_keys); - self - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn updated_keys_are_stored_when_non_top_level_digest_is_built() { - let mut data = IncompleteCachedBuildData::::new(); - data = data.insert(None, vec![vec![1]].into_iter().collect()); - assert_eq!(data.changed_keys.len(), 1); - - let mut cache = BuildCache::new(); - cache.perform(CacheAction::CacheBuildData(data.complete(1, 1))); - assert_eq!(cache.changed_keys.len(), 1); - assert_eq!( - cache.get(&1).unwrap().clone(), - vec![(None, vec![vec![1]].into_iter().collect())].into_iter().collect(), - ); - } - - #[test] - fn obsolete_entries_are_purged_when_new_ct_is_built() { - let mut cache = BuildCache::::new(); - cache.perform(CacheAction::CacheBuildData( - IncompleteCachedBuildData::new() - .insert(None, vec![vec![1]].into_iter().collect()) - .complete(1, 1), - )); - cache.perform(CacheAction::CacheBuildData( - IncompleteCachedBuildData::new() - .insert(None, vec![vec![2]].into_iter().collect()) - .complete(2, 2), - )); - cache.perform(CacheAction::CacheBuildData( - IncompleteCachedBuildData::new() - .insert(None, vec![vec![3]].into_iter().collect()) - .complete(3, 3), - )); - - assert_eq!(cache.changed_keys.len(), 3); - - cache.perform(CacheAction::CacheBuildData( - IncompleteCachedBuildData::new() - .set_digest_input_blocks(vec![1, 2, 3]) - .complete(4, 4), - )); - - assert_eq!(cache.changed_keys.len(), 1); - - cache.perform(CacheAction::CacheBuildData( - IncompleteCachedBuildData::new() - .insert(None, vec![vec![8]].into_iter().collect()) - .complete(8, 8), - )); - cache.perform(CacheAction::CacheBuildData( - IncompleteCachedBuildData::new() - .insert(None, vec![vec![12]].into_iter().collect()) - .complete(12, 12), - )); - - assert_eq!(cache.changed_keys.len(), 3); - - cache.perform(CacheAction::Clear); - - assert_eq!(cache.changed_keys.len(), 0); - } -} diff --git a/primitives/state-machine/src/changes_trie/build_iterator.rs b/primitives/state-machine/src/changes_trie/build_iterator.rs deleted file mode 100644 index 62bb00a2f882..000000000000 --- a/primitives/state-machine/src/changes_trie/build_iterator.rs +++ /dev/null @@ -1,487 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2017-2021 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. - -//! Structures and functions to return blocks whose changes are to be included -//! in given block's changes trie. - -use crate::changes_trie::{BlockNumber, ConfigurationRange}; -use num_traits::Zero; - -/// Returns iterator of OTHER blocks that are required for inclusion into -/// changes trie of given block. Blocks are guaranteed to be returned in -/// ascending order. -/// -/// Skewed digest is built IF block >= config.end. -pub fn digest_build_iterator<'a, Number: BlockNumber>( - config: ConfigurationRange<'a, Number>, - block: Number, -) -> DigestBuildIterator { - // prepare digest build parameters - let (_, _, digest_step) = match config.config.digest_level_at_block(config.zero, block.clone()) - { - Some((current_level, digest_interval, digest_step)) => - (current_level, digest_interval, digest_step), - None => return DigestBuildIterator::empty(), - }; - - DigestBuildIterator::new( - block.clone(), - config.end.unwrap_or(block), - config.config.digest_interval, - digest_step, - ) -} - -/// Changes trie build iterator that returns numbers of OTHER blocks that are -/// required for inclusion into changes trie of given block. -#[derive(Debug)] -pub struct DigestBuildIterator { - /// Block we're building changes trie for. It could (logically) be a post-end block if we are - /// creating skewed digest. - block: Number, - /// Block that is a last block where current configuration is active. We have never yet created - /// anything after this block => digest that we're creating can't reference any blocks that are - /// >= end. - end: Number, - /// Interval of L1 digest blocks. - digest_interval: u32, - /// Max step that could be used when digest is created. - max_step: u32, - - // Mutable data below: - /// Step of current blocks range. - current_step: u32, - /// Reverse step of current blocks range. - current_step_reverse: u32, - /// Current blocks range. - current_range: Option>, - /// Last block that we have returned. - last_block: Option, -} - -impl DigestBuildIterator { - /// Create new digest build iterator. - pub fn new(block: Number, end: Number, digest_interval: u32, max_step: u32) -> Self { - DigestBuildIterator { - block, - end, - digest_interval, - max_step, - current_step: max_step, - current_step_reverse: 0, - current_range: None, - last_block: None, - } - } - - /// Create empty digest build iterator. - pub fn empty() -> Self { - Self::new(Zero::zero(), Zero::zero(), 0, 0) - } -} - -impl Iterator for DigestBuildIterator { - type Item = Number; - - fn next(&mut self) -> Option { - // when we're building skewed digest, we might want to skip some blocks if - // they're not covered by current configuration - loop { - if let Some(next) = self.current_range.as_mut().and_then(|iter| iter.next()) { - if next < self.end { - self.last_block = Some(next.clone()); - return Some(next) - } - } - - // we are safe to use non-checking mul/sub versions here because: - // DigestBuildIterator is created only by internal function that is checking - // that all multiplications/subtractions are safe within max_step limit - - let next_step_reverse = if self.current_step_reverse == 0 { - 1 - } else { - self.current_step_reverse * self.digest_interval - }; - if next_step_reverse > self.max_step { - return None - } - - self.current_step_reverse = next_step_reverse; - self.current_range = Some(BlocksRange::new( - match self.last_block.clone() { - Some(last_block) => last_block + self.current_step.into(), - None => - self.block.clone() - - (self.current_step * self.digest_interval - self.current_step).into(), - }, - self.block.clone(), - self.current_step.into(), - )); - - self.current_step = self.current_step / self.digest_interval; - if self.current_step == 0 { - self.current_step = 1; - } - } - } -} - -/// Blocks range iterator with builtin step_by support. -#[derive(Debug)] -struct BlocksRange { - current: Number, - end: Number, - step: Number, -} - -impl BlocksRange { - pub fn new(begin: Number, end: Number, step: Number) -> Self { - BlocksRange { current: begin, end, step } - } -} - -impl Iterator for BlocksRange { - type Item = Number; - - fn next(&mut self) -> Option { - if self.current >= self.end { - return None - } - - let current = Some(self.current.clone()); - self.current += self.step.clone(); - current - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::changes_trie::Configuration; - - fn digest_build_iterator( - digest_interval: u32, - digest_levels: u32, - zero: u64, - block: u64, - end: Option, - ) -> DigestBuildIterator { - super::digest_build_iterator( - ConfigurationRange { - config: &Configuration { digest_interval, digest_levels }, - zero, - end, - }, - block, - ) - } - - fn digest_build_iterator_basic( - digest_interval: u32, - digest_levels: u32, - zero: u64, - block: u64, - ) -> (u64, u32, u32) { - let iter = digest_build_iterator(digest_interval, digest_levels, zero, block, None); - (iter.block, iter.digest_interval, iter.max_step) - } - - fn digest_build_iterator_blocks( - digest_interval: u32, - digest_levels: u32, - zero: u64, - block: u64, - end: Option, - ) -> Vec { - digest_build_iterator(digest_interval, digest_levels, zero, block, end).collect() - } - - #[test] - fn suggest_digest_inclusion_returns_empty_iterator() { - fn test_with_zero(zero: u64) { - let empty = (0, 0, 0); - assert_eq!(digest_build_iterator_basic(4, 16, zero, zero + 0), empty, "block is 0"); - assert_eq!( - digest_build_iterator_basic(0, 16, zero, zero + 64), - empty, - "digest_interval is 0" - ); - assert_eq!( - digest_build_iterator_basic(1, 16, zero, zero + 64), - empty, - "digest_interval is 1" - ); - assert_eq!( - digest_build_iterator_basic(4, 0, zero, zero + 64), - empty, - "digest_levels is 0" - ); - assert_eq!( - digest_build_iterator_basic(4, 16, zero, zero + 1), - empty, - "digest is not required for this block", - ); - assert_eq!( - digest_build_iterator_basic(4, 16, zero, zero + 2), - empty, - "digest is not required for this block", - ); - assert_eq!( - digest_build_iterator_basic(4, 16, zero, zero + 15), - empty, - "digest is not required for this block", - ); - assert_eq!( - digest_build_iterator_basic(4, 16, zero, zero + 17), - empty, - "digest is not required for this block", - ); - assert_eq!( - digest_build_iterator_basic(::std::u32::MAX / 2 + 1, 16, zero, ::std::u64::MAX,), - empty, - "digest_interval * 2 is greater than u64::MAX" - ); - } - - test_with_zero(0); - test_with_zero(1); - test_with_zero(2); - test_with_zero(4); - test_with_zero(17); - } - - #[test] - fn suggest_digest_inclusion_returns_level1_iterator() { - fn test_with_zero(zero: u64) { - assert_eq!( - digest_build_iterator_basic(16, 1, zero, zero + 16), - (zero + 16, 16, 1), - "!(block % interval) && first digest level == block", - ); - assert_eq!( - digest_build_iterator_basic(16, 1, zero, zero + 256), - (zero + 256, 16, 1), - "!(block % interval^2), but there's only 1 digest level", - ); - assert_eq!( - digest_build_iterator_basic(16, 2, zero, zero + 32), - (zero + 32, 16, 1), - "second level digest is not required for this block", - ); - assert_eq!( - digest_build_iterator_basic(16, 3, zero, zero + 4080), - (zero + 4080, 16, 1), - "second && third level digest are not required for this block", - ); - } - - test_with_zero(0); - test_with_zero(16); - test_with_zero(17); - } - - #[test] - fn suggest_digest_inclusion_returns_level2_iterator() { - fn test_with_zero(zero: u64) { - assert_eq!( - digest_build_iterator_basic(16, 2, zero, zero + 256), - (zero + 256, 16, 16), - "second level digest", - ); - assert_eq!( - digest_build_iterator_basic(16, 2, zero, zero + 4096), - (zero + 4096, 16, 16), - "!(block % interval^3), but there's only 2 digest levels", - ); - } - - test_with_zero(0); - test_with_zero(16); - test_with_zero(17); - } - - #[test] - fn suggest_digest_inclusion_returns_level3_iterator() { - fn test_with_zero(zero: u64) { - assert_eq!( - digest_build_iterator_basic(16, 3, zero, zero + 4096), - (zero + 4096, 16, 256), - "third level digest: beginning", - ); - assert_eq!( - digest_build_iterator_basic(16, 3, zero, zero + 8192), - (zero + 8192, 16, 256), - "third level digest: next", - ); - } - - test_with_zero(0); - test_with_zero(16); - test_with_zero(17); - } - - #[test] - fn digest_iterator_returns_level1_blocks() { - fn test_with_zero(zero: u64) { - assert_eq!( - digest_build_iterator_blocks(16, 1, zero, zero + 16, None), - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] - .iter() - .map(|item| zero + item) - .collect::>() - ); - assert_eq!( - digest_build_iterator_blocks(16, 1, zero, zero + 256, None), - [241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255] - .iter() - .map(|item| zero + item) - .collect::>() - ); - assert_eq!( - digest_build_iterator_blocks(16, 2, zero, zero + 32, None), - [17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31] - .iter() - .map(|item| zero + item) - .collect::>() - ); - assert_eq!( - digest_build_iterator_blocks(16, 3, zero, zero + 4080, None), - [ - 4065, 4066, 4067, 4068, 4069, 4070, 4071, 4072, 4073, 4074, 4075, 4076, 4077, - 4078, 4079 - ] - .iter() - .map(|item| zero + item) - .collect::>() - ); - } - - test_with_zero(0); - test_with_zero(16); - test_with_zero(17); - } - - #[test] - fn digest_iterator_returns_level1_and_level2_blocks() { - fn test_with_zero(zero: u64) { - assert_eq!( - digest_build_iterator_blocks(16, 2, zero, zero + 256, None), - [ - // level2 points to previous 16-1 level1 digests: - 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240, - // level2 is a level1 digest of 16-1 previous blocks: - 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, - ] - .iter() - .map(|item| zero + item) - .collect::>(), - ); - assert_eq!( - digest_build_iterator_blocks(16, 2, zero, zero + 4096, None), - [ - // level2 points to previous 16-1 level1 digests: - 3856, 3872, 3888, 3904, 3920, 3936, 3952, 3968, 3984, 4000, 4016, 4032, 4048, - 4064, 4080, // level2 is a level1 digest of 16-1 previous blocks: - 4081, 4082, 4083, 4084, 4085, 4086, 4087, 4088, 4089, 4090, 4091, 4092, 4093, - 4094, 4095, - ] - .iter() - .map(|item| zero + item) - .collect::>(), - ); - } - - test_with_zero(0); - test_with_zero(16); - test_with_zero(17); - } - - #[test] - fn digest_iterator_returns_level1_and_level2_and_level3_blocks() { - fn test_with_zero(zero: u64) { - assert_eq!( - digest_build_iterator_blocks(16, 3, zero, zero + 4096, None), - [ - // level3 points to previous 16-1 level2 digests: - 256, 512, 768, 1024, 1280, 1536, 1792, 2048, 2304, 2560, 2816, 3072, 3328, 3584, - 3840, // level3 points to previous 16-1 level1 digests: - 3856, 3872, 3888, 3904, 3920, 3936, 3952, 3968, 3984, 4000, 4016, 4032, 4048, - 4064, 4080, // level3 is a level1 digest of 16-1 previous blocks: - 4081, 4082, 4083, 4084, 4085, 4086, 4087, 4088, 4089, 4090, 4091, 4092, 4093, - 4094, 4095, - ] - .iter() - .map(|item| zero + item) - .collect::>(), - ); - } - - test_with_zero(0); - test_with_zero(16); - test_with_zero(17); - } - - #[test] - fn digest_iterator_returns_skewed_digest_blocks() { - fn test_with_zero(zero: u64) { - assert_eq!( - digest_build_iterator_blocks(16, 3, zero, zero + 4096, Some(zero + 1338)), - [ - // level3 MUST point to previous 16-1 level2 digests, BUT there are only 5: - 256, 512, 768, 1024, 1280, - // level3 MUST point to previous 16-1 level1 digests, BUT there are only 3: - 1296, 1312, 1328, - // level3 MUST be a level1 digest of 16-1 previous blocks, BUT there are only - // 9: - 1329, 1330, 1331, 1332, 1333, 1334, 1335, 1336, 1337, - ] - .iter() - .map(|item| zero + item) - .collect::>(), - ); - } - - test_with_zero(0); - test_with_zero(16); - test_with_zero(17); - } - - #[test] - fn digest_iterator_returns_skewed_digest_blocks_skipping_level() { - fn test_with_zero(zero: u64) { - assert_eq!( - digest_build_iterator_blocks(16, 3, zero, zero + 4096, Some(zero + 1284)), - [ - // level3 MUST point to previous 16-1 level2 digests, BUT there are only 5: - 256, 512, 768, 1024, 1280, - // level3 MUST point to previous 16-1 level1 digests, BUT there are NO ANY - // L1-digests: level3 MUST be a level1 digest of 16-1 previous blocks, BUT - // there are only 3: - 1281, 1282, 1283, - ] - .iter() - .map(|item| zero + item) - .collect::>(), - ); - } - - test_with_zero(0); - test_with_zero(16); - test_with_zero(17); - } -} diff --git a/primitives/state-machine/src/changes_trie/changes_iterator.rs b/primitives/state-machine/src/changes_trie/changes_iterator.rs deleted file mode 100644 index 9343a226a3aa..000000000000 --- a/primitives/state-machine/src/changes_trie/changes_iterator.rs +++ /dev/null @@ -1,748 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2017-2021 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. - -//! Functions + iterator that traverses changes tries and returns all -//! (block, extrinsic) pairs where given key has been changed. - -use crate::{ - changes_trie::{ - input::{ChildIndex, DigestIndex, DigestIndexValue, ExtrinsicIndex, ExtrinsicIndexValue}, - storage::{InMemoryStorage, TrieBackendAdapter}, - surface_iterator::{surface_iterator, SurfaceIterator}, - AnchorBlockId, BlockNumber, ConfigurationRange, RootsStorage, Storage, - }, - proving_backend::ProvingBackendRecorder, - trie_backend_essence::TrieBackendEssence, -}; -use codec::{Codec, Decode, Encode}; -use hash_db::Hasher; -use num_traits::Zero; -use sp_core::storage::PrefixedStorageKey; -use sp_trie::Recorder; -use std::{cell::RefCell, collections::VecDeque}; - -/// Return changes of given key at given blocks range. -/// `max` is the number of best known block. -/// Changes are returned in descending order (i.e. last block comes first). -pub fn key_changes<'a, H: Hasher, Number: BlockNumber>( - config: ConfigurationRange<'a, Number>, - storage: &'a dyn Storage, - begin: Number, - end: &'a AnchorBlockId, - max: Number, - storage_key: Option<&'a PrefixedStorageKey>, - key: &'a [u8], -) -> Result, String> { - // we can't query any roots before root - let max = std::cmp::min(max, end.number.clone()); - - Ok(DrilldownIterator { - essence: DrilldownIteratorEssence { - storage_key, - key, - roots_storage: storage.as_roots_storage(), - storage, - begin: begin.clone(), - end, - config: config.clone(), - surface: surface_iterator(config, max, begin, end.number.clone())?, - - extrinsics: Default::default(), - blocks: Default::default(), - - _hasher: ::std::marker::PhantomData::::default(), - }, - }) -} - -/// Returns proof of changes of given key at given blocks range. -/// `max` is the number of best known block. -pub fn key_changes_proof<'a, H: Hasher, Number: BlockNumber>( - config: ConfigurationRange<'a, Number>, - storage: &dyn Storage, - begin: Number, - end: &AnchorBlockId, - max: Number, - storage_key: Option<&PrefixedStorageKey>, - key: &[u8], -) -> Result>, String> -where - H::Out: Codec, -{ - // we can't query any roots before root - let max = std::cmp::min(max, end.number.clone()); - - let mut iter = ProvingDrilldownIterator { - essence: DrilldownIteratorEssence { - storage_key, - key, - roots_storage: storage.as_roots_storage(), - storage, - begin: begin.clone(), - end, - config: config.clone(), - surface: surface_iterator(config, max, begin, end.number.clone())?, - - extrinsics: Default::default(), - blocks: Default::default(), - - _hasher: ::std::marker::PhantomData::::default(), - }, - proof_recorder: Default::default(), - }; - - // iterate to collect proof - while let Some(item) = iter.next() { - item?; - } - - Ok(iter.extract_proof()) -} - -/// Check key changes proof and return changes of the key at given blocks range. -/// `max` is the number of best known block. -/// Changes are returned in descending order (i.e. last block comes first). -pub fn key_changes_proof_check<'a, H: Hasher, Number: BlockNumber>( - config: ConfigurationRange<'a, Number>, - roots_storage: &dyn RootsStorage, - proof: Vec>, - begin: Number, - end: &AnchorBlockId, - max: Number, - storage_key: Option<&PrefixedStorageKey>, - key: &[u8], -) -> Result, String> -where - H::Out: Encode, -{ - key_changes_proof_check_with_db( - config, - roots_storage, - &InMemoryStorage::with_proof(proof), - begin, - end, - max, - storage_key, - key, - ) -} - -/// Similar to the `key_changes_proof_check` function, but works with prepared proof storage. -pub fn key_changes_proof_check_with_db<'a, H: Hasher, Number: BlockNumber>( - config: ConfigurationRange<'a, Number>, - roots_storage: &dyn RootsStorage, - proof_db: &InMemoryStorage, - begin: Number, - end: &AnchorBlockId, - max: Number, - storage_key: Option<&PrefixedStorageKey>, - key: &[u8], -) -> Result, String> -where - H::Out: Encode, -{ - // we can't query any roots before root - let max = std::cmp::min(max, end.number.clone()); - - DrilldownIterator { - essence: DrilldownIteratorEssence { - storage_key, - key, - roots_storage, - storage: proof_db, - begin: begin.clone(), - end, - config: config.clone(), - surface: surface_iterator(config, max, begin, end.number.clone())?, - - extrinsics: Default::default(), - blocks: Default::default(), - - _hasher: ::std::marker::PhantomData::::default(), - }, - } - .collect() -} - -/// Drilldown iterator - receives 'digest points' from surface iterator and explores -/// every point until extrinsic is found. -pub struct DrilldownIteratorEssence<'a, H, Number> -where - H: Hasher, - Number: BlockNumber, - H::Out: 'a, -{ - storage_key: Option<&'a PrefixedStorageKey>, - key: &'a [u8], - roots_storage: &'a dyn RootsStorage, - storage: &'a dyn Storage, - begin: Number, - end: &'a AnchorBlockId, - config: ConfigurationRange<'a, Number>, - surface: SurfaceIterator<'a, Number>, - - extrinsics: VecDeque<(Number, u32)>, - blocks: VecDeque<(Number, Option)>, - - _hasher: ::std::marker::PhantomData, -} - -impl<'a, H, Number> DrilldownIteratorEssence<'a, H, Number> -where - H: Hasher, - Number: BlockNumber, - H::Out: 'a, -{ - pub fn next(&mut self, trie_reader: F) -> Option> - where - F: FnMut(&dyn Storage, H::Out, &[u8]) -> Result>, String>, - { - match self.do_next(trie_reader) { - Ok(Some(res)) => Some(Ok(res)), - Ok(None) => None, - Err(err) => Some(Err(err)), - } - } - - fn do_next(&mut self, mut trie_reader: F) -> Result, String> - where - F: FnMut(&dyn Storage, H::Out, &[u8]) -> Result>, String>, - { - loop { - if let Some((block, extrinsic)) = self.extrinsics.pop_front() { - return Ok(Some((block, extrinsic))) - } - - if let Some((block, level)) = self.blocks.pop_front() { - // not having a changes trie root is an error because: - // we never query roots for future blocks - // AND trie roots for old blocks are known (both on full + light node) - let trie_root = - self.roots_storage.root(&self.end, block.clone())?.ok_or_else(|| { - format!("Changes trie root for block {} is not found", block.clone()) - })?; - let trie_root = if let Some(storage_key) = self.storage_key { - let child_key = - ChildIndex { block: block.clone(), storage_key: storage_key.clone() } - .encode(); - if let Some(trie_root) = trie_reader(self.storage, trie_root, &child_key)? - .and_then(|v| >::decode(&mut &v[..]).ok()) - .map(|v| { - let mut hash = H::Out::default(); - hash.as_mut().copy_from_slice(&v[..]); - hash - }) { - trie_root - } else { - continue - } - } else { - trie_root - }; - - // only return extrinsics for blocks before self.max - // most of blocks will be filtered out before pushing to `self.blocks` - // here we just throwing away changes at digest blocks we're processing - debug_assert!( - block >= self.begin, - "We shall not touch digests earlier than a range' begin" - ); - if block <= self.end.number { - let extrinsics_key = - ExtrinsicIndex { block: block.clone(), key: self.key.to_vec() }.encode(); - let extrinsics = trie_reader(self.storage, trie_root, &extrinsics_key); - if let Some(extrinsics) = extrinsics? { - if let Ok(extrinsics) = ExtrinsicIndexValue::decode(&mut &extrinsics[..]) { - self.extrinsics - .extend(extrinsics.into_iter().rev().map(|e| (block.clone(), e))); - } - } - } - - let blocks_key = - DigestIndex { block: block.clone(), key: self.key.to_vec() }.encode(); - let blocks = trie_reader(self.storage, trie_root, &blocks_key); - if let Some(blocks) = blocks? { - if let Ok(blocks) = >::decode(&mut &blocks[..]) { - // filter level0 blocks here because we tend to use digest blocks, - // AND digest block changes could also include changes for out-of-range - // blocks - let begin = self.begin.clone(); - let end = self.end.number.clone(); - let config = self.config.clone(); - self.blocks.extend( - blocks - .into_iter() - .rev() - .filter(|b| { - level.map(|level| level > 1).unwrap_or(true) || - (*b >= begin && *b <= end) - }) - .map(|b| { - let prev_level = - level.map(|level| Some(level - 1)).unwrap_or_else(|| { - Some( - config - .config - .digest_level_at_block( - config.zero.clone(), - b.clone(), - ) - .map(|(level, _, _)| level) - .unwrap_or_else(|| Zero::zero()), - ) - }); - (b, prev_level) - }), - ); - } - } - - continue - } - - match self.surface.next() { - Some(Ok(block)) => self.blocks.push_back(block), - Some(Err(err)) => return Err(err), - None => return Ok(None), - } - } - } -} - -/// Exploring drilldown operator. -pub struct DrilldownIterator<'a, H, Number> -where - Number: BlockNumber, - H: Hasher, - H::Out: 'a, -{ - essence: DrilldownIteratorEssence<'a, H, Number>, -} - -impl<'a, H: Hasher, Number: BlockNumber> Iterator for DrilldownIterator<'a, H, Number> -where - H::Out: Encode, -{ - type Item = Result<(Number, u32), String>; - - fn next(&mut self) -> Option { - self.essence.next(|storage, root, key| { - TrieBackendEssence::<_, H>::new(TrieBackendAdapter::new(storage), root).storage(key) - }) - } -} - -/// Proving drilldown iterator. -struct ProvingDrilldownIterator<'a, H, Number> -where - Number: BlockNumber, - H: Hasher, - H::Out: 'a, -{ - essence: DrilldownIteratorEssence<'a, H, Number>, - proof_recorder: RefCell>, -} - -impl<'a, H, Number> ProvingDrilldownIterator<'a, H, Number> -where - Number: BlockNumber, - H: Hasher, - H::Out: 'a, -{ - /// Consume the iterator, extracting the gathered proof in lexicographical order - /// by value. - pub fn extract_proof(self) -> Vec> { - self.proof_recorder - .into_inner() - .drain() - .into_iter() - .map(|n| n.data.to_vec()) - .collect() - } -} - -impl<'a, H, Number> Iterator for ProvingDrilldownIterator<'a, H, Number> -where - Number: BlockNumber, - H: Hasher, - H::Out: 'a + Codec, -{ - type Item = Result<(Number, u32), String>; - - fn next(&mut self) -> Option { - let proof_recorder = &mut *self - .proof_recorder - .try_borrow_mut() - .expect("only fails when already borrowed; storage() is non-reentrant; qed"); - self.essence.next(|storage, root, key| { - ProvingBackendRecorder::<_, H> { - backend: &TrieBackendEssence::new(TrieBackendAdapter::new(storage), root), - proof_recorder, - } - .storage(key) - }) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::changes_trie::{input::InputPair, storage::InMemoryStorage, Configuration}; - use sp_runtime::traits::BlakeTwo256; - use std::iter::FromIterator; - - fn child_key() -> PrefixedStorageKey { - let child_info = sp_core::storage::ChildInfo::new_default(&b"1"[..]); - child_info.prefixed_storage_key() - } - - fn prepare_for_drilldown() -> (Configuration, InMemoryStorage) { - let config = Configuration { digest_interval: 4, digest_levels: 2 }; - let backend = InMemoryStorage::with_inputs( - vec![ - // digest: 1..4 => [(3, 0)] - (1, vec![]), - (2, vec![]), - ( - 3, - vec![InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: 3, key: vec![42] }, - vec![0], - )], - ), - (4, vec![InputPair::DigestIndex(DigestIndex { block: 4, key: vec![42] }, vec![3])]), - // digest: 5..8 => [(6, 3), (8, 1+2)] - (5, vec![]), - ( - 6, - vec![InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: 6, key: vec![42] }, - vec![3], - )], - ), - (7, vec![]), - ( - 8, - vec![ - InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: 8, key: vec![42] }, - vec![1, 2], - ), - InputPair::DigestIndex(DigestIndex { block: 8, key: vec![42] }, vec![6]), - ], - ), - // digest: 9..12 => [] - (9, vec![]), - (10, vec![]), - (11, vec![]), - (12, vec![]), - // digest: 0..16 => [4, 8] - (13, vec![]), - (14, vec![]), - (15, vec![]), - ( - 16, - vec![InputPair::DigestIndex( - DigestIndex { block: 16, key: vec![42] }, - vec![4, 8], - )], - ), - ], - vec![( - child_key(), - vec![ - ( - 1, - vec![InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: 1, key: vec![42] }, - vec![0], - )], - ), - ( - 2, - vec![InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: 2, key: vec![42] }, - vec![3], - )], - ), - ( - 16, - vec![ - InputPair::ExtrinsicIndex( - ExtrinsicIndex { block: 16, key: vec![42] }, - vec![5], - ), - InputPair::DigestIndex( - DigestIndex { block: 16, key: vec![42] }, - vec![2], - ), - ], - ), - ], - )], - ); - - (config, backend) - } - - fn configuration_range<'a>( - config: &'a Configuration, - zero: u64, - ) -> ConfigurationRange<'a, u64> { - ConfigurationRange { config, zero, end: None } - } - - #[test] - fn drilldown_iterator_works() { - let (config, storage) = prepare_for_drilldown(); - let drilldown_result = key_changes::( - configuration_range(&config, 0), - &storage, - 1, - &AnchorBlockId { hash: Default::default(), number: 16 }, - 16, - None, - &[42], - ) - .and_then(Result::from_iter); - assert_eq!(drilldown_result, Ok(vec![(8, 2), (8, 1), (6, 3), (3, 0)])); - - let drilldown_result = key_changes::( - configuration_range(&config, 0), - &storage, - 1, - &AnchorBlockId { hash: Default::default(), number: 2 }, - 4, - None, - &[42], - ) - .and_then(Result::from_iter); - assert_eq!(drilldown_result, Ok(vec![])); - - let drilldown_result = key_changes::( - configuration_range(&config, 0), - &storage, - 1, - &AnchorBlockId { hash: Default::default(), number: 3 }, - 4, - None, - &[42], - ) - .and_then(Result::from_iter); - assert_eq!(drilldown_result, Ok(vec![(3, 0)])); - - let drilldown_result = key_changes::( - configuration_range(&config, 0), - &storage, - 1, - &AnchorBlockId { hash: Default::default(), number: 7 }, - 7, - None, - &[42], - ) - .and_then(Result::from_iter); - assert_eq!(drilldown_result, Ok(vec![(6, 3), (3, 0)])); - - let drilldown_result = key_changes::( - configuration_range(&config, 0), - &storage, - 7, - &AnchorBlockId { hash: Default::default(), number: 8 }, - 8, - None, - &[42], - ) - .and_then(Result::from_iter); - assert_eq!(drilldown_result, Ok(vec![(8, 2), (8, 1)])); - - let drilldown_result = key_changes::( - configuration_range(&config, 0), - &storage, - 5, - &AnchorBlockId { hash: Default::default(), number: 7 }, - 8, - None, - &[42], - ) - .and_then(Result::from_iter); - assert_eq!(drilldown_result, Ok(vec![(6, 3)])); - } - - #[test] - fn drilldown_iterator_fails_when_storage_fails() { - let (config, storage) = prepare_for_drilldown(); - storage.clear_storage(); - - assert!(key_changes::( - configuration_range(&config, 0), - &storage, - 1, - &AnchorBlockId { hash: Default::default(), number: 100 }, - 1000, - None, - &[42], - ) - .and_then(|i| i.collect::, _>>()) - .is_err()); - - assert!(key_changes::( - configuration_range(&config, 0), - &storage, - 1, - &AnchorBlockId { hash: Default::default(), number: 100 }, - 1000, - Some(&child_key()), - &[42], - ) - .and_then(|i| i.collect::, _>>()) - .is_err()); - } - - #[test] - fn drilldown_iterator_fails_when_range_is_invalid() { - let (config, storage) = prepare_for_drilldown(); - assert!(key_changes::( - configuration_range(&config, 0), - &storage, - 1, - &AnchorBlockId { hash: Default::default(), number: 100 }, - 50, - None, - &[42], - ) - .is_err()); - assert!(key_changes::( - configuration_range(&config, 0), - &storage, - 20, - &AnchorBlockId { hash: Default::default(), number: 10 }, - 100, - None, - &[42], - ) - .is_err()); - } - - #[test] - fn proving_drilldown_iterator_works() { - // happens on remote full node: - - // create drilldown iterator that records all trie nodes during drilldown - let (remote_config, remote_storage) = prepare_for_drilldown(); - let remote_proof = key_changes_proof::( - configuration_range(&remote_config, 0), - &remote_storage, - 1, - &AnchorBlockId { hash: Default::default(), number: 16 }, - 16, - None, - &[42], - ) - .unwrap(); - - let (remote_config, remote_storage) = prepare_for_drilldown(); - let remote_proof_child = key_changes_proof::( - configuration_range(&remote_config, 0), - &remote_storage, - 1, - &AnchorBlockId { hash: Default::default(), number: 16 }, - 16, - Some(&child_key()), - &[42], - ) - .unwrap(); - - // happens on local light node: - - // create drilldown iterator that works the same, but only depends on trie - let (local_config, local_storage) = prepare_for_drilldown(); - local_storage.clear_storage(); - let local_result = key_changes_proof_check::( - configuration_range(&local_config, 0), - &local_storage, - remote_proof, - 1, - &AnchorBlockId { hash: Default::default(), number: 16 }, - 16, - None, - &[42], - ); - - let (local_config, local_storage) = prepare_for_drilldown(); - local_storage.clear_storage(); - let local_result_child = key_changes_proof_check::( - configuration_range(&local_config, 0), - &local_storage, - remote_proof_child, - 1, - &AnchorBlockId { hash: Default::default(), number: 16 }, - 16, - Some(&child_key()), - &[42], - ); - - // check that drilldown result is the same as if it was happening at the full node - assert_eq!(local_result, Ok(vec![(8, 2), (8, 1), (6, 3), (3, 0)])); - assert_eq!(local_result_child, Ok(vec![(16, 5), (2, 3)])); - } - - #[test] - fn drilldown_iterator_works_with_skewed_digest() { - let config = Configuration { digest_interval: 4, digest_levels: 3 }; - let mut config_range = configuration_range(&config, 0); - config_range.end = Some(91); - - // when 4^3 deactivates at block 91: - // last L3 digest has been created at block#64 - // skewed digest covers: - // L2 digests at blocks: 80 - // L1 digests at blocks: 84, 88 - // regular blocks: 89, 90, 91 - let mut input = (1u64..92u64).map(|b| (b, vec![])).collect::>(); - // changed at block#63 and covered by L3 digest at block#64 - input[63 - 1] - .1 - .push(InputPair::ExtrinsicIndex(ExtrinsicIndex { block: 63, key: vec![42] }, vec![0])); - input[64 - 1] - .1 - .push(InputPair::DigestIndex(DigestIndex { block: 64, key: vec![42] }, vec![63])); - // changed at block#79 and covered by L2 digest at block#80 + skewed digest at block#91 - input[79 - 1] - .1 - .push(InputPair::ExtrinsicIndex(ExtrinsicIndex { block: 79, key: vec![42] }, vec![1])); - input[80 - 1] - .1 - .push(InputPair::DigestIndex(DigestIndex { block: 80, key: vec![42] }, vec![79])); - input[91 - 1] - .1 - .push(InputPair::DigestIndex(DigestIndex { block: 91, key: vec![42] }, vec![80])); - let storage = InMemoryStorage::with_inputs(input, vec![]); - - let drilldown_result = key_changes::( - config_range, - &storage, - 1, - &AnchorBlockId { hash: Default::default(), number: 91 }, - 100_000u64, - None, - &[42], - ) - .and_then(Result::from_iter); - assert_eq!(drilldown_result, Ok(vec![(79, 1), (63, 0)])); - } -} diff --git a/primitives/state-machine/src/changes_trie/input.rs b/primitives/state-machine/src/changes_trie/input.rs deleted file mode 100644 index af0a423e5726..000000000000 --- a/primitives/state-machine/src/changes_trie/input.rs +++ /dev/null @@ -1,207 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2017-2021 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. - -//! Different types of changes trie input pairs. - -use crate::{changes_trie::BlockNumber, StorageKey, StorageValue}; -use codec::{Decode, Encode, Error, Input, Output}; -use sp_core::storage::PrefixedStorageKey; - -/// Key of { changed key => set of extrinsic indices } mapping. -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct ExtrinsicIndex { - /// Block at which this key has been inserted in the trie. - pub block: Number, - /// Storage key this node is responsible for. - pub key: StorageKey, -} - -/// Value of { changed key => set of extrinsic indices } mapping. -pub type ExtrinsicIndexValue = Vec; - -/// Key of { changed key => block/digest block numbers } mapping. -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct DigestIndex { - /// Block at which this key has been inserted in the trie. - pub block: Number, - /// Storage key this node is responsible for. - pub key: StorageKey, -} - -/// Key of { childtrie key => Childchange trie } mapping. -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] -pub struct ChildIndex { - /// Block at which this key has been inserted in the trie. - pub block: Number, - /// Storage key this node is responsible for. - pub storage_key: PrefixedStorageKey, -} - -/// Value of { changed key => block/digest block numbers } mapping. -pub type DigestIndexValue = Vec; - -/// Value of { changed key => block/digest block numbers } mapping. -/// That is the root of the child change trie. -pub type ChildIndexValue = Vec; - -/// Single input pair of changes trie. -#[derive(Clone, Debug, PartialEq, Eq)] -pub enum InputPair { - /// Element of { key => set of extrinsics where key has been changed } element mapping. - ExtrinsicIndex(ExtrinsicIndex, ExtrinsicIndexValue), - /// Element of { key => set of blocks/digest blocks where key has been changed } element - /// mapping. - DigestIndex(DigestIndex, DigestIndexValue), - /// Element of { childtrie key => Childchange trie } where key has been changed } element - /// mapping. - ChildIndex(ChildIndex, ChildIndexValue), -} - -/// Single input key of changes trie. -#[derive(Clone, Debug, PartialEq, Eq)] -pub enum InputKey { - /// Key of { key => set of extrinsics where key has been changed } element mapping. - ExtrinsicIndex(ExtrinsicIndex), - /// Key of { key => set of blocks/digest blocks where key has been changed } element mapping. - DigestIndex(DigestIndex), - /// Key of { childtrie key => Childchange trie } where key has been changed } element mapping. - ChildIndex(ChildIndex), -} - -impl InputPair { - /// Extract storage key that this pair corresponds to. - pub fn key(&self) -> Option<&[u8]> { - match *self { - InputPair::ExtrinsicIndex(ref key, _) => Some(&key.key), - InputPair::DigestIndex(ref key, _) => Some(&key.key), - InputPair::ChildIndex(_, _) => None, - } - } -} - -impl Into<(StorageKey, StorageValue)> for InputPair { - fn into(self) -> (StorageKey, StorageValue) { - match self { - InputPair::ExtrinsicIndex(key, value) => (key.encode(), value.encode()), - InputPair::DigestIndex(key, value) => (key.encode(), value.encode()), - InputPair::ChildIndex(key, value) => (key.encode(), value.encode()), - } - } -} - -impl Into> for InputPair { - fn into(self) -> InputKey { - match self { - InputPair::ExtrinsicIndex(key, _) => InputKey::ExtrinsicIndex(key), - InputPair::DigestIndex(key, _) => InputKey::DigestIndex(key), - InputPair::ChildIndex(key, _) => InputKey::ChildIndex(key), - } - } -} - -impl ExtrinsicIndex { - pub fn key_neutral_prefix(block: Number) -> Vec { - let mut prefix = vec![1]; - prefix.extend(block.encode()); - prefix - } -} - -impl Encode for ExtrinsicIndex { - fn encode_to(&self, dest: &mut W) { - dest.push_byte(1); - self.block.encode_to(dest); - self.key.encode_to(dest); - } -} - -impl codec::EncodeLike for ExtrinsicIndex {} - -impl DigestIndex { - pub fn key_neutral_prefix(block: Number) -> Vec { - let mut prefix = vec![2]; - prefix.extend(block.encode()); - prefix - } -} - -impl Encode for DigestIndex { - fn encode_to(&self, dest: &mut W) { - dest.push_byte(2); - self.block.encode_to(dest); - self.key.encode_to(dest); - } -} - -impl ChildIndex { - pub fn key_neutral_prefix(block: Number) -> Vec { - let mut prefix = vec![3]; - prefix.extend(block.encode()); - prefix - } -} - -impl Encode for ChildIndex { - fn encode_to(&self, dest: &mut W) { - dest.push_byte(3); - self.block.encode_to(dest); - self.storage_key.encode_to(dest); - } -} - -impl codec::EncodeLike for DigestIndex {} - -impl Decode for InputKey { - fn decode(input: &mut I) -> Result { - match input.read_byte()? { - 1 => Ok(InputKey::ExtrinsicIndex(ExtrinsicIndex { - block: Decode::decode(input)?, - key: Decode::decode(input)?, - })), - 2 => Ok(InputKey::DigestIndex(DigestIndex { - block: Decode::decode(input)?, - key: Decode::decode(input)?, - })), - 3 => Ok(InputKey::ChildIndex(ChildIndex { - block: Decode::decode(input)?, - storage_key: PrefixedStorageKey::new(Decode::decode(input)?), - })), - _ => Err("Invalid input key variant".into()), - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn extrinsic_index_serialized_and_deserialized() { - let original = ExtrinsicIndex { block: 777u64, key: vec![42] }; - let serialized = original.encode(); - let deserialized: InputKey = Decode::decode(&mut &serialized[..]).unwrap(); - assert_eq!(InputKey::ExtrinsicIndex(original), deserialized); - } - - #[test] - fn digest_index_serialized_and_deserialized() { - let original = DigestIndex { block: 777u64, key: vec![42] }; - let serialized = original.encode(); - let deserialized: InputKey = Decode::decode(&mut &serialized[..]).unwrap(); - assert_eq!(InputKey::DigestIndex(original), deserialized); - } -} diff --git a/primitives/state-machine/src/changes_trie/mod.rs b/primitives/state-machine/src/changes_trie/mod.rs deleted file mode 100644 index 40148095247d..000000000000 --- a/primitives/state-machine/src/changes_trie/mod.rs +++ /dev/null @@ -1,428 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2017-2021 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. - -//! Changes trie related structures and functions. -//! -//! Changes trie is a trie built of { storage key => extrinsics } pairs -//! at the end of each block. For every changed storage key it contains -//! a pair, mapping key to the set of extrinsics where it has been changed. -//! -//! Optionally, every N blocks, additional level1-digest nodes are appended -//! to the changes trie, containing pairs { storage key => blocks }. For every -//! storage key that has been changed in PREVIOUS N-1 blocks (except for genesis -//! block) it contains a pair, mapping this key to the set of blocks where it -//! has been changed. -//! -//! Optionally, every N^digest_level (where digest_level > 1) blocks, additional -//! digest_level digest is created. It is built out of pairs { storage key => digest -//! block }, containing entries for every storage key that has been changed in -//! the last N*digest_level-1 blocks (except for genesis block), mapping these keys -//! to the set of lower-level digest blocks. -//! -//! Changes trie configuration could change within a time. The range of blocks, where -//! configuration has been active, is given by two blocks: zero and end. Zero block is -//! the block where configuration has been set. But the first changes trie that uses -//! this configuration will be built at the block zero+1. If configuration deactivates -//! at some block, this will be the end block of the configuration. It is also the -//! zero block of the next configuration. -//! -//! If configuration has the end block, it also means that 'skewed digest' has/should -//! been built at that block. If this is the block where max-level digest should have -//! been created, than it is simply max-level digest of this configuration. Otherwise, -//! it is the digest that covers all blocks since last max-level digest block was -//! created. -//! -//! Changes trie only contains the top level storage changes. Sub-level changes -//! are propagated through its storage root on the top level storage. - -mod build; -mod build_cache; -mod build_iterator; -mod changes_iterator; -mod input; -mod prune; -mod storage; -mod surface_iterator; - -pub use self::{ - build_cache::{BuildCache, CacheAction, CachedBuildData}, - changes_iterator::{ - key_changes, key_changes_proof, key_changes_proof_check, key_changes_proof_check_with_db, - }, - prune::prune, - storage::InMemoryStorage, -}; - -use crate::{ - backend::Backend, - changes_trie::{ - build::prepare_input, - build_cache::{IncompleteCacheAction, IncompleteCachedBuildData}, - }, - overlayed_changes::OverlayedChanges, - StorageKey, -}; -use codec::{Decode, Encode}; -use hash_db::{Hasher, Prefix}; -use num_traits::{One, Zero}; -use sp_core::{self, storage::PrefixedStorageKey}; -use sp_trie::{trie_types::TrieDBMut, DBValue, MemoryDB, TrieMut}; -use std::{ - collections::{HashMap, HashSet}, - convert::TryInto, -}; - -/// Requirements for block number that can be used with changes tries. -pub trait BlockNumber: - Send - + Sync - + 'static - + std::fmt::Display - + Clone - + From - + TryInto - + One - + Zero - + PartialEq - + Ord - + std::hash::Hash - + std::ops::Add - + ::std::ops::Sub - + std::ops::Mul - + ::std::ops::Div - + std::ops::Rem - + std::ops::AddAssign - + num_traits::CheckedMul - + num_traits::CheckedSub - + Decode - + Encode -{ -} - -impl BlockNumber for T where - T: Send - + Sync - + 'static - + std::fmt::Display - + Clone - + From - + TryInto - + One - + Zero - + PartialEq - + Ord - + std::hash::Hash - + std::ops::Add - + ::std::ops::Sub - + std::ops::Mul - + ::std::ops::Div - + std::ops::Rem - + std::ops::AddAssign - + num_traits::CheckedMul - + num_traits::CheckedSub - + Decode - + Encode -{ -} - -/// Block identifier that could be used to determine fork of this block. -#[derive(Debug)] -pub struct AnchorBlockId { - /// Hash of this block. - pub hash: Hash, - /// Number of this block. - pub number: Number, -} - -/// Changes tries state at some block. -pub struct State<'a, H, Number> { - /// Configuration that is active at given block. - pub config: Configuration, - /// Configuration activation block number. Zero if it is the first configuration on the chain, - /// or number of the block that have emit NewConfiguration signal (thus activating - /// configuration starting from the **next** block). - pub zero: Number, - /// Underlying changes tries storage reference. - pub storage: &'a dyn Storage, -} - -/// Changes trie storage. Provides access to trie roots and trie nodes. -pub trait RootsStorage: Send + Sync { - /// Resolve hash of the block into anchor. - fn build_anchor(&self, hash: H::Out) -> Result, String>; - /// Get changes trie root for the block with given number which is an ancestor (or the block - /// itself) of the anchor_block (i.e. anchor_block.number >= block). - fn root( - &self, - anchor: &AnchorBlockId, - block: Number, - ) -> Result, String>; -} - -/// Changes trie storage. Provides access to trie roots and trie nodes. -pub trait Storage: RootsStorage { - /// Casts from self reference to RootsStorage reference. - fn as_roots_storage(&self) -> &dyn RootsStorage; - /// Execute given functor with cached entry for given trie root. - /// Returns true if the functor has been called (cache entry exists) and false otherwise. - fn with_cached_changed_keys( - &self, - root: &H::Out, - functor: &mut dyn FnMut(&HashMap, HashSet>), - ) -> bool; - /// Get a trie node. - fn get(&self, key: &H::Out, prefix: Prefix) -> Result, String>; -} - -/// Changes trie storage -> trie backend essence adapter. -pub struct TrieBackendStorageAdapter<'a, H: Hasher, Number: BlockNumber>( - pub &'a dyn Storage, -); - -impl<'a, H: Hasher, N: BlockNumber> crate::TrieBackendStorage - for TrieBackendStorageAdapter<'a, H, N> -{ - type Overlay = sp_trie::MemoryDB; - - fn get(&self, key: &H::Out, prefix: Prefix) -> Result, String> { - self.0.get(key, prefix) - } -} - -/// Changes trie configuration. -pub type Configuration = sp_core::ChangesTrieConfiguration; - -/// Blocks range where configuration has been constant. -#[derive(Clone)] -pub struct ConfigurationRange<'a, N> { - /// Active configuration. - pub config: &'a Configuration, - /// Zero block of this configuration. The configuration is active starting from the next block. - pub zero: N, - /// End block of this configuration. It is the last block where configuration has been active. - pub end: Option, -} - -impl<'a, H, Number> State<'a, H, Number> { - /// Create state with given config and storage. - pub fn new(config: Configuration, zero: Number, storage: &'a dyn Storage) -> Self { - Self { config, zero, storage } - } -} - -impl<'a, H, Number: Clone> Clone for State<'a, H, Number> { - fn clone(&self) -> Self { - State { config: self.config.clone(), zero: self.zero.clone(), storage: self.storage } - } -} - -/// Create state where changes tries are disabled. -pub fn disabled_state<'a, H, Number>() -> Option> { - None -} - -/// Compute the changes trie root and transaction for given block. -/// Returns Err(()) if unknown `parent_hash` has been passed. -/// Returns Ok(None) if there's no data to perform computation. -/// Panics if background storage returns an error OR if insert to MemoryDB fails. -pub fn build_changes_trie<'a, B: Backend, H: Hasher, Number: BlockNumber>( - backend: &B, - state: Option<&'a State<'a, H, Number>>, - changes: &OverlayedChanges, - parent_hash: H::Out, - panic_on_storage_error: bool, -) -> Result, H::Out, CacheAction)>, ()> -where - H::Out: Ord + 'static + Encode, -{ - /// Panics when `res.is_err() && panic`, otherwise it returns `Err(())` on an error. - fn maybe_panic( - res: std::result::Result, - panic: bool, - ) -> std::result::Result { - res.map(Ok).unwrap_or_else(|e| { - if panic { - panic!( - "changes trie: storage access is not allowed to fail within runtime: {:?}", - e - ) - } else { - Err(()) - } - }) - } - - // when storage isn't provided, changes tries aren't created - let state = match state { - Some(state) => state, - None => return Ok(None), - }; - - // build_anchor error should not be considered fatal - let parent = state.storage.build_anchor(parent_hash).map_err(|_| ())?; - let block = parent.number.clone() + One::one(); - - // prepare configuration range - we already know zero block. Current block may be the end block - // if configuration has been changed in this block - let is_config_changed = - match changes.storage(sp_core::storage::well_known_keys::CHANGES_TRIE_CONFIG) { - Some(Some(new_config)) => new_config != &state.config.encode()[..], - Some(None) => true, - None => false, - }; - let config_range = ConfigurationRange { - config: &state.config, - zero: state.zero.clone(), - end: if is_config_changed { Some(block.clone()) } else { None }, - }; - - // storage errors are considered fatal (similar to situations when runtime fetches values from - // storage) - let (input_pairs, child_input_pairs, digest_input_blocks) = maybe_panic( - prepare_input::( - backend, - state.storage, - config_range.clone(), - changes, - &parent, - ), - panic_on_storage_error, - )?; - - // prepare cached data - let mut cache_action = prepare_cached_build_data(config_range, block.clone()); - let needs_changed_keys = cache_action.collects_changed_keys(); - cache_action = cache_action.set_digest_input_blocks(digest_input_blocks); - - let mut mdb = MemoryDB::default(); - let mut child_roots = Vec::with_capacity(child_input_pairs.len()); - for (child_index, input_pairs) in child_input_pairs { - let mut not_empty = false; - let mut root = Default::default(); - { - let mut trie = TrieDBMut::::new(&mut mdb, &mut root); - let mut storage_changed_keys = HashSet::new(); - for input_pair in input_pairs { - if needs_changed_keys { - if let Some(key) = input_pair.key() { - storage_changed_keys.insert(key.to_vec()); - } - } - - let (key, value) = input_pair.into(); - not_empty = true; - maybe_panic(trie.insert(&key, &value), panic_on_storage_error)?; - } - - cache_action = - cache_action.insert(Some(child_index.storage_key.clone()), storage_changed_keys); - } - if not_empty { - child_roots.push(input::InputPair::ChildIndex(child_index, root.as_ref().to_vec())); - } - } - let mut root = Default::default(); - { - let mut trie = TrieDBMut::::new(&mut mdb, &mut root); - for (key, value) in child_roots.into_iter().map(Into::into) { - maybe_panic(trie.insert(&key, &value), panic_on_storage_error)?; - } - - let mut storage_changed_keys = HashSet::new(); - for input_pair in input_pairs { - if needs_changed_keys { - if let Some(key) = input_pair.key() { - storage_changed_keys.insert(key.to_vec()); - } - } - - let (key, value) = input_pair.into(); - maybe_panic(trie.insert(&key, &value), panic_on_storage_error)?; - } - - cache_action = cache_action.insert(None, storage_changed_keys); - } - - let cache_action = cache_action.complete(block, &root); - Ok(Some((mdb, root, cache_action))) -} - -/// Prepare empty cached build data for given block. -fn prepare_cached_build_data( - config: ConfigurationRange, - block: Number, -) -> IncompleteCacheAction { - // when digests are not enabled in configuration, we do not need to cache anything - // because it'll never be used again for building other tries - // => let's clear the cache - if !config.config.is_digest_build_enabled() { - return IncompleteCacheAction::Clear - } - - // when this is the last block where current configuration is active - // => let's clear the cache - if config.end.as_ref() == Some(&block) { - return IncompleteCacheAction::Clear - } - - // we do not need to cache anything when top-level digest trie is created, because - // it'll never be used again for building other tries - // => let's clear the cache - match config.config.digest_level_at_block(config.zero.clone(), block) { - Some((digest_level, _, _)) if digest_level == config.config.digest_levels => - IncompleteCacheAction::Clear, - _ => IncompleteCacheAction::CacheBuildData(IncompleteCachedBuildData::new()), - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn cache_is_cleared_when_digests_are_disabled() { - let config = Configuration { digest_interval: 0, digest_levels: 0 }; - let config_range = ConfigurationRange { zero: 0, end: None, config: &config }; - assert_eq!(prepare_cached_build_data(config_range, 8u32), IncompleteCacheAction::Clear); - } - - #[test] - fn build_data_is_cached_when_digests_are_enabled() { - let config = Configuration { digest_interval: 8, digest_levels: 2 }; - let config_range = ConfigurationRange { zero: 0, end: None, config: &config }; - assert!(prepare_cached_build_data(config_range.clone(), 4u32).collects_changed_keys()); - assert!(prepare_cached_build_data(config_range.clone(), 7u32).collects_changed_keys()); - assert!(prepare_cached_build_data(config_range, 8u32).collects_changed_keys()); - } - - #[test] - fn cache_is_cleared_when_digests_are_enabled_and_top_level_digest_is_built() { - let config = Configuration { digest_interval: 8, digest_levels: 2 }; - let config_range = ConfigurationRange { zero: 0, end: None, config: &config }; - assert_eq!(prepare_cached_build_data(config_range, 64u32), IncompleteCacheAction::Clear); - } - - #[test] - fn cache_is_cleared_when_end_block_of_configuration_is_built() { - let config = Configuration { digest_interval: 8, digest_levels: 2 }; - let config_range = ConfigurationRange { zero: 0, end: Some(4u32), config: &config }; - assert_eq!( - prepare_cached_build_data(config_range.clone(), 4u32), - IncompleteCacheAction::Clear - ); - } -} diff --git a/primitives/state-machine/src/changes_trie/prune.rs b/primitives/state-machine/src/changes_trie/prune.rs deleted file mode 100644 index 2ca540562b47..000000000000 --- a/primitives/state-machine/src/changes_trie/prune.rs +++ /dev/null @@ -1,204 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2017-2021 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. - -//! Changes trie pruning-related functions. - -use crate::{ - changes_trie::{ - input::{ChildIndex, InputKey}, - storage::TrieBackendAdapter, - AnchorBlockId, BlockNumber, Storage, - }, - proving_backend::ProvingBackendRecorder, - trie_backend_essence::TrieBackendEssence, -}; -use codec::{Codec, Decode}; -use hash_db::Hasher; -use log::warn; -use num_traits::One; -use sp_trie::Recorder; - -/// Prune obsolete changes tries. Pruning happens at the same block, where highest -/// level digest is created. Pruning guarantees to save changes tries for last -/// `min_blocks_to_keep` blocks. We only prune changes tries at `max_digest_interval` -/// ranges. -pub fn prune( - storage: &dyn Storage, - first: Number, - last: Number, - current_block: &AnchorBlockId, - mut remove_trie_node: F, -) where - H::Out: Codec, -{ - // delete changes trie for every block in range - let mut block = first; - loop { - if block >= last.clone() + One::one() { - break - } - - let prev_block = block.clone(); - block += One::one(); - - let block = prev_block; - let root = match storage.root(current_block, block.clone()) { - Ok(Some(root)) => root, - Ok(None) => continue, - Err(error) => { - // try to delete other tries - warn!(target: "trie", "Failed to read changes trie root from DB: {}", error); - continue - }, - }; - let children_roots = { - let trie_storage = TrieBackendEssence::<_, H>::new( - crate::changes_trie::TrieBackendStorageAdapter(storage), - root, - ); - let child_prefix = ChildIndex::key_neutral_prefix(block.clone()); - let mut children_roots = Vec::new(); - trie_storage.for_key_values_with_prefix(&child_prefix, |mut key, mut value| { - if let Ok(InputKey::ChildIndex::(_trie_key)) = Decode::decode(&mut key) { - if let Ok(value) = >::decode(&mut value) { - let mut trie_root = ::Out::default(); - trie_root.as_mut().copy_from_slice(&value[..]); - children_roots.push(trie_root); - } - } - }); - - children_roots - }; - for root in children_roots.into_iter() { - prune_trie(storage, root, &mut remove_trie_node); - } - - prune_trie(storage, root, &mut remove_trie_node); - } -} - -// Prune a trie. -fn prune_trie( - storage: &dyn Storage, - root: H::Out, - remove_trie_node: &mut F, -) where - H::Out: Codec, -{ - // enumerate all changes trie' keys, recording all nodes that have been 'touched' - // (effectively - all changes trie nodes) - let mut proof_recorder: Recorder = Default::default(); - { - let mut trie = ProvingBackendRecorder::<_, H> { - backend: &TrieBackendEssence::new(TrieBackendAdapter::new(storage), root), - proof_recorder: &mut proof_recorder, - }; - trie.record_all_keys(); - } - - // all nodes of this changes trie should be pruned - remove_trie_node(root); - for node in proof_recorder.drain().into_iter().map(|n| n.hash) { - remove_trie_node(node); - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::{backend::insert_into_memory_db, changes_trie::storage::InMemoryStorage}; - use codec::Encode; - use sp_core::H256; - use sp_runtime::traits::BlakeTwo256; - use sp_trie::MemoryDB; - use std::collections::HashSet; - - fn prune_by_collect( - storage: &dyn Storage, - first: u64, - last: u64, - current_block: u64, - ) -> HashSet { - let mut pruned_trie_nodes = HashSet::new(); - let anchor = AnchorBlockId { hash: Default::default(), number: current_block }; - prune(storage, first, last, &anchor, |node| { - pruned_trie_nodes.insert(node); - }); - pruned_trie_nodes - } - - #[test] - fn prune_works() { - fn prepare_storage() -> InMemoryStorage { - let child_info = sp_core::storage::ChildInfo::new_default(&b"1"[..]); - let child_key = - ChildIndex { block: 67u64, storage_key: child_info.prefixed_storage_key() } - .encode(); - let mut mdb1 = MemoryDB::::default(); - let root1 = - insert_into_memory_db::(&mut mdb1, vec![(vec![10], vec![20])]) - .unwrap(); - let mut mdb2 = MemoryDB::::default(); - let root2 = insert_into_memory_db::( - &mut mdb2, - vec![(vec![11], vec![21]), (vec![12], vec![22])], - ) - .unwrap(); - let mut mdb3 = MemoryDB::::default(); - let ch_root3 = - insert_into_memory_db::(&mut mdb3, vec![(vec![110], vec![120])]) - .unwrap(); - let root3 = insert_into_memory_db::( - &mut mdb3, - vec![ - (vec![13], vec![23]), - (vec![14], vec![24]), - (child_key, ch_root3.as_ref().encode()), - ], - ) - .unwrap(); - let mut mdb4 = MemoryDB::::default(); - let root4 = - insert_into_memory_db::(&mut mdb4, vec![(vec![15], vec![25])]) - .unwrap(); - let storage = InMemoryStorage::new(); - storage.insert(65, root1, mdb1); - storage.insert(66, root2, mdb2); - storage.insert(67, root3, mdb3); - storage.insert(68, root4, mdb4); - - storage - } - - let storage = prepare_storage(); - assert!(prune_by_collect(&storage, 20, 30, 90).is_empty()); - assert!(!storage.into_mdb().drain().is_empty()); - - let storage = prepare_storage(); - let prune60_65 = prune_by_collect(&storage, 60, 65, 90); - assert!(!prune60_65.is_empty()); - storage.remove_from_storage(&prune60_65); - assert!(!storage.into_mdb().drain().is_empty()); - - let storage = prepare_storage(); - let prune60_70 = prune_by_collect(&storage, 60, 70, 90); - assert!(!prune60_70.is_empty()); - storage.remove_from_storage(&prune60_70); - assert!(storage.into_mdb().drain().is_empty()); - } -} diff --git a/primitives/state-machine/src/changes_trie/storage.rs b/primitives/state-machine/src/changes_trie/storage.rs deleted file mode 100644 index bd5e3a32b565..000000000000 --- a/primitives/state-machine/src/changes_trie/storage.rs +++ /dev/null @@ -1,214 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2017-2021 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. - -//! Changes trie storage utilities. - -use crate::{ - changes_trie::{AnchorBlockId, BlockNumber, BuildCache, RootsStorage, Storage}, - trie_backend_essence::TrieBackendStorage, - StorageKey, -}; -use hash_db::{Hasher, Prefix, EMPTY_PREFIX}; -use parking_lot::RwLock; -use sp_core::storage::PrefixedStorageKey; -use sp_trie::{DBValue, MemoryDB}; -use std::collections::{BTreeMap, HashMap, HashSet}; - -#[cfg(test)] -use crate::backend::insert_into_memory_db; -#[cfg(test)] -use crate::changes_trie::input::{ChildIndex, InputPair}; - -/// In-memory implementation of changes trie storage. -pub struct InMemoryStorage { - data: RwLock>, - cache: BuildCache, -} - -/// Adapter for using changes trie storage as a TrieBackendEssence' storage. -pub struct TrieBackendAdapter<'a, H: Hasher, Number: BlockNumber> { - storage: &'a dyn Storage, - _hasher: std::marker::PhantomData<(H, Number)>, -} - -struct InMemoryStorageData { - roots: BTreeMap, - mdb: MemoryDB, -} - -impl InMemoryStorage { - /// Creates storage from given in-memory database. - pub fn with_db(mdb: MemoryDB) -> Self { - Self { - data: RwLock::new(InMemoryStorageData { roots: BTreeMap::new(), mdb }), - cache: BuildCache::new(), - } - } - - /// Creates storage with empty database. - pub fn new() -> Self { - Self::with_db(Default::default()) - } - - /// Creates storage with given proof. - pub fn with_proof(proof: Vec>) -> Self { - use hash_db::HashDB; - - let mut proof_db = MemoryDB::::default(); - for item in proof { - proof_db.insert(EMPTY_PREFIX, &item); - } - Self::with_db(proof_db) - } - - /// Get mutable cache reference. - pub fn cache_mut(&mut self) -> &mut BuildCache { - &mut self.cache - } - - /// Create the storage with given blocks. - pub fn with_blocks(blocks: Vec<(Number, H::Out)>) -> Self { - Self { - data: RwLock::new(InMemoryStorageData { - roots: blocks.into_iter().collect(), - mdb: MemoryDB::default(), - }), - cache: BuildCache::new(), - } - } - - #[cfg(test)] - pub fn with_inputs( - mut top_inputs: Vec<(Number, Vec>)>, - children_inputs: Vec<(PrefixedStorageKey, Vec<(Number, Vec>)>)>, - ) -> Self { - let mut mdb = MemoryDB::default(); - let mut roots = BTreeMap::new(); - for (storage_key, child_input) in children_inputs { - for (block, pairs) in child_input { - let root = - insert_into_memory_db::(&mut mdb, pairs.into_iter().map(Into::into)); - - if let Some(root) = root { - let ix = if let Some(ix) = top_inputs.iter().position(|v| v.0 == block) { - ix - } else { - top_inputs.push((block.clone(), Default::default())); - top_inputs.len() - 1 - }; - top_inputs[ix].1.push(InputPair::ChildIndex( - ChildIndex { block: block.clone(), storage_key: storage_key.clone() }, - root.as_ref().to_vec(), - )); - } - } - } - - for (block, pairs) in top_inputs { - let root = insert_into_memory_db::(&mut mdb, pairs.into_iter().map(Into::into)); - if let Some(root) = root { - roots.insert(block, root); - } - } - - InMemoryStorage { - data: RwLock::new(InMemoryStorageData { roots, mdb }), - cache: BuildCache::new(), - } - } - - #[cfg(test)] - pub fn clear_storage(&self) { - self.data.write().mdb = MemoryDB::default(); // use new to be more correct - } - - #[cfg(test)] - pub fn remove_from_storage(&self, keys: &HashSet) { - let mut data = self.data.write(); - for key in keys { - data.mdb.remove_and_purge(key, hash_db::EMPTY_PREFIX); - } - } - - #[cfg(test)] - pub fn into_mdb(self) -> MemoryDB { - self.data.into_inner().mdb - } - - /// Insert changes trie for given block. - pub fn insert(&self, block: Number, changes_trie_root: H::Out, trie: MemoryDB) { - let mut data = self.data.write(); - data.roots.insert(block, changes_trie_root); - data.mdb.consolidate(trie); - } -} - -impl RootsStorage for InMemoryStorage { - fn build_anchor(&self, parent_hash: H::Out) -> Result, String> { - self.data - .read() - .roots - .iter() - .find(|(_, v)| **v == parent_hash) - .map(|(k, _)| AnchorBlockId { hash: parent_hash, number: k.clone() }) - .ok_or_else(|| format!("Can't find associated number for block {:?}", parent_hash)) - } - - fn root( - &self, - _anchor_block: &AnchorBlockId, - block: Number, - ) -> Result, String> { - Ok(self.data.read().roots.get(&block).cloned()) - } -} - -impl Storage for InMemoryStorage { - fn as_roots_storage(&self) -> &dyn RootsStorage { - self - } - - fn with_cached_changed_keys( - &self, - root: &H::Out, - functor: &mut dyn FnMut(&HashMap, HashSet>), - ) -> bool { - self.cache.with_changed_keys(root, functor) - } - - fn get(&self, key: &H::Out, prefix: Prefix) -> Result, String> { - MemoryDB::::get(&self.data.read().mdb, key, prefix) - } -} - -impl<'a, H: Hasher, Number: BlockNumber> TrieBackendAdapter<'a, H, Number> { - pub fn new(storage: &'a dyn Storage) -> Self { - Self { storage, _hasher: Default::default() } - } -} - -impl<'a, H, Number> TrieBackendStorage for TrieBackendAdapter<'a, H, Number> -where - Number: BlockNumber, - H: Hasher, -{ - type Overlay = MemoryDB; - - fn get(&self, key: &H::Out, prefix: Prefix) -> Result, String> { - self.storage.get(key, prefix) - } -} diff --git a/primitives/state-machine/src/changes_trie/surface_iterator.rs b/primitives/state-machine/src/changes_trie/surface_iterator.rs deleted file mode 100644 index b3e5a490cd18..000000000000 --- a/primitives/state-machine/src/changes_trie/surface_iterator.rs +++ /dev/null @@ -1,326 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2017-2021 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. - -//! The best way to understand how this iterator works is to imagine some 2D terrain that have some -//! mountains (digest changes tries) and valleys (changes tries for regular blocks). There are gems -//! (blocks) beneath the terrain. Given the request to find all gems in the range [X1; X2] this -//! iterator will return **minimal set** of points at the terrain (mountains and valleys) inside -//! this range that have to be drilled down to search for gems. - -use crate::changes_trie::{BlockNumber, ConfigurationRange}; -use num_traits::One; - -/// Returns surface iterator for given range of blocks. -/// -/// `max` is the number of best block, known to caller. We can't access any changes tries -/// that are built after this block, even though we may have them built already. -pub fn surface_iterator<'a, Number: BlockNumber>( - config: ConfigurationRange<'a, Number>, - max: Number, - begin: Number, - end: Number, -) -> Result, String> { - let (current, current_begin, digest_step, digest_level) = - lower_bound_max_digest(config.clone(), max.clone(), begin.clone(), end)?; - Ok(SurfaceIterator { - config, - begin, - max, - current: Some(current), - current_begin, - digest_step, - digest_level, - }) -} - -/// Surface iterator - only traverses top-level digests from given range and tries to find -/// all valid digest changes. -/// -/// Iterator item is the tuple of (last block of the current point + digest level of the current -/// point). Digest level is Some(0) when it is regular block, is Some(non-zero) when it is digest -/// block and None if it is skewed digest block. -pub struct SurfaceIterator<'a, Number: BlockNumber> { - config: ConfigurationRange<'a, Number>, - begin: Number, - max: Number, - current: Option, - current_begin: Number, - digest_step: u32, - digest_level: Option, -} - -impl<'a, Number: BlockNumber> Iterator for SurfaceIterator<'a, Number> { - type Item = Result<(Number, Option), String>; - - fn next(&mut self) -> Option { - let current = self.current.clone()?; - let digest_level = self.digest_level; - - if current < self.digest_step.into() { - self.current = None; - } else { - let next = current.clone() - self.digest_step.into(); - if next.is_zero() || next < self.begin { - self.current = None; - } else if next > self.current_begin { - self.current = Some(next); - } else { - let max_digest_interval = lower_bound_max_digest( - self.config.clone(), - self.max.clone(), - self.begin.clone(), - next, - ); - let (current, current_begin, digest_step, digest_level) = match max_digest_interval - { - Err(err) => return Some(Err(err)), - Ok(range) => range, - }; - - self.current = Some(current); - self.current_begin = current_begin; - self.digest_step = digest_step; - self.digest_level = digest_level; - } - } - - Some(Ok((current, digest_level))) - } -} - -/// Returns parameters of highest level digest block that includes the end of given range -/// and tends to include the whole range. -fn lower_bound_max_digest<'a, Number: BlockNumber>( - config: ConfigurationRange<'a, Number>, - max: Number, - begin: Number, - end: Number, -) -> Result<(Number, Number, u32, Option), String> { - if end > max || begin > end { - return Err(format!("invalid changes range: {}..{}/{}", begin, end, max)) - } - if begin <= config.zero || - config.end.as_ref().map(|config_end| end > *config_end).unwrap_or(false) - { - return Err(format!( - "changes trie range is not covered by configuration: {}..{}/{}..{}", - begin, - end, - config.zero, - match config.end.as_ref() { - Some(config_end) => format!("{}", config_end), - None => "None".into(), - } - )) - } - - let mut digest_level = 0u32; - let mut digest_step = 1u32; - let mut digest_interval = 0u32; - let mut current = end.clone(); - let mut current_begin = begin.clone(); - if current_begin != current { - while digest_level != config.config.digest_levels { - // try to use next level digest - let new_digest_level = digest_level + 1; - let new_digest_step = digest_step * config.config.digest_interval; - let new_digest_interval = config.config.digest_interval * { - if digest_interval == 0 { - 1 - } else { - digest_interval - } - }; - let new_digest_begin = config.zero.clone() + - ((current.clone() - One::one() - config.zero.clone()) / - new_digest_interval.into()) * - new_digest_interval.into(); - let new_digest_end = new_digest_begin.clone() + new_digest_interval.into(); - let new_current = new_digest_begin.clone() + new_digest_interval.into(); - - // check if we met skewed digest - if let Some(skewed_digest_end) = config.end.as_ref() { - if new_digest_end > *skewed_digest_end { - let skewed_digest_start = config.config.prev_max_level_digest_block( - config.zero.clone(), - skewed_digest_end.clone(), - ); - if let Some(skewed_digest_start) = skewed_digest_start { - let skewed_digest_range = (skewed_digest_end.clone() - - skewed_digest_start.clone()) - .try_into() - .ok() - .expect( - "skewed digest range is always <= max level digest range;\ - max level digest range always fits u32; qed", - ); - return Ok(( - skewed_digest_end.clone(), - skewed_digest_start, - skewed_digest_range, - None, - )) - } - } - } - - // we can't use next level digest if it touches any unknown (> max) blocks - if new_digest_end > max { - if begin < new_digest_begin { - current_begin = new_digest_begin; - } - break - } - - // we can (and will) use this digest - digest_level = new_digest_level; - digest_step = new_digest_step; - digest_interval = new_digest_interval; - current = new_current; - current_begin = new_digest_begin; - - // if current digest covers the whole range => no need to use next level digest - if current_begin <= begin && new_digest_end >= end { - break - } - } - } - - Ok((current, current_begin, digest_step, Some(digest_level))) -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::changes_trie::Configuration; - - fn configuration_range<'a>( - config: &'a Configuration, - zero: u64, - ) -> ConfigurationRange<'a, u64> { - ConfigurationRange { config, zero, end: None } - } - - #[test] - fn lower_bound_max_digest_works() { - let config = Configuration { digest_interval: 4, digest_levels: 2 }; - - // when config activates at 0 - assert_eq!( - lower_bound_max_digest(configuration_range(&config, 0u64), 100_000u64, 20u64, 180u64) - .unwrap(), - (192, 176, 16, Some(2)), - ); - - // when config activates at 30 - assert_eq!( - lower_bound_max_digest(configuration_range(&config, 30u64), 100_000u64, 50u64, 210u64) - .unwrap(), - (222, 206, 16, Some(2)), - ); - } - - #[test] - fn surface_iterator_works() { - let config = Configuration { digest_interval: 4, digest_levels: 2 }; - - // when config activates at 0 - assert_eq!( - surface_iterator(configuration_range(&config, 0u64), 100_000u64, 40u64, 180u64,) - .unwrap() - .collect::>(), - vec![ - Ok((192, Some(2))), - Ok((176, Some(2))), - Ok((160, Some(2))), - Ok((144, Some(2))), - Ok((128, Some(2))), - Ok((112, Some(2))), - Ok((96, Some(2))), - Ok((80, Some(2))), - Ok((64, Some(2))), - Ok((48, Some(2))), - ], - ); - - // when config activates at 30 - assert_eq!( - surface_iterator(configuration_range(&config, 30u64), 100_000u64, 40u64, 180u64,) - .unwrap() - .collect::>(), - vec![ - Ok((190, Some(2))), - Ok((174, Some(2))), - Ok((158, Some(2))), - Ok((142, Some(2))), - Ok((126, Some(2))), - Ok((110, Some(2))), - Ok((94, Some(2))), - Ok((78, Some(2))), - Ok((62, Some(2))), - Ok((46, Some(2))), - ], - ); - - // when config activates at 0 AND max block is before next digest - assert_eq!( - surface_iterator(configuration_range(&config, 0u64), 183u64, 40u64, 183u64) - .unwrap() - .collect::>(), - vec![ - Ok((183, Some(0))), - Ok((182, Some(0))), - Ok((181, Some(0))), - Ok((180, Some(1))), - Ok((176, Some(2))), - Ok((160, Some(2))), - Ok((144, Some(2))), - Ok((128, Some(2))), - Ok((112, Some(2))), - Ok((96, Some(2))), - Ok((80, Some(2))), - Ok((64, Some(2))), - Ok((48, Some(2))), - ], - ); - } - - #[test] - fn surface_iterator_works_with_skewed_digest() { - let config = Configuration { digest_interval: 4, digest_levels: 2 }; - let mut config_range = configuration_range(&config, 0u64); - - // when config activates at 0 AND ends at 170 - config_range.end = Some(170); - assert_eq!( - surface_iterator(config_range, 100_000u64, 40u64, 170u64) - .unwrap() - .collect::>(), - vec![ - Ok((170, None)), - Ok((160, Some(2))), - Ok((144, Some(2))), - Ok((128, Some(2))), - Ok((112, Some(2))), - Ok((96, Some(2))), - Ok((80, Some(2))), - Ok((64, Some(2))), - Ok((48, Some(2))), - ], - ); - } -} diff --git a/primitives/state-machine/src/ext.rs b/primitives/state-machine/src/ext.rs index c20d8492fb1f..8f914ab3eee6 100644 --- a/primitives/state-machine/src/ext.rs +++ b/primitives/state-machine/src/ext.rs @@ -28,8 +28,6 @@ use sp_core::storage::{well_known_keys::is_child_storage_key, ChildInfo, Tracked use sp_externalities::{Extension, ExtensionStore, Externalities}; use sp_trie::{empty_child_trie_root, trie_types::Layout}; -#[cfg(feature = "std")] -use crate::changes_trie::State as ChangesTrieState; use crate::{log_error, trace, warn, StorageTransactionCache}; use sp_std::{ any::{Any, TypeId}, @@ -90,62 +88,52 @@ impl error::Error for Error { } /// Wraps a read-only backend, call executor, and current overlayed changes. -pub struct Ext<'a, H, N, B> +pub struct Ext<'a, H, B> where H: Hasher, B: 'a + Backend, - N: crate::changes_trie::BlockNumber, { /// The overlayed changes to write to. overlay: &'a mut OverlayedChanges, /// The storage backend to read from. backend: &'a B, /// The cache for the storage transactions. - storage_transaction_cache: &'a mut StorageTransactionCache, - /// Changes trie state to read from. - #[cfg(feature = "std")] - changes_trie_state: Option>, + storage_transaction_cache: &'a mut StorageTransactionCache, /// Pseudo-unique id used for tracing. pub id: u16, - /// Dummy usage of N arg. - _phantom: sp_std::marker::PhantomData, /// Extensions registered with this instance. #[cfg(feature = "std")] extensions: Option>, } -impl<'a, H, N, B> Ext<'a, H, N, B> +impl<'a, H, B> Ext<'a, H, B> where H: Hasher, B: Backend, - N: crate::changes_trie::BlockNumber, { /// Create a new `Ext`. #[cfg(not(feature = "std"))] pub fn new( overlay: &'a mut OverlayedChanges, - storage_transaction_cache: &'a mut StorageTransactionCache, + storage_transaction_cache: &'a mut StorageTransactionCache, backend: &'a B, ) -> Self { - Ext { overlay, backend, id: 0, storage_transaction_cache, _phantom: Default::default() } + Ext { overlay, backend, id: 0, storage_transaction_cache } } /// Create a new `Ext` from overlayed changes and read-only backend #[cfg(feature = "std")] pub fn new( overlay: &'a mut OverlayedChanges, - storage_transaction_cache: &'a mut StorageTransactionCache, + storage_transaction_cache: &'a mut StorageTransactionCache, backend: &'a B, - changes_trie_state: Option>, extensions: Option<&'a mut sp_externalities::Extensions>, ) -> Self { Self { overlay, backend, - changes_trie_state, storage_transaction_cache, id: rand::random(), - _phantom: Default::default(), extensions: extensions.map(OverlayedExtensions::new), } } @@ -159,12 +147,11 @@ where } #[cfg(test)] -impl<'a, H, N, B> Ext<'a, H, N, B> +impl<'a, H, B> Ext<'a, H, B> where H: Hasher, H::Out: Ord + 'static, B: 'a + Backend, - N: crate::changes_trie::BlockNumber, { pub fn storage_pairs(&self) -> Vec<(StorageKey, StorageValue)> { use std::collections::HashMap; @@ -181,12 +168,11 @@ where } } -impl<'a, H, N, B> Externalities for Ext<'a, H, N, B> +impl<'a, H, B> Externalities for Ext<'a, H, B> where H: Hasher, H::Out: Ord + 'static + codec::Codec, B: Backend, - N: crate::changes_trie::BlockNumber, { fn set_offchain_storage(&mut self, key: &[u8], value: Option<&[u8]>) { self.overlay.set_offchain_storage(key, value) @@ -644,54 +630,6 @@ where .add_transaction_index(IndexOperation::Renew { extrinsic: index, hash: hash.to_vec() }); } - #[cfg(not(feature = "std"))] - fn storage_changes_root(&mut self, _parent_hash: &[u8]) -> Result>, ()> { - Ok(None) - } - - #[cfg(feature = "std")] - fn storage_changes_root(&mut self, mut parent_hash: &[u8]) -> Result>, ()> { - let _guard = guard(); - if let Some(ref root) = self.storage_transaction_cache.changes_trie_transaction_storage_root - { - trace!( - target: "state", - method = "ChangesRoot", - ext_id = %HexDisplay::from(&self.id.to_le_bytes()), - parent_hash = %HexDisplay::from(&parent_hash), - ?root, - cached = true, - ); - - Ok(Some(root.encode())) - } else { - let root = self.overlay.changes_trie_root( - self.backend, - self.changes_trie_state.as_ref(), - Decode::decode(&mut parent_hash).map_err(|e| { - trace!( - target: "state", - error = %e, - "Failed to decode changes root parent hash", - ) - })?, - true, - self.storage_transaction_cache, - ); - - trace!( - target: "state", - method = "ChangesRoot", - ext_id = %HexDisplay::from(&self.id.to_le_bytes()), - parent_hash = %HexDisplay::from(&parent_hash), - ?root, - cached = false, - ); - - root.map(|r| r.map(|o| o.encode())) - } - } - fn storage_start_transaction(&mut self) { self.overlay.start_transaction() } @@ -710,13 +648,7 @@ where self.overlay.rollback_transaction().expect(BENCHMARKING_FN); } self.overlay - .drain_storage_changes( - self.backend, - #[cfg(feature = "std")] - None, - Default::default(), - self.storage_transaction_cache, - ) + .drain_storage_changes(self.backend, Default::default(), self.storage_transaction_cache) .expect(EXT_NOT_ALLOWED_TO_FAIL); self.backend.wipe().expect(EXT_NOT_ALLOWED_TO_FAIL); self.mark_dirty(); @@ -731,13 +663,7 @@ where } let changes = self .overlay - .drain_storage_changes( - self.backend, - #[cfg(feature = "std")] - None, - Default::default(), - self.storage_transaction_cache, - ) + .drain_storage_changes(self.backend, Default::default(), self.storage_transaction_cache) .expect(EXT_NOT_ALLOWED_TO_FAIL); self.backend .commit( @@ -778,12 +704,11 @@ where } } -impl<'a, H, N, B> Ext<'a, H, N, B> +impl<'a, H, B> Ext<'a, H, B> where H: Hasher, H::Out: Ord + 'static + codec::Codec, B: Backend, - N: crate::changes_trie::BlockNumber, { fn limit_remove_from_backend( &mut self, @@ -869,12 +794,11 @@ impl<'a> StorageAppend<'a> { } #[cfg(not(feature = "std"))] -impl<'a, H, N, B> ExtensionStore for Ext<'a, H, N, B> +impl<'a, H, B> ExtensionStore for Ext<'a, H, B> where H: Hasher, H::Out: Ord + 'static + codec::Codec, B: Backend, - N: crate::changes_trie::BlockNumber, { fn extension_by_type_id(&mut self, _type_id: TypeId) -> Option<&mut dyn Any> { None @@ -897,11 +821,10 @@ where } #[cfg(feature = "std")] -impl<'a, H, N, B> ExtensionStore for Ext<'a, H, N, B> +impl<'a, H, B> ExtensionStore for Ext<'a, H, B> where H: Hasher, B: 'a + Backend, - N: crate::changes_trie::BlockNumber, { fn extension_by_type_id(&mut self, type_id: TypeId) -> Option<&mut dyn Any> { self.extensions.as_mut().and_then(|exts| exts.get_mut(type_id)) @@ -938,86 +861,16 @@ where #[cfg(test)] mod tests { use super::*; - use crate::{ - changes_trie::{ - Configuration as ChangesTrieConfiguration, InMemoryStorage as TestChangesTrieStorage, - }, - InMemoryBackend, - }; + use crate::InMemoryBackend; use codec::Encode; - use hex_literal::hex; - use num_traits::Zero; use sp_core::{ map, - storage::{well_known_keys::EXTRINSIC_INDEX, Storage, StorageChild}, - Blake2Hasher, H256, + storage::{Storage, StorageChild}, + Blake2Hasher, }; type TestBackend = InMemoryBackend; - type TestExt<'a> = Ext<'a, Blake2Hasher, u64, TestBackend>; - - fn prepare_overlay_with_changes() -> OverlayedChanges { - let mut changes = OverlayedChanges::default(); - changes.set_collect_extrinsics(true); - changes.set_extrinsic_index(1); - changes.set_storage(vec![1], Some(vec![100])); - changes.set_storage(EXTRINSIC_INDEX.to_vec(), Some(3u32.encode())); - changes.set_offchain_storage(b"k1", Some(b"v1")); - changes.set_offchain_storage(b"k2", Some(b"v2")); - changes - } - - fn changes_trie_config() -> ChangesTrieConfiguration { - ChangesTrieConfiguration { digest_interval: 0, digest_levels: 0 } - } - - #[test] - fn storage_changes_root_is_none_when_storage_is_not_provided() { - let mut overlay = prepare_overlay_with_changes(); - let mut cache = StorageTransactionCache::default(); - let backend = TestBackend::default(); - let mut ext = TestExt::new(&mut overlay, &mut cache, &backend, None, None); - assert_eq!(ext.storage_changes_root(&H256::default().encode()).unwrap(), None); - } - - #[test] - fn storage_changes_root_is_none_when_state_is_not_provided() { - let mut overlay = prepare_overlay_with_changes(); - let mut cache = StorageTransactionCache::default(); - let backend = TestBackend::default(); - let mut ext = TestExt::new(&mut overlay, &mut cache, &backend, None, None); - assert_eq!(ext.storage_changes_root(&H256::default().encode()).unwrap(), None); - } - - #[test] - fn storage_changes_root_is_some_when_extrinsic_changes_are_non_empty() { - let mut overlay = prepare_overlay_with_changes(); - let mut cache = StorageTransactionCache::default(); - let storage = TestChangesTrieStorage::with_blocks(vec![(99, Default::default())]); - let state = Some(ChangesTrieState::new(changes_trie_config(), Zero::zero(), &storage)); - let backend = TestBackend::default(); - let mut ext = TestExt::new(&mut overlay, &mut cache, &backend, state, None); - assert_eq!( - ext.storage_changes_root(&H256::default().encode()).unwrap(), - Some(hex!("bb0c2ef6e1d36d5490f9766cfcc7dfe2a6ca804504c3bb206053890d6dd02376").to_vec()), - ); - } - - #[test] - fn storage_changes_root_is_some_when_extrinsic_changes_are_empty() { - let mut overlay = prepare_overlay_with_changes(); - let mut cache = StorageTransactionCache::default(); - overlay.set_collect_extrinsics(false); - overlay.set_storage(vec![1], None); - let storage = TestChangesTrieStorage::with_blocks(vec![(99, Default::default())]); - let state = Some(ChangesTrieState::new(changes_trie_config(), Zero::zero(), &storage)); - let backend = TestBackend::default(); - let mut ext = TestExt::new(&mut overlay, &mut cache, &backend, state, None); - assert_eq!( - ext.storage_changes_root(&H256::default().encode()).unwrap(), - Some(hex!("96f5aae4690e7302737b6f9b7f8567d5bbb9eac1c315f80101235a92d9ec27f4").to_vec()), - ); - } + type TestExt<'a> = Ext<'a, Blake2Hasher, TestBackend>; #[test] fn next_storage_key_works() { @@ -1035,7 +888,7 @@ mod tests { } .into(); - let ext = TestExt::new(&mut overlay, &mut cache, &backend, None, None); + let ext = TestExt::new(&mut overlay, &mut cache, &backend, None); // next_backend < next_overlay assert_eq!(ext.next_storage_key(&[5]), Some(vec![10])); @@ -1051,7 +904,7 @@ mod tests { drop(ext); overlay.set_storage(vec![50], Some(vec![50])); - let ext = TestExt::new(&mut overlay, &mut cache, &backend, None, None); + let ext = TestExt::new(&mut overlay, &mut cache, &backend, None); // next_overlay exist but next_backend doesn't exist assert_eq!(ext.next_storage_key(&[40]), Some(vec![50])); @@ -1079,7 +932,7 @@ mod tests { } .into(); - let ext = TestExt::new(&mut overlay, &mut cache, &backend, None, None); + let ext = TestExt::new(&mut overlay, &mut cache, &backend, None); assert_eq!(ext.next_storage_key(&[5]), Some(vec![30])); @@ -1110,7 +963,7 @@ mod tests { } .into(); - let ext = TestExt::new(&mut overlay, &mut cache, &backend, None, None); + let ext = TestExt::new(&mut overlay, &mut cache, &backend, None); // next_backend < next_overlay assert_eq!(ext.next_child_storage_key(child_info, &[5]), Some(vec![10])); @@ -1126,7 +979,7 @@ mod tests { drop(ext); overlay.set_child_storage(child_info, vec![50], Some(vec![50])); - let ext = TestExt::new(&mut overlay, &mut cache, &backend, None, None); + let ext = TestExt::new(&mut overlay, &mut cache, &backend, None); // next_overlay exist but next_backend doesn't exist assert_eq!(ext.next_child_storage_key(child_info, &[40]), Some(vec![50])); @@ -1155,7 +1008,7 @@ mod tests { } .into(); - let ext = TestExt::new(&mut overlay, &mut cache, &backend, None, None); + let ext = TestExt::new(&mut overlay, &mut cache, &backend, None); assert_eq!(ext.child_storage(child_info, &[10]), Some(vec![10])); assert_eq!( @@ -1192,7 +1045,7 @@ mod tests { } .into(); - let ext = TestExt::new(&mut overlay, &mut cache, &backend, None, None); + let ext = TestExt::new(&mut overlay, &mut cache, &backend, None); use sp_core::storage::well_known_keys; let mut ext = ext; diff --git a/primitives/state-machine/src/lib.rs b/primitives/state-machine/src/lib.rs index b0178021f313..f7477e232bc6 100644 --- a/primitives/state-machine/src/lib.rs +++ b/primitives/state-machine/src/lib.rs @@ -23,8 +23,6 @@ pub mod backend; #[cfg(feature = "std")] mod basic; -#[cfg(feature = "std")] -mod changes_trie; mod error; mod ext; #[cfg(feature = "std")] @@ -140,28 +138,10 @@ pub use crate::{ }; pub use error::{Error, ExecutionError}; -#[cfg(not(feature = "std"))] -mod changes_trie { - /// Stub for change trie block number until - /// change trie move to no_std. - pub trait BlockNumber {} - - impl BlockNumber for N {} -} - #[cfg(feature = "std")] mod std_reexport { pub use crate::{ basic::BasicExternalities, - changes_trie::{ - disabled_state as disabled_changes_trie_state, key_changes, key_changes_proof, - key_changes_proof_check, key_changes_proof_check_with_db, prune as prune_changes_tries, - AnchorBlockId as ChangesTrieAnchorBlockId, BlockNumber as ChangesTrieBlockNumber, - BuildCache as ChangesTrieBuildCache, CacheAction as ChangesTrieCacheAction, - ConfigurationRange as ChangesTrieConfigurationRange, - InMemoryStorage as InMemoryChangesTrieStorage, RootsStorage as ChangesTrieRootsStorage, - State as ChangesTrieState, Storage as ChangesTrieStorage, - }, error::{Error, ExecutionError}, in_memory_backend::new_in_mem, proving_backend::{ @@ -205,10 +185,6 @@ mod execution { /// Default handler of the execution manager. pub type DefaultHandler = fn(CallResult, CallResult) -> CallResult; - /// Type of changes trie transaction. - pub type ChangesTrieTransaction = - (MemoryDB, ChangesTrieCacheAction<::Out, N>); - /// Trie backend with in-memory storage. pub type InMemoryBackend = TrieBackend, H>; @@ -308,11 +284,10 @@ mod execution { } /// The substrate state machine. - pub struct StateMachine<'a, B, H, N, Exec> + pub struct StateMachine<'a, B, H, Exec> where H: Hasher, B: Backend, - N: ChangesTrieBlockNumber, { backend: &'a B, exec: &'a Exec, @@ -320,8 +295,7 @@ mod execution { call_data: &'a [u8], overlay: &'a mut OverlayedChanges, extensions: Extensions, - changes_trie_state: Option>, - storage_transaction_cache: Option<&'a mut StorageTransactionCache>, + storage_transaction_cache: Option<&'a mut StorageTransactionCache>, runtime_code: &'a RuntimeCode<'a>, stats: StateMachineStats, /// The hash of the block the state machine will be executed on. @@ -330,29 +304,26 @@ mod execution { parent_hash: Option, } - impl<'a, B, H, N, Exec> Drop for StateMachine<'a, B, H, N, Exec> + impl<'a, B, H, Exec> Drop for StateMachine<'a, B, H, Exec> where H: Hasher, B: Backend, - N: ChangesTrieBlockNumber, { fn drop(&mut self) { self.backend.register_overlay_stats(&self.stats); } } - impl<'a, B, H, N, Exec> StateMachine<'a, B, H, N, Exec> + impl<'a, B, H, Exec> StateMachine<'a, B, H, Exec> where H: Hasher, H::Out: Ord + 'static + codec::Codec, Exec: CodeExecutor + Clone + 'static, B: Backend, - N: crate::changes_trie::BlockNumber, { /// Creates new substrate state machine. pub fn new( backend: &'a B, - changes_trie_state: Option>, overlay: &'a mut OverlayedChanges, exec: &'a Exec, method: &'a str, @@ -371,7 +342,6 @@ mod execution { call_data, extensions, overlay, - changes_trie_state, storage_transaction_cache: None, runtime_code, stats: StateMachineStats::default(), @@ -386,7 +356,7 @@ mod execution { /// build that will be cached. pub fn with_storage_transaction_cache( mut self, - cache: Option<&'a mut StorageTransactionCache>, + cache: Option<&'a mut StorageTransactionCache>, ) -> Self { self.storage_transaction_cache = cache; self @@ -439,13 +409,7 @@ mod execution { .enter_runtime() .expect("StateMachine is never called from the runtime; qed"); - let mut ext = Ext::new( - self.overlay, - cache, - self.backend, - self.changes_trie_state.clone(), - Some(&mut self.extensions), - ); + let mut ext = Ext::new(self.overlay, cache, self.backend, Some(&mut self.extensions)); let ext_id = ext.id; @@ -562,9 +526,6 @@ mod execution { CallResult, ) -> CallResult, { - let changes_tries_enabled = self.changes_trie_state.is_some(); - self.overlay.set_collect_extrinsics(changes_tries_enabled); - let result = { match manager { ExecutionManager::Both(on_consensus_failure) => self @@ -588,7 +549,7 @@ mod execution { } /// Prove execution using the given state backend, overlayed changes, and call executor. - pub fn prove_execution( + pub fn prove_execution( backend: &mut B, overlay: &mut OverlayedChanges, exec: &Exec, @@ -602,13 +563,12 @@ mod execution { H: Hasher, H::Out: Ord + 'static + codec::Codec, Exec: CodeExecutor + Clone + 'static, - N: crate::changes_trie::BlockNumber, Spawn: SpawnNamed + Send + 'static, { let trie_backend = backend .as_trie_backend() .ok_or_else(|| Box::new(ExecutionError::UnableToGenerateProof) as Box)?; - prove_execution_on_trie_backend::<_, _, N, _, _>( + prove_execution_on_trie_backend::<_, _, _, _>( trie_backend, overlay, exec, @@ -628,7 +588,7 @@ mod execution { /// /// Note: changes to code will be in place if this call is made again. For running partial /// blocks (e.g. a transaction at a time), ensure a different method is used. - pub fn prove_execution_on_trie_backend( + pub fn prove_execution_on_trie_backend( trie_backend: &TrieBackend, overlay: &mut OverlayedChanges, exec: &Exec, @@ -642,13 +602,11 @@ mod execution { H: Hasher, H::Out: Ord + 'static + codec::Codec, Exec: CodeExecutor + 'static + Clone, - N: crate::changes_trie::BlockNumber, Spawn: SpawnNamed + Send + 'static, { let proving_backend = proving_backend::ProvingBackend::new(trie_backend); - let mut sm = StateMachine::<_, H, N, Exec>::new( + let mut sm = StateMachine::<_, H, Exec>::new( &proving_backend, - None, overlay, exec, method, @@ -667,7 +625,7 @@ mod execution { } /// Check execution proof, generated by `prove_execution` call. - pub fn execution_proof_check( + pub fn execution_proof_check( root: H::Out, proof: StorageProof, overlay: &mut OverlayedChanges, @@ -681,11 +639,10 @@ mod execution { H: Hasher, Exec: CodeExecutor + Clone + 'static, H::Out: Ord + 'static + codec::Codec, - N: crate::changes_trie::BlockNumber, Spawn: SpawnNamed + Send + 'static, { let trie_backend = create_proof_check_backend::(root.into(), proof)?; - execution_proof_check_on_trie_backend::<_, N, _, _>( + execution_proof_check_on_trie_backend::<_, _, _>( &trie_backend, overlay, exec, @@ -697,7 +654,7 @@ mod execution { } /// Check execution proof on proving backend, generated by `prove_execution` call. - pub fn execution_proof_check_on_trie_backend( + pub fn execution_proof_check_on_trie_backend( trie_backend: &TrieBackend, H>, overlay: &mut OverlayedChanges, exec: &Exec, @@ -710,12 +667,10 @@ mod execution { H: Hasher, H::Out: Ord + 'static + codec::Codec, Exec: CodeExecutor + Clone + 'static, - N: crate::changes_trie::BlockNumber, Spawn: SpawnNamed + Send + 'static, { - let mut sm = StateMachine::<_, H, N, Exec>::new( + let mut sm = StateMachine::<_, H, Exec>::new( trie_backend, - None, overlay, exec, method, @@ -1390,7 +1345,7 @@ mod execution { #[cfg(test)] mod tests { - use super::{changes_trie::Configuration as ChangesTrieConfig, ext::Ext, *}; + use super::{ext::Ext, *}; use crate::execution::CallResult; use codec::{Decode, Encode}; use sp_core::{ @@ -1409,7 +1364,6 @@ mod tests { #[derive(Clone)] struct DummyCodeExecutor { - change_changes_trie_config: bool, native_available: bool, native_succeeds: bool, fallback_succeeds: bool, @@ -1430,13 +1384,6 @@ mod tests { use_native: bool, native_call: Option, ) -> (CallResult, bool) { - if self.change_changes_trie_config { - ext.place_storage( - sp_core::storage::well_known_keys::CHANGES_TRIE_CONFIG.to_vec(), - Some(ChangesTrieConfig { digest_interval: 777, digest_levels: 333 }.encode()), - ); - } - let using_native = use_native && self.native_available; match (using_native, self.native_succeeds, self.fallback_succeeds, native_call) { (true, true, _, Some(call)) => { @@ -1472,10 +1419,8 @@ mod tests { let mut state_machine = StateMachine::new( &backend, - changes_trie::disabled_state::<_, u64>(), &mut overlayed_changes, &DummyCodeExecutor { - change_changes_trie_config: false, native_available: true, native_succeeds: true, fallback_succeeds: true, @@ -1498,10 +1443,8 @@ mod tests { let mut state_machine = StateMachine::new( &backend, - changes_trie::disabled_state::<_, u64>(), &mut overlayed_changes, &DummyCodeExecutor { - change_changes_trie_config: false, native_available: true, native_succeeds: true, fallback_succeeds: true, @@ -1525,10 +1468,8 @@ mod tests { let mut state_machine = StateMachine::new( &backend, - changes_trie::disabled_state::<_, u64>(), &mut overlayed_changes, &DummyCodeExecutor { - change_changes_trie_config: false, native_available: true, native_succeeds: true, fallback_succeeds: false, @@ -1555,7 +1496,6 @@ mod tests { #[test] fn prove_execution_and_proof_check_works() { let executor = DummyCodeExecutor { - change_changes_trie_config: false, native_available: true, native_succeeds: true, fallback_succeeds: true, @@ -1564,7 +1504,7 @@ mod tests { // fetch execution proof from 'remote' full node let mut remote_backend = trie_backend::tests::test_trie(); let remote_root = remote_backend.storage_root(std::iter::empty()).0; - let (remote_result, remote_proof) = prove_execution::<_, _, u64, _, _>( + let (remote_result, remote_proof) = prove_execution( &mut remote_backend, &mut Default::default(), &executor, @@ -1576,7 +1516,7 @@ mod tests { .unwrap(); // check proof locally - let local_result = execution_proof_check::( + let local_result = execution_proof_check::( remote_root, remote_proof, &mut Default::default(), @@ -1614,13 +1554,7 @@ mod tests { let overlay_limit = overlay.clone(); { let mut cache = StorageTransactionCache::default(); - let mut ext = Ext::new( - &mut overlay, - &mut cache, - backend, - changes_trie::disabled_state::<_, u64>(), - None, - ); + let mut ext = Ext::new(&mut overlay, &mut cache, backend, None); ext.clear_prefix(b"ab", None); } overlay.commit_transaction().unwrap(); @@ -1644,13 +1578,7 @@ mod tests { let mut overlay = overlay_limit; { let mut cache = StorageTransactionCache::default(); - let mut ext = Ext::new( - &mut overlay, - &mut cache, - backend, - changes_trie::disabled_state::<_, u64>(), - None, - ); + let mut ext = Ext::new(&mut overlay, &mut cache, backend, None); assert_eq!((false, 1), ext.clear_prefix(b"ab", Some(1))); } overlay.commit_transaction().unwrap(); @@ -1692,13 +1620,7 @@ mod tests { { let mut cache = StorageTransactionCache::default(); - let mut ext = Ext::new( - &mut overlay, - &mut cache, - &backend, - changes_trie::disabled_state::<_, u64>(), - None, - ); + let mut ext = Ext::new(&mut overlay, &mut cache, &backend, None); assert_eq!(ext.kill_child_storage(&child_info, Some(2)), (false, 2)); } @@ -1733,13 +1655,7 @@ mod tests { let backend = InMemoryBackend::::from(initial); let mut overlay = OverlayedChanges::default(); let mut cache = StorageTransactionCache::default(); - let mut ext = Ext::new( - &mut overlay, - &mut cache, - &backend, - changes_trie::disabled_state::<_, u64>(), - None, - ); + let mut ext = Ext::new(&mut overlay, &mut cache, &backend, None); assert_eq!(ext.kill_child_storage(&child_info, Some(0)), (false, 0)); assert_eq!(ext.kill_child_storage(&child_info, Some(1)), (false, 1)); assert_eq!(ext.kill_child_storage(&child_info, Some(2)), (false, 2)); @@ -1758,13 +1674,7 @@ mod tests { let backend = state.as_trie_backend().unwrap(); let mut overlay = OverlayedChanges::default(); let mut cache = StorageTransactionCache::default(); - let mut ext = Ext::new( - &mut overlay, - &mut cache, - backend, - changes_trie::disabled_state::<_, u64>(), - None, - ); + let mut ext = Ext::new(&mut overlay, &mut cache, backend, None); ext.set_child_storage(child_info, b"abc".to_vec(), b"def".to_vec()); assert_eq!(ext.child_storage(child_info, b"abc"), Some(b"def".to_vec())); @@ -1781,26 +1691,14 @@ mod tests { let mut overlay = OverlayedChanges::default(); let mut cache = StorageTransactionCache::default(); { - let mut ext = Ext::new( - &mut overlay, - &mut cache, - backend, - changes_trie::disabled_state::<_, u64>(), - None, - ); + let mut ext = Ext::new(&mut overlay, &mut cache, backend, None); ext.storage_append(key.clone(), reference_data[0].encode()); assert_eq!(ext.storage(key.as_slice()), Some(vec![reference_data[0].clone()].encode())); } overlay.start_transaction(); { - let mut ext = Ext::new( - &mut overlay, - &mut cache, - backend, - changes_trie::disabled_state::<_, u64>(), - None, - ); + let mut ext = Ext::new(&mut overlay, &mut cache, backend, None); for i in reference_data.iter().skip(1) { ext.storage_append(key.clone(), i.encode()); @@ -1809,13 +1707,7 @@ mod tests { } overlay.rollback_transaction().unwrap(); { - let ext = Ext::new( - &mut overlay, - &mut cache, - backend, - changes_trie::disabled_state::<_, u64>(), - None, - ); + let ext = Ext::new(&mut overlay, &mut cache, backend, None); assert_eq!(ext.storage(key.as_slice()), Some(vec![reference_data[0].clone()].encode())); } } @@ -1837,13 +1729,7 @@ mod tests { // For example, block initialization with event. { - let mut ext = Ext::new( - &mut overlay, - &mut cache, - backend, - changes_trie::disabled_state::<_, u64>(), - None, - ); + let mut ext = Ext::new(&mut overlay, &mut cache, backend, None); ext.clear_storage(key.as_slice()); ext.storage_append(key.clone(), Item::InitializationItem.encode()); } @@ -1851,13 +1737,7 @@ mod tests { // For example, first transaction resulted in panic during block building { - let mut ext = Ext::new( - &mut overlay, - &mut cache, - backend, - changes_trie::disabled_state::<_, u64>(), - None, - ); + let mut ext = Ext::new(&mut overlay, &mut cache, backend, None); assert_eq!(ext.storage(key.as_slice()), Some(vec![Item::InitializationItem].encode())); @@ -1872,13 +1752,7 @@ mod tests { // Then we apply next transaction which is valid this time. { - let mut ext = Ext::new( - &mut overlay, - &mut cache, - backend, - changes_trie::disabled_state::<_, u64>(), - None, - ); + let mut ext = Ext::new(&mut overlay, &mut cache, backend, None); assert_eq!(ext.storage(key.as_slice()), Some(vec![Item::InitializationItem].encode())); @@ -1893,13 +1767,7 @@ mod tests { // Then only initlaization item and second (committed) item should persist. { - let ext = Ext::new( - &mut overlay, - &mut cache, - backend, - changes_trie::disabled_state::<_, u64>(), - None, - ); + let ext = Ext::new(&mut overlay, &mut cache, backend, None); assert_eq!( ext.storage(key.as_slice()), Some(vec![Item::InitializationItem, Item::CommitedItem].encode()), @@ -2214,13 +2082,7 @@ mod tests { let mut transaction = { let backend = test_trie(); let mut cache = StorageTransactionCache::default(); - let mut ext = Ext::new( - &mut overlay, - &mut cache, - &backend, - changes_trie::disabled_state::<_, u64>(), - None, - ); + let mut ext = Ext::new(&mut overlay, &mut cache, &backend, None); ext.set_child_storage(&child_info_1, b"abc".to_vec(), b"def".to_vec()); ext.set_child_storage(&child_info_2, b"abc".to_vec(), b"def".to_vec()); ext.storage_root(); @@ -2257,13 +2119,7 @@ mod tests { { let mut cache = StorageTransactionCache::default(); - let mut ext = Ext::new( - &mut overlay, - &mut cache, - backend, - changes_trie::disabled_state::<_, u64>(), - None, - ); + let mut ext = Ext::new(&mut overlay, &mut cache, backend, None); assert_eq!(ext.storage(b"bbb"), Some(vec![])); assert_eq!(ext.storage(b"ccc"), Some(vec![])); ext.clear_storage(b"ccc"); @@ -2286,10 +2142,8 @@ mod tests { let mut state_machine = StateMachine::new( &backend, - changes_trie::disabled_state::<_, u64>(), &mut overlayed_changes, &DummyCodeExecutor { - change_changes_trie_config: false, native_available: true, native_succeeds: true, fallback_succeeds: false, @@ -2301,7 +2155,7 @@ mod tests { TaskExecutor::new(), ); - let run_state_machine = |state_machine: &mut StateMachine<_, _, _, _>| { + let run_state_machine = |state_machine: &mut StateMachine<_, _, _>| { state_machine .execute_using_consensus_failure_handler:: _, _, _>( ExecutionManager::NativeWhenPossible, diff --git a/primitives/state-machine/src/overlayed_changes/changeset.rs b/primitives/state-machine/src/overlayed_changes/changeset.rs index 1ffd569e2828..818b7be99bc6 100644 --- a/primitives/state-machine/src/overlayed_changes/changeset.rs +++ b/primitives/state-machine/src/overlayed_changes/changeset.rs @@ -69,7 +69,6 @@ struct InnerValue { /// Current value. None if value has been deleted. value: V, /// The set of extrinsic indices where the values has been changed. - /// Is filled only if runtime has announced changes trie support. extrinsics: Extrinsics, } diff --git a/primitives/state-machine/src/overlayed_changes/mod.rs b/primitives/state-machine/src/overlayed_changes/mod.rs index cf7af1c9a6f3..b7a535792aae 100644 --- a/primitives/state-machine/src/overlayed_changes/mod.rs +++ b/primitives/state-machine/src/overlayed_changes/mod.rs @@ -21,12 +21,7 @@ mod changeset; mod offchain; use self::changeset::OverlayedChangeSet; -use crate::{backend::Backend, changes_trie::BlockNumber, stats::StateMachineStats, DefaultError}; -#[cfg(feature = "std")] -use crate::{ - changes_trie::{build_changes_trie, State as ChangesTrieState}, - ChangesTrieTransaction, -}; +use crate::{backend::Backend, stats::StateMachineStats, DefaultError}; use codec::{Decode, Encode}; use hash_db::Hasher; pub use offchain::OffchainOverlayedChanges; @@ -134,7 +129,7 @@ pub enum IndexOperation { /// /// This contains all the changes to the storage and transactions to apply theses changes to the /// backend. -pub struct StorageChanges { +pub struct StorageChanges { /// All changes to the main storage. /// /// A value of `None` means that it was deleted. @@ -150,22 +145,13 @@ pub struct StorageChanges { pub transaction: Transaction, /// The storage root after applying the transaction. pub transaction_storage_root: H::Out, - /// Contains the transaction for the backend for the changes trie. - /// - /// If changes trie is disabled the value is set to `None`. - #[cfg(feature = "std")] - pub changes_trie_transaction: Option>, - /// Phantom data for block number until change trie support no_std. - #[cfg(not(feature = "std"))] - pub _ph: sp_std::marker::PhantomData, - /// Changes to the transaction index, #[cfg(feature = "std")] pub transaction_index_changes: Vec, } #[cfg(feature = "std")] -impl StorageChanges { +impl StorageChanges { /// Deconstruct into the inner values pub fn into_inner( self, @@ -175,7 +161,6 @@ impl StorageChanges { OffchainChangesCollection, Transaction, H::Out, - Option>, Vec, ) { ( @@ -184,58 +169,35 @@ impl StorageChanges { self.offchain_storage_changes, self.transaction, self.transaction_storage_root, - self.changes_trie_transaction, self.transaction_index_changes, ) } } -/// The storage transaction are calculated as part of the `storage_root` and -/// `changes_trie_storage_root`. These transactions can be reused for importing the block into the +/// Storage transactions are calculated as part of the `storage_root`. +/// These transactions can be reused for importing the block into the /// storage. So, we cache them to not require a recomputation of those transactions. -pub struct StorageTransactionCache { +pub struct StorageTransactionCache { /// Contains the changes for the main and the child storages as one transaction. pub(crate) transaction: Option, /// The storage root after applying the transaction. pub(crate) transaction_storage_root: Option, - /// Contains the changes trie transaction. - #[cfg(feature = "std")] - pub(crate) changes_trie_transaction: Option>>, - /// The storage root after applying the changes trie transaction. - #[cfg(feature = "std")] - pub(crate) changes_trie_transaction_storage_root: Option>, - /// Phantom data for block number until change trie support no_std. - #[cfg(not(feature = "std"))] - pub(crate) _ph: sp_std::marker::PhantomData, } -impl StorageTransactionCache { +impl StorageTransactionCache { /// Reset the cached transactions. pub fn reset(&mut self) { *self = Self::default(); } } -impl Default - for StorageTransactionCache -{ +impl Default for StorageTransactionCache { fn default() -> Self { - Self { - transaction: None, - transaction_storage_root: None, - #[cfg(feature = "std")] - changes_trie_transaction: None, - #[cfg(feature = "std")] - changes_trie_transaction_storage_root: None, - #[cfg(not(feature = "std"))] - _ph: Default::default(), - } + Self { transaction: None, transaction_storage_root: None } } } -impl Default - for StorageChanges -{ +impl Default for StorageChanges { fn default() -> Self { Self { main_storage_changes: Default::default(), @@ -244,10 +206,6 @@ impl Default transaction: Default::default(), transaction_storage_root: Default::default(), #[cfg(feature = "std")] - changes_trie_transaction: None, - #[cfg(not(feature = "std"))] - _ph: Default::default(), - #[cfg(feature = "std")] transaction_index_changes: Default::default(), } } @@ -539,27 +497,25 @@ impl OverlayedChanges { /// Convert this instance with all changes into a [`StorageChanges`] instance. #[cfg(feature = "std")] - pub fn into_storage_changes, H: Hasher, N: BlockNumber>( + pub fn into_storage_changes, H: Hasher>( mut self, backend: &B, - changes_trie_state: Option<&ChangesTrieState>, parent_hash: H::Out, - mut cache: StorageTransactionCache, - ) -> Result, DefaultError> + mut cache: StorageTransactionCache, + ) -> Result, DefaultError> where H::Out: Ord + Encode + 'static, { - self.drain_storage_changes(backend, changes_trie_state, parent_hash, &mut cache) + self.drain_storage_changes(backend, parent_hash, &mut cache) } /// Drain all changes into a [`StorageChanges`] instance. Leave empty overlay in place. - pub fn drain_storage_changes, H: Hasher, N: BlockNumber>( + pub fn drain_storage_changes, H: Hasher>( &mut self, backend: &B, - #[cfg(feature = "std")] changes_trie_state: Option<&ChangesTrieState>, - parent_hash: H::Out, - mut cache: &mut StorageTransactionCache, - ) -> Result, DefaultError> + _parent_hash: H::Out, + mut cache: &mut StorageTransactionCache, + ) -> Result, DefaultError> where H::Out: Ord + Encode + 'static, { @@ -574,21 +530,6 @@ impl OverlayedChanges { .and_then(|t| cache.transaction_storage_root.take().map(|tr| (t, tr))) .expect("Transaction was be generated as part of `storage_root`; qed"); - // If the transaction does not exist, we generate it. - #[cfg(feature = "std")] - if cache.changes_trie_transaction.is_none() { - self.changes_trie_root(backend, changes_trie_state, parent_hash, false, &mut cache) - .map_err(|_| "Failed to generate changes trie transaction")?; - } - #[cfg(not(feature = "std"))] - let _ = parent_hash; - - #[cfg(feature = "std")] - let changes_trie_transaction = cache - .changes_trie_transaction - .take() - .expect("Changes trie transaction was generated by `changes_trie_root`; qed"); - let (main_storage_changes, child_storage_changes) = self.drain_committed(); let offchain_storage_changes = self.offchain_drain_committed().collect(); @@ -604,11 +545,7 @@ impl OverlayedChanges { transaction, transaction_storage_root, #[cfg(feature = "std")] - changes_trie_transaction, - #[cfg(feature = "std")] transaction_index_changes, - #[cfg(not(feature = "std"))] - _ph: Default::default(), }) } @@ -639,10 +576,10 @@ impl OverlayedChanges { /// as seen by the current transaction. /// /// Returns the storage root and caches storage transaction in the given `cache`. - pub fn storage_root>( + pub fn storage_root>( &self, backend: &B, - cache: &mut StorageTransactionCache, + cache: &mut StorageTransactionCache, ) -> H::Out where H::Out: Ord + Encode, @@ -660,40 +597,6 @@ impl OverlayedChanges { root } - /// Generate the changes trie root. - /// - /// Returns the changes trie root and caches the storage transaction into the given `cache`. - /// - /// # Panics - /// - /// Panics on storage error, when `panic_on_storage_error` is set. - #[cfg(feature = "std")] - pub fn changes_trie_root<'a, H: Hasher, N: BlockNumber, B: Backend>( - &self, - backend: &B, - changes_trie_state: Option<&'a ChangesTrieState<'a, H, N>>, - parent_hash: H::Out, - panic_on_storage_error: bool, - cache: &mut StorageTransactionCache, - ) -> Result, ()> - where - H::Out: Ord + Encode + 'static, - { - build_changes_trie::<_, H, N>( - backend, - changes_trie_state, - self, - parent_hash, - panic_on_storage_error, - ) - .map(|r| { - let root = r.as_ref().map(|r| r.1).clone(); - cache.changes_trie_transaction = Some(r.map(|(db, _, cache)| (db, cache))); - cache.changes_trie_transaction_storage_root = Some(root); - root - }) - } - /// Returns an iterator over the keys (in lexicographic order) following `key` (excluding `key`) /// alongside its value. pub fn iter_after(&self, key: &[u8]) -> impl Iterator { @@ -937,7 +840,6 @@ mod tests { .collect(); let backend = InMemoryBackend::::from(initial); let mut overlay = OverlayedChanges::default(); - overlay.set_collect_extrinsics(false); overlay.start_transaction(); overlay.set_storage(b"dog".to_vec(), Some(b"puppy".to_vec())); @@ -950,13 +852,7 @@ mod tests { overlay.set_storage(b"doug".to_vec(), None); let mut cache = StorageTransactionCache::default(); - let mut ext = Ext::new( - &mut overlay, - &mut cache, - &backend, - crate::changes_trie::disabled_state::<_, u64>(), - None, - ); + let mut ext = Ext::new(&mut overlay, &mut cache, &backend, None); const ROOT: [u8; 32] = hex!("39245109cef3758c2eed2ccba8d9b370a917850af3824bc8348d505df2c298fa"); diff --git a/primitives/state-machine/src/read_only.rs b/primitives/state-machine/src/read_only.rs index 5b7d568b0311..b3e43d4c46e7 100644 --- a/primitives/state-machine/src/read_only.rs +++ b/primitives/state-machine/src/read_only.rs @@ -153,10 +153,6 @@ impl<'a, H: Hasher, B: 'a + Backend> Externalities for ReadOnlyExternalities< unimplemented!("child_storage_root is not supported in ReadOnlyExternalities") } - fn storage_changes_root(&mut self, _parent: &[u8]) -> Result>, ()> { - unimplemented!("storage_changes_root is not supported in ReadOnlyExternalities") - } - fn storage_start_transaction(&mut self) { unimplemented!("Transactions are not supported by ReadOnlyExternalities"); } diff --git a/primitives/state-machine/src/testing.rs b/primitives/state-machine/src/testing.rs index 23f66ee14d87..59a0a5a6837e 100644 --- a/primitives/state-machine/src/testing.rs +++ b/primitives/state-machine/src/testing.rs @@ -23,21 +23,15 @@ use std::{ }; use crate::{ - backend::Backend, - changes_trie::{ - BlockNumber as ChangesTrieBlockNumber, Configuration as ChangesTrieConfiguration, - InMemoryStorage as ChangesTrieInMemoryStorage, State as ChangesTrieState, - }, - ext::Ext, - InMemoryBackend, OverlayedChanges, StorageKey, StorageTransactionCache, StorageValue, + backend::Backend, ext::Ext, InMemoryBackend, OverlayedChanges, StorageKey, + StorageTransactionCache, StorageValue, }; -use codec::Decode; use hash_db::Hasher; use sp_core::{ offchain::testing::TestPersistentOffchainDB, storage::{ - well_known_keys::{is_child_storage_key, CHANGES_TRIE_CONFIG, CODE}, + well_known_keys::{is_child_storage_key, CODE}, Storage, }, testing::TaskExecutor, @@ -46,7 +40,7 @@ use sp_core::{ use sp_externalities::{Extension, ExtensionStore, Extensions}; /// Simple HashMap-based Externalities impl. -pub struct TestExternalities +pub struct TestExternalities where H::Out: codec::Codec + Ord, { @@ -54,33 +48,23 @@ where overlay: OverlayedChanges, offchain_db: TestPersistentOffchainDB, storage_transaction_cache: - StorageTransactionCache< as Backend>::Transaction, H, N>, + StorageTransactionCache< as Backend>::Transaction, H>, /// Storage backend. pub backend: InMemoryBackend, - changes_trie_config: Option, - changes_trie_storage: ChangesTrieInMemoryStorage, /// Extensions. pub extensions: Extensions, } -impl TestExternalities +impl TestExternalities where H::Out: Ord + 'static + codec::Codec, { /// Get externalities implementation. - pub fn ext(&mut self) -> Ext> { + pub fn ext(&mut self) -> Ext> { Ext::new( &mut self.overlay, &mut self.storage_transaction_cache, &self.backend, - match self.changes_trie_config.clone() { - Some(config) => Some(ChangesTrieState { - config, - zero: 0.into(), - storage: &self.changes_trie_storage, - }), - None => None, - }, Some(&mut self.extensions), ) } @@ -97,12 +81,7 @@ where /// Create a new instance of `TestExternalities` with code and storage. pub fn new_with_code(code: &[u8], mut storage: Storage) -> Self { - let mut overlay = OverlayedChanges::default(); - let changes_trie_config = storage - .top - .get(CHANGES_TRIE_CONFIG) - .and_then(|v| Decode::decode(&mut &v[..]).ok()); - overlay.set_collect_extrinsics(changes_trie_config.is_some()); + let overlay = OverlayedChanges::default(); assert!(storage.top.keys().all(|key| !is_child_storage_key(key))); assert!(storage.children_default.keys().all(|key| is_child_storage_key(key))); @@ -117,9 +96,7 @@ where TestExternalities { overlay, offchain_db, - changes_trie_config, extensions, - changes_trie_storage: ChangesTrieInMemoryStorage::new(), backend: storage.into(), storage_transaction_cache: Default::default(), } @@ -150,11 +127,6 @@ where self.extensions.register(ext); } - /// Get mutable reference to changes trie storage. - pub fn changes_trie_storage(&mut self) -> &mut ChangesTrieInMemoryStorage { - &mut self.changes_trie_storage - } - /// Return a new backend with all pending changes. /// /// In contrast to [`commit_all`](Self::commit_all) this will not panic if there are open @@ -180,9 +152,8 @@ where /// /// This will panic if there are still open transactions. pub fn commit_all(&mut self) -> Result<(), String> { - let changes = self.overlay.drain_storage_changes::<_, _, N>( + let changes = self.overlay.drain_storage_changes::<_, _>( &self.backend, - None, Default::default(), &mut Default::default(), )?; @@ -216,7 +187,7 @@ where } } -impl std::fmt::Debug for TestExternalities +impl std::fmt::Debug for TestExternalities where H::Out: Ord + codec::Codec, { @@ -225,18 +196,18 @@ where } } -impl PartialEq for TestExternalities +impl PartialEq for TestExternalities where H::Out: Ord + 'static + codec::Codec, { /// This doesn't test if they are in the same state, only if they contains the /// same data at this state - fn eq(&self, other: &TestExternalities) -> bool { + fn eq(&self, other: &TestExternalities) -> bool { self.as_backend().eq(&other.as_backend()) } } -impl Default for TestExternalities +impl Default for TestExternalities where H::Out: Ord + 'static + codec::Codec, { @@ -245,7 +216,7 @@ where } } -impl From for TestExternalities +impl From for TestExternalities where H::Out: Ord + 'static + codec::Codec, { @@ -254,11 +225,10 @@ where } } -impl sp_externalities::ExtensionStore for TestExternalities +impl sp_externalities::ExtensionStore for TestExternalities where H: Hasher, H::Out: Ord + codec::Codec, - N: ChangesTrieBlockNumber, { fn extension_by_type_id(&mut self, type_id: TypeId) -> Option<&mut dyn Any> { self.extensions.get_mut(type_id) @@ -284,11 +254,10 @@ where } } -impl sp_externalities::ExternalitiesExt for TestExternalities +impl sp_externalities::ExternalitiesExt for TestExternalities where H: Hasher, H::Out: Ord + codec::Codec, - N: ChangesTrieBlockNumber, { fn extension(&mut self) -> Option<&mut T> { self.extension_by_type_id(TypeId::of::()).and_then(::downcast_mut) @@ -312,7 +281,7 @@ mod tests { #[test] fn commit_should_work() { - let mut ext = TestExternalities::::default(); + let mut ext = TestExternalities::::default(); let mut ext = ext.ext(); ext.set_storage(b"doe".to_vec(), b"reindeer".to_vec()); ext.set_storage(b"dog".to_vec(), b"puppy".to_vec()); @@ -324,7 +293,7 @@ mod tests { #[test] fn set_and_retrieve_code() { - let mut ext = TestExternalities::::default(); + let mut ext = TestExternalities::::default(); let mut ext = ext.ext(); let code = vec![1, 2, 3]; @@ -336,12 +305,12 @@ mod tests { #[test] fn check_send() { fn assert_send() {} - assert_send::>(); + assert_send::>(); } #[test] fn commit_all_and_kill_child_storage() { - let mut ext = TestExternalities::::default(); + let mut ext = TestExternalities::::default(); let child_info = ChildInfo::new_default(&b"test_child"[..]); { @@ -366,7 +335,7 @@ mod tests { #[test] fn as_backend_generates_same_backend_as_commit_all() { - let mut ext = TestExternalities::::default(); + let mut ext = TestExternalities::::default(); { let mut ext = ext.ext(); ext.set_storage(b"doe".to_vec(), b"reindeer".to_vec()); diff --git a/primitives/storage/src/lib.rs b/primitives/storage/src/lib.rs index 45474a44693a..1144e258e0e2 100644 --- a/primitives/storage/src/lib.rs +++ b/primitives/storage/src/lib.rs @@ -204,9 +204,6 @@ pub mod well_known_keys { /// Current extrinsic index (u32) is stored under this key. pub const EXTRINSIC_INDEX: &'static [u8] = b":extrinsic_index"; - /// Changes trie configuration is stored under this key. - pub const CHANGES_TRIE_CONFIG: &'static [u8] = b":changes_trie"; - /// Prefix of child storage keys. pub const CHILD_STORAGE_KEY_PREFIX: &'static [u8] = b":child_storage:"; diff --git a/primitives/tasks/src/async_externalities.rs b/primitives/tasks/src/async_externalities.rs index 975a81af4f53..59733490a18f 100644 --- a/primitives/tasks/src/async_externalities.rs +++ b/primitives/tasks/src/async_externalities.rs @@ -134,10 +134,6 @@ impl Externalities for AsyncExternalities { panic!("`child_storage_root`: should not be used in async externalities!") } - fn storage_changes_root(&mut self, _parent: &[u8]) -> Result>, ()> { - panic!("`storage_changes_root`: should not be used in async externalities!") - } - fn storage_start_transaction(&mut self) { unimplemented!("Transactions are not supported by AsyncExternalities"); } diff --git a/primitives/test-primitives/src/lib.rs b/primitives/test-primitives/src/lib.rs index d988160b1dc7..341839a1deb2 100644 --- a/primitives/test-primitives/src/lib.rs +++ b/primitives/test-primitives/src/lib.rs @@ -73,15 +73,10 @@ pub type BlockNumber = u64; /// Index of a transaction. pub type Index = u64; /// The item of a block digest. -pub type DigestItem = sp_runtime::generic::DigestItem; +pub type DigestItem = sp_runtime::generic::DigestItem; /// The digest of a block. -pub type Digest = sp_runtime::generic::Digest; +pub type Digest = sp_runtime::generic::Digest; /// A test block. pub type Block = sp_runtime::generic::Block; /// A test block's header. pub type Header = sp_runtime::generic::Header; - -/// Changes trie configuration (optionally) used in tests. -pub fn changes_trie_config() -> sp_core::ChangesTrieConfiguration { - sp_core::ChangesTrieConfiguration { digest_interval: 4, digest_levels: 2 } -} diff --git a/test-utils/client/Cargo.toml b/test-utils/client/Cargo.toml index a8b2e8f57ac5..1277863c94f7 100644 --- a/test-utils/client/Cargo.toml +++ b/test-utils/client/Cargo.toml @@ -23,7 +23,6 @@ sc-client-db = { version = "0.10.0-dev", features = [ ], path = "../../client/db" } sc-consensus = { version = "0.10.0-dev", path = "../../client/consensus/common" } sc-executor = { version = "0.10.0-dev", path = "../../client/executor" } -sc-light = { version = "4.0.0-dev", path = "../../client/light" } sc-offchain = { version = "4.0.0-dev", path = "../../client/offchain" } sc-service = { version = "0.10.0-dev", default-features = false, features = [ "test-helpers", diff --git a/test-utils/client/src/lib.rs b/test-utils/client/src/lib.rs index 9bc411af5d3e..2d1cb4bbc66a 100644 --- a/test-utils/client/src/lib.rs +++ b/test-utils/client/src/lib.rs @@ -45,21 +45,13 @@ use sc_client_api::BlockchainEvents; use sc_service::client::{ClientConfig, LocalCallExecutor}; use serde::Deserialize; use sp_core::storage::ChildInfo; -use sp_runtime::{ - codec::Encode, - traits::{BlakeTwo256, Block as BlockT}, - OpaqueExtrinsic, -}; +use sp_runtime::{codec::Encode, traits::Block as BlockT, OpaqueExtrinsic}; use std::{ collections::{HashMap, HashSet}, pin::Pin, sync::Arc, }; -/// Test client light database backend. -pub type LightBackend = - sc_light::Backend, BlakeTwo256>; - /// A genesis storage initialization trait. pub trait GenesisInit: Default { /// Construct genesis storage. diff --git a/test-utils/runtime/client/Cargo.toml b/test-utils/runtime/client/Cargo.toml index fbc6aefdb850..e5cba3a3399a 100644 --- a/test-utils/runtime/client/Cargo.toml +++ b/test-utils/runtime/client/Cargo.toml @@ -12,7 +12,6 @@ publish = false targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sc-light = { version = "4.0.0-dev", path = "../../../client/light" } sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" } sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/common" } sc-block-builder = { version = "0.10.0-dev", path = "../../../client/block-builder" } diff --git a/test-utils/runtime/client/src/block_builder_ext.rs b/test-utils/runtime/client/src/block_builder_ext.rs index e8c1d2ac5cd4..4519dce65960 100644 --- a/test-utils/runtime/client/src/block_builder_ext.rs +++ b/test-utils/runtime/client/src/block_builder_ext.rs @@ -19,7 +19,6 @@ use sc_client_api::backend; use sp_api::{ApiExt, ProvideRuntimeApi}; -use sp_core::ChangesTrieConfiguration; use sc_block_builder::BlockBuilderApi; @@ -36,11 +35,6 @@ pub trait BlockBuilderExt { key: Vec, value: Option>, ) -> Result<(), sp_blockchain::Error>; - /// Add changes trie configuration update extrinsic to the block. - fn push_changes_trie_configuration_update( - &mut self, - new_config: Option, - ) -> Result<(), sp_blockchain::Error>; } impl<'a, A, B> BlockBuilderExt @@ -68,11 +62,4 @@ where ) -> Result<(), sp_blockchain::Error> { self.push(substrate_test_runtime::Extrinsic::StorageChange(key, value)) } - - fn push_changes_trie_configuration_update( - &mut self, - new_config: Option, - ) -> Result<(), sp_blockchain::Error> { - self.push(substrate_test_runtime::Extrinsic::ChangesTrieConfigUpdate(new_config)) - } } diff --git a/test-utils/runtime/client/src/lib.rs b/test-utils/runtime/client/src/lib.rs index da92e0f37983..2948e918cdf8 100644 --- a/test-utils/runtime/client/src/lib.rs +++ b/test-utils/runtime/client/src/lib.rs @@ -24,22 +24,18 @@ pub mod trait_tests; mod block_builder_ext; pub use sc_consensus::LongestChain; -use std::{collections::HashMap, sync::Arc}; +use std::sync::Arc; pub use substrate_test_client::*; pub use substrate_test_runtime as runtime; pub use self::block_builder_ext::BlockBuilderExt; -use sc_client_api::light::{ - Fetcher, RemoteBodyRequest, RemoteCallRequest, RemoteChangesRequest, RemoteHeaderRequest, - RemoteReadChildRequest, RemoteReadRequest, -}; use sp_core::{ sr25519, storage::{ChildInfo, Storage, StorageChild}, - ChangesTrieConfiguration, Pair, + Pair, }; -use sp_runtime::traits::{Block as BlockT, Hash as HashT, HashFor, Header as HeaderT, NumberFor}; +use sp_runtime::traits::{Block as BlockT, Hash as HashT, Header as HeaderT}; use substrate_test_runtime::genesismap::{additional_storage_with_genesis, GenesisConfig}; /// A prelude to import in tests. @@ -51,8 +47,8 @@ pub mod prelude { }; // Client structs pub use super::{ - Backend, ExecutorDispatch, LightBackend, LightExecutor, LocalExecutorDispatch, - NativeElseWasmExecutor, TestClient, TestClientBuilder, WasmExecutionMethod, + Backend, ExecutorDispatch, LocalExecutorDispatch, NativeElseWasmExecutor, TestClient, + TestClientBuilder, WasmExecutionMethod, }; // Keyring pub use super::{AccountKeyring, Sr25519Keyring}; @@ -84,26 +80,9 @@ pub type ExecutorDispatch = client::LocalCallExecutor< NativeElseWasmExecutor, >; -/// Test client light database backend. -pub type LightBackend = substrate_test_client::LightBackend; - -/// Test client light executor. -pub type LightExecutor = sc_light::GenesisCallExecutor< - LightBackend, - client::LocalCallExecutor< - substrate_test_runtime::Block, - sc_light::Backend< - sc_client_db::light::LightStorage, - HashFor, - >, - NativeElseWasmExecutor, - >, ->; - /// Parameters of test-client builder with test-runtime. #[derive(Default)] pub struct GenesisParameters { - changes_trie_config: Option, heap_pages_override: Option, extra_storage: Storage, wasm_code: Option>, @@ -112,7 +91,6 @@ pub struct GenesisParameters { impl GenesisParameters { fn genesis_config(&self) -> GenesisConfig { GenesisConfig::new( - self.changes_trie_config.clone(), vec![ sr25519::Public::from(Sr25519Keyring::Alice).into(), sr25519::Public::from(Sr25519Keyring::Bob).into(), @@ -215,12 +193,6 @@ pub trait TestClientBuilderExt: Sized { /// Returns a mutable reference to the genesis parameters. fn genesis_init_mut(&mut self) -> &mut GenesisParameters; - /// Set changes trie configuration for genesis. - fn changes_trie_config(mut self, config: Option) -> Self { - self.genesis_init_mut().changes_trie_config = config; - self - } - /// Override the default value for Wasm heap pages. fn set_heap_pages(mut self, heap_pages: u64) -> Self { self.genesis_init_mut().heap_pages_override = Some(heap_pages); @@ -308,142 +280,11 @@ impl TestClientBuilderExt } } -/// Type of optional fetch callback. -type MaybeFetcherCallback = - Option Result + Send + Sync>>; - -/// Type of fetcher future result. -type FetcherFutureResult = futures::future::Ready>; - -/// Implementation of light client fetcher used in tests. -#[derive(Default)] -pub struct LightFetcher { - call: MaybeFetcherCallback, Vec>, - body: MaybeFetcherCallback< - RemoteBodyRequest, - Vec, - >, -} - -impl LightFetcher { - /// Sets remote call callback. - pub fn with_remote_call( - self, - call: MaybeFetcherCallback, Vec>, - ) -> Self { - LightFetcher { call, body: self.body } - } - - /// Sets remote body callback. - pub fn with_remote_body( - self, - body: MaybeFetcherCallback< - RemoteBodyRequest, - Vec, - >, - ) -> Self { - LightFetcher { call: self.call, body } - } -} - -impl Fetcher for LightFetcher { - type RemoteHeaderResult = FetcherFutureResult; - type RemoteReadResult = FetcherFutureResult, Option>>>; - type RemoteCallResult = FetcherFutureResult>; - type RemoteChangesResult = - FetcherFutureResult, u32)>>; - type RemoteBodyResult = FetcherFutureResult>; - - fn remote_header( - &self, - _: RemoteHeaderRequest, - ) -> Self::RemoteHeaderResult { - unimplemented!() - } - - fn remote_read( - &self, - _: RemoteReadRequest, - ) -> Self::RemoteReadResult { - unimplemented!() - } - - fn remote_read_child( - &self, - _: RemoteReadChildRequest, - ) -> Self::RemoteReadResult { - unimplemented!() - } - - fn remote_call( - &self, - req: RemoteCallRequest, - ) -> Self::RemoteCallResult { - match self.call { - Some(ref call) => futures::future::ready(call(req)), - None => unimplemented!(), - } - } - - fn remote_changes( - &self, - _: RemoteChangesRequest, - ) -> Self::RemoteChangesResult { - unimplemented!() - } - - fn remote_body( - &self, - req: RemoteBodyRequest, - ) -> Self::RemoteBodyResult { - match self.body { - Some(ref body) => futures::future::ready(body(req)), - None => unimplemented!(), - } - } -} - /// Creates new client instance used for tests. pub fn new() -> Client { TestClientBuilder::new().build() } -/// Creates new light client instance used for tests. -pub fn new_light() -> ( - client::Client< - LightBackend, - LightExecutor, - substrate_test_runtime::Block, - substrate_test_runtime::RuntimeApi, - >, - Arc, -) { - let storage = sc_client_db::light::LightStorage::new_test(); - let blockchain = Arc::new(sc_light::Blockchain::new(storage)); - let backend = Arc::new(LightBackend::new(blockchain)); - let executor = new_native_executor(); - let local_call_executor = client::LocalCallExecutor::new( - backend.clone(), - executor, - Box::new(sp_core::testing::TaskExecutor::new()), - Default::default(), - ) - .expect("Creates LocalCallExecutor"); - let call_executor = LightExecutor::new(backend.clone(), local_call_executor); - - ( - TestClientBuilder::with_backend(backend.clone()) - .build_with_executor(call_executor) - .0, - backend, - ) -} - -/// Creates new light client fetcher used for tests. -pub fn new_light_fetcher() -> LightFetcher { - LightFetcher::default() -} - /// Create a new native executor. pub fn new_native_executor() -> sc_executor::NativeElseWasmExecutor { sc_executor::NativeElseWasmExecutor::new(sc_executor::WasmExecutionMethod::Interpreted, None, 8) diff --git a/test-utils/runtime/src/genesismap.rs b/test-utils/runtime/src/genesismap.rs index a8801b8519df..a06d9f310fb0 100644 --- a/test-utils/runtime/src/genesismap.rs +++ b/test-utils/runtime/src/genesismap.rs @@ -23,7 +23,6 @@ use sc_service::client::genesis; use sp_core::{ map, storage::{well_known_keys, Storage}, - ChangesTrieConfiguration, }; use sp_io::hashing::{blake2_256, twox_128}; use sp_runtime::traits::{Block as BlockT, Hash as HashT, Header as HeaderT}; @@ -31,7 +30,6 @@ use std::collections::BTreeMap; /// Configuration of a general Substrate test genesis block. pub struct GenesisConfig { - changes_trie_config: Option, authorities: Vec, balances: Vec<(AccountId, u64)>, heap_pages_override: Option, @@ -41,7 +39,6 @@ pub struct GenesisConfig { impl GenesisConfig { pub fn new( - changes_trie_config: Option, authorities: Vec, endowed_accounts: Vec, balance: u64, @@ -49,7 +46,6 @@ impl GenesisConfig { extra_storage: Storage, ) -> Self { GenesisConfig { - changes_trie_config, authorities, balances: endowed_accounts.into_iter().map(|a| (a, balance)).collect(), heap_pages_override, @@ -77,9 +73,6 @@ impl GenesisConfig { .into_iter(), ) .collect(); - if let Some(ref changes_trie_config) = self.changes_trie_config { - map.insert(well_known_keys::CHANGES_TRIE_CONFIG.to_vec(), changes_trie_config.encode()); - } map.insert(twox_128(&b"sys:auth"[..])[..].to_vec(), self.authorities.encode()); // Add the extra storage entries. map.extend(self.extra_storage.top.clone().into_iter()); diff --git a/test-utils/runtime/src/lib.rs b/test-utils/runtime/src/lib.rs index 943c41c247f7..08863de510d0 100644 --- a/test-utils/runtime/src/lib.rs +++ b/test-utils/runtime/src/lib.rs @@ -28,7 +28,7 @@ use scale_info::TypeInfo; use sp_std::{marker::PhantomData, prelude::*}; use sp_application_crypto::{ecdsa, ed25519, sr25519, RuntimeAppPublic}; -use sp_core::{offchain::KeyTypeId, ChangesTrieConfiguration, OpaqueMetadata, RuntimeDebug}; +use sp_core::{offchain::KeyTypeId, OpaqueMetadata, RuntimeDebug}; use sp_trie::{ trie_types::{TrieDB, TrieDBMut}, PrefixedMemoryDB, StorageProof, @@ -161,7 +161,6 @@ pub enum Extrinsic { }, IncludeData(Vec), StorageChange(Vec, Option>), - ChangesTrieConfigUpdate(Option), OffchainIndexSet(Vec, Vec), OffchainIndexClear(Vec), Store(Vec), @@ -197,8 +196,6 @@ impl BlindCheckable for Extrinsic { }, Extrinsic::IncludeData(v) => Ok(Extrinsic::IncludeData(v)), Extrinsic::StorageChange(key, value) => Ok(Extrinsic::StorageChange(key, value)), - Extrinsic::ChangesTrieConfigUpdate(new_config) => - Ok(Extrinsic::ChangesTrieConfigUpdate(new_config)), Extrinsic::OffchainIndexSet(key, value) => Ok(Extrinsic::OffchainIndexSet(key, value)), Extrinsic::OffchainIndexClear(key) => Ok(Extrinsic::OffchainIndexClear(key)), Extrinsic::Store(data) => Ok(Extrinsic::Store(data)), @@ -265,9 +262,9 @@ pub type BlockNumber = u64; /// Index of a transaction. pub type Index = u64; /// The item of a block digest. -pub type DigestItem = sp_runtime::generic::DigestItem; +pub type DigestItem = sp_runtime::generic::DigestItem; /// The digest of a block. -pub type Digest = sp_runtime::generic::Digest; +pub type Digest = sp_runtime::generic::Digest; /// A test block. pub type Block = sp_runtime::generic::Block; /// A test block's header. @@ -1264,15 +1261,13 @@ fn test_witness(proof: StorageProof, root: crate::Hash) { let db: sp_trie::MemoryDB = proof.into_memory_db(); let backend = sp_state_machine::TrieBackend::<_, crate::Hashing>::new(db, root); let mut overlay = sp_state_machine::OverlayedChanges::default(); - let mut cache = sp_state_machine::StorageTransactionCache::<_, _, BlockNumber>::default(); + let mut cache = sp_state_machine::StorageTransactionCache::<_, _>::default(); let mut ext = sp_state_machine::Ext::new( &mut overlay, &mut cache, &backend, #[cfg(feature = "std")] None, - #[cfg(feature = "std")] - None, ); assert!(ext.storage(b"value3").is_some()); assert!(ext.storage_root().as_slice() == &root[..]); diff --git a/test-utils/runtime/src/system.rs b/test-utils/runtime/src/system.rs index 334569d055a0..165fe0355628 100644 --- a/test-utils/runtime/src/system.rs +++ b/test-utils/runtime/src/system.rs @@ -24,12 +24,8 @@ use crate::{ use codec::{Decode, Encode, KeyedVec}; use frame_support::{decl_module, decl_storage, storage}; use frame_system::Config; -use sp_core::{storage::well_known_keys, ChangesTrieConfiguration}; -use sp_io::{ - hashing::blake2_256, - storage::{changes_root as storage_changes_root, root as storage_root}, - trie, -}; +use sp_core::storage::well_known_keys; +use sp_io::{hashing::blake2_256, storage::root as storage_root, trie}; use sp_runtime::{ generic, traits::Header as _, @@ -54,7 +50,6 @@ decl_storage! { Number get(fn number): Option; ParentHash get(fn parent_hash): Hash; NewAuthorities get(fn new_authorities): Option>; - NewChangesTrieConfig get(fn new_changes_trie_config): Option>; StorageDigest get(fn storage_digest): Option; Authorities get(fn authorities) config(): Vec; } @@ -207,30 +202,17 @@ pub fn finalize_block() -> Header { let mut digest = ::take().expect("StorageDigest is set by `initialize_block`"); let o_new_authorities = ::take(); - let new_changes_trie_config = ::take(); // This MUST come after all changes to storage are done. Otherwise we will fail the // “Storage root does not match that calculated” assertion. let storage_root = Hash::decode(&mut &storage_root()[..]).expect("`storage_root` is a valid hash"); - let storage_changes_root = storage_changes_root(&parent_hash.encode()) - .map(|r| Hash::decode(&mut &r[..]).expect("`storage_changes_root` is a valid hash")); - - if let Some(storage_changes_root) = storage_changes_root { - digest.push(generic::DigestItem::ChangesTrieRoot(storage_changes_root)); - } if let Some(new_authorities) = o_new_authorities { digest.push(generic::DigestItem::Consensus(*b"aura", new_authorities.encode())); digest.push(generic::DigestItem::Consensus(*b"babe", new_authorities.encode())); } - if let Some(new_config) = new_changes_trie_config { - digest.push(generic::DigestItem::ChangesTrieSignal( - generic::ChangesTrieSignal::NewConfiguration(new_config), - )); - } - Header { number, extrinsics_root, state_root: storage_root, parent_hash, digest } } @@ -251,8 +233,6 @@ fn execute_transaction_backend(utx: &Extrinsic, extrinsic_index: u32) -> ApplyEx Extrinsic::IncludeData(_) => Ok(Ok(())), Extrinsic::StorageChange(key, value) => execute_storage_change(key, value.as_ref().map(|v| &**v)), - Extrinsic::ChangesTrieConfigUpdate(ref new_config) => - execute_changes_trie_config_update(new_config.clone()), Extrinsic::OffchainIndexSet(key, value) => { sp_io::offchain_index::set(&key, &value); Ok(Ok(())) @@ -311,18 +291,6 @@ fn execute_storage_change(key: &[u8], value: Option<&[u8]>) -> ApplyExtrinsicRes Ok(Ok(())) } -fn execute_changes_trie_config_update( - new_config: Option, -) -> ApplyExtrinsicResult { - match new_config.clone() { - Some(new_config) => - storage::unhashed::put_raw(well_known_keys::CHANGES_TRIE_CONFIG, &new_config.encode()), - None => storage::unhashed::kill(well_known_keys::CHANGES_TRIE_CONFIG), - } - ::put(new_config); - Ok(Ok(())) -} - #[cfg(feature = "std")] fn info_expect_equal_hash(given: &Hash, expected: &Hash) { use sp_core::hexdisplay::HexDisplay; diff --git a/test-utils/test-runner/src/client.rs b/test-utils/test-runner/src/client.rs index 27c04c40fe6f..c68a33056c16 100644 --- a/test-utils/test-runner/src/client.rs +++ b/test-utils/test-runner/src/client.rs @@ -159,7 +159,6 @@ where transaction_pool: transaction_pool.clone(), spawn_handle: task_manager.spawn_handle(), import_queue, - on_demand: None, block_announce_validator_builder: None, warp_sync: None, }; @@ -195,14 +194,12 @@ where backend: backend.clone(), task_manager: &mut task_manager, keystore: keystore.sync_keystore(), - on_demand: None, transaction_pool: transaction_pool.clone(), rpc_extensions_builder: Box::new(move |_, _| { let mut io = jsonrpc_core::IoHandler::default(); io.extend_with(ManualSealApi::to_delegate(ManualSeal::new(rpc_sink.clone()))); Ok(io) }), - remote_blockchain: None, network, system_rpc_tx, telemetry: None, diff --git a/test-utils/test-runner/src/node.rs b/test-utils/test-runner/src/node.rs index 9114013b747f..07259263c5e4 100644 --- a/test-utils/test-runner/src/node.rs +++ b/test-utils/test-runner/src/node.rs @@ -25,10 +25,7 @@ use futures::{ }; use jsonrpc_core::MetaIoHandler; use manual_seal::EngineCommand; -use sc_client_api::{ - backend::{self, Backend}, - CallExecutor, ExecutorProvider, -}; +use sc_client_api::{backend::Backend, CallExecutor, ExecutorProvider}; use sc_executor::NativeElseWasmExecutor; use sc_service::{TFullBackend, TFullCallExecutor, TFullClient, TaskManager}; use sc_transaction_pool_api::TransactionPool; @@ -160,9 +157,6 @@ where { let id = BlockId::Hash(self.client.info().best_hash); let mut overlay = OverlayedChanges::default(); - let changes_trie = - backend::changes_tries_state_at_block(&id, self.backend.changes_trie_storage()) - .unwrap(); let mut cache = StorageTransactionCache::< T::Block, as Backend>::State, @@ -176,13 +170,7 @@ where .state_at(id.clone()) .expect(&format!("State at block {} not found", id)); - let mut ext = Ext::new( - &mut overlay, - &mut cache, - &state_backend, - changes_trie.clone(), - Some(&mut extensions), - ); + let mut ext = Ext::new(&mut overlay, &mut cache, &state_backend, Some(&mut extensions)); sp_externalities::set_and_run_with_externalities(&mut ext, closure) } diff --git a/utils/frame/benchmarking-cli/src/command.rs b/utils/frame/benchmarking-cli/src/command.rs index 5efa970d9358..48d05dd8dda9 100644 --- a/utils/frame/benchmarking-cli/src/command.rs +++ b/utils/frame/benchmarking-cli/src/command.rs @@ -33,7 +33,7 @@ use sp_core::offchain::{ }; use sp_externalities::Extensions; use sp_keystore::{testing::KeyStore, KeystoreExt, SyncCryptoStorePtr}; -use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor}; +use sp_runtime::traits::{Block as BlockT, Header as HeaderT}; use sp_state_machine::StateMachine; use std::{fmt::Debug, sync::Arc, time}; @@ -152,9 +152,8 @@ impl BenchmarkCmd { // Get Benchmark List let state = &state_without_tracking; - let result = StateMachine::<_, _, NumberFor, _>::new( + let result = StateMachine::new( state, - None, &mut changes, &executor, "Benchmark_benchmark_metadata", @@ -243,9 +242,8 @@ impl BenchmarkCmd { if !self.no_verify { // Dont use these results since verification code will add overhead let state = &state_without_tracking; - let _results = StateMachine::<_, _, NumberFor, _>::new( + let _results = StateMachine::new( state, - None, &mut changes, &executor, "Benchmark_dispatch_benchmark", @@ -270,9 +268,8 @@ impl BenchmarkCmd { // Do one loop of DB tracking. { let state = &state_with_tracking; - let result = StateMachine::<_, _, NumberFor, _>::new( + let result = StateMachine::new( state, // todo remove tracking - None, &mut changes, &executor, "Benchmark_dispatch_benchmark", @@ -303,9 +300,8 @@ impl BenchmarkCmd { // Finally run a bunch of loops to get extrinsic timing information. for r in 0..self.external_repeat { let state = &state_without_tracking; - let result = StateMachine::<_, _, NumberFor, _>::new( + let result = StateMachine::new( state, // todo remove tracking - None, &mut changes, &executor, "Benchmark_dispatch_benchmark", diff --git a/utils/frame/rpc/system/src/lib.rs b/utils/frame/rpc/system/src/lib.rs index f0f37f0b2067..41a5f3ba0eb3 100644 --- a/utils/frame/rpc/system/src/lib.rs +++ b/utils/frame/rpc/system/src/lib.rs @@ -20,14 +20,13 @@ use std::sync::Arc; use codec::{Codec, Decode, Encode}; -use futures::{future::ready, FutureExt, TryFutureExt}; +use futures::FutureExt; use jsonrpc_core::{Error as RpcError, ErrorCode}; use jsonrpc_derive::rpc; -use sc_client_api::light::{future_header, Fetcher, RemoteBlockchain, RemoteCallRequest}; use sc_rpc_api::DenyUnsafe; use sc_transaction_pool_api::{InPoolTransaction, TransactionPool}; use sp_block_builder::BlockBuilder; -use sp_blockchain::{Error as ClientError, HeaderBackend}; +use sp_blockchain::HeaderBackend; use sp_core::{hexdisplay::HexDisplay, Bytes}; use sp_runtime::{generic::BlockId, traits}; @@ -154,90 +153,6 @@ where } } -/// An implementation of System-specific RPC methods on light client. -pub struct LightSystem { - client: Arc, - remote_blockchain: Arc>, - fetcher: Arc, - pool: Arc

, -} - -impl LightSystem { - /// Create new `LightSystem`. - pub fn new( - client: Arc, - remote_blockchain: Arc>, - fetcher: Arc, - pool: Arc

, - ) -> Self { - LightSystem { client, remote_blockchain, fetcher, pool } - } -} - -impl SystemApi<::Hash, AccountId, Index> - for LightSystem -where - P: TransactionPool + 'static, - C: HeaderBackend, - C: Send + Sync + 'static, - F: Fetcher + 'static, - Block: traits::Block, - AccountId: Clone + std::fmt::Display + Codec + Send + 'static, - Index: Clone + std::fmt::Display + Codec + Send + traits::AtLeast32Bit + 'static, -{ - fn nonce(&self, account: AccountId) -> FutureResult { - let best_hash = self.client.info().best_hash; - let best_id = BlockId::hash(best_hash); - let future_best_header = future_header(&*self.remote_blockchain, &*self.fetcher, best_id); - let fetcher = self.fetcher.clone(); - let call_data = account.encode(); - let future_best_header = future_best_header.and_then(move |maybe_best_header| { - ready( - maybe_best_header - .ok_or_else(|| ClientError::UnknownBlock(format!("{}", best_hash))), - ) - }); - - let future_nonce = future_best_header.and_then(move |best_header| { - fetcher.remote_call(RemoteCallRequest { - block: best_hash, - header: best_header, - method: "AccountNonceApi_account_nonce".into(), - call_data, - retry_count: None, - }) - }); - - let future_nonce = future_nonce.and_then(|nonce| async move { - Index::decode(&mut &nonce[..]) - .map_err(|e| ClientError::CallResultDecode("Cannot decode account nonce", e)) - }); - let future_nonce = future_nonce.map_err(|e| RpcError { - code: ErrorCode::ServerError(Error::RuntimeError.into()), - message: "Unable to query nonce.".into(), - data: Some(format!("{:?}", e).into()), - }); - - let pool = self.pool.clone(); - future_nonce.map_ok(move |nonce| adjust_nonce(&*pool, account, nonce)).boxed() - } - - fn dry_run( - &self, - _extrinsic: Bytes, - _at: Option<::Hash>, - ) -> FutureResult { - async { - Err(RpcError { - code: ErrorCode::MethodNotFound, - message: "Unable to dry run extrinsic.".into(), - data: None, - }) - } - .boxed() - } -} - /// Adjust account nonce from state, so that tx with the nonce will be /// placed after all ready txpool transactions. fn adjust_nonce(pool: &P, account: AccountId, nonce: Index) -> Index diff --git a/utils/frame/try-runtime/cli/src/commands/follow_chain.rs b/utils/frame/try-runtime/cli/src/commands/follow_chain.rs index 27fb35dd7a46..70f177dc1f86 100644 --- a/utils/frame/try-runtime/cli/src/commands/follow_chain.rs +++ b/utils/frame/try-runtime/cli/src/commands/follow_chain.rs @@ -152,12 +152,7 @@ where .map_err(|e| format!("failed to decode output: {:?}", e))?; let storage_changes = changes - .drain_storage_changes::<_, _, NumberFor>( - &state_ext.backend, - None, - Default::default(), - &mut Default::default(), - ) + .drain_storage_changes(&state_ext.backend, Default::default(), &mut Default::default()) .unwrap(); state_ext.backend.apply_transaction( storage_changes.transaction_storage_root, diff --git a/utils/frame/try-runtime/cli/src/lib.rs b/utils/frame/try-runtime/cli/src/lib.rs index a74625492bb1..4aa1c213703e 100644 --- a/utils/frame/try-runtime/cli/src/lib.rs +++ b/utils/frame/try-runtime/cli/src/lib.rs @@ -680,9 +680,8 @@ pub(crate) fn state_machine_call sc_cli::Result<(OverlayedChanges, Vec)> { let mut changes = Default::default(); - let encoded_results = StateMachine::<_, _, NumberFor, _>::new( + let encoded_results = StateMachine::new( &ext.backend, - None, &mut changes, executor, method, From 9e8c7b80e9c167dc81244cdae0097d463c1b2e66 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Nov 2021 14:42:26 +0100 Subject: [PATCH 177/695] Bump rustversion from 1.0.4 to 1.0.5 (#10243) Bumps [rustversion](https://github.com/dtolnay/rustversion) from 1.0.4 to 1.0.5. - [Release notes](https://github.com/dtolnay/rustversion/releases) - [Commits](https://github.com/dtolnay/rustversion/compare/1.0.4...1.0.5) --- updated-dependencies: - dependency-name: rustversion dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- frame/support/test/Cargo.toml | 2 +- primitives/api/test/Cargo.toml | 2 +- primitives/runtime-interface/Cargo.toml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 74504d5f1547..998072f2f932 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7510,9 +7510,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb5d2a036dc6d2d8fd16fde3498b04306e29bd193bf306a57427019b823d5acd" +checksum = "61b3909d758bb75c79f23d4736fac9433868679d3ad2ea7a61e3c25cfda9a088" [[package]] name = "rw-stream-sink" diff --git a/frame/support/test/Cargo.toml b/frame/support/test/Cargo.toml index 762c85f75c36..09a1538e2741 100644 --- a/frame/support/test/Cargo.toml +++ b/frame/support/test/Cargo.toml @@ -25,7 +25,7 @@ sp-std = { version = "4.0.0-dev", default-features = false, path = "../../../pri sp-version = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/version" } trybuild = "1.0.52" pretty_assertions = "1.0.0" -rustversion = "1.0.0" +rustversion = "1.0.5" frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" } # The "std" feature for this pallet is never activated on purpose, in order to test construct_runtime error message test-pallet = { package = "frame-support-test-pallet", default-features = false, path = "pallet" } diff --git a/primitives/api/test/Cargo.toml b/primitives/api/test/Cargo.toml index 8c274b386470..dccc123142da 100644 --- a/primitives/api/test/Cargo.toml +++ b/primitives/api/test/Cargo.toml @@ -22,7 +22,7 @@ sc-block-builder = { version = "0.10.0-dev", path = "../../../client/block-build codec = { package = "parity-scale-codec", version = "2.0.0" } sp-state-machine = { version = "0.10.0-dev", path = "../../state-machine" } trybuild = "1.0.52" -rustversion = "1.0.0" +rustversion = "1.0.5" [dev-dependencies] criterion = "0.3.0" diff --git a/primitives/runtime-interface/Cargo.toml b/primitives/runtime-interface/Cargo.toml index c640f02824f2..dd93b92b9be4 100644 --- a/primitives/runtime-interface/Cargo.toml +++ b/primitives/runtime-interface/Cargo.toml @@ -30,7 +30,7 @@ sp-runtime-interface-test-wasm = { version = "2.0.0", path = "test-wasm" } sp-state-machine = { version = "0.10.0-dev", path = "../state-machine" } sp-core = { version = "4.0.0-dev", path = "../core" } sp-io = { version = "4.0.0-dev", path = "../io" } -rustversion = "1.0.0" +rustversion = "1.0.5" trybuild = "1.0.52" [features] From 3f3cc90c06a1e0a7a93dbd5b660a475e9b4a783e Mon Sep 17 00:00:00 2001 From: Sergei Shulepov Date: Fri, 12 Nov 2021 20:38:26 +0100 Subject: [PATCH 178/695] Update requirement for pwasm-utils (#10250) --- client/executor/common/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/executor/common/Cargo.toml b/client/executor/common/Cargo.toml index 276fe9a8380b..1bb057fabad8 100644 --- a/client/executor/common/Cargo.toml +++ b/client/executor/common/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] derive_more = "0.99.2" -pwasm-utils = "0.18.0" +pwasm-utils = "0.18.2" codec = { package = "parity-scale-codec", version = "2.0.0" } wasmi = "0.9.1" sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" } From 54699ec8220fd13fa353f1846db0c923a0fdc310 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 13 Nov 2021 00:32:44 +0000 Subject: [PATCH 179/695] Bump hex-literal from 0.3.3 to 0.3.4 (#10246) Bumps [hex-literal](https://github.com/RustCrypto/utils) from 0.3.3 to 0.3.4. - [Release notes](https://github.com/RustCrypto/utils/releases) - [Commits](https://github.com/RustCrypto/utils/compare/hex-literal-v0.3.3...hex-literal-v0.3.4) --- updated-dependencies: - dependency-name: hex-literal dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- bin/node-template/runtime/Cargo.toml | 2 +- bin/node/cli/Cargo.toml | 2 +- bin/node/runtime/Cargo.toml | 2 +- client/executor/Cargo.toml | 2 +- client/service/test/Cargo.toml | 2 +- frame/benchmarking/Cargo.toml | 2 +- frame/executive/Cargo.toml | 2 +- frame/transaction-storage/Cargo.toml | 2 +- primitives/core/Cargo.toml | 2 +- primitives/state-machine/Cargo.toml | 2 +- primitives/trie/Cargo.toml | 2 +- 12 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 998072f2f932..c90cf1cf5286 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2598,9 +2598,9 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hex-literal" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21e4590e13640f19f249fe3e4eca5113bc4289f2497710378190e7f4bd96f45b" +checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" [[package]] name = "hex_fmt" diff --git a/bin/node-template/runtime/Cargo.toml b/bin/node-template/runtime/Cargo.toml index e4e2039866b4..bff47f5a7ea3 100644 --- a/bin/node-template/runtime/Cargo.toml +++ b/bin/node-template/runtime/Cargo.toml @@ -45,7 +45,7 @@ pallet-transaction-payment-rpc-runtime-api = { version = "4.0.0-dev", default-fe # Used for runtime benchmarking frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../../../frame/benchmarking", optional = true } frame-system-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../../../frame/system/benchmarking", optional = true } -hex-literal = { version = "0.3.3", optional = true } +hex-literal = { version = "0.3.4", optional = true } pallet-template = { version = "3.0.0", default-features = false, path = "../pallets/template" } diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index fc39e47ce411..4e29c7c5314e 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -37,7 +37,7 @@ crate-type = ["cdylib", "rlib"] codec = { package = "parity-scale-codec", version = "2.0.0" } serde = { version = "1.0.126", features = ["derive"] } futures = "0.3.16" -hex-literal = "0.3.3" +hex-literal = "0.3.4" log = "0.4.8" rand = "0.7.2" structopt = { version = "0.3.8", optional = true } diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index c0b888e55b1f..d086b6f12d59 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -20,7 +20,7 @@ codec = { package = "parity-scale-codec", version = "2.2.0", default-features = ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } static_assertions = "1.1.0" -hex-literal = { version = "0.3.3", optional = true } +hex-literal = { version = "0.3.4", optional = true } log = { version = "0.4.14", default-features = false } # primitives diff --git a/client/executor/Cargo.toml b/client/executor/Cargo.toml index 54c4a91d7280..4a8e67810543 100644 --- a/client/executor/Cargo.toml +++ b/client/executor/Cargo.toml @@ -37,7 +37,7 @@ sp-core-hashing-proc-macro = { version = "4.0.0-dev", path = "../../primitives/c [dev-dependencies] wat = "1.0" -hex-literal = "0.3.3" +hex-literal = "0.3.4" sc-runtime-test = { version = "2.0.0", path = "runtime-test" } substrate-test-runtime = { version = "2.0.0", path = "../../test-utils/runtime" } sp-state-machine = { version = "0.10.0-dev", path = "../../primitives/state-machine" } diff --git a/client/service/test/Cargo.toml b/client/service/test/Cargo.toml index 7694e0f6893d..114473b66c97 100644 --- a/client/service/test/Cargo.toml +++ b/client/service/test/Cargo.toml @@ -13,7 +13,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] hex = "0.4" -hex-literal = "0.3.3" +hex-literal = "0.3.4" tempfile = "3.1.0" tokio = { version = "1.10.0", features = ["time"] } log = "0.4.8" diff --git a/frame/benchmarking/Cargo.toml b/frame/benchmarking/Cargo.toml index fdc386978dee..a6bfcf2a552f 100644 --- a/frame/benchmarking/Cargo.toml +++ b/frame/benchmarking/Cargo.toml @@ -28,7 +28,7 @@ frame-system = { version = "4.0.0-dev", default-features = false, path = "../sys log = { version = "0.4.14", default-features = false } [dev-dependencies] -hex-literal = "0.3.3" +hex-literal = "0.3.4" [features] default = ["std"] diff --git a/frame/executive/Cargo.toml b/frame/executive/Cargo.toml index 52d2f41cb1e3..20e31fe0a572 100644 --- a/frame/executive/Cargo.toml +++ b/frame/executive/Cargo.toml @@ -26,7 +26,7 @@ sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primiti sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" } [dev-dependencies] -hex-literal = "0.3.3" +hex-literal = "0.3.4" sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } diff --git a/frame/transaction-storage/Cargo.toml b/frame/transaction-storage/Cargo.toml index 7167ae742457..a8c6e60af2f8 100644 --- a/frame/transaction-storage/Cargo.toml +++ b/frame/transaction-storage/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.126", optional = true } -hex-literal = { version = "0.3.3", optional = true } +hex-literal = { version = "0.3.4", optional = true } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index eaf1d26c2898..dc8904f33e0c 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -73,7 +73,7 @@ sp-runtime-interface = { version = "4.0.0-dev", default-features = false, path = [dev-dependencies] sp-serializer = { version = "4.0.0-dev", path = "../serializer" } -hex-literal = "0.3.3" +hex-literal = "0.3.4" rand = "0.7.2" criterion = "0.3.3" serde_json = "1.0" diff --git a/primitives/state-machine/Cargo.toml b/primitives/state-machine/Cargo.toml index 783837a6442b..0133ea17370a 100644 --- a/primitives/state-machine/Cargo.toml +++ b/primitives/state-machine/Cargo.toml @@ -32,7 +32,7 @@ sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" } tracing = { version = "0.1.29", optional = true } [dev-dependencies] -hex-literal = "0.3.3" +hex-literal = "0.3.4" sp-runtime = { version = "4.0.0-dev", path = "../runtime" } pretty_assertions = "1.0.0" rand = "0.7.2" diff --git a/primitives/trie/Cargo.toml b/primitives/trie/Cargo.toml index 6190df210403..8eaeb424781b 100644 --- a/primitives/trie/Cargo.toml +++ b/primitives/trie/Cargo.toml @@ -31,7 +31,7 @@ sp-core = { version = "4.0.0-dev", default-features = false, path = "../core" } trie-bench = "0.28.0" trie-standardmap = "0.15.2" criterion = "0.3.3" -hex-literal = "0.3.3" +hex-literal = "0.3.4" sp-runtime = { version = "4.0.0-dev", path = "../runtime" } [features] From b01bd3162dd3909f9eba33ba0e63ab074f26d53f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 13 Nov 2021 02:35:07 +0000 Subject: [PATCH 180/695] Bump structopt from 0.3.23 to 0.3.25 (#10253) * Bump structopt from 0.3.23 to 0.3.25 Bumps [structopt](https://github.com/TeXitoi/structopt) from 0.3.23 to 0.3.25. - [Release notes](https://github.com/TeXitoi/structopt/releases) - [Changelog](https://github.com/TeXitoi/structopt/blob/master/CHANGELOG.md) - [Commits](https://github.com/TeXitoi/structopt/compare/v0.3.23...v0.3.25) --- updated-dependencies: - dependency-name: structopt dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * cargo fmt Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Keith Yeung --- Cargo.lock | 8 ++++---- bin/node-template/node/Cargo.toml | 2 +- bin/node/cli/Cargo.toml | 4 ++-- bin/utils/chain-spec-builder/Cargo.toml | 2 +- bin/utils/subkey/Cargo.toml | 2 +- client/cli/Cargo.toml | 2 +- client/consensus/babe/src/verification.rs | 4 ++-- client/network/src/protocol/notifications/behaviour.rs | 4 ++-- client/network/src/protocol/sync/blocks.rs | 2 +- client/network/src/service/tests.rs | 2 +- client/network/src/transactions.rs | 4 ++-- frame/bags-list/remote-tests/Cargo.toml | 2 +- frame/election-provider-multi-phase/src/lib.rs | 2 +- .../support/procedural/src/pallet/parse/pallet_struct.rs | 4 ++-- primitives/npos-elections/fuzzer/Cargo.toml | 2 +- utils/frame/benchmarking-cli/Cargo.toml | 2 +- utils/frame/frame-utilities-cli/Cargo.toml | 2 +- utils/frame/generate-bags/Cargo.toml | 2 +- utils/frame/generate-bags/node-runtime/Cargo.toml | 2 +- utils/frame/try-runtime/cli/Cargo.toml | 2 +- 20 files changed, 28 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c90cf1cf5286..e41a6c867177 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10010,9 +10010,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "structopt" -version = "0.3.23" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf9d950ef167e25e0bdb073cf1d68e9ad2795ac826f2f3f59647817cf23c0bfa" +checksum = "40b9788f4202aa75c240ecc9c15c65185e6a39ccdeb0fd5d008b98825464c87c" dependencies = [ "clap", "lazy_static", @@ -10021,9 +10021,9 @@ dependencies = [ [[package]] name = "structopt-derive" -version = "0.4.16" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134d838a2c9943ac3125cf6df165eda53493451b719f3255b2a26b85f772d0ba" +checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" dependencies = [ "heck", "proc-macro-error", diff --git a/bin/node-template/node/Cargo.toml b/bin/node-template/node/Cargo.toml index 1d8abad406a1..6f3a63593aa3 100644 --- a/bin/node-template/node/Cargo.toml +++ b/bin/node-template/node/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] name = "node-template" [dependencies] -structopt = "0.3.8" +structopt = "0.3.25" sc-cli = { version = "0.10.0-dev", path = "../../../client/cli", features = ["wasmtime"] } sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" } diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index 4e29c7c5314e..374015a3426c 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -40,7 +40,7 @@ futures = "0.3.16" hex-literal = "0.3.4" log = "0.4.8" rand = "0.7.2" -structopt = { version = "0.3.8", optional = true } +structopt = { version = "0.3.25", optional = true } # primitives sp-authority-discovery = { version = "4.0.0-dev", path = "../../../primitives/authority-discovery" } @@ -136,7 +136,7 @@ remote-externalities = { path = "../../../utils/frame/remote-externalities" } pallet-timestamp = { version = "4.0.0-dev", path = "../../../frame/timestamp" } [build-dependencies] -structopt = { version = "0.3.8", optional = true } +structopt = { version = "0.3.25", optional = true } node-inspect = { version = "0.9.0-dev", optional = true, path = "../inspect" } frame-benchmarking-cli = { version = "4.0.0-dev", optional = true, path = "../../../utils/frame/benchmarking-cli" } substrate-build-script-utils = { version = "3.0.0", optional = true, path = "../../../utils/build-script-utils" } diff --git a/bin/utils/chain-spec-builder/Cargo.toml b/bin/utils/chain-spec-builder/Cargo.toml index a35fbba5cdc4..daffd5a0359a 100644 --- a/bin/utils/chain-spec-builder/Cargo.toml +++ b/bin/utils/chain-spec-builder/Cargo.toml @@ -21,4 +21,4 @@ node-cli = { version = "3.0.0-dev", path = "../../node/cli" } sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" } sp-keystore = { version = "0.10.0-dev", path = "../../../primitives/keystore" } rand = "0.7.2" -structopt = "0.3.8" +structopt = "0.3.25" diff --git a/bin/utils/subkey/Cargo.toml b/bin/utils/subkey/Cargo.toml index 14ba673b33be..d3c38edb5771 100644 --- a/bin/utils/subkey/Cargo.toml +++ b/bin/utils/subkey/Cargo.toml @@ -18,4 +18,4 @@ name = "subkey" [dependencies] sc-cli = { version = "0.10.0-dev", path = "../../../client/cli" } -structopt = "0.3.14" +structopt = "0.3.25" diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index 9dc7ff730600..b027063b109a 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -38,7 +38,7 @@ sc-service = { version = "0.10.0-dev", default-features = false, path = "../serv sc-telemetry = { version = "4.0.0-dev", path = "../telemetry" } sp-keyring = { version = "4.0.0-dev", path = "../../primitives/keyring" } names = { version = "0.12.0", default-features = false } -structopt = "0.3.8" +structopt = "0.3.25" sc-tracing = { version = "4.0.0-dev", path = "../tracing" } chrono = "0.4.10" serde = "1.0.126" diff --git a/client/consensus/babe/src/verification.rs b/client/consensus/babe/src/verification.rs index 174b2d03c6ef..2322a9626216 100644 --- a/client/consensus/babe/src/verification.rs +++ b/client/consensus/babe/src/verification.rs @@ -111,7 +111,7 @@ pub(super) fn check_header( ); check_secondary_plain_header::(pre_hash, secondary, sig, &epoch)?; - } + }, PreDigest::SecondaryVRF(secondary) if epoch.config.allowed_slots.is_secondary_vrf_slots_allowed() => { @@ -122,7 +122,7 @@ pub(super) fn check_header( ); check_secondary_vrf_header::(pre_hash, secondary, sig, &epoch)?; - } + }, _ => return Err(babe_err(Error::SecondarySlotAssignmentsDisabled)), } diff --git a/client/network/src/protocol/notifications/behaviour.rs b/client/network/src/protocol/notifications/behaviour.rs index 01138e320757..f66f1fbe9e95 100644 --- a/client/network/src/protocol/notifications/behaviour.rs +++ b/client/network/src/protocol/notifications/behaviour.rs @@ -712,7 +712,7 @@ impl Notifications { timer: delay_id, timer_deadline: *backoff, }; - } + }, // Disabled => Enabled PeerState::Disabled { mut connections, backoff_until } => { @@ -2085,7 +2085,7 @@ impl NetworkBehaviour for Notifications { .boxed(), ); } - } + }, // We intentionally never remove elements from `delays`, and it may // thus contain obsolete entries. This is a normal situation. diff --git a/client/network/src/protocol/sync/blocks.rs b/client/network/src/protocol/sync/blocks.rs index 30ba7ffafeff..ce4535dc0b45 100644 --- a/client/network/src/protocol/sync/blocks.rs +++ b/client/network/src/protocol/sync/blocks.rs @@ -203,7 +203,7 @@ impl BlockCollection { { *downloading -= 1; false - } + }, Some(&mut BlockRangeState::Downloading { .. }) => true, _ => false, }; diff --git a/client/network/src/service/tests.rs b/client/network/src/service/tests.rs index 1c66986e422f..8271da886fca 100644 --- a/client/network/src/service/tests.rs +++ b/client/network/src/service/tests.rs @@ -529,7 +529,7 @@ fn fallback_name_working() { { assert_eq!(negotiated_fallback, Some(PROTOCOL_NAME)); break - } + }, _ => {}, }; } diff --git a/client/network/src/transactions.rs b/client/network/src/transactions.rs index 99350f603a37..6d190651160f 100644 --- a/client/network/src/transactions.rs +++ b/client/network/src/transactions.rs @@ -336,13 +336,13 @@ impl TransactionsHandler { }, ); debug_assert!(_was_in.is_none()); - } + }, Event::NotificationStreamClosed { remote, protocol } if protocol == self.protocol_name => { let _peer = self.peers.remove(&remote); debug_assert!(_peer.is_some()); - } + }, Event::NotificationsReceived { remote, messages } => { for (protocol, message) in messages { diff --git a/frame/bags-list/remote-tests/Cargo.toml b/frame/bags-list/remote-tests/Cargo.toml index 37f351f0d27e..ecc0b4da242c 100644 --- a/frame/bags-list/remote-tests/Cargo.toml +++ b/frame/bags-list/remote-tests/Cargo.toml @@ -33,5 +33,5 @@ remote-externalities = { path = "../../../utils/frame/remote-externalities", ver # others tokio = { version = "1", features = ["macros"] } log = "0.4.14" -structopt = "0.3.23" +structopt = "0.3.25" clap = "2.33.3" diff --git a/frame/election-provider-multi-phase/src/lib.rs b/frame/election-provider-multi-phase/src/lib.rs index 80a13aa99fb7..4c4de82af592 100644 --- a/frame/election-provider-multi-phase/src/lib.rs +++ b/frame/election-provider-multi-phase/src/lib.rs @@ -772,7 +772,7 @@ pub mod pallet { Self::on_initialize_open_unsigned(enabled, now); T::WeightInfo::on_initialize_open_unsigned() } - } + }, _ => T::WeightInfo::on_initialize_nothing(), } } diff --git a/frame/support/procedural/src/pallet/parse/pallet_struct.rs b/frame/support/procedural/src/pallet/parse/pallet_struct.rs index 278f46e13818..c528faf669ee 100644 --- a/frame/support/procedural/src/pallet/parse/pallet_struct.rs +++ b/frame/support/procedural/src/pallet/parse/pallet_struct.rs @@ -130,12 +130,12 @@ impl PalletStructDef { if generate_storage_info.is_none() => { generate_storage_info = Some(span); - } + }, PalletStructAttr::StorageVersion { storage_version, .. } if storage_version_found.is_none() => { storage_version_found = Some(storage_version); - } + }, attr => { let msg = "Unexpected duplicated attribute"; return Err(syn::Error::new(attr.span(), msg)) diff --git a/primitives/npos-elections/fuzzer/Cargo.toml b/primitives/npos-elections/fuzzer/Cargo.toml index f9fce9d8744d..59d12c5a5d2e 100644 --- a/primitives/npos-elections/fuzzer/Cargo.toml +++ b/primitives/npos-elections/fuzzer/Cargo.toml @@ -20,7 +20,7 @@ honggfuzz = "0.5" rand = { version = "0.7.3", features = ["std", "small_rng"] } sp-npos-elections = { version = "4.0.0-dev", path = ".." } sp-runtime = { version = "4.0.0-dev", path = "../../runtime" } -structopt = "0.3.21" +structopt = "0.3.25" [[bin]] name = "reduce" diff --git a/utils/frame/benchmarking-cli/Cargo.toml b/utils/frame/benchmarking-cli/Cargo.toml index 605a14e3adff..03520f9cbd5d 100644 --- a/utils/frame/benchmarking-cli/Cargo.toml +++ b/utils/frame/benchmarking-cli/Cargo.toml @@ -25,7 +25,7 @@ sp-keystore = { version = "0.10.0-dev", path = "../../../primitives/keystore" } sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } sp-state-machine = { version = "0.10.0-dev", path = "../../../primitives/state-machine" } codec = { version = "2.0.0", package = "parity-scale-codec" } -structopt = "0.3.8" +structopt = "0.3.25" chrono = "0.4" serde = "1.0.126" handlebars = "3.5.0" diff --git a/utils/frame/frame-utilities-cli/Cargo.toml b/utils/frame/frame-utilities-cli/Cargo.toml index 9d1481933741..dfbf73ee9d5f 100644 --- a/utils/frame/frame-utilities-cli/Cargo.toml +++ b/utils/frame/frame-utilities-cli/Cargo.toml @@ -14,7 +14,7 @@ readme = "README.md" sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" } sc-cli = { version = "0.10.0-dev", path = "../../../client/cli" } sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } -structopt = "0.3.8" +structopt = "0.3.25" frame-system = { version = "4.0.0-dev", path = "../../../frame/system" } frame-support = { version = "4.0.0-dev", path = "../../../frame/support" } diff --git a/utils/frame/generate-bags/Cargo.toml b/utils/frame/generate-bags/Cargo.toml index 4bc27021b4c5..2c9374fc5cca 100644 --- a/utils/frame/generate-bags/Cargo.toml +++ b/utils/frame/generate-bags/Cargo.toml @@ -23,4 +23,4 @@ sp-io = { version = "4.0.0-dev", path = "../../../primitives/io" } chrono = { version = "0.4.19" } git2 = { version = "0.13.23", default-features = false } num-format = { version = "0.4.0" } -structopt = "0.3.21" +structopt = "0.3.25" diff --git a/utils/frame/generate-bags/node-runtime/Cargo.toml b/utils/frame/generate-bags/node-runtime/Cargo.toml index b0256722f466..b5a7e0b898c9 100644 --- a/utils/frame/generate-bags/node-runtime/Cargo.toml +++ b/utils/frame/generate-bags/node-runtime/Cargo.toml @@ -14,4 +14,4 @@ node-runtime = { version = "3.0.0-dev", path = "../../../../bin/node/runtime" } generate-bags = { version = "4.0.0-dev", path = "../" } # third-party -structopt = "0.3.21" +structopt = "0.3.25" diff --git a/utils/frame/try-runtime/cli/Cargo.toml b/utils/frame/try-runtime/cli/Cargo.toml index a89a625bbd9e..44be678ba381 100644 --- a/utils/frame/try-runtime/cli/Cargo.toml +++ b/utils/frame/try-runtime/cli/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] log = "0.4.8" parity-scale-codec = { version = "2.3.1" } serde = "1.0.126" -structopt = "0.3.8" +structopt = "0.3.25" sc-service = { version = "0.10.0-dev", default-features = false, path = "../../../../client/service" } sc-cli = { version = "0.10.0-dev", path = "../../../../client/cli" } From ab40c7ef81b1ecdce254c1b76bbaf559b5473576 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 13 Nov 2021 19:56:41 +0100 Subject: [PATCH 181/695] Bump nix from 0.19.1 to 0.23.0 (#10254) Bumps [nix](https://github.com/nix-rust/nix) from 0.19.1 to 0.23.0. - [Release notes](https://github.com/nix-rust/nix/releases) - [Changelog](https://github.com/nix-rust/nix/blob/master/CHANGELOG.md) - [Commits](https://github.com/nix-rust/nix/compare/v0.19.1...v0.23.0) --- updated-dependencies: - dependency-name: nix dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 5 +++-- bin/node/cli/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e41a6c867177..7c32ecb3f36d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4469,14 +4469,15 @@ dependencies = [ [[package]] name = "nix" -version = "0.19.1" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ccba0cfe4fdf15982d1674c69b1fd80bad427d293849982668dfe454bd61f2" +checksum = "f305c2c2e4c39a82f7bf0bf65fb557f9070ce06781d4f2454295cc34b1c43188" dependencies = [ "bitflags", "cc", "cfg-if 1.0.0", "libc", + "memoffset", ] [[package]] diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index 374015a3426c..122f2d0c2c8f 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -122,7 +122,7 @@ sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" futures = "0.3.16" tempfile = "3.1.0" assert_cmd = "2.0.2" -nix = "0.19" +nix = "0.23" serde_json = "1.0" regex = "1" platforms = "1.1" From ed60316879773b5d81cad4525fd9c1a511de2952 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 13 Nov 2021 21:27:46 +0100 Subject: [PATCH 182/695] Bump cargo_metadata from 0.13.1 to 0.14.1 (#10255) Bumps [cargo_metadata](https://github.com/oli-obk/cargo_metadata) from 0.13.1 to 0.14.1. - [Release notes](https://github.com/oli-obk/cargo_metadata/releases) - [Commits](https://github.com/oli-obk/cargo_metadata/compare/v0.13.1...0.14.1) --- updated-dependencies: - dependency-name: cargo_metadata dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 11 ++++++----- utils/wasm-builder/Cargo.toml | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7c32ecb3f36d..57bf1278822c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -812,14 +812,13 @@ dependencies = [ [[package]] name = "cargo_metadata" -version = "0.13.1" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "081e3f0755c1f380c2d010481b6fa2e02973586d5f2b24eebb7a2a1d98b143d8" +checksum = "ba2ae6de944143141f6155a473a6b02f66c7c3f9f47316f802f80204ebfe6e12" dependencies = [ "camino", "cargo-platform", - "semver 0.11.0", - "semver-parser 0.10.2", + "semver 1.0.4", "serde", "serde_json", ] @@ -8844,7 +8843,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" dependencies = [ "semver-parser 0.10.2", - "serde", ] [[package]] @@ -8852,6 +8850,9 @@ name = "semver" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012" +dependencies = [ + "serde", +] [[package]] name = "semver-parser" diff --git a/utils/wasm-builder/Cargo.toml b/utils/wasm-builder/Cargo.toml index 88318f4f0d54..a2a56a5bf22c 100644 --- a/utils/wasm-builder/Cargo.toml +++ b/utils/wasm-builder/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] build-helper = "0.1.1" -cargo_metadata = "0.13.1" +cargo_metadata = "0.14.1" tempfile = "3.1.0" toml = "0.5.4" walkdir = "2.3.2" From ee8ac3a6c9c9292911afbf5ec16fbb2bb0d44b27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Sat, 13 Nov 2021 23:57:19 +0100 Subject: [PATCH 183/695] Fix cargo unleash check (#10261) --- utils/frame/remote-externalities/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/frame/remote-externalities/Cargo.toml b/utils/frame/remote-externalities/Cargo.toml index 56f797343c0f..8f54dd01df0a 100644 --- a/utils/frame/remote-externalities/Cargo.toml +++ b/utils/frame/remote-externalities/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] jsonrpsee = { version = "0.4.1", features = ["ws-client", "macros"] } env_logger = "0.9" -frame-support = { path = "../../../frame/support", optional = true } +frame-support = { path = "../../../frame/support", optional = true, version = "4.0.0-dev" } log = "0.4.11" codec = { package = "parity-scale-codec", version = "2.0.0" } serde_json = "1.0" From 1b646b219e0e0c7489a2a8488381fc2e32da6a1c Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Sun, 14 Nov 2021 15:04:20 +0000 Subject: [PATCH 184/695] rework `staking::reap_stash` (#10178) * rework reap_stash * Update frame/staking/src/pallet/mod.rs Co-authored-by: Zeke Mostov * Update frame/staking/src/pallet/mod.rs Co-authored-by: Zeke Mostov * Update frame/staking/src/pallet/mod.rs Co-authored-by: Zeke Mostov * Fix Co-authored-by: Shawn Tabrizi Co-authored-by: Zeke Mostov --- frame/staking/src/benchmarking.rs | 5 +- frame/staking/src/pallet/mod.rs | 40 +++++----- frame/staking/src/tests.rs | 118 +++++++----------------------- 3 files changed, 50 insertions(+), 113 deletions(-) diff --git a/frame/staking/src/benchmarking.rs b/frame/staking/src/benchmarking.rs index 80630818de7e..e312aedbec1f 100644 --- a/frame/staking/src/benchmarking.rs +++ b/frame/staking/src/benchmarking.rs @@ -28,7 +28,7 @@ use frame_support::{ traits::{Currency, CurrencyToVote, Get, Imbalance}, }; use sp_runtime::{ - traits::{StaticLookup, Zero}, + traits::{Bounded, One, StaticLookup, Zero}, Perbill, Percent, }; use sp_staking::SessionIndex; @@ -38,7 +38,6 @@ pub use frame_benchmarking::{ account, benchmarks, impl_benchmark_test_suite, whitelist_account, whitelisted_caller, }; use frame_system::RawOrigin; -use sp_runtime::traits::{Bounded, One}; const SEED: u32 = 0; const MAX_SPANS: u32 = 100; @@ -695,7 +694,7 @@ benchmarks! { let stash = scenario.origin_stash1.clone(); add_slashing_spans::(&stash, s); - T::Currency::make_free_balance_be(&stash, T::Currency::minimum_balance()); + Ledger::::insert(&controller, StakingLedger { active: T::Currency::minimum_balance() - One::one(), total: T::Currency::minimum_balance() - One::one(), ..Default::default() }); assert!(Bonded::::contains_key(&stash)); assert!(T::SortedListProvider::contains(&stash)); diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 8e97a90e0754..197c2eed325a 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -1425,33 +1425,37 @@ pub mod pallet { Ok(()) } - /// Remove all data structure concerning a staker/stash once its balance is at the minimum. - /// This is essentially equivalent to `withdraw_unbonded` except it can be called by anyone - /// and the target `stash` must have no funds left beyond the ED. + /// Remove all data structures concerning a staker/stash once it is at a state where it can + /// be considered `dust` in the staking system. The requirements are: /// - /// This can be called from any origin. + /// 1. the `total_balance` of the stash is below existential deposit. + /// 2. or, the `ledger.total` of the stash is below existential deposit. /// - /// - `stash`: The stash account to reap. Its balance must be zero. + /// The former can happen in cases like a slash; the latter when a fully unbonded account + /// is still receiving staking rewards in `RewardDestination::Staked`. /// - /// # - /// Complexity: O(S) where S is the number of slashing spans on the account. - /// DB Weight: - /// - Reads: Stash Account, Bonded, Slashing Spans, Locks - /// - Writes: Bonded, Slashing Spans (if S > 0), Ledger, Payee, Validators, Nominators, - /// Stash Account, Locks - /// - Writes Each: SpanSlash * S - /// # + /// It can be called by anyone, as long as `stash` meets the above requirements. + /// + /// Refunds the transaction fees upon successful execution. #[pallet::weight(T::WeightInfo::reap_stash(*num_slashing_spans))] pub fn reap_stash( - _origin: OriginFor, + origin: OriginFor, stash: T::AccountId, num_slashing_spans: u32, - ) -> DispatchResult { - let at_minimum = T::Currency::total_balance(&stash) == T::Currency::minimum_balance(); - ensure!(at_minimum, Error::::FundedTarget); + ) -> DispatchResultWithPostInfo { + let _ = ensure_signed(origin)?; + + let ed = T::Currency::minimum_balance(); + let reapable = T::Currency::total_balance(&stash) < ed || + Self::ledger(Self::bonded(stash.clone()).ok_or(Error::::NotStash)?) + .map(|l| l.total) + .unwrap_or_default() < ed; + ensure!(reapable, Error::::FundedTarget); + Self::kill_stash(&stash, num_slashing_spans)?; T::Currency::remove_lock(STAKING_ID, &stash); - Ok(()) + + Ok(Pays::No.into()) } /// Remove the given nominations from the calling validator. diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index d6d92d5bd57f..8e8a7ee636d8 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -1633,115 +1633,49 @@ fn reward_to_stake_works() { } #[test] -fn on_free_balance_zero_stash_removes_validator() { - // Tests that validator storage items are cleaned up when stash is empty - // Tests that storage items are untouched when controller is empty +fn reap_stash_works() { ExtBuilder::default() .existential_deposit(10) .balance_factor(10) .build_and_execute(|| { - // Check the balance of the validator account + // given assert_eq!(Balances::free_balance(10), 10); - // Check the balance of the stash account - assert_eq!(Balances::free_balance(11), 10 * 1000); - // Check these two accounts are bonded - assert_eq!(Staking::bonded(&11), Some(10)); - - // Set payee information - assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Stash)); - - // Check storage items that should be cleaned up - assert!(>::contains_key(&10)); - assert!(>::contains_key(&11)); - assert!(>::contains_key(&11)); - assert!(>::contains_key(&11)); - - // Reduce free_balance of controller to 0 - let _ = Balances::slash(&10, Balance::max_value()); - - // Check the balance of the stash account has not been touched assert_eq!(Balances::free_balance(11), 10 * 1000); - // Check these two accounts are still bonded assert_eq!(Staking::bonded(&11), Some(10)); - // Check storage items have not changed assert!(>::contains_key(&10)); assert!(>::contains_key(&11)); assert!(>::contains_key(&11)); assert!(>::contains_key(&11)); - // Reduce free_balance of stash to 0 - let _ = Balances::slash(&11, Balance::max_value()); - // Check total balance of stash - assert_eq!(Balances::total_balance(&11), 10); - - // Reap the stash - assert_ok!(Staking::reap_stash(Origin::none(), 11, 0)); - - // Check storage items do not exist - assert!(!>::contains_key(&10)); - assert!(!>::contains_key(&11)); - assert!(!>::contains_key(&11)); - assert!(!>::contains_key(&11)); - assert!(!>::contains_key(&11)); - }); -} - -#[test] -fn on_free_balance_zero_stash_removes_nominator() { - // Tests that nominator storage items are cleaned up when stash is empty - // Tests that storage items are untouched when controller is empty - ExtBuilder::default() - .existential_deposit(10) - .balance_factor(10) - .build_and_execute(|| { - // Make 10 a nominator - assert_ok!(Staking::nominate(Origin::signed(10), vec![20])); - // Check that account 10 is a nominator - assert!(>::contains_key(11)); - // Check the balance of the nominator account - assert_eq!(Balances::free_balance(10), 10); - // Check the balance of the stash account - assert_eq!(Balances::free_balance(11), 10_000); - - // Set payee information - assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Stash)); - - // Check storage items that should be cleaned up - assert!(>::contains_key(&10)); - assert!(>::contains_key(&11)); - assert!(>::contains_key(&11)); - assert!(>::contains_key(&11)); - - // Reduce free_balance of controller to 0 - let _ = Balances::slash(&10, Balance::max_value()); - // Check total balance of account 10 - assert_eq!(Balances::total_balance(&10), 0); - - // Check the balance of the stash account has not been touched - assert_eq!(Balances::free_balance(11), 10_000); - // Check these two accounts are still bonded - assert_eq!(Staking::bonded(&11), Some(10)); - - // Check storage items have not changed - assert!(>::contains_key(&10)); - assert!(>::contains_key(&11)); - assert!(>::contains_key(&11)); - assert!(>::contains_key(&11)); + // stash is not reapable + assert_noop!( + Staking::reap_stash(Origin::signed(20), 11, 0), + Error::::FundedTarget + ); + // controller or any other account is not reapable + assert_noop!(Staking::reap_stash(Origin::signed(20), 10, 0), Error::::NotStash); - // Reduce free_balance of stash to 0 - let _ = Balances::slash(&11, Balance::max_value()); - // Check total balance of stash - assert_eq!(Balances::total_balance(&11), 10); + // no easy way to cause an account to go below ED, we tweak their staking ledger + // instead. + Ledger::::insert( + 10, + StakingLedger { + stash: 11, + total: 5, + active: 5, + unlocking: vec![], + claimed_rewards: vec![], + }, + ); - // Reap the stash - assert_ok!(Staking::reap_stash(Origin::none(), 11, 0)); + // reap-able + assert_ok!(Staking::reap_stash(Origin::signed(20), 11, 0)); - // Check storage items do not exist + // then assert!(!>::contains_key(&10)); assert!(!>::contains_key(&11)); assert!(!>::contains_key(&11)); - assert!(!>::contains_key(&11)); assert!(!>::contains_key(&11)); }); } @@ -2556,10 +2490,10 @@ fn garbage_collection_after_slashing() { // reap_stash respects num_slashing_spans so that weight is accurate assert_noop!( - Staking::reap_stash(Origin::none(), 11, 0), + Staking::reap_stash(Origin::signed(20), 11, 0), Error::::IncorrectSlashingSpans ); - assert_ok!(Staking::reap_stash(Origin::none(), 11, 2)); + assert_ok!(Staking::reap_stash(Origin::signed(20), 11, 2)); assert!(::SlashingSpans::get(&11).is_none()); assert_eq!(::SpanSlash::get(&(11, 0)).amount_slashed(), &0); From 7db0768a85dc36a3f2a44d042b32f3715c00a90d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Mon, 15 Nov 2021 12:45:37 +0100 Subject: [PATCH 185/695] Keystore: Store files with permission 600 on unix (#10263) --- client/keystore/src/local.rs | 44 +++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/client/keystore/src/local.rs b/client/keystore/src/local.rs index e5c8ff14af09..965e68336e3b 100644 --- a/client/keystore/src/local.rs +++ b/client/keystore/src/local.rs @@ -364,8 +364,7 @@ impl KeystoreInner { let path = path.into(); fs::create_dir_all(&path)?; - let instance = Self { path: Some(path), additional: HashMap::new(), password }; - Ok(instance) + Ok(Self { path: Some(path), additional: HashMap::new(), password }) } /// Get the password for this store. @@ -397,10 +396,9 @@ impl KeystoreInner { /// Places it into the file system store, if a path is configured. fn insert_unknown(&self, key_type: KeyTypeId, suri: &str, public: &[u8]) -> Result<()> { if let Some(path) = self.key_file_path(public, key_type) { - let mut file = File::create(path).map_err(Error::Io)?; - serde_json::to_writer(&file, &suri).map_err(Error::Json)?; - file.flush().map_err(Error::Io)?; + Self::write_to_file(path, suri)?; } + Ok(()) } @@ -411,15 +409,29 @@ impl KeystoreInner { fn generate_by_type(&mut self, key_type: KeyTypeId) -> Result { let (pair, phrase, _) = Pair::generate_with_phrase(self.password()); if let Some(path) = self.key_file_path(pair.public().as_slice(), key_type) { - let mut file = File::create(path)?; - serde_json::to_writer(&file, &phrase)?; - file.flush()?; + Self::write_to_file(path, &phrase)?; } else { self.insert_ephemeral_pair(&pair, &phrase, key_type); } + Ok(pair) } + /// Write the given `data` to `file`. + fn write_to_file(file: PathBuf, data: &str) -> Result<()> { + let mut file = File::create(file)?; + serde_json::to_writer(&file, data)?; + file.flush()?; + + #[cfg(target_family = "unix")] + { + use std::os::unix::fs::PermissionsExt; + file.set_permissions(fs::Permissions::from_mode(0o600))?; + } + + Ok(()) + } + /// Create a new key from seed. /// /// Does not place it into the file system store. @@ -735,4 +747,20 @@ mod tests { SyncCryptoStore::sr25519_generate_new(&store, TEST_KEY_TYPE, None).unwrap(); assert_eq!(SyncCryptoStore::sr25519_public_keys(&store, TEST_KEY_TYPE).len(), 2); } + + #[test] + #[cfg(target_family = "unix")] + fn uses_correct_file_permissions_on_unix() { + use std::os::unix::fs::PermissionsExt; + + let temp_dir = TempDir::new().unwrap(); + let store = LocalKeystore::open(temp_dir.path(), None).unwrap(); + + let public = SyncCryptoStore::sr25519_generate_new(&store, TEST_KEY_TYPE, None).unwrap(); + + let path = store.0.read().key_file_path(public.as_ref(), TEST_KEY_TYPE).unwrap(); + let permissions = File::open(path).unwrap().metadata().unwrap().permissions(); + + assert_eq!(0o100600, permissions.mode()); + } } From 7ebab91ed5179c3be7176c04d6a4f3996cb50563 Mon Sep 17 00:00:00 2001 From: Ayevbeosa Iyamu Date: Mon, 15 Nov 2021 20:16:03 +0100 Subject: [PATCH 186/695] Add field names to pallet `Event` variants (#10184) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Changed named fields to struct variants * Fixed errors. * Made adjustments as per `cargo +nightly fmt`. * Update frame/uniques/src/lib.rs Co-authored-by: Alexander Theißen * Removed redundant comments for structs. * Moved frame-support to dev dependencies Co-authored-by: Alexander Theißen --- frame/contracts/src/exec.rs | 8 +- frame/proxy/src/tests.rs | 6 +- frame/uniques/src/benchmarking.rs | 52 ++++---- frame/uniques/src/functions.rs | 13 +- frame/uniques/src/impl_nonfungibles.rs | 2 +- frame/uniques/src/lib.rs | 174 +++++++++++++++---------- frame/utility/src/lib.rs | 9 +- frame/utility/src/tests.rs | 20 ++- frame/vesting/src/lib.rs | 27 ++-- 9 files changed, 185 insertions(+), 126 deletions(-) diff --git a/frame/contracts/src/exec.rs b/frame/contracts/src/exec.rs index 7ef1aec2dfc6..90a640418bcc 100644 --- a/frame/contracts/src/exec.rs +++ b/frame/contracts/src/exec.rs @@ -2157,10 +2157,10 @@ mod tests { }, EventRecord { phase: Phase::Initialization, - event: MetaEvent::Utility(pallet_utility::Event::BatchInterrupted( - 1, - frame_system::Error::::CallFiltered.into() - ),), + event: MetaEvent::Utility(pallet_utility::Event::BatchInterrupted { + index: 1, + error: frame_system::Error::::CallFiltered.into() + },), topics: vec![], }, ] diff --git a/frame/proxy/src/tests.rs b/frame/proxy/src/tests.rs index 93a0e4ce7d62..ed21a80f6213 100644 --- a/frame/proxy/src/tests.rs +++ b/frame/proxy/src/tests.rs @@ -369,7 +369,8 @@ fn filtering_works() { ); assert_ok!(Proxy::proxy(Origin::signed(4), 1, None, call.clone())); expect_events(vec![ - UtilityEvent::BatchInterrupted(0, SystemError::CallFiltered.into()).into(), + UtilityEvent::BatchInterrupted { index: 0, error: SystemError::CallFiltered.into() } + .into(), ProxyEvent::ProxyExecuted(Ok(())).into(), ]); @@ -387,7 +388,8 @@ fn filtering_works() { ); assert_ok!(Proxy::proxy(Origin::signed(4), 1, None, call.clone())); expect_events(vec![ - UtilityEvent::BatchInterrupted(0, SystemError::CallFiltered.into()).into(), + UtilityEvent::BatchInterrupted { index: 0, error: SystemError::CallFiltered.into() } + .into(), ProxyEvent::ProxyExecuted(Ok(())).into(), ]); diff --git a/frame/uniques/src/benchmarking.rs b/frame/uniques/src/benchmarking.rs index 0e161bf7bfe8..513509bda70e 100644 --- a/frame/uniques/src/benchmarking.rs +++ b/frame/uniques/src/benchmarking.rs @@ -141,7 +141,7 @@ benchmarks_instance_pallet! { T::Currency::make_free_balance_be(&caller, DepositBalanceOf::::max_value()); }: _(SystemOrigin::Signed(caller.clone()), Default::default(), caller_lookup) verify { - assert_last_event::(Event::Created(Default::default(), caller.clone(), caller).into()); + assert_last_event::(Event::Created { class: Default::default(), creator: caller.clone(), owner: caller }.into()); } force_create { @@ -149,7 +149,7 @@ benchmarks_instance_pallet! { let caller_lookup = T::Lookup::unlookup(caller.clone()); }: _(SystemOrigin::Root, Default::default(), caller_lookup, true) verify { - assert_last_event::(Event::ForceCreated(Default::default(), caller).into()); + assert_last_event::(Event::ForceCreated { class: Default::default(), owner: caller }.into()); } destroy { @@ -171,7 +171,7 @@ benchmarks_instance_pallet! { let witness = Class::::get(class).unwrap().destroy_witness(); }: _(SystemOrigin::Signed(caller), class, witness) verify { - assert_last_event::(Event::Destroyed(class).into()); + assert_last_event::(Event::Destroyed { class: class }.into()); } mint { @@ -179,7 +179,7 @@ benchmarks_instance_pallet! { let instance = Default::default(); }: _(SystemOrigin::Signed(caller.clone()), class, instance, caller_lookup) verify { - assert_last_event::(Event::Issued(class, instance, caller).into()); + assert_last_event::(Event::Issued { class, instance, owner: caller }.into()); } burn { @@ -187,7 +187,7 @@ benchmarks_instance_pallet! { let (instance, ..) = mint_instance::(0); }: _(SystemOrigin::Signed(caller.clone()), class, instance, Some(caller_lookup)) verify { - assert_last_event::(Event::Burned(class, instance, caller).into()); + assert_last_event::(Event::Burned { class, instance, owner: caller }.into()); } transfer { @@ -198,7 +198,7 @@ benchmarks_instance_pallet! { let target_lookup = T::Lookup::unlookup(target.clone()); }: _(SystemOrigin::Signed(caller.clone()), class, instance, target_lookup) verify { - assert_last_event::(Event::Transferred(class, instance, caller, target).into()); + assert_last_event::(Event::Transferred { class, instance, from: caller, to: target }.into()); } redeposit { @@ -217,7 +217,7 @@ benchmarks_instance_pallet! { )?; }: _(SystemOrigin::Signed(caller.clone()), class, instances.clone()) verify { - assert_last_event::(Event::Redeposited(class, instances).into()); + assert_last_event::(Event::Redeposited { class, successful_instances: instances }.into()); } freeze { @@ -225,7 +225,7 @@ benchmarks_instance_pallet! { let (instance, ..) = mint_instance::(Default::default()); }: _(SystemOrigin::Signed(caller.clone()), Default::default(), Default::default()) verify { - assert_last_event::(Event::Frozen(Default::default(), Default::default()).into()); + assert_last_event::(Event::Frozen { class: Default::default(), instance: Default::default() }.into()); } thaw { @@ -238,14 +238,14 @@ benchmarks_instance_pallet! { )?; }: _(SystemOrigin::Signed(caller.clone()), class, instance) verify { - assert_last_event::(Event::Thawed(class, instance).into()); + assert_last_event::(Event::Thawed { class, instance }.into()); } freeze_class { let (class, caller, caller_lookup) = create_class::(); }: _(SystemOrigin::Signed(caller.clone()), class) verify { - assert_last_event::(Event::ClassFrozen(class).into()); + assert_last_event::(Event::ClassFrozen { class }.into()); } thaw_class { @@ -254,7 +254,7 @@ benchmarks_instance_pallet! { Uniques::::freeze_class(origin, class)?; }: _(SystemOrigin::Signed(caller.clone()), class) verify { - assert_last_event::(Event::ClassThawed(class).into()); + assert_last_event::(Event::ClassThawed { class }.into()); } transfer_ownership { @@ -264,7 +264,7 @@ benchmarks_instance_pallet! { T::Currency::make_free_balance_be(&target, T::Currency::minimum_balance()); }: _(SystemOrigin::Signed(caller), class, target_lookup) verify { - assert_last_event::(Event::OwnerChanged(class, target).into()); + assert_last_event::(Event::OwnerChanged { class, new_owner: target }.into()); } set_team { @@ -274,12 +274,12 @@ benchmarks_instance_pallet! { let target2 = T::Lookup::unlookup(account("target", 2, SEED)); }: _(SystemOrigin::Signed(caller), Default::default(), target0.clone(), target1.clone(), target2.clone()) verify { - assert_last_event::(Event::TeamChanged( + assert_last_event::(Event::TeamChanged{ class, - account("target", 0, SEED), - account("target", 1, SEED), - account("target", 2, SEED), - ).into()); + issuer: account("target", 0, SEED), + admin: account("target", 1, SEED), + freezer: account("target", 2, SEED), + }.into()); } force_asset_status { @@ -296,7 +296,7 @@ benchmarks_instance_pallet! { }; }: { call.dispatch_bypass_filter(origin)? } verify { - assert_last_event::(Event::AssetStatusChanged(class).into()); + assert_last_event::(Event::AssetStatusChanged { class }.into()); } set_attribute { @@ -308,7 +308,7 @@ benchmarks_instance_pallet! { add_instance_metadata::(instance); }: _(SystemOrigin::Signed(caller), class, Some(instance), key.clone(), value.clone()) verify { - assert_last_event::(Event::AttributeSet(class, Some(instance), key, value).into()); + assert_last_event::(Event::AttributeSet { class, maybe_instance: Some(instance), key, value }.into()); } clear_attribute { @@ -318,7 +318,7 @@ benchmarks_instance_pallet! { let (key, ..) = add_instance_attribute::(instance); }: _(SystemOrigin::Signed(caller), class, Some(instance), key.clone()) verify { - assert_last_event::(Event::AttributeCleared(class, Some(instance), key).into()); + assert_last_event::(Event::AttributeCleared { class, maybe_instance: Some(instance), key }.into()); } set_metadata { @@ -328,7 +328,7 @@ benchmarks_instance_pallet! { let (instance, ..) = mint_instance::(0); }: _(SystemOrigin::Signed(caller), class, instance, data.clone(), false) verify { - assert_last_event::(Event::MetadataSet(class, instance, data, false).into()); + assert_last_event::(Event::MetadataSet { class, instance, data, is_frozen: false }.into()); } clear_metadata { @@ -337,7 +337,7 @@ benchmarks_instance_pallet! { add_instance_metadata::(instance); }: _(SystemOrigin::Signed(caller), class, instance) verify { - assert_last_event::(Event::MetadataCleared(class, instance).into()); + assert_last_event::(Event::MetadataCleared { class, instance }.into()); } set_class_metadata { @@ -346,7 +346,7 @@ benchmarks_instance_pallet! { let (class, caller, _) = create_class::(); }: _(SystemOrigin::Signed(caller), class, data.clone(), false) verify { - assert_last_event::(Event::ClassMetadataSet(class, data, false).into()); + assert_last_event::(Event::ClassMetadataSet { class, data, is_frozen: false }.into()); } clear_class_metadata { @@ -354,7 +354,7 @@ benchmarks_instance_pallet! { add_class_metadata::(); }: _(SystemOrigin::Signed(caller), class) verify { - assert_last_event::(Event::ClassMetadataCleared(class).into()); + assert_last_event::(Event::ClassMetadataCleared { class }.into()); } approve_transfer { @@ -364,7 +364,7 @@ benchmarks_instance_pallet! { let delegate_lookup = T::Lookup::unlookup(delegate.clone()); }: _(SystemOrigin::Signed(caller.clone()), class, instance, delegate_lookup) verify { - assert_last_event::(Event::ApprovedTransfer(class, instance, caller, delegate).into()); + assert_last_event::(Event::ApprovedTransfer { class, instance, owner: caller, delegate }.into()); } cancel_approval { @@ -376,7 +376,7 @@ benchmarks_instance_pallet! { Uniques::::approve_transfer(origin, class, instance, delegate_lookup.clone())?; }: _(SystemOrigin::Signed(caller.clone()), class, instance, Some(delegate_lookup)) verify { - assert_last_event::(Event::ApprovalCancelled(class, instance, caller, delegate).into()); + assert_last_event::(Event::ApprovalCancelled { class, instance, owner: caller, delegate }.into()); } impl_benchmark_test_suite!(Uniques, crate::mock::new_test_ext(), crate::mock::Test); diff --git a/frame/uniques/src/functions.rs b/frame/uniques/src/functions.rs index 68acf7f1879f..43d634ad569e 100644 --- a/frame/uniques/src/functions.rs +++ b/frame/uniques/src/functions.rs @@ -44,7 +44,12 @@ impl, I: 'static> Pallet { details.owner = dest; Asset::::insert(&class, &instance, &details); - Self::deposit_event(Event::Transferred(class, instance, origin, details.owner)); + Self::deposit_event(Event::Transferred { + class, + instance, + from: origin, + to: details.owner, + }); Ok(()) } @@ -105,7 +110,7 @@ impl, I: 'static> Pallet { Attribute::::remove_prefix((&class,), None); T::Currency::unreserve(&class_details.owner, class_details.total_deposit); - Self::deposit_event(Event::Destroyed(class)); + Self::deposit_event(Event::Destroyed { class }); Ok(DestroyWitness { instances: class_details.instances, @@ -146,7 +151,7 @@ impl, I: 'static> Pallet { Ok(()) })?; - Self::deposit_event(Event::Issued(class, instance, owner)); + Self::deposit_event(Event::Issued { class, instance, owner }); Ok(()) } @@ -174,7 +179,7 @@ impl, I: 'static> Pallet { Asset::::remove(&class, &instance); Account::::remove((&owner, &class, &instance)); - Self::deposit_event(Event::Burned(class, instance, owner)); + Self::deposit_event(Event::Burned { class, instance, owner }); Ok(()) } } diff --git a/frame/uniques/src/impl_nonfungibles.rs b/frame/uniques/src/impl_nonfungibles.rs index 5394f02160e3..72aa1dd0d4cb 100644 --- a/frame/uniques/src/impl_nonfungibles.rs +++ b/frame/uniques/src/impl_nonfungibles.rs @@ -98,7 +98,7 @@ impl, I: 'static> Create<::AccountId> for Pallet admin.clone(), T::ClassDeposit::get(), false, - Event::Created(class.clone(), who.clone(), admin.clone()), + Event::Created { class: class.clone(), creator: who.clone(), owner: admin.clone() }, ) } } diff --git a/frame/uniques/src/lib.rs b/frame/uniques/src/lib.rs index 1bf220e4a787..7e380459252e 100644 --- a/frame/uniques/src/lib.rs +++ b/frame/uniques/src/lib.rs @@ -191,63 +191,90 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event, I: 'static = ()> { - /// An asset class was created. \[ class, creator, owner \] - Created(T::ClassId, T::AccountId, T::AccountId), - /// An asset class was force-created. \[ class, owner \] - ForceCreated(T::ClassId, T::AccountId), - /// An asset `class` was destroyed. \[ class \] - Destroyed(T::ClassId), - /// An asset `instance` was issued. \[ class, instance, owner \] - Issued(T::ClassId, T::InstanceId, T::AccountId), - /// An asset `instance` was transferred. \[ class, instance, from, to \] - Transferred(T::ClassId, T::InstanceId, T::AccountId, T::AccountId), - /// An asset `instance` was destroyed. \[ class, instance, owner \] - Burned(T::ClassId, T::InstanceId, T::AccountId), - /// Some asset `instance` was frozen. \[ class, instance \] - Frozen(T::ClassId, T::InstanceId), - /// Some asset `instance` was thawed. \[ class, instance \] - Thawed(T::ClassId, T::InstanceId), - /// Some asset `class` was frozen. \[ class \] - ClassFrozen(T::ClassId), - /// Some asset `class` was thawed. \[ class \] - ClassThawed(T::ClassId), - /// The owner changed \[ class, new_owner \] - OwnerChanged(T::ClassId, T::AccountId), - /// The management team changed \[ class, issuer, admin, freezer \] - TeamChanged(T::ClassId, T::AccountId, T::AccountId, T::AccountId), + /// An asset class was created. + Created { class: T::ClassId, creator: T::AccountId, owner: T::AccountId }, + /// An asset class was force-created. + ForceCreated { class: T::ClassId, owner: T::AccountId }, + /// An asset `class` was destroyed. + Destroyed { class: T::ClassId }, + /// An asset `instance` was issued. + Issued { class: T::ClassId, instance: T::InstanceId, owner: T::AccountId }, + /// An asset `instance` was transferred. + Transferred { + class: T::ClassId, + instance: T::InstanceId, + from: T::AccountId, + to: T::AccountId, + }, + /// An asset `instance` was destroyed. + Burned { class: T::ClassId, instance: T::InstanceId, owner: T::AccountId }, + /// Some asset `instance` was frozen. + Frozen { class: T::ClassId, instance: T::InstanceId }, + /// Some asset `instance` was thawed. + Thawed { class: T::ClassId, instance: T::InstanceId }, + /// Some asset `class` was frozen. + ClassFrozen { class: T::ClassId }, + /// Some asset `class` was thawed. + ClassThawed { class: T::ClassId }, + /// The owner changed. + OwnerChanged { class: T::ClassId, new_owner: T::AccountId }, + /// The management team changed. + TeamChanged { + class: T::ClassId, + issuer: T::AccountId, + admin: T::AccountId, + freezer: T::AccountId, + }, /// An `instance` of an asset `class` has been approved by the `owner` for transfer by a /// `delegate`. - /// \[ class, instance, owner, delegate \] - ApprovedTransfer(T::ClassId, T::InstanceId, T::AccountId, T::AccountId), + ApprovedTransfer { + class: T::ClassId, + instance: T::InstanceId, + owner: T::AccountId, + delegate: T::AccountId, + }, /// An approval for a `delegate` account to transfer the `instance` of an asset `class` was /// cancelled by its `owner`. - /// \[ class, instance, owner, delegate \] - ApprovalCancelled(T::ClassId, T::InstanceId, T::AccountId, T::AccountId), + ApprovalCancelled { + class: T::ClassId, + instance: T::InstanceId, + owner: T::AccountId, + delegate: T::AccountId, + }, /// An asset `class` has had its attributes changed by the `Force` origin. - /// \[ class \] - AssetStatusChanged(T::ClassId), - /// New metadata has been set for an asset class. \[ class, data, is_frozen \] - ClassMetadataSet(T::ClassId, BoundedVec, bool), - /// Metadata has been cleared for an asset class. \[ class \] - ClassMetadataCleared(T::ClassId), + AssetStatusChanged { class: T::ClassId }, + /// New metadata has been set for an asset class. + ClassMetadataSet { + class: T::ClassId, + data: BoundedVec, + is_frozen: bool, + }, + /// Metadata has been cleared for an asset class. + ClassMetadataCleared { class: T::ClassId }, /// New metadata has been set for an asset instance. - /// \[ class, instance, data, is_frozen \] - MetadataSet(T::ClassId, T::InstanceId, BoundedVec, bool), - /// Metadata has been cleared for an asset instance. \[ class, instance \] - MetadataCleared(T::ClassId, T::InstanceId), - /// Metadata has been cleared for an asset instance. \[ class, successful_instances \] - Redeposited(T::ClassId, Vec), + MetadataSet { + class: T::ClassId, + instance: T::InstanceId, + data: BoundedVec, + is_frozen: bool, + }, + /// Metadata has been cleared for an asset instance. + MetadataCleared { class: T::ClassId, instance: T::InstanceId }, + /// Metadata has been cleared for an asset instance. + Redeposited { class: T::ClassId, successful_instances: Vec }, /// New attribute metadata has been set for an asset class or instance. - /// \[ class, maybe_instance, key, value \] - AttributeSet( - T::ClassId, - Option, - BoundedVec, - BoundedVec, - ), + AttributeSet { + class: T::ClassId, + maybe_instance: Option, + key: BoundedVec, + value: BoundedVec, + }, /// Attribute metadata has been cleared for an asset class or instance. - /// \[ class, maybe_instance, key, maybe_value \] - AttributeCleared(T::ClassId, Option, BoundedVec), + AttributeCleared { + class: T::ClassId, + maybe_instance: Option, + key: BoundedVec, + }, } #[pallet::error] @@ -317,7 +344,7 @@ pub mod pallet { admin.clone(), T::ClassDeposit::get(), false, - Event::Created(class, owner, admin), + Event::Created { class, creator: owner, owner: admin }, ) } @@ -353,7 +380,7 @@ pub mod pallet { owner.clone(), Zero::zero(), free_holding, - Event::ForceCreated(class, owner), + Event::ForceCreated { class, owner }, ) } @@ -549,7 +576,10 @@ pub mod pallet { } Class::::insert(&class, &class_details); - Self::deposit_event(Event::::Redeposited(class, successful)); + Self::deposit_event(Event::::Redeposited { + class, + successful_instances: successful, + }); Ok(()) } @@ -580,7 +610,7 @@ pub mod pallet { details.is_frozen = true; Asset::::insert(&class, &instance, &details); - Self::deposit_event(Event::::Frozen(class, instance)); + Self::deposit_event(Event::::Frozen { class, instance }); Ok(()) } @@ -610,7 +640,7 @@ pub mod pallet { details.is_frozen = false; Asset::::insert(&class, &instance, &details); - Self::deposit_event(Event::::Thawed(class, instance)); + Self::deposit_event(Event::::Thawed { class, instance }); Ok(()) } @@ -636,7 +666,7 @@ pub mod pallet { details.is_frozen = true; - Self::deposit_event(Event::::ClassFrozen(class)); + Self::deposit_event(Event::::ClassFrozen { class }); Ok(()) }) } @@ -663,7 +693,7 @@ pub mod pallet { details.is_frozen = false; - Self::deposit_event(Event::::ClassThawed(class)); + Self::deposit_event(Event::::ClassThawed { class }); Ok(()) }) } @@ -703,7 +733,7 @@ pub mod pallet { )?; details.owner = owner.clone(); - Self::deposit_event(Event::OwnerChanged(class, owner)); + Self::deposit_event(Event::OwnerChanged { class, new_owner: owner }); Ok(()) }) } @@ -741,7 +771,7 @@ pub mod pallet { details.admin = admin.clone(); details.freezer = freezer.clone(); - Self::deposit_event(Event::TeamChanged(class, issuer, admin, freezer)); + Self::deposit_event(Event::TeamChanged { class, issuer, admin, freezer }); Ok(()) }) } @@ -783,7 +813,12 @@ pub mod pallet { Asset::::insert(&class, &instance, &details); let delegate = details.approved.expect("set as Some above; qed"); - Self::deposit_event(Event::ApprovedTransfer(class, instance, details.owner, delegate)); + Self::deposit_event(Event::ApprovedTransfer { + class, + instance, + owner: details.owner, + delegate, + }); Ok(()) } @@ -829,7 +864,12 @@ pub mod pallet { } Asset::::insert(&class, &instance, &details); - Self::deposit_event(Event::ApprovalCancelled(class, instance, details.owner, old)); + Self::deposit_event(Event::ApprovalCancelled { + class, + instance, + owner: details.owner, + delegate: old, + }); Ok(()) } @@ -874,7 +914,7 @@ pub mod pallet { asset.is_frozen = is_frozen; *maybe_asset = Some(asset); - Self::deposit_event(Event::AssetStatusChanged(class)); + Self::deposit_event(Event::AssetStatusChanged { class }); Ok(()) }) } @@ -940,7 +980,7 @@ pub mod pallet { Attribute::::insert((&class, maybe_instance, &key), (&value, deposit)); Class::::insert(class, &class_details); - Self::deposit_event(Event::AttributeSet(class, maybe_instance, key, value)); + Self::deposit_event(Event::AttributeSet { class, maybe_instance, key, value }); Ok(()) } @@ -988,7 +1028,7 @@ pub mod pallet { class_details.total_deposit.saturating_reduce(deposit); T::Currency::unreserve(&class_details.owner, deposit); Class::::insert(class, &class_details); - Self::deposit_event(Event::AttributeCleared(class, maybe_instance, key)); + Self::deposit_event(Event::AttributeCleared { class, maybe_instance, key }); } Ok(()) } @@ -1053,7 +1093,7 @@ pub mod pallet { *metadata = Some(InstanceMetadata { deposit, data: data.clone(), is_frozen }); Class::::insert(&class, &class_details); - Self::deposit_event(Event::MetadataSet(class, instance, data, is_frozen)); + Self::deposit_event(Event::MetadataSet { class, instance, data, is_frozen }); Ok(()) }) } @@ -1098,7 +1138,7 @@ pub mod pallet { class_details.total_deposit.saturating_reduce(deposit); Class::::insert(&class, &class_details); - Self::deposit_event(Event::MetadataCleared(class, instance)); + Self::deposit_event(Event::MetadataCleared { class, instance }); Ok(()) }) } @@ -1158,7 +1198,7 @@ pub mod pallet { *metadata = Some(ClassMetadata { deposit, data: data.clone(), is_frozen }); - Self::deposit_event(Event::ClassMetadataSet(class, data, is_frozen)); + Self::deposit_event(Event::ClassMetadataSet { class, data, is_frozen }); Ok(()) }) } @@ -1195,7 +1235,7 @@ pub mod pallet { let deposit = metadata.take().ok_or(Error::::Unknown)?.deposit; T::Currency::unreserve(&details.owner, deposit); - Self::deposit_event(Event::ClassMetadataCleared(class)); + Self::deposit_event(Event::ClassMetadataCleared { class }); Ok(()) }) } diff --git a/frame/utility/src/lib.rs b/frame/utility/src/lib.rs index 241526cef223..14d8a66514e3 100644 --- a/frame/utility/src/lib.rs +++ b/frame/utility/src/lib.rs @@ -109,8 +109,8 @@ pub mod pallet { #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { /// Batch of dispatches did not complete fully. Index of first failing dispatch given, as - /// well as the error. \[index, error\] - BatchInterrupted(u32, DispatchError), + /// well as the error. + BatchInterrupted { index: u32, error: DispatchError }, /// Batch of dispatches completed fully with no error. BatchCompleted, /// A single item within a Batch of dispatches has completed with no error. @@ -217,7 +217,10 @@ pub mod pallet { // Add the weight of this call. weight = weight.saturating_add(extract_actual_weight(&result, &info)); if let Err(e) = result { - Self::deposit_event(Event::BatchInterrupted(index as u32, e.error)); + Self::deposit_event(Event::BatchInterrupted { + index: index as u32, + error: e.error, + }); // Take the weight of this function itself into account. let base_weight = T::WeightInfo::batch(index.saturating_add(1) as u32); // Return the actual used weight + base_weight of this call. diff --git a/frame/utility/src/tests.rs b/frame/utility/src/tests.rs index f4d09a30ec07..32582fae8211 100644 --- a/frame/utility/src/tests.rs +++ b/frame/utility/src/tests.rs @@ -339,8 +339,11 @@ fn batch_with_signed_filters() { vec![Call::Balances(pallet_balances::Call::transfer_keep_alive { dest: 2, value: 1 })] ),); System::assert_last_event( - utility::Event::BatchInterrupted(0, frame_system::Error::::CallFiltered.into()) - .into(), + utility::Event::BatchInterrupted { + index: 0, + error: frame_system::Error::::CallFiltered.into(), + } + .into(), ); }); } @@ -411,7 +414,7 @@ fn batch_handles_weight_refund() { let result = call.dispatch(Origin::signed(1)); assert_ok!(result); System::assert_last_event( - utility::Event::BatchInterrupted(1, DispatchError::Other("")).into(), + utility::Event::BatchInterrupted { index: 1, error: DispatchError::Other("") }.into(), ); // No weight is refunded assert_eq!(extract_actual_weight(&result, &info), info.weight); @@ -426,7 +429,7 @@ fn batch_handles_weight_refund() { let result = call.dispatch(Origin::signed(1)); assert_ok!(result); System::assert_last_event( - utility::Event::BatchInterrupted(1, DispatchError::Other("")).into(), + utility::Event::BatchInterrupted { index: 1, error: DispatchError::Other("") }.into(), ); assert_eq!(extract_actual_weight(&result, &info), info.weight - diff * batch_len); @@ -439,7 +442,7 @@ fn batch_handles_weight_refund() { let result = call.dispatch(Origin::signed(1)); assert_ok!(result); System::assert_last_event( - utility::Event::BatchInterrupted(1, DispatchError::Other("")).into(), + utility::Event::BatchInterrupted { index: 1, error: DispatchError::Other("") }.into(), ); assert_eq!( extract_actual_weight(&result, &info), @@ -587,8 +590,11 @@ fn batch_all_does_not_nest() { // and balances. assert_ok!(Utility::batch_all(Origin::signed(1), vec![batch_nested])); System::assert_has_event( - utility::Event::BatchInterrupted(0, frame_system::Error::::CallFiltered.into()) - .into(), + utility::Event::BatchInterrupted { + index: 0, + error: frame_system::Error::::CallFiltered.into(), + } + .into(), ); assert_eq!(Balances::free_balance(1), 10); assert_eq!(Balances::free_balance(2), 10); diff --git a/frame/vesting/src/lib.rs b/frame/vesting/src/lib.rs index 654723d009fa..6857918bc9a1 100644 --- a/frame/vesting/src/lib.rs +++ b/frame/vesting/src/lib.rs @@ -104,9 +104,9 @@ enum VestingAction { /// Do not actively remove any schedules. Passive, /// Remove the schedule specified by the index. - Remove(usize), + Remove { index: usize }, /// Remove the two schedules, specified by index, so they can be merged. - Merge(usize, usize), + Merge { index1: usize, index2: usize }, } impl VestingAction { @@ -114,8 +114,8 @@ impl VestingAction { fn should_remove(&self, index: usize) -> bool { match self { Self::Passive => false, - Self::Remove(index1) => *index1 == index, - Self::Merge(index1, index2) => *index1 == index || *index2 == index, + Self::Remove { index: index1 } => *index1 == index, + Self::Merge { index1, index2 } => *index1 == index || *index2 == index, } } @@ -279,10 +279,9 @@ pub mod pallet { pub enum Event { /// The amount vested has been updated. This could indicate a change in funds available. /// The balance given is the amount which is left unvested (and thus locked). - /// \[account, unvested\] - VestingUpdated(T::AccountId, BalanceOf), + VestingUpdated { account: T::AccountId, unvested: BalanceOf }, /// An \[account\] has become fully vested. - VestingCompleted(T::AccountId), + VestingCompleted { account: T::AccountId }, } /// Error for the vesting pallet. @@ -450,7 +449,8 @@ pub mod pallet { let schedule2_index = schedule2_index as usize; let schedules = Self::vesting(&who).ok_or(Error::::NotVesting)?; - let merge_action = VestingAction::Merge(schedule1_index, schedule2_index); + let merge_action = + VestingAction::Merge { index1: schedule1_index, index2: schedule2_index }; let (schedules, locked_now) = Self::exec_action(schedules.to_vec(), merge_action)?; @@ -590,11 +590,14 @@ impl Pallet { fn write_lock(who: &T::AccountId, total_locked_now: BalanceOf) { if total_locked_now.is_zero() { T::Currency::remove_lock(VESTING_ID, who); - Self::deposit_event(Event::::VestingCompleted(who.clone())); + Self::deposit_event(Event::::VestingCompleted { account: who.clone() }); } else { let reasons = WithdrawReasons::TRANSFER | WithdrawReasons::RESERVE; T::Currency::set_lock(VESTING_ID, who, total_locked_now, reasons); - Self::deposit_event(Event::::VestingUpdated(who.clone(), total_locked_now)); + Self::deposit_event(Event::::VestingUpdated { + account: who.clone(), + unvested: total_locked_now, + }); }; } @@ -637,7 +640,7 @@ impl Pallet { action: VestingAction, ) -> Result<(Vec, T::BlockNumber>>, BalanceOf), DispatchError> { let (schedules, locked_now) = match action { - VestingAction::Merge(idx1, idx2) => { + VestingAction::Merge { index1: idx1, index2: idx2 } => { // The schedule index is based off of the schedule ordering prior to filtering out // any schedules that may be ending at this block. let schedule1 = *schedules.get(idx1).ok_or(Error::::ScheduleIndexOutOfBounds)?; @@ -762,7 +765,7 @@ where /// Remove a vesting schedule for a given account. fn remove_vesting_schedule(who: &T::AccountId, schedule_index: u32) -> DispatchResult { let schedules = Self::vesting(who).ok_or(Error::::NotVesting)?; - let remove_action = VestingAction::Remove(schedule_index as usize); + let remove_action = VestingAction::Remove { index: schedule_index as usize }; let (schedules, locked_now) = Self::exec_action(schedules.to_vec(), remove_action)?; From 7aa029ae4101ab61aa1d5d8a043cdf53b853225d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Nov 2021 19:39:11 +0000 Subject: [PATCH 187/695] Bump tokio from 1.12.0 to 1.13.0 (#10265) Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.12.0 to 1.13.0. - [Release notes](https://github.com/tokio-rs/tokio/releases) - [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.12.0...tokio-1.13.0) --- updated-dependencies: - dependency-name: tokio dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- bin/node/cli/Cargo.toml | 2 +- client/cli/Cargo.toml | 2 +- client/consensus/manual-seal/Cargo.toml | 2 +- client/finality-grandpa/Cargo.toml | 2 +- client/offchain/Cargo.toml | 2 +- client/rpc-servers/Cargo.toml | 2 +- client/service/Cargo.toml | 2 +- client/service/test/Cargo.toml | 2 +- test-utils/test-crate/Cargo.toml | 2 +- test-utils/test-runner/Cargo.toml | 2 +- utils/frame/remote-externalities/Cargo.toml | 2 +- utils/frame/rpc/support/Cargo.toml | 2 +- utils/prometheus/Cargo.toml | 4 ++-- 14 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 57bf1278822c..99b2b53a74a4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10545,9 +10545,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2c2416fdedca8443ae44b4527de1ea633af61d8f7169ffa6e72c5b53d24efcc" +checksum = "588b2d10a336da58d877567cd8fb8a14b463e2104910f8132cd054b4b96e29ee" dependencies = [ "autocfg 1.0.1", "bytes 1.0.1", diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index 122f2d0c2c8f..7529138c7f9d 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -129,7 +129,7 @@ platforms = "1.1" async-std = { version = "1.10.0", features = ["attributes"] } soketto = "0.4.2" criterion = { version = "0.3.5", features = [ "async_tokio" ] } -tokio = { version = "1.10", features = ["macros", "time"] } +tokio = { version = "1.13", features = ["macros", "time"] } jsonrpsee-ws-client = "0.4.1" wait-timeout = "0.2" remote-externalities = { path = "../../../utils/frame/remote-externalities" } diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index b027063b109a..2855e63cdc6a 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] log = "0.4.11" regex = "1.5.4" -tokio = { version = "1.10", features = [ "signal", "rt-multi-thread" ] } +tokio = { version = "1.13", features = [ "signal", "rt-multi-thread" ] } futures = "0.3.9" fdlimit = "0.2.1" libp2p = "0.39.1" diff --git a/client/consensus/manual-seal/Cargo.toml b/client/consensus/manual-seal/Cargo.toml index a7679f53ea9e..90edc15863cd 100644 --- a/client/consensus/manual-seal/Cargo.toml +++ b/client/consensus/manual-seal/Cargo.toml @@ -45,7 +45,7 @@ sp-timestamp = { path = "../../../primitives/timestamp", version = "4.0.0-dev" } prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.10.0-dev" } [dev-dependencies] -tokio = { version = "1.10.0", features = ["rt-multi-thread", "macros"] } +tokio = { version = "1.13.0", features = ["rt-multi-thread", "macros"] } sc-basic-authorship = { path = "../../basic-authorship", version = "0.10.0-dev" } substrate-test-runtime-client = { path = "../../../test-utils/runtime/client", version = "2.0.0" } substrate-test-runtime-transaction-pool = { path = "../../../test-utils/runtime/transaction-pool", version = "2.0.0" } diff --git a/client/finality-grandpa/Cargo.toml b/client/finality-grandpa/Cargo.toml index 43511ea59f14..ec4bac715ad4 100644 --- a/client/finality-grandpa/Cargo.toml +++ b/client/finality-grandpa/Cargo.toml @@ -57,5 +57,5 @@ sc-network-test = { version = "0.8.0", path = "../network/test" } sp-keyring = { version = "4.0.0-dev", path = "../../primitives/keyring" } substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } sp-tracing = { version = "4.0.0-dev", path = "../../primitives/tracing" } -tokio = "1.10" +tokio = "1.13" tempfile = "3.1.0" diff --git a/client/offchain/Cargo.toml b/client/offchain/Cargo.toml index c93eec85888d..2a6fdddd7ad3 100644 --- a/client/offchain/Cargo.toml +++ b/client/offchain/Cargo.toml @@ -43,7 +43,7 @@ sc-transaction-pool-api = { version = "4.0.0-dev", path = "../transaction-pool/a sp-tracing = { version = "4.0.0-dev", path = "../../primitives/tracing" } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } -tokio = "1.10" +tokio = "1.13" lazy_static = "1.4.0" [features] diff --git a/client/rpc-servers/Cargo.toml b/client/rpc-servers/Cargo.toml index f0ae6172d6d9..3be238078506 100644 --- a/client/rpc-servers/Cargo.toml +++ b/client/rpc-servers/Cargo.toml @@ -19,7 +19,7 @@ pubsub = { package = "jsonrpc-pubsub", version = "18.0.0" } log = "0.4.8" prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.10.0-dev"} serde_json = "1.0.68" -tokio = "1.10" +tokio = "1.13" http = { package = "jsonrpc-http-server", version = "18.0.0" } ipc = { package = "jsonrpc-ipc-server", version = "18.0.0" } ws = { package = "jsonrpc-ws-server", version = "18.0.0" } diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index 38729fd4ba5c..a66a4fc67680 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -78,7 +78,7 @@ parity-util-mem = { version = "0.10.2", default-features = false, features = [ "primitive-types", ] } async-trait = "0.1.50" -tokio = { version = "1.10", features = ["time", "rt-multi-thread"] } +tokio = { version = "1.13", features = ["time", "rt-multi-thread"] } tempfile = "3.1.0" directories = "4.0.1" diff --git a/client/service/test/Cargo.toml b/client/service/test/Cargo.toml index 114473b66c97..fe953a53bdd0 100644 --- a/client/service/test/Cargo.toml +++ b/client/service/test/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] hex = "0.4" hex-literal = "0.3.4" tempfile = "3.1.0" -tokio = { version = "1.10.0", features = ["time"] } +tokio = { version = "1.13.0", features = ["time"] } log = "0.4.8" fdlimit = "0.2.1" parking_lot = "0.11.1" diff --git a/test-utils/test-crate/Cargo.toml b/test-utils/test-crate/Cargo.toml index 071a82f3c769..4621332ccc0c 100644 --- a/test-utils/test-crate/Cargo.toml +++ b/test-utils/test-crate/Cargo.toml @@ -12,6 +12,6 @@ publish = false targets = ["x86_64-unknown-linux-gnu"] [dev-dependencies] -tokio = { version = "1.10", features = ["macros"] } +tokio = { version = "1.13", features = ["macros"] } test-utils = { version = "4.0.0-dev", path = "..", package = "substrate-test-utils" } sc-service = { version = "0.10.0-dev", path = "../../client/service" } diff --git a/test-utils/test-runner/Cargo.toml b/test-utils/test-runner/Cargo.toml index 9299076bb1f6..7066fc778cbd 100644 --- a/test-utils/test-runner/Cargo.toml +++ b/test-utils/test-runner/Cargo.toml @@ -48,7 +48,7 @@ frame-system = { path = "../../frame/system" } log = "0.4.8" futures = "0.3.16" -tokio = { version = "1.10", features = ["signal"] } +tokio = { version = "1.13", features = ["signal"] } # Calling RPC jsonrpc-core = "18.0" num-traits = "0.2.14" diff --git a/utils/frame/remote-externalities/Cargo.toml b/utils/frame/remote-externalities/Cargo.toml index 8f54dd01df0a..105ab1739f5b 100644 --- a/utils/frame/remote-externalities/Cargo.toml +++ b/utils/frame/remote-externalities/Cargo.toml @@ -28,7 +28,7 @@ sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } sp-version = { version = "4.0.0-dev", path = "../../../primitives/version" } [dev-dependencies] -tokio = { version = "1.10", features = ["macros", "rt-multi-thread"] } +tokio = { version = "1.13", features = ["macros", "rt-multi-thread"] } pallet-elections-phragmen = { path = "../../../frame/elections-phragmen", version = "5.0.0-dev" } frame-support = { path = "../../../frame/support", version = "4.0.0-dev" } diff --git a/utils/frame/rpc/support/Cargo.toml b/utils/frame/rpc/support/Cargo.toml index 0d21bdd6c018..dbaa12ee5ddb 100644 --- a/utils/frame/rpc/support/Cargo.toml +++ b/utils/frame/rpc/support/Cargo.toml @@ -26,4 +26,4 @@ sc-rpc-api = { version = "0.10.0-dev", path = "../../../../client/rpc-api" } [dev-dependencies] frame-system = { version = "4.0.0-dev", path = "../../../../frame/system" } scale-info = "1.0" -tokio = "1.10" +tokio = "1.13" diff --git a/utils/prometheus/Cargo.toml b/utils/prometheus/Cargo.toml index 390a1c733cbd..e2104ec5d55a 100644 --- a/utils/prometheus/Cargo.toml +++ b/utils/prometheus/Cargo.toml @@ -18,9 +18,9 @@ prometheus = { version = "0.13.0", default-features = false } futures-util = { version = "0.3.17", default-features = false, features = ["io"] } derive_more = "0.99" async-std = { version = "1.10.0", features = ["unstable"] } -tokio = "1.10" +tokio = "1.13" hyper = { version = "0.14.14", default-features = false, features = ["http1", "server", "tcp"] } [dev-dependencies] hyper = { version = "0.14.14", features = ["client"] } -tokio = { version = "1.10", features = ["rt-multi-thread"] } +tokio = { version = "1.13", features = ["rt-multi-thread"] } From bc4cb49f4b3993887e6e9a8f6a7f649928f92689 Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Mon, 15 Nov 2021 20:41:41 +0100 Subject: [PATCH 188/695] client/service: refactor group param of spawn into an Enum (#10248) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refractored group param to enum * refractored group param to enum * changed group param to GroupName enum for other methods too such as spawn_inner updated docs * revert on task type * put back ticks in GroupName * Update client/service/src/task_manager/mod.rs Co-authored-by: Bastian Köcher * document group name change specific to actual in enum declaration * change documentation * Update client/service/src/task_manager/mod.rs Co-authored-by: Andronik Ordian * changed Actual to Specific * Update client/service/src/task_manager/mod.rs Co-authored-by: Andronik Ordian * Update client/service/src/task_manager/mod.rs Co-authored-by: Bastian Köcher * Update client/service/src/task_manager/mod.rs Co-authored-by: Bastian Köcher * Update client/service/src/task_manager/mod.rs Co-authored-by: Bastian Köcher Co-authored-by: Damilare Co-authored-by: Bastian Köcher Co-authored-by: Andronik Ordian --- client/service/src/task_manager/mod.rs | 50 ++++++++++++++++++++------ 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/client/service/src/task_manager/mod.rs b/client/service/src/task_manager/mod.rs index 64c00226073c..25d3ecd7d5c3 100644 --- a/client/service/src/task_manager/mod.rs +++ b/client/service/src/task_manager/mod.rs @@ -41,6 +41,32 @@ mod tests; /// Default task group name. pub const DEFAULT_GROUP_NAME: &'static str = "default"; +/// The name of a group a task belongs to. +/// +/// This name is passed belong-side the task name to the prometheus metrics and can be used +/// to group tasks. +pub enum GroupName { + /// Sets the group name to `default`. + Default, + /// Use the specifically given name as group name. + Specific(&'static str), +} + +impl From> for GroupName { + fn from(name: Option<&'static str>) -> Self { + match name { + Some(name) => Self::Specific(name), + None => Self::Default, + } + } +} + +impl From<&'static str> for GroupName { + fn from(name: &'static str) -> Self { + Self::Specific(name) + } +} + /// An handle for spawning tasks in the service. #[derive(Clone)] pub struct SpawnTaskHandle { @@ -51,10 +77,10 @@ pub struct SpawnTaskHandle { } impl SpawnTaskHandle { - /// Spawns the given task with the given name and an optional group name. + /// Spawns the given task with the given name and a group name. /// If group is not specified `DEFAULT_GROUP_NAME` will be used. /// - /// Note that the `name`/`group` is a `&'static str`. The reason for this choice is that + /// Note that the `name` is a `&'static str`. The reason for this choice is that /// statistics about this task are getting reported to the Prometheus endpoint (if enabled), and /// that therefore the set of possible task names must be bounded. /// @@ -63,7 +89,7 @@ impl SpawnTaskHandle { pub fn spawn( &self, name: &'static str, - group: Option<&'static str>, + group: impl Into, task: impl Future + Send + 'static, ) { self.spawn_inner(name, group, task, TaskType::Async) @@ -73,7 +99,7 @@ impl SpawnTaskHandle { pub fn spawn_blocking( &self, name: &'static str, - group: Option<&'static str>, + group: impl Into, task: impl Future + Send + 'static, ) { self.spawn_inner(name, group, task, TaskType::Blocking) @@ -83,7 +109,7 @@ impl SpawnTaskHandle { fn spawn_inner( &self, name: &'static str, - group: Option<&'static str>, + group: impl Into, task: impl Future + Send + 'static, task_type: TaskType, ) { @@ -94,8 +120,12 @@ impl SpawnTaskHandle { let on_exit = self.on_exit.clone(); let metrics = self.metrics.clone(); - // If no group is specified use default. - let group = group.unwrap_or(DEFAULT_GROUP_NAME); + + let group = match group.into() { + GroupName::Specific(var) => var, + // If no group is specified use default. + GroupName::Default => DEFAULT_GROUP_NAME, + }; // Note that we increase the started counter here and not within the future. This way, // we could properly visualize on Prometheus situations where the spawning doesn't work. @@ -198,7 +228,7 @@ impl SpawnEssentialTaskHandle { pub fn spawn( &self, name: &'static str, - group: Option<&'static str>, + group: impl Into, task: impl Future + Send + 'static, ) { self.spawn_inner(name, group, task, TaskType::Async) @@ -210,7 +240,7 @@ impl SpawnEssentialTaskHandle { pub fn spawn_blocking( &self, name: &'static str, - group: Option<&'static str>, + group: impl Into, task: impl Future + Send + 'static, ) { self.spawn_inner(name, group, task, TaskType::Blocking) @@ -219,7 +249,7 @@ impl SpawnEssentialTaskHandle { fn spawn_inner( &self, name: &'static str, - group: Option<&'static str>, + group: impl Into, task: impl Future + Send + 'static, task_type: TaskType, ) { From c087bbedbde16711450c186518314903a2949cb3 Mon Sep 17 00:00:00 2001 From: David Salami <31099392+Wizdave97@users.noreply.github.com> Date: Tue, 16 Nov 2021 02:56:00 +0100 Subject: [PATCH 189/695] Add field names to pallet Event variants (#9993) * convert pallet-assets events to struct types * updated events of a couple pallets * updated pallet event field names * update pallet event field names * updated events in test files * cargo fmt * minorfixes * fix assertion error * minor fix * formatting fix * fmt --- bin/node/executor/tests/basic.rs | 69 ++-- frame/assets/src/benchmarking.rs | 56 +-- frame/assets/src/functions.rs | 41 +- frame/assets/src/lib.rs | 125 +++--- frame/assets/src/tests.rs | 7 +- frame/atomic-swap/src/lib.rs | 21 +- frame/bags-list/src/lib.rs | 6 +- frame/balances/src/lib.rs | 114 +++--- frame/balances/src/tests.rs | 30 +- frame/balances/src/tests_local.rs | 10 +- frame/balances/src/tests_reentrancy.rs | 47 ++- frame/bounties/src/benchmarking.rs | 6 +- frame/bounties/src/lib.rs | 49 ++- frame/bounties/src/tests.rs | 16 +- frame/collective/src/benchmarking.rs | 16 +- frame/collective/src/lib.rs | 77 ++-- frame/collective/src/tests.rs | 373 ++++++++++++++---- frame/contracts/src/tests.rs | 38 +- frame/democracy/src/benchmarking.rs | 2 +- frame/democracy/src/lib.rs | 112 +++--- .../election-provider-multi-phase/src/lib.rs | 48 ++- .../src/signed.rs | 4 +- frame/elections-phragmen/src/lib.rs | 63 +-- frame/elections/src/lib.rs | 23 +- frame/examples/basic/src/lib.rs | 17 +- frame/examples/offchain-worker/src/lib.rs | 5 +- frame/gilt/src/lib.rs | 36 +- frame/grandpa/src/lib.rs | 10 +- frame/grandpa/src/tests.rs | 10 +- frame/identity/src/benchmarking.rs | 8 +- frame/identity/src/lib.rs | 69 ++-- frame/im-online/src/lib.rs | 12 +- frame/indices/src/lib.rs | 22 +- frame/lottery/src/lib.rs | 8 +- frame/membership/src/lib.rs | 2 +- frame/multisig/src/lib.rs | 63 +-- frame/multisig/src/tests.rs | 9 +- frame/nicks/src/lib.rs | 30 +- frame/node-authorization/src/lib.rs | 42 +- frame/offences/benchmarking/src/lib.rs | 14 +- frame/offences/src/lib.rs | 4 +- frame/offences/src/tests.rs | 10 +- frame/proxy/src/benchmarking.rs | 18 +- frame/proxy/src/lib.rs | 44 ++- frame/proxy/src/tests.rs | 62 +-- frame/staking/src/slashing.rs | 2 +- frame/staking/src/tests.rs | 4 +- frame/transaction-payment/src/lib.rs | 8 +- 48 files changed, 1181 insertions(+), 681 deletions(-) diff --git a/bin/node/executor/tests/basic.rs b/bin/node/executor/tests/basic.rs index b7df7bf0bd41..7dc6c22aa354 100644 --- a/bin/node/executor/tests/basic.rs +++ b/bin/node/executor/tests/basic.rs @@ -387,24 +387,27 @@ fn full_native_block_import_works() { }, EventRecord { phase: Phase::ApplyExtrinsic(1), - event: Event::Balances(pallet_balances::Event::Withdraw(alice().into(), fees)), + event: Event::Balances(pallet_balances::Event::Withdraw { + who: alice().into(), + amount: fees, + }), topics: vec![], }, EventRecord { phase: Phase::ApplyExtrinsic(1), - event: Event::Balances(pallet_balances::Event::Transfer( - alice().into(), - bob().into(), - 69 * DOLLARS, - )), + event: Event::Balances(pallet_balances::Event::Transfer { + from: alice().into(), + to: bob().into(), + amount: 69 * DOLLARS, + }), topics: vec![], }, EventRecord { phase: Phase::ApplyExtrinsic(1), - event: Event::Balances(pallet_balances::Event::Deposit( - pallet_treasury::Pallet::::account_id(), - fees * 8 / 10, - )), + event: Event::Balances(pallet_balances::Event::Deposit { + who: pallet_treasury::Pallet::::account_id(), + amount: fees * 8 / 10, + }), topics: vec![], }, EventRecord { @@ -454,24 +457,27 @@ fn full_native_block_import_works() { }, EventRecord { phase: Phase::ApplyExtrinsic(1), - event: Event::Balances(pallet_balances::Event::Withdraw(bob().into(), fees)), + event: Event::Balances(pallet_balances::Event::Withdraw { + who: bob().into(), + amount: fees, + }), topics: vec![], }, EventRecord { phase: Phase::ApplyExtrinsic(1), - event: Event::Balances(pallet_balances::Event::Transfer( - bob().into(), - alice().into(), - 5 * DOLLARS, - )), + event: Event::Balances(pallet_balances::Event::Transfer { + from: bob().into(), + to: alice().into(), + amount: 5 * DOLLARS, + }), topics: vec![], }, EventRecord { phase: Phase::ApplyExtrinsic(1), - event: Event::Balances(pallet_balances::Event::Deposit( - pallet_treasury::Pallet::::account_id(), - fees * 8 / 10, - )), + event: Event::Balances(pallet_balances::Event::Deposit { + who: pallet_treasury::Pallet::::account_id(), + amount: fees * 8 / 10, + }), topics: vec![], }, EventRecord { @@ -489,24 +495,27 @@ fn full_native_block_import_works() { }, EventRecord { phase: Phase::ApplyExtrinsic(2), - event: Event::Balances(pallet_balances::Event::Withdraw(alice().into(), fees)), + event: Event::Balances(pallet_balances::Event::Withdraw { + who: alice().into(), + amount: fees, + }), topics: vec![], }, EventRecord { phase: Phase::ApplyExtrinsic(2), - event: Event::Balances(pallet_balances::Event::Transfer( - alice().into(), - bob().into(), - 15 * DOLLARS, - )), + event: Event::Balances(pallet_balances::Event::Transfer { + from: alice().into(), + to: bob().into(), + amount: 15 * DOLLARS, + }), topics: vec![], }, EventRecord { phase: Phase::ApplyExtrinsic(2), - event: Event::Balances(pallet_balances::Event::Deposit( - pallet_treasury::Pallet::::account_id(), - fees * 8 / 10, - )), + event: Event::Balances(pallet_balances::Event::Deposit { + who: pallet_treasury::Pallet::::account_id(), + amount: fees * 8 / 10, + }), topics: vec![], }, EventRecord { diff --git a/frame/assets/src/benchmarking.rs b/frame/assets/src/benchmarking.rs index d9de9ed3dedd..475864bac943 100644 --- a/frame/assets/src/benchmarking.rs +++ b/frame/assets/src/benchmarking.rs @@ -155,7 +155,7 @@ benchmarks_instance_pallet! { T::Currency::make_free_balance_be(&caller, DepositBalanceOf::::max_value()); }: _(SystemOrigin::Signed(caller.clone()), Default::default(), caller_lookup, 1u32.into()) verify { - assert_last_event::(Event::Created(Default::default(), caller.clone(), caller).into()); + assert_last_event::(Event::Created { asset_id: Default::default(), creator: caller.clone(), owner: caller }.into()); } force_create { @@ -163,7 +163,7 @@ benchmarks_instance_pallet! { let caller_lookup = T::Lookup::unlookup(caller.clone()); }: _(SystemOrigin::Root, Default::default(), caller_lookup, true, 1u32.into()) verify { - assert_last_event::(Event::ForceCreated(Default::default(), caller).into()); + assert_last_event::(Event::ForceCreated { asset_id: Default::default(), owner: caller }.into()); } destroy { @@ -177,7 +177,7 @@ benchmarks_instance_pallet! { let witness = Asset::::get(T::AssetId::default()).unwrap().destroy_witness(); }: _(SystemOrigin::Signed(caller), Default::default(), witness) verify { - assert_last_event::(Event::Destroyed(Default::default()).into()); + assert_last_event::(Event::Destroyed { asset_id: Default::default() }.into()); } mint { @@ -185,7 +185,7 @@ benchmarks_instance_pallet! { let amount = T::Balance::from(100u32); }: _(SystemOrigin::Signed(caller.clone()), Default::default(), caller_lookup, amount) verify { - assert_last_event::(Event::Issued(Default::default(), caller, amount).into()); + assert_last_event::(Event::Issued { asset_id: Default::default(), owner: caller, total_supply: amount }.into()); } burn { @@ -193,7 +193,7 @@ benchmarks_instance_pallet! { let (caller, caller_lookup) = create_default_minted_asset::(true, amount); }: _(SystemOrigin::Signed(caller.clone()), Default::default(), caller_lookup, amount) verify { - assert_last_event::(Event::Burned(Default::default(), caller, amount).into()); + assert_last_event::(Event::Burned { asset_id: Default::default(), owner: caller, balance: amount }.into()); } transfer { @@ -203,7 +203,7 @@ benchmarks_instance_pallet! { let target_lookup = T::Lookup::unlookup(target.clone()); }: _(SystemOrigin::Signed(caller.clone()), Default::default(), target_lookup, amount) verify { - assert_last_event::(Event::Transferred(Default::default(), caller, target, amount).into()); + assert_last_event::(Event::Transferred { asset_id: Default::default(), from: caller, to: target, amount }.into()); } transfer_keep_alive { @@ -215,7 +215,7 @@ benchmarks_instance_pallet! { }: _(SystemOrigin::Signed(caller.clone()), Default::default(), target_lookup, amount) verify { assert!(frame_system::Pallet::::account_exists(&caller)); - assert_last_event::(Event::Transferred(Default::default(), caller, target, amount).into()); + assert_last_event::(Event::Transferred { asset_id: Default::default(), from: caller, to: target, amount }.into()); } force_transfer { @@ -226,7 +226,7 @@ benchmarks_instance_pallet! { }: _(SystemOrigin::Signed(caller.clone()), Default::default(), caller_lookup, target_lookup, amount) verify { assert_last_event::( - Event::Transferred(Default::default(), caller, target, amount).into() + Event::Transferred { asset_id: Default::default(), from: caller, to: target, amount }.into() ); } @@ -234,7 +234,7 @@ benchmarks_instance_pallet! { let (caller, caller_lookup) = create_default_minted_asset::(true, 100u32.into()); }: _(SystemOrigin::Signed(caller.clone()), Default::default(), caller_lookup) verify { - assert_last_event::(Event::Frozen(Default::default(), caller).into()); + assert_last_event::(Event::Frozen { asset_id: Default::default(), who: caller }.into()); } thaw { @@ -246,14 +246,14 @@ benchmarks_instance_pallet! { )?; }: _(SystemOrigin::Signed(caller.clone()), Default::default(), caller_lookup) verify { - assert_last_event::(Event::Thawed(Default::default(), caller).into()); + assert_last_event::(Event::Thawed { asset_id: Default::default(), who: caller }.into()); } freeze_asset { let (caller, caller_lookup) = create_default_minted_asset::(true, 100u32.into()); }: _(SystemOrigin::Signed(caller.clone()), Default::default()) verify { - assert_last_event::(Event::AssetFrozen(Default::default()).into()); + assert_last_event::(Event::AssetFrozen { asset_id: Default::default() }.into()); } thaw_asset { @@ -264,7 +264,7 @@ benchmarks_instance_pallet! { )?; }: _(SystemOrigin::Signed(caller.clone()), Default::default()) verify { - assert_last_event::(Event::AssetThawed(Default::default()).into()); + assert_last_event::(Event::AssetThawed { asset_id: Default::default() }.into()); } transfer_ownership { @@ -273,7 +273,7 @@ benchmarks_instance_pallet! { let target_lookup = T::Lookup::unlookup(target.clone()); }: _(SystemOrigin::Signed(caller), Default::default(), target_lookup) verify { - assert_last_event::(Event::OwnerChanged(Default::default(), target).into()); + assert_last_event::(Event::OwnerChanged { asset_id: Default::default(), owner: target }.into()); } set_team { @@ -283,12 +283,12 @@ benchmarks_instance_pallet! { let target2 = T::Lookup::unlookup(account("target", 2, SEED)); }: _(SystemOrigin::Signed(caller), Default::default(), target0.clone(), target1.clone(), target2.clone()) verify { - assert_last_event::(Event::TeamChanged( - Default::default(), - account("target", 0, SEED), - account("target", 1, SEED), - account("target", 2, SEED), - ).into()); + assert_last_event::(Event::TeamChanged { + asset_id: Default::default(), + issuer: account("target", 0, SEED), + admin: account("target", 1, SEED), + freezer: account("target", 2, SEED), + }.into()); } set_metadata { @@ -304,7 +304,7 @@ benchmarks_instance_pallet! { }: _(SystemOrigin::Signed(caller), Default::default(), name.clone(), symbol.clone(), decimals) verify { let id = Default::default(); - assert_last_event::(Event::MetadataSet(id, name, symbol, decimals, false).into()); + assert_last_event::(Event::MetadataSet { asset_id: id, name, symbol, decimals, is_frozen: false }.into()); } clear_metadata { @@ -315,7 +315,7 @@ benchmarks_instance_pallet! { Assets::::set_metadata(origin, Default::default(), dummy.clone(), dummy, 12)?; }: _(SystemOrigin::Signed(caller), Default::default()) verify { - assert_last_event::(Event::MetadataCleared(Default::default()).into()); + assert_last_event::(Event::MetadataCleared { asset_id: Default::default() }.into()); } force_set_metadata { @@ -339,7 +339,7 @@ benchmarks_instance_pallet! { }: { call.dispatch_bypass_filter(origin)? } verify { let id = Default::default(); - assert_last_event::(Event::MetadataSet(id, name, symbol, decimals, false).into()); + assert_last_event::(Event::MetadataSet { asset_id: id, name, symbol, decimals, is_frozen: false }.into()); } force_clear_metadata { @@ -353,7 +353,7 @@ benchmarks_instance_pallet! { let call = Call::::force_clear_metadata { id: Default::default() }; }: { call.dispatch_bypass_filter(origin)? } verify { - assert_last_event::(Event::MetadataCleared(Default::default()).into()); + assert_last_event::(Event::MetadataCleared { asset_id: Default::default() }.into()); } force_asset_status { @@ -372,7 +372,7 @@ benchmarks_instance_pallet! { }; }: { call.dispatch_bypass_filter(origin)? } verify { - assert_last_event::(Event::AssetStatusChanged(Default::default()).into()); + assert_last_event::(Event::AssetStatusChanged { asset_id: Default::default() }.into()); } approve_transfer { @@ -385,7 +385,7 @@ benchmarks_instance_pallet! { let amount = 100u32.into(); }: _(SystemOrigin::Signed(caller.clone()), id, delegate_lookup, amount) verify { - assert_last_event::(Event::ApprovedTransfer(id, caller, delegate, amount).into()); + assert_last_event::(Event::ApprovedTransfer { asset_id: id, source: caller, delegate, amount }.into()); } transfer_approved { @@ -405,7 +405,7 @@ benchmarks_instance_pallet! { }: _(SystemOrigin::Signed(delegate.clone()), id, owner_lookup, dest_lookup, amount) verify { assert!(T::Currency::reserved_balance(&owner).is_zero()); - assert_event::(Event::Transferred(id, owner, dest, amount).into()); + assert_event::(Event::Transferred { asset_id: id, from: owner, to: dest, amount }.into()); } cancel_approval { @@ -420,7 +420,7 @@ benchmarks_instance_pallet! { Assets::::approve_transfer(origin, id, delegate_lookup.clone(), amount)?; }: _(SystemOrigin::Signed(caller.clone()), id, delegate_lookup) verify { - assert_last_event::(Event::ApprovalCancelled(id, caller, delegate).into()); + assert_last_event::(Event::ApprovalCancelled { asset_id: id, owner: caller, delegate }.into()); } force_cancel_approval { @@ -435,7 +435,7 @@ benchmarks_instance_pallet! { Assets::::approve_transfer(origin, id, delegate_lookup.clone(), amount)?; }: _(SystemOrigin::Signed(caller.clone()), id, caller_lookup, delegate_lookup) verify { - assert_last_event::(Event::ApprovalCancelled(id, caller, delegate).into()); + assert_last_event::(Event::ApprovalCancelled { asset_id: id, owner: caller, delegate }.into()); } impl_benchmark_test_suite!(Assets, crate::mock::new_test_ext(), crate::mock::Test) diff --git a/frame/assets/src/functions.rs b/frame/assets/src/functions.rs index a4685d88d049..f01954cb970e 100644 --- a/frame/assets/src/functions.rs +++ b/frame/assets/src/functions.rs @@ -275,7 +275,11 @@ impl, I: 'static> Pallet { details.supply = details.supply.saturating_add(amount); Ok(()) })?; - Self::deposit_event(Event::Issued(id, beneficiary.clone(), amount)); + Self::deposit_event(Event::Issued { + asset_id: id, + owner: beneficiary.clone(), + total_supply: amount, + }); Ok(()) } @@ -342,7 +346,7 @@ impl, I: 'static> Pallet { Ok(()) })?; - Self::deposit_event(Event::Burned(id, target.clone(), actual)); + Self::deposit_event(Event::Burned { asset_id: id, owner: target.clone(), balance: actual }); Ok(actual) } @@ -415,7 +419,12 @@ impl, I: 'static> Pallet { ) -> Result { // Early exist if no-op. if amount.is_zero() { - Self::deposit_event(Event::Transferred(id, source.clone(), dest.clone(), amount)); + Self::deposit_event(Event::Transferred { + asset_id: id, + from: source.clone(), + to: dest.clone(), + amount, + }); return Ok(amount) } @@ -476,7 +485,12 @@ impl, I: 'static> Pallet { Ok(()) })?; - Self::deposit_event(Event::Transferred(id, source.clone(), dest.clone(), credit)); + Self::deposit_event(Event::Transferred { + asset_id: id, + from: source.clone(), + to: dest.clone(), + amount: credit, + }); Ok(credit) } @@ -514,7 +528,7 @@ impl, I: 'static> Pallet { is_frozen: false, }, ); - Self::deposit_event(Event::ForceCreated(id, owner)); + Self::deposit_event(Event::ForceCreated { asset_id: id, owner }); Ok(()) } @@ -554,7 +568,7 @@ impl, I: 'static> Pallet { for ((owner, _), approval) in Approvals::::drain_prefix((&id,)) { T::Currency::unreserve(&owner, approval.deposit); } - Self::deposit_event(Event::Destroyed(id)); + Self::deposit_event(Event::Destroyed { asset_id: id }); Ok(DestroyWitness { accounts: details.accounts, @@ -599,7 +613,12 @@ impl, I: 'static> Pallet { }, )?; Asset::::insert(id, d); - Self::deposit_event(Event::ApprovedTransfer(id, owner.clone(), delegate.clone(), amount)); + Self::deposit_event(Event::ApprovedTransfer { + asset_id: id, + source: owner.clone(), + delegate: delegate.clone(), + amount, + }); Ok(()) } @@ -683,7 +702,13 @@ impl, I: 'static> Pallet { is_frozen: false, }); - Self::deposit_event(Event::MetadataSet(id, name, symbol, decimals, false)); + Self::deposit_event(Event::MetadataSet { + asset_id: id, + name, + symbol, + decimals, + is_frozen: false, + }); Ok(()) }) } diff --git a/frame/assets/src/lib.rs b/frame/assets/src/lib.rs index b89d411e41db..f2bc86843ad9 100644 --- a/frame/assets/src/lib.rs +++ b/frame/assets/src/lib.rs @@ -379,47 +379,70 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event, I: 'static = ()> { - /// Some asset class was created. \[asset_id, creator, owner\] - Created(T::AssetId, T::AccountId, T::AccountId), - /// Some assets were issued. \[asset_id, owner, total_supply\] - Issued(T::AssetId, T::AccountId, T::Balance), - /// Some assets were transferred. \[asset_id, from, to, amount\] - Transferred(T::AssetId, T::AccountId, T::AccountId, T::Balance), - /// Some assets were destroyed. \[asset_id, owner, balance\] - Burned(T::AssetId, T::AccountId, T::Balance), - /// The management team changed \[asset_id, issuer, admin, freezer\] - TeamChanged(T::AssetId, T::AccountId, T::AccountId, T::AccountId), - /// The owner changed \[asset_id, owner\] - OwnerChanged(T::AssetId, T::AccountId), - /// Some account `who` was frozen. \[asset_id, who\] - Frozen(T::AssetId, T::AccountId), - /// Some account `who` was thawed. \[asset_id, who\] - Thawed(T::AssetId, T::AccountId), - /// Some asset `asset_id` was frozen. \[asset_id\] - AssetFrozen(T::AssetId), - /// Some asset `asset_id` was thawed. \[asset_id\] - AssetThawed(T::AssetId), + /// Some asset class was created. + Created { asset_id: T::AssetId, creator: T::AccountId, owner: T::AccountId }, + /// Some assets were issued. + Issued { asset_id: T::AssetId, owner: T::AccountId, total_supply: T::Balance }, + /// Some assets were transferred. + Transferred { + asset_id: T::AssetId, + from: T::AccountId, + to: T::AccountId, + amount: T::Balance, + }, + /// Some assets were destroyed. + Burned { asset_id: T::AssetId, owner: T::AccountId, balance: T::Balance }, + /// The management team changed. + TeamChanged { + asset_id: T::AssetId, + issuer: T::AccountId, + admin: T::AccountId, + freezer: T::AccountId, + }, + /// The owner changed. + OwnerChanged { asset_id: T::AssetId, owner: T::AccountId }, + /// Some account `who` was frozen. + Frozen { asset_id: T::AssetId, who: T::AccountId }, + /// Some account `who` was thawed. + Thawed { asset_id: T::AssetId, who: T::AccountId }, + /// Some asset `asset_id` was frozen. + AssetFrozen { asset_id: T::AssetId }, + /// Some asset `asset_id` was thawed. + AssetThawed { asset_id: T::AssetId }, /// An asset class was destroyed. - Destroyed(T::AssetId), - /// Some asset class was force-created. \[asset_id, owner\] - ForceCreated(T::AssetId, T::AccountId), - /// New metadata has been set for an asset. \[asset_id, name, symbol, decimals, is_frozen\] - MetadataSet(T::AssetId, Vec, Vec, u8, bool), - /// Metadata has been cleared for an asset. \[asset_id\] - MetadataCleared(T::AssetId), + Destroyed { asset_id: T::AssetId }, + /// Some asset class was force-created. + ForceCreated { asset_id: T::AssetId, owner: T::AccountId }, + /// New metadata has been set for an asset. + MetadataSet { + asset_id: T::AssetId, + name: Vec, + symbol: Vec, + decimals: u8, + is_frozen: bool, + }, + /// Metadata has been cleared for an asset. + MetadataCleared { asset_id: T::AssetId }, /// (Additional) funds have been approved for transfer to a destination account. - /// \[asset_id, source, delegate, amount\] - ApprovedTransfer(T::AssetId, T::AccountId, T::AccountId, T::Balance), + ApprovedTransfer { + asset_id: T::AssetId, + source: T::AccountId, + delegate: T::AccountId, + amount: T::Balance, + }, /// An approval for account `delegate` was cancelled by `owner`. - /// \[id, owner, delegate\] - ApprovalCancelled(T::AssetId, T::AccountId, T::AccountId), + ApprovalCancelled { asset_id: T::AssetId, owner: T::AccountId, delegate: T::AccountId }, /// An `amount` was transferred in its entirety from `owner` to `destination` by /// the approved `delegate`. - /// \[id, owner, delegate, destination\] - TransferredApproved(T::AssetId, T::AccountId, T::AccountId, T::AccountId, T::Balance), + TransferredApproved { + asset_id: T::AssetId, + owner: T::AccountId, + delegate: T::AccountId, + destination: T::AccountId, + amount: T::Balance, + }, /// An asset has had its attributes changed by the `Force` origin. - /// \[id\] - AssetStatusChanged(T::AssetId), + AssetStatusChanged { asset_id: T::AssetId }, } #[pallet::error] @@ -505,7 +528,7 @@ pub mod pallet { is_frozen: false, }, ); - Self::deposit_event(Event::Created(id, owner, admin)); + Self::deposit_event(Event::Created { asset_id: id, creator: owner, owner: admin }); Ok(()) } @@ -761,7 +784,7 @@ pub mod pallet { Account::::mutate(id, &who, |a| a.is_frozen = true); - Self::deposit_event(Event::::Frozen(id, who)); + Self::deposit_event(Event::::Frozen { asset_id: id, who }); Ok(()) } @@ -790,7 +813,7 @@ pub mod pallet { Account::::mutate(id, &who, |a| a.is_frozen = false); - Self::deposit_event(Event::::Thawed(id, who)); + Self::deposit_event(Event::::Thawed { asset_id: id, who }); Ok(()) } @@ -816,7 +839,7 @@ pub mod pallet { d.is_frozen = true; - Self::deposit_event(Event::::AssetFrozen(id)); + Self::deposit_event(Event::::AssetFrozen { asset_id: id }); Ok(()) }) } @@ -843,7 +866,7 @@ pub mod pallet { d.is_frozen = false; - Self::deposit_event(Event::::AssetThawed(id)); + Self::deposit_event(Event::::AssetThawed { asset_id: id }); Ok(()) }) } @@ -882,7 +905,7 @@ pub mod pallet { details.owner = owner.clone(); - Self::deposit_event(Event::OwnerChanged(id, owner)); + Self::deposit_event(Event::OwnerChanged { asset_id: id, owner }); Ok(()) }) } @@ -920,7 +943,7 @@ pub mod pallet { details.admin = admin.clone(); details.freezer = freezer.clone(); - Self::deposit_event(Event::TeamChanged(id, issuer, admin, freezer)); + Self::deposit_event(Event::TeamChanged { asset_id: id, issuer, admin, freezer }); Ok(()) }) } @@ -977,7 +1000,7 @@ pub mod pallet { Metadata::::try_mutate_exists(id, |metadata| { let deposit = metadata.take().ok_or(Error::::Unknown)?.deposit; T::Currency::unreserve(&d.owner, deposit); - Self::deposit_event(Event::MetadataCleared(id)); + Self::deposit_event(Event::MetadataCleared { asset_id: id }); Ok(()) }) } @@ -1024,7 +1047,13 @@ pub mod pallet { is_frozen, }); - Self::deposit_event(Event::MetadataSet(id, name, symbol, decimals, is_frozen)); + Self::deposit_event(Event::MetadataSet { + asset_id: id, + name, + symbol, + decimals, + is_frozen, + }); Ok(()) }) } @@ -1051,7 +1080,7 @@ pub mod pallet { Metadata::::try_mutate_exists(id, |metadata| { let deposit = metadata.take().ok_or(Error::::Unknown)?.deposit; T::Currency::unreserve(&d.owner, deposit); - Self::deposit_event(Event::MetadataCleared(id)); + Self::deposit_event(Event::MetadataCleared { asset_id: id }); Ok(()) }) } @@ -1103,7 +1132,7 @@ pub mod pallet { asset.is_frozen = is_frozen; *maybe_asset = Some(asset); - Self::deposit_event(Event::AssetStatusChanged(id)); + Self::deposit_event(Event::AssetStatusChanged { asset_id: id }); Ok(()) }) } @@ -1169,7 +1198,7 @@ pub mod pallet { d.approvals.saturating_dec(); Asset::::insert(id, d); - Self::deposit_event(Event::ApprovalCancelled(id, owner, delegate)); + Self::deposit_event(Event::ApprovalCancelled { asset_id: id, owner, delegate }); Ok(()) } @@ -1211,7 +1240,7 @@ pub mod pallet { d.approvals.saturating_dec(); Asset::::insert(id, d); - Self::deposit_event(Event::ApprovalCancelled(id, owner, delegate)); + Self::deposit_event(Event::ApprovalCancelled { asset_id: id, owner, delegate }); Ok(()) } diff --git a/frame/assets/src/tests.rs b/frame/assets/src/tests.rs index 5250fafaa8f9..e24a1d45215d 100644 --- a/frame/assets/src/tests.rs +++ b/frame/assets/src/tests.rs @@ -500,7 +500,12 @@ fn transferring_less_than_one_unit_is_fine() { assert_ok!(Assets::mint(Origin::signed(1), 0, 1, 100)); assert_eq!(Assets::balance(0, 1), 100); assert_ok!(Assets::transfer(Origin::signed(1), 0, 2, 0)); - System::assert_last_event(mock::Event::Assets(crate::Event::Transferred(0, 1, 2, 0))); + System::assert_last_event(mock::Event::Assets(crate::Event::Transferred { + asset_id: 0, + from: 1, + to: 2, + amount: 0, + })); }); } diff --git a/frame/atomic-swap/src/lib.rs b/frame/atomic-swap/src/lib.rs index 9cf92c3bd233..4775cd06b1af 100644 --- a/frame/atomic-swap/src/lib.rs +++ b/frame/atomic-swap/src/lib.rs @@ -218,13 +218,12 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { - /// Swap created. \[account, proof, swap\] - NewSwap(T::AccountId, HashedProof, PendingSwap), + /// Swap created. + NewSwap { account: T::AccountId, proof: HashedProof, swap: PendingSwap }, /// Swap claimed. The last parameter indicates whether the execution succeeds. - /// \[account, proof, success\] - SwapClaimed(T::AccountId, HashedProof, bool), - /// Swap cancelled. \[account, proof\] - SwapCancelled(T::AccountId, HashedProof), + SwapClaimed { account: T::AccountId, proof: HashedProof, success: bool }, + /// Swap cancelled. + SwapCancelled { account: T::AccountId, proof: HashedProof }, } /// Old name generated by `decl_event`. @@ -268,7 +267,7 @@ pub mod pallet { }; PendingSwaps::::insert(target.clone(), hashed_proof.clone(), swap.clone()); - Self::deposit_event(Event::NewSwap(target, hashed_proof, swap)); + Self::deposit_event(Event::NewSwap { account: target, proof: hashed_proof, swap }); Ok(()) } @@ -304,7 +303,11 @@ pub mod pallet { PendingSwaps::::remove(target.clone(), hashed_proof.clone()); - Self::deposit_event(Event::SwapClaimed(target, hashed_proof, succeeded)); + Self::deposit_event(Event::SwapClaimed { + account: target, + proof: hashed_proof, + success: succeeded, + }); Ok(()) } @@ -333,7 +336,7 @@ pub mod pallet { swap.action.cancel(&swap.source); PendingSwaps::::remove(&target, hashed_proof.clone()); - Self::deposit_event(Event::SwapCancelled(target, hashed_proof)); + Self::deposit_event(Event::SwapCancelled { account: target, proof: hashed_proof }); Ok(()) } diff --git a/frame/bags-list/src/lib.rs b/frame/bags-list/src/lib.rs index 8d74ecc9bd2d..8be1afbe29bb 100644 --- a/frame/bags-list/src/lib.rs +++ b/frame/bags-list/src/lib.rs @@ -168,8 +168,8 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(crate) fn deposit_event)] pub enum Event { - /// Moved an account from one bag to another. \[who, from, to\]. - Rebagged(T::AccountId, VoteWeight, VoteWeight), + /// Moved an account from one bag to another. + Rebagged { who: T::AccountId, from: VoteWeight, to: VoteWeight }, } #[pallet::call] @@ -216,7 +216,7 @@ impl Pallet { let maybe_movement = list::Node::::get(&account) .and_then(|node| List::update_position_for(node, new_weight)); if let Some((from, to)) = maybe_movement { - Self::deposit_event(Event::::Rebagged(account.clone(), from, to)); + Self::deposit_event(Event::::Rebagged { who: account.clone(), from, to }); }; maybe_movement } diff --git a/frame/balances/src/lib.rs b/frame/balances/src/lib.rs index da8019583c3b..b7c64da46076 100644 --- a/frame/balances/src/lib.rs +++ b/frame/balances/src/lib.rs @@ -346,7 +346,7 @@ pub mod pallet { (account.free, account.reserved) })?; - Self::deposit_event(Event::BalanceSet(who, free, reserved)); + Self::deposit_event(Event::BalanceSet { who, free, reserved }); Ok(().into()) } @@ -454,31 +454,33 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event, I: 'static = ()> { - /// An account was created with some free balance. \[account, free_balance\] - Endowed(T::AccountId, T::Balance), + /// An account was created with some free balance. + Endowed { account: T::AccountId, free_balance: T::Balance }, /// An account was removed whose balance was non-zero but below ExistentialDeposit, - /// resulting in an outright loss. \[account, balance\] - DustLost(T::AccountId, T::Balance), - /// Transfer succeeded. \[from, to, value\] - Transfer(T::AccountId, T::AccountId, T::Balance), - /// A balance was set by root. \[who, free, reserved\] - BalanceSet(T::AccountId, T::Balance, T::Balance), - /// Some balance was reserved (moved from free to reserved). \[who, value\] - Reserved(T::AccountId, T::Balance), - /// Some balance was unreserved (moved from reserved to free). \[who, value\] - Unreserved(T::AccountId, T::Balance), + /// resulting in an outright loss. + DustLost { account: T::AccountId, amount: T::Balance }, + /// Transfer succeeded. + Transfer { from: T::AccountId, to: T::AccountId, amount: T::Balance }, + /// A balance was set by root. + BalanceSet { who: T::AccountId, free: T::Balance, reserved: T::Balance }, + /// Some balance was reserved (moved from free to reserved). + Reserved { who: T::AccountId, amount: T::Balance }, + /// Some balance was unreserved (moved from reserved to free). + Unreserved { who: T::AccountId, amount: T::Balance }, /// Some balance was moved from the reserve of the first account to the second account. /// Final argument indicates the destination balance type. - /// \[from, to, balance, destination_status\] - ReserveRepatriated(T::AccountId, T::AccountId, T::Balance, Status), - /// Some amount was deposited into the account (e.g. for transaction fees). \[who, - /// deposit\] - Deposit(T::AccountId, T::Balance), - /// Some amount was withdrawn from the account (e.g. for transaction fees). \[who, value\] - Withdraw(T::AccountId, T::Balance), - /// Some amount was removed from the account (e.g. for misbehavior). \[who, - /// amount_slashed\] - Slashed(T::AccountId, T::Balance), + ReserveRepatriated { + from: T::AccountId, + to: T::AccountId, + amount: T::Balance, + destination_status: Status, + }, + /// Some amount was deposited (e.g. for transaction fees). + Deposit { who: T::AccountId, amount: T::Balance }, + /// Some amount was withdrawn from the account (e.g. for transaction fees). + Withdraw { who: T::AccountId, amount: T::Balance }, + /// Some amount was removed from the account (e.g. for misbehavior). + Slashed { who: T::AccountId, amount: T::Balance }, } /// Old name generated by `decl_event`. @@ -742,7 +744,7 @@ pub struct DustCleaner, I: 'static = ()>( impl, I: 'static> Drop for DustCleaner { fn drop(&mut self) { if let Some((who, dust)) = self.0.take() { - Pallet::::deposit_event(Event::DustLost(who, dust.peek())); + Pallet::::deposit_event(Event::DustLost { account: who, amount: dust.peek() }); T::DustRemoval::on_unbalanced(dust); } } @@ -939,7 +941,7 @@ impl, I: 'static> Pallet { }); result.map(|(maybe_endowed, maybe_dust, result)| { if let Some(endowed) = maybe_endowed { - Self::deposit_event(Event::Endowed(who.clone(), endowed)); + Self::deposit_event(Event::Endowed { account: who.clone(), free_balance: endowed }); } let dust_cleaner = DustCleaner(maybe_dust.map(|dust| (who.clone(), dust))); (result, dust_cleaner) @@ -1051,12 +1053,12 @@ impl, I: 'static> Pallet { }, )?; - Self::deposit_event(Event::ReserveRepatriated( - slashed.clone(), - beneficiary.clone(), - actual, - status, - )); + Self::deposit_event(Event::ReserveRepatriated { + from: slashed.clone(), + to: beneficiary.clone(), + amount: actual, + destination_status: status, + }); Ok(actual) } } @@ -1109,7 +1111,7 @@ impl, I: 'static> fungible::Mutate for Pallet { Ok(()) })?; TotalIssuance::::mutate(|t| *t += amount); - Self::deposit_event(Event::Deposit(who.clone(), amount)); + Self::deposit_event(Event::Deposit { who: who.clone(), amount }); Ok(()) } @@ -1130,7 +1132,7 @@ impl, I: 'static> fungible::Mutate for Pallet { }, )?; TotalIssuance::::mutate(|t| *t -= actual); - Self::deposit_event(Event::Withdraw(who.clone(), amount)); + Self::deposit_event(Event::Withdraw { who: who.clone(), amount }); Ok(actual) } } @@ -1151,7 +1153,11 @@ impl, I: 'static> fungible::Unbalanced for Pallet DispatchResult { Self::mutate_account(who, |account| { account.free = amount; - Self::deposit_event(Event::BalanceSet(who.clone(), account.free, account.reserved)); + Self::deposit_event(Event::BalanceSet { + who: who.clone(), + free: account.free, + reserved: account.reserved, + }); })?; Ok(()) } @@ -1531,7 +1537,11 @@ where )?; // Emit transfer event. - Self::deposit_event(Event::Transfer(transactor.clone(), dest.clone(), value)); + Self::deposit_event(Event::Transfer { + from: transactor.clone(), + to: dest.clone(), + amount: value, + }); Ok(()) } @@ -1595,10 +1605,10 @@ where }, ) { Ok((imbalance, not_slashed)) => { - Self::deposit_event(Event::Slashed( - who.clone(), - value.saturating_sub(not_slashed), - )); + Self::deposit_event(Event::Slashed { + who: who.clone(), + amount: value.saturating_sub(not_slashed), + }); return (imbalance, not_slashed) }, Err(_) => (), @@ -1625,7 +1635,7 @@ where |account, is_new| -> Result { ensure!(!is_new, Error::::DeadAccount); account.free = account.free.checked_add(&value).ok_or(ArithmeticError::Overflow)?; - Self::deposit_event(Event::Deposit(who.clone(), value)); + Self::deposit_event(Event::Deposit { who: who.clone(), amount: value }); Ok(PositiveImbalance::new(value)) }, ) @@ -1658,7 +1668,7 @@ where None => return Ok(Self::PositiveImbalance::zero()), }; - Self::deposit_event(Event::Deposit(who.clone(), value)); + Self::deposit_event(Event::Deposit { who: who.clone(), amount: value }); Ok(PositiveImbalance::new(value)) }, ) @@ -1696,7 +1706,7 @@ where account.free = new_free_account; - Self::deposit_event(Event::Withdraw(who.clone(), value)); + Self::deposit_event(Event::Withdraw { who: who.clone(), amount: value }); Ok(NegativeImbalance::new(value)) }, ) @@ -1729,7 +1739,11 @@ where SignedImbalance::Negative(NegativeImbalance::new(account.free - value)) }; account.free = value; - Self::deposit_event(Event::BalanceSet(who.clone(), account.free, account.reserved)); + Self::deposit_event(Event::BalanceSet { + who: who.clone(), + free: account.free, + reserved: account.reserved, + }); Ok(imbalance) }, ) @@ -1773,7 +1787,7 @@ where Self::ensure_can_withdraw(&who, value.clone(), WithdrawReasons::RESERVE, account.free) })?; - Self::deposit_event(Event::Reserved(who.clone(), value)); + Self::deposit_event(Event::Reserved { who: who.clone(), amount: value }); Ok(()) } @@ -1805,7 +1819,7 @@ where }, }; - Self::deposit_event(Event::Unreserved(who.clone(), actual.clone())); + Self::deposit_event(Event::Unreserved { who: who.clone(), amount: actual.clone() }); value - actual } @@ -1846,10 +1860,10 @@ where (NegativeImbalance::new(actual), value - actual) }) { Ok((imbalance, not_slashed)) => { - Self::deposit_event(Event::Slashed( - who.clone(), - value.saturating_sub(not_slashed), - )); + Self::deposit_event(Event::Slashed { + who: who.clone(), + amount: value.saturating_sub(not_slashed), + }); return (imbalance, not_slashed) }, Err(_) => (), @@ -1992,7 +2006,7 @@ where // `actual <= to_change` and `to_change <= amount`; qed; reserves[index].amount -= actual; - Self::deposit_event(Event::Slashed(who.clone(), actual)); + Self::deposit_event(Event::Slashed { who: who.clone(), amount: actual }); (imb, value - actual) }, Err(_) => (NegativeImbalance::zero(), value), diff --git a/frame/balances/src/tests.rs b/frame/balances/src/tests.rs index 6a6ebc692c34..1f7f4dd03716 100644 --- a/frame/balances/src/tests.rs +++ b/frame/balances/src/tests.rs @@ -314,7 +314,7 @@ macro_rules! decl_tests { <$ext_builder>::default().monied(true).build().execute_with(|| { assert_eq!(Balances::total_balance(&1), 10); assert_ok!(Balances::deposit_into_existing(&1, 10).map(drop)); - System::assert_last_event(Event::Balances(crate::Event::Deposit(1, 10))); + System::assert_last_event(Event::Balances(crate::Event::Deposit { who: 1, amount: 10 })); assert_eq!(Balances::total_balance(&1), 20); assert_eq!(>::get(), 120); }); @@ -342,7 +342,7 @@ macro_rules! decl_tests { fn balance_works() { <$ext_builder>::default().build().execute_with(|| { let _ = Balances::deposit_creating(&1, 42); - System::assert_has_event(Event::Balances(crate::Event::Deposit(1, 42))); + System::assert_has_event(Event::Balances(crate::Event::Deposit { who: 1, amount: 42 })); assert_eq!(Balances::free_balance(1), 42); assert_eq!(Balances::reserved_balance(1), 0); assert_eq!(Balances::total_balance(&1), 42); @@ -444,7 +444,7 @@ macro_rules! decl_tests { let _ = Balances::withdraw( &2, 11, WithdrawReasons::TRANSFER, ExistenceRequirement::KeepAlive ); - System::assert_last_event(Event::Balances(crate::Event::Withdraw(2, 11))); + System::assert_last_event(Event::Balances(crate::Event::Withdraw { who: 2, amount: 11 })); assert_eq!(Balances::free_balance(2), 100); assert_eq!(>::get(), 100); }); @@ -505,7 +505,7 @@ macro_rules! decl_tests { assert_ok!(Balances::reserve(&1, 110)); assert_ok!(Balances::repatriate_reserved(&1, &2, 41, Status::Free), 0); System::assert_last_event( - Event::Balances(crate::Event::ReserveRepatriated(1, 2, 41, Status::Free)) + Event::Balances(crate::Event::ReserveRepatriated { from: 1, to: 2, amount: 41, destination_status: Status::Free }) ); assert_eq!(Balances::reserved_balance(1), 69); assert_eq!(Balances::free_balance(1), 0); @@ -724,18 +724,18 @@ macro_rules! decl_tests { System::set_block_number(2); assert_ok!(Balances::reserve(&1, 10)); - System::assert_last_event(Event::Balances(crate::Event::Reserved(1, 10))); + System::assert_last_event(Event::Balances(crate::Event::Reserved { who: 1, amount: 10 })); System::set_block_number(3); assert!(Balances::unreserve(&1, 5).is_zero()); - System::assert_last_event(Event::Balances(crate::Event::Unreserved(1, 5))); + System::assert_last_event(Event::Balances(crate::Event::Unreserved { who: 1, amount: 5 })); System::set_block_number(4); assert_eq!(Balances::unreserve(&1, 6), 1); // should only unreserve 5 - System::assert_last_event(Event::Balances(crate::Event::Unreserved(1, 5))); + System::assert_last_event(Event::Balances(crate::Event::Unreserved { who: 1, amount: 5 })); }); } @@ -751,8 +751,8 @@ macro_rules! decl_tests { events(), [ Event::System(system::Event::NewAccount(1)), - Event::Balances(crate::Event::Endowed(1, 100)), - Event::Balances(crate::Event::BalanceSet(1, 100, 0)), + Event::Balances(crate::Event::Endowed { account: 1, free_balance: 100 }), + Event::Balances(crate::Event::BalanceSet { who: 1, free: 100, reserved: 0 }), ] ); @@ -763,8 +763,8 @@ macro_rules! decl_tests { events(), [ Event::System(system::Event::KilledAccount(1)), - Event::Balances(crate::Event::DustLost(1, 99)), - Event::Balances(crate::Event::Slashed(1, 1)), + Event::Balances(crate::Event::DustLost { account: 1, amount: 99 }), + Event::Balances(crate::Event::Slashed { who: 1, amount: 1 }), ] ); }); @@ -782,8 +782,8 @@ macro_rules! decl_tests { events(), [ Event::System(system::Event::NewAccount(1)), - Event::Balances(crate::Event::Endowed(1, 100)), - Event::Balances(crate::Event::BalanceSet(1, 100, 0)), + Event::Balances(crate::Event::Endowed { account: 1, free_balance: 100 }), + Event::Balances(crate::Event::BalanceSet { who: 1, free: 100, reserved: 0 }), ] ); @@ -794,7 +794,7 @@ macro_rules! decl_tests { events(), [ Event::System(system::Event::KilledAccount(1)), - Event::Balances(crate::Event::Slashed(1, 100)), + Event::Balances(crate::Event::Slashed { who: 1, amount: 100 }), ] ); }); @@ -814,7 +814,7 @@ macro_rules! decl_tests { assert_eq!(Balances::slash(&1, 900), (NegativeImbalance::new(900), 0)); // Account is still alive assert!(System::account_exists(&1)); - System::assert_last_event(Event::Balances(crate::Event::Slashed(1, 900))); + System::assert_last_event(Event::Balances(crate::Event::Slashed { who: 1, amount: 900 })); // SCENARIO: Slash will kill account because not enough balance left. assert_ok!(Balances::set_balance(Origin::root(), 1, 1_000, 0)); diff --git a/frame/balances/src/tests_local.rs b/frame/balances/src/tests_local.rs index b2113a916caa..c9de662b9e8f 100644 --- a/frame/balances/src/tests_local.rs +++ b/frame/balances/src/tests_local.rs @@ -164,8 +164,8 @@ fn emit_events_with_no_existential_deposit_suicide_with_dust() { events(), [ Event::System(system::Event::NewAccount(1)), - Event::Balances(crate::Event::Endowed(1, 100)), - Event::Balances(crate::Event::BalanceSet(1, 100, 0)), + Event::Balances(crate::Event::Endowed { account: 1, free_balance: 100 }), + Event::Balances(crate::Event::BalanceSet { who: 1, free: 100, reserved: 0 }), ] ); @@ -173,7 +173,7 @@ fn emit_events_with_no_existential_deposit_suicide_with_dust() { assert_eq!(res, (NegativeImbalance::new(98), 0)); // no events - assert_eq!(events(), [Event::Balances(crate::Event::Slashed(1, 98))]); + assert_eq!(events(), [Event::Balances(crate::Event::Slashed { who: 1, amount: 98 })]); let res = Balances::slash(&1, 1); assert_eq!(res, (NegativeImbalance::new(1), 0)); @@ -182,8 +182,8 @@ fn emit_events_with_no_existential_deposit_suicide_with_dust() { events(), [ Event::System(system::Event::KilledAccount(1)), - Event::Balances(crate::Event::DustLost(1, 1)), - Event::Balances(crate::Event::Slashed(1, 1)), + Event::Balances(crate::Event::DustLost { account: 1, amount: 1 }), + Event::Balances(crate::Event::Slashed { who: 1, amount: 1 }) ] ); }); diff --git a/frame/balances/src/tests_reentrancy.rs b/frame/balances/src/tests_reentrancy.rs index 9a5ebb003af2..43edd16baf3b 100644 --- a/frame/balances/src/tests_reentrancy.rs +++ b/frame/balances/src/tests_reentrancy.rs @@ -169,9 +169,16 @@ fn transfer_dust_removal_tst1_should_work() { // Verify the events assert_eq!(System::events().len(), 12); - System::assert_has_event(Event::Balances(crate::Event::Transfer(2, 3, 450))); - System::assert_has_event(Event::Balances(crate::Event::DustLost(2, 50))); - System::assert_has_event(Event::Balances(crate::Event::Deposit(1, 50))); + System::assert_has_event(Event::Balances(crate::Event::Transfer { + from: 2, + to: 3, + amount: 450, + })); + System::assert_has_event(Event::Balances(crate::Event::DustLost { + account: 2, + amount: 50, + })); + System::assert_has_event(Event::Balances(crate::Event::Deposit { who: 1, amount: 50 })); }); } @@ -197,9 +204,16 @@ fn transfer_dust_removal_tst2_should_work() { // Verify the events assert_eq!(System::events().len(), 10); - System::assert_has_event(Event::Balances(crate::Event::Transfer(2, 1, 450))); - System::assert_has_event(Event::Balances(crate::Event::DustLost(2, 50))); - System::assert_has_event(Event::Balances(crate::Event::Deposit(1, 50))); + System::assert_has_event(Event::Balances(crate::Event::Transfer { + from: 2, + to: 1, + amount: 450, + })); + System::assert_has_event(Event::Balances(crate::Event::DustLost { + account: 2, + amount: 50, + })); + System::assert_has_event(Event::Balances(crate::Event::Deposit { who: 1, amount: 50 })); }); } @@ -234,13 +248,18 @@ fn repatriating_reserved_balance_dust_removal_should_work() { // Verify the events assert_eq!(System::events().len(), 11); - System::assert_has_event(Event::Balances(crate::Event::ReserveRepatriated( - 2, - 1, - 450, - Status::Free, - ))); - System::assert_has_event(Event::Balances(crate::Event::DustLost(2, 50))); - System::assert_last_event(Event::Balances(crate::Event::Deposit(1, 50))); + System::assert_has_event(Event::Balances(crate::Event::ReserveRepatriated { + from: 2, + to: 1, + amount: 450, + destination_status: Status::Free, + })); + + System::assert_has_event(Event::Balances(crate::Event::DustLost { + account: 2, + amount: 50, + })); + + System::assert_last_event(Event::Balances(crate::Event::Deposit { who: 1, amount: 50 })); }); } diff --git a/frame/bounties/src/benchmarking.rs b/frame/bounties/src/benchmarking.rs index 33af02fbb9ea..341d019c49d4 100644 --- a/frame/bounties/src/benchmarking.rs +++ b/frame/bounties/src/benchmarking.rs @@ -172,7 +172,7 @@ benchmarks! { let bounty_id = BountyCount::::get() - 1; }: close_bounty(RawOrigin::Root, bounty_id) verify { - assert_last_event::(Event::BountyCanceled(bounty_id).into()) + assert_last_event::(Event::BountyCanceled { index: bounty_id }.into()) } extend_bounty_expiry { @@ -184,7 +184,7 @@ benchmarks! { let curator = T::Lookup::lookup(curator_lookup).map_err(<&str>::from)?; }: _(RawOrigin::Signed(curator), bounty_id, Vec::new()) verify { - assert_last_event::(Event::BountyExtended(bounty_id).into()) + assert_last_event::(Event::BountyExtended { index: bounty_id }.into()) } spend_funds { @@ -207,7 +207,7 @@ benchmarks! { verify { ensure!(budget_remaining < BalanceOf::::max_value(), "Budget not used"); ensure!(missed_any == false, "Missed some"); - assert_last_event::(Event::BountyBecameActive(b - 1).into()) + assert_last_event::(Event::BountyBecameActive { index: b - 1 }.into()) } impl_benchmark_test_suite!(Bounties, crate::tests::new_test_ext(), crate::tests::Test) diff --git a/frame/bounties/src/lib.rs b/frame/bounties/src/lib.rs index 69380502bad3..5c96fdcc6b98 100644 --- a/frame/bounties/src/lib.rs +++ b/frame/bounties/src/lib.rs @@ -228,20 +228,20 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { - /// New bounty proposal. \[index\] - BountyProposed(BountyIndex), - /// A bounty proposal was rejected; funds were slashed. \[index, bond\] - BountyRejected(BountyIndex, BalanceOf), - /// A bounty proposal is funded and became active. \[index\] - BountyBecameActive(BountyIndex), - /// A bounty is awarded to a beneficiary. \[index, beneficiary\] - BountyAwarded(BountyIndex, T::AccountId), - /// A bounty is claimed by beneficiary. \[index, payout, beneficiary\] - BountyClaimed(BountyIndex, BalanceOf, T::AccountId), - /// A bounty is cancelled. \[index\] - BountyCanceled(BountyIndex), - /// A bounty expiry is extended. \[index\] - BountyExtended(BountyIndex), + /// New bounty proposal. + BountyProposed { index: BountyIndex }, + /// A bounty proposal was rejected; funds were slashed. + BountyRejected { index: BountyIndex, bond: BalanceOf }, + /// A bounty proposal is funded and became active. + BountyBecameActive { index: BountyIndex }, + /// A bounty is awarded to a beneficiary. + BountyAwarded { index: BountyIndex, beneficiary: T::AccountId }, + /// A bounty is claimed by beneficiary. + BountyClaimed { index: BountyIndex, payout: BalanceOf, beneficiary: T::AccountId }, + /// A bounty is cancelled. + BountyCanceled { index: BountyIndex }, + /// A bounty expiry is extended. + BountyExtended { index: BountyIndex }, } /// Number of bounty proposals that have been made. @@ -526,7 +526,7 @@ pub mod pallet { Ok(()) })?; - Self::deposit_event(Event::::BountyAwarded(bounty_id, beneficiary)); + Self::deposit_event(Event::::BountyAwarded { index: bounty_id, beneficiary }); Ok(()) } @@ -571,7 +571,11 @@ pub mod pallet { BountyDescriptions::::remove(bounty_id); - Self::deposit_event(Event::::BountyClaimed(bounty_id, payout, beneficiary)); + Self::deposit_event(Event::::BountyClaimed { + index: bounty_id, + payout, + beneficiary, + }); Ok(()) } else { Err(Error::::UnexpectedStatus.into()) @@ -612,7 +616,10 @@ pub mod pallet { T::OnSlash::on_unbalanced(imbalance); *maybe_bounty = None; - Self::deposit_event(Event::::BountyRejected(bounty_id, value)); + Self::deposit_event(Event::::BountyRejected { + index: bounty_id, + bond: value, + }); // Return early, nothing else to do. return Ok( Some(::WeightInfo::close_bounty_proposed()).into() @@ -656,7 +663,7 @@ pub mod pallet { debug_assert!(res.is_ok()); *maybe_bounty = None; - Self::deposit_event(Event::::BountyCanceled(bounty_id)); + Self::deposit_event(Event::::BountyCanceled { index: bounty_id }); Ok(Some(::WeightInfo::close_bounty_active()).into()) }, ) @@ -696,7 +703,7 @@ pub mod pallet { Ok(()) })?; - Self::deposit_event(Event::::BountyExtended(bounty_id)); + Self::deposit_event(Event::::BountyExtended { index: bounty_id }); Ok(()) } } @@ -753,7 +760,7 @@ impl Pallet { Bounties::::insert(index, &bounty); BountyDescriptions::::insert(index, description); - Self::deposit_event(Event::::BountyProposed(index)); + Self::deposit_event(Event::::BountyProposed { index }); Ok(()) } @@ -787,7 +794,7 @@ impl pallet_treasury::SpendFunds for Pallet { bounty.value, )); - Self::deposit_event(Event::::BountyBecameActive(index)); + Self::deposit_event(Event::::BountyBecameActive { index }); false } else { *missed_any = true; diff --git a/frame/bounties/src/tests.rs b/frame/bounties/src/tests.rs index 96c09581fdd1..344bb6495c3b 100644 --- a/frame/bounties/src/tests.rs +++ b/frame/bounties/src/tests.rs @@ -398,7 +398,7 @@ fn propose_bounty_works() { assert_ok!(Bounties::propose_bounty(Origin::signed(0), 10, b"1234567890".to_vec())); - assert_eq!(last_event(), BountiesEvent::BountyProposed(0)); + assert_eq!(last_event(), BountiesEvent::BountyProposed { index: 0 }); let deposit: u64 = 85 + 5; assert_eq!(Balances::reserved_balance(0), deposit); @@ -460,7 +460,7 @@ fn close_bounty_works() { let deposit: u64 = 80 + 5; - assert_eq!(last_event(), BountiesEvent::BountyRejected(0, deposit)); + assert_eq!(last_event(), BountiesEvent::BountyRejected { index: 0, bond: deposit }); assert_eq!(Balances::reserved_balance(0), 0); assert_eq!(Balances::free_balance(0), 100 - deposit); @@ -692,7 +692,10 @@ fn award_and_claim_bounty_works() { assert_ok!(Bounties::claim_bounty(Origin::signed(1), 0)); - assert_eq!(last_event(), BountiesEvent::BountyClaimed(0, 56, 3)); + assert_eq!( + last_event(), + BountiesEvent::BountyClaimed { index: 0, payout: 56, beneficiary: 3 } + ); assert_eq!(Balances::free_balance(4), 14); // initial 10 + fee 4 @@ -731,7 +734,10 @@ fn claim_handles_high_fee() { assert_ok!(Bounties::claim_bounty(Origin::signed(1), 0)); - assert_eq!(last_event(), BountiesEvent::BountyClaimed(0, 0, 3)); + assert_eq!( + last_event(), + BountiesEvent::BountyClaimed { index: 0, payout: 0, beneficiary: 3 } + ); assert_eq!(Balances::free_balance(4), 70); // 30 + 50 - 10 assert_eq!(Balances::free_balance(3), 0); @@ -808,7 +814,7 @@ fn award_and_cancel() { assert_ok!(Bounties::unassign_curator(Origin::root(), 0)); assert_ok!(Bounties::close_bounty(Origin::root(), 0)); - assert_eq!(last_event(), BountiesEvent::BountyCanceled(0)); + assert_eq!(last_event(), BountiesEvent::BountyCanceled { index: 0 }); assert_eq!(Balances::free_balance(Bounties::bounty_account_id(0)), 0); diff --git a/frame/collective/src/benchmarking.rs b/frame/collective/src/benchmarking.rs index c26a2b43f5b7..5ca57cf72e8f 100644 --- a/frame/collective/src/benchmarking.rs +++ b/frame/collective/src/benchmarking.rs @@ -128,7 +128,7 @@ benchmarks_instance_pallet! { let proposal_hash = T::Hashing::hash_of(&proposal); // Note that execution fails due to mis-matched origin assert_last_event::( - Event::MemberExecuted(proposal_hash, Err(DispatchError::BadOrigin)).into() + Event::MemberExecuted { proposal_hash, result: Err(DispatchError::BadOrigin) }.into() ); } @@ -159,7 +159,7 @@ benchmarks_instance_pallet! { let proposal_hash = T::Hashing::hash_of(&proposal); // Note that execution fails due to mis-matched origin assert_last_event::( - Event::Executed(proposal_hash, Err(DispatchError::BadOrigin)).into() + Event::Executed { proposal_hash, result: Err(DispatchError::BadOrigin) }.into() ); } @@ -203,7 +203,7 @@ benchmarks_instance_pallet! { // New proposal is recorded assert_eq!(Collective::::proposals().len(), p as usize); let proposal_hash = T::Hashing::hash_of(&proposal); - assert_last_event::(Event::Proposed(caller, p - 1, proposal_hash, threshold).into()); + assert_last_event::(Event::Proposed { account: caller, proposal_index: p - 1, proposal_hash, threshold }.into()); } vote { @@ -359,7 +359,7 @@ benchmarks_instance_pallet! { verify { // The last proposal is removed. assert_eq!(Collective::::proposals().len(), (p - 1) as usize); - assert_last_event::(Event::Disapproved(last_hash).into()); + assert_last_event::(Event::Disapproved { proposal_hash: last_hash }.into()); } close_early_approved { @@ -440,7 +440,7 @@ benchmarks_instance_pallet! { verify { // The last proposal is removed. assert_eq!(Collective::::proposals().len(), (p - 1) as usize); - assert_last_event::(Event::Executed(last_hash, Err(DispatchError::BadOrigin)).into()); + assert_last_event::(Event::Executed { proposal_hash: last_hash, result: Err(DispatchError::BadOrigin) }.into()); } close_disapproved { @@ -514,7 +514,7 @@ benchmarks_instance_pallet! { }: close(SystemOrigin::Signed(caller), last_hash, index, Weight::max_value(), bytes_in_storage) verify { assert_eq!(Collective::::proposals().len(), (p - 1) as usize); - assert_last_event::(Event::Disapproved(last_hash).into()); + assert_last_event::(Event::Disapproved { proposal_hash: last_hash }.into()); } close_approved { @@ -586,7 +586,7 @@ benchmarks_instance_pallet! { }: close(SystemOrigin::Signed(caller), last_hash, p - 1, Weight::max_value(), bytes_in_storage) verify { assert_eq!(Collective::::proposals().len(), (p - 1) as usize); - assert_last_event::(Event::Executed(last_hash, Err(DispatchError::BadOrigin)).into()); + assert_last_event::(Event::Executed { proposal_hash: last_hash, result: Err(DispatchError::BadOrigin) }.into()); } disapprove_proposal { @@ -634,7 +634,7 @@ benchmarks_instance_pallet! { }: _(SystemOrigin::Root, last_hash) verify { assert_eq!(Collective::::proposals().len(), (p - 1) as usize); - assert_last_event::(Event::Disapproved(last_hash).into()); + assert_last_event::(Event::Disapproved { proposal_hash: last_hash }.into()); } impl_benchmark_test_suite!(Collective, crate::tests::new_test_ext(), crate::tests::Test); diff --git a/frame/collective/src/lib.rs b/frame/collective/src/lib.rs index 2797d01ffcdb..26b18b623257 100644 --- a/frame/collective/src/lib.rs +++ b/frame/collective/src/lib.rs @@ -279,27 +279,31 @@ pub mod pallet { pub enum Event, I: 'static = ()> { /// A motion (given hash) has been proposed (by given account) with a threshold (given /// `MemberCount`). - /// \[account, proposal_index, proposal_hash, threshold\] - Proposed(T::AccountId, ProposalIndex, T::Hash, MemberCount), + Proposed { + account: T::AccountId, + proposal_index: ProposalIndex, + proposal_hash: T::Hash, + threshold: MemberCount, + }, /// A motion (given hash) has been voted on by given account, leaving /// a tally (yes votes and no votes given respectively as `MemberCount`). - /// \[account, proposal_hash, voted, yes, no\] - Voted(T::AccountId, T::Hash, bool, MemberCount, MemberCount), + Voted { + account: T::AccountId, + proposal_hash: T::Hash, + voted: bool, + yes: MemberCount, + no: MemberCount, + }, /// A motion was approved by the required threshold. - /// \[proposal_hash\] - Approved(T::Hash), + Approved { proposal_hash: T::Hash }, /// A motion was not approved by the required threshold. - /// \[proposal_hash\] - Disapproved(T::Hash), + Disapproved { proposal_hash: T::Hash }, /// A motion was executed; result will be `Ok` if it returned without error. - /// \[proposal_hash, result\] - Executed(T::Hash, DispatchResult), + Executed { proposal_hash: T::Hash, result: DispatchResult }, /// A single member did some action; result will be `Ok` if it returned without error. - /// \[proposal_hash, result\] - MemberExecuted(T::Hash, DispatchResult), + MemberExecuted { proposal_hash: T::Hash, result: DispatchResult }, /// A proposal was closed because its threshold was reached or after its duration was up. - /// \[proposal_hash, yes, no\] - Closed(T::Hash, MemberCount, MemberCount), + Closed { proposal_hash: T::Hash, yes: MemberCount, no: MemberCount }, } /// Old name generated by `decl_event`. @@ -442,10 +446,10 @@ pub mod pallet { let proposal_hash = T::Hashing::hash_of(&proposal); let result = proposal.dispatch(RawOrigin::Member(who).into()); - Self::deposit_event(Event::MemberExecuted( + Self::deposit_event(Event::MemberExecuted { proposal_hash, - result.map(|_| ()).map_err(|e| e.error), - )); + result: result.map(|_| ()).map_err(|e| e.error), + }); Ok(get_result_weight(result) .map(|w| { @@ -521,10 +525,10 @@ pub mod pallet { if threshold < 2 { let seats = Self::members().len() as MemberCount; let result = proposal.dispatch(RawOrigin::Members(1, seats).into()); - Self::deposit_event(Event::Executed( + Self::deposit_event(Event::Executed { proposal_hash, - result.map(|_| ()).map_err(|e| e.error), - )); + result: result.map(|_| ()).map_err(|e| e.error), + }); Ok(get_result_weight(result) .map(|w| { @@ -552,7 +556,12 @@ pub mod pallet { }; >::insert(proposal_hash, votes); - Self::deposit_event(Event::Proposed(who, index, proposal_hash, threshold)); + Self::deposit_event(Event::Proposed { + account: who, + proposal_index: index, + proposal_hash, + threshold, + }); Ok(Some(T::WeightInfo::propose_proposed( proposal_len as u32, // B @@ -620,7 +629,13 @@ pub mod pallet { let yes_votes = voting.ayes.len() as MemberCount; let no_votes = voting.nays.len() as MemberCount; - Self::deposit_event(Event::Voted(who, proposal, approve, yes_votes, no_votes)); + Self::deposit_event(Event::Voted { + account: who, + proposal_hash: proposal, + voted: approve, + yes: yes_votes, + no: no_votes, + }); Voting::::insert(&proposal, voting); @@ -701,7 +716,7 @@ pub mod pallet { length_bound, proposal_weight_bound, )?; - Self::deposit_event(Event::Closed(proposal_hash, yes_votes, no_votes)); + Self::deposit_event(Event::Closed { proposal_hash, yes: yes_votes, no: no_votes }); let (proposal_weight, proposal_count) = Self::do_approve_proposal(seats, yes_votes, proposal_hash, proposal); return Ok(( @@ -713,7 +728,7 @@ pub mod pallet { ) .into()) } else if disapproved { - Self::deposit_event(Event::Closed(proposal_hash, yes_votes, no_votes)); + Self::deposit_event(Event::Closed { proposal_hash, yes: yes_votes, no: no_votes }); let proposal_count = Self::do_disapprove_proposal(proposal_hash); return Ok(( Some(T::WeightInfo::close_early_disapproved(seats, proposal_count)), @@ -746,7 +761,7 @@ pub mod pallet { length_bound, proposal_weight_bound, )?; - Self::deposit_event(Event::Closed(proposal_hash, yes_votes, no_votes)); + Self::deposit_event(Event::Closed { proposal_hash, yes: yes_votes, no: no_votes }); let (proposal_weight, proposal_count) = Self::do_approve_proposal(seats, yes_votes, proposal_hash, proposal); Ok(( @@ -758,7 +773,7 @@ pub mod pallet { ) .into()) } else { - Self::deposit_event(Event::Closed(proposal_hash, yes_votes, no_votes)); + Self::deposit_event(Event::Closed { proposal_hash, yes: yes_votes, no: no_votes }); let proposal_count = Self::do_disapprove_proposal(proposal_hash); Ok((Some(T::WeightInfo::close_disapproved(seats, proposal_count)), Pays::No).into()) } @@ -848,15 +863,15 @@ impl, I: 'static> Pallet { proposal_hash: T::Hash, proposal: >::Proposal, ) -> (Weight, u32) { - Self::deposit_event(Event::Approved(proposal_hash)); + Self::deposit_event(Event::Approved { proposal_hash }); let dispatch_weight = proposal.get_dispatch_info().weight; let origin = RawOrigin::Members(yes_votes, seats).into(); let result = proposal.dispatch(origin); - Self::deposit_event(Event::Executed( + Self::deposit_event(Event::Executed { proposal_hash, - result.map(|_| ()).map_err(|e| e.error), - )); + result: result.map(|_| ()).map_err(|e| e.error), + }); // default to the dispatch info weight for safety let proposal_weight = get_result_weight(result).unwrap_or(dispatch_weight); // P1 @@ -866,7 +881,7 @@ impl, I: 'static> Pallet { fn do_disapprove_proposal(proposal_hash: T::Hash) -> u32 { // disapproved - Self::deposit_event(Event::Disapproved(proposal_hash)); + Self::deposit_event(Event::Disapproved { proposal_hash }); Self::remove_proposal(proposal_hash) } diff --git a/frame/collective/src/tests.rs b/frame/collective/src/tests.rs index b8feb64867cf..7e52b10a9b1d 100644 --- a/frame/collective/src/tests.rs +++ b/frame/collective/src/tests.rs @@ -216,11 +216,32 @@ fn close_works() { assert_eq!( System::events(), vec![ - record(Event::Collective(CollectiveEvent::Proposed(1, 0, hash, 3))), - record(Event::Collective(CollectiveEvent::Voted(1, hash, true, 1, 0))), - record(Event::Collective(CollectiveEvent::Voted(2, hash, true, 2, 0))), - record(Event::Collective(CollectiveEvent::Closed(hash, 2, 1))), - record(Event::Collective(CollectiveEvent::Disapproved(hash))) + record(Event::Collective(CollectiveEvent::Proposed { + account: 1, + proposal_index: 0, + proposal_hash: hash, + threshold: 3 + })), + record(Event::Collective(CollectiveEvent::Voted { + account: 1, + proposal_hash: hash, + voted: true, + yes: 1, + no: 0 + })), + record(Event::Collective(CollectiveEvent::Voted { + account: 2, + proposal_hash: hash, + voted: true, + yes: 2, + no: 0 + })), + record(Event::Collective(CollectiveEvent::Closed { + proposal_hash: hash, + yes: 2, + no: 1 + })), + record(Event::Collective(CollectiveEvent::Disapproved { proposal_hash: hash })) ] ); }); @@ -315,11 +336,32 @@ fn close_with_prime_works() { assert_eq!( System::events(), vec![ - record(Event::Collective(CollectiveEvent::Proposed(1, 0, hash, 3))), - record(Event::Collective(CollectiveEvent::Voted(1, hash, true, 1, 0))), - record(Event::Collective(CollectiveEvent::Voted(2, hash, true, 2, 0))), - record(Event::Collective(CollectiveEvent::Closed(hash, 2, 1))), - record(Event::Collective(CollectiveEvent::Disapproved(hash))) + record(Event::Collective(CollectiveEvent::Proposed { + account: 1, + proposal_index: 0, + proposal_hash: hash, + threshold: 3 + })), + record(Event::Collective(CollectiveEvent::Voted { + account: 1, + proposal_hash: hash, + voted: true, + yes: 1, + no: 0 + })), + record(Event::Collective(CollectiveEvent::Voted { + account: 2, + proposal_hash: hash, + voted: true, + yes: 2, + no: 0 + })), + record(Event::Collective(CollectiveEvent::Closed { + proposal_hash: hash, + yes: 2, + no: 1 + })), + record(Event::Collective(CollectiveEvent::Disapproved { proposal_hash: hash })) ] ); }); @@ -354,15 +396,36 @@ fn close_with_voting_prime_works() { assert_eq!( System::events(), vec![ - record(Event::Collective(CollectiveEvent::Proposed(1, 0, hash, 3))), - record(Event::Collective(CollectiveEvent::Voted(1, hash, true, 1, 0))), - record(Event::Collective(CollectiveEvent::Voted(2, hash, true, 2, 0))), - record(Event::Collective(CollectiveEvent::Closed(hash, 3, 0))), - record(Event::Collective(CollectiveEvent::Approved(hash))), - record(Event::Collective(CollectiveEvent::Executed( - hash, - Err(DispatchError::BadOrigin) - ))) + record(Event::Collective(CollectiveEvent::Proposed { + account: 1, + proposal_index: 0, + proposal_hash: hash, + threshold: 3 + })), + record(Event::Collective(CollectiveEvent::Voted { + account: 1, + proposal_hash: hash, + voted: true, + yes: 1, + no: 0 + })), + record(Event::Collective(CollectiveEvent::Voted { + account: 2, + proposal_hash: hash, + voted: true, + yes: 2, + no: 0 + })), + record(Event::Collective(CollectiveEvent::Closed { + proposal_hash: hash, + yes: 3, + no: 0 + })), + record(Event::Collective(CollectiveEvent::Approved { proposal_hash: hash })), + record(Event::Collective(CollectiveEvent::Executed { + proposal_hash: hash, + result: Err(DispatchError::BadOrigin) + })) ] ); }); @@ -404,16 +467,45 @@ fn close_with_no_prime_but_majority_works() { assert_eq!( System::events(), vec![ - record(Event::CollectiveMajority(CollectiveEvent::Proposed(1, 0, hash, 5))), - record(Event::CollectiveMajority(CollectiveEvent::Voted(1, hash, true, 1, 0))), - record(Event::CollectiveMajority(CollectiveEvent::Voted(2, hash, true, 2, 0))), - record(Event::CollectiveMajority(CollectiveEvent::Voted(3, hash, true, 3, 0))), - record(Event::CollectiveMajority(CollectiveEvent::Closed(hash, 5, 0))), - record(Event::CollectiveMajority(CollectiveEvent::Approved(hash))), - record(Event::CollectiveMajority(CollectiveEvent::Executed( - hash, - Err(DispatchError::BadOrigin) - ))) + record(Event::CollectiveMajority(CollectiveEvent::Proposed { + account: 1, + proposal_index: 0, + proposal_hash: hash, + threshold: 5 + })), + record(Event::CollectiveMajority(CollectiveEvent::Voted { + account: 1, + proposal_hash: hash, + voted: true, + yes: 1, + no: 0 + })), + record(Event::CollectiveMajority(CollectiveEvent::Voted { + account: 2, + proposal_hash: hash, + voted: true, + yes: 2, + no: 0 + })), + record(Event::CollectiveMajority(CollectiveEvent::Voted { + account: 3, + proposal_hash: hash, + voted: true, + yes: 3, + no: 0 + })), + record(Event::CollectiveMajority(CollectiveEvent::Closed { + proposal_hash: hash, + yes: 5, + no: 0 + })), + record(Event::CollectiveMajority(CollectiveEvent::Approved { + proposal_hash: hash + })), + record(Event::CollectiveMajority(CollectiveEvent::Executed { + proposal_hash: hash, + result: Err(DispatchError::BadOrigin) + })) ] ); }); @@ -537,7 +629,12 @@ fn propose_works() { assert_eq!( System::events(), - vec![record(Event::Collective(CollectiveEvent::Proposed(1, 0, hash, 3)))] + vec![record(Event::Collective(CollectiveEvent::Proposed { + account: 1, + proposal_index: 0, + proposal_hash: hash, + threshold: 3 + }))] ); }); } @@ -696,9 +793,26 @@ fn motions_vote_after_works() { assert_eq!( System::events(), vec![ - record(Event::Collective(CollectiveEvent::Proposed(1, 0, hash, 2))), - record(Event::Collective(CollectiveEvent::Voted(1, hash, true, 1, 0))), - record(Event::Collective(CollectiveEvent::Voted(1, hash, false, 0, 1))), + record(Event::Collective(CollectiveEvent::Proposed { + account: 1, + proposal_index: 0, + proposal_hash: hash, + threshold: 2 + })), + record(Event::Collective(CollectiveEvent::Voted { + account: 1, + proposal_hash: hash, + voted: true, + yes: 1, + no: 0 + })), + record(Event::Collective(CollectiveEvent::Voted { + account: 1, + proposal_hash: hash, + voted: false, + yes: 0, + no: 1 + })), ] ); }); @@ -812,15 +926,36 @@ fn motions_approval_with_enough_votes_and_lower_voting_threshold_works() { assert_eq!( System::events(), vec![ - record(Event::Collective(CollectiveEvent::Proposed(1, 0, hash, 2))), - record(Event::Collective(CollectiveEvent::Voted(1, hash, true, 1, 0))), - record(Event::Collective(CollectiveEvent::Voted(2, hash, true, 2, 0))), - record(Event::Collective(CollectiveEvent::Closed(hash, 2, 0))), - record(Event::Collective(CollectiveEvent::Approved(hash))), - record(Event::Collective(CollectiveEvent::Executed( - hash, - Err(DispatchError::BadOrigin) - ))), + record(Event::Collective(CollectiveEvent::Proposed { + account: 1, + proposal_index: 0, + proposal_hash: hash, + threshold: 2 + })), + record(Event::Collective(CollectiveEvent::Voted { + account: 1, + proposal_hash: hash, + voted: true, + yes: 1, + no: 0 + })), + record(Event::Collective(CollectiveEvent::Voted { + account: 2, + proposal_hash: hash, + voted: true, + yes: 2, + no: 0 + })), + record(Event::Collective(CollectiveEvent::Closed { + proposal_hash: hash, + yes: 2, + no: 0 + })), + record(Event::Collective(CollectiveEvent::Approved { proposal_hash: hash })), + record(Event::Collective(CollectiveEvent::Executed { + proposal_hash: hash, + result: Err(DispatchError::BadOrigin) + })), ] ); @@ -840,14 +975,44 @@ fn motions_approval_with_enough_votes_and_lower_voting_threshold_works() { assert_eq!( System::events(), vec![ - record(Event::Collective(CollectiveEvent::Proposed(1, 1, hash, 2))), - record(Event::Collective(CollectiveEvent::Voted(1, hash, true, 1, 0))), - record(Event::Collective(CollectiveEvent::Voted(2, hash, true, 2, 0))), - record(Event::Collective(CollectiveEvent::Voted(3, hash, true, 3, 0))), - record(Event::Collective(CollectiveEvent::Closed(hash, 3, 0))), - record(Event::Collective(CollectiveEvent::Approved(hash))), + record(Event::Collective(CollectiveEvent::Proposed { + account: 1, + proposal_index: 1, + proposal_hash: hash, + threshold: 2 + })), + record(Event::Collective(CollectiveEvent::Voted { + account: 1, + proposal_hash: hash, + voted: true, + yes: 1, + no: 0 + })), + record(Event::Collective(CollectiveEvent::Voted { + account: 2, + proposal_hash: hash, + voted: true, + yes: 2, + no: 0 + })), + record(Event::Collective(CollectiveEvent::Voted { + account: 3, + proposal_hash: hash, + voted: true, + yes: 3, + no: 0 + })), + record(Event::Collective(CollectiveEvent::Closed { + proposal_hash: hash, + yes: 3, + no: 0 + })), + record(Event::Collective(CollectiveEvent::Approved { proposal_hash: hash })), record(Event::Democracy(mock_democracy::pallet::Event::::ExternalProposed)), - record(Event::Collective(CollectiveEvent::Executed(hash, Ok(())))), + record(Event::Collective(CollectiveEvent::Executed { + proposal_hash: hash, + result: Ok(()) + })), ] ); }); @@ -873,11 +1038,32 @@ fn motions_disapproval_works() { assert_eq!( System::events(), vec![ - record(Event::Collective(CollectiveEvent::Proposed(1, 0, hash, 3))), - record(Event::Collective(CollectiveEvent::Voted(1, hash, true, 1, 0))), - record(Event::Collective(CollectiveEvent::Voted(2, hash, false, 1, 1))), - record(Event::Collective(CollectiveEvent::Closed(hash, 1, 1))), - record(Event::Collective(CollectiveEvent::Disapproved(hash))), + record(Event::Collective(CollectiveEvent::Proposed { + account: 1, + proposal_index: 0, + proposal_hash: hash, + threshold: 3 + })), + record(Event::Collective(CollectiveEvent::Voted { + account: 1, + proposal_hash: hash, + voted: true, + yes: 1, + no: 0 + })), + record(Event::Collective(CollectiveEvent::Voted { + account: 2, + proposal_hash: hash, + voted: false, + yes: 1, + no: 1 + })), + record(Event::Collective(CollectiveEvent::Closed { + proposal_hash: hash, + yes: 1, + no: 1 + })), + record(Event::Collective(CollectiveEvent::Disapproved { proposal_hash: hash })), ] ); }); @@ -903,15 +1089,36 @@ fn motions_approval_works() { assert_eq!( System::events(), vec![ - record(Event::Collective(CollectiveEvent::Proposed(1, 0, hash, 2))), - record(Event::Collective(CollectiveEvent::Voted(1, hash, true, 1, 0))), - record(Event::Collective(CollectiveEvent::Voted(2, hash, true, 2, 0))), - record(Event::Collective(CollectiveEvent::Closed(hash, 2, 0))), - record(Event::Collective(CollectiveEvent::Approved(hash))), - record(Event::Collective(CollectiveEvent::Executed( - hash, - Err(DispatchError::BadOrigin) - ))), + record(Event::Collective(CollectiveEvent::Proposed { + account: 1, + proposal_index: 0, + proposal_hash: hash, + threshold: 2 + })), + record(Event::Collective(CollectiveEvent::Voted { + account: 1, + proposal_hash: hash, + voted: true, + yes: 1, + no: 0 + })), + record(Event::Collective(CollectiveEvent::Voted { + account: 2, + proposal_hash: hash, + voted: true, + yes: 2, + no: 0 + })), + record(Event::Collective(CollectiveEvent::Closed { + proposal_hash: hash, + yes: 2, + no: 0 + })), + record(Event::Collective(CollectiveEvent::Approved { proposal_hash: hash })), + record(Event::Collective(CollectiveEvent::Executed { + proposal_hash: hash, + result: Err(DispatchError::BadOrigin) + })), ] ); }); @@ -932,7 +1139,12 @@ fn motion_with_no_votes_closes_with_disapproval() { )); assert_eq!( System::events()[0], - record(Event::Collective(CollectiveEvent::Proposed(1, 0, hash, 3))) + record(Event::Collective(CollectiveEvent::Proposed { + account: 1, + proposal_index: 0, + proposal_hash: hash, + threshold: 3 + })) ); // Closing the motion too early is not possible because it has neither @@ -951,11 +1163,15 @@ fn motion_with_no_votes_closes_with_disapproval() { // Events show that the close ended in a disapproval. assert_eq!( System::events()[1], - record(Event::Collective(CollectiveEvent::Closed(hash, 0, 3))) + record(Event::Collective(CollectiveEvent::Closed { + proposal_hash: hash, + yes: 0, + no: 3 + })) ); assert_eq!( System::events()[2], - record(Event::Collective(CollectiveEvent::Disapproved(hash))) + record(Event::Collective(CollectiveEvent::Disapproved { proposal_hash: hash })) ); }) } @@ -1015,10 +1231,27 @@ fn disapprove_proposal_works() { assert_eq!( System::events(), vec![ - record(Event::Collective(CollectiveEvent::Proposed(1, 0, hash, 2))), - record(Event::Collective(CollectiveEvent::Voted(1, hash, true, 1, 0))), - record(Event::Collective(CollectiveEvent::Voted(2, hash, true, 2, 0))), - record(Event::Collective(CollectiveEvent::Disapproved(hash))), + record(Event::Collective(CollectiveEvent::Proposed { + account: 1, + proposal_index: 0, + proposal_hash: hash, + threshold: 2 + })), + record(Event::Collective(CollectiveEvent::Voted { + account: 1, + proposal_hash: hash, + voted: true, + yes: 1, + no: 0 + })), + record(Event::Collective(CollectiveEvent::Voted { + account: 2, + proposal_hash: hash, + voted: true, + yes: 2, + no: 0 + })), + record(Event::Collective(CollectiveEvent::Disapproved { proposal_hash: hash })), ] ); }) diff --git a/frame/contracts/src/tests.rs b/frame/contracts/src/tests.rs index bd5dbae5b34a..2214ce8f40b1 100644 --- a/frame/contracts/src/tests.rs +++ b/frame/contracts/src/tests.rs @@ -447,7 +447,10 @@ fn instantiate_and_call_and_deposit_event() { vec![ EventRecord { phase: Phase::Initialization, - event: Event::Balances(pallet_balances::Event::Deposit(ALICE, 1_000_000)), + event: Event::Balances(pallet_balances::Event::Deposit { + who: ALICE, + amount: 1_000_000 + }), topics: vec![], }, EventRecord { @@ -457,7 +460,10 @@ fn instantiate_and_call_and_deposit_event() { }, EventRecord { phase: Phase::Initialization, - event: Event::Balances(pallet_balances::Event::Endowed(ALICE, 1_000_000)), + event: Event::Balances(pallet_balances::Event::Endowed { + account: ALICE, + free_balance: 1_000_000 + }), topics: vec![], }, EventRecord { @@ -467,19 +473,19 @@ fn instantiate_and_call_and_deposit_event() { }, EventRecord { phase: Phase::Initialization, - event: Event::Balances(pallet_balances::Event::Endowed( - addr.clone(), - subsistence * 100 - )), + event: Event::Balances(pallet_balances::Event::Endowed { + account: addr.clone(), + free_balance: subsistence * 100 + }), topics: vec![], }, EventRecord { phase: Phase::Initialization, - event: Event::Balances(pallet_balances::Event::Transfer( - ALICE, - addr.clone(), - subsistence * 100 - )), + event: Event::Balances(pallet_balances::Event::Transfer { + from: ALICE, + to: addr.clone(), + amount: subsistence * 100 + }), topics: vec![], }, EventRecord { @@ -766,11 +772,11 @@ fn self_destruct_works() { }, EventRecord { phase: Phase::Initialization, - event: Event::Balances(pallet_balances::Event::Transfer( - addr.clone(), - DJANGO, - 100_000, - )), + event: Event::Balances(pallet_balances::Event::Transfer { + from: addr.clone(), + to: DJANGO, + amount: 100_000, + }), topics: vec![], }, EventRecord { diff --git a/frame/democracy/src/benchmarking.rs b/frame/democracy/src/benchmarking.rs index 34bcb0da301e..136c2d2a7c9e 100644 --- a/frame/democracy/src/benchmarking.rs +++ b/frame/democracy/src/benchmarking.rs @@ -774,7 +774,7 @@ benchmarks! { }: enact_proposal(RawOrigin::Root, proposal_hash, 0) verify { // Fails due to mismatched origin - assert_last_event::(Event::::Executed(0, Err(BadOrigin.into())).into()); + assert_last_event::(Event::::Executed { ref_index: 0, result: Err(BadOrigin.into()) }.into()); } #[extra] diff --git a/frame/democracy/src/lib.rs b/frame/democracy/src/lib.rs index 893e4676bef7..529bcebc8e37 100644 --- a/frame/democracy/src/lib.rs +++ b/frame/democracy/src/lib.rs @@ -507,45 +507,45 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { - /// A motion has been proposed by a public account. \[proposal_index, deposit\] - Proposed(PropIndex, BalanceOf), - /// A public proposal has been tabled for referendum vote. \[proposal_index, deposit, - /// depositors\] - Tabled(PropIndex, BalanceOf, Vec), + /// A motion has been proposed by a public account. + Proposed { proposal_index: PropIndex, deposit: BalanceOf }, + /// A public proposal has been tabled for referendum vote. + Tabled { proposal_index: PropIndex, deposit: BalanceOf, depositors: Vec }, /// An external proposal has been tabled. ExternalTabled, - /// A referendum has begun. \[ref_index, threshold\] - Started(ReferendumIndex, VoteThreshold), - /// A proposal has been approved by referendum. \[ref_index\] - Passed(ReferendumIndex), - /// A proposal has been rejected by referendum. \[ref_index\] - NotPassed(ReferendumIndex), - /// A referendum has been cancelled. \[ref_index\] - Cancelled(ReferendumIndex), - /// A proposal has been enacted. \[ref_index, result\] - Executed(ReferendumIndex, DispatchResult), - /// An account has delegated their vote to another account. \[who, target\] - Delegated(T::AccountId, T::AccountId), - /// An \[account\] has cancelled a previous delegation operation. - Undelegated(T::AccountId), - /// An external proposal has been vetoed. \[who, proposal_hash, until\] - Vetoed(T::AccountId, T::Hash, T::BlockNumber), - /// A proposal's preimage was noted, and the deposit taken. \[proposal_hash, who, deposit\] - PreimageNoted(T::Hash, T::AccountId, BalanceOf), + /// A referendum has begun. + Started { ref_index: ReferendumIndex, threshold: VoteThreshold }, + /// A proposal has been approved by referendum. + Passed { ref_index: ReferendumIndex }, + /// A proposal has been rejected by referendum. + NotPassed { ref_index: ReferendumIndex }, + /// A referendum has been cancelled. + Cancelled { ref_index: ReferendumIndex }, + /// A proposal has been enacted. + Executed { ref_index: ReferendumIndex, result: DispatchResult }, + /// An account has delegated their vote to another account. + Delegated { who: T::AccountId, target: T::AccountId }, + /// An account has cancelled a previous delegation operation. + Undelegated { account: T::AccountId }, + /// An external proposal has been vetoed. + Vetoed { who: T::AccountId, proposal_hash: T::Hash, until: T::BlockNumber }, + /// A proposal's preimage was noted, and the deposit taken. + PreimageNoted { proposal_hash: T::Hash, who: T::AccountId, deposit: BalanceOf }, /// A proposal preimage was removed and used (the deposit was returned). - /// \[proposal_hash, provider, deposit\] - PreimageUsed(T::Hash, T::AccountId, BalanceOf), + PreimageUsed { proposal_hash: T::Hash, provider: T::AccountId, deposit: BalanceOf }, /// A proposal could not be executed because its preimage was invalid. - /// \[proposal_hash, ref_index\] - PreimageInvalid(T::Hash, ReferendumIndex), + PreimageInvalid { proposal_hash: T::Hash, ref_index: ReferendumIndex }, /// A proposal could not be executed because its preimage was missing. - /// \[proposal_hash, ref_index\] - PreimageMissing(T::Hash, ReferendumIndex), + PreimageMissing { proposal_hash: T::Hash, ref_index: ReferendumIndex }, /// A registered preimage was removed and the deposit collected by the reaper. - /// \[proposal_hash, provider, deposit, reaper\] - PreimageReaped(T::Hash, T::AccountId, BalanceOf, T::AccountId), - /// A proposal \[hash\] has been blacklisted permanently. - Blacklisted(T::Hash), + PreimageReaped { + proposal_hash: T::Hash, + provider: T::AccountId, + deposit: BalanceOf, + reaper: T::AccountId, + }, + /// A proposal_hash has been blacklisted permanently. + Blacklisted { proposal_hash: T::Hash }, } #[pallet::error] @@ -657,7 +657,7 @@ pub mod pallet { >::append((index, proposal_hash, who)); - Self::deposit_event(Event::::Proposed(index, value)); + Self::deposit_event(Event::::Proposed { proposal_index: index, deposit: value }); Ok(()) } @@ -882,7 +882,7 @@ pub mod pallet { let until = >::block_number() + T::CooloffPeriod::get(); >::insert(&proposal_hash, (until, existing_vetoers)); - Self::deposit_event(Event::::Vetoed(who, proposal_hash, until)); + Self::deposit_event(Event::::Vetoed { who, proposal_hash, until }); >::kill(); Ok(()) } @@ -1104,7 +1104,12 @@ pub mod pallet { T::Currency::repatriate_reserved(&provider, &who, deposit, BalanceStatus::Free); debug_assert!(res.is_ok()); >::remove(&proposal_hash); - Self::deposit_event(Event::::PreimageReaped(proposal_hash, provider, deposit, who)); + Self::deposit_event(Event::::PreimageReaped { + proposal_hash, + provider, + deposit, + reaper: who, + }); Ok(()) } @@ -1249,7 +1254,7 @@ pub mod pallet { } } - Self::deposit_event(Event::::Blacklisted(proposal_hash)); + Self::deposit_event(Event::::Blacklisted { proposal_hash }); Ok(()) } @@ -1330,7 +1335,7 @@ impl Pallet { /// Remove a referendum. pub fn internal_cancel_referendum(ref_index: ReferendumIndex) { - Self::deposit_event(Event::::Cancelled(ref_index)); + Self::deposit_event(Event::::Cancelled { ref_index }); ReferendumInfoOf::::remove(ref_index); } @@ -1532,7 +1537,7 @@ impl Pallet { T::Currency::extend_lock(DEMOCRACY_ID, &who, balance, WithdrawReasons::TRANSFER); Ok(votes) })?; - Self::deposit_event(Event::::Delegated(who, target)); + Self::deposit_event(Event::::Delegated { who, target }); Ok(votes) } @@ -1558,7 +1563,7 @@ impl Pallet { Voting::Direct { .. } => Err(Error::::NotDelegating.into()), } })?; - Self::deposit_event(Event::::Undelegated(who)); + Self::deposit_event(Event::::Undelegated { account: who }); Ok(votes) } @@ -1589,7 +1594,7 @@ impl Pallet { ReferendumStatus { end, proposal_hash, threshold, delay, tally: Default::default() }; let item = ReferendumInfo::Ongoing(status); >::insert(ref_index, item); - Self::deposit_event(Event::::Started(ref_index, threshold)); + Self::deposit_event(Event::::Started { ref_index, threshold }); ref_index } @@ -1635,7 +1640,11 @@ impl Pallet { for d in &depositors { T::Currency::unreserve(d, deposit); } - Self::deposit_event(Event::::Tabled(prop_index, deposit, depositors)); + Self::deposit_event(Event::::Tabled { + proposal_index: prop_index, + deposit, + depositors, + }); Self::inject_referendum( now + T::VotingPeriod::get(), proposal, @@ -1655,22 +1664,25 @@ impl Pallet { if let Ok(proposal) = T::Proposal::decode(&mut &data[..]) { let err_amount = T::Currency::unreserve(&provider, deposit); debug_assert!(err_amount.is_zero()); - Self::deposit_event(Event::::PreimageUsed(proposal_hash, provider, deposit)); + Self::deposit_event(Event::::PreimageUsed { proposal_hash, provider, deposit }); let res = proposal .dispatch(frame_system::RawOrigin::Root.into()) .map(|_| ()) .map_err(|e| e.error); - Self::deposit_event(Event::::Executed(index, res)); + Self::deposit_event(Event::::Executed { ref_index: index, result: res }); Ok(()) } else { T::Slash::on_unbalanced(T::Currency::slash_reserved(&provider, deposit).0); - Self::deposit_event(Event::::PreimageInvalid(proposal_hash, index)); + Self::deposit_event(Event::::PreimageInvalid { + proposal_hash, + ref_index: index, + }); Err(Error::::PreimageInvalid.into()) } } else { - Self::deposit_event(Event::::PreimageMissing(proposal_hash, index)); + Self::deposit_event(Event::::PreimageMissing { proposal_hash, ref_index: index }); Err(Error::::PreimageMissing.into()) } } @@ -1684,7 +1696,7 @@ impl Pallet { let approved = status.threshold.approved(status.tally, total_issuance); if approved { - Self::deposit_event(Event::::Passed(index)); + Self::deposit_event(Event::::Passed { ref_index: index }); if status.delay.is_zero() { let _ = Self::do_enact_proposal(status.proposal_hash, index); } else { @@ -1713,7 +1725,7 @@ impl Pallet { } } } else { - Self::deposit_event(Event::::NotPassed(index)); + Self::deposit_event(Event::::NotPassed { ref_index: index }); } approved @@ -1870,7 +1882,7 @@ impl Pallet { }; >::insert(proposal_hash, a); - Self::deposit_event(Event::::PreimageNoted(proposal_hash, who, deposit)); + Self::deposit_event(Event::::PreimageNoted { proposal_hash, who, deposit }); Ok(()) } @@ -1896,7 +1908,7 @@ impl Pallet { }; >::insert(proposal_hash, a); - Self::deposit_event(Event::::PreimageNoted(proposal_hash, who, free)); + Self::deposit_event(Event::::PreimageNoted { proposal_hash, who, deposit: free }); Ok(()) } diff --git a/frame/election-provider-multi-phase/src/lib.rs b/frame/election-provider-multi-phase/src/lib.rs index 4c4de82af592..cdf5a2098d6b 100644 --- a/frame/election-provider-multi-phase/src/lib.rs +++ b/frame/election-provider-multi-phase/src/lib.rs @@ -886,10 +886,10 @@ pub mod pallet { log!(info, "queued unsigned solution with score {:?}", ready.score); let ejected_a_solution = >::exists(); >::put(ready); - Self::deposit_event(Event::SolutionStored( - ElectionCompute::Unsigned, - ejected_a_solution, - )); + Self::deposit_event(Event::SolutionStored { + election_compute: ElectionCompute::Unsigned, + prev_ejected: ejected_a_solution, + }); Ok(None.into()) } @@ -1012,7 +1012,10 @@ pub mod pallet { } signed_submissions.put(); - Self::deposit_event(Event::SolutionStored(ElectionCompute::Signed, ejected_a_solution)); + Self::deposit_event(Event::SolutionStored { + election_compute: ElectionCompute::Signed, + prev_ejected: ejected_a_solution, + }); Ok(()) } } @@ -1026,18 +1029,18 @@ pub mod pallet { /// solution is unsigned, this means that it has also been processed. /// /// The `bool` is `true` when a previous solution was ejected to make room for this one. - SolutionStored(ElectionCompute, bool), + SolutionStored { election_compute: ElectionCompute, prev_ejected: bool }, /// The election has been finalized, with `Some` of the given computation, or else if the /// election failed, `None`. - ElectionFinalized(Option), + ElectionFinalized { election_compute: Option }, /// An account has been rewarded for their signed submission being finalized. - Rewarded(::AccountId, BalanceOf), + Rewarded { account: ::AccountId, value: BalanceOf }, /// An account has been slashed for submitting an invalid signed submission. - Slashed(::AccountId, BalanceOf), + Slashed { account: ::AccountId, value: BalanceOf }, /// The signed phase of the given round has started. - SignedPhaseStarted(u32), + SignedPhaseStarted { round: u32 }, /// The unsigned phase of the given round has started. - UnsignedPhaseStarted(u32), + UnsignedPhaseStarted { round: u32 }, } /// Error of the pallet that can be returned in response to dispatches. @@ -1245,7 +1248,7 @@ impl Pallet { pub fn on_initialize_open_signed() { log!(info, "Starting signed phase round {}.", Self::round()); >::put(Phase::Signed); - Self::deposit_event(Event::SignedPhaseStarted(Self::round())); + Self::deposit_event(Event::SignedPhaseStarted { round: Self::round() }); } /// Logic for [`>::on_initialize`] when unsigned phase is being opened. @@ -1253,7 +1256,7 @@ impl Pallet { let round = Self::round(); log!(info, "Starting unsigned phase round {} enabled {}.", round, enabled); >::put(Phase::Unsigned((enabled, now))); - Self::deposit_event(Event::UnsignedPhaseStarted(round)); + Self::deposit_event(Event::UnsignedPhaseStarted { round }); } /// Parts of [`create_snapshot`] that happen inside of this pallet. @@ -1473,14 +1476,14 @@ impl Pallet { |ReadySolution { supports, compute, .. }| Ok((supports, compute)), ) .map(|(supports, compute)| { - Self::deposit_event(Event::ElectionFinalized(Some(compute))); + Self::deposit_event(Event::ElectionFinalized { election_compute: Some(compute) }); if Self::round() != 1 { log!(info, "Finalized election round with compute {:?}.", compute); } supports }) .map_err(|err| { - Self::deposit_event(Event::ElectionFinalized(None)); + Self::deposit_event(Event::ElectionFinalized { election_compute: None }); if Self::round() != 1 { log!(warn, "Failed to finalize election round. reason {:?}", err); } @@ -1737,7 +1740,7 @@ mod tests { roll_to(15); assert_eq!(MultiPhase::current_phase(), Phase::Signed); - assert_eq!(multi_phase_events(), vec![Event::SignedPhaseStarted(1)]); + assert_eq!(multi_phase_events(), vec![Event::SignedPhaseStarted { round: 1 }]); assert!(MultiPhase::snapshot().is_some()); assert_eq!(MultiPhase::round(), 1); @@ -1750,7 +1753,10 @@ mod tests { assert_eq!(MultiPhase::current_phase(), Phase::Unsigned((true, 25))); assert_eq!( multi_phase_events(), - vec![Event::SignedPhaseStarted(1), Event::UnsignedPhaseStarted(1)], + vec![ + Event::SignedPhaseStarted { round: 1 }, + Event::UnsignedPhaseStarted { round: 1 } + ], ); assert!(MultiPhase::snapshot().is_some()); @@ -1861,7 +1867,7 @@ mod tests { assert_eq!(MultiPhase::current_phase(), Phase::Off); roll_to(15); - assert_eq!(multi_phase_events(), vec![Event::SignedPhaseStarted(1)]); + assert_eq!(multi_phase_events(), vec![Event::SignedPhaseStarted { round: 1 }]); assert_eq!(MultiPhase::current_phase(), Phase::Signed); assert_eq!(MultiPhase::round(), 1); @@ -1873,8 +1879,8 @@ mod tests { assert_eq!( multi_phase_events(), vec![ - Event::SignedPhaseStarted(1), - Event::ElectionFinalized(Some(ElectionCompute::Fallback)) + Event::SignedPhaseStarted { round: 1 }, + Event::ElectionFinalized { election_compute: Some(ElectionCompute::Fallback) } ], ); // All storage items must be cleared. @@ -1896,7 +1902,7 @@ mod tests { assert_eq!(MultiPhase::current_phase(), Phase::Off); roll_to(15); - assert_eq!(multi_phase_events(), vec![Event::SignedPhaseStarted(1)]); + assert_eq!(multi_phase_events(), vec![Event::SignedPhaseStarted { round: 1 }]); assert_eq!(MultiPhase::current_phase(), Phase::Signed); assert_eq!(MultiPhase::round(), 1); diff --git a/frame/election-provider-multi-phase/src/signed.rs b/frame/election-provider-multi-phase/src/signed.rs index 61215059c53a..b762ad706486 100644 --- a/frame/election-provider-multi-phase/src/signed.rs +++ b/frame/election-provider-multi-phase/src/signed.rs @@ -429,7 +429,7 @@ impl Pallet { >::put(ready_solution); // emit reward event - Self::deposit_event(crate::Event::Rewarded(who.clone(), reward)); + Self::deposit_event(crate::Event::Rewarded { account: who.clone(), value: reward }); // unreserve deposit. let _remaining = T::Currency::unreserve(who, deposit); @@ -446,7 +446,7 @@ impl Pallet { /// /// Infallible pub fn finalize_signed_phase_reject_solution(who: &T::AccountId, deposit: BalanceOf) { - Self::deposit_event(crate::Event::Slashed(who.clone(), deposit)); + Self::deposit_event(crate::Event::Slashed { account: who.clone(), value: deposit }); let (negative_imbalance, _remaining) = T::Currency::slash_reserved(who, deposit); debug_assert!(_remaining.is_zero()); T::SlashHandler::on_unbalanced(negative_imbalance); diff --git a/frame/elections-phragmen/src/lib.rs b/frame/elections-phragmen/src/lib.rs index d7b42383da75..116c0937bf98 100644 --- a/frame/elections-phragmen/src/lib.rs +++ b/frame/elections-phragmen/src/lib.rs @@ -425,7 +425,7 @@ pub mod pallet { Renouncing::Member => { let _ = Self::remove_and_replace_member(&who, false) .map_err(|_| Error::::InvalidRenouncing)?; - Self::deposit_event(Event::Renounced(who)); + Self::deposit_event(Event::Renounced { candidate: who }); }, Renouncing::RunnerUp => { >::try_mutate::<_, Error, _>(|runners_up| { @@ -437,7 +437,7 @@ pub mod pallet { let SeatHolder { deposit, .. } = runners_up.remove(index); let _remainder = T::Currency::unreserve(&who, deposit); debug_assert!(_remainder.is_zero()); - Self::deposit_event(Event::Renounced(who)); + Self::deposit_event(Event::Renounced { candidate: who }); Ok(()) })?; }, @@ -450,7 +450,7 @@ pub mod pallet { let (_removed, deposit) = candidates.remove(index); let _remainder = T::Currency::unreserve(&who, deposit); debug_assert!(_remainder.is_zero()); - Self::deposit_event(Event::Renounced(who)); + Self::deposit_event(Event::Renounced { candidate: who }); Ok(()) })?; }, @@ -496,7 +496,7 @@ pub mod pallet { let had_replacement = Self::remove_and_replace_member(&who, true)?; debug_assert_eq!(has_replacement, had_replacement); - Self::deposit_event(Event::MemberKicked(who.clone())); + Self::deposit_event(Event::MemberKicked { member: who.clone() }); if !had_replacement { Self::do_phragmen(); @@ -534,29 +534,32 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { - /// A new term with \[new_members\]. This indicates that enough candidates existed to run + /// A new term with new_members. This indicates that enough candidates existed to run /// the election, not that enough have has been elected. The inner value must be examined /// for this purpose. A `NewTerm(\[\])` indicates that some candidates got their bond /// slashed and none were elected, whilst `EmptyTerm` means that no candidates existed to /// begin with. - NewTerm(Vec<(::AccountId, BalanceOf)>), + NewTerm { new_members: Vec<(::AccountId, BalanceOf)> }, /// No (or not enough) candidates existed for this round. This is different from /// `NewTerm(\[\])`. See the description of `NewTerm`. EmptyTerm, /// Internal error happened while trying to perform election. ElectionError, - /// A \[member\] has been removed. This should always be followed by either `NewTerm` or + /// A member has been removed. This should always be followed by either `NewTerm` or /// `EmptyTerm`. - MemberKicked(::AccountId), + MemberKicked { member: ::AccountId }, /// Someone has renounced their candidacy. - Renounced(::AccountId), - /// A \[candidate\] was slashed by \[amount\] due to failing to obtain a seat as member or + Renounced { candidate: ::AccountId }, + /// A candidate was slashed by amount due to failing to obtain a seat as member or /// runner-up. /// /// Note that old members and runners-up are also candidates. - CandidateSlashed(::AccountId, BalanceOf), - /// A \[seat holder\] was slashed by \[amount\] by being forcefully removed from the set. - SeatHolderSlashed(::AccountId, BalanceOf), + CandidateSlashed { candidate: ::AccountId, amount: BalanceOf }, + /// A seat holder was slashed by amount by being forcefully removed from the set. + SeatHolderSlashed { + seat_holder: ::AccountId, + amount: BalanceOf, + }, } #[deprecated(note = "use `Event` instead")] @@ -748,7 +751,10 @@ impl Pallet { let (imbalance, _remainder) = T::Currency::slash_reserved(who, removed.deposit); debug_assert!(_remainder.is_zero()); T::LoserCandidate::on_unbalanced(imbalance); - Self::deposit_event(Event::SeatHolderSlashed(who.clone(), removed.deposit)); + Self::deposit_event(Event::SeatHolderSlashed { + seat_holder: who.clone(), + amount: removed.deposit, + }); } else { T::Currency::unreserve(who, removed.deposit); } @@ -1001,7 +1007,10 @@ impl Pallet { { let (imbalance, _) = T::Currency::slash_reserved(c, *d); T::LoserCandidate::on_unbalanced(imbalance); - Self::deposit_event(Event::CandidateSlashed(c.clone(), *d)); + Self::deposit_event(Event::CandidateSlashed { + candidate: c.clone(), + amount: *d, + }); } }); @@ -1041,7 +1050,7 @@ impl Pallet { // clean candidates. >::kill(); - Self::deposit_event(Event::NewTerm(new_members_sorted_by_id)); + Self::deposit_event(Event::NewTerm { new_members: new_members_sorted_by_id }); >::mutate(|v| *v += 1); }) .map_err(|e| { @@ -2147,10 +2156,9 @@ mod tests { System::set_block_number(5); Elections::on_initialize(System::block_number()); - System::assert_last_event(Event::Elections(super::Event::NewTerm(vec![ - (4, 40), - (5, 50), - ]))); + System::assert_last_event(Event::Elections(super::Event::NewTerm { + new_members: vec![(4, 40), (5, 50)], + })); assert_eq!(members_and_stake(), vec![(4, 40), (5, 50)]); assert_eq!(runners_up_and_stake(), vec![]); @@ -2161,7 +2169,9 @@ mod tests { System::set_block_number(10); Elections::on_initialize(System::block_number()); - System::assert_last_event(Event::Elections(super::Event::NewTerm(vec![]))); + System::assert_last_event(Event::Elections(super::Event::NewTerm { + new_members: vec![], + })); // outgoing have lost their bond. assert_eq!(balances(&4), (37, 0)); @@ -2231,7 +2241,9 @@ mod tests { assert_eq!(Elections::election_rounds(), 1); assert!(members_ids().is_empty()); - System::assert_last_event(Event::Elections(super::Event::NewTerm(vec![]))); + System::assert_last_event(Event::Elections(super::Event::NewTerm { + new_members: vec![], + })); }); } @@ -2583,10 +2595,9 @@ mod tests { // 5 is an outgoing loser. will also get slashed. assert_eq!(balances(&5), (45, 2)); - System::assert_has_event(Event::Elections(super::Event::NewTerm(vec![ - (4, 40), - (5, 50), - ]))); + System::assert_has_event(Event::Elections(super::Event::NewTerm { + new_members: vec![(4, 40), (5, 50)], + })); }) } diff --git a/frame/elections/src/lib.rs b/frame/elections/src/lib.rs index ac13bce31b0f..7ca11f4ed20e 100644 --- a/frame/elections/src/lib.rs +++ b/frame/elections/src/lib.rs @@ -465,15 +465,14 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { - /// Reaped \[voter, reaper\]. - VoterReaped(T::AccountId, T::AccountId), - /// Slashed \[reaper\]. - BadReaperSlashed(T::AccountId), - /// A tally (for approval votes of \[seats\]) has started. - TallyStarted(u32), + /// Reaped + VoterReaped { voter: T::AccountId, reaper: T::AccountId }, + /// Slashed + BadReaperSlashed { reaper: T::AccountId }, + /// A tally (for approval votes of seats) has started. + TallyStarted { seats: u32 }, /// A tally (for approval votes of seat(s)) has ended (with one or more new members). - /// \[incoming, outgoing\] - TallyFinalized(Vec, Vec), + TallyFinalized { incoming: Vec, outgoing: Vec }, } #[pallet::call] @@ -590,11 +589,11 @@ pub mod pallet { T::VotingBond::get(), BalanceStatus::Free, )?; - Self::deposit_event(Event::::VoterReaped(who, reporter)); + Self::deposit_event(Event::::VoterReaped { voter: who, reaper: reporter }); } else { let imbalance = T::Currency::slash_reserved(&reporter, T::VotingBond::get()).0; T::BadReaper::on_unbalanced(imbalance); - Self::deposit_event(Event::::BadReaperSlashed(reporter)); + Self::deposit_event(Event::::BadReaperSlashed { reaper: reporter }); } Ok(()) } @@ -1024,7 +1023,7 @@ impl Pallet { leaderboard_size ]); - Self::deposit_event(Event::::TallyStarted(empty_seats as u32)); + Self::deposit_event(Event::::TallyStarted { seats: empty_seats as u32 }); } } @@ -1118,7 +1117,7 @@ impl Pallet { new_candidates.truncate(last_index + 1); } - Self::deposit_event(Event::::TallyFinalized(incoming, outgoing)); + Self::deposit_event(Event::::TallyFinalized { incoming, outgoing }); >::put(new_candidates); CandidateCount::::put(count); diff --git a/frame/examples/basic/src/lib.rs b/frame/examples/basic/src/lib.rs index b172acb66d32..25ff76f4d151 100644 --- a/frame/examples/basic/src/lib.rs +++ b/frame/examples/basic/src/lib.rs @@ -525,7 +525,7 @@ pub mod pallet { }); // Let's deposit an event to let the outside world know this happened. - Self::deposit_event(Event::AccumulateDummy(increase_by)); + Self::deposit_event(Event::AccumulateDummy { balance: increase_by }); // All good, no refund. Ok(()) @@ -557,7 +557,7 @@ pub mod pallet { // Put the new value into storage. >::put(new_value); - Self::deposit_event(Event::SetDummy(new_value)); + Self::deposit_event(Event::SetDummy { balance: new_value }); // All good, no refund. Ok(()) @@ -574,9 +574,16 @@ pub mod pallet { pub enum Event { // Just a normal `enum`, here's a dummy event to ensure it compiles. /// Dummy event, just here so there's a generic type that's used. - AccumulateDummy(BalanceOf), - SetDummy(BalanceOf), - SetBar(T::AccountId, BalanceOf), + AccumulateDummy { + balance: BalanceOf, + }, + SetDummy { + balance: BalanceOf, + }, + SetBar { + account: T::AccountId, + balance: BalanceOf, + }, } // pallet::storage attributes allow for type-safe usage of the Substrate storage database, diff --git a/frame/examples/offchain-worker/src/lib.rs b/frame/examples/offchain-worker/src/lib.rs index e5f2e00d9a34..9812d35ffa07 100644 --- a/frame/examples/offchain-worker/src/lib.rs +++ b/frame/examples/offchain-worker/src/lib.rs @@ -291,8 +291,7 @@ pub mod pallet { #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { /// Event generated when new price is accepted to contribute to the average. - /// \[price, who\] - NewPrice(u32, T::AccountId), + NewPrice { price: u32, who: T::AccountId }, } #[pallet::validate_unsigned] @@ -658,7 +657,7 @@ impl Pallet { .expect("The average is not empty, because it was just mutated; qed"); log::info!("Current average price is: {}", average); // here we are raising the NewPrice event - Self::deposit_event(Event::NewPrice(price, who)); + Self::deposit_event(Event::NewPrice { price, who }); } /// Calculate current average price. diff --git a/frame/gilt/src/lib.rs b/frame/gilt/src/lib.rs index 1594601b457c..b494eed67445 100644 --- a/frame/gilt/src/lib.rs +++ b/frame/gilt/src/lib.rs @@ -272,17 +272,23 @@ pub mod pallet { #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { /// A bid was successfully placed. - /// \[ who, amount, duration \] - BidPlaced(T::AccountId, BalanceOf, u32), + BidPlaced { who: T::AccountId, amount: BalanceOf, duration: u32 }, /// A bid was successfully removed (before being accepted as a gilt). - /// \[ who, amount, duration \] - BidRetracted(T::AccountId, BalanceOf, u32), + BidRetracted { who: T::AccountId, amount: BalanceOf, duration: u32 }, /// A bid was accepted as a gilt. The balance may not be released until expiry. - /// \[ index, expiry, who, amount \] - GiltIssued(ActiveIndex, T::BlockNumber, T::AccountId, BalanceOf), + GiltIssued { + index: ActiveIndex, + expiry: T::BlockNumber, + who: T::AccountId, + amount: BalanceOf, + }, /// An expired gilt has been thawed. - /// \[ index, who, original_amount, additional_amount \] - GiltThawed(ActiveIndex, T::AccountId, BalanceOf, BalanceOf), + GiltThawed { + index: ActiveIndex, + who: T::AccountId, + original_amount: BalanceOf, + additional_amount: BalanceOf, + }, } #[pallet::error] @@ -376,7 +382,7 @@ pub mod pallet { qs[queue_index].0 += net.0; qs[queue_index].1 = qs[queue_index].1.saturating_add(net.1); }); - Self::deposit_event(Event::BidPlaced(who.clone(), amount, duration)); + Self::deposit_event(Event::BidPlaced { who: who.clone(), amount, duration }); Ok(().into()) } @@ -414,7 +420,7 @@ pub mod pallet { }); T::Currency::unreserve(&bid.who, bid.amount); - Self::deposit_event(Event::BidRetracted(bid.who, bid.amount, duration)); + Self::deposit_event(Event::BidRetracted { who: bid.who, amount: bid.amount, duration }); Ok(().into()) } @@ -493,7 +499,12 @@ pub mod pallet { debug_assert!(err_amt.is_zero()); } - let e = Event::GiltThawed(index, gilt.who, gilt.amount, gilt_value); + let e = Event::GiltThawed { + index, + who: gilt.who, + original_amount: gilt.amount, + additional_amount: gilt_value, + }; Self::deposit_event(e); }); @@ -603,7 +614,8 @@ pub mod pallet { totals.frozen += bid.amount; totals.proportion = totals.proportion.saturating_add(proportion); totals.index += 1; - let e = Event::GiltIssued(index, expiry, who.clone(), amount); + let e = + Event::GiltIssued { index, expiry, who: who.clone(), amount }; Self::deposit_event(e); let gilt = ActiveGilt { amount, proportion, who, expiry }; Active::::insert(index, gilt); diff --git a/frame/grandpa/src/lib.rs b/frame/grandpa/src/lib.rs index 0e7d885649cc..b289da464a93 100644 --- a/frame/grandpa/src/lib.rs +++ b/frame/grandpa/src/lib.rs @@ -154,9 +154,9 @@ pub mod pallet { // enact the change if we've reached the enacting block if block_number == pending_change.scheduled_at + pending_change.delay { Self::set_grandpa_authorities(&pending_change.next_authorities); - Self::deposit_event(Event::NewAuthorities( - pending_change.next_authorities.to_vec(), - )); + Self::deposit_event(Event::NewAuthorities { + authority_set: pending_change.next_authorities.to_vec(), + }); >::kill(); } } @@ -255,8 +255,8 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(fn deposit_event)] pub enum Event { - /// New authority set has been applied. \[authority_set\] - NewAuthorities(AuthorityList), + /// New authority set has been applied. + NewAuthorities { authority_set: AuthorityList }, /// Current authority set has been paused. Paused, /// Current authority set has been resumed. diff --git a/frame/grandpa/src/tests.rs b/frame/grandpa/src/tests.rs index 98f54f966fad..6dc0a26da8bd 100644 --- a/frame/grandpa/src/tests.rs +++ b/frame/grandpa/src/tests.rs @@ -57,7 +57,10 @@ fn authorities_change_logged() { System::events(), vec![EventRecord { phase: Phase::Finalization, - event: Event::NewAuthorities(to_authorities(vec![(4, 1), (5, 1), (6, 1)])).into(), + event: Event::NewAuthorities { + authority_set: to_authorities(vec![(4, 1), (5, 1), (6, 1)]) + } + .into(), topics: vec![], },] ); @@ -93,7 +96,10 @@ fn authorities_change_logged_after_delay() { System::events(), vec![EventRecord { phase: Phase::Finalization, - event: Event::NewAuthorities(to_authorities(vec![(4, 1), (5, 1), (6, 1)])).into(), + event: Event::NewAuthorities { + authority_set: to_authorities(vec![(4, 1), (5, 1), (6, 1)]) + } + .into(), topics: vec![], },] ); diff --git a/frame/identity/src/benchmarking.rs b/frame/identity/src/benchmarking.rs index 68869a43992f..db257fec43a1 100644 --- a/frame/identity/src/benchmarking.rs +++ b/frame/identity/src/benchmarking.rs @@ -153,7 +153,7 @@ benchmarks! { }; }: _(RawOrigin::Signed(caller.clone()), Box::new(create_identity_info::(x))) verify { - assert_last_event::(Event::::IdentitySet(caller).into()); + assert_last_event::(Event::::IdentitySet { who: caller }.into()); } // We need to split `set_subs` into two benchmarks to accurately isolate the potential @@ -237,7 +237,7 @@ benchmarks! { }; }: _(RawOrigin::Signed(caller.clone()), r - 1, 10u32.into()) verify { - assert_last_event::(Event::::JudgementRequested(caller, r-1).into()); + assert_last_event::(Event::::JudgementRequested { who: caller, registrar_index: r-1 }.into()); } cancel_request { @@ -257,7 +257,7 @@ benchmarks! { Identity::::request_judgement(caller_origin, r - 1, 10u32.into())?; }: _(RawOrigin::Signed(caller.clone()), r - 1) verify { - assert_last_event::(Event::::JudgementUnrequested(caller, r-1).into()); + assert_last_event::(Event::::JudgementUnrequested { who: caller, registrar_index: r-1 }.into()); } set_fee { @@ -328,7 +328,7 @@ benchmarks! { Identity::::request_judgement(user_origin.clone(), r, 10u32.into())?; }: _(RawOrigin::Signed(caller), r, user_lookup, Judgement::Reasonable) verify { - assert_last_event::(Event::::JudgementGiven(user, r).into()) + assert_last_event::(Event::::JudgementGiven { target: user, registrar_index: r }.into()) } kill_identity { diff --git a/frame/identity/src/lib.rs b/frame/identity/src/lib.rs index 4d86efd27e53..b4b52331618c 100644 --- a/frame/identity/src/lib.rs +++ b/frame/identity/src/lib.rs @@ -241,28 +241,27 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { - /// A name was set or reset (which will remove all judgements). \[who\] - IdentitySet(T::AccountId), - /// A name was cleared, and the given balance returned. \[who, deposit\] - IdentityCleared(T::AccountId, BalanceOf), - /// A name was removed and the given balance slashed. \[who, deposit\] - IdentityKilled(T::AccountId, BalanceOf), - /// A judgement was asked from a registrar. \[who, registrar_index\] - JudgementRequested(T::AccountId, RegistrarIndex), - /// A judgement request was retracted. \[who, registrar_index\] - JudgementUnrequested(T::AccountId, RegistrarIndex), - /// A judgement was given by a registrar. \[target, registrar_index\] - JudgementGiven(T::AccountId, RegistrarIndex), - /// A registrar was added. \[registrar_index\] - RegistrarAdded(RegistrarIndex), - /// A sub-identity was added to an identity and the deposit paid. \[sub, main, deposit\] - SubIdentityAdded(T::AccountId, T::AccountId, BalanceOf), + /// A name was set or reset (which will remove all judgements). + IdentitySet { who: T::AccountId }, + /// A name was cleared, and the given balance returned. + IdentityCleared { who: T::AccountId, deposit: BalanceOf }, + /// A name was removed and the given balance slashed. + IdentityKilled { who: T::AccountId, deposit: BalanceOf }, + /// A judgement was asked from a registrar. + JudgementRequested { who: T::AccountId, registrar_index: RegistrarIndex }, + /// A judgement request was retracted. + JudgementUnrequested { who: T::AccountId, registrar_index: RegistrarIndex }, + /// A judgement was given by a registrar. + JudgementGiven { target: T::AccountId, registrar_index: RegistrarIndex }, + /// A registrar was added. + RegistrarAdded { registrar_index: RegistrarIndex }, + /// A sub-identity was added to an identity and the deposit paid. + SubIdentityAdded { sub: T::AccountId, main: T::AccountId, deposit: BalanceOf }, /// A sub-identity was removed from an identity and the deposit freed. - /// \[sub, main, deposit\] - SubIdentityRemoved(T::AccountId, T::AccountId, BalanceOf), + SubIdentityRemoved { sub: T::AccountId, main: T::AccountId, deposit: BalanceOf }, /// A sub-identity was cleared, and the given deposit repatriated from the - /// main identity account to the sub-identity account. \[sub, main, deposit\] - SubIdentityRevoked(T::AccountId, T::AccountId, BalanceOf), + /// main identity account to the sub-identity account. + SubIdentityRevoked { sub: T::AccountId, main: T::AccountId, deposit: BalanceOf }, } #[pallet::call] @@ -301,7 +300,7 @@ pub mod pallet { }, )?; - Self::deposit_event(Event::RegistrarAdded(i)); + Self::deposit_event(Event::RegistrarAdded { registrar_index: i }); Ok(Some(T::WeightInfo::add_registrar(registrar_count as u32)).into()) } @@ -364,7 +363,7 @@ pub mod pallet { let judgements = id.judgements.len(); >::insert(&sender, id); - Self::deposit_event(Event::IdentitySet(sender)); + Self::deposit_event(Event::IdentitySet { who: sender }); Ok(Some(T::WeightInfo::set_identity( judgements as u32, // R @@ -489,7 +488,7 @@ pub mod pallet { let err_amount = T::Currency::unreserve(&sender, deposit.clone()); debug_assert!(err_amount.is_zero()); - Self::deposit_event(Event::IdentityCleared(sender, deposit)); + Self::deposit_event(Event::IdentityCleared { who: sender, deposit }); Ok(Some(T::WeightInfo::clear_identity( id.judgements.len() as u32, // R @@ -558,7 +557,10 @@ pub mod pallet { let extra_fields = id.info.additional.len(); >::insert(&sender, id); - Self::deposit_event(Event::JudgementRequested(sender, reg_index)); + Self::deposit_event(Event::JudgementRequested { + who: sender, + registrar_index: reg_index, + }); Ok(Some(T::WeightInfo::request_judgement(judgements as u32, extra_fields as u32)) .into()) @@ -608,7 +610,10 @@ pub mod pallet { let extra_fields = id.info.additional.len(); >::insert(&sender, id); - Self::deposit_event(Event::JudgementUnrequested(sender, reg_index)); + Self::deposit_event(Event::JudgementUnrequested { + who: sender, + registrar_index: reg_index, + }); Ok(Some(T::WeightInfo::cancel_request(judgements as u32, extra_fields as u32)).into()) } @@ -791,7 +796,7 @@ pub mod pallet { let judgements = id.judgements.len(); let extra_fields = id.info.additional.len(); >::insert(&target, id); - Self::deposit_event(Event::JudgementGiven(target, reg_index)); + Self::deposit_event(Event::JudgementGiven { target, registrar_index: reg_index }); Ok(Some(T::WeightInfo::provide_judgement(judgements as u32, extra_fields as u32)) .into()) @@ -839,7 +844,7 @@ pub mod pallet { // Slash their deposit from them. T::Slashed::on_unbalanced(T::Currency::slash_reserved(&target, deposit).0); - Self::deposit_event(Event::IdentityKilled(target, deposit)); + Self::deposit_event(Event::IdentityKilled { who: target, deposit }); Ok(Some(T::WeightInfo::kill_identity( id.judgements.len() as u32, // R @@ -882,7 +887,7 @@ pub mod pallet { sub_ids.try_push(sub.clone()).expect("sub ids length checked above; qed"); *subs_deposit = subs_deposit.saturating_add(deposit); - Self::deposit_event(Event::SubIdentityAdded(sub, sender.clone(), deposit)); + Self::deposit_event(Event::SubIdentityAdded { sub, main: sender.clone(), deposit }); Ok(()) }) } @@ -929,7 +934,7 @@ pub mod pallet { *subs_deposit -= deposit; let err_amount = T::Currency::unreserve(&sender, deposit); debug_assert!(err_amount.is_zero()); - Self::deposit_event(Event::SubIdentityRemoved(sub, sender, deposit)); + Self::deposit_event(Event::SubIdentityRemoved { sub, main: sender, deposit }); }); Ok(()) } @@ -954,7 +959,11 @@ pub mod pallet { *subs_deposit -= deposit; let _ = T::Currency::repatriate_reserved(&sup, &sender, deposit, BalanceStatus::Free); - Self::deposit_event(Event::SubIdentityRevoked(sender, sup.clone(), deposit)); + Self::deposit_event(Event::SubIdentityRevoked { + sub: sender, + main: sup.clone(), + deposit, + }); }); Ok(()) } diff --git a/frame/im-online/src/lib.rs b/frame/im-online/src/lib.rs index 2c5a7633c3b4..718c735fdad4 100644 --- a/frame/im-online/src/lib.rs +++ b/frame/im-online/src/lib.rs @@ -374,12 +374,12 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { - /// A new heartbeat was received from `AuthorityId` \[authority_id\] - HeartbeatReceived(T::AuthorityId), + /// A new heartbeat was received from `AuthorityId`. + HeartbeatReceived { authority_id: T::AuthorityId }, /// At the end of the session, no offence was committed. AllGood, - /// At the end of the session, at least one validator was found to be \[offline\]. - SomeOffline(Vec>), + /// At the end of the session, at least one validator was found to be offline. + SomeOffline { offline: Vec> }, } #[pallet::error] @@ -495,7 +495,7 @@ pub mod pallet { let keys = Keys::::get(); let public = keys.get(heartbeat.authority_index as usize); if let (false, Some(public)) = (exists, public) { - Self::deposit_event(Event::::HeartbeatReceived(public.clone())); + Self::deposit_event(Event::::HeartbeatReceived { authority_id: public.clone() }); let network_state_bounded = BoundedOpaqueNetworkState::< T::MaxPeerDataEncodingSize, @@ -908,7 +908,7 @@ impl OneSessionHandler for Pallet { if offenders.is_empty() { Self::deposit_event(Event::::AllGood); } else { - Self::deposit_event(Event::::SomeOffline(offenders.clone())); + Self::deposit_event(Event::::SomeOffline { offline: offenders.clone() }); let validator_set_count = keys.len() as u32; let offence = UnresponsivenessOffence { session_index, validator_set_count, offenders }; diff --git a/frame/indices/src/lib.rs b/frame/indices/src/lib.rs index 0901a89d41ad..d8051bac0a3c 100644 --- a/frame/indices/src/lib.rs +++ b/frame/indices/src/lib.rs @@ -105,7 +105,7 @@ pub mod pallet { *maybe_value = Some((who.clone(), T::Deposit::get(), false)); T::Currency::reserve(&who, T::Deposit::get()) })?; - Self::deposit_event(Event::IndexAssigned(who, index)); + Self::deposit_event(Event::IndexAssigned { who, index }); Ok(()) } @@ -146,7 +146,7 @@ pub mod pallet { *maybe_value = Some((new.clone(), amount.saturating_sub(lost), false)); Ok(()) })?; - Self::deposit_event(Event::IndexAssigned(new, index)); + Self::deposit_event(Event::IndexAssigned { who: new, index }); Ok(()) } @@ -179,7 +179,7 @@ pub mod pallet { T::Currency::unreserve(&who, amount); Ok(()) })?; - Self::deposit_event(Event::IndexFreed(index)); + Self::deposit_event(Event::IndexFreed { index }); Ok(()) } @@ -219,7 +219,7 @@ pub mod pallet { } *maybe_value = Some((new.clone(), Zero::zero(), freeze)); }); - Self::deposit_event(Event::IndexAssigned(new, index)); + Self::deposit_event(Event::IndexAssigned { who: new, index }); Ok(()) } @@ -253,7 +253,7 @@ pub mod pallet { *maybe_value = Some((account, Zero::zero(), true)); Ok(()) })?; - Self::deposit_event(Event::IndexFrozen(index, who)); + Self::deposit_event(Event::IndexFrozen { index, who }); Ok(()) } } @@ -261,12 +261,12 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { - /// A account index was assigned. \[index, who\] - IndexAssigned(T::AccountId, T::AccountIndex), - /// A account index has been freed up (unassigned). \[index\] - IndexFreed(T::AccountIndex), - /// A account index has been frozen to its current account ID. \[index, who\] - IndexFrozen(T::AccountIndex, T::AccountId), + /// A account index was assigned. + IndexAssigned { who: T::AccountId, index: T::AccountIndex }, + /// A account index has been freed up (unassigned). + IndexFreed { index: T::AccountIndex }, + /// A account index has been frozen to its current account ID. + IndexFrozen { index: T::AccountIndex, who: T::AccountId }, } /// Old name generated by `decl_event`. diff --git a/frame/lottery/src/lib.rs b/frame/lottery/src/lib.rs index 260b4c2d76ae..c1c536b8ba29 100644 --- a/frame/lottery/src/lib.rs +++ b/frame/lottery/src/lib.rs @@ -176,9 +176,9 @@ pub mod pallet { /// A new set of calls have been set! CallsUpdated, /// A winner has been chosen! - Winner(T::AccountId, BalanceOf), + Winner { winner: T::AccountId, lottery_balance: BalanceOf }, /// A ticket has been bought! - TicketBought(T::AccountId, CallIndex), + TicketBought { who: T::AccountId, call_index: CallIndex }, } #[pallet::error] @@ -250,7 +250,7 @@ pub mod pallet { ); debug_assert!(res.is_ok()); - Self::deposit_event(Event::::Winner(winner, lottery_balance)); + Self::deposit_event(Event::::Winner { winner, lottery_balance }); TicketsCount::::kill(); @@ -452,7 +452,7 @@ impl Pallet { }, )?; - Self::deposit_event(Event::::TicketBought(caller.clone(), call_index)); + Self::deposit_event(Event::::TicketBought { who: caller.clone(), call_index }); Ok(()) } diff --git a/frame/membership/src/lib.rs b/frame/membership/src/lib.rs index 8fa2abb0ad3f..6cd8c13f39af 100644 --- a/frame/membership/src/lib.rs +++ b/frame/membership/src/lib.rs @@ -143,7 +143,7 @@ pub mod pallet { /// One of the members' keys changed. KeyChanged, /// Phantom member, never used. - Dummy(PhantomData<(T::AccountId, >::Event)>), + Dummy { _phantom_data: PhantomData<(T::AccountId, >::Event)> }, } /// Old name generated by `decl_event`. diff --git a/frame/multisig/src/lib.rs b/frame/multisig/src/lib.rs index c38ddf1793ee..757a99b42dae 100644 --- a/frame/multisig/src/lib.rs +++ b/frame/multisig/src/lib.rs @@ -205,21 +205,30 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { - /// A new multisig operation has begun. \[approving, multisig, call_hash\] - NewMultisig(T::AccountId, T::AccountId, CallHash), + /// A new multisig operation has begun. + NewMultisig { approving: T::AccountId, multisig: T::AccountId, call_hash: CallHash }, /// A multisig operation has been approved by someone. - /// \[approving, timepoint, multisig, call_hash\] - MultisigApproval(T::AccountId, Timepoint, T::AccountId, CallHash), - /// A multisig operation has been executed. \[approving, timepoint, multisig, call_hash\] - MultisigExecuted( - T::AccountId, - Timepoint, - T::AccountId, - CallHash, - DispatchResult, - ), - /// A multisig operation has been cancelled. \[canceling, timepoint, multisig, call_hash\] - MultisigCancelled(T::AccountId, Timepoint, T::AccountId, CallHash), + MultisigApproval { + approving: T::AccountId, + timepoint: Timepoint, + multisig: T::AccountId, + call_hash: CallHash, + }, + /// A multisig operation has been executed. + MultisigExecuted { + approving: T::AccountId, + timepoint: Timepoint, + multisig: T::AccountId, + call_hash: CallHash, + result: DispatchResult, + }, + /// A multisig operation has been cancelled. + MultisigCancelled { + cancelling: T::AccountId, + timepoint: Timepoint, + multisig: T::AccountId, + call_hash: CallHash, + }, } #[pallet::hooks] @@ -481,7 +490,12 @@ pub mod pallet { >::remove(&id, &call_hash); Self::clear_call(&call_hash); - Self::deposit_event(Event::MultisigCancelled(who, timepoint, id, call_hash)); + Self::deposit_event(Event::MultisigCancelled { + cancelling: who, + timepoint, + multisig: id, + call_hash, + }); Ok(()) } } @@ -557,13 +571,13 @@ impl Pallet { T::Currency::unreserve(&m.depositor, m.deposit); let result = call.dispatch(RawOrigin::Signed(id.clone()).into()); - Self::deposit_event(Event::MultisigExecuted( - who, + Self::deposit_event(Event::MultisigExecuted { + approving: who, timepoint, - id, + multisig: id, call_hash, - result.map(|_| ()).map_err(|e| e.error), - )); + result: result.map(|_| ()).map_err(|e| e.error), + }); Ok(get_result_weight(result) .map(|actual_weight| { T::WeightInfo::as_multi_complete( @@ -594,7 +608,12 @@ impl Pallet { // Record approval. m.approvals.insert(pos, who.clone()); >::insert(&id, call_hash, m); - Self::deposit_event(Event::MultisigApproval(who, timepoint, id, call_hash)); + Self::deposit_event(Event::MultisigApproval { + approving: who, + timepoint, + multisig: id, + call_hash, + }); } else { // If we already approved and didn't store the Call, then this was useless and // we report an error. @@ -638,7 +657,7 @@ impl Pallet { approvals: vec![who.clone()], }, ); - Self::deposit_event(Event::NewMultisig(who, id, call_hash)); + Self::deposit_event(Event::NewMultisig { approving: who, multisig: id, call_hash }); let final_weight = if stored { T::WeightInfo::as_multi_create_store(other_signatories_len as u32, call_len as u32) diff --git a/frame/multisig/src/tests.rs b/frame/multisig/src/tests.rs index c5607c80abce..523aefd1e753 100644 --- a/frame/multisig/src/tests.rs +++ b/frame/multisig/src/tests.rs @@ -706,7 +706,14 @@ fn multisig_2_of_3_cannot_reissue_same_call() { let err = DispatchError::from(BalancesError::::InsufficientBalance).stripped(); System::assert_last_event( - pallet_multisig::Event::MultisigExecuted(3, now(), multi, hash, Err(err)).into(), + pallet_multisig::Event::MultisigExecuted { + approving: 3, + timepoint: now(), + multisig: multi, + call_hash: hash, + result: Err(err), + } + .into(), ); }); } diff --git a/frame/nicks/src/lib.rs b/frame/nicks/src/lib.rs index f502a683f633..438929576269 100644 --- a/frame/nicks/src/lib.rs +++ b/frame/nicks/src/lib.rs @@ -89,16 +89,16 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { - /// A name was set. \[who\] - NameSet(T::AccountId), - /// A name was forcibly set. \[target\] - NameForced(T::AccountId), - /// A name was changed. \[who\] - NameChanged(T::AccountId), - /// A name was cleared, and the given balance returned. \[who, deposit\] - NameCleared(T::AccountId, BalanceOf), - /// A name was removed and the given balance slashed. \[target, deposit\] - NameKilled(T::AccountId, BalanceOf), + /// A name was set. + NameSet { who: T::AccountId }, + /// A name was forcibly set. + NameForced { target: T::AccountId }, + /// A name was changed. + NameChanged { who: T::AccountId }, + /// A name was cleared, and the given balance returned. + NameCleared { who: T::AccountId, deposit: BalanceOf }, + /// A name was removed and the given balance slashed. + NameKilled { target: T::AccountId, deposit: BalanceOf }, } /// Error for the nicks pallet. @@ -147,12 +147,12 @@ pub mod pallet { ensure!(name.len() <= T::MaxLength::get() as usize, Error::::TooLong); let deposit = if let Some((_, deposit)) = >::get(&sender) { - Self::deposit_event(Event::::NameChanged(sender.clone())); + Self::deposit_event(Event::::NameChanged { who: sender.clone() }); deposit } else { let deposit = T::ReservationFee::get(); T::Currency::reserve(&sender, deposit.clone())?; - Self::deposit_event(Event::::NameSet(sender.clone())); + Self::deposit_event(Event::::NameSet { who: sender.clone() }); deposit }; @@ -179,7 +179,7 @@ pub mod pallet { let err_amount = T::Currency::unreserve(&sender, deposit.clone()); debug_assert!(err_amount.is_zero()); - Self::deposit_event(Event::::NameCleared(sender, deposit)); + Self::deposit_event(Event::::NameCleared { who: sender, deposit }); Ok(()) } @@ -210,7 +210,7 @@ pub mod pallet { // Slash their deposit from them. T::Slashed::on_unbalanced(T::Currency::slash_reserved(&target, deposit.clone()).0); - Self::deposit_event(Event::::NameKilled(target, deposit)); + Self::deposit_event(Event::::NameKilled { target, deposit }); Ok(()) } @@ -238,7 +238,7 @@ pub mod pallet { let deposit = >::get(&target).map(|x| x.1).unwrap_or_else(Zero::zero); >::insert(&target, (name, deposit)); - Self::deposit_event(Event::::NameForced(target)); + Self::deposit_event(Event::::NameForced { target }); Ok(()) } } diff --git a/frame/node-authorization/src/lib.rs b/frame/node-authorization/src/lib.rs index 016f12d2eb83..6e3ec58ba63f 100644 --- a/frame/node-authorization/src/lib.rs +++ b/frame/node-authorization/src/lib.rs @@ -128,24 +128,24 @@ pub mod pallet { #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { /// The given well known node was added. - NodeAdded(PeerId, T::AccountId), + NodeAdded { peer_id: PeerId, who: T::AccountId }, /// The given well known node was removed. - NodeRemoved(PeerId), + NodeRemoved { peer_id: PeerId }, /// The given well known node was swapped; first item was removed, /// the latter was added. - NodeSwapped(PeerId, PeerId), + NodeSwapped { removed: PeerId, added: PeerId }, /// The given well known nodes were reset. - NodesReset(Vec<(PeerId, T::AccountId)>), + NodesReset { nodes: Vec<(PeerId, T::AccountId)> }, /// The given node was claimed by a user. - NodeClaimed(PeerId, T::AccountId), + NodeClaimed { peer_id: PeerId, who: T::AccountId }, /// The given claim was removed by its owner. - ClaimRemoved(PeerId, T::AccountId), + ClaimRemoved { peer_id: PeerId, who: T::AccountId }, /// The node was transferred to another account. - NodeTransferred(PeerId, T::AccountId), + NodeTransferred { peer_id: PeerId, target: T::AccountId }, /// The allowed connections were added to a node. - ConnectionsAdded(PeerId, Vec), + ConnectionsAdded { peer_id: PeerId, allowed_connections: Vec }, /// The allowed connections were removed from a node. - ConnectionsRemoved(PeerId, Vec), + ConnectionsRemoved { peer_id: PeerId, allowed_connections: Vec }, } #[pallet::error] @@ -224,7 +224,7 @@ pub mod pallet { WellKnownNodes::::put(&nodes); >::insert(&node, &owner); - Self::deposit_event(Event::NodeAdded(node, owner)); + Self::deposit_event(Event::NodeAdded { peer_id: node, who: owner }); Ok(()) } @@ -248,7 +248,7 @@ pub mod pallet { >::remove(&node); AdditionalConnections::::remove(&node); - Self::deposit_event(Event::NodeRemoved(node)); + Self::deposit_event(Event::NodeRemoved { peer_id: node }); Ok(()) } @@ -284,7 +284,7 @@ pub mod pallet { Owners::::swap(&remove, &add); AdditionalConnections::::swap(&remove, &add); - Self::deposit_event(Event::NodeSwapped(remove, add)); + Self::deposit_event(Event::NodeSwapped { removed: remove, added: add }); Ok(()) } @@ -305,7 +305,7 @@ pub mod pallet { Self::initialize_nodes(&nodes); - Self::deposit_event(Event::NodesReset(nodes)); + Self::deposit_event(Event::NodesReset { nodes }); Ok(()) } @@ -321,7 +321,7 @@ pub mod pallet { ensure!(!Owners::::contains_key(&node), Error::::AlreadyClaimed); Owners::::insert(&node, &sender); - Self::deposit_event(Event::NodeClaimed(node, sender)); + Self::deposit_event(Event::NodeClaimed { peer_id: node, who: sender }); Ok(()) } @@ -342,7 +342,7 @@ pub mod pallet { Owners::::remove(&node); AdditionalConnections::::remove(&node); - Self::deposit_event(Event::ClaimRemoved(node, sender)); + Self::deposit_event(Event::ClaimRemoved { peer_id: node, who: sender }); Ok(()) } @@ -364,7 +364,7 @@ pub mod pallet { Owners::::insert(&node, &owner); - Self::deposit_event(Event::NodeTransferred(node, owner)); + Self::deposit_event(Event::NodeTransferred { peer_id: node, target: owner }); Ok(()) } @@ -395,7 +395,10 @@ pub mod pallet { AdditionalConnections::::insert(&node, nodes); - Self::deposit_event(Event::ConnectionsAdded(node, connections)); + Self::deposit_event(Event::ConnectionsAdded { + peer_id: node, + allowed_connections: connections, + }); Ok(()) } @@ -423,7 +426,10 @@ pub mod pallet { AdditionalConnections::::insert(&node, nodes); - Self::deposit_event(Event::ConnectionsRemoved(node, connections)); + Self::deposit_event(Event::ConnectionsRemoved { + peer_id: node, + allowed_connections: connections, + }); Ok(()) } } diff --git a/frame/offences/benchmarking/src/lib.rs b/frame/offences/benchmarking/src/lib.rs index c920b0b900df..33ebe23d8d1f 100644 --- a/frame/offences/benchmarking/src/lib.rs +++ b/frame/offences/benchmarking/src/lib.rs @@ -315,13 +315,13 @@ benchmarks! { ::Event::from(StakingEvent::::Slashed(id, BalanceOf::::from(slash_amount))) ); let balance_slash = |id| core::iter::once( - ::Event::from(pallet_balances::Event::::Slashed(id, slash_amount.into())) + ::Event::from(pallet_balances::Event::::Slashed{who: id, amount: slash_amount.into()}) ); let chill = |id| core::iter::once( ::Event::from(StakingEvent::::Chilled(id)) ); let balance_deposit = |id, amount: u32| - ::Event::from(pallet_balances::Event::::Deposit(id, amount.into())); + ::Event::from(pallet_balances::Event::::Deposit{who: id, amount: amount.into()}); let mut first = true; let slash_events = raw_offenders.into_iter() .flat_map(|offender| { @@ -344,7 +344,7 @@ benchmarks! { balance_deposit(reporter.clone(), reward.into()).into(), frame_system::Event::::NewAccount(reporter.clone()).into(), ::Event::from( - pallet_balances::Event::::Endowed(reporter.clone(), reward.into()) + pallet_balances::Event::::Endowed{account: reporter.clone(), free_balance: reward.into()} ).into(), ]) .collect::>(); @@ -371,10 +371,10 @@ benchmarks! { std::iter::empty() .chain(slash_events.into_iter().map(Into::into)) .chain(std::iter::once(::Event::from( - pallet_offences::Event::Offence( - UnresponsivenessOffence::::ID, - 0_u32.to_le_bytes().to_vec(), - ) + pallet_offences::Event::Offence{ + kind: UnresponsivenessOffence::::ID, + timeslot: 0_u32.to_le_bytes().to_vec(), + } ).into())) ); } diff --git a/frame/offences/src/lib.rs b/frame/offences/src/lib.rs index d50bc55f8835..ddae73e280d5 100644 --- a/frame/offences/src/lib.rs +++ b/frame/offences/src/lib.rs @@ -108,7 +108,7 @@ pub mod pallet { /// There is an offence reported of the given `kind` happened at the `session_index` and /// (kind-specific) time slot. This event is not deposited for duplicate slashes. /// \[kind, timeslot\]. - Offence(Kind, OpaqueTimeSlot), + Offence { kind: Kind, timeslot: OpaqueTimeSlot }, } #[pallet::hooks] @@ -153,7 +153,7 @@ where ); // Deposit the event. - Self::deposit_event(Event::Offence(O::ID, time_slot.encode())); + Self::deposit_event(Event::Offence { kind: O::ID, timeslot: time_slot.encode() }); Ok(()) } diff --git a/frame/offences/src/tests.rs b/frame/offences/src/tests.rs index 18cfa9410a6c..8c4fdcc08f99 100644 --- a/frame/offences/src/tests.rs +++ b/frame/offences/src/tests.rs @@ -114,7 +114,10 @@ fn should_deposit_event() { System::events(), vec![EventRecord { phase: Phase::Initialization, - event: Event::Offences(crate::Event::Offence(KIND, time_slot.encode())), + event: Event::Offences(crate::Event::Offence { + kind: KIND, + timeslot: time_slot.encode() + }), topics: vec![], }] ); @@ -145,7 +148,10 @@ fn doesnt_deposit_event_for_dups() { System::events(), vec![EventRecord { phase: Phase::Initialization, - event: Event::Offences(crate::Event::Offence(KIND, time_slot.encode())), + event: Event::Offences(crate::Event::Offence { + kind: KIND, + timeslot: time_slot.encode() + }), topics: vec![], }] ); diff --git a/frame/proxy/src/benchmarking.rs b/frame/proxy/src/benchmarking.rs index 1eb3ec577054..224610b65185 100644 --- a/frame/proxy/src/benchmarking.rs +++ b/frame/proxy/src/benchmarking.rs @@ -86,7 +86,7 @@ benchmarks! { let call: ::Call = frame_system::Call::::remark { remark: vec![] }.into(); }: _(RawOrigin::Signed(caller), real, Some(T::ProxyType::default()), Box::new(call)) verify { - assert_last_event::(Event::ProxyExecuted(Ok(())).into()) + assert_last_event::(Event::ProxyExecuted { result: Ok(()) }.into()) } proxy_announced { @@ -107,7 +107,7 @@ benchmarks! { add_announcements::(a, Some(delegate.clone()), None)?; }: _(RawOrigin::Signed(caller), delegate, real, Some(T::ProxyType::default()), Box::new(call)) verify { - assert_last_event::(Event::ProxyExecuted(Ok(())).into()) + assert_last_event::(Event::ProxyExecuted { result: Ok(()) }.into()) } remove_announcement { @@ -165,7 +165,7 @@ benchmarks! { let call_hash = T::CallHasher::hash_of(&call); }: _(RawOrigin::Signed(caller.clone()), real.clone(), call_hash) verify { - assert_last_event::(Event::Announced(real, caller, call_hash).into()); + assert_last_event::(Event::Announced { real, proxy: caller, call_hash }.into()); } add_proxy { @@ -216,12 +216,12 @@ benchmarks! { ) verify { let anon_account = Pallet::::anonymous_account(&caller, &T::ProxyType::default(), 0, None); - assert_last_event::(Event::AnonymousCreated( - anon_account, - caller, - T::ProxyType::default(), - 0, - ).into()); + assert_last_event::(Event::AnonymousCreated { + anonymous: anon_account, + who: caller, + proxy_type: T::ProxyType::default(), + disambiguation_index: 0, + }.into()); } kill_anonymous { diff --git a/frame/proxy/src/lib.rs b/frame/proxy/src/lib.rs index b73101fa7348..695fa077f98d 100644 --- a/frame/proxy/src/lib.rs +++ b/frame/proxy/src/lib.rs @@ -327,7 +327,12 @@ pub mod pallet { T::Currency::reserve(&who, deposit)?; Proxies::::insert(&anonymous, (bounded_proxies, deposit)); - Self::deposit_event(Event::AnonymousCreated(anonymous, who, proxy_type, index)); + Self::deposit_event(Event::AnonymousCreated { + anonymous, + who, + proxy_type, + disambiguation_index: index, + }); Ok(()) } @@ -427,7 +432,7 @@ pub mod pallet { }) .map(|d| *deposit = d) })?; - Self::deposit_event(Event::Announced(real, who, call_hash)); + Self::deposit_event(Event::Announced { real, proxy: who, call_hash }); Ok(()) } @@ -547,16 +552,25 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { - /// A proxy was executed correctly, with the given \[result\]. - ProxyExecuted(DispatchResult), + /// A proxy was executed correctly, with the given. + ProxyExecuted { result: DispatchResult }, /// Anonymous account has been created by new proxy with given - /// disambiguation index and proxy type. \[anonymous, who, proxy_type, - /// disambiguation_index\] - AnonymousCreated(T::AccountId, T::AccountId, T::ProxyType, u16), - /// An announcement was placed to make a call in the future. \[real, proxy, call_hash\] - Announced(T::AccountId, T::AccountId, CallHashOf), - /// A proxy was added. \[delegator, delegatee, proxy_type, delay\] - ProxyAdded(T::AccountId, T::AccountId, T::ProxyType, T::BlockNumber), + /// disambiguation index and proxy type. + AnonymousCreated { + anonymous: T::AccountId, + who: T::AccountId, + proxy_type: T::ProxyType, + disambiguation_index: u16, + }, + /// An announcement was placed to make a call in the future. + Announced { real: T::AccountId, proxy: T::AccountId, call_hash: CallHashOf }, + /// A proxy was added. + ProxyAdded { + delegator: T::AccountId, + delegatee: T::AccountId, + proxy_type: T::ProxyType, + delay: T::BlockNumber, + }, } /// Old name generated by `decl_event`. @@ -672,12 +686,12 @@ impl Pallet { T::Currency::unreserve(delegator, *deposit - new_deposit); } *deposit = new_deposit; - Self::deposit_event(Event::::ProxyAdded( - delegator.clone(), + Self::deposit_event(Event::::ProxyAdded { + delegator: delegator.clone(), delegatee, proxy_type, delay, - )); + }); Ok(()) }) } @@ -800,6 +814,6 @@ impl Pallet { } }); let e = call.dispatch(origin); - Self::deposit_event(Event::ProxyExecuted(e.map(|_| ()).map_err(|e| e.error))); + Self::deposit_event(Event::ProxyExecuted { result: e.map(|_| ()).map_err(|e| e.error) }); } } diff --git a/frame/proxy/src/tests.rs b/frame/proxy/src/tests.rs index ed21a80f6213..d3565525910f 100644 --- a/frame/proxy/src/tests.rs +++ b/frame/proxy/src/tests.rs @@ -211,7 +211,15 @@ fn call_transfer(dest: u64, value: u64) -> Call { fn announcement_works() { new_test_ext().execute_with(|| { assert_ok!(Proxy::add_proxy(Origin::signed(1), 3, ProxyType::Any, 1)); - System::assert_last_event(ProxyEvent::ProxyAdded(1, 3, ProxyType::Any, 1).into()); + System::assert_last_event( + ProxyEvent::ProxyAdded { + delegator: 1, + delegatee: 3, + proxy_type: ProxyType::Any, + delay: 1, + } + .into(), + ); assert_ok!(Proxy::add_proxy(Origin::signed(2), 3, ProxyType::Any, 1)); assert_eq!(Balances::reserved_balance(3), 0); @@ -332,12 +340,12 @@ fn filtering_works() { let call = Box::new(call_transfer(6, 1)); assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, call.clone())); - System::assert_last_event(ProxyEvent::ProxyExecuted(Ok(())).into()); + System::assert_last_event(ProxyEvent::ProxyExecuted { result: Ok(()) }.into()); assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone())); - System::assert_last_event(ProxyEvent::ProxyExecuted(Ok(())).into()); + System::assert_last_event(ProxyEvent::ProxyExecuted { result: Ok(()) }.into()); assert_ok!(Proxy::proxy(Origin::signed(4), 1, None, call.clone())); System::assert_last_event( - ProxyEvent::ProxyExecuted(Err(SystemError::CallFiltered.into())).into(), + ProxyEvent::ProxyExecuted { result: Err(SystemError::CallFiltered.into()) }.into(), ); let derivative_id = Utility::derivative_account_id(1, 0); @@ -347,31 +355,31 @@ fn filtering_works() { let call = Box::new(Call::Utility(UtilityCall::as_derivative { index: 0, call: inner.clone() })); assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, call.clone())); - System::assert_last_event(ProxyEvent::ProxyExecuted(Ok(())).into()); + System::assert_last_event(ProxyEvent::ProxyExecuted { result: Ok(()) }.into()); assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone())); System::assert_last_event( - ProxyEvent::ProxyExecuted(Err(SystemError::CallFiltered.into())).into(), + ProxyEvent::ProxyExecuted { result: Err(SystemError::CallFiltered.into()) }.into(), ); assert_ok!(Proxy::proxy(Origin::signed(4), 1, None, call.clone())); System::assert_last_event( - ProxyEvent::ProxyExecuted(Err(SystemError::CallFiltered.into())).into(), + ProxyEvent::ProxyExecuted { result: Err(SystemError::CallFiltered.into()) }.into(), ); let call = Box::new(Call::Utility(UtilityCall::batch { calls: vec![*inner] })); assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, call.clone())); expect_events(vec![ UtilityEvent::BatchCompleted.into(), - ProxyEvent::ProxyExecuted(Ok(())).into(), + ProxyEvent::ProxyExecuted { result: Ok(()) }.into(), ]); assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone())); System::assert_last_event( - ProxyEvent::ProxyExecuted(Err(SystemError::CallFiltered.into())).into(), + ProxyEvent::ProxyExecuted { result: Err(SystemError::CallFiltered.into()) }.into(), ); assert_ok!(Proxy::proxy(Origin::signed(4), 1, None, call.clone())); expect_events(vec![ UtilityEvent::BatchInterrupted { index: 0, error: SystemError::CallFiltered.into() } .into(), - ProxyEvent::ProxyExecuted(Ok(())).into(), + ProxyEvent::ProxyExecuted { result: Ok(()) }.into(), ]); let inner = @@ -380,32 +388,32 @@ fn filtering_works() { assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, call.clone())); expect_events(vec![ UtilityEvent::BatchCompleted.into(), - ProxyEvent::ProxyExecuted(Ok(())).into(), + ProxyEvent::ProxyExecuted { result: Ok(()) }.into(), ]); assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone())); System::assert_last_event( - ProxyEvent::ProxyExecuted(Err(SystemError::CallFiltered.into())).into(), + ProxyEvent::ProxyExecuted { result: Err(SystemError::CallFiltered.into()) }.into(), ); assert_ok!(Proxy::proxy(Origin::signed(4), 1, None, call.clone())); expect_events(vec![ UtilityEvent::BatchInterrupted { index: 0, error: SystemError::CallFiltered.into() } .into(), - ProxyEvent::ProxyExecuted(Ok(())).into(), + ProxyEvent::ProxyExecuted { result: Ok(()) }.into(), ]); let call = Box::new(Call::Proxy(ProxyCall::remove_proxies {})); assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone())); System::assert_last_event( - ProxyEvent::ProxyExecuted(Err(SystemError::CallFiltered.into())).into(), + ProxyEvent::ProxyExecuted { result: Err(SystemError::CallFiltered.into()) }.into(), ); assert_ok!(Proxy::proxy(Origin::signed(4), 1, None, call.clone())); System::assert_last_event( - ProxyEvent::ProxyExecuted(Err(SystemError::CallFiltered.into())).into(), + ProxyEvent::ProxyExecuted { result: Err(SystemError::CallFiltered.into()) }.into(), ); assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, call.clone())); expect_events(vec![ - BalancesEvent::::Unreserved(1, 5).into(), - ProxyEvent::ProxyExecuted(Ok(())).into(), + BalancesEvent::::Unreserved { who: 1, amount: 5 }.into(), + ProxyEvent::ProxyExecuted { result: Ok(()) }.into(), ]); }); } @@ -476,13 +484,13 @@ fn proxying_works() { Error::::NotProxy ); assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, call.clone())); - System::assert_last_event(ProxyEvent::ProxyExecuted(Ok(())).into()); + System::assert_last_event(ProxyEvent::ProxyExecuted { result: Ok(()) }.into()); assert_eq!(Balances::free_balance(6), 1); let call = Box::new(Call::System(SystemCall::set_code { code: vec![] })); assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone())); System::assert_last_event( - ProxyEvent::ProxyExecuted(Err(SystemError::CallFiltered.into())).into(), + ProxyEvent::ProxyExecuted { result: Err(SystemError::CallFiltered.into()) }.into(), ); let call = @@ -490,10 +498,10 @@ fn proxying_works() { assert_ok!(Call::Proxy(super::Call::new_call_variant_proxy(1, None, call.clone())) .dispatch(Origin::signed(2))); System::assert_last_event( - ProxyEvent::ProxyExecuted(Err(SystemError::CallFiltered.into())).into(), + ProxyEvent::ProxyExecuted { result: Err(SystemError::CallFiltered.into()) }.into(), ); assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone())); - System::assert_last_event(ProxyEvent::ProxyExecuted(Ok(())).into()); + System::assert_last_event(ProxyEvent::ProxyExecuted { result: Ok(()) }.into()); assert_eq!(Balances::free_balance(6), 2); }); } @@ -504,7 +512,13 @@ fn anonymous_works() { assert_ok!(Proxy::anonymous(Origin::signed(1), ProxyType::Any, 0, 0)); let anon = Proxy::anonymous_account(&1, &ProxyType::Any, 0, None); System::assert_last_event( - ProxyEvent::AnonymousCreated(anon.clone(), 1, ProxyType::Any, 0).into(), + ProxyEvent::AnonymousCreated { + anonymous: anon.clone(), + who: 1, + proxy_type: ProxyType::Any, + disambiguation_index: 0, + } + .into(), ); // other calls to anonymous allowed as long as they're not exactly the same. @@ -525,7 +539,7 @@ fn anonymous_works() { let call = Box::new(call_transfer(6, 1)); assert_ok!(Balances::transfer(Origin::signed(3), anon, 5)); assert_ok!(Proxy::proxy(Origin::signed(1), anon, None, call)); - System::assert_last_event(ProxyEvent::ProxyExecuted(Ok(())).into()); + System::assert_last_event(ProxyEvent::ProxyExecuted { result: Ok(()) }.into()); assert_eq!(Balances::free_balance(6), 1); let call = Box::new(Call::Proxy(ProxyCall::new_call_variant_kill_anonymous( @@ -537,7 +551,7 @@ fn anonymous_works() { ))); assert_ok!(Proxy::proxy(Origin::signed(2), anon2, None, call.clone())); let de = DispatchError::from(Error::::NoPermission).stripped(); - System::assert_last_event(ProxyEvent::ProxyExecuted(Err(de)).into()); + System::assert_last_event(ProxyEvent::ProxyExecuted { result: Err(de) }.into()); assert_noop!( Proxy::kill_anonymous(Origin::signed(1), 1, ProxyType::Any, 0, 1, 0), Error::::NoPermission diff --git a/frame/staking/src/slashing.rs b/frame/staking/src/slashing.rs index 68088d0e0d77..414c21aa347f 100644 --- a/frame/staking/src/slashing.rs +++ b/frame/staking/src/slashing.rs @@ -190,7 +190,7 @@ pub(crate) struct SpanRecord { impl SpanRecord { /// The value of stash balance slashed in this span. #[cfg(test)] - pub(crate) fn amount_slashed(&self) -> &Balance { + pub(crate) fn amount(&self) -> &Balance { &self.slashed } } diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 8e8a7ee636d8..8f13fd785080 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -2469,7 +2469,7 @@ fn garbage_collection_after_slashing() { assert_eq!(Balances::free_balance(11), 2000 - 200); assert!(::SlashingSpans::get(&11).is_some()); - assert_eq!(::SpanSlash::get(&(11, 0)).amount_slashed(), &200); + assert_eq!(::SpanSlash::get(&(11, 0)).amount(), &200); on_offence_now( &[OffenceDetails { @@ -2496,7 +2496,7 @@ fn garbage_collection_after_slashing() { assert_ok!(Staking::reap_stash(Origin::signed(20), 11, 2)); assert!(::SlashingSpans::get(&11).is_none()); - assert_eq!(::SpanSlash::get(&(11, 0)).amount_slashed(), &0); + assert_eq!(::SpanSlash::get(&(11, 0)).amount(), &0); }) } diff --git a/frame/transaction-payment/src/lib.rs b/frame/transaction-payment/src/lib.rs index 64cd5d529063..a0d8aeb11706 100644 --- a/frame/transaction-payment/src/lib.rs +++ b/frame/transaction-payment/src/lib.rs @@ -1363,9 +1363,11 @@ mod tests { )); assert_eq!(Balances::free_balance(2), 0); // Transfer Event - System::assert_has_event(Event::Balances(pallet_balances::Event::Transfer( - 2, 3, 80, - ))); + System::assert_has_event(Event::Balances(pallet_balances::Event::Transfer { + from: 2, + to: 3, + amount: 80, + })); // Killed Event System::assert_has_event(Event::System(system::Event::KilledAccount(2))); }); From 07d98e28cd7a79e45f02a982af14fbde929d8a16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Tue, 16 Nov 2021 07:52:27 +0100 Subject: [PATCH 190/695] Forward wasmer-sandbox feature to sp-sandbox (#10268) --- Cargo.lock | 1 + bin/node/runtime/Cargo.toml | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 99b2b53a74a4..d93e70162926 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4758,6 +4758,7 @@ dependencies = [ "sp-npos-elections", "sp-offchain", "sp-runtime", + "sp-sandbox", "sp-session", "sp-staking", "sp-std", diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index d086b6f12d59..9a481120fd01 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -41,6 +41,7 @@ sp-transaction-pool = { version = "4.0.0-dev", default-features = false, path = sp-version = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/version" } sp-npos-elections = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/npos-elections" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/io" } +sp-sandbox = { version = "0.10.0-dev", default-features = false, path = "../../../primitives/sandbox" } # frame dependencies frame-executive = { version = "4.0.0-dev", default-features = false, path = "../../../frame/executive" } @@ -257,3 +258,8 @@ try-runtime = [ # Make contract callable functions marked as __unstable__ available. Do not enable # on live chains as those are subject to change. contracts-unstable-interface = ["pallet-contracts/unstable-interface"] +# Force `sp-sandbox` to call into the host resident executor. One still need to make sure +# that `sc-executor` gets the `wasmer-sandbox` feature which happens automatically when +# specified on the command line. +# Don't use that on a production chain. +wasmer-sandbox = ["sp-sandbox/wasmer-sandbox"] From f846ee0d56e3882cdfa78616d8e9a36885379c98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Tue, 16 Nov 2021 14:01:35 +0100 Subject: [PATCH 191/695] Cli: Introduce `--detailed-log-output` flag (#10278) * Cli: Introduce `--detailed-log-output` flag If this CLI flag is given, detailed log output will be enabled. This includes the log level, log target ad the thread name. Before this was only enabled when a log level higher than `info` should be logged. * Update client/tracing/src/logging/mod.rs Co-authored-by: David Co-authored-by: David --- client/cli/src/config.rs | 9 ++++- client/cli/src/params/shared_params.rs | 13 +++++++ client/tracing/src/logging/mod.rs | 54 ++++++++++++++++++-------- 3 files changed, 59 insertions(+), 17 deletions(-) diff --git a/client/cli/src/config.rs b/client/cli/src/config.rs index 86eeed5b4023..20e2bf0df5b2 100644 --- a/client/cli/src/config.rs +++ b/client/cli/src/config.rs @@ -547,6 +547,11 @@ pub trait CliConfiguration: Sized { Ok(self.shared_params().log_filters().join(",")) } + /// Should the detailed log output be enabled. + fn detailed_log_output(&self) -> Result { + Ok(self.shared_params().detailed_log_output()) + } + /// Is log reloading enabled? fn enable_log_reloading(&self) -> Result { Ok(self.shared_params().enable_log_reloading()) @@ -568,7 +573,9 @@ pub trait CliConfiguration: Sized { sp_panic_handler::set(&C::support_url(), &C::impl_version()); let mut logger = LoggerBuilder::new(self.log_filters()?); - logger.with_log_reloading(self.enable_log_reloading()?); + logger + .with_log_reloading(self.enable_log_reloading()?) + .with_detailed_output(self.detailed_log_output()?); if let Some(tracing_targets) = self.tracing_targets()? { let tracing_receiver = self.tracing_receiver()?; diff --git a/client/cli/src/params/shared_params.rs b/client/cli/src/params/shared_params.rs index 58aabb3148dd..4a6fe0d2743e 100644 --- a/client/cli/src/params/shared_params.rs +++ b/client/cli/src/params/shared_params.rs @@ -49,6 +49,14 @@ pub struct SharedParams { #[structopt(short = "l", long, value_name = "LOG_PATTERN")] pub log: Vec, + /// Enable detailed log output. + /// + /// This includes displaying the log target, log level and thread name. + /// + /// This is automatically enabled when something is logged with any higher level than `info`. + #[structopt(long)] + pub detailed_log_output: bool, + /// Disable log color output. #[structopt(long)] pub disable_log_color: bool, @@ -107,6 +115,11 @@ impl SharedParams { &self.log } + /// Should the detailed log output be enabled. + pub fn detailed_log_output(&self) -> bool { + self.detailed_log_output + } + /// Should the log color output be disabled? pub fn disable_log_color(&self) -> bool { self.disable_log_color diff --git a/client/tracing/src/logging/mod.rs b/client/tracing/src/logging/mod.rs index 49807098d1cf..521cfca30e29 100644 --- a/client/tracing/src/logging/mod.rs +++ b/client/tracing/src/logging/mod.rs @@ -95,6 +95,7 @@ fn prepare_subscriber( directives: &str, profiling_targets: Option<&str>, force_colors: Option, + detailed_output: bool, builder_hook: impl Fn( SubscriberBuilder, ) -> SubscriberBuilder, @@ -157,19 +158,19 @@ where tracing_log::LogTracer::builder().with_max_level(max_level).init()?; // If we're only logging `INFO` entries then we'll use a simplified logging format. - let simple = match max_level_hint { - Some(level) if level <= tracing_subscriber::filter::LevelFilter::INFO => true, - _ => false, - }; + let detailed_output = match max_level_hint { + Some(level) if level <= tracing_subscriber::filter::LevelFilter::INFO => false, + _ => true, + } || detailed_output; let enable_color = force_colors.unwrap_or_else(|| atty::is(atty::Stream::Stderr)); - let timer = fast_local_time::FastLocalTime { with_fractional: !simple }; + let timer = fast_local_time::FastLocalTime { with_fractional: detailed_output }; let event_format = EventFormat { timer, - display_target: !simple, - display_level: !simple, - display_thread_name: !simple, + display_target: detailed_output, + display_level: detailed_output, + display_thread_name: detailed_output, enable_color, dup_to_stdout: !atty::is(atty::Stream::Stderr) && atty::is(atty::Stream::Stdout), }; @@ -194,6 +195,7 @@ pub struct LoggerBuilder { profiling: Option<(crate::TracingReceiver, String)>, log_reloading: bool, force_colors: Option, + detailed_output: bool, } impl LoggerBuilder { @@ -204,6 +206,7 @@ impl LoggerBuilder { profiling: None, log_reloading: false, force_colors: None, + detailed_output: false, } } @@ -223,6 +226,17 @@ impl LoggerBuilder { self } + /// Whether detailed log output should be enabled. + /// + /// This includes showing the log target, log level and thread name. + /// + /// This will be automatically enabled when there is a log level enabled that is higher than + /// `info`. + pub fn with_detailed_output(&mut self, detailed: bool) -> &mut Self { + self.detailed_output = detailed; + self + } + /// Force enable/disable colors. pub fn with_colors(&mut self, enable: bool) -> &mut Self { self.force_colors = Some(enable); @@ -239,6 +253,7 @@ impl LoggerBuilder { &self.directives, Some(&profiling_targets), self.force_colors, + self.detailed_output, |builder| enable_log_reloading!(builder), )?; let profiling = crate::ProfilingLayer::new(tracing_receiver, &profiling_targets); @@ -251,6 +266,7 @@ impl LoggerBuilder { &self.directives, Some(&profiling_targets), self.force_colors, + self.detailed_output, |builder| builder, )?; let profiling = crate::ProfilingLayer::new(tracing_receiver, &profiling_targets); @@ -261,19 +277,25 @@ impl LoggerBuilder { } } else { if self.log_reloading { - let subscriber = - prepare_subscriber(&self.directives, None, self.force_colors, |builder| { - enable_log_reloading!(builder) - })?; + let subscriber = prepare_subscriber( + &self.directives, + None, + self.force_colors, + self.detailed_output, + |builder| enable_log_reloading!(builder), + )?; tracing::subscriber::set_global_default(subscriber)?; Ok(()) } else { - let subscriber = - prepare_subscriber(&self.directives, None, self.force_colors, |builder| { - builder - })?; + let subscriber = prepare_subscriber( + &self.directives, + None, + self.force_colors, + self.detailed_output, + |builder| builder, + )?; tracing::subscriber::set_global_default(subscriber)?; From 74c39a23076bfd23328e1f1d1eed2f508a28247d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Tue, 16 Nov 2021 14:02:04 +0100 Subject: [PATCH 192/695] Vesting: Fix `post_migration` check (#10280) * Vesting: Fix `post_migration` check As the vesting migration could already have been done, people could already have started to merge schedules. * :facepalm: --- frame/vesting/src/migrations.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frame/vesting/src/migrations.rs b/frame/vesting/src/migrations.rs index 086257d285ea..f8024926f34a 100644 --- a/frame/vesting/src/migrations.rs +++ b/frame/vesting/src/migrations.rs @@ -70,7 +70,7 @@ pub(crate) mod v1 { for (_key, schedules) in Vesting::::iter() { assert!( - schedules.len() == 1, + schedules.len() >= 1, "A bounded vec with incorrect count of items was created." ); From 9fec502b0310de85cdfab15cefe467e86d843233 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Nov 2021 14:03:48 +0100 Subject: [PATCH 193/695] Bump handlebars from 3.5.3 to 4.1.4 (#10273) Bumps [handlebars](https://github.com/sunng87/handlebars-rust) from 3.5.3 to 4.1.4. - [Release notes](https://github.com/sunng87/handlebars-rust/releases) - [Changelog](https://github.com/sunng87/handlebars-rust/blob/master/CHANGELOG.md) - [Commits](https://github.com/sunng87/handlebars-rust/compare/v3.5.3...v4.1.4) --- updated-dependencies: - dependency-name: handlebars dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- utils/frame/benchmarking-cli/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d93e70162926..f1e8b00c6eb0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2529,9 +2529,9 @@ checksum = "62aca2aba2d62b4a7f5b33f3712cb1b0692779a56fb510499d5c0aa594daeaf3" [[package]] name = "handlebars" -version = "3.5.3" +version = "4.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb0867bbc5a3da37a753e78021d5fcf8a4db00e18dd2dd90fd36e24190e162d" +checksum = "e1874024f4a29f47d609014caec0b1c866f1c1eb0661a09c9733ecc4757f5f88" dependencies = [ "log 0.4.14", "pest", diff --git a/utils/frame/benchmarking-cli/Cargo.toml b/utils/frame/benchmarking-cli/Cargo.toml index 03520f9cbd5d..fab2b963239d 100644 --- a/utils/frame/benchmarking-cli/Cargo.toml +++ b/utils/frame/benchmarking-cli/Cargo.toml @@ -28,7 +28,7 @@ codec = { version = "2.0.0", package = "parity-scale-codec" } structopt = "0.3.25" chrono = "0.4" serde = "1.0.126" -handlebars = "3.5.0" +handlebars = "4.1.4" Inflector = "0.11.4" linked-hash-map = "0.5.4" log = "0.4.8" From 9a00c43a1a81217548b3b7853271f07de6a6b858 Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Tue, 16 Nov 2021 14:17:19 +0000 Subject: [PATCH 194/695] Update mod.rs (#10277) As many people are unbonding, I've had to explain this to a handful of people recently. This improves the error message a bit and puts it in the error description, so that it is shown in the front page of all explorers if `unbond` fails, hopefully making it clear. --- frame/staking/src/pallet/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 197c2eed325a..ec7e86af958f 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -608,7 +608,9 @@ pub mod pallet { DuplicateIndex, /// Slash record index out of bounds. InvalidSlashIndex, - /// Can not bond with value less than minimum required. + /// Cannot have a validator or nominator role, with value less than the minimum defined by + /// governance (see `MinValidatorBond` and `MinNominatorBond`). If unbonding is the + /// intention, `chill` first to remove one's role as validator/nominator. InsufficientBond, /// Can not schedule more unlock chunks. NoMoreChunks, From cc4bf9134b492d3a11f45c6b1cfa4fdf307e63e2 Mon Sep 17 00:00:00 2001 From: Qinxuan Chen Date: Wed, 17 Nov 2021 15:16:28 +0800 Subject: [PATCH 195/695] pallet-session: Migrate the historical part to the new pallet macro (#9878) * Migrate session-historical to the new pallet macro Signed-off-by: koushiro * pallet-session: Migrate the historical part to the new pallet macro Signed-off-by: koushiro * Fix staking test runtime Signed-off-by: koushiro * Update frame/session/src/historical/mod.rs * Update frame/session/src/historical/mod.rs * update migration doc Signed-off-by: koushiro * use hardcoded prefix for migration v1 Signed-off-by: koushiro * cargo +nightly-2021-11-08 fmt Signed-off-by: koushiro Co-authored-by: Guillaume Thiolliere --- frame/session/benchmarking/src/lib.rs | 4 +- frame/session/src/historical/mod.rs | 136 ++++++++-------- frame/session/src/historical/offchain.rs | 4 +- frame/session/src/lib.rs | 1 + frame/session/src/migrations/mod.rs | 24 +++ frame/session/src/migrations/v1.rs | 194 +++++++++++++++++++++++ frame/session/src/tests.rs | 27 ++++ frame/staking/src/mock.rs | 1 + 8 files changed, 325 insertions(+), 66 deletions(-) create mode 100644 frame/session/src/migrations/mod.rs create mode 100644 frame/session/src/migrations/v1.rs diff --git a/frame/session/benchmarking/src/lib.rs b/frame/session/benchmarking/src/lib.rs index 8ca713b1bbf6..6d9d81f38517 100644 --- a/frame/session/benchmarking/src/lib.rs +++ b/frame/session/benchmarking/src/lib.rs @@ -22,6 +22,7 @@ mod mock; +use sp_runtime::traits::{One, StaticLookup}; use sp_std::{prelude::*, vec}; use frame_benchmarking::benchmarks; @@ -30,12 +31,11 @@ use frame_support::{ traits::{KeyOwnerProofSystem, OnInitialize}, }; use frame_system::RawOrigin; -use pallet_session::{historical::Module as Historical, Pallet as Session, *}; +use pallet_session::{historical::Pallet as Historical, Pallet as Session, *}; use pallet_staking::{ benchmarking::create_validator_with_nominators, testing_utils::create_validators, RewardDestination, }; -use sp_runtime::traits::{One, StaticLookup}; const MAX_VALIDATORS: u32 = 1000; diff --git a/frame/session/src/historical/mod.rs b/frame/session/src/historical/mod.rs index 0801b2aca170..a3e64f4f9efa 100644 --- a/frame/session/src/historical/mod.rs +++ b/frame/session/src/historical/mod.rs @@ -26,62 +26,74 @@ //! These roots and proofs of inclusion can be generated at any time during the current session. //! Afterwards, the proofs can be fed to a consensus module when reporting misbehavior. -use super::{Pallet as SessionModule, SessionIndex}; +pub mod offchain; +pub mod onchain; +mod shared; + use codec::{Decode, Encode}; -use frame_support::{ - decl_module, decl_storage, print, - traits::{ValidatorSet, ValidatorSetWithIdentification}, - Parameter, -}; use sp_runtime::{ traits::{Convert, OpaqueKeys}, KeyTypeId, }; use sp_session::{MembershipProof, ValidatorCount}; +use sp_staking::SessionIndex; use sp_std::prelude::*; use sp_trie::{ trie_types::{TrieDB, TrieDBMut}, MemoryDB, Recorder, Trie, TrieMut, EMPTY_PREFIX, }; -pub mod offchain; -pub mod onchain; -mod shared; +use frame_support::{ + print, + traits::{KeyOwnerProofSystem, StorageVersion, ValidatorSet, ValidatorSetWithIdentification}, + Parameter, +}; -/// Config necessary for the historical module. -pub trait Config: super::Config { - /// Full identification of the validator. - type FullIdentification: Parameter; - - /// A conversion from validator ID to full identification. - /// - /// This should contain any references to economic actors associated with the - /// validator, since they may be outdated by the time this is queried from a - /// historical trie. - /// - /// It must return the identification for the current session index. - type FullIdentificationOf: Convert>; -} +use crate::{self as pallet_session, Pallet as Session}; + +pub use pallet::*; -decl_storage! { - trait Store for Module as Session { - /// Mapping from historical session indices to session-data root hash and validator count. - HistoricalSessions get(fn historical_root): - map hasher(twox_64_concat) SessionIndex => Option<(T::Hash, ValidatorCount)>; - /// The range of historical sessions we store. [first, last) - StoredRange: Option<(SessionIndex, SessionIndex)>; - /// Deprecated. - CachedObsolete: - map hasher(twox_64_concat) SessionIndex - => Option>; +#[frame_support::pallet] +pub mod pallet { + use super::*; + use frame_support::pallet_prelude::*; + + /// The current storage version. + const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); + + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + #[pallet::storage_version(STORAGE_VERSION)] + pub struct Pallet(_); + + /// Config necessary for the historical pallet. + #[pallet::config] + pub trait Config: pallet_session::Config + frame_system::Config { + /// Full identification of the validator. + type FullIdentification: Parameter; + + /// A conversion from validator ID to full identification. + /// + /// This should contain any references to economic actors associated with the + /// validator, since they may be outdated by the time this is queried from a + /// historical trie. + /// + /// It must return the identification for the current session index. + type FullIdentificationOf: Convert>; } -} -decl_module! { - pub struct Module for enum Call where origin: T::Origin {} + /// Mapping from historical session indices to session-data root hash and validator count. + #[pallet::storage] + #[pallet::getter(fn historical_root)] + pub type HistoricalSessions = + StorageMap<_, Twox64Concat, SessionIndex, (T::Hash, ValidatorCount), OptionQuery>; + + /// The range of historical sessions we store. [first, last) + #[pallet::storage] + pub type StoredRange = StorageValue<_, (SessionIndex, SessionIndex), OptionQuery>; } -impl Module { +impl Pallet { /// Prune historical stored session roots up to (but not including) /// `up_to`. pub fn prune_up_to(up_to: SessionIndex) { @@ -109,7 +121,7 @@ impl Module { } } -impl ValidatorSet for Module { +impl ValidatorSet for Pallet { type ValidatorId = T::ValidatorId; type ValidatorIdOf = T::ValidatorIdOf; @@ -122,7 +134,7 @@ impl ValidatorSet for Module { } } -impl ValidatorSetWithIdentification for Module { +impl ValidatorSetWithIdentification for Pallet { type Identification = T::FullIdentification; type IdentificationOf = T::FullIdentificationOf; } @@ -130,7 +142,7 @@ impl ValidatorSetWithIdentification for Module { /// Specialization of the crate-level `SessionManager` which returns the set of full identification /// when creating a new session. pub trait SessionManager: - crate::SessionManager + pallet_session::SessionManager { /// If there was a validator set change, its returns the set of new validators along with their /// full identifications. @@ -150,7 +162,7 @@ pub struct NoteHistoricalRoot(sp_std::marker::PhantomData<(T, I)>); impl> NoteHistoricalRoot { fn do_new_session(new_index: SessionIndex, is_genesis: bool) -> Option> { - StoredRange::mutate(|range| { + >::mutate(|range| { range.get_or_insert_with(|| (new_index, new_index)).1 = new_index + 1; }); @@ -183,7 +195,7 @@ impl> NoteHi } } -impl crate::SessionManager for NoteHistoricalRoot +impl pallet_session::SessionManager for NoteHistoricalRoot where I: SessionManager, { @@ -207,7 +219,7 @@ where /// A tuple of the validator's ID and their full identification. pub type IdentificationTuple = - (::ValidatorId, ::FullIdentification); + (::ValidatorId, ::FullIdentification); /// A trie instance for checking and generating proofs. pub struct ProvingTrie { @@ -227,7 +239,7 @@ impl ProvingTrie { let mut trie = TrieDBMut::new(&mut db, &mut root); for (i, (validator, full_id)) in validators.into_iter().enumerate() { let i = i as u32; - let keys = match >::load_keys(&validator) { + let keys = match >::load_keys(&validator) { None => continue, Some(k) => k, }; @@ -304,15 +316,13 @@ impl ProvingTrie { } } -impl> frame_support::traits::KeyOwnerProofSystem<(KeyTypeId, D)> - for Module -{ +impl> KeyOwnerProofSystem<(KeyTypeId, D)> for Pallet { type Proof = MembershipProof; type IdentificationTuple = IdentificationTuple; fn prove(key: (KeyTypeId, D)) -> Option { - let session = >::current_index(); - let validators = >::validators() + let session = >::current_index(); + let validators = >::validators() .into_iter() .filter_map(|validator| { T::FullIdentificationOf::convert(validator.clone()) @@ -335,10 +345,10 @@ impl> frame_support::traits::KeyOwnerProofSystem<(KeyT fn check_proof(key: (KeyTypeId, D), proof: Self::Proof) -> Option> { let (id, data) = key; - if proof.session == >::current_index() { - >::key_owner(id, data.as_ref()).and_then(|owner| { + if proof.session == >::current_index() { + >::key_owner(id, data.as_ref()).and_then(|owner| { T::FullIdentificationOf::convert(owner.clone()).and_then(move |id| { - let count = >::validators().len() as ValidatorCount; + let count = >::validators().len() as ValidatorCount; if count != proof.validator_count { return None @@ -374,7 +384,7 @@ pub(crate) mod tests { BasicExternalities, }; - type Historical = Module; + type Historical = Pallet; pub(crate) fn new_test_ext() -> sp_io::TestExternalities { let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); @@ -386,7 +396,9 @@ pub(crate) mod tests { frame_system::Pallet::::inc_providers(k); } }); - crate::GenesisConfig:: { keys }.assimilate_storage(&mut t).unwrap(); + pallet_session::GenesisConfig:: { keys } + .assimilate_storage(&mut t) + .unwrap(); sp_io::TestExternalities::new(t) } @@ -436,27 +448,27 @@ pub(crate) mod tests { Session::on_initialize(i); } - assert_eq!(StoredRange::get(), Some((0, 100))); + assert_eq!(>::get(), Some((0, 100))); for i in 0..100 { assert!(Historical::historical_root(i).is_some()) } Historical::prune_up_to(10); - assert_eq!(StoredRange::get(), Some((10, 100))); + assert_eq!(>::get(), Some((10, 100))); Historical::prune_up_to(9); - assert_eq!(StoredRange::get(), Some((10, 100))); + assert_eq!(>::get(), Some((10, 100))); for i in 10..100 { assert!(Historical::historical_root(i).is_some()) } Historical::prune_up_to(99); - assert_eq!(StoredRange::get(), Some((99, 100))); + assert_eq!(>::get(), Some((99, 100))); Historical::prune_up_to(100); - assert_eq!(StoredRange::get(), None); + assert_eq!(>::get(), None); for i in 99..199u64 { set_next_validators(vec![i]); @@ -466,14 +478,14 @@ pub(crate) mod tests { Session::on_initialize(i); } - assert_eq!(StoredRange::get(), Some((100, 200))); + assert_eq!(>::get(), Some((100, 200))); for i in 100..200 { assert!(Historical::historical_root(i).is_some()) } Historical::prune_up_to(9999); - assert_eq!(StoredRange::get(), None); + assert_eq!(>::get(), None); for i in 100..200 { assert!(Historical::historical_root(i).is_none()) diff --git a/frame/session/src/historical/offchain.rs b/frame/session/src/historical/offchain.rs index b646ecc2764f..0b292b57658d 100644 --- a/frame/session/src/historical/offchain.rs +++ b/frame/session/src/historical/offchain.rs @@ -140,7 +140,7 @@ pub fn keep_newest(n_to_keep: usize) { mod tests { use super::*; use crate::{ - historical::{onchain, Module}, + historical::{onchain, Pallet}, mock::{force_new_session, set_next_validators, Session, System, Test, NEXT_VALIDATORS}, }; @@ -156,7 +156,7 @@ mod tests { BasicExternalities, }; - type Historical = Module; + type Historical = Pallet; pub fn new_test_ext() -> sp_io::TestExternalities { let mut t = frame_system::GenesisConfig::default() diff --git a/frame/session/src/lib.rs b/frame/session/src/lib.rs index 6779285ee318..2fd34365705b 100644 --- a/frame/session/src/lib.rs +++ b/frame/session/src/lib.rs @@ -108,6 +108,7 @@ #[cfg(feature = "historical")] pub mod historical; +pub mod migrations; #[cfg(test)] mod mock; #[cfg(test)] diff --git a/frame/session/src/migrations/mod.rs b/frame/session/src/migrations/mod.rs new file mode 100644 index 000000000000..ccc5ee3c2e52 --- /dev/null +++ b/frame/session/src/migrations/mod.rs @@ -0,0 +1,24 @@ +// This file is part of Substrate. + +// Copyright (C) 2019-2021 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. + +/// Version 1. +/// +/// In version 0 session historical pallet uses `Session` for storage module prefix. +/// In version 1 it uses its name as configured in `construct_runtime`. +/// This migration moves session historical pallet storages from old prefix to new prefix. +#[cfg(feature = "historical")] +pub mod v1; diff --git a/frame/session/src/migrations/v1.rs b/frame/session/src/migrations/v1.rs new file mode 100644 index 000000000000..1de199fe7bed --- /dev/null +++ b/frame/session/src/migrations/v1.rs @@ -0,0 +1,194 @@ +// This file is part of Substrate. + +// Copyright (C) 2019-2021 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. + +use sp_io::hashing::twox_128; +use sp_std::str; + +use frame_support::{ + storage::{generator::StorageValue, StoragePrefixedMap}, + traits::{ + Get, GetStorageVersion, PalletInfoAccess, StorageVersion, + STORAGE_VERSION_STORAGE_KEY_POSTFIX, + }, + weights::Weight, +}; + +use crate::historical as pallet_session_historical; + +const OLD_PREFIX: &str = "Session"; + +/// Migrate the entire storage of this pallet to a new prefix. +/// +/// This new prefix must be the same as the one set in construct_runtime. +/// +/// The migration will look into the storage version in order not to trigger a migration on an up +/// to date storage. Thus the on chain storage version must be less than 1 in order to trigger the +/// migration. +pub fn migrate( +) -> Weight { + let new_pallet_name =

::name(); + + if new_pallet_name == OLD_PREFIX { + log::info!( + target: "runtime::session_historical", + "New pallet name is equal to the old prefix. No migration needs to be done.", + ); + return 0 + } + + let on_chain_storage_version =

::on_chain_storage_version(); + log::info!( + target: "runtime::session_historical", + "Running migration to v1 for session_historical with storage version {:?}", + on_chain_storage_version, + ); + + if on_chain_storage_version < 1 { + let storage_prefix = pallet_session_historical::HistoricalSessions::::storage_prefix(); + frame_support::storage::migration::move_storage_from_pallet( + storage_prefix, + OLD_PREFIX.as_bytes(), + new_pallet_name.as_bytes(), + ); + log_migration("migration", storage_prefix, OLD_PREFIX, new_pallet_name); + + let storage_prefix = pallet_session_historical::StoredRange::::storage_prefix(); + frame_support::storage::migration::move_storage_from_pallet( + storage_prefix, + OLD_PREFIX.as_bytes(), + new_pallet_name.as_bytes(), + ); + log_migration("migration", storage_prefix, OLD_PREFIX, new_pallet_name); + + StorageVersion::new(1).put::

(); + ::BlockWeights::get().max_block + } else { + log::warn!( + target: "runtime::session_historical", + "Attempted to apply migration to v1 but failed because storage version is {:?}", + on_chain_storage_version, + ); + 0 + } +} + +/// Some checks prior to migration. This can be linked to +/// [`frame_support::traits::OnRuntimeUpgrade::pre_upgrade`] for further testing. +/// +/// Panics if anything goes wrong. +pub fn pre_migrate< + T: pallet_session_historical::Config, + P: GetStorageVersion + PalletInfoAccess, +>() { + let new_pallet_name =

::name(); + + let storage_prefix_historical_sessions = + pallet_session_historical::HistoricalSessions::::storage_prefix(); + let storage_prefix_stored_range = pallet_session_historical::StoredRange::::storage_prefix(); + + log_migration("pre-migration", storage_prefix_historical_sessions, OLD_PREFIX, new_pallet_name); + log_migration("pre-migration", storage_prefix_stored_range, OLD_PREFIX, new_pallet_name); + + if new_pallet_name == OLD_PREFIX { + return + } + + let new_pallet_prefix = twox_128(new_pallet_name.as_bytes()); + let storage_version_key = twox_128(STORAGE_VERSION_STORAGE_KEY_POSTFIX); + + let mut new_pallet_prefix_iter = frame_support::storage::KeyPrefixIterator::new( + new_pallet_prefix.to_vec(), + new_pallet_prefix.to_vec(), + |key| Ok(key.to_vec()), + ); + + // Ensure nothing except the storage_version_key is stored in the new prefix. + assert!(new_pallet_prefix_iter.all(|key| key == storage_version_key)); + + assert!(

::on_chain_storage_version() < 1); +} + +/// Some checks for after migration. This can be linked to +/// [`frame_support::traits::OnRuntimeUpgrade::post_upgrade`] for further testing. +/// +/// Panics if anything goes wrong. +pub fn post_migrate< + T: pallet_session_historical::Config, + P: GetStorageVersion + PalletInfoAccess, +>() { + let new_pallet_name =

::name(); + + let storage_prefix_historical_sessions = + pallet_session_historical::HistoricalSessions::::storage_prefix(); + let storage_prefix_stored_range = pallet_session_historical::StoredRange::::storage_prefix(); + + log_migration( + "post-migration", + storage_prefix_historical_sessions, + OLD_PREFIX, + new_pallet_name, + ); + log_migration("post-migration", storage_prefix_stored_range, OLD_PREFIX, new_pallet_name); + + if new_pallet_name == OLD_PREFIX { + return + } + + // Assert that no `HistoricalSessions` and `StoredRange` storages remains at the old prefix. + let old_pallet_prefix = twox_128(OLD_PREFIX.as_bytes()); + let old_historical_sessions_key = + [&old_pallet_prefix, &twox_128(storage_prefix_historical_sessions)[..]].concat(); + let old_historical_sessions_key_iter = frame_support::storage::KeyPrefixIterator::new( + old_historical_sessions_key.to_vec(), + old_historical_sessions_key.to_vec(), + |_| Ok(()), + ); + assert_eq!(old_historical_sessions_key_iter.count(), 0); + + let old_stored_range_key = + [&old_pallet_prefix, &twox_128(storage_prefix_stored_range)[..]].concat(); + let old_stored_range_key_iter = frame_support::storage::KeyPrefixIterator::new( + old_stored_range_key.to_vec(), + old_stored_range_key.to_vec(), + |_| Ok(()), + ); + assert_eq!(old_stored_range_key_iter.count(), 0); + + // Assert that the `HistoricalSessions` and `StoredRange` storages (if they exist) have been + // moved to the new prefix. + // NOTE: storage_version_key is already in the new prefix. + let new_pallet_prefix = twox_128(new_pallet_name.as_bytes()); + let new_pallet_prefix_iter = frame_support::storage::KeyPrefixIterator::new( + new_pallet_prefix.to_vec(), + new_pallet_prefix.to_vec(), + |_| Ok(()), + ); + assert!(new_pallet_prefix_iter.count() >= 1); + + assert_eq!(

::on_chain_storage_version(), 1); +} + +fn log_migration(stage: &str, storage_prefix: &[u8], old_pallet_name: &str, new_pallet_name: &str) { + log::info!( + target: "runtime::session_historical", + "{} prefix of storage '{}': '{}' ==> '{}'", + stage, + str::from_utf8(storage_prefix).unwrap_or(""), + old_pallet_name, + new_pallet_name, + ); +} diff --git a/frame/session/src/tests.rs b/frame/session/src/tests.rs index 308ed7c5e548..cc0606edf499 100644 --- a/frame/session/src/tests.rs +++ b/frame/session/src/tests.rs @@ -453,3 +453,30 @@ fn upgrade_keys() { } }) } + +#[cfg(feature = "historical")] +#[test] +fn test_migration_v1() { + use crate::{ + historical::{HistoricalSessions, StoredRange}, + mock::Historical, + }; + use frame_support::traits::PalletInfoAccess; + + new_test_ext().execute_with(|| { + assert!(>::iter_values().count() > 0); + assert!(>::exists()); + + let old_pallet = "Session"; + let new_pallet = ::name(); + frame_support::storage::migration::move_pallet( + new_pallet.as_bytes(), + old_pallet.as_bytes(), + ); + StorageVersion::new(0).put::(); + + crate::migrations::v1::pre_migrate::(); + crate::migrations::v1::migrate::(); + crate::migrations::v1::post_migrate::(); + }); +} diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index 95d397359f8d..e5a3e4903393 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -96,6 +96,7 @@ frame_support::construct_runtime!( Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, Staking: pallet_staking::{Pallet, Call, Config, Storage, Event}, Session: pallet_session::{Pallet, Call, Storage, Event, Config}, + Historical: pallet_session::historical::{Pallet, Storage}, BagsList: pallet_bags_list::{Pallet, Call, Storage, Event}, } ); From 0baa586a57803dffa09ce1051ef54a63ad6f40d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Wed, 17 Nov 2021 10:53:31 +0100 Subject: [PATCH 196/695] authority-discovery: Support multiple authority ids per peer id (#10259) * authority-discovery: Support multiple authority ids per peer id An peer id can be mapped to multiple authority ids, because an authority id is a session key that could be changed every session. Before this pr the internal authority discovery cache assumed that each authority id can only be mapped to one peer id. However, this isn't true since we changed the default implementation of the authority discovery to combine the current and next session authorities. * Review feedback * Update client/authority-discovery/src/worker/addr_cache.rs Co-authored-by: Andronik Ordian * Early return on no peer ids * Update client/authority-discovery/src/worker/addr_cache.rs Co-authored-by: Pierre Krieger * Update types in comment * FMT * Add warning * Update client/authority-discovery/src/worker/addr_cache.rs Co-authored-by: Andronik Ordian * Feedback Co-authored-by: Andronik Ordian Co-authored-by: Pierre Krieger --- client/authority-discovery/src/lib.rs | 11 +- client/authority-discovery/src/service.rs | 11 +- client/authority-discovery/src/tests.rs | 8 +- client/authority-discovery/src/worker.rs | 8 +- .../src/worker/addr_cache.rs | 242 +++++++++++------- .../authority-discovery/src/worker/tests.rs | 5 +- 6 files changed, 173 insertions(+), 112 deletions(-) diff --git a/client/authority-discovery/src/lib.rs b/client/authority-discovery/src/lib.rs index 800f683aa0ae..1bbb9f38796c 100644 --- a/client/authority-discovery/src/lib.rs +++ b/client/authority-discovery/src/lib.rs @@ -18,6 +18,7 @@ #![warn(missing_docs)] #![recursion_limit = "1024"] + //! Substrate authority discovery. //! //! This crate enables Substrate authorities to discover and directly connect to @@ -31,7 +32,7 @@ pub use crate::{ worker::{NetworkProvider, Role, Worker}, }; -use std::{sync::Arc, time::Duration}; +use std::{collections::HashSet, sync::Arc, time::Duration}; use futures::{ channel::{mpsc, oneshot}, @@ -58,11 +59,13 @@ pub struct WorkerConfig { /// /// By default this is set to 1 hour. pub max_publish_interval: Duration, + /// Interval at which the keystore is queried. If the keys have changed, unconditionally /// re-publish its addresses on the DHT. /// /// By default this is set to 1 minute. pub keystore_refresh_interval: Duration, + /// The maximum interval in which the node will query the DHT for new entries. /// /// By default this is set to 10 minutes. @@ -156,7 +159,7 @@ where /// Message send from the [`Service`] to the [`Worker`]. pub(crate) enum ServicetoWorkerMsg { /// See [`Service::get_addresses_by_authority_id`]. - GetAddressesByAuthorityId(AuthorityId, oneshot::Sender>>), - /// See [`Service::get_authority_id_by_peer_id`]. - GetAuthorityIdByPeerId(PeerId, oneshot::Sender>), + GetAddressesByAuthorityId(AuthorityId, oneshot::Sender>>), + /// See [`Service::get_authority_ids_by_peer_id`]. + GetAuthorityIdsByPeerId(PeerId, oneshot::Sender>>), } diff --git a/client/authority-discovery/src/service.rs b/client/authority-discovery/src/service.rs index 2e5ae66e4dd4..9b59a4ec8647 100644 --- a/client/authority-discovery/src/service.rs +++ b/client/authority-discovery/src/service.rs @@ -16,7 +16,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::fmt::Debug; +use std::{collections::HashSet, fmt::Debug}; use crate::ServicetoWorkerMsg; @@ -62,7 +62,7 @@ impl Service { pub async fn get_addresses_by_authority_id( &mut self, authority: AuthorityId, - ) -> Option> { + ) -> Option> { let (tx, rx) = oneshot::channel(); self.to_worker @@ -78,11 +78,14 @@ impl Service { /// /// Returns `None` if no entry was present or connection to the /// [`crate::Worker`] failed. - pub async fn get_authority_id_by_peer_id(&mut self, peer_id: PeerId) -> Option { + pub async fn get_authority_ids_by_peer_id( + &mut self, + peer_id: PeerId, + ) -> Option> { let (tx, rx) = oneshot::channel(); self.to_worker - .send(ServicetoWorkerMsg::GetAuthorityIdByPeerId(peer_id, tx)) + .send(ServicetoWorkerMsg::GetAuthorityIdsByPeerId(peer_id, tx)) .await .ok()?; diff --git a/client/authority-discovery/src/tests.rs b/client/authority-discovery/src/tests.rs index 3784b4c83426..cef91445064c 100644 --- a/client/authority-discovery/src/tests.rs +++ b/client/authority-discovery/src/tests.rs @@ -29,7 +29,7 @@ use libp2p::core::{ multiaddr::{Multiaddr, Protocol}, PeerId, }; -use std::sync::Arc; +use std::{collections::HashSet, sync::Arc}; use sp_authority_discovery::AuthorityId; use sp_core::crypto::key_types; @@ -73,12 +73,12 @@ fn get_addresses_and_authority_id() { pool.run_until(async { assert_eq!( - Some(vec![remote_addr]), + Some(HashSet::from([remote_addr])), service.get_addresses_by_authority_id(remote_authority_id.clone()).await, ); assert_eq!( - Some(remote_authority_id), - service.get_authority_id_by_peer_id(remote_peer_id).await, + Some(HashSet::from([remote_authority_id])), + service.get_authority_ids_by_peer_id(remote_peer_id).await, ); }); } diff --git a/client/authority-discovery/src/worker.rs b/client/authority-discovery/src/worker.rs index a689d0bafd26..00021ecbdcb8 100644 --- a/client/authority-discovery/src/worker.rs +++ b/client/authority-discovery/src/worker.rs @@ -259,9 +259,9 @@ where self.addr_cache.get_addresses_by_authority_id(&authority).map(Clone::clone), ); }, - ServicetoWorkerMsg::GetAuthorityIdByPeerId(peer_id, sender) => { + ServicetoWorkerMsg::GetAuthorityIdsByPeerId(peer_id, sender) => { let _ = sender - .send(self.addr_cache.get_authority_id_by_peer_id(&peer_id).map(Clone::clone)); + .send(self.addr_cache.get_authority_ids_by_peer_id(&peer_id).map(Clone::clone)); }, } } @@ -374,7 +374,7 @@ where .map_err(|e| Error::CallingRuntime(e.into()))? .into_iter() .filter(|id| !local_keys.contains(id.as_ref())) - .collect(); + .collect::>(); self.addr_cache.retain_ids(&authorities); @@ -548,7 +548,7 @@ where if let Some(metrics) = &self.metrics { metrics .known_authorities_count - .set(self.addr_cache.num_ids().try_into().unwrap_or(std::u64::MAX)); + .set(self.addr_cache.num_authority_ids().try_into().unwrap_or(std::u64::MAX)); } } Ok(()) diff --git a/client/authority-discovery/src/worker/addr_cache.rs b/client/authority-discovery/src/worker/addr_cache.rs index e770297f6f3b..d4ba156d5fa1 100644 --- a/client/authority-discovery/src/worker/addr_cache.rs +++ b/client/authority-discovery/src/worker/addr_cache.rs @@ -17,79 +17,94 @@ // along with this program. If not, see . use libp2p::core::multiaddr::{Multiaddr, Protocol}; -use std::collections::HashMap; use sc_network::PeerId; use sp_authority_discovery::AuthorityId; +use std::collections::{hash_map::Entry, HashMap, HashSet}; -/// Cache for [`AuthorityId`] -> [`Vec`] and [`PeerId`] -> [`AuthorityId`] mappings. +/// Cache for [`AuthorityId`] -> [`HashSet`] and [`PeerId`] -> [`HashSet`] +/// mappings. pub(super) struct AddrCache { - // The addresses found in `authority_id_to_addresses` are guaranteed to always match - // the peerids found in `peer_id_to_authority_id`. In other words, these two hashmaps - // are similar to a bi-directional map. - authority_id_to_addresses: HashMap>, - peer_id_to_authority_id: HashMap, + /// The addresses found in `authority_id_to_addresses` are guaranteed to always match + /// the peerids found in `peer_id_to_authority_ids`. In other words, these two hashmaps + /// are similar to a bi-directional map. + /// + /// Since we may store the mapping across several sessions, a single + /// `PeerId` might correspond to multiple `AuthorityId`s. However, + /// it's not expected that a single `AuthorityId` can have multiple `PeerId`s. + authority_id_to_addresses: HashMap>, + peer_id_to_authority_ids: HashMap>, } impl AddrCache { pub fn new() -> Self { AddrCache { authority_id_to_addresses: HashMap::new(), - peer_id_to_authority_id: HashMap::new(), + peer_id_to_authority_ids: HashMap::new(), } } /// Inserts the given [`AuthorityId`] and [`Vec`] pair for future lookups by /// [`AuthorityId`] or [`PeerId`]. - pub fn insert(&mut self, authority_id: AuthorityId, mut addresses: Vec) { - addresses.sort_unstable_by(|a, b| a.as_ref().cmp(b.as_ref())); + pub fn insert(&mut self, authority_id: AuthorityId, addresses: Vec) { + let addresses = addresses.into_iter().collect::>(); + let peer_ids = addresses_to_peer_ids(&addresses); + + if peer_ids.is_empty() { + log::debug!( + target: super::LOG_TARGET, + "Authority({:?}) provides no addresses or addresses without peer ids. Adresses: {:?}", + authority_id, + addresses, + ); - // Insert into `self.peer_id_to_authority_id`. - let peer_ids = addresses - .iter() - .map(|a| peer_id_from_multiaddr(a)) - .filter_map(|peer_id| peer_id); - for peer_id in peer_ids.clone() { - let former_auth = - match self.peer_id_to_authority_id.insert(peer_id, authority_id.clone()) { - Some(a) if a != authority_id => a, - _ => continue, - }; - - // PeerId was associated to a different authority id before. - // Remove corresponding authority from `self.authority_id_to_addresses`. - let former_auth_addrs = match self.authority_id_to_addresses.get_mut(&former_auth) { - Some(a) => a, - None => { - debug_assert!(false); - continue - }, - }; - former_auth_addrs.retain(|a| peer_id_from_multiaddr(a).map_or(true, |p| p != peer_id)); + return + } else if peer_ids.len() > 1 { + log::warn!( + target: super::LOG_TARGET, + "Authority({:?}) can be reached through multiple peer ids: {:?}", + authority_id, + peer_ids + ); } - // Insert into `self.authority_id_to_addresses`. - for former_addr in self - .authority_id_to_addresses - .insert(authority_id.clone(), addresses.clone()) - .unwrap_or_default() - { - // Must remove from `self.peer_id_to_authority_id` any PeerId formerly associated - // to that authority but that can't be found in its new addresses. - - let peer_id = match peer_id_from_multiaddr(&former_addr) { - Some(p) => p, - None => continue, - }; + let old_addresses = self.authority_id_to_addresses.insert(authority_id.clone(), addresses); + let old_peer_ids = addresses_to_peer_ids(&old_addresses.unwrap_or_default()); - if !peer_ids.clone().any(|p| p == peer_id) { - self.peer_id_to_authority_id.remove(&peer_id); + // Add the new peer ids + peer_ids.difference(&old_peer_ids).for_each(|new_peer_id| { + self.peer_id_to_authority_ids + .entry(*new_peer_id) + .or_default() + .insert(authority_id.clone()); + }); + + // Remove the old peer ids + self.remove_authority_id_from_peer_ids(&authority_id, old_peer_ids.difference(&peer_ids)); + } + + /// Remove the given `authority_id` from the `peer_id` to `authority_ids` mapping. + /// + /// If a `peer_id` doesn't have any `authority_id` assigned anymore, it is removed. + fn remove_authority_id_from_peer_ids<'a>( + &mut self, + authority_id: &AuthorityId, + peer_ids: impl Iterator, + ) { + peer_ids.for_each(|peer_id| { + if let Entry::Occupied(mut e) = self.peer_id_to_authority_ids.entry(*peer_id) { + e.get_mut().remove(authority_id); + + // If there are no more entries, remove the peer id. + if e.get().is_empty() { + e.remove(); + } } - } + }) } /// Returns the number of authority IDs in the cache. - pub fn num_ids(&self) -> usize { + pub fn num_authority_ids(&self) -> usize { self.authority_id_to_addresses.len() } @@ -97,18 +112,21 @@ impl AddrCache { pub fn get_addresses_by_authority_id( &self, authority_id: &AuthorityId, - ) -> Option<&Vec> { - self.authority_id_to_addresses.get(&authority_id) + ) -> Option<&HashSet> { + self.authority_id_to_addresses.get(authority_id) } - /// Returns the [`AuthorityId`] for the given [`PeerId`]. - pub fn get_authority_id_by_peer_id(&self, peer_id: &PeerId) -> Option<&AuthorityId> { - self.peer_id_to_authority_id.get(peer_id) + /// Returns the [`AuthorityId`]s for the given [`PeerId`]. + /// + /// As the authority id can change between sessions, one [`PeerId`] can be mapped to + /// multiple authority ids. + pub fn get_authority_ids_by_peer_id(&self, peer_id: &PeerId) -> Option<&HashSet> { + self.peer_id_to_authority_ids.get(peer_id) } /// Removes all [`PeerId`]s and [`Multiaddr`]s from the cache that are not related to the given /// [`AuthorityId`]s. - pub fn retain_ids(&mut self, authority_ids: &Vec) { + pub fn retain_ids(&mut self, authority_ids: &[AuthorityId]) { // The below logic could be replaced by `BtreeMap::drain_filter` once it stabilized. let authority_ids_to_remove = self .authority_id_to_addresses @@ -120,19 +138,18 @@ impl AddrCache { for authority_id_to_remove in authority_ids_to_remove { // Remove other entries from `self.authority_id_to_addresses`. - let addresses = self.authority_id_to_addresses.remove(&authority_id_to_remove); - - // Remove other entries from `self.peer_id_to_authority_id`. - let peer_ids = addresses - .iter() - .flatten() - .map(|a| peer_id_from_multiaddr(a)) - .filter_map(|peer_id| peer_id); - for peer_id in peer_ids { - if let Some(id) = self.peer_id_to_authority_id.remove(&peer_id) { - debug_assert_eq!(authority_id_to_remove, id); - } - } + let addresses = if let Some(addresses) = + self.authority_id_to_addresses.remove(&authority_id_to_remove) + { + addresses + } else { + continue + }; + + self.remove_authority_id_from_peer_ids( + &authority_id_to_remove, + addresses_to_peer_ids(&addresses).iter(), + ); } } } @@ -147,6 +164,13 @@ fn peer_id_from_multiaddr(addr: &Multiaddr) -> Option { }) } +fn addresses_to_peer_ids(addresses: &HashSet) -> HashSet { + addresses + .iter() + .filter_map(|a| peer_id_from_multiaddr(a)) + .collect::>() +} + #[cfg(test)] mod tests { use super::*; @@ -226,27 +250,27 @@ mod tests { cache.insert(third.0.clone(), vec![third.1.clone()]); assert_eq!( - Some(&vec![third.1.clone()]), + Some(&HashSet::from([third.1.clone()])), cache.get_addresses_by_authority_id(&third.0), - "Expect `get_addresses_by_authority_id` to return addresses of third authority." + "Expect `get_addresses_by_authority_id` to return addresses of third authority.", ); assert_eq!( - Some(&third.0), - cache.get_authority_id_by_peer_id(&peer_id_from_multiaddr(&third.1).unwrap()), - "Expect `get_authority_id_by_peer_id` to return `AuthorityId` of third authority." + Some(&HashSet::from([third.0.clone()])), + cache.get_authority_ids_by_peer_id(&peer_id_from_multiaddr(&third.1).unwrap()), + "Expect `get_authority_id_by_peer_id` to return `AuthorityId` of third authority.", ); - cache.retain_ids(&vec![first.0, second.0]); + cache.retain_ids(&vec![first.0.clone(), second.0]); assert_eq!( None, cache.get_addresses_by_authority_id(&third.0), - "Expect `get_addresses_by_authority_id` to not return `None` for third authority." + "Expect `get_addresses_by_authority_id` to not return `None` for third authority.", ); assert_eq!( None, - cache.get_authority_id_by_peer_id(&peer_id_from_multiaddr(&third.1).unwrap()), - "Expect `get_authority_id_by_peer_id` to return `None` for third authority." + cache.get_authority_ids_by_peer_id(&peer_id_from_multiaddr(&third.1).unwrap()), + "Expect `get_authority_id_by_peer_id` to return `None` for third authority.", ); TestResult::passed() @@ -282,44 +306,47 @@ mod tests { assert_eq!( None, - cache.get_authority_id_by_peer_id(&peer_id_from_multiaddr(&multiaddr1).unwrap()) + cache.get_authority_ids_by_peer_id(&peer_id_from_multiaddr(&multiaddr1).unwrap()) ); assert_eq!( - Some(&authority1), - cache.get_authority_id_by_peer_id(&peer_id_from_multiaddr(&multiaddr2).unwrap()) + Some(&HashSet::from([authority1.clone()])), + cache.get_authority_ids_by_peer_id(&peer_id_from_multiaddr(&multiaddr2).unwrap()) ); assert_eq!( - Some(&authority1), - cache.get_authority_id_by_peer_id(&peer_id_from_multiaddr(&multiaddr3).unwrap()) + Some(&HashSet::from([authority1.clone()])), + cache.get_authority_ids_by_peer_id(&peer_id_from_multiaddr(&multiaddr3).unwrap()) ); assert_eq!( - Some(&authority1), - cache.get_authority_id_by_peer_id(&peer_id_from_multiaddr(&multiaddr4).unwrap()) + Some(&HashSet::from([authority1.clone()])), + cache.get_authority_ids_by_peer_id(&peer_id_from_multiaddr(&multiaddr4).unwrap()) ); cache.insert(authority2.clone(), vec![multiaddr2.clone()]); assert_eq!( - Some(&authority2), - cache.get_authority_id_by_peer_id(&peer_id_from_multiaddr(&multiaddr2).unwrap()) + Some(&HashSet::from([authority2.clone(), authority1.clone()])), + cache.get_authority_ids_by_peer_id(&peer_id_from_multiaddr(&multiaddr2).unwrap()) ); assert_eq!( - Some(&authority1), - cache.get_authority_id_by_peer_id(&peer_id_from_multiaddr(&multiaddr3).unwrap()) + Some(&HashSet::from([authority1.clone()])), + cache.get_authority_ids_by_peer_id(&peer_id_from_multiaddr(&multiaddr3).unwrap()) ); - assert_eq!(cache.get_addresses_by_authority_id(&authority1).unwrap().len(), 2); + assert_eq!(cache.get_addresses_by_authority_id(&authority1).unwrap().len(), 3); cache.insert(authority2.clone(), vec![multiaddr2.clone(), multiaddr3.clone()]); assert_eq!( - Some(&authority2), - cache.get_authority_id_by_peer_id(&peer_id_from_multiaddr(&multiaddr2).unwrap()) + Some(&HashSet::from([authority2.clone(), authority1.clone()])), + cache.get_authority_ids_by_peer_id(&peer_id_from_multiaddr(&multiaddr2).unwrap()) + ); + assert_eq!( + Some(&HashSet::from([authority2.clone(), authority1.clone()])), + cache.get_authority_ids_by_peer_id(&peer_id_from_multiaddr(&multiaddr3).unwrap()) ); assert_eq!( - Some(&authority2), - cache.get_authority_id_by_peer_id(&peer_id_from_multiaddr(&multiaddr3).unwrap()) + &HashSet::from([multiaddr2.clone(), multiaddr3.clone(), multiaddr4.clone()]), + cache.get_addresses_by_authority_id(&authority1).unwrap(), ); - assert!(cache.get_addresses_by_authority_id(&authority1).unwrap().is_empty()); TestResult::passed() } @@ -328,4 +355,31 @@ mod tests { .max_tests(10) .quickcheck(property as fn(_, _, _, _, _) -> TestResult) } + + /// As the runtime gives us the current + next authority ids, it can happen that some + /// authority changed its session keys. Changing the sessions keys leads to having two + /// authority ids that map to the same `PeerId` & addresses. + #[test] + fn adding_two_authority_ids_for_the_same_peer_id() { + let mut addr_cache = AddrCache::new(); + + let peer_id = PeerId::random(); + let addr = Multiaddr::empty().with(Protocol::P2p(peer_id.into())); + + let authority_id0 = AuthorityPair::generate().0.public(); + let authority_id1 = AuthorityPair::generate().0.public(); + + addr_cache.insert(authority_id0.clone(), vec![addr.clone()]); + addr_cache.insert(authority_id1.clone(), vec![addr.clone()]); + + assert_eq!(2, addr_cache.num_authority_ids()); + assert_eq!( + &HashSet::from([addr.clone()]), + addr_cache.get_addresses_by_authority_id(&authority_id0).unwrap() + ); + assert_eq!( + &HashSet::from([addr]), + addr_cache.get_addresses_by_authority_id(&authority_id1).unwrap() + ); + } } diff --git a/client/authority-discovery/src/worker/tests.rs b/client/authority-discovery/src/worker/tests.rs index 3c1610256f5b..130aea71fdfb 100644 --- a/client/authority-discovery/src/worker/tests.rs +++ b/client/authority-discovery/src/worker/tests.rs @@ -19,6 +19,7 @@ use crate::worker::schema; use std::{ + collections::HashSet, sync::{Arc, Mutex}, task::Poll, }; @@ -469,7 +470,7 @@ fn dont_stop_polling_dht_event_stream_after_bogus_event() { .send(ServicetoWorkerMsg::GetAddressesByAuthorityId(remote_public_key, sender)) .await .expect("Channel has capacity of 1."); - assert_eq!(Some(vec![remote_multiaddr]), addresses.await.unwrap()); + assert_eq!(Some(HashSet::from([remote_multiaddr])), addresses.await.unwrap()); }); } @@ -562,7 +563,7 @@ fn do_not_cache_addresses_without_peer_id() { local_worker.handle_dht_value_found_event(vec![dht_event]).unwrap(); assert_eq!( - Some(&vec![multiaddr_with_peer_id]), + Some(&HashSet::from([multiaddr_with_peer_id])), local_worker.addr_cache.get_addresses_by_authority_id(&remote_public.into()), "Expect worker to only cache `Multiaddr`s with `PeerId`s.", ); From e75d8e9a51b3d2b793018bd4d9ea772435a39c64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Wed, 17 Nov 2021 11:35:21 +0100 Subject: [PATCH 197/695] Offchain testing: Fix reading response (#10294) --- primitives/core/src/offchain/testing.rs | 2 +- primitives/runtime/src/offchain/http.rs | 32 +++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/primitives/core/src/offchain/testing.rs b/primitives/core/src/offchain/testing.rs index 26bcdb66de83..29b9edb03deb 100644 --- a/primitives/core/src/offchain/testing.rs +++ b/primitives/core/src/offchain/testing.rs @@ -341,7 +341,7 @@ impl offchain::Externalities for TestOffchainExt { Ok(0) } else { let read = std::cmp::min(buffer.len(), response[req.read..].len()); - buffer[0..read].copy_from_slice(&response[req.read..read]); + buffer[0..read].copy_from_slice(&response[req.read..req.read + read]); req.read += read; Ok(read) } diff --git a/primitives/runtime/src/offchain/http.rs b/primitives/runtime/src/offchain/http.rs index 469f2fb5aff3..a8c82e616a47 100644 --- a/primitives/runtime/src/offchain/http.rs +++ b/primitives/runtime/src/offchain/http.rs @@ -535,6 +535,38 @@ mod tests { }) } + #[test] + fn should_send_huge_response() { + let (offchain, state) = testing::TestOffchainExt::new(); + let mut t = TestExternalities::default(); + t.register_extension(OffchainWorkerExt::new(offchain)); + + t.execute_with(|| { + let request: Request = Request::get("http://localhost:1234"); + let pending = request.add_header("X-Auth", "hunter2").send().unwrap(); + // make sure it's sent correctly + state.write().fulfill_pending_request( + 0, + testing::PendingRequest { + method: "GET".into(), + uri: "http://localhost:1234".into(), + headers: vec![("X-Auth".into(), "hunter2".into())], + sent: true, + ..Default::default() + }, + vec![0; 5923], + None, + ); + + // wait + let response = pending.wait().unwrap(); + + let body = response.body(); + assert_eq!(body.clone().collect::>(), vec![0; 5923]); + assert_eq!(body.error(), &None); + }) + } + #[test] fn should_send_a_post_request() { let (offchain, state) = testing::TestOffchainExt::new(); From 6d61f48427ae40b11dbebc2b548818773c3c7f8e Mon Sep 17 00:00:00 2001 From: Seun Lanlege Date: Wed, 17 Nov 2021 13:46:10 +0100 Subject: [PATCH 198/695] Check if BEEFY authority is in current set (#10281) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * check if BEEFY authority is in current set * Update client/beefy/src/round.rs Co-authored-by: Bastian Köcher * Update client/beefy/src/round.rs * Update client/beefy/src/round.rs Co-authored-by: Andreas Doerr * remove stray semi Co-authored-by: Bastian Köcher Co-authored-by: Andreas Doerr --- client/beefy/src/round.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/client/beefy/src/round.rs b/client/beefy/src/round.rs index 7d443603b364..51284c9bd2f6 100644 --- a/client/beefy/src/round.rs +++ b/client/beefy/src/round.rs @@ -82,7 +82,11 @@ where } pub(crate) fn add_vote(&mut self, round: (H, N), vote: (Public, Signature)) -> bool { - self.rounds.entry(round).or_default().add_vote(vote) + if self.validator_set.validators.iter().any(|id| vote.0 == *id) { + self.rounds.entry(round).or_default().add_vote(vote) + } else { + false + } } pub(crate) fn is_done(&self, round: &(H, N)) -> bool { From 05a6abb9369426e862fc09fa51c544f1d03d5b71 Mon Sep 17 00:00:00 2001 From: wigy <1888808+wigy-opensource-developer@users.noreply.github.com> Date: Wed, 17 Nov 2021 15:11:02 +0100 Subject: [PATCH 199/695] Offence implementations can disable offenders independently from slashing (#10201) * Offence implementations can disable offenders independently from slashing * Fix build on CI * Run cargo fmt * Fixes based on review comments * Make parameter naming consistent * Fix migration and some English * Fix migration - again * cargo fmt * Cover 2 new cases with a test --- frame/offences/src/lib.rs | 1 + frame/offences/src/migration.rs | 9 +++- frame/offences/src/mock.rs | 3 +- frame/staking/src/mock.rs | 8 ++-- frame/staking/src/pallet/impls.rs | 4 +- frame/staking/src/slashing.rs | 70 +++++++++++++++---------------- frame/staking/src/tests.rs | 48 +++++++++++++++++++-- primitives/staking/src/offence.rs | 32 ++++++++++++++ 8 files changed, 129 insertions(+), 46 deletions(-) diff --git a/frame/offences/src/lib.rs b/frame/offences/src/lib.rs index ddae73e280d5..c230eac88dce 100644 --- a/frame/offences/src/lib.rs +++ b/frame/offences/src/lib.rs @@ -150,6 +150,7 @@ where &concurrent_offenders, &slash_perbill, offence.session_index(), + offence.disable_strategy(), ); // Deposit the event. diff --git a/frame/offences/src/migration.rs b/frame/offences/src/migration.rs index b6e32cbe69e2..d655f2cec539 100644 --- a/frame/offences/src/migration.rs +++ b/frame/offences/src/migration.rs @@ -19,7 +19,7 @@ use super::{Config, OffenceDetails, Perbill, SessionIndex}; use frame_support::{ generate_storage_alias, pallet_prelude::ValueQuery, traits::Get, weights::Weight, }; -use sp_staking::offence::OnOffenceHandler; +use sp_staking::offence::{DisableStrategy, OnOffenceHandler}; use sp_std::vec::Vec; /// Type of data stored as a deferred offence @@ -41,7 +41,12 @@ pub fn remove_deferred_storage() -> Weight { let deferred = >::take(); log::info!(target: "runtime::offences", "have {} deferred offences, applying.", deferred.len()); for (offences, perbill, session) in deferred.iter() { - let consumed = T::OnOffenceHandler::on_offence(&offences, &perbill, *session); + let consumed = T::OnOffenceHandler::on_offence( + &offences, + &perbill, + *session, + DisableStrategy::WhenSlashed, + ); weight = weight.saturating_add(consumed); } diff --git a/frame/offences/src/mock.rs b/frame/offences/src/mock.rs index 5e4c94944b6f..bce51f527abc 100644 --- a/frame/offences/src/mock.rs +++ b/frame/offences/src/mock.rs @@ -36,7 +36,7 @@ use sp_runtime::{ Perbill, }; use sp_staking::{ - offence::{self, Kind, OffenceDetails}, + offence::{self, DisableStrategy, Kind, OffenceDetails}, SessionIndex, }; use std::cell::RefCell; @@ -55,6 +55,7 @@ impl offence::OnOffenceHandler _offenders: &[OffenceDetails], slash_fraction: &[Perbill], _offence_session: SessionIndex, + _disable_strategy: DisableStrategy, ) -> Weight { ON_OFFENCE_PERBILL.with(|f| { *f.borrow_mut() = slash_fraction.to_vec(); diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index e5a3e4903393..2b74b0188cff 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -33,7 +33,7 @@ use sp_runtime::{ testing::{Header, TestXt, UintAuthorityId}, traits::{IdentityLookup, Zero}, }; -use sp_staking::offence::{OffenceDetails, OnOffenceHandler}; +use sp_staking::offence::{DisableStrategy, OffenceDetails, OnOffenceHandler}; use std::cell::RefCell; pub const INIT_TIMESTAMP: u64 = 30_000; @@ -765,11 +765,12 @@ pub(crate) fn on_offence_in_era( >], slash_fraction: &[Perbill], era: EraIndex, + disable_strategy: DisableStrategy, ) { let bonded_eras = crate::BondedEras::::get(); for &(bonded_era, start_session) in bonded_eras.iter() { if bonded_era == era { - let _ = Staking::on_offence(offenders, slash_fraction, start_session); + let _ = Staking::on_offence(offenders, slash_fraction, start_session, disable_strategy); return } else if bonded_era > era { break @@ -781,6 +782,7 @@ pub(crate) fn on_offence_in_era( offenders, slash_fraction, Staking::eras_start_session_index(era).unwrap(), + disable_strategy, ); } else { panic!("cannot slash in era {}", era); @@ -795,7 +797,7 @@ pub(crate) fn on_offence_now( slash_fraction: &[Perbill], ) { let now = Staking::active_era().unwrap().index; - on_offence_in_era(offenders, slash_fraction, now) + on_offence_in_era(offenders, slash_fraction, now, DisableStrategy::WhenSlashed) } pub(crate) fn add_slash(who: &AccountId) { diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 7ca1cb1a4a61..8d86cfbe6b0d 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -36,7 +36,7 @@ use sp_runtime::{ Perbill, }; use sp_staking::{ - offence::{OffenceDetails, OnOffenceHandler}, + offence::{DisableStrategy, OffenceDetails, OnOffenceHandler}, SessionIndex, }; use sp_std::{collections::btree_map::BTreeMap, prelude::*}; @@ -1137,6 +1137,7 @@ where >], slash_fraction: &[Perbill], slash_session: SessionIndex, + disable_strategy: DisableStrategy, ) -> Weight { let reward_proportion = SlashRewardFraction::::get(); let mut consumed_weight: Weight = 0; @@ -1206,6 +1207,7 @@ where window_start, now: active_era, reward_proportion, + disable_strategy, }); if let Some(mut unapplied) = unapplied { diff --git a/frame/staking/src/slashing.rs b/frame/staking/src/slashing.rs index 414c21aa347f..066142d8ecc2 100644 --- a/frame/staking/src/slashing.rs +++ b/frame/staking/src/slashing.rs @@ -63,6 +63,7 @@ use sp_runtime::{ traits::{Saturating, Zero}, DispatchResult, RuntimeDebug, }; +use sp_staking::offence::DisableStrategy; use sp_std::vec::Vec; /// The proportion of the slashing reward to be paid out on the first slashing detection. @@ -213,6 +214,8 @@ pub(crate) struct SlashParams<'a, T: 'a + Config> { /// The maximum percentage of a slash that ever gets paid out. /// This is f_inf in the paper. pub(crate) reward_proportion: Perbill, + /// When to disable offenders. + pub(crate) disable_strategy: DisableStrategy, } /// Computes a slash of a validator and nominators. It returns an unapplied @@ -224,15 +227,12 @@ pub(crate) struct SlashParams<'a, T: 'a + Config> { pub(crate) fn compute_slash( params: SlashParams, ) -> Option>> { - let SlashParams { stash, slash, exposure, slash_era, window_start, now, reward_proportion } = - params.clone(); - let mut reward_payout = Zero::zero(); let mut val_slashed = Zero::zero(); // is the slash amount here a maximum for the era? - let own_slash = slash * exposure.own; - if slash * exposure.total == Zero::zero() { + let own_slash = params.slash * params.exposure.own; + if params.slash * params.exposure.total == Zero::zero() { // kick out the validator even if they won't be slashed, // as long as the misbehavior is from their most recent slashing span. kick_out_if_recent::(params); @@ -240,13 +240,17 @@ pub(crate) fn compute_slash( } let (prior_slash_p, _era_slash) = - as Store>::ValidatorSlashInEra::get(&slash_era, stash) + as Store>::ValidatorSlashInEra::get(¶ms.slash_era, params.stash) .unwrap_or((Perbill::zero(), Zero::zero())); // compare slash proportions rather than slash values to avoid issues due to rounding // error. - if slash.deconstruct() > prior_slash_p.deconstruct() { - as Store>::ValidatorSlashInEra::insert(&slash_era, stash, &(slash, own_slash)); + if params.slash.deconstruct() > prior_slash_p.deconstruct() { + as Store>::ValidatorSlashInEra::insert( + ¶ms.slash_era, + params.stash, + &(params.slash, own_slash), + ); } else { // we slash based on the max in era - this new event is not the max, // so neither the validator or any nominators will need an update. @@ -261,14 +265,14 @@ pub(crate) fn compute_slash( // apply slash to validator. { let mut spans = fetch_spans::( - stash, - window_start, + params.stash, + params.window_start, &mut reward_payout, &mut val_slashed, - reward_proportion, + params.reward_proportion, ); - let target_span = spans.compare_and_update_span_slash(slash_era, own_slash); + let target_span = spans.compare_and_update_span_slash(params.slash_era, own_slash); if target_span == Some(spans.span_index()) { // misbehavior occurred within the current slashing span - take appropriate @@ -276,20 +280,19 @@ pub(crate) fn compute_slash( // chill the validator - it misbehaved in the current span and should // not continue in the next election. also end the slashing span. - spans.end_span(now); - >::chill_stash(stash); + spans.end_span(params.now); + >::chill_stash(params.stash); } } - // add the validator to the offenders list and make sure it is disabled for - // the duration of the era - add_offending_validator::(params.stash, true); + let disable_when_slashed = params.disable_strategy != DisableStrategy::Never; + add_offending_validator::(params.stash, disable_when_slashed); let mut nominators_slashed = Vec::new(); - reward_payout += slash_nominators::(params, prior_slash_p, &mut nominators_slashed); + reward_payout += slash_nominators::(params.clone(), prior_slash_p, &mut nominators_slashed); Some(UnappliedSlash { - validator: stash.clone(), + validator: params.stash.clone(), own: val_slashed, others: nominators_slashed, reporters: Vec::new(), @@ -316,9 +319,8 @@ fn kick_out_if_recent(params: SlashParams) { >::chill_stash(params.stash); } - // add the validator to the offenders list but since there's no slash being - // applied there's no need to disable the validator - add_offending_validator::(params.stash, false); + let disable_without_slash = params.disable_strategy == DisableStrategy::Always; + add_offending_validator::(params.stash, disable_without_slash); } /// Add the given validator to the offenders list and optionally disable it. @@ -371,13 +373,10 @@ fn slash_nominators( prior_slash_p: Perbill, nominators_slashed: &mut Vec<(T::AccountId, BalanceOf)>, ) -> BalanceOf { - let SlashParams { stash: _, slash, exposure, slash_era, window_start, now, reward_proportion } = - params; - let mut reward_payout = Zero::zero(); - nominators_slashed.reserve(exposure.others.len()); - for nominator in &exposure.others { + nominators_slashed.reserve(params.exposure.others.len()); + for nominator in ¶ms.exposure.others { let stash = &nominator.who; let mut nom_slashed = Zero::zero(); @@ -385,15 +384,16 @@ fn slash_nominators( // had a new max slash for the era. let era_slash = { let own_slash_prior = prior_slash_p * nominator.value; - let own_slash_by_validator = slash * nominator.value; + let own_slash_by_validator = params.slash * nominator.value; let own_slash_difference = own_slash_by_validator.saturating_sub(own_slash_prior); - let mut era_slash = as Store>::NominatorSlashInEra::get(&slash_era, stash) - .unwrap_or_else(|| Zero::zero()); + let mut era_slash = + as Store>::NominatorSlashInEra::get(¶ms.slash_era, stash) + .unwrap_or_else(|| Zero::zero()); era_slash += own_slash_difference; - as Store>::NominatorSlashInEra::insert(&slash_era, stash, &era_slash); + as Store>::NominatorSlashInEra::insert(¶ms.slash_era, stash, &era_slash); era_slash }; @@ -402,18 +402,18 @@ fn slash_nominators( { let mut spans = fetch_spans::( stash, - window_start, + params.window_start, &mut reward_payout, &mut nom_slashed, - reward_proportion, + params.reward_proportion, ); - let target_span = spans.compare_and_update_span_slash(slash_era, era_slash); + let target_span = spans.compare_and_update_span_slash(params.slash_era, era_slash); if target_span == Some(spans.span_index()) { // End the span, but don't chill the nominator. its nomination // on this validator will be ignored in the future. - spans.end_span(now); + spans.end_span(params.now); } } diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 8f13fd785080..f8f37bed0066 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -34,7 +34,7 @@ use sp_runtime::{ Perbill, Percent, }; use sp_staking::{ - offence::{OffenceDetails, OnOffenceHandler}, + offence::{DisableStrategy, OffenceDetails, OnOffenceHandler}, SessionIndex, }; use sp_std::prelude::*; @@ -2250,6 +2250,7 @@ fn slash_in_old_span_does_not_deselect() { }], &[Perbill::from_percent(0)], 1, + DisableStrategy::WhenSlashed, ); // the validator doesn't get chilled again @@ -2266,6 +2267,7 @@ fn slash_in_old_span_does_not_deselect() { // NOTE: A 100% slash here would clean up the account, causing de-registration. &[Perbill::from_percent(95)], 1, + DisableStrategy::WhenSlashed, ); // the validator doesn't get chilled again @@ -2562,6 +2564,7 @@ fn slashing_nominators_by_span_max() { }], &[Perbill::from_percent(10)], 2, + DisableStrategy::WhenSlashed, ); assert_eq!(Balances::free_balance(11), 900); @@ -2588,6 +2591,7 @@ fn slashing_nominators_by_span_max() { }], &[Perbill::from_percent(30)], 3, + DisableStrategy::WhenSlashed, ); // 11 was not further slashed, but 21 and 101 were. @@ -2609,6 +2613,7 @@ fn slashing_nominators_by_span_max() { }], &[Perbill::from_percent(20)], 2, + DisableStrategy::WhenSlashed, ); // 11 was further slashed, but 21 and 101 were not. @@ -2744,6 +2749,7 @@ fn remove_deferred() { &[OffenceDetails { offender: (11, exposure.clone()), reporters: vec![] }], &[Perbill::from_percent(15)], 1, + DisableStrategy::WhenSlashed, ); // fails if empty @@ -2933,6 +2939,40 @@ fn non_slashable_offence_doesnt_disable_validator() { }); } +#[test] +fn slashing_independent_of_disabling_validator() { + ExtBuilder::default().build_and_execute(|| { + mock::start_active_era(1); + assert_eq_uvec!(Session::validators(), vec![11, 21]); + + let exposure_11 = Staking::eras_stakers(Staking::active_era().unwrap().index, &11); + let exposure_21 = Staking::eras_stakers(Staking::active_era().unwrap().index, &21); + + let now = Staking::active_era().unwrap().index; + + // offence with no slash associated, BUT disabling + on_offence_in_era( + &[OffenceDetails { offender: (11, exposure_11.clone()), reporters: vec![] }], + &[Perbill::zero()], + now, + DisableStrategy::Always, + ); + + // offence that slashes 25% of the bond, BUT not disabling + on_offence_in_era( + &[OffenceDetails { offender: (21, exposure_21.clone()), reporters: vec![] }], + &[Perbill::from_percent(25)], + now, + DisableStrategy::Never, + ); + + // the offence for validator 10 was explicitly disabled + assert!(is_disabled(10)); + // whereas validator 20 is explicitly not disabled + assert!(!is_disabled(20)); + }); +} + #[test] fn offence_threshold_triggers_new_era() { ExtBuilder::default() @@ -3595,7 +3635,7 @@ fn offences_weight_calculated_correctly() { ExtBuilder::default().nominate(true).build_and_execute(|| { // On offence with zero offenders: 4 Reads, 1 Write let zero_offence_weight = ::DbWeight::get().reads_writes(4, 1); - assert_eq!(Staking::on_offence(&[], &[Perbill::from_percent(50)], 0), zero_offence_weight); + assert_eq!(Staking::on_offence(&[], &[Perbill::from_percent(50)], 0, DisableStrategy::WhenSlashed), zero_offence_weight); // On Offence with N offenders, Unapplied: 4 Reads, 1 Write + 4 Reads, 5 Writes let n_offence_unapplied_weight = ::DbWeight::get().reads_writes(4, 1) @@ -3608,7 +3648,7 @@ fn offences_weight_calculated_correctly() { reporters: vec![], } ).collect(); - assert_eq!(Staking::on_offence(&offenders, &[Perbill::from_percent(50)], 0), n_offence_unapplied_weight); + assert_eq!(Staking::on_offence(&offenders, &[Perbill::from_percent(50)], 0, DisableStrategy::WhenSlashed), n_offence_unapplied_weight); // On Offence with one offenders, Applied let one_offender = [ @@ -3629,7 +3669,7 @@ fn offences_weight_calculated_correctly() { // `reward_cost` * reporters (1) + ::DbWeight::get().reads_writes(2, 2); - assert_eq!(Staking::on_offence(&one_offender, &[Perbill::from_percent(50)], 0), one_offence_unapplied_weight); + assert_eq!(Staking::on_offence(&one_offender, &[Perbill::from_percent(50)], 0, DisableStrategy::WhenSlashed), one_offence_unapplied_weight); }); } diff --git a/primitives/staking/src/offence.rs b/primitives/staking/src/offence.rs index a91cb47c117b..fdff02d42065 100644 --- a/primitives/staking/src/offence.rs +++ b/primitives/staking/src/offence.rs @@ -37,6 +37,29 @@ pub type Kind = [u8; 16]; /// so that we can slash it accordingly. pub type OffenceCount = u32; +/// In case of an offence, which conditions get an offending validator disabled. +#[derive( + Clone, + Copy, + PartialEq, + Eq, + Hash, + PartialOrd, + Ord, + Encode, + Decode, + sp_runtime::RuntimeDebug, + scale_info::TypeInfo, +)] +pub enum DisableStrategy { + /// Independently of slashing, this offence will not disable the offender. + Never, + /// Only disable the offender if it is also slashed. + WhenSlashed, + /// Independently of slashing, this offence will always disable the offender. + Always, +} + /// A trait implemented by an offence report. /// /// This trait assumes that the offence is legitimate and was validated already. @@ -79,6 +102,11 @@ pub trait Offence { /// number. Note that for GRANDPA the round number is reset each epoch. fn time_slot(&self) -> Self::TimeSlot; + /// In which cases this offence needs to disable offenders until the next era starts. + fn disable_strategy(&self) -> DisableStrategy { + DisableStrategy::WhenSlashed + } + /// A slash fraction of the total exposure that should be slashed for this /// particular offence kind for the given parameters that happened at a singular `TimeSlot`. /// @@ -150,12 +178,15 @@ pub trait OnOffenceHandler { /// /// The `session` parameter is the session index of the offence. /// + /// The `disable_strategy` parameter decides if the offenders need to be disabled immediately. + /// /// The receiver might decide to not accept this offence. In this case, the call site is /// responsible for queuing the report and re-submitting again. fn on_offence( offenders: &[OffenceDetails], slash_fraction: &[Perbill], session: SessionIndex, + disable_strategy: DisableStrategy, ) -> Res; } @@ -164,6 +195,7 @@ impl OnOffenceHandler _offenders: &[OffenceDetails], _slash_fraction: &[Perbill], _session: SessionIndex, + _disable_strategy: DisableStrategy, ) -> Res { Default::default() } From 4c98bbab7fffc9b79525b31caf0e2f346b26185e Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Thu, 18 Nov 2021 00:14:16 -0400 Subject: [PATCH 200/695] Fix Weight Handlebar Template (#10302) * fix template * cargo run --quiet --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_identity --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/identity/src/weights.rs --template=./.maintain/frame-weight-template.hbs Co-authored-by: Parity Bot --- .maintain/frame-weight-template.hbs | 68 +++---- frame/identity/src/weights.rs | 191 +++++++++--------- utils/frame/benchmarking-cli/src/template.hbs | 30 +-- 3 files changed, 144 insertions(+), 145 deletions(-) diff --git a/.maintain/frame-weight-template.hbs b/.maintain/frame-weight-template.hbs index 045140d54dff..4f34707b9602 100644 --- a/.maintain/frame-weight-template.hbs +++ b/.maintain/frame-weight-template.hbs @@ -22,7 +22,7 @@ //! EXECUTION: {{cmd.execution}}, WASM-EXECUTION: {{cmd.wasm_execution}}, CHAIN: {{cmd.chain}}, DB CACHE: {{cmd.db_cache}} // Executed Command: -{{#each args as |arg|~}} +{{#each args as |arg|}} // {{arg}} {{/each}} @@ -35,80 +35,80 @@ use sp_std::marker::PhantomData; /// Weight functions needed for {{pallet}}. pub trait WeightInfo { - {{~#each benchmarks as |benchmark|}} + {{#each benchmarks as |benchmark|}} fn {{benchmark.name~}} ( {{~#each benchmark.components as |c| ~}} {{c.name}}: u32, {{/each~}} ) -> Weight; - {{~/each}} + {{/each}} } /// Weights for {{pallet}} using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); -{{~#if (eq pallet "frame_system")}} +{{#if (eq pallet "frame_system")}} impl WeightInfo for SubstrateWeight { -{{~else}} +{{else}} impl WeightInfo for SubstrateWeight { -{{~/if}} - {{~#each benchmarks as |benchmark|}} - {{~#each benchmark.comments as |comment|}} +{{/if}} + {{#each benchmarks as |benchmark|}} + {{#each benchmark.comments as |comment|}} // {{comment}} - {{~/each}} + {{/each}} fn {{benchmark.name~}} ( {{~#each benchmark.components as |c| ~}} {{~#if (not c.is_used)}}_{{/if}}{{c.name}}: u32, {{/each~}} ) -> Weight { ({{underscore benchmark.base_weight}} as Weight) - {{~#each benchmark.component_weight as |cw|}} + {{#each benchmark.component_weight as |cw|}} // Standard Error: {{underscore cw.error}} .saturating_add(({{underscore cw.slope}} as Weight).saturating_mul({{cw.name}} as Weight)) - {{~/each}} - {{~#if (ne benchmark.base_reads "0")}} + {{/each}} + {{#if (ne benchmark.base_reads "0")}} .saturating_add(T::DbWeight::get().reads({{benchmark.base_reads}} as Weight)) - {{~/if}} - {{~#each benchmark.component_reads as |cr|}} + {{/if}} + {{#each benchmark.component_reads as |cr|}} .saturating_add(T::DbWeight::get().reads(({{cr.slope}} as Weight).saturating_mul({{cr.name}} as Weight))) - {{~/each}} - {{~#if (ne benchmark.base_writes "0")}} + {{/each}} + {{#if (ne benchmark.base_writes "0")}} .saturating_add(T::DbWeight::get().writes({{benchmark.base_writes}} as Weight)) - {{~/if}} - {{~#each benchmark.component_writes as |cw|}} + {{/if}} + {{#each benchmark.component_writes as |cw|}} .saturating_add(T::DbWeight::get().writes(({{cw.slope}} as Weight).saturating_mul({{cw.name}} as Weight))) - {{~/each}} + {{/each}} } - {{~/each}} + {{/each}} } // For backwards compatibility and tests impl WeightInfo for () { - {{~#each benchmarks as |benchmark|}} - {{~#each benchmark.comments as |comment|}} + {{#each benchmarks as |benchmark|}} + {{#each benchmark.comments as |comment|}} // {{comment}} - {{~/each}} + {{/each}} fn {{benchmark.name~}} ( {{~#each benchmark.components as |c| ~}} {{~#if (not c.is_used)}}_{{/if}}{{c.name}}: u32, {{/each~}} ) -> Weight { ({{underscore benchmark.base_weight}} as Weight) - {{~#each benchmark.component_weight as |cw|}} + {{#each benchmark.component_weight as |cw|}} // Standard Error: {{underscore cw.error}} .saturating_add(({{underscore cw.slope}} as Weight).saturating_mul({{cw.name}} as Weight)) - {{~/each}} - {{~#if (ne benchmark.base_reads "0")}} + {{/each}} + {{#if (ne benchmark.base_reads "0")}} .saturating_add(RocksDbWeight::get().reads({{benchmark.base_reads}} as Weight)) - {{~/if}} - {{~#each benchmark.component_reads as |cr|}} + {{/if}} + {{#each benchmark.component_reads as |cr|}} .saturating_add(RocksDbWeight::get().reads(({{cr.slope}} as Weight).saturating_mul({{cr.name}} as Weight))) - {{~/each}} - {{~#if (ne benchmark.base_writes "0")}} + {{/each}} + {{#if (ne benchmark.base_writes "0")}} .saturating_add(RocksDbWeight::get().writes({{benchmark.base_writes}} as Weight)) - {{~/if}} - {{~#each benchmark.component_writes as |cw|}} + {{/if}} + {{#each benchmark.component_writes as |cw|}} .saturating_add(RocksDbWeight::get().writes(({{cw.slope}} as Weight).saturating_mul({{cw.name}} as Weight))) - {{~/each}} + {{/each}} } - {{~/each}} + {{/each}} } diff --git a/frame/identity/src/weights.rs b/frame/identity/src/weights.rs index 611909f326ea..92bc4cbaae92 100644 --- a/frame/identity/src/weights.rs +++ b/frame/identity/src/weights.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_identity //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-08-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2021-11-17, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 // Executed Command: @@ -35,7 +35,6 @@ // --output=./frame/identity/src/weights.rs // --template=./.maintain/frame-weight-template.hbs - #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] #![allow(unused_imports)] @@ -68,19 +67,19 @@ pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { // Storage: Identity Registrars (r:1 w:1) fn add_registrar(r: u32, ) -> Weight { - (22_152_000 as Weight) - // Standard Error: 6_000 - .saturating_add((339_000 as Weight).saturating_mul(r as Weight)) + (19_176_000 as Weight) + // Standard Error: 5_000 + .saturating_add((313_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Identity IdentityOf (r:1 w:1) fn set_identity(r: u32, x: u32, ) -> Weight { - (53_017_000 as Weight) - // Standard Error: 14_000 - .saturating_add((279_000 as Weight).saturating_mul(r as Weight)) + (44_668_000 as Weight) + // Standard Error: 12_000 + .saturating_add((244_000 as Weight).saturating_mul(r as Weight)) // Standard Error: 1_000 - .saturating_add((1_081_000 as Weight).saturating_mul(x as Weight)) + .saturating_add((811_000 as Weight).saturating_mul(x as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -88,9 +87,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Identity SubsOf (r:1 w:1) // Storage: Identity SuperOf (r:1 w:1) fn set_subs_new(s: u32, ) -> Weight { - (44_693_000 as Weight) - // Standard Error: 1_000 - .saturating_add((6_631_000 as Weight).saturating_mul(s as Weight)) + (38_917_000 as Weight) + // Standard Error: 3_000 + .saturating_add((5_331_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -100,9 +99,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Identity SubsOf (r:1 w:1) // Storage: Identity SuperOf (r:0 w:1) fn set_subs_old(p: u32, ) -> Weight { - (42_017_000 as Weight) + (36_057_000 as Weight) // Standard Error: 1_000 - .saturating_add((2_193_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((1_756_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(p as Weight))) @@ -111,13 +110,13 @@ impl WeightInfo for SubstrateWeight { // Storage: Identity IdentityOf (r:1 w:1) // Storage: Identity SuperOf (r:0 w:100) fn clear_identity(r: u32, s: u32, x: u32, ) -> Weight { - (50_989_000 as Weight) - // Standard Error: 11_000 - .saturating_add((258_000 as Weight).saturating_mul(r as Weight)) + (44_348_000 as Weight) + // Standard Error: 9_000 + .saturating_add((183_000 as Weight).saturating_mul(r as Weight)) // Standard Error: 1_000 - .saturating_add((2_184_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((1_724_000 as Weight).saturating_mul(s as Weight)) // Standard Error: 1_000 - .saturating_add((579_000 as Weight).saturating_mul(x as Weight)) + .saturating_add((439_000 as Weight).saturating_mul(x as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) @@ -125,56 +124,56 @@ impl WeightInfo for SubstrateWeight { // Storage: Identity Registrars (r:1 w:0) // Storage: Identity IdentityOf (r:1 w:1) fn request_judgement(r: u32, x: u32, ) -> Weight { - (55_562_000 as Weight) + (46_592_000 as Weight) // Standard Error: 5_000 - .saturating_add((317_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((321_000 as Weight).saturating_mul(r as Weight)) // Standard Error: 0 - .saturating_add((1_137_000 as Weight).saturating_mul(x as Weight)) + .saturating_add((858_000 as Weight).saturating_mul(x as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Identity IdentityOf (r:1 w:1) fn cancel_request(r: u32, x: u32, ) -> Weight { - (51_744_000 as Weight) + (43_556_000 as Weight) // Standard Error: 6_000 - .saturating_add((192_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((174_000 as Weight).saturating_mul(r as Weight)) // Standard Error: 0 - .saturating_add((1_131_000 as Weight).saturating_mul(x as Weight)) + .saturating_add((850_000 as Weight).saturating_mul(x as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Identity Registrars (r:1 w:1) fn set_fee(r: u32, ) -> Weight { - (9_472_000 as Weight) - // Standard Error: 3_000 - .saturating_add((321_000 as Weight).saturating_mul(r as Weight)) + (7_971_000 as Weight) + // Standard Error: 4_000 + .saturating_add((283_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Identity Registrars (r:1 w:1) fn set_account_id(r: u32, ) -> Weight { - (9_705_000 as Weight) - // Standard Error: 3_000 - .saturating_add((312_000 as Weight).saturating_mul(r as Weight)) + (8_234_000 as Weight) + // Standard Error: 4_000 + .saturating_add((280_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Identity Registrars (r:1 w:1) fn set_fields(r: u32, ) -> Weight { - (9_537_000 as Weight) - // Standard Error: 3_000 - .saturating_add((318_000 as Weight).saturating_mul(r as Weight)) + (8_126_000 as Weight) + // Standard Error: 4_000 + .saturating_add((275_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Identity Registrars (r:1 w:0) // Storage: Identity IdentityOf (r:1 w:1) fn provide_judgement(r: u32, x: u32, ) -> Weight { - (36_298_000 as Weight) + (30_949_000 as Weight) // Standard Error: 5_000 - .saturating_add((284_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((286_000 as Weight).saturating_mul(r as Weight)) // Standard Error: 0 - .saturating_add((1_141_000 as Weight).saturating_mul(x as Weight)) + .saturating_add((856_000 as Weight).saturating_mul(x as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -183,11 +182,11 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:1 w:1) // Storage: Identity SuperOf (r:0 w:100) fn kill_identity(r: u32, s: u32, _x: u32, ) -> Weight { - (63_238_000 as Weight) - // Standard Error: 10_000 - .saturating_add((246_000 as Weight).saturating_mul(r as Weight)) + (63_792_000 as Weight) + // Standard Error: 11_000 + .saturating_add((242_000 as Weight).saturating_mul(r as Weight)) // Standard Error: 1_000 - .saturating_add((2_184_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((1_738_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) @@ -196,18 +195,18 @@ impl WeightInfo for SubstrateWeight { // Storage: Identity SuperOf (r:1 w:1) // Storage: Identity SubsOf (r:1 w:1) fn add_sub(s: u32, ) -> Weight { - (57_394_000 as Weight) + (48_751_000 as Weight) // Standard Error: 1_000 - .saturating_add((208_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((193_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Identity IdentityOf (r:1 w:0) // Storage: Identity SuperOf (r:1 w:1) fn rename_sub(s: u32, ) -> Weight { - (18_274_000 as Weight) + (15_892_000 as Weight) // Standard Error: 0 - .saturating_add((52_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((49_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -215,18 +214,18 @@ impl WeightInfo for SubstrateWeight { // Storage: Identity SuperOf (r:1 w:1) // Storage: Identity SubsOf (r:1 w:1) fn remove_sub(s: u32, ) -> Weight { - (58_184_000 as Weight) + (49_746_000 as Weight) // Standard Error: 1_000 - .saturating_add((195_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((181_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Identity SuperOf (r:1 w:1) // Storage: Identity SubsOf (r:1 w:1) fn quit_sub(s: u32, ) -> Weight { - (36_304_000 as Weight) + (32_286_000 as Weight) // Standard Error: 1_000 - .saturating_add((191_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((166_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -236,19 +235,19 @@ impl WeightInfo for SubstrateWeight { impl WeightInfo for () { // Storage: Identity Registrars (r:1 w:1) fn add_registrar(r: u32, ) -> Weight { - (22_152_000 as Weight) - // Standard Error: 6_000 - .saturating_add((339_000 as Weight).saturating_mul(r as Weight)) + (19_176_000 as Weight) + // Standard Error: 5_000 + .saturating_add((313_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Identity IdentityOf (r:1 w:1) fn set_identity(r: u32, x: u32, ) -> Weight { - (53_017_000 as Weight) - // Standard Error: 14_000 - .saturating_add((279_000 as Weight).saturating_mul(r as Weight)) + (44_668_000 as Weight) + // Standard Error: 12_000 + .saturating_add((244_000 as Weight).saturating_mul(r as Weight)) // Standard Error: 1_000 - .saturating_add((1_081_000 as Weight).saturating_mul(x as Weight)) + .saturating_add((811_000 as Weight).saturating_mul(x as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -256,9 +255,9 @@ impl WeightInfo for () { // Storage: Identity SubsOf (r:1 w:1) // Storage: Identity SuperOf (r:1 w:1) fn set_subs_new(s: u32, ) -> Weight { - (44_693_000 as Weight) - // Standard Error: 1_000 - .saturating_add((6_631_000 as Weight).saturating_mul(s as Weight)) + (38_917_000 as Weight) + // Standard Error: 3_000 + .saturating_add((5_331_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -268,9 +267,9 @@ impl WeightInfo for () { // Storage: Identity SubsOf (r:1 w:1) // Storage: Identity SuperOf (r:0 w:1) fn set_subs_old(p: u32, ) -> Weight { - (42_017_000 as Weight) + (36_057_000 as Weight) // Standard Error: 1_000 - .saturating_add((2_193_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((1_756_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(p as Weight))) @@ -279,13 +278,13 @@ impl WeightInfo for () { // Storage: Identity IdentityOf (r:1 w:1) // Storage: Identity SuperOf (r:0 w:100) fn clear_identity(r: u32, s: u32, x: u32, ) -> Weight { - (50_989_000 as Weight) - // Standard Error: 11_000 - .saturating_add((258_000 as Weight).saturating_mul(r as Weight)) + (44_348_000 as Weight) + // Standard Error: 9_000 + .saturating_add((183_000 as Weight).saturating_mul(r as Weight)) // Standard Error: 1_000 - .saturating_add((2_184_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((1_724_000 as Weight).saturating_mul(s as Weight)) // Standard Error: 1_000 - .saturating_add((579_000 as Weight).saturating_mul(x as Weight)) + .saturating_add((439_000 as Weight).saturating_mul(x as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) @@ -293,56 +292,56 @@ impl WeightInfo for () { // Storage: Identity Registrars (r:1 w:0) // Storage: Identity IdentityOf (r:1 w:1) fn request_judgement(r: u32, x: u32, ) -> Weight { - (55_562_000 as Weight) + (46_592_000 as Weight) // Standard Error: 5_000 - .saturating_add((317_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((321_000 as Weight).saturating_mul(r as Weight)) // Standard Error: 0 - .saturating_add((1_137_000 as Weight).saturating_mul(x as Weight)) + .saturating_add((858_000 as Weight).saturating_mul(x as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Identity IdentityOf (r:1 w:1) fn cancel_request(r: u32, x: u32, ) -> Weight { - (51_744_000 as Weight) + (43_556_000 as Weight) // Standard Error: 6_000 - .saturating_add((192_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((174_000 as Weight).saturating_mul(r as Weight)) // Standard Error: 0 - .saturating_add((1_131_000 as Weight).saturating_mul(x as Weight)) + .saturating_add((850_000 as Weight).saturating_mul(x as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Identity Registrars (r:1 w:1) fn set_fee(r: u32, ) -> Weight { - (9_472_000 as Weight) - // Standard Error: 3_000 - .saturating_add((321_000 as Weight).saturating_mul(r as Weight)) + (7_971_000 as Weight) + // Standard Error: 4_000 + .saturating_add((283_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Identity Registrars (r:1 w:1) fn set_account_id(r: u32, ) -> Weight { - (9_705_000 as Weight) - // Standard Error: 3_000 - .saturating_add((312_000 as Weight).saturating_mul(r as Weight)) + (8_234_000 as Weight) + // Standard Error: 4_000 + .saturating_add((280_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Identity Registrars (r:1 w:1) fn set_fields(r: u32, ) -> Weight { - (9_537_000 as Weight) - // Standard Error: 3_000 - .saturating_add((318_000 as Weight).saturating_mul(r as Weight)) + (8_126_000 as Weight) + // Standard Error: 4_000 + .saturating_add((275_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Identity Registrars (r:1 w:0) // Storage: Identity IdentityOf (r:1 w:1) fn provide_judgement(r: u32, x: u32, ) -> Weight { - (36_298_000 as Weight) + (30_949_000 as Weight) // Standard Error: 5_000 - .saturating_add((284_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((286_000 as Weight).saturating_mul(r as Weight)) // Standard Error: 0 - .saturating_add((1_141_000 as Weight).saturating_mul(x as Weight)) + .saturating_add((856_000 as Weight).saturating_mul(x as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -351,11 +350,11 @@ impl WeightInfo for () { // Storage: System Account (r:1 w:1) // Storage: Identity SuperOf (r:0 w:100) fn kill_identity(r: u32, s: u32, _x: u32, ) -> Weight { - (63_238_000 as Weight) - // Standard Error: 10_000 - .saturating_add((246_000 as Weight).saturating_mul(r as Weight)) + (63_792_000 as Weight) + // Standard Error: 11_000 + .saturating_add((242_000 as Weight).saturating_mul(r as Weight)) // Standard Error: 1_000 - .saturating_add((2_184_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((1_738_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) @@ -364,18 +363,18 @@ impl WeightInfo for () { // Storage: Identity SuperOf (r:1 w:1) // Storage: Identity SubsOf (r:1 w:1) fn add_sub(s: u32, ) -> Weight { - (57_394_000 as Weight) + (48_751_000 as Weight) // Standard Error: 1_000 - .saturating_add((208_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((193_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Identity IdentityOf (r:1 w:0) // Storage: Identity SuperOf (r:1 w:1) fn rename_sub(s: u32, ) -> Weight { - (18_274_000 as Weight) + (15_892_000 as Weight) // Standard Error: 0 - .saturating_add((52_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((49_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -383,18 +382,18 @@ impl WeightInfo for () { // Storage: Identity SuperOf (r:1 w:1) // Storage: Identity SubsOf (r:1 w:1) fn remove_sub(s: u32, ) -> Weight { - (58_184_000 as Weight) + (49_746_000 as Weight) // Standard Error: 1_000 - .saturating_add((195_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((181_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Identity SuperOf (r:1 w:1) // Storage: Identity SubsOf (r:1 w:1) fn quit_sub(s: u32, ) -> Weight { - (36_304_000 as Weight) + (32_286_000 as Weight) // Standard Error: 1_000 - .saturating_add((191_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((166_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } diff --git a/utils/frame/benchmarking-cli/src/template.hbs b/utils/frame/benchmarking-cli/src/template.hbs index 36abf27f59a6..ea734e165919 100644 --- a/utils/frame/benchmarking-cli/src/template.hbs +++ b/utils/frame/benchmarking-cli/src/template.hbs @@ -6,7 +6,7 @@ //! EXECUTION: {{cmd.execution}}, WASM-EXECUTION: {{cmd.wasm_execution}}, CHAIN: {{cmd.chain}}, DB CACHE: {{cmd.db_cache}} // Executed Command: -{{#each args as |arg|~}} +{{#each args as |arg|}} // {{arg}} {{/each}} @@ -20,32 +20,32 @@ use sp_std::marker::PhantomData; /// Weight functions for `{{pallet}}`. pub struct WeightInfo(PhantomData); impl {{pallet}}::WeightInfo for WeightInfo { - {{~#each benchmarks as |benchmark|}} - {{~#each benchmark.comments as |comment|}} + {{#each benchmarks as |benchmark|}} + {{#each benchmark.comments as |comment|}} // {{comment}} - {{~/each}} + {{/each}} fn {{benchmark.name~}} ( {{~#each benchmark.components as |c| ~}} {{~#if (not c.is_used)}}_{{/if}}{{c.name}}: u32, {{/each~}} ) -> Weight { ({{underscore benchmark.base_weight}} as Weight) - {{~#each benchmark.component_weight as |cw|}} + {{#each benchmark.component_weight as |cw|}} // Standard Error: {{underscore cw.error}} .saturating_add(({{underscore cw.slope}} as Weight).saturating_mul({{cw.name}} as Weight)) - {{~/each}} - {{~#if (ne benchmark.base_reads "0")}} + {{/each}} + {{#if (ne benchmark.base_reads "0")}} .saturating_add(T::DbWeight::get().reads({{benchmark.base_reads}} as Weight)) - {{~/if}} - {{~#each benchmark.component_reads as |cr|}} + {{/if}} + {{#each benchmark.component_reads as |cr|}} .saturating_add(T::DbWeight::get().reads(({{cr.slope}} as Weight).saturating_mul({{cr.name}} as Weight))) - {{~/each}} - {{~#if (ne benchmark.base_writes "0")}} + {{/each}} + {{#if (ne benchmark.base_writes "0")}} .saturating_add(T::DbWeight::get().writes({{benchmark.base_writes}} as Weight)) - {{~/if}} - {{~#each benchmark.component_writes as |cw|}} + {{/if}} + {{#each benchmark.component_writes as |cw|}} .saturating_add(T::DbWeight::get().writes(({{cw.slope}} as Weight).saturating_mul({{cw.name}} as Weight))) - {{~/each}} + {{/each}} } - {{~/each}} + {{/each}} } From 0214f26b5fb6afb89b5322aa59e18b1d19e88a54 Mon Sep 17 00:00:00 2001 From: MOZGIII Date: Thu, 18 Nov 2021 12:05:48 +0300 Subject: [PATCH 201/695] Set current dir at check_wasm_toolchain_installed at wasm-builder (#10284) * Set current dir at check_wasm_toolchain_installed * Add comments --- utils/wasm-builder/src/prerequisites.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/utils/wasm-builder/src/prerequisites.rs b/utils/wasm-builder/src/prerequisites.rs index 7236b8169bcb..88b1073a2951 100644 --- a/utils/wasm-builder/src/prerequisites.rs +++ b/utils/wasm-builder/src/prerequisites.rs @@ -120,6 +120,9 @@ fn check_wasm_toolchain_installed( let manifest_path = temp.path().join("Cargo.toml").display().to_string(); let mut build_cmd = cargo_command.command(); + // Chdir to temp to avoid including project's .cargo/config.toml + // by accident - it can happen in some CI environments. + build_cmd.current_dir(&temp); build_cmd.args(&[ "build", "--target=wasm32-unknown-unknown", @@ -132,6 +135,9 @@ fn check_wasm_toolchain_installed( } let mut run_cmd = cargo_command.command(); + // Chdir to temp to avoid including project's .cargo/config.toml + // by accident - it can happen in some CI environments. + run_cmd.current_dir(&temp); run_cmd.args(&["run", "--manifest-path", &manifest_path]); // Unset the `CARGO_TARGET_DIR` to prevent a cargo deadlock From e670c040d42132da982e156e25a385df213354ed Mon Sep 17 00:00:00 2001 From: Koute Date: Thu, 18 Nov 2021 20:16:38 +0900 Subject: [PATCH 202/695] Clear WASM linear memory on other OSes besides Linux too (#10291) --- client/executor/src/integration_tests/mod.rs | 78 +++++++++++++++++++ .../executor/wasmtime/src/instance_wrapper.rs | 16 ++-- client/executor/wasmtime/src/runtime.rs | 8 +- 3 files changed, 91 insertions(+), 11 deletions(-) diff --git a/client/executor/src/integration_tests/mod.rs b/client/executor/src/integration_tests/mod.rs index 7aa02a61dba1..01c040687ddd 100644 --- a/client/executor/src/integration_tests/mod.rs +++ b/client/executor/src/integration_tests/mod.rs @@ -699,3 +699,81 @@ fn panic_in_spawned_instance_panics_on_joining_its_result(wasm_method: WasmExecu assert!(format!("{}", error_result).contains("Spawned task")); } + +test_wasm_execution!(memory_is_cleared_between_invocations); +fn memory_is_cleared_between_invocations(wasm_method: WasmExecutionMethod) { + // This is based on the code generated by compiling a runtime *without* + // the `-C link-arg=--import-memory` using the following code and then + // disassembling the resulting blob with `wasm-dis`: + // + // ``` + // #[no_mangle] + // #[cfg(not(feature = "std"))] + // pub fn returns_no_bss_mutable_static(_: *mut u8, _: usize) -> u64 { + // static mut COUNTER: usize = 0; + // let output = unsafe { + // COUNTER += 1; + // COUNTER as u64 + // }; + // sp_core::to_substrate_wasm_fn_return_value(&output) + // } + // ``` + // + // This results in the BSS section to *not* be emitted, hence the executor has no way + // of knowing about the `static` variable's existence, so this test will fail if the linear + // memory is not properly cleared between invocations. + let binary = wat::parse_str(r#" + (module + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $i32_i32_=>_i64 (func (param i32 i32) (result i64))) + (import "env" "ext_allocator_malloc_version_1" (func $ext_allocator_malloc_version_1 (param i32) (result i32))) + (global $__stack_pointer (mut i32) (i32.const 1048576)) + (global $global$1 i32 (i32.const 1048580)) + (global $global$2 i32 (i32.const 1048592)) + (memory $0 17) + (export "memory" (memory $0)) + (export "returns_no_bss_mutable_static" (func $returns_no_bss_mutable_static)) + (export "__data_end" (global $global$1)) + (export "__heap_base" (global $global$2)) + (func $returns_no_bss_mutable_static (param $0 i32) (param $1 i32) (result i64) + (local $2 i32) + (local $3 i32) + (i32.store offset=1048576 + (i32.const 0) + (local.tee $2 + (i32.add + (i32.load offset=1048576 (i32.const 0)) + (i32.const 1) + ) + ) + ) + (i64.store + (local.tee $3 + (call $ext_allocator_malloc_version_1 (i32.const 8)) + ) + (i64.extend_i32_u (local.get $2)) + ) + (i64.or + (i64.extend_i32_u (local.get $3)) + (i64.const 34359738368) + ) + ) + )"#).unwrap(); + + let runtime = crate::wasm_runtime::create_wasm_runtime_with_code( + wasm_method, + 1024, + RuntimeBlob::uncompress_if_needed(&binary[..]).unwrap(), + HostFunctions::host_functions(), + true, + None, + ) + .unwrap(); + + let mut instance = runtime.new_instance().unwrap(); + let res = instance.call_export("returns_no_bss_mutable_static", &[0]).unwrap(); + assert_eq!(1, u64::decode(&mut &res[..]).unwrap()); + + let res = instance.call_export("returns_no_bss_mutable_static", &[0]).unwrap(); + assert_eq!(1, u64::decode(&mut &res[..]).unwrap()); +} diff --git a/client/executor/wasmtime/src/instance_wrapper.rs b/client/executor/wasmtime/src/instance_wrapper.rs index 2b8508ee2b07..1d40563d0a9f 100644 --- a/client/executor/wasmtime/src/instance_wrapper.rs +++ b/client/executor/wasmtime/src/instance_wrapper.rs @@ -403,10 +403,10 @@ impl InstanceWrapper { self.memory.data_ptr(ctx) } - /// Removes physical backing from the allocated linear memory. This leads to returning the - /// memory back to the system. While the memory is zeroed this is considered as a side-effect - /// and is not relied upon. Thus this function acts as a hint. - pub fn decommit(&self, ctx: impl AsContext) { + /// If possible removes physical backing from the allocated linear memory which + /// leads to returning the memory back to the system; this also zeroes the memory + /// as a side-effect. + pub fn decommit(&self, mut ctx: impl AsContextMut) { if self.memory.data_size(&ctx) == 0 { return } @@ -417,7 +417,7 @@ impl InstanceWrapper { unsafe { let ptr = self.memory.data_ptr(&ctx); - let len = self.memory.data_size(ctx); + let len = self.memory.data_size(&ctx); // Linux handles MADV_DONTNEED reliably. The result is that the given area // is unmapped and will be zeroed on the next pagefault. @@ -429,9 +429,15 @@ impl InstanceWrapper { std::io::Error::last_os_error(), ); }); + } else { + return; } } } } + + // If we're on an unsupported OS or the memory couldn't have been + // decommited for some reason then just manually zero it out. + self.memory.data_mut(ctx.as_context_mut()).fill(0); } } diff --git a/client/executor/wasmtime/src/runtime.rs b/client/executor/wasmtime/src/runtime.rs index bd113c338383..4d107862173b 100644 --- a/client/executor/wasmtime/src/runtime.rs +++ b/client/executor/wasmtime/src/runtime.rs @@ -237,7 +237,7 @@ impl WasmInstance for WasmtimeInstance { // Signal to the OS that we are done with the linear memory and that it can be // reclaimed. - instance_wrapper.decommit(&store); + instance_wrapper.decommit(store); result }, @@ -415,11 +415,7 @@ pub struct Semantics { /// /// Primarily this is achieved by not recreating the instance for each call and performing a /// bare minimum clean up: reapplying the data segments and restoring the values for global - /// variables. The vast majority of the linear memory is not restored, meaning that effects - /// of previous executions on the same [`WasmInstance`] can be observed there. - /// - /// This is not a problem for a standard substrate runtime execution because it's up to the - /// runtime itself to make sure that it doesn't involve any non-determinism. + /// variables. /// /// Since this feature depends on instrumentation, it can be set only if runtime is /// instantiated using the runtime blob, e.g. using [`create_runtime`]. From 80bc4a0c79f840e36059eae5427045086b7b8d9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 18 Nov 2021 21:12:08 +0100 Subject: [PATCH 203/695] Make authorship soft deadline configurable. (#10125) * Make soft deadline configurable. * cargo +nightly fmt --all * Move setter where it belongs. --- .../basic-authorship/src/basic_authorship.rs | 37 ++++++++++++++++++- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/client/basic-authorship/src/basic_authorship.rs b/client/basic-authorship/src/basic_authorship.rs index 4c7f6c856ec8..0fd3932807a1 100644 --- a/client/basic-authorship/src/basic_authorship.rs +++ b/client/basic-authorship/src/basic_authorship.rs @@ -42,7 +42,7 @@ use sp_inherents::InherentData; use sp_runtime::{ generic::BlockId, traits::{BlakeTwo256, Block as BlockT, Hash as HashT, Header as HeaderT}, - Digest, + Digest, Percent, SaturatedConversion, }; use std::{marker::PhantomData, pin::Pin, sync::Arc, time}; @@ -58,6 +58,8 @@ use sc_proposer_metrics::MetricsLink as PrometheusMetrics; /// transferred to other nodes. pub const DEFAULT_BLOCK_SIZE_LIMIT: usize = 4 * 1024 * 1024 + 512; +const DEFAULT_SOFT_DEADLINE_PERCENT: Percent = Percent::from_percent(50); + /// [`Proposer`] factory. pub struct ProposerFactory { spawn_handle: Box, @@ -72,6 +74,14 @@ pub struct ProposerFactory { /// If no `block_size_limit` is passed to [`sp_consensus::Proposer::propose`], this block size /// limit will be used. default_block_size_limit: usize, + /// Soft deadline percentage of hard deadline. + /// + /// The value is used to compute soft deadline during block production. + /// The soft deadline indicates where we should stop attempting to add transactions + /// to the block, which exhaust resources. After soft deadline is reached, + /// we switch to a fixed-amount mode, in which after we see `MAX_SKIPPED_TRANSACTIONS` + /// transactions which exhaust resrouces, we will conclude that the block is full. + soft_deadline_percent: Percent, telemetry: Option, /// When estimating the block size, should the proof be included? include_proof_in_block_size_estimation: bool, @@ -96,6 +106,7 @@ impl ProposerFactory { transaction_pool, metrics: PrometheusMetrics::new(prometheus), default_block_size_limit: DEFAULT_BLOCK_SIZE_LIMIT, + soft_deadline_percent: DEFAULT_SOFT_DEADLINE_PERCENT, telemetry, client, include_proof_in_block_size_estimation: false, @@ -124,6 +135,7 @@ impl ProposerFactory { transaction_pool, metrics: PrometheusMetrics::new(prometheus), default_block_size_limit: DEFAULT_BLOCK_SIZE_LIMIT, + soft_deadline_percent: DEFAULT_SOFT_DEADLINE_PERCENT, telemetry, include_proof_in_block_size_estimation: true, _phantom: PhantomData, @@ -147,6 +159,22 @@ impl ProposerFactory { pub fn set_default_block_size_limit(&mut self, limit: usize) { self.default_block_size_limit = limit; } + + /// Set soft deadline percentage. + /// + /// The value is used to compute soft deadline during block production. + /// The soft deadline indicates where we should stop attempting to add transactions + /// to the block, which exhaust resources. After soft deadline is reached, + /// we switch to a fixed-amount mode, in which after we see `MAX_SKIPPED_TRANSACTIONS` + /// transactions which exhaust resrouces, we will conclude that the block is full. + /// + /// Setting the value too low will significantly limit the amount of transactions + /// we try in case they exhaust resources. Setting the value too high can + /// potentially open a DoS vector, where many "exhaust resources" transactions + /// are being tried with no success, hence block producer ends up creating an empty block. + pub fn set_soft_deadline(&mut self, percent: Percent) { + self.soft_deadline_percent = percent; + } } impl ProposerFactory @@ -184,6 +212,7 @@ where now, metrics: self.metrics.clone(), default_block_size_limit: self.default_block_size_limit, + soft_deadline_percent: self.soft_deadline_percent, telemetry: self.telemetry.clone(), _phantom: PhantomData, include_proof_in_block_size_estimation: self.include_proof_in_block_size_estimation, @@ -229,6 +258,7 @@ pub struct Proposer { metrics: PrometheusMetrics, default_block_size_limit: usize, include_proof_in_block_size_estimation: bool, + soft_deadline_percent: Percent, telemetry: Option, _phantom: PhantomData<(B, PR)>, } @@ -340,7 +370,10 @@ where // proceed with transactions // We calculate soft deadline used only in case we start skipping transactions. let now = (self.now)(); - let soft_deadline = now + deadline.saturating_duration_since(now) / 2; + let left = deadline.saturating_duration_since(now); + let left_micros: u64 = left.as_micros().saturated_into(); + let soft_deadline = + now + time::Duration::from_micros(self.soft_deadline_percent.mul_floor(left_micros)); let block_timer = time::Instant::now(); let mut skipped = 0; let mut unqueue_invalid = Vec::new(); From 3d4f1866ebb3cc73cceb12548b15775cedd3e475 Mon Sep 17 00:00:00 2001 From: Qinxuan Chen Date: Fri, 19 Nov 2021 06:08:17 +0800 Subject: [PATCH 204/695] Migrate all doc to new pallet macro (#10187) * Migrate all doc to new pallet macro Signed-off-by: koushiro * Fix indent Signed-off-by: koushiro * Fix format Signed-off-by: koushiro --- bin/node-template/pallets/template/src/lib.rs | 2 +- frame/assets/README.md | 50 +++++++++++-------- frame/assets/src/lib.rs | 21 ++++---- frame/assets/src/mock.rs | 2 +- frame/collective/src/tests.rs | 3 +- frame/democracy/src/lib.rs | 13 ++--- frame/im-online/README.md | 34 ++++++++----- frame/im-online/src/lib.rs | 39 ++++++++------- frame/lottery/src/lib.rs | 4 +- frame/nicks/src/lib.rs | 8 +-- frame/node-authorization/src/lib.rs | 2 +- frame/randomness-collective-flip/README.md | 34 ++++++++----- frame/randomness-collective-flip/src/lib.rs | 8 +-- frame/recovery/src/lib.rs | 4 +- frame/scored-pool/README.md | 41 ++++++++------- frame/scored-pool/src/lib.rs | 27 ++++++---- frame/staking/README.md | 24 ++++++--- frame/staking/src/lib.rs | 22 +++++--- frame/sudo/README.md | 25 ++++++---- frame/sudo/src/lib.rs | 15 +++--- frame/system/README.md | 37 ++++++++------ frame/timestamp/README.md | 37 ++++++++------ frame/timestamp/src/lib.rs | 26 ++++++---- 23 files changed, 276 insertions(+), 202 deletions(-) diff --git a/bin/node-template/pallets/template/src/lib.rs b/bin/node-template/pallets/template/src/lib.rs index 18599168f1a6..f5ce8c5a0f7f 100644 --- a/bin/node-template/pallets/template/src/lib.rs +++ b/bin/node-template/pallets/template/src/lib.rs @@ -16,7 +16,7 @@ mod benchmarking; #[frame_support::pallet] pub mod pallet { - use frame_support::{dispatch::DispatchResult, pallet_prelude::*}; + use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; /// Configure the pallet by specifying the parameters and types on which it depends. diff --git a/frame/assets/README.md b/frame/assets/README.md index a99b60fa33d5..aae5244953e5 100644 --- a/frame/assets/README.md +++ b/frame/assets/README.md @@ -69,35 +69,43 @@ Import the Assets module and types and derive your runtime's configuration trait ```rust use pallet_assets as assets; -use frame_support::{decl_module, dispatch, ensure}; -use frame_system::ensure_signed; use sp_runtime::ArithmeticError; -pub trait Config: assets::Config { } +#[frame_support::pallet] +pub mod pallet { + use super::*; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; -decl_module! { - pub struct Module for enum Call where origin: T::Origin { - pub fn issue_token_airdrop(origin) -> dispatch::DispatchResult { - let sender = ensure_signed(origin).map_err(|e| e.as_str())?; + #[pallet::pallet] + pub struct Pallet(_); - const ACCOUNT_ALICE: u64 = 1; - const ACCOUNT_BOB: u64 = 2; - const COUNT_AIRDROP_RECIPIENTS: u64 = 2; - const TOKENS_FIXED_SUPPLY: u64 = 100; + #[pallet::config] + pub trait Config: frame_system::Config + assets::Config {} - ensure!(!COUNT_AIRDROP_RECIPIENTS.is_zero(), ArithmeticError::DivisionByZero); + #[pallet::call] + impl Pallet { + pub fn issue_token_airdrop(origin: OriginFor) -> DispatchResult { + let sender = ensure_signed(origin)?; - let asset_id = Self::next_asset_id(); + const ACCOUNT_ALICE: u64 = 1; + const ACCOUNT_BOB: u64 = 2; + const COUNT_AIRDROP_RECIPIENTS: u64 = 2; + const TOKENS_FIXED_SUPPLY: u64 = 100; - >::mutate(|asset_id| *asset_id += 1); - >::insert((asset_id, &ACCOUNT_ALICE), TOKENS_FIXED_SUPPLY / COUNT_AIRDROP_RECIPIENTS); - >::insert((asset_id, &ACCOUNT_BOB), TOKENS_FIXED_SUPPLY / COUNT_AIRDROP_RECIPIENTS); - >::insert(asset_id, TOKENS_FIXED_SUPPLY); + ensure!(!COUNT_AIRDROP_RECIPIENTS.is_zero(), ArithmeticError::DivisionByZero); - Self::deposit_event(RawEvent::Issued(asset_id, sender, TOKENS_FIXED_SUPPLY)); - Ok(()) - } - } + let asset_id = Self::next_asset_id(); + + >::mutate(|asset_id| *asset_id += 1); + >::insert((asset_id, &ACCOUNT_ALICE), TOKENS_FIXED_SUPPLY / COUNT_AIRDROP_RECIPIENTS); + >::insert((asset_id, &ACCOUNT_BOB), TOKENS_FIXED_SUPPLY / COUNT_AIRDROP_RECIPIENTS); + >::insert(asset_id, TOKENS_FIXED_SUPPLY); + + Self::deposit_event(Event::Issued(asset_id, sender, TOKENS_FIXED_SUPPLY)); + Ok(()) + } + } } ``` diff --git a/frame/assets/src/lib.rs b/frame/assets/src/lib.rs index f2bc86843ad9..940120954f96 100644 --- a/frame/assets/src/lib.rs +++ b/frame/assets/src/lib.rs @@ -140,6 +140,15 @@ mod types; pub use types::*; use codec::HasCompact; +use scale_info::TypeInfo; +use sp_runtime::{ + traits::{ + AtLeast32BitUnsigned, Bounded, CheckedAdd, CheckedSub, Saturating, StaticLookup, Zero, + }, + ArithmeticError, TokenError, +}; +use sp_std::{borrow::Borrow, convert::TryInto, prelude::*}; + use frame_support::{ dispatch::{DispatchError, DispatchResult}, ensure, @@ -151,16 +160,6 @@ use frame_support::{ }, }; use frame_system::Config as SystemConfig; -use sp_runtime::{ - traits::{ - AtLeast32BitUnsigned, Bounded, CheckedAdd, CheckedSub, Saturating, StaticLookup, Zero, - }, - ArithmeticError, TokenError, -}; -use sp_std::{borrow::Borrow, prelude::*}; - -#[cfg(feature = "std")] -use frame_support::traits::GenesisBuild; pub use pallet::*; pub use weights::WeightInfo; @@ -168,7 +167,7 @@ pub use weights::WeightInfo; #[frame_support::pallet] pub mod pallet { use super::*; - use frame_support::{dispatch::DispatchResult, pallet_prelude::*}; + use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; #[pallet::pallet] diff --git a/frame/assets/src/mock.rs b/frame/assets/src/mock.rs index 1e1ea8ba9a96..aedf437ee843 100644 --- a/frame/assets/src/mock.rs +++ b/frame/assets/src/mock.rs @@ -20,7 +20,7 @@ use super::*; use crate as pallet_assets; -use frame_support::{construct_runtime, parameter_types}; +use frame_support::{construct_runtime, parameter_types, traits::GenesisBuild}; use sp_core::H256; use sp_runtime::{ testing::Header, diff --git a/frame/collective/src/tests.rs b/frame/collective/src/tests.rs index 7e52b10a9b1d..cbd2f68ac73e 100644 --- a/frame/collective/src/tests.rs +++ b/frame/collective/src/tests.rs @@ -52,9 +52,8 @@ mod mock_democracy { pub use pallet::*; #[frame_support::pallet] pub mod pallet { - use frame_support::{pallet_prelude::*, traits::EnsureOrigin}; + use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; - use sp_runtime::DispatchResult; #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] diff --git a/frame/democracy/src/lib.rs b/frame/democracy/src/lib.rs index 529bcebc8e37..ec706ca8f48a 100644 --- a/frame/democracy/src/lib.rs +++ b/frame/democracy/src/lib.rs @@ -240,16 +240,9 @@ enum Releases { #[frame_support::pallet] pub mod pallet { - use super::*; - use frame_support::{ - dispatch::DispatchResultWithPostInfo, - pallet_prelude::*, - traits::EnsureOrigin, - weights::{DispatchClass, Pays}, - Parameter, - }; - use frame_system::{ensure_root, ensure_signed, pallet_prelude::*}; - use sp_runtime::DispatchResult; + use super::{DispatchResult, *}; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] diff --git a/frame/im-online/README.md b/frame/im-online/README.md index 46b2268f18b1..be11e0c49dff 100644 --- a/frame/im-online/README.md +++ b/frame/im-online/README.md @@ -26,21 +26,29 @@ It is submitted as an Unsigned Transaction via off-chain workers. ## Usage ```rust -use frame_support::{decl_module, dispatch}; -use frame_system::ensure_signed; use pallet_im_online::{self as im_online}; -pub trait Config: im_online::Config {} - -decl_module! { - pub struct Module for enum Call where origin: T::Origin { - #[weight = 0] - pub fn is_online(origin, authority_index: u32) -> dispatch::DispatchResult { - let _sender = ensure_signed(origin)?; - let _is_online = >::is_online(authority_index); - Ok(()) - } - } +#[frame_support::pallet] +pub mod pallet { + use super::*; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::config] + pub trait Config: frame_system::Config + im_online::Config {} + + #[pallet::call] + impl Pallet { + #[pallet::weight(0)] + pub fn is_online(origin: OriginFor, authority_index: u32) -> DispatchResult { + let _sender = ensure_signed(origin)?; + let _is_online = >::is_online(authority_index); + Ok(()) + } + } } ``` diff --git a/frame/im-online/src/lib.rs b/frame/im-online/src/lib.rs index 718c735fdad4..dbae5ed96d58 100644 --- a/frame/im-online/src/lib.rs +++ b/frame/im-online/src/lib.rs @@ -17,12 +17,12 @@ //! # I'm online Pallet //! -//! If the local node is a validator (i.e. contains an authority key), this module +//! If the local node is a validator (i.e. contains an authority key), this pallet //! gossips a heartbeat transaction with each new session. The heartbeat functions //! as a simple mechanism to signal that the node is online in the current era. //! //! Received heartbeats are tracked for one era and reset with each new era. The -//! module exposes two public functions to query if a heartbeat has been received +//! pallet exposes two public functions to query if a heartbeat has been received //! in the current era or session. //! //! The heartbeat is a signed transaction, which was signed using the session key @@ -43,16 +43,24 @@ //! ## Usage //! //! ``` -//! use frame_support::{decl_module, dispatch}; -//! use frame_system::ensure_signed; //! use pallet_im_online::{self as im_online}; //! -//! pub trait Config: im_online::Config {} +//! #[frame_support::pallet] +//! pub mod pallet { +//! use super::*; +//! use frame_support::pallet_prelude::*; +//! use frame_system::pallet_prelude::*; //! -//! decl_module! { -//! pub struct Module for enum Call where origin: T::Origin { -//! #[weight = 0] -//! pub fn is_online(origin, authority_index: u32) -> dispatch::DispatchResult { +//! #[pallet::pallet] +//! pub struct Pallet(_); +//! +//! #[pallet::config] +//! pub trait Config: frame_system::Config + im_online::Config {} +//! +//! #[pallet::call] +//! impl Pallet { +//! #[pallet::weight(0)] +//! pub fn is_online(origin: OriginFor, authority_index: u32) -> DispatchResult { //! let _sender = ensure_signed(origin)?; //! let _is_online = >::is_online(authority_index); //! Ok(()) @@ -64,7 +72,7 @@ //! //! ## Dependencies //! -//! This module depends on the [Session module](../pallet_session/index.html). +//! This pallet depends on the [Session pallet](../pallet_session/index.html). // Ensure we're `no_std` when compiling for Wasm. #![cfg_attr(not(feature = "std"), no_std)] @@ -302,15 +310,8 @@ type OffchainResult = Result::B #[frame_support::pallet] pub mod pallet { use super::*; - use frame_support::{pallet_prelude::*, traits::Get, Parameter}; - use frame_system::{ensure_none, pallet_prelude::*}; - use sp_runtime::{ - traits::{MaybeSerializeDeserialize, Member}, - transaction_validity::{ - InvalidTransaction, TransactionPriority, TransactionSource, TransactionValidity, - ValidTransaction, - }, - }; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] diff --git a/frame/lottery/src/lib.rs b/frame/lottery/src/lib.rs index c1c536b8ba29..b30bc1dc523a 100644 --- a/frame/lottery/src/lib.rs +++ b/frame/lottery/src/lib.rs @@ -115,8 +115,8 @@ impl ValidateCall for Pallet { #[frame_support::pallet] pub mod pallet { use super::*; - use frame_support::{pallet_prelude::*, traits::EnsureOrigin, weights::Weight, Parameter}; - use frame_system::{ensure_signed, pallet_prelude::*}; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] diff --git a/frame/nicks/src/lib.rs b/frame/nicks/src/lib.rs index 438929576269..bfc23187fc5b 100644 --- a/frame/nicks/src/lib.rs +++ b/frame/nicks/src/lib.rs @@ -52,12 +52,8 @@ type NegativeImbalanceOf = <::Currency as Currency< #[frame_support::pallet] pub mod pallet { use super::*; - use frame_support::{ - ensure, - pallet_prelude::*, - traits::{EnsureOrigin, Get}, - }; - use frame_system::{ensure_signed, pallet_prelude::*}; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; #[pallet::config] pub trait Config: frame_system::Config { diff --git a/frame/node-authorization/src/lib.rs b/frame/node-authorization/src/lib.rs index 6e3ec58ba63f..17b74053e668 100644 --- a/frame/node-authorization/src/lib.rs +++ b/frame/node-authorization/src/lib.rs @@ -52,7 +52,7 @@ pub use weights::WeightInfo; #[frame_support::pallet] pub mod pallet { use super::*; - use frame_support::{dispatch::DispatchResult, pallet_prelude::*}; + use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; #[pallet::pallet] diff --git a/frame/randomness-collective-flip/README.md b/frame/randomness-collective-flip/README.md index 9885c734d9fa..0730d4abf7cf 100644 --- a/frame/randomness-collective-flip/README.md +++ b/frame/randomness-collective-flip/README.md @@ -20,18 +20,28 @@ the system trait. ### Example - Get random seed for the current block ```rust -use frame_support::{decl_module, dispatch, traits::Randomness}; - -pub trait Config: frame_system::Config {} - -decl_module! { - pub struct Module for enum Call where origin: T::Origin { - #[weight = 0] - pub fn random_module_example(origin) -> dispatch::DispatchResult { - let _random_value = >::random(&b"my context"[..]); - Ok(()) - } - } +use frame_support::traits::Randomness; + +#[frame_support::pallet] +pub mod pallet { + use super::*; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::config] + pub trait Config: frame_system::Config + pallet_randomness_collective_flip::Config {} + + #[pallet::call] + impl Pallet { + #[pallet::weight(0)] + pub fn random_module_example(origin: OriginFor) -> DispatchResult { + let _random_value = >::random(&b"my context"[..]); + Ok(()) + } + } } ``` diff --git a/frame/randomness-collective-flip/src/lib.rs b/frame/randomness-collective-flip/src/lib.rs index a9abb2c9564d..345b8072c5e4 100644 --- a/frame/randomness-collective-flip/src/lib.rs +++ b/frame/randomness-collective-flip/src/lib.rs @@ -15,9 +15,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! # Randomness Module +//! # Randomness Pallet //! -//! The Randomness Collective Flip module provides a [`random`](./struct.Module.html#method.random) +//! The Randomness Collective Flip pallet provides a [`random`](./struct.Module.html#method.random) //! function that generates low-influence random values based on the block hashes from the previous //! `81` blocks. Low-influence randomness can be useful when defending against relatively weak //! adversaries. Using this pallet as a randomness source is advisable primarily in low-security @@ -31,7 +31,7 @@ //! //! ### Prerequisites //! -//! Import the Randomness Collective Flip module and derive your module's configuration trait from +//! Import the Randomness Collective Flip pallet and derive your pallet's configuration trait from //! the system trait. //! //! ### Example - Get random seed for the current block @@ -41,9 +41,9 @@ //! //! #[frame_support::pallet] //! pub mod pallet { +//! use super::*; //! use frame_support::pallet_prelude::*; //! use frame_system::pallet_prelude::*; -//! use super::*; //! //! #[pallet::pallet] //! #[pallet::generate_store(pub(super) trait Store)] diff --git a/frame/recovery/src/lib.rs b/frame/recovery/src/lib.rs index 797581788077..522d7008017f 100644 --- a/frame/recovery/src/lib.rs +++ b/frame/recovery/src/lib.rs @@ -206,8 +206,8 @@ pub struct RecoveryConfig { #[frame_support::pallet] pub mod pallet { use super::*; - use frame_support::{ensure, pallet_prelude::*, traits::Get, Parameter}; - use frame_system::{ensure_root, ensure_signed, pallet_prelude::*}; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; use sp_runtime::ArithmeticError; #[pallet::pallet] diff --git a/frame/scored-pool/README.md b/frame/scored-pool/README.md index bf20124edf52..56c6af916ecd 100644 --- a/frame/scored-pool/README.md +++ b/frame/scored-pool/README.md @@ -37,26 +37,33 @@ by the next highest scoring candidate in the pool, if available. ## Usage ```rust -use frame_support::{decl_module, dispatch}; -use frame_system::ensure_signed; use pallet_scored_pool::{self as scored_pool}; -pub trait Config: scored_pool::Config {} - -decl_module! { - pub struct Module for enum Call where origin: T::Origin { - #[weight = 0] - pub fn candidate(origin) -> dispatch::DispatchResult { - let who = ensure_signed(origin)?; - - let _ = >::submit_candidacy( - T::Origin::from(Some(who.clone()).into()) - ); - Ok(()) - } - } +#[frame_support::pallet] +pub mod pallet { + use super::*; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::config] + pub trait Config: frame_system::Config + scored_pool::Config {} + + #[pallet::call] + impl Pallet { + #[pallet::weight(0)] + pub fn candidate(origin: OriginFor) -> DispatchResult { + let who = ensure_signed(origin)?; + + let _ = >::submit_candidacy( + T::Origin::from(Some(who.clone()).into()) + ); + Ok(()) + } + } } - ``` ## Dependencies diff --git a/frame/scored-pool/src/lib.rs b/frame/scored-pool/src/lib.rs index a5cdb6274f99..7c90d163dee1 100644 --- a/frame/scored-pool/src/lib.rs +++ b/frame/scored-pool/src/lib.rs @@ -54,16 +54,24 @@ //! ## Usage //! //! ``` -//! use frame_support::{decl_module, dispatch}; -//! use frame_system::ensure_signed; //! use pallet_scored_pool::{self as scored_pool}; //! -//! pub trait Config: scored_pool::Config {} +//! #[frame_support::pallet] +//! pub mod pallet { +//! use super::*; +//! use frame_support::pallet_prelude::*; +//! use frame_system::pallet_prelude::*; //! -//! decl_module! { -//! pub struct Module for enum Call where origin: T::Origin { -//! #[weight = 0] -//! pub fn candidate(origin) -> dispatch::DispatchResult { +//! #[pallet::pallet] +//! pub struct Pallet(_); +//! +//! #[pallet::config] +//! pub trait Config: frame_system::Config + scored_pool::Config {} +//! +//! #[pallet::call] +//! impl Pallet { +//! #[pallet::weight(0)] +//! pub fn candidate(origin: OriginFor) -> DispatchResult { //! let who = ensure_signed(origin)?; //! //! let _ = >::submit_candidacy( @@ -116,9 +124,8 @@ enum ChangeReceiver { #[frame_support::pallet] pub mod pallet { use super::*; - use frame_support::{pallet_prelude::*, traits::EnsureOrigin, weights::Weight}; - use frame_system::{ensure_root, ensure_signed, pallet_prelude::*}; - use sp_runtime::traits::MaybeSerializeDeserialize; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] diff --git a/frame/staking/README.md b/frame/staking/README.md index 072353b1a586..bbd5bd18f6e8 100644 --- a/frame/staking/README.md +++ b/frame/staking/README.md @@ -133,19 +133,27 @@ The Staking module contains many public storage items and (im)mutable functions. ### Example: Rewarding a validator by id. ```rust -use frame_support::{decl_module, dispatch}; -use frame_system::ensure_signed; use pallet_staking::{self as staking}; -pub trait Config: staking::Config {} +#[frame_support::pallet] +pub mod pallet { + use super::*; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; -decl_module! { - pub struct Module for enum Call where origin: T::Origin { + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::config] + pub trait Config: frame_system::Config + staking::Config {} + + #[pallet::call] + impl Pallet { /// Reward a validator. - #[weight = 0] - pub fn reward_myself(origin) -> dispatch::DispatchResult { + #[pallet::weight(0)] + pub fn reward_myself(origin: OriginFor) -> DispatchResult { let reported = ensure_signed(origin)?; - >::reward_by_ids(vec![(reported, 10)]); + >::reward_by_ids(vec![(reported, 10)]); Ok(()) } } diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index be02e8d91d32..cb91abe476cb 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -157,17 +157,25 @@ //! ### Example: Rewarding a validator by id. //! //! ``` -//! use frame_support::{decl_module, dispatch}; -//! use frame_system::ensure_signed; //! use pallet_staking::{self as staking}; //! -//! pub trait Config: staking::Config {} +//! #[frame_support::pallet] +//! pub mod pallet { +//! use super::*; +//! use frame_support::pallet_prelude::*; +//! use frame_system::pallet_prelude::*; //! -//! decl_module! { -//! pub struct Module for enum Call where origin: T::Origin { +//! #[pallet::pallet] +//! pub struct Pallet(_); +//! +//! #[pallet::config] +//! pub trait Config: frame_system::Config + staking::Config {} +//! +//! #[pallet::call] +//! impl Pallet { //! /// Reward a validator. -//! #[weight = 0] -//! pub fn reward_myself(origin) -> dispatch::DispatchResult { +//! #[pallet::weight(0)] +//! pub fn reward_myself(origin: OriginFor) -> DispatchResult { //! let reported = ensure_signed(origin)?; //! >::reward_by_ids(vec![(reported, 10)]); //! Ok(()) diff --git a/frame/sudo/README.md b/frame/sudo/README.md index 60090db46a4f..e8f688091e32 100644 --- a/frame/sudo/README.md +++ b/frame/sudo/README.md @@ -35,15 +35,22 @@ Learn more about privileged functions and `Root` origin in the [`Origin`] type d This is an example of a module that exposes a privileged function: ```rust -use frame_support::{decl_module, dispatch}; -use frame_system::ensure_root; - -pub trait Config: frame_system::Config {} - -decl_module! { - pub struct Module for enum Call where origin: T::Origin { - #[weight = 0] - pub fn privileged_function(origin) -> dispatch::DispatchResult { +#[frame_support::pallet] +pub mod pallet { + use super::*; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::config] + pub trait Config: frame_system::Config {} + + #[pallet::call] + impl Pallet { + #[pallet::weight(0)] + pub fn privileged_function(origin: OriginFor) -> DispatchResult { ensure_root(origin)?; // do something... diff --git a/frame/sudo/src/lib.rs b/frame/sudo/src/lib.rs index 5f8e6fc0cc13..de3b3439bc34 100644 --- a/frame/sudo/src/lib.rs +++ b/frame/sudo/src/lib.rs @@ -52,28 +52,27 @@ //! This is an example of a pallet that exposes a privileged function: //! //! ``` -//! //! #[frame_support::pallet] -//! pub mod logger { +//! pub mod pallet { +//! use super::*; //! use frame_support::pallet_prelude::*; //! use frame_system::pallet_prelude::*; -//! use super::*; +//! +//! #[pallet::pallet] +//! pub struct Pallet(_); //! //! #[pallet::config] //! pub trait Config: frame_system::Config {} //! -//! #[pallet::pallet] -//! pub struct Pallet(PhantomData); -//! //! #[pallet::call] //! impl Pallet { //! #[pallet::weight(0)] -//! pub fn privileged_function(origin: OriginFor) -> DispatchResultWithPostInfo { +//! pub fn privileged_function(origin: OriginFor) -> DispatchResult { //! ensure_root(origin)?; //! //! // do something... //! -//! Ok(().into()) +//! Ok(()) //! } //! } //! } diff --git a/frame/system/README.md b/frame/system/README.md index 6766c3d73f4d..c22b41e42d79 100644 --- a/frame/system/README.md +++ b/frame/system/README.md @@ -54,21 +54,28 @@ Import the System module and derive your module's configuration trait from the s ### Example - Get extrinsic count and parent hash for the current block ```rust -use frame_support::{decl_module, dispatch}; -use frame_system::{self as system, ensure_signed}; - -pub trait Config: system::Config {} - -decl_module! { - pub struct Module for enum Call where origin: T::Origin { - #[weight = 0] - pub fn system_module_example(origin) -> dispatch::DispatchResult { - let _sender = ensure_signed(origin)?; - let _extrinsic_count = >::extrinsic_count(); - let _parent_hash = >::parent_hash(); - Ok(()) - } - } +#[frame_support::pallet] +pub mod pallet { + use super::*; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::config] + pub trait Config: frame_system::Config {} + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::call] + impl Pallet { + #[pallet::weight(0)] + pub fn system_module_example(origin: OriginFor) -> DispatchResult { + let _sender = ensure_signed(origin)?; + let _extrinsic_count = >::extrinsic_count(); + let _parent_hash = >::parent_hash(); + Ok(()) + } + } } ``` diff --git a/frame/timestamp/README.md b/frame/timestamp/README.md index 5f8388b04f82..1546377ee674 100644 --- a/frame/timestamp/README.md +++ b/frame/timestamp/README.md @@ -45,20 +45,29 @@ trait from the timestamp trait. ### Get current timestamp ```rust -use frame_support::{decl_module, dispatch}; -use frame_system::ensure_signed; - -pub trait Config: timestamp::Config {} - -decl_module! { - pub struct Module for enum Call where origin: T::Origin { - #[weight = 0] - pub fn get_time(origin) -> dispatch::DispatchResult { - let _sender = ensure_signed(origin)?; - let _now = >::get(); - Ok(()) - } - } +use pallet_timestamp::{self as timestamp}; + +#[frame_support::pallet] +pub mod pallet { + use super::*; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::config] + pub trait Config: frame_system::Config + timestamp::Config {} + + #[pallet::call] + impl Pallet { + #[pallet::weight(0)] + pub fn get_time(origin: OriginFor) -> DispatchResult { + let _sender = ensure_signed(origin)?; + let _now = >::get(); + Ok(()) + } + } } ``` diff --git a/frame/timestamp/src/lib.rs b/frame/timestamp/src/lib.rs index 153606bedbac..eeb840715f81 100644 --- a/frame/timestamp/src/lib.rs +++ b/frame/timestamp/src/lib.rs @@ -64,18 +64,26 @@ //! ### Get current timestamp //! //! ``` -//! use frame_support::{decl_module, dispatch}; -//! # use pallet_timestamp as timestamp; -//! use frame_system::ensure_signed; +//! use pallet_timestamp::{self as timestamp}; //! -//! pub trait Config: timestamp::Config {} +//! #[frame_support::pallet] +//! pub mod pallet { +//! use super::*; +//! use frame_support::pallet_prelude::*; +//! use frame_system::pallet_prelude::*; //! -//! decl_module! { -//! pub struct Module for enum Call where origin: T::Origin { -//! #[weight = 0] -//! pub fn get_time(origin) -> dispatch::DispatchResult { +//! #[pallet::pallet] +//! pub struct Pallet(_); +//! +//! #[pallet::config] +//! pub trait Config: frame_system::Config + timestamp::Config {} +//! +//! #[pallet::call] +//! impl Pallet { +//! #[pallet::weight(0)] +//! pub fn get_time(origin: OriginFor) -> DispatchResult { //! let _sender = ensure_signed(origin)?; -//! let _now = >::get(); +//! let _now = >::get(); //! Ok(()) //! } //! } From 4581dd99ed59f65ede46a34c81133177d5824a68 Mon Sep 17 00:00:00 2001 From: Georges Date: Fri, 19 Nov 2021 09:29:12 +0000 Subject: [PATCH 205/695] Moving `pallet-asset-tx-payment` from cumulus to substrate (#10127) * Moving `pallet-asset-tx-payment` from cumulus * move pallet-asset-tx-payment into transaction payment directory * cargo +nightly fmt * Adding `pallet-asset-tx-payment` to node runtime I had to change the Balance type to u128. Also harmonised that pallet's version * Updating cargo.lock after merge * forgot this * Adding tx-payment signature * Missed one more * `transaction-payment` replaced in`SignedExtension` by `asset-tx-payment` and not added * Fixing benches * add test to verify that we don't charge on post-dispatch if we didn't on pre-dispatch * add (failing) test for asset tx payment of unsigned extrinsics * fix test by removing debug_assert * cargo +nightly fmt * typo in `Cargo.lock` * Object defined twice in lock file * cargo update * remove todo * Apply formatting suggestions from code review Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> * Refactoring `post_dispatch` of `asset-tx-payment` to reuse `post_dispatch` of `transaction-payment` if the fee asset is native Removing unneeded imports. * Removing redundant `TODO` * Reverting an accidental bump of `impl-serde` from `0.3.1` to `0.3.2` * Revert unneeded changes to `cargo.lock` * Update frame/transaction-payment/asset-tx-payment/src/payment.rs Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> * Fixing cargo fmt Reverting changes which broke cargo fmt Co-authored-by: Alexander Popiak Co-authored-by: Alexander Popiak Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> --- Cargo.lock | 26 + Cargo.toml | 1 + bin/node/cli/Cargo.toml | 1 + bin/node/cli/src/service.rs | 6 +- bin/node/runtime/Cargo.toml | 1 + bin/node/runtime/src/impls.rs | 19 +- bin/node/runtime/src/lib.rs | 17 +- bin/node/test-runner-example/Cargo.toml | 1 + bin/node/test-runner-example/src/lib.rs | 2 +- bin/node/testing/Cargo.toml | 1 + bin/node/testing/src/keyring.rs | 2 +- .../asset-tx-payment/Cargo.toml | 55 ++ .../asset-tx-payment/README.md | 21 + .../asset-tx-payment/src/lib.rs | 288 +++++++ .../asset-tx-payment/src/payment.rs | 168 ++++ .../asset-tx-payment/src/tests.rs | 748 ++++++++++++++++++ 16 files changed, 1346 insertions(+), 11 deletions(-) create mode 100644 frame/transaction-payment/asset-tx-payment/Cargo.toml create mode 100644 frame/transaction-payment/asset-tx-payment/README.md create mode 100644 frame/transaction-payment/asset-tx-payment/src/lib.rs create mode 100644 frame/transaction-payment/asset-tx-payment/src/payment.rs create mode 100644 frame/transaction-payment/asset-tx-payment/src/tests.rs diff --git a/Cargo.lock b/Cargo.lock index f1e8b00c6eb0..32234cc4c93a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4536,6 +4536,7 @@ dependencies = [ "node-primitives", "node-rpc", "node-runtime", + "pallet-asset-tx-payment", "pallet-balances", "pallet-im-online", "pallet-timestamp", @@ -4701,6 +4702,7 @@ dependencies = [ "hex-literal", "log 0.4.14", "node-primitives", + "pallet-asset-tx-payment", "pallet-assets", "pallet-authority-discovery", "pallet-authorship", @@ -4861,6 +4863,7 @@ dependencies = [ "node-executor", "node-primitives", "node-runtime", + "pallet-asset-tx-payment", "pallet-transaction-payment", "parity-scale-codec", "sc-block-builder", @@ -5104,6 +5107,28 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "pallet-asset-tx-payment" +version = "4.0.0-dev" +dependencies = [ + "frame-support", + "frame-system", + "pallet-assets", + "pallet-authorship", + "pallet-balances", + "pallet-transaction-payment", + "parity-scale-codec", + "scale-info", + "serde", + "serde_json", + "smallvec 1.7.0", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "sp-storage", +] + [[package]] name = "pallet-assets" version = "4.0.0-dev" @@ -10420,6 +10445,7 @@ dependencies = [ "node-cli", "node-primitives", "node-runtime", + "pallet-asset-tx-payment", "pallet-transaction-payment", "sc-consensus", "sc-consensus-babe", diff --git a/Cargo.toml b/Cargo.toml index e03f33a4d27d..f30b223a9b20 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -124,6 +124,7 @@ members = [ "frame/system/rpc/runtime-api", "frame/timestamp", "frame/transaction-payment", + "frame/transaction-payment/asset-tx-payment", "frame/transaction-payment/rpc", "frame/transaction-payment/rpc/runtime-api", "frame/transaction-storage", diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index 7529138c7f9d..5a9e76bccf63 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -81,6 +81,7 @@ sc-sync-state-rpc = { version = "0.10.0-dev", path = "../../../client/sync-state frame-system = { version = "4.0.0-dev", path = "../../../frame/system" } frame-system-rpc-runtime-api = { version = "4.0.0-dev", path = "../../../frame/system/rpc/runtime-api" } pallet-transaction-payment = { version = "4.0.0-dev", path = "../../../frame/transaction-payment" } +pallet-asset-tx-payment = { version = "4.0.0-dev", path = "../../../frame/transaction-payment/asset-tx-payment/" } pallet-im-online = { version = "4.0.0-dev", default-features = false, path = "../../../frame/im-online" } # node-specific dependencies diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index e73b69153d1d..fec91a9b67cc 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -92,7 +92,7 @@ pub fn create_extrinsic( )), frame_system::CheckNonce::::from(nonce), frame_system::CheckWeight::::new(), - pallet_transaction_payment::ChargeTransactionPayment::::from(tip), + pallet_asset_tx_payment::ChargeAssetTxPayment::::from(tip, None), ); let raw_payload = node_runtime::SignedPayload::from_raw( @@ -725,7 +725,7 @@ mod tests { let check_era = frame_system::CheckEra::from(Era::Immortal); let check_nonce = frame_system::CheckNonce::from(index); let check_weight = frame_system::CheckWeight::new(); - let payment = pallet_transaction_payment::ChargeTransactionPayment::from(0); + let tx_payment = pallet_asset_tx_payment::ChargeAssetTxPayment::from(0, None); let extra = ( check_spec_version, check_tx_version, @@ -733,7 +733,7 @@ mod tests { check_era, check_nonce, check_weight, - payment, + tx_payment, ); let raw_payload = SignedPayload::from_raw( function, diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 9a481120fd01..f9ce4b0fca90 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -95,6 +95,7 @@ pallet-treasury = { version = "4.0.0-dev", default-features = false, path = "../ pallet-utility = { version = "4.0.0-dev", default-features = false, path = "../../../frame/utility" } pallet-transaction-payment = { version = "4.0.0-dev", default-features = false, path = "../../../frame/transaction-payment" } pallet-transaction-payment-rpc-runtime-api = { version = "4.0.0-dev", default-features = false, path = "../../../frame/transaction-payment/rpc/runtime-api/" } +pallet-asset-tx-payment = { version = "4.0.0-dev", default-features = false, path = "../../../frame/transaction-payment/asset-tx-payment/" } pallet-transaction-storage = { version = "4.0.0-dev", default-features = false, path = "../../../frame/transaction-storage" } pallet-uniques = { version = "4.0.0-dev", default-features = false, path = "../../../frame/uniques" } pallet-vesting = { version = "4.0.0-dev", default-features = false, path = "../../../frame/vesting" } diff --git a/bin/node/runtime/src/impls.rs b/bin/node/runtime/src/impls.rs index e315a45e698c..cdd9f0900fd3 100644 --- a/bin/node/runtime/src/impls.rs +++ b/bin/node/runtime/src/impls.rs @@ -17,8 +17,12 @@ //! Some configurable implementations as associated type for the substrate runtime. -use crate::{Authorship, Balances, NegativeImbalance}; -use frame_support::traits::{Currency, OnUnbalanced}; +use crate::{AccountId, Assets, Authorship, Balances, NegativeImbalance, Runtime}; +use frame_support::traits::{ + fungibles::{Balanced, CreditOf}, + Currency, OnUnbalanced, +}; +use pallet_asset_tx_payment::HandleCredit; pub struct Author; impl OnUnbalanced for Author { @@ -27,6 +31,17 @@ impl OnUnbalanced for Author { } } +/// A `HandleCredit` implementation that naively transfers the fees to the block author. +/// Will drop and burn the assets in case the transfer fails. +pub struct CreditToBlockAuthor; +impl HandleCredit for CreditToBlockAuthor { + fn handle_credit(credit: CreditOf) { + let author = pallet_authorship::Pallet::::author(); + // Drop the result which will trigger the `OnDrop` of the imbalance in case of error. + let _ = Assets::resolve(&author, credit); + } +} + #[cfg(test)] mod multiplier_tests { use pallet_transaction_payment::{Multiplier, TargetedFeeAdjustment}; diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 6d04ca8fdca8..5b3c0685d1a2 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -87,7 +87,7 @@ pub use sp_runtime::BuildStorage; /// Implementations of some helper traits passed into runtime modules as associated types. pub mod impls; -use impls::Author; +use impls::{Author, CreditToBlockAuthor}; /// Constant values used within the runtime. pub mod constants; @@ -432,6 +432,14 @@ impl pallet_transaction_payment::Config for Runtime { TargetedFeeAdjustment; } +impl pallet_asset_tx_payment::Config for Runtime { + type Fungibles = Assets; + type OnChargeAssetTransaction = pallet_asset_tx_payment::FungiblesAdapter< + pallet_assets::BalanceToAssetBalance, + CreditToBlockAuthor, + >; +} + parameter_types! { pub const MinimumPeriod: Moment = SLOT_DURATION / 2; } @@ -969,7 +977,7 @@ where frame_system::CheckEra::::from(era), frame_system::CheckNonce::::from(nonce), frame_system::CheckWeight::::new(), - pallet_transaction_payment::ChargeTransactionPayment::::from(tip), + pallet_asset_tx_payment::ChargeAssetTxPayment::::from(tip, None), ); let raw_payload = SignedPayload::new(call, extra) .map_err(|e| { @@ -1168,7 +1176,7 @@ parameter_types! { impl pallet_assets::Config for Runtime { type Event = Event; - type Balance = u64; + type Balance = u128; type AssetId = u32; type Currency = Balances; type ForceOrigin = EnsureRoot; @@ -1257,6 +1265,7 @@ construct_runtime!( Indices: pallet_indices, Balances: pallet_balances, TransactionPayment: pallet_transaction_payment, + AssetTxPayment: pallet_asset_tx_payment, ElectionProviderMultiPhase: pallet_election_provider_multi_phase, Staking: pallet_staking, Session: pallet_session, @@ -1315,7 +1324,7 @@ pub type SignedExtra = ( frame_system::CheckEra, frame_system::CheckNonce, frame_system::CheckWeight, - pallet_transaction_payment::ChargeTransactionPayment, + pallet_asset_tx_payment::ChargeAssetTxPayment, ); /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; diff --git a/bin/node/test-runner-example/Cargo.toml b/bin/node/test-runner-example/Cargo.toml index b664cdb8e50e..831a68725440 100644 --- a/bin/node/test-runner-example/Cargo.toml +++ b/bin/node/test-runner-example/Cargo.toml @@ -11,6 +11,7 @@ test-runner = { path = "../../../test-utils/test-runner" } frame-system = { path = "../../../frame/system" } frame-benchmarking = { path = "../../../frame/benchmarking" } pallet-transaction-payment = { path = "../../../frame/transaction-payment" } +pallet-asset-tx-payment = { path = "../../../frame/transaction-payment/asset-tx-payment/" } node-runtime = { path = "../runtime" } node-primitives = { path = "../primitives" } diff --git a/bin/node/test-runner-example/src/lib.rs b/bin/node/test-runner-example/src/lib.rs index 0de7f5a4e2b7..68c14b73bf56 100644 --- a/bin/node/test-runner-example/src/lib.rs +++ b/bin/node/test-runner-example/src/lib.rs @@ -77,7 +77,7 @@ impl ChainInfo for NodeTemplateChainInfo { frame_system::Pallet::::account_nonce(from), ), frame_system::CheckWeight::::new(), - pallet_transaction_payment::ChargeTransactionPayment::::from(0), + pallet_asset_tx_payment::ChargeAssetTxPayment::::from(0, None), ) } } diff --git a/bin/node/testing/Cargo.toml b/bin/node/testing/Cargo.toml index 1854029b0709..0e5ed07ac295 100644 --- a/bin/node/testing/Cargo.toml +++ b/bin/node/testing/Cargo.toml @@ -38,6 +38,7 @@ sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/c frame-system = { version = "4.0.0-dev", path = "../../../frame/system" } substrate-test-client = { version = "2.0.0", path = "../../../test-utils/client" } pallet-transaction-payment = { version = "4.0.0-dev", path = "../../../frame/transaction-payment" } +pallet-asset-tx-payment = { version = "4.0.0-dev", path = "../../../frame/transaction-payment/asset-tx-payment/" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-timestamp = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/timestamp" } sp-block-builder = { version = "4.0.0-dev", path = "../../../primitives/block-builder" } diff --git a/bin/node/testing/src/keyring.rs b/bin/node/testing/src/keyring.rs index 4e2d88b4bba3..1040e90c4d5d 100644 --- a/bin/node/testing/src/keyring.rs +++ b/bin/node/testing/src/keyring.rs @@ -76,7 +76,7 @@ pub fn signed_extra(nonce: Index, extra_fee: Balance) -> SignedExtra { frame_system::CheckEra::from(Era::mortal(256, 0)), frame_system::CheckNonce::from(nonce), frame_system::CheckWeight::new(), - pallet_transaction_payment::ChargeTransactionPayment::from(extra_fee), + pallet_asset_tx_payment::ChargeAssetTxPayment::from(extra_fee, None), ) } diff --git a/frame/transaction-payment/asset-tx-payment/Cargo.toml b/frame/transaction-payment/asset-tx-payment/Cargo.toml new file mode 100644 index 000000000000..a381145d667a --- /dev/null +++ b/frame/transaction-payment/asset-tx-payment/Cargo.toml @@ -0,0 +1,55 @@ +[package] +name = "pallet-asset-tx-payment" +version = "4.0.0-dev" +authors = ["Parity Technologies "] +edition = "2018" +license = "Apache-2.0" +homepage = "https://substrate.io" +repository = "https://github.com/paritytech/substrate/" +description = "pallet to manage transaction payments in assets" +readme = "README.md" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +# Substrate dependencies +sp-core = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/core" } +sp-io = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/io" } +sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } +sp-std = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/std" } + +frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" } +frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" } +pallet-transaction-payment = { version = "4.0.0-dev", default-features = false, path = ".." } + +# Other dependencies +codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } +serde = { version = "1.0.126", optional = true } + +[dev-dependencies] +smallvec = "1.7.0" +serde_json = "1.0.68" + +sp-storage = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/storage" } + +pallet-assets = { version = "4.0.0-dev", path = "../../assets" } +pallet-authorship = { version = "4.0.0-dev", path = "../../authorship" } +pallet-balances = { version = "4.0.0-dev", path = "../../balances" } + + +[features] +default = ["std"] +std = [ + "serde", + "codec/std", + "sp-std/std", + "sp-runtime/std", + "frame-support/std", + "frame-system/std", + "sp-io/std", + "sp-core/std", + "pallet-transaction-payment/std", +] +try-runtime = ["frame-support/try-runtime"] diff --git a/frame/transaction-payment/asset-tx-payment/README.md b/frame/transaction-payment/asset-tx-payment/README.md new file mode 100644 index 000000000000..fc860347d85f --- /dev/null +++ b/frame/transaction-payment/asset-tx-payment/README.md @@ -0,0 +1,21 @@ +# pallet-asset-tx-payment + +## Asset Transaction Payment Pallet + +This pallet allows runtimes that include it to pay for transactions in assets other than the +native token of the chain. + +### Overview +It does this by extending transactions to include an optional `AssetId` that specifies the asset +to be used for payment (defaulting to the native token on `None`). It expects an +[`OnChargeAssetTransaction`] implementation analogously to [`pallet-transaction-payment`]. The +included [`FungiblesAdapter`] (implementing [`OnChargeAssetTransaction`]) determines the fee +amount by converting the fee calculated by [`pallet-transaction-payment`] into the desired +asset. + +### Integration +This pallet wraps FRAME's transaction payment pallet and functions as a replacement. This means +you should include both pallets in your `construct_runtime` macro, but only include this +pallet's [`SignedExtension`] ([`ChargeAssetTxPayment`]). + +License: Apache-2.0 diff --git a/frame/transaction-payment/asset-tx-payment/src/lib.rs b/frame/transaction-payment/asset-tx-payment/src/lib.rs new file mode 100644 index 000000000000..1f22669857d7 --- /dev/null +++ b/frame/transaction-payment/asset-tx-payment/src/lib.rs @@ -0,0 +1,288 @@ +// Copyright (C) 2021 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. + +//! # Asset Transaction Payment Pallet +//! +//! This pallet allows runtimes that include it to pay for transactions in assets other than the +//! main token of the chain. +//! +//! ## Overview + +//! It does this by extending transactions to include an optional `AssetId` that specifies the asset +//! to be used for payment (defaulting to the native token on `None`). It expects an +//! [`OnChargeAssetTransaction`] implementation analogously to [`pallet-transaction-payment`]. The +//! included [`FungiblesAdapter`] (implementing [`OnChargeAssetTransaction`]) determines the fee +//! amount by converting the fee calculated by [`pallet-transaction-payment`] into the desired +//! asset. +//! +//! ## Integration + +//! This pallet wraps FRAME's transaction payment pallet and functions as a replacement. This means +//! you should include both pallets in your `construct_runtime` macro, but only include this +//! pallet's [`SignedExtension`] ([`ChargeAssetTxPayment`]). + +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_std::prelude::*; + +use codec::{Decode, Encode}; +use frame_support::{ + dispatch::DispatchResult, + traits::{ + tokens::{ + fungibles::{Balanced, CreditOf, Inspect}, + WithdrawConsequence, + }, + IsType, + }, + weights::{DispatchInfo, PostDispatchInfo}, + DefaultNoBound, +}; +use pallet_transaction_payment::OnChargeTransaction; +use scale_info::TypeInfo; +use sp_runtime::{ + traits::{DispatchInfoOf, Dispatchable, PostDispatchInfoOf, SignedExtension, Zero}, + transaction_validity::{ + InvalidTransaction, TransactionValidity, TransactionValidityError, ValidTransaction, + }, + FixedPointOperand, +}; + +#[cfg(test)] +mod tests; + +mod payment; +pub use payment::*; + +// Type aliases used for interaction with `OnChargeTransaction`. +pub(crate) type OnChargeTransactionOf = + ::OnChargeTransaction; +// Balance type alias. +pub(crate) type BalanceOf = as OnChargeTransaction>::Balance; +// Liquity info type alias. +pub(crate) type LiquidityInfoOf = + as OnChargeTransaction>::LiquidityInfo; + +// Type alias used for interaction with fungibles (assets). +// Balance type alias. +pub(crate) type AssetBalanceOf = + <::Fungibles as Inspect<::AccountId>>::Balance; +/// Asset id type alias. +pub(crate) type AssetIdOf = + <::Fungibles as Inspect<::AccountId>>::AssetId; + +// Type aliases used for interaction with `OnChargeAssetTransaction`. +// Balance type alias. +pub(crate) type ChargeAssetBalanceOf = + <::OnChargeAssetTransaction as OnChargeAssetTransaction>::Balance; +// Asset id type alias. +pub(crate) type ChargeAssetIdOf = + <::OnChargeAssetTransaction as OnChargeAssetTransaction>::AssetId; +// Liquity info type alias. +pub(crate) type ChargeAssetLiquidityOf = + <::OnChargeAssetTransaction as OnChargeAssetTransaction>::LiquidityInfo; + +/// Used to pass the initial payment info from pre- to post-dispatch. +#[derive(Encode, Decode, DefaultNoBound, TypeInfo)] +pub enum InitialPayment { + /// No initial fee was payed. + Nothing, + /// The initial fee was payed in the native currency. + Native(LiquidityInfoOf), + /// The initial fee was payed in an asset. + Asset(CreditOf), +} + +pub use pallet::*; + +#[frame_support::pallet] +pub mod pallet { + use super::*; + + #[pallet::config] + pub trait Config: frame_system::Config + pallet_transaction_payment::Config { + /// The fungibles instance used to pay for transactions in assets. + type Fungibles: Balanced; + /// The actual transaction charging logic that charges the fees. + type OnChargeAssetTransaction: OnChargeAssetTransaction; + } + + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet(_); +} + +/// Require the transactor pay for themselves and maybe include a tip to gain additional priority +/// in the queue. Allows paying via both `Currency` as well as `fungibles::Balanced`. +/// +/// Wraps the transaction logic in [`pallet_transaction_payment`] and extends it with assets. +/// An asset id of `None` falls back to the underlying transaction payment via the native currency. +#[derive(Encode, Decode, Clone, Eq, PartialEq, TypeInfo)] +#[scale_info(skip_type_params(T))] +pub struct ChargeAssetTxPayment { + #[codec(compact)] + tip: BalanceOf, + asset_id: Option>, +} + +impl ChargeAssetTxPayment +where + T::Call: Dispatchable, + AssetBalanceOf: Send + Sync + FixedPointOperand, + BalanceOf: Send + Sync + FixedPointOperand + IsType>, + ChargeAssetIdOf: Send + Sync, + CreditOf: IsType>, +{ + /// Utility constructor. Used only in client/factory code. + pub fn from(tip: BalanceOf, asset_id: Option>) -> Self { + Self { tip, asset_id } + } + + /// Fee withdrawal logic that dispatches to either `OnChargeAssetTransaction` or + /// `OnChargeTransaction`. + fn withdraw_fee( + &self, + who: &T::AccountId, + call: &T::Call, + info: &DispatchInfoOf, + len: usize, + ) -> Result<(BalanceOf, InitialPayment), TransactionValidityError> { + let fee = pallet_transaction_payment::Pallet::::compute_fee(len as u32, info, self.tip); + debug_assert!(self.tip <= fee, "tip should be included in the computed fee"); + if fee.is_zero() { + Ok((fee, InitialPayment::Nothing)) + } else if let Some(asset_id) = self.asset_id { + T::OnChargeAssetTransaction::withdraw_fee( + who, + call, + info, + asset_id, + fee.into(), + self.tip.into(), + ) + .map(|i| (fee, InitialPayment::Asset(i.into()))) + } else { + as OnChargeTransaction>::withdraw_fee( + who, call, info, fee, self.tip, + ) + .map(|i| (fee, InitialPayment::Native(i))) + .map_err(|_| -> TransactionValidityError { InvalidTransaction::Payment.into() }) + } + } +} + +impl sp_std::fmt::Debug for ChargeAssetTxPayment { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + write!(f, "ChargeAssetTxPayment<{:?}, {:?}>", self.tip, self.asset_id.encode()) + } + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + Ok(()) + } +} + +impl SignedExtension for ChargeAssetTxPayment +where + T::Call: Dispatchable, + AssetBalanceOf: Send + Sync + FixedPointOperand, + BalanceOf: Send + Sync + From + FixedPointOperand + IsType>, + ChargeAssetIdOf: Send + Sync, + CreditOf: IsType>, +{ + const IDENTIFIER: &'static str = "ChargeAssetTxPayment"; + type AccountId = T::AccountId; + type Call = T::Call; + type AdditionalSigned = (); + type Pre = ( + // tip + BalanceOf, + // who paid the fee + Self::AccountId, + // imbalance resulting from withdrawing the fee + InitialPayment, + ); + + fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { + Ok(()) + } + + fn validate( + &self, + who: &Self::AccountId, + call: &Self::Call, + info: &DispatchInfoOf, + len: usize, + ) -> TransactionValidity { + use pallet_transaction_payment::ChargeTransactionPayment; + let (fee, _) = self.withdraw_fee(who, call, info, len)?; + let priority = ChargeTransactionPayment::::get_priority(info, len, self.tip, fee); + Ok(ValidTransaction { priority, ..Default::default() }) + } + + fn pre_dispatch( + self, + who: &Self::AccountId, + call: &Self::Call, + info: &DispatchInfoOf, + len: usize, + ) -> Result { + let (_fee, initial_payment) = self.withdraw_fee(who, call, info, len)?; + Ok((self.tip, who.clone(), initial_payment)) + } + + fn post_dispatch( + pre: Self::Pre, + info: &DispatchInfoOf, + post_info: &PostDispatchInfoOf, + len: usize, + result: &DispatchResult, + ) -> Result<(), TransactionValidityError> { + let (tip, who, initial_payment) = pre; + match initial_payment { + InitialPayment::Native(already_withdrawn) => { + pallet_transaction_payment::ChargeTransactionPayment::::post_dispatch( + (tip, who, already_withdrawn), + info, + post_info, + len, + result, + )?; + }, + InitialPayment::Asset(already_withdrawn) => { + let actual_fee = pallet_transaction_payment::Pallet::::compute_actual_fee( + len as u32, info, post_info, tip, + ); + T::OnChargeAssetTransaction::correct_and_deposit_fee( + &who, + info, + post_info, + actual_fee.into(), + tip.into(), + already_withdrawn.into(), + )?; + }, + InitialPayment::Nothing => { + // `actual_fee` should be zero here for any signed extrinsic. It would be non-zero + // here in case of unsigned extrinsics as they don't pay fees but + // `compute_actual_fee` is not aware of them. In both cases it's fine to just move + // ahead without adjusting the fee, though, so we do nothing. + debug_assert!(tip.is_zero(), "tip should be zero if initial fee was zero."); + }, + } + + Ok(()) + } +} diff --git a/frame/transaction-payment/asset-tx-payment/src/payment.rs b/frame/transaction-payment/asset-tx-payment/src/payment.rs new file mode 100644 index 000000000000..09482f96490c --- /dev/null +++ b/frame/transaction-payment/asset-tx-payment/src/payment.rs @@ -0,0 +1,168 @@ +// Copyright (C) 2021 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. + +///! Traits and default implementation for paying transaction fees in assets. +use super::*; +use crate::Config; + +use codec::FullCodec; +use frame_support::{ + traits::{ + fungibles::{Balanced, CreditOf, Inspect}, + tokens::BalanceConversion, + }, + unsigned::TransactionValidityError, +}; +use scale_info::TypeInfo; +use sp_runtime::{ + traits::{ + AtLeast32BitUnsigned, DispatchInfoOf, MaybeSerializeDeserialize, One, PostDispatchInfoOf, + }, + transaction_validity::InvalidTransaction, +}; +use sp_std::{fmt::Debug, marker::PhantomData}; + +/// Handle withdrawing, refunding and depositing of transaction fees. +pub trait OnChargeAssetTransaction { + /// The underlying integer type in which fees are calculated. + type Balance: AtLeast32BitUnsigned + + FullCodec + + Copy + + MaybeSerializeDeserialize + + Debug + + Default + + TypeInfo; + /// The type used to identify the assets used for transaction payment. + type AssetId: FullCodec + Copy + MaybeSerializeDeserialize + Debug + Default + Eq + TypeInfo; + /// The type used to store the intermediate values between pre- and post-dispatch. + type LiquidityInfo; + + /// Before the transaction is executed the payment of the transaction fees needs to be secured. + /// + /// Note: The `fee` already includes the `tip`. + fn withdraw_fee( + who: &T::AccountId, + call: &T::Call, + dispatch_info: &DispatchInfoOf, + asset_id: Self::AssetId, + fee: Self::Balance, + tip: Self::Balance, + ) -> Result; + + /// After the transaction was executed the actual fee can be calculated. + /// This function should refund any overpaid fees and optionally deposit + /// the corrected amount. + /// + /// Note: The `fee` already includes the `tip`. + fn correct_and_deposit_fee( + who: &T::AccountId, + dispatch_info: &DispatchInfoOf, + post_info: &PostDispatchInfoOf, + corrected_fee: Self::Balance, + tip: Self::Balance, + already_withdrawn: Self::LiquidityInfo, + ) -> Result<(), TransactionValidityError>; +} + +/// Allows specifying what to do with the withdrawn asset fees. +pub trait HandleCredit> { + /// Implement to determine what to do with the withdrawn asset fees. + /// Default for `CreditOf` from the assets pallet is to burn and + /// decrease total issuance. + fn handle_credit(credit: CreditOf); +} + +/// Default implementation that just drops the credit according to the `OnDrop` in the underlying +/// imbalance type. +impl> HandleCredit for () { + fn handle_credit(_credit: CreditOf) {} +} + +/// Implements the asset transaction for a balance to asset converter (implementing +/// [`BalanceConversion`]) and a credit handler (implementing [`HandleCredit`]). +/// +/// The credit handler is given the complete fee in terms of the asset used for the transaction. +pub struct FungiblesAdapter(PhantomData<(CON, HC)>); + +/// Default implementation for a runtime instantiating this pallet, a balance to asset converter and +/// a credit handler. +impl OnChargeAssetTransaction for FungiblesAdapter +where + T: Config, + CON: BalanceConversion, AssetIdOf, AssetBalanceOf>, + HC: HandleCredit, + AssetIdOf: FullCodec + Copy + MaybeSerializeDeserialize + Debug + Default + Eq + TypeInfo, +{ + type Balance = BalanceOf; + type AssetId = AssetIdOf; + type LiquidityInfo = CreditOf; + + /// Withdraw the predicted fee from the transaction origin. + /// + /// Note: The `fee` already includes the `tip`. + fn withdraw_fee( + who: &T::AccountId, + _call: &T::Call, + _info: &DispatchInfoOf, + asset_id: Self::AssetId, + fee: Self::Balance, + _tip: Self::Balance, + ) -> Result { + // We don't know the precision of the underlying asset. Because the converted fee could be + // less than one (e.g. 0.5) but gets rounded down by integer division we introduce a minimum + // fee. + let min_converted_fee = if fee.is_zero() { Zero::zero() } else { One::one() }; + let converted_fee = CON::to_asset_balance(fee, asset_id) + .map_err(|_| TransactionValidityError::from(InvalidTransaction::Payment))? + .max(min_converted_fee); + let can_withdraw = >::can_withdraw( + asset_id.into(), + who, + converted_fee, + ); + if !matches!(can_withdraw, WithdrawConsequence::Success) { + return Err(InvalidTransaction::Payment.into()) + } + >::withdraw(asset_id.into(), who, converted_fee) + .map_err(|_| TransactionValidityError::from(InvalidTransaction::Payment)) + } + + /// Hand the fee and the tip over to the `[HandleCredit]` implementation. + /// Since the predicted fee might have been too high, parts of the fee may be refunded. + /// + /// Note: The `corrected_fee` already includes the `tip`. + fn correct_and_deposit_fee( + who: &T::AccountId, + _dispatch_info: &DispatchInfoOf, + _post_info: &PostDispatchInfoOf, + corrected_fee: Self::Balance, + _tip: Self::Balance, + paid: Self::LiquidityInfo, + ) -> Result<(), TransactionValidityError> { + let min_converted_fee = if corrected_fee.is_zero() { Zero::zero() } else { One::one() }; + // Convert the corrected fee into the asset used for payment. + let converted_fee = CON::to_asset_balance(corrected_fee, paid.asset().into()) + .map_err(|_| -> TransactionValidityError { InvalidTransaction::Payment.into() })? + .max(min_converted_fee); + // Calculate how much refund we should return. + let (final_fee, refund) = paid.split(converted_fee); + // Refund to the account that paid the fees. If this fails, the account might have dropped + // below the existential balance. In that case we don't refund anything. + let _ = >::resolve(who, refund); + // Handle the final fee, e.g. by transferring to the block author or burning. + HC::handle_credit(final_fee); + Ok(()) + } +} diff --git a/frame/transaction-payment/asset-tx-payment/src/tests.rs b/frame/transaction-payment/asset-tx-payment/src/tests.rs new file mode 100644 index 000000000000..bd5dc57239a2 --- /dev/null +++ b/frame/transaction-payment/asset-tx-payment/src/tests.rs @@ -0,0 +1,748 @@ +// Copyright (C) 2021 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. + +use super::*; +use crate as pallet_asset_tx_payment; + +use frame_support::{ + assert_ok, + pallet_prelude::*, + parameter_types, + traits::{fungibles::Mutate, FindAuthor}, + weights::{ + DispatchClass, DispatchInfo, PostDispatchInfo, Weight, WeightToFeeCoefficient, + WeightToFeeCoefficients, WeightToFeePolynomial, + }, + ConsensusEngineId, +}; +use frame_system as system; +use frame_system::EnsureRoot; +use pallet_balances::Call as BalancesCall; +use pallet_transaction_payment::CurrencyAdapter; +use smallvec::smallvec; +use sp_core::H256; +use sp_runtime::{ + testing::Header, + traits::{BlakeTwo256, ConvertInto, IdentityLookup, StaticLookup}, + Perbill, +}; +use std::cell::RefCell; + +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlock; +type Balance = u64; +type AccountId = u64; + +frame_support::construct_runtime!( + pub enum Runtime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: system::{Pallet, Call, Config, Storage, Event}, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + TransactionPayment: pallet_transaction_payment::{Pallet, Storage}, + Assets: pallet_assets::{Pallet, Call, Storage, Event}, + Authorship: pallet_authorship::{Pallet, Call, Storage}, + AssetTxPayment: pallet_asset_tx_payment::{Pallet}, + } +); + +const CALL: &::Call = + &Call::Balances(BalancesCall::transfer { dest: 2, value: 69 }); + +thread_local! { + static EXTRINSIC_BASE_WEIGHT: RefCell = RefCell::new(0); +} + +pub struct BlockWeights; +impl Get for BlockWeights { + fn get() -> frame_system::limits::BlockWeights { + frame_system::limits::BlockWeights::builder() + .base_block(0) + .for_class(DispatchClass::all(), |weights| { + weights.base_extrinsic = EXTRINSIC_BASE_WEIGHT.with(|v| *v.borrow()).into(); + }) + .for_class(DispatchClass::non_mandatory(), |weights| { + weights.max_total = 1024.into(); + }) + .build_or_panic() + } +} + +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub static TransactionByteFee: u64 = 1; + pub static WeightToFee: u64 = 1; +} + +impl frame_system::Config for Runtime { + type BaseCallFilter = frame_support::traits::Everything; + type BlockWeights = BlockWeights; + type BlockLength = (); + type DbWeight = (); + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Call = Call; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type Header = Header; + type Event = Event; + type BlockHashCount = BlockHashCount; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); +} + +parameter_types! { + pub const ExistentialDeposit: u64 = 10; + pub const MaxReserves: u32 = 50; +} + +impl pallet_balances::Config for Runtime { + type Balance = Balance; + type Event = Event; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type MaxLocks = (); + type WeightInfo = (); + type MaxReserves = MaxReserves; + type ReserveIdentifier = [u8; 8]; +} + +impl WeightToFeePolynomial for WeightToFee { + type Balance = u64; + + fn polynomial() -> WeightToFeeCoefficients { + smallvec![WeightToFeeCoefficient { + degree: 1, + coeff_frac: Perbill::zero(), + coeff_integer: WEIGHT_TO_FEE.with(|v| *v.borrow()), + negative: false, + }] + } +} + +parameter_types! { + pub const OperationalFeeMultiplier: u8 = 5; +} + +impl pallet_transaction_payment::Config for Runtime { + type OnChargeTransaction = CurrencyAdapter; + type TransactionByteFee = TransactionByteFee; + type WeightToFee = WeightToFee; + type FeeMultiplierUpdate = (); + type OperationalFeeMultiplier = OperationalFeeMultiplier; +} + +parameter_types! { + pub const AssetDeposit: u64 = 2; + pub const MetadataDeposit: u64 = 0; + pub const StringLimit: u32 = 20; +} + +impl pallet_assets::Config for Runtime { + type Event = Event; + type Balance = Balance; + type AssetId = u32; + type Currency = Balances; + type ForceOrigin = EnsureRoot; + type AssetDeposit = AssetDeposit; + type MetadataDepositBase = MetadataDeposit; + type MetadataDepositPerByte = MetadataDeposit; + type ApprovalDeposit = MetadataDeposit; + type StringLimit = StringLimit; + type Freezer = (); + type Extra = (); + type WeightInfo = (); +} + +pub struct HardcodedAuthor; +const BLOCK_AUTHOR: AccountId = 1234; +impl FindAuthor for HardcodedAuthor { + fn find_author<'a, I>(_: I) -> Option + where + I: 'a + IntoIterator, + { + Some(BLOCK_AUTHOR) + } +} + +impl pallet_authorship::Config for Runtime { + type FindAuthor = HardcodedAuthor; + type UncleGenerations = (); + type FilterUncle = (); + type EventHandler = (); +} + +pub struct CreditToBlockAuthor; +impl HandleCredit for CreditToBlockAuthor { + fn handle_credit(credit: CreditOf) { + let author = pallet_authorship::Pallet::::author(); + // What to do in case paying the author fails (e.g. because `fee < min_balance`) + // default: drop the result which will trigger the `OnDrop` of the imbalance. + let _ = >::resolve(&author, credit); + } +} + +impl Config for Runtime { + type Fungibles = Assets; + type OnChargeAssetTransaction = FungiblesAdapter< + pallet_assets::BalanceToAssetBalance, + CreditToBlockAuthor, + >; +} + +pub struct ExtBuilder { + balance_factor: u64, + base_weight: u64, + byte_fee: u64, + weight_to_fee: u64, +} + +impl Default for ExtBuilder { + fn default() -> Self { + Self { balance_factor: 1, base_weight: 0, byte_fee: 1, weight_to_fee: 1 } + } +} + +impl ExtBuilder { + pub fn base_weight(mut self, base_weight: u64) -> Self { + self.base_weight = base_weight; + self + } + pub fn balance_factor(mut self, factor: u64) -> Self { + self.balance_factor = factor; + self + } + fn set_constants(&self) { + EXTRINSIC_BASE_WEIGHT.with(|v| *v.borrow_mut() = self.base_weight); + TRANSACTION_BYTE_FEE.with(|v| *v.borrow_mut() = self.byte_fee); + WEIGHT_TO_FEE.with(|v| *v.borrow_mut() = self.weight_to_fee); + } + pub fn build(self) -> sp_io::TestExternalities { + self.set_constants(); + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + pallet_balances::GenesisConfig:: { + balances: if self.balance_factor > 0 { + vec![ + (1, 10 * self.balance_factor), + (2, 20 * self.balance_factor), + (3, 30 * self.balance_factor), + (4, 40 * self.balance_factor), + (5, 50 * self.balance_factor), + (6, 60 * self.balance_factor), + ] + } else { + vec![] + }, + } + .assimilate_storage(&mut t) + .unwrap(); + t.into() + } +} + +/// create a transaction info struct from weight. Handy to avoid building the whole struct. +pub fn info_from_weight(w: Weight) -> DispatchInfo { + // pays_fee: Pays::Yes -- class: DispatchClass::Normal + DispatchInfo { weight: w, ..Default::default() } +} + +fn post_info_from_weight(w: Weight) -> PostDispatchInfo { + PostDispatchInfo { actual_weight: Some(w), pays_fee: Default::default() } +} + +fn info_from_pays(p: Pays) -> DispatchInfo { + DispatchInfo { pays_fee: p, ..Default::default() } +} + +fn post_info_from_pays(p: Pays) -> PostDispatchInfo { + PostDispatchInfo { actual_weight: None, pays_fee: p } +} + +fn default_post_info() -> PostDispatchInfo { + PostDispatchInfo { actual_weight: None, pays_fee: Default::default() } +} + +#[test] +fn transaction_payment_in_native_possible() { + let balance_factor = 100; + ExtBuilder::default() + .balance_factor(balance_factor) + .base_weight(5) + .build() + .execute_with(|| { + let len = 10; + let pre = ChargeAssetTxPayment::::from(0, None) + .pre_dispatch(&1, CALL, &info_from_weight(5), len) + .unwrap(); + let initial_balance = 10 * balance_factor; + assert_eq!(Balances::free_balance(1), initial_balance - 5 - 5 - 10); + + assert_ok!(ChargeAssetTxPayment::::post_dispatch( + pre, + &info_from_weight(5), + &default_post_info(), + len, + &Ok(()) + )); + assert_eq!(Balances::free_balance(1), initial_balance - 5 - 5 - 10); + + let pre = ChargeAssetTxPayment::::from(5 /* tipped */, None) + .pre_dispatch(&2, CALL, &info_from_weight(100), len) + .unwrap(); + let initial_balance_for_2 = 20 * balance_factor; + assert_eq!(Balances::free_balance(2), initial_balance_for_2 - 5 - 10 - 100 - 5); + + assert_ok!(ChargeAssetTxPayment::::post_dispatch( + pre, + &info_from_weight(100), + &post_info_from_weight(50), + len, + &Ok(()) + )); + assert_eq!(Balances::free_balance(2), initial_balance_for_2 - 5 - 10 - 50 - 5); + }); +} + +#[test] +fn transaction_payment_in_asset_possible() { + let base_weight = 5; + let balance_factor = 100; + ExtBuilder::default() + .balance_factor(balance_factor) + .base_weight(base_weight) + .build() + .execute_with(|| { + // create the asset + let asset_id = 1; + let min_balance = 2; + assert_ok!(Assets::force_create( + Origin::root(), + asset_id, + 42, /* owner */ + true, /* is_sufficient */ + min_balance + )); + + // mint into the caller account + let caller = 1; + let beneficiary = ::Lookup::unlookup(caller); + let balance = 100; + assert_ok!(Assets::mint_into(asset_id, &beneficiary, balance)); + assert_eq!(Assets::balance(asset_id, caller), balance); + let weight = 5; + let len = 10; + // we convert the from weight to fee based on the ratio between asset min balance and + // existential deposit + let fee = (base_weight + weight + len as u64) * min_balance / ExistentialDeposit::get(); + let pre = ChargeAssetTxPayment::::from(0, Some(asset_id)) + .pre_dispatch(&caller, CALL, &info_from_weight(weight), len) + .unwrap(); + // assert that native balance is not used + assert_eq!(Balances::free_balance(caller), 10 * balance_factor); + // check that fee was charged in the given asset + assert_eq!(Assets::balance(asset_id, caller), balance - fee); + assert_eq!(Assets::balance(asset_id, BLOCK_AUTHOR), 0); + + assert_ok!(ChargeAssetTxPayment::::post_dispatch( + pre, + &info_from_weight(weight), + &default_post_info(), + len, + &Ok(()) + )); + assert_eq!(Assets::balance(asset_id, caller), balance - fee); + // check that the block author gets rewarded + assert_eq!(Assets::balance(asset_id, BLOCK_AUTHOR), fee); + }); +} + +#[test] +fn transaction_payment_without_fee() { + let base_weight = 5; + let balance_factor = 100; + ExtBuilder::default() + .balance_factor(balance_factor) + .base_weight(base_weight) + .build() + .execute_with(|| { + // create the asset + let asset_id = 1; + let min_balance = 2; + assert_ok!(Assets::force_create( + Origin::root(), + asset_id, + 42, /* owner */ + true, /* is_sufficient */ + min_balance + )); + + // mint into the caller account + let caller = 1; + let beneficiary = ::Lookup::unlookup(caller); + let balance = 100; + assert_ok!(Assets::mint_into(asset_id, &beneficiary, balance)); + assert_eq!(Assets::balance(asset_id, caller), balance); + let weight = 5; + let len = 10; + // we convert the from weight to fee based on the ratio between asset min balance and + // existential deposit + let fee = (base_weight + weight + len as u64) * min_balance / ExistentialDeposit::get(); + let pre = ChargeAssetTxPayment::::from(0, Some(asset_id)) + .pre_dispatch(&caller, CALL, &info_from_weight(weight), len) + .unwrap(); + // assert that native balance is not used + assert_eq!(Balances::free_balance(caller), 10 * balance_factor); + // check that fee was charged in the given asset + assert_eq!(Assets::balance(asset_id, caller), balance - fee); + assert_eq!(Assets::balance(asset_id, BLOCK_AUTHOR), 0); + + assert_ok!(ChargeAssetTxPayment::::post_dispatch( + pre, + &info_from_weight(weight), + &post_info_from_pays(Pays::No), + len, + &Ok(()) + )); + // caller should be refunded + assert_eq!(Assets::balance(asset_id, caller), balance); + // check that the block author did not get rewarded + assert_eq!(Assets::balance(asset_id, BLOCK_AUTHOR), 0); + }); +} + +#[test] +fn asset_transaction_payment_with_tip_and_refund() { + let base_weight = 5; + ExtBuilder::default() + .balance_factor(100) + .base_weight(base_weight) + .build() + .execute_with(|| { + // create the asset + let asset_id = 1; + let min_balance = 2; + assert_ok!(Assets::force_create( + Origin::root(), + asset_id, + 42, /* owner */ + true, /* is_sufficient */ + min_balance + )); + + // mint into the caller account + let caller = 2; + let beneficiary = ::Lookup::unlookup(caller); + let balance = 1000; + assert_ok!(Assets::mint_into(asset_id, &beneficiary, balance)); + assert_eq!(Assets::balance(asset_id, caller), balance); + let weight = 100; + let tip = 5; + let len = 10; + // we convert the from weight to fee based on the ratio between asset min balance and + // existential deposit + let fee_with_tip = + (base_weight + weight + len as u64 + tip) * min_balance / ExistentialDeposit::get(); + let pre = ChargeAssetTxPayment::::from(tip, Some(asset_id)) + .pre_dispatch(&caller, CALL, &info_from_weight(weight), len) + .unwrap(); + assert_eq!(Assets::balance(asset_id, caller), balance - fee_with_tip); + + let final_weight = 50; + assert_ok!(ChargeAssetTxPayment::::post_dispatch( + pre, + &info_from_weight(weight), + &post_info_from_weight(final_weight), + len, + &Ok(()) + )); + let final_fee = + fee_with_tip - (weight - final_weight) * min_balance / ExistentialDeposit::get(); + assert_eq!(Assets::balance(asset_id, caller), balance - (final_fee)); + assert_eq!(Assets::balance(asset_id, BLOCK_AUTHOR), final_fee); + }); +} + +#[test] +fn payment_from_account_with_only_assets() { + let base_weight = 5; + ExtBuilder::default() + .balance_factor(100) + .base_weight(base_weight) + .build() + .execute_with(|| { + // create the asset + let asset_id = 1; + let min_balance = 2; + assert_ok!(Assets::force_create( + Origin::root(), + asset_id, + 42, /* owner */ + true, /* is_sufficient */ + min_balance + )); + + // mint into the caller account + let caller = 333; + let beneficiary = ::Lookup::unlookup(caller); + let balance = 100; + assert_ok!(Assets::mint_into(asset_id, &beneficiary, balance)); + assert_eq!(Assets::balance(asset_id, caller), balance); + // assert that native balance is not necessary + assert_eq!(Balances::free_balance(caller), 0); + let weight = 5; + let len = 10; + // we convert the from weight to fee based on the ratio between asset min balance and + // existential deposit + let fee = (base_weight + weight + len as u64) * min_balance / ExistentialDeposit::get(); + let pre = ChargeAssetTxPayment::::from(0, Some(asset_id)) + .pre_dispatch(&caller, CALL, &info_from_weight(weight), len) + .unwrap(); + assert_eq!(Balances::free_balance(caller), 0); + // check that fee was charged in the given asset + assert_eq!(Assets::balance(asset_id, caller), balance - fee); + + assert_ok!(ChargeAssetTxPayment::::post_dispatch( + pre, + &info_from_weight(weight), + &default_post_info(), + len, + &Ok(()) + )); + assert_eq!(Assets::balance(asset_id, caller), balance - fee); + assert_eq!(Balances::free_balance(caller), 0); + }); +} + +#[test] +fn payment_only_with_existing_sufficient_asset() { + let base_weight = 5; + ExtBuilder::default() + .balance_factor(100) + .base_weight(base_weight) + .build() + .execute_with(|| { + let asset_id = 1; + let caller = 1; + let weight = 5; + let len = 10; + // pre_dispatch fails for non-existent asset + assert!(ChargeAssetTxPayment::::from(0, Some(asset_id)) + .pre_dispatch(&caller, CALL, &info_from_weight(weight), len) + .is_err()); + + // create the non-sufficient asset + let min_balance = 2; + assert_ok!(Assets::force_create( + Origin::root(), + asset_id, + 42, /* owner */ + false, /* is_sufficient */ + min_balance + )); + // pre_dispatch fails for non-sufficient asset + assert!(ChargeAssetTxPayment::::from(0, Some(asset_id)) + .pre_dispatch(&caller, CALL, &info_from_weight(weight), len) + .is_err()); + }); +} + +#[test] +fn converted_fee_is_never_zero_if_input_fee_is_not() { + let base_weight = 1; + ExtBuilder::default() + .balance_factor(100) + .base_weight(base_weight) + .build() + .execute_with(|| { + // create the asset + let asset_id = 1; + let min_balance = 1; + assert_ok!(Assets::force_create( + Origin::root(), + asset_id, + 42, /* owner */ + true, /* is_sufficient */ + min_balance + )); + + // mint into the caller account + let caller = 333; + let beneficiary = ::Lookup::unlookup(caller); + let balance = 100; + assert_ok!(Assets::mint_into(asset_id, &beneficiary, balance)); + assert_eq!(Assets::balance(asset_id, caller), balance); + let weight = 1; + let len = 1; + // we convert the from weight to fee based on the ratio between asset min balance and + // existential deposit + let fee = (base_weight + weight + len as u64) * min_balance / ExistentialDeposit::get(); + // naive fee calculation would round down to zero + assert_eq!(fee, 0); + { + let pre = ChargeAssetTxPayment::::from(0, Some(asset_id)) + .pre_dispatch(&caller, CALL, &info_from_pays(Pays::No), len) + .unwrap(); + // `Pays::No` still implies no fees + assert_eq!(Assets::balance(asset_id, caller), balance); + + assert_ok!(ChargeAssetTxPayment::::post_dispatch( + pre, + &info_from_pays(Pays::No), + &post_info_from_pays(Pays::No), + len, + &Ok(()) + )); + assert_eq!(Assets::balance(asset_id, caller), balance); + } + let pre = ChargeAssetTxPayment::::from(0, Some(asset_id)) + .pre_dispatch(&caller, CALL, &info_from_weight(weight), len) + .unwrap(); + // check that at least one coin was charged in the given asset + assert_eq!(Assets::balance(asset_id, caller), balance - 1); + + assert_ok!(ChargeAssetTxPayment::::post_dispatch( + pre, + &info_from_weight(weight), + &default_post_info(), + len, + &Ok(()) + )); + assert_eq!(Assets::balance(asset_id, caller), balance - 1); + }); +} + +#[test] +fn post_dispatch_fee_is_zero_if_pre_dispatch_fee_is_zero() { + let base_weight = 1; + ExtBuilder::default() + .balance_factor(100) + .base_weight(base_weight) + .build() + .execute_with(|| { + // create the asset + let asset_id = 1; + let min_balance = 100; + assert_ok!(Assets::force_create( + Origin::root(), + asset_id, + 42, /* owner */ + true, /* is_sufficient */ + min_balance + )); + + // mint into the caller account + let caller = 333; + let beneficiary = ::Lookup::unlookup(caller); + let balance = 100; + assert_ok!(Assets::mint_into(asset_id, &beneficiary, balance)); + assert_eq!(Assets::balance(asset_id, caller), balance); + let weight = 1; + let len = 1; + // we convert the from weight to fee based on the ratio between asset min balance and + // existential deposit + let fee = (base_weight + weight + len as u64) * min_balance / ExistentialDeposit::get(); + // calculated fee is greater than 0 + assert!(fee > 0); + let pre = ChargeAssetTxPayment::::from(0, Some(asset_id)) + .pre_dispatch(&caller, CALL, &info_from_pays(Pays::No), len) + .unwrap(); + // `Pays::No` implies no pre-dispatch fees + assert_eq!(Assets::balance(asset_id, caller), balance); + let (_tip, _who, initial_payment) = ⪯ + let not_paying = match initial_payment { + &InitialPayment::Nothing => true, + _ => false, + }; + assert!(not_paying, "initial payment should be Nothing if we pass Pays::No"); + + // `Pays::Yes` on post-dispatch does not mean we pay (we never charge more than the + // initial fee) + assert_ok!(ChargeAssetTxPayment::::post_dispatch( + pre, + &info_from_pays(Pays::No), + &post_info_from_pays(Pays::Yes), + len, + &Ok(()) + )); + assert_eq!(Assets::balance(asset_id, caller), balance); + }); +} + +#[test] +fn post_dispatch_fee_is_zero_if_unsigned_pre_dispatch_fee_is_zero() { + let base_weight = 1; + ExtBuilder::default() + .balance_factor(100) + .base_weight(base_weight) + .build() + .execute_with(|| { + // create the asset + let asset_id = 1; + let min_balance = 100; + assert_ok!(Assets::force_create( + Origin::root(), + asset_id, + 42, /* owner */ + true, /* is_sufficient */ + min_balance + )); + + // mint into the caller account + let caller = 333; + let beneficiary = ::Lookup::unlookup(caller); + let balance = 100; + assert_ok!(Assets::mint_into(asset_id, &beneficiary, balance)); + assert_eq!(Assets::balance(asset_id, caller), balance); + let weight = 1; + let len = 1; + let pre = ChargeAssetTxPayment::::pre_dispatch_unsigned( + CALL, + &info_from_weight(weight), + len, + ) + .unwrap(); + + assert_eq!(Assets::balance(asset_id, caller), balance); + let (_tip, _who, initial_payment) = ⪯ + let not_paying = match initial_payment { + &InitialPayment::Nothing => true, + _ => false, + }; + assert!(not_paying, "initial payment is Nothing for unsigned extrinsics"); + + // `Pays::Yes` on post-dispatch does not mean we pay (we never charge more than the + // initial fee) + assert_ok!(ChargeAssetTxPayment::::post_dispatch( + pre, + &info_from_weight(weight), + &post_info_from_pays(Pays::Yes), + len, + &Ok(()) + )); + assert_eq!(Assets::balance(asset_id, caller), balance); + }); +} From 72b9c36d66e351af9d90cbf8c37e2cf90dd59582 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Fri, 19 Nov 2021 10:37:37 +0100 Subject: [PATCH 206/695] Don't generate the consensusEngine field in chain specs (#10303) --- client/chain-spec/res/chain_spec.json | 1 - client/chain-spec/res/chain_spec2.json | 1 - client/chain-spec/src/chain_spec.rs | 1 + 3 files changed, 1 insertion(+), 2 deletions(-) diff --git a/client/chain-spec/res/chain_spec.json b/client/chain-spec/res/chain_spec.json index 673f35d50791..c3365a9192f6 100644 --- a/client/chain-spec/res/chain_spec.json +++ b/client/chain-spec/res/chain_spec.json @@ -19,7 +19,6 @@ ["wss://telemetry.polkadot.io/submit/", 0] ], "protocolId": "fir", - "consensusEngine": null, "genesis": { "raw": [ { diff --git a/client/chain-spec/res/chain_spec2.json b/client/chain-spec/res/chain_spec2.json index 950a7fc82749..00b9d603ae29 100644 --- a/client/chain-spec/res/chain_spec2.json +++ b/client/chain-spec/res/chain_spec2.json @@ -19,7 +19,6 @@ ["wss://telemetry.polkadot.io/submit/", 0] ], "protocolId": "fir", - "consensusEngine": null, "myProperty": "Test Extension", "genesis": { "raw": [ diff --git a/client/chain-spec/src/chain_spec.rs b/client/chain-spec/src/chain_spec.rs index 4aa0aa74630e..8d8f62a5182c 100644 --- a/client/chain-spec/src/chain_spec.rs +++ b/client/chain-spec/src/chain_spec.rs @@ -168,6 +168,7 @@ struct ClientSpec { #[serde(flatten)] extensions: E, // Never used, left only for backward compatibility. + #[serde(default, skip_serializing)] consensus_engine: (), #[serde(skip_serializing)] #[allow(unused)] From 0d0299099b18816fa3de1dbbe9f8f7b7c751994c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Fri, 19 Nov 2021 12:33:28 +0100 Subject: [PATCH 207/695] Offchain worker: Enable http2 and improve logging (#10305) * Offchain worker: Enable http2 and improve logging Apparently some webpages now return http2 by default and that silently breaks the offchain http extension. The solution to this is to enable the `http2` feature of hyper. Besides that, this pr improves the logging to make it easier to debug such errors. * FMT * Adds http2 test --- Cargo.lock | 22 +++++- client/offchain/Cargo.toml | 4 +- client/offchain/src/api.rs | 50 ++++++++------ client/offchain/src/api/http.rs | 119 ++++++++++++++++++++++++++------ client/offchain/src/lib.rs | 32 ++++++--- 5 files changed, 172 insertions(+), 55 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 32234cc4c93a..60f8217d69e8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2521,6 +2521,25 @@ dependencies = [ "web-sys", ] +[[package]] +name = "h2" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fd819562fcebdac5afc5c113c3ec36f902840b70fd4fc458799c8ce4607ae55" +dependencies = [ + "bytes 1.0.1", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "half" version = "1.7.1" @@ -2738,6 +2757,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", + "h2", "http", "http-body", "httparse", @@ -8349,7 +8369,6 @@ dependencies = [ "hyper 0.14.14", "hyper-rustls", "lazy_static", - "log 0.4.14", "num_cpus", "once_cell", "parity-scale-codec", @@ -8371,6 +8390,7 @@ dependencies = [ "substrate-test-runtime-client", "threadpool", "tokio", + "tracing", ] [[package]] diff --git a/client/offchain/Cargo.toml b/client/offchain/Cargo.toml index 2a6fdddd7ad3..b92ee7041e5f 100644 --- a/client/offchain/Cargo.toml +++ b/client/offchain/Cargo.toml @@ -19,7 +19,6 @@ hex = "0.4" fnv = "1.0.6" futures = "0.3.16" futures-timer = "3.0.2" -log = "0.4.8" num_cpus = "1.10" parking_lot = "0.11.1" rand = "0.7.2" @@ -31,9 +30,10 @@ sp-offchain = { version = "4.0.0-dev", path = "../../primitives/offchain" } sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } sc-utils = { version = "4.0.0-dev", path = "../utils" } threadpool = "1.7" -hyper = { version = "0.14.14", features = ["stream"] } +hyper = { version = "0.14.14", features = ["stream", "http2"] } hyper-rustls = "0.22.1" once_cell = "1.8" +tracing = "0.1.29" [dev-dependencies] sc-client-db = { version = "0.10.0-dev", default-features = true, path = "../db" } diff --git a/client/offchain/src/api.rs b/client/offchain/src/api.rs index 07136d1815b9..c2830510b015 100644 --- a/client/offchain/src/api.rs +++ b/client/offchain/src/api.rs @@ -37,10 +37,11 @@ mod http; mod timestamp; fn unavailable_yet(name: &str) -> R { - log::error!( - target: "sc_offchain", + tracing::error!( + target: super::LOG_TARGET, "The {:?} API is not available for offchain workers yet. Follow \ - https://github.com/paritytech/substrate/issues/1458 for details", name + https://github.com/paritytech/substrate/issues/1458 for details", + name ); Default::default() } @@ -75,9 +76,12 @@ impl Db { impl offchain::DbExternalities for Db { fn local_storage_set(&mut self, kind: StorageKind, key: &[u8], value: &[u8]) { - log::debug!( - target: "sc_offchain", - "{:?}: Write: {:?} <= {:?}", kind, hex::encode(key), hex::encode(value) + tracing::debug!( + target: "offchain-worker::storage", + ?kind, + key = ?hex::encode(key), + value = ?hex::encode(value), + "Write", ); match kind { StorageKind::PERSISTENT => self.persistent.set(STORAGE_PREFIX, key, value), @@ -86,9 +90,11 @@ impl offchain::DbExternalities for Db { } fn local_storage_clear(&mut self, kind: StorageKind, key: &[u8]) { - log::debug!( - target: "sc_offchain", - "{:?}: Clear: {:?}", kind, hex::encode(key) + tracing::debug!( + target: "offchain-worker::storage", + ?kind, + key = ?hex::encode(key), + "Clear", ); match kind { StorageKind::PERSISTENT => self.persistent.remove(STORAGE_PREFIX, key), @@ -103,13 +109,13 @@ impl offchain::DbExternalities for Db { old_value: Option<&[u8]>, new_value: &[u8], ) -> bool { - log::debug!( - target: "sc_offchain", - "{:?}: CAS: {:?} <= {:?} vs {:?}", - kind, - hex::encode(key), - hex::encode(new_value), - old_value.as_ref().map(hex::encode), + tracing::debug!( + target: "offchain-worker::storage", + ?kind, + key = ?hex::encode(key), + new_value = ?hex::encode(new_value), + old_value = ?old_value.as_ref().map(hex::encode), + "CAS", ); match kind { StorageKind::PERSISTENT => @@ -123,12 +129,12 @@ impl offchain::DbExternalities for Db { StorageKind::PERSISTENT => self.persistent.get(STORAGE_PREFIX, key), StorageKind::LOCAL => unavailable_yet(LOCAL_DB), }; - log::debug!( - target: "sc_offchain", - "{:?}: Read: {:?} => {:?}", - kind, - hex::encode(key), - result.as_ref().map(hex::encode) + tracing::debug!( + target: "offchain-worker::storage", + ?kind, + key = ?hex::encode(key), + result = ?result.as_ref().map(hex::encode), + "Read", ); result } diff --git a/client/offchain/src/api/http.rs b/client/offchain/src/api/http.rs index a2975bad1652..632c94b48107 100644 --- a/client/offchain/src/api/http.rs +++ b/client/offchain/src/api/http.rs @@ -33,7 +33,6 @@ use fnv::FnvHashMap; use futures::{channel::mpsc, future, prelude::*}; use hyper::{client, Body, Client as HyperClient}; use hyper_rustls::HttpsConnector; -use log::error; use once_cell::sync::Lazy; use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender}; use sp_core::offchain::{HttpError, HttpRequestId, HttpRequestStatus, Timestamp}; @@ -46,6 +45,8 @@ use std::{ task::{Context, Poll}, }; +const LOG_TARGET: &str = "offchain-worker::http"; + /// Wrapper struct used for keeping the hyper_rustls client running. #[derive(Clone)] pub struct SharedClient(Arc, Body>>>); @@ -146,13 +147,24 @@ impl HttpApi { match self.next_id.0.checked_add(1) { Some(new_id) => self.next_id.0 = new_id, None => { - error!("Overflow in offchain worker HTTP request ID assignment"); + tracing::error!( + target: LOG_TARGET, + "Overflow in offchain worker HTTP request ID assignment" + ); return Err(()) }, }; self.requests .insert(new_id, HttpApiRequest::NotDispatched(request, body_sender)); + tracing::error!( + target: LOG_TARGET, + id = %new_id.0, + %method, + %uri, + "Requested started", + ); + Ok(new_id) } @@ -168,11 +180,14 @@ impl HttpApi { _ => return Err(()), }; - let name = hyper::header::HeaderName::try_from(name).map_err(drop)?; - let value = hyper::header::HeaderValue::try_from(value).map_err(drop)?; + let header_name = hyper::header::HeaderName::try_from(name).map_err(drop)?; + let header_value = hyper::header::HeaderValue::try_from(value).map_err(drop)?; // Note that we're always appending headers and never replacing old values. // We assume here that the user knows what they're doing. - request.headers_mut().append(name, value); + request.headers_mut().append(header_name, header_value); + + tracing::debug!(target: LOG_TARGET, id = %request_id.0, %name, %value, "Added header to request"); + Ok(()) } @@ -207,7 +222,7 @@ impl HttpApi { sender.send_data(hyper::body::Bytes::from(chunk.to_owned())), ) .map_err(|_| { - error!("HTTP sender refused data despite being ready"); + tracing::error!(target: "offchain-worker::http", "HTTP sender refused data despite being ready"); HttpError::IoError }) }; @@ -215,6 +230,7 @@ impl HttpApi { loop { request = match request { HttpApiRequest::NotDispatched(request, sender) => { + tracing::debug!(target: LOG_TARGET, id = %request_id.0, "Added new body chunk"); // If the request is not dispatched yet, dispatch it and loop again. let _ = self .to_worker @@ -225,14 +241,20 @@ impl HttpApi { HttpApiRequest::Dispatched(Some(mut sender)) => { if !chunk.is_empty() { match poll_sender(&mut sender) { - Err(HttpError::IoError) => return Err(HttpError::IoError), + Err(HttpError::IoError) => { + tracing::debug!(target: LOG_TARGET, id = %request_id.0, "Encountered io error while trying to add new chunk to body"); + return Err(HttpError::IoError) + }, other => { + tracing::debug!(target: LOG_TARGET, id = %request_id.0, res = ?other, "Added chunk to body"); self.requests .insert(request_id, HttpApiRequest::Dispatched(Some(sender))); return other }, } } else { + tracing::debug!(target: LOG_TARGET, id = %request_id.0, "Finished writing body"); + // Writing an empty body is a hint that we should stop writing. Dropping // the sender. self.requests.insert(request_id, HttpApiRequest::Dispatched(None)); @@ -250,14 +272,20 @@ impl HttpApi { .as_mut() .expect("Can only enter this match branch if Some; qed"), ) { - Err(HttpError::IoError) => return Err(HttpError::IoError), + Err(HttpError::IoError) => { + tracing::debug!(target: LOG_TARGET, id = %request_id.0, "Encountered io error while trying to add new chunk to body"); + return Err(HttpError::IoError) + }, other => { + tracing::debug!(target: LOG_TARGET, id = %request_id.0, res = ?other, "Added chunk to body"); self.requests .insert(request_id, HttpApiRequest::Response(response)); return other }, } } else { + tracing::debug!(target: LOG_TARGET, id = %request_id.0, "Finished writing body"); + // Writing an empty body is a hint that we should stop writing. Dropping // the sender. self.requests.insert( @@ -271,13 +299,18 @@ impl HttpApi { } }, - HttpApiRequest::Fail(_) => - // If the request has already failed, return without putting back the request - // in the list. - return Err(HttpError::IoError), + HttpApiRequest::Fail(error) => { + tracing::debug!(target: LOG_TARGET, id = %request_id.0, ?error, "Request failed"); + + // If the request has already failed, return without putting back the request + // in the list. + return Err(HttpError::IoError) + }, v @ HttpApiRequest::Dispatched(None) | v @ HttpApiRequest::Response(HttpApiRequestRp { sending_body: None, .. }) => { + tracing::debug!(target: LOG_TARGET, id = %request_id.0, "Body sending already finished"); + // We have already finished sending this body. self.requests.insert(request_id, v); return Err(HttpError::Invalid) @@ -350,8 +383,19 @@ impl HttpApi { // Requests in "fail" mode are purged before returning. debug_assert_eq!(output.len(), ids.len()); for n in (0..ids.len()).rev() { - if let HttpRequestStatus::IoError = output[n] { - self.requests.remove(&ids[n]); + match output[n] { + HttpRequestStatus::IoError => { + self.requests.remove(&ids[n]); + }, + HttpRequestStatus::Invalid => { + tracing::debug!(target: LOG_TARGET, id = %ids[n].0, "Unknown request"); + }, + HttpRequestStatus::DeadlineReached => { + tracing::debug!(target: LOG_TARGET, id = %ids[n].0, "Deadline reached"); + }, + HttpRequestStatus::Finished(_) => { + tracing::debug!(target: LOG_TARGET, id = %ids[n].0, "Request finished"); + }, } } return output @@ -388,20 +432,23 @@ impl HttpApi { ); }, None => {}, // can happen if we detected an IO error when sending the body - _ => error!("State mismatch between the API and worker"), + _ => + tracing::error!(target: "offchain-worker::http", "State mismatch between the API and worker"), } }, Some(WorkerToApi::Fail { id, error }) => match self.requests.remove(&id) { Some(HttpApiRequest::Dispatched(_)) => { + tracing::debug!(target: LOG_TARGET, id = %id.0, ?error, "Request failed"); self.requests.insert(id, HttpApiRequest::Fail(error)); }, None => {}, // can happen if we detected an IO error when sending the body - _ => error!("State mismatch between the API and worker"), + _ => + tracing::error!(target: "offchain-worker::http", "State mismatch between the API and worker"), }, None => { - error!("Worker has crashed"); + tracing::error!(target: "offchain-worker::http", "Worker has crashed"); return ids.iter().map(|_| HttpRequestStatus::IoError).collect() }, } @@ -474,7 +521,7 @@ impl HttpApi { }, Err(err) => { // This code should never be reached unless there's a logic error somewhere. - error!("Failed to read from current read chunk: {:?}", err); + tracing::error!(target: "offchain-worker::http", "Failed to read from current read chunk: {:?}", err); return Err(HttpError::IoError) }, } @@ -719,7 +766,10 @@ mod tests { // Returns an `HttpApi` whose worker is ran in the background, and a `SocketAddr` to an HTTP // server that runs in the background as well. macro_rules! build_api_server { - () => {{ + () => { + build_api_server!(hyper::Response::new(hyper::Body::from("Hello World!"))) + }; + ( $response:expr ) => {{ let hyper_client = SHARED_CLIENT.clone(); let (api, worker) = http(hyper_client.clone()); @@ -736,9 +786,7 @@ mod tests { // otherwise the tests are flaky. let _ = req.into_body().collect::>().await; - Ok::<_, Infallible>(hyper::Response::new(hyper::Body::from( - "Hello World!", - ))) + Ok::<_, Infallible>($response) }, )) }), @@ -776,6 +824,33 @@ mod tests { assert_eq!(&buf[..n], b"Hello World!"); } + #[test] + fn basic_http2_localhost() { + let deadline = timestamp::now().add(Duration::from_millis(10_000)); + + // Performs an HTTP query to a background HTTP server. + + let (mut api, addr) = build_api_server!(hyper::Response::builder() + .version(hyper::Version::HTTP_2) + .body(hyper::Body::from("Hello World!")) + .unwrap()); + + let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); + api.request_write_body(id, &[], Some(deadline)).unwrap(); + + match api.response_wait(&[id], Some(deadline))[0] { + HttpRequestStatus::Finished(200) => {}, + v => panic!("Connecting to localhost failed: {:?}", v), + } + + let headers = api.response_headers(id); + assert!(headers.iter().any(|(h, _)| h.eq_ignore_ascii_case(b"Date"))); + + let mut buf = vec![0; 2048]; + let n = api.response_read_body(id, &mut buf, Some(deadline)).unwrap(); + assert_eq!(&buf[..n], b"Hello World!"); + } + #[test] fn request_start_invalid_call() { let (mut api, addr) = build_api_server!(); diff --git a/client/offchain/src/lib.rs b/client/offchain/src/lib.rs index 2de24e10d927..f9230a1552e1 100644 --- a/client/offchain/src/lib.rs +++ b/client/offchain/src/lib.rs @@ -41,7 +41,6 @@ use futures::{ future::{ready, Future}, prelude::*, }; -use log::{debug, warn}; use parking_lot::Mutex; use sc_network::{ExHashT, NetworkService, NetworkStateInfo, PeerId}; use sp_api::{ApiExt, ProvideRuntimeApi}; @@ -57,6 +56,8 @@ mod api; pub use api::Db as OffchainDb; pub use sp_offchain::{OffchainWorkerApi, STORAGE_PREFIX}; +const LOG_TARGET: &str = "offchain-worker"; + /// NetworkProvider provides [`OffchainWorkers`] with all necessary hooks into the /// underlying Substrate networking. pub trait NetworkProvider: NetworkStateInfo { @@ -149,15 +150,25 @@ where err => { let help = "Consider turning off offchain workers if they are not part of your runtime."; - log::error!("Unsupported Offchain Worker API version: {:?}. {}.", err, help); + tracing::error!( + target: LOG_TARGET, + "Unsupported Offchain Worker API version: {:?}. {}.", + err, + help + ); 0 }, }; - debug!("Checking offchain workers at {:?}: version:{}", at, version); + tracing::debug!( + target: LOG_TARGET, + "Checking offchain workers at {:?}: version:{}", + at, + version + ); let process = (version > 0).then(|| { let (api, runner) = api::AsyncApi::new(network_provider, is_validator, self.shared_http_client.clone()); - debug!("Spawning offchain workers at {:?}", at); + tracing::debug!(target: LOG_TARGET, "Spawning offchain workers at {:?}", at); let header = header.clone(); let client = self.client.clone(); @@ -167,7 +178,7 @@ where self.spawn_worker(move || { let runtime = client.runtime_api(); let api = Box::new(api); - debug!("Running offchain workers at {:?}", at); + tracing::debug!(target: LOG_TARGET, "Running offchain workers at {:?}", at); let context = ExecutionContext::OffchainCall(Some((api, capabilities))); let run = if version == 2 { @@ -181,7 +192,12 @@ where ) }; if let Err(e) = run { - log::error!("Error running offchain workers at {:?}: {:?}", at, e); + tracing::error!( + target: LOG_TARGET, + "Error running offchain workers at {:?}: {:?}", + at, + e + ); } }); @@ -232,8 +248,8 @@ pub async fn notification_future( .boxed(), ); } else { - log::debug!( - target: "sc_offchain", + tracing::debug!( + target: LOG_TARGET, "Skipping offchain workers for non-canon block: {:?}", n.header, ) From 69e384bae9f6189089d2136edb560644964b8788 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Nov 2021 12:36:09 +0100 Subject: [PATCH 208/695] Bump libsecp256k1 from 0.6.0 to 0.7.0 (#10214) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Bump libsecp256k1 from 0.6.0 to 0.7.0 Bumps [libsecp256k1](https://github.com/paritytech/libsecp256k1) from 0.6.0 to 0.7.0. - [Release notes](https://github.com/paritytech/libsecp256k1/releases) - [Changelog](https://github.com/paritytech/libsecp256k1/blob/master/CHANGELOG.md) - [Commits](https://github.com/paritytech/libsecp256k1/commits) --- updated-dependencies: - dependency-name: libsecp256k1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Fix pallet_contracts for new libsecp256k1 version Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alexander Theißen --- Cargo.lock | 42 ++++++++++-------------- client/executor/Cargo.toml | 2 +- frame/contracts/Cargo.toml | 8 ++--- frame/contracts/src/benchmarking/code.rs | 14 ++++---- primitives/core/Cargo.toml | 2 +- primitives/io/Cargo.toml | 2 +- 6 files changed, 31 insertions(+), 39 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 60f8217d69e8..e9798d4c4205 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3843,25 +3843,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "libsecp256k1" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9d220bc1feda2ac231cb78c3d26f27676b8cf82c96971f7aeef3d0cf2797c73" -dependencies = [ - "arrayref", - "base64 0.12.3", - "digest 0.9.0", - "hmac-drbg", - "libsecp256k1-core 0.2.2", - "libsecp256k1-gen-ecmult 0.2.1", - "libsecp256k1-gen-genmult 0.2.1", - "rand 0.7.3", - "serde", - "sha2 0.9.8", - "typenum", -] - [[package]] name = "libsecp256k1" version = "0.7.0" @@ -3871,12 +3852,14 @@ dependencies = [ "arrayref", "base64 0.13.0", "digest 0.9.0", + "hmac-drbg", "libsecp256k1-core 0.3.0", "libsecp256k1-gen-ecmult 0.3.0", "libsecp256k1-gen-genmult 0.3.0", "rand 0.8.4", "serde", "sha2 0.9.8", + "typenum", ] [[package]] @@ -5414,7 +5397,7 @@ dependencies = [ "frame-support", "frame-system", "hex-literal", - "libsecp256k1 0.6.0", + "libsecp256k1 0.7.0", "log 0.4.14", "pallet-balances", "pallet-contracts-primitives", @@ -5425,8 +5408,8 @@ dependencies = [ "parity-scale-codec", "pretty_assertions", "pwasm-utils", - "rand 0.7.3", - "rand_pcg 0.2.1", + "rand 0.8.4", + "rand_pcg 0.3.1", "scale-info", "serde", "smallvec 1.7.0", @@ -7233,6 +7216,15 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "rand_pcg" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59cad018caf63deb318e5a4586d99a24424a364f40f1e5778c29aca23f4fc73e" +dependencies = [ + "rand_core 0.6.2", +] + [[package]] name = "rand_xorshift" version = "0.1.1" @@ -8068,7 +8060,7 @@ version = "0.10.0-dev" dependencies = [ "hex-literal", "lazy_static", - "libsecp256k1 0.6.0", + "libsecp256k1 0.7.0", "log 0.4.14", "parity-scale-codec", "parking_lot 0.11.1", @@ -9442,7 +9434,7 @@ dependencies = [ "hex-literal", "impl-serde", "lazy_static", - "libsecp256k1 0.6.0", + "libsecp256k1 0.7.0", "log 0.4.14", "merlin", "num-traits", @@ -9562,7 +9554,7 @@ version = "4.0.0-dev" dependencies = [ "futures 0.3.16", "hash-db", - "libsecp256k1 0.6.0", + "libsecp256k1 0.7.0", "log 0.4.14", "parity-scale-codec", "parking_lot 0.11.1", diff --git a/client/executor/Cargo.toml b/client/executor/Cargo.toml index 4a8e67810543..ebdcc44ff0d8 100644 --- a/client/executor/Cargo.toml +++ b/client/executor/Cargo.toml @@ -32,7 +32,7 @@ sc-executor-wasmi = { version = "0.10.0-dev", path = "wasmi" } sc-executor-wasmtime = { version = "0.10.0-dev", path = "wasmtime", optional = true } parking_lot = "0.11.1" log = "0.4.8" -libsecp256k1 = "0.6" +libsecp256k1 = "0.7" sp-core-hashing-proc-macro = { version = "4.0.0-dev", path = "../../primitives/core/hashing/proc-macro" } [dev-dependencies] diff --git a/frame/contracts/Cargo.toml b/frame/contracts/Cargo.toml index dec33768a042..6639d939e179 100644 --- a/frame/contracts/Cargo.toml +++ b/frame/contracts/Cargo.toml @@ -28,9 +28,9 @@ smallvec = { version = "1", default-features = false, features = [ wasmi-validation = { version = "0.4", default-features = false } # Only used in benchmarking to generate random contract code -libsecp256k1 = { version = "0.6.0", optional = true, default-features = false, features = ["hmac", "static-context"] } -rand = { version = "0.7.3", optional = true, default-features = false } -rand_pcg = { version = "0.2", optional = true } +libsecp256k1 = { version = "0.7", optional = true, default-features = false, features = ["hmac", "static-context"] } +rand = { version = "0.8", optional = true, default-features = false } +rand_pcg = { version = "0.3", optional = true } # Substrate Dependencies frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } @@ -47,7 +47,7 @@ sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primit [dev-dependencies] assert_matches = "1" hex-literal = "0.3" -pretty_assertions = "1.0.0" +pretty_assertions = "1" wat = "1" # Substrate Dependencies diff --git a/frame/contracts/src/benchmarking/code.rs b/frame/contracts/src/benchmarking/code.rs index 98f52f4719a6..5dac8a84ace8 100644 --- a/frame/contracts/src/benchmarking/code.rs +++ b/frame/contracts/src/benchmarking/code.rs @@ -495,11 +495,11 @@ pub mod body { vec![Instruction::I32Const(current as i32)] }, DynInstr::RandomUnaligned(low, high) => { - let unaligned = rng.gen_range(*low, *high) | 1; + let unaligned = rng.gen_range(*low..*high) | 1; vec![Instruction::I32Const(unaligned as i32)] }, DynInstr::RandomI32(low, high) => { - vec![Instruction::I32Const(rng.gen_range(*low, *high))] + vec![Instruction::I32Const(rng.gen_range(*low..*high))] }, DynInstr::RandomI32Repeated(num) => (&mut rng) .sample_iter(Standard) @@ -512,19 +512,19 @@ pub mod body { .map(|val| Instruction::I64Const(val)) .collect(), DynInstr::RandomGetLocal(low, high) => { - vec![Instruction::GetLocal(rng.gen_range(*low, *high))] + vec![Instruction::GetLocal(rng.gen_range(*low..*high))] }, DynInstr::RandomSetLocal(low, high) => { - vec![Instruction::SetLocal(rng.gen_range(*low, *high))] + vec![Instruction::SetLocal(rng.gen_range(*low..*high))] }, DynInstr::RandomTeeLocal(low, high) => { - vec![Instruction::TeeLocal(rng.gen_range(*low, *high))] + vec![Instruction::TeeLocal(rng.gen_range(*low..*high))] }, DynInstr::RandomGetGlobal(low, high) => { - vec![Instruction::GetGlobal(rng.gen_range(*low, *high))] + vec![Instruction::GetGlobal(rng.gen_range(*low..*high))] }, DynInstr::RandomSetGlobal(low, high) => { - vec![Instruction::SetGlobal(rng.gen_range(*low, *high))] + vec![Instruction::SetGlobal(rng.gen_range(*low..*high))] }, }) .chain(sp_std::iter::once(Instruction::End)) diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index dc8904f33e0c..61451e10ecf2 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -65,7 +65,7 @@ schnorrkel = { version = "0.9.1", features = [ sha2 = { version = "0.9.8", default-features = false, optional = true } hex = { version = "0.4", default-features = false, optional = true } twox-hash = { version = "1.6.1", default-features = false, optional = true } -libsecp256k1 = { version = "0.6", default-features = false, features = ["hmac", "static-context"], optional = true } +libsecp256k1 = { version = "0.7", default-features = false, features = ["hmac", "static-context"], optional = true } sp-core-hashing = { version = "4.0.0-dev", path = "./hashing", default-features = false, optional = true } merlin = { version = "2.0", default-features = false, optional = true } ss58-registry = { version = "1.5.0", default-features = false } diff --git a/primitives/io/Cargo.toml b/primitives/io/Cargo.toml index 2d7c50bdc25e..2e0982a6e5f1 100644 --- a/primitives/io/Cargo.toml +++ b/primitives/io/Cargo.toml @@ -20,7 +20,7 @@ hash-db = { version = "0.15.2", default-features = false } sp-core = { version = "4.0.0-dev", default-features = false, path = "../core" } sp-keystore = { version = "0.10.0-dev", default-features = false, optional = true, path = "../keystore" } sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" } -libsecp256k1 = { version = "0.6", optional = true } +libsecp256k1 = { version = "0.7", optional = true } sp-state-machine = { version = "0.10.0-dev", optional = true, path = "../state-machine" } sp-wasm-interface = { version = "4.0.0-dev", path = "../wasm-interface", default-features = false } sp-runtime-interface = { version = "4.0.0-dev", default-features = false, path = "../runtime-interface" } From cdcf872c3791d148dc67b4df2dff168c9008ca76 Mon Sep 17 00:00:00 2001 From: Zeke Mostov Date: Fri, 19 Nov 2021 16:14:21 +0100 Subject: [PATCH 209/695] Add prometheus metrics for block authorship (#10316) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add prom metric to basic authorship * Add proposer_block_proposal_time * +nightly-2021-10-29 fmt * Use saturating_duration_since, not elasped * Update client/basic-authorship/src/basic_authorship.rs Co-authored-by: Bastian Köcher * Update client/basic-authorship/src/basic_authorship.rs Co-authored-by: Bastian Köcher * +nightly-2021-10-29 fmt Co-authored-by: Bastian Köcher --- .../basic-authorship/src/basic_authorship.rs | 23 ++++++++++++++++++- client/proposer-metrics/src/lib.rs | 16 +++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/client/basic-authorship/src/basic_authorship.rs b/client/basic-authorship/src/basic_authorship.rs index 0fd3932807a1..70633925c5ba 100644 --- a/client/basic-authorship/src/basic_authorship.rs +++ b/client/basic-authorship/src/basic_authorship.rs @@ -346,10 +346,23 @@ where block_size_limit: Option, ) -> Result, PR::Proof>, sp_blockchain::Error> { + let propose_with_start = time::Instant::now(); let mut block_builder = self.client.new_block_at(&self.parent_id, inherent_digests, PR::ENABLED)?; - for inherent in block_builder.create_inherents(inherent_data)? { + let create_inherents_start = time::Instant::now(); + let inherents = block_builder.create_inherents(inherent_data)?; + let create_inherents_end = time::Instant::now(); + + self.metrics.report(|metrics| { + metrics.create_inherents_time.observe( + create_inherents_end + .saturating_duration_since(create_inherents_start) + .as_secs_f64(), + ); + }); + + for inherent in inherents { match block_builder.push(inherent) { Err(ApplyExtrinsicFailed(Validity(e))) if e.exhausted_resources() => { warn!("⚠️ Dropping non-mandatory inherent from overweight block.") @@ -529,6 +542,14 @@ where let proof = PR::into_proof(proof).map_err(|e| sp_blockchain::Error::Application(Box::new(e)))?; + + let propose_with_end = time::Instant::now(); + self.metrics.report(|metrics| { + metrics.create_block_proposal_time.observe( + propose_with_end.saturating_duration_since(propose_with_start).as_secs_f64(), + ); + }); + Ok(Proposal { block, proof, storage_changes }) } } diff --git a/client/proposer-metrics/src/lib.rs b/client/proposer-metrics/src/lib.rs index da29fb295199..452a796b7392 100644 --- a/client/proposer-metrics/src/lib.rs +++ b/client/proposer-metrics/src/lib.rs @@ -47,6 +47,8 @@ impl MetricsLink { pub struct Metrics { pub block_constructed: Histogram, pub number_of_transactions: Gauge, + pub create_inherents_time: Histogram, + pub create_block_proposal_time: Histogram, } impl Metrics { @@ -66,6 +68,20 @@ impl Metrics { )?, registry, )?, + create_inherents_time: register( + Histogram::with_opts(HistogramOpts::new( + "proposer_create_inherents_time", + "Histogram of time taken to execute create inherents", + ))?, + registry, + )?, + create_block_proposal_time: register( + Histogram::with_opts(HistogramOpts::new( + "proposer_block_proposal_time", + "Histogram of time taken to construct a block and prepare it for proposal", + ))?, + registry, + )?, }) } } From 3cf5449fd2143d07ff2ee24eb3b3c40ecf1e57ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Fri, 19 Nov 2021 21:30:37 +0100 Subject: [PATCH 210/695] Taskmanager: Remove `clean_shutdown` (#10314) There is no reason for this function, tokio already blocks automatically until all tasks are ended. Another reason to remove this feature is `mpsc_background_tasks` unbounded channel. Recently this channel was reporting too many unprocessed elements. We assume that this was a result of a lot of very shot lived tasks that somehow flooded this channel. --- client/cli/src/runner.rs | 3 +- client/service/src/task_manager/mod.rs | 83 +----- client/service/src/task_manager/tests.rs | 316 +++++++++-------------- test-utils/test-runner/src/node.rs | 2 - 4 files changed, 140 insertions(+), 264 deletions(-) diff --git a/client/cli/src/runner.rs b/client/cli/src/runner.rs index 6f03e02a12d0..640b87584d4b 100644 --- a/client/cli/src/runner.rs +++ b/client/cli/src/runner.rs @@ -98,7 +98,7 @@ where pin_mut!(f); tokio_runtime.block_on(main(f))?; - tokio_runtime.block_on(task_manager.clean_shutdown()); + drop(task_manager); Ok(()) } @@ -154,7 +154,6 @@ impl Runner { self.print_node_infos(); let mut task_manager = self.tokio_runtime.block_on(initialize(self.config))?; let res = self.tokio_runtime.block_on(main(task_manager.future().fuse())); - self.tokio_runtime.block_on(task_manager.clean_shutdown()); Ok(res?) } diff --git a/client/service/src/task_manager/mod.rs b/client/service/src/task_manager/mod.rs index 25d3ecd7d5c3..342ea6627be6 100644 --- a/client/service/src/task_manager/mod.rs +++ b/client/service/src/task_manager/mod.rs @@ -21,17 +21,16 @@ use crate::{config::TaskType, Error}; use exit_future::Signal; use futures::{ - future::{join_all, pending, select, try_join_all, BoxFuture, Either}, + future::{pending, select, try_join_all, BoxFuture, Either}, Future, FutureExt, StreamExt, }; -use log::debug; use prometheus_endpoint::{ exponential_buckets, register, CounterVec, HistogramOpts, HistogramVec, Opts, PrometheusError, Registry, U64, }; use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender}; use std::{panic, pin::Pin, result::Result}; -use tokio::{runtime::Handle, task::JoinHandle}; +use tokio::runtime::Handle; use tracing_futures::Instrument; mod prometheus_future; @@ -73,7 +72,6 @@ pub struct SpawnTaskHandle { on_exit: exit_future::Exit, tokio_handle: Handle, metrics: Option, - task_notifier: TracingUnboundedSender>, } impl SpawnTaskHandle { @@ -113,11 +111,6 @@ impl SpawnTaskHandle { task: impl Future + Send + 'static, task_type: TaskType, ) { - if self.task_notifier.is_closed() { - debug!("Attempt to spawn a new task has been prevented: {}", name); - return - } - let on_exit = self.on_exit.clone(); let metrics = self.metrics.clone(); @@ -169,17 +162,17 @@ impl SpawnTaskHandle { } .in_current_span(); - let join_handle = match task_type { - TaskType::Async => self.tokio_handle.spawn(future), + match task_type { + TaskType::Async => { + self.tokio_handle.spawn(future); + }, TaskType::Blocking => { let handle = self.tokio_handle.clone(); self.tokio_handle.spawn_blocking(move || { handle.block_on(future); - }) + }); }, - }; - - let _ = self.task_notifier.unbounded_send(join_handle); + } } } @@ -288,8 +281,8 @@ pub struct TaskManager { /// A future that resolves when the service has exited, this is useful to /// make sure any internally spawned futures stop when the service does. on_exit: exit_future::Exit, - /// A signal that makes the exit future above resolve, fired on service drop. - signal: Option, + /// A signal that makes the exit future above resolve, fired on drop. + _signal: Signal, /// Tokio runtime handle that is used to spawn futures. tokio_handle: Handle, /// Prometheus metric where to report the polling times. @@ -301,10 +294,6 @@ pub struct TaskManager { essential_failed_rx: TracingUnboundedReceiver<()>, /// Things to keep alive until the task manager is dropped. keep_alive: Box, - /// A sender to a stream of background tasks. This is used for the completion future. - task_notifier: TracingUnboundedSender>, - /// This future will complete when all the tasks are joined and the stream is closed. - completion_future: JoinHandle<()>, /// A list of other `TaskManager`'s to terminate and gracefully shutdown when the parent /// terminates and gracefully shutdown. Also ends the parent `future()` if a child's essential /// task fails. @@ -325,25 +314,14 @@ impl TaskManager { let metrics = prometheus_registry.map(Metrics::register).transpose()?; - let (task_notifier, background_tasks) = tracing_unbounded("mpsc_background_tasks"); - // NOTE: for_each_concurrent will await on all the JoinHandle futures at the same time. It - // is possible to limit this but it's actually better for the memory foot print to await - // them all to not accumulate anything on that stream. - let completion_future = - tokio_handle.spawn(background_tasks.for_each_concurrent(None, |x| async move { - let _ = x.await; - })); - Ok(Self { on_exit, - signal: Some(signal), + _signal: signal, tokio_handle, metrics, essential_failed_tx, essential_failed_rx, keep_alive: Box::new(()), - task_notifier, - completion_future, children: Vec::new(), }) } @@ -354,7 +332,6 @@ impl TaskManager { on_exit: self.on_exit.clone(), tokio_handle: self.tokio_handle.clone(), metrics: self.metrics.clone(), - task_notifier: self.task_notifier.clone(), } } @@ -363,36 +340,12 @@ impl TaskManager { SpawnEssentialTaskHandle::new(self.essential_failed_tx.clone(), self.spawn_handle()) } - /// Send the signal for termination, prevent new tasks to be created, await for all the existing - /// tasks to be finished and drop the object. You can consider this as an async drop. - /// - /// It's always better to call and await this function before exiting the process as background - /// tasks may be running in the background. If the process exit and the background tasks are not - /// cancelled, this will lead to objects not getting dropped properly. - /// - /// This is an issue in some cases as some of our dependencies do require that we drop all the - /// objects properly otherwise it triggers a SIGABRT on exit. - pub fn clean_shutdown(mut self) -> Pin + Send>> { - self.terminate(); - let children_shutdowns = self.children.into_iter().map(|x| x.clean_shutdown()); - let keep_alive = self.keep_alive; - let completion_future = self.completion_future; - - Box::pin(async move { - join_all(children_shutdowns).await; - let _ = completion_future.await; - - let _ = keep_alive; - }) - } - /// Return a future that will end with success if the signal to terminate was sent /// (`self.terminate()`) or with an error if an essential task fails. /// /// # Warning /// - /// This function will not wait until the end of the remaining task. You must call and await - /// `clean_shutdown()` after this. + /// This function will not wait until the end of the remaining task. pub fn future<'a>( &'a mut self, ) -> Pin> + Send + 'a>> { @@ -417,18 +370,6 @@ impl TaskManager { }) } - /// Signal to terminate all the running tasks. - pub fn terminate(&mut self) { - if let Some(signal) = self.signal.take() { - let _ = signal.fire(); - // NOTE: this will prevent new tasks to be spawned - self.task_notifier.close_channel(); - for child in self.children.iter_mut() { - child.terminate(); - } - } - } - /// Set what the task manager should keep alive, can be called multiple times. pub fn keep_alive(&mut self, to_keep_alive: T) { // allows this fn to safely called multiple times. diff --git a/client/service/src/task_manager/tests.rs b/client/service/src/task_manager/tests.rs index 75092ff2ae62..f14023f34f6b 100644 --- a/client/service/src/task_manager/tests.rs +++ b/client/service/src/task_manager/tests.rs @@ -90,225 +90,163 @@ fn new_task_manager(tokio_handle: tokio::runtime::Handle) -> TaskManager { #[test] fn ensure_tasks_are_awaited_on_shutdown() { - let runtime = tokio::runtime::Runtime::new().unwrap(); - let handle = runtime.handle().clone(); - - let task_manager = new_task_manager(handle); - let spawn_handle = task_manager.spawn_handle(); let drop_tester = DropTester::new(); - spawn_handle.spawn("task1", None, run_background_task(drop_tester.new_ref())); - spawn_handle.spawn("task2", None, run_background_task(drop_tester.new_ref())); - assert_eq!(drop_tester, 2); - // allow the tasks to even start - runtime.block_on(async { tokio::time::sleep(Duration::from_secs(1)).await }); - assert_eq!(drop_tester, 2); - runtime.block_on(task_manager.clean_shutdown()); + { + let runtime = tokio::runtime::Runtime::new().unwrap(); + let handle = runtime.handle().clone(); + + let task_manager = new_task_manager(handle); + let spawn_handle = task_manager.spawn_handle(); + spawn_handle.spawn("task1", None, run_background_task(drop_tester.new_ref())); + spawn_handle.spawn("task2", None, run_background_task(drop_tester.new_ref())); + assert_eq!(drop_tester, 2); + // allow the tasks to even start + runtime.block_on(async { tokio::time::sleep(Duration::from_secs(1)).await }); + assert_eq!(drop_tester, 2); + } drop_tester.wait_on_drop(); } #[test] fn ensure_keep_alive_during_shutdown() { - let runtime = tokio::runtime::Runtime::new().unwrap(); - let handle = runtime.handle().clone(); - - let mut task_manager = new_task_manager(handle); - let spawn_handle = task_manager.spawn_handle(); let drop_tester = DropTester::new(); - task_manager.keep_alive(drop_tester.new_ref()); - spawn_handle.spawn("task1", None, run_background_task(())); - assert_eq!(drop_tester, 1); - // allow the tasks to even start - runtime.block_on(async { tokio::time::sleep(Duration::from_secs(1)).await }); - assert_eq!(drop_tester, 1); - runtime.block_on(task_manager.clean_shutdown()); + { + let runtime = tokio::runtime::Runtime::new().unwrap(); + let handle = runtime.handle().clone(); + + let mut task_manager = new_task_manager(handle); + let spawn_handle = task_manager.spawn_handle(); + task_manager.keep_alive(drop_tester.new_ref()); + spawn_handle.spawn("task1", None, run_background_task(())); + assert_eq!(drop_tester, 1); + // allow the tasks to even start + runtime.block_on(async { tokio::time::sleep(Duration::from_secs(1)).await }); + assert_eq!(drop_tester, 1); + } drop_tester.wait_on_drop(); } #[test] fn ensure_blocking_futures_are_awaited_on_shutdown() { - let runtime = tokio::runtime::Runtime::new().unwrap(); - let handle = runtime.handle().clone(); - - let task_manager = new_task_manager(handle); - let spawn_handle = task_manager.spawn_handle(); - let drop_tester = DropTester::new(); - spawn_handle.spawn( - "task1", - None, - run_background_task_blocking(Duration::from_secs(3), drop_tester.new_ref()), - ); - spawn_handle.spawn( - "task2", - None, - run_background_task_blocking(Duration::from_secs(3), drop_tester.new_ref()), - ); - assert_eq!(drop_tester, 2); - // allow the tasks to even start - runtime.block_on(async { tokio::time::sleep(Duration::from_secs(1)).await }); - assert_eq!(drop_tester, 2); - runtime.block_on(task_manager.clean_shutdown()); - assert_eq!(drop_tester, 0); -} - -#[test] -fn ensure_no_task_can_be_spawn_after_terminate() { - let runtime = tokio::runtime::Runtime::new().unwrap(); - let handle = runtime.handle().clone(); - - let mut task_manager = new_task_manager(handle); - let spawn_handle = task_manager.spawn_handle(); - let drop_tester = DropTester::new(); - spawn_handle.spawn("task1", None, run_background_task(drop_tester.new_ref())); - spawn_handle.spawn("task2", None, run_background_task(drop_tester.new_ref())); - assert_eq!(drop_tester, 2); - // allow the tasks to even start - runtime.block_on(async { tokio::time::sleep(Duration::from_secs(1)).await }); - assert_eq!(drop_tester, 2); - task_manager.terminate(); - spawn_handle.spawn("task3", None, run_background_task(drop_tester.new_ref())); - runtime.block_on(task_manager.clean_shutdown()); - drop_tester.wait_on_drop(); -} - -#[test] -fn ensure_task_manager_future_ends_when_task_manager_terminated() { - let runtime = tokio::runtime::Runtime::new().unwrap(); - let handle = runtime.handle().clone(); - - let mut task_manager = new_task_manager(handle); - let spawn_handle = task_manager.spawn_handle(); let drop_tester = DropTester::new(); - spawn_handle.spawn("task1", None, run_background_task(drop_tester.new_ref())); - spawn_handle.spawn("task2", None, run_background_task(drop_tester.new_ref())); - assert_eq!(drop_tester, 2); - // allow the tasks to even start - runtime.block_on(async { tokio::time::sleep(Duration::from_secs(1)).await }); - assert_eq!(drop_tester, 2); - task_manager.terminate(); - runtime.block_on(task_manager.future()).expect("future has ended without error"); - runtime.block_on(task_manager.clean_shutdown()); + { + let runtime = tokio::runtime::Runtime::new().unwrap(); + let handle = runtime.handle().clone(); + + let task_manager = new_task_manager(handle); + let spawn_handle = task_manager.spawn_handle(); + spawn_handle.spawn( + "task1", + None, + run_background_task_blocking(Duration::from_secs(3), drop_tester.new_ref()), + ); + spawn_handle.spawn( + "task2", + None, + run_background_task_blocking(Duration::from_secs(3), drop_tester.new_ref()), + ); + assert_eq!(drop_tester, 2); + // allow the tasks to even start + runtime.block_on(async { tokio::time::sleep(Duration::from_secs(1)).await }); + assert_eq!(drop_tester, 2); + } assert_eq!(drop_tester, 0); } #[test] fn ensure_task_manager_future_ends_with_error_when_essential_task_fails() { - let runtime = tokio::runtime::Runtime::new().unwrap(); - let handle = runtime.handle().clone(); - - let mut task_manager = new_task_manager(handle); - let spawn_handle = task_manager.spawn_handle(); - let spawn_essential_handle = task_manager.spawn_essential_handle(); let drop_tester = DropTester::new(); - spawn_handle.spawn("task1", None, run_background_task(drop_tester.new_ref())); - spawn_handle.spawn("task2", None, run_background_task(drop_tester.new_ref())); - assert_eq!(drop_tester, 2); - // allow the tasks to even start - runtime.block_on(async { tokio::time::sleep(Duration::from_secs(1)).await }); - assert_eq!(drop_tester, 2); - spawn_essential_handle.spawn("task3", None, async { panic!("task failed") }); - runtime - .block_on(task_manager.future()) - .expect_err("future()'s Result must be Err"); - assert_eq!(drop_tester, 2); - runtime.block_on(task_manager.clean_shutdown()); - drop_tester.wait_on_drop(); -} - -#[test] -fn ensure_children_tasks_ends_when_task_manager_terminated() { - let runtime = tokio::runtime::Runtime::new().unwrap(); - let handle = runtime.handle().clone(); - - let mut task_manager = new_task_manager(handle.clone()); - let child_1 = new_task_manager(handle.clone()); - let spawn_handle_child_1 = child_1.spawn_handle(); - let child_2 = new_task_manager(handle.clone()); - let spawn_handle_child_2 = child_2.spawn_handle(); - task_manager.add_child(child_1); - task_manager.add_child(child_2); - let spawn_handle = task_manager.spawn_handle(); - let drop_tester = DropTester::new(); - spawn_handle.spawn("task1", None, run_background_task(drop_tester.new_ref())); - spawn_handle.spawn("task2", None, run_background_task(drop_tester.new_ref())); - spawn_handle_child_1.spawn("task3", None, run_background_task(drop_tester.new_ref())); - spawn_handle_child_2.spawn("task4", None, run_background_task(drop_tester.new_ref())); - assert_eq!(drop_tester, 4); - // allow the tasks to even start - runtime.block_on(async { tokio::time::sleep(Duration::from_secs(1)).await }); - assert_eq!(drop_tester, 4); - task_manager.terminate(); - runtime.block_on(task_manager.future()).expect("future has ended without error"); - runtime.block_on(task_manager.clean_shutdown()); + { + let runtime = tokio::runtime::Runtime::new().unwrap(); + let handle = runtime.handle().clone(); + + let mut task_manager = new_task_manager(handle); + let spawn_handle = task_manager.spawn_handle(); + let spawn_essential_handle = task_manager.spawn_essential_handle(); + spawn_handle.spawn("task1", None, run_background_task(drop_tester.new_ref())); + spawn_handle.spawn("task2", None, run_background_task(drop_tester.new_ref())); + assert_eq!(drop_tester, 2); + // allow the tasks to even start + runtime.block_on(async { tokio::time::sleep(Duration::from_secs(1)).await }); + assert_eq!(drop_tester, 2); + spawn_essential_handle.spawn("task3", None, async { panic!("task failed") }); + runtime + .block_on(task_manager.future()) + .expect_err("future()'s Result must be Err"); + assert_eq!(drop_tester, 2); + } drop_tester.wait_on_drop(); } #[test] fn ensure_task_manager_future_ends_with_error_when_childs_essential_task_fails() { - let runtime = tokio::runtime::Runtime::new().unwrap(); - let handle = runtime.handle().clone(); - - let mut task_manager = new_task_manager(handle.clone()); - let child_1 = new_task_manager(handle.clone()); - let spawn_handle_child_1 = child_1.spawn_handle(); - let spawn_essential_handle_child_1 = child_1.spawn_essential_handle(); - let child_2 = new_task_manager(handle.clone()); - let spawn_handle_child_2 = child_2.spawn_handle(); - task_manager.add_child(child_1); - task_manager.add_child(child_2); - let spawn_handle = task_manager.spawn_handle(); let drop_tester = DropTester::new(); - spawn_handle.spawn("task1", None, run_background_task(drop_tester.new_ref())); - spawn_handle.spawn("task2", None, run_background_task(drop_tester.new_ref())); - spawn_handle_child_1.spawn("task3", None, run_background_task(drop_tester.new_ref())); - spawn_handle_child_2.spawn("task4", None, run_background_task(drop_tester.new_ref())); - assert_eq!(drop_tester, 4); - // allow the tasks to even start - runtime.block_on(async { tokio::time::sleep(Duration::from_secs(1)).await }); - assert_eq!(drop_tester, 4); - spawn_essential_handle_child_1.spawn("task5", None, async { panic!("task failed") }); - runtime - .block_on(task_manager.future()) - .expect_err("future()'s Result must be Err"); - assert_eq!(drop_tester, 4); - runtime.block_on(task_manager.clean_shutdown()); + { + let runtime = tokio::runtime::Runtime::new().unwrap(); + let handle = runtime.handle().clone(); + + let mut task_manager = new_task_manager(handle.clone()); + let child_1 = new_task_manager(handle.clone()); + let spawn_handle_child_1 = child_1.spawn_handle(); + let spawn_essential_handle_child_1 = child_1.spawn_essential_handle(); + let child_2 = new_task_manager(handle.clone()); + let spawn_handle_child_2 = child_2.spawn_handle(); + task_manager.add_child(child_1); + task_manager.add_child(child_2); + let spawn_handle = task_manager.spawn_handle(); + spawn_handle.spawn("task1", None, run_background_task(drop_tester.new_ref())); + spawn_handle.spawn("task2", None, run_background_task(drop_tester.new_ref())); + spawn_handle_child_1.spawn("task3", None, run_background_task(drop_tester.new_ref())); + spawn_handle_child_2.spawn("task4", None, run_background_task(drop_tester.new_ref())); + assert_eq!(drop_tester, 4); + // allow the tasks to even start + runtime.block_on(async { tokio::time::sleep(Duration::from_secs(1)).await }); + assert_eq!(drop_tester, 4); + spawn_essential_handle_child_1.spawn("task5", None, async { panic!("task failed") }); + runtime + .block_on(task_manager.future()) + .expect_err("future()'s Result must be Err"); + assert_eq!(drop_tester, 4); + } drop_tester.wait_on_drop(); } #[test] fn ensure_task_manager_future_continues_when_childs_not_essential_task_fails() { - let runtime = tokio::runtime::Runtime::new().unwrap(); - let handle = runtime.handle().clone(); - - let mut task_manager = new_task_manager(handle.clone()); - let child_1 = new_task_manager(handle.clone()); - let spawn_handle_child_1 = child_1.spawn_handle(); - let child_2 = new_task_manager(handle.clone()); - let spawn_handle_child_2 = child_2.spawn_handle(); - task_manager.add_child(child_1); - task_manager.add_child(child_2); - let spawn_handle = task_manager.spawn_handle(); let drop_tester = DropTester::new(); - spawn_handle.spawn("task1", None, run_background_task(drop_tester.new_ref())); - spawn_handle.spawn("task2", None, run_background_task(drop_tester.new_ref())); - spawn_handle_child_1.spawn("task3", None, run_background_task(drop_tester.new_ref())); - spawn_handle_child_2.spawn("task4", None, run_background_task(drop_tester.new_ref())); - assert_eq!(drop_tester, 4); - // allow the tasks to even start - runtime.block_on(async { tokio::time::sleep(Duration::from_secs(1)).await }); - assert_eq!(drop_tester, 4); - spawn_handle_child_1.spawn("task5", None, async { panic!("task failed") }); - runtime.block_on(async { - let t1 = task_manager.future().fuse(); - let t2 = tokio::time::sleep(Duration::from_secs(3)).fuse(); - - pin_mut!(t1, t2); - - select! { - res = t1 => panic!("task should not have stopped: {:?}", res), - _ = t2 => {}, - } - }); - assert_eq!(drop_tester, 4); - runtime.block_on(task_manager.clean_shutdown()); + { + let runtime = tokio::runtime::Runtime::new().unwrap(); + let handle = runtime.handle().clone(); + + let mut task_manager = new_task_manager(handle.clone()); + let child_1 = new_task_manager(handle.clone()); + let spawn_handle_child_1 = child_1.spawn_handle(); + let child_2 = new_task_manager(handle.clone()); + let spawn_handle_child_2 = child_2.spawn_handle(); + task_manager.add_child(child_1); + task_manager.add_child(child_2); + let spawn_handle = task_manager.spawn_handle(); + spawn_handle.spawn("task1", None, run_background_task(drop_tester.new_ref())); + spawn_handle.spawn("task2", None, run_background_task(drop_tester.new_ref())); + spawn_handle_child_1.spawn("task3", None, run_background_task(drop_tester.new_ref())); + spawn_handle_child_2.spawn("task4", None, run_background_task(drop_tester.new_ref())); + assert_eq!(drop_tester, 4); + // allow the tasks to even start + runtime.block_on(async { tokio::time::sleep(Duration::from_secs(1)).await }); + assert_eq!(drop_tester, 4); + spawn_handle_child_1.spawn("task5", None, async { panic!("task failed") }); + runtime.block_on(async { + let t1 = task_manager.future().fuse(); + let t2 = tokio::time::sleep(Duration::from_secs(3)).fuse(); + + pin_mut!(t1, t2); + + select! { + res = t1 => panic!("task should not have stopped: {:?}", res), + _ = t2 => {}, + } + }); + assert_eq!(drop_tester, 4); + } drop_tester.wait_on_drop(); } diff --git a/test-utils/test-runner/src/node.rs b/test-utils/test-runner/src/node.rs index 07259263c5e4..5fd8e4669c33 100644 --- a/test-utils/test-runner/src/node.rs +++ b/test-utils/test-runner/src/node.rs @@ -261,8 +261,6 @@ where let signal = tokio::signal::ctrl_c(); futures::pin_mut!(signal); futures::future::select(task, signal).await; - // we don't really care whichever comes first. - task_manager.clean_shutdown().await } } } From 197b8fd3675104a45ad547b2a424a4c70734cba8 Mon Sep 17 00:00:00 2001 From: Doordashcon <90750465+Doordashcon@users.noreply.github.com> Date: Sat, 20 Nov 2021 09:00:43 +0100 Subject: [PATCH 211/695] tuple to struct event variants (#10257) * AFNPEV recovery * AFNPEV session * cargo +nightly fmt && cargo fmt * removed redundant comments * update * update & cargo +nightly fmt * update & cargo +nightly fmt * update recovery/src/lib.rs * update session/src/lib.rs --- frame/recovery/src/lib.rs | 54 +++++++++++++++++++++++++-------------- frame/session/src/lib.rs | 6 ++--- 2 files changed, 38 insertions(+), 22 deletions(-) diff --git a/frame/recovery/src/lib.rs b/frame/recovery/src/lib.rs index 522d7008017f..24090e9000fa 100644 --- a/frame/recovery/src/lib.rs +++ b/frame/recovery/src/lib.rs @@ -262,22 +262,22 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { - /// A recovery process has been set up for an \[account\]. - RecoveryCreated(T::AccountId), + /// A recovery process has been set up for an account. + RecoveryCreated { account: T::AccountId }, /// A recovery process has been initiated for lost account by rescuer account. - /// \[lost, rescuer\] - RecoveryInitiated(T::AccountId, T::AccountId), + RecoveryInitiated { lost_account: T::AccountId, rescuer_account: T::AccountId }, /// A recovery process for lost account by rescuer account has been vouched for by sender. - /// \[lost, rescuer, sender\] - RecoveryVouched(T::AccountId, T::AccountId, T::AccountId), + RecoveryVouched { + lost_account: T::AccountId, + rescuer_account: T::AccountId, + sender: T::AccountId, + }, /// A recovery process for lost account by rescuer account has been closed. - /// \[lost, rescuer\] - RecoveryClosed(T::AccountId, T::AccountId), + RecoveryClosed { lost_account: T::AccountId, rescuer_account: T::AccountId }, /// Lost account has been successfully recovered by rescuer account. - /// \[lost, rescuer\] - AccountRecovered(T::AccountId, T::AccountId), - /// A recovery process has been removed for an \[account\]. - RecoveryRemoved(T::AccountId), + AccountRecovered { lost_account: T::AccountId, rescuer_account: T::AccountId }, + /// A recovery process has been removed for an account. + RecoveryRemoved { lost_account: T::AccountId }, } #[pallet::error] @@ -409,7 +409,10 @@ pub mod pallet { ensure_root(origin)?; // Create the recovery storage item. >::insert(&rescuer, &lost); - Self::deposit_event(Event::::AccountRecovered(lost, rescuer)); + Self::deposit_event(Event::::AccountRecovered { + lost_account: lost, + rescuer_account: rescuer, + }); Ok(()) } @@ -472,7 +475,7 @@ pub mod pallet { // Create the recovery configuration storage item >::insert(&who, recovery_config); - Self::deposit_event(Event::::RecoveryCreated(who)); + Self::deposit_event(Event::::RecoveryCreated { account: who }); Ok(()) } @@ -519,7 +522,10 @@ pub mod pallet { }; // Create the active recovery storage item >::insert(&account, &who, recovery_status); - Self::deposit_event(Event::::RecoveryInitiated(account, who)); + Self::deposit_event(Event::::RecoveryInitiated { + lost_account: account, + rescuer_account: who, + }); Ok(()) } @@ -568,7 +574,11 @@ pub mod pallet { } // Update storage with the latest details >::insert(&lost, &rescuer, active_recovery); - Self::deposit_event(Event::::RecoveryVouched(lost, rescuer, who)); + Self::deposit_event(Event::::RecoveryVouched { + lost_account: lost, + rescuer_account: rescuer, + sender: who, + }); Ok(()) } @@ -617,7 +627,10 @@ pub mod pallet { frame_system::Pallet::::inc_consumers(&who).map_err(|_| Error::::BadState)?; // Create the recovery storage item Proxy::::insert(&who, &account); - Self::deposit_event(Event::::AccountRecovered(account, who)); + Self::deposit_event(Event::::AccountRecovered { + lost_account: account, + rescuer_account: who, + }); Ok(()) } @@ -656,7 +669,10 @@ pub mod pallet { BalanceStatus::Free, ); debug_assert!(res.is_ok()); - Self::deposit_event(Event::::RecoveryClosed(who, rescuer)); + Self::deposit_event(Event::::RecoveryClosed { + lost_account: who, + rescuer_account: rescuer, + }); Ok(()) } @@ -692,7 +708,7 @@ pub mod pallet { // Unreserve the initial deposit for the recovery configuration. T::Currency::unreserve(&who, recovery_config.deposit); - Self::deposit_event(Event::::RecoveryRemoved(who)); + Self::deposit_event(Event::::RecoveryRemoved { lost_account: who }); Ok(()) } diff --git a/frame/session/src/lib.rs b/frame/session/src/lib.rs index 2fd34365705b..f56d282c0f11 100644 --- a/frame/session/src/lib.rs +++ b/frame/session/src/lib.rs @@ -532,9 +532,9 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { - /// New session has happened. Note that the argument is the \[session_index\], not the + /// New session has happened. Note that the argument is the session index, not the /// block number as the type might suggest. - NewSession(SessionIndex), + NewSession { session_index: SessionIndex }, } /// Old name generated by `decl_event`. @@ -703,7 +703,7 @@ impl Pallet { >::put(next_changed); // Record that this happened. - Self::deposit_event(Event::NewSession(session_index)); + Self::deposit_event(Event::NewSession { session_index }); // Tell everyone about the new session keys. T::SessionHandler::on_new_session::(changed, &session_keys, &queued_amalgamated); From 664ac530640823f55bcb8b7a2a4cc215fd5b11d2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 20 Nov 2021 23:08:49 +0000 Subject: [PATCH 212/695] Bump derive_more from 0.99.11 to 0.99.16 (#10282) Bumps [derive_more](https://github.com/JelteF/derive_more) from 0.99.11 to 0.99.16. - [Release notes](https://github.com/JelteF/derive_more/releases) - [Changelog](https://github.com/JelteF/derive_more/blob/master/CHANGELOG.md) - [Commits](https://github.com/JelteF/derive_more/compare/v0.99.11...v0.99.16) --- updated-dependencies: - dependency-name: derive_more dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 12 ++++++++++-- bin/node/bench/Cargo.toml | 2 +- client/authority-discovery/Cargo.toml | 2 +- client/consensus/aura/Cargo.toml | 2 +- client/consensus/babe/Cargo.toml | 2 +- client/consensus/babe/rpc/Cargo.toml | 2 +- client/consensus/manual-seal/Cargo.toml | 2 +- client/consensus/pow/Cargo.toml | 2 +- client/executor/common/Cargo.toml | 2 +- client/finality-grandpa/Cargo.toml | 2 +- client/keystore/Cargo.toml | 2 +- client/network/Cargo.toml | 2 +- client/transaction-pool/api/Cargo.toml | 2 +- primitives/keystore/Cargo.toml | 2 +- test-utils/runtime/transaction-pool/Cargo.toml | 2 +- 15 files changed, 24 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e9798d4c4205..56eb2a5543c8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -993,6 +993,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + [[package]] name = "core-foundation" version = "0.9.1" @@ -1476,12 +1482,14 @@ dependencies = [ [[package]] name = "derive_more" -version = "0.99.11" +version = "0.99.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cb0e6161ad61ed084a36ba71fbba9e3ac5aee3606fb607fe08da6acbcf3d8c" +checksum = "40eebddd2156ce1bb37b20bbe5151340a31828b1f2d22ba4141f3531710e38df" dependencies = [ + "convert_case", "proc-macro2", "quote", + "rustc_version 0.3.3", "syn", ] diff --git a/bin/node/bench/Cargo.toml b/bin/node/bench/Cargo.toml index 66a14a123ee5..037a233a4ca0 100644 --- a/bin/node/bench/Cargo.toml +++ b/bin/node/bench/Cargo.toml @@ -19,7 +19,7 @@ sp-state-machine = { version = "0.10.0-dev", path = "../../../primitives/state-m serde = "1.0.126" serde_json = "1.0.68" structopt = "0.3" -derive_more = "0.99.2" +derive_more = "0.99.16" kvdb = "0.10.0" kvdb-rocksdb = "0.14.0" sp-trie = { version = "4.0.0-dev", path = "../../../primitives/trie" } diff --git a/client/authority-discovery/Cargo.toml b/client/authority-discovery/Cargo.toml index b1d9d4ebd393..fff1ed08a8c1 100644 --- a/client/authority-discovery/Cargo.toml +++ b/client/authority-discovery/Cargo.toml @@ -19,7 +19,7 @@ prost-build = "0.9" [dependencies] async-trait = "0.1" codec = { package = "parity-scale-codec", default-features = false, version = "2.0.0" } -derive_more = "0.99.2" +derive_more = "0.99.16" futures = "0.3.9" futures-timer = "3.0.1" ip_network = "0.4.0" diff --git a/client/consensus/aura/Cargo.toml b/client/consensus/aura/Cargo.toml index 152c40f78f9d..f4f12a0a601c 100644 --- a/client/consensus/aura/Cargo.toml +++ b/client/consensus/aura/Cargo.toml @@ -22,7 +22,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0" } sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" } sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/common" } sp-consensus-slots = { version = "0.10.0-dev", path = "../../../primitives/consensus/slots" } -derive_more = "0.99.2" +derive_more = "0.99.16" futures = "0.3.9" sp-inherents = { version = "4.0.0-dev", path = "../../../primitives/inherents" } log = "0.4.8" diff --git a/client/consensus/babe/Cargo.toml b/client/consensus/babe/Cargo.toml index 7945ecc4ec79..5020a4a56478 100644 --- a/client/consensus/babe/Cargo.toml +++ b/client/consensus/babe/Cargo.toml @@ -49,7 +49,7 @@ log = "0.4.8" schnorrkel = { version = "0.9.1", features = ["preaudit_deprecated"] } rand = "0.7.2" merlin = "2.0" -derive_more = "0.99.2" +derive_more = "0.99.16" retain_mut = "0.1.4" async-trait = "0.1.50" diff --git a/client/consensus/babe/rpc/Cargo.toml b/client/consensus/babe/rpc/Cargo.toml index bc57092d3400..3a7cf86a800c 100644 --- a/client/consensus/babe/rpc/Cargo.toml +++ b/client/consensus/babe/rpc/Cargo.toml @@ -24,7 +24,7 @@ sp-blockchain = { version = "4.0.0-dev", path = "../../../../primitives/blockcha sp-runtime = { version = "4.0.0-dev", path = "../../../../primitives/runtime" } sc-consensus-epochs = { version = "0.10.0-dev", path = "../../epochs" } futures = "0.3.16" -derive_more = "0.99.2" +derive_more = "0.99.16" sp-api = { version = "4.0.0-dev", path = "../../../../primitives/api" } sp-consensus = { version = "0.10.0-dev", path = "../../../../primitives/consensus/common" } sp-core = { version = "4.0.0-dev", path = "../../../../primitives/core" } diff --git a/client/consensus/manual-seal/Cargo.toml b/client/consensus/manual-seal/Cargo.toml index 90edc15863cd..48ba91065544 100644 --- a/client/consensus/manual-seal/Cargo.toml +++ b/client/consensus/manual-seal/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -derive_more = "0.99.2" +derive_more = "0.99.16" futures = "0.3.9" jsonrpc-core = "18.0.0" jsonrpc-core-client = "18.0.0" diff --git a/client/consensus/pow/Cargo.toml b/client/consensus/pow/Cargo.toml index 841631fce7cc..25e39641ae43 100644 --- a/client/consensus/pow/Cargo.toml +++ b/client/consensus/pow/Cargo.toml @@ -28,6 +28,6 @@ log = "0.4.8" futures = "0.3.16" futures-timer = "3.0.1" parking_lot = "0.11.1" -derive_more = "0.99.2" +derive_more = "0.99.16" prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.10.0-dev"} async-trait = "0.1.50" diff --git a/client/executor/common/Cargo.toml b/client/executor/common/Cargo.toml index 1bb057fabad8..3d2cec9ac60c 100644 --- a/client/executor/common/Cargo.toml +++ b/client/executor/common/Cargo.toml @@ -14,7 +14,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -derive_more = "0.99.2" +derive_more = "0.99.16" pwasm-utils = "0.18.2" codec = { package = "parity-scale-codec", version = "2.0.0" } wasmi = "0.9.1" diff --git a/client/finality-grandpa/Cargo.toml b/client/finality-grandpa/Cargo.toml index ec4bac715ad4..1dd8c2518ab7 100644 --- a/client/finality-grandpa/Cargo.toml +++ b/client/finality-grandpa/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] -derive_more = "0.99.2" +derive_more = "0.99.16" dyn-clone = "1.0" fork-tree = { version = "3.0.0", path = "../../utils/fork-tree" } futures = "0.3.9" diff --git a/client/keystore/Cargo.toml b/client/keystore/Cargo.toml index bd158091e747..9e2928d41e89 100644 --- a/client/keystore/Cargo.toml +++ b/client/keystore/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] async-trait = "0.1.50" -derive_more = "0.99.2" +derive_more = "0.99.16" sp-application-crypto = { version = "4.0.0-dev", path = "../../primitives/application-crypto" } sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } sp-keystore = { version = "0.10.0-dev", path = "../../primitives/keystore" } diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index eb91dd145e54..13eb408b0bb5 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -25,7 +25,7 @@ bytes = "1" codec = { package = "parity-scale-codec", version = "2.0.0", features = [ "derive", ] } -derive_more = "0.99.2" +derive_more = "0.99.16" either = "1.5.3" fnv = "1.0.6" fork-tree = { version = "3.0.0", path = "../../utils/fork-tree" } diff --git a/client/transaction-pool/api/Cargo.toml b/client/transaction-pool/api/Cargo.toml index 1ab1ef5bb4a1..f44ec588e954 100644 --- a/client/transaction-pool/api/Cargo.toml +++ b/client/transaction-pool/api/Cargo.toml @@ -15,5 +15,5 @@ serde = { version = "1.0.126", features = ["derive"] } thiserror = { version = "1.0.30" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } -derive_more = { version = "0.99.11" } +derive_more = { version = "0.99.16" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } diff --git a/primitives/keystore/Cargo.toml b/primitives/keystore/Cargo.toml index e16ff4676c3b..ab026ccedd51 100644 --- a/primitives/keystore/Cargo.toml +++ b/primitives/keystore/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] async-trait = "0.1.50" -derive_more = "0.99.2" +derive_more = "0.99.16" codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } futures = { version = "0.3.1" } schnorrkel = { version = "0.9.1", features = ["preaudit_deprecated", "u64_backend"], default-features = false } diff --git a/test-utils/runtime/transaction-pool/Cargo.toml b/test-utils/runtime/transaction-pool/Cargo.toml index 402caa93d10d..ee1ac4814db5 100644 --- a/test-utils/runtime/transaction-pool/Cargo.toml +++ b/test-utils/runtime/transaction-pool/Cargo.toml @@ -20,4 +20,4 @@ sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } sc-transaction-pool = { version = "4.0.0-dev", path = "../../../client/transaction-pool", features = ["test-helpers"] } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../../../client/transaction-pool/api" } futures = "0.3.16" -derive_more = "0.99.2" +derive_more = "0.99.16" From 541a72f9eb41678e4601593735655a5cf794bd4a Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Sun, 21 Nov 2021 14:42:21 +0100 Subject: [PATCH 213/695] use proper intra doc link (#10271) * use proper intra doc link * use proper intra doc link * get system path name from path module name function for the docs * used format macro in formatting doc string for better output * helper function to get intra doc string * helper function to get intra doc string * use helper function on expand_origin_pallet_conversions * remove duplicates * Update frame/support/procedural/src/construct_runtime/expand/origin.rs Co-authored-by: Guillaume Thiolliere * remove leading white space Co-authored-by: Damilare Co-authored-by: Guillaume Thiolliere --- .../src/construct_runtime/expand/origin.rs | 53 +++++++++++++++---- 1 file changed, 44 insertions(+), 9 deletions(-) diff --git a/frame/support/procedural/src/construct_runtime/expand/origin.rs b/frame/support/procedural/src/construct_runtime/expand/origin.rs index eb0212c3efee..5c2b4c9f93b0 100644 --- a/frame/support/procedural/src/construct_runtime/expand/origin.rs +++ b/frame/support/procedural/src/construct_runtime/expand/origin.rs @@ -68,14 +68,39 @@ pub fn expand_outer_origin( } let system_path = &system_pallet.path; + let system_index = system_pallet.index; + let system_path_name = system_path.module_name(); + + let doc_string = get_intra_doc_string( + "Origin is always created with the base filter configured in", + &system_path_name, + ); + + let doc_string_none_origin = + get_intra_doc_string("Create with system none origin and", &system_path_name); + + let doc_string_root_origin = + get_intra_doc_string("Create with system root origin and", &system_path_name); + + let doc_string_signed_origin = + get_intra_doc_string("Create with system signed origin and", &system_path_name); + + let doc_string_runtime_origin = + get_intra_doc_string("Convert to runtime origin, using as filter:", &system_path_name); + + let doc_string_runtime_origin_with_caller = get_intra_doc_string( + "Convert to runtime origin with caller being system signed or none and use filter", + &system_path_name, + ); + Ok(quote! { #( #query_origin_part_macros )* - /// The runtime origin type represanting the origin of a call. + /// The runtime origin type representing the origin of a call. /// - /// Origin is always created with the base filter configured in `frame_system::Config::BaseCallFilter`. + #[doc = #doc_string] #[derive(Clone)] pub struct Origin { caller: OriginCaller, @@ -182,15 +207,18 @@ pub fn expand_outer_origin( // For backwards compatibility and ease of accessing these functions. #[allow(dead_code)] impl Origin { - /// Create with system none origin and `frame-system::Config::BaseCallFilter`. + + #[doc = #doc_string_none_origin] pub fn none() -> Self { ::none() } - /// Create with system root origin and `frame-system::Config::BaseCallFilter`. + + #[doc = #doc_string_root_origin] pub fn root() -> Self { ::root() } - /// Create with system signed origin and `frame-system::Config::BaseCallFilter`. + + #[doc = #doc_string_signed_origin] pub fn signed(by: <#runtime as #system_path::Config>::AccountId) -> Self { ::signed(by) } @@ -216,7 +244,8 @@ pub fn expand_outer_origin( } impl From<#system_path::Origin<#runtime>> for Origin { - /// Convert to runtime origin, using as filter: `frame-system::Config::BaseCallFilter`. + + #[doc = #doc_string_runtime_origin] fn from(x: #system_path::Origin<#runtime>) -> Self { let o: OriginCaller = x.into(); o.into() @@ -247,8 +276,7 @@ pub fn expand_outer_origin( } } impl From::AccountId>> for Origin { - /// Convert to runtime origin with caller being system signed or none and use filter - /// `frame-system::Config::BaseCallFilter`. + #[doc = #doc_string_runtime_origin_with_caller] fn from(x: Option<<#runtime as #system_path::Config>::AccountId>) -> Self { <#system_path::Origin<#runtime>>::from(x).into() } @@ -303,6 +331,8 @@ fn expand_origin_pallet_conversions( None => quote!(#path::Origin), }; + let doc_string = get_intra_doc_string(" Convert to runtime origin using", &path.module_name()); + quote! { impl From<#pallet_origin> for OriginCaller { fn from(x: #pallet_origin) -> Self { @@ -311,7 +341,7 @@ fn expand_origin_pallet_conversions( } impl From<#pallet_origin> for Origin { - /// Convert to runtime origin using `frame-system::Config::BaseCallFilter`. + #[doc = #doc_string] fn from(x: #pallet_origin) -> Self { let x: OriginCaller = x.into(); x.into() @@ -343,3 +373,8 @@ fn expand_origin_pallet_conversions( } } } + +// Get the actual documentation using the doc information and system path name +fn get_intra_doc_string(doc_info: &str, system_path_name: &String) -> String { + format!(" {} [`{}::Config::BaseCallFilter`].", doc_info, system_path_name) +} From 35fcfd66d380c8336030810030d8f09171b51734 Mon Sep 17 00:00:00 2001 From: Guillaume Thiolliere Date: Mon, 22 Nov 2021 19:48:53 +0900 Subject: [PATCH 214/695] Fix some doc link (#10329) * fix some doc link * fmt --- client/consensus/pow/src/lib.rs | 4 ++-- client/executor/wasmtime/src/runtime.rs | 8 ++++---- client/telemetry/src/lib.rs | 2 +- frame/bags-list/src/lib.rs | 11 ++++++----- frame/bags-list/src/list/mod.rs | 6 +++--- frame/beefy-mmr/primitives/src/lib.rs | 5 +++-- frame/beefy-mmr/src/lib.rs | 2 +- frame/benchmarking/src/lib.rs | 6 +++--- frame/contracts/src/lib.rs | 2 +- frame/election-provider-multi-phase/src/lib.rs | 8 ++++---- frame/election-provider-support/src/lib.rs | 6 +++--- frame/election-provider-support/src/onchain.rs | 2 +- frame/executive/src/lib.rs | 2 +- frame/staking/src/pallet/mod.rs | 5 +++-- frame/support/procedural/src/construct_runtime/mod.rs | 1 + frame/support/src/lib.rs | 2 +- frame/support/src/storage/bounded_vec.rs | 2 +- frame/support/src/storage/weak_bounded_vec.rs | 2 +- frame/support/src/traits/misc.rs | 2 +- frame/system/src/lib.rs | 3 ++- primitives/beefy/src/commitment.rs | 9 +++++---- primitives/npos-elections/solution-type/src/lib.rs | 2 +- primitives/npos-elections/src/assignments.rs | 2 +- primitives/sandbox/src/lib.rs | 2 +- utils/frame/generate-bags/src/lib.rs | 2 +- 25 files changed, 52 insertions(+), 46 deletions(-) diff --git a/client/consensus/pow/src/lib.rs b/client/consensus/pow/src/lib.rs index 3ab0b977255e..6ccdf53c0f04 100644 --- a/client/consensus/pow/src/lib.rs +++ b/client/consensus/pow/src/lib.rs @@ -27,9 +27,9 @@ //! started via the [`start_mining_worker`] function. It returns a worker //! handle together with a future. The future must be pulled. Through //! the worker handle, you can pull the metadata needed to start the -//! mining process via [`MiningWorker::metadata`], and then do the actual +//! mining process via [`MiningHandle::metadata`], and then do the actual //! mining on a standalone thread. Finally, when a seal is found, call -//! [`MiningWorker::submit`] to build the block. +//! [`MiningHandle::submit`] to build the block. //! //! The auxiliary storage for PoW engine only stores the total difficulty. //! For other storage requirements for particular PoW algorithm (such as diff --git a/client/executor/wasmtime/src/runtime.rs b/client/executor/wasmtime/src/runtime.rs index 4d107862173b..7808ac7ce547 100644 --- a/client/executor/wasmtime/src/runtime.rs +++ b/client/executor/wasmtime/src/runtime.rs @@ -459,11 +459,11 @@ pub struct Config { /// The total amount of memory in bytes an instance can request. /// /// If specified, the runtime will be able to allocate only that much of wasm memory. - /// This is the total number and therefore the [`heap_pages`] is accounted for. + /// This is the total number and therefore the [`Config::heap_pages`] is accounted for. /// - /// That means that the initial number of pages of a linear memory plus the [`heap_pages`] - /// multiplied by the wasm page size (64KiB) should be less than or equal to `max_memory_size`, - /// otherwise the instance won't be created. + /// That means that the initial number of pages of a linear memory plus the + /// [`Config::heap_pages`] multiplied by the wasm page size (64KiB) should be less than or + /// equal to `max_memory_size`, otherwise the instance won't be created. /// /// Moreover, `memory.grow` will fail (return -1) if the sum of sizes of currently mounted /// and additional pages exceeds `max_memory_size`. diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 9fb86f57d839..2e50bf5884fa 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -440,7 +440,7 @@ enum Register { /// Report a telemetry. /// -/// Translates to [`tracing::info`], but contains an additional verbosity parameter which the log +/// Translates to `tracing::info`, but contains an additional verbosity parameter which the log /// record is tagged with. Additionally the verbosity parameter is added to the record as a /// key-value pair. /// diff --git a/frame/bags-list/src/lib.rs b/frame/bags-list/src/lib.rs index 8be1afbe29bb..2cff68b54c9c 100644 --- a/frame/bags-list/src/lib.rs +++ b/frame/bags-list/src/lib.rs @@ -19,11 +19,11 @@ //! //! A semi-sorted list, where items hold an `AccountId` based on some `VoteWeight`. The `AccountId` //! (`id` for short) might be synonym to a `voter` or `nominator` in some context, and `VoteWeight` -//! signifies the chance of each id being included in the final [`VoteWeightProvider::iter`]. +//! signifies the chance of each id being included in the final [`SortedListProvider::iter`]. //! -//! It implements [`sp_election_provider_support::SortedListProvider`] to provide a semi-sorted list -//! of accounts to another pallet. It needs some other pallet to give it some information about the -//! weights of accounts via [`sp_election_provider_support::VoteWeightProvider`]. +//! It implements [`frame_election_provider_support::SortedListProvider`] to provide a semi-sorted +//! list of accounts to another pallet. It needs some other pallet to give it some information about +//! the weights of accounts via [`frame_election_provider_support::VoteWeightProvider`]. //! //! This pallet is not configurable at genesis. Whoever uses it should call appropriate functions of //! the `SortedListProvider` (e.g. `on_insert`, or `regenerate`) at their genesis. @@ -38,7 +38,8 @@ //! //! # Details //! -//! - items are kept in bags, which are delineated by their range of weight (See [`BagThresholds`]). +//! - items are kept in bags, which are delineated by their range of weight (See +//! [`Config::BagThresholds`]). //! - for iteration, bags are chained together from highest to lowest and elements within the bag //! are iterated from head to tail. //! - items within a bag are iterated in order of insertion. Thus removing an item and re-inserting diff --git a/frame/bags-list/src/list/mod.rs b/frame/bags-list/src/list/mod.rs index df966eea80ce..b381b36dc9ee 100644 --- a/frame/bags-list/src/list/mod.rs +++ b/frame/bags-list/src/list/mod.rs @@ -17,8 +17,8 @@ //! Implementation of a "bags list": a semi-sorted list where ordering granularity is dictated by //! configurable thresholds that delineate the boundaries of bags. It uses a pattern of composite -//! data structures, where multiple storage items are masked by one outer API. See [`ListNodes`], -//! [`ListBags`] for more information. +//! data structures, where multiple storage items are masked by one outer API. See +//! [`crate::ListNodes`], [`crate::ListBags`] for more information. //! //! The outer API of this module is the [`List`] struct. It wraps all acceptable operations on top //! of the aggregate linked list. All operations with the bags list should happen through this @@ -460,7 +460,7 @@ impl List { } } -/// A Bag is a doubly-linked list of ids, where each id is mapped to a [`ListNode`]. +/// A Bag is a doubly-linked list of ids, where each id is mapped to a [`Node`]. /// /// Note that we maintain both head and tail pointers. While it would be possible to get away with /// maintaining only a head pointer and cons-ing elements onto the front of the list, it's more diff --git a/frame/beefy-mmr/primitives/src/lib.rs b/frame/beefy-mmr/primitives/src/lib.rs index 4d4d4e8721ac..ee1484607563 100644 --- a/frame/beefy-mmr/primitives/src/lib.rs +++ b/frame/beefy-mmr/primitives/src/lib.rs @@ -44,7 +44,8 @@ pub type Hash = [u8; 32]; /// Generic hasher trait. /// /// Implement the function to support custom way of hashing data. -/// The implementation must return a [Hash] type, so only 32-byte output hashes are supported. +/// The implementation must return a [Hash](type@Hash) type, so only 32-byte output hashes are +/// supported. pub trait Hasher { /// Hash given arbitrary-length piece of data. fn hash(data: &[u8]) -> Hash; @@ -173,7 +174,7 @@ impl Visitor for () { /// /// # Panic /// -/// The function will panic if given [`leaf_index`] is greater than the number of leaves. +/// The function will panic if given `leaf_index` is greater than the number of leaves. pub fn merkle_proof(leaves: I, leaf_index: usize) -> MerkleProof where H: Hasher, diff --git a/frame/beefy-mmr/src/lib.rs b/frame/beefy-mmr/src/lib.rs index 001831639b16..b846aa4a7dd6 100644 --- a/frame/beefy-mmr/src/lib.rs +++ b/frame/beefy-mmr/src/lib.rs @@ -149,7 +149,7 @@ pub mod pallet { /// Details of next BEEFY authority set. /// - /// This storage entry is used as cache for calls to [`update_beefy_next_authority_set`]. + /// This storage entry is used as cache for calls to `update_beefy_next_authority_set`. #[pallet::storage] #[pallet::getter(fn beefy_next_authorities)] pub type BeefyNextAuthorities = diff --git a/frame/benchmarking/src/lib.rs b/frame/benchmarking/src/lib.rs index 088dbeb0bb78..56545914dcba 100644 --- a/frame/benchmarking/src/lib.rs +++ b/frame/benchmarking/src/lib.rs @@ -1266,21 +1266,21 @@ macro_rules! impl_benchmark_test { /// fn bench_accumulate_dummy() { /// new_test_ext().execute_with(|| { /// assert_ok!(test_benchmark_accumulate_dummy::()); -/// } +/// }) /// } /// /// #[test] /// fn bench_set_dummy() { /// new_test_ext().execute_with(|| { /// assert_ok!(test_benchmark_set_dummy::()); -/// } +/// }) /// } /// /// #[test] /// fn bench_sort_vector() { /// new_test_ext().execute_with(|| { /// assert_ok!(test_benchmark_sort_vector::()); -/// } +/// }) /// } /// } /// ``` diff --git a/frame/contracts/src/lib.rs b/frame/contracts/src/lib.rs index 62b74b9b7b95..b2e221dde6ad 100644 --- a/frame/contracts/src/lib.rs +++ b/frame/contracts/src/lib.rs @@ -202,7 +202,7 @@ pub mod pallet { type Schedule: Get>; /// The deposit that must be placed into the contract's account to instantiate it. - /// This is in **addition** to the [`pallet_balances::Pallet::ExistenialDeposit`]. + /// This is in **addition** to the [`Currency::minimum_balance`]. /// The minimum balance for a contract's account can be queried using /// [`Pallet::subsistence_threshold`]. #[pallet::constant] diff --git a/frame/election-provider-multi-phase/src/lib.rs b/frame/election-provider-multi-phase/src/lib.rs index cdf5a2098d6b..ee4c9ae45d42 100644 --- a/frame/election-provider-multi-phase/src/lib.rs +++ b/frame/election-provider-multi-phase/src/lib.rs @@ -183,8 +183,8 @@ //! are helpful for logging and are thus nested as: //! - [`ElectionError::Miner`]: wraps a [`unsigned::MinerError`]. //! - [`ElectionError::Feasibility`]: wraps a [`FeasibilityError`]. -//! - [`ElectionError::OnChainFallback`]: wraps a -//! [`frame_election_provider_support::onchain::Error`]. +//! - [`ElectionError::Fallback`]: wraps a fallback error. +//! - [`ElectionError::DataProvider`]: wraps a static str. //! //! Note that there could be an overlap between these sub-errors. For example, A //! `SnapshotUnavailable` can happen in both miner and feasibility check phase. @@ -1244,14 +1244,14 @@ impl Pallet { } } - /// Logic for [`::on_initialize`] when signed phase is being opened. + /// Logic for `::on_initialize` when signed phase is being opened. pub fn on_initialize_open_signed() { log!(info, "Starting signed phase round {}.", Self::round()); >::put(Phase::Signed); Self::deposit_event(Event::SignedPhaseStarted { round: Self::round() }); } - /// Logic for [`>::on_initialize`] when unsigned phase is being opened. + /// Logic for `>::on_initialize` when unsigned phase is being opened. pub fn on_initialize_open_unsigned(enabled: bool, now: T::BlockNumber) { let round = Self::round(); log!(info, "Starting unsigned phase round {} enabled {}.", round, enabled); diff --git a/frame/election-provider-support/src/lib.rs b/frame/election-provider-support/src/lib.rs index cb36e025c3be..472584ed2506 100644 --- a/frame/election-provider-support/src/lib.rs +++ b/frame/election-provider-support/src/lib.rs @@ -384,7 +384,7 @@ pub trait NposSolver { ) -> Result, Self::Error>; } -/// A wrapper for [`sp_npos_elections::seq_phragmen`] that implements [`super::NposSolver`]. See the +/// A wrapper for [`sp_npos_elections::seq_phragmen`] that implements [`NposSolver`]. See the /// documentation of [`sp_npos_elections::seq_phragmen`] for more info. pub struct SequentialPhragmen( sp_std::marker::PhantomData<(AccountId, Accuracy, Balancing)>, @@ -408,8 +408,8 @@ impl< } } -/// A wrapper for [`sp_npos_elections::phragmms`] that implements [`NposSolver`]. See the -/// documentation of [`sp_npos_elections::phragmms`] for more info. +/// A wrapper for [`sp_npos_elections::phragmms()`] that implements [`NposSolver`]. See the +/// documentation of [`sp_npos_elections::phragmms()`] for more info. pub struct PhragMMS( sp_std::marker::PhantomData<(AccountId, Accuracy, Balancing)>, ); diff --git a/frame/election-provider-support/src/onchain.rs b/frame/election-provider-support/src/onchain.rs index fb1ccfdfe256..6379adae4206 100644 --- a/frame/election-provider-support/src/onchain.rs +++ b/frame/election-provider-support/src/onchain.rs @@ -57,7 +57,7 @@ pub struct OnChainSequentialPhragmen(PhantomData); /// /// WARNING: the user of this pallet must ensure that the `Accuracy` type will work nicely with the /// normalization operation done inside `seq_phragmen`. See -/// [`sp_npos_elections::assignment::try_normalize`] for more info. +/// [`sp_npos_elections::Assignment::try_normalize`] for more info. pub trait Config: frame_system::Config { /// The accuracy used to compute the election: type Accuracy: PerThing128; diff --git a/frame/executive/src/lib.rs b/frame/executive/src/lib.rs index e77c811a35e2..dd0a9abf8687 100644 --- a/frame/executive/src/lib.rs +++ b/frame/executive/src/lib.rs @@ -219,7 +219,7 @@ where weight } - /// Execute given block, but don't do any of the [`final_checks`]. + /// Execute given block, but don't do any of the `final_checks`. /// /// Should only be used for testing. #[cfg(feature = "try-runtime")] diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index ec7e86af958f..542b79b792dc 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -69,7 +69,8 @@ pub mod pallet { /// Convert a balance into a number used for election calculation. This must fit into a /// `u64` but is allowed to be sensibly lossy. The `u64` is used to communicate with the - /// [`sp_npos_elections`] crate which accepts u64 numbers and does operations in 128. + /// [`frame_election_provider_support`] crate which accepts u64 numbers and does operations + /// in 128. /// Consequently, the backward convert is used convert the u128s from sp-elections back to a /// [`BalanceOf`]. type CurrencyToVote: CurrencyToVote>; @@ -146,7 +147,7 @@ pub mod pallet { type OffendingValidatorsThreshold: Get; /// Something that can provide a sorted list of voters in a somewhat sorted way. The - /// original use case for this was designed with [`pallet_bags_list::Pallet`] in mind. If + /// original use case for this was designed with `pallet_bags_list::Pallet` in mind. If /// the bags-list is not desired, [`impls::UseNominatorsMap`] is likely the desired option. type SortedListProvider: SortedListProvider; diff --git a/frame/support/procedural/src/construct_runtime/mod.rs b/frame/support/procedural/src/construct_runtime/mod.rs index f54fa79ce609..a5da775b9c9e 100644 --- a/frame/support/procedural/src/construct_runtime/mod.rs +++ b/frame/support/procedural/src/construct_runtime/mod.rs @@ -84,6 +84,7 @@ //! }] //! pattern = [{ System: frame_system }] //! tokens = [{ ::{Pallet, Call} }] +//! } //! }] //! pattern = [{ Balances: pallet_balances }] //! tokens = [{ ::{Pallet, Call} }] diff --git a/frame/support/src/lib.rs b/frame/support/src/lib.rs index af9192f6ea83..2adcd8ce4efc 100644 --- a/frame/support/src/lib.rs +++ b/frame/support/src/lib.rs @@ -1749,7 +1749,7 @@ pub mod pallet_prelude { /// ``` /// /// The optional attribute `#[pallet::unbounded]` allows to declare the storage as unbounded. -/// When implementating the storage info (when #[pallet::generate_storage_info]` is specified +/// When implementating the storage info (when `#[pallet::generate_storage_info]` is specified /// on the pallet struct placeholder), the size of the storage will be declared as unbounded. /// This can be useful for storage which can never go into PoV (Proof of Validity). /// diff --git a/frame/support/src/storage/bounded_vec.rs b/frame/support/src/storage/bounded_vec.rs index 3b5e7bda1651..b9ece89bff28 100644 --- a/frame/support/src/storage/bounded_vec.rs +++ b/frame/support/src/storage/bounded_vec.rs @@ -130,7 +130,7 @@ impl BoundedVec { self.0.retain(f) } - /// Exactly the same semantics as [`Vec::get_mut`]. + /// Exactly the same semantics as [`slice::get_mut`]. pub fn get_mut>( &mut self, index: I, diff --git a/frame/support/src/storage/weak_bounded_vec.rs b/frame/support/src/storage/weak_bounded_vec.rs index 823c50c55d0b..566889f5f192 100644 --- a/frame/support/src/storage/weak_bounded_vec.rs +++ b/frame/support/src/storage/weak_bounded_vec.rs @@ -90,7 +90,7 @@ impl WeakBoundedVec { self.0.retain(f) } - /// Exactly the same semantics as [`Vec::get_mut`]. + /// Exactly the same semantics as [`slice::get_mut`]. pub fn get_mut>( &mut self, index: I, diff --git a/frame/support/src/traits/misc.rs b/frame/support/src/traits/misc.rs index 0a3fb045d6c1..153c3804bd59 100644 --- a/frame/support/src/traits/misc.rs +++ b/frame/support/src/traits/misc.rs @@ -301,7 +301,7 @@ pub trait PrivilegeCmp { /// Implementation of [`PrivilegeCmp`] that only checks for equal origins. /// -/// This means it will either return [`Origin::Equal`] or `None`. +/// This means it will either return [`Ordering::Equal`] or `None`. pub struct EqualPrivilegeOnly; impl PrivilegeCmp for EqualPrivilegeOnly { fn cmp_privilege(left: &Origin, right: &Origin) -> Option { diff --git a/frame/system/src/lib.rs b/frame/system/src/lib.rs index d5b930fa165e..12361ed859d0 100644 --- a/frame/system/src/lib.rs +++ b/frame/system/src/lib.rs @@ -301,7 +301,8 @@ pub mod pallet { /// What to do if the runtime wants to change the code to something new. /// /// The default (`()`) implementation is responsible for setting the correct storage - /// entry and emitting corresponding event and log item. (see [`update_code_in_storage`]). + /// entry and emitting corresponding event and log item. (see + /// [`Pallet::update_code_in_storage`]). /// It's unlikely that this needs to be customized, unless you are writing a parachain using /// `Cumulus`, where the actual code change is deferred. type OnSetCode: SetCode; diff --git a/primitives/beefy/src/commitment.rs b/primitives/beefy/src/commitment.rs index 7aab93bbcb97..d9e4de6e19bb 100644 --- a/primitives/beefy/src/commitment.rs +++ b/primitives/beefy/src/commitment.rs @@ -21,7 +21,8 @@ use crate::{crypto::Signature, ValidatorSetId}; /// A commitment signed by GRANDPA validators as part of BEEFY protocol. /// -/// The commitment contains a [payload] extracted from the finalized block at height [block_number]. +/// The commitment contains a [payload](Commitment::payload) extracted from the finalized block at +/// height [block_number](Commitment::block_number). /// GRANDPA validators collect signatures on commitments and a stream of such signed commitments /// (see [SignedCommitment]) forms the BEEFY protocol. #[derive(Clone, Debug, PartialEq, Eq, codec::Encode, codec::Decode)] @@ -33,7 +34,7 @@ pub struct Commitment { /// validator set. The protocol does not enforce any particular format of this data, /// nor how often it should be present in commitments, however the light client has to be /// provided with full validator set whenever it performs the transition (i.e. importing first - /// block with [validator_set_id] incremented). + /// block with [validator_set_id](Commitment::validator_set_id) incremented). pub payload: TPayload, /// Finalized block number this commitment is for. @@ -51,8 +52,8 @@ pub struct Commitment { /// /// Validator set is changing once per epoch. The Light Client must be provided by details /// about the validator set whenever it's importing first commitment with a new - /// `validator_set_id`. Validator set data MUST be verifiable, for instance using [payload] - /// information. + /// `validator_set_id`. Validator set data MUST be verifiable, for instance using + /// [payload](Commitment::payload) information. pub validator_set_id: ValidatorSetId, } diff --git a/primitives/npos-elections/solution-type/src/lib.rs b/primitives/npos-elections/solution-type/src/lib.rs index 9b0ec56fc74d..967ead4400c3 100644 --- a/primitives/npos-elections/solution-type/src/lib.rs +++ b/primitives/npos-elections/solution-type/src/lib.rs @@ -88,7 +88,7 @@ pub(crate) fn syn_err(message: &'static str) -> syn::Error { /// ``` /// /// The given struct provides function to convert from/to `Assignment` as part of -/// [`sp_npos_elections::Solution`] trait: +/// `sp_npos_elections::Solution` trait: /// /// - `fn from_assignment<..>(..)` /// - `fn into_assignment<..>(..)` diff --git a/primitives/npos-elections/src/assignments.rs b/primitives/npos-elections/src/assignments.rs index bdd1e2cd281b..330f7bd7e843 100644 --- a/primitives/npos-elections/src/assignments.rs +++ b/primitives/npos-elections/src/assignments.rs @@ -201,7 +201,7 @@ impl IndexAssignment = IndexAssignment< ::VoterIndex, ::TargetIndex, diff --git a/primitives/sandbox/src/lib.rs b/primitives/sandbox/src/lib.rs index f1a24732b7a0..79c56e70e2f4 100755 --- a/primitives/sandbox/src/lib.rs +++ b/primitives/sandbox/src/lib.rs @@ -89,7 +89,7 @@ pub type HostFuncType = fn(&mut T, &[Value]) -> Result f64 { /// The last element is always `VoteWeight::MAX`. /// /// All other elements are computed from the previous according to the formula -/// `threshold[k + 1] = (threshold[k] * ratio).max(threshold[k] + 1); +/// `threshold[k + 1] = (threshold[k] * ratio).max(threshold[k] + 1);` pub fn thresholds( existential_weight: VoteWeight, constant_ratio: f64, From 68c0952dcf05312c1229e92ff86fa8191c8610a1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Nov 2021 11:12:59 +0000 Subject: [PATCH 215/695] Bump platforms from 1.1.0 to 2.0.0 (#10331) Bumps [platforms](https://github.com/rustsec/rustsec) from 1.1.0 to 2.0.0. - [Release notes](https://github.com/rustsec/rustsec/releases) - [Commits](https://github.com/rustsec/rustsec/commits/platforms/v2.0.0) --- updated-dependencies: - dependency-name: platforms dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- bin/node/cli/Cargo.toml | 2 +- utils/build-script-utils/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 56eb2a5543c8..2c10e9fe0b95 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6643,9 +6643,9 @@ checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" [[package]] name = "platforms" -version = "1.1.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "989d43012e2ca1c4a02507c67282691a0a3207f9dc67cec596b43fe925b3d325" +checksum = "e8d0eef3571242013a0d5dc84861c3ae4a652e56e12adf8bdc26ff5f8cb34c94" [[package]] name = "plotters" diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index 5a9e76bccf63..1bb3671d42ba 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -126,7 +126,7 @@ assert_cmd = "2.0.2" nix = "0.23" serde_json = "1.0" regex = "1" -platforms = "1.1" +platforms = "2.0" async-std = { version = "1.10.0", features = ["attributes"] } soketto = "0.4.2" criterion = { version = "0.3.5", features = [ "async_tokio" ] } diff --git a/utils/build-script-utils/Cargo.toml b/utils/build-script-utils/Cargo.toml index 93611c7b5b01..7150b4fa5adc 100644 --- a/utils/build-script-utils/Cargo.toml +++ b/utils/build-script-utils/Cargo.toml @@ -13,4 +13,4 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -platforms = "1.1" +platforms = "2.0" From c0da7c3d47def8600c9d3ef55617790d81b7d8bb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Nov 2021 12:57:50 +0000 Subject: [PATCH 216/695] Bump serde_json from 1.0.68 to 1.0.71 (#10321) Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.68 to 1.0.71. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.68...v1.0.71) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- bin/node/bench/Cargo.toml | 2 +- client/chain-spec/Cargo.toml | 2 +- client/cli/Cargo.toml | 2 +- client/consensus/babe/rpc/Cargo.toml | 2 +- client/finality-grandpa/Cargo.toml | 2 +- client/keystore/Cargo.toml | 2 +- client/network/Cargo.toml | 2 +- client/peerset/Cargo.toml | 2 +- client/rpc-api/Cargo.toml | 2 +- client/rpc-servers/Cargo.toml | 2 +- client/rpc/Cargo.toml | 2 +- client/service/Cargo.toml | 2 +- client/sync-state-rpc/Cargo.toml | 2 +- client/telemetry/Cargo.toml | 2 +- frame/merkle-mountain-range/rpc/Cargo.toml | 2 +- frame/transaction-payment/Cargo.toml | 2 +- frame/transaction-payment/asset-tx-payment/Cargo.toml | 2 +- primitives/rpc/Cargo.toml | 2 +- primitives/runtime/Cargo.toml | 2 +- primitives/serializer/Cargo.toml | 2 +- test-utils/client/Cargo.toml | 2 +- 22 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2c10e9fe0b95..3fd2ba8085a9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8956,9 +8956,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.68" +version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f690853975602e1bfe1ccbf50504d67174e3bcf340f23b5ea9992e0587a52d8" +checksum = "063bf466a64011ac24040a49009724ee60a57da1b437617ceb32e53ad61bfb19" dependencies = [ "itoa", "ryu", diff --git a/bin/node/bench/Cargo.toml b/bin/node/bench/Cargo.toml index 037a233a4ca0..0beeb4e339e4 100644 --- a/bin/node/bench/Cargo.toml +++ b/bin/node/bench/Cargo.toml @@ -17,7 +17,7 @@ sc-client-api = { version = "4.0.0-dev", path = "../../../client/api/" } sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } sp-state-machine = { version = "0.10.0-dev", path = "../../../primitives/state-machine" } serde = "1.0.126" -serde_json = "1.0.68" +serde_json = "1.0.71" structopt = "0.3" derive_more = "0.99.16" kvdb = "0.10.0" diff --git a/client/chain-spec/Cargo.toml b/client/chain-spec/Cargo.toml index d7557e2062ac..976da4585911 100644 --- a/client/chain-spec/Cargo.toml +++ b/client/chain-spec/Cargo.toml @@ -18,7 +18,7 @@ impl-trait-for-tuples = "0.2.1" sc-network = { version = "0.10.0-dev", path = "../network" } sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } serde = { version = "1.0.126", features = ["derive"] } -serde_json = "1.0.68" +serde_json = "1.0.71" sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } sc-telemetry = { version = "4.0.0-dev", path = "../telemetry" } codec = { package = "parity-scale-codec", version = "2.0.0" } diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index 2855e63cdc6a..8667a5e876c1 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -23,7 +23,7 @@ parity-scale-codec = "2.3.1" hex = "0.4.2" rand = "0.7.3" tiny-bip39 = "0.8.2" -serde_json = "1.0.68" +serde_json = "1.0.71" sc-keystore = { version = "4.0.0-dev", path = "../keystore" } sp-panic-handler = { version = "4.0.0-dev", path = "../../primitives/panic-handler" } sc-client-api = { version = "4.0.0-dev", path = "../api" } diff --git a/client/consensus/babe/rpc/Cargo.toml b/client/consensus/babe/rpc/Cargo.toml index 3a7cf86a800c..b47c3a711df9 100644 --- a/client/consensus/babe/rpc/Cargo.toml +++ b/client/consensus/babe/rpc/Cargo.toml @@ -33,7 +33,7 @@ sp-keystore = { version = "0.10.0-dev", path = "../../../../primitives/keystore" [dev-dependencies] sc-consensus = { version = "0.10.0-dev", path = "../../../consensus/common" } -serde_json = "1.0.68" +serde_json = "1.0.71" sp-keyring = { version = "4.0.0-dev", path = "../../../../primitives/keyring" } sc-keystore = { version = "4.0.0-dev", path = "../../../keystore" } substrate-test-runtime-client = { version = "2.0.0", path = "../../../../test-utils/runtime/client" } diff --git a/client/finality-grandpa/Cargo.toml b/client/finality-grandpa/Cargo.toml index 1dd8c2518ab7..65a0580b9e95 100644 --- a/client/finality-grandpa/Cargo.toml +++ b/client/finality-grandpa/Cargo.toml @@ -35,7 +35,7 @@ sp-keystore = { version = "0.10.0-dev", path = "../../primitives/keystore" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } sc-telemetry = { version = "4.0.0-dev", path = "../telemetry" } sc-keystore = { version = "4.0.0-dev", path = "../keystore" } -serde_json = "1.0.68" +serde_json = "1.0.71" sc-client-api = { version = "4.0.0-dev", path = "../api" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sc-network = { version = "0.10.0-dev", path = "../network" } diff --git a/client/keystore/Cargo.toml b/client/keystore/Cargo.toml index 9e2928d41e89..9da825faf033 100644 --- a/client/keystore/Cargo.toml +++ b/client/keystore/Cargo.toml @@ -22,7 +22,7 @@ sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } sp-keystore = { version = "0.10.0-dev", path = "../../primitives/keystore" } hex = "0.4.0" parking_lot = "0.11.1" -serde_json = "1.0.68" +serde_json = "1.0.71" [dev-dependencies] tempfile = "3.1.0" diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index 13eb408b0bb5..c4622c0c5df0 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -47,7 +47,7 @@ sc-block-builder = { version = "0.10.0-dev", path = "../block-builder" } sc-client-api = { version = "4.0.0-dev", path = "../api" } sc-peerset = { version = "4.0.0-dev", path = "../peerset" } serde = { version = "1.0.126", features = ["derive"] } -serde_json = "1.0.68" +serde_json = "1.0.71" smallvec = "1.7.0" sp-arithmetic = { version = "4.0.0-dev", path = "../../primitives/arithmetic" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } diff --git a/client/peerset/Cargo.toml b/client/peerset/Cargo.toml index 01b75f1094ff..fba499bce00e 100644 --- a/client/peerset/Cargo.toml +++ b/client/peerset/Cargo.toml @@ -18,7 +18,7 @@ futures = "0.3.9" libp2p = { version = "0.39.1", default-features = false } sc-utils = { version = "4.0.0-dev", path = "../utils"} log = "0.4.8" -serde_json = "1.0.68" +serde_json = "1.0.71" wasm-timer = "0.2" [dev-dependencies] diff --git a/client/rpc-api/Cargo.toml b/client/rpc-api/Cargo.toml index 532a5cf6294c..a758d29aed2c 100644 --- a/client/rpc-api/Cargo.toml +++ b/client/rpc-api/Cargo.toml @@ -28,7 +28,7 @@ sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } sp-runtime = { path = "../../primitives/runtime", version = "4.0.0-dev" } sc-chain-spec = { path = "../chain-spec", version = "4.0.0-dev" } serde = { version = "1.0.126", features = ["derive"] } -serde_json = "1.0.68" +serde_json = "1.0.71" sc-transaction-pool-api = { version = "4.0.0-dev", path = "../transaction-pool/api" } sp-rpc = { version = "4.0.0-dev", path = "../../primitives/rpc" } sp-tracing = { version = "4.0.0-dev", path = "../../primitives/tracing" } diff --git a/client/rpc-servers/Cargo.toml b/client/rpc-servers/Cargo.toml index 3be238078506..f6f08ac581d4 100644 --- a/client/rpc-servers/Cargo.toml +++ b/client/rpc-servers/Cargo.toml @@ -18,7 +18,7 @@ jsonrpc-core = "18.0.0" pubsub = { package = "jsonrpc-pubsub", version = "18.0.0" } log = "0.4.8" prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.10.0-dev"} -serde_json = "1.0.68" +serde_json = "1.0.71" tokio = "1.13" http = { package = "jsonrpc-http-server", version = "18.0.0" } ipc = { package = "jsonrpc-ipc-server", version = "18.0.0" } diff --git a/client/rpc/Cargo.toml b/client/rpc/Cargo.toml index d8aecfe9fd35..6cf2d699386d 100644 --- a/client/rpc/Cargo.toml +++ b/client/rpc/Cargo.toml @@ -23,7 +23,7 @@ log = "0.4.8" sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } rpc = { package = "jsonrpc-core", version = "18.0.0" } sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } -serde_json = "1.0.68" +serde_json = "1.0.71" sp-session = { version = "4.0.0-dev", path = "../../primitives/session" } sp-offchain = { version = "4.0.0-dev", path = "../../primitives/offchain" } sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index a66a4fc67680..161863b14710 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -34,7 +34,7 @@ exit-future = "0.2.0" pin-project = "1.0.8" hash-db = "0.15.2" serde = "1.0.126" -serde_json = "1.0.68" +serde_json = "1.0.71" sc-keystore = { version = "4.0.0-dev", path = "../keystore" } sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } sp-trie = { version = "4.0.0-dev", path = "../../primitives/trie" } diff --git a/client/sync-state-rpc/Cargo.toml b/client/sync-state-rpc/Cargo.toml index 6d8d95954629..c609ac42c76e 100644 --- a/client/sync-state-rpc/Cargo.toml +++ b/client/sync-state-rpc/Cargo.toml @@ -23,7 +23,7 @@ sc-consensus-babe = { version = "0.10.0-dev", path = "../consensus/babe" } sc-consensus-epochs = { version = "0.10.0-dev", path = "../consensus/epochs" } sc-finality-grandpa = { version = "0.10.0-dev", path = "../finality-grandpa" } sc-rpc-api = { version = "0.10.0-dev", path = "../rpc-api" } -serde_json = "1.0.68" +serde_json = "1.0.71" serde = { version = "1.0.126", features = ["derive"] } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } diff --git a/client/telemetry/Cargo.toml b/client/telemetry/Cargo.toml index 744a0610a07e..9165f6f87af6 100644 --- a/client/telemetry/Cargo.toml +++ b/client/telemetry/Cargo.toml @@ -23,6 +23,6 @@ log = "0.4.8" pin-project = "1.0.8" rand = "0.7.2" serde = { version = "1.0.126", features = ["derive"] } -serde_json = "1.0.68" +serde_json = "1.0.71" chrono = "0.4.19" thiserror = "1.0.30" diff --git a/frame/merkle-mountain-range/rpc/Cargo.toml b/frame/merkle-mountain-range/rpc/Cargo.toml index 881cbb3c8ebf..d8f861ad8ec5 100644 --- a/frame/merkle-mountain-range/rpc/Cargo.toml +++ b/frame/merkle-mountain-range/rpc/Cargo.toml @@ -27,4 +27,4 @@ sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } pallet-mmr-primitives = { version = "4.0.0-dev", path = "../primitives" } [dev-dependencies] -serde_json = "1.0.68" +serde_json = "1.0.71" diff --git a/frame/transaction-payment/Cargo.toml b/frame/transaction-payment/Cargo.toml index 1d3066e39fbd..3b8b85977db3 100644 --- a/frame/transaction-payment/Cargo.toml +++ b/frame/transaction-payment/Cargo.toml @@ -29,7 +29,7 @@ frame-support = { version = "4.0.0-dev", default-features = false, path = "../su frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } [dev-dependencies] -serde_json = "1.0.68" +serde_json = "1.0.71" pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/frame/transaction-payment/asset-tx-payment/Cargo.toml b/frame/transaction-payment/asset-tx-payment/Cargo.toml index a381145d667a..e4f3b128cfce 100644 --- a/frame/transaction-payment/asset-tx-payment/Cargo.toml +++ b/frame/transaction-payment/asset-tx-payment/Cargo.toml @@ -30,7 +30,7 @@ serde = { version = "1.0.126", optional = true } [dev-dependencies] smallvec = "1.7.0" -serde_json = "1.0.68" +serde_json = "1.0.71" sp-storage = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/storage" } diff --git a/primitives/rpc/Cargo.toml b/primitives/rpc/Cargo.toml index 15f7aa2b3b89..2d56cb06fbcc 100644 --- a/primitives/rpc/Cargo.toml +++ b/primitives/rpc/Cargo.toml @@ -18,4 +18,4 @@ sp-core = { version = "4.0.0-dev", path = "../core" } rustc-hash = "1.1.0" [dev-dependencies] -serde_json = "1.0.68" +serde_json = "1.0.71" diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 8e466bf4a1e8..7966bb28255b 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -32,7 +32,7 @@ hash256-std-hasher = { version = "0.15.2", default-features = false } either = { version = "1.5", default-features = false } [dev-dependencies] -serde_json = "1.0.68" +serde_json = "1.0.71" rand = "0.7.2" sp-state-machine = { version = "0.10.0-dev", path = "../state-machine" } sp-api = { version = "4.0.0-dev", path = "../api" } diff --git a/primitives/serializer/Cargo.toml b/primitives/serializer/Cargo.toml index 2b2acb8dbc37..359217b9b4d5 100644 --- a/primitives/serializer/Cargo.toml +++ b/primitives/serializer/Cargo.toml @@ -15,4 +15,4 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = "1.0.126" -serde_json = "1.0.68" +serde_json = "1.0.71" diff --git a/test-utils/client/Cargo.toml b/test-utils/client/Cargo.toml index 1277863c94f7..ef481dd3f202 100644 --- a/test-utils/client/Cargo.toml +++ b/test-utils/client/Cargo.toml @@ -16,7 +16,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0" } futures = "0.3.16" hex = "0.4" serde = "1.0.126" -serde_json = "1.0.68" +serde_json = "1.0.71" sc-client-api = { version = "4.0.0-dev", path = "../../client/api" } sc-client-db = { version = "0.10.0-dev", features = [ "test-helpers", From 5ed2f8fc99b67befc86fd30dce344e394c65e536 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Nov 2021 19:03:41 +0000 Subject: [PATCH 217/695] Bump paste from 1.0.4 to 1.0.6 (#10333) Bumps [paste](https://github.com/dtolnay/paste) from 1.0.4 to 1.0.6. - [Release notes](https://github.com/dtolnay/paste/releases) - [Commits](https://github.com/dtolnay/paste/compare/1.0.4...1.0.6) --- updated-dependencies: - dependency-name: paste dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 18 +++++++++--------- client/executor/runtime-test/Cargo.toml | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3fd2ba8085a9..6eb7efb08486 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1947,7 +1947,7 @@ dependencies = [ "linregress", "log 0.4.14", "parity-scale-codec", - "paste 1.0.4", + "paste 1.0.6", "scale-info", "sp-api", "sp-io", @@ -2044,7 +2044,7 @@ dependencies = [ "once_cell", "parity-scale-codec", "parity-util-mem", - "paste 1.0.4", + "paste 1.0.6", "pretty_assertions", "scale-info", "serde", @@ -6465,9 +6465,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.4" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5d65c4d95931acda4498f675e332fcbdc9a06705cd07086c510e9b6009cd1c1" +checksum = "0744126afe1a6dd7f394cb50a716dbe086cb06e255e53d8d0185d82828358fb5" [[package]] name = "paste-impl" @@ -8072,7 +8072,7 @@ dependencies = [ "log 0.4.14", "parity-scale-codec", "parking_lot 0.11.1", - "paste 1.0.4", + "paste 1.0.6", "regex", "sc-executor-common", "sc-executor-wasmi", @@ -8495,7 +8495,7 @@ dependencies = [ name = "sc-runtime-test" version = "2.0.0" dependencies = [ - "paste 1.0.4", + "paste 1.0.6", "sp-core", "sp-io", "sp-runtime", @@ -9082,7 +9082,7 @@ dependencies = [ "approx", "num-complex", "num-traits", - "paste 1.0.4", + "paste 1.0.6", ] [[package]] @@ -9696,7 +9696,7 @@ dependencies = [ "log 0.4.14", "parity-scale-codec", "parity-util-mem", - "paste 1.0.4", + "paste 1.0.6", "rand 0.7.3", "scale-info", "serde", @@ -11604,7 +11604,7 @@ dependencies = [ "libc", "log 0.4.14", "object 0.27.1", - "paste 1.0.4", + "paste 1.0.6", "psm", "rayon", "region", diff --git a/client/executor/runtime-test/Cargo.toml b/client/executor/runtime-test/Cargo.toml index 2c82a9705cee..ea379a160f80 100644 --- a/client/executor/runtime-test/Cargo.toml +++ b/client/executor/runtime-test/Cargo.toml @@ -19,7 +19,7 @@ sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../.. sp-sandbox = { version = "0.10.0-dev", default-features = false, path = "../../../primitives/sandbox" } sp-std = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/std" } sp-tasks = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/tasks" } -paste = "1.0.4" +paste = "1.0.6" [build-dependencies] substrate-wasm-builder = { version = "5.0.0-dev", path = "../../../utils/wasm-builder" } From 07101053f9ad7b78de32b7a9df3fe0fb304cf1e2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Nov 2021 22:57:44 +0100 Subject: [PATCH 218/695] Bump prost from 0.8.0 to 0.9.0 (#10341) Bumps [prost](https://github.com/tokio-rs/prost) from 0.8.0 to 0.9.0. - [Release notes](https://github.com/tokio-rs/prost/releases) - [Commits](https://github.com/tokio-rs/prost/compare/v0.8.0...v0.9.0) --- updated-dependencies: - dependency-name: prost dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- client/authority-discovery/Cargo.toml | 2 +- client/network/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6eb7efb08486..a45e0accd49b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7632,7 +7632,7 @@ dependencies = [ "libp2p", "log 0.4.14", "parity-scale-codec", - "prost 0.8.0", + "prost 0.9.0", "prost-build 0.9.0", "quickcheck", "rand 0.7.3", @@ -8282,7 +8282,7 @@ dependencies = [ "parity-scale-codec", "parking_lot 0.11.1", "pin-project 1.0.8", - "prost 0.8.0", + "prost 0.9.0", "prost-build 0.9.0", "quickcheck", "rand 0.7.3", diff --git a/client/authority-discovery/Cargo.toml b/client/authority-discovery/Cargo.toml index fff1ed08a8c1..b6f9b8450d86 100644 --- a/client/authority-discovery/Cargo.toml +++ b/client/authority-discovery/Cargo.toml @@ -26,7 +26,7 @@ ip_network = "0.4.0" libp2p = { version = "0.39.1", default-features = false, features = ["kad"] } log = "0.4.8" prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.10.0-dev" } -prost = "0.8" +prost = "0.9" rand = "0.7.2" sc-client-api = { version = "4.0.0-dev", path = "../api" } sc-network = { version = "0.10.0-dev", path = "../network" } diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index c4622c0c5df0..527a18dc7755 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -41,7 +41,7 @@ log = "0.4.8" parking_lot = "0.11.1" pin-project = "1.0.8" prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.10.0-dev", path = "../../utils/prometheus" } -prost = "0.8" +prost = "0.9" rand = "0.7.2" sc-block-builder = { version = "0.10.0-dev", path = "../block-builder" } sc-client-api = { version = "4.0.0-dev", path = "../api" } From 4de8ee2dee389f4246f3156667fc3d6df7047e4f Mon Sep 17 00:00:00 2001 From: Koute Date: Tue, 23 Nov 2021 15:35:19 +0900 Subject: [PATCH 219/695] Fix WASM executor without instance reuse; cleanups and refactoring (#10313) * Fix WASM executor without instance reuse; cleanups and refactoring * Align to review comments * Move the functions for reading/writing memory to `util.rs` * Only `#[ignore]` the test in debug builds * More review comments and minor extra comments --- client/executor/wasmtime/build.rs | 25 ++ client/executor/wasmtime/src/host.rs | 212 ++++++++--------- client/executor/wasmtime/src/imports.rs | 15 +- .../executor/wasmtime/src/instance_wrapper.rs | 217 ++++++------------ client/executor/wasmtime/src/runtime.rs | 206 ++++++++--------- client/executor/wasmtime/src/tests.rs | 36 +++ client/executor/wasmtime/src/util.rs | 59 ++++- 7 files changed, 394 insertions(+), 376 deletions(-) create mode 100644 client/executor/wasmtime/build.rs diff --git a/client/executor/wasmtime/build.rs b/client/executor/wasmtime/build.rs new file mode 100644 index 000000000000..6ab581c9c268 --- /dev/null +++ b/client/executor/wasmtime/build.rs @@ -0,0 +1,25 @@ +// This file is part of Substrate. + +// Copyright (C) 2021 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 . + +use std::env; + +fn main() { + if let Ok(profile) = env::var("PROFILE") { + println!("cargo:rustc-cfg=build_type=\"{}\"", profile); + } +} diff --git a/client/executor/wasmtime/src/host.rs b/client/executor/wasmtime/src/host.rs index fcb4c4cae3b8..39ee9ced80af 100644 --- a/client/executor/wasmtime/src/host.rs +++ b/client/executor/wasmtime/src/host.rs @@ -19,7 +19,7 @@ //! This module defines `HostState` and `HostContext` structs which provide logic and state //! required for execution of host. -use crate::{instance_wrapper::InstanceWrapper, runtime::StoreData}; +use crate::{runtime::StoreData, util}; use codec::{Decode, Encode}; use log::trace; use sc_allocator::FreeingBumpHeapAllocator; @@ -30,101 +30,104 @@ use sc_executor_common::{ }; use sp_core::sandbox as sandbox_primitives; use sp_wasm_interface::{FunctionContext, MemoryId, Pointer, Sandbox, WordSize}; -use std::{cell::RefCell, rc::Rc}; use wasmtime::{Caller, Func, Val}; +// The sandbox store is inside of a Option>> so that we can temporarily borrow it. +struct SandboxStore(Option>>); + +// There are a bunch of `Rc`s within the sandbox store, however we only manipulate +// those within one thread so this should be safe. +unsafe impl Send for SandboxStore {} + /// The state required to construct a HostContext context. The context only lasts for one host /// call, whereas the state is maintained for the duration of a Wasm runtime call, which may make /// many different host calls that must share state. pub struct HostState { - /// We need some interior mutability here since the host state is shared between all host - /// function handlers and the wasmtime backend's `impl WasmRuntime`. - /// - /// Furthermore, because of recursive calls (e.g. runtime can create and call an sandboxed - /// instance which in turn can call the runtime back) we have to be very careful with borrowing - /// those. - /// - /// Basically, most of the interactions should do temporary borrow immediately releasing the - /// borrow after performing necessary queries/changes. - sandbox_store: Rc>>, - allocator: RefCell, - instance: Rc, + sandbox_store: SandboxStore, + allocator: FreeingBumpHeapAllocator, } impl HostState { /// Constructs a new `HostState`. - pub fn new(allocator: FreeingBumpHeapAllocator, instance: Rc) -> Self { + pub fn new(allocator: FreeingBumpHeapAllocator) -> Self { HostState { - sandbox_store: Rc::new(RefCell::new(sandbox::Store::new( + sandbox_store: SandboxStore(Some(Box::new(sandbox::Store::new( sandbox::SandboxBackend::TryWasmer, - ))), - allocator: RefCell::new(allocator), - instance, + )))), + allocator, } } - - /// Materialize `HostContext` that can be used to invoke a substrate host `dyn Function`. - pub(crate) fn materialize<'a, 'b, 'c>( - &'a self, - caller: &'b mut Caller<'c, StoreData>, - ) -> HostContext<'a, 'b, 'c> { - HostContext { host_state: self, caller } - } } /// A `HostContext` implements `FunctionContext` for making host calls from a Wasmtime /// runtime. The `HostContext` exists only for the lifetime of the call and borrows state from /// a longer-living `HostState`. -pub(crate) struct HostContext<'a, 'b, 'c> { - host_state: &'a HostState, - caller: &'b mut Caller<'c, StoreData>, +pub(crate) struct HostContext<'a, 'b> { + pub(crate) caller: &'a mut Caller<'b, StoreData>, } -impl<'a, 'b, 'c> std::ops::Deref for HostContext<'a, 'b, 'c> { - type Target = HostState; - fn deref(&self) -> &HostState { - self.host_state +impl<'a, 'b> HostContext<'a, 'b> { + fn host_state(&self) -> &HostState { + self.caller + .data() + .host_state() + .expect("host state is not empty when calling a function in wasm; qed") + } + + fn host_state_mut(&mut self) -> &mut HostState { + self.caller + .data_mut() + .host_state_mut() + .expect("host state is not empty when calling a function in wasm; qed") + } + + fn sandbox_store(&self) -> &sandbox::Store { + self.host_state() + .sandbox_store + .0 + .as_ref() + .expect("sandbox store is only empty when temporarily borrowed") + } + + fn sandbox_store_mut(&mut self) -> &mut sandbox::Store { + self.host_state_mut() + .sandbox_store + .0 + .as_mut() + .expect("sandbox store is only empty when temporarily borrowed") } } -impl<'a, 'b, 'c> sp_wasm_interface::FunctionContext for HostContext<'a, 'b, 'c> { +impl<'a, 'b> sp_wasm_interface::FunctionContext for HostContext<'a, 'b> { fn read_memory_into( &self, address: Pointer, dest: &mut [u8], ) -> sp_wasm_interface::Result<()> { - let ctx = &self.caller; - self.host_state - .instance - .read_memory_into(ctx, address, dest) - .map_err(|e| e.to_string()) + util::read_memory_into(&self.caller, address, dest).map_err(|e| e.to_string()) } fn write_memory(&mut self, address: Pointer, data: &[u8]) -> sp_wasm_interface::Result<()> { - let ctx = &mut self.caller; - self.host_state - .instance - .write_memory_from(ctx, address, data) - .map_err(|e| e.to_string()) + util::write_memory_from(&mut self.caller, address, data).map_err(|e| e.to_string()) } fn allocate_memory(&mut self, size: WordSize) -> sp_wasm_interface::Result> { - let ctx = &mut self.caller; - let allocator = &self.host_state.allocator; - - self.host_state - .instance - .allocate(ctx, &mut *allocator.borrow_mut(), size) + let memory = self.caller.data().memory(); + let (memory, data) = memory.data_and_store_mut(&mut self.caller); + data.host_state_mut() + .expect("host state is not empty when calling a function in wasm; qed") + .allocator + .allocate(memory, size) .map_err(|e| e.to_string()) } fn deallocate_memory(&mut self, ptr: Pointer) -> sp_wasm_interface::Result<()> { - let ctx = &mut self.caller; - let allocator = &self.host_state.allocator; - - self.host_state - .instance - .deallocate(ctx, &mut *allocator.borrow_mut(), ptr) + let memory = self.caller.data().memory(); + let (memory, data) = memory.data_and_store_mut(&mut self.caller); + data.host_state_mut() + .expect("host state is not empty when calling a function in wasm; qed") + .allocator + .deallocate(memory, ptr) .map_err(|e| e.to_string()) } @@ -133,7 +136,7 @@ impl<'a, 'b, 'c> sp_wasm_interface::FunctionContext for HostContext<'a, 'b, 'c> } } -impl<'a, 'b, 'c> Sandbox for HostContext<'a, 'b, 'c> { +impl<'a, 'b> Sandbox for HostContext<'a, 'b> { fn memory_get( &mut self, memory_id: MemoryId, @@ -141,8 +144,7 @@ impl<'a, 'b, 'c> Sandbox for HostContext<'a, 'b, 'c> { buf_ptr: Pointer, buf_len: WordSize, ) -> sp_wasm_interface::Result { - let sandboxed_memory = - self.sandbox_store.borrow().memory(memory_id).map_err(|e| e.to_string())?; + let sandboxed_memory = self.sandbox_store().memory(memory_id).map_err(|e| e.to_string())?; let len = buf_len as usize; @@ -151,8 +153,7 @@ impl<'a, 'b, 'c> Sandbox for HostContext<'a, 'b, 'c> { Ok(buffer) => buffer, }; - let instance = self.instance.clone(); - if let Err(_) = instance.write_memory_from(&mut self.caller, buf_ptr, &buffer) { + if util::write_memory_from(&mut self.caller, buf_ptr, &buffer).is_err() { return Ok(sandbox_primitives::ERR_OUT_OF_BOUNDS) } @@ -166,17 +167,16 @@ impl<'a, 'b, 'c> Sandbox for HostContext<'a, 'b, 'c> { val_ptr: Pointer, val_len: WordSize, ) -> sp_wasm_interface::Result { - let sandboxed_memory = - self.sandbox_store.borrow().memory(memory_id).map_err(|e| e.to_string())?; + let sandboxed_memory = self.sandbox_store().memory(memory_id).map_err(|e| e.to_string())?; let len = val_len as usize; - let buffer = match self.instance.read_memory(&self.caller, val_ptr, len) { + let buffer = match util::read_memory(&self.caller, val_ptr, len) { Err(_) => return Ok(sandbox_primitives::ERR_OUT_OF_BOUNDS), Ok(buffer) => buffer, }; - if let Err(_) = sandboxed_memory.write_from(Pointer::new(offset as u32), &buffer) { + if sandboxed_memory.write_from(Pointer::new(offset as u32), &buffer).is_err() { return Ok(sandbox_primitives::ERR_OUT_OF_BOUNDS) } @@ -184,17 +184,11 @@ impl<'a, 'b, 'c> Sandbox for HostContext<'a, 'b, 'c> { } fn memory_teardown(&mut self, memory_id: MemoryId) -> sp_wasm_interface::Result<()> { - self.sandbox_store - .borrow_mut() - .memory_teardown(memory_id) - .map_err(|e| e.to_string()) + self.sandbox_store_mut().memory_teardown(memory_id).map_err(|e| e.to_string()) } fn memory_new(&mut self, initial: u32, maximum: u32) -> sp_wasm_interface::Result { - self.sandbox_store - .borrow_mut() - .new_memory(initial, maximum) - .map_err(|e| e.to_string()) + self.sandbox_store_mut().new_memory(initial, maximum).map_err(|e| e.to_string()) } fn invoke( @@ -215,14 +209,10 @@ impl<'a, 'b, 'c> Sandbox for HostContext<'a, 'b, 'c> { .map(Into::into) .collect::>(); - let instance = - self.sandbox_store.borrow().instance(instance_id).map_err(|e| e.to_string())?; + let instance = self.sandbox_store().instance(instance_id).map_err(|e| e.to_string())?; - let dispatch_thunk = self - .sandbox_store - .borrow() - .dispatch_thunk(instance_id) - .map_err(|e| e.to_string())?; + let dispatch_thunk = + self.sandbox_store().dispatch_thunk(instance_id).map_err(|e| e.to_string())?; let result = instance.invoke( export_name, @@ -249,8 +239,7 @@ impl<'a, 'b, 'c> Sandbox for HostContext<'a, 'b, 'c> { } fn instance_teardown(&mut self, instance_id: u32) -> sp_wasm_interface::Result<()> { - self.sandbox_store - .borrow_mut() + self.sandbox_store_mut() .instance_teardown(instance_id) .map_err(|e| e.to_string()) } @@ -264,14 +253,12 @@ impl<'a, 'b, 'c> Sandbox for HostContext<'a, 'b, 'c> { ) -> sp_wasm_interface::Result { // Extract a dispatch thunk from the instance's table by the specified index. let dispatch_thunk = { - let ctx = &mut self.caller; - let table_item = self - .host_state - .instance + let table = self + .caller + .data() .table() - .as_ref() - .ok_or_else(|| "Runtime doesn't have a table; sandbox is unavailable")? - .get(ctx, dispatch_thunk_id); + .ok_or_else(|| "Runtime doesn't have a table; sandbox is unavailable")?; + let table_item = table.get(&mut self.caller, dispatch_thunk_id); table_item .ok_or_else(|| "dispatch_thunk_id is out of bounds")? @@ -281,25 +268,39 @@ impl<'a, 'b, 'c> Sandbox for HostContext<'a, 'b, 'c> { .clone() }; - let guest_env = - match sandbox::GuestEnvironment::decode(&*self.sandbox_store.borrow(), raw_env_def) { - Ok(guest_env) => guest_env, - Err(_) => return Ok(sandbox_primitives::ERR_MODULE as u32), - }; + let guest_env = match sandbox::GuestEnvironment::decode(&self.sandbox_store(), raw_env_def) + { + Ok(guest_env) => guest_env, + Err(_) => return Ok(sandbox_primitives::ERR_MODULE as u32), + }; - let store = self.sandbox_store.clone(); - let store = &mut store.borrow_mut(); - let result = store - .instantiate( + let mut store = self + .host_state_mut() + .sandbox_store + .0 + .take() + .expect("sandbox store is only empty when borrowed"); + + // Catch any potential panics so that we can properly restore the sandbox store + // which we've destructively borrowed. + let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { + store.instantiate( wasm, guest_env, state, &mut SandboxContext { host_context: self, dispatch_thunk: dispatch_thunk.clone() }, ) - .map(|i| i.register(store, dispatch_thunk)); + })); + + self.host_state_mut().sandbox_store.0 = Some(store); + + let result = match result { + Ok(result) => result, + Err(error) => std::panic::resume_unwind(error), + }; let instance_idx_or_err_code = match result { - Ok(instance_idx) => instance_idx, + Ok(instance) => instance.register(&mut self.sandbox_store_mut(), dispatch_thunk), Err(sandbox::InstantiationError::StartTrapped) => sandbox_primitives::ERR_EXECUTION, Err(_) => sandbox_primitives::ERR_MODULE, }; @@ -312,20 +313,19 @@ impl<'a, 'b, 'c> Sandbox for HostContext<'a, 'b, 'c> { instance_idx: u32, name: &str, ) -> sp_wasm_interface::Result> { - self.sandbox_store - .borrow() + self.sandbox_store() .instance(instance_idx) .map(|i| i.get_global_val(name)) .map_err(|e| e.to_string()) } } -struct SandboxContext<'a, 'b, 'c, 'd> { - host_context: &'a mut HostContext<'b, 'c, 'd>, +struct SandboxContext<'a, 'b, 'c> { + host_context: &'a mut HostContext<'b, 'c>, dispatch_thunk: Func, } -impl<'a, 'b, 'c, 'd> sandbox::SandboxContext for SandboxContext<'a, 'b, 'c, 'd> { +impl<'a, 'b, 'c> sandbox::SandboxContext for SandboxContext<'a, 'b, 'c> { fn invoke( &mut self, invoke_args_ptr: Pointer, diff --git a/client/executor/wasmtime/src/imports.rs b/client/executor/wasmtime/src/imports.rs index a00ab14263e7..57ce48f537e9 100644 --- a/client/executor/wasmtime/src/imports.rs +++ b/client/executor/wasmtime/src/imports.rs @@ -17,6 +17,7 @@ // along with this program. If not, see . use crate::{ + host::HostContext, runtime::{Store, StoreData}, util, }; @@ -191,19 +192,7 @@ fn call_static<'a>( mut caller: Caller<'a, StoreData>, ) -> Result<(), wasmtime::Trap> { let unwind_result = { - let host_state = caller - .data() - .host_state() - .expect( - "host functions can be called only from wasm instance; - wasm instance is always called initializing context; - therefore host_ctx cannot be None; - qed - ", - ) - .clone(); - - let mut host_ctx = host_state.materialize(&mut caller); + let mut host_ctx = HostContext { caller: &mut caller }; // `from_wasmtime_val` panics if it encounters a value that doesn't fit into the values // available in substrate. diff --git a/client/executor/wasmtime/src/instance_wrapper.rs b/client/executor/wasmtime/src/instance_wrapper.rs index 1d40563d0a9f..e9b18d8c2b89 100644 --- a/client/executor/wasmtime/src/instance_wrapper.rs +++ b/client/executor/wasmtime/src/instance_wrapper.rs @@ -19,15 +19,12 @@ //! Defines data and logic needed for interaction with an WebAssembly instance of a substrate //! runtime module. -use crate::imports::Imports; - +use crate::runtime::{Store, StoreData}; use sc_executor_common::{ error::{Error, Result}, - util::checked_range, wasm_runtime::InvokeMethod, }; -use sp_wasm_interface::{Pointer, Value, WordSize}; -use std::marker; +use sp_wasm_interface::{Function, Pointer, Value, WordSize}; use wasmtime::{ AsContext, AsContextMut, Extern, Func, Global, Instance, Memory, Module, Table, Val, }; @@ -107,18 +104,8 @@ impl EntryPoint { /// routines. pub struct InstanceWrapper { instance: Instance, - - // The memory instance of the `instance`. - // - // It is important to make sure that we don't make any copies of this to make it easier to - // proof See `memory_as_slice` and `memory_as_slice_mut`. memory: Memory, - - /// Indirect functions table of the module - table: Option, - - // Make this struct explicitly !Send & !Sync. - _not_send_nor_sync: marker::PhantomData<*const ()>, + store: Store, } fn extern_memory(extern_: &Extern) -> Option<&Memory> { @@ -153,11 +140,36 @@ impl InstanceWrapper { /// Create a new instance wrapper from the given wasm module. pub fn new( module: &Module, - imports: &Imports, + host_functions: &[&'static dyn Function], heap_pages: u64, - mut ctx: impl AsContextMut, + allow_missing_func_imports: bool, + max_memory_size: Option, ) -> Result { - let instance = Instance::new(&mut ctx, module, &imports.externs) + let limits = if let Some(max_memory_size) = max_memory_size { + wasmtime::StoreLimitsBuilder::new().memory_size(max_memory_size).build() + } else { + Default::default() + }; + + let mut store = Store::new( + module.engine(), + StoreData { limits, host_state: None, memory: None, table: None }, + ); + if max_memory_size.is_some() { + store.limiter(|s| &mut s.limits); + } + + // Scan all imports, find the matching host functions, and create stubs that adapt arguments + // and results. + let imports = crate::imports::resolve_imports( + &mut store, + module, + host_functions, + heap_pages, + allow_missing_func_imports, + )?; + + let instance = Instance::new(&mut store, module, &imports.externs) .map_err(|e| Error::from(format!("cannot instantiate: {}", e)))?; let memory = match imports.memory_import_index { @@ -165,55 +177,56 @@ impl InstanceWrapper { .expect("only memory can be at the `memory_idx`; qed") .clone(), None => { - let memory = get_linear_memory(&instance, &mut ctx)?; - if !memory.grow(&mut ctx, heap_pages).is_ok() { + let memory = get_linear_memory(&instance, &mut store)?; + if !memory.grow(&mut store, heap_pages).is_ok() { return Err("failed top increase the linear memory size".into()) } memory }, }; - let table = get_table(&instance, ctx); + let table = get_table(&instance, &mut store); + + store.data_mut().memory = Some(memory); + store.data_mut().table = table; - Ok(Self { table, instance, memory, _not_send_nor_sync: marker::PhantomData }) + Ok(Self { instance, memory, store }) } /// Resolves a substrate entrypoint by the given name. /// /// An entrypoint must have a signature `(i32, i32) -> i64`, otherwise this function will return /// an error. - pub fn resolve_entrypoint( - &self, - method: InvokeMethod, - mut ctx: impl AsContextMut, - ) -> Result { + pub fn resolve_entrypoint(&mut self, method: InvokeMethod) -> Result { Ok(match method { InvokeMethod::Export(method) => { // Resolve the requested method and verify that it has a proper signature. - let export = self.instance.get_export(&mut ctx, method).ok_or_else(|| { - Error::from(format!("Exported method {} is not found", method)) - })?; + let export = + self.instance.get_export(&mut self.store, method).ok_or_else(|| { + Error::from(format!("Exported method {} is not found", method)) + })?; let func = extern_func(&export) .ok_or_else(|| Error::from(format!("Export {} is not a function", method)))? .clone(); - EntryPoint::direct(func, ctx).map_err(|_| { + EntryPoint::direct(func, &self.store).map_err(|_| { Error::from(format!("Exported function '{}' has invalid signature.", method)) })? }, InvokeMethod::Table(func_ref) => { let table = self .instance - .get_table(&mut ctx, "__indirect_function_table") + .get_table(&mut self.store, "__indirect_function_table") .ok_or(Error::NoTable)?; - let val = - table.get(&mut ctx, func_ref).ok_or(Error::NoTableEntryWithIndex(func_ref))?; + let val = table + .get(&mut self.store, func_ref) + .ok_or(Error::NoTableEntryWithIndex(func_ref))?; let func = val .funcref() .ok_or(Error::TableElementIsNotAFunction(func_ref))? .ok_or(Error::FunctionRefIsNull(func_ref))? .clone(); - EntryPoint::direct(func, ctx).map_err(|_| { + EntryPoint::direct(func, &self.store).map_err(|_| { Error::from(format!( "Function @{} in exported table has invalid signature for direct call.", func_ref, @@ -223,10 +236,10 @@ impl InstanceWrapper { InvokeMethod::TableWithWrapper { dispatcher_ref, func } => { let table = self .instance - .get_table(&mut ctx, "__indirect_function_table") + .get_table(&mut self.store, "__indirect_function_table") .ok_or(Error::NoTable)?; let val = table - .get(&mut ctx, dispatcher_ref) + .get(&mut self.store, dispatcher_ref) .ok_or(Error::NoTableEntryWithIndex(dispatcher_ref))?; let dispatcher = val .funcref() @@ -234,7 +247,7 @@ impl InstanceWrapper { .ok_or(Error::FunctionRefIsNull(dispatcher_ref))? .clone(); - EntryPoint::wrapped(dispatcher, func, ctx).map_err(|_| { + EntryPoint::wrapped(dispatcher, func, &self.store).map_err(|_| { Error::from(format!( "Function @{} in exported table has invalid signature for wrapped call.", dispatcher_ref, @@ -244,25 +257,20 @@ impl InstanceWrapper { }) } - /// Returns an indirect function table of this instance. - pub fn table(&self) -> Option<&Table> { - self.table.as_ref() - } - /// Reads `__heap_base: i32` global variable and returns it. /// /// If it doesn't exist, not a global or of not i32 type returns an error. - pub fn extract_heap_base(&self, mut ctx: impl AsContextMut) -> Result { + pub fn extract_heap_base(&mut self) -> Result { let heap_base_export = self .instance - .get_export(&mut ctx, "__heap_base") + .get_export(&mut self.store, "__heap_base") .ok_or_else(|| Error::from("__heap_base is not found"))?; let heap_base_global = extern_global(&heap_base_export) .ok_or_else(|| Error::from("__heap_base is not a global"))?; let heap_base = heap_base_global - .get(&mut ctx) + .get(&mut self.store) .i32() .ok_or_else(|| Error::from("__heap_base is not a i32"))?; @@ -270,15 +278,15 @@ impl InstanceWrapper { } /// Get the value from a global with the given `name`. - pub fn get_global_val(&self, mut ctx: impl AsContextMut, name: &str) -> Result> { - let global = match self.instance.get_export(&mut ctx, name) { + pub fn get_global_val(&mut self, name: &str) -> Result> { + let global = match self.instance.get_export(&mut self.store, name) { Some(global) => global, None => return Ok(None), }; let global = extern_global(&global).ok_or_else(|| format!("`{}` is not a global", name))?; - match global.get(ctx) { + match global.get(&mut self.store) { Val::I32(val) => Ok(Some(Value::I32(val))), Val::I64(val) => Ok(Some(Value::I64(val))), Val::F32(val) => Ok(Some(Value::F32(val))), @@ -288,8 +296,8 @@ impl InstanceWrapper { } /// Get a global with the given `name`. - pub fn get_global(&self, ctx: impl AsContextMut, name: &str) -> Option { - self.instance.get_global(ctx, name) + pub fn get_global(&mut self, name: &str) -> Option { + self.instance.get_global(&mut self.store, name) } } @@ -307,7 +315,7 @@ fn get_linear_memory(instance: &Instance, ctx: impl AsContextMut) -> Result Option
{ +fn get_table(instance: &Instance, ctx: &mut Store) -> Option
{ instance .get_export(ctx, "__indirect_function_table") .as_ref() @@ -317,97 +325,16 @@ fn get_table(instance: &Instance, ctx: impl AsContextMut) -> Option
{ /// Functions related to memory. impl InstanceWrapper { - /// Read data from a slice of memory into a newly allocated buffer. - /// - /// Returns an error if the read would go out of the memory bounds. - pub fn read_memory( - &self, - ctx: impl AsContext, - source_addr: Pointer, - size: usize, - ) -> Result> { - let range = checked_range(source_addr.into(), size, self.memory.data_size(&ctx)) - .ok_or_else(|| Error::Other("memory read is out of bounds".into()))?; - - let mut buffer = vec![0; range.len()]; - self.read_memory_into(ctx, source_addr, &mut buffer)?; - - Ok(buffer) - } - - /// Read data from the instance memory into a slice. - /// - /// Returns an error if the read would go out of the memory bounds. - pub fn read_memory_into( - &self, - ctx: impl AsContext, - address: Pointer, - dest: &mut [u8], - ) -> Result<()> { - let memory = self.memory.data(ctx.as_context()); - - let range = checked_range(address.into(), dest.len(), memory.len()) - .ok_or_else(|| Error::Other("memory read is out of bounds".into()))?; - dest.copy_from_slice(&memory[range]); - Ok(()) - } - - /// Write data to the instance memory from a slice. - /// - /// Returns an error if the write would go out of the memory bounds. - pub fn write_memory_from( - &self, - mut ctx: impl AsContextMut, - address: Pointer, - data: &[u8], - ) -> Result<()> { - let memory = self.memory.data_mut(ctx.as_context_mut()); - - let range = checked_range(address.into(), data.len(), memory.len()) - .ok_or_else(|| Error::Other("memory write is out of bounds".into()))?; - memory[range].copy_from_slice(data); - Ok(()) - } - - /// Allocate some memory of the given size. Returns pointer to the allocated memory region. - /// - /// Returns `Err` in case memory cannot be allocated. Refer to the allocator documentation - /// to get more details. - pub fn allocate( - &self, - mut ctx: impl AsContextMut, - allocator: &mut sc_allocator::FreeingBumpHeapAllocator, - size: WordSize, - ) -> Result> { - let memory = self.memory.data_mut(ctx.as_context_mut()); - - allocator.allocate(memory, size).map_err(Into::into) - } - - /// Deallocate the memory pointed by the given pointer. - /// - /// Returns `Err` in case the given memory region cannot be deallocated. - pub fn deallocate( - &self, - mut ctx: impl AsContextMut, - allocator: &mut sc_allocator::FreeingBumpHeapAllocator, - ptr: Pointer, - ) -> Result<()> { - let memory = self.memory.data_mut(ctx.as_context_mut()); - - allocator.deallocate(memory, ptr).map_err(Into::into) - } - /// Returns the pointer to the first byte of the linear memory for this instance. - pub fn base_ptr(&self, ctx: impl AsContext) -> *const u8 { - self.memory.data_ptr(ctx) + pub fn base_ptr(&self) -> *const u8 { + self.memory.data_ptr(&self.store) } /// If possible removes physical backing from the allocated linear memory which /// leads to returning the memory back to the system; this also zeroes the memory /// as a side-effect. - pub fn decommit(&self, mut ctx: impl AsContextMut) { - if self.memory.data_size(&ctx) == 0 { + pub fn decommit(&mut self) { + if self.memory.data_size(&self.store) == 0 { return } @@ -416,8 +343,8 @@ impl InstanceWrapper { use std::sync::Once; unsafe { - let ptr = self.memory.data_ptr(&ctx); - let len = self.memory.data_size(&ctx); + let ptr = self.memory.data_ptr(&self.store); + let len = self.memory.data_size(&self.store); // Linux handles MADV_DONTNEED reliably. The result is that the given area // is unmapped and will be zeroed on the next pagefault. @@ -438,6 +365,14 @@ impl InstanceWrapper { // If we're on an unsupported OS or the memory couldn't have been // decommited for some reason then just manually zero it out. - self.memory.data_mut(ctx.as_context_mut()).fill(0); + self.memory.data_mut(self.store.as_context_mut()).fill(0); + } + + pub(crate) fn store(&self) -> &Store { + &self.store + } + + pub(crate) fn store_mut(&mut self) -> &mut Store { + &mut self.store } } diff --git a/client/executor/wasmtime/src/runtime.rs b/client/executor/wasmtime/src/runtime.rs index 7808ac7ce547..606401132e9e 100644 --- a/client/executor/wasmtime/src/runtime.rs +++ b/client/executor/wasmtime/src/runtime.rs @@ -20,7 +20,6 @@ use crate::{ host::HostState, - imports::{resolve_imports, Imports}, instance_wrapper::{EntryPoint, InstanceWrapper}, util, }; @@ -37,75 +36,98 @@ use sp_runtime_interface::unpack_ptr_and_len; use sp_wasm_interface::{Function, Pointer, Value, WordSize}; use std::{ path::{Path, PathBuf}, - rc::Rc, sync::{ atomic::{AtomicBool, Ordering}, Arc, }, }; -use wasmtime::{AsContext, AsContextMut, Engine, StoreLimits}; +use wasmtime::{Engine, Memory, StoreLimits, Table}; pub(crate) struct StoreData { - /// The limits we aply to the store. We need to store it here to return a reference to this + /// The limits we apply to the store. We need to store it here to return a reference to this /// object when we have the limits enabled. - limits: StoreLimits, + pub(crate) limits: StoreLimits, /// This will only be set when we call into the runtime. - host_state: Option>, + pub(crate) host_state: Option, + /// This will be always set once the store is initialized. + pub(crate) memory: Option, + /// This will be set only if the runtime actually contains a table. + pub(crate) table: Option
, } impl StoreData { /// Returns a reference to the host state. - pub fn host_state(&self) -> Option<&Rc> { + pub fn host_state(&self) -> Option<&HostState> { self.host_state.as_ref() } + + /// Returns a mutable reference to the host state. + pub fn host_state_mut(&mut self) -> Option<&mut HostState> { + self.host_state.as_mut() + } + + /// Returns the host memory. + pub fn memory(&self) -> Memory { + self.memory.expect("memory is always set; qed") + } + + /// Returns the host table. + pub fn table(&self) -> Option
{ + self.table + } } pub(crate) type Store = wasmtime::Store; enum Strategy { FastInstanceReuse { - instance_wrapper: Rc, + instance_wrapper: InstanceWrapper, globals_snapshot: GlobalsSnapshot, data_segments_snapshot: Arc, heap_base: u32, - store: Store, }, RecreateInstance(InstanceCreator), } struct InstanceCreator { - store: Store, module: Arc, - imports: Arc, + host_functions: Vec<&'static dyn Function>, heap_pages: u64, + allow_missing_func_imports: bool, + max_memory_size: Option, } impl InstanceCreator { fn instantiate(&mut self) -> Result { - InstanceWrapper::new(&*self.module, &*self.imports, self.heap_pages, &mut self.store) + InstanceWrapper::new( + &*self.module, + &self.host_functions, + self.heap_pages, + self.allow_missing_func_imports, + self.max_memory_size, + ) } } -struct InstanceGlobals<'a, C> { - ctx: &'a mut C, - instance: &'a InstanceWrapper, +struct InstanceGlobals<'a> { + instance: &'a mut InstanceWrapper, } -impl<'a, C: AsContextMut> runtime_blob::InstanceGlobals for InstanceGlobals<'a, C> { +impl<'a> runtime_blob::InstanceGlobals for InstanceGlobals<'a> { type Global = wasmtime::Global; fn get_global(&mut self, export_name: &str) -> Self::Global { self.instance - .get_global(&mut self.ctx, export_name) + .get_global(export_name) .expect("get_global is guaranteed to be called with an export name of a global; qed") } fn get_global_value(&mut self, global: &Self::Global) -> Value { - util::from_wasmtime_val(global.get(&mut self.ctx)) + util::from_wasmtime_val(global.get(&mut self.instance.store_mut())) } fn set_global_value(&mut self, global: &Self::Global, value: Value) { - global.set(&mut self.ctx, util::into_wasmtime_val(value)).expect( + global.set(&mut self.instance.store_mut(), util::into_wasmtime_val(value)).expect( "the value is guaranteed to be of the same value; the global is guaranteed to be mutable; qed", ); } @@ -124,50 +146,19 @@ pub struct WasmtimeRuntime { snapshot_data: Option, config: Config, host_functions: Vec<&'static dyn Function>, - engine: Engine, -} - -impl WasmtimeRuntime { - /// Creates the store respecting the set limits. - fn new_store(&self) -> Store { - let limits = if let Some(max_memory_size) = self.config.max_memory_size { - wasmtime::StoreLimitsBuilder::new().memory_size(max_memory_size).build() - } else { - Default::default() - }; - - let mut store = Store::new(&self.engine, StoreData { limits, host_state: None }); - - if self.config.max_memory_size.is_some() { - store.limiter(|s| &mut s.limits); - } - - store - } } impl WasmModule for WasmtimeRuntime { fn new_instance(&self) -> Result> { - let mut store = self.new_store(); - - // Scan all imports, find the matching host functions, and create stubs that adapt arguments - // and results. - // - // NOTE: Attentive reader may notice that this could've been moved in `WasmModule` creation. - // However, I am not sure if that's a good idea since it would be pushing our luck - // further by assuming that `Store` not only `Send` but also `Sync`. - let imports = resolve_imports( - &mut store, - &self.module, - &self.host_functions, - self.config.heap_pages, - self.config.allow_missing_func_imports, - )?; - let strategy = if let Some(ref snapshot_data) = self.snapshot_data { - let instance_wrapper = - InstanceWrapper::new(&self.module, &imports, self.config.heap_pages, &mut store)?; - let heap_base = instance_wrapper.extract_heap_base(&mut store)?; + let mut instance_wrapper = InstanceWrapper::new( + &self.module, + &self.host_functions, + self.config.heap_pages, + self.config.allow_missing_func_imports, + self.config.max_memory_size, + )?; + let heap_base = instance_wrapper.extract_heap_base()?; // This function panics if the instance was created from a runtime blob different from // which the mutable globals were collected. Here, it is easy to see that there is only @@ -175,22 +166,22 @@ impl WasmModule for WasmtimeRuntime { // instance and collecting the mutable globals. let globals_snapshot = GlobalsSnapshot::take( &snapshot_data.mutable_globals, - &mut InstanceGlobals { ctx: &mut store, instance: &instance_wrapper }, + &mut InstanceGlobals { instance: &mut instance_wrapper }, ); Strategy::FastInstanceReuse { - instance_wrapper: Rc::new(instance_wrapper), + instance_wrapper, globals_snapshot, data_segments_snapshot: snapshot_data.data_segments_snapshot.clone(), heap_base, - store, } } else { Strategy::RecreateInstance(InstanceCreator { - imports: Arc::new(imports), module: self.module.clone(), - store, + host_functions: self.host_functions.clone(), heap_pages: self.config.heap_pages, + allow_missing_func_imports: self.config.allow_missing_func_imports, + max_memory_size: self.config.max_memory_size, }) }; @@ -204,68 +195,52 @@ pub struct WasmtimeInstance { strategy: Strategy, } -// This is safe because `WasmtimeInstance` does not leak reference to `self.imports` -// and all imports don't reference anything, other than host functions and memory -unsafe impl Send for WasmtimeInstance {} - impl WasmInstance for WasmtimeInstance { fn call(&mut self, method: InvokeMethod, data: &[u8]) -> Result> { match &mut self.strategy { Strategy::FastInstanceReuse { - instance_wrapper, + ref mut instance_wrapper, globals_snapshot, data_segments_snapshot, heap_base, - ref mut store, } => { - let entrypoint = instance_wrapper.resolve_entrypoint(method, &mut *store)?; + let entrypoint = instance_wrapper.resolve_entrypoint(method)?; data_segments_snapshot.apply(|offset, contents| { - instance_wrapper.write_memory_from(&mut *store, Pointer::new(offset), contents) + util::write_memory_from( + instance_wrapper.store_mut(), + Pointer::new(offset), + contents, + ) })?; - globals_snapshot - .apply(&mut InstanceGlobals { ctx: &mut *store, instance: &*instance_wrapper }); + globals_snapshot.apply(&mut InstanceGlobals { instance: instance_wrapper }); let allocator = FreeingBumpHeapAllocator::new(*heap_base); - let result = perform_call( - &mut *store, - data, - instance_wrapper.clone(), - entrypoint, - allocator, - ); + let result = perform_call(data, instance_wrapper, entrypoint, allocator); // Signal to the OS that we are done with the linear memory and that it can be // reclaimed. - instance_wrapper.decommit(store); + instance_wrapper.decommit(); result }, Strategy::RecreateInstance(ref mut instance_creator) => { - let instance_wrapper = instance_creator.instantiate()?; - let heap_base = instance_wrapper.extract_heap_base(&mut instance_creator.store)?; - let entrypoint = - instance_wrapper.resolve_entrypoint(method, &mut instance_creator.store)?; + let mut instance_wrapper = instance_creator.instantiate()?; + let heap_base = instance_wrapper.extract_heap_base()?; + let entrypoint = instance_wrapper.resolve_entrypoint(method)?; let allocator = FreeingBumpHeapAllocator::new(heap_base); - perform_call( - &mut instance_creator.store, - data, - Rc::new(instance_wrapper), - entrypoint, - allocator, - ) + perform_call(data, &mut instance_wrapper, entrypoint, allocator) }, } } fn get_global_const(&mut self, name: &str) -> Result> { match &mut self.strategy { - Strategy::FastInstanceReuse { instance_wrapper, ref mut store, .. } => - instance_wrapper.get_global_val(&mut *store, name), - Strategy::RecreateInstance(ref mut instance_creator) => instance_creator - .instantiate()? - .get_global_val(&mut instance_creator.store, name), + Strategy::FastInstanceReuse { instance_wrapper, .. } => + instance_wrapper.get_global_val(name), + Strategy::RecreateInstance(ref mut instance_creator) => + instance_creator.instantiate()?.get_global_val(name), } } @@ -276,8 +251,8 @@ impl WasmInstance for WasmtimeInstance { // associated with it. None }, - Strategy::FastInstanceReuse { instance_wrapper, store, .. } => - Some(instance_wrapper.base_ptr(&store)), + Strategy::FastInstanceReuse { instance_wrapper, .. } => + Some(instance_wrapper.base_ptr()), } } } @@ -591,7 +566,7 @@ unsafe fn do_create_runtime( }, }; - Ok(WasmtimeRuntime { module: Arc::new(module), snapshot_data, config, host_functions, engine }) + Ok(WasmtimeRuntime { module: Arc::new(module), snapshot_data, config, host_functions }) } fn instrument( @@ -627,50 +602,51 @@ pub fn prepare_runtime_artifact( } fn perform_call( - mut ctx: impl AsContextMut, data: &[u8], - instance_wrapper: Rc, + instance_wrapper: &mut InstanceWrapper, entrypoint: EntryPoint, mut allocator: FreeingBumpHeapAllocator, ) -> Result> { - let (data_ptr, data_len) = - inject_input_data(&mut ctx, &instance_wrapper, &mut allocator, data)?; + let (data_ptr, data_len) = inject_input_data(instance_wrapper, &mut allocator, data)?; - let host_state = HostState::new(allocator, instance_wrapper.clone()); + let host_state = HostState::new(allocator); // Set the host state before calling into wasm. - ctx.as_context_mut().data_mut().host_state = Some(Rc::new(host_state)); + instance_wrapper.store_mut().data_mut().host_state = Some(host_state); - let ret = entrypoint.call(&mut ctx, data_ptr, data_len).map(unpack_ptr_and_len); + let ret = entrypoint + .call(instance_wrapper.store_mut(), data_ptr, data_len) + .map(unpack_ptr_and_len); // Reset the host state - ctx.as_context_mut().data_mut().host_state = None; + instance_wrapper.store_mut().data_mut().host_state = None; let (output_ptr, output_len) = ret?; - let output = extract_output_data(ctx, &instance_wrapper, output_ptr, output_len)?; + let output = extract_output_data(instance_wrapper, output_ptr, output_len)?; Ok(output) } fn inject_input_data( - mut ctx: impl AsContextMut, - instance: &InstanceWrapper, + instance: &mut InstanceWrapper, allocator: &mut FreeingBumpHeapAllocator, data: &[u8], ) -> Result<(Pointer, WordSize)> { + let mut ctx = instance.store_mut(); + let memory = ctx.data().memory(); + let memory = memory.data_mut(&mut ctx); let data_len = data.len() as WordSize; - let data_ptr = instance.allocate(&mut ctx, allocator, data_len)?; - instance.write_memory_from(ctx, data_ptr, data)?; + let data_ptr = allocator.allocate(memory, data_len)?; + util::write_memory_from(instance.store_mut(), data_ptr, data)?; Ok((data_ptr, data_len)) } fn extract_output_data( - ctx: impl AsContext, instance: &InstanceWrapper, output_ptr: u32, output_len: u32, ) -> Result> { let mut output = vec![0; output_len as usize]; - instance.read_memory_into(ctx, Pointer::new(output_ptr), &mut output)?; + util::read_memory_into(instance.store(), Pointer::new(output_ptr), &mut output)?; Ok(output) } diff --git a/client/executor/wasmtime/src/tests.rs b/client/executor/wasmtime/src/tests.rs index 261afba0c6bc..c34cbfad1113 100644 --- a/client/executor/wasmtime/src/tests.rs +++ b/client/executor/wasmtime/src/tests.rs @@ -310,3 +310,39 @@ fn test_max_memory_pages() { ) .unwrap(); } + +// This test takes quite a while to execute in a debug build (over 6 minutes on a TR 3970x) +// so it's ignored by default unless it was compiled with `--release`. +#[cfg_attr(build_type = "debug", ignore)] +#[test] +fn test_instances_without_reuse_are_not_leaked() { + use sp_wasm_interface::HostFunctions; + + let runtime = crate::create_runtime( + RuntimeBlob::uncompress_if_needed(&wasm_binary_unwrap()[..]).unwrap(), + crate::Config { + heap_pages: 2048, + max_memory_size: None, + allow_missing_func_imports: true, + cache_path: None, + semantics: crate::Semantics { + fast_instance_reuse: false, + deterministic_stack_limit: None, + canonicalize_nans: false, + parallel_compilation: true, + }, + }, + sp_io::SubstrateHostFunctions::host_functions(), + ) + .unwrap(); + + // As long as the `wasmtime`'s `Store` lives the instances spawned through it + // will live indefinitely. Currently it has a maximum limit of 10k instances, + // so let's spawn 10k + 1 of them to make sure our code doesn't keep the `Store` + // alive longer than it is necessary. (And since we disabled instance reuse + // a new instance will be spawned on each call.) + let mut instance = runtime.new_instance().unwrap(); + for _ in 0..10001 { + instance.call_export("test_empty_return", &[0]).unwrap(); + } +} diff --git a/client/executor/wasmtime/src/util.rs b/client/executor/wasmtime/src/util.rs index 2c135fe7a343..2c9379e9ce81 100644 --- a/client/executor/wasmtime/src/util.rs +++ b/client/executor/wasmtime/src/util.rs @@ -16,7 +16,13 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use sp_wasm_interface::Value; +use crate::runtime::StoreData; +use sc_executor_common::{ + error::{Error, Result}, + util::checked_range, +}; +use sp_wasm_interface::{Pointer, Value}; +use wasmtime::{AsContext, AsContextMut}; /// Converts a [`wasmtime::Val`] into a substrate runtime interface [`Value`]. /// @@ -41,3 +47,54 @@ pub fn into_wasmtime_val(value: Value) -> wasmtime::Val { Value::F64(f_bits) => wasmtime::Val::F64(f_bits), } } + +/// Read data from a slice of memory into a newly allocated buffer. +/// +/// Returns an error if the read would go out of the memory bounds. +pub(crate) fn read_memory( + ctx: impl AsContext, + source_addr: Pointer, + size: usize, +) -> Result> { + let range = + checked_range(source_addr.into(), size, ctx.as_context().data().memory().data_size(&ctx)) + .ok_or_else(|| Error::Other("memory read is out of bounds".into()))?; + + let mut buffer = vec![0; range.len()]; + read_memory_into(ctx, source_addr, &mut buffer)?; + + Ok(buffer) +} + +/// Read data from the instance memory into a slice. +/// +/// Returns an error if the read would go out of the memory bounds. +pub(crate) fn read_memory_into( + ctx: impl AsContext, + address: Pointer, + dest: &mut [u8], +) -> Result<()> { + let memory = ctx.as_context().data().memory().data(&ctx); + + let range = checked_range(address.into(), dest.len(), memory.len()) + .ok_or_else(|| Error::Other("memory read is out of bounds".into()))?; + dest.copy_from_slice(&memory[range]); + Ok(()) +} + +/// Write data to the instance memory from a slice. +/// +/// Returns an error if the write would go out of the memory bounds. +pub(crate) fn write_memory_from( + mut ctx: impl AsContextMut, + address: Pointer, + data: &[u8], +) -> Result<()> { + let memory = ctx.as_context().data().memory(); + let memory = memory.data_mut(&mut ctx); + + let range = checked_range(address.into(), data.len(), memory.len()) + .ok_or_else(|| Error::Other("memory write is out of bounds".into()))?; + memory[range].copy_from_slice(data); + Ok(()) +} From fe7c02941122bbe4a7956aff53739b62f575240d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Tue, 23 Nov 2021 09:39:43 +0100 Subject: [PATCH 220/695] frame-benchmarking: Fix `min-square` for `--steps=1` (#10323) --- frame/benchmarking/src/analysis.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frame/benchmarking/src/analysis.rs b/frame/benchmarking/src/analysis.rs index 5ffb6e93c8fc..6e0ffd23ee98 100644 --- a/frame/benchmarking/src/analysis.rs +++ b/frame/benchmarking/src/analysis.rs @@ -199,7 +199,7 @@ impl Analysis { } pub fn min_squares_iqr(r: &Vec, selector: BenchmarkSelector) -> Option { - if r[0].components.is_empty() { + if r[0].components.len() <= 1 { return Self::median_value(r, selector) } From 09252188126a94a40eae47b694a6c9d8f6f35662 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Tue, 23 Nov 2021 10:19:05 +0100 Subject: [PATCH 221/695] Put back consensus_engine, only accept its absence (#10345) --- client/chain-spec/src/chain_spec.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/client/chain-spec/src/chain_spec.rs b/client/chain-spec/src/chain_spec.rs index 8d8f62a5182c..e8247d731499 100644 --- a/client/chain-spec/src/chain_spec.rs +++ b/client/chain-spec/src/chain_spec.rs @@ -168,7 +168,9 @@ struct ClientSpec { #[serde(flatten)] extensions: E, // Never used, left only for backward compatibility. - #[serde(default, skip_serializing)] + // In a future version, a `skip_serializing` attribute should be added in order to no longer + // generate chain specs with this field. + #[serde(default)] consensus_engine: (), #[serde(skip_serializing)] #[allow(unused)] From 1d74e58d2c448a056e915f1672bc87c428e09cb0 Mon Sep 17 00:00:00 2001 From: Guillaume Thiolliere Date: Tue, 23 Nov 2021 19:06:33 +0900 Subject: [PATCH 222/695] fix (#10342) --- frame/contracts/src/storage.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frame/contracts/src/storage.rs b/frame/contracts/src/storage.rs index 41db0796717e..2b994d66af7e 100644 --- a/frame/contracts/src/storage.rs +++ b/frame/contracts/src/storage.rs @@ -182,7 +182,7 @@ where let outcome = child::kill_storage(&child_trie_info(&trie.trie_id), Some(remaining_key_budget)); let keys_removed = match outcome { - // This should not happen as our budget was large enough to remove all keys. + // This happens when our budget wasn't large enough to remove all keys. KillStorageResult::SomeRemaining(count) => count, KillStorageResult::AllRemoved(count) => { // We do not care to preserve order. The contract is deleted already and From c3de64869fc30da61ecb149b7903debddc46940e Mon Sep 17 00:00:00 2001 From: Guillaume Thiolliere Date: Tue, 23 Nov 2021 19:28:58 +0900 Subject: [PATCH 223/695] remove unused file (#10343) --- client/network/src/gossip.rs | 229 -------------------------- client/network/src/gossip/tests.rs | 250 ----------------------------- 2 files changed, 479 deletions(-) delete mode 100644 client/network/src/gossip.rs delete mode 100644 client/network/src/gossip/tests.rs diff --git a/client/network/src/gossip.rs b/client/network/src/gossip.rs deleted file mode 100644 index 0bc46b2164bc..000000000000 --- a/client/network/src/gossip.rs +++ /dev/null @@ -1,229 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2017-2021 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 . - -//! Helper for sending rate-limited gossip messages. -//! -//! # Context -//! -//! The [`NetworkService`] struct provides a way to send notifications to a certain peer through -//! the [`NetworkService::notification_sender`] method. This method is quite low level and isn't -//! expected to be used directly. -//! -//! The [`QueuedSender`] struct provided by this module is built on top of -//! [`NetworkService::notification_sender`] and provides a cleaner way to send notifications. -//! -//! # Behaviour -//! -//! An instance of [`QueuedSender`] is specific to a certain combination of `PeerId` and -//! protocol name. It maintains a buffer of messages waiting to be sent out. The user of this API -//! is able to manipulate that queue, adding or removing obsolete messages. -//! -//! Creating a [`QueuedSender`] also returns a opaque `Future` whose responsibility it to -//! drain that queue and actually send the messages. If the substream with the given combination -//! of peer and protocol is closed, the queue is silently discarded. It is the role of the user -//! to track which peers we are connected to. -//! -//! In normal situations, messages sent through a [`QueuedSender`] will arrive in the same -//! order as they have been sent. -//! It is possible, in the situation of disconnects and reconnects, that messages arrive in a -//! different order. See also . -//! However, if multiple instances of [`QueuedSender`] exist for the same peer and protocol, or -//! if some other code uses the [`NetworkService`] to send notifications to this combination or -//! peer and protocol, then the notifications will be interleaved in an unpredictable way. -//! - -use crate::{ExHashT, NetworkService}; - -use async_std::sync::{Mutex, MutexGuard}; -use futures::prelude::*; -use futures::channel::mpsc::{channel, Receiver, Sender}; -use libp2p::PeerId; -use sp_runtime::traits::Block as BlockT; -use std::{ - borrow::Cow, - collections::VecDeque, - fmt, - sync::Arc, -}; - -#[cfg(test)] -mod tests; - -/// Notifications sender for a specific combination of network service, peer, and protocol. -pub struct QueuedSender { - /// Shared between the user-facing [`QueuedSender`] and the background future. - shared_message_queue: SharedMessageQueue, - /// Used to notify the background future to check for new messages in the message queue. - notify_background_future: Sender<()>, - /// Maximum number of elements in [`QueuedSender::shared_message_queue`]. - queue_size_limit: usize, -} - -impl QueuedSender { - /// Returns a new [`QueuedSender`] containing a queue of message for this specific - /// combination of peer and protocol. - /// - /// In addition to the [`QueuedSender`], also returns a `Future` whose role is to drive - /// the messages sending forward. - pub fn new( - service: Arc>, - peer_id: PeerId, - protocol: Cow<'static, str>, - queue_size_limit: usize, - messages_encode: F - ) -> (Self, impl Future + Send + 'static) - where - M: Send + 'static, - B: BlockT + 'static, - H: ExHashT, - F: Fn(M) -> Vec + Send + 'static, - { - let (notify_background_future, wait_for_sender) = channel(0); - - let shared_message_queue = Arc::new(Mutex::new( - VecDeque::with_capacity(queue_size_limit), - )); - - let background_future = create_background_future( - wait_for_sender, - service, - peer_id, - protocol, - shared_message_queue.clone(), - messages_encode - ); - - let sender = Self { - shared_message_queue, - notify_background_future, - queue_size_limit, - }; - - (sender, background_future) - } - - /// Locks the queue of messages towards this peer. - /// - /// The returned `Future` is expected to be ready quite quickly. - pub async fn lock_queue<'a>(&'a mut self) -> QueueGuard<'a, M> { - QueueGuard { - message_queue: self.shared_message_queue.lock().await, - queue_size_limit: self.queue_size_limit, - notify_background_future: &mut self.notify_background_future, - } - } - - /// Pushes a message to the queue, or discards it if the queue is full. - /// - /// The returned `Future` is expected to be ready quite quickly. - pub async fn queue_or_discard(&mut self, message: M) - where - M: Send + 'static - { - self.lock_queue().await.push_or_discard(message); - } -} - -impl fmt::Debug for QueuedSender { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("QueuedSender").finish() - } -} - -/// Locked queue of messages to the given peer. -/// -/// As long as this struct exists, the background future is asleep and the owner of the -/// [`QueueGuard`] is in total control of the message queue. Messages can only ever be sent out on -/// the network after the [`QueueGuard`] is dropped. -#[must_use] -pub struct QueueGuard<'a, M> { - message_queue: MutexGuard<'a, MessageQueue>, - /// Same as [`QueuedSender::queue_size_limit`]. - queue_size_limit: usize, - notify_background_future: &'a mut Sender<()>, -} - -impl<'a, M: Send + 'static> QueueGuard<'a, M> { - /// Pushes a message to the queue, or discards it if the queue is full. - /// - /// The message will only start being sent out after the [`QueueGuard`] is dropped. - pub fn push_or_discard(&mut self, message: M) { - if self.message_queue.len() < self.queue_size_limit { - self.message_queue.push_back(message); - } - } - - /// Calls `filter` for each message in the queue, and removes the ones for which `false` is - /// returned. - /// - /// > **Note**: The parameter of `filter` is a `&M` and not a `&mut M` (which would be - /// > better) because the underlying implementation relies on `VecDeque::retain`. - pub fn retain(&mut self, filter: impl FnMut(&M) -> bool) { - self.message_queue.retain(filter); - } -} - -impl<'a, M> Drop for QueueGuard<'a, M> { - fn drop(&mut self) { - // Notify background future to check for new messages in the message queue. - let _ = self.notify_background_future.try_send(()); - } -} - -type MessageQueue = VecDeque; - -/// [`MessageQueue`] shared between [`QueuedSender`] and background future. -type SharedMessageQueue = Arc>>; - -async fn create_background_future Vec>( - mut wait_for_sender: Receiver<()>, - service: Arc>, - peer_id: PeerId, - protocol: Cow<'static, str>, - shared_message_queue: SharedMessageQueue, - messages_encode: F, -) { - loop { - if wait_for_sender.next().await.is_none() { - return - } - - loop { - let mut queue_guard = shared_message_queue.lock().await; - let next_message = match queue_guard.pop_front() { - Some(msg) => msg, - None => break, - }; - drop(queue_guard); - - // Starting from below, we try to send the message. If an error happens when sending, - // the only sane option we have is to silently discard the message. - let sender = match service.notification_sender(peer_id.clone(), protocol.clone()) { - Ok(s) => s, - Err(_) => continue, - }; - - let ready = match sender.ready().await { - Ok(r) => r, - Err(_) => continue, - }; - - let _ = ready.send(messages_encode(next_message)); - } - } -} diff --git a/client/network/src/gossip/tests.rs b/client/network/src/gossip/tests.rs deleted file mode 100644 index 88c4160bc506..000000000000 --- a/client/network/src/gossip/tests.rs +++ /dev/null @@ -1,250 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2017-2021 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 . - -use crate::block_request_handler::BlockRequestHandler; -use crate::state_request_handler::StateRequestHandler; -use crate::light_client_requests::handler::LightClientRequestHandler; -use crate::gossip::QueuedSender; -use crate::{config, Event, NetworkService, NetworkWorker}; - -use futures::prelude::*; -use sp_runtime::traits::{Block as BlockT, Header as _}; -use std::{borrow::Cow, sync::Arc, time::Duration}; -use substrate_test_runtime_client::{TestClientBuilder, TestClientBuilderExt as _}; - -type TestNetworkService = NetworkService< - substrate_test_runtime_client::runtime::Block, - substrate_test_runtime_client::runtime::Hash, ->; - -/// Builds a full node to be used for testing. Returns the node service and its associated events -/// stream. -/// -/// > **Note**: We return the events stream in order to not possibly lose events between the -/// > construction of the service and the moment the events stream is grabbed. -fn build_test_full_node(network_config: config::NetworkConfiguration) - -> (Arc, impl Stream) -{ - let client = Arc::new( - TestClientBuilder::with_default_backend() - .build_with_longest_chain() - .0, - ); - - #[derive(Clone)] - struct PassThroughVerifier(bool); - - #[async_trait::async_trait] - impl sc_consensus::Verifier for PassThroughVerifier { - async fn verify( - &mut self, - mut block: sp_consensus::BlockImportParams, - ) -> Result< - ( - sc_consensus::BlockImportParams, - Option)>>, - ), - String, - > { - let maybe_keys = block.header - .digest() - .log(|l| { - l.try_as_raw(sp_runtime::generic::OpaqueDigestItemId::Consensus(b"aura")) - .or_else(|| { - l.try_as_raw(sp_runtime::generic::OpaqueDigestItemId::Consensus(b"babe")) - }) - }) - .map(|blob| { - vec![( - sp_blockchain::well_known_cache_keys::AUTHORITIES, - blob.to_vec(), - )] - }); - - block.finalized = self.0; - block.fork_choice = Some(sc_consensus::ForkChoiceStrategy::LongestChain); - Ok((block, maybe_keys)) - } - } - - let import_queue = Box::new(sc_consensus::BasicQueue::new( - PassThroughVerifier(false), - Box::new(client.clone()), - None, - &sp_core::testing::TaskExecutor::new(), - None, - )); - - let protocol_id = config::ProtocolId::from("/test-protocol-name"); - - let block_request_protocol_config = { - let (handler, protocol_config) = BlockRequestHandler::new( - &protocol_id, - client.clone(), - 50, - ); - async_std::task::spawn(handler.run().boxed()); - protocol_config - }; - - let state_request_protocol_config = { - let (handler, protocol_config) = StateRequestHandler::new( - &protocol_id, - client.clone(), - 50, - ); - async_std::task::spawn(handler.run().boxed()); - protocol_config - }; - - let light_client_request_protocol_config = { - let (handler, protocol_config) = LightClientRequestHandler::new( - &protocol_id, - client.clone(), - ); - async_std::task::spawn(handler.run().boxed()); - protocol_config - }; - - let worker = NetworkWorker::new(config::Params { - role: config::Role::Full, - executor: None, - transactions_handler_executor: Box::new(|task| { async_std::task::spawn(task); }), - network_config, - chain: client.clone(), - on_demand: None, - transaction_pool: Arc::new(crate::config::EmptyTransactionPool), - protocol_id, - import_queue, - block_announce_validator: Box::new( - sp_consensus::block_validation::DefaultBlockAnnounceValidator, - ), - metrics_registry: None, - block_request_protocol_config, - state_request_protocol_config, - light_client_request_protocol_config, - warp_sync: None, - }) - .unwrap(); - - let service = worker.service().clone(); - let event_stream = service.event_stream("test"); - - async_std::task::spawn(async move { - futures::pin_mut!(worker); - let _ = worker.await; - }); - - (service, event_stream) -} - -const PROTOCOL_NAME: Cow<'static, str> = Cow::Borrowed("/foo"); - -/// Builds two nodes and their associated events stream. -/// The nodes are connected together and have the `PROTOCOL_NAME` protocol registered. -fn build_nodes_one_proto() - -> (Arc, impl Stream, Arc, impl Stream) -{ - let listen_addr = config::build_multiaddr![Memory(rand::random::())]; - - let (node1, events_stream1) = build_test_full_node(config::NetworkConfiguration { - extra_sets: vec![ - config::NonDefaultSetConfig { - notifications_protocol: PROTOCOL_NAME, - fallback_names: Vec::new(), - max_notification_size: 1024 * 1024, - set_config: Default::default() - } - ], - listen_addresses: vec![listen_addr.clone()], - transport: config::TransportConfig::MemoryOnly, - .. config::NetworkConfiguration::new_local() - }); - - let (node2, events_stream2) = build_test_full_node(config::NetworkConfiguration { - listen_addresses: vec![], - extra_sets: vec![ - config::NonDefaultSetConfig { - notifications_protocol: PROTOCOL_NAME, - fallback_names: Vec::new(), - max_notification_size: 1024 * 1024, - set_config: config::SetConfig { - reserved_nodes: vec![config::MultiaddrWithPeerId { - multiaddr: listen_addr, - peer_id: node1.local_peer_id().clone(), - }], - .. Default::default() - }, - } - ], - transport: config::TransportConfig::MemoryOnly, - .. config::NetworkConfiguration::new_local() - }); - - (node1, events_stream1, node2, events_stream2) -} - -#[test] -fn basic_works() { - const NUM_NOTIFS: usize = 256; - - let (node1, mut events_stream1, node2, mut events_stream2) = build_nodes_one_proto(); - let node2_id = node2.local_peer_id().clone(); - - let receiver = async_std::task::spawn(async move { - let mut received_notifications = 0; - - while received_notifications < NUM_NOTIFS { - match events_stream2.next().await.unwrap() { - Event::NotificationStreamClosed { .. } => panic!(), - Event::NotificationsReceived { messages, .. } => { - for message in messages { - assert_eq!(message.0, PROTOCOL_NAME); - assert_eq!(message.1, &b"message"[..]); - received_notifications += 1; - } - } - _ => {} - }; - - if rand::random::() < 2 { - async_std::task::sleep(Duration::from_millis(rand::random::() % 750)).await; - } - } - }); - - async_std::task::block_on(async move { - let (mut sender, bg_future) = - QueuedSender::new(node1, node2_id, PROTOCOL_NAME, NUM_NOTIFS, |msg| msg); - async_std::task::spawn(bg_future); - - // Wait for the `NotificationStreamOpened`. - loop { - match events_stream1.next().await.unwrap() { - Event::NotificationStreamOpened { .. } => break, - _ => {} - }; - } - - for _ in 0..NUM_NOTIFS { - sender.queue_or_discard(b"message".to_vec()).await; - } - - receiver.await; - }); -} From 7a531b08ae8ea975dc868ed2a6fa4f4856c0816a Mon Sep 17 00:00:00 2001 From: Xavier Lau Date: Tue, 23 Nov 2021 21:04:05 +0800 Subject: [PATCH 224/695] Support MMR Pruning (#9700) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Use `0.3.2` * Replace `u64` with `NodeIndex` * Fix Typo * Add Pruning Logic * Fix Some Tests * Remove Comment * Log Only Under STD * Return while No Element to Append * Optimize Pruning Algorithm * Update Doc * Update Doc * Zero Copy Algorithm * Import Missing Type * Fix Merge Mistake * Import Missing Item * Make `verify` Off-Chain * `cargo fmt` * Avoid using NodeIndex in incorrect places. * Simplify pruning. * Format Co-authored-by: Tomasz Drwięga --- Cargo.lock | 4 +- bin/node/runtime/src/lib.rs | 2 +- frame/merkle-mountain-range/Cargo.toml | 2 +- .../primitives/src/lib.rs | 16 ++- frame/merkle-mountain-range/rpc/src/lib.rs | 6 +- .../merkle-mountain-range/src/benchmarking.rs | 2 +- frame/merkle-mountain-range/src/lib.rs | 14 +-- frame/merkle-mountain-range/src/mmr/mmr.rs | 14 +-- .../merkle-mountain-range/src/mmr/storage.rs | 99 +++++++++++++++---- frame/merkle-mountain-range/src/mmr/utils.rs | 14 +-- frame/merkle-mountain-range/src/tests.rs | 49 +++++++-- 11 files changed, 163 insertions(+), 59 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a45e0accd49b..0091223b09e6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -936,9 +936,9 @@ dependencies = [ [[package]] name = "ckb-merkle-mountain-range" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e486fe53bb9f2ca0f58cb60e8679a5354fd6687a839942ef0a75967250289ca6" +checksum = "4f061f97d64fd1822664bdfb722f7ae5469a97b77567390f7442be5b5dc82a5b" dependencies = [ "cfg-if 0.1.10", ] diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 5b3c0685d1a2..299b7257f9d4 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -1559,7 +1559,7 @@ impl_runtime_apis! { Block, mmr::Hash, > for Runtime { - fn generate_proof(leaf_index: u64) + fn generate_proof(leaf_index: pallet_mmr::primitives::LeafIndex) -> Result<(mmr::EncodableOpaqueLeaf, mmr::Proof), mmr::Error> { Mmr::generate_proof(leaf_index) diff --git a/frame/merkle-mountain-range/Cargo.toml b/frame/merkle-mountain-range/Cargo.toml index ca09725769ab..2ff8b16fa4bd 100644 --- a/frame/merkle-mountain-range/Cargo.toml +++ b/frame/merkle-mountain-range/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -mmr-lib = { package = "ckb-merkle-mountain-range", default-features = false, version = "0.3.1" } +mmr-lib = { package = "ckb-merkle-mountain-range", default-features = false, version = "0.3.2" } sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } diff --git a/frame/merkle-mountain-range/primitives/src/lib.rs b/frame/merkle-mountain-range/primitives/src/lib.rs index dac57bd42cd3..9aae26508f3c 100644 --- a/frame/merkle-mountain-range/primitives/src/lib.rs +++ b/frame/merkle-mountain-range/primitives/src/lib.rs @@ -26,6 +26,16 @@ use sp_std::fmt; #[cfg(not(feature = "std"))] use sp_std::prelude::Vec; +/// A type to describe node position in the MMR (node index). +pub type NodeIndex = u64; + +/// A type to describe leaf position in the MMR. +/// +/// Note this is different from [`NodeIndex`], which can be applied to +/// both leafs and inner nodes. Leafs will always have consecutive `LeafIndex`, +/// but might be actually at different positions in the MMR `NodeIndex`. +pub type LeafIndex = u64; + /// A provider of the MMR's leaf data. pub trait LeafDataProvider { /// A type that should end up in the leaf of MMR. @@ -275,9 +285,9 @@ impl_leaf_data_for_tuple!(A:0, B:1, C:2, D:3, E:4); #[derive(codec::Encode, codec::Decode, RuntimeDebug, Clone, PartialEq, Eq)] pub struct Proof { /// The index of the leaf the proof is for. - pub leaf_index: u64, + pub leaf_index: LeafIndex, /// Number of leaves in MMR, when the proof was generated. - pub leaf_count: u64, + pub leaf_count: NodeIndex, /// Proof elements (hashes of siblings of inner nodes on the path to the leaf). pub items: Vec, } @@ -402,7 +412,7 @@ sp_api::decl_runtime_apis! { /// API to interact with MMR pallet. pub trait MmrApi { /// Generate MMR proof for a leaf under given index. - fn generate_proof(leaf_index: u64) -> Result<(EncodableOpaqueLeaf, Proof), Error>; + fn generate_proof(leaf_index: LeafIndex) -> Result<(EncodableOpaqueLeaf, Proof), Error>; /// Verify MMR proof against on-chain MMR. /// diff --git a/frame/merkle-mountain-range/rpc/src/lib.rs b/frame/merkle-mountain-range/rpc/src/lib.rs index 4719893778f6..004a70a8e962 100644 --- a/frame/merkle-mountain-range/rpc/src/lib.rs +++ b/frame/merkle-mountain-range/rpc/src/lib.rs @@ -32,7 +32,7 @@ use sp_blockchain::HeaderBackend; use sp_core::Bytes; use sp_runtime::{generic::BlockId, traits::Block as BlockT}; -pub use pallet_mmr_primitives::MmrApi as MmrRuntimeApi; +pub use pallet_mmr_primitives::{LeafIndex, MmrApi as MmrRuntimeApi}; /// Retrieved MMR leaf and its proof. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] @@ -71,7 +71,7 @@ pub trait MmrApi { #[rpc(name = "mmr_generateProof")] fn generate_proof( &self, - leaf_index: u64, + leaf_index: LeafIndex, at: Option, ) -> Result>; } @@ -98,7 +98,7 @@ where { fn generate_proof( &self, - leaf_index: u64, + leaf_index: LeafIndex, at: Option<::Hash>, ) -> Result::Hash>> { let api = self.client.runtime_api(); diff --git a/frame/merkle-mountain-range/src/benchmarking.rs b/frame/merkle-mountain-range/src/benchmarking.rs index d6ef76d01ac3..7c0dae26b337 100644 --- a/frame/merkle-mountain-range/src/benchmarking.rs +++ b/frame/merkle-mountain-range/src/benchmarking.rs @@ -25,7 +25,7 @@ benchmarks_instance_pallet! { on_initialize { let x in 1 .. 1_000; - let leaves = x as u64; + let leaves = x as NodeIndex; }: { for b in 0..leaves { Pallet::::on_initialize((b as u32).into()); diff --git a/frame/merkle-mountain-range/src/lib.rs b/frame/merkle-mountain-range/src/lib.rs index 01bf1b2254f0..12577880c560 100644 --- a/frame/merkle-mountain-range/src/lib.rs +++ b/frame/merkle-mountain-range/src/lib.rs @@ -70,10 +70,10 @@ mod mock; mod tests; pub use pallet::*; -pub use pallet_mmr_primitives as primitives; +pub use pallet_mmr_primitives::{self as primitives, NodeIndex}; pub trait WeightInfo { - fn on_initialize(peaks: u64) -> Weight; + fn on_initialize(peaks: NodeIndex) -> Weight; } #[frame_support::pallet] @@ -160,7 +160,7 @@ pub mod pallet { /// Current size of the MMR (number of leaves). #[pallet::storage] #[pallet::getter(fn mmr_leaves)] - pub type NumberOfLeaves = StorageValue<_, u64, ValueQuery>; + pub type NumberOfLeaves = StorageValue<_, NodeIndex, ValueQuery>; /// Hashes of the nodes in the MMR. /// @@ -169,7 +169,7 @@ pub mod pallet { #[pallet::storage] #[pallet::getter(fn mmr_peak)] pub type Nodes, I: 'static = ()> = - StorageMap<_, Identity, u64, >::Hash, OptionQuery>; + StorageMap<_, Identity, NodeIndex, >::Hash, OptionQuery>; #[pallet::hooks] impl, I: 'static> Hooks> for Pallet { @@ -228,7 +228,7 @@ where } impl, I: 'static> Pallet { - fn offchain_key(pos: u64) -> sp_std::prelude::Vec { + fn offchain_key(pos: NodeIndex) -> sp_std::prelude::Vec { (T::INDEXING_PREFIX, pos).encode() } @@ -239,7 +239,7 @@ impl, I: 'static> Pallet { /// all the leaves to be present. /// It may return an error or panic if used incorrectly. pub fn generate_proof( - leaf_index: u64, + leaf_index: NodeIndex, ) -> Result<(LeafOf, primitives::Proof<>::Hash>), primitives::Error> { let mmr: ModuleMmr = mmr::Mmr::new(Self::mmr_leaves()); mmr.generate_proof(leaf_index) @@ -263,7 +263,7 @@ impl, I: 'static> Pallet { .log_debug("The proof has incorrect number of leaves or proof items.")) } - let mmr: ModuleMmr = mmr::Mmr::new(proof.leaf_count); + let mmr: ModuleMmr = mmr::Mmr::new(proof.leaf_count); let is_valid = mmr.verify_leaf_proof(leaf, proof)?; if is_valid { Ok(()) diff --git a/frame/merkle-mountain-range/src/mmr/mmr.rs b/frame/merkle-mountain-range/src/mmr/mmr.rs index d5036e58f432..a1963275a0cd 100644 --- a/frame/merkle-mountain-range/src/mmr/mmr.rs +++ b/frame/merkle-mountain-range/src/mmr/mmr.rs @@ -21,7 +21,7 @@ use crate::{ utils::NodesUtils, Hasher, Node, NodeOf, }, - primitives::{self, Error}, + primitives::{self, Error, NodeIndex}, Config, HashingOf, }; #[cfg(not(feature = "std"))] @@ -60,7 +60,7 @@ where Storage: mmr_lib::MMRStore>, { mmr: mmr_lib::MMR, Hasher, L>, Storage>, - leaves: u64, + leaves: NodeIndex, } impl Mmr @@ -71,7 +71,7 @@ where Storage: mmr_lib::MMRStore>, { /// Create a pointer to an existing MMR with given number of leaves. - pub fn new(leaves: u64) -> Self { + pub fn new(leaves: NodeIndex) -> Self { let size = NodesUtils::new(leaves).size(); Self { mmr: mmr_lib::MMR::new(size, Default::default()), leaves } } @@ -94,7 +94,7 @@ where /// Return the internal size of the MMR (number of nodes). #[cfg(test)] - pub fn size(&self) -> u64 { + pub fn size(&self) -> NodeIndex { self.mmr.mmr_size() } } @@ -109,7 +109,7 @@ where /// Push another item to the MMR. /// /// Returns element position (index) in the MMR. - pub fn push(&mut self, leaf: L) -> Option { + pub fn push(&mut self, leaf: L) -> Option { let position = self.mmr.push(Node::Data(leaf)).map_err(|e| Error::Push.log_error(e)).ok()?; @@ -120,7 +120,7 @@ where /// Commit the changes to underlying storage, return current number of leaves and /// calculate the new MMR's root hash. - pub fn finalize(self) -> Result<(u64, >::Hash), Error> { + pub fn finalize(self) -> Result<(NodeIndex, >::Hash), Error> { let root = self.mmr.get_root().map_err(|e| Error::GetRoot.log_error(e))?; self.mmr.commit().map_err(|e| Error::Commit.log_error(e))?; Ok((self.leaves, root.hash())) @@ -140,7 +140,7 @@ where /// (i.e. you can't run the function in the pruned storage). pub fn generate_proof( &self, - leaf_index: u64, + leaf_index: NodeIndex, ) -> Result<(L, primitives::Proof<>::Hash>), Error> { let position = mmr_lib::leaf_index_to_pos(leaf_index); let store = >::default(); diff --git a/frame/merkle-mountain-range/src/mmr/storage.rs b/frame/merkle-mountain-range/src/mmr/storage.rs index 09e24017816e..6e4bf91d802f 100644 --- a/frame/merkle-mountain-range/src/mmr/storage.rs +++ b/frame/merkle-mountain-range/src/mmr/storage.rs @@ -18,19 +18,24 @@ //! A MMR storage implementations. use codec::Encode; +use frame_support::log; +use mmr_lib::helper; +use sp_io::offchain_index; +use sp_std::iter::Peekable; #[cfg(not(feature = "std"))] -use sp_std::prelude::Vec; +use sp_std::prelude::*; use crate::{ - mmr::{Node, NodeOf}, - primitives, Config, Nodes, NumberOfLeaves, Pallet, + mmr::{utils::NodesUtils, Node, NodeOf}, + primitives::{self, NodeIndex}, + Config, Nodes, NumberOfLeaves, Pallet, }; /// A marker type for runtime-specific storage implementation. /// /// Allows appending new items to the MMR and proof verification. /// MMR nodes are appended to two different storages: -/// 1. We add nodes (leaves) hashes to the on-chain storge (see [crate::Nodes]). +/// 1. We add nodes (leaves) hashes to the on-chain storage (see [crate::Nodes]). /// 2. We add full leaves (and all inner nodes as well) into the `IndexingAPI` during block /// processing, so the values end up in the Offchain DB if indexing is enabled. pub struct RuntimeStorage; @@ -60,14 +65,14 @@ where I: 'static, L: primitives::FullLeaf + codec::Decode, { - fn get_elem(&self, pos: u64) -> mmr_lib::Result>> { + fn get_elem(&self, pos: NodeIndex) -> mmr_lib::Result>> { let key = Pallet::::offchain_key(pos); // Retrieve the element from Off-chain DB. Ok(sp_io::offchain::local_storage_get(sp_core::offchain::StorageKind::PERSISTENT, &key) .and_then(|v| codec::Decode::decode(&mut &*v).ok())) } - fn append(&mut self, _: u64, _: Vec>) -> mmr_lib::Result<()> { + fn append(&mut self, _: NodeIndex, _: Vec>) -> mmr_lib::Result<()> { panic!("MMR must not be altered in the off-chain context.") } } @@ -78,32 +83,90 @@ where I: 'static, L: primitives::FullLeaf, { - fn get_elem(&self, pos: u64) -> mmr_lib::Result>> { + fn get_elem(&self, pos: NodeIndex) -> mmr_lib::Result>> { Ok(>::get(pos).map(Node::Hash)) } - fn append(&mut self, pos: u64, elems: Vec>) -> mmr_lib::Result<()> { - let mut leaves = crate::NumberOfLeaves::::get(); - let mut size = crate::mmr::utils::NodesUtils::new(leaves).size(); + fn append(&mut self, pos: NodeIndex, elems: Vec>) -> mmr_lib::Result<()> { + if elems.is_empty() { + return Ok(()) + } + + sp_std::if_std! { + log::trace!("elems: {:?}", elems.iter().map(|elem| elem.hash()).collect::>()); + } + + let leaves = NumberOfLeaves::::get(); + let size = NodesUtils::new(leaves).size(); + if pos != size { return Err(mmr_lib::Error::InconsistentStore) } + let new_size = size + elems.len() as NodeIndex; + + // A sorted (ascending) iterator over peak indices to prune and persist. + let (peaks_to_prune, mut peaks_to_store) = peaks_to_prune_and_store(size, new_size); + + // Now we are going to iterate over elements to insert + // and keep track of the current `node_index` and `leaf_index`. + let mut leaf_index = leaves; + let mut node_index = size; + for elem in elems { - // on-chain we only store the hash (even if it's a leaf) - >::insert(size, elem.hash()); - // Indexing API is used to store the full leaf content. - let key = Pallet::::offchain_key(size); - elem.using_encoded(|elem| sp_io::offchain_index::set(&key, elem)); - size += 1; + // Indexing API is used to store the full node content (both leaf and inner). + elem.using_encoded(|elem| { + offchain_index::set(&Pallet::::offchain_key(node_index), elem) + }); + + // On-chain we are going to only store new peaks. + if peaks_to_store.next_if_eq(&node_index).is_some() { + >::insert(node_index, elem.hash()); + } + // Increase the indices. if let Node::Data(..) = elem { - leaves += 1; + leaf_index += 1; } + node_index += 1; } - NumberOfLeaves::::put(leaves); + // Update current number of leaves. + NumberOfLeaves::::put(leaf_index); + + // And remove all remaining items from `peaks_before` collection. + for pos in peaks_to_prune { + >::remove(pos); + } Ok(()) } } + +fn peaks_to_prune_and_store( + old_size: NodeIndex, + new_size: NodeIndex, +) -> (impl Iterator, Peekable>) { + // A sorted (ascending) collection of peak indices before and after insertion. + // both collections may share a common prefix. + let peaks_before = if old_size == 0 { vec![] } else { helper::get_peaks(old_size) }; + let peaks_after = helper::get_peaks(new_size); + sp_std::if_std! { + log::trace!("peaks_before: {:?}", peaks_before); + log::trace!("peaks_after: {:?}", peaks_after); + } + let mut peaks_before = peaks_before.into_iter().peekable(); + let mut peaks_after = peaks_after.into_iter().peekable(); + + // Consume a common prefix between `peaks_before` and `peaks_after`, + // since that's something we will not be touching anyway. + while peaks_before.peek() == peaks_after.peek() { + peaks_before.next(); + peaks_after.next(); + } + + // what's left in both collections is: + // 1. Old peaks to remove from storage + // 2. New peaks to persist in storage + (peaks_before, peaks_after) +} diff --git a/frame/merkle-mountain-range/src/mmr/utils.rs b/frame/merkle-mountain-range/src/mmr/utils.rs index 8fc725f11e72..77ce0e8ebbb3 100644 --- a/frame/merkle-mountain-range/src/mmr/utils.rs +++ b/frame/merkle-mountain-range/src/mmr/utils.rs @@ -17,29 +17,31 @@ //! Merkle Mountain Range utilities. +use crate::primitives::{LeafIndex, NodeIndex}; + /// MMR nodes & size -related utilities. pub struct NodesUtils { - no_of_leaves: u64, + no_of_leaves: LeafIndex, } impl NodesUtils { /// Create new instance of MMR nodes utilities for given number of leaves. - pub fn new(no_of_leaves: u64) -> Self { + pub fn new(no_of_leaves: LeafIndex) -> Self { Self { no_of_leaves } } /// Calculate number of peaks in the MMR. - pub fn number_of_peaks(&self) -> u64 { - self.number_of_leaves().count_ones() as u64 + pub fn number_of_peaks(&self) -> NodeIndex { + self.number_of_leaves().count_ones() as NodeIndex } /// Return the number of leaves in the MMR. - pub fn number_of_leaves(&self) -> u64 { + pub fn number_of_leaves(&self) -> LeafIndex { self.no_of_leaves } /// Calculate the total size of MMR (number of nodes). - pub fn size(&self) -> u64 { + pub fn size(&self) -> NodeIndex { 2 * self.no_of_leaves - self.number_of_peaks() } diff --git a/frame/merkle-mountain-range/src/tests.rs b/frame/merkle-mountain-range/src/tests.rs index 50512e928695..3faf2bfbd9c2 100644 --- a/frame/merkle-mountain-range/src/tests.rs +++ b/frame/merkle-mountain-range/src/tests.rs @@ -15,9 +15,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{mock::*, *}; +use crate::{mmr::utils, mock::*, *}; use frame_support::traits::OnInitialize; +use mmr_lib::helper; use pallet_mmr_primitives::{Compact, Proof}; use sp_core::{ offchain::{testing::TestOffchainExt, OffchainDbExt, OffchainWorkerExt}, @@ -48,6 +49,12 @@ fn new_block() -> u64 { MMR::on_initialize(number) } +fn peaks_from_leaves_count(leaves_count: NodeIndex) -> Vec { + let size = utils::NodesUtils::new(leaves_count).size(); + + helper::get_peaks(size) +} + pub(crate) fn hex(s: &str) -> H256 { s.parse().unwrap() } @@ -115,10 +122,29 @@ fn should_append_to_mmr_when_on_initialize_is_called() { ext.execute_with(|| { // when new_block(); + + // then + assert_eq!(crate::NumberOfLeaves::::get(), 1); + assert_eq!( + ( + crate::Nodes::::get(0), + crate::Nodes::::get(1), + crate::RootHash::::get(), + ), + ( + Some(hex("4320435e8c3318562dba60116bdbcc0b82ffcecb9bb39aae3300cfda3ad0b8b0")), + None, + hex("0x4320435e8c3318562dba60116bdbcc0b82ffcecb9bb39aae3300cfda3ad0b8b0"), + ) + ); + + // when new_block(); // then assert_eq!(crate::NumberOfLeaves::::get(), 2); + let peaks = peaks_from_leaves_count(2); + assert_eq!(peaks, vec![2]); assert_eq!( ( crate::Nodes::::get(0), @@ -128,8 +154,8 @@ fn should_append_to_mmr_when_on_initialize_is_called() { crate::RootHash::::get(), ), ( - Some(hex("4320435e8c3318562dba60116bdbcc0b82ffcecb9bb39aae3300cfda3ad0b8b0")), - Some(hex("ad4cbc033833612ccd4626d5f023b9dfc50a35e838514dd1f3c86f8506728705")), + None, + None, Some(hex("672c04a9cd05a644789d769daa552d35d8de7c33129f8a7cbf49e595234c4854")), None, hex("672c04a9cd05a644789d769daa552d35d8de7c33129f8a7cbf49e595234c4854"), @@ -166,14 +192,21 @@ fn should_construct_larger_mmr_correctly() { // then assert_eq!(crate::NumberOfLeaves::::get(), 7); + let peaks = peaks_from_leaves_count(7); + assert_eq!(peaks, vec![6, 9, 10]); + for i in (0..=10).filter(|p| !peaks.contains(p)) { + assert!(crate::Nodes::::get(i).is_none()); + } assert_eq!( ( - crate::Nodes::::get(0), + crate::Nodes::::get(6), + crate::Nodes::::get(9), crate::Nodes::::get(10), crate::RootHash::::get(), ), ( - Some(hex("4320435e8c3318562dba60116bdbcc0b82ffcecb9bb39aae3300cfda3ad0b8b0")), + Some(hex("ae88a0825da50e953e7a359c55fe13c8015e48d03d301b8bdfc9193874da9252")), + Some(hex("7e4316ae2ebf7c3b6821cb3a46ca8b7a4f9351a9b40fcf014bb0a4fd8e8f29da")), Some(hex("611c2174c6164952a66d985cfe1ec1a623794393e3acff96b136d198f37a648c")), hex("e45e25259f7930626431347fa4dd9aae7ac83b4966126d425ca70ab343709d2c"), ) @@ -265,11 +298,7 @@ fn should_verify() { crate::Pallet::::generate_proof(5).unwrap() }); - // Now to verify the proof, we really shouldn't require offchain storage or extension. - // Hence we initialize the storage once again, using different externalities and then - // verify. - let mut ext2 = new_test_ext(); - ext2.execute_with(|| { + ext.execute_with(|| { init_chain(7); // then assert_eq!(crate::Pallet::::verify_leaf(leaf, proof5), Ok(())); From 1d8f7bf6de1f447b706a121c83e759da807d3a01 Mon Sep 17 00:00:00 2001 From: Alexander Samusev <41779041+alvicsam@users.noreply.github.com> Date: Tue, 23 Nov 2021 17:04:06 +0100 Subject: [PATCH 225/695] [ci] Add ssh token for publishing gh-pages (#10338) * [ci] Added ssh token for publishing gh-pages * changed ssh commands for gh-pages * return github_token back to vault secrets * check simnet-tests-quick without vault secrets * remove vault secrets from simnet jobs --- .gitlab-ci.yml | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index aa275061088d..8815ab15f640 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -204,6 +204,9 @@ default: GITHUB_PR_TOKEN: vault: cicd/gitlab/parity/GITHUB_PR_TOKEN@kv file: false + GITHUB_TOKEN: + vault: cicd/gitlab/parity/GITHUB_TOKEN@kv + file: false AWS_ACCESS_KEY_ID: vault: cicd/gitlab/$CI_PROJECT_PATH/AWS_ACCESS_KEY_ID@kv file: false @@ -228,9 +231,9 @@ default: GITHUB_RELEASE_TOKEN: vault: cicd/gitlab/$CI_PROJECT_PATH/GITHUB_RELEASE_TOKEN@kv file: false - GITHUB_TOKEN: - vault: cicd/gitlab/$CI_PROJECT_PATH/GITHUB_TOKEN@kv - file: false + GITHUB_SSH_PRIV_KEY: + vault: cicd/gitlab/$CI_PROJECT_PATH/GITHUB_SSH_PRIV_KEY@kv + file: true GITHUB_USER: vault: cicd/gitlab/$CI_PROJECT_PATH/GITHUB_USER@kv file: false @@ -809,12 +812,14 @@ publish-rustdoc: # Putting spaces at the front and back to ensure we are not matching just any substring, but the # whole space-separated value. - '[[ " ${RUSTDOCS_DEPLOY_REFS} " =~ " ${CI_COMMIT_REF_NAME} " ]] || exit 0' + # setup ssh + - apt-get update && apt-get install -y ssh - rm -rf /tmp/* # Set git config - - rm -rf .git/config + - git config core.sshCommand "ssh -i ${GITHUB_SSH_PRIV_KEY} -F /dev/null -o StrictHostKeyChecking=no" - git config user.email "devops-team@parity.io" - git config user.name "${GITHUB_USER}" - - git config remote.origin.url "https://${GITHUB_TOKEN}@github.com/paritytech/${CI_PROJECT_NAME}.git" + - git config remote.origin.url "git@github.com:/paritytech/${CI_PROJECT_NAME}.git" - git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*" - git fetch origin gh-pages # Install `ejs` and generate index.html based on RUSTDOCS_DEPLOY_REFS @@ -909,7 +914,6 @@ simnet-tests: stage: deploy image: docker.io/paritytech/simnet:${SIMNET_REF} <<: *kubernetes-env - <<: *vault-secrets rules: - if: $CI_PIPELINE_SOURCE == "pipeline" when: never @@ -939,7 +943,6 @@ simnet-tests-quick: stage: deploy image: docker.io/paritytech/simnet:${SIMNET_REF} <<: *kubernetes-env - <<: *vault-secrets <<: *test-refs-no-trigger-prs-only variables: SIMNET_FEATURES: "${SIMNET_FEATURES_PATH}/quick" From 7406442bea0194ffcafc4e8d48d895d4d8d11346 Mon Sep 17 00:00:00 2001 From: Alexander Samusev <41779041+alvicsam@users.noreply.github.com> Date: Wed, 24 Nov 2021 10:42:44 +0100 Subject: [PATCH 226/695] [ci] Fix publish-rustdoc job (#10363) --- .gitlab-ci.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8815ab15f640..0982ca5b4979 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -233,7 +233,7 @@ default: file: false GITHUB_SSH_PRIV_KEY: vault: cicd/gitlab/$CI_PROJECT_PATH/GITHUB_SSH_PRIV_KEY@kv - file: true + file: false GITHUB_USER: vault: cicd/gitlab/$CI_PROJECT_PATH/GITHUB_USER@kv file: false @@ -814,9 +814,12 @@ publish-rustdoc: - '[[ " ${RUSTDOCS_DEPLOY_REFS} " =~ " ${CI_COMMIT_REF_NAME} " ]] || exit 0' # setup ssh - apt-get update && apt-get install -y ssh + - eval $(ssh-agent) + - ssh-add - <<< ${GITHUB_SSH_PRIV_KEY} + - mkdir ~/.ssh && touch ~/.ssh/known_hosts + - ssh-keyscan -t rsa github.com >> ~/.ssh/known_hosts - rm -rf /tmp/* # Set git config - - git config core.sshCommand "ssh -i ${GITHUB_SSH_PRIV_KEY} -F /dev/null -o StrictHostKeyChecking=no" - git config user.email "devops-team@parity.io" - git config user.name "${GITHUB_USER}" - git config remote.origin.url "git@github.com:/paritytech/${CI_PROJECT_NAME}.git" From 3f657a56b3c9bfe14613d213efc6570292ffaf86 Mon Sep 17 00:00:00 2001 From: Vladimir Istyufeev Date: Wed, 24 Nov 2021 14:10:40 +0300 Subject: [PATCH 227/695] Introduce temporary GitLab & GHA benchmarking jobs (#10311) * Introduce temporary bench job * Add runner label * CI: bench GHA * CI: bench GHA * CI: docs * CI: more docs * CI: run on master only Co-authored-by: Denis P --- .github/workflows/bench_gh_gl.yaml | 75 ++++++++++++++++++++++++++++++ .gitlab-ci.yml | 29 ++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 .github/workflows/bench_gh_gl.yaml diff --git a/.github/workflows/bench_gh_gl.yaml b/.github/workflows/bench_gh_gl.yaml new file mode 100644 index 000000000000..b243f7f66141 --- /dev/null +++ b/.github/workflows/bench_gh_gl.yaml @@ -0,0 +1,75 @@ +# Please do not tamper with this job, it's a part of benchmarking experiment. +# However, you absolutely can copy it into another file and redo the last job in the pipeline. +# Just make sure you won't introduce long queues to the GHA runner, we have just one at the moment. + +name: bench GHA against GitLab + +on: + push: + branches: [ master ] + +jobs: + bench_gh: + runs-on: self-hosted + env: + CARGO_INCREMENTAL: 0 + RUSTUP_HOME: /usr/local/rustup + CARGO_HOME: /usr/local/cargo + CC: clang + CXX: clang + + steps: + + - name: Cancel Previous Runs + uses: styfle/cancel-workflow-action@0.9.1 + with: + access_token: ${{ github.token }} + + - name: Install dependencies + # Template job, one can copy it to another pipeline. + run: | + apt-get update + apt-get install -y --no-install-recommends time clang + update-alternatives --install /usr/bin/cc cc /usr/bin/clang 100 + + - name: Install Rust + # Template job, one can copy it to another pipeline. + # Referance code https://github.com/paritytech/scripts/blob/master/dockerfiles/base-ci-linux/Dockerfile + # Better keep Rust versions here in sync with the CI image, otherwise the results will conflict. + run: | + curl -L "https://static.rust-lang.org/rustup/dist/x86_64-unknown-linux-gnu/rustup-init" -o rustup-init + chmod +x rustup-init + ./rustup-init -y --no-modify-path --profile minimal --default-toolchain stable + rm rustup-init + # add rustup tp PATH so it's usable right away + echo "/usr/local/cargo/bin" >> $GITHUB_PATH + source /usr/local/cargo/env + chmod -R a+w ${RUSTUP_HOME} ${CARGO_HOME} + # install nightly toolchain + rustup toolchain install nightly-2021-11-08 --profile minimal --component rustfmt clippy + # link the pinned toolchain to nightly + ln -s /usr/local/rustup/toolchains/nightly-2021-11-08-x86_64-unknown-linux-gnu /usr/local/rustup/toolchains/nightly-x86_64-unknown-linux-gnu + rustup target add wasm32-unknown-unknown + rustup target add wasm32-unknown-unknown --toolchain nightly + # show versions + rustup show + cargo --version + # remove clutter from the installations + rm -rf "${CARGO_HOME}/registry" "${CARGO_HOME}/git" + + - name: Checkout sources + uses: actions/checkout@v2 + + - name: bench-GHA-test-full-crypto-feature + # GitHub env variables reference: https://docs.github.com/en/actions/learn-github-actions/environment-variables + # The important part of the experiment is the line with `curl`: it sends the job's timing to Prometheus. + run: | + START_TIME=`date '+%s'` + cd primitives/core/ + time cargo +nightly build --verbose --no-default-features --features full_crypto + cd ../application-crypto + time cargo +nightly build --verbose --no-default-features --features full_crypto + END_TIME=`date '+%s'` + TOTAL_TIME=`expr $END_TIME - $START_TIME` + # please remove this line if you want to play with GHA runner. + curl -d "parity_github_job_time{project=\"$GITHUB_REPOSITORY\",job=\"$GITHUB_WORKFLOW\",runner=\"github\"} $TOTAL_TIME" -X POST http://vm-longterm.parity-build.parity.io/api/v1/import/prometheus diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0982ca5b4979..0b578f19d098 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -538,6 +538,35 @@ test-full-crypto-feature: - time cargo +nightly build --verbose --no-default-features --features full_crypto - sccache -s + +# Mostly same as the job above, additional instrumentation was added to push test run times +# to the time series database. +# This is temporary and will be eventually removed. +bench-test-full-crypto-feature: + stage: test + <<: *docker-env + <<: *build-refs + variables: + <<: *default-vars + RUSTFLAGS: "-Cdebug-assertions=y" + RUST_BACKTRACE: 1 + before_script: [""] + script: + # disable sccache for the bench purposes + - unset RUSTC_WRAPPER + - START_TIME=`date '+%s'` + - cd primitives/core/ + - time cargo +nightly build --verbose --no-default-features --features full_crypto + - cd ../application-crypto + - time cargo +nightly build --verbose --no-default-features --features full_crypto + - END_TIME=`date '+%s'` + - TOTAL_TIME=`expr $END_TIME - $START_TIME` + # send the job time measuring to the prometheus endpoint + - curl -d "parity_gitlab_job_time{project=\"$CI_PROJECT_PATH\",job=\"$CI_JOB_NAME\",runner=\"gitlab\"} $TOTAL_TIME" -X POST $VM_LONGTERM_URI/api/v1/import/prometheus + tags: + - linux-docker-compare + + test-wasmer-sandbox: stage: test <<: *docker-env From d732a9d82de5df570a8a849b4367365a3e18075c Mon Sep 17 00:00:00 2001 From: Alexander Popiak Date: Wed, 24 Nov 2021 14:39:11 +0100 Subject: [PATCH 228/695] derive Debug for CrateVersion and StorageVersion (#10355) --- frame/support/src/traits/metadata.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frame/support/src/traits/metadata.rs b/frame/support/src/traits/metadata.rs index 0da76f7585ac..50fb53fc5706 100644 --- a/frame/support/src/traits/metadata.rs +++ b/frame/support/src/traits/metadata.rs @@ -135,7 +135,7 @@ pub trait GetCallMetadata { } /// The version of a crate. -#[derive(RuntimeDebug, Eq, PartialEq, Encode, Decode, Clone, Copy, Default)] +#[derive(Debug, Eq, PartialEq, Encode, Decode, Clone, Copy, Default)] pub struct CrateVersion { /// The major version of the crate. pub major: u16, @@ -175,7 +175,7 @@ pub const STORAGE_VERSION_STORAGE_KEY_POSTFIX: &[u8] = b":__STORAGE_VERSION__:"; /// /// Each storage version of a pallet is stored in the state under a fixed key. See /// [`STORAGE_VERSION_STORAGE_KEY_POSTFIX`] for how this key is built. -#[derive(RuntimeDebug, Eq, PartialEq, Encode, Decode, Ord, Clone, Copy, PartialOrd, Default)] +#[derive(Debug, Eq, PartialEq, Encode, Decode, Ord, Clone, Copy, PartialOrd, Default)] pub struct StorageVersion(u16); impl StorageVersion { From c519f0f11059e14ab40c868429ba91e7d2525f33 Mon Sep 17 00:00:00 2001 From: Alexander Samusev <41779041+alvicsam@users.noreply.github.com> Date: Wed, 24 Nov 2021 16:00:03 +0100 Subject: [PATCH 229/695] [ci] Fix publish-rustdoc (#10364) --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0b578f19d098..b1987b834fef 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -842,12 +842,12 @@ publish-rustdoc: # whole space-separated value. - '[[ " ${RUSTDOCS_DEPLOY_REFS} " =~ " ${CI_COMMIT_REF_NAME} " ]] || exit 0' # setup ssh + # FIXME: add ssh to docker image - apt-get update && apt-get install -y ssh - eval $(ssh-agent) - ssh-add - <<< ${GITHUB_SSH_PRIV_KEY} - mkdir ~/.ssh && touch ~/.ssh/known_hosts - ssh-keyscan -t rsa github.com >> ~/.ssh/known_hosts - - rm -rf /tmp/* # Set git config - git config user.email "devops-team@parity.io" - git config user.name "${GITHUB_USER}" From e9fca0f4d7a65998206f29baf0133a7931452104 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Wed, 24 Nov 2021 18:20:55 +0100 Subject: [PATCH 230/695] Stabilize "seal1" seal_call (#10366) --- frame/contracts/src/wasm/mod.rs | 9 +++------ frame/contracts/src/wasm/runtime.rs | 4 ++-- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/frame/contracts/src/wasm/mod.rs b/frame/contracts/src/wasm/mod.rs index 10aa0d19a04f..6a807710a526 100644 --- a/frame/contracts/src/wasm/mod.rs +++ b/frame/contracts/src/wasm/mod.rs @@ -541,11 +541,10 @@ mod tests { } #[test] - #[cfg(feature = "unstable-interface")] fn contract_call_forward_input() { const CODE: &str = r#" (module - (import "__unstable__" "seal_call" (func $seal_call (param i32 i32 i64 i32 i32 i32 i32 i32) (result i32))) + (import "seal1" "seal_call" (func $seal_call (param i32 i32 i64 i32 i32 i32 i32 i32) (result i32))) (import "seal0" "seal_input" (func $seal_input (param i32 i32))) (import "env" "memory" (memory 1 1)) (func (export "call") @@ -596,11 +595,10 @@ mod tests { } #[test] - #[cfg(feature = "unstable-interface")] fn contract_call_clone_input() { const CODE: &str = r#" (module - (import "__unstable__" "seal_call" (func $seal_call (param i32 i32 i64 i32 i32 i32 i32 i32) (result i32))) + (import "seal1" "seal_call" (func $seal_call (param i32 i32 i64 i32 i32 i32 i32 i32) (result i32))) (import "seal0" "seal_input" (func $seal_input (param i32 i32))) (import "seal0" "seal_return" (func $seal_return (param i32 i32 i32))) (import "env" "memory" (memory 1 1)) @@ -652,11 +650,10 @@ mod tests { } #[test] - #[cfg(feature = "unstable-interface")] fn contract_call_tail_call() { const CODE: &str = r#" (module - (import "__unstable__" "seal_call" (func $seal_call (param i32 i32 i64 i32 i32 i32 i32 i32) (result i32))) + (import "seal1" "seal_call" (func $seal_call (param i32 i32 i64 i32 i32 i32 i32 i32) (result i32))) (import "env" "memory" (memory 1 1)) (func (export "call") (drop diff --git a/frame/contracts/src/wasm/runtime.rs b/frame/contracts/src/wasm/runtime.rs index 883dfd080248..204db09ed3e8 100644 --- a/frame/contracts/src/wasm/runtime.rs +++ b/frame/contracts/src/wasm/runtime.rs @@ -928,7 +928,7 @@ define_env!(Env, , // `ReturnCode::BelowSubsistenceThreshold` // `ReturnCode::TransferFailed` // `ReturnCode::NotCallable` - [__unstable__] seal_call( + [seal1] seal_call( ctx, flags: u32, callee_ptr: u32, @@ -940,7 +940,7 @@ define_env!(Env, , output_len_ptr: u32 ) -> ReturnCode => { ctx.call( - CallFlags::from_bits(flags).ok_or_else(|| "used rerved bit in CallFlags")?, + CallFlags::from_bits(flags).ok_or_else(|| "used reserved bit in CallFlags")?, callee_ptr, gas, value_ptr, From 5e2bb785dd8858c12b2c7f85f59d143507bd9819 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Wed, 24 Nov 2021 20:46:28 +0100 Subject: [PATCH 231/695] Enable wasmtime for aarch64 as well (#10367) --- bin/node/cli/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index 1bb3671d42ba..42df74100415 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -96,7 +96,7 @@ frame-benchmarking-cli = { version = "4.0.0-dev", optional = true, path = "../.. node-inspect = { version = "0.9.0-dev", optional = true, path = "../inspect" } try-runtime-cli = { version = "0.10.0-dev", optional = true, path = "../../../utils/frame/try-runtime/cli" } -[target.'cfg(target_arch="x86_64")'.dependencies] +[target.'cfg(any(target_arch="x86_64", target_arch="aarch64"))'.dependencies] node-executor = { version = "3.0.0-dev", path = "../executor", features = [ "wasmtime", ] } From 3009d322dd2f4ab019afa7b54baa02ff91be0191 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Thu, 25 Nov 2021 09:30:07 +0100 Subject: [PATCH 232/695] Don't send ForceClose repeatedly in send_sync_notification (#10348) --- .../src/protocol/notifications/handler.rs | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/client/network/src/protocol/notifications/handler.rs b/client/network/src/protocol/notifications/handler.rs index a0c49fa592b2..db0385bea8f6 100644 --- a/client/network/src/protocol/notifications/handler.rs +++ b/client/network/src/protocol/notifications/handler.rs @@ -365,10 +365,12 @@ struct NotificationsSinkInner { /// Sender to use in asynchronous contexts. Uses an asynchronous mutex. async_channel: FuturesMutex>, /// Sender to use in synchronous contexts. Uses a synchronous mutex. + /// Contains `None` if the channel was full at some point, in which case the channel will + /// be closed in the near future anyway. /// This channel has a large capacity and is meant to be used in contexts where /// back-pressure cannot be properly exerted. /// It will be removed in a future version. - sync_channel: Mutex>, + sync_channel: Mutex>>, } /// Message emitted through the [`NotificationsSink`] and processed by the background task @@ -400,14 +402,20 @@ impl NotificationsSink { /// This method will be removed in a future version. pub fn send_sync_notification<'a>(&'a self, message: impl Into>) { let mut lock = self.inner.sync_channel.lock(); - let result = - lock.try_send(NotificationsSinkMessage::Notification { message: message.into() }); - - if result.is_err() { - // Cloning the `mpsc::Sender` guarantees the allocation of an extra spot in the - // buffer, and therefore `try_send` will succeed. - let _result2 = lock.clone().try_send(NotificationsSinkMessage::ForceClose); - debug_assert!(_result2.map(|()| true).unwrap_or_else(|err| err.is_disconnected())); + + if let Some(tx) = lock.as_mut() { + let result = + tx.try_send(NotificationsSinkMessage::Notification { message: message.into() }); + + if result.is_err() { + // Cloning the `mpsc::Sender` guarantees the allocation of an extra spot in the + // buffer, and therefore `try_send` will succeed. + let _result2 = tx.clone().try_send(NotificationsSinkMessage::ForceClose); + debug_assert!(_result2.map(|()| true).unwrap_or_else(|err| err.is_disconnected())); + + // Destroy the sender in order to not send more `ForceClose` messages. + *lock = None; + } } } @@ -554,7 +562,7 @@ impl ProtocolsHandler for NotifsHandler { inner: Arc::new(NotificationsSinkInner { peer_id: self.peer_id, async_channel: FuturesMutex::new(async_tx), - sync_channel: Mutex::new(sync_tx), + sync_channel: Mutex::new(Some(sync_tx)), }), }; From 4617267aa82f63c0082592c4cd0f912bbc52b0ef Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 25 Nov 2021 11:33:33 +0300 Subject: [PATCH 233/695] Bump libp2p to 0.40.0 (#10035) * Bump libp2p to 0.40.0-rc.1 * Fix PingFailure import * Reduce the number of compilation errors (this is a FIXME commit) * Bump libp2p to 0.40.0-rc.2 * Fix sc-network::Behaviour to inject events into fields * Fix some NetworkBehaviourAction types * More fixes * More fixes * More fixes * Fix DiscoveryBehaviour * Fix PeerInfoBehaviour * Fix RequestResponsesBehaviour * Fix RequestResponsesBehaviour * Fix Notifications * Fix NetworkWorker * Fix Behaviour * Please borrowchk * Please borrowchk * Please borrowchk * Fix fmt * Cover all cases in matches * Fix some clippy warnings * Fix into_peer_id -> to_peer_id * Fix some warnings * Fix some inject_dial_failure FIXMEs * Fix DiscoveryBehaviour::inject_dial_failure * Fix RequestResponsesBehaviour::inject_dial_failure * Fix the order of inject_connection_closed PeerInfoBehaviour events * Make KademliaEvent with filtering unreachable * Fix Notifications::inject_dial_failure * Use concurrent_dial_errors in NetworkWorker * Remove commented-out RequestResponsesBehaviour::inject_addr_reach_failure * Fix tests * Dont report new PendingConnectionError and DialError variants to metrics * Bump libp2p to 0.40.0 * Add fn inject_listen_failure and inject_address_change * Review fixes --- Cargo.lock | 388 ++++++++---------- client/authority-discovery/Cargo.toml | 2 +- client/cli/Cargo.toml | 2 +- client/cli/src/commands/build_spec_cmd.rs | 2 +- client/cli/src/commands/generate_node_key.rs | 2 +- client/cli/src/commands/inspect_node_key.rs | 2 +- client/consensus/common/Cargo.toml | 2 +- client/network-gossip/Cargo.toml | 2 +- client/network/Cargo.toml | 4 +- client/network/src/behaviour.rs | 12 +- client/network/src/bitswap.rs | 14 +- client/network/src/discovery.rs | 135 ++++-- client/network/src/peer_info.rs | 98 +++-- client/network/src/protocol.rs | 36 +- .../src/protocol/notifications/behaviour.rs | 133 +++--- .../src/protocol/notifications/tests.rs | 38 +- client/network/src/request_responses.rs | 89 ++-- client/network/src/service.rs | 89 ++-- client/network/test/Cargo.toml | 2 +- client/peerset/Cargo.toml | 2 +- client/telemetry/Cargo.toml | 2 +- 21 files changed, 564 insertions(+), 492 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0091223b09e6..3e956ea462ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -545,6 +545,12 @@ dependencies = [ "sp-std", ] +[[package]] +name = "bimap" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50ae17cabbc8a38a1e3e4c1a6a664e9a09672dc14d0896fa8d865d3a5a446b07" + [[package]] name = "bincode" version = "1.3.2" @@ -1592,6 +1598,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" +[[package]] +name = "dtoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0" + [[package]] name = "dyn-clonable" version = "0.9.0" @@ -1874,12 +1886,6 @@ dependencies = [ "static_assertions", ] -[[package]] -name = "fixedbitset" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" - [[package]] name = "fixedbitset" version = "0.4.0" @@ -3388,9 +3394,9 @@ checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a" [[package]] name = "libp2p" -version = "0.39.1" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9004c06878ef8f3b4b4067e69a140d87ed20bf777287f82223e49713b36ee433" +checksum = "3bec54343492ba5940a6c555e512c6721139835d28c59bc22febece72dfd0d9d" dependencies = [ "atomic", "bytes 1.0.1", @@ -3404,12 +3410,14 @@ dependencies = [ "libp2p-identify", "libp2p-kad", "libp2p-mdns", + "libp2p-metrics", "libp2p-mplex", "libp2p-noise", "libp2p-ping", "libp2p-plaintext", "libp2p-pnet", "libp2p-relay", + "libp2p-rendezvous", "libp2p-request-response", "libp2p-swarm", "libp2p-swarm-derive", @@ -3427,9 +3435,9 @@ dependencies = [ [[package]] name = "libp2p-core" -version = "0.29.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af9b4abdeaa420593a297c8592f63fad4234f4b88dc9343b8fd8e736c35faa59" +checksum = "bef22d9bba1e8bcb7ec300073e6802943fe8abb8190431842262b5f1c30abba1" dependencies = [ "asn1_der", "bs58", @@ -3439,16 +3447,16 @@ dependencies = [ "futures 0.3.16", "futures-timer 3.0.2", "lazy_static", - "libsecp256k1 0.5.0", + "libsecp256k1", "log 0.4.14", "multiaddr", "multihash 0.14.0", "multistream-select", "parking_lot 0.11.1", "pin-project 1.0.8", - "prost 0.8.0", - "prost-build 0.8.0", - "rand 0.7.3", + "prost", + "prost-build", + "rand 0.8.4", "ring", "rw-stream-sink", "sha2 0.9.8", @@ -3461,9 +3469,9 @@ dependencies = [ [[package]] name = "libp2p-deflate" -version = "0.29.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66097fccc0b7f8579f90a03ea76ba6196332ea049fd07fd969490a06819dcdc8" +checksum = "51a800adb195f33de63f4b17b63fe64cfc23bf2c6a0d3d0d5321328664e65197" dependencies = [ "flate2", "futures 0.3.16", @@ -3472,9 +3480,9 @@ dependencies = [ [[package]] name = "libp2p-dns" -version = "0.29.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ff08b3196b85a17f202d80589e93b1660a574af67275706657fdc762e42c32" +checksum = "bb8f89d15cb6e3c5bc22afff7513b11bab7856f2872d3cfba86f7f63a06bc498" dependencies = [ "async-std-resolver", "futures 0.3.16", @@ -3486,9 +3494,9 @@ dependencies = [ [[package]] name = "libp2p-floodsub" -version = "0.30.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "404eca8720967179dac7a5b4275eb91f904a53859c69ca8d018560ad6beb214f" +checksum = "aab3d7210901ea51b7bae2b581aa34521797af8c4ec738c980bda4a06434067f" dependencies = [ "cuckoofilter", "fnv", @@ -3496,17 +3504,17 @@ dependencies = [ "libp2p-core", "libp2p-swarm", "log 0.4.14", - "prost 0.8.0", - "prost-build 0.8.0", + "prost", + "prost-build", "rand 0.7.3", "smallvec 1.7.0", ] [[package]] name = "libp2p-gossipsub" -version = "0.32.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1cc48709bcbc3a3321f08a73560b4bbb4166a7d56f6fdb615bc775f4f91058e" +checksum = "dfeead619eb5dac46e65acc78c535a60aaec803d1428cca6407c3a4fc74d698d" dependencies = [ "asynchronous-codec 0.6.0", "base64 0.13.0", @@ -3518,8 +3526,8 @@ dependencies = [ "libp2p-core", "libp2p-swarm", "log 0.4.14", - "prost 0.8.0", - "prost-build 0.8.0", + "prost", + "prost-build", "rand 0.7.3", "regex", "sha2 0.9.8", @@ -3530,25 +3538,26 @@ dependencies = [ [[package]] name = "libp2p-identify" -version = "0.30.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7b61f6cf07664fb97016c318c4d4512b3dd4cc07238607f3f0163245f99008e" +checksum = "cca1275574183f288ff8b72d535d5ffa5ea9292ef7829af8b47dcb197c7b0dcd" dependencies = [ "futures 0.3.16", "libp2p-core", "libp2p-swarm", "log 0.4.14", - "prost 0.8.0", - "prost-build 0.8.0", + "lru 0.6.6", + "prost", + "prost-build", "smallvec 1.7.0", "wasm-timer", ] [[package]] name = "libp2p-kad" -version = "0.31.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50ed78489c87924235665a0ab345b298ee34dff0f7ad62c0ba6608b2144fb75e" +checksum = "a2297dc0ca285f3a09d1368bde02449e539b46f94d32d53233f53f6625bcd3ba" dependencies = [ "arrayvec 0.5.2", "asynchronous-codec 0.6.0", @@ -3559,8 +3568,8 @@ dependencies = [ "libp2p-core", "libp2p-swarm", "log 0.4.14", - "prost 0.8.0", - "prost-build 0.8.0", + "prost", + "prost-build", "rand 0.7.3", "sha2 0.9.8", "smallvec 1.7.0", @@ -3572,9 +3581,9 @@ dependencies = [ [[package]] name = "libp2p-mdns" -version = "0.31.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a29e6cbc2a24b8471b6567e580a0e8e7b70a6d0f0ea2be0844d1e842d7d4fa33" +checksum = "14c864b64bdc8a84ff3910a0df88e6535f256191a450870f1e7e10cbf8e64d45" dependencies = [ "async-io", "data-encoding", @@ -3591,11 +3600,25 @@ dependencies = [ "void", ] +[[package]] +name = "libp2p-metrics" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4af432fcdd2f8ba4579b846489f8f0812cfd738ced2c0af39df9b1c48bbb6ab2" +dependencies = [ + "libp2p-core", + "libp2p-identify", + "libp2p-kad", + "libp2p-ping", + "libp2p-swarm", + "open-metrics-client", +] + [[package]] name = "libp2p-mplex" -version = "0.29.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "313d9ea526c68df4425f580024e67a9d3ffd49f2c33de5154b1f5019816f7a99" +checksum = "7f2cd64ef597f40e14bfce0497f50ecb63dd6d201c61796daeb4227078834fbf" dependencies = [ "asynchronous-codec 0.6.0", "bytes 1.0.1", @@ -3611,9 +3634,9 @@ dependencies = [ [[package]] name = "libp2p-noise" -version = "0.32.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f1db7212f342b6ba7c981cc40e31f76e9e56cb48e65fa4c142ecaca5839523e" +checksum = "a8772c7a99088221bb7ca9c5c0574bf55046a7ab4c319f3619b275f28c8fb87a" dependencies = [ "bytes 1.0.1", "curve25519-dalek 3.0.2", @@ -3621,8 +3644,8 @@ dependencies = [ "lazy_static", "libp2p-core", "log 0.4.14", - "prost 0.8.0", - "prost-build 0.8.0", + "prost", + "prost-build", "rand 0.8.4", "sha2 0.9.8", "snow", @@ -3633,9 +3656,9 @@ dependencies = [ [[package]] name = "libp2p-ping" -version = "0.30.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2482cfd9eb0b7a0baaf3e7b329dc4f2785181a161b1a47b7192f8d758f54a439" +checksum = "80ef7b0ec5cf06530d9eb6cf59ae49d46a2c45663bde31c25a12f682664adbcf" dependencies = [ "futures 0.3.16", "libp2p-core", @@ -3648,26 +3671,26 @@ dependencies = [ [[package]] name = "libp2p-plaintext" -version = "0.29.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13b4783e5423870b9a5c199f65a7a3bc66d86ab56b2b9beebf3c338d889cf8e4" +checksum = "5fba1a6ff33e4a274c89a3b1d78b9f34f32af13265cc5c46c16938262d4e945a" dependencies = [ "asynchronous-codec 0.6.0", "bytes 1.0.1", "futures 0.3.16", "libp2p-core", "log 0.4.14", - "prost 0.8.0", - "prost-build 0.8.0", + "prost", + "prost-build", "unsigned-varint 0.7.0", "void", ] [[package]] name = "libp2p-pnet" -version = "0.21.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07cb4dd4b917e5b40ddefe49b96b07adcd8d342e0317011d175b7b2bb1dcc974" +checksum = "0f1a458bbda880107b5b36fcb9b5a1ef0c329685da0e203ed692a8ebe64cc92c" dependencies = [ "futures 0.3.16", "log 0.4.14", @@ -3679,9 +3702,9 @@ dependencies = [ [[package]] name = "libp2p-relay" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0133f6cfd81cdc16e716de2982e012c62e6b9d4f12e41967b3ee361051c622aa" +checksum = "2852b61c90fa8ce3c8fcc2aba76e6cefc20d648f9df29157d6b3a916278ef3e3" dependencies = [ "asynchronous-codec 0.6.0", "bytes 1.0.1", @@ -3691,8 +3714,8 @@ dependencies = [ "libp2p-swarm", "log 0.4.14", "pin-project 1.0.8", - "prost 0.8.0", - "prost-build 0.8.0", + "prost", + "prost-build", "rand 0.7.3", "smallvec 1.7.0", "unsigned-varint 0.7.0", @@ -3700,11 +3723,33 @@ dependencies = [ "wasm-timer", ] +[[package]] +name = "libp2p-rendezvous" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14a6d2b9e7677eff61dc3d2854876aaf3976d84a01ef6664b610c77a0c9407c5" +dependencies = [ + "asynchronous-codec 0.6.0", + "bimap", + "futures 0.3.16", + "libp2p-core", + "libp2p-swarm", + "log 0.4.14", + "prost", + "prost-build", + "rand 0.8.4", + "sha2 0.9.8", + "thiserror", + "unsigned-varint 0.7.0", + "void", + "wasm-timer", +] + [[package]] name = "libp2p-request-response" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06cdae44b6821466123af93cbcdec7c9e6ba9534a8af9cdc296446d39416d241" +checksum = "a877a4ced6d46bf84677e1974e8cf61fb434af73b2e96fb48d6cb6223a4634d8" dependencies = [ "async-trait", "bytes 1.0.1", @@ -3712,8 +3757,7 @@ dependencies = [ "libp2p-core", "libp2p-swarm", "log 0.4.14", - "lru 0.6.6", - "minicbor", + "lru 0.7.0", "rand 0.7.3", "smallvec 1.7.0", "unsigned-varint 0.7.0", @@ -3722,9 +3766,9 @@ dependencies = [ [[package]] name = "libp2p-swarm" -version = "0.30.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7083861341e1555467863b4cd802bea1e8c4787c0f7b5110097d0f1f3248f9a9" +checksum = "3f5184a508f223bc100a12665517773fb8730e9f36fc09eefb670bf01b107ae9" dependencies = [ "either", "futures 0.3.16", @@ -3738,9 +3782,9 @@ dependencies = [ [[package]] name = "libp2p-swarm-derive" -version = "0.24.0" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab8cb308d4fc854869f5abb54fdab0833d2cf670d407c745849dc47e6e08d79c" +checksum = "072c290f727d39bdc4e9d6d1c847978693d25a673bd757813681e33e5f6c00c2" dependencies = [ "quote", "syn", @@ -3748,9 +3792,9 @@ dependencies = [ [[package]] name = "libp2p-tcp" -version = "0.29.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79edd26b6b4bb5feee210dcda562dca186940dfecb0024b979c3f50824b3bf28" +checksum = "7399c5b6361ef525d41c11fcf51635724f832baf5819b30d3d873eabb4fbae4b" dependencies = [ "async-io", "futures 0.3.16", @@ -3765,9 +3809,9 @@ dependencies = [ [[package]] name = "libp2p-uds" -version = "0.29.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "280e793440dd4e9f273d714f4497325c72cddb0fe85a49f9a03c88f41dd20182" +checksum = "b8b7563e46218165dfd60f64b96f7ce84590d75f53ecbdc74a7dd01450dc5973" dependencies = [ "async-std", "futures 0.3.16", @@ -3777,9 +3821,9 @@ dependencies = [ [[package]] name = "libp2p-wasm-ext" -version = "0.29.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f553b7140fad3d7a76f50497b0ea591e26737d9607428a75509fc191e4d1b1f6" +checksum = "1008a302b73c5020251f9708c653f5ed08368e530e247cc9cd2f109ff30042cf" dependencies = [ "futures 0.3.16", "js-sys", @@ -3791,9 +3835,9 @@ dependencies = [ [[package]] name = "libp2p-websocket" -version = "0.30.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddf99dcbf5063e9d59087f61b1e85c686ceab2f5abedb472d32288065c0e5e27" +checksum = "22e12df82d1ed64969371a9e65ea92b91064658604cc2576c2757f18ead9a1cf" dependencies = [ "either", "futures 0.3.16", @@ -3802,16 +3846,16 @@ dependencies = [ "log 0.4.14", "quicksink", "rw-stream-sink", - "soketto 0.4.2", + "soketto 0.7.0", "url 2.2.1", "webpki-roots", ] [[package]] name = "libp2p-yamux" -version = "0.33.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "214cc0dd9c37cbed27f0bb1eba0c41bbafdb93a8be5e9d6ae1e6b4b42cd044bf" +checksum = "4e7362abb8867d7187e7e93df17f460d554c997fc5c8ac57dc1259057f6889af" dependencies = [ "futures 0.3.16", "libp2p-core", @@ -3832,25 +3876,6 @@ dependencies = [ "libc", ] -[[package]] -name = "libsecp256k1" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd1137239ab33b41aa9637a88a28249e5e70c40a42ccc92db7f12cc356c1fcd7" -dependencies = [ - "arrayref", - "base64 0.12.3", - "digest 0.9.0", - "hmac-drbg", - "libsecp256k1-core 0.2.2", - "libsecp256k1-gen-ecmult 0.2.1", - "libsecp256k1-gen-genmult 0.2.1", - "rand 0.7.3", - "serde", - "sha2 0.9.8", - "typenum", -] - [[package]] name = "libsecp256k1" version = "0.7.0" @@ -3861,26 +3886,15 @@ dependencies = [ "base64 0.13.0", "digest 0.9.0", "hmac-drbg", - "libsecp256k1-core 0.3.0", - "libsecp256k1-gen-ecmult 0.3.0", - "libsecp256k1-gen-genmult 0.3.0", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", "rand 0.8.4", "serde", "sha2 0.9.8", "typenum", ] -[[package]] -name = "libsecp256k1-core" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0f6ab710cec28cef759c5f18671a27dae2a5f952cdaaee1d8e2908cb2478a80" -dependencies = [ - "crunchy", - "digest 0.9.0", - "subtle", -] - [[package]] name = "libsecp256k1-core" version = "0.3.0" @@ -3892,31 +3906,13 @@ dependencies = [ "subtle", ] -[[package]] -name = "libsecp256k1-gen-ecmult" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccab96b584d38fac86a83f07e659f0deafd0253dc096dab5a36d53efe653c5c3" -dependencies = [ - "libsecp256k1-core 0.2.2", -] - [[package]] name = "libsecp256k1-gen-ecmult" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3038c808c55c87e8a172643a7d87187fc6c4174468159cb3090659d55bcb4809" dependencies = [ - "libsecp256k1-core 0.3.0", -] - -[[package]] -name = "libsecp256k1-gen-genmult" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67abfe149395e3aa1c48a2beb32b068e2334402df8181f818d3aee2b304c4f5d" -dependencies = [ - "libsecp256k1-core 0.2.2", + "libsecp256k1-core", ] [[package]] @@ -3925,7 +3921,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3db8d6ba2cec9eacc40e6e8ccc98931840301f1006e95647ceb2dd5c3aa06f7c" dependencies = [ - "libsecp256k1-core 0.3.0", + "libsecp256k1-core", ] [[package]] @@ -4205,26 +4201,6 @@ dependencies = [ "log 0.3.9", ] -[[package]] -name = "minicbor" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea79ce4ab9f445ec6b71833a2290ac0a29c9dde0fa7cae4c481eecae021d9bd9" -dependencies = [ - "minicbor-derive", -] - -[[package]] -name = "minicbor-derive" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce18b5423c573a13e80cb3046ea0af6379ef725dc3af4886bdb8f4e5093068" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "miniz_oxide" version = "0.4.4" @@ -5067,6 +5043,29 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +[[package]] +name = "open-metrics-client" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7337d80c23c2d8b1349563981bc4fb531220733743ba8115454a67b181173f0d" +dependencies = [ + "dtoa", + "itoa", + "open-metrics-client-derive-text-encode", + "owning_ref", +] + +[[package]] +name = "open-metrics-client-derive-text-encode" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a15c83b586f00268c619c1cb3340ec1a6f59dd9ba1d9833a273a68e6d5cd8ffc" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "openssl" version = "0.10.35" @@ -5345,7 +5344,7 @@ dependencies = [ "frame-system", "hex", "hex-literal", - "libsecp256k1 0.7.0", + "libsecp256k1", "log 0.4.14", "pallet-beefy", "pallet-mmr", @@ -5405,7 +5404,7 @@ dependencies = [ "frame-support", "frame-system", "hex-literal", - "libsecp256k1 0.7.0", + "libsecp256k1", "log 0.4.14", "pallet-balances", "pallet-contracts-primitives", @@ -6557,23 +6556,13 @@ dependencies = [ "sha-1 0.8.2", ] -[[package]] -name = "petgraph" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7" -dependencies = [ - "fixedbitset 0.2.0", - "indexmap", -] - [[package]] name = "petgraph" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a13a2fa9d0b63e5f22328828741e523766fff0ee9e779316902290dff3f824f" dependencies = [ - "fixedbitset 0.4.0", + "fixedbitset", "indexmap", ] @@ -6847,16 +6836,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "prost" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de5e2533f59d08fcf364fd374ebda0692a70bd6d7e66ef97f306f45c6c5d8020" -dependencies = [ - "bytes 1.0.1", - "prost-derive 0.8.0", -] - [[package]] name = "prost" version = "0.9.0" @@ -6864,25 +6843,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001" dependencies = [ "bytes 1.0.1", - "prost-derive 0.9.0", -] - -[[package]] -name = "prost-build" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "355f634b43cdd80724ee7848f95770e7e70eefa6dcf14fea676216573b8fd603" -dependencies = [ - "bytes 1.0.1", - "heck", - "itertools", - "log 0.4.14", - "multimap", - "petgraph 0.5.1", - "prost 0.8.0", - "prost-types 0.8.0", - "tempfile", - "which", + "prost-derive", ] [[package]] @@ -6897,27 +6858,14 @@ dependencies = [ "lazy_static", "log 0.4.14", "multimap", - "petgraph 0.6.0", - "prost 0.9.0", - "prost-types 0.9.0", + "petgraph", + "prost", + "prost-types", "regex", "tempfile", "which", ] -[[package]] -name = "prost-derive" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "600d2f334aa05acb02a755e217ef1ab6dea4d51b58b7846588b747edec04efba" -dependencies = [ - "anyhow", - "itertools", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "prost-derive" version = "0.9.0" @@ -6931,16 +6879,6 @@ dependencies = [ "syn", ] -[[package]] -name = "prost-types" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "603bbd6394701d13f3f25aada59c7de9d35a6a5887cfc156181234a44002771b" -dependencies = [ - "bytes 1.0.1", - "prost 0.8.0", -] - [[package]] name = "prost-types" version = "0.9.0" @@ -6948,7 +6886,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "534b7a0e836e3c482d2693070f982e39e7611da9695d4d1f5a4b186b51faef0a" dependencies = [ "bytes 1.0.1", - "prost 0.9.0", + "prost", ] [[package]] @@ -7594,9 +7532,9 @@ checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" [[package]] name = "salsa20" -version = "0.8.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecbd2eb639fd7cab5804a0837fe373cc2172d15437e804c054a9fb885cb923b0" +checksum = "0c0fbb5f676da676c260ba276a8f43a8dc67cf02d1438423aeb1c677a7212686" dependencies = [ "cipher", ] @@ -7632,8 +7570,8 @@ dependencies = [ "libp2p", "log 0.4.14", "parity-scale-codec", - "prost 0.9.0", - "prost-build 0.9.0", + "prost", + "prost-build", "quickcheck", "rand 0.7.3", "sc-client-api", @@ -8068,7 +8006,7 @@ version = "0.10.0-dev" dependencies = [ "hex-literal", "lazy_static", - "libsecp256k1 0.7.0", + "libsecp256k1", "log 0.4.14", "parity-scale-codec", "parking_lot 0.11.1", @@ -8282,8 +8220,8 @@ dependencies = [ "parity-scale-codec", "parking_lot 0.11.1", "pin-project 1.0.8", - "prost 0.9.0", - "prost-build 0.9.0", + "prost", + "prost-build", "quickcheck", "rand 0.7.3", "sc-block-builder", @@ -9159,7 +9097,6 @@ checksum = "b5c71ed3d54db0a699f4948e1bb3e45b450fa31fe602621dee6680361d569c88" dependencies = [ "base64 0.12.3", "bytes 0.5.6", - "flate2", "futures 0.3.16", "httparse", "log 0.4.14", @@ -9175,6 +9112,7 @@ checksum = "083624472e8817d44d02c0e55df043737ff11f279af924abdf93845717c2b75c" dependencies = [ "base64 0.13.0", "bytes 1.0.1", + "flate2", "futures 0.3.16", "httparse", "log 0.4.14", @@ -9442,7 +9380,7 @@ dependencies = [ "hex-literal", "impl-serde", "lazy_static", - "libsecp256k1 0.7.0", + "libsecp256k1", "log 0.4.14", "merlin", "num-traits", @@ -9562,7 +9500,7 @@ version = "4.0.0-dev" dependencies = [ "futures 0.3.16", "hash-db", - "libsecp256k1 0.7.0", + "libsecp256k1", "log 0.4.14", "parity-scale-codec", "parking_lot 0.11.1", diff --git a/client/authority-discovery/Cargo.toml b/client/authority-discovery/Cargo.toml index b6f9b8450d86..f3169e82fb3c 100644 --- a/client/authority-discovery/Cargo.toml +++ b/client/authority-discovery/Cargo.toml @@ -23,7 +23,7 @@ derive_more = "0.99.16" futures = "0.3.9" futures-timer = "3.0.1" ip_network = "0.4.0" -libp2p = { version = "0.39.1", default-features = false, features = ["kad"] } +libp2p = { version = "0.40.0", default-features = false, features = ["kad"] } log = "0.4.8" prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.10.0-dev" } prost = "0.9" diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index 8667a5e876c1..dddd48cb2f14 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -18,7 +18,7 @@ regex = "1.5.4" tokio = { version = "1.13", features = [ "signal", "rt-multi-thread" ] } futures = "0.3.9" fdlimit = "0.2.1" -libp2p = "0.39.1" +libp2p = "0.40.0" parity-scale-codec = "2.3.1" hex = "0.4.2" rand = "0.7.3" diff --git a/client/cli/src/commands/build_spec_cmd.rs b/client/cli/src/commands/build_spec_cmd.rs index 75fdf07643ee..5e43a26a1e67 100644 --- a/client/cli/src/commands/build_spec_cmd.rs +++ b/client/cli/src/commands/build_spec_cmd.rs @@ -65,7 +65,7 @@ impl BuildSpecCmd { if spec.boot_nodes().is_empty() && !self.disable_default_bootnode { let keys = network_config.node_key.into_keypair()?; - let peer_id = keys.public().into_peer_id(); + let peer_id = keys.public().to_peer_id(); let addr = MultiaddrWithPeerId { multiaddr: build_multiaddr![Ip4([127, 0, 0, 1]), Tcp(30333u16)], peer_id, diff --git a/client/cli/src/commands/generate_node_key.rs b/client/cli/src/commands/generate_node_key.rs index 74a4197f3662..cc26bb73240a 100644 --- a/client/cli/src/commands/generate_node_key.rs +++ b/client/cli/src/commands/generate_node_key.rs @@ -42,7 +42,7 @@ impl GenerateNodeKeyCmd { pub fn run(&self) -> Result<(), Error> { let keypair = libp2p_ed25519::Keypair::generate(); let secret = keypair.secret(); - let peer_id = PublicKey::Ed25519(keypair.public()).into_peer_id(); + let peer_id = PublicKey::Ed25519(keypair.public()).to_peer_id(); let secret_hex = hex::encode(secret.as_ref()); match &self.file { diff --git a/client/cli/src/commands/inspect_node_key.rs b/client/cli/src/commands/inspect_node_key.rs index 92a71f897505..7527fbe4315a 100644 --- a/client/cli/src/commands/inspect_node_key.rs +++ b/client/cli/src/commands/inspect_node_key.rs @@ -47,7 +47,7 @@ impl InspectNodeKeyCmd { ed25519::SecretKey::from_bytes(&mut file_content).map_err(|_| "Bad node key file")?; let keypair = ed25519::Keypair::from(secret); - let peer_id = PublicKey::Ed25519(keypair.public()).into_peer_id(); + let peer_id = PublicKey::Ed25519(keypair.public()).to_peer_id(); println!("{}", peer_id); diff --git a/client/consensus/common/Cargo.toml b/client/consensus/common/Cargo.toml index c26e250edf24..308028c85d23 100644 --- a/client/consensus/common/Cargo.toml +++ b/client/consensus/common/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] thiserror = "1.0.30" -libp2p = { version = "0.39.1", default-features = false } +libp2p = { version = "0.40.0", default-features = false } log = "0.4.8" futures = { version = "0.3.1", features = ["thread-pool"] } futures-timer = "3.0.1" diff --git a/client/network-gossip/Cargo.toml b/client/network-gossip/Cargo.toml index e11cb8dbe85d..840cb50c8c9f 100644 --- a/client/network-gossip/Cargo.toml +++ b/client/network-gossip/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] futures = "0.3.9" futures-timer = "3.0.1" -libp2p = { version = "0.39.1", default-features = false } +libp2p = { version = "0.40.0", default-features = false } log = "0.4.8" lru = "0.7.0" prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.10.0-dev", path = "../../utils/prometheus" } diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index 527a18dc7755..8ee4d7f14572 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -64,11 +64,11 @@ unsigned-varint = { version = "0.6.0", features = [ ] } void = "1.0.2" zeroize = "1.4.2" -libp2p = "0.39.1" +libp2p = "0.40.0" [dev-dependencies] assert_matches = "1.3" -libp2p = { version = "0.39.1", default-features = false } +libp2p = { version = "0.40.0", default-features = false } quickcheck = "1.0.3" rand = "0.7.2" sp-test-primitives = { version = "2.0.0", path = "../../primitives/test-primitives" } diff --git a/client/network/src/behaviour.rs b/client/network/src/behaviour.rs index e2b950cf67e8..a6a67d7bce2d 100644 --- a/client/network/src/behaviour.rs +++ b/client/network/src/behaviour.rs @@ -32,7 +32,10 @@ use libp2p::{ core::{Multiaddr, PeerId, PublicKey}, identify::IdentifyInfo, kad::record, - swarm::{toggle::Toggle, NetworkBehaviourAction, NetworkBehaviourEventProcess, PollParameters}, + swarm::{ + toggle::Toggle, NetworkBehaviour, NetworkBehaviourAction, NetworkBehaviourEventProcess, + PollParameters, + }, NetworkBehaviour, }; use log::debug; @@ -58,7 +61,7 @@ pub use crate::request_responses::{ /// General behaviour of the network. Combines all protocols together. #[derive(NetworkBehaviour)] -#[behaviour(out_event = "BehaviourOut", poll_method = "poll")] +#[behaviour(out_event = "BehaviourOut", poll_method = "poll", event_process = true)] pub struct Behaviour { /// All the substrate-specific protocols. substrate: Protocol, @@ -512,11 +515,12 @@ impl NetworkBehaviourEventProcess for Behaviour { } impl Behaviour { - fn poll( + fn poll( &mut self, _cx: &mut Context, _: &mut impl PollParameters, - ) -> Poll>> { + ) -> Poll, ::ProtocolsHandler>> + { if let Some(event) = self.events.pop_front() { return Poll::Ready(NetworkBehaviourAction::GenerateEvent(event)) } diff --git a/client/network/src/bitswap.rs b/client/network/src/bitswap.rs index 6b53dce62650..e6cb1d9d79e3 100644 --- a/client/network/src/bitswap.rs +++ b/client/network/src/bitswap.rs @@ -39,8 +39,7 @@ use libp2p::{ UpgradeInfo, }, swarm::{ - IntoProtocolsHandler, NetworkBehaviour, NetworkBehaviourAction, NotifyHandler, - OneShotHandler, PollParameters, ProtocolsHandler, + NetworkBehaviour, NetworkBehaviourAction, NotifyHandler, OneShotHandler, PollParameters, }, }; use log::{debug, error, trace}; @@ -297,12 +296,11 @@ impl NetworkBehaviour for Bitswap { self.ready_blocks.push_back((peer, response)); } - fn poll(&mut self, _ctx: &mut Context, _: &mut impl PollParameters) -> Poll< - NetworkBehaviourAction< - <::Handler as ProtocolsHandler>::InEvent, - Self::OutEvent, - >, - >{ + fn poll( + &mut self, + _ctx: &mut Context, + _: &mut impl PollParameters, + ) -> Poll> { if let Some((peer_id, message)) = self.ready_blocks.pop_front() { return Poll::Ready(NetworkBehaviourAction::NotifyHandler { peer_id, diff --git a/client/network/src/discovery.rs b/client/network/src/discovery.rs index 2a4b25a621e0..dc08ab57ed3f 100644 --- a/client/network/src/discovery.rs +++ b/client/network/src/discovery.rs @@ -67,8 +67,8 @@ use libp2p::{ mdns::{Mdns, MdnsConfig, MdnsEvent}, multiaddr::Protocol, swarm::{ - protocols_handler::multi::IntoMultiHandler, IntoProtocolsHandler, NetworkBehaviour, - NetworkBehaviourAction, PollParameters, ProtocolsHandler, + protocols_handler::multi::IntoMultiHandler, DialError, IntoProtocolsHandler, + NetworkBehaviour, NetworkBehaviourAction, PollParameters, ProtocolsHandler, }, }; use log::{debug, error, info, trace, warn}; @@ -107,7 +107,7 @@ impl DiscoveryConfig { /// Create a default configuration with the given public key. pub fn new(local_public_key: PublicKey) -> Self { Self { - local_peer_id: local_public_key.into_peer_id(), + local_peer_id: local_public_key.to_peer_id(), permanent_addresses: Vec::new(), dht_random_walk: true, allow_private_ipv4: true, @@ -428,6 +428,29 @@ impl DiscoveryBehaviour { }; ip.is_global() } + + fn new_handler_with_replacement( + &mut self, + pid: ProtocolId, + handler: KademliaHandlerProto, + ) -> ::ProtocolsHandler { + let mut handlers: HashMap<_, _> = self + .kademlias + .iter_mut() + .map(|(p, k)| (p.clone(), NetworkBehaviour::new_handler(k))) + .collect(); + + if let Some(h) = handlers.get_mut(&pid) { + *h = handler + } + + IntoMultiHandler::try_from_iter(handlers).expect( + "There can be at most one handler per `ProtocolId` and protocol names contain the \ + `ProtocolId` so no two protocol names in `self.kademlias` can be equal which is the \ + only error `try_from_iter` can return, therefore this call is guaranteed to succeed; \ + qed", + ) + } } /// Event generated by the `DiscoveryBehaviour`. @@ -527,15 +550,34 @@ impl NetworkBehaviour for DiscoveryBehaviour { list } + fn inject_address_change( + &mut self, + peer_id: &PeerId, + connection_id: &ConnectionId, + old: &ConnectedPoint, + new: &ConnectedPoint, + ) { + for k in self.kademlias.values_mut() { + NetworkBehaviour::inject_address_change(k, peer_id, connection_id, old, new); + } + } + fn inject_connection_established( &mut self, peer_id: &PeerId, conn: &ConnectionId, endpoint: &ConnectedPoint, + failed_addresses: Option<&Vec>, ) { self.num_connections += 1; for k in self.kademlias.values_mut() { - NetworkBehaviour::inject_connection_established(k, peer_id, conn, endpoint) + NetworkBehaviour::inject_connection_established( + k, + peer_id, + conn, + endpoint, + failed_addresses, + ) } } @@ -547,14 +589,13 @@ impl NetworkBehaviour for DiscoveryBehaviour { fn inject_connection_closed( &mut self, - peer_id: &PeerId, - conn: &ConnectionId, - endpoint: &ConnectedPoint, + _peer_id: &PeerId, + _conn: &ConnectionId, + _endpoint: &ConnectedPoint, + _handler: ::Handler, ) { self.num_connections -= 1; - for k in self.kademlias.values_mut() { - NetworkBehaviour::inject_connection_closed(k, peer_id, conn, endpoint) - } + // NetworkBehaviour::inject_connection_closed on Kademlia does nothing. } fn inject_disconnected(&mut self, peer_id: &PeerId) { @@ -563,20 +604,25 @@ impl NetworkBehaviour for DiscoveryBehaviour { } } - fn inject_addr_reach_failure( + fn inject_dial_failure( &mut self, - peer_id: Option<&PeerId>, - addr: &Multiaddr, - error: &dyn std::error::Error, + peer_id: Option, + _: Self::ProtocolsHandler, + error: &DialError, ) { if let Some(peer_id) = peer_id { - if let Some(list) = self.ephemeral_addresses.get_mut(peer_id) { - list.retain(|a| a != addr); + if let DialError::Transport(errors) = error { + if let Some(list) = self.ephemeral_addresses.get_mut(&peer_id) { + for (addr, _error) in errors { + list.retain(|a| a != addr); + } + } } } for k in self.kademlias.values_mut() { - NetworkBehaviour::inject_addr_reach_failure(k, peer_id, addr, error) + let handler = k.new_handler(); + NetworkBehaviour::inject_dial_failure(k, peer_id, handler, error); } } @@ -631,12 +677,6 @@ impl NetworkBehaviour for DiscoveryBehaviour { } } - fn inject_dial_failure(&mut self, peer_id: &PeerId) { - for k in self.kademlias.values_mut() { - NetworkBehaviour::inject_dial_failure(k, peer_id) - } - } - fn inject_new_listener(&mut self, id: ListenerId) { for k in self.kademlias.values_mut() { NetworkBehaviour::inject_new_listener(k, id) @@ -649,6 +689,10 @@ impl NetworkBehaviour for DiscoveryBehaviour { } } + fn inject_listen_failure(&mut self, _: &Multiaddr, _: &Multiaddr, _: Self::ProtocolsHandler) { + // NetworkBehaviour::inject_listen_failure on Kademlia does nothing. + } + fn inject_listener_error(&mut self, id: ListenerId, err: &(dyn std::error::Error + 'static)) { for k in self.kademlias.values_mut() { NetworkBehaviour::inject_listener_error(k, id, err) @@ -665,12 +709,7 @@ impl NetworkBehaviour for DiscoveryBehaviour { &mut self, cx: &mut Context, params: &mut impl PollParameters, - ) -> Poll< - NetworkBehaviourAction< - <::Handler as ProtocolsHandler>::InEvent, - Self::OutEvent, - >, - >{ + ) -> Poll> { // Immediately process the content of `discovered`. if let Some(ev) = self.pending_events.pop_front() { return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev)) @@ -731,6 +770,10 @@ impl NetworkBehaviour for DiscoveryBehaviour { let ev = DiscoveryOut::Discovered(peer); return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev)) }, + KademliaEvent::InboundPutRecordRequest { .. } | + KademliaEvent::InboundAddProviderRequest { .. } => { + debug_assert!(false, "We don't use kad filtering at the moment"); + }, KademliaEvent::PendingRoutablePeer { .. } | KademliaEvent::InboundRequestServed { .. } => { // We are not interested in this event at the moment. @@ -847,10 +890,20 @@ impl NetworkBehaviour for DiscoveryBehaviour { warn!(target: "sub-libp2p", "Libp2p => Unhandled Kademlia event: {:?}", e) }, }, - NetworkBehaviourAction::DialAddress { address } => - return Poll::Ready(NetworkBehaviourAction::DialAddress { address }), - NetworkBehaviourAction::DialPeer { peer_id, condition } => - return Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id, condition }), + NetworkBehaviourAction::DialAddress { address, handler } => { + let pid = pid.clone(); + let handler = self.new_handler_with_replacement(pid, handler); + return Poll::Ready(NetworkBehaviourAction::DialAddress { address, handler }) + }, + NetworkBehaviourAction::DialPeer { peer_id, condition, handler } => { + let pid = pid.clone(); + let handler = self.new_handler_with_replacement(pid, handler); + return Poll::Ready(NetworkBehaviourAction::DialPeer { + peer_id, + condition, + handler, + }) + }, NetworkBehaviourAction::NotifyHandler { peer_id, handler, event } => return Poll::Ready(NetworkBehaviourAction::NotifyHandler { peer_id, @@ -888,10 +941,12 @@ impl NetworkBehaviour for DiscoveryBehaviour { }, MdnsEvent::Expired(_) => {}, }, - NetworkBehaviourAction::DialAddress { address } => - return Poll::Ready(NetworkBehaviourAction::DialAddress { address }), - NetworkBehaviourAction::DialPeer { peer_id, condition } => - return Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id, condition }), + NetworkBehaviourAction::DialAddress { .. } => { + unreachable!("mDNS never dials!"); + }, + NetworkBehaviourAction::DialPeer { .. } => { + unreachable!("mDNS never dials!"); + }, NetworkBehaviourAction::NotifyHandler { event, .. } => match event {}, /* `event` is an enum with no variant */ NetworkBehaviourAction::ReportObservedAddr { address, score } => return Poll::Ready(NetworkBehaviourAction::ReportObservedAddr { @@ -940,7 +995,7 @@ impl MdnsWrapper { &mut self, cx: &mut Context<'_>, params: &mut impl PollParameters, - ) -> Poll> { + ) -> Poll::ProtocolsHandler>> { loop { match self { Self::Instantiating(fut) => @@ -1007,13 +1062,13 @@ mod tests { config.finish() }; - let mut swarm = Swarm::new(transport, behaviour, keypair.public().into_peer_id()); + let mut swarm = Swarm::new(transport, behaviour, keypair.public().to_peer_id()); let listen_addr: Multiaddr = format!("/memory/{}", rand::random::()).parse().unwrap(); if i == 0 { first_swarm_peer_id_and_addr = - Some((keypair.public().into_peer_id(), listen_addr.clone())) + Some((keypair.public().to_peer_id(), listen_addr.clone())) } swarm.listen_on(listen_addr.clone()).unwrap(); diff --git a/client/network/src/peer_info.rs b/client/network/src/peer_info.rs index 141cc59247d1..2c37fdb460a7 100644 --- a/client/network/src/peer_info.rs +++ b/client/network/src/peer_info.rs @@ -186,6 +186,17 @@ impl NetworkBehaviour for PeerInfoBehaviour { list } + fn inject_address_change( + &mut self, + peer_id: &PeerId, + conn: &ConnectionId, + old: &ConnectedPoint, + new: &ConnectedPoint, + ) { + self.ping.inject_address_change(peer_id, conn, old, new); + self.identify.inject_address_change(peer_id, conn, old, new); + } + fn inject_connected(&mut self, peer_id: &PeerId) { self.ping.inject_connected(peer_id); self.identify.inject_connected(peer_id); @@ -196,9 +207,12 @@ impl NetworkBehaviour for PeerInfoBehaviour { peer_id: &PeerId, conn: &ConnectionId, endpoint: &ConnectedPoint, + failed_addresses: Option<&Vec>, ) { - self.ping.inject_connection_established(peer_id, conn, endpoint); - self.identify.inject_connection_established(peer_id, conn, endpoint); + self.ping + .inject_connection_established(peer_id, conn, endpoint, failed_addresses); + self.identify + .inject_connection_established(peer_id, conn, endpoint, failed_addresses); match self.nodes_info.entry(*peer_id) { Entry::Vacant(e) => { e.insert(NodeInfo::new(endpoint.clone())); @@ -220,9 +234,12 @@ impl NetworkBehaviour for PeerInfoBehaviour { peer_id: &PeerId, conn: &ConnectionId, endpoint: &ConnectedPoint, + handler: ::Handler, ) { - self.ping.inject_connection_closed(peer_id, conn, endpoint); - self.identify.inject_connection_closed(peer_id, conn, endpoint); + let (ping_handler, identity_handler) = handler.into_inner(); + self.identify + .inject_connection_closed(peer_id, conn, endpoint, identity_handler); + self.ping.inject_connection_closed(peer_id, conn, endpoint, ping_handler); if let Some(entry) = self.nodes_info.get_mut(peer_id) { entry.endpoints.retain(|ep| ep != endpoint) @@ -256,19 +273,15 @@ impl NetworkBehaviour for PeerInfoBehaviour { } } - fn inject_addr_reach_failure( + fn inject_dial_failure( &mut self, - peer_id: Option<&PeerId>, - addr: &Multiaddr, - error: &dyn std::error::Error, + peer_id: Option, + handler: Self::ProtocolsHandler, + error: &libp2p::swarm::DialError, ) { - self.ping.inject_addr_reach_failure(peer_id, addr, error); - self.identify.inject_addr_reach_failure(peer_id, addr, error); - } - - fn inject_dial_failure(&mut self, peer_id: &PeerId) { - self.ping.inject_dial_failure(peer_id); - self.identify.inject_dial_failure(peer_id); + let (ping_handler, identity_handler) = handler.into_inner(); + self.identify.inject_dial_failure(peer_id, identity_handler, error); + self.ping.inject_dial_failure(peer_id, ping_handler, error); } fn inject_new_listener(&mut self, id: ListenerId) { @@ -296,6 +309,18 @@ impl NetworkBehaviour for PeerInfoBehaviour { self.identify.inject_expired_external_addr(addr); } + fn inject_listen_failure( + &mut self, + local_addr: &Multiaddr, + send_back_addr: &Multiaddr, + handler: Self::ProtocolsHandler, + ) { + let (ping_handler, identity_handler) = handler.into_inner(); + self.identify + .inject_listen_failure(local_addr, send_back_addr, identity_handler); + self.ping.inject_listen_failure(local_addr, send_back_addr, ping_handler); + } + fn inject_listener_error(&mut self, id: ListenerId, err: &(dyn error::Error + 'static)) { self.ping.inject_listener_error(id, err); self.identify.inject_listener_error(id, err); @@ -309,13 +334,8 @@ impl NetworkBehaviour for PeerInfoBehaviour { fn poll( &mut self, cx: &mut Context, - params: &mut impl PollParameters - ) -> Poll< - NetworkBehaviourAction< - <::Handler as ProtocolsHandler>::InEvent, - Self::OutEvent - > - >{ + params: &mut impl PollParameters, + ) -> Poll> { loop { match self.ping.poll(cx, params) { Poll::Pending => break, @@ -324,10 +344,20 @@ impl NetworkBehaviour for PeerInfoBehaviour { self.handle_ping_report(&peer, rtt) } }, - Poll::Ready(NetworkBehaviourAction::DialAddress { address }) => - return Poll::Ready(NetworkBehaviourAction::DialAddress { address }), - Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id, condition }) => - return Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id, condition }), + Poll::Ready(NetworkBehaviourAction::DialAddress { address, handler }) => { + let handler = + IntoProtocolsHandler::select(handler, self.identify.new_handler()); + return Poll::Ready(NetworkBehaviourAction::DialAddress { address, handler }) + }, + Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id, condition, handler }) => { + let handler = + IntoProtocolsHandler::select(handler, self.identify.new_handler()); + return Poll::Ready(NetworkBehaviourAction::DialPeer { + peer_id, + condition, + handler, + }) + }, Poll::Ready(NetworkBehaviourAction::NotifyHandler { peer_id, handler, event }) => return Poll::Ready(NetworkBehaviourAction::NotifyHandler { peer_id, @@ -362,10 +392,18 @@ impl NetworkBehaviour for PeerInfoBehaviour { IdentifyEvent::Pushed { .. } => {}, IdentifyEvent::Sent { .. } => {}, }, - Poll::Ready(NetworkBehaviourAction::DialAddress { address }) => - return Poll::Ready(NetworkBehaviourAction::DialAddress { address }), - Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id, condition }) => - return Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id, condition }), + Poll::Ready(NetworkBehaviourAction::DialAddress { address, handler }) => { + let handler = IntoProtocolsHandler::select(self.ping.new_handler(), handler); + return Poll::Ready(NetworkBehaviourAction::DialAddress { address, handler }) + }, + Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id, condition, handler }) => { + let handler = IntoProtocolsHandler::select(self.ping.new_handler(), handler); + return Poll::Ready(NetworkBehaviourAction::DialPeer { + peer_id, + condition, + handler, + }) + }, Poll::Ready(NetworkBehaviourAction::NotifyHandler { peer_id, handler, event }) => return Poll::Ready(NetworkBehaviourAction::NotifyHandler { peer_id, diff --git a/client/network/src/protocol.rs b/client/network/src/protocol.rs index a0c52d14fa62..bfaf42d5ff22 100644 --- a/client/network/src/protocol.rs +++ b/client/network/src/protocol.rs @@ -1362,8 +1362,10 @@ impl NetworkBehaviour for Protocol { peer_id: &PeerId, conn: &ConnectionId, endpoint: &ConnectedPoint, + failed_addresses: Option<&Vec>, ) { - self.behaviour.inject_connection_established(peer_id, conn, endpoint) + self.behaviour + .inject_connection_established(peer_id, conn, endpoint, failed_addresses) } fn inject_connection_closed( @@ -1371,8 +1373,9 @@ impl NetworkBehaviour for Protocol { peer_id: &PeerId, conn: &ConnectionId, endpoint: &ConnectedPoint, + handler: ::Handler, ) { - self.behaviour.inject_connection_closed(peer_id, conn, endpoint) + self.behaviour.inject_connection_closed(peer_id, conn, endpoint, handler) } fn inject_connected(&mut self, peer_id: &PeerId) { @@ -1396,12 +1399,7 @@ impl NetworkBehaviour for Protocol { &mut self, cx: &mut std::task::Context, params: &mut impl PollParameters, - ) -> Poll< - NetworkBehaviourAction< - <::Handler as ProtocolsHandler>::InEvent, - Self::OutEvent - > - >{ + ) -> Poll> { if let Some(message) = self.pending_messages.pop_front() { return Poll::Ready(NetworkBehaviourAction::GenerateEvent(message)) } @@ -1562,10 +1560,10 @@ impl NetworkBehaviour for Protocol { let event = match self.behaviour.poll(cx, params) { Poll::Pending => return Poll::Pending, Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev)) => ev, - Poll::Ready(NetworkBehaviourAction::DialAddress { address }) => - return Poll::Ready(NetworkBehaviourAction::DialAddress { address }), - Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id, condition }) => - return Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id, condition }), + Poll::Ready(NetworkBehaviourAction::DialAddress { address, handler }) => + return Poll::Ready(NetworkBehaviourAction::DialAddress { address, handler }), + Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id, condition, handler }) => + return Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id, condition, handler }), Poll::Ready(NetworkBehaviourAction::NotifyHandler { peer_id, handler, event }) => return Poll::Ready(NetworkBehaviourAction::NotifyHandler { peer_id, @@ -1778,17 +1776,13 @@ impl NetworkBehaviour for Protocol { Poll::Pending } - fn inject_addr_reach_failure( + fn inject_dial_failure( &mut self, - peer_id: Option<&PeerId>, - addr: &Multiaddr, - error: &dyn std::error::Error, + peer_id: Option, + handler: Self::ProtocolsHandler, + error: &libp2p::swarm::DialError, ) { - self.behaviour.inject_addr_reach_failure(peer_id, addr, error) - } - - fn inject_dial_failure(&mut self, peer_id: &PeerId) { - self.behaviour.inject_dial_failure(peer_id) + self.behaviour.inject_dial_failure(peer_id, handler, error); } fn inject_new_listener(&mut self, id: ListenerId) { diff --git a/client/network/src/protocol/notifications/behaviour.rs b/client/network/src/protocol/notifications/behaviour.rs index f66f1fbe9e95..26a246f57690 100644 --- a/client/network/src/protocol/notifications/behaviour.rs +++ b/client/network/src/protocol/notifications/behaviour.rs @@ -26,7 +26,8 @@ use futures::prelude::*; use libp2p::{ core::{connection::ConnectionId, ConnectedPoint, Multiaddr, PeerId}, swarm::{ - DialPeerCondition, NetworkBehaviour, NetworkBehaviourAction, NotifyHandler, PollParameters, + DialError, DialPeerCondition, IntoProtocolsHandler, NetworkBehaviour, + NetworkBehaviourAction, NotifyHandler, PollParameters, }, }; use log::{error, trace, warn}; @@ -38,7 +39,7 @@ use std::{ borrow::Cow, cmp, collections::{hash_map::Entry, VecDeque}, - error, mem, + mem, pin::Pin, str, sync::Arc, @@ -132,7 +133,7 @@ pub struct Notifications { next_incoming_index: sc_peerset::IncomingIndex, /// Events to produce from `poll()`. - events: VecDeque>, + events: VecDeque>, } /// Configuration for a notifications protocol. @@ -628,6 +629,7 @@ impl Notifications { /// Function that is called when the peerset wants us to connect to a peer. fn peerset_report_connect(&mut self, peer_id: PeerId, set_id: sc_peerset::SetId) { // If `PeerId` is unknown to us, insert an entry, start dialing, and return early. + let handler = self.new_handler(); let mut occ_entry = match self.peers.entry((peer_id, set_id)) { Entry::Occupied(entry) => entry, Entry::Vacant(entry) => { @@ -643,6 +645,7 @@ impl Notifications { self.events.push_back(NetworkBehaviourAction::DialPeer { peer_id: entry.key().0.clone(), condition: DialPeerCondition::Disconnected, + handler, }); entry.insert(PeerState::Requested); return @@ -679,6 +682,7 @@ impl Notifications { self.events.push_back(NetworkBehaviourAction::DialPeer { peer_id: occ_entry.key().0.clone(), condition: DialPeerCondition::Disconnected, + handler, }); *occ_entry.into_mut() = PeerState::Requested; }, @@ -1094,6 +1098,7 @@ impl NetworkBehaviour for Notifications { peer_id: &PeerId, conn: &ConnectionId, endpoint: &ConnectedPoint, + _failed_addresses: Option<&Vec>, ) { for set_id in (0..self.notif_protocols.len()).map(sc_peerset::SetId::from) { match self.peers.entry((*peer_id, set_id)).or_insert(PeerState::Poisoned) { @@ -1152,6 +1157,7 @@ impl NetworkBehaviour for Notifications { peer_id: &PeerId, conn: &ConnectionId, _endpoint: &ConnectedPoint, + _handler: ::Handler, ) { for set_id in (0..self.notif_protocols.len()).map(sc_peerset::SetId::from) { let mut entry = if let Entry::Occupied(entry) = self.peers.entry((*peer_id, set_id)) { @@ -1411,70 +1417,74 @@ impl NetworkBehaviour for Notifications { fn inject_disconnected(&mut self, _peer_id: &PeerId) {} - fn inject_addr_reach_failure( + fn inject_dial_failure( &mut self, - peer_id: Option<&PeerId>, - addr: &Multiaddr, - error: &dyn error::Error, + peer_id: Option, + _: Self::ProtocolsHandler, + error: &DialError, ) { - trace!(target: "sub-libp2p", "Libp2p => Reach failure for {:?} through {:?}: {:?}", peer_id, addr, error); - } + if let DialError::Transport(errors) = error { + for (addr, error) in errors.iter() { + trace!(target: "sub-libp2p", "Libp2p => Reach failure for {:?} through {:?}: {:?}", peer_id, addr, error); + } + } - fn inject_dial_failure(&mut self, peer_id: &PeerId) { - trace!(target: "sub-libp2p", "Libp2p => Dial failure for {:?}", peer_id); + if let Some(peer_id) = peer_id { + trace!(target: "sub-libp2p", "Libp2p => Dial failure for {:?}", peer_id); - for set_id in (0..self.notif_protocols.len()).map(sc_peerset::SetId::from) { - if let Entry::Occupied(mut entry) = self.peers.entry((peer_id.clone(), set_id)) { - match mem::replace(entry.get_mut(), PeerState::Poisoned) { - // The peer is not in our list. - st @ PeerState::Backoff { .. } => { - *entry.into_mut() = st; - }, - - // "Basic" situation: we failed to reach a peer that the peerset requested. - st @ PeerState::Requested | st @ PeerState::PendingRequest { .. } => { - trace!(target: "sub-libp2p", "PSM <= Dropped({}, {:?})", peer_id, set_id); - self.peerset.dropped(set_id, *peer_id, DropReason::Unknown); + for set_id in (0..self.notif_protocols.len()).map(sc_peerset::SetId::from) { + if let Entry::Occupied(mut entry) = self.peers.entry((peer_id.clone(), set_id)) { + match mem::replace(entry.get_mut(), PeerState::Poisoned) { + // The peer is not in our list. + st @ PeerState::Backoff { .. } => { + *entry.into_mut() = st; + }, - let now = Instant::now(); - let ban_duration = match st { - PeerState::PendingRequest { timer_deadline, .. } - if timer_deadline > now => - cmp::max(timer_deadline - now, Duration::from_secs(5)), - _ => Duration::from_secs(5), - }; + // "Basic" situation: we failed to reach a peer that the peerset requested. + st @ PeerState::Requested | st @ PeerState::PendingRequest { .. } => { + trace!(target: "sub-libp2p", "PSM <= Dropped({}, {:?})", peer_id, set_id); + self.peerset.dropped(set_id, peer_id, DropReason::Unknown); - let delay_id = self.next_delay_id; - self.next_delay_id.0 += 1; - let delay = futures_timer::Delay::new(ban_duration); - let peer_id = *peer_id; - self.delays.push( - async move { - delay.await; - (delay_id, peer_id, set_id) - } - .boxed(), - ); - - *entry.into_mut() = PeerState::Backoff { - timer: delay_id, - timer_deadline: now + ban_duration, - }; - }, + let now = Instant::now(); + let ban_duration = match st { + PeerState::PendingRequest { timer_deadline, .. } + if timer_deadline > now => + cmp::max(timer_deadline - now, Duration::from_secs(5)), + _ => Duration::from_secs(5), + }; - // We can still get dial failures even if we are already connected to the peer, - // as an extra diagnostic for an earlier attempt. - st @ PeerState::Disabled { .. } | - st @ PeerState::Enabled { .. } | - st @ PeerState::DisabledPendingEnable { .. } | - st @ PeerState::Incoming { .. } => { - *entry.into_mut() = st; - }, + let delay_id = self.next_delay_id; + self.next_delay_id.0 += 1; + let delay = futures_timer::Delay::new(ban_duration); + let peer_id = peer_id; + self.delays.push( + async move { + delay.await; + (delay_id, peer_id, set_id) + } + .boxed(), + ); - PeerState::Poisoned => { - error!(target: "sub-libp2p", "State of {:?} is poisoned", peer_id); - debug_assert!(false); - }, + *entry.into_mut() = PeerState::Backoff { + timer: delay_id, + timer_deadline: now + ban_duration, + }; + }, + + // We can still get dial failures even if we are already connected to the + // peer, as an extra diagnostic for an earlier attempt. + st @ PeerState::Disabled { .. } | + st @ PeerState::Enabled { .. } | + st @ PeerState::DisabledPendingEnable { .. } | + st @ PeerState::Incoming { .. } => { + *entry.into_mut() = st; + }, + + PeerState::Poisoned => { + error!(target: "sub-libp2p", "State of {:?} is poisoned", peer_id); + debug_assert!(false); + }, + } } } } @@ -2000,7 +2010,7 @@ impl NetworkBehaviour for Notifications { &mut self, cx: &mut Context, _params: &mut impl PollParameters, - ) -> Poll> { + ) -> Poll> { if let Some(event) = self.events.pop_front() { return Poll::Ready(event) } @@ -2032,6 +2042,8 @@ impl NetworkBehaviour for Notifications { while let Poll::Ready(Some((delay_id, peer_id, set_id))) = Pin::new(&mut self.delays).poll_next(cx) { + let handler = self.new_handler(); + let peer_state = match self.peers.get_mut(&(peer_id, set_id)) { Some(s) => s, // We intentionally never remove elements from `delays`, and it may @@ -2051,6 +2063,7 @@ impl NetworkBehaviour for Notifications { self.events.push_back(NetworkBehaviourAction::DialPeer { peer_id, condition: DialPeerCondition::Disconnected, + handler, }); *peer_state = PeerState::Requested; }, diff --git a/client/network/src/protocol/notifications/tests.rs b/client/network/src/protocol/notifications/tests.rs index 0b3ffc01a4b8..ffc25194def0 100644 --- a/client/network/src/protocol/notifications/tests.rs +++ b/client/network/src/protocol/notifications/tests.rs @@ -29,7 +29,7 @@ use libp2p::{ }, identity, noise, swarm::{ - IntoProtocolsHandler, NetworkBehaviour, NetworkBehaviourAction, PollParameters, + DialError, IntoProtocolsHandler, NetworkBehaviour, NetworkBehaviourAction, PollParameters, ProtocolsHandler, Swarm, SwarmEvent, }, yamux, Multiaddr, PeerId, Transport, @@ -68,7 +68,7 @@ fn build_nodes() -> (Swarm, Swarm) { in_peers: 25, out_peers: 25, bootnodes: if index == 0 { - keypairs.iter().skip(1).map(|keypair| keypair.public().into_peer_id()).collect() + keypairs.iter().skip(1).map(|keypair| keypair.public().to_peer_id()).collect() } else { vec![] }, @@ -92,7 +92,7 @@ fn build_nodes() -> (Swarm, Swarm) { .enumerate() .filter_map(|(n, a)| { if n != index { - Some((keypairs[n].public().into_peer_id(), a.clone())) + Some((keypairs[n].public().to_peer_id(), a.clone())) } else { None } @@ -100,7 +100,7 @@ fn build_nodes() -> (Swarm, Swarm) { .collect(), }; - let mut swarm = Swarm::new(transport, behaviour, keypairs[index].public().into_peer_id()); + let mut swarm = Swarm::new(transport, behaviour, keypairs[index].public().to_peer_id()); swarm.listen_on(addrs[index].clone()).unwrap(); out.push(swarm); } @@ -163,8 +163,10 @@ impl NetworkBehaviour for CustomProtoWithAddr { peer_id: &PeerId, conn: &ConnectionId, endpoint: &ConnectedPoint, + failed_addresses: Option<&Vec>, ) { - self.inner.inject_connection_established(peer_id, conn, endpoint) + self.inner + .inject_connection_established(peer_id, conn, endpoint, failed_addresses) } fn inject_connection_closed( @@ -172,8 +174,9 @@ impl NetworkBehaviour for CustomProtoWithAddr { peer_id: &PeerId, conn: &ConnectionId, endpoint: &ConnectedPoint, + handler: ::Handler, ) { - self.inner.inject_connection_closed(peer_id, conn, endpoint) + self.inner.inject_connection_closed(peer_id, conn, endpoint, handler) } fn inject_event( @@ -188,27 +191,18 @@ impl NetworkBehaviour for CustomProtoWithAddr { fn poll( &mut self, cx: &mut Context, - params: &mut impl PollParameters - ) -> Poll< - NetworkBehaviourAction< - <::Handler as ProtocolsHandler>::InEvent, - Self::OutEvent - > - >{ + params: &mut impl PollParameters, + ) -> Poll> { self.inner.poll(cx, params) } - fn inject_addr_reach_failure( + fn inject_dial_failure( &mut self, - peer_id: Option<&PeerId>, - addr: &Multiaddr, - error: &dyn std::error::Error, + peer_id: Option, + handler: Self::ProtocolsHandler, + error: &DialError, ) { - self.inner.inject_addr_reach_failure(peer_id, addr, error) - } - - fn inject_dial_failure(&mut self, peer_id: &PeerId) { - self.inner.inject_dial_failure(peer_id) + self.inner.inject_dial_failure(peer_id, handler, error) } fn inject_new_listener(&mut self, id: ListenerId) { diff --git a/client/network/src/request_responses.rs b/client/network/src/request_responses.rs index 0908d7510e35..aa3e1701eee5 100644 --- a/client/network/src/request_responses.rs +++ b/client/network/src/request_responses.rs @@ -45,12 +45,12 @@ use libp2p::{ ConnectedPoint, Multiaddr, PeerId, }, request_response::{ - ProtocolSupport, RequestResponse, RequestResponseCodec, RequestResponseConfig, - RequestResponseEvent, RequestResponseMessage, ResponseChannel, + handler::RequestResponseHandler, ProtocolSupport, RequestResponse, RequestResponseCodec, + RequestResponseConfig, RequestResponseEvent, RequestResponseMessage, ResponseChannel, }, swarm::{ - protocols_handler::multi::MultiHandler, NetworkBehaviour, NetworkBehaviourAction, - PollParameters, ProtocolsHandler, + protocols_handler::multi::MultiHandler, IntoProtocolsHandler, NetworkBehaviour, + NetworkBehaviourAction, PollParameters, ProtocolsHandler, }, }; use std::{ @@ -377,6 +377,27 @@ impl RequestResponsesBehaviour { }; } } + + fn new_handler_with_replacement( + &mut self, + protocol: String, + handler: RequestResponseHandler, + ) -> ::ProtocolsHandler { + let mut handlers: HashMap<_, _> = self + .protocols + .iter_mut() + .map(|(p, (r, _))| (p.to_string(), NetworkBehaviour::new_handler(r))) + .collect(); + + if let Some(h) = handlers.get_mut(&protocol) { + *h = handler + } + + MultiHandler::try_from_iter(handlers).expect( + "Protocols are in a HashMap and there can be at most one handler per protocol name, \ + which is the only possible error; qed", + ) + } } impl NetworkBehaviour for RequestResponsesBehaviour { @@ -405,9 +426,16 @@ impl NetworkBehaviour for RequestResponsesBehaviour { peer_id: &PeerId, conn: &ConnectionId, endpoint: &ConnectedPoint, + failed_addresses: Option<&Vec>, ) { for (p, _) in self.protocols.values_mut() { - NetworkBehaviour::inject_connection_established(p, peer_id, conn, endpoint) + NetworkBehaviour::inject_connection_established( + p, + peer_id, + conn, + endpoint, + failed_addresses, + ) } } @@ -422,9 +450,11 @@ impl NetworkBehaviour for RequestResponsesBehaviour { peer_id: &PeerId, conn: &ConnectionId, endpoint: &ConnectedPoint, + _handler: ::Handler, ) { for (p, _) in self.protocols.values_mut() { - NetworkBehaviour::inject_connection_closed(p, peer_id, conn, endpoint) + let handler = p.new_handler(); + NetworkBehaviour::inject_connection_closed(p, peer_id, conn, endpoint, handler); } } @@ -434,17 +464,6 @@ impl NetworkBehaviour for RequestResponsesBehaviour { } } - fn inject_addr_reach_failure( - &mut self, - peer_id: Option<&PeerId>, - addr: &Multiaddr, - error: &dyn std::error::Error, - ) { - for (p, _) in self.protocols.values_mut() { - NetworkBehaviour::inject_addr_reach_failure(p, peer_id, addr, error) - } - } - fn inject_event( &mut self, peer_id: PeerId, @@ -478,9 +497,15 @@ impl NetworkBehaviour for RequestResponsesBehaviour { } } - fn inject_dial_failure(&mut self, peer_id: &PeerId) { + fn inject_dial_failure( + &mut self, + peer_id: Option, + _: Self::ProtocolsHandler, + error: &libp2p::swarm::DialError, + ) { for (p, _) in self.protocols.values_mut() { - NetworkBehaviour::inject_dial_failure(p, peer_id) + let handler = p.new_handler(); + NetworkBehaviour::inject_dial_failure(p, peer_id, handler, error) } } @@ -512,12 +537,7 @@ impl NetworkBehaviour for RequestResponsesBehaviour { &mut self, cx: &mut Context, params: &mut impl PollParameters, - ) -> Poll< - NetworkBehaviourAction< - ::InEvent, - Self::OutEvent, - >, - > { + ) -> Poll> { 'poll_all: loop { if let Some(message_request) = self.message_request.take() { // Now we can can poll `MessageRequest` until we get the reputation @@ -658,17 +678,26 @@ impl NetworkBehaviour for RequestResponsesBehaviour { // Other events generated by the underlying behaviour are transparently // passed through. - NetworkBehaviourAction::DialAddress { address } => { + NetworkBehaviourAction::DialAddress { address, handler } => { log::error!( "The request-response isn't supposed to start dialing peers" ); - return Poll::Ready(NetworkBehaviourAction::DialAddress { address }) + let protocol = protocol.to_string(); + let handler = self.new_handler_with_replacement(protocol, handler); + return Poll::Ready(NetworkBehaviourAction::DialAddress { + address, + handler, + }) }, - NetworkBehaviourAction::DialPeer { peer_id, condition } => + NetworkBehaviourAction::DialPeer { peer_id, condition, handler } => { + let protocol = protocol.to_string(); + let handler = self.new_handler_with_replacement(protocol, handler); return Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id, condition, - }), + handler, + }) + }, NetworkBehaviourAction::NotifyHandler { peer_id, handler, event } => return Poll::Ready(NetworkBehaviourAction::NotifyHandler { peer_id, @@ -1061,7 +1090,7 @@ mod tests { let behaviour = RequestResponsesBehaviour::new(list, handle).unwrap(); - let mut swarm = Swarm::new(transport, behaviour, keypair.public().into_peer_id()); + let mut swarm = Swarm::new(transport, behaviour, keypair.public().to_peer_id()); let listen_addr: Multiaddr = format!("/memory/{}", rand::random::()).parse().unwrap(); swarm.listen_on(listen_addr.clone()).unwrap(); diff --git a/client/network/src/service.rs b/client/network/src/service.rs index caf4db89f653..3dadf810c6b4 100644 --- a/client/network/src/service.rs +++ b/client/network/src/service.rs @@ -56,10 +56,10 @@ use libp2p::{ }, kad::record, multiaddr, - ping::handler::PingFailure, + ping::Failure as PingFailure, swarm::{ - protocols_handler::NodeHandlerWrapperError, AddressScore, NetworkBehaviour, SwarmBuilder, - SwarmEvent, + protocols_handler::NodeHandlerWrapperError, AddressScore, DialError, NetworkBehaviour, + SwarmBuilder, SwarmEvent, }, Multiaddr, PeerId, }; @@ -176,7 +176,7 @@ impl NetworkWorker { // Private and public keys configuration. let local_identity = params.network_config.node_key.clone().into_keypair()?; let local_public = local_identity.public(); - let local_peer_id = local_public.clone().into_peer_id(); + let local_peer_id = local_public.clone().to_peer_id(); info!( target: "sub-libp2p", "🏷 Local node identity is: {}", @@ -1845,8 +1845,13 @@ impl Future for NetworkWorker { peer_id, endpoint, num_established, + concurrent_dial_errors, }) => { - debug!(target: "sub-libp2p", "Libp2p => Connected({:?})", peer_id); + if let Some(errors) = concurrent_dial_errors { + debug!(target: "sub-libp2p", "Libp2p => Connected({:?}) with errors: {:?}", peer_id, errors); + } else { + debug!(target: "sub-libp2p", "Libp2p => Connected({:?})", peer_id); + } if let Some(metrics) = this.metrics.as_ref() { let direction = match endpoint { @@ -1914,37 +1919,41 @@ impl Future for NetworkWorker { metrics.listeners_local_addresses.dec(); } }, - Poll::Ready(SwarmEvent::UnreachableAddr { peer_id, address, error, .. }) => { - trace!( - target: "sub-libp2p", - "Libp2p => Failed to reach {:?} through {:?}: {}", - peer_id, address, error, - ); + Poll::Ready(SwarmEvent::OutgoingConnectionError { peer_id, error }) => { + if let Some(peer_id) = peer_id { + trace!( + target: "sub-libp2p", + "Libp2p => Failed to reach {:?}: {}", + peer_id, error, + ); - if this.boot_node_ids.contains(&peer_id) { - if let PendingConnectionError::InvalidPeerId = error { - error!( - "💔 The bootnode you want to connect to at `{}` provided a different peer ID than the one you expect: `{}`.", - address, peer_id, - ); + if this.boot_node_ids.contains(&peer_id) { + if let DialError::InvalidPeerId = error { + error!( + "💔 The bootnode you want to connect provided a different peer ID than the one you expect: `{}`.", + peer_id, + ); + } } } if let Some(metrics) = this.metrics.as_ref() { - match error { - PendingConnectionError::ConnectionLimit(_) => metrics - .pending_connections_errors_total - .with_label_values(&["limit-reached"]) - .inc(), - PendingConnectionError::InvalidPeerId => metrics - .pending_connections_errors_total - .with_label_values(&["invalid-peer-id"]) - .inc(), - PendingConnectionError::Transport(_) | - PendingConnectionError::IO(_) => metrics + let reason = match error { + DialError::ConnectionLimit(_) => Some("limit-reached"), + DialError::InvalidPeerId => Some("invalid-peer-id"), + DialError::Transport(_) | DialError::ConnectionIo(_) => + Some("transport-error"), + DialError::Banned | + DialError::LocalPeerId | + DialError::NoAddresses | + DialError::DialPeerConditionFalse(_) | + DialError::Aborted => None, // ignore them + }; + if let Some(reason) = reason { + metrics .pending_connections_errors_total - .with_label_values(&["transport-error"]) - .inc(), + .with_label_values(&[reason]) + .inc(); } } }, @@ -1970,16 +1979,19 @@ impl Future for NetworkWorker { ); if let Some(metrics) = this.metrics.as_ref() { let reason = match error { - PendingConnectionError::ConnectionLimit(_) => "limit-reached", - PendingConnectionError::InvalidPeerId => "invalid-peer-id", + PendingConnectionError::ConnectionLimit(_) => Some("limit-reached"), + PendingConnectionError::InvalidPeerId => Some("invalid-peer-id"), PendingConnectionError::Transport(_) | - PendingConnectionError::IO(_) => "transport-error", + PendingConnectionError::IO(_) => Some("transport-error"), + PendingConnectionError::Aborted => None, // ignore it }; - metrics - .incoming_connections_errors_total - .with_label_values(&[reason]) - .inc(); + if let Some(reason) = reason { + metrics + .incoming_connections_errors_total + .with_label_values(&[reason]) + .inc(); + } } }, Poll::Ready(SwarmEvent::BannedPeer { peer_id, endpoint }) => { @@ -1995,9 +2007,6 @@ impl Future for NetworkWorker { .inc(); } }, - Poll::Ready(SwarmEvent::UnknownPeerUnreachableAddr { address, error }) => { - trace!(target: "sub-libp2p", "Libp2p => UnknownPeerUnreachableAddr({}): {}", address, error) - }, Poll::Ready(SwarmEvent::ListenerClosed { reason, addresses, .. }) => { if let Some(metrics) = this.metrics.as_ref() { metrics.listeners_local_addresses.sub(addresses.len() as u64); diff --git a/client/network/test/Cargo.toml b/client/network/test/Cargo.toml index 539c57fe4cb9..84aab96a673d 100644 --- a/client/network/test/Cargo.toml +++ b/client/network/test/Cargo.toml @@ -20,7 +20,7 @@ parking_lot = "0.11.1" futures = "0.3.9" futures-timer = "3.0.1" rand = "0.7.2" -libp2p = { version = "0.39.1", default-features = false } +libp2p = { version = "0.40.0", default-features = false } sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" } sc-consensus = { version = "0.10.0-dev", path = "../../consensus/common" } sc-client-api = { version = "4.0.0-dev", path = "../../api" } diff --git a/client/peerset/Cargo.toml b/client/peerset/Cargo.toml index fba499bce00e..ec226b3d9bee 100644 --- a/client/peerset/Cargo.toml +++ b/client/peerset/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] futures = "0.3.9" -libp2p = { version = "0.39.1", default-features = false } +libp2p = { version = "0.40.0", default-features = false } sc-utils = { version = "4.0.0-dev", path = "../utils"} log = "0.4.8" serde_json = "1.0.71" diff --git a/client/telemetry/Cargo.toml b/client/telemetry/Cargo.toml index 9165f6f87af6..73efdbc039c5 100644 --- a/client/telemetry/Cargo.toml +++ b/client/telemetry/Cargo.toml @@ -18,7 +18,7 @@ targets = ["x86_64-unknown-linux-gnu"] parking_lot = "0.11.1" futures = "0.3.9" wasm-timer = "0.2.5" -libp2p = { version = "0.39.1", default-features = false, features = ["dns-async-std", "tcp-async-io", "wasm-ext", "websocket"] } +libp2p = { version = "0.40.0", default-features = false, features = ["dns-async-std", "tcp-async-io", "wasm-ext", "websocket"] } log = "0.4.8" pin-project = "1.0.8" rand = "0.7.2" From 5714e30cd280906a8f20e699b187fdef22989ffc Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Thu, 25 Nov 2021 02:24:45 -0800 Subject: [PATCH 234/695] REAL fix for `min-square` for `--steps=1 --repeats=1` (#10323) (#10369) * Revert "frame-benchmarking: Fix `min-square` for `--steps=1` (#10323)" This reverts commit fe7c02941122bbe4a7956aff53739b62f575240d. * actual fix --- frame/benchmarking/src/analysis.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frame/benchmarking/src/analysis.rs b/frame/benchmarking/src/analysis.rs index 6e0ffd23ee98..f655e8fa7632 100644 --- a/frame/benchmarking/src/analysis.rs +++ b/frame/benchmarking/src/analysis.rs @@ -199,7 +199,7 @@ impl Analysis { } pub fn min_squares_iqr(r: &Vec, selector: BenchmarkSelector) -> Option { - if r[0].components.len() <= 1 { + if r[0].components.is_empty() || r.len() <= 2 { return Self::median_value(r, selector) } From 120bd65e3ee8113f83bf77843ed239daf8cdbbfd Mon Sep 17 00:00:00 2001 From: Andreas Doerr Date: Thu, 25 Nov 2021 11:26:10 +0100 Subject: [PATCH 235/695] `BEEFY` add tests for rounds (#10328) * new_rounds() * WIP * test add_vote() * test drop() * learn to spell * go get some coffee * cargo fmt * lump everythings together again --- Cargo.lock | 1 + client/beefy/Cargo.toml | 1 + client/beefy/src/gossip.rs | 178 ++++++++++++++++++- client/beefy/src/gossip_tests.rs | 182 ------------------- client/beefy/src/keystore.rs | 269 +++++++++++++++++++++++++++- client/beefy/src/keystore_tests.rs | 275 ----------------------------- client/beefy/src/round.rs | 151 ++++++++++++++++ 7 files changed, 592 insertions(+), 465 deletions(-) delete mode 100644 client/beefy/src/gossip_tests.rs delete mode 100644 client/beefy/src/keystore_tests.rs diff --git a/Cargo.lock b/Cargo.lock index 3e956ea462ee..08d39c1d2b3d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -494,6 +494,7 @@ dependencies = [ "sp-core", "sp-keystore", "sp-runtime", + "sp-tracing", "strum", "substrate-prometheus-endpoint", "thiserror", diff --git a/client/beefy/Cargo.toml b/client/beefy/Cargo.toml index 96e5bc4ffbf3..23c9294d3510 100644 --- a/client/beefy/Cargo.toml +++ b/client/beefy/Cargo.toml @@ -35,6 +35,7 @@ sc-network-gossip = { version = "0.10.0-dev", path = "../network-gossip" } beefy-primitives = { version = "4.0.0-dev", path = "../../primitives/beefy" } [dev-dependencies] +sp-tracing = { version = "4.0.0-dev", path = "../../primitives/tracing" } sc-network-test = { version = "0.8.0", path = "../network/test" } strum = { version = "0.22", features = ["derive"] } diff --git a/client/beefy/src/gossip.rs b/client/beefy/src/gossip.rs index d0199964b6eb..8a43b5a03947 100644 --- a/client/beefy/src/gossip.rs +++ b/client/beefy/src/gossip.rs @@ -35,10 +35,6 @@ use beefy_primitives::{ use crate::keystore::BeefyKeystore; -#[cfg(test)] -#[path = "gossip_tests.rs"] -mod tests; - // Limit BEEFY gossip by keeping only a bound number of voting rounds alive. const MAX_LIVE_GOSSIP_ROUNDS: usize = 3; @@ -234,3 +230,177 @@ where }) } } + +#[cfg(test)] +mod tests { + use sc_keystore::LocalKeystore; + use sc_network_test::Block; + use sp_keystore::{SyncCryptoStore, SyncCryptoStorePtr}; + + use beefy_primitives::{crypto::Signature, Commitment, MmrRootHash, VoteMessage, KEY_TYPE}; + + use crate::keystore::{tests::Keyring, BeefyKeystore}; + + use super::*; + + #[test] + fn note_round_works() { + let gv = GossipValidator::::new(); + + gv.note_round(1u64); + + let live = gv.known_votes.read(); + assert!(GossipValidator::::is_live(&live, &1u64)); + + drop(live); + + gv.note_round(3u64); + gv.note_round(7u64); + gv.note_round(10u64); + + let live = gv.known_votes.read(); + + assert_eq!(live.len(), MAX_LIVE_GOSSIP_ROUNDS); + + assert!(!GossipValidator::::is_live(&live, &1u64)); + assert!(GossipValidator::::is_live(&live, &3u64)); + assert!(GossipValidator::::is_live(&live, &7u64)); + assert!(GossipValidator::::is_live(&live, &10u64)); + } + + #[test] + fn keeps_most_recent_max_rounds() { + let gv = GossipValidator::::new(); + + gv.note_round(3u64); + gv.note_round(7u64); + gv.note_round(10u64); + gv.note_round(1u64); + + let live = gv.known_votes.read(); + + assert_eq!(live.len(), MAX_LIVE_GOSSIP_ROUNDS); + + assert!(GossipValidator::::is_live(&live, &3u64)); + assert!(!GossipValidator::::is_live(&live, &1u64)); + + drop(live); + + gv.note_round(23u64); + gv.note_round(15u64); + gv.note_round(20u64); + gv.note_round(2u64); + + let live = gv.known_votes.read(); + + assert_eq!(live.len(), MAX_LIVE_GOSSIP_ROUNDS); + + assert!(GossipValidator::::is_live(&live, &15u64)); + assert!(GossipValidator::::is_live(&live, &20u64)); + assert!(GossipValidator::::is_live(&live, &23u64)); + } + + #[test] + fn note_same_round_twice() { + let gv = GossipValidator::::new(); + + gv.note_round(3u64); + gv.note_round(7u64); + gv.note_round(10u64); + + let live = gv.known_votes.read(); + + assert_eq!(live.len(), MAX_LIVE_GOSSIP_ROUNDS); + + drop(live); + + // note round #7 again -> should not change anything + gv.note_round(7u64); + + let live = gv.known_votes.read(); + + assert_eq!(live.len(), MAX_LIVE_GOSSIP_ROUNDS); + + assert!(GossipValidator::::is_live(&live, &3u64)); + assert!(GossipValidator::::is_live(&live, &7u64)); + assert!(GossipValidator::::is_live(&live, &10u64)); + } + + struct TestContext; + impl ValidatorContext for TestContext { + fn broadcast_topic(&mut self, _topic: B::Hash, _force: bool) { + todo!() + } + + fn broadcast_message(&mut self, _topic: B::Hash, _message: Vec, _force: bool) { + todo!() + } + + fn send_message(&mut self, _who: &sc_network::PeerId, _message: Vec) { + todo!() + } + + fn send_topic(&mut self, _who: &sc_network::PeerId, _topic: B::Hash, _force: bool) { + todo!() + } + } + + fn sign_commitment( + who: &Keyring, + commitment: &Commitment, + ) -> Signature { + let store: SyncCryptoStorePtr = std::sync::Arc::new(LocalKeystore::in_memory()); + SyncCryptoStore::ecdsa_generate_new(&*store, KEY_TYPE, Some(&who.to_seed())).unwrap(); + let beefy_keystore: BeefyKeystore = Some(store).into(); + + beefy_keystore.sign(&who.public(), &commitment.encode()).unwrap() + } + + #[test] + fn should_avoid_verifying_signatures_twice() { + let gv = GossipValidator::::new(); + let sender = sc_network::PeerId::random(); + let mut context = TestContext; + + let commitment = Commitment { + payload: MmrRootHash::default(), + block_number: 3_u64, + validator_set_id: 0, + }; + + let signature = sign_commitment(&Keyring::Alice, &commitment); + + let vote = VoteMessage { commitment, id: Keyring::Alice.public(), signature }; + + gv.note_round(3u64); + gv.note_round(7u64); + gv.note_round(10u64); + + // first time the cache should be populated. + let res = gv.validate(&mut context, &sender, &vote.encode()); + + assert!(matches!(res, ValidationResult::ProcessAndKeep(_))); + assert_eq!( + gv.known_votes.read().get(&vote.commitment.block_number).map(|x| x.len()), + Some(1) + ); + + // second time we should hit the cache + let res = gv.validate(&mut context, &sender, &vote.encode()); + + assert!(matches!(res, ValidationResult::ProcessAndKeep(_))); + + // next we should quickly reject if the round is not live. + gv.note_round(11_u64); + gv.note_round(12_u64); + + assert!(!GossipValidator::::is_live( + &*gv.known_votes.read(), + &vote.commitment.block_number + )); + + let res = gv.validate(&mut context, &sender, &vote.encode()); + + assert!(matches!(res, ValidationResult::Discard)); + } +} diff --git a/client/beefy/src/gossip_tests.rs b/client/beefy/src/gossip_tests.rs deleted file mode 100644 index 2d46b873cb7b..000000000000 --- a/client/beefy/src/gossip_tests.rs +++ /dev/null @@ -1,182 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2017-2021 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 . - -use sc_keystore::LocalKeystore; -use sc_network_test::Block; -use sp_keystore::{SyncCryptoStore, SyncCryptoStorePtr}; - -use beefy_primitives::{crypto::Signature, Commitment, MmrRootHash, VoteMessage, KEY_TYPE}; - -use crate::keystore::{tests::Keyring, BeefyKeystore}; - -use super::*; - -#[test] -fn note_round_works() { - let gv = GossipValidator::::new(); - - gv.note_round(1u64); - - let live = gv.known_votes.read(); - assert!(GossipValidator::::is_live(&live, &1u64)); - - drop(live); - - gv.note_round(3u64); - gv.note_round(7u64); - gv.note_round(10u64); - - let live = gv.known_votes.read(); - - assert_eq!(live.len(), MAX_LIVE_GOSSIP_ROUNDS); - - assert!(!GossipValidator::::is_live(&live, &1u64)); - assert!(GossipValidator::::is_live(&live, &3u64)); - assert!(GossipValidator::::is_live(&live, &7u64)); - assert!(GossipValidator::::is_live(&live, &10u64)); -} - -#[test] -fn keeps_most_recent_max_rounds() { - let gv = GossipValidator::::new(); - - gv.note_round(3u64); - gv.note_round(7u64); - gv.note_round(10u64); - gv.note_round(1u64); - - let live = gv.known_votes.read(); - - assert_eq!(live.len(), MAX_LIVE_GOSSIP_ROUNDS); - - assert!(GossipValidator::::is_live(&live, &3u64)); - assert!(!GossipValidator::::is_live(&live, &1u64)); - - drop(live); - - gv.note_round(23u64); - gv.note_round(15u64); - gv.note_round(20u64); - gv.note_round(2u64); - - let live = gv.known_votes.read(); - - assert_eq!(live.len(), MAX_LIVE_GOSSIP_ROUNDS); - - assert!(GossipValidator::::is_live(&live, &15u64)); - assert!(GossipValidator::::is_live(&live, &20u64)); - assert!(GossipValidator::::is_live(&live, &23u64)); -} - -#[test] -fn note_same_round_twice() { - let gv = GossipValidator::::new(); - - gv.note_round(3u64); - gv.note_round(7u64); - gv.note_round(10u64); - - let live = gv.known_votes.read(); - - assert_eq!(live.len(), MAX_LIVE_GOSSIP_ROUNDS); - - drop(live); - - // note round #7 again -> should not change anything - gv.note_round(7u64); - - let live = gv.known_votes.read(); - - assert_eq!(live.len(), MAX_LIVE_GOSSIP_ROUNDS); - - assert!(GossipValidator::::is_live(&live, &3u64)); - assert!(GossipValidator::::is_live(&live, &7u64)); - assert!(GossipValidator::::is_live(&live, &10u64)); -} - -struct TestContext; -impl ValidatorContext for TestContext { - fn broadcast_topic(&mut self, _topic: B::Hash, _force: bool) { - todo!() - } - - fn broadcast_message(&mut self, _topic: B::Hash, _message: Vec, _force: bool) { - todo!() - } - - fn send_message(&mut self, _who: &sc_network::PeerId, _message: Vec) { - todo!() - } - - fn send_topic(&mut self, _who: &sc_network::PeerId, _topic: B::Hash, _force: bool) { - todo!() - } -} - -fn sign_commitment( - who: &Keyring, - commitment: &Commitment, -) -> Signature { - let store: SyncCryptoStorePtr = std::sync::Arc::new(LocalKeystore::in_memory()); - SyncCryptoStore::ecdsa_generate_new(&*store, KEY_TYPE, Some(&who.to_seed())).unwrap(); - let beefy_keystore: BeefyKeystore = Some(store).into(); - - beefy_keystore.sign(&who.public(), &commitment.encode()).unwrap() -} - -#[test] -fn should_avoid_verifying_signatures_twice() { - let gv = GossipValidator::::new(); - let sender = sc_network::PeerId::random(); - let mut context = TestContext; - - let commitment = - Commitment { payload: MmrRootHash::default(), block_number: 3_u64, validator_set_id: 0 }; - - let signature = sign_commitment(&Keyring::Alice, &commitment); - - let vote = VoteMessage { commitment, id: Keyring::Alice.public(), signature }; - - gv.note_round(3u64); - gv.note_round(7u64); - gv.note_round(10u64); - - // first time the cache should be populated. - let res = gv.validate(&mut context, &sender, &vote.encode()); - - assert!(matches!(res, ValidationResult::ProcessAndKeep(_))); - assert_eq!(gv.known_votes.read().get(&vote.commitment.block_number).map(|x| x.len()), Some(1)); - - // second time we should hit the cache - let res = gv.validate(&mut context, &sender, &vote.encode()); - - assert!(matches!(res, ValidationResult::ProcessAndKeep(_))); - - // next we should quickly reject if the round is not live. - gv.note_round(11_u64); - gv.note_round(12_u64); - - assert!(!GossipValidator::::is_live( - &*gv.known_votes.read(), - &vote.commitment.block_number - )); - - let res = gv.validate(&mut context, &sender, &vote.encode()); - - assert!(matches!(res, ValidationResult::Discard)); -} diff --git a/client/beefy/src/keystore.rs b/client/beefy/src/keystore.rs index 88618b8a5a14..7ee1ceb46bc3 100644 --- a/client/beefy/src/keystore.rs +++ b/client/beefy/src/keystore.rs @@ -31,10 +31,6 @@ use beefy_primitives::{ use crate::error; -#[cfg(test)] -#[path = "keystore_tests.rs"] -pub mod tests; - /// A BEEFY specific keystore implemented as a `Newtype`. This is basically a /// wrapper around [`sp_keystore::SyncCryptoStore`] and allows to customize /// common cryptographic functionality. @@ -117,3 +113,268 @@ impl From> for BeefyKeystore { BeefyKeystore(store) } } + +#[cfg(test)] +pub mod tests { + use std::sync::Arc; + + use sc_keystore::LocalKeystore; + use sp_core::{ecdsa, keccak_256, Pair}; + use sp_keystore::{SyncCryptoStore, SyncCryptoStorePtr}; + + use beefy_primitives::{crypto, KEY_TYPE}; + + use super::BeefyKeystore; + use crate::error::Error; + + /// Set of test accounts using [`beefy_primitives::crypto`] types. + #[allow(missing_docs)] + #[derive(Debug, Clone, Copy, PartialEq, Eq, strum::Display, strum::EnumIter)] + pub(crate) enum Keyring { + Alice, + Bob, + Charlie, + Dave, + Eve, + Ferdie, + One, + Two, + } + + impl Keyring { + /// Sign `msg`. + pub fn sign(self, msg: &[u8]) -> crypto::Signature { + let msg = keccak_256(msg); + ecdsa::Pair::from(self).sign_prehashed(&msg).into() + } + + /// Return key pair. + pub fn pair(self) -> crypto::Pair { + ecdsa::Pair::from_string(self.to_seed().as_str(), None).unwrap().into() + } + + /// Return public key. + pub fn public(self) -> crypto::Public { + self.pair().public() + } + + /// Return seed string. + pub fn to_seed(self) -> String { + format!("//{}", self) + } + } + + impl From for crypto::Pair { + fn from(k: Keyring) -> Self { + k.pair() + } + } + + impl From for ecdsa::Pair { + fn from(k: Keyring) -> Self { + k.pair().into() + } + } + + fn keystore() -> SyncCryptoStorePtr { + Arc::new(LocalKeystore::in_memory()) + } + + #[test] + fn verify_should_work() { + let msg = keccak_256(b"I am Alice!"); + let sig = Keyring::Alice.sign(b"I am Alice!"); + + assert!(ecdsa::Pair::verify_prehashed( + &sig.clone().into(), + &msg, + &Keyring::Alice.public().into(), + )); + + // different public key -> fail + assert!(!ecdsa::Pair::verify_prehashed( + &sig.clone().into(), + &msg, + &Keyring::Bob.public().into(), + )); + + let msg = keccak_256(b"I am not Alice!"); + + // different msg -> fail + assert!( + !ecdsa::Pair::verify_prehashed(&sig.into(), &msg, &Keyring::Alice.public().into(),) + ); + } + + #[test] + fn pair_works() { + let want = crypto::Pair::from_string("//Alice", None).expect("Pair failed").to_raw_vec(); + let got = Keyring::Alice.pair().to_raw_vec(); + assert_eq!(want, got); + + let want = crypto::Pair::from_string("//Bob", None).expect("Pair failed").to_raw_vec(); + let got = Keyring::Bob.pair().to_raw_vec(); + assert_eq!(want, got); + + let want = crypto::Pair::from_string("//Charlie", None).expect("Pair failed").to_raw_vec(); + let got = Keyring::Charlie.pair().to_raw_vec(); + assert_eq!(want, got); + + let want = crypto::Pair::from_string("//Dave", None).expect("Pair failed").to_raw_vec(); + let got = Keyring::Dave.pair().to_raw_vec(); + assert_eq!(want, got); + + let want = crypto::Pair::from_string("//Eve", None).expect("Pair failed").to_raw_vec(); + let got = Keyring::Eve.pair().to_raw_vec(); + assert_eq!(want, got); + + let want = crypto::Pair::from_string("//Ferdie", None).expect("Pair failed").to_raw_vec(); + let got = Keyring::Ferdie.pair().to_raw_vec(); + assert_eq!(want, got); + + let want = crypto::Pair::from_string("//One", None).expect("Pair failed").to_raw_vec(); + let got = Keyring::One.pair().to_raw_vec(); + assert_eq!(want, got); + + let want = crypto::Pair::from_string("//Two", None).expect("Pair failed").to_raw_vec(); + let got = Keyring::Two.pair().to_raw_vec(); + assert_eq!(want, got); + } + + #[test] + fn authority_id_works() { + let store = keystore(); + + let alice: crypto::Public = + SyncCryptoStore::ecdsa_generate_new(&*store, KEY_TYPE, Some(&Keyring::Alice.to_seed())) + .ok() + .unwrap() + .into(); + + let bob = Keyring::Bob.public(); + let charlie = Keyring::Charlie.public(); + + let store: BeefyKeystore = Some(store).into(); + + let mut keys = vec![bob, charlie]; + + let id = store.authority_id(keys.as_slice()); + assert!(id.is_none()); + + keys.push(alice.clone()); + + let id = store.authority_id(keys.as_slice()).unwrap(); + assert_eq!(id, alice); + } + + #[test] + fn sign_works() { + let store = keystore(); + + let alice: crypto::Public = + SyncCryptoStore::ecdsa_generate_new(&*store, KEY_TYPE, Some(&Keyring::Alice.to_seed())) + .ok() + .unwrap() + .into(); + + let store: BeefyKeystore = Some(store).into(); + + let msg = b"are you involved or commited?"; + + let sig1 = store.sign(&alice, msg).unwrap(); + let sig2 = Keyring::Alice.sign(msg); + + assert_eq!(sig1, sig2); + } + + #[test] + fn sign_error() { + let store = keystore(); + + let _ = + SyncCryptoStore::ecdsa_generate_new(&*store, KEY_TYPE, Some(&Keyring::Bob.to_seed())) + .ok() + .unwrap(); + + let store: BeefyKeystore = Some(store).into(); + + let alice = Keyring::Alice.public(); + + let msg = b"are you involved or commited?"; + let sig = store.sign(&alice, msg).err().unwrap(); + let err = Error::Signature("ecdsa_sign_prehashed() failed".to_string()); + + assert_eq!(sig, err); + } + + #[test] + fn sign_no_keystore() { + let store: BeefyKeystore = None.into(); + + let alice = Keyring::Alice.public(); + let msg = b"are you involved or commited"; + + let sig = store.sign(&alice, msg).err().unwrap(); + let err = Error::Keystore("no Keystore".to_string()); + assert_eq!(sig, err); + } + + #[test] + fn verify_works() { + let store = keystore(); + + let alice: crypto::Public = + SyncCryptoStore::ecdsa_generate_new(&*store, KEY_TYPE, Some(&Keyring::Alice.to_seed())) + .ok() + .unwrap() + .into(); + + let store: BeefyKeystore = Some(store).into(); + + // `msg` and `sig` match + let msg = b"are you involved or commited?"; + let sig = store.sign(&alice, msg).unwrap(); + assert!(BeefyKeystore::verify(&alice, &sig, msg)); + + // `msg and `sig` don't match + let msg = b"you are just involved"; + assert!(!BeefyKeystore::verify(&alice, &sig, msg)); + } + + // Note that we use keys with and without a seed for this test. + #[test] + fn public_keys_works() { + const TEST_TYPE: sp_application_crypto::KeyTypeId = + sp_application_crypto::KeyTypeId(*b"test"); + + let store = keystore(); + + let add_key = |key_type, seed: Option<&str>| { + SyncCryptoStore::ecdsa_generate_new(&*store, key_type, seed).unwrap() + }; + + // test keys + let _ = add_key(TEST_TYPE, Some(Keyring::Alice.to_seed().as_str())); + let _ = add_key(TEST_TYPE, Some(Keyring::Bob.to_seed().as_str())); + + let _ = add_key(TEST_TYPE, None); + let _ = add_key(TEST_TYPE, None); + + // BEEFY keys + let _ = add_key(KEY_TYPE, Some(Keyring::Dave.to_seed().as_str())); + let _ = add_key(KEY_TYPE, Some(Keyring::Eve.to_seed().as_str())); + + let key1: crypto::Public = add_key(KEY_TYPE, None).into(); + let key2: crypto::Public = add_key(KEY_TYPE, None).into(); + + let store: BeefyKeystore = Some(store).into(); + + let keys = store.public_keys().ok().unwrap(); + + assert!(keys.len() == 4); + assert!(keys.contains(&Keyring::Dave.public())); + assert!(keys.contains(&Keyring::Eve.public())); + assert!(keys.contains(&key1)); + assert!(keys.contains(&key2)); + } +} diff --git a/client/beefy/src/keystore_tests.rs b/client/beefy/src/keystore_tests.rs deleted file mode 100644 index 99e3e42228df..000000000000 --- a/client/beefy/src/keystore_tests.rs +++ /dev/null @@ -1,275 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2017-2021 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 . - -use std::sync::Arc; - -use sc_keystore::LocalKeystore; -use sp_core::{ecdsa, keccak_256, Pair}; -use sp_keystore::{SyncCryptoStore, SyncCryptoStorePtr}; - -use beefy_primitives::{crypto, KEY_TYPE}; - -use super::BeefyKeystore; -use crate::error::Error; - -/// Set of test accounts using [`beefy_primitives::crypto`] types. -#[allow(missing_docs)] -#[derive(Debug, Clone, Copy, PartialEq, Eq, strum::Display, strum::EnumIter)] -pub(crate) enum Keyring { - Alice, - Bob, - Charlie, - Dave, - Eve, - Ferdie, - One, - Two, -} - -impl Keyring { - /// Sign `msg`. - pub fn sign(self, msg: &[u8]) -> crypto::Signature { - let msg = keccak_256(msg); - ecdsa::Pair::from(self).sign_prehashed(&msg).into() - } - - /// Return key pair. - pub fn pair(self) -> crypto::Pair { - ecdsa::Pair::from_string(self.to_seed().as_str(), None).unwrap().into() - } - - /// Return public key. - pub fn public(self) -> crypto::Public { - self.pair().public() - } - - /// Return seed string. - pub fn to_seed(self) -> String { - format!("//{}", self) - } -} - -impl From for crypto::Pair { - fn from(k: Keyring) -> Self { - k.pair() - } -} - -impl From for ecdsa::Pair { - fn from(k: Keyring) -> Self { - k.pair().into() - } -} - -fn keystore() -> SyncCryptoStorePtr { - Arc::new(LocalKeystore::in_memory()) -} - -#[test] -fn verify_should_work() { - let msg = keccak_256(b"I am Alice!"); - let sig = Keyring::Alice.sign(b"I am Alice!"); - - assert!(ecdsa::Pair::verify_prehashed( - &sig.clone().into(), - &msg, - &Keyring::Alice.public().into(), - )); - - // different public key -> fail - assert!(!ecdsa::Pair::verify_prehashed( - &sig.clone().into(), - &msg, - &Keyring::Bob.public().into(), - )); - - let msg = keccak_256(b"I am not Alice!"); - - // different msg -> fail - assert!(!ecdsa::Pair::verify_prehashed(&sig.into(), &msg, &Keyring::Alice.public().into(),)); -} - -#[test] -fn pair_works() { - let want = crypto::Pair::from_string("//Alice", None).expect("Pair failed").to_raw_vec(); - let got = Keyring::Alice.pair().to_raw_vec(); - assert_eq!(want, got); - - let want = crypto::Pair::from_string("//Bob", None).expect("Pair failed").to_raw_vec(); - let got = Keyring::Bob.pair().to_raw_vec(); - assert_eq!(want, got); - - let want = crypto::Pair::from_string("//Charlie", None).expect("Pair failed").to_raw_vec(); - let got = Keyring::Charlie.pair().to_raw_vec(); - assert_eq!(want, got); - - let want = crypto::Pair::from_string("//Dave", None).expect("Pair failed").to_raw_vec(); - let got = Keyring::Dave.pair().to_raw_vec(); - assert_eq!(want, got); - - let want = crypto::Pair::from_string("//Eve", None).expect("Pair failed").to_raw_vec(); - let got = Keyring::Eve.pair().to_raw_vec(); - assert_eq!(want, got); - - let want = crypto::Pair::from_string("//Ferdie", None).expect("Pair failed").to_raw_vec(); - let got = Keyring::Ferdie.pair().to_raw_vec(); - assert_eq!(want, got); - - let want = crypto::Pair::from_string("//One", None).expect("Pair failed").to_raw_vec(); - let got = Keyring::One.pair().to_raw_vec(); - assert_eq!(want, got); - - let want = crypto::Pair::from_string("//Two", None).expect("Pair failed").to_raw_vec(); - let got = Keyring::Two.pair().to_raw_vec(); - assert_eq!(want, got); -} - -#[test] -fn authority_id_works() { - let store = keystore(); - - let alice: crypto::Public = - SyncCryptoStore::ecdsa_generate_new(&*store, KEY_TYPE, Some(&Keyring::Alice.to_seed())) - .ok() - .unwrap() - .into(); - - let bob = Keyring::Bob.public(); - let charlie = Keyring::Charlie.public(); - - let store: BeefyKeystore = Some(store).into(); - - let mut keys = vec![bob, charlie]; - - let id = store.authority_id(keys.as_slice()); - assert!(id.is_none()); - - keys.push(alice.clone()); - - let id = store.authority_id(keys.as_slice()).unwrap(); - assert_eq!(id, alice); -} - -#[test] -fn sign_works() { - let store = keystore(); - - let alice: crypto::Public = - SyncCryptoStore::ecdsa_generate_new(&*store, KEY_TYPE, Some(&Keyring::Alice.to_seed())) - .ok() - .unwrap() - .into(); - - let store: BeefyKeystore = Some(store).into(); - - let msg = b"are you involved or commited?"; - - let sig1 = store.sign(&alice, msg).unwrap(); - let sig2 = Keyring::Alice.sign(msg); - - assert_eq!(sig1, sig2); -} - -#[test] -fn sign_error() { - let store = keystore(); - - let _ = SyncCryptoStore::ecdsa_generate_new(&*store, KEY_TYPE, Some(&Keyring::Bob.to_seed())) - .ok() - .unwrap(); - - let store: BeefyKeystore = Some(store).into(); - - let alice = Keyring::Alice.public(); - - let msg = b"are you involved or commited?"; - let sig = store.sign(&alice, msg).err().unwrap(); - let err = Error::Signature("ecdsa_sign_prehashed() failed".to_string()); - - assert_eq!(sig, err); -} - -#[test] -fn sign_no_keystore() { - let store: BeefyKeystore = None.into(); - - let alice = Keyring::Alice.public(); - let msg = b"are you involved or commited"; - - let sig = store.sign(&alice, msg).err().unwrap(); - let err = Error::Keystore("no Keystore".to_string()); - assert_eq!(sig, err); -} - -#[test] -fn verify_works() { - let store = keystore(); - - let alice: crypto::Public = - SyncCryptoStore::ecdsa_generate_new(&*store, KEY_TYPE, Some(&Keyring::Alice.to_seed())) - .ok() - .unwrap() - .into(); - - let store: BeefyKeystore = Some(store).into(); - - // `msg` and `sig` match - let msg = b"are you involved or commited?"; - let sig = store.sign(&alice, msg).unwrap(); - assert!(BeefyKeystore::verify(&alice, &sig, msg)); - - // `msg and `sig` don't match - let msg = b"you are just involved"; - assert!(!BeefyKeystore::verify(&alice, &sig, msg)); -} - -// Note that we use keys with and without a seed for this test. -#[test] -fn public_keys_works() { - const TEST_TYPE: sp_application_crypto::KeyTypeId = sp_application_crypto::KeyTypeId(*b"test"); - - let store = keystore(); - - let add_key = |key_type, seed: Option<&str>| { - SyncCryptoStore::ecdsa_generate_new(&*store, key_type, seed).unwrap() - }; - - // test keys - let _ = add_key(TEST_TYPE, Some(Keyring::Alice.to_seed().as_str())); - let _ = add_key(TEST_TYPE, Some(Keyring::Bob.to_seed().as_str())); - - let _ = add_key(TEST_TYPE, None); - let _ = add_key(TEST_TYPE, None); - - // BEEFY keys - let _ = add_key(KEY_TYPE, Some(Keyring::Dave.to_seed().as_str())); - let _ = add_key(KEY_TYPE, Some(Keyring::Eve.to_seed().as_str())); - - let key1: crypto::Public = add_key(KEY_TYPE, None).into(); - let key2: crypto::Public = add_key(KEY_TYPE, None).into(); - - let store: BeefyKeystore = Some(store).into(); - - let keys = store.public_keys().ok().unwrap(); - - assert!(keys.len() == 4); - assert!(keys.contains(&Keyring::Dave.public())); - assert!(keys.contains(&Keyring::Eve.public())); - assert!(keys.contains(&key1)); - assert!(keys.contains(&key2)); -} diff --git a/client/beefy/src/round.rs b/client/beefy/src/round.rs index 51284c9bd2f6..e9f5ad206243 100644 --- a/client/beefy/src/round.rs +++ b/client/beefy/src/round.rs @@ -123,3 +123,154 @@ where ) } } + +#[cfg(test)] +mod tests { + use sc_network_test::Block; + use sp_core::H256; + use sp_runtime::traits::NumberFor; + + use beefy_primitives::{crypto::Public, ValidatorSet}; + + use super::Rounds; + use crate::keystore::tests::Keyring; + + #[test] + fn new_rounds() { + sp_tracing::try_init_simple(); + + let rounds = Rounds::>::new(ValidatorSet::::empty()); + + assert_eq!(0, rounds.validator_set_id()); + assert!(rounds.validators().is_empty()); + + let validators = ValidatorSet:: { + validators: vec![ + Keyring::Alice.public(), + Keyring::Bob.public(), + Keyring::Charlie.public(), + ], + id: 42, + }; + + let rounds = Rounds::>::new(validators); + + assert_eq!(42, rounds.validator_set_id()); + + assert_eq!( + vec![Keyring::Alice.public(), Keyring::Bob.public(), Keyring::Charlie.public()], + rounds.validators() + ); + } + + #[test] + fn add_vote() { + sp_tracing::try_init_simple(); + + let validators = ValidatorSet:: { + validators: vec![ + Keyring::Alice.public(), + Keyring::Bob.public(), + Keyring::Charlie.public(), + ], + id: Default::default(), + }; + + let mut rounds = Rounds::>::new(validators); + + assert!(rounds.add_vote( + (H256::from_low_u64_le(1), 1), + (Keyring::Alice.public(), Keyring::Alice.sign(b"I am committed")) + )); + + assert!(!rounds.is_done(&(H256::from_low_u64_le(1), 1))); + + // invalid vote + assert!(!rounds.add_vote( + (H256::from_low_u64_le(1), 1), + (Keyring::Dave.public(), Keyring::Dave.sign(b"I am committed")) + )); + + assert!(!rounds.is_done(&(H256::from_low_u64_le(1), 1))); + + assert!(rounds.add_vote( + (H256::from_low_u64_le(1), 1), + (Keyring::Bob.public(), Keyring::Bob.sign(b"I am committed")) + )); + + assert!(!rounds.is_done(&(H256::from_low_u64_le(1), 1))); + + assert!(rounds.add_vote( + (H256::from_low_u64_le(1), 1), + (Keyring::Charlie.public(), Keyring::Charlie.sign(b"I am committed")) + )); + + assert!(rounds.is_done(&(H256::from_low_u64_le(1), 1))); + } + + #[test] + fn drop() { + sp_tracing::try_init_simple(); + + let validators = ValidatorSet:: { + validators: vec![ + Keyring::Alice.public(), + Keyring::Bob.public(), + Keyring::Charlie.public(), + ], + id: Default::default(), + }; + + let mut rounds = Rounds::>::new(validators); + + // round 1 + rounds.add_vote( + (H256::from_low_u64_le(1), 1), + (Keyring::Alice.public(), Keyring::Alice.sign(b"I am committed")), + ); + rounds.add_vote( + (H256::from_low_u64_le(1), 1), + (Keyring::Bob.public(), Keyring::Bob.sign(b"I am committed")), + ); + + // round 2 + rounds.add_vote( + (H256::from_low_u64_le(2), 2), + (Keyring::Alice.public(), Keyring::Alice.sign(b"I am again committed")), + ); + rounds.add_vote( + (H256::from_low_u64_le(2), 2), + (Keyring::Bob.public(), Keyring::Bob.sign(b"I am again committed")), + ); + + // round 3 + rounds.add_vote( + (H256::from_low_u64_le(3), 3), + (Keyring::Alice.public(), Keyring::Alice.sign(b"I am still committed")), + ); + rounds.add_vote( + (H256::from_low_u64_le(3), 3), + (Keyring::Bob.public(), Keyring::Bob.sign(b"I am still committed")), + ); + + assert_eq!(3, rounds.rounds.len()); + + // drop unknown round + assert!(rounds.drop(&(H256::from_low_u64_le(5), 5)).is_none()); + assert_eq!(3, rounds.rounds.len()); + + // drop round 2 + let signatures = rounds.drop(&(H256::from_low_u64_le(2), 2)).unwrap(); + + assert_eq!(2, rounds.rounds.len()); + + assert_eq!( + signatures, + vec![ + Some(Keyring::Alice.sign(b"I am again committed")), + Some(Keyring::Bob.sign(b"I am again committed")), + None + ] + ); + } +} From 4f3c3a5d9b6587482f5a57e83c44fcfb79d4d844 Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Fri, 26 Nov 2021 05:38:21 +0100 Subject: [PATCH 236/695] remove base weight annotations (#10373) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * remove base weight annotations * Update frame/scheduler/src/lib.rs Co-authored-by: Shawn Tabrizi Co-authored-by: Damilare Co-authored-by: Bastian Köcher Co-authored-by: Shawn Tabrizi --- frame/balances/src/lib.rs | 17 -------------- frame/scheduler/src/lib.rs | 46 -------------------------------------- frame/system/src/lib.rs | 29 ------------------------ 3 files changed, 92 deletions(-) diff --git a/frame/balances/src/lib.rs b/frame/balances/src/lib.rs index b7c64da46076..4471ed91a9af 100644 --- a/frame/balances/src/lib.rs +++ b/frame/balances/src/lib.rs @@ -271,8 +271,6 @@ pub mod pallet { /// - `transfer_keep_alive` works the same way as `transfer`, but has an additional check /// that the transfer will not kill the origin account. /// --------------------------------- - /// - Base Weight: 73.64 µs, worst case scenario (account created, account removed) - /// - DB Weight: 1 Read and 1 Write to destination account /// - Origin account is already in memory, so no DB operations for them. /// # #[pallet::weight(T::WeightInfo::transfer())] @@ -300,16 +298,6 @@ pub mod pallet { /// it will reset the account nonce (`frame_system::AccountNonce`). /// /// The dispatch origin for this call is `root`. - /// - /// # - /// - Independent of the arguments. - /// - Contains a limited number of reads and writes. - /// --------------------- - /// - Base Weight: - /// - Creating: 27.56 µs - /// - Killing: 35.11 µs - /// - DB Weight: 1 Read, 1 Write to `who` - /// # #[pallet::weight( T::WeightInfo::set_balance_creating() // Creates a new account. .max(T::WeightInfo::set_balance_killing()) // Kills an existing account. @@ -381,11 +369,6 @@ pub mod pallet { /// 99% of the time you want [`transfer`] instead. /// /// [`transfer`]: struct.Pallet.html#method.transfer - /// # - /// - Cheaper than transfer because account cannot be killed. - /// - Base Weight: 51.4 µs - /// - DB Weight: 1 Read and 1 Write to dest (sender is in overlay already) - /// # #[pallet::weight(T::WeightInfo::transfer_keep_alive())] pub fn transfer_keep_alive( origin: OriginFor, diff --git a/frame/scheduler/src/lib.rs b/frame/scheduler/src/lib.rs index d59c42cc850d..d25fc3b376e8 100644 --- a/frame/scheduler/src/lib.rs +++ b/frame/scheduler/src/lib.rs @@ -243,16 +243,6 @@ pub mod pallet { #[pallet::hooks] impl Hooks> for Pallet { /// Execute the scheduled calls - /// - /// # - /// - S = Number of already scheduled calls - /// - N = Named scheduled calls - /// - P = Periodic Calls - /// - Base Weight: 9.243 + 23.45 * S µs - /// - DB Weight: - /// - Read: Agenda + Lookup * N + Agenda(Future) * P - /// - Write: Agenda + Lookup * N + Agenda(future) * P - /// # fn on_initialize(now: T::BlockNumber) -> Weight { let limit = T::MaximumWeight::get(); let mut queued = Agenda::::take(now) @@ -352,15 +342,6 @@ pub mod pallet { #[pallet::call] impl Pallet { /// Anonymously schedule a task. - /// - /// # - /// - S = Number of already scheduled calls - /// - Base Weight: 22.29 + .126 * S µs - /// - DB Weight: - /// - Read: Agenda - /// - Write: Agenda - /// - Will use base weight of 25 which should be good for up to 30 scheduled calls - /// # #[pallet::weight(::WeightInfo::schedule(T::MaxScheduledPerBlock::get()))] pub fn schedule( origin: OriginFor, @@ -382,15 +363,6 @@ pub mod pallet { } /// Cancel an anonymously scheduled task. - /// - /// # - /// - S = Number of already scheduled calls - /// - Base Weight: 22.15 + 2.869 * S µs - /// - DB Weight: - /// - Read: Agenda - /// - Write: Agenda, Lookup - /// - Will use base weight of 100 which should be good for up to 30 scheduled calls - /// # #[pallet::weight(::WeightInfo::cancel(T::MaxScheduledPerBlock::get()))] pub fn cancel(origin: OriginFor, when: T::BlockNumber, index: u32) -> DispatchResult { T::ScheduleOrigin::ensure_origin(origin.clone())?; @@ -400,15 +372,6 @@ pub mod pallet { } /// Schedule a named task. - /// - /// # - /// - S = Number of already scheduled calls - /// - Base Weight: 29.6 + .159 * S µs - /// - DB Weight: - /// - Read: Agenda, Lookup - /// - Write: Agenda, Lookup - /// - Will use base weight of 35 which should be good for more than 30 scheduled calls - /// # #[pallet::weight(::WeightInfo::schedule_named(T::MaxScheduledPerBlock::get()))] pub fn schedule_named( origin: OriginFor, @@ -432,15 +395,6 @@ pub mod pallet { } /// Cancel a named scheduled task. - /// - /// # - /// - S = Number of already scheduled calls - /// - Base Weight: 24.91 + 2.907 * S µs - /// - DB Weight: - /// - Read: Agenda, Lookup - /// - Write: Agenda, Lookup - /// - Will use base weight of 100 which should be good for up to 30 scheduled calls - /// # #[pallet::weight(::WeightInfo::cancel_named(T::MaxScheduledPerBlock::get()))] pub fn cancel_named(origin: OriginFor, id: Vec) -> DispatchResult { T::ScheduleOrigin::ensure_origin(origin.clone())?; diff --git a/frame/system/src/lib.rs b/frame/system/src/lib.rs index 12361ed859d0..0b00a7d8f597 100644 --- a/frame/system/src/lib.rs +++ b/frame/system/src/lib.rs @@ -351,14 +351,6 @@ pub mod pallet { } /// Set the number of pages in the WebAssembly environment's heap. - /// - /// # - /// - `O(1)` - /// - 1 storage write. - /// - Base Weight: 1.405 µs - /// - 1 write to HEAP_PAGES - /// - 1 digest item - /// # #[pallet::weight((T::SystemWeightInfo::set_heap_pages(), DispatchClass::Operational))] pub fn set_heap_pages(origin: OriginFor, pages: u64) -> DispatchResultWithPostInfo { ensure_root(origin)?; @@ -407,13 +399,6 @@ pub mod pallet { } /// Set some items of storage. - /// - /// # - /// - `O(I)` where `I` length of `items` - /// - `I` storage writes (`O(1)`). - /// - Base Weight: 0.568 * i µs - /// - Writes: Number of items - /// # #[pallet::weight(( T::SystemWeightInfo::set_storage(items.len() as u32), DispatchClass::Operational, @@ -430,13 +415,6 @@ pub mod pallet { } /// Kill some items from storage. - /// - /// # - /// - `O(IK)` where `I` length of `keys` and `K` length of one key - /// - `I` storage deletions. - /// - Base Weight: .378 * i µs - /// - Writes: Number of items - /// # #[pallet::weight(( T::SystemWeightInfo::kill_storage(keys.len() as u32), DispatchClass::Operational, @@ -453,13 +431,6 @@ pub mod pallet { /// /// **NOTE:** We rely on the Root origin to provide us the number of subkeys under /// the prefix we are removing to accurately calculate the weight of this function. - /// - /// # - /// - `O(P)` where `P` amount of keys with prefix `prefix` - /// - `P` storage deletions. - /// - Base Weight: 0.834 * P µs - /// - Writes: Number of subkeys + 1 - /// # #[pallet::weight(( T::SystemWeightInfo::kill_prefix(_subkeys.saturating_add(1)), DispatchClass::Operational, From de6033a2aa4f0191877200516fbc2655399faa4b Mon Sep 17 00:00:00 2001 From: Keith Yeung Date: Fri, 26 Nov 2021 00:58:00 -0800 Subject: [PATCH 237/695] Update W3F URL links (#10374) --- frame/staking/src/slashing.rs | 2 +- frame/transaction-payment/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frame/staking/src/slashing.rs b/frame/staking/src/slashing.rs index 066142d8ecc2..acfb30fb8148 100644 --- a/frame/staking/src/slashing.rs +++ b/frame/staking/src/slashing.rs @@ -47,7 +47,7 @@ //! has multiple misbehaviors. However, accounting for such cases is necessary //! to deter a class of "rage-quit" attacks. //! -//! Based on research at +//! Based on research at use crate::{ BalanceOf, Config, EraIndex, Error, Exposure, NegativeImbalanceOf, Pallet, Perbill, diff --git a/frame/transaction-payment/src/lib.rs b/frame/transaction-payment/src/lib.rs index a0d8aeb11706..f912866f7bb3 100644 --- a/frame/transaction-payment/src/lib.rs +++ b/frame/transaction-payment/src/lib.rs @@ -127,7 +127,7 @@ type BalanceOf = <::OnChargeTransaction as OnChargeTransaction +/// pub struct TargetedFeeAdjustment(sp_std::marker::PhantomData<(T, S, V, M)>); /// Something that can convert the current multiplier to the next one. From 3fdb445b3b14880017680a3af85e89fb591666a0 Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Sun, 28 Nov 2021 13:47:33 +0100 Subject: [PATCH 238/695] Reduce the execution time of some tests (#10377) * Reduce the execution time of some tests * Fix * Fix build * fmt --- bin/node/runtime/src/lib.rs | 17 +- frame/babe/src/mock.rs | 3 +- .../election-provider-multi-phase/src/lib.rs | 10 - .../election-provider-multi-phase/src/mock.rs | 15 +- frame/grandpa/src/mock.rs | 1 + frame/offences/benchmarking/src/mock.rs | 1 + frame/session/benchmarking/src/mock.rs | 1 + frame/staking/fuzzer/src/mock.rs | 202 ------------------ frame/staking/src/benchmarking.rs | 17 +- frame/staking/src/lib.rs | 22 +- frame/staking/src/mock.rs | 3 +- frame/staking/src/pallet/mod.rs | 5 + 12 files changed, 68 insertions(+), 229 deletions(-) delete mode 100644 frame/staking/fuzzer/src/mock.rs diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 299b7257f9d4..44cefecd067f 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -26,8 +26,8 @@ use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::{ construct_runtime, parameter_types, traits::{ - Currency, EqualPrivilegeOnly, Everything, Imbalance, InstanceFilter, KeyOwnerProofSystem, - LockIdentifier, Nothing, OnUnbalanced, U128CurrencyToVote, + ConstU32, Currency, EqualPrivilegeOnly, Everything, Imbalance, InstanceFilter, + KeyOwnerProofSystem, LockIdentifier, Nothing, OnUnbalanced, U128CurrencyToVote, }, weights::{ constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND}, @@ -515,6 +515,12 @@ impl onchain::Config for Runtime { type DataProvider = Staking; } +pub struct StakingBenchmarkingConfig; +impl pallet_staking::BenchmarkingConfig for StakingBenchmarkingConfig { + type MaxNominators = ConstU32<1000>; + type MaxValidators = ConstU32<1000>; +} + impl pallet_staking::Config for Runtime { const MAX_NOMINATIONS: u32 = MAX_NOMINATIONS; type Currency = Balances; @@ -544,6 +550,7 @@ impl pallet_staking::Config for Runtime { // Note that the aforementioned does not scale to a very large number of nominators. type SortedListProvider = BagsList; type WeightInfo = pallet_staking::weights::SubstrateWeight; + type BenchmarkingConfig = StakingBenchmarkingConfig; } parameter_types! { @@ -591,8 +598,8 @@ pub const MAX_NOMINATIONS: u32 = ; type WeightInfo = pallet_election_provider_multi_phase::weights::SubstrateWeight; type ForceOrigin = EnsureRootOrHalfCouncil; - type BenchmarkingConfig = BenchmarkConfig; + type BenchmarkingConfig = ElectionProviderBenchmarkConfig; type VoterSnapshotPerBlock = VoterSnapshotPerBlock; } diff --git a/frame/babe/src/mock.rs b/frame/babe/src/mock.rs index e7ec69268903..f62e73aa4391 100644 --- a/frame/babe/src/mock.rs +++ b/frame/babe/src/mock.rs @@ -215,8 +215,9 @@ impl pallet_staking::Config for Test { type NextNewSession = Session; type ElectionProvider = onchain::OnChainSequentialPhragmen; type GenesisElectionProvider = Self::ElectionProvider; - type WeightInfo = (); type SortedListProvider = pallet_staking::UseNominatorsMap; + type BenchmarkingConfig = pallet_staking::TestBenchmarkingConfig; + type WeightInfo = (); } impl pallet_offences::Config for Test { diff --git a/frame/election-provider-multi-phase/src/lib.rs b/frame/election-provider-multi-phase/src/lib.rs index ee4c9ae45d42..70bbed95fe97 100644 --- a/frame/election-provider-multi-phase/src/lib.rs +++ b/frame/election-provider-multi-phase/src/lib.rs @@ -309,16 +309,6 @@ pub trait BenchmarkingConfig { const MAXIMUM_TARGETS: u32; } -impl BenchmarkingConfig for () { - const VOTERS: [u32; 2] = [4000, 6000]; - const TARGETS: [u32; 2] = [1000, 1600]; - const ACTIVE_VOTERS: [u32; 2] = [1000, 3000]; - const DESIRED_TARGETS: [u32; 2] = [400, 800]; - const SNAPSHOT_MAXIMUM_VOTERS: u32 = 10_000; - const MINER_MAXIMUM_VOTERS: u32 = 10_000; - const MAXIMUM_TARGETS: u32 = 2_000; -} - /// A fallback implementation that transitions the pallet to the emergency phase. pub struct NoFallback(sp_std::marker::PhantomData); diff --git a/frame/election-provider-multi-phase/src/mock.rs b/frame/election-provider-multi-phase/src/mock.rs index fbde6ad99170..f90c64b75ccb 100644 --- a/frame/election-provider-multi-phase/src/mock.rs +++ b/frame/election-provider-multi-phase/src/mock.rs @@ -377,6 +377,19 @@ parameter_types! { pub static Balancing: Option<(usize, ExtendedBalance)> = Some((0, 0)); } +pub struct TestBenchmarkingConfig; +impl BenchmarkingConfig for TestBenchmarkingConfig { + const VOTERS: [u32; 2] = [400, 600]; + const ACTIVE_VOTERS: [u32; 2] = [100, 300]; + const TARGETS: [u32; 2] = [200, 400]; + const DESIRED_TARGETS: [u32; 2] = [100, 180]; + + const SNAPSHOT_MAXIMUM_VOTERS: u32 = 1000; + const MINER_MAXIMUM_VOTERS: u32 = 1000; + + const MAXIMUM_TARGETS: u32 = 200; +} + impl crate::Config for Runtime { type Event = Event; type Currency = Balances; @@ -398,7 +411,7 @@ impl crate::Config for Runtime { type RewardHandler = (); type DataProvider = StakingMock; type WeightInfo = DualMockWeightInfo; - type BenchmarkingConfig = (); + type BenchmarkingConfig = TestBenchmarkingConfig; type Fallback = MockFallback; type ForceOrigin = frame_system::EnsureRoot; type Solution = TestNposSolution; diff --git a/frame/grandpa/src/mock.rs b/frame/grandpa/src/mock.rs index 49e4022a4aae..fe7a530ffe0c 100644 --- a/frame/grandpa/src/mock.rs +++ b/frame/grandpa/src/mock.rs @@ -218,6 +218,7 @@ impl pallet_staking::Config for Test { type ElectionProvider = onchain::OnChainSequentialPhragmen; type GenesisElectionProvider = Self::ElectionProvider; type SortedListProvider = pallet_staking::UseNominatorsMap; + type BenchmarkingConfig = pallet_staking::TestBenchmarkingConfig; type WeightInfo = (); } diff --git a/frame/offences/benchmarking/src/mock.rs b/frame/offences/benchmarking/src/mock.rs index 3097f9b95be3..26a53c7f8a04 100644 --- a/frame/offences/benchmarking/src/mock.rs +++ b/frame/offences/benchmarking/src/mock.rs @@ -178,6 +178,7 @@ impl pallet_staking::Config for Test { type ElectionProvider = onchain::OnChainSequentialPhragmen; type GenesisElectionProvider = Self::ElectionProvider; type SortedListProvider = pallet_staking::UseNominatorsMap; + type BenchmarkingConfig = pallet_staking::TestBenchmarkingConfig; type WeightInfo = (); } diff --git a/frame/session/benchmarking/src/mock.rs b/frame/session/benchmarking/src/mock.rs index f534cc097e8a..e000255b84b8 100644 --- a/frame/session/benchmarking/src/mock.rs +++ b/frame/session/benchmarking/src/mock.rs @@ -183,6 +183,7 @@ impl pallet_staking::Config for Test { type ElectionProvider = onchain::OnChainSequentialPhragmen; type GenesisElectionProvider = Self::ElectionProvider; type SortedListProvider = pallet_staking::UseNominatorsMap; + type BenchmarkingConfig = pallet_staking::TestBenchmarkingConfig; type WeightInfo = (); } diff --git a/frame/staking/fuzzer/src/mock.rs b/frame/staking/fuzzer/src/mock.rs deleted file mode 100644 index d5ca78193b0c..000000000000 --- a/frame/staking/fuzzer/src/mock.rs +++ /dev/null @@ -1,202 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2020-2021 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. - -//! Mock file for staking fuzzing. - -use frame_support::parameter_types; - -type AccountId = u64; -type AccountIndex = u32; -type BlockNumber = u64; -type Balance = u64; - -type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; -type Block = frame_system::mocking::MockBlock; - -frame_support::construct_runtime!( - pub enum Test where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic, - { - System: frame_system::{Pallet, Call, Config, Storage, Event}, - Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, - Staking: pallet_staking::{Pallet, Call, Config, Storage, Event, ValidateUnsigned}, - Indices: pallet_indices::{Pallet, Call, Storage, Config, Event}, - Session: pallet_session::{Pallet, Call, Storage, Event, Config}, - } -); - -impl frame_system::Config for Test { - type BaseCallFilter = frame_support::traits::Everything; - type BlockWeights = (); - type BlockLength = (); - type DbWeight = (); - type Origin = Origin; - type Index = AccountIndex; - type BlockNumber = BlockNumber; - type Call = Call; - type Hash = sp_core::H256; - type Hashing = ::sp_runtime::traits::BlakeTwo256; - type AccountId = AccountId; - type Lookup = Indices; - type Header = sp_runtime::testing::Header; - type Event = Event; - type BlockHashCount = (); - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = (); - type OnSetCode = (); -} -parameter_types! { - pub const ExistentialDeposit: Balance = 10; -} -impl pallet_balances::Config for Test { - type MaxLocks = (); - type MaxReserves = (); - type ReserveIdentifier = [u8; 8]; - type Balance = Balance; - type Event = Event; - type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; - type AccountStore = System; - type WeightInfo = (); -} -impl pallet_indices::Config for Test { - type AccountIndex = AccountIndex; - type Event = Event; - type Currency = Balances; - type Deposit = (); - type WeightInfo = (); -} -parameter_types! { - pub const MinimumPeriod: u64 = 5; -} -impl pallet_timestamp::Config for Test { - type Moment = u64; - type OnTimestampSet = (); - type MinimumPeriod = MinimumPeriod; - type WeightInfo = (); -} -impl pallet_session::historical::Config for Test { - type FullIdentification = pallet_staking::Exposure; - type FullIdentificationOf = pallet_staking::ExposureOf; -} - -sp_runtime::impl_opaque_keys! { - pub struct SessionKeys { - pub foo: sp_runtime::testing::UintAuthorityId, - } -} - -pub struct TestSessionHandler; -impl pallet_session::SessionHandler for TestSessionHandler { - const KEY_TYPE_IDS: &'static [sp_runtime::KeyTypeId] = &[]; - - fn on_genesis_session(_validators: &[(AccountId, Ks)]) {} - - fn on_new_session( - _: bool, - _: &[(AccountId, Ks)], - _: &[(AccountId, Ks)], - ) {} - - fn on_disabled(_: u32) {} -} - -impl pallet_session::Config for Test { - type SessionManager = pallet_session::historical::NoteHistoricalRoot; - type Keys = SessionKeys; - type ShouldEndSession = pallet_session::PeriodicSessions<(), ()>; - type NextSessionRotation = pallet_session::PeriodicSessions<(), ()>; - type SessionHandler = TestSessionHandler; - type Event = Event; - type ValidatorId = AccountId; - type ValidatorIdOf = pallet_staking::StashOf; - type DisabledValidatorsThreshold = (); - type WeightInfo = (); -} -pallet_staking_reward_curve::build! { - const I_NPOS: sp_runtime::curve::PiecewiseLinear<'static> = curve!( - min_inflation: 0_025_000, - max_inflation: 0_100_000, - ideal_stake: 0_500_000, - falloff: 0_050_000, - max_piece_count: 40, - test_precision: 0_005_000, - ); -} -parameter_types! { - pub const RewardCurve: &'static sp_runtime::curve::PiecewiseLinear<'static> = &I_NPOS; - pub const MaxNominatorRewardedPerValidator: u32 = 64; - pub const MaxIterations: u32 = 20; -} - -pub type Extrinsic = sp_runtime::testing::TestXt; - -impl frame_system::offchain::SendTransactionTypes for Test -where - Call: From, -{ - type OverarchingCall = Call; - type Extrinsic = Extrinsic; -} - -pub struct MockElectionProvider; -impl frame_election_provider_support::ElectionProvider - for MockElectionProvider -{ - type Error = (); - type DataProvider = pallet_staking::Module; - - fn elect() -> Result< - (sp_npos_elections::Supports, frame_support::weights::Weight), - Self::Error - > { - Err(()) - } -} - -impl pallet_staking::Config for Test { - type Currency = Balances; - type UnixTime = pallet_timestamp::Pallet; - type CurrencyToVote = frame_support::traits::SaturatingCurrencyToVote; - type RewardRemainder = (); - type Event = Event; - type Slash = (); - type Reward = (); - type SessionsPerEra = (); - type SlashDeferDuration = (); - type SlashCancelOrigin = frame_system::EnsureRoot; - type BondingDuration = (); - type SessionInterface = Self; - type EraPayout = pallet_staking::ConvertCurve; - type NextNewSession = Session; - type ElectionLookahead = (); - type Call = Call; - type MaxIterations = MaxIterations; - type MinSolutionScoreBump = (); - type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator; - type UnsignedPriority = (); - type OffchainSolutionWeightLimit = (); - type WeightInfo = (); - type ElectionProvider = MockElectionProvider; -} diff --git a/frame/staking/src/benchmarking.rs b/frame/staking/src/benchmarking.rs index e312aedbec1f..5feb1692d955 100644 --- a/frame/staking/src/benchmarking.rs +++ b/frame/staking/src/benchmarking.rs @@ -41,10 +41,11 @@ use frame_system::RawOrigin; const SEED: u32 = 0; const MAX_SPANS: u32 = 100; -const MAX_VALIDATORS: u32 = 1000; -const MAX_NOMINATORS: u32 = 1000; const MAX_SLASHES: u32 = 1000; +type MaxValidators = <::BenchmarkingConfig as BenchmarkingConfig>::MaxValidators; +type MaxNominators = <::BenchmarkingConfig as BenchmarkingConfig>::MaxNominators; + // Add slashing spans to a user account. Not relevant for actual use, only to benchmark // read and write operations. fn add_slashing_spans(who: &T::AccountId, spans: u32) { @@ -481,7 +482,7 @@ benchmarks! { } set_validator_count { - let validator_count = MAX_VALIDATORS; + let validator_count = MaxValidators::::get(); }: _(RawOrigin::Root, validator_count) verify { assert_eq!(ValidatorCount::::get(), validator_count); @@ -498,7 +499,7 @@ benchmarks! { // Worst case scenario, the list of invulnerables is very long. set_invulnerables { - let v in 0 .. MAX_VALIDATORS; + let v in 0 .. MaxValidators::::get(); let mut invulnerables = Vec::new(); for i in 0 .. v { invulnerables.push(account("invulnerable", i, SEED)); @@ -804,9 +805,9 @@ benchmarks! { get_npos_voters { // number of validator intention. - let v in (MAX_VALIDATORS / 2) .. MAX_VALIDATORS; + let v in (MaxValidators::::get() / 2) .. MaxValidators::::get(); // number of nominator intention. - let n in (MAX_NOMINATORS / 2) .. MAX_NOMINATORS; + let n in (MaxNominators::::get() / 2) .. MaxNominators::::get(); // total number of slashing spans. Assigned to validators randomly. let s in 1 .. 20; @@ -829,9 +830,9 @@ benchmarks! { get_npos_targets { // number of validator intention. - let v in (MAX_VALIDATORS / 2) .. MAX_VALIDATORS; + let v in (MaxValidators::::get() / 2) .. MaxValidators::::get(); // number of nominator intention. - let n = MAX_NOMINATORS; + let n = MaxNominators::::get(); let _ = create_validators_with_nominators_for_era::( v, n, T::MAX_NOMINATIONS as usize, false, None diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index cb91abe476cb..f2e5f0f78389 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -301,7 +301,7 @@ mod pallet; use codec::{Decode, Encode, HasCompact}; use frame_support::{ - traits::{Currency, Get}, + traits::{ConstU32, Currency, Get}, weights::Weight, }; use scale_info::TypeInfo; @@ -807,3 +807,23 @@ where R::is_known_offence(offenders, time_slot) } } + +/// Configurations of the benchmarking of the pallet. +pub trait BenchmarkingConfig { + /// The maximum number of validators to use. + type MaxValidators: Get; + /// The maximum number of nominators to use. + type MaxNominators: Get; +} + +/// A mock benchmarking config for pallet-staking. +/// +/// Should only be used for testing. +#[cfg(feature = "std")] +pub struct TestBenchmarkingConfig; + +#[cfg(feature = "std")] +impl BenchmarkingConfig for TestBenchmarkingConfig { + type MaxValidators = ConstU32<100>; + type MaxNominators = ConstU32<100>; +} diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index 2b74b0188cff..0b1d6a06d9c7 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -272,9 +272,10 @@ impl crate::pallet::pallet::Config for Test { type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type ElectionProvider = onchain::OnChainSequentialPhragmen; type GenesisElectionProvider = Self::ElectionProvider; - type WeightInfo = (); // NOTE: consider a macro and use `UseNominatorsMap` as well. type SortedListProvider = BagsList; + type BenchmarkingConfig = TestBenchmarkingConfig; + type WeightInfo = (); } impl frame_system::offchain::SendTransactionTypes for Test diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 542b79b792dc..f8f9c8c794dc 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -50,6 +50,8 @@ const STAKING_ID: LockIdentifier = *b"staking "; #[frame_support::pallet] pub mod pallet { + use crate::BenchmarkingConfig; + use super::*; #[pallet::pallet] @@ -151,6 +153,9 @@ pub mod pallet { /// the bags-list is not desired, [`impls::UseNominatorsMap`] is likely the desired option. type SortedListProvider: SortedListProvider; + /// Some parameters of the benchmarking. + type BenchmarkingConfig: BenchmarkingConfig; + /// Weight information for extrinsics in this pallet. type WeightInfo: WeightInfo; } From f2cecdbf3fa5b98f5638719109a0ce43303b7160 Mon Sep 17 00:00:00 2001 From: Guillaume Thiolliere Date: Mon, 29 Nov 2021 17:16:23 +0900 Subject: [PATCH 239/695] ignoring errors and some fix (#10344) --- client/network/src/block_request_handler.rs | 2 +- .../src/light_client_requests/handler.rs | 2 +- client/network/src/service.rs | 9 ++--- client/network/src/state_request_handler.rs | 2 +- client/service/src/client/mod.rs | 5 ++- utils/frame/try-runtime/cli/src/lib.rs | 36 +++++++++---------- 6 files changed, 26 insertions(+), 30 deletions(-) diff --git a/client/network/src/block_request_handler.rs b/client/network/src/block_request_handler.rs index 3ea7833970d9..9d963480a7e0 100644 --- a/client/network/src/block_request_handler.rs +++ b/client/network/src/block_request_handler.rs @@ -15,7 +15,7 @@ // along with Substrate. If not, see . //! Helper for handling (i.e. answering) block requests from a remote peer via the -//! [`crate::request_responses::RequestResponsesBehaviour`]. +//! `crate::request_responses::RequestResponsesBehaviour`. use crate::{ chain::Client, diff --git a/client/network/src/light_client_requests/handler.rs b/client/network/src/light_client_requests/handler.rs index a04c5e310a67..5ecc85bdb0a0 100644 --- a/client/network/src/light_client_requests/handler.rs +++ b/client/network/src/light_client_requests/handler.rs @@ -19,7 +19,7 @@ //! Helper for incoming light client requests. //! //! Handle (i.e. answer) incoming light client requests from a remote peer received via -//! [`crate::request_responses::RequestResponsesBehaviour`] with +//! `crate::request_responses::RequestResponsesBehaviour` with //! [`LightClientRequestHandler`](handler::LightClientRequestHandler). use crate::{ diff --git a/client/network/src/service.rs b/client/network/src/service.rs index 3dadf810c6b4..4377ff358de7 100644 --- a/client/network/src/service.rs +++ b/client/network/src/service.rs @@ -710,8 +710,7 @@ impl NetworkService { /// > preventing the message from being delivered. /// /// The protocol must have been registered with - /// [`NetworkConfiguration::notifications_protocols`](crate::config::NetworkConfiguration:: - /// notifications_protocols). + /// `crate::config::NetworkConfiguration::notifications_protocols`. pub fn write_notification( &self, target: PeerId, @@ -775,8 +774,7 @@ impl NetworkService { /// in which case enqueued notifications will be lost. /// /// The protocol must have been registered with - /// [`NetworkConfiguration::notifications_protocols`](crate::config::NetworkConfiguration:: - /// notifications_protocols). + /// `crate::config::NetworkConfiguration::notifications_protocols`. /// /// # Usage /// @@ -817,8 +815,7 @@ impl NetworkService { /// if buffer is full /// /// - /// See also the [`gossip`](crate::gossip) module for a higher-level way to send - /// notifications. + /// See also the `sc-network-gossip` crate for a higher-level way to send notifications. pub fn notification_sender( &self, target: PeerId, diff --git a/client/network/src/state_request_handler.rs b/client/network/src/state_request_handler.rs index 0d710c13af60..89f1f2b363c4 100644 --- a/client/network/src/state_request_handler.rs +++ b/client/network/src/state_request_handler.rs @@ -15,7 +15,7 @@ // along with Substrate. If not, see . //! Helper for handling (i.e. answering) state requests from a remote peer via the -//! [`crate::request_responses::RequestResponsesBehaviour`]. +//! `crate::request_responses::RequestResponsesBehaviour`. use crate::{ chain::Client, diff --git a/client/service/src/client/mod.rs b/client/service/src/client/mod.rs index 7743f479a171..d10b3d16b813 100644 --- a/client/service/src/client/mod.rs +++ b/client/service/src/client/mod.rs @@ -37,9 +37,8 @@ //! The latter typically requires passing one of: //! //! - A [`LocalCallExecutor`] running the runtime locally. -//! - A [`RemoteCallExecutor`](sc_client_api::light::RemoteCallRequest) that will ask a -//! third-party to perform the executions. -//! - A [`RemoteOrLocalCallExecutor`](sc_client_api::light::LocalOrRemote), combination of the two. +//! - A `RemoteCallExecutor` that will ask a third-party to perform the executions. +//! - A `RemoteOrLocalCallExecutor` combination of the two. //! //! Additionally, the fourth generic parameter of the `Client` is a marker type representing //! the ways in which the runtime can interface with the outside. Any code that builds a `Client` diff --git a/utils/frame/try-runtime/cli/src/lib.rs b/utils/frame/try-runtime/cli/src/lib.rs index 4aa1c213703e..8b8c6b2d2bb3 100644 --- a/utils/frame/try-runtime/cli/src/lib.rs +++ b/utils/frame/try-runtime/cli/src/lib.rs @@ -125,7 +125,7 @@ //! #### Adding pre/post hooks //! //! One of the gems that come only in the `try-runtime` feature flag is the `pre_upgrade` and -//! `post_upgrade` hooks for [`OnRuntimeUpgrade`]. This trait is implemented either inside the +//! `post_upgrade` hooks for `OnRuntimeUpgrade`. This trait is implemented either inside the //! pallet, or manually in a runtime, to define a migration. In both cases, these functions can be //! added, given the right flag: //! @@ -141,7 +141,7 @@ //! //! These hooks allow you to execute some code, only within the `on-runtime-upgrade` command, before //! and after the migration. If any data needs to be temporarily stored between the pre/post -//! migration hooks, [`OnRuntimeUpgradeHelpersExt`] can help with that. +//! migration hooks, `OnRuntimeUpgradeHelpersExt` can help with that. //! //! #### Logging //! @@ -151,7 +151,7 @@ //! //! #### Guarding migrations //! -//! Always make sure that any migration code is guarded either by [`StorageVersion`], or by some +//! Always make sure that any migration code is guarded either by `StorageVersion`, or by some //! custom storage item, so that it is NEVER executed twice, even if the code lives in two //! consecutive runtimes. //! @@ -160,7 +160,7 @@ //! Run the migrations of the local runtime on the state of polkadot, from the polkadot repo where //! we have `--chain polkadot-dev`, on the latest finalized block's state //! -//! ```ignore +//! ```sh //! RUST_LOG=runtime=trace,try-runtime::cli=trace,executor=trace \ //! cargo run try-runtime \ //! --execution Native \ @@ -174,7 +174,7 @@ //! Same as previous one, but let's say we want to run this command from the substrate repo, where //! we don't have a matching spec name/version. //! -//! ```ignore +//! ```sh //! RUST_LOG=runtime=trace,try-runtime::cli=trace,executor=trace \ //! cargo run try-runtime \ //! --execution Native \ @@ -188,7 +188,7 @@ //! Same as the previous one, but run it at specific block number's state. This means that this //! block hash's state shall not yet have been pruned in `rpc.polkadot.io`. //! -//! ```ignore +//! ```sh //! RUST_LOG=runtime=trace,try-runtime::cli=trace,executor=trace \ //! cargo run try-runtime \ //! --execution Native \ @@ -206,7 +206,7 @@ //! First, let's assume you are in a branch that has the same spec name/version as the live polkadot //! network. //! -//! ```ignore +//! ```sh //! RUST_LOG=runtime=trace,try-runtime::cli=trace,executor=trace \ //! cargo run try-runtime \ //! --execution Wasm \ @@ -222,14 +222,14 @@ //! change `--execution Wasm` to `--execution Native` to achieve this. Your logs of `executor=trace` //! should show something among the lines of: //! -//! ```ignore +//! ```text //! Request for native execution succeeded (native: polkadot-9900 (parity-polkadot-0.tx7.au0), chain: polkadot-9900 (parity-polkadot-0.tx7.au0)) //! ``` //! //! If you don't have matching spec versions, then are doomed to execute wasm. In this case, you can //! manually overwrite the wasm code with your local runtime: //! -//! ```ignore +//! ```sh //! RUST_LOG=runtime=trace,try-runtime::cli=trace,executor=trace \ //! cargo run try-runtime \ //! --execution Wasm \ @@ -242,12 +242,12 @@ //! ``` //! //! For all of these blocks, the block with hash `` is being used, and the initial state -//! is the state of the parent hash. This is because by omitting [`ExecuteBlockCmd::block_at`], the +//! is the state of the parent hash. This is because by omitting `ExecuteBlockCmd::block_at`, the //! `--at` is used for both. This should be good enough for 99% of the cases. The only case where //! you need to specify `block-at` and `block-ws-uri` is with snapshots. Let's say you have a file //! `snap` and you know it corresponds to the state of the parent block of `X`. Then you'd do: //! -//! ```ignore +//! ```sh //! RUST_LOG=runtime=trace,try-runtime::cli=trace,executor=trace \ //! cargo run try-runtime \ //! --execution Wasm \ @@ -306,7 +306,7 @@ pub enum Command { /// Executes the given block against some state. /// - /// Unlike [`Command:::OnRuntimeUpgrade`], this command needs two inputs: the state, and the + /// Unlike [`Command::OnRuntimeUpgrade`], this command needs two inputs: the state, and the /// block data. Since the state could be cached (see [`State::Snap`]), different flags are /// provided for both. `--block-at` and `--block-uri`, if provided, are only used for fetching /// the block. For convenience, these flags can be both emitted, if the [`State::Live`] is @@ -314,7 +314,7 @@ pub enum Command { /// /// Note that by default, this command does not overwrite the code, so in wasm execution, the /// live chain's code is used. This can be disabled if desired, see - /// [`ExecuteBlockCmd::overwrite_wasm_code`]. + /// `ExecuteBlockCmd::overwrite_wasm_code`. /// /// Note that if you do overwrite the wasm code, or generally use the local runtime for this, /// you might @@ -326,7 +326,7 @@ pub enum Command { /// different state transition function. /// /// To make testing slightly more dynamic, you can disable the state root check by enabling - /// [`ExecuteBlockCmd::no_check`]. If you get signature verification errors, you should + /// `ExecuteBlockCmd::no_check`. If you get signature verification errors, you should /// manually tweak your local runtime's spec version to fix this. /// /// A subtle detail of execute block is that if you want to execute block 100 of a live chain @@ -335,19 +335,19 @@ pub enum Command { /// If [`State::Snap`] is being used, then this needs to be manually taken into consideration. /// /// This executes the same runtime api as normal block import, namely `Core_execute_block`. If - /// [`ExecuteBlockCmd::no_check`] is set, it uses a custom, try-runtime-only runtime + /// `ExecuteBlockCmd::no_check` is set, it uses a custom, try-runtime-only runtime /// api called `TryRuntime_execute_block_no_check`. ExecuteBlock(commands::execute_block::ExecuteBlockCmd), /// Executes *the offchain worker hooks* of a given block against some state. /// - /// Similar to [`Command:::ExecuteBlock`], this command needs two inputs: the state, and the + /// Similar to [`Command::ExecuteBlock`], this command needs two inputs: the state, and the /// header data. Likewise, `--header-at` and `--header-uri` can be filled, or omitted if /// [`State::Live`] is used. /// - /// Similar to [`Command:::ExecuteBlock`], this command does not overwrite the code, so in wasm + /// Similar to [`Command::ExecuteBlock`], this command does not overwrite the code, so in wasm /// execution, the live chain's code is used. This can be disabled if desired, see - /// [`OffchainWorkerCmd::overwrite_wasm_code`]. + /// `OffchainWorkerCmd::overwrite_wasm_code`. /// /// This executes the same runtime api as normal block import, namely /// `OffchainWorkerApi_offchain_worker`. From e2a89b2a6b476ea4dd5e0bd1c0e87790da4c17cb Mon Sep 17 00:00:00 2001 From: ferrell-code Date: Mon, 29 Nov 2021 13:38:07 -0500 Subject: [PATCH 240/695] Tips Benchmarking to be Runtime Agnostic (#10368) * use config traits instead of constants * bounties too * do bounties too * update docs --- frame/bounties/src/benchmarking.rs | 18 +++++++++--------- frame/bounties/src/lib.rs | 2 ++ frame/tips/src/benchmarking.rs | 17 +++++++---------- frame/tips/src/lib.rs | 5 ++++- 4 files changed, 22 insertions(+), 20 deletions(-) diff --git a/frame/bounties/src/benchmarking.rs b/frame/bounties/src/benchmarking.rs index 341d019c49d4..19f50fdf3931 100644 --- a/frame/bounties/src/benchmarking.rs +++ b/frame/bounties/src/benchmarking.rs @@ -33,7 +33,8 @@ const SEED: u32 = 0; // Create bounties that are approved for use in `on_initialize`. fn create_approved_bounties(n: u32) -> Result<(), &'static str> { for i in 0..n { - let (caller, _curator, _fee, value, reason) = setup_bounty::(i, MAX_BYTES); + let (caller, _curator, _fee, value, reason) = + setup_bounty::(i, T::MaximumReasonLength::get()); Bounties::::propose_bounty(RawOrigin::Signed(caller).into(), value, reason)?; let bounty_id = BountyCount::::get() - 1; Bounties::::approve_bounty(RawOrigin::Root.into(), bounty_id)?; @@ -50,7 +51,8 @@ fn setup_bounty( let caller = account("caller", u, SEED); let value: BalanceOf = T::BountyValueMinimum::get().saturating_mul(100u32.into()); let fee = value / 2u32.into(); - let deposit = T::BountyDepositBase::get() + T::DataDepositPerByte::get() * MAX_BYTES.into(); + let deposit = T::BountyDepositBase::get() + + T::DataDepositPerByte::get() * T::MaximumReasonLength::get().into(); let _ = T::Currency::make_free_balance_be(&caller, deposit); let curator = account("curator", u, SEED); let _ = T::Currency::make_free_balance_be(&curator, fee / 2u32.into()); @@ -60,7 +62,7 @@ fn setup_bounty( fn create_bounty( ) -> Result<(::Source, BountyIndex), &'static str> { - let (caller, curator, fee, value, reason) = setup_bounty::(0, MAX_BYTES); + let (caller, curator, fee, value, reason) = setup_bounty::(0, T::MaximumReasonLength::get()); let curator_lookup = T::Lookup::unlookup(curator.clone()); Bounties::::propose_bounty(RawOrigin::Signed(caller).into(), value, reason)?; let bounty_id = BountyCount::::get() - 1; @@ -81,24 +83,22 @@ fn assert_last_event(generic_event: ::Event) { frame_system::Pallet::::assert_last_event(generic_event.into()); } -const MAX_BYTES: u32 = 16384; - benchmarks! { propose_bounty { - let d in 0 .. MAX_BYTES; + let d in 0 .. T::MaximumReasonLength::get(); let (caller, curator, fee, value, description) = setup_bounty::(0, d); }: _(RawOrigin::Signed(caller), value, description) approve_bounty { - let (caller, curator, fee, value, reason) = setup_bounty::(0, MAX_BYTES); + let (caller, curator, fee, value, reason) = setup_bounty::(0, T::MaximumReasonLength::get()); Bounties::::propose_bounty(RawOrigin::Signed(caller).into(), value, reason)?; let bounty_id = BountyCount::::get() - 1; }: _(RawOrigin::Root, bounty_id) propose_curator { setup_pot_account::(); - let (caller, curator, fee, value, reason) = setup_bounty::(0, MAX_BYTES); + let (caller, curator, fee, value, reason) = setup_bounty::(0, T::MaximumReasonLength::get()); let curator_lookup = T::Lookup::unlookup(curator.clone()); Bounties::::propose_bounty(RawOrigin::Signed(caller).into(), value, reason)?; let bounty_id = BountyCount::::get() - 1; @@ -118,7 +118,7 @@ benchmarks! { accept_curator { setup_pot_account::(); - let (caller, curator, fee, value, reason) = setup_bounty::(0, MAX_BYTES); + let (caller, curator, fee, value, reason) = setup_bounty::(0, T::MaximumReasonLength::get()); let curator_lookup = T::Lookup::unlookup(curator.clone()); Bounties::::propose_bounty(RawOrigin::Signed(caller).into(), value, reason)?; let bounty_id = BountyCount::::get() - 1; diff --git a/frame/bounties/src/lib.rs b/frame/bounties/src/lib.rs index 5c96fdcc6b98..5021608b506b 100644 --- a/frame/bounties/src/lib.rs +++ b/frame/bounties/src/lib.rs @@ -195,6 +195,8 @@ pub mod pallet { type Event: From> + IsType<::Event>; /// Maximum acceptable reason length. + /// + /// Benchmarks depend on this value, be sure to update weights file when changing this value #[pallet::constant] type MaximumReasonLength: Get; diff --git a/frame/tips/src/benchmarking.rs b/frame/tips/src/benchmarking.rs index d8227332bb33..5b6f11de77dd 100644 --- a/frame/tips/src/benchmarking.rs +++ b/frame/tips/src/benchmarking.rs @@ -84,12 +84,9 @@ fn setup_pot_account() { let _ = T::Currency::make_free_balance_be(&pot_account, value); } -const MAX_BYTES: u32 = 16384; -const MAX_TIPPERS: u32 = 100; - benchmarks! { report_awesome { - let r in 0 .. MAX_BYTES; + let r in 0 .. T::MaximumReasonLength::get(); let (caller, reason, awesome_person) = setup_awesome::(r); // Whitelist caller account from further DB operations. let caller_key = frame_system::Account::::hashed_key_for(&caller); @@ -97,7 +94,7 @@ benchmarks! { }: _(RawOrigin::Signed(caller), reason, awesome_person) retract_tip { - let r = MAX_BYTES; + let r = T::MaximumReasonLength::get(); let (caller, reason, awesome_person) = setup_awesome::(r); TipsMod::::report_awesome( RawOrigin::Signed(caller.clone()).into(), @@ -112,8 +109,8 @@ benchmarks! { }: _(RawOrigin::Signed(caller), hash) tip_new { - let r in 0 .. MAX_BYTES; - let t in 1 .. MAX_TIPPERS; + let r in 0 .. T::MaximumReasonLength::get(); + let t in 1 .. T::Tippers::max_len() as u32; let (caller, reason, beneficiary, value) = setup_tip::(r, t)?; // Whitelist caller account from further DB operations. @@ -122,7 +119,7 @@ benchmarks! { }: _(RawOrigin::Signed(caller), reason, beneficiary, value) tip { - let t in 1 .. MAX_TIPPERS; + let t in 1 .. T::Tippers::max_len() as u32; let (member, reason, beneficiary, value) = setup_tip::(0, t)?; let value = T::Currency::minimum_balance().saturating_mul(100u32.into()); TipsMod::::tip_new( @@ -142,7 +139,7 @@ benchmarks! { }: _(RawOrigin::Signed(caller), hash, value) close_tip { - let t in 1 .. MAX_TIPPERS; + let t in 1 .. T::Tippers::max_len() as u32; // Make sure pot is funded setup_pot_account::(); @@ -171,7 +168,7 @@ benchmarks! { }: _(RawOrigin::Signed(caller), hash) slash_tip { - let t in 1 .. MAX_TIPPERS; + let t in 1 .. T::Tippers::max_len() as u32; // Make sure pot is funded setup_pot_account::(); diff --git a/frame/tips/src/lib.rs b/frame/tips/src/lib.rs index 5aad9af34660..0d2a56520a15 100644 --- a/frame/tips/src/lib.rs +++ b/frame/tips/src/lib.rs @@ -128,6 +128,8 @@ pub mod pallet { type Event: From> + IsType<::Event>; /// Maximum acceptable reason length. + /// + /// Benchmarks depend on this value, be sure to update weights file when changing this value #[pallet::constant] type MaximumReasonLength: Get; @@ -150,7 +152,8 @@ pub mod pallet { /// Origin from which tippers must come. /// /// `ContainsLengthBound::max_len` must be cost free (i.e. no storage read or heavy - /// operation). + /// operation). Benchmarks depend on the value of `ContainsLengthBound::max_len` be sure to + /// update weights file when altering this method. type Tippers: SortedMembers + ContainsLengthBound; /// Weight information for extrinsics in this pallet. From 270fac303a366c8c4c2e04771a7a346208db648c Mon Sep 17 00:00:00 2001 From: Joshy Orndorff Date: Tue, 30 Nov 2021 08:02:32 -0500 Subject: [PATCH 241/695] Add `vote` and `seconded` events to Democracy pallet. (#10352) * add the events * spec_version * Update bin/node/runtime/src/lib.rs Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Co-authored-by: Alan Sapede Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> --- frame/democracy/src/lib.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/frame/democracy/src/lib.rs b/frame/democracy/src/lib.rs index ec706ca8f48a..d80f8aa89ec3 100644 --- a/frame/democracy/src/lib.rs +++ b/frame/democracy/src/lib.rs @@ -539,6 +539,10 @@ pub mod pallet { }, /// A proposal_hash has been blacklisted permanently. Blacklisted { proposal_hash: T::Hash }, + /// An account has voted in a referendum + Voted { voter: T::AccountId, ref_index: ReferendumIndex, vote: AccountVote> }, + /// An account has secconded a proposal + Seconded { seconder: T::AccountId, prop_index: PropIndex }, } #[pallet::error] @@ -677,8 +681,9 @@ pub mod pallet { ensure!(seconds <= seconds_upper_bound, Error::::WrongUpperBound); let mut deposit = Self::deposit_of(proposal).ok_or(Error::::ProposalMissing)?; T::Currency::reserve(&who, deposit.1)?; - deposit.0.push(who); + deposit.0.push(who.clone()); >::insert(proposal, deposit); + Self::deposit_event(Event::::Seconded { seconder: who, prop_index: proposal }); Ok(()) } @@ -1378,6 +1383,7 @@ impl Pallet { votes.insert(i, (ref_index, vote)); }, } + Self::deposit_event(Event::::Voted { voter: who.clone(), ref_index, vote }); // Shouldn't be possible to fail, but we handle it gracefully. status.tally.add(vote).ok_or(ArithmeticError::Overflow)?; if let Some(approve) = vote.as_standard() { From 20b54920cee7512efc68b4c84dce1febc88c5518 Mon Sep 17 00:00:00 2001 From: zjb0807 Date: Tue, 30 Nov 2021 21:15:52 +0800 Subject: [PATCH 242/695] Add runtime-benchmarks for frame-benchmarking (#10324) * update frame/benchmarking/src/baseline.rs * add runtime-benchmarks feature * add runtime-benchmarks for frame-benchmarking * update frame-benchmarking/runtime-benchmarks * trigger GitHub actions --- bin/node-template/pallets/template/Cargo.toml | 2 +- bin/node-template/runtime/Cargo.toml | 2 +- bin/node/runtime/Cargo.toml | 2 +- frame/assets/Cargo.toml | 2 +- frame/babe/Cargo.toml | 2 +- frame/bags-list/Cargo.toml | 2 +- frame/balances/Cargo.toml | 2 +- frame/benchmarking/Cargo.toml | 1 + frame/benchmarking/src/baseline.rs | 2 ++ frame/bounties/Cargo.toml | 2 +- frame/collective/Cargo.toml | 2 +- frame/contracts/Cargo.toml | 2 +- frame/democracy/Cargo.toml | 2 +- frame/election-provider-multi-phase/Cargo.toml | 2 +- frame/elections-phragmen/Cargo.toml | 2 +- frame/examples/basic/Cargo.toml | 2 +- frame/gilt/Cargo.toml | 2 +- frame/grandpa/Cargo.toml | 2 +- frame/identity/Cargo.toml | 2 +- frame/im-online/Cargo.toml | 2 +- frame/indices/Cargo.toml | 2 +- frame/lottery/Cargo.toml | 2 +- frame/membership/Cargo.toml | 2 +- frame/merkle-mountain-range/Cargo.toml | 2 +- frame/multisig/Cargo.toml | 2 +- frame/proxy/Cargo.toml | 2 +- frame/scheduler/Cargo.toml | 2 +- frame/staking/Cargo.toml | 2 +- frame/timestamp/Cargo.toml | 2 +- frame/tips/Cargo.toml | 2 +- frame/transaction-storage/Cargo.toml | 2 +- frame/treasury/Cargo.toml | 2 +- frame/uniques/Cargo.toml | 2 +- frame/utility/Cargo.toml | 2 +- frame/vesting/Cargo.toml | 2 +- 35 files changed, 36 insertions(+), 33 deletions(-) diff --git a/bin/node-template/pallets/template/Cargo.toml b/bin/node-template/pallets/template/Cargo.toml index 7ea5628b97c1..1a239bef3262 100644 --- a/bin/node-template/pallets/template/Cargo.toml +++ b/bin/node-template/pallets/template/Cargo.toml @@ -36,5 +36,5 @@ std = [ 'frame-benchmarking/std', ] -runtime-benchmarks = ["frame-benchmarking"] +runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks"] try-runtime = ["frame-support/try-runtime"] diff --git a/bin/node-template/runtime/Cargo.toml b/bin/node-template/runtime/Cargo.toml index bff47f5a7ea3..c821bdac169e 100644 --- a/bin/node-template/runtime/Cargo.toml +++ b/bin/node-template/runtime/Cargo.toml @@ -83,7 +83,7 @@ std = [ "sp-version/std", ] runtime-benchmarks = [ - "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system-benchmarking", "frame-system/runtime-benchmarks", diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index f9ce4b0fca90..4771202b90a0 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -176,7 +176,7 @@ std = [ "sp-io/std" ] runtime-benchmarks = [ - "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-election-provider-multi-phase/runtime-benchmarks", diff --git a/frame/assets/Cargo.toml b/frame/assets/Cargo.toml index 08cadb527750..233c88279d35 100644 --- a/frame/assets/Cargo.toml +++ b/frame/assets/Cargo.toml @@ -42,7 +42,7 @@ std = [ "frame-benchmarking/std", ] runtime-benchmarks = [ - "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", "sp-runtime/runtime-benchmarks", "frame-system/runtime-benchmarks", ] diff --git a/frame/babe/Cargo.toml b/frame/babe/Cargo.toml index 9ae942486d62..a2224df86798 100644 --- a/frame/babe/Cargo.toml +++ b/frame/babe/Cargo.toml @@ -60,5 +60,5 @@ std = [ "sp-std/std", "log/std", ] -runtime-benchmarks = ["frame-benchmarking"] +runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks"] try-runtime = ["frame-support/try-runtime"] diff --git a/frame/bags-list/Cargo.toml b/frame/bags-list/Cargo.toml index 6d4cf2363c4f..b7eebdd0df10 100644 --- a/frame/bags-list/Cargo.toml +++ b/frame/bags-list/Cargo.toml @@ -56,7 +56,7 @@ std = [ "log/std", ] runtime-benchmarks = [ - "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", "sp-core", "sp-io", "pallet-balances", diff --git a/frame/balances/Cargo.toml b/frame/balances/Cargo.toml index 4ea2e9cbe8a3..5565915f6ded 100644 --- a/frame/balances/Cargo.toml +++ b/frame/balances/Cargo.toml @@ -39,5 +39,5 @@ std = [ "frame-system/std", "log/std", ] -runtime-benchmarks = ["frame-benchmarking"] +runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks"] try-runtime = ["frame-support/try-runtime"] diff --git a/frame/benchmarking/Cargo.toml b/frame/benchmarking/Cargo.toml index a6bfcf2a552f..2bf4a53b0f42 100644 --- a/frame/benchmarking/Cargo.toml +++ b/frame/benchmarking/Cargo.toml @@ -44,3 +44,4 @@ std = [ "linregress", "log/std", ] +runtime-benchmarks = [] diff --git a/frame/benchmarking/src/baseline.rs b/frame/benchmarking/src/baseline.rs index a2ffca60c5cf..2b924a692129 100644 --- a/frame/benchmarking/src/baseline.rs +++ b/frame/benchmarking/src/baseline.rs @@ -18,6 +18,8 @@ //! A set of benchmarks which can establish a global baseline for all other //! benchmarking. +#![cfg(feature = "runtime-benchmarks")] + use crate::benchmarks; use codec::Encode; use frame_system::Pallet as System; diff --git a/frame/bounties/Cargo.toml b/frame/bounties/Cargo.toml index cce6ed69a25b..6c9cef417e99 100644 --- a/frame/bounties/Cargo.toml +++ b/frame/bounties/Cargo.toml @@ -45,7 +45,7 @@ std = [ "log/std", ] runtime-benchmarks = [ - "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", ] diff --git a/frame/collective/Cargo.toml b/frame/collective/Cargo.toml index 6d4567a7851e..d4dc8f9a2d8d 100644 --- a/frame/collective/Cargo.toml +++ b/frame/collective/Cargo.toml @@ -41,7 +41,7 @@ std = [ "frame-system/std", ] runtime-benchmarks = [ - "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", "sp-runtime/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", diff --git a/frame/contracts/Cargo.toml b/frame/contracts/Cargo.toml index 6639d939e179..cc21f19b6352 100644 --- a/frame/contracts/Cargo.toml +++ b/frame/contracts/Cargo.toml @@ -79,7 +79,7 @@ std = [ "libsecp256k1/std", ] runtime-benchmarks = [ - "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", "libsecp256k1", "rand", "rand_pcg", diff --git a/frame/democracy/Cargo.toml b/frame/democracy/Cargo.toml index 1973677531e9..43b35b9f7a1f 100644 --- a/frame/democracy/Cargo.toml +++ b/frame/democracy/Cargo.toml @@ -44,7 +44,7 @@ std = [ "frame-system/std", ] runtime-benchmarks = [ - "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", "frame-system/runtime-benchmarks", "frame-support/runtime-benchmarks", "sp-runtime/runtime-benchmarks", diff --git a/frame/election-provider-multi-phase/Cargo.toml b/frame/election-provider-multi-phase/Cargo.toml index b37054a7bbdd..c041d6c684c7 100644 --- a/frame/election-provider-multi-phase/Cargo.toml +++ b/frame/election-provider-multi-phase/Cargo.toml @@ -72,7 +72,7 @@ std = [ "log/std", ] runtime-benchmarks = [ - "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", "frame-election-provider-support/runtime-benchmarks", "rand", "strum", diff --git a/frame/elections-phragmen/Cargo.toml b/frame/elections-phragmen/Cargo.toml index 6c87be7b6d58..921a7057bcda 100644 --- a/frame/elections-phragmen/Cargo.toml +++ b/frame/elections-phragmen/Cargo.toml @@ -47,7 +47,7 @@ std = [ "log/std", ] runtime-benchmarks = [ - "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", ] diff --git a/frame/examples/basic/Cargo.toml b/frame/examples/basic/Cargo.toml index a4e8ffe3261c..8ac375cb3603 100644 --- a/frame/examples/basic/Cargo.toml +++ b/frame/examples/basic/Cargo.toml @@ -42,5 +42,5 @@ std = [ "sp-runtime/std", "sp-std/std" ] -runtime-benchmarks = ["frame-benchmarking"] +runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks"] try-runtime = ["frame-support/try-runtime"] diff --git a/frame/gilt/Cargo.toml b/frame/gilt/Cargo.toml index 6b2eae1156a8..e9ee8ba14aba 100644 --- a/frame/gilt/Cargo.toml +++ b/frame/gilt/Cargo.toml @@ -40,7 +40,7 @@ std = [ "frame-system/std", ] runtime-benchmarks = [ - "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", ] diff --git a/frame/grandpa/Cargo.toml b/frame/grandpa/Cargo.toml index af125d64ea21..ba2d98fc354e 100644 --- a/frame/grandpa/Cargo.toml +++ b/frame/grandpa/Cargo.toml @@ -60,5 +60,5 @@ std = [ "pallet-session/std", "log/std", ] -runtime-benchmarks = ["frame-benchmarking"] +runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks"] try-runtime = ["frame-support/try-runtime"] diff --git a/frame/identity/Cargo.toml b/frame/identity/Cargo.toml index 9a370674e587..b791256d9452 100644 --- a/frame/identity/Cargo.toml +++ b/frame/identity/Cargo.toml @@ -40,7 +40,7 @@ std = [ "frame-system/std", ] runtime-benchmarks = [ - "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", ] diff --git a/frame/im-online/Cargo.toml b/frame/im-online/Cargo.toml index f4cf5a9077c9..2fa0b5ebc12a 100644 --- a/frame/im-online/Cargo.toml +++ b/frame/im-online/Cargo.toml @@ -47,5 +47,5 @@ std = [ "frame-system/std", "log/std", ] -runtime-benchmarks = ["frame-benchmarking"] +runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks"] try-runtime = ["frame-support/try-runtime"] diff --git a/frame/indices/Cargo.toml b/frame/indices/Cargo.toml index f1913d4138be..7f27ac23c645 100644 --- a/frame/indices/Cargo.toml +++ b/frame/indices/Cargo.toml @@ -42,7 +42,7 @@ std = [ "frame-system/std", ] runtime-benchmarks = [ - "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", ] diff --git a/frame/lottery/Cargo.toml b/frame/lottery/Cargo.toml index d4ee5b8008f1..e65bb01660b5 100644 --- a/frame/lottery/Cargo.toml +++ b/frame/lottery/Cargo.toml @@ -41,7 +41,7 @@ std = [ "frame-system/std", ] runtime-benchmarks = [ - "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", "frame-system/runtime-benchmarks", "frame-support/runtime-benchmarks", ] diff --git a/frame/membership/Cargo.toml b/frame/membership/Cargo.toml index a3747ca0576f..9eafaedee7db 100644 --- a/frame/membership/Cargo.toml +++ b/frame/membership/Cargo.toml @@ -41,7 +41,7 @@ std = [ "frame-benchmarking/std", ] runtime-benchmarks = [ - "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", "sp-runtime/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", diff --git a/frame/merkle-mountain-range/Cargo.toml b/frame/merkle-mountain-range/Cargo.toml index 2ff8b16fa4bd..ee9080b19d61 100644 --- a/frame/merkle-mountain-range/Cargo.toml +++ b/frame/merkle-mountain-range/Cargo.toml @@ -46,5 +46,5 @@ std = [ "frame-system/std", "pallet-mmr-primitives/std", ] -runtime-benchmarks = ["frame-benchmarking"] +runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks"] try-runtime = ["frame-support/try-runtime"] diff --git a/frame/multisig/Cargo.toml b/frame/multisig/Cargo.toml index 2b0d8f5cee79..f409e0c6c8d0 100644 --- a/frame/multisig/Cargo.toml +++ b/frame/multisig/Cargo.toml @@ -39,7 +39,7 @@ std = [ "sp-std/std" ] runtime-benchmarks = [ - "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", ] diff --git a/frame/proxy/Cargo.toml b/frame/proxy/Cargo.toml index 030209b83cc6..be288ecc0d75 100644 --- a/frame/proxy/Cargo.toml +++ b/frame/proxy/Cargo.toml @@ -40,7 +40,7 @@ std = [ "sp-io/std", ] runtime-benchmarks = [ - "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", ] diff --git a/frame/scheduler/Cargo.toml b/frame/scheduler/Cargo.toml index fab2bc2c635c..01cf95fa7fc7 100644 --- a/frame/scheduler/Cargo.toml +++ b/frame/scheduler/Cargo.toml @@ -39,7 +39,7 @@ std = [ "log/std", ] runtime-benchmarks = [ - "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", ] diff --git a/frame/staking/Cargo.toml b/frame/staking/Cargo.toml index d9461ab454f3..81f5b181850c 100644 --- a/frame/staking/Cargo.toml +++ b/frame/staking/Cargo.toml @@ -68,7 +68,7 @@ std = [ "frame-election-provider-support/std", ] runtime-benchmarks = [ - "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", "frame-election-provider-support/runtime-benchmarks", "rand_chacha", ] diff --git a/frame/timestamp/Cargo.toml b/frame/timestamp/Cargo.toml index 2f07b2a0975a..a942b58e0950 100644 --- a/frame/timestamp/Cargo.toml +++ b/frame/timestamp/Cargo.toml @@ -45,5 +45,5 @@ std = [ "sp-timestamp/std", "log/std", ] -runtime-benchmarks = ["frame-benchmarking", "sp-io"] +runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks", "sp-io"] try-runtime = ["frame-support/try-runtime"] diff --git a/frame/tips/Cargo.toml b/frame/tips/Cargo.toml index 805f1663d1ae..49b19756e43c 100644 --- a/frame/tips/Cargo.toml +++ b/frame/tips/Cargo.toml @@ -50,7 +50,7 @@ std = [ "pallet-treasury/std", ] runtime-benchmarks = [ - "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", ] diff --git a/frame/transaction-storage/Cargo.toml b/frame/transaction-storage/Cargo.toml index a8c6e60af2f8..4b4ee7de8509 100644 --- a/frame/transaction-storage/Cargo.toml +++ b/frame/transaction-storage/Cargo.toml @@ -33,7 +33,7 @@ sp-core = { version = "4.0.0-dev", path = "../../primitives/core", default-featu [features] default = ["std"] -runtime-benchmarks = ["frame-benchmarking", "hex-literal"] +runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks", "hex-literal"] std = [ "serde", "codec/std", diff --git a/frame/treasury/Cargo.toml b/frame/treasury/Cargo.toml index d375e22df949..d44699825a6f 100644 --- a/frame/treasury/Cargo.toml +++ b/frame/treasury/Cargo.toml @@ -47,7 +47,7 @@ std = [ "pallet-balances/std", ] runtime-benchmarks = [ - "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", ] diff --git a/frame/uniques/Cargo.toml b/frame/uniques/Cargo.toml index 4b6d0485567c..9d7e8f7184d1 100644 --- a/frame/uniques/Cargo.toml +++ b/frame/uniques/Cargo.toml @@ -39,7 +39,7 @@ std = [ "frame-benchmarking/std", ] runtime-benchmarks = [ - "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", "sp-runtime/runtime-benchmarks", "frame-system/runtime-benchmarks", ] diff --git a/frame/utility/Cargo.toml b/frame/utility/Cargo.toml index c55b20df2785..8407bf53e73d 100644 --- a/frame/utility/Cargo.toml +++ b/frame/utility/Cargo.toml @@ -40,7 +40,7 @@ std = [ "sp-std/std", ] runtime-benchmarks = [ - "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", ] diff --git a/frame/vesting/Cargo.toml b/frame/vesting/Cargo.toml index 035124f7d0de..efec3be330dc 100644 --- a/frame/vesting/Cargo.toml +++ b/frame/vesting/Cargo.toml @@ -39,5 +39,5 @@ std = [ "frame-support/std", "frame-system/std", ] -runtime-benchmarks = ["frame-benchmarking"] +runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks"] try-runtime = ["frame-support/try-runtime"] From 4bef50f5ea7726d77142ec21437fb14e3e737a3b Mon Sep 17 00:00:00 2001 From: Enoch Chejieh Date: Tue, 30 Nov 2021 21:03:06 +0100 Subject: [PATCH 243/695] Add pallet names to Events (#10296) * chore: add pallet names to events * chore: add pallet names to events * chore: add pallet names to events * chore: add pallet names to events * chore: add pallet names to events * chore: add pallet names to events * chore: add pallet names to events * chore: add pallet names to events * chore: add pallet names to events * chore: add pallet names to events * chore: add pallet names to events * chore: add pallet names to events * chore: add pallet names to events * chore: add pallet names to events * chore: formatted pallet name changes in events * chore: formatted pallet name changes in events * chore: formatted pallet name changes in events * chore: formatted pallet name changes in events * chore: formatted pallet name changes in events * chore: formatted pallet name changes in events * chore: formatted pallet name changes in events * chore: formatted pallet name changes in events * chore: formatted pallet name changes in events * fix: add fix to tests for event variants * chore: modified comments for event variants * chore: modified comments for event variants * chore: modified comments for event variants * chore: modified comments for event variants * chore: modified system pallet event variants * chore: modified system pallet event variants * chore: modified system pallet event variants * chore: modified system pallet event variants * chore: modified system pallet event variants * chore: modified system pallet event variants * chore: modified system pallet event variants * chore: modified system pallet event variants * chore: modified system pallet event variants * chore: updated transaction-storage pallet event variants * chore: updated transaction-storage pallet event variants * chore: formatted contracts pallet * chore: update treasury event variants --- bin/node/executor/tests/basic.rs | 51 ++++----- frame/balances/src/tests.rs | 8 +- frame/balances/src/tests_local.rs | 4 +- frame/contracts/src/exec.rs | 10 +- frame/contracts/src/tests.rs | 10 +- frame/offences/benchmarking/src/lib.rs | 2 +- frame/scheduler/src/lib.rs | 42 ++++---- frame/society/src/lib.rs | 101 +++++++++--------- frame/system/src/lib.rs | 30 +++--- frame/system/src/tests.rs | 63 ++++++----- frame/transaction-payment/src/lib.rs | 4 +- frame/transaction-storage/src/benchmarking.rs | 4 +- frame/transaction-storage/src/lib.rs | 8 +- frame/treasury/src/lib.rs | 48 +++++---- frame/utility/src/lib.rs | 8 +- 15 files changed, 209 insertions(+), 184 deletions(-) diff --git a/bin/node/executor/tests/basic.rs b/bin/node/executor/tests/basic.rs index 7dc6c22aa354..9c460a0238e3 100644 --- a/bin/node/executor/tests/basic.rs +++ b/bin/node/executor/tests/basic.rs @@ -378,11 +378,13 @@ fn full_native_block_import_works() { let events = vec![ EventRecord { phase: Phase::ApplyExtrinsic(0), - event: Event::System(frame_system::Event::ExtrinsicSuccess(DispatchInfo { - weight: timestamp_weight, - class: DispatchClass::Mandatory, - ..Default::default() - })), + event: Event::System(frame_system::Event::ExtrinsicSuccess { + dispatch_info: DispatchInfo { + weight: timestamp_weight, + class: DispatchClass::Mandatory, + ..Default::default() + }, + }), topics: vec![], }, EventRecord { @@ -412,15 +414,14 @@ fn full_native_block_import_works() { }, EventRecord { phase: Phase::ApplyExtrinsic(1), - event: Event::Treasury(pallet_treasury::Event::Deposit(fees * 8 / 10)), + event: Event::Treasury(pallet_treasury::Event::Deposit { value: fees * 8 / 10 }), topics: vec![], }, EventRecord { phase: Phase::ApplyExtrinsic(1), - event: Event::System(frame_system::Event::ExtrinsicSuccess(DispatchInfo { - weight: transfer_weight, - ..Default::default() - })), + event: Event::System(frame_system::Event::ExtrinsicSuccess { + dispatch_info: DispatchInfo { weight: transfer_weight, ..Default::default() }, + }), topics: vec![], }, ]; @@ -448,11 +449,13 @@ fn full_native_block_import_works() { let events = vec![ EventRecord { phase: Phase::ApplyExtrinsic(0), - event: Event::System(frame_system::Event::ExtrinsicSuccess(DispatchInfo { - weight: timestamp_weight, - class: DispatchClass::Mandatory, - ..Default::default() - })), + event: Event::System(frame_system::Event::ExtrinsicSuccess { + dispatch_info: DispatchInfo { + weight: timestamp_weight, + class: DispatchClass::Mandatory, + ..Default::default() + }, + }), topics: vec![], }, EventRecord { @@ -482,15 +485,14 @@ fn full_native_block_import_works() { }, EventRecord { phase: Phase::ApplyExtrinsic(1), - event: Event::Treasury(pallet_treasury::Event::Deposit(fees * 8 / 10)), + event: Event::Treasury(pallet_treasury::Event::Deposit { value: fees * 8 / 10 }), topics: vec![], }, EventRecord { phase: Phase::ApplyExtrinsic(1), - event: Event::System(frame_system::Event::ExtrinsicSuccess(DispatchInfo { - weight: transfer_weight, - ..Default::default() - })), + event: Event::System(frame_system::Event::ExtrinsicSuccess { + dispatch_info: DispatchInfo { weight: transfer_weight, ..Default::default() }, + }), topics: vec![], }, EventRecord { @@ -520,15 +522,14 @@ fn full_native_block_import_works() { }, EventRecord { phase: Phase::ApplyExtrinsic(2), - event: Event::Treasury(pallet_treasury::Event::Deposit(fees * 8 / 10)), + event: Event::Treasury(pallet_treasury::Event::Deposit { value: fees * 8 / 10 }), topics: vec![], }, EventRecord { phase: Phase::ApplyExtrinsic(2), - event: Event::System(frame_system::Event::ExtrinsicSuccess(DispatchInfo { - weight: transfer_weight, - ..Default::default() - })), + event: Event::System(frame_system::Event::ExtrinsicSuccess { + dispatch_info: DispatchInfo { weight: transfer_weight, ..Default::default() }, + }), topics: vec![], }, ]; diff --git a/frame/balances/src/tests.rs b/frame/balances/src/tests.rs index 1f7f4dd03716..e05ed5a3d689 100644 --- a/frame/balances/src/tests.rs +++ b/frame/balances/src/tests.rs @@ -750,7 +750,7 @@ macro_rules! decl_tests { assert_eq!( events(), [ - Event::System(system::Event::NewAccount(1)), + Event::System(system::Event::NewAccount { account: 1 }), Event::Balances(crate::Event::Endowed { account: 1, free_balance: 100 }), Event::Balances(crate::Event::BalanceSet { who: 1, free: 100, reserved: 0 }), ] @@ -762,7 +762,7 @@ macro_rules! decl_tests { assert_eq!( events(), [ - Event::System(system::Event::KilledAccount(1)), + Event::System(system::Event::KilledAccount { account: 1 }), Event::Balances(crate::Event::DustLost { account: 1, amount: 99 }), Event::Balances(crate::Event::Slashed { who: 1, amount: 1 }), ] @@ -781,7 +781,7 @@ macro_rules! decl_tests { assert_eq!( events(), [ - Event::System(system::Event::NewAccount(1)), + Event::System(system::Event::NewAccount { account: 1 }), Event::Balances(crate::Event::Endowed { account: 1, free_balance: 100 }), Event::Balances(crate::Event::BalanceSet { who: 1, free: 100, reserved: 0 }), ] @@ -793,7 +793,7 @@ macro_rules! decl_tests { assert_eq!( events(), [ - Event::System(system::Event::KilledAccount(1)), + Event::System(system::Event::KilledAccount { account: 1 }), Event::Balances(crate::Event::Slashed { who: 1, amount: 100 }), ] ); diff --git a/frame/balances/src/tests_local.rs b/frame/balances/src/tests_local.rs index c9de662b9e8f..a861df4746a1 100644 --- a/frame/balances/src/tests_local.rs +++ b/frame/balances/src/tests_local.rs @@ -163,7 +163,7 @@ fn emit_events_with_no_existential_deposit_suicide_with_dust() { assert_eq!( events(), [ - Event::System(system::Event::NewAccount(1)), + Event::System(system::Event::NewAccount { account: 1 }), Event::Balances(crate::Event::Endowed { account: 1, free_balance: 100 }), Event::Balances(crate::Event::BalanceSet { who: 1, free: 100, reserved: 0 }), ] @@ -181,7 +181,7 @@ fn emit_events_with_no_existential_deposit_suicide_with_dust() { assert_eq!( events(), [ - Event::System(system::Event::KilledAccount(1)), + Event::System(system::Event::KilledAccount { account: 1 }), Event::Balances(crate::Event::DustLost { account: 1, amount: 1 }), Event::Balances(crate::Event::Slashed { who: 1, amount: 1 }) ] diff --git a/frame/contracts/src/exec.rs b/frame/contracts/src/exec.rs index 90a640418bcc..bc88e162c5c0 100644 --- a/frame/contracts/src/exec.rs +++ b/frame/contracts/src/exec.rs @@ -2089,7 +2089,10 @@ mod tests { System::events(), vec![EventRecord { phase: Phase::Initialization, - event: MetaEvent::System(frame_system::Event::Remarked(BOB, remark_hash)), + event: MetaEvent::System(frame_system::Event::Remarked { + sender: BOB, + hash: remark_hash + }), topics: vec![], },] ); @@ -2147,7 +2150,10 @@ mod tests { vec![ EventRecord { phase: Phase::Initialization, - event: MetaEvent::System(frame_system::Event::Remarked(BOB, remark_hash)), + event: MetaEvent::System(frame_system::Event::Remarked { + sender: BOB, + hash: remark_hash + }), topics: vec![], }, EventRecord { diff --git a/frame/contracts/src/tests.rs b/frame/contracts/src/tests.rs index 2214ce8f40b1..6a252527d1ea 100644 --- a/frame/contracts/src/tests.rs +++ b/frame/contracts/src/tests.rs @@ -455,7 +455,9 @@ fn instantiate_and_call_and_deposit_event() { }, EventRecord { phase: Phase::Initialization, - event: Event::System(frame_system::Event::NewAccount(ALICE.clone())), + event: Event::System(frame_system::Event::NewAccount { + account: ALICE.clone() + }), topics: vec![], }, EventRecord { @@ -468,7 +470,7 @@ fn instantiate_and_call_and_deposit_event() { }, EventRecord { phase: Phase::Initialization, - event: Event::System(frame_system::Event::NewAccount(addr.clone())), + event: Event::System(frame_system::Event::NewAccount { account: addr.clone() }), topics: vec![], }, EventRecord { @@ -767,7 +769,9 @@ fn self_destruct_works() { vec![ EventRecord { phase: Phase::Initialization, - event: Event::System(frame_system::Event::KilledAccount(addr.clone())), + event: Event::System(frame_system::Event::KilledAccount { + account: addr.clone() + }), topics: vec![], }, EventRecord { diff --git a/frame/offences/benchmarking/src/lib.rs b/frame/offences/benchmarking/src/lib.rs index 33ebe23d8d1f..4d042cfd9997 100644 --- a/frame/offences/benchmarking/src/lib.rs +++ b/frame/offences/benchmarking/src/lib.rs @@ -342,7 +342,7 @@ benchmarks! { let mut reward_events = reporters.clone().into_iter() .flat_map(|reporter| vec![ balance_deposit(reporter.clone(), reward.into()).into(), - frame_system::Event::::NewAccount(reporter.clone()).into(), + frame_system::Event::::NewAccount { account: reporter.clone() }.into(), ::Event::from( pallet_balances::Event::::Endowed{account: reporter.clone(), free_balance: reward.into()} ).into(), diff --git a/frame/scheduler/src/lib.rs b/frame/scheduler/src/lib.rs index d25fc3b376e8..b3e64fe57f64 100644 --- a/frame/scheduler/src/lib.rs +++ b/frame/scheduler/src/lib.rs @@ -203,12 +203,16 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { - /// Scheduled some task. \[when, index\] - Scheduled(T::BlockNumber, u32), - /// Canceled some task. \[when, index\] - Canceled(T::BlockNumber, u32), - /// Dispatched some task. \[task, id, result\] - Dispatched(TaskAddress, Option>, DispatchResult), + /// Scheduled some task. + Scheduled { when: T::BlockNumber, index: u32 }, + /// Canceled some task. + Canceled { when: T::BlockNumber, index: u32 }, + /// Dispatched some task. + Dispatched { + task: TaskAddress, + id: Option>, + result: DispatchResult, + }, } #[pallet::error] @@ -319,11 +323,11 @@ pub mod pallet { Lookup::::remove(id); } } - Self::deposit_event(Event::Dispatched( - (now, index), - maybe_id, - r.map(|_| ()).map_err(|e| e.error), - )); + Self::deposit_event(Event::Dispatched { + task: (now, index), + id: maybe_id, + result: r.map(|_| ()).map_err(|e| e.error), + }); total_weight = cumulative_weight; None } else { @@ -563,7 +567,7 @@ impl Pallet { expected from the runtime configuration. An update might be needed.", ); } - Self::deposit_event(Event::Scheduled(when, index)); + Self::deposit_event(Event::Scheduled { when, index }); Ok((when, index)) } @@ -592,7 +596,7 @@ impl Pallet { if let Some(id) = s.maybe_id { Lookup::::remove(id); } - Self::deposit_event(Event::Canceled(when, index)); + Self::deposit_event(Event::Canceled { when, index }); Ok(()) } else { Err(Error::::NotFound)? @@ -617,8 +621,8 @@ impl Pallet { })?; let new_index = Agenda::::decode_len(new_time).unwrap_or(1) as u32 - 1; - Self::deposit_event(Event::Canceled(when, index)); - Self::deposit_event(Event::Scheduled(new_time, new_index)); + Self::deposit_event(Event::Canceled { when, index }); + Self::deposit_event(Event::Scheduled { when: new_time, index: new_index }); Ok((new_time, new_index)) } @@ -663,7 +667,7 @@ impl Pallet { } let address = (when, index); Lookup::::insert(&id, &address); - Self::deposit_event(Event::Scheduled(when, index)); + Self::deposit_event(Event::Scheduled { when, index }); Ok(address) } @@ -686,7 +690,7 @@ impl Pallet { } Ok(()) })?; - Self::deposit_event(Event::Canceled(when, index)); + Self::deposit_event(Event::Canceled { when, index }); Ok(()) } else { Err(Error::::NotFound)? @@ -718,8 +722,8 @@ impl Pallet { })?; let new_index = Agenda::::decode_len(new_time).unwrap_or(1) as u32 - 1; - Self::deposit_event(Event::Canceled(when, index)); - Self::deposit_event(Event::Scheduled(new_time, new_index)); + Self::deposit_event(Event::Canceled { when, index }); + Self::deposit_event(Event::Scheduled { when: new_time, index: new_index }); *lookup = Some((new_time, new_index)); diff --git a/frame/society/src/lib.rs b/frame/society/src/lib.rs index 83b1c4203722..0b9512903267 100644 --- a/frame/society/src/lib.rs +++ b/frame/society/src/lib.rs @@ -475,42 +475,41 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event, I: 'static = ()> { - /// The society is founded by the given identity. \[founder\] - Founded(T::AccountId), + /// The society is founded by the given identity. + Founded { founder: T::AccountId }, /// A membership bid just happened. The given account is the candidate's ID and their offer - /// is the second. \[candidate_id, offer\] - Bid(T::AccountId, BalanceOf), + /// is the second. + Bid { candidate_id: T::AccountId, offer: BalanceOf }, /// A membership bid just happened by vouching. The given account is the candidate's ID and - /// their offer is the second. The vouching party is the third. \[candidate_id, offer, - /// vouching\] - Vouch(T::AccountId, BalanceOf, T::AccountId), - /// A \[candidate\] was dropped (due to an excess of bids in the system). - AutoUnbid(T::AccountId), - /// A \[candidate\] was dropped (by their request). - Unbid(T::AccountId), - /// A \[candidate\] was dropped (by request of who vouched for them). - Unvouch(T::AccountId), + /// their offer is the second. The vouching party is the third. + Vouch { candidate_id: T::AccountId, offer: BalanceOf, vouching: T::AccountId }, + /// A candidate was dropped (due to an excess of bids in the system). + AutoUnbid { candidate: T::AccountId }, + /// A candidate was dropped (by their request). + Unbid { candidate: T::AccountId }, + /// A candidate was dropped (by request of who vouched for them). + Unvouch { candidate: T::AccountId }, /// A group of candidates have been inducted. The batch's primary is the first value, the - /// batch in full is the second. \[primary, candidates\] - Inducted(T::AccountId, Vec), - /// A suspended member has been judged. \[who, judged\] - SuspendedMemberJudgement(T::AccountId, bool), - /// A \[candidate\] has been suspended - CandidateSuspended(T::AccountId), - /// A \[member\] has been suspended - MemberSuspended(T::AccountId), - /// A \[member\] has been challenged - Challenged(T::AccountId), - /// A vote has been placed \[candidate, voter, vote\] - Vote(T::AccountId, T::AccountId, bool), - /// A vote has been placed for a defending member \[voter, vote\] - DefenderVote(T::AccountId, bool), + /// batch in full is the second. + Inducted { primary: T::AccountId, candidates: Vec }, + /// A suspended member has been judged. + SuspendedMemberJudgement { who: T::AccountId, judged: bool }, + /// A candidate has been suspended + CandidateSuspended { candidate: T::AccountId }, + /// A member has been suspended + MemberSuspended { member: T::AccountId }, + /// A member has been challenged + Challenged { member: T::AccountId }, + /// A vote has been placed + Vote { candidate: T::AccountId, voter: T::AccountId, vote: bool }, + /// A vote has been placed for a defending member + DefenderVote { voter: T::AccountId, vote: bool }, /// A new \[max\] member count has been set - NewMaxMembers(u32), - /// Society is unfounded. \[founder\] - Unfounded(T::AccountId), - /// Some funds were deposited into the society account. \[value\] - Deposit(BalanceOf), + NewMaxMembers { max: u32 }, + /// Society is unfounded. + Unfounded { founder: T::AccountId }, + /// Some funds were deposited into the society account. + Deposit { value: BalanceOf }, } /// Old name generated by `decl_event`. @@ -729,7 +728,7 @@ pub mod pallet { T::Currency::reserve(&who, deposit)?; Self::put_bid(bids, &who, value.clone(), BidKind::Deposit(deposit)); - Self::deposit_event(Event::::Bid(who, value)); + Self::deposit_event(Event::::Bid { candidate_id: who, offer: value }); Ok(()) } @@ -771,7 +770,7 @@ pub mod pallet { >::remove(&voucher); }, } - Self::deposit_event(Event::::Unbid(who)); + Self::deposit_event(Event::::Unbid { candidate: who }); Ok(()) } else { Err(Error::::BadPosition)? @@ -849,7 +848,11 @@ pub mod pallet { >::insert(&voucher, VouchingStatus::Vouching); Self::put_bid(bids, &who, value.clone(), BidKind::Vouch(voucher.clone(), tip)); - Self::deposit_event(Event::::Vouch(who, value, voucher)); + Self::deposit_event(Event::::Vouch { + candidate_id: who, + offer: value, + vouching: voucher, + }); Ok(()) } @@ -884,7 +887,7 @@ pub mod pallet { b[pos].kind.check_voucher(&voucher)?; >::remove(&voucher); let who = b.remove(pos).who; - Self::deposit_event(Event::::Unvouch(who)); + Self::deposit_event(Event::::Unvouch { candidate: who }); Ok(()) } else { Err(Error::::BadPosition)? @@ -927,7 +930,7 @@ pub mod pallet { let vote = if approve { Vote::Approve } else { Vote::Reject }; >::insert(&candidate, &voter, vote); - Self::deposit_event(Event::::Vote(candidate, voter, approve)); + Self::deposit_event(Event::::Vote { candidate, voter, vote: approve }); Ok(()) } @@ -956,7 +959,7 @@ pub mod pallet { let vote = if approve { Vote::Approve } else { Vote::Reject }; >::insert(&voter, vote); - Self::deposit_event(Event::::DefenderVote(voter, approve)); + Self::deposit_event(Event::::DefenderVote { voter, vote: approve }); Ok(()) } @@ -1039,7 +1042,7 @@ pub mod pallet { >::put(&founder); >::put(&founder); Rules::::put(T::Hashing::hash(&rules)); - Self::deposit_event(Event::::Founded(founder)); + Self::deposit_event(Event::::Founded { founder }); Ok(()) } @@ -1068,7 +1071,7 @@ pub mod pallet { Rules::::kill(); Candidates::::kill(); SuspendedCandidates::::remove_all(None); - Self::deposit_event(Event::::Unfounded(founder)); + Self::deposit_event(Event::::Unfounded { founder }); Ok(()) } @@ -1125,14 +1128,14 @@ pub mod pallet { if let Some(pos) = bids.iter().position(|b| b.kind.check_voucher(&who).is_ok()) { // Remove the bid, and emit an event let vouched = bids.remove(pos).who; - Self::deposit_event(Event::::Unvouch(vouched)); + Self::deposit_event(Event::::Unvouch { candidate: vouched }); } ); } } >::remove(&who); - Self::deposit_event(Event::::SuspendedMemberJudgement(who, forgive)); + Self::deposit_event(Event::::SuspendedMemberJudgement { who, judged: forgive }); Ok(()) } @@ -1253,7 +1256,7 @@ pub mod pallet { ensure_root(origin)?; ensure!(max > 1, Error::::MaxMembers); MaxMembers::::put(max); - Self::deposit_event(Event::::NewMaxMembers(max)); + Self::deposit_event(Event::::NewMaxMembers { max }); Ok(()) } } @@ -1339,7 +1342,7 @@ impl, I: 'static> Pallet { >::remove(&voucher); }, } - Self::deposit_event(Event::::AutoUnbid(popped)); + Self::deposit_event(Event::::AutoUnbid { candidate: popped }); } >::put(bids); @@ -1504,7 +1507,7 @@ impl, I: 'static> Pallet { } else { // Suspend Candidate >::insert(&candidate, (value, kind)); - Self::deposit_event(Event::::CandidateSuspended(candidate)); + Self::deposit_event(Event::::CandidateSuspended { candidate }); None } }) @@ -1573,7 +1576,7 @@ impl, I: 'static> Pallet { >::put(&primary); T::MembershipChanged::change_members_sorted(&accounts, &[], &members); - Self::deposit_event(Event::::Inducted(primary, accounts)); + Self::deposit_event(Event::::Inducted { primary, candidates: accounts }); } // Bump the pot by at most PeriodSpend, but less if there's not very much left in our @@ -1638,7 +1641,7 @@ impl, I: 'static> Pallet { if Self::remove_member(&who).is_ok() { >::insert(who, true); >::remove(who); - Self::deposit_event(Event::::MemberSuspended(who.clone())); + Self::deposit_event(Event::::MemberSuspended { member: who.clone() }); } } @@ -1716,7 +1719,7 @@ impl, I: 'static> Pallet { let chosen = pick_item(&mut rng, &members[1..members.len() - 1]) .expect("exited if members empty; qed"); >::put(&chosen); - Self::deposit_event(Event::::Challenged(chosen.clone())); + Self::deposit_event(Event::::Challenged { member: chosen.clone() }); } else { >::kill(); } @@ -1820,6 +1823,6 @@ impl, I: 'static> OnUnbalanced> for Palle // Must resolve into existing but better to be safe. let _ = T::Currency::resolve_creating(&Self::account_id(), amount); - Self::deposit_event(Event::::Deposit(numeric_amount)); + Self::deposit_event(Event::::Deposit { value: numeric_amount }); } } diff --git a/frame/system/src/lib.rs b/frame/system/src/lib.rs index 0b00a7d8f597..31b702c135de 100644 --- a/frame/system/src/lib.rs +++ b/frame/system/src/lib.rs @@ -458,7 +458,7 @@ pub mod pallet { ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; let hash = T::Hashing::hash(&remark[..]); - Self::deposit_event(Event::Remarked(who, hash)); + Self::deposit_event(Event::Remarked { sender: who, hash }); Ok(().into()) } } @@ -466,18 +466,18 @@ pub mod pallet { /// Event for the System pallet. #[pallet::event] pub enum Event { - /// An extrinsic completed successfully. \[info\] - ExtrinsicSuccess(DispatchInfo), - /// An extrinsic failed. \[error, info\] - ExtrinsicFailed(DispatchError, DispatchInfo), + /// An extrinsic completed successfully. + ExtrinsicSuccess { dispatch_info: DispatchInfo }, + /// An extrinsic failed. + ExtrinsicFailed { dispatch_error: DispatchError, dispatch_info: DispatchInfo }, /// `:code` was updated. CodeUpdated, - /// A new \[account\] was created. - NewAccount(T::AccountId), - /// An \[account\] was reaped. - KilledAccount(T::AccountId), - /// On on-chain remark happened. \[origin, remark_hash\] - Remarked(T::AccountId, T::Hash), + /// A new account was created. + NewAccount { account: T::AccountId }, + /// An account was reaped. + KilledAccount { account: T::AccountId }, + /// On on-chain remark happened. + Remarked { sender: T::AccountId, hash: T::Hash }, } /// Old name generated by `decl_event`. @@ -1486,7 +1486,7 @@ impl Pallet { pub fn note_applied_extrinsic(r: &DispatchResultWithPostInfo, mut info: DispatchInfo) { info.weight = extract_actual_weight(r, &info); Self::deposit_event(match r { - Ok(_) => Event::ExtrinsicSuccess(info), + Ok(_) => Event::ExtrinsicSuccess { dispatch_info: info }, Err(err) => { log::trace!( target: "runtime::system", @@ -1494,7 +1494,7 @@ impl Pallet { Self::block_number(), err, ); - Event::ExtrinsicFailed(err.error, info) + Event::ExtrinsicFailed { dispatch_error: err.error, dispatch_info: info } }, }); @@ -1522,13 +1522,13 @@ impl Pallet { /// An account is being created. pub fn on_created_account(who: T::AccountId, _a: &mut AccountInfo) { T::OnNewAccount::on_new_account(&who); - Self::deposit_event(Event::NewAccount(who)); + Self::deposit_event(Event::NewAccount { account: who }); } /// Do anything that needs to be done after an account has been killed. fn on_killed_account(who: T::AccountId) { T::OnKilledAccount::on_killed_account(&who); - Self::deposit_event(Event::KilledAccount(who)); + Self::deposit_event(Event::KilledAccount { account: who }); } /// Determine whether or not it is possible to update the code. diff --git a/frame/system/src/tests.rs b/frame/system/src/tests.rs index a4dd3403f2c3..f9c167ec4be3 100644 --- a/frame/system/src/tests.rs +++ b/frame/system/src/tests.rs @@ -168,44 +168,44 @@ fn deposit_event_should_work() { ); System::initialize(&2, &[0u8; 32].into(), &Default::default(), InitKind::Full); - System::deposit_event(SysEvent::NewAccount(32)); + System::deposit_event(SysEvent::NewAccount { account: 32 }); System::note_finished_initialize(); - System::deposit_event(SysEvent::KilledAccount(42)); + System::deposit_event(SysEvent::KilledAccount { account: 42 }); System::note_applied_extrinsic(&Ok(().into()), Default::default()); System::note_applied_extrinsic(&Err(DispatchError::BadOrigin.into()), Default::default()); System::note_finished_extrinsics(); - System::deposit_event(SysEvent::NewAccount(3)); + System::deposit_event(SysEvent::NewAccount { account: 3 }); System::finalize(); assert_eq!( System::events(), vec![ EventRecord { phase: Phase::Initialization, - event: SysEvent::NewAccount(32).into(), + event: SysEvent::NewAccount { account: 32 }.into(), topics: vec![], }, EventRecord { phase: Phase::ApplyExtrinsic(0), - event: SysEvent::KilledAccount(42).into(), + event: SysEvent::KilledAccount { account: 42 }.into(), topics: vec![] }, EventRecord { phase: Phase::ApplyExtrinsic(0), - event: SysEvent::ExtrinsicSuccess(Default::default()).into(), + event: SysEvent::ExtrinsicSuccess { dispatch_info: Default::default() }.into(), topics: vec![] }, EventRecord { phase: Phase::ApplyExtrinsic(1), - event: SysEvent::ExtrinsicFailed( - DispatchError::BadOrigin.into(), - Default::default() - ) + event: SysEvent::ExtrinsicFailed { + dispatch_error: DispatchError::BadOrigin.into(), + dispatch_info: Default::default() + } .into(), topics: vec![] }, EventRecord { phase: Phase::Finalization, - event: SysEvent::NewAccount(3).into(), + event: SysEvent::NewAccount { account: 3 }.into(), topics: vec![] }, ] @@ -234,37 +234,34 @@ fn deposit_event_uses_actual_weight() { vec![ EventRecord { phase: Phase::ApplyExtrinsic(0), - event: SysEvent::ExtrinsicSuccess(DispatchInfo { - weight: 300, - ..Default::default() - },) + event: SysEvent::ExtrinsicSuccess { + dispatch_info: DispatchInfo { weight: 300, ..Default::default() }, + } .into(), topics: vec![] }, EventRecord { phase: Phase::ApplyExtrinsic(1), - event: SysEvent::ExtrinsicSuccess(DispatchInfo { - weight: 1000, - ..Default::default() - },) + event: SysEvent::ExtrinsicSuccess { + dispatch_info: DispatchInfo { weight: 1000, ..Default::default() }, + } .into(), topics: vec![] }, EventRecord { phase: Phase::ApplyExtrinsic(2), - event: SysEvent::ExtrinsicSuccess(DispatchInfo { - weight: 1000, - ..Default::default() - },) + event: SysEvent::ExtrinsicSuccess { + dispatch_info: DispatchInfo { weight: 1000, ..Default::default() }, + } .into(), topics: vec![] }, EventRecord { phase: Phase::ApplyExtrinsic(3), - event: SysEvent::ExtrinsicFailed( - DispatchError::BadOrigin.into(), - DispatchInfo { weight: 999, ..Default::default() }, - ) + event: SysEvent::ExtrinsicFailed { + dispatch_error: DispatchError::BadOrigin.into(), + dispatch_info: DispatchInfo { weight: 999, ..Default::default() }, + } .into(), topics: vec![] }, @@ -284,9 +281,9 @@ fn deposit_event_topics() { let topics = vec![H256::repeat_byte(1), H256::repeat_byte(2), H256::repeat_byte(3)]; // We deposit a few events with different sets of topics. - System::deposit_event_indexed(&topics[0..3], SysEvent::NewAccount(1).into()); - System::deposit_event_indexed(&topics[0..1], SysEvent::NewAccount(2).into()); - System::deposit_event_indexed(&topics[1..2], SysEvent::NewAccount(3).into()); + System::deposit_event_indexed(&topics[0..3], SysEvent::NewAccount { account: 1 }.into()); + System::deposit_event_indexed(&topics[0..1], SysEvent::NewAccount { account: 2 }.into()); + System::deposit_event_indexed(&topics[1..2], SysEvent::NewAccount { account: 3 }.into()); System::finalize(); @@ -296,17 +293,17 @@ fn deposit_event_topics() { vec![ EventRecord { phase: Phase::Finalization, - event: SysEvent::NewAccount(1).into(), + event: SysEvent::NewAccount { account: 1 }.into(), topics: topics[0..3].to_vec(), }, EventRecord { phase: Phase::Finalization, - event: SysEvent::NewAccount(2).into(), + event: SysEvent::NewAccount { account: 2 }.into(), topics: topics[0..1].to_vec(), }, EventRecord { phase: Phase::Finalization, - event: SysEvent::NewAccount(3).into(), + event: SysEvent::NewAccount { account: 3 }.into(), topics: topics[1..2].to_vec(), } ] diff --git a/frame/transaction-payment/src/lib.rs b/frame/transaction-payment/src/lib.rs index f912866f7bb3..ed96f26cc007 100644 --- a/frame/transaction-payment/src/lib.rs +++ b/frame/transaction-payment/src/lib.rs @@ -1369,7 +1369,9 @@ mod tests { amount: 80, })); // Killed Event - System::assert_has_event(Event::System(system::Event::KilledAccount(2))); + System::assert_has_event(Event::System(system::Event::KilledAccount { + account: 2, + })); }); } diff --git a/frame/transaction-storage/src/benchmarking.rs b/frame/transaction-storage/src/benchmarking.rs index 6ca9b247f022..0f90b51087ae 100644 --- a/frame/transaction-storage/src/benchmarking.rs +++ b/frame/transaction-storage/src/benchmarking.rs @@ -109,7 +109,7 @@ benchmarks! { }: _(RawOrigin::Signed(caller.clone()), vec![0u8; l as usize]) verify { assert!(!BlockTransactions::::get().is_empty()); - assert_last_event::(Event::Stored(0).into()); + assert_last_event::(Event::Stored { index: 0 }.into()); } renew { @@ -122,7 +122,7 @@ benchmarks! { run_to_block::(1u32.into()); }: _(RawOrigin::Signed(caller.clone()), T::BlockNumber::zero(), 0) verify { - assert_last_event::(Event::Renewed(0).into()); + assert_last_event::(Event::Renewed { index: 0 }.into()); } check_proof_max { diff --git a/frame/transaction-storage/src/lib.rs b/frame/transaction-storage/src/lib.rs index bc31199d9039..94937c04ed5d 100644 --- a/frame/transaction-storage/src/lib.rs +++ b/frame/transaction-storage/src/lib.rs @@ -210,7 +210,7 @@ pub mod pallet { }); Ok(()) })?; - Self::deposit_event(Event::Stored(index)); + Self::deposit_event(Event::Stored { index }); Ok(()) } @@ -251,7 +251,7 @@ pub mod pallet { }); Ok(()) })?; - Self::deposit_event(Event::Renewed(index)); + Self::deposit_event(Event::Renewed { index }); Ok(().into()) } @@ -313,9 +313,9 @@ pub mod pallet { #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { /// Stored data under specified index. - Stored(u32), + Stored { index: u32 }, /// Renewed data under specified index. - Renewed(u32), + Renewed { index: u32 }, /// Storage proof was successfully checked. ProofChecked, } diff --git a/frame/treasury/src/lib.rs b/frame/treasury/src/lib.rs index 646baa99b99b..5258426e2681 100644 --- a/frame/treasury/src/lib.rs +++ b/frame/treasury/src/lib.rs @@ -255,21 +255,20 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event, I: 'static = ()> { - /// New proposal. \[proposal_index\] - Proposed(ProposalIndex), - /// We have ended a spend period and will now allocate funds. \[budget_remaining\] - Spending(BalanceOf), - /// Some funds have been allocated. \[proposal_index, award, beneficiary\] - Awarded(ProposalIndex, BalanceOf, T::AccountId), - /// A proposal was rejected; funds were slashed. \[proposal_index, slashed\] - Rejected(ProposalIndex, BalanceOf), - /// Some of our funds have been burnt. \[burn\] - Burnt(BalanceOf), + /// New proposal. + Proposed { proposal_index: ProposalIndex }, + /// We have ended a spend period and will now allocate funds. + Spending { budget_remaining: BalanceOf }, + /// Some funds have been allocated. + Awarded { proposal_index: ProposalIndex, award: BalanceOf, account: T::AccountId }, + /// A proposal was rejected; funds were slashed. + Rejected { proposal_index: ProposalIndex, slashed: BalanceOf }, + /// Some of our funds have been burnt. + Burnt { burnt_funds: BalanceOf }, /// Spending has finished; this is the amount that rolls over until next spend. - /// \[budget_remaining\] - Rollover(BalanceOf), - /// Some funds have been deposited. \[deposit\] - Deposit(BalanceOf), + Rollover { rollover_balance: BalanceOf }, + /// Some funds have been deposited. + Deposit { value: BalanceOf }, } /// Old name generated by `decl_event`. @@ -334,7 +333,7 @@ pub mod pallet { >::put(c + 1); >::insert(c, Proposal { proposer, value, beneficiary, bond }); - Self::deposit_event(Event::Proposed(c)); + Self::deposit_event(Event::Proposed { proposal_index: c }); Ok(()) } @@ -360,7 +359,10 @@ pub mod pallet { let imbalance = T::Currency::slash_reserved(&proposal.proposer, value).0; T::OnSlash::on_unbalanced(imbalance); - Self::deposit_event(Event::::Rejected(proposal_id, value)); + Self::deposit_event(Event::::Rejected { + proposal_index: proposal_id, + slashed: value, + }); Ok(()) } @@ -410,7 +412,7 @@ impl, I: 'static> Pallet { let mut total_weight: Weight = Zero::zero(); let mut budget_remaining = Self::pot(); - Self::deposit_event(Event::Spending(budget_remaining)); + Self::deposit_event(Event::Spending { budget_remaining }); let account_id = Self::account_id(); let mut missed_any = false; @@ -431,7 +433,11 @@ impl, I: 'static> Pallet { // provide the allocation. imbalance.subsume(T::Currency::deposit_creating(&p.beneficiary, p.value)); - Self::deposit_event(Event::Awarded(index, p.value, p.beneficiary)); + Self::deposit_event(Event::Awarded { + proposal_index: index, + award: p.value, + account: p.beneficiary, + }); false } else { missed_any = true; @@ -462,7 +468,7 @@ impl, I: 'static> Pallet { let (debit, credit) = T::Currency::pair(burn); imbalance.subsume(debit); T::BurnDestination::on_unbalanced(credit); - Self::deposit_event(Event::Burnt(burn)) + Self::deposit_event(Event::Burnt { burnt_funds: burn }) } // Must never be an error, but better to be safe. @@ -477,7 +483,7 @@ impl, I: 'static> Pallet { drop(problem); } - Self::deposit_event(Event::Rollover(budget_remaining)); + Self::deposit_event(Event::Rollover { rollover_balance: budget_remaining }); total_weight } @@ -498,6 +504,6 @@ impl, I: 'static> OnUnbalanced> for Palle // Must resolve into existing but better to be safe. let _ = T::Currency::resolve_creating(&Self::account_id(), amount); - Self::deposit_event(Event::Deposit(numeric_amount)); + Self::deposit_event(Event::Deposit { value: numeric_amount }); } } diff --git a/frame/utility/src/lib.rs b/frame/utility/src/lib.rs index 14d8a66514e3..fde4e78366e6 100644 --- a/frame/utility/src/lib.rs +++ b/frame/utility/src/lib.rs @@ -115,8 +115,8 @@ pub mod pallet { BatchCompleted, /// A single item within a Batch of dispatches has completed with no error. ItemCompleted, - /// A call was dispatched. \[result\] - DispatchedAs(DispatchResult), + /// A call was dispatched. + DispatchedAs { result: DispatchResult }, } // Align the call size to 1KB. As we are currently compiling the runtime for native/wasm @@ -380,7 +380,9 @@ pub mod pallet { let res = call.dispatch_bypass_filter((*as_origin).into()); - Self::deposit_event(Event::DispatchedAs(res.map(|_| ()).map_err(|e| e.error))); + Self::deposit_event(Event::DispatchedAs { + result: res.map(|_| ()).map_err(|e| e.error), + }); Ok(()) } } From b6c1c1bcfa5d831bfd1f278064d7af757f9b38f5 Mon Sep 17 00:00:00 2001 From: Guillaume Thiolliere Date: Wed, 1 Dec 2021 09:59:09 +0900 Subject: [PATCH 244/695] Fix order of hook execution (#10043) * fix order * Update frame/support/procedural/src/construct_runtime/mod.rs Co-authored-by: Alexander Popiak * format * more accurate description * format * better explicit types * fix tests * address feedback * add a type to ease non breaking implementation * add comment about constraint * fix test * add test for generated types Co-authored-by: Alexander Popiak --- bin/node-template/runtime/src/lib.rs | 2 +- bin/node/runtime/src/lib.rs | 4 +- frame/executive/src/lib.rs | 104 +++++++-------- .../procedural/src/construct_runtime/mod.rs | 71 +++++++++-- frame/support/test/tests/pallet.rs | 120 +++++++++++++++++- frame/support/test/tests/pallet_instance.rs | 19 ++- 6 files changed, 231 insertions(+), 89 deletions(-) diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index 8ecb2199dda7..4eaa0aa00d0b 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -323,7 +323,7 @@ pub type Executive = frame_executive::Executive< Block, frame_system::ChainContext, Runtime, - AllPallets, + AllPalletsWithSystem, >; impl_runtime_apis! { diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 44cefecd067f..3f553221e67a 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -1268,6 +1268,8 @@ construct_runtime!( Utility: pallet_utility, Babe: pallet_babe, Timestamp: pallet_timestamp, + // Authorship must be before session in order to note author in the correct session and era + // for im-online and staking. Authorship: pallet_authorship, Indices: pallet_indices, Balances: pallet_balances, @@ -1345,7 +1347,7 @@ pub type Executive = frame_executive::Executive< Block, frame_system::ChainContext, Runtime, - AllPallets, + AllPalletsWithSystem, pallet_bags_list::migrations::CheckCounterPrefix, >; diff --git a/frame/executive/src/lib.rs b/frame/executive/src/lib.rs index dd0a9abf8687..9b81527fadb3 100644 --- a/frame/executive/src/lib.rs +++ b/frame/executive/src/lib.rs @@ -59,7 +59,7 @@ //! # type Context = frame_system::ChainContext; //! # pub type Block = generic::Block; //! # pub type Balances = u64; -//! # pub type AllPallets = u64; +//! # pub type AllPalletsWithSystem = u64; //! # pub enum Runtime {}; //! # use sp_runtime::transaction_validity::{ //! # TransactionValidity, UnknownTransaction, TransactionSource, @@ -73,7 +73,7 @@ //! # } //! # } //! /// Executive: handles dispatch to the various modules. -//! pub type Executive = executive::Executive; +//! pub type Executive = executive::Executive; //! ``` //! //! ### Custom `OnRuntimeUpgrade` logic @@ -90,7 +90,7 @@ //! # type Context = frame_system::ChainContext; //! # pub type Block = generic::Block; //! # pub type Balances = u64; -//! # pub type AllPallets = u64; +//! # pub type AllPalletsWithSystem = u64; //! # pub enum Runtime {}; //! # use sp_runtime::transaction_validity::{ //! # TransactionValidity, UnknownTransaction, TransactionSource, @@ -111,7 +111,7 @@ //! } //! } //! -//! pub type Executive = executive::Executive; +//! pub type Executive = executive::Executive; //! ``` #![cfg_attr(not(feature = "std"), no_std)] @@ -147,11 +147,26 @@ pub type OriginOf = as Dispatchable>::Origin; /// - `Block`: The block type of the runtime /// - `Context`: The context that is used when checking an extrinsic. /// - `UnsignedValidator`: The unsigned transaction validator of the runtime. -/// - `AllPallets`: Tuple that contains all modules. Will be used to call e.g. `on_initialize`. +/// - `AllPalletsWithSystem`: Tuple that contains all pallets including frame system pallet. Will be +/// used to call hooks e.g. `on_initialize`. /// - `OnRuntimeUpgrade`: Custom logic that should be called after a runtime upgrade. Modules are -/// already called by `AllPallets`. It will be called before all modules will be called. -pub struct Executive( - PhantomData<(System, Block, Context, UnsignedValidator, AllPallets, OnRuntimeUpgrade)>, +/// already called by `AllPalletsWithSystem`. It will be called before all modules will be called. +pub struct Executive< + System, + Block, + Context, + UnsignedValidator, + AllPalletsWithSystem, + OnRuntimeUpgrade = (), +>( + PhantomData<( + System, + Block, + Context, + UnsignedValidator, + AllPalletsWithSystem, + OnRuntimeUpgrade, + )>, ); impl< @@ -159,14 +174,14 @@ impl< Block: traits::Block
, Context: Default, UnsignedValidator, - AllPallets: OnRuntimeUpgrade + AllPalletsWithSystem: OnRuntimeUpgrade + OnInitialize + OnIdle + OnFinalize + OffchainWorker, COnRuntimeUpgrade: OnRuntimeUpgrade, > ExecuteBlock - for Executive + for Executive where Block::Extrinsic: Checkable + Codec, CheckedOf: Applyable + GetDispatchInfo, @@ -181,7 +196,7 @@ where Block, Context, UnsignedValidator, - AllPallets, + AllPalletsWithSystem, COnRuntimeUpgrade, >::execute_block(block); } @@ -192,13 +207,13 @@ impl< Block: traits::Block
, Context: Default, UnsignedValidator, - AllPallets: OnRuntimeUpgrade + AllPalletsWithSystem: OnRuntimeUpgrade + OnInitialize + OnIdle + OnFinalize + OffchainWorker, COnRuntimeUpgrade: OnRuntimeUpgrade, - > Executive + > Executive where Block::Extrinsic: Checkable + Codec, CheckedOf: Applyable + GetDispatchInfo, @@ -209,14 +224,7 @@ where { /// Execute all `OnRuntimeUpgrade` of this runtime, and return the aggregate weight. pub fn execute_on_runtime_upgrade() -> frame_support::weights::Weight { - let mut weight = 0; - weight = weight.saturating_add(COnRuntimeUpgrade::on_runtime_upgrade()); - weight = weight.saturating_add( - as OnRuntimeUpgrade>::on_runtime_upgrade(), - ); - weight = weight.saturating_add(::on_runtime_upgrade()); - - weight + <(COnRuntimeUpgrade, AllPalletsWithSystem) as OnRuntimeUpgrade>::on_runtime_upgrade() } /// Execute given block, but don't do any of the `final_checks`. @@ -255,19 +263,10 @@ where /// This should only be used for testing. #[cfg(feature = "try-runtime")] pub fn try_runtime_upgrade() -> Result { - < - (frame_system::Pallet::, COnRuntimeUpgrade, AllPallets) - as - OnRuntimeUpgrade - >::pre_upgrade().unwrap(); - + <(COnRuntimeUpgrade, AllPalletsWithSystem) as OnRuntimeUpgrade>::pre_upgrade().unwrap(); let weight = Self::execute_on_runtime_upgrade(); - < - (frame_system::Pallet::, COnRuntimeUpgrade, AllPallets) - as - OnRuntimeUpgrade - >::post_upgrade().unwrap(); + <(COnRuntimeUpgrade, AllPalletsWithSystem) as OnRuntimeUpgrade>::post_upgrade().unwrap(); Ok(weight) } @@ -305,12 +304,9 @@ where digest, frame_system::InitKind::Full, ); - weight = weight.saturating_add( as OnInitialize< + weight = weight.saturating_add(>::on_initialize(*block_number)); - weight = weight.saturating_add( - >::on_initialize(*block_number), - ); weight = weight.saturating_add( >::get().base_block, ); @@ -415,30 +411,20 @@ where fn idle_and_finalize_hook(block_number: NumberFor) { let weight = >::block_weight(); let max_weight = >::get().max_block; - let mut remaining_weight = max_weight.saturating_sub(weight.total()); + let remaining_weight = max_weight.saturating_sub(weight.total()); if remaining_weight > 0 { - let mut used_weight = - as OnIdle>::on_idle( - block_number, - remaining_weight, - ); - remaining_weight = remaining_weight.saturating_sub(used_weight); - used_weight = >::on_idle( + let used_weight = >::on_idle( block_number, remaining_weight, - ) - .saturating_add(used_weight); + ); >::register_extra_weight_unchecked( used_weight, DispatchClass::Mandatory, ); } - as OnFinalize>::on_finalize( - block_number, - ); - >::on_finalize(block_number); + >::on_finalize(block_number); } /// Apply extrinsic outside of the block execution function. @@ -567,7 +553,9 @@ where // as well. frame_system::BlockHash::::insert(header.number(), header.hash()); - >::offchain_worker(*header.number()) + >::offchain_worker( + *header.number(), + ) } } @@ -849,7 +837,7 @@ mod tests { Block, ChainContext, Runtime, - AllPallets, + AllPalletsWithSystem, CustomOnRuntimeUpgrade, >; @@ -1360,23 +1348,19 @@ mod tests { )); // All weights that show up in the `initialize_block_impl` - let frame_system_upgrade_weight = frame_system::Pallet::::on_runtime_upgrade(); let custom_runtime_upgrade_weight = CustomOnRuntimeUpgrade::on_runtime_upgrade(); - let runtime_upgrade_weight = ::on_runtime_upgrade(); - let frame_system_on_initialize_weight = - frame_system::Pallet::::on_initialize(block_number); + let runtime_upgrade_weight = + ::on_runtime_upgrade(); let on_initialize_weight = - >::on_initialize(block_number); + >::on_initialize(block_number); let base_block_weight = ::BlockWeights::get().base_block; // Weights are recorded correctly assert_eq!( frame_system::Pallet::::block_weight().total(), - frame_system_upgrade_weight + - custom_runtime_upgrade_weight + + custom_runtime_upgrade_weight + runtime_upgrade_weight + - frame_system_on_initialize_weight + on_initialize_weight + base_block_weight, ); }); diff --git a/frame/support/procedural/src/construct_runtime/mod.rs b/frame/support/procedural/src/construct_runtime/mod.rs index a5da775b9c9e..b32ecf1bccd5 100644 --- a/frame/support/procedural/src/construct_runtime/mod.rs +++ b/frame/support/procedural/src/construct_runtime/mod.rs @@ -304,35 +304,82 @@ fn decl_all_pallets<'a>( types.extend(type_decl); names.push(&pallet_declaration.name); } - // Make nested tuple structure like (((Babe, Consensus), Grandpa), ...) + + // Make nested tuple structure like: + // `((FirstPallet, (SecondPallet, ( ... , LastPallet) ... ))))` // But ignore the system pallet. - let all_pallets = names + let all_pallets_without_system = names .iter() .filter(|n| **n != SYSTEM_PALLET_NAME) + .rev() .fold(TokenStream2::default(), |combined, name| quote!((#name, #combined))); + // Make nested tuple structure like: + // `((FirstPallet, (SecondPallet, ( ... , LastPallet) ... ))))` let all_pallets_with_system = names .iter() + .rev() + .fold(TokenStream2::default(), |combined, name| quote!((#name, #combined))); + + // Make nested tuple structure like: + // `((LastPallet, (SecondLastPallet, ( ... , FirstPallet) ... ))))` + // But ignore the system pallet. + let all_pallets_without_system_reversed = names + .iter() + .filter(|n| **n != SYSTEM_PALLET_NAME) .fold(TokenStream2::default(), |combined, name| quote!((#name, #combined))); + // Make nested tuple structure like: + // `((LastPallet, (SecondLastPallet, ( ... , FirstPallet) ... ))))` + let all_pallets_with_system_reversed = names + .iter() + .fold(TokenStream2::default(), |combined, name| quote!((#name, #combined))); + + let system_pallet = match names.iter().find(|n| **n == SYSTEM_PALLET_NAME) { + Some(name) => name, + None => + return syn::Error::new( + proc_macro2::Span::call_site(), + "`System` pallet declaration is missing. \ + Please add this line: `System: frame_system::{Pallet, Call, Storage, Config, Event},`", + ) + .into_compile_error(), + }; + quote!( #types /// All pallets included in the runtime as a nested tuple of types. - /// Excludes the System pallet. - pub type AllPallets = ( #all_pallets ); + #[deprecated(note = "The type definition has changed from representing all pallets \ + excluding system, in reversed order to become the representation of all pallets \ + including system pallet in regular order. For this reason it is encouraged to use \ + explicitly one of `AllPalletsWithSystem`, `AllPalletsWithoutSystem`, \ + `AllPalletsWithSystemReversed`, `AllPalletsWithoutSystemReversed`. \ + Note that the type `frame_executive::Executive` expects one of `AllPalletsWithSystem` \ + , `AllPalletsWithSystemReversed`, `AllPalletsReversedWithSystemFirst`. More details in \ + https://github.com/paritytech/substrate/pull/10043")] + pub type AllPallets = AllPalletsWithSystem; + /// All pallets included in the runtime as a nested tuple of types. pub type AllPalletsWithSystem = ( #all_pallets_with_system ); - /// All modules included in the runtime as a nested tuple of types. + /// All pallets included in the runtime as a nested tuple of types. + /// Excludes the System pallet. + pub type AllPalletsWithoutSystem = ( #all_pallets_without_system ); + + /// All pallets included in the runtime as a nested tuple of types in reversed order. /// Excludes the System pallet. - #[deprecated(note = "use `AllPallets` instead")] - #[allow(dead_code)] - pub type AllModules = ( #all_pallets ); - /// All modules included in the runtime as a nested tuple of types. - #[deprecated(note = "use `AllPalletsWithSystem` instead")] - #[allow(dead_code)] - pub type AllModulesWithSystem = ( #all_pallets_with_system ); + pub type AllPalletsWithoutSystemReversed = ( #all_pallets_without_system_reversed ); + + /// All pallets included in the runtime as a nested tuple of types in reversed order. + pub type AllPalletsWithSystemReversed = ( #all_pallets_with_system_reversed ); + + /// All pallets included in the runtime as a nested tuple of types in reversed order. + /// With the system pallet first. + pub type AllPalletsReversedWithSystemFirst = ( + #system_pallet, + AllPalletsWithoutSystemReversed + ); ) } diff --git a/frame/support/test/tests/pallet.rs b/frame/support/test/tests/pallet.rs index dcf739af614b..509e3217ddf9 100644 --- a/frame/support/test/tests/pallet.rs +++ b/frame/support/test/tests/pallet.rs @@ -453,9 +453,21 @@ pub mod pallet2 { pub struct Pallet(_); #[pallet::hooks] - impl Hooks> for Pallet where - T::AccountId: From + SomeAssociation1 + impl Hooks> for Pallet + where + T::AccountId: From + SomeAssociation1, { + fn on_initialize(_: BlockNumberFor) -> Weight { + Self::deposit_event(Event::Something(11)); + 0 + } + fn on_finalize(_: BlockNumberFor) { + Self::deposit_event(Event::Something(21)); + } + fn on_runtime_upgrade() -> Weight { + Self::deposit_event(Event::Something(31)); + 0 + } } #[pallet::call] @@ -469,6 +481,7 @@ pub mod pallet2 { CountedStorageMap; #[pallet::event] + #[pallet::generate_deposit(fn deposit_event)] pub enum Event { /// Something Something(u32), @@ -963,10 +976,10 @@ fn pallet_hooks_expand() { TestExternalities::default().execute_with(|| { frame_system::Pallet::::set_block_number(1); - assert_eq!(AllPallets::on_initialize(1), 10); - AllPallets::on_finalize(1); + assert_eq!(AllPalletsWithoutSystem::on_initialize(1), 10); + AllPalletsWithoutSystem::on_finalize(1); - assert_eq!(AllPallets::on_runtime_upgrade(), 30); + assert_eq!(AllPalletsWithoutSystem::on_runtime_upgrade(), 30); assert_eq!( frame_system::Pallet::::events()[0].event, @@ -974,10 +987,62 @@ fn pallet_hooks_expand() { ); assert_eq!( frame_system::Pallet::::events()[1].event, + Event::Example2(pallet2::Event::Something(11)), + ); + assert_eq!( + frame_system::Pallet::::events()[2].event, Event::Example(pallet::Event::Something(20)), ); + assert_eq!( + frame_system::Pallet::::events()[3].event, + Event::Example2(pallet2::Event::Something(21)), + ); + assert_eq!( + frame_system::Pallet::::events()[4].event, + Event::Example(pallet::Event::Something(30)), + ); + assert_eq!( + frame_system::Pallet::::events()[5].event, + Event::Example2(pallet2::Event::Something(31)), + ); + }) +} + +#[test] +fn all_pallets_type_reversed_order_is_correct() { + TestExternalities::default().execute_with(|| { + frame_system::Pallet::::set_block_number(1); + + #[allow(deprecated)] + { + assert_eq!(AllPalletsWithoutSystemReversed::on_initialize(1), 10); + AllPalletsWithoutSystemReversed::on_finalize(1); + + assert_eq!(AllPalletsWithoutSystemReversed::on_runtime_upgrade(), 30); + } + + assert_eq!( + frame_system::Pallet::::events()[0].event, + Event::Example2(pallet2::Event::Something(11)), + ); + assert_eq!( + frame_system::Pallet::::events()[1].event, + Event::Example(pallet::Event::Something(10)), + ); assert_eq!( frame_system::Pallet::::events()[2].event, + Event::Example2(pallet2::Event::Something(21)), + ); + assert_eq!( + frame_system::Pallet::::events()[3].event, + Event::Example(pallet::Event::Something(20)), + ); + assert_eq!( + frame_system::Pallet::::events()[4].event, + Event::Example2(pallet2::Event::Something(31)), + ); + assert_eq!( + frame_system::Pallet::::events()[5].event, Event::Example(pallet::Event::Something(30)), ); }) @@ -1499,3 +1564,48 @@ fn test_storage_info() { ], ); } + +#[test] +fn assert_type_all_pallets_reversed_with_system_first_is_correct() { + // Just ensure the 2 types are same. + fn _a(_t: AllPalletsReversedWithSystemFirst) {} + fn _b(t: (System, (Example4, (Example2, (Example,))))) { + _a(t) + } +} + +#[test] +fn assert_type_all_pallets_with_system_is_correct() { + // Just ensure the 2 types are same. + fn _a(_t: AllPalletsWithSystem) {} + fn _b(t: (System, (Example, (Example2, (Example4,))))) { + _a(t) + } +} + +#[test] +fn assert_type_all_pallets_without_system_is_correct() { + // Just ensure the 2 types are same. + fn _a(_t: AllPalletsWithoutSystem) {} + fn _b(t: (Example, (Example2, (Example4,)))) { + _a(t) + } +} + +#[test] +fn assert_type_all_pallets_with_system_reversed_is_correct() { + // Just ensure the 2 types are same. + fn _a(_t: AllPalletsWithSystemReversed) {} + fn _b(t: (Example4, (Example2, (Example, (System,))))) { + _a(t) + } +} + +#[test] +fn assert_type_all_pallets_without_system_reversed_is_correct() { + // Just ensure the 2 types are same. + fn _a(_t: AllPalletsWithoutSystemReversed) {} + fn _b(t: (Example4, (Example2, (Example,)))) { + _a(t) + } +} diff --git a/frame/support/test/tests/pallet_instance.rs b/frame/support/test/tests/pallet_instance.rs index c031ac9fe1bf..de70b0e7e404 100644 --- a/frame/support/test/tests/pallet_instance.rs +++ b/frame/support/test/tests/pallet_instance.rs @@ -551,35 +551,34 @@ fn pallet_hooks_expand() { TestExternalities::default().execute_with(|| { frame_system::Pallet::::set_block_number(1); - assert_eq!(AllPallets::on_initialize(1), 21); - AllPallets::on_finalize(1); + assert_eq!(AllPalletsWithoutSystem::on_initialize(1), 21); + AllPalletsWithoutSystem::on_finalize(1); - assert_eq!(AllPallets::on_runtime_upgrade(), 61); + assert_eq!(AllPalletsWithoutSystem::on_runtime_upgrade(), 61); - // The order is indeed reversed due to https://github.com/paritytech/substrate/issues/6280 assert_eq!( frame_system::Pallet::::events()[0].event, - Event::Instance1Example(pallet::Event::Something(11)), + Event::Example(pallet::Event::Something(10)), ); assert_eq!( frame_system::Pallet::::events()[1].event, - Event::Example(pallet::Event::Something(10)), + Event::Instance1Example(pallet::Event::Something(11)), ); assert_eq!( frame_system::Pallet::::events()[2].event, - Event::Instance1Example(pallet::Event::Something(21)), + Event::Example(pallet::Event::Something(20)), ); assert_eq!( frame_system::Pallet::::events()[3].event, - Event::Example(pallet::Event::Something(20)), + Event::Instance1Example(pallet::Event::Something(21)), ); assert_eq!( frame_system::Pallet::::events()[4].event, - Event::Instance1Example(pallet::Event::Something(31)), + Event::Example(pallet::Event::Something(30)), ); assert_eq!( frame_system::Pallet::::events()[5].event, - Event::Example(pallet::Event::Something(30)), + Event::Instance1Example(pallet::Event::Something(31)), ); }) } From b6a3ecc150040daa440637ac892265165f3450f6 Mon Sep 17 00:00:00 2001 From: zjb0807 Date: Wed, 1 Dec 2021 13:37:30 +0800 Subject: [PATCH 245/695] use double quotes instead of single quotes & upgrade 2021 (#10398) --- bin/node-template/pallets/template/Cargo.toml | 18 +++++++++--------- bin/node-template/runtime/Cargo.toml | 2 +- .../asset-tx-payment/Cargo.toml | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/bin/node-template/pallets/template/Cargo.toml b/bin/node-template/pallets/template/Cargo.toml index 1a239bef3262..887b022d6ca7 100644 --- a/bin/node-template/pallets/template/Cargo.toml +++ b/bin/node-template/pallets/template/Cargo.toml @@ -1,10 +1,10 @@ [package] -name = 'pallet-template' +name = "pallet-template" version = "3.0.0" description = "FRAME pallet template for defining custom runtime logic." -authors = ['Substrate DevHub '] +authors = ["Substrate DevHub "] homepage = "https://substrate.io/" -edition = '2018' +edition = "2021" license = "Unlicense" publish = false repository = "https://github.com/substrate-developer-hub/substrate-node-template/" @@ -27,13 +27,13 @@ sp-io = { default-features = false, version = "4.0.0-dev", path = "../../../../p sp-runtime = { default-features = false, version = "4.0.0-dev", path = "../../../../primitives/runtime" } [features] -default = ['std'] +default = ["std"] std = [ - 'codec/std', - 'scale-info/std', - 'frame-support/std', - 'frame-system/std', - 'frame-benchmarking/std', + "codec/std", + "scale-info/std", + "frame-support/std", + "frame-system/std", + "frame-benchmarking/std", ] runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks"] diff --git a/bin/node-template/runtime/Cargo.toml b/bin/node-template/runtime/Cargo.toml index c821bdac169e..c7ff0ff5a268 100644 --- a/bin/node-template/runtime/Cargo.toml +++ b/bin/node-template/runtime/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "node-template-runtime" version = "3.0.0" -description = 'A fresh FRAME-based Substrate runtime, ready for hacking.' +description = "A fresh FRAME-based Substrate runtime, ready for hacking." authors = ["Substrate DevHub "] homepage = "https://substrate.io/" edition = "2021" diff --git a/frame/transaction-payment/asset-tx-payment/Cargo.toml b/frame/transaction-payment/asset-tx-payment/Cargo.toml index e4f3b128cfce..a79bf6855100 100644 --- a/frame/transaction-payment/asset-tx-payment/Cargo.toml +++ b/frame/transaction-payment/asset-tx-payment/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-asset-tx-payment" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" From 8bf9836f3a709f220ff74be23a4004146480eb79 Mon Sep 17 00:00:00 2001 From: Seun Lanlege Date: Wed, 1 Dec 2021 12:45:36 +0100 Subject: [PATCH 246/695] Make BEEFY payload extensible (#10307) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * make BEEFY payload extensible * cargo fmt * cargo fmt * remove generic payload param in beefy-primitives * cargo fmt * Apply suggestions from code review Co-authored-by: Tomasz Drwięga * adds Paylaod Type * remove hex * fix tests * Apply suggestions from code review Co-authored-by: Tomasz Drwięga * use binary_search_by to sort * Payload::new() * fix tests * Apply suggestions from code review Co-authored-by: Tomasz Drwięga * fix tests * cargo fmt * fix get_decoded * fix test Co-authored-by: Tomasz Drwięga --- Cargo.lock | 1 + client/beefy/src/gossip.rs | 32 +++----- client/beefy/src/notification.rs | 3 +- client/beefy/src/round.rs | 36 ++++----- client/beefy/src/worker.rs | 15 ++-- primitives/beefy/Cargo.toml | 2 +- primitives/beefy/src/commitment.rs | 122 +++++++++++++++++++++-------- primitives/beefy/src/lib.rs | 8 +- primitives/beefy/src/witness.rs | 32 ++++---- 9 files changed, 152 insertions(+), 99 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 08d39c1d2b3d..fbdf0297d453 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -535,6 +535,7 @@ dependencies = [ name = "beefy-primitives" version = "4.0.0-dev" dependencies = [ + "hex", "hex-literal", "parity-scale-codec", "scale-info", diff --git a/client/beefy/src/gossip.rs b/client/beefy/src/gossip.rs index 8a43b5a03947..dc59f664caa9 100644 --- a/client/beefy/src/gossip.rs +++ b/client/beefy/src/gossip.rs @@ -30,7 +30,7 @@ use wasm_timer::Instant; use beefy_primitives::{ crypto::{Public, Signature}, - MmrRootHash, VoteMessage, + VoteMessage, }; use crate::keystore::BeefyKeystore; @@ -142,9 +142,7 @@ where sender: &PeerId, mut data: &[u8], ) -> ValidationResult { - if let Ok(msg) = - VoteMessage::, Public, Signature>::decode(&mut data) - { + if let Ok(msg) = VoteMessage::, Public, Signature>::decode(&mut data) { let msg_hash = twox_64(data); let round = msg.commitment.block_number; @@ -178,9 +176,7 @@ where fn message_expired<'a>(&'a self) -> Box bool + 'a> { let known_votes = self.known_votes.read(); Box::new(move |_topic, mut data| { - let msg = match VoteMessage::, Public, Signature>::decode( - &mut data, - ) { + let msg = match VoteMessage::, Public, Signature>::decode(&mut data) { Ok(vote) => vote, Err(_) => return true, }; @@ -214,9 +210,7 @@ where return do_rebroadcast } - let msg = match VoteMessage::, Public, Signature>::decode( - &mut data, - ) { + let msg = match VoteMessage::, Public, Signature>::decode(&mut data) { Ok(vote) => vote, Err(_) => return true, }; @@ -237,9 +231,11 @@ mod tests { use sc_network_test::Block; use sp_keystore::{SyncCryptoStore, SyncCryptoStorePtr}; - use beefy_primitives::{crypto::Signature, Commitment, MmrRootHash, VoteMessage, KEY_TYPE}; - use crate::keystore::{tests::Keyring, BeefyKeystore}; + use beefy_primitives::{ + crypto::Signature, known_payload_ids, Commitment, MmrRootHash, Payload, VoteMessage, + KEY_TYPE, + }; use super::*; @@ -345,10 +341,7 @@ mod tests { } } - fn sign_commitment( - who: &Keyring, - commitment: &Commitment, - ) -> Signature { + fn sign_commitment(who: &Keyring, commitment: &Commitment) -> Signature { let store: SyncCryptoStorePtr = std::sync::Arc::new(LocalKeystore::in_memory()); SyncCryptoStore::ecdsa_generate_new(&*store, KEY_TYPE, Some(&who.to_seed())).unwrap(); let beefy_keystore: BeefyKeystore = Some(store).into(); @@ -362,11 +355,8 @@ mod tests { let sender = sc_network::PeerId::random(); let mut context = TestContext; - let commitment = Commitment { - payload: MmrRootHash::default(), - block_number: 3_u64, - validator_set_id: 0, - }; + let payload = Payload::new(known_payload_ids::MMR_ROOT_ID, MmrRootHash::default().encode()); + let commitment = Commitment { payload, block_number: 3_u64, validator_set_id: 0 }; let signature = sign_commitment(&Keyring::Alice, &commitment); diff --git a/client/beefy/src/notification.rs b/client/beefy/src/notification.rs index 6099c9681447..f394ae6c840a 100644 --- a/client/beefy/src/notification.rs +++ b/client/beefy/src/notification.rs @@ -24,8 +24,7 @@ use sp_runtime::traits::{Block, NumberFor}; use parking_lot::Mutex; /// Stream of signed commitments returned when subscribing. -pub type SignedCommitment = - beefy_primitives::SignedCommitment, beefy_primitives::MmrRootHash>; +pub type SignedCommitment = beefy_primitives::SignedCommitment>; /// Stream of signed commitments returned when subscribing. type SignedCommitmentStream = TracingUnboundedReceiver>; diff --git a/client/beefy/src/round.rs b/client/beefy/src/round.rs index e9f5ad206243..db41f0f465db 100644 --- a/client/beefy/src/round.rs +++ b/client/beefy/src/round.rs @@ -53,14 +53,14 @@ fn threshold(authorities: usize) -> usize { authorities - faulty } -pub(crate) struct Rounds { - rounds: BTreeMap<(Hash, Number), RoundTracker>, +pub(crate) struct Rounds { + rounds: BTreeMap<(Payload, Number), RoundTracker>, validator_set: ValidatorSet, } -impl Rounds +impl Rounds where - H: Ord + Hash, + P: Ord + Hash, N: Ord + AtLeast32BitUnsigned + MaybeDisplay, { pub(crate) fn new(validator_set: ValidatorSet) -> Self { @@ -70,8 +70,8 @@ where impl Rounds where - H: Ord + Hash, - N: Ord + AtLeast32BitUnsigned + MaybeDisplay, + H: Ord + Hash + Clone, + N: Ord + AtLeast32BitUnsigned + MaybeDisplay + Clone, { pub(crate) fn validator_set_id(&self) -> ValidatorSetId { self.validator_set.id @@ -81,9 +81,9 @@ where self.validator_set.validators.clone() } - pub(crate) fn add_vote(&mut self, round: (H, N), vote: (Public, Signature)) -> bool { + pub(crate) fn add_vote(&mut self, round: &(H, N), vote: (Public, Signature)) -> bool { if self.validator_set.validators.iter().any(|id| vote.0 == *id) { - self.rounds.entry(round).or_default().add_vote(vote) + self.rounds.entry(round.clone()).or_default().add_vote(vote) } else { false } @@ -179,7 +179,7 @@ mod tests { let mut rounds = Rounds::>::new(validators); assert!(rounds.add_vote( - (H256::from_low_u64_le(1), 1), + &(H256::from_low_u64_le(1), 1), (Keyring::Alice.public(), Keyring::Alice.sign(b"I am committed")) )); @@ -187,21 +187,21 @@ mod tests { // invalid vote assert!(!rounds.add_vote( - (H256::from_low_u64_le(1), 1), + &(H256::from_low_u64_le(1), 1), (Keyring::Dave.public(), Keyring::Dave.sign(b"I am committed")) )); assert!(!rounds.is_done(&(H256::from_low_u64_le(1), 1))); assert!(rounds.add_vote( - (H256::from_low_u64_le(1), 1), + &(H256::from_low_u64_le(1), 1), (Keyring::Bob.public(), Keyring::Bob.sign(b"I am committed")) )); assert!(!rounds.is_done(&(H256::from_low_u64_le(1), 1))); assert!(rounds.add_vote( - (H256::from_low_u64_le(1), 1), + &(H256::from_low_u64_le(1), 1), (Keyring::Charlie.public(), Keyring::Charlie.sign(b"I am committed")) )); @@ -225,31 +225,31 @@ mod tests { // round 1 rounds.add_vote( - (H256::from_low_u64_le(1), 1), + &(H256::from_low_u64_le(1), 1), (Keyring::Alice.public(), Keyring::Alice.sign(b"I am committed")), ); rounds.add_vote( - (H256::from_low_u64_le(1), 1), + &(H256::from_low_u64_le(1), 1), (Keyring::Bob.public(), Keyring::Bob.sign(b"I am committed")), ); // round 2 rounds.add_vote( - (H256::from_low_u64_le(2), 2), + &(H256::from_low_u64_le(2), 2), (Keyring::Alice.public(), Keyring::Alice.sign(b"I am again committed")), ); rounds.add_vote( - (H256::from_low_u64_le(2), 2), + &(H256::from_low_u64_le(2), 2), (Keyring::Bob.public(), Keyring::Bob.sign(b"I am again committed")), ); // round 3 rounds.add_vote( - (H256::from_low_u64_le(3), 3), + &(H256::from_low_u64_le(3), 3), (Keyring::Alice.public(), Keyring::Alice.sign(b"I am still committed")), ); rounds.add_vote( - (H256::from_low_u64_le(3), 3), + &(H256::from_low_u64_le(3), 3), (Keyring::Bob.public(), Keyring::Bob.sign(b"I am still committed")), ); diff --git a/client/beefy/src/worker.rs b/client/beefy/src/worker.rs index 3f5268693033..fa48e64c12b4 100644 --- a/client/beefy/src/worker.rs +++ b/client/beefy/src/worker.rs @@ -36,8 +36,8 @@ use sp_runtime::{ use beefy_primitives::{ crypto::{AuthorityId, Public, Signature}, - BeefyApi, Commitment, ConsensusLog, MmrRootHash, SignedCommitment, ValidatorSet, - VersionedCommitment, VoteMessage, BEEFY_ENGINE_ID, GENESIS_AUTHORITY_SET_ID, + known_payload_ids, BeefyApi, Commitment, ConsensusLog, MmrRootHash, Payload, SignedCommitment, + ValidatorSet, VersionedCommitment, VoteMessage, BEEFY_ENGINE_ID, GENESIS_AUTHORITY_SET_ID, }; use crate::{ @@ -79,7 +79,7 @@ where /// Min delta in block numbers between two blocks, BEEFY should vote on min_block_delta: u32, metrics: Option, - rounds: round::Rounds>, + rounds: round::Rounds>, finality_notifications: FinalityNotifications, /// Best block we received a GRANDPA notification for best_grandpa_block: NumberFor, @@ -262,8 +262,9 @@ where return }; + let payload = Payload::new(known_payload_ids::MMR_ROOT_ID, mmr_root.encode()); let commitment = Commitment { - payload: mmr_root, + payload, block_number: notification.header.number(), validator_set_id: self.rounds.validator_set_id(), }; @@ -301,10 +302,10 @@ where } } - fn handle_vote(&mut self, round: (MmrRootHash, NumberFor), vote: (Public, Signature)) { + fn handle_vote(&mut self, round: (Payload, NumberFor), vote: (Public, Signature)) { self.gossip_validator.note_round(round.1); - let vote_added = self.rounds.add_vote(round, vote); + let vote_added = self.rounds.add_vote(&round, vote); if vote_added && self.rounds.is_done(&round) { if let Some(signatures) = self.rounds.drop(&round) { @@ -352,7 +353,7 @@ where |notification| async move { debug!(target: "beefy", "🥩 Got vote message: {:?}", notification); - VoteMessage::, Public, Signature>::decode( + VoteMessage::, Public, Signature>::decode( &mut ¬ification.message[..], ) .ok() diff --git a/primitives/beefy/Cargo.toml b/primitives/beefy/Cargo.toml index 23e98012027c..e38af745cd71 100644 --- a/primitives/beefy/Cargo.toml +++ b/primitives/beefy/Cargo.toml @@ -18,8 +18,8 @@ sp-runtime = { version = "4.0.0-dev", path = "../runtime", default-features = fa sp-std = { version = "4.0.0-dev", path = "../std", default-features = false } [dev-dependencies] +hex = "0.4.3" hex-literal = "0.3" - sp-keystore = { version = "0.10.0-dev", path = "../keystore" } [features] diff --git a/primitives/beefy/src/commitment.rs b/primitives/beefy/src/commitment.rs index d9e4de6e19bb..667c03cc2284 100644 --- a/primitives/beefy/src/commitment.rs +++ b/primitives/beefy/src/commitment.rs @@ -15,10 +15,65 @@ // See the License for the specific language governing permissions and // limitations under the License. +use codec::{Decode, Encode}; use sp_std::{cmp, prelude::*}; use crate::{crypto::Signature, ValidatorSetId}; +/// Id of different payloads in the [`Commitment`] data +pub type BeefyPayloadId = [u8; 2]; + +/// Registry of all known [`BeefyPayloadId`]. +pub mod known_payload_ids { + use crate::BeefyPayloadId; + + /// A [`Payload`] identifier for Merkle Mountain Range root hash. + /// + /// Encoded value should contain a [`beefy_primitives::MmrRootHash`] type (i.e. 32-bytes hash). + pub const MMR_ROOT_ID: BeefyPayloadId = *b"mh"; +} + +/// A BEEFY payload type allowing for future extensibility of adding additional kinds of payloads. +/// +/// The idea is to store a vector of SCALE-encoded values with an extra identifier. +/// Identifiers MUST be sorted by the [`BeefyPayloadId`] to allow efficient lookup of expected +/// value. Duplicated identifiers are disallowed. It's okay for different implementations to only +/// support a subset of possible values. +#[derive(Decode, Encode, Debug, PartialEq, Eq, Clone, Ord, PartialOrd, Hash)] +pub struct Payload(Vec<(BeefyPayloadId, Vec)>); + +impl Payload { + /// Construct a new payload given an initial vallue + pub fn new(id: BeefyPayloadId, value: Vec) -> Self { + Self(vec![(id, value)]) + } + + /// Returns a raw payload under given `id`. + /// + /// If the [`BeefyPayloadId`] is not found in the payload `None` is returned. + pub fn get_raw(&self, id: &BeefyPayloadId) -> Option<&Vec> { + let index = self.0.binary_search_by(|probe| probe.0.cmp(id)).ok()?; + Some(&self.0[index].1) + } + + /// Returns a decoded payload value under given `id`. + /// + /// In case the value is not there or it cannot be decoded does not match `None` is returned. + pub fn get_decoded(&self, id: &BeefyPayloadId) -> Option { + self.get_raw(id).and_then(|raw| T::decode(&mut &raw[..]).ok()) + } + + /// Push a `Vec` with a given id into the payload vec. + /// This method will internally sort the payload vec after every push. + /// + /// Returns self to allow for daisy chaining. + pub fn push_raw(mut self, id: BeefyPayloadId, value: Vec) -> Self { + self.0.push((id, value)); + self.0.sort_by_key(|(id, _)| *id); + self + } +} + /// A commitment signed by GRANDPA validators as part of BEEFY protocol. /// /// The commitment contains a [payload](Commitment::payload) extracted from the finalized block at @@ -26,16 +81,17 @@ use crate::{crypto::Signature, ValidatorSetId}; /// GRANDPA validators collect signatures on commitments and a stream of such signed commitments /// (see [SignedCommitment]) forms the BEEFY protocol. #[derive(Clone, Debug, PartialEq, Eq, codec::Encode, codec::Decode)] -pub struct Commitment { - /// The payload being signed. +pub struct Commitment { + /// A collection of payloads to be signed, see [`Payload`] for details. /// - /// This should be some form of cumulative representation of the chain (think MMR root hash). - /// The payload should also contain some details that allow the light client to verify next - /// validator set. The protocol does not enforce any particular format of this data, - /// nor how often it should be present in commitments, however the light client has to be - /// provided with full validator set whenever it performs the transition (i.e. importing first - /// block with [validator_set_id](Commitment::validator_set_id) incremented). - pub payload: TPayload, + /// One of the payloads should be some form of cumulative representation of the chain (think + /// MMR root hash). Additionally one of the payloads should also contain some details that + /// allow the light client to verify next validator set. The protocol does not enforce any + /// particular format of this data, nor how often it should be present in commitments, however + /// the light client has to be provided with full validator set whenever it performs the + /// transition (i.e. importing first block with + /// [validator_set_id](Commitment::validator_set_id) incremented). + pub payload: Payload, /// Finalized block number this commitment is for. /// @@ -57,20 +113,18 @@ pub struct Commitment { pub validator_set_id: ValidatorSetId, } -impl cmp::PartialOrd for Commitment +impl cmp::PartialOrd for Commitment where TBlockNumber: cmp::Ord, - TPayload: cmp::Eq, { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } -impl cmp::Ord for Commitment +impl cmp::Ord for Commitment where TBlockNumber: cmp::Ord, - TPayload: cmp::Eq, { fn cmp(&self, other: &Self) -> cmp::Ordering { self.validator_set_id @@ -81,9 +135,9 @@ where /// A commitment with matching GRANDPA validators' signatures. #[derive(Clone, Debug, PartialEq, Eq, codec::Encode, codec::Decode)] -pub struct SignedCommitment { +pub struct SignedCommitment { /// The commitment signatures are collected for. - pub commitment: Commitment, + pub commitment: Commitment, /// GRANDPA validators' signatures for the commitment. /// /// The length of this `Vec` must match number of validators in the current set (see @@ -91,7 +145,7 @@ pub struct SignedCommitment { pub signatures: Vec>, } -impl SignedCommitment { +impl SignedCommitment { /// Return the number of collected signatures. pub fn no_of_signatures(&self) -> usize { self.signatures.iter().filter(|x| x.is_some()).count() @@ -102,10 +156,10 @@ impl SignedCommitment { /// to the block justifications for the block for which the signed commitment /// has been generated. #[derive(Clone, Debug, PartialEq, codec::Encode, codec::Decode)] -pub enum VersionedCommitment { +pub enum VersionedCommitment { #[codec(index = 1)] /// Current active version - V1(SignedCommitment), + V1(SignedCommitment), } #[cfg(test)] @@ -119,9 +173,9 @@ mod tests { use crate::{crypto, KEY_TYPE}; - type TestCommitment = Commitment; - type TestSignedCommitment = SignedCommitment; - type TestVersionedCommitment = VersionedCommitment; + type TestCommitment = Commitment; + type TestSignedCommitment = SignedCommitment; + type TestVersionedCommitment = VersionedCommitment; // The mock signatures are equivalent to the ones produced by the BEEFY keystore fn mock_signatures() -> (crypto::Signature, crypto::Signature) { @@ -148,8 +202,9 @@ mod tests { #[test] fn commitment_encode_decode() { // given + let payload = Payload::new(known_payload_ids::MMR_ROOT_ID, "Hello World!".encode()); let commitment: TestCommitment = - Commitment { payload: "Hello World!".into(), block_number: 5, validator_set_id: 0 }; + Commitment { payload, block_number: 5, validator_set_id: 0 }; // when let encoded = codec::Encode::encode(&commitment); @@ -160,7 +215,7 @@ mod tests { assert_eq!( encoded, hex_literal::hex!( - "3048656c6c6f20576f726c6421050000000000000000000000000000000000000000000000" + "046d68343048656c6c6f20576f726c6421050000000000000000000000000000000000000000000000" ) ); } @@ -168,8 +223,9 @@ mod tests { #[test] fn signed_commitment_encode_decode() { // given + let payload = Payload::new(known_payload_ids::MMR_ROOT_ID, "Hello World!".encode()); let commitment: TestCommitment = - Commitment { payload: "Hello World!".into(), block_number: 5, validator_set_id: 0 }; + Commitment { payload, block_number: 5, validator_set_id: 0 }; let sigs = mock_signatures(); @@ -187,10 +243,11 @@ mod tests { assert_eq!( encoded, hex_literal::hex!( - "3048656c6c6f20576f726c64210500000000000000000000000000000000000000000000001000 - 0001558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d - 10dd3cd68ce3dc0c33c86e99bcb7816f9ba01012d6e1f8105c337a86cdd9aaacdc496577f3db8c55ef9e6fd48f2c5c05a - 2274707491635d8ba3df64f324575b7b2a34487bca2324b6a0046395a71681be3d0c2a00" + "046d68343048656c6c6f20576f726c6421050000000000000000000000000000000000000000000000 + 10000001558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321 + f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01012d6e1f8105c337a86cdd9aaa + cdc496577f3db8c55ef9e6fd48f2c5c05a2274707491635d8ba3df64f324575b7b2a34487bca2324b6a + 0046395a71681be3d0c2a00" ) ); } @@ -198,8 +255,9 @@ mod tests { #[test] fn signed_commitment_count_signatures() { // given + let payload = Payload::new(known_payload_ids::MMR_ROOT_ID, "Hello World!".encode()); let commitment: TestCommitment = - Commitment { payload: "Hello World!".into(), block_number: 5, validator_set_id: 0 }; + Commitment { payload, block_number: 5, validator_set_id: 0 }; let sigs = mock_signatures(); @@ -222,7 +280,8 @@ mod tests { block_number: u128, validator_set_id: crate::ValidatorSetId, ) -> TestCommitment { - Commitment { payload: "Hello World!".into(), block_number, validator_set_id } + let payload = Payload::new(known_payload_ids::MMR_ROOT_ID, "Hello World!".encode()); + Commitment { payload, block_number, validator_set_id } } // given @@ -241,8 +300,9 @@ mod tests { #[test] fn versioned_commitment_encode_decode() { + let payload = Payload::new(known_payload_ids::MMR_ROOT_ID, "Hello World!".encode()); let commitment: TestCommitment = - Commitment { payload: "Hello World!".into(), block_number: 5, validator_set_id: 0 }; + Commitment { payload, block_number: 5, validator_set_id: 0 }; let sigs = mock_signatures(); diff --git a/primitives/beefy/src/lib.rs b/primitives/beefy/src/lib.rs index 790b915ab98d..cb3cf601a76b 100644 --- a/primitives/beefy/src/lib.rs +++ b/primitives/beefy/src/lib.rs @@ -35,7 +35,9 @@ mod commitment; pub mod mmr; pub mod witness; -pub use commitment::{Commitment, SignedCommitment, VersionedCommitment}; +pub use commitment::{ + known_payload_ids, BeefyPayloadId, Commitment, Payload, SignedCommitment, VersionedCommitment, +}; use codec::{Codec, Decode, Encode}; use scale_info::TypeInfo; @@ -118,9 +120,9 @@ pub enum ConsensusLog { /// A vote message is a direct vote created by a BEEFY node on every voting round /// and is gossiped to its peers. #[derive(Debug, Decode, Encode, TypeInfo)] -pub struct VoteMessage { +pub struct VoteMessage { /// Commit to information extracted from a finalized block - pub commitment: Commitment, + pub commitment: Commitment, /// Node authority id pub id: Id, /// Node signature diff --git a/primitives/beefy/src/witness.rs b/primitives/beefy/src/witness.rs index c28a464e72df..3ead08bdd7cb 100644 --- a/primitives/beefy/src/witness.rs +++ b/primitives/beefy/src/witness.rs @@ -40,9 +40,9 @@ use crate::{ /// Ethereum Mainnet), in a commit-reveal like scheme, where first we submit only the signed /// commitment witness and later on, the client picks only some signatures to verify at random. #[derive(Debug, PartialEq, Eq, codec::Encode, codec::Decode)] -pub struct SignedCommitmentWitness { +pub struct SignedCommitmentWitness { /// The full content of the commitment. - pub commitment: Commitment, + pub commitment: Commitment, /// The bit vector of validators who signed the commitment. pub signed_by: Vec, // TODO [ToDr] Consider replacing with bitvec crate @@ -51,9 +51,7 @@ pub struct SignedCommitmentWitness { pub signatures_merkle_root: TMerkleRoot, } -impl - SignedCommitmentWitness -{ +impl SignedCommitmentWitness { /// Convert [SignedCommitment] into [SignedCommitmentWitness]. /// /// This takes a [SignedCommitment], which contains full signatures @@ -63,7 +61,7 @@ impl /// /// Returns the full list of signatures along with the witness. pub fn from_signed( - signed: SignedCommitment, + signed: SignedCommitment, merkelize: TMerkelize, ) -> (Self, Vec>) where @@ -86,12 +84,11 @@ mod tests { use super::*; use codec::Decode; - use crate::{crypto, KEY_TYPE}; + use crate::{crypto, known_payload_ids, Payload, KEY_TYPE}; - type TestCommitment = Commitment; - type TestSignedCommitment = SignedCommitment; - type TestSignedCommitmentWitness = - SignedCommitmentWitness>>; + type TestCommitment = Commitment; + type TestSignedCommitment = SignedCommitment; + type TestSignedCommitmentWitness = SignedCommitmentWitness>>; // The mock signatures are equivalent to the ones produced by the BEEFY keystore fn mock_signatures() -> (crypto::Signature, crypto::Signature) { @@ -116,8 +113,10 @@ mod tests { } fn signed_commitment() -> TestSignedCommitment { + let payload = + Payload::new(known_payload_ids::MMR_ROOT_ID, "Hello World!".as_bytes().to_vec()); let commitment: TestCommitment = - Commitment { payload: "Hello World!".into(), block_number: 5, validator_set_id: 0 }; + Commitment { payload, block_number: 5, validator_set_id: 0 }; let sigs = mock_signatures(); @@ -152,10 +151,11 @@ mod tests { assert_eq!( encoded, hex_literal::hex!( - "3048656c6c6f20576f726c64210500000000000000000000000000000000000000000000001000 - 00010110000001558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e9 - 9a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01012d6e1f8105c337a86cdd9aaacdc496577f3db8c55ef9e6fd - 48f2c5c05a2274707491635d8ba3df64f324575b7b2a34487bca2324b6a0046395a71681be3d0c2a00" + "046d683048656c6c6f20576f726c642105000000000000000000000000000000000000000000000010 + 0000010110000001558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c + 746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01012d6e1f8105c337a86 + cdd9aaacdc496577f3db8c55ef9e6fd48f2c5c05a2274707491635d8ba3df64f324575b7b2a34487bc + a2324b6a0046395a71681be3d0c2a00" ) ); } From 089aa2509f928b161b0f970d1ff670635f6a26fe Mon Sep 17 00:00:00 2001 From: Alex Pozhylenkov Date: Wed, 1 Dec 2021 23:31:57 +0200 Subject: [PATCH 247/695] Move EnsureOneOf into the dispatch.rs, make an interface more general (#10379) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * move EnsureOneOf into the dispatch.rs, make an interface more general * Update frame/support/src/traits/dispatch.rs Co-authored-by: Bastian Köcher Co-authored-by: Bastian Köcher Co-authored-by: Shawn Tabrizi --- bin/node/runtime/src/lib.rs | 9 +---- frame/identity/src/tests.rs | 10 +++-- frame/scheduler/src/lib.rs | 6 +-- frame/support/src/traits.rs | 2 +- frame/support/src/traits/dispatch.rs | 60 +++++++++++++++++++++++++++- frame/system/src/lib.rs | 25 +----------- frame/system/src/tests.rs | 11 ----- 7 files changed, 72 insertions(+), 51 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 3f553221e67a..2cf6548b7921 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -26,7 +26,7 @@ use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::{ construct_runtime, parameter_types, traits::{ - ConstU32, Currency, EqualPrivilegeOnly, Everything, Imbalance, InstanceFilter, + ConstU32, Currency, EnsureOneOf, EqualPrivilegeOnly, Everything, Imbalance, InstanceFilter, KeyOwnerProofSystem, LockIdentifier, Nothing, OnUnbalanced, U128CurrencyToVote, }, weights::{ @@ -37,7 +37,7 @@ use frame_support::{ }; use frame_system::{ limits::{BlockLength, BlockWeights}, - EnsureOneOf, EnsureRoot, + EnsureRoot, }; pub use node_primitives::{AccountId, Signature}; use node_primitives::{AccountIndex, Balance, BlockNumber, Hash, Index, Moment}; @@ -535,7 +535,6 @@ impl pallet_staking::Config for Runtime { type SlashDeferDuration = SlashDeferDuration; /// A super-majority of the council can cancel the slash. type SlashCancelOrigin = EnsureOneOf< - AccountId, EnsureRoot, pallet_collective::EnsureProportionAtLeast<_3, _4, AccountId, CouncilCollective>, >; @@ -726,7 +725,6 @@ impl pallet_democracy::Config for Runtime { // To cancel a proposal before it has been passed, the technical committee must be unanimous or // Root must agree. type CancelProposalOrigin = EnsureOneOf< - AccountId, EnsureRoot, pallet_collective::EnsureProportionAtLeast<_1, _1, AccountId, TechnicalCollective>, >; @@ -817,7 +815,6 @@ impl pallet_collective::Config for Runtime { } type EnsureRootOrHalfCouncil = EnsureOneOf< - AccountId, EnsureRoot, pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>, >; @@ -857,12 +854,10 @@ impl pallet_treasury::Config for Runtime { type PalletId = TreasuryPalletId; type Currency = Balances; type ApproveOrigin = EnsureOneOf< - AccountId, EnsureRoot, pallet_collective::EnsureProportionAtLeast<_3, _5, AccountId, CouncilCollective>, >; type RejectOrigin = EnsureOneOf< - AccountId, EnsureRoot, pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>, >; diff --git a/frame/identity/src/tests.rs b/frame/identity/src/tests.rs index c842b0e2f64b..31b93e70fd3d 100644 --- a/frame/identity/src/tests.rs +++ b/frame/identity/src/tests.rs @@ -21,8 +21,10 @@ use super::*; use crate as pallet_identity; use codec::{Decode, Encode}; -use frame_support::{assert_noop, assert_ok, ord_parameter_types, parameter_types, BoundedVec}; -use frame_system::{EnsureOneOf, EnsureRoot, EnsureSignedBy}; +use frame_support::{ + assert_noop, assert_ok, ord_parameter_types, parameter_types, traits::EnsureOneOf, BoundedVec, +}; +use frame_system::{EnsureRoot, EnsureSignedBy}; use sp_core::H256; use sp_runtime::{ testing::Header, @@ -100,8 +102,8 @@ ord_parameter_types! { pub const One: u64 = 1; pub const Two: u64 = 2; } -type EnsureOneOrRoot = EnsureOneOf, EnsureSignedBy>; -type EnsureTwoOrRoot = EnsureOneOf, EnsureSignedBy>; +type EnsureOneOrRoot = EnsureOneOf, EnsureSignedBy>; +type EnsureTwoOrRoot = EnsureOneOf, EnsureSignedBy>; impl pallet_identity::Config for Test { type Event = Event; type Currency = Balances; diff --git a/frame/scheduler/src/lib.rs b/frame/scheduler/src/lib.rs index b3e64fe57f64..260ef90b0537 100644 --- a/frame/scheduler/src/lib.rs +++ b/frame/scheduler/src/lib.rs @@ -805,11 +805,11 @@ mod tests { use crate as scheduler; use frame_support::{ assert_err, assert_noop, assert_ok, ord_parameter_types, parameter_types, - traits::{Contains, EqualPrivilegeOnly, OnFinalize, OnInitialize}, + traits::{Contains, EnsureOneOf, EqualPrivilegeOnly, OnFinalize, OnInitialize}, weights::constants::RocksDbWeight, Hashable, }; - use frame_system::{EnsureOneOf, EnsureRoot, EnsureSignedBy}; + use frame_system::{EnsureRoot, EnsureSignedBy}; use sp_core::H256; use sp_runtime::{ testing::Header, @@ -950,7 +950,7 @@ mod tests { type PalletsOrigin = OriginCaller; type Call = Call; type MaximumWeight = MaximumSchedulerWeight; - type ScheduleOrigin = EnsureOneOf, EnsureSignedBy>; + type ScheduleOrigin = EnsureOneOf, EnsureSignedBy>; type MaxScheduledPerBlock = MaxScheduledPerBlock; type WeightInfo = (); type OriginPrivilegeCmp = EqualPrivilegeOnly; diff --git a/frame/support/src/traits.rs b/frame/support/src/traits.rs index bb990e25646d..9b5453c0a01a 100644 --- a/frame/support/src/traits.rs +++ b/frame/support/src/traits.rs @@ -84,7 +84,7 @@ pub use storage::{ }; mod dispatch; -pub use dispatch::{EnsureOrigin, OriginTrait, UnfilteredDispatchable}; +pub use dispatch::{EnsureOneOf, EnsureOrigin, OriginTrait, UnfilteredDispatchable}; mod voting; pub use voting::{CurrencyToVote, SaturatingCurrencyToVote, U128CurrencyToVote}; diff --git a/frame/support/src/traits/dispatch.rs b/frame/support/src/traits/dispatch.rs index 92b832ba3296..d7605593cd60 100644 --- a/frame/support/src/traits/dispatch.rs +++ b/frame/support/src/traits/dispatch.rs @@ -18,7 +18,7 @@ //! Traits for dealing with dispatching calls and the origin from which they are dispatched. use crate::dispatch::DispatchResultWithPostInfo; -use sp_runtime::traits::BadOrigin; +use sp_runtime::{traits::BadOrigin, Either}; /// Some sort of check on the origin is performed by this object. pub trait EnsureOrigin { @@ -94,3 +94,61 @@ pub trait OriginTrait: Sized { /// Create with system signed origin and `frame_system::Config::BaseCallFilter`. fn signed(by: Self::AccountId) -> Self; } + +/// The "OR gate" implementation of `EnsureOrigin`. +/// +/// Origin check will pass if `L` or `R` origin check passes. `L` is tested first. +pub struct EnsureOneOf(sp_std::marker::PhantomData<(L, R)>); + +impl, R: EnsureOrigin> + EnsureOrigin for EnsureOneOf +{ + type Success = Either; + fn try_origin(o: OuterOrigin) -> Result { + L::try_origin(o) + .map_or_else(|o| R::try_origin(o).map(|o| Either::Right(o)), |o| Ok(Either::Left(o))) + } + + #[cfg(feature = "runtime-benchmarks")] + fn successful_origin() -> OuterOrigin { + L::successful_origin() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + struct EnsureSuccess; + struct EnsureFail; + + impl EnsureOrigin<()> for EnsureSuccess { + type Success = (); + fn try_origin(_: ()) -> Result { + Ok(()) + } + #[cfg(feature = "runtime-benchmarks")] + fn successful_origin() -> () { + () + } + } + + impl EnsureOrigin<()> for EnsureFail { + type Success = (); + fn try_origin(_: ()) -> Result { + Err(()) + } + #[cfg(feature = "runtime-benchmarks")] + fn successful_origin() -> () { + () + } + } + + #[test] + fn ensure_one_of_test() { + assert!(>::try_origin(()).is_ok()); + assert!(>::try_origin(()).is_ok()); + assert!(>::try_origin(()).is_ok()); + assert!(>::try_origin(()).is_err()); + } +} diff --git a/frame/system/src/lib.rs b/frame/system/src/lib.rs index 31b702c135de..aac104fa8f76 100644 --- a/frame/system/src/lib.rs +++ b/frame/system/src/lib.rs @@ -73,7 +73,7 @@ use sp_runtime::{ CheckEqual, Dispatchable, Hash, Lookup, LookupError, MaybeDisplay, MaybeMallocSizeOf, MaybeSerializeDeserialize, Member, One, Saturating, SimpleBitOps, StaticLookup, Zero, }, - DispatchError, Either, Perbill, RuntimeDebug, + DispatchError, Perbill, RuntimeDebug, }; #[cfg(any(feature = "std", test))] use sp_std::map; @@ -902,29 +902,6 @@ impl EnsureOrigin for EnsureNever { } } -/// The "OR gate" implementation of `EnsureOrigin`. -/// -/// Origin check will pass if `L` or `R` origin check passes. `L` is tested first. -pub struct EnsureOneOf(sp_std::marker::PhantomData<(AccountId, L, R)>); -impl< - AccountId, - O: Into, O>> + From>, - L: EnsureOrigin, - R: EnsureOrigin, - > EnsureOrigin for EnsureOneOf -{ - type Success = Either; - fn try_origin(o: O) -> Result { - L::try_origin(o) - .map_or_else(|o| R::try_origin(o).map(|o| Either::Right(o)), |o| Ok(Either::Left(o))) - } - - #[cfg(feature = "runtime-benchmarks")] - fn successful_origin() -> O { - L::successful_origin() - } -} - /// Ensure that the origin `o` represents a signed extrinsic (i.e. transaction). /// Returns `Ok` with the account that signed the extrinsic or an `Err` otherwise. pub fn ensure_signed(o: OuterOrigin) -> Result diff --git a/frame/system/src/tests.rs b/frame/system/src/tests.rs index f9c167ec4be3..d8f9fd1af2bc 100644 --- a/frame/system/src/tests.rs +++ b/frame/system/src/tests.rs @@ -461,17 +461,6 @@ fn events_not_emitted_during_genesis() { }); } -#[test] -fn ensure_one_of_works() { - fn ensure_root_or_signed(o: RawOrigin) -> Result, Origin> { - EnsureOneOf::, EnsureSigned>::try_origin(o.into()) - } - - assert_eq!(ensure_root_or_signed(RawOrigin::Root).unwrap(), Either::Left(())); - assert_eq!(ensure_root_or_signed(RawOrigin::Signed(0)).unwrap(), Either::Right(0)); - assert!(ensure_root_or_signed(RawOrigin::None).is_err()); -} - #[test] fn extrinsics_root_is_calculated_correctly() { new_test_ext().execute_with(|| { From 3904d77ad2499ab36b242e52fbe23d5cd8773ad9 Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Thu, 2 Dec 2021 09:11:10 +0100 Subject: [PATCH 248/695] Minimum commission for validators (#10347) * Minimum commission for validators * rename * Fix benchmakrs * cargo run --quiet --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_staking --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/staking/src/weights.rs --template=./.maintain/frame-weight-template.hbs * Update frame/staking/src/pallet/mod.rs * cargo run --quiet --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_staking --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/staking/src/weights.rs --template=./.maintain/frame-weight-template.hbs Co-authored-by: Parity Bot Co-authored-by: Shawn Tabrizi --- frame/staking/src/benchmarking.rs | 11 +- frame/staking/src/pallet/mod.rs | 38 +++- frame/staking/src/tests.rs | 80 +++++++- frame/staking/src/weights.rs | 233 ++++++++++++------------ primitives/arithmetic/src/per_things.rs | 10 + 5 files changed, 236 insertions(+), 136 deletions(-) diff --git a/frame/staking/src/benchmarking.rs b/frame/staking/src/benchmarking.rs index 5feb1692d955..69a73c51fdc7 100644 --- a/frame/staking/src/benchmarking.rs +++ b/frame/staking/src/benchmarking.rs @@ -842,7 +842,7 @@ benchmarks! { assert_eq!(targets.len() as u32, v); } - set_staking_limits { + set_staking_configs { // This function always does the same thing... just write to 4 storage items. }: _( RawOrigin::Root, @@ -850,13 +850,15 @@ benchmarks! { BalanceOf::::max_value(), Some(u32::MAX), Some(u32::MAX), - Some(Percent::max_value()) + Some(Percent::max_value()), + Perbill::max_value() ) verify { assert_eq!(MinNominatorBond::::get(), BalanceOf::::max_value()); assert_eq!(MinValidatorBond::::get(), BalanceOf::::max_value()); assert_eq!(MaxNominatorsCount::::get(), Some(u32::MAX)); assert_eq!(MaxValidatorsCount::::get(), Some(u32::MAX)); assert_eq!(ChillThreshold::::get(), Some(Percent::from_percent(100))); + assert_eq!(MinCommission::::get(), Perbill::from_percent(100)); } chill_other { @@ -872,13 +874,14 @@ benchmarks! { let stash = scenario.origin_stash1.clone(); assert!(T::SortedListProvider::contains(&stash)); - Staking::::set_staking_limits( + Staking::::set_staking_configs( RawOrigin::Root.into(), BalanceOf::::max_value(), BalanceOf::::max_value(), Some(0), Some(0), - Some(Percent::from_percent(0)) + Some(Percent::from_percent(0)), + Zero::zero(), )?; let caller = whitelisted_caller(); diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index f8f9c8c794dc..f7e96ce0cf76 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -215,6 +215,12 @@ pub mod pallet { #[pallet::storage] pub type MinValidatorBond = StorageValue<_, BalanceOf, ValueQuery>; + /// The minimum amount of commission that validators can set. + /// + /// If set to `0`, no limit exists. + #[pallet::storage] + pub type MinCommission = StorageValue<_, Perbill, ValueQuery>; + /// Map from all (unlocked) "controller" accounts to the info regarding the staking. #[pallet::storage] #[pallet::getter(fn ledger)] @@ -486,6 +492,8 @@ pub mod pallet { Vec<(T::AccountId, T::AccountId, BalanceOf, crate::StakerStatus)>, pub min_nominator_bond: BalanceOf, pub min_validator_bond: BalanceOf, + pub max_validator_count: Option, + pub max_nominator_count: Option, } #[cfg(feature = "std")] @@ -502,6 +510,8 @@ pub mod pallet { stakers: Default::default(), min_nominator_bond: Default::default(), min_validator_bond: Default::default(), + max_validator_count: None, + max_nominator_count: None, } } } @@ -519,6 +529,12 @@ pub mod pallet { StorageVersion::::put(Releases::V7_0_0); MinNominatorBond::::put(self.min_nominator_bond); MinValidatorBond::::put(self.min_validator_bond); + if let Some(x) = self.max_validator_count { + MaxValidatorsCount::::put(x); + } + if let Some(x) = self.max_nominator_count { + MaxNominatorsCount::::put(x); + } for &(ref stash, ref controller, balance, ref status) in &self.stakers { log!( @@ -650,6 +666,8 @@ pub mod pallet { /// There are too many validators in the system. Governance needs to adjust the staking /// settings to keep things safe for the runtime. TooManyValidators, + /// Commission is too low. Must be at least `MinCommission`. + CommissionTooLow, } #[pallet::hooks] @@ -955,9 +973,13 @@ pub mod pallet { let controller = ensure_signed(origin)?; let ledger = Self::ledger(&controller).ok_or(Error::::NotController)?; + ensure!(ledger.active >= MinValidatorBond::::get(), Error::::InsufficientBond); let stash = &ledger.stash; + // ensure their commission is correct. + ensure!(prefs.commission >= MinCommission::::get(), Error::::CommissionTooLow); + // Only check limits if they are not already a validator. if !Validators::::contains_key(stash) { // If this error is reached, we need to adjust the `MinValidatorBond` and start @@ -1508,7 +1530,7 @@ pub mod pallet { Ok(()) } - /// Update the various staking limits this pallet. + /// Update the various staking configurations . /// /// * `min_nominator_bond`: The minimum active bond needed to be a nominator. /// * `min_validator_bond`: The minimum active bond needed to be a validator. @@ -1516,26 +1538,32 @@ pub mod pallet { /// set to `None`, no limit is enforced. /// * `max_validator_count`: The max number of users who can be a validator at once. When /// set to `None`, no limit is enforced. + /// * `chill_threshold`: The ratio of `max_nominator_count` or `max_validator_count` which + /// should be filled in order for the `chill_other` transaction to work. + /// * `min_commission`: The minimum amount of commission that each validators must maintain. + /// This is checked only upon calling `validate`. Existing validators are not affected. /// /// Origin must be Root to call this function. /// /// NOTE: Existing nominators and validators will not be affected by this update. /// to kick people under the new limits, `chill_other` should be called. - #[pallet::weight(T::WeightInfo::set_staking_limits())] - pub fn set_staking_limits( + #[pallet::weight(T::WeightInfo::set_staking_configs())] + pub fn set_staking_configs( origin: OriginFor, min_nominator_bond: BalanceOf, min_validator_bond: BalanceOf, max_nominator_count: Option, max_validator_count: Option, - threshold: Option, + chill_threshold: Option, + min_commission: Perbill, ) -> DispatchResult { ensure_root(origin)?; MinNominatorBond::::set(min_nominator_bond); MinValidatorBond::::set(min_validator_bond); MaxNominatorsCount::::set(max_nominator_count); MaxValidatorsCount::::set(max_validator_count); - ChillThreshold::::set(threshold); + ChillThreshold::::set(chill_threshold); + MinCommission::::set(min_commission); Ok(()) } diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index f8f37bed0066..4604351b5230 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -4350,7 +4350,15 @@ fn chill_other_works() { ); // Change the minimum bond... but no limits. - assert_ok!(Staking::set_staking_limits(Origin::root(), 1_500, 2_000, None, None, None)); + assert_ok!(Staking::set_staking_configs( + Origin::root(), + 1_500, + 2_000, + None, + None, + None, + Zero::zero() + )); // Still can't chill these users assert_noop!( @@ -4363,13 +4371,14 @@ fn chill_other_works() { ); // Add limits, but no threshold - assert_ok!(Staking::set_staking_limits( + assert_ok!(Staking::set_staking_configs( Origin::root(), 1_500, 2_000, Some(10), Some(10), - None + None, + Zero::zero() )); // Still can't chill these users @@ -4383,13 +4392,14 @@ fn chill_other_works() { ); // Add threshold, but no limits - assert_ok!(Staking::set_staking_limits( + assert_ok!(Staking::set_staking_configs( Origin::root(), 1_500, 2_000, None, None, - Some(Percent::from_percent(0)) + Some(Percent::from_percent(0)), + Zero::zero() )); // Still can't chill these users @@ -4403,13 +4413,14 @@ fn chill_other_works() { ); // Add threshold and limits - assert_ok!(Staking::set_staking_limits( + assert_ok!(Staking::set_staking_configs( Origin::root(), 1_500, 2_000, Some(10), Some(10), - Some(Percent::from_percent(75)) + Some(Percent::from_percent(75)), + Zero::zero() )); // 16 people total because tests start with 2 active one @@ -4447,13 +4458,14 @@ fn capped_stakers_works() { // Change the maximums let max = 10; - assert_ok!(Staking::set_staking_limits( + assert_ok!(Staking::set_staking_configs( Origin::root(), 10, 10, Some(max), Some(max), - Some(Percent::from_percent(0)) + Some(Percent::from_percent(0)), + Zero::zero(), )); // can create `max - validator_count` validators @@ -4516,12 +4528,60 @@ fn capped_stakers_works() { )); // No problem when we set to `None` again - assert_ok!(Staking::set_staking_limits(Origin::root(), 10, 10, None, None, None)); + assert_ok!(Staking::set_staking_configs( + Origin::root(), + 10, + 10, + None, + None, + None, + Zero::zero(), + )); assert_ok!(Staking::nominate(Origin::signed(last_nominator), vec![1])); assert_ok!(Staking::validate(Origin::signed(last_validator), ValidatorPrefs::default())); }) } +#[test] +fn min_commission_works() { + ExtBuilder::default().build_and_execute(|| { + assert_ok!(Staking::validate( + Origin::signed(10), + ValidatorPrefs { commission: Perbill::from_percent(5), blocked: false } + )); + + assert_ok!(Staking::set_staking_configs( + Origin::root(), + 0, + 0, + None, + None, + None, + Perbill::from_percent(10), + )); + + // can't make it less than 10 now + assert_noop!( + Staking::validate( + Origin::signed(10), + ValidatorPrefs { commission: Perbill::from_percent(5), blocked: false } + ), + Error::::CommissionTooLow + ); + + // can only change to higher. + assert_ok!(Staking::validate( + Origin::signed(10), + ValidatorPrefs { commission: Perbill::from_percent(10), blocked: false } + )); + + assert_ok!(Staking::validate( + Origin::signed(10), + ValidatorPrefs { commission: Perbill::from_percent(15), blocked: false } + )); + }) +} + mod sorted_list_provider { use super::*; use frame_election_provider_support::SortedListProvider; diff --git a/frame/staking/src/weights.rs b/frame/staking/src/weights.rs index 32c8dc80da15..0ca819898fbb 100644 --- a/frame/staking/src/weights.rs +++ b/frame/staking/src/weights.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_staking //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-09-04, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2021-11-29, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 // Executed Command: @@ -35,7 +35,6 @@ // --output=./frame/staking/src/weights.rs // --template=./.maintain/frame-weight-template.hbs - #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] #![allow(unused_imports)] @@ -71,7 +70,7 @@ pub trait WeightInfo { fn new_era(v: u32, n: u32, ) -> Weight; fn get_npos_voters(v: u32, n: u32, s: u32, ) -> Weight; fn get_npos_targets(v: u32, ) -> Weight; - fn set_staking_limits() -> Weight; + fn set_staking_configs() -> Weight; fn chill_other() -> Weight; } @@ -85,7 +84,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Balances Locks (r:1 w:1) // Storage: Staking Payee (r:0 w:1) fn bond() -> Weight { - (73_865_000 as Weight) + (63_660_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } @@ -95,7 +94,7 @@ impl WeightInfo for SubstrateWeight { // Storage: BagsList ListNodes (r:3 w:3) // Storage: BagsList ListBags (r:2 w:2) fn bond_extra() -> Weight { - (114_296_000 as Weight) + (103_672_000 as Weight) .saturating_add(T::DbWeight::get().reads(8 as Weight)) .saturating_add(T::DbWeight::get().writes(7 as Weight)) } @@ -109,7 +108,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking Bonded (r:1 w:0) // Storage: BagsList ListBags (r:2 w:2) fn unbond() -> Weight { - (121_737_000 as Weight) + (110_884_000 as Weight) .saturating_add(T::DbWeight::get().reads(12 as Weight)) .saturating_add(T::DbWeight::get().writes(8 as Weight)) } @@ -118,7 +117,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn withdraw_unbonded_update(s: u32, ) -> Weight { - (51_631_000 as Weight) + (46_379_000 as Weight) // Standard Error: 0 .saturating_add((55_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) @@ -138,12 +137,13 @@ impl WeightInfo for SubstrateWeight { // Storage: Balances Locks (r:1 w:1) // Storage: Staking Payee (r:0 w:1) fn withdraw_unbonded_kill(_s: u32, ) -> Weight { - (101_870_000 as Weight) + (91_303_000 as Weight) .saturating_add(T::DbWeight::get().reads(13 as Weight)) .saturating_add(T::DbWeight::get().writes(11 as Weight)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking MinValidatorBond (r:1 w:0) + // Storage: Staking MinCommission (r:1 w:0) // Storage: Staking Validators (r:1 w:1) // Storage: Staking MaxValidatorsCount (r:1 w:0) // Storage: Staking Nominators (r:1 w:1) @@ -153,16 +153,16 @@ impl WeightInfo for SubstrateWeight { // Storage: BagsList CounterForListNodes (r:1 w:1) // Storage: Staking CounterForValidators (r:1 w:1) fn validate() -> Weight { - (69_092_000 as Weight) - .saturating_add(T::DbWeight::get().reads(11 as Weight)) + (66_587_000 as Weight) + .saturating_add(T::DbWeight::get().reads(12 as Weight)) .saturating_add(T::DbWeight::get().writes(8 as Weight)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking Nominators (r:1 w:1) fn kick(k: u32, ) -> Weight { - (21_468_000 as Weight) - // Standard Error: 19_000 - .saturating_add((16_415_000 as Weight).saturating_mul(k as Weight)) + (21_153_000 as Weight) + // Standard Error: 16_000 + .saturating_add((13_502_000 as Weight).saturating_mul(k as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(k as Weight))) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) @@ -179,9 +179,9 @@ impl WeightInfo for SubstrateWeight { // Storage: BagsList ListBags (r:1 w:1) // Storage: BagsList CounterForListNodes (r:1 w:1) fn nominate(n: u32, ) -> Weight { - (82_389_000 as Weight) - // Standard Error: 14_000 - .saturating_add((5_597_000 as Weight).saturating_mul(n as Weight)) + (75_456_000 as Weight) + // Standard Error: 12_000 + .saturating_add((5_051_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(12 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(n as Weight))) .saturating_add(T::DbWeight::get().writes(6 as Weight)) @@ -194,47 +194,47 @@ impl WeightInfo for SubstrateWeight { // Storage: BagsList ListBags (r:1 w:1) // Storage: BagsList CounterForListNodes (r:1 w:1) fn chill() -> Weight { - (69_655_000 as Weight) + (65_332_000 as Weight) .saturating_add(T::DbWeight::get().reads(8 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking Payee (r:0 w:1) fn set_payee() -> Weight { - (12_770_000 as Weight) + (11_757_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Staking Bonded (r:1 w:1) // Storage: Staking Ledger (r:2 w:2) fn set_controller() -> Weight { - (27_756_000 as Weight) + (24_252_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Staking ValidatorCount (r:0 w:1) fn set_validator_count() -> Weight { - (2_446_000 as Weight) + (2_252_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Staking ForceEra (r:0 w:1) fn force_no_eras() -> Weight { - (2_720_000 as Weight) + (2_431_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Staking ForceEra (r:0 w:1) fn force_new_era() -> Weight { - (2_711_000 as Weight) + (2_397_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Staking ForceEra (r:0 w:1) fn force_new_era_always() -> Weight { - (2_796_000 as Weight) + (2_423_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Staking Invulnerables (r:0 w:1) fn set_invulnerables(v: u32, ) -> Weight { - (3_141_000 as Weight) + (2_876_000 as Weight) // Standard Error: 0 .saturating_add((53_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -253,18 +253,18 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking Payee (r:0 w:1) // Storage: Staking SpanSlash (r:0 w:2) fn force_unstake(s: u32, ) -> Weight { - (97_394_000 as Weight) - // Standard Error: 2_000 - .saturating_add((2_370_000 as Weight).saturating_mul(s as Weight)) + (87_540_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_791_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(11 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) } // Storage: Staking UnappliedSlashes (r:1 w:1) fn cancel_deferred_slash(s: u32, ) -> Weight { - (2_783_746_000 as Weight) - // Standard Error: 182_000 - .saturating_add((16_223_000 as Weight).saturating_mul(s as Weight)) + (2_769_801_000 as Weight) + // Standard Error: 181_000 + .saturating_add((16_225_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -279,9 +279,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking Payee (r:2 w:0) // Storage: System Account (r:2 w:2) fn payout_stakers_dead_controller(n: u32, ) -> Weight { - (109_233_000 as Weight) - // Standard Error: 17_000 - .saturating_add((47_612_000 as Weight).saturating_mul(n as Weight)) + (103_452_000 as Weight) + // Standard Error: 19_000 + .saturating_add((42_909_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(10 as Weight)) .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(n as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -299,9 +299,9 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:2 w:2) // Storage: Balances Locks (r:2 w:2) fn payout_stakers_alive_staked(n: u32, ) -> Weight { - (177_392_000 as Weight) - // Standard Error: 20_000 - .saturating_add((60_771_000 as Weight).saturating_mul(n as Weight)) + (145_995_000 as Weight) + // Standard Error: 27_000 + .saturating_add((55_974_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(11 as Weight)) .saturating_add(T::DbWeight::get().reads((5 as Weight).saturating_mul(n as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -314,9 +314,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking Bonded (r:1 w:0) // Storage: BagsList ListBags (r:2 w:2) fn rebond(l: u32, ) -> Weight { - (111_858_000 as Weight) - // Standard Error: 4_000 - .saturating_add((36_000 as Weight).saturating_mul(l as Weight)) + (101_568_000 as Weight) + // Standard Error: 2_000 + .saturating_add((66_000 as Weight).saturating_mul(l as Weight)) .saturating_add(T::DbWeight::get().reads(9 as Weight)) .saturating_add(T::DbWeight::get().writes(8 as Weight)) } @@ -331,14 +331,15 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking ErasStartSessionIndex (r:0 w:1) fn set_history_depth(e: u32, ) -> Weight { (0 as Weight) - // Standard Error: 68_000 - .saturating_add((33_495_000 as Weight).saturating_mul(e as Weight)) + // Standard Error: 69_000 + .saturating_add((29_939_000 as Weight).saturating_mul(e as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) .saturating_add(T::DbWeight::get().writes((7 as Weight).saturating_mul(e as Weight))) } // Storage: System Account (r:1 w:1) // Storage: Staking Bonded (r:1 w:1) + // Storage: Staking Ledger (r:1 w:1) // Storage: Staking SlashingSpans (r:1 w:1) // Storage: Staking Validators (r:1 w:0) // Storage: Staking Nominators (r:1 w:1) @@ -347,14 +348,13 @@ impl WeightInfo for SubstrateWeight { // Storage: BagsList ListBags (r:1 w:1) // Storage: BagsList CounterForListNodes (r:1 w:1) // Storage: Balances Locks (r:1 w:1) - // Storage: Staking Ledger (r:0 w:1) // Storage: Staking Payee (r:0 w:1) // Storage: Staking SpanSlash (r:0 w:1) fn reap_stash(s: u32, ) -> Weight { - (100_178_000 as Weight) + (96_886_000 as Weight) // Standard Error: 1_000 - .saturating_add((2_358_000 as Weight).saturating_mul(s as Weight)) - .saturating_add(T::DbWeight::get().reads(11 as Weight)) + .saturating_add((1_790_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(12 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) } @@ -378,10 +378,10 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking ErasStartSessionIndex (r:0 w:1) fn new_era(v: u32, n: u32, ) -> Weight { (0 as Weight) - // Standard Error: 860_000 - .saturating_add((298_721_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 873_000 + .saturating_add((286_141_000 as Weight).saturating_mul(v as Weight)) // Standard Error: 43_000 - .saturating_add((49_427_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((44_712_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(208 as Weight)) .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(v as Weight))) .saturating_add(T::DbWeight::get().reads((4 as Weight).saturating_mul(n as Weight))) @@ -399,12 +399,10 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking Nominators (r:1000 w:0) fn get_npos_voters(v: u32, n: u32, s: u32, ) -> Weight { (0 as Weight) - // Standard Error: 91_000 - .saturating_add((26_605_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 91_000 - .saturating_add((31_481_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 3_122_000 - .saturating_add((16_672_000 as Weight).saturating_mul(s as Weight)) + // Standard Error: 87_000 + .saturating_add((24_049_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 87_000 + .saturating_add((27_514_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(204 as Weight)) .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(v as Weight))) .saturating_add(T::DbWeight::get().reads((4 as Weight).saturating_mul(n as Weight))) @@ -413,19 +411,20 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking Validators (r:501 w:0) fn get_npos_targets(v: u32, ) -> Weight { (0 as Weight) - // Standard Error: 34_000 - .saturating_add((10_558_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 32_000 + .saturating_add((10_128_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(v as Weight))) } + // Storage: Staking MinCommission (r:0 w:1) // Storage: Staking MinValidatorBond (r:0 w:1) // Storage: Staking MaxValidatorsCount (r:0 w:1) // Storage: Staking ChillThreshold (r:0 w:1) // Storage: Staking MaxNominatorsCount (r:0 w:1) // Storage: Staking MinNominatorBond (r:0 w:1) - fn set_staking_limits() -> Weight { - (6_353_000 as Weight) - .saturating_add(T::DbWeight::get().writes(5 as Weight)) + fn set_staking_configs() -> Weight { + (6_187_000 as Weight) + .saturating_add(T::DbWeight::get().writes(6 as Weight)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking ChillThreshold (r:1 w:0) @@ -438,7 +437,7 @@ impl WeightInfo for SubstrateWeight { // Storage: BagsList ListBags (r:1 w:1) // Storage: BagsList CounterForListNodes (r:1 w:1) fn chill_other() -> Weight { - (83_389_000 as Weight) + (78_282_000 as Weight) .saturating_add(T::DbWeight::get().reads(11 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } @@ -453,7 +452,7 @@ impl WeightInfo for () { // Storage: Balances Locks (r:1 w:1) // Storage: Staking Payee (r:0 w:1) fn bond() -> Weight { - (73_865_000 as Weight) + (63_660_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } @@ -463,7 +462,7 @@ impl WeightInfo for () { // Storage: BagsList ListNodes (r:3 w:3) // Storage: BagsList ListBags (r:2 w:2) fn bond_extra() -> Weight { - (114_296_000 as Weight) + (103_672_000 as Weight) .saturating_add(RocksDbWeight::get().reads(8 as Weight)) .saturating_add(RocksDbWeight::get().writes(7 as Weight)) } @@ -477,7 +476,7 @@ impl WeightInfo for () { // Storage: Staking Bonded (r:1 w:0) // Storage: BagsList ListBags (r:2 w:2) fn unbond() -> Weight { - (121_737_000 as Weight) + (110_884_000 as Weight) .saturating_add(RocksDbWeight::get().reads(12 as Weight)) .saturating_add(RocksDbWeight::get().writes(8 as Weight)) } @@ -486,7 +485,7 @@ impl WeightInfo for () { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn withdraw_unbonded_update(s: u32, ) -> Weight { - (51_631_000 as Weight) + (46_379_000 as Weight) // Standard Error: 0 .saturating_add((55_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) @@ -506,12 +505,13 @@ impl WeightInfo for () { // Storage: Balances Locks (r:1 w:1) // Storage: Staking Payee (r:0 w:1) fn withdraw_unbonded_kill(_s: u32, ) -> Weight { - (101_870_000 as Weight) + (91_303_000 as Weight) .saturating_add(RocksDbWeight::get().reads(13 as Weight)) .saturating_add(RocksDbWeight::get().writes(11 as Weight)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking MinValidatorBond (r:1 w:0) + // Storage: Staking MinCommission (r:1 w:0) // Storage: Staking Validators (r:1 w:1) // Storage: Staking MaxValidatorsCount (r:1 w:0) // Storage: Staking Nominators (r:1 w:1) @@ -521,16 +521,16 @@ impl WeightInfo for () { // Storage: BagsList CounterForListNodes (r:1 w:1) // Storage: Staking CounterForValidators (r:1 w:1) fn validate() -> Weight { - (69_092_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(11 as Weight)) + (66_587_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(12 as Weight)) .saturating_add(RocksDbWeight::get().writes(8 as Weight)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking Nominators (r:1 w:1) fn kick(k: u32, ) -> Weight { - (21_468_000 as Weight) - // Standard Error: 19_000 - .saturating_add((16_415_000 as Weight).saturating_mul(k as Weight)) + (21_153_000 as Weight) + // Standard Error: 16_000 + .saturating_add((13_502_000 as Weight).saturating_mul(k as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(k as Weight))) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) @@ -547,9 +547,9 @@ impl WeightInfo for () { // Storage: BagsList ListBags (r:1 w:1) // Storage: BagsList CounterForListNodes (r:1 w:1) fn nominate(n: u32, ) -> Weight { - (82_389_000 as Weight) - // Standard Error: 14_000 - .saturating_add((5_597_000 as Weight).saturating_mul(n as Weight)) + (75_456_000 as Weight) + // Standard Error: 12_000 + .saturating_add((5_051_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(12 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(n as Weight))) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) @@ -562,47 +562,47 @@ impl WeightInfo for () { // Storage: BagsList ListBags (r:1 w:1) // Storage: BagsList CounterForListNodes (r:1 w:1) fn chill() -> Weight { - (69_655_000 as Weight) + (65_332_000 as Weight) .saturating_add(RocksDbWeight::get().reads(8 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking Payee (r:0 w:1) fn set_payee() -> Weight { - (12_770_000 as Weight) + (11_757_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Staking Bonded (r:1 w:1) // Storage: Staking Ledger (r:2 w:2) fn set_controller() -> Weight { - (27_756_000 as Weight) + (24_252_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } // Storage: Staking ValidatorCount (r:0 w:1) fn set_validator_count() -> Weight { - (2_446_000 as Weight) + (2_252_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Staking ForceEra (r:0 w:1) fn force_no_eras() -> Weight { - (2_720_000 as Weight) + (2_431_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Staking ForceEra (r:0 w:1) fn force_new_era() -> Weight { - (2_711_000 as Weight) + (2_397_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Staking ForceEra (r:0 w:1) fn force_new_era_always() -> Weight { - (2_796_000 as Weight) + (2_423_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Staking Invulnerables (r:0 w:1) fn set_invulnerables(v: u32, ) -> Weight { - (3_141_000 as Weight) + (2_876_000 as Weight) // Standard Error: 0 .saturating_add((53_000 as Weight).saturating_mul(v as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -621,18 +621,18 @@ impl WeightInfo for () { // Storage: Staking Payee (r:0 w:1) // Storage: Staking SpanSlash (r:0 w:2) fn force_unstake(s: u32, ) -> Weight { - (97_394_000 as Weight) - // Standard Error: 2_000 - .saturating_add((2_370_000 as Weight).saturating_mul(s as Weight)) + (87_540_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_791_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(11 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) } // Storage: Staking UnappliedSlashes (r:1 w:1) fn cancel_deferred_slash(s: u32, ) -> Weight { - (2_783_746_000 as Weight) - // Standard Error: 182_000 - .saturating_add((16_223_000 as Weight).saturating_mul(s as Weight)) + (2_769_801_000 as Weight) + // Standard Error: 181_000 + .saturating_add((16_225_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -647,9 +647,9 @@ impl WeightInfo for () { // Storage: Staking Payee (r:2 w:0) // Storage: System Account (r:2 w:2) fn payout_stakers_dead_controller(n: u32, ) -> Weight { - (109_233_000 as Weight) - // Standard Error: 17_000 - .saturating_add((47_612_000 as Weight).saturating_mul(n as Weight)) + (103_452_000 as Weight) + // Standard Error: 19_000 + .saturating_add((42_909_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(10 as Weight)) .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(n as Weight))) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) @@ -667,9 +667,9 @@ impl WeightInfo for () { // Storage: System Account (r:2 w:2) // Storage: Balances Locks (r:2 w:2) fn payout_stakers_alive_staked(n: u32, ) -> Weight { - (177_392_000 as Weight) - // Standard Error: 20_000 - .saturating_add((60_771_000 as Weight).saturating_mul(n as Weight)) + (145_995_000 as Weight) + // Standard Error: 27_000 + .saturating_add((55_974_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(11 as Weight)) .saturating_add(RocksDbWeight::get().reads((5 as Weight).saturating_mul(n as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -682,9 +682,9 @@ impl WeightInfo for () { // Storage: Staking Bonded (r:1 w:0) // Storage: BagsList ListBags (r:2 w:2) fn rebond(l: u32, ) -> Weight { - (111_858_000 as Weight) - // Standard Error: 4_000 - .saturating_add((36_000 as Weight).saturating_mul(l as Weight)) + (101_568_000 as Weight) + // Standard Error: 2_000 + .saturating_add((66_000 as Weight).saturating_mul(l as Weight)) .saturating_add(RocksDbWeight::get().reads(9 as Weight)) .saturating_add(RocksDbWeight::get().writes(8 as Weight)) } @@ -699,14 +699,15 @@ impl WeightInfo for () { // Storage: Staking ErasStartSessionIndex (r:0 w:1) fn set_history_depth(e: u32, ) -> Weight { (0 as Weight) - // Standard Error: 68_000 - .saturating_add((33_495_000 as Weight).saturating_mul(e as Weight)) + // Standard Error: 69_000 + .saturating_add((29_939_000 as Weight).saturating_mul(e as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) .saturating_add(RocksDbWeight::get().writes((7 as Weight).saturating_mul(e as Weight))) } // Storage: System Account (r:1 w:1) // Storage: Staking Bonded (r:1 w:1) + // Storage: Staking Ledger (r:1 w:1) // Storage: Staking SlashingSpans (r:1 w:1) // Storage: Staking Validators (r:1 w:0) // Storage: Staking Nominators (r:1 w:1) @@ -715,14 +716,13 @@ impl WeightInfo for () { // Storage: BagsList ListBags (r:1 w:1) // Storage: BagsList CounterForListNodes (r:1 w:1) // Storage: Balances Locks (r:1 w:1) - // Storage: Staking Ledger (r:0 w:1) // Storage: Staking Payee (r:0 w:1) // Storage: Staking SpanSlash (r:0 w:1) fn reap_stash(s: u32, ) -> Weight { - (100_178_000 as Weight) + (96_886_000 as Weight) // Standard Error: 1_000 - .saturating_add((2_358_000 as Weight).saturating_mul(s as Weight)) - .saturating_add(RocksDbWeight::get().reads(11 as Weight)) + .saturating_add((1_790_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(RocksDbWeight::get().reads(12 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) } @@ -746,10 +746,10 @@ impl WeightInfo for () { // Storage: Staking ErasStartSessionIndex (r:0 w:1) fn new_era(v: u32, n: u32, ) -> Weight { (0 as Weight) - // Standard Error: 860_000 - .saturating_add((298_721_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 873_000 + .saturating_add((286_141_000 as Weight).saturating_mul(v as Weight)) // Standard Error: 43_000 - .saturating_add((49_427_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((44_712_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(208 as Weight)) .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(v as Weight))) .saturating_add(RocksDbWeight::get().reads((4 as Weight).saturating_mul(n as Weight))) @@ -767,12 +767,10 @@ impl WeightInfo for () { // Storage: Staking Nominators (r:1000 w:0) fn get_npos_voters(v: u32, n: u32, s: u32, ) -> Weight { (0 as Weight) - // Standard Error: 91_000 - .saturating_add((26_605_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 91_000 - .saturating_add((31_481_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 3_122_000 - .saturating_add((16_672_000 as Weight).saturating_mul(s as Weight)) + // Standard Error: 87_000 + .saturating_add((24_049_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 87_000 + .saturating_add((27_514_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(204 as Weight)) .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(v as Weight))) .saturating_add(RocksDbWeight::get().reads((4 as Weight).saturating_mul(n as Weight))) @@ -781,19 +779,20 @@ impl WeightInfo for () { // Storage: Staking Validators (r:501 w:0) fn get_npos_targets(v: u32, ) -> Weight { (0 as Weight) - // Standard Error: 34_000 - .saturating_add((10_558_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 32_000 + .saturating_add((10_128_000 as Weight).saturating_mul(v as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(v as Weight))) } + // Storage: Staking MinCommission (r:0 w:1) // Storage: Staking MinValidatorBond (r:0 w:1) // Storage: Staking MaxValidatorsCount (r:0 w:1) // Storage: Staking ChillThreshold (r:0 w:1) // Storage: Staking MaxNominatorsCount (r:0 w:1) // Storage: Staking MinNominatorBond (r:0 w:1) - fn set_staking_limits() -> Weight { - (6_353_000 as Weight) - .saturating_add(RocksDbWeight::get().writes(5 as Weight)) + fn set_staking_configs() -> Weight { + (6_187_000 as Weight) + .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking ChillThreshold (r:1 w:0) @@ -806,7 +805,7 @@ impl WeightInfo for () { // Storage: BagsList ListBags (r:1 w:1) // Storage: BagsList CounterForListNodes (r:1 w:1) fn chill_other() -> Weight { - (83_389_000 as Weight) + (78_282_000 as Weight) .saturating_add(RocksDbWeight::get().reads(11 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } diff --git a/primitives/arithmetic/src/per_things.rs b/primitives/arithmetic/src/per_things.rs index f388c19de6b4..783b331b3353 100644 --- a/primitives/arithmetic/src/per_things.rs +++ b/primitives/arithmetic/src/per_things.rs @@ -833,6 +833,16 @@ macro_rules! implement_per_thing { } } + impl $crate::traits::Zero for $name { + fn zero() -> Self { + Self::zero() + } + + fn is_zero(&self) -> bool { + self == &Self::zero() + } + } + #[cfg(test)] mod $test_mod { From 40f24836121ed5574696efe37cdc4bdf4ecbff70 Mon Sep 17 00:00:00 2001 From: Nazar Mokrynskyi Date: Fri, 3 Dec 2021 01:17:23 +0200 Subject: [PATCH 249/695] Account for transaction priority when enforcing limits (#10388) * Account for transaction priority when enforcing limits * Improve `enforce_limits` comment * Explanation comment on why comparison impl is not used for limit enforcement --- .../transaction-pool/src/graph/base_pool.rs | 44 +++++++----- client/transaction-pool/src/graph/pool.rs | 70 ++++++++++++++++++- 2 files changed, 97 insertions(+), 17 deletions(-) diff --git a/client/transaction-pool/src/graph/base_pool.rs b/client/transaction-pool/src/graph/base_pool.rs index 2c8becdfb2f0..cf634c3213a8 100644 --- a/client/transaction-pool/src/graph/base_pool.rs +++ b/client/transaction-pool/src/graph/base_pool.rs @@ -20,7 +20,7 @@ //! //! For a more full-featured pool, have a look at the `pool` module. -use std::{collections::HashSet, fmt, hash, sync::Arc}; +use std::{cmp::Ordering, collections::HashSet, fmt, hash, sync::Arc}; use log::{debug, trace, warn}; use sc_transaction_pool_api::{error, InPoolTransaction, PoolStatus}; @@ -36,7 +36,7 @@ use sp_runtime::{ use super::{ future::{FutureTransactions, WaitingTransaction}, - ready::{BestIterator, ReadyTransactions}, + ready::{BestIterator, ReadyTransactions, TransactionRef}, }; /// Successful import result. @@ -384,8 +384,8 @@ impl BasePool BasePool, _>(|worst, current| { let transaction = ¤t.transaction; - match minimal { - None => Some(transaction.clone()), - Some(ref tx) if tx.insertion_id > transaction.insertion_id => - Some(transaction.clone()), - other => other, - } + worst + .map(|worst| { + // Here we don't use `TransactionRef`'s ordering implementation because + // while it prefers priority like need here, it also prefers older + // transactions for inclusion purposes and limit enforcement needs to prefer + // newer transactions instead and drop the older ones. + match worst.transaction.priority.cmp(&transaction.transaction.priority) { + Ordering::Less => worst, + Ordering::Equal => + if worst.insertion_id > transaction.insertion_id { + transaction.clone() + } else { + worst + }, + Ordering::Greater => transaction.clone(), + } + }) + .or_else(|| Some(transaction.clone())) }); - if let Some(minimal) = minimal { - removed.append(&mut self.remove_subtree(&[minimal.transaction.hash.clone()])) + if let Some(worst) = worst { + removed.append(&mut self.remove_subtree(&[worst.transaction.hash.clone()])) } else { break } @@ -414,14 +426,14 @@ impl BasePool Some(current.clone()), Some(ref tx) if tx.imported_at > current.imported_at => Some(current.clone()), other => other, }); - if let Some(minimal) = minimal { - removed.append(&mut self.remove_subtree(&[minimal.transaction.hash.clone()])) + if let Some(worst) = worst { + removed.append(&mut self.remove_subtree(&[worst.transaction.hash.clone()])) } else { break } diff --git a/client/transaction-pool/src/graph/pool.rs b/client/transaction-pool/src/graph/pool.rs index 2af5a8a19a5a..af46dbad0ee5 100644 --- a/client/transaction-pool/src/graph/pool.rs +++ b/client/transaction-pool/src/graph/pool.rs @@ -539,6 +539,13 @@ mod tests { longevity: 9001, propagate: false, }), + Extrinsic::Store(_) => Ok(ValidTransaction { + priority: 9001, + requires: vec![], + provides: vec![vec![43]], + longevity: 9001, + propagate: false, + }), _ => unimplemented!(), }; @@ -1044,7 +1051,7 @@ mod tests { } #[test] - fn should_trigger_dropped() { + fn should_trigger_dropped_older() { // given let limit = Limit { count: 1, total_bytes: 1000 }; let options = @@ -1077,6 +1084,67 @@ mod tests { assert_eq!(stream.next(), Some(TransactionStatus::Dropped)); } + #[test] + fn should_trigger_dropped_lower_priority() { + { + // given + let limit = Limit { count: 1, total_bytes: 1000 }; + let options = + Options { ready: limit.clone(), future: limit.clone(), ..Default::default() }; + + let pool = Pool::new(options, true.into(), TestApi::default().into()); + + let xt = Extrinsic::IncludeData(Vec::new()); + block_on(pool.submit_one(&BlockId::Number(0), SOURCE, xt)).unwrap(); + assert_eq!(pool.validated_pool().status().ready, 1); + + // then + let xt = uxt(Transfer { + from: AccountId::from_h256(H256::from_low_u64_be(2)), + to: AccountId::from_h256(H256::from_low_u64_be(1)), + amount: 4, + nonce: 1, + }); + let result = block_on(pool.submit_one(&BlockId::Number(1), SOURCE, xt)); + assert!(matches!( + result, + Err(sc_transaction_pool_api::error::Error::ImmediatelyDropped) + )); + } + { + // given + let limit = Limit { count: 2, total_bytes: 1000 }; + let options = + Options { ready: limit.clone(), future: limit.clone(), ..Default::default() }; + + let pool = Pool::new(options, true.into(), TestApi::default().into()); + + let xt = Extrinsic::IncludeData(Vec::new()); + block_on(pool.submit_and_watch(&BlockId::Number(0), SOURCE, xt)).unwrap(); + assert_eq!(pool.validated_pool().status().ready, 1); + + let xt = uxt(Transfer { + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), + amount: 5, + nonce: 0, + }); + let watcher = + block_on(pool.submit_and_watch(&BlockId::Number(0), SOURCE, xt)).unwrap(); + assert_eq!(pool.validated_pool().status().ready, 2); + + // when + let xt = Extrinsic::Store(Vec::new()); + block_on(pool.submit_one(&BlockId::Number(1), SOURCE, xt)).unwrap(); + assert_eq!(pool.validated_pool().status().ready, 2); + + // then + let mut stream = futures::executor::block_on_stream(watcher.into_stream()); + assert_eq!(stream.next(), Some(TransactionStatus::Ready)); + assert_eq!(stream.next(), Some(TransactionStatus::Dropped)); + } + } + #[test] fn should_handle_pruning_in_the_middle_of_import() { // given From b6d489ed3015646e0cd65861ec9381a44de76985 Mon Sep 17 00:00:00 2001 From: Guillaume Thiolliere Date: Fri, 3 Dec 2021 14:58:12 +0900 Subject: [PATCH 250/695] Fix pallet bags list and doc (#10231) * fix bags list * improve doc * doc * inner doc * fix test * Update docs in frame/election-provider-support/src/lib.rs * fix staking impl * prepend unsafe to clear and regenerate * fix test Co-authored-by: Keith Yeung Co-authored-by: Shawn Tabrizi --- frame/bags-list/remote-tests/src/migration.rs | 2 +- frame/bags-list/src/benchmarks.rs | 6 +++-- frame/bags-list/src/lib.rs | 16 +++++++++---- frame/bags-list/src/list/mod.rs | 23 +++++++++---------- frame/election-provider-support/src/lib.rs | 18 +++++++++++---- frame/staking/src/migrations.rs | 2 +- frame/staking/src/pallet/impls.rs | 17 ++++++-------- frame/staking/src/testing_utils.rs | 3 ++- frame/support/src/storage/mod.rs | 6 ++++- .../support/src/storage/types/counted_map.rs | 15 ++++++------ frame/support/src/storage/types/double_map.rs | 6 ++++- frame/support/src/storage/types/map.rs | 6 ++++- primitives/io/src/lib.rs | 6 ++--- 13 files changed, 76 insertions(+), 50 deletions(-) diff --git a/frame/bags-list/remote-tests/src/migration.rs b/frame/bags-list/remote-tests/src/migration.rs index 86595c7feba9..aadbbdae3d61 100644 --- a/frame/bags-list/remote-tests/src/migration.rs +++ b/frame/bags-list/remote-tests/src/migration.rs @@ -47,7 +47,7 @@ pub async fn execute( log::info!(target: LOG_TARGET, "Nominator count: {}", pre_migrate_nominator_count); // run the actual migration, - let moved = ::SortedListProvider::regenerate( + let moved = ::SortedListProvider::unsafe_regenerate( pallet_staking::Nominators::::iter().map(|(n, _)| n), pallet_staking::Pallet::::weight_of_fn(), ); diff --git a/frame/bags-list/src/benchmarks.rs b/frame/bags-list/src/benchmarks.rs index d86adc674c44..800e668324e0 100644 --- a/frame/bags-list/src/benchmarks.rs +++ b/frame/bags-list/src/benchmarks.rs @@ -35,7 +35,8 @@ frame_benchmarking::benchmarks! { // node in the destination in addition to the work we do otherwise. (2 W/R) // clear any pre-existing storage. - List::::clear(None); + // NOTE: safe to call outside block production + List::::unsafe_clear(); // define our origin and destination thresholds. let origin_bag_thresh = T::BagThresholds::get()[0]; @@ -94,7 +95,8 @@ frame_benchmarking::benchmarks! { // node in the destination in addition to the work we do otherwise. (2 W/R) // clear any pre-existing storage. - List::::clear(None); + // NOTE: safe to call outside block production + List::::unsafe_clear(); // define our origin and destination thresholds. let origin_bag_thresh = T::BagThresholds::get()[0]; diff --git a/frame/bags-list/src/lib.rs b/frame/bags-list/src/lib.rs index 2cff68b54c9c..d3be2c29533f 100644 --- a/frame/bags-list/src/lib.rs +++ b/frame/bags-list/src/lib.rs @@ -26,7 +26,7 @@ //! the weights of accounts via [`frame_election_provider_support::VoteWeightProvider`]. //! //! This pallet is not configurable at genesis. Whoever uses it should call appropriate functions of -//! the `SortedListProvider` (e.g. `on_insert`, or `regenerate`) at their genesis. +//! the `SortedListProvider` (e.g. `on_insert`, or `unsafe_regenerate`) at their genesis. //! //! # Goals //! @@ -256,11 +256,14 @@ impl SortedListProvider for Pallet { List::::remove(id) } - fn regenerate( + fn unsafe_regenerate( all: impl IntoIterator, weight_of: Box VoteWeight>, ) -> u32 { - List::::regenerate(all, weight_of) + // NOTE: This call is unsafe for the same reason as SortedListProvider::unsafe_regenerate. + // I.e. because it can lead to many storage accesses. + // So it is ok to call it as caller must ensure the conditions. + List::::unsafe_regenerate(all, weight_of) } #[cfg(feature = "std")] @@ -273,8 +276,11 @@ impl SortedListProvider for Pallet { Ok(()) } - fn clear(maybe_count: Option) -> u32 { - List::::clear(maybe_count) + fn unsafe_clear() { + // NOTE: This call is unsafe for the same reason as SortedListProvider::unsafe_clear. + // I.e. because it can lead to many storage accesses. + // So it is ok to call it as caller must ensure the conditions. + List::::unsafe_clear() } #[cfg(feature = "runtime-benchmarks")] diff --git a/frame/bags-list/src/list/mod.rs b/frame/bags-list/src/list/mod.rs index b381b36dc9ee..1ec4996c26fd 100644 --- a/frame/bags-list/src/list/mod.rs +++ b/frame/bags-list/src/list/mod.rs @@ -76,19 +76,15 @@ pub fn notional_bag_for(weight: VoteWeight) -> VoteWeight { pub struct List(PhantomData); impl List { - /// Remove all data associated with the list from storage. Parameter `items` is the number of - /// items to clear from the list. + /// Remove all data associated with the list from storage. /// /// ## WARNING /// - /// `None` will clear all items and should generally not be used in production as it could lead - /// to a very large number of storage accesses. - pub(crate) fn clear(maybe_count: Option) -> u32 { - crate::ListBags::::remove_all(maybe_count); - let pre = crate::ListNodes::::count(); - crate::ListNodes::::remove_all(maybe_count); - let post = crate::ListNodes::::count(); - pre.saturating_sub(post) + /// this function should generally not be used in production as it could lead to a very large + /// number of storage accesses. + pub(crate) fn unsafe_clear() { + crate::ListBags::::remove_all(None); + crate::ListNodes::::remove_all(); } /// Regenerate all of the data from the given ids. @@ -100,11 +96,14 @@ impl List { /// pallet using this `List`. /// /// Returns the number of ids migrated. - pub fn regenerate( + pub fn unsafe_regenerate( all: impl IntoIterator, weight_of: Box VoteWeight>, ) -> u32 { - Self::clear(None); + // NOTE: This call is unsafe for the same reason as SortedListProvider::unsafe_regenerate. + // I.e. because it can lead to many storage accesses. + // So it is ok to call it as caller must ensure the conditions. + Self::unsafe_clear(); Self::insert_many(all, weight_of) } diff --git a/frame/election-provider-support/src/lib.rs b/frame/election-provider-support/src/lib.rs index 472584ed2506..ac3bfccbbdb5 100644 --- a/frame/election-provider-support/src/lib.rs +++ b/frame/election-provider-support/src/lib.rs @@ -333,15 +333,23 @@ pub trait SortedListProvider { /// Regenerate this list from scratch. Returns the count of items inserted. /// /// This should typically only be used at a runtime upgrade. - fn regenerate( + /// + /// ## WARNING + /// + /// This function should be called with care, regenerate will remove the current list write the + /// new list, which can lead to too many storage accesses, exhausting the block weight. + fn unsafe_regenerate( all: impl IntoIterator, weight_of: Box VoteWeight>, ) -> u32; - /// Remove `maybe_count` number of items from the list. Returns the number of items actually - /// removed. WARNING: removes all items if `maybe_count` is `None`, which should never be done - /// in production settings because it can lead to an unbounded amount of storage accesses. - fn clear(maybe_count: Option) -> u32; + /// Remove all items from the list. + /// + /// ## WARNING + /// + /// This function should never be called in production settings because it can lead to an + /// unbounded amount of storage accesses. + fn unsafe_clear(); /// Sanity check internal state of list. Only meant for debug compilation. fn sanity_check() -> Result<(), &'static str>; diff --git a/frame/staking/src/migrations.rs b/frame/staking/src/migrations.rs index 7064f06dd12c..6f1d3953f8f1 100644 --- a/frame/staking/src/migrations.rs +++ b/frame/staking/src/migrations.rs @@ -40,7 +40,7 @@ pub mod v8 { if StorageVersion::::get() == crate::Releases::V7_0_0 { crate::log!(info, "migrating staking to Releases::V8_0_0"); - let migrated = T::SortedListProvider::regenerate( + let migrated = T::SortedListProvider::unsafe_regenerate( Nominators::::iter().map(|(id, _)| id), Pallet::::weight_of_fn(), ); diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 8d86cfbe6b0d..cd26ff3b729c 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -971,7 +971,7 @@ impl ElectionDataProvider> for Pallet >::remove_all(None); >::kill(); >::kill(); - let _ = T::SortedListProvider::clear(None); + T::SortedListProvider::unsafe_clear(); } #[cfg(feature = "runtime-benchmarks")] @@ -1299,7 +1299,7 @@ impl SortedListProvider for UseNominatorsMap { fn on_remove(_: &T::AccountId) { // nothing to do on remove. } - fn regenerate( + fn unsafe_regenerate( _: impl IntoIterator, _: Box VoteWeight>, ) -> u32 { @@ -1309,13 +1309,10 @@ impl SortedListProvider for UseNominatorsMap { fn sanity_check() -> Result<(), &'static str> { Ok(()) } - fn clear(maybe_count: Option) -> u32 { - Nominators::::remove_all(maybe_count); - if let Some(count) = maybe_count { - CounterForNominators::::mutate(|noms| *noms - count); - count - } else { - CounterForNominators::::take() - } + fn unsafe_clear() { + // NOTE: Caller must ensure this doesn't lead to too many storage accesses. This is a + // condition of SortedListProvider::unsafe_clear. + Nominators::::remove_all(None); + CounterForNominators::::take(); } } diff --git a/frame/staking/src/testing_utils.rs b/frame/staking/src/testing_utils.rs index 13762cf5886d..611773fc0ccf 100644 --- a/frame/staking/src/testing_utils.rs +++ b/frame/staking/src/testing_utils.rs @@ -42,7 +42,8 @@ pub fn clear_validators_and_nominators() { // whenever we touch nominators counter we should update `T::SortedListProvider` as well. Nominators::::remove_all(None); CounterForNominators::::kill(); - let _ = T::SortedListProvider::clear(None); + // NOTE: safe to call outside block production + T::SortedListProvider::unsafe_clear(); } /// Grab a funded user. diff --git a/frame/support/src/storage/mod.rs b/frame/support/src/storage/mod.rs index 81f98f2c23d4..9217cf4e6d9e 100644 --- a/frame/support/src/storage/mod.rs +++ b/frame/support/src/storage/mod.rs @@ -1133,7 +1133,11 @@ pub trait StoragePrefixedMap { crate::storage::storage_prefix(Self::module_prefix(), Self::storage_prefix()) } - /// Remove all value of the storage. + /// Remove all values of the storage in the overlay and up to `limit` in the backend. + /// + /// All values in the client overlay will be deleted, if there is some `limit` then up to + /// `limit` values are deleted from the client backend, if `limit` is none then all values in + /// the client backend are deleted. fn remove_all(limit: Option) -> sp_io::KillStorageResult { sp_io::storage::clear_prefix(&Self::final_prefix(), limit) } diff --git a/frame/support/src/storage/types/counted_map.rs b/frame/support/src/storage/types/counted_map.rs index 51edf1089026..5211453fd09b 100644 --- a/frame/support/src/storage/types/counted_map.rs +++ b/frame/support/src/storage/types/counted_map.rs @@ -31,7 +31,6 @@ use crate::{ Never, }; use codec::{Decode, Encode, EncodeLike, FullCodec, MaxEncodedLen, Ref}; -use sp_arithmetic::traits::Bounded; use sp_runtime::traits::Saturating; use sp_std::prelude::*; @@ -263,10 +262,12 @@ where } /// Remove all value of the storage. - pub fn remove_all(maybe_limit: Option) { - let leftover = Self::count().saturating_sub(maybe_limit.unwrap_or_else(Bounded::max_value)); - CounterFor::::set(leftover); - ::Map::remove_all(maybe_limit); + pub fn remove_all() { + // NOTE: it is not possible to remove up to some limit because + // `sp_io::storage::clear_prefix` and `StorageMap::remove_all` don't give the number of + // value removed from the overlay. + CounterFor::::set(0u32); + ::Map::remove_all(None); } /// Iter over all value of the storage. @@ -678,7 +679,7 @@ mod test { assert_eq!(A::count(), 2); // Remove all. - A::remove_all(None); + A::remove_all(); assert_eq!(A::count(), 0); assert_eq!(A::initialize_counter(), 0); @@ -909,7 +910,7 @@ mod test { assert_eq!(B::count(), 2); // Remove all. - B::remove_all(None); + B::remove_all(); assert_eq!(B::count(), 0); assert_eq!(B::initialize_counter(), 0); diff --git a/frame/support/src/storage/types/double_map.rs b/frame/support/src/storage/types/double_map.rs index b9af4a621b92..d3595814d04b 100644 --- a/frame/support/src/storage/types/double_map.rs +++ b/frame/support/src/storage/types/double_map.rs @@ -335,7 +335,11 @@ where >(key1, key2) } - /// Remove all value of the storage. + /// Remove all values of the storage in the overlay and up to `limit` in the backend. + /// + /// All values in the client overlay will be deleted, if there is some `limit` then up to + /// `limit` values are deleted from the client backend, if `limit` is none then all values in + /// the client backend are deleted. pub fn remove_all(limit: Option) -> sp_io::KillStorageResult { >::remove_all(limit) } diff --git a/frame/support/src/storage/types/map.rs b/frame/support/src/storage/types/map.rs index 45340f9015ea..6532d47cfec6 100644 --- a/frame/support/src/storage/types/map.rs +++ b/frame/support/src/storage/types/map.rs @@ -234,7 +234,11 @@ where >::migrate_key::(key) } - /// Remove all value of the storage. + /// Remove all values of the storage in the overlay and up to `limit` in the backend. + /// + /// All values in the client overlay will be deleted, if there is some `limit` then up to + /// `limit` values are deleted from the client backend, if `limit` is none then all values in + /// the client backend are deleted. pub fn remove_all(limit: Option) -> sp_io::KillStorageResult { >::remove_all(limit) } diff --git a/primitives/io/src/lib.rs b/primitives/io/src/lib.rs index e4f52fd4e0e2..94ae1a8f7083 100644 --- a/primitives/io/src/lib.rs +++ b/primitives/io/src/lib.rs @@ -88,12 +88,12 @@ pub enum EcdsaVerifyError { } /// The outcome of calling `storage_kill`. Returned value is the number of storage items -/// removed from the trie from making the `storage_kill` call. +/// removed from the backend from making the `storage_kill` call. #[derive(PassByCodec, Encode, Decode)] pub enum KillStorageResult { - /// No key remains in the child trie. + /// All key to remove were removed, return number of key removed from backend. AllRemoved(u32), - /// At least one key still resides in the child trie due to the supplied limit. + /// Not all key to remove were removed, return number of key removed from backend. SomeRemaining(u32), } From 3d005a3eaa968e4dc58407a1369a8d670c9a35df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Fri, 3 Dec 2021 11:29:51 +0100 Subject: [PATCH 251/695] wasm-override: Support checking `spec_name` (#10380) This adds support to the wasm-override feature to compare the spec_name. If the spec_name doesn't match, a warning will be printed and the override will be ignored. --- client/service/src/client/call_executor.rs | 15 ++- client/service/src/client/wasm_override.rs | 125 ++++++++++++++++----- primitives/runtime/src/runtime_string.rs | 12 ++ 3 files changed, 118 insertions(+), 34 deletions(-) diff --git a/client/service/src/client/call_executor.rs b/client/service/src/client/call_executor.rs index be871cc371ed..7d15ce4704ab 100644 --- a/client/service/src/client/call_executor.rs +++ b/client/service/src/client/call_executor.rs @@ -38,7 +38,7 @@ use std::{cell::RefCell, panic::UnwindSafe, result, sync::Arc}; pub struct LocalCallExecutor { backend: Arc, executor: E, - wasm_override: Option, + wasm_override: Arc>, wasm_substitutes: WasmSubstitutes, spawn_handle: Box, client_config: ClientConfig, @@ -71,7 +71,7 @@ where Ok(LocalCallExecutor { backend, executor, - wasm_override, + wasm_override: Arc::new(wasm_override), spawn_handle, client_config, wasm_substitutes, @@ -90,16 +90,19 @@ where Block: BlockT, B: backend::Backend, { - let spec = self.runtime_version(id)?.spec_version; + let spec = self.runtime_version(id)?; let code = if let Some(d) = self .wasm_override .as_ref() - .map(|o| o.get(&spec, onchain_code.heap_pages)) + .as_ref() + .map(|o| o.get(&spec.spec_version, onchain_code.heap_pages, &spec.spec_name)) .flatten() { log::debug!(target: "wasm_overrides", "using WASM override for block {}", id); d - } else if let Some(s) = self.wasm_substitutes.get(spec, onchain_code.heap_pages, id) { + } else if let Some(s) = + self.wasm_substitutes.get(spec.spec_version, onchain_code.heap_pages, id) + { log::debug!(target: "wasm_substitutes", "Using WASM substitute for block {:?}", id); s } else { @@ -395,7 +398,7 @@ mod tests { let call_executor = LocalCallExecutor { backend: backend.clone(), executor: executor.clone(), - wasm_override: Some(overrides), + wasm_override: Arc::new(Some(overrides)), spawn_handle: Box::new(TaskExecutor::new()), client_config, wasm_substitutes: WasmSubstitutes::new( diff --git a/client/service/src/client/wasm_override.rs b/client/service/src/client/wasm_override.rs index 3d28467a9cbd..ba3f2855fc7a 100644 --- a/client/service/src/client/wasm_override.rs +++ b/client/service/src/client/wasm_override.rs @@ -35,9 +35,10 @@ //! A custom WASM blob will override on-chain WASM if the spec version matches. If it is //! required to overrides multiple runtimes, multiple WASM blobs matching each of the spec versions //! needed must be provided in the given directory. + use sc_executor::RuntimeVersionOf; use sp_blockchain::Result; -use sp_core::traits::{FetchRuntimeCode, RuntimeCode}; +use sp_core::traits::{FetchRuntimeCode, RuntimeCode, WrappedRuntimeCode}; use sp_state_machine::BasicExternalities; use sp_version::RuntimeVersion; use std::{ @@ -45,19 +46,32 @@ use std::{ fs, hash::Hasher as _, path::{Path, PathBuf}, + time::{Duration, Instant}, }; -#[derive(Clone, Debug, PartialEq)] +/// The interval in that we will print a warning when a wasm blob `spec_name` +/// doesn't match with the on-chain `spec_name`. +const WARN_INTERVAL: Duration = Duration::from_secs(30); + /// Auxiliary structure that holds a wasm blob and its hash. +#[derive(Debug)] struct WasmBlob { + /// The actual wasm blob, aka the code. code: Vec, + /// The hash of [`Self::code`]. hash: Vec, + /// The path where this blob was found. + path: PathBuf, + /// The `spec_name` found in the runtime version of this blob. + spec_name: String, + /// When was the last time we have warned about the wasm blob having + /// a wrong `spec_name`? + last_warn: parking_lot::Mutex>, } impl WasmBlob { - fn new(code: Vec) -> Self { - let hash = make_hash(&code); - Self { code, hash } + fn new(code: Vec, hash: Vec, path: PathBuf, spec_name: String) -> Self { + Self { code, hash, path, spec_name, last_warn: Default::default() } } fn runtime_code(&self, heap_pages: Option) -> RuntimeCode { @@ -103,7 +117,7 @@ impl From for sp_blockchain::Error { /// Scrapes WASM from a folder and returns WASM from that folder /// if the runtime spec version matches. -#[derive(Clone, Debug)] +#[derive(Debug)] pub struct WasmOverride { // Map of runtime spec version -> Wasm Blob overrides: HashMap, @@ -122,8 +136,35 @@ impl WasmOverride { /// Gets an override by it's runtime spec version. /// /// Returns `None` if an override for a spec version does not exist. - pub fn get<'a, 'b: 'a>(&'b self, spec: &u32, pages: Option) -> Option> { - self.overrides.get(spec).map(|w| w.runtime_code(pages)) + pub fn get<'a, 'b: 'a>( + &'b self, + spec: &u32, + pages: Option, + spec_name: &str, + ) -> Option> { + self.overrides.get(spec).and_then(|w| { + if spec_name == w.spec_name { + Some(w.runtime_code(pages)) + } else { + let mut last_warn = w.last_warn.lock(); + let now = Instant::now(); + + if last_warn.map_or(true, |l| l + WARN_INTERVAL <= now) { + *last_warn = Some(now); + + tracing::warn!( + target = "wasm_overrides", + on_chain_spec_name = %spec_name, + override_spec_name = %w.spec_name, + spec_version = %spec, + wasm_file = %w.path.display(), + "On chain and override `spec_name` do not match! Ignoring override.", + ); + } + + None + } + }) } /// Scrapes a folder for WASM runtimes. @@ -147,22 +188,29 @@ impl WasmOverride { let path = entry.path(); match path.extension().map(|e| e.to_str()).flatten() { Some("wasm") => { - let wasm = WasmBlob::new(fs::read(&path).map_err(handle_err)?); - let version = Self::runtime_version(executor, &wasm, Some(128))?; - log::info!( + let code = fs::read(&path).map_err(handle_err)?; + let code_hash = make_hash(&code); + let version = Self::runtime_version(executor, &code, &code_hash, Some(128))?; + + tracing::info!( target: "wasm_overrides", - "Found wasm override in file: `{:?}`, version: {}", - path.to_str(), - version, + version = %version, + file = %path.display(), + "Found wasm override.", ); - if let Some(_duplicate) = overrides.insert(version.spec_version, wasm) { - log::info!( + + let wasm = + WasmBlob::new(code, code_hash, path.clone(), version.spec_name.to_string()); + + if let Some(other) = overrides.insert(version.spec_version, wasm) { + tracing::info!( target: "wasm_overrides", - "Found duplicate spec version for runtime in file: `{:?}`, version: {}", - path.to_str(), - version, + first = %other.path.display(), + second = %path.display(), + %version, + "Found duplicate spec version for runtime.", ); - duplicates.push(format!("{}", path.display())); + duplicates.push(path.display().to_string()); } }, _ => (), @@ -178,7 +226,8 @@ impl WasmOverride { fn runtime_version( executor: &E, - code: &WasmBlob, + code: &[u8], + code_hash: &[u8], heap_pages: Option, ) -> Result where @@ -186,7 +235,14 @@ impl WasmOverride { { let mut ext = BasicExternalities::default(); executor - .runtime_version(&mut ext, &code.runtime_code(heap_pages)) + .runtime_version( + &mut ext, + &RuntimeCode { + code_fetcher: &WrappedRuntimeCode(code.into()), + heap_pages, + hash: code_hash.into(), + }, + ) .map_err(|e| WasmOverrideError::VersionInvalid(format!("{:?}", e)).into()) } } @@ -195,9 +251,18 @@ impl WasmOverride { #[cfg(test)] pub fn dummy_overrides() -> WasmOverride { let mut overrides = HashMap::new(); - overrides.insert(0, WasmBlob::new(vec![0, 0, 0, 0, 0, 0, 0, 0])); - overrides.insert(1, WasmBlob::new(vec![1, 1, 1, 1, 1, 1, 1, 1])); - overrides.insert(2, WasmBlob::new(vec![2, 2, 2, 2, 2, 2, 2, 2])); + overrides.insert( + 0, + WasmBlob::new(vec![0, 0, 0, 0, 0, 0, 0, 0], vec![0], PathBuf::new(), "test".into()), + ); + overrides.insert( + 1, + WasmBlob::new(vec![1, 1, 1, 1, 1, 1, 1, 1], vec![1], PathBuf::new(), "test".into()), + ); + overrides.insert( + 2, + WasmBlob::new(vec![2, 2, 2, 2, 2, 2, 2, 2], vec![2], PathBuf::new(), "test".into()), + ); WasmOverride { overrides } } @@ -226,15 +291,19 @@ mod tests { #[test] fn should_get_runtime_version() { - let wasm = WasmBlob::new(substrate_test_runtime::wasm_binary_unwrap().to_vec()); let executor = NativeElseWasmExecutor::::new( WasmExecutionMethod::Interpreted, Some(128), 1, ); - let version = WasmOverride::runtime_version(&executor, &wasm, Some(128)) - .expect("should get the `RuntimeVersion` of the test-runtime wasm blob"); + let version = WasmOverride::runtime_version( + &executor, + substrate_test_runtime::wasm_binary_unwrap(), + &[1], + Some(128), + ) + .expect("should get the `RuntimeVersion` of the test-runtime wasm blob"); assert_eq!(version.spec_version, 2); } diff --git a/primitives/runtime/src/runtime_string.rs b/primitives/runtime/src/runtime_string.rs index 179e88145181..a69e85418d82 100644 --- a/primitives/runtime/src/runtime_string.rs +++ b/primitives/runtime/src/runtime_string.rs @@ -92,6 +92,18 @@ impl AsRef<[u8]> for RuntimeString { } } +#[cfg(feature = "std")] +impl std::ops::Deref for RuntimeString { + type Target = str; + + fn deref(&self) -> &str { + match self { + Self::Borrowed(val) => &val, + Self::Owned(val) => &val, + } + } +} + impl Encode for RuntimeString { fn encode(&self) -> Vec { match self { From 205069d0540973362902aa2ad68af924bfdf2a3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Fri, 3 Dec 2021 16:11:06 +0100 Subject: [PATCH 252/695] Fix cumulus companion checks (#10412) * Fix cumulus companion checks * Add missing tag * Fix * Update .gitlab-ci.yml Co-authored-by: Denis Pisarev <17856421+TriplEight@users.noreply.github.com> Co-authored-by: Shawn Tabrizi Co-authored-by: Denis Pisarev <17856421+TriplEight@users.noreply.github.com> --- .gitlab-ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b1987b834fef..f4391cf7d312 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -46,6 +46,7 @@ variables: &default-vars VAULT_AUTH_PATH: "gitlab-parity-io-jwt" VAULT_AUTH_ROLE: "cicd_gitlab_parity_${CI_PROJECT_NAME}" SIMNET_FEATURES_PATH: "simnet_tests/tests" + PIPELINE_SCRIPTS_TAG: "v0.4" default: cache: {} @@ -606,6 +607,7 @@ cargo-check-macos: --substrate "$DEPENDENT_REPO" "$GITHUB_PR_TOKEN" + "$CARGO_UPDATE_CRATES" # Individual jobs are set up for each dependent project so that they can be ran in parallel. # Arguably we could generate a job for each companion in the PR's description using Gitlab's @@ -615,11 +617,13 @@ check-dependent-polkadot: <<: *check-dependent-project variables: DEPENDENT_REPO: polkadot + CARGO_UPDATE_CRATES: "sp-io" check-dependent-cumulus: <<: *check-dependent-project variables: DEPENDENT_REPO: cumulus + CARGO_UPDATE_CRATES: "sp-io polkadot-runtime-common" build-linux-substrate: From a2f24d5d721e158a8aefa50c6022ee9acfeeb975 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Fri, 3 Dec 2021 19:50:23 +0100 Subject: [PATCH 253/695] No longer include :code and :heappages in execution proofs (#10419) * No longer include :code and :heap_pages in execution proofs * Oops, forgot the line * Rustfmt --- client/service/src/client/client.rs | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/client/service/src/client/client.rs b/client/service/src/client/client.rs index b46c6b99b9a9..833d8b7bc225 100644 --- a/client/service/src/client/client.rs +++ b/client/service/src/client/client.rs @@ -1085,18 +1085,7 @@ where method: &str, call_data: &[u8], ) -> sp_blockchain::Result<(Vec, StorageProof)> { - // Make sure we include the `:code` and `:heap_pages` in the execution proof to be - // backwards compatible. - // - // TODO: Remove when solved: https://github.com/paritytech/substrate/issues/5047 - let code_proof = self.read_proof( - id, - &mut [well_known_keys::CODE, well_known_keys::HEAP_PAGES].iter().map(|v| *v), - )?; - - self.executor - .prove_execution(id, method, call_data) - .map(|(r, p)| (r, StorageProof::merge(vec![p, code_proof]))) + self.executor.prove_execution(id, method, call_data) } fn read_proof_collection( From e9ebf0c00fde8657a3a5989ad099e6272427ddd2 Mon Sep 17 00:00:00 2001 From: Devdutt Shenoi Date: Sat, 4 Dec 2021 03:18:11 +0530 Subject: [PATCH 254/695] Optimize encoded-size of `SignedCommitment` (#10409) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Include code from paritytech/grandpa-bridge-gadget#186 * Cargo fmt commitment.rs * Make changes suggested by @tomusdrw Co-authored-by: Tomasz Drwięga --- primitives/beefy/src/commitment.rs | 212 ++++++++++++++++++++++++++++- 1 file changed, 205 insertions(+), 7 deletions(-) diff --git a/primitives/beefy/src/commitment.rs b/primitives/beefy/src/commitment.rs index 667c03cc2284..6553f6ffc905 100644 --- a/primitives/beefy/src/commitment.rs +++ b/primitives/beefy/src/commitment.rs @@ -15,7 +15,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use codec::{Decode, Encode}; +use codec::{Decode, Encode, Error, Input}; use sp_std::{cmp, prelude::*}; use crate::{crypto::Signature, ValidatorSetId}; @@ -80,7 +80,7 @@ impl Payload { /// height [block_number](Commitment::block_number). /// GRANDPA validators collect signatures on commitments and a stream of such signed commitments /// (see [SignedCommitment]) forms the BEEFY protocol. -#[derive(Clone, Debug, PartialEq, Eq, codec::Encode, codec::Decode)] +#[derive(Clone, Debug, PartialEq, Eq, Encode, Decode)] pub struct Commitment { /// A collection of payloads to be signed, see [`Payload`] for details. /// @@ -134,7 +134,11 @@ where } /// A commitment with matching GRANDPA validators' signatures. -#[derive(Clone, Debug, PartialEq, Eq, codec::Encode, codec::Decode)] +/// +/// Note that SCALE-encoding of the structure is optimized for size efficiency over the wire, +/// please take a look at custom [`Encode`] and [`Decode`] implementations and +/// [`CompactSignedCommitment`] struct. +#[derive(Clone, Debug, PartialEq, Eq)] pub struct SignedCommitment { /// The commitment signatures are collected for. pub commitment: Commitment, @@ -152,6 +156,126 @@ impl SignedCommitment { } } +/// Type to be used to denote placement of signatures +type BitField = Vec; +/// Compress 8 bit values into a single u8 Byte +const CONTAINER_BIT_SIZE: usize = 8; + +/// Compressed representation of [`SignedCommitment`], used for encoding efficiency. +#[derive(Clone, Debug, PartialEq, Eq, Encode, Decode)] +struct CompactSignedCommitment { + /// The commitment, unchanged compared to regular [`SignedCommitment`]. + commitment: TCommitment, + /// A bitfield representing presence of a signature coming from a validator at some index. + /// + /// The bit at index `0` is set to `1` in case we have a signature coming from a validator at + /// index `0` in in the original validator set. In case the [`SignedCommitment`] does not + /// contain that signature the `bit` will be set to `0`. Bits are packed into `Vec` + signatures_from: BitField, + /// Number of validators in the Validator Set and hence number of significant bits in the + /// [`signatures_from`] collection. + /// + /// Note this might be smaller than the size of `signatures_compact` in case some signatures + /// are missing. + validator_set_len: u32, + /// A `Vec` containing all `Signature`s present in the original [`SignedCommitment`]. + /// + /// Note that in order to associate a `Signature` from this `Vec` with a validator, one needs + /// to look at the `signatures_from` bitfield, since some validators might have not produced a + /// signature. + signatures_compact: Vec, +} + +impl<'a, TBlockNumber> CompactSignedCommitment<&'a Commitment> { + /// Packs a `SignedCommitment` into the compressed `CompactSignedCommitment` format for + /// efficient network transport. + fn pack(signed_commitment: &'a SignedCommitment) -> Self { + let SignedCommitment { commitment, signatures } = signed_commitment; + let validator_set_len = signatures.len() as u32; + let mut signatures_from: BitField = vec![]; + let mut signatures_compact: Vec = vec![]; + + for signature in signatures { + match signature { + Some(value) => signatures_compact.push(value.clone()), + None => (), + } + } + + let mut bits: Vec = + signatures.iter().map(|x| if x.is_some() { 1 } else { 0 }).collect(); + + // Resize with excess bits for placement purposes + let excess_bits_len = + CONTAINER_BIT_SIZE - (validator_set_len as usize % CONTAINER_BIT_SIZE); + bits.resize(bits.len() + excess_bits_len, 0); + + let chunks = bits.chunks(CONTAINER_BIT_SIZE); + for chunk in chunks { + let mut iter = chunk.iter().copied(); + let mut v = iter.next().unwrap() as u8; + + for bit in iter { + v <<= 1; + v |= bit as u8; + } + + signatures_from.push(v); + } + + Self { commitment, signatures_from, validator_set_len, signatures_compact } + } + + /// Unpacks a `CompactSignedCommitment` into the uncompressed `SignedCommitment` form. + fn unpack( + temporary_signatures: CompactSignedCommitment>, + ) -> SignedCommitment { + let CompactSignedCommitment { + commitment, + signatures_from, + validator_set_len, + signatures_compact, + } = temporary_signatures; + let mut bits: Vec = vec![]; + + for block in signatures_from { + for bit in 0..CONTAINER_BIT_SIZE { + bits.push((block >> (CONTAINER_BIT_SIZE - bit - 1)) & 1); + } + } + + bits.truncate(validator_set_len as usize); + + let mut next_signature = signatures_compact.into_iter(); + let signatures: Vec> = bits + .iter() + .map(|&x| if x == 1 { next_signature.next() } else { None }) + .collect(); + + SignedCommitment { commitment, signatures } + } +} + +impl Encode for SignedCommitment +where + TBlockNumber: Encode, +{ + fn using_encoded R>(&self, f: F) -> R { + let temp = CompactSignedCommitment::pack(self); + temp.using_encoded(f) + } +} + +impl Decode for SignedCommitment +where + TBlockNumber: Decode, +{ + fn decode(input: &mut I) -> Result { + let temp = CompactSignedCommitment::decode(input)?; + Ok(CompactSignedCommitment::unpack(temp)) + } +} + /// A [SignedCommitment] with a version number. This variant will be appended /// to the block justifications for the block for which the signed commitment /// has been generated. @@ -244,10 +368,10 @@ mod tests { encoded, hex_literal::hex!( "046d68343048656c6c6f20576f726c6421050000000000000000000000000000000000000000000000 - 10000001558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321 - f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01012d6e1f8105c337a86cdd9aaa - cdc496577f3db8c55ef9e6fd48f2c5c05a2274707491635d8ba3df64f324575b7b2a34487bca2324b6a - 0046395a71681be3d0c2a00" + 04300400000008558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746 + cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba012d6e1f8105c337a86cdd9a + aacdc496577f3db8c55ef9e6fd48f2c5c05a2274707491635d8ba3df64f324575b7b2a34487bca2324b + 6a0046395a71681be3d0c2a00" ) ); } @@ -322,4 +446,78 @@ mod tests { assert_eq!(decoded, Ok(versioned)); } + + #[test] + fn large_signed_commitment_encode_decode() { + // given + let payload = Payload::new(known_payload_ids::MMR_ROOT_ID, "Hello World!".encode()); + let commitment: TestCommitment = + Commitment { payload, block_number: 5, validator_set_id: 0 }; + + let sigs = mock_signatures(); + + let signatures: Vec> = (0..1024) + .into_iter() + .map(|x| if x < 340 { None } else { Some(sigs.0.clone()) }) + .collect(); + let signed = SignedCommitment { commitment, signatures }; + + // when + let encoded = codec::Encode::encode(&signed); + let decoded = TestSignedCommitment::decode(&mut &*encoded); + + // then + assert_eq!(decoded, Ok(signed)); + assert_eq!( + encoded, + hex_literal::hex!( + "046d68343048656c6c6f20576f726c6421050000000000000000000000000000000000000000000000 + 05020000000000000000000000000000000000000000000000000000000000000000000000000000000 + 000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + fffffffffff0000040000b10a558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed + 4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad812 + 79df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d1 + 0dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2 + ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01 + 558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e9 + 9a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72 + d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bc + b7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc3 + 21f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc9855 + 80e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0 + c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da + 8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279d + f0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd + 3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac8 + 0a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558 + 455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a8 + 30e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d94 + 8d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb78 + 16f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f + 2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e + 4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33 + c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da848 + 0c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df07 + 95cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd + 68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a0 + 9abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455 + ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e + 314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1 + 107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f + 9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f231 + 9a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb + 75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86 + e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c7 + 46cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795c + c985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68c + e3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09ab + ed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad8 + 1279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314 + d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107 + b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba + 01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01" + ) + ); + } } From 6d09a45caf40a143791deab4f605b95230b787d1 Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Sat, 4 Dec 2021 07:11:25 +0100 Subject: [PATCH 255/695] allow try-runtime and `TestExternalities` to report PoV size (#10372) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * allow try-runtime and test-externalities to report proof size * self review * fix test * Fix humanized dispaly of bytes * Fix some test * Fix some review grumbles * last of the review comments * fmt * remove unused import * move test * fix import * Update primitives/state-machine/src/testing.rs Co-authored-by: Bastian Köcher * last touches * fix Co-authored-by: Bastian Köcher --- Cargo.lock | 2 + primitives/runtime/Cargo.toml | 1 + primitives/runtime/src/lib.rs | 47 ++ primitives/state-machine/src/lib.rs | 3 + .../state-machine/src/proving_backend.rs | 9 +- primitives/state-machine/src/testing.rs | 34 +- primitives/storage/src/lib.rs | 26 +- primitives/trie/src/storage_proof.rs | 6 +- utils/frame/remote-externalities/src/lib.rs | 561 +++++++++++++++--- .../test_data/{proxy_test => proxy_test.top} | Bin utils/frame/try-runtime/cli/Cargo.toml | 2 + .../cli/src/commands/execute_block.rs | 4 +- .../cli/src/commands/follow_chain.rs | 4 +- .../cli/src/commands/on_runtime_upgrade.rs | 4 +- utils/frame/try-runtime/cli/src/lib.rs | 102 +++- 15 files changed, 688 insertions(+), 117 deletions(-) rename utils/frame/remote-externalities/test_data/{proxy_test => proxy_test.top} (100%) diff --git a/Cargo.lock b/Cargo.lock index fbdf0297d453..d277db3f519b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9650,6 +9650,7 @@ dependencies = [ "sp-std", "sp-tracing", "substrate-test-runtime-client", + "zstd", ] [[package]] @@ -10925,6 +10926,7 @@ dependencies = [ "sp-state-machine", "sp-version", "structopt", + "zstd", ] [[package]] diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 7966bb28255b..511d3c1e3792 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -38,6 +38,7 @@ sp-state-machine = { version = "0.10.0-dev", path = "../state-machine" } sp-api = { version = "4.0.0-dev", path = "../api" } substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } sp-tracing = { version = "4.0.0-dev", path = "../../primitives/tracing" } +zstd = "0.9" [features] bench = [] diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 80293fe73484..8cd15b51a32c 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -916,9 +916,13 @@ impl TransactionOutcome { #[cfg(test)] mod tests { + use crate::traits::BlakeTwo256; + use super::*; use codec::{Decode, Encode}; use sp_core::crypto::Pair; + use sp_io::TestExternalities; + use sp_state_machine::create_proof_check_backend; #[test] fn opaque_extrinsic_serialization() { @@ -1019,4 +1023,47 @@ mod tests { panic!("Hey, I'm an error"); }); } + + #[test] + fn execute_and_generate_proof_works() { + use codec::Encode; + use sp_state_machine::Backend; + let mut ext = TestExternalities::default(); + + ext.insert(b"a".to_vec(), vec![1u8; 33]); + ext.insert(b"b".to_vec(), vec![2u8; 33]); + ext.insert(b"c".to_vec(), vec![3u8; 33]); + ext.insert(b"d".to_vec(), vec![4u8; 33]); + + let pre_root = ext.backend.root().clone(); + let (_, proof) = ext.execute_and_prove(|| { + sp_io::storage::get(b"a"); + sp_io::storage::get(b"b"); + sp_io::storage::get(b"v"); + sp_io::storage::get(b"d"); + }); + + let compact_proof = proof.clone().into_compact_proof::(pre_root).unwrap(); + let compressed_proof = zstd::stream::encode_all(&compact_proof.encode()[..], 0).unwrap(); + + // just an example of how you'd inspect the size of the proof. + println!("proof size: {:?}", proof.encoded_size()); + println!("compact proof size: {:?}", compact_proof.encoded_size()); + println!("zstd-compressed compact proof size: {:?}", &compressed_proof.len()); + + // create a new trie-backed from the proof and make sure it contains everything + let proof_check = create_proof_check_backend::(pre_root, proof).unwrap(); + assert_eq!(proof_check.storage(b"a",).unwrap().unwrap(), vec![1u8; 33]); + + let _ = ext.execute_and_prove(|| { + sp_io::storage::set(b"a", &vec![1u8; 44]); + }); + + // ensure that these changes are propagated to the backend. + + ext.execute_with(|| { + assert_eq!(sp_io::storage::get(b"a").unwrap(), vec![1u8; 44]); + assert_eq!(sp_io::storage::get(b"b").unwrap(), vec![2u8; 33]); + }); + } } diff --git a/primitives/state-machine/src/lib.rs b/primitives/state-machine/src/lib.rs index f7477e232bc6..e5c19f3bb0d5 100644 --- a/primitives/state-machine/src/lib.rs +++ b/primitives/state-machine/src/lib.rs @@ -188,6 +188,9 @@ mod execution { /// Trie backend with in-memory storage. pub type InMemoryBackend = TrieBackend, H>; + /// Proving Trie backend with in-memory storage. + pub type InMemoryProvingBackend<'a, H> = ProvingBackend<'a, MemoryDB, H>; + /// Strategy for executing a call into the runtime. #[derive(Copy, Clone, Eq, PartialEq, Debug)] pub enum ExecutionStrategy { diff --git a/primitives/state-machine/src/proving_backend.rs b/primitives/state-machine/src/proving_backend.rs index 690266dab1e7..a354adaf697d 100644 --- a/primitives/state-machine/src/proving_backend.rs +++ b/primitives/state-machine/src/proving_backend.rs @@ -221,6 +221,11 @@ where pub fn estimate_encoded_size(&self) -> usize { self.0.essence().backend_storage().proof_recorder.estimate_encoded_size() } + + /// Clear the proof recorded data. + pub fn clear_recorder(&self) { + self.0.essence().backend_storage().proof_recorder.reset() + } } impl<'a, S: 'a + TrieBackendStorage, H: 'a + Hasher> TrieBackendStorage @@ -358,7 +363,9 @@ where } } -/// Create proof check backend. +/// Create a backend used for checking the proof., using `H` as hasher. +/// +/// `proof` and `root` must match, i.e. `root` must be the correct root of `proof` nodes. pub fn create_proof_check_backend( root: H::Out, proof: StorageProof, diff --git a/primitives/state-machine/src/testing.rs b/primitives/state-machine/src/testing.rs index 59a0a5a6837e..890137c43d88 100644 --- a/primitives/state-machine/src/testing.rs +++ b/primitives/state-machine/src/testing.rs @@ -23,8 +23,8 @@ use std::{ }; use crate::{ - backend::Backend, ext::Ext, InMemoryBackend, OverlayedChanges, StorageKey, - StorageTransactionCache, StorageValue, + backend::Backend, ext::Ext, InMemoryBackend, InMemoryProvingBackend, OverlayedChanges, + StorageKey, StorageTransactionCache, StorageValue, }; use hash_db::Hasher; @@ -38,6 +38,7 @@ use sp_core::{ traits::TaskExecutorExt, }; use sp_externalities::{Extension, ExtensionStore, Extensions}; +use sp_trie::StorageProof; /// Simple HashMap-based Externalities impl. pub struct TestExternalities @@ -122,6 +123,13 @@ where self.backend.insert(vec![(None, vec![(k, Some(v))])]); } + /// Insert key/value into backend. + /// + /// This only supports inserting keys in child tries. + pub fn insert_child(&mut self, c: sp_core::storage::ChildInfo, k: StorageKey, v: StorageValue) { + self.backend.insert(vec![(Some(c), vec![(k, Some(v))])]); + } + /// Registers the given extension for this instance. pub fn register_extension(&mut self, ext: E) { self.extensions.register(ext); @@ -171,9 +179,29 @@ where sp_externalities::set_and_run_with_externalities(&mut ext, execute) } + /// Execute the given closure while `self`, with `proving_backend` as backend, is set as + /// externalities. + /// + /// This implementation will wipe the proof recorded in between calls. Consecutive calls will + /// get their own proof from scratch. + pub fn execute_and_prove<'a, R>(&mut self, execute: impl FnOnce() -> R) -> (R, StorageProof) { + let proving_backend = InMemoryProvingBackend::new(&self.backend); + let mut proving_ext = Ext::new( + &mut self.overlay, + &mut self.storage_transaction_cache, + &proving_backend, + Some(&mut self.extensions), + ); + + let outcome = sp_externalities::set_and_run_with_externalities(&mut proving_ext, execute); + let proof = proving_backend.extract_proof(); + + (outcome, proof) + } + /// Execute the given closure while `self` is set as externalities. /// - /// Returns the result of the given closure, if no panics occured. + /// Returns the result of the given closure, if no panics occurred. /// Otherwise, returns `Err`. pub fn execute_with_safe( &mut self, diff --git a/primitives/storage/src/lib.rs b/primitives/storage/src/lib.rs index 1144e258e0e2..c655a9bdc1cf 100644 --- a/primitives/storage/src/lib.rs +++ b/primitives/storage/src/lib.rs @@ -210,6 +210,14 @@ pub mod well_known_keys { /// Prefix of the default child storage keys in the top trie. pub const DEFAULT_CHILD_STORAGE_KEY_PREFIX: &'static [u8] = b":child_storage:default:"; + /// Whether a key is a default child storage key. + /// + /// This is convenience function which basically checks if the given `key` starts + /// with `DEFAULT_CHILD_STORAGE_KEY_PREFIX` and doesn't do anything apart from that. + pub fn is_default_child_storage_key(key: &[u8]) -> bool { + key.starts_with(DEFAULT_CHILD_STORAGE_KEY_PREFIX) + } + /// Whether a key is a child storage key. /// /// This is convenience function which basically checks if the given `key` starts @@ -231,7 +239,7 @@ pub mod well_known_keys { /// Information related to a child state. #[derive(Debug, Clone)] -#[cfg_attr(feature = "std", derive(PartialEq, Eq, Hash, PartialOrd, Ord))] +#[cfg_attr(feature = "std", derive(PartialEq, Eq, Hash, PartialOrd, Ord, Encode, Decode))] pub enum ChildInfo { /// This is the one used by default. ParentKeyId(ChildTrieParentKeyId), @@ -370,16 +378,14 @@ impl ChildType { } /// A child trie of default type. -/// It uses the same default implementation as the top trie, -/// top trie being a child trie with no keyspace and no storage key. -/// Its keyspace is the variable (unprefixed) part of its storage key. -/// It shares its trie nodes backend storage with every other -/// child trie, so its storage key needs to be a unique id -/// that will be use only once. -/// Those unique id also required to be long enough to avoid any -/// unique id to be prefixed by an other unique id. +/// +/// It uses the same default implementation as the top trie, top trie being a child trie with no +/// keyspace and no storage key. Its keyspace is the variable (unprefixed) part of its storage key. +/// It shares its trie nodes backend storage with every other child trie, so its storage key needs +/// to be a unique id that will be use only once. Those unique id also required to be long enough to +/// avoid any unique id to be prefixed by an other unique id. #[derive(Debug, Clone)] -#[cfg_attr(feature = "std", derive(PartialEq, Eq, Hash, PartialOrd, Ord))] +#[cfg_attr(feature = "std", derive(PartialEq, Eq, Hash, PartialOrd, Ord, Encode, Decode))] pub struct ChildTrieParentKeyId { /// Data is the storage key without prefix. data: Vec, diff --git a/primitives/trie/src/storage_proof.rs b/primitives/trie/src/storage_proof.rs index cfdb8566ea75..91f2159f2957 100644 --- a/primitives/trie/src/storage_proof.rs +++ b/primitives/trie/src/storage_proof.rs @@ -67,6 +67,7 @@ impl StorageProof { pub fn into_nodes(self) -> Vec> { self.trie_nodes } + /// Creates a `MemoryDB` from `Self`. pub fn into_memory_db(self) -> crate::MemoryDB { self.into() @@ -100,8 +101,9 @@ impl StorageProof { /// Returns the estimated encoded size of the compact proof. /// - /// Runing this operation is a slow operation (build the whole compact proof) and should only be - /// in non sensitive path. + /// Running this operation is a slow operation (build the whole compact proof) and should only + /// be in non sensitive path. + /// /// Return `None` on error. pub fn encoded_compact_size(self, root: H::Out) -> Option { let compact_proof = self.into_compact_proof::(root); diff --git a/utils/frame/remote-externalities/src/lib.rs b/utils/frame/remote-externalities/src/lib.rs index da715be6b4be..e8453ddcd8f6 100644 --- a/utils/frame/remote-externalities/src/lib.rs +++ b/utils/frame/remote-externalities/src/lib.rs @@ -34,7 +34,10 @@ use serde::de::DeserializeOwned; use sp_core::{ hashing::twox_128, hexdisplay::HexDisplay, - storage::{StorageData, StorageKey}, + storage::{ + well_known_keys::{is_default_child_storage_key, DEFAULT_CHILD_STORAGE_KEY_PREFIX}, + ChildInfo, ChildType, PrefixedStorageKey, StorageData, StorageKey, + }, }; pub use sp_io::TestExternalities; use sp_runtime::traits::Block as BlockT; @@ -45,7 +48,9 @@ use std::{ pub mod rpc_api; -type KeyPair = (StorageKey, StorageData); +type KeyValue = (StorageKey, StorageData); +type TopKeyValues = Vec; +type ChildKeyValues = Vec<(ChildInfo, Vec)>; const LOG_TARGET: &str = "remote-ext"; const DEFAULT_TARGET: &str = "wss://rpc.polkadot.io:443"; @@ -53,6 +58,22 @@ const BATCH_SIZE: usize = 1000; #[rpc(client)] pub trait RpcApi { + #[method(name = "childstate_getKeys")] + fn child_get_keys( + &self, + child_key: PrefixedStorageKey, + prefix: StorageKey, + hash: Option, + ) -> Result, RpcError>; + + #[method(name = "childstate_getStorage")] + fn child_get_storage( + &self, + child_key: PrefixedStorageKey, + prefix: StorageKey, + hash: Option, + ) -> Result; + #[method(name = "state_getStorage")] fn get_storage(&self, prefix: StorageKey, hash: Option) -> Result; @@ -180,7 +201,7 @@ impl Default for SnapshotConfig { pub struct Builder { /// Custom key-pairs to be injected into the externalities. The *hashed* keys and values must /// be given. - hashed_key_values: Vec, + hashed_key_values: Vec, /// Storage entry key prefixes to be injected into the externalities. The *hashed* prefix must /// be given. hashed_prefixes: Vec>, @@ -234,21 +255,22 @@ impl Builder { ) -> Result { trace!(target: LOG_TARGET, "rpc: get_storage"); self.as_online().rpc_client().get_storage(key, maybe_at).await.map_err(|e| { - error!("Error = {:?}", e); + error!(target: LOG_TARGET, "Error = {:?}", e); "rpc get_storage failed." }) } + /// Get the latest finalized head. async fn rpc_get_head(&self) -> Result { trace!(target: LOG_TARGET, "rpc: finalized_head"); self.as_online().rpc_client().finalized_head().await.map_err(|e| { - error!("Error = {:?}", e); + error!(target: LOG_TARGET, "Error = {:?}", e); "rpc finalized_head failed." }) } /// Get all the keys at `prefix` at `hash` using the paged, safe RPC methods. - async fn get_keys_paged( + async fn rpc_get_keys_paged( &self, prefix: StorageKey, at: B::Hash, @@ -277,7 +299,7 @@ impl Builder { all_keys.last().expect("all_keys is populated; has .last(); qed"); log::debug!( target: LOG_TARGET, - "new total = {}, full page received: {:?}", + "new total = {}, full page received: {}", all_keys.len(), HexDisplay::from(new_last_key) ); @@ -296,12 +318,12 @@ impl Builder { &self, prefix: StorageKey, at: B::Hash, - ) -> Result, &'static str> { - let keys = self.get_keys_paged(prefix, at).await?; + ) -> Result, &'static str> { + let keys = self.rpc_get_keys_paged(prefix, at).await?; let keys_count = keys.len(); log::debug!(target: LOG_TARGET, "Querying a total of {} keys", keys.len()); - let mut key_values: Vec = vec![]; + let mut key_values: Vec = vec![]; let client = self.as_online().rpc_client(); for chunk_keys in keys.chunks(BATCH_SIZE) { let batch = chunk_keys @@ -318,7 +340,9 @@ impl Builder { ); "batch failed." })?; + assert_eq!(chunk_keys.len(), values.len()); + for (idx, key) in chunk_keys.into_iter().enumerate() { let maybe_value = values[idx].clone(); let value = maybe_value.unwrap_or_else(|| { @@ -341,26 +365,216 @@ impl Builder { Ok(key_values) } + + /// Get the values corresponding to `child_keys` at the given `prefixed_top_key`. + pub(crate) async fn rpc_child_get_storage_paged( + &self, + prefixed_top_key: &StorageKey, + child_keys: Vec, + at: B::Hash, + ) -> Result, &'static str> { + let mut child_kv_inner = vec![]; + for batch_child_key in child_keys.chunks(BATCH_SIZE) { + let batch_request = batch_child_key + .iter() + .cloned() + .map(|key| { + ( + "childstate_getStorage", + rpc_params![ + PrefixedStorageKey::new(prefixed_top_key.as_ref().to_vec()), + key, + at + ], + ) + }) + .collect::>(); + + let batch_response = self + .as_online() + .rpc_client() + .batch_request::>(batch_request) + .await + .map_err(|e| { + log::error!( + target: LOG_TARGET, + "failed to execute batch: {:?}. Error: {:?}", + batch_child_key, + e + ); + "batch failed." + })?; + + assert_eq!(batch_child_key.len(), batch_response.len()); + + for (idx, key) in batch_child_key.into_iter().enumerate() { + let maybe_value = batch_response[idx].clone(); + let value = maybe_value.unwrap_or_else(|| { + log::warn!(target: LOG_TARGET, "key {:?} had none corresponding value.", &key); + StorageData(vec![]) + }); + child_kv_inner.push((key.clone(), value)); + } + } + + Ok(child_kv_inner) + } + + pub(crate) async fn rpc_child_get_keys( + &self, + prefixed_top_key: &StorageKey, + child_prefix: StorageKey, + at: B::Hash, + ) -> Result, &'static str> { + let child_keys = self + .as_online() + .rpc_client() + .child_get_keys( + PrefixedStorageKey::new(prefixed_top_key.as_ref().to_vec()), + child_prefix, + Some(at), + ) + .await + .map_err(|e| { + error!(target: LOG_TARGET, "Error = {:?}", e); + "rpc child_get_keys failed." + })?; + + debug!( + target: LOG_TARGET, + "scraped {} child-keys of the child-bearing top key: {}", + child_keys.len(), + HexDisplay::from(prefixed_top_key) + ); + + Ok(child_keys) + } } // Internal methods impl Builder { - /// Save the given data as state snapshot. - fn save_state_snapshot(&self, data: &[KeyPair], path: &Path) -> Result<(), &'static str> { - log::debug!(target: LOG_TARGET, "writing to state snapshot file {:?}", path); - fs::write(path, data.encode()).map_err(|_| "fs::write failed.")?; + /// Save the given data to the top keys snapshot. + fn save_top_snapshot(&self, data: &[KeyValue], path: &PathBuf) -> Result<(), &'static str> { + let mut path = path.clone(); + let encoded = data.encode(); + path.set_extension("top"); + debug!( + target: LOG_TARGET, + "writing {} bytes to state snapshot file {:?}", + encoded.len(), + path + ); + fs::write(path, encoded).map_err(|_| "fs::write failed.")?; Ok(()) } - /// initialize `Self` from state snapshot. Panics if the file does not exist. - fn load_state_snapshot(&self, path: &Path) -> Result, &'static str> { - log::info!(target: LOG_TARGET, "scraping key-pairs from state snapshot {:?}", path); + /// Save the given data to the child keys snapshot. + fn save_child_snapshot( + &self, + data: &ChildKeyValues, + path: &PathBuf, + ) -> Result<(), &'static str> { + let mut path = path.clone(); + path.set_extension("child"); + let encoded = data.encode(); + debug!( + target: LOG_TARGET, + "writing {} bytes to state snapshot file {:?}", + encoded.len(), + path + ); + fs::write(path, encoded).map_err(|_| "fs::write failed.")?; + Ok(()) + } + + fn load_top_snapshot(&self, path: &PathBuf) -> Result { + let mut path = path.clone(); + path.set_extension("top"); + info!(target: LOG_TARGET, "loading top key-pairs from snapshot {:?}", path); + let bytes = fs::read(path).map_err(|_| "fs::read failed.")?; + Decode::decode(&mut &*bytes).map_err(|e| { + log::error!(target: LOG_TARGET, "{:?}", e); + "decode failed" + }) + } + + fn load_child_snapshot(&self, path: &PathBuf) -> Result { + let mut path = path.clone(); + path.set_extension("child"); + info!(target: LOG_TARGET, "loading child key-pairs from snapshot {:?}", path); let bytes = fs::read(path).map_err(|_| "fs::read failed.")?; - Decode::decode(&mut &*bytes).map_err(|_| "decode failed") + Decode::decode(&mut &*bytes).map_err(|e| { + log::error!(target: LOG_TARGET, "{:?}", e); + "decode failed" + }) + } + + /// Load all the `top` keys from the remote config, and maybe write then to cache. + async fn load_top_remote_and_maybe_save(&self) -> Result { + let top_kv = self.load_top_remote().await?; + if let Some(c) = &self.as_online().state_snapshot { + self.save_top_snapshot(&top_kv, &c.path)?; + } + Ok(top_kv) + } + + /// Load all of the child keys from the remote config, given the already scraped list of top key + /// pairs. + /// + /// Stores all values to cache as well, if provided. + async fn load_child_remote_and_maybe_save( + &self, + top_kv: &[KeyValue], + ) -> Result { + let child_kv = self.load_child_remote(&top_kv).await?; + if let Some(c) = &self.as_online().state_snapshot { + self.save_child_snapshot(&child_kv, &c.path)?; + } + Ok(child_kv) + } + + /// Load all of the child keys from the remote config, given the already scraped list of top key + /// pairs. + /// + /// `top_kv` need not be only child-bearing top keys. It should be all of the top keys that are + /// included thus far. + async fn load_child_remote(&self, top_kv: &[KeyValue]) -> Result { + let child_roots = top_kv + .iter() + .filter_map(|(k, _)| is_default_child_storage_key(k.as_ref()).then(|| k)) + .collect::>(); + + info!( + target: LOG_TARGET, + "👩‍👦 scraping child-tree data from {} top keys", + child_roots.len() + ); + + let mut child_kv = vec![]; + for prefixed_top_key in child_roots { + let at = self.as_online().at.expect("at must be initialized in online mode."); + let child_keys = + self.rpc_child_get_keys(prefixed_top_key, StorageKey(vec![]), at).await?; + let child_kv_inner = + self.rpc_child_get_storage_paged(prefixed_top_key, child_keys, at).await?; + + let prefixed_top_key = PrefixedStorageKey::new(prefixed_top_key.clone().0); + let un_prefixed = match ChildType::from_prefixed_key(&prefixed_top_key) { + Some((ChildType::ParentKeyId, storage_key)) => storage_key, + None => { + log::error!(target: LOG_TARGET, "invalid key: {:?}", prefixed_top_key); + return Err("Invalid child key") + }, + }; + + child_kv.push((ChildInfo::new_default(&un_prefixed), child_kv_inner)); + } + + Ok(child_kv) } /// Build `Self` from a network node denoted by `uri`. - async fn load_remote(&self) -> Result, &'static str> { + async fn load_top_remote(&self) -> Result { let config = self.as_online(); let at = self .as_online() @@ -371,17 +585,17 @@ impl Builder { let mut keys_and_values = if config.pallets.len() > 0 { let mut filtered_kv = vec![]; - for f in config.pallets.iter() { - let hashed_prefix = StorageKey(twox_128(f.as_bytes()).to_vec()); - let module_kv = self.rpc_get_pairs_paged(hashed_prefix.clone(), at).await?; + for p in config.pallets.iter() { + let hashed_prefix = StorageKey(twox_128(p.as_bytes()).to_vec()); + let pallet_kv = self.rpc_get_pairs_paged(hashed_prefix.clone(), at).await?; log::info!( target: LOG_TARGET, - "downloaded data for module {} (count: {} / prefix: {:?}).", - f, - module_kv.len(), + "downloaded data for module {} (count: {} / prefix: {}).", + p, + pallet_kv.len(), HexDisplay::from(&hashed_prefix), ); - filtered_kv.extend(module_kv); + filtered_kv.extend(pallet_kv); } filtered_kv } else { @@ -423,7 +637,10 @@ impl Builder { .max_request_body_size(u32::MAX) .build(&online.transport.uri) .await - .map_err(|_| "failed to build ws client")?; + .map_err(|e| { + log::error!(target: LOG_TARGET, "error: {:?}", e); + "failed to build ws client" + })?; online.transport.client = Some(ws_client); // Then, if `at` is not set, set it. @@ -435,27 +652,21 @@ impl Builder { Ok(()) } - pub(crate) async fn pre_build(mut self) -> Result, &'static str> { - let mut base_kv = match self.mode.clone() { - Mode::Offline(config) => self.load_state_snapshot(&config.state_snapshot.path)?, - Mode::Online(config) => { + pub(crate) async fn pre_build( + mut self, + ) -> Result<(TopKeyValues, ChildKeyValues), &'static str> { + let mut top_kv = match self.mode.clone() { + Mode::Offline(config) => self.load_top_snapshot(&config.state_snapshot.path)?, + Mode::Online(_) => { self.init_remote_client().await?; - let kp = self.load_remote().await?; - if let Some(c) = config.state_snapshot { - self.save_state_snapshot(&kp, &c.path)?; - } - kp + self.load_top_remote_and_maybe_save().await? }, - Mode::OfflineOrElseOnline(offline_config, online_config) => { - if let Ok(kv) = self.load_state_snapshot(&offline_config.state_snapshot.path) { + Mode::OfflineOrElseOnline(offline_config, _) => { + if let Ok(kv) = self.load_top_snapshot(&offline_config.state_snapshot.path) { kv } else { self.init_remote_client().await?; - let kp = self.load_remote().await?; - if let Some(c) = online_config.state_snapshot { - self.save_state_snapshot(&kp, &c.path)?; - } - kp + self.load_top_remote_and_maybe_save().await? } }, }; @@ -467,7 +678,7 @@ impl Builder { "extending externalities with {} manually injected key-values", self.hashed_key_values.len() ); - base_kv.extend(self.hashed_key_values.clone()); + top_kv.extend(self.hashed_key_values.clone()); } // exclude manual key values. @@ -477,10 +688,30 @@ impl Builder { "excluding externalities from {} keys", self.hashed_blacklist.len() ); - base_kv.retain(|(k, _)| !self.hashed_blacklist.contains(&k.0)) + top_kv.retain(|(k, _)| !self.hashed_blacklist.contains(&k.0)) } - Ok(base_kv) + let child_kv = match self.mode.clone() { + Mode::Online(_) => self.load_child_remote_and_maybe_save(&top_kv).await?, + Mode::OfflineOrElseOnline(offline_config, _) => + if let Ok(kv) = self.load_child_snapshot(&offline_config.state_snapshot.path) { + kv + } else { + self.load_child_remote_and_maybe_save(&top_kv).await? + }, + Mode::Offline(ref config) => self + .load_child_snapshot(&config.state_snapshot.path) + .map_err(|why| { + log::warn!( + target: LOG_TARGET, + "failed to load child-key file due to {:?}.", + why + ) + }) + .unwrap_or_default(), + }; + + Ok((top_kv, child_kv)) } } @@ -492,12 +723,13 @@ impl Builder { } /// Inject a manual list of key and values to the storage. - pub fn inject_hashed_key_value(mut self, injections: &[KeyPair]) -> Self { + pub fn inject_hashed_key_value(mut self, injections: &[KeyValue]) -> Self { for i in injections { self.hashed_key_values.push(i.clone()); } self } + /// Inject a hashed prefix. This is treated as-is, and should be pre-hashed. /// /// This should be used to inject a "PREFIX", like a storage (double) map. @@ -506,6 +738,22 @@ impl Builder { self } + /// Just a utility wrapper of [`inject_hashed_prefix`] that injects + /// [`DEFAULT_CHILD_STORAGE_KEY_PREFIX`] as a prefix. + /// + /// If set, this will guarantee that the child-tree data of ALL pallets will be downloaded. + /// + /// This is not needed if the entire state is being downloaded. + /// + /// Otherwise, the only other way to make sure a child-tree is manually included is to inject + /// its root (`DEFAULT_CHILD_STORAGE_KEY_PREFIX`, plus some other postfix) into + /// [`inject_hashed_key`]. Unfortunately, there's no federated way of managing child tree roots + /// as of now and each pallet does its own thing. Therefore, it is not possible for this library + /// to automatically include child trees of pallet X, when its top keys are included. + pub fn inject_default_child_tree_prefix(self) -> Self { + self.inject_hashed_prefix(DEFAULT_CHILD_STORAGE_KEY_PREFIX) + } + /// Inject a hashed key to scrape. This is treated as-is, and should be pre-hashed. /// /// This should be used to inject a "KEY", like a storage value. @@ -540,16 +788,37 @@ impl Builder { /// Build the test externalities. pub async fn build(self) -> Result { - let kv = self.pre_build().await?; - let mut ext = TestExternalities::new_empty(); - - log::info!(target: LOG_TARGET, "injecting a total of {} keys", kv.len()); - for (k, v) in kv { - let (k, v) = (k.0, v.0); - // Insert the key,value pair into the test trie backend - ext.insert(k, v); + let (top_kv, child_kv) = self.pre_build().await?; + let mut ext = TestExternalities::new_with_code(Default::default(), Default::default()); + + info!(target: LOG_TARGET, "injecting a total of {} top keys", top_kv.len()); + for (k, v) in top_kv { + // skip writing the child root data. + if is_default_child_storage_key(k.as_ref()) { + continue + } + ext.insert(k.0, v.0); } + info!( + target: LOG_TARGET, + "injecting a total of {} child keys", + child_kv.iter().map(|(_, kv)| kv).flatten().count() + ); + + for (info, key_values) in child_kv { + for (k, v) in key_values { + ext.insert_child(info.clone(), k.0, v.0); + } + } + + ext.commit_all().unwrap(); + info!( + target: LOG_TARGET, + "initialized state externalities with storage root {:?}", + ext.as_backend().root() + ); + Ok(ext) } } @@ -621,7 +890,6 @@ mod tests { #[cfg(all(test, feature = "remote-test"))] mod remote_tests { use super::test_prelude::*; - use pallet_elections_phragmen::Members; const REMOTE_INACCESSIBLE: &'static str = "Can't reach the remote node. Is it running?"; #[tokio::test] @@ -631,11 +899,11 @@ mod remote_tests { Builder::::new() .mode(Mode::OfflineOrElseOnline( OfflineConfig { - state_snapshot: SnapshotConfig::new("test_snapshot_to_remove.bin"), + state_snapshot: SnapshotConfig::new("offline_else_online_works_data"), }, OnlineConfig { pallets: vec!["Proxy".to_owned()], - state_snapshot: Some(SnapshotConfig::new("test_snapshot_to_remove.bin")), + state_snapshot: Some(SnapshotConfig::new("offline_else_online_works_data")), ..Default::default() }, )) @@ -648,11 +916,11 @@ mod remote_tests { Builder::::new() .mode(Mode::OfflineOrElseOnline( OfflineConfig { - state_snapshot: SnapshotConfig::new("test_snapshot_to_remove.bin"), + state_snapshot: SnapshotConfig::new("offline_else_online_works_data"), }, OnlineConfig { pallets: vec!["Proxy".to_owned()], - state_snapshot: Some(SnapshotConfig::new("test_snapshot_to_remove.bin")), + state_snapshot: Some(SnapshotConfig::new("offline_else_online_works_data")), transport: "ws://non-existent:666".to_owned().into(), ..Default::default() }, @@ -661,14 +929,56 @@ mod remote_tests { .await .expect(REMOTE_INACCESSIBLE) .execute_with(|| {}); + + let to_delete = std::fs::read_dir(Path::new(".")) + .unwrap() + .into_iter() + .map(|d| d.unwrap()) + .filter(|p| { + p.path().file_name().unwrap_or_default() == "offline_else_online_works_data" || + p.path().extension().unwrap_or_default() == "top" || + p.path().extension().unwrap_or_default() == "child" + }) + .collect::>(); + assert!(to_delete.len() > 0); + for d in to_delete { + std::fs::remove_file(d.path()).unwrap(); + } } #[tokio::test] - async fn can_build_one_pallet() { + #[ignore = "too slow"] + async fn can_build_one_big_pallet() { init_logger(); Builder::::new() .mode(Mode::Online(OnlineConfig { - pallets: vec!["Proxy".to_owned()], + pallets: vec!["System".to_owned()], + ..Default::default() + })) + .build() + .await + .expect(REMOTE_INACCESSIBLE) + .execute_with(|| {}); + } + + #[tokio::test] + async fn can_build_one_small_pallet() { + init_logger(); + Builder::::new() + .mode(Mode::Online(OnlineConfig { + transport: "wss://kusama-rpc.polkadot.io:443".to_owned().into(), + pallets: vec!["Council".to_owned()], + ..Default::default() + })) + .build() + .await + .expect(REMOTE_INACCESSIBLE) + .execute_with(|| {}); + + Builder::::new() + .mode(Mode::Online(OnlineConfig { + transport: "wss://rpc.polkadot.io:443".to_owned().into(), + pallets: vec!["Council".to_owned()], ..Default::default() })) .build() @@ -682,6 +992,18 @@ mod remote_tests { init_logger(); Builder::::new() .mode(Mode::Online(OnlineConfig { + transport: "wss://kusama-rpc.polkadot.io:443".to_owned().into(), + pallets: vec!["Proxy".to_owned(), "Multisig".to_owned()], + ..Default::default() + })) + .build() + .await + .expect(REMOTE_INACCESSIBLE) + .execute_with(|| {}); + + Builder::::new() + .mode(Mode::Online(OnlineConfig { + transport: "wss://rpc.polkadot.io:443".to_owned().into(), pallets: vec!["Proxy".to_owned(), "Multisig".to_owned()], ..Default::default() })) @@ -692,49 +1014,70 @@ mod remote_tests { } #[tokio::test] - async fn sanity_check_decoding() { - use sp_core::crypto::Ss58Codec; - - type AccountId = sp_runtime::AccountId32; - type Balance = u128; - frame_support::generate_storage_alias!( - PhragmenElection, - Members => - Value>> - ); + async fn can_create_top_snapshot() { + init_logger(); + Builder::::new() + .mode(Mode::Online(OnlineConfig { + state_snapshot: Some(SnapshotConfig::new("can_create_top_snapshot_data")), + pallets: vec!["Proxy".to_owned()], + ..Default::default() + })) + .build() + .await + .expect(REMOTE_INACCESSIBLE) + .execute_with(|| {}); + + let to_delete = std::fs::read_dir(Path::new(".")) + .unwrap() + .into_iter() + .map(|d| d.unwrap()) + .filter(|p| { + p.path().file_name().unwrap_or_default() == "can_create_top_snapshot_data" || + p.path().extension().unwrap_or_default() == "top" || + p.path().extension().unwrap_or_default() == "child" + }) + .collect::>(); + + assert!(to_delete.len() > 0); + + for d in to_delete { + use std::os::unix::fs::MetadataExt; + if d.path().extension().unwrap_or_default() == "top" { + // if this is the top snapshot it must not be empty. + assert!(std::fs::metadata(d.path()).unwrap().size() > 1); + } else { + // the child is empty for this pallet. + assert!(std::fs::metadata(d.path()).unwrap().size() == 1); + } + std::fs::remove_file(d.path()).unwrap(); + } + } + #[tokio::test] + async fn can_build_child_tree() { init_logger(); Builder::::new() .mode(Mode::Online(OnlineConfig { - pallets: vec!["PhragmenElection".to_owned()], + transport: "wss://rpc.polkadot.io:443".to_owned().into(), + pallets: vec!["Crowdloan".to_owned()], ..Default::default() })) .build() .await .expect(REMOTE_INACCESSIBLE) - .execute_with(|| { - // Gav's polkadot account. 99% this will be in the council. - let gav_polkadot = - AccountId::from_ss58check("13RDY9nrJpyTDBSUdBw12dGwhk19sGwsrVZ2bxkzYHBSagP2") - .unwrap(); - let members = Members::get(); - assert!(members - .iter() - .map(|s| s.who.clone()) - .find(|a| a == &gav_polkadot) - .is_some()); - }); + .execute_with(|| {}); } #[tokio::test] - async fn can_create_state_snapshot() { + async fn can_create_child_snapshot() { init_logger(); Builder::::new() .mode(Mode::Online(OnlineConfig { - state_snapshot: Some(SnapshotConfig::new("test_snapshot_to_remove.bin")), - pallets: vec!["Proxy".to_owned()], + state_snapshot: Some(SnapshotConfig::new("can_create_child_snapshot_data")), + pallets: vec!["Crowdloan".to_owned()], ..Default::default() })) + .inject_default_child_tree_prefix() .build() .await .expect(REMOTE_INACCESSIBLE) @@ -744,24 +1087,62 @@ mod remote_tests { .unwrap() .into_iter() .map(|d| d.unwrap()) - .filter(|p| p.path().extension().unwrap_or_default() == "bin") + .filter(|p| { + p.path().file_name().unwrap_or_default() == "can_create_child_snapshot_data" || + p.path().extension().unwrap_or_default() == "top" || + p.path().extension().unwrap_or_default() == "child" + }) .collect::>(); assert!(to_delete.len() > 0); for d in to_delete { + use std::os::unix::fs::MetadataExt; + // if this is the top snapshot it must not be empty + if d.path().extension().unwrap_or_default() == "child" { + assert!(std::fs::metadata(d.path()).unwrap().size() > 1); + } else { + assert!(std::fs::metadata(d.path()).unwrap().size() > 1); + } std::fs::remove_file(d.path()).unwrap(); } } #[tokio::test] - #[ignore = "takes too much time on average."] async fn can_fetch_all() { init_logger(); Builder::::new() + .mode(Mode::Online(OnlineConfig { + state_snapshot: Some(SnapshotConfig::new("can_fetch_all_data")), + ..Default::default() + })) .build() .await .expect(REMOTE_INACCESSIBLE) .execute_with(|| {}); + + let to_delete = std::fs::read_dir(Path::new(".")) + .unwrap() + .into_iter() + .map(|d| d.unwrap()) + .filter(|p| { + p.path().file_name().unwrap_or_default() == "can_fetch_all_data" || + p.path().extension().unwrap_or_default() == "top" || + p.path().extension().unwrap_or_default() == "child" + }) + .collect::>(); + + assert!(to_delete.len() > 0); + + for d in to_delete { + use std::os::unix::fs::MetadataExt; + // if we download everything, child tree must also be filled. + if d.path().extension().unwrap_or_default() == "child" { + assert!(std::fs::metadata(d.path()).unwrap().size() > 1); + } else { + assert!(std::fs::metadata(d.path()).unwrap().size() > 1); + } + std::fs::remove_file(d.path()).unwrap(); + } } } diff --git a/utils/frame/remote-externalities/test_data/proxy_test b/utils/frame/remote-externalities/test_data/proxy_test.top similarity index 100% rename from utils/frame/remote-externalities/test_data/proxy_test rename to utils/frame/remote-externalities/test_data/proxy_test.top diff --git a/utils/frame/try-runtime/cli/Cargo.toml b/utils/frame/try-runtime/cli/Cargo.toml index 44be678ba381..388b23aeb3eb 100644 --- a/utils/frame/try-runtime/cli/Cargo.toml +++ b/utils/frame/try-runtime/cli/Cargo.toml @@ -32,3 +32,5 @@ sp-version = { version = "4.0.0-dev", path = "../../../../primitives/version" } remote-externalities = { version = "0.10.0-dev", path = "../../remote-externalities" } jsonrpsee = { version = "0.4.1", default-features = false, features = ["ws-client"]} + +zstd = "0.9.0" diff --git a/utils/frame/try-runtime/cli/src/commands/execute_block.rs b/utils/frame/try-runtime/cli/src/commands/execute_block.rs index 216c63d00525..a717b410c2bf 100644 --- a/utils/frame/try-runtime/cli/src/commands/execute_block.rs +++ b/utils/frame/try-runtime/cli/src/commands/execute_block.rs @@ -17,7 +17,7 @@ use crate::{ build_executor, ensure_matching_spec, extract_code, full_extensions, hash_of, local_spec, - state_machine_call, SharedParams, State, LOG_TARGET, + state_machine_call_with_proof, SharedParams, State, LOG_TARGET, }; use remote_externalities::rpc_api; use sc_service::{Configuration, NativeExecutionDispatch}; @@ -167,7 +167,7 @@ where ) .await; - let _ = state_machine_call::( + let _ = state_machine_call_with_proof::( &ext, &executor, execution, diff --git a/utils/frame/try-runtime/cli/src/commands/follow_chain.rs b/utils/frame/try-runtime/cli/src/commands/follow_chain.rs index 70f177dc1f86..09f541c88753 100644 --- a/utils/frame/try-runtime/cli/src/commands/follow_chain.rs +++ b/utils/frame/try-runtime/cli/src/commands/follow_chain.rs @@ -17,7 +17,7 @@ use crate::{ build_executor, ensure_matching_spec, extract_code, full_extensions, local_spec, parse, - state_machine_call, SharedParams, LOG_TARGET, + state_machine_call_with_proof, SharedParams, LOG_TARGET, }; use jsonrpsee::{ types::{traits::SubscriptionClient, Subscription}, @@ -139,7 +139,7 @@ where let state_ext = maybe_state_ext.as_mut().expect("state_ext either existed or was just created"); - let (mut changes, encoded_result) = state_machine_call::( + let (mut changes, encoded_result) = state_machine_call_with_proof::( &state_ext, &executor, execution, diff --git a/utils/frame/try-runtime/cli/src/commands/on_runtime_upgrade.rs b/utils/frame/try-runtime/cli/src/commands/on_runtime_upgrade.rs index 8de3cb3a3200..6343b2b2e3f0 100644 --- a/utils/frame/try-runtime/cli/src/commands/on_runtime_upgrade.rs +++ b/utils/frame/try-runtime/cli/src/commands/on_runtime_upgrade.rs @@ -23,7 +23,7 @@ use sc_service::Configuration; use sp_runtime::traits::{Block as BlockT, NumberFor}; use crate::{ - build_executor, ensure_matching_spec, extract_code, local_spec, state_machine_call, + build_executor, ensure_matching_spec, extract_code, local_spec, state_machine_call_with_proof, SharedParams, State, LOG_TARGET, }; @@ -69,7 +69,7 @@ where .await; } - let (_, encoded_result) = state_machine_call::( + let (_, encoded_result) = state_machine_call_with_proof::( &ext, &executor, execution, diff --git a/utils/frame/try-runtime/cli/src/lib.rs b/utils/frame/try-runtime/cli/src/lib.rs index 8b8c6b2d2bb3..8ea2e39297a9 100644 --- a/utils/frame/try-runtime/cli/src/lib.rs +++ b/utils/frame/try-runtime/cli/src/lib.rs @@ -285,7 +285,7 @@ use sp_runtime::{ traits::{Block as BlockT, NumberFor}, DeserializeOwned, }; -use sp_state_machine::{OverlayedChanges, StateMachine}; +use sp_state_machine::{InMemoryProvingBackend, OverlayedChanges, StateMachine}; use std::{fmt::Debug, path::PathBuf, str::FromStr}; mod commands; @@ -462,6 +462,14 @@ pub enum State { /// The pallets to scrape. If empty, entire chain state will be scraped. #[structopt(short, long, require_delimiter = true)] pallets: Option>, + + /// Fetch the child-keys as well. + /// + /// Default is `false`, if specific `pallets` are specified, true otherwise. In other + /// words, if you scrape the whole state the child tree data is included out of the box. + /// Otherwise, it must be enabled explicitly using this flag. + #[structopt(long, require_delimiter = true)] + child_tree: bool, }, } @@ -477,21 +485,26 @@ impl State { Builder::::new().mode(Mode::Offline(OfflineConfig { state_snapshot: SnapshotConfig::new(snapshot_path), })), - State::Live { snapshot_path, pallets, uri, at } => { + State::Live { snapshot_path, pallets, uri, at, child_tree } => { let at = match at { Some(at_str) => Some(hash_of::(at_str)?), None => None, }; - Builder::::new() + let mut builder = Builder::::new() .mode(Mode::Online(OnlineConfig { transport: uri.to_owned().into(), state_snapshot: snapshot_path.as_ref().map(SnapshotConfig::new), - pallets: pallets.to_owned().unwrap_or_default(), + pallets: pallets.clone().unwrap_or_default(), at, + ..Default::default() })) .inject_hashed_key( &[twox_128(b"System"), twox_128(b"LastRuntimeUpgrade")].concat(), - ) + ); + if *child_tree { + builder = builder.inject_default_child_tree_prefix(); + } + builder }, }) } @@ -697,6 +710,85 @@ pub(crate) fn state_machine_call( + ext: &TestExternalities, + executor: &NativeElseWasmExecutor, + execution: sc_cli::ExecutionStrategy, + method: &'static str, + data: &[u8], + extensions: Extensions, +) -> sc_cli::Result<(OverlayedChanges, Vec)> { + use parity_scale_codec::Encode; + use sp_core::hexdisplay::HexDisplay; + + let mut changes = Default::default(); + let backend = ext.backend.clone(); + let proving_backend = InMemoryProvingBackend::new(&backend); + + let runtime_code_backend = sp_state_machine::backend::BackendRuntimeCode::new(&proving_backend); + let runtime_code = runtime_code_backend.runtime_code()?; + + let pre_root = backend.root().clone(); + + let encoded_results = StateMachine::new( + &proving_backend, + &mut changes, + executor, + method, + data, + extensions, + &runtime_code, + sp_core::testing::TaskExecutor::new(), + ) + .execute(execution.into()) + .map_err(|e| format!("failed to execute {}: {:?}", method, e)) + .map_err::(Into::into)?; + + let proof = proving_backend.extract_proof(); + let proof_size = proof.encoded_size(); + let compact_proof = proof + .clone() + .into_compact_proof::(pre_root) + .map_err(|e| format!("failed to generate compact proof {}: {:?}", method, e))?; + + let compact_proof_size = compact_proof.encoded_size(); + let compressed_proof = zstd::stream::encode_all(&compact_proof.encode()[..], 0) + .map_err(|e| format!("failed to generate compact proof {}: {:?}", method, e))?; + + let proof_nodes = proof.into_nodes(); + + let humanize = |s| { + if s < 1024 * 1024 { + format!("{:.2} KB ({} bytes)", s as f64 / 1024f64, s) + } else { + format!( + "{:.2} MB ({} KB) ({} bytes)", + s as f64 / (1024f64 * 1024f64), + s as f64 / 1024f64, + s + ) + } + }; + log::info!( + target: LOG_TARGET, + "proof: {} / {} nodes", + HexDisplay::from(&proof_nodes.iter().flatten().cloned().collect::>()), + proof_nodes.len() + ); + log::info!(target: LOG_TARGET, "proof size: {}", humanize(proof_size)); + log::info!(target: LOG_TARGET, "compact proof size: {}", humanize(compact_proof_size),); + log::info!( + target: LOG_TARGET, + "zstd-compressed compact proof {}", + humanize(compressed_proof.len()), + ); + Ok((changes, encoded_results)) +} + /// Get the spec `(name, version)` from the local runtime. pub(crate) fn local_spec( ext: &TestExternalities, From 76d34c44bdc137beff9aabcd965b7302ba9abc4c Mon Sep 17 00:00:00 2001 From: wigy <1888808+wigy-opensource-developer@users.noreply.github.com> Date: Sun, 5 Dec 2021 20:17:14 +0100 Subject: [PATCH 256/695] Authentication of PeerIds in authority discovery records (#10317) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Consolidating test and production code * Signing/verifying authority discovery records with PeerId Unsigned records cannot be rejected yet, they just produce a warning in the log. * Upgrading to libp2p 0.40 * libp2p::identity and sp_core::crypto Ed25519 are compatible * Rejecting authority records unsigned by peer id can be configured * Fixes based on review comments * No command-line argument needed * info was still too much spam in the logs * Added tests for both strict and loose validation * Fixing based on review comments * Pierre preferred a signing method * Ooops, I need to slow down * Update bin/node/cli/src/service.rs * Reexport libp2p crypto used in sc-network * Added proto3 compatibility tests. And import noise. Co-authored-by: Bastian Köcher --- client/authority-discovery/README.md | 4 +- client/authority-discovery/build.rs | 6 +- client/authority-discovery/src/error.rs | 8 + client/authority-discovery/src/lib.rs | 6 + client/authority-discovery/src/tests.rs | 29 ++ client/authority-discovery/src/worker.rs | 238 +++++++++---- .../worker/schema/{dht.proto => dht-v1.proto} | 4 +- .../src/worker/schema/dht-v2.proto | 23 ++ .../src/worker/schema/tests.rs | 90 +++++ .../authority-discovery/src/worker/tests.rs | 330 ++++++++++++------ client/keystore/src/local.rs | 4 +- client/network/src/lib.rs | 5 +- client/network/src/service.rs | 32 +- client/network/src/service/signature.rs | 50 +++ 14 files changed, 633 insertions(+), 196 deletions(-) rename client/authority-discovery/src/worker/schema/{dht.proto => dht-v1.proto} (90%) create mode 100644 client/authority-discovery/src/worker/schema/dht-v2.proto create mode 100644 client/authority-discovery/src/worker/schema/tests.rs create mode 100644 client/network/src/service/signature.rs diff --git a/client/authority-discovery/README.md b/client/authority-discovery/README.md index 54c51d5ba04f..042e8f5982cd 100644 --- a/client/authority-discovery/README.md +++ b/client/authority-discovery/README.md @@ -1,4 +1,4 @@ -Substrate authority discovery. +# Substrate authority discovery This crate enables Substrate authorities to discover and directly connect to other authorities. It is split into two components the [`Worker`] and the @@ -6,4 +6,4 @@ other authorities. It is split into two components the [`Worker`] and the See [`Worker`] and [`Service`] for more documentation. -License: GPL-3.0-or-later WITH Classpath-exception-2.0 \ No newline at end of file +License: GPL-3.0-or-later WITH Classpath-exception-2.0 diff --git a/client/authority-discovery/build.rs b/client/authority-discovery/build.rs index c44fe8578ba2..00d45f07ae15 100644 --- a/client/authority-discovery/build.rs +++ b/client/authority-discovery/build.rs @@ -1,3 +1,7 @@ fn main() { - prost_build::compile_protos(&["src/worker/schema/dht.proto"], &["src/worker/schema"]).unwrap(); + prost_build::compile_protos( + &["src/worker/schema/dht-v1.proto", "src/worker/schema/dht-v2.proto"], + &["src/worker/schema"], + ) + .unwrap(); } diff --git a/client/authority-discovery/src/error.rs b/client/authority-discovery/src/error.rs index b271f7b9d62b..d37b6f3b43bc 100644 --- a/client/authority-discovery/src/error.rs +++ b/client/authority-discovery/src/error.rs @@ -46,10 +46,18 @@ pub enum Error { EncodingDecodingScale(codec::Error), /// Failed to parse a libp2p multi address. ParsingMultiaddress(libp2p::core::multiaddr::Error), + /// Failed to parse a libp2p key. + ParsingLibp2pIdentity(sc_network::DecodingError), /// Failed to sign using a specific public key. MissingSignature(CryptoTypePublicPair), /// Failed to sign using all public keys. Signing, /// Failed to register Prometheus metric. Prometheus(prometheus_endpoint::PrometheusError), + /// Received authority record that contains addresses with multiple peer ids + ReceivingDhtValueFoundEventWithDifferentPeerIds, + /// Received authority record without any addresses having a peer id + ReceivingDhtValueFoundEventWithNoPeerIds, + /// Received authority record without a valid signature for the remote peer id. + MissingPeerIdSignature, } diff --git a/client/authority-discovery/src/lib.rs b/client/authority-discovery/src/lib.rs index 1bbb9f38796c..e619463fa1ad 100644 --- a/client/authority-discovery/src/lib.rs +++ b/client/authority-discovery/src/lib.rs @@ -78,6 +78,11 @@ pub struct WorkerConfig { /// /// Defaults to `true` to avoid the surprise factor. pub publish_non_global_ips: bool, + + /// Reject authority discovery records that are not signed by their network identity (PeerId) + /// + /// Defaults to `false` to provide compatibility with old versions + pub strict_record_validation: bool, } impl Default for WorkerConfig { @@ -98,6 +103,7 @@ impl Default for WorkerConfig { // `authority_discovery_dht_event_received`. max_query_interval: Duration::from_secs(10 * 60), publish_non_global_ips: true, + strict_record_validation: false, } } } diff --git a/client/authority-discovery/src/tests.rs b/client/authority-discovery/src/tests.rs index cef91445064c..f1965907f4da 100644 --- a/client/authority-discovery/src/tests.rs +++ b/client/authority-discovery/src/tests.rs @@ -82,3 +82,32 @@ fn get_addresses_and_authority_id() { ); }); } + +#[test] +fn cryptos_are_compatible() { + use sp_core::crypto::Pair; + + let libp2p_secret = sc_network::Keypair::generate_ed25519(); + let libp2p_public = libp2p_secret.public(); + + let sp_core_secret = { + let libp2p_ed_secret = match libp2p_secret.clone() { + sc_network::Keypair::Ed25519(x) => x, + _ => panic!("generate_ed25519 should have generated an Ed25519 key ¯\\_(ツ)_/¯"), + }; + sp_core::ed25519::Pair::from_seed_slice(&libp2p_ed_secret.secret().as_ref()).unwrap() + }; + let sp_core_public = sp_core_secret.public(); + + let message = b"we are more powerful than not to be better"; + + let libp2p_signature = libp2p_secret.sign(message).unwrap(); + let sp_core_signature = sp_core_secret.sign(message); // no error expected... + + assert!(sp_core::ed25519::Pair::verify( + &sp_core::ed25519::Signature::from_slice(&libp2p_signature), + message, + &sp_core_public + )); + assert!(libp2p_public.verify(message, sp_core_signature.as_ref())); +} diff --git a/client/authority-discovery/src/worker.rs b/client/authority-discovery/src/worker.rs index 00021ecbdcb8..ce04e0eb65b1 100644 --- a/client/authority-discovery/src/worker.rs +++ b/client/authority-discovery/src/worker.rs @@ -19,7 +19,7 @@ use crate::{ error::{Error, Result}, interval::ExpIncInterval, - ServicetoWorkerMsg, + ServicetoWorkerMsg, WorkerConfig, }; use std::{ @@ -57,7 +57,10 @@ use sp_runtime::{generic::BlockId, traits::Block as BlockT}; mod addr_cache; /// Dht payload schemas generated from Protobuf definitions via Prost crate in build.rs. mod schema { - include!(concat!(env!("OUT_DIR"), "/authority_discovery.rs")); + #[cfg(test)] + mod tests; + + include!(concat!(env!("OUT_DIR"), "/authority_discovery_v2.rs")); } #[cfg(test)] pub mod tests; @@ -111,6 +114,7 @@ pub struct Worker { client: Arc, network: Arc, + /// Channel we receive Dht events on. dht_event_rx: DhtEventStream, @@ -124,6 +128,8 @@ pub struct Worker { latest_published_keys: HashSet, /// Same value as in the configuration. publish_non_global_ips: bool, + /// Same value as in the configuration. + strict_record_validation: bool, /// Interval at which to request addresses of authorities, refilling the pending lookups queue. query_interval: ExpIncInterval, @@ -131,7 +137,7 @@ pub struct Worker { /// Queue of throttled lookups pending to be passed to the network. pending_lookups: Vec, /// Set of in-flight lookups. - in_flight_lookups: HashMap, + in_flight_lookups: HashMap, addr_cache: addr_cache::AddrCache, @@ -158,7 +164,7 @@ where dht_event_rx: DhtEventStream, role: Role, prometheus_registry: Option, - config: crate::WorkerConfig, + config: WorkerConfig, ) -> Self { // When a node starts up publishing and querying might fail due to various reasons, for // example due to being not yet fully bootstrapped on the DHT. Thus one should retry rather @@ -197,6 +203,7 @@ where publish_if_changed_interval, latest_published_keys: HashSet::new(), publish_non_global_ips: config.publish_non_global_ips, + strict_record_validation: config.strict_record_validation, query_interval, pending_lookups: Vec::new(), in_flight_lookups: HashMap::new(), @@ -313,7 +320,7 @@ where return Ok(()) } - let addresses = self.addresses_to_publish().map(|a| a.to_vec()).collect::>(); + let addresses = serialize_addresses(self.addresses_to_publish()); if let Some(metrics) = &self.metrics { metrics.publish.inc(); @@ -322,32 +329,21 @@ where .set(addresses.len().try_into().unwrap_or(std::u64::MAX)); } - let mut serialized_addresses = vec![]; - schema::AuthorityAddresses { addresses } - .encode(&mut serialized_addresses) - .map_err(Error::EncodingProto)?; + let serialized_record = serialize_authority_record(addresses)?; + let peer_signature = sign_record_with_peer_id(&serialized_record, self.network.as_ref())?; let keys_vec = keys.iter().cloned().collect::>(); - let signatures = key_store - .sign_with_all( - key_types::AUTHORITY_DISCOVERY, - keys_vec.clone(), - serialized_addresses.as_slice(), - ) - .await - .map_err(|_| Error::Signing)?; - - for (sign_result, key) in signatures.into_iter().zip(keys_vec.iter()) { - let mut signed_addresses = vec![]; - // Verify that all signatures exist for all provided keys. - let signature = - sign_result.ok().flatten().ok_or_else(|| Error::MissingSignature(key.clone()))?; - schema::SignedAuthorityAddresses { addresses: serialized_addresses.clone(), signature } - .encode(&mut signed_addresses) - .map_err(Error::EncodingProto)?; + let kv_pairs = sign_record_with_authority_ids( + serialized_record, + Some(peer_signature), + key_store.as_ref(), + keys_vec, + ) + .await?; - self.network.put_value(hash_authority_id(key.1.as_ref()), signed_addresses); + for (key, value) in kv_pairs.into_iter() { + self.network.put_value(key, value); } self.latest_published_keys = keys; @@ -471,18 +467,11 @@ where fn handle_dht_value_found_event( &mut self, - values: Vec<(libp2p::kad::record::Key, Vec)>, + values: Vec<(sc_network::KademliaKey, Vec)>, ) -> Result<()> { // Ensure `values` is not empty and all its keys equal. - let remote_key = values - .iter() - .fold(Ok(None), |acc, (key, _)| match acc { - Ok(None) => Ok(Some(key.clone())), - Ok(Some(ref prev_key)) if prev_key != key => - Err(Error::ReceivingDhtValueFoundEventWithDifferentKeys), - x @ Ok(_) => x, - Err(e) => Err(e), - })? + let remote_key = single(values.iter().map(|(key, _)| key.clone())) + .map_err(|_| Error::ReceivingDhtValueFoundEventWithDifferentKeys)? .ok_or(Error::ReceivingDhtValueFoundEventWithNoRecords)?; let authority_id: AuthorityId = self @@ -495,18 +484,18 @@ where let remote_addresses: Vec = values .into_iter() .map(|(_k, v)| { - let schema::SignedAuthorityAddresses { signature, addresses } = - schema::SignedAuthorityAddresses::decode(v.as_slice()) + let schema::SignedAuthorityRecord { record, auth_signature, peer_signature } = + schema::SignedAuthorityRecord::decode(v.as_slice()) .map_err(Error::DecodingProto)?; - let signature = AuthoritySignature::decode(&mut &signature[..]) + let auth_signature = AuthoritySignature::decode(&mut &auth_signature[..]) .map_err(Error::EncodingDecodingScale)?; - if !AuthorityPair::verify(&signature, &addresses, &authority_id) { + if !AuthorityPair::verify(&auth_signature, &record, &authority_id) { return Err(Error::VerifyingDhtPayload) } - let addresses = schema::AuthorityAddresses::decode(addresses.as_slice()) + let addresses: Vec = schema::AuthorityRecord::decode(record.as_slice()) .map(|a| a.addresses) .map_err(Error::DecodingProto)? .into_iter() @@ -514,32 +503,49 @@ where .collect::>() .map_err(Error::ParsingMultiaddress)?; + let get_peer_id = |a: &Multiaddr| match a.iter().last() { + Some(multiaddr::Protocol::P2p(key)) => PeerId::from_multihash(key).ok(), + _ => None, + }; + + // Ignore [`Multiaddr`]s without [`PeerId`] or with own addresses. + let addresses: Vec = addresses + .into_iter() + .filter(|a| get_peer_id(&a).filter(|p| *p != local_peer_id).is_some()) + .collect(); + + let remote_peer_id = single(addresses.iter().map(get_peer_id)) + .map_err(|_| Error::ReceivingDhtValueFoundEventWithDifferentPeerIds)? // different peer_id in records + .flatten() + .ok_or(Error::ReceivingDhtValueFoundEventWithNoPeerIds)?; // no records with peer_id in them + + // At this point we know all the valid multiaddresses from the record, know that + // each of them belong to the same PeerId, we just need to check if the record is + // properly signed by the owner of the PeerId + + if let Some(peer_signature) = peer_signature { + let public_key = + sc_network::PublicKey::from_protobuf_encoding(&peer_signature.public_key) + .map_err(|e| Error::ParsingLibp2pIdentity(e))?; + let signature = + sc_network::Signature { public_key, bytes: peer_signature.signature }; + + if !signature.verify(record, &remote_peer_id) { + return Err(Error::VerifyingDhtPayload) + } + } else if self.strict_record_validation { + return Err(Error::MissingPeerIdSignature) + } else { + debug!( + target: LOG_TARGET, + "Received unsigned authority discovery record from {}", authority_id + ); + } Ok(addresses) }) .collect::>>>()? .into_iter() .flatten() - // Ignore [`Multiaddr`]s without [`PeerId`] and own addresses. - .filter(|addr| { - addr.iter().any(|protocol| { - // Parse to PeerId first as Multihashes of old and new PeerId - // representation don't equal. - // - // See https://github.com/libp2p/rust-libp2p/issues/555 for - // details. - if let multiaddr::Protocol::P2p(hash) = protocol { - let peer_id = match PeerId::from_multihash(hash) { - Ok(peer_id) => peer_id, - Err(_) => return false, // Discard address. - }; - - // Discard if equal to local peer id, keep if it differs. - return !(peer_id == local_peer_id) - } - - false // `protocol` is not a [`Protocol::P2p`], let's keep looking. - }) - }) .take(MAX_ADDRESSES_PER_AUTHORITY) .collect(); @@ -588,16 +594,37 @@ where } } +pub trait NetworkSigner { + /// Sign a message in the name of `self.local_peer_id()` + fn sign_with_local_identity( + &self, + msg: impl AsRef<[u8]>, + ) -> std::result::Result; +} + /// NetworkProvider provides [`Worker`] with all necessary hooks into the /// underlying Substrate networking. Using this trait abstraction instead of /// [`sc_network::NetworkService`] directly is necessary to unit test [`Worker`]. #[async_trait] -pub trait NetworkProvider: NetworkStateInfo { +pub trait NetworkProvider: NetworkStateInfo + NetworkSigner { /// Start putting a value in the Dht. - fn put_value(&self, key: libp2p::kad::record::Key, value: Vec); + fn put_value(&self, key: sc_network::KademliaKey, value: Vec); /// Start getting a value from the Dht. - fn get_value(&self, key: &libp2p::kad::record::Key); + fn get_value(&self, key: &sc_network::KademliaKey); +} + +impl NetworkSigner for sc_network::NetworkService +where + B: BlockT + 'static, + H: ExHashT, +{ + fn sign_with_local_identity( + &self, + msg: impl AsRef<[u8]>, + ) -> std::result::Result { + self.sign_with_local_identity(msg) + } } #[async_trait::async_trait] @@ -606,16 +633,87 @@ where B: BlockT + 'static, H: ExHashT, { - fn put_value(&self, key: libp2p::kad::record::Key, value: Vec) { + fn put_value(&self, key: sc_network::KademliaKey, value: Vec) { self.put_value(key, value) } - fn get_value(&self, key: &libp2p::kad::record::Key) { + fn get_value(&self, key: &sc_network::KademliaKey) { self.get_value(key) } } -fn hash_authority_id(id: &[u8]) -> libp2p::kad::record::Key { - libp2p::kad::record::Key::new(&libp2p::multihash::Sha2_256::digest(id)) +fn hash_authority_id(id: &[u8]) -> sc_network::KademliaKey { + sc_network::KademliaKey::new(&libp2p::multihash::Sha2_256::digest(id)) +} + +// Makes sure all values are the same and returns it +// +// Returns Err(_) if not all values are equal. Returns Ok(None) if there are +// no values. +fn single(values: impl IntoIterator) -> std::result::Result, ()> +where + T: PartialEq, +{ + values.into_iter().try_fold(None, |acc, item| match acc { + None => Ok(Some(item)), + Some(ref prev) if *prev != item => Err(()), + Some(x) => Ok(Some(x)), + }) +} + +fn serialize_addresses(addresses: impl Iterator) -> Vec> { + addresses.map(|a| a.to_vec()).collect() +} + +fn serialize_authority_record(addresses: Vec>) -> Result> { + let mut serialized_record = vec![]; + schema::AuthorityRecord { addresses } + .encode(&mut serialized_record) + .map_err(Error::EncodingProto)?; + Ok(serialized_record) +} + +fn sign_record_with_peer_id( + serialized_record: &[u8], + network: &impl NetworkSigner, +) -> Result { + let signature = network + .sign_with_local_identity(serialized_record) + .map_err(|_| Error::Signing)?; + let public_key = signature.public_key.to_protobuf_encoding(); + let signature = signature.bytes; + Ok(schema::PeerSignature { signature, public_key }) +} + +async fn sign_record_with_authority_ids( + serialized_record: Vec, + peer_signature: Option, + key_store: &dyn CryptoStore, + keys: Vec, +) -> Result)>> { + let signatures = key_store + .sign_with_all(key_types::AUTHORITY_DISCOVERY, keys.clone(), &serialized_record) + .await + .map_err(|_| Error::Signing)?; + + let mut result = vec![]; + for (sign_result, key) in signatures.into_iter().zip(keys.iter()) { + let mut signed_record = vec![]; + + // Verify that all signatures exist for all provided keys. + let auth_signature = + sign_result.ok().flatten().ok_or_else(|| Error::MissingSignature(key.clone()))?; + schema::SignedAuthorityRecord { + record: serialized_record.clone(), + auth_signature, + peer_signature: peer_signature.clone(), + } + .encode(&mut signed_record) + .map_err(Error::EncodingProto)?; + + result.push((hash_authority_id(key.1.as_ref()), signed_record)); + } + + Ok(result) } /// Prometheus metrics for a [`Worker`]. diff --git a/client/authority-discovery/src/worker/schema/dht.proto b/client/authority-discovery/src/worker/schema/dht-v1.proto similarity index 90% rename from client/authority-discovery/src/worker/schema/dht.proto rename to client/authority-discovery/src/worker/schema/dht-v1.proto index 9dbe9d559f4b..0ef628888c09 100644 --- a/client/authority-discovery/src/worker/schema/dht.proto +++ b/client/authority-discovery/src/worker/schema/dht-v1.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -package authority_discovery; +package authority_discovery_v1; // First we need to serialize the addresses in order to be able to sign them. message AuthorityAddresses { @@ -11,4 +11,4 @@ message AuthorityAddresses { message SignedAuthorityAddresses { bytes addresses = 1; bytes signature = 2; -} +} \ No newline at end of file diff --git a/client/authority-discovery/src/worker/schema/dht-v2.proto b/client/authority-discovery/src/worker/schema/dht-v2.proto new file mode 100644 index 000000000000..c63f6c176735 --- /dev/null +++ b/client/authority-discovery/src/worker/schema/dht-v2.proto @@ -0,0 +1,23 @@ +syntax = "proto3"; + +package authority_discovery_v2; + +// First we need to serialize the addresses in order to be able to sign them. +message AuthorityRecord { + // Possibly multiple `MultiAddress`es through which the node can be + repeated bytes addresses = 1; +} + +message PeerSignature { + bytes signature = 1; + bytes public_key = 2; +} + +// Then we need to serialize the authority record and signature to send them over the wire. +message SignedAuthorityRecord { + bytes record = 1; + bytes auth_signature = 2; + // Even if there are multiple `record.addresses`, all of them have the same peer id. + // Old versions are missing this field, so `optional` will provide compatibility both ways. + optional PeerSignature peer_signature = 3; +} diff --git a/client/authority-discovery/src/worker/schema/tests.rs b/client/authority-discovery/src/worker/schema/tests.rs new file mode 100644 index 000000000000..ef96078411e9 --- /dev/null +++ b/client/authority-discovery/src/worker/schema/tests.rs @@ -0,0 +1,90 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2021 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 . + +mod schema_v1 { + include!(concat!(env!("OUT_DIR"), "/authority_discovery_v1.rs")); +} + +use super::*; +use libp2p::multiaddr::Multiaddr; +use prost::Message; +use sc_network::PeerId; + +#[test] +fn v2_decodes_v1() { + let peer_id = PeerId::random(); + let multiaddress: Multiaddr = + format!("/ip4/127.0.0.1/tcp/3003/p2p/{}", peer_id).parse().unwrap(); + let vec_addresses = vec![multiaddress.to_vec()]; + let vec_auth_signature = b"Totally valid signature, I promise!".to_vec(); + + let addresses_v1 = schema_v1::AuthorityAddresses { addresses: vec_addresses.clone() }; + let mut vec_addresses_v1 = vec![]; + addresses_v1.encode(&mut vec_addresses_v1).unwrap(); + let signed_addresses_v1 = schema_v1::SignedAuthorityAddresses { + addresses: vec_addresses_v1.clone(), + signature: vec_auth_signature.clone(), + }; + let mut vec_signed_addresses_v1 = vec![]; + signed_addresses_v1.encode(&mut vec_signed_addresses_v1).unwrap(); + + let signed_record_v2_decoded = + SignedAuthorityRecord::decode(vec_signed_addresses_v1.as_slice()).unwrap(); + + assert_eq!(&signed_record_v2_decoded.record, &vec_addresses_v1); + assert_eq!(&signed_record_v2_decoded.auth_signature, &vec_auth_signature); + assert_eq!(&signed_record_v2_decoded.peer_signature, &None); + + let record_v2_decoded = AuthorityRecord::decode(vec_addresses_v1.as_slice()).unwrap(); + assert_eq!(&record_v2_decoded.addresses, &vec_addresses); +} + +#[test] +fn v1_decodes_v2() { + let peer_secret = sc_network::Keypair::generate_ed25519(); + let peer_public = peer_secret.public(); + let peer_id = peer_public.to_peer_id(); + let multiaddress: Multiaddr = + format!("/ip4/127.0.0.1/tcp/3003/p2p/{}", peer_id).parse().unwrap(); + let vec_addresses = vec![multiaddress.to_vec()]; + let vec_auth_signature = b"Totally valid signature, I promise!".to_vec(); + let vec_peer_signature = b"Surprisingly hard to crack crypto".to_vec(); + + let record_v2 = AuthorityRecord { addresses: vec_addresses.clone() }; + let mut vec_record_v2 = vec![]; + record_v2.encode(&mut vec_record_v2).unwrap(); + let vec_peer_public = peer_public.to_protobuf_encoding(); + let peer_signature_v2 = + PeerSignature { public_key: vec_peer_public, signature: vec_peer_signature }; + let signed_record_v2 = SignedAuthorityRecord { + record: vec_record_v2.clone(), + auth_signature: vec_auth_signature.clone(), + peer_signature: Some(peer_signature_v2.clone()), + }; + let mut vec_signed_record_v2 = vec![]; + signed_record_v2.encode(&mut vec_signed_record_v2).unwrap(); + + let signed_addresses_v1_decoded = + schema_v1::SignedAuthorityAddresses::decode(vec_signed_record_v2.as_slice()).unwrap(); + + assert_eq!(&signed_addresses_v1_decoded.addresses, &vec_record_v2); + assert_eq!(&signed_addresses_v1_decoded.signature, &vec_auth_signature); + + let addresses_v2_decoded = AuthorityRecord::decode(vec_record_v2.as_slice()).unwrap(); + assert_eq!(&addresses_v2_decoded.addresses, &vec_addresses); +} diff --git a/client/authority-discovery/src/worker/tests.rs b/client/authority-discovery/src/worker/tests.rs index 130aea71fdfb..1129427ac868 100644 --- a/client/authority-discovery/src/worker/tests.rs +++ b/client/authority-discovery/src/worker/tests.rs @@ -16,8 +16,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use crate::worker::schema; - use std::{ collections::HashSet, sync::{Arc, Mutex}, @@ -32,11 +30,10 @@ use futures::{ sink::SinkExt, task::LocalSpawn, }; -use libp2p::{core::multiaddr, kad, PeerId}; +use libp2p::{core::multiaddr, PeerId}; use prometheus_endpoint::prometheus::default_registry; use sp_api::{ApiRef, ProvideRuntimeApi}; -use sp_core::crypto::Public; use sp_keystore::{testing::KeyStore, CryptoStore}; use sp_runtime::traits::{Block as BlockT, NumberFor, Zero}; use substrate_test_runtime_client::runtime::Block; @@ -114,17 +111,18 @@ sp_api::mock_impl_runtime_apis! { #[derive(Debug)] pub enum TestNetworkEvent { - GetCalled(kad::record::Key), - PutCalled(kad::record::Key, Vec), + GetCalled(sc_network::KademliaKey), + PutCalled(sc_network::KademliaKey, Vec), } pub struct TestNetwork { peer_id: PeerId, + identity: sc_network::Keypair, external_addresses: Vec, // Whenever functions on `TestNetwork` are called, the function arguments are added to the // vectors below. - pub put_value_call: Arc)>>>, - pub get_value_call: Arc>>, + pub put_value_call: Arc)>>>, + pub get_value_call: Arc>>, event_sender: mpsc::UnboundedSender, event_receiver: Option>, } @@ -138,8 +136,10 @@ impl TestNetwork { impl Default for TestNetwork { fn default() -> Self { let (tx, rx) = mpsc::unbounded(); + let identity = sc_network::Keypair::generate_ed25519(); TestNetwork { - peer_id: PeerId::random(), + peer_id: identity.public().to_peer_id(), + identity, external_addresses: vec!["/ip6/2001:db8::/tcp/30333".parse().unwrap()], put_value_call: Default::default(), get_value_call: Default::default(), @@ -149,16 +149,25 @@ impl Default for TestNetwork { } } +impl NetworkSigner for TestNetwork { + fn sign_with_local_identity( + &self, + msg: impl AsRef<[u8]>, + ) -> std::result::Result { + sc_network::Signature::sign_message(msg, &self.identity) + } +} + #[async_trait] impl NetworkProvider for TestNetwork { - fn put_value(&self, key: kad::record::Key, value: Vec) { + fn put_value(&self, key: sc_network::KademliaKey, value: Vec) { self.put_value_call.lock().unwrap().push((key.clone(), value.clone())); self.event_sender .clone() .unbounded_send(TestNetworkEvent::PutCalled(key, value)) .unwrap(); } - fn get_value(&self, key: &kad::record::Key) { + fn get_value(&self, key: &sc_network::KademliaKey) { self.get_value_call.lock().unwrap().push(key.clone()); self.event_sender .clone() @@ -177,35 +186,35 @@ impl NetworkStateInfo for TestNetwork { } } -async fn build_dht_event( +impl NetworkSigner for sc_network::Keypair { + fn sign_with_local_identity( + &self, + msg: impl AsRef<[u8]>, + ) -> std::result::Result { + sc_network::Signature::sign_message(msg, self) + } +} + +async fn build_dht_event( addresses: Vec, public_key: AuthorityId, - key_store: &KeyStore, -) -> (libp2p::kad::record::Key, Vec) { - let mut serialized_addresses = vec![]; - schema::AuthorityAddresses { addresses: addresses.into_iter().map(|a| a.to_vec()).collect() } - .encode(&mut serialized_addresses) - .map_err(Error::EncodingProto) - .unwrap(); - - let signature = key_store - .sign_with( - key_types::AUTHORITY_DISCOVERY, - &public_key.clone().into(), - serialized_addresses.as_slice(), - ) - .await - .unwrap() - .unwrap(); - - let mut signed_addresses = vec![]; - schema::SignedAuthorityAddresses { addresses: serialized_addresses.clone(), signature } - .encode(&mut signed_addresses) - .unwrap(); - - let key = hash_authority_id(&public_key.to_raw_vec()); - let value = signed_addresses; - (key, value) + key_store: &dyn CryptoStore, + network: Option<&Signer>, +) -> Vec<(sc_network::KademliaKey, Vec)> { + let serialized_record = + serialize_authority_record(serialize_addresses(addresses.into_iter())).unwrap(); + + let peer_signature = network.map(|n| sign_record_with_peer_id(&serialized_record, n).unwrap()); + let kv_pairs = sign_record_with_authority_ids( + serialized_record, + peer_signature, + key_store, + vec![public_key.into()], + ) + .await + .unwrap(); + // There is always a single item in it, because we signed it with a single key + kv_pairs } #[test] @@ -453,13 +462,14 @@ fn dont_stop_polling_dht_event_stream_after_bogus_event() { // Make previously triggered lookup succeed. let dht_event = { - let (key, value) = build_dht_event( + let kv_pairs = build_dht_event::( vec![remote_multiaddr.clone()], remote_public_key.clone(), &remote_key_store, + None, ) .await; - sc_network::DhtEvent::ValueFound(vec![(key, value)]) + sc_network::DhtEvent::ValueFound(kv_pairs) }; dht_event_tx.send(dht_event).await.expect("Channel has capacity of 1."); @@ -474,97 +484,191 @@ fn dont_stop_polling_dht_event_stream_after_bogus_event() { }); } -#[test] -fn limit_number_of_addresses_added_to_cache_per_authority() { - let remote_key_store = KeyStore::new(); - let remote_public = - block_on(remote_key_store.sr25519_generate_new(key_types::AUTHORITY_DISCOVERY, None)) - .unwrap(); +struct DhtValueFoundTester { + pub remote_key_store: KeyStore, + pub remote_authority_public: sp_core::sr25519::Public, + pub remote_node_key: sc_network::Keypair, + pub local_worker: Option< + Worker< + TestApi, + TestNetwork, + sp_runtime::generic::Block< + sp_runtime::generic::Header, + substrate_test_runtime_client::runtime::Extrinsic, + >, + std::pin::Pin>>, + >, + >, +} - let addresses = (0..100) - .map(|_| { - let peer_id = PeerId::random(); - let address: Multiaddr = "/ip6/2001:db8:0:0:0:0:0:1/tcp/30333".parse().unwrap(); - address.with(multiaddr::Protocol::P2p(peer_id.into())) - }) - .collect(); +impl DhtValueFoundTester { + fn new() -> Self { + let remote_key_store = KeyStore::new(); + let remote_authority_public = + block_on(remote_key_store.sr25519_generate_new(key_types::AUTHORITY_DISCOVERY, None)) + .unwrap(); - let dht_event = block_on(build_dht_event(addresses, remote_public.into(), &remote_key_store)); + let remote_node_key = sc_network::Keypair::generate_ed25519(); + Self { remote_key_store, remote_authority_public, remote_node_key, local_worker: None } + } - let (_dht_event_tx, dht_event_rx) = channel(1); + fn multiaddr_with_peer_id(&self, idx: u16) -> Multiaddr { + let peer_id = self.remote_node_key.public().to_peer_id(); + let address: Multiaddr = + format!("/ip6/2001:db8:0:0:0:0:0:{:x}/tcp/30333", idx).parse().unwrap(); - let (_to_worker, from_service) = mpsc::channel(0); - let mut worker = Worker::new( - from_service, - Arc::new(TestApi { authorities: vec![remote_public.into()] }), - Arc::new(TestNetwork::default()), - Box::pin(dht_event_rx), - Role::Discover, + address.with(multiaddr::Protocol::P2p(peer_id.into())) + } + + fn process_value_found( + &mut self, + strict_record_validation: bool, + values: Vec<(sc_network::KademliaKey, Vec)>, + ) -> Option<&HashSet> { + let (_dht_event_tx, dht_event_rx) = channel(1); + let local_test_api = + Arc::new(TestApi { authorities: vec![self.remote_authority_public.clone().into()] }); + let local_network: Arc = Arc::new(Default::default()); + let local_key_store = KeyStore::new(); + + let (_to_worker, from_service) = mpsc::channel(0); + let mut local_worker = Worker::new( + from_service, + local_test_api, + local_network.clone(), + Box::pin(dht_event_rx), + Role::PublishAndDiscover(Arc::new(local_key_store)), + None, + WorkerConfig { strict_record_validation, ..Default::default() }, + ); + + block_on(local_worker.refill_pending_lookups_queue()).unwrap(); + local_worker.start_new_lookups(); + + drop(local_worker.handle_dht_value_found_event(values)); + + self.local_worker = Some(local_worker); + + self.local_worker + .as_ref() + .map(|w| { + w.addr_cache + .get_addresses_by_authority_id(&self.remote_authority_public.clone().into()) + }) + .unwrap() + } +} + +#[test] +fn limit_number_of_addresses_added_to_cache_per_authority() { + let mut tester = DhtValueFoundTester::new(); + assert!(MAX_ADDRESSES_PER_AUTHORITY < 100); + let addresses = (1..100).map(|i| tester.multiaddr_with_peer_id(i)).collect(); + let kv_pairs = block_on(build_dht_event::( + addresses, + tester.remote_authority_public.clone().into(), + &tester.remote_key_store, None, - Default::default(), - ); + )); + + let cached_remote_addresses = tester.process_value_found(false, kv_pairs); + assert_eq!(MAX_ADDRESSES_PER_AUTHORITY, cached_remote_addresses.unwrap().len()); +} + +#[test] +fn strict_accept_address_with_peer_signature() { + let mut tester = DhtValueFoundTester::new(); + let addr = tester.multiaddr_with_peer_id(1); + let kv_pairs = block_on(build_dht_event( + vec![addr.clone()], + tester.remote_authority_public.clone().into(), + &tester.remote_key_store, + Some(&tester.remote_node_key), + )); - block_on(worker.refill_pending_lookups_queue()).unwrap(); - worker.start_new_lookups(); + let cached_remote_addresses = tester.process_value_found(true, kv_pairs); - worker.handle_dht_value_found_event(vec![dht_event]).unwrap(); assert_eq!( - MAX_ADDRESSES_PER_AUTHORITY, - worker - .addr_cache - .get_addresses_by_authority_id(&remote_public.into()) - .unwrap() - .len(), + Some(&HashSet::from([addr])), + cached_remote_addresses, + "Expect worker to only cache `Multiaddr`s with `PeerId`s.", ); } #[test] -fn do_not_cache_addresses_without_peer_id() { - let remote_key_store = KeyStore::new(); - let remote_public = - block_on(remote_key_store.sr25519_generate_new(key_types::AUTHORITY_DISCOVERY, None)) - .unwrap(); - - let multiaddr_with_peer_id = { - let peer_id = PeerId::random(); - let address: Multiaddr = "/ip6/2001:db8:0:0:0:0:0:2/tcp/30333".parse().unwrap(); +fn reject_address_with_rogue_peer_signature() { + let mut tester = DhtValueFoundTester::new(); + let rogue_remote_node_key = sc_network::Keypair::generate_ed25519(); + let kv_pairs = block_on(build_dht_event( + vec![tester.multiaddr_with_peer_id(1)], + tester.remote_authority_public.clone().into(), + &tester.remote_key_store, + Some(&rogue_remote_node_key), + )); - address.with(multiaddr::Protocol::P2p(peer_id.into())) - }; + let cached_remote_addresses = tester.process_value_found(false, kv_pairs); - let multiaddr_without_peer_id: Multiaddr = - "/ip6/2001:db8:0:0:0:0:0:1/tcp/30333".parse().unwrap(); + assert!( + cached_remote_addresses.is_none(), + "Expected worker to ignore record signed by a different key.", + ); +} - let dht_event = block_on(build_dht_event( - vec![multiaddr_with_peer_id.clone(), multiaddr_without_peer_id], - remote_public.into(), - &remote_key_store, +#[test] +fn reject_address_with_invalid_peer_signature() { + let mut tester = DhtValueFoundTester::new(); + let mut kv_pairs = block_on(build_dht_event( + vec![tester.multiaddr_with_peer_id(1)], + tester.remote_authority_public.clone().into(), + &tester.remote_key_store, + Some(&tester.remote_node_key), )); + // tamper with the signature + let mut record = schema::SignedAuthorityRecord::decode(kv_pairs[0].1.as_slice()).unwrap(); + record.peer_signature.as_mut().map(|p| p.signature[1] += 1); + record.encode(&mut kv_pairs[0].1).unwrap(); - let (_dht_event_tx, dht_event_rx) = channel(1); - let local_test_api = Arc::new(TestApi { authorities: vec![remote_public.into()] }); - let local_network: Arc = Arc::new(Default::default()); - let local_key_store = KeyStore::new(); + let cached_remote_addresses = tester.process_value_found(false, kv_pairs); - let (_to_worker, from_service) = mpsc::channel(0); - let mut local_worker = Worker::new( - from_service, - local_test_api, - local_network.clone(), - Box::pin(dht_event_rx), - Role::PublishAndDiscover(Arc::new(local_key_store)), - None, - Default::default(), + assert!( + cached_remote_addresses.is_none(), + "Expected worker to ignore record with tampered signature.", ); +} + +#[test] +fn reject_address_without_peer_signature() { + let mut tester = DhtValueFoundTester::new(); + let kv_pairs = block_on(build_dht_event::( + vec![tester.multiaddr_with_peer_id(1)], + tester.remote_authority_public.clone().into(), + &tester.remote_key_store, + None, + )); - block_on(local_worker.refill_pending_lookups_queue()).unwrap(); - local_worker.start_new_lookups(); + let cached_remote_addresses = tester.process_value_found(true, kv_pairs); - local_worker.handle_dht_value_found_event(vec![dht_event]).unwrap(); + assert!(cached_remote_addresses.is_none(), "Expected worker to ignore unsigned record.",); +} + +#[test] +fn do_not_cache_addresses_without_peer_id() { + let mut tester = DhtValueFoundTester::new(); + let multiaddr_with_peer_id = tester.multiaddr_with_peer_id(1); + let multiaddr_without_peer_id: Multiaddr = + "/ip6/2001:db8:0:0:0:0:0:2/tcp/30333".parse().unwrap(); + let kv_pairs = block_on(build_dht_event::( + vec![multiaddr_with_peer_id.clone(), multiaddr_without_peer_id], + tester.remote_authority_public.clone().into(), + &tester.remote_key_store, + None, + )); + + let cached_remote_addresses = tester.process_value_found(false, kv_pairs); assert_eq!( Some(&HashSet::from([multiaddr_with_peer_id])), - local_worker.addr_cache.get_addresses_by_authority_id(&remote_public.into()), + cached_remote_addresses, "Expect worker to only cache `Multiaddr`s with `PeerId`s.", ); } @@ -697,10 +801,14 @@ fn lookup_throttling() { let remote_hash = network.get_value_call.lock().unwrap().pop().unwrap(); let remote_key: AuthorityId = remote_hash_to_key.get(&remote_hash).unwrap().clone(); let dht_event = { - let (key, value) = - build_dht_event(vec![remote_multiaddr.clone()], remote_key, &remote_key_store) - .await; - sc_network::DhtEvent::ValueFound(vec![(key, value)]) + let kv_pairs = build_dht_event::( + vec![remote_multiaddr.clone()], + remote_key, + &remote_key_store, + None, + ) + .await; + sc_network::DhtEvent::ValueFound(kv_pairs) }; dht_event_tx.send(dht_event).await.expect("Channel has capacity of 1."); diff --git a/client/keystore/src/local.rs b/client/keystore/src/local.rs index 965e68336e3b..d5a7fd93d7dc 100644 --- a/client/keystore/src/local.rs +++ b/client/keystore/src/local.rs @@ -420,8 +420,6 @@ impl KeystoreInner { /// Write the given `data` to `file`. fn write_to_file(file: PathBuf, data: &str) -> Result<()> { let mut file = File::create(file)?; - serde_json::to_writer(&file, data)?; - file.flush()?; #[cfg(target_family = "unix")] { @@ -429,6 +427,8 @@ impl KeystoreInner { file.set_permissions(fs::Permissions::from_mode(0o600))?; } + serde_json::to_writer(&file, data)?; + file.flush()?; Ok(()) } diff --git a/client/network/src/lib.rs b/client/network/src/lib.rs index cb16eb163ee4..d07e9d3baaa4 100644 --- a/client/network/src/lib.rs +++ b/client/network/src/lib.rs @@ -273,8 +273,9 @@ pub use protocol::{ PeerInfo, }; pub use service::{ - IfDisconnected, NetworkService, NetworkWorker, NotificationSender, NotificationSenderReady, - OutboundFailure, RequestFailure, + DecodingError, IfDisconnected, KademliaKey, Keypair, NetworkService, NetworkWorker, + NotificationSender, NotificationSenderReady, OutboundFailure, PublicKey, RequestFailure, + Signature, SigningError, }; pub use sc_peerset::ReputationChange; diff --git a/client/network/src/service.rs b/client/network/src/service.rs index 4377ff358de7..e03bdcfa2f7e 100644 --- a/client/network/src/service.rs +++ b/client/network/src/service.rs @@ -54,7 +54,6 @@ use libp2p::{ either::EitherError, upgrade, ConnectedPoint, Executor, }, - kad::record, multiaddr, ping::Failure as PingFailure, swarm::{ @@ -93,9 +92,19 @@ pub use behaviour::{ mod metrics; mod out_events; +mod signature; #[cfg(test)] mod tests; +pub use libp2p::{ + identity::{ + error::{DecodingError, SigningError}, + Keypair, PublicKey, + }, + kad::record::Key as KademliaKey, +}; +pub use signature::*; + /// Substrate network service. Handles network IO and manages connectivity. pub struct NetworkService { /// Number of peers we're connected to. @@ -106,6 +115,8 @@ pub struct NetworkService { is_major_syncing: Arc, /// Local copy of the `PeerId` of the local node. local_peer_id: PeerId, + /// The `KeyPair` that defines the `PeerId` of the local node. + local_identity: Keypair, /// Bandwidth logging system. Can be queried to know the average bandwidth consumed. bandwidth: Arc, /// Peerset manager (PSM); manages the reputation of nodes and indicates the network which @@ -318,7 +329,7 @@ impl NetworkWorker { }; transport::build_transport( - local_identity, + local_identity.clone(), config_mem, params.network_config.yamux_window_size, yamux_maximum_buffer_size, @@ -406,6 +417,7 @@ impl NetworkWorker { is_major_syncing: is_major_syncing.clone(), peerset: peerset_handle, local_peer_id, + local_identity, to_worker, peers_notifications_sinks: peers_notifications_sinks.clone(), notifications_sizes_metric: metrics @@ -667,6 +679,14 @@ impl NetworkService { &self.local_peer_id } + /// Signs the message with the `KeyPair` that defined the local `PeerId`. + pub fn sign_with_local_identity( + &self, + msg: impl AsRef<[u8]>, + ) -> Result { + Signature::sign_message(msg.as_ref(), &self.local_identity) + } + /// Set authorized peers. /// /// Need a better solution to manage authorized peers, but now just use reserved peers for @@ -1024,7 +1044,7 @@ impl NetworkService { /// /// This will generate either a `ValueFound` or a `ValueNotFound` event and pass it as an /// item on the [`NetworkWorker`] stream. - pub fn get_value(&self, key: &record::Key) { + pub fn get_value(&self, key: &KademliaKey) { let _ = self.to_worker.unbounded_send(ServiceToWorkerMsg::GetValue(key.clone())); } @@ -1032,7 +1052,7 @@ impl NetworkService { /// /// This will generate either a `ValuePut` or a `ValuePutFailed` event and pass it as an /// item on the [`NetworkWorker`] stream. - pub fn put_value(&self, key: record::Key, value: Vec) { + pub fn put_value(&self, key: KademliaKey, value: Vec) { let _ = self.to_worker.unbounded_send(ServiceToWorkerMsg::PutValue(key, value)); } @@ -1393,8 +1413,8 @@ enum ServiceToWorkerMsg { RequestJustification(B::Hash, NumberFor), ClearJustificationRequests, AnnounceBlock(B::Hash, Option>), - GetValue(record::Key), - PutValue(record::Key, Vec), + GetValue(KademliaKey), + PutValue(KademliaKey, Vec), AddKnownAddress(PeerId, Multiaddr), SetReservedOnly(bool), AddReserved(PeerId), diff --git a/client/network/src/service/signature.rs b/client/network/src/service/signature.rs new file mode 100644 index 000000000000..c2d6c4f7db6e --- /dev/null +++ b/client/network/src/service/signature.rs @@ -0,0 +1,50 @@ +// This file is part of Substrate. +// +// Copyright (C) 2017-2021 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 . +// +// If you read this, you are very thorough, congratulations. + +use super::*; + +/// A result of signing a message with a network identity. Since `PeerId` is potentially a hash of a +/// `PublicKey`, you need to reveal the `PublicKey` next to the signature, so the verifier can check +/// if the signature was made by the entity that controls a given `PeerId`. +pub struct Signature { + /// The public key derived from the network identity that signed the message. + pub public_key: PublicKey, + /// The actual signature made for the message signed. + pub bytes: Vec, +} + +impl Signature { + /// Create a signature for a message with a given network identity. + pub fn sign_message( + message: impl AsRef<[u8]>, + keypair: &Keypair, + ) -> Result { + let public_key = keypair.public(); + let bytes = keypair.sign(message.as_ref())?; + Ok(Self { public_key, bytes }) + } + + /// Verify whether the signature was made for the given message by the entity that controls the + /// given `PeerId`. + pub fn verify(&self, message: impl AsRef<[u8]>, peer_id: &PeerId) -> bool { + *peer_id == self.public_key.to_peer_id() && + self.public_key.verify(message.as_ref(), &self.bytes) + } +} From 0e6cc5668d9ee8d852a3aa3f85a2ab5fcb4c75a1 Mon Sep 17 00:00:00 2001 From: Xiliang Chen Date: Tue, 7 Dec 2021 00:31:13 +1300 Subject: [PATCH 257/695] allow tip value of 1 (#10425) * allow tip value of 1 * update comment * fmt * update test * fmt --- frame/transaction-payment/src/lib.rs | 56 ++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/frame/transaction-payment/src/lib.rs b/frame/transaction-payment/src/lib.rs index ed96f26cc007..02ba9621c175 100644 --- a/frame/transaction-payment/src/lib.rs +++ b/frame/transaction-payment/src/lib.rs @@ -52,8 +52,8 @@ use scale_info::TypeInfo; use sp_runtime::{ traits::{ - Convert, DispatchInfoOf, Dispatchable, PostDispatchInfoOf, SaturatedConversion, Saturating, - SignedExtension, Zero, + Convert, DispatchInfoOf, Dispatchable, One, PostDispatchInfoOf, SaturatedConversion, + Saturating, SignedExtension, Zero, }, transaction_validity::{ TransactionPriority, TransactionValidity, TransactionValidityError, ValidTransaction, @@ -649,9 +649,9 @@ where .saturated_into::>(); let max_reward = |val: BalanceOf| val.saturating_mul(max_tx_per_block); - // To distribute no-tip transactions a little bit, we set the minimal tip as `1`. + // To distribute no-tip transactions a little bit, we increase the tip value by one. // This means that given two transactions without a tip, smaller one will be preferred. - let tip = tip.max(1.saturated_into()); + let tip = tip.saturating_add(One::one()); let scaled_tip = max_reward(tip); match info.class { @@ -1480,14 +1480,14 @@ mod tests { .unwrap() .priority; - assert_eq!(priority, 50); + assert_eq!(priority, 60); let priority = ChargeTransactionPayment::(2 * tip) .validate(&2, CALL, &normal, len) .unwrap() .priority; - assert_eq!(priority, 100); + assert_eq!(priority, 110); }); ExtBuilder::default().balance_factor(100).build().execute_with(|| { @@ -1500,13 +1500,13 @@ mod tests { .validate(&2, CALL, &op, len) .unwrap() .priority; - assert_eq!(priority, 5800); + assert_eq!(priority, 5810); let priority = ChargeTransactionPayment::(2 * tip) .validate(&2, CALL, &op, len) .unwrap() .priority; - assert_eq!(priority, 6100); + assert_eq!(priority, 6110); }); } @@ -1540,6 +1540,46 @@ mod tests { }); } + #[test] + fn higher_tip_have_higher_priority() { + let get_priorities = |tip: u64| { + let mut priority1 = 0; + let mut priority2 = 0; + let len = 10; + ExtBuilder::default().balance_factor(100).build().execute_with(|| { + let normal = + DispatchInfo { weight: 100, class: DispatchClass::Normal, pays_fee: Pays::Yes }; + priority1 = ChargeTransactionPayment::(tip) + .validate(&2, CALL, &normal, len) + .unwrap() + .priority; + }); + + ExtBuilder::default().balance_factor(100).build().execute_with(|| { + let op = DispatchInfo { + weight: 100, + class: DispatchClass::Operational, + pays_fee: Pays::Yes, + }; + priority2 = ChargeTransactionPayment::(tip) + .validate(&2, CALL, &op, len) + .unwrap() + .priority; + }); + + (priority1, priority2) + }; + + let mut prev_priorities = get_priorities(0); + + for tip in 1..3 { + let priorities = get_priorities(tip); + assert!(prev_priorities.0 < priorities.0); + assert!(prev_priorities.1 < priorities.1); + prev_priorities = priorities; + } + } + #[test] fn post_info_can_change_pays_fee() { ExtBuilder::default() From f0b85c6024296519913ca6f748bb3081f1b4bacd Mon Sep 17 00:00:00 2001 From: Zeke Mostov Date: Mon, 6 Dec 2021 13:31:16 -0800 Subject: [PATCH 258/695] Add baseline benchmark for sr25519 verification (#10414) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add baseline benchmark for sr25519 verification * cargo run --quiet --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=frame_benchmarking --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/benchmarking/src/weights.rs --template=./.maintain/frame-weight-template.hbs * Register keystore for correct test externalities * Update frame/benchmarking/src/baseline.rs Co-authored-by: Bastian Köcher * fix build Co-authored-by: Parity Bot Co-authored-by: Bastian Köcher --- Cargo.lock | 2 ++ frame/benchmarking/Cargo.toml | 2 ++ frame/benchmarking/src/baseline.rs | 41 +++++++++++++++++++++-- frame/benchmarking/src/weights.rs | 54 +++++++++++++++++++----------- 4 files changed, 77 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d277db3f519b..d67ebd7f24dd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1958,7 +1958,9 @@ dependencies = [ "paste 1.0.6", "scale-info", "sp-api", + "sp-application-crypto", "sp-io", + "sp-keystore", "sp-runtime", "sp-runtime-interface", "sp-std", diff --git a/frame/benchmarking/Cargo.toml b/frame/benchmarking/Cargo.toml index 2bf4a53b0f42..4160f040c3bc 100644 --- a/frame/benchmarking/Cargo.toml +++ b/frame/benchmarking/Cargo.toml @@ -22,6 +22,7 @@ sp-runtime-interface = { version = "4.0.0-dev", path = "../../primitives/runtime sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime", default-features = false } sp-std = { version = "4.0.0-dev", path = "../../primitives/std", default-features = false } sp-io = { version = "4.0.0-dev", path = "../../primitives/io", default-features = false } +sp-application-crypto = { version = "4.0.0-dev", path = "../../primitives/application-crypto", default-features = false } sp-storage = { version = "4.0.0-dev", path = "../../primitives/storage", default-features = false } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } @@ -29,6 +30,7 @@ log = { version = "0.4.14", default-features = false } [dev-dependencies] hex-literal = "0.3.4" +sp-keystore = { version = "0.10.0-dev", path = "../../primitives/keystore" } [features] default = ["std"] diff --git a/frame/benchmarking/src/baseline.rs b/frame/benchmarking/src/baseline.rs index 2b924a692129..87cdf80409b8 100644 --- a/frame/benchmarking/src/baseline.rs +++ b/frame/benchmarking/src/baseline.rs @@ -23,9 +23,23 @@ use crate::benchmarks; use codec::Encode; use frame_system::Pallet as System; -use sp_runtime::traits::Hash; +use sp_application_crypto::KeyTypeId; +use sp_runtime::{ + traits::{AppVerify, Hash}, + RuntimeAppPublic, +}; use sp_std::prelude::*; +pub const TEST_KEY_TYPE_ID: KeyTypeId = KeyTypeId(*b"test"); + +mod app_sr25519 { + use super::TEST_KEY_TYPE_ID; + use sp_application_crypto::{app_crypto, sr25519}; + app_crypto!(sr25519, TEST_KEY_TYPE_ID); +} + +type SignerId = app_sr25519::Public; + pub struct Pallet(System); pub trait Config: frame_system::Config {} @@ -75,6 +89,23 @@ benchmarks! { assert!(hash != T::Hash::default()); } + sr25519_verification { + let i in 1 .. 100; + + let public = SignerId::generate_pair(None); + + let sigs_count: u8 = i.try_into().unwrap(); + let msg_and_sigs: Vec<_> = (0..sigs_count).map(|j| { + let msg = vec![j, j]; + (msg.clone(), public.sign(&msg).unwrap()) + }) + .collect(); + }: { + msg_and_sigs.iter().for_each(|(msg, sig)| { + assert!(sig.verify(&msg[..], &public)); + }); + } + #[skip_meta] storage_read { let i in 0 .. 1_000; @@ -169,7 +200,13 @@ pub mod mock { impl super::Config for Test {} pub fn new_test_ext() -> sp_io::TestExternalities { + use sp_keystore::{testing::KeyStore, KeystoreExt, SyncCryptoStorePtr}; + use sp_std::sync::Arc; + let t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - sp_io::TestExternalities::new(t) + let mut ext = sp_io::TestExternalities::new(t); + ext.register_extension(KeystoreExt(Arc::new(KeyStore::new()) as SyncCryptoStorePtr)); + + ext } } diff --git a/frame/benchmarking/src/weights.rs b/frame/benchmarking/src/weights.rs index 807ff697fdca..af0a782e6b2c 100644 --- a/frame/benchmarking/src/weights.rs +++ b/frame/benchmarking/src/weights.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for frame_benchmarking //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-10-30, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2021-12-02, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 // Executed Command: @@ -35,7 +35,6 @@ // --output=./frame/benchmarking/src/weights.rs // --template=./.maintain/frame-weight-template.hbs - #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] #![allow(unused_imports)] @@ -50,6 +49,7 @@ pub trait WeightInfo { fn multiplication(i: u32, ) -> Weight; fn division(i: u32, ) -> Weight; fn hashing(i: u32, ) -> Weight; + fn sr25519_verification(i: u32, ) -> Weight; fn storage_read(i: u32, ) -> Weight; fn storage_write(i: u32, ) -> Weight; } @@ -58,32 +58,39 @@ pub trait WeightInfo { pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { fn addition(_i: u32, ) -> Weight { - (337_000 as Weight) + (284_000 as Weight) } fn subtraction(_i: u32, ) -> Weight { - (343_000 as Weight) + (279_000 as Weight) } fn multiplication(_i: u32, ) -> Weight { - (340_000 as Weight) + (278_000 as Weight) } fn division(_i: u32, ) -> Weight { - (346_000 as Weight) + (274_000 as Weight) + } + fn hashing(i: u32, ) -> Weight { + (33_441_957_000 as Weight) + // Standard Error: 535_000 + .saturating_add((363_000 as Weight).saturating_mul(i as Weight)) } - fn hashing(_i: u32, ) -> Weight { - (35_449_143_000 as Weight) + fn sr25519_verification(i: u32, ) -> Weight { + (26_000 as Weight) + // Standard Error: 14_000 + .saturating_add((48_151_000 as Weight).saturating_mul(i as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn storage_read(i: u32, ) -> Weight { (0 as Weight) - // Standard Error: 3_000 - .saturating_add((2_851_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 4_000 + .saturating_add((2_694_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) } // Storage: Skipped Metadata (r:0 w:0) fn storage_write(i: u32, ) -> Weight { (0 as Weight) // Standard Error: 0 - .saturating_add((662_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((606_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(i as Weight))) } } @@ -91,32 +98,39 @@ impl WeightInfo for SubstrateWeight { // For backwards compatibility and tests impl WeightInfo for () { fn addition(_i: u32, ) -> Weight { - (337_000 as Weight) + (284_000 as Weight) } fn subtraction(_i: u32, ) -> Weight { - (343_000 as Weight) + (279_000 as Weight) } fn multiplication(_i: u32, ) -> Weight { - (340_000 as Weight) + (278_000 as Weight) } fn division(_i: u32, ) -> Weight { - (346_000 as Weight) + (274_000 as Weight) + } + fn hashing(i: u32, ) -> Weight { + (33_441_957_000 as Weight) + // Standard Error: 535_000 + .saturating_add((363_000 as Weight).saturating_mul(i as Weight)) } - fn hashing(_i: u32, ) -> Weight { - (35_449_143_000 as Weight) + fn sr25519_verification(i: u32, ) -> Weight { + (26_000 as Weight) + // Standard Error: 14_000 + .saturating_add((48_151_000 as Weight).saturating_mul(i as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn storage_read(i: u32, ) -> Weight { (0 as Weight) - // Standard Error: 3_000 - .saturating_add((2_851_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 4_000 + .saturating_add((2_694_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) } // Storage: Skipped Metadata (r:0 w:0) fn storage_write(i: u32, ) -> Weight { (0 as Weight) // Standard Error: 0 - .saturating_add((662_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((606_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(i as Weight))) } } From 264da3bedca973f0028c1e521e96327e2e72c35d Mon Sep 17 00:00:00 2001 From: Nazar Mokrynskyi Date: Tue, 7 Dec 2021 00:35:45 +0200 Subject: [PATCH 259/695] Minor documentation update for `AuxStore` and `BlockImportParams.auxiliary` (#10428) --- client/api/src/backend.rs | 4 ++++ client/consensus/common/src/block_import.rs | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/client/api/src/backend.rs b/client/api/src/backend.rs index a681d75fe9af..f300e31f826c 100644 --- a/client/api/src/backend.rs +++ b/client/api/src/backend.rs @@ -259,6 +259,10 @@ pub trait Finalizer> { } /// Provides access to an auxiliary database. +/// +/// This is a simple global database not aware of forks. Can be used for storing auxiliary +/// information like total block weight/difficulty for fork resolution purposes as a common use +/// case. pub trait AuxStore { /// Insert auxiliary data into key-value store. /// diff --git a/client/consensus/common/src/block_import.rs b/client/consensus/common/src/block_import.rs index 03fde159736c..aff16566e0de 100644 --- a/client/consensus/common/src/block_import.rs +++ b/client/consensus/common/src/block_import.rs @@ -190,8 +190,9 @@ pub struct BlockImportParams { /// rejects block import if there are still intermediate values that remain unhandled. pub intermediates: HashMap, Box>, /// Auxiliary consensus data produced by the block. - /// Contains a list of key-value pairs. If values are `None`, the keys - /// will be deleted. + /// Contains a list of key-value pairs. If values are `None`, the keys will be deleted. These + /// changes will be applied to `AuxStore` database all as one batch, which is more efficient + /// than updating `AuxStore` directly. pub auxiliary: Vec<(Vec, Option>)>, /// Fork choice strategy of this import. This should only be set by a /// synchronous import, otherwise it may race against other imports. From 6079539db562472bce2276cdf44dccef6c2b3a6f Mon Sep 17 00:00:00 2001 From: Ayevbeosa Iyamu Date: Tue, 7 Dec 2021 10:21:27 +0100 Subject: [PATCH 260/695] Used CountedStorageMap in pallet-staking (#10233) * Removed counters and used CountedStorageMap instead. * Little refactoring * Update frame/staking/src/migrations.rs Co-authored-by: Shawn Tabrizi * Removed redundant code to update counter for validator & nominator. * Removed redundant code to update counter for validator & nominator. * Removed unreachable code to inject the hashed prefix for nominator & validator. * Removed redundant check for nominator & validator count. * Generated `fn prefix_hash` for `CountedStorageMap`. * Applied changes from `cargo fmt` * Possible correct implementation of migration code * Implemented fn module_prefix, storage_prefix and prefix_hash. * Removed counted_map.rs * Renamed `fn storage_prefix` to `storage_counter_prefix`. * Update frame/support/src/storage/types/counted_map.rs * Update frame/bags-list/remote-tests/src/snapshot.rs * Update frame/support/src/storage/types/counted_map.rs * Fixed errors. Co-authored-by: Shawn Tabrizi Co-authored-by: Guillaume Thiolliere --- frame/bags-list/remote-tests/src/snapshot.rs | 9 +-- frame/staking/src/benchmarking.rs | 8 +-- frame/staking/src/migrations.rs | 20 +++++-- frame/staking/src/mock.rs | 4 +- frame/staking/src/pallet/impls.rs | 55 ++++++------------- frame/staking/src/pallet/mod.rs | 26 +++------ frame/staking/src/testing_utils.rs | 7 +-- frame/staking/src/tests.rs | 16 +++--- .../support/src/storage/types/counted_map.rs | 11 ++++ 9 files changed, 74 insertions(+), 82 deletions(-) diff --git a/frame/bags-list/remote-tests/src/snapshot.rs b/frame/bags-list/remote-tests/src/snapshot.rs index 0e68a4495edf..f05c00cd9a24 100644 --- a/frame/bags-list/remote-tests/src/snapshot.rs +++ b/frame/bags-list/remote-tests/src/snapshot.rs @@ -27,6 +27,7 @@ pub async fn execute ws_url: String, ) { use frame_support::storage::generator::StorageMap; + let mut ext = Builder::::new() .mode(Mode::Online(OnlineConfig { transport: ws_url.to_string().into(), @@ -38,10 +39,10 @@ pub async fn execute })) .inject_hashed_prefix(&>::prefix_hash()) .inject_hashed_prefix(&>::prefix_hash()) - .inject_hashed_prefix(&>::prefix_hash()) - .inject_hashed_prefix(&>::prefix_hash()) - .inject_hashed_key(&>::hashed_key()) - .inject_hashed_key(&>::hashed_key()) + .inject_hashed_prefix(&>::map_storage_final_prefix()) + .inject_hashed_prefix(&>::map_storage_final_prefix()) + .inject_hashed_key(&>::counter_storage_final_key()) + .inject_hashed_key(&>::counter_storage_final_key()) .build() .await .unwrap(); diff --git a/frame/staking/src/benchmarking.rs b/frame/staking/src/benchmarking.rs index 69a73c51fdc7..5b242e1f223a 100644 --- a/frame/staking/src/benchmarking.rs +++ b/frame/staking/src/benchmarking.rs @@ -112,8 +112,8 @@ pub fn create_validator_with_nominators( assert_eq!(new_validators.len(), 1); assert_eq!(new_validators[0], v_stash, "Our validator was not selected!"); - assert_ne!(CounterForValidators::::get(), 0); - assert_ne!(CounterForNominators::::get(), 0); + assert_ne!(Validators::::count(), 0); + assert_ne!(Nominators::::count(), 0); // Give Era Points let reward = EraRewardPoints:: { @@ -922,8 +922,8 @@ mod tests { let count_validators = Validators::::iter().count(); let count_nominators = Nominators::::iter().count(); - assert_eq!(count_validators, CounterForValidators::::get() as usize); - assert_eq!(count_nominators, CounterForNominators::::get() as usize); + assert_eq!(count_validators, Validators::::count() as usize); + assert_eq!(count_nominators, Nominators::::count() as usize); assert_eq!(count_validators, v as usize); assert_eq!(count_nominators, n as usize); diff --git a/frame/staking/src/migrations.rs b/frame/staking/src/migrations.rs index 6f1d3953f8f1..33f45d80870a 100644 --- a/frame/staking/src/migrations.rs +++ b/frame/staking/src/migrations.rs @@ -70,10 +70,22 @@ pub mod v8 { pub mod v7 { use super::*; + use frame_support::generate_storage_alias; + + generate_storage_alias!(Staking, CounterForValidators => Value); + generate_storage_alias!(Staking, CounterForNominators => Value); pub fn pre_migrate() -> Result<(), &'static str> { - assert!(CounterForValidators::::get().is_zero(), "CounterForValidators already set."); - assert!(CounterForNominators::::get().is_zero(), "CounterForNominators already set."); + assert!( + CounterForValidators::get().unwrap().is_zero(), + "CounterForValidators already set." + ); + assert!( + CounterForNominators::get().unwrap().is_zero(), + "CounterForNominators already set." + ); + assert!(Validators::::count().is_zero(), "Validators already set."); + assert!(Nominators::::count().is_zero(), "Nominators already set."); assert!(StorageVersion::::get() == Releases::V6_0_0); Ok(()) } @@ -83,8 +95,8 @@ pub mod v7 { let validator_count = Validators::::iter().count() as u32; let nominator_count = Nominators::::iter().count() as u32; - CounterForValidators::::put(validator_count); - CounterForNominators::::put(nominator_count); + CounterForValidators::put(validator_count); + CounterForNominators::put(nominator_count); StorageVersion::::put(Releases::V7_0_0); log!(info, "Completed staking migration to Releases::V7_0_0"); diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index 0b1d6a06d9c7..8a8ab1f1e4d0 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -536,8 +536,8 @@ fn post_conditions() { fn check_count() { let nominator_count = Nominators::::iter().count() as u32; let validator_count = Validators::::iter().count() as u32; - assert_eq!(nominator_count, CounterForNominators::::get()); - assert_eq!(validator_count, CounterForValidators::::get()); + assert_eq!(nominator_count, Nominators::::count()); + assert_eq!(validator_count, Validators::::count()); // the voters that the `SortedListProvider` list is storing for us. let external_voters = ::SortedListProvider::count(); diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index cd26ff3b729c..b3158c4ef6b3 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -665,8 +665,8 @@ impl Pallet { maybe_max_len: Option, ) -> Vec<(T::AccountId, VoteWeight, Vec)> { let max_allowed_len = { - let nominator_count = CounterForNominators::::get() as usize; - let validator_count = CounterForValidators::::get() as usize; + let nominator_count = Nominators::::count() as usize; + let validator_count = Validators::::count() as usize; let all_voter_count = validator_count.saturating_add(nominator_count); maybe_max_len.unwrap_or(all_voter_count).min(all_voter_count) }; @@ -765,18 +765,15 @@ impl Pallet { } /// This function will add a nominator to the `Nominators` storage map, - /// [`SortedListProvider`] and keep track of the `CounterForNominators`. + /// and [`SortedListProvider`]. /// /// If the nominator already exists, their nominations will be updated. /// /// NOTE: you must ALWAYS use this function to add nominator or update their targets. Any access - /// to `Nominators`, its counter, or `VoterList` outside of this function is almost certainly + /// to `Nominators` or `VoterList` outside of this function is almost certainly /// wrong. pub fn do_add_nominator(who: &T::AccountId, nominations: Nominations) { if !Nominators::::contains_key(who) { - // maybe update the counter. - CounterForNominators::::mutate(|x| x.saturating_inc()); - // maybe update sorted list. Error checking is defensive-only - this should never fail. if T::SortedListProvider::on_insert(who.clone(), Self::weight_of(who)).is_err() { log!(warn, "attempt to insert duplicate nominator ({:#?})", who); @@ -790,53 +787,46 @@ impl Pallet { } /// This function will remove a nominator from the `Nominators` storage map, - /// [`SortedListProvider`] and keep track of the `CounterForNominators`. + /// and [`SortedListProvider`]. /// /// Returns true if `who` was removed from `Nominators`, otherwise false. /// /// NOTE: you must ALWAYS use this function to remove a nominator from the system. Any access to - /// `Nominators`, its counter, or `VoterList` outside of this function is almost certainly + /// `Nominators` or `VoterList` outside of this function is almost certainly /// wrong. pub fn do_remove_nominator(who: &T::AccountId) -> bool { if Nominators::::contains_key(who) { Nominators::::remove(who); - CounterForNominators::::mutate(|x| x.saturating_dec()); T::SortedListProvider::on_remove(who); debug_assert_eq!(T::SortedListProvider::sanity_check(), Ok(())); - debug_assert_eq!(CounterForNominators::::get(), T::SortedListProvider::count()); + debug_assert_eq!(Nominators::::count(), T::SortedListProvider::count()); true } else { false } } - /// This function will add a validator to the `Validators` storage map, and keep track of the - /// `CounterForValidators`. + /// This function will add a validator to the `Validators` storage map. /// /// If the validator already exists, their preferences will be updated. /// /// NOTE: you must ALWAYS use this function to add a validator to the system. Any access to - /// `Validators`, its counter, or `VoterList` outside of this function is almost certainly + /// `Validators` or `VoterList` outside of this function is almost certainly /// wrong. pub fn do_add_validator(who: &T::AccountId, prefs: ValidatorPrefs) { - if !Validators::::contains_key(who) { - CounterForValidators::::mutate(|x| x.saturating_inc()) - } Validators::::insert(who, prefs); } - /// This function will remove a validator from the `Validators` storage map, - /// and keep track of the `CounterForValidators`. + /// This function will remove a validator from the `Validators` storage map. /// /// Returns true if `who` was removed from `Validators`, otherwise false. /// /// NOTE: you must ALWAYS use this function to remove a validator from the system. Any access to - /// `Validators`, its counter, or `VoterList` outside of this function is almost certainly + /// `Validators` or `VoterList` outside of this function is almost certainly /// wrong. pub fn do_remove_validator(who: &T::AccountId) -> bool { if Validators::::contains_key(who) { Validators::::remove(who); - CounterForValidators::::mutate(|x| x.saturating_dec()); true } else { false @@ -865,14 +855,6 @@ impl ElectionDataProvider> for Pallet fn voters( maybe_max_len: Option, ) -> data_provider::Result)>> { - debug_assert!(>::iter().count() as u32 == CounterForNominators::::get()); - debug_assert!(>::iter().count() as u32 == CounterForValidators::::get()); - debug_assert_eq!( - CounterForNominators::::get(), - T::SortedListProvider::count(), - "voter_count must be accurate", - ); - // This can never fail -- if `maybe_max_len` is `Some(_)` we handle it. let voters = Self::get_npos_voters(maybe_max_len); debug_assert!(maybe_max_len.map_or(true, |max| voters.len() <= max)); @@ -881,7 +863,7 @@ impl ElectionDataProvider> for Pallet } fn targets(maybe_max_len: Option) -> data_provider::Result> { - let target_count = CounterForValidators::::get(); + let target_count = Validators::::count(); // We can't handle this case yet -- return an error. if maybe_max_len.map_or(false, |max_len| target_count > max_len as u32) { @@ -967,10 +949,9 @@ impl ElectionDataProvider> for Pallet fn clear() { >::remove_all(None); >::remove_all(None); - >::remove_all(None); - >::remove_all(None); - >::kill(); - >::kill(); + >::remove_all(); + >::remove_all(); + T::SortedListProvider::unsafe_clear(); } @@ -1284,7 +1265,7 @@ impl SortedListProvider for UseNominatorsMap { Box::new(Nominators::::iter().map(|(n, _)| n)) } fn count() -> u32 { - CounterForNominators::::get() + Nominators::::count() } fn contains(id: &T::AccountId) -> bool { Nominators::::contains_key(id) @@ -1309,10 +1290,10 @@ impl SortedListProvider for UseNominatorsMap { fn sanity_check() -> Result<(), &'static str> { Ok(()) } + fn unsafe_clear() { // NOTE: Caller must ensure this doesn't lead to too many storage accesses. This is a // condition of SortedListProvider::unsafe_clear. - Nominators::::remove_all(None); - CounterForNominators::::take(); + Nominators::::remove_all(); } } diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index f7e96ce0cf76..091df82e2817 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -234,16 +234,10 @@ pub mod pallet { StorageMap<_, Twox64Concat, T::AccountId, RewardDestination, ValueQuery>; /// The map from (wannabe) validator stash key to the preferences of that validator. - /// - /// When updating this storage item, you must also update the `CounterForValidators`. #[pallet::storage] #[pallet::getter(fn validators)] pub type Validators = - StorageMap<_, Twox64Concat, T::AccountId, ValidatorPrefs, ValueQuery>; - - /// A tracker to keep count of the number of items in the `Validators` map. - #[pallet::storage] - pub type CounterForValidators = StorageValue<_, u32, ValueQuery>; + CountedStorageMap<_, Twox64Concat, T::AccountId, ValidatorPrefs, ValueQuery>; /// The maximum validator count before we stop allowing new validators to join. /// @@ -252,16 +246,10 @@ pub mod pallet { pub type MaxValidatorsCount = StorageValue<_, u32, OptionQuery>; /// The map from nominator stash key to the set of stash keys of all validators to nominate. - /// - /// When updating this storage item, you must also update the `CounterForNominators`. #[pallet::storage] #[pallet::getter(fn nominators)] pub type Nominators = - StorageMap<_, Twox64Concat, T::AccountId, Nominations>; - - /// A tracker to keep count of the number of items in the `Nominators` map. - #[pallet::storage] - pub type CounterForNominators = StorageValue<_, u32, ValueQuery>; + CountedStorageMap<_, Twox64Concat, T::AccountId, Nominations>; /// The maximum nominator count before we stop allowing new validators to join. /// @@ -570,7 +558,7 @@ pub mod pallet { // all voters are reported to the `SortedListProvider`. assert_eq!( T::SortedListProvider::count(), - CounterForNominators::::get(), + Nominators::::count(), "not all genesis stakers were inserted into sorted list provider, something is wrong." ); } @@ -987,7 +975,7 @@ pub mod pallet { // the runtime. if let Some(max_validators) = MaxValidatorsCount::::get() { ensure!( - CounterForValidators::::get() < max_validators, + Validators::::count() < max_validators, Error::::TooManyValidators ); } @@ -1027,7 +1015,7 @@ pub mod pallet { // the runtime. if let Some(max_nominators) = MaxNominatorsCount::::get() { ensure!( - CounterForNominators::::get() < max_nominators, + Nominators::::count() < max_nominators, Error::::TooManyNominators ); } @@ -1610,7 +1598,7 @@ pub mod pallet { let min_active_bond = if Nominators::::contains_key(&stash) { let max_nominator_count = MaxNominatorsCount::::get().ok_or(Error::::CannotChillOther)?; - let current_nominator_count = CounterForNominators::::get(); + let current_nominator_count = Nominators::::count(); ensure!( threshold * max_nominator_count < current_nominator_count, Error::::CannotChillOther @@ -1619,7 +1607,7 @@ pub mod pallet { } else if Validators::::contains_key(&stash) { let max_validator_count = MaxValidatorsCount::::get().ok_or(Error::::CannotChillOther)?; - let current_validator_count = CounterForValidators::::get(); + let current_validator_count = Validators::::count(); ensure!( threshold * max_validator_count < current_validator_count, Error::::CannotChillOther diff --git a/frame/staking/src/testing_utils.rs b/frame/staking/src/testing_utils.rs index 611773fc0ccf..1c9163bd5640 100644 --- a/frame/staking/src/testing_utils.rs +++ b/frame/staking/src/testing_utils.rs @@ -36,12 +36,11 @@ const SEED: u32 = 0; /// This function removes all validators and nominators from storage. pub fn clear_validators_and_nominators() { - Validators::::remove_all(None); - CounterForValidators::::kill(); + Validators::::remove_all(); // whenever we touch nominators counter we should update `T::SortedListProvider` as well. - Nominators::::remove_all(None); - CounterForNominators::::kill(); + Nominators::::remove_all(); + // NOTE: safe to call outside block production T::SortedListProvider::unsafe_clear(); } diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 4604351b5230..ec8be43f0284 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -4300,8 +4300,8 @@ fn chill_other_works() { .min_nominator_bond(1_000) .min_validator_bond(1_500) .build_and_execute(|| { - let initial_validators = CounterForValidators::::get(); - let initial_nominators = CounterForNominators::::get(); + let initial_validators = Validators::::count(); + let initial_nominators = Nominators::::count(); for i in 0..15 { let a = 4 * i; let b = 4 * i + 1; @@ -4424,8 +4424,8 @@ fn chill_other_works() { )); // 16 people total because tests start with 2 active one - assert_eq!(CounterForNominators::::get(), 15 + initial_nominators); - assert_eq!(CounterForValidators::::get(), 15 + initial_validators); + assert_eq!(Nominators::::count(), 15 + initial_nominators); + assert_eq!(Validators::::count(), 15 + initial_validators); // Users can now be chilled down to 7 people, so we try to remove 9 of them (starting // with 16) @@ -4437,13 +4437,13 @@ fn chill_other_works() { } // chill a nominator. Limit is not reached, not chill-able - assert_eq!(CounterForNominators::::get(), 7); + assert_eq!(Nominators::::count(), 7); assert_noop!( Staking::chill_other(Origin::signed(1337), 1), Error::::CannotChillOther ); // chill a validator. Limit is reached, chill-able. - assert_eq!(CounterForValidators::::get(), 9); + assert_eq!(Validators::::count(), 9); assert_ok!(Staking::chill_other(Origin::signed(1337), 3)); }) } @@ -4451,9 +4451,9 @@ fn chill_other_works() { #[test] fn capped_stakers_works() { ExtBuilder::default().build_and_execute(|| { - let validator_count = CounterForValidators::::get(); + let validator_count = Validators::::count(); assert_eq!(validator_count, 3); - let nominator_count = CounterForNominators::::get(); + let nominator_count = Nominators::::count(); assert_eq!(nominator_count, 1); // Change the maximums diff --git a/frame/support/src/storage/types/counted_map.rs b/frame/support/src/storage/types/counted_map.rs index 5211453fd09b..01414d7019ae 100644 --- a/frame/support/src/storage/types/counted_map.rs +++ b/frame/support/src/storage/types/counted_map.rs @@ -98,6 +98,17 @@ where OnEmpty: Get + 'static, MaxValues: Get>, { + /// The key used to store the counter of the map. + pub fn counter_storage_final_key() -> [u8; 32] { + CounterFor::::hashed_key() + } + + /// The prefix used to generate the key of the map. + pub fn map_storage_final_prefix() -> Vec { + use crate::storage::generator::StorageMap; + ::Map::prefix_hash() + } + /// Get the storage key used to fetch a value corresponding to a specific key. pub fn hashed_key_for>(key: KeyArg) -> Vec { ::Map::hashed_key_for(key) From a1c31a7bdb004cf9b9c5c0abc723e4cb58d005e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Tue, 7 Dec 2021 13:19:30 +0100 Subject: [PATCH 261/695] contracts: Add storage deposits (#10082) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Frame no longer needs to be mutable (refactoring artifact) * Remove Contract/Tombstone deposit * Add StorageMeter * cargo fmt * Fix weight annotation * cargo run --quiet --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_contracts --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/contracts/src/weights.rs --template=./.maintain/frame-weight-template.hbs * Simplify keep check for contract accounts - Make sure that the "base deposit" for each contract >= ed - Remove now obsolete checks when sneding away free balance * Remove unused imports and functions * Rename storage_limit to storage_deposit_limit * cargo fmt * Fix typo Co-authored-by: Michael Müller * Finish up rename of storage_limit * Fix rpc tests * Make use of `StorageDepositLimitTooHigh` * Add tests and fix bugs discovered by tests * Add storage migration * Don't use u128 in RPC * Fix weight of migration * Rename `endowment` to `value` * Fix bug where contract couldn't get funded by a storage deposit - Make sure that contract gets funded from deposits before value is transferred - Don't reserve value at origin because otherwise funding isn't possible - Just transfer free balance and reserve it after the transfer - When refunding make sure that this refund can't dust the contract - Can only happen after a runtime upgrade where costs where upped - Add more tests * Apply suggestions from code review Co-authored-by: Andrew Jones * Remove unused `fn storage_meter` * Fix copy pasta doc error * Import `MaxEncodeLen` from codec * Beautify RPC trait bounds * Add re-instrument behaviour to dispatchable doc * Make sure a account won't be destroyed a refund after a slash * Apply suggestions from code review Co-authored-by: Andrew Jones * Update `Storage::write` docs * Improve doc * Remove superflous conditional * Typos * Remove superflous clone (refactoring artifact) * Apply suggestions from code review Co-authored-by: Andrew Jones Co-authored-by: Parity Bot Co-authored-by: Michael Müller Co-authored-by: Andrew Jones --- Cargo.lock | 3 + bin/node/executor/Cargo.toml | 1 + bin/node/executor/tests/basic.rs | 6 +- bin/node/executor/tests/common.rs | 2 +- bin/node/runtime/src/lib.rs | 30 +- frame/contracts/Cargo.toml | 1 + frame/contracts/common/Cargo.toml | 2 + frame/contracts/common/src/lib.rs | 183 +- .../fixtures/destroy_and_transfer.wat | 2 +- frame/contracts/fixtures/drain.wat | 6 +- frame/contracts/fixtures/multi_store.wat | 54 + frame/contracts/fixtures/store.wat | 45 + frame/contracts/rpc/runtime-api/src/lib.rs | 20 +- frame/contracts/rpc/src/lib.rs | 167 +- frame/contracts/src/benchmarking/mod.rs | 285 +-- frame/contracts/src/exec.rs | 483 +++-- frame/contracts/src/lib.rs | 298 ++- frame/contracts/src/migration.rs | 142 +- frame/contracts/src/schedule.rs | 4 - frame/contracts/src/storage.rs | 65 +- frame/contracts/src/storage/meter.rs | 726 +++++++ frame/contracts/src/tests.rs | 1499 ++++++++++++--- frame/contracts/src/wasm/code_cache.rs | 243 ++- frame/contracts/src/wasm/mod.rs | 202 +- frame/contracts/src/wasm/prepare.rs | 54 +- frame/contracts/src/wasm/runtime.rs | 69 +- frame/contracts/src/weights.rs | 1677 +++++++++-------- 27 files changed, 4375 insertions(+), 1894 deletions(-) create mode 100644 frame/contracts/fixtures/multi_store.wat create mode 100644 frame/contracts/fixtures/store.wat create mode 100644 frame/contracts/src/storage/meter.rs diff --git a/Cargo.lock b/Cargo.lock index d67ebd7f24dd..08d2ab732839 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4616,6 +4616,7 @@ dependencies = [ "sp-keystore", "sp-runtime", "sp-state-machine", + "sp-tracing", "sp-trie", "wat", ] @@ -5404,6 +5405,7 @@ version = "4.0.0-dev" dependencies = [ "assert_matches", "bitflags", + "env_logger 0.9.0", "frame-benchmarking", "frame-support", "frame-system", @@ -5442,6 +5444,7 @@ dependencies = [ "scale-info", "serde", "sp-core", + "sp-rpc", "sp-runtime", "sp-std", ] diff --git a/bin/node/executor/Cargo.toml b/bin/node/executor/Cargo.toml index 21785079c6c5..6fdd5f8d2351 100644 --- a/bin/node/executor/Cargo.toml +++ b/bin/node/executor/Cargo.toml @@ -20,6 +20,7 @@ sc-executor = { version = "0.10.0-dev", path = "../../../client/executor" } sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" } sp-keystore = { version = "0.10.0-dev", path = "../../../primitives/keystore" } sp-state-machine = { version = "0.10.0-dev", path = "../../../primitives/state-machine" } +sp-tracing = { version = "4.0.0-dev", path = "../../../primitives/tracing" } sp-trie = { version = "4.0.0-dev", path = "../../../primitives/trie" } frame-benchmarking = { version = "4.0.0-dev", path = "../../../frame/benchmarking" } diff --git a/bin/node/executor/tests/basic.rs b/bin/node/executor/tests/basic.rs index 9c460a0238e3..6406a04e8dc6 100644 --- a/bin/node/executor/tests/basic.rs +++ b/bin/node/executor/tests/basic.rs @@ -685,8 +685,6 @@ fn deploying_wasm_contract_should_work() { let addr = pallet_contracts::Pallet::::contract_address(&charlie(), &transfer_ch, &[]); - let subsistence = pallet_contracts::Pallet::::subsistence_threshold(); - let time = 42 * 1000; let b = construct_block( &mut new_test_ext(compact_code_unwrap()), @@ -701,8 +699,9 @@ fn deploying_wasm_contract_should_work() { signed: Some((charlie(), signed_extra(0, 0))), function: Call::Contracts( pallet_contracts::Call::instantiate_with_code:: { - endowment: 1000 * DOLLARS + subsistence, + value: 0, gas_limit: 500_000_000, + storage_deposit_limit: None, code: transfer_code, data: Vec::new(), salt: Vec::new(), @@ -715,6 +714,7 @@ fn deploying_wasm_contract_should_work() { dest: sp_runtime::MultiAddress::Id(addr.clone()), value: 10, gas_limit: 500_000_000, + storage_deposit_limit: None, data: vec![0x00, 0x01, 0x02, 0x03], }), }, diff --git a/bin/node/executor/tests/common.rs b/bin/node/executor/tests/common.rs index c81d6b7c14e0..87506ba66a3e 100644 --- a/bin/node/executor/tests/common.rs +++ b/bin/node/executor/tests/common.rs @@ -119,7 +119,7 @@ pub fn executor_call< hash: sp_core::blake2_256(&code).to_vec(), heap_pages: heap_pages.and_then(|hp| Decode::decode(&mut &hp[..]).ok()), }; - + sp_tracing::try_init_simple(); executor().call::(&mut t, &runtime_code, method, data, use_native, native_call) } diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 2cf6548b7921..9573b86c6ee2 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -897,10 +897,8 @@ impl pallet_tips::Config for Runtime { } parameter_types! { - pub ContractDeposit: Balance = deposit( - 1, - >::contract_info_size(), - ); + pub const DepositPerItem: Balance = deposit(1, 0); + pub const DepositPerByte: Balance = deposit(0, 1); pub const MaxValueSize: u32 = 16 * 1024; // The lazy deletion runs inside on_initialize. pub DeletionWeightLimit: Weight = AVERAGE_ON_INITIALIZE_RATIO * @@ -927,7 +925,8 @@ impl pallet_contracts::Config for Runtime { /// change because that would break already deployed contracts. The `Call` structure itself /// is not allowed to change the indices of existing pallets, too. type CallFilter = Nothing; - type ContractDeposit = ContractDeposit; + type DepositPerItem = DepositPerItem; + type DepositPerByte = DepositPerByte; type CallStack = [pallet_contracts::Frame; 31]; type WeightPrice = pallet_transaction_payment::Pallet; type WeightInfo = pallet_contracts::weights::SubstrateWeight; @@ -1522,21 +1521,32 @@ impl_runtime_apis! { dest: AccountId, value: Balance, gas_limit: u64, + storage_deposit_limit: Option, input_data: Vec, - ) -> pallet_contracts_primitives::ContractExecResult { - Contracts::bare_call(origin, dest, value, gas_limit, input_data, true) + ) -> pallet_contracts_primitives::ContractExecResult { + Contracts::bare_call(origin, dest, value, gas_limit, storage_deposit_limit, input_data, true) } fn instantiate( origin: AccountId, - endowment: Balance, + value: Balance, gas_limit: u64, + storage_deposit_limit: Option, code: pallet_contracts_primitives::Code, data: Vec, salt: Vec, - ) -> pallet_contracts_primitives::ContractInstantiateResult + ) -> pallet_contracts_primitives::ContractInstantiateResult + { + Contracts::bare_instantiate(origin, value, gas_limit, storage_deposit_limit, code, data, salt, true) + } + + fn upload_code( + origin: AccountId, + code: Vec, + storage_deposit_limit: Option, + ) -> pallet_contracts_primitives::CodeUploadResult { - Contracts::bare_instantiate(origin, endowment, gas_limit, code, data, salt, true) + Contracts::bare_upload_code(origin, code, storage_deposit_limit) } fn get_storage( diff --git a/frame/contracts/Cargo.toml b/frame/contracts/Cargo.toml index cc21f19b6352..0b10962f0e63 100644 --- a/frame/contracts/Cargo.toml +++ b/frame/contracts/Cargo.toml @@ -46,6 +46,7 @@ sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primit [dev-dependencies] assert_matches = "1" +env_logger = "0.9" hex-literal = "0.3" pretty_assertions = "1" wat = "1" diff --git a/frame/contracts/common/Cargo.toml b/frame/contracts/common/Cargo.toml index c30efc686940..5f52ce7fcfe5 100644 --- a/frame/contracts/common/Cargo.toml +++ b/frame/contracts/common/Cargo.toml @@ -21,6 +21,7 @@ serde = { version = "1", features = ["derive"], optional = true } # Substrate Dependencies (This crate should not rely on frame) sp-core = { version = "4.0.0-dev", path = "../../../primitives/core", default-features = false } sp-std = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/std" } +sp-rpc = { version = "4.0.0-dev", path = "../../../primitives/rpc", optional = true } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } [features] @@ -31,5 +32,6 @@ std = [ "sp-core/std", "sp-runtime/std", "sp-std/std", + "sp-rpc", "serde", ] diff --git a/frame/contracts/common/src/lib.rs b/frame/contracts/common/src/lib.rs index c57f728c26b6..d8408f77e06e 100644 --- a/frame/contracts/common/src/lib.rs +++ b/frame/contracts/common/src/lib.rs @@ -22,19 +22,32 @@ use bitflags::bitflags; use codec::{Decode, Encode}; use sp_core::Bytes; -use sp_runtime::{DispatchError, RuntimeDebug}; +use sp_runtime::{ + traits::{Saturating, Zero}, + DispatchError, RuntimeDebug, +}; use sp_std::prelude::*; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; +#[cfg(feature = "std")] +use sp_rpc::number::NumberOrHex; + /// Result type of a `bare_call` or `bare_instantiate` call. /// /// It contains the execution result together with some auxiliary information. #[derive(Eq, PartialEq, Encode, Decode, RuntimeDebug)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] -pub struct ContractResult { +#[cfg_attr( + feature = "std", + serde( + rename_all = "camelCase", + bound(serialize = "R: Serialize, Balance: Copy + Into"), + bound(deserialize = "R: Deserialize<'de>, Balance: TryFrom") + ) +)] +pub struct ContractResult { /// How much gas was consumed during execution. pub gas_consumed: u64, /// How much gas is required as gas limit in order to execute this call. @@ -45,7 +58,14 @@ pub struct ContractResult { /// /// This can only different from [`Self::gas_consumed`] when weight pre charging /// is used. Currently, only `seal_call_runtime` makes use of pre charging. + /// Additionally, any `seal_call` or `seal_instantiate` makes use of pre-charging + /// when a non-zero `gas_limit` argument is supplied. pub gas_required: u64, + /// How much balance was deposited and reserved during execution in order to pay for storage. + /// + /// The storage deposit is never actually charged from the caller in case of [`Self::result`] + /// is `Err`. This is because on error all storage changes are rolled back. + pub storage_deposit: StorageDeposit, /// An optional debug message. This message is only filled when explicitly requested /// by the code that calls into the contract. Otherwise it is empty. /// @@ -63,15 +83,20 @@ pub struct ContractResult { #[cfg_attr(feature = "std", serde(with = "as_string"))] pub debug_message: Vec, /// The execution result of the wasm code. - pub result: T, + pub result: R, } /// Result type of a `bare_call` call. -pub type ContractExecResult = ContractResult>; +pub type ContractExecResult = + ContractResult, Balance>; /// Result type of a `bare_instantiate` call. -pub type ContractInstantiateResult = - ContractResult, DispatchError>>; +pub type ContractInstantiateResult = + ContractResult, DispatchError>, Balance>; + +/// Result type of a `bare_code_upload` call. +pub type CodeUploadResult = + Result, DispatchError>; /// Result type of a `get_storage` call. pub type GetStorageResult = Result>, ContractAccessError>; @@ -123,6 +148,17 @@ pub struct InstantiateReturnValue { pub account_id: AccountId, } +/// The result of succesfully uploading a contract. +#[derive(PartialEq, Eq, Encode, Decode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] +pub struct CodeUploadReturnValue { + /// The key under which the new code is stored. + pub code_hash: CodeHash, + /// The deposit that was reserved at the caller. Is zero when the code already existed. + pub deposit: Balance, +} + /// Reference to an existing code hash or a new wasm module. #[derive(Eq, PartialEq, Encode, Decode, RuntimeDebug)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] @@ -134,6 +170,116 @@ pub enum Code { Existing(Hash), } +/// The amount of balance that was either charged or refunded in order to pay for storage. +#[derive(Eq, PartialEq, Ord, PartialOrd, Encode, Decode, RuntimeDebug, Clone)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[cfg_attr( + feature = "std", + serde( + rename_all = "camelCase", + bound(serialize = "Balance: Copy + Into"), + bound(deserialize = "Balance: TryFrom") + ) +)] +pub enum StorageDeposit { + /// The transaction reduced storage consumption. + /// + /// This means that the specified amount of balance was transferred from the involved + /// contracts to the call origin. + #[cfg_attr(feature = "std", serde(with = "as_hex"))] + Refund(Balance), + /// The transaction increased overall storage usage. + /// + /// This means that the specified amount of balance was transferred from the call origin + /// to the contracts involved. + #[cfg_attr(feature = "std", serde(with = "as_hex"))] + Charge(Balance), +} + +impl Default for StorageDeposit { + fn default() -> Self { + Self::Charge(Zero::zero()) + } +} + +impl StorageDeposit { + /// Returns how much balance is charged or `0` in case of a refund. + pub fn charge_or_zero(&self) -> Balance { + match self { + Self::Charge(amount) => *amount, + Self::Refund(_) => Zero::zero(), + } + } + + pub fn is_zero(&self) -> bool { + match self { + Self::Charge(amount) => amount.is_zero(), + Self::Refund(amount) => amount.is_zero(), + } + } +} + +impl StorageDeposit +where + Balance: Saturating + Ord + Copy, +{ + /// This is essentially a saturating signed add. + pub fn saturating_add(&self, rhs: &Self) -> Self { + use StorageDeposit::*; + match (self, rhs) { + (Charge(lhs), Charge(rhs)) => Charge(lhs.saturating_add(*rhs)), + (Refund(lhs), Refund(rhs)) => Refund(lhs.saturating_add(*rhs)), + (Charge(lhs), Refund(rhs)) => + if lhs >= rhs { + Charge(lhs.saturating_sub(*rhs)) + } else { + Refund(rhs.saturating_sub(*lhs)) + }, + (Refund(lhs), Charge(rhs)) => + if lhs > rhs { + Refund(lhs.saturating_sub(*rhs)) + } else { + Charge(rhs.saturating_sub(*lhs)) + }, + } + } + + /// This is essentially a saturating signed sub. + pub fn saturating_sub(&self, rhs: &Self) -> Self { + use StorageDeposit::*; + match (self, rhs) { + (Charge(lhs), Refund(rhs)) => Charge(lhs.saturating_add(*rhs)), + (Refund(lhs), Charge(rhs)) => Refund(lhs.saturating_add(*rhs)), + (Charge(lhs), Charge(rhs)) => + if lhs >= rhs { + Charge(lhs.saturating_sub(*rhs)) + } else { + Refund(rhs.saturating_sub(*lhs)) + }, + (Refund(lhs), Refund(rhs)) => + if lhs > rhs { + Refund(lhs.saturating_sub(*rhs)) + } else { + Charge(rhs.saturating_sub(*lhs)) + }, + } + } + + /// If the amount of deposit (this type) is constrained by a `limit` this calcuates how + /// much balance (if any) is still available from this limit. + /// + /// # Note + /// + /// In case of a refund the return value can be larger than `limit`. + pub fn available(&self, limit: &Balance) -> Balance { + use StorageDeposit::*; + match self { + Charge(amount) => limit.saturating_sub(*amount), + Refund(amount) => limit.saturating_add(*amount), + } + } +} + #[cfg(feature = "std")] mod as_string { use super::*; @@ -149,3 +295,26 @@ mod as_string { Ok(String::deserialize(deserializer)?.into_bytes()) } } + +#[cfg(feature = "std")] +mod as_hex { + use super::*; + use serde::{de::Error as _, Deserializer, Serializer}; + + pub fn serialize(balance: &Balance, serializer: S) -> Result + where + S: Serializer, + Balance: Copy + Into, + { + Into::::into(*balance).serialize(serializer) + } + + pub fn deserialize<'de, D, Balance>(deserializer: D) -> Result + where + D: Deserializer<'de>, + Balance: TryFrom, + { + Balance::try_from(NumberOrHex::deserialize(deserializer)?) + .map_err(|_| D::Error::custom("Cannot decode NumberOrHex to Balance")) + } +} diff --git a/frame/contracts/fixtures/destroy_and_transfer.wat b/frame/contracts/fixtures/destroy_and_transfer.wat index aa13cd8b8107..255547955527 100644 --- a/frame/contracts/fixtures/destroy_and_transfer.wat +++ b/frame/contracts/fixtures/destroy_and_transfer.wat @@ -9,7 +9,7 @@ )) (import "env" "memory" (memory 1 1)) - ;; [0, 8) Endowment to send when creating contract. + ;; [0, 8) value to send when creating contract. (data (i32.const 0) "\00\00\01") ;; [8, 16) Value to send when calling contract. diff --git a/frame/contracts/fixtures/drain.wat b/frame/contracts/fixtures/drain.wat index 546026ac9598..94c651842266 100644 --- a/frame/contracts/fixtures/drain.wat +++ b/frame/contracts/fixtures/drain.wat @@ -33,7 +33,9 @@ ) ) - ;; Self-destruct by sending full balance to the 0 address. + ;; Try to self-destruct by sending full balance to the 0 address. + ;; All the *free* balance will be send away, which is a valid thing to do + ;; because the storage deposits will keep the account alive. (call $assert (i32.eq (call $seal_transfer @@ -42,7 +44,7 @@ (i32.const 0) ;; Pointer to the buffer with value to transfer (i32.const 8) ;; Length of the buffer with value to transfer ) - (i32.const 4) ;; ReturnCode::BelowSubsistenceThreshold + (i32.const 0) ;; ReturnCode::Success ) ) ) diff --git a/frame/contracts/fixtures/multi_store.wat b/frame/contracts/fixtures/multi_store.wat new file mode 100644 index 000000000000..2592baf61835 --- /dev/null +++ b/frame/contracts/fixtures/multi_store.wat @@ -0,0 +1,54 @@ +;; Does two stores to two seperate storage items +;; Expects (len0, len1) as input. +(module + (import "seal0" "seal_set_storage" (func $seal_set_storage (param i32 i32 i32))) + (import "seal0" "seal_input" (func $seal_input (param i32 i32))) + (import "env" "memory" (memory 16 16)) + + ;; [0, 32) storage key 0 + (data (i32.const 0) "\01") + + ;; [32, 64) storage key 1 + (data (i32.const 32) "\02") + + ;; [64, 72) buffer where input is copied (expected sizes of storage items) + + ;; [72, 76) size of the input buffer + (data (i32.const 72) "\08") + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func (export "call") + (call $seal_input (i32.const 64) (i32.const 72)) + + ;; assert input size == 8 + (call $assert + (i32.eq + (i32.load (i32.const 72)) + (i32.const 8) + ) + ) + + ;; place a values in storage sizes are specified in the input buffer + ;; we don't care about the contents of the storage item + (call $seal_set_storage + (i32.const 0) ;; Pointer to storage key + (i32.const 0) ;; Pointer to value + (i32.load (i32.const 64)) ;; Size of value + ) + (call $seal_set_storage + (i32.const 32) ;; Pointer to storage key + (i32.const 0) ;; Pointer to value + (i32.load (i32.const 68)) ;; Size of value + ) + ) + + (func (export "deploy")) +) diff --git a/frame/contracts/fixtures/store.wat b/frame/contracts/fixtures/store.wat new file mode 100644 index 000000000000..9e090d31801f --- /dev/null +++ b/frame/contracts/fixtures/store.wat @@ -0,0 +1,45 @@ +;; Stores a value of the passed size. +(module + (import "seal0" "seal_set_storage" (func $seal_set_storage (param i32 i32 i32))) + (import "seal0" "seal_input" (func $seal_input (param i32 i32))) + (import "env" "memory" (memory 16 16)) + + ;; [0, 32) storage key + (data (i32.const 0) "\01") + + ;; [32, 36) buffer where input is copied (expected size of storage item) + + ;; [36, 40) size of the input buffer + (data (i32.const 36) "\04") + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func (export "call") + (call $seal_input (i32.const 32) (i32.const 36)) + + ;; assert input size == 4 + (call $assert + (i32.eq + (i32.load (i32.const 36)) + (i32.const 4) + ) + ) + + ;; place a value in storage, the size of which is specified by the call input. + ;; we don't care about the contents of the storage item + (call $seal_set_storage + (i32.const 0) ;; Pointer to storage key + (i32.const 0) ;; Pointer to value + (i32.load (i32.const 32)) ;; Size of value + ) + ) + + (func (export "deploy")) +) diff --git a/frame/contracts/rpc/runtime-api/src/lib.rs b/frame/contracts/rpc/runtime-api/src/lib.rs index 20dfbe210e5c..485040fd235c 100644 --- a/frame/contracts/rpc/runtime-api/src/lib.rs +++ b/frame/contracts/rpc/runtime-api/src/lib.rs @@ -25,7 +25,7 @@ use codec::Codec; use pallet_contracts_primitives::{ - Code, ContractExecResult, ContractInstantiateResult, GetStorageResult, + Code, CodeUploadResult, ContractExecResult, ContractInstantiateResult, GetStorageResult, }; use sp_std::vec::Vec; @@ -45,20 +45,32 @@ sp_api::decl_runtime_apis! { dest: AccountId, value: Balance, gas_limit: u64, + storage_deposit_limit: Option, input_data: Vec, - ) -> ContractExecResult; + ) -> ContractExecResult; /// Instantiate a new contract. /// /// See `pallet_contracts::Pallet::instantiate`. fn instantiate( origin: AccountId, - endowment: Balance, + value: Balance, gas_limit: u64, + storage_deposit_limit: Option, code: Code, data: Vec, salt: Vec, - ) -> ContractInstantiateResult; + ) -> ContractInstantiateResult; + + + /// Upload new code without instantiating a contract from it. + /// + /// See `pallet_contracts::Pallet::upload_code`. + fn upload_code( + origin: AccountId, + code: Vec, + storage_deposit_limit: Option, + ) -> CodeUploadResult; /// Query a given storage key in a given contract. /// diff --git a/frame/contracts/rpc/src/lib.rs b/frame/contracts/rpc/src/lib.rs index c82cf44d97c7..c4a577196c99 100644 --- a/frame/contracts/rpc/src/lib.rs +++ b/frame/contracts/rpc/src/lib.rs @@ -22,7 +22,9 @@ use std::sync::Arc; use codec::Codec; use jsonrpc_core::{Error, ErrorCode, Result}; use jsonrpc_derive::rpc; -use pallet_contracts_primitives::{Code, ContractExecResult, ContractInstantiateResult}; +use pallet_contracts_primitives::{ + Code, CodeUploadResult, ContractExecResult, ContractInstantiateResult, +}; use serde::{Deserialize, Serialize}; use sp_api::ProvideRuntimeApi; use sp_blockchain::HeaderBackend; @@ -78,6 +80,7 @@ pub struct CallRequest { dest: AccountId, value: NumberOrHex, gas_limit: NumberOrHex, + storage_deposit_limit: Option, input_data: Bytes, } @@ -87,32 +90,47 @@ pub struct CallRequest { #[serde(deny_unknown_fields)] pub struct InstantiateRequest { origin: AccountId, - endowment: NumberOrHex, + value: NumberOrHex, gas_limit: NumberOrHex, + storage_deposit_limit: Option, code: Code, data: Bytes, salt: Bytes, } +/// A struct that encodes RPC parameters required for a call to upload a new code. +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +#[serde(deny_unknown_fields)] +pub struct CodeUploadRequest { + origin: AccountId, + code: Bytes, + storage_deposit_limit: Option, +} + /// Contracts RPC methods. #[rpc] -pub trait ContractsApi { +pub trait ContractsApi +where + Balance: Copy + TryFrom + Into, +{ /// Executes a call to a contract. /// /// This call is performed locally without submitting any transactions. Thus executing this /// won't change any state. Nonetheless, the calling state-changing contracts is still possible. /// - /// This method is useful for calling getter-like methods on contracts. + /// This method is useful for calling getter-like methods on contracts or to dry-run a + /// a contract call in order to determine the `gas_limit`. #[rpc(name = "contracts_call")] fn call( &self, call_request: CallRequest, at: Option, - ) -> Result; + ) -> Result>; /// Instantiate a new contract. /// - /// This call is performed locally without submitting any transactions. Thus the contract + /// This instantiate is performed locally without submitting any transactions. Thus the contract /// is not actually created. /// /// This method is useful for UIs to dry-run contract instantiations. @@ -121,7 +139,20 @@ pub trait ContractsApi { &self, instantiate_request: InstantiateRequest, at: Option, - ) -> Result>; + ) -> Result>; + + /// Upload new code without instantiating a contract from it. + /// + /// This upload is performed locally without submitting any transactions. Thus executing this + /// won't change any state. + /// + /// This method is useful for UIs to dry-run code upload. + #[rpc(name = "contracts_upload_code")] + fn upload_code( + &self, + upload_request: CodeUploadRequest, + at: Option, + ) -> Result>; /// Returns the value under a specified storage `key` in a contract given by `address` param, /// or `None` if it is not set. @@ -165,54 +196,88 @@ where Hash, >, AccountId: Codec, - Balance: Codec + TryFrom, + Balance: Codec + Copy + TryFrom + Into, Hash: Codec, { fn call( &self, call_request: CallRequest, at: Option<::Hash>, - ) -> Result { + ) -> Result> { let api = self.client.runtime_api(); let at = BlockId::hash(at.unwrap_or_else(|| // If the block hash is not supplied assume the best block. self.client.info().best_hash)); - let CallRequest { origin, dest, value, gas_limit, input_data } = call_request; + let CallRequest { origin, dest, value, gas_limit, storage_deposit_limit, input_data } = + call_request; let value: Balance = decode_hex(value, "balance")?; let gas_limit: Weight = decode_hex(gas_limit, "weight")?; + let storage_deposit_limit: Option = + storage_deposit_limit.map(|l| decode_hex(l, "balance")).transpose()?; limit_gas(gas_limit)?; - let exec_result = api - .call(&at, origin, dest, value, gas_limit, input_data.to_vec()) - .map_err(runtime_error_into_rpc_err)?; - - Ok(exec_result) + api.call(&at, origin, dest, value, gas_limit, storage_deposit_limit, input_data.to_vec()) + .map_err(runtime_error_into_rpc_err) } fn instantiate( &self, instantiate_request: InstantiateRequest, at: Option<::Hash>, - ) -> Result> { + ) -> Result> { let api = self.client.runtime_api(); let at = BlockId::hash(at.unwrap_or_else(|| // If the block hash is not supplied assume the best block. self.client.info().best_hash)); - let InstantiateRequest { origin, endowment, gas_limit, code, data, salt } = - instantiate_request; + let InstantiateRequest { + origin, + value, + gas_limit, + storage_deposit_limit, + code, + data, + salt, + } = instantiate_request; - let endowment: Balance = decode_hex(endowment, "balance")?; + let value: Balance = decode_hex(value, "balance")?; let gas_limit: Weight = decode_hex(gas_limit, "weight")?; + let storage_deposit_limit: Option = + storage_deposit_limit.map(|l| decode_hex(l, "balance")).transpose()?; limit_gas(gas_limit)?; - let exec_result = api - .instantiate(&at, origin, endowment, gas_limit, code, data.to_vec(), salt.to_vec()) - .map_err(runtime_error_into_rpc_err)?; + api.instantiate( + &at, + origin, + value, + gas_limit, + storage_deposit_limit, + code, + data.to_vec(), + salt.to_vec(), + ) + .map_err(runtime_error_into_rpc_err) + } + + fn upload_code( + &self, + upload_request: CodeUploadRequest, + at: Option<::Hash>, + ) -> Result> { + let api = self.client.runtime_api(); + let at = BlockId::hash(at.unwrap_or_else(|| + // If the block hash is not supplied assume the best block. + self.client.info().best_hash)); + + let CodeUploadRequest { origin, code, storage_deposit_limit } = upload_request; - Ok(exec_result) + let storage_deposit_limit: Option = + storage_deposit_limit.map(|l| decode_hex(l, "balance")).transpose()?; + + api.upload_code(&at, origin, code.to_vec(), storage_deposit_limit) + .map_err(runtime_error_into_rpc_err) } fn get_storage( @@ -287,12 +352,14 @@ mod tests { "dest": "5DRakbLVnjVrW6niwLfHGW24EeCEvDAFGEXrtaYS5M4ynoom", "value": "0x112210f4B16c1cb1", "gasLimit": 1000000000000, + "storageDepositLimit": 5000, "inputData": "0x8c97db39" } "#, ) .unwrap(); assert_eq!(req.gas_limit.into_u256(), U256::from(0xe8d4a51000u64)); + assert_eq!(req.storage_deposit_limit.map(|l| l.into_u256()), Some(5000.into())); assert_eq!(req.value.into_u256(), U256::from(1234567890987654321u128)); } @@ -303,7 +370,7 @@ mod tests { r#" { "origin": "5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL", - "endowment": "0x88", + "value": "0x88", "gasLimit": 42, "code": { "existing": "0x1122" }, "data": "0x4299", @@ -314,8 +381,9 @@ mod tests { .unwrap(); assert_eq!(req.origin, "5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL"); - assert_eq!(req.endowment.into_u256(), 0x88.into()); + assert_eq!(req.value.into_u256(), 0x88.into()); assert_eq!(req.gas_limit.into_u256(), 42.into()); + assert_eq!(req.storage_deposit_limit, None); assert_eq!(&*req.data, [0x42, 0x99].as_ref()); assert_eq!(&*req.salt, [0x99, 0x88].as_ref()); let code = match req.code { @@ -325,10 +393,28 @@ mod tests { assert_eq!(&code, "0x1122"); } + #[test] + fn code_upload_request_should_serialize_deserialize_properly() { + type Req = CodeUploadRequest; + let req: Req = serde_json::from_str( + r#" + { + "origin": "5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL", + "code": "0x8c97db39", + "storageDepositLimit": 5000 + } + "#, + ) + .unwrap(); + assert_eq!(req.origin, "5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL"); + assert_eq!(&*req.code, [0x8c, 0x97, 0xdb, 0x39].as_ref()); + assert_eq!(req.storage_deposit_limit.map(|l| l.into_u256()), Some(5000.into())); + } + #[test] fn call_result_should_serialize_deserialize_properly() { fn test(expected: &str) { - let res: ContractExecResult = serde_json::from_str(expected).unwrap(); + let res: ContractExecResult = serde_json::from_str(expected).unwrap(); let actual = serde_json::to_string(&res).unwrap(); assert_eq!(actual, trim(expected).as_str()); } @@ -336,6 +422,7 @@ mod tests { r#"{ "gasConsumed": 5000, "gasRequired": 8000, + "storageDeposit": {"charge": 42000}, "debugMessage": "HelloWorld", "result": { "Ok": { @@ -349,6 +436,7 @@ mod tests { r#"{ "gasConsumed": 3400, "gasRequired": 5200, + "storageDeposit": {"refund": 12000}, "debugMessage": "HelloWorld", "result": { "Err": "BadOrigin" @@ -360,7 +448,8 @@ mod tests { #[test] fn instantiate_result_should_serialize_deserialize_properly() { fn test(expected: &str) { - let res: ContractInstantiateResult = serde_json::from_str(expected).unwrap(); + let res: ContractInstantiateResult = + serde_json::from_str(expected).unwrap(); let actual = serde_json::to_string(&res).unwrap(); assert_eq!(actual, trim(expected).as_str()); } @@ -368,6 +457,7 @@ mod tests { r#"{ "gasConsumed": 5000, "gasRequired": 8000, + "storageDeposit": {"refund": 12000}, "debugMessage": "HelloWorld", "result": { "Ok": { @@ -384,6 +474,7 @@ mod tests { r#"{ "gasConsumed": 3400, "gasRequired": 5200, + "storageDeposit": {"charge": 0}, "debugMessage": "HelloWorld", "result": { "Err": "BadOrigin" @@ -391,4 +482,26 @@ mod tests { }"#, ); } + + #[test] + fn code_upload_result_should_serialize_deserialize_properly() { + fn test(expected: &str) { + let res: CodeUploadResult = serde_json::from_str(expected).unwrap(); + let actual = serde_json::to_string(&res).unwrap(); + assert_eq!(actual, trim(expected).as_str()); + } + test( + r#"{ + "Ok": { + "codeHash": 4711, + "deposit": 99 + } + }"#, + ); + test( + r#"{ + "Err": "BadOrigin" + }"#, + ); + } } diff --git a/frame/contracts/src/benchmarking/mod.rs b/frame/contracts/src/benchmarking/mod.rs index 665ec565c8e6..884fddb6f907 100644 --- a/frame/contracts/src/benchmarking/mod.rs +++ b/frame/contracts/src/benchmarking/mod.rs @@ -57,13 +57,14 @@ struct Contract { caller: T::AccountId, account_id: T::AccountId, addr: ::Source, - endowment: BalanceOf, + value: BalanceOf, } impl Contract where T: Config, T::AccountId: UncheckedFrom + AsRef<[u8]>, + as HasCompact>::Type: Clone + Eq + PartialEq + Debug + TypeInfo + Encode, { /// Create new contract and use a default account id as instantiator. fn new(module: WasmModule, data: Vec) -> Result, &'static str> { @@ -85,27 +86,24 @@ where module: WasmModule, data: Vec, ) -> Result, &'static str> { - let endowment = contract_funding::(); + let value = T::Currency::minimum_balance(); T::Currency::make_free_balance_be(&caller, caller_funding::()); let salt = vec![0xff]; let addr = Contracts::::contract_address(&caller, &module.hash, &salt); - Contracts::::store_code_raw(module.code)?; + Contracts::::store_code_raw(module.code, caller.clone())?; Contracts::::instantiate( RawOrigin::Signed(caller.clone()).into(), - endowment, - Weight::max_value(), + value, + Weight::MAX, + None, module.hash, data, salt, )?; - let result = Contract { - caller, - account_id: addr.clone(), - addr: T::Lookup::unlookup(addr), - endowment, - }; + let result = + Contract { caller, account_id: addr.clone(), addr: T::Lookup::unlookup(addr), value }; ContractInfoOf::::insert(&result.account_id, result.info()?); @@ -134,9 +132,9 @@ where /// Store the supplied storage items into this contracts storage. fn store(&self, items: &Vec<(StorageKey, Vec)>) -> Result<(), &'static str> { - let mut info = self.info()?; + let info = self.info()?; for item in items { - Storage::::write(&mut info, &item.0, Some(item.1.clone())) + Storage::::write(&info.trie_id, &item.0, Some(item.1.clone()), None) .map_err(|_| "Failed to write storage to restoration dest")?; } >::insert(&self.account_id, info.clone()); @@ -152,6 +150,25 @@ where fn info(&self) -> Result, &'static str> { Self::address_info(&self.account_id) } + + /// Set the balance of the contract to the supplied amount. + fn set_balance(&self, balance: BalanceOf) { + T::Currency::make_free_balance_be(&self.account_id, balance); + } + + /// Returns `true` iff all storage entries related to code storage exist. + fn code_exists(hash: &CodeHash) -> bool { + >::contains_key(hash) && + >::contains_key(&hash) && + >::contains_key(&hash) + } + + /// Returns `true` iff no storage entry related to code storage exist. + fn code_removed(hash: &CodeHash) -> bool { + !>::contains_key(hash) && + !>::contains_key(&hash) && + !>::contains_key(&hash) + } } /// The funding that each account that either calls or instantiates contracts is funded with. @@ -159,11 +176,6 @@ fn caller_funding() -> BalanceOf { BalanceOf::::max_value() / 2u32.into() } -/// The funding used for contracts. It is less than `caller_funding` in purpose. -fn contract_funding() -> BalanceOf { - caller_funding::().saturating_sub(T::Currency::minimum_balance() * 100u32.into()) -} - /// Load the specified contract file from disk by including it into the runtime. /// /// We need to load a different version of ink! contracts when the benchmark is run as @@ -186,11 +198,12 @@ benchmarks! { where_clause { where T::AccountId: UncheckedFrom, T::AccountId: AsRef<[u8]>, + as codec::HasCompact>::Type: Clone + Eq + PartialEq + sp_std::fmt::Debug + scale_info::TypeInfo + codec::Encode, } // The base weight without any actual work performed apart from the setup costs. on_initialize {}: { - Storage::::process_deletion_queue_batch(Weight::max_value()) + Storage::::process_deletion_queue_batch(Weight::MAX) } #[skip_meta] @@ -199,7 +212,7 @@ benchmarks! { let instance = Contract::::with_storage(WasmModule::dummy(), k, T::Schedule::get().limits.payload_len)?; Storage::::queue_trie_for_deletion(&instance.info()?)?; }: { - Storage::::process_deletion_queue_batch(Weight::max_value()) + Storage::::process_deletion_queue_batch(Weight::MAX) } on_initialize_per_queue_item { @@ -210,7 +223,7 @@ benchmarks! { ContractInfoOf::::remove(instance.account_id); } }: { - Storage::::process_deletion_queue_batch(Weight::max_value()) + Storage::::process_deletion_queue_batch(Weight::MAX) } // This benchmarks the additional weight that is charged when a contract is executed the @@ -219,9 +232,10 @@ benchmarks! { instrument { let c in 0 .. T::Schedule::get().limits.code_len / 1024; let WasmModule { code, hash, .. } = WasmModule::::sized(c * 1024); - Contracts::::store_code_raw(code)?; - let mut module = PrefabWasmModule::from_storage_noinstr(hash)?; + Contracts::::store_code_raw(code, whitelisted_caller())?; let schedule = T::Schedule::get(); + let mut gas_meter = GasMeter::new(Weight::MAX); + let mut module = PrefabWasmModule::from_storage(hash, &schedule, &mut gas_meter)?; }: { Contracts::::reinstrument_module(&mut module, &schedule)?; } @@ -230,19 +244,11 @@ benchmarks! { code_load { let c in 0 .. T::Schedule::get().limits.code_len / 1024; let WasmModule { code, hash, .. } = WasmModule::::dummy_with_bytes(c * 1024); - Contracts::::store_code_raw(code)?; - }: { - >::from_storage_noinstr(hash)?; - } - - // The weight of changing the refcount of a contract's code per kilobyte. - code_refcount { - let c in 0 .. T::Schedule::get().limits.code_len / 1024; - let WasmModule { code, hash, .. } = WasmModule::::dummy_with_bytes(c * 1024); - Contracts::::store_code_raw(code)?; - let mut gas_meter = GasMeter::new(Weight::max_value()); + Contracts::::store_code_raw(code, whitelisted_caller())?; + let schedule = T::Schedule::get(); + let mut gas_meter = GasMeter::new(Weight::MAX); }: { - >::add_user(hash, &mut gas_meter)?; + >::from_storage(hash, &schedule, &mut gas_meter)?; } // This constructs a contract that is maximal expensive to instrument. @@ -260,18 +266,24 @@ benchmarks! { let c in 0 .. Perbill::from_percent(50).mul_ceil(T::Schedule::get().limits.code_len / 1024); let s in 0 .. code::max_pages::() * 64; let salt = vec![42u8; (s * 1024) as usize]; - let endowment = contract_funding::() / 3u32.into(); + let value = T::Currency::minimum_balance(); let caller = whitelisted_caller(); T::Currency::make_free_balance_be(&caller, caller_funding::()); let WasmModule { code, hash, .. } = WasmModule::::sized(c * 1024); let origin = RawOrigin::Signed(caller.clone()); let addr = Contracts::::contract_address(&caller, &hash, &salt); - }: _(origin, endowment, Weight::max_value(), code, vec![], salt) + }: _(origin, value, Weight::MAX, None, code, vec![], salt) verify { - // endowment was removed from the caller - assert_eq!(T::Currency::free_balance(&caller), caller_funding::() - endowment); - // contract has the full endowment - assert_eq!(T::Currency::free_balance(&addr), endowment); + // the contract itself does not trigger any reserves + let deposit = T::Currency::reserved_balance(&addr); + // uploading the code reserves some balance in the callers account + let code_deposit = T::Currency::reserved_balance(&caller); + assert_eq!( + T::Currency::free_balance(&caller), + caller_funding::() - value - deposit - code_deposit, + ); + // contract has the full value + assert_eq!(T::Currency::free_balance(&addr), value); // instantiate should leave a contract Contract::::address_info(&addr)?; } @@ -281,19 +293,21 @@ benchmarks! { instantiate { let s in 0 .. code::max_pages::() * 64; let salt = vec![42u8; (s * 1024) as usize]; - let endowment = contract_funding::() / 3u32.into(); + let value = T::Currency::minimum_balance(); let caller = whitelisted_caller(); T::Currency::make_free_balance_be(&caller, caller_funding::()); let WasmModule { code, hash, .. } = WasmModule::::dummy(); let origin = RawOrigin::Signed(caller.clone()); let addr = Contracts::::contract_address(&caller, &hash, &salt); - Contracts::::store_code_raw(code)?; - }: _(origin, endowment, Weight::max_value(), hash, vec![], salt) + Contracts::::store_code_raw(code, caller.clone())?; + }: _(origin, value, Weight::MAX, None, hash, vec![], salt) verify { - // endowment was removed from the caller - assert_eq!(T::Currency::free_balance(&caller), caller_funding::() - endowment); - // contract has the full endowment - assert_eq!(T::Currency::free_balance(&addr), endowment); + // the contract itself does not trigger any reserves + let deposit = T::Currency::reserved_balance(&addr); + // value was removed from the caller + assert_eq!(T::Currency::free_balance(&caller), caller_funding::() - value - deposit); + // contract has the full value + assert_eq!(T::Currency::free_balance(&addr), value); // instantiate should leave a contract Contract::::address_info(&addr)?; } @@ -312,12 +326,14 @@ benchmarks! { let origin = RawOrigin::Signed(instance.caller.clone()); let callee = instance.addr.clone(); let before = T::Currency::free_balance(&instance.account_id); - }: _(origin, callee, value, Weight::max_value(), data) + }: _(origin, callee, value, Weight::MAX, None, data) verify { - // endowment and value transfered via call should be removed from the caller + // the contract itself does not trigger any reserves + let deposit = T::Currency::reserved_balance(&instance.account_id); + // value and value transfered via call should be removed from the caller assert_eq!( T::Currency::free_balance(&instance.caller), - caller_funding::() - instance.endowment - value, + caller_funding::() - instance.value - value - deposit, ); // contract should have received the value assert_eq!(T::Currency::free_balance(&instance.account_id), before + value); @@ -325,13 +341,53 @@ benchmarks! { instance.info()?; } + // This constructs a contract that is maximal expensive to instrument. + // It creates a maximum number of metering blocks per byte. + // `c`: Size of the code in kilobytes. + // + // # Note + // + // We cannot let `c` grow to the maximum code size because the code is not allowed + // to be larger than the maximum size **after instrumentation**. + upload_code { + let c in 0 .. Perbill::from_percent(50).mul_ceil(T::Schedule::get().limits.code_len / 1024); + let caller = whitelisted_caller(); + T::Currency::make_free_balance_be(&caller, caller_funding::()); + let WasmModule { code, hash, .. } = WasmModule::::sized(c * 1024); + let origin = RawOrigin::Signed(caller.clone()); + }: _(origin, code, None) + verify { + // uploading the code reserves some balance in the callers account + assert!(T::Currency::reserved_balance(&caller) > 0u32.into()); + assert!(>::code_exists(&hash)); + } + + // Removing code does not depend on the size of the contract because all the information + // needed to verify the removal claim (refcount, owner) is stored in a separate storage + // item (`OwnerInfoOf`). + remove_code { + let caller = whitelisted_caller(); + T::Currency::make_free_balance_be(&caller, caller_funding::()); + let WasmModule { code, hash, .. } = WasmModule::::dummy(); + let origin = RawOrigin::Signed(caller.clone()); + let uploaded = >::bare_upload_code(caller.clone(), code, None)?; + assert_eq!(uploaded.code_hash, hash); + assert_eq!(uploaded.deposit, T::Currency::reserved_balance(&caller)); + assert!(>::code_exists(&hash)); + }: _(origin, hash) + verify { + // removing the code should have unreserved the deposit + assert_eq!(T::Currency::reserved_balance(&caller), 0u32.into()); + assert!(>::code_removed(&hash)); + } + seal_caller { let r in 0 .. API_BENCHMARK_BATCHES; let instance = Contract::::new(WasmModule::getter( "seal_caller", r * API_BENCHMARK_BATCH_SIZE ), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![]) + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) seal_address { let r in 0 .. API_BENCHMARK_BATCHES; @@ -339,7 +395,7 @@ benchmarks! { "seal_address", r * API_BENCHMARK_BATCH_SIZE ), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![]) + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) seal_gas_left { let r in 0 .. API_BENCHMARK_BATCHES; @@ -347,7 +403,7 @@ benchmarks! { "seal_gas_left", r * API_BENCHMARK_BATCH_SIZE ), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![]) + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) seal_balance { let r in 0 .. API_BENCHMARK_BATCHES; @@ -355,7 +411,7 @@ benchmarks! { "seal_balance", r * API_BENCHMARK_BATCH_SIZE ), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![]) + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) seal_value_transferred { let r in 0 .. API_BENCHMARK_BATCHES; @@ -363,7 +419,7 @@ benchmarks! { "seal_value_transferred", r * API_BENCHMARK_BATCH_SIZE ), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![]) + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) seal_minimum_balance { let r in 0 .. API_BENCHMARK_BATCHES; @@ -371,15 +427,7 @@ benchmarks! { "seal_minimum_balance", r * API_BENCHMARK_BATCH_SIZE ), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![]) - - seal_tombstone_deposit { - let r in 0 .. API_BENCHMARK_BATCHES; - let instance = Contract::::new(WasmModule::getter( - "seal_tombstone_deposit", r * API_BENCHMARK_BATCH_SIZE - ), vec![])?; - let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![]) + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) seal_block_number { let r in 0 .. API_BENCHMARK_BATCHES; @@ -387,7 +435,7 @@ benchmarks! { "seal_block_number", r * API_BENCHMARK_BATCH_SIZE ), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![]) + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) seal_now { let r in 0 .. API_BENCHMARK_BATCHES; @@ -395,7 +443,7 @@ benchmarks! { "seal_now", r * API_BENCHMARK_BATCH_SIZE ), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![]) + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) seal_weight_to_fee { let r in 0 .. API_BENCHMARK_BATCHES; @@ -422,7 +470,7 @@ benchmarks! { }); let instance = Contract::::new(code, vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![]) + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) seal_gas { let r in 0 .. API_BENCHMARK_BATCHES; @@ -442,7 +490,7 @@ benchmarks! { let instance = Contract::::new(code, vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![]) + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) seal_input { let r in 0 .. API_BENCHMARK_BATCHES; @@ -469,7 +517,7 @@ benchmarks! { }); let instance = Contract::::new(code, vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![]) + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) seal_input_per_kb { let n in 0 .. code::max_pages::() * 64; @@ -499,7 +547,7 @@ benchmarks! { let instance = Contract::::new(code, vec![])?; let data = vec![42u8; (n * 1024).min(buffer_size) as usize]; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), data) + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, data) // We cannot call `seal_return` multiple times. Therefore our weight determination is not // as precise as with other APIs. Because this function can only be called once per @@ -524,7 +572,7 @@ benchmarks! { }); let instance = Contract::::new(code, vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![]) + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) seal_return_per_kb { let n in 0 .. code::max_pages::() * 64; @@ -547,7 +595,7 @@ benchmarks! { }); let instance = Contract::::new(code, vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![]) + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) // The same argument as for `seal_return` is true here. seal_terminate { @@ -579,12 +627,13 @@ benchmarks! { let instance = Contract::::new(code, vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); assert_eq!(T::Currency::total_balance(&beneficiary), 0u32.into()); - assert_eq!(T::Currency::total_balance(&instance.account_id), contract_funding::()); - }: call(origin, instance.addr.clone(), 0u32.into(), Weight::max_value(), vec![]) + assert_eq!(T::Currency::free_balance(&instance.account_id), T::Currency::minimum_balance()); + assert_ne!(T::Currency::reserved_balance(&instance.account_id), 0u32.into()); + }: call(origin, instance.addr.clone(), 0u32.into(), Weight::MAX, None, vec![]) verify { if r > 0 { assert_eq!(T::Currency::total_balance(&instance.account_id), 0u32.into()); - assert_eq!(T::Currency::total_balance(&beneficiary), contract_funding::()); + assert_eq!(T::Currency::total_balance(&beneficiary), T::Currency::minimum_balance()); } } @@ -621,7 +670,7 @@ benchmarks! { }); let instance = Contract::::new(code, vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![]) + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) // Overhead of calling the function without any topic. // We benchmark for the worst case (largest event). @@ -646,7 +695,7 @@ benchmarks! { }); let instance = Contract::::new(code, vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![]) + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) // Benchmark the overhead that topics generate. // `t`: Number of topics @@ -684,7 +733,7 @@ benchmarks! { }); let instance = Contract::::new(code, vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![]) + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) // The size of the supplied message does not influence the weight because as it is never // processed during on-chain execution: It is only ever read during debugging which happens @@ -710,7 +759,7 @@ benchmarks! { }); let instance = Contract::::new(code, vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![]) + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) // Only the overhead of calling the function itself with minimal arguments. // The contract is a bit more complex because I needs to use different keys in order @@ -747,7 +796,7 @@ benchmarks! { }); let instance = Contract::::new(code, vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![]) + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) seal_set_storage_per_kb { let n in 0 .. T::Schedule::get().limits.payload_len / 1024; @@ -777,7 +826,7 @@ benchmarks! { }); let instance = Contract::::new(code, vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![]) + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) // Similar to seal_set_storage. However, we store all the keys that we are about to // delete beforehand in order to prevent any optimizations that could occur when @@ -811,18 +860,19 @@ benchmarks! { .. Default::default() }); let instance = Contract::::new(code, vec![])?; - let mut info = instance.info()?; + let info = instance.info()?; for key in keys { Storage::::write( - &mut info, + &info.trie_id, key.as_slice().try_into().map_err(|e| "Key has wrong length")?, - Some(vec![42; T::Schedule::get().limits.payload_len as usize]) + Some(vec![42; T::Schedule::get().limits.payload_len as usize]), + None, ) .map_err(|_| "Failed to write to storage during setup.")?; } >::insert(&instance.account_id, info.clone()); let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![]) + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) // We make sure that all storage accesses are to unique keys. #[skip_meta] @@ -858,18 +908,19 @@ benchmarks! { .. Default::default() }); let instance = Contract::::new(code, vec![])?; - let mut info = instance.info()?; + let info = instance.info()?; for key in keys { Storage::::write( - &mut info, + &info.trie_id, key.as_slice().try_into().map_err(|e| "Key has wrong length")?, - Some(vec![]) + Some(vec![]), + None, ) .map_err(|_| "Failed to write to storage during setup.")?; } >::insert(&instance.account_id, info.clone()); let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![]) + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) seal_get_storage_per_kb { let n in 0 .. T::Schedule::get().limits.payload_len / 1024; @@ -904,16 +955,17 @@ benchmarks! { .. Default::default() }); let instance = Contract::::new(code, vec![])?; - let mut info = instance.info()?; + let info = instance.info()?; Storage::::write( - &mut info, + &info.trie_id, key.as_slice().try_into().map_err(|e| "Key has wrong length")?, - Some(vec![42u8; (n * 1024) as usize]) + Some(vec![42u8; (n * 1024) as usize]), + None, ) .map_err(|_| "Failed to write to storage during setup.")?; >::insert(&instance.account_id, info.clone()); let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![]) + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) // We transfer to unique accounts. seal_transfer { @@ -923,7 +975,7 @@ benchmarks! { .collect::>(); let account_len = accounts.get(0).map(|i| i.encode().len()).unwrap_or(0); let account_bytes = accounts.iter().flat_map(|x| x.encode()).collect(); - let value = Contracts::::subsistence_threshold(); + let value = T::Currency::minimum_balance(); assert!(value > 0u32.into()); let value_bytes = value.encode(); let value_len = value_bytes.len(); @@ -956,11 +1008,12 @@ benchmarks! { .. Default::default() }); let instance = Contract::::new(code, vec![])?; + instance.set_balance(value * (r * API_BENCHMARK_BATCH_SIZE + 1).into()); let origin = RawOrigin::Signed(instance.caller.clone()); for account in &accounts { assert_eq!(T::Currency::total_balance(account), 0u32.into()); } - }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![]) + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) verify { for account in &accounts { assert_eq!(T::Currency::total_balance(account), value); @@ -1024,7 +1077,7 @@ benchmarks! { }); let instance = Contract::::new(code, vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![]) + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) seal_call_per_transfer_input_output_kb { let t in 0 .. 1; @@ -1109,9 +1162,9 @@ benchmarks! { }); let instance = Contract::::new(code, vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![]) + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) - // We assume that every instantiate sends at least the subsistence amount. + // We assume that every instantiate sends at least the minimum balance. seal_instantiate { let r in 0 .. API_BENCHMARK_BATCHES; let hashes = (0..r * API_BENCHMARK_BATCH_SIZE) @@ -1127,14 +1180,14 @@ benchmarks! { ])), .. Default::default() }); - Contracts::::store_code_raw(code.code)?; + Contracts::::store_code_raw(code.code, whitelisted_caller())?; Ok(code.hash) }) .collect::, &'static str>>()?; let hash_len = hashes.get(0).map(|x| x.encode().len()).unwrap_or(0); let hashes_bytes = hashes.iter().flat_map(|x| x.encode()).collect::>(); let hashes_len = hashes_bytes.len(); - let value = contract_funding::() / (r * API_BENCHMARK_BATCH_SIZE + 2).into(); + let value = T::Currency::minimum_balance(); assert!(value > 0u32.into()); let value_bytes = value.encode(); let value_len = value_bytes.len(); @@ -1202,6 +1255,7 @@ benchmarks! { .. Default::default() }); let instance = Contract::::new(code, vec![])?; + instance.set_balance(value * (r * API_BENCHMARK_BATCH_SIZE + 1).into()); let origin = RawOrigin::Signed(instance.caller.clone()); let callee = instance.addr.clone(); let addresses = hashes @@ -1216,7 +1270,7 @@ benchmarks! { return Err("Expected that contract does not exist at this point.".into()); } } - }: call(origin, callee, 0u32.into(), Weight::max_value(), vec![]) + }: call(origin, callee, 0u32.into(), Weight::MAX, None, vec![]) verify { for addr in &addresses { ContractInfoOf::::get(&addr) @@ -1252,12 +1306,12 @@ benchmarks! { let hash = callee_code.hash.clone(); let hash_bytes = callee_code.hash.encode(); let hash_len = hash_bytes.len(); - Contracts::::store_code_raw(callee_code.code)?; + Contracts::::store_code_raw(callee_code.code, whitelisted_caller())?; let inputs = (0..API_BENCHMARK_BATCH_SIZE).map(|x| x.encode()).collect::>(); let input_len = inputs.get(0).map(|x| x.len()).unwrap_or(0); let input_bytes = inputs.iter().cloned().flatten().collect::>(); let inputs_len = input_bytes.len(); - let value = contract_funding::() / (API_BENCHMARK_BATCH_SIZE + 2).into(); + let value = T::Currency::minimum_balance(); assert!(value > 0u32.into()); let value_bytes = value.encode(); let value_len = value_bytes.len(); @@ -1340,8 +1394,9 @@ benchmarks! { .. Default::default() }); let instance = Contract::::new(code, vec![])?; + instance.set_balance(value * (API_BENCHMARK_BATCH_SIZE + 1).into()); let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![]) + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) // Only the overhead of calling the function itself with minimal arguments. seal_hash_sha2_256 { @@ -1350,7 +1405,7 @@ benchmarks! { "seal_hash_sha2_256", r * API_BENCHMARK_BATCH_SIZE, 0, ), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![]) + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) // `n`: Input to hash in kilobytes seal_hash_sha2_256_per_kb { @@ -1359,7 +1414,7 @@ benchmarks! { "seal_hash_sha2_256", API_BENCHMARK_BATCH_SIZE, n * 1024, ), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![]) + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) // Only the overhead of calling the function itself with minimal arguments. seal_hash_keccak_256 { @@ -1368,7 +1423,7 @@ benchmarks! { "seal_hash_keccak_256", r * API_BENCHMARK_BATCH_SIZE, 0, ), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![]) + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) // `n`: Input to hash in kilobytes seal_hash_keccak_256_per_kb { @@ -1377,7 +1432,7 @@ benchmarks! { "seal_hash_keccak_256", API_BENCHMARK_BATCH_SIZE, n * 1024, ), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![]) + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) // Only the overhead of calling the function itself with minimal arguments. seal_hash_blake2_256 { @@ -1386,7 +1441,7 @@ benchmarks! { "seal_hash_blake2_256", r * API_BENCHMARK_BATCH_SIZE, 0, ), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![]) + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) // `n`: Input to hash in kilobytes seal_hash_blake2_256_per_kb { @@ -1395,7 +1450,7 @@ benchmarks! { "seal_hash_blake2_256", API_BENCHMARK_BATCH_SIZE, n * 1024, ), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![]) + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) // Only the overhead of calling the function itself with minimal arguments. seal_hash_blake2_128 { @@ -1404,7 +1459,7 @@ benchmarks! { "seal_hash_blake2_128", r * API_BENCHMARK_BATCH_SIZE, 0, ), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![]) + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) // `n`: Input to hash in kilobytes seal_hash_blake2_128_per_kb { @@ -1413,7 +1468,7 @@ benchmarks! { "seal_hash_blake2_128", API_BENCHMARK_BATCH_SIZE, n * 1024, ), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![]) + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) // Only calling the function itself with valid arguments. // It generates different private keys and signatures for the message "Hello world". @@ -1467,7 +1522,7 @@ benchmarks! { }); let instance = Contract::::new(code, vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![]) + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) // We make the assumption that pushing a constant and dropping a value takes roughly // the same amount of time. We follow that `t.load` and `drop` both have the weight @@ -2274,6 +2329,7 @@ benchmarks! { instance.account_id, 0u32.into(), Weight::MAX, + None, data, false, ) @@ -2320,6 +2376,7 @@ benchmarks! { instance.account_id, 0u32.into(), Weight::MAX, + None, data, false, ) diff --git a/frame/contracts/src/exec.rs b/frame/contracts/src/exec.rs index bc88e162c5c0..916c2d3df84f 100644 --- a/frame/contracts/src/exec.rs +++ b/frame/contracts/src/exec.rs @@ -16,12 +16,13 @@ // limitations under the License. use crate::{ - gas::GasMeter, storage::Storage, AccountCounter, BalanceOf, CodeHash, Config, ContractInfo, - ContractInfoOf, Error, Event, Pallet as Contracts, Schedule, + gas::GasMeter, + storage::{self, Storage}, + AccountCounter, BalanceOf, CodeHash, Config, ContractInfo, ContractInfoOf, Error, Event, + Pallet as Contracts, Schedule, }; use frame_support::{ dispatch::{DispatchError, DispatchResult, DispatchResultWithPostInfo, Dispatchable}, - ensure, storage::{with_transaction, TransactionOutcome}, traits::{Contains, Currency, ExistenceRequirement, Get, OriginTrait, Randomness, Time}, weights::Weight, @@ -31,14 +32,9 @@ use pallet_contracts_primitives::ExecReturnValue; use smallvec::{Array, SmallVec}; use sp_core::crypto::UncheckedFrom; use sp_io::crypto::secp256k1_ecdsa_recover_compressed; -use sp_runtime::traits::{Convert, Saturating}; +use sp_runtime::traits::Convert; use sp_std::{marker::PhantomData, mem, prelude::*}; -/// When fields are added to the [`ContractInfo`] that can change during execution this -/// variable needs to be set to true. This will also force changes to the -/// `in_memory_changes_not_discarded` test. -const CONTRACT_INFO_CAN_CHANGE: bool = false; - pub type AccountIdOf = ::AccountId; pub type MomentOf = <::Time as Time>::Moment; pub type SeedOf = ::Hash; @@ -112,7 +108,7 @@ pub trait Ext: sealing::Sealed { /// /// Returns the original code size of the called contract. /// The newly created account will be associated with `code`. `value` specifies the amount of - /// value transferred from this to the newly created account (also known as endowment). + /// value transferred from this to the newly created account. /// /// # Return Value /// @@ -159,7 +155,7 @@ pub trait Ext: sealing::Sealed { /// The `value_transferred` is already added. fn balance(&self) -> BalanceOf; - /// Returns the value transferred along with this call or as endowment. + /// Returns the value transferred along with this call. fn value_transferred(&self) -> BalanceOf; /// Returns a reference to the timestamp of the current block @@ -168,9 +164,6 @@ pub trait Ext: sealing::Sealed { /// Returns the minimum balance that is required for creating an account. fn minimum_balance(&self) -> BalanceOf; - /// Returns the deposit required to instantiate a contract. - fn contract_deposit(&self) -> BalanceOf; - /// Returns a random number for the current block with the given subject. fn random(&self, subject: &[u8]) -> (SeedOf, BlockNumberOf); @@ -209,6 +202,10 @@ pub trait Ext: sealing::Sealed { /// Recovers ECDSA compressed public key based on signature and message hash. fn ecdsa_recover(&self, signature: &[u8; 65], message_hash: &[u8; 32]) -> Result<[u8; 33], ()>; + + /// Tests sometimes need to modify and inspect the contract info directly. + #[cfg(test)] + fn contract_info(&mut self) -> &mut ContractInfo; } /// Describes the different functions that can be exported by an [`Executable`]. @@ -235,37 +232,12 @@ pub trait Executable: Sized { gas_meter: &mut GasMeter, ) -> Result; - /// Load the module from storage without re-instrumenting it. - /// - /// A code module is re-instrumented on-load when it was originally instrumented with - /// an older schedule. This skips this step for cases where the code storage is - /// queried for purposes other than execution. - /// - /// # Note - /// - /// Does not charge from the gas meter. Do not call in contexts where this is important. - fn from_storage_noinstr(code_hash: CodeHash) -> Result; - - /// Increment the refcount by one. Fails if the code does not exist on-chain. - /// - /// Returns the size of the original code. + /// Decrement the refcount by one if the code exists. /// /// # Note /// /// Charges weight proportional to the code size from the gas meter. - fn add_user(code_hash: CodeHash, gas_meter: &mut GasMeter) -> Result<(), DispatchError>; - - /// Decrement the refcount by one and remove the code when it drops to zero. - /// - /// Returns the size of the original code. - /// - /// # Note - /// - /// Charges weight proportional to the code size from the gas meter - fn remove_user( - code_hash: CodeHash, - gas_meter: &mut GasMeter, - ) -> Result<(), DispatchError>; + fn remove_user(code_hash: CodeHash) -> Result<(), DispatchError>; /// Execute the specified exported function and return the result. /// @@ -288,12 +260,6 @@ pub trait Executable: Sized { /// Size of the instrumented code in bytes. fn code_len(&self) -> u32; - - /// Sum of instrumented and pristine code len. - fn aggregate_code_len(&self) -> u32; - - // The number of contracts using this executable. - fn refcount(&self) -> u32; } /// The complete call stack of a contract execution. @@ -314,6 +280,8 @@ pub struct Stack<'a, T: Config, E> { schedule: &'a Schedule, /// The gas meter where costs are charged to. gas_meter: &'a mut GasMeter, + /// The storage meter makes sure that the storage deposit limit is obeyed. + storage_meter: &'a mut storage::meter::Meter, /// The timestamp at the point of call stack instantiation. timestamp: MomentOf, /// The block number at the time of call stack instantiation. @@ -354,7 +322,9 @@ pub struct Frame { /// Determines whether this is a call or instantiate frame. entry_point: ExportedFunction, /// The gas meter capped to the supplied gas limit. - nested_meter: GasMeter, + nested_gas: GasMeter, + /// The storage meter for the individual call. + nested_storage: storage::meter::NestedMeter, /// If `false` the contract enabled its defense against reentrance attacks. allows_reentry: bool, } @@ -396,6 +366,26 @@ enum CachedContract { Terminated, } +impl CachedContract { + /// Return `Some(ContractInfo)` if the contract is in cached state. `None` otherwise. + fn into_contract(self) -> Option> { + if let CachedContract::Cached(contract) = self { + Some(contract) + } else { + None + } + } + + /// Return `Some(&mut ContractInfo)` if the contract is in cached state. `None` otherwise. + fn as_contract(&mut self) -> Option<&mut ContractInfo> { + if let CachedContract::Cached(contract) = self { + Some(contract) + } else { + None + } + } +} + impl Frame { /// Return the `contract_info` of the current contract. fn contract_info(&mut self) -> &mut ContractInfo { @@ -432,6 +422,26 @@ macro_rules! get_cached_or_panic_after_load { }}; } +/// Same as [`Stack::top_frame`]. +/// +/// We need this access as a macro because sometimes hiding the lifetimes behind +/// a function won't work out. +macro_rules! top_frame { + ($stack:expr) => { + $stack.frames.last().unwrap_or(&$stack.first_frame) + }; +} + +/// Same as [`Stack::top_frame_mut`]. +/// +/// We need this access as a macro because sometimes hiding the lifetimes behind +/// a function won't work out. +macro_rules! top_frame_mut { + ($stack:expr) => { + $stack.frames.last_mut().unwrap_or(&mut $stack.first_frame) + }; +} + impl CachedContract { /// Load the `contract_info` from storage if necessary. fn load(&mut self, account_id: &T::AccountId) { @@ -476,6 +486,7 @@ where origin: T::AccountId, dest: T::AccountId, gas_meter: &'a mut GasMeter, + storage_meter: &'a mut storage::meter::Meter, schedule: &'a Schedule, value: BalanceOf, input_data: Vec, @@ -485,6 +496,7 @@ where FrameArgs::Call { dest, cached_info: None }, origin, gas_meter, + storage_meter, schedule, value, debug_message, @@ -506,6 +518,7 @@ where origin: T::AccountId, executable: E, gas_meter: &'a mut GasMeter, + storage_meter: &'a mut storage::meter::Meter, schedule: &'a Schedule, value: BalanceOf, input_data: Vec, @@ -521,6 +534,7 @@ where }, origin, gas_meter, + storage_meter, schedule, value, debug_message, @@ -534,16 +548,18 @@ where args: FrameArgs, origin: T::AccountId, gas_meter: &'a mut GasMeter, + storage_meter: &'a mut storage::meter::Meter, schedule: &'a Schedule, value: BalanceOf, debug_message: Option<&'a mut Vec>, ) -> Result<(Self, E), ExecError> { let (first_frame, executable, account_counter) = - Self::new_frame(args, value, gas_meter, 0, &schedule)?; + Self::new_frame(args, value, gas_meter, storage_meter, 0, &schedule)?; let stack = Self { origin, schedule, gas_meter, + storage_meter, timestamp: T::Time::now(), block_number: >::block_number(), account_counter, @@ -560,10 +576,11 @@ where /// /// This does not take `self` because when constructing the first frame `self` is /// not initialized, yet. - fn new_frame( + fn new_frame( frame_args: FrameArgs, value_transferred: BalanceOf, gas_meter: &mut GasMeter, + storage_meter: &mut storage::meter::GenericMeter, gas_limit: Weight, schedule: &Schedule, ) -> Result<(Frame, E, Option), ExecError> { @@ -598,7 +615,8 @@ where contract_info: CachedContract::Cached(contract_info), account_id, entry_point, - nested_meter: gas_meter.nested(gas_limit)?, + nested_gas: gas_meter.nested(gas_limit)?, + nested_storage: storage_meter.nested(), allows_reentry: true, }; @@ -616,23 +634,28 @@ where return Err(Error::::MaxCallDepthReached.into()) } - if CONTRACT_INFO_CAN_CHANGE { - // We need to make sure that changes made to the contract info are not discarded. - // See the `in_memory_changes_not_discarded` test for more information. - // We do not store on instantiate because we do not allow to call into a contract - // from its own constructor. - let frame = self.top_frame(); - if let (CachedContract::Cached(contract), ExportedFunction::Call) = - (&frame.contract_info, frame.entry_point) - { - >::insert(frame.account_id.clone(), contract.clone()); - } + // We need to make sure that changes made to the contract info are not discarded. + // See the `in_memory_changes_not_discarded` test for more information. + // We do not store on instantiate because we do not allow to call into a contract + // from its own constructor. + let frame = self.top_frame(); + if let (CachedContract::Cached(contract), ExportedFunction::Call) = + (&frame.contract_info, frame.entry_point) + { + >::insert(frame.account_id.clone(), contract.clone()); } - let nested_meter = - &mut self.frames.last_mut().unwrap_or(&mut self.first_frame).nested_meter; - let (frame, executable, _) = - Self::new_frame(frame_args, value_transferred, nested_meter, gas_limit, self.schedule)?; + let frame = top_frame_mut!(self); + let nested_gas = &mut frame.nested_gas; + let nested_storage = &mut frame.nested_storage; + let (frame, executable, _) = Self::new_frame( + frame_args, + value_transferred, + nested_gas, + nested_storage, + gas_limit, + self.schedule, + )?; self.frames.push(frame); Ok(executable) } @@ -643,6 +666,17 @@ where fn run(&mut self, executable: E, input_data: Vec) -> Result { let entry_point = self.top_frame().entry_point; let do_transaction = || { + // We need to charge the storage deposit before the initial transfer so that + // it can create the account in case the initial transfer is < ed. + if entry_point == ExportedFunction::Constructor { + let top_frame = top_frame_mut!(self); + top_frame.nested_storage.charge_instantiate( + &self.origin, + &top_frame.account_id, + &mut top_frame.contract_info.get(&top_frame.account_id), + )?; + } + // Every call or instantiate also optionally transferres balance. self.initial_transfer()?; @@ -653,18 +687,20 @@ where // Additional work needs to be performed in case of an instantiation. if output.is_success() && entry_point == ExportedFunction::Constructor { - let frame = self.top_frame_mut(); - let account_id = frame.account_id.clone(); + let frame = self.top_frame(); // It is not allowed to terminate a contract inside its constructor. - if let CachedContract::Terminated = frame.contract_info { + if matches!(frame.contract_info, CachedContract::Terminated) { return Err(Error::::TerminatedInConstructor.into()) } // Deposit an instantiation event. deposit_event::( vec![], - Event::Instantiated { deployer: self.caller().clone(), contract: account_id }, + Event::Instantiated { + deployer: self.caller().clone(), + contract: frame.account_id.clone(), + }, ); } @@ -700,15 +736,34 @@ where // A `None` means that we are returning from the `first_frame`. let frame = self.frames.pop(); - if let Some(frame) = frame { - let prev = self.top_frame_mut(); + // Both branches do essentially the same with the exception. The difference is that + // the else branch does consume the hardcoded `first_frame`. + if let Some(mut frame) = frame { let account_id = &frame.account_id; - prev.nested_meter.absorb_nested(frame.nested_meter); + let prev = top_frame_mut!(self); + + prev.nested_gas.absorb_nested(frame.nested_gas); + // Only gas counter changes are persisted in case of a failure. if !persist { return } - if let CachedContract::Cached(contract) = frame.contract_info { + + // Record the storage meter changes of the nested call into the parent meter. + // If the dropped frame's contract wasn't terminated we update the deposit counter + // in its contract info. The load is necessary to to pull it from storage in case + // it was invalidated. + frame.contract_info.load(account_id); + let mut contract = frame.contract_info.into_contract(); + prev.nested_storage.absorb( + frame.nested_storage, + &self.origin, + account_id, + contract.as_mut(), + ); + + // In case the contract wasn't terminated we need to persist changes made to it. + if let Some(contract) = contract { // optimization: Predecessor is the same contract. // We can just copy the contract into the predecessor without a storage write. // This is possible when there is no other contract in-between that could @@ -736,14 +791,19 @@ where core::str::from_utf8(msg).unwrap_or(""), ); } - // Write back to the root gas meter. - self.gas_meter.absorb_nested(mem::take(&mut self.first_frame.nested_meter)); - // Only gas counter changes are persisted in case of a failure. + self.gas_meter.absorb_nested(mem::take(&mut self.first_frame.nested_gas)); if !persist { return } - if let CachedContract::Cached(contract) = &self.first_frame.contract_info { - >::insert(&self.first_frame.account_id, contract.clone()); + let mut contract = self.first_frame.contract_info.as_contract(); + self.storage_meter.absorb( + mem::take(&mut self.first_frame.nested_storage), + &self.origin, + &self.first_frame.account_id, + contract.as_deref_mut(), + ); + if let Some(contract) = contract { + >::insert(&self.first_frame.account_id, contract); } if let Some(counter) = self.account_counter { >::set(counter); @@ -752,38 +812,14 @@ where } /// Transfer some funds from `from` to `to`. - /// - /// We only allow allow for draining all funds of the sender if `allow_death` is - /// is specified as `true`. Otherwise, any transfer that would bring the sender below the - /// subsistence threshold (for contracts) or the existential deposit (for plain accounts) - /// results in an error. fn transfer( - sender_is_contract: bool, - allow_death: bool, + existence_requirement: ExistenceRequirement, from: &T::AccountId, to: &T::AccountId, value: BalanceOf, ) -> DispatchResult { - if value == 0u32.into() { - return Ok(()) - } - - let existence_requirement = match (allow_death, sender_is_contract) { - (true, _) => ExistenceRequirement::AllowDeath, - (false, true) => { - ensure!( - T::Currency::total_balance(from).saturating_sub(value) >= - Contracts::::subsistence_threshold(), - Error::::BelowSubsistenceThreshold, - ); - ExistenceRequirement::KeepAlive - }, - (false, false) => ExistenceRequirement::KeepAlive, - }; - T::Currency::transfer(from, to, value, existence_requirement) .map_err(|_| Error::::TransferFailed)?; - Ok(()) } @@ -791,31 +827,18 @@ where fn initial_transfer(&self) -> DispatchResult { let frame = self.top_frame(); let value = frame.value_transferred; - let subsistence_threshold = >::subsistence_threshold(); - - // If the value transferred to a new contract is less than the subsistence threshold - // we can error out early. This avoids executing the constructor in cases where - // we already know that the contract has too little balance. - if frame.entry_point == ExportedFunction::Constructor && value < subsistence_threshold { - return Err(>::NewContractNotFunded.into()) - } - Self::transfer(self.caller_is_origin(), false, self.caller(), &frame.account_id, value) - } - - /// Wether the caller is the initiator of the call stack. - fn caller_is_origin(&self) -> bool { - !self.frames.is_empty() + Self::transfer(ExistenceRequirement::KeepAlive, self.caller(), &frame.account_id, value) } /// Reference to the current (top) frame. fn top_frame(&self) -> &Frame { - self.frames.last().unwrap_or(&self.first_frame) + top_frame!(self) } /// Mutable reference to the current (top) frame. fn top_frame_mut(&mut self) -> &mut Frame { - self.frames.last_mut().unwrap_or(&mut self.first_frame) + top_frame_mut!(self) } /// Iterator over all frames. @@ -911,7 +934,7 @@ where &mut self, gas_limit: Weight, code_hash: CodeHash, - endowment: BalanceOf, + value: BalanceOf, input_data: Vec, salt: &[u8], ) -> Result<(AccountIdOf, ExecReturnValue), ExecError> { @@ -924,7 +947,7 @@ where executable, salt, }, - endowment, + value, gas_limit, )?; let account_id = self.top_frame().account_id.clone(); @@ -937,16 +960,16 @@ where } let frame = self.top_frame_mut(); let info = frame.terminate(); + frame.nested_storage.terminate(&info); Storage::::queue_trie_for_deletion(&info)?; >::transfer( - true, - true, + ExistenceRequirement::AllowDeath, &frame.account_id, beneficiary, T::Currency::free_balance(&frame.account_id), )?; ContractInfoOf::::remove(&frame.account_id); - E::remove_user(info.code_hash, &mut frame.nested_meter)?; + E::remove_user(info.code_hash)?; Contracts::::deposit_event(Event::Terminated { contract: frame.account_id.clone(), beneficiary: beneficiary.clone(), @@ -955,7 +978,7 @@ where } fn transfer(&mut self, to: &T::AccountId, value: BalanceOf) -> DispatchResult { - Self::transfer(true, false, &self.top_frame().account_id, to, value) + Self::transfer(ExistenceRequirement::KeepAlive, &self.top_frame().account_id, to, value) } fn get_storage(&mut self, key: &StorageKey) -> Option> { @@ -964,7 +987,12 @@ where fn set_storage(&mut self, key: StorageKey, value: Option>) -> DispatchResult { let frame = self.top_frame_mut(); - Storage::::write(frame.contract_info(), &key, value) + Storage::::write( + &frame.contract_info.get(&frame.account_id).trie_id, + &key, + value, + Some(&mut frame.nested_storage), + ) } fn address(&self) -> &T::AccountId { @@ -995,10 +1023,6 @@ where T::Currency::minimum_balance() } - fn contract_deposit(&self) -> BalanceOf { - T::ContractDeposit::get() - } - fn deposit_event(&mut self, topics: Vec, data: Vec) { deposit_event::( topics, @@ -1023,7 +1047,7 @@ where } fn gas_meter(&mut self) -> &mut GasMeter { - &mut self.top_frame_mut().nested_meter + &mut self.top_frame_mut().nested_gas } fn append_debug_buffer(&mut self, msg: &str) -> bool { @@ -1046,6 +1070,11 @@ where fn ecdsa_recover(&self, signature: &[u8; 65], message_hash: &[u8; 32]) -> Result<[u8; 33], ()> { secp256k1_ecdsa_recover_compressed(&signature, &message_hash).map_err(|_| ()) } + + #[cfg(test)] + fn contract_info(&mut self) -> &mut ContractInfo { + self.top_frame_mut().contract_info() + } } fn deposit_event(topics: Vec, event: Event) { @@ -1083,9 +1112,9 @@ mod tests { storage::Storage, tests::{ test_utils::{get_balance, place_contract, set_balance}, - Call, Event as MetaEvent, ExtBuilder, Test, TestFilter, ALICE, BOB, CHARLIE, + Call, Event as MetaEvent, ExtBuilder, Test, TestFilter, ALICE, BOB, CHARLIE, GAS_LIMIT, }, - Error, Weight, + Error, }; use assert_matches::assert_matches; use codec::{Decode, Encode}; @@ -1101,8 +1130,6 @@ mod tests { type MockStack<'a> = Stack<'a, Test, MockExecutable>; - const GAS_LIMIT: Weight = 10_000_000_000; - thread_local! { static LOADER: RefCell = RefCell::new(MockLoader::default()); } @@ -1193,10 +1220,6 @@ mod tests { _schedule: &Schedule, _gas_meter: &mut GasMeter, ) -> Result { - Self::from_storage_noinstr(code_hash) - } - - fn from_storage_noinstr(code_hash: CodeHash) -> Result { LOADER.with(|loader| { loader .borrow_mut() @@ -1207,18 +1230,7 @@ mod tests { }) } - fn add_user( - code_hash: CodeHash, - _: &mut GasMeter, - ) -> Result<(), DispatchError> { - MockLoader::increment_refcount(code_hash); - Ok(()) - } - - fn remove_user( - code_hash: CodeHash, - _: &mut GasMeter, - ) -> Result<(), DispatchError> { + fn remove_user(code_hash: CodeHash) -> Result<(), DispatchError> { MockLoader::decrement_refcount(code_hash); Ok(()) } @@ -1246,14 +1258,6 @@ mod tests { fn code_len(&self) -> u32 { 0 } - - fn aggregate_code_len(&self) -> u32 { - 0 - } - - fn refcount(&self) -> u32 { - self.refcount as u32 - } } fn exec_success() -> ExecResult { @@ -1280,9 +1284,19 @@ mod tests { ExtBuilder::default().build().execute_with(|| { let schedule = ::Schedule::get(); place_contract(&BOB, exec_ch); + let mut storage_meter = storage::meter::Meter::new(&ALICE, Some(0), value).unwrap(); assert_matches!( - MockStack::run_call(ALICE, BOB, &mut gas_meter, &schedule, value, vec![], None,), + MockStack::run_call( + ALICE, + BOB, + &mut gas_meter, + &mut storage_meter, + &schedule, + value, + vec![], + None, + ), Ok(_) ); }); @@ -1301,7 +1315,7 @@ mod tests { set_balance(&origin, 100); set_balance(&dest, 0); - MockStack::transfer(true, false, &origin, &dest, 55).unwrap(); + MockStack::transfer(ExistenceRequirement::KeepAlive, &origin, &dest, 55).unwrap(); assert_eq!(get_balance(&origin), 45); assert_eq!(get_balance(&dest), 55); @@ -1324,11 +1338,13 @@ mod tests { place_contract(&dest, return_ch); set_balance(&origin, 100); let balance = get_balance(&dest); + let mut storage_meter = storage::meter::Meter::new(&origin, Some(0), 55).unwrap(); let output = MockStack::run_call( origin.clone(), dest.clone(), &mut GasMeter::::new(GAS_LIMIT), + &mut storage_meter, &schedule, 55, vec![], @@ -1352,7 +1368,7 @@ mod tests { ExtBuilder::default().build().execute_with(|| { set_balance(&origin, 0); - let result = MockStack::transfer(false, false, &origin, &dest, 100); + let result = MockStack::transfer(ExistenceRequirement::KeepAlive, &origin, &dest, 100); assert_eq!(result, Err(Error::::TransferFailed.into())); assert_eq!(get_balance(&origin), 0); @@ -1372,12 +1388,14 @@ mod tests { ExtBuilder::default().build().execute_with(|| { let schedule = ::Schedule::get(); + let mut storage_meter = storage::meter::Meter::new(&origin, Some(0), 0).unwrap(); place_contract(&BOB, return_ch); let result = MockStack::run_call( origin, dest, &mut GasMeter::::new(GAS_LIMIT), + &mut storage_meter, &schedule, 0, vec![], @@ -1403,11 +1421,13 @@ mod tests { ExtBuilder::default().build().execute_with(|| { let schedule = ::Schedule::get(); place_contract(&BOB, return_ch); + let mut storage_meter = storage::meter::Meter::new(&origin, Some(0), 0).unwrap(); let result = MockStack::run_call( origin, dest, &mut GasMeter::::new(GAS_LIMIT), + &mut storage_meter, &schedule, 0, vec![], @@ -1431,11 +1451,13 @@ mod tests { ExtBuilder::default().build().execute_with(|| { let schedule = ::Schedule::get(); place_contract(&BOB, input_data_ch); + let mut storage_meter = storage::meter::Meter::new(&ALICE, Some(0), 0).unwrap(); let result = MockStack::run_call( ALICE, BOB, &mut GasMeter::::new(GAS_LIMIT), + &mut storage_meter, &schedule, 0, vec![1, 2, 3, 4], @@ -1455,19 +1477,21 @@ mod tests { // This one tests passing the input data into a contract via instantiate. ExtBuilder::default().build().execute_with(|| { let schedule = ::Schedule::get(); - let subsistence = Contracts::::subsistence_threshold(); + let min_balance = ::Currency::minimum_balance(); let mut gas_meter = GasMeter::::new(GAS_LIMIT); let executable = MockExecutable::from_storage(input_data_ch, &schedule, &mut gas_meter).unwrap(); - - set_balance(&ALICE, subsistence * 10); + set_balance(&ALICE, min_balance * 1000); + let mut storage_meter = + storage::meter::Meter::new(&ALICE, Some(min_balance * 100), min_balance).unwrap(); let result = MockStack::run_instantiate( ALICE, executable, &mut gas_meter, + &mut storage_meter, &schedule, - subsistence * 3, + min_balance, vec![1, 2, 3, 4], &[], None, @@ -1508,11 +1532,13 @@ mod tests { let schedule = ::Schedule::get(); set_balance(&BOB, 1); place_contract(&BOB, recurse_ch); + let mut storage_meter = storage::meter::Meter::new(&ALICE, Some(0), value).unwrap(); let result = MockStack::run_call( ALICE, BOB, &mut GasMeter::::new(GAS_LIMIT), + &mut storage_meter, &schedule, value, vec![], @@ -1553,11 +1579,13 @@ mod tests { let schedule = ::Schedule::get(); place_contract(&dest, bob_ch); place_contract(&CHARLIE, charlie_ch); + let mut storage_meter = storage::meter::Meter::new(&origin, Some(0), 0).unwrap(); let result = MockStack::run_call( origin.clone(), dest.clone(), &mut GasMeter::::new(GAS_LIMIT), + &mut storage_meter, &schedule, 0, vec![], @@ -1590,11 +1618,13 @@ mod tests { let schedule = ::Schedule::get(); place_contract(&BOB, bob_ch); place_contract(&CHARLIE, charlie_ch); + let mut storage_meter = storage::meter::Meter::new(&ALICE, Some(0), 0).unwrap(); let result = MockStack::run_call( ALICE, BOB, &mut GasMeter::::new(GAS_LIMIT), + &mut storage_meter, &schedule, 0, vec![], @@ -1614,14 +1644,16 @@ mod tests { let mut gas_meter = GasMeter::::new(GAS_LIMIT); let executable = MockExecutable::from_storage(dummy_ch, &schedule, &mut gas_meter).unwrap(); + let mut storage_meter = storage::meter::Meter::new(&ALICE, Some(0), 0).unwrap(); assert_matches!( MockStack::run_instantiate( ALICE, executable, &mut gas_meter, + &mut storage_meter, &schedule, - 0, // <- zero endowment + 0, // <- zero value vec![], &[], None, @@ -1639,18 +1671,22 @@ mod tests { ExtBuilder::default().existential_deposit(15).build().execute_with(|| { let schedule = ::Schedule::get(); + let min_balance = ::Currency::minimum_balance(); let mut gas_meter = GasMeter::::new(GAS_LIMIT); let executable = MockExecutable::from_storage(dummy_ch, &schedule, &mut gas_meter).unwrap(); - set_balance(&ALICE, 1000); + set_balance(&ALICE, min_balance * 1000); + let mut storage_meter = + storage::meter::Meter::new(&ALICE, Some(min_balance * 100), min_balance).unwrap(); let instantiated_contract_address = assert_matches!( MockStack::run_instantiate( ALICE, executable, &mut gas_meter, + &mut storage_meter, &schedule, - 100, + min_balance, vec![], &[], None, @@ -1679,18 +1715,22 @@ mod tests { ExtBuilder::default().existential_deposit(15).build().execute_with(|| { let schedule = ::Schedule::get(); + let min_balance = ::Currency::minimum_balance(); let mut gas_meter = GasMeter::::new(GAS_LIMIT); let executable = MockExecutable::from_storage(dummy_ch, &schedule, &mut gas_meter).unwrap(); - set_balance(&ALICE, 1000); + set_balance(&ALICE, min_balance * 1000); + let mut storage_meter = + storage::meter::Meter::new(&ALICE, Some(min_balance * 100), min_balance).unwrap(); let instantiated_contract_address = assert_matches!( MockStack::run_instantiate( ALICE, executable, &mut gas_meter, + &mut storage_meter, &schedule, - 100, + min_balance, vec![], &[], None, @@ -1718,7 +1758,7 @@ mod tests { .instantiate( 0, dummy_ch, - Contracts::::subsistence_threshold() * 3, + ::Currency::minimum_balance(), vec![], &[48, 49, 50], ) @@ -1731,16 +1771,21 @@ mod tests { ExtBuilder::default().existential_deposit(15).build().execute_with(|| { let schedule = ::Schedule::get(); - set_balance(&ALICE, Contracts::::subsistence_threshold() * 100); + let min_balance = ::Currency::minimum_balance(); + set_balance(&ALICE, min_balance * 100); place_contract(&BOB, instantiator_ch); + let mut storage_meter = + storage::meter::Meter::new(&ALICE, Some(min_balance * 10), min_balance * 10) + .unwrap(); assert_matches!( MockStack::run_call( ALICE, BOB, &mut GasMeter::::new(GAS_LIMIT), + &mut storage_meter, &schedule, - 20, + min_balance * 10, vec![], None, ), @@ -1774,7 +1819,7 @@ mod tests { ctx.ext.instantiate( 0, dummy_ch, - Contracts::::subsistence_threshold(), + ::Currency::minimum_balance(), vec![], &[], ), @@ -1793,14 +1838,16 @@ mod tests { set_balance(&ALICE, 1000); set_balance(&BOB, 100); place_contract(&BOB, instantiator_ch); + let mut storage_meter = storage::meter::Meter::new(&ALICE, Some(100), 0).unwrap(); assert_matches!( MockStack::run_call( ALICE, BOB, &mut GasMeter::::new(GAS_LIMIT), + &mut storage_meter, &schedule, - 20, + 0, vec![], None, ), @@ -1826,12 +1873,14 @@ mod tests { let executable = MockExecutable::from_storage(terminate_ch, &schedule, &mut gas_meter).unwrap(); set_balance(&ALICE, 1000); + let mut storage_meter = storage::meter::Meter::new(&ALICE, Some(100), 100).unwrap(); assert_eq!( MockStack::run_instantiate( ALICE, executable, &mut gas_meter, + &mut storage_meter, &schedule, 100, vec![], @@ -1847,10 +1896,6 @@ mod tests { #[test] fn in_memory_changes_not_discarded() { - // Remove this assert and fill out the "DO" stubs once fields are added to the - // contract info that can be modified during exection. - assert!(!CONTRACT_INFO_CAN_CHANGE); - // Call stack: BOB -> CHARLIE (trap) -> BOB' (success) // This tests verfies some edge case of the contract info cache: // We change some value in our contract info before calling into a contract @@ -1861,9 +1906,11 @@ mod tests { // are made before calling into CHARLIE are not discarded. let code_bob = MockLoader::insert(Call, |ctx, _| { if ctx.input_data[0] == 0 { - // DO: modify medata (ContractInfo) of own contract through ctx.ext functions + let info = ctx.ext.contract_info(); + assert_eq!(info.storage_deposit, 0); + info.storage_deposit = 42; assert_eq!(ctx.ext.call(0, CHARLIE, 0, vec![], true), exec_trapped()); - // DO: check that the value is not discarded (query via ctx.ext) + assert_eq!(ctx.ext.contract_info().storage_deposit, 42); } exec_success() }); @@ -1877,11 +1924,13 @@ mod tests { let schedule = ::Schedule::get(); place_contract(&BOB, code_bob); place_contract(&CHARLIE, code_charlie); + let mut storage_meter = storage::meter::Meter::new(&ALICE, Some(0), 0).unwrap(); let result = MockStack::run_call( ALICE, BOB, &mut GasMeter::::new(GAS_LIMIT), + &mut storage_meter, &schedule, 0, vec![0], @@ -1904,18 +1953,20 @@ mod tests { // This one tests passing the input data into a contract via instantiate. ExtBuilder::default().build().execute_with(|| { let schedule = ::Schedule::get(); - let subsistence = Contracts::::subsistence_threshold(); + let min_balance = ::Currency::minimum_balance(); let mut gas_meter = GasMeter::::new(GAS_LIMIT); let executable = MockExecutable::from_storage(code, &schedule, &mut gas_meter).unwrap(); - - set_balance(&ALICE, subsistence * 10); + set_balance(&ALICE, min_balance * 1000); + let mut storage_meter = + storage::meter::Meter::new(&ALICE, Some(min_balance * 100), min_balance).unwrap(); let result = MockStack::run_instantiate( ALICE, executable, &mut gas_meter, + &mut storage_meter, &schedule, - subsistence * 3, + min_balance, vec![], &[], None, @@ -1935,15 +1986,17 @@ mod tests { let mut debug_buffer = Vec::new(); ExtBuilder::default().build().execute_with(|| { - let subsistence = Contracts::::subsistence_threshold(); + let min_balance = ::Currency::minimum_balance(); let schedule = ::Schedule::get(); let mut gas_meter = GasMeter::::new(GAS_LIMIT); - set_balance(&ALICE, subsistence * 10); + set_balance(&ALICE, min_balance * 10); place_contract(&BOB, code_hash); + let mut storage_meter = storage::meter::Meter::new(&ALICE, Some(0), 0).unwrap(); MockStack::run_call( ALICE, BOB, &mut gas_meter, + &mut storage_meter, &schedule, 0, vec![], @@ -1966,15 +2019,17 @@ mod tests { let mut debug_buffer = Vec::new(); ExtBuilder::default().build().execute_with(|| { - let subsistence = Contracts::::subsistence_threshold(); + let min_balance = ::Currency::minimum_balance(); let schedule = ::Schedule::get(); let mut gas_meter = GasMeter::::new(GAS_LIMIT); - set_balance(&ALICE, subsistence * 10); + set_balance(&ALICE, min_balance * 10); place_contract(&BOB, code_hash); + let mut storage_meter = storage::meter::Meter::new(&ALICE, Some(0), 0).unwrap(); let result = MockStack::run_call( ALICE, BOB, &mut gas_meter, + &mut storage_meter, &schedule, 0, vec![], @@ -2000,12 +2055,14 @@ mod tests { let schedule = ::Schedule::get(); place_contract(&BOB, code_bob); place_contract(&CHARLIE, code_charlie); + let mut storage_meter = storage::meter::Meter::new(&ALICE, Some(0), 0).unwrap(); // Calling another contract should succeed assert_ok!(MockStack::run_call( ALICE, BOB, &mut GasMeter::::new(GAS_LIMIT), + &mut storage_meter, &schedule, 0, CHARLIE.encode(), @@ -2018,6 +2075,7 @@ mod tests { ALICE, BOB, &mut GasMeter::::new(GAS_LIMIT), + &mut storage_meter, &schedule, 0, BOB.encode(), @@ -2047,6 +2105,7 @@ mod tests { let schedule = ::Schedule::get(); place_contract(&BOB, code_bob); place_contract(&CHARLIE, code_charlie); + let mut storage_meter = storage::meter::Meter::new(&ALICE, Some(0), 0).unwrap(); // BOB -> CHARLIE -> BOB fails as BOB denies reentry. assert_err!( @@ -2054,6 +2113,7 @@ mod tests { ALICE, BOB, &mut GasMeter::::new(GAS_LIMIT), + &mut storage_meter, &schedule, 0, vec![0], @@ -2076,13 +2136,24 @@ mod tests { }); ExtBuilder::default().build().execute_with(|| { - let subsistence = Contracts::::subsistence_threshold(); + let min_balance = ::Currency::minimum_balance(); let schedule = ::Schedule::get(); let mut gas_meter = GasMeter::::new(GAS_LIMIT); - set_balance(&ALICE, subsistence * 10); + set_balance(&ALICE, min_balance * 10); place_contract(&BOB, code_hash); + let mut storage_meter = storage::meter::Meter::new(&ALICE, Some(0), 0).unwrap(); System::reset_events(); - MockStack::run_call(ALICE, BOB, &mut gas_meter, &schedule, 0, vec![], None).unwrap(); + MockStack::run_call( + ALICE, + BOB, + &mut gas_meter, + &mut storage_meter, + &schedule, + 0, + vec![], + None, + ) + .unwrap(); let remark_hash = ::Hashing::hash(b"Hello World"); assert_eq!( @@ -2136,13 +2207,24 @@ mod tests { }); ExtBuilder::default().build().execute_with(|| { - let subsistence = Contracts::::subsistence_threshold(); + let min_balance = ::Currency::minimum_balance(); let schedule = ::Schedule::get(); let mut gas_meter = GasMeter::::new(GAS_LIMIT); - set_balance(&ALICE, subsistence * 10); + set_balance(&ALICE, min_balance * 10); place_contract(&BOB, code_hash); + let mut storage_meter = storage::meter::Meter::new(&ALICE, Some(0), 0).unwrap(); System::reset_events(); - MockStack::run_call(ALICE, BOB, &mut gas_meter, &schedule, 0, vec![], None).unwrap(); + MockStack::run_call( + ALICE, + BOB, + &mut gas_meter, + &mut storage_meter, + &schedule, + 0, + vec![], + None, + ) + .unwrap(); let remark_hash = ::Hashing::hash(b"Hello"); assert_eq!( @@ -2209,11 +2291,15 @@ mod tests { let succ_succ_executable = MockExecutable::from_storage(succ_succ_code, &schedule, &mut gas_meter).unwrap(); set_balance(&ALICE, min_balance * 1000); + let mut storage_meter = + storage::meter::Meter::new(&ALICE, Some(min_balance * 500), min_balance * 100) + .unwrap(); MockStack::run_instantiate( ALICE, fail_executable, &mut gas_meter, + &mut storage_meter, &schedule, min_balance * 100, vec![], @@ -2227,6 +2313,7 @@ mod tests { ALICE, success_executable, &mut gas_meter, + &mut storage_meter, &schedule, min_balance * 100, vec![], @@ -2239,6 +2326,7 @@ mod tests { ALICE, succ_fail_executable, &mut gas_meter, + &mut storage_meter, &schedule, min_balance * 200, vec![], @@ -2251,6 +2339,7 @@ mod tests { ALICE, succ_succ_executable, &mut gas_meter, + &mut storage_meter, &schedule, min_balance * 200, vec![], diff --git a/frame/contracts/src/lib.rs b/frame/contracts/src/lib.rs index b2e221dde6ad..0b8786fa704a 100644 --- a/frame/contracts/src/lib.rs +++ b/frame/contracts/src/lib.rs @@ -106,24 +106,27 @@ pub use crate::{ use crate::{ exec::{AccountIdOf, ExecError, Executable, Stack as ExecStack}, gas::GasMeter, - storage::{ContractInfo, DeletedContract, Storage}, - wasm::PrefabWasmModule, + storage::{meter::Meter as StorageMeter, ContractInfo, DeletedContract, Storage}, + wasm::{OwnerInfo, PrefabWasmModule}, weights::WeightInfo, }; +use codec::{Encode, HasCompact}; use frame_support::{ dispatch::Dispatchable, ensure, - traits::{Contains, Currency, Get, Randomness, StorageVersion, Time}, - weights::{GetDispatchInfo, PostDispatchInfo, Weight}, + traits::{Contains, Currency, Get, Randomness, ReservableCurrency, StorageVersion, Time}, + weights::{GetDispatchInfo, Pays, PostDispatchInfo, Weight}, }; use frame_system::Pallet as System; use pallet_contracts_primitives::{ - Code, ContractAccessError, ContractExecResult, ContractInstantiateResult, ExecReturnValue, - GetStorageResult, InstantiateReturnValue, + Code, CodeUploadResult, CodeUploadReturnValue, ContractAccessError, ContractExecResult, + ContractInstantiateResult, ExecReturnValue, GetStorageResult, InstantiateReturnValue, + StorageDeposit, }; +use scale_info::TypeInfo; use sp_core::{crypto::UncheckedFrom, Bytes}; use sp_runtime::traits::{Convert, Hash, Saturating, StaticLookup}; -use sp_std::prelude::*; +use sp_std::{fmt::Debug, prelude::*}; type CodeHash = ::Hash; type TrieId = Vec; @@ -131,7 +134,7 @@ type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; /// The current storage version. -const STORAGE_VERSION: StorageVersion = StorageVersion::new(5); +const STORAGE_VERSION: StorageVersion = StorageVersion::new(6); #[frame_support::pallet] pub mod pallet { @@ -148,7 +151,7 @@ pub mod pallet { type Randomness: Randomness; /// The currency in which fees are paid and contract balances are held. - type Currency: Currency; + type Currency: ReservableCurrency; /// The overarching event type. type Event: From> + IsType<::Event>; @@ -165,12 +168,6 @@ pub mod pallet { /// This is applied in **addition** to [`frame_system::Config::BaseCallFilter`]. /// It is recommended to treat this as a whitelist. /// - /// # Subsistence Threshold - /// - /// The runtime **must** make sure that any allowed dispatchable makes sure that the - /// `total_balance` of the contract stays above [`Pallet::subsistence_threshold()`]. - /// Otherwise users could clutter the storage with contracts. - /// /// # Stability /// /// The runtime **must** make sure that all dispatchables that are callable by @@ -201,13 +198,6 @@ pub mod pallet { #[pallet::constant] type Schedule: Get>; - /// The deposit that must be placed into the contract's account to instantiate it. - /// This is in **addition** to the [`Currency::minimum_balance`]. - /// The minimum balance for a contract's account can be queried using - /// [`Pallet::subsistence_threshold`]. - #[pallet::constant] - type ContractDeposit: Get>; - /// The type of the call stack determines the maximum nesting depth of contract calls. /// /// The allowed depth is `CallStack::size() + 1`. @@ -222,6 +212,21 @@ pub mod pallet { /// The maximum amount of weight that can be consumed per block for lazy trie removal. #[pallet::constant] type DeletionWeightLimit: Get; + + /// The amount of balance a caller has to pay for each byte of storage. + /// + /// # Note + /// + /// Changing this value for an existing chain might need a storage migration. + #[pallet::constant] + type DepositPerByte: Get>; + + /// The amount of balance a caller has to pay for each storage item. + /// # Note + /// + /// Changing this value for an existing chain might need a storage migration. + #[pallet::constant] + type DepositPerItem: Get>; } #[pallet::pallet] @@ -255,9 +260,19 @@ pub mod pallet { where T::AccountId: UncheckedFrom, T::AccountId: AsRef<[u8]>, + as HasCompact>::Type: Clone + Eq + PartialEq + Debug + TypeInfo + Encode, { /// Makes a call to an account, optionally transferring some balance. /// + /// # Parameters + /// + /// * `dest`: Address of the contract to call. + /// * `value`: The balance to transfer from the `origin` to `dest`. + /// * `gas_limit`: The gas limit enforced when executing the constructor. + /// * `storage_deposit_limit`: The maximum amount of balance that can be charged from the + /// caller to pay for the storage consumed. + /// * `data`: The input data to pass to the contract. + /// /// * If the account is a smart-contract account, the associated code will be /// executed and any value will be transferred. /// * If the account is a regular account, any value will be transferred. @@ -269,23 +284,36 @@ pub mod pallet { dest: ::Source, #[pallet::compact] value: BalanceOf, #[pallet::compact] gas_limit: Weight, + storage_deposit_limit: Option< as codec::HasCompact>::Type>, data: Vec, ) -> DispatchResultWithPostInfo { let origin = ensure_signed(origin)?; let dest = T::Lookup::lookup(dest)?; - let output = Self::internal_call(origin, dest, value, gas_limit, data, None); + let output = Self::internal_call( + origin, + dest, + value, + gas_limit, + storage_deposit_limit.map(Into::into), + data, + None, + ); output.gas_meter.into_dispatch_result(output.result, T::WeightInfo::call()) } /// Instantiates a new contract from the supplied `code` optionally transferring /// some balance. /// - /// This is the only function that can deploy new code to the chain. + /// This dispatchable has the same effect as calling [`Self::upload_code`] + + /// [`Self::instantiate`]. Bundling them together provides efficiency gains. Please + /// also check the documentation of [`Self::upload_code`]. /// /// # Parameters /// - /// * `endowment`: The balance to transfer from the `origin` to the newly created contract. + /// * `value`: The balance to transfer from the `origin` to the newly created contract. /// * `gas_limit`: The gas limit enforced when executing the constructor. + /// * `storage_deposit_limit`: The maximum amount of balance that can be charged/reserved + /// from the caller to pay for the storage consumed. /// * `code`: The contract code to deploy in raw bytes. /// * `data`: The input data to pass to the contract constructor. /// * `salt`: Used for the address derivation. See [`Pallet::contract_address`]. @@ -297,7 +325,7 @@ pub mod pallet { /// - If the `code_hash` already exists on the chain the underlying `code` will be shared. /// - The destination address is computed based on the sender, code_hash and the salt. /// - The smart-contract account is created at the computed address. - /// - The `endowment` is transferred to the new account. + /// - The `value` is transferred to the new account. /// - The `deploy` function is executed in the context of the newly-created account. #[pallet::weight( T::WeightInfo::instantiate_with_code( @@ -308,8 +336,9 @@ pub mod pallet { )] pub fn instantiate_with_code( origin: OriginFor, - #[pallet::compact] endowment: BalanceOf, + #[pallet::compact] value: BalanceOf, #[pallet::compact] gas_limit: Weight, + storage_deposit_limit: Option< as codec::HasCompact>::Type>, code: Vec, data: Vec, salt: Vec, @@ -319,8 +348,9 @@ pub mod pallet { let salt_len = salt.len() as u32; let output = Self::internal_instantiate( origin, - endowment, + value, gas_limit, + storage_deposit_limit.map(Into::into), Code::Upload(Bytes(code)), data, salt, @@ -342,8 +372,9 @@ pub mod pallet { )] pub fn instantiate( origin: OriginFor, - #[pallet::compact] endowment: BalanceOf, + #[pallet::compact] value: BalanceOf, #[pallet::compact] gas_limit: Weight, + storage_deposit_limit: Option< as codec::HasCompact>::Type>, code_hash: CodeHash, data: Vec, salt: Vec, @@ -352,8 +383,9 @@ pub mod pallet { let salt_len = salt.len() as u32; let output = Self::internal_instantiate( origin, - endowment, + value, gas_limit, + storage_deposit_limit.map(Into::into), Code::Existing(code_hash), data, salt, @@ -364,6 +396,47 @@ pub mod pallet { T::WeightInfo::instantiate(salt_len / 1024), ) } + + /// Upload new `code` without instantiating a contract from it. + /// + /// If the code does not already exist a deposit is reserved from the caller + /// and unreserved only when [`Self::remove_code`] is called. The size of the reserve + /// depends on the instrumented size of the the supplied `code`. + /// + /// If the code already exists in storage it will still return `Ok` and upgrades + /// the in storage version to the current + /// [`InstructionWeights::version`](InstructionWeights). + /// + /// # Note + /// + /// Anyone can instantiate a contract from any uploaded code and thus prevent its removal. + /// To avoid this situation a constructor could employ access control so that it can + /// only be instantiated by permissioned entities. The same is true when uploading + /// through [`Self::instantiate_with_code`]. + #[pallet::weight(T::WeightInfo::upload_code(code.len() as u32 / 1024))] + pub fn upload_code( + origin: OriginFor, + code: Vec, + storage_deposit_limit: Option< as codec::HasCompact>::Type>, + ) -> DispatchResult { + let origin = ensure_signed(origin)?; + Self::bare_upload_code(origin, code, storage_deposit_limit.map(Into::into)).map(|_| ()) + } + + /// Remove the code stored under `code_hash` and refund the deposit to its owner. + /// + /// A code can only be removed by its original uploader (its owner) and only if it is + /// not used by any contract. + #[pallet::weight(T::WeightInfo::remove_code())] + pub fn remove_code( + origin: OriginFor, + code_hash: CodeHash, + ) -> DispatchResultWithPostInfo { + let origin = ensure_signed(origin)?; + >::remove(&origin, code_hash)?; + // we waive the fee because removing unused code is beneficial + Ok(Pays::No.into()) + } } #[pallet::event] @@ -388,12 +461,6 @@ pub mod pallet { /// Code with the specified hash has been stored. CodeStored { code_hash: T::Hash }, - /// Triggered when the current schedule is updated. - ScheduleUpdated { - /// The version of the newly set schedule. - version: u32, - }, - /// A custom event emitted by the contract. ContractEmitted { /// The contract that emitted the event. @@ -404,8 +471,6 @@ pub mod pallet { }, /// A code with the specified hash was removed. - /// - /// This happens when the last contract that uses this code hash was removed. CodeRemoved { code_hash: T::Hash }, } @@ -417,16 +482,8 @@ pub mod pallet { OutOfGas, /// The output buffer supplied to a contract API call was too small. OutputBufferTooSmall, - /// Performing the requested transfer would have brought the contract below - /// the subsistence threshold. No transfer is allowed to do this. Use `seal_terminate` - /// to recover a deposit. - BelowSubsistenceThreshold, - /// The newly created contract is below the subsistence threshold after executing - /// its contructor. No contracts are allowed to exist below that threshold. - NewContractNotFunded, - /// Performing the requested transfer failed for a reason originating in the - /// chosen currency implementation of the runtime. Most probably the balance is - /// too low or locks are placed on it. + /// Performing the requested transfer failed. Probably because there isn't enough + /// free balance in the sender's account. TransferFailed, /// Performing a call was denied because the calling depth reached the limit /// of what is specified in the schedule. @@ -467,11 +524,6 @@ pub mod pallet { /// The queue is filled by deleting contracts and emptied by a fixed amount each block. /// Trying again during another block is the only way to resolve this issue. DeletionQueueFull, - /// A storage modification exhausted the 32bit type that holds the storage size. - /// - /// This can either happen when the accumulated storage in bytes is too large or - /// when number of storage items is too large. - StorageExhausted, /// A contract with the same AccountId already exists. DuplicateContract, /// A contract self destructed in its constructor. @@ -482,6 +534,12 @@ pub mod pallet { DebugMessageInvalidUTF8, /// A call tried to invoke a contract that is flagged as non-reentrant. ReentranceDenied, + /// Origin doesn't have enough balance to pay the required storage deposits. + StorageDepositNotEnoughFunds, + /// More storage was created than allowed by the storage deposit limit. + StorageDepositLimitExhausted, + /// Code removal was denied because the code is still in use by at least one contract. + CodeInUse, } /// A mapping from an original code hash to the original code, untouched by instrumentation. @@ -493,6 +551,10 @@ pub mod pallet { pub(crate) type CodeStorage = StorageMap<_, Identity, CodeHash, PrefabWasmModule>; + /// A mapping between an original code hash and its owner information. + #[pallet::storage] + pub(crate) type OwnerInfoOf = StorageMap<_, Identity, CodeHash, OwnerInfo>; + /// The subtrie counter. #[pallet::storage] pub(crate) type AccountCounter = StorageValue<_, u64, ValueQuery>; @@ -522,6 +584,8 @@ type InternalInstantiateOutput = InternalOutput, ExecRetur struct InternalOutput { /// The gas meter that was used to execute the call. gas_meter: GasMeter, + /// The storage deposit used by the call. + storage_deposit: StorageDeposit>, /// The result of the call. result: Result, } @@ -547,16 +611,25 @@ where dest: T::AccountId, value: BalanceOf, gas_limit: Weight, + storage_deposit_limit: Option>, data: Vec, debug: bool, - ) -> ContractExecResult { + ) -> ContractExecResult> { let mut debug_message = if debug { Some(Vec::new()) } else { None }; - let output = - Self::internal_call(origin, dest, value, gas_limit, data, debug_message.as_mut()); + let output = Self::internal_call( + origin, + dest, + value, + gas_limit, + storage_deposit_limit, + data, + debug_message.as_mut(), + ); ContractExecResult { result: output.result.map_err(|r| r.error), gas_consumed: output.gas_meter.gas_consumed(), gas_required: output.gas_meter.gas_required(), + storage_deposit: output.storage_deposit, debug_message: debug_message.unwrap_or_default(), } } @@ -568,7 +641,6 @@ where /// /// It returns the execution result, account id and the amount of used weight. /// - /// /// # Note /// /// `debug` should only ever be set to `true` when executing as an RPC because @@ -576,18 +648,20 @@ where /// If set to `true` it returns additional human readable debugging information. pub fn bare_instantiate( origin: T::AccountId, - endowment: BalanceOf, + value: BalanceOf, gas_limit: Weight, + storage_deposit_limit: Option>, code: Code>, data: Vec, salt: Vec, debug: bool, - ) -> ContractInstantiateResult { + ) -> ContractInstantiateResult> { let mut debug_message = if debug { Some(Vec::new()) } else { None }; let output = Self::internal_instantiate( origin, - endowment, + value, gas_limit, + storage_deposit_limit, code, data, salt, @@ -600,10 +674,31 @@ where .map_err(|e| e.error), gas_consumed: output.gas_meter.gas_consumed(), gas_required: output.gas_meter.gas_required(), + storage_deposit: output.storage_deposit, debug_message: debug_message.unwrap_or_default(), } } + /// Upload new code without instantiating a contract from it. + /// + /// This function is similar to [`Self::upload_code`], but doesn't perform any address lookups + /// and better suitable for calling directly from Rust. + pub fn bare_upload_code( + origin: T::AccountId, + code: Vec, + storage_deposit_limit: Option>, + ) -> CodeUploadResult, BalanceOf> { + let schedule = T::Schedule::get(); + let module = PrefabWasmModule::from_code(code, &schedule, origin)?; + let deposit = module.open_deposit(); + if let Some(storage_deposit_limit) = storage_deposit_limit { + ensure!(storage_deposit_limit >= deposit, >::StorageDepositLimitExhausted); + } + let result = CodeUploadReturnValue { code_hash: *module.code_hash(), deposit }; + module.store()?; + Ok(result) + } + /// Query storage of a specified contract under a specified key. pub fn get_storage(address: T::AccountId, key: [u8; 32]) -> GetStorageResult { let contract_info = @@ -636,35 +731,14 @@ where UncheckedFrom::unchecked_from(T::Hashing::hash(&buf)) } - /// Subsistence threshold is the extension of the minimum balance (aka existential deposit) - /// by the contract deposit. It is the minimum balance any contract must hold. - /// - /// Any contract initiated balance transfer mechanism cannot make the balance lower - /// than the subsistence threshold. The only way to recover the balance is to remove - /// contract using `seal_terminate`. - pub fn subsistence_threshold() -> BalanceOf { - T::Currency::minimum_balance().saturating_add(T::ContractDeposit::get()) - } - - /// The in-memory size in bytes of the data structure associated with each contract. - /// - /// The data structure is also put into storage for each contract. The in-storage size - /// is never larger than the in-memory representation and usually smaller due to compact - /// encoding and lack of padding. - /// - /// # Note - /// - /// This returns the in-memory size because the in-storage size (SCALE encoded) cannot - /// be efficiently determined. Treat this as an upper bound of the in-storage size. - pub fn contract_info_size() -> u32 { - sp_std::mem::size_of::>() as u32 - } - /// Store code for benchmarks which does not check nor instrument the code. #[cfg(feature = "runtime-benchmarks")] - fn store_code_raw(code: Vec) -> frame_support::dispatch::DispatchResult { + fn store_code_raw( + code: Vec, + owner: T::AccountId, + ) -> frame_support::dispatch::DispatchResult { let schedule = T::Schedule::get(); - PrefabWasmModule::store_code_unchecked(code, &schedule)?; + PrefabWasmModule::store_code_unchecked(code, &schedule, owner)?; Ok(()) } @@ -685,21 +759,32 @@ where dest: T::AccountId, value: BalanceOf, gas_limit: Weight, + storage_deposit_limit: Option>, data: Vec, debug_message: Option<&mut Vec>, ) -> InternalCallOutput { let mut gas_meter = GasMeter::new(gas_limit); + let mut storage_meter = match StorageMeter::new(&origin, storage_deposit_limit, value) { + Ok(meter) => meter, + Err(err) => + return InternalCallOutput { + result: Err(err.into()), + gas_meter, + storage_deposit: Default::default(), + }, + }; let schedule = T::Schedule::get(); let result = ExecStack::>::run_call( origin, dest, &mut gas_meter, + &mut storage_meter, &schedule, value, data, debug_message, ); - InternalCallOutput { gas_meter, result } + InternalCallOutput { result, gas_meter, storage_deposit: storage_meter.into_deposit() } } /// Internal function that does the actual instantiation. @@ -707,43 +792,62 @@ where /// Called by dispatchables and public functions. fn internal_instantiate( origin: T::AccountId, - endowment: BalanceOf, + value: BalanceOf, gas_limit: Weight, + storage_deposit_limit: Option>, code: Code>, data: Vec, salt: Vec, debug_message: Option<&mut Vec>, ) -> InternalInstantiateOutput { + let mut storage_deposit = Default::default(); let mut gas_meter = GasMeter::new(gas_limit); - let schedule = T::Schedule::get(); let try_exec = || { - let executable = match code { + let schedule = T::Schedule::get(); + let (extra_deposit, executable) = match code { Code::Upload(Bytes(binary)) => { ensure!( binary.len() as u32 <= schedule.limits.code_len, >::CodeTooLarge ); - let executable = PrefabWasmModule::from_code(binary, &schedule)?; + let executable = + PrefabWasmModule::from_code(binary, &schedule, origin.clone())?; ensure!( executable.code_len() <= schedule.limits.code_len, >::CodeTooLarge ); - executable + // The open deposit will be charged during execution when the + // uploaded module does not already exist. This deposit is not part of the + // storage meter because it is not transfered to the contract but + // reserved on the uploading account. + (executable.open_deposit(), executable) }, - Code::Existing(hash) => + Code::Existing(hash) => ( + Default::default(), PrefabWasmModule::from_storage(hash, &schedule, &mut gas_meter)?, + ), }; - ExecStack::>::run_instantiate( + let mut storage_meter = StorageMeter::new( + &origin, + storage_deposit_limit, + value.saturating_add(extra_deposit), + )?; + let result = ExecStack::>::run_instantiate( origin, executable, &mut gas_meter, + &mut storage_meter, &schedule, - endowment, + value, data, &salt, debug_message, - ) + ); + storage_deposit = storage_meter + .into_deposit() + .saturating_add(&StorageDeposit::Charge(extra_deposit)); + result }; - InternalInstantiateOutput { result: try_exec(), gas_meter } + InternalInstantiateOutput { result: try_exec(), gas_meter, storage_deposit } } } diff --git a/frame/contracts/src/migration.rs b/frame/contracts/src/migration.rs index b7fa9575e23b..93eb2e64a1d8 100644 --- a/frame/contracts/src/migration.rs +++ b/frame/contracts/src/migration.rs @@ -15,12 +15,15 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{Config, Pallet, Weight}; +use crate::{BalanceOf, CodeHash, Config, Pallet, TrieId, Weight}; +use codec::{Decode, Encode}; use frame_support::{ + codec, generate_storage_alias, storage::migration, traits::{Get, PalletInfoAccess}, + Identity, Twox64Concat, }; -use sp_std::prelude::*; +use sp_std::{marker::PhantomData, prelude::*}; pub fn migrate() -> Weight { use frame_support::traits::StorageVersion; @@ -38,6 +41,11 @@ pub fn migrate() -> Weight { StorageVersion::new(5).put::>(); } + if version < 6 { + weight = weight.saturating_add(v6::migrate::()); + StorageVersion::new(6).put::>(); + } + weight } @@ -54,11 +62,6 @@ mod v4 { /// V5: State rent is removed which obsoletes some fields in `ContractInfo`. mod v5 { use super::*; - use crate::{ - BalanceOf, CodeHash, ContractInfo, ContractInfoOf, DeletedContract, DeletionQueue, TrieId, - }; - use codec::Decode; - use sp_std::marker::PhantomData; type AliveContractInfo = RawAliveContractInfo, BalanceOf, ::BlockNumber>; @@ -95,6 +98,30 @@ mod v5 { trie_id: TrieId, } + pub type ContractInfo = RawContractInfo>; + + #[derive(Encode, Decode)] + pub struct RawContractInfo { + pub trie_id: TrieId, + pub code_hash: CodeHash, + pub _reserved: Option<()>, + } + + #[derive(Encode, Decode)] + struct DeletedContract { + trie_id: TrieId, + } + + generate_storage_alias!( + Contracts, + ContractInfoOf => Map<(Twox64Concat, T::AccountId), ContractInfo> + ); + + generate_storage_alias!( + Contracts, + DeletionQueue => Value> + ); + pub fn migrate() -> Weight { let mut weight: Weight = 0; @@ -110,7 +137,7 @@ mod v5 { } }); - >::translate(|old: Option>| { + DeletionQueue::translate(|old: Option>| { weight = weight.saturating_add(T::DbWeight::get().reads_writes(1, 1)); old.map(|old| old.into_iter().map(|o| DeletedContract { trie_id: o.trie_id }).collect()) }) @@ -119,3 +146,102 @@ mod v5 { weight } } + +/// V6: Added storage deposits +mod v6 { + use super::*; + + #[derive(Encode, Decode)] + struct OldPrefabWasmModule { + #[codec(compact)] + instruction_weights_version: u32, + #[codec(compact)] + initial: u32, + #[codec(compact)] + maximum: u32, + #[codec(compact)] + refcount: u64, + _reserved: Option<()>, + code: Vec, + original_code_len: u32, + } + + #[derive(Encode, Decode)] + struct PrefabWasmModule { + #[codec(compact)] + instruction_weights_version: u32, + #[codec(compact)] + initial: u32, + #[codec(compact)] + maximum: u32, + code: Vec, + } + + use v5::ContractInfo as OldContractInfo; + + #[derive(Encode, Decode)] + pub struct RawContractInfo { + trie_id: TrieId, + code_hash: CodeHash, + storage_deposit: Balance, + } + + #[derive(Encode, Decode)] + pub struct OwnerInfo { + owner: T::AccountId, + #[codec(compact)] + deposit: BalanceOf, + #[codec(compact)] + refcount: u64, + } + + type ContractInfo = RawContractInfo, BalanceOf>; + + generate_storage_alias!( + Contracts, + ContractInfoOf => Map<(Twox64Concat, T::AccountId), ContractInfo> + ); + + generate_storage_alias!( + Contracts, + CodeStorage => Map<(Identity, CodeHash), PrefabWasmModule> + ); + + generate_storage_alias!( + Contracts, + OwnerInfoOf => Map<(Identity, CodeHash), OwnerInfo> + ); + + pub fn migrate() -> Weight { + let mut weight: Weight = 0; + + >::translate(|_key, old: OldContractInfo| { + weight = weight.saturating_add(T::DbWeight::get().reads_writes(1, 1)); + Some(ContractInfo:: { + trie_id: old.trie_id, + code_hash: old.code_hash, + storage_deposit: Default::default(), + }) + }); + + >::translate(|key, old: OldPrefabWasmModule| { + weight = weight.saturating_add(T::DbWeight::get().reads_writes(1, 2)); + >::insert( + key, + OwnerInfo { + refcount: old.refcount, + owner: Default::default(), + deposit: Default::default(), + }, + ); + Some(PrefabWasmModule { + instruction_weights_version: old.instruction_weights_version, + initial: old.initial, + maximum: old.maximum, + code: old.code, + }) + }); + + weight + } +} diff --git a/frame/contracts/src/schedule.rs b/frame/contracts/src/schedule.rs index c14165b4c6ae..b9acc9d49204 100644 --- a/frame/contracts/src/schedule.rs +++ b/frame/contracts/src/schedule.rs @@ -271,9 +271,6 @@ pub struct HostFnWeights { /// Weight of calling `seal_minimum_balance`. pub minimum_balance: Weight, - /// Weight of calling `seal_contract_deposit`. - pub contract_deposit: Weight, - /// Weight of calling `seal_block_number`. pub block_number: Weight, @@ -561,7 +558,6 @@ impl Default for HostFnWeights { balance: cost_batched!(seal_balance), value_transferred: cost_batched!(seal_value_transferred), minimum_balance: cost_batched!(seal_minimum_balance), - contract_deposit: cost_batched!(seal_tombstone_deposit), block_number: cost_batched!(seal_block_number), now: cost_batched!(seal_now), weight_to_fee: cost_batched!(seal_weight_to_fee), diff --git a/frame/contracts/src/storage.rs b/frame/contracts/src/storage.rs index 2b994d66af7e..6d67729a9a68 100644 --- a/frame/contracts/src/storage.rs +++ b/frame/contracts/src/storage.rs @@ -17,10 +17,12 @@ //! This module contains routines for accessing and altering a contract related state. +pub mod meter; + use crate::{ exec::{AccountIdOf, StorageKey}, weights::WeightInfo, - CodeHash, Config, ContractInfoOf, DeletionQueue, Error, TrieId, + BalanceOf, CodeHash, Config, ContractInfoOf, DeletionQueue, Error, TrieId, }; use codec::{Decode, Encode}; use frame_support::{ @@ -32,24 +34,27 @@ use frame_support::{ use scale_info::TypeInfo; use sp_core::crypto::UncheckedFrom; use sp_io::hashing::blake2_256; -use sp_runtime::{traits::Hash, RuntimeDebug}; +use sp_runtime::{ + traits::{Hash, Zero}, + RuntimeDebug, +}; use sp_std::{marker::PhantomData, prelude::*}; -pub type ContractInfo = RawContractInfo>; +pub type ContractInfo = RawContractInfo, BalanceOf>; /// Information for managing an account and its sub trie abstraction. /// This is the required info to cache for an account. #[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] -pub struct RawContractInfo { +pub struct RawContractInfo { /// Unique ID for the subtree encoded as a bytes vector. pub trie_id: TrieId, /// The code associated with a given account. pub code_hash: CodeHash, - /// This field is reserved for future evolution of format. - pub _reserved: Option<()>, + /// The amount of balance that is currently deposited to pay for consumed storage. + pub storage_deposit: Balance, } -impl RawContractInfo { +impl RawContractInfo { /// Associated child trie unique id is built from the hash part of the trie id. #[cfg(test)] pub fn child_trie_info(&self) -> ChildInfo { @@ -79,26 +84,49 @@ where /// The read is performed from the `trie_id` only. The `address` is not necessary. If the /// contract doesn't store under the given `key` `None` is returned. pub fn read(trie_id: &TrieId, key: &StorageKey) -> Option> { - child::get_raw(&child_trie_info(&trie_id), &blake2_256(key)) + child::get_raw(&child_trie_info(trie_id), &blake2_256(key)) } /// Update a storage entry into a contract's kv storage. /// - /// If the `opt_new_value` is `None` then the kv pair is removed. + /// If the `new_value` is `None` then the kv pair is removed. /// - /// This function also updates the bookkeeping info such as: number of total non-empty pairs a - /// contract owns, the last block the storage was written to, etc. That's why, in contrast to - /// `read`, this function also requires the `account` ID. + /// This function also records how much storage was created or removed if a `storage_meter` + /// is supplied. It should only be absent for testing or benchmarking code. pub fn write( - new_info: &mut ContractInfo, + trie_id: &TrieId, key: &StorageKey, - opt_new_value: Option>, + new_value: Option>, + storage_meter: Option<&mut meter::NestedMeter>, ) -> DispatchResult { let hashed_key = blake2_256(key); - let child_trie_info = &child_trie_info(&new_info.trie_id); + let child_trie_info = &child_trie_info(trie_id); + + if let Some(storage_meter) = storage_meter { + let mut diff = meter::Diff::default(); + let old_len = child::len(&child_trie_info, &hashed_key); + match (old_len, new_value.as_ref().map(|v| v.len() as u32)) { + (Some(old_len), Some(new_len)) => + if new_len > old_len { + diff.bytes_added = new_len - old_len; + } else { + diff.bytes_removed = old_len - new_len; + }, + (None, Some(new_len)) => { + diff.bytes_added = new_len; + diff.items_added = 1; + }, + (Some(old_len), None) => { + diff.bytes_removed = old_len; + diff.items_removed = 1; + }, + (None, None) => (), + } + storage_meter.charge(&diff)?; + } - match opt_new_value { - Some(new_value) => child::put_raw(&child_trie_info, &hashed_key, &new_value[..]), + match &new_value { + Some(new_value) => child::put_raw(&child_trie_info, &hashed_key, new_value), None => child::kill(&child_trie_info, &hashed_key), } @@ -118,7 +146,8 @@ where return Err(Error::::DuplicateContract.into()) } - let contract = ContractInfo:: { code_hash: ch, trie_id, _reserved: None }; + let contract = + ContractInfo:: { code_hash: ch, trie_id, storage_deposit: >::zero() }; Ok(contract) } diff --git a/frame/contracts/src/storage/meter.rs b/frame/contracts/src/storage/meter.rs new file mode 100644 index 000000000000..96ce02fd83ae --- /dev/null +++ b/frame/contracts/src/storage/meter.rs @@ -0,0 +1,726 @@ +// This file is part of Substrate. + +// Copyright (C) 2019-2021 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. + +//! This module contains functions to meter the storage deposit. + +use crate::{storage::ContractInfo, BalanceOf, Config, Error}; +use codec::Encode; +use frame_support::{ + dispatch::DispatchError, + traits::{tokens::BalanceStatus, Currency, ExistenceRequirement, Get, ReservableCurrency}, + DefaultNoBound, +}; +use pallet_contracts_primitives::StorageDeposit as Deposit; +use sp_core::crypto::UncheckedFrom; +use sp_runtime::traits::{Saturating, Zero}; +use sp_std::marker::PhantomData; + +/// Deposit that uses the native currency's balance type. +pub type DepositOf = Deposit>; + +/// A production root storage meter that actually charges from its origin. +pub type Meter = RawMeter; + +/// A poduction nested storage meter that actually charges from its origin. +pub type NestedMeter = RawMeter; + +/// A poduction storage meter that actually charges from its origin. +/// +/// This can be used where we want to be generic over the state (Root vs. Nested). +pub type GenericMeter = RawMeter; + +/// A trait that allows to decouple the metering from the charging of balance. +/// +/// This mostly exists for testing so that the charging can be mocked. +pub trait Ext { + /// This checks whether `origin` is able to afford the storage deposit limit. + /// + /// It is necessary to do this check beforehand so that the charge won't fail later on. + /// + /// `origin`: The origin of the call stack from which is responsible for putting down a deposit. + /// `limit`: The limit with which the meter was constructed. + /// `min_leftover`: How much `free_balance` in addition to the ed should be left inside the + /// `origin` account. + /// + /// Returns the limit that should be used by the meter. If origin can't afford the `limit` + /// it returns `Err`. + fn check_limit( + origin: &T::AccountId, + limit: Option>, + min_leftover: BalanceOf, + ) -> Result, DispatchError>; + /// This is called to inform the implementer that some balance should be charged due to + /// some interaction of the `origin` with a `contract`. + /// + /// The balance transfer can either flow from `origin` to `contract` or the other way + /// around depending on whether `amount` constitutes a `Charge` or a `Refund`. + /// It is guaranteed that that this succeeds because no more balance than returned by + /// `check_limit` is ever charged. This is why this function is infallible. + /// `terminated` designates whether the `contract` was terminated. + fn charge( + origin: &T::AccountId, + contract: &T::AccountId, + amount: &DepositOf, + terminated: bool, + ); +} + +/// This [`Ext`] is used for actual on-chain execution when balance needs to be charged. +/// +/// It uses [`ReservableCurrency`] in order to do accomplish the reserves. +pub enum ReservingExt {} + +/// Used to implement a type state pattern for the meter. +/// +/// It is sealed and cannot be implemented outside of this module. +pub trait State: private::Sealed {} + +/// State parameter that constitutes a meter that is in its root state. +pub enum Root {} + +/// State parameter that constitutes a meter that is in its nested state. +pub enum Nested {} + +impl State for Root {} +impl State for Nested {} + +/// A type that allows the metering of consumed or freed storage of a single contract call stack. +#[derive(DefaultNoBound)] +pub struct RawMeter, S: State> { + /// The limit of how much balance this meter is allowed to consume. + limit: BalanceOf, + /// The amount of balance that was used in this meter and all of its already absorbed children. + total_deposit: DepositOf, + /// The amount of balance that was used in this meter alone. + own_deposit: DepositOf, + /// Only when a contract was terminated we allow it to drop below the minimum balance. + terminated: bool, + /// Type parameters are only used in impls. + _phantom: PhantomData<(E, S)>, +} + +/// This type is used to describe a storage change when charging from the meter. +#[derive(Default)] +pub struct Diff { + /// How many bytes were added to storage. + pub bytes_added: u32, + /// How many bytes were removed from storage. + pub bytes_removed: u32, + /// How many storage items were added to storage. + pub items_added: u32, + /// How many storage items were removed from storage. + pub items_removed: u32, + /// If set to true the derived deposit will always a `Charge` larger than the + /// the existential deposit. + pub require_ed: bool, +} + +impl Diff { + /// Calculate how much of a charge or refund results from applying the diff. + pub fn to_deposit(&self) -> DepositOf { + let mut deposit = Deposit::default(); + let per_byte = T::DepositPerByte::get(); + let per_item = T::DepositPerItem::get(); + + if self.bytes_added > self.bytes_removed { + deposit = deposit.saturating_add(&Deposit::Charge( + per_byte.saturating_mul((self.bytes_added - self.bytes_removed).into()), + )); + } else if self.bytes_removed > self.bytes_added { + deposit = deposit.saturating_add(&Deposit::Refund( + per_byte.saturating_mul((self.bytes_removed - self.bytes_added).into()), + )); + } + + if self.items_added > self.items_removed { + deposit = deposit.saturating_add(&Deposit::Charge( + per_item.saturating_mul((self.items_added - self.items_removed).into()), + )); + } else if self.items_removed > self.items_added { + deposit = deposit.saturating_add(&Deposit::Refund( + per_item.saturating_mul((self.items_removed - self.items_added).into()), + )); + } + + if self.require_ed { + deposit = deposit.max(Deposit::Charge(T::Currency::minimum_balance())) + } + + deposit + } +} + +/// Functions that apply to all states. +impl RawMeter +where + T: Config, + T::AccountId: UncheckedFrom + AsRef<[u8]>, + E: Ext, + S: State, +{ + /// Create a new child that has its `limit` set to whatever is remaining of it. + /// + /// This is called whenever a new subcall is initiated in order to track the storage + /// usage for this sub call separately. This is necessary because we want to exchange balance + /// with the current contract we are interacting with. + pub fn nested(&self) -> RawMeter { + RawMeter { limit: self.available(), ..Default::default() } + } + + /// Absorb a child that was spawned to handle a sub call. + /// + /// This should be called whenever a sub call comes to its end and it is **not** reverted. + /// This does the actual balance transfer from/to `origin` and `contract` based on the overall + /// storage consumption of the call. It also updates the supplied contract info. + /// + /// In case a contract reverted the child meter should just be dropped in order to revert + /// any changes it recorded. + /// + /// # Parameters + /// + /// `absorbed`: The child storage meter that should be absorbed. + /// `origin`: The origin that spawned the original root meter. + /// `contract`: The contract that this sub call belongs to. + /// `info`: The info of the contract in question. `None` if the contract was terminated. + pub fn absorb( + &mut self, + mut absorbed: RawMeter, + origin: &T::AccountId, + contract: &T::AccountId, + info: Option<&mut ContractInfo>, + ) { + // Absorbing from an existing (non terminated) contract. + if let Some(info) = info { + match &mut absorbed.own_deposit { + Deposit::Charge(amount) => + info.storage_deposit = info.storage_deposit.saturating_add(*amount), + Deposit::Refund(amount) => { + // We need to make sure to never refund more than what was deposited and + // still leave the existential deposit inside the contract's account. + // This case can happen when costs change due to a runtime upgrade where + // increased costs could remove an account due to refunds. + let amount = { + let corrected_amount = (*amount).min( + info.storage_deposit.saturating_sub(T::Currency::minimum_balance()), + ); + let correction = (*amount).saturating_sub(corrected_amount); + absorbed.total_deposit = + absorbed.total_deposit.saturating_sub(&Deposit::Refund(correction)); + *amount = corrected_amount; + corrected_amount + }; + info.storage_deposit = info.storage_deposit.saturating_sub(amount); + }, + } + } + + self.total_deposit = self.total_deposit.saturating_add(&absorbed.total_deposit); + if !absorbed.own_deposit.is_zero() { + E::charge(origin, &contract, &absorbed.own_deposit, absorbed.terminated); + } + } + + /// The amount of balance that is still available from the original `limit`. + fn available(&self) -> BalanceOf { + self.total_deposit.available(&self.limit) + } +} + +/// Functions that only apply to the root state. +impl RawMeter +where + T: Config, + T::AccountId: UncheckedFrom + AsRef<[u8]>, + E: Ext, +{ + /// Create new storage meter for the specified `origin` and `limit`. + /// + /// This tries to [`Ext::check_limit`] on `origin` and fails if this is not possible. + pub fn new( + origin: &T::AccountId, + limit: Option>, + min_leftover: BalanceOf, + ) -> Result { + let limit = E::check_limit(&origin, limit, min_leftover)?; + Ok(Self { limit, ..Default::default() }) + } + + /// The total amount of deposit that should change hands as result of the execution + /// that this meter was passed into. + /// + /// This drops the root meter in order to make sure it is only called when the whole + /// execution did finish. + pub fn into_deposit(self) -> DepositOf { + self.total_deposit + } +} + +/// Functions that only apply to the nested state. +impl RawMeter +where + T: Config, + T::AccountId: UncheckedFrom + AsRef<[u8]>, + E: Ext, +{ + /// Try to charge the `diff` from the meter. Fails if this would exceed the original limit. + pub fn charge(&mut self, diff: &Diff) -> Result, DispatchError> { + debug_assert!(!self.terminated); + let deposit = diff.to_deposit::(); + let total_deposit = self.total_deposit.saturating_add(&deposit); + if let Deposit::Charge(amount) = total_deposit { + if amount > self.limit { + return Err(>::StorageDepositLimitExhausted.into()) + } + } + self.total_deposit = total_deposit; + self.own_deposit = self.own_deposit.saturating_add(&deposit); + Ok(deposit) + } + + /// Charge from `origin` a storage deposit for contract instantiation. + /// + /// This immediately transfers the balance in order to create the account. + pub fn charge_instantiate( + &mut self, + origin: &T::AccountId, + contract: &T::AccountId, + info: &mut ContractInfo, + ) -> Result, DispatchError> { + debug_assert!(!self.terminated); + let deposit = Diff { + bytes_added: info.encoded_size() as u32, + items_added: 1, + require_ed: true, + ..Default::default() + } + .to_deposit::(); + debug_assert!(matches!(deposit, Deposit::Charge(_))); + // We do not increase `own_deposit` because this will be charged later when the contract + // execution does conclude. + let total_deposit = self.total_deposit.saturating_add(&deposit); + if let Deposit::Charge(amount) = &total_deposit { + if amount > &self.limit { + return Err(>::StorageDepositLimitExhausted.into()) + } + } + info.storage_deposit = info.storage_deposit.saturating_add(deposit.charge_or_zero()); + self.total_deposit = total_deposit; + if !deposit.is_zero() { + // We need to charge immediately so that the account is created before the `value` + // is transferred from the caller to the contract. + E::charge(origin, contract, &deposit, false); + } + Ok(deposit) + } + + /// Call to tell the meter that the currently executing contract was executed. + /// + /// This will manipulate the meter so that all storage deposit accumulated in + /// `contract_info` will be refunded to the `origin` of the meter. + pub fn terminate(&mut self, contract_info: &ContractInfo) { + debug_assert!(!self.terminated); + let refund = Deposit::Refund(contract_info.storage_deposit); + + // The deposit for `own_deposit` isn't persisted into the contract info until the current + // frame is dropped. This means that whatever changes were introduced during the + // current frame are dicarded when terminating. + self.total_deposit = + self.total_deposit.saturating_add(&refund).saturating_sub(&self.own_deposit); + self.own_deposit = refund; + self.terminated = true; + } +} + +impl Ext for ReservingExt { + fn check_limit( + origin: &T::AccountId, + limit: Option>, + min_leftover: BalanceOf, + ) -> Result, DispatchError> { + let max = T::Currency::free_balance(origin) + .saturating_sub(T::Currency::minimum_balance()) + .saturating_sub(min_leftover); + match limit { + Some(limit) if limit <= max => Ok(limit), + None => Ok(max), + _ => Err(>::StorageDepositNotEnoughFunds.into()), + } + } + + fn charge( + origin: &T::AccountId, + contract: &T::AccountId, + amount: &DepositOf, + terminated: bool, + ) { + // There is nothing we can do when this fails as this constitutes a bug in the runtime: + // Either the runtime does not hold up the invariant of never deleting a contract's account + // or it does not honor reserved balances. We need to settle for emitting an error log + // in this case. + match amount { + Deposit::Charge(amount) => { + // This will never fail because a contract's account is required to exist + // at all times. The pallet enforces this invariant by depositing at least the + // existential deposit when instantiating and never refunds it unless the contract + // is removed. This means the receiver always exists except when instantiating a + // contract. In this case we made sure that at least the existential deposit is + // sent. The sender always has enough balance because we checked that it had enough + // balance when instantiating the storage meter. + let result = T::Currency::transfer( + origin, + contract, + *amount, + ExistenceRequirement::KeepAlive, + ) + .and_then(|_| T::Currency::reserve(contract, *amount)); + if let Err(err) = result { + log::error!( + target: "runtime::contracts", + "Failed to transfer storage deposit {:?} from origin {:?} to contract {:?}: {:?}", + amount, origin, contract, err, + ); + } + }, + // For `Refund(_)` no error happen because the initial value transfer from the + // origin to the contract has a keep alive existence requirement and when reserving we + // make sure to leave at least the ed in the free balance. Therefore the receiver always + // exists because there is no way for it to be removed in between. The sender always has + // enough reserved balance because we track it in the `ContractInfo` and never send more + // back than we have. + Deposit::Refund(amount) => { + let amount = if terminated { + *amount + } else { + // This is necessary when the `storage_deposit` tracked inside the account + // info is out of sync with the actual balance. That can only happen due to + // slashing. We make sure to never dust the contract's account through a + // refund because we consider this unexpected behaviour. + *amount.min( + &T::Currency::reserved_balance(contract) + .saturating_sub(T::Currency::minimum_balance()), + ) + }; + let result = + T::Currency::repatriate_reserved(contract, origin, amount, BalanceStatus::Free); + if matches!(result, Ok(val) if !val.is_zero()) || matches!(result, Err(_)) { + log::error!( + target: "runtime::contracts", + "Failed to repatriate storage deposit {:?} from contract {:?} to origin {:?}: {:?}", + amount, contract, origin, result, + ); + } + }, + }; + } +} + +mod private { + pub trait Sealed {} + impl Sealed for super::Root {} + impl Sealed for super::Nested {} +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{ + exec::AccountIdOf, + tests::{Test, ALICE, BOB, CHARLIE}, + }; + use pretty_assertions::assert_eq; + use std::cell::RefCell; + + type TestMeter = RawMeter; + + thread_local! { + static TEST_EXT: RefCell = RefCell::new(Default::default()); + } + + #[derive(Debug, PartialEq, Eq)] + struct LimitCheck { + origin: AccountIdOf, + limit: BalanceOf, + min_leftover: BalanceOf, + } + + #[derive(Debug, PartialEq, Eq)] + struct Charge { + origin: AccountIdOf, + contract: AccountIdOf, + amount: DepositOf, + terminated: bool, + } + + #[derive(Default, Debug, PartialEq, Eq)] + struct TestExt { + limit_checks: Vec, + charges: Vec, + } + + impl TestExt { + fn clear(&mut self) { + self.limit_checks.clear(); + self.charges.clear(); + } + } + + impl Ext for TestExt { + fn check_limit( + origin: &AccountIdOf, + limit: Option>, + min_leftover: BalanceOf, + ) -> Result, DispatchError> { + let limit = limit.unwrap_or(42); + TEST_EXT.with(|ext| { + ext.borrow_mut().limit_checks.push(LimitCheck { + origin: origin.clone(), + limit, + min_leftover, + }) + }); + Ok(limit) + } + + fn charge( + origin: &AccountIdOf, + contract: &AccountIdOf, + amount: &DepositOf, + terminated: bool, + ) { + TEST_EXT.with(|ext| { + ext.borrow_mut().charges.push(Charge { + origin: origin.clone(), + contract: contract.clone(), + amount: amount.clone(), + terminated, + }) + }); + } + } + + fn clear_ext() { + TEST_EXT.with(|ext| ext.borrow_mut().clear()) + } + + fn new_info(deposit: BalanceOf) -> ContractInfo { + use crate::storage::Storage; + use sp_runtime::traits::Hash; + + ContractInfo:: { + trie_id: >::generate_trie_id(&ALICE, 42), + code_hash: ::Hashing::hash(b"42"), + storage_deposit: deposit, + } + } + + #[test] + fn new_reserves_balance_works() { + clear_ext(); + + TestMeter::new(&ALICE, Some(1_000), 0).unwrap(); + + TEST_EXT.with(|ext| { + assert_eq!( + *ext.borrow(), + TestExt { + limit_checks: vec![LimitCheck { origin: ALICE, limit: 1_000, min_leftover: 0 }], + ..Default::default() + } + ) + }); + } + + #[test] + fn empty_charge_works() { + clear_ext(); + + let mut meter = TestMeter::new(&ALICE, Some(1_000), 0).unwrap(); + assert_eq!(meter.available(), 1_000); + + // an empty charge foes not create a `Charge` entry + let mut nested0 = meter.nested(); + nested0.charge(&Default::default()).unwrap(); + meter.absorb(nested0, &ALICE, &BOB, None); + + TEST_EXT.with(|ext| { + assert_eq!( + *ext.borrow(), + TestExt { + limit_checks: vec![LimitCheck { origin: ALICE, limit: 1_000, min_leftover: 0 }], + ..Default::default() + } + ) + }); + } + + #[test] + fn existential_deposit_works() { + clear_ext(); + + let mut meter = TestMeter::new(&ALICE, Some(1_000), 0).unwrap(); + assert_eq!(meter.available(), 1_000); + + // a `Refund` will be turned into a `Charge(ed)` which is intended behaviour + let mut nested0 = meter.nested(); + nested0.charge(&Diff { require_ed: true, ..Default::default() }).unwrap(); + nested0 + .charge(&Diff { bytes_removed: 1, require_ed: true, ..Default::default() }) + .unwrap(); + meter.absorb(nested0, &ALICE, &BOB, None); + + TEST_EXT.with(|ext| { + assert_eq!( + *ext.borrow(), + TestExt { + limit_checks: vec![LimitCheck { origin: ALICE, limit: 1_000, min_leftover: 0 }], + charges: vec![Charge { + origin: ALICE, + contract: BOB, + amount: Deposit::Charge(::Currency::minimum_balance() * 2), + terminated: false, + }], + ..Default::default() + } + ) + }); + } + + #[test] + fn charging_works() { + clear_ext(); + + let min_balance = ::Currency::minimum_balance(); + + let mut meter = TestMeter::new(&ALICE, Some(1_000), 0).unwrap(); + assert_eq!(meter.available(), 1_000); + + let mut nested0_info = new_info(100); + let mut nested0 = meter.nested(); + nested0 + .charge(&Diff { + bytes_added: 10, + bytes_removed: 5, + items_added: 1, + items_removed: 2, + ..Default::default() + }) + .unwrap(); + nested0.charge(&Diff { bytes_removed: 1, ..Default::default() }).unwrap(); + + let mut nested1_info = new_info(50); + let mut nested1 = nested0.nested(); + nested1.charge(&Diff { items_removed: 5, ..Default::default() }).unwrap(); + nested0.absorb(nested1, &ALICE, &CHARLIE, Some(&mut nested1_info)); + + // Trying to refund more than is available in the contract will cap the charge + // to (deposit_in_contract - ed). + let mut nested2_info = new_info(5); + let mut nested2 = nested0.nested(); + nested2.charge(&Diff { bytes_removed: 7, ..Default::default() }).unwrap(); + nested0.absorb(nested2, &ALICE, &CHARLIE, Some(&mut nested2_info)); + + meter.absorb(nested0, &ALICE, &BOB, Some(&mut nested0_info)); + + assert_eq!(nested0_info.storage_deposit, 102); + assert_eq!(nested1_info.storage_deposit, 40); + assert_eq!(nested2_info.storage_deposit, min_balance); + + TEST_EXT.with(|ext| { + assert_eq!( + *ext.borrow(), + TestExt { + limit_checks: vec![LimitCheck { origin: ALICE, limit: 1_000, min_leftover: 0 }], + charges: vec![ + Charge { + origin: ALICE, + contract: CHARLIE, + amount: Deposit::Refund(10), + terminated: false + }, + Charge { + origin: ALICE, + contract: CHARLIE, + amount: Deposit::Refund(4), + terminated: false + }, + Charge { + origin: ALICE, + contract: BOB, + amount: Deposit::Charge(2), + terminated: false + } + ], + ..Default::default() + } + ) + }); + } + + #[test] + fn termination_works() { + clear_ext(); + + let mut meter = TestMeter::new(&ALICE, Some(1_000), 0).unwrap(); + assert_eq!(meter.available(), 1_000); + + let mut nested0 = meter.nested(); + nested0 + .charge(&Diff { + bytes_added: 5, + bytes_removed: 1, + items_added: 3, + items_removed: 1, + ..Default::default() + }) + .unwrap(); + nested0.charge(&Diff { items_added: 2, ..Default::default() }).unwrap(); + + let nested1_info = new_info(400); + let mut nested1 = nested0.nested(); + nested1.charge(&Diff { items_removed: 5, ..Default::default() }).unwrap(); + nested1.charge(&Diff { bytes_added: 20, ..Default::default() }).unwrap(); + nested1.terminate(&nested1_info); + nested0.absorb(nested1, &ALICE, &CHARLIE, None); + + meter.absorb(nested0, &ALICE, &BOB, None); + drop(meter); + + TEST_EXT.with(|ext| { + assert_eq!( + *ext.borrow(), + TestExt { + limit_checks: vec![LimitCheck { origin: ALICE, limit: 1_000, min_leftover: 0 }], + charges: vec![ + Charge { + origin: ALICE, + contract: CHARLIE, + amount: Deposit::Refund(400), + terminated: true + }, + Charge { + origin: ALICE, + contract: BOB, + amount: Deposit::Charge(12), + terminated: false + } + ], + ..Default::default() + } + ) + }); + } +} diff --git a/frame/contracts/src/tests.rs b/frame/contracts/src/tests.rs index 6a252527d1ea..f19f5a315955 100644 --- a/frame/contracts/src/tests.rs +++ b/frame/contracts/src/tests.rs @@ -21,19 +21,19 @@ use crate::{ ReturnFlags, SysConfig, UncheckedFrom, }, exec::Frame, - storage::{RawContractInfo, Storage}, + storage::Storage, wasm::{PrefabWasmModule, ReturnCode as RuntimeReturnCode}, weights::WeightInfo, - BalanceOf, Config, ContractInfoOf, Error, Pallet, Schedule, + BalanceOf, CodeStorage, Config, ContractInfoOf, Error, Pallet, Schedule, }; use assert_matches::assert_matches; use codec::Encode; use frame_support::{ - assert_err, assert_err_ignore_postinfo, assert_ok, + assert_err, assert_err_ignore_postinfo, assert_noop, assert_ok, dispatch::DispatchErrorWithPostInfo, parameter_types, storage::child, - traits::{Contains, Currency, OnInitialize, ReservableCurrency}, + traits::{BalanceStatus, Contains, Currency, OnInitialize, ReservableCurrency}, weights::{constants::WEIGHT_PER_SECOND, DispatchClass, PostDispatchInfo, Weight}, }; use frame_system::{self as system, EventRecord, Phase}; @@ -71,30 +71,17 @@ frame_support::construct_runtime!( pub mod test_utils { use super::{Balances, Test}; use crate::{ - exec::{AccountIdOf, StorageKey}, - storage::Storage, - AccountCounter, CodeHash, ContractInfoOf, Pallet as Contracts, TrieId, + exec::AccountIdOf, storage::Storage, AccountCounter, CodeHash, Config, ContractInfoOf, }; use frame_support::traits::Currency; - pub fn set_storage(addr: &AccountIdOf, key: &StorageKey, value: Option>) { - let mut contract_info = >::get(&addr).unwrap(); - Storage::::write(&mut contract_info, key, value).unwrap(); - } - pub fn get_storage(addr: &AccountIdOf, key: &StorageKey) -> Option> { - let contract_info = >::get(&addr).unwrap(); - Storage::::read(&contract_info.trie_id, key) - } - pub fn generate_trie_id(address: &AccountIdOf) -> TrieId { + pub fn place_contract(address: &AccountIdOf, code_hash: CodeHash) { let seed = >::mutate(|counter| { *counter += 1; *counter }); - Storage::::generate_trie_id(address, seed) - } - pub fn place_contract(address: &AccountIdOf, code_hash: CodeHash) { - let trie_id = generate_trie_id(address); - set_balance(address, Contracts::::subsistence_threshold() * 10); + let trie_id = Storage::::generate_trie_id(address, seed); + set_balance(address, ::Currency::minimum_balance() * 10); let contract = Storage::::new_contract(&address, trie_id, code_hash).unwrap(); >::insert(address, contract); } @@ -113,7 +100,7 @@ pub mod test_utils { } macro_rules! assert_refcount { ( $code_hash:expr , $should:expr $(,)? ) => {{ - let is = crate::CodeStorage::::get($code_hash).map(|m| m.refcount()).unwrap_or(0); + let is = crate::OwnerInfoOf::::get($code_hash).map(|m| m.refcount()).unwrap(); assert_eq!(is, $should); }}; } @@ -193,7 +180,7 @@ parameter_types! { pub const BlockHashCount: u64 = 250; pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max(2 * WEIGHT_PER_SECOND); - pub static ExistentialDeposit: u64 = 0; + pub static ExistentialDeposit: u64 = 1; } impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; @@ -248,13 +235,14 @@ impl pallet_utility::Config for Test { type WeightInfo = (); } parameter_types! { - pub const ContractDeposit: u64 = 16; pub const MaxValueSize: u32 = 16_384; pub const DeletionQueueDepth: u32 = 1024; pub const DeletionWeightLimit: Weight = 500_000_000_000; pub const MaxCodeSize: u32 = 2 * 1024; pub MySchedule: Schedule = >::default(); pub const TransactionByteFee: u64 = 0; + pub static DepositPerByte: BalanceOf = 1; + pub const DepositPerItem: BalanceOf = 2; } impl Convert> for Test { @@ -289,7 +277,6 @@ impl Config for Test { type Event = Event; type Call = Call; type CallFilter = TestFilter; - type ContractDeposit = ContractDeposit; type CallStack = [Frame; 31]; type WeightPrice = Self; type WeightInfo = (); @@ -297,6 +284,8 @@ impl Config for Test { type DeletionQueueDepth = DeletionQueueDepth; type DeletionWeightLimit = DeletionWeightLimit; type Schedule = MySchedule; + type DepositPerByte = DepositPerByte; + type DepositPerItem = DepositPerItem; } pub const ALICE: AccountId32 = AccountId32::new([1u8; 32]); @@ -304,14 +293,14 @@ pub const BOB: AccountId32 = AccountId32::new([2u8; 32]); pub const CHARLIE: AccountId32 = AccountId32::new([3u8; 32]); pub const DJANGO: AccountId32 = AccountId32::new([4u8; 32]); -const GAS_LIMIT: Weight = 10_000_000_000; +pub const GAS_LIMIT: Weight = 10_000_000_000; pub struct ExtBuilder { existential_deposit: u64, } impl Default for ExtBuilder { fn default() -> Self { - Self { existential_deposit: 1 } + Self { existential_deposit: ExistentialDeposit::get() } } } impl ExtBuilder { @@ -323,6 +312,9 @@ impl ExtBuilder { EXISTENTIAL_DEPOSIT.with(|v| *v.borrow_mut() = self.existential_deposit); } pub fn build(self) -> sp_io::TestExternalities { + use env_logger::{Builder, Env}; + let env = Env::new().default_filter_or("runtime=debug"); + let _ = Builder::from_env(env).is_test(true).try_init(); self.set_associated_consts(); let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); pallet_balances::GenesisConfig:: { balances: vec![] } @@ -358,7 +350,7 @@ fn calling_plain_account_fails() { let base_cost = <::WeightInfo as WeightInfo>::call(); assert_eq!( - Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, Vec::new()), + Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, None, Vec::new()), Err(DispatchErrorWithPostInfo { error: Error::::ContractNotFound.into(), post_info: PostDispatchInfo { @@ -370,114 +362,65 @@ fn calling_plain_account_fails() { }); } -#[test] -fn account_removal_does_not_remove_storage() { - use self::test_utils::{get_storage, set_storage}; - - ExtBuilder::default().existential_deposit(100).build().execute_with(|| { - let trie_id1 = test_utils::generate_trie_id(&ALICE); - let trie_id2 = test_utils::generate_trie_id(&BOB); - let key1 = &[1; 32]; - let key2 = &[2; 32]; - - // Set up two accounts with free balance above the existential threshold. - { - let alice_contract_info = RawContractInfo { - trie_id: trie_id1.clone(), - code_hash: H256::repeat_byte(1), - _reserved: None, - }; - let _ = Balances::deposit_creating(&ALICE, 110); - ContractInfoOf::::insert(ALICE, &alice_contract_info); - set_storage(&ALICE, &key1, Some(b"1".to_vec())); - set_storage(&ALICE, &key2, Some(b"2".to_vec())); - - let bob_contract_info = RawContractInfo { - trie_id: trie_id2.clone(), - code_hash: H256::repeat_byte(2), - _reserved: None, - }; - let _ = Balances::deposit_creating(&BOB, 110); - ContractInfoOf::::insert(BOB, &bob_contract_info); - set_storage(&BOB, &key1, Some(b"3".to_vec())); - set_storage(&BOB, &key2, Some(b"4".to_vec())); - } - - // Transfer funds from ALICE account of such amount that after this transfer - // the balance of the ALICE account will be below the existential threshold. - // - // This does not remove the contract storage as we are not notified about a - // account removal. This cannot happen in reality because a contract can only - // remove itself by `seal_terminate`. There is no external event that can remove - // the account appart from that. - assert_ok!(Balances::transfer(Origin::signed(ALICE), BOB, 20)); - - // Verify that no entries are removed. - { - assert_eq!(get_storage(&ALICE, key1), Some(b"1".to_vec())); - assert_eq!(get_storage(&ALICE, key2), Some(b"2".to_vec())); - - assert_eq!(get_storage(&BOB, key1), Some(b"3".to_vec())); - assert_eq!(get_storage(&BOB, key2), Some(b"4".to_vec())); - } - }); -} - #[test] fn instantiate_and_call_and_deposit_event() { let (wasm, code_hash) = compile_module::("return_from_start_fn").unwrap(); - ExtBuilder::default().existential_deposit(100).build().execute_with(|| { + ExtBuilder::default().existential_deposit(500).build().execute_with(|| { let _ = Balances::deposit_creating(&ALICE, 1_000_000); - let subsistence = Pallet::::subsistence_threshold(); + let min_balance = ::Currency::minimum_balance(); + let value = 100; + + // We determine the storage deposit limit after uploading because it depends on ALICEs free + // balance which is changed by uploading a module. + assert_ok!(Contracts::upload_code(Origin::signed(ALICE), wasm, None)); + + // Drop previous events + initialize_block(2); // Check at the end to get hash on error easily - let creation = Contracts::instantiate_with_code( + assert_ok!(Contracts::instantiate( Origin::signed(ALICE), - subsistence * 100, + value, GAS_LIMIT, - wasm, + None, + code_hash, vec![], vec![], - ); + )); let addr = Contracts::contract_address(&ALICE, &code_hash, &[]); + assert!(ContractInfoOf::::contains_key(&addr)); assert_eq!( System::events(), vec![ EventRecord { phase: Phase::Initialization, - event: Event::Balances(pallet_balances::Event::Deposit { - who: ALICE, - amount: 1_000_000 - }), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: Event::System(frame_system::Event::NewAccount { - account: ALICE.clone() - }), + event: Event::System(frame_system::Event::NewAccount { account: addr.clone() }), topics: vec![], }, EventRecord { phase: Phase::Initialization, event: Event::Balances(pallet_balances::Event::Endowed { - account: ALICE, - free_balance: 1_000_000 + account: addr.clone(), + free_balance: min_balance, }), topics: vec![], }, EventRecord { phase: Phase::Initialization, - event: Event::System(frame_system::Event::NewAccount { account: addr.clone() }), + event: Event::Balances(pallet_balances::Event::Transfer { + from: ALICE, + to: addr.clone(), + amount: min_balance, + }), topics: vec![], }, EventRecord { phase: Phase::Initialization, - event: Event::Balances(pallet_balances::Event::Endowed { - account: addr.clone(), - free_balance: subsistence * 100 + event: Event::Balances(pallet_balances::Event::Reserved { + who: addr.clone(), + amount: min_balance, }), topics: vec![], }, @@ -486,14 +429,7 @@ fn instantiate_and_call_and_deposit_event() { event: Event::Balances(pallet_balances::Event::Transfer { from: ALICE, to: addr.clone(), - amount: subsistence * 100 - }), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: Event::Contracts(crate::Event::CodeStored { - code_hash: code_hash.into() + amount: value, }), topics: vec![], }, @@ -515,9 +451,6 @@ fn instantiate_and_call_and_deposit_event() { }, ] ); - - assert_ok!(creation); - assert!(ContractInfoOf::::contains_key(&addr)); }); } @@ -532,6 +465,7 @@ fn deposit_event_max_value_limit() { Origin::signed(ALICE), 30_000, GAS_LIMIT, + None, wasm, vec![], vec![], @@ -544,6 +478,7 @@ fn deposit_event_max_value_limit() { addr.clone(), 0, GAS_LIMIT * 2, // we are copying a huge buffer, + None, ::Schedule::get().limits.payload_len.encode(), )); @@ -554,6 +489,7 @@ fn deposit_event_max_value_limit() { addr, 0, GAS_LIMIT, + None, (::Schedule::get().limits.payload_len + 1).encode(), ), Error::::ValueTooLarge, @@ -564,15 +500,15 @@ fn deposit_event_max_value_limit() { #[test] fn run_out_of_gas() { let (wasm, code_hash) = compile_module::("run_out_of_gas").unwrap(); - let subsistence = Pallet::::subsistence_threshold(); - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + let min_balance = ::Currency::minimum_balance(); let _ = Balances::deposit_creating(&ALICE, 1_000_000); assert_ok!(Contracts::instantiate_with_code( Origin::signed(ALICE), - 100 * subsistence, + 100 * min_balance, GAS_LIMIT, + None, wasm, vec![], vec![], @@ -587,6 +523,7 @@ fn run_out_of_gas() { addr, // newly created account 0, 1_000_000_000_000, + None, vec![], ), Error::::OutOfGas, @@ -609,6 +546,7 @@ fn storage_max_value_limit() { Origin::signed(ALICE), 30_000, GAS_LIMIT, + None, wasm, vec![], vec![], @@ -622,6 +560,7 @@ fn storage_max_value_limit() { addr.clone(), 0, GAS_LIMIT * 2, // we are copying a huge buffer + None, ::Schedule::get().limits.payload_len.encode(), )); @@ -632,6 +571,7 @@ fn storage_max_value_limit() { addr, 0, GAS_LIMIT, + None, (::Schedule::get().limits.payload_len + 1).encode(), ), Error::::ValueTooLarge, @@ -641,16 +581,21 @@ fn storage_max_value_limit() { #[test] fn deploy_and_call_other_contract() { - let (callee_wasm, callee_code_hash) = compile_module::("return_with_data").unwrap(); let (caller_wasm, caller_code_hash) = compile_module::("caller_contract").unwrap(); + let (callee_wasm, callee_code_hash) = compile_module::("return_with_data").unwrap(); + let caller_addr = Contracts::contract_address(&ALICE, &caller_code_hash, &[]); + let callee_addr = Contracts::contract_address(&caller_addr, &callee_code_hash, &[]); + + ExtBuilder::default().existential_deposit(500).build().execute_with(|| { + let min_balance = ::Currency::minimum_balance(); - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { // Create let _ = Balances::deposit_creating(&ALICE, 1_000_000); assert_ok!(Contracts::instantiate_with_code( Origin::signed(ALICE), 100_000, GAS_LIMIT, + None, caller_wasm, vec![], vec![], @@ -659,34 +604,104 @@ fn deploy_and_call_other_contract() { Origin::signed(ALICE), 100_000, GAS_LIMIT, + None, callee_wasm, 0u32.to_le_bytes().encode(), vec![42], )); + // Drop previous events + initialize_block(2); + // Call BOB contract, which attempts to instantiate and call the callee contract and // makes various assertions on the results from those calls. assert_ok!(Contracts::call( Origin::signed(ALICE), - Contracts::contract_address(&ALICE, &caller_code_hash, &[]), + caller_addr.clone(), 0, GAS_LIMIT, + None, callee_code_hash.as_ref().to_vec(), )); + + assert_eq!( + System::events(), + vec![ + EventRecord { + phase: Phase::Initialization, + event: Event::System(frame_system::Event::NewAccount { + account: callee_addr.clone() + }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: Event::Balances(pallet_balances::Event::Endowed { + account: callee_addr.clone(), + free_balance: min_balance, + }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: Event::Balances(pallet_balances::Event::Transfer { + from: ALICE, + to: callee_addr.clone(), + amount: min_balance, + }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: Event::Balances(pallet_balances::Event::Reserved { + who: callee_addr.clone(), + amount: min_balance, + }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: Event::Balances(pallet_balances::Event::Transfer { + from: caller_addr.clone(), + to: callee_addr.clone(), + amount: 32768, // hard coded in wasm + }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: Event::Contracts(crate::Event::Instantiated { + deployer: caller_addr.clone(), + contract: callee_addr.clone(), + }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: Event::Balances(pallet_balances::Event::Transfer { + from: caller_addr.clone(), + to: callee_addr.clone(), + amount: 32768, + }), + topics: vec![], + }, + ] + ); }); } #[test] fn cannot_self_destruct_through_draning() { let (wasm, code_hash) = compile_module::("drain").unwrap(); - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + ExtBuilder::default().existential_deposit(200).build().execute_with(|| { let _ = Balances::deposit_creating(&ALICE, 1_000_000); // Instantiate the BOB contract. assert_ok!(Contracts::instantiate_with_code( Origin::signed(ALICE), - 100_000, + 1_000, GAS_LIMIT, + None, wasm, vec![], vec![], @@ -697,8 +712,153 @@ fn cannot_self_destruct_through_draning() { assert_matches!(ContractInfoOf::::get(&addr), Some(_)); // Call BOB which makes it send all funds to the zero address - // The contract code asserts that the correct error value is returned. - assert_ok!(Contracts::call(Origin::signed(ALICE), addr, 0, GAS_LIMIT, vec![])); + // The contract code asserts that the transfer was successful + assert_ok!(Contracts::call( + Origin::signed(ALICE), + addr.clone(), + 0, + GAS_LIMIT, + None, + vec![] + )); + + // Make sure the account wasn't remove by sending all free balance away. + assert_eq!( + ::Currency::total_balance(&addr), + ::Currency::minimum_balance(), + ); + }); +} + +#[test] +fn cannot_self_destruct_through_storage_refund_after_price_change() { + let (wasm, code_hash) = compile_module::("store").unwrap(); + ExtBuilder::default().existential_deposit(200).build().execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + let min_balance = ::Currency::minimum_balance(); + + // Instantiate the BOB contract. + assert_ok!(Contracts::instantiate_with_code( + Origin::signed(ALICE), + 0, + GAS_LIMIT, + None, + wasm, + vec![], + vec![], + )); + let addr = Contracts::contract_address(&ALICE, &code_hash, &[]); + + // Check that the BOB contract has been instantiated and has the minimum balance + let info = ContractInfoOf::::get(&addr).unwrap(); + assert_eq!(info.storage_deposit, min_balance); + assert_eq!(::Currency::total_balance(&addr), min_balance); + + // Create 100 bytes of storage with a price of per byte + assert_ok!(Contracts::call( + Origin::signed(ALICE), + addr.clone(), + 0, + GAS_LIMIT, + None, + 100u32.to_le_bytes().to_vec() + )); + + // Increase the byte price and trigger a refund. This could potentially destroy the account + // because the refund removes the reserved existential deposit. This should not happen. + DEPOSIT_PER_BYTE.with(|c| *c.borrow_mut() = 500); + assert_ok!(Contracts::call( + Origin::signed(ALICE), + addr.clone(), + 0, + GAS_LIMIT, + None, + 0u32.to_le_bytes().to_vec() + )); + + // Make sure the account wasn't removed by the refund + assert_eq!( + ::Currency::total_balance(&addr), + ::Currency::minimum_balance(), + ); + }); +} + +#[test] +fn cannot_self_destruct_by_refund_after_slash() { + let (wasm, code_hash) = compile_module::("store").unwrap(); + ExtBuilder::default().existential_deposit(500).build().execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + let min_balance = ::Currency::minimum_balance(); + + assert_ok!(Contracts::instantiate_with_code( + Origin::signed(ALICE), + 0, + GAS_LIMIT, + None, + wasm, + vec![], + vec![], + )); + let addr = Contracts::contract_address(&ALICE, &code_hash, &[]); + + // create 100 more reserved balance + assert_ok!(Contracts::call( + Origin::signed(ALICE), + addr.clone(), + 0, + GAS_LIMIT, + None, + 98u32.encode(), + )); + + // Drop previous events + initialize_block(2); + + // slash parts of the 100 so that the next refund ould remove the account + // because it the value it stored for `storage_deposit` becomes out of sync + let _ = ::Currency::slash(&addr, 90); + assert_eq!(::Currency::total_balance(&addr), min_balance + 10); + + // trigger a refund of 50 which would bring the contract below min when actually refunded + assert_ok!(Contracts::call( + Origin::signed(ALICE), + addr.clone(), + 0, + GAS_LIMIT, + None, + 48u32.encode(), + )); + + // Make sure the account kept the minimum balance and was not destroyed + assert_eq!(::Currency::total_balance(&addr), min_balance); + + // even though it was not charged it is still substracted from the storage deposit tracker + assert_eq!(ContractInfoOf::::get(&addr).unwrap().storage_deposit, 550); + + assert_eq!( + System::events(), + vec![ + EventRecord { + phase: Phase::Initialization, + event: Event::Balances(pallet_balances::Event::Slashed { + who: addr.clone(), + amount: 90, + }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: Event::Balances(pallet_balances::Event::ReserveRepatriated { + from: addr.clone(), + to: ALICE, + amount: 10, + destination_status: BalanceStatus::Free, + }), + topics: vec![], + }, + ] + ); }); } @@ -713,6 +873,7 @@ fn cannot_self_destruct_while_live() { Origin::signed(ALICE), 100_000, GAS_LIMIT, + None, wasm, vec![], vec![], @@ -725,7 +886,7 @@ fn cannot_self_destruct_while_live() { // Call BOB with input data, forcing it make a recursive call to itself to // self-destruct, resulting in a trap. assert_err_ignore_postinfo!( - Contracts::call(Origin::signed(ALICE), addr.clone(), 0, GAS_LIMIT, vec![0],), + Contracts::call(Origin::signed(ALICE), addr.clone(), 0, GAS_LIMIT, None, vec![0],), Error::::ContractTrapped, ); @@ -737,7 +898,7 @@ fn cannot_self_destruct_while_live() { #[test] fn self_destruct_works() { let (wasm, code_hash) = compile_module::("self_destruct").unwrap(); - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + ExtBuilder::default().existential_deposit(1_000).build().execute_with(|| { let _ = Balances::deposit_creating(&ALICE, 1_000_000); let _ = Balances::deposit_creating(&DJANGO, 1_000_000); @@ -746,6 +907,7 @@ fn self_destruct_works() { Origin::signed(ALICE), 100_000, GAS_LIMIT, + None, wasm, vec![], vec![], @@ -760,51 +922,59 @@ fn self_destruct_works() { // Call BOB without input data which triggers termination. assert_matches!( - Contracts::call(Origin::signed(ALICE), addr.clone(), 0, GAS_LIMIT, vec![],), + Contracts::call(Origin::signed(ALICE), addr.clone(), 0, GAS_LIMIT, None, vec![],), Ok(_) ); + // Check that code is still there but refcount dropped to zero. + assert_refcount!(&code_hash, 0); + + // Check that account is gone + assert!(ContractInfoOf::::get(&addr).is_none()); + assert_eq!(Balances::total_balance(&addr), 0); + + // check that the beneficiary (django) got remaining balance + assert_eq!(Balances::free_balance(DJANGO), 1_000_000 + 100_000); + pretty_assertions::assert_eq!( System::events(), vec![ EventRecord { phase: Phase::Initialization, - event: Event::System(frame_system::Event::KilledAccount { - account: addr.clone() + event: Event::Balances(pallet_balances::Event::Transfer { + from: addr.clone(), + to: DJANGO, + amount: 100_000, }), topics: vec![], }, EventRecord { phase: Phase::Initialization, - event: Event::Balances(pallet_balances::Event::Transfer { - from: addr.clone(), - to: DJANGO, - amount: 100_000, + event: Event::Contracts(crate::Event::Terminated { + contract: addr.clone(), + beneficiary: DJANGO }), topics: vec![], }, EventRecord { phase: Phase::Initialization, - event: Event::Contracts(crate::Event::CodeRemoved { code_hash }), + event: Event::System(frame_system::Event::KilledAccount { + account: addr.clone() + }), topics: vec![], }, EventRecord { phase: Phase::Initialization, - event: Event::Contracts(crate::Event::Terminated { - contract: addr.clone(), - beneficiary: DJANGO + event: Event::Balances(pallet_balances::Event::ReserveRepatriated { + from: addr.clone(), + to: ALICE, + amount: 1_000, + destination_status: BalanceStatus::Free, }), topics: vec![], }, ], ); - - // Check that account is gone - assert!(ContractInfoOf::::get(&addr).is_none()); - - // check that the beneficiary (django) got remaining balance - // some rent was deducted before termination - assert_eq!(Balances::free_balance(DJANGO), 1_000_000 + 100_000); }); } @@ -822,6 +992,7 @@ fn destroy_contract_and_transfer_funds() { Origin::signed(ALICE), 200_000, GAS_LIMIT, + None, callee_wasm, vec![], vec![42] @@ -833,6 +1004,7 @@ fn destroy_contract_and_transfer_funds() { Origin::signed(ALICE), 200_000, GAS_LIMIT, + None, caller_wasm, callee_code_hash.as_ref().to_vec(), vec![], @@ -849,6 +1021,7 @@ fn destroy_contract_and_transfer_funds() { addr_bob, 0, GAS_LIMIT, + None, addr_charlie.encode(), )); @@ -869,6 +1042,7 @@ fn cannot_self_destruct_in_constructor() { Origin::signed(ALICE), 100_000, GAS_LIMIT, + None, wasm, vec![], vec![], @@ -890,6 +1064,7 @@ fn crypto_hashes() { Origin::signed(ALICE), 100_000, GAS_LIMIT, + None, wasm, vec![], vec![], @@ -917,7 +1092,7 @@ fn crypto_hashes() { let mut params = vec![(n + 1) as u8]; params.extend_from_slice(input); let result = - >::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, params, false) + >::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, None, params, false) .result .unwrap(); assert!(result.is_success()); @@ -931,32 +1106,35 @@ fn crypto_hashes() { fn transfer_return_code() { let (wasm, code_hash) = compile_module::("transfer_return_code").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - let subsistence = Pallet::::subsistence_threshold(); - let _ = Balances::deposit_creating(&ALICE, 1000 * subsistence); + let min_balance = ::Currency::minimum_balance(); + let _ = Balances::deposit_creating(&ALICE, 1000 * min_balance); assert_ok!(Contracts::instantiate_with_code( Origin::signed(ALICE), - subsistence * 100, + min_balance * 100, GAS_LIMIT, + None, wasm, vec![], vec![], ),); let addr = Contracts::contract_address(&ALICE, &code_hash, &[]); - // Contract has only the minimal balance so any transfer will return BelowSubsistence. - Balances::make_free_balance_be(&addr, subsistence); - let result = Contracts::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, vec![], false) + // Contract has only the minimal balance so any transfer will fail. + Balances::make_free_balance_be(&addr, min_balance); + let result = Contracts::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, None, vec![], false) .result .unwrap(); - assert_return_code!(result, RuntimeReturnCode::BelowSubsistenceThreshold); + assert_return_code!(result, RuntimeReturnCode::TransferFailed); - // Contract has enough total balance in order to not go below the subsistence + // Contract has enough total balance in order to not go below the min balance // threshold when transfering 100 balance but this balance is reserved so - // the transfer still fails but with another return code. - Balances::make_free_balance_be(&addr, subsistence + 100); - Balances::reserve(&addr, subsistence + 100).unwrap(); - let result = Contracts::bare_call(ALICE, addr, 0, GAS_LIMIT, vec![], false).result.unwrap(); + // the transfer still fails. + Balances::make_free_balance_be(&addr, min_balance + 100); + Balances::reserve(&addr, min_balance + 100).unwrap(); + let result = Contracts::bare_call(ALICE, addr, 0, GAS_LIMIT, None, vec![], false) + .result + .unwrap(); assert_return_code!(result, RuntimeReturnCode::TransferFailed); }); } @@ -966,20 +1144,21 @@ fn call_return_code() { let (caller_code, caller_hash) = compile_module::("call_return_code").unwrap(); let (callee_code, callee_hash) = compile_module::("ok_trap_revert").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - let subsistence = Pallet::::subsistence_threshold(); - let _ = Balances::deposit_creating(&ALICE, 1000 * subsistence); - let _ = Balances::deposit_creating(&CHARLIE, 1000 * subsistence); + let min_balance = ::Currency::minimum_balance(); + let _ = Balances::deposit_creating(&ALICE, 1000 * min_balance); + let _ = Balances::deposit_creating(&CHARLIE, 1000 * min_balance); assert_ok!(Contracts::instantiate_with_code( Origin::signed(ALICE), - subsistence * 100, + min_balance * 100, GAS_LIMIT, + None, caller_code, vec![0], vec![], ),); let addr_bob = Contracts::contract_address(&ALICE, &caller_hash, &[]); - Balances::make_free_balance_be(&addr_bob, subsistence); + Balances::make_free_balance_be(&addr_bob, min_balance); // Contract calls into Django which is no valid contract let result = Contracts::bare_call( @@ -987,6 +1166,7 @@ fn call_return_code() { addr_bob.clone(), 0, GAS_LIMIT, + None, AsRef::<[u8]>::as_ref(&DJANGO).to_vec(), false, ) @@ -996,21 +1176,23 @@ fn call_return_code() { assert_ok!(Contracts::instantiate_with_code( Origin::signed(CHARLIE), - subsistence * 100, + min_balance * 100, GAS_LIMIT, + None, callee_code, vec![0], vec![], ),); let addr_django = Contracts::contract_address(&CHARLIE, &callee_hash, &[]); - Balances::make_free_balance_be(&addr_django, subsistence); + Balances::make_free_balance_be(&addr_django, min_balance); - // Contract has only the minimal balance so any transfer will return BelowSubsistence. + // Contract has only the minimal balance so any transfer will fail. let result = Contracts::bare_call( ALICE, addr_bob.clone(), 0, GAS_LIMIT, + None, AsRef::<[u8]>::as_ref(&addr_django) .iter() .chain(&0u32.to_le_bytes()) @@ -1020,18 +1202,19 @@ fn call_return_code() { ) .result .unwrap(); - assert_return_code!(result, RuntimeReturnCode::BelowSubsistenceThreshold); + assert_return_code!(result, RuntimeReturnCode::TransferFailed); - // Contract has enough total balance in order to not go below the subsistence + // Contract has enough total balance in order to not go below the min balance // threshold when transfering 100 balance but this balance is reserved so - // the transfer still fails but with another return code. - Balances::make_free_balance_be(&addr_bob, subsistence + 100); - Balances::reserve(&addr_bob, subsistence + 100).unwrap(); + // the transfer still fails. + Balances::make_free_balance_be(&addr_bob, min_balance + 100); + Balances::reserve(&addr_bob, min_balance + 100).unwrap(); let result = Contracts::bare_call( ALICE, addr_bob.clone(), 0, GAS_LIMIT, + None, AsRef::<[u8]>::as_ref(&addr_django) .iter() .chain(&0u32.to_le_bytes()) @@ -1044,12 +1227,13 @@ fn call_return_code() { assert_return_code!(result, RuntimeReturnCode::TransferFailed); // Contract has enough balance but callee reverts because "1" is passed. - Balances::make_free_balance_be(&addr_bob, subsistence + 1000); + Balances::make_free_balance_be(&addr_bob, min_balance + 1000); let result = Contracts::bare_call( ALICE, addr_bob.clone(), 0, GAS_LIMIT, + None, AsRef::<[u8]>::as_ref(&addr_django) .iter() .chain(&1u32.to_le_bytes()) @@ -1067,6 +1251,7 @@ fn call_return_code() { addr_bob, 0, GAS_LIMIT, + None, AsRef::<[u8]>::as_ref(&addr_django) .iter() .chain(&2u32.to_le_bytes()) @@ -1085,15 +1270,16 @@ fn instantiate_return_code() { let (caller_code, caller_hash) = compile_module::("instantiate_return_code").unwrap(); let (callee_code, callee_hash) = compile_module::("ok_trap_revert").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - let subsistence = Pallet::::subsistence_threshold(); - let _ = Balances::deposit_creating(&ALICE, 1000 * subsistence); - let _ = Balances::deposit_creating(&CHARLIE, 1000 * subsistence); + let min_balance = ::Currency::minimum_balance(); + let _ = Balances::deposit_creating(&ALICE, 1000 * min_balance); + let _ = Balances::deposit_creating(&CHARLIE, 1000 * min_balance); let callee_hash = callee_hash.as_ref().to_vec(); assert_ok!(Contracts::instantiate_with_code( Origin::signed(ALICE), - subsistence * 100, + min_balance * 100, GAS_LIMIT, + None, callee_code, vec![], vec![], @@ -1101,46 +1287,63 @@ fn instantiate_return_code() { assert_ok!(Contracts::instantiate_with_code( Origin::signed(ALICE), - subsistence * 100, + min_balance * 100, GAS_LIMIT, + None, caller_code, vec![], vec![], ),); let addr = Contracts::contract_address(&ALICE, &caller_hash, &[]); - // Contract has only the minimal balance so any transfer will return BelowSubsistence. - Balances::make_free_balance_be(&addr, subsistence); - let result = - Contracts::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, callee_hash.clone(), false) - .result - .unwrap(); - assert_return_code!(result, RuntimeReturnCode::BelowSubsistenceThreshold); - - // Contract has enough total balance in order to not go below the subsistence - // threshold when transfering the balance but this balance is reserved so - // the transfer still fails but with another return code. - Balances::make_free_balance_be(&addr, subsistence + 10_000); - Balances::reserve(&addr, subsistence + 10_000).unwrap(); - let result = - Contracts::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, callee_hash.clone(), false) - .result - .unwrap(); - assert_return_code!(result, RuntimeReturnCode::TransferFailed); - - // Contract has enough balance but the passed code hash is invalid - Balances::make_free_balance_be(&addr, subsistence + 10_000); - let result = Contracts::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, vec![0; 33], false) - .result - .unwrap(); - assert_return_code!(result, RuntimeReturnCode::CodeNotFound); - - // Contract has enough balance but callee reverts because "1" is passed. + // Contract has only the minimal balance so any transfer will fail. + Balances::make_free_balance_be(&addr, min_balance); let result = Contracts::bare_call( ALICE, addr.clone(), 0, GAS_LIMIT, + None, + callee_hash.clone(), + false, + ) + .result + .unwrap(); + assert_return_code!(result, RuntimeReturnCode::TransferFailed); + + // Contract has enough total balance in order to not go below the min_balance + // threshold when transfering the balance but this balance is reserved so + // the transfer still fails. + Balances::make_free_balance_be(&addr, min_balance + 10_000); + Balances::reserve(&addr, min_balance + 10_000).unwrap(); + let result = Contracts::bare_call( + ALICE, + addr.clone(), + 0, + GAS_LIMIT, + None, + callee_hash.clone(), + false, + ) + .result + .unwrap(); + assert_return_code!(result, RuntimeReturnCode::TransferFailed); + + // Contract has enough balance but the passed code hash is invalid + Balances::make_free_balance_be(&addr, min_balance + 10_000); + let result = + Contracts::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, None, vec![0; 33], false) + .result + .unwrap(); + assert_return_code!(result, RuntimeReturnCode::CodeNotFound); + + // Contract has enough balance but callee reverts because "1" is passed. + let result = Contracts::bare_call( + ALICE, + addr.clone(), + 0, + GAS_LIMIT, + None, callee_hash.iter().chain(&1u32.to_le_bytes()).cloned().collect(), false, ) @@ -1154,6 +1357,7 @@ fn instantiate_return_code() { addr, 0, GAS_LIMIT, + None, callee_hash.iter().chain(&2u32.to_le_bytes()).cloned().collect(), false, ) @@ -1167,14 +1371,15 @@ fn instantiate_return_code() { fn disabled_chain_extension_wont_deploy() { let (code, _hash) = compile_module::("chain_extension").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - let subsistence = Pallet::::subsistence_threshold(); - let _ = Balances::deposit_creating(&ALICE, 1000 * subsistence); + let min_balance = ::Currency::minimum_balance(); + let _ = Balances::deposit_creating(&ALICE, 1000 * min_balance); TestExtension::disable(); assert_err_ignore_postinfo!( Contracts::instantiate_with_code( Origin::signed(ALICE), - 3 * subsistence, + 3 * min_balance, GAS_LIMIT, + None, code, vec![], vec![], @@ -1188,12 +1393,13 @@ fn disabled_chain_extension_wont_deploy() { fn disabled_chain_extension_errors_on_call() { let (code, hash) = compile_module::("chain_extension").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - let subsistence = Pallet::::subsistence_threshold(); - let _ = Balances::deposit_creating(&ALICE, 1000 * subsistence); + let min_balance = ::Currency::minimum_balance(); + let _ = Balances::deposit_creating(&ALICE, 1000 * min_balance); assert_ok!(Contracts::instantiate_with_code( Origin::signed(ALICE), - subsistence * 100, + min_balance * 100, GAS_LIMIT, + None, code, vec![], vec![], @@ -1201,7 +1407,7 @@ fn disabled_chain_extension_errors_on_call() { let addr = Contracts::contract_address(&ALICE, &hash, &[]); TestExtension::disable(); assert_err_ignore_postinfo!( - Contracts::call(Origin::signed(ALICE), addr.clone(), 0, GAS_LIMIT, vec![],), + Contracts::call(Origin::signed(ALICE), addr.clone(), 0, GAS_LIMIT, None, vec![],), Error::::NoChainExtension, ); }); @@ -1211,12 +1417,13 @@ fn disabled_chain_extension_errors_on_call() { fn chain_extension_works() { let (code, hash) = compile_module::("chain_extension").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - let subsistence = Pallet::::subsistence_threshold(); - let _ = Balances::deposit_creating(&ALICE, 1000 * subsistence); + let min_balance = ::Currency::minimum_balance(); + let _ = Balances::deposit_creating(&ALICE, 1000 * min_balance); assert_ok!(Contracts::instantiate_with_code( Origin::signed(ALICE), - subsistence * 100, + min_balance * 100, GAS_LIMIT, + None, code, vec![], vec![], @@ -1228,25 +1435,27 @@ fn chain_extension_works() { // func_id. // 0 = read input buffer and pass it through as output - let result = Contracts::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, vec![0, 99], false); + let result = + Contracts::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, None, vec![0, 99], false); let gas_consumed = result.gas_consumed; assert_eq!(TestExtension::last_seen_buffer(), vec![0, 99]); assert_eq!(result.result.unwrap().data, Bytes(vec![0, 99])); // 1 = treat inputs as integer primitives and store the supplied integers - Contracts::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, vec![1], false) + Contracts::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, None, vec![1], false) .result .unwrap(); // those values passed in the fixture assert_eq!(TestExtension::last_seen_inputs(), (4, 1, 16, 12)); // 2 = charge some extra weight (amount supplied in second byte) - let result = Contracts::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, vec![2, 42], false); + let result = + Contracts::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, None, vec![2, 42], false); assert_ok!(result.result); assert_eq!(result.gas_consumed, gas_consumed + 42); // 3 = diverging chain extension call that sets flags to 0x1 and returns a fixed buffer - let result = Contracts::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, vec![3], false) + let result = Contracts::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, None, vec![3], false) .result .unwrap(); assert_eq!(result.flags, ReturnFlags::REVERT); @@ -1258,13 +1467,14 @@ fn chain_extension_works() { fn lazy_removal_works() { let (code, hash) = compile_module::("self_destruct").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - let subsistence = Pallet::::subsistence_threshold(); - let _ = Balances::deposit_creating(&ALICE, 1000 * subsistence); + let min_balance = ::Currency::minimum_balance(); + let _ = Balances::deposit_creating(&ALICE, 1000 * min_balance); assert_ok!(Contracts::instantiate_with_code( Origin::signed(ALICE), - subsistence * 100, + min_balance * 100, GAS_LIMIT, + None, code, vec![], vec![], @@ -1278,7 +1488,14 @@ fn lazy_removal_works() { child::put(trie, &[99], &42); // Terminate the contract - assert_ok!(Contracts::call(Origin::signed(ALICE), addr.clone(), 0, GAS_LIMIT, vec![])); + assert_ok!(Contracts::call( + Origin::signed(ALICE), + addr.clone(), + 0, + GAS_LIMIT, + None, + vec![] + )); // Contract info should be gone assert!(!>::contains_key(&addr)); @@ -1309,29 +1526,37 @@ fn lazy_removal_partial_remove_works() { let mut ext = ExtBuilder::default().existential_deposit(50).build(); let trie = ext.execute_with(|| { - let subsistence = Pallet::::subsistence_threshold(); - let _ = Balances::deposit_creating(&ALICE, 1000 * subsistence); + let min_balance = ::Currency::minimum_balance(); + let _ = Balances::deposit_creating(&ALICE, 1000 * min_balance); assert_ok!(Contracts::instantiate_with_code( Origin::signed(ALICE), - subsistence * 100, + min_balance * 100, GAS_LIMIT, + None, code, vec![], vec![], ),); let addr = Contracts::contract_address(&ALICE, &hash, &[]); - let mut info = >::get(&addr).unwrap(); + let info = >::get(&addr).unwrap(); // Put value into the contracts child trie for val in &vals { - Storage::::write(&mut info, &val.0, Some(val.2.clone())).unwrap(); + Storage::::write(&info.trie_id, &val.0, Some(val.2.clone()), None).unwrap(); } >::insert(&addr, info.clone()); // Terminate the contract - assert_ok!(Contracts::call(Origin::signed(ALICE), addr.clone(), 0, GAS_LIMIT, vec![])); + assert_ok!(Contracts::call( + Origin::signed(ALICE), + addr.clone(), + 0, + GAS_LIMIT, + None, + vec![] + )); // Contract info should be gone assert!(!>::contains_key(&addr)); @@ -1379,20 +1604,21 @@ fn lazy_removal_partial_remove_works() { fn lazy_removal_does_no_run_on_full_block() { let (code, hash) = compile_module::("self_destruct").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - let subsistence = Pallet::::subsistence_threshold(); - let _ = Balances::deposit_creating(&ALICE, 1000 * subsistence); + let min_balance = ::Currency::minimum_balance(); + let _ = Balances::deposit_creating(&ALICE, 1000 * min_balance); assert_ok!(Contracts::instantiate_with_code( Origin::signed(ALICE), - subsistence * 100, + min_balance * 100, GAS_LIMIT, + None, code, vec![], vec![], ),); let addr = Contracts::contract_address(&ALICE, &hash, &[]); - let mut info = >::get(&addr).unwrap(); + let info = >::get(&addr).unwrap(); let max_keys = 30; // Create some storage items for the contract. @@ -1402,12 +1628,19 @@ fn lazy_removal_does_no_run_on_full_block() { // Put value into the contracts child trie for val in &vals { - Storage::::write(&mut info, &val.0, Some(val.2.clone())).unwrap(); + Storage::::write(&info.trie_id, &val.0, Some(val.2.clone()), None).unwrap(); } >::insert(&addr, info.clone()); // Terminate the contract - assert_ok!(Contracts::call(Origin::signed(ALICE), addr.clone(), 0, GAS_LIMIT, vec![])); + assert_ok!(Contracts::call( + Origin::signed(ALICE), + addr.clone(), + 0, + GAS_LIMIT, + None, + vec![] + )); // Contract info should be gone assert!(!>::contains_key(&addr)); @@ -1454,20 +1687,21 @@ fn lazy_removal_does_not_use_all_weight() { let mut ext = ExtBuilder::default().existential_deposit(50).build(); let (trie, vals, weight_per_key) = ext.execute_with(|| { - let subsistence = Pallet::::subsistence_threshold(); - let _ = Balances::deposit_creating(&ALICE, 1000 * subsistence); + let min_balance = ::Currency::minimum_balance(); + let _ = Balances::deposit_creating(&ALICE, 1000 * min_balance); assert_ok!(Contracts::instantiate_with_code( Origin::signed(ALICE), - subsistence * 100, + min_balance * 100, GAS_LIMIT, + None, code, vec![], vec![], ),); let addr = Contracts::contract_address(&ALICE, &hash, &[]); - let mut info = >::get(&addr).unwrap(); + let info = >::get(&addr).unwrap(); let (weight_per_key, max_keys) = Storage::::deletion_budget(1, weight_limit); // We create a contract with one less storage item than we can remove within the limit @@ -1477,12 +1711,19 @@ fn lazy_removal_does_not_use_all_weight() { // Put value into the contracts child trie for val in &vals { - Storage::::write(&mut info, &val.0, Some(val.2.clone())).unwrap(); + Storage::::write(&info.trie_id, &val.0, Some(val.2.clone()), None).unwrap(); } >::insert(&addr, info.clone()); // Terminate the contract - assert_ok!(Contracts::call(Origin::signed(ALICE), addr.clone(), 0, GAS_LIMIT, vec![])); + assert_ok!(Contracts::call( + Origin::signed(ALICE), + addr.clone(), + 0, + GAS_LIMIT, + None, + vec![] + )); // Contract info should be gone assert!(!>::contains_key(&addr)); @@ -1519,13 +1760,14 @@ fn lazy_removal_does_not_use_all_weight() { fn deletion_queue_full() { let (code, hash) = compile_module::("self_destruct").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - let subsistence = Pallet::::subsistence_threshold(); - let _ = Balances::deposit_creating(&ALICE, 1000 * subsistence); + let min_balance = ::Currency::minimum_balance(); + let _ = Balances::deposit_creating(&ALICE, 1000 * min_balance); assert_ok!(Contracts::instantiate_with_code( Origin::signed(ALICE), - subsistence * 100, + min_balance * 100, GAS_LIMIT, + None, code, vec![], vec![], @@ -1538,7 +1780,7 @@ fn deletion_queue_full() { // Terminate the contract should fail assert_err_ignore_postinfo!( - Contracts::call(Origin::signed(ALICE), addr.clone(), 0, GAS_LIMIT, vec![],), + Contracts::call(Origin::signed(ALICE), addr.clone(), 0, GAS_LIMIT, None, vec![],), Error::::DeletionQueueFull, ); @@ -1552,21 +1794,23 @@ fn refcounter() { let (wasm, code_hash) = compile_module::("self_destruct").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { let _ = Balances::deposit_creating(&ALICE, 1_000_000); - let subsistence = Pallet::::subsistence_threshold(); + let min_balance = ::Currency::minimum_balance(); // Create two contracts with the same code and check that they do in fact share it. assert_ok!(Contracts::instantiate_with_code( Origin::signed(ALICE), - subsistence * 100, + min_balance * 100, GAS_LIMIT, + None, wasm.clone(), vec![], vec![0], )); assert_ok!(Contracts::instantiate_with_code( Origin::signed(ALICE), - subsistence * 100, + min_balance * 100, GAS_LIMIT, + None, wasm.clone(), vec![], vec![1], @@ -1576,8 +1820,9 @@ fn refcounter() { // Sharing should also work with the usual instantiate call assert_ok!(Contracts::instantiate( Origin::signed(ALICE), - subsistence * 100, + min_balance * 100, GAS_LIMIT, + None, code_hash, vec![], vec![2], @@ -1590,23 +1835,23 @@ fn refcounter() { let addr2 = Contracts::contract_address(&ALICE, &code_hash, &[2]); // Terminating one contract should decrement the refcount - assert_ok!(Contracts::call(Origin::signed(ALICE), addr0, 0, GAS_LIMIT, vec![])); + assert_ok!(Contracts::call(Origin::signed(ALICE), addr0, 0, GAS_LIMIT, None, vec![])); assert_refcount!(code_hash, 2); // remove another one - assert_ok!(Contracts::call(Origin::signed(ALICE), addr1, 0, GAS_LIMIT, vec![])); + assert_ok!(Contracts::call(Origin::signed(ALICE), addr1, 0, GAS_LIMIT, None, vec![])); assert_refcount!(code_hash, 1); // Pristine code should still be there crate::PristineCode::::get(code_hash).unwrap(); // remove the last contract - assert_ok!(Contracts::call(Origin::signed(ALICE), addr2, 0, GAS_LIMIT, vec![])); + assert_ok!(Contracts::call(Origin::signed(ALICE), addr2, 0, GAS_LIMIT, None, vec![])); assert_refcount!(code_hash, 0); - // all code should be gone - assert_matches!(crate::PristineCode::::get(code_hash), None); - assert_matches!(crate::CodeStorage::::get(code_hash), None); + // refcount is `0` but code should still exists because it needs to be removed manually + assert!(crate::PristineCode::::contains_key(&code_hash)); + assert!(crate::CodeStorage::::contains_key(&code_hash)); }); } @@ -1615,14 +1860,15 @@ fn reinstrument_does_charge() { let (wasm, code_hash) = compile_module::("return_with_data").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { let _ = Balances::deposit_creating(&ALICE, 1_000_000); - let subsistence = Pallet::::subsistence_threshold(); + let min_balance = ::Currency::minimum_balance(); let zero = 0u32.to_le_bytes().encode(); let code_len = wasm.len() as u32; assert_ok!(Contracts::instantiate_with_code( Origin::signed(ALICE), - subsistence * 100, + min_balance * 100, GAS_LIMIT, + None, wasm, zero.clone(), vec![], @@ -1632,10 +1878,12 @@ fn reinstrument_does_charge() { // Call the contract two times without reinstrument - let result0 = Contracts::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, zero.clone(), false); + let result0 = + Contracts::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, None, zero.clone(), false); assert!(result0.result.unwrap().is_success()); - let result1 = Contracts::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, zero.clone(), false); + let result1 = + Contracts::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, None, zero.clone(), false); assert!(result1.result.unwrap().is_success()); // They should match because both where called with the same schedule. @@ -1648,7 +1896,8 @@ fn reinstrument_does_charge() { }); // This call should trigger reinstrumentation - let result2 = Contracts::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, zero.clone(), false); + let result2 = + Contracts::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, None, zero.clone(), false); assert!(result2.result.unwrap().is_success()); assert!(result2.gas_consumed > result1.gas_consumed); assert_eq!( @@ -1668,12 +1917,13 @@ fn debug_message_works() { Origin::signed(ALICE), 30_000, GAS_LIMIT, + None, wasm, vec![], vec![], ),); let addr = Contracts::contract_address(&ALICE, &code_hash, &[]); - let result = Contracts::bare_call(ALICE, addr, 0, GAS_LIMIT, vec![], true); + let result = Contracts::bare_call(ALICE, addr, 0, GAS_LIMIT, None, vec![], true); assert_matches!(result.result, Ok(_)); assert_eq!(std::str::from_utf8(&result.debug_message).unwrap(), "Hello World!"); @@ -1690,16 +1940,17 @@ fn debug_message_logging_disabled() { Origin::signed(ALICE), 30_000, GAS_LIMIT, + None, wasm, vec![], vec![], ),); let addr = Contracts::contract_address(&ALICE, &code_hash, &[]); // disable logging by passing `false` - let result = Contracts::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, vec![], false); + let result = Contracts::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, None, vec![], false); assert_matches!(result.result, Ok(_)); // the dispatchables always run without debugging - assert_ok!(Contracts::call(Origin::signed(ALICE), addr, 0, GAS_LIMIT, vec![])); + assert_ok!(Contracts::call(Origin::signed(ALICE), addr, 0, GAS_LIMIT, None, vec![])); assert!(result.debug_message.is_empty()); }); } @@ -1714,12 +1965,13 @@ fn debug_message_invalid_utf8() { Origin::signed(ALICE), 30_000, GAS_LIMIT, + None, wasm, vec![], vec![], ),); let addr = Contracts::contract_address(&ALICE, &code_hash, &[]); - let result = Contracts::bare_call(ALICE, addr, 0, GAS_LIMIT, vec![], true); + let result = Contracts::bare_call(ALICE, addr, 0, GAS_LIMIT, None, vec![], true); assert_err!(result.result, >::DebugMessageInvalidUTF8); }); } @@ -1729,14 +1981,15 @@ fn gas_estimation_nested_call_fixed_limit() { let (caller_code, caller_hash) = compile_module::("call_with_limit").unwrap(); let (callee_code, callee_hash) = compile_module::("dummy").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - let subsistence = Pallet::::subsistence_threshold(); - let _ = Balances::deposit_creating(&ALICE, 1000 * subsistence); - let _ = Balances::deposit_creating(&CHARLIE, 1000 * subsistence); + let min_balance = ::Currency::minimum_balance(); + let _ = Balances::deposit_creating(&ALICE, 1000 * min_balance); + let _ = Balances::deposit_creating(&CHARLIE, 1000 * min_balance); assert_ok!(Contracts::instantiate_with_code( Origin::signed(ALICE), - subsistence * 100, + min_balance * 100, GAS_LIMIT, + None, caller_code, vec![], vec![0], @@ -1745,8 +1998,9 @@ fn gas_estimation_nested_call_fixed_limit() { assert_ok!(Contracts::instantiate_with_code( Origin::signed(ALICE), - subsistence * 100, + min_balance * 100, GAS_LIMIT, + None, callee_code, vec![], vec![1], @@ -1760,15 +2014,32 @@ fn gas_estimation_nested_call_fixed_limit() { .collect(); // Call in order to determine the gas that is required for this call - let result = - Contracts::bare_call(ALICE, addr_caller.clone(), 0, GAS_LIMIT, input.clone(), false); + let result = Contracts::bare_call( + ALICE, + addr_caller.clone(), + 0, + GAS_LIMIT, + None, + input.clone(), + false, + ); assert_ok!(&result.result); + // We have a subcall with a fixed gas limit. This constitutes precharging. assert!(result.gas_required > result.gas_consumed); // Make the same call using the estimated gas. Should succeed. assert_ok!( - Contracts::bare_call(ALICE, addr_caller, 0, result.gas_required, input, false,).result + Contracts::bare_call( + ALICE, + addr_caller, + 0, + result.gas_required, + Some(result.storage_deposit.charge_or_zero()), + input, + false, + ) + .result ); }); } @@ -1779,14 +2050,15 @@ fn gas_estimation_call_runtime() { let (caller_code, caller_hash) = compile_module::("call_runtime").unwrap(); let (callee_code, callee_hash) = compile_module::("dummy").unwrap(); ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - let subsistence = Pallet::::subsistence_threshold(); - let _ = Balances::deposit_creating(&ALICE, 1000 * subsistence); - let _ = Balances::deposit_creating(&CHARLIE, 1000 * subsistence); + let min_balance = ::Currency::minimum_balance(); + let _ = Balances::deposit_creating(&ALICE, 1000 * min_balance); + let _ = Balances::deposit_creating(&CHARLIE, 1000 * min_balance); assert_ok!(Contracts::instantiate_with_code( Origin::signed(ALICE), - subsistence * 100, + min_balance * 100, GAS_LIMIT, + None, caller_code, vec![], vec![0], @@ -1795,8 +2067,9 @@ fn gas_estimation_call_runtime() { assert_ok!(Contracts::instantiate_with_code( Origin::signed(ALICE), - subsistence * 100, + min_balance * 100, GAS_LIMIT, + None, callee_code, vec![], vec![1], @@ -1809,18 +2082,34 @@ fn gas_estimation_call_runtime() { dest: addr_callee, value: 0, gas_limit: GAS_LIMIT / 3, + storage_deposit_limit: None, data: vec![], }); - let result = - Contracts::bare_call(ALICE, addr_caller.clone(), 0, GAS_LIMIT, call.encode(), false); + let result = Contracts::bare_call( + ALICE, + addr_caller.clone(), + 0, + GAS_LIMIT, + None, + call.encode(), + false, + ); assert_ok!(&result.result); assert!(result.gas_required > result.gas_consumed); // Make the same call using the required gas. Should succeed. assert_ok!( - Contracts::bare_call(ALICE, addr_caller, 0, result.gas_required, call.encode(), false,) - .result + Contracts::bare_call( + ALICE, + addr_caller, + 0, + result.gas_required, + None, + call.encode(), + false, + ) + .result ); }); } @@ -1838,6 +2127,7 @@ fn ecdsa_recover() { Origin::signed(ALICE), 100_000, GAS_LIMIT, + None, wasm, vec![], vec![], @@ -1867,10 +2157,653 @@ fn ecdsa_recover() { params.extend_from_slice(&signature); params.extend_from_slice(&message_hash); assert!(params.len() == 65 + 32); - let result = >::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, params, false) - .result - .unwrap(); + let result = + >::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, None, params, false) + .result + .unwrap(); assert!(result.is_success()); assert_eq!(result.data.as_ref(), &EXPECTED_COMPRESSED_PUBLIC_KEY); }) } + +#[test] +fn upload_code_works() { + let (wasm, code_hash) = compile_module::("dummy").unwrap(); + + ExtBuilder::default().existential_deposit(100).build().execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + + // Drop previous events + initialize_block(2); + + assert!(!>::contains_key(code_hash)); + assert_ok!(Contracts::upload_code( + Origin::signed(ALICE), + wasm, + Some(codec::Compact(1_000)) + )); + assert!(>::contains_key(code_hash)); + + assert_eq!( + System::events(), + vec![ + EventRecord { + phase: Phase::Initialization, + event: Event::Balances(pallet_balances::Event::Reserved { + who: ALICE, + amount: 180, + }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: Event::Contracts(crate::Event::CodeStored { code_hash }), + topics: vec![], + }, + ] + ); + }); +} + +#[test] +fn upload_code_limit_too_low() { + let (wasm, _code_hash) = compile_module::("dummy").unwrap(); + + ExtBuilder::default().existential_deposit(100).build().execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + + // Drop previous events + initialize_block(2); + + assert_noop!( + Contracts::upload_code(Origin::signed(ALICE), wasm, Some(codec::Compact(100))), + >::StorageDepositLimitExhausted, + ); + + assert_eq!(System::events(), vec![]); + }); +} + +#[test] +fn upload_code_not_enough_balance() { + let (wasm, _code_hash) = compile_module::("dummy").unwrap(); + + ExtBuilder::default().existential_deposit(100).build().execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 150); + + // Drop previous events + initialize_block(2); + + assert_noop!( + Contracts::upload_code(Origin::signed(ALICE), wasm, Some(codec::Compact(1_000))), + >::StorageDepositNotEnoughFunds, + ); + + assert_eq!(System::events(), vec![]); + }); +} + +#[test] +fn remove_code_works() { + let (wasm, code_hash) = compile_module::("dummy").unwrap(); + + ExtBuilder::default().existential_deposit(100).build().execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + + // Drop previous events + initialize_block(2); + + assert_ok!(Contracts::upload_code( + Origin::signed(ALICE), + wasm, + Some(codec::Compact(1_000)) + )); + + assert!(>::contains_key(code_hash)); + assert_ok!(Contracts::remove_code(Origin::signed(ALICE), code_hash)); + assert!(!>::contains_key(code_hash)); + + assert_eq!( + System::events(), + vec![ + EventRecord { + phase: Phase::Initialization, + event: Event::Balances(pallet_balances::Event::Reserved { + who: ALICE, + amount: 180, + }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: Event::Contracts(crate::Event::CodeStored { code_hash }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: Event::Balances(pallet_balances::Event::Unreserved { + who: ALICE, + amount: 180, + }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: Event::Contracts(crate::Event::CodeRemoved { code_hash }), + topics: vec![], + }, + ] + ); + }); +} + +#[test] +fn remove_code_wrong_origin() { + let (wasm, code_hash) = compile_module::("dummy").unwrap(); + + ExtBuilder::default().existential_deposit(100).build().execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + + // Drop previous events + initialize_block(2); + + assert_ok!(Contracts::upload_code( + Origin::signed(ALICE), + wasm, + Some(codec::Compact(1_000)) + )); + + assert_noop!( + Contracts::remove_code(Origin::signed(BOB), code_hash), + sp_runtime::traits::BadOrigin, + ); + + assert_eq!( + System::events(), + vec![ + EventRecord { + phase: Phase::Initialization, + event: Event::Balances(pallet_balances::Event::Reserved { + who: ALICE, + amount: 180, + }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: Event::Contracts(crate::Event::CodeStored { code_hash }), + topics: vec![], + }, + ] + ); + }); +} + +#[test] +fn remove_code_in_use() { + let (wasm, code_hash) = compile_module::("dummy").unwrap(); + + ExtBuilder::default().existential_deposit(100).build().execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + + assert_ok!(Contracts::instantiate_with_code( + Origin::signed(ALICE), + 0, + GAS_LIMIT, + None, + wasm, + vec![], + vec![], + )); + + // Drop previous events + initialize_block(2); + + assert_noop!( + Contracts::remove_code(Origin::signed(ALICE), code_hash), + >::CodeInUse, + ); + + assert_eq!(System::events(), vec![]); + }); +} + +#[test] +fn remove_code_not_found() { + let (_wasm, code_hash) = compile_module::("dummy").unwrap(); + + ExtBuilder::default().existential_deposit(100).build().execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + + // Drop previous events + initialize_block(2); + + assert_noop!( + Contracts::remove_code(Origin::signed(ALICE), code_hash), + >::CodeNotFound, + ); + + assert_eq!(System::events(), vec![]); + }); +} + +#[test] +fn instantiate_with_zero_balance_works() { + let (wasm, code_hash) = compile_module::("dummy").unwrap(); + ExtBuilder::default().existential_deposit(200).build().execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + let min_balance = ::Currency::minimum_balance(); + + // Drop previous events + initialize_block(2); + + // Instantiate the BOB contract. + assert_ok!(Contracts::instantiate_with_code( + Origin::signed(ALICE), + 0, + GAS_LIMIT, + None, + wasm, + vec![], + vec![], + )); + let addr = Contracts::contract_address(&ALICE, &code_hash, &[]); + + // Check that the BOB contract has been instantiated. + assert_matches!(ContractInfoOf::::get(&addr), Some(_)); + + // Make sure the account exists even though no free balance was send + assert_eq!(::Currency::free_balance(&addr), 0,); + assert_eq!( + ::Currency::total_balance(&addr), + ::Currency::minimum_balance(), + ); + + assert_eq!( + System::events(), + vec![ + EventRecord { + phase: Phase::Initialization, + event: Event::System(frame_system::Event::NewAccount { account: addr.clone() }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: Event::Balances(pallet_balances::Event::Endowed { + account: addr.clone(), + free_balance: min_balance, + }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: Event::Balances(pallet_balances::Event::Transfer { + from: ALICE, + to: addr.clone(), + amount: min_balance, + }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: Event::Balances(pallet_balances::Event::Reserved { + who: addr.clone(), + amount: min_balance, + }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: Event::Balances(pallet_balances::Event::Reserved { + who: ALICE, + amount: 180, + }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: Event::Contracts(crate::Event::CodeStored { code_hash }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: Event::Contracts(crate::Event::Instantiated { + deployer: ALICE, + contract: addr.clone(), + }), + topics: vec![], + }, + ] + ); + }); +} + +#[test] +fn instantiate_with_below_existential_deposit_works() { + let (wasm, code_hash) = compile_module::("dummy").unwrap(); + ExtBuilder::default().existential_deposit(200).build().execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + let min_balance = ::Currency::minimum_balance(); + + // Drop previous events + initialize_block(2); + + // Instantiate the BOB contract. + assert_ok!(Contracts::instantiate_with_code( + Origin::signed(ALICE), + 50, + GAS_LIMIT, + None, + wasm, + vec![], + vec![], + )); + let addr = Contracts::contract_address(&ALICE, &code_hash, &[]); + + // Check that the BOB contract has been instantiated. + assert_matches!(ContractInfoOf::::get(&addr), Some(_)); + + // Make sure the account exists even though no free balance was send + assert_eq!(::Currency::free_balance(&addr), 50,); + assert_eq!( + ::Currency::total_balance(&addr), + ::Currency::minimum_balance() + 50, + ); + + assert_eq!( + System::events(), + vec![ + EventRecord { + phase: Phase::Initialization, + event: Event::System(frame_system::Event::NewAccount { account: addr.clone() }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: Event::Balances(pallet_balances::Event::Endowed { + account: addr.clone(), + free_balance: min_balance, + }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: Event::Balances(pallet_balances::Event::Transfer { + from: ALICE, + to: addr.clone(), + amount: min_balance, + }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: Event::Balances(pallet_balances::Event::Reserved { + who: addr.clone(), + amount: min_balance, + }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: Event::Balances(pallet_balances::Event::Transfer { + from: ALICE, + to: addr.clone(), + amount: 50, + }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: Event::Balances(pallet_balances::Event::Reserved { + who: ALICE, + amount: 180, + }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: Event::Contracts(crate::Event::CodeStored { code_hash }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: Event::Contracts(crate::Event::Instantiated { + deployer: ALICE, + contract: addr.clone(), + }), + topics: vec![], + }, + ] + ); + }); +} + +#[test] +fn storage_deposit_works() { + let (wasm, code_hash) = compile_module::("multi_store").unwrap(); + ExtBuilder::default().existential_deposit(200).build().execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + let mut deposit = ::Currency::minimum_balance(); + + assert_ok!(Contracts::instantiate_with_code( + Origin::signed(ALICE), + 0, + GAS_LIMIT, + None, + wasm, + vec![], + vec![], + )); + let addr = Contracts::contract_address(&ALICE, &code_hash, &[]); + + // Drop previous events + initialize_block(2); + + // Create storage + assert_ok!(Contracts::call( + Origin::signed(ALICE), + addr.clone(), + 42, + GAS_LIMIT, + None, + (1_000u32, 5_000u32).encode(), + )); + // 4 is for creating 2 storage items + let charged0 = 4 + 1_000 + 5_000; + deposit += charged0; + assert_eq!(>::get(&addr).unwrap().storage_deposit, deposit); + + // Add more storage (but also remove some) + assert_ok!(Contracts::call( + Origin::signed(ALICE), + addr.clone(), + 0, + GAS_LIMIT, + None, + (2_000u32, 4_900u32).encode(), + )); + let charged1 = 1_000 - 100; + deposit += charged1; + assert_eq!(>::get(&addr).unwrap().storage_deposit, deposit); + + // Remove more storage (but also add some) + assert_ok!(Contracts::call( + Origin::signed(ALICE), + addr.clone(), + 0, + GAS_LIMIT, + None, + (2_100u32, 900u32).encode(), + )); + let refunded0 = 4_000 - 100; + deposit -= refunded0; + assert_eq!(>::get(&addr).unwrap().storage_deposit, deposit); + + assert_eq!( + System::events(), + vec![ + EventRecord { + phase: Phase::Initialization, + event: Event::Balances(pallet_balances::Event::Transfer { + from: ALICE, + to: addr.clone(), + amount: 42, + }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: Event::Balances(pallet_balances::Event::Transfer { + from: ALICE, + to: addr.clone(), + amount: charged0, + }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: Event::Balances(pallet_balances::Event::Reserved { + who: addr.clone(), + amount: charged0, + }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: Event::Balances(pallet_balances::Event::Transfer { + from: ALICE, + to: addr.clone(), + amount: charged1, + }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: Event::Balances(pallet_balances::Event::Reserved { + who: addr.clone(), + amount: charged1, + }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: Event::Balances(pallet_balances::Event::ReserveRepatriated { + from: addr.clone(), + to: ALICE, + amount: refunded0, + destination_status: BalanceStatus::Free, + }), + topics: vec![], + }, + ] + ); + }); +} + +#[test] +fn call_after_killed_account_needs_funding() { + let (wasm, code_hash) = compile_module::("dummy").unwrap(); + ExtBuilder::default().existential_deposit(200).build().execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + let min_balance = ::Currency::minimum_balance(); + + assert_ok!(Contracts::instantiate_with_code( + Origin::signed(ALICE), + 700, + GAS_LIMIT, + None, + wasm, + vec![], + vec![], + )); + let addr = Contracts::contract_address(&ALICE, &code_hash, &[]); + + // Drop previous events + initialize_block(2); + + // Destroy the account of the contract by slashing. + // Slashing can actually happen if the contract takes part in staking. + // It is a corner case and we except the destruction of the account. + let _ = ::Currency::slash( + &addr, + ::Currency::total_balance(&addr), + ); + + // Sending below the minimum balance will fail the call because it needs to create the + // account in order to send balance there. + assert_err_ignore_postinfo!( + Contracts::call( + Origin::signed(ALICE), + addr.clone(), + min_balance - 1, + GAS_LIMIT, + None, + vec![], + ), + >::TransferFailed + ); + + // Sending zero should work as it does not do a transfer + assert_ok!(Contracts::call( + Origin::signed(ALICE), + addr.clone(), + 0, + GAS_LIMIT, + None, + vec![], + )); + + // Sending minimum balance should work + assert_ok!(Contracts::call( + Origin::signed(ALICE), + addr.clone(), + min_balance, + GAS_LIMIT, + None, + vec![], + )); + + assert_eq!( + System::events(), + vec![ + EventRecord { + phase: Phase::Initialization, + event: Event::System(frame_system::Event::KilledAccount { + account: addr.clone() + }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: Event::Balances(pallet_balances::Event::Slashed { + who: addr.clone(), + amount: min_balance + 700 + }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: Event::System(frame_system::Event::NewAccount { account: addr.clone() }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: Event::Balances(pallet_balances::Event::Endowed { + account: addr.clone(), + free_balance: min_balance + }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: Event::Balances(pallet_balances::Event::Transfer { + from: ALICE, + to: addr.clone(), + amount: min_balance + }), + topics: vec![], + }, + ] + ); + }); +} diff --git a/frame/contracts/src/wasm/code_cache.rs b/frame/contracts/src/wasm/code_cache.rs index afb68d4d8117..823d6ed34a67 100644 --- a/frame/contracts/src/wasm/code_cache.rs +++ b/frame/contracts/src/wasm/code_cache.rs @@ -28,177 +28,170 @@ //! this guarantees that every instrumented contract code in cache cannot have the version equal to //! the current one. Thus, before executing a contract it should be reinstrument with new schedule. -#[cfg(feature = "runtime-benchmarks")] -pub use self::private::reinstrument; use crate::{ gas::{GasMeter, Token}, wasm::{prepare, PrefabWasmModule}, weights::WeightInfo, - CodeHash, CodeStorage, Config, Error, Event, Pallet as Contracts, PristineCode, Schedule, + CodeHash, CodeStorage, Config, Error, Event, OwnerInfoOf, Pallet, PristineCode, Schedule, Weight, }; -use frame_support::dispatch::DispatchError; +use frame_support::{ + dispatch::{DispatchError, DispatchResult}, + ensure, + storage::StorageMap, + traits::ReservableCurrency, +}; use sp_core::crypto::UncheckedFrom; +use sp_runtime::traits::BadOrigin; /// Put the instrumented module in storage. /// /// Increments the refcount of the in-storage `prefab_module` if it already exists in storage /// under the specified `code_hash`. -pub fn store(mut prefab_module: PrefabWasmModule) +pub fn store(mut module: PrefabWasmModule, instantiated: bool) -> DispatchResult where T::AccountId: UncheckedFrom + AsRef<[u8]>, { - let code_hash = sp_std::mem::take(&mut prefab_module.code_hash); - - // original_code is only `Some` if the contract was instantiated from a new code - // but `None` if it was loaded from storage. - if let Some(code) = prefab_module.original_code.take() { - >::insert(&code_hash, code); - } + let code_hash = sp_std::mem::take(&mut module.code_hash); >::mutate(&code_hash, |existing| match existing { - Some(module) => increment_64(&mut module.refcount), + Some(existing) => { + // We instrument any uploaded contract anyways. We might as well store it to save + // a potential re-instrumentation later. + existing.code = module.code; + existing.instruction_weights_version = module.instruction_weights_version; + // When the code was merely uploaded but not instantiated we can skip this. + if instantiated { + >::mutate(&code_hash, |owner_info| { + if let Some(owner_info) = owner_info { + owner_info.refcount = owner_info.refcount.checked_add(1).expect( + " + refcount is 64bit. Generating this overflow would require to store + _at least_ 18 exabyte of data assuming that a contract consumes only + one byte of data. Any node would run out of storage space before hitting + this overflow. + qed + ", + ); + } + }) + } + Ok(()) + }, None => { - *existing = Some(prefab_module); - Contracts::::deposit_event(Event::CodeStored { code_hash }) + let orig_code = module.original_code.take().expect( + " + If an executable isn't in storage it was uploaded. + If it was uploaded the original code must exist. qed + ", + ); + let mut owner_info = module.owner_info.take().expect( + "If an executable isn't in storage it was uploaded. + If it was uploaded the owner info was generated and attached. qed + ", + ); + // This `None` case happens only in freshly uploaded modules. This means that + // the `owner` is always the origin of the current transaction. + T::Currency::reserve(&owner_info.owner, owner_info.deposit) + .map_err(|_| >::StorageDepositNotEnoughFunds)?; + owner_info.refcount = if instantiated { 1 } else { 0 }; + >::insert(&code_hash, orig_code); + >::insert(&code_hash, owner_info); + *existing = Some(module); + >::deposit_event(Event::CodeStored { code_hash }); + Ok(()) }, + }) +} + +/// Decrement the refcount of a code in-storage by one. +/// +/// # Note +/// +/// A contract whose refcount dropped to zero isn't automatically removed. A `remove_code` +/// transaction must be submitted by the original uploader to do so. +pub fn decrement_refcount(code_hash: CodeHash) -> Result<(), DispatchError> { + >::mutate(code_hash, |existing| { + if let Some(info) = existing { + info.refcount = info.refcount.saturating_sub(1); + } }); + Ok(()) } -/// Increment the refcount of a code in-storage by one. -pub fn increment_refcount( - code_hash: CodeHash, - gas_meter: &mut GasMeter, -) -> Result<(), DispatchError> -where - T::AccountId: UncheckedFrom + AsRef<[u8]>, -{ - gas_meter.charge(CodeToken::UpdateRefcount(estimate_code_size::(&code_hash)?))?; - >::mutate(code_hash, |existing| { - if let Some(module) = existing { - increment_64(&mut module.refcount); +/// Try to remove code together with all associated information. +pub fn try_remove(origin: &T::AccountId, code_hash: CodeHash) -> DispatchResult { + >::try_mutate_exists(&code_hash, |existing| { + if let Some(owner_info) = existing { + ensure!(owner_info.refcount == 0, >::CodeInUse); + ensure!(&owner_info.owner == origin, BadOrigin); + T::Currency::unreserve(&owner_info.owner, owner_info.deposit); + *existing = None; + >::remove(&code_hash); + >::remove(&code_hash); + >::deposit_event(Event::CodeRemoved { code_hash }); Ok(()) } else { - Err(Error::::CodeNotFound.into()) + Err(>::CodeNotFound.into()) } }) } -/// Decrement the refcount of a code in-storage by one and remove the code when it drops to zero. -pub fn decrement_refcount( - code_hash: CodeHash, - gas_meter: &mut GasMeter, -) -> Result<(), DispatchError> -where - T::AccountId: UncheckedFrom + AsRef<[u8]>, -{ - if let Ok(len) = estimate_code_size::(&code_hash) { - gas_meter.charge(CodeToken::UpdateRefcount(len))?; - } - >::mutate_exists(code_hash, |existing| { - if let Some(module) = existing { - module.refcount = module.refcount.saturating_sub(1); - if module.refcount == 0 { - *existing = None; - finish_removal::(code_hash); - } - } - }); - Ok(()) -} - /// Load code with the given code hash. /// /// If the module was instrumented with a lower version of schedule than /// the current one given as an argument, then this function will perform /// re-instrumentation and update the cache in the storage. -/// -/// # Note -/// -/// If `reinstrument` is set it is assumed that the load is performed in the context of -/// a contract call: This means we charge the size based cased for loading the contract. pub fn load( code_hash: CodeHash, - mut reinstrument: Option<(&Schedule, &mut GasMeter)>, + schedule: &Schedule, + gas_meter: &mut GasMeter, ) -> Result, DispatchError> where T::AccountId: UncheckedFrom + AsRef<[u8]>, { - // The reinstrument case coincides with the cases where we need to charge extra - // based upon the code size: On-chain execution. - if let Some((_, gas_meter)) = &mut reinstrument { - gas_meter.charge(CodeToken::Load(estimate_code_size::(&code_hash)?))?; - } + gas_meter.charge(CodeToken::Load(estimate_code_size::, _>(&code_hash)?))?; let mut prefab_module = >::get(code_hash).ok_or_else(|| Error::::CodeNotFound)?; prefab_module.code_hash = code_hash; - if let Some((schedule, gas_meter)) = reinstrument { - if prefab_module.instruction_weights_version < schedule.instruction_weights.version { - // The instruction weights have changed. - // We need to re-instrument the code with the new instruction weights. - gas_meter.charge(CodeToken::Instrument(prefab_module.original_code_len))?; - private::reinstrument(&mut prefab_module, schedule)?; - } - } - Ok(prefab_module) -} - -mod private { - use super::*; - - /// Instruments the passed prefab wasm module with the supplied schedule. - pub fn reinstrument( - prefab_module: &mut PrefabWasmModule, - schedule: &Schedule, - ) -> Result<(), DispatchError> - where - T::AccountId: UncheckedFrom + AsRef<[u8]>, - { - let original_code = >::get(&prefab_module.code_hash) - .ok_or_else(|| Error::::CodeNotFound)?; - prefab_module.code = prepare::reinstrument_contract::(original_code, schedule)?; - prefab_module.instruction_weights_version = schedule.instruction_weights.version; - >::insert(&prefab_module.code_hash, &*prefab_module); - Ok(()) + if prefab_module.instruction_weights_version < schedule.instruction_weights.version { + // The instruction weights have changed. + // We need to re-instrument the code with the new instruction weights. + gas_meter.charge(CodeToken::Instrument(estimate_code_size::, _>( + &code_hash, + )?))?; + reinstrument(&mut prefab_module, schedule)?; } -} -/// Finish removal of a code by deleting the pristine code and emitting an event. -fn finish_removal(code_hash: CodeHash) -where - T::AccountId: UncheckedFrom + AsRef<[u8]>, -{ - >::remove(code_hash); - Contracts::::deposit_event(Event::CodeRemoved { code_hash }) + Ok(prefab_module) } -/// Increment the refcount panicking if it should ever overflow (which will not happen). -/// -/// We try hard to be infallible here because otherwise more storage transactions would be -/// necessary to account for failures in storing code for an already instantiated contract. -fn increment_64(refcount: &mut u64) { - *refcount = refcount.checked_add(1).expect( - " - refcount is 64bit. Generating this overflow would require to store - _at least_ 18 exabyte of data assuming that a contract consumes only - one byte of data. Any node would run out of storage space before hitting - this overflow. - qed - ", - ); +/// Instruments the passed prefab wasm module with the supplied schedule. +pub fn reinstrument( + prefab_module: &mut PrefabWasmModule, + schedule: &Schedule, +) -> Result<(), DispatchError> { + let original_code = + >::get(&prefab_module.code_hash).ok_or_else(|| Error::::CodeNotFound)?; + prefab_module.code = prepare::reinstrument_contract::(original_code, schedule)?; + prefab_module.instruction_weights_version = schedule.instruction_weights.version; + >::insert(&prefab_module.code_hash, &*prefab_module); + Ok(()) } -/// Get the size of the instrumented code stored at `code_hash` without loading it. +/// Get the size of the code stored at `code_hash` without loading it. /// -/// The returned value is slightly too large because it also contains the fields apart from -/// `code` which are located inside [`PrefabWasmModule`]. However, those are negligible when -/// compared to the code size. Additionally, charging too much weight is completely safe. -fn estimate_code_size(code_hash: &CodeHash) -> Result +/// The returned value is slightly too large when using it for the [`PrefabWasmModule`] +/// because it has other fields in addition to the code itself. However, those are negligible +/// when compared to the code size. Additionally, charging too much weight is completely safe. +fn estimate_code_size(code_hash: &CodeHash) -> Result where - T::AccountId: UncheckedFrom + AsRef<[u8]>, + T: Config, + M: StorageMap, V>, + V: codec::FullCodec, { - let key = >::hashed_key_for(code_hash); + let key = M::hashed_key_for(code_hash); let mut data = [0u8; 0]; let len = sp_io::storage::read(&key, &mut data, 0).ok_or_else(|| Error::::CodeNotFound)?; Ok(len) @@ -212,18 +205,12 @@ enum CodeToken { Instrument(u32), /// Weight for loading a contract per kilobyte. Load(u32), - /// Weight for changing the refcount of a contract per kilobyte. - UpdateRefcount(u32), } -impl Token for CodeToken -where - T: Config, - T::AccountId: UncheckedFrom + AsRef<[u8]>, -{ +impl Token for CodeToken { fn weight(&self) -> Weight { use self::CodeToken::*; - // In case of `Load` and `UpdateRefcount` we already covered the general costs of + // In case of `Load` we already covered the general costs of // accessing the storage but still need to account for the actual size of the // contract code. This is why we substract `T::*::(0)`. We need to do this at this // point because when charging the general weight we do not know the size of @@ -232,8 +219,6 @@ where Instrument(len) => T::WeightInfo::instrument(len / 1024), Load(len) => T::WeightInfo::code_load(len / 1024).saturating_sub(T::WeightInfo::code_load(0)), - UpdateRefcount(len) => T::WeightInfo::code_refcount(len / 1024) - .saturating_sub(T::WeightInfo::code_refcount(0)), } } } diff --git a/frame/contracts/src/wasm/mod.rs b/frame/contracts/src/wasm/mod.rs index 6a807710a526..01e220d410fa 100644 --- a/frame/contracts/src/wasm/mod.rs +++ b/frame/contracts/src/wasm/mod.rs @@ -31,10 +31,10 @@ use crate::{ exec::{ExecResult, Executable, ExportedFunction, Ext}, gas::GasMeter, wasm::env_def::FunctionImplProvider, - CodeHash, Config, Schedule, + AccountIdOf, BalanceOf, CodeHash, CodeStorage, Config, Schedule, }; -use codec::{Decode, Encode}; -use frame_support::dispatch::DispatchError; +use codec::{Decode, Encode, MaxEncodedLen}; +use frame_support::dispatch::{DispatchError, DispatchResult}; use sp_core::crypto::UncheckedFrom; use sp_sandbox::{SandboxEnvironmentBuilder, SandboxInstance, SandboxMemory}; use sp_std::prelude::*; @@ -46,10 +46,9 @@ pub use tests::MockExt; /// # Note /// /// This data structure is mostly immutable once created and stored. The exceptions that -/// can be changed by calling a contract are `refcount`, `instruction_weights_version` and `code`. -/// `refcount` can change when a contract instantiates a new contract or self terminates. -/// `instruction_weights_version` and `code` when a contract with an outdated instrumention is -/// called. Therefore one must be careful when holding any in-memory representation of this +/// can be changed by calling a contract are `instruction_weights_version` and `code`. +/// `instruction_weights_version` and `code` change when a contract with an outdated instrumentation +/// is called. Therefore one must be careful when holding any in-memory representation of this /// type while calling into a contract as those fields can get out of date. #[derive(Clone, Encode, Decode, scale_info::TypeInfo)] #[scale_info(skip_type_params(T))] @@ -63,26 +62,8 @@ pub struct PrefabWasmModule { /// The maximum memory size of a contract's sandbox. #[codec(compact)] maximum: u32, - /// The number of contracts that use this as their contract code. - /// - /// If this number drops to zero this module is removed from storage. - #[codec(compact)] - refcount: u64, - /// This field is reserved for future evolution of format. - /// - /// For now this field is serialized as `None`. In the future we are able to change the - /// type parameter to a new struct that contains the fields that we want to add. - /// That new struct would also contain a reserved field for its future extensions. - /// This works because in SCALE `None` is encoded independently from the type parameter - /// of the option. - _reserved: Option<()>, /// Code instrumented with the latest schedule. code: Vec, - /// The size of the uninstrumented code. - /// - /// We cache this value here in order to avoid the need to pull the pristine code - /// from storage when we only need its length for rent calculations. - original_code_len: u32, /// The uninstrumented, pristine version of the code. /// /// It is not stored because the pristine code has its own storage item. The value @@ -96,6 +77,27 @@ pub struct PrefabWasmModule { /// when loading the module from storage. #[codec(skip)] code_hash: CodeHash, + // This isn't needed for contract execution and does not get loaded from storage by default. + // It is `Some` if and only if this struct was generated from code. + #[codec(skip)] + owner_info: Option>, +} + +/// Information that belongs to a [`PrefabWasmModule`] but is stored separately. +/// +/// It is stored in a separate storage entry to avoid loading the code when not necessary. +#[derive(Clone, Encode, Decode, scale_info::TypeInfo, MaxEncodedLen)] +#[codec(mel_bound(T: Config))] +#[scale_info(skip_type_params(T))] +pub struct OwnerInfo { + /// The account that has deployed the contract and hence is allowed to remove it. + owner: AccountIdOf, + /// The amount of balance that was deposited by the owner in order to deploy it. + #[codec(compact)] + deposit: BalanceOf, + /// The number of contracts that use this as their code. + #[codec(compact)] + refcount: u64, } impl ExportedFunction { @@ -113,11 +115,43 @@ where T::AccountId: UncheckedFrom + AsRef<[u8]>, { /// Create the module by checking and instrumenting `original_code`. + /// + /// This does **not** store the module. For this one need to either call [`Self::store`] + /// or [`::execute`]. pub fn from_code( original_code: Vec, schedule: &Schedule, + owner: AccountIdOf, ) -> Result { - prepare::prepare_contract(original_code, schedule).map_err(Into::into) + prepare::prepare_contract(original_code, schedule, owner).map_err(Into::into) + } + + /// Store the code without instantiating it. + /// + /// Otherwise the code is stored when [`::execute`] is called. + pub fn store(self) -> DispatchResult { + code_cache::store(self, false) + } + + /// Remove the code from storage and refund the deposit to its owner. + /// + /// Applies all necessary checks before removing the code. + pub fn remove(origin: &T::AccountId, code_hash: CodeHash) -> DispatchResult { + code_cache::try_remove::(origin, code_hash) + } + + /// Returns whether there is a deposit to be payed for this module. + /// + /// Returns `0` if the module is already in storage and hence no deposit will + /// be charged when storing it. + pub fn open_deposit(&self) -> BalanceOf { + if >::contains_key(&self.code_hash) { + 0u32.into() + } else { + // Only already in-storage contracts have their `owner_info` set to `None`. + // Therefore it is correct to return `0` in this case. + self.owner_info.as_ref().map(|i| i.deposit).unwrap_or_default() + } } /// Create and store the module without checking nor instrumenting the passed code. @@ -125,22 +159,16 @@ where /// # Note /// /// This is useful for benchmarking where we don't want instrumentation to skew - /// our results. + /// our results. This also does not collect any deposit from the `owner`. #[cfg(feature = "runtime-benchmarks")] pub fn store_code_unchecked( original_code: Vec, schedule: &Schedule, - ) -> Result<(), DispatchError> { - let executable = prepare::benchmarking::prepare_contract(original_code, schedule) + owner: T::AccountId, + ) -> DispatchResult { + let executable = prepare::benchmarking::prepare_contract(original_code, schedule, owner) .map_err::(Into::into)?; - code_cache::store(executable); - Ok(()) - } - - /// Return the refcount of the module. - #[cfg(test)] - pub fn refcount(&self) -> u64 { - self.refcount + code_cache::store(executable, false) } /// Decrement instruction_weights_version by 1. Panics if it is already 0. @@ -150,6 +178,14 @@ where } } +impl OwnerInfo { + /// Return the refcount of the module. + #[cfg(test)] + pub fn refcount(&self) -> u64 { + self.refcount + } +} + impl Executable for PrefabWasmModule where T::AccountId: UncheckedFrom + AsRef<[u8]>, @@ -159,22 +195,11 @@ where schedule: &Schedule, gas_meter: &mut GasMeter, ) -> Result { - code_cache::load(code_hash, Some((schedule, gas_meter))) - } - - fn from_storage_noinstr(code_hash: CodeHash) -> Result { - code_cache::load(code_hash, None) + code_cache::load(code_hash, schedule, gas_meter) } - fn add_user(code_hash: CodeHash, gas_meter: &mut GasMeter) -> Result<(), DispatchError> { - code_cache::increment_refcount::(code_hash, gas_meter) - } - - fn remove_user( - code_hash: CodeHash, - gas_meter: &mut GasMeter, - ) -> Result<(), DispatchError> { - code_cache::decrement_refcount::(code_hash, gas_meter) + fn remove_user(code_hash: CodeHash) -> Result<(), DispatchError> { + code_cache::decrement_refcount::(code_hash) } fn execute>( @@ -200,16 +225,15 @@ where imports.add_host_func(module, name, func_ptr); }); - let mut runtime = Runtime::new(ext, input_data, memory); - // We store before executing so that the code hash is available in the constructor. let code = self.code.clone(); if let &ExportedFunction::Constructor = function { - code_cache::store(self) + code_cache::store(self, true)?; } // Instantiate the instance from the instrumented module code and invoke the contract // entrypoint. + let mut runtime = Runtime::new(ext, input_data, memory); let result = sp_sandbox::default_executor::Instance::new(&code, &imports, &mut runtime) .and_then(|mut instance| instance.invoke(function.identifier(), &[], &mut runtime)); @@ -223,14 +247,6 @@ where fn code_len(&self) -> u32 { self.code.len() as u32 } - - fn aggregate_code_len(&self) -> u32 { - self.original_code_len.saturating_add(self.code_len()) - } - - fn refcount(&self) -> u32 { - self.refcount as u32 - } } #[cfg(test)] @@ -260,7 +276,7 @@ mod tests { #[derive(Debug, PartialEq, Eq)] struct InstantiateEntry { code_hash: H256, - endowment: u64, + value: u64, data: Vec, gas_left: u64, salt: Vec, @@ -341,13 +357,13 @@ mod tests { &mut self, gas_limit: Weight, code_hash: CodeHash, - endowment: u64, + value: u64, data: Vec, salt: &[u8], ) -> Result<(AccountIdOf, ExecReturnValue), ExecError> { self.instantiates.push(InstantiateEntry { code_hash: code_hash.clone(), - endowment, + value, data: data.to_vec(), gas_left: gas_limit, salt: salt.to_vec(), @@ -390,9 +406,6 @@ mod tests { fn minimum_balance(&self) -> u64 { 666 } - fn contract_deposit(&self) -> u64 { - 16 - } fn random(&self, subject: &[u8]) -> (SeedOf, BlockNumberOf) { (H256::from_slice(subject), 42) } @@ -422,7 +435,6 @@ mod tests { self.runtime_calls.borrow_mut().push(call); Ok(Default::default()) } - fn ecdsa_recover( &self, signature: &[u8; 65], @@ -431,13 +443,16 @@ mod tests { self.ecdsa_recover.borrow_mut().push((signature.clone(), message_hash.clone())); Ok([3; 33]) } + fn contract_info(&mut self) -> &mut crate::ContractInfo { + unimplemented!() + } } fn execute>(wat: &str, input_data: Vec, mut ext: E) -> ExecResult { let wasm = wat::parse_str(wat).unwrap(); let schedule = crate::Schedule::default(); let executable = - PrefabWasmModule::<::T>::from_code(wasm, &schedule).unwrap(); + PrefabWasmModule::<::T>::from_code(wasm, &schedule, ALICE).unwrap(); executable.execute(ext.borrow_mut(), &ExportedFunction::Call, input_data) } @@ -761,7 +776,7 @@ mod tests { &mock_ext.instantiates[..], [InstantiateEntry { code_hash, - endowment: 3, + value: 3, data, gas_left: _, salt, @@ -1393,51 +1408,6 @@ mod tests { assert_ok!(execute(CODE_MINIMUM_BALANCE, vec![], MockExt::default())); } - const CODE_CONTRACT_DEPOSIT: &str = r#" -(module - (import "seal0" "seal_contract_deposit" (func $seal_contract_deposit (param i32 i32))) - (import "env" "memory" (memory 1 1)) - - ;; size of our buffer is 32 bytes - (data (i32.const 32) "\20") - - (func $assert (param i32) - (block $ok - (br_if $ok - (get_local 0) - ) - (unreachable) - ) - ) - - (func (export "call") - (call $seal_contract_deposit (i32.const 0) (i32.const 32)) - - ;; assert len == 8 - (call $assert - (i32.eq - (i32.load (i32.const 32)) - (i32.const 8) - ) - ) - - ;; assert that contents of the buffer is equal to the i64 value of 16. - (call $assert - (i64.eq - (i64.load (i32.const 0)) - (i64.const 16) - ) - ) - ) - (func (export "deploy")) -) -"#; - - #[test] - fn contract_deposit() { - assert_ok!(execute(CODE_CONTRACT_DEPOSIT, vec![], MockExt::default())); - } - const CODE_RANDOM: &str = r#" (module (import "seal0" "seal_random" (func $seal_random (param i32 i32 i32 i32))) diff --git a/frame/contracts/src/wasm/prepare.rs b/frame/contracts/src/wasm/prepare.rs index c766914f3d46..6d13c097bd43 100644 --- a/frame/contracts/src/wasm/prepare.rs +++ b/frame/contracts/src/wasm/prepare.rs @@ -21,9 +21,11 @@ use crate::{ chain_extension::ChainExtension, - wasm::{env_def::ImportSatisfyCheck, PrefabWasmModule}, - Config, Schedule, + storage::meter::Diff, + wasm::{env_def::ImportSatisfyCheck, OwnerInfo, PrefabWasmModule}, + AccountIdOf, Config, Schedule, }; +use codec::{Encode, MaxEncodedLen}; use pwasm_utils::parity_wasm::elements::{self, External, Internal, MemoryType, Type, ValueType}; use sp_runtime::traits::Hash; use sp_std::prelude::*; @@ -395,20 +397,35 @@ fn check_and_instrument( fn do_preparation( original_code: Vec, schedule: &Schedule, + owner: AccountIdOf, ) -> Result, &'static str> { let (code, (initial, maximum)) = check_and_instrument::(original_code.as_ref(), schedule)?; - Ok(PrefabWasmModule { + let original_code_len = original_code.len(); + + let mut module = PrefabWasmModule { instruction_weights_version: schedule.instruction_weights.version, initial, maximum, - _reserved: None, code, - original_code_len: original_code.len() as u32, - refcount: 1, code_hash: T::Hashing::hash(&original_code), original_code: Some(original_code), - }) + owner_info: None, + }; + + // We need to add the sizes of the `#[codec(skip)]` fields which are stored in different + // storage items. This is also why we have `3` items added and not only one. + let bytes_added = module + .encoded_size() + .saturating_add(original_code_len) + .saturating_add(>::max_encoded_len()) as u32; + let deposit = Diff { bytes_added, items_added: 3, ..Default::default() } + .to_deposit::() + .charge_or_zero(); + + module.owner_info = Some(OwnerInfo { owner, deposit, refcount: 0 }); + + Ok(module) } /// Loads the given module given in `original_code`, performs some checks on it and @@ -425,8 +442,9 @@ fn do_preparation( pub fn prepare_contract( original_code: Vec, schedule: &Schedule, + owner: AccountIdOf, ) -> Result, &'static str> { - do_preparation::(original_code, schedule) + do_preparation::(original_code, schedule, owner) } /// The same as [`prepare_contract`] but without constructing a new [`PrefabWasmModule`] @@ -461,6 +479,7 @@ pub mod benchmarking { pub fn prepare_contract( original_code: Vec, schedule: &Schedule, + owner: AccountIdOf, ) -> Result, &'static str> { let contract_module = ContractModule::new(&original_code, schedule)?; let memory_limits = get_memory_limits(contract_module.scan_imports::<()>(&[])?, schedule)?; @@ -468,12 +487,15 @@ pub mod benchmarking { instruction_weights_version: schedule.instruction_weights.version, initial: memory_limits.0, maximum: memory_limits.1, - _reserved: None, code: contract_module.into_wasm_code()?, - original_code_len: original_code.len() as u32, - refcount: 1, code_hash: T::Hashing::hash(&original_code), original_code: Some(original_code), + owner_info: Some(OwnerInfo { + owner, + // this is a helper function for benchmarking which skips deposit collection + deposit: Default::default(), + refcount: 0, + }), }) } } @@ -481,10 +503,14 @@ pub mod benchmarking { #[cfg(test)] mod tests { use super::*; - use crate::{exec::Ext, schedule::Limits}; + use crate::{ + exec::Ext, + schedule::Limits, + tests::{Test, ALICE}, + }; use std::fmt; - impl fmt::Debug for PrefabWasmModule { + impl fmt::Debug for PrefabWasmModule { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "PreparedContract {{ .. }}") } @@ -526,7 +552,7 @@ mod tests { }, .. Default::default() }; - let r = do_preparation::(wasm, &schedule); + let r = do_preparation::(wasm, &schedule, ALICE); assert_matches::assert_matches!(r, $($expected)*); } }; diff --git a/frame/contracts/src/wasm/runtime.rs b/frame/contracts/src/wasm/runtime.rs index 204db09ed3e8..a7341e9e02e5 100644 --- a/frame/contracts/src/wasm/runtime.rs +++ b/frame/contracts/src/wasm/runtime.rs @@ -31,7 +31,7 @@ use pallet_contracts_primitives::{ExecReturnValue, ReturnFlags}; use pwasm_utils::parity_wasm::elements::ValueType; use sp_core::{crypto::UncheckedFrom, Bytes}; use sp_io::hashing::{blake2_128, blake2_256, keccak_256, sha2_256}; -use sp_runtime::traits::Bounded; +use sp_runtime::traits::{Bounded, Zero}; use sp_sandbox::SandboxMemory; use sp_std::prelude::*; @@ -55,15 +55,12 @@ pub enum ReturnCode { CalleeReverted = 2, /// The passed key does not exist in storage. KeyNotFound = 3, - /// Transfer failed because it would have brought the sender's total balance below the - /// subsistence threshold. - BelowSubsistenceThreshold = 4, - /// Transfer failed for other reasons. Most probably reserved or locked balance of the - /// sender prevents the transfer. + /// Deprecated and no longer returned: There is only the minimum balance. + _BelowSubsistenceThreshold = 4, + /// See [`Error::TransferFailed`]. TransferFailed = 5, - /// The newly created contract is below the subsistence threshold after executing - /// its constructor. - NewContractNotFunded = 6, + /// Deprecated and no longer returned: Endowment is no longer required. + _EndowmentTooLow = 6, /// No code could be found at the supplied code hash. CodeNotFound = 7, /// The contract that was called is no contract (a plain account). @@ -151,8 +148,6 @@ pub enum RuntimeCosts { ValueTransferred, /// Weight of calling `seal_minimum_balance`. MinimumBalance, - /// Weight of calling `seal_contract_deposit`. - ContractDeposit, /// Weight of calling `seal_block_number`. BlockNumber, /// Weight of calling `seal_now`. @@ -231,7 +226,6 @@ impl RuntimeCosts { Balance => s.balance, ValueTransferred => s.value_transferred, MinimumBalance => s.minimum_balance, - ContractDeposit => s.contract_deposit, BlockNumber => s.block_number, Now => s.now, WeightToFee => s.weight_to_fee, @@ -611,16 +605,12 @@ where fn err_into_return_code(from: DispatchError) -> Result { use ReturnCode::*; - let below_sub = Error::::BelowSubsistenceThreshold.into(); let transfer_failed = Error::::TransferFailed.into(); - let not_funded = Error::::NewContractNotFunded.into(); let no_code = Error::::CodeNotFound.into(); let not_found = Error::::ContractNotFound.into(); match from { - x if x == below_sub => Ok(BelowSubsistenceThreshold), x if x == transfer_failed => Ok(TransferFailed), - x if x == not_funded => Ok(NewContractNotFunded), x if x == no_code => Ok(CodeNotFound), x if x == not_found => Ok(NotCallable), err => Err(err), @@ -837,7 +827,6 @@ define_env!(Env, , // // # Errors // - // `ReturnCode::BelowSubsistenceThreshold` // `ReturnCode::TransferFailed` [seal0] seal_transfer( ctx, @@ -925,7 +914,6 @@ define_env!(Env, , // // `ReturnCode::CalleeReverted`: Output buffer is returned. // `ReturnCode::CalleeTrapped` - // `ReturnCode::BelowSubsistenceThreshold` // `ReturnCode::TransferFailed` // `ReturnCode::NotCallable` [seal1] seal_call( @@ -1002,9 +990,8 @@ define_env!(Env, , // length to `output_len_ptr`. The copy of the output buffer and address can be skipped by // supplying the sentinel value of `u32::MAX` to `output_ptr` or `address_ptr`. // - // After running the constructor it is verified that the contract account holds at - // least the subsistence threshold. If that is not the case the instantiation fails and - // the contract is not created. + // `value` must be at least the minimum balance. Otherwise the instantiation fails and the + // contract is not created. // // # Parameters // @@ -1033,9 +1020,7 @@ define_env!(Env, , // // `ReturnCode::CalleeReverted`: Output buffer is returned. // `ReturnCode::CalleeTrapped` - // `ReturnCode::BelowSubsistenceThreshold` // `ReturnCode::TransferFailed` - // `ReturnCode::NewContractNotFunded` // `ReturnCode::CodeNotFound` [seal1] seal_instantiate( ctx, @@ -1082,7 +1067,7 @@ define_env!(Env, , ctx.terminate(beneficiary_ptr) }, - // Remove the calling account and transfer remaining balance. + // Remove the calling account and transfer remaining **free** balance. // // This function never returns. Either the termination was successful and the // execution of the destroyed contract is halted. Or it failed during the termination @@ -1215,7 +1200,7 @@ define_env!(Env, , )?) }, - // Stores the balance of the current account into the supplied buffer. + // Stores the **free* balance of the current account into the supplied buffer. // // The value is stored to linear memory at the address pointed to by `out_ptr`. // `out_len_ptr` must point to a u32 value that describes the available space at @@ -1230,7 +1215,7 @@ define_env!(Env, , )?) }, - // Stores the value transferred along with this call or as endowment into the supplied buffer. + // Stores the value transferred along with this call/instantiate into the supplied buffer. // // The value is stored to linear memory at the address pointed to by `out_ptr`. // `out_len_ptr` must point to a u32 value that describes the available space at @@ -1323,38 +1308,20 @@ define_env!(Env, , )?) }, - // Stores the contract deposit into the supplied buffer. - // - // # Deprecation - // - // This is equivalent to calling `seal_contract_deposit` and only exists for backwards - // compatibility. See that function for documentation. - [seal0] seal_tombstone_deposit(ctx, out_ptr: u32, out_len_ptr: u32) => { - ctx.charge_gas(RuntimeCosts::ContractDeposit)?; - Ok(ctx.write_sandbox_output( - out_ptr, out_len_ptr, &ctx.ext.contract_deposit().encode(), false, already_charged - )?) - }, - - // Stores the contract deposit into the supplied buffer. + // Stores the tombstone deposit into the supplied buffer. // // The value is stored to linear memory at the address pointed to by `out_ptr`. // `out_len_ptr` must point to a u32 value that describes the available space at // `out_ptr`. This call overwrites it with the size of the value. If the available // space at `out_ptr` is less than the size of the value a trap is triggered. // - // The data is encoded as T::Balance. - // - // # Note + // # Deprecation // - // The contract deposit is on top of the existential deposit. The sum - // is commonly referred as subsistence threshold in code. No contract initiated - // balance transfer can go below this threshold. - [seal0] seal_contract_deposit(ctx, out_ptr: u32, out_len_ptr: u32) => { - ctx.charge_gas(RuntimeCosts::ContractDeposit)?; - Ok(ctx.write_sandbox_output( - out_ptr, out_len_ptr, &ctx.ext.contract_deposit().encode(), false, already_charged - )?) + // There is no longer a tombstone deposit. This function always returns 0. + [seal0] seal_tombstone_deposit(ctx, out_ptr: u32, out_len_ptr: u32) => { + ctx.charge_gas(RuntimeCosts::Balance)?; + let deposit = >::zero().encode(); + Ok(ctx.write_sandbox_output(out_ptr, out_len_ptr, &deposit, false, already_charged)?) }, // Was used to restore the given destination contract sacrificing the caller. diff --git a/frame/contracts/src/weights.rs b/frame/contracts/src/weights.rs index 4b6c40764ad0..504ee9ebde03 100644 --- a/frame/contracts/src/weights.rs +++ b/frame/contracts/src/weights.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_contracts //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-10-28, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2021-11-19, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 // Executed Command: @@ -35,7 +35,6 @@ // --output=./frame/contracts/src/weights.rs // --template=./.maintain/frame-weight-template.hbs - #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] #![allow(unused_imports)] @@ -50,17 +49,17 @@ pub trait WeightInfo { fn on_initialize_per_queue_item(q: u32, ) -> Weight; fn instrument(c: u32, ) -> Weight; fn code_load(c: u32, ) -> Weight; - fn code_refcount(c: u32, ) -> Weight; fn instantiate_with_code(c: u32, s: u32, ) -> Weight; fn instantiate(s: u32, ) -> Weight; fn call() -> Weight; + fn upload_code(c: u32, ) -> Weight; + fn remove_code() -> Weight; fn seal_caller(r: u32, ) -> Weight; fn seal_address(r: u32, ) -> Weight; fn seal_gas_left(r: u32, ) -> Weight; fn seal_balance(r: u32, ) -> Weight; fn seal_value_transferred(r: u32, ) -> Weight; fn seal_minimum_balance(r: u32, ) -> Weight; - fn seal_tombstone_deposit(r: u32, ) -> Weight; fn seal_block_number(r: u32, ) -> Weight; fn seal_now(r: u32, ) -> Weight; fn seal_weight_to_fee(r: u32, ) -> Weight; @@ -151,761 +150,792 @@ pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize() -> Weight { - (2_987_000 as Weight) + (2_832_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn on_initialize_per_trie_key(k: u32, ) -> Weight { (0 as Weight) - // Standard Error: 2_000 - .saturating_add((2_201_000 as Weight).saturating_mul(k as Weight)) + // Standard Error: 3_000 + .saturating_add((2_197_000 as Weight).saturating_mul(k as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) } // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize_per_queue_item(q: u32, ) -> Weight { - (97_470_000 as Weight) + (92_378_000 as Weight) // Standard Error: 2_000 - .saturating_add((322_000 as Weight).saturating_mul(q as Weight)) + .saturating_add((328_000 as Weight).saturating_mul(q as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Contracts PristineCode (r:1 w:0) // Storage: Contracts CodeStorage (r:0 w:1) fn instrument(c: u32, ) -> Weight { - (28_804_000 as Weight) - // Standard Error: 84_000 - .saturating_add((71_838_000 as Weight).saturating_mul(c as Weight)) + (27_381_000 as Weight) + // Standard Error: 92_000 + .saturating_add((90_220_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Contracts CodeStorage (r:1 w:0) fn code_load(c: u32, ) -> Weight { - (5_658_000 as Weight) + (7_710_000 as Weight) // Standard Error: 0 - .saturating_add((1_425_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((1_457_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) } // Storage: Contracts CodeStorage (r:1 w:1) - fn code_refcount(c: u32, ) -> Weight { - (9_001_000 as Weight) - // Standard Error: 1_000 - .saturating_add((2_281_000 as Weight).saturating_mul(c as Weight)) - .saturating_add(T::DbWeight::get().reads(1 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) - } // Storage: Contracts AccountCounter (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) - // Storage: Contracts CodeStorage (r:1 w:1) // Storage: Contracts PristineCode (r:0 w:1) + // Storage: Contracts OwnerInfoOf (r:0 w:1) fn instantiate_with_code(c: u32, s: u32, ) -> Weight { - (499_349_000 as Weight) - // Standard Error: 199_000 - .saturating_add((174_439_000 as Weight).saturating_mul(c as Weight)) - // Standard Error: 13_000 - .saturating_add((2_096_000 as Weight).saturating_mul(s as Weight)) + (559_294_000 as Weight) + // Standard Error: 171_000 + .saturating_add((206_170_000 as Weight).saturating_mul(c as Weight)) + // Standard Error: 11_000 + .saturating_add((2_107_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) - .saturating_add(T::DbWeight::get().writes(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(6 as Weight)) } // Storage: Contracts CodeStorage (r:1 w:1) // Storage: Contracts AccountCounter (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) + // Storage: Contracts OwnerInfoOf (r:1 w:1) fn instantiate(s: u32, ) -> Weight { - (181_151_000 as Weight) + (236_193_000 as Weight) // Standard Error: 2_000 - .saturating_add((2_025_000 as Weight).saturating_mul(s as Weight)) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) - .saturating_add(T::DbWeight::get().writes(4 as Weight)) + .saturating_add((2_022_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) + .saturating_add(T::DbWeight::get().writes(5 as Weight)) } // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call() -> Weight { - (153_830_000 as Weight) + (189_193_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } + // Storage: Contracts CodeStorage (r:1 w:1) + // Storage: Contracts PristineCode (r:0 w:1) + // Storage: Contracts OwnerInfoOf (r:0 w:1) + fn upload_code(c: u32, ) -> Weight { + (79_753_000 as Weight) + // Standard Error: 98_000 + .saturating_add((90_928_000 as Weight).saturating_mul(c as Weight)) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } + // Storage: Contracts OwnerInfoOf (r:1 w:1) + // Storage: Contracts CodeStorage (r:0 w:1) + // Storage: Contracts PristineCode (r:0 w:1) + fn remove_code() -> Weight { + (40_206_000 as Weight) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_caller(r: u32, ) -> Weight { - (423_222_000 as Weight) - // Standard Error: 169_000 - .saturating_add((114_763_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + (464_937_000 as Weight) + // Standard Error: 182_000 + .saturating_add((112_166_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_address(r: u32, ) -> Weight { - (420_731_000 as Weight) - // Standard Error: 165_000 - .saturating_add((115_213_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + (464_387_000 as Weight) + // Standard Error: 155_000 + .saturating_add((112_307_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas_left(r: u32, ) -> Weight { - (422_407_000 as Weight) - // Standard Error: 176_000 - .saturating_add((113_935_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + (462_005_000 as Weight) + // Standard Error: 185_000 + .saturating_add((111_402_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) - // Storage: System Account (r:1 w:0) fn seal_balance(r: u32, ) -> Weight { - (425_698_000 as Weight) - // Standard Error: 210_000 - .saturating_add((335_171_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(T::DbWeight::get().reads(4 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + (468_139_000 as Weight) + // Standard Error: 192_000 + .saturating_add((317_634_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_value_transferred(r: u32, ) -> Weight { - (410_218_000 as Weight) - // Standard Error: 187_000 - .saturating_add((115_360_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + (447_610_000 as Weight) + // Standard Error: 196_000 + .saturating_add((112_915_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_minimum_balance(r: u32, ) -> Weight { - (402_765_000 as Weight) - // Standard Error: 169_000 - .saturating_add((116_553_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) - } - // Storage: Contracts ContractInfoOf (r:1 w:1) - // Storage: Contracts CodeStorage (r:1 w:0) - // Storage: Timestamp Now (r:1 w:0) - fn seal_tombstone_deposit(r: u32, ) -> Weight { - (404_817_000 as Weight) - // Standard Error: 173_000 - .saturating_add((115_894_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + (450_012_000 as Weight) + // Standard Error: 167_000 + .saturating_add((112_311_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_block_number(r: u32, ) -> Weight { - (405_604_000 as Weight) - // Standard Error: 193_000 - .saturating_add((115_757_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + (453_687_000 as Weight) + // Standard Error: 185_000 + .saturating_add((111_902_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_now(r: u32, ) -> Weight { - (413_577_000 as Weight) - // Standard Error: 166_000 - .saturating_add((115_115_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + (453_283_000 as Weight) + // Standard Error: 162_000 + .saturating_add((112_543_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0) fn seal_weight_to_fee(r: u32, ) -> Weight { - (413_932_000 as Weight) - // Standard Error: 201_000 - .saturating_add((272_742_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(T::DbWeight::get().reads(4 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + (454_171_000 as Weight) + // Standard Error: 205_000 + .saturating_add((267_487_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas(r: u32, ) -> Weight { - (144_109_000 as Weight) - // Standard Error: 96_000 - .saturating_add((52_461_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + (190_254_000 as Weight) + // Standard Error: 116_000 + .saturating_add((51_037_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input(r: u32, ) -> Weight { - (422_584_000 as Weight) - // Standard Error: 158_000 - .saturating_add((98_316_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + (460_590_000 as Weight) + // Standard Error: 173_000 + .saturating_add((99_887_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input_per_kb(n: u32, ) -> Weight { - (549_530_000 as Weight) - // Standard Error: 8_000 - .saturating_add((38_025_000 as Weight).saturating_mul(n as Weight)) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + (616_346_000 as Weight) + // Standard Error: 9_000 + .saturating_add((38_016_000 as Weight).saturating_mul(n as Weight)) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) - fn seal_return(r: u32, ) -> Weight { - (403_711_000 as Weight) - // Standard Error: 114_000 - .saturating_add((2_996_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + fn seal_return(_r: u32, ) -> Weight { + (447_340_000 as Weight) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return_per_kb(n: u32, ) -> Weight { - (408_252_000 as Weight) + (452_105_000 as Weight) // Standard Error: 1_000 - .saturating_add((630_000 as Weight).saturating_mul(n as Weight)) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + .saturating_add((633_000 as Weight).saturating_mul(n as Weight)) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) // Storage: Contracts DeletionQueue (r:1 w:1) - // Storage: System Account (r:2 w:2) + // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_terminate(r: u32, ) -> Weight { - (412_619_000 as Weight) - // Standard Error: 896_000 - .saturating_add((66_155_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(r as Weight))) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + (456_662_000 as Weight) + // Standard Error: 2_550_000 + .saturating_add((71_297_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().reads((4 as Weight).saturating_mul(r as Weight))) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) .saturating_add(T::DbWeight::get().writes((4 as Weight).saturating_mul(r as Weight))) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) // Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) fn seal_random(r: u32, ) -> Weight { - (416_604_000 as Weight) - // Standard Error: 274_000 - .saturating_add((366_304_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(T::DbWeight::get().reads(4 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + (460_302_000 as Weight) + // Standard Error: 223_000 + .saturating_add((351_206_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_deposit_event(r: u32, ) -> Weight { - (417_326_000 as Weight) - // Standard Error: 457_000 - .saturating_add((640_211_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + (456_800_000 as Weight) + // Standard Error: 413_000 + .saturating_add((574_183_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) // Storage: System EventTopics (r:100 w:100) fn seal_deposit_event_per_topic_and_kb(t: u32, n: u32, ) -> Weight { - (1_121_348_000 as Weight) - // Standard Error: 2_483_000 - .saturating_add((463_498_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 489_000 - .saturating_add((167_147_000 as Weight).saturating_mul(n as Weight)) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) + (1_099_926_000 as Weight) + // Standard Error: 2_170_000 + .saturating_add((461_522_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 427_000 + .saturating_add((164_778_000 as Weight).saturating_mul(n as Weight)) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(t as Weight))) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) .saturating_add(T::DbWeight::get().writes((100 as Weight).saturating_mul(t as Weight))) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_debug_message(r: u32, ) -> Weight { - (159_880_000 as Weight) - // Standard Error: 138_000 - .saturating_add((67_837_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + (208_518_000 as Weight) + // Standard Error: 131_000 + .saturating_add((70_862_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage(r: u32, ) -> Weight { - (389_400_000 as Weight) - // Standard Error: 239_000 - .saturating_add((238_933_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + (492_961_000 as Weight) + // Standard Error: 506_000 + .saturating_add((373_157_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) .saturating_add(T::DbWeight::get().writes((100 as Weight).saturating_mul(r as Weight))) } + // Storage: System Account (r:2 w:2) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) - // Storage: unknown [0x7afa01283080ef247df84e0ba38ea5a587d25ce6633a6bfbba02068c14023441] (r:0 w:1) + // Storage: unknown [0x7afa01283080ef247df84e0ba38ea5a587d25ce6633a6bfbba02068c14023441] (r:1 w:1) fn seal_set_storage_per_kb(n: u32, ) -> Weight { - (611_980_000 as Weight) - // Standard Error: 234_000 - .saturating_add((72_047_000 as Weight).saturating_mul(n as Weight)) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + (793_894_000 as Weight) + // Standard Error: 250_000 + .saturating_add((74_081_000 as Weight).saturating_mul(n as Weight)) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) + .saturating_add(T::DbWeight::get().writes(4 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage(r: u32, ) -> Weight { - (436_588_000 as Weight) - // Standard Error: 222_000 - .saturating_add((209_734_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + (214_581_000 as Weight) + // Standard Error: 1_604_000 + .saturating_add((844_938_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) .saturating_add(T::DbWeight::get().writes((100 as Weight).saturating_mul(r as Weight))) } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage(r: u32, ) -> Weight { - (285_689_000 as Weight) - // Standard Error: 742_000 - .saturating_add((496_745_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) + (328_005_000 as Weight) + // Standard Error: 753_000 + .saturating_add((493_893_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) // Storage: unknown [0x7afa01283080ef247df84e0ba38ea5a587d25ce6633a6bfbba02068c14023441] (r:1 w:0) fn seal_get_storage_per_kb(n: u32, ) -> Weight { - (693_967_000 as Weight) - // Standard Error: 226_000 - .saturating_add((111_370_000 as Weight).saturating_mul(n as Weight)) - .saturating_add(T::DbWeight::get().reads(4 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + (736_348_000 as Weight) + // Standard Error: 232_000 + .saturating_add((110_871_000 as Weight).saturating_mul(n as Weight)) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) - // Storage: System Account (r:101 w:101) fn seal_transfer(r: u32, ) -> Weight { - (332_032_000 as Weight) - // Standard Error: 2_537_000 - .saturating_add((4_071_041_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(T::DbWeight::get().reads(4 as Weight)) + (346_206_000 as Weight) + // Standard Error: 1_888_000 + .saturating_add((3_729_835_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) .saturating_add(T::DbWeight::get().writes((100 as Weight).saturating_mul(r as Weight))) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_call(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 10_806_000 - .saturating_add((39_442_275_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(T::DbWeight::get().reads(4 as Weight)) + // Standard Error: 11_456_000 + .saturating_add((39_404_197_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) .saturating_add(T::DbWeight::get().writes((100 as Weight).saturating_mul(r as Weight))) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:101 w:101) // Storage: Contracts CodeStorage (r:2 w:0) // Storage: Timestamp Now (r:1 w:0) - // Storage: System Account (r:101 w:101) - fn seal_call_per_transfer_input_output_kb(t: u32, i: u32, o: u32, ) -> Weight { - (38_600_435_000 as Weight) - // Standard Error: 53_014_000 - .saturating_add((3_392_887_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 18_000 - .saturating_add((63_348_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 20_000 - .saturating_add((101_366_000 as Weight).saturating_mul(o as Weight)) - .saturating_add(T::DbWeight::get().reads(104 as Weight)) - .saturating_add(T::DbWeight::get().reads((101 as Weight).saturating_mul(t as Weight))) - .saturating_add(T::DbWeight::get().writes(101 as Weight)) - .saturating_add(T::DbWeight::get().writes((101 as Weight).saturating_mul(t as Weight))) + fn seal_call_per_transfer_input_output_kb(t: u32, i: u32, _o: u32, ) -> Weight { + (136_101_024_000 as Weight) + // Standard Error: 6_000 + .saturating_add((62_954_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(T::DbWeight::get().reads(105 as Weight)) + .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(t as Weight))) + .saturating_add(T::DbWeight::get().writes(102 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) // Storage: Contracts AccountCounter (r:1 w:1) - // Storage: System Account (r:101 w:101) + // Storage: Contracts OwnerInfoOf (r:100 w:100) fn seal_instantiate(r: u32, ) -> Weight { - (643_999_000 as Weight) - // Standard Error: 37_244_000 - .saturating_add((45_559_839_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) - .saturating_add(T::DbWeight::get().reads((300 as Weight).saturating_mul(r as Weight))) - .saturating_add(T::DbWeight::get().writes(3 as Weight)) - .saturating_add(T::DbWeight::get().writes((300 as Weight).saturating_mul(r as Weight))) + (0 as Weight) + // Standard Error: 47_948_000 + .saturating_add((48_494_963_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) + .saturating_add(T::DbWeight::get().reads((400 as Weight).saturating_mul(r as Weight))) + .saturating_add(T::DbWeight::get().writes(4 as Weight)) + .saturating_add(T::DbWeight::get().writes((400 as Weight).saturating_mul(r as Weight))) } + // Storage: System Account (r:102 w:102) // Storage: Contracts ContractInfoOf (r:101 w:101) // Storage: Contracts CodeStorage (r:2 w:1) // Storage: Timestamp Now (r:1 w:0) // Storage: Contracts AccountCounter (r:1 w:1) - // Storage: System Account (r:101 w:101) + // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_instantiate_per_input_output_salt_kb(i: u32, o: u32, s: u32, ) -> Weight { - (45_415_035_000 as Weight) - // Standard Error: 30_000 - .saturating_add((63_567_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 30_000 - .saturating_add((100_900_000 as Weight).saturating_mul(o as Weight)) - // Standard Error: 30_000 - .saturating_add((201_139_000 as Weight).saturating_mul(s as Weight)) - .saturating_add(T::DbWeight::get().reads(206 as Weight)) - .saturating_add(T::DbWeight::get().writes(204 as Weight)) + (45_566_426_000 as Weight) + // Standard Error: 50_000 + .saturating_add((63_809_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 50_000 + .saturating_add((101_448_000 as Weight).saturating_mul(o as Weight)) + // Standard Error: 50_000 + .saturating_add((201_652_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(208 as Weight)) + .saturating_add(T::DbWeight::get().writes(206 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256(r: u32, ) -> Weight { - (417_335_000 as Weight) - // Standard Error: 174_000 - .saturating_add((126_268_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + (457_229_000 as Weight) + // Standard Error: 197_000 + .saturating_add((124_742_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256_per_kb(n: u32, ) -> Weight { - (700_565_000 as Weight) - // Standard Error: 68_000 - .saturating_add((499_898_000 as Weight).saturating_mul(n as Weight)) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + (586_056_000 as Weight) + // Standard Error: 30_000 + .saturating_add((505_871_000 as Weight).saturating_mul(n as Weight)) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256(r: u32, ) -> Weight { - (416_014_000 as Weight) - // Standard Error: 168_000 - .saturating_add((134_320_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + (458_528_000 as Weight) + // Standard Error: 154_000 + .saturating_add((137_710_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256_per_kb(n: u32, ) -> Weight { - (534_466_000 as Weight) + (573_132_000 as Weight) // Standard Error: 19_000 - .saturating_add((346_588_000 as Weight).saturating_mul(n as Weight)) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + .saturating_add((363_983_000 as Weight).saturating_mul(n as Weight)) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256(r: u32, ) -> Weight { - (414_278_000 as Weight) - // Standard Error: 164_000 - .saturating_add((106_210_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + (456_881_000 as Weight) + // Standard Error: 187_000 + .saturating_add((106_987_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256_per_kb(n: u32, ) -> Weight { - (569_659_000 as Weight) - // Standard Error: 16_000 - .saturating_add((163_989_000 as Weight).saturating_mul(n as Weight)) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + (587_192_000 as Weight) + // Standard Error: 17_000 + .saturating_add((164_114_000 as Weight).saturating_mul(n as Weight)) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128(r: u32, ) -> Weight { - (421_251_000 as Weight) - // Standard Error: 166_000 - .saturating_add((104_678_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + (457_938_000 as Weight) + // Standard Error: 184_000 + .saturating_add((105_658_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128_per_kb(n: u32, ) -> Weight { - (568_490_000 as Weight) - // Standard Error: 21_000 - .saturating_add((163_999_000 as Weight).saturating_mul(n as Weight)) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + (567_129_000 as Weight) + // Standard Error: 16_000 + .saturating_add((164_146_000 as Weight).saturating_mul(n as Weight)) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_ecdsa_recover(r: u32, ) -> Weight { - (361_122_000 as Weight) - // Standard Error: 1_172_000 - .saturating_add((15_591_590_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + (426_602_000 as Weight) + // Standard Error: 1_393_000 + .saturating_add((15_587_531_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } fn instr_i64const(r: u32, ) -> Weight { - (46_003_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_185_000 as Weight).saturating_mul(r as Weight)) + (39_689_000 as Weight) + // Standard Error: 14_000 + .saturating_add((1_361_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64load(r: u32, ) -> Weight { - (42_908_000 as Weight) - // Standard Error: 13_000 - .saturating_add((2_570_000 as Weight).saturating_mul(r as Weight)) + (45_362_000 as Weight) + // Standard Error: 10_000 + .saturating_add((2_665_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64store(r: u32, ) -> Weight { - (42_739_000 as Weight) - // Standard Error: 13_000 - .saturating_add((2_791_000 as Weight).saturating_mul(r as Weight)) + (45_514_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_696_000 as Weight).saturating_mul(r as Weight)) } fn instr_select(r: u32, ) -> Weight { - (47_543_000 as Weight) - // Standard Error: 8_000 - .saturating_add((2_834_000 as Weight).saturating_mul(r as Weight)) + (45_931_000 as Weight) + // Standard Error: 12_000 + .saturating_add((2_919_000 as Weight).saturating_mul(r as Weight)) } fn instr_if(r: u32, ) -> Weight { - (50_540_000 as Weight) - // Standard Error: 13_000 - .saturating_add((2_663_000 as Weight).saturating_mul(r as Weight)) + (46_362_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_942_000 as Weight).saturating_mul(r as Weight)) } fn instr_br(r: u32, ) -> Weight { - (47_732_000 as Weight) - // Standard Error: 8_000 - .saturating_add((1_771_000 as Weight).saturating_mul(r as Weight)) + (44_648_000 as Weight) + // Standard Error: 15_000 + .saturating_add((1_856_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_if(r: u32, ) -> Weight { - (49_005_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_072_000 as Weight).saturating_mul(r as Weight)) + (45_989_000 as Weight) + // Standard Error: 10_000 + .saturating_add((2_418_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table(r: u32, ) -> Weight { - (45_975_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_492_000 as Weight).saturating_mul(r as Weight)) + (48_883_000 as Weight) + // Standard Error: 18_000 + .saturating_add((2_471_000 as Weight).saturating_mul(r as Weight)) } - fn instr_br_table_per_entry(_e: u32, ) -> Weight { - (55_461_000 as Weight) + fn instr_br_table_per_entry(e: u32, ) -> Weight { + (48_685_000 as Weight) + // Standard Error: 2_000 + .saturating_add((39_000 as Weight).saturating_mul(e as Weight)) } fn instr_call(r: u32, ) -> Weight { - (41_932_000 as Weight) - // Standard Error: 29_000 - .saturating_add((19_800_000 as Weight).saturating_mul(r as Weight)) + (50_428_000 as Weight) + // Standard Error: 24_000 + .saturating_add((20_121_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect(r: u32, ) -> Weight { - (56_550_000 as Weight) - // Standard Error: 34_000 - .saturating_add((28_414_000 as Weight).saturating_mul(r as Weight)) + (54_899_000 as Weight) + // Standard Error: 32_000 + .saturating_add((29_588_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect_per_param(p: u32, ) -> Weight { - (93_172_000 as Weight) - // Standard Error: 6_000 - .saturating_add((1_018_000 as Weight).saturating_mul(p as Weight)) + (92_176_000 as Weight) + // Standard Error: 5_000 + .saturating_add((989_000 as Weight).saturating_mul(p as Weight)) } fn instr_local_get(r: u32, ) -> Weight { - (54_603_000 as Weight) - // Standard Error: 14_000 - .saturating_add((764_000 as Weight).saturating_mul(r as Weight)) + (48_130_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_194_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_set(r: u32, ) -> Weight { - (54_763_000 as Weight) - // Standard Error: 14_000 - .saturating_add((878_000 as Weight).saturating_mul(r as Weight)) + (47_550_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_244_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_tee(r: u32, ) -> Weight { - (56_137_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_194_000 as Weight).saturating_mul(r as Weight)) + (48_806_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_757_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_get(r: u32, ) -> Weight { - (69_513_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_125_000 as Weight).saturating_mul(r as Weight)) + (62_369_000 as Weight) + // Standard Error: 9_000 + .saturating_add((1_779_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_set(r: u32, ) -> Weight { - (69_120_000 as Weight) - // Standard Error: 12_000 - .saturating_add((1_215_000 as Weight).saturating_mul(r as Weight)) + (61_063_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_751_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_current(r: u32, ) -> Weight { - (46_021_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_103_000 as Weight).saturating_mul(r as Weight)) + (39_781_000 as Weight) + // Standard Error: 14_000 + .saturating_add((1_370_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_grow(r: u32, ) -> Weight { - (52_245_000 as Weight) - // Standard Error: 4_119_000 - .saturating_add((619_498_000 as Weight).saturating_mul(r as Weight)) + (50_983_000 as Weight) + // Standard Error: 4_238_000 + .saturating_add((618_956_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64clz(r: u32, ) -> Weight { - (47_314_000 as Weight) - // Standard Error: 9_000 - .saturating_add((1_720_000 as Weight).saturating_mul(r as Weight)) + (42_490_000 as Weight) + // Standard Error: 13_000 + .saturating_add((1_937_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ctz(r: u32, ) -> Weight { - (47_855_000 as Weight) - // Standard Error: 9_000 - .saturating_add((1_701_000 as Weight).saturating_mul(r as Weight)) + (42_296_000 as Weight) + // Standard Error: 13_000 + .saturating_add((1_943_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64popcnt(r: u32, ) -> Weight { - (47_704_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_708_000 as Weight).saturating_mul(r as Weight)) + (42_263_000 as Weight) + // Standard Error: 13_000 + .saturating_add((1_944_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eqz(r: u32, ) -> Weight { - (47_656_000 as Weight) - // Standard Error: 9_000 - .saturating_add((1_705_000 as Weight).saturating_mul(r as Weight)) + (42_087_000 as Weight) + // Standard Error: 13_000 + .saturating_add((1_952_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendsi32(r: u32, ) -> Weight { - (55_202_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_229_000 as Weight).saturating_mul(r as Weight)) + (48_024_000 as Weight) + // Standard Error: 9_000 + .saturating_add((1_783_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendui32(r: u32, ) -> Weight { - (55_193_000 as Weight) - // Standard Error: 9_000 - .saturating_add((1_223_000 as Weight).saturating_mul(r as Weight)) + (48_056_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_780_000 as Weight).saturating_mul(r as Weight)) } fn instr_i32wrapi64(r: u32, ) -> Weight { - (48_125_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_704_000 as Weight).saturating_mul(r as Weight)) + (42_352_000 as Weight) + // Standard Error: 13_000 + .saturating_add((1_928_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eq(r: u32, ) -> Weight { - (49_162_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_241_000 as Weight).saturating_mul(r as Weight)) + (45_439_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_382_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ne(r: u32, ) -> Weight { - (48_635_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_262_000 as Weight).saturating_mul(r as Weight)) + (45_232_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_393_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64lts(r: u32, ) -> Weight { - (48_550_000 as Weight) - // Standard Error: 9_000 - .saturating_add((2_267_000 as Weight).saturating_mul(r as Weight)) + (45_351_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_386_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ltu(r: u32, ) -> Weight { - (49_135_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_219_000 as Weight).saturating_mul(r as Weight)) + (45_448_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_385_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gts(r: u32, ) -> Weight { - (49_638_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_206_000 as Weight).saturating_mul(r as Weight)) + (45_275_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_386_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gtu(r: u32, ) -> Weight { - (49_889_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_201_000 as Weight).saturating_mul(r as Weight)) + (45_180_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_396_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64les(r: u32, ) -> Weight { - (49_763_000 as Weight) - // Standard Error: 9_000 - .saturating_add((2_210_000 as Weight).saturating_mul(r as Weight)) + (45_396_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_400_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64leu(r: u32, ) -> Weight { - (49_607_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_207_000 as Weight).saturating_mul(r as Weight)) + (45_597_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_392_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ges(r: u32, ) -> Weight { - (49_664_000 as Weight) - // Standard Error: 9_000 - .saturating_add((2_213_000 as Weight).saturating_mul(r as Weight)) + (45_137_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_400_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64geu(r: u32, ) -> Weight { - (49_718_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_206_000 as Weight).saturating_mul(r as Weight)) + (45_091_000 as Weight) + // Standard Error: 10_000 + .saturating_add((2_401_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64add(r: u32, ) -> Weight { - (49_513_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_208_000 as Weight).saturating_mul(r as Weight)) + (45_547_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_380_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64sub(r: u32, ) -> Weight { - (49_837_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_201_000 as Weight).saturating_mul(r as Weight)) + (45_435_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_383_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64mul(r: u32, ) -> Weight { - (49_684_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_210_000 as Weight).saturating_mul(r as Weight)) + (45_244_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_389_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divs(r: u32, ) -> Weight { - (48_749_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_872_000 as Weight).saturating_mul(r as Weight)) + (45_253_000 as Weight) + // Standard Error: 11_000 + .saturating_add((3_046_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divu(r: u32, ) -> Weight { - (49_134_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_630_000 as Weight).saturating_mul(r as Weight)) + (45_339_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_711_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rems(r: u32, ) -> Weight { - (48_981_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_861_000 as Weight).saturating_mul(r as Weight)) + (45_312_000 as Weight) + // Standard Error: 11_000 + .saturating_add((3_020_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64remu(r: u32, ) -> Weight { - (49_195_000 as Weight) - // Standard Error: 8_000 - .saturating_add((2_593_000 as Weight).saturating_mul(r as Weight)) + (45_397_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_739_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64and(r: u32, ) -> Weight { - (49_304_000 as Weight) - // Standard Error: 8_000 - .saturating_add((2_238_000 as Weight).saturating_mul(r as Weight)) + (45_282_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_387_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64or(r: u32, ) -> Weight { - (48_636_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_259_000 as Weight).saturating_mul(r as Weight)) + (45_508_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_390_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64xor(r: u32, ) -> Weight { - (48_761_000 as Weight) - // Standard Error: 8_000 - .saturating_add((2_262_000 as Weight).saturating_mul(r as Weight)) + (45_089_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_397_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shl(r: u32, ) -> Weight { - (48_492_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_263_000 as Weight).saturating_mul(r as Weight)) + (45_878_000 as Weight) + // Standard Error: 13_000 + .saturating_add((2_395_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shrs(r: u32, ) -> Weight { - (48_736_000 as Weight) - // Standard Error: 8_000 - .saturating_add((2_256_000 as Weight).saturating_mul(r as Weight)) + (45_459_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_401_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shru(r: u32, ) -> Weight { - (48_675_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_256_000 as Weight).saturating_mul(r as Weight)) + (45_663_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_398_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotl(r: u32, ) -> Weight { - (48_703_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_257_000 as Weight).saturating_mul(r as Weight)) + (45_739_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_393_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotr(r: u32, ) -> Weight { - (48_758_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_259_000 as Weight).saturating_mul(r as Weight)) + (45_290_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_392_000 as Weight).saturating_mul(r as Weight)) } } @@ -913,760 +943,791 @@ impl WeightInfo for SubstrateWeight { impl WeightInfo for () { // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize() -> Weight { - (2_987_000 as Weight) + (2_832_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn on_initialize_per_trie_key(k: u32, ) -> Weight { (0 as Weight) - // Standard Error: 2_000 - .saturating_add((2_201_000 as Weight).saturating_mul(k as Weight)) + // Standard Error: 3_000 + .saturating_add((2_197_000 as Weight).saturating_mul(k as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) } // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize_per_queue_item(q: u32, ) -> Weight { - (97_470_000 as Weight) + (92_378_000 as Weight) // Standard Error: 2_000 - .saturating_add((322_000 as Weight).saturating_mul(q as Weight)) + .saturating_add((328_000 as Weight).saturating_mul(q as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Contracts PristineCode (r:1 w:0) // Storage: Contracts CodeStorage (r:0 w:1) fn instrument(c: u32, ) -> Weight { - (28_804_000 as Weight) - // Standard Error: 84_000 - .saturating_add((71_838_000 as Weight).saturating_mul(c as Weight)) + (27_381_000 as Weight) + // Standard Error: 92_000 + .saturating_add((90_220_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Contracts CodeStorage (r:1 w:0) fn code_load(c: u32, ) -> Weight { - (5_658_000 as Weight) + (7_710_000 as Weight) // Standard Error: 0 - .saturating_add((1_425_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((1_457_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) } // Storage: Contracts CodeStorage (r:1 w:1) - fn code_refcount(c: u32, ) -> Weight { - (9_001_000 as Weight) - // Standard Error: 1_000 - .saturating_add((2_281_000 as Weight).saturating_mul(c as Weight)) - .saturating_add(RocksDbWeight::get().reads(1 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) - } // Storage: Contracts AccountCounter (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) - // Storage: Contracts CodeStorage (r:1 w:1) // Storage: Contracts PristineCode (r:0 w:1) + // Storage: Contracts OwnerInfoOf (r:0 w:1) fn instantiate_with_code(c: u32, s: u32, ) -> Weight { - (499_349_000 as Weight) - // Standard Error: 199_000 - .saturating_add((174_439_000 as Weight).saturating_mul(c as Weight)) - // Standard Error: 13_000 - .saturating_add((2_096_000 as Weight).saturating_mul(s as Weight)) + (559_294_000 as Weight) + // Standard Error: 171_000 + .saturating_add((206_170_000 as Weight).saturating_mul(c as Weight)) + // Standard Error: 11_000 + .saturating_add((2_107_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) - .saturating_add(RocksDbWeight::get().writes(5 as Weight)) + .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } // Storage: Contracts CodeStorage (r:1 w:1) // Storage: Contracts AccountCounter (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) + // Storage: Contracts OwnerInfoOf (r:1 w:1) fn instantiate(s: u32, ) -> Weight { - (181_151_000 as Weight) + (236_193_000 as Weight) // Standard Error: 2_000 - .saturating_add((2_025_000 as Weight).saturating_mul(s as Weight)) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) - .saturating_add(RocksDbWeight::get().writes(4 as Weight)) + .saturating_add((2_022_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(RocksDbWeight::get().reads(6 as Weight)) + .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call() -> Weight { - (153_830_000 as Weight) + (189_193_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } + // Storage: Contracts CodeStorage (r:1 w:1) + // Storage: Contracts PristineCode (r:0 w:1) + // Storage: Contracts OwnerInfoOf (r:0 w:1) + fn upload_code(c: u32, ) -> Weight { + (79_753_000 as Weight) + // Standard Error: 98_000 + .saturating_add((90_928_000 as Weight).saturating_mul(c as Weight)) + .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + } + // Storage: Contracts OwnerInfoOf (r:1 w:1) + // Storage: Contracts CodeStorage (r:0 w:1) + // Storage: Contracts PristineCode (r:0 w:1) + fn remove_code() -> Weight { + (40_206_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_caller(r: u32, ) -> Weight { - (423_222_000 as Weight) - // Standard Error: 169_000 - .saturating_add((114_763_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + (464_937_000 as Weight) + // Standard Error: 182_000 + .saturating_add((112_166_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_address(r: u32, ) -> Weight { - (420_731_000 as Weight) - // Standard Error: 165_000 - .saturating_add((115_213_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + (464_387_000 as Weight) + // Standard Error: 155_000 + .saturating_add((112_307_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas_left(r: u32, ) -> Weight { - (422_407_000 as Weight) - // Standard Error: 176_000 - .saturating_add((113_935_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + (462_005_000 as Weight) + // Standard Error: 185_000 + .saturating_add((111_402_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) - // Storage: System Account (r:1 w:0) fn seal_balance(r: u32, ) -> Weight { - (425_698_000 as Weight) - // Standard Error: 210_000 - .saturating_add((335_171_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + (468_139_000 as Weight) + // Standard Error: 192_000 + .saturating_add((317_634_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_value_transferred(r: u32, ) -> Weight { - (410_218_000 as Weight) - // Standard Error: 187_000 - .saturating_add((115_360_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + (447_610_000 as Weight) + // Standard Error: 196_000 + .saturating_add((112_915_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_minimum_balance(r: u32, ) -> Weight { - (402_765_000 as Weight) - // Standard Error: 169_000 - .saturating_add((116_553_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) - } - // Storage: Contracts ContractInfoOf (r:1 w:1) - // Storage: Contracts CodeStorage (r:1 w:0) - // Storage: Timestamp Now (r:1 w:0) - fn seal_tombstone_deposit(r: u32, ) -> Weight { - (404_817_000 as Weight) - // Standard Error: 173_000 - .saturating_add((115_894_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + (450_012_000 as Weight) + // Standard Error: 167_000 + .saturating_add((112_311_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_block_number(r: u32, ) -> Weight { - (405_604_000 as Weight) - // Standard Error: 193_000 - .saturating_add((115_757_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + (453_687_000 as Weight) + // Standard Error: 185_000 + .saturating_add((111_902_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_now(r: u32, ) -> Weight { - (413_577_000 as Weight) - // Standard Error: 166_000 - .saturating_add((115_115_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + (453_283_000 as Weight) + // Standard Error: 162_000 + .saturating_add((112_543_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0) fn seal_weight_to_fee(r: u32, ) -> Weight { - (413_932_000 as Weight) - // Standard Error: 201_000 - .saturating_add((272_742_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + (454_171_000 as Weight) + // Standard Error: 205_000 + .saturating_add((267_487_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas(r: u32, ) -> Weight { - (144_109_000 as Weight) - // Standard Error: 96_000 - .saturating_add((52_461_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + (190_254_000 as Weight) + // Standard Error: 116_000 + .saturating_add((51_037_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input(r: u32, ) -> Weight { - (422_584_000 as Weight) - // Standard Error: 158_000 - .saturating_add((98_316_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + (460_590_000 as Weight) + // Standard Error: 173_000 + .saturating_add((99_887_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input_per_kb(n: u32, ) -> Weight { - (549_530_000 as Weight) - // Standard Error: 8_000 - .saturating_add((38_025_000 as Weight).saturating_mul(n as Weight)) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + (616_346_000 as Weight) + // Standard Error: 9_000 + .saturating_add((38_016_000 as Weight).saturating_mul(n as Weight)) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) - fn seal_return(r: u32, ) -> Weight { - (403_711_000 as Weight) - // Standard Error: 114_000 - .saturating_add((2_996_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + fn seal_return(_r: u32, ) -> Weight { + (447_340_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return_per_kb(n: u32, ) -> Weight { - (408_252_000 as Weight) + (452_105_000 as Weight) // Standard Error: 1_000 - .saturating_add((630_000 as Weight).saturating_mul(n as Weight)) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + .saturating_add((633_000 as Weight).saturating_mul(n as Weight)) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) // Storage: Contracts DeletionQueue (r:1 w:1) - // Storage: System Account (r:2 w:2) + // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_terminate(r: u32, ) -> Weight { - (412_619_000 as Weight) - // Standard Error: 896_000 - .saturating_add((66_155_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(r as Weight))) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + (456_662_000 as Weight) + // Standard Error: 2_550_000 + .saturating_add((71_297_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().reads((4 as Weight).saturating_mul(r as Weight))) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) .saturating_add(RocksDbWeight::get().writes((4 as Weight).saturating_mul(r as Weight))) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) // Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) fn seal_random(r: u32, ) -> Weight { - (416_604_000 as Weight) - // Standard Error: 274_000 - .saturating_add((366_304_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + (460_302_000 as Weight) + // Standard Error: 223_000 + .saturating_add((351_206_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_deposit_event(r: u32, ) -> Weight { - (417_326_000 as Weight) - // Standard Error: 457_000 - .saturating_add((640_211_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + (456_800_000 as Weight) + // Standard Error: 413_000 + .saturating_add((574_183_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) // Storage: System EventTopics (r:100 w:100) fn seal_deposit_event_per_topic_and_kb(t: u32, n: u32, ) -> Weight { - (1_121_348_000 as Weight) - // Standard Error: 2_483_000 - .saturating_add((463_498_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 489_000 - .saturating_add((167_147_000 as Weight).saturating_mul(n as Weight)) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + (1_099_926_000 as Weight) + // Standard Error: 2_170_000 + .saturating_add((461_522_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 427_000 + .saturating_add((164_778_000 as Weight).saturating_mul(n as Weight)) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(t as Weight))) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) .saturating_add(RocksDbWeight::get().writes((100 as Weight).saturating_mul(t as Weight))) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_debug_message(r: u32, ) -> Weight { - (159_880_000 as Weight) - // Standard Error: 138_000 - .saturating_add((67_837_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + (208_518_000 as Weight) + // Standard Error: 131_000 + .saturating_add((70_862_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage(r: u32, ) -> Weight { - (389_400_000 as Weight) - // Standard Error: 239_000 - .saturating_add((238_933_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + (492_961_000 as Weight) + // Standard Error: 506_000 + .saturating_add((373_157_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) .saturating_add(RocksDbWeight::get().writes((100 as Weight).saturating_mul(r as Weight))) } + // Storage: System Account (r:2 w:2) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) - // Storage: unknown [0x7afa01283080ef247df84e0ba38ea5a587d25ce6633a6bfbba02068c14023441] (r:0 w:1) + // Storage: unknown [0x7afa01283080ef247df84e0ba38ea5a587d25ce6633a6bfbba02068c14023441] (r:1 w:1) fn seal_set_storage_per_kb(n: u32, ) -> Weight { - (611_980_000 as Weight) - // Standard Error: 234_000 - .saturating_add((72_047_000 as Weight).saturating_mul(n as Weight)) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + (793_894_000 as Weight) + // Standard Error: 250_000 + .saturating_add((74_081_000 as Weight).saturating_mul(n as Weight)) + .saturating_add(RocksDbWeight::get().reads(6 as Weight)) + .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage(r: u32, ) -> Weight { - (436_588_000 as Weight) - // Standard Error: 222_000 - .saturating_add((209_734_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + (214_581_000 as Weight) + // Standard Error: 1_604_000 + .saturating_add((844_938_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) .saturating_add(RocksDbWeight::get().writes((100 as Weight).saturating_mul(r as Weight))) } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage(r: u32, ) -> Weight { - (285_689_000 as Weight) - // Standard Error: 742_000 - .saturating_add((496_745_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + (328_005_000 as Weight) + // Standard Error: 753_000 + .saturating_add((493_893_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) // Storage: unknown [0x7afa01283080ef247df84e0ba38ea5a587d25ce6633a6bfbba02068c14023441] (r:1 w:0) fn seal_get_storage_per_kb(n: u32, ) -> Weight { - (693_967_000 as Weight) - // Standard Error: 226_000 - .saturating_add((111_370_000 as Weight).saturating_mul(n as Weight)) - .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + (736_348_000 as Weight) + // Standard Error: 232_000 + .saturating_add((110_871_000 as Weight).saturating_mul(n as Weight)) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) - // Storage: System Account (r:101 w:101) fn seal_transfer(r: u32, ) -> Weight { - (332_032_000 as Weight) - // Standard Error: 2_537_000 - .saturating_add((4_071_041_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + (346_206_000 as Weight) + // Standard Error: 1_888_000 + .saturating_add((3_729_835_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) .saturating_add(RocksDbWeight::get().writes((100 as Weight).saturating_mul(r as Weight))) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_call(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 10_806_000 - .saturating_add((39_442_275_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + // Standard Error: 11_456_000 + .saturating_add((39_404_197_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) .saturating_add(RocksDbWeight::get().writes((100 as Weight).saturating_mul(r as Weight))) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:101 w:101) // Storage: Contracts CodeStorage (r:2 w:0) // Storage: Timestamp Now (r:1 w:0) - // Storage: System Account (r:101 w:101) - fn seal_call_per_transfer_input_output_kb(t: u32, i: u32, o: u32, ) -> Weight { - (38_600_435_000 as Weight) - // Standard Error: 53_014_000 - .saturating_add((3_392_887_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 18_000 - .saturating_add((63_348_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 20_000 - .saturating_add((101_366_000 as Weight).saturating_mul(o as Weight)) - .saturating_add(RocksDbWeight::get().reads(104 as Weight)) - .saturating_add(RocksDbWeight::get().reads((101 as Weight).saturating_mul(t as Weight))) - .saturating_add(RocksDbWeight::get().writes(101 as Weight)) - .saturating_add(RocksDbWeight::get().writes((101 as Weight).saturating_mul(t as Weight))) + fn seal_call_per_transfer_input_output_kb(t: u32, i: u32, _o: u32, ) -> Weight { + (136_101_024_000 as Weight) + // Standard Error: 6_000 + .saturating_add((62_954_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(RocksDbWeight::get().reads(105 as Weight)) + .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(t as Weight))) + .saturating_add(RocksDbWeight::get().writes(102 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) // Storage: Contracts AccountCounter (r:1 w:1) - // Storage: System Account (r:101 w:101) + // Storage: Contracts OwnerInfoOf (r:100 w:100) fn seal_instantiate(r: u32, ) -> Weight { - (643_999_000 as Weight) - // Standard Error: 37_244_000 - .saturating_add((45_559_839_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) - .saturating_add(RocksDbWeight::get().reads((300 as Weight).saturating_mul(r as Weight))) - .saturating_add(RocksDbWeight::get().writes(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes((300 as Weight).saturating_mul(r as Weight))) + (0 as Weight) + // Standard Error: 47_948_000 + .saturating_add((48_494_963_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(RocksDbWeight::get().reads(6 as Weight)) + .saturating_add(RocksDbWeight::get().reads((400 as Weight).saturating_mul(r as Weight))) + .saturating_add(RocksDbWeight::get().writes(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes((400 as Weight).saturating_mul(r as Weight))) } + // Storage: System Account (r:102 w:102) // Storage: Contracts ContractInfoOf (r:101 w:101) // Storage: Contracts CodeStorage (r:2 w:1) // Storage: Timestamp Now (r:1 w:0) // Storage: Contracts AccountCounter (r:1 w:1) - // Storage: System Account (r:101 w:101) + // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_instantiate_per_input_output_salt_kb(i: u32, o: u32, s: u32, ) -> Weight { - (45_415_035_000 as Weight) - // Standard Error: 30_000 - .saturating_add((63_567_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 30_000 - .saturating_add((100_900_000 as Weight).saturating_mul(o as Weight)) - // Standard Error: 30_000 - .saturating_add((201_139_000 as Weight).saturating_mul(s as Weight)) - .saturating_add(RocksDbWeight::get().reads(206 as Weight)) - .saturating_add(RocksDbWeight::get().writes(204 as Weight)) + (45_566_426_000 as Weight) + // Standard Error: 50_000 + .saturating_add((63_809_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 50_000 + .saturating_add((101_448_000 as Weight).saturating_mul(o as Weight)) + // Standard Error: 50_000 + .saturating_add((201_652_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(RocksDbWeight::get().reads(208 as Weight)) + .saturating_add(RocksDbWeight::get().writes(206 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256(r: u32, ) -> Weight { - (417_335_000 as Weight) - // Standard Error: 174_000 - .saturating_add((126_268_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + (457_229_000 as Weight) + // Standard Error: 197_000 + .saturating_add((124_742_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256_per_kb(n: u32, ) -> Weight { - (700_565_000 as Weight) - // Standard Error: 68_000 - .saturating_add((499_898_000 as Weight).saturating_mul(n as Weight)) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + (586_056_000 as Weight) + // Standard Error: 30_000 + .saturating_add((505_871_000 as Weight).saturating_mul(n as Weight)) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256(r: u32, ) -> Weight { - (416_014_000 as Weight) - // Standard Error: 168_000 - .saturating_add((134_320_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + (458_528_000 as Weight) + // Standard Error: 154_000 + .saturating_add((137_710_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256_per_kb(n: u32, ) -> Weight { - (534_466_000 as Weight) + (573_132_000 as Weight) // Standard Error: 19_000 - .saturating_add((346_588_000 as Weight).saturating_mul(n as Weight)) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + .saturating_add((363_983_000 as Weight).saturating_mul(n as Weight)) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256(r: u32, ) -> Weight { - (414_278_000 as Weight) - // Standard Error: 164_000 - .saturating_add((106_210_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + (456_881_000 as Weight) + // Standard Error: 187_000 + .saturating_add((106_987_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256_per_kb(n: u32, ) -> Weight { - (569_659_000 as Weight) - // Standard Error: 16_000 - .saturating_add((163_989_000 as Weight).saturating_mul(n as Weight)) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + (587_192_000 as Weight) + // Standard Error: 17_000 + .saturating_add((164_114_000 as Weight).saturating_mul(n as Weight)) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128(r: u32, ) -> Weight { - (421_251_000 as Weight) - // Standard Error: 166_000 - .saturating_add((104_678_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + (457_938_000 as Weight) + // Standard Error: 184_000 + .saturating_add((105_658_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128_per_kb(n: u32, ) -> Weight { - (568_490_000 as Weight) - // Standard Error: 21_000 - .saturating_add((163_999_000 as Weight).saturating_mul(n as Weight)) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + (567_129_000 as Weight) + // Standard Error: 16_000 + .saturating_add((164_146_000 as Weight).saturating_mul(n as Weight)) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } + // Storage: System Account (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_ecdsa_recover(r: u32, ) -> Weight { - (361_122_000 as Weight) - // Standard Error: 1_172_000 - .saturating_add((15_591_590_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + (426_602_000 as Weight) + // Standard Error: 1_393_000 + .saturating_add((15_587_531_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } fn instr_i64const(r: u32, ) -> Weight { - (46_003_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_185_000 as Weight).saturating_mul(r as Weight)) + (39_689_000 as Weight) + // Standard Error: 14_000 + .saturating_add((1_361_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64load(r: u32, ) -> Weight { - (42_908_000 as Weight) - // Standard Error: 13_000 - .saturating_add((2_570_000 as Weight).saturating_mul(r as Weight)) + (45_362_000 as Weight) + // Standard Error: 10_000 + .saturating_add((2_665_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64store(r: u32, ) -> Weight { - (42_739_000 as Weight) - // Standard Error: 13_000 - .saturating_add((2_791_000 as Weight).saturating_mul(r as Weight)) + (45_514_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_696_000 as Weight).saturating_mul(r as Weight)) } fn instr_select(r: u32, ) -> Weight { - (47_543_000 as Weight) - // Standard Error: 8_000 - .saturating_add((2_834_000 as Weight).saturating_mul(r as Weight)) + (45_931_000 as Weight) + // Standard Error: 12_000 + .saturating_add((2_919_000 as Weight).saturating_mul(r as Weight)) } fn instr_if(r: u32, ) -> Weight { - (50_540_000 as Weight) - // Standard Error: 13_000 - .saturating_add((2_663_000 as Weight).saturating_mul(r as Weight)) + (46_362_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_942_000 as Weight).saturating_mul(r as Weight)) } fn instr_br(r: u32, ) -> Weight { - (47_732_000 as Weight) - // Standard Error: 8_000 - .saturating_add((1_771_000 as Weight).saturating_mul(r as Weight)) + (44_648_000 as Weight) + // Standard Error: 15_000 + .saturating_add((1_856_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_if(r: u32, ) -> Weight { - (49_005_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_072_000 as Weight).saturating_mul(r as Weight)) + (45_989_000 as Weight) + // Standard Error: 10_000 + .saturating_add((2_418_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table(r: u32, ) -> Weight { - (45_975_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_492_000 as Weight).saturating_mul(r as Weight)) + (48_883_000 as Weight) + // Standard Error: 18_000 + .saturating_add((2_471_000 as Weight).saturating_mul(r as Weight)) } - fn instr_br_table_per_entry(_e: u32, ) -> Weight { - (55_461_000 as Weight) + fn instr_br_table_per_entry(e: u32, ) -> Weight { + (48_685_000 as Weight) + // Standard Error: 2_000 + .saturating_add((39_000 as Weight).saturating_mul(e as Weight)) } fn instr_call(r: u32, ) -> Weight { - (41_932_000 as Weight) - // Standard Error: 29_000 - .saturating_add((19_800_000 as Weight).saturating_mul(r as Weight)) + (50_428_000 as Weight) + // Standard Error: 24_000 + .saturating_add((20_121_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect(r: u32, ) -> Weight { - (56_550_000 as Weight) - // Standard Error: 34_000 - .saturating_add((28_414_000 as Weight).saturating_mul(r as Weight)) + (54_899_000 as Weight) + // Standard Error: 32_000 + .saturating_add((29_588_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect_per_param(p: u32, ) -> Weight { - (93_172_000 as Weight) - // Standard Error: 6_000 - .saturating_add((1_018_000 as Weight).saturating_mul(p as Weight)) + (92_176_000 as Weight) + // Standard Error: 5_000 + .saturating_add((989_000 as Weight).saturating_mul(p as Weight)) } fn instr_local_get(r: u32, ) -> Weight { - (54_603_000 as Weight) - // Standard Error: 14_000 - .saturating_add((764_000 as Weight).saturating_mul(r as Weight)) + (48_130_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_194_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_set(r: u32, ) -> Weight { - (54_763_000 as Weight) - // Standard Error: 14_000 - .saturating_add((878_000 as Weight).saturating_mul(r as Weight)) + (47_550_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_244_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_tee(r: u32, ) -> Weight { - (56_137_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_194_000 as Weight).saturating_mul(r as Weight)) + (48_806_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_757_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_get(r: u32, ) -> Weight { - (69_513_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_125_000 as Weight).saturating_mul(r as Weight)) + (62_369_000 as Weight) + // Standard Error: 9_000 + .saturating_add((1_779_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_set(r: u32, ) -> Weight { - (69_120_000 as Weight) - // Standard Error: 12_000 - .saturating_add((1_215_000 as Weight).saturating_mul(r as Weight)) + (61_063_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_751_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_current(r: u32, ) -> Weight { - (46_021_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_103_000 as Weight).saturating_mul(r as Weight)) + (39_781_000 as Weight) + // Standard Error: 14_000 + .saturating_add((1_370_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_grow(r: u32, ) -> Weight { - (52_245_000 as Weight) - // Standard Error: 4_119_000 - .saturating_add((619_498_000 as Weight).saturating_mul(r as Weight)) + (50_983_000 as Weight) + // Standard Error: 4_238_000 + .saturating_add((618_956_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64clz(r: u32, ) -> Weight { - (47_314_000 as Weight) - // Standard Error: 9_000 - .saturating_add((1_720_000 as Weight).saturating_mul(r as Weight)) + (42_490_000 as Weight) + // Standard Error: 13_000 + .saturating_add((1_937_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ctz(r: u32, ) -> Weight { - (47_855_000 as Weight) - // Standard Error: 9_000 - .saturating_add((1_701_000 as Weight).saturating_mul(r as Weight)) + (42_296_000 as Weight) + // Standard Error: 13_000 + .saturating_add((1_943_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64popcnt(r: u32, ) -> Weight { - (47_704_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_708_000 as Weight).saturating_mul(r as Weight)) + (42_263_000 as Weight) + // Standard Error: 13_000 + .saturating_add((1_944_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eqz(r: u32, ) -> Weight { - (47_656_000 as Weight) - // Standard Error: 9_000 - .saturating_add((1_705_000 as Weight).saturating_mul(r as Weight)) + (42_087_000 as Weight) + // Standard Error: 13_000 + .saturating_add((1_952_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendsi32(r: u32, ) -> Weight { - (55_202_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_229_000 as Weight).saturating_mul(r as Weight)) + (48_024_000 as Weight) + // Standard Error: 9_000 + .saturating_add((1_783_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendui32(r: u32, ) -> Weight { - (55_193_000 as Weight) - // Standard Error: 9_000 - .saturating_add((1_223_000 as Weight).saturating_mul(r as Weight)) + (48_056_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_780_000 as Weight).saturating_mul(r as Weight)) } fn instr_i32wrapi64(r: u32, ) -> Weight { - (48_125_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_704_000 as Weight).saturating_mul(r as Weight)) + (42_352_000 as Weight) + // Standard Error: 13_000 + .saturating_add((1_928_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eq(r: u32, ) -> Weight { - (49_162_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_241_000 as Weight).saturating_mul(r as Weight)) + (45_439_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_382_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ne(r: u32, ) -> Weight { - (48_635_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_262_000 as Weight).saturating_mul(r as Weight)) + (45_232_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_393_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64lts(r: u32, ) -> Weight { - (48_550_000 as Weight) - // Standard Error: 9_000 - .saturating_add((2_267_000 as Weight).saturating_mul(r as Weight)) + (45_351_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_386_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ltu(r: u32, ) -> Weight { - (49_135_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_219_000 as Weight).saturating_mul(r as Weight)) + (45_448_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_385_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gts(r: u32, ) -> Weight { - (49_638_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_206_000 as Weight).saturating_mul(r as Weight)) + (45_275_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_386_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gtu(r: u32, ) -> Weight { - (49_889_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_201_000 as Weight).saturating_mul(r as Weight)) + (45_180_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_396_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64les(r: u32, ) -> Weight { - (49_763_000 as Weight) - // Standard Error: 9_000 - .saturating_add((2_210_000 as Weight).saturating_mul(r as Weight)) + (45_396_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_400_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64leu(r: u32, ) -> Weight { - (49_607_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_207_000 as Weight).saturating_mul(r as Weight)) + (45_597_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_392_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ges(r: u32, ) -> Weight { - (49_664_000 as Weight) - // Standard Error: 9_000 - .saturating_add((2_213_000 as Weight).saturating_mul(r as Weight)) + (45_137_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_400_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64geu(r: u32, ) -> Weight { - (49_718_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_206_000 as Weight).saturating_mul(r as Weight)) + (45_091_000 as Weight) + // Standard Error: 10_000 + .saturating_add((2_401_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64add(r: u32, ) -> Weight { - (49_513_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_208_000 as Weight).saturating_mul(r as Weight)) + (45_547_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_380_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64sub(r: u32, ) -> Weight { - (49_837_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_201_000 as Weight).saturating_mul(r as Weight)) + (45_435_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_383_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64mul(r: u32, ) -> Weight { - (49_684_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_210_000 as Weight).saturating_mul(r as Weight)) + (45_244_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_389_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divs(r: u32, ) -> Weight { - (48_749_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_872_000 as Weight).saturating_mul(r as Weight)) + (45_253_000 as Weight) + // Standard Error: 11_000 + .saturating_add((3_046_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divu(r: u32, ) -> Weight { - (49_134_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_630_000 as Weight).saturating_mul(r as Weight)) + (45_339_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_711_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rems(r: u32, ) -> Weight { - (48_981_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_861_000 as Weight).saturating_mul(r as Weight)) + (45_312_000 as Weight) + // Standard Error: 11_000 + .saturating_add((3_020_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64remu(r: u32, ) -> Weight { - (49_195_000 as Weight) - // Standard Error: 8_000 - .saturating_add((2_593_000 as Weight).saturating_mul(r as Weight)) + (45_397_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_739_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64and(r: u32, ) -> Weight { - (49_304_000 as Weight) - // Standard Error: 8_000 - .saturating_add((2_238_000 as Weight).saturating_mul(r as Weight)) + (45_282_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_387_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64or(r: u32, ) -> Weight { - (48_636_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_259_000 as Weight).saturating_mul(r as Weight)) + (45_508_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_390_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64xor(r: u32, ) -> Weight { - (48_761_000 as Weight) - // Standard Error: 8_000 - .saturating_add((2_262_000 as Weight).saturating_mul(r as Weight)) + (45_089_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_397_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shl(r: u32, ) -> Weight { - (48_492_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_263_000 as Weight).saturating_mul(r as Weight)) + (45_878_000 as Weight) + // Standard Error: 13_000 + .saturating_add((2_395_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shrs(r: u32, ) -> Weight { - (48_736_000 as Weight) - // Standard Error: 8_000 - .saturating_add((2_256_000 as Weight).saturating_mul(r as Weight)) + (45_459_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_401_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shru(r: u32, ) -> Weight { - (48_675_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_256_000 as Weight).saturating_mul(r as Weight)) + (45_663_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_398_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotl(r: u32, ) -> Weight { - (48_703_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_257_000 as Weight).saturating_mul(r as Weight)) + (45_739_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_393_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotr(r: u32, ) -> Weight { - (48_758_000 as Weight) - // Standard Error: 7_000 - .saturating_add((2_259_000 as Weight).saturating_mul(r as Weight)) + (45_290_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_392_000 as Weight).saturating_mul(r as Weight)) } } From 95853fb270774c8e62155878cc7a21a1e40cccc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Tue, 7 Dec 2021 17:48:28 +0100 Subject: [PATCH 262/695] Clean up `pallet-contracts` documentation (#10438) * Update CHANGELOG.md * Remove COMPLEXITY.md --- frame/contracts/CHANGELOG.md | 10 +- frame/contracts/COMPLEXITY.md | 487 ---------------------------- frame/contracts/README.md | 28 ++ frame/contracts/src/wasm/runtime.rs | 7 +- 4 files changed, 34 insertions(+), 498 deletions(-) delete mode 100644 frame/contracts/COMPLEXITY.md diff --git a/frame/contracts/CHANGELOG.md b/frame/contracts/CHANGELOG.md index eaedd28bf3e4..ab3998e6dc4f 100644 --- a/frame/contracts/CHANGELOG.md +++ b/frame/contracts/CHANGELOG.md @@ -23,13 +23,9 @@ In other words: Upgrading this pallet will not break pre-existing contracts. - Allow contracts to dispatch calls into the runtime (**unstable**) [#9276](https://github.com/paritytech/substrate/pull/9276) -- New **unstable** version of `seal_call` that offers more features. +- New version of `seal_call` that offers more features. [#8909](https://github.com/paritytech/substrate/pull/8909) -- New **unstable** `seal_rent_params` and `seal_rent_status` contract callable function. -[#8231](https://github.com/paritytech/substrate/pull/8231) -[#8780](https://github.com/paritytech/substrate/pull/8780) - - New `instantiate` RPC that allows clients to dry-run contract instantiation. [#8451](https://github.com/paritytech/substrate/pull/8451) @@ -38,6 +34,10 @@ In other words: Upgrading this pallet will not break pre-existing contracts. ### Changed +- Replaced storage rent with automatic storage deposits +[#9669](https://github.com/paritytech/substrate/pull/9669) +[#10082](https://github.com/paritytech/substrate/pull/10082) + - Replaced `seal_println` with the `seal_debug_message` API which allows outputting debug messages to the console and RPC clients. [#8773](https://github.com/paritytech/substrate/pull/8773) diff --git a/frame/contracts/COMPLEXITY.md b/frame/contracts/COMPLEXITY.md deleted file mode 100644 index 1fc1932fe1b5..000000000000 --- a/frame/contracts/COMPLEXITY.md +++ /dev/null @@ -1,487 +0,0 @@ -# Complexity - -This analysis is on the computing and memory complexity of specific procedures. It provides a rough estimate of operations performed in general and especially focusing on DB reads and writes. It is also an attempt to estimate the memory consumption at its peak. - -The primary goal is to come up with decent pricing for functions that can be invoked by a user (via extrinsics) or by untrusted code that prevents DoS attacks. - -## Sandboxing - -It makes sense to describe the sandboxing module first because the smart-contract module is built upon it. - -### Memory - -#### set - -Copies data from the supervisor's memory to the guest's memory. - -**complexity**: It doesn't allocate, and the computational complexity is proportional to the number of bytes to copy. - -#### get - -Copies data from the guest's memory to the supervisor's memory. - -**complexity**: It doesn't allocate, and the computational complexity is proportional to the number of bytes to copy. - -## Instance - -### Instantiation - -Instantiation of a sandbox module consists of the following steps: - -1. Loading the wasm module in the in-memory representation, -2. Performing validation of the wasm code, -3. Setting up the environment which will be used to instantiate the module, -4. Performing the standard wasm instantiation process, which includes (but is not limited to): - 1. Allocating of memory requested by the instance, - 2. Copying static data from the module to newly allocated memory, - 3. Executing the `start` function. - -**Note** that the `start` function can be viewed as a normal function and can do anything that a normal function can do, including allocation of more memory or calling the host environment. The complexity of running the `start` function should be considered separately. - -In order to start the process of instantiation, the supervisor should provide the wasm module code being instantiated and the environment definition (a set of functions, memories (and maybe globals and tables in the future) available for import by the guest module) for that module. While the environment definition typically is of the constant size (unless mechanisms like dynamic linking are used), the size of wasm is not. - -Validation and instantiation in WebAssembly are designed to be able to be performed in linear time. The allocation and computational complexity of loading a wasm module depend on the underlying wasm VM being used. For example, for JIT compilers it can and probably will be non-linear because of compilation. However, for wasmi, it should be linear. We can try to use other VMs that are able to compile code with memory and time consumption proportional to the size of the code. - -Since the module itself requests memory, the amount of allocation depends on the module code itself. If untrusted code is being instantiated, it's up to the supervisor to limit the amount of memory available to allocate. - -**complexity**: The computational complexity is proportional to the size of wasm code. Memory complexity is proportional to the size of wasm code and the amount of memory requested by the module. - -### Preparation to invoke - -Invocation of an exported function in the sandboxed module consists of the following steps: - -1. Marshalling, copying and unmarshalling the arguments when passing them between the supervisor and executor, -2. Calling into the underlying VM, -3. Marshalling, copying and unmarshalling the result when passing it between the executor and supervisor, - -**Note** that the complexity of running the function code itself should be considered separately. - -The actual complexity of invocation depends on the underlying VM. Wasmi will reserve a relatively large chunk of memory for the stack before execution of the code, although it's of constant size. - -The size of the arguments and the return value depends on the exact function in question, but can be considered as constant. - -**complexity**: Memory and computational complexity can be considered as a constant. - -### Call from the guest to the supervisor - -The executor handles each call from the guest. The execution of it consists of the following steps: - -1. Marshalling, copying and unmarshalling the arguments when passing them between the guest and executor, -2. Calling into the supervisor, -3. Marshaling, copying and unmarshalling the result when passing it between the executor and guest. - -**Note** that the complexity of running the supervisor handler should be considered separately. - -Because calling into the supervisor requires invoking a wasm VM, the actual complexity of invocation depends on the actual VM used for the runtime/supervisor. Wasmi will reserve a relatively large chunk of memory for the stack before execution of the code, although it's of constant size. - -The size of the arguments and the return value depends on the exact function in question, but can be considered as a constant. - -**complexity**: Memory and computational complexity can be considered as a constant. - -## Transactional Storage - -The contracts module makes use of the nested storage transactions feature offered by -the underlying storage which allows efficient roll back of changes made by contracts. - -> ℹ️ The underlying storage has a overlay layer implemented as a `Map`. If the runtime reads a storage location and the -> respective key doesn't exist in the overlay, then the underlying storage performs a DB access, but the value won't be -> placed into the overlay. The overlay is only filled with writes. -> -> This means that the overlay can be abused in the following ways: -> -> - The overlay can be inflated by issuing a lot of writes to unique locations, -> - Deliberate cache misses can be induced by reading non-modified storage locations, - -It also worth noting that the performance degrades with more state stored in the trie. Due to this -there is not negligible chance that gas schedule will be updated for all operations that involve -storage access. - -## get_storage, get_code_hash, get_rent_allowance, get_balance, contract_exists - -Those query the underlying storage for the requested value. If the value was modified in the -current block they are served from the cache. Otherwise a database read is performed. - -**complexity**: The memory complexity is proportional to the size of the value. The computational complexity is proportional the size of the value; the cost is dominated by the DB read. - -## set_storage, set_balance, set_rent_allowance - -These function write to the underlying storage which caches those values and does not write -them to the database immediately. - -While these functions only modify the local cache, they trigger a database write later when -all changes that were not rolled back are written to storage. Moreover, if the balance of the -account is changed to be below `existential_deposit` then that account along with all its storage -will be removed, which requires time proportional to the number of storage entries that account has. -It should be ensured that pricing accounts for these facts. - -**complexity**: Each lookup has a logarithmical computing time to the number of already inserted entries. -No additional memory is required. - -## instantiate_contract - -Calls `contract_exists` and if it doesn't exist, do not modify the local `Map` similarly to `set_rent_allowance`. - -**complexity**: The computational complexity is proportional to the depth of the overlay cascade and the size of the value; the cost is dominated by the DB read though. No additional memory is required. - -## commit - -In this function, all values modified in the current transactions are committed to the parent -transaction. - -This will trigger `N` inserts into parent transaction (`O(log M)` complexity) or into the storage, where `N` is the size of the current transaction and `M` is the size of the parent transaction. Consider adjusting the price of modifying the -current transaction to account for this (since pricing for the count of entries in `commit` will make the price of commit way less predictable). No additional memory is required. - -Note that in case of storage modification we need to construct a key in the underlying storage. In order to do that we need: - -- perform `twox_128` hashing over a concatenation of some prefix literal and the `AccountId` of the storage owner. -- then perform `blake2_256` hashing of the storage key. -- concatenation of these hashes will constitute the key in the underlying storage. - -There is also a special case to think of: if the balance of some account goes below `existential_deposit`, then all storage entries of that account will be erased, which requires time proportional to the number of storage entries that account has. - -**complexity**: `N` inserts into a transaction or eventually into the storage (if committed). Every deleted account will induce removal of all its storage which is proportional to the number of storage entries that account has. - -## revert - -Consists of dropping (in the Rust sense) of the current transaction. - -**complexity**: Computing complexity is proportional to a number of changed entries in a overlay. No additional memory is required. - -## Executive - -### Transfer - -This function performs the following steps: - -1. Querying source and destination balances from the current transaction (see `get_balance`), -2. Querying `existential_deposit`. -3. Executing `ensure_account_liquid` hook. -4. Updating source and destination balance in the overlay (see `set_balance`). - -**Note** that the complexity of executing `ensure_account_liquid` hook should be considered separately. - -In the course of the execution this function can perform up to 2 DB reads to `get_balance` of source and destination accounts. It can also induce up to 2 DB writes via `set_balance` if flushed to the storage. - -Moreover, if the source balance goes below `existential_deposit` then the transfer is denied and -returns with an error. - -Assuming marshaled size of a balance value is of the constant size we can neglect its effect on the performance. - -**complexity**: up to 2 DB reads and up to 2 DB writes (if flushed to the storage) in the standard case. If removal of the source account takes place then it will additionally perform a DB write per one storage entry that the account has. Memorywise it can be assumed to be constant. - -### Initialization - -Before a call or instantiate can be performed the execution context must be initialized. - -For the first call or instantiation in the handling of an extrinsic, this involves two calls: - -1. `>::now()` -2. `>::block_number()` - -The complexity of initialization depends on the complexity of these functions. In the current -implementation they just involve a DB read. - -For subsequent calls and instantiations during contract execution, the initialization requires no -expensive operations. - -### Terminate - -This function performs the following steps: - -1. Check the calling contract is not already on the callstack by calling `is_live`. -2. `transfer` funds from caller to the beneficiary. -3. Flag the caller contract as deleted in the overlay. - -`is_live` does not do any database access nor does it allocate memory. It walks up the call -stack and therefore executes in linear time depending on size of the call stack. Because -the call stack is of a fixed maximum size we consider this operation as constant time. - -**complexity**: Database accesses as described in Transfer + Removal of the contract. Currently, -we are using child trie removal which is linear in the amount of stored keys. Upcoming changes -will make the account removal constant time. - -### Call - -This function receives input data for the contract execution. The execution consists of the following steps: - -1. Initialization of the execution context. -2. Checking rent payment. -3. Loading code from the DB. -4. Starting a new storage transaction. -5. `transfer`-ing funds between the caller and the destination account. -6. Executing the code of the destination account. -7. Committing or rolling back the storage transaction. - -**Note** that the complexity of executing the contract code should be considered separately. - -Checking for rent involves 2 unconditional DB reads: `ContractInfoOf` and `block_number` -and on top of that at most once per block: - -- DB read to `free_balance` and -- `rent_deposit_offset` and -- `rent_byte_price` and -- `Currency::minimum_balance` and -- `tombstone_deposit`. -- Calls to `ensure_can_withdraw`, `withdraw`, `make_free_balance_be` can perform arbitrary logic and should be considered separately, -- `child_storage_root` -- `kill_child_storage` -- mutation of `ContractInfoOf` - -Loading code most likely will trigger a DB read, since the code is immutable and therefore will not get into the cache (unless a suicide removes it, or it has been instantiated in the same call chain). - -Also, `transfer` can make up to 2 DB reads and up to 2 DB writes (if flushed to the storage) in the standard case. If removal of the source account takes place then it will additionally perform a DB write per one storage entry that the account has. - -Finally, the current storage transaction is closed. The complexity of this depends on the number of changes performed by the code. Thus, the pricing of storage modification should account for that. - -**complexity**: - -- Only for the first invocation of the contract: up to 5 DB reads and one DB write as well as logic executed by `ensure_can_withdraw`, `withdraw`, `make_free_balance_be`. -- On top of that for every invocation: Up to 5 DB reads. DB read of the code is of dynamic size. There can also be up to 2 DB writes (if flushed to the storage). Additionally, if the source account removal takes place a DB write will be performed per one storage entry that the account has. - -### Instantiate - -This function takes the code of the constructor and input data. Instantiation of a contract consists of the following steps: - -1. Initialization of the execution context. -2. Calling `DetermineContractAddress` hook to determine an address for the contract, -3. Starting a new storage transaction. -4. `transfer`-ing funds between self and the newly instantiated contract. -5. Executing the constructor code. This will yield the final code of the code. -6. Storing the code for the newly instantiated contract in the overlay. -7. Committing or rolling back the storage transaction. - -**Note** that the complexity of executing the constructor code should be considered separately. - -**Note** that the complexity of `DetermineContractAddress` hook should be considered separately as well. Most likely it will use some kind of hashing over the code of the constructor and input data. The default `SimpleAddressDeterminer` does precisely that. - -**Note** that the constructor returns code in the owned form and it's obtained via return facilities, which should have take fee for the return value. - -Also, `transfer` can make up to 2 DB reads and up to 2 DB writes (if flushed to the storage) in the standard case. If removal of the source account takes place then it will additionally perform a DB write per one storage entry that the account has. - -Storing the code in the overlay may induce another DB write (if flushed to the storage) with the size proportional to the size of the constructor code. - -Finally, the current storage transaction is closed.. The complexity of this depends on the number of changes performed by the constructor code. Thus, the pricing of storage modification should account for that. - -**complexity**: Up to 2 DB reads and induces up to 3 DB writes (if flushed to the storage), one of which is dependent on the size of the code. Additionally, if the source account removal takes place a DB write will be performed per one storage entry that the account has. - -## Contracts API - -Each API function invoked from a contract can involve some overhead. - -## Getter functions - -Those are simple getter functions which copy a requested value to contract memory. They -all have the following two arguments: - -- `output_ptr`: Pointer into contract memory where to copy the value. -- `output_len_ptr`: Pointer into contract memory where the size of the buffer is stored. The size of the copied value is also stored there. - -**complexity**: The size of the returned value is constant for a given runtime. Therefore we -consider its complexity constant even though some of them might involve at most one DB read. Some of those -functions call into other pallets of the runtime. The assumption here is that those functions are also -linear in regard to the size of the data that is returned and therefore considered constant for a -given runtime. - -This is the list of getters: - -- seal_caller -- seal_address -- seal_weight_to_fee -- seal_gas_left -- seal_balance -- seal_value_transferred -- seal_now -- seal_minimum_balance -- seal_tombstone_deposit -- seal_rent_allowance -- seal_block_number - -### seal_set_storage - -This function receives a `key` and `value` as arguments. It consists of the following steps: - -1. Reading the sandbox memory for `key` and `value` (see sandboxing memory get). -2. Setting the storage at the given `key` to the given `value` (see `set_storage`). - -**complexity**: Complexity is proportional to the size of the `value`. This function induces a DB write of size proportional to the `value` size (if flushed to the storage), so should be priced accordingly. - -### seal_clear_storage - -This function receives a `key` as argument. It consists of the following steps: - -1. Reading the sandbox memory for `key` (see sandboxing memory get). -2. Clearing the storage at the given `key` (see `set_storage`). - -**complexity**: Complexity is constant. This function induces a DB write to clear the storage entry -(upon being flushed to the storage) and should be priced accordingly. - -### seal_get_storage - -This function receives a `key` as an argument. It consists of the following steps: - -1. Reading the sandbox memory for `key` (see sandboxing memory get). -2. Reading the storage with the given key (see `get_storage`). It receives back the owned result buffer. -3. Writing the storage value to contract memory. - -Key is of a constant size. Therefore, the sandbox memory load can be considered to be of constant complexity. - -Unless the value is cached, a DB read will be performed. The size of the value is not known until the read is -performed. Moreover, the DB read has to be synchronous and no progress can be made until the value is fetched. - -**complexity**: The memory and computing complexity is proportional to the size of the fetched value. This function performs a DB read. - -### seal_transfer - -This function receives the following arguments: - -- `account` buffer of a marshaled `AccountId`, -- `value` buffer of a marshaled `Balance`, - -It consists of the following steps: - -1. Loading `account` buffer from the sandbox memory (see sandboxing memory get) and then decoding it. -2. Loading `value` buffer from the sandbox memory and then decoding it. -3. Invoking the executive function `transfer`. - -Loading of `account` and `value` buffers should be charged. This is because the sizes of buffers are specified by the calling code, even though marshaled representations are, essentially, of constant size. This can be fixed by assigning an upper bound for sizes of `AccountId` and `Balance`. - -### seal_call - -This function receives the following arguments: - -- `callee` buffer of a marshaled `AccountId`, -- `gas` limit which is plain u64, -- `value` buffer of a marshaled `Balance`, -- `input_data` an arbitrarily sized byte vector. -- `output_ptr` pointer to contract memory. - -It consists of the following steps: - -1. Loading `callee` buffer from the sandbox memory (see sandboxing memory get) and then decoding it. -2. Loading `value` buffer from the sandbox memory and then decoding it. -3. Loading `input_data` buffer from the sandbox memory. -4. Invoking the executive function `call`. -5. Writing output buffer to contract memory. - -Loading of `callee` and `value` buffers should be charged. This is because the sizes of buffers are specified by the calling code, even though marshaled representations are, essentially, of constant size. This can be fixed by assigning an upper bound for sizes of `AccountId` and `Balance`. - -Loading `input_data` should be charged in any case. - -**complexity**: All complexity comes from loading and writing buffers and executing `call` executive function. The former component is proportional to the sizes of `callee`, `value`, `input_data` and `output_ptr` buffers. The latter component completely depends on the complexity of `call` executive function, and also dominated by it. - -### seal_instantiate - -This function receives the following arguments: - -- `init_code`, a buffer which contains the code of the constructor. -- `gas` limit which is plain u64 -- `value` buffer of a marshaled `Balance` -- `input_data`. an arbitrarily sized byte vector. - -It consists of the following steps: - -1. Loading `init_code` buffer from the sandbox memory (see sandboxing memory get) and then decoding it. -2. Loading `value` buffer from the sandbox memory and then decoding it. -3. Loading `input_data` buffer from the sandbox memory. -4. Invoking `instantiate` executive function. - -Loading of `value` buffer should be charged. This is because the size of the buffer is specified by the calling code, even though marshaled representation is, essentially, of constant size. This can be fixed by assigning an upper bound for size for `Balance`. - -Loading `init_code` and `input_data` should be charged in any case. - -**complexity**: All complexity comes from loading buffers and executing `instantiate` executive function. The former component is proportional to the sizes of `init_code`, `value` and `input_data` buffers. The latter component completely depends on the complexity of `instantiate` executive function and also dominated by it. - -### seal_terminate - -This function receives the following arguments: - -- `beneficiary`, buffer of a marshaled `AccountId` - -It consists of the following steps: - -1. Loading `beneficiary` buffer from the sandbox memory (see sandboxing memory get) and then decoding it. - -Loading of the `beneficiary` buffer should be charged. This is because the sizes of buffers are specified by the calling code, even though marshaled representations are, essentially, of constant size. This can be fixed by assigning an upper bound for sizes of `AccountId`. - -**complexity**: All complexity comes from loading buffers and executing `terminate` executive function. The former component is proportional to the size of the `beneficiary` buffer. The latter component completely depends on the complexity of `terminate` executive function and also dominated by it. - -### seal_input - -This function receives a pointer to contract memory. It copies the input to the contract call to this location. - -**complexity**: The complextity is proportional to the size of the input buffer. - -### seal_return - -This function receives a `data` buffer and `flags` arguments. Execution of the function consists of the following steps: - -1. Loading `data` buffer from the sandbox memory (see sandboxing memory get). -2. Storing the `u32` flags value. -3. Trapping - -**complexity**: The complexity of this function is proportional to the size of the `data` buffer. - -### seal_deposit_event - -This function receives a `data` buffer as an argument. Execution of the function consists of the following steps: - -1. Loading `data` buffer from the sandbox memory (see sandboxing memory get), -2. Insert to nested context execution -3. Copies from nested to underlying contexts -4. Call system deposit event - -**complexity**: The complexity of this function is proportional to the size of the `data` buffer. - -### seal_set_rent_allowance - -This function receives the following argument: - -- `value` buffer of a marshaled `Balance`, - -It consists of the following steps: - -1. Loading `value` buffer from the sandbox memory and then decoding it. -2. Invoking `set_rent_allowance` AccountDB function. - -**complexity**: Complexity is proportional to the size of the `value`. This function induces a DB write of size proportional to the `value` size (if flushed to the storage), so should be priced accordingly. - -## Built-in hashing functions - -This paragraph concerns the following supported built-in hash functions: - -- `SHA2` with 256-bit width -- `KECCAK` with 256-bit width -- `BLAKE2` with 128-bit and 256-bit widths - -These functions compute a cryptographic hash on the given inputs and copy the -resulting hash directly back into the sandboxed Wasm contract output buffer. - -Execution of the function consists of the following steps: - -1. Load data stored in the input buffer into an intermediate buffer. -2. Compute the cryptographic hash `H` on the intermediate buffer. -3. Copy back the bytes of `H` into the contract side output buffer. - -**complexity**: Complexity is proportional to the size of the input buffer in bytes -as well as to the size of the output buffer in bytes. Also different cryptographic -algorithms have different inherent complexity so users must expect the above -mentioned crypto hashes to have varying gas costs. -The complexity of each cryptographic hash function highly depends on the underlying -implementation. - -### seal_ecdsa_recover - -This function receives the following arguments: - -- `signature` is 65 bytes buffer, -- `message_hash` is 32 bytes buffer, -- `output` is 33 bytes buffer to return compressed public key, - -It consists of the following steps: - -1. Loading `signature` buffer from the sandbox memory (see sandboxing memory get). -2. Loading `message_hash` buffer from the sandbox memory. -3. Invoking the executive function `secp256k1_ecdsa_recover_compressed`. -4. Copy the bytes of compressed public key into the contract side output buffer. - -**complexity**: Complexity is partially constant(it doesn't depend on input) but still depends on points of ECDSA and calculation. \ No newline at end of file diff --git a/frame/contracts/README.md b/frame/contracts/README.md index 978ee25fcb10..50e43ddb998a 100644 --- a/frame/contracts/README.md +++ b/frame/contracts/README.md @@ -49,6 +49,34 @@ fails, A can decide how to handle that failure, either proceeding or reverting A Those are documented in the [reference documentation](https://docs.rs/pallet-contracts/latest/pallet_contracts/#dispatchable-functions). +### Interface exposed to contracts + +Each contract is one WebAssembly module that looks like this: + +```wat +(module + ;; Invoked by pallet-contracts when a contract is instantiated. + ;; No arguments and empty return type. + (func (export "deploy")) + + ;; Invoked by pallet-contracts when a contract is called. + ;; No arguments and empty return type. + (func (export "call")) + + ;; If a contract uses memory it must be imported. Memory is optional. + ;; The maximum allowed memory size depends on the pallet-contracts configuration. + (import "env" "memory" (memory 1 1)) + + ;; This is one of many functions that can be imported and is implemented by pallet-contracts. + ;; This function is used to copy the result buffer and flags back to the caller. + (import "seal0" "seal_return" (func $seal_return (param i32 i32 i32))) +) +``` + +The documentation of all importable functions can be found +[here](https://github.com/paritytech/substrate/blob/master/frame/contracts/src/wasm/runtime.rs). +Look for the `define_env!` macro invocation. + ## Usage This module executes WebAssembly smart contracts. These can potentially be written in any language diff --git a/frame/contracts/src/wasm/runtime.rs b/frame/contracts/src/wasm/runtime.rs index a7341e9e02e5..ad13d18435a9 100644 --- a/frame/contracts/src/wasm/runtime.rs +++ b/frame/contracts/src/wasm/runtime.rs @@ -726,12 +726,7 @@ where } } -// *********************************************************** -// * AFTER MAKING A CHANGE MAKE SURE TO UPDATE COMPLEXITY.MD * -// *********************************************************** - -// Define a function `fn init_env() -> HostFunctionSet` that returns -// a function set which can be imported by an executed contract. +// This is the API exposed to contracts. // // # Note // From fd350e3c02d7fb9421d908e6c552d50992b167ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Silva?= <123550+andresilva@users.noreply.github.com> Date: Tue, 7 Dec 2021 21:31:28 +0000 Subject: [PATCH 263/695] grandpa: allow authority set hard forks to be forced (#10444) * grandpa: allow authority set hard forks to be forced * grandpa: fix authority set hard forks in warp proof provider * grandpa: make AuthoritySetHardFork public * grandpa: extend comment --- client/finality-grandpa/src/lib.rs | 41 ++++++++++++++++++----- client/finality-grandpa/src/warp_proof.rs | 11 +++--- 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/client/finality-grandpa/src/lib.rs b/client/finality-grandpa/src/lib.rs index e7618929fd08..b30006646947 100644 --- a/client/finality-grandpa/src/lib.rs +++ b/client/finality-grandpa/src/lib.rs @@ -541,6 +541,24 @@ where ) } +/// A descriptor for an authority set hard fork. These are authority set changes +/// that are not signalled by the runtime and instead are defined off-chain +/// (hence the hard fork). +pub struct AuthoritySetHardFork { + /// The new authority set id. + pub set_id: SetId, + /// The block hash and number at which the hard fork should be applied. + pub block: (Block::Hash, NumberFor), + /// The authorities in the new set. + pub authorities: AuthorityList, + /// The latest block number that was finalized before this authority set + /// hard fork. When defined, the authority set change will be forced, i.e. + /// the node won't wait for the block above to be finalized before enacting + /// the change, and the given finalized number will be used as a base for + /// voting. + pub last_finalized: Option>, +} + /// Make block importer and link half necessary to tie the background voter to /// it. A vector of authority set hard forks can be passed, any authority set /// change signaled at the given block (either already signalled or in a further @@ -550,7 +568,7 @@ pub fn block_import_with_authority_set_hard_forks client: Arc, genesis_authorities_provider: &dyn GenesisAuthoritySetProvider, select_chain: SC, - authority_set_hard_forks: Vec<(SetId, (Block::Hash, NumberFor), AuthorityList)>, + authority_set_hard_forks: Vec>, telemetry: Option, ) -> Result<(GrandpaBlockImport, LinkHalf), ClientError> where @@ -580,19 +598,24 @@ where let (justification_sender, justification_stream) = GrandpaJustificationStream::channel(); - // create pending change objects with 0 delay and enacted on finality - // (i.e. standard changes) for each authority set hard fork. + // create pending change objects with 0 delay for each authority set hard fork. let authority_set_hard_forks = authority_set_hard_forks .into_iter() - .map(|(set_id, (hash, number), authorities)| { + .map(|fork| { + let delay_kind = if let Some(last_finalized) = fork.last_finalized { + authorities::DelayKind::Best { median_last_finalized: last_finalized } + } else { + authorities::DelayKind::Finalized + }; + ( - set_id, + fork.set_id, authorities::PendingChange { - next_authorities: authorities, + next_authorities: fork.authorities, delay: Zero::zero(), - canon_hash: hash, - canon_height: number, - delay_kind: authorities::DelayKind::Finalized, + canon_hash: fork.block.0, + canon_height: fork.block.1, + delay_kind, }, ) }) diff --git a/client/finality-grandpa/src/warp_proof.rs b/client/finality-grandpa/src/warp_proof.rs index 3c1fa4892f8a..39d570d22bd7 100644 --- a/client/finality-grandpa/src/warp_proof.rs +++ b/client/finality-grandpa/src/warp_proof.rs @@ -19,8 +19,8 @@ use sp_runtime::codec::{self, Decode, Encode}; use crate::{ - best_justification, find_scheduled_change, AuthoritySetChanges, BlockNumberOps, - GrandpaJustification, SharedAuthoritySet, + best_justification, find_scheduled_change, AuthoritySetChanges, AuthoritySetHardFork, + BlockNumberOps, GrandpaJustification, SharedAuthoritySet, }; use sc_client_api::Backend as ClientBackend; use sc_network::warp_request_handler::{EncodedProof, VerificationResult, WarpSyncProvider}; @@ -255,12 +255,15 @@ where pub fn new( backend: Arc, authority_set: SharedAuthoritySet>, - hard_forks: Vec<(SetId, (Block::Hash, NumberFor), AuthorityList)>, + hard_forks: Vec>, ) -> Self { NetworkProvider { backend, authority_set, - hard_forks: hard_forks.into_iter().map(|(s, hn, list)| (hn, (s, list))).collect(), + hard_forks: hard_forks + .into_iter() + .map(|fork| (fork.block, (fork.set_id, fork.authorities))) + .collect(), } } } From 4abd91cee8ea4599f1940e819102256c557c63cc Mon Sep 17 00:00:00 2001 From: Gautam Dhameja Date: Tue, 7 Dec 2021 23:40:47 +0100 Subject: [PATCH 264/695] Add child-bounties pallet. (#10309) * Extract child-bounties as a separate pallet. * Initial tests added. * More tests. * Tests complete. Fixed curator fee issue. * Fixed comments. * Added benchmarks for child-bounties pallet. * Added weights. * Fixed formatting. * Fixed comments. * Re-run benchmarks for bounties pallet. * Make cargo fmt happy again * add max encoded len * use event structs * fmt * fix compile * Addressed review comments. * Use config type instead of const in benchmarking. * Addressed more review comments. * Use ensure_can_withdraw instead of just checking min balance. * fmt. * Introduce ChildBountyCuratorDepositBase to avoid zero curator deposits for child bounties. * Fix unassign curator logic for child-bounties. * Added more tests for unassign curator. * Reduce bounty description max length in node runtime. * Updated weights for child bounties pallet. * reduce indentation of unassign_curator * more indentation reduction * deduplicate slashing arms * reintroduce ensure check * add assertion to check that bad unassign origin fails * formatting * Updated comments. Co-authored-by: Ricardo Rius Co-authored-by: Shawn Tabrizi Co-authored-by: Alexander Popiak --- Cargo.lock | 20 + Cargo.toml | 1 + bin/node/runtime/Cargo.toml | 6 +- bin/node/runtime/src/lib.rs | 17 +- frame/bounties/src/lib.rs | 57 +- frame/bounties/src/tests.rs | 1 + frame/bounties/src/weights.rs | 158 +-- frame/child-bounties/Cargo.toml | 54 + frame/child-bounties/README.md | 21 + frame/child-bounties/src/benchmarking.rs | 308 ++++++ frame/child-bounties/src/lib.rs | 897 ++++++++++++++++ frame/child-bounties/src/tests.rs | 1219 ++++++++++++++++++++++ frame/child-bounties/src/weights.rs | 215 ++++ 13 files changed, 2896 insertions(+), 78 deletions(-) create mode 100644 frame/child-bounties/Cargo.toml create mode 100644 frame/child-bounties/README.md create mode 100644 frame/child-bounties/src/benchmarking.rs create mode 100644 frame/child-bounties/src/lib.rs create mode 100644 frame/child-bounties/src/tests.rs create mode 100644 frame/child-bounties/src/weights.rs diff --git a/Cargo.lock b/Cargo.lock index 08d2ab732839..d1618f83b476 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4702,6 +4702,7 @@ dependencies = [ "pallet-bags-list", "pallet-balances", "pallet-bounties", + "pallet-child-bounties", "pallet-collective", "pallet-contracts", "pallet-contracts-primitives", @@ -5383,6 +5384,25 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-child-bounties" +version = "4.0.0-dev" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log 0.4.14", + "pallet-balances", + "pallet-bounties", + "pallet-treasury", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-collective" version = "4.0.0-dev" diff --git a/Cargo.toml b/Cargo.toml index f30b223a9b20..7bb08345c0fe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -74,6 +74,7 @@ members = [ "frame/beefy-mmr/primitives", "frame/benchmarking", "frame/bounties", + "frame/child-bounties", "frame/collective", "frame/contracts", "frame/contracts/rpc", diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 4771202b90a0..a61c2311917a 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -59,6 +59,7 @@ pallet-babe = { version = "4.0.0-dev", default-features = false, path = "../../. pallet-bags-list = { version = "4.0.0-dev", default-features = false, path = "../../../frame/bags-list" } pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../../../frame/balances" } pallet-bounties = { version = "4.0.0-dev", default-features = false, path = "../../../frame/bounties" } +pallet-child-bounties = { version = "4.0.0-dev", default-features = false, path = "../../../frame/child-bounties" } pallet-collective = { version = "4.0.0-dev", default-features = false, path = "../../../frame/collective" } pallet-contracts = { version = "4.0.0-dev", default-features = false, path = "../../../frame/contracts" } pallet-contracts-primitives = { version = "4.0.0-dev", default-features = false, path = "../../../frame/contracts/common/" } @@ -173,7 +174,8 @@ std = [ "log/std", "frame-try-runtime/std", "sp-npos-elections/std", - "sp-io/std" + "sp-io/std", + "pallet-child-bounties/std", ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", @@ -186,6 +188,7 @@ runtime-benchmarks = [ "pallet-bags-list/runtime-benchmarks", "pallet-balances/runtime-benchmarks", "pallet-bounties/runtime-benchmarks", + "pallet-child-bounties/runtime-benchmarks", "pallet-collective/runtime-benchmarks", "pallet-contracts/runtime-benchmarks", "pallet-democracy/runtime-benchmarks", @@ -225,6 +228,7 @@ try-runtime = [ "pallet-babe/try-runtime", "pallet-balances/try-runtime", "pallet-bounties/try-runtime", + "pallet-child-bounties/try-runtime", "pallet-collective/try-runtime", "pallet-contracts/try-runtime", "pallet-democracy/try-runtime", diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 9573b86c6ee2..45b49dc46b89 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -844,10 +844,13 @@ parameter_types! { pub const BountyDepositPayoutDelay: BlockNumber = 1 * DAYS; pub const TreasuryPalletId: PalletId = PalletId(*b"py/trsry"); pub const BountyUpdatePeriod: BlockNumber = 14 * DAYS; - pub const MaximumReasonLength: u32 = 16384; + pub const MaximumReasonLength: u32 = 300; pub const BountyCuratorDeposit: Permill = Permill::from_percent(50); pub const BountyValueMinimum: Balance = 5 * DOLLARS; pub const MaxApprovals: u32 = 100; + pub const MaxActiveChildBountyCount: u32 = 5; + pub const ChildBountyValueMinimum: Balance = 1 * DOLLARS; + pub const ChildBountyCuratorDepositBase: Permill = Permill::from_percent(10); } impl pallet_treasury::Config for Runtime { @@ -883,6 +886,15 @@ impl pallet_bounties::Config for Runtime { type DataDepositPerByte = DataDepositPerByte; type MaximumReasonLength = MaximumReasonLength; type WeightInfo = pallet_bounties::weights::SubstrateWeight; + type ChildBountyManager = ChildBounties; +} + +impl pallet_child_bounties::Config for Runtime { + type Event = Event; + type MaxActiveChildBountyCount = MaxActiveChildBountyCount; + type ChildBountyValueMinimum = ChildBountyValueMinimum; + type ChildBountyCuratorDepositBase = ChildBountyCuratorDepositBase; + type WeightInfo = pallet_child_bounties::weights::SubstrateWeight; } impl pallet_tips::Config for Runtime { @@ -1302,6 +1314,7 @@ construct_runtime!( Uniques: pallet_uniques, TransactionStorage: pallet_transaction_storage, BagsList: pallet_bags_list, + ChildBounties: pallet_child_bounties, } ); @@ -1652,6 +1665,7 @@ impl_runtime_apis! { list_benchmark!(list, extra, pallet_bags_list, BagsList); list_benchmark!(list, extra, pallet_balances, Balances); list_benchmark!(list, extra, pallet_bounties, Bounties); + list_benchmark!(list, extra, pallet_child_bounties, ChildBounties); list_benchmark!(list, extra, pallet_collective, Council); list_benchmark!(list, extra, pallet_contracts, Contracts); list_benchmark!(list, extra, pallet_democracy, Democracy); @@ -1729,6 +1743,7 @@ impl_runtime_apis! { add_benchmark!(params, batches, pallet_balances, Balances); add_benchmark!(params, batches, pallet_bags_list, BagsList); add_benchmark!(params, batches, pallet_bounties, Bounties); + add_benchmark!(params, batches, pallet_child_bounties, ChildBounties); add_benchmark!(params, batches, pallet_collective, Council); add_benchmark!(params, batches, pallet_contracts, Contracts); add_benchmark!(params, batches, pallet_democracy, Democracy); diff --git a/frame/bounties/src/lib.rs b/frame/bounties/src/lib.rs index 5021608b506b..1d32b63f38f9 100644 --- a/frame/bounties/src/lib.rs +++ b/frame/bounties/src/lib.rs @@ -123,6 +123,15 @@ pub struct Bounty { status: BountyStatus, } +impl + Bounty +{ + /// Getter for bounty status, to be used for child bounties. + pub fn get_status(&self) -> BountyStatus { + self.status.clone() + } +} + /// The status of a bounty proposal. #[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] pub enum BountyStatus { @@ -156,6 +165,15 @@ pub enum BountyStatus { }, } +/// The child-bounty manager. +pub trait ChildBountyManager { + /// Get the active child-bounties for a parent bounty. + fn child_bounties_count(bounty_id: BountyIndex) -> BountyIndex; + + /// Get total curator fees of children-bounty curators. + fn children_curator_fees(bounty_id: BountyIndex) -> Balance; +} + #[frame_support::pallet] pub mod pallet { use super::*; @@ -202,6 +220,9 @@ pub mod pallet { /// Weight information for extrinsics in this pallet. type WeightInfo: WeightInfo; + + /// The child-bounty manager. + type ChildBountyManager: ChildBountyManager>; } #[pallet::error] @@ -225,6 +246,8 @@ pub mod pallet { PendingPayout, /// The bounties cannot be claimed/closed because it's still in the countdown period. Premature, + /// The bounty cannot be closed because it has active child-bounties. + HasActiveChildBounty, } #[pallet::event] @@ -512,6 +535,13 @@ pub mod pallet { Bounties::::try_mutate_exists(bounty_id, |maybe_bounty| -> DispatchResult { let mut bounty = maybe_bounty.as_mut().ok_or(Error::::InvalidIndex)?; + + // Ensure no active child-bounties before processing the call. + ensure!( + T::ChildBountyManager::child_bounties_count(bounty_id) == 0, + Error::::HasActiveChildBounty + ); + match &bounty.status { BountyStatus::Active { curator, .. } => { ensure!(signer == *curator, Error::::RequireCurator); @@ -563,7 +593,15 @@ pub mod pallet { let payout = balance.saturating_sub(fee); let err_amount = T::Currency::unreserve(&curator, bounty.curator_deposit); debug_assert!(err_amount.is_zero()); - let res = T::Currency::transfer(&bounty_account, &curator, fee, AllowDeath); // should not fail + + // Get total child-bounties curator fees, and subtract it from master curator + // fee. + let children_fee = T::ChildBountyManager::children_curator_fees(bounty_id); + debug_assert!(children_fee <= fee); + + let final_fee = fee.saturating_sub(children_fee); + let res = + T::Currency::transfer(&bounty_account, &curator, final_fee, AllowDeath); // should not fail debug_assert!(res.is_ok()); let res = T::Currency::transfer(&bounty_account, &beneficiary, payout, AllowDeath); // should not fail @@ -609,6 +647,12 @@ pub mod pallet { |maybe_bounty| -> DispatchResultWithPostInfo { let bounty = maybe_bounty.as_ref().ok_or(Error::::InvalidIndex)?; + // Ensure no active child-bounties before processing the call. + ensure!( + T::ChildBountyManager::child_bounties_count(bounty_id) == 0, + Error::::HasActiveChildBounty + ); + match &bounty.status { BountyStatus::Proposed => { // The reject origin would like to cancel a proposed bounty. @@ -813,3 +857,14 @@ impl pallet_treasury::SpendFunds for Pallet { *total_weight += ::WeightInfo::spend_funds(bounties_len); } } + +// Default impl for when ChildBounties is not being used in the runtime. +impl ChildBountyManager for () { + fn child_bounties_count(_bounty_id: BountyIndex) -> BountyIndex { + Default::default() + } + + fn children_curator_fees(_bounty_id: BountyIndex) -> Balance { + Zero::zero() + } +} diff --git a/frame/bounties/src/tests.rs b/frame/bounties/src/tests.rs index 344bb6495c3b..bbcf9d6d9e72 100644 --- a/frame/bounties/src/tests.rs +++ b/frame/bounties/src/tests.rs @@ -146,6 +146,7 @@ impl Config for Test { type DataDepositPerByte = DataDepositPerByte; type MaximumReasonLength = MaximumReasonLength; type WeightInfo = (); + type ChildBountyManager = (); } type TreasuryError = pallet_treasury::Error; diff --git a/frame/bounties/src/weights.rs b/frame/bounties/src/weights.rs index be9363642439..1383f69bed91 100644 --- a/frame/bounties/src/weights.rs +++ b/frame/bounties/src/weights.rs @@ -18,24 +18,24 @@ //! Autogenerated weights for pallet_bounties //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-08-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2021-11-19, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 // Executed Command: -// target/release/substrate +// ./target/release/substrate // benchmark // --chain=dev // --steps=50 // --repeat=20 -// --pallet=pallet_bounties +// --pallet +// pallet_bounties // --extrinsic=* // --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/bounties/src/weights.rs +// --output=./frame/bounties/src/ // --template=./.maintain/frame-weight-template.hbs - #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] #![allow(unused_imports)] @@ -61,87 +61,91 @@ pub trait WeightInfo { /// Weights for pallet_bounties using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - // Storage: Treasury BountyCount (r:1 w:1) + // Storage: Bounties BountyCount (r:1 w:1) // Storage: System Account (r:1 w:1) - // Storage: Treasury BountyDescriptions (r:0 w:1) - // Storage: Treasury Bounties (r:0 w:1) + // Storage: Bounties BountyDescriptions (r:0 w:1) + // Storage: Bounties Bounties (r:0 w:1) fn propose_bounty(d: u32, ) -> Weight { - (44_482_000 as Weight) + (58_161_000 as Weight) // Standard Error: 0 .saturating_add((1_000 as Weight).saturating_mul(d as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } - // Storage: Treasury Bounties (r:1 w:1) - // Storage: Treasury BountyApprovals (r:1 w:1) + // Storage: Bounties Bounties (r:1 w:1) + // Storage: Bounties BountyApprovals (r:1 w:1) fn approve_bounty() -> Weight { - (11_955_000 as Weight) + (20_000_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } - // Storage: Treasury Bounties (r:1 w:1) + // Storage: Bounties Bounties (r:1 w:1) fn propose_curator() -> Weight { - (9_771_000 as Weight) + (14_000_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - // Storage: Treasury Bounties (r:1 w:1) + // Storage: Bounties Bounties (r:1 w:1) // Storage: System Account (r:1 w:1) fn unassign_curator() -> Weight { - (40_683_000 as Weight) + (62_000_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } - // Storage: Treasury Bounties (r:1 w:1) + // Storage: Bounties Bounties (r:1 w:1) // Storage: System Account (r:1 w:1) fn accept_curator() -> Weight { - (36_390_000 as Weight) + (55_000_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } - // Storage: Treasury Bounties (r:1 w:1) + // Storage: Bounties Bounties (r:1 w:1) + // Storage: ChildBounties ParentChildBounties (r:1 w:0) fn award_bounty() -> Weight { - (25_187_000 as Weight) - .saturating_add(T::DbWeight::get().reads(1 as Weight)) + (46_000_000 as Weight) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - // Storage: Treasury Bounties (r:1 w:1) + // Storage: Bounties Bounties (r:1 w:1) // Storage: System Account (r:3 w:3) - // Storage: Treasury BountyDescriptions (r:0 w:1) + // Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) + // Storage: Bounties BountyDescriptions (r:0 w:1) fn claim_bounty() -> Weight { - (124_785_000 as Weight) - .saturating_add(T::DbWeight::get().reads(4 as Weight)) - .saturating_add(T::DbWeight::get().writes(5 as Weight)) + (185_000_000 as Weight) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(6 as Weight)) } - // Storage: Treasury Bounties (r:1 w:1) + // Storage: Bounties Bounties (r:1 w:1) + // Storage: ChildBounties ParentChildBounties (r:1 w:0) // Storage: System Account (r:1 w:1) - // Storage: Treasury BountyDescriptions (r:0 w:1) + // Storage: Bounties BountyDescriptions (r:0 w:1) fn close_bounty_proposed() -> Weight { - (39_483_000 as Weight) - .saturating_add(T::DbWeight::get().reads(2 as Weight)) + (82_000_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } - // Storage: Treasury Bounties (r:1 w:1) + // Storage: Bounties Bounties (r:1 w:1) + // Storage: ChildBounties ParentChildBounties (r:1 w:0) // Storage: System Account (r:2 w:2) - // Storage: Treasury BountyDescriptions (r:0 w:1) + // Storage: Bounties BountyDescriptions (r:0 w:1) fn close_bounty_active() -> Weight { - (83_453_000 as Weight) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) + (137_000_000 as Weight) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } - // Storage: Treasury Bounties (r:1 w:1) + // Storage: Bounties Bounties (r:1 w:1) fn extend_bounty_expiry() -> Weight { - (24_151_000 as Weight) + (33_000_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - // Storage: Treasury BountyApprovals (r:1 w:1) - // Storage: Treasury Bounties (r:1 w:1) + // Storage: Bounties BountyApprovals (r:1 w:1) + // Storage: Bounties Bounties (r:1 w:1) // Storage: System Account (r:2 w:2) fn spend_funds(b: u32, ) -> Weight { (0 as Weight) - // Standard Error: 16_000 - .saturating_add((58_004_000 as Weight).saturating_mul(b as Weight)) + // Standard Error: 191_000 + .saturating_add((81_116_000 as Weight).saturating_mul(b as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(b as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -151,87 +155,91 @@ impl WeightInfo for SubstrateWeight { // For backwards compatibility and tests impl WeightInfo for () { - // Storage: Treasury BountyCount (r:1 w:1) + // Storage: Bounties BountyCount (r:1 w:1) // Storage: System Account (r:1 w:1) - // Storage: Treasury BountyDescriptions (r:0 w:1) - // Storage: Treasury Bounties (r:0 w:1) + // Storage: Bounties BountyDescriptions (r:0 w:1) + // Storage: Bounties Bounties (r:0 w:1) fn propose_bounty(d: u32, ) -> Weight { - (44_482_000 as Weight) + (58_161_000 as Weight) // Standard Error: 0 .saturating_add((1_000 as Weight).saturating_mul(d as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } - // Storage: Treasury Bounties (r:1 w:1) - // Storage: Treasury BountyApprovals (r:1 w:1) + // Storage: Bounties Bounties (r:1 w:1) + // Storage: Bounties BountyApprovals (r:1 w:1) fn approve_bounty() -> Weight { - (11_955_000 as Weight) + (20_000_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } - // Storage: Treasury Bounties (r:1 w:1) + // Storage: Bounties Bounties (r:1 w:1) fn propose_curator() -> Weight { - (9_771_000 as Weight) + (14_000_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } - // Storage: Treasury Bounties (r:1 w:1) + // Storage: Bounties Bounties (r:1 w:1) // Storage: System Account (r:1 w:1) fn unassign_curator() -> Weight { - (40_683_000 as Weight) + (62_000_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } - // Storage: Treasury Bounties (r:1 w:1) + // Storage: Bounties Bounties (r:1 w:1) // Storage: System Account (r:1 w:1) fn accept_curator() -> Weight { - (36_390_000 as Weight) + (55_000_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } - // Storage: Treasury Bounties (r:1 w:1) + // Storage: Bounties Bounties (r:1 w:1) + // Storage: ChildBounties ParentChildBounties (r:1 w:0) fn award_bounty() -> Weight { - (25_187_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + (46_000_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } - // Storage: Treasury Bounties (r:1 w:1) + // Storage: Bounties Bounties (r:1 w:1) // Storage: System Account (r:3 w:3) - // Storage: Treasury BountyDescriptions (r:0 w:1) + // Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) + // Storage: Bounties BountyDescriptions (r:0 w:1) fn claim_bounty() -> Weight { - (124_785_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - .saturating_add(RocksDbWeight::get().writes(5 as Weight)) + (185_000_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } - // Storage: Treasury Bounties (r:1 w:1) + // Storage: Bounties Bounties (r:1 w:1) + // Storage: ChildBounties ParentChildBounties (r:1 w:0) // Storage: System Account (r:1 w:1) - // Storage: Treasury BountyDescriptions (r:0 w:1) + // Storage: Bounties BountyDescriptions (r:0 w:1) fn close_bounty_proposed() -> Weight { - (39_483_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(2 as Weight)) + (82_000_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } - // Storage: Treasury Bounties (r:1 w:1) + // Storage: Bounties Bounties (r:1 w:1) + // Storage: ChildBounties ParentChildBounties (r:1 w:0) // Storage: System Account (r:2 w:2) - // Storage: Treasury BountyDescriptions (r:0 w:1) + // Storage: Bounties BountyDescriptions (r:0 w:1) fn close_bounty_active() -> Weight { - (83_453_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + (137_000_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } - // Storage: Treasury Bounties (r:1 w:1) + // Storage: Bounties Bounties (r:1 w:1) fn extend_bounty_expiry() -> Weight { - (24_151_000 as Weight) + (33_000_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } - // Storage: Treasury BountyApprovals (r:1 w:1) - // Storage: Treasury Bounties (r:1 w:1) + // Storage: Bounties BountyApprovals (r:1 w:1) + // Storage: Bounties Bounties (r:1 w:1) // Storage: System Account (r:2 w:2) fn spend_funds(b: u32, ) -> Weight { (0 as Weight) - // Standard Error: 16_000 - .saturating_add((58_004_000 as Weight).saturating_mul(b as Weight)) + // Standard Error: 191_000 + .saturating_add((81_116_000 as Weight).saturating_mul(b as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(b as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) diff --git a/frame/child-bounties/Cargo.toml b/frame/child-bounties/Cargo.toml new file mode 100644 index 000000000000..040337424d39 --- /dev/null +++ b/frame/child-bounties/Cargo.toml @@ -0,0 +1,54 @@ +[package] +name = "pallet-child-bounties" +version = "4.0.0-dev" +authors = ["Parity Technologies "] +edition = "2021" +license = "Apache-2.0" +homepage = "https://substrate.io" +repository = "https://github.com/paritytech/substrate/" +description = "FRAME pallet to manage child bounties" +readme = "README.md" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ + "derive", +] } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } +sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } +frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } +pallet-treasury = { version = "4.0.0-dev", default-features = false, path = "../treasury" } +pallet-bounties = { version = "4.0.0-dev", default-features = false, path = "../bounties" } +sp-io = { version = "4.0.0-dev", path = "../../primitives/io", default-features = false } +sp-core = { version = "4.0.0-dev", path = "../../primitives/core", default-features = false } +frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } +log = { version = "0.4.14", default-features = false } + +[dev-dependencies] +pallet-balances = { version = "4.0.0-dev", path = "../balances" } + +[features] +default = ["std"] +std = [ + "codec/std", + "sp-core/std", + "sp-io/std", + "scale-info/std", + "sp-std/std", + "sp-runtime/std", + "frame-support/std", + "frame-system/std", + "pallet-treasury/std", + "pallet-bounties/std", + "log/std", +] +runtime-benchmarks = [ + "frame-benchmarking", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", +] +try-runtime = ["frame-support/try-runtime"] diff --git a/frame/child-bounties/README.md b/frame/child-bounties/README.md new file mode 100644 index 000000000000..e07996d54957 --- /dev/null +++ b/frame/child-bounties/README.md @@ -0,0 +1,21 @@ +# Child Bounties Pallet (pallet-child-bounties) + +## Child Bounty + +> NOTE: This pallet is tightly coupled with pallet-treasury and pallet-bounties. + +With child bounties, a large bounty proposal can be divided into smaller chunks, for parallel execution, and for efficient governance and tracking of spent funds. + +A child-bounty is a smaller piece of work, extracted from a parent bounty. A curator is assigned after the child-bounty is created by the parent bounty curator, to be delegated with the responsibility of assigning a payout address once the specified set of tasks is completed. + +## Interface + +### Dispatchable Functions + +- `add_child_bounty` - Add a child-bounty for a parent-bounty to for dividing the work in smaller tasks. +- `propose_curator` - Assign an account to a child-bounty as candidate curator. +- `accept_curator` - Accept a child-bounty assignment from the parent-bounty curator, setting a curator deposit. +- `award_child_bounty` - Close and pay out the specified amount for the completed work. +- `claim_child_bounty` - Claim a specific child-bounty amount from the payout address. +- `unassign_curator` - Unassign an accepted curator from a specific child-bounty. +- `close_child_bounty` - Cancel the child-bounty for a specific treasury amount and close the bounty. diff --git a/frame/child-bounties/src/benchmarking.rs b/frame/child-bounties/src/benchmarking.rs new file mode 100644 index 000000000000..3386245cbdca --- /dev/null +++ b/frame/child-bounties/src/benchmarking.rs @@ -0,0 +1,308 @@ +// This file is part of Substrate. + +// Copyright (C) 2021 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. + +//! Child-bounties pallet benchmarking. + +#![cfg(feature = "runtime-benchmarks")] + +use super::*; + +use frame_benchmarking::{account, benchmarks, whitelisted_caller}; +use frame_system::RawOrigin; + +use crate::Pallet as ChildBounties; +use pallet_bounties::Pallet as Bounties; +use pallet_treasury::Pallet as Treasury; + +const SEED: u32 = 0; + +#[derive(Clone)] +struct BenchmarkChildBounty { + /// Bounty ID. + bounty_id: BountyIndex, + /// ChildBounty ID. + child_bounty_id: BountyIndex, + /// The account proposing it. + caller: T::AccountId, + /// The master curator account. + curator: T::AccountId, + /// The child-bounty curator account. + child_curator: T::AccountId, + /// The (total) amount that should be paid if the bounty is rewarded. + value: BalanceOf, + /// The curator fee. included in value. + fee: BalanceOf, + /// The (total) amount that should be paid if the child-bounty is rewarded. + child_bounty_value: BalanceOf, + /// The child-bounty curator fee. included in value. + child_bounty_fee: BalanceOf, + /// Bounty description. + reason: Vec, +} + +fn setup_bounty( + user: u32, + description: u32, +) -> (T::AccountId, T::AccountId, BalanceOf, BalanceOf, Vec) { + let caller = account("caller", user, SEED); + let value: BalanceOf = T::BountyValueMinimum::get().saturating_mul(100u32.into()); + let fee = value / 2u32.into(); + let deposit = T::BountyDepositBase::get() + + T::DataDepositPerByte::get() * T::MaximumReasonLength::get().into(); + let _ = T::Currency::make_free_balance_be(&caller, deposit); + let curator = account("curator", user, SEED); + let _ = T::Currency::make_free_balance_be(&curator, fee / 2u32.into()); + let reason = vec![0; description as usize]; + (caller, curator, fee, value, reason) +} + +fn setup_child_bounty(user: u32, description: u32) -> BenchmarkChildBounty { + let (caller, curator, fee, value, reason) = setup_bounty::(user, description); + let child_curator = account("child-curator", user, SEED); + let _ = T::Currency::make_free_balance_be(&child_curator, fee / 2u32.into()); + let child_bounty_value = (value - fee) / 4u32.into(); + let child_bounty_fee = child_bounty_value / 2u32.into(); + + BenchmarkChildBounty:: { + bounty_id: 0, + child_bounty_id: 0, + caller, + curator, + child_curator, + value, + fee, + child_bounty_value, + child_bounty_fee, + reason, + } +} + +fn activate_bounty( + user: u32, + description: u32, +) -> Result, &'static str> { + let mut child_bounty_setup = setup_child_bounty::(user, description); + let curator_lookup = T::Lookup::unlookup(child_bounty_setup.curator.clone()); + Bounties::::propose_bounty( + RawOrigin::Signed(child_bounty_setup.caller.clone()).into(), + child_bounty_setup.value, + child_bounty_setup.reason.clone(), + )?; + + child_bounty_setup.bounty_id = Bounties::::bounty_count() - 1; + + Bounties::::approve_bounty(RawOrigin::Root.into(), child_bounty_setup.bounty_id)?; + Treasury::::on_initialize(T::BlockNumber::zero()); + Bounties::::propose_curator( + RawOrigin::Root.into(), + child_bounty_setup.bounty_id, + curator_lookup.clone(), + child_bounty_setup.fee, + )?; + Bounties::::accept_curator( + RawOrigin::Signed(child_bounty_setup.curator.clone()).into(), + child_bounty_setup.bounty_id, + )?; + + Ok(child_bounty_setup) +} + +fn activate_child_bounty( + user: u32, + description: u32, +) -> Result, &'static str> { + let mut bounty_setup = activate_bounty::(user, description)?; + let child_curator_lookup = T::Lookup::unlookup(bounty_setup.child_curator.clone()); + + ChildBounties::::add_child_bounty( + RawOrigin::Signed(bounty_setup.curator.clone()).into(), + bounty_setup.bounty_id, + bounty_setup.child_bounty_value, + bounty_setup.reason.clone(), + )?; + + bounty_setup.child_bounty_id = ChildBountyCount::::get() - 1; + + ChildBounties::::propose_curator( + RawOrigin::Signed(bounty_setup.curator.clone()).into(), + bounty_setup.bounty_id, + bounty_setup.child_bounty_id, + child_curator_lookup.clone(), + bounty_setup.child_bounty_fee, + )?; + + ChildBounties::::accept_curator( + RawOrigin::Signed(bounty_setup.child_curator.clone()).into(), + bounty_setup.bounty_id, + bounty_setup.child_bounty_id, + )?; + + Ok(bounty_setup) +} + +fn setup_pot_account() { + let pot_account = Bounties::::account_id(); + let value = T::Currency::minimum_balance().saturating_mul(1_000_000_000u32.into()); + let _ = T::Currency::make_free_balance_be(&pot_account, value); +} + +fn assert_last_event(generic_event: ::Event) { + frame_system::Pallet::::assert_last_event(generic_event.into()); +} + +benchmarks! { + add_child_bounty { + let d in 0 .. T::MaximumReasonLength::get(); + setup_pot_account::(); + let bounty_setup = activate_bounty::(0, d)?; + }: _(RawOrigin::Signed(bounty_setup.curator), bounty_setup.bounty_id, + bounty_setup.child_bounty_value, bounty_setup.reason.clone()) + verify { + assert_last_event::(Event::Added { + index: bounty_setup.bounty_id, + child_index: bounty_setup.child_bounty_id, + }.into()) + } + + propose_curator { + setup_pot_account::(); + let bounty_setup = activate_bounty::(0, T::MaximumReasonLength::get())?; + let child_curator_lookup = T::Lookup::unlookup(bounty_setup.child_curator.clone()); + + ChildBounties::::add_child_bounty( + RawOrigin::Signed(bounty_setup.curator.clone()).into(), + bounty_setup.bounty_id, + bounty_setup.child_bounty_value, + bounty_setup.reason.clone(), + )?; + let child_bounty_id = ChildBountyCount::::get() - 1; + + }: _(RawOrigin::Signed(bounty_setup.curator), bounty_setup.bounty_id, + child_bounty_id, child_curator_lookup, bounty_setup.child_bounty_fee) + + accept_curator { + setup_pot_account::(); + let mut bounty_setup = activate_bounty::(0, T::MaximumReasonLength::get())?; + let child_curator_lookup = T::Lookup::unlookup(bounty_setup.child_curator.clone()); + + ChildBounties::::add_child_bounty( + RawOrigin::Signed(bounty_setup.curator.clone()).into(), + bounty_setup.bounty_id, + bounty_setup.child_bounty_value, + bounty_setup.reason.clone(), + )?; + bounty_setup.child_bounty_id = ChildBountyCount::::get() - 1; + + ChildBounties::::propose_curator( + RawOrigin::Signed(bounty_setup.curator.clone()).into(), + bounty_setup.bounty_id, + bounty_setup.child_bounty_id, + child_curator_lookup.clone(), + bounty_setup.child_bounty_fee, + )?; + }: _(RawOrigin::Signed(bounty_setup.child_curator), bounty_setup.bounty_id, + bounty_setup.child_bounty_id) + + // Worst case when curator is inactive and any sender un-assigns the curator. + unassign_curator { + setup_pot_account::(); + let bounty_setup = activate_child_bounty::(0, T::MaximumReasonLength::get())?; + Bounties::::on_initialize(T::BlockNumber::zero()); + frame_system::Pallet::::set_block_number(T::BountyUpdatePeriod::get() + 1u32.into()); + let caller = whitelisted_caller(); + }: _(RawOrigin::Signed(caller), bounty_setup.bounty_id, + bounty_setup.child_bounty_id) + + award_child_bounty { + setup_pot_account::(); + let bounty_setup = activate_child_bounty::(0, T::MaximumReasonLength::get())?; + let beneficiary_account: T::AccountId = account("beneficiary", 0, SEED); + let beneficiary = T::Lookup::unlookup(beneficiary_account.clone()); + }: _(RawOrigin::Signed(bounty_setup.child_curator), bounty_setup.bounty_id, + bounty_setup.child_bounty_id, beneficiary) + verify { + assert_last_event::(Event::Awarded { + index: bounty_setup.bounty_id, + child_index: bounty_setup.child_bounty_id, + beneficiary: beneficiary_account + }.into()) + } + + claim_child_bounty { + setup_pot_account::(); + let bounty_setup = activate_child_bounty::(0, T::MaximumReasonLength::get())?; + let beneficiary_account: T::AccountId = account("beneficiary", 0, SEED); + let beneficiary = T::Lookup::unlookup(beneficiary_account.clone()); + + ChildBounties::::award_child_bounty( + RawOrigin::Signed(bounty_setup.child_curator.clone()).into(), + bounty_setup.bounty_id, + bounty_setup.child_bounty_id, + beneficiary + )?; + + let beneficiary_account: T::AccountId = account("beneficiary", 0, SEED); + let beneficiary = T::Lookup::unlookup(beneficiary_account.clone()); + + frame_system::Pallet::::set_block_number(T::BountyDepositPayoutDelay::get()); + ensure!(T::Currency::free_balance(&beneficiary_account).is_zero(), + "Beneficiary already has balance."); + + }: _(RawOrigin::Signed(bounty_setup.curator), bounty_setup.bounty_id, + bounty_setup.child_bounty_id) + verify { + ensure!(!T::Currency::free_balance(&beneficiary_account).is_zero(), + "Beneficiary didn't get paid."); + } + + // Best case scenario. + close_child_bounty_added { + setup_pot_account::(); + let mut bounty_setup = activate_bounty::(0, T::MaximumReasonLength::get())?; + + ChildBounties::::add_child_bounty( + RawOrigin::Signed(bounty_setup.curator.clone()).into(), + bounty_setup.bounty_id, + bounty_setup.child_bounty_value, + bounty_setup.reason.clone(), + )?; + bounty_setup.child_bounty_id = ChildBountyCount::::get() - 1; + + }: close_child_bounty(RawOrigin::Root, bounty_setup.bounty_id, + bounty_setup.child_bounty_id) + verify { + assert_last_event::(Event::Canceled { + index: bounty_setup.bounty_id, + child_index: bounty_setup.child_bounty_id + }.into()) + } + + // Worst case scenario. + close_child_bounty_active { + setup_pot_account::(); + let bounty_setup = activate_child_bounty::(0, T::MaximumReasonLength::get())?; + Bounties::::on_initialize(T::BlockNumber::zero()); + }: close_child_bounty(RawOrigin::Root, bounty_setup.bounty_id, bounty_setup.child_bounty_id) + verify { + assert_last_event::(Event::Canceled { + index: bounty_setup.bounty_id, + child_index: bounty_setup.child_bounty_id, + }.into()) + } + + impl_benchmark_test_suite!(ChildBounties, crate::tests::new_test_ext(), crate::tests::Test) +} diff --git a/frame/child-bounties/src/lib.rs b/frame/child-bounties/src/lib.rs new file mode 100644 index 000000000000..3aa160277c82 --- /dev/null +++ b/frame/child-bounties/src/lib.rs @@ -0,0 +1,897 @@ +// This file is part of Substrate. + +// Copyright (C) 2021 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. + +//! # Child Bounties Pallet ( pallet-child-bounties ) +//! +//! ## Child Bounty +//! +//! > NOTE: This pallet is tightly coupled with pallet-treasury and pallet-bounties. +//! +//! With child bounties, a large bounty proposal can be divided into smaller chunks, +//! for parallel execution, and for efficient governance and tracking of spent funds. +//! A child-bounty is a smaller piece of work, extracted from a parent bounty. +//! A curator is assigned after the child-bounty is created by the parent bounty curator, +//! to be delegated with the responsibility of assigning a payout address once the specified +//! set of tasks is completed. +//! +//! ## Interface +//! +//! ### Dispatchable Functions +//! +//! Child Bounty protocol: +//! - `add_child_bounty` - Add a child-bounty for a parent-bounty to for dividing the work in +//! smaller tasks. +//! - `propose_curator` - Assign an account to a child-bounty as candidate curator. +//! - `accept_curator` - Accept a child-bounty assignment from the parent-bounty curator, setting a +//! curator deposit. +//! - `award_child_bounty` - Close and pay out the specified amount for the completed work. +//! - `claim_child_bounty` - Claim a specific child-bounty amount from the payout address. +//! - `unassign_curator` - Unassign an accepted curator from a specific child-bounty. +//! - `close_child_bounty` - Cancel the child-bounty for a specific treasury amount and close the +//! bounty. + +// Most of the business logic in this pallet has been +// originally contributed by "https://github.com/shamb0", +// as part of the PR - https://github.com/paritytech/substrate/pull/7965. +// The code has been moved here and then refactored in order to +// extract child-bounties as a separate pallet. + +#![cfg_attr(not(feature = "std"), no_std)] + +mod benchmarking; +mod tests; +pub mod weights; + +use sp_std::prelude::*; + +use frame_support::traits::{ + Currency, + ExistenceRequirement::{AllowDeath, KeepAlive}, + Get, OnUnbalanced, ReservableCurrency, WithdrawReasons, +}; + +use sp_runtime::{ + traits::{AccountIdConversion, BadOrigin, CheckedSub, Saturating, StaticLookup, Zero}, + DispatchResult, Permill, RuntimeDebug, +}; + +use frame_support::pallet_prelude::*; +use frame_system::pallet_prelude::*; +use pallet_bounties::BountyStatus; +use scale_info::TypeInfo; +pub use weights::WeightInfo; + +pub use pallet::*; + +type BalanceOf = pallet_treasury::BalanceOf; +type BountiesError = pallet_bounties::Error; +type BountyIndex = pallet_bounties::BountyIndex; + +/// A child bounty proposal. +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub struct ChildBounty { + /// The parent of this child-bounty. + parent_bounty: BountyIndex, + /// The (total) amount that should be paid if this child-bounty is rewarded. + value: Balance, + /// The child bounty curator fee. + fee: Balance, + /// The deposit of child-bounty curator. + curator_deposit: Balance, + /// The status of this child-bounty. + status: ChildBountyStatus, +} + +/// The status of a child-bounty. +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub enum ChildBountyStatus { + /// The child-bounty is added and waiting for curator assignment. + Added, + /// A curator has been proposed by the parent-bounty curator. Waiting for + /// acceptance from the child-bounty curator. + CuratorProposed { + /// The assigned child-bounty curator of this bounty. + curator: AccountId, + }, + /// The child-bounty is active and waiting to be awarded. + Active { + /// The curator of this child-bounty. + curator: AccountId, + }, + /// The child-bounty is awarded and waiting to released after a delay. + PendingPayout { + /// The curator of this child-bounty. + curator: AccountId, + /// The beneficiary of the child-bounty. + beneficiary: AccountId, + /// When the child-bounty can be claimed. + unlock_at: BlockNumber, + }, +} + +#[frame_support::pallet] +pub mod pallet { + + use super::*; + + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + #[pallet::generate_storage_info] + pub struct Pallet(_); + + #[pallet::config] + pub trait Config: + frame_system::Config + pallet_treasury::Config + pallet_bounties::Config + { + /// Maximum number of child-bounties that can be added to a parent bounty. + #[pallet::constant] + type MaxActiveChildBountyCount: Get; + + /// Minimum value for a child-bounty. + #[pallet::constant] + type ChildBountyValueMinimum: Get>; + + /// Percentage of child-bounty value to be reserved as curator deposit + /// when curator fee is zero. + #[pallet::constant] + type ChildBountyCuratorDepositBase: Get; + + /// The overarching event type. + type Event: From> + IsType<::Event>; + + /// Weight information for extrinsics in this pallet. + type WeightInfo: WeightInfo; + } + + #[pallet::error] + pub enum Error { + /// The parent bounty is not in active state. + ParentBountyNotActive, + /// The bounty balance is not enough to add new child-bounty. + InsufficientBountyBalance, + /// Number of child-bounties exceeds limit `MaxActiveChildBountyCount`. + TooManyChildBounties, + } + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + /// A child-bounty is added. + Added { index: BountyIndex, child_index: BountyIndex }, + /// A child-bounty is awarded to a beneficiary. + Awarded { index: BountyIndex, child_index: BountyIndex, beneficiary: T::AccountId }, + /// A child-bounty is claimed by beneficiary. + Claimed { + index: BountyIndex, + child_index: BountyIndex, + payout: BalanceOf, + beneficiary: T::AccountId, + }, + /// A child-bounty is cancelled. + Canceled { index: BountyIndex, child_index: BountyIndex }, + } + + /// Number of total child bounties. + #[pallet::storage] + #[pallet::getter(fn child_bounty_count)] + pub type ChildBountyCount = StorageValue<_, BountyIndex, ValueQuery>; + + /// Number of child-bounties per parent bounty. + /// Map of parent bounty index to number of child bounties. + #[pallet::storage] + #[pallet::getter(fn parent_child_bounties)] + pub type ParentChildBounties = + StorageMap<_, Twox64Concat, BountyIndex, u32, ValueQuery>; + + /// Child-bounties that have been added. + #[pallet::storage] + #[pallet::getter(fn child_bounties)] + pub type ChildBounties = StorageDoubleMap< + _, + Twox64Concat, + BountyIndex, + Twox64Concat, + BountyIndex, + ChildBounty, T::BlockNumber>, + >; + + /// The description of each child-bounty. + #[pallet::storage] + #[pallet::getter(fn child_bounty_descriptions)] + pub type ChildBountyDescriptions = + StorageMap<_, Twox64Concat, BountyIndex, BoundedVec>; + + /// The cumulative child-bounty curator fee for each parent bounty. + #[pallet::storage] + #[pallet::getter(fn children_curator_fees)] + pub type ChildrenCuratorFees = + StorageMap<_, Twox64Concat, BountyIndex, BalanceOf, ValueQuery>; + + #[pallet::call] + impl Pallet { + /// Add a new child-bounty. + /// + /// The dispatch origin for this call must be the curator of parent + /// bounty and the parent bounty must be in "active" state. + /// + /// Child-bounty gets added successfully & fund gets transferred from + /// parent bounty to child-bounty account, if parent bounty has enough + /// funds, else the call fails. + /// + /// Upper bound to maximum number of active child-bounties that can be + /// added are managed via runtime trait config + /// [`Config::MaxActiveChildBountyCount`]. + /// + /// If the call is success, the status of child-bounty is updated to + /// "Added". + /// + /// - `parent_bounty_id`: Index of parent bounty for which child-bounty is being added. + /// - `value`: Value for executing the proposal. + /// - `description`: Text description for the child-bounty. + #[pallet::weight(::WeightInfo::add_child_bounty(description.len() as u32))] + pub fn add_child_bounty( + origin: OriginFor, + #[pallet::compact] parent_bounty_id: BountyIndex, + #[pallet::compact] value: BalanceOf, + description: Vec, + ) -> DispatchResult { + let signer = ensure_signed(origin)?; + + // Verify the arguments. + let bounded_description = + description.try_into().map_err(|_| BountiesError::::ReasonTooBig)?; + ensure!(value >= T::ChildBountyValueMinimum::get(), BountiesError::::InvalidValue); + ensure!( + Self::parent_child_bounties(parent_bounty_id) <= + T::MaxActiveChildBountyCount::get() as u32, + Error::::TooManyChildBounties, + ); + + let (curator, _) = Self::ensure_bounty_active(parent_bounty_id)?; + ensure!(signer == curator, BountiesError::::RequireCurator); + + // Read parent bounty account info. + let parent_bounty_account = + pallet_bounties::Pallet::::bounty_account_id(parent_bounty_id); + + // Ensure parent bounty has enough balance after adding child-bounty. + let bounty_balance = T::Currency::free_balance(&parent_bounty_account); + let new_bounty_balance = bounty_balance + .checked_sub(&value) + .ok_or(Error::::InsufficientBountyBalance)?; + T::Currency::ensure_can_withdraw( + &parent_bounty_account, + value, + WithdrawReasons::TRANSFER, + new_bounty_balance, + )?; + + // Get child-bounty ID. + let child_bounty_id = Self::child_bounty_count(); + let child_bounty_account = Self::child_bounty_account_id(child_bounty_id); + + // Transfer funds from parent bounty to child-bounty. + T::Currency::transfer(&parent_bounty_account, &child_bounty_account, value, KeepAlive)?; + + // Increment the active child-bounty count. + >::mutate(parent_bounty_id, |count| count.saturating_inc()); + >::put(child_bounty_id.saturating_add(1)); + + // Create child-bounty instance. + Self::create_child_bounty( + parent_bounty_id, + child_bounty_id, + value, + bounded_description, + ); + Ok(()) + } + + /// Propose curator for funded child-bounty. + /// + /// The dispatch origin for this call must be curator of parent bounty. + /// + /// Parent bounty must be in active state, for this child-bounty call to + /// work. + /// + /// Child-bounty must be in "Added" state, for processing the call. And + /// state of child-bounty is moved to "CuratorProposed" on successful + /// call completion. + /// + /// - `parent_bounty_id`: Index of parent bounty. + /// - `child_bounty_id`: Index of child bounty. + /// - `curator`: Address of child-bounty curator. + /// - `fee`: payment fee to child-bounty curator for execution. + #[pallet::weight(::WeightInfo::propose_curator())] + pub fn propose_curator( + origin: OriginFor, + #[pallet::compact] parent_bounty_id: BountyIndex, + #[pallet::compact] child_bounty_id: BountyIndex, + curator: ::Source, + #[pallet::compact] fee: BalanceOf, + ) -> DispatchResult { + let signer = ensure_signed(origin)?; + let child_bounty_curator = T::Lookup::lookup(curator)?; + + let (curator, _) = Self::ensure_bounty_active(parent_bounty_id)?; + ensure!(signer == curator, BountiesError::::RequireCurator); + + // Mutate the child-bounty instance. + ChildBounties::::try_mutate_exists( + parent_bounty_id, + child_bounty_id, + |maybe_child_bounty| -> DispatchResult { + let mut child_bounty = + maybe_child_bounty.as_mut().ok_or(BountiesError::::InvalidIndex)?; + + // Ensure child-bounty is in expected state. + ensure!( + child_bounty.status == ChildBountyStatus::Added, + BountiesError::::UnexpectedStatus, + ); + + // Ensure child-bounty curator fee is less than child-bounty value. + ensure!(fee < child_bounty.value, BountiesError::::InvalidFee); + + // Add child-bounty curator fee to the cumulative sum. To be + // subtracted from the parent bounty curator when claiming + // bounty. + ChildrenCuratorFees::::mutate(parent_bounty_id, |value| { + *value = value.saturating_add(fee) + }); + + // Update the child-bounty curator fee. + child_bounty.fee = fee; + + // Update the child-bounty state. + child_bounty.status = + ChildBountyStatus::CuratorProposed { curator: child_bounty_curator }; + + Ok(()) + }, + ) + } + + /// Accept the curator role for the child-bounty. + /// + /// The dispatch origin for this call must be the curator of this + /// child-bounty. + /// + /// A deposit will be reserved from the curator and refund upon + /// successful payout or cancellation. + /// + /// Fee for curator is deducted from curator fee of parent bounty. + /// + /// Parent bounty must be in active state, for this child-bounty call to + /// work. + /// + /// Child-bounty must be in "CuratorProposed" state, for processing the + /// call. And state of child-bounty is moved to "Active" on successful + /// call completion. + /// + /// - `parent_bounty_id`: Index of parent bounty. + /// - `child_bounty_id`: Index of child bounty. + #[pallet::weight(::WeightInfo::accept_curator())] + pub fn accept_curator( + origin: OriginFor, + #[pallet::compact] parent_bounty_id: BountyIndex, + #[pallet::compact] child_bounty_id: BountyIndex, + ) -> DispatchResult { + let signer = ensure_signed(origin)?; + + let _ = Self::ensure_bounty_active(parent_bounty_id)?; + // Mutate child-bounty. + ChildBounties::::try_mutate_exists( + parent_bounty_id, + child_bounty_id, + |maybe_child_bounty| -> DispatchResult { + let mut child_bounty = + maybe_child_bounty.as_mut().ok_or(BountiesError::::InvalidIndex)?; + + // Ensure child-bounty is in expected state. + if let ChildBountyStatus::CuratorProposed { ref curator } = child_bounty.status + { + ensure!(signer == *curator, BountiesError::::RequireCurator); + + // Reserve child-bounty curator deposit. Curator deposit + // is reserved based on a percentage of child-bounty + // value instead of fee, to avoid no deposit in case the + // fee is set as zero. + let deposit = T::ChildBountyCuratorDepositBase::get() * child_bounty.value; + T::Currency::reserve(curator, deposit)?; + child_bounty.curator_deposit = deposit; + + child_bounty.status = + ChildBountyStatus::Active { curator: curator.clone() }; + Ok(()) + } else { + Err(BountiesError::::UnexpectedStatus.into()) + } + }, + ) + } + + /// Unassign curator from a child-bounty. + /// + /// The dispatch origin for this call can be either `RejectOrigin`, or + /// the curator of the parent bounty, or any signed origin. + /// + /// For the origin other than T::RejectOrigin and the child-bounty + /// curator, parent-bounty must be in active state, for this call to + /// work. We allow child-bounty curator and T::RejectOrigin to execute + /// this call irrespective of the parent-bounty state. + /// + /// If this function is called by the `RejectOrigin` or the + /// parent-bounty curator, we assume that the child-bounty curator is + /// malicious or inactive. As a result, child-bounty curator deposit is + /// slashed. + /// + /// If the origin is the child-bounty curator, we take this as a sign + /// that they are unable to do their job, and are willingly giving up. + /// We could slash the deposit, but for now we allow them to unreserve + /// their deposit and exit without issue. (We may want to change this if + /// it is abused.) + /// + /// Finally, the origin can be anyone iff the child-bounty curator is + /// "inactive". Expiry update due of parent bounty is used to estimate + /// inactive state of child-bounty curator. + /// + /// This allows anyone in the community to call out that a child-bounty + /// curator is not doing their due diligence, and we should pick a new + /// one. In this case the child-bounty curator deposit is slashed. + /// + /// State of child-bounty is moved to Added state on successful call + /// completion. + /// + /// - `parent_bounty_id`: Index of parent bounty. + /// - `child_bounty_id`: Index of child bounty. + #[pallet::weight(::WeightInfo::unassign_curator())] + pub fn unassign_curator( + origin: OriginFor, + #[pallet::compact] parent_bounty_id: BountyIndex, + #[pallet::compact] child_bounty_id: BountyIndex, + ) -> DispatchResult { + let maybe_sender = ensure_signed(origin.clone()) + .map(Some) + .or_else(|_| T::RejectOrigin::ensure_origin(origin).map(|_| None))?; + + ChildBounties::::try_mutate_exists( + parent_bounty_id, + child_bounty_id, + |maybe_child_bounty| -> DispatchResult { + let mut child_bounty = + maybe_child_bounty.as_mut().ok_or(BountiesError::::InvalidIndex)?; + + let slash_curator = |curator: &T::AccountId, + curator_deposit: &mut BalanceOf| { + let imbalance = T::Currency::slash_reserved(curator, *curator_deposit).0; + T::OnSlash::on_unbalanced(imbalance); + *curator_deposit = Zero::zero(); + }; + + match child_bounty.status { + ChildBountyStatus::Added => { + // No curator to unassign at this point. + return Err(BountiesError::::UnexpectedStatus.into()) + }, + ChildBountyStatus::CuratorProposed { ref curator } => { + // A child-bounty curator has been proposed, but not accepted yet. + // Either `RejectOrigin`, parent-bounty curator or the proposed + // child-bounty curator can unassign the child-bounty curator. + ensure!( + maybe_sender.map_or(true, |sender| { + sender == *curator || + Self::ensure_bounty_active(parent_bounty_id) + .map_or(false, |(parent_curator, _)| { + sender == parent_curator + }) + }), + BadOrigin + ); + // Continue to change bounty status below. + }, + ChildBountyStatus::Active { ref curator } => { + // The child-bounty is active. + match maybe_sender { + // If the `RejectOrigin` is calling this function, slash the curator + // deposit. + None => { + slash_curator(curator, &mut child_bounty.curator_deposit); + // Continue to change child-bounty status below. + }, + Some(sender) if sender == *curator => { + // This is the child-bounty curator, willingly giving up their + // role. Give back their deposit. + T::Currency::unreserve(&curator, child_bounty.curator_deposit); + // Reset curator deposit. + child_bounty.curator_deposit = Zero::zero(); + // Continue to change bounty status below. + }, + Some(sender) => { + let (parent_curator, update_due) = + Self::ensure_bounty_active(parent_bounty_id)?; + if sender == parent_curator || + update_due < frame_system::Pallet::::block_number() + { + // Slash the child-bounty curator if + // + the call is made by the parent-bounty curator. + // + or the curator is inactive. + slash_curator(curator, &mut child_bounty.curator_deposit); + // Continue to change bounty status below. + } else { + // Curator has more time to give an update. + return Err(BountiesError::::Premature.into()) + } + }, + } + }, + ChildBountyStatus::PendingPayout { ref curator, .. } => { + let (parent_curator, _) = Self::ensure_bounty_active(parent_bounty_id)?; + ensure!( + maybe_sender.map_or(true, |sender| parent_curator == sender), + BadOrigin, + ); + slash_curator(curator, &mut child_bounty.curator_deposit); + // Continue to change child-bounty status below. + }, + }; + // Move the child-bounty state to Added. + child_bounty.status = ChildBountyStatus::Added; + Ok(()) + }, + ) + } + + /// Award child-bounty to a beneficiary. + /// + /// The beneficiary will be able to claim the funds after a delay. + /// + /// The dispatch origin for this call must be the master curator or + /// curator of this child-bounty. + /// + /// Parent bounty must be in active state, for this child-bounty call to + /// work. + /// + /// Child-bounty must be in active state, for processing the call. And + /// state of child-bounty is moved to "PendingPayout" on successful call + /// completion. + /// + /// - `parent_bounty_id`: Index of parent bounty. + /// - `child_bounty_id`: Index of child bounty. + /// - `beneficiary`: Beneficiary account. + #[pallet::weight(::WeightInfo::award_child_bounty())] + pub fn award_child_bounty( + origin: OriginFor, + #[pallet::compact] parent_bounty_id: BountyIndex, + #[pallet::compact] child_bounty_id: BountyIndex, + beneficiary: ::Source, + ) -> DispatchResult { + let signer = ensure_signed(origin)?; + let beneficiary = T::Lookup::lookup(beneficiary)?; + + // Ensure parent bounty exists, and is active. + let (parent_curator, _) = Self::ensure_bounty_active(parent_bounty_id)?; + + ChildBounties::::try_mutate_exists( + parent_bounty_id, + child_bounty_id, + |maybe_child_bounty| -> DispatchResult { + let mut child_bounty = + maybe_child_bounty.as_mut().ok_or(BountiesError::::InvalidIndex)?; + + // Ensure child-bounty is in active state. + if let ChildBountyStatus::Active { ref curator } = child_bounty.status { + ensure!( + signer == *curator || signer == parent_curator, + BountiesError::::RequireCurator, + ); + // Move the child-bounty state to pending payout. + child_bounty.status = ChildBountyStatus::PendingPayout { + curator: signer, + beneficiary: beneficiary.clone(), + unlock_at: frame_system::Pallet::::block_number() + + T::BountyDepositPayoutDelay::get(), + }; + Ok(()) + } else { + Err(BountiesError::::UnexpectedStatus.into()) + } + }, + )?; + + // Trigger the event Awarded. + Self::deposit_event(Event::::Awarded { + index: parent_bounty_id, + child_index: child_bounty_id, + beneficiary, + }); + + Ok(()) + } + + /// Claim the payout from an awarded child-bounty after payout delay. + /// + /// The dispatch origin for this call may be any signed origin. + /// + /// Call works independent of parent bounty state, No need for parent + /// bounty to be in active state. + /// + /// The Beneficiary is paid out with agreed bounty value. Curator fee is + /// paid & curator deposit is unreserved. + /// + /// Child-bounty must be in "PendingPayout" state, for processing the + /// call. And instance of child-bounty is removed from the state on + /// successful call completion. + /// + /// - `parent_bounty_id`: Index of parent bounty. + /// - `child_bounty_id`: Index of child bounty. + #[pallet::weight(::WeightInfo::claim_child_bounty())] + pub fn claim_child_bounty( + origin: OriginFor, + #[pallet::compact] parent_bounty_id: BountyIndex, + #[pallet::compact] child_bounty_id: BountyIndex, + ) -> DispatchResult { + let _ = ensure_signed(origin)?; + + // Ensure child-bounty is in expected state. + ChildBounties::::try_mutate_exists( + parent_bounty_id, + child_bounty_id, + |maybe_child_bounty| -> DispatchResult { + let child_bounty = + maybe_child_bounty.as_mut().ok_or(BountiesError::::InvalidIndex)?; + + if let ChildBountyStatus::PendingPayout { + ref curator, + ref beneficiary, + ref unlock_at, + } = child_bounty.status + { + // Ensure block number is elapsed for processing the + // claim. + ensure!( + frame_system::Pallet::::block_number() >= *unlock_at, + BountiesError::::Premature, + ); + + // Make curator fee payment. + let child_bounty_account = Self::child_bounty_account_id(child_bounty_id); + let balance = T::Currency::free_balance(&child_bounty_account); + let curator_fee = child_bounty.fee.min(balance); + let payout = balance.saturating_sub(curator_fee); + + // Unreserve the curator deposit. Should not fail + // because the deposit is always reserved when curator is + // assigned. + let _ = T::Currency::unreserve(&curator, child_bounty.curator_deposit); + + // Make payout to child-bounty curator. + // Should not fail because curator fee is always less than bounty value. + let fee_transfer_result = T::Currency::transfer( + &child_bounty_account, + &curator, + curator_fee, + AllowDeath, + ); + debug_assert!(fee_transfer_result.is_ok()); + + // Make payout to beneficiary. + // Should not fail. + let payout_transfer_result = T::Currency::transfer( + &child_bounty_account, + beneficiary, + payout, + AllowDeath, + ); + debug_assert!(payout_transfer_result.is_ok()); + + // Trigger the Claimed event. + Self::deposit_event(Event::::Claimed { + index: parent_bounty_id, + child_index: child_bounty_id, + payout, + beneficiary: beneficiary.clone(), + }); + + // Update the active child-bounty tracking count. + >::mutate(parent_bounty_id, |count| { + count.saturating_dec() + }); + + // Remove the child-bounty description. + >::remove(child_bounty_id); + + // Remove the child-bounty instance from the state. + *maybe_child_bounty = None; + + Ok(()) + } else { + Err(BountiesError::::UnexpectedStatus.into()) + } + }, + ) + } + + /// Cancel a proposed or active child-bounty. Child-bounty account funds + /// are transferred to parent bounty account. The child-bounty curator + /// deposit may be unreserved if possible. + /// + /// The dispatch origin for this call must be either parent curator or + /// `T::RejectOrigin`. + /// + /// If the state of child-bounty is `Active`, curator deposit is + /// unreserved. + /// + /// If the state of child-bounty is `PendingPayout`, call fails & + /// returns `PendingPayout` error. + /// + /// For the origin other than T::RejectOrigin, parent bounty must be in + /// active state, for this child-bounty call to work. For origin + /// T::RejectOrigin execution is forced. + /// + /// Instance of child-bounty is removed from the state on successful + /// call completion. + /// + /// - `parent_bounty_id`: Index of parent bounty. + /// - `child_bounty_id`: Index of child bounty. + #[pallet::weight(::WeightInfo::close_child_bounty_added() + .max(::WeightInfo::close_child_bounty_active()))] + pub fn close_child_bounty( + origin: OriginFor, + #[pallet::compact] parent_bounty_id: BountyIndex, + #[pallet::compact] child_bounty_id: BountyIndex, + ) -> DispatchResult { + let maybe_sender = ensure_signed(origin.clone()) + .map(Some) + .or_else(|_| T::RejectOrigin::ensure_origin(origin).map(|_| None))?; + + // Ensure parent bounty exist, get parent curator. + let (parent_curator, _) = Self::ensure_bounty_active(parent_bounty_id)?; + + ensure!(maybe_sender.map_or(true, |sender| parent_curator == sender), BadOrigin); + + Self::impl_close_child_bounty(parent_bounty_id, child_bounty_id)?; + Ok(()) + } + } +} + +impl Pallet { + /// The account ID of a child-bounty account. + pub fn child_bounty_account_id(id: BountyIndex) -> T::AccountId { + // This function is taken from the parent (bounties) pallet, but the + // prefix is changed to have different AccountId when the index of + // parent and child is same. + T::PalletId::get().into_sub_account(("cb", id)) + } + + fn create_child_bounty( + parent_bounty_id: BountyIndex, + child_bounty_id: BountyIndex, + child_bounty_value: BalanceOf, + description: BoundedVec, + ) { + let child_bounty = ChildBounty { + parent_bounty: parent_bounty_id, + value: child_bounty_value, + fee: 0u32.into(), + curator_deposit: 0u32.into(), + status: ChildBountyStatus::Added, + }; + ChildBounties::::insert(parent_bounty_id, child_bounty_id, &child_bounty); + ChildBountyDescriptions::::insert(child_bounty_id, description); + Self::deposit_event(Event::Added { index: parent_bounty_id, child_index: child_bounty_id }); + } + + fn ensure_bounty_active( + bounty_id: BountyIndex, + ) -> Result<(T::AccountId, T::BlockNumber), DispatchError> { + let parent_bounty = pallet_bounties::Pallet::::bounties(bounty_id) + .ok_or(BountiesError::::InvalidIndex)?; + if let BountyStatus::Active { curator, update_due } = parent_bounty.get_status() { + Ok((curator, update_due)) + } else { + Err(Error::::ParentBountyNotActive.into()) + } + } + + fn impl_close_child_bounty( + parent_bounty_id: BountyIndex, + child_bounty_id: BountyIndex, + ) -> DispatchResult { + ChildBounties::::try_mutate_exists( + parent_bounty_id, + child_bounty_id, + |maybe_child_bounty| -> DispatchResult { + let child_bounty = + maybe_child_bounty.as_mut().ok_or(BountiesError::::InvalidIndex)?; + + match &child_bounty.status { + ChildBountyStatus::Added | ChildBountyStatus::CuratorProposed { .. } => { + // Nothing extra to do besides the removal of the child-bounty below. + }, + ChildBountyStatus::Active { curator } => { + // Cancelled by master curator or RejectOrigin, + // refund deposit of the working child-bounty curator. + let _ = T::Currency::unreserve(curator, child_bounty.curator_deposit); + // Then execute removal of the child-bounty below. + }, + ChildBountyStatus::PendingPayout { .. } => { + // Child-bounty is already in pending payout. If parent + // curator or RejectOrigin wants to close this + // child-bounty, it should mean the child-bounty curator + // was acting maliciously. So first unassign the + // child-bounty curator, slashing their deposit. + return Err(BountiesError::::PendingPayout.into()) + }, + } + + // Revert the curator fee back to parent-bounty curator & + // reduce the active child-bounty count. + ChildrenCuratorFees::::mutate(parent_bounty_id, |value| { + *value = value.saturating_sub(child_bounty.fee) + }); + >::mutate(parent_bounty_id, |count| { + *count = count.saturating_sub(1) + }); + + // Transfer fund from child-bounty to parent bounty. + let parent_bounty_account = + pallet_bounties::Pallet::::bounty_account_id(parent_bounty_id); + let child_bounty_account = Self::child_bounty_account_id(child_bounty_id); + let balance = T::Currency::free_balance(&child_bounty_account); + let transfer_result = T::Currency::transfer( + &child_bounty_account, + &parent_bounty_account, + balance, + AllowDeath, + ); // Should not fail; child bounty account gets this balance during creation. + debug_assert!(transfer_result.is_ok()); + + // Remove the child-bounty description. + >::remove(child_bounty_id); + + *maybe_child_bounty = None; + + Self::deposit_event(Event::::Canceled { + index: parent_bounty_id, + child_index: child_bounty_id, + }); + Ok(()) + }, + ) + } +} + +// Implement ChildBountyManager to connect with the bounties pallet. This is +// where we pass the active child-bounties and child curator fees to the parent +// bounty. +impl pallet_bounties::ChildBountyManager> for Pallet { + fn child_bounties_count( + bounty_id: pallet_bounties::BountyIndex, + ) -> pallet_bounties::BountyIndex { + Self::parent_child_bounties(bounty_id) + } + + fn children_curator_fees(bounty_id: pallet_bounties::BountyIndex) -> BalanceOf { + // This is asked for when the parent bounty is being claimed. No use of + // keeping it in state after that. Hence removing. + let children_fee_total = Self::children_curator_fees(bounty_id); + >::remove(bounty_id); + children_fee_total + } +} diff --git a/frame/child-bounties/src/tests.rs b/frame/child-bounties/src/tests.rs new file mode 100644 index 000000000000..ada13e968c4d --- /dev/null +++ b/frame/child-bounties/src/tests.rs @@ -0,0 +1,1219 @@ +// This file is part of Substrate. + +// Copyright (C) 2021 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. + +//! Child-bounties pallet tests. + +#![cfg(test)] + +use super::*; +use crate as pallet_child_bounties; +use std::cell::RefCell; + +use frame_support::{ + assert_noop, assert_ok, pallet_prelude::GenesisBuild, parameter_types, traits::OnInitialize, + weights::Weight, PalletId, +}; + +use sp_core::H256; +use sp_runtime::{ + testing::Header, + traits::{BadOrigin, BlakeTwo256, IdentityLookup}, + Perbill, Permill, +}; + +use super::Event as ChildBountiesEvent; + +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlock; +type BountiesError = pallet_bounties::Error; + +frame_support::construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + Bounties: pallet_bounties::{Pallet, Call, Storage, Event}, + Treasury: pallet_treasury::{Pallet, Call, Storage, Config, Event}, + ChildBounties: pallet_child_bounties::{Pallet, Call, Storage, Event}, + } +); + +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); +} + +impl frame_system::Config for Test { + type BaseCallFilter = frame_support::traits::Everything; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Call = Call; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u128; + type Lookup = IdentityLookup; + type Header = Header; + type Event = Event; + type BlockHashCount = BlockHashCount; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); +} +parameter_types! { + pub const ExistentialDeposit: u64 = 1; +} +impl pallet_balances::Config for Test { + type MaxLocks = (); + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; + type Balance = u64; + type Event = Event; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); +} +thread_local! { + static TEN_TO_FOURTEEN: RefCell> = RefCell::new(vec![10,11,12,13,14]); +} +parameter_types! { + pub const ProposalBond: Permill = Permill::from_percent(5); + pub const ProposalBondMinimum: u64 = 1; + pub const SpendPeriod: u64 = 2; + pub const Burn: Permill = Permill::from_percent(50); + pub const DataDepositPerByte: u64 = 1; + pub const TreasuryPalletId: PalletId = PalletId(*b"py/trsry"); + pub const MaxApprovals: u32 = 100; +} + +impl pallet_treasury::Config for Test { + type PalletId = TreasuryPalletId; + type Currency = pallet_balances::Pallet; + type ApproveOrigin = frame_system::EnsureRoot; + type RejectOrigin = frame_system::EnsureRoot; + type Event = Event; + type OnSlash = (); + type ProposalBond = ProposalBond; + type ProposalBondMinimum = ProposalBondMinimum; + type SpendPeriod = SpendPeriod; + type Burn = Burn; + type BurnDestination = (); + type WeightInfo = (); + type SpendFunds = Bounties; + type MaxApprovals = MaxApprovals; +} +parameter_types! { + pub const BountyDepositBase: u64 = 80; + pub const BountyDepositPayoutDelay: u64 = 3; + pub const BountyUpdatePeriod: u32 = 10; + pub const BountyCuratorDeposit: Permill = Permill::from_percent(50); + pub const BountyValueMinimum: u64 = 5; + pub const MaximumReasonLength: u32 = 300; +} +impl pallet_bounties::Config for Test { + type Event = Event; + type BountyDepositBase = BountyDepositBase; + type BountyDepositPayoutDelay = BountyDepositPayoutDelay; + type BountyUpdatePeriod = BountyUpdatePeriod; + type BountyCuratorDeposit = BountyCuratorDeposit; + type BountyValueMinimum = BountyValueMinimum; + type DataDepositPerByte = DataDepositPerByte; + type MaximumReasonLength = MaximumReasonLength; + type WeightInfo = (); + type ChildBountyManager = ChildBounties; +} +parameter_types! { + pub const MaxActiveChildBountyCount: u32 = 2; + pub const ChildBountyValueMinimum: u64 = 1; + pub const ChildBountyCuratorDepositBase: Permill = Permill::from_percent(10); +} +impl pallet_child_bounties::Config for Test { + type Event = Event; + type MaxActiveChildBountyCount = MaxActiveChildBountyCount; + type ChildBountyValueMinimum = ChildBountyValueMinimum; + type ChildBountyCuratorDepositBase = ChildBountyCuratorDepositBase; + type WeightInfo = (); +} + +pub fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + pallet_balances::GenesisConfig:: { + // Total issuance will be 200 with treasury account initialized at ED. + balances: vec![(0, 100), (1, 98), (2, 1)], + } + .assimilate_storage(&mut t) + .unwrap(); + GenesisBuild::::assimilate_storage(&pallet_treasury::GenesisConfig, &mut t).unwrap(); + t.into() +} + +fn last_event() -> ChildBountiesEvent { + System::events() + .into_iter() + .map(|r| r.event) + .filter_map(|e| if let Event::ChildBounties(inner) = e { Some(inner) } else { None }) + .last() + .unwrap() +} + +#[test] +fn genesis_config_works() { + new_test_ext().execute_with(|| { + assert_eq!(Treasury::pot(), 0); + assert_eq!(Treasury::proposal_count(), 0); + }); +} + +#[test] +fn minting_works() { + new_test_ext().execute_with(|| { + // Check that accumulate works when we have Some value in Dummy already. + Balances::make_free_balance_be(&Treasury::account_id(), 101); + assert_eq!(Treasury::pot(), 100); + }); +} + +#[test] +fn add_child_bounty() { + new_test_ext().execute_with(|| { + // TestProcedure. + // 1, Create bounty & move to active state with enough bounty fund & master-curator. + // 2, Master-curator adds child-bounty child-bounty-1, test for error like RequireCurator + // ,InsufficientProposersBalance, InsufficientBountyBalance with invalid arguments. + // 3, Master-curator adds child-bounty child-bounty-1, moves to "Approved" state & + // test for the event Added. + // 4, Test for DB state of `Bounties` & `ChildBounties`. + // 5, Observe fund transaction moment between Bounty, Child-bounty, + // Curator, child-bounty curator & beneficiary. + + // Make the parent bounty. + System::set_block_number(1); + Balances::make_free_balance_be(&Treasury::account_id(), 101); + + assert_ok!(Bounties::propose_bounty(Origin::signed(0), 50, b"12345".to_vec())); + + assert_ok!(Bounties::approve_bounty(Origin::root(), 0)); + + System::set_block_number(2); + >::on_initialize(2); + + assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, 4)); + + Balances::make_free_balance_be(&4, 10); + + assert_ok!(Bounties::accept_curator(Origin::signed(4), 0)); + + assert_eq!(Balances::free_balance(&4), 8); + assert_eq!(Balances::reserved_balance(&4), 2); + + // Add child-bounty. + // Acc-4 is the master curator. + // Call from invalid origin & check for error "RequireCurator". + assert_noop!( + ChildBounties::add_child_bounty(Origin::signed(0), 0, 10, b"12345-p1".to_vec()), + BountiesError::RequireCurator, + ); + + // Update the master curator balance. + Balances::make_free_balance_be(&4, 101); + + // Master curator fee is reserved on parent bounty account. + assert_eq!(Balances::free_balance(Bounties::bounty_account_id(0)), 50); + assert_eq!(Balances::reserved_balance(Bounties::bounty_account_id(0)), 0); + + assert_noop!( + ChildBounties::add_child_bounty(Origin::signed(4), 0, 50, b"12345-p1".to_vec()), + pallet_balances::Error::::KeepAlive, + ); + + assert_noop!( + ChildBounties::add_child_bounty(Origin::signed(4), 0, 100, b"12345-p1".to_vec()), + Error::::InsufficientBountyBalance, + ); + + // Add child-bounty with valid value, which can be funded by parent bounty. + assert_ok!(ChildBounties::add_child_bounty(Origin::signed(4), 0, 10, b"12345-p1".to_vec())); + + // Check for the event child-bounty added. + assert_eq!(last_event(), ChildBountiesEvent::Added { index: 0, child_index: 0 }); + + assert_eq!(Balances::free_balance(4), 101); + assert_eq!(Balances::reserved_balance(4), 2); + + // DB check. + // Check the child-bounty status. + assert_eq!( + ChildBounties::child_bounties(0, 0).unwrap(), + ChildBounty { + parent_bounty: 0, + value: 10, + fee: 0, + curator_deposit: 0, + status: ChildBountyStatus::Added, + } + ); + + // Check the child-bounty count. + assert_eq!(ChildBounties::parent_child_bounties(0), 1); + + // Check the child-bounty description status. + assert_eq!(ChildBounties::child_bounty_descriptions(0).unwrap(), b"12345-p1".to_vec(),); + }); +} + +#[test] +fn child_bounty_assign_curator() { + new_test_ext().execute_with(|| { + // TestProcedure + // 1, Create bounty & move to active state with enough bounty fund & master-curator. + // 2, Master-curator adds child-bounty child-bounty-1, moves to "Active" state. + // 3, Test for DB state of `ChildBounties`. + + // Make the parent bounty. + System::set_block_number(1); + Balances::make_free_balance_be(&Treasury::account_id(), 101); + Balances::make_free_balance_be(&4, 101); + Balances::make_free_balance_be(&8, 101); + + assert_ok!(Bounties::propose_bounty(Origin::signed(0), 50, b"12345".to_vec())); + + assert_ok!(Bounties::approve_bounty(Origin::root(), 0)); + + System::set_block_number(2); + >::on_initialize(2); + + assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, 4)); + + assert_ok!(Bounties::accept_curator(Origin::signed(4), 0)); + + // Bounty account status before adding child-bounty. + assert_eq!(Balances::free_balance(Bounties::bounty_account_id(0)), 50); + assert_eq!(Balances::reserved_balance(Bounties::bounty_account_id(0)), 0); + + // Check the balance of master curator. + // Curator deposit is reserved for master curator on parent bounty. + assert_eq!(Balances::free_balance(4), 99); + assert_eq!(Balances::reserved_balance(4), 2); + + // Add child-bounty. + // Acc-4 is the master curator & make sure enough deposit. + assert_ok!(ChildBounties::add_child_bounty(Origin::signed(4), 0, 10, b"12345-p1".to_vec())); + + assert_eq!(last_event(), ChildBountiesEvent::Added { index: 0, child_index: 0 }); + + // Bounty account status after adding child-bounty. + assert_eq!(Balances::free_balance(Bounties::bounty_account_id(0)), 40); + assert_eq!(Balances::reserved_balance(Bounties::bounty_account_id(0)), 0); + + // Child-bounty account status. + assert_eq!(Balances::free_balance(ChildBounties::child_bounty_account_id(0)), 10); + assert_eq!(Balances::reserved_balance(ChildBounties::child_bounty_account_id(0)), 0); + + assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 8, 2)); + + assert_eq!( + ChildBounties::child_bounties(0, 0).unwrap(), + ChildBounty { + parent_bounty: 0, + value: 10, + fee: 2, + curator_deposit: 0, + status: ChildBountyStatus::CuratorProposed { curator: 8 }, + } + ); + + // Check the balance of master curator. + assert_eq!(Balances::free_balance(4), 99); + assert_eq!(Balances::reserved_balance(4), 2); + + assert_noop!( + ChildBounties::accept_curator(Origin::signed(3), 0, 0), + BountiesError::RequireCurator, + ); + + assert_ok!(ChildBounties::accept_curator(Origin::signed(8), 0, 0)); + + assert_eq!( + ChildBounties::child_bounties(0, 0).unwrap(), + ChildBounty { + parent_bounty: 0, + value: 10, + fee: 2, + curator_deposit: 1, + status: ChildBountyStatus::Active { curator: 8 }, + } + ); + + // Deposit for child-bounty curator is reserved. + assert_eq!(Balances::free_balance(8), 100); + assert_eq!(Balances::reserved_balance(8), 1); + + // Bounty account status at exit. + assert_eq!(Balances::free_balance(Bounties::bounty_account_id(0)), 40); + assert_eq!(Balances::reserved_balance(Bounties::bounty_account_id(0)), 0); + + // Child-bounty account status at exit. + assert_eq!(Balances::free_balance(ChildBounties::child_bounty_account_id(0)), 10); + assert_eq!(Balances::reserved_balance(ChildBounties::child_bounty_account_id(0)), 0); + + // Treasury account status at exit. + assert_eq!(Balances::free_balance(Treasury::account_id()), 26); + assert_eq!(Balances::reserved_balance(Treasury::account_id()), 0); + }); +} + +#[test] +fn award_claim_child_bounty() { + new_test_ext().execute_with(|| { + // Make the parent bounty. + System::set_block_number(1); + Balances::make_free_balance_be(&Treasury::account_id(), 101); + assert_eq!(Balances::free_balance(Treasury::account_id()), 101); + assert_eq!(Balances::reserved_balance(Treasury::account_id()), 0); + + // Bounty curator initial balance. + Balances::make_free_balance_be(&4, 101); // Parent-bounty curator. + Balances::make_free_balance_be(&8, 101); // Child-bounty curator. + + assert_ok!(Bounties::propose_bounty(Origin::signed(0), 50, b"12345".to_vec())); + + assert_ok!(Bounties::approve_bounty(Origin::root(), 0)); + + System::set_block_number(2); + >::on_initialize(2); + + assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, 6)); + assert_ok!(Bounties::accept_curator(Origin::signed(4), 0)); + + // Child-bounty. + assert_ok!(ChildBounties::add_child_bounty(Origin::signed(4), 0, 10, b"12345-p1".to_vec())); + + assert_eq!(last_event(), ChildBountiesEvent::Added { index: 0, child_index: 0 }); + + // Propose and accept curator for child-bounty. + assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 8, 2)); + assert_ok!(ChildBounties::accept_curator(Origin::signed(8), 0, 0)); + + // Award child-bounty. + // Test for non child-bounty curator. + assert_noop!( + ChildBounties::award_child_bounty(Origin::signed(3), 0, 0, 7), + BountiesError::RequireCurator, + ); + + assert_ok!(ChildBounties::award_child_bounty(Origin::signed(8), 0, 0, 7)); + + assert_eq!( + ChildBounties::child_bounties(0, 0).unwrap(), + ChildBounty { + parent_bounty: 0, + value: 10, + fee: 2, + curator_deposit: 1, + status: ChildBountyStatus::PendingPayout { + curator: 8, + beneficiary: 7, + unlock_at: 5 + }, + } + ); + + // Claim child-bounty. + // Test for Premature condition. + assert_noop!( + ChildBounties::claim_child_bounty(Origin::signed(7), 0, 0), + BountiesError::Premature + ); + + System::set_block_number(9); + + assert_ok!(ChildBounties::claim_child_bounty(Origin::signed(7), 0, 0)); + + // Ensure child-bounty curator is paid with curator fee & deposit refund. + assert_eq!(Balances::free_balance(8), 103); + assert_eq!(Balances::reserved_balance(8), 0); + + // Ensure executor is paid with beneficiary amount. + assert_eq!(Balances::free_balance(7), 8); + assert_eq!(Balances::reserved_balance(7), 0); + + // Child-bounty account status. + assert_eq!(Balances::free_balance(ChildBounties::child_bounty_account_id(0)), 0); + assert_eq!(Balances::reserved_balance(ChildBounties::child_bounty_account_id(0)), 0); + + // Check the child-bounty count. + assert_eq!(ChildBounties::parent_child_bounties(0), 0); + }); +} + +#[test] +fn close_child_bounty_added() { + new_test_ext().execute_with(|| { + // Make the parent bounty. + System::set_block_number(1); + Balances::make_free_balance_be(&Treasury::account_id(), 101); + assert_eq!(Balances::free_balance(Treasury::account_id()), 101); + assert_eq!(Balances::reserved_balance(Treasury::account_id()), 0); + + // Bounty curator initial balance. + Balances::make_free_balance_be(&4, 101); // Parent-bounty curator. + Balances::make_free_balance_be(&8, 101); // Child-bounty curator. + + assert_ok!(Bounties::propose_bounty(Origin::signed(0), 50, b"12345".to_vec())); + + assert_ok!(Bounties::approve_bounty(Origin::root(), 0)); + + System::set_block_number(2); + >::on_initialize(2); + + assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, 6)); + + assert_ok!(Bounties::accept_curator(Origin::signed(4), 0)); + + // Child-bounty. + assert_ok!(ChildBounties::add_child_bounty(Origin::signed(4), 0, 10, b"12345-p1".to_vec())); + + assert_eq!(last_event(), ChildBountiesEvent::Added { index: 0, child_index: 0 }); + + System::set_block_number(4); + + // Close child-bounty. + // Wrong origin. + assert_noop!(ChildBounties::close_child_bounty(Origin::signed(7), 0, 0), BadOrigin); + assert_noop!(ChildBounties::close_child_bounty(Origin::signed(8), 0, 0), BadOrigin); + + // Correct origin - parent curator. + assert_ok!(ChildBounties::close_child_bounty(Origin::signed(4), 0, 0)); + + // Check the child-bounty count. + assert_eq!(ChildBounties::parent_child_bounties(0), 0); + + // Parent-bounty account status. + assert_eq!(Balances::free_balance(Bounties::bounty_account_id(0)), 50); + assert_eq!(Balances::reserved_balance(Bounties::bounty_account_id(0)), 0); + + // Child-bounty account status. + assert_eq!(Balances::free_balance(ChildBounties::child_bounty_account_id(0)), 0); + assert_eq!(Balances::reserved_balance(ChildBounties::child_bounty_account_id(0)), 0); + }); +} + +#[test] +fn close_child_bounty_active() { + new_test_ext().execute_with(|| { + // Make the parent bounty. + System::set_block_number(1); + Balances::make_free_balance_be(&Treasury::account_id(), 101); + assert_eq!(Balances::free_balance(Treasury::account_id()), 101); + assert_eq!(Balances::reserved_balance(Treasury::account_id()), 0); + + // Bounty curator initial balance. + Balances::make_free_balance_be(&4, 101); // Parent-bounty curator. + Balances::make_free_balance_be(&8, 101); // Child-bounty curator. + + assert_ok!(Bounties::propose_bounty(Origin::signed(0), 50, b"12345".to_vec())); + + assert_ok!(Bounties::approve_bounty(Origin::root(), 0)); + + System::set_block_number(2); + >::on_initialize(2); + + assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, 6)); + + assert_ok!(Bounties::accept_curator(Origin::signed(4), 0)); + + // Child-bounty. + assert_ok!(ChildBounties::add_child_bounty(Origin::signed(4), 0, 10, b"12345-p1".to_vec())); + + assert_eq!(last_event(), ChildBountiesEvent::Added { index: 0, child_index: 0 }); + + // Propose and accept curator for child-bounty. + assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 8, 2)); + assert_ok!(ChildBounties::accept_curator(Origin::signed(8), 0, 0)); + + // Close child-bounty in active state. + assert_ok!(ChildBounties::close_child_bounty(Origin::signed(4), 0, 0)); + + // Check the child-bounty count. + assert_eq!(ChildBounties::parent_child_bounties(0), 0); + + // Ensure child-bounty curator balance is unreserved. + assert_eq!(Balances::free_balance(8), 101); + assert_eq!(Balances::reserved_balance(8), 0); + + // Parent-bounty account status. + assert_eq!(Balances::free_balance(Bounties::bounty_account_id(0)), 50); + assert_eq!(Balances::reserved_balance(Bounties::bounty_account_id(0)), 0); + + // Child-bounty account status. + assert_eq!(Balances::free_balance(ChildBounties::child_bounty_account_id(0)), 0); + assert_eq!(Balances::reserved_balance(ChildBounties::child_bounty_account_id(0)), 0); + }); +} + +#[test] +fn close_child_bounty_pending() { + new_test_ext().execute_with(|| { + // Make the parent bounty. + System::set_block_number(1); + Balances::make_free_balance_be(&Treasury::account_id(), 101); + assert_eq!(Balances::free_balance(Treasury::account_id()), 101); + assert_eq!(Balances::reserved_balance(Treasury::account_id()), 0); + + // Bounty curator initial balance. + Balances::make_free_balance_be(&4, 101); // Parent-bounty curator. + Balances::make_free_balance_be(&8, 101); // Child-bounty curator. + + assert_ok!(Bounties::propose_bounty(Origin::signed(0), 50, b"12345".to_vec())); + + assert_ok!(Bounties::approve_bounty(Origin::root(), 0)); + + System::set_block_number(2); + >::on_initialize(2); + + assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, 6)); + + assert_ok!(Bounties::accept_curator(Origin::signed(4), 0)); + + // Child-bounty. + assert_ok!(ChildBounties::add_child_bounty(Origin::signed(4), 0, 10, b"12345-p1".to_vec())); + + assert_eq!(last_event(), ChildBountiesEvent::Added { index: 0, child_index: 0 }); + + // Propose and accept curator for child-bounty. + assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 8, 2)); + assert_ok!(ChildBounties::accept_curator(Origin::signed(8), 0, 0)); + + assert_ok!(ChildBounties::award_child_bounty(Origin::signed(8), 0, 0, 7)); + + // Close child-bounty in pending_payout state. + assert_noop!( + ChildBounties::close_child_bounty(Origin::signed(4), 0, 0), + BountiesError::PendingPayout + ); + + // Check the child-bounty count. + assert_eq!(ChildBounties::parent_child_bounties(0), 1); + + // Ensure no changes in child-bounty curator balance. + assert_eq!(Balances::free_balance(8), 100); + assert_eq!(Balances::reserved_balance(8), 1); + + // Child-bounty account status. + assert_eq!(Balances::free_balance(ChildBounties::child_bounty_account_id(0)), 10); + assert_eq!(Balances::reserved_balance(ChildBounties::child_bounty_account_id(0)), 0); + }); +} + +#[test] +fn child_bounty_added_unassign_curator() { + new_test_ext().execute_with(|| { + // Make the parent bounty. + System::set_block_number(1); + Balances::make_free_balance_be(&Treasury::account_id(), 101); + assert_eq!(Balances::free_balance(Treasury::account_id()), 101); + assert_eq!(Balances::reserved_balance(Treasury::account_id()), 0); + + // Bounty curator initial balance. + Balances::make_free_balance_be(&4, 101); // Parent-bounty curator. + Balances::make_free_balance_be(&8, 101); // Child-bounty curator. + + assert_ok!(Bounties::propose_bounty(Origin::signed(0), 50, b"12345".to_vec())); + + assert_ok!(Bounties::approve_bounty(Origin::root(), 0)); + + System::set_block_number(2); + >::on_initialize(2); + + assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, 6)); + + assert_ok!(Bounties::accept_curator(Origin::signed(4), 0)); + + // Child-bounty. + assert_ok!(ChildBounties::add_child_bounty(Origin::signed(4), 0, 10, b"12345-p1".to_vec())); + + assert_eq!(last_event(), ChildBountiesEvent::Added { index: 0, child_index: 0 }); + + // Unassign curator in added state. + assert_noop!( + ChildBounties::unassign_curator(Origin::signed(4), 0, 0), + BountiesError::UnexpectedStatus + ); + }); +} + +#[test] +fn child_bounty_curator_proposed_unassign_curator() { + new_test_ext().execute_with(|| { + // Make the parent bounty. + System::set_block_number(1); + Balances::make_free_balance_be(&Treasury::account_id(), 101); + assert_eq!(Balances::free_balance(Treasury::account_id()), 101); + assert_eq!(Balances::reserved_balance(Treasury::account_id()), 0); + + // Bounty curator initial balance. + Balances::make_free_balance_be(&4, 101); // Parent-bounty curator. + Balances::make_free_balance_be(&8, 101); // Child-bounty curator. + + assert_ok!(Bounties::propose_bounty(Origin::signed(0), 50, b"12345".to_vec())); + + assert_ok!(Bounties::approve_bounty(Origin::root(), 0)); + + System::set_block_number(2); + >::on_initialize(2); + + assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, 6)); + + assert_ok!(Bounties::accept_curator(Origin::signed(4), 0)); + + // Child-bounty. + assert_ok!(ChildBounties::add_child_bounty(Origin::signed(4), 0, 10, b"12345-p1".to_vec())); + + assert_eq!(last_event(), ChildBountiesEvent::Added { index: 0, child_index: 0 }); + + // Propose curator for child-bounty. + assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 8, 2)); + + assert_eq!( + ChildBounties::child_bounties(0, 0).unwrap(), + ChildBounty { + parent_bounty: 0, + value: 10, + fee: 2, + curator_deposit: 0, + status: ChildBountyStatus::CuratorProposed { curator: 8 }, + } + ); + + // Random account cannot unassign the curator when in proposed state. + assert_noop!(ChildBounties::unassign_curator(Origin::signed(99), 0, 0), BadOrigin); + + // Unassign curator. + assert_ok!(ChildBounties::unassign_curator(Origin::signed(4), 0, 0)); + + // Verify updated child-bounty status. + assert_eq!( + ChildBounties::child_bounties(0, 0).unwrap(), + ChildBounty { + parent_bounty: 0, + value: 10, + fee: 2, + curator_deposit: 0, + status: ChildBountyStatus::Added, + } + ); + }); +} + +#[test] +fn child_bounty_active_unassign_curator() { + // Covers all scenarios with all origin types. + // Step 1: Setup bounty, child bounty. + // Step 2: Assign, accept curator for child bounty. Unassign from reject origin. Should slash. + // Step 3: Assign, accept another curator for child bounty. Unassign from parent-bounty curator. + // Should slash. Step 4: Assign, accept another curator for child bounty. Unassign from + // child-bounty curator. Should NOT slash. Step 5: Assign, accept another curator for child + // bounty. Unassign from random account. Should slash. + new_test_ext().execute_with(|| { + // Make the parent bounty. + System::set_block_number(1); + Balances::make_free_balance_be(&Treasury::account_id(), 101); + assert_eq!(Balances::free_balance(Treasury::account_id()), 101); + assert_eq!(Balances::reserved_balance(Treasury::account_id()), 0); + + // Bounty curator initial balance. + Balances::make_free_balance_be(&4, 101); // Parent-bounty curator. + Balances::make_free_balance_be(&6, 101); // Child-bounty curator 1. + Balances::make_free_balance_be(&7, 101); // Child-bounty curator 2. + Balances::make_free_balance_be(&8, 101); // Child-bounty curator 3. + + assert_ok!(Bounties::propose_bounty(Origin::signed(0), 50, b"12345".to_vec())); + + assert_ok!(Bounties::approve_bounty(Origin::root(), 0)); + + System::set_block_number(2); + >::on_initialize(2); + + assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, 6)); + + assert_ok!(Bounties::accept_curator(Origin::signed(4), 0)); + + // Create Child-bounty. + assert_ok!(ChildBounties::add_child_bounty(Origin::signed(4), 0, 10, b"12345-p1".to_vec())); + assert_eq!(last_event(), ChildBountiesEvent::Added { index: 0, child_index: 0 }); + + System::set_block_number(3); + >::on_initialize(3); + + // Propose and accept curator for child-bounty. + assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 8, 2)); + assert_ok!(ChildBounties::accept_curator(Origin::signed(8), 0, 0)); + + assert_eq!( + ChildBounties::child_bounties(0, 0).unwrap(), + ChildBounty { + parent_bounty: 0, + value: 10, + fee: 2, + curator_deposit: 1, + status: ChildBountyStatus::Active { curator: 8 }, + } + ); + + System::set_block_number(4); + >::on_initialize(4); + + // Unassign curator - from reject origin. + assert_ok!(ChildBounties::unassign_curator(Origin::root(), 0, 0)); + + // Verify updated child-bounty status. + assert_eq!( + ChildBounties::child_bounties(0, 0).unwrap(), + ChildBounty { + parent_bounty: 0, + value: 10, + fee: 2, + curator_deposit: 0, + status: ChildBountyStatus::Added, + } + ); + + // Ensure child-bounty curator was slashed. + assert_eq!(Balances::free_balance(8), 100); + assert_eq!(Balances::reserved_balance(8), 0); // slashed + + // Propose and accept curator for child-bounty again. + assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 7, 2)); + assert_ok!(ChildBounties::accept_curator(Origin::signed(7), 0, 0)); + + assert_eq!( + ChildBounties::child_bounties(0, 0).unwrap(), + ChildBounty { + parent_bounty: 0, + value: 10, + fee: 2, + curator_deposit: 1, + status: ChildBountyStatus::Active { curator: 7 }, + } + ); + + System::set_block_number(5); + >::on_initialize(5); + + // Unassign curator again - from master curator. + assert_ok!(ChildBounties::unassign_curator(Origin::signed(4), 0, 0)); + + // Verify updated child-bounty status. + assert_eq!( + ChildBounties::child_bounties(0, 0).unwrap(), + ChildBounty { + parent_bounty: 0, + value: 10, + fee: 2, + curator_deposit: 0, + status: ChildBountyStatus::Added, + } + ); + + // Ensure child-bounty curator was slashed. + assert_eq!(Balances::free_balance(7), 100); + assert_eq!(Balances::reserved_balance(7), 0); // slashed + + // Propose and accept curator for child-bounty again. + assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 6, 2)); + assert_ok!(ChildBounties::accept_curator(Origin::signed(6), 0, 0)); + + assert_eq!( + ChildBounties::child_bounties(0, 0).unwrap(), + ChildBounty { + parent_bounty: 0, + value: 10, + fee: 2, + curator_deposit: 1, + status: ChildBountyStatus::Active { curator: 6 }, + } + ); + + System::set_block_number(6); + >::on_initialize(6); + + // Unassign curator again - from child-bounty curator. + assert_ok!(ChildBounties::unassign_curator(Origin::signed(6), 0, 0)); + + // Verify updated child-bounty status. + assert_eq!( + ChildBounties::child_bounties(0, 0).unwrap(), + ChildBounty { + parent_bounty: 0, + value: 10, + fee: 2, + curator_deposit: 0, + status: ChildBountyStatus::Added, + } + ); + + // Ensure child-bounty curator was **not** slashed. + assert_eq!(Balances::free_balance(6), 101); // not slashed + assert_eq!(Balances::reserved_balance(6), 0); + + // Propose and accept curator for child-bounty one last time. + assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 6, 2)); + assert_ok!(ChildBounties::accept_curator(Origin::signed(6), 0, 0)); + + assert_eq!( + ChildBounties::child_bounties(0, 0).unwrap(), + ChildBounty { + parent_bounty: 0, + value: 10, + fee: 2, + curator_deposit: 1, + status: ChildBountyStatus::Active { curator: 6 }, + } + ); + + System::set_block_number(7); + >::on_initialize(7); + + // Unassign curator again - from non curator; non reject origin; some random guy. + // Bounty update period is not yet complete. + assert_noop!( + ChildBounties::unassign_curator(Origin::signed(3), 0, 0), + BountiesError::Premature + ); + + System::set_block_number(20); + >::on_initialize(20); + + // Unassign child curator from random account after inactivity. + assert_ok!(ChildBounties::unassign_curator(Origin::signed(3), 0, 0)); + + // Verify updated child-bounty status. + assert_eq!( + ChildBounties::child_bounties(0, 0).unwrap(), + ChildBounty { + parent_bounty: 0, + value: 10, + fee: 2, + curator_deposit: 0, + status: ChildBountyStatus::Added, + } + ); + + // Ensure child-bounty curator was slashed. + assert_eq!(Balances::free_balance(6), 100); // slashed + assert_eq!(Balances::reserved_balance(6), 0); + }); +} + +#[test] +fn parent_bounty_inactive_unassign_curator_child_bounty() { + // Unassign curator when parent bounty in not in active state. + // This can happen when the curator of parent bounty has been unassigned. + new_test_ext().execute_with(|| { + // Make the parent bounty. + System::set_block_number(1); + Balances::make_free_balance_be(&Treasury::account_id(), 101); + assert_eq!(Balances::free_balance(Treasury::account_id()), 101); + assert_eq!(Balances::reserved_balance(Treasury::account_id()), 0); + + // Bounty curator initial balance. + Balances::make_free_balance_be(&4, 101); // Parent-bounty curator 1. + Balances::make_free_balance_be(&5, 101); // Parent-bounty curator 2. + Balances::make_free_balance_be(&6, 101); // Child-bounty curator 1. + Balances::make_free_balance_be(&7, 101); // Child-bounty curator 2. + Balances::make_free_balance_be(&8, 101); // Child-bounty curator 3. + + assert_ok!(Bounties::propose_bounty(Origin::signed(0), 50, b"12345".to_vec())); + assert_ok!(Bounties::approve_bounty(Origin::root(), 0)); + + System::set_block_number(2); + >::on_initialize(2); + + assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, 6)); + assert_ok!(Bounties::accept_curator(Origin::signed(4), 0)); + + // Create Child-bounty. + assert_ok!(ChildBounties::add_child_bounty(Origin::signed(4), 0, 10, b"12345-p1".to_vec())); + assert_eq!(last_event(), ChildBountiesEvent::Added { index: 0, child_index: 0 }); + + System::set_block_number(3); + >::on_initialize(3); + + // Propose and accept curator for child-bounty. + assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 8, 2)); + assert_ok!(ChildBounties::accept_curator(Origin::signed(8), 0, 0)); + + assert_eq!( + ChildBounties::child_bounties(0, 0).unwrap(), + ChildBounty { + parent_bounty: 0, + value: 10, + fee: 2, + curator_deposit: 1, + status: ChildBountyStatus::Active { curator: 8 }, + } + ); + + System::set_block_number(4); + >::on_initialize(4); + + // Unassign parent bounty curator. + assert_ok!(Bounties::unassign_curator(Origin::root(), 0)); + + System::set_block_number(5); + >::on_initialize(5); + + // Try unassign child-bounty curator - from non curator; non reject + // origin; some random guy. Bounty update period is not yet complete. + assert_noop!( + ChildBounties::unassign_curator(Origin::signed(3), 0, 0), + Error::::ParentBountyNotActive + ); + + // Unassign curator - from reject origin. + assert_ok!(ChildBounties::unassign_curator(Origin::root(), 0, 0)); + + // Verify updated child-bounty status. + assert_eq!( + ChildBounties::child_bounties(0, 0).unwrap(), + ChildBounty { + parent_bounty: 0, + value: 10, + fee: 2, + curator_deposit: 0, + status: ChildBountyStatus::Added, + } + ); + + // Ensure child-bounty curator was slashed. + assert_eq!(Balances::free_balance(8), 100); + assert_eq!(Balances::reserved_balance(8), 0); // slashed + + System::set_block_number(6); + >::on_initialize(6); + + // Propose and accept curator for parent-bounty again. + assert_ok!(Bounties::propose_curator(Origin::root(), 0, 5, 6)); + assert_ok!(Bounties::accept_curator(Origin::signed(5), 0)); + + System::set_block_number(7); + >::on_initialize(7); + + // Propose and accept curator for child-bounty again. + assert_ok!(ChildBounties::propose_curator(Origin::signed(5), 0, 0, 7, 2)); + assert_ok!(ChildBounties::accept_curator(Origin::signed(7), 0, 0)); + + assert_eq!( + ChildBounties::child_bounties(0, 0).unwrap(), + ChildBounty { + parent_bounty: 0, + value: 10, + fee: 2, + curator_deposit: 1, + status: ChildBountyStatus::Active { curator: 7 }, + } + ); + + System::set_block_number(8); + >::on_initialize(8); + + assert_noop!( + ChildBounties::unassign_curator(Origin::signed(3), 0, 0), + BountiesError::Premature + ); + + // Unassign parent bounty curator again. + assert_ok!(Bounties::unassign_curator(Origin::signed(5), 0)); + + System::set_block_number(9); + >::on_initialize(9); + + // Unassign curator again - from master curator. + assert_ok!(ChildBounties::unassign_curator(Origin::signed(7), 0, 0)); + + // Verify updated child-bounty status. + assert_eq!( + ChildBounties::child_bounties(0, 0).unwrap(), + ChildBounty { + parent_bounty: 0, + value: 10, + fee: 2, + curator_deposit: 0, + status: ChildBountyStatus::Added, + } + ); + + // Ensure child-bounty curator was not slashed. + assert_eq!(Balances::free_balance(7), 101); + assert_eq!(Balances::reserved_balance(7), 0); // slashed + }); +} + +#[test] +fn close_parent_with_child_bounty() { + new_test_ext().execute_with(|| { + // Make the parent bounty. + System::set_block_number(1); + Balances::make_free_balance_be(&Treasury::account_id(), 101); + assert_eq!(Balances::free_balance(Treasury::account_id()), 101); + assert_eq!(Balances::reserved_balance(Treasury::account_id()), 0); + + // Bounty curator initial balance. + Balances::make_free_balance_be(&4, 101); // Parent-bounty curator. + Balances::make_free_balance_be(&8, 101); // Child-bounty curator. + + assert_ok!(Bounties::propose_bounty(Origin::signed(0), 50, b"12345".to_vec())); + assert_ok!(Bounties::approve_bounty(Origin::root(), 0)); + + // Try add child-bounty. + // Should fail, parent bounty not active yet. + assert_noop!( + ChildBounties::add_child_bounty(Origin::signed(4), 0, 10, b"12345-p1".to_vec()), + Error::::ParentBountyNotActive + ); + + System::set_block_number(2); + >::on_initialize(2); + + assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, 6)); + assert_ok!(Bounties::accept_curator(Origin::signed(4), 0)); + + // Child-bounty. + assert_ok!(ChildBounties::add_child_bounty(Origin::signed(4), 0, 10, b"12345-p1".to_vec())); + assert_eq!(last_event(), ChildBountiesEvent::Added { index: 0, child_index: 0 }); + + System::set_block_number(4); + >::on_initialize(4); + + // Try close parent-bounty. + // Child bounty active, can't close parent. + assert_noop!( + Bounties::close_bounty(Origin::root(), 0), + BountiesError::HasActiveChildBounty + ); + + System::set_block_number(2); + + // Close child-bounty. + assert_ok!(ChildBounties::close_child_bounty(Origin::root(), 0, 0)); + + // Check the child-bounty count. + assert_eq!(ChildBounties::parent_child_bounties(0), 0); + + // Try close parent-bounty again. + // Should pass this time. + assert_ok!(Bounties::close_bounty(Origin::root(), 0)); + }); +} + +#[test] +fn children_curator_fee_calculation_test() { + // Tests the calculation of subtracting child-bounty curator fee + // from parent bounty fee when claiming bounties. + new_test_ext().execute_with(|| { + // Make the parent bounty. + System::set_block_number(1); + Balances::make_free_balance_be(&Treasury::account_id(), 101); + assert_eq!(Balances::free_balance(Treasury::account_id()), 101); + assert_eq!(Balances::reserved_balance(Treasury::account_id()), 0); + + // Bounty curator initial balance. + Balances::make_free_balance_be(&4, 101); // Parent-bounty curator. + Balances::make_free_balance_be(&8, 101); // Child-bounty curator. + + assert_ok!(Bounties::propose_bounty(Origin::signed(0), 50, b"12345".to_vec())); + assert_ok!(Bounties::approve_bounty(Origin::root(), 0)); + + System::set_block_number(2); + >::on_initialize(2); + + assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, 6)); + assert_ok!(Bounties::accept_curator(Origin::signed(4), 0)); + + // Child-bounty. + assert_ok!(ChildBounties::add_child_bounty(Origin::signed(4), 0, 10, b"12345-p1".to_vec())); + assert_eq!(last_event(), ChildBountiesEvent::Added { index: 0, child_index: 0 }); + + System::set_block_number(4); + >::on_initialize(4); + + // Propose curator for child-bounty. + assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 8, 2)); + + // Check curator fee added to the sum. + assert_eq!(ChildBounties::children_curator_fees(0), 2); + + // Accept curator for child-bounty. + assert_ok!(ChildBounties::accept_curator(Origin::signed(8), 0, 0)); + + // Award child-bounty. + assert_ok!(ChildBounties::award_child_bounty(Origin::signed(8), 0, 0, 7)); + + assert_eq!( + ChildBounties::child_bounties(0, 0).unwrap(), + ChildBounty { + parent_bounty: 0, + value: 10, + fee: 2, + curator_deposit: 1, + status: ChildBountyStatus::PendingPayout { + curator: 8, + beneficiary: 7, + unlock_at: 7 + }, + } + ); + + System::set_block_number(9); + + // Claim child-bounty. + assert_ok!(ChildBounties::claim_child_bounty(Origin::signed(7), 0, 0)); + + // Check the child-bounty count. + assert_eq!(ChildBounties::parent_child_bounties(0), 0); + + // Award the parent bounty. + assert_ok!(Bounties::award_bounty(Origin::signed(4), 0, 9)); + + System::set_block_number(15); + + // Claim the parent bounty. + assert_ok!(Bounties::claim_bounty(Origin::signed(9), 0)); + + // Ensure parent-bounty curator received correctly reduced fee. + assert_eq!(Balances::free_balance(4), 105); // 101 + 6 - 2 + assert_eq!(Balances::reserved_balance(4), 0); + + // Verify parent-bounty beneficiary balance. + assert_eq!(Balances::free_balance(9), 34); + assert_eq!(Balances::reserved_balance(9), 0); + }); +} diff --git a/frame/child-bounties/src/weights.rs b/frame/child-bounties/src/weights.rs new file mode 100644 index 000000000000..7a52495d980b --- /dev/null +++ b/frame/child-bounties/src/weights.rs @@ -0,0 +1,215 @@ +// This file is part of Substrate. + +// Copyright (C) 2021 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. + +//! Autogenerated weights for pallet_child_bounties +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2021-12-03, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 + +// Executed Command: +// ./target/release/substrate +// benchmark +// --chain=dev +// --steps=50 +// --repeat=20 +// --pallet +// pallet_child_bounties +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 +// --output=./frame/child-bounties/src/ +// --template=./.maintain/frame-weight-template.hbs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +/// Weight functions needed for pallet_child_bounties. +pub trait WeightInfo { + fn add_child_bounty(d: u32, ) -> Weight; + fn propose_curator() -> Weight; + fn accept_curator() -> Weight; + fn unassign_curator() -> Weight; + fn award_child_bounty() -> Weight; + fn claim_child_bounty() -> Weight; + fn close_child_bounty_added() -> Weight; + fn close_child_bounty_active() -> Weight; +} + +/// Weights for pallet_child_bounties using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + // Storage: ChildBounties ParentChildBounties (r:1 w:1) + // Storage: Bounties Bounties (r:1 w:0) + // Storage: System Account (r:2 w:2) + // Storage: ChildBounties ChildBountyCount (r:1 w:1) + // Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) + // Storage: ChildBounties ChildBounties (r:0 w:1) + fn add_child_bounty(d: u32, ) -> Weight { + (113_579_000 as Weight) + // Standard Error: 1_000 + .saturating_add((4_000 as Weight).saturating_mul(d as Weight)) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(6 as Weight)) + } + // Storage: Bounties Bounties (r:1 w:0) + // Storage: ChildBounties ChildBounties (r:1 w:1) + // Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) + fn propose_curator() -> Weight { + (24_000_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + } + // Storage: Bounties Bounties (r:1 w:0) + // Storage: ChildBounties ChildBounties (r:1 w:1) + // Storage: System Account (r:1 w:1) + fn accept_curator() -> Weight { + (55_000_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + } + // Storage: ChildBounties ChildBounties (r:1 w:1) + // Storage: Bounties Bounties (r:1 w:0) + // Storage: System Account (r:1 w:1) + fn unassign_curator() -> Weight { + (61_000_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + } + // Storage: Bounties Bounties (r:1 w:0) + // Storage: ChildBounties ChildBounties (r:1 w:1) + fn award_child_bounty() -> Weight { + (42_000_000 as Weight) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + // Storage: ChildBounties ChildBounties (r:1 w:1) + // Storage: System Account (r:3 w:3) + // Storage: ChildBounties ParentChildBounties (r:1 w:1) + // Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) + fn claim_child_bounty() -> Weight { + (153_000_000 as Weight) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(6 as Weight)) + } + // Storage: Bounties Bounties (r:1 w:0) + // Storage: ChildBounties ChildBounties (r:1 w:1) + // Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) + // Storage: ChildBounties ParentChildBounties (r:1 w:1) + // Storage: System Account (r:2 w:2) + // Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) + fn close_child_bounty_added() -> Weight { + (101_000_000 as Weight) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) + .saturating_add(T::DbWeight::get().writes(6 as Weight)) + } + // Storage: Bounties Bounties (r:1 w:0) + // Storage: ChildBounties ChildBounties (r:1 w:1) + // Storage: System Account (r:3 w:3) + // Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) + // Storage: ChildBounties ParentChildBounties (r:1 w:1) + // Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) + fn close_child_bounty_active() -> Weight { + (130_000_000 as Weight) + .saturating_add(T::DbWeight::get().reads(7 as Weight)) + .saturating_add(T::DbWeight::get().writes(7 as Weight)) + } +} + +// For backwards compatibility and tests +impl WeightInfo for () { + // Storage: ChildBounties ParentChildBounties (r:1 w:1) + // Storage: Bounties Bounties (r:1 w:0) + // Storage: System Account (r:2 w:2) + // Storage: ChildBounties ChildBountyCount (r:1 w:1) + // Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) + // Storage: ChildBounties ChildBounties (r:0 w:1) + fn add_child_bounty(d: u32, ) -> Weight { + (113_579_000 as Weight) + // Standard Error: 1_000 + .saturating_add((4_000 as Weight).saturating_mul(d as Weight)) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + .saturating_add(RocksDbWeight::get().writes(6 as Weight)) + } + // Storage: Bounties Bounties (r:1 w:0) + // Storage: ChildBounties ChildBounties (r:1 w:1) + // Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) + fn propose_curator() -> Weight { + (24_000_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + } + // Storage: Bounties Bounties (r:1 w:0) + // Storage: ChildBounties ChildBounties (r:1 w:1) + // Storage: System Account (r:1 w:1) + fn accept_curator() -> Weight { + (55_000_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + } + // Storage: ChildBounties ChildBounties (r:1 w:1) + // Storage: Bounties Bounties (r:1 w:0) + // Storage: System Account (r:1 w:1) + fn unassign_curator() -> Weight { + (61_000_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + } + // Storage: Bounties Bounties (r:1 w:0) + // Storage: ChildBounties ChildBounties (r:1 w:1) + fn award_child_bounty() -> Weight { + (42_000_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + // Storage: ChildBounties ChildBounties (r:1 w:1) + // Storage: System Account (r:3 w:3) + // Storage: ChildBounties ParentChildBounties (r:1 w:1) + // Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) + fn claim_child_bounty() -> Weight { + (153_000_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + .saturating_add(RocksDbWeight::get().writes(6 as Weight)) + } + // Storage: Bounties Bounties (r:1 w:0) + // Storage: ChildBounties ChildBounties (r:1 w:1) + // Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) + // Storage: ChildBounties ParentChildBounties (r:1 w:1) + // Storage: System Account (r:2 w:2) + // Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) + fn close_child_bounty_added() -> Weight { + (101_000_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(6 as Weight)) + .saturating_add(RocksDbWeight::get().writes(6 as Weight)) + } + // Storage: Bounties Bounties (r:1 w:0) + // Storage: ChildBounties ChildBounties (r:1 w:1) + // Storage: System Account (r:3 w:3) + // Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) + // Storage: ChildBounties ParentChildBounties (r:1 w:1) + // Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) + fn close_child_bounty_active() -> Weight { + (130_000_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(7 as Weight)) + .saturating_add(RocksDbWeight::get().writes(7 as Weight)) + } +} From c9cad66c7ed0c2d24ceaf2a5292f1c3188987b0c Mon Sep 17 00:00:00 2001 From: Zeke Mostov Date: Tue, 7 Dec 2021 20:35:44 -0800 Subject: [PATCH 265/695] Add extrinsic to improve position in a bag of bags-list (#9829) * pallet-bags-list: Add `put_in_front_of` extrinsic This PR adds the extrinsic `put_in_front_of` which allows the user to specify a `lighter` and `heavier` account within the same bag. The extrinsic will move `heavier` directly in front of `lighter`. The parameter names refer to the fact that `lighter` must have a lower `VoteWeight` then `heavier`. In the ideal use case, where a user wants to improve the position of their account within a bag, the user would iterate the bag, starting from the head, and find the first node who's `VoteWeight` is less than theirs. They would then supply the `id` of the node as the `lighter` argument and their own `id` as the `heavier` argument. * Test & Benchmarks * Respect line width * Remove List::put_in_fron_of tests; Remove AlreadyHigher error * The dispatch origin for this call must be ... * Add some periods * Add back test to list module: put_in_front_of_exits_early_if_bag_not_found * add test tests::pallet::heavier_is_head_lighter_is_not_terminal * Cater for edge case of heavier being head * Add ExtBuilder::add_aux_data; try to make some tests use simpler data * Update frame/bags-list/src/list/tests.rs * make insert_at_unchecked infallible * Make it permissioned - only callable by heavier * Add test cases for insert_at_unchecked * Move counter update to insert_at; fix comments * Address some feedback * Make voteweight constructed with parameter_types * Always set vote weight for Ids in build * Add skip_genesis_ids * Do not pass weight fn to List put_in_front_of * Remove remants of CounterForListNodes * fmt * cargo run --quiet --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_bags_list --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/bags-list/src/weights.rs --template=./.maintain/frame-weight-template.hbs * Delete messed up weights file * Some place holder stuff so we can run bench in CI * Fix * cargo run --quiet --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_bags_list --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/bags-list/src/weights.rs --template=./.maintain/frame-weight-template.hbs * Update frame/bags-list/src/list/mod.rs Co-authored-by: Guillaume Thiolliere * fmt * Log + debug assert when refetching an Id Co-authored-by: Parity Bot Co-authored-by: Guillaume Thiolliere --- frame/bags-list/src/benchmarks.rs | 44 ++++- frame/bags-list/src/lib.rs | 25 +++ frame/bags-list/src/list/mod.rs | 78 +++++++++ frame/bags-list/src/list/tests.rs | 117 ++++++++++++++ frame/bags-list/src/mock.rs | 33 ++-- frame/bags-list/src/tests.rs | 261 +++++++++++++++++++++++++++++- frame/bags-list/src/weights.rs | 32 +++- 7 files changed, 561 insertions(+), 29 deletions(-) diff --git a/frame/bags-list/src/benchmarks.rs b/frame/bags-list/src/benchmarks.rs index 800e668324e0..41c65978e0d4 100644 --- a/frame/bags-list/src/benchmarks.rs +++ b/frame/bags-list/src/benchmarks.rs @@ -19,7 +19,7 @@ use super::*; use crate::list::List; -use frame_benchmarking::{account, whitelisted_caller}; +use frame_benchmarking::{account, whitelist_account, whitelisted_caller}; use frame_election_provider_support::VoteWeightProvider; use frame_support::{assert_ok, traits::Get}; use frame_system::RawOrigin as SystemOrigin; @@ -137,9 +137,41 @@ frame_benchmarking::benchmarks! { ); } - impl_benchmark_test_suite!( - Pallet, - crate::mock::ExtBuilder::default().build(), - crate::mock::Runtime, - ) + put_in_front_of { + // The most expensive case for `put_in_front_of`: + // + // - both heavier's `prev` and `next` are nodes that will need to be read and written. + // - `lighter` is the bag's `head`, so the bag will need to be read and written. + + let bag_thresh = T::BagThresholds::get()[0]; + + // insert the nodes in order + let lighter: T::AccountId = account("lighter", 0, 0); + assert_ok!(List::::insert(lighter.clone(), bag_thresh)); + + let heavier_prev: T::AccountId = account("heavier_prev", 0, 0); + assert_ok!(List::::insert(heavier_prev.clone(), bag_thresh)); + + let heavier: T::AccountId = account("heavier", 0, 0); + assert_ok!(List::::insert(heavier.clone(), bag_thresh)); + + let heavier_next: T::AccountId = account("heavier_next", 0, 0); + assert_ok!(List::::insert(heavier_next.clone(), bag_thresh)); + + T::VoteWeightProvider::set_vote_weight_of(&lighter, bag_thresh - 1); + T::VoteWeightProvider::set_vote_weight_of(&heavier, bag_thresh); + + assert_eq!( + List::::iter().map(|n| n.id().clone()).collect::>(), + vec![lighter.clone(), heavier_prev.clone(), heavier.clone(), heavier_next.clone()] + ); + + whitelist_account!(heavier); + }: _(SystemOrigin::Signed(heavier.clone()), lighter.clone()) + verify { + assert_eq!( + List::::iter().map(|n| n.id().clone()).collect::>(), + vec![heavier, lighter, heavier_prev, heavier_next] + ) + } } diff --git a/frame/bags-list/src/lib.rs b/frame/bags-list/src/lib.rs index d3be2c29533f..193a334cf08f 100644 --- a/frame/bags-list/src/lib.rs +++ b/frame/bags-list/src/lib.rs @@ -173,6 +173,17 @@ pub mod pallet { Rebagged { who: T::AccountId, from: VoteWeight, to: VoteWeight }, } + #[pallet::error] + #[cfg_attr(test, derive(PartialEq))] + pub enum Error { + /// Attempted to place node in front of a node in another bag. + NotInSameBag, + /// Id not found in list. + IdNotFound, + /// An Id does not have a greater vote weight than another Id. + NotHeavier, + } + #[pallet::call] impl Pallet { /// Declare that some `dislocated` account has, through rewards or penalties, sufficiently @@ -190,6 +201,20 @@ pub mod pallet { let _ = Pallet::::do_rebag(&dislocated, current_weight); Ok(()) } + + /// Move the caller's Id directly in front of `lighter`. + /// + /// The dispatch origin for this call must be _Signed_ and can only be called by the Id of + /// the account going in front of `lighter`. + /// + /// Only works if + /// - both nodes are within the same bag, + /// - and `origin` has a greater `VoteWeight` than `lighter`. + #[pallet::weight(T::WeightInfo::put_in_front_of())] + pub fn put_in_front_of(origin: OriginFor, lighter: T::AccountId) -> DispatchResult { + let heavier = ensure_signed(origin)?; + List::::put_in_front_of(&lighter, &heavier).map_err(Into::into) + } } #[pallet::hooks] diff --git a/frame/bags-list/src/list/mod.rs b/frame/bags-list/src/list/mod.rs index 1ec4996c26fd..4524101d793c 100644 --- a/frame/bags-list/src/list/mod.rs +++ b/frame/bags-list/src/list/mod.rs @@ -376,6 +376,84 @@ impl List { }) } + /// Put `heavier_id` to the position directly in front of `lighter_id`. Both ids must be in the + /// same bag and the `weight_of` `lighter_id` must be less than that of `heavier_id`. + pub(crate) fn put_in_front_of( + lighter_id: &T::AccountId, + heavier_id: &T::AccountId, + ) -> Result<(), crate::pallet::Error> { + use crate::pallet; + use frame_support::ensure; + + let lighter_node = Node::::get(&lighter_id).ok_or(pallet::Error::IdNotFound)?; + let heavier_node = Node::::get(&heavier_id).ok_or(pallet::Error::IdNotFound)?; + + ensure!(lighter_node.bag_upper == heavier_node.bag_upper, pallet::Error::NotInSameBag); + + // this is the most expensive check, so we do it last. + ensure!( + T::VoteWeightProvider::vote_weight(&heavier_id) > + T::VoteWeightProvider::vote_weight(&lighter_id), + pallet::Error::NotHeavier + ); + + // remove the heavier node from this list. Note that this removes the node from storage and + // decrements the node counter. + Self::remove(&heavier_id); + + // re-fetch `lighter_node` from storage since it may have been updated when `heavier_node` + // was removed. + let lighter_node = Node::::get(&lighter_id).ok_or_else(|| { + debug_assert!(false, "id that should exist cannot be found"); + crate::log!(warn, "id that should exist cannot be found"); + pallet::Error::IdNotFound + })?; + + // insert `heavier_node` directly in front of `lighter_node`. This will update both nodes + // in storage and update the node counter. + Self::insert_at_unchecked(lighter_node, heavier_node); + + Ok(()) + } + + /// Insert `node` directly in front of `at`. + /// + /// WARNINGS: + /// - this is a naive function in that it does not check if `node` belongs to the same bag as + /// `at`. It is expected that the call site will check preconditions. + /// - this will panic if `at.bag_upper` is not a bag that already exists in storage. + fn insert_at_unchecked(mut at: Node, mut node: Node) { + // connect `node` to its new `prev`. + node.prev = at.prev.clone(); + if let Some(mut prev) = at.prev() { + prev.next = Some(node.id().clone()); + prev.put() + } + + // connect `node` and `at`. + node.next = Some(at.id().clone()); + at.prev = Some(node.id().clone()); + + if node.is_terminal() { + // `node` is the new head, so we make sure the bag is updated. Note, + // since `node` is always in front of `at` we know that 1) there is always at least 2 + // nodes in the bag, and 2) only `node` could be the head and only `at` could be the + // tail. + let mut bag = Bag::::get(at.bag_upper) + .expect("given nodes must always have a valid bag. qed."); + + if node.prev == None { + bag.head = Some(node.id().clone()) + } + + bag.put() + }; + + // write the updated nodes to storage. + at.put(); + node.put(); + } + /// Sanity check the list. /// /// This should be called from the call-site, whenever one of the mutating apis (e.g. `insert`) diff --git a/frame/bags-list/src/list/tests.rs b/frame/bags-list/src/list/tests.rs index 1c345df9a2fb..f3043589681e 100644 --- a/frame/bags-list/src/list/tests.rs +++ b/frame/bags-list/src/list/tests.rs @@ -383,6 +383,123 @@ mod list { assert!(non_existent_ids.iter().all(|id| !List::::contains(id))); }) } + + #[test] + #[should_panic = "given nodes must always have a valid bag. qed."] + fn put_in_front_of_panics_if_bag_not_found() { + ExtBuilder::default().skip_genesis_ids().build_and_execute_no_post_check(|| { + let node_10_no_bag = Node:: { id: 10, prev: None, next: None, bag_upper: 15 }; + let node_11_no_bag = Node:: { id: 11, prev: None, next: None, bag_upper: 15 }; + + // given + ListNodes::::insert(10, node_10_no_bag); + ListNodes::::insert(11, node_11_no_bag); + StakingMock::set_vote_weight_of(&10, 14); + StakingMock::set_vote_weight_of(&11, 15); + assert!(!ListBags::::contains_key(15)); + assert_eq!(List::::get_bags(), vec![]); + + // then .. this panics + let _ = List::::put_in_front_of(&10, &11); + }); + } + + #[test] + fn insert_at_unchecked_at_is_only_node() { + // Note that this `insert_at_unchecked` test should fail post checks because node 42 does + // not get re-assigned the correct bagu pper. This is because `insert_at_unchecked` assumes + // both nodes are already in the same bag with the correct bag upper. + ExtBuilder::default().build_and_execute_no_post_check(|| { + // given + assert_eq!(List::::get_bags(), vec![(10, vec![1]), (1_000, vec![2, 3, 4])]); + + // implicitly also test that `node`'s `prev`/`next` are correctly re-assigned. + let node_42 = + Node:: { id: 42, prev: Some(1), next: Some(2), bag_upper: 1_000 }; + assert!(!crate::ListNodes::::contains_key(42)); + + let node_1 = crate::ListNodes::::get(&1).unwrap(); + + // when + List::::insert_at_unchecked(node_1, node_42); + + // then + assert_eq!( + List::::get_bags(), + vec![(10, vec![42, 1]), (1_000, vec![2, 3, 4])] + ); + }) + } + + #[test] + fn insert_at_unchecked_at_is_head() { + ExtBuilder::default().build_and_execute(|| { + // given + assert_eq!(List::::get_bags(), vec![(10, vec![1]), (1_000, vec![2, 3, 4])]); + + // implicitly also test that `node`'s `prev`/`next` are correctly re-assigned. + let node_42 = Node:: { id: 42, prev: Some(4), next: None, bag_upper: 1_000 }; + assert!(!crate::ListNodes::::contains_key(42)); + + let node_2 = crate::ListNodes::::get(&2).unwrap(); + + // when + List::::insert_at_unchecked(node_2, node_42); + + // then + assert_eq!( + List::::get_bags(), + vec![(10, vec![1]), (1_000, vec![42, 2, 3, 4])] + ); + }) + } + + #[test] + fn insert_at_unchecked_at_is_non_terminal() { + ExtBuilder::default().build_and_execute(|| { + // given + assert_eq!(List::::get_bags(), vec![(10, vec![1]), (1_000, vec![2, 3, 4])]); + + // implicitly also test that `node`'s `prev`/`next` are correctly re-assigned. + let node_42 = Node:: { id: 42, prev: None, next: Some(2), bag_upper: 1_000 }; + assert!(!crate::ListNodes::::contains_key(42)); + + let node_3 = crate::ListNodes::::get(&3).unwrap(); + + // when + List::::insert_at_unchecked(node_3, node_42); + + // then + assert_eq!( + List::::get_bags(), + vec![(10, vec![1]), (1_000, vec![2, 42, 3, 4])] + ); + }) + } + + #[test] + fn insert_at_unchecked_at_is_tail() { + ExtBuilder::default().build_and_execute(|| { + // given + assert_eq!(List::::get_bags(), vec![(10, vec![1]), (1_000, vec![2, 3, 4])]); + + // implicitly also test that `node`'s `prev`/`next` are correctly re-assigned. + let node_42 = + Node:: { id: 42, prev: Some(42), next: Some(42), bag_upper: 1_000 }; + assert!(!crate::ListNodes::::contains_key(42)); + + let node_4 = crate::ListNodes::::get(&4).unwrap(); + + // when + List::::insert_at_unchecked(node_4, node_42); + + // then + assert_eq!( + List::::get_bags(), + vec![(10, vec![1]), (1_000, vec![2, 3, 42, 4])] + ); + }) + } } mod bags { diff --git a/frame/bags-list/src/mock.rs b/frame/bags-list/src/mock.rs index 45eb1d85abe3..6545e563a3ef 100644 --- a/frame/bags-list/src/mock.rs +++ b/frame/bags-list/src/mock.rs @@ -21,28 +21,26 @@ use super::*; use crate::{self as bags_list}; use frame_election_provider_support::VoteWeight; use frame_support::parameter_types; +use std::collections::HashMap; pub type AccountId = u32; pub type Balance = u32; parameter_types! { + // Set the vote weight for any id who's weight has _not_ been set with `set_vote_weight_of`. pub static NextVoteWeight: VoteWeight = 0; + pub static NextVoteWeightMap: HashMap = Default::default(); } pub struct StakingMock; impl frame_election_provider_support::VoteWeightProvider for StakingMock { fn vote_weight(id: &AccountId) -> VoteWeight { - match id { - 710 => 15, - 711 => 16, - 712 => 2_000, // special cases used for migrate test - _ => NextVoteWeight::get(), - } + *NextVoteWeightMap::get().get(id).unwrap_or(&NextVoteWeight::get()) } + #[cfg(any(feature = "runtime-benchmarks", test))] - fn set_vote_weight_of(_: &AccountId, weight: VoteWeight) { - // we don't really keep a mapping, just set weight for everyone. - NextVoteWeight::set(weight) + fn set_vote_weight_of(id: &AccountId, weight: VoteWeight) { + NEXT_VOTE_WEIGHT_MAP.with(|m| m.borrow_mut().insert(id.clone(), weight)); } } @@ -103,9 +101,17 @@ pub(crate) const GENESIS_IDS: [(AccountId, VoteWeight); 4] = #[derive(Default)] pub struct ExtBuilder { ids: Vec<(AccountId, VoteWeight)>, + skip_genesis_ids: bool, } impl ExtBuilder { + /// Skip adding the default genesis ids to the list. + #[cfg(test)] + pub(crate) fn skip_genesis_ids(mut self) -> Self { + self.skip_genesis_ids = true; + self + } + /// Add some AccountIds to insert into `List`. #[cfg(test)] pub(crate) fn add_ids(mut self, ids: Vec<(AccountId, VoteWeight)>) -> Self { @@ -117,10 +123,17 @@ impl ExtBuilder { sp_tracing::try_init_simple(); let storage = frame_system::GenesisConfig::default().build_storage::().unwrap(); + let ids_with_weight: Vec<_> = if self.skip_genesis_ids { + self.ids.iter().collect() + } else { + GENESIS_IDS.iter().chain(self.ids.iter()).collect() + }; + let mut ext = sp_io::TestExternalities::from(storage); ext.execute_with(|| { - for (id, weight) in GENESIS_IDS.iter().chain(self.ids.iter()) { + for (id, weight) in ids_with_weight { frame_support::assert_ok!(List::::insert(*id, *weight)); + StakingMock::set_vote_weight_of(id, *weight); } }); diff --git a/frame/bags-list/src/tests.rs b/frame/bags-list/src/tests.rs index 270d25855ccd..8f1ccacaf117 100644 --- a/frame/bags-list/src/tests.rs +++ b/frame/bags-list/src/tests.rs @@ -15,7 +15,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use frame_support::{assert_ok, assert_storage_noop, traits::IntegrityTest}; +use frame_support::{assert_noop, assert_ok, assert_storage_noop, traits::IntegrityTest}; use super::*; use frame_election_provider_support::SortedListProvider; @@ -35,7 +35,7 @@ mod pallet { ); // when increasing vote weight to the level of non-existent bag - NextVoteWeight::set(2_000); + StakingMock::set_vote_weight_of(&42, 2_000); assert_ok!(BagsList::rebag(Origin::signed(0), 42)); // then a new bag is created and the id moves into it @@ -45,7 +45,7 @@ mod pallet { ); // when decreasing weight within the range of the current bag - NextVoteWeight::set(1001); + StakingMock::set_vote_weight_of(&42, 1_001); assert_ok!(BagsList::rebag(Origin::signed(0), 42)); // then the id does not move @@ -55,7 +55,7 @@ mod pallet { ); // when reducing weight to the level of a non-existent bag - NextVoteWeight::set(30); + StakingMock::set_vote_weight_of(&42, 30); assert_ok!(BagsList::rebag(Origin::signed(0), 42)); // then a new bag is created and the id moves into it @@ -65,7 +65,7 @@ mod pallet { ); // when increasing weight to the level of a pre-existing bag - NextVoteWeight::set(500); + StakingMock::set_vote_weight_of(&42, 500); assert_ok!(BagsList::rebag(Origin::signed(0), 42)); // then the id moves into that bag @@ -85,7 +85,7 @@ mod pallet { assert_eq!(List::::get_bags(), vec![(10, vec![1]), (1_000, vec![2, 3, 4])]); // when - NextVoteWeight::set(10); + StakingMock::set_vote_weight_of(&4, 10); assert_ok!(BagsList::rebag(Origin::signed(0), 4)); // then @@ -93,6 +93,7 @@ mod pallet { assert_eq!(Bag::::get(1_000).unwrap(), Bag::new(Some(2), Some(3), 1_000)); // when + StakingMock::set_vote_weight_of(&3, 10); assert_ok!(BagsList::rebag(Origin::signed(0), 3)); // then @@ -103,6 +104,7 @@ mod pallet { assert_eq!(get_list_as_ids(), vec![2u32, 1, 4, 3]); // when + StakingMock::set_vote_weight_of(&2, 10); assert_ok!(BagsList::rebag(Origin::signed(0), 2)); // then @@ -117,7 +119,7 @@ mod pallet { fn rebag_head_works() { ExtBuilder::default().build_and_execute(|| { // when - NextVoteWeight::set(10); + StakingMock::set_vote_weight_of(&2, 10); assert_ok!(BagsList::rebag(Origin::signed(0), 2)); // then @@ -125,6 +127,7 @@ mod pallet { assert_eq!(Bag::::get(1_000).unwrap(), Bag::new(Some(3), Some(4), 1_000)); // when + StakingMock::set_vote_weight_of(&3, 10); assert_ok!(BagsList::rebag(Origin::signed(0), 3)); // then @@ -132,6 +135,7 @@ mod pallet { assert_eq!(Bag::::get(1_000).unwrap(), Bag::new(Some(4), Some(4), 1_000)); // when + StakingMock::set_vote_weight_of(&4, 10); assert_ok!(BagsList::rebag(Origin::signed(0), 4)); // then @@ -196,6 +200,249 @@ mod pallet { assert_storage_noop!(assert!(BagsList::rebag(Origin::signed(0), 10).is_ok())); }) } + + #[test] + fn put_in_front_of_two_node_bag_heavier_is_tail() { + ExtBuilder::default() + .skip_genesis_ids() + .add_ids(vec![(10, 15), (11, 16)]) + .build_and_execute(|| { + // given + assert_eq!(List::::get_bags(), vec![(20, vec![10, 11])]); + + // when + assert_ok!(BagsList::put_in_front_of(Origin::signed(11), 10)); + + // then + assert_eq!(List::::get_bags(), vec![(20, vec![11, 10])]); + }); + } + + #[test] + fn put_in_front_of_two_node_bag_heavier_is_head() { + ExtBuilder::default() + .skip_genesis_ids() + .add_ids(vec![(11, 16), (10, 15)]) + .build_and_execute(|| { + // given + assert_eq!(List::::get_bags(), vec![(20, vec![11, 10])]); + + // when + assert_ok!(BagsList::put_in_front_of(Origin::signed(11), 10)); + + // then + assert_eq!(List::::get_bags(), vec![(20, vec![11, 10])]); + }); + } + + #[test] + fn put_in_front_of_non_terminal_nodes_heavier_behind() { + ExtBuilder::default().add_ids(vec![(5, 1_000)]).build_and_execute(|| { + // given + assert_eq!(List::::get_bags(), vec![(10, vec![1]), (1_000, vec![2, 3, 4, 5])]); + + StakingMock::set_vote_weight_of(&3, 999); + + // when + assert_ok!(BagsList::put_in_front_of(Origin::signed(4), 3)); + + // then + assert_eq!(List::::get_bags(), vec![(10, vec![1]), (1_000, vec![2, 4, 3, 5])]); + }); + } + + #[test] + fn put_in_front_of_non_terminal_nodes_heavier_in_front() { + ExtBuilder::default() + .add_ids(vec![(5, 1_000), (6, 1_000)]) + .build_and_execute(|| { + // given + assert_eq!( + List::::get_bags(), + vec![(10, vec![1]), (1_000, vec![2, 3, 4, 5, 6])] + ); + + StakingMock::set_vote_weight_of(&5, 999); + + // when + assert_ok!(BagsList::put_in_front_of(Origin::signed(3), 5)); + + // then + assert_eq!( + List::::get_bags(), + vec![(10, vec![1]), (1_000, vec![2, 4, 3, 5, 6])] + ); + }); + } + + #[test] + fn put_in_front_of_lighter_is_head_heavier_is_non_terminal() { + ExtBuilder::default().build_and_execute(|| { + // given + assert_eq!(List::::get_bags(), vec![(10, vec![1]), (1_000, vec![2, 3, 4])]); + + StakingMock::set_vote_weight_of(&2, 999); + + // when + assert_ok!(BagsList::put_in_front_of(Origin::signed(3), 2)); + + // then + assert_eq!(List::::get_bags(), vec![(10, vec![1]), (1_000, vec![3, 2, 4])]); + }); + } + + #[test] + fn put_in_front_of_heavier_is_tail_lighter_is_non_terminal() { + ExtBuilder::default().build_and_execute(|| { + // given + assert_eq!(List::::get_bags(), vec![(10, vec![1]), (1_000, vec![2, 3, 4])]); + + StakingMock::set_vote_weight_of(&3, 999); + + // when + assert_ok!(BagsList::put_in_front_of(Origin::signed(4), 3)); + + // then + assert_eq!(List::::get_bags(), vec![(10, vec![1]), (1_000, vec![2, 4, 3])]); + }); + } + + #[test] + fn put_in_front_of_heavier_is_tail_lighter_is_head() { + ExtBuilder::default().add_ids(vec![(5, 1_000)]).build_and_execute(|| { + // given + assert_eq!(List::::get_bags(), vec![(10, vec![1]), (1_000, vec![2, 3, 4, 5])]); + + StakingMock::set_vote_weight_of(&2, 999); + + // when + assert_ok!(BagsList::put_in_front_of(Origin::signed(5), 2)); + + // then + assert_eq!(List::::get_bags(), vec![(10, vec![1]), (1_000, vec![5, 2, 3, 4])]); + }); + } + + #[test] + fn put_in_front_of_heavier_is_head_lighter_is_not_terminal() { + ExtBuilder::default().add_ids(vec![(5, 1_000)]).build_and_execute(|| { + // given + assert_eq!(List::::get_bags(), vec![(10, vec![1]), (1_000, vec![2, 3, 4, 5])]); + + StakingMock::set_vote_weight_of(&4, 999); + + // when + BagsList::put_in_front_of(Origin::signed(2), 4).unwrap(); + + // then + assert_eq!(List::::get_bags(), vec![(10, vec![1]), (1_000, vec![3, 2, 4, 5])]); + }); + } + + #[test] + fn put_in_front_of_lighter_is_tail_heavier_is_not_terminal() { + ExtBuilder::default().add_ids(vec![(5, 900)]).build_and_execute(|| { + // given + assert_eq!(List::::get_bags(), vec![(10, vec![1]), (1_000, vec![2, 3, 4, 5])]); + + // when + BagsList::put_in_front_of(Origin::signed(3), 5).unwrap(); + + // then + assert_eq!(List::::get_bags(), vec![(10, vec![1]), (1_000, vec![2, 4, 3, 5])]); + }); + } + + #[test] + fn put_in_front_of_lighter_is_tail_heavier_is_head() { + ExtBuilder::default().build_and_execute(|| { + // given + assert_eq!(List::::get_bags(), vec![(10, vec![1]), (1_000, vec![2, 3, 4])]); + + StakingMock::set_vote_weight_of(&4, 999); + + // when + BagsList::put_in_front_of(Origin::signed(2), 4).unwrap(); + + // then + assert_eq!(List::::get_bags(), vec![(10, vec![1]), (1_000, vec![3, 2, 4])]); + }); + } + + #[test] + fn put_in_front_of_errors_if_heavier_is_less_than_lighter() { + ExtBuilder::default().build_and_execute(|| { + // given + assert_eq!(List::::get_bags(), vec![(10, vec![1]), (1_000, vec![2, 3, 4])]); + + StakingMock::set_vote_weight_of(&3, 999); + + // then + assert_noop!( + BagsList::put_in_front_of(Origin::signed(3), 2), + crate::pallet::Error::::NotHeavier + ); + }); + } + + #[test] + fn put_in_front_of_errors_if_heavier_is_equal_weight_to_lighter() { + ExtBuilder::default().build_and_execute(|| { + // given + assert_eq!(List::::get_bags(), vec![(10, vec![1]), (1_000, vec![2, 3, 4])]); + + // then + assert_noop!( + BagsList::put_in_front_of(Origin::signed(3), 4), + crate::pallet::Error::::NotHeavier + ); + }); + } + + #[test] + fn put_in_front_of_errors_if_nodes_not_found() { + // `heavier` not found + ExtBuilder::default().build_and_execute(|| { + // given + assert_eq!(List::::get_bags(), vec![(10, vec![1]), (1_000, vec![2, 3, 4])]); + + assert!(!ListNodes::::contains_key(5)); + + // then + assert_noop!( + BagsList::put_in_front_of(Origin::signed(5), 4), + crate::pallet::Error::::IdNotFound + ); + }); + + // `lighter` not found + ExtBuilder::default().build_and_execute(|| { + // given + assert_eq!(List::::get_bags(), vec![(10, vec![1]), (1_000, vec![2, 3, 4])]); + + assert!(!ListNodes::::contains_key(5)); + + // then + assert_noop!( + BagsList::put_in_front_of(Origin::signed(4), 5), + crate::pallet::Error::::IdNotFound + ); + }); + } + + #[test] + fn put_in_front_of_errors_if_nodes_not_in_same_bag() { + ExtBuilder::default().build_and_execute(|| { + // given + assert_eq!(List::::get_bags(), vec![(10, vec![1]), (1_000, vec![2, 3, 4])]); + + // then + assert_noop!( + BagsList::put_in_front_of(Origin::signed(4), 1), + crate::pallet::Error::::NotInSameBag + ); + }); + } } mod sorted_list_provider { diff --git a/frame/bags-list/src/weights.rs b/frame/bags-list/src/weights.rs index 95d3dfa6eb98..7433c7ac564f 100644 --- a/frame/bags-list/src/weights.rs +++ b/frame/bags-list/src/weights.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_bags_list //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-09-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2021-11-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 // Executed Command: @@ -35,7 +35,6 @@ // --output=./frame/bags-list/src/weights.rs // --template=./.maintain/frame-weight-template.hbs - #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] #![allow(unused_imports)] @@ -47,6 +46,7 @@ use sp_std::marker::PhantomData; pub trait WeightInfo { fn rebag_non_terminal() -> Weight; fn rebag_terminal() -> Weight; + fn put_in_front_of() -> Weight; } /// Weights for pallet_bags_list using the Substrate node and recommended hardware. @@ -57,7 +57,7 @@ impl WeightInfo for SubstrateWeight { // Storage: BagsList ListNodes (r:4 w:4) // Storage: BagsList ListBags (r:1 w:1) fn rebag_non_terminal() -> Weight { - (74_175_000 as Weight) + (70_481_000 as Weight) .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } @@ -66,10 +66,20 @@ impl WeightInfo for SubstrateWeight { // Storage: BagsList ListNodes (r:3 w:3) // Storage: BagsList ListBags (r:2 w:2) fn rebag_terminal() -> Weight { - (73_305_000 as Weight) + (68_642_000 as Weight) .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } + // Storage: BagsList ListNodes (r:4 w:4) + // Storage: Staking Bonded (r:2 w:0) + // Storage: Staking Ledger (r:2 w:0) + // Storage: BagsList CounterForListNodes (r:1 w:1) + // Storage: BagsList ListBags (r:1 w:1) + fn put_in_front_of() -> Weight { + (82_341_000 as Weight) + .saturating_add(T::DbWeight::get().reads(10 as Weight)) + .saturating_add(T::DbWeight::get().writes(6 as Weight)) + } } // For backwards compatibility and tests @@ -79,7 +89,7 @@ impl WeightInfo for () { // Storage: BagsList ListNodes (r:4 w:4) // Storage: BagsList ListBags (r:1 w:1) fn rebag_non_terminal() -> Weight { - (74_175_000 as Weight) + (70_481_000 as Weight) .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } @@ -88,8 +98,18 @@ impl WeightInfo for () { // Storage: BagsList ListNodes (r:3 w:3) // Storage: BagsList ListBags (r:2 w:2) fn rebag_terminal() -> Weight { - (73_305_000 as Weight) + (68_642_000 as Weight) .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } + // Storage: BagsList ListNodes (r:4 w:4) + // Storage: Staking Bonded (r:2 w:0) + // Storage: Staking Ledger (r:2 w:0) + // Storage: BagsList CounterForListNodes (r:1 w:1) + // Storage: BagsList ListBags (r:1 w:1) + fn put_in_front_of() -> Weight { + (82_341_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(10 as Weight)) + .saturating_add(RocksDbWeight::get().writes(6 as Weight)) + } } From 2651d5cf410700c8a9bbe1b5df54aa9956926b34 Mon Sep 17 00:00:00 2001 From: Gavin Wood Date: Wed, 8 Dec 2021 11:28:03 +0100 Subject: [PATCH 266/695] Introduce CheckNonZeroSender (#10413) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Introduce CheckNonZeroSender * Missing file * Formatting * Fixes * Formatting * some fixes to compile * Update frame/system/src/extensions/check_non_zero_sender.rs Co-authored-by: Bastian Köcher * Fixes * Fixes * another fix * Formatting Co-authored-by: Shawn Tabrizi Co-authored-by: Bastian Köcher --- bin/node/cli/src/service.rs | 6 +- bin/node/executor/tests/submit_transaction.rs | 4 +- bin/node/runtime/src/lib.rs | 2 + bin/node/test-runner-example/src/lib.rs | 1 + bin/node/testing/src/keyring.rs | 1 + .../src/extensions/check_non_zero_sender.rs | 100 ++++++++++++++++++ frame/system/src/extensions/mod.rs | 1 + frame/system/src/lib.rs | 3 +- .../runtime/src/transaction_validity.rs | 3 + test-utils/test-runner/src/lib.rs | 1 + 10 files changed, 118 insertions(+), 4 deletions(-) create mode 100644 frame/system/src/extensions/check_non_zero_sender.rs diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index fec91a9b67cc..1dfce9331b75 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -83,6 +83,7 @@ pub fn create_extrinsic( .unwrap_or(2) as u64; let tip = 0; let extra: node_runtime::SignedExtra = ( + frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), frame_system::CheckGenesis::::new(), @@ -99,6 +100,7 @@ pub fn create_extrinsic( function.clone(), extra.clone(), ( + (), node_runtime::VERSION.spec_version, node_runtime::VERSION.transaction_version, genesis_hash, @@ -719,6 +721,7 @@ mod tests { let function = Call::Balances(BalancesCall::transfer { dest: to.into(), value: amount }); + let check_non_zero_sender = frame_system::CheckNonZeroSender::new(); let check_spec_version = frame_system::CheckSpecVersion::new(); let check_tx_version = frame_system::CheckTxVersion::new(); let check_genesis = frame_system::CheckGenesis::new(); @@ -727,6 +730,7 @@ mod tests { let check_weight = frame_system::CheckWeight::new(); let tx_payment = pallet_asset_tx_payment::ChargeAssetTxPayment::from(0, None); let extra = ( + check_non_zero_sender, check_spec_version, check_tx_version, check_genesis, @@ -738,7 +742,7 @@ mod tests { let raw_payload = SignedPayload::from_raw( function, extra, - (spec_version, transaction_version, genesis_hash, genesis_hash, (), (), ()), + ((), spec_version, transaction_version, genesis_hash, genesis_hash, (), (), ()), ); let signature = raw_payload.using_encoded(|payload| signer.sign(payload)); let (function, extra, _) = raw_payload.deconstruct(); diff --git a/bin/node/executor/tests/submit_transaction.rs b/bin/node/executor/tests/submit_transaction.rs index f047c6a44a66..4f0f8061641f 100644 --- a/bin/node/executor/tests/submit_transaction.rs +++ b/bin/node/executor/tests/submit_transaction.rs @@ -146,7 +146,7 @@ fn should_submit_signed_twice_from_the_same_account() { let s = state.read(); fn nonce(tx: UncheckedExtrinsic) -> frame_system::CheckNonce { let extra = tx.signature.unwrap().2; - extra.4 + extra.5 } let nonce1 = nonce(UncheckedExtrinsic::decode(&mut &*s.transactions[0]).unwrap()); let nonce2 = nonce(UncheckedExtrinsic::decode(&mut &*s.transactions[1]).unwrap()); @@ -195,7 +195,7 @@ fn should_submit_signed_twice_from_all_accounts() { let s = state.read(); fn nonce(tx: UncheckedExtrinsic) -> frame_system::CheckNonce { let extra = tx.signature.unwrap().2; - extra.4 + extra.5 } let nonce1 = nonce(UncheckedExtrinsic::decode(&mut &*s.transactions[0]).unwrap()); let nonce2 = nonce(UncheckedExtrinsic::decode(&mut &*s.transactions[1]).unwrap()); diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 45b49dc46b89..44d39a870efc 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -984,6 +984,7 @@ where .saturating_sub(1); let era = Era::mortal(period, current_block); let extra = ( + frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), frame_system::CheckGenesis::::new(), @@ -1334,6 +1335,7 @@ pub type BlockId = generic::BlockId; /// /// [`sign`]: <../../testing/src/keyring.rs.html> pub type SignedExtra = ( + frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, frame_system::CheckGenesis, diff --git a/bin/node/test-runner-example/src/lib.rs b/bin/node/test-runner-example/src/lib.rs index 68c14b73bf56..e247fca22320 100644 --- a/bin/node/test-runner-example/src/lib.rs +++ b/bin/node/test-runner-example/src/lib.rs @@ -69,6 +69,7 @@ impl ChainInfo for NodeTemplateChainInfo { from: ::AccountId, ) -> Self::SignedExtras { ( + frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), frame_system::CheckGenesis::::new(), diff --git a/bin/node/testing/src/keyring.rs b/bin/node/testing/src/keyring.rs index 1040e90c4d5d..3e6dff301fc4 100644 --- a/bin/node/testing/src/keyring.rs +++ b/bin/node/testing/src/keyring.rs @@ -70,6 +70,7 @@ pub fn to_session_keys( /// Returns transaction extra. pub fn signed_extra(nonce: Index, extra_fee: Balance) -> SignedExtra { ( + frame_system::CheckNonZeroSender::new(), frame_system::CheckSpecVersion::new(), frame_system::CheckTxVersion::new(), frame_system::CheckGenesis::new(), diff --git a/frame/system/src/extensions/check_non_zero_sender.rs b/frame/system/src/extensions/check_non_zero_sender.rs new file mode 100644 index 000000000000..1d45ae17cb7a --- /dev/null +++ b/frame/system/src/extensions/check_non_zero_sender.rs @@ -0,0 +1,100 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2021 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. + +use crate::Config; +use codec::{Decode, Encode}; +use frame_support::weights::DispatchInfo; +use scale_info::TypeInfo; +use sp_runtime::{ + traits::{DispatchInfoOf, Dispatchable, SignedExtension}, + transaction_validity::{ + InvalidTransaction, TransactionValidity, TransactionValidityError, ValidTransaction, + }, +}; +use sp_std::{marker::PhantomData, prelude::*}; + +/// Check to ensure that the sender is not the zero address. +#[derive(Encode, Decode, Clone, Eq, PartialEq, TypeInfo)] +#[scale_info(skip_type_params(T))] +pub struct CheckNonZeroSender(PhantomData); + +impl sp_std::fmt::Debug for CheckNonZeroSender { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + write!(f, "CheckNonZeroSender") + } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + Ok(()) + } +} + +impl CheckNonZeroSender { + /// Create new `SignedExtension` to check runtime version. + pub fn new() -> Self { + Self(sp_std::marker::PhantomData) + } +} + +impl SignedExtension for CheckNonZeroSender +where + T::Call: Dispatchable, +{ + type AccountId = T::AccountId; + type Call = T::Call; + type AdditionalSigned = (); + type Pre = (); + const IDENTIFIER: &'static str = "CheckNonZeroSender"; + + fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { + Ok(()) + } + + fn validate( + &self, + who: &Self::AccountId, + _call: &Self::Call, + _info: &DispatchInfoOf, + _len: usize, + ) -> TransactionValidity { + if who.using_encoded(|d| d.into_iter().all(|x| *x == 0)) { + return Err(TransactionValidityError::Invalid(InvalidTransaction::BadSigner)) + } + Ok(ValidTransaction::default()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::{new_test_ext, Test, CALL}; + use frame_support::{assert_noop, assert_ok}; + + #[test] + fn zero_account_ban_works() { + new_test_ext().execute_with(|| { + let info = DispatchInfo::default(); + let len = 0_usize; + assert_noop!( + CheckNonZeroSender::::new().validate(&0, CALL, &info, len), + InvalidTransaction::BadSigner + ); + assert_ok!(CheckNonZeroSender::::new().validate(&1, CALL, &info, len)); + }) + } +} diff --git a/frame/system/src/extensions/mod.rs b/frame/system/src/extensions/mod.rs index 0af9722e475d..7eaff34c1d7f 100644 --- a/frame/system/src/extensions/mod.rs +++ b/frame/system/src/extensions/mod.rs @@ -17,6 +17,7 @@ pub mod check_genesis; pub mod check_mortality; +pub mod check_non_zero_sender; pub mod check_nonce; pub mod check_spec_version; pub mod check_tx_version; diff --git a/frame/system/src/lib.rs b/frame/system/src/lib.rs index aac104fa8f76..7603fe654141 100644 --- a/frame/system/src/lib.rs +++ b/frame/system/src/lib.rs @@ -115,7 +115,8 @@ mod tests; pub mod weights; pub use extensions::{ - check_genesis::CheckGenesis, check_mortality::CheckMortality, check_nonce::CheckNonce, + check_genesis::CheckGenesis, check_mortality::CheckMortality, + check_non_zero_sender::CheckNonZeroSender, check_nonce::CheckNonce, check_spec_version::CheckSpecVersion, check_tx_version::CheckTxVersion, check_weight::CheckWeight, }; diff --git a/primitives/runtime/src/transaction_validity.rs b/primitives/runtime/src/transaction_validity.rs index e114bb598546..cf5d92597599 100644 --- a/primitives/runtime/src/transaction_validity.rs +++ b/primitives/runtime/src/transaction_validity.rs @@ -79,6 +79,8 @@ pub enum InvalidTransaction { /// A transaction with a mandatory dispatch. This is invalid; only inherent extrinsics are /// allowed to have mandatory dispatches. MandatoryDispatch, + /// The sending address is disabled or known to be invalid. + BadSigner, } impl InvalidTransaction { @@ -109,6 +111,7 @@ impl From for &'static str { InvalidTransaction::MandatoryDispatch => "Transaction dispatch is mandatory; transactions may not have mandatory dispatches.", InvalidTransaction::Custom(_) => "InvalidTransaction custom error", + InvalidTransaction::BadSigner => "Invalid signing address", } } } diff --git a/test-utils/test-runner/src/lib.rs b/test-utils/test-runner/src/lib.rs index ca2c518fd692..9f51442ed743 100644 --- a/test-utils/test-runner/src/lib.rs +++ b/test-utils/test-runner/src/lib.rs @@ -106,6 +106,7 @@ //! let nonce = frame_system::Pallet::::account_nonce(from); //! //! ( +//! frame_system::CheckNonZeroSender::::new(), //! frame_system::CheckSpecVersion::::new(), //! frame_system::CheckTxVersion::::new(), //! frame_system::CheckGenesis::::new(), From 25e636bcbf756afb4d4534c62ad9e9b806e98be7 Mon Sep 17 00:00:00 2001 From: David Date: Wed, 8 Dec 2021 21:06:50 +0100 Subject: [PATCH 267/695] Release sp-core 4.0.0 (#10447) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Bump versions of sp-core and dependencies to v4.0.0 * Update references from `4.0.0-dev` –> `4.0.0` * Funny whitespace * Funny whitespace 2 --- Cargo.lock | 20 +++++++++---------- bin/node-template/node/Cargo.toml | 2 +- bin/node-template/pallets/template/Cargo.toml | 2 +- bin/node-template/runtime/Cargo.toml | 4 ++-- bin/node/bench/Cargo.toml | 4 ++-- bin/node/cli/Cargo.toml | 4 ++-- bin/node/executor/Cargo.toml | 6 +++--- bin/node/inspect/Cargo.toml | 2 +- bin/node/primitives/Cargo.toml | 2 +- bin/node/runtime/Cargo.toml | 4 ++-- bin/node/testing/Cargo.toml | 2 +- bin/utils/chain-spec-builder/Cargo.toml | 2 +- client/allocator/Cargo.toml | 4 ++-- client/api/Cargo.toml | 6 +++--- client/authority-discovery/Cargo.toml | 4 ++-- client/basic-authorship/Cargo.toml | 2 +- client/beefy/Cargo.toml | 4 ++-- client/beefy/rpc/Cargo.toml | 2 +- client/block-builder/Cargo.toml | 2 +- client/chain-spec/Cargo.toml | 2 +- client/cli/Cargo.toml | 2 +- client/consensus/aura/Cargo.toml | 4 ++-- client/consensus/babe/Cargo.toml | 4 ++-- client/consensus/babe/rpc/Cargo.toml | 2 +- client/consensus/common/Cargo.toml | 2 +- client/consensus/manual-seal/Cargo.toml | 2 +- client/consensus/pow/Cargo.toml | 2 +- client/consensus/slots/Cargo.toml | 2 +- client/db/Cargo.toml | 4 ++-- client/executor/Cargo.toml | 8 ++++---- client/executor/common/Cargo.toml | 4 ++-- client/executor/runtime-test/Cargo.toml | 4 ++-- client/executor/wasmi/Cargo.toml | 6 +++--- client/executor/wasmtime/Cargo.toml | 6 +++--- client/finality-grandpa/Cargo.toml | 4 ++-- client/finality-grandpa/rpc/Cargo.toml | 4 ++-- client/keystore/Cargo.toml | 2 +- client/network/Cargo.toml | 4 ++-- client/network/test/Cargo.toml | 4 ++-- client/offchain/Cargo.toml | 4 ++-- client/rpc-api/Cargo.toml | 4 ++-- client/rpc/Cargo.toml | 2 +- client/service/Cargo.toml | 8 ++++---- client/service/test/Cargo.toml | 8 ++++---- client/state-db/Cargo.toml | 2 +- client/tracing/Cargo.toml | 4 ++-- client/transaction-pool/Cargo.toml | 4 ++-- frame/assets/Cargo.toml | 6 +++--- frame/atomic-swap/Cargo.toml | 4 ++-- frame/aura/Cargo.toml | 4 ++-- frame/authority-discovery/Cargo.toml | 4 ++-- frame/authorship/Cargo.toml | 4 ++-- frame/babe/Cargo.toml | 4 ++-- frame/bags-list/Cargo.toml | 11 +++++----- frame/bags-list/remote-tests/Cargo.toml | 8 ++++---- frame/balances/Cargo.toml | 4 ++-- frame/beefy-mmr/Cargo.toml | 4 ++-- frame/beefy/Cargo.toml | 4 ++-- frame/benchmarking/Cargo.toml | 6 +++--- frame/bounties/Cargo.toml | 4 ++-- frame/child-bounties/Cargo.toml | 4 ++-- frame/collective/Cargo.toml | 4 ++-- frame/contracts/Cargo.toml | 4 ++-- frame/contracts/common/Cargo.toml | 4 ++-- frame/contracts/rpc/Cargo.toml | 2 +- frame/contracts/rpc/runtime-api/Cargo.toml | 2 +- frame/democracy/Cargo.toml | 4 ++-- .../election-provider-multi-phase/Cargo.toml | 8 ++++---- frame/election-provider-support/Cargo.toml | 4 ++-- frame/elections-phragmen/Cargo.toml | 6 +++--- frame/elections/Cargo.toml | 4 ++-- frame/examples/basic/Cargo.toml | 4 ++-- frame/examples/offchain-worker/Cargo.toml | 4 ++-- frame/examples/parallel/Cargo.toml | 4 ++-- frame/executive/Cargo.toml | 8 ++++---- frame/gilt/Cargo.toml | 4 ++-- frame/grandpa/Cargo.toml | 4 ++-- frame/identity/Cargo.toml | 4 ++-- frame/im-online/Cargo.toml | 4 ++-- frame/indices/Cargo.toml | 4 ++-- frame/lottery/Cargo.toml | 4 ++-- frame/membership/Cargo.toml | 4 ++-- frame/merkle-mountain-range/Cargo.toml | 4 ++-- .../primitives/Cargo.toml | 4 ++-- frame/merkle-mountain-range/rpc/Cargo.toml | 2 +- frame/multisig/Cargo.toml | 4 ++-- frame/nicks/Cargo.toml | 4 ++-- frame/node-authorization/Cargo.toml | 4 ++-- frame/offences/Cargo.toml | 4 ++-- frame/offences/benchmarking/Cargo.toml | 4 ++-- frame/proxy/Cargo.toml | 4 ++-- frame/randomness-collective-flip/Cargo.toml | 4 ++-- frame/recovery/Cargo.toml | 4 ++-- frame/scheduler/Cargo.toml | 4 ++-- frame/scored-pool/Cargo.toml | 4 ++-- frame/session/Cargo.toml | 4 ++-- frame/session/benchmarking/Cargo.toml | 4 ++-- frame/society/Cargo.toml | 4 ++-- frame/staking/Cargo.toml | 6 +++--- frame/sudo/Cargo.toml | 4 ++-- frame/support/Cargo.toml | 6 +++--- frame/support/test/Cargo.toml | 4 ++-- frame/support/test/compile_pass/Cargo.toml | 2 +- frame/system/Cargo.toml | 6 +++--- frame/system/benchmarking/Cargo.toml | 4 ++-- frame/timestamp/Cargo.toml | 4 ++-- frame/tips/Cargo.toml | 6 +++--- frame/transaction-payment/Cargo.toml | 4 ++-- .../asset-tx-payment/Cargo.toml | 6 +++--- frame/transaction-payment/rpc/Cargo.toml | 2 +- frame/transaction-storage/Cargo.toml | 4 ++-- frame/treasury/Cargo.toml | 4 ++-- frame/try-runtime/Cargo.toml | 2 +- frame/uniques/Cargo.toml | 6 +++--- frame/utility/Cargo.toml | 6 +++--- frame/vesting/Cargo.toml | 4 ++-- primitives/api/Cargo.toml | 4 ++-- primitives/api/test/Cargo.toml | 4 ++-- primitives/application-crypto/Cargo.toml | 4 ++-- primitives/application-crypto/test/Cargo.toml | 2 +- primitives/arithmetic/Cargo.toml | 4 ++-- primitives/authority-discovery/Cargo.toml | 2 +- primitives/authorship/Cargo.toml | 2 +- primitives/beefy/Cargo.toml | 4 ++-- primitives/block-builder/Cargo.toml | 2 +- primitives/consensus/aura/Cargo.toml | 2 +- primitives/consensus/babe/Cargo.toml | 4 ++-- primitives/consensus/common/Cargo.toml | 4 ++-- primitives/consensus/pow/Cargo.toml | 4 ++-- primitives/consensus/vrf/Cargo.toml | 4 ++-- primitives/core/Cargo.toml | 14 ++++++------- primitives/core/hashing/Cargo.toml | 4 ++-- primitives/core/hashing/proc-macro/Cargo.toml | 2 +- primitives/debug-derive/Cargo.toml | 2 +- primitives/externalities/Cargo.toml | 6 +++--- primitives/finality-grandpa/Cargo.toml | 4 ++-- primitives/inherents/Cargo.toml | 4 ++-- primitives/io/Cargo.toml | 12 +++++------ primitives/keyring/Cargo.toml | 2 +- primitives/keystore/Cargo.toml | 4 ++-- primitives/npos-elections/Cargo.toml | 4 ++-- primitives/offchain/Cargo.toml | 2 +- primitives/rpc/Cargo.toml | 2 +- primitives/runtime-interface/Cargo.toml | 16 +++++++-------- .../runtime-interface/proc-macro/Cargo.toml | 2 +- .../test-wasm-deprecated/Cargo.toml | 6 +++--- .../runtime-interface/test-wasm/Cargo.toml | 6 +++--- primitives/runtime-interface/test/Cargo.toml | 2 +- primitives/runtime/Cargo.toml | 6 +++--- primitives/sandbox/Cargo.toml | 6 +++--- primitives/session/Cargo.toml | 4 ++-- primitives/staking/Cargo.toml | 2 +- primitives/state-machine/Cargo.toml | 6 +++--- primitives/std/Cargo.toml | 2 +- primitives/storage/Cargo.toml | 6 +++--- primitives/tasks/Cargo.toml | 8 ++++---- primitives/test-primitives/Cargo.toml | 2 +- primitives/timestamp/Cargo.toml | 2 +- primitives/tracing/Cargo.toml | 4 ++-- .../transaction-storage-proof/Cargo.toml | 4 ++-- primitives/trie/Cargo.toml | 4 ++-- primitives/version/Cargo.toml | 2 +- primitives/wasm-interface/Cargo.toml | 4 ++-- test-utils/client/Cargo.toml | 2 +- test-utils/runtime/Cargo.toml | 8 ++++---- test-utils/runtime/client/Cargo.toml | 2 +- utils/frame/benchmarking-cli/Cargo.toml | 4 ++-- utils/frame/frame-utilities-cli/Cargo.toml | 2 +- utils/frame/remote-externalities/Cargo.toml | 2 +- utils/frame/rpc/support/Cargo.toml | 2 +- utils/frame/rpc/system/Cargo.toml | 4 ++-- utils/frame/try-runtime/cli/Cargo.toml | 4 ++-- 172 files changed, 360 insertions(+), 361 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d1618f83b476..3693fe080693 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9391,7 +9391,7 @@ dependencies = [ [[package]] name = "sp-core" -version = "4.0.0-dev" +version = "4.0.0" dependencies = [ "base58", "bitflags", @@ -9443,7 +9443,7 @@ dependencies = [ [[package]] name = "sp-core-hashing" -version = "4.0.0-dev" +version = "4.0.0" dependencies = [ "blake2-rfc", "byteorder", @@ -9473,7 +9473,7 @@ dependencies = [ [[package]] name = "sp-debug-derive" -version = "4.0.0-dev" +version = "4.0.0" dependencies = [ "proc-macro2", "quote", @@ -9482,7 +9482,7 @@ dependencies = [ [[package]] name = "sp-externalities" -version = "0.10.0-dev" +version = "0.10.0" dependencies = [ "environmental", "parity-scale-codec", @@ -9680,7 +9680,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface" -version = "4.0.0-dev" +version = "4.0.0" dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", @@ -9702,7 +9702,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface-proc-macro" -version = "4.0.0-dev" +version = "4.0.0" dependencies = [ "Inflector", "proc-macro-crate 1.1.0", @@ -9822,11 +9822,11 @@ dependencies = [ [[package]] name = "sp-std" -version = "4.0.0-dev" +version = "4.0.0" [[package]] name = "sp-storage" -version = "4.0.0-dev" +version = "4.0.0" dependencies = [ "impl-serde", "parity-scale-codec", @@ -9878,7 +9878,7 @@ dependencies = [ [[package]] name = "sp-tracing" -version = "4.0.0-dev" +version = "4.0.0" dependencies = [ "parity-scale-codec", "sp-std", @@ -9957,7 +9957,7 @@ dependencies = [ [[package]] name = "sp-wasm-interface" -version = "4.0.0-dev" +version = "4.0.0" dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", diff --git a/bin/node-template/node/Cargo.toml b/bin/node-template/node/Cargo.toml index 6f3a63593aa3..2680b91b3a25 100644 --- a/bin/node-template/node/Cargo.toml +++ b/bin/node-template/node/Cargo.toml @@ -20,7 +20,7 @@ name = "node-template" structopt = "0.3.25" sc-cli = { version = "0.10.0-dev", path = "../../../client/cli", features = ["wasmtime"] } -sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../../primitives/core" } sc-executor = { version = "0.10.0-dev", path = "../../../client/executor", features = ["wasmtime"] } sc-service = { version = "0.10.0-dev", path = "../../../client/service", features = ["wasmtime"] } sc-telemetry = { version = "4.0.0-dev", path = "../../../client/telemetry" } diff --git a/bin/node-template/pallets/template/Cargo.toml b/bin/node-template/pallets/template/Cargo.toml index 887b022d6ca7..646038ca6ced 100644 --- a/bin/node-template/pallets/template/Cargo.toml +++ b/bin/node-template/pallets/template/Cargo.toml @@ -22,7 +22,7 @@ frame-system = { default-features = false, version = "4.0.0-dev", path = "../../ frame-benchmarking = { default-features = false, version = "4.0.0-dev", path = "../../../../frame/benchmarking", optional = true } [dev-dependencies] -sp-core = { default-features = false, version = "4.0.0-dev", path = "../../../../primitives/core" } +sp-core = { default-features = false, version = "4.0.0", path = "../../../../primitives/core" } sp-io = { default-features = false, version = "4.0.0-dev", path = "../../../../primitives/io" } sp-runtime = { default-features = false, version = "4.0.0-dev", path = "../../../../primitives/runtime" } diff --git a/bin/node-template/runtime/Cargo.toml b/bin/node-template/runtime/Cargo.toml index c7ff0ff5a268..a25c45c692de 100644 --- a/bin/node-template/runtime/Cargo.toml +++ b/bin/node-template/runtime/Cargo.toml @@ -29,12 +29,12 @@ frame-executive = { version = "4.0.0-dev", default-features = false, path = "../ sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/api" } sp-block-builder = { path = "../../../primitives/block-builder", default-features = false, version = "4.0.0-dev"} sp-consensus-aura = { version = "0.10.0-dev", default-features = false, path = "../../../primitives/consensus/aura" } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/core" } +sp-core = { version = "4.0.0", default-features = false, path = "../../../primitives/core" } sp-inherents = { path = "../../../primitives/inherents", default-features = false, version = "4.0.0-dev"} sp-offchain = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/offchain" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/session" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } sp-transaction-pool = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/transaction-pool" } sp-version = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/version" } diff --git a/bin/node/bench/Cargo.toml b/bin/node/bench/Cargo.toml index 0beeb4e339e4..27c26d21dfe0 100644 --- a/bin/node/bench/Cargo.toml +++ b/bin/node/bench/Cargo.toml @@ -23,12 +23,12 @@ derive_more = "0.99.16" kvdb = "0.10.0" kvdb-rocksdb = "0.14.0" sp-trie = { version = "4.0.0-dev", path = "../../../primitives/trie" } -sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../../primitives/core" } sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" } sc-basic-authorship = { version = "0.10.0-dev", path = "../../../client/basic-authorship" } sp-inherents = { version = "4.0.0-dev", path = "../../../primitives/inherents" } sp-timestamp = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/timestamp" } -sp-tracing = { version = "4.0.0-dev", path = "../../../primitives/tracing" } +sp-tracing = { version = "4.0.0", path = "../../../primitives/tracing" } hash-db = "0.15.2" tempfile = "3.1.0" fs_extra = "1" diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index 42df74100415..cb632d936a2d 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -47,7 +47,7 @@ sp-authority-discovery = { version = "4.0.0-dev", path = "../../../primitives/au sp-consensus-babe = { version = "0.10.0-dev", path = "../../../primitives/consensus/babe" } grandpa-primitives = { version = "4.0.0-dev", package = "sp-finality-grandpa", path = "../../../primitives/finality-grandpa" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } -sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../../primitives/core" } sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } sp-timestamp = { version = "4.0.0-dev", path = "../../../primitives/timestamp" } sp-authorship = { version = "4.0.0-dev", path = "../../../primitives/authorship" } @@ -118,7 +118,7 @@ sc-consensus-babe = { version = "0.10.0-dev", path = "../../../client/consensus/ sc-consensus-epochs = { version = "0.10.0-dev", path = "../../../client/consensus/epochs" } sc-service-test = { version = "2.0.0", path = "../../../client/service/test" } sc-block-builder = { version = "0.10.0-dev", path = "../../../client/block-builder" } -sp-tracing = { version = "4.0.0-dev", path = "../../../primitives/tracing" } +sp-tracing = { version = "4.0.0", path = "../../../primitives/tracing" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } futures = "0.3.16" tempfile = "3.1.0" diff --git a/bin/node/executor/Cargo.toml b/bin/node/executor/Cargo.toml index 6fdd5f8d2351..13ed4d313994 100644 --- a/bin/node/executor/Cargo.toml +++ b/bin/node/executor/Cargo.toml @@ -17,10 +17,10 @@ scale-info = { version = "1.0", features = ["derive"] } node-primitives = { version = "2.0.0", path = "../primitives" } node-runtime = { version = "3.0.0-dev", path = "../runtime" } sc-executor = { version = "0.10.0-dev", path = "../../../client/executor" } -sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../../primitives/core" } sp-keystore = { version = "0.10.0-dev", path = "../../../primitives/keystore" } sp-state-machine = { version = "0.10.0-dev", path = "../../../primitives/state-machine" } -sp-tracing = { version = "4.0.0-dev", path = "../../../primitives/tracing" } +sp-tracing = { version = "4.0.0", path = "../../../primitives/tracing" } sp-trie = { version = "4.0.0-dev", path = "../../../primitives/trie" } frame-benchmarking = { version = "4.0.0-dev", path = "../../../frame/benchmarking" } @@ -37,7 +37,7 @@ pallet-treasury = { version = "4.0.0-dev", path = "../../../frame/treasury" } sp-application-crypto = { version = "4.0.0-dev", path = "../../../primitives/application-crypto" } sp-consensus-babe = { version = "0.10.0-dev", path = "../../../primitives/consensus/babe" } sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } -sp-externalities = { version = "0.10.0-dev", path = "../../../primitives/externalities" } +sp-externalities = { version = "0.10.0", path = "../../../primitives/externalities" } wat = "1.0" futures = "0.3.9" diff --git a/bin/node/inspect/Cargo.toml b/bin/node/inspect/Cargo.toml index 6504f39a0582..18f24651ed35 100644 --- a/bin/node/inspect/Cargo.toml +++ b/bin/node/inspect/Cargo.toml @@ -18,6 +18,6 @@ sc-client-api = { version = "4.0.0-dev", path = "../../../client/api" } sc-executor = { version = "0.10.0-dev", path = "../../../client/executor" } sc-service = { version = "0.10.0-dev", default-features = false, path = "../../../client/service" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../../primitives/core" } sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } structopt = "0.3.8" diff --git a/bin/node/primitives/Cargo.toml b/bin/node/primitives/Cargo.toml index 2c8185d5c9c4..03d587acecd2 100644 --- a/bin/node/primitives/Cargo.toml +++ b/bin/node/primitives/Cargo.toml @@ -17,7 +17,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../../frame/system" } sp-application-crypto = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/application-crypto" } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/core" } +sp-core = { version = "4.0.0", default-features = false, path = "../../../primitives/core" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } [features] diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index a61c2311917a..b36fd622dfa3 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -30,8 +30,8 @@ sp-block-builder = { path = "../../../primitives/block-builder", default-feature sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/inherents" } node-primitives = { version = "2.0.0", default-features = false, path = "../primitives" } sp-offchain = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/offchain" } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/core" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/std" } +sp-core = { version = "4.0.0", default-features = false, path = "../../../primitives/core" } +sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/api" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/staking" } diff --git a/bin/node/testing/Cargo.toml b/bin/node/testing/Cargo.toml index 0e5ed07ac295..0fb0d40a7c2d 100644 --- a/bin/node/testing/Cargo.toml +++ b/bin/node/testing/Cargo.toml @@ -28,7 +28,7 @@ sp-keyring = { version = "4.0.0-dev", path = "../../../primitives/keyring" } node-executor = { version = "3.0.0-dev", path = "../executor" } node-primitives = { version = "2.0.0", path = "../primitives" } node-runtime = { version = "3.0.0-dev", path = "../runtime" } -sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../../primitives/core" } sp-io = { version = "4.0.0-dev", path = "../../../primitives/io" } sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } sc-executor = { version = "0.10.0-dev", path = "../../../client/executor", features = [ diff --git a/bin/utils/chain-spec-builder/Cargo.toml b/bin/utils/chain-spec-builder/Cargo.toml index daffd5a0359a..79eb5becfeb8 100644 --- a/bin/utils/chain-spec-builder/Cargo.toml +++ b/bin/utils/chain-spec-builder/Cargo.toml @@ -18,7 +18,7 @@ ansi_term = "0.12.1" sc-keystore = { version = "4.0.0-dev", path = "../../../client/keystore" } sc-chain-spec = { version = "4.0.0-dev", path = "../../../client/chain-spec" } node-cli = { version = "3.0.0-dev", path = "../../node/cli" } -sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../../primitives/core" } sp-keystore = { version = "0.10.0-dev", path = "../../../primitives/keystore" } rand = "0.7.2" structopt = "0.3.25" diff --git a/client/allocator/Cargo.toml b/client/allocator/Cargo.toml index 44facf0ad889..48191273ff36 100644 --- a/client/allocator/Cargo.toml +++ b/client/allocator/Cargo.toml @@ -14,7 +14,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } -sp-wasm-interface = { version = "4.0.0-dev", path = "../../primitives/wasm-interface" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-wasm-interface = { version = "4.0.0", path = "../../primitives/wasm-interface" } log = "0.4.11" thiserror = "1.0.30" diff --git a/client/api/Cargo.toml b/client/api/Cargo.toml index 39fe804a1415..5e0fe88b3ca7 100644 --- a/client/api/Cargo.toml +++ b/client/api/Cargo.toml @@ -19,7 +19,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = ] } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } sc-executor = { version = "0.10.0-dev", path = "../executor" } -sp-externalities = { version = "0.10.0-dev", path = "../../primitives/externalities" } +sp-externalities = { version = "0.10.0", path = "../../primitives/externalities" } fnv = "1.0.6" futures = "0.3.1" hash-db = { version = "0.15.2", default-features = false } @@ -27,14 +27,14 @@ sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } log = "0.4.8" parking_lot = "0.11.1" sp-database = { version = "4.0.0-dev", path = "../../primitives/database" } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" } +sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } sp-keystore = { version = "0.10.0-dev", default-features = false, path = "../../primitives/keystore" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } sc-utils = { version = "4.0.0-dev", path = "../utils" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } sp-state-machine = { version = "0.10.0-dev", path = "../../primitives/state-machine" } sp-trie = { version = "4.0.0-dev", path = "../../primitives/trie" } -sp-storage = { version = "4.0.0-dev", path = "../../primitives/storage" } +sp-storage = { version = "4.0.0", path = "../../primitives/storage" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../transaction-pool/api" } prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.10.0-dev", path = "../../utils/prometheus" } diff --git a/client/authority-discovery/Cargo.toml b/client/authority-discovery/Cargo.toml index f3169e82fb3c..8dcf8ab4c814 100644 --- a/client/authority-discovery/Cargo.toml +++ b/client/authority-discovery/Cargo.toml @@ -32,12 +32,12 @@ sc-client-api = { version = "4.0.0-dev", path = "../api" } sc-network = { version = "0.10.0-dev", path = "../network" } sp-authority-discovery = { version = "4.0.0-dev", path = "../../primitives/authority-discovery" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } sp-keystore = { version = "0.10.0-dev", path = "../../primitives/keystore" } sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } [dev-dependencies] quickcheck = "1.0.3" -sp-tracing = { version = "4.0.0-dev", path = "../../primitives/tracing" } +sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } diff --git a/client/basic-authorship/Cargo.toml b/client/basic-authorship/Cargo.toml index 4bfc3ca50c83..049876f47879 100644 --- a/client/basic-authorship/Cargo.toml +++ b/client/basic-authorship/Cargo.toml @@ -20,7 +20,7 @@ log = "0.4.8" prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.10.0-dev"} sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sc-client-api = { version = "4.0.0-dev", path = "../api" } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } diff --git a/client/beefy/Cargo.toml b/client/beefy/Cargo.toml index 23c9294d3510..b0f05888712d 100644 --- a/client/beefy/Cargo.toml +++ b/client/beefy/Cargo.toml @@ -22,7 +22,7 @@ sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } sp-application-crypto = { version = "4.0.0-dev", path = "../../primitives/application-crypto" } sp-arithmetic = { version = "4.0.0-dev", path = "../../primitives/arithmetic" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } sp-keystore = { version = "0.10.0-dev", path = "../../primitives/keystore" } sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } @@ -35,7 +35,7 @@ sc-network-gossip = { version = "0.10.0-dev", path = "../network-gossip" } beefy-primitives = { version = "4.0.0-dev", path = "../../primitives/beefy" } [dev-dependencies] -sp-tracing = { version = "4.0.0-dev", path = "../../primitives/tracing" } +sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } sc-network-test = { version = "0.8.0", path = "../network/test" } strum = { version = "0.22", features = ["derive"] } diff --git a/client/beefy/rpc/Cargo.toml b/client/beefy/rpc/Cargo.toml index 594736841ed2..4d7bd6cef6c8 100644 --- a/client/beefy/rpc/Cargo.toml +++ b/client/beefy/rpc/Cargo.toml @@ -21,7 +21,7 @@ codec = { version = "2.2.0", package = "parity-scale-codec", features = ["derive sc-rpc = { version = "4.0.0-dev", path = "../../rpc" } -sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../../primitives/core" } sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } beefy-gadget = { version = "4.0.0-dev", path = "../." } diff --git a/client/block-builder/Cargo.toml b/client/block-builder/Cargo.toml index 25950a9e9061..789e3fffcfa1 100644 --- a/client/block-builder/Cargo.toml +++ b/client/block-builder/Cargo.toml @@ -18,7 +18,7 @@ sp-state-machine = { version = "0.10.0-dev", path = "../../primitives/state-mach sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } sp-block-builder = { version = "4.0.0-dev", path = "../../primitives/block-builder" } sp-inherents = { version = "4.0.0-dev", path = "../../primitives/inherents" } sc-client-api = { version = "4.0.0-dev", path = "../api" } diff --git a/client/chain-spec/Cargo.toml b/client/chain-spec/Cargo.toml index 976da4585911..1b4e3ed72d56 100644 --- a/client/chain-spec/Cargo.toml +++ b/client/chain-spec/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] sc-chain-spec-derive = { version = "4.0.0-dev", path = "./derive" } impl-trait-for-tuples = "0.2.1" sc-network = { version = "0.10.0-dev", path = "../network" } -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } serde = { version = "1.0.126", features = ["derive"] } serde_json = "1.0.71" sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index dddd48cb2f14..a9bc4e9f87a5 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -32,7 +32,7 @@ sc-network = { version = "0.10.0-dev", path = "../network" } sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } sc-utils = { version = "4.0.0-dev", path = "../utils" } sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } sp-keystore = { version = "0.10.0-dev", path = "../../primitives/keystore" } sc-service = { version = "0.10.0-dev", default-features = false, path = "../service" } sc-telemetry = { version = "4.0.0-dev", path = "../telemetry" } diff --git a/client/consensus/aura/Cargo.toml b/client/consensus/aura/Cargo.toml index f4f12a0a601c..967f59999c7e 100644 --- a/client/consensus/aura/Cargo.toml +++ b/client/consensus/aura/Cargo.toml @@ -26,7 +26,7 @@ derive_more = "0.99.16" futures = "0.3.9" sp-inherents = { version = "4.0.0-dev", path = "../../../primitives/inherents" } log = "0.4.8" -sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../../primitives/core" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sc-consensus-slots = { version = "0.10.0-dev", path = "../slots" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } @@ -42,7 +42,7 @@ getrandom = { version = "0.2", features = ["js"], optional = true } [dev-dependencies] sp-timestamp = { version = "4.0.0-dev", path = "../../../primitives/timestamp" } sp-keyring = { version = "4.0.0-dev", path = "../../../primitives/keyring" } -sp-tracing = { version = "4.0.0-dev", path = "../../../primitives/tracing" } +sp-tracing = { version = "4.0.0", path = "../../../primitives/tracing" } sc-keystore = { version = "4.0.0-dev", path = "../../keystore" } sc-network = { version = "0.10.0-dev", path = "../../network" } sc-network-test = { version = "0.8.0", path = "../../network/test" } diff --git a/client/consensus/babe/Cargo.toml b/client/consensus/babe/Cargo.toml index 5020a4a56478..5f1a8a088916 100644 --- a/client/consensus/babe/Cargo.toml +++ b/client/consensus/babe/Cargo.toml @@ -19,7 +19,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", features = [ ] } sp-consensus-babe = { version = "0.10.0-dev", path = "../../../primitives/consensus/babe" } sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/common" } -sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../../primitives/core" } sp-application-crypto = { version = "4.0.0-dev", path = "../../../primitives/application-crypto" } sp-keystore = { version = "0.10.0-dev", path = "../../../primitives/keystore" } num-bigint = "0.2.3" @@ -55,7 +55,7 @@ async-trait = "0.1.50" [dev-dependencies] sp-timestamp = { version = "4.0.0-dev", path = "../../../primitives/timestamp" } -sp-tracing = { version = "4.0.0-dev", path = "../../../primitives/tracing" } +sp-tracing = { version = "4.0.0", path = "../../../primitives/tracing" } sc-network = { version = "0.10.0-dev", path = "../../network" } sc-network-test = { version = "0.8.0", path = "../../network/test" } substrate-test-runtime-client = { version = "2.0.0", path = "../../../test-utils/runtime/client" } diff --git a/client/consensus/babe/rpc/Cargo.toml b/client/consensus/babe/rpc/Cargo.toml index b47c3a711df9..bba579ee111b 100644 --- a/client/consensus/babe/rpc/Cargo.toml +++ b/client/consensus/babe/rpc/Cargo.toml @@ -27,7 +27,7 @@ futures = "0.3.16" derive_more = "0.99.16" sp-api = { version = "4.0.0-dev", path = "../../../../primitives/api" } sp-consensus = { version = "0.10.0-dev", path = "../../../../primitives/consensus/common" } -sp-core = { version = "4.0.0-dev", path = "../../../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../../../primitives/core" } sp-application-crypto = { version = "4.0.0-dev", path = "../../../../primitives/application-crypto" } sp-keystore = { version = "0.10.0-dev", path = "../../../../primitives/keystore" } diff --git a/client/consensus/common/Cargo.toml b/client/consensus/common/Cargo.toml index 308028c85d23..13b720354018 100644 --- a/client/consensus/common/Cargo.toml +++ b/client/consensus/common/Cargo.toml @@ -20,7 +20,7 @@ futures = { version = "0.3.1", features = ["thread-pool"] } futures-timer = "3.0.1" sc-client-api = { version = "4.0.0-dev", path = "../../api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-core = { path = "../../../primitives/core", version = "4.0.0-dev" } +sp-core = { path = "../../../primitives/core", version = "4.0.0" } sp-consensus = { path = "../../../primitives/consensus/common", version = "0.10.0-dev" } sp-state-machine = { version = "0.10.0-dev", path = "../../../primitives/state-machine" } sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } diff --git a/client/consensus/manual-seal/Cargo.toml b/client/consensus/manual-seal/Cargo.toml index 48ba91065544..24314fefd156 100644 --- a/client/consensus/manual-seal/Cargo.toml +++ b/client/consensus/manual-seal/Cargo.toml @@ -36,7 +36,7 @@ sp-consensus = { path = "../../../primitives/consensus/common", version = "0.10. sp-consensus-slots = { path = "../../../primitives/consensus/slots", version = "0.10.0-dev" } sp-inherents = { path = "../../../primitives/inherents", version = "4.0.0-dev" } sp-runtime = { path = "../../../primitives/runtime", version = "4.0.0-dev" } -sp-core = { path = "../../../primitives/core", version = "4.0.0-dev" } +sp-core = { path = "../../../primitives/core", version = "4.0.0" } sp-keystore = { path = "../../../primitives/keystore", version = "0.10.0-dev" } sp-api = { path = "../../../primitives/api", version = "4.0.0-dev" } sc-transaction-pool-api = { path = "../../../client/transaction-pool/api", version = "4.0.0-dev" } diff --git a/client/consensus/pow/Cargo.toml b/client/consensus/pow/Cargo.toml index 25e39641ae43..2b0926ce887e 100644 --- a/client/consensus/pow/Cargo.toml +++ b/client/consensus/pow/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", features = ["derive"] } -sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../../primitives/core" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } diff --git a/client/consensus/slots/Cargo.toml b/client/consensus/slots/Cargo.toml index ff4fdf041b4f..7b4aa26cdf54 100644 --- a/client/consensus/slots/Cargo.toml +++ b/client/consensus/slots/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0" } sc-client-api = { version = "4.0.0-dev", path = "../../api" } -sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../../primitives/core" } sp-arithmetic = { version = "4.0.0-dev", path = "../../../primitives/arithmetic" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/common" } diff --git a/client/db/Cargo.toml b/client/db/Cargo.toml index 437431a50883..08e228ee9afa 100644 --- a/client/db/Cargo.toml +++ b/client/db/Cargo.toml @@ -26,7 +26,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", features = [ sc-client-api = { version = "4.0.0-dev", path = "../api" } sp-arithmetic = { version = "4.0.0-dev", path = "../../primitives/arithmetic" } -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } sp-state-machine = { version = "0.10.0-dev", path = "../../primitives/state-machine" } sc-state-db = { version = "0.10.0-dev", path = "../state-db" } @@ -36,7 +36,7 @@ sp-database = { version = "4.0.0-dev", path = "../../primitives/database" } parity-db = { version = "0.3.4", optional = true } [dev-dependencies] -sp-tracing = { version = "4.0.0-dev", path = "../../primitives/tracing" } +sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } quickcheck = "1.0.3" kvdb-rocksdb = "0.14.0" diff --git a/client/executor/Cargo.toml b/client/executor/Cargo.toml index ebdcc44ff0d8..b3a393f9472a 100644 --- a/client/executor/Cargo.toml +++ b/client/executor/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0" } sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } sp-tasks = { version = "4.0.0-dev", path = "../../primitives/tasks" } sp-trie = { version = "4.0.0-dev", path = "../../primitives/trie" } sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } @@ -24,9 +24,9 @@ sp-panic-handler = { version = "4.0.0-dev", path = "../../primitives/panic-handl wasmi = "0.9.1" lazy_static = "1.4.0" sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } -sp-wasm-interface = { version = "4.0.0-dev", path = "../../primitives/wasm-interface" } -sp-runtime-interface = { version = "4.0.0-dev", path = "../../primitives/runtime-interface" } -sp-externalities = { version = "0.10.0-dev", path = "../../primitives/externalities" } +sp-wasm-interface = { version = "4.0.0", path = "../../primitives/wasm-interface" } +sp-runtime-interface = { version = "4.0.0", path = "../../primitives/runtime-interface" } +sp-externalities = { version = "0.10.0", path = "../../primitives/externalities" } sc-executor-common = { version = "0.10.0-dev", path = "common" } sc-executor-wasmi = { version = "0.10.0-dev", path = "wasmi" } sc-executor-wasmtime = { version = "0.10.0-dev", path = "wasmtime", optional = true } diff --git a/client/executor/common/Cargo.toml b/client/executor/common/Cargo.toml index 3d2cec9ac60c..198d5201e1f5 100644 --- a/client/executor/common/Cargo.toml +++ b/client/executor/common/Cargo.toml @@ -18,9 +18,9 @@ derive_more = "0.99.16" pwasm-utils = "0.18.2" codec = { package = "parity-scale-codec", version = "2.0.0" } wasmi = "0.9.1" -sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../../primitives/core" } sc-allocator = { version = "4.1.0-dev", path = "../../allocator" } -sp-wasm-interface = { version = "4.0.0-dev", path = "../../../primitives/wasm-interface" } +sp-wasm-interface = { version = "4.0.0", path = "../../../primitives/wasm-interface" } sp-maybe-compressed-blob = { version = "4.1.0-dev", path = "../../../primitives/maybe-compressed-blob" } sp-serializer = { version = "4.0.0-dev", path = "../../../primitives/serializer" } thiserror = "1.0.30" diff --git a/client/executor/runtime-test/Cargo.toml b/client/executor/runtime-test/Cargo.toml index ea379a160f80..831ff786ca09 100644 --- a/client/executor/runtime-test/Cargo.toml +++ b/client/executor/runtime-test/Cargo.toml @@ -13,11 +13,11 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-core = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/core" } +sp-core = { version = "4.0.0", default-features = false, path = "../../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/io" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } sp-sandbox = { version = "0.10.0-dev", default-features = false, path = "../../../primitives/sandbox" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } sp-tasks = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/tasks" } paste = "1.0.6" diff --git a/client/executor/wasmi/Cargo.toml b/client/executor/wasmi/Cargo.toml index 871a8aa68b62..f1e01d944a6e 100644 --- a/client/executor/wasmi/Cargo.toml +++ b/client/executor/wasmi/Cargo.toml @@ -19,7 +19,7 @@ wasmi = "0.9.1" codec = { package = "parity-scale-codec", version = "2.0.0" } sc-executor-common = { version = "0.10.0-dev", path = "../common" } sc-allocator = { version = "4.1.0-dev", path = "../../allocator" } -sp-wasm-interface = { version = "4.0.0-dev", path = "../../../primitives/wasm-interface" } -sp-runtime-interface = { version = "4.0.0-dev", path = "../../../primitives/runtime-interface" } -sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" } +sp-wasm-interface = { version = "4.0.0", path = "../../../primitives/wasm-interface" } +sp-runtime-interface = { version = "4.0.0", path = "../../../primitives/runtime-interface" } +sp-core = { version = "4.0.0", path = "../../../primitives/core" } scoped-tls = "1.0" diff --git a/client/executor/wasmtime/Cargo.toml b/client/executor/wasmtime/Cargo.toml index 006415869c92..77210b97f376 100644 --- a/client/executor/wasmtime/Cargo.toml +++ b/client/executor/wasmtime/Cargo.toml @@ -19,9 +19,9 @@ log = "0.4.8" parity-wasm = "0.42.0" codec = { package = "parity-scale-codec", version = "2.0.0" } sc-executor-common = { version = "0.10.0-dev", path = "../common" } -sp-wasm-interface = { version = "4.0.0-dev", path = "../../../primitives/wasm-interface" } -sp-runtime-interface = { version = "4.0.0-dev", path = "../../../primitives/runtime-interface" } -sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" } +sp-wasm-interface = { version = "4.0.0", path = "../../../primitives/wasm-interface" } +sp-runtime-interface = { version = "4.0.0", path = "../../../primitives/runtime-interface" } +sp-core = { version = "4.0.0", path = "../../../primitives/core" } sc-allocator = { version = "4.1.0-dev", path = "../../allocator" } wasmtime = { version = "0.31.0", default-features = false, features = [ "cache", diff --git a/client/finality-grandpa/Cargo.toml b/client/finality-grandpa/Cargo.toml index 65a0580b9e95..fa60751d4891 100644 --- a/client/finality-grandpa/Cargo.toml +++ b/client/finality-grandpa/Cargo.toml @@ -30,7 +30,7 @@ sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } sc-utils = { version = "4.0.0-dev", path = "../utils" } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } sc-consensus = { version = "0.10.0-dev", path = "../consensus/common" } -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } sp-keystore = { version = "0.10.0-dev", path = "../../primitives/keystore" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } sc-telemetry = { version = "4.0.0-dev", path = "../telemetry" } @@ -56,6 +56,6 @@ sc-network = { version = "0.10.0-dev", path = "../network" } sc-network-test = { version = "0.8.0", path = "../network/test" } sp-keyring = { version = "4.0.0-dev", path = "../../primitives/keyring" } substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } -sp-tracing = { version = "4.0.0-dev", path = "../../primitives/tracing" } +sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } tokio = "1.13" tempfile = "3.1.0" diff --git a/client/finality-grandpa/rpc/Cargo.toml b/client/finality-grandpa/rpc/Cargo.toml index ad39ad6ba95b..a83a47af9ed4 100644 --- a/client/finality-grandpa/rpc/Cargo.toml +++ b/client/finality-grandpa/rpc/Cargo.toml @@ -12,7 +12,7 @@ readme = "README.md" sc-finality-grandpa = { version = "0.10.0-dev", path = "../" } sc-rpc = { version = "4.0.0-dev", path = "../../rpc" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../../primitives/core" } sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } finality-grandpa = { version = "0.14.4", features = ["derive-codec"] } jsonrpc-core = "18.0.0" @@ -32,7 +32,7 @@ sc-block-builder = { version = "0.10.0-dev", path = "../../block-builder" } sc-rpc = { version = "4.0.0-dev", path = "../../rpc", features = [ "test-helpers", ] } -sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../../primitives/core" } sp-finality-grandpa = { version = "4.0.0-dev", path = "../../../primitives/finality-grandpa" } sp-keyring = { version = "4.0.0-dev", path = "../../../primitives/keyring" } substrate-test-runtime-client = { version = "2.0.0", path = "../../../test-utils/runtime/client" } diff --git a/client/keystore/Cargo.toml b/client/keystore/Cargo.toml index 9da825faf033..ac2663902b67 100644 --- a/client/keystore/Cargo.toml +++ b/client/keystore/Cargo.toml @@ -18,7 +18,7 @@ targets = ["x86_64-unknown-linux-gnu"] async-trait = "0.1.50" derive_more = "0.99.16" sp-application-crypto = { version = "4.0.0-dev", path = "../../primitives/application-crypto" } -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } sp-keystore = { version = "0.10.0-dev", path = "../../primitives/keystore" } hex = "0.4.0" parking_lot = "0.11.1" diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index 8ee4d7f14572..229a273eabdc 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -53,7 +53,7 @@ sp-arithmetic = { version = "4.0.0-dev", path = "../../primitives/arithmetic" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } sc-consensus = { version = "0.10.0-dev", path = "../consensus/common" } -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } sc-utils = { version = "4.0.0-dev", path = "../utils" } sp-finality-grandpa = { version = "4.0.0-dev", path = "../../primitives/finality-grandpa" } @@ -72,7 +72,7 @@ libp2p = { version = "0.40.0", default-features = false } quickcheck = "1.0.3" rand = "0.7.2" sp-test-primitives = { version = "2.0.0", path = "../../primitives/test-primitives" } -sp-tracing = { version = "4.0.0-dev", path = "../../primitives/tracing" } +sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } substrate-test-runtime = { version = "2.0.0", path = "../../test-utils/runtime" } substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } tempfile = "3.1.0" diff --git a/client/network/test/Cargo.toml b/client/network/test/Cargo.toml index 84aab96a673d..afa4622d2f05 100644 --- a/client/network/test/Cargo.toml +++ b/client/network/test/Cargo.toml @@ -26,11 +26,11 @@ sc-consensus = { version = "0.10.0-dev", path = "../../consensus/common" } sc-client-api = { version = "4.0.0-dev", path = "../../api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } -sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../../primitives/core" } sc-block-builder = { version = "0.10.0-dev", path = "../../block-builder" } sp-consensus-babe = { version = "0.10.0-dev", path = "../../../primitives/consensus/babe" } substrate-test-runtime-client = { version = "2.0.0", path = "../../../test-utils/runtime/client" } substrate-test-runtime = { version = "2.0.0", path = "../../../test-utils/runtime" } -sp-tracing = { version = "4.0.0-dev", path = "../../../primitives/tracing" } +sp-tracing = { version = "4.0.0", path = "../../../primitives/tracing" } sc-service = { version = "0.10.0-dev", default-features = false, features = ["test-helpers"], path = "../../service" } async-trait = "0.1.50" diff --git a/client/offchain/Cargo.toml b/client/offchain/Cargo.toml index b92ee7041e5f..6f1fd3a035fe 100644 --- a/client/offchain/Cargo.toml +++ b/client/offchain/Cargo.toml @@ -25,7 +25,7 @@ rand = "0.7.2" sc-client-api = { version = "4.0.0-dev", path = "../api" } sc-network = { version = "0.10.0-dev", path = "../network" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } sp-offchain = { version = "4.0.0-dev", path = "../../primitives/offchain" } sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } sc-utils = { version = "4.0.0-dev", path = "../utils" } @@ -40,7 +40,7 @@ sc-client-db = { version = "0.10.0-dev", default-features = true, path = "../db" sc-block-builder = { version = "0.10.0-dev", path = "../block-builder" } sc-transaction-pool = { version = "4.0.0-dev", path = "../transaction-pool" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../transaction-pool/api" } -sp-tracing = { version = "4.0.0-dev", path = "../../primitives/tracing" } +sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } tokio = "1.13" diff --git a/client/rpc-api/Cargo.toml b/client/rpc-api/Cargo.toml index a758d29aed2c..5f7a2d2fb32b 100644 --- a/client/rpc-api/Cargo.toml +++ b/client/rpc-api/Cargo.toml @@ -23,7 +23,7 @@ log = "0.4.8" parking_lot = "0.11.1" thiserror = "1.0" -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } sp-runtime = { path = "../../primitives/runtime", version = "4.0.0-dev" } sc-chain-spec = { path = "../chain-spec", version = "4.0.0-dev" } @@ -31,4 +31,4 @@ serde = { version = "1.0.126", features = ["derive"] } serde_json = "1.0.71" sc-transaction-pool-api = { version = "4.0.0-dev", path = "../transaction-pool/api" } sp-rpc = { version = "4.0.0-dev", path = "../../primitives/rpc" } -sp-tracing = { version = "4.0.0-dev", path = "../../primitives/tracing" } +sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } diff --git a/client/rpc/Cargo.toml b/client/rpc/Cargo.toml index 6cf2d699386d..9d8461238fc0 100644 --- a/client/rpc/Cargo.toml +++ b/client/rpc/Cargo.toml @@ -20,7 +20,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0" } futures = "0.3.16" jsonrpc-pubsub = "18.0.0" log = "0.4.8" -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } rpc = { package = "jsonrpc-core", version = "18.0.0" } sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } serde_json = "1.0.71" diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index 161863b14710..91143c45b4a2 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -38,11 +38,11 @@ serde_json = "1.0.71" sc-keystore = { version = "4.0.0-dev", path = "../keystore" } sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } sp-trie = { version = "4.0.0-dev", path = "../../primitives/trie" } -sp-externalities = { version = "0.10.0-dev", path = "../../primitives/externalities" } +sp-externalities = { version = "0.10.0", path = "../../primitives/externalities" } sc-utils = { version = "4.0.0-dev", path = "../utils" } sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } sp-keystore = { version = "0.10.0-dev", path = "../../primitives/keystore" } sp-session = { version = "4.0.0-dev", path = "../../primitives/session" } sp-state-machine = { version = "0.10.0-dev", path = "../../primitives/state-machine" } @@ -50,7 +50,7 @@ sp-application-crypto = { version = "4.0.0-dev", path = "../../primitives/applic sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } sc-consensus = { version = "0.10.0-dev", path = "../../client/consensus/common" } sp-inherents = { version = "4.0.0-dev", path = "../../primitives/inherents" } -sp-storage = { version = "4.0.0-dev", path = "../../primitives/storage" } +sp-storage = { version = "4.0.0", path = "../../primitives/storage" } sc-network = { version = "0.10.0-dev", path = "../network" } sc-chain-spec = { version = "4.0.0-dev", path = "../chain-spec" } sc-client-api = { version = "4.0.0-dev", path = "../api" } @@ -71,7 +71,7 @@ sc-telemetry = { version = "4.0.0-dev", path = "../telemetry" } sc-offchain = { version = "4.0.0-dev", path = "../offchain" } prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.10.0-dev" } sc-tracing = { version = "4.0.0-dev", path = "../tracing" } -sp-tracing = { version = "4.0.0-dev", path = "../../primitives/tracing" } +sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } tracing = "0.1.29" tracing-futures = { version = "0.2.4" } parity-util-mem = { version = "0.10.2", default-features = false, features = [ diff --git a/client/service/test/Cargo.toml b/client/service/test/Cargo.toml index fe953a53bdd0..c89442f3aec7 100644 --- a/client/service/test/Cargo.toml +++ b/client/service/test/Cargo.toml @@ -22,9 +22,9 @@ parking_lot = "0.11.1" sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-state-machine = { version = "0.10.0-dev", path = "../../../primitives/state-machine" } -sp-externalities = { version = "0.10.0-dev", path = "../../../primitives/externalities" } +sp-externalities = { version = "0.10.0", path = "../../../primitives/externalities" } sp-trie = { version = "4.0.0-dev", path = "../../../primitives/trie" } -sp-storage = { version = "4.0.0-dev", path = "../../../primitives/storage" } +sp-storage = { version = "4.0.0", path = "../../../primitives/storage" } sc-client-db = { version = "0.10.0-dev", default-features = false, path = "../../db" } futures = "0.3.16" sc-service = { version = "0.10.0-dev", features = ["test-helpers"], path = "../../service" } @@ -32,7 +32,7 @@ sc-network = { version = "0.10.0-dev", path = "../../network" } sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" } sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/common" } sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } -sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../../primitives/core" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../../../client/transaction-pool/api" } substrate-test-runtime = { version = "2.0.0", path = "../../../test-utils/runtime" } substrate-test-runtime-client = { version = "2.0.0", path = "../../../test-utils/runtime/client" } @@ -41,4 +41,4 @@ sc-block-builder = { version = "0.10.0-dev", path = "../../block-builder" } sc-executor = { version = "0.10.0-dev", path = "../../executor" } sp-panic-handler = { version = "4.0.0-dev", path = "../../../primitives/panic-handler" } parity-scale-codec = "2.3.1" -sp-tracing = { version = "4.0.0-dev", path = "../../../primitives/tracing" } +sp-tracing = { version = "4.0.0", path = "../../../primitives/tracing" } diff --git a/client/state-db/Cargo.toml b/client/state-db/Cargo.toml index cd14038cb77b..8c059e80cdb2 100644 --- a/client/state-db/Cargo.toml +++ b/client/state-db/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] parking_lot = "0.11.1" log = "0.4.11" sc-client-api = { version = "4.0.0-dev", path = "../api" } -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } codec = { package = "parity-scale-codec", version = "2.0.0", features = ["derive"] } parity-util-mem = { version = "0.10.2", default-features = false, features = ["primitive-types"] } parity-util-mem-derive = "0.1.0" diff --git a/client/tracing/Cargo.toml b/client/tracing/Cargo.toml index 6a969b33deb1..81710887b816 100644 --- a/client/tracing/Cargo.toml +++ b/client/tracing/Cargo.toml @@ -28,12 +28,12 @@ thiserror = "1.0.30" tracing = "0.1.29" tracing-log = "0.1.2" tracing-subscriber = { version = "0.2.25", features = ["parking_lot"] } -sp-tracing = { version = "4.0.0-dev", path = "../../primitives/tracing" } +sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } sp-rpc = { version = "4.0.0-dev", path = "../../primitives/rpc" } sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } sc-client-api = { version = "4.0.0-dev", path = "../api" } sc-tracing-proc-macro = { version = "4.0.0-dev", path = "./proc-macro" } sc-rpc-server = { version = "4.0.0-dev", path = "../rpc-servers" } diff --git a/client/transaction-pool/Cargo.toml b/client/transaction-pool/Cargo.toml index 3d2a450c4101..b3a7095fcb75 100644 --- a/client/transaction-pool/Cargo.toml +++ b/client/transaction-pool/Cargo.toml @@ -23,9 +23,9 @@ parking_lot = "0.11.1" prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.10.0-dev"} sc-client-api = { version = "4.0.0-dev", path = "../api" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } -sp-tracing = { version = "4.0.0-dev", path = "../../primitives/tracing" } +sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } sp-transaction-pool = { version = "4.0.0-dev", path = "../../primitives/transaction-pool" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "./api" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } diff --git a/frame/assets/Cargo.toml b/frame/assets/Cargo.toml index 233c88279d35..0f2e3cbf3d4e 100644 --- a/frame/assets/Cargo.toml +++ b/frame/assets/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } # Needed for various traits. In our case, `OnFinalize`. sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } # Needed for type-safe access to storage DB. @@ -25,8 +25,8 @@ frame-system = { version = "4.0.0-dev", default-features = false, path = "../sys frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } -sp-std = { version = "4.0.0-dev", path = "../../primitives/std" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-std = { version = "4.0.0", path = "../../primitives/std" } sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } diff --git a/frame/atomic-swap/Cargo.toml b/frame/atomic-swap/Cargo.toml index 303116161a2d..0c2d7616f57e 100644 --- a/frame/atomic-swap/Cargo.toml +++ b/frame/atomic-swap/Cargo.toml @@ -18,9 +18,9 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" } +sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } [dev-dependencies] pallet-balances = { version = "4.0.0-dev", path = "../balances" } diff --git a/frame/aura/Cargo.toml b/frame/aura/Cargo.toml index cb5903048ff8..1252e7b51e00 100644 --- a/frame/aura/Cargo.toml +++ b/frame/aura/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] sp-application-crypto = { version = "4.0.0-dev", default-features = false, path = "../../primitives/application-crypto" } codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } sp-consensus-aura = { version = "0.10.0-dev", path = "../../primitives/consensus/aura", default-features = false } @@ -24,7 +24,7 @@ frame-system = { version = "4.0.0-dev", default-features = false, path = "../sys pallet-timestamp = { version = "4.0.0-dev", default-features = false, path = "../timestamp" } [dev-dependencies] -sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" } +sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } [features] diff --git a/frame/authority-discovery/Cargo.toml b/frame/authority-discovery/Cargo.toml index 06a4e92270b2..c7b5abe350b8 100644 --- a/frame/authority-discovery/Cargo.toml +++ b/frame/authority-discovery/Cargo.toml @@ -19,7 +19,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = "derive", ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } pallet-session = { version = "4.0.0-dev", features = [ "historical", ], path = "../session", default-features = false } @@ -28,7 +28,7 @@ frame-support = { version = "4.0.0-dev", default-features = false, path = "../su frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } [features] diff --git a/frame/authorship/Cargo.toml b/frame/authorship/Cargo.toml index a24b578fc250..48a6c473875c 100644 --- a/frame/authorship/Cargo.toml +++ b/frame/authorship/Cargo.toml @@ -18,14 +18,14 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-authorship = { version = "4.0.0-dev", default-features = false, path = "../../primitives/authorship" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } impl-trait-for-tuples = "0.2.1" [dev-dependencies] -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } [features] diff --git a/frame/babe/Cargo.toml b/frame/babe/Cargo.toml index a2224df86798..077a8cb89a92 100644 --- a/frame/babe/Cargo.toml +++ b/frame/babe/Cargo.toml @@ -28,7 +28,7 @@ sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primiti sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../primitives/session" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } log = { version = "0.4.14", default-features = false } [dev-dependencies] @@ -36,7 +36,7 @@ pallet-balances = { version = "4.0.0-dev", path = "../balances" } pallet-offences = { version = "4.0.0-dev", path = "../offences" } pallet-staking = { version = "4.0.0-dev", path = "../staking" } pallet-staking-reward-curve = { version = "4.0.0-dev", path = "../staking/reward-curve" } -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } frame-election-provider-support = { version = "4.0.0-dev", path = "../election-provider-support" } [features] diff --git a/frame/bags-list/Cargo.toml b/frame/bags-list/Cargo.toml index b7eebdd0df10..fe8d08ed9766 100644 --- a/frame/bags-list/Cargo.toml +++ b/frame/bags-list/Cargo.toml @@ -19,7 +19,7 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] # primitives sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } # FRAME frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } @@ -32,14 +32,14 @@ log = { version = "0.4.14", default-features = false } # Optional imports for benchmarking frame-benchmarking = { version = "4.0.0-dev", path = "../benchmarking", optional = true, default-features = false } pallet-balances = { version = "4.0.0-dev", path = "../balances", optional = true, default-features = false } -sp-core = { version = "4.0.0-dev", path = "../../primitives/core", optional = true, default-features = false } +sp-core = { version = "4.0.0", path = "../../primitives/core", optional = true, default-features = false } sp-io = { version = "4.0.0-dev", path = "../../primitives/io", optional = true, default-features = false } -sp-tracing = { version = "4.0.0-dev", path = "../../primitives/tracing", optional = true, default-features = false } +sp-tracing = { version = "4.0.0", path = "../../primitives/tracing", optional = true, default-features = false } [dev-dependencies] -sp-core = { version = "4.0.0-dev", path = "../../primitives/core"} +sp-core = { version = "4.0.0", path = "../../primitives/core"} sp-io = { version = "4.0.0-dev", path = "../../primitives/io"} -sp-tracing = { version = "4.0.0-dev", path = "../../primitives/tracing" } +sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } frame-election-provider-support = { version = "4.0.0-dev", path = "../election-provider-support", features = ["runtime-benchmarks"] } frame-benchmarking = { version = "4.0.0-dev", path = "../benchmarking" } @@ -70,4 +70,3 @@ fuzz = [ "sp-tracing", ] try-runtime = [ "frame-support/try-runtime" ] - diff --git a/frame/bags-list/remote-tests/Cargo.toml b/frame/bags-list/remote-tests/Cargo.toml index ecc0b4da242c..5a5b028285d8 100644 --- a/frame/bags-list/remote-tests/Cargo.toml +++ b/frame/bags-list/remote-tests/Cargo.toml @@ -21,11 +21,11 @@ frame-system = { path = "../../system", version = "4.0.0-dev" } frame-support = { path = "../../support", version = "4.0.0-dev" } # core -sp-storage = { path = "../../../primitives/storage", version = "4.0.0-dev" } -sp-core = { path = "../../../primitives/core", version = "4.0.0-dev" } -sp-tracing = { path = "../../../primitives/tracing", version = "4.0.0-dev" } +sp-storage = { path = "../../../primitives/storage", version = "4.0.0" } +sp-core = { path = "../../../primitives/core", version = "4.0.0" } +sp-tracing = { path = "../../../primitives/tracing", version = "4.0.0" } sp-runtime = { path = "../../../primitives/runtime", version = "4.0.0-dev" } -sp-std = { path = "../../../primitives/std", version = "4.0.0-dev" } +sp-std = { path = "../../../primitives/std", version = "4.0.0" } # utils remote-externalities = { path = "../../../utils/frame/remote-externalities", version = "0.10.0-dev" } diff --git a/frame/balances/Cargo.toml b/frame/balances/Cargo.toml index 5565915f6ded..825869c6b972 100644 --- a/frame/balances/Cargo.toml +++ b/frame/balances/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } @@ -24,7 +24,7 @@ log = { version = "0.4.14", default-features = false } [dev-dependencies] sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } pallet-transaction-payment = { version = "4.0.0-dev", path = "../transaction-payment" } [features] diff --git a/frame/beefy-mmr/Cargo.toml b/frame/beefy-mmr/Cargo.toml index b99b6f7e9fea..cebd7a6d962b 100644 --- a/frame/beefy-mmr/Cargo.toml +++ b/frame/beefy-mmr/Cargo.toml @@ -21,10 +21,10 @@ pallet-mmr = { version = "4.0.0-dev", path = "../merkle-mountain-range", default pallet-mmr-primitives = { version = "4.0.0-dev", path = "../merkle-mountain-range/primitives", default-features = false } pallet-session = { version = "4.0.0-dev", path = "../session", default-features = false } -sp-core = { version = "4.0.0-dev", path = "../../primitives/core", default-features = false } +sp-core = { version = "4.0.0", path = "../../primitives/core", default-features = false } sp-io = { version = "4.0.0-dev", path = "../../primitives/io", default-features = false } sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime", default-features = false } -sp-std = { version = "4.0.0-dev", path = "../../primitives/std", default-features = false } +sp-std = { version = "4.0.0", path = "../../primitives/std", default-features = false } beefy-merkle-tree = { version = "4.0.0-dev", path = "./primitives", default-features = false } beefy-primitives = { version = "4.0.0-dev", path = "../../primitives/beefy", default-features = false } diff --git a/frame/beefy/Cargo.toml b/frame/beefy/Cargo.toml index 7e1cec9d438e..4bfd9f19b280 100644 --- a/frame/beefy/Cargo.toml +++ b/frame/beefy/Cargo.toml @@ -16,14 +16,14 @@ frame-support = { version = "4.0.0-dev", path = "../support", default-features = frame-system = { version = "4.0.0-dev", path = "../system", default-features = false } sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime", default-features = false } -sp-std = { version = "4.0.0-dev", path = "../../primitives/std", default-features = false } +sp-std = { version = "4.0.0", path = "../../primitives/std", default-features = false } pallet-session = { version = "4.0.0-dev", path = "../session", default-features = false } beefy-primitives = { version = "4.0.0-dev", path = "../../primitives/beefy", default-features = false } [dev-dependencies] -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } sp-staking = { version = "4.0.0-dev", path = "../../primitives/staking" } diff --git a/frame/benchmarking/Cargo.toml b/frame/benchmarking/Cargo.toml index 4160f040c3bc..d907cf71948f 100644 --- a/frame/benchmarking/Cargo.toml +++ b/frame/benchmarking/Cargo.toml @@ -18,12 +18,12 @@ paste = "1.0" codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-api = { version = "4.0.0-dev", path = "../../primitives/api", default-features = false } -sp-runtime-interface = { version = "4.0.0-dev", path = "../../primitives/runtime-interface", default-features = false } +sp-runtime-interface = { version = "4.0.0", path = "../../primitives/runtime-interface", default-features = false } sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime", default-features = false } -sp-std = { version = "4.0.0-dev", path = "../../primitives/std", default-features = false } +sp-std = { version = "4.0.0", path = "../../primitives/std", default-features = false } sp-io = { version = "4.0.0-dev", path = "../../primitives/io", default-features = false } sp-application-crypto = { version = "4.0.0-dev", path = "../../primitives/application-crypto", default-features = false } -sp-storage = { version = "4.0.0-dev", path = "../../primitives/storage", default-features = false } +sp-storage = { version = "4.0.0", path = "../../primitives/storage", default-features = false } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } log = { version = "0.4.14", default-features = false } diff --git a/frame/bounties/Cargo.toml b/frame/bounties/Cargo.toml index 6c9cef417e99..5dfa05bba0a0 100644 --- a/frame/bounties/Cargo.toml +++ b/frame/bounties/Cargo.toml @@ -17,13 +17,13 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = "derive", ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } pallet-treasury = { version = "4.0.0-dev", default-features = false, path = "../treasury" } sp-io = { version = "4.0.0-dev", path = "../../primitives/io", default-features = false } -sp-core = { version = "4.0.0-dev", path = "../../primitives/core", default-features = false } +sp-core = { version = "4.0.0", path = "../../primitives/core", default-features = false } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } log = { version = "0.4.14", default-features = false } diff --git a/frame/child-bounties/Cargo.toml b/frame/child-bounties/Cargo.toml index 040337424d39..37152e29d8f4 100644 --- a/frame/child-bounties/Cargo.toml +++ b/frame/child-bounties/Cargo.toml @@ -17,14 +17,14 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = "derive", ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } pallet-treasury = { version = "4.0.0-dev", default-features = false, path = "../treasury" } pallet-bounties = { version = "4.0.0-dev", default-features = false, path = "../bounties" } sp-io = { version = "4.0.0-dev", path = "../../primitives/io", default-features = false } -sp-core = { version = "4.0.0-dev", path = "../../primitives/core", default-features = false } +sp-core = { version = "4.0.0", path = "../../primitives/core", default-features = false } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } log = { version = "0.4.14", default-features = false } diff --git a/frame/collective/Cargo.toml b/frame/collective/Cargo.toml index d4dc8f9a2d8d..76799ae981c7 100644 --- a/frame/collective/Cargo.toml +++ b/frame/collective/Cargo.toml @@ -17,10 +17,10 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = log = { version = "0.4.14", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" } +sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/frame/contracts/Cargo.toml b/frame/contracts/Cargo.toml index 0b10962f0e63..bb7a0693147b 100644 --- a/frame/contracts/Cargo.toml +++ b/frame/contracts/Cargo.toml @@ -38,11 +38,11 @@ frame-support = { version = "4.0.0-dev", default-features = false, path = "../su frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } pallet-contracts-primitives = { version = "4.0.0-dev", default-features = false, path = "common" } pallet-contracts-proc-macro = { version = "4.0.0-dev", path = "proc-macro" } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" } +sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } sp-sandbox = { version = "0.10.0-dev", default-features = false, path = "../../primitives/sandbox" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } [dev-dependencies] assert_matches = "1" diff --git a/frame/contracts/common/Cargo.toml b/frame/contracts/common/Cargo.toml index 5f52ce7fcfe5..ebfd5fab5af1 100644 --- a/frame/contracts/common/Cargo.toml +++ b/frame/contracts/common/Cargo.toml @@ -19,8 +19,8 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] serde = { version = "1", features = ["derive"], optional = true } # Substrate Dependencies (This crate should not rely on frame) -sp-core = { version = "4.0.0-dev", path = "../../../primitives/core", default-features = false } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/std" } +sp-core = { version = "4.0.0", path = "../../../primitives/core", default-features = false } +sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } sp-rpc = { version = "4.0.0-dev", path = "../../../primitives/rpc", optional = true } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } diff --git a/frame/contracts/rpc/Cargo.toml b/frame/contracts/rpc/Cargo.toml index 82ce4bedb498..aac5683a79e5 100644 --- a/frame/contracts/rpc/Cargo.toml +++ b/frame/contracts/rpc/Cargo.toml @@ -24,7 +24,7 @@ pallet-contracts-primitives = { version = "4.0.0-dev", path = "../common" } pallet-contracts-rpc-runtime-api = { version = "4.0.0-dev", path = "./runtime-api" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../../primitives/core" } sp-rpc = { version = "4.0.0-dev", path = "../../../primitives/rpc" } sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } diff --git a/frame/contracts/rpc/runtime-api/Cargo.toml b/frame/contracts/rpc/runtime-api/Cargo.toml index b65fbf9aba0c..2c293b3a906a 100644 --- a/frame/contracts/rpc/runtime-api/Cargo.toml +++ b/frame/contracts/rpc/runtime-api/Cargo.toml @@ -20,7 +20,7 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] pallet-contracts-primitives = { version = "4.0.0-dev", default-features = false, path = "../../common" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/api" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/runtime" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../../../primitives/std" } [features] default = ["std"] diff --git a/frame/democracy/Cargo.toml b/frame/democracy/Cargo.toml index 43b35b9f7a1f..becec8a878d5 100644 --- a/frame/democracy/Cargo.toml +++ b/frame/democracy/Cargo.toml @@ -18,7 +18,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = "derive", ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } @@ -26,7 +26,7 @@ frame-support = { version = "4.0.0-dev", default-features = false, path = "../su frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } pallet-scheduler = { version = "4.0.0-dev", path = "../scheduler" } diff --git a/frame/election-provider-multi-phase/Cargo.toml b/frame/election-provider-multi-phase/Cargo.toml index c041d6c684c7..42d7c4064cb3 100644 --- a/frame/election-provider-multi-phase/Cargo.toml +++ b/frame/election-provider-multi-phase/Cargo.toml @@ -24,8 +24,8 @@ frame-support = { version = "4.0.0-dev", default-features = false, path = "../su frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } +sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } sp-npos-elections = { version = "4.0.0-dev", default-features = false, path = "../../primitives/npos-elections" } sp-arithmetic = { version = "4.0.0-dev", default-features = false, path = "../../primitives/arithmetic" } @@ -43,10 +43,10 @@ strum_macros = { optional = true, version = "0.22.0" } [dev-dependencies] parking_lot = "0.11.0" rand = { version = "0.7.3" } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" } +sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } sp-npos-elections = { version = "4.0.0-dev", default-features = false, path = "../../primitives/npos-elections" } -sp-tracing = { version = "4.0.0-dev", path = "../../primitives/tracing" } +sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } frame-election-provider-support = { version = "4.0.0-dev", features = [ ], path = "../election-provider-support" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } diff --git a/frame/election-provider-support/Cargo.toml b/frame/election-provider-support/Cargo.toml index e22338f456c4..a69dca39b8e8 100644 --- a/frame/election-provider-support/Cargo.toml +++ b/frame/election-provider-support/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-arithmetic = { version = "4.0.0-dev", default-features = false, path = "../../primitives/arithmetic" } sp-npos-elections = { version = "4.0.0-dev", default-features = false, path = "../../primitives/npos-elections" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } @@ -24,7 +24,7 @@ frame-system = { version = "4.0.0-dev", default-features = false, path = "../sys [dev-dependencies] sp-npos-elections = { version = "4.0.0-dev", path = "../../primitives/npos-elections" } sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } [features] diff --git a/frame/elections-phragmen/Cargo.toml b/frame/elections-phragmen/Cargo.toml index 921a7057bcda..a5e9ca777c3c 100644 --- a/frame/elections-phragmen/Cargo.toml +++ b/frame/elections-phragmen/Cargo.toml @@ -22,14 +22,14 @@ sp-npos-elections = { version = "4.0.0-dev", default-features = false, path = ". sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } +sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } log = { version = "0.4.14", default-features = false } [dev-dependencies] pallet-balances = { version = "4.0.0-dev", path = "../balances" } -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } substrate-test-utils = { version = "4.0.0-dev", path = "../../test-utils" } [features] diff --git a/frame/elections/Cargo.toml b/frame/elections/Cargo.toml index 2ca2e584d2f4..e5f7d27d8911 100644 --- a/frame/elections/Cargo.toml +++ b/frame/elections/Cargo.toml @@ -17,8 +17,8 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = "derive", ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/frame/examples/basic/Cargo.toml b/frame/examples/basic/Cargo.toml index 8ac375cb3603..5edd3bfef8de 100644 --- a/frame/examples/basic/Cargo.toml +++ b/frame/examples/basic/Cargo.toml @@ -23,10 +23,10 @@ frame-system = { version = "4.0.0-dev", default-features = false, path = "../../ pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../../balances" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/io" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } [dev-dependencies] -sp-core = { version = "4.0.0-dev", path = "../../../primitives/core", default-features = false } +sp-core = { version = "4.0.0", path = "../../../primitives/core", default-features = false } [features] default = ["std"] diff --git a/frame/examples/offchain-worker/Cargo.toml b/frame/examples/offchain-worker/Cargo.toml index cb505ad42f25..44886afba5e1 100644 --- a/frame/examples/offchain-worker/Cargo.toml +++ b/frame/examples/offchain-worker/Cargo.toml @@ -20,11 +20,11 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/core" } +sp-core = { version = "4.0.0", default-features = false, path = "../../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/io" } sp-keystore = { version = "0.10.0-dev", path = "../../../primitives/keystore", optional = true } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } [features] default = ["std"] diff --git a/frame/examples/parallel/Cargo.toml b/frame/examples/parallel/Cargo.toml index cf7f46b23224..3d9104eb3545 100644 --- a/frame/examples/parallel/Cargo.toml +++ b/frame/examples/parallel/Cargo.toml @@ -17,10 +17,10 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/core" } +sp-core = { version = "4.0.0", default-features = false, path = "../../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/io" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } sp-tasks = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/tasks" } [features] diff --git a/frame/executive/Cargo.toml b/frame/executive/Cargo.toml index 20e31fe0a572..9509fc5c977b 100644 --- a/frame/executive/Cargo.toml +++ b/frame/executive/Cargo.toml @@ -20,14 +20,14 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-tracing = { version = "4.0.0-dev", default-features = false, path = "../../primitives/tracing" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-tracing = { version = "4.0.0", default-features = false, path = "../../primitives/tracing" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" } +sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } [dev-dependencies] hex-literal = "0.3.4" -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } pallet-transaction-payment = { version = "4.0.0-dev", path = "../transaction-payment" } diff --git a/frame/gilt/Cargo.toml b/frame/gilt/Cargo.toml index e9ee8ba14aba..14948546a177 100644 --- a/frame/gilt/Cargo.toml +++ b/frame/gilt/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } sp-arithmetic = { version = "4.0.0-dev", default-features = false, path = "../../primitives/arithmetic" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } @@ -24,7 +24,7 @@ frame-system = { version = "4.0.0-dev", default-features = false, path = "../sys [dev-dependencies] sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/frame/grandpa/Cargo.toml b/frame/grandpa/Cargo.toml index ba2d98fc354e..d052b468f927 100644 --- a/frame/grandpa/Cargo.toml +++ b/frame/grandpa/Cargo.toml @@ -16,11 +16,11 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-application-crypto = { version = "4.0.0-dev", default-features = false, path = "../../primitives/application-crypto" } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" } +sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } sp-finality-grandpa = { version = "4.0.0-dev", default-features = false, path = "../../primitives/finality-grandpa" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../primitives/session" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } diff --git a/frame/identity/Cargo.toml b/frame/identity/Cargo.toml index b791256d9452..dc247727e098 100644 --- a/frame/identity/Cargo.toml +++ b/frame/identity/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } enumflags2 = { version = "0.6.2" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } @@ -24,7 +24,7 @@ frame-support = { version = "4.0.0-dev", default-features = false, path = "../su frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/frame/im-online/Cargo.toml b/frame/im-online/Cargo.toml index 2fa0b5ebc12a..fc0a6acf1798 100644 --- a/frame/im-online/Cargo.toml +++ b/frame/im-online/Cargo.toml @@ -17,8 +17,8 @@ sp-application-crypto = { version = "4.0.0-dev", default-features = false, path pallet-authorship = { version = "4.0.0-dev", default-features = false, path = "../authorship" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" } diff --git a/frame/indices/Cargo.toml b/frame/indices/Cargo.toml index 7f27ac23c645..f4f5146ae118 100644 --- a/frame/indices/Cargo.toml +++ b/frame/indices/Cargo.toml @@ -16,10 +16,10 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-keyring = { version = "4.0.0-dev", optional = true, path = "../../primitives/keyring" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" } +sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/lottery/Cargo.toml b/frame/lottery/Cargo.toml index e65bb01660b5..db317d0d01ec 100644 --- a/frame/lottery/Cargo.toml +++ b/frame/lottery/Cargo.toml @@ -17,7 +17,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = "derive", ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } @@ -27,7 +27,7 @@ frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = " [dev-dependencies] frame-support-test = { version = "3.0.0", path = "../support/test" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } [features] diff --git a/frame/membership/Cargo.toml b/frame/membership/Cargo.toml index 9eafaedee7db..105bdc55b5c0 100644 --- a/frame/membership/Cargo.toml +++ b/frame/membership/Cargo.toml @@ -17,10 +17,10 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } log = { version = "0.4.0", default-features = false } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" } +sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/frame/merkle-mountain-range/Cargo.toml b/frame/merkle-mountain-range/Cargo.toml index ee9080b19d61..51b7e4a2a607 100644 --- a/frame/merkle-mountain-range/Cargo.toml +++ b/frame/merkle-mountain-range/Cargo.toml @@ -16,10 +16,10 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } mmr-lib = { package = "ckb-merkle-mountain-range", default-features = false, version = "0.3.2" } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" } +sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/frame/merkle-mountain-range/primitives/Cargo.toml b/frame/merkle-mountain-range/primitives/Cargo.toml index 0531a295fafe..11562c02bf32 100644 --- a/frame/merkle-mountain-range/primitives/Cargo.toml +++ b/frame/merkle-mountain-range/primitives/Cargo.toml @@ -17,9 +17,9 @@ log = { version = "0.4.14", default-features = false } serde = { version = "1.0.126", optional = true, features = ["derive"] } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/api" } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/core" } +sp-core = { version = "4.0.0", default-features = false, path = "../../../primitives/core" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" } diff --git a/frame/merkle-mountain-range/rpc/Cargo.toml b/frame/merkle-mountain-range/rpc/Cargo.toml index d8f861ad8ec5..1cad739e3ba0 100644 --- a/frame/merkle-mountain-range/rpc/Cargo.toml +++ b/frame/merkle-mountain-range/rpc/Cargo.toml @@ -21,7 +21,7 @@ serde = { version = "1.0.126", features = ["derive"] } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../../primitives/core" } sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } pallet-mmr-primitives = { version = "4.0.0-dev", path = "../primitives" } diff --git a/frame/multisig/Cargo.toml b/frame/multisig/Cargo.toml index f409e0c6c8d0..bb6323bc5cb7 100644 --- a/frame/multisig/Cargo.toml +++ b/frame/multisig/Cargo.toml @@ -18,13 +18,13 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/frame/nicks/Cargo.toml b/frame/nicks/Cargo.toml index 039fd7f97c85..8d66bbb6b397 100644 --- a/frame/nicks/Cargo.toml +++ b/frame/nicks/Cargo.toml @@ -15,14 +15,14 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/frame/node-authorization/Cargo.toml b/frame/node-authorization/Cargo.toml index 450da1325f67..ec62d972d3a0 100644 --- a/frame/node-authorization/Cargo.toml +++ b/frame/node-authorization/Cargo.toml @@ -16,10 +16,10 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" } +sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } log = { version = "0.4.14", default-features = false } [features] diff --git a/frame/offences/Cargo.toml b/frame/offences/Cargo.toml index 15939027d3be..8957f0c88cae 100644 --- a/frame/offences/Cargo.toml +++ b/frame/offences/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../balances" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } serde = { version = "1.0.126", optional = true } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" } @@ -26,7 +26,7 @@ log = { version = "0.4.14", default-features = false } [dev-dependencies] sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } [features] default = ["std"] diff --git a/frame/offences/benchmarking/Cargo.toml b/frame/offences/benchmarking/Cargo.toml index cf628b6967ce..96674989e0f7 100644 --- a/frame/offences/benchmarking/Cargo.toml +++ b/frame/offences/benchmarking/Cargo.toml @@ -31,13 +31,13 @@ pallet-staking = { version = "4.0.0-dev", default-features = false, features = [ ], path = "../../staking" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/staking" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } frame-election-provider-support = { version = "4.0.0-dev", default-features = false, path = "../../election-provider-support" } [dev-dependencies] pallet-staking-reward-curve = { version = "4.0.0-dev", path = "../../staking/reward-curve" } pallet-timestamp = { version = "4.0.0-dev", path = "../../timestamp" } -sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../../primitives/core" } sp-io = { version = "4.0.0-dev", path = "../../../primitives/io" } [features] diff --git a/frame/proxy/Cargo.toml b/frame/proxy/Cargo.toml index be288ecc0d75..762ab482b985 100644 --- a/frame/proxy/Cargo.toml +++ b/frame/proxy/Cargo.toml @@ -19,12 +19,12 @@ frame-support = { version = "4.0.0-dev", default-features = false, path = "../su frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } pallet-utility = { version = "4.0.0-dev", path = "../utility" } diff --git a/frame/randomness-collective-flip/Cargo.toml b/frame/randomness-collective-flip/Cargo.toml index 38fe2f73bc71..3bf2a9c30213 100644 --- a/frame/randomness-collective-flip/Cargo.toml +++ b/frame/randomness-collective-flip/Cargo.toml @@ -17,13 +17,13 @@ safe-mix = { version = "1.0", default-features = false } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } [features] diff --git a/frame/recovery/Cargo.toml b/frame/recovery/Cargo.toml index 12198c135e53..18d4dfe7e47c 100644 --- a/frame/recovery/Cargo.toml +++ b/frame/recovery/Cargo.toml @@ -15,14 +15,14 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/frame/scheduler/Cargo.toml b/frame/scheduler/Cargo.toml index 01cf95fa7fc7..57eb5e16bd36 100644 --- a/frame/scheduler/Cargo.toml +++ b/frame/scheduler/Cargo.toml @@ -15,14 +15,14 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } log = { version = "0.4.14", default-features = false } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -sp-core = { version = "4.0.0-dev", path = "../../primitives/core", default-features = false } +sp-core = { version = "4.0.0", path = "../../primitives/core", default-features = false } substrate-test-utils = { version = "4.0.0-dev", path = "../../test-utils" } [features] diff --git a/frame/scored-pool/Cargo.toml b/frame/scored-pool/Cargo.toml index d60e55ae9896..8f91908dddb9 100644 --- a/frame/scored-pool/Cargo.toml +++ b/frame/scored-pool/Cargo.toml @@ -17,13 +17,13 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } [dev-dependencies] pallet-balances = { version = "4.0.0-dev", path = "../balances" } -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } [features] default = ["std"] diff --git a/frame/session/Cargo.toml b/frame/session/Cargo.toml index 90de15632a0e..50aa623c90a8 100644 --- a/frame/session/Cargo.toml +++ b/frame/session/Cargo.toml @@ -19,8 +19,8 @@ impl-trait-for-tuples = "0.2.1" codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } +sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../primitives/session" } diff --git a/frame/session/benchmarking/Cargo.toml b/frame/session/benchmarking/Cargo.toml index 31a028679cfb..5dc0573b278f 100644 --- a/frame/session/benchmarking/Cargo.toml +++ b/frame/session/benchmarking/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] rand = { version = "0.7.2", default-features = false } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/session" } @@ -28,7 +28,7 @@ pallet-staking = { version = "4.0.0-dev", default-features = false, features = [ [dev-dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", features = ["derive"] } scale-info = "1.0" -sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../../primitives/core" } sp-io = { version = "4.0.0-dev", path = "../../../primitives/io" } pallet-balances = { version = "4.0.0-dev", path = "../../balances" } pallet-timestamp = { version = "4.0.0-dev", path = "../../timestamp" } diff --git a/frame/society/Cargo.toml b/frame/society/Cargo.toml index 8a817f7e0060..47ad0865b8f4 100644 --- a/frame/society/Cargo.toml +++ b/frame/society/Cargo.toml @@ -16,13 +16,13 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } rand_chacha = { version = "0.2", default-features = false } [dev-dependencies] -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } sp-io ={ version = "4.0.0-dev", path = "../../primitives/io" } frame-support-test = { version = "3.0.0", path = "../support/test" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } diff --git a/frame/staking/Cargo.toml b/frame/staking/Cargo.toml index 81f5b181850c..70beead038b2 100644 --- a/frame/staking/Cargo.toml +++ b/frame/staking/Cargo.toml @@ -18,7 +18,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = "derive", ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" } @@ -37,8 +37,8 @@ frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = " rand_chacha = { version = "0.2", default-features = false, optional = true } [dev-dependencies] -sp-tracing = { version = "4.0.0-dev", path = "../../primitives/tracing" } -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } sp-npos-elections = { version = "4.0.0-dev", path = "../../primitives/npos-elections" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } pallet-timestamp = { version = "4.0.0-dev", path = "../timestamp" } diff --git a/frame/sudo/Cargo.toml b/frame/sudo/Cargo.toml index 969dc11dbb6c..d211d327b2d0 100644 --- a/frame/sudo/Cargo.toml +++ b/frame/sudo/Cargo.toml @@ -15,14 +15,14 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } [features] default = ["std"] diff --git a/frame/support/Cargo.toml b/frame/support/Cargo.toml index 1f48dadc2987..411b02449e4e 100644 --- a/frame/support/Cargo.toml +++ b/frame/support/Cargo.toml @@ -17,11 +17,11 @@ serde = { version = "1.0.126", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } frame-metadata = { version = "14.0.0", default-features = false, features = ["v14"] } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-tracing = { version = "4.0.0-dev", default-features = false, path = "../../primitives/tracing" } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" } +sp-tracing = { version = "4.0.0", default-features = false, path = "../../primitives/tracing" } +sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } sp-arithmetic = { version = "4.0.0-dev", default-features = false, path = "../../primitives/arithmetic" } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../primitives/inherents" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" } diff --git a/frame/support/test/Cargo.toml b/frame/support/test/Cargo.toml index 09a1538e2741..13d66d147e57 100644 --- a/frame/support/test/Cargo.toml +++ b/frame/support/test/Cargo.toml @@ -20,8 +20,8 @@ sp-io = { version = "4.0.0-dev", path = "../../../primitives/io", default-featur sp-state-machine = { version = "0.10.0-dev", optional = true, path = "../../../primitives/state-machine" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/core" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/std" } +sp-core = { version = "4.0.0", default-features = false, path = "../../../primitives/core" } +sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } sp-version = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/version" } trybuild = "1.0.52" pretty_assertions = "1.0.0" diff --git a/frame/support/test/compile_pass/Cargo.toml b/frame/support/test/compile_pass/Cargo.toml index b8a64f4e7022..62472a8957ce 100644 --- a/frame/support/test/compile_pass/Cargo.toml +++ b/frame/support/test/compile_pass/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/core" } +sp-core = { version = "4.0.0", default-features = false, path = "../../../../primitives/core" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/runtime" } sp-version = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/version" } support = { package = "frame-support", version = "4.0.0-dev", default-features = false, path = "../../" } diff --git a/frame/system/Cargo.toml b/frame/system/Cargo.toml index c5d2144e28dd..fc510d1d9d79 100644 --- a/frame/system/Cargo.toml +++ b/frame/system/Cargo.toml @@ -16,8 +16,8 @@ targets = ["x86_64-unknown-linux-gnu"] serde = { version = "1.0.126", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0-dev", path = "../../primitives/io", default-features = false } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } sp-version = { version = "4.0.0-dev", default-features = false, path = "../../primitives/version" } @@ -26,7 +26,7 @@ log = { version = "0.4.14", default-features = false } [dev-dependencies] criterion = "0.3.3" -sp-externalities = { version = "0.10.0-dev", path = "../../primitives/externalities" } +sp-externalities = { version = "0.10.0", path = "../../primitives/externalities" } substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } [features] diff --git a/frame/system/benchmarking/Cargo.toml b/frame/system/benchmarking/Cargo.toml index 7e7c2f6e69f2..9468c8761435 100644 --- a/frame/system/benchmarking/Cargo.toml +++ b/frame/system/benchmarking/Cargo.toml @@ -15,12 +15,12 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../../benchmarking" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/core" } +sp-core = { version = "4.0.0", default-features = false, path = "../../../primitives/core" } [dev-dependencies] sp-io = { version = "4.0.0-dev", path = "../../../primitives/io" } diff --git a/frame/timestamp/Cargo.toml b/frame/timestamp/Cargo.toml index a942b58e0950..26554598be10 100644 --- a/frame/timestamp/Cargo.toml +++ b/frame/timestamp/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io", optional = true } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../primitives/inherents" } @@ -29,7 +29,7 @@ log = { version = "0.4.14", default-features = false } [dev-dependencies] sp-io ={ version = "4.0.0-dev", path = "../../primitives/io" } -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } [features] default = ["std"] diff --git a/frame/tips/Cargo.toml b/frame/tips/Cargo.toml index 49b19756e43c..565afcd3fbc6 100644 --- a/frame/tips/Cargo.toml +++ b/frame/tips/Cargo.toml @@ -18,10 +18,10 @@ log = { version = "0.4.0", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } serde = { version = "1.0.126", features = ["derive"], optional = true } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" } +sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } @@ -30,7 +30,7 @@ pallet-treasury = { version = "4.0.0-dev", default-features = false, path = "../ frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -sp-storage = { version = "4.0.0-dev", path = "../../primitives/storage" } +sp-storage = { version = "4.0.0", path = "../../primitives/storage" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/frame/transaction-payment/Cargo.toml b/frame/transaction-payment/Cargo.toml index 3b8b85977db3..64e1d5c762ca 100644 --- a/frame/transaction-payment/Cargo.toml +++ b/frame/transaction-payment/Cargo.toml @@ -20,10 +20,10 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] serde = { version = "1.0.126", optional = true } smallvec = "1.7.0" -sp-core = { version = "4.0.0-dev", path = "../../primitives/core", default-features = false } +sp-core = { version = "4.0.0", path = "../../primitives/core", default-features = false } sp-io = { version = "4.0.0-dev", path = "../../primitives/io", default-features = false } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/transaction-payment/asset-tx-payment/Cargo.toml b/frame/transaction-payment/asset-tx-payment/Cargo.toml index a79bf6855100..cae6b7b914e1 100644 --- a/frame/transaction-payment/asset-tx-payment/Cargo.toml +++ b/frame/transaction-payment/asset-tx-payment/Cargo.toml @@ -14,10 +14,10 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] # Substrate dependencies -sp-core = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/core" } +sp-core = { version = "4.0.0", default-features = false, path = "../../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/io" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" } @@ -32,7 +32,7 @@ serde = { version = "1.0.126", optional = true } smallvec = "1.7.0" serde_json = "1.0.71" -sp-storage = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/storage" } +sp-storage = { version = "4.0.0", default-features = false, path = "../../../primitives/storage" } pallet-assets = { version = "4.0.0-dev", path = "../../assets" } pallet-authorship = { version = "4.0.0-dev", path = "../../authorship" } diff --git a/frame/transaction-payment/rpc/Cargo.toml b/frame/transaction-payment/rpc/Cargo.toml index 8ce2e4991568..dd18edf5daf0 100644 --- a/frame/transaction-payment/rpc/Cargo.toml +++ b/frame/transaction-payment/rpc/Cargo.toml @@ -20,7 +20,7 @@ jsonrpc-derive = "18.0.0" sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../../primitives/core" } sp-rpc = { version = "4.0.0-dev", path = "../../../primitives/rpc" } sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } pallet-transaction-payment-rpc-runtime-api = { version = "4.0.0-dev", path = "./runtime-api" } diff --git a/frame/transaction-storage/Cargo.toml b/frame/transaction-storage/Cargo.toml index 4b4ee7de8509..141aeb496dde 100644 --- a/frame/transaction-storage/Cargo.toml +++ b/frame/transaction-storage/Cargo.toml @@ -21,7 +21,7 @@ frame-support = { version = "4.0.0-dev", default-features = false, path = "../su frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../balances" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../primitives/inherents" } sp-transaction-storage-proof = { version = "4.0.0-dev", default-features = false, path = "../../primitives/transaction-storage-proof" } @@ -29,7 +29,7 @@ frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = " [dev-dependencies] sp-transaction-storage-proof = { version = "4.0.0-dev", default-features = true, path = "../../primitives/transaction-storage-proof" } -sp-core = { version = "4.0.0-dev", path = "../../primitives/core", default-features = false } +sp-core = { version = "4.0.0", path = "../../primitives/core", default-features = false } [features] default = ["std"] diff --git a/frame/treasury/Cargo.toml b/frame/treasury/Cargo.toml index d44699825a6f..4cbcb08c3ef6 100644 --- a/frame/treasury/Cargo.toml +++ b/frame/treasury/Cargo.toml @@ -21,7 +21,7 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] serde = { version = "1.0.126", features = ["derive"], optional = true } impl-trait-for-tuples = "0.2.1" -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } @@ -32,7 +32,7 @@ pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../ [dev-dependencies] sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } [features] default = ["std"] diff --git a/frame/try-runtime/Cargo.toml b/frame/try-runtime/Cargo.toml index c94771795319..64622bcceb02 100644 --- a/frame/try-runtime/Cargo.toml +++ b/frame/try-runtime/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-api = { version = "4.0.0-dev", path = "../../primitives/api", default-features = false } -sp-std = { version = "4.0.0-dev", path = "../../primitives/std" , default-features = false } +sp-std = { version = "4.0.0", path = "../../primitives/std" , default-features = false } sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" , default-features = false } frame-support = { version = "4.0.0-dev", path = "../support", default-features = false } diff --git a/frame/uniques/Cargo.toml b/frame/uniques/Cargo.toml index 9d7e8f7184d1..7eddc85b67bb 100644 --- a/frame/uniques/Cargo.toml +++ b/frame/uniques/Cargo.toml @@ -15,15 +15,15 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -sp-std = { version = "4.0.0-dev", path = "../../primitives/std" } -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-std = { version = "4.0.0", path = "../../primitives/std" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } diff --git a/frame/utility/Cargo.toml b/frame/utility/Cargo.toml index 8407bf53e73d..ac9254bd0854 100644 --- a/frame/utility/Cargo.toml +++ b/frame/utility/Cargo.toml @@ -17,15 +17,15 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" } +sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/frame/vesting/Cargo.toml b/frame/vesting/Cargo.toml index efec3be330dc..5d66db1c981b 100644 --- a/frame/vesting/Cargo.toml +++ b/frame/vesting/Cargo.toml @@ -17,7 +17,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = "derive", ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } @@ -26,7 +26,7 @@ log = { version = "0.4.0", default-features = false } [dev-dependencies] sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/primitives/api/Cargo.toml b/primitives/api/Cargo.toml index 5723f9cf11b5..d64da8ff84d7 100644 --- a/primitives/api/Cargo.toml +++ b/primitives/api/Cargo.toml @@ -15,8 +15,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } sp-api-proc-macro = { version = "4.0.0-dev", path = "proc-macro" } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../core" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" } +sp-core = { version = "4.0.0", default-features = false, path = "../core" } +sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../runtime" } sp-version = { version = "4.0.0-dev", default-features = false, path = "../version" } sp-state-machine = { version = "0.10.0-dev", optional = true, path = "../state-machine" } diff --git a/primitives/api/test/Cargo.toml b/primitives/api/test/Cargo.toml index dccc123142da..dc2ca67242ac 100644 --- a/primitives/api/test/Cargo.toml +++ b/primitives/api/test/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] sp-api = { version = "4.0.0-dev", path = "../" } substrate-test-runtime-client = { version = "2.0.0", path = "../../../test-utils/runtime/client" } sp-version = { version = "4.0.0-dev", path = "../../version" } -sp-tracing = { version = "4.0.0-dev", path = "../../tracing" } +sp-tracing = { version = "4.0.0", path = "../../tracing" } sp-runtime = { version = "4.0.0-dev", path = "../../runtime" } sp-consensus = { version = "0.10.0-dev", path = "../../consensus/common" } sc-block-builder = { version = "0.10.0-dev", path = "../../../client/block-builder" } @@ -28,7 +28,7 @@ rustversion = "1.0.5" criterion = "0.3.0" futures = "0.3.9" log = "0.4.14" -sp-core = { version = "4.0.0-dev", path = "../../core" } +sp-core = { version = "4.0.0", path = "../../core" } [[bench]] name = "bench" diff --git a/primitives/application-crypto/Cargo.toml b/primitives/application-crypto/Cargo.toml index e715d2ed3d31..fd6dd87fa1b2 100644 --- a/primitives/application-crypto/Cargo.toml +++ b/primitives/application-crypto/Cargo.toml @@ -15,11 +15,11 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-core = { version = "4.0.0-dev", default-features = false, path = "../core" } +sp-core = { version = "4.0.0", default-features = false, path = "../core" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } serde = { version = "1.0.126", optional = true, features = ["derive"] } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" } +sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../io" } [features] diff --git a/primitives/application-crypto/test/Cargo.toml b/primitives/application-crypto/test/Cargo.toml index f59f5d9a249c..6ab3cfed0815 100644 --- a/primitives/application-crypto/test/Cargo.toml +++ b/primitives/application-crypto/test/Cargo.toml @@ -13,7 +13,7 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-core = { version = "4.0.0-dev", default-features = false, path = "../../core" } +sp-core = { version = "4.0.0", default-features = false, path = "../../core" } sp-keystore = { version = "0.10.0-dev", path = "../../keystore", default-features = false } substrate-test-runtime-client = { version = "2.0.0", path = "../../../test-utils/runtime/client" } sp-runtime = { version = "4.0.0-dev", path = "../../runtime" } diff --git a/primitives/arithmetic/Cargo.toml b/primitives/arithmetic/Cargo.toml index 139a04180828..9bd634bb5187 100644 --- a/primitives/arithmetic/Cargo.toml +++ b/primitives/arithmetic/Cargo.toml @@ -22,9 +22,9 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] integer-sqrt = "0.1.2" static_assertions = "1.1.0" num-traits = { version = "0.2.8", default-features = false } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" } +sp-std = { version = "4.0.0", default-features = false, path = "../std" } serde = { version = "1.0.126", optional = true, features = ["derive"] } -sp-debug-derive = { version = "4.0.0-dev", default-features = false, path = "../debug-derive" } +sp-debug-derive = { version = "4.0.0", default-features = false, path = "../debug-derive" } [dev-dependencies] rand = "0.7.2" diff --git a/primitives/authority-discovery/Cargo.toml b/primitives/authority-discovery/Cargo.toml index 22f3884b5502..116bc1438ce6 100644 --- a/primitives/authority-discovery/Cargo.toml +++ b/primitives/authority-discovery/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] sp-application-crypto = { version = "4.0.0-dev", default-features = false, path = "../application-crypto" } codec = { package = "parity-scale-codec", default-features = false, version = "2.0.0" } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" } +sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../runtime" } diff --git a/primitives/authorship/Cargo.toml b/primitives/authorship/Cargo.toml index a31a34961116..26259e45ea6b 100644 --- a/primitives/authorship/Cargo.toml +++ b/primitives/authorship/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../inherents" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../runtime" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" } +sp-std = { version = "4.0.0", default-features = false, path = "../std" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } async-trait = { version = "0.1.50", optional = true } diff --git a/primitives/beefy/Cargo.toml b/primitives/beefy/Cargo.toml index e38af745cd71..4a1f844b9200 100644 --- a/primitives/beefy/Cargo.toml +++ b/primitives/beefy/Cargo.toml @@ -13,9 +13,9 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] sp-api = { version = "4.0.0-dev", path = "../api", default-features = false } sp-application-crypto = { version = "4.0.0-dev", path = "../application-crypto", default-features = false } -sp-core = { version = "4.0.0-dev", path = "../core", default-features = false } +sp-core = { version = "4.0.0", path = "../core", default-features = false } sp-runtime = { version = "4.0.0-dev", path = "../runtime", default-features = false } -sp-std = { version = "4.0.0-dev", path = "../std", default-features = false } +sp-std = { version = "4.0.0", path = "../std", default-features = false } [dev-dependencies] hex = "0.4.3" diff --git a/primitives/block-builder/Cargo.toml b/primitives/block-builder/Cargo.toml index 6c6579c35329..a346f95cc4c4 100644 --- a/primitives/block-builder/Cargo.toml +++ b/primitives/block-builder/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../runtime" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" } +sp-std = { version = "4.0.0", default-features = false, path = "../std" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../inherents" } diff --git a/primitives/consensus/aura/Cargo.toml b/primitives/consensus/aura/Cargo.toml index 361095c6218f..e3c883a6e783 100644 --- a/primitives/consensus/aura/Cargo.toml +++ b/primitives/consensus/aura/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] sp-application-crypto = { version = "4.0.0-dev", default-features = false, path = "../../application-crypto" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../std" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../api" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../runtime" } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../inherents" } diff --git a/primitives/consensus/babe/Cargo.toml b/primitives/consensus/babe/Cargo.toml index d942f7290945..a07dc54e2979 100644 --- a/primitives/consensus/babe/Cargo.toml +++ b/primitives/consensus/babe/Cargo.toml @@ -17,12 +17,12 @@ sp-application-crypto = { version = "4.0.0-dev", default-features = false, path codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } merlin = { version = "2.0", default-features = false } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../std" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../api" } sp-consensus = { version = "0.10.0-dev", optional = true, path = "../common" } sp-consensus-slots = { version = "0.10.0-dev", default-features = false, path = "../slots" } sp-consensus-vrf = { version = "0.10.0-dev", path = "../vrf", default-features = false } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../../core" } +sp-core = { version = "4.0.0", default-features = false, path = "../../core" } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../inherents" } sp-keystore = { version = "0.10.0-dev", default-features = false, path = "../../keystore", optional = true } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../runtime" } diff --git a/primitives/consensus/common/Cargo.toml b/primitives/consensus/common/Cargo.toml index 08e50a954288..4b5ef8796afa 100644 --- a/primitives/consensus/common/Cargo.toml +++ b/primitives/consensus/common/Cargo.toml @@ -20,11 +20,11 @@ codec = { package = "parity-scale-codec", version = "2.0.0", features = [ ] } futures = { version = "0.3.1", features = ["thread-pool"] } log = "0.4.8" -sp-core = { path = "../../core", version = "4.0.0-dev" } +sp-core = { path = "../../core", version = "4.0.0" } sp-inherents = { version = "4.0.0-dev", path = "../../inherents" } sp-state-machine = { version = "0.10.0-dev", path = "../../state-machine" } futures-timer = "3.0.1" -sp-std = { version = "4.0.0-dev", path = "../../std" } +sp-std = { version = "4.0.0", path = "../../std" } sp-version = { version = "4.0.0-dev", path = "../../version" } sp-runtime = { version = "4.0.0-dev", path = "../../runtime" } thiserror = "1.0.30" diff --git a/primitives/consensus/pow/Cargo.toml b/primitives/consensus/pow/Cargo.toml index 07863850a8f8..1612868b3637 100644 --- a/primitives/consensus/pow/Cargo.toml +++ b/primitives/consensus/pow/Cargo.toml @@ -14,9 +14,9 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-api = { version = "4.0.0-dev", default-features = false, path = "../../api" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../std" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../runtime" } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../../core" } +sp-core = { version = "4.0.0", default-features = false, path = "../../core" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } [features] diff --git a/primitives/consensus/vrf/Cargo.toml b/primitives/consensus/vrf/Cargo.toml index 8a99dc9432a0..97e426016d9a 100644 --- a/primitives/consensus/vrf/Cargo.toml +++ b/primitives/consensus/vrf/Cargo.toml @@ -15,8 +15,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { version = "2.0.0", package = "parity-scale-codec", default-features = false } schnorrkel = { version = "0.9.1", features = ["preaudit_deprecated", "u64_backend"], default-features = false } -sp-std = { version = "4.0.0-dev", path = "../../std", default-features = false } -sp-core = { version = "4.0.0-dev", path = "../../core", default-features = false } +sp-std = { version = "4.0.0", path = "../../std", default-features = false } +sp-core = { version = "4.0.0", path = "../../core", default-features = false } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../runtime" } [features] diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index 61451e10ecf2..5c805ff1dab8 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-core" -version = "4.0.0-dev" +version = "4.0.0" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" @@ -13,7 +13,6 @@ documentation = "https://docs.rs/sp-core" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" } codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = [ "derive", "max-encoded-len", @@ -40,9 +39,10 @@ zeroize = { version = "1.4.2", default-features = false } secrecy = { version = "0.8.0", default-features = false } lazy_static = { version = "1.4.0", default-features = false, optional = true } parking_lot = { version = "0.11.1", optional = true } -sp-debug-derive = { version = "4.0.0-dev", default-features = false, path = "../debug-derive" } -sp-externalities = { version = "0.10.0-dev", optional = true, path = "../externalities" } -sp-storage = { version = "4.0.0-dev", default-features = false, path = "../storage" } +sp-std = { version = "4.0.0", default-features = false, path = "../std" } +sp-debug-derive = { version = "4.0.0", default-features = false, path = "../debug-derive" } +sp-storage = { version = "4.0.0", default-features = false, path = "../storage" } +sp-externalities = { version = "0.10.0", optional = true, path = "../externalities" } parity-util-mem = { version = "0.10.2", default-features = false, features = [ "primitive-types", ] } @@ -66,10 +66,10 @@ sha2 = { version = "0.9.8", default-features = false, optional = true } hex = { version = "0.4", default-features = false, optional = true } twox-hash = { version = "1.6.1", default-features = false, optional = true } libsecp256k1 = { version = "0.7", default-features = false, features = ["hmac", "static-context"], optional = true } -sp-core-hashing = { version = "4.0.0-dev", path = "./hashing", default-features = false, optional = true } merlin = { version = "2.0", default-features = false, optional = true } ss58-registry = { version = "1.5.0", default-features = false } -sp-runtime-interface = { version = "4.0.0-dev", default-features = false, path = "../runtime-interface" } +sp-core-hashing = { version = "4.0.0", path = "./hashing", default-features = false, optional = true } +sp-runtime-interface = { version = "4.0.0", default-features = false, path = "../runtime-interface" } [dev-dependencies] sp-serializer = { version = "4.0.0-dev", path = "../serializer" } diff --git a/primitives/core/hashing/Cargo.toml b/primitives/core/hashing/Cargo.toml index eeee40405344..23ff01c0b34b 100644 --- a/primitives/core/hashing/Cargo.toml +++ b/primitives/core/hashing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-core-hashing" -version = "4.0.0-dev" +version = "4.0.0" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" @@ -13,7 +13,7 @@ documentation = "https://docs.rs/sp-core-hashing" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../std" } byteorder = { version = "1.3.2", default-features = false } blake2-rfc = { version = "0.2.18", default-features = false } diff --git a/primitives/core/hashing/proc-macro/Cargo.toml b/primitives/core/hashing/proc-macro/Cargo.toml index 89b225e6aaa5..dcd2f134519e 100644 --- a/primitives/core/hashing/proc-macro/Cargo.toml +++ b/primitives/core/hashing/proc-macro/Cargo.toml @@ -19,4 +19,4 @@ proc-macro = true syn = { version = "1.0.81", features = ["full", "parsing"] } quote = "1.0.6" proc-macro2 = "1.0.29" -sp-core-hashing = { version = "4.0.0-dev", path = "../", default-features = false } +sp-core-hashing = { version = "4.0.0", path = "../", default-features = false } diff --git a/primitives/debug-derive/Cargo.toml b/primitives/debug-derive/Cargo.toml index 49b8ac832cf0..a38cc186fb52 100644 --- a/primitives/debug-derive/Cargo.toml +++ b/primitives/debug-derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-debug-derive" -version = "4.0.0-dev" +version = "4.0.0" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" diff --git a/primitives/externalities/Cargo.toml b/primitives/externalities/Cargo.toml index 96199c5b4d22..6c26b436796e 100644 --- a/primitives/externalities/Cargo.toml +++ b/primitives/externalities/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-externalities" -version = "0.10.0-dev" +version = "0.10.0" license = "Apache-2.0" authors = ["Parity Technologies "] edition = "2021" @@ -14,8 +14,8 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-storage = { version = "4.0.0-dev", path = "../storage", default-features = false } -sp-std = { version = "4.0.0-dev", path = "../std", default-features = false } +sp-storage = { version = "4.0.0", path = "../storage", default-features = false } +sp-std = { version = "4.0.0", path = "../std", default-features = false } environmental = { version = "1.1.3", default-features = false } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } diff --git a/primitives/finality-grandpa/Cargo.toml b/primitives/finality-grandpa/Cargo.toml index 4b9fde85147e..be4f3c6d1e3d 100644 --- a/primitives/finality-grandpa/Cargo.toml +++ b/primitives/finality-grandpa/Cargo.toml @@ -22,10 +22,10 @@ log = { version = "0.4.8", optional = true } serde = { version = "1.0.126", optional = true, features = ["derive"] } sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } sp-application-crypto = { version = "4.0.0-dev", default-features = false, path = "../application-crypto" } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../core" } +sp-core = { version = "4.0.0", default-features = false, path = "../core" } sp-keystore = { version = "0.10.0-dev", default-features = false, path = "../keystore", optional = true } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../runtime" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" } +sp-std = { version = "4.0.0", default-features = false, path = "../std" } [features] default = ["std"] diff --git a/primitives/inherents/Cargo.toml b/primitives/inherents/Cargo.toml index 3efd6ab03213..c531ad4e5764 100644 --- a/primitives/inherents/Cargo.toml +++ b/primitives/inherents/Cargo.toml @@ -15,8 +15,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../core" } +sp-std = { version = "4.0.0", default-features = false, path = "../std" } +sp-core = { version = "4.0.0", default-features = false, path = "../core" } sp-runtime = { version = "4.0.0-dev", path = "../runtime", optional = true } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } thiserror = { version = "1.0.30", optional = true } diff --git a/primitives/io/Cargo.toml b/primitives/io/Cargo.toml index 2e0982a6e5f1..520dc12a5260 100644 --- a/primitives/io/Cargo.toml +++ b/primitives/io/Cargo.toml @@ -17,16 +17,16 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } hash-db = { version = "0.15.2", default-features = false } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../core" } +sp-core = { version = "4.0.0", default-features = false, path = "../core" } sp-keystore = { version = "0.10.0-dev", default-features = false, optional = true, path = "../keystore" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" } +sp-std = { version = "4.0.0", default-features = false, path = "../std" } libsecp256k1 = { version = "0.7", optional = true } sp-state-machine = { version = "0.10.0-dev", optional = true, path = "../state-machine" } -sp-wasm-interface = { version = "4.0.0-dev", path = "../wasm-interface", default-features = false } -sp-runtime-interface = { version = "4.0.0-dev", default-features = false, path = "../runtime-interface" } +sp-wasm-interface = { version = "4.0.0", path = "../wasm-interface", default-features = false } +sp-runtime-interface = { version = "4.0.0", default-features = false, path = "../runtime-interface" } sp-trie = { version = "4.0.0-dev", optional = true, path = "../trie" } -sp-externalities = { version = "0.10.0-dev", optional = true, path = "../externalities" } -sp-tracing = { version = "4.0.0-dev", default-features = false, path = "../tracing" } +sp-externalities = { version = "0.10.0", optional = true, path = "../externalities" } +sp-tracing = { version = "4.0.0", default-features = false, path = "../tracing" } log = { version = "0.4.8", optional = true } futures = { version = "0.3.1", features = ["thread-pool"], optional = true } parking_lot = { version = "0.11.1", optional = true } diff --git a/primitives/keyring/Cargo.toml b/primitives/keyring/Cargo.toml index 249e7d766e39..66c1240a8a56 100644 --- a/primitives/keyring/Cargo.toml +++ b/primitives/keyring/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-core = { version = "4.0.0-dev", path = "../core" } +sp-core = { version = "4.0.0", path = "../core" } sp-runtime = { version = "4.0.0-dev", path = "../runtime" } lazy_static = "1.4.0" strum = { version = "0.22.0", features = ["derive"] } diff --git a/primitives/keystore/Cargo.toml b/primitives/keystore/Cargo.toml index ab026ccedd51..b0061ac111e2 100644 --- a/primitives/keystore/Cargo.toml +++ b/primitives/keystore/Cargo.toml @@ -21,8 +21,8 @@ schnorrkel = { version = "0.9.1", features = ["preaudit_deprecated", "u64_backen merlin = { version = "2.0", default-features = false } parking_lot = { version = "0.11.1", default-features = false } serde = { version = "1.0", optional = true} -sp-core = { version = "4.0.0-dev", path = "../core" } -sp-externalities = { version = "0.10.0-dev", path = "../externalities", default-features = false } +sp-core = { version = "4.0.0", path = "../core" } +sp-externalities = { version = "0.10.0", path = "../externalities", default-features = false } [dev-dependencies] rand = "0.7.2" diff --git a/primitives/npos-elections/Cargo.toml b/primitives/npos-elections/Cargo.toml index 95f303a38252..16aca8dc71d9 100644 --- a/primitives/npos-elections/Cargo.toml +++ b/primitives/npos-elections/Cargo.toml @@ -16,10 +16,10 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } serde = { version = "1.0.126", optional = true, features = ["derive"] } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" } +sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-npos-elections-solution-type = { version = "4.0.0-dev", path = "./solution-type" } sp-arithmetic = { version = "4.0.0-dev", default-features = false, path = "../arithmetic" } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../core" } +sp-core = { version = "4.0.0", default-features = false, path = "../core" } sp-runtime = { version = "4.0.0-dev", path = "../runtime", default-features = false } [dev-dependencies] diff --git a/primitives/offchain/Cargo.toml b/primitives/offchain/Cargo.toml index c4da2b4f8892..f079ccb7913f 100644 --- a/primitives/offchain/Cargo.toml +++ b/primitives/offchain/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-core = { version = "4.0.0-dev", default-features = false, path = "../core" } +sp-core = { version = "4.0.0", default-features = false, path = "../core" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../runtime" } diff --git a/primitives/rpc/Cargo.toml b/primitives/rpc/Cargo.toml index 2d56cb06fbcc..59cbf53fee2a 100644 --- a/primitives/rpc/Cargo.toml +++ b/primitives/rpc/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.126", features = ["derive"] } -sp-core = { version = "4.0.0-dev", path = "../core" } +sp-core = { version = "4.0.0", path = "../core" } rustc-hash = "1.1.0" [dev-dependencies] diff --git a/primitives/runtime-interface/Cargo.toml b/primitives/runtime-interface/Cargo.toml index dd93b92b9be4..64781481fa12 100644 --- a/primitives/runtime-interface/Cargo.toml +++ b/primitives/runtime-interface/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-runtime-interface" -version = "4.0.0-dev" +version = "4.0.0" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" @@ -14,21 +14,21 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-wasm-interface = { version = "4.0.0-dev", path = "../wasm-interface", default-features = false } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" } -sp-tracing = { version = "4.0.0-dev", default-features = false, path = "../tracing" } -sp-runtime-interface-proc-macro = { version = "4.0.0-dev", path = "proc-macro" } -sp-externalities = { version = "0.10.0-dev", optional = true, path = "../externalities" } +sp-wasm-interface = { version = "4.0.0", path = "../wasm-interface", default-features = false } +sp-std = { version = "4.0.0", default-features = false, path = "../std" } +sp-tracing = { version = "4.0.0", default-features = false, path = "../tracing" } +sp-runtime-interface-proc-macro = { version = "4.0.0", path = "proc-macro" } +sp-externalities = { version = "0.10.0", optional = true, path = "../externalities" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } static_assertions = "1.0.0" primitive-types = { version = "0.10.1", default-features = false } -sp-storage = { version = "4.0.0-dev", default-features = false, path = "../storage" } +sp-storage = { version = "4.0.0", default-features = false, path = "../storage" } impl-trait-for-tuples = "0.2.1" [dev-dependencies] sp-runtime-interface-test-wasm = { version = "2.0.0", path = "test-wasm" } sp-state-machine = { version = "0.10.0-dev", path = "../state-machine" } -sp-core = { version = "4.0.0-dev", path = "../core" } +sp-core = { version = "4.0.0", path = "../core" } sp-io = { version = "4.0.0-dev", path = "../io" } rustversion = "1.0.5" trybuild = "1.0.52" diff --git a/primitives/runtime-interface/proc-macro/Cargo.toml b/primitives/runtime-interface/proc-macro/Cargo.toml index 0be33c2c55ad..0b5929616bd3 100644 --- a/primitives/runtime-interface/proc-macro/Cargo.toml +++ b/primitives/runtime-interface/proc-macro/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-runtime-interface-proc-macro" -version = "4.0.0-dev" +version = "4.0.0" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" diff --git a/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml b/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml index 60ece9d78795..68ed8a73282a 100644 --- a/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml +++ b/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml @@ -13,10 +13,10 @@ publish = false targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-runtime-interface = { version = "4.0.0-dev", default-features = false, path = "../" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../std" } +sp-runtime-interface = { version = "4.0.0", default-features = false, path = "../" } +sp-std = { version = "4.0.0", default-features = false, path = "../../std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../io" } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../../core" } +sp-core = { version = "4.0.0", default-features = false, path = "../../core" } [build-dependencies] substrate-wasm-builder = { version = "5.0.0-dev", path = "../../../utils/wasm-builder" } diff --git a/primitives/runtime-interface/test-wasm/Cargo.toml b/primitives/runtime-interface/test-wasm/Cargo.toml index d8dcc8a47053..ab227ddeda27 100644 --- a/primitives/runtime-interface/test-wasm/Cargo.toml +++ b/primitives/runtime-interface/test-wasm/Cargo.toml @@ -13,10 +13,10 @@ publish = false targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-runtime-interface = { version = "4.0.0-dev", default-features = false, path = "../" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../std" } +sp-runtime-interface = { version = "4.0.0", default-features = false, path = "../" } +sp-std = { version = "4.0.0", default-features = false, path = "../../std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../io" } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../../core" } +sp-core = { version = "4.0.0", default-features = false, path = "../../core" } [build-dependencies] substrate-wasm-builder = { version = "5.0.0-dev", path = "../../../utils/wasm-builder" } diff --git a/primitives/runtime-interface/test/Cargo.toml b/primitives/runtime-interface/test/Cargo.toml index 4c88438f08c6..5e4483fb38ed 100644 --- a/primitives/runtime-interface/test/Cargo.toml +++ b/primitives/runtime-interface/test/Cargo.toml @@ -12,7 +12,7 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-runtime-interface = { version = "4.0.0-dev", path = "../" } +sp-runtime-interface = { version = "4.0.0", path = "../" } sc-executor = { version = "0.10.0-dev", path = "../../../client/executor" } sc-executor-common = { version = "0.10.0-dev", path = "../../../client/executor/common" } sp-runtime-interface-test-wasm = { version = "2.0.0", path = "../test-wasm" } diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 511d3c1e3792..76c1d94a3b6d 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -18,10 +18,10 @@ targets = ["x86_64-unknown-linux-gnu"] serde = { version = "1.0.126", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../core" } +sp-core = { version = "4.0.0", default-features = false, path = "../core" } sp-application-crypto = { version = "4.0.0-dev", default-features = false, path = "../application-crypto" } sp-arithmetic = { version = "4.0.0-dev", default-features = false, path = "../arithmetic" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" } +sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../io" } log = { version = "0.4.14", default-features = false } paste = "1.0" @@ -37,7 +37,7 @@ rand = "0.7.2" sp-state-machine = { version = "0.10.0-dev", path = "../state-machine" } sp-api = { version = "4.0.0-dev", path = "../api" } substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } -sp-tracing = { version = "4.0.0-dev", path = "../../primitives/tracing" } +sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } zstd = "0.9" [features] diff --git a/primitives/sandbox/Cargo.toml b/primitives/sandbox/Cargo.toml index 8e7acff4ff7e..a51873dc1e99 100644 --- a/primitives/sandbox/Cargo.toml +++ b/primitives/sandbox/Cargo.toml @@ -20,10 +20,10 @@ wasmi = "0.9.0" [dependencies] wasmi = { version = "0.9.0", optional = true } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../core" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" } +sp-core = { version = "4.0.0", default-features = false, path = "../core" } +sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../io" } -sp-wasm-interface = { version = "4.0.0-dev", default-features = false, path = "../wasm-interface" } +sp-wasm-interface = { version = "4.0.0", default-features = false, path = "../wasm-interface" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } log = { version = "0.4", default-features = false } diff --git a/primitives/session/Cargo.toml b/primitives/session/Cargo.toml index 01b299091ed1..eda98b2ab6a8 100644 --- a/primitives/session/Cargo.toml +++ b/primitives/session/Cargo.toml @@ -16,8 +16,8 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../core" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" } +sp-core = { version = "4.0.0", default-features = false, path = "../core" } +sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../staking" } sp-runtime = { version = "4.0.0-dev", optional = true, path = "../runtime" } diff --git a/primitives/staking/Cargo.toml b/primitives/staking/Cargo.toml index 3be8f4aba142..531e696b6930 100644 --- a/primitives/staking/Cargo.toml +++ b/primitives/staking/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../runtime" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" } +sp-std = { version = "4.0.0", default-features = false, path = "../std" } [features] default = ["std"] diff --git a/primitives/state-machine/Cargo.toml b/primitives/state-machine/Cargo.toml index 0133ea17370a..f5047c3c7c46 100644 --- a/primitives/state-machine/Cargo.toml +++ b/primitives/state-machine/Cargo.toml @@ -21,14 +21,14 @@ hash-db = { version = "0.15.2", default-features = false } trie-db = { version = "0.22.6", default-features = false } trie-root = { version = "0.16.0", default-features = false } sp-trie = { version = "4.0.0-dev", path = "../trie", default-features = false } -sp-core = { version = "4.0.0-dev", path = "../core", default-features = false } +sp-core = { version = "4.0.0", path = "../core", default-features = false } sp-panic-handler = { version = "4.0.0-dev", path = "../panic-handler", optional = true } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } num-traits = { version = "0.2.8", default-features = false } rand = { version = "0.7.2", optional = true } -sp-externalities = { version = "0.10.0-dev", path = "../externalities", default-features = false } +sp-externalities = { version = "0.10.0", path = "../externalities", default-features = false } smallvec = "1.7.0" -sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" } +sp-std = { version = "4.0.0", default-features = false, path = "../std" } tracing = { version = "0.1.29", optional = true } [dev-dependencies] diff --git a/primitives/std/Cargo.toml b/primitives/std/Cargo.toml index 34f27ae7256d..4c6aa8f40b49 100644 --- a/primitives/std/Cargo.toml +++ b/primitives/std/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-std" -version = "4.0.0-dev" +version = "4.0.0" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" diff --git a/primitives/storage/Cargo.toml b/primitives/storage/Cargo.toml index c9166a5bbba0..918938273c62 100644 --- a/primitives/storage/Cargo.toml +++ b/primitives/storage/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-storage" -version = "4.0.0-dev" +version = "4.0.0" authors = ["Parity Technologies "] edition = "2021" description = "Storage related primitives" @@ -14,11 +14,11 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" } +sp-std = { version = "4.0.0", default-features = false, path = "../std" } serde = { version = "1.0.126", optional = true, features = ["derive"] } impl-serde = { version = "0.3.1", optional = true } ref-cast = "1.0.0" -sp-debug-derive = { version = "4.0.0-dev", default-features = false, path = "../debug-derive" } +sp-debug-derive = { version = "4.0.0", default-features = false, path = "../debug-derive" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } [features] diff --git a/primitives/tasks/Cargo.toml b/primitives/tasks/Cargo.toml index f472ec88ea18..9a80cc50cf2f 100644 --- a/primitives/tasks/Cargo.toml +++ b/primitives/tasks/Cargo.toml @@ -15,11 +15,11 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] log = { version = "0.4.8", optional = true } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../core" } -sp-externalities = { version = "0.10.0-dev", optional = true, path = "../externalities" } +sp-core = { version = "4.0.0", default-features = false, path = "../core" } +sp-externalities = { version = "0.10.0", optional = true, path = "../externalities" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../io" } -sp-runtime-interface = { version = "4.0.0-dev", default-features = false, path = "../runtime-interface" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" } +sp-runtime-interface = { version = "4.0.0", default-features = false, path = "../runtime-interface" } +sp-std = { version = "4.0.0", default-features = false, path = "../std" } [dev-dependencies] codec = { package = "parity-scale-codec", default-features = false, version = "2.0.0" } diff --git a/primitives/test-primitives/Cargo.toml b/primitives/test-primitives/Cargo.toml index b95c88626996..ea1e61c8da11 100644 --- a/primitives/test-primitives/Cargo.toml +++ b/primitives/test-primitives/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-application-crypto = { version = "4.0.0-dev", default-features = false, path = "../application-crypto" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../core" } +sp-core = { version = "4.0.0", default-features = false, path = "../core" } serde = { version = "1.0.126", optional = true, features = ["derive"] } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../runtime" } parity-util-mem = { version = "0.10.2", default-features = false, features = ["primitive-types"] } diff --git a/primitives/timestamp/Cargo.toml b/primitives/timestamp/Cargo.toml index 609ecd0d3192..0096fe4c809d 100644 --- a/primitives/timestamp/Cargo.toml +++ b/primitives/timestamp/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" } +sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../runtime" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../inherents" } diff --git a/primitives/tracing/Cargo.toml b/primitives/tracing/Cargo.toml index f4bfb1f15dad..0b5a273e11d3 100644 --- a/primitives/tracing/Cargo.toml +++ b/primitives/tracing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-tracing" -version = "4.0.0-dev" +version = "4.0.0" license = "Apache-2.0" authors = ["Parity Technologies "] edition = "2021" @@ -18,7 +18,7 @@ features = ["with-tracing"] targets = ["x86_64-unknown-linux-gnu", "wasm32-unknown-unknown"] [dependencies] -sp-std = { version = "4.0.0-dev", path = "../std", default-features = false } +sp-std = { version = "4.0.0", path = "../std", default-features = false } codec = { version = "2.0.0", package = "parity-scale-codec", default-features = false, features = [ "derive", ] } diff --git a/primitives/transaction-storage-proof/Cargo.toml b/primitives/transaction-storage-proof/Cargo.toml index c967497f4ff9..05da54b24f78 100644 --- a/primitives/transaction-storage-proof/Cargo.toml +++ b/primitives/transaction-storage-proof/Cargo.toml @@ -15,9 +15,9 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../inherents" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../runtime" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" } +sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-trie = { version = "4.0.0-dev", optional = true, path = "../trie" } -sp-core = { version = "4.0.0-dev", path = "../core", optional = true } +sp-core = { version = "4.0.0", path = "../core", optional = true } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } log = { version = "0.4.8", optional = true } diff --git a/primitives/trie/Cargo.toml b/primitives/trie/Cargo.toml index 8eaeb424781b..af81164ed799 100644 --- a/primitives/trie/Cargo.toml +++ b/primitives/trie/Cargo.toml @@ -20,12 +20,12 @@ harness = false [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" } +sp-std = { version = "4.0.0", default-features = false, path = "../std" } hash-db = { version = "0.15.2", default-features = false } trie-db = { version = "0.22.6", default-features = false } trie-root = { version = "0.16.0", default-features = false } memory-db = { version = "0.27.0", default-features = false } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../core" } +sp-core = { version = "4.0.0", default-features = false, path = "../core" } [dev-dependencies] trie-bench = "0.28.0" diff --git a/primitives/version/Cargo.toml b/primitives/version/Cargo.toml index bbdaf9c1cab1..103fe16dc53a 100644 --- a/primitives/version/Cargo.toml +++ b/primitives/version/Cargo.toml @@ -19,7 +19,7 @@ impl-serde = { version = "0.3.1", optional = true } serde = { version = "1.0.126", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" } +sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../runtime" } sp-version-proc-macro = { version = "4.0.0-dev", default-features = false, path = "proc-macro" } parity-wasm = { version = "0.42.2", optional = true } diff --git a/primitives/wasm-interface/Cargo.toml b/primitives/wasm-interface/Cargo.toml index c378b185e392..da0d0161c086 100644 --- a/primitives/wasm-interface/Cargo.toml +++ b/primitives/wasm-interface/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-wasm-interface" -version = "4.0.0-dev" +version = "4.0.0" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] wasmi = { version = "0.9.1", optional = true } impl-trait-for-tuples = "0.2.1" -sp-std = { version = "4.0.0-dev", path = "../std", default-features = false } +sp-std = { version = "4.0.0", path = "../std", default-features = false } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } [features] diff --git a/test-utils/client/Cargo.toml b/test-utils/client/Cargo.toml index ef481dd3f202..3917f3fefcf9 100644 --- a/test-utils/client/Cargo.toml +++ b/test-utils/client/Cargo.toml @@ -29,7 +29,7 @@ sc-service = { version = "0.10.0-dev", default-features = false, features = [ ], path = "../../client/service" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } -sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../primitives/core" } sp-keystore = { version = "0.10.0-dev", path = "../../primitives/keystore" } sp-keyring = { version = "4.0.0-dev", path = "../../primitives/keyring" } sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } diff --git a/test-utils/runtime/Cargo.toml b/test-utils/runtime/Cargo.toml index d0d85029738e..35c14a23f2a2 100644 --- a/test-utils/runtime/Cargo.toml +++ b/test-utils/runtime/Cargo.toml @@ -23,9 +23,9 @@ sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../ sp-keyring = { version = "4.0.0-dev", optional = true, path = "../../primitives/keyring" } memory-db = { version = "0.27.0", default-features = false } sp-offchain = { version = "4.0.0-dev", default-features = false, path = "../../primitives/offchain" } -sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } -sp-runtime-interface = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime-interface" } +sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } +sp-runtime-interface = { version = "4.0.0", default-features = false, path = "../../primitives/runtime-interface" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../../frame/support" } sp-version = { version = "4.0.0-dev", default-features = false, path = "../../primitives/version" } @@ -43,7 +43,7 @@ trie-db = { version = "0.22.6", default-features = false } parity-util-mem = { version = "0.10.2", default-features = false, features = ["primitive-types"] } sc-service = { version = "0.10.0-dev", default-features = false, optional = true, features = ["test-helpers"], path = "../../client/service" } sp-state-machine = { version = "0.10.0-dev", default-features = false, path = "../../primitives/state-machine" } -sp-externalities = { version = "0.10.0-dev", default-features = false, path = "../../primitives/externalities" } +sp-externalities = { version = "0.10.0", default-features = false, path = "../../primitives/externalities" } # 3rd party cfg-if = "1.0" diff --git a/test-utils/runtime/client/Cargo.toml b/test-utils/runtime/client/Cargo.toml index e5cba3a3399a..6dd22e4954c2 100644 --- a/test-utils/runtime/client/Cargo.toml +++ b/test-utils/runtime/client/Cargo.toml @@ -16,7 +16,7 @@ sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/c sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/common" } sc-block-builder = { version = "0.10.0-dev", path = "../../../client/block-builder" } substrate-test-client = { version = "2.0.0", path = "../../client" } -sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../../primitives/core" } substrate-test-runtime = { version = "2.0.0", path = "../../runtime" } sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } diff --git a/utils/frame/benchmarking-cli/Cargo.toml b/utils/frame/benchmarking-cli/Cargo.toml index fab2b963239d..2943877ce4a0 100644 --- a/utils/frame/benchmarking-cli/Cargo.toml +++ b/utils/frame/benchmarking-cli/Cargo.toml @@ -15,12 +15,12 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] frame-benchmarking = { version = "4.0.0-dev", path = "../../../frame/benchmarking" } frame-support = { version = "4.0.0-dev", path = "../../../frame/support" } -sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../../primitives/core" } sc-service = { version = "0.10.0-dev", default-features = false, path = "../../../client/service" } sc-cli = { version = "0.10.0-dev", path = "../../../client/cli" } sc-client-db = { version = "0.10.0-dev", path = "../../../client/db" } sc-executor = { version = "0.10.0-dev", path = "../../../client/executor" } -sp-externalities = { version = "0.10.0-dev", path = "../../../primitives/externalities" } +sp-externalities = { version = "0.10.0", path = "../../../primitives/externalities" } sp-keystore = { version = "0.10.0-dev", path = "../../../primitives/keystore" } sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } sp-state-machine = { version = "0.10.0-dev", path = "../../../primitives/state-machine" } diff --git a/utils/frame/frame-utilities-cli/Cargo.toml b/utils/frame/frame-utilities-cli/Cargo.toml index dfbf73ee9d5f..6c3cb0428284 100644 --- a/utils/frame/frame-utilities-cli/Cargo.toml +++ b/utils/frame/frame-utilities-cli/Cargo.toml @@ -11,7 +11,7 @@ documentation = "https://docs.rs/substrate-frame-cli" readme = "README.md" [dependencies] -sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../../primitives/core" } sc-cli = { version = "0.10.0-dev", path = "../../../client/cli" } sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } structopt = "0.3.25" diff --git a/utils/frame/remote-externalities/Cargo.toml b/utils/frame/remote-externalities/Cargo.toml index 105ab1739f5b..ab91f2649017 100644 --- a/utils/frame/remote-externalities/Cargo.toml +++ b/utils/frame/remote-externalities/Cargo.toml @@ -23,7 +23,7 @@ serde_json = "1.0" serde = "1.0.126" sp-io = { version = "4.0.0-dev", path = "../../../primitives/io" } -sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../../primitives/core" } sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } sp-version = { version = "4.0.0-dev", path = "../../../primitives/version" } diff --git a/utils/frame/rpc/support/Cargo.toml b/utils/frame/rpc/support/Cargo.toml index dbaa12ee5ddb..8e491cc634de 100644 --- a/utils/frame/rpc/support/Cargo.toml +++ b/utils/frame/rpc/support/Cargo.toml @@ -20,7 +20,7 @@ jsonrpc-client-transports = { version = "18.0.0", features = ["http"] } codec = { package = "parity-scale-codec", version = "2.0.0" } serde = "1" frame-support = { version = "4.0.0-dev", path = "../../../../frame/support" } -sp-storage = { version = "4.0.0-dev", path = "../../../../primitives/storage" } +sp-storage = { version = "4.0.0", path = "../../../../primitives/storage" } sc-rpc-api = { version = "0.10.0-dev", path = "../../../../client/rpc-api" } [dev-dependencies] diff --git a/utils/frame/rpc/system/Cargo.toml b/utils/frame/rpc/system/Cargo.toml index 31a46b390210..5fc3812b84da 100644 --- a/utils/frame/rpc/system/Cargo.toml +++ b/utils/frame/rpc/system/Cargo.toml @@ -23,7 +23,7 @@ log = "0.4.8" sp-runtime = { version = "4.0.0-dev", path = "../../../../primitives/runtime" } sp-api = { version = "4.0.0-dev", path = "../../../../primitives/api" } frame-system-rpc-runtime-api = { version = "4.0.0-dev", path = "../../../../frame/system/rpc/runtime-api" } -sp-core = { version = "4.0.0-dev", path = "../../../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../../../primitives/core" } sp-blockchain = { version = "4.0.0-dev", path = "../../../../primitives/blockchain" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../../../../client/transaction-pool/api" } sp-block-builder = { version = "4.0.0-dev", path = "../../../../primitives/block-builder" } @@ -31,5 +31,5 @@ sc-rpc-api = { version = "0.10.0-dev", path = "../../../../client/rpc-api" } [dev-dependencies] substrate-test-runtime-client = { version = "2.0.0", path = "../../../../test-utils/runtime/client" } -sp-tracing = { version = "4.0.0-dev", path = "../../../../primitives/tracing" } +sp-tracing = { version = "4.0.0", path = "../../../../primitives/tracing" } sc-transaction-pool = { version = "4.0.0-dev", path = "../../../../client/transaction-pool" } diff --git a/utils/frame/try-runtime/cli/Cargo.toml b/utils/frame/try-runtime/cli/Cargo.toml index 388b23aeb3eb..71db6100ca17 100644 --- a/utils/frame/try-runtime/cli/Cargo.toml +++ b/utils/frame/try-runtime/cli/Cargo.toml @@ -24,10 +24,10 @@ sc-executor = { version = "0.10.0-dev", path = "../../../../client/executor" } sc-chain-spec = { version = "4.0.0-dev", path = "../../../../client/chain-spec" } sp-state-machine = { version = "0.10.0-dev", path = "../../../../primitives/state-machine" } sp-runtime = { version = "4.0.0-dev", path = "../../../../primitives/runtime" } -sp-core = { version = "4.0.0-dev", path = "../../../../primitives/core" } +sp-core = { version = "4.0.0", path = "../../../../primitives/core" } sp-io = { version = "4.0.0-dev", path = "../../../../primitives/io" } sp-keystore = { version = "0.10.0-dev", path = "../../../../primitives/keystore" } -sp-externalities = { version = "0.10.0-dev", path = "../../../../primitives/externalities" } +sp-externalities = { version = "0.10.0", path = "../../../../primitives/externalities" } sp-version = { version = "4.0.0-dev", path = "../../../../primitives/version" } remote-externalities = { version = "0.10.0-dev", path = "../../remote-externalities" } From c6f86e139d57a37511af769c49b426c2fff3f260 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 Dec 2021 21:03:35 +0000 Subject: [PATCH 268/695] Bump parity-db from 0.3.4 to 0.3.5 (#10330) Bumps [parity-db](https://github.com/paritytech/parity-db) from 0.3.4 to 0.3.5. - [Release notes](https://github.com/paritytech/parity-db/releases) - [Commits](https://github.com/paritytech/parity-db/commits) --- updated-dependencies: - dependency-name: parity-db dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- client/db/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3693fe080693..a3e186aca428 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6299,9 +6299,9 @@ dependencies = [ [[package]] name = "parity-db" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cb5195cb862b13055cf7f7a76c55073dc73885c2a61511e322b8c1666be7332" +checksum = "78a95abf24f1097c6e3181abbbbfc3630b3b5e681470940f719b69acb4911c7f" dependencies = [ "blake2-rfc", "crc32fast", diff --git a/client/db/Cargo.toml b/client/db/Cargo.toml index 08e228ee9afa..f0ce20354a80 100644 --- a/client/db/Cargo.toml +++ b/client/db/Cargo.toml @@ -33,7 +33,7 @@ sc-state-db = { version = "0.10.0-dev", path = "../state-db" } sp-trie = { version = "4.0.0-dev", path = "../../primitives/trie" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-database = { version = "4.0.0-dev", path = "../../primitives/database" } -parity-db = { version = "0.3.4", optional = true } +parity-db = { version = "0.3.5", optional = true } [dev-dependencies] sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } From b45359a50fa0dea641dc9258e60d0b513006a298 Mon Sep 17 00:00:00 2001 From: remzrn Date: Thu, 9 Dec 2021 08:05:48 +0300 Subject: [PATCH 269/695] Fixed logic of the storage migration to triple reference counting. (#10337) * Fixed logic of the storage migration to triple reference counting. The previous behaviour made it impossible for any chain not already upgraded to dual reference counting to upgrade the runtime. * +Removed the on_runtime_upgrade() function from frame-system. +Removed the specific migration .anciallaries from the frame-system pallet level. +Introducted a new module that hosts self-contained ancillary functions and logic to perform the storage migration. The current logic attempts to infer the state of the storage based on whether or not a given migration can be conducted. * Formatting. * + Removed specific AccountData struct. AccountData must now be provided during the runtime implementation of the trait V2ToV3. + Removed apply function. + Made the individual translation function self-sufficient. * + Removed unused decorators. --- frame/system/src/lib.rs | 51 +---------- frame/system/src/migrations/mod.rs | 139 +++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+), 49 deletions(-) create mode 100644 frame/system/src/migrations/mod.rs diff --git a/frame/system/src/lib.rs b/frame/system/src/lib.rs index 7603fe654141..7825c9ec0780 100644 --- a/frame/system/src/lib.rs +++ b/frame/system/src/lib.rs @@ -114,6 +114,8 @@ pub mod mocking; mod tests; pub mod weights; +pub mod migrations; + pub use extensions::{ check_genesis::CheckGenesis, check_mortality::CheckMortality, check_non_zero_sender::CheckNonZeroSender, check_nonce::CheckNonce, @@ -315,15 +317,6 @@ pub mod pallet { #[pallet::hooks] impl Hooks> for Pallet { - fn on_runtime_upgrade() -> frame_support::weights::Weight { - if !UpgradedToTripleRefCount::::get() { - UpgradedToTripleRefCount::::put(true); - migrations::migrate_to_triple_ref_count::() - } else { - 0 - } - } - fn integrity_test() { T::BlockWeights::get().validate().expect("The weights are invalid."); } @@ -634,46 +627,6 @@ pub mod pallet { } } -pub mod migrations { - use super::*; - - #[allow(dead_code)] - /// Migrate from unique `u8` reference counting to triple `u32` reference counting. - pub fn migrate_all() -> frame_support::weights::Weight { - Account::::translate::<(T::Index, u8, T::AccountData), _>(|_key, (nonce, rc, data)| { - Some(AccountInfo { - nonce, - consumers: rc as RefCount, - providers: 1, - sufficients: 0, - data, - }) - }); - T::BlockWeights::get().max_block - } - - #[allow(dead_code)] - /// Migrate from unique `u32` reference counting to triple `u32` reference counting. - pub fn migrate_to_dual_ref_count() -> frame_support::weights::Weight { - Account::::translate::<(T::Index, RefCount, T::AccountData), _>( - |_key, (nonce, consumers, data)| { - Some(AccountInfo { nonce, consumers, providers: 1, sufficients: 0, data }) - }, - ); - T::BlockWeights::get().max_block - } - - /// Migrate from dual `u32` reference counting to triple `u32` reference counting. - pub fn migrate_to_triple_ref_count() -> frame_support::weights::Weight { - Account::::translate::<(T::Index, RefCount, RefCount, T::AccountData), _>( - |_key, (nonce, consumers, providers, data)| { - Some(AccountInfo { nonce, consumers, providers, sufficients: 0, data }) - }, - ); - T::BlockWeights::get().max_block - } -} - #[cfg(feature = "std")] impl GenesisConfig { /// Direct implementation of `GenesisBuild::build_storage`. diff --git a/frame/system/src/migrations/mod.rs b/frame/system/src/migrations/mod.rs new file mode 100644 index 000000000000..03547d200f4a --- /dev/null +++ b/frame/system/src/migrations/mod.rs @@ -0,0 +1,139 @@ +// This file is part of Substrate. + +// Copyright (C) 2021 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. + +//! Migrate the reference counting state. + +use codec::{Decode, Encode, FullCodec}; +use frame_support::{ + pallet_prelude::ValueQuery, traits::PalletInfoAccess, weights::Weight, Blake2_128Concat, + RuntimeDebug, +}; +use sp_std::prelude::*; + +/// Type used to encode the number of references an account has. +type RefCount = u32; + +/// Information of an account. +#[derive(Clone, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode)] +struct AccountInfo { + nonce: Index, + consumers: RefCount, + providers: RefCount, + sufficients: RefCount, + data: AccountData, +} + +/// Trait to implement to give information about types used for migration +pub trait V2ToV3 { + /// The system pallet. + type Pallet: 'static + PalletInfoAccess; + + /// System config account id + type AccountId: 'static + FullCodec; + + /// System config index + type Index: 'static + FullCodec + Copy; + + /// System config account data + type AccountData: 'static + FullCodec; +} + +// ### Warning +// +// The call below is only valid because the name System is enforced +// at runtime construction level for the system pallet. +frame_support::generate_storage_alias!( + System, UpgradedToU32RefCount => Value< + bool, + ValueQuery + > +); + +// ### Warning +// +// The call below is only valid because the name System is enforced +// at runtime construction level for the system pallet. +frame_support::generate_storage_alias!( + System, UpgradedToTripleRefCount => Value< + bool, + ValueQuery + > +); + +// ### Warning +// +// The call below is only valid because the name System is enforced +// at runtime construction level for the system pallet. +frame_support::generate_storage_alias!( + System, Account => Map< + (Blake2_128Concat, T::AccountId), + AccountInfo + > +); + +/// Migrate from unique `u8` reference counting to triple `u32` reference counting. +pub fn migrate_from_single_u8_to_triple_ref_count() -> Weight { + let mut translated: usize = 0; + >::translate::<(T::Index, u8, T::AccountData), _>(|_key, (nonce, rc, data)| { + translated = translated + 1; + Some(AccountInfo { nonce, consumers: rc as RefCount, providers: 1, sufficients: 0, data }) + }); + log::info!( + target: "runtime::system", + "Applied migration from single u8 to triple reference counting to {:?} elements.", + translated + ); + ::put(true); + ::put(true); + Weight::max_value() +} + +/// Migrate from unique `u32` reference counting to triple `u32` reference counting. +pub fn migrate_from_single_to_triple_ref_count() -> Weight { + let mut translated: usize = 0; + >::translate::<(T::Index, RefCount, T::AccountData), _>( + |_key, (nonce, consumers, data)| { + translated = translated + 1; + Some(AccountInfo { nonce, consumers, providers: 1, sufficients: 0, data }) + }, + ); + log::info!( + target: "runtime::system", + "Applied migration from single to triple reference counting to {:?} elements.", + translated + ); + ::put(true); + Weight::max_value() +} + +/// Migrate from dual `u32` reference counting to triple `u32` reference counting. +pub fn migrate_from_dual_to_triple_ref_count() -> Weight { + let mut translated: usize = 0; + >::translate::<(T::Index, RefCount, RefCount, T::AccountData), _>( + |_key, (nonce, consumers, providers, data)| { + translated = translated + 1; + Some(AccountInfo { nonce, consumers, providers, sufficients: 0, data }) + }, + ); + log::info!( + target: "runtime::system", + "Applied migration from dual to triple reference counting to {:?} elements.", + translated + ); + ::put(true); + Weight::max_value() +} From 7926c6dd211694368120f754b7037ec31bf9c4fa Mon Sep 17 00:00:00 2001 From: Guillaume Thiolliere Date: Thu, 9 Dec 2021 15:31:31 +0900 Subject: [PATCH 270/695] improve doc (#10431) --- frame/assets/src/types.rs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/frame/assets/src/types.rs b/frame/assets/src/types.rs index 879e9d5cdcb9..16f7368f12b7 100644 --- a/frame/assets/src/types.rs +++ b/frame/assets/src/types.rs @@ -122,20 +122,25 @@ pub struct DestroyWitness { /// `minimum_balance` of the asset. This is additive - the `minimum_balance` of the asset must be /// met *and then* anything here in addition. pub trait FrozenBalance { - /// Return the frozen balance. Under normal behaviour, this amount should always be - /// withdrawable. + /// Return the frozen balance. /// - /// In reality, the balance of every account must be at least the sum of this (if `Some`) and - /// the asset's minimum_balance, since there may be complications to destroying an asset's - /// account completely. + /// Under normal behaviour, the account balance should not go below the sum of this (if `Some`) + /// and the asset's minimum balance. + /// But the account balance can be below this sum (e.g. if less than the sum has been + /// transfered to the account). /// - /// If `None` is returned, then nothing special is enforced. + /// In special case (privileged intervention) the account balance can go below the sum. /// - /// If any operation ever breaks this requirement (which will only happen through some sort of - /// privileged intervention), then `melted` is called to do any cleanup. + /// If `None` is returned, then nothing special is enforced. fn frozen_balance(asset: AssetId, who: &AccountId) -> Option; /// Called when an account has been removed. + /// + /// # Warning + /// + /// This function must never access storage of pallet asset. This function is called while some + /// change are pending. Calling into the pallet asset in this function can result in unexpected + /// state. fn died(asset: AssetId, who: &AccountId); } From 6681cad311d43f0b41f43da6b1c93836e6bab1c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Thu, 9 Dec 2021 10:28:59 +0100 Subject: [PATCH 271/695] Run contract benchmarks (#10452) * Trigger benchmarks * cargo run --quiet --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_contracts --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/contracts/src/weights.rs --template=./.maintain/frame-weight-template.hbs Co-authored-by: Parity Bot --- frame/contracts/src/weights.rs | 1444 ++++++++++++++++---------------- 1 file changed, 729 insertions(+), 715 deletions(-) diff --git a/frame/contracts/src/weights.rs b/frame/contracts/src/weights.rs index 504ee9ebde03..8a78a7f289a6 100644 --- a/frame/contracts/src/weights.rs +++ b/frame/contracts/src/weights.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_contracts //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-11-19, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2021-12-09, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 // Executed Command: @@ -150,40 +150,40 @@ pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize() -> Weight { - (2_832_000 as Weight) + (2_854_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn on_initialize_per_trie_key(k: u32, ) -> Weight { (0 as Weight) // Standard Error: 3_000 - .saturating_add((2_197_000 as Weight).saturating_mul(k as Weight)) + .saturating_add((2_190_000 as Weight).saturating_mul(k as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) } // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize_per_queue_item(q: u32, ) -> Weight { - (92_378_000 as Weight) + (101_551_000 as Weight) // Standard Error: 2_000 - .saturating_add((328_000 as Weight).saturating_mul(q as Weight)) + .saturating_add((292_000 as Weight).saturating_mul(q as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Contracts PristineCode (r:1 w:0) // Storage: Contracts CodeStorage (r:0 w:1) fn instrument(c: u32, ) -> Weight { - (27_381_000 as Weight) - // Standard Error: 92_000 - .saturating_add((90_220_000 as Weight).saturating_mul(c as Weight)) + (33_350_000 as Weight) + // Standard Error: 106_000 + .saturating_add((91_098_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Contracts CodeStorage (r:1 w:0) fn code_load(c: u32, ) -> Weight { - (7_710_000 as Weight) + (8_080_000 as Weight) // Standard Error: 0 - .saturating_add((1_457_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((1_455_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) } // Storage: Contracts CodeStorage (r:1 w:1) @@ -194,11 +194,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn instantiate_with_code(c: u32, s: u32, ) -> Weight { - (559_294_000 as Weight) - // Standard Error: 171_000 - .saturating_add((206_170_000 as Weight).saturating_mul(c as Weight)) - // Standard Error: 11_000 - .saturating_add((2_107_000 as Weight).saturating_mul(s as Weight)) + (464_920_000 as Weight) + // Standard Error: 136_000 + .saturating_add((211_340_000 as Weight).saturating_mul(c as Weight)) + // Standard Error: 8_000 + .saturating_add((2_190_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } @@ -209,9 +209,9 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn instantiate(s: u32, ) -> Weight { - (236_193_000 as Weight) + (236_192_000 as Weight) // Standard Error: 2_000 - .saturating_add((2_022_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((2_010_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } @@ -220,7 +220,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call() -> Weight { - (189_193_000 as Weight) + (172_780_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -228,9 +228,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn upload_code(c: u32, ) -> Weight { - (79_753_000 as Weight) + (80_415_000 as Weight) // Standard Error: 98_000 - .saturating_add((90_928_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((93_463_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -238,233 +238,235 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:0 w:1) // Storage: Contracts PristineCode (r:0 w:1) fn remove_code() -> Weight { - (40_206_000 as Weight) + (40_042_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_caller(r: u32, ) -> Weight { - (464_937_000 as Weight) - // Standard Error: 182_000 - .saturating_add((112_166_000 as Weight).saturating_mul(r as Weight)) + (416_770_000 as Weight) + // Standard Error: 175_000 + .saturating_add((114_550_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_address(r: u32, ) -> Weight { - (464_387_000 as Weight) - // Standard Error: 155_000 - .saturating_add((112_307_000 as Weight).saturating_mul(r as Weight)) + (415_774_000 as Weight) + // Standard Error: 176_000 + .saturating_add((115_169_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas_left(r: u32, ) -> Weight { - (462_005_000 as Weight) - // Standard Error: 185_000 - .saturating_add((111_402_000 as Weight).saturating_mul(r as Weight)) + (411_883_000 as Weight) + // Standard Error: 200_000 + .saturating_add((113_740_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_balance(r: u32, ) -> Weight { - (468_139_000 as Weight) - // Standard Error: 192_000 - .saturating_add((317_634_000 as Weight).saturating_mul(r as Weight)) + (422_382_000 as Weight) + // Standard Error: 189_000 + .saturating_add((313_581_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_value_transferred(r: u32, ) -> Weight { - (447_610_000 as Weight) - // Standard Error: 196_000 - .saturating_add((112_915_000 as Weight).saturating_mul(r as Weight)) + (437_411_000 as Weight) + // Standard Error: 191_000 + .saturating_add((111_580_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_minimum_balance(r: u32, ) -> Weight { - (450_012_000 as Weight) - // Standard Error: 167_000 - .saturating_add((112_311_000 as Weight).saturating_mul(r as Weight)) + (431_815_000 as Weight) + // Standard Error: 170_000 + .saturating_add((111_289_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_block_number(r: u32, ) -> Weight { - (453_687_000 as Weight) - // Standard Error: 185_000 - .saturating_add((111_902_000 as Weight).saturating_mul(r as Weight)) + (430_451_000 as Weight) + // Standard Error: 152_000 + .saturating_add((111_214_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_now(r: u32, ) -> Weight { - (453_283_000 as Weight) - // Standard Error: 162_000 - .saturating_add((112_543_000 as Weight).saturating_mul(r as Weight)) + (419_363_000 as Weight) + // Standard Error: 175_000 + .saturating_add((112_089_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0) fn seal_weight_to_fee(r: u32, ) -> Weight { - (454_171_000 as Weight) - // Standard Error: 205_000 - .saturating_add((267_487_000 as Weight).saturating_mul(r as Weight)) + (427_501_000 as Weight) + // Standard Error: 247_000 + .saturating_add((262_104_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas(r: u32, ) -> Weight { - (190_254_000 as Weight) - // Standard Error: 116_000 - .saturating_add((51_037_000 as Weight).saturating_mul(r as Weight)) + (145_426_000 as Weight) + // Standard Error: 115_000 + .saturating_add((52_082_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input(r: u32, ) -> Weight { - (460_590_000 as Weight) - // Standard Error: 173_000 - .saturating_add((99_887_000 as Weight).saturating_mul(r as Weight)) + (415_783_000 as Weight) + // Standard Error: 184_000 + .saturating_add((101_266_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input_per_kb(n: u32, ) -> Weight { - (616_346_000 as Weight) - // Standard Error: 9_000 - .saturating_add((38_016_000 as Weight).saturating_mul(n as Weight)) + (536_645_000 as Weight) + // Standard Error: 6_000 + .saturating_add((38_077_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) - fn seal_return(_r: u32, ) -> Weight { - (447_340_000 as Weight) + fn seal_return(r: u32, ) -> Weight { + (412_785_000 as Weight) + // Standard Error: 92_000 + .saturating_add((1_476_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return_per_kb(n: u32, ) -> Weight { - (452_105_000 as Weight) + (400_232_000 as Weight) // Standard Error: 1_000 - .saturating_add((633_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((644_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) // Storage: Contracts DeletionQueue (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_terminate(r: u32, ) -> Weight { - (456_662_000 as Weight) - // Standard Error: 2_550_000 - .saturating_add((71_297_000 as Weight).saturating_mul(r as Weight)) + (409_343_000 as Weight) + // Standard Error: 1_325_000 + .saturating_add((101_661_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((4 as Weight).saturating_mul(r as Weight))) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) - .saturating_add(T::DbWeight::get().writes((4 as Weight).saturating_mul(r as Weight))) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + .saturating_add(T::DbWeight::get().writes((5 as Weight).saturating_mul(r as Weight))) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) // Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) fn seal_random(r: u32, ) -> Weight { - (460_302_000 as Weight) - // Standard Error: 223_000 - .saturating_add((351_206_000 as Weight).saturating_mul(r as Weight)) + (417_354_000 as Weight) + // Standard Error: 299_000 + .saturating_add((343_766_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_deposit_event(r: u32, ) -> Weight { - (456_800_000 as Weight) - // Standard Error: 413_000 - .saturating_add((574_183_000 as Weight).saturating_mul(r as Weight)) + (412_092_000 as Weight) + // Standard Error: 403_000 + .saturating_add((568_199_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) // Storage: System EventTopics (r:100 w:100) fn seal_deposit_event_per_topic_and_kb(t: u32, n: u32, ) -> Weight { - (1_099_926_000 as Weight) - // Standard Error: 2_170_000 - .saturating_add((461_522_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 427_000 - .saturating_add((164_778_000 as Weight).saturating_mul(n as Weight)) + (1_095_614_000 as Weight) + // Standard Error: 2_151_000 + .saturating_add((455_690_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 424_000 + .saturating_add((163_553_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(t as Weight))) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) .saturating_add(T::DbWeight::get().writes((100 as Weight).saturating_mul(t as Weight))) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_debug_message(r: u32, ) -> Weight { - (208_518_000 as Weight) - // Standard Error: 131_000 - .saturating_add((70_862_000 as Weight).saturating_mul(r as Weight)) + (169_113_000 as Weight) + // Standard Error: 146_000 + .saturating_add((72_877_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage(r: u32, ) -> Weight { - (492_961_000 as Weight) - // Standard Error: 506_000 - .saturating_add((373_157_000 as Weight).saturating_mul(r as Weight)) + (484_647_000 as Weight) + // Standard Error: 479_000 + .saturating_add((369_854_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -476,17 +478,17 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: unknown [0x7afa01283080ef247df84e0ba38ea5a587d25ce6633a6bfbba02068c14023441] (r:1 w:1) fn seal_set_storage_per_kb(n: u32, ) -> Weight { - (793_894_000 as Weight) - // Standard Error: 250_000 - .saturating_add((74_081_000 as Weight).saturating_mul(n as Weight)) + (793_777_000 as Weight) + // Standard Error: 264_000 + .saturating_add((73_253_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage(r: u32, ) -> Weight { - (214_581_000 as Weight) - // Standard Error: 1_604_000 - .saturating_add((844_938_000 as Weight).saturating_mul(r as Weight)) + (180_385_000 as Weight) + // Standard Error: 1_470_000 + .saturating_add((834_911_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -494,64 +496,69 @@ impl WeightInfo for SubstrateWeight { } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage(r: u32, ) -> Weight { - (328_005_000 as Weight) - // Standard Error: 753_000 - .saturating_add((493_893_000 as Weight).saturating_mul(r as Weight)) + (282_452_000 as Weight) + // Standard Error: 802_000 + .saturating_add((492_119_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) // Storage: unknown [0x7afa01283080ef247df84e0ba38ea5a587d25ce6633a6bfbba02068c14023441] (r:1 w:0) fn seal_get_storage_per_kb(n: u32, ) -> Weight { - (736_348_000 as Weight) - // Standard Error: 232_000 - .saturating_add((110_871_000 as Weight).saturating_mul(n as Weight)) + (687_019_000 as Weight) + // Standard Error: 226_000 + .saturating_add((111_245_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_transfer(r: u32, ) -> Weight { - (346_206_000 as Weight) - // Standard Error: 1_888_000 - .saturating_add((3_729_835_000 as Weight).saturating_mul(r as Weight)) + (273_106_000 as Weight) + // Standard Error: 1_498_000 + .saturating_add((3_509_324_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) - .saturating_add(T::DbWeight::get().writes(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) .saturating_add(T::DbWeight::get().writes((100 as Weight).saturating_mul(r as Weight))) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_call(r: u32, ) -> Weight { - (0 as Weight) - // Standard Error: 11_456_000 - .saturating_add((39_404_197_000 as Weight).saturating_mul(r as Weight)) + (2_702_839_000 as Weight) + // Standard Error: 21_310_000 + .saturating_add((37_721_061_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) .saturating_add(T::DbWeight::get().writes((100 as Weight).saturating_mul(r as Weight))) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:101 w:101) // Storage: Contracts CodeStorage (r:2 w:0) // Storage: Timestamp Now (r:1 w:0) - fn seal_call_per_transfer_input_output_kb(t: u32, i: u32, _o: u32, ) -> Weight { - (136_101_024_000 as Weight) - // Standard Error: 6_000 - .saturating_add((62_954_000 as Weight).saturating_mul(i as Weight)) + fn seal_call_per_transfer_input_output_kb(t: u32, i: u32, o: u32, ) -> Weight { + (40_088_516_000 as Weight) + // Standard Error: 69_999_000 + .saturating_add((2_981_897_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 25_000 + .saturating_add((63_345_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 26_000 + .saturating_add((100_683_000 as Weight).saturating_mul(o as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) - .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(t as Weight))) - .saturating_add(T::DbWeight::get().writes(102 as Weight)) + .saturating_add(T::DbWeight::get().reads((101 as Weight).saturating_mul(t as Weight))) + .saturating_add(T::DbWeight::get().writes(101 as Weight)) + .saturating_add(T::DbWeight::get().writes((101 as Weight).saturating_mul(t as Weight))) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) @@ -559,11 +566,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts OwnerInfoOf (r:100 w:100) fn seal_instantiate(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 47_948_000 - .saturating_add((48_494_963_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 49_379_000 + .saturating_add((51_630_139_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().reads((400 as Weight).saturating_mul(r as Weight))) - .saturating_add(T::DbWeight::get().writes(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) .saturating_add(T::DbWeight::get().writes((400 as Weight).saturating_mul(r as Weight))) } // Storage: System Account (r:102 w:102) @@ -573,369 +580,369 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts AccountCounter (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_instantiate_per_input_output_salt_kb(i: u32, o: u32, s: u32, ) -> Weight { - (45_566_426_000 as Weight) - // Standard Error: 50_000 - .saturating_add((63_809_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 50_000 - .saturating_add((101_448_000 as Weight).saturating_mul(o as Weight)) - // Standard Error: 50_000 - .saturating_add((201_652_000 as Weight).saturating_mul(s as Weight)) + (47_691_523_000 as Weight) + // Standard Error: 36_000 + .saturating_add((63_693_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 36_000 + .saturating_add((101_775_000 as Weight).saturating_mul(o as Weight)) + // Standard Error: 36_000 + .saturating_add((200_727_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(208 as Weight)) .saturating_add(T::DbWeight::get().writes(206 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256(r: u32, ) -> Weight { - (457_229_000 as Weight) - // Standard Error: 197_000 - .saturating_add((124_742_000 as Weight).saturating_mul(r as Weight)) + (411_050_000 as Weight) + // Standard Error: 177_000 + .saturating_add((125_380_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256_per_kb(n: u32, ) -> Weight { - (586_056_000 as Weight) - // Standard Error: 30_000 - .saturating_add((505_871_000 as Weight).saturating_mul(n as Weight)) + (381_286_000 as Weight) + // Standard Error: 48_000 + .saturating_add((506_160_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256(r: u32, ) -> Weight { - (458_528_000 as Weight) - // Standard Error: 154_000 - .saturating_add((137_710_000 as Weight).saturating_mul(r as Weight)) + (415_554_000 as Weight) + // Standard Error: 186_000 + .saturating_add((138_154_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256_per_kb(n: u32, ) -> Weight { - (573_132_000 as Weight) - // Standard Error: 19_000 - .saturating_add((363_983_000 as Weight).saturating_mul(n as Weight)) + (509_653_000 as Weight) + // Standard Error: 20_000 + .saturating_add((364_008_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256(r: u32, ) -> Weight { - (456_881_000 as Weight) - // Standard Error: 187_000 - .saturating_add((106_987_000 as Weight).saturating_mul(r as Weight)) + (416_442_000 as Weight) + // Standard Error: 186_000 + .saturating_add((120_321_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256_per_kb(n: u32, ) -> Weight { - (587_192_000 as Weight) + (586_411_000 as Weight) // Standard Error: 17_000 - .saturating_add((164_114_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((164_095_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128(r: u32, ) -> Weight { - (457_938_000 as Weight) - // Standard Error: 184_000 - .saturating_add((105_658_000 as Weight).saturating_mul(r as Weight)) + (410_054_000 as Weight) + // Standard Error: 198_000 + .saturating_add((109_368_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128_per_kb(n: u32, ) -> Weight { - (567_129_000 as Weight) + (548_447_000 as Weight) // Standard Error: 16_000 - .saturating_add((164_146_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((164_100_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_ecdsa_recover(r: u32, ) -> Weight { - (426_602_000 as Weight) - // Standard Error: 1_393_000 - .saturating_add((15_587_531_000 as Weight).saturating_mul(r as Weight)) + (368_727_000 as Weight) + // Standard Error: 1_294_000 + .saturating_add((15_563_119_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn instr_i64const(r: u32, ) -> Weight { - (39_689_000 as Weight) - // Standard Error: 14_000 - .saturating_add((1_361_000 as Weight).saturating_mul(r as Weight)) + (47_482_000 as Weight) + // Standard Error: 11_000 + .saturating_add((811_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64load(r: u32, ) -> Weight { - (45_362_000 as Weight) - // Standard Error: 10_000 - .saturating_add((2_665_000 as Weight).saturating_mul(r as Weight)) + (55_014_000 as Weight) + // Standard Error: 13_000 + .saturating_add((2_502_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64store(r: u32, ) -> Weight { - (45_514_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_696_000 as Weight).saturating_mul(r as Weight)) + (54_708_000 as Weight) + // Standard Error: 13_000 + .saturating_add((2_547_000 as Weight).saturating_mul(r as Weight)) } fn instr_select(r: u32, ) -> Weight { - (45_931_000 as Weight) - // Standard Error: 12_000 - .saturating_add((2_919_000 as Weight).saturating_mul(r as Weight)) + (38_583_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_979_000 as Weight).saturating_mul(r as Weight)) } fn instr_if(r: u32, ) -> Weight { - (46_362_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_942_000 as Weight).saturating_mul(r as Weight)) + (37_647_000 as Weight) + // Standard Error: 16_000 + .saturating_add((3_107_000 as Weight).saturating_mul(r as Weight)) } fn instr_br(r: u32, ) -> Weight { - (44_648_000 as Weight) - // Standard Error: 15_000 - .saturating_add((1_856_000 as Weight).saturating_mul(r as Weight)) + (40_586_000 as Weight) + // Standard Error: 17_000 + .saturating_add((1_940_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_if(r: u32, ) -> Weight { - (45_989_000 as Weight) - // Standard Error: 10_000 - .saturating_add((2_418_000 as Weight).saturating_mul(r as Weight)) + (39_436_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_533_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table(r: u32, ) -> Weight { - (48_883_000 as Weight) - // Standard Error: 18_000 - .saturating_add((2_471_000 as Weight).saturating_mul(r as Weight)) + (45_741_000 as Weight) + // Standard Error: 21_000 + .saturating_add((2_450_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table_per_entry(e: u32, ) -> Weight { - (48_685_000 as Weight) - // Standard Error: 2_000 - .saturating_add((39_000 as Weight).saturating_mul(e as Weight)) + (48_440_000 as Weight) + // Standard Error: 3_000 + .saturating_add((29_000 as Weight).saturating_mul(e as Weight)) } fn instr_call(r: u32, ) -> Weight { - (50_428_000 as Weight) - // Standard Error: 24_000 - .saturating_add((20_121_000 as Weight).saturating_mul(r as Weight)) + (49_819_000 as Weight) + // Standard Error: 22_000 + .saturating_add((20_642_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect(r: u32, ) -> Weight { - (54_899_000 as Weight) - // Standard Error: 32_000 - .saturating_add((29_588_000 as Weight).saturating_mul(r as Weight)) + (54_317_000 as Weight) + // Standard Error: 29_000 + .saturating_add((30_663_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect_per_param(p: u32, ) -> Weight { - (92_176_000 as Weight) + (88_087_000 as Weight) // Standard Error: 5_000 - .saturating_add((989_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((1_106_000 as Weight).saturating_mul(p as Weight)) } fn instr_local_get(r: u32, ) -> Weight { - (48_130_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_194_000 as Weight).saturating_mul(r as Weight)) + (40_540_000 as Weight) + // Standard Error: 14_000 + .saturating_add((1_362_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_set(r: u32, ) -> Weight { - (47_550_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_244_000 as Weight).saturating_mul(r as Weight)) + (40_842_000 as Weight) + // Standard Error: 14_000 + .saturating_add((1_375_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_tee(r: u32, ) -> Weight { - (48_806_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_757_000 as Weight).saturating_mul(r as Weight)) + (43_679_000 as Weight) + // Standard Error: 13_000 + .saturating_add((1_882_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_get(r: u32, ) -> Weight { - (62_369_000 as Weight) - // Standard Error: 9_000 - .saturating_add((1_779_000 as Weight).saturating_mul(r as Weight)) + (52_999_000 as Weight) + // Standard Error: 14_000 + .saturating_add((1_970_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_set(r: u32, ) -> Weight { - (61_063_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_751_000 as Weight).saturating_mul(r as Weight)) + (58_630_000 as Weight) + // Standard Error: 12_000 + .saturating_add((1_776_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_current(r: u32, ) -> Weight { - (39_781_000 as Weight) - // Standard Error: 14_000 - .saturating_add((1_370_000 as Weight).saturating_mul(r as Weight)) + (47_810_000 as Weight) + // Standard Error: 11_000 + .saturating_add((817_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_grow(r: u32, ) -> Weight { - (50_983_000 as Weight) - // Standard Error: 4_238_000 - .saturating_add((618_956_000 as Weight).saturating_mul(r as Weight)) + (51_086_000 as Weight) + // Standard Error: 3_690_000 + .saturating_add((622_068_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64clz(r: u32, ) -> Weight { - (42_490_000 as Weight) - // Standard Error: 13_000 - .saturating_add((1_937_000 as Weight).saturating_mul(r as Weight)) + (44_599_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_498_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ctz(r: u32, ) -> Weight { - (42_296_000 as Weight) - // Standard Error: 13_000 - .saturating_add((1_943_000 as Weight).saturating_mul(r as Weight)) + (44_523_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_500_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64popcnt(r: u32, ) -> Weight { - (42_263_000 as Weight) - // Standard Error: 13_000 - .saturating_add((1_944_000 as Weight).saturating_mul(r as Weight)) + (44_633_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_501_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eqz(r: u32, ) -> Weight { - (42_087_000 as Weight) - // Standard Error: 13_000 - .saturating_add((1_952_000 as Weight).saturating_mul(r as Weight)) + (44_654_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_499_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendsi32(r: u32, ) -> Weight { - (48_024_000 as Weight) - // Standard Error: 9_000 - .saturating_add((1_783_000 as Weight).saturating_mul(r as Weight)) + (42_020_000 as Weight) + // Standard Error: 13_000 + .saturating_add((1_950_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendui32(r: u32, ) -> Weight { - (48_056_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_780_000 as Weight).saturating_mul(r as Weight)) + (42_077_000 as Weight) + // Standard Error: 13_000 + .saturating_add((1_943_000 as Weight).saturating_mul(r as Weight)) } fn instr_i32wrapi64(r: u32, ) -> Weight { - (42_352_000 as Weight) - // Standard Error: 13_000 - .saturating_add((1_928_000 as Weight).saturating_mul(r as Weight)) + (44_559_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_499_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eq(r: u32, ) -> Weight { - (45_439_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_382_000 as Weight).saturating_mul(r as Weight)) + (37_902_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_480_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ne(r: u32, ) -> Weight { - (45_232_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_393_000 as Weight).saturating_mul(r as Weight)) + (37_799_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_484_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64lts(r: u32, ) -> Weight { - (45_351_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_386_000 as Weight).saturating_mul(r as Weight)) + (37_492_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_507_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ltu(r: u32, ) -> Weight { - (45_448_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_385_000 as Weight).saturating_mul(r as Weight)) + (37_509_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_503_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gts(r: u32, ) -> Weight { - (45_275_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_386_000 as Weight).saturating_mul(r as Weight)) + (37_563_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_501_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gtu(r: u32, ) -> Weight { - (45_180_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_396_000 as Weight).saturating_mul(r as Weight)) + (37_584_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_496_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64les(r: u32, ) -> Weight { - (45_396_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_400_000 as Weight).saturating_mul(r as Weight)) + (37_738_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_490_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64leu(r: u32, ) -> Weight { - (45_597_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_392_000 as Weight).saturating_mul(r as Weight)) + (37_806_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_490_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ges(r: u32, ) -> Weight { - (45_137_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_400_000 as Weight).saturating_mul(r as Weight)) + (37_858_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_483_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64geu(r: u32, ) -> Weight { - (45_091_000 as Weight) - // Standard Error: 10_000 - .saturating_add((2_401_000 as Weight).saturating_mul(r as Weight)) + (37_862_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_483_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64add(r: u32, ) -> Weight { - (45_547_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_380_000 as Weight).saturating_mul(r as Weight)) + (37_695_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_491_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64sub(r: u32, ) -> Weight { - (45_435_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_383_000 as Weight).saturating_mul(r as Weight)) + (37_693_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_495_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64mul(r: u32, ) -> Weight { - (45_244_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_389_000 as Weight).saturating_mul(r as Weight)) + (37_623_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_499_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divs(r: u32, ) -> Weight { - (45_253_000 as Weight) - // Standard Error: 11_000 - .saturating_add((3_046_000 as Weight).saturating_mul(r as Weight)) + (37_595_000 as Weight) + // Standard Error: 16_000 + .saturating_add((3_150_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divu(r: u32, ) -> Weight { - (45_339_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_711_000 as Weight).saturating_mul(r as Weight)) + (37_661_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_797_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rems(r: u32, ) -> Weight { - (45_312_000 as Weight) - // Standard Error: 11_000 - .saturating_add((3_020_000 as Weight).saturating_mul(r as Weight)) + (37_978_000 as Weight) + // Standard Error: 16_000 + .saturating_add((3_107_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64remu(r: u32, ) -> Weight { - (45_397_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_739_000 as Weight).saturating_mul(r as Weight)) + (37_668_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_842_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64and(r: u32, ) -> Weight { - (45_282_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_387_000 as Weight).saturating_mul(r as Weight)) + (37_846_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_482_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64or(r: u32, ) -> Weight { - (45_508_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_390_000 as Weight).saturating_mul(r as Weight)) + (37_902_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_478_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64xor(r: u32, ) -> Weight { - (45_089_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_397_000 as Weight).saturating_mul(r as Weight)) + (37_670_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_489_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shl(r: u32, ) -> Weight { - (45_878_000 as Weight) - // Standard Error: 13_000 - .saturating_add((2_395_000 as Weight).saturating_mul(r as Weight)) + (37_987_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_479_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shrs(r: u32, ) -> Weight { - (45_459_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_401_000 as Weight).saturating_mul(r as Weight)) + (37_945_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_486_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shru(r: u32, ) -> Weight { - (45_663_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_398_000 as Weight).saturating_mul(r as Weight)) + (37_570_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_503_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotl(r: u32, ) -> Weight { - (45_739_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_393_000 as Weight).saturating_mul(r as Weight)) + (37_674_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_498_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotr(r: u32, ) -> Weight { - (45_290_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_392_000 as Weight).saturating_mul(r as Weight)) + (37_467_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_503_000 as Weight).saturating_mul(r as Weight)) } } @@ -943,40 +950,40 @@ impl WeightInfo for SubstrateWeight { impl WeightInfo for () { // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize() -> Weight { - (2_832_000 as Weight) + (2_854_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn on_initialize_per_trie_key(k: u32, ) -> Weight { (0 as Weight) // Standard Error: 3_000 - .saturating_add((2_197_000 as Weight).saturating_mul(k as Weight)) + .saturating_add((2_190_000 as Weight).saturating_mul(k as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) } // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize_per_queue_item(q: u32, ) -> Weight { - (92_378_000 as Weight) + (101_551_000 as Weight) // Standard Error: 2_000 - .saturating_add((328_000 as Weight).saturating_mul(q as Weight)) + .saturating_add((292_000 as Weight).saturating_mul(q as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Contracts PristineCode (r:1 w:0) // Storage: Contracts CodeStorage (r:0 w:1) fn instrument(c: u32, ) -> Weight { - (27_381_000 as Weight) - // Standard Error: 92_000 - .saturating_add((90_220_000 as Weight).saturating_mul(c as Weight)) + (33_350_000 as Weight) + // Standard Error: 106_000 + .saturating_add((91_098_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Contracts CodeStorage (r:1 w:0) fn code_load(c: u32, ) -> Weight { - (7_710_000 as Weight) + (8_080_000 as Weight) // Standard Error: 0 - .saturating_add((1_457_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((1_455_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) } // Storage: Contracts CodeStorage (r:1 w:1) @@ -987,11 +994,11 @@ impl WeightInfo for () { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn instantiate_with_code(c: u32, s: u32, ) -> Weight { - (559_294_000 as Weight) - // Standard Error: 171_000 - .saturating_add((206_170_000 as Weight).saturating_mul(c as Weight)) - // Standard Error: 11_000 - .saturating_add((2_107_000 as Weight).saturating_mul(s as Weight)) + (464_920_000 as Weight) + // Standard Error: 136_000 + .saturating_add((211_340_000 as Weight).saturating_mul(c as Weight)) + // Standard Error: 8_000 + .saturating_add((2_190_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } @@ -1002,9 +1009,9 @@ impl WeightInfo for () { // Storage: System Account (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn instantiate(s: u32, ) -> Weight { - (236_193_000 as Weight) + (236_192_000 as Weight) // Standard Error: 2_000 - .saturating_add((2_022_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((2_010_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } @@ -1013,7 +1020,7 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call() -> Weight { - (189_193_000 as Weight) + (172_780_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -1021,9 +1028,9 @@ impl WeightInfo for () { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn upload_code(c: u32, ) -> Weight { - (79_753_000 as Weight) + (80_415_000 as Weight) // Standard Error: 98_000 - .saturating_add((90_928_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((93_463_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -1031,233 +1038,235 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:0 w:1) // Storage: Contracts PristineCode (r:0 w:1) fn remove_code() -> Weight { - (40_206_000 as Weight) + (40_042_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_caller(r: u32, ) -> Weight { - (464_937_000 as Weight) - // Standard Error: 182_000 - .saturating_add((112_166_000 as Weight).saturating_mul(r as Weight)) + (416_770_000 as Weight) + // Standard Error: 175_000 + .saturating_add((114_550_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_address(r: u32, ) -> Weight { - (464_387_000 as Weight) - // Standard Error: 155_000 - .saturating_add((112_307_000 as Weight).saturating_mul(r as Weight)) + (415_774_000 as Weight) + // Standard Error: 176_000 + .saturating_add((115_169_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas_left(r: u32, ) -> Weight { - (462_005_000 as Weight) - // Standard Error: 185_000 - .saturating_add((111_402_000 as Weight).saturating_mul(r as Weight)) + (411_883_000 as Weight) + // Standard Error: 200_000 + .saturating_add((113_740_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_balance(r: u32, ) -> Weight { - (468_139_000 as Weight) - // Standard Error: 192_000 - .saturating_add((317_634_000 as Weight).saturating_mul(r as Weight)) + (422_382_000 as Weight) + // Standard Error: 189_000 + .saturating_add((313_581_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_value_transferred(r: u32, ) -> Weight { - (447_610_000 as Weight) - // Standard Error: 196_000 - .saturating_add((112_915_000 as Weight).saturating_mul(r as Weight)) + (437_411_000 as Weight) + // Standard Error: 191_000 + .saturating_add((111_580_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_minimum_balance(r: u32, ) -> Weight { - (450_012_000 as Weight) - // Standard Error: 167_000 - .saturating_add((112_311_000 as Weight).saturating_mul(r as Weight)) + (431_815_000 as Weight) + // Standard Error: 170_000 + .saturating_add((111_289_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_block_number(r: u32, ) -> Weight { - (453_687_000 as Weight) - // Standard Error: 185_000 - .saturating_add((111_902_000 as Weight).saturating_mul(r as Weight)) + (430_451_000 as Weight) + // Standard Error: 152_000 + .saturating_add((111_214_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_now(r: u32, ) -> Weight { - (453_283_000 as Weight) - // Standard Error: 162_000 - .saturating_add((112_543_000 as Weight).saturating_mul(r as Weight)) + (419_363_000 as Weight) + // Standard Error: 175_000 + .saturating_add((112_089_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0) fn seal_weight_to_fee(r: u32, ) -> Weight { - (454_171_000 as Weight) - // Standard Error: 205_000 - .saturating_add((267_487_000 as Weight).saturating_mul(r as Weight)) + (427_501_000 as Weight) + // Standard Error: 247_000 + .saturating_add((262_104_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas(r: u32, ) -> Weight { - (190_254_000 as Weight) - // Standard Error: 116_000 - .saturating_add((51_037_000 as Weight).saturating_mul(r as Weight)) + (145_426_000 as Weight) + // Standard Error: 115_000 + .saturating_add((52_082_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input(r: u32, ) -> Weight { - (460_590_000 as Weight) - // Standard Error: 173_000 - .saturating_add((99_887_000 as Weight).saturating_mul(r as Weight)) + (415_783_000 as Weight) + // Standard Error: 184_000 + .saturating_add((101_266_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input_per_kb(n: u32, ) -> Weight { - (616_346_000 as Weight) - // Standard Error: 9_000 - .saturating_add((38_016_000 as Weight).saturating_mul(n as Weight)) + (536_645_000 as Weight) + // Standard Error: 6_000 + .saturating_add((38_077_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) - fn seal_return(_r: u32, ) -> Weight { - (447_340_000 as Weight) + fn seal_return(r: u32, ) -> Weight { + (412_785_000 as Weight) + // Standard Error: 92_000 + .saturating_add((1_476_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return_per_kb(n: u32, ) -> Weight { - (452_105_000 as Weight) + (400_232_000 as Weight) // Standard Error: 1_000 - .saturating_add((633_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((644_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) // Storage: Contracts DeletionQueue (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_terminate(r: u32, ) -> Weight { - (456_662_000 as Weight) - // Standard Error: 2_550_000 - .saturating_add((71_297_000 as Weight).saturating_mul(r as Weight)) + (409_343_000 as Weight) + // Standard Error: 1_325_000 + .saturating_add((101_661_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((4 as Weight).saturating_mul(r as Weight))) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) - .saturating_add(RocksDbWeight::get().writes((4 as Weight).saturating_mul(r as Weight))) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes((5 as Weight).saturating_mul(r as Weight))) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) // Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) fn seal_random(r: u32, ) -> Weight { - (460_302_000 as Weight) - // Standard Error: 223_000 - .saturating_add((351_206_000 as Weight).saturating_mul(r as Weight)) + (417_354_000 as Weight) + // Standard Error: 299_000 + .saturating_add((343_766_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_deposit_event(r: u32, ) -> Weight { - (456_800_000 as Weight) - // Standard Error: 413_000 - .saturating_add((574_183_000 as Weight).saturating_mul(r as Weight)) + (412_092_000 as Weight) + // Standard Error: 403_000 + .saturating_add((568_199_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) // Storage: System EventTopics (r:100 w:100) fn seal_deposit_event_per_topic_and_kb(t: u32, n: u32, ) -> Weight { - (1_099_926_000 as Weight) - // Standard Error: 2_170_000 - .saturating_add((461_522_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 427_000 - .saturating_add((164_778_000 as Weight).saturating_mul(n as Weight)) + (1_095_614_000 as Weight) + // Standard Error: 2_151_000 + .saturating_add((455_690_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 424_000 + .saturating_add((163_553_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(t as Weight))) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) .saturating_add(RocksDbWeight::get().writes((100 as Weight).saturating_mul(t as Weight))) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_debug_message(r: u32, ) -> Weight { - (208_518_000 as Weight) - // Standard Error: 131_000 - .saturating_add((70_862_000 as Weight).saturating_mul(r as Weight)) + (169_113_000 as Weight) + // Standard Error: 146_000 + .saturating_add((72_877_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage(r: u32, ) -> Weight { - (492_961_000 as Weight) - // Standard Error: 506_000 - .saturating_add((373_157_000 as Weight).saturating_mul(r as Weight)) + (484_647_000 as Weight) + // Standard Error: 479_000 + .saturating_add((369_854_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -1269,17 +1278,17 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: unknown [0x7afa01283080ef247df84e0ba38ea5a587d25ce6633a6bfbba02068c14023441] (r:1 w:1) fn seal_set_storage_per_kb(n: u32, ) -> Weight { - (793_894_000 as Weight) - // Standard Error: 250_000 - .saturating_add((74_081_000 as Weight).saturating_mul(n as Weight)) + (793_777_000 as Weight) + // Standard Error: 264_000 + .saturating_add((73_253_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage(r: u32, ) -> Weight { - (214_581_000 as Weight) - // Standard Error: 1_604_000 - .saturating_add((844_938_000 as Weight).saturating_mul(r as Weight)) + (180_385_000 as Weight) + // Standard Error: 1_470_000 + .saturating_add((834_911_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -1287,64 +1296,69 @@ impl WeightInfo for () { } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage(r: u32, ) -> Weight { - (328_005_000 as Weight) - // Standard Error: 753_000 - .saturating_add((493_893_000 as Weight).saturating_mul(r as Weight)) + (282_452_000 as Weight) + // Standard Error: 802_000 + .saturating_add((492_119_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) // Storage: unknown [0x7afa01283080ef247df84e0ba38ea5a587d25ce6633a6bfbba02068c14023441] (r:1 w:0) fn seal_get_storage_per_kb(n: u32, ) -> Weight { - (736_348_000 as Weight) - // Standard Error: 232_000 - .saturating_add((110_871_000 as Weight).saturating_mul(n as Weight)) + (687_019_000 as Weight) + // Standard Error: 226_000 + .saturating_add((111_245_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_transfer(r: u32, ) -> Weight { - (346_206_000 as Weight) - // Standard Error: 1_888_000 - .saturating_add((3_729_835_000 as Weight).saturating_mul(r as Weight)) + (273_106_000 as Weight) + // Standard Error: 1_498_000 + .saturating_add((3_509_324_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) - .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) .saturating_add(RocksDbWeight::get().writes((100 as Weight).saturating_mul(r as Weight))) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_call(r: u32, ) -> Weight { - (0 as Weight) - // Standard Error: 11_456_000 - .saturating_add((39_404_197_000 as Weight).saturating_mul(r as Weight)) + (2_702_839_000 as Weight) + // Standard Error: 21_310_000 + .saturating_add((37_721_061_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) .saturating_add(RocksDbWeight::get().writes((100 as Weight).saturating_mul(r as Weight))) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:101 w:101) // Storage: Contracts CodeStorage (r:2 w:0) // Storage: Timestamp Now (r:1 w:0) - fn seal_call_per_transfer_input_output_kb(t: u32, i: u32, _o: u32, ) -> Weight { - (136_101_024_000 as Weight) - // Standard Error: 6_000 - .saturating_add((62_954_000 as Weight).saturating_mul(i as Weight)) + fn seal_call_per_transfer_input_output_kb(t: u32, i: u32, o: u32, ) -> Weight { + (40_088_516_000 as Weight) + // Standard Error: 69_999_000 + .saturating_add((2_981_897_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 25_000 + .saturating_add((63_345_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 26_000 + .saturating_add((100_683_000 as Weight).saturating_mul(o as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) - .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(t as Weight))) - .saturating_add(RocksDbWeight::get().writes(102 as Weight)) + .saturating_add(RocksDbWeight::get().reads((101 as Weight).saturating_mul(t as Weight))) + .saturating_add(RocksDbWeight::get().writes(101 as Weight)) + .saturating_add(RocksDbWeight::get().writes((101 as Weight).saturating_mul(t as Weight))) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) @@ -1352,11 +1366,11 @@ impl WeightInfo for () { // Storage: Contracts OwnerInfoOf (r:100 w:100) fn seal_instantiate(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 47_948_000 - .saturating_add((48_494_963_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 49_379_000 + .saturating_add((51_630_139_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().reads((400 as Weight).saturating_mul(r as Weight))) - .saturating_add(RocksDbWeight::get().writes(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) .saturating_add(RocksDbWeight::get().writes((400 as Weight).saturating_mul(r as Weight))) } // Storage: System Account (r:102 w:102) @@ -1366,368 +1380,368 @@ impl WeightInfo for () { // Storage: Contracts AccountCounter (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_instantiate_per_input_output_salt_kb(i: u32, o: u32, s: u32, ) -> Weight { - (45_566_426_000 as Weight) - // Standard Error: 50_000 - .saturating_add((63_809_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 50_000 - .saturating_add((101_448_000 as Weight).saturating_mul(o as Weight)) - // Standard Error: 50_000 - .saturating_add((201_652_000 as Weight).saturating_mul(s as Weight)) + (47_691_523_000 as Weight) + // Standard Error: 36_000 + .saturating_add((63_693_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 36_000 + .saturating_add((101_775_000 as Weight).saturating_mul(o as Weight)) + // Standard Error: 36_000 + .saturating_add((200_727_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(208 as Weight)) .saturating_add(RocksDbWeight::get().writes(206 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256(r: u32, ) -> Weight { - (457_229_000 as Weight) - // Standard Error: 197_000 - .saturating_add((124_742_000 as Weight).saturating_mul(r as Weight)) + (411_050_000 as Weight) + // Standard Error: 177_000 + .saturating_add((125_380_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256_per_kb(n: u32, ) -> Weight { - (586_056_000 as Weight) - // Standard Error: 30_000 - .saturating_add((505_871_000 as Weight).saturating_mul(n as Weight)) + (381_286_000 as Weight) + // Standard Error: 48_000 + .saturating_add((506_160_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256(r: u32, ) -> Weight { - (458_528_000 as Weight) - // Standard Error: 154_000 - .saturating_add((137_710_000 as Weight).saturating_mul(r as Weight)) + (415_554_000 as Weight) + // Standard Error: 186_000 + .saturating_add((138_154_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256_per_kb(n: u32, ) -> Weight { - (573_132_000 as Weight) - // Standard Error: 19_000 - .saturating_add((363_983_000 as Weight).saturating_mul(n as Weight)) + (509_653_000 as Weight) + // Standard Error: 20_000 + .saturating_add((364_008_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256(r: u32, ) -> Weight { - (456_881_000 as Weight) - // Standard Error: 187_000 - .saturating_add((106_987_000 as Weight).saturating_mul(r as Weight)) + (416_442_000 as Weight) + // Standard Error: 186_000 + .saturating_add((120_321_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256_per_kb(n: u32, ) -> Weight { - (587_192_000 as Weight) + (586_411_000 as Weight) // Standard Error: 17_000 - .saturating_add((164_114_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((164_095_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128(r: u32, ) -> Weight { - (457_938_000 as Weight) - // Standard Error: 184_000 - .saturating_add((105_658_000 as Weight).saturating_mul(r as Weight)) + (410_054_000 as Weight) + // Standard Error: 198_000 + .saturating_add((109_368_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128_per_kb(n: u32, ) -> Weight { - (567_129_000 as Weight) + (548_447_000 as Weight) // Standard Error: 16_000 - .saturating_add((164_146_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((164_100_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:1) + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_ecdsa_recover(r: u32, ) -> Weight { - (426_602_000 as Weight) - // Standard Error: 1_393_000 - .saturating_add((15_587_531_000 as Weight).saturating_mul(r as Weight)) + (368_727_000 as Weight) + // Standard Error: 1_294_000 + .saturating_add((15_563_119_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn instr_i64const(r: u32, ) -> Weight { - (39_689_000 as Weight) - // Standard Error: 14_000 - .saturating_add((1_361_000 as Weight).saturating_mul(r as Weight)) + (47_482_000 as Weight) + // Standard Error: 11_000 + .saturating_add((811_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64load(r: u32, ) -> Weight { - (45_362_000 as Weight) - // Standard Error: 10_000 - .saturating_add((2_665_000 as Weight).saturating_mul(r as Weight)) + (55_014_000 as Weight) + // Standard Error: 13_000 + .saturating_add((2_502_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64store(r: u32, ) -> Weight { - (45_514_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_696_000 as Weight).saturating_mul(r as Weight)) + (54_708_000 as Weight) + // Standard Error: 13_000 + .saturating_add((2_547_000 as Weight).saturating_mul(r as Weight)) } fn instr_select(r: u32, ) -> Weight { - (45_931_000 as Weight) - // Standard Error: 12_000 - .saturating_add((2_919_000 as Weight).saturating_mul(r as Weight)) + (38_583_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_979_000 as Weight).saturating_mul(r as Weight)) } fn instr_if(r: u32, ) -> Weight { - (46_362_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_942_000 as Weight).saturating_mul(r as Weight)) + (37_647_000 as Weight) + // Standard Error: 16_000 + .saturating_add((3_107_000 as Weight).saturating_mul(r as Weight)) } fn instr_br(r: u32, ) -> Weight { - (44_648_000 as Weight) - // Standard Error: 15_000 - .saturating_add((1_856_000 as Weight).saturating_mul(r as Weight)) + (40_586_000 as Weight) + // Standard Error: 17_000 + .saturating_add((1_940_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_if(r: u32, ) -> Weight { - (45_989_000 as Weight) - // Standard Error: 10_000 - .saturating_add((2_418_000 as Weight).saturating_mul(r as Weight)) + (39_436_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_533_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table(r: u32, ) -> Weight { - (48_883_000 as Weight) - // Standard Error: 18_000 - .saturating_add((2_471_000 as Weight).saturating_mul(r as Weight)) + (45_741_000 as Weight) + // Standard Error: 21_000 + .saturating_add((2_450_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table_per_entry(e: u32, ) -> Weight { - (48_685_000 as Weight) - // Standard Error: 2_000 - .saturating_add((39_000 as Weight).saturating_mul(e as Weight)) + (48_440_000 as Weight) + // Standard Error: 3_000 + .saturating_add((29_000 as Weight).saturating_mul(e as Weight)) } fn instr_call(r: u32, ) -> Weight { - (50_428_000 as Weight) - // Standard Error: 24_000 - .saturating_add((20_121_000 as Weight).saturating_mul(r as Weight)) + (49_819_000 as Weight) + // Standard Error: 22_000 + .saturating_add((20_642_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect(r: u32, ) -> Weight { - (54_899_000 as Weight) - // Standard Error: 32_000 - .saturating_add((29_588_000 as Weight).saturating_mul(r as Weight)) + (54_317_000 as Weight) + // Standard Error: 29_000 + .saturating_add((30_663_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect_per_param(p: u32, ) -> Weight { - (92_176_000 as Weight) + (88_087_000 as Weight) // Standard Error: 5_000 - .saturating_add((989_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((1_106_000 as Weight).saturating_mul(p as Weight)) } fn instr_local_get(r: u32, ) -> Weight { - (48_130_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_194_000 as Weight).saturating_mul(r as Weight)) + (40_540_000 as Weight) + // Standard Error: 14_000 + .saturating_add((1_362_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_set(r: u32, ) -> Weight { - (47_550_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_244_000 as Weight).saturating_mul(r as Weight)) + (40_842_000 as Weight) + // Standard Error: 14_000 + .saturating_add((1_375_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_tee(r: u32, ) -> Weight { - (48_806_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_757_000 as Weight).saturating_mul(r as Weight)) + (43_679_000 as Weight) + // Standard Error: 13_000 + .saturating_add((1_882_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_get(r: u32, ) -> Weight { - (62_369_000 as Weight) - // Standard Error: 9_000 - .saturating_add((1_779_000 as Weight).saturating_mul(r as Weight)) + (52_999_000 as Weight) + // Standard Error: 14_000 + .saturating_add((1_970_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_set(r: u32, ) -> Weight { - (61_063_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_751_000 as Weight).saturating_mul(r as Weight)) + (58_630_000 as Weight) + // Standard Error: 12_000 + .saturating_add((1_776_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_current(r: u32, ) -> Weight { - (39_781_000 as Weight) - // Standard Error: 14_000 - .saturating_add((1_370_000 as Weight).saturating_mul(r as Weight)) + (47_810_000 as Weight) + // Standard Error: 11_000 + .saturating_add((817_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_grow(r: u32, ) -> Weight { - (50_983_000 as Weight) - // Standard Error: 4_238_000 - .saturating_add((618_956_000 as Weight).saturating_mul(r as Weight)) + (51_086_000 as Weight) + // Standard Error: 3_690_000 + .saturating_add((622_068_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64clz(r: u32, ) -> Weight { - (42_490_000 as Weight) - // Standard Error: 13_000 - .saturating_add((1_937_000 as Weight).saturating_mul(r as Weight)) + (44_599_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_498_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ctz(r: u32, ) -> Weight { - (42_296_000 as Weight) - // Standard Error: 13_000 - .saturating_add((1_943_000 as Weight).saturating_mul(r as Weight)) + (44_523_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_500_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64popcnt(r: u32, ) -> Weight { - (42_263_000 as Weight) - // Standard Error: 13_000 - .saturating_add((1_944_000 as Weight).saturating_mul(r as Weight)) + (44_633_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_501_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eqz(r: u32, ) -> Weight { - (42_087_000 as Weight) - // Standard Error: 13_000 - .saturating_add((1_952_000 as Weight).saturating_mul(r as Weight)) + (44_654_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_499_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendsi32(r: u32, ) -> Weight { - (48_024_000 as Weight) - // Standard Error: 9_000 - .saturating_add((1_783_000 as Weight).saturating_mul(r as Weight)) + (42_020_000 as Weight) + // Standard Error: 13_000 + .saturating_add((1_950_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendui32(r: u32, ) -> Weight { - (48_056_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_780_000 as Weight).saturating_mul(r as Weight)) + (42_077_000 as Weight) + // Standard Error: 13_000 + .saturating_add((1_943_000 as Weight).saturating_mul(r as Weight)) } fn instr_i32wrapi64(r: u32, ) -> Weight { - (42_352_000 as Weight) - // Standard Error: 13_000 - .saturating_add((1_928_000 as Weight).saturating_mul(r as Weight)) + (44_559_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_499_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eq(r: u32, ) -> Weight { - (45_439_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_382_000 as Weight).saturating_mul(r as Weight)) + (37_902_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_480_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ne(r: u32, ) -> Weight { - (45_232_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_393_000 as Weight).saturating_mul(r as Weight)) + (37_799_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_484_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64lts(r: u32, ) -> Weight { - (45_351_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_386_000 as Weight).saturating_mul(r as Weight)) + (37_492_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_507_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ltu(r: u32, ) -> Weight { - (45_448_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_385_000 as Weight).saturating_mul(r as Weight)) + (37_509_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_503_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gts(r: u32, ) -> Weight { - (45_275_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_386_000 as Weight).saturating_mul(r as Weight)) + (37_563_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_501_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gtu(r: u32, ) -> Weight { - (45_180_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_396_000 as Weight).saturating_mul(r as Weight)) + (37_584_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_496_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64les(r: u32, ) -> Weight { - (45_396_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_400_000 as Weight).saturating_mul(r as Weight)) + (37_738_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_490_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64leu(r: u32, ) -> Weight { - (45_597_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_392_000 as Weight).saturating_mul(r as Weight)) + (37_806_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_490_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ges(r: u32, ) -> Weight { - (45_137_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_400_000 as Weight).saturating_mul(r as Weight)) + (37_858_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_483_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64geu(r: u32, ) -> Weight { - (45_091_000 as Weight) - // Standard Error: 10_000 - .saturating_add((2_401_000 as Weight).saturating_mul(r as Weight)) + (37_862_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_483_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64add(r: u32, ) -> Weight { - (45_547_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_380_000 as Weight).saturating_mul(r as Weight)) + (37_695_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_491_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64sub(r: u32, ) -> Weight { - (45_435_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_383_000 as Weight).saturating_mul(r as Weight)) + (37_693_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_495_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64mul(r: u32, ) -> Weight { - (45_244_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_389_000 as Weight).saturating_mul(r as Weight)) + (37_623_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_499_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divs(r: u32, ) -> Weight { - (45_253_000 as Weight) - // Standard Error: 11_000 - .saturating_add((3_046_000 as Weight).saturating_mul(r as Weight)) + (37_595_000 as Weight) + // Standard Error: 16_000 + .saturating_add((3_150_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divu(r: u32, ) -> Weight { - (45_339_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_711_000 as Weight).saturating_mul(r as Weight)) + (37_661_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_797_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rems(r: u32, ) -> Weight { - (45_312_000 as Weight) - // Standard Error: 11_000 - .saturating_add((3_020_000 as Weight).saturating_mul(r as Weight)) + (37_978_000 as Weight) + // Standard Error: 16_000 + .saturating_add((3_107_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64remu(r: u32, ) -> Weight { - (45_397_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_739_000 as Weight).saturating_mul(r as Weight)) + (37_668_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_842_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64and(r: u32, ) -> Weight { - (45_282_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_387_000 as Weight).saturating_mul(r as Weight)) + (37_846_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_482_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64or(r: u32, ) -> Weight { - (45_508_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_390_000 as Weight).saturating_mul(r as Weight)) + (37_902_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_478_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64xor(r: u32, ) -> Weight { - (45_089_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_397_000 as Weight).saturating_mul(r as Weight)) + (37_670_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_489_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shl(r: u32, ) -> Weight { - (45_878_000 as Weight) - // Standard Error: 13_000 - .saturating_add((2_395_000 as Weight).saturating_mul(r as Weight)) + (37_987_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_479_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shrs(r: u32, ) -> Weight { - (45_459_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_401_000 as Weight).saturating_mul(r as Weight)) + (37_945_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_486_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shru(r: u32, ) -> Weight { - (45_663_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_398_000 as Weight).saturating_mul(r as Weight)) + (37_570_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_503_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotl(r: u32, ) -> Weight { - (45_739_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_393_000 as Weight).saturating_mul(r as Weight)) + (37_674_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_498_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotr(r: u32, ) -> Weight { - (45_290_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_392_000 as Weight).saturating_mul(r as Weight)) + (37_467_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_503_000 as Weight).saturating_mul(r as Weight)) } } From 1a30fa202e00dfeac07cb648e1f557ce938d5f1a Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Thu, 9 Dec 2021 11:21:27 +0100 Subject: [PATCH 272/695] Remove Prometheus metrics prefix (#9543) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Remove Prometheus metrics prefix * Fix line widths * Missed some metrics * Fix CLI * Run rustfmt on modified files * Missing prefixes * Hopefully fix compilation * Rustfmt protocol.rs * Should compile now I guess * Rustfmt Co-authored-by: Bastian Köcher --- client/api/src/notifications.rs | 2 +- client/authority-discovery/src/worker.rs | 14 ++--- client/beefy/src/metrics.rs | 18 ++++-- client/cli/src/commands/run_cmd.rs | 11 ++-- client/consensus/common/src/metrics.rs | 14 +++-- .../src/communication/gossip.rs | 2 +- client/finality-grandpa/src/environment.rs | 6 +- client/finality-grandpa/src/until_imported.rs | 2 +- client/network-gossip/src/state_machine.rs | 4 +- client/network/src/protocol.rs | 9 +-- client/network/src/service/metrics.rs | 63 ++++++++++--------- client/network/src/service/out_events.rs | 6 +- client/network/src/transactions.rs | 2 +- client/proposer-metrics/src/lib.rs | 4 +- client/rpc-servers/src/lib.rs | 4 +- client/rpc-servers/src/middleware.rs | 10 +-- client/service/src/config.rs | 7 ++- client/service/src/metrics.rs | 23 ++++--- client/service/src/task_manager/mod.rs | 8 +-- client/transaction-pool/src/metrics.rs | 12 ++-- client/utils/src/metrics.rs | 6 +- 21 files changed, 125 insertions(+), 102 deletions(-) diff --git a/client/api/src/notifications.rs b/client/api/src/notifications.rs index 1346afd5e54d..9565fd673acf 100644 --- a/client/api/src/notifications.rs +++ b/client/api/src/notifications.rs @@ -121,7 +121,7 @@ impl StorageNotifications { let metrics = prometheus_registry.and_then(|r| { CounterVec::new( Opts::new( - "storage_notification_subscribers", + "substrate_storage_notification_subscribers", "Number of subscribers in storage notification sytem", ), &["action"], // added | removed diff --git a/client/authority-discovery/src/worker.rs b/client/authority-discovery/src/worker.rs index ce04e0eb65b1..5ca93b73c813 100644 --- a/client/authority-discovery/src/worker.rs +++ b/client/authority-discovery/src/worker.rs @@ -733,14 +733,14 @@ impl Metrics { Ok(Self { publish: register( Counter::new( - "authority_discovery_times_published_total", + "substrate_authority_discovery_times_published_total", "Number of times authority discovery has published external addresses.", )?, registry, )?, amount_addresses_last_published: register( Gauge::new( - "authority_discovery_amount_external_addresses_last_published", + "substrate_authority_discovery_amount_external_addresses_last_published", "Number of external addresses published when authority discovery last \ published addresses.", )?, @@ -748,7 +748,7 @@ impl Metrics { )?, requests: register( Counter::new( - "authority_discovery_authority_addresses_requested_total", + "substrate_authority_discovery_authority_addresses_requested_total", "Number of times authority discovery has requested external addresses of a \ single authority.", )?, @@ -756,7 +756,7 @@ impl Metrics { )?, requests_pending: register( Gauge::new( - "authority_discovery_authority_address_requests_pending", + "substrate_authority_discovery_authority_address_requests_pending", "Number of pending authority address requests.", )?, registry, @@ -764,7 +764,7 @@ impl Metrics { dht_event_received: register( CounterVec::new( Opts::new( - "authority_discovery_dht_event_received", + "substrate_authority_discovery_dht_event_received", "Number of dht events received by authority discovery.", ), &["name"], @@ -773,14 +773,14 @@ impl Metrics { )?, handle_value_found_event_failure: register( Counter::new( - "authority_discovery_handle_value_found_event_failure", + "substrate_authority_discovery_handle_value_found_event_failure", "Number of times handling a dht value found event failed.", )?, registry, )?, known_authorities_count: register( Gauge::new( - "authority_discovery_known_authorities_count", + "substrate_authority_discovery_known_authorities_count", "Number of authorities known by authority discovery.", )?, registry, diff --git a/client/beefy/src/metrics.rs b/client/beefy/src/metrics.rs index 0fdc29f97c37..55edee962a2e 100644 --- a/client/beefy/src/metrics.rs +++ b/client/beefy/src/metrics.rs @@ -40,28 +40,34 @@ impl Metrics { pub(crate) fn register(registry: &Registry) -> Result { Ok(Self { beefy_validator_set_id: register( - Gauge::new("beefy_validator_set_id", "Current BEEFY active validator set id.")?, + Gauge::new( + "substrate_beefy_validator_set_id", + "Current BEEFY active validator set id.", + )?, registry, )?, beefy_votes_sent: register( - Counter::new("beefy_votes_sent", "Number of votes sent by this node")?, + Counter::new("substrate_beefy_votes_sent", "Number of votes sent by this node")?, registry, )?, beefy_round_concluded: register( - Gauge::new("beefy_round_concluded", "Voting round, that has been concluded")?, + Gauge::new( + "substrate_beefy_round_concluded", + "Voting round, that has been concluded", + )?, registry, )?, beefy_best_block: register( - Gauge::new("beefy_best_block", "Best block finalized by BEEFY")?, + Gauge::new("substrate_beefy_best_block", "Best block finalized by BEEFY")?, registry, )?, beefy_should_vote_on: register( - Gauge::new("beefy_should_vote_on", "Next block, BEEFY should vote on")?, + Gauge::new("substrate_beefy_should_vote_on", "Next block, BEEFY should vote on")?, registry, )?, beefy_skipped_sessions: register( Counter::new( - "beefy_skipped_sessions", + "substrate_beefy_skipped_sessions", "Number of sessions without a signed commitment", )?, registry, diff --git a/client/cli/src/commands/run_cmd.rs b/client/cli/src/commands/run_cmd.rs index ad2f04583c10..622206fdf297 100644 --- a/client/cli/src/commands/run_cmd.rs +++ b/client/cli/src/commands/run_cmd.rs @@ -368,10 +368,13 @@ impl CliConfiguration for RunCmd { let interface = if self.prometheus_external { Ipv4Addr::UNSPECIFIED } else { Ipv4Addr::LOCALHOST }; - Some(PrometheusConfig::new_with_default_registry(SocketAddr::new( - interface.into(), - self.prometheus_port.unwrap_or(default_listen_port), - ))) + Some(PrometheusConfig::new_with_default_registry( + SocketAddr::new( + interface.into(), + self.prometheus_port.unwrap_or(default_listen_port), + ), + self.shared_params.chain_id(self.shared_params.dev), + )) }) } diff --git a/client/consensus/common/src/metrics.rs b/client/consensus/common/src/metrics.rs index ade45e3ffb68..ec6ef89f609f 100644 --- a/client/consensus/common/src/metrics.rs +++ b/client/consensus/common/src/metrics.rs @@ -41,28 +41,34 @@ impl Metrics { Ok(Self { import_queue_processed: register( CounterVec::new( - Opts::new("import_queue_processed_total", "Blocks processed by import queue"), + Opts::new( + "substrate_import_queue_processed_total", + "Blocks processed by import queue", + ), &["result"], // 'success or failure )?, registry, )?, block_verification_time: register( HistogramVec::new( - HistogramOpts::new("block_verification_time", "Time taken to verify blocks"), + HistogramOpts::new( + "substrate_block_verification_time", + "Time taken to verify blocks", + ), &["result"], )?, registry, )?, block_verification_and_import_time: register( Histogram::with_opts(HistogramOpts::new( - "block_verification_and_import_time", + "substrate_block_verification_and_import_time", "Time taken to verify and import blocks", ))?, registry, )?, justification_import_time: register( Histogram::with_opts(HistogramOpts::new( - "justification_import_time", + "substrate_justification_import_time", "Time taken to import justifications", ))?, registry, diff --git a/client/finality-grandpa/src/communication/gossip.rs b/client/finality-grandpa/src/communication/gossip.rs index 2e50a3bac01d..8a3b6afcad32 100644 --- a/client/finality-grandpa/src/communication/gossip.rs +++ b/client/finality-grandpa/src/communication/gossip.rs @@ -1299,7 +1299,7 @@ impl Metrics { messages_validated: register( CounterVec::new( Opts::new( - "finality_grandpa_communication_gossip_validator_messages", + "substrate_finality_grandpa_communication_gossip_validator_messages", "Number of messages validated by the finality grandpa gossip validator.", ), &["message", "action"], diff --git a/client/finality-grandpa/src/environment.rs b/client/finality-grandpa/src/environment.rs index c79698902e97..1f5b381c1382 100644 --- a/client/finality-grandpa/src/environment.rs +++ b/client/finality-grandpa/src/environment.rs @@ -404,19 +404,19 @@ impl Metrics { ) -> Result { Ok(Self { finality_grandpa_round: register( - Gauge::new("finality_grandpa_round", "Highest completed GRANDPA round.")?, + Gauge::new("substrate_finality_grandpa_round", "Highest completed GRANDPA round.")?, registry, )?, finality_grandpa_prevotes: register( Counter::new( - "finality_grandpa_prevotes_total", + "substrate_finality_grandpa_prevotes_total", "Total number of GRANDPA prevotes cast locally.", )?, registry, )?, finality_grandpa_precommits: register( Counter::new( - "finality_grandpa_precommits_total", + "substrate_finality_grandpa_precommits_total", "Total number of GRANDPA precommits cast locally.", )?, registry, diff --git a/client/finality-grandpa/src/until_imported.rs b/client/finality-grandpa/src/until_imported.rs index deb657726434..e2c00b54ea06 100644 --- a/client/finality-grandpa/src/until_imported.rs +++ b/client/finality-grandpa/src/until_imported.rs @@ -100,7 +100,7 @@ impl Metrics { Ok(Self { global_waiting_messages: register( Gauge::new( - "finality_grandpa_until_imported_waiting_messages_number", + "substrate_finality_grandpa_until_imported_waiting_messages_number", "Number of finality grandpa messages waiting within the until imported queue.", )?, registry, diff --git a/client/network-gossip/src/state_machine.rs b/client/network-gossip/src/state_machine.rs index 920b44d8c1e5..63553f2f1602 100644 --- a/client/network-gossip/src/state_machine.rs +++ b/client/network-gossip/src/state_machine.rs @@ -508,14 +508,14 @@ impl Metrics { Ok(Self { registered_messages: register( Counter::new( - "network_gossip_registered_messages_total", + "substrate_network_gossip_registered_messages_total", "Number of registered messages by the gossip service.", )?, registry, )?, expired_messages: register( Counter::new( - "network_gossip_expired_messages_total", + "substrate_network_gossip_expired_messages_total", "Number of expired messages by the gossip service.", )?, registry, diff --git a/client/network/src/protocol.rs b/client/network/src/protocol.rs index bfaf42d5ff22..abd723f13d20 100644 --- a/client/network/src/protocol.rs +++ b/client/network/src/protocol.rs @@ -132,21 +132,22 @@ impl Metrics { fn register(r: &Registry) -> Result { Ok(Self { peers: { - let g = Gauge::new("sync_peers", "Number of peers we sync with")?; + let g = Gauge::new("substrate_sync_peers", "Number of peers we sync with")?; register(g, r)? }, queued_blocks: { - let g = Gauge::new("sync_queued_blocks", "Number of blocks in import queue")?; + let g = + Gauge::new("substrate_sync_queued_blocks", "Number of blocks in import queue")?; register(g, r)? }, fork_targets: { - let g = Gauge::new("sync_fork_targets", "Number of fork sync targets")?; + let g = Gauge::new("substrate_sync_fork_targets", "Number of fork sync targets")?; register(g, r)? }, justifications: { let g = GaugeVec::new( Opts::new( - "sync_extra_justifications", + "substrate_sync_extra_justifications", "Number of extra justifications requests", ), &["status"], diff --git a/client/network/src/service/metrics.rs b/client/network/src/service/metrics.rs index e33cd4b194d6..2550f255e848 100644 --- a/client/network/src/service/metrics.rs +++ b/client/network/src/service/metrics.rs @@ -84,54 +84,54 @@ impl Metrics { // This list is ordered alphabetically connections_closed_total: prometheus::register(CounterVec::new( Opts::new( - "sub_libp2p_connections_closed_total", + "substrate_sub_libp2p_connections_closed_total", "Total number of connections closed, by direction and reason" ), &["direction", "reason"] )?, registry)?, connections_opened_total: prometheus::register(CounterVec::new( Opts::new( - "sub_libp2p_connections_opened_total", + "substrate_sub_libp2p_connections_opened_total", "Total number of connections opened by direction" ), &["direction"] )?, registry)?, distinct_peers_connections_closed_total: prometheus::register(Counter::new( - "sub_libp2p_distinct_peers_connections_closed_total", + "substrate_sub_libp2p_distinct_peers_connections_closed_total", "Total number of connections closed with distinct peers" )?, registry)?, distinct_peers_connections_opened_total: prometheus::register(Counter::new( - "sub_libp2p_distinct_peers_connections_opened_total", + "substrate_sub_libp2p_distinct_peers_connections_opened_total", "Total number of connections opened with distinct peers" )?, registry)?, import_queue_blocks_submitted: prometheus::register(Counter::new( - "import_queue_blocks_submitted", + "substrate_import_queue_blocks_submitted", "Number of blocks submitted to the import queue.", )?, registry)?, import_queue_justifications_submitted: prometheus::register(Counter::new( - "import_queue_justifications_submitted", + "substrate_import_queue_justifications_submitted", "Number of justifications submitted to the import queue.", )?, registry)?, incoming_connections_errors_total: prometheus::register(CounterVec::new( Opts::new( - "sub_libp2p_incoming_connections_handshake_errors_total", + "substrate_sub_libp2p_incoming_connections_handshake_errors_total", "Total number of incoming connections that have failed during the \ initial handshake" ), &["reason"] )?, registry)?, incoming_connections_total: prometheus::register(Counter::new( - "sub_libp2p_incoming_connections_total", + "substrate_sub_libp2p_incoming_connections_total", "Total number of incoming connections on the listening sockets" )?, registry)?, issued_light_requests: prometheus::register(Counter::new( - "issued_light_requests", + "substrate_issued_light_requests", "Number of light client requests that our node has issued.", )?, registry)?, kademlia_query_duration: prometheus::register(HistogramVec::new( HistogramOpts { common_opts: Opts::new( - "sub_libp2p_kademlia_query_duration", + "substrate_sub_libp2p_kademlia_query_duration", "Duration of Kademlia queries per query type" ), buckets: prometheus::exponential_buckets(0.5, 2.0, 10) @@ -141,43 +141,44 @@ impl Metrics { )?, registry)?, kademlia_random_queries_total: prometheus::register(CounterVec::new( Opts::new( - "sub_libp2p_kademlia_random_queries_total", + "substrate_sub_libp2p_kademlia_random_queries_total", "Number of random Kademlia queries started" ), &["protocol"] )?, registry)?, kademlia_records_count: prometheus::register(GaugeVec::new( Opts::new( - "sub_libp2p_kademlia_records_count", + "substrate_sub_libp2p_kademlia_records_count", "Number of records in the Kademlia records store" ), &["protocol"] )?, registry)?, kademlia_records_sizes_total: prometheus::register(GaugeVec::new( Opts::new( - "sub_libp2p_kademlia_records_sizes_total", + "substrate_sub_libp2p_kademlia_records_sizes_total", "Total size of all the records in the Kademlia records store" ), &["protocol"] )?, registry)?, kbuckets_num_nodes: prometheus::register(GaugeVec::new( Opts::new( - "sub_libp2p_kbuckets_num_nodes", + "substrate_sub_libp2p_kbuckets_num_nodes", "Number of nodes per kbucket per Kademlia instance" ), &["protocol", "lower_ilog2_bucket_bound"] )?, registry)?, listeners_local_addresses: prometheus::register(Gauge::new( - "sub_libp2p_listeners_local_addresses", "Number of local addresses we're listening on" + "substrate_sub_libp2p_listeners_local_addresses", + "Number of local addresses we're listening on" )?, registry)?, listeners_errors_total: prometheus::register(Counter::new( - "sub_libp2p_listeners_errors_total", + "substrate_sub_libp2p_listeners_errors_total", "Total number of non-fatal errors reported by a listener" )?, registry)?, notifications_sizes: prometheus::register(HistogramVec::new( HistogramOpts { common_opts: Opts::new( - "sub_libp2p_notifications_sizes", + "substrate_sub_libp2p_notifications_sizes", "Sizes of the notifications send to and received from all nodes" ), buckets: prometheus::exponential_buckets(64.0, 4.0, 8) @@ -187,38 +188,40 @@ impl Metrics { )?, registry)?, notifications_streams_closed_total: prometheus::register(CounterVec::new( Opts::new( - "sub_libp2p_notifications_streams_closed_total", + "substrate_sub_libp2p_notifications_streams_closed_total", "Total number of notification substreams that have been closed" ), &["protocol"] )?, registry)?, notifications_streams_opened_total: prometheus::register(CounterVec::new( Opts::new( - "sub_libp2p_notifications_streams_opened_total", + "substrate_sub_libp2p_notifications_streams_opened_total", "Total number of notification substreams that have been opened" ), &["protocol"] )?, registry)?, peerset_num_discovered: prometheus::register(Gauge::new( - "sub_libp2p_peerset_num_discovered", "Number of nodes stored in the peerset manager", + "substrate_sub_libp2p_peerset_num_discovered", + "Number of nodes stored in the peerset manager", )?, registry)?, peerset_num_requested: prometheus::register(Gauge::new( - "sub_libp2p_peerset_num_requested", "Number of nodes that the peerset manager wants us to be connected to", + "substrate_sub_libp2p_peerset_num_requested", + "Number of nodes that the peerset manager wants us to be connected to", )?, registry)?, pending_connections: prometheus::register(Gauge::new( - "sub_libp2p_pending_connections", + "substrate_sub_libp2p_pending_connections", "Number of connections in the process of being established", )?, registry)?, pending_connections_errors_total: prometheus::register(CounterVec::new( Opts::new( - "sub_libp2p_pending_connections_errors_total", + "substrate_sub_libp2p_pending_connections_errors_total", "Total number of pending connection errors" ), &["reason"] )?, registry)?, requests_in_failure_total: prometheus::register(CounterVec::new( Opts::new( - "sub_libp2p_requests_in_failure_total", + "substrate_sub_libp2p_requests_in_failure_total", "Total number of incoming requests that the node has failed to answer" ), &["protocol", "reason"] @@ -226,7 +229,7 @@ impl Metrics { requests_in_success_total: prometheus::register(HistogramVec::new( HistogramOpts { common_opts: Opts::new( - "sub_libp2p_requests_in_success_total", + "substrate_sub_libp2p_requests_in_success_total", "For successful incoming requests, time between receiving the request and \ starting to send the response" ), @@ -237,7 +240,7 @@ impl Metrics { )?, registry)?, requests_out_failure_total: prometheus::register(CounterVec::new( Opts::new( - "sub_libp2p_requests_out_failure_total", + "substrate_sub_libp2p_requests_out_failure_total", "Total number of requests that have failed" ), &["protocol", "reason"] @@ -245,7 +248,7 @@ impl Metrics { requests_out_success_total: prometheus::register(HistogramVec::new( HistogramOpts { common_opts: Opts::new( - "sub_libp2p_requests_out_success_total", + "substrate_sub_libp2p_requests_out_success_total", "For successful outgoing requests, time between a request's start and finish" ), buckets: prometheus::exponential_buckets(0.001, 2.0, 16) @@ -267,7 +270,7 @@ impl BandwidthCounters { fn register(registry: &Registry, sinks: Arc) -> Result<(), PrometheusError> { prometheus::register( SourcedCounter::new( - &Opts::new("sub_libp2p_network_bytes_total", "Total bandwidth usage") + &Opts::new("substrate_sub_libp2p_network_bytes_total", "Total bandwidth usage") .variable_label("direction"), BandwidthCounters(sinks), )?, @@ -298,7 +301,7 @@ impl MajorSyncingGauge { prometheus::register( SourcedGauge::new( &Opts::new( - "sub_libp2p_is_major_syncing", + "substrate_sub_libp2p_is_major_syncing", "Whether the node is performing a major sync or not.", ), MajorSyncingGauge(value), @@ -328,7 +331,7 @@ impl NumConnectedGauge { fn register(registry: &Registry, value: Arc) -> Result<(), PrometheusError> { prometheus::register( SourcedGauge::new( - &Opts::new("sub_libp2p_peers_count", "Number of connected peers"), + &Opts::new("substrate_sub_libp2p_peers_count", "Number of connected peers"), NumConnectedGauge(value), )?, registry, diff --git a/client/network/src/service/out_events.rs b/client/network/src/service/out_events.rs index 2d6241278005..90888c2371f9 100644 --- a/client/network/src/service/out_events.rs +++ b/client/network/src/service/out_events.rs @@ -192,7 +192,7 @@ impl Metrics { Ok(Self { events_total: register(CounterVec::new( Opts::new( - "sub_libp2p_out_events_events_total", + "substrate_sub_libp2p_out_events_events_total", "Number of broadcast network events that have been sent or received across all \ channels" ), @@ -200,7 +200,7 @@ impl Metrics { )?, registry)?, notifications_sizes: register(CounterVec::new( Opts::new( - "sub_libp2p_out_events_notifications_sizes", + "substrate_sub_libp2p_out_events_notifications_sizes", "Size of notification events that have been sent or received across all \ channels" ), @@ -208,7 +208,7 @@ impl Metrics { )?, registry)?, num_channels: register(GaugeVec::new( Opts::new( - "sub_libp2p_out_events_num_channels", + "substrate_sub_libp2p_out_events_num_channels", "Number of internal active channels that broadcast network events", ), &["name"] diff --git a/client/network/src/transactions.rs b/client/network/src/transactions.rs index 6d190651160f..21fc55acd274 100644 --- a/client/network/src/transactions.rs +++ b/client/network/src/transactions.rs @@ -95,7 +95,7 @@ impl Metrics { Ok(Self { propagated_transactions: register( Counter::new( - "sync_propagated_transactions", + "substrate_sync_propagated_transactions", "Number of transactions propagated to at least one peer", )?, r, diff --git a/client/proposer-metrics/src/lib.rs b/client/proposer-metrics/src/lib.rs index 452a796b7392..8bd626bd0791 100644 --- a/client/proposer-metrics/src/lib.rs +++ b/client/proposer-metrics/src/lib.rs @@ -56,14 +56,14 @@ impl Metrics { Ok(Self { block_constructed: register( Histogram::with_opts(HistogramOpts::new( - "proposer_block_constructed", + "substrate_proposer_block_constructed", "Histogram of time taken to construct new block", ))?, registry, )?, number_of_transactions: register( Gauge::new( - "proposer_number_of_transactions", + "substrate_proposer_number_of_transactions", "Number of transactions included in block", )?, registry, diff --git a/client/rpc-servers/src/lib.rs b/client/rpc-servers/src/lib.rs index 1ac409d6ba89..82da84834320 100644 --- a/client/rpc-servers/src/lib.rs +++ b/client/rpc-servers/src/lib.rs @@ -90,7 +90,7 @@ impl ServerMetrics { Ok(Self { session_opened: register( Counter::new( - "rpc_sessions_opened", + "substrate_rpc_sessions_opened", "Number of persistent RPC sessions opened", )?, r, @@ -98,7 +98,7 @@ impl ServerMetrics { .into(), session_closed: register( Counter::new( - "rpc_sessions_closed", + "substrate_rpc_sessions_closed", "Number of persistent RPC sessions closed", )?, r, diff --git a/client/rpc-servers/src/middleware.rs b/client/rpc-servers/src/middleware.rs index 00532b0e8d66..a78c0642cb58 100644 --- a/client/rpc-servers/src/middleware.rs +++ b/client/rpc-servers/src/middleware.rs @@ -48,7 +48,7 @@ impl RpcMetrics { requests_started: register( CounterVec::new( Opts::new( - "rpc_requests_started", + "substrate_rpc_requests_started", "Number of RPC requests (not calls) received by the server.", ), &["protocol"], @@ -58,7 +58,7 @@ impl RpcMetrics { requests_finished: register( CounterVec::new( Opts::new( - "rpc_requests_finished", + "substrate_rpc_requests_finished", "Number of RPC requests (not calls) processed by the server.", ), &["protocol"], @@ -68,7 +68,7 @@ impl RpcMetrics { calls_time: register( HistogramVec::new( HistogramOpts::new( - "rpc_calls_time", + "substrate_rpc_calls_time", "Total time [μs] of processed RPC calls", ), &["protocol", "method"], @@ -78,7 +78,7 @@ impl RpcMetrics { calls_started: register( CounterVec::new( Opts::new( - "rpc_calls_started", + "substrate_rpc_calls_started", "Number of received RPC calls (unique un-batched requests)", ), &["protocol", "method"], @@ -88,7 +88,7 @@ impl RpcMetrics { calls_finished: register( CounterVec::new( Opts::new( - "rpc_calls_finished", + "substrate_rpc_calls_finished", "Number of processed RPC calls (unique un-batched requests)", ), &["protocol", "method", "is_error"], diff --git a/client/service/src/config.rs b/client/service/src/config.rs index d3bd4e4e4879..0552baf5c209 100644 --- a/client/service/src/config.rs +++ b/client/service/src/config.rs @@ -36,7 +36,7 @@ pub use sc_telemetry::TelemetryEndpoints; pub use sc_transaction_pool::Options as TransactionPoolOptions; use sp_core::crypto::SecretString; use std::{ - io, + io, iter, net::SocketAddr, path::{Path, PathBuf}, }; @@ -188,10 +188,11 @@ impl PrometheusConfig { /// Create a new config using the default registry. /// /// The default registry prefixes metrics with `substrate`. - pub fn new_with_default_registry(port: SocketAddr) -> Self { + pub fn new_with_default_registry(port: SocketAddr, chain_id: String) -> Self { + let param = iter::once((String::from("chain"), chain_id)).collect(); Self { port, - registry: Registry::new_custom(Some("substrate".into()), None) + registry: Registry::new_custom(None, Some(param)) .expect("this can only fail if the prefix is empty"), } } diff --git a/client/service/src/metrics.rs b/client/service/src/metrics.rs index 4d3c6df92fee..54550330d75e 100644 --- a/client/service/src/metrics.rs +++ b/client/service/src/metrics.rs @@ -55,7 +55,7 @@ impl PrometheusMetrics { register( Gauge::::with_opts( Opts::new( - "build_info", + "substrate_build_info", "A metric with a constant '1' value labeled by name, version", ) .const_label("name", name) @@ -65,8 +65,11 @@ impl PrometheusMetrics { )? .set(1); - register(Gauge::::new("node_roles", "The roles the node is running as")?, ®istry)? - .set(roles); + register( + Gauge::::new("substrate_node_roles", "The roles the node is running as")?, + ®istry, + )? + .set(roles); register_globals(registry)?; @@ -74,7 +77,7 @@ impl PrometheusMetrics { SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap_or_default(); register( Gauge::::new( - "process_start_time_seconds", + "substrate_process_start_time_seconds", "Number of seconds between the UNIX epoch and the moment the process started", )?, registry, @@ -85,20 +88,20 @@ impl PrometheusMetrics { // generic internals block_height: register( GaugeVec::new( - Opts::new("block_height", "Block height info of the chain"), + Opts::new("substrate_block_height", "Block height info of the chain"), &["status"], )?, registry, )?, number_leaves: register( - Gauge::new("number_leaves", "Number of known chain leaves (aka forks)")?, + Gauge::new("substrate_number_leaves", "Number of known chain leaves (aka forks)")?, registry, )?, ready_transactions_number: register( Gauge::new( - "ready_transactions_number", + "substrate_ready_transactions_number", "Number of transactions in the ready queue", )?, registry, @@ -106,16 +109,16 @@ impl PrometheusMetrics { // I/ O database_cache: register( - Gauge::new("database_cache_bytes", "RocksDB cache size in bytes")?, + Gauge::new("substrate_database_cache_bytes", "RocksDB cache size in bytes")?, registry, )?, state_cache: register( - Gauge::new("state_cache_bytes", "State cache size in bytes")?, + Gauge::new("substrate_state_cache_bytes", "State cache size in bytes")?, registry, )?, state_db: register( GaugeVec::new( - Opts::new("state_db_cache_bytes", "State DB cache in bytes"), + Opts::new("substrate_state_db_cache_bytes", "State DB cache in bytes"), &["subtype"], )?, registry, diff --git a/client/service/src/task_manager/mod.rs b/client/service/src/task_manager/mod.rs index 342ea6627be6..e09a351b6092 100644 --- a/client/service/src/task_manager/mod.rs +++ b/client/service/src/task_manager/mod.rs @@ -401,7 +401,7 @@ impl Metrics { poll_duration: register(HistogramVec::new( HistogramOpts { common_opts: Opts::new( - "tasks_polling_duration", + "substrate_tasks_polling_duration", "Duration in seconds of each invocation of Future::poll" ), buckets: exponential_buckets(0.001, 4.0, 9) @@ -411,21 +411,21 @@ impl Metrics { )?, registry)?, poll_start: register(CounterVec::new( Opts::new( - "tasks_polling_started_total", + "substrate_tasks_polling_started_total", "Total number of times we started invoking Future::poll" ), &["task_name", "task_group"] )?, registry)?, tasks_spawned: register(CounterVec::new( Opts::new( - "tasks_spawned_total", + "substrate_tasks_spawned_total", "Total number of tasks that have been spawned on the Service" ), &["task_name", "task_group"] )?, registry)?, tasks_ended: register(CounterVec::new( Opts::new( - "tasks_ended_total", + "substrate_tasks_ended_total", "Total number of tasks for which Future::poll has returned Ready(()) or panicked" ), &["task_name", "reason", "task_group"] diff --git a/client/transaction-pool/src/metrics.rs b/client/transaction-pool/src/metrics.rs index d62d64f13a0a..7afed2150978 100644 --- a/client/transaction-pool/src/metrics.rs +++ b/client/transaction-pool/src/metrics.rs @@ -56,28 +56,28 @@ impl Metrics { Ok(Self { submitted_transactions: register( Counter::new( - "sub_txpool_submitted_transactions", + "substrate_sub_txpool_submitted_transactions", "Total number of transactions submitted", )?, registry, )?, validations_invalid: register( Counter::new( - "sub_txpool_validations_invalid", + "substrate_sub_txpool_validations_invalid", "Total number of transactions that were removed from the pool as invalid", )?, registry, )?, block_transactions_pruned: register( Counter::new( - "sub_txpool_block_transactions_pruned", + "substrate_sub_txpool_block_transactions_pruned", "Total number of transactions that was requested to be pruned by block events", )?, registry, )?, block_transactions_resubmitted: register( Counter::new( - "sub_txpool_block_transactions_resubmitted", + "substrate_sub_txpool_block_transactions_resubmitted", "Total number of transactions that was requested to be resubmitted by block events", )?, registry, @@ -98,14 +98,14 @@ impl ApiMetrics { Ok(Self { validations_scheduled: register( Counter::new( - "sub_txpool_validations_scheduled", + "substrate_sub_txpool_validations_scheduled", "Total number of transactions scheduled for validation", )?, registry, )?, validations_finished: register( Counter::new( - "sub_txpool_validations_finished", + "substrate_sub_txpool_validations_finished", "Total number of transactions that finished validation", )?, registry, diff --git a/client/utils/src/metrics.rs b/client/utils/src/metrics.rs index 85ccce626bc2..6e85a66e62e5 100644 --- a/client/utils/src/metrics.rs +++ b/client/utils/src/metrics.rs @@ -29,17 +29,17 @@ use prometheus::{core::GenericCounterVec, Opts}; lazy_static! { pub static ref TOKIO_THREADS_TOTAL: GenericCounter = - GenericCounter::new("tokio_threads_total", "Total number of threads created") + GenericCounter::new("substrate_tokio_threads_total", "Total number of threads created") .expect("Creating of statics doesn't fail. qed"); pub static ref TOKIO_THREADS_ALIVE: GenericGauge = - GenericGauge::new("tokio_threads_alive", "Number of threads alive right now") + GenericGauge::new("substrate_tokio_threads_alive", "Number of threads alive right now") .expect("Creating of statics doesn't fail. qed"); } #[cfg(feature = "metered")] lazy_static! { pub static ref UNBOUNDED_CHANNELS_COUNTER : GenericCounterVec = GenericCounterVec::new( - Opts::new("unbounded_channel_len", "Items in each mpsc::unbounded instance"), + Opts::new("substrate_unbounded_channel_len", "Items in each mpsc::unbounded instance"), &["entity", "action"] // 'name of channel, send|received|dropped ).expect("Creating of statics doesn't fail. qed"); From 3dc984280b4380179fa83a3895aff84048dfe146 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Thu, 9 Dec 2021 12:29:24 +0100 Subject: [PATCH 273/695] Rename some missed metrics (#10455) --- client/proposer-metrics/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/proposer-metrics/src/lib.rs b/client/proposer-metrics/src/lib.rs index 8bd626bd0791..ca60cafef3f6 100644 --- a/client/proposer-metrics/src/lib.rs +++ b/client/proposer-metrics/src/lib.rs @@ -70,14 +70,14 @@ impl Metrics { )?, create_inherents_time: register( Histogram::with_opts(HistogramOpts::new( - "proposer_create_inherents_time", + "substrate_proposer_create_inherents_time", "Histogram of time taken to execute create inherents", ))?, registry, )?, create_block_proposal_time: register( Histogram::with_opts(HistogramOpts::new( - "proposer_block_proposal_time", + "substrate_proposer_block_proposal_time", "Histogram of time taken to construct a block and prepare it for proposal", ))?, registry, From 8a3434bb5e8f204107644cd32f97f5ba76d8714f Mon Sep 17 00:00:00 2001 From: Gavin Wood Date: Thu, 9 Dec 2021 13:22:54 +0100 Subject: [PATCH 274/695] Insufficient asset quota and deposits (#10382) * Allow asset accounts to exist by deposit * Place limit on consumers (and therefore freebie asset accounts) * Maximum number of assets * Fixes * Fixes * Formatting * Docs * Formatting * Destroyed assets are properly tidied * Update frame/assets/src/types.rs Co-authored-by: Guillaume Thiolliere * Docs * Docs * Formatting * Docs * Docs * Fixes * Fixes Co-authored-by: Guillaume Thiolliere --- .../pallets/template/src/mock.rs | 1 + bin/node-template/runtime/src/lib.rs | 3 +- bin/node/runtime/src/lib.rs | 7 +- frame/assets/src/extra_mutator.rs | 25 +-- frame/assets/src/functions.rs | 208 +++++++++++++----- frame/assets/src/impl_stored_map.rs | 10 +- frame/assets/src/lib.rs | 66 +++++- frame/assets/src/mock.rs | 36 ++- frame/assets/src/tests.rs | 103 ++++++++- frame/assets/src/types.rs | 54 ++++- frame/atomic-swap/src/tests.rs | 1 + frame/aura/src/mock.rs | 1 + frame/authority-discovery/src/lib.rs | 1 + frame/authorship/src/lib.rs | 1 + frame/babe/src/mock.rs | 1 + frame/bags-list/src/mock.rs | 1 + frame/balances/src/tests_composite.rs | 1 + frame/balances/src/tests_local.rs | 1 + frame/balances/src/tests_reentrancy.rs | 1 + frame/beefy-mmr/src/mock.rs | 1 + frame/beefy/src/mock.rs | 1 + frame/benchmarking/src/baseline.rs | 1 + frame/benchmarking/src/tests.rs | 1 + frame/benchmarking/src/tests_instance.rs | 1 + frame/bounties/src/tests.rs | 1 + frame/child-bounties/src/tests.rs | 1 + frame/collective/src/tests.rs | 1 + frame/contracts/src/tests.rs | 1 + frame/democracy/src/tests.rs | 1 + .../election-provider-multi-phase/src/mock.rs | 1 + .../election-provider-support/src/onchain.rs | 1 + frame/elections-phragmen/src/lib.rs | 1 + frame/elections/src/mock.rs | 1 + frame/examples/basic/src/tests.rs | 1 + frame/examples/offchain-worker/src/tests.rs | 1 + frame/examples/parallel/src/tests.rs | 1 + frame/executive/src/lib.rs | 1 + frame/gilt/src/mock.rs | 1 + frame/grandpa/src/mock.rs | 1 + frame/identity/src/tests.rs | 1 + frame/im-online/src/mock.rs | 1 + frame/indices/src/mock.rs | 1 + frame/lottery/src/mock.rs | 1 + frame/membership/src/lib.rs | 1 + frame/merkle-mountain-range/src/mock.rs | 1 + frame/multisig/src/tests.rs | 1 + frame/nicks/src/lib.rs | 1 + frame/node-authorization/src/mock.rs | 1 + frame/offences/benchmarking/src/mock.rs | 1 + frame/offences/src/mock.rs | 1 + frame/proxy/src/tests.rs | 1 + frame/randomness-collective-flip/src/lib.rs | 1 + frame/recovery/src/mock.rs | 1 + frame/scheduler/src/lib.rs | 1 + frame/scored-pool/src/mock.rs | 1 + frame/session/benchmarking/src/mock.rs | 1 + frame/session/src/mock.rs | 1 + frame/society/src/mock.rs | 1 + frame/staking/src/mock.rs | 1 + frame/sudo/src/mock.rs | 1 + frame/support/src/traits.rs | 7 +- frame/support/src/traits/misc.rs | 41 ++-- frame/support/test/compile_pass/Cargo.toml | 11 +- frame/support/test/compile_pass/src/lib.rs | 9 +- frame/support/test/tests/pallet.rs | 1 + .../test/tests/pallet_compatibility.rs | 1 + .../tests/pallet_compatibility_instance.rs | 1 + frame/support/test/tests/pallet_instance.rs | 1 + .../tests/pallet_with_name_trait_is_valid.rs | 1 + frame/system/benches/bench.rs | 1 + frame/system/benchmarking/src/mock.rs | 1 + frame/system/src/lib.rs | 15 +- frame/system/src/mock.rs | 1 + frame/timestamp/src/lib.rs | 1 + frame/tips/src/tests.rs | 1 + .../asset-tx-payment/src/tests.rs | 2 + frame/transaction-payment/src/lib.rs | 1 + frame/transaction-storage/src/mock.rs | 1 + frame/treasury/src/tests.rs | 1 + frame/uniques/src/mock.rs | 1 + frame/utility/src/tests.rs | 1 + frame/vesting/src/mock.rs | 1 + primitives/runtime/src/lib.rs | 4 + test-utils/runtime/src/lib.rs | 1 + 84 files changed, 514 insertions(+), 155 deletions(-) diff --git a/bin/node-template/pallets/template/src/mock.rs b/bin/node-template/pallets/template/src/mock.rs index 4532d3d09b49..733ac79d6577 100644 --- a/bin/node-template/pallets/template/src/mock.rs +++ b/bin/node-template/pallets/template/src/mock.rs @@ -51,6 +51,7 @@ impl system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = SS58Prefix; type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } impl pallet_template::Config for Test { diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index 4eaa0aa00d0b..335b36fe2f5c 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -26,7 +26,7 @@ use sp_version::RuntimeVersion; // A few exports that help ease life for downstream crates. pub use frame_support::{ construct_runtime, parameter_types, - traits::{KeyOwnerProofSystem, Randomness, StorageInfo}, + traits::{ConstU32, KeyOwnerProofSystem, Randomness, StorageInfo}, weights::{ constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND}, IdentityFee, Weight, @@ -191,6 +191,7 @@ impl frame_system::Config for Runtime { type SS58Prefix = SS58Prefix; /// The set code logic, just the default since we're not a parachain. type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } impl pallet_randomness_collective_flip::Config for Runtime {} diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 44d39a870efc..3134f25cfb26 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -26,8 +26,9 @@ use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::{ construct_runtime, parameter_types, traits::{ - ConstU32, Currency, EnsureOneOf, EqualPrivilegeOnly, Everything, Imbalance, InstanceFilter, - KeyOwnerProofSystem, LockIdentifier, Nothing, OnUnbalanced, U128CurrencyToVote, + ConstU128, ConstU32, Currency, EnsureOneOf, EqualPrivilegeOnly, Everything, Imbalance, + InstanceFilter, KeyOwnerProofSystem, LockIdentifier, Nothing, OnUnbalanced, + U128CurrencyToVote, }, weights::{ constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND}, @@ -219,6 +220,7 @@ impl frame_system::Config for Runtime { type SystemWeightInfo = frame_system::weights::SubstrateWeight; type SS58Prefix = SS58Prefix; type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } impl pallet_randomness_collective_flip::Config for Runtime {} @@ -1195,6 +1197,7 @@ impl pallet_assets::Config for Runtime { type Currency = Balances; type ForceOrigin = EnsureRoot; type AssetDeposit = AssetDeposit; + type AssetAccountDeposit = ConstU128; type MetadataDepositBase = MetadataDepositBase; type MetadataDepositPerByte = MetadataDepositPerByte; type ApprovalDeposit = ApprovalDeposit; diff --git a/frame/assets/src/extra_mutator.rs b/frame/assets/src/extra_mutator.rs index 8c601b746346..5ebfc3e54713 100644 --- a/frame/assets/src/extra_mutator.rs +++ b/frame/assets/src/extra_mutator.rs @@ -62,11 +62,11 @@ impl, I: 'static> ExtraMutator { id: T::AssetId, who: impl sp_std::borrow::Borrow, ) -> Option> { - if Account::::contains_key(id, who.borrow()) { + if let Some(a) = Account::::get(id, who.borrow()) { Some(ExtraMutator:: { id, who: who.borrow().clone(), - original: Account::::get(id, who.borrow()).extra, + original: a.extra, pending: None, }) } else { @@ -77,13 +77,8 @@ impl, I: 'static> ExtraMutator { /// Commit any changes to storage. pub fn commit(&mut self) -> Result<(), ()> { if let Some(extra) = self.pending.take() { - Account::::try_mutate_exists(self.id, self.who.borrow(), |maybe_account| { - if let Some(ref mut account) = maybe_account { - account.extra = extra; - Ok(()) - } else { - Err(()) - } + Account::::try_mutate(self.id, self.who.borrow(), |maybe_account| { + maybe_account.as_mut().ok_or(()).map(|account| account.extra = extra) }) } else { Ok(()) @@ -93,13 +88,11 @@ impl, I: 'static> ExtraMutator { /// Revert any changes, even those already committed by `self` and drop self. pub fn revert(mut self) -> Result<(), ()> { self.pending = None; - Account::::try_mutate_exists(self.id, self.who.borrow(), |maybe_account| { - if let Some(ref mut account) = maybe_account { - account.extra = self.original.clone(); - Ok(()) - } else { - Err(()) - } + Account::::try_mutate(self.id, self.who.borrow(), |maybe_account| { + maybe_account + .as_mut() + .ok_or(()) + .map(|account| account.extra = self.original.clone()) }) } } diff --git a/frame/assets/src/functions.rs b/frame/assets/src/functions.rs index f01954cb970e..a34900e74bbb 100644 --- a/frame/assets/src/functions.rs +++ b/frame/assets/src/functions.rs @@ -20,6 +20,14 @@ use super::*; use frame_support::{traits::Get, BoundedVec}; +#[must_use] +pub(super) enum DeadConsequence { + Remove, + Keep, +} + +use DeadConsequence::*; + // The main implementation block for the module. impl, I: 'static> Pallet { // Public immutables @@ -32,9 +40,17 @@ impl, I: 'static> Pallet { ExtraMutator::maybe_new(id, who) } - /// Get the asset `id` balance of `who`. + /// Get the asset `id` balance of `who`, or zero if the asset-account doesn't exist. pub fn balance(id: T::AssetId, who: impl sp_std::borrow::Borrow) -> T::Balance { - Account::::get(id, who.borrow()).balance + Self::maybe_balance(id, who).unwrap_or_default() + } + + /// Get the asset `id` balance of `who` if the asset-account exists. + pub fn maybe_balance( + id: T::AssetId, + who: impl sp_std::borrow::Borrow, + ) -> Option { + Account::::get(id, who.borrow()).map(|a| a.balance) } /// Get the total supply of an asset `id`. @@ -45,34 +61,44 @@ impl, I: 'static> Pallet { pub(super) fn new_account( who: &T::AccountId, d: &mut AssetDetails>, - ) -> Result { + maybe_deposit: Option>, + ) -> Result>, DispatchError> { let accounts = d.accounts.checked_add(1).ok_or(ArithmeticError::Overflow)?; - let is_sufficient = if d.is_sufficient { + let reason = if let Some(deposit) = maybe_deposit { + ExistenceReason::DepositHeld(deposit) + } else if d.is_sufficient { frame_system::Pallet::::inc_sufficients(who); d.sufficients += 1; - true + ExistenceReason::Sufficient } else { frame_system::Pallet::::inc_consumers(who).map_err(|_| Error::::NoProvider)?; - false + ExistenceReason::Consumer }; d.accounts = accounts; - Ok(is_sufficient) + Ok(reason) } pub(super) fn dead_account( what: T::AssetId, who: &T::AccountId, d: &mut AssetDetails>, - sufficient: bool, - ) { - if sufficient { - d.sufficients = d.sufficients.saturating_sub(1); - frame_system::Pallet::::dec_sufficients(who); - } else { - frame_system::Pallet::::dec_consumers(who); + reason: &ExistenceReason>, + force: bool, + ) -> DeadConsequence { + let mut result = Remove; + match *reason { + ExistenceReason::Consumer => frame_system::Pallet::::dec_consumers(who), + ExistenceReason::Sufficient => { + d.sufficients = d.sufficients.saturating_sub(1); + frame_system::Pallet::::dec_sufficients(who); + }, + ExistenceReason::DepositRefunded => {}, + ExistenceReason::DepositHeld(_) if !force => return Keep, + ExistenceReason::DepositHeld(_) => result = Keep, } d.accounts = d.accounts.saturating_sub(1); - T::Freezer::died(what, who) + T::Freezer::died(what, who); + result } pub(super) fn can_increase( @@ -87,15 +113,15 @@ impl, I: 'static> Pallet { if details.supply.checked_add(&amount).is_none() { return DepositConsequence::Overflow } - let account = Account::::get(id, who); - if account.balance.checked_add(&amount).is_none() { - return DepositConsequence::Overflow - } - if account.balance.is_zero() { + if let Some(balance) = Self::maybe_balance(id, who) { + if balance.checked_add(&amount).is_none() { + return DepositConsequence::Overflow + } + } else { if amount < details.min_balance { return DepositConsequence::BelowMinimum } - if !details.is_sufficient && frame_system::Pallet::::providers(who) == 0 { + if !details.is_sufficient && !frame_system::Pallet::::can_inc_consumer(who) { return DepositConsequence::CannotCreate } if details.is_sufficient && details.sufficients.checked_add(1).is_none() { @@ -124,7 +150,13 @@ impl, I: 'static> Pallet { if details.is_frozen { return Frozen } - let account = Account::::get(id, who); + if amount.is_zero() { + return Success + } + let account = match Account::::get(id, who) { + Some(a) => a, + None => return NoFunds, + }; if account.is_frozen { return Frozen } @@ -165,7 +197,7 @@ impl, I: 'static> Pallet { let details = Asset::::get(id).ok_or_else(|| Error::::Unknown)?; ensure!(!details.is_frozen, Error::::Frozen); - let account = Account::::get(id, who); + let account = Account::::get(id, who).ok_or(Error::::NoAccount)?; ensure!(!account.is_frozen, Error::::Frozen); let amount = if let Some(frozen) = T::Freezer::frozen_balance(id, who) { @@ -253,6 +285,48 @@ impl, I: 'static> Pallet { Ok((credit, maybe_burn)) } + /// Creates a account for `who` to hold asset `id` with a zero balance and takes a deposit. + pub(super) fn do_touch(id: T::AssetId, who: T::AccountId) -> DispatchResult { + ensure!(!Account::::contains_key(id, &who), Error::::AlreadyExists); + let deposit = T::AssetAccountDeposit::get(); + let mut details = Asset::::get(&id).ok_or(Error::::Unknown)?; + let reason = Self::new_account(&who, &mut details, Some(deposit))?; + T::Currency::reserve(&who, deposit)?; + Asset::::insert(&id, details); + Account::::insert( + id, + &who, + AssetAccountOf:: { + balance: Zero::zero(), + is_frozen: false, + reason, + extra: T::Extra::default(), + }, + ); + Ok(()) + } + + /// Returns a deposit, destroying an asset-account. + pub(super) fn do_refund(id: T::AssetId, who: T::AccountId, allow_burn: bool) -> DispatchResult { + let mut account = Account::::get(id, &who).ok_or(Error::::NoDeposit)?; + let deposit = account.reason.take_deposit().ok_or(Error::::NoDeposit)?; + let mut details = Asset::::get(&id).ok_or(Error::::Unknown)?; + + ensure!(account.balance.is_zero() || allow_burn, Error::::WouldBurn); + ensure!(!details.is_frozen, Error::::Frozen); + ensure!(!account.is_frozen, Error::::Frozen); + + T::Currency::unreserve(&who, deposit); + + if let Remove = Self::dead_account(id, &who, &mut details, &account.reason, false) { + Account::::remove(id, &who); + } else { + debug_assert!(false, "refund did not result in dead account?!"); + } + Asset::::insert(&id, details); + Ok(()) + } + /// Increases the asset `id` balance of `beneficiary` by `amount`. /// /// This alters the registered supply of the asset and emits an event. @@ -307,13 +381,22 @@ impl, I: 'static> Pallet { check(details)?; - Account::::try_mutate(id, beneficiary, |t| -> DispatchResult { - let new_balance = t.balance.saturating_add(amount); - ensure!(new_balance >= details.min_balance, TokenError::BelowMinimum); - if t.balance.is_zero() { - t.sufficient = Self::new_account(beneficiary, details)?; + Account::::try_mutate(id, beneficiary, |maybe_account| -> DispatchResult { + match maybe_account { + Some(ref mut account) => { + account.balance.saturating_accrue(amount); + }, + maybe_account @ None => { + // Note this should never fail as it's already checked by `can_increase`. + ensure!(amount >= details.min_balance, TokenError::BelowMinimum); + *maybe_account = Some(AssetAccountOf:: { + balance: amount, + reason: Self::new_account(beneficiary, details, None)?, + is_frozen: false, + extra: T::Extra::default(), + }); + }, } - t.balance = new_balance; Ok(()) })?; Ok(()) @@ -375,23 +458,25 @@ impl, I: 'static> Pallet { let actual = Self::prep_debit(id, target, amount, f)?; Asset::::try_mutate(id, |maybe_details| -> DispatchResult { - let details = maybe_details.as_mut().ok_or(Error::::Unknown)?; + let mut details = maybe_details.as_mut().ok_or(Error::::Unknown)?; check(actual, details)?; - Account::::try_mutate_exists(id, target, |maybe_account| -> DispatchResult { - let mut account = maybe_account.take().unwrap_or_default(); + Account::::try_mutate(id, target, |maybe_account| -> DispatchResult { + let mut account = maybe_account.take().ok_or(Error::::NoAccount)?; debug_assert!(account.balance >= actual, "checked in prep; qed"); // Make the debit. account.balance = account.balance.saturating_sub(actual); - *maybe_account = if account.balance < details.min_balance { + if account.balance < details.min_balance { debug_assert!(account.balance.is_zero(), "checked in prep; qed"); - Self::dead_account(id, target, details, account.sufficient); - None - } else { - Some(account) + if let Remove = + Self::dead_account(id, target, &mut details, &account.reason, false) + { + return Ok(()) + } }; + *maybe_account = Some(account); Ok(()) })?; @@ -432,7 +517,8 @@ impl, I: 'static> Pallet { let debit = Self::prep_debit(id, &source, amount, f.into())?; let (credit, maybe_burn) = Self::prep_credit(id, &dest, amount, debit, f.burn_dust)?; - let mut source_account = Account::::get(id, &source); + let mut source_account = + Account::::get(id, &source).ok_or(Error::::NoAccount)?; Asset::::try_mutate(id, |maybe_details| -> DispatchResult { let details = maybe_details.as_mut().ok_or(Error::::Unknown)?; @@ -459,29 +545,40 @@ impl, I: 'static> Pallet { debug_assert!(source_account.balance >= debit, "checked in prep; qed"); source_account.balance = source_account.balance.saturating_sub(debit); - Account::::try_mutate(id, &dest, |a| -> DispatchResult { - // Calculate new balance; this will not saturate since it's already checked in prep. - debug_assert!(a.balance.checked_add(&credit).is_some(), "checked in prep; qed"); - let new_balance = a.balance.saturating_add(credit); - - // Create a new account if there wasn't one already. - if a.balance.is_zero() { - a.sufficient = Self::new_account(&dest, details)?; + Account::::try_mutate(id, &dest, |maybe_account| -> DispatchResult { + match maybe_account { + Some(ref mut account) => { + // Calculate new balance; this will not saturate since it's already checked + // in prep. + debug_assert!( + account.balance.checked_add(&credit).is_some(), + "checked in prep; qed" + ); + account.balance.saturating_accrue(credit); + }, + maybe_account @ None => { + *maybe_account = Some(AssetAccountOf:: { + balance: credit, + is_frozen: false, + reason: Self::new_account(&dest, details, None)?, + extra: T::Extra::default(), + }); + }, } - - a.balance = new_balance; Ok(()) })?; // Remove source account if it's now dead. if source_account.balance < details.min_balance { debug_assert!(source_account.balance.is_zero(), "checked in prep; qed"); - Self::dead_account(id, &source, details, source_account.sufficient); - Account::::remove(id, &source); - } else { - Account::::insert(id, &source, &source_account) + if let Remove = + Self::dead_account(id, &source, details, &source_account.reason, false) + { + Account::::remove(id, &source); + return Ok(()) + } } - + Account::::insert(id, &source, &source_account); Ok(()) })?; @@ -554,7 +651,10 @@ impl, I: 'static> Pallet { ensure!(details.approvals <= witness.approvals, Error::::BadWitness); for (who, v) in Account::::drain_prefix(id) { - Self::dead_account(id, &who, &mut details, v.sufficient); + // We have to force this as it's destroying the entire asset class. + // This could mean that some accounts now have irreversibly reserved + // funds. + let _ = Self::dead_account(id, &who, &mut details, &v.reason, true); } debug_assert_eq!(details.accounts, 0); debug_assert_eq!(details.sufficients, 0); diff --git a/frame/assets/src/impl_stored_map.rs b/frame/assets/src/impl_stored_map.rs index 4c1ff1a0c602..88e2203f046b 100644 --- a/frame/assets/src/impl_stored_map.rs +++ b/frame/assets/src/impl_stored_map.rs @@ -22,11 +22,7 @@ use super::*; impl, I: 'static> StoredMap<(T::AssetId, T::AccountId), T::Extra> for Pallet { fn get(id_who: &(T::AssetId, T::AccountId)) -> T::Extra { let &(id, ref who) = id_who; - if Account::::contains_key(id, who) { - Account::::get(id, who).extra - } else { - Default::default() - } + Account::::get(id, who).map(|a| a.extra).unwrap_or_default() } fn try_mutate_exists>( @@ -34,13 +30,13 @@ impl, I: 'static> StoredMap<(T::AssetId, T::AccountId), T::Extra> f f: impl FnOnce(&mut Option) -> Result, ) -> Result { let &(id, ref who) = id_who; - let mut maybe_extra = Some(Account::::get(id, who).extra); + let mut maybe_extra = Account::::get(id, who).map(|a| a.extra); let r = f(&mut maybe_extra)?; // They want to write some value or delete it. // If the account existed and they want to write a value, then we write. // If the account didn't exist and they want to delete it, then we let it pass. // Otherwise, we fail. - Account::::try_mutate_exists(id, who, |maybe_account| { + Account::::try_mutate(id, who, |maybe_account| { if let Some(extra) = maybe_extra { // They want to write a value. Let this happen only if the account actually exists. if let Some(ref mut account) = maybe_account { diff --git a/frame/assets/src/lib.rs b/frame/assets/src/lib.rs index 940120954f96..b86661d9fa4f 100644 --- a/frame/assets/src/lib.rs +++ b/frame/assets/src/lib.rs @@ -212,6 +212,11 @@ pub mod pallet { #[pallet::constant] type AssetDeposit: Get>; + /// The amount of funds that must be reserved for a non-provider asset account to be + /// maintained. + #[pallet::constant] + type AssetAccountDeposit: Get>; + /// The basic amount of funds that must be reserved when adding metadata to your asset. #[pallet::constant] type MetadataDepositBase: Get>; @@ -250,15 +255,15 @@ pub mod pallet { >; #[pallet::storage] - /// The number of units of assets held by any given account. + /// The holdings of a specific account for a specific asset. pub(super) type Account, I: 'static = ()> = StorageDoubleMap< _, Blake2_128Concat, T::AssetId, Blake2_128Concat, T::AccountId, - AssetBalance, - ValueQuery, + AssetAccountOf, + OptionQuery, GetDefault, ConstU32<300_000>, >; @@ -448,8 +453,8 @@ pub mod pallet { pub enum Error { /// Account balance must be greater than or equal to the transfer amount. BalanceLow, - /// Balance should be non-zero. - BalanceZero, + /// The account to alter does not exist. + NoAccount, /// The signing account has no permission to do the operation. NoPermission, /// The given asset ID is unknown. @@ -471,6 +476,12 @@ pub mod pallet { Unapproved, /// The source account would not survive the transfer and it needs to stay alive. WouldDie, + /// The asset-account already exists. + AlreadyExists, + /// The asset-account doesn't have an associated deposit. + NoDeposit, + /// The operation would result in funds being burned. + WouldBurn, } #[pallet::call] @@ -633,7 +644,7 @@ pub mod pallet { /// /// Origin must be Signed and the sender should be the Manager of the asset `id`. /// - /// Bails with `BalanceZero` if the `who` is already dead. + /// Bails with `NoAccount` if the `who` is already dead. /// /// - `id`: The identifier of the asset to have some amount burned. /// - `who`: The account to be debited from. @@ -779,9 +790,11 @@ pub mod pallet { let d = Asset::::get(id).ok_or(Error::::Unknown)?; ensure!(&origin == &d.freezer, Error::::NoPermission); let who = T::Lookup::lookup(who)?; - ensure!(Account::::contains_key(id, &who), Error::::BalanceZero); - Account::::mutate(id, &who, |a| a.is_frozen = true); + Account::::try_mutate(id, &who, |maybe_account| -> DispatchResult { + maybe_account.as_mut().ok_or(Error::::NoAccount)?.is_frozen = true; + Ok(()) + })?; Self::deposit_event(Event::::Frozen { asset_id: id, who }); Ok(()) @@ -808,9 +821,11 @@ pub mod pallet { let details = Asset::::get(id).ok_or(Error::::Unknown)?; ensure!(&origin == &details.admin, Error::::NoPermission); let who = T::Lookup::lookup(who)?; - ensure!(Account::::contains_key(id, &who), Error::::BalanceZero); - Account::::mutate(id, &who, |a| a.is_frozen = false); + Account::::try_mutate(id, &who, |maybe_account| -> DispatchResult { + maybe_account.as_mut().ok_or(Error::::NoAccount)?.is_frozen = false; + Ok(()) + })?; Self::deposit_event(Event::::Thawed { asset_id: id, who }); Ok(()) @@ -1274,5 +1289,36 @@ pub mod pallet { let destination = T::Lookup::lookup(destination)?; Self::do_transfer_approved(id, &owner, &delegate, &destination, amount) } + + /// Create an asset account for non-provider assets. + /// + /// A deposit will be taken from the signer account. + /// + /// - `origin`: Must be Signed; the signer account must have sufficient funds for a deposit + /// to be taken. + /// - `id`: The identifier of the asset for the account to be created. + /// + /// Emits `Touched` event when successful. + #[pallet::weight(T::WeightInfo::mint())] + pub fn touch(origin: OriginFor, #[pallet::compact] id: T::AssetId) -> DispatchResult { + Self::do_touch(id, ensure_signed(origin)?) + } + + /// Return the deposit (if any) of an asset account. + /// + /// The origin must be Signed. + /// + /// - `id`: The identifier of the asset for the account to be created. + /// - `allow_burn`: If `true` then assets may be destroyed in order to complete the refund. + /// + /// Emits `Refunded` event when successful. + #[pallet::weight(T::WeightInfo::mint())] + pub fn refund( + origin: OriginFor, + #[pallet::compact] id: T::AssetId, + allow_burn: bool, + ) -> DispatchResult { + Self::do_refund(id, ensure_signed(origin)?, allow_burn) + } } } diff --git a/frame/assets/src/mock.rs b/frame/assets/src/mock.rs index aedf437ee843..1e88421dd5ac 100644 --- a/frame/assets/src/mock.rs +++ b/frame/assets/src/mock.rs @@ -20,7 +20,10 @@ use super::*; use crate as pallet_assets; -use frame_support::{construct_runtime, parameter_types, traits::GenesisBuild}; +use frame_support::{ + construct_runtime, + traits::{ConstU32, ConstU64, GenesisBuild}, +}; use sp_core::H256; use sp_runtime::{ testing::Header, @@ -42,9 +45,6 @@ construct_runtime!( } ); -parameter_types! { - pub const BlockHashCount: u64 = 250; -} impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); @@ -59,7 +59,7 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type DbWeight = (); type Version = (); type PalletInfo = PalletInfo; @@ -69,17 +69,14 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); -} - -parameter_types! { - pub const ExistentialDeposit: u64 = 1; + type MaxConsumers = ConstU32<2>; } impl pallet_balances::Config for Test { type Balance = u64; type DustRemoval = (); type Event = Event; - type ExistentialDeposit = ExistentialDeposit; + type ExistentialDeposit = ConstU64<1>; type AccountStore = System; type WeightInfo = (); type MaxLocks = (); @@ -87,25 +84,18 @@ impl pallet_balances::Config for Test { type ReserveIdentifier = [u8; 8]; } -parameter_types! { - pub const AssetDeposit: u64 = 1; - pub const ApprovalDeposit: u64 = 1; - pub const StringLimit: u32 = 50; - pub const MetadataDepositBase: u64 = 1; - pub const MetadataDepositPerByte: u64 = 1; -} - impl Config for Test { type Event = Event; type Balance = u64; type AssetId = u32; type Currency = Balances; type ForceOrigin = frame_system::EnsureRoot; - type AssetDeposit = AssetDeposit; - type MetadataDepositBase = MetadataDepositBase; - type MetadataDepositPerByte = MetadataDepositPerByte; - type ApprovalDeposit = ApprovalDeposit; - type StringLimit = StringLimit; + type AssetDeposit = ConstU64<1>; + type AssetAccountDeposit = ConstU64<10>; + type MetadataDepositBase = ConstU64<1>; + type MetadataDepositPerByte = ConstU64<1>; + type ApprovalDeposit = ConstU64<1>; + type StringLimit = ConstU32<50>; type Freezer = TestFreezer; type WeightInfo = (); type Extra = (); diff --git a/frame/assets/src/tests.rs b/frame/assets/src/tests.rs index e24a1d45215d..a3eacdda4452 100644 --- a/frame/assets/src/tests.rs +++ b/frame/assets/src/tests.rs @@ -34,6 +34,97 @@ fn basic_minting_should_work() { }); } +#[test] +fn minting_too_many_insufficient_assets_fails() { + new_test_ext().execute_with(|| { + assert_ok!(Assets::force_create(Origin::root(), 0, 1, false, 1)); + assert_ok!(Assets::force_create(Origin::root(), 1, 1, false, 1)); + assert_ok!(Assets::force_create(Origin::root(), 2, 1, false, 1)); + Balances::make_free_balance_be(&1, 100); + assert_ok!(Assets::mint(Origin::signed(1), 0, 1, 100)); + assert_ok!(Assets::mint(Origin::signed(1), 1, 1, 100)); + assert_noop!(Assets::mint(Origin::signed(1), 2, 1, 100), TokenError::CannotCreate); + + Balances::make_free_balance_be(&2, 1); + assert_ok!(Assets::transfer(Origin::signed(1), 0, 2, 100)); + assert_ok!(Assets::mint(Origin::signed(1), 2, 1, 100)); + }); +} + +#[test] +fn minting_insufficient_asset_with_deposit_should_work_when_consumers_exhausted() { + new_test_ext().execute_with(|| { + assert_ok!(Assets::force_create(Origin::root(), 0, 1, false, 1)); + assert_ok!(Assets::force_create(Origin::root(), 1, 1, false, 1)); + assert_ok!(Assets::force_create(Origin::root(), 2, 1, false, 1)); + Balances::make_free_balance_be(&1, 100); + assert_ok!(Assets::mint(Origin::signed(1), 0, 1, 100)); + assert_ok!(Assets::mint(Origin::signed(1), 1, 1, 100)); + assert_noop!(Assets::mint(Origin::signed(1), 2, 1, 100), TokenError::CannotCreate); + + assert_ok!(Assets::touch(Origin::signed(1), 2)); + assert_eq!(Balances::reserved_balance(&1), 10); + + assert_ok!(Assets::mint(Origin::signed(1), 2, 1, 100)); + }); +} + +#[test] +fn minting_insufficient_assets_with_deposit_without_consumer_should_work() { + new_test_ext().execute_with(|| { + assert_ok!(Assets::force_create(Origin::root(), 0, 1, false, 1)); + assert_noop!(Assets::mint(Origin::signed(1), 0, 1, 100), TokenError::CannotCreate); + Balances::make_free_balance_be(&1, 100); + assert_ok!(Assets::touch(Origin::signed(1), 0)); + assert_ok!(Assets::mint(Origin::signed(1), 0, 1, 100)); + assert_eq!(Balances::reserved_balance(&1), 10); + assert_eq!(System::consumers(&1), 0); + }); +} + +#[test] +fn refunding_asset_deposit_with_burn_should_work() { + new_test_ext().execute_with(|| { + assert_ok!(Assets::force_create(Origin::root(), 0, 1, false, 1)); + Balances::make_free_balance_be(&1, 100); + assert_ok!(Assets::touch(Origin::signed(1), 0)); + assert_ok!(Assets::mint(Origin::signed(1), 0, 1, 100)); + assert_ok!(Assets::refund(Origin::signed(1), 0, true)); + assert_eq!(Balances::reserved_balance(&1), 0); + assert_eq!(Assets::balance(1, 0), 0); + }); +} + +#[test] +fn refunding_asset_deposit_with_burn_disallowed_should_fail() { + new_test_ext().execute_with(|| { + assert_ok!(Assets::force_create(Origin::root(), 0, 1, false, 1)); + Balances::make_free_balance_be(&1, 100); + assert_ok!(Assets::touch(Origin::signed(1), 0)); + assert_ok!(Assets::mint(Origin::signed(1), 0, 1, 100)); + assert_noop!(Assets::refund(Origin::signed(1), 0, false), Error::::WouldBurn); + }); +} + +#[test] +fn refunding_asset_deposit_without_burn_should_work() { + new_test_ext().execute_with(|| { + assert_ok!(Assets::force_create(Origin::root(), 0, 1, false, 1)); + assert_noop!(Assets::mint(Origin::signed(1), 0, 1, 100), TokenError::CannotCreate); + Balances::make_free_balance_be(&1, 100); + assert_ok!(Assets::touch(Origin::signed(1), 0)); + assert_ok!(Assets::mint(Origin::signed(1), 0, 1, 100)); + Balances::make_free_balance_be(&2, 100); + assert_ok!(Assets::transfer(Origin::signed(1), 0, 2, 100)); + assert_eq!(Assets::balance(0, 2), 100); + assert_eq!(Assets::balance(0, 1), 0); + assert_eq!(Balances::reserved_balance(&1), 10); + assert_ok!(Assets::refund(Origin::signed(1), 0, false)); + assert_eq!(Balances::reserved_balance(&1), 0); + assert_eq!(Assets::balance(1, 0), 0); + }); +} + #[test] fn approval_lifecycle_works() { new_test_ext().execute_with(|| { @@ -299,17 +390,17 @@ fn min_balance_should_work() { // When deducting from an account to below minimum, it should be reaped. assert_ok!(Assets::transfer(Origin::signed(1), 0, 2, 91)); - assert!(Assets::balance(0, 1).is_zero()); + assert!(Assets::maybe_balance(0, 1).is_none()); assert_eq!(Assets::balance(0, 2), 100); assert_eq!(Asset::::get(0).unwrap().accounts, 1); assert_ok!(Assets::force_transfer(Origin::signed(1), 0, 2, 1, 91)); - assert!(Assets::balance(0, 2).is_zero()); + assert!(Assets::maybe_balance(0, 2).is_none()); assert_eq!(Assets::balance(0, 1), 100); assert_eq!(Asset::::get(0).unwrap().accounts, 1); assert_ok!(Assets::burn(Origin::signed(1), 0, 1, 91)); - assert!(Assets::balance(0, 1).is_zero()); + assert!(Assets::maybe_balance(0, 1).is_none()); assert_eq!(Asset::::get(0).unwrap().accounts, 0); }); } @@ -488,7 +579,7 @@ fn transferring_amount_more_than_available_balance_should_not_work() { assert_eq!(Assets::balance(0, 2), 50); assert_ok!(Assets::burn(Origin::signed(1), 0, 1, u64::MAX)); assert_eq!(Assets::balance(0, 1), 0); - assert_noop!(Assets::transfer(Origin::signed(1), 0, 1, 50), Error::::BalanceLow); + assert_noop!(Assets::transfer(Origin::signed(1), 0, 1, 50), Error::::NoAccount); assert_noop!(Assets::transfer(Origin::signed(2), 0, 1, 51), Error::::BalanceLow); }); } @@ -536,7 +627,7 @@ fn burning_asset_balance_with_zero_balance_does_nothing() { assert_ok!(Assets::force_create(Origin::root(), 0, 1, true, 1)); assert_ok!(Assets::mint(Origin::signed(1), 0, 1, 100)); assert_eq!(Assets::balance(0, 2), 0); - assert_ok!(Assets::burn(Origin::signed(1), 0, 2, u64::MAX)); + assert_noop!(Assets::burn(Origin::signed(1), 0, 2, u64::MAX), Error::::NoAccount); assert_eq!(Assets::balance(0, 2), 0); assert_eq!(Assets::total_supply(0), 100); }); @@ -688,7 +779,7 @@ fn force_metadata_should_work() { ); // string length limit check - let limit = StringLimit::get() as usize; + let limit = 50usize; assert_noop!( Assets::force_set_metadata( Origin::root(), diff --git a/frame/assets/src/types.rs b/frame/assets/src/types.rs index 16f7368f12b7..ecf5f5edf417 100644 --- a/frame/assets/src/types.rs +++ b/frame/assets/src/types.rs @@ -26,6 +26,8 @@ use sp_runtime::{traits::Convert, FixedPointNumber, FixedPointOperand, FixedU128 pub(super) type DepositBalanceOf = <>::Currency as Currency<::AccountId>>::Balance; +pub(super) type AssetAccountOf = + AssetAccount<>::Balance, DepositBalanceOf, >::Extra>; #[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, MaxEncodedLen, TypeInfo)] pub struct AssetDetails { @@ -76,14 +78,47 @@ pub struct Approval { pub(super) deposit: DepositBalance, } -#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, Default, MaxEncodedLen, TypeInfo)] -pub struct AssetBalance { +#[test] +fn ensure_bool_decodes_to_consumer_or_sufficient() { + assert_eq!(false.encode(), ExistenceReason::<()>::Consumer.encode()); + assert_eq!(true.encode(), ExistenceReason::<()>::Sufficient.encode()); +} + +#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, MaxEncodedLen, TypeInfo)] +pub enum ExistenceReason { + #[codec(index = 0)] + Consumer, + #[codec(index = 1)] + Sufficient, + #[codec(index = 2)] + DepositHeld(Balance), + #[codec(index = 3)] + DepositRefunded, +} + +impl ExistenceReason { + pub(crate) fn take_deposit(&mut self) -> Option { + if !matches!(self, ExistenceReason::DepositHeld(_)) { + return None + } + if let ExistenceReason::DepositHeld(deposit) = + sp_std::mem::replace(self, ExistenceReason::DepositRefunded) + { + return Some(deposit) + } else { + return None + } + } +} + +#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, MaxEncodedLen, TypeInfo)] +pub struct AssetAccount { /// The balance. pub(super) balance: Balance, /// Whether the account is frozen. pub(super) is_frozen: bool, - /// `true` if this balance gave the account a self-sufficient reference. - pub(super) sufficient: bool, + /// The reason for the existence of the account. + pub(super) reason: ExistenceReason, /// Additional "sidecar" data, in case some other pallet wants to use this storage item. pub(super) extra: Extra, } @@ -124,12 +159,15 @@ pub struct DestroyWitness { pub trait FrozenBalance { /// Return the frozen balance. /// + /// Generally, the balance of every account must be at least the sum of this (if `Some`) and + /// the asset's `minimum_balance` (the latter since there may be complications to destroying an + /// asset's account completely). + /// /// Under normal behaviour, the account balance should not go below the sum of this (if `Some`) - /// and the asset's minimum balance. - /// But the account balance can be below this sum (e.g. if less than the sum has been - /// transfered to the account). + /// and the asset's minimum balance. However, the account balance may reasonably begin below + /// this sum (e.g. if less than the sum had ever been transfered into the account). /// - /// In special case (privileged intervention) the account balance can go below the sum. + /// In special cases (privileged intervention) the account balance may also go below the sum. /// /// If `None` is returned, then nothing special is enforced. fn frozen_balance(asset: AssetId, who: &AccountId) -> Option; diff --git a/frame/atomic-swap/src/tests.rs b/frame/atomic-swap/src/tests.rs index a76d0f20ffa3..47e33252e094 100644 --- a/frame/atomic-swap/src/tests.rs +++ b/frame/atomic-swap/src/tests.rs @@ -54,6 +54,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { pub const ExistentialDeposit: u64 = 1; diff --git a/frame/aura/src/mock.rs b/frame/aura/src/mock.rs index 4418d9e85ae2..12748bd212d3 100644 --- a/frame/aura/src/mock.rs +++ b/frame/aura/src/mock.rs @@ -78,6 +78,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } impl pallet_timestamp::Config for Test { diff --git a/frame/authority-discovery/src/lib.rs b/frame/authority-discovery/src/lib.rs index a6609860d7cf..c867f98af3e1 100644 --- a/frame/authority-discovery/src/lib.rs +++ b/frame/authority-discovery/src/lib.rs @@ -260,6 +260,7 @@ mod tests { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } pub struct TestSessionHandler; diff --git a/frame/authorship/src/lib.rs b/frame/authorship/src/lib.rs index 5d36adabe888..cd91957475a1 100644 --- a/frame/authorship/src/lib.rs +++ b/frame/authorship/src/lib.rs @@ -458,6 +458,7 @@ mod tests { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { diff --git a/frame/babe/src/mock.rs b/frame/babe/src/mock.rs index f62e73aa4391..f3325d0c65a0 100644 --- a/frame/babe/src/mock.rs +++ b/frame/babe/src/mock.rs @@ -96,6 +96,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } impl frame_system::offchain::SendTransactionTypes for Test diff --git a/frame/bags-list/src/mock.rs b/frame/bags-list/src/mock.rs index 6545e563a3ef..90d5347b1242 100644 --- a/frame/bags-list/src/mock.rs +++ b/frame/bags-list/src/mock.rs @@ -68,6 +68,7 @@ impl frame_system::Config for Runtime { type OnKilledAccount = (); type SystemWeightInfo = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { diff --git a/frame/balances/src/tests_composite.rs b/frame/balances/src/tests_composite.rs index 60feedb326d8..b1a7f2417df8 100644 --- a/frame/balances/src/tests_composite.rs +++ b/frame/balances/src/tests_composite.rs @@ -73,6 +73,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { pub const TransactionByteFee: u64 = 1; diff --git a/frame/balances/src/tests_local.rs b/frame/balances/src/tests_local.rs index a861df4746a1..ff08e6356201 100644 --- a/frame/balances/src/tests_local.rs +++ b/frame/balances/src/tests_local.rs @@ -75,6 +75,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { pub const TransactionByteFee: u64 = 1; diff --git a/frame/balances/src/tests_reentrancy.rs b/frame/balances/src/tests_reentrancy.rs index 43edd16baf3b..01b02943484b 100644 --- a/frame/balances/src/tests_reentrancy.rs +++ b/frame/balances/src/tests_reentrancy.rs @@ -77,6 +77,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { pub const TransactionByteFee: u64 = 1; diff --git a/frame/beefy-mmr/src/mock.rs b/frame/beefy-mmr/src/mock.rs index 95b87c360510..f1195dcc9c02 100644 --- a/frame/beefy-mmr/src/mock.rs +++ b/frame/beefy-mmr/src/mock.rs @@ -86,6 +86,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = SS58Prefix; type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { diff --git a/frame/beefy/src/mock.rs b/frame/beefy/src/mock.rs index a1fbeda4ab35..3ce582b29d22 100644 --- a/frame/beefy/src/mock.rs +++ b/frame/beefy/src/mock.rs @@ -84,6 +84,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = SS58Prefix; type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } impl pallet_beefy::Config for Test { diff --git a/frame/benchmarking/src/baseline.rs b/frame/benchmarking/src/baseline.rs index 87cdf80409b8..e2f9f1f2975f 100644 --- a/frame/benchmarking/src/baseline.rs +++ b/frame/benchmarking/src/baseline.rs @@ -195,6 +195,7 @@ pub mod mock { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } impl super::Config for Test {} diff --git a/frame/benchmarking/src/tests.rs b/frame/benchmarking/src/tests.rs index a2cf381e6ecf..e27b3e09dbed 100644 --- a/frame/benchmarking/src/tests.rs +++ b/frame/benchmarking/src/tests.rs @@ -108,6 +108,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { diff --git a/frame/benchmarking/src/tests_instance.rs b/frame/benchmarking/src/tests_instance.rs index 0ad156ce5a88..09d11eb6c58d 100644 --- a/frame/benchmarking/src/tests_instance.rs +++ b/frame/benchmarking/src/tests_instance.rs @@ -110,6 +110,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { diff --git a/frame/bounties/src/tests.rs b/frame/bounties/src/tests.rs index bbcf9d6d9e72..ac1f104119df 100644 --- a/frame/bounties/src/tests.rs +++ b/frame/bounties/src/tests.rs @@ -84,6 +84,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { pub const ExistentialDeposit: u64 = 1; diff --git a/frame/child-bounties/src/tests.rs b/frame/child-bounties/src/tests.rs index ada13e968c4d..8e2569738b1f 100644 --- a/frame/child-bounties/src/tests.rs +++ b/frame/child-bounties/src/tests.rs @@ -86,6 +86,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { pub const ExistentialDeposit: u64 = 1; diff --git a/frame/collective/src/tests.rs b/frame/collective/src/tests.rs index cbd2f68ac73e..466cdb3eeeb5 100644 --- a/frame/collective/src/tests.rs +++ b/frame/collective/src/tests.rs @@ -115,6 +115,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } impl Config for Test { type Origin = Origin; diff --git a/frame/contracts/src/tests.rs b/frame/contracts/src/tests.rs index f19f5a315955..1554d1230089 100644 --- a/frame/contracts/src/tests.rs +++ b/frame/contracts/src/tests.rs @@ -206,6 +206,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } impl pallet_randomness_collective_flip::Config for Test {} impl pallet_balances::Config for Test { diff --git a/frame/democracy/src/tests.rs b/frame/democracy/src/tests.rs index 06c4ac666cfb..3c223172987e 100644 --- a/frame/democracy/src/tests.rs +++ b/frame/democracy/src/tests.rs @@ -105,6 +105,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { pub MaximumSchedulerWeight: Weight = Perbill::from_percent(80) * BlockWeights::get().max_block; diff --git a/frame/election-provider-multi-phase/src/mock.rs b/frame/election-provider-multi-phase/src/mock.rs index f90c64b75ccb..3ac14b89e795 100644 --- a/frame/election-provider-multi-phase/src/mock.rs +++ b/frame/election-provider-multi-phase/src/mock.rs @@ -218,6 +218,7 @@ impl frame_system::Config for Runtime { type OnKilledAccount = (); type SystemWeightInfo = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); diff --git a/frame/election-provider-support/src/onchain.rs b/frame/election-provider-support/src/onchain.rs index 6379adae4206..a2eb53edcf84 100644 --- a/frame/election-provider-support/src/onchain.rs +++ b/frame/election-provider-support/src/onchain.rs @@ -145,6 +145,7 @@ mod tests { type OnKilledAccount = (); type SystemWeightInfo = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } impl Config for Runtime { diff --git a/frame/elections-phragmen/src/lib.rs b/frame/elections-phragmen/src/lib.rs index 116c0937bf98..8daa4e7fe13c 100644 --- a/frame/elections-phragmen/src/lib.rs +++ b/frame/elections-phragmen/src/lib.rs @@ -1150,6 +1150,7 @@ mod tests { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { diff --git a/frame/elections/src/mock.rs b/frame/elections/src/mock.rs index 91318e1e07bc..bce60534a352 100644 --- a/frame/elections/src/mock.rs +++ b/frame/elections/src/mock.rs @@ -60,6 +60,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { diff --git a/frame/examples/basic/src/tests.rs b/frame/examples/basic/src/tests.rs index e069cccf8d80..b97083f27d5e 100644 --- a/frame/examples/basic/src/tests.rs +++ b/frame/examples/basic/src/tests.rs @@ -79,6 +79,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { pub const ExistentialDeposit: u64 = 1; diff --git a/frame/examples/offchain-worker/src/tests.rs b/frame/examples/offchain-worker/src/tests.rs index 1dde8a1df60c..9fb965784f18 100644 --- a/frame/examples/offchain-worker/src/tests.rs +++ b/frame/examples/offchain-worker/src/tests.rs @@ -77,6 +77,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } type Extrinsic = TestXt; diff --git a/frame/examples/parallel/src/tests.rs b/frame/examples/parallel/src/tests.rs index 4c36f0d6eb85..5de9af878723 100644 --- a/frame/examples/parallel/src/tests.rs +++ b/frame/examples/parallel/src/tests.rs @@ -68,6 +68,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { diff --git a/frame/executive/src/lib.rs b/frame/executive/src/lib.rs index 9b81527fadb3..7ff5584879ce 100644 --- a/frame/executive/src/lib.rs +++ b/frame/executive/src/lib.rs @@ -767,6 +767,7 @@ mod tests { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } type Balance = u64; diff --git a/frame/gilt/src/mock.rs b/frame/gilt/src/mock.rs index ac3f4df1b71d..9ea33a6d6b68 100644 --- a/frame/gilt/src/mock.rs +++ b/frame/gilt/src/mock.rs @@ -74,6 +74,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = SS58Prefix; type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { diff --git a/frame/grandpa/src/mock.rs b/frame/grandpa/src/mock.rs index fe7a530ffe0c..aed13ec3717a 100644 --- a/frame/grandpa/src/mock.rs +++ b/frame/grandpa/src/mock.rs @@ -98,6 +98,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } impl frame_system::offchain::SendTransactionTypes for Test diff --git a/frame/identity/src/tests.rs b/frame/identity/src/tests.rs index 31b93e70fd3d..2faf65f560a8 100644 --- a/frame/identity/src/tests.rs +++ b/frame/identity/src/tests.rs @@ -75,6 +75,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { pub const ExistentialDeposit: u64 = 1; diff --git a/frame/im-online/src/mock.rs b/frame/im-online/src/mock.rs index 1e4d4b43d578..1d985b9007ea 100644 --- a/frame/im-online/src/mock.rs +++ b/frame/im-online/src/mock.rs @@ -139,6 +139,7 @@ impl frame_system::Config for Runtime { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { diff --git a/frame/indices/src/mock.rs b/frame/indices/src/mock.rs index f4c87016141b..3e3aed2986b9 100644 --- a/frame/indices/src/mock.rs +++ b/frame/indices/src/mock.rs @@ -69,6 +69,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { diff --git a/frame/lottery/src/mock.rs b/frame/lottery/src/mock.rs index d1f090aa26dc..df86e063c477 100644 --- a/frame/lottery/src/mock.rs +++ b/frame/lottery/src/mock.rs @@ -79,6 +79,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { diff --git a/frame/membership/src/lib.rs b/frame/membership/src/lib.rs index 6cd8c13f39af..4bcc28c0ef46 100644 --- a/frame/membership/src/lib.rs +++ b/frame/membership/src/lib.rs @@ -560,6 +560,7 @@ mod tests { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } ord_parameter_types! { pub const One: u64 = 1; diff --git a/frame/merkle-mountain-range/src/mock.rs b/frame/merkle-mountain-range/src/mock.rs index 3616a8d1d524..392ae5050a96 100644 --- a/frame/merkle-mountain-range/src/mock.rs +++ b/frame/merkle-mountain-range/src/mock.rs @@ -69,6 +69,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } impl Config for Test { diff --git a/frame/multisig/src/tests.rs b/frame/multisig/src/tests.rs index 523aefd1e753..f050ac9d7200 100644 --- a/frame/multisig/src/tests.rs +++ b/frame/multisig/src/tests.rs @@ -74,6 +74,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { pub const ExistentialDeposit: u64 = 1; diff --git a/frame/nicks/src/lib.rs b/frame/nicks/src/lib.rs index bfc23187fc5b..ea58ea693d3f 100644 --- a/frame/nicks/src/lib.rs +++ b/frame/nicks/src/lib.rs @@ -297,6 +297,7 @@ mod tests { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { pub const ExistentialDeposit: u64 = 1; diff --git a/frame/node-authorization/src/mock.rs b/frame/node-authorization/src/mock.rs index 6c79f601c197..8e2bc7cfd2a6 100644 --- a/frame/node-authorization/src/mock.rs +++ b/frame/node-authorization/src/mock.rs @@ -71,6 +71,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } ord_parameter_types! { diff --git a/frame/offences/benchmarking/src/mock.rs b/frame/offences/benchmarking/src/mock.rs index 26a53c7f8a04..ab2b3569228c 100644 --- a/frame/offences/benchmarking/src/mock.rs +++ b/frame/offences/benchmarking/src/mock.rs @@ -63,6 +63,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { pub const ExistentialDeposit: Balance = 10; diff --git a/frame/offences/src/mock.rs b/frame/offences/src/mock.rs index bce51f527abc..c2db42ec72fa 100644 --- a/frame/offences/src/mock.rs +++ b/frame/offences/src/mock.rs @@ -112,6 +112,7 @@ impl frame_system::Config for Runtime { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } impl Config for Runtime { diff --git a/frame/proxy/src/tests.rs b/frame/proxy/src/tests.rs index d3565525910f..538527d47ecd 100644 --- a/frame/proxy/src/tests.rs +++ b/frame/proxy/src/tests.rs @@ -78,6 +78,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { pub const ExistentialDeposit: u64 = 1; diff --git a/frame/randomness-collective-flip/src/lib.rs b/frame/randomness-collective-flip/src/lib.rs index 345b8072c5e4..eee70984f257 100644 --- a/frame/randomness-collective-flip/src/lib.rs +++ b/frame/randomness-collective-flip/src/lib.rs @@ -219,6 +219,7 @@ mod tests { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } impl pallet_randomness_collective_flip::Config for Test {} diff --git a/frame/recovery/src/mock.rs b/frame/recovery/src/mock.rs index f6d4a6b15943..1bd7507436b7 100644 --- a/frame/recovery/src/mock.rs +++ b/frame/recovery/src/mock.rs @@ -75,6 +75,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { diff --git a/frame/scheduler/src/lib.rs b/frame/scheduler/src/lib.rs index 260ef90b0537..02bcb5eb3109 100644 --- a/frame/scheduler/src/lib.rs +++ b/frame/scheduler/src/lib.rs @@ -932,6 +932,7 @@ mod tests { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } impl logger::Config for Test { type Event = Event; diff --git a/frame/scored-pool/src/mock.rs b/frame/scored-pool/src/mock.rs index 5c5425ae2bdd..992aecba38e8 100644 --- a/frame/scored-pool/src/mock.rs +++ b/frame/scored-pool/src/mock.rs @@ -81,6 +81,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } impl pallet_balances::Config for Test { diff --git a/frame/session/benchmarking/src/mock.rs b/frame/session/benchmarking/src/mock.rs index e000255b84b8..3f3b103905b5 100644 --- a/frame/session/benchmarking/src/mock.rs +++ b/frame/session/benchmarking/src/mock.rs @@ -68,6 +68,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { pub const ExistentialDeposit: Balance = 10; diff --git a/frame/session/src/mock.rs b/frame/session/src/mock.rs index 6db7727fa539..d0511d393682 100644 --- a/frame/session/src/mock.rs +++ b/frame/session/src/mock.rs @@ -264,6 +264,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } impl pallet_timestamp::Config for Test { diff --git a/frame/society/src/mock.rs b/frame/society/src/mock.rs index 9356c083f233..4348f2378c42 100644 --- a/frame/society/src/mock.rs +++ b/frame/society/src/mock.rs @@ -89,6 +89,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } impl pallet_balances::Config for Test { diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index 8a8ab1f1e4d0..89ab86259b95 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -150,6 +150,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } impl pallet_balances::Config for Test { type MaxLocks = MaxLocks; diff --git a/frame/sudo/src/mock.rs b/frame/sudo/src/mock.rs index bfbed0d38ab3..88379d0e5fda 100644 --- a/frame/sudo/src/mock.rs +++ b/frame/sudo/src/mock.rs @@ -144,6 +144,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } // Implement the logger module's `Config` on the Test runtime. diff --git a/frame/support/src/traits.rs b/frame/support/src/traits.rs index 9b5453c0a01a..3c1f268ade07 100644 --- a/frame/support/src/traits.rs +++ b/frame/support/src/traits.rs @@ -50,9 +50,10 @@ pub use filter::{ClearFilterGuard, FilterStack, FilterStackGuard, InstanceFilter mod misc; pub use misc::{ - Backing, ConstU32, EnsureInherentsAreFirst, EqualPrivilegeOnly, EstimateCallFee, ExecuteBlock, - ExtrinsicCall, Get, GetBacking, GetDefault, HandleLifetime, IsSubType, IsType, Len, - OffchainWorker, OnKilledAccount, OnNewAccount, PrivilegeCmp, SameOrOther, Time, TryDrop, + Backing, ConstBool, ConstI128, ConstI16, ConstI32, ConstI64, ConstI8, ConstU128, ConstU16, + ConstU32, ConstU64, ConstU8, EnsureInherentsAreFirst, EqualPrivilegeOnly, EstimateCallFee, + ExecuteBlock, ExtrinsicCall, Get, GetBacking, GetDefault, HandleLifetime, IsSubType, IsType, + Len, OffchainWorker, OnKilledAccount, OnNewAccount, PrivilegeCmp, SameOrOther, Time, TryDrop, UnixTime, WrapperKeepOpaque, WrapperOpaque, }; diff --git a/frame/support/src/traits/misc.rs b/frame/support/src/traits/misc.rs index 153c3804bd59..165a83b4be2a 100644 --- a/frame/support/src/traits/misc.rs +++ b/frame/support/src/traits/misc.rs @@ -60,20 +60,33 @@ impl Get for GetDefault { } } -/// Implement `Get` and `Get>` using the given const. -pub struct ConstU32; - -impl Get for ConstU32 { - fn get() -> u32 { - T - } -} - -impl Get> for ConstU32 { - fn get() -> Option { - Some(T) - } -} +macro_rules! impl_const_get { + ($name:ident, $t:ty) => { + pub struct $name; + impl Get<$t> for $name { + fn get() -> $t { + T + } + } + impl Get> for $name { + fn get() -> Option<$t> { + Some(T) + } + } + }; +} + +impl_const_get!(ConstBool, bool); +impl_const_get!(ConstU8, u8); +impl_const_get!(ConstU16, u16); +impl_const_get!(ConstU32, u32); +impl_const_get!(ConstU64, u64); +impl_const_get!(ConstU128, u128); +impl_const_get!(ConstI8, i8); +impl_const_get!(ConstI16, i16); +impl_const_get!(ConstI32, i32); +impl_const_get!(ConstI64, i64); +impl_const_get!(ConstI128, i128); /// A type for which some values make sense to be able to drop without further consideration. pub trait TryDrop: Sized { diff --git a/frame/support/test/compile_pass/Cargo.toml b/frame/support/test/compile_pass/Cargo.toml index 62472a8957ce..aa53f7ad358d 100644 --- a/frame/support/test/compile_pass/Cargo.toml +++ b/frame/support/test/compile_pass/Cargo.toml @@ -17,14 +17,17 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] sp-core = { version = "4.0.0", default-features = false, path = "../../../../primitives/core" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/runtime" } sp-version = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/version" } -support = { package = "frame-support", version = "4.0.0-dev", default-features = false, path = "../../" } -system = { package = "frame-system", version = "4.0.0-dev", default-features = false, path = "../../../system" } +frame-support = { version = "4.0.0-dev", default-features = false, path = "../../" } +frame-system = { version = "4.0.0-dev", default-features = false, path = "../../../system" } [features] default = ["std"] std = [ "codec/std", "scale-info/std", - "support/std", - "system/std", + "sp-core/std", + "sp-runtime/std", + "sp-version/std", + "frame-support/std", + "frame-system/std", ] diff --git a/frame/support/test/compile_pass/src/lib.rs b/frame/support/test/compile_pass/src/lib.rs index 17ba40574adf..06fb6345d3c8 100644 --- a/frame/support/test/compile_pass/src/lib.rs +++ b/frame/support/test/compile_pass/src/lib.rs @@ -22,13 +22,13 @@ //! This crate tests that `construct_runtime!` expands the pallet parts //! correctly even when frame-support is renamed in Cargo.toml +use frame_support::{construct_runtime, parameter_types}; use sp_core::{sr25519, H256}; use sp_runtime::{ create_runtime_str, generic, traits::{BlakeTwo256, IdentityLookup, Verify}, }; use sp_version::RuntimeVersion; -use support::{construct_runtime, parameter_types}; pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("frame-support-test-compile-pass"), @@ -51,8 +51,8 @@ parameter_types! { pub const SS58Prefix: u8 = 0; } -impl system::Config for Runtime { - type BaseCallFilter = support::traits::Everything; +impl frame_system::Config for Runtime { + type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); type BlockLength = (); type Index = u128; @@ -73,6 +73,7 @@ impl system::Config for Runtime { type OnNewAccount = (); type OnKilledAccount = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; type SystemWeightInfo = (); type SS58Prefix = SS58Prefix; } @@ -87,6 +88,6 @@ construct_runtime!( NodeBlock = Block, UncheckedExtrinsic = UncheckedExtrinsic { - System: system, + System: frame_system, } ); diff --git a/frame/support/test/tests/pallet.rs b/frame/support/test/tests/pallet.rs index 509e3217ddf9..e9c6fe8be560 100644 --- a/frame/support/test/tests/pallet.rs +++ b/frame/support/test/tests/pallet.rs @@ -566,6 +566,7 @@ impl frame_system::Config for Runtime { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } impl pallet::Config for Runtime { type Event = Event; diff --git a/frame/support/test/tests/pallet_compatibility.rs b/frame/support/test/tests/pallet_compatibility.rs index 4523063252ab..0cd6a6e59cff 100644 --- a/frame/support/test/tests/pallet_compatibility.rs +++ b/frame/support/test/tests/pallet_compatibility.rs @@ -246,6 +246,7 @@ impl frame_system::Config for Runtime { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } impl pallet::Config for Runtime { type Event = Event; diff --git a/frame/support/test/tests/pallet_compatibility_instance.rs b/frame/support/test/tests/pallet_compatibility_instance.rs index 768b9f28d35f..16f5e16cb873 100644 --- a/frame/support/test/tests/pallet_compatibility_instance.rs +++ b/frame/support/test/tests/pallet_compatibility_instance.rs @@ -226,6 +226,7 @@ impl frame_system::Config for Runtime { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } impl pallet::Config for Runtime { type Event = Event; diff --git a/frame/support/test/tests/pallet_instance.rs b/frame/support/test/tests/pallet_instance.rs index de70b0e7e404..9fd748eb332c 100644 --- a/frame/support/test/tests/pallet_instance.rs +++ b/frame/support/test/tests/pallet_instance.rs @@ -274,6 +274,7 @@ impl frame_system::Config for Runtime { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } impl pallet::Config for Runtime { type Event = Event; diff --git a/frame/support/test/tests/pallet_with_name_trait_is_valid.rs b/frame/support/test/tests/pallet_with_name_trait_is_valid.rs index 1c47d13a619f..170e515740b3 100644 --- a/frame/support/test/tests/pallet_with_name_trait_is_valid.rs +++ b/frame/support/test/tests/pallet_with_name_trait_is_valid.rs @@ -152,6 +152,7 @@ mod tests { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } impl pallet_test::Trait for Runtime { diff --git a/frame/system/benches/bench.rs b/frame/system/benches/bench.rs index c8a9d4eadfea..0d513ff599d5 100644 --- a/frame/system/benches/bench.rs +++ b/frame/system/benches/bench.rs @@ -92,6 +92,7 @@ impl frame_system::Config for Runtime { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } impl module::Config for Runtime { diff --git a/frame/system/benchmarking/src/mock.rs b/frame/system/benchmarking/src/mock.rs index d828fb22ff5f..ff00b76c45fd 100644 --- a/frame/system/benchmarking/src/mock.rs +++ b/frame/system/benchmarking/src/mock.rs @@ -62,6 +62,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } impl crate::Config for Test {} diff --git a/frame/system/src/lib.rs b/frame/system/src/lib.rs index 7825c9ec0780..8823aa37c19c 100644 --- a/frame/system/src/lib.rs +++ b/frame/system/src/lib.rs @@ -309,6 +309,10 @@ pub mod pallet { /// It's unlikely that this needs to be customized, unless you are writing a parachain using /// `Cumulus`, where the actual code change is deferred. type OnSetCode: SetCode; + + /// The maximum number of consumers allowed on a single account. + #[pallet::constant] + type MaxConsumers: Get; } #[pallet::pallet] @@ -1107,8 +1111,12 @@ impl Pallet { pub fn inc_consumers(who: &T::AccountId) -> Result<(), DispatchError> { Account::::try_mutate(who, |a| { if a.providers > 0 { - a.consumers = a.consumers.saturating_add(1); - Ok(()) + if a.consumers < T::MaxConsumers::get() { + a.consumers = a.consumers.saturating_add(1); + Ok(()) + } else { + Err(DispatchError::TooManyConsumers) + } } else { Err(DispatchError::NoProviders) } @@ -1148,7 +1156,8 @@ impl Pallet { /// True if the account has at least one provider reference. pub fn can_inc_consumer(who: &T::AccountId) -> bool { - Account::::get(who).providers > 0 + let a = Account::::get(who); + a.providers > 0 && a.consumers < T::MaxConsumers::get() } /// Deposits an event into this block's event record. diff --git a/frame/system/src/mock.rs b/frame/system/src/mock.rs index 9dd35691cab8..de89324ec9fb 100644 --- a/frame/system/src/mock.rs +++ b/frame/system/src/mock.rs @@ -111,6 +111,7 @@ impl Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } pub type SysEvent = frame_system::Event; diff --git a/frame/timestamp/src/lib.rs b/frame/timestamp/src/lib.rs index eeb840715f81..ae9a3b5f69ad 100644 --- a/frame/timestamp/src/lib.rs +++ b/frame/timestamp/src/lib.rs @@ -372,6 +372,7 @@ mod tests { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { pub const MinimumPeriod: u64 = 5; diff --git a/frame/tips/src/tests.rs b/frame/tips/src/tests.rs index 2aac22ffe18c..7d6a71734731 100644 --- a/frame/tips/src/tests.rs +++ b/frame/tips/src/tests.rs @@ -83,6 +83,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { pub const ExistentialDeposit: u64 = 1; diff --git a/frame/transaction-payment/asset-tx-payment/src/tests.rs b/frame/transaction-payment/asset-tx-payment/src/tests.rs index bd5dc57239a2..106b361aff8f 100644 --- a/frame/transaction-payment/asset-tx-payment/src/tests.rs +++ b/frame/transaction-payment/asset-tx-payment/src/tests.rs @@ -112,6 +112,7 @@ impl frame_system::Config for Runtime { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { @@ -169,6 +170,7 @@ impl pallet_assets::Config for Runtime { type Currency = Balances; type ForceOrigin = EnsureRoot; type AssetDeposit = AssetDeposit; + type AssetAccountDeposit = frame_support::traits::ConstU64<2>; type MetadataDepositBase = MetadataDeposit; type MetadataDepositPerByte = MetadataDeposit; type ApprovalDeposit = MetadataDeposit; diff --git a/frame/transaction-payment/src/lib.rs b/frame/transaction-payment/src/lib.rs index 02ba9621c175..a5bcc6d12dec 100644 --- a/frame/transaction-payment/src/lib.rs +++ b/frame/transaction-payment/src/lib.rs @@ -865,6 +865,7 @@ mod tests { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { diff --git a/frame/transaction-storage/src/mock.rs b/frame/transaction-storage/src/mock.rs index 38d14129d76e..49b81348e7d4 100644 --- a/frame/transaction-storage/src/mock.rs +++ b/frame/transaction-storage/src/mock.rs @@ -77,6 +77,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = SS58Prefix; type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { diff --git a/frame/treasury/src/tests.rs b/frame/treasury/src/tests.rs index 534661b2773b..c2b41e716523 100644 --- a/frame/treasury/src/tests.rs +++ b/frame/treasury/src/tests.rs @@ -79,6 +79,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { pub const ExistentialDeposit: u64 = 1; diff --git a/frame/uniques/src/mock.rs b/frame/uniques/src/mock.rs index 658e82a5143e..f65f69209b9e 100644 --- a/frame/uniques/src/mock.rs +++ b/frame/uniques/src/mock.rs @@ -69,6 +69,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { diff --git a/frame/utility/src/tests.rs b/frame/utility/src/tests.rs index 32582fae8211..169ac6cfff89 100644 --- a/frame/utility/src/tests.rs +++ b/frame/utility/src/tests.rs @@ -127,6 +127,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { pub const ExistentialDeposit: u64 = 1; diff --git a/frame/vesting/src/mock.rs b/frame/vesting/src/mock.rs index cb8961150003..1e04875a7e07 100644 --- a/frame/vesting/src/mock.rs +++ b/frame/vesting/src/mock.rs @@ -64,6 +64,7 @@ impl frame_system::Config for Test { type OnKilledAccount = (); type OnNewAccount = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; type Origin = Origin; type PalletInfo = PalletInfo; type SS58Prefix = (); diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 8cd15b51a32c..10fd39d38f4c 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -494,6 +494,8 @@ pub enum DispatchError { ConsumerRemaining, /// There are no providers so the account cannot be created. NoProviders, + /// There are too many consumers so the account cannot be created. + TooManyConsumers, /// An error to do with tokens. Token(TokenError), /// An arithmetic error. @@ -629,6 +631,7 @@ impl From for &'static str { DispatchError::Module { message, .. } => message.unwrap_or("Unknown module error"), DispatchError::ConsumerRemaining => "Consumer remaining", DispatchError::NoProviders => "No providers", + DispatchError::TooManyConsumers => "Too many consumers", DispatchError::Token(e) => e.into(), DispatchError::Arithmetic(e) => e.into(), } @@ -660,6 +663,7 @@ impl traits::Printable for DispatchError { }, Self::ConsumerRemaining => "Consumer remaining".print(), Self::NoProviders => "No providers".print(), + Self::TooManyConsumers => "Too many consumers".print(), Self::Token(e) => { "Token error: ".print(); <&'static str>::from(*e).print(); diff --git a/test-utils/runtime/src/lib.rs b/test-utils/runtime/src/lib.rs index 08863de510d0..7b78880c2c3b 100644 --- a/test-utils/runtime/src/lib.rs +++ b/test-utils/runtime/src/lib.rs @@ -591,6 +591,7 @@ impl frame_system::Config for Runtime { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } impl pallet_timestamp::Config for Runtime { From 6a634fb132f4ae50b42ac5efd10ea89e086216dc Mon Sep 17 00:00:00 2001 From: Gautam Dhameja Date: Thu, 9 Dec 2021 15:16:35 +0100 Subject: [PATCH 275/695] Fix reset curator deposit when curator unassigns themself. (#10443) --- frame/bounties/src/lib.rs | 1 + frame/bounties/src/tests.rs | 39 +++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/frame/bounties/src/lib.rs b/frame/bounties/src/lib.rs index 1d32b63f38f9..7e8ba6005056 100644 --- a/frame/bounties/src/lib.rs +++ b/frame/bounties/src/lib.rs @@ -453,6 +453,7 @@ pub mod pallet { let err_amount = T::Currency::unreserve(&curator, bounty.curator_deposit); debug_assert!(err_amount.is_zero()); + bounty.curator_deposit = Zero::zero(); // Continue to change bounty status below... } }, diff --git a/frame/bounties/src/tests.rs b/frame/bounties/src/tests.rs index ac1f104119df..dc6cecc06f5e 100644 --- a/frame/bounties/src/tests.rs +++ b/frame/bounties/src/tests.rs @@ -1004,3 +1004,42 @@ fn genesis_funding_works() { assert_eq!(Treasury::pot(), initial_funding - Balances::minimum_balance()); }); } + +#[test] +fn unassign_curator_self() { + new_test_ext().execute_with(|| { + System::set_block_number(1); + Balances::make_free_balance_be(&Treasury::account_id(), 101); + assert_ok!(Bounties::propose_bounty(Origin::signed(0), 50, b"12345".to_vec())); + assert_ok!(Bounties::approve_bounty(Origin::root(), 0)); + + System::set_block_number(2); + >::on_initialize(2); + + assert_ok!(Bounties::propose_curator(Origin::root(), 0, 1, 10)); + assert_ok!(Bounties::accept_curator(Origin::signed(1), 0)); + + assert_eq!(Balances::free_balance(1), 93); + assert_eq!(Balances::reserved_balance(1), 5); + + System::set_block_number(8); + >::on_initialize(8); + + assert_ok!(Bounties::unassign_curator(Origin::signed(1), 0)); + + assert_eq!( + Bounties::bounties(0).unwrap(), + Bounty { + proposer: 0, + fee: 10, + curator_deposit: 0, + value: 50, + bond: 85, + status: BountyStatus::Funded, + } + ); + + assert_eq!(Balances::free_balance(1), 98); + assert_eq!(Balances::reserved_balance(1), 0); // not slashed + }); +} From 1aea26eb820199c422f05f0d26558d8d7c70542e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89lo=C3=AFs?= Date: Thu, 9 Dec 2021 16:10:16 +0100 Subject: [PATCH 276/695] Make wasm runtime cache size configurable (#10177) * Make wasm runtime cache size configurable * apply review comments * remove VersionedRuntimeValue * fix compilation * VersionedRuntime: replace clone by Arc * fmt * fix warnings * fix tests compilation * fmt --- Cargo.lock | 1 + bin/node-template/node/src/service.rs | 1 + bin/node/cli/benches/block_production.rs | 1 + bin/node/cli/benches/transaction_pool.rs | 1 + bin/node/cli/src/service.rs | 1 + bin/node/executor/benches/bench.rs | 2 +- bin/node/executor/tests/common.rs | 2 +- bin/node/inspect/src/command.rs | 1 + bin/node/testing/src/bench.rs | 2 +- client/cli/src/commands/run_cmd.rs | 8 ++ client/cli/src/config.rs | 9 ++ client/executor/Cargo.toml | 1 + client/executor/src/integration_tests/mod.rs | 3 + client/executor/src/lib.rs | 1 + client/executor/src/native_executor.rs | 10 +- client/executor/src/wasm_runtime.rs | 143 +++++++++---------- client/service/src/client/call_executor.rs | 1 + client/service/src/client/wasm_override.rs | 2 + client/service/src/config.rs | 2 + client/service/test/src/client/mod.rs | 7 +- client/service/test/src/lib.rs | 1 + primitives/api/test/tests/runtime_calls.rs | 1 + primitives/runtime-interface/test/src/lib.rs | 1 + test-utils/client/src/lib.rs | 2 +- test-utils/runtime/client/src/lib.rs | 7 +- test-utils/runtime/src/system.rs | 2 +- test-utils/test-runner/src/client.rs | 1 + test-utils/test-runner/src/utils.rs | 1 + utils/frame/benchmarking-cli/src/command.rs | 1 + utils/frame/try-runtime/cli/src/lib.rs | 8 +- 30 files changed, 142 insertions(+), 82 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a3e186aca428..e7ddb66e2918 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8035,6 +8035,7 @@ dependencies = [ "lazy_static", "libsecp256k1", "log 0.4.14", + "lru 0.6.6", "parity-scale-codec", "parking_lot 0.11.1", "paste 1.0.6", diff --git a/bin/node-template/node/src/service.rs b/bin/node-template/node/src/service.rs index 82b1c5625373..92bd059e528a 100644 --- a/bin/node-template/node/src/service.rs +++ b/bin/node-template/node/src/service.rs @@ -78,6 +78,7 @@ pub fn new_partial( config.wasm_method, config.default_heap_pages, config.max_runtime_instances, + config.runtime_cache_size, ); let (client, backend, keystore_container, task_manager) = diff --git a/bin/node/cli/benches/block_production.rs b/bin/node/cli/benches/block_production.rs index 5a520e7b6339..f2dbc1fff6be 100644 --- a/bin/node/cli/benches/block_production.rs +++ b/bin/node/cli/benches/block_production.rs @@ -104,6 +104,7 @@ fn new_node(tokio_handle: Handle) -> node_cli::service::NewFullBase { tracing_targets: None, tracing_receiver: Default::default(), max_runtime_instances: 8, + runtime_cache_size: 2, announce_block: true, base_path: Some(base_path), informant_output_format: Default::default(), diff --git a/bin/node/cli/benches/transaction_pool.rs b/bin/node/cli/benches/transaction_pool.rs index 4f5ccd6ea912..2965c6336f0f 100644 --- a/bin/node/cli/benches/transaction_pool.rs +++ b/bin/node/cli/benches/transaction_pool.rs @@ -96,6 +96,7 @@ fn new_node(tokio_handle: Handle) -> node_cli::service::NewFullBase { tracing_targets: None, tracing_receiver: Default::default(), max_runtime_instances: 8, + runtime_cache_size: 2, announce_block: true, base_path: Some(base_path), informant_output_format: Default::default(), diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index 1dfce9331b75..fbc91c5f7d2e 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -161,6 +161,7 @@ pub fn new_partial( config.wasm_method, config.default_heap_pages, config.max_runtime_instances, + config.runtime_cache_size, ); let (client, backend, keystore_container, task_manager) = diff --git a/bin/node/executor/benches/bench.rs b/bin/node/executor/benches/bench.rs index 03c3eb53e23f..aea37b68d55b 100644 --- a/bin/node/executor/benches/bench.rs +++ b/bin/node/executor/benches/bench.rs @@ -194,7 +194,7 @@ fn bench_execute_block(c: &mut Criterion) { ExecutionMethod::Wasm(wasm_method) => (false, wasm_method), }; - let executor = NativeElseWasmExecutor::new(wasm_method, None, 8); + let executor = NativeElseWasmExecutor::new(wasm_method, None, 8, 2); let runtime_code = RuntimeCode { code_fetcher: &sp_core::traits::WrappedRuntimeCode(compact_code_unwrap().into()), hash: vec![1, 2, 3], diff --git a/bin/node/executor/tests/common.rs b/bin/node/executor/tests/common.rs index 87506ba66a3e..84b5728a1a84 100644 --- a/bin/node/executor/tests/common.rs +++ b/bin/node/executor/tests/common.rs @@ -96,7 +96,7 @@ pub fn from_block_number(n: u32) -> Header { } pub fn executor() -> NativeElseWasmExecutor { - NativeElseWasmExecutor::new(WasmExecutionMethod::Interpreted, None, 8) + NativeElseWasmExecutor::new(WasmExecutionMethod::Interpreted, None, 8, 2) } pub fn executor_call< diff --git a/bin/node/inspect/src/command.rs b/bin/node/inspect/src/command.rs index 9bf69511689c..e20c91456515 100644 --- a/bin/node/inspect/src/command.rs +++ b/bin/node/inspect/src/command.rs @@ -41,6 +41,7 @@ impl InspectCmd { config.wasm_method, config.default_heap_pages, config.max_runtime_instances, + config.runtime_cache_size, ); let client = new_full_client::(&config, None, executor)?; diff --git a/bin/node/testing/src/bench.rs b/bin/node/testing/src/bench.rs index 3240497a9d62..6a5c4b80e1fe 100644 --- a/bin/node/testing/src/bench.rs +++ b/bin/node/testing/src/bench.rs @@ -400,7 +400,7 @@ impl BenchDb { let backend = sc_service::new_db_backend(db_config).expect("Should not fail"); let client = sc_service::new_client( backend.clone(), - NativeElseWasmExecutor::new(WasmExecutionMethod::Compiled, None, 8), + NativeElseWasmExecutor::new(WasmExecutionMethod::Compiled, None, 8, 2), &keyring.generate_genesis(), None, None, diff --git a/client/cli/src/commands/run_cmd.rs b/client/cli/src/commands/run_cmd.rs index 622206fdf297..78ea4b1276b2 100644 --- a/client/cli/src/commands/run_cmd.rs +++ b/client/cli/src/commands/run_cmd.rs @@ -238,6 +238,10 @@ pub struct RunCmd { #[structopt(long)] pub max_runtime_instances: Option, + /// Maximum number of different runtimes that can be cached. + #[structopt(long, default_value = "2")] + pub runtime_cache_size: u8, + /// Run a temporary node. /// /// A temporary directory will be created to store the configuration and will be deleted @@ -453,6 +457,10 @@ impl CliConfiguration for RunCmd { Ok(self.max_runtime_instances.map(|x| x.min(256))) } + fn runtime_cache_size(&self) -> Result { + Ok(self.runtime_cache_size) + } + fn base_path(&self) -> Result> { Ok(if self.tmp { Some(BasePath::new_temp_dir()?) diff --git a/client/cli/src/config.rs b/client/cli/src/config.rs index 20e2bf0df5b2..1fda07d2571f 100644 --- a/client/cli/src/config.rs +++ b/client/cli/src/config.rs @@ -452,6 +452,13 @@ pub trait CliConfiguration: Sized { Ok(Default::default()) } + /// Get maximum different runtimes in cache + /// + /// By default this is `2`. + fn runtime_cache_size(&self) -> Result { + Ok(2) + } + /// Activate or not the automatic announcing of blocks after import /// /// By default this is `false`. @@ -482,6 +489,7 @@ pub trait CliConfiguration: Sized { let is_validator = role.is_authority(); let (keystore_remote, keystore) = self.keystore_config(&config_dir)?; let telemetry_endpoints = self.telemetry_endpoints(&chain_spec)?; + let runtime_cache_size = self.runtime_cache_size()?; let unsafe_pruning = self.import_params().map(|p| p.unsafe_pruning).unwrap_or(false); @@ -534,6 +542,7 @@ pub trait CliConfiguration: Sized { role, base_path: Some(base_path), informant_output_format: Default::default(), + runtime_cache_size, }) } diff --git a/client/executor/Cargo.toml b/client/executor/Cargo.toml index b3a393f9472a..dea8a26edde3 100644 --- a/client/executor/Cargo.toml +++ b/client/executor/Cargo.toml @@ -34,6 +34,7 @@ parking_lot = "0.11.1" log = "0.4.8" libsecp256k1 = "0.7" sp-core-hashing-proc-macro = { version = "4.0.0-dev", path = "../../primitives/core/hashing/proc-macro" } +lru = "0.6.6" [dev-dependencies] wat = "1.0" diff --git a/client/executor/src/integration_tests/mod.rs b/client/executor/src/integration_tests/mod.rs index 01c040687ddd..3ff0ecebd9ac 100644 --- a/client/executor/src/integration_tests/mod.rs +++ b/client/executor/src/integration_tests/mod.rs @@ -130,6 +130,7 @@ fn call_in_wasm( HostFunctions::host_functions(), 8, None, + 2, ); executor.uncached_call( RuntimeBlob::uncompress_if_needed(&wasm_binary_unwrap()[..]).unwrap(), @@ -480,6 +481,7 @@ fn should_trap_when_heap_exhausted(wasm_method: WasmExecutionMethod) { HostFunctions::host_functions(), 8, None, + 2, ); let err = executor @@ -593,6 +595,7 @@ fn parallel_execution(wasm_method: WasmExecutionMethod) { HostFunctions::host_functions(), 8, None, + 2, )); let threads: Vec<_> = (0..8) .map(|_| { diff --git a/client/executor/src/lib.rs b/client/executor/src/lib.rs index 041db87bc82a..9a4d8e3cf0b6 100644 --- a/client/executor/src/lib.rs +++ b/client/executor/src/lib.rs @@ -80,6 +80,7 @@ mod tests { sp_io::SubstrateHostFunctions::host_functions(), 8, None, + 2, ); let res = executor .uncached_call( diff --git a/client/executor/src/native_executor.rs b/client/executor/src/native_executor.rs index 62e76d559c0f..1c01520ac9c8 100644 --- a/client/executor/src/native_executor.rs +++ b/client/executor/src/native_executor.rs @@ -130,12 +130,17 @@ impl WasmExecutor { host_functions: Vec<&'static dyn Function>, max_runtime_instances: usize, cache_path: Option, + runtime_cache_size: u8, ) -> Self { WasmExecutor { method, default_heap_pages: default_heap_pages.unwrap_or(DEFAULT_HEAP_PAGES), host_functions: Arc::new(host_functions), - cache: Arc::new(RuntimeCache::new(max_runtime_instances, cache_path.clone())), + cache: Arc::new(RuntimeCache::new( + max_runtime_instances, + cache_path.clone(), + runtime_cache_size, + )), cache_path, } } @@ -330,6 +335,7 @@ impl NativeElseWasmExecutor { fallback_method: WasmExecutionMethod, default_heap_pages: Option, max_runtime_instances: usize, + runtime_cache_size: u8, ) -> Self { let extended = D::ExtendHostFunctions::host_functions(); let mut host_functions = sp_io::SubstrateHostFunctions::host_functions() @@ -351,6 +357,7 @@ impl NativeElseWasmExecutor { host_functions, max_runtime_instances, None, + runtime_cache_size, ); NativeElseWasmExecutor { @@ -636,6 +643,7 @@ mod tests { WasmExecutionMethod::Interpreted, None, 8, + 2, ); my_interface::HostFunctions::host_functions().iter().for_each(|function| { assert_eq!(executor.wasm.host_functions.iter().filter(|f| f == &function).count(), 2); diff --git a/client/executor/src/wasm_runtime.rs b/client/executor/src/wasm_runtime.rs index 88c033814ed6..44ed6eb32304 100644 --- a/client/executor/src/wasm_runtime.rs +++ b/client/executor/src/wasm_runtime.rs @@ -23,6 +23,7 @@ use crate::error::{Error, WasmError}; use codec::Decode; +use lru::LruCache; use parking_lot::Mutex; use sc_executor_common::{ runtime_blob::RuntimeBlob, @@ -54,20 +55,24 @@ impl Default for WasmExecutionMethod { } } -/// A Wasm runtime object along with its cached runtime version. -struct VersionedRuntime { +#[derive(Debug, PartialEq, Eq, Hash, Clone)] +struct VersionedRuntimeId { /// Runtime code hash. code_hash: Vec, /// Wasm runtime type. wasm_method: WasmExecutionMethod, - /// Shared runtime that can spawn instances. - module: Arc, /// The number of WebAssembly heap pages this instance was created with. heap_pages: u64, +} + +/// A Wasm runtime object along with its cached runtime version. +struct VersionedRuntime { + /// Shared runtime that can spawn instances. + module: Arc, /// Runtime version according to `Core_version` if any. version: Option, /// Cached instance pool. - instances: Vec>>>, + instances: Arc>>>>, } impl VersionedRuntime { @@ -137,8 +142,6 @@ impl VersionedRuntime { } } -const MAX_RUNTIMES: usize = 2; - /// Cache for the runtimes. /// /// When an instance is requested for the first time it is added to this cache. Metadata is kept @@ -149,12 +152,12 @@ const MAX_RUNTIMES: usize = 2; /// the memory reset to the initial memory. So, one runtime instance is reused for every fetch /// request. /// -/// The size of cache is equal to `MAX_RUNTIMES`. +/// The size of cache is configurable via the cli option `--runtime-cache-size`. pub struct RuntimeCache { /// A cache of runtimes along with metadata. /// /// Runtimes sorted by recent usage. The most recently used is at the front. - runtimes: Mutex<[Option>; MAX_RUNTIMES]>, + runtimes: Mutex>>, /// The size of the instances cache for each runtime. max_runtime_instances: usize, cache_path: Option, @@ -163,13 +166,24 @@ pub struct RuntimeCache { impl RuntimeCache { /// Creates a new instance of a runtimes cache. /// - /// `max_runtime_instances` specifies the number of runtime instances preserved in an in-memory - /// cache. + /// `max_runtime_instances` specifies the number of instances per runtime preserved in an + /// in-memory cache. /// /// `cache_path` allows to specify an optional directory where the executor can store files /// for caching. - pub fn new(max_runtime_instances: usize, cache_path: Option) -> RuntimeCache { - RuntimeCache { runtimes: Default::default(), max_runtime_instances, cache_path } + /// + /// `runtime_cache_size` specifies the number of different runtimes versions preserved in an + /// in-memory cache. + pub fn new( + max_runtime_instances: usize, + cache_path: Option, + runtime_cache_size: u8, + ) -> RuntimeCache { + RuntimeCache { + runtimes: Mutex::new(LruCache::new(runtime_cache_size.into())), + max_runtime_instances, + cache_path, + } } /// Prepares a WASM module instance and executes given function for it. @@ -221,71 +235,55 @@ impl RuntimeCache { let code_hash = &runtime_code.hash; let heap_pages = runtime_code.heap_pages.unwrap_or(default_heap_pages); + let versioned_runtime_id = + VersionedRuntimeId { code_hash: code_hash.clone(), heap_pages, wasm_method }; + let mut runtimes = self.runtimes.lock(); // this must be released prior to calling f - let pos = runtimes.iter().position(|r| { - r.as_ref().map_or(false, |r| { - r.wasm_method == wasm_method && - r.code_hash == *code_hash && - r.heap_pages == heap_pages - }) - }); + let versioned_runtime = if let Some(versioned_runtime) = runtimes.get(&versioned_runtime_id) + { + versioned_runtime.clone() + } else { + let code = runtime_code.fetch_runtime_code().ok_or(WasmError::CodeNotFound)?; + + let time = std::time::Instant::now(); + + let result = create_versioned_wasm_runtime( + &code, + ext, + wasm_method, + heap_pages, + host_functions.into(), + allow_missing_func_imports, + self.max_runtime_instances, + self.cache_path.as_deref(), + ); + + match result { + Ok(ref result) => { + log::debug!( + target: "wasm-runtime", + "Prepared new runtime version {:?} in {} ms.", + result.version, + time.elapsed().as_millis(), + ); + }, + Err(ref err) => { + log::warn!(target: "wasm-runtime", "Cannot create a runtime: {:?}", err); + }, + } - let runtime = match pos { - Some(n) => runtimes[n] - .clone() - .expect("`position` only returns `Some` for entries that are `Some`"), - None => { - let code = runtime_code.fetch_runtime_code().ok_or(WasmError::CodeNotFound)?; - - let time = std::time::Instant::now(); - - let result = create_versioned_wasm_runtime( - &code, - code_hash.clone(), - ext, - wasm_method, - heap_pages, - host_functions.into(), - allow_missing_func_imports, - self.max_runtime_instances, - self.cache_path.as_deref(), - ); - - match result { - Ok(ref result) => { - log::debug!( - target: "wasm-runtime", - "Prepared new runtime version {:?} in {} ms.", - result.version, - time.elapsed().as_millis(), - ); - }, - Err(ref err) => { - log::warn!(target: "wasm-runtime", "Cannot create a runtime: {:?}", err); - }, - } + let versioned_runtime = Arc::new(result?); - Arc::new(result?) - }, + // Save new versioned wasm runtime in cache + runtimes.put(versioned_runtime_id, versioned_runtime.clone()); + + versioned_runtime }; - // Rearrange runtimes by last recently used. - match pos { - Some(0) => {}, - Some(n) => - for i in (1..n + 1).rev() { - runtimes.swap(i, i - 1); - }, - None => { - runtimes[MAX_RUNTIMES - 1] = Some(runtime.clone()); - for i in (1..MAX_RUNTIMES).rev() { - runtimes.swap(i, i - 1); - } - }, - } + // Lock must be released prior to calling f drop(runtimes); - Ok(runtime.with_instance(ext, f)) + Ok(versioned_runtime.with_instance(ext, f)) } } @@ -396,7 +394,6 @@ pub fn read_embedded_version(blob: &RuntimeBlob) -> Result, ext: &mut dyn Externalities, wasm_method: WasmExecutionMethod, heap_pages: u64, @@ -449,7 +446,7 @@ fn create_versioned_wasm_runtime( let mut instances = Vec::with_capacity(max_instances); instances.resize_with(max_instances, || Mutex::new(None)); - Ok(VersionedRuntime { code_hash, module: runtime, version, heap_pages, wasm_method, instances }) + Ok(VersionedRuntime { module: runtime, version, instances: Arc::new(instances) }) } #[cfg(test)] diff --git a/client/service/src/client/call_executor.rs b/client/service/src/client/call_executor.rs index 7d15ce4704ab..9f56424daf2f 100644 --- a/client/service/src/client/call_executor.rs +++ b/client/service/src/client/call_executor.rs @@ -360,6 +360,7 @@ mod tests { WasmExecutionMethod::Interpreted, Some(128), 1, + 2, ); let overrides = crate::client::wasm_override::dummy_overrides(); diff --git a/client/service/src/client/wasm_override.rs b/client/service/src/client/wasm_override.rs index ba3f2855fc7a..88b2c3895b02 100644 --- a/client/service/src/client/wasm_override.rs +++ b/client/service/src/client/wasm_override.rs @@ -282,6 +282,7 @@ mod tests { WasmExecutionMethod::Interpreted, Some(128), 1, + 2, ); let bytes = substrate_test_runtime::wasm_binary_unwrap(); let dir = tempfile::tempdir().expect("Create a temporary directory"); @@ -295,6 +296,7 @@ mod tests { WasmExecutionMethod::Interpreted, Some(128), 1, + 2, ); let version = WasmOverride::runtime_version( diff --git a/client/service/src/config.rs b/client/service/src/config.rs index 0552baf5c209..61ef8233f8e3 100644 --- a/client/service/src/config.rs +++ b/client/service/src/config.rs @@ -132,6 +132,8 @@ pub struct Configuration { pub base_path: Option, /// Configuration of the output format that the informant uses. pub informant_output_format: sc_informant::OutputFormat, + /// Maximum number of different runtime versions that can be cached. + pub runtime_cache_size: u8, } /// Type for tasks spawned by the executor. diff --git a/client/service/test/src/client/mod.rs b/client/service/test/src/client/mod.rs index d5e23d319e83..286d819a6ce5 100644 --- a/client/service/test/src/client/mod.rs +++ b/client/service/test/src/client/mod.rs @@ -72,7 +72,12 @@ impl sc_executor::NativeExecutionDispatch for ExecutorDispatch { } fn executor() -> sc_executor::NativeElseWasmExecutor { - sc_executor::NativeElseWasmExecutor::new(sc_executor::WasmExecutionMethod::Interpreted, None, 8) + sc_executor::NativeElseWasmExecutor::new( + sc_executor::WasmExecutionMethod::Interpreted, + None, + 8, + 2, + ) } fn construct_block( diff --git a/client/service/test/src/lib.rs b/client/service/test/src/lib.rs index c44a5cdb9743..7033001db43c 100644 --- a/client/service/test/src/lib.rs +++ b/client/service/test/src/lib.rs @@ -261,6 +261,7 @@ fn node_config< announce_block: true, base_path: Some(BasePath::new(root)), informant_output_format: Default::default(), + runtime_cache_size: 2, } } diff --git a/primitives/api/test/tests/runtime_calls.rs b/primitives/api/test/tests/runtime_calls.rs index e32290b12a59..21dfd456b1a1 100644 --- a/primitives/api/test/tests/runtime_calls.rs +++ b/primitives/api/test/tests/runtime_calls.rs @@ -210,6 +210,7 @@ fn record_proof_works() { WasmExecutionMethod::Interpreted, None, 8, + 2, ); execution_proof_check_on_trie_backend( &backend, diff --git a/primitives/runtime-interface/test/src/lib.rs b/primitives/runtime-interface/test/src/lib.rs index 1749cc485367..f64b74336427 100644 --- a/primitives/runtime-interface/test/src/lib.rs +++ b/primitives/runtime-interface/test/src/lib.rs @@ -48,6 +48,7 @@ fn call_wasm_method_with_result( host_functions, 8, None, + 2, ); executor .uncached_call( diff --git a/test-utils/client/src/lib.rs b/test-utils/client/src/lib.rs index 2d1cb4bbc66a..96f3c9898395 100644 --- a/test-utils/client/src/lib.rs +++ b/test-utils/client/src/lib.rs @@ -283,7 +283,7 @@ impl Backend: sc_client_api::backend::Backend + 'static, { let executor = executor.into().unwrap_or_else(|| { - NativeElseWasmExecutor::new(WasmExecutionMethod::Interpreted, None, 8) + NativeElseWasmExecutor::new(WasmExecutionMethod::Interpreted, None, 8, 2) }); let executor = LocalCallExecutor::new( self.backend.clone(), diff --git a/test-utils/runtime/client/src/lib.rs b/test-utils/runtime/client/src/lib.rs index 2948e918cdf8..a5d1e1966e30 100644 --- a/test-utils/runtime/client/src/lib.rs +++ b/test-utils/runtime/client/src/lib.rs @@ -287,5 +287,10 @@ pub fn new() -> Client { /// Create a new native executor. pub fn new_native_executor() -> sc_executor::NativeElseWasmExecutor { - sc_executor::NativeElseWasmExecutor::new(sc_executor::WasmExecutionMethod::Interpreted, None, 8) + sc_executor::NativeElseWasmExecutor::new( + sc_executor::WasmExecutionMethod::Interpreted, + None, + 8, + 2, + ) } diff --git a/test-utils/runtime/src/system.rs b/test-utils/runtime/src/system.rs index 165fe0355628..0c72c083baae 100644 --- a/test-utils/runtime/src/system.rs +++ b/test-utils/runtime/src/system.rs @@ -342,7 +342,7 @@ mod tests { } fn executor() -> NativeElseWasmExecutor { - NativeElseWasmExecutor::new(WasmExecutionMethod::Interpreted, None, 8) + NativeElseWasmExecutor::new(WasmExecutionMethod::Interpreted, None, 8, 2) } fn new_test_ext() -> TestExternalities { diff --git a/test-utils/test-runner/src/client.rs b/test-utils/test-runner/src/client.rs index c68a33056c16..21039d3bc4b1 100644 --- a/test-utils/test-runner/src/client.rs +++ b/test-utils/test-runner/src/client.rs @@ -111,6 +111,7 @@ where config.wasm_method, config.default_heap_pages, config.max_runtime_instances, + config.runtime_cache_size, ); let (client, backend, keystore, mut task_manager) = diff --git a/test-utils/test-runner/src/utils.rs b/test-utils/test-runner/src/utils.rs index a4c45c25f969..4b44d12e1ed4 100644 --- a/test-utils/test-runner/src/utils.rs +++ b/test-utils/test-runner/src/utils.rs @@ -113,5 +113,6 @@ pub fn default_config(tokio_handle: Handle, mut chain_spec: Box) keep_blocks: KeepBlocks::All, state_pruning: Default::default(), transaction_storage: TransactionStorageMode::BlockBody, + runtime_cache_size: 2, } } diff --git a/utils/frame/benchmarking-cli/src/command.rs b/utils/frame/benchmarking-cli/src/command.rs index 48d05dd8dda9..2a0429b27908 100644 --- a/utils/frame/benchmarking-cli/src/command.rs +++ b/utils/frame/benchmarking-cli/src/command.rs @@ -137,6 +137,7 @@ impl BenchmarkCmd { wasm_method, self.heap_pages, 2, // The runtime instances cache size. + 2, // The runtime cache size ); let extensions = || -> Extensions { diff --git a/utils/frame/try-runtime/cli/src/lib.rs b/utils/frame/try-runtime/cli/src/lib.rs index 8ea2e39297a9..3872f84a62a4 100644 --- a/utils/frame/try-runtime/cli/src/lib.rs +++ b/utils/frame/try-runtime/cli/src/lib.rs @@ -678,8 +678,14 @@ pub(crate) fn build_executor( let wasm_method = shared.wasm_method; let heap_pages = shared.heap_pages.or(config.default_heap_pages); let max_runtime_instances = config.max_runtime_instances; + let runtime_cache_size = config.runtime_cache_size; - NativeElseWasmExecutor::::new(wasm_method.into(), heap_pages, max_runtime_instances) + NativeElseWasmExecutor::::new( + wasm_method.into(), + heap_pages, + max_runtime_instances, + runtime_cache_size, + ) } /// Execute the given `method` and `data` on top of `ext`, returning the results (encoded) and the From 0064dd52f8f81615b5c2c45dff6409cb77c82bcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Thu, 9 Dec 2021 20:42:43 +0100 Subject: [PATCH 277/695] Prometheus: Use correct chain id (#10457) * Prometheus: Use correct chain id * FMT --- client/cli/src/commands/run_cmd.rs | 8 ++++++-- client/cli/src/config.rs | 9 +++++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/client/cli/src/commands/run_cmd.rs b/client/cli/src/commands/run_cmd.rs index 78ea4b1276b2..661b3ff38233 100644 --- a/client/cli/src/commands/run_cmd.rs +++ b/client/cli/src/commands/run_cmd.rs @@ -365,7 +365,11 @@ impl CliConfiguration for RunCmd { Ok(self.shared_params.dev || self.force_authoring) } - fn prometheus_config(&self, default_listen_port: u16) -> Result> { + fn prometheus_config( + &self, + default_listen_port: u16, + chain_spec: &Box, + ) -> Result> { Ok(if self.no_prometheus { None } else { @@ -377,7 +381,7 @@ impl CliConfiguration for RunCmd { interface.into(), self.prometheus_port.unwrap_or(default_listen_port), ), - self.shared_params.chain_id(self.shared_params.dev), + chain_spec.id().into(), )) }) } diff --git a/client/cli/src/config.rs b/client/cli/src/config.rs index 1fda07d2571f..6d5ac7118281 100644 --- a/client/cli/src/config.rs +++ b/client/cli/src/config.rs @@ -368,7 +368,11 @@ pub trait CliConfiguration: Sized { /// Get the prometheus configuration (`None` if disabled) /// /// By default this is `None`. - fn prometheus_config(&self, _default_listen_port: u16) -> Result> { + fn prometheus_config( + &self, + _default_listen_port: u16, + _chain_spec: &Box, + ) -> Result> { Ok(None) } @@ -527,7 +531,8 @@ pub trait CliConfiguration: Sized { rpc_cors: self.rpc_cors(is_dev)?, rpc_max_payload: self.rpc_max_payload()?, ws_max_out_buffer_capacity: self.ws_max_out_buffer_capacity()?, - prometheus_config: self.prometheus_config(DCV::prometheus_listen_port())?, + prometheus_config: self + .prometheus_config(DCV::prometheus_listen_port(), &chain_spec)?, telemetry_endpoints, default_heap_pages: self.default_heap_pages()?, offchain_worker: self.offchain_worker(&role)?, From 28ae4ba635527df4fdaaf9a8e8897140eaa1f59d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Thu, 9 Dec 2021 20:43:46 +0100 Subject: [PATCH 278/695] Remove simnet from CI (#10456) --- .gitlab-ci.yml | 97 -------------- simnet_tests/README.md | 39 ------ .../configs/default_local_testnet.toml | 14 -- simnet_tests/run_tests.sh | 126 ------------------ simnet_tests/tests/long/002-loadtest.feature | 5 - .../tests/quick/001-smoketest.feature | 16 --- 6 files changed, 297 deletions(-) delete mode 100644 simnet_tests/README.md delete mode 100644 simnet_tests/configs/default_local_testnet.toml delete mode 100755 simnet_tests/run_tests.sh delete mode 100644 simnet_tests/tests/long/002-loadtest.feature delete mode 100644 simnet_tests/tests/quick/001-smoketest.feature diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f4391cf7d312..7af3675f0771 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -45,7 +45,6 @@ variables: &default-vars VAULT_SERVER_URL: "https://vault.parity-mgmt-vault.parity.io" VAULT_AUTH_PATH: "gitlab-parity-io-jwt" VAULT_AUTH_ROLE: "cicd_gitlab_parity_${CI_PROJECT_NAME}" - SIMNET_FEATURES_PATH: "simnet_tests/tests" PIPELINE_SCRIPTS_TAG: "v0.4" default: @@ -641,18 +640,6 @@ build-linux-substrate: - printf '\n# building node-template\n\n' - ./.maintain/node-template-release.sh ./artifacts/substrate/substrate-node-template.tar.gz - -#Build binary for simnet quick tests. -build-linux-substrate-simnet: - stage: build - <<: *collect-artifacts-short - <<: *docker-env - <<: *test-refs-no-trigger-prs-only - before_script: - - mkdir -p ./artifacts/substrate/ - script: - - *build-linux-substrate-script - build-linux-subkey: &build-subkey stage: build <<: *collect-artifacts @@ -739,7 +726,6 @@ build-rustdoc: - buildah push --format=v2s2 "$IMAGE_NAME:latest" after_script: - buildah logout --all - # pass artifacts to the trigger-simnet job - echo "SUBSTRATE_IMAGE_NAME=${IMAGE_NAME}" | tee -a ./artifacts/$PRODUCT/build.env - IMAGE_TAG="$(cat ./artifacts/$PRODUCT/VERSION)" - echo "SUBSTRATE_IMAGE_TAG=${IMAGE_TAG}" | tee -a ./artifacts/$PRODUCT/build.env @@ -755,30 +741,6 @@ publish-docker-substrate: variables: <<: *docker-build-vars PRODUCT: substrate - artifacts: - reports: - # this artifact is used in trigger-simnet job - # https://docs.gitlab.com/ee/ci/multi_project_pipelines.html#with-variable-inheritance - dotenv: ./artifacts/substrate/build.env - -#publish artifact for quick simnet tests -publish-docker-substrate-simnet: - stage: publish - <<: *build-push-docker-image - <<: *test-refs-no-trigger-prs-only - needs: - - job: build-linux-substrate-simnet - artifacts: true - variables: - <<: *default-vars - GIT_STRATEGY: none - DOCKERFILE: $PRODUCT.Dockerfile - PRODUCT: substrate - IMAGE_NAME: docker.io/paritypr/$PRODUCT - artifacts: - reports: - # this artifact is used in simnet-tests-quick job - dotenv: ./artifacts/substrate/build.env publish-docker-subkey: stage: publish @@ -940,62 +902,3 @@ deploy-prometheus-alerting-rules: changes: - .gitlab-ci.yml - .maintain/monitoring/**/* - -# Runs "quick" and "long" tests on nightly schedule and on commit / merge to master -# A "quick" test is a smoke test where basic check-expect tests run by -# checking values from metrics exposed by the app. -# A "long" test is the load testing where we send 50K transactions into the -# network and check if all completed successfully -simnet-tests: - stage: deploy - image: docker.io/paritytech/simnet:${SIMNET_REF} - <<: *kubernetes-env - rules: - - if: $CI_PIPELINE_SOURCE == "pipeline" - when: never - - if: $CI_PIPELINE_SOURCE == "web" && $CI_COMMIT_REF_NAME == "master" - - if: $CI_COMMIT_REF_NAME == "master" - needs: - - job: publish-docker-substrate - # variables: - # `build.env` brings here `${SUBSTRATE_IMAGE_NAME}` and `${SUBSTRATE_IMAGE_TAG}` - # (`$VERSION` here, # i.e. `2643-0.8.29-5f689e0a-6b24dc54`). - # ${SIMNET_REF} is a gitlab variable - before_script: - - echo "Simnet Tests Config - docker.io/paritytech/simnet:${SIMNET_REF} - ${SUBSTRATE_IMAGE_NAME} ${SUBSTRATE_IMAGE_TAG}" - script: - - /home/nonroot/simnet/gurke/scripts/run-test-environment-manager.sh - --github-remote-dir="https://github.com/paritytech/substrate/tree/master/simnet_tests" - --config="simnet_tests/configs/default_local_testnet.toml" - --image="${SUBSTRATE_IMAGE_NAME}:${SUBSTRATE_IMAGE_TAG}" - retry: 2 - tags: - - substrate-simnet - -#run quick simnet-tests for each PR -simnet-tests-quick: - stage: deploy - image: docker.io/paritytech/simnet:${SIMNET_REF} - <<: *kubernetes-env - <<: *test-refs-no-trigger-prs-only - variables: - SIMNET_FEATURES: "${SIMNET_FEATURES_PATH}/quick" - needs: - - job: publish-docker-substrate-simnet - before_script: - - echo "Simnet Tests Config - docker.io/paritytech/simnet:${SIMNET_REF} - ${SUBSTRATE_IMAGE_NAME} ${SUBSTRATE_IMAGE_TAG}" - script: - - echo "Image=${SUBSTRATE_IMAGE_NAME}:${SUBSTRATE_IMAGE_TAG}" - - echo "Features=${SIMNET_FEATURES}" - - /home/nonroot/simnet/gurke/scripts/run-test-environment-manager.sh - --github-remote-dir="https://github.com/paritytech/substrate/tree/master/simnet_tests" - --config="simnet_tests/configs/default_local_testnet.toml" - --image="${SUBSTRATE_IMAGE_NAME}:${SUBSTRATE_IMAGE_TAG}" - --features="${SIMNET_FEATURES}" - tags: - - substrate-simnet - diff --git a/simnet_tests/README.md b/simnet_tests/README.md deleted file mode 100644 index cb1b13ae9850..000000000000 --- a/simnet_tests/README.md +++ /dev/null @@ -1,39 +0,0 @@ -# Simulation tests, or high level integration tests. - - -_The content of this directory is meant to be used by Parity's private CI/CD -infrastructure with private tools. At the moment those tools are still early -stage of development and we don't when if / when they will available for -public use._ - - -## Content of this dir. - -`configs` dir contains config files in toml format that describe how to -configure the simulation network that you want to launch. - -`tests` dir contains [cucumber](https://cucumber.io/) files. Those are -Behavior-Driven Development test files that describe tests in plain English. -Under the hood there are assertions that specific metrics should have specific -values. - -At the moment we have 2 tests: `tests/quick/001-smoketest.feature` and -`tests/long/002-loadtest.feature` -The load test uses a JS script that we added to simnet image and it's launched -by this step in the cucumber file: -`Then launch 'node' with parameters '/usr/local/bin/sub-flood --finalization --url ws://localhost:11222'` - -`run_test.sh` is a script meant to ease up launching a test. -In order to use this script locally, you need to install -[gurke](https://github.com/paritytech/gurke) -This script also helps preparing the test environment. Once you have access to -a kubernetes cluster (meaning you can do `kubectl get pods`) you can run this -script with no arguments, like `./run_test.sh` and tests should run. -Kubernetes cluster can be local, spawned with -[kind](https://kind.sigs.k8s.io/docs/user/quick-start/#installation) -or an instance living in the -[cloud](https://github.com/paritytech/gurke/blob/main/docs/How-to-setup-access-to-gke-k8s-cluster.md) - - -### [Here is link to barcamp presenation of simnet](https://www.crowdcast.io/e/ph49xu01) -### [Here is link to the simnet repo, hosted on private gitlab](https://gitlab.parity.io/parity/simnet/-/tree/master) diff --git a/simnet_tests/configs/default_local_testnet.toml b/simnet_tests/configs/default_local_testnet.toml deleted file mode 100644 index 066bd4c9e332..000000000000 --- a/simnet_tests/configs/default_local_testnet.toml +++ /dev/null @@ -1,14 +0,0 @@ -[settings] -bootnode-domain-name = "bootnode.{{get_env(name="NAMESPACE")}}.svc.cluster.local" - - -[settings.setup] -timeout = 300 - -[settings.defaults] -timeout = 300 - -[nodes] -alice = { extra-args = ["--alice"], validator = true } -bob = { extra-args = ["--bob"], validator = true } -charlie = { extra-args = ["--charlie"], validator = true } diff --git a/simnet_tests/run_tests.sh b/simnet_tests/run_tests.sh deleted file mode 100755 index 3b8ac8a71dad..000000000000 --- a/simnet_tests/run_tests.sh +++ /dev/null @@ -1,126 +0,0 @@ -#!/bin/bash - -### ARGS FOR THIS SCRIPT ### -# ./${SCRIPT_NAME} NAMESPACE IMAGE LOG_PATH FEATURES -# NAMESPACE the kubernetes namespace where the test will run -# IMAGE Substrate image used to spawn network -# LOG_PATH path to dir where to save logs from external JS script that is run as part -# of step in features file -# FEATURES directory containing cucumber files or single cucumber file that describes -# what to test. -# -# All args have default values, specify args to override -# e.g: ./${SCRIPT_NAME} test-name parity/substrate:latest logs quick - -set -eou pipefail -SCRIPT_NAME="$0" -SCRIPT_PATH=$(dirname "${SCRIPT_NAME}") # relative -SCRIPT_PATH=$(cd "${SCRIPT_PATH}" && pwd) # absolutized and normalized - -function random_string { - head -1 <(fold -w 30 <(tr -dc 'a-z0-9' < /dev/urandom)) - } - -# -### Script args -# - -NAMESPACE=${1:-gurke-"$(random_string)"-runtest} -IMAGE=${2:-"parity/substrate:latest"} -LOG_PATH=${3:-"${SCRIPT_PATH}/logs"} -FEATURES=${4:-"ALL"} - -mkdir -p "${SCRIPT_PATH}"/logs - -echo "Running tests in namespace: ${NAMESPACE}" -echo "Testing image: ${IMAGE}" -echo "Storing scripts logs to: ${LOG_PATH}" -echo "Using features files from: ${FEATURES}" - -# -### Script logic -# - -function forward_port { - # RUN_IN_CONTAINER is env var that is set in the dockerfile - # use the -v operator to explicitly test if a variable is set - if [[ ! -v RUN_IN_CONTAINER ]] ; then - if is_port_forward_running ; then - kill_previous_job - fi - fi - start_forwading_job -} - -FORWARD_GREP_FILTER='kubectl.*[p]ort-forward.*svc/rpc.*11222' - -function is_port_forward_running { - # shellcheck disable=SC2009 - ps aux | grep -qE "${FORWARD_GREP_FILTER}" -} - -function kill_previous_job { - # shellcheck disable=SC2009 - job_pid=$(ps aux | grep -E "${FORWARD_GREP_FILTER}" | awk '{ print $2 }') - echo "INFO Killed forwading port 9944 into bootnode" - kill "${job_pid}" -} - -function start_forwading_job { - kubectl -n "${NAMESPACE}" \ - expose pod bootnode \ - --name=rpc \ - --type=NodePort \ - --target-port=9944 \ - --port=9944 - kubectl -n "${NAMESPACE}" \ - port-forward svc/rpc 11222:9944 &> "${LOG_PATH}/forward-${NAMESPACE}.log" & - sleep 2 - echo "INFO Started forwading port 9944 into bootnode" -} - -function update_api { - echo "INFO: Updating Polkadot JS API" - pwd - cd "${SCRIPT_PATH}"/../../sub-flood/ - npm run build - cd - -} - -function run_test { - case "${FEATURES}" in - quick) - gurke test "${NAMESPACE}" "${SCRIPT_PATH}"/tests/quick --log-path "${LOG_PATH}" - ;; - long) - gurke test "${NAMESPACE}" "${SCRIPT_PATH}"/tests/long --log-path "${LOG_PATH}" - ;; - ALL ) - gurke test "${NAMESPACE}" "${SCRIPT_PATH}"/tests --log-path "${LOG_PATH}" - ;; - ??* ) - gurke test \ - "${NAMESPACE}" \ - "${SCRIPT_PATH}"/"${FEATURES}" \ - --log-path "${LOG_PATH}" - ;; - esac -} - - -export NAMESPACE="${NAMESPACE}" - -set -x # echo the commands to stdout -gurke spawn --config "${SCRIPT_PATH}"/configs/default_local_testnet.toml \ - -n "${NAMESPACE}" \ - --image "${IMAGE}" - -echo "INFO: Checking if pods launched correctly" -kubectl -n "${NAMESPACE}" get pods -o wide - -update_api - -forward_port -run_test - - diff --git a/simnet_tests/tests/long/002-loadtest.feature b/simnet_tests/tests/long/002-loadtest.feature deleted file mode 100644 index 67d108ea5541..000000000000 --- a/simnet_tests/tests/long/002-loadtest.feature +++ /dev/null @@ -1,5 +0,0 @@ -Feature: LoadTesting - - Scenario: spawn 50k transactions and wait their finalization - Given a test network - Then launch 'node' with parameters '/usr/local/bin/sub-flood --finalization --url ws://localhost:11222' diff --git a/simnet_tests/tests/quick/001-smoketest.feature b/simnet_tests/tests/quick/001-smoketest.feature deleted file mode 100644 index a07041e4ea62..000000000000 --- a/simnet_tests/tests/quick/001-smoketest.feature +++ /dev/null @@ -1,16 +0,0 @@ -Feature: Smoketest - - Scenario: Minimal Example - Given a test network - Then alice is up - And alice reports substrate_node_roles is 4 - And alice reports substrate_sub_libp2p_is_major_syncing is 0 - When alice's best block should be above 30 - Then alice reports block height is greater than 30 - And alice reports peers count is at least 2 - Then bob is up - And bob reports block height is greater than 30 - And bob reports peers count is at least 2 - Then charlie is up - And charlie reports block height is greater than 30 - And charlie reports peers count is at least 2 From a634b44f504e57c33797e831d8e54ca97816ffed Mon Sep 17 00:00:00 2001 From: Andreas Doerr Date: Fri, 10 Dec 2021 09:33:23 +0100 Subject: [PATCH 279/695] BEEFY update CODEOWNERS (#10460) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * BEEFY update CODEOWNERS Remove myself as `BEEFY` code owner. New code owner needs to be decided upon. * Update docs/CODEOWNERS * Update docs/CODEOWNERS * Update docs/CODEOWNERS Co-authored-by: Bastian Köcher --- docs/CODEOWNERS | 6 ------ 1 file changed, 6 deletions(-) diff --git a/docs/CODEOWNERS b/docs/CODEOWNERS index ee6382b72f1b..42d25a0a228f 100644 --- a/docs/CODEOWNERS +++ b/docs/CODEOWNERS @@ -40,12 +40,6 @@ /client/consensus/pow/ @sorpaas /primitives/consensus/pow/ @sorpaas -# BEEFY -/client/beefy/ @adoerr -/frame/beefy/ @adoerr -/frame/beefy-mmr/ @adoerr -/primitives/beefy/ @adoerr - # Contracts /frame/contracts/ @athei From be75e554aa14774804bc949b2d77f424b74e23fd Mon Sep 17 00:00:00 2001 From: Koute Date: Fri, 10 Dec 2021 20:31:04 +0900 Subject: [PATCH 280/695] Automatically unsubscribe storage listeners when they're dropped (RCP node memory leak fix) (#10454) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Automatically unsubscribe storage listeners when they're dropped * Fix tests' compilation in `sc-client-api` * Add an extra test * Align to review comments; cleanups * Update client/api/src/notifications.rs * FMT Co-authored-by: Bastian Köcher Co-authored-by: Bastian Köcher --- client/api/src/notifications.rs | 229 ++++++++++++++++++++++++-------- 1 file changed, 174 insertions(+), 55 deletions(-) diff --git a/client/api/src/notifications.rs b/client/api/src/notifications.rs index 9565fd673acf..88a709beb1f0 100644 --- a/client/api/src/notifications.rs +++ b/client/api/src/notifications.rs @@ -20,13 +20,20 @@ use std::{ collections::{HashMap, HashSet}, - sync::Arc, + pin::Pin, + sync::{Arc, Weak}, + task::Poll, }; use fnv::{FnvHashMap, FnvHashSet}; +use futures::Stream; +use parking_lot::Mutex; use prometheus_endpoint::{register, CounterVec, Opts, Registry, U64}; use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender}; -use sp_core::storage::{StorageData, StorageKey}; +use sp_core::{ + hexdisplay::HexDisplay, + storage::{StorageData, StorageKey}, +}; use sp_runtime::traits::Block as BlockT; /// Storage change set @@ -34,8 +41,8 @@ use sp_runtime::traits::Block as BlockT; pub struct StorageChangeSet { changes: Arc)>>, child_changes: Arc)>)>>, - filter: Option>, - child_filters: Option>>>, + filter: Keys, + child_filters: ChildKeys, } impl StorageChangeSet { @@ -74,7 +81,46 @@ impl StorageChangeSet { } /// Type that implements `futures::Stream` of storage change events. -pub type StorageEventStream = TracingUnboundedReceiver<(H, StorageChangeSet)>; +pub struct StorageEventStream { + rx: TracingUnboundedReceiver<(H, StorageChangeSet)>, + storage_notifications: Weak>>, + was_triggered: bool, + id: u64, +} + +impl Stream for StorageEventStream { + type Item = as Stream>::Item; + fn poll_next( + mut self: Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> Poll> { + let result = Stream::poll_next(Pin::new(&mut self.rx), cx); + if result.is_ready() { + self.was_triggered = true; + } + result + } +} + +impl Drop for StorageEventStream { + fn drop(&mut self) { + if let Some(storage_notifications) = self.storage_notifications.upgrade() { + if let Some((keys, child_keys)) = + storage_notifications.lock().remove_subscriber(self.id) + { + if !self.was_triggered { + log::trace!( + target: "storage_notifications", + "Listener was never triggered: id={}, keys={:?}, child_keys={:?}", + self.id, + PrintKeys(&keys), + PrintChildKeys(&child_keys), + ); + } + } + } + } +} type SubscriberId = u64; @@ -82,7 +128,13 @@ type SubscribersGauge = CounterVec; /// Manages storage listeners. #[derive(Debug)] -pub struct StorageNotifications { +pub struct StorageNotifications(Arc>>); + +type Keys = Option>; +type ChildKeys = Option>>>; + +#[derive(Debug)] +struct StorageNotificationsImpl { metrics: Option, next_id: SubscriberId, wildcard_listeners: FnvHashSet, @@ -93,15 +145,17 @@ pub struct StorageNotifications { >, sinks: FnvHashMap< SubscriberId, - ( - TracingUnboundedSender<(Block::Hash, StorageChangeSet)>, - Option>, - Option>>>, - ), + (TracingUnboundedSender<(Hash, StorageChangeSet)>, Keys, ChildKeys), >, } impl Default for StorageNotifications { + fn default() -> Self { + Self(Default::default()) + } +} + +impl Default for StorageNotificationsImpl { fn default() -> Self { Self { metrics: Default::default(), @@ -114,10 +168,68 @@ impl Default for StorageNotifications { } } +struct PrintKeys<'a>(&'a Keys); +impl<'a> std::fmt::Debug for PrintKeys<'a> { + fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { + if let Some(keys) = self.0 { + fmt.debug_list().entries(keys.iter().map(HexDisplay::from)).finish() + } else { + write!(fmt, "None") + } + } +} + +struct PrintChildKeys<'a>(&'a ChildKeys); +impl<'a> std::fmt::Debug for PrintChildKeys<'a> { + fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { + if let Some(map) = self.0 { + fmt.debug_map() + .entries(map.iter().map(|(key, values)| (HexDisplay::from(key), PrintKeys(values)))) + .finish() + } else { + write!(fmt, "None") + } + } +} + impl StorageNotifications { /// Initialize a new StorageNotifications /// optionally pass a prometheus registry to send subscriber metrics to pub fn new(prometheus_registry: Option) -> Self { + StorageNotifications(Arc::new(Mutex::new(StorageNotificationsImpl::new( + prometheus_registry, + )))) + } + + /// Trigger notification to all listeners. + /// + /// Note the changes are going to be filtered by listener's filter key. + /// In fact no event might be sent if clients are not interested in the changes. + pub fn trigger( + &mut self, + hash: &Block::Hash, + changeset: impl Iterator, Option>)>, + child_changeset: impl Iterator< + Item = (Vec, impl Iterator, Option>)>), + >, + ) { + self.0.lock().trigger(hash, changeset, child_changeset); + } + + /// Start listening for particular storage keys. + pub fn listen( + &mut self, + filter_keys: Option<&[StorageKey]>, + filter_child_keys: Option<&[(StorageKey, Option>)]>, + ) -> StorageEventStream { + let (id, rx) = self.0.lock().listen(filter_keys, filter_child_keys); + let storage_notifications = Arc::downgrade(&self.0); + StorageEventStream { rx, storage_notifications, was_triggered: false, id } + } +} + +impl StorageNotificationsImpl { + fn new(prometheus_registry: Option) -> Self { let metrics = prometheus_registry.and_then(|r| { CounterVec::new( Opts::new( @@ -130,7 +242,7 @@ impl StorageNotifications { .ok() }); - StorageNotifications { + StorageNotificationsImpl { metrics, next_id: Default::default(), wildcard_listeners: Default::default(), @@ -139,18 +251,16 @@ impl StorageNotifications { sinks: Default::default(), } } - /// Trigger notification to all listeners. - /// - /// Note the changes are going to be filtered by listener's filter key. - /// In fact no event might be sent if clients are not interested in the changes. - pub fn trigger( + fn trigger( &mut self, - hash: &Block::Hash, + hash: &Hash, changeset: impl Iterator, Option>)>, child_changeset: impl Iterator< Item = (Vec, impl Iterator, Option>)>), >, - ) { + ) where + Hash: Clone, + { let has_wildcard = !self.wildcard_listeners.is_empty(); // early exit if no listeners @@ -244,7 +354,7 @@ impl StorageNotifications { fn remove_subscriber_from( subscriber: &SubscriberId, - filters: &Option>, + filters: &Keys, listeners: &mut HashMap>, wildcards: &mut FnvHashSet, ) { @@ -269,34 +379,35 @@ impl StorageNotifications { } } - fn remove_subscriber(&mut self, subscriber: SubscriberId) { - if let Some((_, filters, child_filters)) = self.sinks.remove(&subscriber) { - Self::remove_subscriber_from( - &subscriber, - &filters, - &mut self.listeners, - &mut self.wildcard_listeners, - ); - if let Some(child_filters) = child_filters.as_ref() { - for (c_key, filters) in child_filters { - if let Some((listeners, wildcards)) = self.child_listeners.get_mut(&c_key) { - Self::remove_subscriber_from( - &subscriber, - &filters, - &mut *listeners, - &mut *wildcards, - ); - - if listeners.is_empty() && wildcards.is_empty() { - self.child_listeners.remove(&c_key); - } + fn remove_subscriber(&mut self, subscriber: SubscriberId) -> Option<(Keys, ChildKeys)> { + let (_, filters, child_filters) = self.sinks.remove(&subscriber)?; + Self::remove_subscriber_from( + &subscriber, + &filters, + &mut self.listeners, + &mut self.wildcard_listeners, + ); + if let Some(child_filters) = child_filters.as_ref() { + for (c_key, filters) in child_filters { + if let Some((listeners, wildcards)) = self.child_listeners.get_mut(&c_key) { + Self::remove_subscriber_from( + &subscriber, + &filters, + &mut *listeners, + &mut *wildcards, + ); + + if listeners.is_empty() && wildcards.is_empty() { + self.child_listeners.remove(&c_key); } } } - if let Some(m) = self.metrics.as_ref() { - m.with_label_values(&[&"removed"]).inc(); - } } + if let Some(m) = self.metrics.as_ref() { + m.with_label_values(&[&"removed"]).inc(); + } + + Some((filters, child_filters)) } fn listen_from( @@ -304,7 +415,7 @@ impl StorageNotifications { filter_keys: &Option>, listeners: &mut HashMap>, wildcards: &mut FnvHashSet, - ) -> Option> { + ) -> Keys { match filter_keys { None => { wildcards.insert(current_id); @@ -325,12 +436,11 @@ impl StorageNotifications { } } - /// Start listening for particular storage keys. - pub fn listen( + fn listen( &mut self, filter_keys: Option<&[StorageKey]>, filter_child_keys: Option<&[(StorageKey, Option>)]>, - ) -> StorageEventStream { + ) -> (u64, TracingUnboundedReceiver<(Hash, StorageChangeSet)>) { self.next_id += 1; let current_id = self.next_id; @@ -364,7 +474,7 @@ impl StorageNotifications { m.with_label_values(&[&"added"]).inc(); } - rx + (current_id, rx) } } @@ -517,9 +627,9 @@ mod tests { let _recv3 = futures::executor::block_on_stream(notifications.listen(None, None)); let _recv4 = futures::executor::block_on_stream(notifications.listen(None, Some(&child_filter))); - assert_eq!(notifications.listeners.len(), 2); - assert_eq!(notifications.wildcard_listeners.len(), 2); - assert_eq!(notifications.child_listeners.len(), 1); + assert_eq!(notifications.0.lock().listeners.len(), 2); + assert_eq!(notifications.0.lock().wildcard_listeners.len(), 2); + assert_eq!(notifications.0.lock().child_listeners.len(), 1); } // when @@ -528,9 +638,18 @@ mod tests { notifications.trigger(&Hash::from_low_u64_be(1), changeset.into_iter(), c_changeset); // then - assert_eq!(notifications.listeners.len(), 0); - assert_eq!(notifications.wildcard_listeners.len(), 0); - assert_eq!(notifications.child_listeners.len(), 0); + assert_eq!(notifications.0.lock().listeners.len(), 0); + assert_eq!(notifications.0.lock().wildcard_listeners.len(), 0); + assert_eq!(notifications.0.lock().child_listeners.len(), 0); + } + + #[test] + fn should_cleanup_subscriber_if_stream_is_dropped() { + let mut notifications = StorageNotifications::::default(); + let stream = notifications.listen(None, None); + assert_eq!(notifications.0.lock().sinks.len(), 1); + std::mem::drop(stream); + assert_eq!(notifications.0.lock().sinks.len(), 0); } #[test] From 5f49f1498a44614e3fb48394c99d4e8a253e910f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Fri, 10 Dec 2021 15:26:17 +0100 Subject: [PATCH 281/695] Make sure that weight for loading code into the sandbox is accounted for (#10448) --- frame/contracts/src/benchmarking/code.rs | 23 +- frame/contracts/src/benchmarking/mod.rs | 41 +- frame/contracts/src/tests.rs | 2 +- frame/contracts/src/wasm/code_cache.rs | 20 +- frame/contracts/src/weights.rs | 1192 +++++++++++----------- 5 files changed, 653 insertions(+), 625 deletions(-) diff --git a/frame/contracts/src/benchmarking/code.rs b/frame/contracts/src/benchmarking/code.rs index 5dac8a84ace8..49df1c383821 100644 --- a/frame/contracts/src/benchmarking/code.rs +++ b/frame/contracts/src/benchmarking/code.rs @@ -41,6 +41,14 @@ use sp_sandbox::{ }; use sp_std::{borrow::ToOwned, prelude::*}; +/// The location where to put the genrated code. +pub enum Location { + /// Generate all code into the `call` exported function. + Call, + /// Generate all code into the `deploy` exported function. + Deploy, +} + /// Pass to `create_code` in order to create a compiled `WasmModule`. /// /// This exists to have a more declarative way to describe a wasm module than to use @@ -308,7 +316,8 @@ where /// Creates a wasm module of `target_bytes` size. Used to benchmark the performance of /// `instantiate_with_code` for different sizes of wasm modules. The generated module maximizes /// instrumentation runtime by nesting blocks as deeply as possible given the byte budget. - pub fn sized(target_bytes: u32) -> Self { + /// `code_location`: Whether to place the code into `deploy` or `call`. + pub fn sized(target_bytes: u32, code_location: Location) -> Self { use self::elements::Instruction::{End, I32Const, If, Return}; // Base size of a contract is 63 bytes and each expansion adds 6 bytes. // We do one expansion less to account for the code section and function body @@ -317,12 +326,14 @@ where // because of the maximum code size that is enforced by `instantiate_with_code`. let expansions = (target_bytes.saturating_sub(63) / 6).saturating_sub(1); const EXPANSION: [Instruction; 4] = [I32Const(0), If(BlockType::NoResult), Return, End]; - ModuleDefinition { - call_body: Some(body::repeated(expansions, &EXPANSION)), - memory: Some(ImportedMemory::max::()), - ..Default::default() + let mut module = + ModuleDefinition { memory: Some(ImportedMemory::max::()), ..Default::default() }; + let body = Some(body::repeated(expansions, &EXPANSION)); + match code_location { + Location::Call => module.call_body = body, + Location::Deploy => module.deploy_body = body, } - .into() + module.into() } /// Creates a wasm module that calls the imported function named `getter_name` `repeat` diff --git a/frame/contracts/src/benchmarking/mod.rs b/frame/contracts/src/benchmarking/mod.rs index 884fddb6f907..ae39d1feca11 100644 --- a/frame/contracts/src/benchmarking/mod.rs +++ b/frame/contracts/src/benchmarking/mod.rs @@ -25,7 +25,7 @@ mod sandbox; use self::{ code::{ body::{self, DynInstr::*}, - DataSegment, ImportedFunction, ImportedMemory, ModuleDefinition, WasmModule, + DataSegment, ImportedFunction, ImportedMemory, Location, ModuleDefinition, WasmModule, }, sandbox::Sandbox, }; @@ -229,9 +229,9 @@ benchmarks! { // This benchmarks the additional weight that is charged when a contract is executed the // first time after a new schedule was deployed: For every new schedule a contract needs // to re-run the instrumentation once. - instrument { + reinstrument { let c in 0 .. T::Schedule::get().limits.code_len / 1024; - let WasmModule { code, hash, .. } = WasmModule::::sized(c * 1024); + let WasmModule { code, hash, .. } = WasmModule::::sized(c * 1024, Location::Call); Contracts::::store_code_raw(code, whitelisted_caller())?; let schedule = T::Schedule::get(); let mut gas_meter = GasMeter::new(Weight::MAX); @@ -240,21 +240,28 @@ benchmarks! { Contracts::::reinstrument_module(&mut module, &schedule)?; } - // The weight of loading and decoding of a contract's code per kilobyte. - code_load { + // This benchmarks the overhead of loading a code of size `c` kb from storage and into + // the sandbox. This does **not** include the actual execution for which the gas meter + // is responsible. This is achieved by generating all code to the `deploy` function + // which is in the wasm module but not executed on `call`. + // The results are supposed to be used as `call_with_code_kb(c) - call_with_code_kb(0)`. + call_with_code_kb { let c in 0 .. T::Schedule::get().limits.code_len / 1024; - let WasmModule { code, hash, .. } = WasmModule::::dummy_with_bytes(c * 1024); - Contracts::::store_code_raw(code, whitelisted_caller())?; - let schedule = T::Schedule::get(); - let mut gas_meter = GasMeter::new(Weight::MAX); - }: { - >::from_storage(hash, &schedule, &mut gas_meter)?; - } + let instance = Contract::::with_caller( + whitelisted_caller(), WasmModule::sized(c * 1024, Location::Deploy), vec![], + )?; + let value = T::Currency::minimum_balance(); + let origin = RawOrigin::Signed(instance.caller.clone()); + let callee = instance.addr.clone(); + }: call(origin, callee, value, Weight::MAX, None, vec![]) // This constructs a contract that is maximal expensive to instrument. // It creates a maximum number of metering blocks per byte. // The size of the salt influences the runtime because is is hashed in order to - // determine the contract address. + // determine the contract address. All code is generated to the `call` function so that + // we don't benchmark the actual execution of this code but merely what it takes to load + // a code of that size into the sandbox. + // // `c`: Size of the code in kilobytes. // `s`: Size of the salt in kilobytes. // @@ -269,7 +276,7 @@ benchmarks! { let value = T::Currency::minimum_balance(); let caller = whitelisted_caller(); T::Currency::make_free_balance_be(&caller, caller_funding::()); - let WasmModule { code, hash, .. } = WasmModule::::sized(c * 1024); + let WasmModule { code, hash, .. } = WasmModule::::sized(c * 1024, Location::Call); let origin = RawOrigin::Signed(caller.clone()); let addr = Contracts::::contract_address(&caller, &hash, &salt); }: _(origin, value, Weight::MAX, None, code, vec![], salt) @@ -316,7 +323,9 @@ benchmarks! { // The size of the data has no influence on the costs of this extrinsic as long as the contract // won't call `seal_input` in its constructor to copy the data to contract memory. // The dummy contract used here does not do this. The costs for the data copy is billed as - // part of `seal_input`. + // part of `seal_input`. The costs for invoking a contract of a specific size are not part + // of this benchmark because we cannot know the size of the contract when issuing a call + // transaction. See `invoke_per_code_kb` for this. call { let data = vec![42u8; 1024]; let instance = Contract::::with_caller( @@ -353,7 +362,7 @@ benchmarks! { let c in 0 .. Perbill::from_percent(50).mul_ceil(T::Schedule::get().limits.code_len / 1024); let caller = whitelisted_caller(); T::Currency::make_free_balance_be(&caller, caller_funding::()); - let WasmModule { code, hash, .. } = WasmModule::::sized(c * 1024); + let WasmModule { code, hash, .. } = WasmModule::::sized(c * 1024, Location::Call); let origin = RawOrigin::Signed(caller.clone()); }: _(origin, code, None) verify { diff --git a/frame/contracts/src/tests.rs b/frame/contracts/src/tests.rs index 1554d1230089..1078a7e73352 100644 --- a/frame/contracts/src/tests.rs +++ b/frame/contracts/src/tests.rs @@ -1903,7 +1903,7 @@ fn reinstrument_does_charge() { assert!(result2.gas_consumed > result1.gas_consumed); assert_eq!( result2.gas_consumed, - result1.gas_consumed + ::WeightInfo::instrument(code_len / 1024), + result1.gas_consumed + ::WeightInfo::reinstrument(code_len / 1024), ); }); } diff --git a/frame/contracts/src/wasm/code_cache.rs b/frame/contracts/src/wasm/code_cache.rs index 823d6ed34a67..2cff043f64ef 100644 --- a/frame/contracts/src/wasm/code_cache.rs +++ b/frame/contracts/src/wasm/code_cache.rs @@ -158,7 +158,7 @@ where if prefab_module.instruction_weights_version < schedule.instruction_weights.version { // The instruction weights have changed. // We need to re-instrument the code with the new instruction weights. - gas_meter.charge(CodeToken::Instrument(estimate_code_size::, _>( + gas_meter.charge(CodeToken::Reinstrument(estimate_code_size::, _>( &code_hash, )?))?; reinstrument(&mut prefab_module, schedule)?; @@ -201,9 +201,9 @@ where #[cfg_attr(test, derive(Debug, PartialEq, Eq))] #[derive(Clone, Copy)] enum CodeToken { - /// Weight for instrumenting a contract contract of the supplied size in bytes. - Instrument(u32), - /// Weight for loading a contract per kilobyte. + /// Weight for reinstrumenting a contract contract of the supplied size in bytes. + Reinstrument(u32), + /// Weight for loading a contract per byte. Load(u32), } @@ -211,14 +211,14 @@ impl Token for CodeToken { fn weight(&self) -> Weight { use self::CodeToken::*; // In case of `Load` we already covered the general costs of - // accessing the storage but still need to account for the actual size of the + // calling the storage but still need to account for the actual size of the // contract code. This is why we substract `T::*::(0)`. We need to do this at this - // point because when charging the general weight we do not know the size of - // the contract. + // point because when charging the general weight for calling the contract we not know the + // size of the contract. match *self { - Instrument(len) => T::WeightInfo::instrument(len / 1024), - Load(len) => - T::WeightInfo::code_load(len / 1024).saturating_sub(T::WeightInfo::code_load(0)), + Reinstrument(len) => T::WeightInfo::reinstrument(len / 1024), + Load(len) => T::WeightInfo::call_with_code_kb(len / 1024) + .saturating_sub(T::WeightInfo::call_with_code_kb(0)), } } } diff --git a/frame/contracts/src/weights.rs b/frame/contracts/src/weights.rs index 8a78a7f289a6..5f61c1e4a346 100644 --- a/frame/contracts/src/weights.rs +++ b/frame/contracts/src/weights.rs @@ -47,8 +47,8 @@ pub trait WeightInfo { fn on_initialize() -> Weight; fn on_initialize_per_trie_key(k: u32, ) -> Weight; fn on_initialize_per_queue_item(q: u32, ) -> Weight; - fn instrument(c: u32, ) -> Weight; - fn code_load(c: u32, ) -> Weight; + fn reinstrument(c: u32, ) -> Weight; + fn call_with_code_kb(c: u32, ) -> Weight; fn instantiate_with_code(c: u32, s: u32, ) -> Weight; fn instantiate(s: u32, ) -> Weight; fn call() -> Weight; @@ -150,41 +150,45 @@ pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize() -> Weight { - (2_854_000 as Weight) + (2_720_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn on_initialize_per_trie_key(k: u32, ) -> Weight { (0 as Weight) // Standard Error: 3_000 - .saturating_add((2_190_000 as Weight).saturating_mul(k as Weight)) + .saturating_add((2_208_000 as Weight).saturating_mul(k as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) } // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize_per_queue_item(q: u32, ) -> Weight { - (101_551_000 as Weight) + (95_834_000 as Weight) // Standard Error: 2_000 - .saturating_add((292_000 as Weight).saturating_mul(q as Weight)) + .saturating_add((317_000 as Weight).saturating_mul(q as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Contracts PristineCode (r:1 w:0) // Storage: Contracts CodeStorage (r:0 w:1) - fn instrument(c: u32, ) -> Weight { - (33_350_000 as Weight) - // Standard Error: 106_000 - .saturating_add((91_098_000 as Weight).saturating_mul(c as Weight)) + fn reinstrument(c: u32, ) -> Weight { + (17_177_000 as Weight) + // Standard Error: 85_000 + .saturating_add((91_306_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } + // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) - fn code_load(c: u32, ) -> Weight { - (8_080_000 as Weight) - // Standard Error: 0 - .saturating_add((1_455_000 as Weight).saturating_mul(c as Weight)) - .saturating_add(T::DbWeight::get().reads(1 as Weight)) + // Storage: Timestamp Now (r:1 w:0) + // Storage: System Account (r:1 w:1) + fn call_with_code_kb(c: u32, ) -> Weight { + (371_888_000 as Weight) + // Standard Error: 137_000 + .saturating_add((92_314_000 as Weight).saturating_mul(c as Weight)) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Contracts CodeStorage (r:1 w:1) // Storage: Contracts AccountCounter (r:1 w:1) @@ -194,11 +198,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn instantiate_with_code(c: u32, s: u32, ) -> Weight { - (464_920_000 as Weight) - // Standard Error: 136_000 - .saturating_add((211_340_000 as Weight).saturating_mul(c as Weight)) - // Standard Error: 8_000 - .saturating_add((2_190_000 as Weight).saturating_mul(s as Weight)) + (429_131_000 as Weight) + // Standard Error: 154_000 + .saturating_add((208_736_000 as Weight).saturating_mul(c as Weight)) + // Standard Error: 10_000 + .saturating_add((2_203_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } @@ -209,9 +213,9 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn instantiate(s: u32, ) -> Weight { - (236_192_000 as Weight) + (241_132_000 as Weight) // Standard Error: 2_000 - .saturating_add((2_010_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((1_986_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } @@ -220,7 +224,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call() -> Weight { - (172_780_000 as Weight) + (173_649_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -228,9 +232,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn upload_code(c: u32, ) -> Weight { - (80_415_000 as Weight) - // Standard Error: 98_000 - .saturating_add((93_463_000 as Weight).saturating_mul(c as Weight)) + (84_508_000 as Weight) + // Standard Error: 93_000 + .saturating_add((91_690_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -238,7 +242,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:0 w:1) // Storage: Contracts PristineCode (r:0 w:1) fn remove_code() -> Weight { - (40_042_000 as Weight) + (39_407_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -247,9 +251,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_caller(r: u32, ) -> Weight { - (416_770_000 as Weight) - // Standard Error: 175_000 - .saturating_add((114_550_000 as Weight).saturating_mul(r as Weight)) + (421_879_000 as Weight) + // Standard Error: 168_000 + .saturating_add((114_154_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -258,9 +262,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_address(r: u32, ) -> Weight { - (415_774_000 as Weight) - // Standard Error: 176_000 - .saturating_add((115_169_000 as Weight).saturating_mul(r as Weight)) + (428_124_000 as Weight) + // Standard Error: 167_000 + .saturating_add((113_196_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -269,9 +273,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas_left(r: u32, ) -> Weight { - (411_883_000 as Weight) - // Standard Error: 200_000 - .saturating_add((113_740_000 as Weight).saturating_mul(r as Weight)) + (424_405_000 as Weight) + // Standard Error: 182_000 + .saturating_add((112_511_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -280,9 +284,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_balance(r: u32, ) -> Weight { - (422_382_000 as Weight) - // Standard Error: 189_000 - .saturating_add((313_581_000 as Weight).saturating_mul(r as Weight)) + (433_901_000 as Weight) + // Standard Error: 206_000 + .saturating_add((307_273_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -291,9 +295,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_value_transferred(r: u32, ) -> Weight { - (437_411_000 as Weight) - // Standard Error: 191_000 - .saturating_add((111_580_000 as Weight).saturating_mul(r as Weight)) + (428_707_000 as Weight) + // Standard Error: 203_000 + .saturating_add((113_558_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -302,9 +306,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_minimum_balance(r: u32, ) -> Weight { - (431_815_000 as Weight) - // Standard Error: 170_000 - .saturating_add((111_289_000 as Weight).saturating_mul(r as Weight)) + (423_775_000 as Weight) + // Standard Error: 174_000 + .saturating_add((113_371_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -313,9 +317,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_block_number(r: u32, ) -> Weight { - (430_451_000 as Weight) - // Standard Error: 152_000 - .saturating_add((111_214_000 as Weight).saturating_mul(r as Weight)) + (423_282_000 as Weight) + // Standard Error: 220_000 + .saturating_add((113_709_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -324,9 +328,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_now(r: u32, ) -> Weight { - (419_363_000 as Weight) - // Standard Error: 175_000 - .saturating_add((112_089_000 as Weight).saturating_mul(r as Weight)) + (435_209_000 as Weight) + // Standard Error: 157_000 + .saturating_add((111_492_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -336,9 +340,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0) fn seal_weight_to_fee(r: u32, ) -> Weight { - (427_501_000 as Weight) - // Standard Error: 247_000 - .saturating_add((262_104_000 as Weight).saturating_mul(r as Weight)) + (432_886_000 as Weight) + // Standard Error: 193_000 + .saturating_add((260_787_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -347,9 +351,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas(r: u32, ) -> Weight { - (145_426_000 as Weight) - // Standard Error: 115_000 - .saturating_add((52_082_000 as Weight).saturating_mul(r as Weight)) + (147_315_000 as Weight) + // Standard Error: 124_000 + .saturating_add((52_336_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -358,9 +362,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input(r: u32, ) -> Weight { - (415_783_000 as Weight) - // Standard Error: 184_000 - .saturating_add((101_266_000 as Weight).saturating_mul(r as Weight)) + (422_074_000 as Weight) + // Standard Error: 199_000 + .saturating_add((100_398_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -369,9 +373,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input_per_kb(n: u32, ) -> Weight { - (536_645_000 as Weight) - // Standard Error: 6_000 - .saturating_add((38_077_000 as Weight).saturating_mul(n as Weight)) + (543_944_000 as Weight) + // Standard Error: 10_000 + .saturating_add((38_098_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -380,9 +384,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return(r: u32, ) -> Weight { - (412_785_000 as Weight) - // Standard Error: 92_000 - .saturating_add((1_476_000 as Weight).saturating_mul(r as Weight)) + (398_945_000 as Weight) + // Standard Error: 417_000 + .saturating_add((15_763_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -391,9 +395,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return_per_kb(n: u32, ) -> Weight { - (400_232_000 as Weight) + (416_850_000 as Weight) // Standard Error: 1_000 - .saturating_add((644_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((635_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -404,9 +408,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts DeletionQueue (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_terminate(r: u32, ) -> Weight { - (409_343_000 as Weight) - // Standard Error: 1_325_000 - .saturating_add((101_661_000 as Weight).saturating_mul(r as Weight)) + (408_445_000 as Weight) + // Standard Error: 248_000 + .saturating_add((102_109_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((4 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -418,9 +422,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) fn seal_random(r: u32, ) -> Weight { - (417_354_000 as Weight) - // Standard Error: 299_000 - .saturating_add((343_766_000 as Weight).saturating_mul(r as Weight)) + (410_845_000 as Weight) + // Standard Error: 289_000 + .saturating_add((341_867_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -429,9 +433,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_deposit_event(r: u32, ) -> Weight { - (412_092_000 as Weight) - // Standard Error: 403_000 - .saturating_add((568_199_000 as Weight).saturating_mul(r as Weight)) + (425_037_000 as Weight) + // Standard Error: 424_000 + .saturating_add((571_604_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -441,11 +445,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: System EventTopics (r:100 w:100) fn seal_deposit_event_per_topic_and_kb(t: u32, n: u32, ) -> Weight { - (1_095_614_000 as Weight) - // Standard Error: 2_151_000 - .saturating_add((455_690_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 424_000 - .saturating_add((163_553_000 as Weight).saturating_mul(n as Weight)) + (1_055_868_000 as Weight) + // Standard Error: 3_004_000 + .saturating_add((453_979_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 592_000 + .saturating_add((166_716_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(t as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -456,17 +460,17 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_debug_message(r: u32, ) -> Weight { - (169_113_000 as Weight) - // Standard Error: 146_000 - .saturating_add((72_877_000 as Weight).saturating_mul(r as Weight)) + (161_170_000 as Weight) + // Standard Error: 169_000 + .saturating_add((74_379_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage(r: u32, ) -> Weight { - (484_647_000 as Weight) - // Standard Error: 479_000 - .saturating_add((369_854_000 as Weight).saturating_mul(r as Weight)) + (500_168_000 as Weight) + // Standard Error: 473_000 + .saturating_add((371_239_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -478,17 +482,17 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: unknown [0x7afa01283080ef247df84e0ba38ea5a587d25ce6633a6bfbba02068c14023441] (r:1 w:1) fn seal_set_storage_per_kb(n: u32, ) -> Weight { - (793_777_000 as Weight) - // Standard Error: 264_000 - .saturating_add((73_253_000 as Weight).saturating_mul(n as Weight)) + (796_175_000 as Weight) + // Standard Error: 249_000 + .saturating_add((74_071_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage(r: u32, ) -> Weight { - (180_385_000 as Weight) - // Standard Error: 1_470_000 - .saturating_add((834_911_000 as Weight).saturating_mul(r as Weight)) + (178_237_000 as Weight) + // Standard Error: 1_652_000 + .saturating_add((835_947_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -496,9 +500,9 @@ impl WeightInfo for SubstrateWeight { } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage(r: u32, ) -> Weight { - (282_452_000 as Weight) - // Standard Error: 802_000 - .saturating_add((492_119_000 as Weight).saturating_mul(r as Weight)) + (305_702_000 as Weight) + // Standard Error: 750_000 + .saturating_add((493_580_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -509,9 +513,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: unknown [0x7afa01283080ef247df84e0ba38ea5a587d25ce6633a6bfbba02068c14023441] (r:1 w:0) fn seal_get_storage_per_kb(n: u32, ) -> Weight { - (687_019_000 as Weight) - // Standard Error: 226_000 - .saturating_add((111_245_000 as Weight).saturating_mul(n as Weight)) + (697_017_000 as Weight) + // Standard Error: 216_000 + .saturating_add((111_743_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -520,9 +524,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_transfer(r: u32, ) -> Weight { - (273_106_000 as Weight) - // Standard Error: 1_498_000 - .saturating_add((3_509_324_000 as Weight).saturating_mul(r as Weight)) + (243_124_000 as Weight) + // Standard Error: 1_718_000 + .saturating_add((3_530_873_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -533,9 +537,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_call(r: u32, ) -> Weight { - (2_702_839_000 as Weight) - // Standard Error: 21_310_000 - .saturating_add((37_721_061_000 as Weight).saturating_mul(r as Weight)) + (140_524_000 as Weight) + // Standard Error: 4_504_000 + .saturating_add((39_287_224_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -546,13 +550,13 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:2 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_call_per_transfer_input_output_kb(t: u32, i: u32, o: u32, ) -> Weight { - (40_088_516_000 as Weight) - // Standard Error: 69_999_000 - .saturating_add((2_981_897_000 as Weight).saturating_mul(t as Weight)) + (38_929_132_000 as Weight) + // Standard Error: 65_806_000 + .saturating_add((2_980_358_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 23_000 + .saturating_add((62_980_000 as Weight).saturating_mul(i as Weight)) // Standard Error: 25_000 - .saturating_add((63_345_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 26_000 - .saturating_add((100_683_000 as Weight).saturating_mul(o as Weight)) + .saturating_add((101_383_000 as Weight).saturating_mul(o as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().reads((101 as Weight).saturating_mul(t as Weight))) .saturating_add(T::DbWeight::get().writes(101 as Weight)) @@ -566,8 +570,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts OwnerInfoOf (r:100 w:100) fn seal_instantiate(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 49_379_000 - .saturating_add((51_630_139_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 120_171_000 + .saturating_add((50_779_937_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().reads((400 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -580,13 +584,13 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts AccountCounter (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_instantiate_per_input_output_salt_kb(i: u32, o: u32, s: u32, ) -> Weight { - (47_691_523_000 as Weight) - // Standard Error: 36_000 - .saturating_add((63_693_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 36_000 - .saturating_add((101_775_000 as Weight).saturating_mul(o as Weight)) - // Standard Error: 36_000 - .saturating_add((200_727_000 as Weight).saturating_mul(s as Weight)) + (45_749_415_000 as Weight) + // Standard Error: 34_000 + .saturating_add((64_650_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 34_000 + .saturating_add((101_902_000 as Weight).saturating_mul(o as Weight)) + // Standard Error: 34_000 + .saturating_add((201_402_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(208 as Weight)) .saturating_add(T::DbWeight::get().writes(206 as Weight)) } @@ -595,9 +599,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256(r: u32, ) -> Weight { - (411_050_000 as Weight) - // Standard Error: 177_000 - .saturating_add((125_380_000 as Weight).saturating_mul(r as Weight)) + (414_773_000 as Weight) + // Standard Error: 183_000 + .saturating_add((127_117_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -606,9 +610,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256_per_kb(n: u32, ) -> Weight { - (381_286_000 as Weight) - // Standard Error: 48_000 - .saturating_add((506_160_000 as Weight).saturating_mul(n as Weight)) + (581_981_000 as Weight) + // Standard Error: 38_000 + .saturating_add((505_754_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -617,9 +621,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256(r: u32, ) -> Weight { - (415_554_000 as Weight) - // Standard Error: 186_000 - .saturating_add((138_154_000 as Weight).saturating_mul(r as Weight)) + (424_421_000 as Weight) + // Standard Error: 223_000 + .saturating_add((137_068_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -628,9 +632,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256_per_kb(n: u32, ) -> Weight { - (509_653_000 as Weight) - // Standard Error: 20_000 - .saturating_add((364_008_000 as Weight).saturating_mul(n as Weight)) + (497_132_000 as Weight) + // Standard Error: 24_000 + .saturating_add((363_894_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -639,9 +643,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256(r: u32, ) -> Weight { - (416_442_000 as Weight) - // Standard Error: 186_000 - .saturating_add((120_321_000 as Weight).saturating_mul(r as Weight)) + (419_414_000 as Weight) + // Standard Error: 174_000 + .saturating_add((106_283_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -650,9 +654,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256_per_kb(n: u32, ) -> Weight { - (586_411_000 as Weight) - // Standard Error: 17_000 - .saturating_add((164_095_000 as Weight).saturating_mul(n as Weight)) + (572_206_000 as Weight) + // Standard Error: 24_000 + .saturating_add((163_930_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -661,9 +665,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128(r: u32, ) -> Weight { - (410_054_000 as Weight) - // Standard Error: 198_000 - .saturating_add((109_368_000 as Weight).saturating_mul(r as Weight)) + (417_971_000 as Weight) + // Standard Error: 180_000 + .saturating_add((106_016_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -672,9 +676,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128_per_kb(n: u32, ) -> Weight { - (548_447_000 as Weight) - // Standard Error: 16_000 - .saturating_add((164_100_000 as Weight).saturating_mul(n as Weight)) + (568_067_000 as Weight) + // Standard Error: 20_000 + .saturating_add((163_853_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -683,266 +687,266 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_ecdsa_recover(r: u32, ) -> Weight { - (368_727_000 as Weight) - // Standard Error: 1_294_000 - .saturating_add((15_563_119_000 as Weight).saturating_mul(r as Weight)) + (372_816_000 as Weight) + // Standard Error: 1_677_000 + .saturating_add((15_723_462_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn instr_i64const(r: u32, ) -> Weight { - (47_482_000 as Weight) - // Standard Error: 11_000 - .saturating_add((811_000 as Weight).saturating_mul(r as Weight)) + (53_407_000 as Weight) + // Standard Error: 14_000 + .saturating_add((885_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64load(r: u32, ) -> Weight { - (55_014_000 as Weight) - // Standard Error: 13_000 - .saturating_add((2_502_000 as Weight).saturating_mul(r as Weight)) + (48_061_000 as Weight) + // Standard Error: 10_000 + .saturating_add((2_947_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64store(r: u32, ) -> Weight { - (54_708_000 as Weight) - // Standard Error: 13_000 - .saturating_add((2_547_000 as Weight).saturating_mul(r as Weight)) + (48_150_000 as Weight) + // Standard Error: 10_000 + .saturating_add((2_978_000 as Weight).saturating_mul(r as Weight)) } fn instr_select(r: u32, ) -> Weight { - (38_583_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_979_000 as Weight).saturating_mul(r as Weight)) + (50_943_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_446_000 as Weight).saturating_mul(r as Weight)) } fn instr_if(r: u32, ) -> Weight { - (37_647_000 as Weight) - // Standard Error: 16_000 - .saturating_add((3_107_000 as Weight).saturating_mul(r as Weight)) + (47_862_000 as Weight) + // Standard Error: 12_000 + .saturating_add((2_627_000 as Weight).saturating_mul(r as Weight)) } fn instr_br(r: u32, ) -> Weight { - (40_586_000 as Weight) - // Standard Error: 17_000 - .saturating_add((1_940_000 as Weight).saturating_mul(r as Weight)) + (51_291_000 as Weight) + // Standard Error: 16_000 + .saturating_add((1_467_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_if(r: u32, ) -> Weight { - (39_436_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_533_000 as Weight).saturating_mul(r as Weight)) + (44_627_000 as Weight) + // Standard Error: 18_000 + .saturating_add((2_211_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table(r: u32, ) -> Weight { - (45_741_000 as Weight) - // Standard Error: 21_000 - .saturating_add((2_450_000 as Weight).saturating_mul(r as Weight)) + (38_208_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_914_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table_per_entry(e: u32, ) -> Weight { - (48_440_000 as Weight) + (47_228_000 as Weight) // Standard Error: 3_000 - .saturating_add((29_000 as Weight).saturating_mul(e as Weight)) + .saturating_add((17_000 as Weight).saturating_mul(e as Weight)) } fn instr_call(r: u32, ) -> Weight { - (49_819_000 as Weight) - // Standard Error: 22_000 - .saturating_add((20_642_000 as Weight).saturating_mul(r as Weight)) + (39_507_000 as Weight) + // Standard Error: 26_000 + .saturating_add((20_544_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect(r: u32, ) -> Weight { - (54_317_000 as Weight) - // Standard Error: 29_000 - .saturating_add((30_663_000 as Weight).saturating_mul(r as Weight)) + (47_235_000 as Weight) + // Standard Error: 31_000 + .saturating_add((29_869_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect_per_param(p: u32, ) -> Weight { - (88_087_000 as Weight) - // Standard Error: 5_000 - .saturating_add((1_106_000 as Weight).saturating_mul(p as Weight)) + (78_847_000 as Weight) + // Standard Error: 6_000 + .saturating_add((1_217_000 as Weight).saturating_mul(p as Weight)) } fn instr_local_get(r: u32, ) -> Weight { - (40_540_000 as Weight) - // Standard Error: 14_000 - .saturating_add((1_362_000 as Weight).saturating_mul(r as Weight)) + (48_441_000 as Weight) + // Standard Error: 11_000 + .saturating_add((816_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_set(r: u32, ) -> Weight { - (40_842_000 as Weight) - // Standard Error: 14_000 - .saturating_add((1_375_000 as Weight).saturating_mul(r as Weight)) + (48_324_000 as Weight) + // Standard Error: 11_000 + .saturating_add((861_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_tee(r: u32, ) -> Weight { - (43_679_000 as Weight) - // Standard Error: 13_000 - .saturating_add((1_882_000 as Weight).saturating_mul(r as Weight)) + (45_372_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_488_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_get(r: u32, ) -> Weight { - (52_999_000 as Weight) - // Standard Error: 14_000 - .saturating_add((1_970_000 as Weight).saturating_mul(r as Weight)) + (58_465_000 as Weight) + // Standard Error: 20_000 + .saturating_add((1_655_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_set(r: u32, ) -> Weight { - (58_630_000 as Weight) - // Standard Error: 12_000 - .saturating_add((1_776_000 as Weight).saturating_mul(r as Weight)) + (55_457_000 as Weight) + // Standard Error: 18_000 + .saturating_add((1_671_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_current(r: u32, ) -> Weight { - (47_810_000 as Weight) - // Standard Error: 11_000 - .saturating_add((817_000 as Weight).saturating_mul(r as Weight)) + (52_615_000 as Weight) + // Standard Error: 14_000 + .saturating_add((905_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_grow(r: u32, ) -> Weight { - (51_086_000 as Weight) - // Standard Error: 3_690_000 - .saturating_add((622_068_000 as Weight).saturating_mul(r as Weight)) + (37_739_000 as Weight) + // Standard Error: 2_851_000 + .saturating_add((634_780_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64clz(r: u32, ) -> Weight { - (44_599_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_498_000 as Weight).saturating_mul(r as Weight)) + (54_830_000 as Weight) + // Standard Error: 9_000 + .saturating_add((1_309_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ctz(r: u32, ) -> Weight { - (44_523_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_500_000 as Weight).saturating_mul(r as Weight)) + (54_712_000 as Weight) + // Standard Error: 9_000 + .saturating_add((1_310_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64popcnt(r: u32, ) -> Weight { - (44_633_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_501_000 as Weight).saturating_mul(r as Weight)) + (54_864_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_312_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eqz(r: u32, ) -> Weight { - (44_654_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_499_000 as Weight).saturating_mul(r as Weight)) + (54_596_000 as Weight) + // Standard Error: 9_000 + .saturating_add((1_314_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendsi32(r: u32, ) -> Weight { - (42_020_000 as Weight) - // Standard Error: 13_000 - .saturating_add((1_950_000 as Weight).saturating_mul(r as Weight)) + (44_536_000 as Weight) + // Standard Error: 12_000 + .saturating_add((1_514_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendui32(r: u32, ) -> Weight { - (42_077_000 as Weight) - // Standard Error: 13_000 - .saturating_add((1_943_000 as Weight).saturating_mul(r as Weight)) + (44_380_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_512_000 as Weight).saturating_mul(r as Weight)) } fn instr_i32wrapi64(r: u32, ) -> Weight { - (44_559_000 as Weight) + (54_968_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_499_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_310_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eq(r: u32, ) -> Weight { - (37_902_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_480_000 as Weight).saturating_mul(r as Weight)) + (50_161_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_917_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ne(r: u32, ) -> Weight { - (37_799_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_484_000 as Weight).saturating_mul(r as Weight)) + (50_417_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_911_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64lts(r: u32, ) -> Weight { - (37_492_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_507_000 as Weight).saturating_mul(r as Weight)) + (50_358_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_914_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ltu(r: u32, ) -> Weight { - (37_509_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_503_000 as Weight).saturating_mul(r as Weight)) + (49_864_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_928_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gts(r: u32, ) -> Weight { - (37_563_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_501_000 as Weight).saturating_mul(r as Weight)) + (50_159_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_917_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gtu(r: u32, ) -> Weight { - (37_584_000 as Weight) + (50_037_000 as Weight) // Standard Error: 16_000 - .saturating_add((2_496_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_945_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64les(r: u32, ) -> Weight { - (37_738_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_490_000 as Weight).saturating_mul(r as Weight)) + (50_482_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_909_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64leu(r: u32, ) -> Weight { - (37_806_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_490_000 as Weight).saturating_mul(r as Weight)) + (50_426_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_908_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ges(r: u32, ) -> Weight { - (37_858_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_483_000 as Weight).saturating_mul(r as Weight)) + (50_205_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_918_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64geu(r: u32, ) -> Weight { - (37_862_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_483_000 as Weight).saturating_mul(r as Weight)) + (50_189_000 as Weight) + // Standard Error: 12_000 + .saturating_add((1_928_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64add(r: u32, ) -> Weight { - (37_695_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_491_000 as Weight).saturating_mul(r as Weight)) + (50_205_000 as Weight) + // Standard Error: 12_000 + .saturating_add((1_922_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64sub(r: u32, ) -> Weight { - (37_693_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_495_000 as Weight).saturating_mul(r as Weight)) + (50_375_000 as Weight) + // Standard Error: 15_000 + .saturating_add((1_929_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64mul(r: u32, ) -> Weight { - (37_623_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_499_000 as Weight).saturating_mul(r as Weight)) + (50_343_000 as Weight) + // Standard Error: 12_000 + .saturating_add((1_916_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divs(r: u32, ) -> Weight { - (37_595_000 as Weight) - // Standard Error: 16_000 - .saturating_add((3_150_000 as Weight).saturating_mul(r as Weight)) + (50_707_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_667_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divu(r: u32, ) -> Weight { - (37_661_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_797_000 as Weight).saturating_mul(r as Weight)) + (50_318_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_408_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rems(r: u32, ) -> Weight { - (37_978_000 as Weight) - // Standard Error: 16_000 - .saturating_add((3_107_000 as Weight).saturating_mul(r as Weight)) + (50_214_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_702_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64remu(r: u32, ) -> Weight { - (37_668_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_842_000 as Weight).saturating_mul(r as Weight)) + (50_394_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_411_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64and(r: u32, ) -> Weight { - (37_846_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_482_000 as Weight).saturating_mul(r as Weight)) + (50_397_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_910_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64or(r: u32, ) -> Weight { - (37_902_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_478_000 as Weight).saturating_mul(r as Weight)) + (50_291_000 as Weight) + // Standard Error: 12_000 + .saturating_add((1_915_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64xor(r: u32, ) -> Weight { - (37_670_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_489_000 as Weight).saturating_mul(r as Weight)) + (50_684_000 as Weight) + // Standard Error: 12_000 + .saturating_add((1_903_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shl(r: u32, ) -> Weight { - (37_987_000 as Weight) + (49_638_000 as Weight) // Standard Error: 17_000 - .saturating_add((2_479_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_967_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shrs(r: u32, ) -> Weight { - (37_945_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_486_000 as Weight).saturating_mul(r as Weight)) + (50_817_000 as Weight) + // Standard Error: 12_000 + .saturating_add((1_899_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shru(r: u32, ) -> Weight { - (37_570_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_503_000 as Weight).saturating_mul(r as Weight)) + (50_987_000 as Weight) + // Standard Error: 12_000 + .saturating_add((1_899_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotl(r: u32, ) -> Weight { - (37_674_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_498_000 as Weight).saturating_mul(r as Weight)) + (50_885_000 as Weight) + // Standard Error: 12_000 + .saturating_add((1_905_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotr(r: u32, ) -> Weight { - (37_467_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_503_000 as Weight).saturating_mul(r as Weight)) + (50_465_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_908_000 as Weight).saturating_mul(r as Weight)) } } @@ -950,41 +954,45 @@ impl WeightInfo for SubstrateWeight { impl WeightInfo for () { // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize() -> Weight { - (2_854_000 as Weight) + (2_720_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn on_initialize_per_trie_key(k: u32, ) -> Weight { (0 as Weight) // Standard Error: 3_000 - .saturating_add((2_190_000 as Weight).saturating_mul(k as Weight)) + .saturating_add((2_208_000 as Weight).saturating_mul(k as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) } // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize_per_queue_item(q: u32, ) -> Weight { - (101_551_000 as Weight) + (95_834_000 as Weight) // Standard Error: 2_000 - .saturating_add((292_000 as Weight).saturating_mul(q as Weight)) + .saturating_add((317_000 as Weight).saturating_mul(q as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Contracts PristineCode (r:1 w:0) // Storage: Contracts CodeStorage (r:0 w:1) - fn instrument(c: u32, ) -> Weight { - (33_350_000 as Weight) - // Standard Error: 106_000 - .saturating_add((91_098_000 as Weight).saturating_mul(c as Weight)) + fn reinstrument(c: u32, ) -> Weight { + (17_177_000 as Weight) + // Standard Error: 85_000 + .saturating_add((91_306_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } + // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) - fn code_load(c: u32, ) -> Weight { - (8_080_000 as Weight) - // Standard Error: 0 - .saturating_add((1_455_000 as Weight).saturating_mul(c as Weight)) - .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + // Storage: Timestamp Now (r:1 w:0) + // Storage: System Account (r:1 w:1) + fn call_with_code_kb(c: u32, ) -> Weight { + (371_888_000 as Weight) + // Standard Error: 137_000 + .saturating_add((92_314_000 as Weight).saturating_mul(c as Weight)) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Contracts CodeStorage (r:1 w:1) // Storage: Contracts AccountCounter (r:1 w:1) @@ -994,11 +1002,11 @@ impl WeightInfo for () { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn instantiate_with_code(c: u32, s: u32, ) -> Weight { - (464_920_000 as Weight) - // Standard Error: 136_000 - .saturating_add((211_340_000 as Weight).saturating_mul(c as Weight)) - // Standard Error: 8_000 - .saturating_add((2_190_000 as Weight).saturating_mul(s as Weight)) + (429_131_000 as Weight) + // Standard Error: 154_000 + .saturating_add((208_736_000 as Weight).saturating_mul(c as Weight)) + // Standard Error: 10_000 + .saturating_add((2_203_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } @@ -1009,9 +1017,9 @@ impl WeightInfo for () { // Storage: System Account (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn instantiate(s: u32, ) -> Weight { - (236_192_000 as Weight) + (241_132_000 as Weight) // Standard Error: 2_000 - .saturating_add((2_010_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((1_986_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } @@ -1020,7 +1028,7 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call() -> Weight { - (172_780_000 as Weight) + (173_649_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -1028,9 +1036,9 @@ impl WeightInfo for () { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn upload_code(c: u32, ) -> Weight { - (80_415_000 as Weight) - // Standard Error: 98_000 - .saturating_add((93_463_000 as Weight).saturating_mul(c as Weight)) + (84_508_000 as Weight) + // Standard Error: 93_000 + .saturating_add((91_690_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -1038,7 +1046,7 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:0 w:1) // Storage: Contracts PristineCode (r:0 w:1) fn remove_code() -> Weight { - (40_042_000 as Weight) + (39_407_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -1047,9 +1055,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_caller(r: u32, ) -> Weight { - (416_770_000 as Weight) - // Standard Error: 175_000 - .saturating_add((114_550_000 as Weight).saturating_mul(r as Weight)) + (421_879_000 as Weight) + // Standard Error: 168_000 + .saturating_add((114_154_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1058,9 +1066,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_address(r: u32, ) -> Weight { - (415_774_000 as Weight) - // Standard Error: 176_000 - .saturating_add((115_169_000 as Weight).saturating_mul(r as Weight)) + (428_124_000 as Weight) + // Standard Error: 167_000 + .saturating_add((113_196_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1069,9 +1077,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas_left(r: u32, ) -> Weight { - (411_883_000 as Weight) - // Standard Error: 200_000 - .saturating_add((113_740_000 as Weight).saturating_mul(r as Weight)) + (424_405_000 as Weight) + // Standard Error: 182_000 + .saturating_add((112_511_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1080,9 +1088,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_balance(r: u32, ) -> Weight { - (422_382_000 as Weight) - // Standard Error: 189_000 - .saturating_add((313_581_000 as Weight).saturating_mul(r as Weight)) + (433_901_000 as Weight) + // Standard Error: 206_000 + .saturating_add((307_273_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1091,9 +1099,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_value_transferred(r: u32, ) -> Weight { - (437_411_000 as Weight) - // Standard Error: 191_000 - .saturating_add((111_580_000 as Weight).saturating_mul(r as Weight)) + (428_707_000 as Weight) + // Standard Error: 203_000 + .saturating_add((113_558_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1102,9 +1110,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_minimum_balance(r: u32, ) -> Weight { - (431_815_000 as Weight) - // Standard Error: 170_000 - .saturating_add((111_289_000 as Weight).saturating_mul(r as Weight)) + (423_775_000 as Weight) + // Standard Error: 174_000 + .saturating_add((113_371_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1113,9 +1121,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_block_number(r: u32, ) -> Weight { - (430_451_000 as Weight) - // Standard Error: 152_000 - .saturating_add((111_214_000 as Weight).saturating_mul(r as Weight)) + (423_282_000 as Weight) + // Standard Error: 220_000 + .saturating_add((113_709_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1124,9 +1132,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_now(r: u32, ) -> Weight { - (419_363_000 as Weight) - // Standard Error: 175_000 - .saturating_add((112_089_000 as Weight).saturating_mul(r as Weight)) + (435_209_000 as Weight) + // Standard Error: 157_000 + .saturating_add((111_492_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1136,9 +1144,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0) fn seal_weight_to_fee(r: u32, ) -> Weight { - (427_501_000 as Weight) - // Standard Error: 247_000 - .saturating_add((262_104_000 as Weight).saturating_mul(r as Weight)) + (432_886_000 as Weight) + // Standard Error: 193_000 + .saturating_add((260_787_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1147,9 +1155,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas(r: u32, ) -> Weight { - (145_426_000 as Weight) - // Standard Error: 115_000 - .saturating_add((52_082_000 as Weight).saturating_mul(r as Weight)) + (147_315_000 as Weight) + // Standard Error: 124_000 + .saturating_add((52_336_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1158,9 +1166,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input(r: u32, ) -> Weight { - (415_783_000 as Weight) - // Standard Error: 184_000 - .saturating_add((101_266_000 as Weight).saturating_mul(r as Weight)) + (422_074_000 as Weight) + // Standard Error: 199_000 + .saturating_add((100_398_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1169,9 +1177,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input_per_kb(n: u32, ) -> Weight { - (536_645_000 as Weight) - // Standard Error: 6_000 - .saturating_add((38_077_000 as Weight).saturating_mul(n as Weight)) + (543_944_000 as Weight) + // Standard Error: 10_000 + .saturating_add((38_098_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1180,9 +1188,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return(r: u32, ) -> Weight { - (412_785_000 as Weight) - // Standard Error: 92_000 - .saturating_add((1_476_000 as Weight).saturating_mul(r as Weight)) + (398_945_000 as Weight) + // Standard Error: 417_000 + .saturating_add((15_763_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1191,9 +1199,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return_per_kb(n: u32, ) -> Weight { - (400_232_000 as Weight) + (416_850_000 as Weight) // Standard Error: 1_000 - .saturating_add((644_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((635_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1204,9 +1212,9 @@ impl WeightInfo for () { // Storage: Contracts DeletionQueue (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_terminate(r: u32, ) -> Weight { - (409_343_000 as Weight) - // Standard Error: 1_325_000 - .saturating_add((101_661_000 as Weight).saturating_mul(r as Weight)) + (408_445_000 as Weight) + // Standard Error: 248_000 + .saturating_add((102_109_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((4 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1218,9 +1226,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) fn seal_random(r: u32, ) -> Weight { - (417_354_000 as Weight) - // Standard Error: 299_000 - .saturating_add((343_766_000 as Weight).saturating_mul(r as Weight)) + (410_845_000 as Weight) + // Standard Error: 289_000 + .saturating_add((341_867_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1229,9 +1237,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_deposit_event(r: u32, ) -> Weight { - (412_092_000 as Weight) - // Standard Error: 403_000 - .saturating_add((568_199_000 as Weight).saturating_mul(r as Weight)) + (425_037_000 as Weight) + // Standard Error: 424_000 + .saturating_add((571_604_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1241,11 +1249,11 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: System EventTopics (r:100 w:100) fn seal_deposit_event_per_topic_and_kb(t: u32, n: u32, ) -> Weight { - (1_095_614_000 as Weight) - // Standard Error: 2_151_000 - .saturating_add((455_690_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 424_000 - .saturating_add((163_553_000 as Weight).saturating_mul(n as Weight)) + (1_055_868_000 as Weight) + // Standard Error: 3_004_000 + .saturating_add((453_979_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 592_000 + .saturating_add((166_716_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(t as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1256,17 +1264,17 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_debug_message(r: u32, ) -> Weight { - (169_113_000 as Weight) - // Standard Error: 146_000 - .saturating_add((72_877_000 as Weight).saturating_mul(r as Weight)) + (161_170_000 as Weight) + // Standard Error: 169_000 + .saturating_add((74_379_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage(r: u32, ) -> Weight { - (484_647_000 as Weight) - // Standard Error: 479_000 - .saturating_add((369_854_000 as Weight).saturating_mul(r as Weight)) + (500_168_000 as Weight) + // Standard Error: 473_000 + .saturating_add((371_239_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -1278,17 +1286,17 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: unknown [0x7afa01283080ef247df84e0ba38ea5a587d25ce6633a6bfbba02068c14023441] (r:1 w:1) fn seal_set_storage_per_kb(n: u32, ) -> Weight { - (793_777_000 as Weight) - // Standard Error: 264_000 - .saturating_add((73_253_000 as Weight).saturating_mul(n as Weight)) + (796_175_000 as Weight) + // Standard Error: 249_000 + .saturating_add((74_071_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage(r: u32, ) -> Weight { - (180_385_000 as Weight) - // Standard Error: 1_470_000 - .saturating_add((834_911_000 as Weight).saturating_mul(r as Weight)) + (178_237_000 as Weight) + // Standard Error: 1_652_000 + .saturating_add((835_947_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -1296,9 +1304,9 @@ impl WeightInfo for () { } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage(r: u32, ) -> Weight { - (282_452_000 as Weight) - // Standard Error: 802_000 - .saturating_add((492_119_000 as Weight).saturating_mul(r as Weight)) + (305_702_000 as Weight) + // Standard Error: 750_000 + .saturating_add((493_580_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1309,9 +1317,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: unknown [0x7afa01283080ef247df84e0ba38ea5a587d25ce6633a6bfbba02068c14023441] (r:1 w:0) fn seal_get_storage_per_kb(n: u32, ) -> Weight { - (687_019_000 as Weight) - // Standard Error: 226_000 - .saturating_add((111_245_000 as Weight).saturating_mul(n as Weight)) + (697_017_000 as Weight) + // Standard Error: 216_000 + .saturating_add((111_743_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1320,9 +1328,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_transfer(r: u32, ) -> Weight { - (273_106_000 as Weight) - // Standard Error: 1_498_000 - .saturating_add((3_509_324_000 as Weight).saturating_mul(r as Weight)) + (243_124_000 as Weight) + // Standard Error: 1_718_000 + .saturating_add((3_530_873_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) @@ -1333,9 +1341,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_call(r: u32, ) -> Weight { - (2_702_839_000 as Weight) - // Standard Error: 21_310_000 - .saturating_add((37_721_061_000 as Weight).saturating_mul(r as Weight)) + (140_524_000 as Weight) + // Standard Error: 4_504_000 + .saturating_add((39_287_224_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1346,13 +1354,13 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:2 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_call_per_transfer_input_output_kb(t: u32, i: u32, o: u32, ) -> Weight { - (40_088_516_000 as Weight) - // Standard Error: 69_999_000 - .saturating_add((2_981_897_000 as Weight).saturating_mul(t as Weight)) + (38_929_132_000 as Weight) + // Standard Error: 65_806_000 + .saturating_add((2_980_358_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 23_000 + .saturating_add((62_980_000 as Weight).saturating_mul(i as Weight)) // Standard Error: 25_000 - .saturating_add((63_345_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 26_000 - .saturating_add((100_683_000 as Weight).saturating_mul(o as Weight)) + .saturating_add((101_383_000 as Weight).saturating_mul(o as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().reads((101 as Weight).saturating_mul(t as Weight))) .saturating_add(RocksDbWeight::get().writes(101 as Weight)) @@ -1366,8 +1374,8 @@ impl WeightInfo for () { // Storage: Contracts OwnerInfoOf (r:100 w:100) fn seal_instantiate(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 49_379_000 - .saturating_add((51_630_139_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 120_171_000 + .saturating_add((50_779_937_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().reads((400 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -1380,13 +1388,13 @@ impl WeightInfo for () { // Storage: Contracts AccountCounter (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_instantiate_per_input_output_salt_kb(i: u32, o: u32, s: u32, ) -> Weight { - (47_691_523_000 as Weight) - // Standard Error: 36_000 - .saturating_add((63_693_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 36_000 - .saturating_add((101_775_000 as Weight).saturating_mul(o as Weight)) - // Standard Error: 36_000 - .saturating_add((200_727_000 as Weight).saturating_mul(s as Weight)) + (45_749_415_000 as Weight) + // Standard Error: 34_000 + .saturating_add((64_650_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 34_000 + .saturating_add((101_902_000 as Weight).saturating_mul(o as Weight)) + // Standard Error: 34_000 + .saturating_add((201_402_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(208 as Weight)) .saturating_add(RocksDbWeight::get().writes(206 as Weight)) } @@ -1395,9 +1403,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256(r: u32, ) -> Weight { - (411_050_000 as Weight) - // Standard Error: 177_000 - .saturating_add((125_380_000 as Weight).saturating_mul(r as Weight)) + (414_773_000 as Weight) + // Standard Error: 183_000 + .saturating_add((127_117_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1406,9 +1414,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256_per_kb(n: u32, ) -> Weight { - (381_286_000 as Weight) - // Standard Error: 48_000 - .saturating_add((506_160_000 as Weight).saturating_mul(n as Weight)) + (581_981_000 as Weight) + // Standard Error: 38_000 + .saturating_add((505_754_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1417,9 +1425,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256(r: u32, ) -> Weight { - (415_554_000 as Weight) - // Standard Error: 186_000 - .saturating_add((138_154_000 as Weight).saturating_mul(r as Weight)) + (424_421_000 as Weight) + // Standard Error: 223_000 + .saturating_add((137_068_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1428,9 +1436,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256_per_kb(n: u32, ) -> Weight { - (509_653_000 as Weight) - // Standard Error: 20_000 - .saturating_add((364_008_000 as Weight).saturating_mul(n as Weight)) + (497_132_000 as Weight) + // Standard Error: 24_000 + .saturating_add((363_894_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1439,9 +1447,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256(r: u32, ) -> Weight { - (416_442_000 as Weight) - // Standard Error: 186_000 - .saturating_add((120_321_000 as Weight).saturating_mul(r as Weight)) + (419_414_000 as Weight) + // Standard Error: 174_000 + .saturating_add((106_283_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1450,9 +1458,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256_per_kb(n: u32, ) -> Weight { - (586_411_000 as Weight) - // Standard Error: 17_000 - .saturating_add((164_095_000 as Weight).saturating_mul(n as Weight)) + (572_206_000 as Weight) + // Standard Error: 24_000 + .saturating_add((163_930_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1461,9 +1469,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128(r: u32, ) -> Weight { - (410_054_000 as Weight) - // Standard Error: 198_000 - .saturating_add((109_368_000 as Weight).saturating_mul(r as Weight)) + (417_971_000 as Weight) + // Standard Error: 180_000 + .saturating_add((106_016_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1472,9 +1480,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128_per_kb(n: u32, ) -> Weight { - (548_447_000 as Weight) - // Standard Error: 16_000 - .saturating_add((164_100_000 as Weight).saturating_mul(n as Weight)) + (568_067_000 as Weight) + // Standard Error: 20_000 + .saturating_add((163_853_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1483,265 +1491,265 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_ecdsa_recover(r: u32, ) -> Weight { - (368_727_000 as Weight) - // Standard Error: 1_294_000 - .saturating_add((15_563_119_000 as Weight).saturating_mul(r as Weight)) + (372_816_000 as Weight) + // Standard Error: 1_677_000 + .saturating_add((15_723_462_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn instr_i64const(r: u32, ) -> Weight { - (47_482_000 as Weight) - // Standard Error: 11_000 - .saturating_add((811_000 as Weight).saturating_mul(r as Weight)) + (53_407_000 as Weight) + // Standard Error: 14_000 + .saturating_add((885_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64load(r: u32, ) -> Weight { - (55_014_000 as Weight) - // Standard Error: 13_000 - .saturating_add((2_502_000 as Weight).saturating_mul(r as Weight)) + (48_061_000 as Weight) + // Standard Error: 10_000 + .saturating_add((2_947_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64store(r: u32, ) -> Weight { - (54_708_000 as Weight) - // Standard Error: 13_000 - .saturating_add((2_547_000 as Weight).saturating_mul(r as Weight)) + (48_150_000 as Weight) + // Standard Error: 10_000 + .saturating_add((2_978_000 as Weight).saturating_mul(r as Weight)) } fn instr_select(r: u32, ) -> Weight { - (38_583_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_979_000 as Weight).saturating_mul(r as Weight)) + (50_943_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_446_000 as Weight).saturating_mul(r as Weight)) } fn instr_if(r: u32, ) -> Weight { - (37_647_000 as Weight) - // Standard Error: 16_000 - .saturating_add((3_107_000 as Weight).saturating_mul(r as Weight)) + (47_862_000 as Weight) + // Standard Error: 12_000 + .saturating_add((2_627_000 as Weight).saturating_mul(r as Weight)) } fn instr_br(r: u32, ) -> Weight { - (40_586_000 as Weight) - // Standard Error: 17_000 - .saturating_add((1_940_000 as Weight).saturating_mul(r as Weight)) + (51_291_000 as Weight) + // Standard Error: 16_000 + .saturating_add((1_467_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_if(r: u32, ) -> Weight { - (39_436_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_533_000 as Weight).saturating_mul(r as Weight)) + (44_627_000 as Weight) + // Standard Error: 18_000 + .saturating_add((2_211_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table(r: u32, ) -> Weight { - (45_741_000 as Weight) - // Standard Error: 21_000 - .saturating_add((2_450_000 as Weight).saturating_mul(r as Weight)) + (38_208_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_914_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table_per_entry(e: u32, ) -> Weight { - (48_440_000 as Weight) + (47_228_000 as Weight) // Standard Error: 3_000 - .saturating_add((29_000 as Weight).saturating_mul(e as Weight)) + .saturating_add((17_000 as Weight).saturating_mul(e as Weight)) } fn instr_call(r: u32, ) -> Weight { - (49_819_000 as Weight) - // Standard Error: 22_000 - .saturating_add((20_642_000 as Weight).saturating_mul(r as Weight)) + (39_507_000 as Weight) + // Standard Error: 26_000 + .saturating_add((20_544_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect(r: u32, ) -> Weight { - (54_317_000 as Weight) - // Standard Error: 29_000 - .saturating_add((30_663_000 as Weight).saturating_mul(r as Weight)) + (47_235_000 as Weight) + // Standard Error: 31_000 + .saturating_add((29_869_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect_per_param(p: u32, ) -> Weight { - (88_087_000 as Weight) - // Standard Error: 5_000 - .saturating_add((1_106_000 as Weight).saturating_mul(p as Weight)) + (78_847_000 as Weight) + // Standard Error: 6_000 + .saturating_add((1_217_000 as Weight).saturating_mul(p as Weight)) } fn instr_local_get(r: u32, ) -> Weight { - (40_540_000 as Weight) - // Standard Error: 14_000 - .saturating_add((1_362_000 as Weight).saturating_mul(r as Weight)) + (48_441_000 as Weight) + // Standard Error: 11_000 + .saturating_add((816_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_set(r: u32, ) -> Weight { - (40_842_000 as Weight) - // Standard Error: 14_000 - .saturating_add((1_375_000 as Weight).saturating_mul(r as Weight)) + (48_324_000 as Weight) + // Standard Error: 11_000 + .saturating_add((861_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_tee(r: u32, ) -> Weight { - (43_679_000 as Weight) - // Standard Error: 13_000 - .saturating_add((1_882_000 as Weight).saturating_mul(r as Weight)) + (45_372_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_488_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_get(r: u32, ) -> Weight { - (52_999_000 as Weight) - // Standard Error: 14_000 - .saturating_add((1_970_000 as Weight).saturating_mul(r as Weight)) + (58_465_000 as Weight) + // Standard Error: 20_000 + .saturating_add((1_655_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_set(r: u32, ) -> Weight { - (58_630_000 as Weight) - // Standard Error: 12_000 - .saturating_add((1_776_000 as Weight).saturating_mul(r as Weight)) + (55_457_000 as Weight) + // Standard Error: 18_000 + .saturating_add((1_671_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_current(r: u32, ) -> Weight { - (47_810_000 as Weight) - // Standard Error: 11_000 - .saturating_add((817_000 as Weight).saturating_mul(r as Weight)) + (52_615_000 as Weight) + // Standard Error: 14_000 + .saturating_add((905_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_grow(r: u32, ) -> Weight { - (51_086_000 as Weight) - // Standard Error: 3_690_000 - .saturating_add((622_068_000 as Weight).saturating_mul(r as Weight)) + (37_739_000 as Weight) + // Standard Error: 2_851_000 + .saturating_add((634_780_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64clz(r: u32, ) -> Weight { - (44_599_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_498_000 as Weight).saturating_mul(r as Weight)) + (54_830_000 as Weight) + // Standard Error: 9_000 + .saturating_add((1_309_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ctz(r: u32, ) -> Weight { - (44_523_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_500_000 as Weight).saturating_mul(r as Weight)) + (54_712_000 as Weight) + // Standard Error: 9_000 + .saturating_add((1_310_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64popcnt(r: u32, ) -> Weight { - (44_633_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_501_000 as Weight).saturating_mul(r as Weight)) + (54_864_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_312_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eqz(r: u32, ) -> Weight { - (44_654_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_499_000 as Weight).saturating_mul(r as Weight)) + (54_596_000 as Weight) + // Standard Error: 9_000 + .saturating_add((1_314_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendsi32(r: u32, ) -> Weight { - (42_020_000 as Weight) - // Standard Error: 13_000 - .saturating_add((1_950_000 as Weight).saturating_mul(r as Weight)) + (44_536_000 as Weight) + // Standard Error: 12_000 + .saturating_add((1_514_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendui32(r: u32, ) -> Weight { - (42_077_000 as Weight) - // Standard Error: 13_000 - .saturating_add((1_943_000 as Weight).saturating_mul(r as Weight)) + (44_380_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_512_000 as Weight).saturating_mul(r as Weight)) } fn instr_i32wrapi64(r: u32, ) -> Weight { - (44_559_000 as Weight) + (54_968_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_499_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_310_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eq(r: u32, ) -> Weight { - (37_902_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_480_000 as Weight).saturating_mul(r as Weight)) + (50_161_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_917_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ne(r: u32, ) -> Weight { - (37_799_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_484_000 as Weight).saturating_mul(r as Weight)) + (50_417_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_911_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64lts(r: u32, ) -> Weight { - (37_492_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_507_000 as Weight).saturating_mul(r as Weight)) + (50_358_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_914_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ltu(r: u32, ) -> Weight { - (37_509_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_503_000 as Weight).saturating_mul(r as Weight)) + (49_864_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_928_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gts(r: u32, ) -> Weight { - (37_563_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_501_000 as Weight).saturating_mul(r as Weight)) + (50_159_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_917_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gtu(r: u32, ) -> Weight { - (37_584_000 as Weight) + (50_037_000 as Weight) // Standard Error: 16_000 - .saturating_add((2_496_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_945_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64les(r: u32, ) -> Weight { - (37_738_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_490_000 as Weight).saturating_mul(r as Weight)) + (50_482_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_909_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64leu(r: u32, ) -> Weight { - (37_806_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_490_000 as Weight).saturating_mul(r as Weight)) + (50_426_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_908_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ges(r: u32, ) -> Weight { - (37_858_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_483_000 as Weight).saturating_mul(r as Weight)) + (50_205_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_918_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64geu(r: u32, ) -> Weight { - (37_862_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_483_000 as Weight).saturating_mul(r as Weight)) + (50_189_000 as Weight) + // Standard Error: 12_000 + .saturating_add((1_928_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64add(r: u32, ) -> Weight { - (37_695_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_491_000 as Weight).saturating_mul(r as Weight)) + (50_205_000 as Weight) + // Standard Error: 12_000 + .saturating_add((1_922_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64sub(r: u32, ) -> Weight { - (37_693_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_495_000 as Weight).saturating_mul(r as Weight)) + (50_375_000 as Weight) + // Standard Error: 15_000 + .saturating_add((1_929_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64mul(r: u32, ) -> Weight { - (37_623_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_499_000 as Weight).saturating_mul(r as Weight)) + (50_343_000 as Weight) + // Standard Error: 12_000 + .saturating_add((1_916_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divs(r: u32, ) -> Weight { - (37_595_000 as Weight) - // Standard Error: 16_000 - .saturating_add((3_150_000 as Weight).saturating_mul(r as Weight)) + (50_707_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_667_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divu(r: u32, ) -> Weight { - (37_661_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_797_000 as Weight).saturating_mul(r as Weight)) + (50_318_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_408_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rems(r: u32, ) -> Weight { - (37_978_000 as Weight) - // Standard Error: 16_000 - .saturating_add((3_107_000 as Weight).saturating_mul(r as Weight)) + (50_214_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_702_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64remu(r: u32, ) -> Weight { - (37_668_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_842_000 as Weight).saturating_mul(r as Weight)) + (50_394_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_411_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64and(r: u32, ) -> Weight { - (37_846_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_482_000 as Weight).saturating_mul(r as Weight)) + (50_397_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_910_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64or(r: u32, ) -> Weight { - (37_902_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_478_000 as Weight).saturating_mul(r as Weight)) + (50_291_000 as Weight) + // Standard Error: 12_000 + .saturating_add((1_915_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64xor(r: u32, ) -> Weight { - (37_670_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_489_000 as Weight).saturating_mul(r as Weight)) + (50_684_000 as Weight) + // Standard Error: 12_000 + .saturating_add((1_903_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shl(r: u32, ) -> Weight { - (37_987_000 as Weight) + (49_638_000 as Weight) // Standard Error: 17_000 - .saturating_add((2_479_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_967_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shrs(r: u32, ) -> Weight { - (37_945_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_486_000 as Weight).saturating_mul(r as Weight)) + (50_817_000 as Weight) + // Standard Error: 12_000 + .saturating_add((1_899_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shru(r: u32, ) -> Weight { - (37_570_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_503_000 as Weight).saturating_mul(r as Weight)) + (50_987_000 as Weight) + // Standard Error: 12_000 + .saturating_add((1_899_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotl(r: u32, ) -> Weight { - (37_674_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_498_000 as Weight).saturating_mul(r as Weight)) + (50_885_000 as Weight) + // Standard Error: 12_000 + .saturating_add((1_905_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotr(r: u32, ) -> Weight { - (37_467_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_503_000 as Weight).saturating_mul(r as Weight)) + (50_465_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_908_000 as Weight).saturating_mul(r as Weight)) } } From a991b0aecba1635861eaf104a7912f55fc1f323c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Sat, 11 Dec 2021 08:13:18 +0100 Subject: [PATCH 282/695] `inspect-key`: Adds support for `expect-public` (#10430) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Introduce `SecretUri` * `inspect-key`: Adds support for `expect-public` `expect-public` can be used to check that a given secret uri corresponds to the given public key. This is mainly useful when the secret uri is protected by a password and a new derived account should be generated. With `--expect-public` the user can pass the public key/account-id of the "base" secret uri aka the one without any derivation to ensure the correct password was inserted. * Fixes * :facepalm: * Apply suggestions from code review Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> * Review feedback * FMT * Bump the versions Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> --- Cargo.lock | 2 +- bin/node-template/node/Cargo.toml | 2 +- bin/node-template/pallets/template/Cargo.toml | 2 +- bin/node-template/runtime/Cargo.toml | 2 +- bin/node/bench/Cargo.toml | 2 +- bin/node/cli/Cargo.toml | 2 +- bin/node/executor/Cargo.toml | 2 +- bin/node/inspect/Cargo.toml | 2 +- bin/node/primitives/Cargo.toml | 2 +- bin/node/runtime/Cargo.toml | 2 +- bin/node/testing/Cargo.toml | 2 +- bin/utils/chain-spec-builder/Cargo.toml | 2 +- client/allocator/Cargo.toml | 2 +- client/api/Cargo.toml | 2 +- client/authority-discovery/Cargo.toml | 2 +- client/basic-authorship/Cargo.toml | 2 +- client/beefy/Cargo.toml | 2 +- client/beefy/rpc/Cargo.toml | 2 +- client/block-builder/Cargo.toml | 2 +- client/chain-spec/Cargo.toml | 2 +- client/cli/Cargo.toml | 2 +- client/cli/src/commands/inspect_key.rs | 149 ++++++++++++++++++ client/consensus/aura/Cargo.toml | 2 +- client/consensus/babe/Cargo.toml | 2 +- client/consensus/babe/rpc/Cargo.toml | 2 +- client/consensus/common/Cargo.toml | 2 +- client/consensus/manual-seal/Cargo.toml | 2 +- client/consensus/pow/Cargo.toml | 2 +- client/consensus/slots/Cargo.toml | 2 +- client/db/Cargo.toml | 2 +- client/executor/Cargo.toml | 2 +- client/executor/common/Cargo.toml | 2 +- client/executor/runtime-test/Cargo.toml | 2 +- client/executor/wasmi/Cargo.toml | 2 +- client/executor/wasmtime/Cargo.toml | 2 +- client/finality-grandpa/Cargo.toml | 2 +- client/finality-grandpa/rpc/Cargo.toml | 4 +- client/keystore/Cargo.toml | 2 +- client/network/Cargo.toml | 2 +- client/network/test/Cargo.toml | 2 +- client/offchain/Cargo.toml | 2 +- client/rpc-api/Cargo.toml | 2 +- client/rpc/Cargo.toml | 2 +- client/service/Cargo.toml | 2 +- client/service/test/Cargo.toml | 2 +- client/state-db/Cargo.toml | 2 +- client/tracing/Cargo.toml | 2 +- client/transaction-pool/Cargo.toml | 2 +- frame/assets/Cargo.toml | 2 +- frame/atomic-swap/Cargo.toml | 2 +- frame/aura/Cargo.toml | 2 +- frame/authority-discovery/Cargo.toml | 2 +- frame/authorship/Cargo.toml | 2 +- frame/babe/Cargo.toml | 2 +- frame/bags-list/Cargo.toml | 4 +- frame/bags-list/remote-tests/Cargo.toml | 2 +- frame/balances/Cargo.toml | 2 +- frame/beefy-mmr/Cargo.toml | 2 +- frame/beefy/Cargo.toml | 2 +- frame/bounties/Cargo.toml | 2 +- frame/child-bounties/Cargo.toml | 2 +- frame/collective/Cargo.toml | 2 +- frame/contracts/Cargo.toml | 2 +- frame/contracts/common/Cargo.toml | 2 +- frame/contracts/rpc/Cargo.toml | 2 +- frame/democracy/Cargo.toml | 2 +- .../election-provider-multi-phase/Cargo.toml | 4 +- frame/election-provider-support/Cargo.toml | 2 +- frame/elections-phragmen/Cargo.toml | 4 +- frame/elections/Cargo.toml | 2 +- frame/examples/basic/Cargo.toml | 2 +- frame/examples/offchain-worker/Cargo.toml | 2 +- frame/examples/parallel/Cargo.toml | 2 +- frame/executive/Cargo.toml | 4 +- frame/gilt/Cargo.toml | 2 +- frame/grandpa/Cargo.toml | 2 +- frame/identity/Cargo.toml | 2 +- frame/im-online/Cargo.toml | 2 +- frame/indices/Cargo.toml | 2 +- frame/lottery/Cargo.toml | 2 +- frame/membership/Cargo.toml | 2 +- frame/merkle-mountain-range/Cargo.toml | 2 +- .../primitives/Cargo.toml | 2 +- frame/merkle-mountain-range/rpc/Cargo.toml | 2 +- frame/multisig/Cargo.toml | 2 +- frame/nicks/Cargo.toml | 2 +- frame/node-authorization/Cargo.toml | 2 +- frame/offences/Cargo.toml | 2 +- frame/offences/benchmarking/Cargo.toml | 2 +- frame/proxy/Cargo.toml | 2 +- frame/randomness-collective-flip/Cargo.toml | 2 +- frame/recovery/Cargo.toml | 2 +- frame/scheduler/Cargo.toml | 2 +- frame/scored-pool/Cargo.toml | 2 +- frame/session/Cargo.toml | 2 +- frame/session/benchmarking/Cargo.toml | 2 +- frame/society/Cargo.toml | 2 +- frame/staking/Cargo.toml | 2 +- frame/sudo/Cargo.toml | 2 +- frame/support/Cargo.toml | 2 +- frame/support/test/Cargo.toml | 2 +- frame/support/test/compile_pass/Cargo.toml | 2 +- frame/system/Cargo.toml | 2 +- frame/system/benchmarking/Cargo.toml | 2 +- frame/timestamp/Cargo.toml | 2 +- frame/tips/Cargo.toml | 2 +- frame/transaction-payment/Cargo.toml | 2 +- .../asset-tx-payment/Cargo.toml | 2 +- frame/transaction-payment/rpc/Cargo.toml | 2 +- frame/transaction-storage/Cargo.toml | 2 +- frame/treasury/Cargo.toml | 2 +- frame/uniques/Cargo.toml | 2 +- frame/utility/Cargo.toml | 4 +- frame/vesting/Cargo.toml | 2 +- primitives/api/Cargo.toml | 2 +- primitives/api/test/Cargo.toml | 2 +- primitives/application-crypto/Cargo.toml | 2 +- primitives/application-crypto/test/Cargo.toml | 2 +- primitives/beefy/Cargo.toml | 2 +- primitives/consensus/babe/Cargo.toml | 2 +- primitives/consensus/common/Cargo.toml | 2 +- primitives/consensus/pow/Cargo.toml | 2 +- primitives/consensus/vrf/Cargo.toml | 2 +- primitives/core/Cargo.toml | 2 +- primitives/core/src/crypto.rs | 117 ++++++++++++-- primitives/finality-grandpa/Cargo.toml | 2 +- primitives/inherents/Cargo.toml | 2 +- primitives/io/Cargo.toml | 2 +- primitives/keyring/Cargo.toml | 2 +- primitives/keystore/Cargo.toml | 2 +- primitives/npos-elections/Cargo.toml | 2 +- primitives/offchain/Cargo.toml | 2 +- primitives/rpc/Cargo.toml | 2 +- primitives/runtime-interface/Cargo.toml | 2 +- .../test-wasm-deprecated/Cargo.toml | 2 +- .../runtime-interface/test-wasm/Cargo.toml | 2 +- primitives/runtime/Cargo.toml | 2 +- primitives/sandbox/Cargo.toml | 2 +- primitives/session/Cargo.toml | 2 +- primitives/state-machine/Cargo.toml | 2 +- primitives/tasks/Cargo.toml | 2 +- primitives/test-primitives/Cargo.toml | 2 +- .../transaction-storage-proof/Cargo.toml | 2 +- primitives/trie/Cargo.toml | 2 +- test-utils/client/Cargo.toml | 2 +- test-utils/runtime/Cargo.toml | 2 +- test-utils/runtime/client/Cargo.toml | 2 +- utils/frame/benchmarking-cli/Cargo.toml | 2 +- utils/frame/frame-utilities-cli/Cargo.toml | 2 +- utils/frame/remote-externalities/Cargo.toml | 2 +- utils/frame/rpc/system/Cargo.toml | 2 +- utils/frame/try-runtime/cli/Cargo.toml | 2 +- 152 files changed, 413 insertions(+), 165 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e7ddb66e2918..612cbdc8b0de 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9392,7 +9392,7 @@ dependencies = [ [[package]] name = "sp-core" -version = "4.0.0" +version = "4.1.0-dev" dependencies = [ "base58", "bitflags", diff --git a/bin/node-template/node/Cargo.toml b/bin/node-template/node/Cargo.toml index 2680b91b3a25..731e6fcda408 100644 --- a/bin/node-template/node/Cargo.toml +++ b/bin/node-template/node/Cargo.toml @@ -20,7 +20,7 @@ name = "node-template" structopt = "0.3.25" sc-cli = { version = "0.10.0-dev", path = "../../../client/cli", features = ["wasmtime"] } -sp-core = { version = "4.0.0", path = "../../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sc-executor = { version = "0.10.0-dev", path = "../../../client/executor", features = ["wasmtime"] } sc-service = { version = "0.10.0-dev", path = "../../../client/service", features = ["wasmtime"] } sc-telemetry = { version = "4.0.0-dev", path = "../../../client/telemetry" } diff --git a/bin/node-template/pallets/template/Cargo.toml b/bin/node-template/pallets/template/Cargo.toml index 646038ca6ced..d473119702f8 100644 --- a/bin/node-template/pallets/template/Cargo.toml +++ b/bin/node-template/pallets/template/Cargo.toml @@ -22,7 +22,7 @@ frame-system = { default-features = false, version = "4.0.0-dev", path = "../../ frame-benchmarking = { default-features = false, version = "4.0.0-dev", path = "../../../../frame/benchmarking", optional = true } [dev-dependencies] -sp-core = { default-features = false, version = "4.0.0", path = "../../../../primitives/core" } +sp-core = { default-features = false, version = "4.1.0-dev", path = "../../../../primitives/core" } sp-io = { default-features = false, version = "4.0.0-dev", path = "../../../../primitives/io" } sp-runtime = { default-features = false, version = "4.0.0-dev", path = "../../../../primitives/runtime" } diff --git a/bin/node-template/runtime/Cargo.toml b/bin/node-template/runtime/Cargo.toml index a25c45c692de..4818535e196c 100644 --- a/bin/node-template/runtime/Cargo.toml +++ b/bin/node-template/runtime/Cargo.toml @@ -29,7 +29,7 @@ frame-executive = { version = "4.0.0-dev", default-features = false, path = "../ sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/api" } sp-block-builder = { path = "../../../primitives/block-builder", default-features = false, version = "4.0.0-dev"} sp-consensus-aura = { version = "0.10.0-dev", default-features = false, path = "../../../primitives/consensus/aura" } -sp-core = { version = "4.0.0", default-features = false, path = "../../../primitives/core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } sp-inherents = { path = "../../../primitives/inherents", default-features = false, version = "4.0.0-dev"} sp-offchain = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/offchain" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } diff --git a/bin/node/bench/Cargo.toml b/bin/node/bench/Cargo.toml index 27c26d21dfe0..65d12378c4cf 100644 --- a/bin/node/bench/Cargo.toml +++ b/bin/node/bench/Cargo.toml @@ -23,7 +23,7 @@ derive_more = "0.99.16" kvdb = "0.10.0" kvdb-rocksdb = "0.14.0" sp-trie = { version = "4.0.0-dev", path = "../../../primitives/trie" } -sp-core = { version = "4.0.0", path = "../../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" } sc-basic-authorship = { version = "0.10.0-dev", path = "../../../client/basic-authorship" } sp-inherents = { version = "4.0.0-dev", path = "../../../primitives/inherents" } diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index cb632d936a2d..6da2fddd331e 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -47,7 +47,7 @@ sp-authority-discovery = { version = "4.0.0-dev", path = "../../../primitives/au sp-consensus-babe = { version = "0.10.0-dev", path = "../../../primitives/consensus/babe" } grandpa-primitives = { version = "4.0.0-dev", package = "sp-finality-grandpa", path = "../../../primitives/finality-grandpa" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } -sp-core = { version = "4.0.0", path = "../../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } sp-timestamp = { version = "4.0.0-dev", path = "../../../primitives/timestamp" } sp-authorship = { version = "4.0.0-dev", path = "../../../primitives/authorship" } diff --git a/bin/node/executor/Cargo.toml b/bin/node/executor/Cargo.toml index 13ed4d313994..2144b9298616 100644 --- a/bin/node/executor/Cargo.toml +++ b/bin/node/executor/Cargo.toml @@ -17,7 +17,7 @@ scale-info = { version = "1.0", features = ["derive"] } node-primitives = { version = "2.0.0", path = "../primitives" } node-runtime = { version = "3.0.0-dev", path = "../runtime" } sc-executor = { version = "0.10.0-dev", path = "../../../client/executor" } -sp-core = { version = "4.0.0", path = "../../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sp-keystore = { version = "0.10.0-dev", path = "../../../primitives/keystore" } sp-state-machine = { version = "0.10.0-dev", path = "../../../primitives/state-machine" } sp-tracing = { version = "4.0.0", path = "../../../primitives/tracing" } diff --git a/bin/node/inspect/Cargo.toml b/bin/node/inspect/Cargo.toml index 18f24651ed35..b0db8f630476 100644 --- a/bin/node/inspect/Cargo.toml +++ b/bin/node/inspect/Cargo.toml @@ -18,6 +18,6 @@ sc-client-api = { version = "4.0.0-dev", path = "../../../client/api" } sc-executor = { version = "0.10.0-dev", path = "../../../client/executor" } sc-service = { version = "0.10.0-dev", default-features = false, path = "../../../client/service" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-core = { version = "4.0.0", path = "../../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } structopt = "0.3.8" diff --git a/bin/node/primitives/Cargo.toml b/bin/node/primitives/Cargo.toml index 03d587acecd2..d2c315bd9b6e 100644 --- a/bin/node/primitives/Cargo.toml +++ b/bin/node/primitives/Cargo.toml @@ -17,7 +17,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../../frame/system" } sp-application-crypto = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/application-crypto" } -sp-core = { version = "4.0.0", default-features = false, path = "../../../primitives/core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } [features] diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index b36fd622dfa3..32dcc003e879 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -30,7 +30,7 @@ sp-block-builder = { path = "../../../primitives/block-builder", default-feature sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/inherents" } node-primitives = { version = "2.0.0", default-features = false, path = "../primitives" } sp-offchain = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/offchain" } -sp-core = { version = "4.0.0", default-features = false, path = "../../../primitives/core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/api" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } diff --git a/bin/node/testing/Cargo.toml b/bin/node/testing/Cargo.toml index 0fb0d40a7c2d..7f3a91196248 100644 --- a/bin/node/testing/Cargo.toml +++ b/bin/node/testing/Cargo.toml @@ -28,7 +28,7 @@ sp-keyring = { version = "4.0.0-dev", path = "../../../primitives/keyring" } node-executor = { version = "3.0.0-dev", path = "../executor" } node-primitives = { version = "2.0.0", path = "../primitives" } node-runtime = { version = "3.0.0-dev", path = "../runtime" } -sp-core = { version = "4.0.0", path = "../../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sp-io = { version = "4.0.0-dev", path = "../../../primitives/io" } sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } sc-executor = { version = "0.10.0-dev", path = "../../../client/executor", features = [ diff --git a/bin/utils/chain-spec-builder/Cargo.toml b/bin/utils/chain-spec-builder/Cargo.toml index 79eb5becfeb8..c5872ca29700 100644 --- a/bin/utils/chain-spec-builder/Cargo.toml +++ b/bin/utils/chain-spec-builder/Cargo.toml @@ -18,7 +18,7 @@ ansi_term = "0.12.1" sc-keystore = { version = "4.0.0-dev", path = "../../../client/keystore" } sc-chain-spec = { version = "4.0.0-dev", path = "../../../client/chain-spec" } node-cli = { version = "3.0.0-dev", path = "../../node/cli" } -sp-core = { version = "4.0.0", path = "../../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sp-keystore = { version = "0.10.0-dev", path = "../../../primitives/keystore" } rand = "0.7.2" structopt = "0.3.25" diff --git a/client/allocator/Cargo.toml b/client/allocator/Cargo.toml index 48191273ff36..ea0ce3c0bbea 100644 --- a/client/allocator/Cargo.toml +++ b/client/allocator/Cargo.toml @@ -14,7 +14,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-wasm-interface = { version = "4.0.0", path = "../../primitives/wasm-interface" } log = "0.4.11" thiserror = "1.0.30" diff --git a/client/api/Cargo.toml b/client/api/Cargo.toml index 5e0fe88b3ca7..13ec13538e65 100644 --- a/client/api/Cargo.toml +++ b/client/api/Cargo.toml @@ -27,7 +27,7 @@ sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } log = "0.4.8" parking_lot = "0.11.1" sp-database = { version = "4.0.0-dev", path = "../../primitives/database" } -sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-keystore = { version = "0.10.0-dev", default-features = false, path = "../../primitives/keystore" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } sc-utils = { version = "4.0.0-dev", path = "../utils" } diff --git a/client/authority-discovery/Cargo.toml b/client/authority-discovery/Cargo.toml index 8dcf8ab4c814..207f22753e45 100644 --- a/client/authority-discovery/Cargo.toml +++ b/client/authority-discovery/Cargo.toml @@ -32,7 +32,7 @@ sc-client-api = { version = "4.0.0-dev", path = "../api" } sc-network = { version = "0.10.0-dev", path = "../network" } sp-authority-discovery = { version = "4.0.0-dev", path = "../../primitives/authority-discovery" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-keystore = { version = "0.10.0-dev", path = "../../primitives/keystore" } sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } diff --git a/client/basic-authorship/Cargo.toml b/client/basic-authorship/Cargo.toml index 049876f47879..c1a8e9210a41 100644 --- a/client/basic-authorship/Cargo.toml +++ b/client/basic-authorship/Cargo.toml @@ -20,7 +20,7 @@ log = "0.4.8" prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.10.0-dev"} sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sc-client-api = { version = "4.0.0-dev", path = "../api" } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } diff --git a/client/beefy/Cargo.toml b/client/beefy/Cargo.toml index b0f05888712d..cb561c0dc77a 100644 --- a/client/beefy/Cargo.toml +++ b/client/beefy/Cargo.toml @@ -22,7 +22,7 @@ sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } sp-application-crypto = { version = "4.0.0-dev", path = "../../primitives/application-crypto" } sp-arithmetic = { version = "4.0.0-dev", path = "../../primitives/arithmetic" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-keystore = { version = "0.10.0-dev", path = "../../primitives/keystore" } sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } diff --git a/client/beefy/rpc/Cargo.toml b/client/beefy/rpc/Cargo.toml index 4d7bd6cef6c8..83f6b392f55c 100644 --- a/client/beefy/rpc/Cargo.toml +++ b/client/beefy/rpc/Cargo.toml @@ -21,7 +21,7 @@ codec = { version = "2.2.0", package = "parity-scale-codec", features = ["derive sc-rpc = { version = "4.0.0-dev", path = "../../rpc" } -sp-core = { version = "4.0.0", path = "../../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } beefy-gadget = { version = "4.0.0-dev", path = "../." } diff --git a/client/block-builder/Cargo.toml b/client/block-builder/Cargo.toml index 789e3fffcfa1..69154699e3f1 100644 --- a/client/block-builder/Cargo.toml +++ b/client/block-builder/Cargo.toml @@ -18,7 +18,7 @@ sp-state-machine = { version = "0.10.0-dev", path = "../../primitives/state-mach sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-block-builder = { version = "4.0.0-dev", path = "../../primitives/block-builder" } sp-inherents = { version = "4.0.0-dev", path = "../../primitives/inherents" } sc-client-api = { version = "4.0.0-dev", path = "../api" } diff --git a/client/chain-spec/Cargo.toml b/client/chain-spec/Cargo.toml index 1b4e3ed72d56..fdc72307af2a 100644 --- a/client/chain-spec/Cargo.toml +++ b/client/chain-spec/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] sc-chain-spec-derive = { version = "4.0.0-dev", path = "./derive" } impl-trait-for-tuples = "0.2.1" sc-network = { version = "0.10.0-dev", path = "../network" } -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } serde = { version = "1.0.126", features = ["derive"] } serde_json = "1.0.71" sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index a9bc4e9f87a5..566ce21cfe90 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -32,7 +32,7 @@ sc-network = { version = "0.10.0-dev", path = "../network" } sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } sc-utils = { version = "4.0.0-dev", path = "../utils" } sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-keystore = { version = "0.10.0-dev", path = "../../primitives/keystore" } sc-service = { version = "0.10.0-dev", default-features = false, path = "../service" } sc-telemetry = { version = "4.0.0-dev", path = "../telemetry" } diff --git a/client/cli/src/commands/inspect_key.rs b/client/cli/src/commands/inspect_key.rs index 277c9015f4da..48b045f4cbaf 100644 --- a/client/cli/src/commands/inspect_key.rs +++ b/client/cli/src/commands/inspect_key.rs @@ -21,7 +21,10 @@ use crate::{ utils::{self, print_from_public, print_from_uri}, with_crypto_scheme, CryptoSchemeFlag, Error, KeystoreParams, NetworkSchemeFlag, OutputTypeFlag, }; +use sp_core::crypto::{ExposeSecret, SecretString, SecretUri, Ss58Codec}; +use std::str::FromStr; use structopt::StructOpt; + /// The `inspect` command #[derive(Debug, StructOpt)] #[structopt( @@ -59,6 +62,18 @@ pub struct InspectKeyCmd { #[allow(missing_docs)] #[structopt(flatten)] pub crypto_scheme: CryptoSchemeFlag, + + /// Expect that `--uri` has the given public key/account-id. + /// + /// If `--uri` has any derivations, the public key is checked against the base `uri`, i.e. the + /// `uri` without any derivation applied. However, if `uri` has a password or there is one + /// given by `--password`, it will be used to decrypt `uri` before comparing the public + /// key/account-id. + /// + /// If there is no derivation in `--uri`, the public key will be checked against the public key + /// of `--uri` directly. + #[structopt(long, conflicts_with = "public")] + pub expect_public: Option, } impl InspectKeyCmd { @@ -77,6 +92,13 @@ impl InspectKeyCmd { ) )?; } else { + if let Some(ref expect_public) = self.expect_public { + with_crypto_scheme!( + self.crypto_scheme.scheme, + expect_public_from_phrase(&&expect_public, &uri, password.as_ref(),) + )?; + } + with_crypto_scheme!( self.crypto_scheme.scheme, print_from_uri( @@ -92,9 +114,50 @@ impl InspectKeyCmd { } } +/// Checks that `expect_public` is the public key of `suri`. +/// +/// If `suri` has any derivations, `expect_public` is checked against the public key of the "bare" +/// `suri`, i.e. without any derivations. +/// +/// Returns an error if the public key does not match. +fn expect_public_from_phrase( + expect_public: &str, + suri: &str, + password: Option<&SecretString>, +) -> Result<(), Error> { + let secret_uri = SecretUri::from_str(suri).map_err(|e| format!("{:?}", e))?; + let expected_public = if let Some(public) = expect_public.strip_prefix("0x") { + let hex_public = hex::decode(&public) + .map_err(|_| format!("Invalid expected public key hex: `{}`", expect_public))?; + Pair::Public::try_from(&hex_public) + .map_err(|_| format!("Invalid expected public key: `{}`", expect_public))? + } else { + Pair::Public::from_string_with_version(expect_public) + .map_err(|_| format!("Invalid expected account id: `{}`", expect_public))? + .0 + }; + + let pair = Pair::from_string_with_seed( + secret_uri.phrase.expose_secret().as_str(), + password + .or_else(|| secret_uri.password.as_ref()) + .map(|p| p.expose_secret().as_str()), + ) + .map_err(|_| format!("Invalid secret uri: {}", suri))? + .0; + + if pair.public() == expected_public { + Ok(()) + } else { + Err(format!("Expected public ({}) key does not match.", expect_public).into()) + } +} + #[cfg(test)] mod tests { use super::*; + use sp_core::crypto::{Pair, Public}; + use sp_runtime::traits::IdentifyAccount; use structopt::StructOpt; #[test] @@ -117,4 +180,90 @@ mod tests { let inspect = InspectKeyCmd::from_iter(&["inspect-key", "--public", public]); assert!(inspect.run().is_ok()); } + + #[test] + fn inspect_with_expected_public_key() { + let check_cmd = |seed, expected_public, success| { + let inspect = InspectKeyCmd::from_iter(&[ + "inspect-key", + "--expect-public", + expected_public, + seed, + ]); + let res = inspect.run(); + + if success { + assert!(res.is_ok()); + } else { + assert!(res.unwrap_err().to_string().contains(&format!( + "Expected public ({}) key does not match.", + expected_public + ))); + } + }; + + let seed = + "remember fiber forum demise paper uniform squirrel feel access exclude casual effort"; + let invalid_public = "0x12e76e0ae8ce41b6516cce52b3f23a08dcb4cfeed53c6ee8f5eb9f7367341069"; + let valid_public = sp_core::sr25519::Pair::from_string_with_seed(seed, None) + .expect("Valid") + .0 + .public(); + let valid_public_hex = format!("0x{}", hex::encode(valid_public.as_slice())); + let valid_accountid = format!("{}", valid_public.into_account()); + + // It should fail with the invalid public key + check_cmd(seed, invalid_public, false); + + // It should work with the valid public key & account id + check_cmd(seed, &valid_public_hex, true); + check_cmd(seed, &valid_accountid, true); + + let password = "test12245"; + let seed_with_password = format!("{}///{}", seed, password); + let valid_public_with_password = + sp_core::sr25519::Pair::from_string_with_seed(&seed_with_password, Some(password)) + .expect("Valid") + .0 + .public(); + let valid_public_hex_with_password = + format!("0x{}", hex::encode(&valid_public_with_password.as_slice())); + let valid_accountid_with_password = + format!("{}", &valid_public_with_password.into_account()); + + // Only the public key that corresponds to the seed with password should be accepted. + check_cmd(&seed_with_password, &valid_public_hex, false); + check_cmd(&seed_with_password, &valid_accountid, false); + + check_cmd(&seed_with_password, &valid_public_hex_with_password, true); + check_cmd(&seed_with_password, &valid_accountid_with_password, true); + + let seed_with_password_and_derivation = format!("{}//test//account///{}", seed, password); + + let valid_public_with_password_and_derivation = + sp_core::sr25519::Pair::from_string_with_seed( + &seed_with_password_and_derivation, + Some(password), + ) + .expect("Valid") + .0 + .public(); + let valid_public_hex_with_password_and_derivation = + format!("0x{}", hex::encode(&valid_public_with_password_and_derivation.as_slice())); + + // They should still be valid, because we check the base secret key. + check_cmd(&seed_with_password_and_derivation, &valid_public_hex_with_password, true); + check_cmd(&seed_with_password_and_derivation, &valid_accountid_with_password, true); + + // And these should be invalid. + check_cmd(&seed_with_password_and_derivation, &valid_public_hex, false); + check_cmd(&seed_with_password_and_derivation, &valid_accountid, false); + + // The public of the derived account should fail. + check_cmd( + &seed_with_password_and_derivation, + &valid_public_hex_with_password_and_derivation, + false, + ); + } } diff --git a/client/consensus/aura/Cargo.toml b/client/consensus/aura/Cargo.toml index 967f59999c7e..f12578b8a678 100644 --- a/client/consensus/aura/Cargo.toml +++ b/client/consensus/aura/Cargo.toml @@ -26,7 +26,7 @@ derive_more = "0.99.16" futures = "0.3.9" sp-inherents = { version = "4.0.0-dev", path = "../../../primitives/inherents" } log = "0.4.8" -sp-core = { version = "4.0.0", path = "../../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sc-consensus-slots = { version = "0.10.0-dev", path = "../slots" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } diff --git a/client/consensus/babe/Cargo.toml b/client/consensus/babe/Cargo.toml index 5f1a8a088916..7daab5557b57 100644 --- a/client/consensus/babe/Cargo.toml +++ b/client/consensus/babe/Cargo.toml @@ -19,7 +19,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", features = [ ] } sp-consensus-babe = { version = "0.10.0-dev", path = "../../../primitives/consensus/babe" } sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/common" } -sp-core = { version = "4.0.0", path = "../../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sp-application-crypto = { version = "4.0.0-dev", path = "../../../primitives/application-crypto" } sp-keystore = { version = "0.10.0-dev", path = "../../../primitives/keystore" } num-bigint = "0.2.3" diff --git a/client/consensus/babe/rpc/Cargo.toml b/client/consensus/babe/rpc/Cargo.toml index bba579ee111b..3bd8bf6e7658 100644 --- a/client/consensus/babe/rpc/Cargo.toml +++ b/client/consensus/babe/rpc/Cargo.toml @@ -27,7 +27,7 @@ futures = "0.3.16" derive_more = "0.99.16" sp-api = { version = "4.0.0-dev", path = "../../../../primitives/api" } sp-consensus = { version = "0.10.0-dev", path = "../../../../primitives/consensus/common" } -sp-core = { version = "4.0.0", path = "../../../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../../../primitives/core" } sp-application-crypto = { version = "4.0.0-dev", path = "../../../../primitives/application-crypto" } sp-keystore = { version = "0.10.0-dev", path = "../../../../primitives/keystore" } diff --git a/client/consensus/common/Cargo.toml b/client/consensus/common/Cargo.toml index 13b720354018..f20e12cc4aae 100644 --- a/client/consensus/common/Cargo.toml +++ b/client/consensus/common/Cargo.toml @@ -20,7 +20,7 @@ futures = { version = "0.3.1", features = ["thread-pool"] } futures-timer = "3.0.1" sc-client-api = { version = "4.0.0-dev", path = "../../api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-core = { path = "../../../primitives/core", version = "4.0.0" } +sp-core = { path = "../../../primitives/core", version = "4.1.0-dev" } sp-consensus = { path = "../../../primitives/consensus/common", version = "0.10.0-dev" } sp-state-machine = { version = "0.10.0-dev", path = "../../../primitives/state-machine" } sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } diff --git a/client/consensus/manual-seal/Cargo.toml b/client/consensus/manual-seal/Cargo.toml index 24314fefd156..59d35819c781 100644 --- a/client/consensus/manual-seal/Cargo.toml +++ b/client/consensus/manual-seal/Cargo.toml @@ -36,7 +36,7 @@ sp-consensus = { path = "../../../primitives/consensus/common", version = "0.10. sp-consensus-slots = { path = "../../../primitives/consensus/slots", version = "0.10.0-dev" } sp-inherents = { path = "../../../primitives/inherents", version = "4.0.0-dev" } sp-runtime = { path = "../../../primitives/runtime", version = "4.0.0-dev" } -sp-core = { path = "../../../primitives/core", version = "4.0.0" } +sp-core = { path = "../../../primitives/core", version = "4.1.0-dev" } sp-keystore = { path = "../../../primitives/keystore", version = "0.10.0-dev" } sp-api = { path = "../../../primitives/api", version = "4.0.0-dev" } sc-transaction-pool-api = { path = "../../../client/transaction-pool/api", version = "4.0.0-dev" } diff --git a/client/consensus/pow/Cargo.toml b/client/consensus/pow/Cargo.toml index 2b0926ce887e..d4b156f0b8fa 100644 --- a/client/consensus/pow/Cargo.toml +++ b/client/consensus/pow/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", features = ["derive"] } -sp-core = { version = "4.0.0", path = "../../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } diff --git a/client/consensus/slots/Cargo.toml b/client/consensus/slots/Cargo.toml index 7b4aa26cdf54..c97a3d1fe035 100644 --- a/client/consensus/slots/Cargo.toml +++ b/client/consensus/slots/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0" } sc-client-api = { version = "4.0.0-dev", path = "../../api" } -sp-core = { version = "4.0.0", path = "../../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sp-arithmetic = { version = "4.0.0-dev", path = "../../../primitives/arithmetic" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/common" } diff --git a/client/db/Cargo.toml b/client/db/Cargo.toml index f0ce20354a80..a2ed46c48e1c 100644 --- a/client/db/Cargo.toml +++ b/client/db/Cargo.toml @@ -26,7 +26,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", features = [ sc-client-api = { version = "4.0.0-dev", path = "../api" } sp-arithmetic = { version = "4.0.0-dev", path = "../../primitives/arithmetic" } -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } sp-state-machine = { version = "0.10.0-dev", path = "../../primitives/state-machine" } sc-state-db = { version = "0.10.0-dev", path = "../state-db" } diff --git a/client/executor/Cargo.toml b/client/executor/Cargo.toml index dea8a26edde3..58d7ec34b20e 100644 --- a/client/executor/Cargo.toml +++ b/client/executor/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0" } sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-tasks = { version = "4.0.0-dev", path = "../../primitives/tasks" } sp-trie = { version = "4.0.0-dev", path = "../../primitives/trie" } sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } diff --git a/client/executor/common/Cargo.toml b/client/executor/common/Cargo.toml index 198d5201e1f5..abaee7607303 100644 --- a/client/executor/common/Cargo.toml +++ b/client/executor/common/Cargo.toml @@ -18,7 +18,7 @@ derive_more = "0.99.16" pwasm-utils = "0.18.2" codec = { package = "parity-scale-codec", version = "2.0.0" } wasmi = "0.9.1" -sp-core = { version = "4.0.0", path = "../../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sc-allocator = { version = "4.1.0-dev", path = "../../allocator" } sp-wasm-interface = { version = "4.0.0", path = "../../../primitives/wasm-interface" } sp-maybe-compressed-blob = { version = "4.1.0-dev", path = "../../../primitives/maybe-compressed-blob" } diff --git a/client/executor/runtime-test/Cargo.toml b/client/executor/runtime-test/Cargo.toml index 831ff786ca09..4572a23c630a 100644 --- a/client/executor/runtime-test/Cargo.toml +++ b/client/executor/runtime-test/Cargo.toml @@ -13,7 +13,7 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-core = { version = "4.0.0", default-features = false, path = "../../../primitives/core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/io" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } sp-sandbox = { version = "0.10.0-dev", default-features = false, path = "../../../primitives/sandbox" } diff --git a/client/executor/wasmi/Cargo.toml b/client/executor/wasmi/Cargo.toml index f1e01d944a6e..d50237edfe4a 100644 --- a/client/executor/wasmi/Cargo.toml +++ b/client/executor/wasmi/Cargo.toml @@ -21,5 +21,5 @@ sc-executor-common = { version = "0.10.0-dev", path = "../common" } sc-allocator = { version = "4.1.0-dev", path = "../../allocator" } sp-wasm-interface = { version = "4.0.0", path = "../../../primitives/wasm-interface" } sp-runtime-interface = { version = "4.0.0", path = "../../../primitives/runtime-interface" } -sp-core = { version = "4.0.0", path = "../../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } scoped-tls = "1.0" diff --git a/client/executor/wasmtime/Cargo.toml b/client/executor/wasmtime/Cargo.toml index 77210b97f376..49e44766b9d4 100644 --- a/client/executor/wasmtime/Cargo.toml +++ b/client/executor/wasmtime/Cargo.toml @@ -21,7 +21,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0" } sc-executor-common = { version = "0.10.0-dev", path = "../common" } sp-wasm-interface = { version = "4.0.0", path = "../../../primitives/wasm-interface" } sp-runtime-interface = { version = "4.0.0", path = "../../../primitives/runtime-interface" } -sp-core = { version = "4.0.0", path = "../../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sc-allocator = { version = "4.1.0-dev", path = "../../allocator" } wasmtime = { version = "0.31.0", default-features = false, features = [ "cache", diff --git a/client/finality-grandpa/Cargo.toml b/client/finality-grandpa/Cargo.toml index fa60751d4891..12aedbfe0143 100644 --- a/client/finality-grandpa/Cargo.toml +++ b/client/finality-grandpa/Cargo.toml @@ -30,7 +30,7 @@ sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } sc-utils = { version = "4.0.0-dev", path = "../utils" } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } sc-consensus = { version = "0.10.0-dev", path = "../consensus/common" } -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-keystore = { version = "0.10.0-dev", path = "../../primitives/keystore" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } sc-telemetry = { version = "4.0.0-dev", path = "../telemetry" } diff --git a/client/finality-grandpa/rpc/Cargo.toml b/client/finality-grandpa/rpc/Cargo.toml index a83a47af9ed4..9d0affde3b17 100644 --- a/client/finality-grandpa/rpc/Cargo.toml +++ b/client/finality-grandpa/rpc/Cargo.toml @@ -12,7 +12,7 @@ readme = "README.md" sc-finality-grandpa = { version = "0.10.0-dev", path = "../" } sc-rpc = { version = "4.0.0-dev", path = "../../rpc" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-core = { version = "4.0.0", path = "../../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } finality-grandpa = { version = "0.14.4", features = ["derive-codec"] } jsonrpc-core = "18.0.0" @@ -32,7 +32,7 @@ sc-block-builder = { version = "0.10.0-dev", path = "../../block-builder" } sc-rpc = { version = "4.0.0-dev", path = "../../rpc", features = [ "test-helpers", ] } -sp-core = { version = "4.0.0", path = "../../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sp-finality-grandpa = { version = "4.0.0-dev", path = "../../../primitives/finality-grandpa" } sp-keyring = { version = "4.0.0-dev", path = "../../../primitives/keyring" } substrate-test-runtime-client = { version = "2.0.0", path = "../../../test-utils/runtime/client" } diff --git a/client/keystore/Cargo.toml b/client/keystore/Cargo.toml index ac2663902b67..912de249ad0b 100644 --- a/client/keystore/Cargo.toml +++ b/client/keystore/Cargo.toml @@ -18,7 +18,7 @@ targets = ["x86_64-unknown-linux-gnu"] async-trait = "0.1.50" derive_more = "0.99.16" sp-application-crypto = { version = "4.0.0-dev", path = "../../primitives/application-crypto" } -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-keystore = { version = "0.10.0-dev", path = "../../primitives/keystore" } hex = "0.4.0" parking_lot = "0.11.1" diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index 229a273eabdc..5c8aedc84c19 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -53,7 +53,7 @@ sp-arithmetic = { version = "4.0.0-dev", path = "../../primitives/arithmetic" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } sc-consensus = { version = "0.10.0-dev", path = "../consensus/common" } -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } sc-utils = { version = "4.0.0-dev", path = "../utils" } sp-finality-grandpa = { version = "4.0.0-dev", path = "../../primitives/finality-grandpa" } diff --git a/client/network/test/Cargo.toml b/client/network/test/Cargo.toml index afa4622d2f05..748037fef644 100644 --- a/client/network/test/Cargo.toml +++ b/client/network/test/Cargo.toml @@ -26,7 +26,7 @@ sc-consensus = { version = "0.10.0-dev", path = "../../consensus/common" } sc-client-api = { version = "4.0.0-dev", path = "../../api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } -sp-core = { version = "4.0.0", path = "../../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sc-block-builder = { version = "0.10.0-dev", path = "../../block-builder" } sp-consensus-babe = { version = "0.10.0-dev", path = "../../../primitives/consensus/babe" } substrate-test-runtime-client = { version = "2.0.0", path = "../../../test-utils/runtime/client" } diff --git a/client/offchain/Cargo.toml b/client/offchain/Cargo.toml index 6f1fd3a035fe..4494beb2e3f4 100644 --- a/client/offchain/Cargo.toml +++ b/client/offchain/Cargo.toml @@ -25,7 +25,7 @@ rand = "0.7.2" sc-client-api = { version = "4.0.0-dev", path = "../api" } sc-network = { version = "0.10.0-dev", path = "../network" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-offchain = { version = "4.0.0-dev", path = "../../primitives/offchain" } sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } sc-utils = { version = "4.0.0-dev", path = "../utils" } diff --git a/client/rpc-api/Cargo.toml b/client/rpc-api/Cargo.toml index 5f7a2d2fb32b..3c97677c3fee 100644 --- a/client/rpc-api/Cargo.toml +++ b/client/rpc-api/Cargo.toml @@ -23,7 +23,7 @@ log = "0.4.8" parking_lot = "0.11.1" thiserror = "1.0" -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } sp-runtime = { path = "../../primitives/runtime", version = "4.0.0-dev" } sc-chain-spec = { path = "../chain-spec", version = "4.0.0-dev" } diff --git a/client/rpc/Cargo.toml b/client/rpc/Cargo.toml index 9d8461238fc0..1f1fe6b12aed 100644 --- a/client/rpc/Cargo.toml +++ b/client/rpc/Cargo.toml @@ -20,7 +20,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0" } futures = "0.3.16" jsonrpc-pubsub = "18.0.0" log = "0.4.8" -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } rpc = { package = "jsonrpc-core", version = "18.0.0" } sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } serde_json = "1.0.71" diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index 91143c45b4a2..25cd9026bc8b 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -42,7 +42,7 @@ sp-externalities = { version = "0.10.0", path = "../../primitives/externalities" sc-utils = { version = "4.0.0-dev", path = "../utils" } sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-keystore = { version = "0.10.0-dev", path = "../../primitives/keystore" } sp-session = { version = "4.0.0-dev", path = "../../primitives/session" } sp-state-machine = { version = "0.10.0-dev", path = "../../primitives/state-machine" } diff --git a/client/service/test/Cargo.toml b/client/service/test/Cargo.toml index c89442f3aec7..52f0ff6ecce0 100644 --- a/client/service/test/Cargo.toml +++ b/client/service/test/Cargo.toml @@ -32,7 +32,7 @@ sc-network = { version = "0.10.0-dev", path = "../../network" } sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" } sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/common" } sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } -sp-core = { version = "4.0.0", path = "../../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../../../client/transaction-pool/api" } substrate-test-runtime = { version = "2.0.0", path = "../../../test-utils/runtime" } substrate-test-runtime-client = { version = "2.0.0", path = "../../../test-utils/runtime/client" } diff --git a/client/state-db/Cargo.toml b/client/state-db/Cargo.toml index 8c059e80cdb2..6a5b8516237d 100644 --- a/client/state-db/Cargo.toml +++ b/client/state-db/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] parking_lot = "0.11.1" log = "0.4.11" sc-client-api = { version = "4.0.0-dev", path = "../api" } -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } codec = { package = "parity-scale-codec", version = "2.0.0", features = ["derive"] } parity-util-mem = { version = "0.10.2", default-features = false, features = ["primitive-types"] } parity-util-mem-derive = "0.1.0" diff --git a/client/tracing/Cargo.toml b/client/tracing/Cargo.toml index 81710887b816..4d91e61127db 100644 --- a/client/tracing/Cargo.toml +++ b/client/tracing/Cargo.toml @@ -33,7 +33,7 @@ sp-rpc = { version = "4.0.0-dev", path = "../../primitives/rpc" } sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sc-client-api = { version = "4.0.0-dev", path = "../api" } sc-tracing-proc-macro = { version = "4.0.0-dev", path = "./proc-macro" } sc-rpc-server = { version = "4.0.0-dev", path = "../rpc-servers" } diff --git a/client/transaction-pool/Cargo.toml b/client/transaction-pool/Cargo.toml index b3a7095fcb75..6ed97edbf476 100644 --- a/client/transaction-pool/Cargo.toml +++ b/client/transaction-pool/Cargo.toml @@ -23,7 +23,7 @@ parking_lot = "0.11.1" prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.10.0-dev"} sc-client-api = { version = "4.0.0-dev", path = "../api" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } sp-transaction-pool = { version = "4.0.0-dev", path = "../../primitives/transaction-pool" } diff --git a/frame/assets/Cargo.toml b/frame/assets/Cargo.toml index 0f2e3cbf3d4e..37ff7582f5c6 100644 --- a/frame/assets/Cargo.toml +++ b/frame/assets/Cargo.toml @@ -25,7 +25,7 @@ frame-system = { version = "4.0.0-dev", default-features = false, path = "../sys frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-std = { version = "4.0.0", path = "../../primitives/std" } sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } diff --git a/frame/atomic-swap/Cargo.toml b/frame/atomic-swap/Cargo.toml index 0c2d7616f57e..54e579550443 100644 --- a/frame/atomic-swap/Cargo.toml +++ b/frame/atomic-swap/Cargo.toml @@ -20,7 +20,7 @@ frame-system = { version = "4.0.0-dev", default-features = false, path = "../sys sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } [dev-dependencies] pallet-balances = { version = "4.0.0-dev", path = "../balances" } diff --git a/frame/aura/Cargo.toml b/frame/aura/Cargo.toml index 1252e7b51e00..9ed07e724b30 100644 --- a/frame/aura/Cargo.toml +++ b/frame/aura/Cargo.toml @@ -24,7 +24,7 @@ frame-system = { version = "4.0.0-dev", default-features = false, path = "../sys pallet-timestamp = { version = "4.0.0-dev", default-features = false, path = "../timestamp" } [dev-dependencies] -sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } [features] diff --git a/frame/authority-discovery/Cargo.toml b/frame/authority-discovery/Cargo.toml index c7b5abe350b8..1a0f5925732c 100644 --- a/frame/authority-discovery/Cargo.toml +++ b/frame/authority-discovery/Cargo.toml @@ -28,7 +28,7 @@ frame-support = { version = "4.0.0-dev", default-features = false, path = "../su frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } [features] diff --git a/frame/authorship/Cargo.toml b/frame/authorship/Cargo.toml index 48a6c473875c..2a0dc8bdd9a7 100644 --- a/frame/authorship/Cargo.toml +++ b/frame/authorship/Cargo.toml @@ -25,7 +25,7 @@ frame-system = { version = "4.0.0-dev", default-features = false, path = "../sys impl-trait-for-tuples = "0.2.1" [dev-dependencies] -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } [features] diff --git a/frame/babe/Cargo.toml b/frame/babe/Cargo.toml index 077a8cb89a92..414cfcb222d4 100644 --- a/frame/babe/Cargo.toml +++ b/frame/babe/Cargo.toml @@ -36,7 +36,7 @@ pallet-balances = { version = "4.0.0-dev", path = "../balances" } pallet-offences = { version = "4.0.0-dev", path = "../offences" } pallet-staking = { version = "4.0.0-dev", path = "../staking" } pallet-staking-reward-curve = { version = "4.0.0-dev", path = "../staking/reward-curve" } -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } frame-election-provider-support = { version = "4.0.0-dev", path = "../election-provider-support" } [features] diff --git a/frame/bags-list/Cargo.toml b/frame/bags-list/Cargo.toml index fe8d08ed9766..66bb1c48a929 100644 --- a/frame/bags-list/Cargo.toml +++ b/frame/bags-list/Cargo.toml @@ -32,12 +32,12 @@ log = { version = "0.4.14", default-features = false } # Optional imports for benchmarking frame-benchmarking = { version = "4.0.0-dev", path = "../benchmarking", optional = true, default-features = false } pallet-balances = { version = "4.0.0-dev", path = "../balances", optional = true, default-features = false } -sp-core = { version = "4.0.0", path = "../../primitives/core", optional = true, default-features = false } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core", optional = true, default-features = false } sp-io = { version = "4.0.0-dev", path = "../../primitives/io", optional = true, default-features = false } sp-tracing = { version = "4.0.0", path = "../../primitives/tracing", optional = true, default-features = false } [dev-dependencies] -sp-core = { version = "4.0.0", path = "../../primitives/core"} +sp-core = { version = "4.1.0-dev", path = "../../primitives/core"} sp-io = { version = "4.0.0-dev", path = "../../primitives/io"} sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } diff --git a/frame/bags-list/remote-tests/Cargo.toml b/frame/bags-list/remote-tests/Cargo.toml index 5a5b028285d8..646b47275c18 100644 --- a/frame/bags-list/remote-tests/Cargo.toml +++ b/frame/bags-list/remote-tests/Cargo.toml @@ -22,7 +22,7 @@ frame-support = { path = "../../support", version = "4.0.0-dev" } # core sp-storage = { path = "../../../primitives/storage", version = "4.0.0" } -sp-core = { path = "../../../primitives/core", version = "4.0.0" } +sp-core = { path = "../../../primitives/core", version = "4.1.0-dev" } sp-tracing = { path = "../../../primitives/tracing", version = "4.0.0" } sp-runtime = { path = "../../../primitives/runtime", version = "4.0.0-dev" } sp-std = { path = "../../../primitives/std", version = "4.0.0" } diff --git a/frame/balances/Cargo.toml b/frame/balances/Cargo.toml index 825869c6b972..1ac7b71fb340 100644 --- a/frame/balances/Cargo.toml +++ b/frame/balances/Cargo.toml @@ -24,7 +24,7 @@ log = { version = "0.4.14", default-features = false } [dev-dependencies] sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } pallet-transaction-payment = { version = "4.0.0-dev", path = "../transaction-payment" } [features] diff --git a/frame/beefy-mmr/Cargo.toml b/frame/beefy-mmr/Cargo.toml index cebd7a6d962b..64cdf805db9a 100644 --- a/frame/beefy-mmr/Cargo.toml +++ b/frame/beefy-mmr/Cargo.toml @@ -21,7 +21,7 @@ pallet-mmr = { version = "4.0.0-dev", path = "../merkle-mountain-range", default pallet-mmr-primitives = { version = "4.0.0-dev", path = "../merkle-mountain-range/primitives", default-features = false } pallet-session = { version = "4.0.0-dev", path = "../session", default-features = false } -sp-core = { version = "4.0.0", path = "../../primitives/core", default-features = false } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core", default-features = false } sp-io = { version = "4.0.0-dev", path = "../../primitives/io", default-features = false } sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime", default-features = false } sp-std = { version = "4.0.0", path = "../../primitives/std", default-features = false } diff --git a/frame/beefy/Cargo.toml b/frame/beefy/Cargo.toml index 4bfd9f19b280..c90f0d7328be 100644 --- a/frame/beefy/Cargo.toml +++ b/frame/beefy/Cargo.toml @@ -23,7 +23,7 @@ pallet-session = { version = "4.0.0-dev", path = "../session", default-features beefy-primitives = { version = "4.0.0-dev", path = "../../primitives/beefy", default-features = false } [dev-dependencies] -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } sp-staking = { version = "4.0.0-dev", path = "../../primitives/staking" } diff --git a/frame/bounties/Cargo.toml b/frame/bounties/Cargo.toml index 5dfa05bba0a0..97364ba41f63 100644 --- a/frame/bounties/Cargo.toml +++ b/frame/bounties/Cargo.toml @@ -23,7 +23,7 @@ frame-support = { version = "4.0.0-dev", default-features = false, path = "../su frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } pallet-treasury = { version = "4.0.0-dev", default-features = false, path = "../treasury" } sp-io = { version = "4.0.0-dev", path = "../../primitives/io", default-features = false } -sp-core = { version = "4.0.0", path = "../../primitives/core", default-features = false } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core", default-features = false } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } log = { version = "0.4.14", default-features = false } diff --git a/frame/child-bounties/Cargo.toml b/frame/child-bounties/Cargo.toml index 37152e29d8f4..17cfc482af06 100644 --- a/frame/child-bounties/Cargo.toml +++ b/frame/child-bounties/Cargo.toml @@ -24,7 +24,7 @@ frame-system = { version = "4.0.0-dev", default-features = false, path = "../sys pallet-treasury = { version = "4.0.0-dev", default-features = false, path = "../treasury" } pallet-bounties = { version = "4.0.0-dev", default-features = false, path = "../bounties" } sp-io = { version = "4.0.0-dev", path = "../../primitives/io", default-features = false } -sp-core = { version = "4.0.0", path = "../../primitives/core", default-features = false } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core", default-features = false } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } log = { version = "0.4.14", default-features = false } diff --git a/frame/collective/Cargo.toml b/frame/collective/Cargo.toml index 76799ae981c7..6d3b081c89c1 100644 --- a/frame/collective/Cargo.toml +++ b/frame/collective/Cargo.toml @@ -17,7 +17,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = log = { version = "0.4.14", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } diff --git a/frame/contracts/Cargo.toml b/frame/contracts/Cargo.toml index bb7a0693147b..963f1466a9ea 100644 --- a/frame/contracts/Cargo.toml +++ b/frame/contracts/Cargo.toml @@ -38,7 +38,7 @@ frame-support = { version = "4.0.0-dev", default-features = false, path = "../su frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } pallet-contracts-primitives = { version = "4.0.0-dev", default-features = false, path = "common" } pallet-contracts-proc-macro = { version = "4.0.0-dev", path = "proc-macro" } -sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } sp-sandbox = { version = "0.10.0-dev", default-features = false, path = "../../primitives/sandbox" } diff --git a/frame/contracts/common/Cargo.toml b/frame/contracts/common/Cargo.toml index ebfd5fab5af1..0e0cf1528b1a 100644 --- a/frame/contracts/common/Cargo.toml +++ b/frame/contracts/common/Cargo.toml @@ -19,7 +19,7 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] serde = { version = "1", features = ["derive"], optional = true } # Substrate Dependencies (This crate should not rely on frame) -sp-core = { version = "4.0.0", path = "../../../primitives/core", default-features = false } +sp-core = { version = "4.1.0-dev", path = "../../../primitives/core", default-features = false } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } sp-rpc = { version = "4.0.0-dev", path = "../../../primitives/rpc", optional = true } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } diff --git a/frame/contracts/rpc/Cargo.toml b/frame/contracts/rpc/Cargo.toml index aac5683a79e5..e380708a9dee 100644 --- a/frame/contracts/rpc/Cargo.toml +++ b/frame/contracts/rpc/Cargo.toml @@ -24,7 +24,7 @@ pallet-contracts-primitives = { version = "4.0.0-dev", path = "../common" } pallet-contracts-rpc-runtime-api = { version = "4.0.0-dev", path = "./runtime-api" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-core = { version = "4.0.0", path = "../../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sp-rpc = { version = "4.0.0-dev", path = "../../../primitives/rpc" } sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } diff --git a/frame/democracy/Cargo.toml b/frame/democracy/Cargo.toml index becec8a878d5..32acdb964ed8 100644 --- a/frame/democracy/Cargo.toml +++ b/frame/democracy/Cargo.toml @@ -26,7 +26,7 @@ frame-support = { version = "4.0.0-dev", default-features = false, path = "../su frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } pallet-scheduler = { version = "4.0.0-dev", path = "../scheduler" } diff --git a/frame/election-provider-multi-phase/Cargo.toml b/frame/election-provider-multi-phase/Cargo.toml index 42d7c4064cb3..a1df7edc1331 100644 --- a/frame/election-provider-multi-phase/Cargo.toml +++ b/frame/election-provider-multi-phase/Cargo.toml @@ -25,7 +25,7 @@ frame-system = { version = "4.0.0-dev", default-features = false, path = "../sys sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } sp-npos-elections = { version = "4.0.0-dev", default-features = false, path = "../../primitives/npos-elections" } sp-arithmetic = { version = "4.0.0-dev", default-features = false, path = "../../primitives/arithmetic" } @@ -43,7 +43,7 @@ strum_macros = { optional = true, version = "0.22.0" } [dev-dependencies] parking_lot = "0.11.0" rand = { version = "0.7.3" } -sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } sp-npos-elections = { version = "4.0.0-dev", default-features = false, path = "../../primitives/npos-elections" } sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } diff --git a/frame/election-provider-support/Cargo.toml b/frame/election-provider-support/Cargo.toml index a69dca39b8e8..80b7f9d7bfc0 100644 --- a/frame/election-provider-support/Cargo.toml +++ b/frame/election-provider-support/Cargo.toml @@ -24,7 +24,7 @@ frame-system = { version = "4.0.0-dev", default-features = false, path = "../sys [dev-dependencies] sp-npos-elections = { version = "4.0.0-dev", path = "../../primitives/npos-elections" } sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } [features] diff --git a/frame/elections-phragmen/Cargo.toml b/frame/elections-phragmen/Cargo.toml index a5e9ca777c3c..7ab81a4f3300 100644 --- a/frame/elections-phragmen/Cargo.toml +++ b/frame/elections-phragmen/Cargo.toml @@ -23,13 +23,13 @@ sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primiti frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } log = { version = "0.4.14", default-features = false } [dev-dependencies] pallet-balances = { version = "4.0.0-dev", path = "../balances" } -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } substrate-test-utils = { version = "4.0.0-dev", path = "../../test-utils" } [features] diff --git a/frame/elections/Cargo.toml b/frame/elections/Cargo.toml index e5f7d27d8911..d1404f762612 100644 --- a/frame/elections/Cargo.toml +++ b/frame/elections/Cargo.toml @@ -17,7 +17,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = "derive", ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } diff --git a/frame/examples/basic/Cargo.toml b/frame/examples/basic/Cargo.toml index 5edd3bfef8de..db39d339f2c5 100644 --- a/frame/examples/basic/Cargo.toml +++ b/frame/examples/basic/Cargo.toml @@ -26,7 +26,7 @@ sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../.. sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } [dev-dependencies] -sp-core = { version = "4.0.0", path = "../../../primitives/core", default-features = false } +sp-core = { version = "4.1.0-dev", path = "../../../primitives/core", default-features = false } [features] default = ["std"] diff --git a/frame/examples/offchain-worker/Cargo.toml b/frame/examples/offchain-worker/Cargo.toml index 44886afba5e1..f53ea369278d 100644 --- a/frame/examples/offchain-worker/Cargo.toml +++ b/frame/examples/offchain-worker/Cargo.toml @@ -20,7 +20,7 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" } -sp-core = { version = "4.0.0", default-features = false, path = "../../../primitives/core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/io" } sp-keystore = { version = "0.10.0-dev", path = "../../../primitives/keystore", optional = true } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } diff --git a/frame/examples/parallel/Cargo.toml b/frame/examples/parallel/Cargo.toml index 3d9104eb3545..d28dd5b9ee0a 100644 --- a/frame/examples/parallel/Cargo.toml +++ b/frame/examples/parallel/Cargo.toml @@ -17,7 +17,7 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" } -sp-core = { version = "4.0.0", default-features = false, path = "../../../primitives/core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/io" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } diff --git a/frame/executive/Cargo.toml b/frame/executive/Cargo.toml index 9509fc5c977b..d511bb858c7d 100644 --- a/frame/executive/Cargo.toml +++ b/frame/executive/Cargo.toml @@ -23,11 +23,11 @@ sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../pr sp-tracing = { version = "4.0.0", default-features = false, path = "../../primitives/tracing" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } [dev-dependencies] hex-literal = "0.3.4" -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } pallet-transaction-payment = { version = "4.0.0-dev", path = "../transaction-payment" } diff --git a/frame/gilt/Cargo.toml b/frame/gilt/Cargo.toml index 14948546a177..05e252627b2b 100644 --- a/frame/gilt/Cargo.toml +++ b/frame/gilt/Cargo.toml @@ -24,7 +24,7 @@ frame-system = { version = "4.0.0-dev", default-features = false, path = "../sys [dev-dependencies] sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/frame/grandpa/Cargo.toml b/frame/grandpa/Cargo.toml index d052b468f927..601ec9aee10e 100644 --- a/frame/grandpa/Cargo.toml +++ b/frame/grandpa/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-application-crypto = { version = "4.0.0-dev", default-features = false, path = "../../primitives/application-crypto" } -sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-finality-grandpa = { version = "4.0.0-dev", default-features = false, path = "../../primitives/finality-grandpa" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../primitives/session" } diff --git a/frame/identity/Cargo.toml b/frame/identity/Cargo.toml index dc247727e098..76a187f90c5d 100644 --- a/frame/identity/Cargo.toml +++ b/frame/identity/Cargo.toml @@ -24,7 +24,7 @@ frame-support = { version = "4.0.0-dev", default-features = false, path = "../su frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/frame/im-online/Cargo.toml b/frame/im-online/Cargo.toml index fc0a6acf1798..fdafc5376ad5 100644 --- a/frame/im-online/Cargo.toml +++ b/frame/im-online/Cargo.toml @@ -17,7 +17,7 @@ sp-application-crypto = { version = "4.0.0-dev", default-features = false, path pallet-authorship = { version = "4.0.0-dev", default-features = false, path = "../authorship" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } diff --git a/frame/indices/Cargo.toml b/frame/indices/Cargo.toml index f4f5146ae118..cd3957a45f82 100644 --- a/frame/indices/Cargo.toml +++ b/frame/indices/Cargo.toml @@ -19,7 +19,7 @@ sp-keyring = { version = "4.0.0-dev", optional = true, path = "../../primitives/ sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/lottery/Cargo.toml b/frame/lottery/Cargo.toml index db317d0d01ec..259be8267fe7 100644 --- a/frame/lottery/Cargo.toml +++ b/frame/lottery/Cargo.toml @@ -27,7 +27,7 @@ frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = " [dev-dependencies] frame-support-test = { version = "3.0.0", path = "../support/test" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } [features] diff --git a/frame/membership/Cargo.toml b/frame/membership/Cargo.toml index 105bdc55b5c0..d0567a3eeb15 100644 --- a/frame/membership/Cargo.toml +++ b/frame/membership/Cargo.toml @@ -17,7 +17,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } log = { version = "0.4.0", default-features = false } -sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } diff --git a/frame/merkle-mountain-range/Cargo.toml b/frame/merkle-mountain-range/Cargo.toml index 51b7e4a2a607..fd6615a4b542 100644 --- a/frame/merkle-mountain-range/Cargo.toml +++ b/frame/merkle-mountain-range/Cargo.toml @@ -16,7 +16,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } mmr-lib = { package = "ckb-merkle-mountain-range", default-features = false, version = "0.3.2" } -sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } diff --git a/frame/merkle-mountain-range/primitives/Cargo.toml b/frame/merkle-mountain-range/primitives/Cargo.toml index 11562c02bf32..0d11e50a8b68 100644 --- a/frame/merkle-mountain-range/primitives/Cargo.toml +++ b/frame/merkle-mountain-range/primitives/Cargo.toml @@ -17,7 +17,7 @@ log = { version = "0.4.14", default-features = false } serde = { version = "1.0.126", optional = true, features = ["derive"] } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/api" } -sp-core = { version = "4.0.0", default-features = false, path = "../../../primitives/core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } diff --git a/frame/merkle-mountain-range/rpc/Cargo.toml b/frame/merkle-mountain-range/rpc/Cargo.toml index 1cad739e3ba0..7283a4fac8b2 100644 --- a/frame/merkle-mountain-range/rpc/Cargo.toml +++ b/frame/merkle-mountain-range/rpc/Cargo.toml @@ -21,7 +21,7 @@ serde = { version = "1.0.126", features = ["derive"] } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-core = { version = "4.0.0", path = "../../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } pallet-mmr-primitives = { version = "4.0.0-dev", path = "../primitives" } diff --git a/frame/multisig/Cargo.toml b/frame/multisig/Cargo.toml index bb6323bc5cb7..d01dd58a2f3f 100644 --- a/frame/multisig/Cargo.toml +++ b/frame/multisig/Cargo.toml @@ -24,7 +24,7 @@ sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primiti frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/frame/nicks/Cargo.toml b/frame/nicks/Cargo.toml index 8d66bbb6b397..28cabde09166 100644 --- a/frame/nicks/Cargo.toml +++ b/frame/nicks/Cargo.toml @@ -22,7 +22,7 @@ frame-support = { version = "4.0.0-dev", default-features = false, path = "../su frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/frame/node-authorization/Cargo.toml b/frame/node-authorization/Cargo.toml index ec62d972d3a0..efaaf6371f8c 100644 --- a/frame/node-authorization/Cargo.toml +++ b/frame/node-authorization/Cargo.toml @@ -16,7 +16,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } -sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } diff --git a/frame/offences/Cargo.toml b/frame/offences/Cargo.toml index 8957f0c88cae..5058f17d3857 100644 --- a/frame/offences/Cargo.toml +++ b/frame/offences/Cargo.toml @@ -26,7 +26,7 @@ log = { version = "0.4.14", default-features = false } [dev-dependencies] sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } [features] default = ["std"] diff --git a/frame/offences/benchmarking/Cargo.toml b/frame/offences/benchmarking/Cargo.toml index 96674989e0f7..625f275a70ce 100644 --- a/frame/offences/benchmarking/Cargo.toml +++ b/frame/offences/benchmarking/Cargo.toml @@ -37,7 +37,7 @@ frame-election-provider-support = { version = "4.0.0-dev", default-features = fa [dev-dependencies] pallet-staking-reward-curve = { version = "4.0.0-dev", path = "../../staking/reward-curve" } pallet-timestamp = { version = "4.0.0-dev", path = "../../timestamp" } -sp-core = { version = "4.0.0", path = "../../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sp-io = { version = "4.0.0-dev", path = "../../../primitives/io" } [features] diff --git a/frame/proxy/Cargo.toml b/frame/proxy/Cargo.toml index 762ab482b985..7a1fc61da9d4 100644 --- a/frame/proxy/Cargo.toml +++ b/frame/proxy/Cargo.toml @@ -24,7 +24,7 @@ sp-std = { version = "4.0.0", default-features = false, path = "../../primitives frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } pallet-utility = { version = "4.0.0-dev", path = "../utility" } diff --git a/frame/randomness-collective-flip/Cargo.toml b/frame/randomness-collective-flip/Cargo.toml index 3bf2a9c30213..903e167ef95a 100644 --- a/frame/randomness-collective-flip/Cargo.toml +++ b/frame/randomness-collective-flip/Cargo.toml @@ -23,7 +23,7 @@ frame-support = { version = "4.0.0-dev", default-features = false, path = "../su frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } [features] diff --git a/frame/recovery/Cargo.toml b/frame/recovery/Cargo.toml index 18d4dfe7e47c..c1126ad1edd1 100644 --- a/frame/recovery/Cargo.toml +++ b/frame/recovery/Cargo.toml @@ -22,7 +22,7 @@ frame-support = { version = "4.0.0-dev", default-features = false, path = "../su frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/frame/scheduler/Cargo.toml b/frame/scheduler/Cargo.toml index 57eb5e16bd36..a1d43b359a88 100644 --- a/frame/scheduler/Cargo.toml +++ b/frame/scheduler/Cargo.toml @@ -22,7 +22,7 @@ log = { version = "0.4.14", default-features = false } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -sp-core = { version = "4.0.0", path = "../../primitives/core", default-features = false } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core", default-features = false } substrate-test-utils = { version = "4.0.0-dev", path = "../../test-utils" } [features] diff --git a/frame/scored-pool/Cargo.toml b/frame/scored-pool/Cargo.toml index 8f91908dddb9..e77661204d73 100644 --- a/frame/scored-pool/Cargo.toml +++ b/frame/scored-pool/Cargo.toml @@ -23,7 +23,7 @@ frame-system = { version = "4.0.0-dev", default-features = false, path = "../sys [dev-dependencies] pallet-balances = { version = "4.0.0-dev", path = "../balances" } -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } [features] default = ["std"] diff --git a/frame/session/Cargo.toml b/frame/session/Cargo.toml index 50aa623c90a8..909dfe329c9c 100644 --- a/frame/session/Cargo.toml +++ b/frame/session/Cargo.toml @@ -20,7 +20,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../primitives/session" } diff --git a/frame/session/benchmarking/Cargo.toml b/frame/session/benchmarking/Cargo.toml index 5dc0573b278f..37dc40e9b25c 100644 --- a/frame/session/benchmarking/Cargo.toml +++ b/frame/session/benchmarking/Cargo.toml @@ -28,7 +28,7 @@ pallet-staking = { version = "4.0.0-dev", default-features = false, features = [ [dev-dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", features = ["derive"] } scale-info = "1.0" -sp-core = { version = "4.0.0", path = "../../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sp-io = { version = "4.0.0-dev", path = "../../../primitives/io" } pallet-balances = { version = "4.0.0-dev", path = "../../balances" } pallet-timestamp = { version = "4.0.0-dev", path = "../../timestamp" } diff --git a/frame/society/Cargo.toml b/frame/society/Cargo.toml index 47ad0865b8f4..cf14d7f9f51c 100644 --- a/frame/society/Cargo.toml +++ b/frame/society/Cargo.toml @@ -22,7 +22,7 @@ frame-system = { version = "4.0.0-dev", default-features = false, path = "../sys rand_chacha = { version = "0.2", default-features = false } [dev-dependencies] -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-io ={ version = "4.0.0-dev", path = "../../primitives/io" } frame-support-test = { version = "3.0.0", path = "../support/test" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } diff --git a/frame/staking/Cargo.toml b/frame/staking/Cargo.toml index 70beead038b2..42fe1075317d 100644 --- a/frame/staking/Cargo.toml +++ b/frame/staking/Cargo.toml @@ -38,7 +38,7 @@ rand_chacha = { version = "0.2", default-features = false, optional = true } [dev-dependencies] sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-npos-elections = { version = "4.0.0-dev", path = "../../primitives/npos-elections" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } pallet-timestamp = { version = "4.0.0-dev", path = "../timestamp" } diff --git a/frame/sudo/Cargo.toml b/frame/sudo/Cargo.toml index d211d327b2d0..33642ef7dc3e 100644 --- a/frame/sudo/Cargo.toml +++ b/frame/sudo/Cargo.toml @@ -22,7 +22,7 @@ frame-support = { version = "4.0.0-dev", default-features = false, path = "../su frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } [features] default = ["std"] diff --git a/frame/support/Cargo.toml b/frame/support/Cargo.toml index 411b02449e4e..c3eab98f9e77 100644 --- a/frame/support/Cargo.toml +++ b/frame/support/Cargo.toml @@ -21,7 +21,7 @@ sp-std = { version = "4.0.0", default-features = false, path = "../../primitives sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } sp-tracing = { version = "4.0.0", default-features = false, path = "../../primitives/tracing" } -sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-arithmetic = { version = "4.0.0-dev", default-features = false, path = "../../primitives/arithmetic" } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../primitives/inherents" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" } diff --git a/frame/support/test/Cargo.toml b/frame/support/test/Cargo.toml index 13d66d147e57..0cd3f9ac0291 100644 --- a/frame/support/test/Cargo.toml +++ b/frame/support/test/Cargo.toml @@ -20,7 +20,7 @@ sp-io = { version = "4.0.0-dev", path = "../../../primitives/io", default-featur sp-state-machine = { version = "0.10.0-dev", optional = true, path = "../../../primitives/state-machine" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } -sp-core = { version = "4.0.0", default-features = false, path = "../../../primitives/core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } sp-version = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/version" } trybuild = "1.0.52" diff --git a/frame/support/test/compile_pass/Cargo.toml b/frame/support/test/compile_pass/Cargo.toml index aa53f7ad358d..b72bbc2f01f5 100644 --- a/frame/support/test/compile_pass/Cargo.toml +++ b/frame/support/test/compile_pass/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-core = { version = "4.0.0", default-features = false, path = "../../../../primitives/core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../../primitives/core" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/runtime" } sp-version = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/version" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../../" } diff --git a/frame/system/Cargo.toml b/frame/system/Cargo.toml index fc510d1d9d79..0d771cd1f80d 100644 --- a/frame/system/Cargo.toml +++ b/frame/system/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] serde = { version = "1.0.126", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0-dev", path = "../../primitives/io", default-features = false } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } diff --git a/frame/system/benchmarking/Cargo.toml b/frame/system/benchmarking/Cargo.toml index 9468c8761435..acf13c8f6b2a 100644 --- a/frame/system/benchmarking/Cargo.toml +++ b/frame/system/benchmarking/Cargo.toml @@ -20,7 +20,7 @@ sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../.. frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../../benchmarking" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" } -sp-core = { version = "4.0.0", default-features = false, path = "../../../primitives/core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } [dev-dependencies] sp-io = { version = "4.0.0-dev", path = "../../../primitives/io" } diff --git a/frame/timestamp/Cargo.toml b/frame/timestamp/Cargo.toml index 26554598be10..f8ff0a587b1a 100644 --- a/frame/timestamp/Cargo.toml +++ b/frame/timestamp/Cargo.toml @@ -29,7 +29,7 @@ log = { version = "0.4.14", default-features = false } [dev-dependencies] sp-io ={ version = "4.0.0-dev", path = "../../primitives/io" } -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } [features] default = ["std"] diff --git a/frame/tips/Cargo.toml b/frame/tips/Cargo.toml index 565afcd3fbc6..cb682769ec85 100644 --- a/frame/tips/Cargo.toml +++ b/frame/tips/Cargo.toml @@ -18,7 +18,7 @@ log = { version = "0.4.0", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } serde = { version = "1.0.126", features = ["derive"], optional = true } -sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } diff --git a/frame/transaction-payment/Cargo.toml b/frame/transaction-payment/Cargo.toml index 64e1d5c762ca..642c9bd399b9 100644 --- a/frame/transaction-payment/Cargo.toml +++ b/frame/transaction-payment/Cargo.toml @@ -20,7 +20,7 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] serde = { version = "1.0.126", optional = true } smallvec = "1.7.0" -sp-core = { version = "4.0.0", path = "../../primitives/core", default-features = false } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core", default-features = false } sp-io = { version = "4.0.0-dev", path = "../../primitives/io", default-features = false } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } diff --git a/frame/transaction-payment/asset-tx-payment/Cargo.toml b/frame/transaction-payment/asset-tx-payment/Cargo.toml index cae6b7b914e1..21fae45282d0 100644 --- a/frame/transaction-payment/asset-tx-payment/Cargo.toml +++ b/frame/transaction-payment/asset-tx-payment/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] # Substrate dependencies -sp-core = { version = "4.0.0", default-features = false, path = "../../../primitives/core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/io" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } diff --git a/frame/transaction-payment/rpc/Cargo.toml b/frame/transaction-payment/rpc/Cargo.toml index dd18edf5daf0..36dad610f696 100644 --- a/frame/transaction-payment/rpc/Cargo.toml +++ b/frame/transaction-payment/rpc/Cargo.toml @@ -20,7 +20,7 @@ jsonrpc-derive = "18.0.0" sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-core = { version = "4.0.0", path = "../../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sp-rpc = { version = "4.0.0-dev", path = "../../../primitives/rpc" } sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } pallet-transaction-payment-rpc-runtime-api = { version = "4.0.0-dev", path = "./runtime-api" } diff --git a/frame/transaction-storage/Cargo.toml b/frame/transaction-storage/Cargo.toml index 141aeb496dde..f5ce6f844166 100644 --- a/frame/transaction-storage/Cargo.toml +++ b/frame/transaction-storage/Cargo.toml @@ -29,7 +29,7 @@ frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = " [dev-dependencies] sp-transaction-storage-proof = { version = "4.0.0-dev", default-features = true, path = "../../primitives/transaction-storage-proof" } -sp-core = { version = "4.0.0", path = "../../primitives/core", default-features = false } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core", default-features = false } [features] default = ["std"] diff --git a/frame/treasury/Cargo.toml b/frame/treasury/Cargo.toml index 4cbcb08c3ef6..fed6b98f55eb 100644 --- a/frame/treasury/Cargo.toml +++ b/frame/treasury/Cargo.toml @@ -32,7 +32,7 @@ pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../ [dev-dependencies] sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } [features] default = ["std"] diff --git a/frame/uniques/Cargo.toml b/frame/uniques/Cargo.toml index 7eddc85b67bb..2ce0c1b484ea 100644 --- a/frame/uniques/Cargo.toml +++ b/frame/uniques/Cargo.toml @@ -23,7 +23,7 @@ frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = " [dev-dependencies] sp-std = { version = "4.0.0", path = "../../primitives/std" } -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } diff --git a/frame/utility/Cargo.toml b/frame/utility/Cargo.toml index ac9254bd0854..9dfbd7b410ef 100644 --- a/frame/utility/Cargo.toml +++ b/frame/utility/Cargo.toml @@ -17,7 +17,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } -sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } @@ -25,7 +25,7 @@ sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primiti frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/frame/vesting/Cargo.toml b/frame/vesting/Cargo.toml index 5d66db1c981b..30cdc91d44f3 100644 --- a/frame/vesting/Cargo.toml +++ b/frame/vesting/Cargo.toml @@ -26,7 +26,7 @@ log = { version = "0.4.0", default-features = false } [dev-dependencies] sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/primitives/api/Cargo.toml b/primitives/api/Cargo.toml index d64da8ff84d7..65e39571c7eb 100644 --- a/primitives/api/Cargo.toml +++ b/primitives/api/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } sp-api-proc-macro = { version = "4.0.0-dev", path = "proc-macro" } -sp-core = { version = "4.0.0", default-features = false, path = "../core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../runtime" } sp-version = { version = "4.0.0-dev", default-features = false, path = "../version" } diff --git a/primitives/api/test/Cargo.toml b/primitives/api/test/Cargo.toml index dc2ca67242ac..91675e941c78 100644 --- a/primitives/api/test/Cargo.toml +++ b/primitives/api/test/Cargo.toml @@ -28,7 +28,7 @@ rustversion = "1.0.5" criterion = "0.3.0" futures = "0.3.9" log = "0.4.14" -sp-core = { version = "4.0.0", path = "../../core" } +sp-core = { version = "4.1.0-dev", path = "../../core" } [[bench]] name = "bench" diff --git a/primitives/application-crypto/Cargo.toml b/primitives/application-crypto/Cargo.toml index fd6dd87fa1b2..f3a9f9a93839 100644 --- a/primitives/application-crypto/Cargo.toml +++ b/primitives/application-crypto/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-core = { version = "4.0.0", default-features = false, path = "../core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } serde = { version = "1.0.126", optional = true, features = ["derive"] } diff --git a/primitives/application-crypto/test/Cargo.toml b/primitives/application-crypto/test/Cargo.toml index 6ab3cfed0815..dc51dceeeb4d 100644 --- a/primitives/application-crypto/test/Cargo.toml +++ b/primitives/application-crypto/test/Cargo.toml @@ -13,7 +13,7 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-core = { version = "4.0.0", default-features = false, path = "../../core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../../core" } sp-keystore = { version = "0.10.0-dev", path = "../../keystore", default-features = false } substrate-test-runtime-client = { version = "2.0.0", path = "../../../test-utils/runtime/client" } sp-runtime = { version = "4.0.0-dev", path = "../../runtime" } diff --git a/primitives/beefy/Cargo.toml b/primitives/beefy/Cargo.toml index 4a1f844b9200..4391b1939d10 100644 --- a/primitives/beefy/Cargo.toml +++ b/primitives/beefy/Cargo.toml @@ -13,7 +13,7 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] sp-api = { version = "4.0.0-dev", path = "../api", default-features = false } sp-application-crypto = { version = "4.0.0-dev", path = "../application-crypto", default-features = false } -sp-core = { version = "4.0.0", path = "../core", default-features = false } +sp-core = { version = "4.1.0-dev", path = "../core", default-features = false } sp-runtime = { version = "4.0.0-dev", path = "../runtime", default-features = false } sp-std = { version = "4.0.0", path = "../std", default-features = false } diff --git a/primitives/consensus/babe/Cargo.toml b/primitives/consensus/babe/Cargo.toml index a07dc54e2979..997744dd52bb 100644 --- a/primitives/consensus/babe/Cargo.toml +++ b/primitives/consensus/babe/Cargo.toml @@ -22,7 +22,7 @@ sp-api = { version = "4.0.0-dev", default-features = false, path = "../../api" } sp-consensus = { version = "0.10.0-dev", optional = true, path = "../common" } sp-consensus-slots = { version = "0.10.0-dev", default-features = false, path = "../slots" } sp-consensus-vrf = { version = "0.10.0-dev", path = "../vrf", default-features = false } -sp-core = { version = "4.0.0", default-features = false, path = "../../core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../../core" } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../inherents" } sp-keystore = { version = "0.10.0-dev", default-features = false, path = "../../keystore", optional = true } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../runtime" } diff --git a/primitives/consensus/common/Cargo.toml b/primitives/consensus/common/Cargo.toml index 4b5ef8796afa..2ad4a0895935 100644 --- a/primitives/consensus/common/Cargo.toml +++ b/primitives/consensus/common/Cargo.toml @@ -20,7 +20,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", features = [ ] } futures = { version = "0.3.1", features = ["thread-pool"] } log = "0.4.8" -sp-core = { path = "../../core", version = "4.0.0" } +sp-core = { path = "../../core", version = "4.1.0-dev" } sp-inherents = { version = "4.0.0-dev", path = "../../inherents" } sp-state-machine = { version = "0.10.0-dev", path = "../../state-machine" } futures-timer = "3.0.1" diff --git a/primitives/consensus/pow/Cargo.toml b/primitives/consensus/pow/Cargo.toml index 1612868b3637..d7f2b18e3fdb 100644 --- a/primitives/consensus/pow/Cargo.toml +++ b/primitives/consensus/pow/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] sp-api = { version = "4.0.0-dev", default-features = false, path = "../../api" } sp-std = { version = "4.0.0", default-features = false, path = "../../std" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../runtime" } -sp-core = { version = "4.0.0", default-features = false, path = "../../core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../../core" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } [features] diff --git a/primitives/consensus/vrf/Cargo.toml b/primitives/consensus/vrf/Cargo.toml index 97e426016d9a..4eb545b08a21 100644 --- a/primitives/consensus/vrf/Cargo.toml +++ b/primitives/consensus/vrf/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { version = "2.0.0", package = "parity-scale-codec", default-features = false } schnorrkel = { version = "0.9.1", features = ["preaudit_deprecated", "u64_backend"], default-features = false } sp-std = { version = "4.0.0", path = "../../std", default-features = false } -sp-core = { version = "4.0.0", path = "../../core", default-features = false } +sp-core = { version = "4.1.0-dev", path = "../../core", default-features = false } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../runtime" } [features] diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index 5c805ff1dab8..a078cc09aafc 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-core" -version = "4.0.0" +version = "4.1.0-dev" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" diff --git a/primitives/core/src/crypto.rs b/primitives/core/src/crypto.rs index 4f21d62f5850..dc08d69bf418 100644 --- a/primitives/core/src/crypto.rs +++ b/primitives/core/src/crypto.rs @@ -460,6 +460,7 @@ pub trait Public: fn as_slice(&self) -> &[u8] { self.as_ref() } + /// Return `CryptoTypePublicPair` from public key. fn to_public_crypto_pair(&self) -> CryptoTypePublicPair; } @@ -709,6 +710,104 @@ mod dummy { } } +/// A secret uri (`SURI`) that can be used to generate a key pair. +/// +/// The `SURI` can be parsed from a string. The string is interpreted in the following way: +/// +/// - If `string` is a possibly `0x` prefixed 64-digit hex string, then it will be interpreted +/// directly as a `MiniSecretKey` (aka "seed" in `subkey`). +/// - If `string` is a valid BIP-39 key phrase of 12, 15, 18, 21 or 24 words, then the key will +/// be derived from it. In this case: +/// - the phrase may be followed by one or more items delimited by `/` characters. +/// - the path may be followed by `///`, in which case everything after the `///` is treated +/// as a password. +/// - If `string` begins with a `/` character it is prefixed with the Substrate public `DEV_PHRASE` +/// and interpreted as above. +/// +/// In this case they are interpreted as HDKD junctions; purely numeric items are interpreted as +/// integers, non-numeric items as strings. Junctions prefixed with `/` are interpreted as soft +/// junctions, and with `//` as hard junctions. +/// +/// There is no correspondence mapping between `SURI` strings and the keys they represent. +/// Two different non-identical strings can actually lead to the same secret being derived. +/// Notably, integer junction indices may be legally prefixed with arbitrary number of zeros. +/// Similarly an empty password (ending the `SURI` with `///`) is perfectly valid and will +/// generally be equivalent to no password at all. +/// +/// # Example +/// +/// Parse [`DEV_PHRASE`] secret uri with junction: +/// +/// ``` +/// # use sp_core::crypto::{SecretUri, DeriveJunction, DEV_PHRASE, ExposeSecret}; +/// # use std::str::FromStr; +/// let suri = SecretUri::from_str("//Alice").expect("Parse SURI"); +/// +/// assert_eq!(vec![DeriveJunction::from("Alice").harden()], suri.junctions); +/// assert_eq!(DEV_PHRASE, suri.phrase.expose_secret()); +/// assert!(suri.password.is_none()); +/// ``` +/// +/// Parse [`DEV_PHRASE`] secret ui with junction and password: +/// +/// ``` +/// # use sp_core::crypto::{SecretUri, DeriveJunction, DEV_PHRASE, ExposeSecret}; +/// # use std::str::FromStr; +/// let suri = SecretUri::from_str("//Alice///SECRET_PASSWORD").expect("Parse SURI"); +/// +/// assert_eq!(vec![DeriveJunction::from("Alice").harden()], suri.junctions); +/// assert_eq!(DEV_PHRASE, suri.phrase.expose_secret()); +/// assert_eq!("SECRET_PASSWORD", suri.password.unwrap().expose_secret()); +/// ``` +/// +/// Parse [`DEV_PHRASE`] secret ui with hex phrase and junction: +/// +/// ``` +/// # use sp_core::crypto::{SecretUri, DeriveJunction, DEV_PHRASE, ExposeSecret}; +/// # use std::str::FromStr; +/// let suri = SecretUri::from_str("0xe5be9a5092b81bca64be81d212e7f2f9eba183bb7a90954f7b76361f6edb5c0a//Alice").expect("Parse SURI"); +/// +/// assert_eq!(vec![DeriveJunction::from("Alice").harden()], suri.junctions); +/// assert_eq!("0xe5be9a5092b81bca64be81d212e7f2f9eba183bb7a90954f7b76361f6edb5c0a", suri.phrase.expose_secret()); +/// assert!(suri.password.is_none()); +/// ``` +#[cfg(feature = "std")] +pub struct SecretUri { + /// The phrase to derive the private key. + /// + /// This can either be a 64-bit hex string or a BIP-39 key phrase. + pub phrase: SecretString, + /// Optional password as given as part of the uri. + pub password: Option, + /// The junctions as part of the uri. + pub junctions: Vec, +} + +#[cfg(feature = "std")] +impl sp_std::str::FromStr for SecretUri { + type Err = SecretStringError; + + fn from_str(s: &str) -> Result { + let cap = SECRET_PHRASE_REGEX.captures(s).ok_or(SecretStringError::InvalidFormat)?; + + let junctions = JUNCTION_REGEX + .captures_iter(&cap["path"]) + .map(|f| DeriveJunction::from(&f[1])) + .collect::>(); + + let phrase = cap.name("phrase").map(|r| r.as_str()).unwrap_or(DEV_PHRASE); + let password = cap.name("password"); + + Ok(Self { + phrase: SecretString::from_str(phrase).expect("Returns infallible error; qed"), + password: password.map(|v| { + SecretString::from_str(v.as_str()).expect("Returns infallible error; qed") + }), + junctions, + }) + } +} + /// Trait suitable for typical cryptographic PKI key pair type. /// /// For now it just specifies how to create a key from a phrase and derivation path. @@ -821,14 +920,12 @@ pub trait Pair: CryptoType + Sized + Clone + Send + Sync + 'static { s: &str, password_override: Option<&str>, ) -> Result<(Self, Option), SecretStringError> { - let cap = SECRET_PHRASE_REGEX.captures(s).ok_or(SecretStringError::InvalidFormat)?; - - let path = JUNCTION_REGEX.captures_iter(&cap["path"]).map(|f| DeriveJunction::from(&f[1])); - - let phrase = cap.name("phrase").map(|r| r.as_str()).unwrap_or(DEV_PHRASE); - let password = password_override.or_else(|| cap.name("password").map(|m| m.as_str())); + use sp_std::str::FromStr; + let SecretUri { junctions, phrase, password } = SecretUri::from_str(s)?; + let password = + password_override.or_else(|| password.as_ref().map(|p| p.expose_secret().as_str())); - let (root, seed) = if let Some(stripped) = phrase.strip_prefix("0x") { + let (root, seed) = if let Some(stripped) = phrase.expose_secret().strip_prefix("0x") { hex::decode(stripped) .ok() .and_then(|seed_vec| { @@ -842,9 +939,11 @@ pub trait Pair: CryptoType + Sized + Clone + Send + Sync + 'static { }) .ok_or(SecretStringError::InvalidSeed)? } else { - Self::from_phrase(phrase, password).map_err(|_| SecretStringError::InvalidPhrase)? + Self::from_phrase(phrase.expose_secret().as_str(), password) + .map_err(|_| SecretStringError::InvalidPhrase)? }; - root.derive(path, Some(seed)).map_err(|_| SecretStringError::InvalidPath) + root.derive(junctions.into_iter(), Some(seed)) + .map_err(|_| SecretStringError::InvalidPath) } /// Interprets the string `s` in order to generate a key pair. diff --git a/primitives/finality-grandpa/Cargo.toml b/primitives/finality-grandpa/Cargo.toml index be4f3c6d1e3d..fed861553bf0 100644 --- a/primitives/finality-grandpa/Cargo.toml +++ b/primitives/finality-grandpa/Cargo.toml @@ -22,7 +22,7 @@ log = { version = "0.4.8", optional = true } serde = { version = "1.0.126", optional = true, features = ["derive"] } sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } sp-application-crypto = { version = "4.0.0-dev", default-features = false, path = "../application-crypto" } -sp-core = { version = "4.0.0", default-features = false, path = "../core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } sp-keystore = { version = "0.10.0-dev", default-features = false, path = "../keystore", optional = true } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } diff --git a/primitives/inherents/Cargo.toml b/primitives/inherents/Cargo.toml index c531ad4e5764..82c4f21b5c07 100644 --- a/primitives/inherents/Cargo.toml +++ b/primitives/inherents/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-std = { version = "4.0.0", default-features = false, path = "../std" } -sp-core = { version = "4.0.0", default-features = false, path = "../core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } sp-runtime = { version = "4.0.0-dev", path = "../runtime", optional = true } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } thiserror = { version = "1.0.30", optional = true } diff --git a/primitives/io/Cargo.toml b/primitives/io/Cargo.toml index 520dc12a5260..4485a8a7f45a 100644 --- a/primitives/io/Cargo.toml +++ b/primitives/io/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } hash-db = { version = "0.15.2", default-features = false } -sp-core = { version = "4.0.0", default-features = false, path = "../core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } sp-keystore = { version = "0.10.0-dev", default-features = false, optional = true, path = "../keystore" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } libsecp256k1 = { version = "0.7", optional = true } diff --git a/primitives/keyring/Cargo.toml b/primitives/keyring/Cargo.toml index 66c1240a8a56..be7d138979a1 100644 --- a/primitives/keyring/Cargo.toml +++ b/primitives/keyring/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-core = { version = "4.0.0", path = "../core" } +sp-core = { version = "4.1.0-dev", path = "../core" } sp-runtime = { version = "4.0.0-dev", path = "../runtime" } lazy_static = "1.4.0" strum = { version = "0.22.0", features = ["derive"] } diff --git a/primitives/keystore/Cargo.toml b/primitives/keystore/Cargo.toml index b0061ac111e2..7994c67b4c51 100644 --- a/primitives/keystore/Cargo.toml +++ b/primitives/keystore/Cargo.toml @@ -21,7 +21,7 @@ schnorrkel = { version = "0.9.1", features = ["preaudit_deprecated", "u64_backen merlin = { version = "2.0", default-features = false } parking_lot = { version = "0.11.1", default-features = false } serde = { version = "1.0", optional = true} -sp-core = { version = "4.0.0", path = "../core" } +sp-core = { version = "4.1.0-dev", path = "../core" } sp-externalities = { version = "0.10.0", path = "../externalities", default-features = false } [dev-dependencies] diff --git a/primitives/npos-elections/Cargo.toml b/primitives/npos-elections/Cargo.toml index 16aca8dc71d9..a418cda2feef 100644 --- a/primitives/npos-elections/Cargo.toml +++ b/primitives/npos-elections/Cargo.toml @@ -19,7 +19,7 @@ serde = { version = "1.0.126", optional = true, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-npos-elections-solution-type = { version = "4.0.0-dev", path = "./solution-type" } sp-arithmetic = { version = "4.0.0-dev", default-features = false, path = "../arithmetic" } -sp-core = { version = "4.0.0", default-features = false, path = "../core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } sp-runtime = { version = "4.0.0-dev", path = "../runtime", default-features = false } [dev-dependencies] diff --git a/primitives/offchain/Cargo.toml b/primitives/offchain/Cargo.toml index f079ccb7913f..55de9177e45d 100644 --- a/primitives/offchain/Cargo.toml +++ b/primitives/offchain/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-core = { version = "4.0.0", default-features = false, path = "../core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../runtime" } diff --git a/primitives/rpc/Cargo.toml b/primitives/rpc/Cargo.toml index 59cbf53fee2a..e16280f95d35 100644 --- a/primitives/rpc/Cargo.toml +++ b/primitives/rpc/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.126", features = ["derive"] } -sp-core = { version = "4.0.0", path = "../core" } +sp-core = { version = "4.1.0-dev", path = "../core" } rustc-hash = "1.1.0" [dev-dependencies] diff --git a/primitives/runtime-interface/Cargo.toml b/primitives/runtime-interface/Cargo.toml index 64781481fa12..6b120ab50c50 100644 --- a/primitives/runtime-interface/Cargo.toml +++ b/primitives/runtime-interface/Cargo.toml @@ -28,7 +28,7 @@ impl-trait-for-tuples = "0.2.1" [dev-dependencies] sp-runtime-interface-test-wasm = { version = "2.0.0", path = "test-wasm" } sp-state-machine = { version = "0.10.0-dev", path = "../state-machine" } -sp-core = { version = "4.0.0", path = "../core" } +sp-core = { version = "4.1.0-dev", path = "../core" } sp-io = { version = "4.0.0-dev", path = "../io" } rustversion = "1.0.5" trybuild = "1.0.52" diff --git a/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml b/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml index 68ed8a73282a..02fb75d108fd 100644 --- a/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml +++ b/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] sp-runtime-interface = { version = "4.0.0", default-features = false, path = "../" } sp-std = { version = "4.0.0", default-features = false, path = "../../std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../io" } -sp-core = { version = "4.0.0", default-features = false, path = "../../core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../../core" } [build-dependencies] substrate-wasm-builder = { version = "5.0.0-dev", path = "../../../utils/wasm-builder" } diff --git a/primitives/runtime-interface/test-wasm/Cargo.toml b/primitives/runtime-interface/test-wasm/Cargo.toml index ab227ddeda27..24fdb8842963 100644 --- a/primitives/runtime-interface/test-wasm/Cargo.toml +++ b/primitives/runtime-interface/test-wasm/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] sp-runtime-interface = { version = "4.0.0", default-features = false, path = "../" } sp-std = { version = "4.0.0", default-features = false, path = "../../std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../io" } -sp-core = { version = "4.0.0", default-features = false, path = "../../core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../../core" } [build-dependencies] substrate-wasm-builder = { version = "5.0.0-dev", path = "../../../utils/wasm-builder" } diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 76c1d94a3b6d..1d7c79ba68c9 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -18,7 +18,7 @@ targets = ["x86_64-unknown-linux-gnu"] serde = { version = "1.0.126", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-core = { version = "4.0.0", default-features = false, path = "../core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } sp-application-crypto = { version = "4.0.0-dev", default-features = false, path = "../application-crypto" } sp-arithmetic = { version = "4.0.0-dev", default-features = false, path = "../arithmetic" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } diff --git a/primitives/sandbox/Cargo.toml b/primitives/sandbox/Cargo.toml index a51873dc1e99..a94ba0f375f8 100644 --- a/primitives/sandbox/Cargo.toml +++ b/primitives/sandbox/Cargo.toml @@ -20,7 +20,7 @@ wasmi = "0.9.0" [dependencies] wasmi = { version = "0.9.0", optional = true } -sp-core = { version = "4.0.0", default-features = false, path = "../core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../io" } sp-wasm-interface = { version = "4.0.0", default-features = false, path = "../wasm-interface" } diff --git a/primitives/session/Cargo.toml b/primitives/session/Cargo.toml index eda98b2ab6a8..d402f36859ac 100644 --- a/primitives/session/Cargo.toml +++ b/primitives/session/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } -sp-core = { version = "4.0.0", default-features = false, path = "../core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../staking" } sp-runtime = { version = "4.0.0-dev", optional = true, path = "../runtime" } diff --git a/primitives/state-machine/Cargo.toml b/primitives/state-machine/Cargo.toml index f5047c3c7c46..b6b3c90f5a7f 100644 --- a/primitives/state-machine/Cargo.toml +++ b/primitives/state-machine/Cargo.toml @@ -21,7 +21,7 @@ hash-db = { version = "0.15.2", default-features = false } trie-db = { version = "0.22.6", default-features = false } trie-root = { version = "0.16.0", default-features = false } sp-trie = { version = "4.0.0-dev", path = "../trie", default-features = false } -sp-core = { version = "4.0.0", path = "../core", default-features = false } +sp-core = { version = "4.1.0-dev", path = "../core", default-features = false } sp-panic-handler = { version = "4.0.0-dev", path = "../panic-handler", optional = true } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } num-traits = { version = "0.2.8", default-features = false } diff --git a/primitives/tasks/Cargo.toml b/primitives/tasks/Cargo.toml index 9a80cc50cf2f..c154d1c92dca 100644 --- a/primitives/tasks/Cargo.toml +++ b/primitives/tasks/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] log = { version = "0.4.8", optional = true } -sp-core = { version = "4.0.0", default-features = false, path = "../core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } sp-externalities = { version = "0.10.0", optional = true, path = "../externalities" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../io" } sp-runtime-interface = { version = "4.0.0", default-features = false, path = "../runtime-interface" } diff --git a/primitives/test-primitives/Cargo.toml b/primitives/test-primitives/Cargo.toml index ea1e61c8da11..18a0b9501e18 100644 --- a/primitives/test-primitives/Cargo.toml +++ b/primitives/test-primitives/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-application-crypto = { version = "4.0.0-dev", default-features = false, path = "../application-crypto" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } -sp-core = { version = "4.0.0", default-features = false, path = "../core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } serde = { version = "1.0.126", optional = true, features = ["derive"] } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../runtime" } parity-util-mem = { version = "0.10.2", default-features = false, features = ["primitive-types"] } diff --git a/primitives/transaction-storage-proof/Cargo.toml b/primitives/transaction-storage-proof/Cargo.toml index 05da54b24f78..f2ea55cc18c5 100644 --- a/primitives/transaction-storage-proof/Cargo.toml +++ b/primitives/transaction-storage-proof/Cargo.toml @@ -17,7 +17,7 @@ sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../inh sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-trie = { version = "4.0.0-dev", optional = true, path = "../trie" } -sp-core = { version = "4.0.0", path = "../core", optional = true } +sp-core = { version = "4.1.0-dev", path = "../core", optional = true } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } log = { version = "0.4.8", optional = true } diff --git a/primitives/trie/Cargo.toml b/primitives/trie/Cargo.toml index af81164ed799..983d58c9bb8d 100644 --- a/primitives/trie/Cargo.toml +++ b/primitives/trie/Cargo.toml @@ -25,7 +25,7 @@ hash-db = { version = "0.15.2", default-features = false } trie-db = { version = "0.22.6", default-features = false } trie-root = { version = "0.16.0", default-features = false } memory-db = { version = "0.27.0", default-features = false } -sp-core = { version = "4.0.0", default-features = false, path = "../core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } [dev-dependencies] trie-bench = "0.28.0" diff --git a/test-utils/client/Cargo.toml b/test-utils/client/Cargo.toml index 3917f3fefcf9..9b77cde505af 100644 --- a/test-utils/client/Cargo.toml +++ b/test-utils/client/Cargo.toml @@ -29,7 +29,7 @@ sc-service = { version = "0.10.0-dev", default-features = false, features = [ ], path = "../../client/service" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } -sp-core = { version = "4.0.0", path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-keystore = { version = "0.10.0-dev", path = "../../primitives/keystore" } sp-keyring = { version = "4.0.0-dev", path = "../../primitives/keyring" } sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } diff --git a/test-utils/runtime/Cargo.toml b/test-utils/runtime/Cargo.toml index 35c14a23f2a2..3be0e40b0b6b 100644 --- a/test-utils/runtime/Cargo.toml +++ b/test-utils/runtime/Cargo.toml @@ -23,7 +23,7 @@ sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../ sp-keyring = { version = "4.0.0-dev", optional = true, path = "../../primitives/keyring" } memory-db = { version = "0.27.0", default-features = false } sp-offchain = { version = "4.0.0-dev", default-features = false, path = "../../primitives/offchain" } -sp-core = { version = "4.0.0", default-features = false, path = "../../primitives/core" } +sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-runtime-interface = { version = "4.0.0", default-features = false, path = "../../primitives/runtime-interface" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } diff --git a/test-utils/runtime/client/Cargo.toml b/test-utils/runtime/client/Cargo.toml index 6dd22e4954c2..b66fdc3422ae 100644 --- a/test-utils/runtime/client/Cargo.toml +++ b/test-utils/runtime/client/Cargo.toml @@ -16,7 +16,7 @@ sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/c sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/common" } sc-block-builder = { version = "0.10.0-dev", path = "../../../client/block-builder" } substrate-test-client = { version = "2.0.0", path = "../../client" } -sp-core = { version = "4.0.0", path = "../../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } substrate-test-runtime = { version = "2.0.0", path = "../../runtime" } sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } diff --git a/utils/frame/benchmarking-cli/Cargo.toml b/utils/frame/benchmarking-cli/Cargo.toml index 2943877ce4a0..c8d762ec73cd 100644 --- a/utils/frame/benchmarking-cli/Cargo.toml +++ b/utils/frame/benchmarking-cli/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] frame-benchmarking = { version = "4.0.0-dev", path = "../../../frame/benchmarking" } frame-support = { version = "4.0.0-dev", path = "../../../frame/support" } -sp-core = { version = "4.0.0", path = "../../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sc-service = { version = "0.10.0-dev", default-features = false, path = "../../../client/service" } sc-cli = { version = "0.10.0-dev", path = "../../../client/cli" } sc-client-db = { version = "0.10.0-dev", path = "../../../client/db" } diff --git a/utils/frame/frame-utilities-cli/Cargo.toml b/utils/frame/frame-utilities-cli/Cargo.toml index 6c3cb0428284..feb02f1eb721 100644 --- a/utils/frame/frame-utilities-cli/Cargo.toml +++ b/utils/frame/frame-utilities-cli/Cargo.toml @@ -11,7 +11,7 @@ documentation = "https://docs.rs/substrate-frame-cli" readme = "README.md" [dependencies] -sp-core = { version = "4.0.0", path = "../../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sc-cli = { version = "0.10.0-dev", path = "../../../client/cli" } sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } structopt = "0.3.25" diff --git a/utils/frame/remote-externalities/Cargo.toml b/utils/frame/remote-externalities/Cargo.toml index ab91f2649017..0cf4980a104c 100644 --- a/utils/frame/remote-externalities/Cargo.toml +++ b/utils/frame/remote-externalities/Cargo.toml @@ -23,7 +23,7 @@ serde_json = "1.0" serde = "1.0.126" sp-io = { version = "4.0.0-dev", path = "../../../primitives/io" } -sp-core = { version = "4.0.0", path = "../../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } sp-version = { version = "4.0.0-dev", path = "../../../primitives/version" } diff --git a/utils/frame/rpc/system/Cargo.toml b/utils/frame/rpc/system/Cargo.toml index 5fc3812b84da..f71f3d6e93e1 100644 --- a/utils/frame/rpc/system/Cargo.toml +++ b/utils/frame/rpc/system/Cargo.toml @@ -23,7 +23,7 @@ log = "0.4.8" sp-runtime = { version = "4.0.0-dev", path = "../../../../primitives/runtime" } sp-api = { version = "4.0.0-dev", path = "../../../../primitives/api" } frame-system-rpc-runtime-api = { version = "4.0.0-dev", path = "../../../../frame/system/rpc/runtime-api" } -sp-core = { version = "4.0.0", path = "../../../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../../../primitives/core" } sp-blockchain = { version = "4.0.0-dev", path = "../../../../primitives/blockchain" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../../../../client/transaction-pool/api" } sp-block-builder = { version = "4.0.0-dev", path = "../../../../primitives/block-builder" } diff --git a/utils/frame/try-runtime/cli/Cargo.toml b/utils/frame/try-runtime/cli/Cargo.toml index 71db6100ca17..d6b75d31fac8 100644 --- a/utils/frame/try-runtime/cli/Cargo.toml +++ b/utils/frame/try-runtime/cli/Cargo.toml @@ -24,7 +24,7 @@ sc-executor = { version = "0.10.0-dev", path = "../../../../client/executor" } sc-chain-spec = { version = "4.0.0-dev", path = "../../../../client/chain-spec" } sp-state-machine = { version = "0.10.0-dev", path = "../../../../primitives/state-machine" } sp-runtime = { version = "4.0.0-dev", path = "../../../../primitives/runtime" } -sp-core = { version = "4.0.0", path = "../../../../primitives/core" } +sp-core = { version = "4.1.0-dev", path = "../../../../primitives/core" } sp-io = { version = "4.0.0-dev", path = "../../../../primitives/io" } sp-keystore = { version = "0.10.0-dev", path = "../../../../primitives/keystore" } sp-externalities = { version = "0.10.0", path = "../../../../primitives/externalities" } From 4d24ae04ec8c60fe7eca069df09d1ac0a636a80c Mon Sep 17 00:00:00 2001 From: Gavin Wood Date: Sat, 11 Dec 2021 15:55:23 +0100 Subject: [PATCH 283/695] Preimage registrar and Scheduler integration (#10356) * initial idea * more * fix compile * add clear and request logic * improve some docs * Add and implement trait * continuing to improve * refcount type * infallible system preimage upload * fmt * fix requests * Make it simple * Make it simple * Formatting * Initial draft * request when scheduled * Docs * Scheduler good * Scheduler good * Scheduler tests working * Add new files * Missing stuff * Repotting, add weights. * Add some tests to preimage pallet * More tests * Fix benchmarks * preimage benchmarks * All preimage benchmarks * Tidy cargo * Update weights.rs * Allow hash provision in benchmarks * Initial work on new benchmarks for Scheduler * Tests working, refactor looks good * Tests for new Scheduler functionality * Use real weight, make tests work with runtimes without Preimage * Rename * Update benchmarks * Formatting * Formatting * Fix weird formatting * Update frame/preimage/src/lib.rs * Fix try-runtime build * Fixes * Fixes * Update frame/support/src/traits/tokens/currency.rs Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> * Update frame/support/src/traits/tokens/currency/reservable.rs Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> * Update frame/support/src/traits/tokens/imbalance.rs Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> * Update frame/preimage/src/mock.rs Co-authored-by: Guillaume Thiolliere * Update frame/scheduler/src/lib.rs Co-authored-by: Guillaume Thiolliere * Update frame/preimage/src/lib.rs * Fixes * Fixes * Formatting * Fixes * Fixes * cargo run --quiet --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_scheduler --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/scheduler/src/weights.rs --template=./.maintain/frame-weight-template.hbs * cargo run --quiet --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_preimage --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/preimage/src/weights.rs --template=./.maintain/frame-weight-template.hbs Co-authored-by: Shawn Tabrizi Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Co-authored-by: Guillaume Thiolliere Co-authored-by: Parity Bot --- Cargo.lock | 18 + Cargo.toml | 1 + bin/node/runtime/Cargo.toml | 4 + bin/node/runtime/src/lib.rs | 32 +- frame/democracy/src/tests.rs | 2 + frame/preimage/Cargo.toml | 46 + frame/preimage/src/benchmarking.rs | 161 ++ frame/preimage/src/lib.rs | 347 +++++ frame/preimage/src/mock.rs | 131 ++ frame/preimage/src/tests.rs | 233 +++ frame/preimage/src/weights.rs | 238 +++ frame/scheduler/Cargo.toml | 37 +- frame/scheduler/src/benchmarking.rs | 214 ++- frame/scheduler/src/lib.rs | 1383 ++++------------- frame/scheduler/src/mock.rs | 203 +++ frame/scheduler/src/tests.rs | 901 +++++++++++ frame/scheduler/src/weights.rs | 275 +++- frame/support/src/traits.rs | 4 +- frame/support/src/traits/misc.rs | 65 + frame/support/src/traits/schedule.rs | 401 ++++- frame/support/src/traits/tokens/currency.rs | 88 ++ .../src/traits/tokens/currency/reservable.rs | 27 + frame/support/src/traits/tokens/imbalance.rs | 52 + frame/system/src/lib.rs | 18 +- 24 files changed, 3593 insertions(+), 1288 deletions(-) create mode 100644 frame/preimage/Cargo.toml create mode 100644 frame/preimage/src/benchmarking.rs create mode 100644 frame/preimage/src/lib.rs create mode 100644 frame/preimage/src/mock.rs create mode 100644 frame/preimage/src/tests.rs create mode 100644 frame/preimage/src/weights.rs create mode 100644 frame/scheduler/src/mock.rs create mode 100644 frame/scheduler/src/tests.rs diff --git a/Cargo.lock b/Cargo.lock index 612cbdc8b0de..ab8132c6b7cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4721,6 +4721,7 @@ dependencies = [ "pallet-multisig", "pallet-offences", "pallet-offences-benchmarking", + "pallet-preimage", "pallet-proxy", "pallet-randomness-collective-flip", "pallet-recovery", @@ -5912,6 +5913,22 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-preimage" +version = "4.0.0-dev" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "pallet-balances", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-proxy" version = "4.0.0-dev" @@ -5967,6 +5984,7 @@ dependencies = [ "frame-support", "frame-system", "log 0.4.14", + "pallet-preimage", "parity-scale-codec", "scale-info", "sp-core", diff --git a/Cargo.toml b/Cargo.toml index 7bb08345c0fe..a26652e39774 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -102,6 +102,7 @@ members = [ "frame/nicks", "frame/node-authorization", "frame/offences", + "frame/preimage", "frame/proxy", "frame/randomness-collective-flip", "frame/recovery", diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 32dcc003e879..83a66f5a47b6 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -78,6 +78,7 @@ pallet-mmr = { version = "4.0.0-dev", default-features = false, path = "../../.. pallet-multisig = { version = "4.0.0-dev", default-features = false, path = "../../../frame/multisig" } pallet-offences = { version = "4.0.0-dev", default-features = false, path = "../../../frame/offences" } pallet-offences-benchmarking = { version = "4.0.0-dev", path = "../../../frame/offences/benchmarking", default-features = false, optional = true } +pallet-preimage = { version = "4.0.0-dev", default-features = false, path = "../../../frame/preimage" } pallet-proxy = { version = "4.0.0-dev", default-features = false, path = "../../../frame/proxy" } pallet-randomness-collective-flip = { version = "4.0.0-dev", default-features = false, path = "../../../frame/randomness-collective-flip" } pallet-recovery = { version = "4.0.0-dev", default-features = false, path = "../../../frame/recovery" } @@ -141,6 +142,7 @@ std = [ "node-primitives/std", "sp-offchain/std", "pallet-offences/std", + "pallet-preimage/std", "pallet-proxy/std", "sp-core/std", "pallet-randomness-collective-flip/std", @@ -202,6 +204,7 @@ runtime-benchmarks = [ "pallet-membership/runtime-benchmarks", "pallet-mmr/runtime-benchmarks", "pallet-multisig/runtime-benchmarks", + "pallet-preimage/runtime-benchmarks", "pallet-proxy/runtime-benchmarks", "pallet-scheduler/runtime-benchmarks", "pallet-society/runtime-benchmarks", @@ -243,6 +246,7 @@ try-runtime = [ "pallet-identity/try-runtime", "pallet-scheduler/try-runtime", "pallet-offences/try-runtime", + "pallet-preimage/try-runtime", "pallet-proxy/try-runtime", "pallet-randomness-collective-flip/try-runtime", "pallet-session/try-runtime", diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 3134f25cfb26..bd4bb450c749 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -337,6 +337,8 @@ parameter_types! { pub MaximumSchedulerWeight: Weight = Perbill::from_percent(80) * RuntimeBlockWeights::get().max_block; pub const MaxScheduledPerBlock: u32 = 50; + // Retry a scheduled item every 10 blocks (1 minute) until the preimage exists. + pub const NoPreimagePostponement: Option = Some(10); } impl pallet_scheduler::Config for Runtime { @@ -349,6 +351,25 @@ impl pallet_scheduler::Config for Runtime { type MaxScheduledPerBlock = MaxScheduledPerBlock; type WeightInfo = pallet_scheduler::weights::SubstrateWeight; type OriginPrivilegeCmp = EqualPrivilegeOnly; + type PreimageProvider = Preimage; + type NoPreimagePostponement = NoPreimagePostponement; +} + +parameter_types! { + pub const PreimageMaxSize: u32 = 4096 * 1024; + pub const PreimageBaseDeposit: Balance = 1 * DOLLARS; + // One cent: $10,000 / MB + pub const PreimageByteDeposit: Balance = 1 * CENTS; +} + +impl pallet_preimage::Config for Runtime { + type WeightInfo = pallet_preimage::weights::SubstrateWeight; + type Event = Event; + type Currency = Balances; + type ManagerOrigin = EnsureRoot; + type MaxSize = PreimageMaxSize; + type BaseDeposit = PreimageBaseDeposit; + type ByteDeposit = PreimageByteDeposit; } parameter_types! { @@ -688,8 +709,6 @@ parameter_types! { pub const MinimumDeposit: Balance = 100 * DOLLARS; pub const EnactmentPeriod: BlockNumber = 30 * 24 * 60 * MINUTES; pub const CooloffPeriod: BlockNumber = 28 * 24 * 60 * MINUTES; - // One cent: $10,000 / MB - pub const PreimageByteDeposit: Balance = 1 * CENTS; pub const MaxVotes: u32 = 100; pub const MaxProposals: u32 = 100; } @@ -1307,6 +1326,7 @@ construct_runtime!( Recovery: pallet_recovery, Vesting: pallet_vesting, Scheduler: pallet_scheduler, + Preimage: pallet_preimage, Proxy: pallet_proxy, Multisig: pallet_multisig, Bounties: pallet_bounties, @@ -1686,6 +1706,7 @@ impl_runtime_apis! { list_benchmark!(list, extra, pallet_mmr, Mmr); list_benchmark!(list, extra, pallet_multisig, Multisig); list_benchmark!(list, extra, pallet_offences, OffencesBench::); + list_benchmark!(list, extra, pallet_preimage, Preimage); list_benchmark!(list, extra, pallet_proxy, Proxy); list_benchmark!(list, extra, pallet_scheduler, Scheduler); list_benchmark!(list, extra, pallet_session, SessionBench::); @@ -1764,6 +1785,7 @@ impl_runtime_apis! { add_benchmark!(params, batches, pallet_mmr, Mmr); add_benchmark!(params, batches, pallet_multisig, Multisig); add_benchmark!(params, batches, pallet_offences, OffencesBench::); + add_benchmark!(params, batches, pallet_preimage, Preimage); add_benchmark!(params, batches, pallet_proxy, Proxy); add_benchmark!(params, batches, pallet_scheduler, Scheduler); add_benchmark!(params, batches, pallet_session, SessionBench::); @@ -1811,11 +1833,13 @@ mod tests { #[test] fn call_size() { + let size = core::mem::size_of::(); assert!( - core::mem::size_of::() <= 200, - "size of Call is more than 200 bytes: some calls have too big arguments, use Box to reduce the + size <= 200, + "size of Call {} is more than 200 bytes: some calls have too big arguments, use Box to reduce the size of Call. If the limit is too strong, maybe consider increase the limit to 300.", + size, ); } } diff --git a/frame/democracy/src/tests.rs b/frame/democracy/src/tests.rs index 3c223172987e..839478a5b8d9 100644 --- a/frame/democracy/src/tests.rs +++ b/frame/democracy/src/tests.rs @@ -120,6 +120,8 @@ impl pallet_scheduler::Config for Test { type MaxScheduledPerBlock = (); type WeightInfo = (); type OriginPrivilegeCmp = EqualPrivilegeOnly; + type PreimageProvider = (); + type NoPreimagePostponement = (); } parameter_types! { pub const ExistentialDeposit: u64 = 1; diff --git a/frame/preimage/Cargo.toml b/frame/preimage/Cargo.toml new file mode 100644 index 000000000000..b60c3fa85487 --- /dev/null +++ b/frame/preimage/Cargo.toml @@ -0,0 +1,46 @@ +[package] +name = "pallet-preimage" +version = "4.0.0-dev" +authors = ["Parity Technologies "] +edition = "2021" +license = "Apache-2.0" +homepage = "https://substrate.io" +repository = "https://github.com/paritytech/substrate/" +description = "FRAME pallet for storing preimages of hashes" +readme = "README.md" + +[dependencies] +codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } + +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } +sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } +sp-core = { version = "4.1.0-dev", default-features = false, optional = true, path = "../../primitives/core" } +sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } +frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } +frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } + +[dev-dependencies] +sp-core = { version = "4.1.0-dev", path = "../../primitives/core", default-features = false } +pallet-balances = { version = "4.0.0-dev", path = "../balances" } + +[features] +default = ["std"] +runtime-benchmarks = [ + "frame-benchmarking", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", +] +std = [ + "codec/std", + "scale-info/std", + "sp-std/std", + "sp-io/std", + "sp-core/std", + "sp-runtime/std", + "frame-system/std", + "frame-support/std", + "frame-benchmarking/std", +] +try-runtime = ["frame-support/try-runtime"] diff --git a/frame/preimage/src/benchmarking.rs b/frame/preimage/src/benchmarking.rs new file mode 100644 index 000000000000..c18c27555025 --- /dev/null +++ b/frame/preimage/src/benchmarking.rs @@ -0,0 +1,161 @@ +// This file is part of Substrate. + +// Copyright (C) 2020-2021 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. + +//! Preimage pallet benchmarking. + +use super::*; +use frame_benchmarking::{account, benchmarks, whitelist_account}; +use frame_support::assert_ok; +use frame_system::RawOrigin; +use sp_runtime::traits::Bounded; +use sp_std::{prelude::*, vec}; + +use crate::Pallet as Preimage; + +const SEED: u32 = 0; + +fn funded_account(name: &'static str, index: u32) -> T::AccountId { + let caller: T::AccountId = account(name, index, SEED); + T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); + caller +} + +fn preimage_and_hash() -> (Vec, T::Hash) { + sized_preimage_and_hash::(T::MaxSize::get()) +} + +fn sized_preimage_and_hash(size: u32) -> (Vec, T::Hash) { + let mut preimage = vec![]; + preimage.resize(size as usize, 0); + let hash = ::Hashing::hash(&preimage[..]); + (preimage, hash) +} + +benchmarks! { + // Expensive note - will reserve. + note_preimage { + let s in 0 .. T::MaxSize::get(); + let caller = funded_account::("caller", 0); + whitelist_account!(caller); + let (preimage, hash) = sized_preimage_and_hash::(s); + }: _(RawOrigin::Signed(caller), preimage) + verify { + assert!(Preimage::::have_preimage(&hash)); + } + // Cheap note - will not reserve since it was requested. + note_requested_preimage { + let s in 0 .. T::MaxSize::get(); + let caller = funded_account::("caller", 0); + whitelist_account!(caller); + let (preimage, hash) = sized_preimage_and_hash::(s); + assert_ok!(Preimage::::request_preimage(T::ManagerOrigin::successful_origin(), hash.clone())); + }: note_preimage(RawOrigin::Signed(caller), preimage) + verify { + assert!(Preimage::::have_preimage(&hash)); + } + // Cheap note - will not reserve since it's the manager. + note_no_deposit_preimage { + let s in 0 .. T::MaxSize::get(); + let (preimage, hash) = sized_preimage_and_hash::(s); + assert_ok!(Preimage::::request_preimage(T::ManagerOrigin::successful_origin(), hash.clone())); + }: note_preimage(T::ManagerOrigin::successful_origin(), preimage) + verify { + assert!(Preimage::::have_preimage(&hash)); + } + + // Expensive unnote - will unreserve. + unnote_preimage { + let caller = funded_account::("caller", 0); + whitelist_account!(caller); + let (preimage, hash) = preimage_and_hash::(); + assert_ok!(Preimage::::note_preimage(RawOrigin::Signed(caller.clone()).into(), preimage)); + }: _(RawOrigin::Signed(caller), hash.clone()) + verify { + assert!(!Preimage::::have_preimage(&hash)); + } + // Cheap unnote - will not unreserve since there's no deposit held. + unnote_no_deposit_preimage { + let (preimage, hash) = preimage_and_hash::(); + assert_ok!(Preimage::::note_preimage(T::ManagerOrigin::successful_origin(), preimage)); + }: unnote_preimage(T::ManagerOrigin::successful_origin(), hash.clone()) + verify { + assert!(!Preimage::::have_preimage(&hash)); + } + + // Expensive request - will unreserve the noter's deposit. + request_preimage { + let (preimage, hash) = preimage_and_hash::(); + let noter = funded_account::("noter", 0); + whitelist_account!(noter); + assert_ok!(Preimage::::note_preimage(RawOrigin::Signed(noter).into(), preimage)); + }: _(T::ManagerOrigin::successful_origin(), hash) + verify { + assert_eq!(StatusFor::::get(&hash), Some(RequestStatus::Requested(1))); + } + // Cheap request - would unreserve the deposit but none was held. + request_no_deposit_preimage { + let (preimage, hash) = preimage_and_hash::(); + assert_ok!(Preimage::::note_preimage(T::ManagerOrigin::successful_origin(), preimage)); + }: request_preimage(T::ManagerOrigin::successful_origin(), hash) + verify { + assert_eq!(StatusFor::::get(&hash), Some(RequestStatus::Requested(1))); + } + // Cheap request - the preimage is not yet noted, so deposit to unreserve. + request_unnoted_preimage { + let (_, hash) = preimage_and_hash::(); + }: request_preimage(T::ManagerOrigin::successful_origin(), hash) + verify { + assert_eq!(StatusFor::::get(&hash), Some(RequestStatus::Requested(1))); + } + // Cheap request - the preimage is already requested, so just a counter bump. + request_requested_preimage { + let (_, hash) = preimage_and_hash::(); + assert_ok!(Preimage::::request_preimage(T::ManagerOrigin::successful_origin(), hash.clone())); + }: request_preimage(T::ManagerOrigin::successful_origin(), hash) + verify { + assert_eq!(StatusFor::::get(&hash), Some(RequestStatus::Requested(2))); + } + + // Expensive unrequest - last reference and it's noted, so will destroy the preimage. + unrequest_preimage { + let (preimage, hash) = preimage_and_hash::(); + assert_ok!(Preimage::::request_preimage(T::ManagerOrigin::successful_origin(), hash.clone())); + assert_ok!(Preimage::::note_preimage(T::ManagerOrigin::successful_origin(), preimage)); + }: _(T::ManagerOrigin::successful_origin(), hash.clone()) + verify { + assert_eq!(StatusFor::::get(&hash), None); + } + // Cheap unrequest - last reference, but it's not noted. + unrequest_unnoted_preimage { + let (_, hash) = preimage_and_hash::(); + assert_ok!(Preimage::::request_preimage(T::ManagerOrigin::successful_origin(), hash.clone())); + }: unrequest_preimage(T::ManagerOrigin::successful_origin(), hash.clone()) + verify { + assert_eq!(StatusFor::::get(&hash), None); + } + // Cheap unrequest - not the last reference. + unrequest_multi_referenced_preimage { + let (_, hash) = preimage_and_hash::(); + assert_ok!(Preimage::::request_preimage(T::ManagerOrigin::successful_origin(), hash.clone())); + assert_ok!(Preimage::::request_preimage(T::ManagerOrigin::successful_origin(), hash.clone())); + }: unrequest_preimage(T::ManagerOrigin::successful_origin(), hash.clone()) + verify { + assert_eq!(StatusFor::::get(&hash), Some(RequestStatus::Requested(1))); + } + + impl_benchmark_test_suite!(Preimage, crate::mock::new_test_ext(), crate::mock::Test); +} diff --git a/frame/preimage/src/lib.rs b/frame/preimage/src/lib.rs new file mode 100644 index 000000000000..bfa1ce526336 --- /dev/null +++ b/frame/preimage/src/lib.rs @@ -0,0 +1,347 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2021 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. + +//! # Preimage Pallet +//! +//! - [`Config`] +//! - [`Call`] +//! +//! ## Overview +//! +//! The Preimage pallet allows for the users and the runtime to store the preimage +//! of a hash on chain. This can be used by other pallets where storing and managing +//! large byte-blobs. + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; +#[cfg(test)] +mod mock; +#[cfg(test)] +mod tests; +pub mod weights; + +use sp_runtime::traits::{BadOrigin, Hash, Saturating}; +use sp_std::{convert::TryFrom, prelude::*}; + +use codec::{Decode, Encode, MaxEncodedLen}; +use frame_support::{ + ensure, + pallet_prelude::Get, + traits::{Currency, PreimageProvider, PreimageRecipient, ReservableCurrency}, + weights::Pays, + BoundedVec, +}; +use scale_info::TypeInfo; +use weights::WeightInfo; + +use frame_support::pallet_prelude::*; +use frame_system::pallet_prelude::*; + +pub use pallet::*; + +/// A type to note whether a preimage is owned by a user or the system. +#[derive(Clone, Eq, PartialEq, Encode, Decode, TypeInfo, MaxEncodedLen, RuntimeDebug)] +pub enum RequestStatus { + /// The associated preimage has not yet been requested by the system. The given deposit (if + /// some) is being held until either it becomes requested or the user retracts the primage. + Unrequested(Option<(AccountId, Balance)>), + /// There are a non-zero number of outstanding requests for this hash by this chain. If there + /// is a preimage registered, then it may be removed iff this counter becomes zero. + Requested(u32), +} + +type BalanceOf = + <::Currency as Currency<::AccountId>>::Balance; + +#[frame_support::pallet] +pub mod pallet { + use super::*; + + #[pallet::config] + pub trait Config: frame_system::Config { + /// The overarching event type. + type Event: From> + IsType<::Event>; + + /// The Weight information for this pallet. + type WeightInfo: weights::WeightInfo; + + /// Currency type for this pallet. + type Currency: ReservableCurrency; + + /// An origin that can request a preimage be placed on-chain without a deposit or fee, or + /// manage existing preimages. + type ManagerOrigin: EnsureOrigin; + + /// Max size allowed for a preimage. + type MaxSize: Get; + + /// The base deposit for placing a preimage on chain. + type BaseDeposit: Get>; + + /// The per-byte deposit for placing a preimage on chain. + type ByteDeposit: Get>; + } + + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + #[pallet::generate_storage_info] + pub struct Pallet(PhantomData); + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + /// A preimage has been noted. + Noted { hash: T::Hash }, + /// A preimage has been requested. + Requested { hash: T::Hash }, + /// A preimage has ben cleared. + Cleared { hash: T::Hash }, + } + + #[pallet::error] + pub enum Error { + /// Preimage is too large to store on-chain. + TooLarge, + /// Preimage has already been noted on-chain. + AlreadyNoted, + /// The user is not authorized to perform this action. + NotAuthorized, + /// The preimage cannot be removed since it has not yet been noted. + NotNoted, + /// A preimage may not be removed when there are outstanding requests. + Requested, + /// The preimage request cannot be removed since no outstanding requests exist. + NotRequested, + } + + /// The request status of a given hash. + #[pallet::storage] + pub(super) type StatusFor = + StorageMap<_, Identity, T::Hash, RequestStatus>>; + + /// The preimages stored by this pallet. + #[pallet::storage] + pub(super) type PreimageFor = + StorageMap<_, Identity, T::Hash, BoundedVec>; + + #[pallet::call] + impl Pallet { + /// Register a preimage on-chain. + /// + /// If the preimage was previously requested, no fees or deposits are taken for providing + /// the preimage. Otherwise, a deposit is taken proportional to the size of the preimage. + #[pallet::weight(T::WeightInfo::note_preimage(bytes.len() as u32))] + pub fn note_preimage(origin: OriginFor, bytes: Vec) -> DispatchResultWithPostInfo { + // We accept a signed origin which will pay a deposit, or a root origin where a deposit + // is not taken. + let maybe_sender = Self::ensure_signed_or_manager(origin)?; + let bounded_vec = + BoundedVec::::try_from(bytes).map_err(|()| Error::::TooLarge)?; + let system_requested = Self::note_bytes(bounded_vec, maybe_sender.as_ref())?; + if system_requested || maybe_sender.is_none() { + Ok(Pays::No.into()) + } else { + Ok(().into()) + } + } + + /// Clear an unrequested preimage from the runtime storage. + #[pallet::weight(T::WeightInfo::unnote_preimage())] + pub fn unnote_preimage(origin: OriginFor, hash: T::Hash) -> DispatchResult { + let maybe_sender = Self::ensure_signed_or_manager(origin)?; + Self::do_unnote_preimage(&hash, maybe_sender) + } + + /// Request a preimage be uploaded to the chain without paying any fees or deposits. + /// + /// If the preimage requests has already been provided on-chain, we unreserve any deposit + /// a user may have paid, and take the control of the preimage out of their hands. + #[pallet::weight(T::WeightInfo::request_preimage())] + pub fn request_preimage(origin: OriginFor, hash: T::Hash) -> DispatchResult { + T::ManagerOrigin::ensure_origin(origin)?; + Self::do_request_preimage(&hash); + Ok(()) + } + + /// Clear a previously made request for a preimage. + /// + /// NOTE: THIS MUST NOT BE CALLED ON `hash` MORE TIMES THAN `request_preimage`. + #[pallet::weight(T::WeightInfo::unrequest_preimage())] + pub fn unrequest_preimage(origin: OriginFor, hash: T::Hash) -> DispatchResult { + T::ManagerOrigin::ensure_origin(origin)?; + Self::do_unrequest_preimage(&hash) + } + } +} + +impl Pallet { + /// Ensure that the origin is either the `ManagerOrigin` or a signed origin. + fn ensure_signed_or_manager(origin: T::Origin) -> Result, BadOrigin> { + if T::ManagerOrigin::ensure_origin(origin.clone()).is_ok() { + return Ok(None) + } + let who = ensure_signed(origin)?; + Ok(Some(who)) + } + + /// Store some preimage on chain. + /// + /// We verify that the preimage is within the bounds of what the pallet supports. + /// + /// If the preimage was requested to be uploaded, then the user pays no deposits or tx fees. + fn note_bytes( + preimage: BoundedVec, + maybe_depositor: Option<&T::AccountId>, + ) -> Result { + let hash = T::Hashing::hash(&preimage); + ensure!(!PreimageFor::::contains_key(hash), Error::::AlreadyNoted); + + // We take a deposit only if there is a provided depositor, and the preimage was not + // previously requested. This also allows the tx to pay no fee. + let was_requested = match (StatusFor::::get(hash), maybe_depositor) { + (Some(RequestStatus::Requested(..)), _) => true, + (Some(RequestStatus::Unrequested(..)), _) => Err(Error::::AlreadyNoted)?, + (None, None) => { + StatusFor::::insert(hash, RequestStatus::Unrequested(None)); + false + }, + (None, Some(depositor)) => { + let length = preimage.len() as u32; + let deposit = T::BaseDeposit::get() + .saturating_add(T::ByteDeposit::get().saturating_mul(length.into())); + T::Currency::reserve(depositor, deposit)?; + let status = RequestStatus::Unrequested(Some((depositor.clone(), deposit))); + StatusFor::::insert(hash, status); + false + }, + }; + + PreimageFor::::insert(hash, preimage); + Self::deposit_event(Event::Noted { hash }); + + Ok(was_requested) + } + + // This function will add a hash to the list of requested preimages. + // + // If the preimage already exists before the request is made, the deposit for the preimage is + // returned to the user, and removed from their management. + fn do_request_preimage(hash: &T::Hash) { + let count = StatusFor::::get(hash).map_or(1, |x| match x { + RequestStatus::Requested(mut count) => { + count.saturating_inc(); + count + }, + RequestStatus::Unrequested(None) => 1, + RequestStatus::Unrequested(Some((owner, deposit))) => { + // Return the deposit - the preimage now has outstanding requests. + T::Currency::unreserve(&owner, deposit); + 1 + }, + }); + StatusFor::::insert(hash, RequestStatus::Requested(count)); + if count == 1 { + Self::deposit_event(Event::Requested { hash: hash.clone() }); + } + } + + // Clear a preimage from the storage of the chain, returning any deposit that may be reserved. + // + // If `maybe_owner` is provided, we verify that it is the correct owner before clearing the + // data. + fn do_unnote_preimage( + hash: &T::Hash, + maybe_check_owner: Option, + ) -> DispatchResult { + match StatusFor::::get(hash).ok_or(Error::::NotNoted)? { + RequestStatus::Unrequested(Some((owner, deposit))) => { + ensure!( + maybe_check_owner.map_or(true, |c| &c == &owner), + Error::::NotAuthorized + ); + T::Currency::unreserve(&owner, deposit); + }, + RequestStatus::Unrequested(None) => { + ensure!(maybe_check_owner.is_none(), Error::::NotAuthorized); + }, + RequestStatus::Requested(_) => Err(Error::::Requested)?, + } + StatusFor::::remove(hash); + PreimageFor::::remove(hash); + Self::deposit_event(Event::Cleared { hash: hash.clone() }); + Ok(()) + } + + /// Clear a preimage request. + fn do_unrequest_preimage(hash: &T::Hash) -> DispatchResult { + match StatusFor::::get(hash).ok_or(Error::::NotRequested)? { + RequestStatus::Requested(mut count) if count > 1 => { + count.saturating_dec(); + StatusFor::::insert(hash, RequestStatus::Requested(count)); + }, + RequestStatus::Requested(count) => { + debug_assert!(count == 1, "preimage request counter at zero?"); + PreimageFor::::remove(hash); + StatusFor::::remove(hash); + Self::deposit_event(Event::Cleared { hash: hash.clone() }); + }, + RequestStatus::Unrequested(_) => Err(Error::::NotRequested)?, + } + Ok(()) + } +} + +impl PreimageProvider for Pallet { + fn have_preimage(hash: &T::Hash) -> bool { + PreimageFor::::contains_key(hash) + } + + fn preimage_requested(hash: &T::Hash) -> bool { + matches!(StatusFor::::get(hash), Some(RequestStatus::Requested(..))) + } + + fn get_preimage(hash: &T::Hash) -> Option> { + PreimageFor::::get(hash).map(|preimage| preimage.to_vec()) + } + + fn request_preimage(hash: &T::Hash) { + Self::do_request_preimage(hash) + } + + fn unrequest_preimage(hash: &T::Hash) { + let res = Self::do_unrequest_preimage(hash); + debug_assert!(res.is_ok(), "do_unrequest_preimage failed - counter underflow?"); + } +} + +impl PreimageRecipient for Pallet { + type MaxSize = T::MaxSize; + + fn note_preimage(bytes: BoundedVec) { + // We don't really care if this fails, since that's only the case if someone else has + // already noted it. + let _ = Self::note_bytes(bytes, None); + } + + fn unnote_preimage(hash: &T::Hash) { + // Should never fail if authorization check is skipped. + let res = Self::do_unnote_preimage(hash, None); + debug_assert!(res.is_ok(), "unnote_preimage failed - request outstanding?"); + } +} diff --git a/frame/preimage/src/mock.rs b/frame/preimage/src/mock.rs new file mode 100644 index 000000000000..601f72547237 --- /dev/null +++ b/frame/preimage/src/mock.rs @@ -0,0 +1,131 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2021 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. + +//! # Scheduler test environment. + +use super::*; + +use crate as pallet_preimage; +use frame_support::{ + ord_parameter_types, parameter_types, traits::Everything, weights::constants::RocksDbWeight, +}; +use frame_system::EnsureSignedBy; +use sp_core::H256; +use sp_runtime::{ + testing::Header, + traits::{BlakeTwo256, IdentityLookup}, + Perbill, +}; + +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlock; + +frame_support::construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system, + Balances: pallet_balances, + Preimage: pallet_preimage, + } +); + +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub BlockWeights: frame_system::limits::BlockWeights = + frame_system::limits::BlockWeights::simple_max(2_000_000_000_000); +} +impl frame_system::Config for Test { + type BaseCallFilter = Everything; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = RocksDbWeight; + type Origin = Origin; + type Call = Call; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = Event; + type BlockHashCount = BlockHashCount; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + +parameter_types! { + pub const ExistentialDeposit: u64 = 5; + pub const MaxReserves: u32 = 50; +} + +impl pallet_balances::Config for Test { + type Balance = u64; + type Event = Event; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); + type MaxLocks = (); + type MaxReserves = MaxReserves; + type ReserveIdentifier = [u8; 8]; +} + +parameter_types! { + pub MaximumSchedulerWeight: Weight = Perbill::from_percent(80) * BlockWeights::get().max_block; + pub const MaxScheduledPerBlock: u32 = 10; + pub const MaxSize: u32 = 1024; + pub const BaseDeposit: u64 = 2; + pub const ByteDeposit: u64 = 1; +} + +ord_parameter_types! { + pub const One: u64 = 1; +} + +impl Config for Test { + type WeightInfo = (); + type Event = Event; + type Currency = Balances; + type ManagerOrigin = EnsureSignedBy; + type MaxSize = MaxSize; + type BaseDeposit = BaseDeposit; + type ByteDeposit = ByteDeposit; +} + +pub fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + let balances = pallet_balances::GenesisConfig:: { + balances: vec![(1, 100), (2, 100), (3, 100), (4, 100), (5, 100)], + }; + balances.assimilate_storage(&mut t).unwrap(); + t.into() +} + +pub fn hashed(data: impl AsRef<[u8]>) -> H256 { + BlakeTwo256::hash(data.as_ref()) +} diff --git a/frame/preimage/src/tests.rs b/frame/preimage/src/tests.rs new file mode 100644 index 000000000000..528b26330371 --- /dev/null +++ b/frame/preimage/src/tests.rs @@ -0,0 +1,233 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2021 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. + +//! # Scheduler tests. + +use super::*; +use crate::mock::*; + +use frame_support::{assert_noop, assert_ok}; +use pallet_balances::Error as BalancesError; + +#[test] +fn user_note_preimage_works() { + new_test_ext().execute_with(|| { + assert_ok!(Preimage::note_preimage(Origin::signed(2), vec![1])); + assert_eq!(Balances::reserved_balance(2), 3); + assert_eq!(Balances::free_balance(2), 97); + + let h = hashed([1]); + assert!(Preimage::have_preimage(&h)); + assert_eq!(Preimage::get_preimage(&h), Some(vec![1])); + + assert_noop!( + Preimage::note_preimage(Origin::signed(2), vec![1]), + Error::::AlreadyNoted + ); + assert_noop!( + Preimage::note_preimage(Origin::signed(0), vec![2]), + BalancesError::::InsufficientBalance + ); + }); +} + +#[test] +fn manager_note_preimage_works() { + new_test_ext().execute_with(|| { + assert_ok!(Preimage::note_preimage(Origin::signed(1), vec![1])); + assert_eq!(Balances::reserved_balance(1), 0); + assert_eq!(Balances::free_balance(1), 100); + + let h = hashed([1]); + assert!(Preimage::have_preimage(&h)); + assert_eq!(Preimage::get_preimage(&h), Some(vec![1])); + + assert_noop!( + Preimage::note_preimage(Origin::signed(1), vec![1]), + Error::::AlreadyNoted + ); + }); +} + +#[test] +fn user_unnote_preimage_works() { + new_test_ext().execute_with(|| { + assert_ok!(Preimage::note_preimage(Origin::signed(2), vec![1])); + assert_noop!( + Preimage::unnote_preimage(Origin::signed(3), hashed([1])), + Error::::NotAuthorized + ); + assert_noop!( + Preimage::unnote_preimage(Origin::signed(2), hashed([2])), + Error::::NotNoted + ); + + assert_ok!(Preimage::unnote_preimage(Origin::signed(2), hashed([1]))); + assert_noop!( + Preimage::unnote_preimage(Origin::signed(2), hashed([1])), + Error::::NotNoted + ); + + let h = hashed([1]); + assert!(!Preimage::have_preimage(&h)); + assert_eq!(Preimage::get_preimage(&h), None); + }); +} + +#[test] +fn manager_unnote_preimage_works() { + new_test_ext().execute_with(|| { + assert_ok!(Preimage::note_preimage(Origin::signed(1), vec![1])); + assert_ok!(Preimage::unnote_preimage(Origin::signed(1), hashed([1]))); + assert_noop!( + Preimage::unnote_preimage(Origin::signed(1), hashed([1])), + Error::::NotNoted + ); + + let h = hashed([1]); + assert!(!Preimage::have_preimage(&h)); + assert_eq!(Preimage::get_preimage(&h), None); + }); +} + +#[test] +fn manager_unnote_user_preimage_works() { + new_test_ext().execute_with(|| { + assert_ok!(Preimage::note_preimage(Origin::signed(2), vec![1])); + assert_noop!( + Preimage::unnote_preimage(Origin::signed(3), hashed([1])), + Error::::NotAuthorized + ); + assert_noop!( + Preimage::unnote_preimage(Origin::signed(2), hashed([2])), + Error::::NotNoted + ); + + assert_ok!(Preimage::unnote_preimage(Origin::signed(1), hashed([1]))); + + let h = hashed([1]); + assert!(!Preimage::have_preimage(&h)); + assert_eq!(Preimage::get_preimage(&h), None); + }); +} + +#[test] +fn requested_then_noted_preimage_cannot_be_unnoted() { + new_test_ext().execute_with(|| { + assert_ok!(Preimage::note_preimage(Origin::signed(1), vec![1])); + assert_ok!(Preimage::request_preimage(Origin::signed(1), hashed([1]))); + assert_noop!( + Preimage::unnote_preimage(Origin::signed(1), hashed([1])), + Error::::Requested + ); + + let h = hashed([1]); + assert!(Preimage::have_preimage(&h)); + assert_eq!(Preimage::get_preimage(&h), Some(vec![1])); + }); +} + +#[test] +fn request_note_order_makes_no_difference() { + let one_way = new_test_ext().execute_with(|| { + assert_ok!(Preimage::request_preimage(Origin::signed(1), hashed([1]))); + assert_ok!(Preimage::note_preimage(Origin::signed(1), vec![1])); + ( + StatusFor::::iter().collect::>(), + PreimageFor::::iter().collect::>(), + ) + }); + new_test_ext().execute_with(|| { + assert_ok!(Preimage::note_preimage(Origin::signed(1), vec![1])); + assert_ok!(Preimage::request_preimage(Origin::signed(1), hashed([1]))); + let other_way = ( + StatusFor::::iter().collect::>(), + PreimageFor::::iter().collect::>(), + ); + assert_eq!(one_way, other_way); + }); +} + +#[test] +fn requested_then_user_noted_preimage_is_free() { + new_test_ext().execute_with(|| { + assert_ok!(Preimage::request_preimage(Origin::signed(1), hashed([1]))); + assert_ok!(Preimage::note_preimage(Origin::signed(2), vec![1])); + assert_eq!(Balances::reserved_balance(2), 0); + assert_eq!(Balances::free_balance(2), 100); + + let h = hashed([1]); + assert!(Preimage::have_preimage(&h)); + assert_eq!(Preimage::get_preimage(&h), Some(vec![1])); + }); +} + +#[test] +fn request_user_note_order_makes_no_difference() { + let one_way = new_test_ext().execute_with(|| { + assert_ok!(Preimage::request_preimage(Origin::signed(1), hashed([1]))); + assert_ok!(Preimage::note_preimage(Origin::signed(2), vec![1])); + ( + StatusFor::::iter().collect::>(), + PreimageFor::::iter().collect::>(), + ) + }); + new_test_ext().execute_with(|| { + assert_ok!(Preimage::note_preimage(Origin::signed(2), vec![1])); + assert_ok!(Preimage::request_preimage(Origin::signed(1), hashed([1]))); + let other_way = ( + StatusFor::::iter().collect::>(), + PreimageFor::::iter().collect::>(), + ); + assert_eq!(one_way, other_way); + }); +} + +#[test] +fn unrequest_preimage_works() { + new_test_ext().execute_with(|| { + assert_ok!(Preimage::request_preimage(Origin::signed(1), hashed([1]))); + assert_ok!(Preimage::request_preimage(Origin::signed(1), hashed([1]))); + assert_ok!(Preimage::note_preimage(Origin::signed(2), vec![1])); + assert_noop!( + Preimage::unrequest_preimage(Origin::signed(1), hashed([2])), + Error::::NotRequested + ); + + assert_ok!(Preimage::unrequest_preimage(Origin::signed(1), hashed([1]))); + assert!(Preimage::have_preimage(&hashed([1]))); + + assert_ok!(Preimage::unrequest_preimage(Origin::signed(1), hashed([1]))); + assert_noop!( + Preimage::unrequest_preimage(Origin::signed(1), hashed([1])), + Error::::NotRequested + ); + }); +} + +#[test] +fn user_noted_then_requested_preimage_is_refunded_once_only() { + new_test_ext().execute_with(|| { + assert_ok!(Preimage::note_preimage(Origin::signed(2), vec![1; 3])); + assert_ok!(Preimage::note_preimage(Origin::signed(2), vec![1])); + assert_ok!(Preimage::request_preimage(Origin::signed(1), hashed([1]))); + assert_ok!(Preimage::unrequest_preimage(Origin::signed(1), hashed([1]))); + // Still have reserve from `vec[1; 3]`. + assert_eq!(Balances::reserved_balance(2), 5); + assert_eq!(Balances::free_balance(2), 95); + }); +} diff --git a/frame/preimage/src/weights.rs b/frame/preimage/src/weights.rs new file mode 100644 index 000000000000..406ca99bfb79 --- /dev/null +++ b/frame/preimage/src/weights.rs @@ -0,0 +1,238 @@ +// This file is part of Substrate. + +// Copyright (C) 2021 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. + +//! Autogenerated weights for pallet_preimage +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2021-12-10, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 + +// Executed Command: +// target/release/substrate +// benchmark +// --chain=dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_preimage +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 +// --output=./frame/preimage/src/weights.rs +// --template=./.maintain/frame-weight-template.hbs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +/// Weight functions needed for pallet_preimage. +pub trait WeightInfo { + fn note_preimage(s: u32, ) -> Weight; + fn note_requested_preimage(s: u32, ) -> Weight; + fn note_no_deposit_preimage(s: u32, ) -> Weight; + fn unnote_preimage() -> Weight; + fn unnote_no_deposit_preimage() -> Weight; + fn request_preimage() -> Weight; + fn request_no_deposit_preimage() -> Weight; + fn request_unnoted_preimage() -> Weight; + fn request_requested_preimage() -> Weight; + fn unrequest_preimage() -> Weight; + fn unrequest_unnoted_preimage() -> Weight; + fn unrequest_multi_referenced_preimage() -> Weight; +} + +/// Weights for pallet_preimage using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + // Storage: Preimage PreimageFor (r:1 w:1) + // Storage: Preimage StatusFor (r:1 w:1) + fn note_preimage(s: u32, ) -> Weight { + (0 as Weight) + // Standard Error: 0 + .saturating_add((2_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + } + // Storage: Preimage PreimageFor (r:1 w:1) + // Storage: Preimage StatusFor (r:1 w:0) + fn note_requested_preimage(s: u32, ) -> Weight { + (0 as Weight) + // Standard Error: 0 + .saturating_add((2_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + // Storage: Preimage PreimageFor (r:1 w:1) + // Storage: Preimage StatusFor (r:1 w:0) + fn note_no_deposit_preimage(s: u32, ) -> Weight { + (0 as Weight) + // Standard Error: 0 + .saturating_add((2_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + // Storage: Preimage StatusFor (r:1 w:1) + // Storage: Preimage PreimageFor (r:0 w:1) + fn unnote_preimage() -> Weight { + (60_560_000 as Weight) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + } + // Storage: Preimage StatusFor (r:1 w:1) + // Storage: Preimage PreimageFor (r:0 w:1) + fn unnote_no_deposit_preimage() -> Weight { + (37_575_000 as Weight) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + } + // Storage: Preimage StatusFor (r:1 w:1) + fn request_preimage() -> Weight { + (56_868_000 as Weight) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + // Storage: Preimage StatusFor (r:1 w:1) + fn request_no_deposit_preimage() -> Weight { + (37_058_000 as Weight) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + // Storage: Preimage StatusFor (r:1 w:1) + fn request_unnoted_preimage() -> Weight { + (21_500_000 as Weight) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + // Storage: Preimage StatusFor (r:1 w:1) + fn request_requested_preimage() -> Weight { + (7_798_000 as Weight) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + // Storage: Preimage StatusFor (r:1 w:1) + // Storage: Preimage PreimageFor (r:0 w:1) + fn unrequest_preimage() -> Weight { + (37_771_000 as Weight) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + } + // Storage: Preimage StatusFor (r:1 w:1) + // Storage: Preimage PreimageFor (r:0 w:1) + fn unrequest_unnoted_preimage() -> Weight { + (22_913_000 as Weight) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + } + // Storage: Preimage StatusFor (r:1 w:1) + fn unrequest_multi_referenced_preimage() -> Weight { + (7_608_000 as Weight) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } +} + +// For backwards compatibility and tests +impl WeightInfo for () { + // Storage: Preimage PreimageFor (r:1 w:1) + // Storage: Preimage StatusFor (r:1 w:1) + fn note_preimage(s: u32, ) -> Weight { + (0 as Weight) + // Standard Error: 0 + .saturating_add((2_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(RocksDbWeight::get().reads(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + } + // Storage: Preimage PreimageFor (r:1 w:1) + // Storage: Preimage StatusFor (r:1 w:0) + fn note_requested_preimage(s: u32, ) -> Weight { + (0 as Weight) + // Standard Error: 0 + .saturating_add((2_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(RocksDbWeight::get().reads(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + // Storage: Preimage PreimageFor (r:1 w:1) + // Storage: Preimage StatusFor (r:1 w:0) + fn note_no_deposit_preimage(s: u32, ) -> Weight { + (0 as Weight) + // Standard Error: 0 + .saturating_add((2_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(RocksDbWeight::get().reads(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + // Storage: Preimage StatusFor (r:1 w:1) + // Storage: Preimage PreimageFor (r:0 w:1) + fn unnote_preimage() -> Weight { + (60_560_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + } + // Storage: Preimage StatusFor (r:1 w:1) + // Storage: Preimage PreimageFor (r:0 w:1) + fn unnote_no_deposit_preimage() -> Weight { + (37_575_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + } + // Storage: Preimage StatusFor (r:1 w:1) + fn request_preimage() -> Weight { + (56_868_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + // Storage: Preimage StatusFor (r:1 w:1) + fn request_no_deposit_preimage() -> Weight { + (37_058_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + // Storage: Preimage StatusFor (r:1 w:1) + fn request_unnoted_preimage() -> Weight { + (21_500_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + // Storage: Preimage StatusFor (r:1 w:1) + fn request_requested_preimage() -> Weight { + (7_798_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + // Storage: Preimage StatusFor (r:1 w:1) + // Storage: Preimage PreimageFor (r:0 w:1) + fn unrequest_preimage() -> Weight { + (37_771_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + } + // Storage: Preimage StatusFor (r:1 w:1) + // Storage: Preimage PreimageFor (r:0 w:1) + fn unrequest_unnoted_preimage() -> Weight { + (22_913_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + } + // Storage: Preimage StatusFor (r:1 w:1) + fn unrequest_multi_referenced_preimage() -> Weight { + (7_608_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } +} diff --git a/frame/scheduler/Cargo.toml b/frame/scheduler/Cargo.toml index a1d43b359a88..2f7673598151 100644 --- a/frame/scheduler/Cargo.toml +++ b/frame/scheduler/Cargo.toml @@ -3,44 +3,45 @@ name = "pallet-scheduler" version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2021" -license = "Unlicense" +license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" -description = "FRAME example pallet" +description = "FRAME Scheduler pallet" readme = "README.md" [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } +codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } log = { version = "0.4.14", default-features = false } +sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } +frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] sp-core = { version = "4.1.0-dev", path = "../../primitives/core", default-features = false } substrate-test-utils = { version = "4.0.0-dev", path = "../../test-utils" } +pallet-preimage = { version = "4.0.0-dev", path = "../preimage" } [features] default = ["std"] +runtime-benchmarks = [ + "frame-benchmarking", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", +] std = [ "codec/std", "scale-info/std", + "log/std", + "sp-std/std", + "sp-io/std", "sp-runtime/std", - "frame-benchmarking/std", - "frame-support/std", "frame-system/std", - "sp-io/std", - "sp-std/std", - "log/std", -] -runtime-benchmarks = [ - "frame-benchmarking/runtime-benchmarks", - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", + "frame-support/std", + "frame-benchmarking/std", ] try-runtime = ["frame-support/try-runtime"] diff --git a/frame/scheduler/src/benchmarking.rs b/frame/scheduler/src/benchmarking.rs index 1065f1702774..22e3e4f4530b 100644 --- a/frame/scheduler/src/benchmarking.rs +++ b/frame/scheduler/src/benchmarking.rs @@ -17,12 +17,14 @@ //! Scheduler pallet benchmarking. -#![cfg(feature = "runtime-benchmarks")] - use super::*; use frame_benchmarking::benchmarks; -use frame_support::{ensure, traits::OnInitialize}; +use frame_support::{ + ensure, + traits::{OnInitialize, PreimageProvider, PreimageRecipient}, +}; use frame_system::RawOrigin; +use sp_runtime::traits::Hash; use sp_std::{prelude::*, vec}; use crate::Pallet as Scheduler; @@ -30,37 +32,184 @@ use frame_system::Pallet as System; const BLOCK_NUMBER: u32 = 2; -// Add `n` named items to the schedule -fn fill_schedule(when: T::BlockNumber, n: u32) -> Result<(), &'static str> { - // Essentially a no-op call. - let call = frame_system::Call::set_storage { items: vec![] }; +/// Add `n` named items to the schedule. +/// +/// For `resolved`: +/// - `None`: aborted (hash without preimage) +/// - `Some(true)`: hash resolves into call if possible, plain call otherwise +/// - `Some(false)`: plain call +fn fill_schedule( + when: T::BlockNumber, + n: u32, + periodic: bool, + named: bool, + resolved: Option, +) -> Result<(), &'static str> { for i in 0..n { // Named schedule is strictly heavier than anonymous - Scheduler::::do_schedule_named( - i.encode(), - DispatchTime::At(when), - // Add periodicity - Some((T::BlockNumber::one(), 100)), - // HARD_DEADLINE priority means it gets executed no matter what - 0, - frame_system::RawOrigin::Root.into(), - call.clone().into(), - )?; + let (call, hash) = call_and_hash::(i); + let call_or_hash = match resolved { + Some(true) => { + T::PreimageProvider::note_preimage(call.encode().try_into().unwrap()); + if T::PreimageProvider::have_preimage(&hash) { + CallOrHashOf::::Hash(hash) + } else { + call.into() + } + }, + Some(false) => call.into(), + None => CallOrHashOf::::Hash(hash), + }; + let period = match periodic { + true => Some(((i + 100).into(), 100)), + false => None, + }; + let t = DispatchTime::At(when); + let origin = frame_system::RawOrigin::Root.into(); + if named { + Scheduler::::do_schedule_named(i.encode(), t, period, 0, origin, call_or_hash)?; + } else { + Scheduler::::do_schedule(t, period, 0, origin, call_or_hash)?; + } } ensure!(Agenda::::get(when).len() == n as usize, "didn't fill schedule"); Ok(()) } +fn call_and_hash(i: u32) -> (::Call, T::Hash) { + // Essentially a no-op call. + let call: ::Call = frame_system::Call::remark { remark: i.encode() }.into(); + let hash = T::Hashing::hash_of(&call); + (call, hash) +} + benchmarks! { + on_initialize_periodic_named_resolved { + let s in 1 .. T::MaxScheduledPerBlock::get(); + let when = BLOCK_NUMBER.into(); + fill_schedule::(when, s, true, true, Some(true))?; + }: { Scheduler::::on_initialize(BLOCK_NUMBER.into()); } + verify { + assert_eq!(System::::event_count(), s * 2); + for i in 0..s { + assert_eq!(Agenda::::get(when + (i + 100).into()).len(), 1 as usize); + } + } + + on_initialize_named_resolved { + let s in 1 .. T::MaxScheduledPerBlock::get(); + let when = BLOCK_NUMBER.into(); + fill_schedule::(when, s, false, true, Some(true))?; + }: { Scheduler::::on_initialize(BLOCK_NUMBER.into()); } + verify { + assert_eq!(System::::event_count(), s * 2); + assert!(Agenda::::iter().count() == 0); + } + + on_initialize_periodic_resolved { + let s in 1 .. T::MaxScheduledPerBlock::get(); + let when = BLOCK_NUMBER.into(); + fill_schedule::(when, s, true, false, Some(true))?; + }: { Scheduler::::on_initialize(BLOCK_NUMBER.into()); } + verify { + assert_eq!(System::::event_count(), s * 2); + for i in 0..s { + assert_eq!(Agenda::::get(when + (i + 100).into()).len(), 1 as usize); + } + } + + on_initialize_resolved { + let s in 1 .. T::MaxScheduledPerBlock::get(); + let when = BLOCK_NUMBER.into(); + fill_schedule::(when, s, false, false, Some(true))?; + }: { Scheduler::::on_initialize(BLOCK_NUMBER.into()); } + verify { + assert_eq!(System::::event_count(), s * 2); + assert!(Agenda::::iter().count() == 0); + } + + on_initialize_named_aborted { + let s in 1 .. T::MaxScheduledPerBlock::get(); + let when = BLOCK_NUMBER.into(); + fill_schedule::(when, s, false, true, None)?; + }: { Scheduler::::on_initialize(BLOCK_NUMBER.into()); } + verify { + assert_eq!(System::::event_count(), 0); + if let Some(delay) = T::NoPreimagePostponement::get() { + assert_eq!(Agenda::::get(when + delay).len(), s as usize); + } else { + assert!(Agenda::::iter().count() == 0); + } + } + + on_initialize_aborted { + let s in 1 .. T::MaxScheduledPerBlock::get(); + let when = BLOCK_NUMBER.into(); + fill_schedule::(when, s, false, false, None)?; + }: { Scheduler::::on_initialize(BLOCK_NUMBER.into()); } + verify { + assert_eq!(System::::event_count(), 0); + if let Some(delay) = T::NoPreimagePostponement::get() { + assert_eq!(Agenda::::get(when + delay).len(), s as usize); + } else { + assert!(Agenda::::iter().count() == 0); + } + } + + on_initialize_periodic_named { + let s in 1 .. T::MaxScheduledPerBlock::get(); + let when = BLOCK_NUMBER.into(); + fill_schedule::(when, s, true, true, Some(false))?; + }: { Scheduler::::on_initialize(BLOCK_NUMBER.into()); } + verify { + assert_eq!(System::::event_count(), s); + for i in 0..s { + assert_eq!(Agenda::::get(when + (i + 100).into()).len(), 1 as usize); + } + } + + on_initialize_periodic { + let s in 1 .. T::MaxScheduledPerBlock::get(); + let when = BLOCK_NUMBER.into(); + fill_schedule::(when, s, true, false, Some(false))?; + }: { Scheduler::::on_initialize(when); } + verify { + assert_eq!(System::::event_count(), s); + for i in 0..s { + assert_eq!(Agenda::::get(when + (i + 100).into()).len(), 1 as usize); + } + } + + on_initialize_named { + let s in 1 .. T::MaxScheduledPerBlock::get(); + let when = BLOCK_NUMBER.into(); + fill_schedule::(when, s, false, true, Some(false))?; + }: { Scheduler::::on_initialize(BLOCK_NUMBER.into()); } + verify { + assert_eq!(System::::event_count(), s); + assert!(Agenda::::iter().count() == 0); + } + + on_initialize { + let s in 1 .. T::MaxScheduledPerBlock::get(); + let when = BLOCK_NUMBER.into(); + fill_schedule::(when, s, false, false, Some(false))?; + }: { Scheduler::::on_initialize(BLOCK_NUMBER.into()); } + verify { + assert_eq!(System::::event_count(), s); + assert!(Agenda::::iter().count() == 0); + } + schedule { let s in 0 .. T::MaxScheduledPerBlock::get(); let when = BLOCK_NUMBER.into(); let periodic = Some((T::BlockNumber::one(), 100)); let priority = 0; // Essentially a no-op call. - let call = Box::new(frame_system::Call::set_storage { items: vec![] }.into()); + let inner_call = frame_system::Call::set_storage { items: vec![] }.into(); + let call = Box::new(CallOrHashOf::::Value(inner_call)); - fill_schedule::(when, s)?; + fill_schedule::(when, s, true, true, Some(false))?; }: _(RawOrigin::Root, when, periodic, priority, call) verify { ensure!( @@ -73,7 +222,7 @@ benchmarks! { let s in 1 .. T::MaxScheduledPerBlock::get(); let when = BLOCK_NUMBER.into(); - fill_schedule::(when, s)?; + fill_schedule::(when, s, true, true, Some(false))?; assert_eq!(Agenda::::get(when).len(), s as usize); }: _(RawOrigin::Root, when, 0) verify { @@ -95,9 +244,10 @@ benchmarks! { let periodic = Some((T::BlockNumber::one(), 100)); let priority = 0; // Essentially a no-op call. - let call = Box::new(frame_system::Call::set_storage { items: vec![] }.into()); + let inner_call = frame_system::Call::set_storage { items: vec![] }.into(); + let call = Box::new(CallOrHashOf::::Value(inner_call)); - fill_schedule::(when, s)?; + fill_schedule::(when, s, true, true, Some(false))?; }: _(RawOrigin::Root, id, when, periodic, priority, call) verify { ensure!( @@ -110,7 +260,7 @@ benchmarks! { let s in 1 .. T::MaxScheduledPerBlock::get(); let when = BLOCK_NUMBER.into(); - fill_schedule::(when, s)?; + fill_schedule::(when, s, true, true, Some(false))?; }: _(RawOrigin::Root, 0.encode()) verify { ensure!( @@ -124,21 +274,5 @@ benchmarks! { ); } - // TODO [#7141]: Make this more complex and flexible so it can be used in automation. - #[extra] - on_initialize { - let s in 0 .. T::MaxScheduledPerBlock::get(); - let when = BLOCK_NUMBER.into(); - fill_schedule::(when, s)?; - }: { Scheduler::::on_initialize(BLOCK_NUMBER.into()); } - verify { - assert_eq!(System::::event_count(), s); - // Next block should have all the schedules again - ensure!( - Agenda::::get(when + T::BlockNumber::one()).len() == s as usize, - "didn't append schedule" - ); - } - - impl_benchmark_test_suite!(Scheduler, crate::tests::new_test_ext(), crate::tests::Test); + impl_benchmark_test_suite!(Scheduler, crate::mock::new_test_ext(), crate::mock::Test); } diff --git a/frame/scheduler/src/lib.rs b/frame/scheduler/src/lib.rs index 02bcb5eb3109..b4ee2575e23d 100644 --- a/frame/scheduler/src/lib.rs +++ b/frame/scheduler/src/lib.rs @@ -50,14 +50,19 @@ // Ensure we're `no_std` when compiling for Wasm. #![cfg_attr(not(feature = "std"), no_std)] +#[cfg(feature = "runtime-benchmarks")] mod benchmarking; +#[cfg(test)] +mod mock; +#[cfg(test)] +mod tests; pub mod weights; use codec::{Codec, Decode, Encode}; use frame_support::{ dispatch::{DispatchError, DispatchResult, Dispatchable, Parameter}, traits::{ - schedule::{self, DispatchTime}, + schedule::{self, DispatchTime, MaybeHashed}, EnsureOrigin, Get, IsType, OriginTrait, PrivilegeCmp, }, weights::{GetDispatchInfo, Weight}, @@ -77,6 +82,8 @@ pub type PeriodicIndex = u32; /// The location of a scheduled task that can be used to remove it. pub type TaskAddress = (BlockNumber, u32); +pub type CallOrHashOf = MaybeHashed<::Call, ::Hash>; + #[cfg_attr(any(feature = "std", test), derive(PartialEq, Eq))] #[derive(Clone, RuntimeDebug, Encode, Decode)] struct ScheduledV1 { @@ -89,7 +96,7 @@ struct ScheduledV1 { /// Information regarding an item to be executed in the future. #[cfg_attr(any(feature = "std", test), derive(PartialEq, Eq))] #[derive(Clone, RuntimeDebug, Encode, Decode, TypeInfo)] -pub struct ScheduledV2 { +pub struct ScheduledV3 { /// The unique identity for this task, if there is one. maybe_id: Option>, /// This task's priority. @@ -103,6 +110,24 @@ pub struct ScheduledV2 { _phantom: PhantomData, } +use crate::ScheduledV3 as ScheduledV2; + +pub type ScheduledV2Of = ScheduledV3< + ::Call, + ::BlockNumber, + ::PalletsOrigin, + ::AccountId, +>; + +pub type ScheduledV3Of = ScheduledV3< + CallOrHashOf, + ::BlockNumber, + ::PalletsOrigin, + ::AccountId, +>; + +pub type ScheduledOf = ScheduledV3Of; + /// The current version of Scheduled struct. pub type Scheduled = ScheduledV2; @@ -110,10 +135,11 @@ pub type Scheduled = // A value placed in storage that represents the current version of the Scheduler storage. // This value is used by the `on_runtime_upgrade` logic to determine whether we run // storage migration logic. -#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo)] +#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug, TypeInfo)] enum Releases { V1, V2, + V3, } impl Default for Releases { @@ -122,10 +148,57 @@ impl Default for Releases { } } +#[cfg(feature = "runtime-benchmarks")] +mod preimage_provider { + use frame_support::traits::PreimageRecipient; + pub trait PreimageProviderAndMaybeRecipient: PreimageRecipient {} + impl> PreimageProviderAndMaybeRecipient for T {} +} + +#[cfg(not(feature = "runtime-benchmarks"))] +mod preimage_provider { + use frame_support::traits::PreimageProvider; + pub trait PreimageProviderAndMaybeRecipient: PreimageProvider {} + impl> PreimageProviderAndMaybeRecipient for T {} +} + +pub use preimage_provider::PreimageProviderAndMaybeRecipient; + +pub(crate) trait MarginalWeightInfo: WeightInfo { + fn item(periodic: bool, named: bool, resolved: Option) -> Weight { + match (periodic, named, resolved) { + (_, false, None) => Self::on_initialize_aborted(2) - Self::on_initialize_aborted(1), + (_, true, None) => + Self::on_initialize_named_aborted(2) - Self::on_initialize_named_aborted(1), + (false, false, Some(false)) => Self::on_initialize(2) - Self::on_initialize(1), + (false, true, Some(false)) => + Self::on_initialize_named(2) - Self::on_initialize_named(1), + (true, false, Some(false)) => + Self::on_initialize_periodic(2) - Self::on_initialize_periodic(1), + (true, true, Some(false)) => + Self::on_initialize_periodic_named(2) - Self::on_initialize_periodic_named(1), + (false, false, Some(true)) => + Self::on_initialize_resolved(2) - Self::on_initialize_resolved(1), + (false, true, Some(true)) => + Self::on_initialize_named_resolved(2) - Self::on_initialize_named_resolved(1), + (true, false, Some(true)) => + Self::on_initialize_periodic_resolved(2) - Self::on_initialize_periodic_resolved(1), + (true, true, Some(true)) => + Self::on_initialize_periodic_named_resolved(2) - + Self::on_initialize_periodic_named_resolved(1), + } + } +} +impl MarginalWeightInfo for T {} + #[frame_support::pallet] pub mod pallet { use super::*; - use frame_support::pallet_prelude::*; + use frame_support::{ + dispatch::PostDispatchInfo, + pallet_prelude::*, + traits::{schedule::LookupError, PreimageProvider}, + }; use frame_system::pallet_prelude::*; #[pallet::pallet] @@ -148,7 +221,7 @@ pub mod pallet { /// The aggregated call type. type Call: Parameter - + Dispatchable::Origin> + + Dispatchable::Origin, PostInfo = PostDispatchInfo> + GetDispatchInfo + From>; @@ -176,17 +249,18 @@ pub mod pallet { /// Weight information for extrinsics in this pallet. type WeightInfo: WeightInfo; + + /// The preimage provider with which we look up call hashes to get the call. + type PreimageProvider: PreimageProviderAndMaybeRecipient; + + /// If `Some` then the number of blocks to postpone execution for when the item is delayed. + type NoPreimagePostponement: Get>; } /// Items to be executed, indexed by the block number that they should be executed on. #[pallet::storage] - pub type Agenda = StorageMap< - _, - Twox64Concat, - T::BlockNumber, - Vec::Call, T::BlockNumber, T::PalletsOrigin, T::AccountId>>>, - ValueQuery, - >; + pub type Agenda = + StorageMap<_, Twox64Concat, T::BlockNumber, Vec>>, ValueQuery>; /// Lookup from identity to the block number and index of the task. #[pallet::storage] @@ -213,6 +287,12 @@ pub mod pallet { id: Option>, result: DispatchResult, }, + /// The call for the provided hash was not found so the task has been aborted. + CallLookupFailed { + task: TaskAddress, + id: Option>, + error: LookupError, + }, } #[pallet::error] @@ -240,7 +320,7 @@ pub mod pallet { #[pallet::genesis_build] impl GenesisBuild for GenesisConfig { fn build(&self) { - StorageVersion::::put(Releases::V2); + StorageVersion::::put(Releases::V3); } } @@ -249,11 +329,13 @@ pub mod pallet { /// Execute the scheduled calls fn on_initialize(now: T::BlockNumber) -> Weight { let limit = T::MaximumWeight::get(); + let mut queued = Agenda::::take(now) .into_iter() .enumerate() - .filter_map(|(index, s)| s.map(|inner| (index as u32, inner))) + .filter_map(|(index, s)| Some((index as u32, s?))) .collect::>(); + if queued.len() as u32 > T::MaxScheduledPerBlock::get() { log::warn!( target: "runtime::scheduler", @@ -261,84 +343,111 @@ pub mod pallet { expected from the runtime configuration. An update might be needed." ); } - queued.sort_by_key(|(_, s)| s.priority); - let base_weight: Weight = T::DbWeight::get().reads_writes(1, 2); // Agenda + Agenda(next) - let mut total_weight: Weight = 0; - queued - .into_iter() - .enumerate() - .scan(base_weight, |cumulative_weight, (order, (index, s))| { - *cumulative_weight = - cumulative_weight.saturating_add(s.call.get_dispatch_info().weight); - - let origin = - <::Origin as From>::from(s.origin.clone()) - .into(); - - if ensure_signed(origin).is_ok() { - // AccountData for inner call origin accountdata. - *cumulative_weight = - cumulative_weight.saturating_add(T::DbWeight::get().reads_writes(1, 1)); - } - if s.maybe_id.is_some() { - // Remove/Modify Lookup - *cumulative_weight = - cumulative_weight.saturating_add(T::DbWeight::get().writes(1)); - } - if s.maybe_periodic.is_some() { - // Read/Write Agenda for future block - *cumulative_weight = - cumulative_weight.saturating_add(T::DbWeight::get().reads_writes(1, 1)); - } + queued.sort_by_key(|(_, s)| s.priority); - Some((order, index, *cumulative_weight, s)) - }) - .filter_map(|(order, index, cumulative_weight, mut s)| { - // We allow a scheduled call if any is true: - // - It's priority is `HARD_DEADLINE` - // - It does not push the weight past the limit. - // - It is the first item in the schedule - if s.priority <= schedule::HARD_DEADLINE || - cumulative_weight <= limit || - order == 0 - { - let r = s.call.clone().dispatch(s.origin.clone().into()); - let maybe_id = s.maybe_id.clone(); - if let &Some((period, count)) = &s.maybe_periodic { - if count > 1 { - s.maybe_periodic = Some((period, count - 1)); - } else { - s.maybe_periodic = None; - } - let next = now + period; - // If scheduled is named, place it's information in `Lookup` + let next = now + One::one(); + + let mut total_weight: Weight = T::WeightInfo::on_initialize(0); + for (order, (index, mut s)) in queued.into_iter().enumerate() { + let named = if let Some(ref id) = s.maybe_id { + Lookup::::remove(id); + true + } else { + false + }; + + let (call, maybe_completed) = s.call.resolved::(); + s.call = call; + + let resolved = if let Some(completed) = maybe_completed { + T::PreimageProvider::unrequest_preimage(&completed); + true + } else { + false + }; + + let call = match s.call.as_value().cloned() { + Some(c) => c, + None => { + // Preimage not available - postpone until some block. + total_weight.saturating_accrue(T::WeightInfo::item(false, named, None)); + if let Some(delay) = T::NoPreimagePostponement::get() { + let until = now.saturating_add(delay); if let Some(ref id) = s.maybe_id { - let next_index = Agenda::::decode_len(now + period).unwrap_or(0); - Lookup::::insert(id, (next, next_index as u32)); - } - Agenda::::append(next, Some(s)); - } else { - if let Some(ref id) = s.maybe_id { - Lookup::::remove(id); + let index = Agenda::::decode_len(until).unwrap_or(0); + Lookup::::insert(id, (until, index as u32)); } + Agenda::::append(until, Some(s)); } - Self::deposit_event(Event::Dispatched { - task: (now, index), - id: maybe_id, - result: r.map(|_| ()).map_err(|e| e.error), - }); - total_weight = cumulative_weight; - None - } else { - Some(Some(s)) + continue + }, + }; + + let periodic = s.maybe_periodic.is_some(); + let call_weight = call.get_dispatch_info().weight; + let mut item_weight = T::WeightInfo::item(periodic, named, Some(resolved)); + let origin = + <::Origin as From>::from(s.origin.clone()) + .into(); + if ensure_signed(origin).is_ok() { + // Weights of Signed dispatches expect their signing account to be whitelisted. + item_weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); + } + + // We allow a scheduled call if any is true: + // - It's priority is `HARD_DEADLINE` + // - It does not push the weight past the limit. + // - It is the first item in the schedule + let hard_deadline = s.priority <= schedule::HARD_DEADLINE; + let test_weight = + total_weight.saturating_add(call_weight).saturating_add(item_weight); + if !hard_deadline && order > 0 && test_weight > limit { + // Cannot be scheduled this block - postpone until next. + total_weight.saturating_accrue(T::WeightInfo::item(false, named, None)); + if let Some(ref id) = s.maybe_id { + // NOTE: We could reasonably not do this (in which case there would be one + // block where the named and delayed item could not be referenced by name), + // but we will do it anyway since it should be mostly free in terms of + // weight and it is slightly cleaner. + let index = Agenda::::decode_len(next).unwrap_or(0); + Lookup::::insert(id, (next, index as u32)); } - }) - .for_each(|unused| { - let next = now + One::one(); - Agenda::::append(next, unused); + Agenda::::append(next, Some(s)); + continue + } + + let dispatch_origin = s.origin.clone().into(); + let (maybe_actual_call_weight, result) = match call.dispatch(dispatch_origin) { + Ok(post_info) => (post_info.actual_weight, Ok(())), + Err(error_and_info) => + (error_and_info.post_info.actual_weight, Err(error_and_info.error)), + }; + let actual_call_weight = maybe_actual_call_weight.unwrap_or(call_weight); + total_weight.saturating_accrue(item_weight); + total_weight.saturating_accrue(actual_call_weight); + + Self::deposit_event(Event::Dispatched { + task: (now, index), + id: s.maybe_id.clone(), + result, }); + if let &Some((period, count)) = &s.maybe_periodic { + if count > 1 { + s.maybe_periodic = Some((period, count - 1)); + } else { + s.maybe_periodic = None; + } + let wake = now + period; + // If scheduled is named, place its information in `Lookup` + if let Some(ref id) = s.maybe_id { + let wake_index = Agenda::::decode_len(wake).unwrap_or(0); + Lookup::::insert(id, (wake, wake_index as u32)); + } + Agenda::::append(wake, Some(s)); + } + } total_weight } } @@ -352,7 +461,7 @@ pub mod pallet { when: T::BlockNumber, maybe_periodic: Option>, priority: schedule::Priority, - call: Box<::Call>, + call: Box>, ) -> DispatchResult { T::ScheduleOrigin::ensure_origin(origin.clone())?; let origin = ::Origin::from(origin); @@ -383,7 +492,7 @@ pub mod pallet { when: T::BlockNumber, maybe_periodic: Option>, priority: schedule::Priority, - call: Box<::Call>, + call: Box>, ) -> DispatchResult { T::ScheduleOrigin::ensure_origin(origin.clone())?; let origin = ::Origin::from(origin); @@ -418,7 +527,7 @@ pub mod pallet { after: T::BlockNumber, maybe_periodic: Option>, priority: schedule::Priority, - call: Box<::Call>, + call: Box>, ) -> DispatchResult { T::ScheduleOrigin::ensure_origin(origin.clone())?; let origin = ::Origin::from(origin); @@ -444,7 +553,7 @@ pub mod pallet { after: T::BlockNumber, maybe_periodic: Option>, priority: schedule::Priority, - call: Box<::Call>, + call: Box>, ) -> DispatchResult { T::ScheduleOrigin::ensure_origin(origin.clone())?; let origin = ::Origin::from(origin); @@ -462,11 +571,11 @@ pub mod pallet { } impl Pallet { - /// Migrate storage format from V1 to V2. + /// Migrate storage format from V1 to V3. /// Return true if migration is performed. - pub fn migrate_v1_to_t2() -> bool { + pub fn migrate_v1_to_v3() -> bool { if StorageVersion::::get() == Releases::V1 { - StorageVersion::::put(Releases::V2); + StorageVersion::::put(Releases::V3); Agenda::::translate::< Vec::Call, T::BlockNumber>>>, @@ -476,10 +585,10 @@ impl Pallet { agenda .into_iter() .map(|schedule| { - schedule.map(|schedule| ScheduledV2 { + schedule.map(|schedule| ScheduledV3 { maybe_id: schedule.maybe_id, priority: schedule.priority, - call: schedule.call, + call: schedule.call.into(), maybe_periodic: schedule.maybe_periodic, origin: system::RawOrigin::Root.into(), _phantom: Default::default(), @@ -495,10 +604,58 @@ impl Pallet { } } + /// Migrate storage format from V2 to V3. + /// Return true if migration is performed. + pub fn migrate_v2_to_v3() -> Weight { + if StorageVersion::::get() == Releases::V2 { + StorageVersion::::put(Releases::V3); + + let mut weight = T::DbWeight::get().reads_writes(1, 1); + + Agenda::::translate::>>, _>(|_, agenda| { + Some( + agenda + .into_iter() + .map(|schedule| { + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); + schedule.map(|schedule| ScheduledV3 { + maybe_id: schedule.maybe_id, + priority: schedule.priority, + call: schedule.call.into(), + maybe_periodic: schedule.maybe_periodic, + origin: system::RawOrigin::Root.into(), + _phantom: Default::default(), + }) + }) + .collect::>(), + ) + }); + + weight + } else { + 0 + } + } + + #[cfg(feature = "try-runtime")] + pub fn pre_migrate_to_v3() -> Result<(), &'static str> { + assert!(StorageVersion::::get() < Releases::V3); + Ok(()) + } + + #[cfg(feature = "try-runtime")] + pub fn post_migrate_to_v3() -> Result<(), &'static str> { + assert!(StorageVersion::::get() == Releases::V3); + for k in Agenda::::iter_keys() { + let _ = Agenda::::try_get(k).map_err(|()| "Invalid item in Agenda")?; + } + Ok(()) + } + /// Helper to migrate scheduler when the pallet origin type has changed. pub fn migrate_origin + codec::Decode>() { Agenda::::translate::< - Vec::Call, T::BlockNumber, OldOrigin, T::AccountId>>>, + Vec, T::BlockNumber, OldOrigin, T::AccountId>>>, _, >(|_, agenda| { Some( @@ -541,9 +698,10 @@ impl Pallet { maybe_periodic: Option>, priority: schedule::Priority, origin: T::PalletsOrigin, - call: ::Call, + call: CallOrHashOf, ) -> Result, DispatchError> { let when = Self::resolve_time(when)?; + call.ensure_requested::(); // sanitize maybe_periodic let maybe_periodic = maybe_periodic @@ -593,6 +751,7 @@ impl Pallet { ) })?; if let Some(s) = scheduled { + s.call.ensure_unrequested::(); if let Some(id) = s.maybe_id { Lookup::::remove(id); } @@ -633,7 +792,7 @@ impl Pallet { maybe_periodic: Option>, priority: schedule::Priority, origin: T::PalletsOrigin, - call: ::Call, + call: CallOrHashOf, ) -> Result, DispatchError> { // ensure id it is unique if Lookup::::contains_key(&id) { @@ -642,6 +801,8 @@ impl Pallet { let when = Self::resolve_time(when)?; + call.ensure_requested::(); + // sanitize maybe_periodic let maybe_periodic = maybe_periodic .filter(|p| p.1 > 1 && !p.0.is_zero()) @@ -685,6 +846,7 @@ impl Pallet { ) { return Err(BadOrigin.into()) } + s.call.ensure_unrequested::(); } *s = None; } @@ -733,17 +895,18 @@ impl Pallet { } } -impl schedule::Anon::Call, T::PalletsOrigin> +impl schedule::v2::Anon::Call, T::PalletsOrigin> for Pallet { type Address = TaskAddress; + type Hash = T::Hash; fn schedule( when: DispatchTime, maybe_periodic: Option>, priority: schedule::Priority, origin: T::PalletsOrigin, - call: ::Call, + call: CallOrHashOf, ) -> Result { Self::do_schedule(when, maybe_periodic, priority, origin, call) } @@ -764,10 +927,11 @@ impl schedule::Anon::Call, T::PalletsOr } } -impl schedule::Named::Call, T::PalletsOrigin> +impl schedule::v2::Named::Call, T::PalletsOrigin> for Pallet { type Address = TaskAddress; + type Hash = T::Hash; fn schedule_named( id: Vec, @@ -775,7 +939,7 @@ impl schedule::Named::Call, T::PalletsO maybe_periodic: Option>, priority: schedule::Priority, origin: T::PalletsOrigin, - call: ::Call, + call: CallOrHashOf, ) -> Result { Self::do_schedule_named(id, when, maybe_periodic, priority, origin, call).map_err(|_| ()) } @@ -797,1022 +961,3 @@ impl schedule::Named::Call, T::PalletsO .ok_or(()) } } - -#[cfg(test)] -mod tests { - use super::*; - - use crate as scheduler; - use frame_support::{ - assert_err, assert_noop, assert_ok, ord_parameter_types, parameter_types, - traits::{Contains, EnsureOneOf, EqualPrivilegeOnly, OnFinalize, OnInitialize}, - weights::constants::RocksDbWeight, - Hashable, - }; - use frame_system::{EnsureRoot, EnsureSignedBy}; - use sp_core::H256; - use sp_runtime::{ - testing::Header, - traits::{BlakeTwo256, IdentityLookup}, - Perbill, - }; - use substrate_test_utils::assert_eq_uvec; - - // Logger module to track execution. - #[frame_support::pallet] - pub mod logger { - use super::*; - use frame_support::pallet_prelude::*; - use frame_system::pallet_prelude::*; - use std::cell::RefCell; - - thread_local! { - static LOG: RefCell> = RefCell::new(Vec::new()); - } - pub fn log() -> Vec<(OriginCaller, u32)> { - LOG.with(|log| log.borrow().clone()) - } - - #[pallet::pallet] - #[pallet::generate_store(pub(super) trait Store)] - pub struct Pallet(PhantomData); - - #[pallet::hooks] - impl Hooks> for Pallet {} - - #[pallet::config] - pub trait Config: frame_system::Config { - type Event: From> + IsType<::Event>; - } - - #[pallet::event] - #[pallet::generate_deposit(pub(super) fn deposit_event)] - pub enum Event { - Logged(u32, Weight), - } - - #[pallet::call] - impl Pallet - where - ::Origin: OriginTrait, - { - #[pallet::weight(*weight)] - pub fn log(origin: OriginFor, i: u32, weight: Weight) -> DispatchResult { - Self::deposit_event(Event::Logged(i, weight)); - LOG.with(|log| { - log.borrow_mut().push((origin.caller().clone(), i)); - }); - Ok(()) - } - - #[pallet::weight(*weight)] - pub fn log_without_filter( - origin: OriginFor, - i: u32, - weight: Weight, - ) -> DispatchResult { - Self::deposit_event(Event::Logged(i, weight)); - LOG.with(|log| { - log.borrow_mut().push((origin.caller().clone(), i)); - }); - Ok(()) - } - } - } - - type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; - type Block = frame_system::mocking::MockBlock; - - frame_support::construct_runtime!( - pub enum Test where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic, - { - System: frame_system::{Pallet, Call, Config, Storage, Event}, - Logger: logger::{Pallet, Call, Event}, - Scheduler: scheduler::{Pallet, Call, Storage, Event}, - } - ); - - // Scheduler must dispatch with root and no filter, this tests base filter is indeed not used. - pub struct BaseFilter; - impl Contains for BaseFilter { - fn contains(call: &Call) -> bool { - !matches!(call, Call::Logger(LoggerCall::log { .. })) - } - } - - parameter_types! { - pub const BlockHashCount: u64 = 250; - pub BlockWeights: frame_system::limits::BlockWeights = - frame_system::limits::BlockWeights::simple_max(2_000_000_000_000); - } - impl system::Config for Test { - type BaseCallFilter = BaseFilter; - type BlockWeights = (); - type BlockLength = (); - type DbWeight = RocksDbWeight; - type Origin = Origin; - type Call = Call; - type Index = u64; - type BlockNumber = u64; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type Event = Event; - type BlockHashCount = BlockHashCount; - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = (); - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = (); - type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; - } - impl logger::Config for Test { - type Event = Event; - } - parameter_types! { - pub MaximumSchedulerWeight: Weight = Perbill::from_percent(80) * BlockWeights::get().max_block; - pub const MaxScheduledPerBlock: u32 = 10; - } - ord_parameter_types! { - pub const One: u64 = 1; - } - - impl Config for Test { - type Event = Event; - type Origin = Origin; - type PalletsOrigin = OriginCaller; - type Call = Call; - type MaximumWeight = MaximumSchedulerWeight; - type ScheduleOrigin = EnsureOneOf, EnsureSignedBy>; - type MaxScheduledPerBlock = MaxScheduledPerBlock; - type WeightInfo = (); - type OriginPrivilegeCmp = EqualPrivilegeOnly; - } - - pub type LoggerCall = logger::Call; - - pub fn new_test_ext() -> sp_io::TestExternalities { - let t = system::GenesisConfig::default().build_storage::().unwrap(); - t.into() - } - - fn run_to_block(n: u64) { - while System::block_number() < n { - Scheduler::on_finalize(System::block_number()); - System::set_block_number(System::block_number() + 1); - Scheduler::on_initialize(System::block_number()); - } - } - - fn root() -> OriginCaller { - system::RawOrigin::Root.into() - } - - #[test] - fn basic_scheduling_works() { - new_test_ext().execute_with(|| { - let call = Call::Logger(LoggerCall::log { i: 42, weight: 1000 }); - assert!(!::BaseCallFilter::contains(&call)); - assert_ok!(Scheduler::do_schedule(DispatchTime::At(4), None, 127, root(), call)); - run_to_block(3); - assert!(logger::log().is_empty()); - run_to_block(4); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - run_to_block(100); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - }); - } - - #[test] - fn schedule_after_works() { - new_test_ext().execute_with(|| { - run_to_block(2); - let call = Call::Logger(LoggerCall::log { i: 42, weight: 1000 }); - assert!(!::BaseCallFilter::contains(&call)); - // This will schedule the call 3 blocks after the next block... so block 3 + 3 = 6 - assert_ok!(Scheduler::do_schedule(DispatchTime::After(3), None, 127, root(), call)); - run_to_block(5); - assert!(logger::log().is_empty()); - run_to_block(6); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - run_to_block(100); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - }); - } - - #[test] - fn schedule_after_zero_works() { - new_test_ext().execute_with(|| { - run_to_block(2); - let call = Call::Logger(LoggerCall::log { i: 42, weight: 1000 }); - assert!(!::BaseCallFilter::contains(&call)); - assert_ok!(Scheduler::do_schedule(DispatchTime::After(0), None, 127, root(), call)); - // Will trigger on the next block. - run_to_block(3); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - run_to_block(100); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - }); - } - - #[test] - fn periodic_scheduling_works() { - new_test_ext().execute_with(|| { - // at #4, every 3 blocks, 3 times. - assert_ok!(Scheduler::do_schedule( - DispatchTime::At(4), - Some((3, 3)), - 127, - root(), - Call::Logger(logger::Call::log { i: 42, weight: 1000 }) - )); - run_to_block(3); - assert!(logger::log().is_empty()); - run_to_block(4); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - run_to_block(6); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - run_to_block(7); - assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 42u32)]); - run_to_block(9); - assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 42u32)]); - run_to_block(10); - assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 42u32), (root(), 42u32)]); - run_to_block(100); - assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 42u32), (root(), 42u32)]); - }); - } - - #[test] - fn reschedule_works() { - new_test_ext().execute_with(|| { - let call = Call::Logger(LoggerCall::log { i: 42, weight: 1000 }); - assert!(!::BaseCallFilter::contains(&call)); - assert_eq!( - Scheduler::do_schedule(DispatchTime::At(4), None, 127, root(), call).unwrap(), - (4, 0) - ); - - run_to_block(3); - assert!(logger::log().is_empty()); - - assert_eq!(Scheduler::do_reschedule((4, 0), DispatchTime::At(6)).unwrap(), (6, 0)); - - assert_noop!( - Scheduler::do_reschedule((6, 0), DispatchTime::At(6)), - Error::::RescheduleNoChange - ); - - run_to_block(4); - assert!(logger::log().is_empty()); - - run_to_block(6); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - - run_to_block(100); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - }); - } - - #[test] - fn reschedule_named_works() { - new_test_ext().execute_with(|| { - let call = Call::Logger(LoggerCall::log { i: 42, weight: 1000 }); - assert!(!::BaseCallFilter::contains(&call)); - assert_eq!( - Scheduler::do_schedule_named( - 1u32.encode(), - DispatchTime::At(4), - None, - 127, - root(), - call - ) - .unwrap(), - (4, 0) - ); - - run_to_block(3); - assert!(logger::log().is_empty()); - - assert_eq!( - Scheduler::do_reschedule_named(1u32.encode(), DispatchTime::At(6)).unwrap(), - (6, 0) - ); - - assert_noop!( - Scheduler::do_reschedule_named(1u32.encode(), DispatchTime::At(6)), - Error::::RescheduleNoChange - ); - - run_to_block(4); - assert!(logger::log().is_empty()); - - run_to_block(6); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - - run_to_block(100); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - }); - } - - #[test] - fn reschedule_named_perodic_works() { - new_test_ext().execute_with(|| { - let call = Call::Logger(LoggerCall::log { i: 42, weight: 1000 }); - assert!(!::BaseCallFilter::contains(&call)); - assert_eq!( - Scheduler::do_schedule_named( - 1u32.encode(), - DispatchTime::At(4), - Some((3, 3)), - 127, - root(), - call - ) - .unwrap(), - (4, 0) - ); - - run_to_block(3); - assert!(logger::log().is_empty()); - - assert_eq!( - Scheduler::do_reschedule_named(1u32.encode(), DispatchTime::At(5)).unwrap(), - (5, 0) - ); - assert_eq!( - Scheduler::do_reschedule_named(1u32.encode(), DispatchTime::At(6)).unwrap(), - (6, 0) - ); - - run_to_block(5); - assert!(logger::log().is_empty()); - - run_to_block(6); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - - assert_eq!( - Scheduler::do_reschedule_named(1u32.encode(), DispatchTime::At(10)).unwrap(), - (10, 0) - ); - - run_to_block(9); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - - run_to_block(10); - assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 42u32)]); - - run_to_block(13); - assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 42u32), (root(), 42u32)]); - - run_to_block(100); - assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 42u32), (root(), 42u32)]); - }); - } - - #[test] - fn cancel_named_scheduling_works_with_normal_cancel() { - new_test_ext().execute_with(|| { - // at #4. - Scheduler::do_schedule_named( - 1u32.encode(), - DispatchTime::At(4), - None, - 127, - root(), - Call::Logger(LoggerCall::log { i: 69, weight: 1000 }), - ) - .unwrap(); - let i = Scheduler::do_schedule( - DispatchTime::At(4), - None, - 127, - root(), - Call::Logger(LoggerCall::log { i: 42, weight: 1000 }), - ) - .unwrap(); - run_to_block(3); - assert!(logger::log().is_empty()); - assert_ok!(Scheduler::do_cancel_named(None, 1u32.encode())); - assert_ok!(Scheduler::do_cancel(None, i)); - run_to_block(100); - assert!(logger::log().is_empty()); - }); - } - - #[test] - fn cancel_named_periodic_scheduling_works() { - new_test_ext().execute_with(|| { - // at #4, every 3 blocks, 3 times. - Scheduler::do_schedule_named( - 1u32.encode(), - DispatchTime::At(4), - Some((3, 3)), - 127, - root(), - Call::Logger(LoggerCall::log { i: 42, weight: 1000 }), - ) - .unwrap(); - // same id results in error. - assert!(Scheduler::do_schedule_named( - 1u32.encode(), - DispatchTime::At(4), - None, - 127, - root(), - Call::Logger(LoggerCall::log { i: 69, weight: 1000 }) - ) - .is_err()); - // different id is ok. - Scheduler::do_schedule_named( - 2u32.encode(), - DispatchTime::At(8), - None, - 127, - root(), - Call::Logger(LoggerCall::log { i: 69, weight: 1000 }), - ) - .unwrap(); - run_to_block(3); - assert!(logger::log().is_empty()); - run_to_block(4); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - run_to_block(6); - assert_ok!(Scheduler::do_cancel_named(None, 1u32.encode())); - run_to_block(100); - assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 69u32)]); - }); - } - - #[test] - fn scheduler_respects_weight_limits() { - new_test_ext().execute_with(|| { - assert_ok!(Scheduler::do_schedule( - DispatchTime::At(4), - None, - 127, - root(), - Call::Logger(LoggerCall::log { i: 42, weight: MaximumSchedulerWeight::get() / 2 }) - )); - assert_ok!(Scheduler::do_schedule( - DispatchTime::At(4), - None, - 127, - root(), - Call::Logger(LoggerCall::log { i: 69, weight: MaximumSchedulerWeight::get() / 2 }) - )); - // 69 and 42 do not fit together - run_to_block(4); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - run_to_block(5); - assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 69u32)]); - }); - } - - #[test] - fn scheduler_respects_hard_deadlines_more() { - new_test_ext().execute_with(|| { - assert_ok!(Scheduler::do_schedule( - DispatchTime::At(4), - None, - 0, - root(), - Call::Logger(LoggerCall::log { i: 42, weight: MaximumSchedulerWeight::get() / 2 }) - )); - assert_ok!(Scheduler::do_schedule( - DispatchTime::At(4), - None, - 0, - root(), - Call::Logger(LoggerCall::log { i: 69, weight: MaximumSchedulerWeight::get() / 2 }) - )); - // With base weights, 69 and 42 should not fit together, but do because of hard - // deadlines - run_to_block(4); - assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 69u32)]); - }); - } - - #[test] - fn scheduler_respects_priority_ordering() { - new_test_ext().execute_with(|| { - assert_ok!(Scheduler::do_schedule( - DispatchTime::At(4), - None, - 1, - root(), - Call::Logger(LoggerCall::log { i: 42, weight: MaximumSchedulerWeight::get() / 2 }) - )); - assert_ok!(Scheduler::do_schedule( - DispatchTime::At(4), - None, - 0, - root(), - Call::Logger(LoggerCall::log { i: 69, weight: MaximumSchedulerWeight::get() / 2 }) - )); - run_to_block(4); - assert_eq!(logger::log(), vec![(root(), 69u32), (root(), 42u32)]); - }); - } - - #[test] - fn scheduler_respects_priority_ordering_with_soft_deadlines() { - new_test_ext().execute_with(|| { - assert_ok!(Scheduler::do_schedule( - DispatchTime::At(4), - None, - 255, - root(), - Call::Logger(LoggerCall::log { i: 42, weight: MaximumSchedulerWeight::get() / 3 }) - )); - assert_ok!(Scheduler::do_schedule( - DispatchTime::At(4), - None, - 127, - root(), - Call::Logger(LoggerCall::log { i: 69, weight: MaximumSchedulerWeight::get() / 2 }) - )); - assert_ok!(Scheduler::do_schedule( - DispatchTime::At(4), - None, - 126, - root(), - Call::Logger(LoggerCall::log { - i: 2600, - weight: MaximumSchedulerWeight::get() / 2 - }) - )); - - // 2600 does not fit with 69 or 42, but has higher priority, so will go through - run_to_block(4); - assert_eq!(logger::log(), vec![(root(), 2600u32)]); - // 69 and 42 fit together - run_to_block(5); - assert_eq!(logger::log(), vec![(root(), 2600u32), (root(), 69u32), (root(), 42u32)]); - }); - } - - #[test] - fn on_initialize_weight_is_correct() { - new_test_ext().execute_with(|| { - let base_weight: Weight = - ::DbWeight::get().reads_writes(1, 2); - let base_multiplier = 0; - let named_multiplier = ::DbWeight::get().writes(1); - let periodic_multiplier = - ::DbWeight::get().reads_writes(1, 1); - - // Named - assert_ok!(Scheduler::do_schedule_named( - 1u32.encode(), - DispatchTime::At(1), - None, - 255, - root(), - Call::Logger(LoggerCall::log { i: 3, weight: MaximumSchedulerWeight::get() / 3 }) - )); - // Anon Periodic - assert_ok!(Scheduler::do_schedule( - DispatchTime::At(1), - Some((1000, 3)), - 128, - root(), - Call::Logger(LoggerCall::log { i: 42, weight: MaximumSchedulerWeight::get() / 3 }) - )); - // Anon - assert_ok!(Scheduler::do_schedule( - DispatchTime::At(1), - None, - 127, - root(), - Call::Logger(LoggerCall::log { i: 69, weight: MaximumSchedulerWeight::get() / 2 }) - )); - // Named Periodic - assert_ok!(Scheduler::do_schedule_named( - 2u32.encode(), - DispatchTime::At(1), - Some((1000, 3)), - 126, - root(), - Call::Logger(LoggerCall::log { - i: 2600, - weight: MaximumSchedulerWeight::get() / 2 - }) - )); - - // Will include the named periodic only - let actual_weight = Scheduler::on_initialize(1); - let call_weight = MaximumSchedulerWeight::get() / 2; - assert_eq!( - actual_weight, - call_weight + - base_weight + base_multiplier + - named_multiplier + periodic_multiplier - ); - assert_eq!(logger::log(), vec![(root(), 2600u32)]); - - // Will include anon and anon periodic - let actual_weight = Scheduler::on_initialize(2); - let call_weight = MaximumSchedulerWeight::get() / 2 + MaximumSchedulerWeight::get() / 3; - assert_eq!( - actual_weight, - call_weight + base_weight + base_multiplier * 2 + periodic_multiplier - ); - assert_eq!(logger::log(), vec![(root(), 2600u32), (root(), 69u32), (root(), 42u32)]); - - // Will include named only - let actual_weight = Scheduler::on_initialize(3); - let call_weight = MaximumSchedulerWeight::get() / 3; - assert_eq!( - actual_weight, - call_weight + base_weight + base_multiplier + named_multiplier - ); - assert_eq!( - logger::log(), - vec![(root(), 2600u32), (root(), 69u32), (root(), 42u32), (root(), 3u32)] - ); - - // Will contain none - let actual_weight = Scheduler::on_initialize(4); - assert_eq!(actual_weight, 0); - }); - } - - #[test] - fn root_calls_works() { - new_test_ext().execute_with(|| { - let call = Box::new(Call::Logger(LoggerCall::log { i: 69, weight: 1000 })); - let call2 = Box::new(Call::Logger(LoggerCall::log { i: 42, weight: 1000 })); - assert_ok!(Scheduler::schedule_named( - Origin::root(), - 1u32.encode(), - 4, - None, - 127, - call - )); - assert_ok!(Scheduler::schedule(Origin::root(), 4, None, 127, call2)); - run_to_block(3); - // Scheduled calls are in the agenda. - assert_eq!(Agenda::::get(4).len(), 2); - assert!(logger::log().is_empty()); - assert_ok!(Scheduler::cancel_named(Origin::root(), 1u32.encode())); - assert_ok!(Scheduler::cancel(Origin::root(), 4, 1)); - // Scheduled calls are made NONE, so should not effect state - run_to_block(100); - assert!(logger::log().is_empty()); - }); - } - - #[test] - fn fails_to_schedule_task_in_the_past() { - new_test_ext().execute_with(|| { - run_to_block(3); - - let call = Box::new(Call::Logger(LoggerCall::log { i: 69, weight: 1000 })); - let call2 = Box::new(Call::Logger(LoggerCall::log { i: 42, weight: 1000 })); - - assert_err!( - Scheduler::schedule_named(Origin::root(), 1u32.encode(), 2, None, 127, call), - Error::::TargetBlockNumberInPast, - ); - - assert_err!( - Scheduler::schedule(Origin::root(), 2, None, 127, call2.clone()), - Error::::TargetBlockNumberInPast, - ); - - assert_err!( - Scheduler::schedule(Origin::root(), 3, None, 127, call2), - Error::::TargetBlockNumberInPast, - ); - }); - } - - #[test] - fn should_use_orign() { - new_test_ext().execute_with(|| { - let call = Box::new(Call::Logger(LoggerCall::log { i: 69, weight: 1000 })); - let call2 = Box::new(Call::Logger(LoggerCall::log { i: 42, weight: 1000 })); - assert_ok!(Scheduler::schedule_named( - system::RawOrigin::Signed(1).into(), - 1u32.encode(), - 4, - None, - 127, - call - )); - assert_ok!(Scheduler::schedule( - system::RawOrigin::Signed(1).into(), - 4, - None, - 127, - call2 - )); - run_to_block(3); - // Scheduled calls are in the agenda. - assert_eq!(Agenda::::get(4).len(), 2); - assert!(logger::log().is_empty()); - assert_ok!(Scheduler::cancel_named(system::RawOrigin::Signed(1).into(), 1u32.encode())); - assert_ok!(Scheduler::cancel(system::RawOrigin::Signed(1).into(), 4, 1)); - // Scheduled calls are made NONE, so should not effect state - run_to_block(100); - assert!(logger::log().is_empty()); - }); - } - - #[test] - fn should_check_orign() { - new_test_ext().execute_with(|| { - let call = Box::new(Call::Logger(LoggerCall::log { i: 69, weight: 1000 })); - let call2 = Box::new(Call::Logger(LoggerCall::log { i: 42, weight: 1000 })); - assert_noop!( - Scheduler::schedule_named( - system::RawOrigin::Signed(2).into(), - 1u32.encode(), - 4, - None, - 127, - call - ), - BadOrigin - ); - assert_noop!( - Scheduler::schedule(system::RawOrigin::Signed(2).into(), 4, None, 127, call2), - BadOrigin - ); - }); - } - - #[test] - fn should_check_orign_for_cancel() { - new_test_ext().execute_with(|| { - let call = - Box::new(Call::Logger(LoggerCall::log_without_filter { i: 69, weight: 1000 })); - let call2 = - Box::new(Call::Logger(LoggerCall::log_without_filter { i: 42, weight: 1000 })); - assert_ok!(Scheduler::schedule_named( - system::RawOrigin::Signed(1).into(), - 1u32.encode(), - 4, - None, - 127, - call - )); - assert_ok!(Scheduler::schedule( - system::RawOrigin::Signed(1).into(), - 4, - None, - 127, - call2 - )); - run_to_block(3); - // Scheduled calls are in the agenda. - assert_eq!(Agenda::::get(4).len(), 2); - assert!(logger::log().is_empty()); - assert_noop!( - Scheduler::cancel_named(system::RawOrigin::Signed(2).into(), 1u32.encode()), - BadOrigin - ); - assert_noop!(Scheduler::cancel(system::RawOrigin::Signed(2).into(), 4, 1), BadOrigin); - assert_noop!( - Scheduler::cancel_named(system::RawOrigin::Root.into(), 1u32.encode()), - BadOrigin - ); - assert_noop!(Scheduler::cancel(system::RawOrigin::Root.into(), 4, 1), BadOrigin); - run_to_block(5); - assert_eq!( - logger::log(), - vec![ - (system::RawOrigin::Signed(1).into(), 69u32), - (system::RawOrigin::Signed(1).into(), 42u32) - ] - ); - }); - } - - #[test] - fn migration_to_v2_works() { - new_test_ext().execute_with(|| { - for i in 0..3u64 { - let k = i.twox_64_concat(); - let old = vec![ - Some(ScheduledV1 { - maybe_id: None, - priority: i as u8 + 10, - call: Call::Logger(LoggerCall::log { i: 96, weight: 100 }), - maybe_periodic: None, - }), - None, - Some(ScheduledV1 { - maybe_id: Some(b"test".to_vec()), - priority: 123, - call: Call::Logger(LoggerCall::log { i: 69, weight: 1000 }), - maybe_periodic: Some((456u64, 10)), - }), - ]; - frame_support::migration::put_storage_value(b"Scheduler", b"Agenda", &k, old); - } - - assert_eq!(StorageVersion::::get(), Releases::V1); - - assert!(Scheduler::migrate_v1_to_t2()); - - assert_eq_uvec!( - Agenda::::iter().collect::>(), - vec![ - ( - 0, - vec![ - Some(ScheduledV2 { - maybe_id: None, - priority: 10, - call: Call::Logger(LoggerCall::log { i: 96, weight: 100 }), - maybe_periodic: None, - origin: root(), - _phantom: PhantomData::::default(), - }), - None, - Some(ScheduledV2 { - maybe_id: Some(b"test".to_vec()), - priority: 123, - call: Call::Logger(LoggerCall::log { i: 69, weight: 1000 }), - maybe_periodic: Some((456u64, 10)), - origin: root(), - _phantom: PhantomData::::default(), - }), - ] - ), - ( - 1, - vec![ - Some(ScheduledV2 { - maybe_id: None, - priority: 11, - call: Call::Logger(LoggerCall::log { i: 96, weight: 100 }), - maybe_periodic: None, - origin: root(), - _phantom: PhantomData::::default(), - }), - None, - Some(ScheduledV2 { - maybe_id: Some(b"test".to_vec()), - priority: 123, - call: Call::Logger(LoggerCall::log { i: 69, weight: 1000 }), - maybe_periodic: Some((456u64, 10)), - origin: root(), - _phantom: PhantomData::::default(), - }), - ] - ), - ( - 2, - vec![ - Some(ScheduledV2 { - maybe_id: None, - priority: 12, - call: Call::Logger(LoggerCall::log { i: 96, weight: 100 }), - maybe_periodic: None, - origin: root(), - _phantom: PhantomData::::default(), - }), - None, - Some(ScheduledV2 { - maybe_id: Some(b"test".to_vec()), - priority: 123, - call: Call::Logger(LoggerCall::log { i: 69, weight: 1000 }), - maybe_periodic: Some((456u64, 10)), - origin: root(), - _phantom: PhantomData::::default(), - }), - ] - ) - ] - ); - - assert_eq!(StorageVersion::::get(), Releases::V2); - }); - } - - #[test] - fn test_migrate_origin() { - new_test_ext().execute_with(|| { - for i in 0..3u64 { - let k = i.twox_64_concat(); - let old: Vec>> = vec![ - Some(Scheduled { - maybe_id: None, - priority: i as u8 + 10, - call: Call::Logger(LoggerCall::log { i: 96, weight: 100 }), - origin: 3u32, - maybe_periodic: None, - _phantom: Default::default(), - }), - None, - Some(Scheduled { - maybe_id: Some(b"test".to_vec()), - priority: 123, - origin: 2u32, - call: Call::Logger(LoggerCall::log { i: 69, weight: 1000 }), - maybe_periodic: Some((456u64, 10)), - _phantom: Default::default(), - }), - ]; - frame_support::migration::put_storage_value(b"Scheduler", b"Agenda", &k, old); - } - - impl Into for u32 { - fn into(self) -> OriginCaller { - match self { - 3u32 => system::RawOrigin::Root.into(), - 2u32 => system::RawOrigin::None.into(), - _ => unreachable!("test make no use of it"), - } - } - } - - Scheduler::migrate_origin::(); - - assert_eq_uvec!( - Agenda::::iter().collect::>(), - vec![ - ( - 0, - vec![ - Some(ScheduledV2::<_, _, OriginCaller, u64> { - maybe_id: None, - priority: 10, - call: Call::Logger(LoggerCall::log { i: 96, weight: 100 }), - maybe_periodic: None, - origin: system::RawOrigin::Root.into(), - _phantom: PhantomData::::default(), - }), - None, - Some(ScheduledV2 { - maybe_id: Some(b"test".to_vec()), - priority: 123, - call: Call::Logger(LoggerCall::log { i: 69, weight: 1000 }), - maybe_periodic: Some((456u64, 10)), - origin: system::RawOrigin::None.into(), - _phantom: PhantomData::::default(), - }), - ] - ), - ( - 1, - vec![ - Some(ScheduledV2 { - maybe_id: None, - priority: 11, - call: Call::Logger(LoggerCall::log { i: 96, weight: 100 }), - maybe_periodic: None, - origin: system::RawOrigin::Root.into(), - _phantom: PhantomData::::default(), - }), - None, - Some(ScheduledV2 { - maybe_id: Some(b"test".to_vec()), - priority: 123, - call: Call::Logger(LoggerCall::log { i: 69, weight: 1000 }), - maybe_periodic: Some((456u64, 10)), - origin: system::RawOrigin::None.into(), - _phantom: PhantomData::::default(), - }), - ] - ), - ( - 2, - vec![ - Some(ScheduledV2 { - maybe_id: None, - priority: 12, - call: Call::Logger(LoggerCall::log { i: 96, weight: 100 }), - maybe_periodic: None, - origin: system::RawOrigin::Root.into(), - _phantom: PhantomData::::default(), - }), - None, - Some(ScheduledV2 { - maybe_id: Some(b"test".to_vec()), - priority: 123, - call: Call::Logger(LoggerCall::log { i: 69, weight: 1000 }), - maybe_periodic: Some((456u64, 10)), - origin: system::RawOrigin::None.into(), - _phantom: PhantomData::::default(), - }), - ] - ) - ] - ); - }); - } -} diff --git a/frame/scheduler/src/mock.rs b/frame/scheduler/src/mock.rs new file mode 100644 index 000000000000..535e91937e4d --- /dev/null +++ b/frame/scheduler/src/mock.rs @@ -0,0 +1,203 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2021 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. + +//! # Scheduler test environment. + +use super::*; + +use crate as scheduler; +use frame_support::{ + ord_parameter_types, parameter_types, + traits::{Contains, EnsureOneOf, EqualPrivilegeOnly, OnFinalize, OnInitialize}, + weights::constants::RocksDbWeight, +}; +use frame_system::{EnsureRoot, EnsureSignedBy}; +use sp_core::H256; +use sp_runtime::{ + testing::Header, + traits::{BlakeTwo256, IdentityLookup}, + Perbill, +}; + +// Logger module to track execution. +#[frame_support::pallet] +pub mod logger { + use super::*; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + use std::cell::RefCell; + + thread_local! { + static LOG: RefCell> = RefCell::new(Vec::new()); + } + pub fn log() -> Vec<(OriginCaller, u32)> { + LOG.with(|log| log.borrow().clone()) + } + + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet(PhantomData); + + #[pallet::hooks] + impl Hooks> for Pallet {} + + #[pallet::config] + pub trait Config: frame_system::Config { + type Event: From> + IsType<::Event>; + } + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + Logged(u32, Weight), + } + + #[pallet::call] + impl Pallet + where + ::Origin: OriginTrait, + { + #[pallet::weight(*weight)] + pub fn log(origin: OriginFor, i: u32, weight: Weight) -> DispatchResult { + Self::deposit_event(Event::Logged(i, weight)); + LOG.with(|log| { + log.borrow_mut().push((origin.caller().clone(), i)); + }); + Ok(()) + } + + #[pallet::weight(*weight)] + pub fn log_without_filter(origin: OriginFor, i: u32, weight: Weight) -> DispatchResult { + Self::deposit_event(Event::Logged(i, weight)); + LOG.with(|log| { + log.borrow_mut().push((origin.caller().clone(), i)); + }); + Ok(()) + } + } +} + +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlock; + +frame_support::construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Logger: logger::{Pallet, Call, Event}, + Scheduler: scheduler::{Pallet, Call, Storage, Event}, + Preimage: pallet_preimage::{Pallet, Call, Storage, Event}, + } +); + +// Scheduler must dispatch with root and no filter, this tests base filter is indeed not used. +pub struct BaseFilter; +impl Contains for BaseFilter { + fn contains(call: &Call) -> bool { + !matches!(call, Call::Logger(LoggerCall::log { .. })) + } +} + +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub BlockWeights: frame_system::limits::BlockWeights = + frame_system::limits::BlockWeights::simple_max(2_000_000_000_000); +} +impl system::Config for Test { + type BaseCallFilter = BaseFilter; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = RocksDbWeight; + type Origin = Origin; + type Call = Call; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = Event; + type BlockHashCount = BlockHashCount; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; +} +impl logger::Config for Test { + type Event = Event; +} +parameter_types! { + pub MaximumSchedulerWeight: Weight = Perbill::from_percent(80) * BlockWeights::get().max_block; + pub const MaxScheduledPerBlock: u32 = 10; + pub const MaxSize: u32 = 1024; + pub const NoPreimagePostponement: Option = Some(2); +} +ord_parameter_types! { + pub const One: u64 = 1; +} + +impl pallet_preimage::Config for Test { + type Event = Event; + type WeightInfo = (); + type Currency = (); + type ManagerOrigin = EnsureRoot; + type MaxSize = MaxSize; + type BaseDeposit = (); + type ByteDeposit = (); +} + +impl Config for Test { + type Event = Event; + type Origin = Origin; + type PalletsOrigin = OriginCaller; + type Call = Call; + type MaximumWeight = MaximumSchedulerWeight; + type ScheduleOrigin = EnsureOneOf, EnsureSignedBy>; + type MaxScheduledPerBlock = MaxScheduledPerBlock; + type WeightInfo = (); + type OriginPrivilegeCmp = EqualPrivilegeOnly; + type PreimageProvider = Preimage; + type NoPreimagePostponement = NoPreimagePostponement; +} + +pub type LoggerCall = logger::Call; + +pub fn new_test_ext() -> sp_io::TestExternalities { + let t = system::GenesisConfig::default().build_storage::().unwrap(); + t.into() +} + +pub fn run_to_block(n: u64) { + while System::block_number() < n { + Scheduler::on_finalize(System::block_number()); + System::set_block_number(System::block_number() + 1); + Scheduler::on_initialize(System::block_number()); + } +} + +pub fn root() -> OriginCaller { + system::RawOrigin::Root.into() +} diff --git a/frame/scheduler/src/tests.rs b/frame/scheduler/src/tests.rs new file mode 100644 index 000000000000..4774cfe38704 --- /dev/null +++ b/frame/scheduler/src/tests.rs @@ -0,0 +1,901 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2021 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. + +//! # Scheduler tests. + +use super::*; +use crate::mock::{logger, new_test_ext, root, run_to_block, Call, LoggerCall, Scheduler, Test, *}; +use frame_support::{ + assert_err, assert_noop, assert_ok, + traits::{Contains, OnInitialize, PreimageProvider}, + Hashable, +}; +use sp_runtime::traits::Hash; +use substrate_test_utils::assert_eq_uvec; + +#[test] +fn basic_scheduling_works() { + new_test_ext().execute_with(|| { + let call = Call::Logger(LoggerCall::log { i: 42, weight: 1000 }); + assert!(!::BaseCallFilter::contains(&call)); + assert_ok!(Scheduler::do_schedule(DispatchTime::At(4), None, 127, root(), call.into())); + run_to_block(3); + assert!(logger::log().is_empty()); + run_to_block(4); + assert_eq!(logger::log(), vec![(root(), 42u32)]); + run_to_block(100); + assert_eq!(logger::log(), vec![(root(), 42u32)]); + }); +} + +#[test] +fn scheduling_with_preimages_works() { + new_test_ext().execute_with(|| { + let call = Call::Logger(LoggerCall::log { i: 42, weight: 1000 }); + let hash = ::Hashing::hash_of(&call); + let hashed = MaybeHashed::Hash(hash.clone()); + assert_ok!(Preimage::note_preimage(Origin::signed(0), call.encode())); + assert_ok!(Scheduler::do_schedule(DispatchTime::At(4), None, 127, root(), hashed)); + assert!(Preimage::preimage_requested(&hash)); + run_to_block(3); + assert!(logger::log().is_empty()); + run_to_block(4); + assert!(!Preimage::have_preimage(&hash)); + assert!(!Preimage::preimage_requested(&hash)); + assert_eq!(logger::log(), vec![(root(), 42u32)]); + run_to_block(100); + assert_eq!(logger::log(), vec![(root(), 42u32)]); + }); +} + +#[test] +fn scheduling_with_preimage_postpones_correctly() { + new_test_ext().execute_with(|| { + let call = Call::Logger(LoggerCall::log { i: 42, weight: 1000 }); + let hash = ::Hashing::hash_of(&call); + let hashed = MaybeHashed::Hash(hash.clone()); + + assert_ok!(Scheduler::do_schedule(DispatchTime::At(4), None, 127, root(), hashed)); + assert!(Preimage::preimage_requested(&hash)); + + run_to_block(4); + // #4 empty due to no preimage + assert!(logger::log().is_empty()); + + // Register preimage. + assert_ok!(Preimage::note_preimage(Origin::signed(0), call.encode())); + + run_to_block(5); + // #5 empty since postponement is 2 blocks. + assert!(logger::log().is_empty()); + + run_to_block(6); + // #6 is good. + assert_eq!(logger::log(), vec![(root(), 42u32)]); + assert!(!Preimage::have_preimage(&hash)); + assert!(!Preimage::preimage_requested(&hash)); + + run_to_block(100); + assert_eq!(logger::log(), vec![(root(), 42u32)]); + }); +} + +#[test] +fn schedule_after_works() { + new_test_ext().execute_with(|| { + run_to_block(2); + let call = Call::Logger(LoggerCall::log { i: 42, weight: 1000 }); + assert!(!::BaseCallFilter::contains(&call)); + // This will schedule the call 3 blocks after the next block... so block 3 + 3 = 6 + assert_ok!(Scheduler::do_schedule(DispatchTime::After(3), None, 127, root(), call.into())); + run_to_block(5); + assert!(logger::log().is_empty()); + run_to_block(6); + assert_eq!(logger::log(), vec![(root(), 42u32)]); + run_to_block(100); + assert_eq!(logger::log(), vec![(root(), 42u32)]); + }); +} + +#[test] +fn schedule_after_zero_works() { + new_test_ext().execute_with(|| { + run_to_block(2); + let call = Call::Logger(LoggerCall::log { i: 42, weight: 1000 }); + assert!(!::BaseCallFilter::contains(&call)); + assert_ok!(Scheduler::do_schedule(DispatchTime::After(0), None, 127, root(), call.into())); + // Will trigger on the next block. + run_to_block(3); + assert_eq!(logger::log(), vec![(root(), 42u32)]); + run_to_block(100); + assert_eq!(logger::log(), vec![(root(), 42u32)]); + }); +} + +#[test] +fn periodic_scheduling_works() { + new_test_ext().execute_with(|| { + // at #4, every 3 blocks, 3 times. + assert_ok!(Scheduler::do_schedule( + DispatchTime::At(4), + Some((3, 3)), + 127, + root(), + Call::Logger(logger::Call::log { i: 42, weight: 1000 }).into() + )); + run_to_block(3); + assert!(logger::log().is_empty()); + run_to_block(4); + assert_eq!(logger::log(), vec![(root(), 42u32)]); + run_to_block(6); + assert_eq!(logger::log(), vec![(root(), 42u32)]); + run_to_block(7); + assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 42u32)]); + run_to_block(9); + assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 42u32)]); + run_to_block(10); + assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 42u32), (root(), 42u32)]); + run_to_block(100); + assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 42u32), (root(), 42u32)]); + }); +} + +#[test] +fn reschedule_works() { + new_test_ext().execute_with(|| { + let call = Call::Logger(LoggerCall::log { i: 42, weight: 1000 }); + assert!(!::BaseCallFilter::contains(&call)); + assert_eq!( + Scheduler::do_schedule(DispatchTime::At(4), None, 127, root(), call.into()).unwrap(), + (4, 0) + ); + + run_to_block(3); + assert!(logger::log().is_empty()); + + assert_eq!(Scheduler::do_reschedule((4, 0), DispatchTime::At(6)).unwrap(), (6, 0)); + + assert_noop!( + Scheduler::do_reschedule((6, 0), DispatchTime::At(6)), + Error::::RescheduleNoChange + ); + + run_to_block(4); + assert!(logger::log().is_empty()); + + run_to_block(6); + assert_eq!(logger::log(), vec![(root(), 42u32)]); + + run_to_block(100); + assert_eq!(logger::log(), vec![(root(), 42u32)]); + }); +} + +#[test] +fn reschedule_named_works() { + new_test_ext().execute_with(|| { + let call = Call::Logger(LoggerCall::log { i: 42, weight: 1000 }); + assert!(!::BaseCallFilter::contains(&call)); + assert_eq!( + Scheduler::do_schedule_named( + 1u32.encode(), + DispatchTime::At(4), + None, + 127, + root(), + call.into(), + ) + .unwrap(), + (4, 0) + ); + + run_to_block(3); + assert!(logger::log().is_empty()); + + assert_eq!( + Scheduler::do_reschedule_named(1u32.encode(), DispatchTime::At(6)).unwrap(), + (6, 0) + ); + + assert_noop!( + Scheduler::do_reschedule_named(1u32.encode(), DispatchTime::At(6)), + Error::::RescheduleNoChange + ); + + run_to_block(4); + assert!(logger::log().is_empty()); + + run_to_block(6); + assert_eq!(logger::log(), vec![(root(), 42u32)]); + + run_to_block(100); + assert_eq!(logger::log(), vec![(root(), 42u32)]); + }); +} + +#[test] +fn reschedule_named_perodic_works() { + new_test_ext().execute_with(|| { + let call = Call::Logger(LoggerCall::log { i: 42, weight: 1000 }); + assert!(!::BaseCallFilter::contains(&call)); + assert_eq!( + Scheduler::do_schedule_named( + 1u32.encode(), + DispatchTime::At(4), + Some((3, 3)), + 127, + root(), + call.into(), + ) + .unwrap(), + (4, 0) + ); + + run_to_block(3); + assert!(logger::log().is_empty()); + + assert_eq!( + Scheduler::do_reschedule_named(1u32.encode(), DispatchTime::At(5)).unwrap(), + (5, 0) + ); + assert_eq!( + Scheduler::do_reschedule_named(1u32.encode(), DispatchTime::At(6)).unwrap(), + (6, 0) + ); + + run_to_block(5); + assert!(logger::log().is_empty()); + + run_to_block(6); + assert_eq!(logger::log(), vec![(root(), 42u32)]); + + assert_eq!( + Scheduler::do_reschedule_named(1u32.encode(), DispatchTime::At(10)).unwrap(), + (10, 0) + ); + + run_to_block(9); + assert_eq!(logger::log(), vec![(root(), 42u32)]); + + run_to_block(10); + assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 42u32)]); + + run_to_block(13); + assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 42u32), (root(), 42u32)]); + + run_to_block(100); + assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 42u32), (root(), 42u32)]); + }); +} + +#[test] +fn cancel_named_scheduling_works_with_normal_cancel() { + new_test_ext().execute_with(|| { + // at #4. + Scheduler::do_schedule_named( + 1u32.encode(), + DispatchTime::At(4), + None, + 127, + root(), + Call::Logger(LoggerCall::log { i: 69, weight: 1000 }).into(), + ) + .unwrap(); + let i = Scheduler::do_schedule( + DispatchTime::At(4), + None, + 127, + root(), + Call::Logger(LoggerCall::log { i: 42, weight: 1000 }).into(), + ) + .unwrap(); + run_to_block(3); + assert!(logger::log().is_empty()); + assert_ok!(Scheduler::do_cancel_named(None, 1u32.encode())); + assert_ok!(Scheduler::do_cancel(None, i)); + run_to_block(100); + assert!(logger::log().is_empty()); + }); +} + +#[test] +fn cancel_named_periodic_scheduling_works() { + new_test_ext().execute_with(|| { + // at #4, every 3 blocks, 3 times. + Scheduler::do_schedule_named( + 1u32.encode(), + DispatchTime::At(4), + Some((3, 3)), + 127, + root(), + Call::Logger(LoggerCall::log { i: 42, weight: 1000 }).into(), + ) + .unwrap(); + // same id results in error. + assert!(Scheduler::do_schedule_named( + 1u32.encode(), + DispatchTime::At(4), + None, + 127, + root(), + Call::Logger(LoggerCall::log { i: 69, weight: 1000 }).into(), + ) + .is_err()); + // different id is ok. + Scheduler::do_schedule_named( + 2u32.encode(), + DispatchTime::At(8), + None, + 127, + root(), + Call::Logger(LoggerCall::log { i: 69, weight: 1000 }).into(), + ) + .unwrap(); + run_to_block(3); + assert!(logger::log().is_empty()); + run_to_block(4); + assert_eq!(logger::log(), vec![(root(), 42u32)]); + run_to_block(6); + assert_ok!(Scheduler::do_cancel_named(None, 1u32.encode())); + run_to_block(100); + assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 69u32)]); + }); +} + +#[test] +fn scheduler_respects_weight_limits() { + new_test_ext().execute_with(|| { + assert_ok!(Scheduler::do_schedule( + DispatchTime::At(4), + None, + 127, + root(), + Call::Logger(LoggerCall::log { i: 42, weight: MaximumSchedulerWeight::get() / 2 }) + .into(), + )); + assert_ok!(Scheduler::do_schedule( + DispatchTime::At(4), + None, + 127, + root(), + Call::Logger(LoggerCall::log { i: 69, weight: MaximumSchedulerWeight::get() / 2 }) + .into(), + )); + // 69 and 42 do not fit together + run_to_block(4); + assert_eq!(logger::log(), vec![(root(), 42u32)]); + run_to_block(5); + assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 69u32)]); + }); +} + +#[test] +fn scheduler_respects_hard_deadlines_more() { + new_test_ext().execute_with(|| { + assert_ok!(Scheduler::do_schedule( + DispatchTime::At(4), + None, + 0, + root(), + Call::Logger(LoggerCall::log { i: 42, weight: MaximumSchedulerWeight::get() / 2 }) + .into(), + )); + assert_ok!(Scheduler::do_schedule( + DispatchTime::At(4), + None, + 0, + root(), + Call::Logger(LoggerCall::log { i: 69, weight: MaximumSchedulerWeight::get() / 2 }) + .into(), + )); + // With base weights, 69 and 42 should not fit together, but do because of hard + // deadlines + run_to_block(4); + assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 69u32)]); + }); +} + +#[test] +fn scheduler_respects_priority_ordering() { + new_test_ext().execute_with(|| { + assert_ok!(Scheduler::do_schedule( + DispatchTime::At(4), + None, + 1, + root(), + Call::Logger(LoggerCall::log { i: 42, weight: MaximumSchedulerWeight::get() / 2 }) + .into(), + )); + assert_ok!(Scheduler::do_schedule( + DispatchTime::At(4), + None, + 0, + root(), + Call::Logger(LoggerCall::log { i: 69, weight: MaximumSchedulerWeight::get() / 2 }) + .into(), + )); + run_to_block(4); + assert_eq!(logger::log(), vec![(root(), 69u32), (root(), 42u32)]); + }); +} + +#[test] +fn scheduler_respects_priority_ordering_with_soft_deadlines() { + new_test_ext().execute_with(|| { + let max_weight = MaximumSchedulerWeight::get() - <() as WeightInfo>::on_initialize(0); + let item_weight = + <() as WeightInfo>::on_initialize(1) - <() as WeightInfo>::on_initialize(0); + assert_ok!(Scheduler::do_schedule( + DispatchTime::At(4), + None, + 255, + root(), + Call::Logger(LoggerCall::log { i: 42, weight: max_weight / 2 - item_weight }).into(), + )); + assert_ok!(Scheduler::do_schedule( + DispatchTime::At(4), + None, + 127, + root(), + Call::Logger(LoggerCall::log { i: 69, weight: max_weight / 2 - item_weight }).into(), + )); + assert_ok!(Scheduler::do_schedule( + DispatchTime::At(4), + None, + 126, + root(), + Call::Logger(LoggerCall::log { i: 2600, weight: max_weight / 2 - item_weight + 1 }) + .into(), + )); + + // 2600 does not fit with 69 or 42, but has higher priority, so will go through + run_to_block(4); + assert_eq!(logger::log(), vec![(root(), 2600u32)]); + // 69 and 42 fit together + run_to_block(5); + assert_eq!(logger::log(), vec![(root(), 2600u32), (root(), 69u32), (root(), 42u32)]); + }); +} + +#[test] +fn on_initialize_weight_is_correct() { + new_test_ext().execute_with(|| { + let base_weight = <() as WeightInfo>::on_initialize(0); + let call_weight = MaximumSchedulerWeight::get() / 4; + + // Named + assert_ok!(Scheduler::do_schedule_named( + 1u32.encode(), + DispatchTime::At(3), + None, + 255, + root(), + Call::Logger(LoggerCall::log { i: 3, weight: call_weight + 1 }).into(), + )); + // Anon Periodic + assert_ok!(Scheduler::do_schedule( + DispatchTime::At(2), + Some((1000, 3)), + 128, + root(), + Call::Logger(LoggerCall::log { i: 42, weight: call_weight + 2 }).into(), + )); + // Anon + assert_ok!(Scheduler::do_schedule( + DispatchTime::At(2), + None, + 127, + root(), + Call::Logger(LoggerCall::log { i: 69, weight: call_weight + 3 }).into(), + )); + // Named Periodic + assert_ok!(Scheduler::do_schedule_named( + 2u32.encode(), + DispatchTime::At(1), + Some((1000, 3)), + 126, + root(), + Call::Logger(LoggerCall::log { i: 2600, weight: call_weight + 4 }).into(), + )); + + // Will include the named periodic only + let actual_weight = Scheduler::on_initialize(1); + assert_eq!( + actual_weight, + base_weight + + call_weight + 4 + <() as MarginalWeightInfo>::item(true, true, Some(false)) + ); + assert_eq!(logger::log(), vec![(root(), 2600u32)]); + + // Will include anon and anon periodic + let actual_weight = Scheduler::on_initialize(2); + assert_eq!( + actual_weight, + base_weight + + call_weight + 2 + <() as MarginalWeightInfo>::item(false, false, Some(false)) + + call_weight + 3 + <() as MarginalWeightInfo>::item(true, false, Some(false)) + ); + assert_eq!(logger::log(), vec![(root(), 2600u32), (root(), 69u32), (root(), 42u32)]); + + // Will include named only + let actual_weight = Scheduler::on_initialize(3); + assert_eq!( + actual_weight, + base_weight + + call_weight + 1 + <() as MarginalWeightInfo>::item(false, true, Some(false)) + ); + assert_eq!( + logger::log(), + vec![(root(), 2600u32), (root(), 69u32), (root(), 42u32), (root(), 3u32)] + ); + + // Will contain none + let actual_weight = Scheduler::on_initialize(4); + assert_eq!(actual_weight, base_weight); + }); +} + +#[test] +fn root_calls_works() { + new_test_ext().execute_with(|| { + let call = Box::new(Call::Logger(LoggerCall::log { i: 69, weight: 1000 }).into()); + let call2 = Box::new(Call::Logger(LoggerCall::log { i: 42, weight: 1000 }).into()); + assert_ok!(Scheduler::schedule_named(Origin::root(), 1u32.encode(), 4, None, 127, call,)); + assert_ok!(Scheduler::schedule(Origin::root(), 4, None, 127, call2)); + run_to_block(3); + // Scheduled calls are in the agenda. + assert_eq!(Agenda::::get(4).len(), 2); + assert!(logger::log().is_empty()); + assert_ok!(Scheduler::cancel_named(Origin::root(), 1u32.encode())); + assert_ok!(Scheduler::cancel(Origin::root(), 4, 1)); + // Scheduled calls are made NONE, so should not effect state + run_to_block(100); + assert!(logger::log().is_empty()); + }); +} + +#[test] +fn fails_to_schedule_task_in_the_past() { + new_test_ext().execute_with(|| { + run_to_block(3); + + let call1 = Box::new(Call::Logger(LoggerCall::log { i: 69, weight: 1000 }).into()); + let call2 = Box::new(Call::Logger(LoggerCall::log { i: 42, weight: 1000 }).into()); + let call3 = Box::new(Call::Logger(LoggerCall::log { i: 42, weight: 1000 }).into()); + + assert_err!( + Scheduler::schedule_named(Origin::root(), 1u32.encode(), 2, None, 127, call1), + Error::::TargetBlockNumberInPast, + ); + + assert_err!( + Scheduler::schedule(Origin::root(), 2, None, 127, call2), + Error::::TargetBlockNumberInPast, + ); + + assert_err!( + Scheduler::schedule(Origin::root(), 3, None, 127, call3), + Error::::TargetBlockNumberInPast, + ); + }); +} + +#[test] +fn should_use_orign() { + new_test_ext().execute_with(|| { + let call = Box::new(Call::Logger(LoggerCall::log { i: 69, weight: 1000 }).into()); + let call2 = Box::new(Call::Logger(LoggerCall::log { i: 42, weight: 1000 }).into()); + assert_ok!(Scheduler::schedule_named( + system::RawOrigin::Signed(1).into(), + 1u32.encode(), + 4, + None, + 127, + call, + )); + assert_ok!(Scheduler::schedule(system::RawOrigin::Signed(1).into(), 4, None, 127, call2,)); + run_to_block(3); + // Scheduled calls are in the agenda. + assert_eq!(Agenda::::get(4).len(), 2); + assert!(logger::log().is_empty()); + assert_ok!(Scheduler::cancel_named(system::RawOrigin::Signed(1).into(), 1u32.encode())); + assert_ok!(Scheduler::cancel(system::RawOrigin::Signed(1).into(), 4, 1)); + // Scheduled calls are made NONE, so should not effect state + run_to_block(100); + assert!(logger::log().is_empty()); + }); +} + +#[test] +fn should_check_orign() { + new_test_ext().execute_with(|| { + let call = Box::new(Call::Logger(LoggerCall::log { i: 69, weight: 1000 }).into()); + let call2 = Box::new(Call::Logger(LoggerCall::log { i: 42, weight: 1000 }).into()); + assert_noop!( + Scheduler::schedule_named( + system::RawOrigin::Signed(2).into(), + 1u32.encode(), + 4, + None, + 127, + call + ), + BadOrigin + ); + assert_noop!( + Scheduler::schedule(system::RawOrigin::Signed(2).into(), 4, None, 127, call2), + BadOrigin + ); + }); +} + +#[test] +fn should_check_orign_for_cancel() { + new_test_ext().execute_with(|| { + let call = + Box::new(Call::Logger(LoggerCall::log_without_filter { i: 69, weight: 1000 }).into()); + let call2 = + Box::new(Call::Logger(LoggerCall::log_without_filter { i: 42, weight: 1000 }).into()); + assert_ok!(Scheduler::schedule_named( + system::RawOrigin::Signed(1).into(), + 1u32.encode(), + 4, + None, + 127, + call, + )); + assert_ok!(Scheduler::schedule(system::RawOrigin::Signed(1).into(), 4, None, 127, call2,)); + run_to_block(3); + // Scheduled calls are in the agenda. + assert_eq!(Agenda::::get(4).len(), 2); + assert!(logger::log().is_empty()); + assert_noop!( + Scheduler::cancel_named(system::RawOrigin::Signed(2).into(), 1u32.encode()), + BadOrigin + ); + assert_noop!(Scheduler::cancel(system::RawOrigin::Signed(2).into(), 4, 1), BadOrigin); + assert_noop!( + Scheduler::cancel_named(system::RawOrigin::Root.into(), 1u32.encode()), + BadOrigin + ); + assert_noop!(Scheduler::cancel(system::RawOrigin::Root.into(), 4, 1), BadOrigin); + run_to_block(5); + assert_eq!( + logger::log(), + vec![ + (system::RawOrigin::Signed(1).into(), 69u32), + (system::RawOrigin::Signed(1).into(), 42u32) + ] + ); + }); +} + +#[test] +fn migration_to_v3_works() { + new_test_ext().execute_with(|| { + for i in 0..3u64 { + let k = i.twox_64_concat(); + let old = vec![ + Some(ScheduledV1 { + maybe_id: None, + priority: i as u8 + 10, + call: Call::Logger(LoggerCall::log { i: 96, weight: 100 }), + maybe_periodic: None, + }), + None, + Some(ScheduledV1 { + maybe_id: Some(b"test".to_vec()), + priority: 123, + call: Call::Logger(LoggerCall::log { i: 69, weight: 1000 }), + maybe_periodic: Some((456u64, 10)), + }), + ]; + frame_support::migration::put_storage_value(b"Scheduler", b"Agenda", &k, old); + } + + assert_eq!(StorageVersion::::get(), Releases::V1); + + assert!(Scheduler::migrate_v1_to_v3()); + + assert_eq_uvec!( + Agenda::::iter().collect::>(), + vec![ + ( + 0, + vec![ + Some(ScheduledV3Of:: { + maybe_id: None, + priority: 10, + call: Call::Logger(LoggerCall::log { i: 96, weight: 100 }).into(), + maybe_periodic: None, + origin: root(), + _phantom: PhantomData::::default(), + }), + None, + Some(ScheduledV3Of:: { + maybe_id: Some(b"test".to_vec()), + priority: 123, + call: Call::Logger(LoggerCall::log { i: 69, weight: 1000 }).into(), + maybe_periodic: Some((456u64, 10)), + origin: root(), + _phantom: PhantomData::::default(), + }), + ] + ), + ( + 1, + vec![ + Some(ScheduledV3Of:: { + maybe_id: None, + priority: 11, + call: Call::Logger(LoggerCall::log { i: 96, weight: 100 }).into(), + maybe_periodic: None, + origin: root(), + _phantom: PhantomData::::default(), + }), + None, + Some(ScheduledV3Of:: { + maybe_id: Some(b"test".to_vec()), + priority: 123, + call: Call::Logger(LoggerCall::log { i: 69, weight: 1000 }).into(), + maybe_periodic: Some((456u64, 10)), + origin: root(), + _phantom: PhantomData::::default(), + }), + ] + ), + ( + 2, + vec![ + Some(ScheduledV3Of:: { + maybe_id: None, + priority: 12, + call: Call::Logger(LoggerCall::log { i: 96, weight: 100 }).into(), + maybe_periodic: None, + origin: root(), + _phantom: PhantomData::::default(), + }), + None, + Some(ScheduledV3Of:: { + maybe_id: Some(b"test".to_vec()), + priority: 123, + call: Call::Logger(LoggerCall::log { i: 69, weight: 1000 }).into(), + maybe_periodic: Some((456u64, 10)), + origin: root(), + _phantom: PhantomData::::default(), + }), + ] + ) + ] + ); + + assert_eq!(StorageVersion::::get(), Releases::V3); + }); +} + +#[test] +fn test_migrate_origin() { + new_test_ext().execute_with(|| { + for i in 0..3u64 { + let k = i.twox_64_concat(); + let old: Vec, u64, u32, u64>>> = vec![ + Some(Scheduled { + maybe_id: None, + priority: i as u8 + 10, + call: Call::Logger(LoggerCall::log { i: 96, weight: 100 }).into(), + origin: 3u32, + maybe_periodic: None, + _phantom: Default::default(), + }), + None, + Some(Scheduled { + maybe_id: Some(b"test".to_vec()), + priority: 123, + origin: 2u32, + call: Call::Logger(LoggerCall::log { i: 69, weight: 1000 }).into(), + maybe_periodic: Some((456u64, 10)), + _phantom: Default::default(), + }), + ]; + frame_support::migration::put_storage_value(b"Scheduler", b"Agenda", &k, old); + } + + impl Into for u32 { + fn into(self) -> OriginCaller { + match self { + 3u32 => system::RawOrigin::Root.into(), + 2u32 => system::RawOrigin::None.into(), + _ => unreachable!("test make no use of it"), + } + } + } + + Scheduler::migrate_origin::(); + + assert_eq_uvec!( + Agenda::::iter().collect::>(), + vec![ + ( + 0, + vec![ + Some(ScheduledV2::, u64, OriginCaller, u64> { + maybe_id: None, + priority: 10, + call: Call::Logger(LoggerCall::log { i: 96, weight: 100 }).into(), + maybe_periodic: None, + origin: system::RawOrigin::Root.into(), + _phantom: PhantomData::::default(), + }), + None, + Some(ScheduledV2 { + maybe_id: Some(b"test".to_vec()), + priority: 123, + call: Call::Logger(LoggerCall::log { i: 69, weight: 1000 }).into(), + maybe_periodic: Some((456u64, 10)), + origin: system::RawOrigin::None.into(), + _phantom: PhantomData::::default(), + }), + ] + ), + ( + 1, + vec![ + Some(ScheduledV2 { + maybe_id: None, + priority: 11, + call: Call::Logger(LoggerCall::log { i: 96, weight: 100 }).into(), + maybe_periodic: None, + origin: system::RawOrigin::Root.into(), + _phantom: PhantomData::::default(), + }), + None, + Some(ScheduledV2 { + maybe_id: Some(b"test".to_vec()), + priority: 123, + call: Call::Logger(LoggerCall::log { i: 69, weight: 1000 }).into(), + maybe_periodic: Some((456u64, 10)), + origin: system::RawOrigin::None.into(), + _phantom: PhantomData::::default(), + }), + ] + ), + ( + 2, + vec![ + Some(ScheduledV2 { + maybe_id: None, + priority: 12, + call: Call::Logger(LoggerCall::log { i: 96, weight: 100 }).into(), + maybe_periodic: None, + origin: system::RawOrigin::Root.into(), + _phantom: PhantomData::::default(), + }), + None, + Some(ScheduledV2 { + maybe_id: Some(b"test".to_vec()), + priority: 123, + call: Call::Logger(LoggerCall::log { i: 69, weight: 1000 }).into(), + maybe_periodic: Some((456u64, 10)), + origin: system::RawOrigin::None.into(), + _phantom: PhantomData::::default(), + }), + ] + ) + ] + ); + }); +} diff --git a/frame/scheduler/src/weights.rs b/frame/scheduler/src/weights.rs index d83aefdc453a..3c2ed47110b6 100644 --- a/frame/scheduler/src/weights.rs +++ b/frame/scheduler/src/weights.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_scheduler //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-08-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2021-12-10, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 // Executed Command: @@ -35,7 +35,6 @@ // --output=./frame/scheduler/src/weights.rs // --template=./.maintain/frame-weight-template.hbs - #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] #![allow(unused_imports)] @@ -45,6 +44,16 @@ use sp_std::marker::PhantomData; /// Weight functions needed for pallet_scheduler. pub trait WeightInfo { + fn on_initialize_periodic_named_resolved(s: u32, ) -> Weight; + fn on_initialize_named_resolved(s: u32, ) -> Weight; + fn on_initialize_periodic_resolved(s: u32, ) -> Weight; + fn on_initialize_resolved(s: u32, ) -> Weight; + fn on_initialize_named_aborted(s: u32, ) -> Weight; + fn on_initialize_aborted(s: u32, ) -> Weight; + fn on_initialize_periodic_named(s: u32, ) -> Weight; + fn on_initialize_periodic(s: u32, ) -> Weight; + fn on_initialize_named(s: u32, ) -> Weight; + fn on_initialize(s: u32, ) -> Weight; fn schedule(s: u32, ) -> Weight; fn cancel(s: u32, ) -> Weight; fn schedule_named(s: u32, ) -> Weight; @@ -54,38 +63,149 @@ pub trait WeightInfo { /// Weights for pallet_scheduler using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { + // Storage: Scheduler Agenda (r:2 w:2) + // Storage: Preimage PreimageFor (r:1 w:1) + // Storage: Preimage StatusFor (r:1 w:1) + // Storage: Scheduler Lookup (r:0 w:1) + fn on_initialize_periodic_named_resolved(s: u32, ) -> Weight { + (8_183_000 as Weight) + // Standard Error: 36_000 + .saturating_add((34_670_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(s as Weight))) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + .saturating_add(T::DbWeight::get().writes((4 as Weight).saturating_mul(s as Weight))) + } + // Storage: Scheduler Agenda (r:1 w:1) + // Storage: Preimage PreimageFor (r:1 w:1) + // Storage: Preimage StatusFor (r:1 w:1) + // Storage: Scheduler Lookup (r:0 w:1) + fn on_initialize_named_resolved(s: u32, ) -> Weight { + (11_520_000 as Weight) + // Standard Error: 30_000 + .saturating_add((26_386_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(s as Weight))) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + .saturating_add(T::DbWeight::get().writes((3 as Weight).saturating_mul(s as Weight))) + } + // Storage: Scheduler Agenda (r:2 w:2) + // Storage: Preimage PreimageFor (r:1 w:1) + // Storage: Preimage StatusFor (r:1 w:1) + fn on_initialize_periodic_resolved(s: u32, ) -> Weight { + (8_222_000 as Weight) + // Standard Error: 33_000 + .saturating_add((28_925_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(s as Weight))) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + .saturating_add(T::DbWeight::get().writes((3 as Weight).saturating_mul(s as Weight))) + } + // Storage: Scheduler Agenda (r:1 w:1) + // Storage: Preimage PreimageFor (r:1 w:1) + // Storage: Preimage StatusFor (r:1 w:1) + fn on_initialize_resolved(s: u32, ) -> Weight { + (11_610_000 as Weight) + // Standard Error: 26_000 + .saturating_add((23_857_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(s as Weight))) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + .saturating_add(T::DbWeight::get().writes((2 as Weight).saturating_mul(s as Weight))) + } + // Storage: Scheduler Agenda (r:2 w:2) + // Storage: Preimage PreimageFor (r:1 w:0) + // Storage: Scheduler Lookup (r:0 w:1) + fn on_initialize_named_aborted(s: u32, ) -> Weight { + (11_067_000 as Weight) + // Standard Error: 15_000 + .saturating_add((11_728_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) + } + // Storage: Scheduler Agenda (r:2 w:2) + // Storage: Preimage PreimageFor (r:1 w:0) + fn on_initialize_aborted(s: u32, ) -> Weight { + (13_045_000 as Weight) + // Standard Error: 5_000 + .saturating_add((6_378_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + } + // Storage: Scheduler Agenda (r:2 w:2) + // Storage: Scheduler Lookup (r:0 w:1) + fn on_initialize_periodic_named(s: u32, ) -> Weight { + (13_496_000 as Weight) + // Standard Error: 27_000 + .saturating_add((17_932_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + .saturating_add(T::DbWeight::get().writes((2 as Weight).saturating_mul(s as Weight))) + } + // Storage: Scheduler Agenda (r:2 w:2) + fn on_initialize_periodic(s: u32, ) -> Weight { + (17_074_000 as Weight) + // Standard Error: 16_000 + .saturating_add((11_982_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) + } + // Storage: Scheduler Agenda (r:1 w:1) + // Storage: Scheduler Lookup (r:0 w:1) + fn on_initialize_named(s: u32, ) -> Weight { + (18_730_000 as Weight) + // Standard Error: 10_000 + .saturating_add((9_909_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) + } + // Storage: Scheduler Agenda (r:1 w:1) + fn on_initialize(s: u32, ) -> Weight { + (17_844_000 as Weight) + // Standard Error: 9_000 + .saturating_add((7_719_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } // Storage: Scheduler Agenda (r:1 w:1) fn schedule(s: u32, ) -> Weight { - (24_730_000 as Weight) + (23_361_000 as Weight) // Standard Error: 1_000 - .saturating_add((77_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((82_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Scheduler Agenda (r:1 w:1) // Storage: Scheduler Lookup (r:0 w:1) fn cancel(s: u32, ) -> Weight { - (23_272_000 as Weight) - // Standard Error: 4_000 - .saturating_add((1_261_000 as Weight).saturating_mul(s as Weight)) + (22_359_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_219_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Scheduler Lookup (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) fn schedule_named(s: u32, ) -> Weight { - (30_971_000 as Weight) + (28_499_000 as Weight) // Standard Error: 1_000 - .saturating_add((96_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((98_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Scheduler Lookup (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) fn cancel_named(s: u32, ) -> Weight { - (25_778_000 as Weight) - // Standard Error: 4_000 - .saturating_add((1_270_000 as Weight).saturating_mul(s as Weight)) + (24_995_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_223_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -93,38 +213,149 @@ impl WeightInfo for SubstrateWeight { // For backwards compatibility and tests impl WeightInfo for () { + // Storage: Scheduler Agenda (r:2 w:2) + // Storage: Preimage PreimageFor (r:1 w:1) + // Storage: Preimage StatusFor (r:1 w:1) + // Storage: Scheduler Lookup (r:0 w:1) + fn on_initialize_periodic_named_resolved(s: u32, ) -> Weight { + (8_183_000 as Weight) + // Standard Error: 36_000 + .saturating_add((34_670_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(s as Weight))) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes((4 as Weight).saturating_mul(s as Weight))) + } + // Storage: Scheduler Agenda (r:1 w:1) + // Storage: Preimage PreimageFor (r:1 w:1) + // Storage: Preimage StatusFor (r:1 w:1) + // Storage: Scheduler Lookup (r:0 w:1) + fn on_initialize_named_resolved(s: u32, ) -> Weight { + (11_520_000 as Weight) + // Standard Error: 30_000 + .saturating_add((26_386_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + .saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(s as Weight))) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes((3 as Weight).saturating_mul(s as Weight))) + } + // Storage: Scheduler Agenda (r:2 w:2) + // Storage: Preimage PreimageFor (r:1 w:1) + // Storage: Preimage StatusFor (r:1 w:1) + fn on_initialize_periodic_resolved(s: u32, ) -> Weight { + (8_222_000 as Weight) + // Standard Error: 33_000 + .saturating_add((28_925_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(s as Weight))) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes((3 as Weight).saturating_mul(s as Weight))) + } + // Storage: Scheduler Agenda (r:1 w:1) + // Storage: Preimage PreimageFor (r:1 w:1) + // Storage: Preimage StatusFor (r:1 w:1) + fn on_initialize_resolved(s: u32, ) -> Weight { + (11_610_000 as Weight) + // Standard Error: 26_000 + .saturating_add((23_857_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + .saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(s as Weight))) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes((2 as Weight).saturating_mul(s as Weight))) + } + // Storage: Scheduler Agenda (r:2 w:2) + // Storage: Preimage PreimageFor (r:1 w:0) + // Storage: Scheduler Lookup (r:0 w:1) + fn on_initialize_named_aborted(s: u32, ) -> Weight { + (11_067_000 as Weight) + // Standard Error: 15_000 + .saturating_add((11_728_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(RocksDbWeight::get().reads(2 as Weight)) + .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) + } + // Storage: Scheduler Agenda (r:2 w:2) + // Storage: Preimage PreimageFor (r:1 w:0) + fn on_initialize_aborted(s: u32, ) -> Weight { + (13_045_000 as Weight) + // Standard Error: 5_000 + .saturating_add((6_378_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(RocksDbWeight::get().reads(2 as Weight)) + .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + } + // Storage: Scheduler Agenda (r:2 w:2) + // Storage: Scheduler Lookup (r:0 w:1) + fn on_initialize_periodic_named(s: u32, ) -> Weight { + (13_496_000 as Weight) + // Standard Error: 27_000 + .saturating_add((17_932_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes((2 as Weight).saturating_mul(s as Weight))) + } + // Storage: Scheduler Agenda (r:2 w:2) + fn on_initialize_periodic(s: u32, ) -> Weight { + (17_074_000 as Weight) + // Standard Error: 16_000 + .saturating_add((11_982_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) + } + // Storage: Scheduler Agenda (r:1 w:1) + // Storage: Scheduler Lookup (r:0 w:1) + fn on_initialize_named(s: u32, ) -> Weight { + (18_730_000 as Weight) + // Standard Error: 10_000 + .saturating_add((9_909_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) + } + // Storage: Scheduler Agenda (r:1 w:1) + fn on_initialize(s: u32, ) -> Weight { + (17_844_000 as Weight) + // Standard Error: 9_000 + .saturating_add((7_719_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } // Storage: Scheduler Agenda (r:1 w:1) fn schedule(s: u32, ) -> Weight { - (24_730_000 as Weight) + (23_361_000 as Weight) // Standard Error: 1_000 - .saturating_add((77_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((82_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Scheduler Agenda (r:1 w:1) // Storage: Scheduler Lookup (r:0 w:1) fn cancel(s: u32, ) -> Weight { - (23_272_000 as Weight) - // Standard Error: 4_000 - .saturating_add((1_261_000 as Weight).saturating_mul(s as Weight)) + (22_359_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_219_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Scheduler Lookup (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) fn schedule_named(s: u32, ) -> Weight { - (30_971_000 as Weight) + (28_499_000 as Weight) // Standard Error: 1_000 - .saturating_add((96_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((98_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Scheduler Lookup (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) fn cancel_named(s: u32, ) -> Weight { - (25_778_000 as Weight) - // Standard Error: 4_000 - .saturating_add((1_270_000 as Weight).saturating_mul(s as Weight)) + (24_995_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_223_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } diff --git a/frame/support/src/traits.rs b/frame/support/src/traits.rs index 3c1f268ade07..01817723e94e 100644 --- a/frame/support/src/traits.rs +++ b/frame/support/src/traits.rs @@ -53,8 +53,8 @@ pub use misc::{ Backing, ConstBool, ConstI128, ConstI16, ConstI32, ConstI64, ConstI8, ConstU128, ConstU16, ConstU32, ConstU64, ConstU8, EnsureInherentsAreFirst, EqualPrivilegeOnly, EstimateCallFee, ExecuteBlock, ExtrinsicCall, Get, GetBacking, GetDefault, HandleLifetime, IsSubType, IsType, - Len, OffchainWorker, OnKilledAccount, OnNewAccount, PrivilegeCmp, SameOrOther, Time, TryDrop, - UnixTime, WrapperKeepOpaque, WrapperOpaque, + Len, OffchainWorker, OnKilledAccount, OnNewAccount, PreimageProvider, PreimageRecipient, + PrivilegeCmp, SameOrOther, Time, TryDrop, UnixTime, WrapperKeepOpaque, WrapperOpaque, }; mod stored_map; diff --git a/frame/support/src/traits/misc.rs b/frame/support/src/traits/misc.rs index 165a83b4be2a..8bab1581a697 100644 --- a/frame/support/src/traits/misc.rs +++ b/frame/support/src/traits/misc.rs @@ -94,6 +94,12 @@ pub trait TryDrop: Sized { fn try_drop(self) -> Result<(), Self>; } +impl TryDrop for () { + fn try_drop(self) -> Result<(), Self> { + Ok(()) + } +} + /// Return type used when we need to return one of two items, each of the opposite direction or /// sign, with one (`Same`) being of the same type as the `self` or primary argument of the function /// that returned it. @@ -577,6 +583,65 @@ impl TypeInfo for WrapperKeepOpaque { } } +/// A interface for looking up preimages from their hash on chain. +pub trait PreimageProvider { + /// Returns whether a preimage exists for a given hash. + /// + /// A value of `true` implies that `get_preimage` is `Some`. + fn have_preimage(hash: &Hash) -> bool; + + /// Returns the preimage for a given hash. + fn get_preimage(hash: &Hash) -> Option>; + + /// Returns whether a preimage request exists for a given hash. + fn preimage_requested(hash: &Hash) -> bool; + + /// Request that someone report a preimage. Providers use this to optimise the economics for + /// preimage reporting. + fn request_preimage(hash: &Hash); + + /// Cancel a previous preimage request. + fn unrequest_preimage(hash: &Hash); +} + +impl PreimageProvider for () { + fn have_preimage(_: &Hash) -> bool { + false + } + fn get_preimage(_: &Hash) -> Option> { + None + } + fn preimage_requested(_: &Hash) -> bool { + false + } + fn request_preimage(_: &Hash) {} + fn unrequest_preimage(_: &Hash) {} +} + +/// A interface for managing preimages to hashes on chain. +/// +/// Note that this API does not assume any underlying user is calling, and thus +/// does not handle any preimage ownership or fees. Other system level logic that +/// uses this API should implement that on their own side. +pub trait PreimageRecipient: PreimageProvider { + /// Maximum size of a preimage. + type MaxSize: Get; + + /// Store the bytes of a preimage on chain. + fn note_preimage(bytes: crate::BoundedVec); + + /// Clear a previously noted preimage. This is infallible and should be treated more like a + /// hint - if it was not previously noted or if it is now requested, then this will not do + /// anything. + fn unnote_preimage(hash: &Hash); +} + +impl PreimageRecipient for () { + type MaxSize = (); + fn note_preimage(_: crate::BoundedVec) {} + fn unnote_preimage(_: &Hash) {} +} + #[cfg(test)] mod test { use super::*; diff --git a/frame/support/src/traits/schedule.rs b/frame/support/src/traits/schedule.rs index 19f50a93c068..1cedb96cb14b 100644 --- a/frame/support/src/traits/schedule.rs +++ b/frame/support/src/traits/schedule.rs @@ -17,10 +17,10 @@ //! Traits and associated utilities for scheduling dispatchables in FRAME. -use codec::{Codec, Decode, Encode, EncodeLike}; +use codec::{Codec, Decode, Encode, EncodeLike, MaxEncodedLen}; use scale_info::TypeInfo; use sp_runtime::{DispatchError, RuntimeDebug}; -use sp_std::{fmt::Debug, prelude::*}; +use sp_std::{fmt::Debug, prelude::*, result::Result}; /// Information relating to the period of a scheduled task. First item is the length of the /// period and the second is the number of times it should be executed in total before the task @@ -49,86 +49,323 @@ pub const HARD_DEADLINE: Priority = 63; /// The lowest priority. Most stuff should be around here. pub const LOWEST_PRIORITY: Priority = 255; -/// A type that can be used as a scheduler. -pub trait Anon { - /// An address which can be used for removing a scheduled task. - type Address: Codec + Clone + Eq + EncodeLike + Debug; - - /// Schedule a dispatch to happen at the beginning of some block in the future. - /// - /// This is not named. - fn schedule( - when: DispatchTime, - maybe_periodic: Option>, - priority: Priority, - origin: Origin, - call: Call, - ) -> Result; - - /// Cancel a scheduled task. If periodic, then it will cancel all further instances of that, - /// also. - /// - /// Will return an error if the `address` is invalid. - /// - /// NOTE: This guaranteed to work only *before* the point that it is due to be executed. - /// If it ends up being delayed beyond the point of execution, then it cannot be cancelled. - /// - /// NOTE2: This will not work to cancel periodic tasks after their initial execution. For - /// that, you must name the task explicitly using the `Named` trait. - fn cancel(address: Self::Address) -> Result<(), ()>; - - /// Reschedule a task. For one-off tasks, this dispatch is guaranteed to succeed - /// only if it is executed *before* the currently scheduled block. For periodic tasks, - /// this dispatch is guaranteed to succeed only before the *initial* execution; for - /// others, use `reschedule_named`. - /// - /// Will return an error if the `address` is invalid. - fn reschedule( - address: Self::Address, - when: DispatchTime, - ) -> Result; - - /// Return the next dispatch time for a given task. - /// - /// Will return an error if the `address` is invalid. - fn next_dispatch_time(address: Self::Address) -> Result; +/// Type representing an encodable value or the hash of the encoding of such a value. +#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub enum MaybeHashed { + /// The value itself. + Value(T), + /// The hash of the encoded value which this value represents. + Hash(Hash), } -/// A type that can be used as a scheduler. -pub trait Named { - /// An address which can be used for removing a scheduled task. - type Address: Codec + Clone + Eq + EncodeLike + sp_std::fmt::Debug; - - /// Schedule a dispatch to happen at the beginning of some block in the future. - /// - /// - `id`: The identity of the task. This must be unique and will return an error if not. - fn schedule_named( - id: Vec, - when: DispatchTime, - maybe_periodic: Option>, - priority: Priority, - origin: Origin, - call: Call, - ) -> Result; - - /// Cancel a scheduled, named task. If periodic, then it will cancel all further instances - /// of that, also. - /// - /// Will return an error if the `id` is invalid. - /// - /// NOTE: This guaranteed to work only *before* the point that it is due to be executed. - /// If it ends up being delayed beyond the point of execution, then it cannot be cancelled. - fn cancel_named(id: Vec) -> Result<(), ()>; - - /// Reschedule a task. For one-off tasks, this dispatch is guaranteed to succeed - /// only if it is executed *before* the currently scheduled block. - fn reschedule_named( - id: Vec, - when: DispatchTime, - ) -> Result; - - /// Return the next dispatch time for a given task. - /// - /// Will return an error if the `id` is invalid. - fn next_dispatch_time(id: Vec) -> Result; +impl From for MaybeHashed { + fn from(t: T) -> Self { + MaybeHashed::Value(t) + } } + +/// Error type for `MaybeHashed::lookup`. +#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub enum LookupError { + /// A call of this hash was not known. + Unknown, + /// The preimage for this hash was known but could not be decoded into a `Call`. + BadFormat, +} + +impl MaybeHashed { + pub fn as_value(&self) -> Option<&T> { + match &self { + Self::Value(c) => Some(c), + Self::Hash(_) => None, + } + } + + pub fn as_hash(&self) -> Option<&H> { + match &self { + Self::Value(_) => None, + Self::Hash(h) => Some(h), + } + } + + pub fn ensure_requested>(&self) { + match &self { + Self::Value(_) => (), + Self::Hash(hash) => P::request_preimage(hash), + } + } + + pub fn ensure_unrequested>(&self) { + match &self { + Self::Value(_) => (), + Self::Hash(hash) => P::unrequest_preimage(hash), + } + } + + pub fn resolved>(self) -> (Self, Option) { + match self { + Self::Value(c) => (Self::Value(c), None), + Self::Hash(h) => { + let data = match P::get_preimage(&h) { + Some(p) => p, + None => return (Self::Hash(h), None), + }; + match T::decode(&mut &data[..]) { + Ok(c) => (Self::Value(c), Some(h)), + Err(_) => (Self::Hash(h), None), + } + }, + } + } +} + +pub mod v1 { + use super::*; + + /// A type that can be used as a scheduler. + pub trait Anon { + /// An address which can be used for removing a scheduled task. + type Address: Codec + Clone + Eq + EncodeLike + Debug; + + /// Schedule a dispatch to happen at the beginning of some block in the future. + /// + /// This is not named. + fn schedule( + when: DispatchTime, + maybe_periodic: Option>, + priority: Priority, + origin: Origin, + call: Call, + ) -> Result; + + /// Cancel a scheduled task. If periodic, then it will cancel all further instances of that, + /// also. + /// + /// Will return an error if the `address` is invalid. + /// + /// NOTE: This guaranteed to work only *before* the point that it is due to be executed. + /// If it ends up being delayed beyond the point of execution, then it cannot be cancelled. + /// + /// NOTE2: This will not work to cancel periodic tasks after their initial execution. For + /// that, you must name the task explicitly using the `Named` trait. + fn cancel(address: Self::Address) -> Result<(), ()>; + + /// Reschedule a task. For one-off tasks, this dispatch is guaranteed to succeed + /// only if it is executed *before* the currently scheduled block. For periodic tasks, + /// this dispatch is guaranteed to succeed only before the *initial* execution; for + /// others, use `reschedule_named`. + /// + /// Will return an error if the `address` is invalid. + fn reschedule( + address: Self::Address, + when: DispatchTime, + ) -> Result; + + /// Return the next dispatch time for a given task. + /// + /// Will return an error if the `address` is invalid. + fn next_dispatch_time(address: Self::Address) -> Result; + } + + /// A type that can be used as a scheduler. + pub trait Named { + /// An address which can be used for removing a scheduled task. + type Address: Codec + Clone + Eq + EncodeLike + sp_std::fmt::Debug; + + /// Schedule a dispatch to happen at the beginning of some block in the future. + /// + /// - `id`: The identity of the task. This must be unique and will return an error if not. + fn schedule_named( + id: Vec, + when: DispatchTime, + maybe_periodic: Option>, + priority: Priority, + origin: Origin, + call: Call, + ) -> Result; + + /// Cancel a scheduled, named task. If periodic, then it will cancel all further instances + /// of that, also. + /// + /// Will return an error if the `id` is invalid. + /// + /// NOTE: This guaranteed to work only *before* the point that it is due to be executed. + /// If it ends up being delayed beyond the point of execution, then it cannot be cancelled. + fn cancel_named(id: Vec) -> Result<(), ()>; + + /// Reschedule a task. For one-off tasks, this dispatch is guaranteed to succeed + /// only if it is executed *before* the currently scheduled block. + fn reschedule_named( + id: Vec, + when: DispatchTime, + ) -> Result; + + /// Return the next dispatch time for a given task. + /// + /// Will return an error if the `id` is invalid. + fn next_dispatch_time(id: Vec) -> Result; + } + + impl Anon for T + where + T: v2::Anon, + { + type Address = T::Address; + + fn schedule( + when: DispatchTime, + maybe_periodic: Option>, + priority: Priority, + origin: Origin, + call: Call, + ) -> Result { + let c = MaybeHashed::::Value(call); + T::schedule(when, maybe_periodic, priority, origin, c) + } + + fn cancel(address: Self::Address) -> Result<(), ()> { + T::cancel(address) + } + + fn reschedule( + address: Self::Address, + when: DispatchTime, + ) -> Result { + T::reschedule(address, when) + } + + fn next_dispatch_time(address: Self::Address) -> Result { + T::next_dispatch_time(address) + } + } + + impl Named for T + where + T: v2::Named, + { + type Address = T::Address; + + fn schedule_named( + id: Vec, + when: DispatchTime, + maybe_periodic: Option>, + priority: Priority, + origin: Origin, + call: Call, + ) -> Result { + let c = MaybeHashed::::Value(call); + T::schedule_named(id, when, maybe_periodic, priority, origin, c) + } + + fn cancel_named(id: Vec) -> Result<(), ()> { + T::cancel_named(id) + } + + fn reschedule_named( + id: Vec, + when: DispatchTime, + ) -> Result { + T::reschedule_named(id, when) + } + + fn next_dispatch_time(id: Vec) -> Result { + T::next_dispatch_time(id) + } + } +} + +pub mod v2 { + use super::*; + + /// A type that can be used as a scheduler. + pub trait Anon { + /// An address which can be used for removing a scheduled task. + type Address: Codec + Clone + Eq + EncodeLike + Debug; + /// A means of expressing a call by the hash of its encoded data. + type Hash; + + /// Schedule a dispatch to happen at the beginning of some block in the future. + /// + /// This is not named. + fn schedule( + when: DispatchTime, + maybe_periodic: Option>, + priority: Priority, + origin: Origin, + call: MaybeHashed, + ) -> Result; + + /// Cancel a scheduled task. If periodic, then it will cancel all further instances of that, + /// also. + /// + /// Will return an error if the `address` is invalid. + /// + /// NOTE: This guaranteed to work only *before* the point that it is due to be executed. + /// If it ends up being delayed beyond the point of execution, then it cannot be cancelled. + /// + /// NOTE2: This will not work to cancel periodic tasks after their initial execution. For + /// that, you must name the task explicitly using the `Named` trait. + fn cancel(address: Self::Address) -> Result<(), ()>; + + /// Reschedule a task. For one-off tasks, this dispatch is guaranteed to succeed + /// only if it is executed *before* the currently scheduled block. For periodic tasks, + /// this dispatch is guaranteed to succeed only before the *initial* execution; for + /// others, use `reschedule_named`. + /// + /// Will return an error if the `address` is invalid. + fn reschedule( + address: Self::Address, + when: DispatchTime, + ) -> Result; + + /// Return the next dispatch time for a given task. + /// + /// Will return an error if the `address` is invalid. + fn next_dispatch_time(address: Self::Address) -> Result; + } + + /// A type that can be used as a scheduler. + pub trait Named { + /// An address which can be used for removing a scheduled task. + type Address: Codec + Clone + Eq + EncodeLike + sp_std::fmt::Debug; + /// A means of expressing a call by the hash of its encoded data. + type Hash; + + /// Schedule a dispatch to happen at the beginning of some block in the future. + /// + /// - `id`: The identity of the task. This must be unique and will return an error if not. + fn schedule_named( + id: Vec, + when: DispatchTime, + maybe_periodic: Option>, + priority: Priority, + origin: Origin, + call: MaybeHashed, + ) -> Result; + + /// Cancel a scheduled, named task. If periodic, then it will cancel all further instances + /// of that, also. + /// + /// Will return an error if the `id` is invalid. + /// + /// NOTE: This guaranteed to work only *before* the point that it is due to be executed. + /// If it ends up being delayed beyond the point of execution, then it cannot be cancelled. + fn cancel_named(id: Vec) -> Result<(), ()>; + + /// Reschedule a task. For one-off tasks, this dispatch is guaranteed to succeed + /// only if it is executed *before* the currently scheduled block. + fn reschedule_named( + id: Vec, + when: DispatchTime, + ) -> Result; + + /// Return the next dispatch time for a given task. + /// + /// Will return an error if the `id` is invalid. + fn next_dispatch_time(id: Vec) -> Result; + } +} + +pub use v1::*; + +use super::PreimageProvider; diff --git a/frame/support/src/traits/tokens/currency.rs b/frame/support/src/traits/tokens/currency.rs index bf078658477f..9fdb08b8bd6e 100644 --- a/frame/support/src/traits/tokens/currency.rs +++ b/frame/support/src/traits/tokens/currency.rs @@ -199,3 +199,91 @@ pub trait Currency { balance: Self::Balance, ) -> SignedImbalance; } + +#[cfg(feature = "std")] +impl Currency for () { + type Balance = u32; + type PositiveImbalance = (); + type NegativeImbalance = (); + fn total_balance(_: &AccountId) -> Self::Balance { + 0 + } + fn can_slash(_: &AccountId, _: Self::Balance) -> bool { + true + } + fn total_issuance() -> Self::Balance { + 0 + } + fn minimum_balance() -> Self::Balance { + 0 + } + fn burn(_: Self::Balance) -> Self::PositiveImbalance { + () + } + fn issue(_: Self::Balance) -> Self::NegativeImbalance { + () + } + fn pair(_: Self::Balance) -> (Self::PositiveImbalance, Self::NegativeImbalance) { + ((), ()) + } + fn free_balance(_: &AccountId) -> Self::Balance { + 0 + } + fn ensure_can_withdraw( + _: &AccountId, + _: Self::Balance, + _: WithdrawReasons, + _: Self::Balance, + ) -> DispatchResult { + Ok(()) + } + fn transfer( + _: &AccountId, + _: &AccountId, + _: Self::Balance, + _: ExistenceRequirement, + ) -> DispatchResult { + Ok(()) + } + fn slash(_: &AccountId, _: Self::Balance) -> (Self::NegativeImbalance, Self::Balance) { + ((), 0) + } + fn deposit_into_existing( + _: &AccountId, + _: Self::Balance, + ) -> Result { + Ok(()) + } + fn resolve_into_existing( + _: &AccountId, + _: Self::NegativeImbalance, + ) -> Result<(), Self::NegativeImbalance> { + Ok(()) + } + fn deposit_creating(_: &AccountId, _: Self::Balance) -> Self::PositiveImbalance { + () + } + fn resolve_creating(_: &AccountId, _: Self::NegativeImbalance) {} + fn withdraw( + _: &AccountId, + _: Self::Balance, + _: WithdrawReasons, + _: ExistenceRequirement, + ) -> Result { + Ok(()) + } + fn settle( + _: &AccountId, + _: Self::PositiveImbalance, + _: WithdrawReasons, + _: ExistenceRequirement, + ) -> Result<(), Self::PositiveImbalance> { + Ok(()) + } + fn make_free_balance_be( + _: &AccountId, + _: Self::Balance, + ) -> SignedImbalance { + SignedImbalance::Positive(()) + } +} diff --git a/frame/support/src/traits/tokens/currency/reservable.rs b/frame/support/src/traits/tokens/currency/reservable.rs index 0ca7a93dc7f6..e2313a9d2550 100644 --- a/frame/support/src/traits/tokens/currency/reservable.rs +++ b/frame/support/src/traits/tokens/currency/reservable.rs @@ -81,6 +81,33 @@ pub trait ReservableCurrency: Currency { ) -> Result; } +#[cfg(feature = "std")] +impl ReservableCurrency for () { + fn can_reserve(_: &AccountId, _: Self::Balance) -> bool { + true + } + fn slash_reserved(_: &AccountId, _: Self::Balance) -> (Self::NegativeImbalance, Self::Balance) { + ((), 0) + } + fn reserved_balance(_: &AccountId) -> Self::Balance { + 0 + } + fn reserve(_: &AccountId, _: Self::Balance) -> DispatchResult { + Ok(()) + } + fn unreserve(_: &AccountId, _: Self::Balance) -> Self::Balance { + 0 + } + fn repatriate_reserved( + _: &AccountId, + _: &AccountId, + _: Self::Balance, + _: BalanceStatus, + ) -> Result { + Ok(0) + } +} + pub trait NamedReservableCurrency: ReservableCurrency { /// An identifier for a reserve. Used for disambiguating different reserves so that /// they can be individually replaced or removed. diff --git a/frame/support/src/traits/tokens/imbalance.rs b/frame/support/src/traits/tokens/imbalance.rs index 0f7b38a65efc..eaa18be58f61 100644 --- a/frame/support/src/traits/tokens/imbalance.rs +++ b/frame/support/src/traits/tokens/imbalance.rs @@ -177,3 +177,55 @@ pub trait Imbalance: Sized + TryDrop + Default { /// The raw value of self. fn peek(&self) -> Balance; } + +#[cfg(feature = "std")] +impl Imbalance for () { + type Opposite = (); + fn zero() -> Self { + () + } + fn drop_zero(self) -> Result<(), Self> { + Ok(()) + } + fn split(self, _: Balance) -> (Self, Self) { + ((), ()) + } + fn ration(self, _: u32, _: u32) -> (Self, Self) + where + Balance: From + Saturating + Div, + { + ((), ()) + } + fn split_merge(self, _: Balance, _: (Self, Self)) -> (Self, Self) { + ((), ()) + } + fn ration_merge(self, _: u32, _: u32, _: (Self, Self)) -> (Self, Self) + where + Balance: From + Saturating + Div, + { + ((), ()) + } + fn split_merge_into(self, _: Balance, _: &mut (Self, Self)) {} + fn ration_merge_into(self, _: u32, _: u32, _: &mut (Self, Self)) + where + Balance: From + Saturating + Div, + { + } + fn merge(self, _: Self) -> Self { + () + } + fn merge_into(self, _: &mut Self) {} + fn maybe_merge(self, _: Option) -> Self { + () + } + fn subsume(&mut self, _: Self) {} + fn maybe_subsume(&mut self, _: Option) { + () + } + fn offset(self, _: Self::Opposite) -> SameOrOther { + SameOrOther::None + } + fn peek(&self) -> Balance { + Default::default() + } +} diff --git a/frame/system/src/lib.rs b/frame/system/src/lib.rs index 8823aa37c19c..f62d60f6fda9 100644 --- a/frame/system/src/lib.rs +++ b/frame/system/src/lib.rs @@ -344,7 +344,7 @@ pub mod pallet { /// # #[pallet::weight(T::SystemWeightInfo::remark(_remark.len() as u32))] pub fn remark(origin: OriginFor, _remark: Vec) -> DispatchResultWithPostInfo { - ensure_signed(origin)?; + ensure_signed_or_root(origin)?; Ok(().into()) } @@ -872,6 +872,22 @@ where } } +/// Ensure that the origin `o` represents either a signed extrinsic (i.e. transaction) or the root. +/// Returns `Ok` with the account that signed the extrinsic, `None` if it was root, or an `Err` +/// otherwise. +pub fn ensure_signed_or_root( + o: OuterOrigin, +) -> Result, BadOrigin> +where + OuterOrigin: Into, OuterOrigin>>, +{ + match o.into() { + Ok(RawOrigin::Root) => Ok(None), + Ok(RawOrigin::Signed(t)) => Ok(Some(t)), + _ => Err(BadOrigin), + } +} + /// Ensure that the origin `o` represents the root. Returns `Ok` or an `Err` otherwise. pub fn ensure_root(o: OuterOrigin) -> Result<(), BadOrigin> where From c7a3e46d315063d553baeba2bb5ee5b84efdfb1a Mon Sep 17 00:00:00 2001 From: Denis Tsai Date: Sat, 11 Dec 2021 23:20:18 +0800 Subject: [PATCH 284/695] expose ecdsa_sign_prehashed in sp-io (#10119) * expose ecdsa_sign_prehashed in sp-io * add ecdsa_verify_prehashed to host functions for completeness * cargo fmt --- primitives/io/src/lib.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/primitives/io/src/lib.rs b/primitives/io/src/lib.rs index 94ae1a8f7083..44649abd2891 100644 --- a/primitives/io/src/lib.rs +++ b/primitives/io/src/lib.rs @@ -709,6 +709,22 @@ pub trait Crypto { .map(|sig| ecdsa::Signature::from_slice(sig.as_slice())) } + /// Sign the given a pre-hashed `msg` with the `ecdsa` key that corresponds to the given public + /// key and key type in the keystore. + /// + /// Returns the signature. + fn ecdsa_sign_prehashed( + &mut self, + id: KeyTypeId, + pub_key: &ecdsa::Public, + msg: &[u8; 32], + ) -> Option { + let keystore = &***self + .extension::() + .expect("No `keystore` associated for the current context!"); + SyncCryptoStore::ecdsa_sign_prehashed(keystore, id, pub_key, msg).ok().flatten() + } + /// Verify `ecdsa` signature. /// /// Returns `true` when the verification was successful. @@ -724,6 +740,17 @@ pub trait Crypto { ecdsa::Pair::verify(sig, msg, pub_key) } + /// Verify `ecdsa` signature with pre-hashed `msg`. + /// + /// Returns `true` when the verification was successful. + fn ecdsa_verify_prehashed( + sig: &ecdsa::Signature, + msg: &[u8; 32], + pub_key: &ecdsa::Public, + ) -> bool { + ecdsa::Pair::verify_prehashed(sig, msg, pub_key) + } + /// Register a `ecdsa` signature for batch verification. /// /// Batch verification must be enabled by calling [`start_batch_verify`]. From 914f6e50ea39682cb1e881bd3d67f4bcb2c01af9 Mon Sep 17 00:00:00 2001 From: Gavin Wood Date: Sun, 12 Dec 2021 00:41:46 +0100 Subject: [PATCH 285/695] Make Preimage WeightInfo public (#10474) --- frame/preimage/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frame/preimage/src/lib.rs b/frame/preimage/src/lib.rs index bfa1ce526336..2d227000c9ed 100644 --- a/frame/preimage/src/lib.rs +++ b/frame/preimage/src/lib.rs @@ -48,7 +48,7 @@ use frame_support::{ BoundedVec, }; use scale_info::TypeInfo; -use weights::WeightInfo; +pub use weights::WeightInfo; use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; From b9cafba3d0e7a5950ac78d81e4ab7f2074938666 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Mon, 13 Dec 2021 08:23:26 +0100 Subject: [PATCH 286/695] frame-system weights: Remove `set_changes_trie_config`. (#10470) This dispatchable was removed, so we don't need it anymore. --- frame/system/src/weights.rs | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/frame/system/src/weights.rs b/frame/system/src/weights.rs index 281d26375c81..d05ad2a867b5 100644 --- a/frame/system/src/weights.rs +++ b/frame/system/src/weights.rs @@ -48,7 +48,6 @@ pub trait WeightInfo { fn remark(b: u32, ) -> Weight; fn remark_with_event(b: u32, ) -> Weight; fn set_heap_pages() -> Weight; - fn set_changes_trie_config() -> Weight; fn set_storage(i: u32, ) -> Weight; fn kill_storage(i: u32, ) -> Weight; fn kill_prefix(p: u32, ) -> Weight; @@ -72,13 +71,6 @@ impl WeightInfo for SubstrateWeight { (1_891_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - // Storage: System Digest (r:1 w:1) - // Storage: unknown [0x3a6368616e6765735f74726965] (r:0 w:1) - fn set_changes_trie_config() -> Weight { - (7_370_000 as Weight) - .saturating_add(T::DbWeight::get().reads(1 as Weight)) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) - } // Storage: Skipped Metadata (r:0 w:0) fn set_storage(i: u32, ) -> Weight { (0 as Weight) @@ -119,13 +111,6 @@ impl WeightInfo for () { (1_891_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } - // Storage: System Digest (r:1 w:1) - // Storage: unknown [0x3a6368616e6765735f74726965] (r:0 w:1) - fn set_changes_trie_config() -> Weight { - (7_370_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(1 as Weight)) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) - } // Storage: Skipped Metadata (r:0 w:0) fn set_storage(i: u32, ) -> Weight { (0 as Weight) From 55cd07a7e22c26932f7bd16b87ea5a7569e38eb4 Mon Sep 17 00:00:00 2001 From: Gavin Wood Date: Mon, 13 Dec 2021 15:03:59 +0100 Subject: [PATCH 287/695] Remove Default bound for AccountId (#10403) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Remove Default for AccountId * More removals of default * Update frame/authorship/src/lib.rs Co-authored-by: Bastian Köcher * Update frame/authorship/src/lib.rs Co-authored-by: Bastian Köcher * Update frame/authorship/src/lib.rs Co-authored-by: Bastian Köcher * Update frame/authorship/src/lib.rs Co-authored-by: Bastian Köcher * More work * More work * Remove old code * More work * pallet-asset-tx-payment * tips * sc-consensus-babe * sc-finality-grandpa * sc-consensus-babe-rpc * sc-cli * make npos crates accept non-default account (#10420) * minimal changes to make npos pallets all work * make this pesky reduce.rs a bit cleaner * more work * more work * Tests build * Fix imonline tests * Formatting * Fixes * Fixes * Fix bench * Fixes * Fixes * Fixes * Fixes * Fixes * Formatting * Fixes * Formatting * Fixes * Formatting * Fixes * Formatting * Fixes * Formatting * Update client/keystore/src/local.rs Co-authored-by: Bastian Köcher * Update client/finality-grandpa/src/lib.rs Co-authored-by: Bastian Köcher * Update client/keystore/src/local.rs Co-authored-by: Bastian Köcher * Update client/keystore/src/local.rs Co-authored-by: Bastian Köcher * Update frame/staking/src/lib.rs Co-authored-by: Bastian Köcher * Update frame/staking/src/lib.rs Co-authored-by: Bastian Köcher * Update primitives/runtime/src/traits.rs Co-authored-by: Bastian Köcher * Formatting Co-authored-by: Bastian Köcher Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Co-authored-by: kianenigma --- Cargo.lock | 16 +- Cargo.toml | 1 - bin/node-template/node/src/chain_spec.rs | 2 +- bin/node/cli/src/chain_spec.rs | 2 +- bin/node/executor/Cargo.toml | 1 + bin/node/executor/tests/submit_transaction.rs | 16 +- bin/node/runtime/src/impls.rs | 11 +- bin/node/runtime/src/lib.rs | 4 +- bin/node/testing/src/genesis.rs | 6 +- bin/utils/chain-spec-builder/src/main.rs | 2 +- .../basic-authorship/src/basic_authorship.rs | 8 +- client/cli/src/commands/insert_key.rs | 2 +- client/cli/src/commands/inspect_key.rs | 2 +- client/cli/src/commands/verify.rs | 15 +- client/cli/src/error.rs | 12 +- client/cli/src/runner.rs | 4 +- client/consensus/aura/src/lib.rs | 2 +- client/consensus/babe/rpc/src/lib.rs | 2 +- client/consensus/babe/src/authorship.rs | 2 +- client/consensus/babe/src/lib.rs | 2 +- client/consensus/babe/src/verification.rs | 2 +- client/finality-grandpa/rpc/src/lib.rs | 8 +- client/finality-grandpa/src/authorities.rs | 37 +- client/finality-grandpa/src/aux_schema.rs | 12 +- .../src/communication/gossip.rs | 21 +- .../src/communication/tests.rs | 4 +- client/finality-grandpa/src/finality_proof.rs | 10 +- client/finality-grandpa/src/lib.rs | 17 +- client/finality-grandpa/src/tests.rs | 2 +- client/finality-grandpa/src/until_imported.rs | 17 +- client/keystore/src/local.rs | 39 +- client/network/src/service.rs | 2 +- client/rpc/src/author/tests.rs | 12 +- client/service/src/lib.rs | 2 +- client/tracing/proc-macro/src/lib.rs | 8 +- client/transaction-pool/benches/basics.rs | 5 +- client/transaction-pool/src/graph/pool.rs | 7 +- frame/aura/src/lib.rs | 1 - frame/authorship/src/lib.rs | 31 +- frame/babe/src/equivocation.rs | 2 +- frame/babe/src/lib.rs | 2 +- frame/beefy-mmr/src/lib.rs | 2 +- frame/beefy/src/lib.rs | 2 +- frame/benchmarking/src/utils.rs | 12 +- frame/bounties/src/lib.rs | 2 +- frame/collective/src/benchmarking.rs | 36 +- frame/contracts/src/migration.rs | 5 +- frame/democracy/src/benchmarking.rs | 9 +- .../src/benchmarking.rs | 13 +- .../election-provider-multi-phase/src/lib.rs | 2 +- .../src/signed.rs | 20 +- frame/elections-phragmen/src/lib.rs | 17 +- frame/elections/Cargo.toml | 42 - frame/elections/README.md | 7 - frame/elections/src/lib.rs | 1324 ------------ frame/elections/src/mock.rs | 274 --- frame/elections/src/tests.rs | 1881 ----------------- frame/examples/basic/src/lib.rs | 10 + frame/examples/offchain-worker/src/lib.rs | 12 +- frame/examples/offchain-worker/src/tests.rs | 8 +- frame/examples/parallel/src/lib.rs | 8 +- frame/examples/parallel/src/tests.rs | 19 +- frame/grandpa/src/equivocation.rs | 2 +- frame/im-online/src/lib.rs | 1 - frame/im-online/src/mock.rs | 10 +- frame/multisig/src/lib.rs | 5 +- frame/proxy/src/lib.rs | 5 +- frame/session/benchmarking/src/lib.rs | 7 +- frame/session/src/lib.rs | 37 +- frame/staking/src/benchmarking.rs | 22 +- frame/staking/src/lib.rs | 49 +- frame/staking/src/mock.rs | 12 +- frame/staking/src/pallet/impls.rs | 18 +- frame/staking/src/tests.rs | 58 +- frame/sudo/src/lib.rs | 26 +- frame/sudo/src/mock.rs | 2 +- frame/sudo/src/tests.rs | 8 +- frame/support/src/traits/validation.rs | 2 +- frame/support/test/tests/construct_runtime.rs | 18 +- frame/system/src/extensions/check_genesis.rs | 12 +- .../system/src/extensions/check_mortality.rs | 10 + .../src/extensions/check_non_zero_sender.rs | 10 + .../src/extensions/check_spec_version.rs | 15 +- .../system/src/extensions/check_tx_version.rs | 14 +- frame/system/src/extensions/check_weight.rs | 18 +- frame/system/src/lib.rs | 1 - frame/tips/src/lib.rs | 7 +- .../asset-tx-payment/src/lib.rs | 65 +- .../asset-tx-payment/src/tests.rs | 37 +- frame/transaction-payment/src/lib.rs | 31 +- frame/utility/src/lib.rs | 5 +- primitives/api/test/tests/runtime_calls.rs | 2 +- primitives/application-crypto/src/ecdsa.rs | 2 +- primitives/application-crypto/src/ed25519.rs | 2 +- primitives/application-crypto/src/lib.rs | 34 +- primitives/application-crypto/src/sr25519.rs | 2 +- primitives/core/src/crypto.rs | 86 +- primitives/core/src/ecdsa.rs | 38 +- primitives/core/src/ed25519.rs | 43 +- primitives/core/src/lib.rs | 2 +- primitives/core/src/sr25519.rs | 40 +- primitives/io/src/lib.rs | 30 +- primitives/keyring/src/ed25519.rs | 2 +- primitives/keyring/src/sr25519.rs | 2 +- primitives/keystore/src/testing.rs | 12 +- primitives/npos-elections/src/lib.rs | 39 +- primitives/npos-elections/src/pjr.rs | 35 +- primitives/npos-elections/src/reduce.rs | 72 +- primitives/npos-elections/src/tests.rs | 13 +- primitives/npos-elections/src/traits.rs | 4 +- .../runtime/src/generic/checked_extrinsic.rs | 16 +- .../src/generic/unchecked_extrinsic.rs | 12 +- primitives/runtime/src/lib.rs | 37 +- primitives/runtime/src/multiaddress.rs | 6 - primitives/runtime/src/testing.rs | 8 +- primitives/runtime/src/traits.rs | 64 +- .../runtime/transaction-pool/src/lib.rs | 5 +- test-utils/test-runner/src/node.rs | 6 +- 118 files changed, 998 insertions(+), 4181 deletions(-) delete mode 100644 frame/elections/Cargo.toml delete mode 100644 frame/elections/README.md delete mode 100644 frame/elections/src/lib.rs delete mode 100644 frame/elections/src/mock.rs delete mode 100644 frame/elections/src/tests.rs diff --git a/Cargo.lock b/Cargo.lock index ab8132c6b7cd..4bed90287893 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4613,6 +4613,7 @@ dependencies = [ "sp-consensus-babe", "sp-core", "sp-externalities", + "sp-keyring", "sp-keystore", "sp-runtime", "sp-state-machine", @@ -5554,21 +5555,6 @@ dependencies = [ "strum_macros", ] -[[package]] -name = "pallet-elections" -version = "4.0.0-dev" -dependencies = [ - "frame-support", - "frame-system", - "pallet-balances", - "parity-scale-codec", - "scale-info", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", -] - [[package]] name = "pallet-elections-phragmen" version = "5.0.0-dev" diff --git a/Cargo.toml b/Cargo.toml index a26652e39774..93f7d42c8238 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -81,7 +81,6 @@ members = [ "frame/contracts/rpc/runtime-api", "frame/democracy", "frame/try-runtime", - "frame/elections", "frame/election-provider-multi-phase", "frame/election-provider-support", "frame/examples/basic", diff --git a/bin/node-template/node/src/chain_spec.rs b/bin/node-template/node/src/chain_spec.rs index d32a0dcb29d0..af94a63335e0 100644 --- a/bin/node-template/node/src/chain_spec.rs +++ b/bin/node-template/node/src/chain_spec.rs @@ -147,7 +147,7 @@ fn testnet_genesis( }, sudo: SudoConfig { // Assign network admin rights. - key: root_key, + key: Some(root_key), }, transaction_payment: Default::default(), } diff --git a/bin/node/cli/src/chain_spec.rs b/bin/node/cli/src/chain_spec.rs index 6d11722081e3..b29248519cc0 100644 --- a/bin/node/cli/src/chain_spec.rs +++ b/bin/node/cli/src/chain_spec.rs @@ -338,7 +338,7 @@ pub fn testnet_genesis( .collect(), phantom: Default::default(), }, - sudo: SudoConfig { key: root_key }, + sudo: SudoConfig { key: Some(root_key) }, babe: BabeConfig { authorities: vec![], epoch_config: Some(node_runtime::BABE_GENESIS_EPOCH_CONFIG), diff --git a/bin/node/executor/Cargo.toml b/bin/node/executor/Cargo.toml index 2144b9298616..20898315d0e0 100644 --- a/bin/node/executor/Cargo.toml +++ b/bin/node/executor/Cargo.toml @@ -38,6 +38,7 @@ sp-application-crypto = { version = "4.0.0-dev", path = "../../../primitives/app sp-consensus-babe = { version = "0.10.0-dev", path = "../../../primitives/consensus/babe" } sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } sp-externalities = { version = "0.10.0", path = "../../../primitives/externalities" } +sp-keyring = { version = "4.0.0-dev", path = "../../../primitives/keyring" } wat = "1.0" futures = "0.3.9" diff --git a/bin/node/executor/tests/submit_transaction.rs b/bin/node/executor/tests/submit_transaction.rs index 4f0f8061641f..d561e08762df 100644 --- a/bin/node/executor/tests/submit_transaction.rs +++ b/bin/node/executor/tests/submit_transaction.rs @@ -20,6 +20,7 @@ use frame_system::offchain::{SendSignedTransaction, Signer, SubmitTransaction}; use node_runtime::{Executive, Indices, Runtime, UncheckedExtrinsic}; use sp_application_crypto::AppKey; use sp_core::offchain::{testing::TestTransactionPoolExt, TransactionPoolExt}; +use sp_keyring::sr25519::Keyring::Alice; use sp_keystore::{testing::KeyStore, KeystoreExt, SyncCryptoStore}; use std::sync::Arc; @@ -33,7 +34,8 @@ fn should_submit_unsigned_transaction() { t.register_extension(TransactionPoolExt::new(pool)); t.execute_with(|| { - let signature = Default::default(); + let signature = + pallet_im_online::sr25519::AuthoritySignature::try_from(vec![0; 64]).unwrap(); let heartbeat_data = pallet_im_online::Heartbeat { block_number: 1, network_state: Default::default(), @@ -85,7 +87,7 @@ fn should_submit_signed_transaction() { let results = Signer::::all_accounts().send_signed_transaction(|_| { pallet_balances::Call::transfer { - dest: Default::default(), + dest: Alice.to_account_id().into(), value: Default::default(), } }); @@ -122,7 +124,7 @@ fn should_submit_signed_twice_from_the_same_account() { let result = Signer::::any_account().send_signed_transaction(|_| { pallet_balances::Call::transfer { - dest: Default::default(), + dest: Alice.to_account_id().into(), value: Default::default(), } }); @@ -134,7 +136,7 @@ fn should_submit_signed_twice_from_the_same_account() { let result = Signer::::any_account().send_signed_transaction(|_| { pallet_balances::Call::transfer { - dest: Default::default(), + dest: Alice.to_account_id().into(), value: Default::default(), } }); @@ -172,7 +174,7 @@ fn should_submit_signed_twice_from_all_accounts() { t.execute_with(|| { let results = Signer::::all_accounts() .send_signed_transaction(|_| { - pallet_balances::Call::transfer { dest: Default::default(), value: Default::default() } + pallet_balances::Call::transfer { dest: Alice.to_account_id().into(), value: Default::default() } }); let len = results.len(); @@ -183,7 +185,7 @@ fn should_submit_signed_twice_from_all_accounts() { // submit another one from the same account. The nonce should be incremented. let results = Signer::::all_accounts() .send_signed_transaction(|_| { - pallet_balances::Call::transfer { dest: Default::default(), value: Default::default() } + pallet_balances::Call::transfer { dest: Alice.to_account_id().into(), value: Default::default() } }); let len = results.len(); @@ -237,7 +239,7 @@ fn submitted_transaction_should_be_valid() { let results = Signer::::all_accounts().send_signed_transaction(|_| { pallet_balances::Call::transfer { - dest: Default::default(), + dest: Alice.to_account_id().into(), value: Default::default(), } }); diff --git a/bin/node/runtime/src/impls.rs b/bin/node/runtime/src/impls.rs index cdd9f0900fd3..689dc8c23fb4 100644 --- a/bin/node/runtime/src/impls.rs +++ b/bin/node/runtime/src/impls.rs @@ -27,7 +27,9 @@ use pallet_asset_tx_payment::HandleCredit; pub struct Author; impl OnUnbalanced for Author { fn on_nonzero_unbalanced(amount: NegativeImbalance) { - Balances::resolve_creating(&Authorship::author(), amount); + if let Some(author) = Authorship::author() { + Balances::resolve_creating(&author, amount); + } } } @@ -36,9 +38,10 @@ impl OnUnbalanced for Author { pub struct CreditToBlockAuthor; impl HandleCredit for CreditToBlockAuthor { fn handle_credit(credit: CreditOf) { - let author = pallet_authorship::Pallet::::author(); - // Drop the result which will trigger the `OnDrop` of the imbalance in case of error. - let _ = Assets::resolve(&author, credit); + if let Some(author) = pallet_authorship::Pallet::::author() { + // Drop the result which will trigger the `OnDrop` of the imbalance in case of error. + let _ = Assets::resolve(&author, credit); + } } } diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index bd4bb450c749..e61a46abeb72 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -1835,8 +1835,8 @@ mod tests { fn call_size() { let size = core::mem::size_of::(); assert!( - size <= 200, - "size of Call {} is more than 200 bytes: some calls have too big arguments, use Box to reduce the + size <= 208, + "size of Call {} is more than 208 bytes: some calls have too big arguments, use Box to reduce the size of Call. If the limit is too strong, maybe consider increase the limit to 300.", size, diff --git a/bin/node/testing/src/genesis.rs b/bin/node/testing/src/genesis.rs index fa0dd22c9c99..52296230b055 100644 --- a/bin/node/testing/src/genesis.rs +++ b/bin/node/testing/src/genesis.rs @@ -54,11 +54,11 @@ pub fn config_endowed(code: Option<&[u8]>, extra_endowed: Vec) -> Gen balances: BalancesConfig { balances: endowed }, session: SessionConfig { keys: vec![ - (dave(), alice(), to_session_keys(&Ed25519Keyring::Alice, &Sr25519Keyring::Alice)), - (eve(), bob(), to_session_keys(&Ed25519Keyring::Bob, &Sr25519Keyring::Bob)), + (alice(), dave(), to_session_keys(&Ed25519Keyring::Alice, &Sr25519Keyring::Alice)), + (bob(), eve(), to_session_keys(&Ed25519Keyring::Bob, &Sr25519Keyring::Bob)), ( - ferdie(), charlie(), + ferdie(), to_session_keys(&Ed25519Keyring::Charlie, &Sr25519Keyring::Charlie), ), ], diff --git a/bin/utils/chain-spec-builder/src/main.rs b/bin/utils/chain-spec-builder/src/main.rs index bf5f1a149578..f45031f1eb81 100644 --- a/bin/utils/chain-spec-builder/src/main.rs +++ b/bin/utils/chain-spec-builder/src/main.rs @@ -29,7 +29,7 @@ use structopt::StructOpt; use node_cli::chain_spec::{self, AccountId}; use sc_keystore::LocalKeystore; use sp_core::{ - crypto::{Public, Ss58Codec}, + crypto::{ByteArray, Ss58Codec}, sr25519, }; use sp_keystore::{SyncCryptoStore, SyncCryptoStorePtr}; diff --git a/client/basic-authorship/src/basic_authorship.rs b/client/basic-authorship/src/basic_authorship.rs index 70633925c5ba..e79fc1f03a54 100644 --- a/client/basic-authorship/src/basic_authorship.rs +++ b/client/basic-authorship/src/basic_authorship.rs @@ -581,7 +581,7 @@ mod tests { amount: Default::default(), nonce, from: AccountKeyring::Alice.into(), - to: Default::default(), + to: AccountKeyring::Bob.into(), } .into_signed_tx() } @@ -593,7 +593,7 @@ mod tests { amount: 1, nonce: 0, from: pair.public(), - to: Default::default(), + to: AccountKeyring::Bob.into(), }; let signature = pair.sign(&transfer.encode()).into(); Extrinsic::Transfer { transfer, signature, exhaust_resources_when_not_first: true } @@ -777,14 +777,14 @@ mod tests { amount: Default::default(), nonce: 2, from: AccountKeyring::Alice.into(), - to: Default::default(), + to: AccountKeyring::Bob.into(), }.into_resources_exhausting_tx(), extrinsic(3), Transfer { amount: Default::default(), nonce: 4, from: AccountKeyring::Alice.into(), - to: Default::default(), + to: AccountKeyring::Bob.into(), }.into_resources_exhausting_tx(), extrinsic(5), extrinsic(6), diff --git a/client/cli/src/commands/insert_key.rs b/client/cli/src/commands/insert_key.rs index 081c31908160..e85b85f111ad 100644 --- a/client/cli/src/commands/insert_key.rs +++ b/client/cli/src/commands/insert_key.rs @@ -99,7 +99,7 @@ fn to_vec(uri: &str, pass: Option) -> Result( #[cfg(test)] mod tests { use super::*; - use sp_core::crypto::{Pair, Public}; + use sp_core::crypto::{ByteArray, Pair}; use sp_runtime::traits::IdentifyAccount; use structopt::StructOpt; diff --git a/client/cli/src/commands/verify.rs b/client/cli/src/commands/verify.rs index 760793374242..0dce444a2859 100644 --- a/client/cli/src/commands/verify.rs +++ b/client/cli/src/commands/verify.rs @@ -19,7 +19,7 @@ //! implementation of the `verify` subcommand use crate::{error, utils, with_crypto_scheme, CryptoSchemeFlag}; -use sp_core::{crypto::Ss58Codec, Public}; +use sp_core::crypto::{ByteArray, Ss58Codec}; use structopt::StructOpt; /// The `verify` command @@ -66,19 +66,14 @@ impl VerifyCmd { fn verify(sig_data: Vec, message: Vec, uri: &str) -> error::Result<()> where Pair: sp_core::Pair, - Pair::Signature: Default + AsMut<[u8]>, + Pair::Signature: for<'a> std::convert::TryFrom<&'a [u8]>, { - let mut signature = Pair::Signature::default(); - if sig_data.len() != signature.as_ref().len() { - return Err(error::Error::SignatureInvalidLength { - read: sig_data.len(), - expected: signature.as_ref().len(), - }) - } - signature.as_mut().copy_from_slice(&sig_data); + let signature = + Pair::Signature::try_from(&sig_data).map_err(|_| error::Error::SignatureFormatInvalid)?; let pubkey = if let Ok(pubkey_vec) = hex::decode(uri) { Pair::Public::from_slice(pubkey_vec.as_slice()) + .map_err(|_| error::Error::KeyFormatInvalid)? } else { Pair::Public::from_string(uri)? }; diff --git a/client/cli/src/error.rs b/client/cli/src/error.rs index c5784b201817..9a09e560063e 100644 --- a/client/cli/src/error.rs +++ b/client/cli/src/error.rs @@ -51,13 +51,11 @@ pub enum Error { #[error("Invalid URI; expecting either a secret URI or a public URI.")] InvalidUri(crypto::PublicError), - #[error("Signature has an invalid length. Read {read} bytes, expected {expected} bytes")] - SignatureInvalidLength { - /// Amount of signature bytes read. - read: usize, - /// Expected number of signature bytes. - expected: usize, - }, + #[error("Signature is an invalid format.")] + SignatureFormatInvalid, + + #[error("Key is an invalid format.")] + KeyFormatInvalid, #[error("Unknown key type, must be a known 4-character sequence")] KeyTypeInvalid, diff --git a/client/cli/src/runner.rs b/client/cli/src/runner.rs index 640b87584d4b..34c194801213 100644 --- a/client/cli/src/runner.rs +++ b/client/cli/src/runner.rs @@ -132,7 +132,7 @@ impl Runner { /// 2020-06-03 16:14:21 ✌️ version 2.0.0-rc3-f4940588c-x86_64-linux-gnu /// 2020-06-03 16:14:21 ❤️ by Parity Technologies , 2017-2020 /// 2020-06-03 16:14:21 📋 Chain specification: Flaming Fir - /// 2020-06-03 16:14:21 🏷 Node name: jolly-rod-7462 + /// 2020-06-03 16:14:21 🏷 Node name: jolly-rod-7462 /// 2020-06-03 16:14:21 👤 Role: FULL /// 2020-06-03 16:14:21 💾 Database: RocksDb at /tmp/c/chains/flamingfir7/db /// 2020-06-03 16:14:21 ⛓ Native runtime: node-251 (substrate-node-1.tx1.au10) @@ -199,7 +199,7 @@ pub fn print_node_infos(config: &Configuration) { info!("✌️ version {}", C::impl_version()); info!("❤️ by {}, {}-{}", C::author(), C::copyright_start_year(), Local::today().year()); info!("📋 Chain specification: {}", config.chain_spec.name()); - info!("🏷 Node name: {}", config.network.node_name); + info!("🏷 Node name: {}", config.network.node_name); info!("👤 Role: {}", config.display_role()); info!( "💾 Database: {} at {}", diff --git a/client/consensus/aura/src/lib.rs b/client/consensus/aura/src/lib.rs index 16880ae188ad..0d79e3c4ecf0 100644 --- a/client/consensus/aura/src/lib.rs +++ b/client/consensus/aura/src/lib.rs @@ -57,7 +57,7 @@ use sp_consensus::{ BlockOrigin, CanAuthorWith, Environment, Error as ConsensusError, Proposer, SelectChain, }; use sp_consensus_slots::Slot; -use sp_core::crypto::{Pair, Public}; +use sp_core::crypto::{ByteArray, Pair, Public}; use sp_inherents::CreateInherentDataProviders; use sp_keystore::{SyncCryptoStore, SyncCryptoStorePtr}; use sp_runtime::{ diff --git a/client/consensus/babe/rpc/src/lib.rs b/client/consensus/babe/rpc/src/lib.rs index 285cfe543cee..eeec7b86b1f1 100644 --- a/client/consensus/babe/rpc/src/lib.rs +++ b/client/consensus/babe/rpc/src/lib.rs @@ -30,7 +30,7 @@ use sp_application_crypto::AppKey; use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata}; use sp_consensus::{Error as ConsensusError, SelectChain}; use sp_consensus_babe::{digests::PreDigest, AuthorityId, BabeApi as BabeRuntimeApi}; -use sp_core::crypto::Public; +use sp_core::crypto::ByteArray; use sp_keystore::{SyncCryptoStore, SyncCryptoStorePtr}; use sp_runtime::traits::{Block as BlockT, Header as _}; use std::{collections::HashMap, sync::Arc}; diff --git a/client/consensus/babe/src/authorship.rs b/client/consensus/babe/src/authorship.rs index 609f96c83c19..1bee73f40858 100644 --- a/client/consensus/babe/src/authorship.rs +++ b/client/consensus/babe/src/authorship.rs @@ -27,7 +27,7 @@ use sp_consensus_babe::{ make_transcript, make_transcript_data, AuthorityId, BabeAuthorityWeight, Slot, BABE_VRF_PREFIX, }; use sp_consensus_vrf::schnorrkel::{VRFOutput, VRFProof}; -use sp_core::{blake2_256, crypto::Public, U256}; +use sp_core::{blake2_256, crypto::ByteArray, U256}; use sp_keystore::{SyncCryptoStore, SyncCryptoStorePtr}; /// Calculates the primary selection threshold for a given authority, taking diff --git a/client/consensus/babe/src/lib.rs b/client/consensus/babe/src/lib.rs index 4fb9f750004c..168cdff43cda 100644 --- a/client/consensus/babe/src/lib.rs +++ b/client/consensus/babe/src/lib.rs @@ -110,7 +110,7 @@ use sp_consensus::{ }; use sp_consensus_babe::inherents::BabeInherentData; use sp_consensus_slots::Slot; -use sp_core::{crypto::Public, ExecutionContext}; +use sp_core::{crypto::ByteArray, ExecutionContext}; use sp_inherents::{CreateInherentDataProviders, InherentData, InherentDataProvider}; use sp_keystore::{SyncCryptoStore, SyncCryptoStorePtr}; use sp_runtime::{ diff --git a/client/consensus/babe/src/verification.rs b/client/consensus/babe/src/verification.rs index 2322a9626216..13d2f956c8d5 100644 --- a/client/consensus/babe/src/verification.rs +++ b/client/consensus/babe/src/verification.rs @@ -31,7 +31,7 @@ use sp_consensus_babe::{ make_transcript, AuthorityId, AuthorityPair, AuthoritySignature, }; use sp_consensus_slots::Slot; -use sp_core::{Pair, Public}; +use sp_core::{ByteArray, Pair}; use sp_runtime::{traits::Header, DigestItem}; /// BABE verification parameters diff --git a/client/finality-grandpa/rpc/src/lib.rs b/client/finality-grandpa/rpc/src/lib.rs index b8b8b2d95646..3e7fddfddf2f 100644 --- a/client/finality-grandpa/rpc/src/lib.rs +++ b/client/finality-grandpa/rpc/src/lib.rs @@ -179,7 +179,7 @@ mod tests { report, AuthorityId, FinalityProof, GrandpaJustification, GrandpaJustificationSender, }; use sp_blockchain::HeaderBackend; - use sp_core::crypto::Public; + use sp_core::crypto::ByteArray; use sp_keyring::Ed25519Keyring; use sp_runtime::traits::{Block as BlockT, Header as HeaderT}; use substrate_test_runtime_client::{ @@ -196,8 +196,8 @@ mod tests { } fn voters() -> HashSet { - let voter_id_1 = AuthorityId::from_slice(&[1; 32]); - let voter_id_2 = AuthorityId::from_slice(&[2; 32]); + let voter_id_1 = AuthorityId::from_slice(&[1; 32]).unwrap(); + let voter_id_2 = AuthorityId::from_slice(&[2; 32]).unwrap(); vec![voter_id_1, voter_id_2].into_iter().collect() } @@ -245,7 +245,7 @@ mod tests { impl ReportVoterState for TestVoterState { fn get(&self) -> Option> { - let voter_id_1 = AuthorityId::from_slice(&[1; 32]); + let voter_id_1 = AuthorityId::from_slice(&[1; 32]).unwrap(); let voters_best: HashSet<_> = vec![voter_id_1].into_iter().collect(); let best_round_state = sc_finality_grandpa::report::RoundState { diff --git a/client/finality-grandpa/src/authorities.rs b/client/finality-grandpa/src/authorities.rs index 6eb13099aa20..6ab36847fe3d 100644 --- a/client/finality-grandpa/src/authorities.rs +++ b/client/finality-grandpa/src/authorities.rs @@ -753,7 +753,7 @@ impl AuthoritySetChanges { #[cfg(test)] mod tests { use super::*; - use sp_core::crypto::Public; + use sp_core::crypto::{ByteArray, UncheckedFrom}; fn static_is_descendent_of(value: bool) -> impl Fn(&A, &A) -> Result { move |_, _| Ok(value) @@ -768,7 +768,7 @@ mod tests { #[test] fn current_limit_filters_min() { - let current_authorities = vec![(AuthorityId::from_slice(&[1; 32]), 1)]; + let current_authorities = vec![(AuthorityId::from_slice(&[1; 32]).unwrap(), 1)]; let mut authorities = AuthoritySet { current_authorities: current_authorities.clone(), @@ -802,7 +802,7 @@ mod tests { #[test] fn changes_iterated_in_pre_order() { - let current_authorities = vec![(AuthorityId::from_slice(&[1; 32]), 1)]; + let current_authorities = vec![(AuthorityId::from_slice(&[1; 32]).unwrap(), 1)]; let mut authorities = AuthoritySet { current_authorities: current_authorities.clone(), @@ -894,8 +894,8 @@ mod tests { authority_set_changes: AuthoritySetChanges::empty(), }; - let set_a = vec![(AuthorityId::from_slice(&[1; 32]), 5)]; - let set_b = vec![(AuthorityId::from_slice(&[2; 32]), 5)]; + let set_a = vec![(AuthorityId::from_slice(&[1; 32]).unwrap(), 5)]; + let set_b = vec![(AuthorityId::from_slice(&[2; 32]).unwrap(), 5)]; // two competing changes at the same height on different forks let change_a = PendingChange { @@ -977,8 +977,8 @@ mod tests { authority_set_changes: AuthoritySetChanges::empty(), }; - let set_a = vec![(AuthorityId::from_slice(&[1; 32]), 5)]; - let set_c = vec![(AuthorityId::from_slice(&[2; 32]), 5)]; + let set_a = vec![(AuthorityId::from_slice(&[1; 32]).unwrap(), 5)]; + let set_c = vec![(AuthorityId::from_slice(&[2; 32]).unwrap(), 5)]; // two competing changes at the same height on different forks let change_a = PendingChange { @@ -1057,7 +1057,7 @@ mod tests { authority_set_changes: AuthoritySetChanges::empty(), }; - let set_a = vec![(AuthorityId::from_slice(&[1; 32]), 5)]; + let set_a = vec![(AuthorityId::from_slice(&[1; 32]).unwrap(), 5)]; let change_a = PendingChange { next_authorities: set_a.clone(), @@ -1128,8 +1128,8 @@ mod tests { authority_set_changes: AuthoritySetChanges::empty(), }; - let set_a = vec![(AuthorityId::from_slice(&[1; 32]), 5)]; - let set_b = vec![(AuthorityId::from_slice(&[2; 32]), 5)]; + let set_a = vec![(AuthorityId::from_slice(&[1; 32]).unwrap(), 5)]; + let set_b = vec![(AuthorityId::from_slice(&[2; 32]).unwrap(), 5)]; let change_a = PendingChange { next_authorities: set_a.clone(), @@ -1228,7 +1228,7 @@ mod tests { authority_set_changes: AuthoritySetChanges::empty(), }; - let set_a = vec![(AuthorityId::from_slice(&[1; 32]), 5)]; + let set_a = vec![(AuthorityId::from_slice(&[1; 32]).unwrap(), 5)]; // we create a forced change with no delay let change_a = PendingChange { @@ -1253,7 +1253,7 @@ mod tests { #[test] fn forced_changes_blocked_by_standard_changes() { - let set_a = vec![(AuthorityId::from_slice(&[1; 32]), 1)]; + let set_a = vec![(AuthorityId::from_slice(&[1; 32]).unwrap(), 1)]; let mut authorities = AuthoritySet { current_authorities: set_a.clone(), @@ -1378,7 +1378,7 @@ mod tests { #[test] fn next_change_works() { - let current_authorities = vec![(AuthorityId::from_slice(&[1; 32]), 1)]; + let current_authorities = vec![(AuthorityId::from_slice(&[1; 32]).unwrap(), 1)]; let mut authorities = AuthoritySet { current_authorities: current_authorities.clone(), @@ -1493,8 +1493,10 @@ mod tests { None, ); - let invalid_authorities_weight = - vec![(AuthorityId::from_slice(&[1; 32]), 5), (AuthorityId::from_slice(&[2; 32]), 0)]; + let invalid_authorities_weight = vec![ + (AuthorityId::from_slice(&[1; 32]).unwrap(), 5), + (AuthorityId::from_slice(&[2; 32]).unwrap(), 0), + ]; // authority weight of zero is invalid assert_eq!(AuthoritySet::<(), ()>::genesis(invalid_authorities_weight.clone()), None); @@ -1510,7 +1512,8 @@ mod tests { ); let mut authority_set = - AuthoritySet::<(), u64>::genesis(vec![(AuthorityId::from_slice(&[1; 32]), 5)]).unwrap(); + AuthoritySet::<(), u64>::genesis(vec![(AuthorityId::unchecked_from([1; 32]), 5)]) + .unwrap(); let invalid_change_empty_authorities = PendingChange { next_authorities: vec![], @@ -1550,7 +1553,7 @@ mod tests { #[test] fn cleans_up_stale_forced_changes_when_applying_standard_change() { - let current_authorities = vec![(AuthorityId::from_slice(&[1; 32]), 1)]; + let current_authorities = vec![(AuthorityId::from_slice(&[1; 32]).unwrap(), 1)]; let mut authorities = AuthoritySet { current_authorities: current_authorities.clone(), diff --git a/client/finality-grandpa/src/aux_schema.rs b/client/finality-grandpa/src/aux_schema.rs index bad01e6dfc62..9294fbc4161b 100644 --- a/client/finality-grandpa/src/aux_schema.rs +++ b/client/finality-grandpa/src/aux_schema.rs @@ -498,15 +498,19 @@ pub(crate) fn load_authorities( #[cfg(test)] mod test { use super::*; - use sp_core::H256; + use sp_core::{crypto::UncheckedFrom, H256}; use sp_finality_grandpa::AuthorityId; use substrate_test_runtime_client; + fn dummy_id() -> AuthorityId { + AuthorityId::unchecked_from([1; 32]) + } + #[test] fn load_decode_from_v0_migrates_data_format() { let client = substrate_test_runtime_client::new(); - let authorities = vec![(AuthorityId::default(), 100)]; + let authorities = vec![(dummy_id(), 100)]; let set_id = 3; let round_number: RoundNumber = 42; let round_state = RoundState:: { @@ -595,7 +599,7 @@ mod test { fn load_decode_from_v1_migrates_data_format() { let client = substrate_test_runtime_client::new(); - let authorities = vec![(AuthorityId::default(), 100)]; + let authorities = vec![(dummy_id(), 100)]; let set_id = 3; let round_number: RoundNumber = 42; let round_state = RoundState:: { @@ -688,7 +692,7 @@ mod test { fn load_decode_from_v2_migrates_data_format() { let client = substrate_test_runtime_client::new(); - let authorities = vec![(AuthorityId::default(), 100)]; + let authorities = vec![(dummy_id(), 100)]; let set_id = 3; { diff --git a/client/finality-grandpa/src/communication/gossip.rs b/client/finality-grandpa/src/communication/gossip.rs index 8a3b6afcad32..74e7cc530065 100644 --- a/client/finality-grandpa/src/communication/gossip.rs +++ b/client/finality-grandpa/src/communication/gossip.rs @@ -1670,7 +1670,7 @@ mod tests { use sc_network::config::Role; use sc_network_gossip::Validator as GossipValidatorT; use sc_network_test::Block; - use sp_core::{crypto::Public, H256}; + use sp_core::{crypto::UncheckedFrom, H256}; // some random config (not really needed) fn config() -> crate::Config { @@ -1691,7 +1691,7 @@ mod tests { let base = (H256::zero(), 0); - let voters = vec![(AuthorityId::from_slice(&[1; 32]), 1)]; + let voters = vec![(AuthorityId::unchecked_from([1; 32]), 1)]; let voters = AuthoritySet::genesis(voters).unwrap(); let set_state = VoterSetState::live(0, &voters, base); @@ -1861,7 +1861,7 @@ mod tests { let (val, _) = GossipValidator::::new(config(), voter_set_state(), None, None); let set_id = 1; - let auth = AuthorityId::from_slice(&[1u8; 32]); + let auth = AuthorityId::unchecked_from([1u8; 32]); let peer = PeerId::random(); val.note_set(SetId(set_id), vec![auth.clone()], |_, _| {}); @@ -1878,8 +1878,8 @@ mod tests { target_hash: Default::default(), target_number: 10, }), - signature: Default::default(), - id: AuthorityId::from_slice(&[2u8; 32]), + signature: UncheckedFrom::unchecked_from([1; 64]), + id: UncheckedFrom::unchecked_from([2u8; 32]), }, }, ); @@ -1894,7 +1894,7 @@ mod tests { target_hash: Default::default(), target_number: 10, }), - signature: Default::default(), + signature: UncheckedFrom::unchecked_from([1; 64]), id: auth.clone(), }, }, @@ -1909,7 +1909,7 @@ mod tests { let (val, _) = GossipValidator::::new(config(), voter_set_state(), None, None); let set_id = 1; - let auth = AuthorityId::from_slice(&[1u8; 32]); + let auth = AuthorityId::unchecked_from([1u8; 32]); let peer = PeerId::random(); val.note_set(SetId(set_id), vec![auth.clone()], |_, _| {}); @@ -1972,7 +1972,7 @@ mod tests { let (val, _) = GossipValidator::::new(config(), set_state.clone(), None, None); let set_id = 1; - let auth = AuthorityId::from_slice(&[1u8; 32]); + let auth = AuthorityId::unchecked_from([1u8; 32]); let peer = PeerId::random(); val.note_set(SetId(set_id), vec![auth.clone()], |_, _| {}); @@ -2550,12 +2550,13 @@ mod tests { fn allow_noting_different_authorities_for_same_set() { let (val, _) = GossipValidator::::new(config(), voter_set_state(), None, None); - let a1 = vec![AuthorityId::from_slice(&[0; 32])]; + let a1 = vec![UncheckedFrom::unchecked_from([0; 32])]; val.note_set(SetId(1), a1.clone(), |_, _| {}); assert_eq!(val.inner().read().authorities, a1); - let a2 = vec![AuthorityId::from_slice(&[1; 32]), AuthorityId::from_slice(&[2; 32])]; + let a2 = + vec![UncheckedFrom::unchecked_from([1; 32]), UncheckedFrom::unchecked_from([2; 32])]; val.note_set(SetId(1), a2.clone(), |_, _| {}); assert_eq!(val.inner().read().authorities, a2); diff --git a/client/finality-grandpa/src/communication/tests.rs b/client/finality-grandpa/src/communication/tests.rs index 1fac0230b2a8..1e88f8a93404 100644 --- a/client/finality-grandpa/src/communication/tests.rs +++ b/client/finality-grandpa/src/communication/tests.rs @@ -155,13 +155,13 @@ fn config() -> crate::Config { fn voter_set_state() -> SharedVoterSetState { use crate::{authorities::AuthoritySet, environment::VoterSetState}; use finality_grandpa::round::State as RoundState; - use sp_core::{crypto::Public, H256}; + use sp_core::{crypto::ByteArray, H256}; use sp_finality_grandpa::AuthorityId; let state = RoundState::genesis((H256::zero(), 0)); let base = state.prevote_ghost.unwrap(); - let voters = vec![(AuthorityId::from_slice(&[1; 32]), 1)]; + let voters = vec![(AuthorityId::from_slice(&[1; 32]).unwrap(), 1)]; let voters = AuthoritySet::genesis(voters).unwrap(); let set_state = VoterSetState::live(0, &voters, base); diff --git a/client/finality-grandpa/src/finality_proof.rs b/client/finality-grandpa/src/finality_proof.rs index 1e20c2edc3a6..ac7be37eb20c 100644 --- a/client/finality-grandpa/src/finality_proof.rs +++ b/client/finality-grandpa/src/finality_proof.rs @@ -243,8 +243,8 @@ pub(crate) mod tests { use sc_block_builder::BlockBuilderProvider; use sc_client_api::{apply_aux, LockImportRun}; use sp_consensus::BlockOrigin; - use sp_core::crypto::Public; - use sp_finality_grandpa::{AuthorityId, GRANDPA_ENGINE_ID as ID}; + use sp_core::crypto::UncheckedFrom; + use sp_finality_grandpa::GRANDPA_ENGINE_ID as ID; use sp_keyring::Ed25519Keyring; use substrate_test_runtime_client::{ runtime::{Block, Header, H256}, @@ -350,7 +350,7 @@ pub(crate) mod tests { // When we can't decode proof from Vec check_finality_proof::( 1, - vec![(AuthorityId::from_slice(&[3u8; 32]), 1u64)], + vec![(UncheckedFrom::unchecked_from([3u8; 32]), 1u64)], vec![42], ) .unwrap_err(); @@ -361,7 +361,7 @@ pub(crate) mod tests { // When decoded proof has zero length check_finality_proof::( 1, - vec![(AuthorityId::from_slice(&[3u8; 32]), 1u64)], + vec![(UncheckedFrom::unchecked_from([3u8; 32]), 1u64)], Vec::>::new().encode(), ) .unwrap_err(); @@ -387,7 +387,7 @@ pub(crate) mod tests { check_finality_proof::( 1, - vec![(AuthorityId::from_slice(&[3u8; 32]), 1u64)], + vec![(UncheckedFrom::unchecked_from([3u8; 32]), 1u64)], finality_proof.encode(), ) .unwrap_err(); diff --git a/client/finality-grandpa/src/lib.rs b/client/finality-grandpa/src/lib.rs index b30006646947..656d8ea43434 100644 --- a/client/finality-grandpa/src/lib.rs +++ b/client/finality-grandpa/src/lib.rs @@ -73,7 +73,7 @@ use sp_api::ProvideRuntimeApi; use sp_application_crypto::AppKey; use sp_blockchain::{Error as ClientError, HeaderBackend, HeaderMetadata}; use sp_consensus::SelectChain; -use sp_core::crypto::Public; +use sp_core::crypto::ByteArray; use sp_keystore::{SyncCryptoStore, SyncCryptoStorePtr}; use sp_runtime::{ generic::BlockId, @@ -786,8 +786,8 @@ where let events = telemetry_on_connect.for_each(move |_| { let current_authorities = authorities.current_authorities(); let set_id = authorities.set_id(); - let authority_id = local_authority_id(¤t_authorities, conf.keystore.as_ref()) - .unwrap_or_default(); + let maybe_authority_id = + local_authority_id(¤t_authorities, conf.keystore.as_ref()); let authorities = current_authorities.iter().map(|(id, _)| id.to_string()).collect::>(); @@ -801,7 +801,7 @@ where telemetry; CONSENSUS_INFO; "afg.authority_set"; - "authority_id" => authority_id.to_string(), + "authority_id" => maybe_authority_id.map_or("".into(), |s| s.to_string()), "authority_set_id" => ?set_id, "authorities" => authorities, ); @@ -940,8 +940,9 @@ where fn rebuild_voter(&mut self) { debug!(target: "afg", "{}: Starting new voter with set ID {}", self.env.config.name(), self.env.set_id); - let authority_id = local_authority_id(&self.env.voters, self.env.config.keystore.as_ref()) - .unwrap_or_default(); + let maybe_authority_id = + local_authority_id(&self.env.voters, self.env.config.keystore.as_ref()); + let authority_id = maybe_authority_id.map_or("".into(), |s| s.to_string()); telemetry!( self.telemetry; @@ -949,7 +950,7 @@ where "afg.starting_new_voter"; "name" => ?self.env.config.name(), "set_id" => ?self.env.set_id, - "authority_id" => authority_id.to_string(), + "authority_id" => authority_id, ); let chain_info = self.env.client.info(); @@ -966,7 +967,7 @@ where "afg.authority_set"; "number" => ?chain_info.finalized_number, "hash" => ?chain_info.finalized_hash, - "authority_id" => authority_id.to_string(), + "authority_id" => authority_id, "authority_set_id" => ?self.env.set_id, "authorities" => authorities, ); diff --git a/client/finality-grandpa/src/tests.rs b/client/finality-grandpa/src/tests.rs index 8439bf6963d0..7af02d066be3 100644 --- a/client/finality-grandpa/src/tests.rs +++ b/client/finality-grandpa/src/tests.rs @@ -1671,7 +1671,7 @@ fn grandpa_environment_doesnt_send_equivocation_reports_for_itself() { // if we set the equivocation offender to another id for which we don't have // keys it should work - equivocation.identity = Default::default(); + equivocation.identity = TryFrom::try_from(&[1; 32][..]).unwrap(); let equivocation_proof = sp_finality_grandpa::Equivocation::Prevote(equivocation); assert!(environment.report_equivocation(equivocation_proof).is_ok()); } diff --git a/client/finality-grandpa/src/until_imported.rs b/client/finality-grandpa/src/until_imported.rs index e2c00b54ea06..430db23d6220 100644 --- a/client/finality-grandpa/src/until_imported.rs +++ b/client/finality-grandpa/src/until_imported.rs @@ -563,6 +563,7 @@ mod tests { use sc_client_api::BlockImportNotification; use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedSender}; use sp_consensus::BlockOrigin; + use sp_core::crypto::UncheckedFrom; use substrate_test_runtime_client::runtime::{Block, Hash, Header}; #[derive(Clone)] @@ -796,8 +797,8 @@ mod tests { let h3 = make_header(7); let signed_prevote = |header: &Header| finality_grandpa::SignedPrevote { - id: Default::default(), - signature: Default::default(), + id: UncheckedFrom::unchecked_from([1; 32]), + signature: UncheckedFrom::unchecked_from([1; 64]), prevote: finality_grandpa::Prevote { target_hash: header.hash(), target_number: *header.number(), @@ -805,8 +806,8 @@ mod tests { }; let signed_precommit = |header: &Header| finality_grandpa::SignedPrecommit { - id: Default::default(), - signature: Default::default(), + id: UncheckedFrom::unchecked_from([1; 32]), + signature: UncheckedFrom::unchecked_from([1; 64]), precommit: finality_grandpa::Precommit { target_hash: header.hash(), target_number: *header.number(), @@ -844,8 +845,8 @@ mod tests { let h3 = make_header(7); let signed_prevote = |header: &Header| finality_grandpa::SignedPrevote { - id: Default::default(), - signature: Default::default(), + id: UncheckedFrom::unchecked_from([1; 32]), + signature: UncheckedFrom::unchecked_from([1; 64]), prevote: finality_grandpa::Prevote { target_hash: header.hash(), target_number: *header.number(), @@ -853,8 +854,8 @@ mod tests { }; let signed_precommit = |header: &Header| finality_grandpa::SignedPrecommit { - id: Default::default(), - signature: Default::default(), + id: UncheckedFrom::unchecked_from([1; 32]), + signature: UncheckedFrom::unchecked_from([1; 64]), precommit: finality_grandpa::Precommit { target_hash: header.hash(), target_number: *header.number(), diff --git a/client/keystore/src/local.rs b/client/keystore/src/local.rs index d5a7fd93d7dc..be9bb5e14597 100644 --- a/client/keystore/src/local.rs +++ b/client/keystore/src/local.rs @@ -21,7 +21,9 @@ use async_trait::async_trait; use parking_lot::RwLock; use sp_application_crypto::{ecdsa, ed25519, sr25519, AppKey, AppPair, IsWrappedBy}; use sp_core::{ - crypto::{CryptoTypePublicPair, ExposeSecret, KeyTypeId, Pair as PairT, Public, SecretString}, + crypto::{ + ByteArray, CryptoTypePublicPair, ExposeSecret, KeyTypeId, Pair as PairT, SecretString, + }, sr25519::{Pair as Sr25519Pair, Public as Sr25519Public}, Encode, }; @@ -189,7 +191,9 @@ impl SyncCryptoStore for LocalKeystore { ) -> std::result::Result>, TraitError> { match key.0 { ed25519::CRYPTO_ID => { - let pub_key = ed25519::Public::from_slice(key.1.as_slice()); + let pub_key = ed25519::Public::from_slice(key.1.as_slice()).map_err(|()| { + TraitError::Other("Corrupted public key - Invalid size".into()) + })?; let key_pair = self .0 .read() @@ -198,7 +202,9 @@ impl SyncCryptoStore for LocalKeystore { key_pair.map(|k| k.sign(msg).encode()).map(Ok).transpose() }, sr25519::CRYPTO_ID => { - let pub_key = sr25519::Public::from_slice(key.1.as_slice()); + let pub_key = sr25519::Public::from_slice(key.1.as_slice()).map_err(|()| { + TraitError::Other("Corrupted public key - Invalid size".into()) + })?; let key_pair = self .0 .read() @@ -207,7 +213,9 @@ impl SyncCryptoStore for LocalKeystore { key_pair.map(|k| k.sign(msg).encode()).map(Ok).transpose() }, ecdsa::CRYPTO_ID => { - let pub_key = ecdsa::Public::from_slice(key.1.as_slice()); + let pub_key = ecdsa::Public::from_slice(key.1.as_slice()).map_err(|()| { + TraitError::Other("Corrupted public key - Invalid size".into()) + })?; let key_pair = self .0 .read() @@ -223,7 +231,11 @@ impl SyncCryptoStore for LocalKeystore { self.0 .read() .raw_public_keys(key_type) - .map(|v| v.into_iter().map(|k| sr25519::Public::from_slice(k.as_slice())).collect()) + .map(|v| { + v.into_iter() + .filter_map(|k| sr25519::Public::from_slice(k.as_slice()).ok()) + .collect() + }) .unwrap_or_default() } @@ -246,7 +258,11 @@ impl SyncCryptoStore for LocalKeystore { self.0 .read() .raw_public_keys(key_type) - .map(|v| v.into_iter().map(|k| ed25519::Public::from_slice(k.as_slice())).collect()) + .map(|v| { + v.into_iter() + .filter_map(|k| ed25519::Public::from_slice(k.as_slice()).ok()) + .collect() + }) .unwrap_or_default() } @@ -269,7 +285,11 @@ impl SyncCryptoStore for LocalKeystore { self.0 .read() .raw_public_keys(key_type) - .map(|v| v.into_iter().map(|k| ecdsa::Public::from_slice(k.as_slice())).collect()) + .map(|v| { + v.into_iter() + .filter_map(|k| ecdsa::Public::from_slice(k.as_slice()).ok()) + .collect() + }) .unwrap_or_default() } @@ -561,8 +581,9 @@ mod tests { } fn public_keys(&self) -> Result> { - self.raw_public_keys(Public::ID) - .map(|v| v.into_iter().map(|k| Public::from_slice(k.as_slice())).collect()) + self.raw_public_keys(Public::ID).map(|v| { + v.into_iter().filter_map(|k| Public::from_slice(k.as_slice()).ok()).collect() + }) } fn generate(&mut self) -> Result { diff --git a/client/network/src/service.rs b/client/network/src/service.rs index e03bdcfa2f7e..8b153bc4edf5 100644 --- a/client/network/src/service.rs +++ b/client/network/src/service.rs @@ -190,7 +190,7 @@ impl NetworkWorker { let local_peer_id = local_public.clone().to_peer_id(); info!( target: "sub-libp2p", - "🏷 Local node identity is: {}", + "🏷 Local node identity is: {}", local_peer_id.to_base58(), ); diff --git a/client/rpc/src/author/tests.rs b/client/rpc/src/author/tests.rs index 2349e08fee50..5c1ade96f96b 100644 --- a/client/rpc/src/author/tests.rs +++ b/client/rpc/src/author/tests.rs @@ -24,7 +24,7 @@ use futures::executor; use sc_transaction_pool::{BasicPool, FullChainApi}; use sp_core::{ blake2_256, - crypto::{CryptoTypePublicPair, Pair, Public}, + crypto::{ByteArray, CryptoTypePublicPair, Pair}, ed25519, hexdisplay::HexDisplay, sr25519, @@ -40,8 +40,12 @@ use substrate_test_runtime_client::{ }; fn uxt(sender: AccountKeyring, nonce: u64) -> Extrinsic { - let tx = - Transfer { amount: Default::default(), nonce, from: sender.into(), to: Default::default() }; + let tx = Transfer { + amount: Default::default(), + nonce, + from: sender.into(), + to: AccountKeyring::Bob.into(), + }; tx.into_signed_tx() } @@ -133,7 +137,7 @@ fn should_watch_extrinsic() { amount: 5, nonce: 0, from: AccountKeyring::Alice.into(), - to: Default::default(), + to: AccountKeyring::Bob.into(), }; tx.into_signed_tx() }; diff --git a/client/service/src/lib.rs b/client/service/src/lib.rs index 563846c75d89..9cf5cc69bdc3 100644 --- a/client/service/src/lib.rs +++ b/client/service/src/lib.rs @@ -576,7 +576,7 @@ mod tests { amount: 5, nonce: 0, from: AccountKeyring::Alice.into(), - to: Default::default(), + to: AccountKeyring::Bob.into(), } .into_signed_tx(); block_on(pool.submit_one(&BlockId::hash(best.hash()), source, transaction.clone())) diff --git a/client/tracing/proc-macro/src/lib.rs b/client/tracing/proc-macro/src/lib.rs index e9a4f58705b4..005fcf4ba0f5 100644 --- a/client/tracing/proc-macro/src/lib.rs +++ b/client/tracing/proc-macro/src/lib.rs @@ -56,7 +56,7 @@ use syn::{Error, Expr, Ident, ItemFn}; /// 2020-10-16 08:03:14 ✌️ version 2.0.0-47f7d3f2e-x86_64-linux-gnu /// 2020-10-16 08:03:14 ❤️ by Anonymous, 2017-2020 /// 2020-10-16 08:03:14 📋 Chain specification: Local Testnet -/// 2020-10-16 08:03:14 🏷 Node name: nice-glove-1401 +/// 2020-10-16 08:03:14 🏷 Node name: nice-glove-1401 /// 2020-10-16 08:03:14 👤 Role: LIGHT /// 2020-10-16 08:03:14 💾 Database: RocksDb at /tmp/substrate95w2Dk/chains/local_testnet/db /// 2020-10-16 08:03:14 ⛓ Native runtime: node-template-1 (node-template-1.tx1.au1) @@ -64,7 +64,7 @@ use syn::{Error, Expr, Ident, ItemFn}; /// 2020-10-16 08:03:14 [light] Loading GRANDPA authorities from genesis on what appears to be first startup. /// 2020-10-16 08:03:15 [light] ⏱ Loaded block-time = 6000 milliseconds from genesis on first-launch /// 2020-10-16 08:03:15 [light] Using default protocol ID "sup" because none is configured in the chain specs -/// 2020-10-16 08:03:15 [light] 🏷 Local node identity is: 12D3KooWHX4rkWT6a6N55Km7ZnvenGdShSKPkzJ3yj9DU5nqDtWR +/// 2020-10-16 08:03:15 [light] 🏷 Local node identity is: 12D3KooWHX4rkWT6a6N55Km7ZnvenGdShSKPkzJ3yj9DU5nqDtWR /// 2020-10-16 08:03:15 [light] 📦 Highest known block at #0 /// 2020-10-16 08:03:15 [light] 〽️ Prometheus server started at 127.0.0.1:9615 /// 2020-10-16 08:03:15 [light] Listening for new connections on 127.0.0.1:9944. @@ -90,7 +90,7 @@ use syn::{Error, Expr, Ident, ItemFn}; /// 2020-10-16 08:12:57 ✌️ version 2.0.0-efb9b822a-x86_64-linux-gnu /// 2020-10-16 08:12:57 ❤️ by Anonymous, 2017-2020 /// 2020-10-16 08:12:57 📋 Chain specification: Local Testnet -/// 2020-10-16 08:12:57 🏷 Node name: open-harbor-1619 +/// 2020-10-16 08:12:57 🏷 Node name: open-harbor-1619 /// 2020-10-16 08:12:57 👤 Role: LIGHT /// 2020-10-16 08:12:57 💾 Database: RocksDb at /tmp/substrate9T9Mtb/chains/local_testnet/db /// 2020-10-16 08:12:57 ⛓ Native runtime: node-template-1 (node-template-1.tx1.au1) @@ -98,7 +98,7 @@ use syn::{Error, Expr, Ident, ItemFn}; /// 2020-10-16 08:12:58 [open-harbor-1619] Loading GRANDPA authorities from genesis on what appears to be first startup. /// 2020-10-16 08:12:58 [open-harbor-1619] ⏱ Loaded block-time = 6000 milliseconds from genesis on first-launch /// 2020-10-16 08:12:58 [open-harbor-1619] Using default protocol ID "sup" because none is configured in the chain specs -/// 2020-10-16 08:12:58 [open-harbor-1619] 🏷 Local node identity is: 12D3KooWRzmYC8QTK1Pm8Cfvid3skTS4Hn54jc4AUtje8Rqbfgtp +/// 2020-10-16 08:12:58 [open-harbor-1619] 🏷 Local node identity is: 12D3KooWRzmYC8QTK1Pm8Cfvid3skTS4Hn54jc4AUtje8Rqbfgtp /// 2020-10-16 08:12:58 [open-harbor-1619] 📦 Highest known block at #0 /// 2020-10-16 08:12:58 [open-harbor-1619] 〽️ Prometheus server started at 127.0.0.1:9615 /// 2020-10-16 08:12:58 [open-harbor-1619] Listening for new connections on 127.0.0.1:9944. diff --git a/client/transaction-pool/benches/basics.rs b/client/transaction-pool/benches/basics.rs index cf30a0200ad7..cfb40c6cb2ab 100644 --- a/client/transaction-pool/benches/basics.rs +++ b/client/transaction-pool/benches/basics.rs @@ -18,7 +18,7 @@ use criterion::{criterion_group, criterion_main, Criterion}; -use codec::Encode; +use codec::{Decode, Encode}; use futures::{ executor::block_on, future::{ready, Ready}, @@ -126,7 +126,8 @@ impl ChainApi for TestApi { fn uxt(transfer: Transfer) -> Extrinsic { Extrinsic::Transfer { transfer, - signature: Default::default(), + signature: Decode::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()) + .expect("infinite input; no dead input space; qed"), exhaust_resources_when_not_first: false, } } diff --git a/client/transaction-pool/src/graph/pool.rs b/client/transaction-pool/src/graph/pool.rs index af46dbad0ee5..1032282af99d 100644 --- a/client/transaction-pool/src/graph/pool.rs +++ b/client/transaction-pool/src/graph/pool.rs @@ -594,11 +594,8 @@ mod tests { } fn uxt(transfer: Transfer) -> Extrinsic { - Extrinsic::Transfer { - transfer, - signature: Default::default(), - exhaust_resources_when_not_first: false, - } + let signature = TryFrom::try_from(&[0; 64][..]).unwrap(); + Extrinsic::Transfer { transfer, signature, exhaust_resources_when_not_first: false } } fn pool() -> Pool { diff --git a/frame/aura/src/lib.rs b/frame/aura/src/lib.rs index 887bb359ed3d..e98097055920 100644 --- a/frame/aura/src/lib.rs +++ b/frame/aura/src/lib.rs @@ -69,7 +69,6 @@ pub mod pallet { type AuthorityId: Member + Parameter + RuntimeAppPublic - + Default + MaybeSerializeDeserialize + MaxEncodedLen; /// The maximum number of authorities that the pallet can hold. diff --git a/frame/authorship/src/lib.rs b/frame/authorship/src/lib.rs index cd91957475a1..98dd8f1ce6df 100644 --- a/frame/authorship/src/lib.rs +++ b/frame/authorship/src/lib.rs @@ -170,7 +170,9 @@ pub mod pallet { >::put(false); - T::EventHandler::note_author(Self::author()); + if let Some(author) = Self::author() { + T::EventHandler::note_author(author); + } 0 } @@ -300,20 +302,18 @@ impl Pallet { /// /// This is safe to invoke in `on_initialize` implementations, as well /// as afterwards. - pub fn author() -> T::AccountId { + pub fn author() -> Option { // Check the memoized storage value. if let Some(author) = >::get() { - return author + return Some(author) } let digest = >::digest(); let pre_runtime_digests = digest.logs.iter().filter_map(|d| d.as_pre_runtime()); - if let Some(author) = T::FindAuthor::find_author(pre_runtime_digests) { - >::put(&author); - author - } else { - Default::default() - } + T::FindAuthor::find_author(pre_runtime_digests).map(|a| { + >::put(&a); + a + }) } fn verify_and_import_uncles(new_uncles: Vec) -> dispatch::DispatchResult { @@ -329,14 +329,13 @@ impl Pallet { UncleEntryItem::InclusionHeight(_) => None, UncleEntryItem::Uncle(h, _) => Some(h), }); - let author = Self::verify_uncle(&uncle, prev_uncles, &mut acc)?; + let maybe_author = Self::verify_uncle(&uncle, prev_uncles, &mut acc)?; let hash = uncle.hash(); - T::EventHandler::note_uncle( - author.clone().unwrap_or_default(), - now - uncle.number().clone(), - ); - uncles.push(UncleEntryItem::Uncle(hash, author)); + if let Some(author) = maybe_author.clone() { + T::EventHandler::note_uncle(author, now - uncle.number().clone()); + } + uncles.push(UncleEntryItem::Uncle(hash, maybe_author)); } >::put(&uncles); @@ -693,7 +692,7 @@ mod tests { header.digest_mut().pop(); // pop the seal off. System::initialize(&1, &Default::default(), header.digest(), Default::default()); - assert_eq!(Authorship::author(), author); + assert_eq!(Authorship::author(), Some(author)); }); } diff --git a/frame/babe/src/equivocation.rs b/frame/babe/src/equivocation.rs index 2397918d1ef1..9247acbb3b12 100644 --- a/frame/babe/src/equivocation.rs +++ b/frame/babe/src/equivocation.rs @@ -176,7 +176,7 @@ where } fn block_author() -> Option { - Some(>::author()) + >::author() } } diff --git a/frame/babe/src/lib.rs b/frame/babe/src/lib.rs index 569722ca38ce..6ae0796c866f 100644 --- a/frame/babe/src/lib.rs +++ b/frame/babe/src/lib.rs @@ -31,7 +31,7 @@ use frame_support::{ weights::{Pays, Weight}, BoundedVec, WeakBoundedVec, }; -use sp_application_crypto::Public; +use sp_application_crypto::ByteArray; use sp_runtime::{ generic::DigestItem, traits::{IsMember, One, SaturatedConversion, Saturating, Zero}, diff --git a/frame/beefy-mmr/src/lib.rs b/frame/beefy-mmr/src/lib.rs index b846aa4a7dd6..cf65e39dba53 100644 --- a/frame/beefy-mmr/src/lib.rs +++ b/frame/beefy-mmr/src/lib.rs @@ -72,7 +72,7 @@ where pub struct BeefyEcdsaToEthereum; impl Convert> for BeefyEcdsaToEthereum { fn convert(a: beefy_primitives::crypto::AuthorityId) -> Vec { - use sp_core::crypto::Public; + use sp_core::crypto::ByteArray; let compressed_key = a.as_slice(); libsecp256k1::PublicKey::parse_slice( diff --git a/frame/beefy/src/lib.rs b/frame/beefy/src/lib.rs index 6a7118c1f5c9..c18b28901bb6 100644 --- a/frame/beefy/src/lib.rs +++ b/frame/beefy/src/lib.rs @@ -47,7 +47,7 @@ pub mod pallet { #[pallet::config] pub trait Config: frame_system::Config { /// Authority identifier type - type BeefyId: Member + Parameter + RuntimeAppPublic + Default + MaybeSerializeDeserialize; + type BeefyId: Member + Parameter + RuntimeAppPublic + MaybeSerializeDeserialize; } #[pallet::pallet] diff --git a/frame/benchmarking/src/utils.rs b/frame/benchmarking/src/utils.rs index c24ad2f64e18..0bbe8156a9f9 100644 --- a/frame/benchmarking/src/utils.rs +++ b/frame/benchmarking/src/utils.rs @@ -23,6 +23,7 @@ use frame_support::{ traits::StorageInfo, }; use sp_io::hashing::blake2_256; +use sp_runtime::traits::TrailingZeroInput; use sp_std::{prelude::Box, vec::Vec}; use sp_storage::TrackedStorageKey; @@ -321,17 +322,14 @@ pub trait BenchmarkingSetup { } /// Grab an account, seeded by a name and index. -pub fn account( - name: &'static str, - index: u32, - seed: u32, -) -> AccountId { +pub fn account(name: &'static str, index: u32, seed: u32) -> AccountId { let entropy = (name, index, seed).using_encoded(blake2_256); - AccountId::decode(&mut &entropy[..]).unwrap_or_default() + Decode::decode(&mut TrailingZeroInput::new(entropy.as_ref())) + .expect("infinite length input; no invalid inputs for type; qed") } /// This caller account is automatically whitelisted for DB reads/writes by the benchmarking macro. -pub fn whitelisted_caller() -> AccountId { +pub fn whitelisted_caller() -> AccountId { account::("whitelisted_caller", 0, 0) } diff --git a/frame/bounties/src/lib.rs b/frame/bounties/src/lib.rs index 7e8ba6005056..752697ce668f 100644 --- a/frame/bounties/src/lib.rs +++ b/frame/bounties/src/lib.rs @@ -123,7 +123,7 @@ pub struct Bounty { status: BountyStatus, } -impl +impl Bounty { /// Getter for bounty status, to be used for child bounties. diff --git a/frame/collective/src/benchmarking.rs b/frame/collective/src/benchmarking.rs index 5ca57cf72e8f..9dcfa2a9c6c8 100644 --- a/frame/collective/src/benchmarking.rs +++ b/frame/collective/src/benchmarking.rs @@ -43,9 +43,9 @@ benchmarks_instance_pallet! { // Set old members. // We compute the difference of old and new members, so it should influence timing. let mut old_members = vec![]; - let mut last_old_member = T::AccountId::default(); + let mut last_old_member = account::("old member", 0, SEED); for i in 0 .. m { - last_old_member = account("old member", i, SEED); + last_old_member = account::("old member", i, SEED); old_members.push(last_old_member.clone()); } let old_members_count = old_members.len() as u32; @@ -91,9 +91,9 @@ benchmarks_instance_pallet! { // Construct `new_members`. // It should influence timing since it will sort this vector. let mut new_members = vec![]; - let mut last_member = T::AccountId::default(); + let mut last_member = account::("member", 0, SEED); for i in 0 .. n { - last_member = account("member", i, SEED); + last_member = account::("member", i, SEED); new_members.push(last_member.clone()); } @@ -112,7 +112,7 @@ benchmarks_instance_pallet! { // Construct `members`. let mut members = vec![]; for i in 0 .. m - 1 { - let member = account("member", i, SEED); + let member = account::("member", i, SEED); members.push(member); } @@ -142,7 +142,7 @@ benchmarks_instance_pallet! { // Construct `members`. let mut members = vec![]; for i in 0 .. m - 1 { - let member = account("member", i, SEED); + let member = account::("member", i, SEED); members.push(member); } @@ -174,7 +174,7 @@ benchmarks_instance_pallet! { // Construct `members`. let mut members = vec![]; for i in 0 .. m - 1 { - let member = account("member", i, SEED); + let member = account::("member", i, SEED); members.push(member); } let caller: T::AccountId = whitelisted_caller(); @@ -216,13 +216,13 @@ benchmarks_instance_pallet! { // Construct `members`. let mut members = vec![]; - let proposer: T::AccountId = account("proposer", 0, SEED); + let proposer: T::AccountId = account::("proposer", 0, SEED); members.push(proposer.clone()); for i in 1 .. m - 1 { - let member = account("member", i, SEED); + let member = account::("member", i, SEED); members.push(member); } - let voter: T::AccountId = account("voter", 0, SEED); + let voter: T::AccountId = account::("voter", 0, SEED); members.push(voter.clone()); Collective::::set_members(SystemOrigin::Root.into(), members.clone(), None, T::MaxMembers::get())?; @@ -291,13 +291,13 @@ benchmarks_instance_pallet! { // Construct `members`. let mut members = vec![]; - let proposer: T::AccountId = account("proposer", 0, SEED); + let proposer = account::("proposer", 0, SEED); members.push(proposer.clone()); for i in 1 .. m - 1 { - let member = account("member", i, SEED); + let member = account::("member", i, SEED); members.push(member); } - let voter: T::AccountId = account("voter", 0, SEED); + let voter = account::("voter", 0, SEED); members.push(voter.clone()); Collective::::set_members(SystemOrigin::Root.into(), members.clone(), None, T::MaxMembers::get())?; @@ -373,7 +373,7 @@ benchmarks_instance_pallet! { // Construct `members`. let mut members = vec![]; for i in 0 .. m - 1 { - let member = account("member", i, SEED); + let member = account::("member", i, SEED); members.push(member); } let caller: T::AccountId = whitelisted_caller(); @@ -454,7 +454,7 @@ benchmarks_instance_pallet! { // Construct `members`. let mut members = vec![]; for i in 0 .. m - 1 { - let member = account("member", i, SEED); + let member = account::("member", i, SEED); members.push(member); } let caller: T::AccountId = whitelisted_caller(); @@ -528,7 +528,7 @@ benchmarks_instance_pallet! { // Construct `members`. let mut members = vec![]; for i in 0 .. m - 1 { - let member = account("member", i, SEED); + let member = account::("member", i, SEED); members.push(member); } let caller: T::AccountId = whitelisted_caller(); @@ -599,10 +599,10 @@ benchmarks_instance_pallet! { // Construct `members`. let mut members = vec![]; for i in 0 .. m - 1 { - let member = account("member", i, SEED); + let member = account::("member", i, SEED); members.push(member); } - let caller: T::AccountId = account("caller", 0, SEED); + let caller = account::("caller", 0, SEED); members.push(caller.clone()); Collective::::set_members( SystemOrigin::Root.into(), diff --git a/frame/contracts/src/migration.rs b/frame/contracts/src/migration.rs index 93eb2e64a1d8..7751eb1a2c77 100644 --- a/frame/contracts/src/migration.rs +++ b/frame/contracts/src/migration.rs @@ -224,13 +224,16 @@ mod v6 { }) }); + let nobody = T::AccountId::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()) + .expect("Infinite input; no dead input space; qed"); + >::translate(|key, old: OldPrefabWasmModule| { weight = weight.saturating_add(T::DbWeight::get().reads_writes(1, 2)); >::insert( key, OwnerInfo { refcount: old.refcount, - owner: Default::default(), + owner: nobody.clone(), deposit: Default::default(), }, ); diff --git a/frame/democracy/src/benchmarking.rs b/frame/democracy/src/benchmarking.rs index 136c2d2a7c9e..4068b55f6e7b 100644 --- a/frame/democracy/src/benchmarking.rs +++ b/frame/democracy/src/benchmarking.rs @@ -239,9 +239,14 @@ benchmarks! { let origin = T::ExternalOrigin::successful_origin(); let proposal_hash = T::Hashing::hash_of(&0); // Add proposal to blacklist with block number 0 + + let addresses = (0..v) + .into_iter() + .map(|i| account::("blacklist", i, SEED)) + .collect::>(); Blacklist::::insert( proposal_hash, - (T::BlockNumber::zero(), vec![T::AccountId::default(); v as usize]) + (T::BlockNumber::zero(), addresses), ); }: _(origin, proposal_hash) verify { @@ -292,7 +297,7 @@ benchmarks! { let mut vetoers: Vec = Vec::new(); for i in 0 .. v { - vetoers.push(account("vetoer", i, SEED)); + vetoers.push(account::("vetoer", i, SEED)); } vetoers.sort(); Blacklist::::insert(proposal_hash, (T::BlockNumber::zero(), vetoers)); diff --git a/frame/election-provider-multi-phase/src/benchmarking.rs b/frame/election-provider-multi-phase/src/benchmarking.rs index d9db6c309099..1e0d3b1e9325 100644 --- a/frame/election-provider-multi-phase/src/benchmarking.rs +++ b/frame/election-provider-multi-phase/src/benchmarking.rs @@ -209,7 +209,11 @@ frame_benchmarking::benchmarks! { let receiver = account("receiver", 0, SEED); let initial_balance = T::Currency::minimum_balance() * 10u32.into(); T::Currency::make_free_balance_be(&receiver, initial_balance); - let ready: ReadySolution = Default::default(); + let ready = ReadySolution { + supports: vec![], + score: Default::default(), + compute: Default::default() + }; let deposit: BalanceOf = 10u32.into(); let reward: BalanceOf = 20u32.into(); @@ -314,7 +318,12 @@ frame_benchmarking::benchmarks! { score: [(10_000_000 + i).into(), 0, 0], ..Default::default() }; - let signed_submission = SignedSubmission { raw_solution, ..Default::default() }; + let signed_submission = SignedSubmission { + raw_solution, + who: account("submitters", i, SEED), + deposit: Default::default(), + reward: Default::default(), + }; signed_submissions.insert(signed_submission); } signed_submissions.put(); diff --git a/frame/election-provider-multi-phase/src/lib.rs b/frame/election-provider-multi-phase/src/lib.rs index 70bbed95fe97..70668dbe9f67 100644 --- a/frame/election-provider-multi-phase/src/lib.rs +++ b/frame/election-provider-multi-phase/src/lib.rs @@ -1189,7 +1189,7 @@ pub mod pallet { /// affect; we shouldn't need a cryptographically secure hasher. #[pallet::storage] pub(crate) type SignedSubmissionsMap = - StorageMap<_, Twox64Concat, u32, SignedSubmissionOf, ValueQuery>; + StorageMap<_, Twox64Concat, u32, SignedSubmissionOf, OptionQuery>; // `SignedSubmissions` items end here. diff --git a/frame/election-provider-multi-phase/src/signed.rs b/frame/election-provider-multi-phase/src/signed.rs index b762ad706486..08cae62ef7d3 100644 --- a/frame/election-provider-multi-phase/src/signed.rs +++ b/frame/election-provider-multi-phase/src/signed.rs @@ -42,7 +42,7 @@ use sp_std::{ /// A raw, unchecked signed submission. /// /// This is just a wrapper around [`RawSolution`] and some additional info. -#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, Default, scale_info::TypeInfo)] +#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, scale_info::TypeInfo)] pub struct SignedSubmission { /// Who submitted this solution. pub who: AccountId, @@ -167,17 +167,17 @@ impl SignedSubmissions { } /// Get the submission at a particular index. - fn get_submission(&self, idx: u32) -> Option> { - if self.deletion_overlay.contains(&idx) { + fn get_submission(&self, index: u32) -> Option> { + if self.deletion_overlay.contains(&index) { // Note: can't actually remove the item from the insertion overlay (if present) // because we don't want to use `&mut self` here. There may be some kind of // `RefCell` optimization possible here in the future. None } else { self.insertion_overlay - .get(&idx) + .get(&index) .cloned() - .or_else(|| SignedSubmissionsMap::::try_get(idx).ok()) + .or_else(|| SignedSubmissionsMap::::get(index)) } } @@ -200,18 +200,18 @@ impl SignedSubmissions { remove_score: ElectionScore, insert: Option<(ElectionScore, u32)>, ) -> Option> { - let remove_idx = self.indices.remove(&remove_score)?; + let remove_index = self.indices.remove(&remove_score)?; if let Some((insert_score, insert_idx)) = insert { self.indices .try_insert(insert_score, insert_idx) .expect("just removed an item, we must be under capacity; qed"); } - self.insertion_overlay.remove(&remove_idx).or_else(|| { - (!self.deletion_overlay.contains(&remove_idx)) + self.insertion_overlay.remove(&remove_index).or_else(|| { + (!self.deletion_overlay.contains(&remove_index)) .then(|| { - self.deletion_overlay.insert(remove_idx); - SignedSubmissionsMap::::try_get(remove_idx).ok() + self.deletion_overlay.insert(remove_index); + SignedSubmissionsMap::::get(remove_index) }) .flatten() }) diff --git a/frame/elections-phragmen/src/lib.rs b/frame/elections-phragmen/src/lib.rs index 8daa4e7fe13c..c0b6fdfce6cd 100644 --- a/frame/elections-phragmen/src/lib.rs +++ b/frame/elections-phragmen/src/lib.rs @@ -147,7 +147,7 @@ pub enum Renouncing { } /// An active voter. -#[derive(Encode, Decode, Clone, Default, RuntimeDebug, PartialEq, TypeInfo)] +#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, TypeInfo)] pub struct Voter { /// The members being backed. pub votes: Vec, @@ -159,6 +159,12 @@ pub struct Voter { pub deposit: Balance, } +impl Default for Voter { + fn default() -> Self { + Self { votes: vec![], stake: Default::default(), deposit: Default::default() } + } +} + /// A holder of a seat as either a member or a runner-up. #[derive(Encode, Decode, Clone, Default, RuntimeDebug, PartialEq, TypeInfo)] pub struct SeatHolder { @@ -1087,7 +1093,14 @@ impl SortedMembers for Pallet { fn add(who: &T::AccountId) { Members::::mutate(|members| match members.binary_search_by(|m| m.who.cmp(who)) { Ok(_) => (), - Err(pos) => members.insert(pos, SeatHolder { who: who.clone(), ..Default::default() }), + Err(pos) => { + let s = SeatHolder { + who: who.clone(), + stake: Default::default(), + deposit: Default::default(), + }; + members.insert(pos, s) + }, }) } } diff --git a/frame/elections/Cargo.toml b/frame/elections/Cargo.toml deleted file mode 100644 index d1404f762612..000000000000 --- a/frame/elections/Cargo.toml +++ /dev/null @@ -1,42 +0,0 @@ -[package] -name = "pallet-elections" -version = "4.0.0-dev" -authors = ["Parity Technologies "] -edition = "2021" -license = "Apache-2.0" -homepage = "https://substrate.io" -repository = "https://github.com/paritytech/substrate/" -description = "FRAME pallet for elections" -readme = "README.md" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ - "derive", -] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } -sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } -frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } - -[dev-dependencies] -pallet-balances = { version = "4.0.0-dev", path = "../balances" } - -[features] -default = ["std"] -std = [ - "codec/std", - "scale-info/std", - "sp-core/std", - "sp-std/std", - "sp-io/std", - "frame-support/std", - "sp-runtime/std", - "frame-system/std", -] -try-runtime = ["frame-support/try-runtime"] diff --git a/frame/elections/README.md b/frame/elections/README.md deleted file mode 100644 index 1f6fd42331c1..000000000000 --- a/frame/elections/README.md +++ /dev/null @@ -1,7 +0,0 @@ -Election module for stake-weighted membership selection of a collective. - -The composition of a set of account IDs works according to one or more approval votes -weighted by stake. There is a partial carry-over facility to give greater weight to those -whose voting is serially unsuccessful. - -License: Apache-2.0 \ No newline at end of file diff --git a/frame/elections/src/lib.rs b/frame/elections/src/lib.rs deleted file mode 100644 index 7ca11f4ed20e..000000000000 --- a/frame/elections/src/lib.rs +++ /dev/null @@ -1,1324 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2017-2021 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. - -//! # WARNING: NOT ACTIVELY MAINTAINED -//! -//! This pallet is currently not maintained and should not be used in production until further -//! notice. -//! -//! --- -//! -//! Election pallet for stake-weighted membership selection of a collective. -//! -//! The composition of a set of account IDs works according to one or more approval votes -//! weighted by stake. There is a partial carry-over facility to give greater weight to those -//! whose voting is serially unsuccessful. - -#![cfg_attr(not(feature = "std"), no_std)] -#![recursion_limit = "128"] - -use codec::{Decode, Encode}; -use frame_support::{ - ensure, - pallet_prelude::*, - traits::{ - BalanceStatus, ChangeMembers, Currency, ExistenceRequirement, LockIdentifier, - LockableCurrency, OnUnbalanced, ReservableCurrency, WithdrawReasons, - }, - weights::{DispatchClass, Weight}, -}; -use frame_system::pallet_prelude::*; -pub use pallet::*; -use sp_runtime::{ - print, - traits::{One, Saturating, StaticLookup, Zero}, - RuntimeDebug, -}; -use sp_std::prelude::*; - -mod mock; -mod tests; - -// no polynomial attacks: -// -// all unbonded public operations should be constant time. -// all other public operations must be linear time in terms of prior public operations and: -// - those "valid" ones that cost nothing be limited to a constant number per single protected -// operation -// - the rest costing the same order as the computational complexity -// all protected operations must complete in at most O(public operations) -// -// we assume "beneficial" transactions will have the same access as attack transactions. -// -// any storage requirements should be bonded by the same order as the volume. - -// public operations: -// - express approvals (you pay in a "voter" bond the first time you do this; O(1); one extra DB -// entry, one DB change) -// - remove active voter (you get your "voter" bond back; O(1); one fewer DB entry, one DB change) -// - remove inactive voter (either you or the target is removed; if the target, you get their -// "voter" bond back; O(1); one fewer DB entry, one DB change) -// - submit candidacy (you pay a "candidate" bond; O(1); one extra DB entry, two DB changes) -// - present winner/runner-up (you may pay a "presentation" bond of O(voters) if the presentation is -// invalid; O(voters) compute; ) protected operations: -// - remove candidacy (remove all votes for a candidate) (one fewer DB entry, two DB changes) - -// to avoid a potentially problematic case of not-enough approvals prior to voting causing a -// back-to-back votes that have no way of ending, then there's a forced grace period between votes. -// to keep the system as stateless as possible (making it a bit easier to reason about), we just -// restrict when votes can begin to blocks that lie on boundaries (`voting_period`). - -// for an approval vote of C members: - -// top K runners-up are maintained between votes. all others are discarded. -// - candidate removed & bond returned when elected. -// - candidate removed & bond burned when discarded. - -// at the point that the vote ends (), all voters' balances are snapshotted. - -// for B blocks following, there's a counting period whereby each of the candidates that believe -// they fall in the top K+C voted can present themselves. they get the total stake -// recorded (based on the snapshot); an ordered list is maintained (the leaderboard). No one may -// present themselves that, if elected, would result in being included twice in the collective -// (important since existing members will have their approval votes as it may be that they -// don't get removed), nor if existing presenters would mean they're not in the top K+C. - -// following B blocks, the top C candidates are elected and have their bond returned. the top C -// candidates and all other candidates beyond the top C+K are cleared. - -// vote-clearing happens lazily; for an approval to count, the most recent vote at the time of the -// voter's most recent vote must be no later than the most recent vote at the time that the -// candidate in the approval position was registered there. as candidates are removed from the -// register and others join in their place, this prevents an approval meant for an earlier candidate -// being used to elect a new candidate. - -// the candidate list increases as needed, but the contents (though not really the capacity) reduce -// after each vote as all but K entries are cleared. newly registering candidates must use cleared -// entries before they increase the capacity. - -/// The activity status of a voter. -#[derive( - PartialEq, Eq, Copy, Clone, Encode, Decode, Default, RuntimeDebug, scale_info::TypeInfo, -)] -pub struct VoterInfo { - /// Last VoteIndex in which this voter assigned (or initialized) approvals. - last_active: VoteIndex, - /// Last VoteIndex in which one of this voter's approvals won. - /// Note that `last_win = N` indicates a last win at index `N-1`, hence `last_win = 0` means no - /// win ever. - last_win: VoteIndex, - /// The amount of stored weight as a result of not winning but changing approvals. - pot: Balance, - /// Current staked amount. A lock equal to this value always exists. - stake: Balance, -} - -/// Used to demonstrate the status of a particular index in the global voter list. -#[derive(PartialEq, Eq, RuntimeDebug)] -pub enum CellStatus { - /// Any out of bound index. Means a push a must happen to the chunk pointed by - /// `NextVoterSet`. Voting fee is applied in case a new chunk is created. - Head, - /// Already occupied by another voter. Voting fee is applied. - Occupied, - /// Empty hole which should be filled. No fee will be applied. - Hole, -} - -/// Number of voters grouped in one chunk. -pub const VOTER_SET_SIZE: usize = 64; -/// NUmber of approvals grouped in one chunk. -pub const APPROVAL_SET_SIZE: usize = 8; - -type BalanceOf = - <::Currency as Currency<::AccountId>>::Balance; -type NegativeImbalanceOf = <::Currency as Currency< - ::AccountId, ->>::NegativeImbalance; - -/// Index used to access chunks. -type SetIndex = u32; -/// Index used to count voting rounds. -pub type VoteIndex = u32; -/// Underlying data type of the approvals. -type ApprovalFlag = u32; -/// Number of approval flags that can fit into [`ApprovalFlag`] type. -const APPROVAL_FLAG_LEN: usize = 32; - -#[frame_support::pallet] -pub mod pallet { - use super::*; - - #[pallet::pallet] - #[pallet::generate_store(pub(super) trait Store)] - pub struct Pallet(_); - - #[pallet::config] - pub trait Config: frame_system::Config { - type Event: From> + IsType<::Event>; - - /// Identifier for the elections pallet's lock - #[pallet::constant] - type PalletId: Get; - - /// The currency that people are electing with. - type Currency: LockableCurrency - + ReservableCurrency; - - /// Handler for the unbalanced reduction when slashing a validator. - type BadPresentation: OnUnbalanced>; - - /// Handler for the unbalanced reduction when slashing an invalid reaping attempt. - type BadReaper: OnUnbalanced>; - - /// Handler for the unbalanced reduction when submitting a bad `voter_index`. - type BadVoterIndex: OnUnbalanced>; - - /// Handler for the unbalanced reduction when a candidate has lost (and is not a runner up) - type LoserCandidate: OnUnbalanced>; - - /// What to do when the members change. - type ChangeMembers: ChangeMembers; - - /// How much should be locked up in order to submit one's candidacy. A reasonable - /// default value is 9. - #[pallet::constant] - type CandidacyBond: Get>; - - /// How much should be locked up in order to be able to submit votes. - #[pallet::constant] - type VotingBond: Get>; - - /// The amount of fee paid upon each vote submission, unless if they submit a - /// _hole_ index and replace it. - #[pallet::constant] - type VotingFee: Get>; - - /// Minimum about that can be used as the locked value for voting. - #[pallet::constant] - type MinimumVotingLock: Get>; - - /// The punishment, per voter, if you provide an invalid presentation. A - /// reasonable default value is 1. - #[pallet::constant] - type PresentSlashPerVoter: Get>; - - /// How many runners-up should have their approvals persist until the next - /// vote. A reasonable default value is 2. - #[pallet::constant] - type CarryCount: Get; - - /// How many vote indices need to go by after a target voter's last vote before - /// they can be reaped if their approvals are moot. A reasonable default value - /// is 1. - #[pallet::constant] - type InactiveGracePeriod: Get; - - /// How often (in blocks) to check for new votes. A reasonable default value - /// is 1000. - #[pallet::constant] - type VotingPeriod: Get; - - /// Decay factor of weight when being accumulated. It should typically be set to - /// __at least__ `membership_size -1` to keep the collective secure. - /// When set to `N`, it indicates `(1/N)^t` of staked is decayed at weight - /// increment step `t`. 0 will result in no weight being added at all (normal - /// approval voting). A reasonable default value is 24. - #[pallet::constant] - type DecayRatio: Get; - } - - #[pallet::extra_constants] - impl Pallet { - // TODO: rename to snake case after https://github.com/paritytech/substrate/issues/8826 fixed. - /// The chunk size of the voter vector. - #[allow(non_snake_case)] - fn VOTER_SET_SIZE() -> u32 { - VOTER_SET_SIZE as u32 - } - - // TODO: rename to snake case after https://github.com/paritytech/substrate/issues/8826 fixed. - /// The chunk size of the approval vector. - #[allow(non_snake_case)] - fn APPROVAL_SET_SIZE() -> u32 { - APPROVAL_SET_SIZE as u32 - } - } - - // ---- permanent state (always relevant, changes only at the finalization of voting) - - /// How long to give each top candidate to present themselves after the vote ends. - #[pallet::storage] - #[pallet::getter(fn presentation_duration)] - pub type PresentationDuration = StorageValue<_, T::BlockNumber, ValueQuery>; - - /// How long each position is active for. - #[pallet::storage] - #[pallet::getter(fn term_duration)] - pub type TermDuration = StorageValue<_, T::BlockNumber, ValueQuery>; - - /// Number of accounts that should constitute the collective. - #[pallet::storage] - #[pallet::getter(fn desired_seats)] - pub type DesiredSeats = StorageValue<_, u32, ValueQuery>; - - // ---- permanent state (always relevant, changes only at the finalization of voting) - - /// The current membership. When there's a vote going on, this should still be used for - /// executive matters. The block number (second element in the tuple) is the block that - /// their position is active until (calculated by the sum of the block number when the - /// member was elected and their term duration). - #[pallet::storage] - #[pallet::getter(fn members)] - pub type Members = StorageValue<_, Vec<(T::AccountId, T::BlockNumber)>, ValueQuery>; - - /// The total number of vote rounds that have happened or are in progress. - #[pallet::storage] - #[pallet::getter(fn vote_index)] - pub type VoteCount = StorageValue<_, VoteIndex, ValueQuery>; - - // ---- persistent state (always relevant, changes constantly) - - // A list of votes for each voter. The votes are stored as numeric values and parsed in a - // bit-wise manner. In order to get a human-readable representation (`Vec`), use - // [`all_approvals_of`]. Furthermore, each vector of scalars is chunked with the cap of - // `APPROVAL_SET_SIZE`. - /// TWOX-NOTE: SAFE as `AccountId` is a crypto hash and `SetIndex` is not - /// attacker-controlled. - #[pallet::storage] - #[pallet::getter(fn approvals_of)] - pub type ApprovalsOf = - StorageMap<_, Twox64Concat, (T::AccountId, SetIndex), Vec, ValueQuery>; - - /// The vote index and list slot that the candidate `who` was registered or `None` if they - /// are not currently registered. - /// - /// TWOX-NOTE: SAFE as `AccountId` is a crypto hash. - #[pallet::storage] - #[pallet::getter(fn candidate_reg_info)] - pub type RegisterInfoOf = - StorageMap<_, Twox64Concat, T::AccountId, (VoteIndex, u32)>; - - /// Basic information about a voter. - /// - /// TWOX-NOTE: SAFE as `AccountId` is a crypto hash. - #[pallet::storage] - #[pallet::getter(fn voter_info)] - pub type VoterInfoOf = - StorageMap<_, Twox64Concat, T::AccountId, VoterInfo>>; - - /// The present voter list (chunked and capped at [`VOTER_SET_SIZE`]). - /// - /// TWOX-NOTE: OKAY ― `SetIndex` is not user-controlled data. - #[pallet::storage] - #[pallet::getter(fn voters)] - pub type Voters = - StorageMap<_, Twox64Concat, SetIndex, Vec>, ValueQuery>; - - /// the next free set to store a voter in. This will keep growing. - #[pallet::storage] - #[pallet::getter(fn next_nonfull_voter_set)] - pub type NextVoterSet = StorageValue<_, SetIndex, ValueQuery>; - - /// Current number of Voters. - #[pallet::storage] - #[pallet::getter(fn voter_count)] - pub type VoterCount = StorageValue<_, SetIndex, ValueQuery>; - - /// The present candidate list. - #[pallet::storage] - #[pallet::getter(fn candidates)] - pub type Candidates = StorageValue<_, Vec, ValueQuery>; // has holes - - /// Current number of active candidates - #[pallet::storage] - #[pallet::getter(fn candidate_count)] - pub type CandidateCount = StorageValue<_, u32, ValueQuery>; - - // ---- temporary state (only relevant during finalization/presentation) - - /// The accounts holding the seats that will become free on the next tally. - #[pallet::storage] - #[pallet::getter(fn next_finalize)] - pub type NextFinalize = StorageValue<_, (T::BlockNumber, u32, Vec)>; - - /// Get the leaderboard if we're in the presentation phase. The first element is the weight - /// of each entry; It may be the direct summed approval stakes, or a weighted version of it. - /// Sorted from low to high. - #[pallet::storage] - #[pallet::getter(fn leaderboard)] - pub type Leaderboard = StorageValue<_, Vec<(BalanceOf, T::AccountId)>>; - - #[pallet::genesis_config] - pub struct GenesisConfig { - pub presentation_duration: T::BlockNumber, - pub term_duration: T::BlockNumber, - pub desired_seats: u32, - pub members: Vec<(T::AccountId, T::BlockNumber)>, - } - - #[cfg(feature = "std")] - impl Default for GenesisConfig { - fn default() -> Self { - GenesisConfig { - presentation_duration: Default::default(), - term_duration: Default::default(), - desired_seats: Default::default(), - members: Default::default(), - } - } - } - - #[pallet::genesis_build] - impl GenesisBuild for GenesisConfig { - fn build(&self) { - PresentationDuration::::put(self.presentation_duration); - TermDuration::::put(self.term_duration); - DesiredSeats::::put(self.desired_seats); - Members::::put(&self.members); - } - } - - #[pallet::error] - pub enum Error { - /// Reporter must be a voter. - NotVoter, - /// Target for inactivity cleanup must be active. - InactiveTarget, - /// Cannot reap during presentation period. - CannotReapPresenting, - /// Cannot reap during grace period. - ReapGrace, - /// Invalid reporter index. - InvalidReporterIndex, - /// Invalid target index. - InvalidTargetIndex, - /// Invalid vote index. - InvalidVoteIndex, - /// Cannot retract when presenting. - CannotRetractPresenting, - /// Cannot retract non-voter. - RetractNonVoter, - /// Invalid retraction index. - InvalidRetractionIndex, - /// Duplicate candidate submission. - DuplicatedCandidate, - /// Invalid candidate slot. - InvalidCandidateSlot, - /// Candidate has not enough funds. - InsufficientCandidateFunds, - /// Presenter must have sufficient slashable funds. - InsufficientPresenterFunds, - /// Stake deposited to present winner and be added to leaderboard should be non-zero. - ZeroDeposit, - /// Candidate not worthy of leaderboard. - UnworthyCandidate, - /// Leaderboard must exist while present phase active. - LeaderboardMustExist, - /// Cannot present outside of presentation period. - NotPresentationPeriod, - /// Presented candidate must be current. - InvalidCandidate, - /// Duplicated presentation. - DuplicatedPresentation, - /// Incorrect total. - IncorrectTotal, - /// Invalid voter index. - InvalidVoterIndex, - /// New voter must have sufficient funds to pay the bond. - InsufficientVoterFunds, - /// Locked value must be more than limit. - InsufficientLockedValue, - /// Amount of candidate votes cannot exceed amount of candidates. - TooManyVotes, - /// Amount of candidates to receive approval votes should be non-zero. - ZeroCandidates, - /// No approval changes during presentation period. - ApprovalPresentation, - } - - #[pallet::hooks] - impl Hooks> for Pallet { - fn on_initialize(n: T::BlockNumber) -> Weight { - if let Err(e) = Self::end_block(n) { - print("Guru meditation"); - print(e); - } - 0 - } - } - - #[pallet::event] - #[pallet::generate_deposit(pub(super) fn deposit_event)] - pub enum Event { - /// Reaped - VoterReaped { voter: T::AccountId, reaper: T::AccountId }, - /// Slashed - BadReaperSlashed { reaper: T::AccountId }, - /// A tally (for approval votes of seats) has started. - TallyStarted { seats: u32 }, - /// A tally (for approval votes of seat(s)) has ended (with one or more new members). - TallyFinalized { incoming: Vec, outgoing: Vec }, - } - - #[pallet::call] - impl Pallet { - /// Set candidate approvals. Approval slots stay valid as long as candidates in those slots - /// are registered. - /// - /// Locks `value` from the balance of `origin` indefinitely. Only - /// [`retract_voter`](Self::retract_voter) or - /// [`reap_inactive_voter`](Self::reap_inactive_voter) can unlock the balance. - /// - /// `hint` argument is interpreted differently based on: - /// - if `origin` is setting approvals for the first time: The index will be checked for - /// being a valid _hole_ in the voter list. - /// - if the hint is correctly pointing to a hole, no fee is deducted from `origin`. - /// - Otherwise, the call will succeed but the index is ignored and simply a push to the - /// last chunk with free space happens. If the new push causes a new chunk to be - /// created, a fee indicated by [`Config::VotingFee`] is deducted. - /// - if `origin` is already a voter: the index __must__ be valid and point to the correct - /// position of the `origin` in the current voters list. - /// - /// Note that any trailing `false` votes in `votes` is ignored; In approval voting, not - /// voting for a candidate and voting false, are equal. - /// - /// # - /// - O(1). - /// - Two extra DB entries, one DB change. - /// - Argument `votes` is limited in length to number of candidates. - /// # - #[pallet::weight(2_500_000_000)] - pub fn set_approvals( - origin: OriginFor, - votes: Vec, - #[pallet::compact] index: VoteIndex, - hint: SetIndex, - #[pallet::compact] value: BalanceOf, - ) -> DispatchResult { - let who = ensure_signed(origin)?; - Self::do_set_approvals(who, votes, index, hint, value) - } - - /// Remove a voter. For it not to be a bond-consuming no-op, all approved candidate indices - /// must now be either unregistered or registered to a candidate that registered the slot - /// after the voter gave their last approval set. - /// - /// Both indices must be provided according to the following principle: - /// Voter index does not take holes into account. This means that any account submitting an - /// index at any point in time should submit: - /// `VOTER_SET_SIZE * set_index + local_index`, meaning that you are ignoring all holes in - /// the first `set_index` sets. - /// - /// May be called by anyone. Returns the voter deposit to `signed`. - /// - /// # - /// - O(1). - /// - Two fewer DB entries, one DB change. - /// # - #[pallet::weight(2_500_000_000)] - pub fn reap_inactive_voter( - origin: OriginFor, - #[pallet::compact] reporter_index: u32, - who: ::Source, - #[pallet::compact] who_index: u32, - #[pallet::compact] assumed_vote_index: VoteIndex, - ) -> DispatchResult { - let reporter = ensure_signed(origin)?; - let who = T::Lookup::lookup(who)?; - - ensure!(!Self::presentation_active(), Error::::CannotReapPresenting); - ensure!(Self::voter_info(&reporter).is_some(), Error::::NotVoter); - - let info = Self::voter_info(&who).ok_or(Error::::InactiveTarget)?; - let last_active = info.last_active; - - ensure!(assumed_vote_index == Self::vote_index(), Error::::InvalidVoteIndex); - ensure!( - assumed_vote_index > last_active + T::InactiveGracePeriod::get(), - Error::::ReapGrace, - ); - - let reporter_index = reporter_index as usize; - let who_index = who_index as usize; - let assumed_reporter = - Self::voter_at(reporter_index).ok_or(Error::::InvalidReporterIndex)?; - let assumed_who = Self::voter_at(who_index).ok_or(Error::::InvalidTargetIndex)?; - - ensure!(assumed_reporter == reporter, Error::::InvalidReporterIndex); - ensure!(assumed_who == who, Error::::InvalidTargetIndex); - - // will definitely kill one of reporter or who now. - - let valid = !Self::all_approvals_of(&who).iter().zip(Self::candidates().iter()).any( - |(&appr, addr)| { - appr && - *addr != T::AccountId::default() && - // defensive only: all items in candidates list are registered - Self::candidate_reg_info(addr).map_or(false, |x| x.0 <= last_active) - }, - ); - - Self::remove_voter( - if valid { &who } else { &reporter }, - if valid { who_index } else { reporter_index }, - ); - - T::Currency::remove_lock(T::PalletId::get(), if valid { &who } else { &reporter }); - - if valid { - // This only fails if `reporter` doesn't exist, which it clearly must do since its - // the origin. Still, it's no more harmful to propagate any error at this point. - T::Currency::repatriate_reserved( - &who, - &reporter, - T::VotingBond::get(), - BalanceStatus::Free, - )?; - Self::deposit_event(Event::::VoterReaped { voter: who, reaper: reporter }); - } else { - let imbalance = T::Currency::slash_reserved(&reporter, T::VotingBond::get()).0; - T::BadReaper::on_unbalanced(imbalance); - Self::deposit_event(Event::::BadReaperSlashed { reaper: reporter }); - } - Ok(()) - } - - /// Remove a voter. All votes are cancelled and the voter deposit is returned. - /// - /// The index must be provided according to the following principle: - /// Voter index does not take holes into account. This means that any account submitting an - /// index at any point in time should submit: - /// `VOTER_SET_SIZE * set_index + local_index`, meaning that you are ignoring all holes in - /// the first `set_index` sets. - /// - /// Also removes the lock on the balance of the voter. - /// - /// # - /// - O(1). - /// - Two fewer DB entries, one DB change. - /// # - #[pallet::weight(1_250_000_000)] - pub fn retract_voter( - origin: OriginFor, - #[pallet::compact] index: u32, - ) -> DispatchResult { - let who = ensure_signed(origin)?; - - ensure!(!Self::presentation_active(), Error::::CannotRetractPresenting); - ensure!(>::contains_key(&who), Error::::RetractNonVoter); - let index = index as usize; - let voter = Self::voter_at(index).ok_or(Error::::InvalidRetractionIndex)?; - ensure!(voter == who, Error::::InvalidRetractionIndex); - - Self::remove_voter(&who, index); - T::Currency::unreserve(&who, T::VotingBond::get()); - T::Currency::remove_lock(T::PalletId::get(), &who); - Ok(()) - } - - /// Submit oneself for candidacy. - /// - /// Account must have enough transferrable funds in it to pay the bond. - /// - /// NOTE: if `origin` has already assigned approvals via - /// [`set_approvals`](Self::set_approvals), it will NOT have any usable funds to pass - /// candidacy bond and must first retract. - /// Note that setting approvals will lock the entire balance of the voter until - /// retraction or being reported. - /// - /// # - /// - Independent of input. - /// - Three DB changes. - /// # - #[pallet::weight(2_500_000_000)] - pub fn submit_candidacy( - origin: OriginFor, - #[pallet::compact] slot: u32, - ) -> DispatchResult { - let who = ensure_signed(origin)?; - - ensure!(!Self::is_a_candidate(&who), Error::::DuplicatedCandidate); - let slot = slot as usize; - let count = Self::candidate_count() as usize; - let candidates = Self::candidates(); - ensure!( - (slot == count && count == candidates.len()) || - (slot < candidates.len() && candidates[slot] == T::AccountId::default()), - Error::::InvalidCandidateSlot, - ); - // NOTE: This must be last as it has side-effects. - T::Currency::reserve(&who, T::CandidacyBond::get()) - .map_err(|_| Error::::InsufficientCandidateFunds)?; - - >::insert(&who, (Self::vote_index(), slot as u32)); - let mut candidates = candidates; - if slot == candidates.len() { - candidates.push(who); - } else { - candidates[slot] = who; - } - >::put(candidates); - CandidateCount::::put(count as u32 + 1); - Ok(()) - } - - /// Claim that `candidate` is one of the top `carry_count + desired_seats` candidates. Only - /// works iff the presentation period is active. `candidate` should have at least collected - /// some non-zero `total` votes and `origin` must have enough funds to pay for a potential - /// slash. - /// - /// # - /// - O(voters) compute. - /// - One DB change. - /// # - #[pallet::weight(10_000_000_000)] - pub fn present_winner( - origin: OriginFor, - candidate: ::Source, - #[pallet::compact] total: BalanceOf, - #[pallet::compact] index: VoteIndex, - ) -> DispatchResult { - let who = ensure_signed(origin)?; - ensure!(!total.is_zero(), Error::::ZeroDeposit); - - let candidate = T::Lookup::lookup(candidate)?; - ensure!(index == Self::vote_index(), Error::::InvalidVoteIndex); - let (_, _, expiring) = - Self::next_finalize().ok_or(Error::::NotPresentationPeriod)?; - let bad_presentation_punishment = - T::PresentSlashPerVoter::get() * BalanceOf::::from(Self::voter_count() as u32); - ensure!( - T::Currency::can_slash(&who, bad_presentation_punishment), - Error::::InsufficientPresenterFunds, - ); - - let mut leaderboard = Self::leaderboard().ok_or(Error::::LeaderboardMustExist)?; - ensure!(total > leaderboard[0].0, Error::::UnworthyCandidate); - - if let Some(p) = Self::members().iter().position(|&(ref c, _)| c == &candidate) { - ensure!(p < expiring.len(), Error::::DuplicatedCandidate); - } - - let voters = Self::all_voters(); - let (registered_since, candidate_index): (VoteIndex, u32) = - Self::candidate_reg_info(&candidate).ok_or(Error::::InvalidCandidate)?; - let actual_total = voters - .iter() - .filter_map(|maybe_voter| maybe_voter.as_ref()) - .filter_map(|voter| match Self::voter_info(voter) { - Some(b) if b.last_active >= registered_since => { - let last_win = b.last_win; - let now = Self::vote_index(); - let stake = b.stake; - let offset = Self::get_offset(stake, now - last_win); - let weight = stake + offset + b.pot; - if Self::approvals_of_at(voter, candidate_index as usize) { - Some(weight) - } else { - None - } - }, - _ => None, - }) - .fold(Zero::zero(), |acc, n| acc + n); - let dupe = leaderboard.iter().find(|&&(_, ref c)| c == &candidate).is_some(); - if total == actual_total && !dupe { - // insert into leaderboard - leaderboard[0] = (total, candidate); - leaderboard.sort_by_key(|&(t, _)| t); - >::put(leaderboard); - Ok(()) - } else { - // we can rest assured it will be Ok since we checked `can_slash` earlier; still - // better safe than sorry. - let imbalance = T::Currency::slash(&who, bad_presentation_punishment).0; - T::BadPresentation::on_unbalanced(imbalance); - Err(if dupe { - Error::::DuplicatedPresentation - } else { - Error::::IncorrectTotal - })? - } - } - - /// Set the desired member count; if lower than the current count, then seats will not be up - /// election when they expire. If more, then a new vote will be started if one is not - /// already in progress. - #[pallet::weight((0, DispatchClass::Operational))] - pub fn set_desired_seats( - origin: OriginFor, - #[pallet::compact] count: u32, - ) -> DispatchResult { - ensure_root(origin)?; - DesiredSeats::::put(count); - Ok(()) - } - - /// Remove a particular member from the set. This is effective immediately. - /// - /// Note: A tally should happen instantly (if not already in a presentation - /// period) to fill the seat if removal means that the desired members are not met. - #[pallet::weight((0, DispatchClass::Operational))] - pub fn remove_member( - origin: OriginFor, - who: ::Source, - ) -> DispatchResult { - ensure_root(origin)?; - let who = T::Lookup::lookup(who)?; - let new_set: Vec<(T::AccountId, T::BlockNumber)> = - Self::members().into_iter().filter(|i| i.0 != who).collect(); - >::put(&new_set); - let new_set = new_set.into_iter().map(|x| x.0).collect::>(); - T::ChangeMembers::change_members(&[], &[who], new_set); - Ok(()) - } - - /// Set the presentation duration. If there is currently a vote being presented for, will - /// invoke `finalize_vote`. - #[pallet::weight((0, DispatchClass::Operational))] - pub fn set_presentation_duration( - origin: OriginFor, - #[pallet::compact] count: T::BlockNumber, - ) -> DispatchResult { - ensure_root(origin)?; - >::put(count); - Ok(()) - } - - /// Set the presentation duration. If there is current a vote being presented for, will - /// invoke `finalize_vote`. - #[pallet::weight((0, DispatchClass::Operational))] - pub fn set_term_duration( - origin: OriginFor, - #[pallet::compact] count: T::BlockNumber, - ) -> DispatchResult { - ensure_root(origin)?; - >::put(count); - Ok(()) - } - } -} - -impl Pallet { - // exposed immutables. - - /// True if we're currently in a presentation period. - pub fn presentation_active() -> bool { - >::exists() - } - - /// If `who` a candidate at the moment? - pub fn is_a_candidate(who: &T::AccountId) -> bool { - >::contains_key(who) - } - - /// Iff the member `who` still has a seat at blocknumber `n` returns `true`. - pub fn will_still_be_member_at(who: &T::AccountId, n: T::BlockNumber) -> bool { - Self::members() - .iter() - .find(|&&(ref a, _)| a == who) - .map(|&(_, expires)| expires > n) - .unwrap_or(false) - } - - /// Determine the block that a vote can happen on which is no less than `n`. - pub fn next_vote_from(n: T::BlockNumber) -> T::BlockNumber { - let voting_period = T::VotingPeriod::get(); - (n + voting_period - One::one()) / voting_period * voting_period - } - - /// The block number on which the tally for the next election will happen. `None` only if the - /// desired seats of the set is zero. - pub fn next_tally() -> Option { - let desired_seats = Self::desired_seats(); - if desired_seats == 0 { - None - } else { - let c = Self::members(); - let (next_possible, count, coming) = if let Some((tally_end, comers, leavers)) = - Self::next_finalize() - { - // if there's a tally in progress, then next tally can begin immediately afterwards - (tally_end, c.len() - leavers.len() + comers as usize, comers) - } else { - (>::block_number(), c.len(), 0) - }; - if count < desired_seats as usize { - Some(next_possible) - } else { - // next tally begins once enough members expire to bring members below desired. - if desired_seats <= coming { - // the entire amount of desired seats is less than those new members - we'll - // have to wait until they expire. - Some(next_possible + Self::term_duration()) - } else { - Some(c[c.len() - (desired_seats - coming) as usize].1) - } - } - .map(Self::next_vote_from) - } - } - - // Private - /// Check there's nothing to do this block - fn end_block(block_number: T::BlockNumber) -> DispatchResult { - if (block_number % T::VotingPeriod::get()).is_zero() { - if let Some(number) = Self::next_tally() { - if block_number == number { - Self::start_tally(); - } - } - } - if let Some((number, _, _)) = Self::next_finalize() { - if block_number == number { - Self::finalize_tally()? - } - } - Ok(()) - } - - /// Remove a voter at a specified index from the system. - fn remove_voter(voter: &T::AccountId, index: usize) { - let (set_index, vec_index) = Self::split_index(index, VOTER_SET_SIZE); - let mut set = Self::voters(set_index); - set[vec_index] = None; - >::insert(set_index, set); - VoterCount::::mutate(|c| *c = *c - 1); - Self::remove_all_approvals_of(voter); - >::remove(voter); - } - - /// Actually do the voting. - /// - /// The voter index must be provided as explained in [`voter_at`] function. - fn do_set_approvals( - who: T::AccountId, - votes: Vec, - index: VoteIndex, - hint: SetIndex, - value: BalanceOf, - ) -> DispatchResult { - let candidates_len = ::Candidates::decode_len().unwrap_or(0_usize); - - ensure!(!Self::presentation_active(), Error::::ApprovalPresentation); - ensure!(index == Self::vote_index(), Error::::InvalidVoteIndex); - ensure!(!candidates_len.is_zero(), Error::::ZeroCandidates); - // Prevent a vote from voters that provide a list of votes that exceeds the candidates - // length since otherwise an attacker may be able to submit a very long list of `votes` that - // far exceeds the amount of candidates and waste more computation than a reasonable voting - // bond would cover. - ensure!(candidates_len >= votes.len(), Error::::TooManyVotes); - ensure!(value >= T::MinimumVotingLock::get(), Error::::InsufficientLockedValue); - - // Amount to be locked up. - let mut locked_balance = value.min(T::Currency::total_balance(&who)); - let mut pot_to_set = Zero::zero(); - let hint = hint as usize; - - if let Some(info) = Self::voter_info(&who) { - // already a voter. Index must be valid. No fee. update pot. O(1) - let voter = Self::voter_at(hint).ok_or(Error::::InvalidVoterIndex)?; - ensure!(voter == who, Error::::InvalidVoterIndex); - - // write new accumulated offset. - let last_win = info.last_win; - let now = index; - let offset = Self::get_offset(info.stake, now - last_win); - pot_to_set = info.pot + offset; - } else { - // not yet a voter. Index _could be valid_. Fee might apply. Bond will be reserved O(1). - ensure!( - T::Currency::free_balance(&who) > T::VotingBond::get(), - Error::::InsufficientVoterFunds, - ); - - let (set_index, vec_index) = Self::split_index(hint, VOTER_SET_SIZE); - match Self::cell_status(set_index, vec_index) { - CellStatus::Hole => { - // requested cell was a valid hole. - >::mutate(set_index, |set| set[vec_index] = Some(who.clone())); - }, - CellStatus::Head | CellStatus::Occupied => { - // Either occupied or out-of-range. - let next = Self::next_nonfull_voter_set(); - let set_len = >::decode_len(next).unwrap_or(0_usize); - // Caused a new set to be created. Pay for it. - // This is the last potential error. Writes will begin afterwards. - if set_len == 0 { - let imbalance = T::Currency::withdraw( - &who, - T::VotingFee::get(), - WithdrawReasons::FEE, - ExistenceRequirement::KeepAlive, - )?; - T::BadVoterIndex::on_unbalanced(imbalance); - // NOTE: this is safe since the `withdraw()` will check this. - locked_balance -= T::VotingFee::get(); - } - if set_len + 1 == VOTER_SET_SIZE { - NextVoterSet::::put(next + 1); - } - >::append(next, Some(who.clone())); - }, - } - - T::Currency::reserve(&who, T::VotingBond::get())?; - VoterCount::::mutate(|c| *c = *c + 1); - } - - T::Currency::set_lock(T::PalletId::get(), &who, locked_balance, WithdrawReasons::all()); - - >::insert( - &who, - VoterInfo::> { - last_active: index, - last_win: index, - stake: locked_balance, - pot: pot_to_set, - }, - ); - Self::set_approvals_chunked(&who, votes); - - Ok(()) - } - - /// Close the voting, record the number of seats that are actually up for grabs. - fn start_tally() { - let members = Self::members(); - let desired_seats = Self::desired_seats() as usize; - let number = >::block_number(); - let expiring = members - .iter() - .take_while(|i| i.1 <= number) - .map(|i| i.0.clone()) - .collect::>(); - let retaining_seats = members.len() - expiring.len(); - if retaining_seats < desired_seats { - let empty_seats = desired_seats - retaining_seats; - >::put(( - number + Self::presentation_duration(), - empty_seats as u32, - expiring, - )); - - // initialize leaderboard. - let leaderboard_size = empty_seats + T::CarryCount::get() as usize; - >::put(vec![ - (BalanceOf::::zero(), T::AccountId::default()); - leaderboard_size - ]); - - Self::deposit_event(Event::::TallyStarted { seats: empty_seats as u32 }); - } - } - - /// Finalize the vote, removing each of the `removals` and inserting `seats` of the most - /// approved candidates in their place. If the total number of members is less than the desired - /// membership a new vote is started. Clears all presented candidates, returning the bond of the - /// elected ones. - fn finalize_tally() -> DispatchResult { - let (_, coming, expiring): (T::BlockNumber, u32, Vec) = - >::take() - .ok_or("finalize can only be called after a tally is started.")?; - let leaderboard: Vec<(BalanceOf, T::AccountId)> = - >::take().unwrap_or_default(); - let new_expiry = >::block_number() + Self::term_duration(); - - // return bond to winners. - let candidacy_bond = T::CandidacyBond::get(); - let incoming: Vec<_> = leaderboard - .iter() - .rev() - .take_while(|&&(b, _)| !b.is_zero()) - .take(coming as usize) - .map(|(_, a)| a) - .cloned() - .inspect(|a| { - T::Currency::unreserve(a, candidacy_bond); - }) - .collect(); - - // Update last win index for anyone voted for any of the incomings. - incoming.iter().filter_map(|i| Self::candidate_reg_info(i)).for_each(|r| { - let index = r.1 as usize; - Self::all_voters() - .iter() - .filter_map(|mv| mv.as_ref()) - .filter(|v| Self::approvals_of_at(*v, index)) - .for_each(|v| { - >::mutate(v, |a| { - if let Some(activity) = a { - activity.last_win = Self::vote_index() + 1; - } - }) - }); - }); - let members = Self::members(); - let outgoing: Vec<_> = members.iter().take(expiring.len()).map(|a| a.0.clone()).collect(); - - // set the new membership set. - let mut new_set: Vec<_> = members - .into_iter() - .skip(expiring.len()) - .chain(incoming.iter().cloned().map(|a| (a, new_expiry))) - .collect(); - new_set.sort_by_key(|&(_, expiry)| expiry); - >::put(&new_set); - - let new_set = new_set.into_iter().map(|x| x.0).collect::>(); - T::ChangeMembers::change_members(&incoming, &outgoing, new_set); - - // clear all except runners-up from candidate list. - let candidates = Self::candidates(); - let mut new_candidates = vec![T::AccountId::default(); candidates.len()]; // shrink later. - let runners_up = leaderboard - .into_iter() - .rev() - .take_while(|&(b, _)| !b.is_zero()) - .skip(coming as usize) - .filter_map(|(_, a)| Self::candidate_reg_info(&a).map(|i| (a, i.1))); - let mut count = 0u32; - for (address, slot) in runners_up { - new_candidates[slot as usize] = address; - count += 1; - } - for (old, new) in candidates.iter().zip(new_candidates.iter()) { - // candidate is not a runner up. - if old != new { - // removed - kill it - >::remove(old); - - // and candidate is not a winner. - if incoming.iter().find(|e| *e == old).is_none() { - // slash the bond. - let (imbalance, _) = T::Currency::slash_reserved(&old, T::CandidacyBond::get()); - T::LoserCandidate::on_unbalanced(imbalance); - } - } - } - // discard any superfluous slots. - if let Some(last_index) = new_candidates.iter().rposition(|c| *c != T::AccountId::default()) - { - new_candidates.truncate(last_index + 1); - } - - Self::deposit_event(Event::::TallyFinalized { incoming, outgoing }); - - >::put(new_candidates); - CandidateCount::::put(count); - VoteCount::::put(Self::vote_index() + 1); - Ok(()) - } - - /// Get the set and vector index of a global voter index. - /// - /// Note that this function does not take holes into account. - /// See [`voter_at`]. - fn split_index(index: usize, scale: usize) -> (SetIndex, usize) { - let set_index = (index / scale) as u32; - let vec_index = index % scale; - (set_index, vec_index) - } - - /// Return a concatenated vector over all voter sets. - fn all_voters() -> Vec> { - let mut all = >::get(0); - let mut index = 1; - // NOTE: we could also use `Self::next_nonfull_voter_set()` here but that might change based - // on how we do chunking. This is more generic. - loop { - let next_set = >::get(index); - if next_set.is_empty() { - break - } else { - index += 1; - all.extend(next_set); - } - } - all - } - - /// Shorthand for fetching a voter at a specific (global) index. - /// - /// NOTE: this function is used for checking indices. Yet, it does not take holes into account. - /// This means that any account submitting an index at any point in time should submit: - /// `VOTER_SET_SIZE * set_index + local_index`, meaning that you are ignoring all holes in the - /// first `set_index` sets. - fn voter_at(index: usize) -> Option { - let (set_index, vec_index) = Self::split_index(index, VOTER_SET_SIZE); - let set = Self::voters(set_index); - if vec_index < set.len() { - set[vec_index].clone() - } else { - None - } - } - - /// A more sophisticated version of `voter_at`. Will be kept separate as most often it is an - /// overdue compared to `voter_at`. Only used when setting approvals. - fn cell_status(set_index: SetIndex, vec_index: usize) -> CellStatus { - let set = Self::voters(set_index); - if vec_index < set.len() { - if let Some(_) = set[vec_index] { - CellStatus::Occupied - } else { - CellStatus::Hole - } - } else { - CellStatus::Head - } - } - - /// Sets the approval of a voter in a chunked manner. - fn set_approvals_chunked(who: &T::AccountId, approvals: Vec) { - let approvals_flag_vec = Self::bool_to_flag(approvals); - approvals_flag_vec - .chunks(APPROVAL_SET_SIZE) - .enumerate() - .for_each(|(index, slice)| >::insert((&who, index as SetIndex), slice)); - } - - /// shorthand for fetching a specific approval of a voter at a specific (global) index. - /// - /// Using this function to read a vote is preferred as it reads `APPROVAL_SET_SIZE` items of - /// type `ApprovalFlag` from storage at most; not all of them. - /// - /// Note that false is returned in case of no-vote or an explicit `false`. - fn approvals_of_at(who: &T::AccountId, index: usize) -> bool { - let (flag_index, bit) = Self::split_index(index, APPROVAL_FLAG_LEN); - let (set_index, vec_index) = Self::split_index(flag_index as usize, APPROVAL_SET_SIZE); - let set = Self::approvals_of((who.clone(), set_index)); - if vec_index < set.len() { - // This is because bit_at treats numbers in lsb -> msb order. - let reversed_index = set.len() - 1 - vec_index; - Self::bit_at(set[reversed_index], bit) - } else { - false - } - } - - /// Return true of the bit `n` of scalar `x` is set to `1` and false otherwise. - fn bit_at(x: ApprovalFlag, n: usize) -> bool { - if n < APPROVAL_FLAG_LEN { - x & (1 << n) != 0 - } else { - false - } - } - - /// Convert a vec of boolean approval flags to a vec of integers, as denoted by - /// the type `ApprovalFlag`. see `bool_to_flag_should_work` test for examples. - pub fn bool_to_flag(x: Vec) -> Vec { - let mut result: Vec = Vec::with_capacity(x.len() / APPROVAL_FLAG_LEN); - if x.is_empty() { - return result - } - result.push(0); - let mut index = 0; - let mut counter = 0; - loop { - let shl_index = counter % APPROVAL_FLAG_LEN; - result[index] += (if x[counter] { 1 } else { 0 }) << shl_index; - counter += 1; - if counter > x.len() - 1 { - break - } - if counter % APPROVAL_FLAG_LEN == 0 { - result.push(0); - index += 1; - } - } - result - } - - /// Convert a vec of flags (u32) to boolean. - pub fn flag_to_bool(chunk: Vec) -> Vec { - let mut result = Vec::with_capacity(chunk.len()); - if chunk.is_empty() { - return vec![] - } - chunk - .into_iter() - .map(|num| { - (0..APPROVAL_FLAG_LEN).map(|bit| Self::bit_at(num, bit)).collect::>() - }) - .for_each(|c| { - let last_approve = match c.iter().rposition(|n| *n) { - Some(index) => index + 1, - None => 0, - }; - result.extend(c.into_iter().take(last_approve)); - }); - result - } - - /// Return a concatenated vector over all approvals of a voter as boolean. - /// The trailing zeros are removed. - fn all_approvals_of(who: &T::AccountId) -> Vec { - let mut all: Vec = vec![]; - let mut index = 0_u32; - loop { - let chunk = Self::approvals_of((who.clone(), index)); - if chunk.is_empty() { - break - } - all.extend(Self::flag_to_bool(chunk)); - index += 1; - } - all - } - - /// Remove all approvals associated with one account. - fn remove_all_approvals_of(who: &T::AccountId) { - let mut index = 0; - loop { - let set = Self::approvals_of((who.clone(), index)); - if set.len() > 0 { - >::remove((who.clone(), index)); - index += 1; - } else { - break - } - } - } - - /// Calculates the offset value (stored pot) of a stake, based on the distance - /// to the last win_index, `t`. Regardless of the internal implementation, - /// it should always be used with the following structure: - /// - /// Given Stake of voter `V` being `x` and distance to last_win index `t`, the new weight - /// of `V` is `x + get_offset(x, t)`. - /// - /// In other words, this function returns everything extra that should be added - /// to a voter's stake value to get the correct weight. Indeed, zero is - /// returned if `t` is zero. - fn get_offset(stake: BalanceOf, t: VoteIndex) -> BalanceOf { - let decay_ratio: BalanceOf = T::DecayRatio::get().into(); - if t > 150 { - return stake * decay_ratio - } - let mut offset = stake; - let mut r = Zero::zero(); - let decay = decay_ratio + One::one(); - for _ in 0..t { - offset = offset.saturating_sub(offset / decay); - r += offset - } - r - } -} diff --git a/frame/elections/src/mock.rs b/frame/elections/src/mock.rs deleted file mode 100644 index bce60534a352..000000000000 --- a/frame/elections/src/mock.rs +++ /dev/null @@ -1,274 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2019-2021 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. - -//! Mock file for election module. - -#![cfg(test)] - -use crate as elections; -use frame_support::{ - assert_ok, parameter_types, - traits::{ChangeMembers, Currency, LockIdentifier}, -}; -use sp_core::H256; -use sp_runtime::{ - testing::Header, - traits::{BlakeTwo256, IdentityLookup}, - BuildStorage, -}; - -parameter_types! { - pub const BlockHashCount: u64 = 250; - pub BlockWeights: frame_system::limits::BlockWeights = - frame_system::limits::BlockWeights::simple_max(1024); -} -impl frame_system::Config for Test { - type BaseCallFilter = frame_support::traits::Everything; - type BlockWeights = (); - type BlockLength = (); - type DbWeight = (); - type Origin = Origin; - type Call = Call; - type Index = u64; - type BlockNumber = u64; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type Event = Event; - type BlockHashCount = BlockHashCount; - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = (); - type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; -} - -parameter_types! { - pub const ExistentialDeposit: u64 = 1; -} -impl pallet_balances::Config for Test { - type MaxLocks = (); - type MaxReserves = (); - type ReserveIdentifier = [u8; 8]; - type Balance = u64; - type DustRemoval = (); - type Event = Event; - type ExistentialDeposit = ExistentialDeposit; - type AccountStore = System; - type WeightInfo = (); -} - -parameter_types! { - pub const CandidacyBond: u64 = 3; - pub const CarryCount: u32 = 2; - pub const InactiveGracePeriod: u32 = 1; - pub const VotingPeriod: u64 = 4; - pub const MinimumVotingLock: u64 = 5; - pub static VotingBond: u64 = 0; - pub static VotingFee: u64 = 0; - pub static PresentSlashPerVoter: u64 = 0; - pub static DecayRatio: u32 = 0; - pub static Members: Vec = vec![]; -} - -pub struct TestChangeMembers; -impl ChangeMembers for TestChangeMembers { - fn change_members_sorted(incoming: &[u64], outgoing: &[u64], new: &[u64]) { - let mut old_plus_incoming = MEMBERS.with(|m| m.borrow().to_vec()); - old_plus_incoming.extend_from_slice(incoming); - old_plus_incoming.sort(); - let mut new_plus_outgoing = new.to_vec(); - new_plus_outgoing.extend_from_slice(outgoing); - new_plus_outgoing.sort(); - assert_eq!(old_plus_incoming, new_plus_outgoing); - - MEMBERS.with(|m| *m.borrow_mut() = new.to_vec()); - } -} - -parameter_types! { - pub const ElectionPalletId: LockIdentifier = *b"py/elect"; -} - -impl elections::Config for Test { - type Event = Event; - type Currency = Balances; - type BadPresentation = (); - type BadReaper = (); - type BadVoterIndex = (); - type LoserCandidate = (); - type ChangeMembers = TestChangeMembers; - type CandidacyBond = CandidacyBond; - type VotingBond = VotingBond; - type VotingFee = VotingFee; - type MinimumVotingLock = MinimumVotingLock; - type PresentSlashPerVoter = PresentSlashPerVoter; - type CarryCount = CarryCount; - type InactiveGracePeriod = InactiveGracePeriod; - type VotingPeriod = VotingPeriod; - type DecayRatio = DecayRatio; - type PalletId = ElectionPalletId; -} - -pub type Block = sp_runtime::generic::Block; -pub type UncheckedExtrinsic = sp_runtime::generic::UncheckedExtrinsic; - -use frame_system as system; -frame_support::construct_runtime!( - pub enum Test where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic - { - System: system::{Pallet, Call, Event}, - Balances: pallet_balances::{Pallet, Call, Event, Config}, - Elections: elections::{Pallet, Call, Event, Config}, - } -); - -pub struct ExtBuilder { - balance_factor: u64, - decay_ratio: u32, - desired_seats: u32, - voting_fee: u64, - voting_bond: u64, - bad_presentation_punishment: u64, -} - -impl Default for ExtBuilder { - fn default() -> Self { - Self { - balance_factor: 1, - decay_ratio: 24, - desired_seats: 2, - voting_fee: 0, - voting_bond: 0, - bad_presentation_punishment: 1, - } - } -} - -impl ExtBuilder { - pub fn balance_factor(mut self, factor: u64) -> Self { - self.balance_factor = factor; - self - } - pub fn decay_ratio(mut self, ratio: u32) -> Self { - self.decay_ratio = ratio; - self - } - pub fn voting_fee(mut self, fee: u64) -> Self { - self.voting_fee = fee; - self - } - pub fn bad_presentation_punishment(mut self, fee: u64) -> Self { - self.bad_presentation_punishment = fee; - self - } - pub fn voting_bond(mut self, fee: u64) -> Self { - self.voting_bond = fee; - self - } - pub fn desired_seats(mut self, seats: u32) -> Self { - self.desired_seats = seats; - self - } - pub fn build(self) -> sp_io::TestExternalities { - VOTING_BOND.with(|v| *v.borrow_mut() = self.voting_bond); - VOTING_FEE.with(|v| *v.borrow_mut() = self.voting_fee); - PRESENT_SLASH_PER_VOTER.with(|v| *v.borrow_mut() = self.bad_presentation_punishment); - DECAY_RATIO.with(|v| *v.borrow_mut() = self.decay_ratio); - let mut ext: sp_io::TestExternalities = GenesisConfig { - balances: pallet_balances::GenesisConfig:: { - balances: vec![ - (1, 10 * self.balance_factor), - (2, 20 * self.balance_factor), - (3, 30 * self.balance_factor), - (4, 40 * self.balance_factor), - (5, 50 * self.balance_factor), - (6, 60 * self.balance_factor), - ], - }, - elections: elections::GenesisConfig:: { - members: vec![], - desired_seats: self.desired_seats, - presentation_duration: 2, - term_duration: 5, - }, - } - .build_storage() - .unwrap() - .into(); - ext.execute_with(|| System::set_block_number(1)); - ext - } -} - -pub(crate) fn voter_ids() -> Vec { - Elections::all_voters().iter().map(|v| v.unwrap_or(0)).collect::>() -} - -pub(crate) fn vote(i: u64, l: usize) { - let _ = Balances::make_free_balance_be(&i, 20); - assert_ok!(Elections::set_approvals( - Origin::signed(i), - (0..l).map(|_| true).collect::>(), - 0, - 0, - 20, - )); -} - -pub(crate) fn vote_at(i: u64, l: usize, index: elections::VoteIndex) { - let _ = Balances::make_free_balance_be(&i, 20); - assert_ok!(Elections::set_approvals( - Origin::signed(i), - (0..l).map(|_| true).collect::>(), - 0, - index, - 20, - )); -} - -pub(crate) fn create_candidate(i: u64, index: u32) { - let _ = Balances::make_free_balance_be(&i, 20); - assert_ok!(Elections::submit_candidacy(Origin::signed(i), index)); -} - -pub(crate) fn balances(who: &u64) -> (u64, u64) { - (Balances::free_balance(who), Balances::reserved_balance(who)) -} - -pub(crate) fn locks(who: &u64) -> Vec { - Balances::locks(who).iter().map(|l| l.amount).collect::>() -} - -pub(crate) fn new_test_ext_with_candidate_holes() -> sp_io::TestExternalities { - let mut t = ExtBuilder::default().build(); - t.execute_with(|| { - >::put(vec![0, 0, 1]); - elections::CandidateCount::::put(1); - >::insert(1, (0, 2)); - }); - t -} diff --git a/frame/elections/src/tests.rs b/frame/elections/src/tests.rs deleted file mode 100644 index 0df84c6d79ba..000000000000 --- a/frame/elections/src/tests.rs +++ /dev/null @@ -1,1881 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2019-2021 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. - -//! Tests for election module. - -#![cfg(test)] - -use crate::{mock::*, *}; - -use frame_support::{assert_err, assert_noop, assert_ok}; - -#[test] -fn params_should_work() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!(Elections::next_vote_from(1), 4); - assert_eq!(Elections::next_vote_from(4), 4); - assert_eq!(Elections::next_vote_from(5), 8); - assert_eq!(Elections::vote_index(), 0); - assert_eq!(Elections::presentation_duration(), 2); - assert_eq!(Elections::term_duration(), 5); - assert_eq!(Elections::desired_seats(), 2); - - assert_eq!(Elections::members(), vec![]); - assert_eq!(Elections::next_tally(), Some(4)); - assert_eq!(Elections::presentation_active(), false); - assert_eq!(Elections::next_finalize(), None); - - assert_eq!(Elections::candidates(), Vec::::new()); - assert_eq!(Elections::is_a_candidate(&1), false); - assert_eq!(Elections::candidate_reg_info(1), None); - - assert_eq!(Elections::voters(0), Vec::>::new()); - assert_eq!(Elections::voter_info(1), None); - assert!(Elections::all_approvals_of(&1).is_empty()); - }); -} - -#[test] -fn chunking_bool_to_flag_should_work() { - ExtBuilder::default().build().execute_with(|| { - assert!(Elections::bool_to_flag(vec![]).is_empty()); - assert_eq!(Elections::bool_to_flag(vec![false]), vec![0]); - assert_eq!(Elections::bool_to_flag(vec![true]), vec![1]); - assert_eq!(Elections::bool_to_flag(vec![true, true, true, true]), vec![15]); - assert_eq!(Elections::bool_to_flag(vec![true, true, true, true, true]), vec![15 + 16]); - - let set_1 = vec![ - true, false, false, false, // 0x1 - false, true, true, true, // 0xE - ]; - assert_eq!(Elections::bool_to_flag(set_1.clone()), vec![0x00_00_00_E1_u32]); - assert_eq!(Elections::flag_to_bool(vec![0x00_00_00_E1_u32]), set_1); - - let set_2 = vec![ - false, false, false, true, // 0x8 - false, true, false, true, // 0xA - ]; - assert_eq!(Elections::bool_to_flag(set_2.clone()), vec![0x00_00_00_A8_u32]); - assert_eq!(Elections::flag_to_bool(vec![0x00_00_00_A8_u32]), set_2); - - let mut rhs = (0..100 / APPROVAL_FLAG_LEN).map(|_| 0xFFFFFFFF_u32).collect::>(); - // NOTE: this might be need change based on `APPROVAL_FLAG_LEN`. - rhs.extend(vec![0x00_00_00_0F]); - assert_eq!(Elections::bool_to_flag((0..100).map(|_| true).collect()), rhs) - }) -} - -#[test] -fn chunking_voter_set_growth_should_work() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - - // create 65. 64 (set0) + 1 (set1) - (1..=63).for_each(|i| vote(i, 0)); - assert_eq!(Elections::next_nonfull_voter_set(), 0); - vote(64, 0); - assert_eq!(Elections::next_nonfull_voter_set(), 1); - vote(65, 0); - - let set1 = Elections::voters(0); - let set2 = Elections::voters(1); - - assert_eq!(set1.len(), 64); - assert_eq!(set2.len(), 1); - - assert_eq!(set1[0], Some(1)); - assert_eq!(set1[10], Some(11)); - assert_eq!(set2[0], Some(65)); - }) -} - -#[test] -fn chunking_voter_set_reclaim_should_work() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - - (1..=129).for_each(|i| vote(i, 0)); - assert_eq!(Elections::next_nonfull_voter_set(), 2); - - assert_ok!(Elections::retract_voter(Origin::signed(11), 10)); - - assert_ok!(Elections::retract_voter(Origin::signed(66), 65)); - assert_ok!(Elections::retract_voter(Origin::signed(67), 66)); - - // length does not show it but holes do exist. - assert_eq!(Elections::voters(0).len(), 64); - assert_eq!(Elections::voters(1).len(), 64); - assert_eq!(Elections::voters(2).len(), 1); - - assert_eq!(Elections::voters(0)[10], None); - assert_eq!(Elections::voters(1)[1], None); - assert_eq!(Elections::voters(1)[2], None); - // Next set with capacity is 2. - assert_eq!(Elections::next_nonfull_voter_set(), 2); - - // But we can fill a hole. - vote_at(130, 0, 10); - - // Nothing added to set 2. A hole was filled. - assert_eq!(Elections::voters(0).len(), 64); - assert_eq!(Elections::voters(1).len(), 64); - assert_eq!(Elections::voters(2).len(), 1); - - // and the next two (scheduled) to the second set. - assert_eq!(Elections::next_nonfull_voter_set(), 2); - }) -} - -#[test] -fn chunking_approvals_set_growth_should_work() { - ExtBuilder::default().build().execute_with(|| { - // create candidates and voters. - (1..=250).for_each(|i| create_candidate(i, (i - 1) as u32)); - (1..=250).for_each(|i| vote(i, i as usize)); - - // all approvals of should return the exact expected vector. - assert_eq!( - Elections::all_approvals_of(&180), - (0..180).map(|_| true).collect::>() - ); - assert_eq!(Elections::all_approvals_of(&32), (0..32).map(|_| true).collect::>()); - assert_eq!(Elections::all_approvals_of(&8), (0..8).map(|_| true).collect::>()); - assert_eq!(Elections::all_approvals_of(&64), (0..64).map(|_| true).collect::>()); - assert_eq!(Elections::all_approvals_of(&65), (0..65).map(|_| true).collect::>()); - assert_eq!(Elections::all_approvals_of(&63), (0..63).map(|_| true).collect::>()); - - // NOTE: assuming that APPROVAL_SET_SIZE is more or less small-ish. Might fail otherwise. - let full_sets = (180 / APPROVAL_FLAG_LEN) / APPROVAL_SET_SIZE; - let left_over = (180 / APPROVAL_FLAG_LEN) / APPROVAL_SET_SIZE; - let rem = 180 % APPROVAL_FLAG_LEN; - - // grab and check the last full set, if it exists. - if full_sets > 0 { - assert_eq!( - Elections::approvals_of((180, (full_sets - 1) as SetIndex)), - Elections::bool_to_flag( - (0..APPROVAL_SET_SIZE * APPROVAL_FLAG_LEN).map(|_| true).collect::>() - ) - ); - } - - // grab and check the last, half-empty, set. - if left_over > 0 { - assert_eq!( - Elections::approvals_of((180, full_sets as SetIndex)), - Elections::bool_to_flag( - (0..left_over * APPROVAL_FLAG_LEN + rem).map(|_| true).collect::>() - ) - ); - } - }) -} - -#[test] -fn chunking_cell_status_works() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - - (1..=63).for_each(|i| vote(i, 0)); - - assert_ok!(Elections::retract_voter(Origin::signed(11), 10)); - assert_ok!(Elections::retract_voter(Origin::signed(21), 20)); - - assert_eq!(Elections::cell_status(0, 10), CellStatus::Hole); - assert_eq!(Elections::cell_status(0, 0), CellStatus::Occupied); - assert_eq!(Elections::cell_status(0, 20), CellStatus::Hole); - assert_eq!(Elections::cell_status(0, 63), CellStatus::Head); - assert_eq!(Elections::cell_status(1, 0), CellStatus::Head); - assert_eq!(Elections::cell_status(1, 10), CellStatus::Head); - }) -} - -#[test] -fn chunking_voter_index_does_not_take_holes_into_account() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - - // create 65. 64 (set0) + 1 (set1) - (1..=65).for_each(|i| vote(i, 0)); - - // account 65 has global index 65. - assert_eq!(Elections::voter_at(64).unwrap(), 65); - - assert_ok!(Elections::retract_voter(Origin::signed(1), 0)); - assert_ok!(Elections::retract_voter(Origin::signed(2), 1)); - - // still the same. These holes are in some other set. - assert_eq!(Elections::voter_at(64).unwrap(), 65); - // proof: can submit a new approval with the old index. - assert_noop!( - Elections::set_approvals(Origin::signed(65), vec![], 0, 64 - 2, 10), - Error::::InvalidVoterIndex, - ); - assert_ok!(Elections::set_approvals(Origin::signed(65), vec![], 0, 64, 10)); - }) -} - -#[test] -fn chunking_approval_storage_should_work() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 1)); - - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true, false], 0, 0, 20)); - assert_ok!(Elections::set_approvals(Origin::signed(3), vec![false, false], 0, 0, 30)); - assert_ok!(Elections::set_approvals(Origin::signed(4), vec![], 0, 0, 40)); - - assert_eq!(Elections::all_approvals_of(&2), vec![true]); - // NOTE: these two are stored in mem differently though. - assert!(Elections::all_approvals_of(&3).is_empty()); - assert!(Elections::all_approvals_of(&4).is_empty()); - - assert_eq!(Elections::approvals_of((3, 0)), vec![0]); - assert!(Elections::approvals_of((4, 0)).is_empty()); - }); -} - -#[test] -fn voting_initial_set_approvals_ignores_voter_index() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - - // Last argument is essentially irrelevant. You might get or miss a tip. - assert_ok!(Elections::set_approvals(Origin::signed(3), vec![], 0, 0, 30)); - assert_ok!(Elections::set_approvals(Origin::signed(4), vec![], 0, 5, 40)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![], 0, 100, 50)); - - // indices are more or less ignored. all is pushed. - assert_eq!(voter_ids(), vec![3, 4, 5]); - }) -} -#[test] -fn voting_bad_approval_index_slashes_voters_and_bond_reduces_stake() { - ExtBuilder::default().voting_fee(5).voting_bond(2).build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - - (1..=63).for_each(|i| vote(i, 0)); - assert_eq!(balances(&1), (13, 2)); - assert_eq!(balances(&10), (18, 2)); - assert_eq!(balances(&60), (18, 2)); - - // still no fee - vote(64, 0); - assert_eq!(balances(&64), (18, 2)); - assert_eq!( - Elections::voter_info(&64).unwrap(), - VoterInfo { last_win: 0, last_active: 0, stake: 20, pot: 0 } - ); - - assert_eq!(Elections::next_nonfull_voter_set(), 1); - - // now we charge the next voter. - vote(65, 0); - assert_eq!(balances(&65), (13, 2)); - assert_eq!( - Elections::voter_info(&65).unwrap(), - VoterInfo { last_win: 0, last_active: 0, stake: 15, pot: 0 } - ); - }); -} - -#[test] -fn voting_subsequent_set_approvals_checks_voter_index() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - - assert_ok!(Elections::set_approvals(Origin::signed(3), vec![], 0, 0, 30)); - assert_ok!(Elections::set_approvals(Origin::signed(4), vec![], 0, 5, 40)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![], 0, 100, 50)); - - // invalid index - assert_noop!( - Elections::set_approvals(Origin::signed(4), vec![true], 0, 5, 40), - Error::::InvalidVoterIndex, - ); - // wrong index - assert_noop!( - Elections::set_approvals(Origin::signed(4), vec![true], 0, 0, 40), - Error::::InvalidVoterIndex, - ); - // correct - assert_ok!(Elections::set_approvals(Origin::signed(4), vec![true], 0, 1, 40)); - }) -} - -#[test] -fn voting_cannot_lock_less_than_limit() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - - assert_noop!( - Elections::set_approvals(Origin::signed(3), vec![], 0, 0, 4), - Error::::InsufficientLockedValue, - ); - assert_ok!(Elections::set_approvals(Origin::signed(3), vec![], 0, 0, 5)); - }); -} - -#[test] -fn voting_locking_more_than_total_balance_is_moot() { - ExtBuilder::default().voting_bond(2).build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - - assert_eq!(balances(&3), (30, 0)); - assert_ok!(Elections::set_approvals(Origin::signed(3), vec![], 0, 0, 35)); - - assert_eq!(balances(&3), (28, 2)); - assert_eq!( - Elections::voter_info(&3).unwrap(), - VoterInfo { last_win: 0, last_active: 0, stake: 30, pot: 0 } - ); - }); -} - -#[test] -fn voting_locking_stake_and_reserving_bond_works() { - ExtBuilder::default().voting_bond(2).build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); - - assert_eq!(balances(&2), (20, 0)); - assert!(locks(&2).is_empty()); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![], 0, 0, 15)); - assert_eq!(balances(&2), (18, 2)); - assert_eq!(locks(&2), vec![15]); - - // deposit a bit more. - let _ = Balances::make_free_balance_be(&2, 100); - - // change vote - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 70)); - assert_eq!(balances(&2), (100, 2)); - assert_eq!(locks(&2), vec![70]); - - assert_ok!(Elections::retract_voter(Origin::signed(2), 0)); - - assert_eq!(balances(&2), (102, 0)); - assert!(locks(&2).is_empty()); - }); -} - -#[test] -fn voting_without_any_candidate_count_should_not_work() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!(Elections::candidates().len(), 0); - - assert_noop!( - Elections::set_approvals(Origin::signed(4), vec![], 0, 0, 40), - Error::::ZeroCandidates, - ); - }); -} - -#[test] -fn voting_setting_an_approval_vote_count_more_than_candidate_count_should_not_work() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); - assert_eq!(Elections::candidates().len(), 1); - - assert_noop!( - Elections::set_approvals(Origin::signed(4), vec![true, true], 0, 0, 40), - Error::::TooManyVotes, - ); - }); -} - -#[test] -fn voting_resubmitting_approvals_should_work() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(4), vec![true], 0, 0, 40)); - - assert_eq!(Elections::all_approvals_of(&4), vec![true]); - - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); - assert_eq!(Elections::candidates().len(), 3); - assert_ok!(Elections::set_approvals(Origin::signed(4), vec![true, false, true], 0, 0, 40)); - - assert_eq!(Elections::all_approvals_of(&4), vec![true, false, true]); - }); -} - -#[test] -fn voting_retracting_voter_should_work() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); - assert_eq!(Elections::candidates().len(), 1); - - assert_ok!(Elections::set_approvals(Origin::signed(1), vec![true], 0, 0, 10)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 1, 20)); - assert_ok!(Elections::set_approvals(Origin::signed(3), vec![true], 0, 2, 30)); - assert_ok!(Elections::set_approvals(Origin::signed(4), vec![true], 0, 3, 40)); - - assert_eq!(voter_ids(), vec![1, 2, 3, 4]); - assert_eq!(Elections::all_approvals_of(&1), vec![true]); - assert_eq!(Elections::all_approvals_of(&2), vec![true]); - assert_eq!(Elections::all_approvals_of(&3), vec![true]); - assert_eq!(Elections::all_approvals_of(&4), vec![true]); - - assert_ok!(Elections::retract_voter(Origin::signed(1), 0)); - - assert_eq!(voter_ids(), vec![0, 2, 3, 4]); - assert_eq!(Elections::all_approvals_of(&1), Vec::::new()); - assert_eq!(Elections::all_approvals_of(&2), vec![true]); - assert_eq!(Elections::all_approvals_of(&3), vec![true]); - assert_eq!(Elections::all_approvals_of(&4), vec![true]); - - assert_ok!(Elections::retract_voter(Origin::signed(2), 1)); - - assert_eq!(voter_ids(), vec![0, 0, 3, 4]); - assert_eq!(Elections::all_approvals_of(&1), Vec::::new()); - assert_eq!(Elections::all_approvals_of(&2), Vec::::new()); - assert_eq!(Elections::all_approvals_of(&3), vec![true]); - assert_eq!(Elections::all_approvals_of(&4), vec![true]); - - assert_ok!(Elections::retract_voter(Origin::signed(3), 2)); - - assert_eq!(voter_ids(), vec![0, 0, 0, 4]); - assert_eq!(Elections::all_approvals_of(&1), Vec::::new()); - assert_eq!(Elections::all_approvals_of(&2), Vec::::new()); - assert_eq!(Elections::all_approvals_of(&3), Vec::::new()); - assert_eq!(Elections::all_approvals_of(&4), vec![true]); - }); -} - -#[test] -fn voting_invalid_retraction_index_should_not_work() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 0)); - - assert_ok!(Elections::set_approvals(Origin::signed(1), vec![true], 0, 0, 10)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 20)); - assert_eq!(voter_ids(), vec![1, 2]); - assert_noop!( - Elections::retract_voter(Origin::signed(1), 1), - Error::::InvalidRetractionIndex - ); - }); -} - -#[test] -fn voting_overflow_retraction_index_should_not_work() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 0)); - - assert_ok!(Elections::set_approvals(Origin::signed(1), vec![true], 0, 0, 10)); - assert_noop!( - Elections::retract_voter(Origin::signed(1), 1), - Error::::InvalidRetractionIndex - ); - }); -} - -#[test] -fn voting_non_voter_retraction_should_not_work() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 0)); - - assert_ok!(Elections::set_approvals(Origin::signed(1), vec![true], 0, 0, 10)); - assert_noop!( - Elections::retract_voter(Origin::signed(2), 0), - Error::::RetractNonVoter - ); - }); -} - -#[test] -fn retracting_inactive_voter_should_work() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(4); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 20)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(8); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![true], 1, 0, 50)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(10); - assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 1)); - assert_ok!(Elections::end_block(System::block_number())); - - assert_ok!(Elections::reap_inactive_voter( - Origin::signed(5), - (voter_ids().iter().position(|&i| i == 5).unwrap() as u32).into(), - 2, - (voter_ids().iter().position(|&i| i == 2).unwrap() as u32).into(), - 2 - )); - - assert_eq!(voter_ids(), vec![0, 5]); - assert_eq!(Elections::all_approvals_of(&2).len(), 0); - assert_eq!(Balances::total_balance(&2), 20); - assert_eq!(Balances::total_balance(&5), 50); - }); -} - -#[test] -fn retracting_inactive_voter_with_other_candidates_in_slots_should_work() { - ExtBuilder::default().voting_bond(2).build().execute_with(|| { - System::set_block_number(4); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 20)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(8); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![true], 1, 0, 50)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(10); - assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 1)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(11); - assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); - - assert_ok!(Elections::reap_inactive_voter( - Origin::signed(5), - (voter_ids().iter().position(|&i| i == 5).unwrap() as u32).into(), - 2, - (voter_ids().iter().position(|&i| i == 2).unwrap() as u32).into(), - 2 - )); - - assert_eq!(voter_ids(), vec![0, 5]); - assert_eq!(Elections::all_approvals_of(&2).len(), 0); - }); -} - -#[test] -fn retracting_inactive_voter_with_bad_reporter_index_should_not_work() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(4); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 20)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(8); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![true], 1, 0, 50)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(10); - assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 1)); - assert_ok!(Elections::end_block(System::block_number())); - - assert_noop!( - Elections::reap_inactive_voter( - Origin::signed(2), - 42, - 2, - (voter_ids().iter().position(|&i| i == 2).unwrap() as u32).into(), - 2 - ), - Error::::InvalidReporterIndex - ); - }); -} - -#[test] -fn retracting_inactive_voter_with_bad_target_index_should_not_work() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(4); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 20)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(8); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![true], 1, 0, 50)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(10); - assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 1)); - assert_ok!(Elections::end_block(System::block_number())); - - assert_noop!( - Elections::reap_inactive_voter( - Origin::signed(2), - (voter_ids().iter().position(|&i| i == 2).unwrap() as u32).into(), - 2, - 42, - 2 - ), - Error::::InvalidTargetIndex - ); - }); -} - -#[test] -fn retracting_active_voter_should_slash_reporter() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(4); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 1)); - assert_ok!(Elections::submit_candidacy(Origin::signed(4), 2)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 3)); - assert_ok!(Elections::set_approvals( - Origin::signed(2), - vec![true, false, false, false], - 0, - 0, - 20 - )); - assert_ok!(Elections::set_approvals( - Origin::signed(3), - vec![false, true, false, false], - 0, - 0, - 30 - )); - assert_ok!(Elections::set_approvals( - Origin::signed(4), - vec![false, false, true, false], - 0, - 0, - 40 - )); - assert_ok!(Elections::set_approvals( - Origin::signed(5), - vec![false, false, false, true], - 0, - 0, - 50 - )); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 3, 30, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 4, 40, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(8); - assert_ok!(Elections::set_desired_seats(Origin::root(), 3)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(10); - assert_ok!(Elections::present_winner( - Origin::signed(4), - 2, - 20 + Elections::get_offset(20, 1), - 1 - )); - assert_ok!(Elections::present_winner( - Origin::signed(4), - 3, - 30 + Elections::get_offset(30, 1), - 1 - )); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::vote_index(), 2); - assert_eq!(::InactiveGracePeriod::get(), 1); - assert_eq!(::VotingPeriod::get(), 4); - assert_eq!( - Elections::voter_info(4), - Some(VoterInfo { last_win: 1, last_active: 0, stake: 40, pot: 0 }) - ); - - assert_ok!(Elections::reap_inactive_voter( - Origin::signed(4), - (voter_ids().iter().position(|&i| i == 4).unwrap() as u32).into(), - 2, - (voter_ids().iter().position(|&i| i == 2).unwrap() as u32).into(), - 2 - )); - - assert_eq!(voter_ids(), vec![2, 3, 0, 5]); - assert_eq!(Elections::all_approvals_of(&4).len(), 0); - assert_eq!(Balances::total_balance(&4), 40); - }); -} - -#[test] -fn retracting_inactive_voter_by_nonvoter_should_not_work() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(4); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 20)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(8); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![true], 1, 0, 50)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(10); - assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 1)); - assert_ok!(Elections::end_block(System::block_number())); - - assert_noop!( - Elections::reap_inactive_voter( - Origin::signed(4), - 0, - 2, - (voter_ids().iter().position(|&i| i == 2).unwrap() as u32).into(), - 2 - ), - Error::::NotVoter - ); - }); -} - -#[test] -fn candidacy_simple_candidate_submission_should_work() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!(Elections::candidates(), Vec::::new()); - assert_eq!(Elections::candidate_reg_info(1), None); - assert_eq!(Elections::candidate_reg_info(2), None); - assert_eq!(Elections::is_a_candidate(&1), false); - assert_eq!(Elections::is_a_candidate(&2), false); - - assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); - assert_eq!(Elections::candidates(), vec![1]); - assert_eq!(Elections::candidate_reg_info(1), Some((0, 0))); - assert_eq!(Elections::candidate_reg_info(2), None); - assert_eq!(Elections::is_a_candidate(&1), true); - assert_eq!(Elections::is_a_candidate(&2), false); - - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); - assert_eq!(Elections::candidates(), vec![1, 2]); - assert_eq!(Elections::candidate_reg_info(1), Some((0, 0))); - assert_eq!(Elections::candidate_reg_info(2), Some((0, 1))); - assert_eq!(Elections::is_a_candidate(&1), true); - assert_eq!(Elections::is_a_candidate(&2), true); - }); -} - -#[test] -fn candidacy_submission_using_free_slot_should_work() { - let mut t = new_test_ext_with_candidate_holes(); - - t.execute_with(|| { - assert_eq!(Elections::candidates(), vec![0, 0, 1]); - - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); - assert_eq!(Elections::candidates(), vec![0, 2, 1]); - - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 0)); - assert_eq!(Elections::candidates(), vec![3, 2, 1]); - }); -} - -#[test] -fn candidacy_submission_using_alternative_free_slot_should_work() { - let mut t = new_test_ext_with_candidate_holes(); - - t.execute_with(|| { - assert_eq!(Elections::candidates(), vec![0, 0, 1]); - - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_eq!(Elections::candidates(), vec![2, 0, 1]); - - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 1)); - assert_eq!(Elections::candidates(), vec![2, 3, 1]); - }); -} - -#[test] -fn candidacy_submission_not_using_free_slot_should_not_work() { - let mut t = new_test_ext_with_candidate_holes(); - - t.execute_with(|| { - assert_noop!( - Elections::submit_candidacy(Origin::signed(4), 3), - Error::::InvalidCandidateSlot - ); - }); -} - -#[test] -fn candidacy_bad_candidate_slot_submission_should_not_work() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!(Elections::candidates(), Vec::::new()); - assert_noop!( - Elections::submit_candidacy(Origin::signed(1), 1), - Error::::InvalidCandidateSlot - ); - }); -} - -#[test] -fn candidacy_non_free_candidate_slot_submission_should_not_work() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!(Elections::candidates(), Vec::::new()); - assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); - assert_eq!(Elections::candidates(), vec![1]); - assert_noop!( - Elections::submit_candidacy(Origin::signed(2), 0), - Error::::InvalidCandidateSlot - ); - }); -} - -#[test] -fn candidacy_dupe_candidate_submission_should_not_work() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!(Elections::candidates(), Vec::::new()); - assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); - assert_eq!(Elections::candidates(), vec![1]); - assert_noop!( - Elections::submit_candidacy(Origin::signed(1), 1), - Error::::DuplicatedCandidate, - ); - }); -} - -#[test] -fn candidacy_poor_candidate_submission_should_not_work() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!(Elections::candidates(), Vec::::new()); - assert_noop!( - Elections::submit_candidacy(Origin::signed(7), 0), - Error::::InsufficientCandidateFunds, - ); - }); -} - -#[test] -fn election_voting_should_work() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); - - assert_ok!(Elections::set_approvals(Origin::signed(1), vec![true], 0, 0, 10)); - assert_ok!(Elections::set_approvals(Origin::signed(4), vec![true], 0, 1, 40)); - - assert_eq!(Elections::all_approvals_of(&1), vec![true]); - assert_eq!(Elections::all_approvals_of(&4), vec![true]); - assert_eq!(voter_ids(), vec![1, 4]); - - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); - - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![false, true, true], 0, 2, 20)); - assert_ok!(Elections::set_approvals(Origin::signed(3), vec![false, true, true], 0, 3, 30)); - - assert_eq!(Elections::all_approvals_of(&1), vec![true]); - assert_eq!(Elections::all_approvals_of(&4), vec![true]); - assert_eq!(Elections::all_approvals_of(&2), vec![false, true, true]); - assert_eq!(Elections::all_approvals_of(&3), vec![false, true, true]); - - assert_eq!(voter_ids(), vec![1, 4, 2, 3]); - }); -} - -#[test] -fn election_simple_tally_should_work() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(4); - assert!(!Elections::presentation_active()); - - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 20)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, true], 0, 0, 50)); - assert_eq!(voter_ids(), vec![2, 5]); - assert_eq!(Elections::all_approvals_of(&2), vec![true]); - assert_eq!(Elections::all_approvals_of(&5), vec![false, true]); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert!(Elections::presentation_active()); - assert_eq!(Elections::present_winner(Origin::signed(4), 2, 20, 0), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(4), 5, 50, 0), Ok(())); - assert_eq!(Elections::leaderboard(), Some(vec![(0, 0), (0, 0), (20, 2), (50, 5)])); - assert_ok!(Elections::end_block(System::block_number())); - - assert!(!Elections::presentation_active()); - assert_eq!(Elections::members(), vec![(5, 11), (2, 11)]); - - assert!(!Elections::is_a_candidate(&2)); - assert!(!Elections::is_a_candidate(&5)); - assert_eq!(Elections::vote_index(), 1); - assert_eq!( - Elections::voter_info(2), - Some(VoterInfo { last_win: 1, last_active: 0, stake: 20, pot: 0 }) - ); - assert_eq!( - Elections::voter_info(5), - Some(VoterInfo { last_win: 1, last_active: 0, stake: 50, pot: 0 }) - ); - }); -} - -#[test] -fn election_seats_should_be_released() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(4); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true, false], 0, 0, 20)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, true], 0, 0, 50)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert!(Elections::presentation_active()); - assert_eq!(Elections::present_winner(Origin::signed(4), 2, 20, 0), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(4), 5, 50, 0), Ok(())); - assert_eq!(Elections::leaderboard(), Some(vec![(0, 0), (0, 0), (20, 2), (50, 5)])); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![(5, 11), (2, 11)]); - let mut current = System::block_number(); - let free_block; - loop { - current += 1; - System::set_block_number(current); - assert_ok!(Elections::end_block(System::block_number())); - if Elections::members().len() == 0 { - free_block = current; - break - } - } - // 11 + 2 which is the next voting period. - assert_eq!(free_block, 14); - }); -} - -#[test] -fn election_presentations_with_zero_staked_deposit_should_not_work() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(4); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 20)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_noop!( - Elections::present_winner(Origin::signed(4), 2, 0, 0), - Error::::ZeroDeposit, - ); - }); -} - -#[test] -fn election_double_presentations_should_be_punished() { - ExtBuilder::default().build().execute_with(|| { - assert!(Balances::can_slash(&4, 10)); - - System::set_block_number(4); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true, false], 0, 0, 20)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, true], 0, 0, 50)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 0)); - assert_eq!( - Elections::present_winner(Origin::signed(4), 5, 50, 0), - Err(Error::::DuplicatedPresentation.into()), - ); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![(5, 11), (2, 11)]); - assert_eq!(Balances::total_balance(&4), 38); - }); -} - -#[test] -fn election_presenting_for_double_election_should_not_work() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(4); - assert_eq!(Elections::submit_candidacy(Origin::signed(2), 0), Ok(())); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 20)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(8); - // NOTE: This is now mandatory to disable the lock - assert_ok!(Elections::retract_voter(Origin::signed(2), 0)); - assert_eq!(Elections::submit_candidacy(Origin::signed(2), 0), Ok(())); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 1, 0, 20)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(10); - assert_noop!( - Elections::present_winner(Origin::signed(4), 2, 20, 1), - Error::::DuplicatedCandidate, - ); - }); -} - -#[test] -fn election_presenting_loser_should_not_work() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(4); - assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true], 0, 0, 60)); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![false, true], 0, 0, 20)); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); - assert_ok!(Elections::set_approvals(Origin::signed(3), vec![false, false, true], 0, 0, 30)); - assert_ok!(Elections::submit_candidacy(Origin::signed(4), 3)); - assert_ok!(Elections::set_approvals( - Origin::signed(4), - vec![false, false, false, true], - 0, - 0, - 40 - )); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 4)); - assert_ok!(Elections::set_approvals( - Origin::signed(5), - vec![false, false, false, false, true], - 0, - 0, - 50 - )); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_ok!(Elections::present_winner(Origin::signed(4), 1, 60, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 3, 30, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 4, 40, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 0)); - - assert_eq!(Elections::leaderboard(), Some(vec![(30, 3), (40, 4), (50, 5), (60, 1)])); - - assert_noop!( - Elections::present_winner(Origin::signed(4), 2, 20, 0), - Error::::UnworthyCandidate - ); - }); -} - -#[test] -fn election_presenting_loser_first_should_not_matter() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(4); - assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true], 0, 0, 60)); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![false, true], 0, 0, 20)); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); - assert_ok!(Elections::set_approvals(Origin::signed(3), vec![false, false, true], 0, 0, 30)); - assert_ok!(Elections::submit_candidacy(Origin::signed(4), 3)); - assert_ok!(Elections::set_approvals( - Origin::signed(4), - vec![false, false, false, true], - 0, - 0, - 40 - )); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 4)); - assert_ok!(Elections::set_approvals( - Origin::signed(5), - vec![false, false, false, false, true], - 0, - 0, - 50 - )); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 1, 60, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 3, 30, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 4, 40, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 0)); - - assert_eq!(Elections::leaderboard(), Some(vec![(30, 3), (40, 4), (50, 5), (60, 1)])); - }); -} - -#[test] -fn election_present_outside_of_presentation_period_should_not_work() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(4); - assert!(!Elections::presentation_active()); - assert_noop!( - Elections::present_winner(Origin::signed(5), 5, 1, 0), - Error::::NotPresentationPeriod, - ); - }); -} - -#[test] -fn election_present_with_invalid_vote_index_should_not_work() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(4); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true, false], 0, 0, 20)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, true], 0, 0, 50)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_noop!( - Elections::present_winner(Origin::signed(4), 2, 20, 1), - Error::::InvalidVoteIndex - ); - }); -} - -#[test] -fn election_present_when_presenter_is_poor_should_not_work() { - let test_present = |p| { - ExtBuilder::default() - .voting_fee(5) - .voting_bond(2) - .bad_presentation_punishment(p) - .build() - .execute_with(|| { - System::set_block_number(4); - let _ = Balances::make_free_balance_be(&1, 15); - assert!(!Elections::presentation_active()); - - // -3 - assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); - assert_eq!(Balances::free_balance(1), 12); - // -2 -5 - assert_ok!(Elections::set_approvals(Origin::signed(1), vec![true], 0, 0, 15)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_eq!(Balances::free_balance(1), 5); - assert_eq!(Balances::reserved_balance(1), 5); - if p > 5 { - assert_noop!( - Elections::present_winner(Origin::signed(1), 1, 10, 0), - Error::::InsufficientPresenterFunds, - ); - } else { - assert_ok!(Elections::present_winner(Origin::signed(1), 1, 10, 0)); - } - }); - }; - test_present(4); - test_present(6); -} - -#[test] -fn election_invalid_present_tally_should_slash() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(4); - assert!(!Elections::presentation_active()); - assert_eq!(Balances::total_balance(&4), 40); - - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true, false], 0, 0, 20)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, true], 0, 0, 50)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_err!( - Elections::present_winner(Origin::signed(4), 2, 80, 0), - Error::::IncorrectTotal - ); - - assert_eq!(Balances::total_balance(&4), 38); - }); -} - -#[test] -fn election_runners_up_should_be_kept() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(4); - assert!(!Elections::presentation_active()); - - assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true], 0, 0, 60)); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![false, true], 0, 0, 20)); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); - assert_ok!(Elections::set_approvals(Origin::signed(3), vec![false, false, true], 0, 0, 30)); - assert_ok!(Elections::submit_candidacy(Origin::signed(4), 3)); - assert_ok!(Elections::set_approvals( - Origin::signed(4), - vec![false, false, false, true], - 0, - 0, - 40 - )); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 4)); - assert_ok!(Elections::set_approvals( - Origin::signed(5), - vec![false, false, false, false, true], - 0, - 0, - 50 - )); - - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert!(Elections::presentation_active()); - assert_ok!(Elections::present_winner(Origin::signed(4), 1, 60, 0)); - // leaderboard length is the empty seats plus the carry count (i.e. 5 + 2), where those - // to be carried are the lowest and stored in lowest indices - assert_eq!(Elections::leaderboard(), Some(vec![(0, 0), (0, 0), (0, 0), (60, 1)])); - assert_ok!(Elections::present_winner(Origin::signed(4), 3, 30, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 4, 40, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 0)); - assert_eq!(Elections::leaderboard(), Some(vec![(30, 3), (40, 4), (50, 5), (60, 1)])); - - assert_ok!(Elections::end_block(System::block_number())); - - assert!(!Elections::presentation_active()); - assert_eq!(Elections::members(), vec![(1, 11), (5, 11)]); - - assert!(!Elections::is_a_candidate(&1)); - assert!(!Elections::is_a_candidate(&5)); - assert!(!Elections::is_a_candidate(&2)); - assert!(Elections::is_a_candidate(&3)); - assert!(Elections::is_a_candidate(&4)); - assert_eq!(Elections::vote_index(), 1); - assert_eq!( - Elections::voter_info(2), - Some(VoterInfo { last_win: 0, last_active: 0, stake: 20, pot: 0 }) - ); - assert_eq!( - Elections::voter_info(3), - Some(VoterInfo { last_win: 0, last_active: 0, stake: 30, pot: 0 }) - ); - assert_eq!( - Elections::voter_info(4), - Some(VoterInfo { last_win: 0, last_active: 0, stake: 40, pot: 0 }) - ); - assert_eq!( - Elections::voter_info(5), - Some(VoterInfo { last_win: 1, last_active: 0, stake: 50, pot: 0 }) - ); - assert_eq!( - Elections::voter_info(6), - Some(VoterInfo { last_win: 1, last_active: 0, stake: 60, pot: 0 }) - ); - assert_eq!(Elections::candidate_reg_info(3), Some((0, 2))); - assert_eq!(Elections::candidate_reg_info(4), Some((0, 3))); - }); -} - -#[test] -fn election_second_tally_should_use_runners_up() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(4); - assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true], 0, 0, 60)); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![false, true], 0, 0, 20)); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); - assert_ok!(Elections::set_approvals(Origin::signed(3), vec![false, false, true], 0, 0, 30)); - assert_ok!(Elections::submit_candidacy(Origin::signed(4), 3)); - assert_ok!(Elections::set_approvals( - Origin::signed(4), - vec![false, false, false, true], - 0, - 0, - 40 - )); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 4)); - assert_ok!(Elections::set_approvals( - Origin::signed(5), - vec![false, false, false, false, true], - 0, - 0, - 50 - )); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_ok!(Elections::present_winner(Origin::signed(4), 1, 60, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 3, 30, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 4, 40, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(8); - assert_ok!(Elections::set_approvals( - Origin::signed(6), - vec![false, false, true, false], - 1, - 0, - 60 - )); - assert_ok!(Elections::set_desired_seats(Origin::root(), 3)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(10); - assert_ok!(Elections::present_winner( - Origin::signed(4), - 3, - 30 + Elections::get_offset(30, 1) + 60, - 1 - )); - assert_ok!(Elections::present_winner( - Origin::signed(4), - 4, - 40 + Elections::get_offset(40, 1), - 1 - )); - assert_ok!(Elections::end_block(System::block_number())); - - assert!(!Elections::presentation_active()); - assert_eq!(Elections::members(), vec![(1, 11), (5, 11), (3, 15)]); - - assert!(!Elections::is_a_candidate(&1)); - assert!(!Elections::is_a_candidate(&2)); - assert!(!Elections::is_a_candidate(&3)); - assert!(!Elections::is_a_candidate(&5)); - assert!(Elections::is_a_candidate(&4)); - assert_eq!(Elections::vote_index(), 2); - assert_eq!( - Elections::voter_info(2), - Some(VoterInfo { last_win: 0, last_active: 0, stake: 20, pot: 0 }) - ); - assert_eq!( - Elections::voter_info(3), - Some(VoterInfo { last_win: 2, last_active: 0, stake: 30, pot: 0 }) - ); - assert_eq!( - Elections::voter_info(4), - Some(VoterInfo { last_win: 0, last_active: 0, stake: 40, pot: 0 }) - ); - assert_eq!( - Elections::voter_info(5), - Some(VoterInfo { last_win: 1, last_active: 0, stake: 50, pot: 0 }) - ); - assert_eq!( - Elections::voter_info(6), - Some(VoterInfo { last_win: 2, last_active: 1, stake: 60, pot: 0 }) - ); - - assert_eq!(Elections::candidate_reg_info(4), Some((0, 3))); - }); -} - -#[test] -fn election_loser_candidates_bond_gets_slashed() { - ExtBuilder::default().desired_seats(1).build().execute_with(|| { - System::set_block_number(4); - assert!(!Elections::presentation_active()); - - assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); - assert_ok!(Elections::submit_candidacy(Origin::signed(4), 3)); - - assert_eq!(balances(&2), (17, 3)); - - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![true], 0, 0, 50)); - assert_ok!(Elections::set_approvals( - Origin::signed(1), - vec![false, true, true, true], - 0, - 0, - 10 - )); - - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert!(Elections::presentation_active()); - assert_eq!(Elections::present_winner(Origin::signed(4), 4, 10, 0), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(3), 3, 10, 0), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(2), 2, 10, 0), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(1), 1, 50, 0), Ok(())); - - // winner + carry - assert_eq!(Elections::leaderboard(), Some(vec![(10, 3), (10, 4), (50, 1)])); - assert_ok!(Elections::end_block(System::block_number())); - assert!(!Elections::presentation_active()); - assert_eq!(Elections::members(), vec![(1, 11)]); - - // account 2 is not a runner up or in leaderboard. - assert_eq!(balances(&2), (17, 0)); - }); -} - -#[test] -fn pot_accumulating_weight_and_decaying_should_work() { - ExtBuilder::default().balance_factor(10).build().execute_with(|| { - System::set_block_number(4); - assert!(!Elections::presentation_active()); - - assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); - assert_ok!(Elections::submit_candidacy(Origin::signed(1), 2)); - - assert_ok!(Elections::set_approvals( - Origin::signed(6), - vec![true, false, false], - 0, - 0, - 600 - )); - assert_ok!(Elections::set_approvals( - Origin::signed(5), - vec![false, true, false], - 0, - 0, - 500 - )); - assert_ok!(Elections::set_approvals( - Origin::signed(1), - vec![false, false, true], - 0, - 0, - 100 - )); - - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert!(Elections::presentation_active()); - - assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 0), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(5), 5, 500, 0), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(1), 1, 100, 0), Ok(())); - assert_eq!(Elections::leaderboard(), Some(vec![(0, 0), (100, 1), (500, 5), (600, 6)])); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![(6, 11), (5, 11)]); - assert_eq!( - Elections::voter_info(6).unwrap(), - VoterInfo { last_win: 1, last_active: 0, stake: 600, pot: 0 }, - ); - assert_eq!( - Elections::voter_info(5).unwrap(), - VoterInfo { last_win: 1, last_active: 0, stake: 500, pot: 0 }, - ); - assert_eq!( - Elections::voter_info(1).unwrap(), - VoterInfo { last_win: 0, last_active: 0, stake: 100, pot: 0 }, - ); - - System::set_block_number(12); - // retract needed to unlock approval funds => submit candidacy again. - assert_ok!(Elections::retract_voter(Origin::signed(6), 0)); - assert_ok!(Elections::retract_voter(Origin::signed(5), 1)); - assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); - assert_ok!(Elections::set_approvals( - Origin::signed(6), - vec![true, false, false], - 1, - 0, - 600 - )); - assert_ok!(Elections::set_approvals( - Origin::signed(5), - vec![false, true, false], - 1, - 1, - 500 - )); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(14); - assert!(Elections::presentation_active()); - assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 1), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(5), 5, 500, 1), Ok(())); - assert_eq!( - Elections::present_winner(Origin::signed(1), 1, 100 + Elections::get_offset(100, 1), 1), - Ok(()) - ); - assert_eq!(Elections::leaderboard(), Some(vec![(0, 0), (100 + 96, 1), (500, 5), (600, 6)])); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![(6, 19), (5, 19)]); - assert_eq!( - Elections::voter_info(6).unwrap(), - VoterInfo { last_win: 2, last_active: 1, stake: 600, pot: 0 } - ); - assert_eq!( - Elections::voter_info(5).unwrap(), - VoterInfo { last_win: 2, last_active: 1, stake: 500, pot: 0 } - ); - assert_eq!( - Elections::voter_info(1).unwrap(), - VoterInfo { last_win: 0, last_active: 0, stake: 100, pot: 0 } - ); - - System::set_block_number(20); - assert_ok!(Elections::retract_voter(Origin::signed(6), 0)); - assert_ok!(Elections::retract_voter(Origin::signed(5), 1)); - assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); - assert_ok!(Elections::set_approvals( - Origin::signed(6), - vec![true, false, false], - 2, - 0, - 600 - )); - assert_ok!(Elections::set_approvals( - Origin::signed(5), - vec![false, true, false], - 2, - 1, - 500 - )); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(22); - assert!(Elections::presentation_active()); - assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 2), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(5), 5, 500, 2), Ok(())); - assert_eq!( - Elections::present_winner(Origin::signed(1), 1, 100 + Elections::get_offset(100, 2), 2), - Ok(()) - ); - assert_eq!( - Elections::leaderboard(), - Some(vec![(0, 0), (100 + 96 + 93, 1), (500, 5), (600, 6)]) - ); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![(6, 27), (5, 27)]); - assert_eq!( - Elections::voter_info(6).unwrap(), - VoterInfo { last_win: 3, last_active: 2, stake: 600, pot: 0 } - ); - assert_eq!( - Elections::voter_info(5).unwrap(), - VoterInfo { last_win: 3, last_active: 2, stake: 500, pot: 0 } - ); - assert_eq!( - Elections::voter_info(1).unwrap(), - VoterInfo { last_win: 0, last_active: 0, stake: 100, pot: 0 } - ); - - System::set_block_number(28); - assert_ok!(Elections::retract_voter(Origin::signed(6), 0)); - assert_ok!(Elections::retract_voter(Origin::signed(5), 1)); - assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); - assert_ok!(Elections::set_approvals( - Origin::signed(6), - vec![true, false, false], - 3, - 0, - 600 - )); - assert_ok!(Elections::set_approvals( - Origin::signed(5), - vec![false, true, false], - 3, - 1, - 500 - )); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(30); - assert!(Elections::presentation_active()); - assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 3), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(5), 5, 500, 3), Ok(())); - assert_eq!( - Elections::present_winner(Origin::signed(1), 1, 100 + Elections::get_offset(100, 3), 3), - Ok(()) - ); - assert_eq!( - Elections::leaderboard(), - Some(vec![(0, 0), (100 + 96 + 93 + 90, 1), (500, 5), (600, 6)]) - ); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![(6, 35), (5, 35)]); - assert_eq!( - Elections::voter_info(6).unwrap(), - VoterInfo { last_win: 4, last_active: 3, stake: 600, pot: 0 } - ); - assert_eq!( - Elections::voter_info(5).unwrap(), - VoterInfo { last_win: 4, last_active: 3, stake: 500, pot: 0 } - ); - assert_eq!( - Elections::voter_info(1).unwrap(), - VoterInfo { last_win: 0, last_active: 0, stake: 100, pot: 0 } - ); - }) -} - -#[test] -fn pot_winning_resets_accumulated_pot() { - ExtBuilder::default().balance_factor(10).build().execute_with(|| { - System::set_block_number(4); - assert!(!Elections::presentation_active()); - - assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(4), 1)); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 3)); - - assert_ok!(Elections::set_approvals( - Origin::signed(6), - vec![true, false, false, false], - 0, - 0, - 600 - )); - assert_ok!(Elections::set_approvals( - Origin::signed(4), - vec![false, true, false, false], - 0, - 1, - 400 - )); - assert_ok!(Elections::set_approvals( - Origin::signed(3), - vec![false, false, true, true], - 0, - 2, - 300 - )); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert!(Elections::presentation_active()); - assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 0), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(4), 4, 400, 0), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(3), 3, 300, 0), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(2), 2, 300, 0), Ok(())); - assert_eq!(Elections::leaderboard(), Some(vec![(300, 2), (300, 3), (400, 4), (600, 6)])); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![(6, 11), (4, 11)]); - - System::set_block_number(12); - assert_ok!(Elections::retract_voter(Origin::signed(6), 0)); - assert_ok!(Elections::retract_voter(Origin::signed(4), 1)); - assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(4), 1)); - assert_ok!(Elections::set_approvals( - Origin::signed(6), - vec![true, false, false, false], - 1, - 0, - 600 - )); - assert_ok!(Elections::set_approvals( - Origin::signed(4), - vec![false, true, false, false], - 1, - 1, - 400 - )); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(14); - assert!(Elections::presentation_active()); - assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 1), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(4), 4, 400, 1), Ok(())); - assert_eq!( - Elections::present_winner(Origin::signed(3), 3, 300 + Elections::get_offset(300, 1), 1), - Ok(()) - ); - assert_eq!( - Elections::present_winner(Origin::signed(2), 2, 300 + Elections::get_offset(300, 1), 1), - Ok(()) - ); - assert_eq!(Elections::leaderboard(), Some(vec![(400, 4), (588, 2), (588, 3), (600, 6)])); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![(6, 19), (3, 19)]); - - System::set_block_number(20); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(22); - // 2 will not get re-elected with 300 + 288, instead just 300. - // because one of 3's candidates (3) won in previous round - // 4 on the other hand will get extra weight since it was unlucky. - assert_eq!(Elections::present_winner(Origin::signed(3), 2, 300, 2), Ok(())); - assert_eq!( - Elections::present_winner(Origin::signed(4), 4, 400 + Elections::get_offset(400, 1), 2), - Ok(()) - ); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![(4, 27), (2, 27)]); - }) -} - -#[test] -fn pot_resubmitting_approvals_stores_pot() { - ExtBuilder::default() - .voting_bond(0) - .voting_fee(0) - .balance_factor(10) - .build() - .execute_with(|| { - System::set_block_number(4); - assert!(!Elections::presentation_active()); - - assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); - assert_ok!(Elections::submit_candidacy(Origin::signed(1), 2)); - - assert_ok!(Elections::set_approvals( - Origin::signed(6), - vec![true, false, false], - 0, - 0, - 600 - ),); - assert_ok!(Elections::set_approvals( - Origin::signed(5), - vec![false, true, false], - 0, - 1, - 500 - ),); - assert_ok!(Elections::set_approvals( - Origin::signed(1), - vec![false, false, true], - 0, - 2, - 100 - ),); - - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert!(Elections::presentation_active()); - - assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 0), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(5), 5, 500, 0), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(1), 1, 100, 0), Ok(())); - assert_eq!(Elections::leaderboard(), Some(vec![(0, 0), (100, 1), (500, 5), (600, 6)])); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![(6, 11), (5, 11)]); - - System::set_block_number(12); - assert_ok!(Elections::retract_voter(Origin::signed(6), 0)); - assert_ok!(Elections::retract_voter(Origin::signed(5), 1)); - assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); - assert_ok!(Elections::set_approvals( - Origin::signed(6), - vec![true, false, false], - 1, - 0, - 600 - ),); - assert_ok!(Elections::set_approvals( - Origin::signed(5), - vec![false, true, false], - 1, - 1, - 500 - ),); - // give 1 some new high balance - let _ = Balances::make_free_balance_be(&1, 997); - assert_ok!(Elections::set_approvals( - Origin::signed(1), - vec![false, false, true], - 1, - 2, - 1000 - ),); - assert_eq!( - Elections::voter_info(1).unwrap(), - VoterInfo { - stake: 1000, // 997 + 3 which is candidacy bond. - pot: Elections::get_offset(100, 1), - last_active: 1, - last_win: 1, - } - ); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![(6, 11), (5, 11)]); - - System::set_block_number(14); - assert!(Elections::presentation_active()); - assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 1), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(5), 5, 500, 1), Ok(())); - assert_eq!( - Elections::present_winner(Origin::signed(1), 1, 1000 + 96 /* pot */, 1), - Ok(()), - ); - assert_eq!(Elections::leaderboard(), Some(vec![(0, 0), (500, 5), (600, 6), (1096, 1)])); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![(1, 19), (6, 19)]); - }) -} - -#[test] -fn pot_get_offset_should_work() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!(Elections::get_offset(100, 0), 0); - assert_eq!(Elections::get_offset(100, 1), 96); - assert_eq!(Elections::get_offset(100, 2), 96 + 93); - assert_eq!(Elections::get_offset(100, 3), 96 + 93 + 90); - assert_eq!(Elections::get_offset(100, 4), 96 + 93 + 90 + 87); - // limit - assert_eq!(Elections::get_offset(100, 1000), 100 * 24); - - assert_eq!(Elections::get_offset(50_000_000_000, 0), 0); - assert_eq!(Elections::get_offset(50_000_000_000, 1), 48_000_000_000); - assert_eq!(Elections::get_offset(50_000_000_000, 2), 48_000_000_000 + 46_080_000_000); - assert_eq!( - Elections::get_offset(50_000_000_000, 3), - 48_000_000_000 + 46_080_000_000 + 44_236_800_000 - ); - assert_eq!( - Elections::get_offset(50_000_000_000, 4), - 48_000_000_000 + 46_080_000_000 + 44_236_800_000 + 42_467_328_000 - ); - // limit - assert_eq!(Elections::get_offset(50_000_000_000, 1000), 50_000_000_000 * 24); - }) -} - -#[test] -fn pot_get_offset_with_zero_decay() { - ExtBuilder::default().decay_ratio(0).build().execute_with(|| { - assert_eq!(Elections::get_offset(100, 0), 0); - assert_eq!(Elections::get_offset(100, 1), 0); - assert_eq!(Elections::get_offset(100, 2), 0); - assert_eq!(Elections::get_offset(100, 3), 0); - // limit - assert_eq!(Elections::get_offset(100, 1000), 0); - }) -} diff --git a/frame/examples/basic/src/lib.rs b/frame/examples/basic/src/lib.rs index 25ff76f4d151..2b443ff8e8dd 100644 --- a/frame/examples/basic/src/lib.rs +++ b/frame/examples/basic/src/lib.rs @@ -731,6 +731,16 @@ where Ok(()) } + fn pre_dispatch( + self, + who: &Self::AccountId, + call: &Self::Call, + info: &DispatchInfoOf, + len: usize, + ) -> Result { + Ok(self.validate(who, call, info, len).map(|_| ())?) + } + fn validate( &self, _who: &Self::AccountId, diff --git a/frame/examples/offchain-worker/src/lib.rs b/frame/examples/offchain-worker/src/lib.rs index 9812d35ffa07..ec728e791295 100644 --- a/frame/examples/offchain-worker/src/lib.rs +++ b/frame/examples/offchain-worker/src/lib.rs @@ -233,7 +233,7 @@ pub mod pallet { // Retrieve sender of the transaction. let who = ensure_signed(origin)?; // Add the price to the on-chain list. - Self::add_price(who, price); + Self::add_price(Some(who), price); Ok(().into()) } @@ -262,7 +262,7 @@ pub mod pallet { // This ensures that the function can only be called via unsigned transaction. ensure_none(origin)?; // Add the price to the on-chain list, but mark it as coming from an empty address. - Self::add_price(Default::default(), price); + Self::add_price(None, price); // now increment the block number at which we expect next unsigned transaction. let current_block = >::block_number(); >::put(current_block + T::UnsignedInterval::get()); @@ -278,7 +278,7 @@ pub mod pallet { // This ensures that the function can only be called via unsigned transaction. ensure_none(origin)?; // Add the price to the on-chain list, but mark it as coming from an empty address. - Self::add_price(Default::default(), price_payload.price); + Self::add_price(None, price_payload.price); // now increment the block number at which we expect next unsigned transaction. let current_block = >::block_number(); >::put(current_block + T::UnsignedInterval::get()); @@ -291,7 +291,7 @@ pub mod pallet { #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { /// Event generated when new price is accepted to contribute to the average. - NewPrice { price: u32, who: T::AccountId }, + NewPrice { price: u32, maybe_who: Option }, } #[pallet::validate_unsigned] @@ -641,7 +641,7 @@ impl Pallet { } /// Add new price to the list. - fn add_price(who: T::AccountId, price: u32) { + fn add_price(maybe_who: Option, price: u32) { log::info!("Adding to the average: {}", price); >::mutate(|prices| { const MAX_LEN: usize = 64; @@ -657,7 +657,7 @@ impl Pallet { .expect("The average is not empty, because it was just mutated; qed"); log::info!("Current average price is: {}", average); // here we are raising the NewPrice event - Self::deposit_event(Event::NewPrice { price, who }); + Self::deposit_event(Event::NewPrice { price, maybe_who }); } /// Calculate current average price. diff --git a/frame/examples/offchain-worker/src/tests.rs b/frame/examples/offchain-worker/src/tests.rs index 9fb965784f18..d83c3c6df9ee 100644 --- a/frame/examples/offchain-worker/src/tests.rs +++ b/frame/examples/offchain-worker/src/tests.rs @@ -125,15 +125,19 @@ impl Config for Test { type UnsignedPriority = UnsignedPriority; } +fn test_pub() -> sp_core::sr25519::Public { + sp_core::sr25519::Public::from_raw([1u8; 32]) +} + #[test] fn it_aggregates_the_price() { sp_io::TestExternalities::default().execute_with(|| { assert_eq!(Example::average_price(), None); - assert_ok!(Example::submit_price(Origin::signed(Default::default()), 27)); + assert_ok!(Example::submit_price(Origin::signed(test_pub()), 27)); assert_eq!(Example::average_price(), Some(27)); - assert_ok!(Example::submit_price(Origin::signed(Default::default()), 43)); + assert_ok!(Example::submit_price(Origin::signed(test_pub()), 43)); assert_eq!(Example::average_price(), Some(35)); }); } diff --git a/frame/examples/parallel/src/lib.rs b/frame/examples/parallel/src/lib.rs index 51e022bed08b..55714abb4827 100644 --- a/frame/examples/parallel/src/lib.rs +++ b/frame/examples/parallel/src/lib.rs @@ -105,13 +105,13 @@ pub struct EnlistedParticipant { impl EnlistedParticipant { fn verify(&self, event_id: &[u8]) -> bool { - use sp_core::Public; + use sp_core::ByteArray; use sp_runtime::traits::Verify; match sp_core::sr25519::Signature::try_from(&self.signature[..]) { - Ok(signature) => { - let public = sp_core::sr25519::Public::from_slice(self.account.as_ref()); - signature.verify(event_id, &public) + Ok(signature) => match sp_core::sr25519::Public::from_slice(self.account.as_ref()) { + Err(()) => false, + Ok(signer) => signature.verify(event_id, &signer), }, _ => false, } diff --git a/frame/examples/parallel/src/tests.rs b/frame/examples/parallel/src/tests.rs index 5de9af878723..1a841ca68184 100644 --- a/frame/examples/parallel/src/tests.rs +++ b/frame/examples/parallel/src/tests.rs @@ -81,6 +81,14 @@ impl Config for Test { type Call = Call; } +fn test_pub(n: u8) -> sp_core::sr25519::Public { + sp_core::sr25519::Public::from_raw([n; 32]) +} + +fn test_origin(n: u8) -> Origin { + Origin::signed(test_pub(n)) +} + #[test] fn it_can_enlist() { use sp_core::Pair; @@ -91,8 +99,7 @@ fn it_can_enlist() { let event_name = b"test"; - Example::run_event(Origin::signed(Default::default()), event_name.to_vec()) - .expect("Failed to enlist"); + Example::run_event(test_origin(1), event_name.to_vec()).expect("Failed to enlist"); let participants = vec![ EnlistedParticipant { @@ -105,7 +112,7 @@ fn it_can_enlist() { }, ]; - Example::enlist_participants(Origin::signed(Default::default()), participants) + Example::enlist_participants(Origin::signed(test_pub(1)), participants) .expect("Failed to enlist"); assert_eq!(Example::participants().len(), 2); @@ -123,8 +130,7 @@ fn one_wrong_will_not_enlist_anyone() { let event_name = b"test"; - Example::run_event(Origin::signed(Default::default()), event_name.to_vec()) - .expect("Failed to enlist"); + Example::run_event(test_origin(1), event_name.to_vec()).expect("Failed to enlist"); let participants = vec![ EnlistedParticipant { @@ -142,8 +148,7 @@ fn one_wrong_will_not_enlist_anyone() { }, ]; - Example::enlist_participants(Origin::signed(Default::default()), participants) - .expect("Failed to enlist"); + Example::enlist_participants(test_origin(1), participants).expect("Failed to enlist"); assert_eq!(Example::participants().len(), 0); }); diff --git a/frame/grandpa/src/equivocation.rs b/frame/grandpa/src/equivocation.rs index 8a23ce6e1ef1..77e38cb63b7d 100644 --- a/frame/grandpa/src/equivocation.rs +++ b/frame/grandpa/src/equivocation.rs @@ -185,7 +185,7 @@ where } fn block_author() -> Option { - Some(>::author()) + >::author() } } diff --git a/frame/im-online/src/lib.rs b/frame/im-online/src/lib.rs index dbae5ed96d58..3499078149f2 100644 --- a/frame/im-online/src/lib.rs +++ b/frame/im-online/src/lib.rs @@ -324,7 +324,6 @@ pub mod pallet { type AuthorityId: Member + Parameter + RuntimeAppPublic - + Default + Ord + MaybeSerializeDeserialize + MaxEncodedLen; diff --git a/frame/im-online/src/mock.rs b/frame/im-online/src/mock.rs index 1d985b9007ea..3168f60ce022 100644 --- a/frame/im-online/src/mock.rs +++ b/frame/im-online/src/mock.rs @@ -106,7 +106,15 @@ impl ReportOffence for OffenceHandler { pub fn new_test_ext() -> sp_io::TestExternalities { let t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - t.into() + let mut result: sp_io::TestExternalities = t.into(); + // Set the default keys, otherwise session will discard the validator. + result.execute_with(|| { + for i in 1..=6 { + System::inc_providers(&i); + assert_eq!(Session::set_keys(Origin::signed(i), (i - 1).into(), vec![]), Ok(())); + } + }); + result } parameter_types! { diff --git a/frame/multisig/src/lib.rs b/frame/multisig/src/lib.rs index 757a99b42dae..c02efdc0d371 100644 --- a/frame/multisig/src/lib.rs +++ b/frame/multisig/src/lib.rs @@ -64,7 +64,7 @@ use frame_system::{self as system, RawOrigin}; use scale_info::TypeInfo; use sp_io::hashing::blake2_256; use sp_runtime::{ - traits::{Dispatchable, Zero}, + traits::{Dispatchable, TrailingZeroInput, Zero}, DispatchError, }; use sp_std::prelude::*; @@ -508,7 +508,8 @@ impl Pallet { /// NOTE: `who` must be sorted. If it is not, then you'll get the wrong answer. pub fn multi_account_id(who: &[T::AccountId], threshold: u16) -> T::AccountId { let entropy = (b"modlpy/utilisuba", who, threshold).using_encoded(blake2_256); - T::AccountId::decode(&mut &entropy[..]).unwrap_or_default() + Decode::decode(&mut TrailingZeroInput::new(entropy.as_ref())) + .expect("infinite length input; no invalid inputs for type; qed") } fn operate( diff --git a/frame/proxy/src/lib.rs b/frame/proxy/src/lib.rs index 695fa077f98d..fefc66554f45 100644 --- a/frame/proxy/src/lib.rs +++ b/frame/proxy/src/lib.rs @@ -45,7 +45,7 @@ use frame_system::{self as system}; use scale_info::TypeInfo; use sp_io::hashing::blake2_256; use sp_runtime::{ - traits::{Dispatchable, Hash, Saturating, Zero}, + traits::{Dispatchable, Hash, Saturating, TrailingZeroInput, Zero}, DispatchResult, }; use sp_std::{convert::TryInto, prelude::*}; @@ -653,7 +653,8 @@ impl Pallet { }); let entropy = (b"modlpy/proxy____", who, height, ext_index, proxy_type, index) .using_encoded(blake2_256); - T::AccountId::decode(&mut &entropy[..]).unwrap_or_default() + Decode::decode(&mut TrailingZeroInput::new(entropy.as_ref())) + .expect("infinite length input; no invalid inputs for type; qed") } /// Register a proxy account for the delegator that is able to make calls on its behalf. diff --git a/frame/session/benchmarking/src/lib.rs b/frame/session/benchmarking/src/lib.rs index 6d9d81f38517..4e0e51b76fe1 100644 --- a/frame/session/benchmarking/src/lib.rs +++ b/frame/session/benchmarking/src/lib.rs @@ -22,7 +22,7 @@ mod mock; -use sp_runtime::traits::{One, StaticLookup}; +use sp_runtime::traits::{One, StaticLookup, TrailingZeroInput}; use sp_std::{prelude::*, vec}; use frame_benchmarking::benchmarks; @@ -61,7 +61,8 @@ benchmarks! { RewardDestination::Staked, )?; let v_controller = pallet_staking::Pallet::::bonded(&v_stash).ok_or("not stash")?; - let keys = T::Keys::default(); + + let keys = T::Keys::decode(&mut TrailingZeroInput::zeroes()).unwrap(); let proof: Vec = vec![0,1,2,3]; // Whitelist controller account from further DB operations. let v_controller_key = frame_system::Account::::hashed_key_for(&v_controller); @@ -77,7 +78,7 @@ benchmarks! { RewardDestination::Staked )?; let v_controller = pallet_staking::Pallet::::bonded(&v_stash).ok_or("not stash")?; - let keys = T::Keys::default(); + let keys = T::Keys::decode(&mut TrailingZeroInput::zeroes()).unwrap(); let proof: Vec = vec![0,1,2,3]; Session::::set_keys(RawOrigin::Signed(v_controller.clone()).into(), keys, proof)?; // Whitelist controller account from further DB operations. diff --git a/frame/session/src/lib.rs b/frame/session/src/lib.rs index f56d282c0f11..0f8049455084 100644 --- a/frame/session/src/lib.rs +++ b/frame/session/src/lib.rs @@ -312,8 +312,10 @@ impl SessionHandler for Tuple { for_tuples!( #( let our_keys: Box> = Box::new(validators.iter() - .map(|k| (&k.0, k.1.get::(::ID) - .unwrap_or_default()))); + .filter_map(|k| + k.1.get::(::ID).map(|k1| (&k.0, k1)) + ) + ); Tuple::on_genesis_session(our_keys); )* @@ -328,11 +330,13 @@ impl SessionHandler for Tuple { for_tuples!( #( let our_keys: Box> = Box::new(validators.iter() - .map(|k| (&k.0, k.1.get::(::ID) - .unwrap_or_default()))); + .filter_map(|k| + k.1.get::(::ID).map(|k1| (&k.0, k1)) + )); let queued_keys: Box> = Box::new(queued_validators.iter() - .map(|k| (&k.0, k.1.get::(::ID) - .unwrap_or_default()))); + .filter_map(|k| + k.1.get::(::ID).map(|k1| (&k.0, k1)) + )); Tuple::on_new_session(changed, our_keys, queued_keys); )* ) @@ -403,7 +407,7 @@ pub mod pallet { type SessionHandler: SessionHandler; /// The keys. - type Keys: OpaqueKeys + Member + Parameter + Default + MaybeSerializeDeserialize; + type Keys: OpaqueKeys + Member + Parameter + MaybeSerializeDeserialize; /// Weight information for extrinsics in this pallet. type WeightInfo: WeightInfo; @@ -476,13 +480,18 @@ pub mod pallet { let queued_keys: Vec<_> = initial_validators_1 .iter() .cloned() - .map(|v| (v.clone(), >::load_keys(&v).unwrap_or_default())) + .filter_map(|v| { + Some(( + v.clone(), + Pallet::::load_keys(&v).expect("Validator in session 1 missing keys!"), + )) + }) .collect(); // Tell everyone about the genesis session keys T::SessionHandler::on_genesis_session::(&queued_keys); - >::put(initial_validators_0); + Validators::::put(initial_validators_0); >::put(queued_keys); T::SessionManager::start_session(0); @@ -641,7 +650,7 @@ impl Pallet { let session_keys = >::get(); let validators = session_keys.iter().map(|(validator, _)| validator.clone()).collect::>(); - >::put(&validators); + Validators::::put(&validators); if changed { // reset disabled validators @@ -663,7 +672,7 @@ impl Pallet { // same as before, as underlying economic conditions may have changed. (validators, true) } else { - (>::get(), false) + (Validators::::get(), false) }; // Queue next session keys. @@ -689,10 +698,10 @@ impl Pallet { }; let queued_amalgamated = next_validators .into_iter() - .map(|a| { - let k = Self::load_keys(&a).unwrap_or_default(); + .filter_map(|a| { + let k = Self::load_keys(&a)?; check_next_changed(&k); - (a, k) + Some((a, k)) }) .collect::>(); diff --git a/frame/staking/src/benchmarking.rs b/frame/staking/src/benchmarking.rs index 5b242e1f223a..f96b7fd2f37b 100644 --- a/frame/staking/src/benchmarking.rs +++ b/frame/staking/src/benchmarking.rs @@ -21,6 +21,7 @@ use super::*; use crate::Pallet as Staking; use testing_utils::*; +use codec::Decode; use frame_election_provider_support::SortedListProvider; use frame_support::{ dispatch::UnfilteredDispatchable, @@ -28,7 +29,7 @@ use frame_support::{ traits::{Currency, CurrencyToVote, Get, Imbalance}, }; use sp_runtime::{ - traits::{Bounded, One, StaticLookup, Zero}, + traits::{Bounded, One, StaticLookup, TrailingZeroInput, Zero}, Perbill, Percent, }; use sp_staking::SessionIndex; @@ -535,8 +536,9 @@ benchmarks! { let s in 1 .. MAX_SLASHES; let mut unapplied_slashes = Vec::new(); let era = EraIndex::one(); + let dummy = || T::AccountId::decode(&mut TrailingZeroInput::zeroes()).unwrap(); for _ in 0 .. MAX_SLASHES { - unapplied_slashes.push(UnappliedSlash::>::default()); + unapplied_slashes.push(UnappliedSlash::>::default_from(dummy())); } UnappliedSlashes::::insert(era, &unapplied_slashes); @@ -667,10 +669,11 @@ benchmarks! { let e in 1 .. 100; HistoryDepth::::put(e); CurrentEra::::put(e); + let dummy = || -> T::AccountId { codec::Decode::decode(&mut TrailingZeroInput::zeroes()).unwrap() }; for i in 0 .. e { - >::insert(i, T::AccountId::default(), Exposure::>::default()); - >::insert(i, T::AccountId::default(), Exposure::>::default()); - >::insert(i, T::AccountId::default(), ValidatorPrefs::default()); + >::insert(i, dummy(), Exposure::>::default()); + >::insert(i, dummy(), Exposure::>::default()); + >::insert(i, dummy(), ValidatorPrefs::default()); >::insert(i, BalanceOf::::one()); >::insert(i, EraRewardPoints::::default()); >::insert(i, BalanceOf::::one()); @@ -695,7 +698,14 @@ benchmarks! { let stash = scenario.origin_stash1.clone(); add_slashing_spans::(&stash, s); - Ledger::::insert(&controller, StakingLedger { active: T::Currency::minimum_balance() - One::one(), total: T::Currency::minimum_balance() - One::one(), ..Default::default() }); + let l = StakingLedger { + stash: stash.clone(), + active: T::Currency::minimum_balance() - One::one(), + total: T::Currency::minimum_balance() - One::one(), + unlocking: vec![], + claimed_rewards: vec![], + }; + Ledger::::insert(&controller, l); assert!(Bonded::::contains_key(&stash)); assert!(T::SortedListProvider::contains(&stash)); diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index f2e5f0f78389..7bc3ac8aa707 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -364,7 +364,7 @@ pub struct ActiveEraInfo { /// Reward points of an era. Used to split era total payout between validators. /// /// This points will be used to reward validators and their respective nominators. -#[derive(PartialEq, Encode, Decode, Default, RuntimeDebug, TypeInfo)] +#[derive(PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] pub struct EraRewardPoints { /// Total number of points. Equals the sum of reward points for each validator. total: RewardPoint, @@ -372,9 +372,15 @@ pub struct EraRewardPoints { individual: BTreeMap, } +impl Default for EraRewardPoints { + fn default() -> Self { + EraRewardPoints { total: Default::default(), individual: BTreeMap::new() } + } +} + /// Indicates the initial status of the staker. #[derive(RuntimeDebug, TypeInfo)] -#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize, Clone))] pub enum StakerStatus { /// Chilling. Idle, @@ -436,7 +442,6 @@ pub struct UnlockChunk { } /// The ledger of a (bonded) stash. -#[cfg_attr(feature = "runtime-benchmarks", derive(Default))] #[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo)] pub struct StakingLedger { /// The stash account whose balance is actually locked and at stake. @@ -457,9 +462,20 @@ pub struct StakingLedger { pub claimed_rewards: Vec, } -impl +impl StakingLedger { + /// Initializes the default object using the given `validator`. + pub fn default_from(stash: AccountId) -> Self { + Self { + stash, + total: Zero::zero(), + active: Zero::zero(), + unlocking: vec![], + claimed_rewards: vec![], + } + } + /// Remove entries from `unlocking` that are sufficiently old and reduce the /// total by the sum of their balances. fn consolidate_unlocked(self, current_era: EraIndex) -> Self { @@ -593,9 +609,7 @@ pub struct IndividualExposure { } /// A snapshot of the stake backing a single validator in the system. -#[derive( - PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, Default, RuntimeDebug, TypeInfo, -)] +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, RuntimeDebug, TypeInfo)] pub struct Exposure { /// The total balance backing this validator. #[codec(compact)] @@ -607,9 +621,15 @@ pub struct Exposure { pub others: Vec>, } +impl Default for Exposure { + fn default() -> Self { + Self { total: Default::default(), own: Default::default(), others: vec![] } + } +} + /// A pending slash record. The value of the slash has been computed but not applied yet, /// rather deferred for several eras. -#[derive(Encode, Decode, Default, RuntimeDebug, TypeInfo)] +#[derive(Encode, Decode, RuntimeDebug, TypeInfo)] pub struct UnappliedSlash { /// The stash ID of the offending validator. validator: AccountId, @@ -623,6 +643,19 @@ pub struct UnappliedSlash { payout: Balance, } +impl UnappliedSlash { + /// Initializes the default object using the given `validator`. + pub fn default_from(validator: AccountId) -> Self { + Self { + validator, + own: Zero::zero(), + others: vec![], + reporters: vec![], + payout: Zero::zero(), + } + } +} + /// Means for interacting with a specialized version of the `session` trait. /// /// This is needed because `Staking` sets the `ValidatorIdOf` of the `pallet_session::Config` diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index 89ab86259b95..f6e2ce0e4bc1 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -480,7 +480,7 @@ impl ExtBuilder { } let _ = pallet_staking::GenesisConfig:: { - stakers, + stakers: stakers.clone(), validator_count: self.validator_count, minimum_validator_count: self.minimum_validator_count, invulnerables: self.invulnerables, @@ -493,12 +493,15 @@ impl ExtBuilder { let _ = pallet_session::GenesisConfig:: { keys: if self.has_stakers { - // genesis election will overwrite this, no worries. - Default::default() + // set the keys for the first session. + stakers + .into_iter() + .map(|(id, ..)| (id, id, SessionKeys { other: id.into() })) + .collect() } else { // set some dummy validators in genesis. (0..self.validator_count as u64) - .map(|x| (x, x, SessionKeys { other: UintAuthorityId(x as u64) })) + .map(|id| (id, id, SessionKeys { other: id.into() })) .collect() }, } @@ -644,6 +647,7 @@ pub(crate) fn bond(stash: AccountId, ctrl: AccountId, val: Balance) { pub(crate) fn bond_validator(stash: AccountId, ctrl: AccountId, val: Balance) { bond(stash, ctrl, val); assert_ok!(Staking::validate(Origin::signed(ctrl), ValidatorPrefs::default())); + assert_ok!(Session::set_keys(Origin::signed(ctrl), SessionKeys { other: ctrl.into() }, vec![])); } pub(crate) fn bond_nominator( diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index b3158c4ef6b3..6c11e942106a 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -1089,8 +1089,13 @@ where fn note_author(author: T::AccountId) { Self::reward_by_ids(vec![(author, 20)]) } - fn note_uncle(author: T::AccountId, _age: T::BlockNumber) { - Self::reward_by_ids(vec![(>::author(), 2), (author, 1)]) + fn note_uncle(uncle_author: T::AccountId, _age: T::BlockNumber) { + // defensive-only: block author must exist. + if let Some(block_author) = >::author() { + Self::reward_by_ids(vec![(block_author, 2), (uncle_author, 1)]) + } else { + crate::log!(warn, "block author not set, this should never happen"); + } } } @@ -1238,8 +1243,13 @@ impl VoteWeightProvider for Pallet { // this will clearly results in an inconsistent state, but it should not matter for a // benchmark. let active: BalanceOf = weight.try_into().map_err(|_| ()).unwrap(); - let mut ledger = Self::ledger(who).unwrap_or_default(); - ledger.active = active; + let ledger = match Self::ledger(who) { + None => StakingLedger::default_from(who.clone()), + Some(mut l) => { + l.active = active; + l + }, + }; >::insert(who, ledger); >::insert(who, who); diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index ec8be43f0284..aa806d4a15e2 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -217,16 +217,17 @@ fn rewards_should_work() { Payee::::insert(21, RewardDestination::Controller); Payee::::insert(101, RewardDestination::Controller); - >::reward_by_ids(vec![(11, 50)]); - >::reward_by_ids(vec![(11, 50)]); + Pallet::::reward_by_ids(vec![(11, 50)]); + Pallet::::reward_by_ids(vec![(11, 50)]); // This is the second validator of the current elected set. - >::reward_by_ids(vec![(21, 50)]); + Pallet::::reward_by_ids(vec![(21, 50)]); // Compute total payout now for whole duration of the session. let total_payout_0 = current_total_payout_for_duration(reward_time_per_era()); let maximum_payout = maximum_payout_for_duration(reward_time_per_era()); start_session(1); + assert_eq_uvec!(Session::validators(), vec![11, 21]); assert_eq!(Balances::total_balance(&10), init_balance_10); assert_eq!(Balances::total_balance(&11), init_balance_11); @@ -234,7 +235,6 @@ fn rewards_should_work() { assert_eq!(Balances::total_balance(&21), init_balance_21); assert_eq!(Balances::total_balance(&100), init_balance_100); assert_eq!(Balances::total_balance(&101), init_balance_101); - assert_eq_uvec!(Session::validators(), vec![11, 21]); assert_eq!( Staking::eras_reward_points(active_era()), EraRewardPoints { @@ -283,7 +283,7 @@ fn rewards_should_work() { assert_eq_error_rate!(Balances::total_balance(&101), init_balance_101, 2); assert_eq_uvec!(Session::validators(), vec![11, 21]); - >::reward_by_ids(vec![(11, 1)]); + Pallet::::reward_by_ids(vec![(11, 1)]); // Compute total payout now for whole duration as other parameter won't change let total_payout_1 = current_total_payout_for_duration(reward_time_per_era()); @@ -338,6 +338,7 @@ fn staking_should_work() { // add a new candidate for being a validator. account 3 controlled by 4. assert_ok!(Staking::bond(Origin::signed(3), 4, 1500, RewardDestination::Controller)); assert_ok!(Staking::validate(Origin::signed(4), ValidatorPrefs::default())); + assert_ok!(Session::set_keys(Origin::signed(4), SessionKeys { other: 4.into() }, vec![])); // No effects will be seen so far. assert_eq_uvec!(validator_controllers(), vec![20, 10]); @@ -519,8 +520,8 @@ fn nominating_and_rewards_should_work() { // the total reward for era 0 let total_payout_0 = current_total_payout_for_duration(reward_time_per_era()); - >::reward_by_ids(vec![(41, 1)]); - >::reward_by_ids(vec![(21, 1)]); + Pallet::::reward_by_ids(vec![(41, 1)]); + Pallet::::reward_by_ids(vec![(21, 1)]); mock::start_active_era(1); @@ -561,8 +562,8 @@ fn nominating_and_rewards_should_work() { // the total reward for era 1 let total_payout_1 = current_total_payout_for_duration(reward_time_per_era()); - >::reward_by_ids(vec![(21, 2)]); - >::reward_by_ids(vec![(11, 1)]); + Pallet::::reward_by_ids(vec![(21, 2)]); + Pallet::::reward_by_ids(vec![(11, 1)]); mock::start_active_era(2); @@ -942,7 +943,7 @@ fn reward_destination_works() { // Compute total payout now for whole duration as other parameter won't change let total_payout_0 = current_total_payout_for_duration(reward_time_per_era()); - >::reward_by_ids(vec![(11, 1)]); + Pallet::::reward_by_ids(vec![(11, 1)]); mock::start_active_era(1); mock::make_all_reward_payment(0); @@ -968,7 +969,7 @@ fn reward_destination_works() { // Compute total payout now for whole duration as other parameter won't change let total_payout_1 = current_total_payout_for_duration(reward_time_per_era()); - >::reward_by_ids(vec![(11, 1)]); + Pallet::::reward_by_ids(vec![(11, 1)]); mock::start_active_era(2); mock::make_all_reward_payment(1); @@ -999,7 +1000,7 @@ fn reward_destination_works() { // Compute total payout now for whole duration as other parameter won't change let total_payout_2 = current_total_payout_for_duration(reward_time_per_era()); - >::reward_by_ids(vec![(11, 1)]); + Pallet::::reward_by_ids(vec![(11, 1)]); mock::start_active_era(3); mock::make_all_reward_payment(2); @@ -1049,7 +1050,7 @@ fn validator_payment_prefs_work() { // Compute total payout now for whole duration as other parameter won't change let total_payout_1 = current_total_payout_for_duration(reward_time_per_era()); let exposure_1 = Staking::eras_stakers(active_era(), 11); - >::reward_by_ids(vec![(11, 1)]); + Pallet::::reward_by_ids(vec![(11, 1)]); mock::start_active_era(2); mock::make_all_reward_payment(1); @@ -1610,8 +1611,8 @@ fn reward_to_stake_works() { // Compute total payout now for whole duration as other parameter won't change let total_payout_0 = current_total_payout_for_duration(reward_time_per_era()); - >::reward_by_ids(vec![(11, 1)]); - >::reward_by_ids(vec![(21, 1)]); + Pallet::::reward_by_ids(vec![(11, 1)]); + Pallet::::reward_by_ids(vec![(21, 1)]); // New era --> rewards are paid --> stakes are changed mock::start_active_era(1); @@ -1707,6 +1708,7 @@ fn switching_roles() { // add a new validator candidate assert_ok!(Staking::bond(Origin::signed(5), 6, 1000, RewardDestination::Controller)); assert_ok!(Staking::validate(Origin::signed(6), ValidatorPrefs::default())); + assert_ok!(Session::set_keys(Origin::signed(6), SessionKeys { other: 6.into() }, vec![])); mock::start_active_era(1); @@ -1715,6 +1717,7 @@ fn switching_roles() { // 2 decides to be a validator. Consequences: assert_ok!(Staking::validate(Origin::signed(2), ValidatorPrefs::default())); + assert_ok!(Session::set_keys(Origin::signed(2), SessionKeys { other: 2.into() }, vec![])); // new stakes: // 10: 1000 self vote // 20: 1000 self vote + 250 vote @@ -1819,6 +1822,11 @@ fn bond_with_little_staked_value_bounded() { // Stingy validator. assert_ok!(Staking::bond(Origin::signed(1), 2, 1, RewardDestination::Controller)); assert_ok!(Staking::validate(Origin::signed(2), ValidatorPrefs::default())); + assert_ok!(Session::set_keys( + Origin::signed(2), + SessionKeys { other: 2.into() }, + vec![] + )); // 1 era worth of reward. BUT, we set the timestamp after on_initialize, so outdated by // one block. @@ -2051,12 +2059,12 @@ fn reward_from_authorship_event_handler_works() { ExtBuilder::default().build_and_execute(|| { use pallet_authorship::EventHandler; - assert_eq!(>::author(), 11); + assert_eq!(>::author(), Some(11)); - >::note_author(11); - >::note_uncle(21, 1); + Pallet::::note_author(11); + Pallet::::note_uncle(21, 1); // Rewarding the same two times works. - >::note_uncle(11, 1); + Pallet::::note_uncle(11, 1); // Not mandatory but must be coherent with rewards assert_eq_uvec!(Session::validators(), vec![11, 21]); @@ -2079,9 +2087,9 @@ fn add_reward_points_fns_works() { // Not mandatory but must be coherent with rewards assert_eq_uvec!(Session::validators(), vec![21, 11]); - >::reward_by_ids(vec![(21, 1), (11, 1), (11, 1)]); + Pallet::::reward_by_ids(vec![(21, 1), (11, 1), (11, 1)]); - >::reward_by_ids(vec![(21, 1), (11, 1), (11, 1)]); + Pallet::::reward_by_ids(vec![(21, 1), (11, 1), (11, 1)]); assert_eq!( ErasRewardPoints::::get(active_era()), @@ -3091,13 +3099,13 @@ fn claim_reward_at_the_last_era_and_no_double_claim_and_invalid_claim() { Payee::::insert(11, RewardDestination::Controller); Payee::::insert(101, RewardDestination::Controller); - >::reward_by_ids(vec![(11, 1)]); + Pallet::::reward_by_ids(vec![(11, 1)]); // Compute total payout now for whole duration as other parameter won't change let total_payout_0 = current_total_payout_for_duration(reward_time_per_era()); mock::start_active_era(1); - >::reward_by_ids(vec![(11, 1)]); + Pallet::::reward_by_ids(vec![(11, 1)]); // Change total issuance in order to modify total payout let _ = Balances::deposit_creating(&999, 1_000_000_000); // Compute total payout now for whole duration as other parameter won't change @@ -3106,7 +3114,7 @@ fn claim_reward_at_the_last_era_and_no_double_claim_and_invalid_claim() { mock::start_active_era(2); - >::reward_by_ids(vec![(11, 1)]); + Pallet::::reward_by_ids(vec![(11, 1)]); // Change total issuance in order to modify total payout let _ = Balances::deposit_creating(&999, 1_000_000_000); // Compute total payout now for whole duration as other parameter won't change @@ -3266,7 +3274,7 @@ fn test_max_nominator_rewarded_per_validator_and_cant_steal_someone_else_reward( } mock::start_active_era(1); - >::reward_by_ids(vec![(11, 1)]); + Pallet::::reward_by_ids(vec![(11, 1)]); // compute and ensure the reward amount is greater than zero. let _ = current_total_payout_for_duration(reward_time_per_era()); diff --git a/frame/sudo/src/lib.rs b/frame/sudo/src/lib.rs index de3b3439bc34..b6255da1d1c4 100644 --- a/frame/sudo/src/lib.rs +++ b/frame/sudo/src/lib.rs @@ -146,7 +146,7 @@ pub mod pallet { ) -> DispatchResultWithPostInfo { // This is a public call, so we ensure that the origin is some signed account. let sender = ensure_signed(origin)?; - ensure!(sender == Self::key(), Error::::RequireSudo); + ensure!(Self::key().map_or(false, |k| sender == k), Error::::RequireSudo); let res = call.dispatch_bypass_filter(frame_system::RawOrigin::Root.into()); Self::deposit_event(Event::Sudid { sudo_result: res.map(|_| ()).map_err(|e| e.error) }); @@ -172,7 +172,7 @@ pub mod pallet { ) -> DispatchResultWithPostInfo { // This is a public call, so we ensure that the origin is some signed account. let sender = ensure_signed(origin)?; - ensure!(sender == Self::key(), Error::::RequireSudo); + ensure!(Self::key().map_or(false, |k| sender == k), Error::::RequireSudo); let res = call.dispatch_bypass_filter(frame_system::RawOrigin::Root.into()); Self::deposit_event(Event::Sudid { sudo_result: res.map(|_| ()).map_err(|e| e.error) }); @@ -197,11 +197,11 @@ pub mod pallet { ) -> DispatchResultWithPostInfo { // This is a public call, so we ensure that the origin is some signed account. let sender = ensure_signed(origin)?; - ensure!(sender == Self::key(), Error::::RequireSudo); + ensure!(Self::key().map_or(false, |k| sender == k), Error::::RequireSudo); let new = T::Lookup::lookup(new)?; - Self::deposit_event(Event::KeyChanged { new_sudoer: Self::key() }); - >::put(new); + Self::deposit_event(Event::KeyChanged { old_sudoer: Key::::get() }); + Key::::put(&new); // Sudo user does not pay a fee. Ok(Pays::No.into()) } @@ -234,7 +234,7 @@ pub mod pallet { ) -> DispatchResultWithPostInfo { // This is a public call, so we ensure that the origin is some signed account. let sender = ensure_signed(origin)?; - ensure!(sender == Self::key(), Error::::RequireSudo); + ensure!(Self::key().map_or(false, |k| sender == k), Error::::RequireSudo); let who = T::Lookup::lookup(who)?; @@ -253,8 +253,8 @@ pub mod pallet { pub enum Event { /// A sudo just took place. \[result\] Sudid { sudo_result: DispatchResult }, - /// The \[sudoer\] just switched identity; the old key is supplied. - KeyChanged { new_sudoer: T::AccountId }, + /// The \[sudoer\] just switched identity; the old key is supplied if one existed. + KeyChanged { old_sudoer: Option }, /// A sudo just took place. \[result\] SudoAsDone { sudo_result: DispatchResult }, } @@ -269,25 +269,27 @@ pub mod pallet { /// The `AccountId` of the sudo key. #[pallet::storage] #[pallet::getter(fn key)] - pub(super) type Key = StorageValue<_, T::AccountId, ValueQuery>; + pub(super) type Key = StorageValue<_, T::AccountId, OptionQuery>; #[pallet::genesis_config] pub struct GenesisConfig { /// The `AccountId` of the sudo key. - pub key: T::AccountId, + pub key: Option, } #[cfg(feature = "std")] impl Default for GenesisConfig { fn default() -> Self { - Self { key: Default::default() } + Self { key: None } } } #[pallet::genesis_build] impl GenesisBuild for GenesisConfig { fn build(&self) { - >::put(&self.key); + if let Some(ref key) = self.key { + Key::::put(key); + } } } } diff --git a/frame/sudo/src/mock.rs b/frame/sudo/src/mock.rs index 88379d0e5fda..408cccc7de21 100644 --- a/frame/sudo/src/mock.rs +++ b/frame/sudo/src/mock.rs @@ -165,7 +165,7 @@ pub type LoggerCall = logger::Call; // Build test environment by setting the root `key` for the Genesis. pub fn new_test_ext(root_key: u64) -> sp_io::TestExternalities { let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - sudo::GenesisConfig:: { key: root_key } + sudo::GenesisConfig:: { key: Some(root_key) } .assimilate_storage(&mut t) .unwrap(); t.into() diff --git a/frame/sudo/src/tests.rs b/frame/sudo/src/tests.rs index 3fd199a1c8ca..882187906167 100644 --- a/frame/sudo/src/tests.rs +++ b/frame/sudo/src/tests.rs @@ -28,7 +28,7 @@ use mock::{ fn test_setup_works() { // Environment setup, logger storage, and sudo `key` retrieval should work as expected. new_test_ext(1).execute_with(|| { - assert_eq!(Sudo::key(), 1u64); + assert_eq!(Sudo::key(), Some(1u64)); assert!(Logger::i32_log().is_empty()); assert!(Logger::account_log().is_empty()); }); @@ -105,7 +105,7 @@ fn set_key_basics() { new_test_ext(1).execute_with(|| { // A root `key` can change the root `key` assert_ok!(Sudo::set_key(Origin::signed(1), 2)); - assert_eq!(Sudo::key(), 2u64); + assert_eq!(Sudo::key(), Some(2u64)); }); new_test_ext(1).execute_with(|| { @@ -123,10 +123,10 @@ fn set_key_emits_events_correctly() { // A root `key` can change the root `key`. assert_ok!(Sudo::set_key(Origin::signed(1), 2)); - System::assert_has_event(TestEvent::Sudo(Event::KeyChanged { new_sudoer: 1 })); + System::assert_has_event(TestEvent::Sudo(Event::KeyChanged { old_sudoer: Some(1) })); // Double check. assert_ok!(Sudo::set_key(Origin::signed(2), 4)); - System::assert_has_event(TestEvent::Sudo(Event::KeyChanged { new_sudoer: 2 })); + System::assert_has_event(TestEvent::Sudo(Event::KeyChanged { old_sudoer: Some(2) })); }); } diff --git a/frame/support/src/traits/validation.rs b/frame/support/src/traits/validation.rs index 674f2d718fff..e5c81a149e4d 100644 --- a/frame/support/src/traits/validation.rs +++ b/frame/support/src/traits/validation.rs @@ -77,7 +77,7 @@ pub trait VerifySeal { /// A session handler for specific key type. pub trait OneSessionHandler: BoundToRuntimeAppPublic { /// The key type expected. - type Key: Decode + Default + RuntimeAppPublic; + type Key: Decode + RuntimeAppPublic; /// The given validator set will be used for the genesis session. /// It is guaranteed that the given validator set will also be used diff --git a/frame/support/test/tests/construct_runtime.rs b/frame/support/test/tests/construct_runtime.rs index 2d14da04f64b..b2717b0f095c 100644 --- a/frame/support/test/tests/construct_runtime.rs +++ b/frame/support/test/tests/construct_runtime.rs @@ -229,6 +229,10 @@ pub type AccountId = ::Signer; pub type BlockNumber = u64; pub type Index = u64; +fn test_pub() -> AccountId { + AccountId::from_raw([0; 32]) +} + impl system::Config for Runtime { type BaseCallFilter = frame_support::traits::Everything; type Hash = H256; @@ -451,13 +455,13 @@ fn event_codec() { let event = system::Event::::ExtrinsicSuccess; assert_eq!(Event::from(event).encode()[0], 30); - let event = module1::Event::::A(Default::default()); + let event = module1::Event::::A(test_pub()); assert_eq!(Event::from(event).encode()[0], 31); let event = module2::Event::A; assert_eq!(Event::from(event).encode()[0], 32); - let event = module1::Event::::A(Default::default()); + let event = module1::Event::::A(test_pub()); assert_eq!(Event::from(event).encode()[0], 33); let event = nested::module3::Event::A; @@ -466,19 +470,19 @@ fn event_codec() { let event = module3::Event::A; assert_eq!(Event::from(event).encode()[0], 35); - let event = module1::Event::::A(Default::default()); + let event = module1::Event::::A(test_pub()); assert_eq!(Event::from(event).encode()[0], 4); - let event = module1::Event::::A(Default::default()); + let event = module1::Event::::A(test_pub()); assert_eq!(Event::from(event).encode()[0], 1); - let event = module1::Event::::A(Default::default()); + let event = module1::Event::::A(test_pub()); assert_eq!(Event::from(event).encode()[0], 2); - let event = module1::Event::::A(Default::default()); + let event = module1::Event::::A(test_pub()); assert_eq!(Event::from(event).encode()[0], 12); - let event = module1::Event::::A(Default::default()); + let event = module1::Event::::A(test_pub()); assert_eq!(Event::from(event).encode()[0], 13); } diff --git a/frame/system/src/extensions/check_genesis.rs b/frame/system/src/extensions/check_genesis.rs index 9c5c890ee609..c758f9b6cb6e 100644 --- a/frame/system/src/extensions/check_genesis.rs +++ b/frame/system/src/extensions/check_genesis.rs @@ -19,7 +19,7 @@ use crate::{Config, Pallet}; use codec::{Decode, Encode}; use scale_info::TypeInfo; use sp_runtime::{ - traits::{SignedExtension, Zero}, + traits::{DispatchInfoOf, SignedExtension, Zero}, transaction_validity::TransactionValidityError, }; @@ -62,4 +62,14 @@ impl SignedExtension for CheckGenesis { fn additional_signed(&self) -> Result { Ok(>::block_hash(T::BlockNumber::zero())) } + + fn pre_dispatch( + self, + who: &Self::AccountId, + call: &Self::Call, + info: &DispatchInfoOf, + len: usize, + ) -> Result { + Ok(self.validate(who, call, info, len).map(|_| ())?) + } } diff --git a/frame/system/src/extensions/check_mortality.rs b/frame/system/src/extensions/check_mortality.rs index 941f28dc6fc6..140a06298df3 100644 --- a/frame/system/src/extensions/check_mortality.rs +++ b/frame/system/src/extensions/check_mortality.rs @@ -85,6 +85,16 @@ impl SignedExtension for CheckMortality { Ok(>::block_hash(n)) } } + + fn pre_dispatch( + self, + who: &Self::AccountId, + call: &Self::Call, + info: &DispatchInfoOf, + len: usize, + ) -> Result { + Ok(self.validate(who, call, info, len).map(|_| ())?) + } } #[cfg(test)] diff --git a/frame/system/src/extensions/check_non_zero_sender.rs b/frame/system/src/extensions/check_non_zero_sender.rs index 1d45ae17cb7a..349bc0bede0d 100644 --- a/frame/system/src/extensions/check_non_zero_sender.rs +++ b/frame/system/src/extensions/check_non_zero_sender.rs @@ -65,6 +65,16 @@ where Ok(()) } + fn pre_dispatch( + self, + who: &Self::AccountId, + call: &Self::Call, + info: &DispatchInfoOf, + len: usize, + ) -> Result { + Ok(self.validate(who, call, info, len).map(|_| ())?) + } + fn validate( &self, who: &Self::AccountId, diff --git a/frame/system/src/extensions/check_spec_version.rs b/frame/system/src/extensions/check_spec_version.rs index 688abe99763a..1e1a31d4d870 100644 --- a/frame/system/src/extensions/check_spec_version.rs +++ b/frame/system/src/extensions/check_spec_version.rs @@ -18,7 +18,10 @@ use crate::{Config, Pallet}; use codec::{Decode, Encode}; use scale_info::TypeInfo; -use sp_runtime::{traits::SignedExtension, transaction_validity::TransactionValidityError}; +use sp_runtime::{ + traits::{DispatchInfoOf, SignedExtension}, + transaction_validity::TransactionValidityError, +}; /// Ensure the runtime version registered in the transaction is the same as at present. /// @@ -59,4 +62,14 @@ impl SignedExtension for CheckSpecVersion { fn additional_signed(&self) -> Result { Ok(>::runtime_version().spec_version) } + + fn pre_dispatch( + self, + who: &Self::AccountId, + call: &Self::Call, + info: &DispatchInfoOf, + len: usize, + ) -> Result { + Ok(self.validate(who, call, info, len).map(|_| ())?) + } } diff --git a/frame/system/src/extensions/check_tx_version.rs b/frame/system/src/extensions/check_tx_version.rs index f6bb53e1cba3..e1e7b070e831 100644 --- a/frame/system/src/extensions/check_tx_version.rs +++ b/frame/system/src/extensions/check_tx_version.rs @@ -18,7 +18,10 @@ use crate::{Config, Pallet}; use codec::{Decode, Encode}; use scale_info::TypeInfo; -use sp_runtime::{traits::SignedExtension, transaction_validity::TransactionValidityError}; +use sp_runtime::{ + traits::{DispatchInfoOf, SignedExtension}, + transaction_validity::TransactionValidityError, +}; /// Ensure the transaction version registered in the transaction is the same as at present. /// @@ -59,4 +62,13 @@ impl SignedExtension for CheckTxVersion { fn additional_signed(&self) -> Result { Ok(>::runtime_version().transaction_version) } + fn pre_dispatch( + self, + who: &Self::AccountId, + call: &Self::Call, + info: &DispatchInfoOf, + len: usize, + ) -> Result { + Ok(self.validate(who, call, info, len).map(|_| ())?) + } } diff --git a/frame/system/src/extensions/check_weight.rs b/frame/system/src/extensions/check_weight.rs index ca885accd660..8f83b7594cb5 100644 --- a/frame/system/src/extensions/check_weight.rs +++ b/frame/system/src/extensions/check_weight.rs @@ -223,7 +223,7 @@ where } fn post_dispatch( - _pre: Self::Pre, + _pre: Option, info: &DispatchInfoOf, post_info: &PostDispatchInfoOf, _len: usize, @@ -563,7 +563,13 @@ mod tests { let pre = CheckWeight::(PhantomData).pre_dispatch(&1, CALL, &info, len).unwrap(); assert_eq!(BlockWeight::::get().total(), info.weight + 256); - assert_ok!(CheckWeight::::post_dispatch(pre, &info, &post_info, len, &Ok(()))); + assert_ok!(CheckWeight::::post_dispatch( + Some(pre), + &info, + &post_info, + len, + &Ok(()) + )); assert_eq!(BlockWeight::::get().total(), post_info.actual_weight.unwrap() + 256); }) } @@ -587,7 +593,13 @@ mod tests { info.weight + 128 + block_weights().get(DispatchClass::Normal).base_extrinsic, ); - assert_ok!(CheckWeight::::post_dispatch(pre, &info, &post_info, len, &Ok(()))); + assert_ok!(CheckWeight::::post_dispatch( + Some(pre), + &info, + &post_info, + len, + &Ok(()) + )); assert_eq!( BlockWeight::::get().total(), info.weight + 128 + block_weights().get(DispatchClass::Normal).base_extrinsic, diff --git a/frame/system/src/lib.rs b/frame/system/src/lib.rs index f62d60f6fda9..6bdaf8bd4b50 100644 --- a/frame/system/src/lib.rs +++ b/frame/system/src/lib.rs @@ -238,7 +238,6 @@ pub mod pallet { + Debug + MaybeDisplay + Ord - + Default + MaxEncodedLen; /// Converting trait to take a source type and convert to `AccountId`. diff --git a/frame/tips/src/lib.rs b/frame/tips/src/lib.rs index 0d2a56520a15..5edb5f042a61 100644 --- a/frame/tips/src/lib.rs +++ b/frame/tips/src/lib.rs @@ -61,7 +61,7 @@ pub mod migrations; pub mod weights; use sp_runtime::{ - traits::{AccountIdConversion, BadOrigin, Hash, Zero}, + traits::{AccountIdConversion, BadOrigin, Hash, TrailingZeroInput, Zero}, Percent, RuntimeDebug, }; use sp_std::prelude::*; @@ -580,6 +580,9 @@ impl Pallet { use frame_support::{migration::storage_key_iter, Twox64Concat}; + let zero_account = T::AccountId::decode(&mut TrailingZeroInput::new(&[][..])) + .expect("infinite input; qed"); + for (hash, old_tip) in storage_key_iter::< T::Hash, OldOpenTip, T::BlockNumber, T::Hash>, @@ -589,7 +592,7 @@ impl Pallet { { let (finder, deposit, finders_fee) = match old_tip.finder { Some((finder, deposit)) => (finder, deposit, true), - None => (T::AccountId::default(), Zero::zero(), false), + None => (zero_account.clone(), Zero::zero(), false), }; let new_tip = OpenTip { reason: old_tip.reason, diff --git a/frame/transaction-payment/asset-tx-payment/src/lib.rs b/frame/transaction-payment/asset-tx-payment/src/lib.rs index 1f22669857d7..be16fa45f953 100644 --- a/frame/transaction-payment/asset-tx-payment/src/lib.rs +++ b/frame/transaction-payment/asset-tx-payment/src/lib.rs @@ -244,43 +244,44 @@ where } fn post_dispatch( - pre: Self::Pre, + pre: Option, info: &DispatchInfoOf, post_info: &PostDispatchInfoOf, len: usize, result: &DispatchResult, ) -> Result<(), TransactionValidityError> { - let (tip, who, initial_payment) = pre; - match initial_payment { - InitialPayment::Native(already_withdrawn) => { - pallet_transaction_payment::ChargeTransactionPayment::::post_dispatch( - (tip, who, already_withdrawn), - info, - post_info, - len, - result, - )?; - }, - InitialPayment::Asset(already_withdrawn) => { - let actual_fee = pallet_transaction_payment::Pallet::::compute_actual_fee( - len as u32, info, post_info, tip, - ); - T::OnChargeAssetTransaction::correct_and_deposit_fee( - &who, - info, - post_info, - actual_fee.into(), - tip.into(), - already_withdrawn.into(), - )?; - }, - InitialPayment::Nothing => { - // `actual_fee` should be zero here for any signed extrinsic. It would be non-zero - // here in case of unsigned extrinsics as they don't pay fees but - // `compute_actual_fee` is not aware of them. In both cases it's fine to just move - // ahead without adjusting the fee, though, so we do nothing. - debug_assert!(tip.is_zero(), "tip should be zero if initial fee was zero."); - }, + if let Some((tip, who, initial_payment)) = pre { + match initial_payment { + InitialPayment::Native(already_withdrawn) => { + pallet_transaction_payment::ChargeTransactionPayment::::post_dispatch( + Some((tip, who, already_withdrawn)), + info, + post_info, + len, + result, + )?; + }, + InitialPayment::Asset(already_withdrawn) => { + let actual_fee = pallet_transaction_payment::Pallet::::compute_actual_fee( + len as u32, info, post_info, tip, + ); + T::OnChargeAssetTransaction::correct_and_deposit_fee( + &who, + info, + post_info, + actual_fee.into(), + tip.into(), + already_withdrawn.into(), + )?; + }, + InitialPayment::Nothing => { + // `actual_fee` should be zero here for any signed extrinsic. It would be + // non-zero here in case of unsigned extrinsics as they don't pay fees but + // `compute_actual_fee` is not aware of them. In both cases it's fine to just + // move ahead without adjusting the fee, though, so we do nothing. + debug_assert!(tip.is_zero(), "tip should be zero if initial fee was zero."); + }, + } } Ok(()) diff --git a/frame/transaction-payment/asset-tx-payment/src/tests.rs b/frame/transaction-payment/asset-tx-payment/src/tests.rs index 106b361aff8f..c6c60cfe237d 100644 --- a/frame/transaction-payment/asset-tx-payment/src/tests.rs +++ b/frame/transaction-payment/asset-tx-payment/src/tests.rs @@ -201,10 +201,11 @@ impl pallet_authorship::Config for Runtime { pub struct CreditToBlockAuthor; impl HandleCredit for CreditToBlockAuthor { fn handle_credit(credit: CreditOf) { - let author = pallet_authorship::Pallet::::author(); - // What to do in case paying the author fails (e.g. because `fee < min_balance`) - // default: drop the result which will trigger the `OnDrop` of the imbalance. - let _ = >::resolve(&author, credit); + if let Some(author) = pallet_authorship::Pallet::::author() { + // What to do in case paying the author fails (e.g. because `fee < min_balance`) + // default: drop the result which will trigger the `OnDrop` of the imbalance. + let _ = >::resolve(&author, credit); + } } } @@ -304,7 +305,7 @@ fn transaction_payment_in_native_possible() { assert_eq!(Balances::free_balance(1), initial_balance - 5 - 5 - 10); assert_ok!(ChargeAssetTxPayment::::post_dispatch( - pre, + Some(pre), &info_from_weight(5), &default_post_info(), len, @@ -319,7 +320,7 @@ fn transaction_payment_in_native_possible() { assert_eq!(Balances::free_balance(2), initial_balance_for_2 - 5 - 10 - 100 - 5); assert_ok!(ChargeAssetTxPayment::::post_dispatch( - pre, + Some(pre), &info_from_weight(100), &post_info_from_weight(50), len, @@ -370,7 +371,7 @@ fn transaction_payment_in_asset_possible() { assert_eq!(Assets::balance(asset_id, BLOCK_AUTHOR), 0); assert_ok!(ChargeAssetTxPayment::::post_dispatch( - pre, + Some(pre), &info_from_weight(weight), &default_post_info(), len, @@ -423,7 +424,7 @@ fn transaction_payment_without_fee() { assert_eq!(Assets::balance(asset_id, BLOCK_AUTHOR), 0); assert_ok!(ChargeAssetTxPayment::::post_dispatch( - pre, + Some(pre), &info_from_weight(weight), &post_info_from_pays(Pays::No), len, @@ -475,7 +476,7 @@ fn asset_transaction_payment_with_tip_and_refund() { let final_weight = 50; assert_ok!(ChargeAssetTxPayment::::post_dispatch( - pre, + Some(pre), &info_from_weight(weight), &post_info_from_weight(final_weight), len, @@ -528,7 +529,7 @@ fn payment_from_account_with_only_assets() { assert_eq!(Assets::balance(asset_id, caller), balance - fee); assert_ok!(ChargeAssetTxPayment::::post_dispatch( - pre, + Some(pre), &info_from_weight(weight), &default_post_info(), len, @@ -612,7 +613,7 @@ fn converted_fee_is_never_zero_if_input_fee_is_not() { assert_eq!(Assets::balance(asset_id, caller), balance); assert_ok!(ChargeAssetTxPayment::::post_dispatch( - pre, + Some(pre), &info_from_pays(Pays::No), &post_info_from_pays(Pays::No), len, @@ -627,7 +628,7 @@ fn converted_fee_is_never_zero_if_input_fee_is_not() { assert_eq!(Assets::balance(asset_id, caller), balance - 1); assert_ok!(ChargeAssetTxPayment::::post_dispatch( - pre, + Some(pre), &info_from_weight(weight), &default_post_info(), len, @@ -684,7 +685,7 @@ fn post_dispatch_fee_is_zero_if_pre_dispatch_fee_is_zero() { // `Pays::Yes` on post-dispatch does not mean we pay (we never charge more than the // initial fee) assert_ok!(ChargeAssetTxPayment::::post_dispatch( - pre, + Some(pre), &info_from_pays(Pays::No), &post_info_from_pays(Pays::Yes), len, @@ -721,7 +722,7 @@ fn post_dispatch_fee_is_zero_if_unsigned_pre_dispatch_fee_is_zero() { assert_eq!(Assets::balance(asset_id, caller), balance); let weight = 1; let len = 1; - let pre = ChargeAssetTxPayment::::pre_dispatch_unsigned( + ChargeAssetTxPayment::::pre_dispatch_unsigned( CALL, &info_from_weight(weight), len, @@ -729,17 +730,11 @@ fn post_dispatch_fee_is_zero_if_unsigned_pre_dispatch_fee_is_zero() { .unwrap(); assert_eq!(Assets::balance(asset_id, caller), balance); - let (_tip, _who, initial_payment) = ⪯ - let not_paying = match initial_payment { - &InitialPayment::Nothing => true, - _ => false, - }; - assert!(not_paying, "initial payment is Nothing for unsigned extrinsics"); // `Pays::Yes` on post-dispatch does not mean we pay (we never charge more than the // initial fee) assert_ok!(ChargeAssetTxPayment::::post_dispatch( - pre, + None, &info_from_weight(weight), &post_info_from_pays(Pays::Yes), len, diff --git a/frame/transaction-payment/src/lib.rs b/frame/transaction-payment/src/lib.rs index a5bcc6d12dec..c7ccdafc7828 100644 --- a/frame/transaction-payment/src/lib.rs +++ b/frame/transaction-payment/src/lib.rs @@ -704,7 +704,7 @@ where type Pre = ( // tip BalanceOf, - // who paid the fee + // who paid the fee - this is an option to allow for a Default impl. Self::AccountId, // imbalance resulting from withdrawing the fee <::OnChargeTransaction as OnChargeTransaction>::LiquidityInfo, @@ -740,17 +740,18 @@ where } fn post_dispatch( - pre: Self::Pre, + maybe_pre: Option, info: &DispatchInfoOf, post_info: &PostDispatchInfoOf, len: usize, _result: &DispatchResult, ) -> Result<(), TransactionValidityError> { - let (tip, who, imbalance) = pre; - let actual_fee = Pallet::::compute_actual_fee(len as u32, info, post_info, tip); - T::OnChargeTransaction::correct_and_deposit_fee( - &who, info, post_info, actual_fee, tip, imbalance, - )?; + if let Some((tip, who, imbalance)) = maybe_pre { + let actual_fee = Pallet::::compute_actual_fee(len as u32, info, post_info, tip); + T::OnChargeTransaction::correct_and_deposit_fee( + &who, info, post_info, actual_fee, tip, imbalance, + )?; + } Ok(()) } } @@ -1014,7 +1015,7 @@ mod tests { assert_eq!(Balances::free_balance(1), 100 - 5 - 5 - 10); assert_ok!(ChargeTransactionPayment::::post_dispatch( - pre, + Some(pre), &info_from_weight(5), &default_post_info(), len, @@ -1032,7 +1033,7 @@ mod tests { assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 100 - 5); assert_ok!(ChargeTransactionPayment::::post_dispatch( - pre, + Some(pre), &info_from_weight(100), &post_info_from_weight(50), len, @@ -1061,7 +1062,7 @@ mod tests { assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 150 - 5); assert_ok!(ChargeTransactionPayment::::post_dispatch( - pre, + Some(pre), &info_from_weight(100), &post_info_from_weight(50), len, @@ -1356,7 +1357,7 @@ mod tests { assert_eq!(Balances::free_balance(2), 0); assert_ok!(ChargeTransactionPayment::::post_dispatch( - pre, + Some(pre), &info_from_weight(100), &post_info_from_weight(50), len, @@ -1390,7 +1391,7 @@ mod tests { assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 100 - 5); assert_ok!(ChargeTransactionPayment::::post_dispatch( - pre, + Some(pre), &info_from_weight(100), &post_info_from_weight(101), len, @@ -1418,7 +1419,7 @@ mod tests { .unwrap(); assert_eq!(Balances::total_balance(&user), 0); assert_ok!(ChargeTransactionPayment::::post_dispatch( - pre, + Some(pre), &dispatch_info, &default_post_info(), len, @@ -1450,7 +1451,7 @@ mod tests { .unwrap(); ChargeTransactionPayment::::post_dispatch( - pre, + Some(pre), &info, &post_info, len, @@ -1601,7 +1602,7 @@ mod tests { .unwrap(); ChargeTransactionPayment::::post_dispatch( - pre, + Some(pre), &info, &post_info, len, diff --git a/frame/utility/src/lib.rs b/frame/utility/src/lib.rs index fde4e78366e6..2200d96da600 100644 --- a/frame/utility/src/lib.rs +++ b/frame/utility/src/lib.rs @@ -65,7 +65,7 @@ use frame_support::{ }; use sp_core::TypeId; use sp_io::hashing::blake2_256; -use sp_runtime::traits::Dispatchable; +use sp_runtime::traits::{Dispatchable, TrailingZeroInput}; use sp_std::prelude::*; pub use weights::WeightInfo; @@ -400,6 +400,7 @@ impl Pallet { /// Derive a derivative account ID from the owner account and the sub-account index. pub fn derivative_account_id(who: T::AccountId, index: u16) -> T::AccountId { let entropy = (b"modlpy/utilisuba", who, index).using_encoded(blake2_256); - T::AccountId::decode(&mut &entropy[..]).unwrap_or_default() + Decode::decode(&mut TrailingZeroInput::new(entropy.as_ref())) + .expect("infinite length input; no invalid inputs for type; qed") } } diff --git a/primitives/api/test/tests/runtime_calls.rs b/primitives/api/test/tests/runtime_calls.rs index 21dfd456b1a1..5c9b25fa3186 100644 --- a/primitives/api/test/tests/runtime_calls.rs +++ b/primitives/api/test/tests/runtime_calls.rs @@ -187,7 +187,7 @@ fn record_proof_works() { amount: 1000, nonce: 0, from: AccountKeyring::Alice.into(), - to: Default::default(), + to: AccountKeyring::Bob.into(), } .into_signed_tx(); diff --git a/primitives/application-crypto/src/ecdsa.rs b/primitives/application-crypto/src/ecdsa.rs index 915e16ba3b1a..fba1fc03b253 100644 --- a/primitives/application-crypto/src/ecdsa.rs +++ b/primitives/application-crypto/src/ecdsa.rs @@ -57,6 +57,6 @@ impl RuntimePublic for Public { } fn to_raw_vec(&self) -> Vec { - sp_core::crypto::Public::to_raw_vec(self) + sp_core::crypto::ByteArray::to_raw_vec(self) } } diff --git a/primitives/application-crypto/src/ed25519.rs b/primitives/application-crypto/src/ed25519.rs index 09ce48fcb274..35fcb2403a03 100644 --- a/primitives/application-crypto/src/ed25519.rs +++ b/primitives/application-crypto/src/ed25519.rs @@ -57,6 +57,6 @@ impl RuntimePublic for Public { } fn to_raw_vec(&self) -> Vec { - sp_core::crypto::Public::to_raw_vec(self) + sp_core::crypto::ByteArray::to_raw_vec(self) } } diff --git a/primitives/application-crypto/src/lib.rs b/primitives/application-crypto/src/lib.rs index baa656066705..a6bba4363222 100644 --- a/primitives/application-crypto/src/lib.rs +++ b/primitives/application-crypto/src/lib.rs @@ -27,7 +27,10 @@ pub use sp_core::crypto::{DeriveJunction, Pair, SecretStringError, Ss58Codec}; #[doc(hidden)] pub use sp_core::{ self, - crypto::{CryptoType, CryptoTypePublicPair, Derive, IsWrappedBy, Public, Wraps}, + crypto::{ + ByteArray, CryptoType, CryptoTypePublicPair, Derive, IsWrappedBy, Public, UncheckedFrom, + Wraps, + }, RuntimeDebug, }; @@ -221,7 +224,7 @@ macro_rules! app_crypto_public_full_crypto { $crate::wrap! { /// A generic `AppPublic` wrapper type over $public crypto; this has no specific App. #[derive( - Clone, Default, Eq, Hash, PartialEq, PartialOrd, Ord, + Clone, Eq, Hash, PartialEq, PartialOrd, Ord, $crate::codec::Encode, $crate::codec::Decode, $crate::RuntimeDebug, @@ -258,7 +261,7 @@ macro_rules! app_crypto_public_not_full_crypto { $crate::wrap! { /// A generic `AppPublic` wrapper type over $public crypto; this has no specific App. #[derive( - Clone, Default, Eq, PartialEq, Ord, PartialOrd, + Clone, Eq, PartialEq, Ord, PartialOrd, $crate::codec::Encode, $crate::codec::Decode, $crate::RuntimeDebug, @@ -301,13 +304,12 @@ macro_rules! app_crypto_public_common { } } + impl $crate::ByteArray for Public { + const LEN: usize = <$public>::LEN; + } impl $crate::Public for Public { - fn from_slice(x: &[u8]) -> Self { - Self(<$public>::from_slice(x)) - } - fn to_public_crypto_pair(&self) -> $crate::CryptoTypePublicPair { - $crate::CryptoTypePublicPair($crypto_type, self.to_raw_vec()) + $crate::CryptoTypePublicPair($crypto_type, $crate::ByteArray::to_raw_vec(self)) } } @@ -357,7 +359,7 @@ macro_rules! app_crypto_public_common { impl From<&Public> for $crate::CryptoTypePublicPair { fn from(key: &Public) -> Self { - $crate::CryptoTypePublicPair($crypto_type, $crate::Public::to_raw_vec(key)) + $crate::CryptoTypePublicPair($crypto_type, $crate::ByteArray::to_raw_vec(key)) } } @@ -435,7 +437,7 @@ macro_rules! app_crypto_signature_full_crypto { ($sig:ty, $key_type:expr, $crypto_type:expr) => { $crate::wrap! { /// A generic `AppPublic` wrapper type over $public crypto; this has no specific App. - #[derive(Clone, Default, Eq, PartialEq, + #[derive(Clone, Eq, PartialEq, $crate::codec::Encode, $crate::codec::Decode, $crate::RuntimeDebug, @@ -470,7 +472,7 @@ macro_rules! app_crypto_signature_not_full_crypto { ($sig:ty, $key_type:expr, $crypto_type:expr) => { $crate::wrap! { /// A generic `AppPublic` wrapper type over $public crypto; this has no specific App. - #[derive(Clone, Default, Eq, PartialEq, + #[derive(Clone, Eq, PartialEq, $crate::codec::Encode, $crate::codec::Decode, $crate::scale_info::TypeInfo, @@ -516,11 +518,19 @@ macro_rules! app_crypto_signature_common { type Generic = $sig; } + impl<'a> $crate::TryFrom<&'a [u8]> for Signature { + type Error = (); + + fn try_from(data: &'a [u8]) -> Result { + <$sig>::try_from(data).map(Into::into) + } + } + impl $crate::TryFrom<$crate::Vec> for Signature { type Error = (); fn try_from(data: $crate::Vec) -> Result { - Ok(<$sig>::try_from(data.as_slice())?.into()) + Self::try_from(&data[..]) } } }; diff --git a/primitives/application-crypto/src/sr25519.rs b/primitives/application-crypto/src/sr25519.rs index f51236f2ab38..6cd1bf35a235 100644 --- a/primitives/application-crypto/src/sr25519.rs +++ b/primitives/application-crypto/src/sr25519.rs @@ -57,6 +57,6 @@ impl RuntimePublic for Public { } fn to_raw_vec(&self) -> Vec { - sp_core::crypto::Public::to_raw_vec(self) + sp_core::crypto::ByteArray::to_raw_vec(self) } } diff --git a/primitives/core/src/crypto.rs b/primitives/core/src/crypto.rs index dc08d69bf418..671f526fde32 100644 --- a/primitives/core/src/crypto.rs +++ b/primitives/core/src/crypto.rs @@ -222,7 +222,7 @@ pub enum PublicError { /// See /// for information on the codec. #[cfg(feature = "full_crypto")] -pub trait Ss58Codec: Sized + AsMut<[u8]> + AsRef<[u8]> + Default { +pub trait Ss58Codec: Sized + AsMut<[u8]> + AsRef<[u8]> + ByteArray { /// A format filterer, can be used to ensure that `from_ss58check` family only decode for /// allowed identifiers. By default just refuses the two reserved identifiers. fn format_is_allowed(f: Ss58AddressFormat) -> bool { @@ -243,10 +243,7 @@ pub trait Ss58Codec: Sized + AsMut<[u8]> + AsRef<[u8]> + Default { #[cfg(feature = "std")] fn from_ss58check_with_version(s: &str) -> Result<(Self, Ss58AddressFormat), PublicError> { const CHECKSUM_LEN: usize = 2; - let mut res = Self::default(); - - // Must decode to our type. - let body_len = res.as_mut().len(); + let body_len = Self::LEN; let data = s.from_base58().map_err(|_| PublicError::BadBase58)?; if data.len() < 2 { @@ -280,8 +277,10 @@ pub trait Ss58Codec: Sized + AsMut<[u8]> + AsRef<[u8]> + Default { // Invalid checksum. return Err(PublicError::InvalidChecksum) } - res.as_mut().copy_from_slice(&data[prefix_len..body_len + prefix_len]); - Ok((res, format)) + + let result = Self::from_slice(&data[prefix_len..body_len + prefix_len]) + .map_err(|()| PublicError::BadLength)?; + Ok((result, format)) } /// Some if the string is a properly encoded SS58Check address, optionally with @@ -391,19 +390,13 @@ lazy_static::lazy_static! { } #[cfg(feature = "std")] -impl + AsRef<[u8]> + Default + Derive> Ss58Codec for T { +impl + AsRef<[u8]> + Public + Derive> Ss58Codec for T { fn from_string(s: &str) -> Result { let cap = SS58_REGEX.captures(s).ok_or(PublicError::InvalidFormat)?; let s = cap.name("ss58").map(|r| r.as_str()).unwrap_or(DEV_ADDRESS); let addr = if let Some(stripped) = s.strip_prefix("0x") { let d = hex::decode(stripped).map_err(|_| PublicError::InvalidFormat)?; - let mut r = Self::default(); - if d.len() == r.as_ref().len() { - r.as_mut().copy_from_slice(&d); - r - } else { - return Err(PublicError::BadLength) - } + Self::from_slice(&d).map_err(|()| PublicError::BadLength)? } else { Self::from_ss58check(s)? }; @@ -431,25 +424,15 @@ impl + AsRef<[u8]> + Default + Derive> Ss58Codec for T { } } -/// Trait suitable for typical cryptographic PKI key public type. -pub trait Public: - AsRef<[u8]> - + AsMut<[u8]> - + Default - + Derive - + CryptoType - + PartialEq - + Eq - + Clone - + Send - + Sync - + for<'a> TryFrom<&'a [u8]> -{ - /// A new instance from the given slice. - /// - /// NOTE: No checking goes on to ensure this is a real public key. Only use it if - /// you are certain that the array actually is a pubkey. GIGO! - fn from_slice(data: &[u8]) -> Self; +/// Trait used for types that are really just a fixed-length array. +pub trait ByteArray: AsRef<[u8]> + AsMut<[u8]> + for<'a> TryFrom<&'a [u8], Error = ()> { + /// The "length" of the values of this type, which is always the same. + const LEN: usize; + + /// A new instance from the given slice that should be `Self::LEN` bytes long. + fn from_slice(data: &[u8]) -> Result { + Self::try_from(data) + } /// Return a `Vec` filled with raw data. fn to_raw_vec(&self) -> Vec { @@ -460,7 +443,10 @@ pub trait Public: fn as_slice(&self) -> &[u8] { self.as_ref() } +} +/// Trait suitable for typical cryptographic PKI key public type. +pub trait Public: ByteArray + Derive + CryptoType + PartialEq + Eq + Clone + Send + Sync { /// Return `CryptoTypePublicPair` from public key. fn to_public_crypto_pair(&self) -> CryptoTypePublicPair; } @@ -488,6 +474,10 @@ impl UncheckedFrom for AccountId32 { } } +impl ByteArray for AccountId32 { + const LEN: usize = 32; +} + #[cfg(feature = "std")] impl Ss58Codec for AccountId32 {} @@ -650,9 +640,10 @@ mod dummy { impl Derive for Dummy {} - impl Public for Dummy { - fn from_slice(_: &[u8]) -> Self { - Self + impl ByteArray for Dummy { + const LEN: usize = 0; + fn from_slice(_: &[u8]) -> Result { + Ok(Self) } #[cfg(feature = "std")] fn to_raw_vec(&self) -> Vec { @@ -661,8 +652,10 @@ mod dummy { fn as_slice(&self) -> &[u8] { b"" } + } + impl Public for Dummy { fn to_public_crypto_pair(&self) -> CryptoTypePublicPair { - CryptoTypePublicPair(CryptoTypeId(*b"dumm"), Public::to_raw_vec(self)) + CryptoTypePublicPair(CryptoTypeId(*b"dumm"), ::to_raw_vec(self)) } } @@ -1146,17 +1139,22 @@ mod tests { impl<'a> TryFrom<&'a [u8]> for TestPublic { type Error = (); - fn try_from(_: &'a [u8]) -> Result { - Ok(Self) + fn try_from(data: &'a [u8]) -> Result { + Self::from_slice(data) } } impl CryptoType for TestPublic { type Pair = TestPair; } impl Derive for TestPublic {} - impl Public for TestPublic { - fn from_slice(_bytes: &[u8]) -> Self { - Self + impl ByteArray for TestPublic { + const LEN: usize = 0; + fn from_slice(bytes: &[u8]) -> Result { + if bytes.len() == 0 { + Ok(Self) + } else { + Err(()) + } } fn as_slice(&self) -> &[u8] { &[] @@ -1164,6 +1162,8 @@ mod tests { fn to_raw_vec(&self) -> Vec { vec![] } + } + impl Public for TestPublic { fn to_public_crypto_pair(&self) -> CryptoTypePublicPair { CryptoTypePublicPair(CryptoTypeId(*b"dumm"), self.to_raw_vec()) } diff --git a/primitives/core/src/ecdsa.rs b/primitives/core/src/ecdsa.rs index 2751a0c40e3e..827be8eb9aab 100644 --- a/primitives/core/src/ecdsa.rs +++ b/primitives/core/src/ecdsa.rs @@ -27,7 +27,8 @@ use sp_std::cmp::Ordering; #[cfg(feature = "std")] use crate::crypto::Ss58Codec; use crate::crypto::{ - CryptoType, CryptoTypeId, CryptoTypePublicPair, Derive, Public as TraitPublic, UncheckedFrom, + ByteArray, CryptoType, CryptoTypeId, CryptoTypePublicPair, Derive, Public as TraitPublic, + UncheckedFrom, }; #[cfg(feature = "full_crypto")] use crate::{ @@ -113,17 +114,11 @@ impl Public { } } -impl TraitPublic for Public { - /// A new instance from the given slice that should be 33 bytes long. - /// - /// NOTE: No checking goes on to ensure this is a real public key. Only use it if - /// you are certain that the array actually is a pubkey. GIGO! - fn from_slice(data: &[u8]) -> Self { - let mut r = [0u8; 33]; - r.copy_from_slice(data); - Self(r) - } +impl ByteArray for Public { + const LEN: usize = 33; +} +impl TraitPublic for Public { fn to_public_crypto_pair(&self) -> CryptoTypePublicPair { CryptoTypePublicPair(CRYPTO_ID, self.to_raw_vec()) } @@ -143,12 +138,6 @@ impl From<&Public> for CryptoTypePublicPair { impl Derive for Public {} -impl Default for Public { - fn default() -> Self { - Public([0u8; 33]) - } -} - impl AsRef<[u8]> for Public { fn as_ref(&self) -> &[u8] { &self.0[..] @@ -165,11 +154,12 @@ impl sp_std::convert::TryFrom<&[u8]> for Public { type Error = (); fn try_from(data: &[u8]) -> Result { - if data.len() == 33 { - Ok(Self::from_slice(data)) - } else { - Err(()) + if data.len() != Self::LEN { + return Err(()) } + let mut r = [0u8; Self::LEN]; + r.copy_from_slice(data); + Ok(Self::unchecked_from(r)) } } @@ -340,6 +330,12 @@ impl sp_std::hash::Hash for Signature { } } +impl UncheckedFrom<[u8; 65]> for Signature { + fn unchecked_from(data: [u8; 65]) -> Signature { + Signature(data) + } +} + impl Signature { /// A new instance from the given 65-byte `data`. /// diff --git a/primitives/core/src/ed25519.rs b/primitives/core/src/ed25519.rs index d786ee9d255f..7d60998b15df 100644 --- a/primitives/core/src/ed25519.rs +++ b/primitives/core/src/ed25519.rs @@ -22,7 +22,10 @@ #[cfg(feature = "full_crypto")] use sp_std::vec::Vec; -use crate::hash::{H256, H512}; +use crate::{ + crypto::ByteArray, + hash::{H256, H512}, +}; use codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; @@ -66,7 +69,6 @@ type Seed = [u8; 32]; Copy, Encode, Decode, - Default, PassByInner, MaxEncodedLen, TypeInfo, @@ -118,13 +120,12 @@ impl sp_std::convert::TryFrom<&[u8]> for Public { type Error = (); fn try_from(data: &[u8]) -> Result { - if data.len() == 32 { - let mut inner = [0u8; 32]; - inner.copy_from_slice(data); - Ok(Public(inner)) - } else { - Err(()) + if data.len() != Self::LEN { + return Err(()) } + let mut r = [0u8; Self::LEN]; + r.copy_from_slice(data); + Ok(Self::unchecked_from(r)) } } @@ -258,12 +259,6 @@ impl Clone for Signature { } } -impl Default for Signature { - fn default() -> Self { - Signature([0u8; 64]) - } -} - impl PartialEq for Signature { fn eq(&self, b: &Self) -> bool { self.0[..] == b.0[..] @@ -321,6 +316,12 @@ impl sp_std::hash::Hash for Signature { } } +impl UncheckedFrom<[u8; 64]> for Signature { + fn unchecked_from(data: [u8; 64]) -> Signature { + Signature(data) + } +} + impl Signature { /// A new instance from the given 64-byte `data`. /// @@ -400,17 +401,11 @@ impl Public { } } -impl TraitPublic for Public { - /// A new instance from the given slice that should be 32 bytes long. - /// - /// NOTE: No checking goes on to ensure this is a real public key. Only use it if - /// you are certain that the array actually is a pubkey. GIGO! - fn from_slice(data: &[u8]) -> Self { - let mut r = [0u8; 32]; - r.copy_from_slice(data); - Public(r) - } +impl ByteArray for Public { + const LEN: usize = 32; +} +impl TraitPublic for Public { fn to_public_crypto_pair(&self) -> CryptoTypePublicPair { CryptoTypePublicPair(CRYPTO_ID, self.to_raw_vec()) } diff --git a/primitives/core/src/lib.rs b/primitives/core/src/lib.rs index 3983f7cc155d..5fca42adde99 100644 --- a/primitives/core/src/lib.rs +++ b/primitives/core/src/lib.rs @@ -76,7 +76,7 @@ pub use self::{ uint::{U256, U512}, }; #[cfg(feature = "full_crypto")] -pub use crypto::{DeriveJunction, Pair, Public}; +pub use crypto::{ByteArray, DeriveJunction, Pair, Public}; #[cfg(feature = "std")] pub use self::hasher::blake2::Blake2Hasher; diff --git a/primitives/core/src/sr25519.rs b/primitives/core/src/sr25519.rs index 4787c2d9d13e..97e9de5de09a 100644 --- a/primitives/core/src/sr25519.rs +++ b/primitives/core/src/sr25519.rs @@ -41,7 +41,7 @@ use substrate_bip39::mini_secret_from_entropy; use crate::{ crypto::{ - CryptoType, CryptoTypeId, CryptoTypePublicPair, Derive, Public as TraitPublic, + ByteArray, CryptoType, CryptoTypeId, CryptoTypePublicPair, Derive, Public as TraitPublic, UncheckedFrom, }, hash::{H256, H512}, @@ -74,7 +74,6 @@ pub const CRYPTO_ID: CryptoTypeId = CryptoTypeId(*b"sr25"); Copy, Encode, Decode, - Default, PassByInner, MaxEncodedLen, TypeInfo, @@ -147,13 +146,12 @@ impl sp_std::convert::TryFrom<&[u8]> for Public { type Error = (); fn try_from(data: &[u8]) -> Result { - if data.len() == 32 { - let mut inner = [0u8; 32]; - inner.copy_from_slice(data); - Ok(Public(inner)) - } else { - Err(()) + if data.len() != Self::LEN { + return Err(()) } + let mut r = [0u8; 32]; + r.copy_from_slice(data); + Ok(Self::unchecked_from(r)) } } @@ -261,12 +259,6 @@ impl Clone for Signature { } } -impl Default for Signature { - fn default() -> Self { - Signature([0u8; 64]) - } -} - impl PartialEq for Signature { fn eq(&self, b: &Self) -> bool { self.0[..] == b.0[..] @@ -342,6 +334,12 @@ pub struct LocalizedSignature { pub signature: Signature, } +impl UncheckedFrom<[u8; 64]> for Signature { + fn unchecked_from(data: [u8; 64]) -> Signature { + Signature(data) + } +} + impl Signature { /// A new instance from the given 64-byte `data`. /// @@ -412,17 +410,11 @@ impl Public { } } -impl TraitPublic for Public { - /// A new instance from the given slice that should be 32 bytes long. - /// - /// NOTE: No checking goes on to ensure this is a real public key. Only use it if - /// you are certain that the array actually is a pubkey. GIGO! - fn from_slice(data: &[u8]) -> Self { - let mut r = [0u8; 32]; - r.copy_from_slice(data); - Public(r) - } +impl ByteArray for Public { + const LEN: usize = 32; +} +impl TraitPublic for Public { fn to_public_crypto_pair(&self) -> CryptoTypePublicPair { CryptoTypePublicPair(CRYPTO_ID, self.to_raw_vec()) } diff --git a/primitives/io/src/lib.rs b/primitives/io/src/lib.rs index 44649abd2891..1edf87703fbe 100644 --- a/primitives/io/src/lib.rs +++ b/primitives/io/src/lib.rs @@ -1543,7 +1543,10 @@ pub type SubstrateHostFunctions = ( #[cfg(test)] mod tests { use super::*; - use sp_core::{map, storage::Storage, testing::TaskExecutor, traits::TaskExecutorExt}; + use sp_core::{ + crypto::UncheckedInto, map, storage::Storage, testing::TaskExecutor, + traits::TaskExecutorExt, + }; use sp_state_machine::BasicExternalities; use std::any::TypeId; @@ -1644,7 +1647,7 @@ mod tests { } // push invlaid - crypto::sr25519_batch_verify(&Default::default(), &Vec::new(), &Default::default()); + crypto::sr25519_batch_verify(&zero_sr_sig(), &Vec::new(), &zero_sr_pub()); assert!(!crypto::finish_batch_verify()); crypto::start_batch_verify(); @@ -1657,14 +1660,31 @@ mod tests { }); } + fn zero_ed_pub() -> ed25519::Public { + [0u8; 32].unchecked_into() + } + + fn zero_ed_sig() -> ed25519::Signature { + ed25519::Signature::from_raw([0u8; 64]) + } + + fn zero_sr_pub() -> sr25519::Public { + [0u8; 32].unchecked_into() + } + + fn zero_sr_sig() -> sr25519::Signature { + sr25519::Signature::from_raw([0u8; 64]) + } + #[test] fn batching_works() { let mut ext = BasicExternalities::default(); ext.register_extension(TaskExecutorExt::new(TaskExecutor::new())); + ext.execute_with(|| { // invalid ed25519 signature crypto::start_batch_verify(); - crypto::ed25519_batch_verify(&Default::default(), &Vec::new(), &Default::default()); + crypto::ed25519_batch_verify(&zero_ed_sig(), &Vec::new(), &zero_ed_pub()); assert!(!crypto::finish_batch_verify()); // 2 valid ed25519 signatures @@ -1690,7 +1710,7 @@ mod tests { let signature = pair.sign(msg); crypto::ed25519_batch_verify(&signature, msg, &pair.public()); - crypto::ed25519_batch_verify(&Default::default(), &Vec::new(), &Default::default()); + crypto::ed25519_batch_verify(&zero_ed_sig(), &Vec::new(), &zero_ed_pub()); assert!(!crypto::finish_batch_verify()); @@ -1722,7 +1742,7 @@ mod tests { let signature = pair.sign(msg); crypto::sr25519_batch_verify(&signature, msg, &pair.public()); - crypto::sr25519_batch_verify(&Default::default(), &Vec::new(), &Default::default()); + crypto::sr25519_batch_verify(&zero_sr_sig(), &Vec::new(), &zero_sr_pub()); assert!(!crypto::finish_batch_verify()); }); diff --git a/primitives/keyring/src/ed25519.rs b/primitives/keyring/src/ed25519.rs index 65341a360579..4d99de6c59d7 100644 --- a/primitives/keyring/src/ed25519.rs +++ b/primitives/keyring/src/ed25519.rs @@ -21,7 +21,7 @@ use lazy_static::lazy_static; pub use sp_core::ed25519; use sp_core::{ ed25519::{Pair, Public, Signature}, - Pair as PairT, Public as PublicT, H256, + ByteArray, Pair as PairT, H256, }; use sp_runtime::AccountId32; use std::{collections::HashMap, ops::Deref}; diff --git a/primitives/keyring/src/sr25519.rs b/primitives/keyring/src/sr25519.rs index 604c330b1ea1..d400cde035b7 100644 --- a/primitives/keyring/src/sr25519.rs +++ b/primitives/keyring/src/sr25519.rs @@ -21,7 +21,7 @@ use lazy_static::lazy_static; pub use sp_core::sr25519; use sp_core::{ sr25519::{Pair, Public, Signature}, - Pair as PairT, Public as PublicT, H256, + ByteArray, Pair as PairT, H256, }; use sp_runtime::AccountId32; use std::{collections::HashMap, ops::Deref}; diff --git a/primitives/keystore/src/testing.rs b/primitives/keystore/src/testing.rs index 718ba798dc0f..92a73eb98c90 100644 --- a/primitives/keystore/src/testing.rs +++ b/primitives/keystore/src/testing.rs @@ -18,7 +18,7 @@ //! Types that should only be used for testing! use sp_core::{ - crypto::{CryptoTypePublicPair, KeyTypeId, Pair, Public}, + crypto::{ByteArray, CryptoTypePublicPair, KeyTypeId, Pair}, ecdsa, ed25519, sr25519, }; @@ -340,20 +340,20 @@ impl SyncCryptoStore for KeyStore { match key.0 { ed25519::CRYPTO_ID => { - let key_pair = - self.ed25519_key_pair(id, &ed25519::Public::from_slice(key.1.as_slice())); + let key_pair = self + .ed25519_key_pair(id, &ed25519::Public::from_slice(key.1.as_slice()).unwrap()); key_pair.map(|k| k.sign(msg).encode()).map(Ok).transpose() }, sr25519::CRYPTO_ID => { - let key_pair = - self.sr25519_key_pair(id, &sr25519::Public::from_slice(key.1.as_slice())); + let key_pair = self + .sr25519_key_pair(id, &sr25519::Public::from_slice(key.1.as_slice()).unwrap()); key_pair.map(|k| k.sign(msg).encode()).map(Ok).transpose() }, ecdsa::CRYPTO_ID => { let key_pair = - self.ecdsa_key_pair(id, &ecdsa::Public::from_slice(key.1.as_slice())); + self.ecdsa_key_pair(id, &ecdsa::Public::from_slice(key.1.as_slice()).unwrap()); key_pair.map(|k| k.sign(msg).encode()).map(Ok).transpose() }, diff --git a/primitives/npos-elections/src/lib.rs b/primitives/npos-elections/src/lib.rs index afe85ef53b3a..0b10b4c7c1b8 100644 --- a/primitives/npos-elections/src/lib.rs +++ b/primitives/npos-elections/src/lib.rs @@ -178,7 +178,7 @@ impl Candidate { } /// A vote being casted by a [`Voter`] to a [`Candidate`] is an `Edge`. -#[derive(Clone, Default)] +#[derive(Clone)] pub struct Edge { /// Identifier of the target. /// @@ -193,6 +193,15 @@ pub struct Edge { weight: ExtendedBalance, } +#[cfg(test)] +impl Edge { + fn new(candidate: Candidate, weight: ExtendedBalance) -> Self { + let who = candidate.who.clone(); + let candidate = Rc::new(RefCell::new(candidate)); + Self { weight, who, candidate, load: Default::default() } + } +} + #[cfg(feature = "std")] impl sp_std::fmt::Debug for Edge { fn fmt(&self, f: &mut sp_std::fmt::Formatter<'_>) -> sp_std::fmt::Result { @@ -223,7 +232,12 @@ impl std::fmt::Debug for Voter { impl Voter { /// Create a new `Voter`. pub fn new(who: AccountId) -> Self { - Self { who, ..Default::default() } + Self { + who, + edges: Default::default(), + budget: Default::default(), + load: Default::default(), + } } /// Returns `true` if `self` votes for `target`. @@ -339,7 +353,7 @@ pub struct ElectionResult { /// /// This, at the current version, resembles the `Exposure` defined in the Staking pallet, yet they /// do not necessarily have to be the same. -#[derive(Default, RuntimeDebug, Encode, Decode, Clone, Eq, PartialEq, scale_info::TypeInfo)] +#[derive(RuntimeDebug, Encode, Decode, Clone, Eq, PartialEq, scale_info::TypeInfo)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct Support { /// Total support. @@ -348,6 +362,12 @@ pub struct Support { pub voters: Vec<(AccountId, ExtendedBalance)>, } +impl Default for Support { + fn default() -> Self { + Self { total: Default::default(), voters: vec![] } + } +} + /// A target-major representation of the the election outcome. /// /// Essentially a flat variant of [`SupportMap`]. @@ -461,7 +481,15 @@ pub fn setup_inputs( .enumerate() .map(|(idx, who)| { c_idx_cache.insert(who.clone(), idx); - Candidate { who, ..Default::default() }.to_ptr() + Candidate { + who, + score: Default::default(), + approval_stake: Default::default(), + backed_stake: Default::default(), + elected: Default::default(), + round: Default::default(), + } + .to_ptr() }) .collect::>>(); @@ -482,7 +510,8 @@ pub fn setup_inputs( edges.push(Edge { who: v.clone(), candidate: Rc::clone(&candidates[*idx]), - ..Default::default() + load: Default::default(), + weight: Default::default(), }); } // else {} would be wrong votes. We don't really care about it. } diff --git a/primitives/npos-elections/src/pjr.rs b/primitives/npos-elections/src/pjr.rs index e27acf1408f9..50556ea9cc33 100644 --- a/primitives/npos-elections/src/pjr.rs +++ b/primitives/npos-elections/src/pjr.rs @@ -287,7 +287,15 @@ fn prepare_pjr_input( let elected = maybe_support.is_some(); let backed_stake = maybe_support.map(|support| support.total).unwrap_or_default(); - Candidate { who, elected, backed_stake, ..Default::default() }.to_ptr() + Candidate { + who, + elected, + backed_stake, + score: Default::default(), + approval_stake: Default::default(), + round: Default::default(), + } + .to_ptr() }) .collect::>(); @@ -315,14 +323,14 @@ fn prepare_pjr_input( who: t, candidate: Rc::clone(&candidates[*idx]), weight, - ..Default::default() + load: Default::default(), }); } } let who = v; let budget: ExtendedBalance = w.into(); - Voter { who, budget, edges, ..Default::default() } + Voter { who, budget, edges, load: Default::default() } }) .collect::>(); @@ -387,7 +395,14 @@ mod tests { .into_iter() .map(|(t, w, e)| { budget += w; - Candidate { who: t, elected: e, backed_stake: w, ..Default::default() } + Candidate { + who: t, + elected: e, + backed_stake: w, + score: Default::default(), + approval_stake: Default::default(), + round: Default::default(), + } }) .collect::>(); let edges = candidates @@ -396,7 +411,7 @@ mod tests { who: c.who, weight: c.backed_stake, candidate: c.to_ptr(), - ..Default::default() + load: Default::default(), }) .collect::>(); voter.edges = edges; @@ -432,7 +447,15 @@ mod tests { // will give 10 slack. let v3 = setup_voter(30, vec![(1, 20, true), (2, 20, true), (3, 0, false)]); - let unelected = Candidate { who: 3u32, elected: false, ..Default::default() }.to_ptr(); + let unelected = Candidate { + who: 3u32, + elected: false, + score: Default::default(), + approval_stake: Default::default(), + backed_stake: Default::default(), + round: Default::default(), + } + .to_ptr(); let score = pre_score(unelected, &vec![v1, v2, v3], 15); assert_eq!(score, 15); diff --git a/primitives/npos-elections/src/reduce.rs b/primitives/npos-elections/src/reduce.rs index 8b90796af85c..8ff0244b4694 100644 --- a/primitives/npos-elections/src/reduce.rs +++ b/primitives/npos-elections/src/reduce.rs @@ -55,7 +55,6 @@ use sp_arithmetic::traits::{Bounded, Zero}; use sp_std::{ collections::btree_map::{BTreeMap, Entry::*}, prelude::*, - vec, }; /// Map type used for reduce_4. Can be easily swapped with HashMap. @@ -356,7 +355,7 @@ fn reduce_all(assignments: &mut Vec>) -> u32 .or_insert_with(|| Node::new(target_id).into_ref()) .clone(); - // If one exists but the other one doesn't, or if both does not, then set the existing + // If one exists but the other one doesn't, or if both do not, then set the existing // one as the parent of the non-existing one and move on. Else, continue with the rest // of the code. match (voter_exists, target_exists) { @@ -390,39 +389,44 @@ fn reduce_all(assignments: &mut Vec>) -> u32 let common_count = trailing_common(&voter_root_path, &target_root_path); // because roots are the same. - #[cfg(feature = "std")] - debug_assert_eq!(target_root_path.last().unwrap(), voter_root_path.last().unwrap()); + //debug_assert_eq!(target_root_path.last().unwrap(), + // voter_root_path.last().unwrap()); TODO: @kian + // the common path must be non-void.. debug_assert!(common_count > 0); + // and smaller than btoh + debug_assert!(common_count <= voter_root_path.len()); + debug_assert!(common_count <= target_root_path.len()); // cycle part of each path will be `path[path.len() - common_count - 1 : 0]` // NOTE: the order of chaining is important! it is always build from [target, ..., // voter] let cycle = target_root_path .iter() - .take(target_root_path.len() - common_count + 1) + .take(target_root_path.len().saturating_sub(common_count).saturating_add(1)) .cloned() .chain( voter_root_path .iter() - .take(voter_root_path.len() - common_count) + .take(voter_root_path.len().saturating_sub(common_count)) .rev() .cloned(), ) .collect::>>(); // a cycle's length shall always be multiple of two. - #[cfg(feature = "std")] debug_assert_eq!(cycle.len() % 2, 0); // find minimum of cycle. let mut min_value: ExtendedBalance = Bounded::max_value(); - // The voter and the target pair that create the min edge. - let mut min_target: A = Default::default(); - let mut min_voter: A = Default::default(); + // The voter and the target pair that create the min edge. These MUST be set by the + // end of this code block, otherwise we skip. + let mut maybe_min_target: Option = None; + let mut maybe_min_voter: Option = None; // The index of the min in opaque cycle list. - let mut min_index = 0usize; + let mut maybe_min_index: Option = None; // 1 -> next // 0 -> prev - let mut min_direction = 0u32; + let mut maybe_min_direction: Option = None; + // helpers let next_index = |i| { if i < (cycle.len() - 1) { @@ -438,6 +442,7 @@ fn reduce_all(assignments: &mut Vec>) -> u32 cycle.len() - 1 } }; + for i in 0..cycle.len() { if cycle[i].borrow().id.role == NodeRole::Voter { // NOTE: sadly way too many clones since I don't want to make A: Copy @@ -448,10 +453,10 @@ fn reduce_all(assignments: &mut Vec>) -> u32 ass.distribution.iter().find(|d| d.0 == next).map(|(_, w)| { if *w < min_value { min_value = *w; - min_target = next.clone(); - min_voter = current.clone(); - min_index = i; - min_direction = 1; + maybe_min_target = Some(next.clone()); + maybe_min_voter = Some(current.clone()); + maybe_min_index = Some(i); + maybe_min_direction = Some(1); } }) }); @@ -459,16 +464,39 @@ fn reduce_all(assignments: &mut Vec>) -> u32 ass.distribution.iter().find(|d| d.0 == prev).map(|(_, w)| { if *w < min_value { min_value = *w; - min_target = prev.clone(); - min_voter = current.clone(); - min_index = i; - min_direction = 0; + maybe_min_target = Some(prev.clone()); + maybe_min_voter = Some(current.clone()); + maybe_min_index = Some(i); + maybe_min_direction = Some(0); } }) }); } } + // all of these values must be set by now, we assign them to un-mut values, no + // longer being optional either. + let (min_value, min_target, min_voter, min_index, min_direction) = + match ( + min_value, + maybe_min_target, + maybe_min_voter, + maybe_min_index, + maybe_min_direction, + ) { + ( + min_value, + Some(min_target), + Some(min_voter), + Some(min_index), + Some(min_direction), + ) => (min_value, min_target, min_voter, min_index, min_direction), + _ => { + sp_runtime::print("UNREACHABLE code reached in `reduce` algorithm. This must be a bug."); + break + }, + }; + // if the min edge is in the voter's sub-chain. // [target, ..., X, Y, ... voter] let target_chunk = target_root_path.len() - common_count; @@ -624,8 +652,8 @@ fn reduce_all(assignments: &mut Vec>) -> u32 num_changed } -/// Reduce the given [`Vec>`]. This removes redundant edges from -/// without changing the overall backing of any of the elected candidates. +/// Reduce the given [`Vec>`]. This removes redundant edges without +/// changing the overall backing of any of the elected candidates. /// /// Returns the number of edges removed. /// diff --git a/primitives/npos-elections/src/tests.rs b/primitives/npos-elections/src/tests.rs index bf9ca57677ef..0aac5c3c35df 100644 --- a/primitives/npos-elections/src/tests.rs +++ b/primitives/npos-elections/src/tests.rs @@ -192,16 +192,15 @@ fn balancing_core_works() { #[test] fn voter_normalize_ops_works() { use crate::{Candidate, Edge}; - use sp_std::{cell::RefCell, rc::Rc}; // normalize { let c1 = Candidate { who: 10, elected: false, ..Default::default() }; let c2 = Candidate { who: 20, elected: false, ..Default::default() }; let c3 = Candidate { who: 30, elected: false, ..Default::default() }; - let e1 = Edge { candidate: Rc::new(RefCell::new(c1)), weight: 30, ..Default::default() }; - let e2 = Edge { candidate: Rc::new(RefCell::new(c2)), weight: 33, ..Default::default() }; - let e3 = Edge { candidate: Rc::new(RefCell::new(c3)), weight: 30, ..Default::default() }; + let e1 = Edge::new(c1, 30); + let e2 = Edge::new(c2, 33); + let e3 = Edge::new(c3, 30); let mut v = Voter { who: 1, budget: 100, edges: vec![e1, e2, e3], ..Default::default() }; @@ -214,9 +213,9 @@ fn voter_normalize_ops_works() { let c2 = Candidate { who: 20, elected: true, ..Default::default() }; let c3 = Candidate { who: 30, elected: true, ..Default::default() }; - let e1 = Edge { candidate: Rc::new(RefCell::new(c1)), weight: 30, ..Default::default() }; - let e2 = Edge { candidate: Rc::new(RefCell::new(c2)), weight: 33, ..Default::default() }; - let e3 = Edge { candidate: Rc::new(RefCell::new(c3)), weight: 30, ..Default::default() }; + let e1 = Edge::new(c1, 30); + let e2 = Edge::new(c2, 33); + let e3 = Edge::new(c3, 30); let mut v = Voter { who: 1, budget: 100, edges: vec![e1, e2, e3], ..Default::default() }; diff --git a/primitives/npos-elections/src/traits.rs b/primitives/npos-elections/src/traits.rs index 597d7e648fd9..cb24f770cdea 100644 --- a/primitives/npos-elections/src/traits.rs +++ b/primitives/npos-elections/src/traits.rs @@ -36,8 +36,8 @@ use sp_std::{ /// an aggregator trait for a generic type of a voter/target identifier. This usually maps to /// substrate's account id. -pub trait IdentifierT: Clone + Eq + Default + Ord + Debug + codec::Codec {} -impl IdentifierT for T {} +pub trait IdentifierT: Clone + Eq + Ord + Debug + codec::Codec {} +impl IdentifierT for T {} /// Aggregator trait for a PerThing that can be multiplied by u128 (ExtendedBalance). pub trait PerThing128: PerThing + Mul {} diff --git a/primitives/runtime/src/generic/checked_extrinsic.rs b/primitives/runtime/src/generic/checked_extrinsic.rs index b2044a6cf74f..f65e4ead089f 100644 --- a/primitives/runtime/src/generic/checked_extrinsic.rs +++ b/primitives/runtime/src/generic/checked_extrinsic.rs @@ -70,20 +70,26 @@ where info: &DispatchInfoOf, len: usize, ) -> crate::ApplyExtrinsicResultWithInfo> { - let (maybe_who, pre) = if let Some((id, extra)) = self.signed { + let (maybe_who, maybe_pre) = if let Some((id, extra)) = self.signed { let pre = Extra::pre_dispatch(extra, &id, &self.function, info, len)?; - (Some(id), pre) + (Some(id), Some(pre)) } else { - let pre = Extra::pre_dispatch_unsigned(&self.function, info, len)?; + Extra::pre_dispatch_unsigned(&self.function, info, len)?; U::pre_dispatch(&self.function)?; - (None, pre) + (None, None) }; let res = self.function.dispatch(Origin::from(maybe_who)); let post_info = match res { Ok(info) => info, Err(err) => err.post_info, }; - Extra::post_dispatch(pre, info, &post_info, len, &res.map(|_| ()).map_err(|e| e.error))?; + Extra::post_dispatch( + maybe_pre, + info, + &post_info, + len, + &res.map(|_| ()).map_err(|e| e.error), + )?; Ok(res) } } diff --git a/primitives/runtime/src/generic/unchecked_extrinsic.rs b/primitives/runtime/src/generic/unchecked_extrinsic.rs index 95f4f2f3584d..53e7c349f2a7 100644 --- a/primitives/runtime/src/generic/unchecked_extrinsic.rs +++ b/primitives/runtime/src/generic/unchecked_extrinsic.rs @@ -364,7 +364,7 @@ mod tests { use crate::{ codec::{Decode, Encode}, testing::TestSignature as TestSig, - traits::{IdentityLookup, SignedExtension}, + traits::{DispatchInfoOf, IdentityLookup, SignedExtension}, }; use sp_io::hashing::blake2_256; @@ -387,6 +387,16 @@ mod tests { fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { Ok(()) } + + fn pre_dispatch( + self, + who: &Self::AccountId, + call: &Self::Call, + info: &DispatchInfoOf, + len: usize, + ) -> Result { + Ok(self.validate(who, call, info, len).map(|_| ())?) + } } type Ex = UncheckedExtrinsic; diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 10fd39d38f4c..26db5ef081a8 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -44,7 +44,7 @@ pub use sp_application_crypto as app_crypto; pub use sp_core::storage::{Storage, StorageChild}; use sp_core::{ - crypto::{self, Public}, + crypto::{self, ByteArray}, ecdsa, ed25519, hash::{H256, H512}, sr25519, @@ -284,12 +284,6 @@ impl TryFrom for ecdsa::Signature { } } -impl Default for MultiSignature { - fn default() -> Self { - Self::Ed25519(Default::default()) - } -} - /// Public key for any known crypto algorithm. #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Encode, Decode, RuntimeDebug, TypeInfo)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] @@ -302,12 +296,6 @@ pub enum MultiSigner { Ecdsa(ecdsa::Public), } -impl Default for MultiSigner { - fn default() -> Self { - Self::Ed25519(Default::default()) - } -} - /// NOTE: This implementations is required by `SimpleAddressDeterminer`, /// we convert the hash into some AccountId, it's fine to use any scheme. impl> crypto::UncheckedFrom for MultiSigner { @@ -403,10 +391,14 @@ impl Verify for MultiSignature { type Signer = MultiSigner; fn verify>(&self, mut msg: L, signer: &AccountId32) -> bool { match (self, signer) { - (Self::Ed25519(ref sig), who) => - sig.verify(msg, &ed25519::Public::from_slice(who.as_ref())), - (Self::Sr25519(ref sig), who) => - sig.verify(msg, &sr25519::Public::from_slice(who.as_ref())), + (Self::Ed25519(ref sig), who) => match ed25519::Public::from_slice(who.as_ref()) { + Ok(signer) => sig.verify(msg, &signer), + Err(()) => false, + }, + (Self::Sr25519(ref sig), who) => match sr25519::Public::from_slice(who.as_ref()) { + Ok(signer) => sig.verify(msg, &signer), + Err(()) => false, + }, (Self::Ecdsa(ref sig), who) => { let m = sp_io::hashing::blake2_256(msg.get()); match sp_io::crypto::secp256k1_ecdsa_recover_compressed(sig.as_ref(), &m) { @@ -433,7 +425,10 @@ impl Verify for AnySignature { .map(|s| s.verify(msg, signer)) .unwrap_or(false) || ed25519::Signature::try_from(self.0.as_fixed_bytes().as_ref()) - .map(|s| s.verify(msg, &ed25519::Public::from_slice(signer.as_ref()))) + .map(|s| match ed25519::Public::from_slice(signer.as_ref()) { + Err(()) => false, + Ok(signer) => s.verify(msg, &signer), + }) .unwrap_or(false) } } @@ -924,7 +919,7 @@ mod tests { use super::*; use codec::{Decode, Encode}; - use sp_core::crypto::Pair; + use sp_core::crypto::{Pair, UncheckedFrom}; use sp_io::TestExternalities; use sp_state_machine::create_proof_check_backend; @@ -1010,7 +1005,9 @@ mod tests { ext.execute_with(|| { let _batching = SignatureBatching::start(); - sp_io::crypto::sr25519_verify(&Default::default(), &Vec::new(), &Default::default()); + let dummy = UncheckedFrom::unchecked_from([1; 32]); + let dummy_sig = UncheckedFrom::unchecked_from([1; 64]); + sp_io::crypto::sr25519_verify(&dummy_sig, &Vec::new(), &dummy); }); } diff --git a/primitives/runtime/src/multiaddress.rs b/primitives/runtime/src/multiaddress.rs index 46d80608352d..629099d85d72 100644 --- a/primitives/runtime/src/multiaddress.rs +++ b/primitives/runtime/src/multiaddress.rs @@ -62,9 +62,3 @@ impl From for MultiAddress Default for MultiAddress { - fn default() -> Self { - Self::Id(Default::default()) - } -} diff --git a/primitives/runtime/src/testing.rs b/primitives/runtime/src/testing.rs index 4573bc84473a..46e7ee634c25 100644 --- a/primitives/runtime/src/testing.rs +++ b/primitives/runtime/src/testing.rs @@ -30,7 +30,7 @@ use crate::{ }; use serde::{de::Error as DeError, Deserialize, Deserializer, Serialize, Serializer}; use sp_core::{ - crypto::{key_types, CryptoType, Dummy, Public}, + crypto::{key_types, ByteArray, CryptoType, Dummy}, U256, }; pub use sp_core::{sr25519, H256}; @@ -77,10 +77,10 @@ impl From for u64 { } impl UintAuthorityId { - /// Convert this authority id into a public key. - pub fn to_public_key(&self) -> T { + /// Convert this authority ID into a public key. + pub fn to_public_key(&self) -> T { let bytes: [u8; 32] = U256::from(self.0).into(); - T::from_slice(&bytes) + T::from_slice(&bytes).unwrap() } } diff --git a/primitives/runtime/src/traits.rs b/primitives/runtime/src/traits.rs index f61de70e3519..0ddd8cae93ea 100644 --- a/primitives/runtime/src/traits.rs +++ b/primitives/runtime/src/traits.rs @@ -851,7 +851,7 @@ pub trait SignedExtension: type AdditionalSigned: Encode + TypeInfo; /// The type that encodes information that can be passed from pre_dispatch to post-dispatch. - type Pre: Default; + type Pre; /// Construct any additional data that should be in the signed payload of the transaction. Can /// also perform any pre-signature-verification checks and return an error if needed. @@ -890,11 +890,7 @@ pub trait SignedExtension: call: &Self::Call, info: &DispatchInfoOf, len: usize, - ) -> Result { - self.validate(who, call, info, len) - .map(|_| Self::Pre::default()) - .map_err(Into::into) - } + ) -> Result; /// Validate an unsigned transaction for the transaction queue. /// @@ -924,14 +920,15 @@ pub trait SignedExtension: call: &Self::Call, info: &DispatchInfoOf, len: usize, - ) -> Result { - Self::validate_unsigned(call, info, len) - .map(|_| Self::Pre::default()) - .map_err(Into::into) + ) -> Result<(), TransactionValidityError> { + Self::validate_unsigned(call, info, len).map(|_| ()).map_err(Into::into) } /// Do any post-flight stuff for an extrinsic. /// + /// If the transaction is signed, then `_pre` will contain the output of `pre_dispatch`, + /// and `None` otherwise. + /// /// This gets given the `DispatchResult` `_result` from the extrinsic and can, if desired, /// introduce a `TransactionValidityError`, causing the block to become invalid for including /// it. @@ -944,7 +941,7 @@ pub trait SignedExtension: /// introduced by the current block author; generally this implies that it is an inherent and /// will come from either an offchain-worker or via `InherentData`. fn post_dispatch( - _pre: Self::Pre, + _pre: Option, _info: &DispatchInfoOf, _post_info: &PostDispatchInfoOf, _len: usize, @@ -1029,18 +1026,26 @@ impl SignedExtension for Tuple { call: &Self::Call, info: &DispatchInfoOf, len: usize, - ) -> Result { - Ok(for_tuples!( ( #( Tuple::pre_dispatch_unsigned(call, info, len)? ),* ) )) + ) -> Result<(), TransactionValidityError> { + for_tuples!( #( Tuple::pre_dispatch_unsigned(call, info, len)?; )* ); + Ok(()) } fn post_dispatch( - pre: Self::Pre, + pre: Option, info: &DispatchInfoOf, post_info: &PostDispatchInfoOf, len: usize, result: &DispatchResult, ) -> Result<(), TransactionValidityError> { - for_tuples!( #( Tuple::post_dispatch(pre.Tuple, info, post_info, len, result)?; )* ); + match pre { + Some(x) => { + for_tuples!( #( Tuple::post_dispatch(Some(x.Tuple), info, post_info, len, result)?; )* ); + }, + None => { + for_tuples!( #( Tuple::post_dispatch(None, info, post_info, len, result)?; )* ); + }, + } Ok(()) } @@ -1062,6 +1067,15 @@ impl SignedExtension for () { fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { Ok(()) } + fn pre_dispatch( + self, + who: &Self::AccountId, + call: &Self::Call, + info: &DispatchInfoOf, + len: usize, + ) -> Result { + Ok(self.validate(who, call, info, len).map(|_| ())?) + } } /// An "executable" piece of information, used by the standard Substrate Executive in order to @@ -1212,6 +1226,11 @@ impl<'a> TrailingZeroInput<'a> { pub fn new(data: &'a [u8]) -> Self { Self(data) } + + /// Create a new instance which only contains zeroes as input. + pub fn zeroes() -> Self { + Self::new(&[][..]) + } } impl<'a> codec::Input for TrailingZeroInput<'a> { @@ -1260,11 +1279,11 @@ pub trait AccountIdConversion: Sized { /// Format is TYPE_ID ++ encode(parachain ID) ++ 00.... where 00... is indefinite trailing zeroes to /// fill AccountId. -impl AccountIdConversion for Id { +impl AccountIdConversion for Id { fn into_sub_account(&self, sub: S) -> T { (Id::TYPE_ID, self, sub) .using_encoded(|b| T::decode(&mut TrailingZeroInput(b))) - .unwrap_or_default() + .expect("`AccountId` type is never greater than 32 bytes; qed") } fn try_from_sub_account(x: &T) -> Option<(Self, S)> { @@ -1317,7 +1336,7 @@ macro_rules! impl_opaque_keys_inner { ) => { $( #[ $attr ] )* #[derive( - Default, Clone, PartialEq, Eq, + Clone, PartialEq, Eq, $crate::codec::Encode, $crate::codec::Decode, $crate::scale_info::TypeInfo, @@ -1616,7 +1635,10 @@ pub trait BlockNumberProvider { mod tests { use super::*; use crate::codec::{Decode, Encode, Input}; - use sp_core::{crypto::Pair, ecdsa}; + use sp_core::{ + crypto::{Pair, UncheckedFrom}, + ecdsa, + }; mod t { use sp_application_crypto::{app_crypto, sr25519}; @@ -1629,8 +1651,8 @@ mod tests { use super::AppVerify; use t::*; - let s = Signature::default(); - let _ = s.verify(&[0u8; 100][..], &Public::default()); + let s = Signature::try_from(vec![0; 64]).unwrap(); + let _ = s.verify(&[0u8; 100][..], &Public::unchecked_from([0; 32])); } #[derive(Encode, Decode, Default, PartialEq, Debug)] diff --git a/test-utils/runtime/transaction-pool/src/lib.rs b/test-utils/runtime/transaction-pool/src/lib.rs index d0cd50394c53..e80c24b17144 100644 --- a/test-utils/runtime/transaction-pool/src/lib.rs +++ b/test-utils/runtime/transaction-pool/src/lib.rs @@ -25,7 +25,7 @@ use parking_lot::RwLock; use sp_blockchain::CachedHeaderMetadata; use sp_runtime::{ generic::{self, BlockId}, - traits::{BlakeTwo256, Block as BlockT, Hash as HashT, Header as _}, + traits::{BlakeTwo256, Block as BlockT, Hash as HashT, Header as _, TrailingZeroInput}, transaction_validity::{ InvalidTransaction, TransactionSource, TransactionValidity, TransactionValidityError, ValidTransaction, @@ -370,7 +370,8 @@ impl sp_blockchain::HeaderMetadata for TestApi { /// /// Part of the test api. pub fn uxt(who: AccountKeyring, nonce: Index) -> Extrinsic { - let transfer = Transfer { from: who.into(), to: AccountId::default(), nonce, amount: 1 }; + let dummy = codec::Decode::decode(&mut TrailingZeroInput::zeroes()).unwrap(); + let transfer = Transfer { from: who.into(), to: dummy, nonce, amount: 1 }; let signature = transfer.using_encoded(|e| who.sign(e)).into(); Extrinsic::Transfer { transfer, signature, exhaust_resources_when_not_first: false } } diff --git a/test-utils/test-runner/src/node.rs b/test-utils/test-runner/src/node.rs index 5fd8e4669c33..421a4b641b59 100644 --- a/test-utils/test-runner/src/node.rs +++ b/test-utils/test-runner/src/node.rs @@ -195,7 +195,11 @@ where { let signed_data = if let Some(signer) = signer { let extra = self.with_state(|| T::signed_extras(signer.clone())); - Some((signer.into(), MultiSignature::Sr25519(Default::default()), extra)) + Some(( + signer.into(), + MultiSignature::Sr25519(sp_core::sr25519::Signature::from_raw([0u8; 64])), + extra, + )) } else { None }; From 3cdb30e1ecbafe8a866317d4550c921b4d686869 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Mon, 13 Dec 2021 21:25:05 +0200 Subject: [PATCH 288/695] beefy: update CODEOWNERS (#10464) Signed-off-by: acatangiu --- docs/CODEOWNERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/CODEOWNERS b/docs/CODEOWNERS index 42d25a0a228f..bf9e589ff487 100644 --- a/docs/CODEOWNERS +++ b/docs/CODEOWNERS @@ -40,6 +40,12 @@ /client/consensus/pow/ @sorpaas /primitives/consensus/pow/ @sorpaas +# BEEFY +/client/beefy/ @acatangiu +/frame/beefy/ @acatangiu +/frame/beefy-mmr/ @acatangiu +/primitives/beefy/ @acatangiu + # Contracts /frame/contracts/ @athei From 49a4b1822e19e5b82c59ba5b36a1d7997f0a3929 Mon Sep 17 00:00:00 2001 From: Koute Date: Tue, 14 Dec 2021 17:26:40 +0900 Subject: [PATCH 289/695] Statically register host WASM functions (#10394) * Statically register host WASM functions * Fix `substrate-test-client` compilation * Move `ExtendedHostFunctions` to `sp-wasm-interface` * Fix `sp-runtime-interface` tests' compilation * Fix `sc-executor-wasmtime` tests' compilation * Use `runtime_interface` macro in `test-runner` * Fix `sc-executor` tests' compilation * Reformatting/`rustfmt` * Add an extra comment regarding the `H` generic arg in `create_runtime` * Even more `rustfmt` * Depend on `wasmtime` without default features in `sp-wasm-interface` * Bump version of `sp-wasm-interface` to 4.0.1 * Bump `sp-wasm-interface` in `Cargo.lock` too * Bump all of the `sp-wasm-interface` requirements to 4.0.1 Maybe this will appease cargo-unleash? * Revert "Bump all of the `sp-wasm-interface` requirements to 4.0.1" This reverts commit 0f7ccf8e0f371542861121b145ab87af6541ac30. * Make `cargo-unleash` happy (maybe) * Use `cargo-unleash` to bump the crates' versions * Align to review comments --- Cargo.lock | 6 +- client/allocator/Cargo.toml | 2 +- client/executor/Cargo.toml | 4 +- client/executor/common/Cargo.toml | 2 +- client/executor/runtime-test/src/lib.rs | 8 + client/executor/src/integration_tests/mod.rs | 42 ++- client/executor/src/lib.rs | 4 +- client/executor/src/native_executor.rs | 89 +++-- client/executor/src/wasm_runtime.rs | 37 +- client/executor/wasmi/Cargo.toml | 4 +- client/executor/wasmtime/Cargo.toml | 4 +- client/executor/wasmtime/src/host.rs | 16 +- client/executor/wasmtime/src/imports.rs | 241 +++++------- .../executor/wasmtime/src/instance_wrapper.rs | 13 +- client/executor/wasmtime/src/runtime.rs | 79 ++-- client/executor/wasmtime/src/tests.rs | 11 +- frame/benchmarking/Cargo.toml | 2 +- primitives/core/Cargo.toml | 2 +- primitives/io/Cargo.toml | 4 +- primitives/runtime-interface/Cargo.toml | 4 +- .../host_function_interface.rs | 354 ++++++++++-------- primitives/runtime-interface/src/impls.rs | 20 +- primitives/runtime-interface/src/lib.rs | 14 +- primitives/runtime-interface/src/pass_by.rs | 12 +- .../test-wasm-deprecated/Cargo.toml | 2 +- .../runtime-interface/test-wasm/Cargo.toml | 2 +- primitives/runtime-interface/test/Cargo.toml | 2 +- primitives/runtime-interface/test/src/lib.rs | 18 +- primitives/sandbox/Cargo.toml | 2 +- primitives/tasks/Cargo.toml | 2 +- primitives/wasm-interface/Cargo.toml | 6 +- primitives/wasm-interface/src/lib.rs | 203 +++++++++- test-utils/client/src/lib.rs | 3 +- test-utils/runtime/Cargo.toml | 2 +- test-utils/test-runner/Cargo.toml | 5 + test-utils/test-runner/src/host_functions.rs | 93 ++--- 36 files changed, 743 insertions(+), 571 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4bed90287893..b576a12ea6f6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9685,7 +9685,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface" -version = "4.0.0" +version = "4.1.0-dev" dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", @@ -9962,12 +9962,14 @@ dependencies = [ [[package]] name = "sp-wasm-interface" -version = "4.0.0" +version = "4.1.0-dev" dependencies = [ "impl-trait-for-tuples", + "log 0.4.14", "parity-scale-codec", "sp-std", "wasmi", + "wasmtime", ] [[package]] diff --git a/client/allocator/Cargo.toml b/client/allocator/Cargo.toml index ea0ce3c0bbea..eb8d298e1ec2 100644 --- a/client/allocator/Cargo.toml +++ b/client/allocator/Cargo.toml @@ -15,6 +15,6 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } -sp-wasm-interface = { version = "4.0.0", path = "../../primitives/wasm-interface" } +sp-wasm-interface = { version = "4.1.0-dev", path = "../../primitives/wasm-interface" } log = "0.4.11" thiserror = "1.0.30" diff --git a/client/executor/Cargo.toml b/client/executor/Cargo.toml index 58d7ec34b20e..377623512fa3 100644 --- a/client/executor/Cargo.toml +++ b/client/executor/Cargo.toml @@ -24,8 +24,8 @@ sp-panic-handler = { version = "4.0.0-dev", path = "../../primitives/panic-handl wasmi = "0.9.1" lazy_static = "1.4.0" sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } -sp-wasm-interface = { version = "4.0.0", path = "../../primitives/wasm-interface" } -sp-runtime-interface = { version = "4.0.0", path = "../../primitives/runtime-interface" } +sp-wasm-interface = { version = "4.1.0-dev", path = "../../primitives/wasm-interface" } +sp-runtime-interface = { version = "4.1.0-dev", path = "../../primitives/runtime-interface" } sp-externalities = { version = "0.10.0", path = "../../primitives/externalities" } sc-executor-common = { version = "0.10.0-dev", path = "common" } sc-executor-wasmi = { version = "0.10.0-dev", path = "wasmi" } diff --git a/client/executor/common/Cargo.toml b/client/executor/common/Cargo.toml index abaee7607303..5edf179c056a 100644 --- a/client/executor/common/Cargo.toml +++ b/client/executor/common/Cargo.toml @@ -20,7 +20,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0" } wasmi = "0.9.1" sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sc-allocator = { version = "4.1.0-dev", path = "../../allocator" } -sp-wasm-interface = { version = "4.0.0", path = "../../../primitives/wasm-interface" } +sp-wasm-interface = { version = "4.1.0-dev", path = "../../../primitives/wasm-interface" } sp-maybe-compressed-blob = { version = "4.1.0-dev", path = "../../../primitives/maybe-compressed-blob" } sp-serializer = { version = "4.0.0-dev", path = "../../../primitives/serializer" } thiserror = "1.0.30" diff --git a/client/executor/runtime-test/src/lib.rs b/client/executor/runtime-test/src/lib.rs index 3ea6e2d7ed1a..01e46ab94635 100644 --- a/client/executor/runtime-test/src/lib.rs +++ b/client/executor/runtime-test/src/lib.rs @@ -332,6 +332,14 @@ sp_core::wasm_export_functions! { fn test_panic_in_spawned() { sp_tasks::spawn(tasks::panicker, vec![]).join(); } + + fn test_return_i8() -> i8 { + -66 + } + + fn test_take_i8(value: i8) { + assert_eq!(value, -66); + } } #[cfg(not(feature = "std"))] diff --git a/client/executor/src/integration_tests/mod.rs b/client/executor/src/integration_tests/mod.rs index 3ff0ecebd9ac..b2b31679926c 100644 --- a/client/executor/src/integration_tests/mod.rs +++ b/client/executor/src/integration_tests/mod.rs @@ -34,7 +34,6 @@ use sp_core::{ use sp_runtime::traits::BlakeTwo256; use sp_state_machine::TestExternalities as CoreTestExternalities; use sp_trie::{trie_types::Layout, TrieConfiguration}; -use sp_wasm_interface::HostFunctions as _; use std::sync::Arc; use tracing_subscriber::layer::SubscriberExt; @@ -124,14 +123,8 @@ fn call_in_wasm( execution_method: WasmExecutionMethod, ext: &mut E, ) -> Result, String> { - let executor = crate::WasmExecutor::new( - execution_method, - Some(1024), - HostFunctions::host_functions(), - 8, - None, - 2, - ); + let executor = + crate::WasmExecutor::::new(execution_method, Some(1024), 8, None, 2); executor.uncached_call( RuntimeBlob::uncompress_if_needed(&wasm_binary_unwrap()[..]).unwrap(), ext, @@ -475,10 +468,9 @@ test_wasm_execution!(should_trap_when_heap_exhausted); fn should_trap_when_heap_exhausted(wasm_method: WasmExecutionMethod) { let mut ext = TestExternalities::default(); - let executor = crate::WasmExecutor::new( + let executor = crate::WasmExecutor::::new( wasm_method, Some(17), // `17` is the initial number of pages compiled into the binary. - HostFunctions::host_functions(), 8, None, 2, @@ -501,11 +493,10 @@ fn mk_test_runtime(wasm_method: WasmExecutionMethod, pages: u64) -> Arc( wasm_method, pages, blob, - HostFunctions::host_functions(), true, None, ) @@ -589,10 +580,9 @@ fn heap_is_reset_between_calls(wasm_method: WasmExecutionMethod) { test_wasm_execution!(parallel_execution); fn parallel_execution(wasm_method: WasmExecutionMethod) { - let executor = std::sync::Arc::new(crate::WasmExecutor::new( + let executor = std::sync::Arc::new(crate::WasmExecutor::::new( wasm_method, Some(1024), - HostFunctions::host_functions(), 8, None, 2, @@ -763,11 +753,10 @@ fn memory_is_cleared_between_invocations(wasm_method: WasmExecutionMethod) { ) )"#).unwrap(); - let runtime = crate::wasm_runtime::create_wasm_runtime_with_code( + let runtime = crate::wasm_runtime::create_wasm_runtime_with_code::( wasm_method, 1024, RuntimeBlob::uncompress_if_needed(&binary[..]).unwrap(), - HostFunctions::host_functions(), true, None, ) @@ -780,3 +769,22 @@ fn memory_is_cleared_between_invocations(wasm_method: WasmExecutionMethod) { let res = instance.call_export("returns_no_bss_mutable_static", &[0]).unwrap(); assert_eq!(1, u64::decode(&mut &res[..]).unwrap()); } + +test_wasm_execution!(return_i8); +fn return_i8(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + let mut ext = ext.ext(); + + assert_eq!( + call_in_wasm("test_return_i8", &[], wasm_method, &mut ext).unwrap(), + (-66_i8).encode() + ); +} + +test_wasm_execution!(take_i8); +fn take_i8(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + let mut ext = ext.ext(); + + call_in_wasm("test_take_i8", &(-66_i8).encode(), wasm_method, &mut ext).unwrap(); +} diff --git a/client/executor/src/lib.rs b/client/executor/src/lib.rs index 9a4d8e3cf0b6..8bac541afc37 100644 --- a/client/executor/src/lib.rs +++ b/client/executor/src/lib.rs @@ -67,17 +67,15 @@ mod tests { use sc_executor_common::runtime_blob::RuntimeBlob; use sc_runtime_test::wasm_binary_unwrap; use sp_io::TestExternalities; - use sp_wasm_interface::HostFunctions; #[test] fn call_in_interpreted_wasm_works() { let mut ext = TestExternalities::default(); let mut ext = ext.ext(); - let executor = WasmExecutor::new( + let executor = WasmExecutor::::new( WasmExecutionMethod::Interpreted, Some(8), - sp_io::SubstrateHostFunctions::host_functions(), 8, None, 2, diff --git a/client/executor/src/native_executor.rs b/client/executor/src/native_executor.rs index 1c01520ac9c8..60e661d10da6 100644 --- a/client/executor/src/native_executor.rs +++ b/client/executor/src/native_executor.rs @@ -24,6 +24,7 @@ use crate::{ use std::{ collections::HashMap, + marker::PhantomData, panic::{AssertUnwindSafe, UnwindSafe}, path::PathBuf, result, @@ -46,7 +47,7 @@ use sp_core::{ use sp_externalities::ExternalitiesExt as _; use sp_tasks::new_async_externalities; use sp_version::{GetNativeVersion, NativeVersion, RuntimeVersion}; -use sp_wasm_interface::{Function, HostFunctions}; +use sp_wasm_interface::{ExtendedHostFunctions, HostFunctions}; /// Default num of pages for the heap const DEFAULT_HEAP_PAGES: u64 = 2048; @@ -91,22 +92,36 @@ pub trait NativeExecutionDispatch: Send + Sync { /// An abstraction over Wasm code executor. Supports selecting execution backend and /// manages runtime cache. -#[derive(Clone)] -pub struct WasmExecutor { +pub struct WasmExecutor { /// Method used to execute fallback Wasm code. method: WasmExecutionMethod, /// The number of 64KB pages to allocate for Wasm execution. default_heap_pages: u64, - /// The host functions registered with this instance. - host_functions: Arc>, /// WASM runtime cache. cache: Arc, /// The path to a directory which the executor can leverage for a file cache, e.g. put there /// compiled artifacts. cache_path: Option, + + phantom: PhantomData, +} + +impl Clone for WasmExecutor { + fn clone(&self) -> Self { + Self { + method: self.method, + default_heap_pages: self.default_heap_pages, + cache: self.cache.clone(), + cache_path: self.cache_path.clone(), + phantom: self.phantom, + } + } } -impl WasmExecutor { +impl WasmExecutor +where + H: HostFunctions, +{ /// Create new instance. /// /// # Parameters @@ -127,7 +142,6 @@ impl WasmExecutor { pub fn new( method: WasmExecutionMethod, default_heap_pages: Option, - host_functions: Vec<&'static dyn Function>, max_runtime_instances: usize, cache_path: Option, runtime_cache_size: u8, @@ -135,13 +149,13 @@ impl WasmExecutor { WasmExecutor { method, default_heap_pages: default_heap_pages.unwrap_or(DEFAULT_HEAP_PAGES), - host_functions: Arc::new(host_functions), cache: Arc::new(RuntimeCache::new( max_runtime_instances, cache_path.clone(), runtime_cache_size, )), cache_path, + phantom: PhantomData, } } @@ -173,12 +187,11 @@ impl WasmExecutor { AssertUnwindSafe<&mut dyn Externalities>, ) -> Result>, { - match self.cache.with_instance( + match self.cache.with_instance::( runtime_code, ext, self.method, self.default_heap_pages, - &*self.host_functions, allow_missing_host_functions, |module, instance, version, ext| { let module = AssertUnwindSafe(module); @@ -208,11 +221,10 @@ impl WasmExecutor { export_name: &str, call_data: &[u8], ) -> std::result::Result, String> { - let module = crate::wasm_runtime::create_wasm_runtime_with_code( + let module = crate::wasm_runtime::create_wasm_runtime_with_code::( self.method, self.default_heap_pages, runtime_blob, - self.host_functions.to_vec(), allow_missing_host_functions, self.cache_path.as_deref(), ) @@ -235,7 +247,10 @@ impl WasmExecutor { } } -impl sp_core::traits::ReadRuntimeVersion for WasmExecutor { +impl sp_core::traits::ReadRuntimeVersion for WasmExecutor +where + H: HostFunctions, +{ fn read_runtime_version( &self, wasm_code: &[u8], @@ -269,7 +284,10 @@ impl sp_core::traits::ReadRuntimeVersion for WasmExecutor { } } -impl CodeExecutor for WasmExecutor { +impl CodeExecutor for WasmExecutor +where + H: HostFunctions, +{ type Error = Error; fn call< @@ -299,7 +317,10 @@ impl CodeExecutor for WasmExecutor { } } -impl RuntimeVersionOf for WasmExecutor { +impl RuntimeVersionOf for WasmExecutor +where + H: HostFunctions, +{ fn runtime_version( &self, ext: &mut dyn Externalities, @@ -313,13 +334,17 @@ impl RuntimeVersionOf for WasmExecutor { /// A generic `CodeExecutor` implementation that uses a delegate to determine wasm code equivalence /// and dispatch to native code when possible, falling back on `WasmExecutor` when not. -pub struct NativeElseWasmExecutor { +pub struct NativeElseWasmExecutor +where + D: NativeExecutionDispatch, +{ /// Dummy field to avoid the compiler complaining about us not using `D`. _dummy: std::marker::PhantomData, /// Native runtime version info. native_version: NativeVersion, /// Fallback wasm executor. - wasm: WasmExecutor, + wasm: + WasmExecutor>, } impl NativeElseWasmExecutor { @@ -337,24 +362,9 @@ impl NativeElseWasmExecutor { max_runtime_instances: usize, runtime_cache_size: u8, ) -> Self { - let extended = D::ExtendHostFunctions::host_functions(); - let mut host_functions = sp_io::SubstrateHostFunctions::host_functions() - .into_iter() - // filter out any host function overrides provided. - .filter(|host_fn| { - extended - .iter() - .find(|ext_host_fn| host_fn.name() == ext_host_fn.name()) - .is_none() - }) - .collect::>(); - - // Add the custom host functions provided by the user. - host_functions.extend(extended); let wasm_executor = WasmExecutor::new( fallback_method, default_heap_pages, - host_functions, max_runtime_instances, None, runtime_cache_size, @@ -645,8 +655,21 @@ mod tests { 8, 2, ); + + fn extract_host_functions( + _: &WasmExecutor, + ) -> Vec<&'static dyn sp_wasm_interface::Function> + where + H: HostFunctions, + { + H::host_functions() + } + my_interface::HostFunctions::host_functions().iter().for_each(|function| { - assert_eq!(executor.wasm.host_functions.iter().filter(|f| f == &function).count(), 2); + assert_eq!( + extract_host_functions(&executor.wasm).iter().filter(|f| f == &function).count(), + 2 + ); }); my_interface::say_hello_world("hey"); diff --git a/client/executor/src/wasm_runtime.rs b/client/executor/src/wasm_runtime.rs index 44ed6eb32304..cebfc7b01b8d 100644 --- a/client/executor/src/wasm_runtime.rs +++ b/client/executor/src/wasm_runtime.rs @@ -37,7 +37,7 @@ use std::{ sync::Arc, }; -use sp_wasm_interface::Function; +use sp_wasm_interface::HostFunctions; /// Specification of different methods of executing the runtime Wasm code. #[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)] @@ -199,14 +199,14 @@ impl RuntimeCache { /// /// `wasm_method` - Type of WASM backend to use. /// - /// `host_functions` - The host functions that should be registered for the Wasm runtime. - /// /// `allow_missing_func_imports` - Ignore missing function imports. /// /// `max_runtime_instances` - The size of the instances cache. /// /// `f` - Function to execute. /// + /// `H` - A compile-time list of host functions to expose to the runtime. + /// /// # Returns result of `f` wrapped in an additional result. /// In case of failure one of two errors can be returned: /// @@ -214,17 +214,17 @@ impl RuntimeCache { /// /// `Error::InvalidMemoryReference` is returned if no memory export with the /// identifier `memory` can be found in the runtime. - pub fn with_instance<'c, R, F>( + pub fn with_instance<'c, H, R, F>( &self, runtime_code: &'c RuntimeCode<'c>, ext: &mut dyn Externalities, wasm_method: WasmExecutionMethod, default_heap_pages: u64, - host_functions: &[&'static dyn Function], allow_missing_func_imports: bool, f: F, ) -> Result, Error> where + H: HostFunctions, F: FnOnce( &Arc, &mut dyn WasmInstance, @@ -247,12 +247,11 @@ impl RuntimeCache { let time = std::time::Instant::now(); - let result = create_versioned_wasm_runtime( + let result = create_versioned_wasm_runtime::( &code, ext, wasm_method, heap_pages, - host_functions.into(), allow_missing_func_imports, self.max_runtime_instances, self.cache_path.as_deref(), @@ -288,14 +287,16 @@ impl RuntimeCache { } /// Create a wasm runtime with the given `code`. -pub fn create_wasm_runtime_with_code( +pub fn create_wasm_runtime_with_code( wasm_method: WasmExecutionMethod, heap_pages: u64, blob: RuntimeBlob, - host_functions: Vec<&'static dyn Function>, allow_missing_func_imports: bool, cache_path: Option<&Path>, -) -> Result, WasmError> { +) -> Result, WasmError> +where + H: HostFunctions, +{ match wasm_method { WasmExecutionMethod::Interpreted => { // Wasmi doesn't have any need in a cache directory. @@ -307,13 +308,13 @@ pub fn create_wasm_runtime_with_code( sc_executor_wasmi::create_runtime( blob, heap_pages, - host_functions, + H::host_functions(), allow_missing_func_imports, ) .map(|runtime| -> Arc { Arc::new(runtime) }) }, #[cfg(feature = "wasmtime")] - WasmExecutionMethod::Compiled => sc_executor_wasmtime::create_runtime( + WasmExecutionMethod::Compiled => sc_executor_wasmtime::create_runtime::( blob, sc_executor_wasmtime::Config { heap_pages, @@ -327,7 +328,6 @@ pub fn create_wasm_runtime_with_code( parallel_compilation: true, }, }, - host_functions, ) .map(|runtime| -> Arc { Arc::new(runtime) }), } @@ -392,16 +392,18 @@ pub fn read_embedded_version(blob: &RuntimeBlob) -> Result( code: &[u8], ext: &mut dyn Externalities, wasm_method: WasmExecutionMethod, heap_pages: u64, - host_functions: Vec<&'static dyn Function>, allow_missing_func_imports: bool, max_instances: usize, cache_path: Option<&Path>, -) -> Result { +) -> Result +where + H: HostFunctions, +{ // The incoming code may be actually compressed. We decompress it here and then work with // the uncompressed code from now on. let blob = sc_executor_common::runtime_blob::RuntimeBlob::uncompress_if_needed(&code)?; @@ -411,11 +413,10 @@ fn create_versioned_wasm_runtime( // runtime. let mut version: Option<_> = read_embedded_version(&blob)?; - let runtime = create_wasm_runtime_with_code( + let runtime = create_wasm_runtime_with_code::( wasm_method, heap_pages, blob, - host_functions, allow_missing_func_imports, cache_path, )?; diff --git a/client/executor/wasmi/Cargo.toml b/client/executor/wasmi/Cargo.toml index d50237edfe4a..9dc63747166b 100644 --- a/client/executor/wasmi/Cargo.toml +++ b/client/executor/wasmi/Cargo.toml @@ -19,7 +19,7 @@ wasmi = "0.9.1" codec = { package = "parity-scale-codec", version = "2.0.0" } sc-executor-common = { version = "0.10.0-dev", path = "../common" } sc-allocator = { version = "4.1.0-dev", path = "../../allocator" } -sp-wasm-interface = { version = "4.0.0", path = "../../../primitives/wasm-interface" } -sp-runtime-interface = { version = "4.0.0", path = "../../../primitives/runtime-interface" } +sp-wasm-interface = { version = "4.1.0-dev", path = "../../../primitives/wasm-interface" } +sp-runtime-interface = { version = "4.1.0-dev", path = "../../../primitives/runtime-interface" } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } scoped-tls = "1.0" diff --git a/client/executor/wasmtime/Cargo.toml b/client/executor/wasmtime/Cargo.toml index 49e44766b9d4..06f668ef67b4 100644 --- a/client/executor/wasmtime/Cargo.toml +++ b/client/executor/wasmtime/Cargo.toml @@ -19,8 +19,8 @@ log = "0.4.8" parity-wasm = "0.42.0" codec = { package = "parity-scale-codec", version = "2.0.0" } sc-executor-common = { version = "0.10.0-dev", path = "../common" } -sp-wasm-interface = { version = "4.0.0", path = "../../../primitives/wasm-interface" } -sp-runtime-interface = { version = "4.0.0", path = "../../../primitives/runtime-interface" } +sp-wasm-interface = { version = "4.1.0-dev", path = "../../../primitives/wasm-interface", features = ["wasmtime"] } +sp-runtime-interface = { version = "4.1.0-dev", path = "../../../primitives/runtime-interface" } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sc-allocator = { version = "4.1.0-dev", path = "../../allocator" } wasmtime = { version = "0.31.0", default-features = false, features = [ diff --git a/client/executor/wasmtime/src/host.rs b/client/executor/wasmtime/src/host.rs index 39ee9ced80af..ab8b4cf8b73c 100644 --- a/client/executor/wasmtime/src/host.rs +++ b/client/executor/wasmtime/src/host.rs @@ -62,11 +62,11 @@ impl HostState { /// A `HostContext` implements `FunctionContext` for making host calls from a Wasmtime /// runtime. The `HostContext` exists only for the lifetime of the call and borrows state from /// a longer-living `HostState`. -pub(crate) struct HostContext<'a, 'b> { - pub(crate) caller: &'a mut Caller<'b, StoreData>, +pub(crate) struct HostContext<'a> { + pub(crate) caller: Caller<'a, StoreData>, } -impl<'a, 'b> HostContext<'a, 'b> { +impl<'a> HostContext<'a> { fn host_state(&self) -> &HostState { self.caller .data() @@ -98,7 +98,7 @@ impl<'a, 'b> HostContext<'a, 'b> { } } -impl<'a, 'b> sp_wasm_interface::FunctionContext for HostContext<'a, 'b> { +impl<'a> sp_wasm_interface::FunctionContext for HostContext<'a> { fn read_memory_into( &self, address: Pointer, @@ -136,7 +136,7 @@ impl<'a, 'b> sp_wasm_interface::FunctionContext for HostContext<'a, 'b> { } } -impl<'a, 'b> Sandbox for HostContext<'a, 'b> { +impl<'a> Sandbox for HostContext<'a> { fn memory_get( &mut self, memory_id: MemoryId, @@ -320,12 +320,12 @@ impl<'a, 'b> Sandbox for HostContext<'a, 'b> { } } -struct SandboxContext<'a, 'b, 'c> { - host_context: &'a mut HostContext<'b, 'c>, +struct SandboxContext<'a, 'b> { + host_context: &'a mut HostContext<'b>, dispatch_thunk: Func, } -impl<'a, 'b, 'c> sandbox::SandboxContext for SandboxContext<'a, 'b, 'c> { +impl<'a, 'b> sandbox::SandboxContext for SandboxContext<'a, 'b> { fn invoke( &mut self, invoke_args_ptr: Pointer, diff --git a/client/executor/wasmtime/src/imports.rs b/client/executor/wasmtime/src/imports.rs index 57ce48f537e9..c18cf58ac722 100644 --- a/client/executor/wasmtime/src/imports.rs +++ b/client/executor/wasmtime/src/imports.rs @@ -19,14 +19,11 @@ use crate::{ host::HostContext, runtime::{Store, StoreData}, - util, }; use sc_executor_common::error::WasmError; -use sp_wasm_interface::{Function, ValueType}; -use std::{any::Any, convert::TryInto}; -use wasmtime::{ - Caller, Extern, ExternType, Func, FuncType, ImportType, Memory, MemoryType, Module, Trap, Val, -}; +use sp_wasm_interface::{FunctionContext, HostFunctions}; +use std::{collections::HashMap, convert::TryInto}; +use wasmtime::{Extern, ExternType, Func, FuncType, ImportType, Memory, MemoryType, Module, Trap}; pub struct Imports { /// Contains the index into `externs` where the memory import is stored if any. `None` if there @@ -37,16 +34,19 @@ pub struct Imports { /// Goes over all imports of a module and prepares a vector of `Extern`s that can be used for /// instantiation of the module. Returns an error if there are imports that cannot be satisfied. -pub(crate) fn resolve_imports( +pub(crate) fn resolve_imports( store: &mut Store, module: &Module, - host_functions: &[&'static dyn Function], heap_pages: u64, allow_missing_func_imports: bool, -) -> Result { +) -> Result +where + H: HostFunctions, +{ let mut externs = vec![]; let mut memory_import_index = None; - for import_ty in module.imports() { + let mut pending_func_imports = HashMap::new(); + for (index, import_ty) in module.imports().enumerate() { let name = import_name(&import_ty)?; if import_ty.module() != "env" { @@ -57,19 +57,89 @@ pub(crate) fn resolve_imports( ))) } - let resolved = match name { - "memory" => { - memory_import_index = Some(externs.len()); - resolve_memory_import(store, &import_ty, heap_pages)? + if name == "memory" { + memory_import_index = Some(index); + externs.push((index, resolve_memory_import(store, &import_ty, heap_pages)?)); + continue + } + + match import_ty.ty() { + ExternType::Func(func_ty) => { + pending_func_imports.insert(name.to_owned(), (index, import_ty, func_ty)); }, _ => - resolve_func_import(store, &import_ty, host_functions, allow_missing_func_imports)?, + return Err(WasmError::Other(format!( + "host doesn't provide any non function imports besides 'memory': {}:{}", + import_ty.module(), + name, + ))), }; - externs.push(resolved); } + + let mut registry = Registry { store, externs, pending_func_imports }; + + H::register_static(&mut registry)?; + let mut externs = registry.externs; + + if !registry.pending_func_imports.is_empty() { + if allow_missing_func_imports { + for (_, (index, import_ty, func_ty)) in registry.pending_func_imports { + externs.push(( + index, + MissingHostFuncHandler::new(&import_ty)?.into_extern(store, &func_ty), + )); + } + } else { + let mut names = Vec::new(); + for (name, (_, import_ty, _)) in registry.pending_func_imports { + names.push(format!("'{}:{}'", import_ty.module(), name)); + } + let names = names.join(", "); + return Err(WasmError::Other(format!( + "runtime requires function imports which are not present on the host: {}", + names + ))) + } + } + + externs.sort_unstable_by_key(|&(index, _)| index); + let externs = externs.into_iter().map(|(_, ext)| ext).collect(); + Ok(Imports { memory_import_index, externs }) } +struct Registry<'a, 'b> { + store: &'a mut Store, + externs: Vec<(usize, Extern)>, + pending_func_imports: HashMap, FuncType)>, +} + +impl<'a, 'b> sp_wasm_interface::HostFunctionRegistry for Registry<'a, 'b> { + type State = StoreData; + type Error = WasmError; + type FunctionContext = HostContext<'a>; + + fn with_function_context( + caller: wasmtime::Caller, + callback: impl FnOnce(&mut dyn FunctionContext) -> R, + ) -> R { + callback(&mut HostContext { caller }) + } + + fn register_static( + &mut self, + fn_name: &str, + func: impl wasmtime::IntoFunc, + ) -> Result<(), Self::Error> { + if let Some((index, _, _)) = self.pending_func_imports.remove(fn_name) { + let func = Func::wrap(&mut *self.store, func); + self.externs.push((index, Extern::Func(func))); + } + + Ok(()) + } +} + /// When the module linking proposal is supported the import's name can be `None`. /// Because we are not using this proposal we could safely unwrap the name. /// However, we opt for an error in order to avoid panics at all costs. @@ -139,115 +209,6 @@ fn resolve_memory_import( Ok(Extern::Memory(memory)) } -fn resolve_func_import( - store: &mut Store, - import_ty: &ImportType, - host_functions: &[&'static dyn Function], - allow_missing_func_imports: bool, -) -> Result { - let name = import_name(&import_ty)?; - - let func_ty = match import_ty.ty() { - ExternType::Func(func_ty) => func_ty, - _ => - return Err(WasmError::Other(format!( - "host doesn't provide any non function imports besides 'memory': {}:{}", - import_ty.module(), - name, - ))), - }; - - let host_func = match host_functions.iter().find(|host_func| host_func.name() == name) { - Some(host_func) => host_func, - None if allow_missing_func_imports => - return Ok(MissingHostFuncHandler::new(import_ty)?.into_extern(store, &func_ty)), - None => - return Err(WasmError::Other(format!( - "host doesn't provide such function: {}:{}", - import_ty.module(), - name, - ))), - }; - if &func_ty != &wasmtime_func_sig(*host_func) { - return Err(WasmError::Other(format!( - "signature mismatch for: {}:{}", - import_ty.module(), - name, - ))) - } - - Ok(HostFuncHandler::new(*host_func).into_extern(store)) -} - -/// This structure implements `Callable` and acts as a bridge between wasmtime and -/// substrate host functions. -struct HostFuncHandler { - host_func: &'static dyn Function, -} - -fn call_static<'a>( - static_func: &'static dyn Function, - wasmtime_params: &[Val], - wasmtime_results: &mut [Val], - mut caller: Caller<'a, StoreData>, -) -> Result<(), wasmtime::Trap> { - let unwind_result = { - let mut host_ctx = HostContext { caller: &mut caller }; - - // `from_wasmtime_val` panics if it encounters a value that doesn't fit into the values - // available in substrate. - // - // This, however, cannot happen since the signature of this function is created from - // a `dyn Function` signature of which cannot have a non substrate value by definition. - let mut params = wasmtime_params.iter().cloned().map(util::from_wasmtime_val); - - std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { - static_func.execute(&mut host_ctx, &mut params) - })) - }; - - let execution_result = match unwind_result { - Ok(execution_result) => execution_result, - Err(err) => return Err(Trap::new(stringify_panic_payload(err))), - }; - - match execution_result { - Ok(Some(ret_val)) => { - debug_assert!( - wasmtime_results.len() == 1, - "wasmtime function signature, therefore the number of results, should always \ - correspond to the number of results returned by the host function", - ); - wasmtime_results[0] = util::into_wasmtime_val(ret_val); - Ok(()) - }, - Ok(None) => { - debug_assert!( - wasmtime_results.len() == 0, - "wasmtime function signature, therefore the number of results, should always \ - correspond to the number of results returned by the host function", - ); - Ok(()) - }, - Err(msg) => Err(Trap::new(msg)), - } -} - -impl HostFuncHandler { - fn new(host_func: &'static dyn Function) -> Self { - Self { host_func } - } - - fn into_extern(self, store: &mut Store) -> Extern { - let host_func = self.host_func; - let func_ty = wasmtime_func_sig(self.host_func); - let func = Func::new(store, func_ty, move |caller, params, result| { - call_static(host_func, params, result, caller) - }); - Extern::Func(func) - } -} - /// A `Callable` handler for missing functions. struct MissingHostFuncHandler { module: String, @@ -270,33 +231,3 @@ impl MissingHostFuncHandler { Extern::Func(func) } } - -fn wasmtime_func_sig(func: &dyn Function) -> wasmtime::FuncType { - let signature = func.signature(); - let params = signature.args.iter().cloned().map(into_wasmtime_val_type); - - let results = signature.return_value.iter().cloned().map(into_wasmtime_val_type); - - wasmtime::FuncType::new(params, results) -} - -fn into_wasmtime_val_type(val_ty: ValueType) -> wasmtime::ValType { - match val_ty { - ValueType::I32 => wasmtime::ValType::I32, - ValueType::I64 => wasmtime::ValType::I64, - ValueType::F32 => wasmtime::ValType::F32, - ValueType::F64 => wasmtime::ValType::F64, - } -} - -/// Attempt to convert a opaque panic payload to a string. -fn stringify_panic_payload(payload: Box) -> String { - match payload.downcast::<&'static str>() { - Ok(msg) => msg.to_string(), - Err(payload) => match payload.downcast::() { - Ok(msg) => *msg, - // At least we tried... - Err(_) => "Box".to_string(), - }, - } -} diff --git a/client/executor/wasmtime/src/instance_wrapper.rs b/client/executor/wasmtime/src/instance_wrapper.rs index e9b18d8c2b89..58f96eb26363 100644 --- a/client/executor/wasmtime/src/instance_wrapper.rs +++ b/client/executor/wasmtime/src/instance_wrapper.rs @@ -24,7 +24,7 @@ use sc_executor_common::{ error::{Error, Result}, wasm_runtime::InvokeMethod, }; -use sp_wasm_interface::{Function, Pointer, Value, WordSize}; +use sp_wasm_interface::{HostFunctions, Pointer, Value, WordSize}; use wasmtime::{ AsContext, AsContextMut, Extern, Func, Global, Instance, Memory, Module, Table, Val, }; @@ -138,13 +138,15 @@ fn extern_func(extern_: &Extern) -> Option<&Func> { impl InstanceWrapper { /// Create a new instance wrapper from the given wasm module. - pub fn new( + pub fn new( module: &Module, - host_functions: &[&'static dyn Function], heap_pages: u64, allow_missing_func_imports: bool, max_memory_size: Option, - ) -> Result { + ) -> Result + where + H: HostFunctions, + { let limits = if let Some(max_memory_size) = max_memory_size { wasmtime::StoreLimitsBuilder::new().memory_size(max_memory_size).build() } else { @@ -161,10 +163,9 @@ impl InstanceWrapper { // Scan all imports, find the matching host functions, and create stubs that adapt arguments // and results. - let imports = crate::imports::resolve_imports( + let imports = crate::imports::resolve_imports::( &mut store, module, - host_functions, heap_pages, allow_missing_func_imports, )?; diff --git a/client/executor/wasmtime/src/runtime.rs b/client/executor/wasmtime/src/runtime.rs index 606401132e9e..b870405f92d3 100644 --- a/client/executor/wasmtime/src/runtime.rs +++ b/client/executor/wasmtime/src/runtime.rs @@ -23,6 +23,7 @@ use crate::{ instance_wrapper::{EntryPoint, InstanceWrapper}, util, }; +use core::marker::PhantomData; use sc_allocator::FreeingBumpHeapAllocator; use sc_executor_common::{ @@ -33,7 +34,7 @@ use sc_executor_common::{ wasm_runtime::{InvokeMethod, WasmInstance, WasmModule}, }; use sp_runtime_interface::unpack_ptr_and_len; -use sp_wasm_interface::{Function, Pointer, Value, WordSize}; +use sp_wasm_interface::{HostFunctions, Pointer, Value, WordSize}; use std::{ path::{Path, PathBuf}, sync::{ @@ -79,29 +80,31 @@ impl StoreData { pub(crate) type Store = wasmtime::Store; -enum Strategy { +enum Strategy { FastInstanceReuse { instance_wrapper: InstanceWrapper, globals_snapshot: GlobalsSnapshot, data_segments_snapshot: Arc, heap_base: u32, }, - RecreateInstance(InstanceCreator), + RecreateInstance(InstanceCreator), } -struct InstanceCreator { +struct InstanceCreator { module: Arc, - host_functions: Vec<&'static dyn Function>, heap_pages: u64, allow_missing_func_imports: bool, max_memory_size: Option, + phantom: PhantomData, } -impl InstanceCreator { +impl InstanceCreator +where + H: HostFunctions, +{ fn instantiate(&mut self) -> Result { - InstanceWrapper::new( + InstanceWrapper::new::( &*self.module, - &self.host_functions, self.heap_pages, self.allow_missing_func_imports, self.max_memory_size, @@ -141,19 +144,21 @@ struct InstanceSnapshotData { /// A `WasmModule` implementation using wasmtime to compile the runtime module to machine code /// and execute the compiled code. -pub struct WasmtimeRuntime { +pub struct WasmtimeRuntime { module: Arc, snapshot_data: Option, config: Config, - host_functions: Vec<&'static dyn Function>, + phantom: PhantomData, } -impl WasmModule for WasmtimeRuntime { +impl WasmModule for WasmtimeRuntime +where + H: HostFunctions, +{ fn new_instance(&self) -> Result> { let strategy = if let Some(ref snapshot_data) = self.snapshot_data { - let mut instance_wrapper = InstanceWrapper::new( + let mut instance_wrapper = InstanceWrapper::new::( &self.module, - &self.host_functions, self.config.heap_pages, self.config.allow_missing_func_imports, self.config.max_memory_size, @@ -169,19 +174,19 @@ impl WasmModule for WasmtimeRuntime { &mut InstanceGlobals { instance: &mut instance_wrapper }, ); - Strategy::FastInstanceReuse { + Strategy::::FastInstanceReuse { instance_wrapper, globals_snapshot, data_segments_snapshot: snapshot_data.data_segments_snapshot.clone(), heap_base, } } else { - Strategy::RecreateInstance(InstanceCreator { + Strategy::::RecreateInstance(InstanceCreator { module: self.module.clone(), - host_functions: self.host_functions.clone(), heap_pages: self.config.heap_pages, allow_missing_func_imports: self.config.allow_missing_func_imports, max_memory_size: self.config.max_memory_size, + phantom: PhantomData, }) }; @@ -191,11 +196,14 @@ impl WasmModule for WasmtimeRuntime { /// A `WasmInstance` implementation that reuses compiled module and spawns instances /// to execute the compiled code. -pub struct WasmtimeInstance { - strategy: Strategy, +pub struct WasmtimeInstance { + strategy: Strategy, } -impl WasmInstance for WasmtimeInstance { +impl WasmInstance for WasmtimeInstance +where + H: HostFunctions, +{ fn call(&mut self, method: InvokeMethod, data: &[u8]) -> Result> { match &mut self.strategy { Strategy::FastInstanceReuse { @@ -483,13 +491,18 @@ enum CodeSupplyMode<'a> { /// Create a new `WasmtimeRuntime` given the code. This function performs translation from Wasm to /// machine code, which can be computationally heavy. -pub fn create_runtime( +/// +/// The `H` generic parameter is used to statically pass a set of host functions which are exposed +/// to the runtime. +pub fn create_runtime( blob: RuntimeBlob, config: Config, - host_functions: Vec<&'static dyn Function>, -) -> std::result::Result { +) -> std::result::Result, WasmError> +where + H: HostFunctions, +{ // SAFETY: this is safe because it doesn't use `CodeSupplyMode::Artifact`. - unsafe { do_create_runtime(CodeSupplyMode::Verbatim { blob }, config, host_functions) } + unsafe { do_create_runtime::(CodeSupplyMode::Verbatim { blob }, config) } } /// The same as [`create_runtime`] but takes a precompiled artifact, which makes this function @@ -503,23 +516,27 @@ pub fn create_runtime( /// /// It is ok though if the `compiled_artifact` was created by code of another version or with /// different configuration flags. In such case the caller will receive an `Err` deterministically. -pub unsafe fn create_runtime_from_artifact( +pub unsafe fn create_runtime_from_artifact( compiled_artifact: &[u8], config: Config, - host_functions: Vec<&'static dyn Function>, -) -> std::result::Result { - do_create_runtime(CodeSupplyMode::Artifact { compiled_artifact }, config, host_functions) +) -> std::result::Result, WasmError> +where + H: HostFunctions, +{ + do_create_runtime::(CodeSupplyMode::Artifact { compiled_artifact }, config) } /// # Safety /// /// This is only unsafe if called with [`CodeSupplyMode::Artifact`]. See /// [`create_runtime_from_artifact`] to get more details. -unsafe fn do_create_runtime( +unsafe fn do_create_runtime( code_supply_mode: CodeSupplyMode<'_>, config: Config, - host_functions: Vec<&'static dyn Function>, -) -> std::result::Result { +) -> std::result::Result, WasmError> +where + H: HostFunctions, +{ // Create the engine, store and finally the module from the given code. let mut wasmtime_config = common_config(&config.semantics)?; if let Some(ref cache_path) = config.cache_path { @@ -566,7 +583,7 @@ unsafe fn do_create_runtime( }, }; - Ok(WasmtimeRuntime { module: Arc::new(module), snapshot_data, config, host_functions }) + Ok(WasmtimeRuntime { module: Arc::new(module), snapshot_data, config, phantom: PhantomData }) } fn instrument( diff --git a/client/executor/wasmtime/src/tests.rs b/client/executor/wasmtime/src/tests.rs index c34cbfad1113..31fb5d3da1c7 100644 --- a/client/executor/wasmtime/src/tests.rs +++ b/client/executor/wasmtime/src/tests.rs @@ -78,7 +78,7 @@ impl RuntimeBuilder { .expect("failed to create a runtime blob out of test runtime") }; - let rt = crate::create_runtime( + let rt = crate::create_runtime::( blob, crate::Config { heap_pages: self.heap_pages, @@ -98,10 +98,6 @@ impl RuntimeBuilder { parallel_compilation: true, }, }, - { - use sp_wasm_interface::HostFunctions as _; - HostFunctions::host_functions() - }, ) .expect("cannot create runtime"); @@ -316,9 +312,7 @@ fn test_max_memory_pages() { #[cfg_attr(build_type = "debug", ignore)] #[test] fn test_instances_without_reuse_are_not_leaked() { - use sp_wasm_interface::HostFunctions; - - let runtime = crate::create_runtime( + let runtime = crate::create_runtime::( RuntimeBlob::uncompress_if_needed(&wasm_binary_unwrap()[..]).unwrap(), crate::Config { heap_pages: 2048, @@ -332,7 +326,6 @@ fn test_instances_without_reuse_are_not_leaked() { parallel_compilation: true, }, }, - sp_io::SubstrateHostFunctions::host_functions(), ) .unwrap(); diff --git a/frame/benchmarking/Cargo.toml b/frame/benchmarking/Cargo.toml index d907cf71948f..1e89c39be1c4 100644 --- a/frame/benchmarking/Cargo.toml +++ b/frame/benchmarking/Cargo.toml @@ -18,7 +18,7 @@ paste = "1.0" codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-api = { version = "4.0.0-dev", path = "../../primitives/api", default-features = false } -sp-runtime-interface = { version = "4.0.0", path = "../../primitives/runtime-interface", default-features = false } +sp-runtime-interface = { version = "4.1.0-dev", path = "../../primitives/runtime-interface", default-features = false } sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime", default-features = false } sp-std = { version = "4.0.0", path = "../../primitives/std", default-features = false } sp-io = { version = "4.0.0-dev", path = "../../primitives/io", default-features = false } diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index a078cc09aafc..330dd57e817f 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -69,7 +69,7 @@ libsecp256k1 = { version = "0.7", default-features = false, features = ["hmac", merlin = { version = "2.0", default-features = false, optional = true } ss58-registry = { version = "1.5.0", default-features = false } sp-core-hashing = { version = "4.0.0", path = "./hashing", default-features = false, optional = true } -sp-runtime-interface = { version = "4.0.0", default-features = false, path = "../runtime-interface" } +sp-runtime-interface = { version = "4.1.0-dev", default-features = false, path = "../runtime-interface" } [dev-dependencies] sp-serializer = { version = "4.0.0-dev", path = "../serializer" } diff --git a/primitives/io/Cargo.toml b/primitives/io/Cargo.toml index 4485a8a7f45a..436420261800 100644 --- a/primitives/io/Cargo.toml +++ b/primitives/io/Cargo.toml @@ -22,8 +22,8 @@ sp-keystore = { version = "0.10.0-dev", default-features = false, optional = tru sp-std = { version = "4.0.0", default-features = false, path = "../std" } libsecp256k1 = { version = "0.7", optional = true } sp-state-machine = { version = "0.10.0-dev", optional = true, path = "../state-machine" } -sp-wasm-interface = { version = "4.0.0", path = "../wasm-interface", default-features = false } -sp-runtime-interface = { version = "4.0.0", default-features = false, path = "../runtime-interface" } +sp-wasm-interface = { version = "4.1.0-dev", path = "../wasm-interface", default-features = false } +sp-runtime-interface = { version = "4.1.0-dev", default-features = false, path = "../runtime-interface" } sp-trie = { version = "4.0.0-dev", optional = true, path = "../trie" } sp-externalities = { version = "0.10.0", optional = true, path = "../externalities" } sp-tracing = { version = "4.0.0", default-features = false, path = "../tracing" } diff --git a/primitives/runtime-interface/Cargo.toml b/primitives/runtime-interface/Cargo.toml index 6b120ab50c50..9ff17b1dff0f 100644 --- a/primitives/runtime-interface/Cargo.toml +++ b/primitives/runtime-interface/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-runtime-interface" -version = "4.0.0" +version = "4.1.0-dev" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" @@ -14,7 +14,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-wasm-interface = { version = "4.0.0", path = "../wasm-interface", default-features = false } +sp-wasm-interface = { version = "4.1.0-dev", path = "../wasm-interface", default-features = false } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-tracing = { version = "4.0.0", default-features = false, path = "../tracing" } sp-runtime-interface-proc-macro = { version = "4.0.0", path = "proc-macro" } diff --git a/primitives/runtime-interface/proc-macro/src/runtime_interface/host_function_interface.rs b/primitives/runtime-interface/proc-macro/src/runtime_interface/host_function_interface.rs index 75498c09c18c..c79886d45b18 100644 --- a/primitives/runtime-interface/proc-macro/src/runtime_interface/host_function_interface.rs +++ b/primitives/runtime-interface/proc-macro/src/runtime_interface/host_function_interface.rs @@ -35,11 +35,11 @@ use syn::{ use proc_macro2::{Span, TokenStream}; -use quote::{quote, ToTokens}; +use quote::quote; use inflector::Inflector; -use std::iter::{self, Iterator}; +use std::iter::Iterator; /// Generate the extern host functions for wasm and the `HostFunctions` struct that provides the /// implementations for the host functions on the host. @@ -163,14 +163,20 @@ fn generate_host_functions_struct( ) -> Result { let crate_ = generate_crate_access(); - let host_functions = get_runtime_interface(trait_def)? - .all_versions() - .map(|(version, method)| { - generate_host_function_implementation(&trait_def.ident, method, version, is_wasm_only) - }) - .collect::>>()?; + let mut host_function_impls = Vec::new(); + let mut host_function_names = Vec::new(); + let mut register_bodies = Vec::new(); + for (version, method) in get_runtime_interface(trait_def)?.all_versions() { + let (implementation, name, register_body) = + generate_host_function_implementation(&trait_def.ident, method, version, is_wasm_only)?; + host_function_impls.push(implementation); + host_function_names.push(name); + register_bodies.push(register_body); + } Ok(quote! { + #(#host_function_impls)* + /// Provides implementations for the extern host functions. #[cfg(feature = "std")] pub struct HostFunctions; @@ -178,7 +184,16 @@ fn generate_host_functions_struct( #[cfg(feature = "std")] impl #crate_::sp_wasm_interface::HostFunctions for HostFunctions { fn host_functions() -> Vec<&'static dyn #crate_::sp_wasm_interface::Function> { - vec![ #( #host_functions ),* ] + vec![ #( &#host_function_names as &dyn #crate_::sp_wasm_interface::Function ),* ] + } + + #crate_::sp_wasm_interface::if_wasmtime_is_enabled! { + fn register_static(registry: &mut T) -> core::result::Result<(), T::Error> + where T: #crate_::sp_wasm_interface::HostFunctionRegistry + { + #(#register_bodies)* + Ok(()) + } } } }) @@ -194,47 +209,182 @@ fn generate_host_function_implementation( method: &TraitItemMethod, version: u32, is_wasm_only: bool, -) -> Result { +) -> Result<(TokenStream, Ident, TokenStream)> { let name = create_host_function_ident(&method.sig.ident, version, trait_name).to_string(); let struct_name = Ident::new(&name.to_pascal_case(), Span::call_site()); let crate_ = generate_crate_access(); let signature = generate_wasm_interface_signature_for_host_function(&method.sig)?; - let wasm_to_ffi_values = - generate_wasm_to_ffi_values(&method.sig, trait_name).collect::>>()?; - let ffi_to_host_values = generate_ffi_to_host_value(&method.sig).collect::>>()?; - let host_function_call = generate_host_function_call(&method.sig, version, is_wasm_only); - let into_preallocated_ffi_value = generate_into_preallocated_ffi_value(&method.sig)?; - let convert_return_value = generate_return_value_into_wasm_value(&method.sig); - Ok(quote! { - { - struct #struct_name; + let fn_name = create_function_ident_with_version(&method.sig.ident, version); + let ref_and_mut = get_function_argument_types_ref_and_mut(&method.sig); + + // List of variable names containing WASM FFI-compatible arguments. + let mut ffi_names = Vec::new(); + + // List of `$name: $ty` tokens containing WASM FFI-compatible arguments. + let mut ffi_args_prototype = Vec::new(); + + // List of variable names containing arguments already converted into native Rust types. + // Also includes the preceding `&` or `&mut`. To be used to call the actual implementation of + // the host function. + let mut host_names_with_ref = Vec::new(); + + // List of code snippets to copy over the results returned from a host function through + // any `&mut` arguments back into WASM's linear memory. + let mut copy_data_into_ref_mut_args = Vec::new(); + + // List of code snippets to convert dynamic FFI args (`Value` enum) into concrete static FFI + // types (`u32`, etc.). + let mut convert_args_dynamic_ffi_to_static_ffi = Vec::new(); + + // List of code snippets to convert static FFI args (`u32`, etc.) into native Rust types. + let mut convert_args_static_ffi_to_host = Vec::new(); + + for ((host_name, host_ty), ref_and_mut) in + get_function_argument_names_and_types_without_ref(&method.sig).zip(ref_and_mut) + { + let ffi_name = generate_ffi_value_var_name(&host_name)?; + let host_name_ident = match *host_name { + Pat::Ident(ref pat_ident) => pat_ident.ident.clone(), + _ => unreachable!("`generate_ffi_value_var_name` above would return an error on `Pat` != `Ident`; qed"), + }; + + let ffi_ty = quote! { <#host_ty as #crate_::RIType>::FFIType }; + ffi_args_prototype.push(quote! { #ffi_name: #ffi_ty }); + ffi_names.push(quote! { #ffi_name }); + + let convert_arg_error = format!( + "could not marshal the '{}' argument through the WASM FFI boundary while executing '{}' from interface '{}'", + host_name_ident, + method.sig.ident, + trait_name + ); + convert_args_static_ffi_to_host.push(quote! { + let mut #host_name = <#host_ty as #crate_::host::FromFFIValue>::from_ffi_value(__function_context__, #ffi_name) + .map_err(|err| format!("{}: {}", err, #convert_arg_error))?; + }); - impl #crate_::sp_wasm_interface::Function for #struct_name { - fn name(&self) -> &str { - #name - } + let ref_and_mut_tokens = + ref_and_mut.map(|(token_ref, token_mut)| quote!(#token_ref #token_mut)); - fn signature(&self) -> #crate_::sp_wasm_interface::Signature { - #signature - } + host_names_with_ref.push(quote! { #ref_and_mut_tokens #host_name }); - fn execute( - &self, - __function_context__: &mut dyn #crate_::sp_wasm_interface::FunctionContext, - args: &mut dyn Iterator, - ) -> std::result::Result, String> { - #( #wasm_to_ffi_values )* - #( #ffi_to_host_values )* - #host_function_call - #into_preallocated_ffi_value - #convert_return_value - } + if ref_and_mut.map(|(_, token_mut)| token_mut.is_some()).unwrap_or(false) { + copy_data_into_ref_mut_args.push(quote! { + <#host_ty as #crate_::host::IntoPreallocatedFFIValue>::into_preallocated_ffi_value( + #host_name, + __function_context__, + #ffi_name, + )?; + }); + } + + let arg_count_mismatch_error = format!( + "missing argument '{}': number of arguments given to '{}' from interface '{}' does not match the expected number of arguments", + host_name_ident, + method.sig.ident, + trait_name + ); + convert_args_dynamic_ffi_to_static_ffi.push(quote! { + let #ffi_name = args.next().ok_or_else(|| #arg_count_mismatch_error.to_owned())?; + let #ffi_name: #ffi_ty = #crate_::sp_wasm_interface::TryFromValue::try_from_value(#ffi_name) + .ok_or_else(|| #convert_arg_error.to_owned())?; + }); + } + + let ffi_return_ty = match &method.sig.output { + ReturnType::Type(_, ty) => quote! { <#ty as #crate_::RIType>::FFIType }, + ReturnType::Default => quote! { () }, + }; + + let convert_return_value_host_to_static_ffi = match &method.sig.output { + ReturnType::Type(_, ty) => quote! { + let __result__ = <#ty as #crate_::host::IntoFFIValue>::into_ffi_value( + __result__, + __function_context__ + ); + }, + ReturnType::Default => quote! { + let __result__ = Ok(__result__); + }, + }; + + let convert_return_value_static_ffi_to_dynamic_ffi = match &method.sig.output { + ReturnType::Type(_, _) => quote! { + let __result__ = Ok(Some(#crate_::sp_wasm_interface::IntoValue::into_value(__result__))); + }, + ReturnType::Default => quote! { + let __result__ = Ok(None); + }, + }; + + if is_wasm_only { + host_names_with_ref.push(quote! { + __function_context__ + }); + } + + let implementation = quote! { + #[cfg(feature = "std")] + struct #struct_name; + + #[cfg(feature = "std")] + impl #struct_name { + fn call( + __function_context__: &mut dyn #crate_::sp_wasm_interface::FunctionContext, + #(#ffi_args_prototype),* + ) -> std::result::Result<#ffi_return_ty, String> { + #(#convert_args_static_ffi_to_host)* + let __result__ = #fn_name(#(#host_names_with_ref),*); + #(#copy_data_into_ref_mut_args)* + #convert_return_value_host_to_static_ffi + __result__ + } + } + + #[cfg(feature = "std")] + impl #crate_::sp_wasm_interface::Function for #struct_name { + fn name(&self) -> &str { + #name } - &#struct_name as &dyn #crate_::sp_wasm_interface::Function + fn signature(&self) -> #crate_::sp_wasm_interface::Signature { + #signature + } + + fn execute( + &self, + __function_context__: &mut dyn #crate_::sp_wasm_interface::FunctionContext, + args: &mut dyn Iterator, + ) -> std::result::Result, String> { + #(#convert_args_dynamic_ffi_to_static_ffi)* + let __result__ = Self::call( + __function_context__, + #(#ffi_names),* + )?; + #convert_return_value_static_ffi_to_dynamic_ffi + __result__ + } } - }) + }; + + let register_body = quote! { + registry.register_static( + #crate_::sp_wasm_interface::Function::name(&#struct_name), + |mut caller: #crate_::sp_wasm_interface::wasmtime::Caller, #(#ffi_args_prototype),*| + -> std::result::Result<#ffi_return_ty, #crate_::sp_wasm_interface::wasmtime::Trap> + { + T::with_function_context(caller, move |__function_context__| { + #struct_name::call( + __function_context__, + #(#ffi_names,)* + ) + }).map_err(#crate_::sp_wasm_interface::wasmtime::Trap::new) + } + )?; + }; + + Ok((implementation, struct_name, register_body)) } /// Generate the `wasm_interface::Signature` for the given host function `sig`. @@ -260,86 +410,6 @@ fn generate_wasm_interface_signature_for_host_function(sig: &Signature) -> Resul }) } -/// Generate the code that converts the wasm values given to `HostFunctions::execute` into the FFI -/// values. -fn generate_wasm_to_ffi_values<'a>( - sig: &'a Signature, - trait_name: &'a Ident, -) -> impl Iterator> + 'a { - let crate_ = generate_crate_access(); - let function_name = &sig.ident; - let error_message = format!( - "Number of arguments given to `{}` does not match the expected number of arguments!", - function_name, - ); - - get_function_argument_names_and_types_without_ref(sig).map(move |(name, ty)| { - let try_from_error = format!( - "Could not instantiate `{}` from wasm value while executing `{}` from interface `{}`!", - name.to_token_stream(), - function_name, - trait_name, - ); - - let var_name = generate_ffi_value_var_name(&name)?; - - Ok(quote! { - let val = args.next().ok_or_else(|| #error_message)?; - let #var_name = < - <#ty as #crate_::RIType>::FFIType as #crate_::sp_wasm_interface::TryFromValue - >::try_from_value(val).ok_or_else(|| #try_from_error)?; - }) - }) -} - -/// Generate the code to convert the ffi values on the host to the host values using `FromFFIValue`. -fn generate_ffi_to_host_value<'a>( - sig: &'a Signature, -) -> impl Iterator> + 'a { - let mut_access = get_function_argument_types_ref_and_mut(sig); - let crate_ = generate_crate_access(); - - get_function_argument_names_and_types_without_ref(sig) - .zip(mut_access.map(|v| v.and_then(|m| m.1))) - .map(move |((name, ty), mut_access)| { - let ffi_value_var_name = generate_ffi_value_var_name(&name)?; - - Ok(quote! { - let #mut_access #name = <#ty as #crate_::host::FromFFIValue>::from_ffi_value( - __function_context__, - #ffi_value_var_name, - )?; - }) - }) -} - -/// Generate the code to call the host function and the ident that stores the result. -fn generate_host_function_call(sig: &Signature, version: u32, is_wasm_only: bool) -> TokenStream { - let host_function_name = create_function_ident_with_version(&sig.ident, version); - let result_var_name = generate_host_function_result_var_name(&sig.ident); - let ref_and_mut = - get_function_argument_types_ref_and_mut(sig).map(|ram| ram.map(|(vr, vm)| quote!(#vr #vm))); - let names = get_function_argument_names(sig); - - let var_access = names - .zip(ref_and_mut) - .map(|(n, ref_and_mut)| quote!( #ref_and_mut #n )) - // If this is a wasm only interface, we add the function context as last parameter. - .chain( - iter::from_fn(|| if is_wasm_only { Some(quote!(__function_context__)) } else { None }) - .take(1), - ); - - quote! { - let #result_var_name = #host_function_name ( #( #var_access ),* ); - } -} - -/// Generate the variable name that stores the result of the host function. -fn generate_host_function_result_var_name(name: &Ident) -> Ident { - Ident::new(&format!("{}_result", name), Span::call_site()) -} - /// Generate the variable name that stores the FFI value. fn generate_ffi_value_var_name(pat: &Pat) -> Result { match pat { @@ -354,49 +424,3 @@ fn generate_ffi_value_var_name(pat: &Pat) -> Result { _ => Err(Error::new(pat.span(), "Not supported as variable name!")), } } - -/// Generate code that copies data from the host back to preallocated wasm memory. -/// -/// Any argument that is given as `&mut` is interpreted as preallocated memory and it is expected -/// that the type implements `IntoPreAllocatedFFIValue`. -fn generate_into_preallocated_ffi_value(sig: &Signature) -> Result { - let crate_ = generate_crate_access(); - let ref_and_mut = get_function_argument_types_ref_and_mut(sig) - .map(|ram| ram.and_then(|(vr, vm)| vm.map(|v| (vr, v)))); - let names_and_types = get_function_argument_names_and_types_without_ref(sig); - - ref_and_mut - .zip(names_and_types) - .filter_map(|(ram, (name, ty))| ram.map(|_| (name, ty))) - .map(|(name, ty)| { - let ffi_var_name = generate_ffi_value_var_name(&name)?; - - Ok(quote! { - <#ty as #crate_::host::IntoPreallocatedFFIValue>::into_preallocated_ffi_value( - #name, - __function_context__, - #ffi_var_name, - )?; - }) - }) - .collect() -} - -/// Generate the code that converts the return value into the appropriate wasm value. -fn generate_return_value_into_wasm_value(sig: &Signature) -> TokenStream { - let crate_ = generate_crate_access(); - - match &sig.output { - ReturnType::Default => quote!(Ok(None)), - ReturnType::Type(_, ty) => { - let result_var_name = generate_host_function_result_var_name(&sig.ident); - - quote! { - <#ty as #crate_::host::IntoFFIValue>::into_ffi_value( - #result_var_name, - __function_context__, - ).map(#crate_::sp_wasm_interface::IntoValue::into_value).map(Some) - } - }, - } -} diff --git a/primitives/runtime-interface/src/impls.rs b/primitives/runtime-interface/src/impls.rs index 0b9cdc26f465..35badd27fa99 100644 --- a/primitives/runtime-interface/src/impls.rs +++ b/primitives/runtime-interface/src/impls.rs @@ -95,36 +95,36 @@ macro_rules! impl_traits_for_primitives { } impl_traits_for_primitives! { - u8, u8, - u16, u16, + u8, u32, + u16, u32, u32, u32, u64, u64, - i8, i8, - i16, i16, + i8, i32, + i16, i32, i32, i32, i64, i64, } -/// `bool` is passed as `u8`. +/// `bool` is passed as `u32`. /// /// - `1`: true /// - `0`: false impl RIType for bool { - type FFIType = u8; + type FFIType = u32; } #[cfg(not(feature = "std"))] impl IntoFFIValue for bool { type Owned = (); - fn into_ffi_value(&self) -> WrappedFFIValue { + fn into_ffi_value(&self) -> WrappedFFIValue { if *self { 1 } else { 0 }.into() } } #[cfg(not(feature = "std"))] impl FromFFIValue for bool { - fn from_ffi_value(arg: u8) -> bool { + fn from_ffi_value(arg: u32) -> bool { arg == 1 } } @@ -133,14 +133,14 @@ impl FromFFIValue for bool { impl FromFFIValue for bool { type SelfInstance = bool; - fn from_ffi_value(_: &mut dyn FunctionContext, arg: u8) -> Result { + fn from_ffi_value(_: &mut dyn FunctionContext, arg: u32) -> Result { Ok(arg == 1) } } #[cfg(feature = "std")] impl IntoFFIValue for bool { - fn into_ffi_value(self, _: &mut dyn FunctionContext) -> Result { + fn into_ffi_value(self, _: &mut dyn FunctionContext) -> Result { Ok(if self { 1 } else { 0 }) } } diff --git a/primitives/runtime-interface/src/lib.rs b/primitives/runtime-interface/src/lib.rs index 27c4422ed900..e8e29329a980 100644 --- a/primitives/runtime-interface/src/lib.rs +++ b/primitives/runtime-interface/src/lib.rs @@ -80,17 +80,17 @@ //! //! | Type | FFI type | Conversion | //! |----|----|----| -//! | `u8` | `u8` | `Identity` | -//! | `u16` | `u16` | `Identity` | +//! | `u8` | `u32` | zero-extended to 32-bits | +//! | `u16` | `u32` | zero-extended to 32-bits | //! | `u32` | `u32` | `Identity` | //! | `u64` | `u64` | `Identity` | //! | `i128` | `u32` | `v.as_ptr()` (pointer to a 16 byte array) | -//! | `i8` | `i8` | `Identity` | -//! | `i16` | `i16` | `Identity` | +//! | `i8` | `i32` | sign-extended to 32-bits | +//! | `i16` | `i32` | sign-extended to 32-bits | //! | `i32` | `i32` | `Identity` | //! | `i64` | `i64` | `Identity` | //! | `u128` | `u32` | `v.as_ptr()` (pointer to a 16 byte array) | -//! | `bool` | `u8` | `if v { 1 } else { 0 }` | +//! | `bool` | `u32` | `if v { 1 } else { 0 }` | //! | `&str` | `u64` | v.len() 32bit << 32 | v.as_ptr() 32bit | //! | `&[u8]` | `u64` | v.len() 32bit << 32 | v.as_ptr() 32bit | //! | `Vec` | `u64` | v.len() 32bit << 32 | v.as_ptr() 32bit | @@ -325,7 +325,9 @@ pub use util::{pack_ptr_and_len, unpack_ptr_and_len}; pub trait RIType { /// The ffi type that is used to represent `Self`. #[cfg(feature = "std")] - type FFIType: sp_wasm_interface::IntoValue + sp_wasm_interface::TryFromValue; + type FFIType: sp_wasm_interface::IntoValue + + sp_wasm_interface::TryFromValue + + sp_wasm_interface::WasmTy; #[cfg(not(feature = "std"))] type FFIType; } diff --git a/primitives/runtime-interface/src/pass_by.rs b/primitives/runtime-interface/src/pass_by.rs index 7324e9363804..02cbe502f02c 100644 --- a/primitives/runtime-interface/src/pass_by.rs +++ b/primitives/runtime-interface/src/pass_by.rs @@ -403,11 +403,11 @@ pub struct Enum + TryFrom>(PhantomData); #[cfg(feature = "std")] impl + TryFrom> PassByImpl for Enum { fn into_ffi_value(instance: T, _: &mut dyn FunctionContext) -> Result { - Ok(instance.into()) + Ok(instance.into() as u32) } fn from_ffi_value(_: &mut dyn FunctionContext, arg: Self::FFIType) -> Result { - T::try_from(arg).map_err(|_| format!("Invalid enum discriminant: {}", arg)) + T::try_from(arg as u8).map_err(|_| format!("Invalid enum discriminant: {}", arg)) } } @@ -417,17 +417,17 @@ impl + TryFrom> PassByImpl for Enum { fn into_ffi_value(instance: &T) -> WrappedFFIValue { let value: u8 = (*instance).into(); - value.into() + (value as u32).into() } fn from_ffi_value(arg: Self::FFIType) -> T { - T::try_from(arg).expect("Host to wasm provides a valid enum discriminant; qed") + T::try_from(arg as u8).expect("Host to wasm provides a valid enum discriminant; qed") } } -/// The type is passed as `u8`. +/// The type is passed as `u32`. /// /// The value is corresponds to the discriminant of the variant. impl + TryFrom> RIType for Enum { - type FFIType = u8; + type FFIType = u32; } diff --git a/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml b/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml index 02fb75d108fd..032de1d215f2 100644 --- a/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml +++ b/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml @@ -13,7 +13,7 @@ publish = false targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-runtime-interface = { version = "4.0.0", default-features = false, path = "../" } +sp-runtime-interface = { version = "4.1.0-dev", default-features = false, path = "../" } sp-std = { version = "4.0.0", default-features = false, path = "../../std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../io" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../core" } diff --git a/primitives/runtime-interface/test-wasm/Cargo.toml b/primitives/runtime-interface/test-wasm/Cargo.toml index 24fdb8842963..80ad44569e99 100644 --- a/primitives/runtime-interface/test-wasm/Cargo.toml +++ b/primitives/runtime-interface/test-wasm/Cargo.toml @@ -13,7 +13,7 @@ publish = false targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-runtime-interface = { version = "4.0.0", default-features = false, path = "../" } +sp-runtime-interface = { version = "4.1.0-dev", default-features = false, path = "../" } sp-std = { version = "4.0.0", default-features = false, path = "../../std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../io" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../core" } diff --git a/primitives/runtime-interface/test/Cargo.toml b/primitives/runtime-interface/test/Cargo.toml index 5e4483fb38ed..b197f2ab8ba9 100644 --- a/primitives/runtime-interface/test/Cargo.toml +++ b/primitives/runtime-interface/test/Cargo.toml @@ -12,7 +12,7 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-runtime-interface = { version = "4.0.0", path = "../" } +sp-runtime-interface = { version = "4.1.0-dev", path = "../" } sc-executor = { version = "0.10.0-dev", path = "../../../client/executor" } sc-executor-common = { version = "0.10.0-dev", path = "../../../client/executor/common" } sp-runtime-interface-test-wasm = { version = "2.0.0", path = "../test-wasm" } diff --git a/primitives/runtime-interface/test/src/lib.rs b/primitives/runtime-interface/test/src/lib.rs index f64b74336427..bf82f3b4b52e 100644 --- a/primitives/runtime-interface/test/src/lib.rs +++ b/primitives/runtime-interface/test/src/lib.rs @@ -24,7 +24,7 @@ use sp_runtime_interface_test_wasm::{test_api::HostFunctions, wasm_binary_unwrap use sp_runtime_interface_test_wasm_deprecated::wasm_binary_unwrap as wasm_binary_deprecated_unwrap; use sc_executor_common::runtime_blob::RuntimeBlob; -use sp_wasm_interface::HostFunctions as HostFunctionsT; +use sp_wasm_interface::{ExtendedHostFunctions, HostFunctions as HostFunctionsT}; use std::{ collections::HashSet, @@ -39,17 +39,11 @@ fn call_wasm_method_with_result( ) -> Result { let mut ext = TestExternalities::default(); let mut ext_ext = ext.ext(); - let mut host_functions = HF::host_functions(); - host_functions.extend(sp_io::SubstrateHostFunctions::host_functions()); - - let executor = sc_executor::WasmExecutor::new( - sc_executor::WasmExecutionMethod::Interpreted, - Some(8), - host_functions, - 8, - None, - 2, - ); + + let executor = sc_executor::WasmExecutor::< + ExtendedHostFunctions, + >::new(sc_executor::WasmExecutionMethod::Interpreted, Some(8), 8, None, 2); + executor .uncached_call( RuntimeBlob::uncompress_if_needed(binary).expect("Failed to parse binary"), diff --git a/primitives/sandbox/Cargo.toml b/primitives/sandbox/Cargo.toml index a94ba0f375f8..26a81caea89b 100644 --- a/primitives/sandbox/Cargo.toml +++ b/primitives/sandbox/Cargo.toml @@ -23,7 +23,7 @@ wasmi = { version = "0.9.0", optional = true } sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../io" } -sp-wasm-interface = { version = "4.0.0", default-features = false, path = "../wasm-interface" } +sp-wasm-interface = { version = "4.1.0-dev", default-features = false, path = "../wasm-interface" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } log = { version = "0.4", default-features = false } diff --git a/primitives/tasks/Cargo.toml b/primitives/tasks/Cargo.toml index c154d1c92dca..c57eb50eddb5 100644 --- a/primitives/tasks/Cargo.toml +++ b/primitives/tasks/Cargo.toml @@ -18,7 +18,7 @@ log = { version = "0.4.8", optional = true } sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } sp-externalities = { version = "0.10.0", optional = true, path = "../externalities" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../io" } -sp-runtime-interface = { version = "4.0.0", default-features = false, path = "../runtime-interface" } +sp-runtime-interface = { version = "4.1.0-dev", default-features = false, path = "../runtime-interface" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } [dev-dependencies] diff --git a/primitives/wasm-interface/Cargo.toml b/primitives/wasm-interface/Cargo.toml index da0d0161c086..cffc05e4d8af 100644 --- a/primitives/wasm-interface/Cargo.toml +++ b/primitives/wasm-interface/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-wasm-interface" -version = "4.0.0" +version = "4.1.0-dev" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" @@ -15,10 +15,12 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] wasmi = { version = "0.9.1", optional = true } +wasmtime = { version = "0.31.0", optional = true, default-features = false } +log = { version = "0.4.14", optional = true } impl-trait-for-tuples = "0.2.1" sp-std = { version = "4.0.0", path = "../std", default-features = false } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } [features] default = [ "std" ] -std = [ "wasmi", "sp-std/std", "codec/std" ] +std = [ "wasmi", "sp-std/std", "codec/std", "log" ] diff --git a/primitives/wasm-interface/src/lib.rs b/primitives/wasm-interface/src/lib.rs index e1903ef425ae..44afaf82ed4c 100644 --- a/primitives/wasm-interface/src/lib.rs +++ b/primitives/wasm-interface/src/lib.rs @@ -24,6 +24,25 @@ use sp_std::{borrow::Cow, iter::Iterator, marker::PhantomData, mem, result, vec, #[cfg(feature = "std")] mod wasmi_impl; +#[cfg(not(all(feature = "std", feature = "wasmtime")))] +#[macro_export] +macro_rules! if_wasmtime_is_enabled { + ($($token:tt)*) => {}; +} + +#[cfg(all(feature = "std", feature = "wasmtime"))] +#[macro_export] +macro_rules! if_wasmtime_is_enabled { + ($($token:tt)*) => { + $($token)* + } +} + +if_wasmtime_is_enabled! { + // Reexport wasmtime so that its types are accessible from the procedural macro. + pub use wasmtime; +} + /// Result type used by traits in this crate. #[cfg(feature = "std")] pub type Result = result::Result; @@ -105,7 +124,8 @@ impl Value { } } -/// Provides `Sealed` trait to prevent implementing trait `PointerType` outside of this crate. +/// Provides `Sealed` trait to prevent implementing trait `PointerType` and `WasmTy` outside of this +/// crate. mod private { pub trait Sealed {} @@ -113,6 +133,9 @@ mod private { impl Sealed for u16 {} impl Sealed for u32 {} impl Sealed for u64 {} + + impl Sealed for i32 {} + impl Sealed for i64 {} } /// Something that can be wrapped in a wasm `Pointer`. @@ -338,10 +361,48 @@ pub trait Sandbox { fn get_global_val(&self, instance_idx: u32, name: &str) -> Result>; } +if_wasmtime_is_enabled! { + /// A trait used to statically register host callbacks with the WASM executor, + /// so that they call be called from within the runtime with minimal overhead. + /// + /// This is used internally to interface the wasmtime-based executor with the + /// host functions' definitions generated through the runtime interface macro, + /// and is not meant to be used directly. + pub trait HostFunctionRegistry { + type State; + type Error; + type FunctionContext: FunctionContext; + + /// Wraps the given `caller` in a type which implements `FunctionContext` + /// and calls the given `callback`. + fn with_function_context( + caller: wasmtime::Caller, + callback: impl FnOnce(&mut dyn FunctionContext) -> R, + ) -> R; + + /// Registers a given host function with the WASM executor. + /// + /// The function has to be statically callable, and all of its arguments + /// and its return value have to be compatible with WASM FFI. + fn register_static( + &mut self, + fn_name: &str, + func: impl wasmtime::IntoFunc + 'static, + ) -> core::result::Result<(), Self::Error>; + } +} + /// Something that provides implementations for host functions. -pub trait HostFunctions: 'static { +pub trait HostFunctions: 'static + Send + Sync { /// Returns the host functions `Self` provides. fn host_functions() -> Vec<&'static dyn Function>; + + if_wasmtime_is_enabled! { + /// Statically registers the host functions. + fn register_static(registry: &mut T) -> core::result::Result<(), T::Error> + where + T: HostFunctionRegistry; + } } #[impl_trait_for_tuples::impl_for_tuples(30)] @@ -353,8 +414,146 @@ impl HostFunctions for Tuple { host_functions } + + #[cfg(all(feature = "std", feature = "wasmtime"))] + fn register_static(registry: &mut T) -> core::result::Result<(), T::Error> + where + T: HostFunctionRegistry, + { + for_tuples!( + #( Tuple::register_static(registry)?; )* + ); + + Ok(()) + } +} + +/// A wrapper which merges two sets of host functions, and allows the second set to override +/// the host functions from the first set. +pub struct ExtendedHostFunctions { + phantom: PhantomData<(Base, Overlay)>, +} + +impl HostFunctions for ExtendedHostFunctions +where + Base: HostFunctions, + Overlay: HostFunctions, +{ + fn host_functions() -> Vec<&'static dyn Function> { + let mut base = Base::host_functions(); + let overlay = Overlay::host_functions(); + base.retain(|host_fn| { + !overlay.iter().any(|ext_host_fn| host_fn.name() == ext_host_fn.name()) + }); + base.extend(overlay); + base + } + + if_wasmtime_is_enabled! { + fn register_static(registry: &mut T) -> core::result::Result<(), T::Error> + where + T: HostFunctionRegistry, + { + struct Proxy<'a, T> { + registry: &'a mut T, + seen_overlay: std::collections::HashSet, + seen_base: std::collections::HashSet, + overlay_registered: bool, + } + + impl<'a, T> HostFunctionRegistry for Proxy<'a, T> + where + T: HostFunctionRegistry, + { + type State = T::State; + type Error = T::Error; + type FunctionContext = T::FunctionContext; + + fn with_function_context( + caller: wasmtime::Caller, + callback: impl FnOnce(&mut dyn FunctionContext) -> R, + ) -> R { + T::with_function_context(caller, callback) + } + + fn register_static( + &mut self, + fn_name: &str, + func: impl wasmtime::IntoFunc + 'static, + ) -> core::result::Result<(), Self::Error> { + if self.overlay_registered { + if !self.seen_base.insert(fn_name.to_owned()) { + log::warn!( + target: "extended_host_functions", + "Duplicate base host function: '{}'", + fn_name, + ); + + // TODO: Return an error here? + return Ok(()) + } + + if self.seen_overlay.contains(fn_name) { + // Was already registered when we went through the overlay, so just ignore it. + log::debug!( + target: "extended_host_functions", + "Overriding base host function: '{}'", + fn_name, + ); + + return Ok(()) + } + } else if !self.seen_overlay.insert(fn_name.to_owned()) { + log::warn!( + target: "extended_host_functions", + "Duplicate overlay host function: '{}'", + fn_name, + ); + + // TODO: Return an error here? + return Ok(()) + } + + self.registry.register_static(fn_name, func) + } + } + + let mut proxy = Proxy { + registry, + seen_overlay: Default::default(), + seen_base: Default::default(), + overlay_registered: false, + }; + + // The functions from the `Overlay` can override those from the `Base`, + // so `Overlay` is registered first, and then we skip those functions + // in `Base` if they were already registered from the `Overlay`. + Overlay::register_static(&mut proxy)?; + proxy.overlay_registered = true; + Base::register_static(&mut proxy)?; + + Ok(()) + } + } } +/// A trait for types directly usable at the WASM FFI boundary without any conversion at all. +/// +/// This trait is sealed and should not be implemented downstream. +#[cfg(all(feature = "std", feature = "wasmtime"))] +pub trait WasmTy: wasmtime::WasmTy + private::Sealed {} + +/// A trait for types directly usable at the WASM FFI boundary without any conversion at all. +/// +/// This trait is sealed and should not be implemented downstream. +#[cfg(not(all(feature = "std", feature = "wasmtime")))] +pub trait WasmTy: private::Sealed {} + +impl WasmTy for i32 {} +impl WasmTy for u32 {} +impl WasmTy for i64 {} +impl WasmTy for u64 {} + /// Something that can be converted into a wasm compatible `Value`. pub trait IntoValue { /// The type of the value in wasm. diff --git a/test-utils/client/src/lib.rs b/test-utils/client/src/lib.rs index 96f3c9898395..86231bb34c50 100644 --- a/test-utils/client/src/lib.rs +++ b/test-utils/client/src/lib.rs @@ -262,7 +262,8 @@ impl client::LocalCallExecutor>, Backend, G, - > + > where + D: sc_executor::NativeExecutionDispatch, { /// Build the test client with the given native executor. pub fn build_with_native_executor( diff --git a/test-utils/runtime/Cargo.toml b/test-utils/runtime/Cargo.toml index 3be0e40b0b6b..ae4be0d13af7 100644 --- a/test-utils/runtime/Cargo.toml +++ b/test-utils/runtime/Cargo.toml @@ -25,7 +25,7 @@ memory-db = { version = "0.27.0", default-features = false } sp-offchain = { version = "4.0.0-dev", default-features = false, path = "../../primitives/offchain" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime-interface = { version = "4.0.0", default-features = false, path = "../../primitives/runtime-interface" } +sp-runtime-interface = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime-interface" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../../frame/support" } sp-version = { version = "4.0.0-dev", default-features = false, path = "../../primitives/version" } diff --git a/test-utils/test-runner/Cargo.toml b/test-utils/test-runner/Cargo.toml index 7066fc778cbd..eb565fd7b587 100644 --- a/test-utils/test-runner/Cargo.toml +++ b/test-utils/test-runner/Cargo.toml @@ -52,3 +52,8 @@ tokio = { version = "1.13", features = ["signal"] } # Calling RPC jsonrpc-core = "18.0" num-traits = "0.2.14" + +[features] +default = ["std"] +# This is here so that we can use the `runtime_interface` procedural macro +std = [] diff --git a/test-utils/test-runner/src/host_functions.rs b/test-utils/test-runner/src/host_functions.rs index 731abfbb9db0..6d9fa3534b34 100644 --- a/test-utils/test-runner/src/host_functions.rs +++ b/test-utils/test-runner/src/host_functions.rs @@ -16,75 +16,38 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -/// Use this to override host functions. -/// eg -/// ```rust -/// use test_runner::override_host_functions; -/// pub struct SignatureVerificationOverride; -/// -/// impl sp_wasm_interface::HostFunctions for SignatureVerificationOverride { -/// fn host_functions() -> Vec<&'static dyn sp_wasm_interface::Function> { -/// override_host_functions!( -/// "ext_crypto_ecdsa_verify_version_1", EcdsaVerify, -/// ) -/// } -/// } -/// ``` -#[macro_export] -macro_rules! override_host_functions { - ($($fn_name:expr, $name:ident,)*) => {{ - let mut host_functions = vec![]; - $( - struct $name; - impl sp_wasm_interface::Function for $name { - fn name(&self) -> &str { - &$fn_name - } +use sp_core::{ecdsa, ed25519, sr25519}; +use sp_runtime_interface::runtime_interface; - fn signature(&self) -> sp_wasm_interface::Signature { - sp_wasm_interface::Signature { - args: std::borrow::Cow::Owned(vec![ - sp_wasm_interface::ValueType::I32, - sp_wasm_interface::ValueType::I64, - sp_wasm_interface::ValueType::I32, - ]), - return_value: Some(sp_wasm_interface::ValueType::I32), - } - } +#[runtime_interface] +trait Crypto { + fn ecdsa_verify(_sig: &ecdsa::Signature, _msg: &[u8], _pub_key: &ecdsa::Public) -> bool { + true + } + + #[version(2)] + fn ecdsa_verify(_sig: &ecdsa::Signature, _msg: &[u8], _pub_key: &ecdsa::Public) -> bool { + true + } + + fn ed25519_verify(_sig: &ed25519::Signature, _msg: &[u8], _pub_key: &ed25519::Public) -> bool { + true + } - fn execute( - &self, - context: &mut dyn sp_wasm_interface::FunctionContext, - _args: &mut dyn Iterator, - ) -> Result, String> { - ::into_ffi_value(true, context) - .map(sp_wasm_interface::IntoValue::into_value) - .map(Some) - } - } - host_functions.push(&$name as &'static dyn sp_wasm_interface::Function); - )* - host_functions - }}; + fn sr25519_verify(_sig: &sr25519::Signature, _msg: &[u8], _pub_key: &sr25519::Public) -> bool { + true + } + + #[version(2)] + fn sr25519_verify(_sig: &sr25519::Signature, _msg: &[u8], _pub_key: &sr25519::Public) -> bool { + true + } } /// Provides host functions that overrides runtime signature verification /// to always return true. -pub struct SignatureVerificationOverride; +pub type SignatureVerificationOverride = crypto::HostFunctions; -impl sp_wasm_interface::HostFunctions for SignatureVerificationOverride { - fn host_functions() -> Vec<&'static dyn sp_wasm_interface::Function> { - override_host_functions!( - "ext_crypto_ecdsa_verify_version_1", - EcdsaVerify, - "ext_crypto_ecdsa_verify_version_2", - EcdsaVerifyV2, - "ext_crypto_ed25519_verify_version_1", - Ed25519Verify, - "ext_crypto_sr25519_verify_version_1", - Sr25519Verify, - "ext_crypto_sr25519_verify_version_2", - Sr25519VerifyV2, - ) - } -} +// This is here to get rid of the warnings. +#[allow(unused_imports, dead_code)] +use self::crypto::{ecdsa_verify, ed25519_verify, sr25519_verify}; From 8aeeef953d44460c4415afce195a0ff9536d9493 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Tue, 14 Dec 2021 13:05:47 +0100 Subject: [PATCH 290/695] Prepare code for rust 1.57 (#10471) * Prepare code for rust 1.57 * CI: revert me; staging image with stable 1.57 * Revert "CI: revert me; staging image with stable 1.57 [skip CI]" This reverts commit f3c3b8a9e877ef7126ffce6ebc4822bb4ace0379. Co-authored-by: CI system <> --- Cargo.lock | 4 ++-- frame/support/test/Cargo.toml | 2 +- .../tests/derive_no_bound_ui/clone.stderr | 6 ++--- .../test/tests/derive_no_bound_ui/eq.stderr | 6 ++--- .../call_argument_invalid_bound.stderr | 10 ++++----- .../call_argument_invalid_bound_2.stderr | 22 +++++++++---------- .../call_argument_invalid_bound_3.stderr | 12 +++++----- .../pallet_ui/event_field_not_member.stderr | 10 ++++----- .../storage_info_unsatisfied_nmap.stderr | 10 ++++----- .../reserved_keyword/on_initialize.stderr | 20 ++++++++--------- primitives/api/test/Cargo.toml | 2 +- .../npos-elections/solution-type/Cargo.toml | 2 +- primitives/runtime-interface/Cargo.toml | 2 +- test-utils/Cargo.toml | 2 +- 14 files changed, 54 insertions(+), 56 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b576a12ea6f6..c6c49939a8ff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10963,9 +10963,9 @@ dependencies = [ [[package]] name = "trybuild" -version = "1.0.52" +version = "1.0.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "150e726dc059e6fbd4fce3288f5bb3cf70128cf63b0dde23b938a3cad810fb23" +checksum = "9d664de8ea7e531ad4c0f5a834f20b8cb2b8e6dfe88d05796ee7887518ed67b9" dependencies = [ "dissimilar", "glob", diff --git a/frame/support/test/Cargo.toml b/frame/support/test/Cargo.toml index 0cd3f9ac0291..cdbefae4bde7 100644 --- a/frame/support/test/Cargo.toml +++ b/frame/support/test/Cargo.toml @@ -23,7 +23,7 @@ sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../.. sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } sp-version = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/version" } -trybuild = "1.0.52" +trybuild = "1.0.53" pretty_assertions = "1.0.0" rustversion = "1.0.5" frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" } diff --git a/frame/support/test/tests/derive_no_bound_ui/clone.stderr b/frame/support/test/tests/derive_no_bound_ui/clone.stderr index 050b576c8b9e..45428a8728c2 100644 --- a/frame/support/test/tests/derive_no_bound_ui/clone.stderr +++ b/frame/support/test/tests/derive_no_bound_ui/clone.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `::C: Clone` is not satisfied - --> $DIR/clone.rs:7:2 + --> tests/derive_no_bound_ui/clone.rs:7:2 | 7 | c: T::C, | ^ the trait `Clone` is not implemented for `::C` | note: required by `clone` - --> $DIR/clone.rs:121:5 + --> $RUST/core/src/clone.rs | -121 | fn clone(&self) -> Self; + | fn clone(&self) -> Self; | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/frame/support/test/tests/derive_no_bound_ui/eq.stderr b/frame/support/test/tests/derive_no_bound_ui/eq.stderr index 19fb3ac248b8..97ac29f96902 100644 --- a/frame/support/test/tests/derive_no_bound_ui/eq.stderr +++ b/frame/support/test/tests/derive_no_bound_ui/eq.stderr @@ -1,12 +1,12 @@ error[E0277]: can't compare `Foo` with `Foo` - --> $DIR/eq.rs:6:8 + --> tests/derive_no_bound_ui/eq.rs:6:8 | 6 | struct Foo { | ^^^ no implementation for `Foo == Foo` | = help: the trait `PartialEq` is not implemented for `Foo` note: required by a bound in `std::cmp::Eq` - --> $DIR/cmp.rs:272:15 + --> $RUST/core/src/cmp.rs | -272 | pub trait Eq: PartialEq { + | pub trait Eq: PartialEq { | ^^^^^^^^^^^^^^^ required by this bound in `std::cmp::Eq` diff --git a/frame/support/test/tests/pallet_ui/call_argument_invalid_bound.stderr b/frame/support/test/tests/pallet_ui/call_argument_invalid_bound.stderr index b7a8e40e69a1..9701b1bdd06f 100644 --- a/frame/support/test/tests/pallet_ui/call_argument_invalid_bound.stderr +++ b/frame/support/test/tests/pallet_ui/call_argument_invalid_bound.stderr @@ -1,5 +1,5 @@ error[E0277]: `::Bar` doesn't implement `std::fmt::Debug` - --> $DIR/call_argument_invalid_bound.rs:20:36 + --> tests/pallet_ui/call_argument_invalid_bound.rs:20:36 | 20 | pub fn foo(origin: OriginFor, bar: T::Bar) -> DispatchResultWithPostInfo { | ^^^ `::Bar` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug` @@ -9,19 +9,19 @@ error[E0277]: `::Bar` doesn't implement `std::fmt::Debug` = note: required for the cast to the object type `dyn std::fmt::Debug` error[E0277]: the trait bound `::Bar: Clone` is not satisfied - --> $DIR/call_argument_invalid_bound.rs:20:36 + --> tests/pallet_ui/call_argument_invalid_bound.rs:20:36 | 20 | pub fn foo(origin: OriginFor, bar: T::Bar) -> DispatchResultWithPostInfo { | ^^^ the trait `Clone` is not implemented for `::Bar` | note: required by `clone` - --> $DIR/clone.rs:121:5 + --> $RUST/core/src/clone.rs | -121 | fn clone(&self) -> Self; + | fn clone(&self) -> Self; | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0369]: binary operation `==` cannot be applied to type `&::Bar` - --> $DIR/call_argument_invalid_bound.rs:20:36 + --> tests/pallet_ui/call_argument_invalid_bound.rs:20:36 | 20 | pub fn foo(origin: OriginFor, bar: T::Bar) -> DispatchResultWithPostInfo { | ^^^ diff --git a/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr b/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr index f1bc3b5d8f38..b4a10a6af01f 100644 --- a/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr +++ b/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr @@ -1,5 +1,5 @@ error[E0277]: `::Bar` doesn't implement `std::fmt::Debug` - --> $DIR/call_argument_invalid_bound_2.rs:20:36 + --> tests/pallet_ui/call_argument_invalid_bound_2.rs:20:36 | 20 | pub fn foo(origin: OriginFor, bar: T::Bar) -> DispatchResultWithPostInfo { | ^^^ `::Bar` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug` @@ -9,19 +9,19 @@ error[E0277]: `::Bar` doesn't implement `std::fmt::Debug` = note: required for the cast to the object type `dyn std::fmt::Debug` error[E0277]: the trait bound `::Bar: Clone` is not satisfied - --> $DIR/call_argument_invalid_bound_2.rs:20:36 + --> tests/pallet_ui/call_argument_invalid_bound_2.rs:20:36 | 20 | pub fn foo(origin: OriginFor, bar: T::Bar) -> DispatchResultWithPostInfo { | ^^^ the trait `Clone` is not implemented for `::Bar` | note: required by `clone` - --> $DIR/clone.rs:121:5 + --> $RUST/core/src/clone.rs | -121 | fn clone(&self) -> Self; + | fn clone(&self) -> Self; | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0369]: binary operation `==` cannot be applied to type `&::Bar` - --> $DIR/call_argument_invalid_bound_2.rs:20:36 + --> tests/pallet_ui/call_argument_invalid_bound_2.rs:20:36 | 20 | pub fn foo(origin: OriginFor, bar: T::Bar) -> DispatchResultWithPostInfo { | ^^^ @@ -32,7 +32,7 @@ help: consider further restricting this bound | +++++++++++++++++++++ error[E0277]: the trait bound `::Bar: WrapperTypeEncode` is not satisfied - --> $DIR/call_argument_invalid_bound_2.rs:1:1 + --> tests/pallet_ui/call_argument_invalid_bound_2.rs:1:1 | 1 | #[frame_support::pallet] | ^----------------------- @@ -49,21 +49,21 @@ error[E0277]: the trait bound `::Bar: WrapperTypeEncode` is | = note: required because of the requirements on the impl of `Encode` for `::Bar` note: required by a bound in `encode_to` - --> $DIR/codec.rs:223:18 + --> $CARGO/parity-scale-codec-2.3.1/src/codec.rs | -223 | fn encode_to(&self, dest: &mut T) { + | fn encode_to(&self, dest: &mut T) { | ^^^^^^ required by this bound in `encode_to` = note: this error originates in the derive macro `frame_support::codec::Encode` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `::Bar: WrapperTypeDecode` is not satisfied - --> $DIR/call_argument_invalid_bound_2.rs:20:36 + --> tests/pallet_ui/call_argument_invalid_bound_2.rs:20:36 | 20 | pub fn foo(origin: OriginFor, bar: T::Bar) -> DispatchResultWithPostInfo { | ^^^ the trait `WrapperTypeDecode` is not implemented for `::Bar` | = note: required because of the requirements on the impl of `Decode` for `::Bar` note: required by a bound in `parity_scale_codec::Decode::decode` - --> $DIR/codec.rs:284:15 + --> $CARGO/parity-scale-codec-2.3.1/src/codec.rs | -284 | fn decode(input: &mut I) -> Result; + | fn decode(input: &mut I) -> Result; | ^^^^^ required by this bound in `parity_scale_codec::Decode::decode` diff --git a/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_3.stderr b/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_3.stderr index 144b7e12bd66..b884d24103f2 100644 --- a/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_3.stderr +++ b/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_3.stderr @@ -1,5 +1,5 @@ error[E0277]: `Bar` doesn't implement `std::fmt::Debug` - --> $DIR/call_argument_invalid_bound_3.rs:22:36 + --> tests/pallet_ui/call_argument_invalid_bound_3.rs:22:36 | 22 | pub fn foo(origin: OriginFor, bar: Bar) -> DispatchResultWithPostInfo { | ^^^ `Bar` cannot be formatted using `{:?}` @@ -10,21 +10,19 @@ error[E0277]: `Bar` doesn't implement `std::fmt::Debug` = note: required for the cast to the object type `dyn std::fmt::Debug` error[E0277]: the trait bound `Bar: Clone` is not satisfied - --> $DIR/call_argument_invalid_bound_3.rs:22:36 + --> tests/pallet_ui/call_argument_invalid_bound_3.rs:22:36 | 22 | pub fn foo(origin: OriginFor, bar: Bar) -> DispatchResultWithPostInfo { | ^^^ the trait `Clone` is not implemented for `Bar` | note: required by `clone` - --> $DIR/clone.rs:121:5 + --> $RUST/core/src/clone.rs | -121 | fn clone(&self) -> Self; + | fn clone(&self) -> Self; | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0369]: binary operation `==` cannot be applied to type `&Bar` - --> $DIR/call_argument_invalid_bound_3.rs:22:36 + --> tests/pallet_ui/call_argument_invalid_bound_3.rs:22:36 | 22 | pub fn foo(origin: OriginFor, bar: Bar) -> DispatchResultWithPostInfo { | ^^^ - | - = note: an implementation of `std::cmp::PartialEq` might be missing for `&Bar` diff --git a/frame/support/test/tests/pallet_ui/event_field_not_member.stderr b/frame/support/test/tests/pallet_ui/event_field_not_member.stderr index 06384b0b66b8..ff184db988e3 100644 --- a/frame/support/test/tests/pallet_ui/event_field_not_member.stderr +++ b/frame/support/test/tests/pallet_ui/event_field_not_member.stderr @@ -1,17 +1,17 @@ error[E0277]: the trait bound `::Bar: Clone` is not satisfied - --> $DIR/event_field_not_member.rs:23:7 + --> tests/pallet_ui/event_field_not_member.rs:23:7 | 23 | B { b: T::Bar }, | ^ the trait `Clone` is not implemented for `::Bar` | note: required by `clone` - --> $DIR/clone.rs:121:5 + --> $RUST/core/src/clone.rs | -121 | fn clone(&self) -> Self; + | fn clone(&self) -> Self; | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0369]: binary operation `==` cannot be applied to type `&::Bar` - --> $DIR/event_field_not_member.rs:23:7 + --> tests/pallet_ui/event_field_not_member.rs:23:7 | 23 | B { b: T::Bar }, | ^ @@ -22,7 +22,7 @@ help: consider further restricting this bound | +++++++++++++++++++++ error[E0277]: `::Bar` doesn't implement `std::fmt::Debug` - --> $DIR/event_field_not_member.rs:23:7 + --> tests/pallet_ui/event_field_not_member.rs:23:7 | 23 | B { b: T::Bar }, | ^ `::Bar` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug` diff --git a/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr b/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr index ffbc5aeea6b4..00d350b943d0 100644 --- a/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr +++ b/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr @@ -1,13 +1,13 @@ error[E0277]: the trait bound `Bar: MaxEncodedLen` is not satisfied - --> $DIR/storage_info_unsatisfied_nmap.rs:10:12 + --> tests/pallet_ui/storage_info_unsatisfied_nmap.rs:10:12 | 10 | #[pallet::generate_storage_info] | ^^^^^^^^^^^^^^^^^^^^^ the trait `MaxEncodedLen` is not implemented for `Bar` | - = note: required because of the requirements on the impl of `KeyGeneratorMaxEncodedLen` for `NMapKey` - = note: required because of the requirements on the impl of `StorageInfoTrait` for `frame_support::pallet_prelude::StorageNMap<_GeneratedPrefixForStorageFoo, NMapKey, u32>` + = note: required because of the requirements on the impl of `KeyGeneratorMaxEncodedLen` for `Key` + = note: required because of the requirements on the impl of `StorageInfoTrait` for `frame_support::pallet_prelude::StorageNMap<_GeneratedPrefixForStorageFoo, Key, u32>` note: required by `storage_info` - --> $DIR/storage.rs:71:2 + --> $WORKSPACE/frame/support/src/traits/storage.rs | -71 | fn storage_info() -> Vec; + | fn storage_info() -> Vec; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/frame/support/test/tests/reserved_keyword/on_initialize.stderr b/frame/support/test/tests/reserved_keyword/on_initialize.stderr index 84e93fa52c2d..58273fb1bd3b 100644 --- a/frame/support/test/tests/reserved_keyword/on_initialize.stderr +++ b/frame/support/test/tests/reserved_keyword/on_initialize.stderr @@ -1,39 +1,39 @@ error: Invalid call fn name: `on_finalize`, name is reserved and doesn't match expected signature, please refer to `decl_module!` documentation to see the appropriate usage, or rename it to an unreserved keyword. - --> $DIR/on_initialize.rs:28:1 + --> tests/reserved_keyword/on_initialize.rs:28:1 | 28 | reserved!(on_finalize on_initialize on_runtime_upgrade offchain_worker deposit_event); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this error originates in the macro `$crate::__check_reserved_fn_name` (in Nightly builds, run with -Z macro-backtrace for more info) error: Invalid call fn name: `on_initialize`, name is reserved and doesn't match expected signature, please refer to `decl_module!` documentation to see the appropriate usage, or rename it to an unreserved keyword. - --> $DIR/on_initialize.rs:28:1 + --> tests/reserved_keyword/on_initialize.rs:28:1 | 28 | reserved!(on_finalize on_initialize on_runtime_upgrade offchain_worker deposit_event); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this error originates in the macro `$crate::__check_reserved_fn_name` (in Nightly builds, run with -Z macro-backtrace for more info) error: Invalid call fn name: `on_runtime_upgrade`, name is reserved and doesn't match expected signature, please refer to `decl_module!` documentation to see the appropriate usage, or rename it to an unreserved keyword. - --> $DIR/on_initialize.rs:28:1 + --> tests/reserved_keyword/on_initialize.rs:28:1 | 28 | reserved!(on_finalize on_initialize on_runtime_upgrade offchain_worker deposit_event); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this error originates in the macro `$crate::__check_reserved_fn_name` (in Nightly builds, run with -Z macro-backtrace for more info) error: Invalid call fn name: `offchain_worker`, name is reserved and doesn't match expected signature, please refer to `decl_module!` documentation to see the appropriate usage, or rename it to an unreserved keyword. - --> $DIR/on_initialize.rs:28:1 + --> tests/reserved_keyword/on_initialize.rs:28:1 | 28 | reserved!(on_finalize on_initialize on_runtime_upgrade offchain_worker deposit_event); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this error originates in the macro `$crate::__check_reserved_fn_name` (in Nightly builds, run with -Z macro-backtrace for more info) error: Invalid call fn name: `deposit_event`, name is reserved and doesn't match expected signature, please refer to `decl_module!` documentation to see the appropriate usage, or rename it to an unreserved keyword. - --> $DIR/on_initialize.rs:28:1 + --> tests/reserved_keyword/on_initialize.rs:28:1 | 28 | reserved!(on_finalize on_initialize on_runtime_upgrade offchain_worker deposit_event); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this error originates in the macro `$crate::__check_reserved_fn_name` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/primitives/api/test/Cargo.toml b/primitives/api/test/Cargo.toml index 91675e941c78..b7716f6b8de7 100644 --- a/primitives/api/test/Cargo.toml +++ b/primitives/api/test/Cargo.toml @@ -21,7 +21,7 @@ sp-consensus = { version = "0.10.0-dev", path = "../../consensus/common" } sc-block-builder = { version = "0.10.0-dev", path = "../../../client/block-builder" } codec = { package = "parity-scale-codec", version = "2.0.0" } sp-state-machine = { version = "0.10.0-dev", path = "../../state-machine" } -trybuild = "1.0.52" +trybuild = "1.0.53" rustversion = "1.0.5" [dev-dependencies] diff --git a/primitives/npos-elections/solution-type/Cargo.toml b/primitives/npos-elections/solution-type/Cargo.toml index a64ca45ce842..5bffcff1038d 100644 --- a/primitives/npos-elections/solution-type/Cargo.toml +++ b/primitives/npos-elections/solution-type/Cargo.toml @@ -26,4 +26,4 @@ scale-info = "1.0" sp-arithmetic = { path = "../../arithmetic", version = "4.0.0-dev" } # used by generate_solution_type: sp-npos-elections = { path = "..", version = "4.0.0-dev" } -trybuild = "1.0.52" +trybuild = "1.0.53" diff --git a/primitives/runtime-interface/Cargo.toml b/primitives/runtime-interface/Cargo.toml index 9ff17b1dff0f..69a6792ead29 100644 --- a/primitives/runtime-interface/Cargo.toml +++ b/primitives/runtime-interface/Cargo.toml @@ -31,7 +31,7 @@ sp-state-machine = { version = "0.10.0-dev", path = "../state-machine" } sp-core = { version = "4.1.0-dev", path = "../core" } sp-io = { version = "4.0.0-dev", path = "../io" } rustversion = "1.0.5" -trybuild = "1.0.52" +trybuild = "1.0.53" [features] default = [ "std" ] diff --git a/test-utils/Cargo.toml b/test-utils/Cargo.toml index 6cb91bb589c6..756de5803280 100644 --- a/test-utils/Cargo.toml +++ b/test-utils/Cargo.toml @@ -18,4 +18,4 @@ tokio = { version = "1.10", features = ["macros", "time"] } [dev-dependencies] sc-service = { version = "0.10.0-dev", path = "../client/service" } -trybuild = { version = "1.0.52", features = [ "diff" ] } +trybuild = { version = "1.0.53", features = [ "diff" ] } From f32e7932fc24e6a6f20c6265c98d2e869f8ff92d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Tue, 14 Dec 2021 23:44:04 +0100 Subject: [PATCH 291/695] Remove cargo unleash CI job (#10482) * Remove cargo unleash CI job The CI job is currently breaking, because we released some crates. We also don't need the job currently because releases are not done. So, the job currently just annoys people and eats CPU time. This brings us to the conclusion that this job is currently not required and can be readded at a later point when we are sure that we need it. * Hopefully fix UI test * Another try * Remove `reserved_keyword` ui --- .gitlab-ci.yml | 30 -------------- .../call_argument_invalid_bound_3.rs | 9 ++--- .../call_argument_invalid_bound_3.stderr | 18 --------- .../storage_info_unsatisfied_nmap.rs | 10 +++-- .../storage_info_unsatisfied_nmap.stderr | 4 +- frame/support/test/tests/reserved_keyword.rs | 26 ------------- .../tests/reserved_keyword/on_initialize.rs | 30 -------------- .../reserved_keyword/on_initialize.stderr | 39 ------------------- 8 files changed, 12 insertions(+), 154 deletions(-) delete mode 100644 frame/support/test/tests/reserved_keyword.rs delete mode 100644 frame/support/test/tests/reserved_keyword/on_initialize.rs delete mode 100644 frame/support/test/tests/reserved_keyword/on_initialize.stderr diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7af3675f0771..3f830c7e8e24 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -39,9 +39,6 @@ variables: &default-vars DOCKER_OS: "debian:stretch" ARCH: "x86_64" CI_IMAGE: "paritytech/ci-linux:production" - # FIXME set to release - CARGO_UNLEASH_INSTALL_PARAMS: "--version 1.0.0-alpha.13" - CARGO_UNLEASH_PKG_DEF: "--skip node node-* pallet-template pallet-example-* subkey chain-spec-builder" VAULT_SERVER_URL: "https://vault.parity-mgmt-vault.parity.io" VAULT_AUTH_PATH: "gitlab-parity-io-jwt" VAULT_AUTH_ROLE: "cicd_gitlab_parity_${CI_PROJECT_NAME}" @@ -458,21 +455,6 @@ test-linux-stable: &test-linux - SUBSTRATE_TEST_TIMEOUT=1 time cargo test -p substrate-test-utils --release --verbose --locked -- --ignored timeout - sccache -s -unleash-check: - stage: test - <<: *docker-env - <<: *test-refs-no-trigger - script: - - cargo install cargo-unleash ${CARGO_UNLEASH_INSTALL_PARAMS} - - cargo unleash de-dev-deps - # Reuse build artifacts when running checks (cuts down check time by 3x) - # TODO: Implement this optimization in cargo-unleash rather than here - - mkdir -p target/unleash - - export CARGO_TARGET_DIR=target/unleash - - cargo unleash check ${CARGO_UNLEASH_PKG_DEF} - # FIXME: this job must not fail, or unleash-to-crates-io will publish broken stuff - allow_failure: true - test-frame-examples-compile-to-wasm: # into one job stage: test @@ -869,18 +851,6 @@ publish-draft-release: - ./.maintain/gitlab/publish_draft_release.sh allow_failure: true -unleash-to-crates-io: - stage: publish - <<: *docker-env - <<: *vault-secrets - rules: - - if: $CI_COMMIT_REF_NAME =~ /^ci-release-.*$/ - - if: $CI_COMMIT_REF_NAME =~ /^v[0-9]+\.[0-9]+.*$/ # i.e. v1.0, v2.1rc1 - script: - - cargo install cargo-unleash ${CARGO_UNLEASH_INSTALL_PARAMS} - - cargo unleash em-dragons --no-check --owner github:paritytech:core-devs ${CARGO_UNLEASH_PKG_DEF} - allow_failure: true - #### stage: deploy deploy-prometheus-alerting-rules: diff --git a/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_3.rs b/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_3.rs index e7f99d7ca4f2..1cdfb369fead 100644 --- a/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_3.rs +++ b/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_3.rs @@ -1,8 +1,8 @@ #[frame_support::pallet] mod pallet { - use frame_support::pallet_prelude::{Hooks, DispatchResultWithPostInfo}; + use codec::{Decode, Encode}; + use frame_support::pallet_prelude::{DispatchResultWithPostInfo, Hooks}; use frame_system::pallet_prelude::{BlockNumberFor, OriginFor}; - use codec::{Encode, Decode}; #[pallet::config] pub trait Config: frame_system::Config {} @@ -13,7 +13,7 @@ mod pallet { #[pallet::hooks] impl Hooks> for Pallet {} - #[derive(Encode, Decode, scale_info::TypeInfo)] + #[derive(Encode, Decode, scale_info::TypeInfo, PartialEq, Clone)] struct Bar; #[pallet::call] @@ -25,5 +25,4 @@ mod pallet { } } -fn main() { -} +fn main() {} diff --git a/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_3.stderr b/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_3.stderr index b884d24103f2..c196b28a31ce 100644 --- a/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_3.stderr +++ b/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_3.stderr @@ -8,21 +8,3 @@ error[E0277]: `Bar` doesn't implement `std::fmt::Debug` = note: add `#[derive(Debug)]` to `Bar` or manually `impl std::fmt::Debug for Bar` = note: required because of the requirements on the impl of `std::fmt::Debug` for `&Bar` = note: required for the cast to the object type `dyn std::fmt::Debug` - -error[E0277]: the trait bound `Bar: Clone` is not satisfied - --> tests/pallet_ui/call_argument_invalid_bound_3.rs:22:36 - | -22 | pub fn foo(origin: OriginFor, bar: Bar) -> DispatchResultWithPostInfo { - | ^^^ the trait `Clone` is not implemented for `Bar` - | -note: required by `clone` - --> $RUST/core/src/clone.rs - | - | fn clone(&self) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0369]: binary operation `==` cannot be applied to type `&Bar` - --> tests/pallet_ui/call_argument_invalid_bound_3.rs:22:36 - | -22 | pub fn foo(origin: OriginFor, bar: Bar) -> DispatchResultWithPostInfo { - | ^^^ diff --git a/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.rs b/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.rs index c5d773d71611..15456c78e9ba 100644 --- a/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.rs +++ b/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.rs @@ -1,6 +1,9 @@ #[frame_support::pallet] mod pallet { - use frame_support::pallet_prelude::{Hooks, StorageNMap, Twox64Concat, NMapKey}; + use frame_support::{ + pallet_prelude::{Hooks, Twox64Concat}, + storage::types::{StorageNMap, Key}, + }; use frame_system::pallet_prelude::BlockNumberFor; #[pallet::config] @@ -20,8 +23,7 @@ mod pallet { struct Bar; #[pallet::storage] - type Foo = StorageNMap<_, NMapKey, u32>; + type Foo = StorageNMap<_, Key, u32>; } -fn main() { -} +fn main() {} diff --git a/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr b/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr index 00d350b943d0..cb9a0bd55989 100644 --- a/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr +++ b/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr @@ -1,7 +1,7 @@ error[E0277]: the trait bound `Bar: MaxEncodedLen` is not satisfied - --> tests/pallet_ui/storage_info_unsatisfied_nmap.rs:10:12 + --> tests/pallet_ui/storage_info_unsatisfied_nmap.rs:13:12 | -10 | #[pallet::generate_storage_info] +13 | #[pallet::generate_storage_info] | ^^^^^^^^^^^^^^^^^^^^^ the trait `MaxEncodedLen` is not implemented for `Bar` | = note: required because of the requirements on the impl of `KeyGeneratorMaxEncodedLen` for `Key` diff --git a/frame/support/test/tests/reserved_keyword.rs b/frame/support/test/tests/reserved_keyword.rs deleted file mode 100644 index d29b0477c383..000000000000 --- a/frame/support/test/tests/reserved_keyword.rs +++ /dev/null @@ -1,26 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2019-2021 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. - -#[rustversion::attr(not(stable), ignore)] -#[test] -fn reserved_keyword() { - // As trybuild is using `cargo check`, we don't need the real WASM binaries. - std::env::set_var("SKIP_WASM_BUILD", "1"); - - let t = trybuild::TestCases::new(); - t.compile_fail("tests/reserved_keyword/*.rs"); -} diff --git a/frame/support/test/tests/reserved_keyword/on_initialize.rs b/frame/support/test/tests/reserved_keyword/on_initialize.rs deleted file mode 100644 index 72d53abfb103..000000000000 --- a/frame/support/test/tests/reserved_keyword/on_initialize.rs +++ /dev/null @@ -1,30 +0,0 @@ -macro_rules! reserved { - ($($reserved:ident)*) => { - $( - mod $reserved { - pub use frame_support::dispatch; - - pub trait Config: frame_support_test::Config {} - - pub mod system { - use frame_support::dispatch; - - pub fn ensure_root(_: R) -> dispatch::DispatchResult { - Ok(()) - } - } - - frame_support::decl_module! { - pub struct Module for enum Call where origin: T::Origin, system=frame_support_test { - #[weight = 0] - fn $reserved(_origin) -> dispatch::DispatchResult { unreachable!() } - } - } - } - )* - } -} - -reserved!(on_finalize on_initialize on_runtime_upgrade offchain_worker deposit_event); - -fn main() {} diff --git a/frame/support/test/tests/reserved_keyword/on_initialize.stderr b/frame/support/test/tests/reserved_keyword/on_initialize.stderr deleted file mode 100644 index 58273fb1bd3b..000000000000 --- a/frame/support/test/tests/reserved_keyword/on_initialize.stderr +++ /dev/null @@ -1,39 +0,0 @@ -error: Invalid call fn name: `on_finalize`, name is reserved and doesn't match expected signature, please refer to `decl_module!` documentation to see the appropriate usage, or rename it to an unreserved keyword. - --> tests/reserved_keyword/on_initialize.rs:28:1 - | -28 | reserved!(on_finalize on_initialize on_runtime_upgrade offchain_worker deposit_event); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the macro `$crate::__check_reserved_fn_name` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: Invalid call fn name: `on_initialize`, name is reserved and doesn't match expected signature, please refer to `decl_module!` documentation to see the appropriate usage, or rename it to an unreserved keyword. - --> tests/reserved_keyword/on_initialize.rs:28:1 - | -28 | reserved!(on_finalize on_initialize on_runtime_upgrade offchain_worker deposit_event); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the macro `$crate::__check_reserved_fn_name` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: Invalid call fn name: `on_runtime_upgrade`, name is reserved and doesn't match expected signature, please refer to `decl_module!` documentation to see the appropriate usage, or rename it to an unreserved keyword. - --> tests/reserved_keyword/on_initialize.rs:28:1 - | -28 | reserved!(on_finalize on_initialize on_runtime_upgrade offchain_worker deposit_event); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the macro `$crate::__check_reserved_fn_name` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: Invalid call fn name: `offchain_worker`, name is reserved and doesn't match expected signature, please refer to `decl_module!` documentation to see the appropriate usage, or rename it to an unreserved keyword. - --> tests/reserved_keyword/on_initialize.rs:28:1 - | -28 | reserved!(on_finalize on_initialize on_runtime_upgrade offchain_worker deposit_event); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the macro `$crate::__check_reserved_fn_name` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: Invalid call fn name: `deposit_event`, name is reserved and doesn't match expected signature, please refer to `decl_module!` documentation to see the appropriate usage, or rename it to an unreserved keyword. - --> tests/reserved_keyword/on_initialize.rs:28:1 - | -28 | reserved!(on_finalize on_initialize on_runtime_upgrade offchain_worker deposit_event); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the macro `$crate::__check_reserved_fn_name` (in Nightly builds, run with -Z macro-backtrace for more info) From 9652011866b49e8c46f0fe04febd8f28a45b6233 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Wed, 15 Dec 2021 00:51:12 +0100 Subject: [PATCH 292/695] rpc-author: Downgrade the logging level of some logs (#10483) * rpc-author: Downgrade the logging level of some logs Currently these messages are printed with `warn` levels, but they don't bring the node operator anything. The problem with these log lines is that they are triggered by external users when they send invalid transactions. This pr "resolves" this by downgrading the log severity to debug, aka not shown by default. * FMT --- client/rpc/src/author/mod.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/client/rpc/src/author/mod.rs b/client/rpc/src/author/mod.rs index 40b477a662a6..5046f2631920 100644 --- a/client/rpc/src/author/mod.rs +++ b/client/rpc/src/author/mod.rs @@ -21,7 +21,6 @@ #[cfg(test)] mod tests; -use log::warn; use std::{convert::TryInto, sync::Arc}; use sp_blockchain::HeaderBackend; @@ -188,7 +187,7 @@ where let dxt = match TransactionFor::

::decode(&mut &xt[..]).map_err(error::Error::from) { Ok(tx) => tx, Err(err) => { - warn!("Failed to submit extrinsic: {}", err); + log::debug!("Failed to submit extrinsic: {}", err); // reject the subscriber (ignore errors - we don't care if subscriber is no longer // there). let _ = subscriber.reject(err.into()); @@ -211,7 +210,7 @@ where let tx_stream = match submit.await { Ok(s) => s, Err(err) => { - warn!("Failed to submit extrinsic: {}", err); + log::debug!("Failed to submit extrinsic: {}", err); // reject the subscriber (ignore errors - we don't care if subscriber is no // longer there). let _ = subscriber.reject(err.into()); @@ -222,14 +221,16 @@ where subscriptions.add(subscriber, move |sink| { tx_stream .map(|v| Ok(Ok(v))) - .forward(sink.sink_map_err(|e| warn!("Error sending notifications: {:?}", e))) + .forward( + sink.sink_map_err(|e| log::debug!("Error sending notifications: {:?}", e)), + ) .map(drop) }); }; let res = self.subscriptions.executor().spawn_obj(future.boxed().into()); if res.is_err() { - warn!("Error spawning subscription RPC task."); + log::warn!("Error spawning subscription RPC task."); } } From a64f702d20fd0e979c69d11b60e0d6d6b81d6c6d Mon Sep 17 00:00:00 2001 From: Gavin Wood Date: Wed, 15 Dec 2021 01:27:13 +0100 Subject: [PATCH 293/695] Fix update_lock (#10485) * Fix update_lock * Fixes * Formatting * add `inc_consumers_without_limits` to session too Co-authored-by: Shawn Tabrizi --- frame/assets/src/lib.rs | 5 ++-- frame/balances/src/lib.rs | 2 +- frame/session/src/lib.rs | 2 +- frame/system/src/lib.rs | 58 ++++++++++++++++++++++++++++++++++----- 4 files changed, 56 insertions(+), 11 deletions(-) diff --git a/frame/assets/src/lib.rs b/frame/assets/src/lib.rs index b86661d9fa4f..6643cc177460 100644 --- a/frame/assets/src/lib.rs +++ b/frame/assets/src/lib.rs @@ -467,8 +467,9 @@ pub mod pallet { BadWitness, /// Minimum balance should be non-zero. MinBalanceZero, - /// No provider reference exists to allow a non-zero balance of a non-self-sufficient - /// asset. + /// Unable to increment the consumer reference counters on the account. Either no provider + /// reference exists to allow a non-zero balance of a non-self-sufficient asset, or the + /// maximum number of consumers has been reached. NoProvider, /// Invalid metadata given. BadMetadata, diff --git a/frame/balances/src/lib.rs b/frame/balances/src/lib.rs index 4471ed91a9af..6919c66f7211 100644 --- a/frame/balances/src/lib.rs +++ b/frame/balances/src/lib.rs @@ -971,7 +971,7 @@ impl, I: 'static> Pallet { } else { Locks::::insert(who, bounded_locks); if !existed { - if system::Pallet::::inc_consumers(who).is_err() { + if system::Pallet::::inc_consumers_without_limit(who).is_err() { // No providers for the locks. This is impossible under normal circumstances // since the funds that are under the lock will themselves be stored in the // account and therefore will need a reference. diff --git a/frame/session/src/lib.rs b/frame/session/src/lib.rs index 0f8049455084..e88f14306505 100644 --- a/frame/session/src/lib.rs +++ b/frame/session/src/lib.rs @@ -448,7 +448,7 @@ pub mod pallet { for (account, val, keys) in self.keys.iter().cloned() { >::inner_set_keys(&val, keys) .expect("genesis config must not contain duplicates; qed"); - if frame_system::Pallet::::inc_consumers(&account).is_err() { + if frame_system::Pallet::::inc_consumers_without_limit(&account).is_err() { // This will leak a provider reference, however it only happens once (at // genesis) so it's really not a big deal and we assume that the user wants to // do this since it's the only way a non-endowed account can contain a session diff --git a/frame/system/src/lib.rs b/frame/system/src/lib.rs index 6bdaf8bd4b50..e167f44ffd88 100644 --- a/frame/system/src/lib.rs +++ b/frame/system/src/lib.rs @@ -85,8 +85,8 @@ use frame_support::{ dispatch::{DispatchResult, DispatchResultWithPostInfo}, storage, traits::{ - Contains, EnsureOrigin, Get, HandleLifetime, OnKilledAccount, OnNewAccount, OriginTrait, - PalletInfo, SortedMembers, StoredMap, + ConstU32, Contains, EnsureOrigin, Get, HandleLifetime, OnKilledAccount, OnNewAccount, + OriginTrait, PalletInfo, SortedMembers, StoredMap, }, weights::{ extract_actual_weight, DispatchClass, DispatchInfo, PerDispatchClass, RuntimeDbWeight, @@ -154,6 +154,36 @@ impl SetCode for () { } } +/// Numeric limits over the ability to add a consumer ref using `inc_consumers`. +pub trait ConsumerLimits { + /// The number of consumers over which `inc_consumers` will cease to work. + fn max_consumers() -> RefCount; + /// The maximum number of additional consumers expected to be over be added at once using + /// `inc_consumers_without_limit`. + /// + /// Note: This is not enforced and it's up to the chain's author to ensure this reflects the + /// actual situation. + fn max_overflow() -> RefCount; +} + +impl ConsumerLimits for ConstU32 { + fn max_consumers() -> RefCount { + Z + } + fn max_overflow() -> RefCount { + Z + } +} + +impl, MaxOverflow: Get> ConsumerLimits for (MaxNormal, MaxOverflow) { + fn max_consumers() -> RefCount { + MaxNormal::get() + } + fn max_overflow() -> RefCount { + MaxOverflow::get() + } +} + #[frame_support::pallet] pub mod pallet { use crate::{self as frame_system, pallet_prelude::*, *}; @@ -310,8 +340,7 @@ pub mod pallet { type OnSetCode: SetCode; /// The maximum number of consumers allowed on a single account. - #[pallet::constant] - type MaxConsumers: Get; + type MaxConsumers: ConsumerLimits; } #[pallet::pallet] @@ -1122,11 +1151,12 @@ impl Pallet { /// Increment the reference counter on an account. /// - /// The account `who`'s `providers` must be non-zero or this will return an error. + /// The account `who`'s `providers` must be non-zero and the current number of consumers must + /// be less than `MaxConsumers::max_consumers()` or this will return an error. pub fn inc_consumers(who: &T::AccountId) -> Result<(), DispatchError> { Account::::try_mutate(who, |a| { if a.providers > 0 { - if a.consumers < T::MaxConsumers::get() { + if a.consumers < T::MaxConsumers::max_consumers() { a.consumers = a.consumers.saturating_add(1); Ok(()) } else { @@ -1138,6 +1168,20 @@ impl Pallet { }) } + /// Increment the reference counter on an account, ignoring the `MaxConsumers` limits. + /// + /// The account `who`'s `providers` must be non-zero or this will return an error. + pub fn inc_consumers_without_limit(who: &T::AccountId) -> Result<(), DispatchError> { + Account::::try_mutate(who, |a| { + if a.providers > 0 { + a.consumers = a.consumers.saturating_add(1); + Ok(()) + } else { + Err(DispatchError::NoProviders) + } + }) + } + /// Decrement the reference counter on an account. This *MUST* only be done once for every time /// you called `inc_consumers` on `who`. pub fn dec_consumers(who: &T::AccountId) { @@ -1172,7 +1216,7 @@ impl Pallet { /// True if the account has at least one provider reference. pub fn can_inc_consumer(who: &T::AccountId) -> bool { let a = Account::::get(who); - a.providers > 0 && a.consumers < T::MaxConsumers::get() + a.providers > 0 && a.consumers < T::MaxConsumers::max_consumers() } /// Deposits an event into this block's event record. From edaf25f99a86011c3249125274e8889b06f7adb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Wed, 15 Dec 2021 08:35:05 +0100 Subject: [PATCH 294/695] Emit `ContractReverted` error when revert flag is set (#10481) * Emit `ContractReverted` error when revert flag is set * `is_success()` -> `did_revert()` --- frame/contracts/common/src/lib.rs | 12 +++- frame/contracts/src/exec.rs | 10 +-- frame/contracts/src/lib.rs | 26 +++++++- frame/contracts/src/tests.rs | 103 ++++++++++++++++++++++++++++-- frame/contracts/src/wasm/mod.rs | 4 +- 5 files changed, 136 insertions(+), 19 deletions(-) diff --git a/frame/contracts/common/src/lib.rs b/frame/contracts/common/src/lib.rs index d8408f77e06e..b5873869495e 100644 --- a/frame/contracts/common/src/lib.rs +++ b/frame/contracts/common/src/lib.rs @@ -131,9 +131,9 @@ pub struct ExecReturnValue { } impl ExecReturnValue { - /// We understand the absense of a revert flag as success. - pub fn is_success(&self) -> bool { - !self.flags.contains(ReturnFlags::REVERT) + /// The contract did revert all storage changes. + pub fn did_revert(&self) -> bool { + self.flags.contains(ReturnFlags::REVERT) } } @@ -170,6 +170,12 @@ pub enum Code { Existing(Hash), } +impl>, Hash> From for Code { + fn from(from: T) -> Self { + Code::Upload(Bytes(from.into())) + } +} + /// The amount of balance that was either charged or refunded in order to pay for storage. #[derive(Eq, PartialEq, Ord, PartialOrd, Encode, Decode, RuntimeDebug, Clone)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] diff --git a/frame/contracts/src/exec.rs b/frame/contracts/src/exec.rs index 916c2d3df84f..bd54c7a08c63 100644 --- a/frame/contracts/src/exec.rs +++ b/frame/contracts/src/exec.rs @@ -686,7 +686,7 @@ where .map_err(|e| ExecError { error: e.error, origin: ErrorOrigin::Callee })?; // Additional work needs to be performed in case of an instantiation. - if output.is_success() && entry_point == ExportedFunction::Constructor { + if !output.did_revert() && entry_point == ExportedFunction::Constructor { let frame = self.top_frame(); // It is not allowed to terminate a contract inside its constructor. @@ -713,7 +713,7 @@ where let (success, output) = with_transaction(|| { let output = do_transaction(); match &output { - Ok(result) if result.is_success() => TransactionOutcome::Commit((true, output)), + Ok(result) if !result.did_revert() => TransactionOutcome::Commit((true, output)), _ => TransactionOutcome::Rollback((false, output)), } }); @@ -1352,7 +1352,7 @@ mod tests { ) .unwrap(); - assert!(!output.is_success()); + assert!(output.did_revert()); assert_eq!(get_balance(&origin), 100); assert_eq!(get_balance(&dest), balance); }); @@ -1403,7 +1403,7 @@ mod tests { ); let output = result.unwrap(); - assert!(output.is_success()); + assert!(!output.did_revert()); assert_eq!(output.data, Bytes(vec![1, 2, 3, 4])); }); } @@ -1435,7 +1435,7 @@ mod tests { ); let output = result.unwrap(); - assert!(!output.is_success()); + assert!(output.did_revert()); assert_eq!(output.data, Bytes(vec![1, 2, 3, 4])); }); } diff --git a/frame/contracts/src/lib.rs b/frame/contracts/src/lib.rs index 0b8786fa704a..b604c9618c6a 100644 --- a/frame/contracts/src/lib.rs +++ b/frame/contracts/src/lib.rs @@ -289,7 +289,7 @@ pub mod pallet { ) -> DispatchResultWithPostInfo { let origin = ensure_signed(origin)?; let dest = T::Lookup::lookup(dest)?; - let output = Self::internal_call( + let mut output = Self::internal_call( origin, dest, value, @@ -298,6 +298,11 @@ pub mod pallet { data, None, ); + if let Ok(retval) = &output.result { + if retval.did_revert() { + output.result = Err(>::ContractReverted.into()); + } + } output.gas_meter.into_dispatch_result(output.result, T::WeightInfo::call()) } @@ -346,7 +351,7 @@ pub mod pallet { let origin = ensure_signed(origin)?; let code_len = code.len() as u32; let salt_len = salt.len() as u32; - let output = Self::internal_instantiate( + let mut output = Self::internal_instantiate( origin, value, gas_limit, @@ -356,6 +361,11 @@ pub mod pallet { salt, None, ); + if let Ok(retval) = &output.result { + if retval.1.did_revert() { + output.result = Err(>::ContractReverted.into()); + } + } output.gas_meter.into_dispatch_result( output.result.map(|(_address, result)| result), T::WeightInfo::instantiate_with_code(code_len / 1024, salt_len / 1024), @@ -381,7 +391,7 @@ pub mod pallet { ) -> DispatchResultWithPostInfo { let origin = ensure_signed(origin)?; let salt_len = salt.len() as u32; - let output = Self::internal_instantiate( + let mut output = Self::internal_instantiate( origin, value, gas_limit, @@ -391,6 +401,11 @@ pub mod pallet { salt, None, ); + if let Ok(retval) = &output.result { + if retval.1.did_revert() { + output.result = Err(>::ContractReverted.into()); + } + } output.gas_meter.into_dispatch_result( output.result.map(|(_address, output)| output), T::WeightInfo::instantiate(salt_len / 1024), @@ -540,6 +555,11 @@ pub mod pallet { StorageDepositLimitExhausted, /// Code removal was denied because the code is still in use by at least one contract. CodeInUse, + /// The contract ran to completion but decided to revert its storage changes. + /// Please note that this error is only returned from extrinsics. When called directly + /// or via RPC an `Ok` will be returned. In this case the caller needs to inspect the flags + /// to determine whether a reversion has taken place. + ContractReverted, } /// A mapping from an original code hash to the original code, untouched by instrumentation. diff --git a/frame/contracts/src/tests.rs b/frame/contracts/src/tests.rs index 1078a7e73352..e7745e1e5f7f 100644 --- a/frame/contracts/src/tests.rs +++ b/frame/contracts/src/tests.rs @@ -24,7 +24,7 @@ use crate::{ storage::Storage, wasm::{PrefabWasmModule, ReturnCode as RuntimeReturnCode}, weights::WeightInfo, - BalanceOf, CodeStorage, Config, ContractInfoOf, Error, Pallet, Schedule, + BalanceOf, Code, CodeStorage, Config, ContractInfoOf, Error, Pallet, Schedule, }; use assert_matches::assert_matches; use codec::Encode; @@ -1096,7 +1096,7 @@ fn crypto_hashes() { >::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, None, params, false) .result .unwrap(); - assert!(result.is_success()); + assert!(!result.did_revert()); let expected = hash_fn(input.as_ref()); assert_eq!(&result.data[..*expected_size], &*expected); } @@ -1881,11 +1881,11 @@ fn reinstrument_does_charge() { let result0 = Contracts::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, None, zero.clone(), false); - assert!(result0.result.unwrap().is_success()); + assert!(!result0.result.unwrap().did_revert()); let result1 = Contracts::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, None, zero.clone(), false); - assert!(result1.result.unwrap().is_success()); + assert!(!result1.result.unwrap().did_revert()); // They should match because both where called with the same schedule. assert_eq!(result0.gas_consumed, result1.gas_consumed); @@ -1899,7 +1899,7 @@ fn reinstrument_does_charge() { // This call should trigger reinstrumentation let result2 = Contracts::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, None, zero.clone(), false); - assert!(result2.result.unwrap().is_success()); + assert!(!result2.result.unwrap().did_revert()); assert!(result2.gas_consumed > result1.gas_consumed); assert_eq!( result2.gas_consumed, @@ -2162,7 +2162,7 @@ fn ecdsa_recover() { >::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, None, params, false) .result .unwrap(); - assert!(result.is_success()); + assert!(!result.did_revert()); assert_eq!(result.data.as_ref(), &EXPECTED_COMPRESSED_PUBLIC_KEY); }) } @@ -2808,3 +2808,94 @@ fn call_after_killed_account_needs_funding() { ); }); } + +#[test] +fn contract_reverted() { + let (wasm, code_hash) = compile_module::("return_with_data").unwrap(); + + ExtBuilder::default().existential_deposit(100).build().execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + let flags = ReturnFlags::REVERT; + let buffer = [4u8, 8, 15, 16, 23, 42]; + let input = (flags.bits(), buffer).encode(); + + // We just upload the code for later use + assert_ok!(Contracts::upload_code(Origin::signed(ALICE), wasm.clone(), None)); + + // Calling extrinsic: revert leads to an error + assert_err_ignore_postinfo!( + Contracts::instantiate( + Origin::signed(ALICE), + 0, + GAS_LIMIT, + None, + code_hash, + input.clone(), + vec![], + ), + >::ContractReverted, + ); + + // Calling extrinsic: revert leads to an error + assert_err_ignore_postinfo!( + Contracts::instantiate_with_code( + Origin::signed(ALICE), + 0, + GAS_LIMIT, + None, + wasm, + input.clone(), + vec![], + ), + >::ContractReverted, + ); + + // Calling directly: revert leads to success but the flags indicate the error + // This is just a different way of transporting the error that allows the read out + // the `data` which is only there on success. Obviously, the contract isn't + // instantiated. + let result = Contracts::bare_instantiate( + ALICE, + 0, + GAS_LIMIT, + None, + Code::Existing(code_hash), + input.clone(), + vec![], + false, + ) + .result + .unwrap(); + assert_eq!(result.result.flags, flags); + assert_eq!(result.result.data.0, buffer); + assert!(!>::contains_key(result.account_id)); + + // Pass empty flags and therefore successfully instantiate the contract for later use. + let addr = Contracts::bare_instantiate( + ALICE, + 0, + GAS_LIMIT, + None, + Code::Existing(code_hash), + ReturnFlags::empty().bits().encode(), + vec![], + false, + ) + .result + .unwrap() + .account_id; + + // Calling extrinsic: revert leads to an error + assert_err_ignore_postinfo!( + Contracts::call(Origin::signed(ALICE), addr.clone(), 0, GAS_LIMIT, None, input.clone()), + >::ContractReverted, + ); + + // Calling directly: revert leads to success but the flags indicate the error + let result = Contracts::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, None, input, false) + .result + .unwrap(); + assert_eq!(result.flags, flags); + assert_eq!(result.data.0, buffer); + }); +} diff --git a/frame/contracts/src/wasm/mod.rs b/frame/contracts/src/wasm/mod.rs index 01e220d410fa..913894e8152d 100644 --- a/frame/contracts/src/wasm/mod.rs +++ b/frame/contracts/src/wasm/mod.rs @@ -1765,7 +1765,7 @@ mod tests { data: Bytes(hex!("445566778899").to_vec()), } ); - assert!(output.is_success()); + assert!(!output.did_revert()); } #[test] @@ -1781,7 +1781,7 @@ mod tests { data: Bytes(hex!("5566778899").to_vec()), } ); - assert!(!output.is_success()); + assert!(output.did_revert()); } const CODE_OUT_OF_BOUNDS_ACCESS: &str = r#" From 31cc6a535cdb019763f82f8f53342ffa077fdfc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Wed, 15 Dec 2021 09:15:48 +0100 Subject: [PATCH 295/695] sp-version: Add some more docs. (#10486) * sp-version: Add some more docs. * Apply suggestions from code review Co-authored-by: Shawn Tabrizi * Update lib.rs Co-authored-by: Shawn Tabrizi --- primitives/version/Cargo.toml | 1 - primitives/version/src/lib.rs | 42 +++++++++++++++++++++++++++++++---- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/primitives/version/Cargo.toml b/primitives/version/Cargo.toml index 103fe16dc53a..a58b27c7c151 100644 --- a/primitives/version/Cargo.toml +++ b/primitives/version/Cargo.toml @@ -13,7 +13,6 @@ readme = "README.md" [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] - [dependencies] impl-serde = { version = "0.3.1", optional = true } serde = { version = "1.0.126", optional = true, features = ["derive"] } diff --git a/primitives/version/src/lib.rs b/primitives/version/src/lib.rs index 58216bc494dd..0b72865e7b69 100644 --- a/primitives/version/src/lib.rs +++ b/primitives/version/src/lib.rs @@ -15,7 +15,21 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Version module for the Substrate runtime; Provides a function that returns the runtime version. +//! Substrate runtime version +//! +//! Each runtime that should be executed by a Substrate based node needs to have a runtime version. +//! The runtime version is defined by [`RuntimeVersion`]. The runtime version is used to +//! distinguish different runtimes. The most important field is the +//! [`spec_version`](RuntimeVersion::spec_version). The `spec_version` should be increased in a +//! runtime when a new runtime build includes breaking changes that would make other runtimes unable +//! to import blocks built by this runtime or vice-versa, where the new runtime could not import +//! blocks built by the old runtime. The runtime version also carries other version information +//! about the runtime, see [`RuntimeVersion`] for more information on this. +//! +//! Substrate will fetch the runtime version from a `wasm` blob by first checking the +//! `runtime_version` link section or calling the `Core::version` runtime api. The link section can +//! be generated in the runtime using the [`runtime_version`] attribute. The `Core` runtime api also +//! needs to be implemented for the runtime using `impl_runtime_apis!`. #![cfg_attr(not(feature = "std"), no_std)] @@ -104,7 +118,23 @@ pub use sp_version_proc_macro::runtime_version; /// The id is generated by hashing the name of the runtime api with BLAKE2 using a hash size /// of 8 bytes. /// -/// The name of the runtime api is the name of the trait when using `decl_runtime_apis!` macro. +/// The name of the runtime api is the name of the trait when using `decl_runtime_apis!` macro. So, +/// in the following runtime api declaration: +/// +/// ```nocompile +/// decl_runtime_apis! { +/// trait TestApi { +/// fn do_test(); +/// } +/// } +/// ``` +/// +/// The name of the trait would be `TestApi` and would be taken as input to the BLAKE2 hash +/// function. +/// +/// As Rust supports renaming of traits, the name of a runtime api given to `impl_runtime_apis!` +/// doesn't need to be the same as in `decl_runtime_apis!`, but only the name in +/// `decl_runtime_apis!` is the important one! pub type ApiId = [u8; 8]; /// A vector of pairs of `ApiId` and a `u32` for version. @@ -216,12 +246,16 @@ impl RuntimeVersion { } } -#[cfg(feature = "std")] +/// The version of the native runtime. +/// +/// In contrast to the bare [`RuntimeVersion`] this also carries a list of `spec_version`s of +/// runtimes this native runtime can be used to author blocks for. #[derive(Debug)] +#[cfg(feature = "std")] pub struct NativeVersion { /// Basic runtime version info. pub runtime_version: RuntimeVersion, - /// Authoring runtimes that this native runtime supports. + /// Authoring runtimes (`spec_version`s) that this native runtime supports. pub can_author_with: HashSet, } From 027368fe34e9a57ead752d4f900db6b5f85352e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Wed, 15 Dec 2021 12:13:18 +0100 Subject: [PATCH 296/695] Fix link to grafana dashboard (#10492) --- .maintain/monitoring/grafana-dashboards/README_dashboard.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.maintain/monitoring/grafana-dashboards/README_dashboard.md b/.maintain/monitoring/grafana-dashboards/README_dashboard.md index e00b89449cfa..50f54a107e93 100644 --- a/.maintain/monitoring/grafana-dashboards/README_dashboard.md +++ b/.maintain/monitoring/grafana-dashboards/README_dashboard.md @@ -4,4 +4,4 @@ Shared templated Grafana dashboards. To import the dashboards follow the [Grafana documentation](https://grafana.com/docs/grafana/latest/reference/export_import/). -You can see an example setup [here](../../../.maintain/sentry-node). +You can see an example setup [here](./substrate-networking.json). From 50ab759f7a3194173ce8da0937ec2d888dee10e0 Mon Sep 17 00:00:00 2001 From: David Date: Wed, 15 Dec 2021 12:36:17 +0100 Subject: [PATCH 297/695] Prepare `sp-runtime` for publication (#10451) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Bump versions of sp-core and dependencies to v4.0.0 * Update references from `4.0.0-dev` –> `4.0.0` * Funny whitespace * Funny whitespace 2 * Prepare `sp-runtime` for publication --- Cargo.lock | 16 ++++++++-------- bin/node-template/node/Cargo.toml | 2 +- bin/node-template/pallets/template/Cargo.toml | 2 +- bin/node-template/runtime/Cargo.toml | 2 +- bin/node/bench/Cargo.toml | 6 +++--- bin/node/cli/Cargo.toml | 6 +++--- bin/node/executor/Cargo.toml | 10 +++++----- bin/node/inspect/Cargo.toml | 2 +- bin/node/primitives/Cargo.toml | 4 ++-- bin/node/rpc/Cargo.toml | 4 ++-- bin/node/runtime/Cargo.toml | 4 ++-- bin/node/testing/Cargo.toml | 2 +- bin/utils/chain-spec-builder/Cargo.toml | 2 +- client/api/Cargo.toml | 8 ++++---- client/authority-discovery/Cargo.toml | 4 ++-- client/basic-authorship/Cargo.toml | 2 +- client/beefy/Cargo.toml | 8 ++++---- client/beefy/rpc/Cargo.toml | 2 +- client/block-builder/Cargo.toml | 4 ++-- client/chain-spec/Cargo.toml | 2 +- client/cli/Cargo.toml | 6 +++--- client/consensus/aura/Cargo.toml | 6 +++--- client/consensus/babe/Cargo.toml | 8 ++++---- client/consensus/babe/rpc/Cargo.toml | 6 +++--- client/consensus/common/Cargo.toml | 4 ++-- client/consensus/epochs/Cargo.toml | 2 +- client/consensus/manual-seal/Cargo.toml | 4 ++-- client/consensus/pow/Cargo.toml | 2 +- client/consensus/slots/Cargo.toml | 6 +++--- client/consensus/uncles/Cargo.toml | 2 +- client/db/Cargo.toml | 8 ++++---- client/executor/Cargo.toml | 8 ++++---- client/executor/runtime-test/Cargo.toml | 2 +- client/executor/wasmtime/Cargo.toml | 2 +- client/finality-grandpa/Cargo.toml | 8 ++++---- client/finality-grandpa/rpc/Cargo.toml | 2 +- client/informant/Cargo.toml | 2 +- client/keystore/Cargo.toml | 4 ++-- client/network-gossip/Cargo.toml | 2 +- client/network/Cargo.toml | 4 ++-- client/network/test/Cargo.toml | 2 +- client/offchain/Cargo.toml | 2 +- client/rpc-api/Cargo.toml | 2 +- client/rpc/Cargo.toml | 6 +++--- client/service/Cargo.toml | 10 +++++----- client/service/test/Cargo.toml | 8 ++++---- client/sync-state-rpc/Cargo.toml | 2 +- client/tracing/Cargo.toml | 2 +- client/transaction-pool/Cargo.toml | 2 +- client/transaction-pool/api/Cargo.toml | 2 +- frame/assets/Cargo.toml | 4 ++-- frame/atomic-swap/Cargo.toml | 2 +- frame/aura/Cargo.toml | 4 ++-- frame/authority-discovery/Cargo.toml | 4 ++-- frame/authorship/Cargo.toml | 2 +- frame/babe/Cargo.toml | 6 +++--- frame/bags-list/Cargo.toml | 2 +- frame/bags-list/remote-tests/Cargo.toml | 2 +- frame/balances/Cargo.toml | 2 +- frame/beefy-mmr/Cargo.toml | 2 +- frame/beefy/Cargo.toml | 2 +- frame/benchmarking/Cargo.toml | 8 ++++---- frame/bounties/Cargo.toml | 4 ++-- frame/child-bounties/Cargo.toml | 2 +- frame/collective/Cargo.toml | 2 +- frame/contracts/Cargo.toml | 2 +- frame/contracts/common/Cargo.toml | 2 +- frame/contracts/rpc/Cargo.toml | 2 +- frame/contracts/rpc/runtime-api/Cargo.toml | 2 +- frame/democracy/Cargo.toml | 4 ++-- frame/election-provider-multi-phase/Cargo.toml | 6 +++--- frame/election-provider-support/Cargo.toml | 4 ++-- frame/elections-phragmen/Cargo.toml | 4 ++-- frame/examples/basic/Cargo.toml | 4 ++-- frame/examples/offchain-worker/Cargo.toml | 4 ++-- frame/examples/parallel/Cargo.toml | 2 +- frame/executive/Cargo.toml | 2 +- frame/gilt/Cargo.toml | 4 ++-- frame/grandpa/Cargo.toml | 6 +++--- frame/identity/Cargo.toml | 4 ++-- frame/im-online/Cargo.toml | 6 +++--- frame/indices/Cargo.toml | 2 +- frame/lottery/Cargo.toml | 2 +- frame/membership/Cargo.toml | 2 +- frame/merkle-mountain-range/Cargo.toml | 2 +- .../merkle-mountain-range/primitives/Cargo.toml | 2 +- frame/merkle-mountain-range/rpc/Cargo.toml | 2 +- frame/multisig/Cargo.toml | 4 ++-- frame/nicks/Cargo.toml | 4 ++-- frame/node-authorization/Cargo.toml | 2 +- frame/offences/Cargo.toml | 2 +- frame/offences/benchmarking/Cargo.toml | 2 +- frame/preimage/Cargo.toml | 2 +- frame/proxy/Cargo.toml | 4 ++-- frame/randomness-collective-flip/Cargo.toml | 2 +- frame/recovery/Cargo.toml | 4 ++-- frame/scheduler/Cargo.toml | 4 ++-- frame/scored-pool/Cargo.toml | 4 ++-- frame/session/Cargo.toml | 4 ++-- frame/session/benchmarking/Cargo.toml | 2 +- frame/society/Cargo.toml | 2 +- frame/staking/Cargo.toml | 6 +++--- frame/staking/reward-curve/Cargo.toml | 2 +- frame/staking/reward-fn/Cargo.toml | 2 +- frame/sudo/Cargo.toml | 4 ++-- frame/support/Cargo.toml | 8 ++++---- frame/support/test/Cargo.toml | 8 ++++---- frame/support/test/compile_pass/Cargo.toml | 2 +- frame/system/Cargo.toml | 4 ++-- frame/system/benchmarking/Cargo.toml | 4 ++-- frame/timestamp/Cargo.toml | 4 ++-- frame/tips/Cargo.toml | 2 +- frame/transaction-payment/Cargo.toml | 2 +- .../asset-tx-payment/Cargo.toml | 2 +- frame/transaction-payment/rpc/Cargo.toml | 2 +- .../rpc/runtime-api/Cargo.toml | 2 +- frame/transaction-storage/Cargo.toml | 4 ++-- frame/treasury/Cargo.toml | 2 +- frame/try-runtime/Cargo.toml | 2 +- frame/uniques/Cargo.toml | 2 +- frame/utility/Cargo.toml | 4 ++-- frame/vesting/Cargo.toml | 2 +- primitives/api/Cargo.toml | 4 ++-- primitives/api/test/Cargo.toml | 4 ++-- primitives/application-crypto/Cargo.toml | 4 ++-- primitives/application-crypto/test/Cargo.toml | 6 +++--- primitives/arithmetic/Cargo.toml | 2 +- primitives/arithmetic/fuzzer/Cargo.toml | 2 +- primitives/authority-discovery/Cargo.toml | 4 ++-- primitives/authorship/Cargo.toml | 2 +- primitives/beefy/Cargo.toml | 6 +++--- primitives/block-builder/Cargo.toml | 2 +- primitives/blockchain/Cargo.toml | 4 ++-- primitives/consensus/aura/Cargo.toml | 4 ++-- primitives/consensus/babe/Cargo.toml | 6 +++--- primitives/consensus/common/Cargo.toml | 4 ++-- primitives/consensus/pow/Cargo.toml | 2 +- primitives/consensus/slots/Cargo.toml | 4 ++-- primitives/consensus/vrf/Cargo.toml | 2 +- primitives/finality-grandpa/Cargo.toml | 6 +++--- primitives/inherents/Cargo.toml | 2 +- primitives/io/Cargo.toml | 8 ++++---- primitives/keyring/Cargo.toml | 2 +- primitives/keystore/Cargo.toml | 2 +- primitives/npos-elections/Cargo.toml | 4 ++-- primitives/npos-elections/fuzzer/Cargo.toml | 2 +- .../npos-elections/solution-type/Cargo.toml | 2 +- primitives/offchain/Cargo.toml | 2 +- primitives/panic-handler/Cargo.toml | 2 +- primitives/runtime-interface/Cargo.toml | 2 +- primitives/runtime-interface/test/Cargo.toml | 6 +++--- primitives/runtime/Cargo.toml | 10 +++++----- primitives/sandbox/Cargo.toml | 2 +- primitives/session/Cargo.toml | 2 +- primitives/staking/Cargo.toml | 2 +- primitives/state-machine/Cargo.toml | 8 ++++---- primitives/tasks/Cargo.toml | 2 +- primitives/test-primitives/Cargo.toml | 4 ++-- primitives/timestamp/Cargo.toml | 2 +- primitives/transaction-pool/Cargo.toml | 2 +- primitives/transaction-storage-proof/Cargo.toml | 4 ++-- primitives/trie/Cargo.toml | 4 ++-- primitives/version/Cargo.toml | 2 +- test-utils/client/Cargo.toml | 6 +++--- test-utils/runtime/Cargo.toml | 10 +++++----- test-utils/runtime/client/Cargo.toml | 2 +- test-utils/runtime/transaction-pool/Cargo.toml | 2 +- utils/frame/benchmarking-cli/Cargo.toml | 6 +++--- utils/frame/frame-utilities-cli/Cargo.toml | 2 +- utils/frame/generate-bags/Cargo.toml | 2 +- utils/frame/remote-externalities/Cargo.toml | 2 +- utils/frame/rpc/system/Cargo.toml | 2 +- utils/frame/try-runtime/cli/Cargo.toml | 6 +++--- 173 files changed, 317 insertions(+), 317 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c6c49939a8ff..0364fafd2547 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9203,7 +9203,7 @@ dependencies = [ [[package]] name = "sp-application-crypto" -version = "4.0.0-dev" +version = "4.0.0" dependencies = [ "parity-scale-codec", "scale-info", @@ -9227,7 +9227,7 @@ dependencies = [ [[package]] name = "sp-arithmetic" -version = "4.0.0-dev" +version = "4.0.0" dependencies = [ "criterion", "integer-sqrt", @@ -9528,7 +9528,7 @@ dependencies = [ [[package]] name = "sp-io" -version = "4.0.0-dev" +version = "4.0.0" dependencies = [ "futures 0.3.16", "hash-db", @@ -9561,7 +9561,7 @@ dependencies = [ [[package]] name = "sp-keystore" -version = "0.10.0-dev" +version = "0.10.0" dependencies = [ "async-trait", "derive_more", @@ -9639,7 +9639,7 @@ dependencies = [ [[package]] name = "sp-panic-handler" -version = "4.0.0-dev" +version = "4.0.0" dependencies = [ "backtrace", "lazy_static", @@ -9658,7 +9658,7 @@ dependencies = [ [[package]] name = "sp-runtime" -version = "4.0.0-dev" +version = "4.0.0" dependencies = [ "either", "hash256-std-hasher", @@ -9802,7 +9802,7 @@ dependencies = [ [[package]] name = "sp-state-machine" -version = "0.10.0-dev" +version = "0.10.0" dependencies = [ "hash-db", "hex-literal", @@ -9917,7 +9917,7 @@ dependencies = [ [[package]] name = "sp-trie" -version = "4.0.0-dev" +version = "4.0.0" dependencies = [ "criterion", "hash-db", diff --git a/bin/node-template/node/Cargo.toml b/bin/node-template/node/Cargo.toml index 731e6fcda408..dbf44a75c139 100644 --- a/bin/node-template/node/Cargo.toml +++ b/bin/node-template/node/Cargo.toml @@ -34,7 +34,7 @@ sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/commo sc-finality-grandpa = { version = "0.10.0-dev", path = "../../../client/finality-grandpa" } sp-finality-grandpa = { version = "4.0.0-dev", path = "../../../primitives/finality-grandpa" } sc-client-api = { version = "4.0.0-dev", path = "../../../client/api" } -sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } sp-timestamp = { version = "4.0.0-dev", path = "../../../primitives/timestamp" } # These dependencies are used for the node template's RPCs diff --git a/bin/node-template/pallets/template/Cargo.toml b/bin/node-template/pallets/template/Cargo.toml index d473119702f8..ab69a3fe73ea 100644 --- a/bin/node-template/pallets/template/Cargo.toml +++ b/bin/node-template/pallets/template/Cargo.toml @@ -24,7 +24,7 @@ frame-benchmarking = { default-features = false, version = "4.0.0-dev", path = " [dev-dependencies] sp-core = { default-features = false, version = "4.1.0-dev", path = "../../../../primitives/core" } sp-io = { default-features = false, version = "4.0.0-dev", path = "../../../../primitives/io" } -sp-runtime = { default-features = false, version = "4.0.0-dev", path = "../../../../primitives/runtime" } +sp-runtime = { default-features = false, version = "4.0.0", path = "../../../../primitives/runtime" } [features] default = ["std"] diff --git a/bin/node-template/runtime/Cargo.toml b/bin/node-template/runtime/Cargo.toml index 4818535e196c..c56162c8ffed 100644 --- a/bin/node-template/runtime/Cargo.toml +++ b/bin/node-template/runtime/Cargo.toml @@ -32,7 +32,7 @@ sp-consensus-aura = { version = "0.10.0-dev", default-features = false, path = " sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } sp-inherents = { path = "../../../primitives/inherents", default-features = false, version = "4.0.0-dev"} sp-offchain = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/offchain" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../../primitives/runtime" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/session" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } sp-transaction-pool = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/transaction-pool" } diff --git a/bin/node/bench/Cargo.toml b/bin/node/bench/Cargo.toml index 65d12378c4cf..8d2ca810273c 100644 --- a/bin/node/bench/Cargo.toml +++ b/bin/node/bench/Cargo.toml @@ -14,15 +14,15 @@ node-primitives = { version = "2.0.0", path = "../primitives" } node-testing = { version = "3.0.0-dev", path = "../testing" } node-runtime = { version = "3.0.0-dev", path = "../runtime" } sc-client-api = { version = "4.0.0-dev", path = "../../../client/api/" } -sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } -sp-state-machine = { version = "0.10.0-dev", path = "../../../primitives/state-machine" } +sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } +sp-state-machine = { version = "0.10.0", path = "../../../primitives/state-machine" } serde = "1.0.126" serde_json = "1.0.71" structopt = "0.3" derive_more = "0.99.16" kvdb = "0.10.0" kvdb-rocksdb = "0.14.0" -sp-trie = { version = "4.0.0-dev", path = "../../../primitives/trie" } +sp-trie = { version = "4.0.0", path = "../../../primitives/trie" } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" } sc-basic-authorship = { version = "0.10.0-dev", path = "../../../client/basic-authorship" } diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index 6da2fddd331e..d7143b39816b 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -48,12 +48,12 @@ sp-consensus-babe = { version = "0.10.0-dev", path = "../../../primitives/consen grandpa-primitives = { version = "4.0.0-dev", package = "sp-finality-grandpa", path = "../../../primitives/finality-grandpa" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } -sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } sp-timestamp = { version = "4.0.0-dev", path = "../../../primitives/timestamp" } sp-authorship = { version = "4.0.0-dev", path = "../../../primitives/authorship" } sp-inherents = { version = "4.0.0-dev", path = "../../../primitives/inherents" } sp-keyring = { version = "4.0.0-dev", path = "../../../primitives/keyring" } -sp-keystore = { version = "0.10.0-dev", path = "../../../primitives/keystore" } +sp-keystore = { version = "0.10.0", path = "../../../primitives/keystore" } sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" } sp-transaction-pool = { version = "4.0.0-dev", path = "../../../primitives/transaction-pool" } sp-transaction-storage-proof = { version = "4.0.0-dev", path = "../../../primitives/transaction-storage-proof" } @@ -106,7 +106,7 @@ sc-cli = { version = "0.10.0-dev", optional = true, path = "../../../client/cli" sc-service = { version = "0.10.0-dev", default-features = false, path = "../../../client/service", features = [ "wasmtime", ] } -sp-trie = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/trie", features = [ +sp-trie = { version = "4.0.0", default-features = false, path = "../../../primitives/trie", features = [ "memory-tracker", ] } diff --git a/bin/node/executor/Cargo.toml b/bin/node/executor/Cargo.toml index 20898315d0e0..531e53d2048a 100644 --- a/bin/node/executor/Cargo.toml +++ b/bin/node/executor/Cargo.toml @@ -18,10 +18,10 @@ node-primitives = { version = "2.0.0", path = "../primitives" } node-runtime = { version = "3.0.0-dev", path = "../runtime" } sc-executor = { version = "0.10.0-dev", path = "../../../client/executor" } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } -sp-keystore = { version = "0.10.0-dev", path = "../../../primitives/keystore" } -sp-state-machine = { version = "0.10.0-dev", path = "../../../primitives/state-machine" } +sp-keystore = { version = "0.10.0", path = "../../../primitives/keystore" } +sp-state-machine = { version = "0.10.0", path = "../../../primitives/state-machine" } sp-tracing = { version = "4.0.0", path = "../../../primitives/tracing" } -sp-trie = { version = "4.0.0-dev", path = "../../../primitives/trie" } +sp-trie = { version = "4.0.0", path = "../../../primitives/trie" } frame-benchmarking = { version = "4.0.0-dev", path = "../../../frame/benchmarking" } [dev-dependencies] @@ -34,9 +34,9 @@ pallet-contracts = { version = "4.0.0-dev", path = "../../../frame/contracts" } pallet-im-online = { version = "4.0.0-dev", path = "../../../frame/im-online" } pallet-timestamp = { version = "4.0.0-dev", path = "../../../frame/timestamp" } pallet-treasury = { version = "4.0.0-dev", path = "../../../frame/treasury" } -sp-application-crypto = { version = "4.0.0-dev", path = "../../../primitives/application-crypto" } +sp-application-crypto = { version = "4.0.0", path = "../../../primitives/application-crypto" } sp-consensus-babe = { version = "0.10.0-dev", path = "../../../primitives/consensus/babe" } -sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } sp-externalities = { version = "0.10.0", path = "../../../primitives/externalities" } sp-keyring = { version = "4.0.0-dev", path = "../../../primitives/keyring" } wat = "1.0" diff --git a/bin/node/inspect/Cargo.toml b/bin/node/inspect/Cargo.toml index b0db8f630476..cb9557b506a1 100644 --- a/bin/node/inspect/Cargo.toml +++ b/bin/node/inspect/Cargo.toml @@ -19,5 +19,5 @@ sc-executor = { version = "0.10.0-dev", path = "../../../client/executor" } sc-service = { version = "0.10.0-dev", default-features = false, path = "../../../client/service" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } -sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } structopt = "0.3.8" diff --git a/bin/node/primitives/Cargo.toml b/bin/node/primitives/Cargo.toml index d2c315bd9b6e..05def58be234 100644 --- a/bin/node/primitives/Cargo.toml +++ b/bin/node/primitives/Cargo.toml @@ -16,9 +16,9 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../../frame/system" } -sp-application-crypto = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/application-crypto" } +sp-application-crypto = { version = "4.0.0", default-features = false, path = "../../../primitives/application-crypto" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../../primitives/runtime" } [features] default = ["std"] diff --git a/bin/node/rpc/Cargo.toml b/bin/node/rpc/Cargo.toml index ef111e3f1949..3eed3ad4e0cc 100644 --- a/bin/node/rpc/Cargo.toml +++ b/bin/node/rpc/Cargo.toml @@ -29,9 +29,9 @@ sc-sync-state-rpc = { version = "0.10.0-dev", path = "../../../client/sync-state sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-block-builder = { version = "4.0.0-dev", path = "../../../primitives/block-builder" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-keystore = { version = "0.10.0-dev", path = "../../../primitives/keystore" } +sp-keystore = { version = "0.10.0", path = "../../../primitives/keystore" } sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" } sp-consensus-babe = { version = "0.10.0-dev", path = "../../../primitives/consensus/babe" } -sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../../../client/transaction-pool/api" } substrate-frame-rpc-system = { version = "4.0.0-dev", path = "../../../utils/frame/rpc/system" } diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 83a66f5a47b6..fa879adf5cbb 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -33,14 +33,14 @@ sp-offchain = { version = "4.0.0-dev", default-features = false, path = "../../. sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/api" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../../primitives/runtime" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/staking" } sp-keyring = { version = "4.0.0-dev", optional = true, path = "../../../primitives/keyring" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/session" } sp-transaction-pool = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/transaction-pool" } sp-version = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/version" } sp-npos-elections = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/npos-elections" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/io" } +sp-io = { version = "4.0.0", default-features = false, path = "../../../primitives/io" } sp-sandbox = { version = "0.10.0-dev", default-features = false, path = "../../../primitives/sandbox" } # frame dependencies diff --git a/bin/node/testing/Cargo.toml b/bin/node/testing/Cargo.toml index 7f3a91196248..bee6f92d1280 100644 --- a/bin/node/testing/Cargo.toml +++ b/bin/node/testing/Cargo.toml @@ -30,7 +30,7 @@ node-primitives = { version = "2.0.0", path = "../primitives" } node-runtime = { version = "3.0.0-dev", path = "../runtime" } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sp-io = { version = "4.0.0-dev", path = "../../../primitives/io" } -sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } sc-executor = { version = "0.10.0-dev", path = "../../../client/executor", features = [ "wasmtime", ] } diff --git a/bin/utils/chain-spec-builder/Cargo.toml b/bin/utils/chain-spec-builder/Cargo.toml index c5872ca29700..f9bb4f94491a 100644 --- a/bin/utils/chain-spec-builder/Cargo.toml +++ b/bin/utils/chain-spec-builder/Cargo.toml @@ -19,6 +19,6 @@ sc-keystore = { version = "4.0.0-dev", path = "../../../client/keystore" } sc-chain-spec = { version = "4.0.0-dev", path = "../../../client/chain-spec" } node-cli = { version = "3.0.0-dev", path = "../../node/cli" } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } -sp-keystore = { version = "0.10.0-dev", path = "../../../primitives/keystore" } +sp-keystore = { version = "0.10.0", path = "../../../primitives/keystore" } rand = "0.7.2" structopt = "0.3.25" diff --git a/client/api/Cargo.toml b/client/api/Cargo.toml index 13ec13538e65..4738a7d611b1 100644 --- a/client/api/Cargo.toml +++ b/client/api/Cargo.toml @@ -28,12 +28,12 @@ log = "0.4.8" parking_lot = "0.11.1" sp-database = { version = "4.0.0-dev", path = "../../primitives/database" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } -sp-keystore = { version = "0.10.0-dev", default-features = false, path = "../../primitives/keystore" } +sp-keystore = { version = "0.10.0", default-features = false, path = "../../primitives/keystore" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } sc-utils = { version = "4.0.0-dev", path = "../utils" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-state-machine = { version = "0.10.0-dev", path = "../../primitives/state-machine" } -sp-trie = { version = "4.0.0-dev", path = "../../primitives/trie" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-state-machine = { version = "0.10.0", path = "../../primitives/state-machine" } +sp-trie = { version = "4.0.0", path = "../../primitives/trie" } sp-storage = { version = "4.0.0", path = "../../primitives/storage" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../transaction-pool/api" } prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.10.0-dev", path = "../../utils/prometheus" } diff --git a/client/authority-discovery/Cargo.toml b/client/authority-discovery/Cargo.toml index 207f22753e45..fd94e71ceb84 100644 --- a/client/authority-discovery/Cargo.toml +++ b/client/authority-discovery/Cargo.toml @@ -33,8 +33,8 @@ sc-network = { version = "0.10.0-dev", path = "../network" } sp-authority-discovery = { version = "4.0.0-dev", path = "../../primitives/authority-discovery" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } -sp-keystore = { version = "0.10.0-dev", path = "../../primitives/keystore" } -sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } +sp-keystore = { version = "0.10.0", path = "../../primitives/keystore" } +sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } [dev-dependencies] diff --git a/client/basic-authorship/Cargo.toml b/client/basic-authorship/Cargo.toml index c1a8e9210a41..4b4627cb6eea 100644 --- a/client/basic-authorship/Cargo.toml +++ b/client/basic-authorship/Cargo.toml @@ -19,7 +19,7 @@ futures-timer = "3.0.1" log = "0.4.8" prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.10.0-dev"} sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } -sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sc-client-api = { version = "4.0.0-dev", path = "../api" } diff --git a/client/beefy/Cargo.toml b/client/beefy/Cargo.toml index cb561c0dc77a..6c281deb85ea 100644 --- a/client/beefy/Cargo.toml +++ b/client/beefy/Cargo.toml @@ -19,12 +19,12 @@ codec = { version = "2.2.0", package = "parity-scale-codec", features = ["derive prometheus = { version = "0.10.0-dev", package = "substrate-prometheus-endpoint", path = "../../utils/prometheus" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } -sp-application-crypto = { version = "4.0.0-dev", path = "../../primitives/application-crypto" } -sp-arithmetic = { version = "4.0.0-dev", path = "../../primitives/arithmetic" } +sp-application-crypto = { version = "4.0.0", path = "../../primitives/application-crypto" } +sp-arithmetic = { version = "4.0.0", path = "../../primitives/arithmetic" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } -sp-keystore = { version = "0.10.0-dev", path = "../../primitives/keystore" } -sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } +sp-keystore = { version = "0.10.0", path = "../../primitives/keystore" } +sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } sc-utils = { version = "4.0.0-dev", path = "../utils" } sc-client-api = { version = "4.0.0-dev", path = "../api" } diff --git a/client/beefy/rpc/Cargo.toml b/client/beefy/rpc/Cargo.toml index 83f6b392f55c..9f4a1305f2d0 100644 --- a/client/beefy/rpc/Cargo.toml +++ b/client/beefy/rpc/Cargo.toml @@ -22,7 +22,7 @@ codec = { version = "2.2.0", package = "parity-scale-codec", features = ["derive sc-rpc = { version = "4.0.0-dev", path = "../../rpc" } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } -sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } beefy-gadget = { version = "4.0.0-dev", path = "../." } beefy-primitives = { version = "4.0.0-dev", path = "../../../primitives/beefy" } diff --git a/client/block-builder/Cargo.toml b/client/block-builder/Cargo.toml index 69154699e3f1..ab77bc005f6c 100644 --- a/client/block-builder/Cargo.toml +++ b/client/block-builder/Cargo.toml @@ -14,8 +14,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-state-machine = { version = "0.10.0-dev", path = "../../primitives/state-machine" } -sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } +sp-state-machine = { version = "0.10.0", path = "../../primitives/state-machine" } +sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } diff --git a/client/chain-spec/Cargo.toml b/client/chain-spec/Cargo.toml index fdc72307af2a..d06e0bce18c1 100644 --- a/client/chain-spec/Cargo.toml +++ b/client/chain-spec/Cargo.toml @@ -19,7 +19,7 @@ sc-network = { version = "0.10.0-dev", path = "../network" } sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } serde = { version = "1.0.126", features = ["derive"] } serde_json = "1.0.71" -sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } sc-telemetry = { version = "4.0.0-dev", path = "../telemetry" } codec = { package = "parity-scale-codec", version = "2.0.0" } memmap2 = "0.5.0" diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index 566ce21cfe90..2e2b208923d5 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -25,15 +25,15 @@ rand = "0.7.3" tiny-bip39 = "0.8.2" serde_json = "1.0.71" sc-keystore = { version = "4.0.0-dev", path = "../keystore" } -sp-panic-handler = { version = "4.0.0-dev", path = "../../primitives/panic-handler" } +sp-panic-handler = { version = "4.0.0", path = "../../primitives/panic-handler" } sc-client-api = { version = "4.0.0-dev", path = "../api" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sc-network = { version = "0.10.0-dev", path = "../network" } -sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } sc-utils = { version = "4.0.0-dev", path = "../utils" } sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } -sp-keystore = { version = "0.10.0-dev", path = "../../primitives/keystore" } +sp-keystore = { version = "0.10.0", path = "../../primitives/keystore" } sc-service = { version = "0.10.0-dev", default-features = false, path = "../service" } sc-telemetry = { version = "4.0.0-dev", path = "../telemetry" } sp-keyring = { version = "4.0.0-dev", path = "../../primitives/keyring" } diff --git a/client/consensus/aura/Cargo.toml b/client/consensus/aura/Cargo.toml index f12578b8a678..05f0d3804e7b 100644 --- a/client/consensus/aura/Cargo.toml +++ b/client/consensus/aura/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-application-crypto = { version = "4.0.0-dev", path = "../../../primitives/application-crypto" } +sp-application-crypto = { version = "4.0.0", path = "../../../primitives/application-crypto" } sp-consensus-aura = { version = "0.10.0-dev", path = "../../../primitives/consensus/aura" } sp-block-builder = { version = "4.0.0-dev", path = "../../../primitives/block-builder" } sc-block-builder = { version = "0.10.0-dev", path = "../../block-builder" } @@ -30,8 +30,8 @@ sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sc-consensus-slots = { version = "0.10.0-dev", path = "../slots" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } -sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } -sp-keystore = { version = "0.10.0-dev", path = "../../../primitives/keystore" } +sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } +sp-keystore = { version = "0.10.0", path = "../../../primitives/keystore" } sc-telemetry = { version = "4.0.0-dev", path = "../../telemetry" } prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.10.0-dev" } async-trait = "0.1.50" diff --git a/client/consensus/babe/Cargo.toml b/client/consensus/babe/Cargo.toml index 7daab5557b57..634c987444a0 100644 --- a/client/consensus/babe/Cargo.toml +++ b/client/consensus/babe/Cargo.toml @@ -20,14 +20,14 @@ codec = { package = "parity-scale-codec", version = "2.0.0", features = [ sp-consensus-babe = { version = "0.10.0-dev", path = "../../../primitives/consensus/babe" } sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/common" } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } -sp-application-crypto = { version = "4.0.0-dev", path = "../../../primitives/application-crypto" } -sp-keystore = { version = "0.10.0-dev", path = "../../../primitives/keystore" } +sp-application-crypto = { version = "4.0.0", path = "../../../primitives/application-crypto" } +sp-keystore = { version = "0.10.0", path = "../../../primitives/keystore" } num-bigint = "0.2.3" num-rational = "0.2.2" num-traits = "0.2.8" serde = { version = "1.0.126", features = ["derive"] } sp-version = { version = "4.0.0-dev", path = "../../../primitives/version" } -sp-io = { version = "4.0.0-dev", path = "../../../primitives/io" } +sp-io = { version = "4.0.0", path = "../../../primitives/io" } sp-inherents = { version = "4.0.0-dev", path = "../../../primitives/inherents" } sc-telemetry = { version = "4.0.0-dev", path = "../../telemetry" } sc-keystore = { version = "4.0.0-dev", path = "../../keystore" } @@ -40,7 +40,7 @@ sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/c sp-consensus-slots = { version = "0.10.0-dev", path = "../../../primitives/consensus/slots" } sp-consensus-vrf = { version = "0.10.0-dev", path = "../../../primitives/consensus/vrf" } sc-consensus-slots = { version = "0.10.0-dev", path = "../slots" } -sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } fork-tree = { version = "3.0.0", path = "../../../utils/fork-tree" } prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.10.0-dev" } futures = "0.3.9" diff --git a/client/consensus/babe/rpc/Cargo.toml b/client/consensus/babe/rpc/Cargo.toml index 3bd8bf6e7658..cea2aea4553b 100644 --- a/client/consensus/babe/rpc/Cargo.toml +++ b/client/consensus/babe/rpc/Cargo.toml @@ -21,15 +21,15 @@ jsonrpc-derive = "18.0.0" sp-consensus-babe = { version = "0.10.0-dev", path = "../../../../primitives/consensus/babe" } serde = { version = "1.0.126", features=["derive"] } sp-blockchain = { version = "4.0.0-dev", path = "../../../../primitives/blockchain" } -sp-runtime = { version = "4.0.0-dev", path = "../../../../primitives/runtime" } +sp-runtime = { version = "4.0.0", path = "../../../../primitives/runtime" } sc-consensus-epochs = { version = "0.10.0-dev", path = "../../epochs" } futures = "0.3.16" derive_more = "0.99.16" sp-api = { version = "4.0.0-dev", path = "../../../../primitives/api" } sp-consensus = { version = "0.10.0-dev", path = "../../../../primitives/consensus/common" } sp-core = { version = "4.1.0-dev", path = "../../../../primitives/core" } -sp-application-crypto = { version = "4.0.0-dev", path = "../../../../primitives/application-crypto" } -sp-keystore = { version = "0.10.0-dev", path = "../../../../primitives/keystore" } +sp-application-crypto = { version = "4.0.0", path = "../../../../primitives/application-crypto" } +sp-keystore = { version = "0.10.0", path = "../../../../primitives/keystore" } [dev-dependencies] sc-consensus = { version = "0.10.0-dev", path = "../../../consensus/common" } diff --git a/client/consensus/common/Cargo.toml b/client/consensus/common/Cargo.toml index f20e12cc4aae..9d2323b75760 100644 --- a/client/consensus/common/Cargo.toml +++ b/client/consensus/common/Cargo.toml @@ -22,8 +22,8 @@ sc-client-api = { version = "4.0.0-dev", path = "../../api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sp-core = { path = "../../../primitives/core", version = "4.1.0-dev" } sp-consensus = { path = "../../../primitives/consensus/common", version = "0.10.0-dev" } -sp-state-machine = { version = "0.10.0-dev", path = "../../../primitives/state-machine" } -sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } +sp-state-machine = { version = "0.10.0", path = "../../../primitives/state-machine" } +sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } sc-utils = { version = "4.0.0-dev", path = "../../utils" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } parking_lot = "0.11.1" diff --git a/client/consensus/epochs/Cargo.toml b/client/consensus/epochs/Cargo.toml index 4cac4a24d187..efd11b8d401d 100644 --- a/client/consensus/epochs/Cargo.toml +++ b/client/consensus/epochs/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", features = ["derive"] } fork-tree = { version = "3.0.0", path = "../../../utils/fork-tree" } -sp-runtime = { path = "../../../primitives/runtime" , version = "4.0.0-dev"} +sp-runtime = { path = "../../../primitives/runtime" , version = "4.0.0"} sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sc-client-api = { path = "../../api" , version = "4.0.0-dev"} sc-consensus = { path = "../common" , version = "0.10.0-dev"} diff --git a/client/consensus/manual-seal/Cargo.toml b/client/consensus/manual-seal/Cargo.toml index 59d35819c781..c69ed21fb3a9 100644 --- a/client/consensus/manual-seal/Cargo.toml +++ b/client/consensus/manual-seal/Cargo.toml @@ -35,9 +35,9 @@ sp-blockchain = { path = "../../../primitives/blockchain", version = "4.0.0-dev" sp-consensus = { path = "../../../primitives/consensus/common", version = "0.10.0-dev" } sp-consensus-slots = { path = "../../../primitives/consensus/slots", version = "0.10.0-dev" } sp-inherents = { path = "../../../primitives/inherents", version = "4.0.0-dev" } -sp-runtime = { path = "../../../primitives/runtime", version = "4.0.0-dev" } +sp-runtime = { path = "../../../primitives/runtime", version = "4.0.0" } sp-core = { path = "../../../primitives/core", version = "4.1.0-dev" } -sp-keystore = { path = "../../../primitives/keystore", version = "0.10.0-dev" } +sp-keystore = { path = "../../../primitives/keystore", version = "0.10.0" } sp-api = { path = "../../../primitives/api", version = "4.0.0-dev" } sc-transaction-pool-api = { path = "../../../client/transaction-pool/api", version = "4.0.0-dev" } sp-timestamp = { path = "../../../primitives/timestamp", version = "4.0.0-dev" } diff --git a/client/consensus/pow/Cargo.toml b/client/consensus/pow/Cargo.toml index d4b156f0b8fa..00ee58c21247 100644 --- a/client/consensus/pow/Cargo.toml +++ b/client/consensus/pow/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0", features = ["derive"] } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sc-client-api = { version = "4.0.0-dev", path = "../../api" } sp-block-builder = { version = "4.0.0-dev", path = "../../../primitives/block-builder" } diff --git a/client/consensus/slots/Cargo.toml b/client/consensus/slots/Cargo.toml index c97a3d1fe035..bf2bd59bb91e 100644 --- a/client/consensus/slots/Cargo.toml +++ b/client/consensus/slots/Cargo.toml @@ -17,12 +17,12 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0" } sc-client-api = { version = "4.0.0-dev", path = "../../api" } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } -sp-arithmetic = { version = "4.0.0-dev", path = "../../../primitives/arithmetic" } +sp-arithmetic = { version = "4.0.0", path = "../../../primitives/arithmetic" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/common" } sp-consensus-slots = { version = "0.10.0-dev", path = "../../../primitives/consensus/slots" } -sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } -sp-state-machine = { version = "0.10.0-dev", path = "../../../primitives/state-machine" } +sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } +sp-state-machine = { version = "0.10.0", path = "../../../primitives/state-machine" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sc-telemetry = { version = "4.0.0-dev", path = "../../telemetry" } sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" } diff --git a/client/consensus/uncles/Cargo.toml b/client/consensus/uncles/Cargo.toml index bc5f1f25838c..346d3e34c01b 100644 --- a/client/consensus/uncles/Cargo.toml +++ b/client/consensus/uncles/Cargo.toml @@ -14,6 +14,6 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sc-client-api = { version = "4.0.0-dev", path = "../../api" } -sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } sp-authorship = { version = "4.0.0-dev", path = "../../../primitives/authorship" } thiserror = "1.0.30" diff --git a/client/db/Cargo.toml b/client/db/Cargo.toml index a2ed46c48e1c..80ba026de3cf 100644 --- a/client/db/Cargo.toml +++ b/client/db/Cargo.toml @@ -25,12 +25,12 @@ codec = { package = "parity-scale-codec", version = "2.0.0", features = [ ] } sc-client-api = { version = "4.0.0-dev", path = "../api" } -sp-arithmetic = { version = "4.0.0-dev", path = "../../primitives/arithmetic" } +sp-arithmetic = { version = "4.0.0", path = "../../primitives/arithmetic" } sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } -sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } -sp-state-machine = { version = "0.10.0-dev", path = "../../primitives/state-machine" } +sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } +sp-state-machine = { version = "0.10.0", path = "../../primitives/state-machine" } sc-state-db = { version = "0.10.0-dev", path = "../state-db" } -sp-trie = { version = "4.0.0-dev", path = "../../primitives/trie" } +sp-trie = { version = "4.0.0", path = "../../primitives/trie" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-database = { version = "4.0.0-dev", path = "../../primitives/database" } parity-db = { version = "0.3.5", optional = true } diff --git a/client/executor/Cargo.toml b/client/executor/Cargo.toml index 377623512fa3..a87a38291370 100644 --- a/client/executor/Cargo.toml +++ b/client/executor/Cargo.toml @@ -18,9 +18,9 @@ codec = { package = "parity-scale-codec", version = "2.0.0" } sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-tasks = { version = "4.0.0-dev", path = "../../primitives/tasks" } -sp-trie = { version = "4.0.0-dev", path = "../../primitives/trie" } +sp-trie = { version = "4.0.0", path = "../../primitives/trie" } sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } -sp-panic-handler = { version = "4.0.0-dev", path = "../../primitives/panic-handler" } +sp-panic-handler = { version = "4.0.0", path = "../../primitives/panic-handler" } wasmi = "0.9.1" lazy_static = "1.4.0" sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } @@ -41,8 +41,8 @@ wat = "1.0" hex-literal = "0.3.4" sc-runtime-test = { version = "2.0.0", path = "runtime-test" } substrate-test-runtime = { version = "2.0.0", path = "../../test-utils/runtime" } -sp-state-machine = { version = "0.10.0-dev", path = "../../primitives/state-machine" } -sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } +sp-state-machine = { version = "0.10.0", path = "../../primitives/state-machine" } +sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } sp-maybe-compressed-blob = { version = "4.1.0-dev", path = "../../primitives/maybe-compressed-blob" } sc-tracing = { version = "4.0.0-dev", path = "../tracing" } tracing = "0.1.29" diff --git a/client/executor/runtime-test/Cargo.toml b/client/executor/runtime-test/Cargo.toml index 4572a23c630a..8fbaf2102aeb 100644 --- a/client/executor/runtime-test/Cargo.toml +++ b/client/executor/runtime-test/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/io" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../../primitives/runtime" } sp-sandbox = { version = "0.10.0-dev", default-features = false, path = "../../../primitives/sandbox" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } sp-tasks = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/tasks" } diff --git a/client/executor/wasmtime/Cargo.toml b/client/executor/wasmtime/Cargo.toml index 06f668ef67b4..6718e6d13f3c 100644 --- a/client/executor/wasmtime/Cargo.toml +++ b/client/executor/wasmtime/Cargo.toml @@ -32,5 +32,5 @@ wasmtime = { version = "0.31.0", default-features = false, features = [ [dev-dependencies] sc-runtime-test = { version = "2.0.0", path = "../runtime-test" } -sp-io = { version = "4.0.0-dev", path = "../../../primitives/io" } +sp-io = { version = "4.0.0", path = "../../../primitives/io" } wat = "1.0" diff --git a/client/finality-grandpa/Cargo.toml b/client/finality-grandpa/Cargo.toml index 12aedbfe0143..2ddd4f765163 100644 --- a/client/finality-grandpa/Cargo.toml +++ b/client/finality-grandpa/Cargo.toml @@ -24,14 +24,14 @@ log = "0.4.8" parking_lot = "0.11.1" rand = "0.8.4" parity-scale-codec = { version = "2.3.1", features = ["derive"] } -sp-application-crypto = { version = "4.0.0-dev", path = "../../primitives/application-crypto" } -sp-arithmetic = { version = "4.0.0-dev", path = "../../primitives/arithmetic" } -sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } +sp-application-crypto = { version = "4.0.0", path = "../../primitives/application-crypto" } +sp-arithmetic = { version = "4.0.0", path = "../../primitives/arithmetic" } +sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } sc-utils = { version = "4.0.0-dev", path = "../utils" } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } sc-consensus = { version = "0.10.0-dev", path = "../consensus/common" } sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } -sp-keystore = { version = "0.10.0-dev", path = "../../primitives/keystore" } +sp-keystore = { version = "0.10.0", path = "../../primitives/keystore" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } sc-telemetry = { version = "4.0.0-dev", path = "../telemetry" } sc-keystore = { version = "4.0.0-dev", path = "../keystore" } diff --git a/client/finality-grandpa/rpc/Cargo.toml b/client/finality-grandpa/rpc/Cargo.toml index 9d0affde3b17..b923ec41d33f 100644 --- a/client/finality-grandpa/rpc/Cargo.toml +++ b/client/finality-grandpa/rpc/Cargo.toml @@ -13,7 +13,7 @@ sc-finality-grandpa = { version = "0.10.0-dev", path = "../" } sc-rpc = { version = "4.0.0-dev", path = "../../rpc" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } -sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } finality-grandpa = { version = "0.14.4", features = ["derive-codec"] } jsonrpc-core = "18.0.0" jsonrpc-core-client = "18.0.0" diff --git a/client/informant/Cargo.toml b/client/informant/Cargo.toml index 5eba3ecaeb2a..d6e9c655aad9 100644 --- a/client/informant/Cargo.toml +++ b/client/informant/Cargo.toml @@ -21,5 +21,5 @@ parity-util-mem = { version = "0.10.2", default-features = false, features = ["p sc-client-api = { version = "4.0.0-dev", path = "../api" } sc-network = { version = "0.10.0-dev", path = "../network" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } -sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../transaction-pool/api" } diff --git a/client/keystore/Cargo.toml b/client/keystore/Cargo.toml index 912de249ad0b..abdd4ac372e7 100644 --- a/client/keystore/Cargo.toml +++ b/client/keystore/Cargo.toml @@ -17,9 +17,9 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] async-trait = "0.1.50" derive_more = "0.99.16" -sp-application-crypto = { version = "4.0.0-dev", path = "../../primitives/application-crypto" } +sp-application-crypto = { version = "4.0.0", path = "../../primitives/application-crypto" } sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } -sp-keystore = { version = "0.10.0-dev", path = "../../primitives/keystore" } +sp-keystore = { version = "0.10.0", path = "../../primitives/keystore" } hex = "0.4.0" parking_lot = "0.11.1" serde_json = "1.0.71" diff --git a/client/network-gossip/Cargo.toml b/client/network-gossip/Cargo.toml index 840cb50c8c9f..c90d1db44afc 100644 --- a/client/network-gossip/Cargo.toml +++ b/client/network-gossip/Cargo.toml @@ -22,7 +22,7 @@ log = "0.4.8" lru = "0.7.0" prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.10.0-dev", path = "../../utils/prometheus" } sc-network = { version = "0.10.0-dev", path = "../network" } -sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } tracing = "0.1.29" [dev-dependencies] diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index 5c8aedc84c19..95f84f493bb7 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -49,12 +49,12 @@ sc-peerset = { version = "4.0.0-dev", path = "../peerset" } serde = { version = "1.0.126", features = ["derive"] } serde_json = "1.0.71" smallvec = "1.7.0" -sp-arithmetic = { version = "4.0.0-dev", path = "../../primitives/arithmetic" } +sp-arithmetic = { version = "4.0.0", path = "../../primitives/arithmetic" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } sc-consensus = { version = "0.10.0-dev", path = "../consensus/common" } sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } -sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } sc-utils = { version = "4.0.0-dev", path = "../utils" } sp-finality-grandpa = { version = "4.0.0-dev", path = "../../primitives/finality-grandpa" } thiserror = "1" diff --git a/client/network/test/Cargo.toml b/client/network/test/Cargo.toml index 748037fef644..fd9e9e2f7ef3 100644 --- a/client/network/test/Cargo.toml +++ b/client/network/test/Cargo.toml @@ -25,7 +25,7 @@ sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/c sc-consensus = { version = "0.10.0-dev", path = "../../consensus/common" } sc-client-api = { version = "4.0.0-dev", path = "../../api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sc-block-builder = { version = "0.10.0-dev", path = "../../block-builder" } sp-consensus-babe = { version = "0.10.0-dev", path = "../../../primitives/consensus/babe" } diff --git a/client/offchain/Cargo.toml b/client/offchain/Cargo.toml index 4494beb2e3f4..5ed182d6cfc4 100644 --- a/client/offchain/Cargo.toml +++ b/client/offchain/Cargo.toml @@ -27,7 +27,7 @@ sc-network = { version = "0.10.0-dev", path = "../network" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-offchain = { version = "4.0.0-dev", path = "../../primitives/offchain" } -sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } sc-utils = { version = "4.0.0-dev", path = "../utils" } threadpool = "1.7" hyper = { version = "0.14.14", features = ["stream", "http2"] } diff --git a/client/rpc-api/Cargo.toml b/client/rpc-api/Cargo.toml index 3c97677c3fee..18f499c51448 100644 --- a/client/rpc-api/Cargo.toml +++ b/client/rpc-api/Cargo.toml @@ -25,7 +25,7 @@ thiserror = "1.0" sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } -sp-runtime = { path = "../../primitives/runtime", version = "4.0.0-dev" } +sp-runtime = { path = "../../primitives/runtime", version = "4.0.0" } sc-chain-spec = { path = "../chain-spec", version = "4.0.0-dev" } serde = { version = "1.0.126", features = ["derive"] } serde_json = "1.0.71" diff --git a/client/rpc/Cargo.toml b/client/rpc/Cargo.toml index 1f1fe6b12aed..707fbf75f7c6 100644 --- a/client/rpc/Cargo.toml +++ b/client/rpc/Cargo.toml @@ -26,10 +26,10 @@ sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } serde_json = "1.0.71" sp-session = { version = "4.0.0-dev", path = "../../primitives/session" } sp-offchain = { version = "4.0.0-dev", path = "../../primitives/offchain" } -sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } sc-utils = { version = "4.0.0-dev", path = "../utils" } sp-rpc = { version = "4.0.0-dev", path = "../../primitives/rpc" } -sp-keystore = { version = "0.10.0-dev", path = "../../primitives/keystore" } +sp-keystore = { version = "0.10.0", path = "../../primitives/keystore" } sc-chain-spec = { version = "4.0.0-dev", path = "../chain-spec" } sc-block-builder = { version = "0.10.0-dev", path = "../block-builder" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } @@ -43,7 +43,7 @@ sc-transaction-pool-api = { version = "4.0.0-dev", path = "../transaction-pool/a assert_matches = "1.3.0" lazy_static = "1.4.0" sc-network = { version = "0.10.0-dev", path = "../network" } -sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } +sp-io = { version = "4.0.0", path = "../../primitives/io" } substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } sc-transaction-pool = { version = "4.0.0-dev", path = "../transaction-pool" } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index 25cd9026bc8b..6d96cafec201 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -36,17 +36,17 @@ hash-db = "0.15.2" serde = "1.0.126" serde_json = "1.0.71" sc-keystore = { version = "4.0.0-dev", path = "../keystore" } -sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } -sp-trie = { version = "4.0.0-dev", path = "../../primitives/trie" } +sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } +sp-trie = { version = "4.0.0", path = "../../primitives/trie" } sp-externalities = { version = "0.10.0", path = "../../primitives/externalities" } sc-utils = { version = "4.0.0-dev", path = "../utils" } sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } -sp-keystore = { version = "0.10.0-dev", path = "../../primitives/keystore" } +sp-keystore = { version = "0.10.0", path = "../../primitives/keystore" } sp-session = { version = "4.0.0-dev", path = "../../primitives/session" } -sp-state-machine = { version = "0.10.0-dev", path = "../../primitives/state-machine" } -sp-application-crypto = { version = "4.0.0-dev", path = "../../primitives/application-crypto" } +sp-state-machine = { version = "0.10.0", path = "../../primitives/state-machine" } +sp-application-crypto = { version = "4.0.0", path = "../../primitives/application-crypto" } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } sc-consensus = { version = "0.10.0-dev", path = "../../client/consensus/common" } sp-inherents = { version = "4.0.0-dev", path = "../../primitives/inherents" } diff --git a/client/service/test/Cargo.toml b/client/service/test/Cargo.toml index 52f0ff6ecce0..113ed0d0802b 100644 --- a/client/service/test/Cargo.toml +++ b/client/service/test/Cargo.toml @@ -21,9 +21,9 @@ fdlimit = "0.2.1" parking_lot = "0.11.1" sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } -sp-state-machine = { version = "0.10.0-dev", path = "../../../primitives/state-machine" } +sp-state-machine = { version = "0.10.0", path = "../../../primitives/state-machine" } sp-externalities = { version = "0.10.0", path = "../../../primitives/externalities" } -sp-trie = { version = "4.0.0-dev", path = "../../../primitives/trie" } +sp-trie = { version = "4.0.0", path = "../../../primitives/trie" } sp-storage = { version = "4.0.0", path = "../../../primitives/storage" } sc-client-db = { version = "0.10.0-dev", default-features = false, path = "../../db" } futures = "0.3.16" @@ -31,7 +31,7 @@ sc-service = { version = "0.10.0-dev", features = ["test-helpers"], path = "../. sc-network = { version = "0.10.0-dev", path = "../../network" } sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" } sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/common" } -sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../../../client/transaction-pool/api" } substrate-test-runtime = { version = "2.0.0", path = "../../../test-utils/runtime" } @@ -39,6 +39,6 @@ substrate-test-runtime-client = { version = "2.0.0", path = "../../../test-utils sc-client-api = { version = "4.0.0-dev", path = "../../api" } sc-block-builder = { version = "0.10.0-dev", path = "../../block-builder" } sc-executor = { version = "0.10.0-dev", path = "../../executor" } -sp-panic-handler = { version = "4.0.0-dev", path = "../../../primitives/panic-handler" } +sp-panic-handler = { version = "4.0.0", path = "../../../primitives/panic-handler" } parity-scale-codec = "2.3.1" sp-tracing = { version = "4.0.0", path = "../../../primitives/tracing" } diff --git a/client/sync-state-rpc/Cargo.toml b/client/sync-state-rpc/Cargo.toml index c609ac42c76e..a7b632b81800 100644 --- a/client/sync-state-rpc/Cargo.toml +++ b/client/sync-state-rpc/Cargo.toml @@ -26,5 +26,5 @@ sc-rpc-api = { version = "0.10.0-dev", path = "../rpc-api" } serde_json = "1.0.71" serde = { version = "1.0.126", features = ["derive"] } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } -sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } codec = { package = "parity-scale-codec", version = "2.0.0" } diff --git a/client/tracing/Cargo.toml b/client/tracing/Cargo.toml index 4d91e61127db..137cab554613 100644 --- a/client/tracing/Cargo.toml +++ b/client/tracing/Cargo.toml @@ -30,7 +30,7 @@ tracing-log = "0.1.2" tracing-subscriber = { version = "0.2.25", features = ["parking_lot"] } sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } sp-rpc = { version = "4.0.0-dev", path = "../../primitives/rpc" } -sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } diff --git a/client/transaction-pool/Cargo.toml b/client/transaction-pool/Cargo.toml index 6ed97edbf476..9aaaaa36a2cb 100644 --- a/client/transaction-pool/Cargo.toml +++ b/client/transaction-pool/Cargo.toml @@ -24,7 +24,7 @@ prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../.. sc-client-api = { version = "4.0.0-dev", path = "../api" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } -sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } sp-transaction-pool = { version = "4.0.0-dev", path = "../../primitives/transaction-pool" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "./api" } diff --git a/client/transaction-pool/api/Cargo.toml b/client/transaction-pool/api/Cargo.toml index f44ec588e954..0c65234b0d68 100644 --- a/client/transaction-pool/api/Cargo.toml +++ b/client/transaction-pool/api/Cargo.toml @@ -13,7 +13,7 @@ futures = { version = "0.3.1" } log = { version = "0.4.8" } serde = { version = "1.0.126", features = ["derive"] } thiserror = { version = "1.0.30" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../../primitives/runtime" } derive_more = { version = "0.99.16" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } diff --git a/frame/assets/Cargo.toml b/frame/assets/Cargo.toml index 37ff7582f5c6..c36200fb1ac4 100644 --- a/frame/assets/Cargo.toml +++ b/frame/assets/Cargo.toml @@ -17,7 +17,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } # Needed for various traits. In our case, `OnFinalize`. -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } # Needed for type-safe access to storage DB. frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } # `system` module provides us with all sorts of useful stuff and macros depend on it being around. @@ -27,7 +27,7 @@ frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = " [dev-dependencies] sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-std = { version = "4.0.0", path = "../../primitives/std" } -sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } +sp-io = { version = "4.0.0", path = "../../primitives/io" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/frame/atomic-swap/Cargo.toml b/frame/atomic-swap/Cargo.toml index 54e579550443..7a1415946e76 100644 --- a/frame/atomic-swap/Cargo.toml +++ b/frame/atomic-swap/Cargo.toml @@ -17,7 +17,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } diff --git a/frame/aura/Cargo.toml b/frame/aura/Cargo.toml index 9ed07e724b30..34956b1116e9 100644 --- a/frame/aura/Cargo.toml +++ b/frame/aura/Cargo.toml @@ -13,11 +13,11 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-application-crypto = { version = "4.0.0-dev", default-features = false, path = "../../primitives/application-crypto" } +sp-application-crypto = { version = "4.0.0", default-features = false, path = "../../primitives/application-crypto" } codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } sp-consensus-aura = { version = "0.10.0-dev", path = "../../primitives/consensus/aura", default-features = false } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/authority-discovery/Cargo.toml b/frame/authority-discovery/Cargo.toml index 1a0f5925732c..4cb40a0f2661 100644 --- a/frame/authority-discovery/Cargo.toml +++ b/frame/authority-discovery/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-authority-discovery = { version = "4.0.0-dev", default-features = false, path = "../../primitives/authority-discovery" } -sp-application-crypto = { version = "4.0.0-dev", default-features = false, path = "../../primitives/application-crypto" } +sp-application-crypto = { version = "4.0.0", default-features = false, path = "../../primitives/application-crypto" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ "derive", ] } @@ -23,7 +23,7 @@ sp-std = { version = "4.0.0", default-features = false, path = "../../primitives pallet-session = { version = "4.0.0-dev", features = [ "historical", ], path = "../session", default-features = false } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/authorship/Cargo.toml b/frame/authorship/Cargo.toml index 2a0dc8bdd9a7..77be81c082b1 100644 --- a/frame/authorship/Cargo.toml +++ b/frame/authorship/Cargo.toml @@ -19,7 +19,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-authorship = { version = "4.0.0-dev", default-features = false, path = "../../primitives/authorship" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } impl-trait-for-tuples = "0.2.1" diff --git a/frame/babe/Cargo.toml b/frame/babe/Cargo.toml index 414cfcb222d4..5242de638c38 100644 --- a/frame/babe/Cargo.toml +++ b/frame/babe/Cargo.toml @@ -21,11 +21,11 @@ frame-system = { version = "4.0.0-dev", default-features = false, path = "../sys pallet-authorship = { version = "4.0.0-dev", default-features = false, path = "../authorship" } pallet-session = { version = "4.0.0-dev", default-features = false, path = "../session" } pallet-timestamp = { version = "4.0.0-dev", default-features = false, path = "../timestamp" } -sp-application-crypto = { version = "4.0.0-dev", default-features = false, path = "../../primitives/application-crypto" } +sp-application-crypto = { version = "4.0.0", default-features = false, path = "../../primitives/application-crypto" } sp-consensus-babe = { version = "0.10.0-dev", default-features = false, path = "../../primitives/consensus/babe" } sp-consensus-vrf = { version = "0.10.0-dev", default-features = false, path = "../../primitives/consensus/vrf" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../primitives/session" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } diff --git a/frame/bags-list/Cargo.toml b/frame/bags-list/Cargo.toml index 66bb1c48a929..e5e746ad1b62 100644 --- a/frame/bags-list/Cargo.toml +++ b/frame/bags-list/Cargo.toml @@ -18,7 +18,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } # primitives -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } # FRAME diff --git a/frame/bags-list/remote-tests/Cargo.toml b/frame/bags-list/remote-tests/Cargo.toml index 646b47275c18..8e6a24674d0a 100644 --- a/frame/bags-list/remote-tests/Cargo.toml +++ b/frame/bags-list/remote-tests/Cargo.toml @@ -24,7 +24,7 @@ frame-support = { path = "../../support", version = "4.0.0-dev" } sp-storage = { path = "../../../primitives/storage", version = "4.0.0" } sp-core = { path = "../../../primitives/core", version = "4.1.0-dev" } sp-tracing = { path = "../../../primitives/tracing", version = "4.0.0" } -sp-runtime = { path = "../../../primitives/runtime", version = "4.0.0-dev" } +sp-runtime = { path = "../../../primitives/runtime", version = "4.0.0" } sp-std = { path = "../../../primitives/std", version = "4.0.0" } # utils diff --git a/frame/balances/Cargo.toml b/frame/balances/Cargo.toml index 1ac7b71fb340..fdabb4132b1a 100644 --- a/frame/balances/Cargo.toml +++ b/frame/balances/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/beefy-mmr/Cargo.toml b/frame/beefy-mmr/Cargo.toml index 64cdf805db9a..50c4fd3f7f3b 100644 --- a/frame/beefy-mmr/Cargo.toml +++ b/frame/beefy-mmr/Cargo.toml @@ -23,7 +23,7 @@ pallet-session = { version = "4.0.0-dev", path = "../session", default-features sp-core = { version = "4.1.0-dev", path = "../../primitives/core", default-features = false } sp-io = { version = "4.0.0-dev", path = "../../primitives/io", default-features = false } -sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime", default-features = false } +sp-runtime = { version = "4.0.0", path = "../../primitives/runtime", default-features = false } sp-std = { version = "4.0.0", path = "../../primitives/std", default-features = false } beefy-merkle-tree = { version = "4.0.0-dev", path = "./primitives", default-features = false } diff --git a/frame/beefy/Cargo.toml b/frame/beefy/Cargo.toml index c90f0d7328be..2f7059d5156c 100644 --- a/frame/beefy/Cargo.toml +++ b/frame/beefy/Cargo.toml @@ -15,7 +15,7 @@ serde = { version = "1.0.130", optional = true } frame-support = { version = "4.0.0-dev", path = "../support", default-features = false } frame-system = { version = "4.0.0-dev", path = "../system", default-features = false } -sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime", default-features = false } +sp-runtime = { version = "4.0.0", path = "../../primitives/runtime", default-features = false } sp-std = { version = "4.0.0", path = "../../primitives/std", default-features = false } pallet-session = { version = "4.0.0-dev", path = "../session", default-features = false } diff --git a/frame/benchmarking/Cargo.toml b/frame/benchmarking/Cargo.toml index 1e89c39be1c4..d3dcf589e446 100644 --- a/frame/benchmarking/Cargo.toml +++ b/frame/benchmarking/Cargo.toml @@ -19,10 +19,10 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-api = { version = "4.0.0-dev", path = "../../primitives/api", default-features = false } sp-runtime-interface = { version = "4.1.0-dev", path = "../../primitives/runtime-interface", default-features = false } -sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime", default-features = false } +sp-runtime = { version = "4.0.0", path = "../../primitives/runtime", default-features = false } sp-std = { version = "4.0.0", path = "../../primitives/std", default-features = false } -sp-io = { version = "4.0.0-dev", path = "../../primitives/io", default-features = false } -sp-application-crypto = { version = "4.0.0-dev", path = "../../primitives/application-crypto", default-features = false } +sp-io = { version = "4.0.0", path = "../../primitives/io", default-features = false } +sp-application-crypto = { version = "4.0.0", path = "../../primitives/application-crypto", default-features = false } sp-storage = { version = "4.0.0", path = "../../primitives/storage", default-features = false } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } @@ -30,7 +30,7 @@ log = { version = "0.4.14", default-features = false } [dev-dependencies] hex-literal = "0.3.4" -sp-keystore = { version = "0.10.0-dev", path = "../../primitives/keystore" } +sp-keystore = { version = "0.10.0", path = "../../primitives/keystore" } [features] default = ["std"] diff --git a/frame/bounties/Cargo.toml b/frame/bounties/Cargo.toml index 97364ba41f63..2e328e19b8ec 100644 --- a/frame/bounties/Cargo.toml +++ b/frame/bounties/Cargo.toml @@ -18,11 +18,11 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } pallet-treasury = { version = "4.0.0-dev", default-features = false, path = "../treasury" } -sp-io = { version = "4.0.0-dev", path = "../../primitives/io", default-features = false } +sp-io = { version = "4.0.0", path = "../../primitives/io", default-features = false } sp-core = { version = "4.1.0-dev", path = "../../primitives/core", default-features = false } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } log = { version = "0.4.14", default-features = false } diff --git a/frame/child-bounties/Cargo.toml b/frame/child-bounties/Cargo.toml index 17cfc482af06..fcd8e839fb1e 100644 --- a/frame/child-bounties/Cargo.toml +++ b/frame/child-bounties/Cargo.toml @@ -18,7 +18,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } pallet-treasury = { version = "4.0.0-dev", default-features = false, path = "../treasury" } diff --git a/frame/collective/Cargo.toml b/frame/collective/Cargo.toml index 6d3b081c89c1..cc17a6d7ce60 100644 --- a/frame/collective/Cargo.toml +++ b/frame/collective/Cargo.toml @@ -19,7 +19,7 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } diff --git a/frame/contracts/Cargo.toml b/frame/contracts/Cargo.toml index 963f1466a9ea..4067148e13e1 100644 --- a/frame/contracts/Cargo.toml +++ b/frame/contracts/Cargo.toml @@ -40,7 +40,7 @@ pallet-contracts-primitives = { version = "4.0.0-dev", default-features = false, pallet-contracts-proc-macro = { version = "4.0.0-dev", path = "proc-macro" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } sp-sandbox = { version = "0.10.0-dev", default-features = false, path = "../../primitives/sandbox" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } diff --git a/frame/contracts/common/Cargo.toml b/frame/contracts/common/Cargo.toml index 0e0cf1528b1a..2b565b4c9e2c 100644 --- a/frame/contracts/common/Cargo.toml +++ b/frame/contracts/common/Cargo.toml @@ -22,7 +22,7 @@ serde = { version = "1", features = ["derive"], optional = true } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core", default-features = false } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } sp-rpc = { version = "4.0.0-dev", path = "../../../primitives/rpc", optional = true } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../../primitives/runtime" } [features] default = ["std"] diff --git a/frame/contracts/rpc/Cargo.toml b/frame/contracts/rpc/Cargo.toml index e380708a9dee..51a512277c56 100644 --- a/frame/contracts/rpc/Cargo.toml +++ b/frame/contracts/rpc/Cargo.toml @@ -26,7 +26,7 @@ sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sp-rpc = { version = "4.0.0-dev", path = "../../../primitives/rpc" } -sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } [dev-dependencies] serde_json = "1" diff --git a/frame/contracts/rpc/runtime-api/Cargo.toml b/frame/contracts/rpc/runtime-api/Cargo.toml index 2c293b3a906a..c7251306192e 100644 --- a/frame/contracts/rpc/runtime-api/Cargo.toml +++ b/frame/contracts/rpc/runtime-api/Cargo.toml @@ -19,7 +19,7 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] # Substrate Dependencies pallet-contracts-primitives = { version = "4.0.0-dev", default-features = false, path = "../../common" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/api" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../../../primitives/std" } [features] diff --git a/frame/democracy/Cargo.toml b/frame/democracy/Cargo.toml index 32acdb964ed8..b1b84d9ad03d 100644 --- a/frame/democracy/Cargo.toml +++ b/frame/democracy/Cargo.toml @@ -19,8 +19,8 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/election-provider-multi-phase/Cargo.toml b/frame/election-provider-multi-phase/Cargo.toml index a1df7edc1331..72ec62f321cf 100644 --- a/frame/election-provider-multi-phase/Cargo.toml +++ b/frame/election-provider-multi-phase/Cargo.toml @@ -23,12 +23,12 @@ log = { version = "0.4.14", default-features = false } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } +sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } sp-npos-elections = { version = "4.0.0-dev", default-features = false, path = "../../primitives/npos-elections" } -sp-arithmetic = { version = "4.0.0-dev", default-features = false, path = "../../primitives/arithmetic" } +sp-arithmetic = { version = "4.0.0", default-features = false, path = "../../primitives/arithmetic" } frame-election-provider-support = { version = "4.0.0-dev", default-features = false, path = "../election-provider-support" } # Optional imports for benchmarking diff --git a/frame/election-provider-support/Cargo.toml b/frame/election-provider-support/Cargo.toml index 80b7f9d7bfc0..8fabefa7a12c 100644 --- a/frame/election-provider-support/Cargo.toml +++ b/frame/election-provider-support/Cargo.toml @@ -16,14 +16,14 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-arithmetic = { version = "4.0.0-dev", default-features = false, path = "../../primitives/arithmetic" } +sp-arithmetic = { version = "4.0.0", default-features = false, path = "../../primitives/arithmetic" } sp-npos-elections = { version = "4.0.0-dev", default-features = false, path = "../../primitives/npos-elections" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } [dev-dependencies] sp-npos-elections = { version = "4.0.0-dev", path = "../../primitives/npos-elections" } -sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } diff --git a/frame/elections-phragmen/Cargo.toml b/frame/elections-phragmen/Cargo.toml index 7ab81a4f3300..bcf91ac5c73c 100644 --- a/frame/elections-phragmen/Cargo.toml +++ b/frame/elections-phragmen/Cargo.toml @@ -17,9 +17,9 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = "derive", ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } sp-npos-elections = { version = "4.0.0-dev", default-features = false, path = "../../primitives/npos-elections" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } +sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } diff --git a/frame/examples/basic/Cargo.toml b/frame/examples/basic/Cargo.toml index db39d339f2c5..48f505444884 100644 --- a/frame/examples/basic/Cargo.toml +++ b/frame/examples/basic/Cargo.toml @@ -21,8 +21,8 @@ frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = " frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" } pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../../balances" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/io" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } +sp-io = { version = "4.0.0", default-features = false, path = "../../../primitives/io" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } [dev-dependencies] diff --git a/frame/examples/offchain-worker/Cargo.toml b/frame/examples/offchain-worker/Cargo.toml index f53ea369278d..6152b2ca95ee 100644 --- a/frame/examples/offchain-worker/Cargo.toml +++ b/frame/examples/offchain-worker/Cargo.toml @@ -22,8 +22,8 @@ frame-support = { version = "4.0.0-dev", default-features = false, path = "../.. frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/io" } -sp-keystore = { version = "0.10.0-dev", path = "../../../primitives/keystore", optional = true } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } +sp-keystore = { version = "0.10.0", path = "../../../primitives/keystore", optional = true } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } [features] diff --git a/frame/examples/parallel/Cargo.toml b/frame/examples/parallel/Cargo.toml index d28dd5b9ee0a..94c18b6c9828 100644 --- a/frame/examples/parallel/Cargo.toml +++ b/frame/examples/parallel/Cargo.toml @@ -19,7 +19,7 @@ frame-support = { version = "4.0.0-dev", default-features = false, path = "../.. frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/io" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } sp-tasks = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/tasks" } diff --git a/frame/executive/Cargo.toml b/frame/executive/Cargo.toml index d511bb858c7d..02cb2b22b388 100644 --- a/frame/executive/Cargo.toml +++ b/frame/executive/Cargo.toml @@ -19,7 +19,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } sp-tracing = { version = "4.0.0", default-features = false, path = "../../primitives/tracing" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } diff --git a/frame/gilt/Cargo.toml b/frame/gilt/Cargo.toml index 05e252627b2b..39b9fb558293 100644 --- a/frame/gilt/Cargo.toml +++ b/frame/gilt/Cargo.toml @@ -16,8 +16,8 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-arithmetic = { version = "4.0.0-dev", default-features = false, path = "../../primitives/arithmetic" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-arithmetic = { version = "4.0.0", default-features = false, path = "../../primitives/arithmetic" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/grandpa/Cargo.toml b/frame/grandpa/Cargo.toml index 601ec9aee10e..f123fdbb61ee 100644 --- a/frame/grandpa/Cargo.toml +++ b/frame/grandpa/Cargo.toml @@ -15,13 +15,13 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-application-crypto = { version = "4.0.0-dev", default-features = false, path = "../../primitives/application-crypto" } +sp-application-crypto = { version = "4.0.0", default-features = false, path = "../../primitives/application-crypto" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-finality-grandpa = { version = "4.0.0-dev", default-features = false, path = "../../primitives/finality-grandpa" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } +sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../primitives/session" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/frame/identity/Cargo.toml b/frame/identity/Cargo.toml index 76a187f90c5d..32e62d8aec0b 100644 --- a/frame/identity/Cargo.toml +++ b/frame/identity/Cargo.toml @@ -17,8 +17,8 @@ codec = { package = "parity-scale-codec", version = "2.2.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } enumflags2 = { version = "0.6.2" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/im-online/Cargo.toml b/frame/im-online/Cargo.toml index fdafc5376ad5..dc839d0d1f9e 100644 --- a/frame/im-online/Cargo.toml +++ b/frame/im-online/Cargo.toml @@ -13,14 +13,14 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-application-crypto = { version = "4.0.0-dev", default-features = false, path = "../../primitives/application-crypto" } +sp-application-crypto = { version = "4.0.0", default-features = false, path = "../../primitives/application-crypto" } pallet-authorship = { version = "4.0.0-dev", default-features = false, path = "../authorship" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/indices/Cargo.toml b/frame/indices/Cargo.toml index cd3957a45f82..da56606ed2f6 100644 --- a/frame/indices/Cargo.toml +++ b/frame/indices/Cargo.toml @@ -18,7 +18,7 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] sp-keyring = { version = "4.0.0-dev", optional = true, path = "../../primitives/keyring" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/lottery/Cargo.toml b/frame/lottery/Cargo.toml index 259be8267fe7..9f31f8017341 100644 --- a/frame/lottery/Cargo.toml +++ b/frame/lottery/Cargo.toml @@ -18,7 +18,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/membership/Cargo.toml b/frame/membership/Cargo.toml index d0567a3eeb15..fc0d44c76656 100644 --- a/frame/membership/Cargo.toml +++ b/frame/membership/Cargo.toml @@ -19,7 +19,7 @@ log = { version = "0.4.0", default-features = false } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } diff --git a/frame/merkle-mountain-range/Cargo.toml b/frame/merkle-mountain-range/Cargo.toml index fd6615a4b542..10476e9a73dd 100644 --- a/frame/merkle-mountain-range/Cargo.toml +++ b/frame/merkle-mountain-range/Cargo.toml @@ -18,7 +18,7 @@ mmr-lib = { package = "ckb-merkle-mountain-range", default-features = false, ver sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } diff --git a/frame/merkle-mountain-range/primitives/Cargo.toml b/frame/merkle-mountain-range/primitives/Cargo.toml index 0d11e50a8b68..713da64e26d9 100644 --- a/frame/merkle-mountain-range/primitives/Cargo.toml +++ b/frame/merkle-mountain-range/primitives/Cargo.toml @@ -18,7 +18,7 @@ serde = { version = "1.0.126", optional = true, features = ["derive"] } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/api" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" } diff --git a/frame/merkle-mountain-range/rpc/Cargo.toml b/frame/merkle-mountain-range/rpc/Cargo.toml index 7283a4fac8b2..13d60142dfc3 100644 --- a/frame/merkle-mountain-range/rpc/Cargo.toml +++ b/frame/merkle-mountain-range/rpc/Cargo.toml @@ -22,7 +22,7 @@ serde = { version = "1.0.126", features = ["derive"] } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } -sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } pallet-mmr-primitives = { version = "4.0.0-dev", path = "../primitives" } diff --git a/frame/multisig/Cargo.toml b/frame/multisig/Cargo.toml index d01dd58a2f3f..d1c8d8c60c21 100644 --- a/frame/multisig/Cargo.toml +++ b/frame/multisig/Cargo.toml @@ -17,9 +17,9 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } +sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } diff --git a/frame/nicks/Cargo.toml b/frame/nicks/Cargo.toml index 28cabde09166..08d529070a5e 100644 --- a/frame/nicks/Cargo.toml +++ b/frame/nicks/Cargo.toml @@ -16,8 +16,8 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/node-authorization/Cargo.toml b/frame/node-authorization/Cargo.toml index efaaf6371f8c..350914381c1e 100644 --- a/frame/node-authorization/Cargo.toml +++ b/frame/node-authorization/Cargo.toml @@ -18,7 +18,7 @@ frame-support = { version = "4.0.0-dev", default-features = false, path = "../su frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } log = { version = "0.4.14", default-features = false } diff --git a/frame/offences/Cargo.toml b/frame/offences/Cargo.toml index 5058f17d3857..02f36fab0a21 100644 --- a/frame/offences/Cargo.toml +++ b/frame/offences/Cargo.toml @@ -18,7 +18,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } serde = { version = "1.0.126", optional = true } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/offences/benchmarking/Cargo.toml b/frame/offences/benchmarking/Cargo.toml index 625f275a70ce..28e4fde7c3ce 100644 --- a/frame/offences/benchmarking/Cargo.toml +++ b/frame/offences/benchmarking/Cargo.toml @@ -29,7 +29,7 @@ pallet-session = { version = "4.0.0-dev", default-features = false, path = "../. pallet-staking = { version = "4.0.0-dev", default-features = false, features = [ "runtime-benchmarks", ], path = "../../staking" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../../primitives/runtime" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/staking" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } frame-election-provider-support = { version = "4.0.0-dev", default-features = false, path = "../../election-provider-support" } diff --git a/frame/preimage/Cargo.toml b/frame/preimage/Cargo.toml index b60c3fa85487..29763d08017f 100644 --- a/frame/preimage/Cargo.toml +++ b/frame/preimage/Cargo.toml @@ -16,7 +16,7 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } sp-core = { version = "4.1.0-dev", default-features = false, optional = true, path = "../../primitives/core" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } diff --git a/frame/proxy/Cargo.toml b/frame/proxy/Cargo.toml index 7a1fc61da9d4..c5d9dc857b8d 100644 --- a/frame/proxy/Cargo.toml +++ b/frame/proxy/Cargo.toml @@ -17,8 +17,8 @@ codec = { package = "parity-scale-codec", version = "2.2.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } diff --git a/frame/randomness-collective-flip/Cargo.toml b/frame/randomness-collective-flip/Cargo.toml index 903e167ef95a..037ce134045c 100644 --- a/frame/randomness-collective-flip/Cargo.toml +++ b/frame/randomness-collective-flip/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] safe-mix = { version = "1.0", default-features = false } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/frame/recovery/Cargo.toml b/frame/recovery/Cargo.toml index c1126ad1edd1..3ed194225d0a 100644 --- a/frame/recovery/Cargo.toml +++ b/frame/recovery/Cargo.toml @@ -16,8 +16,8 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/scheduler/Cargo.toml b/frame/scheduler/Cargo.toml index 2f7673598151..9cc34f69db79 100644 --- a/frame/scheduler/Cargo.toml +++ b/frame/scheduler/Cargo.toml @@ -13,10 +13,10 @@ readme = "README.md" codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } log = { version = "0.4.14", default-features = false } -sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } diff --git a/frame/scored-pool/Cargo.toml b/frame/scored-pool/Cargo.toml index e77661204d73..f570039abc33 100644 --- a/frame/scored-pool/Cargo.toml +++ b/frame/scored-pool/Cargo.toml @@ -15,8 +15,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/session/Cargo.toml b/frame/session/Cargo.toml index 909dfe329c9c..57b7fff99479 100644 --- a/frame/session/Cargo.toml +++ b/frame/session/Cargo.toml @@ -22,10 +22,10 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../primitives/session" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" } -sp-trie = { version = "4.0.0-dev", default-features = false, path = "../../primitives/trie", optional = true } +sp-trie = { version = "4.0.0", default-features = false, path = "../../primitives/trie", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/session/benchmarking/Cargo.toml b/frame/session/benchmarking/Cargo.toml index 37dc40e9b25c..5f889e66a870 100644 --- a/frame/session/benchmarking/Cargo.toml +++ b/frame/session/benchmarking/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] rand = { version = "0.7.2", default-features = false } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../../primitives/runtime" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/session" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../../benchmarking" } diff --git a/frame/society/Cargo.toml b/frame/society/Cargo.toml index cf14d7f9f51c..ad53026f4ce0 100644 --- a/frame/society/Cargo.toml +++ b/frame/society/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/staking/Cargo.toml b/frame/staking/Cargo.toml index 42fe1075317d..c91db8c24fda 100644 --- a/frame/staking/Cargo.toml +++ b/frame/staking/Cargo.toml @@ -19,8 +19,8 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } @@ -28,7 +28,7 @@ pallet-session = { version = "4.0.0-dev", default-features = false, features = [ "historical", ], path = "../session" } pallet-authorship = { version = "4.0.0-dev", default-features = false, path = "../authorship" } -sp-application-crypto = { version = "4.0.0-dev", default-features = false, path = "../../primitives/application-crypto" } +sp-application-crypto = { version = "4.0.0", default-features = false, path = "../../primitives/application-crypto" } frame-election-provider-support = { version = "4.0.0-dev", default-features = false, path = "../election-provider-support" } log = { version = "0.4.14", default-features = false } diff --git a/frame/staking/reward-curve/Cargo.toml b/frame/staking/reward-curve/Cargo.toml index fd306eb08572..82f0a6dde2be 100644 --- a/frame/staking/reward-curve/Cargo.toml +++ b/frame/staking/reward-curve/Cargo.toml @@ -21,4 +21,4 @@ proc-macro2 = "1.0.29" proc-macro-crate = "1.1.0" [dev-dependencies] -sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } diff --git a/frame/staking/reward-fn/Cargo.toml b/frame/staking/reward-fn/Cargo.toml index 4e3be2a1bc71..07dc404c8e35 100644 --- a/frame/staking/reward-fn/Cargo.toml +++ b/frame/staking/reward-fn/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [lib] [dependencies] -sp-arithmetic = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/arithmetic" } +sp-arithmetic = { version = "4.0.0", default-features = false, path = "../../../primitives/arithmetic" } log = { version = "0.4.14", default-features = false } [features] diff --git a/frame/sudo/Cargo.toml b/frame/sudo/Cargo.toml index 33642ef7dc3e..c553c80d19d2 100644 --- a/frame/sudo/Cargo.toml +++ b/frame/sudo/Cargo.toml @@ -16,8 +16,8 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/support/Cargo.toml b/frame/support/Cargo.toml index c3eab98f9e77..3cfce23dabe0 100644 --- a/frame/support/Cargo.toml +++ b/frame/support/Cargo.toml @@ -18,18 +18,18 @@ codec = { package = "parity-scale-codec", version = "2.2.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } frame-metadata = { version = "14.0.0", default-features = false, features = ["v14"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } sp-tracing = { version = "4.0.0", default-features = false, path = "../../primitives/tracing" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } -sp-arithmetic = { version = "4.0.0-dev", default-features = false, path = "../../primitives/arithmetic" } +sp-arithmetic = { version = "4.0.0", default-features = false, path = "../../primitives/arithmetic" } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../primitives/inherents" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" } tt-call = "1.0.8" frame-support-procedural = { version = "4.0.0-dev", default-features = false, path = "./procedural" } paste = "1.0" once_cell = { version = "1", default-features = false, optional = true } -sp-state-machine = { version = "0.10.0-dev", optional = true, path = "../../primitives/state-machine" } +sp-state-machine = { version = "0.10.0", optional = true, path = "../../primitives/state-machine" } bitflags = "1.3" impl-trait-for-tuples = "0.2.1" smallvec = "1.7.0" diff --git a/frame/support/test/Cargo.toml b/frame/support/test/Cargo.toml index cdbefae4bde7..d41b0fcacf23 100644 --- a/frame/support/test/Cargo.toml +++ b/frame/support/test/Cargo.toml @@ -15,11 +15,11 @@ targets = ["x86_64-unknown-linux-gnu"] serde = { version = "1.0.126", default-features = false, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-arithmetic = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/arithmetic" } -sp-io = { version = "4.0.0-dev", path = "../../../primitives/io", default-features = false } -sp-state-machine = { version = "0.10.0-dev", optional = true, path = "../../../primitives/state-machine" } +sp-arithmetic = { version = "4.0.0", default-features = false, path = "../../../primitives/arithmetic" } +sp-io = { version = "4.0.0", path = "../../../primitives/io", default-features = false } +sp-state-machine = { version = "0.10.0", optional = true, path = "../../../primitives/state-machine" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../../primitives/runtime" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } sp-version = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/version" } diff --git a/frame/support/test/compile_pass/Cargo.toml b/frame/support/test/compile_pass/Cargo.toml index b72bbc2f01f5..21d3be667253 100644 --- a/frame/support/test/compile_pass/Cargo.toml +++ b/frame/support/test/compile_pass/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../../primitives/core" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../../../primitives/runtime" } sp-version = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/version" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../../" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../../system" } diff --git a/frame/system/Cargo.toml b/frame/system/Cargo.toml index 0d771cd1f80d..70a9b12c7a23 100644 --- a/frame/system/Cargo.toml +++ b/frame/system/Cargo.toml @@ -18,8 +18,8 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "4.0.0-dev", path = "../../primitives/io", default-features = false } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "4.0.0", path = "../../primitives/io", default-features = false } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } sp-version = { version = "4.0.0-dev", default-features = false, path = "../../primitives/version" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } log = { version = "0.4.14", default-features = false } diff --git a/frame/system/benchmarking/Cargo.toml b/frame/system/benchmarking/Cargo.toml index acf13c8f6b2a..ff31c6fdbac4 100644 --- a/frame/system/benchmarking/Cargo.toml +++ b/frame/system/benchmarking/Cargo.toml @@ -16,14 +16,14 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../../primitives/runtime" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../../benchmarking" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } [dev-dependencies] -sp-io = { version = "4.0.0-dev", path = "../../../primitives/io" } +sp-io = { version = "4.0.0", path = "../../../primitives/io" } [features] default = ["std"] diff --git a/frame/timestamp/Cargo.toml b/frame/timestamp/Cargo.toml index f8ff0a587b1a..e10acdc25457 100644 --- a/frame/timestamp/Cargo.toml +++ b/frame/timestamp/Cargo.toml @@ -18,8 +18,8 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io", optional = true } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io", optional = true } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../primitives/inherents" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/frame/tips/Cargo.toml b/frame/tips/Cargo.toml index cb682769ec85..a637fa3928e0 100644 --- a/frame/tips/Cargo.toml +++ b/frame/tips/Cargo.toml @@ -20,7 +20,7 @@ serde = { version = "1.0.126", features = ["derive"], optional = true } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/frame/transaction-payment/Cargo.toml b/frame/transaction-payment/Cargo.toml index 642c9bd399b9..ac6fc5c71c04 100644 --- a/frame/transaction-payment/Cargo.toml +++ b/frame/transaction-payment/Cargo.toml @@ -22,7 +22,7 @@ smallvec = "1.7.0" sp-core = { version = "4.1.0-dev", path = "../../primitives/core", default-features = false } sp-io = { version = "4.0.0-dev", path = "../../primitives/io", default-features = false } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/frame/transaction-payment/asset-tx-payment/Cargo.toml b/frame/transaction-payment/asset-tx-payment/Cargo.toml index 21fae45282d0..3f89a5c4b5f0 100644 --- a/frame/transaction-payment/asset-tx-payment/Cargo.toml +++ b/frame/transaction-payment/asset-tx-payment/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] # Substrate dependencies sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/io" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" } diff --git a/frame/transaction-payment/rpc/Cargo.toml b/frame/transaction-payment/rpc/Cargo.toml index 36dad610f696..b8e43848dbf4 100644 --- a/frame/transaction-payment/rpc/Cargo.toml +++ b/frame/transaction-payment/rpc/Cargo.toml @@ -22,5 +22,5 @@ sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sp-rpc = { version = "4.0.0-dev", path = "../../../primitives/rpc" } -sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } pallet-transaction-payment-rpc-runtime-api = { version = "4.0.0-dev", path = "./runtime-api" } diff --git a/frame/transaction-payment/rpc/runtime-api/Cargo.toml b/frame/transaction-payment/rpc/runtime-api/Cargo.toml index 315f140fc4f2..6cfe02d15c4f 100644 --- a/frame/transaction-payment/rpc/runtime-api/Cargo.toml +++ b/frame/transaction-payment/rpc/runtime-api/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/api" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../../../primitives/runtime" } pallet-transaction-payment = { version = "4.0.0-dev", default-features = false, path = "../../../transaction-payment" } [features] diff --git a/frame/transaction-storage/Cargo.toml b/frame/transaction-storage/Cargo.toml index f5ce6f844166..10f1d3d2e2b2 100644 --- a/frame/transaction-storage/Cargo.toml +++ b/frame/transaction-storage/Cargo.toml @@ -20,9 +20,9 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../balances" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } +sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../primitives/inherents" } sp-transaction-storage-proof = { version = "4.0.0-dev", default-features = false, path = "../../primitives/transaction-storage-proof" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } diff --git a/frame/treasury/Cargo.toml b/frame/treasury/Cargo.toml index fed6b98f55eb..5fe5734120d6 100644 --- a/frame/treasury/Cargo.toml +++ b/frame/treasury/Cargo.toml @@ -22,7 +22,7 @@ serde = { version = "1.0.126", features = ["derive"], optional = true } impl-trait-for-tuples = "0.2.1" sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/frame/try-runtime/Cargo.toml b/frame/try-runtime/Cargo.toml index 64622bcceb02..860a9e988b11 100644 --- a/frame/try-runtime/Cargo.toml +++ b/frame/try-runtime/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-api = { version = "4.0.0-dev", path = "../../primitives/api", default-features = false } sp-std = { version = "4.0.0", path = "../../primitives/std" , default-features = false } -sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" , default-features = false } +sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" , default-features = false } frame-support = { version = "4.0.0-dev", path = "../support", default-features = false } diff --git a/frame/uniques/Cargo.toml b/frame/uniques/Cargo.toml index 2ce0c1b484ea..c9892cac2697 100644 --- a/frame/uniques/Cargo.toml +++ b/frame/uniques/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } diff --git a/frame/utility/Cargo.toml b/frame/utility/Cargo.toml index 9dfbd7b410ef..62fa402705ef 100644 --- a/frame/utility/Cargo.toml +++ b/frame/utility/Cargo.toml @@ -18,9 +18,9 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } +sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } diff --git a/frame/vesting/Cargo.toml b/frame/vesting/Cargo.toml index 30cdc91d44f3..fa0b564c855d 100644 --- a/frame/vesting/Cargo.toml +++ b/frame/vesting/Cargo.toml @@ -18,7 +18,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } diff --git a/primitives/api/Cargo.toml b/primitives/api/Cargo.toml index 65e39571c7eb..b940ae93baa5 100644 --- a/primitives/api/Cargo.toml +++ b/primitives/api/Cargo.toml @@ -17,9 +17,9 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = sp-api-proc-macro = { version = "4.0.0-dev", path = "proc-macro" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../runtime" } sp-version = { version = "4.0.0-dev", default-features = false, path = "../version" } -sp-state-machine = { version = "0.10.0-dev", optional = true, path = "../state-machine" } +sp-state-machine = { version = "0.10.0", optional = true, path = "../state-machine" } hash-db = { version = "0.15.2", optional = true } thiserror = { version = "1.0.30", optional = true } diff --git a/primitives/api/test/Cargo.toml b/primitives/api/test/Cargo.toml index b7716f6b8de7..53d26c08c1d9 100644 --- a/primitives/api/test/Cargo.toml +++ b/primitives/api/test/Cargo.toml @@ -16,11 +16,11 @@ sp-api = { version = "4.0.0-dev", path = "../" } substrate-test-runtime-client = { version = "2.0.0", path = "../../../test-utils/runtime/client" } sp-version = { version = "4.0.0-dev", path = "../../version" } sp-tracing = { version = "4.0.0", path = "../../tracing" } -sp-runtime = { version = "4.0.0-dev", path = "../../runtime" } +sp-runtime = { version = "4.0.0", path = "../../runtime" } sp-consensus = { version = "0.10.0-dev", path = "../../consensus/common" } sc-block-builder = { version = "0.10.0-dev", path = "../../../client/block-builder" } codec = { package = "parity-scale-codec", version = "2.0.0" } -sp-state-machine = { version = "0.10.0-dev", path = "../../state-machine" } +sp-state-machine = { version = "0.10.0", path = "../../state-machine" } trybuild = "1.0.53" rustversion = "1.0.5" diff --git a/primitives/application-crypto/Cargo.toml b/primitives/application-crypto/Cargo.toml index f3a9f9a93839..8090203bbca0 100644 --- a/primitives/application-crypto/Cargo.toml +++ b/primitives/application-crypto/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-application-crypto" -version = "4.0.0-dev" +version = "4.0.0" authors = ["Parity Technologies "] edition = "2021" description = "Provides facilities for generating application specific crypto wrapper types." @@ -20,7 +20,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } serde = { version = "1.0.126", optional = true, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../std" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../io" } +sp-io = { version = "4.0.0", default-features = false, path = "../io" } [features] default = [ "std" ] diff --git a/primitives/application-crypto/test/Cargo.toml b/primitives/application-crypto/test/Cargo.toml index dc51dceeeb4d..0fdb64c5b292 100644 --- a/primitives/application-crypto/test/Cargo.toml +++ b/primitives/application-crypto/test/Cargo.toml @@ -14,8 +14,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-core = { version = "4.1.0-dev", default-features = false, path = "../../core" } -sp-keystore = { version = "0.10.0-dev", path = "../../keystore", default-features = false } +sp-keystore = { version = "0.10.0", path = "../../keystore", default-features = false } substrate-test-runtime-client = { version = "2.0.0", path = "../../../test-utils/runtime/client" } -sp-runtime = { version = "4.0.0-dev", path = "../../runtime" } +sp-runtime = { version = "4.0.0", path = "../../runtime" } sp-api = { version = "4.0.0-dev", path = "../../api" } -sp-application-crypto = { version = "4.0.0-dev", path = "../" } +sp-application-crypto = { version = "4.0.0", path = "../" } diff --git a/primitives/arithmetic/Cargo.toml b/primitives/arithmetic/Cargo.toml index 9bd634bb5187..8db65342cfa0 100644 --- a/primitives/arithmetic/Cargo.toml +++ b/primitives/arithmetic/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-arithmetic" -version = "4.0.0-dev" +version = "4.0.0" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" diff --git a/primitives/arithmetic/fuzzer/Cargo.toml b/primitives/arithmetic/fuzzer/Cargo.toml index d6b208852377..33951687c313 100644 --- a/primitives/arithmetic/fuzzer/Cargo.toml +++ b/primitives/arithmetic/fuzzer/Cargo.toml @@ -14,7 +14,7 @@ publish = false targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-arithmetic = { version = "4.0.0-dev", path = ".." } +sp-arithmetic = { version = "4.0.0", path = ".." } honggfuzz = "0.5.49" primitive-types = "0.10.1" num-bigint = "0.2" diff --git a/primitives/authority-discovery/Cargo.toml b/primitives/authority-discovery/Cargo.toml index 116bc1438ce6..2f1d38c31152 100644 --- a/primitives/authority-discovery/Cargo.toml +++ b/primitives/authority-discovery/Cargo.toml @@ -13,12 +13,12 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-application-crypto = { version = "4.0.0-dev", default-features = false, path = "../application-crypto" } +sp-application-crypto = { version = "4.0.0", default-features = false, path = "../application-crypto" } codec = { package = "parity-scale-codec", default-features = false, version = "2.0.0" } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../runtime" } [features] default = ["std"] diff --git a/primitives/authorship/Cargo.toml b/primitives/authorship/Cargo.toml index 26259e45ea6b..81fa39e93a1a 100644 --- a/primitives/authorship/Cargo.toml +++ b/primitives/authorship/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../inherents" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } async-trait = { version = "0.1.50", optional = true } diff --git a/primitives/beefy/Cargo.toml b/primitives/beefy/Cargo.toml index 4391b1939d10..6a74c58d2ceb 100644 --- a/primitives/beefy/Cargo.toml +++ b/primitives/beefy/Cargo.toml @@ -12,15 +12,15 @@ codec = { version = "2.2.0", package = "parity-scale-codec", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-api = { version = "4.0.0-dev", path = "../api", default-features = false } -sp-application-crypto = { version = "4.0.0-dev", path = "../application-crypto", default-features = false } +sp-application-crypto = { version = "4.0.0", path = "../application-crypto", default-features = false } sp-core = { version = "4.1.0-dev", path = "../core", default-features = false } -sp-runtime = { version = "4.0.0-dev", path = "../runtime", default-features = false } +sp-runtime = { version = "4.0.0", path = "../runtime", default-features = false } sp-std = { version = "4.0.0", path = "../std", default-features = false } [dev-dependencies] hex = "0.4.3" hex-literal = "0.3" -sp-keystore = { version = "0.10.0-dev", path = "../keystore" } +sp-keystore = { version = "0.10.0", path = "../keystore" } [features] default = ["std"] diff --git a/primitives/block-builder/Cargo.toml b/primitives/block-builder/Cargo.toml index a346f95cc4c4..083865cd2ccc 100644 --- a/primitives/block-builder/Cargo.toml +++ b/primitives/block-builder/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../runtime" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } diff --git a/primitives/blockchain/Cargo.toml b/primitives/blockchain/Cargo.toml index 02e74a63d959..6eeacf5f2697 100644 --- a/primitives/blockchain/Cargo.toml +++ b/primitives/blockchain/Cargo.toml @@ -21,7 +21,7 @@ thiserror = "1.0.30" futures = "0.3.9" codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } sp-consensus = { version = "0.10.0-dev", path = "../consensus/common" } -sp-runtime = { version = "4.0.0-dev", path = "../runtime" } -sp-state-machine = { version = "0.10.0-dev", path = "../state-machine" } +sp-runtime = { version = "4.0.0", path = "../runtime" } +sp-state-machine = { version = "0.10.0", path = "../state-machine" } sp-database = { version = "4.0.0-dev", path = "../database" } sp-api = { version = "4.0.0-dev", path = "../api" } diff --git a/primitives/consensus/aura/Cargo.toml b/primitives/consensus/aura/Cargo.toml index e3c883a6e783..747a9f546cb0 100644 --- a/primitives/consensus/aura/Cargo.toml +++ b/primitives/consensus/aura/Cargo.toml @@ -13,12 +13,12 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-application-crypto = { version = "4.0.0-dev", default-features = false, path = "../../application-crypto" } +sp-application-crypto = { version = "4.0.0", default-features = false, path = "../../application-crypto" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../std" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../api" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../runtime" } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../inherents" } sp-timestamp = { version = "4.0.0-dev", default-features = false, path = "../../timestamp" } sp-consensus-slots = { version = "0.10.0-dev", default-features = false, path = "../slots" } diff --git a/primitives/consensus/babe/Cargo.toml b/primitives/consensus/babe/Cargo.toml index 997744dd52bb..fcfda410765e 100644 --- a/primitives/consensus/babe/Cargo.toml +++ b/primitives/consensus/babe/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-application-crypto = { version = "4.0.0-dev", default-features = false, path = "../../application-crypto" } +sp-application-crypto = { version = "4.0.0", default-features = false, path = "../../application-crypto" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } merlin = { version = "2.0", default-features = false } @@ -24,8 +24,8 @@ sp-consensus-slots = { version = "0.10.0-dev", default-features = false, path = sp-consensus-vrf = { version = "0.10.0-dev", path = "../vrf", default-features = false } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../core" } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../inherents" } -sp-keystore = { version = "0.10.0-dev", default-features = false, path = "../../keystore", optional = true } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../runtime" } +sp-keystore = { version = "0.10.0", default-features = false, path = "../../keystore", optional = true } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../runtime" } sp-timestamp = { version = "4.0.0-dev", path = "../../timestamp", optional = true } serde = { version = "1.0.126", features = ["derive"], optional = true } async-trait = { version = "0.1.50", optional = true } diff --git a/primitives/consensus/common/Cargo.toml b/primitives/consensus/common/Cargo.toml index 2ad4a0895935..e638c04a08dc 100644 --- a/primitives/consensus/common/Cargo.toml +++ b/primitives/consensus/common/Cargo.toml @@ -22,11 +22,11 @@ futures = { version = "0.3.1", features = ["thread-pool"] } log = "0.4.8" sp-core = { path = "../../core", version = "4.1.0-dev" } sp-inherents = { version = "4.0.0-dev", path = "../../inherents" } -sp-state-machine = { version = "0.10.0-dev", path = "../../state-machine" } +sp-state-machine = { version = "0.10.0", path = "../../state-machine" } futures-timer = "3.0.1" sp-std = { version = "4.0.0", path = "../../std" } sp-version = { version = "4.0.0-dev", path = "../../version" } -sp-runtime = { version = "4.0.0-dev", path = "../../runtime" } +sp-runtime = { version = "4.0.0", path = "../../runtime" } thiserror = "1.0.30" [dev-dependencies] diff --git a/primitives/consensus/pow/Cargo.toml b/primitives/consensus/pow/Cargo.toml index d7f2b18e3fdb..6e00453da1bd 100644 --- a/primitives/consensus/pow/Cargo.toml +++ b/primitives/consensus/pow/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-api = { version = "4.0.0-dev", default-features = false, path = "../../api" } sp-std = { version = "4.0.0", default-features = false, path = "../../std" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../runtime" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../core" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } diff --git a/primitives/consensus/slots/Cargo.toml b/primitives/consensus/slots/Cargo.toml index 9177157bd5ed..23f73454aad9 100644 --- a/primitives/consensus/slots/Cargo.toml +++ b/primitives/consensus/slots/Cargo.toml @@ -16,8 +16,8 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } serde = { version = "1.0", features = ["derive"], optional = true } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../runtime" } -sp-arithmetic = { version = "4.0.0-dev", default-features = false, path = "../../arithmetic" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../runtime" } +sp-arithmetic = { version = "4.0.0", default-features = false, path = "../../arithmetic" } [features] default = ["std"] diff --git a/primitives/consensus/vrf/Cargo.toml b/primitives/consensus/vrf/Cargo.toml index 4eb545b08a21..586b6354f55a 100644 --- a/primitives/consensus/vrf/Cargo.toml +++ b/primitives/consensus/vrf/Cargo.toml @@ -17,7 +17,7 @@ codec = { version = "2.0.0", package = "parity-scale-codec", default-features = schnorrkel = { version = "0.9.1", features = ["preaudit_deprecated", "u64_backend"], default-features = false } sp-std = { version = "4.0.0", path = "../../std", default-features = false } sp-core = { version = "4.1.0-dev", path = "../../core", default-features = false } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../runtime" } [features] default = ["std"] diff --git a/primitives/finality-grandpa/Cargo.toml b/primitives/finality-grandpa/Cargo.toml index fed861553bf0..8bcdf1462fc8 100644 --- a/primitives/finality-grandpa/Cargo.toml +++ b/primitives/finality-grandpa/Cargo.toml @@ -21,10 +21,10 @@ grandpa = { package = "finality-grandpa", version = "0.14.1", default-features = log = { version = "0.4.8", optional = true } serde = { version = "1.0.126", optional = true, features = ["derive"] } sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } -sp-application-crypto = { version = "4.0.0-dev", default-features = false, path = "../application-crypto" } +sp-application-crypto = { version = "4.0.0", default-features = false, path = "../application-crypto" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } -sp-keystore = { version = "0.10.0-dev", default-features = false, path = "../keystore", optional = true } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../runtime" } +sp-keystore = { version = "0.10.0", default-features = false, path = "../keystore", optional = true } +sp-runtime = { version = "4.0.0", default-features = false, path = "../runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } [features] diff --git a/primitives/inherents/Cargo.toml b/primitives/inherents/Cargo.toml index 82c4f21b5c07..1ef0f2012056 100644 --- a/primitives/inherents/Cargo.toml +++ b/primitives/inherents/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } -sp-runtime = { version = "4.0.0-dev", path = "../runtime", optional = true } +sp-runtime = { version = "4.0.0", path = "../runtime", optional = true } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } thiserror = { version = "1.0.30", optional = true } impl-trait-for-tuples = "0.2.0" diff --git a/primitives/io/Cargo.toml b/primitives/io/Cargo.toml index 436420261800..9f95eb40a4e7 100644 --- a/primitives/io/Cargo.toml +++ b/primitives/io/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-io" -version = "4.0.0-dev" +version = "4.0.0" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" @@ -18,13 +18,13 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } hash-db = { version = "0.15.2", default-features = false } sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } -sp-keystore = { version = "0.10.0-dev", default-features = false, optional = true, path = "../keystore" } +sp-keystore = { version = "0.10.0", default-features = false, optional = true, path = "../keystore" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } libsecp256k1 = { version = "0.7", optional = true } -sp-state-machine = { version = "0.10.0-dev", optional = true, path = "../state-machine" } +sp-state-machine = { version = "0.10.0", optional = true, path = "../state-machine" } sp-wasm-interface = { version = "4.1.0-dev", path = "../wasm-interface", default-features = false } sp-runtime-interface = { version = "4.1.0-dev", default-features = false, path = "../runtime-interface" } -sp-trie = { version = "4.0.0-dev", optional = true, path = "../trie" } +sp-trie = { version = "4.0.0", optional = true, path = "../trie" } sp-externalities = { version = "0.10.0", optional = true, path = "../externalities" } sp-tracing = { version = "4.0.0", default-features = false, path = "../tracing" } log = { version = "0.4.8", optional = true } diff --git a/primitives/keyring/Cargo.toml b/primitives/keyring/Cargo.toml index be7d138979a1..a8529716b712 100644 --- a/primitives/keyring/Cargo.toml +++ b/primitives/keyring/Cargo.toml @@ -16,6 +16,6 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-core = { version = "4.1.0-dev", path = "../core" } -sp-runtime = { version = "4.0.0-dev", path = "../runtime" } +sp-runtime = { version = "4.0.0", path = "../runtime" } lazy_static = "1.4.0" strum = { version = "0.22.0", features = ["derive"] } diff --git a/primitives/keystore/Cargo.toml b/primitives/keystore/Cargo.toml index 7994c67b4c51..dea78c61242c 100644 --- a/primitives/keystore/Cargo.toml +++ b/primitives/keystore/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-keystore" -version = "0.10.0-dev" +version = "0.10.0" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" diff --git a/primitives/npos-elections/Cargo.toml b/primitives/npos-elections/Cargo.toml index a418cda2feef..3a5b00dcdf77 100644 --- a/primitives/npos-elections/Cargo.toml +++ b/primitives/npos-elections/Cargo.toml @@ -18,9 +18,9 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] serde = { version = "1.0.126", optional = true, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-npos-elections-solution-type = { version = "4.0.0-dev", path = "./solution-type" } -sp-arithmetic = { version = "4.0.0-dev", default-features = false, path = "../arithmetic" } +sp-arithmetic = { version = "4.0.0", default-features = false, path = "../arithmetic" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } -sp-runtime = { version = "4.0.0-dev", path = "../runtime", default-features = false } +sp-runtime = { version = "4.0.0", path = "../runtime", default-features = false } [dev-dependencies] substrate-test-utils = { version = "4.0.0-dev", path = "../../test-utils" } diff --git a/primitives/npos-elections/fuzzer/Cargo.toml b/primitives/npos-elections/fuzzer/Cargo.toml index 59d12c5a5d2e..62bb1090d047 100644 --- a/primitives/npos-elections/fuzzer/Cargo.toml +++ b/primitives/npos-elections/fuzzer/Cargo.toml @@ -19,7 +19,7 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] honggfuzz = "0.5" rand = { version = "0.7.3", features = ["std", "small_rng"] } sp-npos-elections = { version = "4.0.0-dev", path = ".." } -sp-runtime = { version = "4.0.0-dev", path = "../../runtime" } +sp-runtime = { version = "4.0.0", path = "../../runtime" } structopt = "0.3.25" [[bin]] diff --git a/primitives/npos-elections/solution-type/Cargo.toml b/primitives/npos-elections/solution-type/Cargo.toml index 5bffcff1038d..160778857f39 100644 --- a/primitives/npos-elections/solution-type/Cargo.toml +++ b/primitives/npos-elections/solution-type/Cargo.toml @@ -23,7 +23,7 @@ proc-macro-crate = "1.1.0" [dev-dependencies] parity-scale-codec = "2.3.1" scale-info = "1.0" -sp-arithmetic = { path = "../../arithmetic", version = "4.0.0-dev" } +sp-arithmetic = { path = "../../arithmetic", version = "4.0.0" } # used by generate_solution_type: sp-npos-elections = { path = "..", version = "4.0.0-dev" } trybuild = "1.0.53" diff --git a/primitives/offchain/Cargo.toml b/primitives/offchain/Cargo.toml index 55de9177e45d..50a6d8344f0d 100644 --- a/primitives/offchain/Cargo.toml +++ b/primitives/offchain/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../runtime" } [features] default = ["std"] diff --git a/primitives/panic-handler/Cargo.toml b/primitives/panic-handler/Cargo.toml index b7f3b6b5cb4d..8c3578442a79 100644 --- a/primitives/panic-handler/Cargo.toml +++ b/primitives/panic-handler/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-panic-handler" -version = "4.0.0-dev" +version = "4.0.0" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" diff --git a/primitives/runtime-interface/Cargo.toml b/primitives/runtime-interface/Cargo.toml index 69a6792ead29..fb978fbbbac1 100644 --- a/primitives/runtime-interface/Cargo.toml +++ b/primitives/runtime-interface/Cargo.toml @@ -27,7 +27,7 @@ impl-trait-for-tuples = "0.2.1" [dev-dependencies] sp-runtime-interface-test-wasm = { version = "2.0.0", path = "test-wasm" } -sp-state-machine = { version = "0.10.0-dev", path = "../state-machine" } +sp-state-machine = { version = "0.10.0", path = "../state-machine" } sp-core = { version = "4.1.0-dev", path = "../core" } sp-io = { version = "4.0.0-dev", path = "../io" } rustversion = "1.0.5" diff --git a/primitives/runtime-interface/test/Cargo.toml b/primitives/runtime-interface/test/Cargo.toml index b197f2ab8ba9..06fcf920a691 100644 --- a/primitives/runtime-interface/test/Cargo.toml +++ b/primitives/runtime-interface/test/Cargo.toml @@ -17,8 +17,8 @@ sc-executor = { version = "0.10.0-dev", path = "../../../client/executor" } sc-executor-common = { version = "0.10.0-dev", path = "../../../client/executor/common" } sp-runtime-interface-test-wasm = { version = "2.0.0", path = "../test-wasm" } sp-runtime-interface-test-wasm-deprecated = { version = "2.0.0", path = "../test-wasm-deprecated" } -sp-state-machine = { version = "0.10.0-dev", path = "../../state-machine" } -sp-runtime = { version = "4.0.0-dev", path = "../../runtime" } -sp-io = { version = "4.0.0-dev", path = "../../io" } +sp-state-machine = { version = "0.10.0", path = "../../state-machine" } +sp-runtime = { version = "4.0.0", path = "../../runtime" } +sp-io = { version = "4.0.0", path = "../../io" } tracing = "0.1.29" tracing-core = "0.1.17" diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 1d7c79ba68c9..6363a0a28631 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-runtime" -version = "4.0.0-dev" +version = "4.0.0" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" @@ -19,10 +19,10 @@ serde = { version = "1.0.126", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } -sp-application-crypto = { version = "4.0.0-dev", default-features = false, path = "../application-crypto" } -sp-arithmetic = { version = "4.0.0-dev", default-features = false, path = "../arithmetic" } +sp-application-crypto = { version = "4.0.0", default-features = false, path = "../application-crypto" } +sp-arithmetic = { version = "4.0.0", default-features = false, path = "../arithmetic" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../io" } +sp-io = { version = "4.0.0", default-features = false, path = "../io" } log = { version = "0.4.14", default-features = false } paste = "1.0" rand = { version = "0.7.2", optional = true } @@ -34,7 +34,7 @@ either = { version = "1.5", default-features = false } [dev-dependencies] serde_json = "1.0.71" rand = "0.7.2" -sp-state-machine = { version = "0.10.0-dev", path = "../state-machine" } +sp-state-machine = { version = "0.10.0", path = "../state-machine" } sp-api = { version = "4.0.0-dev", path = "../api" } substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } diff --git a/primitives/sandbox/Cargo.toml b/primitives/sandbox/Cargo.toml index 26a81caea89b..59941c9648dd 100644 --- a/primitives/sandbox/Cargo.toml +++ b/primitives/sandbox/Cargo.toml @@ -22,7 +22,7 @@ wasmi = "0.9.0" wasmi = { version = "0.9.0", optional = true } sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../io" } +sp-io = { version = "4.0.0", default-features = false, path = "../io" } sp-wasm-interface = { version = "4.1.0-dev", default-features = false, path = "../wasm-interface" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } log = { version = "0.4", default-features = false } diff --git a/primitives/session/Cargo.toml b/primitives/session/Cargo.toml index d402f36859ac..cca35710172b 100644 --- a/primitives/session/Cargo.toml +++ b/primitives/session/Cargo.toml @@ -19,7 +19,7 @@ sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../staking" } -sp-runtime = { version = "4.0.0-dev", optional = true, path = "../runtime" } +sp-runtime = { version = "4.0.0", optional = true, path = "../runtime" } [features] default = [ "std" ] diff --git a/primitives/staking/Cargo.toml b/primitives/staking/Cargo.toml index 531e696b6930..533e177391b0 100644 --- a/primitives/staking/Cargo.toml +++ b/primitives/staking/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } [features] diff --git a/primitives/state-machine/Cargo.toml b/primitives/state-machine/Cargo.toml index b6b3c90f5a7f..7ca76ed58313 100644 --- a/primitives/state-machine/Cargo.toml +++ b/primitives/state-machine/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-state-machine" -version = "0.10.0-dev" +version = "0.10.0" authors = ["Parity Technologies "] description = "Substrate State Machine" edition = "2021" @@ -20,9 +20,9 @@ parking_lot = { version = "0.11.1", optional = true } hash-db = { version = "0.15.2", default-features = false } trie-db = { version = "0.22.6", default-features = false } trie-root = { version = "0.16.0", default-features = false } -sp-trie = { version = "4.0.0-dev", path = "../trie", default-features = false } +sp-trie = { version = "4.0.0", path = "../trie", default-features = false } sp-core = { version = "4.1.0-dev", path = "../core", default-features = false } -sp-panic-handler = { version = "4.0.0-dev", path = "../panic-handler", optional = true } +sp-panic-handler = { version = "4.0.0", path = "../panic-handler", optional = true } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } num-traits = { version = "0.2.8", default-features = false } rand = { version = "0.7.2", optional = true } @@ -33,7 +33,7 @@ tracing = { version = "0.1.29", optional = true } [dev-dependencies] hex-literal = "0.3.4" -sp-runtime = { version = "4.0.0-dev", path = "../runtime" } +sp-runtime = { version = "4.0.0", path = "../runtime" } pretty_assertions = "1.0.0" rand = "0.7.2" diff --git a/primitives/tasks/Cargo.toml b/primitives/tasks/Cargo.toml index c57eb50eddb5..6ac6c6aa98be 100644 --- a/primitives/tasks/Cargo.toml +++ b/primitives/tasks/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] log = { version = "0.4.8", optional = true } sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } sp-externalities = { version = "0.10.0", optional = true, path = "../externalities" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../io" } +sp-io = { version = "4.0.0", default-features = false, path = "../io" } sp-runtime-interface = { version = "4.1.0-dev", default-features = false, path = "../runtime-interface" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } diff --git a/primitives/test-primitives/Cargo.toml b/primitives/test-primitives/Cargo.toml index 18a0b9501e18..5d0a3d440c46 100644 --- a/primitives/test-primitives/Cargo.toml +++ b/primitives/test-primitives/Cargo.toml @@ -12,11 +12,11 @@ publish = false targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-application-crypto = { version = "4.0.0-dev", default-features = false, path = "../application-crypto" } +sp-application-crypto = { version = "4.0.0", default-features = false, path = "../application-crypto" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } serde = { version = "1.0.126", optional = true, features = ["derive"] } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../runtime" } parity-util-mem = { version = "0.10.2", default-features = false, features = ["primitive-types"] } [features] diff --git a/primitives/timestamp/Cargo.toml b/primitives/timestamp/Cargo.toml index 0096fe4c809d..4c5fdefe990a 100644 --- a/primitives/timestamp/Cargo.toml +++ b/primitives/timestamp/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../runtime" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../inherents" } thiserror = { version = "1.0.30", optional = true } diff --git a/primitives/transaction-pool/Cargo.toml b/primitives/transaction-pool/Cargo.toml index e4a407547971..2590208078db 100644 --- a/primitives/transaction-pool/Cargo.toml +++ b/primitives/transaction-pool/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../runtime" } [features] default = [ "std" ] diff --git a/primitives/transaction-storage-proof/Cargo.toml b/primitives/transaction-storage-proof/Cargo.toml index f2ea55cc18c5..d731808c64c2 100644 --- a/primitives/transaction-storage-proof/Cargo.toml +++ b/primitives/transaction-storage-proof/Cargo.toml @@ -14,9 +14,9 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../inherents" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } -sp-trie = { version = "4.0.0-dev", optional = true, path = "../trie" } +sp-trie = { version = "4.0.0", optional = true, path = "../trie" } sp-core = { version = "4.1.0-dev", path = "../core", optional = true } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } diff --git a/primitives/trie/Cargo.toml b/primitives/trie/Cargo.toml index 983d58c9bb8d..02aaa75aa939 100644 --- a/primitives/trie/Cargo.toml +++ b/primitives/trie/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-trie" -version = "4.0.0-dev" +version = "4.0.0" authors = ["Parity Technologies "] description = "Patricia trie stuff using a parity-scale-codec node format" repository = "https://github.com/paritytech/substrate/" @@ -32,7 +32,7 @@ trie-bench = "0.28.0" trie-standardmap = "0.15.2" criterion = "0.3.3" hex-literal = "0.3.4" -sp-runtime = { version = "4.0.0-dev", path = "../runtime" } +sp-runtime = { version = "4.0.0", path = "../runtime" } [features] default = ["std"] diff --git a/primitives/version/Cargo.toml b/primitives/version/Cargo.toml index a58b27c7c151..b8a3a5bc3e30 100644 --- a/primitives/version/Cargo.toml +++ b/primitives/version/Cargo.toml @@ -19,7 +19,7 @@ serde = { version = "1.0.126", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../std" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../runtime" } sp-version-proc-macro = { version = "4.0.0-dev", default-features = false, path = "proc-macro" } parity-wasm = { version = "0.42.2", optional = true } thiserror = { version = "1.0.30", optional = true } diff --git a/test-utils/client/Cargo.toml b/test-utils/client/Cargo.toml index 9b77cde505af..5d148ccd125e 100644 --- a/test-utils/client/Cargo.toml +++ b/test-utils/client/Cargo.toml @@ -30,8 +30,8 @@ sc-service = { version = "0.10.0-dev", default-features = false, features = [ sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } -sp-keystore = { version = "0.10.0-dev", path = "../../primitives/keystore" } +sp-keystore = { version = "0.10.0", path = "../../primitives/keystore" } sp-keyring = { version = "4.0.0-dev", path = "../../primitives/keyring" } -sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } -sp-state-machine = { version = "0.10.0-dev", path = "../../primitives/state-machine" } +sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } +sp-state-machine = { version = "0.10.0", path = "../../primitives/state-machine" } async-trait = "0.1.50" diff --git a/test-utils/runtime/Cargo.toml b/test-utils/runtime/Cargo.toml index ae4be0d13af7..72e2c255c15c 100644 --- a/test-utils/runtime/Cargo.toml +++ b/test-utils/runtime/Cargo.toml @@ -13,7 +13,7 @@ publish = false targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-application-crypto = { version = "4.0.0-dev", default-features = false, path = "../../primitives/application-crypto" } +sp-application-crypto = { version = "4.0.0", default-features = false, path = "../../primitives/application-crypto" } sp-consensus-aura = { version = "0.10.0-dev", default-features = false, path = "../../primitives/consensus/aura" } sp-consensus-babe = { version = "0.10.0-dev", default-features = false, path = "../../primitives/consensus/babe" } sp-block-builder = { version = "4.0.0-dev", default-features = false, path = "../../primitives/block-builder" } @@ -26,23 +26,23 @@ sp-offchain = { version = "4.0.0-dev", default-features = false, path = "../../p sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-runtime-interface = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime-interface" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } +sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../../frame/support" } sp-version = { version = "4.0.0-dev", default-features = false, path = "../../primitives/version" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../primitives/session" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../primitives/api" } -sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } pallet-babe = { version = "4.0.0-dev", default-features = false, path = "../../frame/babe" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../frame/system" } frame-system-rpc-runtime-api = { version = "4.0.0-dev", default-features = false, path = "../../frame/system/rpc/runtime-api" } pallet-timestamp = { version = "4.0.0-dev", default-features = false, path = "../../frame/timestamp" } sp-finality-grandpa = { version = "4.0.0-dev", default-features = false, path = "../../primitives/finality-grandpa" } -sp-trie = { version = "4.0.0-dev", default-features = false, path = "../../primitives/trie" } +sp-trie = { version = "4.0.0", default-features = false, path = "../../primitives/trie" } sp-transaction-pool = { version = "4.0.0-dev", default-features = false, path = "../../primitives/transaction-pool" } trie-db = { version = "0.22.6", default-features = false } parity-util-mem = { version = "0.10.2", default-features = false, features = ["primitive-types"] } sc-service = { version = "0.10.0-dev", default-features = false, optional = true, features = ["test-helpers"], path = "../../client/service" } -sp-state-machine = { version = "0.10.0-dev", default-features = false, path = "../../primitives/state-machine" } +sp-state-machine = { version = "0.10.0", default-features = false, path = "../../primitives/state-machine" } sp-externalities = { version = "0.10.0", default-features = false, path = "../../primitives/externalities" } # 3rd party diff --git a/test-utils/runtime/client/Cargo.toml b/test-utils/runtime/client/Cargo.toml index b66fdc3422ae..7babbfb2ed8e 100644 --- a/test-utils/runtime/client/Cargo.toml +++ b/test-utils/runtime/client/Cargo.toml @@ -18,7 +18,7 @@ sc-block-builder = { version = "0.10.0-dev", path = "../../../client/block-build substrate-test-client = { version = "2.0.0", path = "../../client" } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } substrate-test-runtime = { version = "2.0.0", path = "../../runtime" } -sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } codec = { package = "parity-scale-codec", version = "2.0.0" } diff --git a/test-utils/runtime/transaction-pool/Cargo.toml b/test-utils/runtime/transaction-pool/Cargo.toml index ee1ac4814db5..c1794d288eca 100644 --- a/test-utils/runtime/transaction-pool/Cargo.toml +++ b/test-utils/runtime/transaction-pool/Cargo.toml @@ -16,7 +16,7 @@ substrate-test-runtime-client = { version = "2.0.0", path = "../client" } parking_lot = "0.11.1" codec = { package = "parity-scale-codec", version = "2.0.0" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } sc-transaction-pool = { version = "4.0.0-dev", path = "../../../client/transaction-pool", features = ["test-helpers"] } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../../../client/transaction-pool/api" } futures = "0.3.16" diff --git a/utils/frame/benchmarking-cli/Cargo.toml b/utils/frame/benchmarking-cli/Cargo.toml index c8d762ec73cd..d61cf71aec38 100644 --- a/utils/frame/benchmarking-cli/Cargo.toml +++ b/utils/frame/benchmarking-cli/Cargo.toml @@ -21,9 +21,9 @@ sc-cli = { version = "0.10.0-dev", path = "../../../client/cli" } sc-client-db = { version = "0.10.0-dev", path = "../../../client/db" } sc-executor = { version = "0.10.0-dev", path = "../../../client/executor" } sp-externalities = { version = "0.10.0", path = "../../../primitives/externalities" } -sp-keystore = { version = "0.10.0-dev", path = "../../../primitives/keystore" } -sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } -sp-state-machine = { version = "0.10.0-dev", path = "../../../primitives/state-machine" } +sp-keystore = { version = "0.10.0", path = "../../../primitives/keystore" } +sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } +sp-state-machine = { version = "0.10.0", path = "../../../primitives/state-machine" } codec = { version = "2.0.0", package = "parity-scale-codec" } structopt = "0.3.25" chrono = "0.4" diff --git a/utils/frame/frame-utilities-cli/Cargo.toml b/utils/frame/frame-utilities-cli/Cargo.toml index feb02f1eb721..db9e4a7d9074 100644 --- a/utils/frame/frame-utilities-cli/Cargo.toml +++ b/utils/frame/frame-utilities-cli/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" [dependencies] sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sc-cli = { version = "0.10.0-dev", path = "../../../client/cli" } -sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } structopt = "0.3.25" frame-system = { version = "4.0.0-dev", path = "../../../frame/system" } frame-support = { version = "4.0.0-dev", path = "../../../frame/support" } diff --git a/utils/frame/generate-bags/Cargo.toml b/utils/frame/generate-bags/Cargo.toml index 2c9374fc5cca..6a512842129e 100644 --- a/utils/frame/generate-bags/Cargo.toml +++ b/utils/frame/generate-bags/Cargo.toml @@ -17,7 +17,7 @@ frame-system = { version = "4.0.0-dev", path = "../../../frame/system" } pallet-staking = { version = "4.0.0-dev", path = "../../../frame/staking" } # primitives -sp-io = { version = "4.0.0-dev", path = "../../../primitives/io" } +sp-io = { version = "4.0.0", path = "../../../primitives/io" } # third party chrono = { version = "0.4.19" } diff --git a/utils/frame/remote-externalities/Cargo.toml b/utils/frame/remote-externalities/Cargo.toml index 0cf4980a104c..edd538baf562 100644 --- a/utils/frame/remote-externalities/Cargo.toml +++ b/utils/frame/remote-externalities/Cargo.toml @@ -24,7 +24,7 @@ serde = "1.0.126" sp-io = { version = "4.0.0-dev", path = "../../../primitives/io" } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } -sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } sp-version = { version = "4.0.0-dev", path = "../../../primitives/version" } [dev-dependencies] diff --git a/utils/frame/rpc/system/Cargo.toml b/utils/frame/rpc/system/Cargo.toml index f71f3d6e93e1..53ad36a96930 100644 --- a/utils/frame/rpc/system/Cargo.toml +++ b/utils/frame/rpc/system/Cargo.toml @@ -20,7 +20,7 @@ jsonrpc-core = "18.0.0" jsonrpc-core-client = "18.0.0" jsonrpc-derive = "18.0.0" log = "0.4.8" -sp-runtime = { version = "4.0.0-dev", path = "../../../../primitives/runtime" } +sp-runtime = { version = "4.0.0", path = "../../../../primitives/runtime" } sp-api = { version = "4.0.0-dev", path = "../../../../primitives/api" } frame-system-rpc-runtime-api = { version = "4.0.0-dev", path = "../../../../frame/system/rpc/runtime-api" } sp-core = { version = "4.1.0-dev", path = "../../../../primitives/core" } diff --git a/utils/frame/try-runtime/cli/Cargo.toml b/utils/frame/try-runtime/cli/Cargo.toml index d6b75d31fac8..a0eca3cc9e9c 100644 --- a/utils/frame/try-runtime/cli/Cargo.toml +++ b/utils/frame/try-runtime/cli/Cargo.toml @@ -22,11 +22,11 @@ sc-service = { version = "0.10.0-dev", default-features = false, path = "../../. sc-cli = { version = "0.10.0-dev", path = "../../../../client/cli" } sc-executor = { version = "0.10.0-dev", path = "../../../../client/executor" } sc-chain-spec = { version = "4.0.0-dev", path = "../../../../client/chain-spec" } -sp-state-machine = { version = "0.10.0-dev", path = "../../../../primitives/state-machine" } -sp-runtime = { version = "4.0.0-dev", path = "../../../../primitives/runtime" } +sp-state-machine = { version = "0.10.0", path = "../../../../primitives/state-machine" } +sp-runtime = { version = "4.0.0", path = "../../../../primitives/runtime" } sp-core = { version = "4.1.0-dev", path = "../../../../primitives/core" } sp-io = { version = "4.0.0-dev", path = "../../../../primitives/io" } -sp-keystore = { version = "0.10.0-dev", path = "../../../../primitives/keystore" } +sp-keystore = { version = "0.10.0", path = "../../../../primitives/keystore" } sp-externalities = { version = "0.10.0", path = "../../../../primitives/externalities" } sp-version = { version = "4.0.0-dev", path = "../../../../primitives/version" } From 76f6078825dc1641ef134d71ab7443b552d71273 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Dec 2021 13:45:30 +0100 Subject: [PATCH 298/695] Bump parking_lot from 0.11.1 to 0.11.2 (#10335) Bumps [parking_lot](https://github.com/Amanieu/parking_lot) from 0.11.1 to 0.11.2. - [Release notes](https://github.com/Amanieu/parking_lot/releases) - [Changelog](https://github.com/Amanieu/parking_lot/blob/master/CHANGELOG.md) - [Commits](https://github.com/Amanieu/parking_lot/compare/0.11.1...0.11.2) --- updated-dependencies: - dependency-name: parking_lot dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 124 +++++++++--------- client/api/Cargo.toml | 2 +- client/basic-authorship/Cargo.toml | 2 +- client/consensus/aura/Cargo.toml | 2 +- client/consensus/babe/Cargo.toml | 2 +- client/consensus/common/Cargo.toml | 2 +- client/consensus/pow/Cargo.toml | 2 +- client/db/Cargo.toml | 2 +- client/executor/Cargo.toml | 2 +- client/finality-grandpa/Cargo.toml | 2 +- client/keystore/Cargo.toml | 2 +- client/network/Cargo.toml | 2 +- client/network/test/Cargo.toml | 2 +- client/offchain/Cargo.toml | 2 +- client/rpc-api/Cargo.toml | 2 +- client/rpc/Cargo.toml | 2 +- client/service/Cargo.toml | 2 +- client/service/test/Cargo.toml | 2 +- client/state-db/Cargo.toml | 2 +- client/telemetry/Cargo.toml | 2 +- client/tracing/Cargo.toml | 2 +- client/transaction-pool/Cargo.toml | 2 +- .../election-provider-multi-phase/Cargo.toml | 2 +- primitives/blockchain/Cargo.toml | 2 +- primitives/core/Cargo.toml | 2 +- primitives/database/Cargo.toml | 2 +- primitives/io/Cargo.toml | 2 +- primitives/keystore/Cargo.toml | 2 +- primitives/state-machine/Cargo.toml | 2 +- .../runtime/transaction-pool/Cargo.toml | 2 +- 30 files changed, 91 insertions(+), 91 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0364fafd2547..4ff6fc1974fa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -480,7 +480,7 @@ dependencies = [ "futures 0.3.16", "log 0.4.14", "parity-scale-codec", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "sc-client-api", "sc-keystore", "sc-network", @@ -1871,7 +1871,7 @@ dependencies = [ "log 0.4.14", "num-traits", "parity-scale-codec", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "rand 0.8.4", "scale-info", ] @@ -3097,7 +3097,7 @@ dependencies = [ "jsonrpc-server-utils", "log 0.4.14", "net2", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "unicase 2.6.0", ] @@ -3112,7 +3112,7 @@ dependencies = [ "jsonrpc-server-utils", "log 0.4.14", "parity-tokio-ipc", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "tower-service", ] @@ -3126,7 +3126,7 @@ dependencies = [ "jsonrpc-core", "lazy_static", "log 0.4.14", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "rand 0.7.3", "serde", ] @@ -3160,7 +3160,7 @@ dependencies = [ "jsonrpc-server-utils", "log 0.4.14", "parity-ws", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "slab", ] @@ -3297,7 +3297,7 @@ checksum = "c3b6b85fc643f5acd0bffb2cc8a6d150209379267af0d41db72170021841f9f5" dependencies = [ "kvdb", "parity-util-mem", - "parking_lot 0.11.1", + "parking_lot 0.11.2", ] [[package]] @@ -3312,7 +3312,7 @@ dependencies = [ "num_cpus", "owning_ref", "parity-util-mem", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "regex", "rocksdb", "smallvec 1.7.0", @@ -3431,7 +3431,7 @@ dependencies = [ "libp2p-websocket", "libp2p-yamux", "multiaddr", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "pin-project 1.0.8", "smallvec 1.7.0", "wasm-timer", @@ -3456,7 +3456,7 @@ dependencies = [ "multiaddr", "multihash 0.14.0", "multistream-select", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "pin-project 1.0.8", "prost", "prost-build", @@ -3630,7 +3630,7 @@ dependencies = [ "libp2p-core", "log 0.4.14", "nohash-hasher", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "rand 0.7.3", "smallvec 1.7.0", "unsigned-varint 0.7.0", @@ -3863,7 +3863,7 @@ checksum = "4e7362abb8867d7187e7e93df17f460d554c997fc5c8ac57dc1259057f6889af" dependencies = [ "futures 0.3.16", "libp2p-core", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "thiserror", "yamux", ] @@ -4000,9 +4000,9 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.2" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312" +checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" dependencies = [ "scopeguard", ] @@ -5540,7 +5540,7 @@ dependencies = [ "log 0.4.14", "pallet-balances", "parity-scale-codec", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "rand 0.7.3", "scale-info", "sp-arithmetic", @@ -6315,7 +6315,7 @@ dependencies = [ "log 0.4.14", "lz4", "memmap2 0.2.1", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "rand 0.8.4", "snap", ] @@ -6376,7 +6376,7 @@ dependencies = [ "hashbrown 0.11.2", "impl-trait-for-tuples", "parity-util-mem-derive", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "primitive-types", "smallvec 1.7.0", "winapi 0.3.9", @@ -6445,13 +6445,13 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", - "lock_api 0.4.2", - "parking_lot_core 0.8.3", + "lock_api 0.4.5", + "parking_lot_core 0.8.5", ] [[package]] @@ -6471,14 +6471,14 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" dependencies = [ "cfg-if 1.0.0", "instant", "libc", - "redox_syscall 0.2.5", + "redox_syscall 0.2.10", "smallvec 1.7.0", "winapi 0.3.9", ] @@ -6863,7 +6863,7 @@ dependencies = [ "fnv", "lazy_static", "memchr", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "thiserror", ] @@ -7259,9 +7259,9 @@ checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" [[package]] name = "redox_syscall" -version = "0.2.5" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" dependencies = [ "bitflags", ] @@ -7273,7 +7273,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" dependencies = [ "getrandom 0.2.3", - "redox_syscall 0.2.5", + "redox_syscall 0.2.10", ] [[package]] @@ -7626,7 +7626,7 @@ dependencies = [ "futures-timer 3.0.2", "log 0.4.14", "parity-scale-codec", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "sc-block-builder", "sc-client-api", "sc-proposer-metrics", @@ -7732,7 +7732,7 @@ dependencies = [ "hash-db", "log 0.4.14", "parity-scale-codec", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "sc-executor", "sc-transaction-pool-api", "sc-utils", @@ -7765,7 +7765,7 @@ dependencies = [ "log 0.4.14", "parity-db", "parity-scale-codec", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "quickcheck", "sc-client-api", "sc-state-db", @@ -7790,7 +7790,7 @@ dependencies = [ "futures-timer 3.0.2", "libp2p", "log 0.4.14", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "sc-client-api", "sc-utils", "serde", @@ -7815,7 +7815,7 @@ dependencies = [ "getrandom 0.2.3", "log 0.4.14", "parity-scale-codec", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "sc-block-builder", "sc-client-api", "sc-consensus", @@ -7857,7 +7857,7 @@ dependencies = [ "num-rational 0.2.4", "num-traits", "parity-scale-codec", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "rand 0.7.3", "rand_chacha 0.2.2", "retain_mut", @@ -7981,7 +7981,7 @@ dependencies = [ "futures-timer 3.0.2", "log 0.4.14", "parity-scale-codec", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "sc-client-api", "sc-consensus", "sp-api", @@ -8041,7 +8041,7 @@ dependencies = [ "log 0.4.14", "lru 0.6.6", "parity-scale-codec", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "paste 1.0.6", "regex", "sc-executor-common", @@ -8138,7 +8138,7 @@ dependencies = [ "futures-timer 3.0.2", "log 0.4.14", "parity-scale-codec", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "rand 0.8.4", "sc-block-builder", "sc-client-api", @@ -8217,7 +8217,7 @@ dependencies = [ "async-trait", "derive_more", "hex", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "serde_json", "sp-application-crypto", "sp-core", @@ -8250,7 +8250,7 @@ dependencies = [ "log 0.4.14", "lru 0.7.0", "parity-scale-codec", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "pin-project 1.0.8", "prost", "prost-build", @@ -8310,7 +8310,7 @@ dependencies = [ "futures-timer 3.0.2", "libp2p", "log 0.4.14", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "rand 0.7.3", "sc-block-builder", "sc-client-api", @@ -8342,7 +8342,7 @@ dependencies = [ "num_cpus", "once_cell", "parity-scale-codec", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "rand 0.7.3", "sc-block-builder", "sc-client-api", @@ -8396,7 +8396,7 @@ dependencies = [ "lazy_static", "log 0.4.14", "parity-scale-codec", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "sc-block-builder", "sc-chain-spec", "sc-client-api", @@ -8432,7 +8432,7 @@ dependencies = [ "jsonrpc-pubsub", "log 0.4.14", "parity-scale-codec", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "sc-chain-spec", "sc-transaction-pool-api", "serde", @@ -8491,7 +8491,7 @@ dependencies = [ "log 0.4.14", "parity-scale-codec", "parity-util-mem", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "pin-project 1.0.8", "rand 0.7.3", "sc-block-builder", @@ -8551,7 +8551,7 @@ dependencies = [ "hex-literal", "log 0.4.14", "parity-scale-codec", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "sc-block-builder", "sc-client-api", "sc-client-db", @@ -8585,7 +8585,7 @@ dependencies = [ "parity-scale-codec", "parity-util-mem", "parity-util-mem-derive", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "sc-client-api", "sp-core", ] @@ -8619,7 +8619,7 @@ dependencies = [ "futures 0.3.16", "libp2p", "log 0.4.14", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "pin-project 1.0.8", "rand 0.7.3", "serde", @@ -8640,7 +8640,7 @@ dependencies = [ "libc", "log 0.4.14", "once_cell", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "regex", "rustc-hash", "sc-client-api", @@ -8682,7 +8682,7 @@ dependencies = [ "log 0.4.14", "parity-scale-codec", "parity-util-mem", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "retain_mut", "sc-block-builder", "sc-client-api", @@ -9294,7 +9294,7 @@ dependencies = [ "log 0.4.14", "lru 0.7.0", "parity-scale-codec", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "sp-api", "sp-consensus", "sp-database", @@ -9418,7 +9418,7 @@ dependencies = [ "num-traits", "parity-scale-codec", "parity-util-mem", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "primitive-types", "rand 0.7.3", "regex", @@ -9473,7 +9473,7 @@ name = "sp-database" version = "4.0.0-dev" dependencies = [ "kvdb", - "parking_lot 0.11.1", + "parking_lot 0.11.2", ] [[package]] @@ -9535,7 +9535,7 @@ dependencies = [ "libsecp256k1", "log 0.4.14", "parity-scale-codec", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "sp-core", "sp-externalities", "sp-keystore", @@ -9568,7 +9568,7 @@ dependencies = [ "futures 0.3.16", "merlin", "parity-scale-codec", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "rand 0.7.3", "rand_chacha 0.2.2", "schnorrkel", @@ -9809,7 +9809,7 @@ dependencies = [ "log 0.4.14", "num-traits", "parity-scale-codec", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "pretty_assertions", "rand 0.7.3", "smallvec 1.7.0", @@ -10263,7 +10263,7 @@ dependencies = [ "derive_more", "futures 0.3.16", "parity-scale-codec", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "sc-transaction-pool", "sc-transaction-pool-api", "sp-blockchain", @@ -10371,7 +10371,7 @@ dependencies = [ "cfg-if 1.0.0", "libc", "rand 0.8.4", - "redox_syscall 0.2.5", + "redox_syscall 0.2.10", "remove_dir_all", "winapi 0.3.9", ] @@ -10576,7 +10576,7 @@ dependencies = [ "mio 0.7.13", "num_cpus", "once_cell", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "pin-project-lite 0.2.6", "signal-hook-registry", "tokio-macros", @@ -10815,7 +10815,7 @@ dependencies = [ "chrono", "lazy_static", "matchers", - "parking_lot 0.11.1", + "parking_lot 0.9.0", "regex", "serde", "serde_json", @@ -10924,7 +10924,7 @@ dependencies = [ "lazy_static", "log 0.4.14", "lru-cache", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "resolv-conf", "smallvec 1.7.0", "thiserror", @@ -11324,7 +11324,7 @@ checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f" dependencies = [ "futures 0.3.16", "js-sys", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "pin-utils", "wasm-bindgen", "wasm-bindgen-futures", @@ -11920,7 +11920,7 @@ dependencies = [ "futures 0.3.16", "log 0.4.14", "nohash-hasher", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "rand 0.8.4", "static_assertions", ] diff --git a/client/api/Cargo.toml b/client/api/Cargo.toml index 4738a7d611b1..f1d3969ec27a 100644 --- a/client/api/Cargo.toml +++ b/client/api/Cargo.toml @@ -25,7 +25,7 @@ futures = "0.3.1" hash-db = { version = "0.15.2", default-features = false } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } log = "0.4.8" -parking_lot = "0.11.1" +parking_lot = "0.11.2" sp-database = { version = "4.0.0-dev", path = "../../primitives/database" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-keystore = { version = "0.10.0", default-features = false, path = "../../primitives/keystore" } diff --git a/client/basic-authorship/Cargo.toml b/client/basic-authorship/Cargo.toml index 4b4627cb6eea..26a2defbbb4d 100644 --- a/client/basic-authorship/Cargo.toml +++ b/client/basic-authorship/Cargo.toml @@ -33,4 +33,4 @@ sc-proposer-metrics = { version = "0.10.0-dev", path = "../proposer-metrics" } [dev-dependencies] sc-transaction-pool = { version = "4.0.0-dev", path = "../transaction-pool" } substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } -parking_lot = "0.11.1" +parking_lot = "0.11.2" diff --git a/client/consensus/aura/Cargo.toml b/client/consensus/aura/Cargo.toml index 05f0d3804e7b..e9c897de5dcb 100644 --- a/client/consensus/aura/Cargo.toml +++ b/client/consensus/aura/Cargo.toml @@ -48,4 +48,4 @@ sc-network = { version = "0.10.0-dev", path = "../../network" } sc-network-test = { version = "0.8.0", path = "../../network/test" } substrate-test-runtime-client = { version = "2.0.0", path = "../../../test-utils/runtime/client" } tempfile = "3.1.0" -parking_lot = "0.11.1" +parking_lot = "0.11.2" diff --git a/client/consensus/babe/Cargo.toml b/client/consensus/babe/Cargo.toml index 634c987444a0..c96d648846c5 100644 --- a/client/consensus/babe/Cargo.toml +++ b/client/consensus/babe/Cargo.toml @@ -44,7 +44,7 @@ sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } fork-tree = { version = "3.0.0", path = "../../../utils/fork-tree" } prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.10.0-dev" } futures = "0.3.9" -parking_lot = "0.11.1" +parking_lot = "0.11.2" log = "0.4.8" schnorrkel = { version = "0.9.1", features = ["preaudit_deprecated"] } rand = "0.7.2" diff --git a/client/consensus/common/Cargo.toml b/client/consensus/common/Cargo.toml index 9d2323b75760..0ca0c5675839 100644 --- a/client/consensus/common/Cargo.toml +++ b/client/consensus/common/Cargo.toml @@ -26,7 +26,7 @@ sp-state-machine = { version = "0.10.0", path = "../../../primitives/state-machi sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } sc-utils = { version = "4.0.0-dev", path = "../../utils" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } -parking_lot = "0.11.1" +parking_lot = "0.11.2" serde = { version = "1.0", features = ["derive"] } prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.10.0-dev" } async-trait = "0.1.42" diff --git a/client/consensus/pow/Cargo.toml b/client/consensus/pow/Cargo.toml index 00ee58c21247..19cc5135de03 100644 --- a/client/consensus/pow/Cargo.toml +++ b/client/consensus/pow/Cargo.toml @@ -27,7 +27,7 @@ sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/commo log = "0.4.8" futures = "0.3.16" futures-timer = "3.0.1" -parking_lot = "0.11.1" +parking_lot = "0.11.2" derive_more = "0.99.16" prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.10.0-dev"} async-trait = "0.1.50" diff --git a/client/db/Cargo.toml b/client/db/Cargo.toml index 80ba026de3cf..5acc7e9df8b8 100644 --- a/client/db/Cargo.toml +++ b/client/db/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -parking_lot = "0.11.1" +parking_lot = "0.11.2" log = "0.4.8" kvdb = "0.10.0" kvdb-rocksdb = { version = "0.14.0", optional = true } diff --git a/client/executor/Cargo.toml b/client/executor/Cargo.toml index a87a38291370..09f10a975340 100644 --- a/client/executor/Cargo.toml +++ b/client/executor/Cargo.toml @@ -30,7 +30,7 @@ sp-externalities = { version = "0.10.0", path = "../../primitives/externalities" sc-executor-common = { version = "0.10.0-dev", path = "common" } sc-executor-wasmi = { version = "0.10.0-dev", path = "wasmi" } sc-executor-wasmtime = { version = "0.10.0-dev", path = "wasmtime", optional = true } -parking_lot = "0.11.1" +parking_lot = "0.11.2" log = "0.4.8" libsecp256k1 = "0.7" sp-core-hashing-proc-macro = { version = "4.0.0-dev", path = "../../primitives/core/hashing/proc-macro" } diff --git a/client/finality-grandpa/Cargo.toml b/client/finality-grandpa/Cargo.toml index 2ddd4f765163..e296c5a4e3da 100644 --- a/client/finality-grandpa/Cargo.toml +++ b/client/finality-grandpa/Cargo.toml @@ -21,7 +21,7 @@ fork-tree = { version = "3.0.0", path = "../../utils/fork-tree" } futures = "0.3.9" futures-timer = "3.0.1" log = "0.4.8" -parking_lot = "0.11.1" +parking_lot = "0.11.2" rand = "0.8.4" parity-scale-codec = { version = "2.3.1", features = ["derive"] } sp-application-crypto = { version = "4.0.0", path = "../../primitives/application-crypto" } diff --git a/client/keystore/Cargo.toml b/client/keystore/Cargo.toml index abdd4ac372e7..b4c684a206f3 100644 --- a/client/keystore/Cargo.toml +++ b/client/keystore/Cargo.toml @@ -21,7 +21,7 @@ sp-application-crypto = { version = "4.0.0", path = "../../primitives/applicatio sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-keystore = { version = "0.10.0", path = "../../primitives/keystore" } hex = "0.4.0" -parking_lot = "0.11.1" +parking_lot = "0.11.2" serde_json = "1.0.71" [dev-dependencies] diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index 95f84f493bb7..643b2440209f 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -38,7 +38,7 @@ linked-hash-map = "0.5.4" linked_hash_set = "0.1.3" lru = "0.7.0" log = "0.4.8" -parking_lot = "0.11.1" +parking_lot = "0.11.2" pin-project = "1.0.8" prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.10.0-dev", path = "../../utils/prometheus" } prost = "0.9" diff --git a/client/network/test/Cargo.toml b/client/network/test/Cargo.toml index fd9e9e2f7ef3..e2e46a27b273 100644 --- a/client/network/test/Cargo.toml +++ b/client/network/test/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] async-std = "1.10.0" sc-network = { version = "0.10.0-dev", path = "../" } log = "0.4.8" -parking_lot = "0.11.1" +parking_lot = "0.11.2" futures = "0.3.9" futures-timer = "3.0.1" rand = "0.7.2" diff --git a/client/offchain/Cargo.toml b/client/offchain/Cargo.toml index 5ed182d6cfc4..4271c7f5d2b2 100644 --- a/client/offchain/Cargo.toml +++ b/client/offchain/Cargo.toml @@ -20,7 +20,7 @@ fnv = "1.0.6" futures = "0.3.16" futures-timer = "3.0.2" num_cpus = "1.10" -parking_lot = "0.11.1" +parking_lot = "0.11.2" rand = "0.7.2" sc-client-api = { version = "4.0.0-dev", path = "../api" } sc-network = { version = "0.10.0-dev", path = "../network" } diff --git a/client/rpc-api/Cargo.toml b/client/rpc-api/Cargo.toml index 18f499c51448..2e75dd460bd3 100644 --- a/client/rpc-api/Cargo.toml +++ b/client/rpc-api/Cargo.toml @@ -20,7 +20,7 @@ jsonrpc-core-client = "18.0.0" jsonrpc-derive = "18.0.0" jsonrpc-pubsub = "18.0.0" log = "0.4.8" -parking_lot = "0.11.1" +parking_lot = "0.11.2" thiserror = "1.0" sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } diff --git a/client/rpc/Cargo.toml b/client/rpc/Cargo.toml index 707fbf75f7c6..b8829dca870b 100644 --- a/client/rpc/Cargo.toml +++ b/client/rpc/Cargo.toml @@ -35,7 +35,7 @@ sc-block-builder = { version = "0.10.0-dev", path = "../block-builder" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sc-tracing = { version = "4.0.0-dev", path = "../tracing" } hash-db = { version = "0.15.2", default-features = false } -parking_lot = "0.11.1" +parking_lot = "0.11.2" lazy_static = { version = "1.4.0", optional = true } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../transaction-pool/api" } diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index 6d96cafec201..e81125fc9154 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -27,7 +27,7 @@ futures = "0.3.16" jsonrpc-pubsub = "18.0" jsonrpc-core = "18.0" rand = "0.7.3" -parking_lot = "0.11.1" +parking_lot = "0.11.2" log = "0.4.11" futures-timer = "3.0.1" exit-future = "0.2.0" diff --git a/client/service/test/Cargo.toml b/client/service/test/Cargo.toml index 113ed0d0802b..a8088ebb08cb 100644 --- a/client/service/test/Cargo.toml +++ b/client/service/test/Cargo.toml @@ -18,7 +18,7 @@ tempfile = "3.1.0" tokio = { version = "1.13.0", features = ["time"] } log = "0.4.8" fdlimit = "0.2.1" -parking_lot = "0.11.1" +parking_lot = "0.11.2" sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-state-machine = { version = "0.10.0", path = "../../../primitives/state-machine" } diff --git a/client/state-db/Cargo.toml b/client/state-db/Cargo.toml index 6a5b8516237d..fbde840fbb8e 100644 --- a/client/state-db/Cargo.toml +++ b/client/state-db/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -parking_lot = "0.11.1" +parking_lot = "0.11.2" log = "0.4.11" sc-client-api = { version = "4.0.0-dev", path = "../api" } sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } diff --git a/client/telemetry/Cargo.toml b/client/telemetry/Cargo.toml index 73efdbc039c5..af7b1d0a0669 100644 --- a/client/telemetry/Cargo.toml +++ b/client/telemetry/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] -parking_lot = "0.11.1" +parking_lot = "0.11.2" futures = "0.3.9" wasm-timer = "0.2.5" libp2p = { version = "0.40.0", default-features = false, features = ["dns-async-std", "tcp-async-io", "wasm-ext", "websocket"] } diff --git a/client/tracing/Cargo.toml b/client/tracing/Cargo.toml index 137cab554613..c4fdcde3f067 100644 --- a/client/tracing/Cargo.toml +++ b/client/tracing/Cargo.toml @@ -20,7 +20,7 @@ lazy_static = "1.4.0" libc = "0.2.105" log = { version = "0.4.8" } once_cell = "1.8.0" -parking_lot = "0.11.1" +parking_lot = "0.11.2" regex = "1.5.4" rustc-hash = "1.1.0" serde = "1.0.126" diff --git a/client/transaction-pool/Cargo.toml b/client/transaction-pool/Cargo.toml index 9aaaaa36a2cb..6439a1854352 100644 --- a/client/transaction-pool/Cargo.toml +++ b/client/transaction-pool/Cargo.toml @@ -19,7 +19,7 @@ futures = "0.3.16" intervalier = "0.4.0" log = "0.4.8" parity-util-mem = { version = "0.10.2", default-features = false, features = ["primitive-types"] } -parking_lot = "0.11.1" +parking_lot = "0.11.2" prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.10.0-dev"} sc-client-api = { version = "4.0.0-dev", path = "../api" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } diff --git a/frame/election-provider-multi-phase/Cargo.toml b/frame/election-provider-multi-phase/Cargo.toml index 72ec62f321cf..75a1ed083829 100644 --- a/frame/election-provider-multi-phase/Cargo.toml +++ b/frame/election-provider-multi-phase/Cargo.toml @@ -41,7 +41,7 @@ strum = { optional = true, version = "0.22.0" } strum_macros = { optional = true, version = "0.22.0" } [dev-dependencies] -parking_lot = "0.11.0" +parking_lot = "0.11.2" rand = { version = "0.7.3" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } diff --git a/primitives/blockchain/Cargo.toml b/primitives/blockchain/Cargo.toml index 6eeacf5f2697..57732c360bac 100644 --- a/primitives/blockchain/Cargo.toml +++ b/primitives/blockchain/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] log = "0.4.11" lru = "0.7.0" -parking_lot = "0.11.1" +parking_lot = "0.11.2" thiserror = "1.0.30" futures = "0.3.9" codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index 330dd57e817f..2922c8b940ea 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -38,7 +38,7 @@ num-traits = { version = "0.2.8", default-features = false } zeroize = { version = "1.4.2", default-features = false } secrecy = { version = "0.8.0", default-features = false } lazy_static = { version = "1.4.0", default-features = false, optional = true } -parking_lot = { version = "0.11.1", optional = true } +parking_lot = { version = "0.11.2", optional = true } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-debug-derive = { version = "4.0.0", default-features = false, path = "../debug-derive" } sp-storage = { version = "4.0.0", default-features = false, path = "../storage" } diff --git a/primitives/database/Cargo.toml b/primitives/database/Cargo.toml index 94e16f3cfb3d..6c3eea9aa1f9 100644 --- a/primitives/database/Cargo.toml +++ b/primitives/database/Cargo.toml @@ -11,6 +11,6 @@ documentation = "https://docs.rs/sp-database" readme = "README.md" [dependencies] -parking_lot = "0.11.1" +parking_lot = "0.11.2" kvdb = "0.10.0" diff --git a/primitives/io/Cargo.toml b/primitives/io/Cargo.toml index 9f95eb40a4e7..ee3c9e8945eb 100644 --- a/primitives/io/Cargo.toml +++ b/primitives/io/Cargo.toml @@ -29,7 +29,7 @@ sp-externalities = { version = "0.10.0", optional = true, path = "../externaliti sp-tracing = { version = "4.0.0", default-features = false, path = "../tracing" } log = { version = "0.4.8", optional = true } futures = { version = "0.3.1", features = ["thread-pool"], optional = true } -parking_lot = { version = "0.11.1", optional = true } +parking_lot = { version = "0.11.2", optional = true } tracing = { version = "0.1.29", default-features = false } tracing-core = { version = "0.1.17", default-features = false} diff --git a/primitives/keystore/Cargo.toml b/primitives/keystore/Cargo.toml index dea78c61242c..e918f5d2c6d7 100644 --- a/primitives/keystore/Cargo.toml +++ b/primitives/keystore/Cargo.toml @@ -19,7 +19,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = futures = { version = "0.3.1" } schnorrkel = { version = "0.9.1", features = ["preaudit_deprecated", "u64_backend"], default-features = false } merlin = { version = "2.0", default-features = false } -parking_lot = { version = "0.11.1", default-features = false } +parking_lot = { version = "0.11.2", default-features = false } serde = { version = "1.0", optional = true} sp-core = { version = "4.1.0-dev", path = "../core" } sp-externalities = { version = "0.10.0", path = "../externalities", default-features = false } diff --git a/primitives/state-machine/Cargo.toml b/primitives/state-machine/Cargo.toml index 7ca76ed58313..2c84b9186d0a 100644 --- a/primitives/state-machine/Cargo.toml +++ b/primitives/state-machine/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] log = { version = "0.4.11", optional = true } thiserror = { version = "1.0.30", optional = true } -parking_lot = { version = "0.11.1", optional = true } +parking_lot = { version = "0.11.2", optional = true } hash-db = { version = "0.15.2", default-features = false } trie-db = { version = "0.22.6", default-features = false } trie-root = { version = "0.16.0", default-features = false } diff --git a/test-utils/runtime/transaction-pool/Cargo.toml b/test-utils/runtime/transaction-pool/Cargo.toml index c1794d288eca..a0d04bd70271 100644 --- a/test-utils/runtime/transaction-pool/Cargo.toml +++ b/test-utils/runtime/transaction-pool/Cargo.toml @@ -13,7 +13,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] substrate-test-runtime-client = { version = "2.0.0", path = "../client" } -parking_lot = "0.11.1" +parking_lot = "0.11.2" codec = { package = "parity-scale-codec", version = "2.0.0" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } From 1306573829700eb5912e342e4372a3735a0b0679 Mon Sep 17 00:00:00 2001 From: Guillaume Thiolliere Date: Thu, 16 Dec 2021 04:28:18 +0900 Subject: [PATCH 299/695] Deny warning when building doc (#10387) * deny warning * add new job * fix doc * fmt --- .gitlab-ci.yml | 13 ++++++++++++- primitives/beefy/src/commitment.rs | 6 +++--- utils/frame/remote-externalities/src/lib.rs | 8 ++++---- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3f830c7e8e24..589adeec5260 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -650,6 +650,18 @@ build-macos-subkey: tags: - osx +check-rustdoc: + stage: test + <<: *docker-env + <<: *test-refs + variables: + <<: *default-vars + SKIP_WASM_BUILD: 1 + RUSTDOCFLAGS: "-Dwarnings" + script: + - time cargo +nightly doc --workspace --all-features --verbose --no-deps + - sccache -s + build-rustdoc: stage: build <<: *docker-env @@ -665,7 +677,6 @@ build-rustdoc: paths: - ./crate-docs/ script: - # FIXME: it fails with `RUSTDOCFLAGS="-Dwarnings"` - time cargo +nightly doc --workspace --all-features --verbose - rm -f ./target/doc/.lock - mv ./target/doc ./crate-docs diff --git a/primitives/beefy/src/commitment.rs b/primitives/beefy/src/commitment.rs index 6553f6ffc905..ec1ceeded878 100644 --- a/primitives/beefy/src/commitment.rs +++ b/primitives/beefy/src/commitment.rs @@ -27,9 +27,9 @@ pub type BeefyPayloadId = [u8; 2]; pub mod known_payload_ids { use crate::BeefyPayloadId; - /// A [`Payload`] identifier for Merkle Mountain Range root hash. + /// A [`Payload`](super::Payload) identifier for Merkle Mountain Range root hash. /// - /// Encoded value should contain a [`beefy_primitives::MmrRootHash`] type (i.e. 32-bytes hash). + /// Encoded value should contain a [`crate::MmrRootHash`] type (i.e. 32-bytes hash). pub const MMR_ROOT_ID: BeefyPayloadId = *b"mh"; } @@ -137,7 +137,7 @@ where /// /// Note that SCALE-encoding of the structure is optimized for size efficiency over the wire, /// please take a look at custom [`Encode`] and [`Decode`] implementations and -/// [`CompactSignedCommitment`] struct. +/// `CompactSignedCommitment` struct. #[derive(Clone, Debug, PartialEq, Eq)] pub struct SignedCommitment { /// The commitment signatures are collected for. diff --git a/utils/frame/remote-externalities/src/lib.rs b/utils/frame/remote-externalities/src/lib.rs index e8453ddcd8f6..1b61f0711406 100644 --- a/utils/frame/remote-externalities/src/lib.rs +++ b/utils/frame/remote-externalities/src/lib.rs @@ -738,7 +738,7 @@ impl Builder { self } - /// Just a utility wrapper of [`inject_hashed_prefix`] that injects + /// Just a utility wrapper of [`Self::inject_hashed_prefix`] that injects /// [`DEFAULT_CHILD_STORAGE_KEY_PREFIX`] as a prefix. /// /// If set, this will guarantee that the child-tree data of ALL pallets will be downloaded. @@ -747,9 +747,9 @@ impl Builder { /// /// Otherwise, the only other way to make sure a child-tree is manually included is to inject /// its root (`DEFAULT_CHILD_STORAGE_KEY_PREFIX`, plus some other postfix) into - /// [`inject_hashed_key`]. Unfortunately, there's no federated way of managing child tree roots - /// as of now and each pallet does its own thing. Therefore, it is not possible for this library - /// to automatically include child trees of pallet X, when its top keys are included. + /// [`Self::inject_hashed_key`]. Unfortunately, there's no federated way of managing child tree + /// roots as of now and each pallet does its own thing. Therefore, it is not possible for this + /// library to automatically include child trees of pallet X, when its top keys are included. pub fn inject_default_child_tree_prefix(self) -> Self { self.inject_hashed_prefix(DEFAULT_CHILD_STORAGE_KEY_PREFIX) } From 4db2f22446edc340374a0e16243136b7222b0d0e Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Thu, 16 Dec 2021 04:06:11 +0100 Subject: [PATCH 300/695] Replace parameter_types with ConstU32 &c. (#10402) * remove parameter types and use const type * remove parameter types and use const type * Delete { * Delete count, * refractor for beefy, benchmarking, child bounties, and collective pallets * refractor for pallet contracts * refractor for elections * refractor for more pallets * fix CI issues * fix CI issues * fix CI issues * fix CI issues * remove warning to fix CI issue * remove warning to fix CI issue refractor for pallet preimage * remove warning to fix CI issue refractor for pallet proxy * remove warning to fix CI issue refractor for pallet recovery refractor for pallet randomness-collective-flip * remove warning to fix CI issue refractor for pallet scored-pool refractor for pallet scheduler refractor for pallet session * remove warning to fix CI issue refractor for pallet society, support, system, timestamp, tips * remove warning to fix CI issue refractor for pallet transaction_payment, transaction_storage, treasury, uniques, utility * remove warning to fix CI issue * cargo +nightly fmt * CI fix * more param refractor on beefy-mmr * refractor for beefy * Update frame/babe/src/mock.rs * Update frame/babe/src/mock.rs * Update frame/bounties/src/tests.rs * Update frame/tips/src/tests.rs * Delete mock.rs * Update frame/examples/basic/src/tests.rs * Apply suggestions from code review * Update frame/im-online/src/mock.rs * Update frame/im-online/src/mock.rs * Update frame/offences/benchmarking/src/mock.rs * Update frame/session/benchmarking/src/mock.rs * Update frame/support/test/tests/pallet_compatibility.rs * Update frame/support/test/tests/pallet_compatibility_instance.rs * Update frame/treasury/src/tests.rs * Update test-utils/runtime/src/lib.rs * some cleanup * fmt * remove unused Co-authored-by: Damilare Co-authored-by: Guillaume Thiolliere --- .../pallets/template/src/mock.rs | 11 ++-- bin/node-template/runtime/src/lib.rs | 22 +++----- bin/node/runtime/src/lib.rs | 38 +++++--------- frame/atomic-swap/src/tests.rs | 21 ++++---- frame/aura/src/mock.rs | 14 ++--- frame/authority-discovery/src/lib.rs | 14 ++--- frame/authorship/src/lib.rs | 17 +++--- frame/babe/src/mock.rs | 35 +++---------- frame/balances/src/tests_composite.rs | 19 +++---- frame/balances/src/tests_local.rs | 23 +++----- frame/balances/src/tests_reentrancy.rs | 27 +++++----- frame/beefy-mmr/src/mock.rs | 24 +++------ frame/beefy/src/mock.rs | 21 +++----- frame/benchmarking/src/tests.rs | 8 ++- frame/benchmarking/src/tests_instance.rs | 11 ++-- frame/bounties/src/tests.rs | 46 +++++++--------- frame/child-bounties/src/tests.rs | 52 ++++++++----------- frame/collective/src/tests.rs | 19 ++++--- frame/contracts/src/tests.rs | 16 +++--- frame/democracy/src/tests.rs | 45 ++++++---------- .../election-provider-multi-phase/src/mock.rs | 8 ++- frame/elections-phragmen/src/lib.rs | 17 +++--- frame/examples/basic/src/tests.rs | 16 ++---- frame/examples/offchain-worker/src/tests.rs | 16 +++--- frame/examples/parallel/src/tests.rs | 9 +--- frame/executive/src/lib.rs | 13 ++--- frame/gilt/src/mock.rs | 38 ++++---------- frame/grandpa/src/mock.rs | 35 ++++--------- frame/identity/src/tests.rs | 29 +++++------ frame/im-online/src/mock.rs | 26 ++++------ frame/indices/src/mock.rs | 22 +++----- frame/lottery/src/mock.rs | 21 +++----- frame/membership/src/lib.rs | 11 ++-- frame/merkle-mountain-range/src/mock.rs | 9 ++-- frame/multisig/src/tests.rs | 28 +++++----- frame/nicks/src/lib.rs | 28 +++++----- frame/node-authorization/src/mock.rs | 21 ++++---- frame/offences/benchmarking/src/mock.rs | 23 ++++---- frame/offences/src/mock.rs | 6 +-- frame/preimage/src/mock.rs | 27 ++++------ frame/proxy/src/tests.rs | 37 ++++++------- frame/randomness-collective-flip/src/lib.rs | 7 ++- frame/recovery/src/mock.rs | 10 ++-- frame/scheduler/src/mock.rs | 15 +++--- frame/scored-pool/src/mock.rs | 16 +++--- frame/session/benchmarking/src/mock.rs | 16 +++--- frame/session/src/mock.rs | 14 ++--- frame/session/src/tests.rs | 12 ++--- frame/society/src/mock.rs | 37 ++++++------- frame/staking/src/benchmarking.rs | 4 +- frame/staking/src/mock.rs | 25 ++++----- frame/sudo/src/mock.rs | 7 ++- .../support/src/storage/bounded_btree_map.rs | 30 +++++------ .../support/src/storage/bounded_btree_set.rs | 30 +++++------ frame/support/src/storage/bounded_vec.rs | 36 ++++++------- frame/support/src/storage/mod.rs | 26 ++++------ frame/support/src/storage/weak_bounded_vec.rs | 36 ++++++------- frame/support/test/compile_pass/src/lib.rs | 10 ++-- frame/support/test/tests/instance.rs | 11 ++-- frame/support/test/tests/pallet.rs | 15 +++--- .../test/tests/pallet_compatibility.rs | 15 +++--- .../tests/pallet_compatibility_instance.rs | 23 ++++---- frame/support/test/tests/pallet_instance.rs | 15 ++---- .../tests/pallet_with_name_trait_is_valid.rs | 8 +-- frame/system/benches/bench.rs | 6 +-- frame/system/src/mock.rs | 10 ++-- frame/timestamp/src/lib.rs | 16 +++--- frame/tips/src/tests.rs | 42 ++++++--------- .../asset-tx-payment/src/tests.rs | 36 +++++-------- frame/transaction-payment/src/lib.rs | 13 ++--- frame/transaction-storage/src/mock.rs | 22 ++------ frame/treasury/src/tests.rs | 21 ++++---- frame/uniques/src/mock.rs | 48 ++++++----------- frame/utility/src/tests.rs | 13 ++--- frame/vesting/src/mock.rs | 14 ++--- test-utils/runtime/src/lib.rs | 13 ++--- 76 files changed, 629 insertions(+), 966 deletions(-) diff --git a/bin/node-template/pallets/template/src/mock.rs b/bin/node-template/pallets/template/src/mock.rs index 733ac79d6577..8721fe6c7885 100644 --- a/bin/node-template/pallets/template/src/mock.rs +++ b/bin/node-template/pallets/template/src/mock.rs @@ -1,5 +1,5 @@ use crate as pallet_template; -use frame_support::parameter_types; +use frame_support::traits::{ConstU16, ConstU64}; use frame_system as system; use sp_core::H256; use sp_runtime::{ @@ -22,11 +22,6 @@ frame_support::construct_runtime!( } ); -parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const SS58Prefix: u8 = 42; -} - impl system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); @@ -42,14 +37,14 @@ impl system::Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); type SystemWeightInfo = (); - type SS58Prefix = SS58Prefix; + type SS58Prefix = ConstU16<42>; type OnSetCode = (); type MaxConsumers = frame_support::traits::ConstU32<16>; } diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index 335b36fe2f5c..5c277a1bb794 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -26,7 +26,7 @@ use sp_version::RuntimeVersion; // A few exports that help ease life for downstream crates. pub use frame_support::{ construct_runtime, parameter_types, - traits::{ConstU32, KeyOwnerProofSystem, Randomness, StorageInfo}, + traits::{ConstU128, ConstU32, ConstU8, KeyOwnerProofSystem, Randomness, StorageInfo}, weights::{ constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND}, IdentityFee, Weight, @@ -196,14 +196,10 @@ impl frame_system::Config for Runtime { impl pallet_randomness_collective_flip::Config for Runtime {} -parameter_types! { - pub const MaxAuthorities: u32 = 32; -} - impl pallet_aura::Config for Runtime { type AuthorityId = AuraId; type DisabledValidators = (); - type MaxAuthorities = MaxAuthorities; + type MaxAuthorities = ConstU32<32>; } impl pallet_grandpa::Config for Runtime { @@ -223,7 +219,7 @@ impl pallet_grandpa::Config for Runtime { type HandleEquivocation = (); type WeightInfo = (); - type MaxAuthorities = MaxAuthorities; + type MaxAuthorities = ConstU32<32>; } parameter_types! { @@ -238,13 +234,8 @@ impl pallet_timestamp::Config for Runtime { type WeightInfo = (); } -parameter_types! { - pub const ExistentialDeposit: u128 = 500; - pub const MaxLocks: u32 = 50; -} - impl pallet_balances::Config for Runtime { - type MaxLocks = MaxLocks; + type MaxLocks = ConstU32<50>; type MaxReserves = (); type ReserveIdentifier = [u8; 8]; /// The type for recording an account's balance. @@ -252,20 +243,19 @@ impl pallet_balances::Config for Runtime { /// The ubiquitous event type. type Event = Event; type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; + type ExistentialDeposit = ConstU128<500>; type AccountStore = System; type WeightInfo = pallet_balances::weights::SubstrateWeight; } parameter_types! { pub const TransactionByteFee: Balance = 1; - pub OperationalFeeMultiplier: u8 = 5; } impl pallet_transaction_payment::Config for Runtime { type OnChargeTransaction = CurrencyAdapter; type TransactionByteFee = TransactionByteFee; - type OperationalFeeMultiplier = OperationalFeeMultiplier; + type OperationalFeeMultiplier = ConstU8<5>; type WeightToFee = IdentityFee; type FeeMultiplierUpdate = (); } diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index e61a46abeb72..97de54fc21e8 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -26,8 +26,8 @@ use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::{ construct_runtime, parameter_types, traits::{ - ConstU128, ConstU32, Currency, EnsureOneOf, EqualPrivilegeOnly, Everything, Imbalance, - InstanceFilter, KeyOwnerProofSystem, LockIdentifier, Nothing, OnUnbalanced, + ConstU128, ConstU16, ConstU32, Currency, EnsureOneOf, EqualPrivilegeOnly, Everything, + Imbalance, InstanceFilter, KeyOwnerProofSystem, LockIdentifier, Nothing, OnUnbalanced, U128CurrencyToVote, }, weights::{ @@ -191,7 +191,6 @@ parameter_types! { }) .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) .build_or_panic(); - pub const SS58Prefix: u16 = 42; } const_assert!(NORMAL_DISPATCH_RATIO.deconstruct() >= AVERAGE_ON_INITIALIZE_RATIO.deconstruct()); @@ -218,7 +217,7 @@ impl frame_system::Config for Runtime { type OnNewAccount = (); type OnKilledAccount = (); type SystemWeightInfo = frame_system::weights::SubstrateWeight; - type SS58Prefix = SS58Prefix; + type SS58Prefix = ConstU16<42>; type OnSetCode = (); type MaxConsumers = frame_support::traits::ConstU32<16>; } @@ -237,7 +236,6 @@ parameter_types! { pub const DepositBase: Balance = deposit(1, 88); // Additional storage item size of 32 bytes. pub const DepositFactor: Balance = deposit(0, 32); - pub const MaxSignatories: u16 = 100; } impl pallet_multisig::Config for Runtime { @@ -246,7 +244,7 @@ impl pallet_multisig::Config for Runtime { type Currency = Balances; type DepositBase = DepositBase; type DepositFactor = DepositFactor; - type MaxSignatories = MaxSignatories; + type MaxSignatories = ConstU16<100>; type WeightInfo = pallet_multisig::weights::SubstrateWeight; } @@ -255,10 +253,8 @@ parameter_types! { pub const ProxyDepositBase: Balance = deposit(1, 8); // Additional storage item size of 33 bytes. pub const ProxyDepositFactor: Balance = deposit(0, 33); - pub const MaxProxies: u16 = 32; pub const AnnouncementDepositBase: Balance = deposit(1, 8); pub const AnnouncementDepositFactor: Balance = deposit(0, 66); - pub const MaxPending: u16 = 32; } /// The type used to represent the kinds of proxying allowed. @@ -325,9 +321,9 @@ impl pallet_proxy::Config for Runtime { type ProxyType = ProxyType; type ProxyDepositBase = ProxyDepositBase; type ProxyDepositFactor = ProxyDepositFactor; - type MaxProxies = MaxProxies; + type MaxProxies = ConstU32<32>; type WeightInfo = pallet_proxy::weights::SubstrateWeight; - type MaxPending = MaxPending; + type MaxPending = ConstU32<32>; type CallHasher = BlakeTwo256; type AnnouncementDepositBase = AnnouncementDepositBase; type AnnouncementDepositFactor = AnnouncementDepositFactor; @@ -336,7 +332,6 @@ impl pallet_proxy::Config for Runtime { parameter_types! { pub MaximumSchedulerWeight: Weight = Perbill::from_percent(80) * RuntimeBlockWeights::get().max_block; - pub const MaxScheduledPerBlock: u32 = 50; // Retry a scheduled item every 10 blocks (1 minute) until the preimage exists. pub const NoPreimagePostponement: Option = Some(10); } @@ -348,7 +343,7 @@ impl pallet_scheduler::Config for Runtime { type Call = Call; type MaximumWeight = MaximumSchedulerWeight; type ScheduleOrigin = EnsureRoot; - type MaxScheduledPerBlock = MaxScheduledPerBlock; + type MaxScheduledPerBlock = ConstU32<50>; type WeightInfo = pallet_scheduler::weights::SubstrateWeight; type OriginPrivilegeCmp = EqualPrivilegeOnly; type PreimageProvider = Preimage; @@ -581,7 +576,6 @@ parameter_types! { pub const UnsignedPhase: u32 = EPOCH_DURATION_IN_BLOCKS / 4; // signed config - pub const SignedMaxSubmissions: u32 = 10; pub const SignedRewardBase: Balance = 1 * DOLLARS; pub const SignedDepositBase: Balance = 1 * DOLLARS; pub const SignedDepositByte: Balance = 1 * CENTS; @@ -599,11 +593,6 @@ parameter_types! { *RuntimeBlockLength::get() .max .get(DispatchClass::Normal); - - // BagsList allows a practically unbounded count of nominators to participate in NPoS elections. - // To ensure we respect memory limits when using the BagsList this must be set to a number of - // voters we know can fit into a single vec allocation. - pub const VoterSnapshotPerBlock: u32 = 10_000; } sp_npos_elections::generate_solution_type!( @@ -668,7 +657,7 @@ impl pallet_election_provider_multi_phase::Config for Runtime { type MinerMaxWeight = MinerMaxWeight; type MinerMaxLength = MinerMaxLength; type MinerTxPriority = MultiPhaseUnsignedPriority; - type SignedMaxSubmissions = SignedMaxSubmissions; + type SignedMaxSubmissions = ConstU32<10>; type SignedRewardBase = SignedRewardBase; type SignedDepositBase = SignedDepositBase; type SignedDepositByte = SignedDepositByte; @@ -687,7 +676,10 @@ impl pallet_election_provider_multi_phase::Config for Runtime { type WeightInfo = pallet_election_provider_multi_phase::weights::SubstrateWeight; type ForceOrigin = EnsureRootOrHalfCouncil; type BenchmarkingConfig = ElectionProviderBenchmarkConfig; - type VoterSnapshotPerBlock = VoterSnapshotPerBlock; + // BagsList allows a practically unbounded count of nominators to participate in NPoS elections. + // To ensure we respect memory limits when using the BagsList this must be set to a number of + // voters we know can fit into a single vec allocation. + type VoterSnapshotPerBlock = ConstU32<10_000>; } parameter_types! { @@ -705,11 +697,9 @@ parameter_types! { pub const LaunchPeriod: BlockNumber = 28 * 24 * 60 * MINUTES; pub const VotingPeriod: BlockNumber = 28 * 24 * 60 * MINUTES; pub const FastTrackVotingPeriod: BlockNumber = 3 * 24 * 60 * MINUTES; - pub const InstantAllowed: bool = true; pub const MinimumDeposit: Balance = 100 * DOLLARS; pub const EnactmentPeriod: BlockNumber = 30 * 24 * 60 * MINUTES; pub const CooloffPeriod: BlockNumber = 28 * 24 * 60 * MINUTES; - pub const MaxVotes: u32 = 100; pub const MaxProposals: u32 = 100; } @@ -738,7 +728,7 @@ impl pallet_democracy::Config for Runtime { pallet_collective::EnsureProportionAtLeast<_2, _3, AccountId, TechnicalCollective>; type InstantOrigin = pallet_collective::EnsureProportionAtLeast<_1, _1, AccountId, TechnicalCollective>; - type InstantAllowed = InstantAllowed; + type InstantAllowed = frame_support::traits::ConstBool; type FastTrackVotingPeriod = FastTrackVotingPeriod; // To cancel a proposal which has been passed, 2/3 of the council must agree to it. type CancellationOrigin = @@ -759,7 +749,7 @@ impl pallet_democracy::Config for Runtime { type Slash = Treasury; type Scheduler = Scheduler; type PalletsOrigin = OriginCaller; - type MaxVotes = MaxVotes; + type MaxVotes = frame_support::traits::ConstU32<100>; type WeightInfo = pallet_democracy::weights::SubstrateWeight; type MaxProposals = MaxProposals; } diff --git a/frame/atomic-swap/src/tests.rs b/frame/atomic-swap/src/tests.rs index 47e33252e094..2352e7852d09 100644 --- a/frame/atomic-swap/src/tests.rs +++ b/frame/atomic-swap/src/tests.rs @@ -3,7 +3,10 @@ use super::*; use crate as pallet_atomic_swap; -use frame_support::parameter_types; +use frame_support::{ + parameter_types, + traits::{ConstU32, ConstU64}, +}; use sp_core::H256; use sp_runtime::{ testing::Header, @@ -26,7 +29,6 @@ frame_support::construct_runtime!( ); parameter_types! { - pub const BlockHashCount: u64 = 250; pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max(1024); } @@ -45,7 +47,7 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; @@ -56,9 +58,7 @@ impl frame_system::Config for Test { type OnSetCode = (); type MaxConsumers = frame_support::traits::ConstU32<16>; } -parameter_types! { - pub const ExistentialDeposit: u64 = 1; -} + impl pallet_balances::Config for Test { type MaxLocks = (); type MaxReserves = (); @@ -66,18 +66,15 @@ impl pallet_balances::Config for Test { type Balance = u64; type DustRemoval = (); type Event = Event; - type ExistentialDeposit = ExistentialDeposit; + type ExistentialDeposit = ConstU64<1>; type AccountStore = System; type WeightInfo = (); } -parameter_types! { - pub const ProofLimit: u32 = 1024; - pub const ExpireDuration: u64 = 100; -} + impl Config for Test { type Event = Event; type SwapAction = BalanceSwapAction; - type ProofLimit = ProofLimit; + type ProofLimit = ConstU32<1024>; } const A: u64 = 1; diff --git a/frame/aura/src/mock.rs b/frame/aura/src/mock.rs index 12748bd212d3..b9df2cfa0e4d 100644 --- a/frame/aura/src/mock.rs +++ b/frame/aura/src/mock.rs @@ -22,7 +22,7 @@ use crate as pallet_aura; use frame_support::{ parameter_types, - traits::{DisabledValidators, GenesisBuild}, + traits::{ConstU32, ConstU64, DisabledValidators, GenesisBuild}, }; use sp_consensus_aura::{ed25519::AuthorityId, AuthorityIndex}; use sp_core::H256; @@ -48,10 +48,8 @@ frame_support::construct_runtime!( ); parameter_types! { - pub const BlockHashCount: u64 = 250; pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max(1024); - pub const MinimumPeriod: u64 = 1; } impl frame_system::Config for Test { @@ -69,7 +67,7 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = (); @@ -84,14 +82,10 @@ impl frame_system::Config for Test { impl pallet_timestamp::Config for Test { type Moment = u64; type OnTimestampSet = Aura; - type MinimumPeriod = MinimumPeriod; + type MinimumPeriod = ConstU64<1>; type WeightInfo = (); } -parameter_types! { - pub const MaxAuthorities: u32 = 10; -} - thread_local! { static DISABLED_VALIDATORS: RefCell> = RefCell::new(Default::default()); } @@ -118,7 +112,7 @@ impl DisabledValidators for MockDisabledValidators { impl pallet_aura::Config for Test { type AuthorityId = AuthorityId; type DisabledValidators = MockDisabledValidators; - type MaxAuthorities = MaxAuthorities; + type MaxAuthorities = ConstU32<10>; } pub fn new_test_ext(authorities: Vec) -> sp_io::TestExternalities { diff --git a/frame/authority-discovery/src/lib.rs b/frame/authority-discovery/src/lib.rs index c867f98af3e1..5f905e92569f 100644 --- a/frame/authority-discovery/src/lib.rs +++ b/frame/authority-discovery/src/lib.rs @@ -173,7 +173,10 @@ impl OneSessionHandler for Pallet { mod tests { use super::*; use crate as pallet_authority_discovery; - use frame_support::{parameter_types, traits::GenesisBuild}; + use frame_support::{ + parameter_types, + traits::{ConstU32, ConstU64, GenesisBuild}, + }; use sp_application_crypto::Pair; use sp_authority_discovery::AuthorityPair; use sp_core::{crypto::key_types, H256}; @@ -201,11 +204,10 @@ mod tests { parameter_types! { pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(33); - pub const MaxAuthorities: u32 = 100; } impl Config for Test { - type MaxAuthorities = MaxAuthorities; + type MaxAuthorities = ConstU32<100>; } impl pallet_session::Config for Test { @@ -230,8 +232,6 @@ mod tests { parameter_types! { pub const Period: BlockNumber = 1; pub const Offset: BlockNumber = 0; - pub const UncleGenerations: u64 = 0; - pub const BlockHashCount: u64 = 250; pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max(1024); } @@ -251,7 +251,7 @@ mod tests { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = (); @@ -260,7 +260,7 @@ mod tests { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type MaxConsumers = ConstU32<16>; } pub struct TestSessionHandler; diff --git a/frame/authorship/src/lib.rs b/frame/authorship/src/lib.rs index 98dd8f1ce6df..297f74ce8b48 100644 --- a/frame/authorship/src/lib.rs +++ b/frame/authorship/src/lib.rs @@ -405,7 +405,11 @@ impl Pallet { mod tests { use super::*; use crate as pallet_authorship; - use frame_support::{parameter_types, ConsensusEngineId}; + use frame_support::{ + parameter_types, + traits::{ConstU32, ConstU64}, + ConsensusEngineId, + }; use sp_core::H256; use sp_runtime::{ generic::DigestItem, @@ -428,7 +432,6 @@ mod tests { ); parameter_types! { - pub const BlockHashCount: u64 = 250; pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max(1024); } @@ -448,7 +451,7 @@ mod tests { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = (); @@ -457,16 +460,12 @@ mod tests { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; - } - - parameter_types! { - pub const UncleGenerations: u64 = 5; + type MaxConsumers = ConstU32<16>; } impl pallet::Config for Test { type FindAuthor = AuthorGiven; - type UncleGenerations = UncleGenerations; + type UncleGenerations = ConstU64<5>; type FilterUncle = SealVerify; type EventHandler = (); } diff --git a/frame/babe/src/mock.rs b/frame/babe/src/mock.rs index f3325d0c65a0..90051770b80f 100644 --- a/frame/babe/src/mock.rs +++ b/frame/babe/src/mock.rs @@ -22,7 +22,7 @@ use codec::Encode; use frame_election_provider_support::onchain; use frame_support::{ parameter_types, - traits::{GenesisBuild, KeyOwnerProofSystem, OnInitialize}, + traits::{ConstU128, ConstU32, ConstU64, GenesisBuild, KeyOwnerProofSystem, OnInitialize}, }; use frame_system::InitKind; use pallet_session::historical as pallet_session_historical; @@ -67,7 +67,6 @@ frame_support::construct_runtime!( ); parameter_types! { - pub const BlockHashCount: u64 = 250; pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max(1024); } @@ -88,7 +87,7 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; type OnNewAccount = (); @@ -130,32 +129,20 @@ impl pallet_session::historical::Config for Test { type FullIdentificationOf = pallet_staking::ExposureOf; } -parameter_types! { - pub const UncleGenerations: u64 = 0; -} - impl pallet_authorship::Config for Test { type FindAuthor = pallet_session::FindAccountFromAuthorIndex; - type UncleGenerations = UncleGenerations; + type UncleGenerations = ConstU64<0>; type FilterUncle = (); type EventHandler = (); } -parameter_types! { - pub const MinimumPeriod: u64 = 1; -} - impl pallet_timestamp::Config for Test { type Moment = u64; type OnTimestampSet = Babe; - type MinimumPeriod = MinimumPeriod; + type MinimumPeriod = ConstU64<1>; type WeightInfo = (); } -parameter_types! { - pub const ExistentialDeposit: u128 = 1; -} - impl pallet_balances::Config for Test { type MaxLocks = (); type MaxReserves = (); @@ -163,7 +150,7 @@ impl pallet_balances::Config for Test { type Balance = u128; type DustRemoval = (); type Event = Event; - type ExistentialDeposit = ExistentialDeposit; + type ExistentialDeposit = ConstU128<1>; type AccountStore = System; type WeightInfo = (); } @@ -183,11 +170,7 @@ parameter_types! { pub const SessionsPerEra: SessionIndex = 3; pub const BondingDuration: EraIndex = 3; pub const SlashDeferDuration: EraIndex = 0; - pub const AttestationPeriod: u64 = 100; pub const RewardCurve: &'static PiecewiseLinear<'static> = &REWARD_CURVE; - pub const MaxNominatorRewardedPerValidator: u32 = 64; - pub const ElectionLookahead: u64 = 0; - pub const StakingUnsignedPriority: u64 = u64::MAX / 2; pub const OffendingValidatorsThreshold: Perbill = Perbill::from_percent(16); } @@ -211,7 +194,7 @@ impl pallet_staking::Config for Test { type SessionInterface = Self; type UnixTime = pallet_timestamp::Pallet; type EraPayout = pallet_staking::ConvertCurve; - type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator; + type MaxNominatorRewardedPerValidator = ConstU32<64>; type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type NextNewSession = Session; type ElectionProvider = onchain::OnChainSequentialPhragmen; @@ -229,15 +212,13 @@ impl pallet_offences::Config for Test { parameter_types! { pub const EpochDuration: u64 = 3; - pub const ExpectedBlockTime: u64 = 1; pub const ReportLongevity: u64 = BondingDuration::get() as u64 * SessionsPerEra::get() as u64 * EpochDuration::get(); - pub const MaxAuthorities: u32 = 10; } impl Config for Test { type EpochDuration = EpochDuration; - type ExpectedBlockTime = ExpectedBlockTime; + type ExpectedBlockTime = ConstU64<1>; type EpochChangeTrigger = crate::ExternalTrigger; type DisabledValidators = Session; @@ -255,7 +236,7 @@ impl Config for Test { super::EquivocationHandler; type WeightInfo = (); - type MaxAuthorities = MaxAuthorities; + type MaxAuthorities = ConstU32<10>; } pub fn go_to_block(n: u64, s: u64) { diff --git a/frame/balances/src/tests_composite.rs b/frame/balances/src/tests_composite.rs index b1a7f2417df8..15648d7356be 100644 --- a/frame/balances/src/tests_composite.rs +++ b/frame/balances/src/tests_composite.rs @@ -22,6 +22,7 @@ use crate::{self as pallet_balances, decl_tests, Config, Pallet}; use frame_support::{ parameter_types, + traits::{ConstU32, ConstU64, ConstU8}, weights::{DispatchInfo, IdentityFee, Weight}, }; use pallet_transaction_payment::CurrencyAdapter; @@ -44,7 +45,6 @@ frame_support::construct_runtime!( ); parameter_types! { - pub const BlockHashCount: u64 = 250; pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max(1024); pub static ExistentialDeposit: u64 = 0; @@ -64,7 +64,7 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = super::AccountData; @@ -75,22 +75,15 @@ impl frame_system::Config for Test { type OnSetCode = (); type MaxConsumers = frame_support::traits::ConstU32<16>; } -parameter_types! { - pub const TransactionByteFee: u64 = 1; - pub const OperationalFeeMultiplier: u8 = 5; -} + impl pallet_transaction_payment::Config for Test { type OnChargeTransaction = CurrencyAdapter, ()>; - type TransactionByteFee = TransactionByteFee; - type OperationalFeeMultiplier = OperationalFeeMultiplier; + type TransactionByteFee = ConstU64<1>; + type OperationalFeeMultiplier = ConstU8<5>; type WeightToFee = IdentityFee; type FeeMultiplierUpdate = (); } -parameter_types! { - pub const MaxReserves: u32 = 2; -} - impl Config for Test { type Balance = u64; type DustRemoval = (); @@ -98,7 +91,7 @@ impl Config for Test { type ExistentialDeposit = ExistentialDeposit; type AccountStore = frame_system::Pallet; type MaxLocks = (); - type MaxReserves = MaxReserves; + type MaxReserves = ConstU32<2>; type ReserveIdentifier = [u8; 8]; type WeightInfo = (); } diff --git a/frame/balances/src/tests_local.rs b/frame/balances/src/tests_local.rs index ff08e6356201..4ceaff26c4d0 100644 --- a/frame/balances/src/tests_local.rs +++ b/frame/balances/src/tests_local.rs @@ -22,7 +22,7 @@ use crate::{self as pallet_balances, decl_tests, Config, Pallet}; use frame_support::{ parameter_types, - traits::StorageMapShim, + traits::{ConstU32, ConstU64, ConstU8, StorageMapShim}, weights::{DispatchInfo, IdentityFee, Weight}, }; use pallet_transaction_payment::CurrencyAdapter; @@ -46,7 +46,6 @@ frame_support::construct_runtime!( ); parameter_types! { - pub const BlockHashCount: u64 = 250; pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max(1024); pub static ExistentialDeposit: u64 = 0; @@ -66,7 +65,7 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = (); @@ -77,21 +76,15 @@ impl frame_system::Config for Test { type OnSetCode = (); type MaxConsumers = frame_support::traits::ConstU32<16>; } -parameter_types! { - pub const TransactionByteFee: u64 = 1; - pub const OperationalFeeMultiplier: u8 = 5; -} + impl pallet_transaction_payment::Config for Test { type OnChargeTransaction = CurrencyAdapter, ()>; - type TransactionByteFee = TransactionByteFee; - type OperationalFeeMultiplier = OperationalFeeMultiplier; + type TransactionByteFee = ConstU64<1>; + type OperationalFeeMultiplier = ConstU8<5>; type WeightToFee = IdentityFee; type FeeMultiplierUpdate = (); } -parameter_types! { - pub const MaxLocks: u32 = 50; - pub const MaxReserves: u32 = 2; -} + impl Config for Test { type Balance = u64; type DustRemoval = (); @@ -99,8 +92,8 @@ impl Config for Test { type ExistentialDeposit = ExistentialDeposit; type AccountStore = StorageMapShim, system::Provider, u64, super::AccountData>; - type MaxLocks = MaxLocks; - type MaxReserves = MaxReserves; + type MaxLocks = ConstU32<50>; + type MaxReserves = ConstU32<2>; type ReserveIdentifier = [u8; 8]; type WeightInfo = (); } diff --git a/frame/balances/src/tests_reentrancy.rs b/frame/balances/src/tests_reentrancy.rs index 01b02943484b..8067e5974caa 100644 --- a/frame/balances/src/tests_reentrancy.rs +++ b/frame/balances/src/tests_reentrancy.rs @@ -20,7 +20,11 @@ #![cfg(test)] use crate::{self as pallet_balances, Config, Pallet}; -use frame_support::{parameter_types, traits::StorageMapShim, weights::IdentityFee}; +use frame_support::{ + parameter_types, + traits::{ConstU32, ConstU64, ConstU8, StorageMapShim}, + weights::IdentityFee, +}; use pallet_transaction_payment::CurrencyAdapter; use sp_core::H256; use sp_io; @@ -48,7 +52,6 @@ frame_support::construct_runtime!( ); parameter_types! { - pub const BlockHashCount: u64 = 250; pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max(1024); pub static ExistentialDeposit: u64 = 0; @@ -68,7 +71,7 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = (); @@ -79,14 +82,11 @@ impl frame_system::Config for Test { type OnSetCode = (); type MaxConsumers = frame_support::traits::ConstU32<16>; } -parameter_types! { - pub const TransactionByteFee: u64 = 1; - pub const OperationalFeeMultiplier: u8 = 5; -} + impl pallet_transaction_payment::Config for Test { type OnChargeTransaction = CurrencyAdapter, ()>; - type TransactionByteFee = TransactionByteFee; - type OperationalFeeMultiplier = OperationalFeeMultiplier; + type TransactionByteFee = ConstU64<1>; + type OperationalFeeMultiplier = ConstU8<5>; type WeightToFee = IdentityFee; type FeeMultiplierUpdate = (); } @@ -97,10 +97,7 @@ impl OnUnbalanced> for OnDustRemoval { assert_ok!(Balances::resolve_into_existing(&1, amount)); } } -parameter_types! { - pub const MaxLocks: u32 = 50; - pub const MaxReserves: u32 = 2; -} + impl Config for Test { type Balance = u64; type DustRemoval = OnDustRemoval; @@ -108,8 +105,8 @@ impl Config for Test { type ExistentialDeposit = ExistentialDeposit; type AccountStore = StorageMapShim, system::Provider, u64, super::AccountData>; - type MaxLocks = MaxLocks; - type MaxReserves = MaxReserves; + type MaxLocks = ConstU32<50>; + type MaxReserves = ConstU32<2>; type ReserveIdentifier = [u8; 8]; type WeightInfo = (); } diff --git a/frame/beefy-mmr/src/mock.rs b/frame/beefy-mmr/src/mock.rs index f1195dcc9c02..d66385f8807b 100644 --- a/frame/beefy-mmr/src/mock.rs +++ b/frame/beefy-mmr/src/mock.rs @@ -19,7 +19,9 @@ use std::vec; use beefy_primitives::mmr::MmrLeafVersion; use frame_support::{ - construct_runtime, parameter_types, sp_io::TestExternalities, traits::GenesisBuild, + construct_runtime, parameter_types, + sp_io::TestExternalities, + traits::{ConstU16, ConstU32, ConstU64, GenesisBuild}, BasicExternalities, }; use sp_core::{Hasher, H256}; @@ -57,11 +59,6 @@ construct_runtime!( } ); -parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const SS58Prefix: u8 = 42; -} - impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); @@ -77,29 +74,24 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); type SystemWeightInfo = (); - type SS58Prefix = SS58Prefix; + type SS58Prefix = ConstU16<42>; type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; -} - -parameter_types! { - pub const Period: u64 = 1; - pub const Offset: u64 = 0; + type MaxConsumers = ConstU32<16>; } impl pallet_session::Config for Test { type Event = Event; type ValidatorId = u64; type ValidatorIdOf = ConvertInto; - type ShouldEndSession = pallet_session::PeriodicSessions; - type NextSessionRotation = pallet_session::PeriodicSessions; + type ShouldEndSession = pallet_session::PeriodicSessions, ConstU64<0>>; + type NextSessionRotation = pallet_session::PeriodicSessions, ConstU64<0>>; type SessionManager = MockSessionManager; type SessionHandler = ::KeyTypeIdProviders; type Keys = MockSessionKeys; diff --git a/frame/beefy/src/mock.rs b/frame/beefy/src/mock.rs index 3ce582b29d22..22330b29b670 100644 --- a/frame/beefy/src/mock.rs +++ b/frame/beefy/src/mock.rs @@ -18,7 +18,9 @@ use std::vec; use frame_support::{ - construct_runtime, parameter_types, sp_io::TestExternalities, traits::GenesisBuild, + construct_runtime, parameter_types, + sp_io::TestExternalities, + traits::{ConstU16, ConstU32, ConstU64, GenesisBuild}, BasicExternalities, }; use sp_core::H256; @@ -55,11 +57,6 @@ construct_runtime!( } ); -parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const SS58Prefix: u8 = 42; -} - impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); @@ -75,16 +72,16 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); type SystemWeightInfo = (); - type SS58Prefix = SS58Prefix; + type SS58Prefix = ConstU16<42>; type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type MaxConsumers = ConstU32<16>; } impl pallet_beefy::Config for Test { @@ -92,8 +89,6 @@ impl pallet_beefy::Config for Test { } parameter_types! { - pub const Period: u64 = 1; - pub const Offset: u64 = 0; pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(33); } @@ -101,8 +96,8 @@ impl pallet_session::Config for Test { type Event = Event; type ValidatorId = u64; type ValidatorIdOf = ConvertInto; - type ShouldEndSession = pallet_session::PeriodicSessions; - type NextSessionRotation = pallet_session::PeriodicSessions; + type ShouldEndSession = pallet_session::PeriodicSessions, ConstU64<0>>; + type NextSessionRotation = pallet_session::PeriodicSessions, ConstU64<0>>; type SessionManager = MockSessionManager; type SessionHandler = ::KeyTypeIdProviders; type Keys = MockSessionKeys; diff --git a/frame/benchmarking/src/tests.rs b/frame/benchmarking/src/tests.rs index e27b3e09dbed..eded93c696bd 100644 --- a/frame/benchmarking/src/tests.rs +++ b/frame/benchmarking/src/tests.rs @@ -20,7 +20,7 @@ #![cfg(test)] use super::*; -use frame_support::parameter_types; +use frame_support::{parameter_types, traits::ConstU32}; use sp_runtime::{ testing::{Header, H256}, traits::{BlakeTwo256, IdentityLookup}, @@ -112,14 +112,12 @@ impl frame_system::Config for Test { } parameter_types! { - pub const LowerBound: u32 = 1; - pub const UpperBound: u32 = 100; pub const MaybeItem: Option = None; } impl pallet_test::Config for Test { - type LowerBound = LowerBound; - type UpperBound = UpperBound; + type LowerBound = ConstU32<1>; + type UpperBound = ConstU32<100>; type MaybeItem = MaybeItem; } diff --git a/frame/benchmarking/src/tests_instance.rs b/frame/benchmarking/src/tests_instance.rs index 09d11eb6c58d..2ac01a052820 100644 --- a/frame/benchmarking/src/tests_instance.rs +++ b/frame/benchmarking/src/tests_instance.rs @@ -20,7 +20,7 @@ #![cfg(test)] use super::*; -use frame_support::parameter_types; +use frame_support::traits::ConstU32; use sp_runtime::{ testing::{Header, H256}, traits::{BlakeTwo256, IdentityLookup}, @@ -113,15 +113,10 @@ impl frame_system::Config for Test { type MaxConsumers = frame_support::traits::ConstU32<16>; } -parameter_types! { - pub const LowerBound: u32 = 1; - pub const UpperBound: u32 = 100; -} - impl pallet_test::Config for Test { type Event = Event; - type LowerBound = LowerBound; - type UpperBound = UpperBound; + type LowerBound = ConstU32<1>; + type UpperBound = ConstU32<100>; } impl pallet_test::OtherConfig for Test { diff --git a/frame/bounties/src/tests.rs b/frame/bounties/src/tests.rs index dc6cecc06f5e..209136dcda1e 100644 --- a/frame/bounties/src/tests.rs +++ b/frame/bounties/src/tests.rs @@ -24,8 +24,11 @@ use crate as pallet_bounties; use std::cell::RefCell; use frame_support::{ - assert_noop, assert_ok, pallet_prelude::GenesisBuild, parameter_types, traits::OnInitialize, - weights::Weight, PalletId, + assert_noop, assert_ok, + pallet_prelude::GenesisBuild, + parameter_types, + traits::{ConstU32, ConstU64, OnInitialize}, + PalletId, }; use sp_core::H256; @@ -54,9 +57,6 @@ frame_support::construct_runtime!( ); parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: Weight = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; pub const AvailableBlockRatio: Perbill = Perbill::one(); } @@ -75,7 +75,7 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; @@ -86,9 +86,7 @@ impl frame_system::Config for Test { type OnSetCode = (); type MaxConsumers = frame_support::traits::ConstU32<16>; } -parameter_types! { - pub const ExistentialDeposit: u64 = 1; -} + impl pallet_balances::Config for Test { type MaxLocks = (); type MaxReserves = (); @@ -96,7 +94,7 @@ impl pallet_balances::Config for Test { type Balance = u64; type Event = Event; type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; + type ExistentialDeposit = ConstU64<1>; type AccountStore = System; type WeightInfo = (); } @@ -105,13 +103,10 @@ thread_local! { } parameter_types! { pub const ProposalBond: Permill = Permill::from_percent(5); - pub const ProposalBondMinimum: u64 = 1; - pub const SpendPeriod: u64 = 2; pub const Burn: Permill = Permill::from_percent(50); - pub const DataDepositPerByte: u64 = 1; pub const TreasuryPalletId: PalletId = PalletId(*b"py/trsry"); - pub const MaxApprovals: u32 = 100; } + // impl pallet_treasury::Config for Test { impl pallet_treasury::Config for Test { type PalletId = TreasuryPalletId; @@ -121,31 +116,26 @@ impl pallet_treasury::Config for Test { type Event = Event; type OnSlash = (); type ProposalBond = ProposalBond; - type ProposalBondMinimum = ProposalBondMinimum; - type SpendPeriod = SpendPeriod; + type ProposalBondMinimum = ConstU64<1>; + type SpendPeriod = ConstU64<2>; type Burn = Burn; type BurnDestination = (); // Just gets burned. type WeightInfo = (); type SpendFunds = Bounties; - type MaxApprovals = MaxApprovals; + type MaxApprovals = ConstU32<100>; } parameter_types! { - pub const BountyDepositBase: u64 = 80; - pub const BountyDepositPayoutDelay: u64 = 3; - pub const BountyUpdatePeriod: u32 = 20; pub const BountyCuratorDeposit: Permill = Permill::from_percent(50); - pub const BountyValueMinimum: u64 = 1; - pub const MaximumReasonLength: u32 = 16384; } impl Config for Test { type Event = Event; - type BountyDepositBase = BountyDepositBase; - type BountyDepositPayoutDelay = BountyDepositPayoutDelay; - type BountyUpdatePeriod = BountyUpdatePeriod; + type BountyDepositBase = ConstU64<80>; + type BountyDepositPayoutDelay = ConstU64<3>; + type BountyUpdatePeriod = ConstU64<20>; type BountyCuratorDeposit = BountyCuratorDeposit; - type BountyValueMinimum = BountyValueMinimum; - type DataDepositPerByte = DataDepositPerByte; - type MaximumReasonLength = MaximumReasonLength; + type BountyValueMinimum = ConstU64<1>; + type DataDepositPerByte = ConstU64<1>; + type MaximumReasonLength = ConstU32<16384>; type WeightInfo = (); type ChildBountyManager = (); } diff --git a/frame/child-bounties/src/tests.rs b/frame/child-bounties/src/tests.rs index 8e2569738b1f..ba68d73ceddc 100644 --- a/frame/child-bounties/src/tests.rs +++ b/frame/child-bounties/src/tests.rs @@ -24,8 +24,12 @@ use crate as pallet_child_bounties; use std::cell::RefCell; use frame_support::{ - assert_noop, assert_ok, pallet_prelude::GenesisBuild, parameter_types, traits::OnInitialize, - weights::Weight, PalletId, + assert_noop, assert_ok, + pallet_prelude::GenesisBuild, + parameter_types, + traits::{ConstU32, ConstU64, OnInitialize}, + weights::Weight, + PalletId, }; use sp_core::H256; @@ -56,7 +60,6 @@ frame_support::construct_runtime!( ); parameter_types! { - pub const BlockHashCount: u64 = 250; pub const MaximumBlockWeight: Weight = 1024; pub const MaximumBlockLength: u32 = 2 * 1024; pub const AvailableBlockRatio: Perbill = Perbill::one(); @@ -77,7 +80,7 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; @@ -86,11 +89,9 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; -} -parameter_types! { - pub const ExistentialDeposit: u64 = 1; + type MaxConsumers = ConstU32<16>; } + impl pallet_balances::Config for Test { type MaxLocks = (); type MaxReserves = (); @@ -98,7 +99,7 @@ impl pallet_balances::Config for Test { type Balance = u64; type Event = Event; type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; + type ExistentialDeposit = ConstU64<1>; type AccountStore = System; type WeightInfo = (); } @@ -107,12 +108,8 @@ thread_local! { } parameter_types! { pub const ProposalBond: Permill = Permill::from_percent(5); - pub const ProposalBondMinimum: u64 = 1; - pub const SpendPeriod: u64 = 2; pub const Burn: Permill = Permill::from_percent(50); - pub const DataDepositPerByte: u64 = 1; pub const TreasuryPalletId: PalletId = PalletId(*b"py/trsry"); - pub const MaxApprovals: u32 = 100; } impl pallet_treasury::Config for Test { @@ -123,43 +120,36 @@ impl pallet_treasury::Config for Test { type Event = Event; type OnSlash = (); type ProposalBond = ProposalBond; - type ProposalBondMinimum = ProposalBondMinimum; - type SpendPeriod = SpendPeriod; + type ProposalBondMinimum = ConstU64<1>; + type SpendPeriod = ConstU64<2>; type Burn = Burn; type BurnDestination = (); type WeightInfo = (); type SpendFunds = Bounties; - type MaxApprovals = MaxApprovals; + type MaxApprovals = ConstU32<100>; } parameter_types! { - pub const BountyDepositBase: u64 = 80; - pub const BountyDepositPayoutDelay: u64 = 3; - pub const BountyUpdatePeriod: u32 = 10; pub const BountyCuratorDeposit: Permill = Permill::from_percent(50); - pub const BountyValueMinimum: u64 = 5; - pub const MaximumReasonLength: u32 = 300; } impl pallet_bounties::Config for Test { type Event = Event; - type BountyDepositBase = BountyDepositBase; - type BountyDepositPayoutDelay = BountyDepositPayoutDelay; - type BountyUpdatePeriod = BountyUpdatePeriod; + type BountyDepositBase = ConstU64<80>; + type BountyDepositPayoutDelay = ConstU64<3>; + type BountyUpdatePeriod = ConstU64<10>; type BountyCuratorDeposit = BountyCuratorDeposit; - type BountyValueMinimum = BountyValueMinimum; - type DataDepositPerByte = DataDepositPerByte; - type MaximumReasonLength = MaximumReasonLength; + type BountyValueMinimum = ConstU64<5>; + type DataDepositPerByte = ConstU64<1>; + type MaximumReasonLength = ConstU32<300>; type WeightInfo = (); type ChildBountyManager = ChildBounties; } parameter_types! { - pub const MaxActiveChildBountyCount: u32 = 2; - pub const ChildBountyValueMinimum: u64 = 1; pub const ChildBountyCuratorDepositBase: Permill = Permill::from_percent(10); } impl pallet_child_bounties::Config for Test { type Event = Event; - type MaxActiveChildBountyCount = MaxActiveChildBountyCount; - type ChildBountyValueMinimum = ChildBountyValueMinimum; + type MaxActiveChildBountyCount = ConstU32<2>; + type ChildBountyValueMinimum = ConstU64<1>; type ChildBountyCuratorDepositBase = ChildBountyCuratorDepositBase; type WeightInfo = (); } diff --git a/frame/collective/src/tests.rs b/frame/collective/src/tests.rs index 466cdb3eeeb5..2af8b1b97036 100644 --- a/frame/collective/src/tests.rs +++ b/frame/collective/src/tests.rs @@ -18,7 +18,10 @@ use super::{Event as CollectiveEvent, *}; use crate as pallet_collective; use frame_support::{ - assert_noop, assert_ok, parameter_types, traits::GenesisBuild, weights::Pays, Hashable, + assert_noop, assert_ok, parameter_types, + traits::{ConstU32, ConstU64, GenesisBuild}, + weights::Pays, + Hashable, }; use frame_system::{EventRecord, Phase}; use sp_core::{ @@ -83,11 +86,11 @@ mod mock_democracy { } } +pub type MaxMembers = ConstU32<100>; + parameter_types! { - pub const BlockHashCount: u64 = 250; pub const MotionDuration: u64 = 3; pub const MaxProposals: u32 = 100; - pub const MaxMembers: u32 = 100; pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max(1024); } @@ -106,7 +109,7 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = (); @@ -115,13 +118,13 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type MaxConsumers = ConstU32<16>; } impl Config for Test { type Origin = Origin; type Proposal = Call; type Event = Event; - type MotionDuration = MotionDuration; + type MotionDuration = ConstU64<3>; type MaxProposals = MaxProposals; type MaxMembers = MaxMembers; type DefaultVote = PrimeDefaultVote; @@ -131,7 +134,7 @@ impl Config for Test { type Origin = Origin; type Proposal = Call; type Event = Event; - type MotionDuration = MotionDuration; + type MotionDuration = ConstU64<3>; type MaxProposals = MaxProposals; type MaxMembers = MaxMembers; type DefaultVote = MoreThanMajorityThenPrimeDefaultVote; @@ -145,7 +148,7 @@ impl Config for Test { type Origin = Origin; type Proposal = Call; type Event = Event; - type MotionDuration = MotionDuration; + type MotionDuration = ConstU64<3>; type MaxProposals = MaxProposals; type MaxMembers = MaxMembers; type DefaultVote = PrimeDefaultVote; diff --git a/frame/contracts/src/tests.rs b/frame/contracts/src/tests.rs index e7745e1e5f7f..584253aeaadf 100644 --- a/frame/contracts/src/tests.rs +++ b/frame/contracts/src/tests.rs @@ -33,7 +33,9 @@ use frame_support::{ dispatch::DispatchErrorWithPostInfo, parameter_types, storage::child, - traits::{BalanceStatus, Contains, Currency, OnInitialize, ReservableCurrency}, + traits::{ + BalanceStatus, ConstU32, ConstU64, Contains, Currency, OnInitialize, ReservableCurrency, + }, weights::{constants::WEIGHT_PER_SECOND, DispatchClass, PostDispatchInfo, Weight}, }; use frame_system::{self as system, EventRecord, Phase}; @@ -177,7 +179,6 @@ impl ChainExtension for TestExtension { } parameter_types! { - pub const BlockHashCount: u64 = 250; pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max(2 * WEIGHT_PER_SECOND); pub static ExistentialDeposit: u64 = 1; @@ -197,7 +198,7 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; @@ -220,13 +221,11 @@ impl pallet_balances::Config for Test { type AccountStore = System; type WeightInfo = (); } -parameter_types! { - pub const MinimumPeriod: u64 = 1; -} + impl pallet_timestamp::Config for Test { type Moment = u64; type OnTimestampSet = (); - type MinimumPeriod = MinimumPeriod; + type MinimumPeriod = ConstU64<1>; type WeightInfo = (); } impl pallet_utility::Config for Test { @@ -237,7 +236,6 @@ impl pallet_utility::Config for Test { } parameter_types! { pub const MaxValueSize: u32 = 16_384; - pub const DeletionQueueDepth: u32 = 1024; pub const DeletionWeightLimit: Weight = 500_000_000_000; pub const MaxCodeSize: u32 = 2 * 1024; pub MySchedule: Schedule = >::default(); @@ -282,7 +280,7 @@ impl Config for Test { type WeightPrice = Self; type WeightInfo = (); type ChainExtension = TestExtension; - type DeletionQueueDepth = DeletionQueueDepth; + type DeletionQueueDepth = ConstU32<1024>; type DeletionWeightLimit = DeletionWeightLimit; type Schedule = MySchedule; type DepositPerByte = DepositPerByte; diff --git a/frame/democracy/src/tests.rs b/frame/democracy/src/tests.rs index 839478a5b8d9..1e36313122f0 100644 --- a/frame/democracy/src/tests.rs +++ b/frame/democracy/src/tests.rs @@ -22,7 +22,9 @@ use crate as pallet_democracy; use codec::Encode; use frame_support::{ assert_noop, assert_ok, ord_parameter_types, parameter_types, - traits::{Contains, EqualPrivilegeOnly, GenesisBuild, OnInitialize, SortedMembers}, + traits::{ + ConstU32, ConstU64, Contains, EqualPrivilegeOnly, GenesisBuild, OnInitialize, SortedMembers, + }, weights::Weight, }; use frame_system::{EnsureRoot, EnsureSignedBy}; @@ -50,8 +52,6 @@ const NAY: Vote = Vote { aye: false, conviction: Conviction::None }; const BIG_AYE: Vote = Vote { aye: true, conviction: Conviction::Locked1x }; const BIG_NAY: Vote = Vote { aye: false, conviction: Conviction::Locked1x }; -const MAX_PROPOSALS: u32 = 100; - type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; type Block = frame_system::mocking::MockBlock; @@ -77,7 +77,6 @@ impl Contains for BaseFilter { } parameter_types! { - pub const BlockHashCount: u64 = 250; pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max(1_000_000); } @@ -96,7 +95,7 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; @@ -123,31 +122,19 @@ impl pallet_scheduler::Config for Test { type PreimageProvider = (); type NoPreimagePostponement = (); } -parameter_types! { - pub const ExistentialDeposit: u64 = 1; - pub const MaxLocks: u32 = 10; -} + impl pallet_balances::Config for Test { type MaxReserves = (); type ReserveIdentifier = [u8; 8]; - type MaxLocks = MaxLocks; + type MaxLocks = ConstU32<10>; type Balance = u64; type Event = Event; type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; + type ExistentialDeposit = ConstU64<1>; type AccountStore = System; type WeightInfo = (); } parameter_types! { - pub const LaunchPeriod: u64 = 2; - pub const VotingPeriod: u64 = 2; - pub const FastTrackVotingPeriod: u64 = 2; - pub const MinimumDeposit: u64 = 1; - pub const EnactmentPeriod: u64 = 2; - pub const VoteLockingPeriod: u64 = 3; - pub const CooloffPeriod: u64 = 2; - pub const MaxVotes: u32 = 100; - pub const MaxProposals: u32 = MAX_PROPOSALS; pub static PreimageByteDeposit: u64 = 0; pub static InstantAllowed: bool = false; } @@ -172,12 +159,12 @@ impl Config for Test { type Proposal = Call; type Event = Event; type Currency = pallet_balances::Pallet; - type EnactmentPeriod = EnactmentPeriod; - type LaunchPeriod = LaunchPeriod; - type VotingPeriod = VotingPeriod; - type VoteLockingPeriod = VoteLockingPeriod; - type FastTrackVotingPeriod = FastTrackVotingPeriod; - type MinimumDeposit = MinimumDeposit; + type EnactmentPeriod = ConstU64<2>; + type LaunchPeriod = ConstU64<2>; + type VotingPeriod = ConstU64<2>; + type VoteLockingPeriod = ConstU64<3>; + type FastTrackVotingPeriod = ConstU64<2>; + type MinimumDeposit = ConstU64<1>; type ExternalOrigin = EnsureSignedBy; type ExternalMajorityOrigin = EnsureSignedBy; type ExternalDefaultOrigin = EnsureSignedBy; @@ -186,17 +173,17 @@ impl Config for Test { type BlacklistOrigin = EnsureRoot; type CancelProposalOrigin = EnsureRoot; type VetoOrigin = EnsureSignedBy; - type CooloffPeriod = CooloffPeriod; + type CooloffPeriod = ConstU64<2>; type PreimageByteDeposit = PreimageByteDeposit; type Slash = (); type InstantOrigin = EnsureSignedBy; type InstantAllowed = InstantAllowed; type Scheduler = Scheduler; - type MaxVotes = MaxVotes; + type MaxVotes = ConstU32<100>; type OperationalPreimageOrigin = EnsureSignedBy; type PalletsOrigin = OriginCaller; type WeightInfo = (); - type MaxProposals = MaxProposals; + type MaxProposals = ConstU32<100>; } pub fn new_test_ext() -> sp_io::TestExternalities { diff --git a/frame/election-provider-multi-phase/src/mock.rs b/frame/election-provider-multi-phase/src/mock.rs index 3ac14b89e795..d686df2a72f6 100644 --- a/frame/election-provider-multi-phase/src/mock.rs +++ b/frame/election-provider-multi-phase/src/mock.rs @@ -21,7 +21,11 @@ use frame_election_provider_support::{ data_provider, onchain, ElectionDataProvider, SequentialPhragmen, }; pub use frame_support::{assert_noop, assert_ok}; -use frame_support::{parameter_types, traits::Hooks, weights::Weight}; +use frame_support::{ + parameter_types, + traits::{ConstU32, Hooks}, + weights::Weight, +}; use multi_phase::unsigned::{IndexAssignmentOf, Voter}; use parking_lot::RwLock; use sp_core::{ @@ -218,7 +222,7 @@ impl frame_system::Config for Runtime { type OnKilledAccount = (); type SystemWeightInfo = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type MaxConsumers = ConstU32<16>; } const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); diff --git a/frame/elections-phragmen/src/lib.rs b/frame/elections-phragmen/src/lib.rs index c0b6fdfce6cd..3a6c657a6f99 100644 --- a/frame/elections-phragmen/src/lib.rs +++ b/frame/elections-phragmen/src/lib.rs @@ -1121,8 +1121,10 @@ mod tests { use super::*; use crate as elections_phragmen; use frame_support::{ - assert_noop, assert_ok, dispatch::DispatchResultWithPostInfo, parameter_types, - traits::OnInitialize, + assert_noop, assert_ok, + dispatch::DispatchResultWithPostInfo, + parameter_types, + traits::{ConstU32, ConstU64, OnInitialize}, }; use frame_system::ensure_signed; use sp_core::H256; @@ -1134,7 +1136,6 @@ mod tests { use substrate_test_utils::assert_eq_uvec; parameter_types! { - pub const BlockHashCount: u64 = 250; pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max(1024); } @@ -1154,7 +1155,7 @@ mod tests { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; @@ -1163,18 +1164,14 @@ mod tests { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; - } - - parameter_types! { - pub const ExistentialDeposit: u64 = 1; + type MaxConsumers = ConstU32<16>; } impl pallet_balances::Config for Test { type Balance = u64; type Event = Event; type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; + type ExistentialDeposit = ConstU64<1>; type AccountStore = frame_system::Pallet; type MaxLocks = (); type MaxReserves = (); diff --git a/frame/examples/basic/src/tests.rs b/frame/examples/basic/src/tests.rs index b97083f27d5e..9f93c9053118 100644 --- a/frame/examples/basic/src/tests.rs +++ b/frame/examples/basic/src/tests.rs @@ -20,7 +20,7 @@ use crate::*; use frame_support::{ assert_ok, parameter_types, - traits::OnInitialize, + traits::{ConstU64, OnInitialize}, weights::{DispatchInfo, GetDispatchInfo}, }; use sp_core::H256; @@ -51,7 +51,6 @@ frame_support::construct_runtime!( ); parameter_types! { - pub const BlockHashCount: u64 = 250; pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max(1024); } @@ -70,7 +69,7 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; @@ -81,9 +80,7 @@ impl frame_system::Config for Test { type OnSetCode = (); type MaxConsumers = frame_support::traits::ConstU32<16>; } -parameter_types! { - pub const ExistentialDeposit: u64 = 1; -} + impl pallet_balances::Config for Test { type MaxLocks = (); type MaxReserves = (); @@ -91,16 +88,13 @@ impl pallet_balances::Config for Test { type Balance = u64; type DustRemoval = (); type Event = Event; - type ExistentialDeposit = ExistentialDeposit; + type ExistentialDeposit = ConstU64<1>; type AccountStore = System; type WeightInfo = (); } -parameter_types! { - pub const MagicNumber: u64 = 1_000_000_000; -} impl Config for Test { - type MagicNumber = MagicNumber; + type MagicNumber = ConstU64<1_000_000_000>; type Event = Event; type WeightInfo = (); } diff --git a/frame/examples/offchain-worker/src/tests.rs b/frame/examples/offchain-worker/src/tests.rs index d83c3c6df9ee..2c3e623e9c84 100644 --- a/frame/examples/offchain-worker/src/tests.rs +++ b/frame/examples/offchain-worker/src/tests.rs @@ -18,7 +18,10 @@ use crate as example_offchain_worker; use crate::*; use codec::Decode; -use frame_support::{assert_ok, parameter_types}; +use frame_support::{ + assert_ok, parameter_types, + traits::{ConstU32, ConstU64}, +}; use sp_core::{ offchain::{testing, OffchainWorkerExt, TransactionPoolExt}, sr25519::Signature, @@ -49,7 +52,6 @@ frame_support::construct_runtime!( ); parameter_types! { - pub const BlockHashCount: u64 = 250; pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max(1024); } @@ -68,7 +70,7 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = (); @@ -77,7 +79,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type MaxConsumers = ConstU32<16>; } type Extrinsic = TestXt; @@ -111,8 +113,6 @@ where } parameter_types! { - pub const GracePeriod: u64 = 5; - pub const UnsignedInterval: u64 = 128; pub const UnsignedPriority: u64 = 1 << 20; } @@ -120,8 +120,8 @@ impl Config for Test { type Event = Event; type AuthorityId = crypto::TestAuthId; type Call = Call; - type GracePeriod = GracePeriod; - type UnsignedInterval = UnsignedInterval; + type GracePeriod = ConstU64<5>; + type UnsignedInterval = ConstU64<128>; type UnsignedPriority = UnsignedPriority; } diff --git a/frame/examples/parallel/src/tests.rs b/frame/examples/parallel/src/tests.rs index 1a841ca68184..82ce95d7a85b 100644 --- a/frame/examples/parallel/src/tests.rs +++ b/frame/examples/parallel/src/tests.rs @@ -40,7 +40,6 @@ frame_support::construct_runtime!( ); parameter_types! { - pub const BlockHashCount: u64 = 250; pub const AvailableBlockRatio: Perbill = Perbill::one(); } @@ -57,7 +56,7 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = frame_support::traits::ConstU64<250>; type DbWeight = (); type BlockWeights = (); type BlockLength = (); @@ -71,12 +70,6 @@ impl frame_system::Config for Test { type MaxConsumers = frame_support::traits::ConstU32<16>; } -parameter_types! { - pub const GracePeriod: u64 = 5; - pub const UnsignedInterval: u64 = 128; - pub const UnsignedPriority: u64 = 1 << 20; -} - impl Config for Test { type Call = Call; } diff --git a/frame/executive/src/lib.rs b/frame/executive/src/lib.rs index 7ff5584879ce..cc013d4c333f 100644 --- a/frame/executive/src/lib.rs +++ b/frame/executive/src/lib.rs @@ -578,7 +578,10 @@ mod tests { use frame_support::{ assert_err, parameter_types, - traits::{Currency, LockIdentifier, LockableCurrency, WithdrawReasons}, + traits::{ + ConstU32, ConstU64, ConstU8, Currency, LockIdentifier, LockableCurrency, + WithdrawReasons, + }, weights::{IdentityFee, RuntimeDbWeight, Weight, WeightToFeePolynomial}, }; use frame_system::{Call as SystemCall, ChainContext, LastRuntimeUpgradeInfo}; @@ -731,7 +734,6 @@ mod tests { ); parameter_types! { - pub const BlockHashCount: u64 = 250; pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::builder() .base_block(10) @@ -758,7 +760,7 @@ mod tests { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = RuntimeVersion; type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; @@ -767,7 +769,7 @@ mod tests { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type MaxConsumers = ConstU32<16>; } type Balance = u64; @@ -788,12 +790,11 @@ mod tests { parameter_types! { pub const TransactionByteFee: Balance = 0; - pub const OperationalFeeMultiplier: u8 = 5; } impl pallet_transaction_payment::Config for Runtime { type OnChargeTransaction = CurrencyAdapter; type TransactionByteFee = TransactionByteFee; - type OperationalFeeMultiplier = OperationalFeeMultiplier; + type OperationalFeeMultiplier = ConstU8<5>; type WeightToFee = IdentityFee; type FeeMultiplierUpdate = (); } diff --git a/frame/gilt/src/mock.rs b/frame/gilt/src/mock.rs index 9ea33a6d6b68..6299f7c32031 100644 --- a/frame/gilt/src/mock.rs +++ b/frame/gilt/src/mock.rs @@ -21,7 +21,7 @@ use crate as pallet_gilt; use frame_support::{ ord_parameter_types, parameter_types, - traits::{Currency, GenesisBuild, OnFinalize, OnInitialize}, + traits::{ConstU16, ConstU32, ConstU64, Currency, GenesisBuild, OnFinalize, OnInitialize}, }; use sp_core::H256; use sp_runtime::{ @@ -45,11 +45,6 @@ frame_support::construct_runtime!( } ); -parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const SS58Prefix: u8 = 42; -} - impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); @@ -64,7 +59,7 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type DbWeight = (); type Version = (); type PalletInfo = PalletInfo; @@ -72,20 +67,16 @@ impl frame_system::Config for Test { type OnNewAccount = (); type OnKilledAccount = (); type SystemWeightInfo = (); - type SS58Prefix = SS58Prefix; + type SS58Prefix = ConstU16<42>; type OnSetCode = (); type MaxConsumers = frame_support::traits::ConstU32<16>; } -parameter_types! { - pub const ExistentialDeposit: u64 = 1; -} - impl pallet_balances::Config for Test { type Balance = u64; type DustRemoval = (); type Event = Event; - type ExistentialDeposit = ExistentialDeposit; + type ExistentialDeposit = frame_support::traits::ConstU64<1>; type AccountStore = System; type WeightInfo = (); type MaxLocks = (); @@ -95,13 +86,6 @@ impl pallet_balances::Config for Test { parameter_types! { pub IgnoredIssuance: u64 = Balances::total_balance(&0); // Account zero is ignored. - pub const QueueCount: u32 = 3; - pub const MaxQueueLen: u32 = 3; - pub const FifoQueueLen: u32 = 1; - pub const Period: u64 = 3; - pub const MinFreeze: u64 = 2; - pub const IntakePeriod: u64 = 2; - pub const MaxIntakeBids: u32 = 2; } ord_parameter_types! { pub const One: u64 = 1; @@ -115,13 +99,13 @@ impl pallet_gilt::Config for Test { type Deficit = (); type Surplus = (); type IgnoredIssuance = IgnoredIssuance; - type QueueCount = QueueCount; - type MaxQueueLen = MaxQueueLen; - type FifoQueueLen = FifoQueueLen; - type Period = Period; - type MinFreeze = MinFreeze; - type IntakePeriod = IntakePeriod; - type MaxIntakeBids = MaxIntakeBids; + type QueueCount = ConstU32<3>; + type MaxQueueLen = ConstU32<3>; + type FifoQueueLen = ConstU32<1>; + type Period = ConstU64<3>; + type MinFreeze = ConstU64<2>; + type IntakePeriod = ConstU64<2>; + type MaxIntakeBids = ConstU32<2>; type WeightInfo = (); } diff --git a/frame/grandpa/src/mock.rs b/frame/grandpa/src/mock.rs index aed13ec3717a..6f7c57cad0b5 100644 --- a/frame/grandpa/src/mock.rs +++ b/frame/grandpa/src/mock.rs @@ -25,7 +25,9 @@ use codec::Encode; use frame_election_provider_support::onchain; use frame_support::{ parameter_types, - traits::{GenesisBuild, KeyOwnerProofSystem, OnFinalize, OnInitialize}, + traits::{ + ConstU128, ConstU32, ConstU64, GenesisBuild, KeyOwnerProofSystem, OnFinalize, OnInitialize, + }, }; use pallet_session::historical as pallet_session_historical; use pallet_staking::EraIndex; @@ -69,7 +71,6 @@ impl_opaque_keys! { } parameter_types! { - pub const BlockHashCount: u64 = 250; pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max(1024); } @@ -89,7 +90,7 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; @@ -119,8 +120,8 @@ impl pallet_session::Config for Test { type Event = Event; type ValidatorId = u64; type ValidatorIdOf = pallet_staking::StashOf; - type ShouldEndSession = pallet_session::PeriodicSessions; - type NextSessionRotation = pallet_session::PeriodicSessions; + type ShouldEndSession = pallet_session::PeriodicSessions, ConstU64<0>>; + type NextSessionRotation = pallet_session::PeriodicSessions, ConstU64<0>>; type SessionManager = pallet_session::historical::NoteHistoricalRoot; type SessionHandler = ::KeyTypeIdProviders; type Keys = TestSessionKeys; @@ -132,21 +133,13 @@ impl pallet_session::historical::Config for Test { type FullIdentificationOf = pallet_staking::ExposureOf; } -parameter_types! { - pub const UncleGenerations: u64 = 0; -} - impl pallet_authorship::Config for Test { type FindAuthor = (); - type UncleGenerations = UncleGenerations; + type UncleGenerations = ConstU64<0>; type FilterUncle = (); type EventHandler = (); } -parameter_types! { - pub const ExistentialDeposit: u128 = 1; -} - impl pallet_balances::Config for Test { type MaxLocks = (); type MaxReserves = (); @@ -154,19 +147,15 @@ impl pallet_balances::Config for Test { type Balance = u128; type DustRemoval = (); type Event = Event; - type ExistentialDeposit = ExistentialDeposit; + type ExistentialDeposit = ConstU128<1>; type AccountStore = System; type WeightInfo = (); } -parameter_types! { - pub const MinimumPeriod: u64 = 3; -} - impl pallet_timestamp::Config for Test { type Moment = u64; type OnTimestampSet = (); - type MinimumPeriod = MinimumPeriod; + type MinimumPeriod = ConstU64<3>; type WeightInfo = (); } @@ -187,7 +176,6 @@ parameter_types! { pub const SlashDeferDuration: EraIndex = 0; pub const AttestationPeriod: u64 = 100; pub const RewardCurve: &'static PiecewiseLinear<'static> = &REWARD_CURVE; - pub const MaxNominatorRewardedPerValidator: u32 = 64; pub const ElectionLookahead: u64 = 0; pub const StakingUnsignedPriority: u64 = u64::MAX / 2; pub const OffendingValidatorsThreshold: Perbill = Perbill::from_percent(17); @@ -213,7 +201,7 @@ impl pallet_staking::Config for Test { type SessionInterface = Self; type UnixTime = pallet_timestamp::Pallet; type EraPayout = pallet_staking::ConvertCurve; - type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator; + type MaxNominatorRewardedPerValidator = ConstU32<64>; type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type NextNewSession = Session; type ElectionProvider = onchain::OnChainSequentialPhragmen; @@ -232,7 +220,6 @@ impl pallet_offences::Config for Test { parameter_types! { pub const ReportLongevity: u64 = BondingDuration::get() as u64 * SessionsPerEra::get() as u64 * Period::get(); - pub const MaxAuthorities: u32 = 100; } impl Config for Test { @@ -253,7 +240,7 @@ impl Config for Test { super::EquivocationHandler; type WeightInfo = (); - type MaxAuthorities = MaxAuthorities; + type MaxAuthorities = ConstU32<100>; } pub fn grandpa_log(log: ConsensusLog) -> DigestItem { diff --git a/frame/identity/src/tests.rs b/frame/identity/src/tests.rs index 2faf65f560a8..efbd1d984f33 100644 --- a/frame/identity/src/tests.rs +++ b/frame/identity/src/tests.rs @@ -22,7 +22,9 @@ use crate as pallet_identity; use codec::{Decode, Encode}; use frame_support::{ - assert_noop, assert_ok, ord_parameter_types, parameter_types, traits::EnsureOneOf, BoundedVec, + assert_noop, assert_ok, ord_parameter_types, parameter_types, + traits::{ConstU32, ConstU64, EnsureOneOf}, + BoundedVec, }; use frame_system::{EnsureRoot, EnsureSignedBy}; use sp_core::H256; @@ -47,7 +49,6 @@ frame_support::construct_runtime!( ); parameter_types! { - pub const BlockHashCount: u64 = 250; pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max(1024); } @@ -65,7 +66,7 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type DbWeight = (); type Version = (); type PalletInfo = PalletInfo; @@ -75,30 +76,26 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; -} -parameter_types! { - pub const ExistentialDeposit: u64 = 1; + type MaxConsumers = ConstU32<16>; } + impl pallet_balances::Config for Test { type Balance = u64; type Event = Event; type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; + type ExistentialDeposit = ConstU64<1>; type AccountStore = System; type MaxLocks = (); type MaxReserves = (); type ReserveIdentifier = [u8; 8]; type WeightInfo = (); } + parameter_types! { - pub const BasicDeposit: u64 = 10; - pub const FieldDeposit: u64 = 10; - pub const SubAccountDeposit: u64 = 10; - pub const MaxSubAccounts: u32 = 2; pub const MaxAdditionalFields: u32 = 2; pub const MaxRegistrars: u32 = 20; } + ord_parameter_types! { pub const One: u64 = 1; pub const Two: u64 = 2; @@ -109,10 +106,10 @@ impl pallet_identity::Config for Test { type Event = Event; type Currency = Balances; type Slashed = (); - type BasicDeposit = BasicDeposit; - type FieldDeposit = FieldDeposit; - type SubAccountDeposit = SubAccountDeposit; - type MaxSubAccounts = MaxSubAccounts; + type BasicDeposit = ConstU64<10>; + type FieldDeposit = ConstU64<10>; + type SubAccountDeposit = ConstU64<10>; + type MaxSubAccounts = ConstU32<2>; type MaxAdditionalFields = MaxAdditionalFields; type MaxRegistrars = MaxRegistrars; type RegistrarOrigin = EnsureOneOrRoot; diff --git a/frame/im-online/src/mock.rs b/frame/im-online/src/mock.rs index 3168f60ce022..8166bfc9119e 100644 --- a/frame/im-online/src/mock.rs +++ b/frame/im-online/src/mock.rs @@ -21,7 +21,11 @@ use std::cell::RefCell; -use frame_support::{parameter_types, weights::Weight}; +use frame_support::{ + parameter_types, + traits::{ConstU32, ConstU64}, + weights::Weight, +}; use pallet_session::historical as pallet_session_historical; use sp_core::H256; use sp_runtime::{ @@ -118,7 +122,6 @@ pub fn new_test_ext() -> sp_io::TestExternalities { } parameter_types! { - pub const BlockHashCount: u64 = 250; pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max(1024); } @@ -138,7 +141,7 @@ impl frame_system::Config for Runtime { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = (); @@ -147,7 +150,7 @@ impl frame_system::Config for Runtime { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type MaxConsumers = ConstU32<16>; } parameter_types! { @@ -173,13 +176,9 @@ impl pallet_session::historical::Config for Runtime { type FullIdentificationOf = ConvertInto; } -parameter_types! { - pub const UncleGenerations: u32 = 5; -} - impl pallet_authorship::Config for Runtime { type FindAuthor = (); - type UncleGenerations = UncleGenerations; + type UncleGenerations = ConstU64<5>; type FilterUncle = (); type EventHandler = ImOnline; } @@ -221,9 +220,6 @@ impl frame_support::traits::EstimateNextSessionRotation for TestNextSession parameter_types! { pub const UnsignedPriority: u64 = 1 << 20; - pub const MaxKeys: u32 = 10_000; - pub const MaxPeerInHeartbeats: u32 = 10_000; - pub const MaxPeerDataEncodingSize: u32 = 1_000; } impl Config for Runtime { @@ -234,9 +230,9 @@ impl Config for Runtime { type ReportUnresponsiveness = OffenceHandler; type UnsignedPriority = UnsignedPriority; type WeightInfo = (); - type MaxKeys = MaxKeys; - type MaxPeerInHeartbeats = MaxPeerInHeartbeats; - type MaxPeerDataEncodingSize = MaxPeerDataEncodingSize; + type MaxKeys = ConstU32<10_000>; + type MaxPeerInHeartbeats = ConstU32<10_000>; + type MaxPeerDataEncodingSize = ConstU32<1_000>; } impl frame_system::offchain::SendTransactionTypes for Runtime diff --git a/frame/indices/src/mock.rs b/frame/indices/src/mock.rs index 3e3aed2986b9..ef654833c3a3 100644 --- a/frame/indices/src/mock.rs +++ b/frame/indices/src/mock.rs @@ -20,7 +20,10 @@ #![cfg(test)] use crate::{self as pallet_indices, Config}; -use frame_support::parameter_types; +use frame_support::{ + parameter_types, + traits::{ConstU32, ConstU64}, +}; use sp_core::H256; use sp_runtime::testing::Header; @@ -40,7 +43,6 @@ frame_support::construct_runtime!( ); parameter_types! { - pub const BlockHashCount: u64 = 250; pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max(1024); } @@ -60,7 +62,7 @@ impl frame_system::Config for Test { type Lookup = Indices; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; @@ -69,11 +71,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; -} - -parameter_types! { - pub const ExistentialDeposit: u64 = 1; + type MaxConsumers = ConstU32<16>; } impl pallet_balances::Config for Test { @@ -83,19 +81,15 @@ impl pallet_balances::Config for Test { type Balance = u64; type DustRemoval = (); type Event = Event; - type ExistentialDeposit = ExistentialDeposit; + type ExistentialDeposit = ConstU64<1>; type AccountStore = System; type WeightInfo = (); } -parameter_types! { - pub const Deposit: u64 = 1; -} - impl Config for Test { type AccountIndex = u64; type Currency = Balances; - type Deposit = Deposit; + type Deposit = ConstU64<1>; type Event = Event; type WeightInfo = (); } diff --git a/frame/lottery/src/mock.rs b/frame/lottery/src/mock.rs index df86e063c477..36b847d48d97 100644 --- a/frame/lottery/src/mock.rs +++ b/frame/lottery/src/mock.rs @@ -22,7 +22,7 @@ use crate as pallet_lottery; use frame_support::{ parameter_types, - traits::{OnFinalize, OnInitialize}, + traits::{ConstU32, ConstU64, OnFinalize, OnInitialize}, }; use frame_support_test::TestRandomness; use frame_system::EnsureRoot; @@ -49,9 +49,6 @@ frame_support::construct_runtime!( ); parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: u32 = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; pub const AvailableBlockRatio: Perbill = Perbill::one(); } @@ -70,7 +67,7 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; @@ -79,11 +76,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; -} - -parameter_types! { - pub const ExistentialDeposit: u64 = 1; + type MaxConsumers = ConstU32<16>; } impl pallet_balances::Config for Test { @@ -93,15 +86,13 @@ impl pallet_balances::Config for Test { type Balance = u64; type Event = Event; type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; + type ExistentialDeposit = ConstU64<1>; type AccountStore = System; type WeightInfo = (); } parameter_types! { pub const LotteryPalletId: PalletId = PalletId(*b"py/lotto"); - pub const MaxCalls: u32 = 2; - pub const MaxGenerateRandom: u32 = 10; } impl Config for Test { @@ -111,9 +102,9 @@ impl Config for Test { type Randomness = TestRandomness; type Event = Event; type ManagerOrigin = EnsureRoot; - type MaxCalls = MaxCalls; + type MaxCalls = ConstU32<2>; type ValidateCall = Lottery; - type MaxGenerateRandom = MaxGenerateRandom; + type MaxGenerateRandom = ConstU32<10>; type WeightInfo = (); } diff --git a/frame/membership/src/lib.rs b/frame/membership/src/lib.rs index 4bcc28c0ef46..b34051731f69 100644 --- a/frame/membership/src/lib.rs +++ b/frame/membership/src/lib.rs @@ -509,7 +509,8 @@ mod tests { }; use frame_support::{ - assert_noop, assert_ok, ord_parameter_types, parameter_types, traits::GenesisBuild, + assert_noop, assert_ok, ord_parameter_types, parameter_types, + traits::{ConstU32, ConstU64, GenesisBuild}, }; use frame_system::EnsureSignedBy; @@ -528,8 +529,6 @@ mod tests { ); parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaxMembers: u32 = 10; pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max(1024); pub static Members: Vec = vec![]; @@ -551,7 +550,7 @@ mod tests { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = (); @@ -560,7 +559,7 @@ mod tests { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type MaxConsumers = ConstU32<16>; } ord_parameter_types! { pub const One: u64 = 1; @@ -607,7 +606,7 @@ mod tests { type PrimeOrigin = EnsureSignedBy; type MembershipInitialized = TestChangeMembers; type MembershipChanged = TestChangeMembers; - type MaxMembers = MaxMembers; + type MaxMembers = ConstU32<10>; type WeightInfo = (); } diff --git a/frame/merkle-mountain-range/src/mock.rs b/frame/merkle-mountain-range/src/mock.rs index 392ae5050a96..2adea420f03d 100644 --- a/frame/merkle-mountain-range/src/mock.rs +++ b/frame/merkle-mountain-range/src/mock.rs @@ -19,7 +19,7 @@ use crate as pallet_mmr; use crate::*; use codec::{Decode, Encode}; -use frame_support::parameter_types; +use frame_support::traits::{ConstU32, ConstU64}; use pallet_mmr_primitives::{Compact, LeafDataProvider}; use sp_core::H256; use sp_runtime::{ @@ -42,9 +42,6 @@ frame_support::construct_runtime!( } ); -parameter_types! { - pub const BlockHashCount: u64 = 250; -} impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type Origin = Origin; @@ -57,7 +54,7 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type DbWeight = (); type BlockWeights = (); type BlockLength = (); @@ -69,7 +66,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type MaxConsumers = ConstU32<16>; } impl Config for Test { diff --git a/frame/multisig/src/tests.rs b/frame/multisig/src/tests.rs index f050ac9d7200..2d6c02c559e8 100644 --- a/frame/multisig/src/tests.rs +++ b/frame/multisig/src/tests.rs @@ -22,7 +22,10 @@ use super::*; use crate as pallet_multisig; -use frame_support::{assert_noop, assert_ok, parameter_types, traits::Contains}; +use frame_support::{ + assert_noop, assert_ok, parameter_types, + traits::{ConstU16, ConstU32, ConstU64, Contains}, +}; use sp_core::H256; use sp_runtime::{ testing::Header, @@ -46,7 +49,6 @@ frame_support::construct_runtime!( ); parameter_types! { - pub const BlockHashCount: u64 = 250; pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max(1024); } @@ -65,7 +67,7 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; @@ -74,11 +76,9 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; -} -parameter_types! { - pub const ExistentialDeposit: u64 = 1; + type MaxConsumers = ConstU32<16>; } + impl pallet_balances::Config for Test { type MaxLocks = (); type MaxReserves = (); @@ -86,15 +86,11 @@ impl pallet_balances::Config for Test { type Balance = u64; type Event = Event; type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; + type ExistentialDeposit = ConstU64<1>; type AccountStore = System; type WeightInfo = (); } -parameter_types! { - pub const DepositBase: u64 = 1; - pub const DepositFactor: u64 = 1; - pub const MaxSignatories: u16 = 3; -} + pub struct TestBaseCallFilter; impl Contains for TestBaseCallFilter { fn contains(c: &Call) -> bool { @@ -110,9 +106,9 @@ impl Config for Test { type Event = Event; type Call = Call; type Currency = Balances; - type DepositBase = DepositBase; - type DepositFactor = DepositFactor; - type MaxSignatories = MaxSignatories; + type DepositBase = ConstU64<1>; + type DepositFactor = ConstU64<1>; + type MaxSignatories = ConstU16<3>; type WeightInfo = (); } diff --git a/frame/nicks/src/lib.rs b/frame/nicks/src/lib.rs index ea58ea693d3f..91918ce84600 100644 --- a/frame/nicks/src/lib.rs +++ b/frame/nicks/src/lib.rs @@ -245,7 +245,10 @@ mod tests { use super::*; use crate as pallet_nicks; - use frame_support::{assert_noop, assert_ok, ord_parameter_types, parameter_types}; + use frame_support::{ + assert_noop, assert_ok, ord_parameter_types, parameter_types, + traits::{ConstU32, ConstU64}, + }; use frame_system::EnsureSignedBy; use sp_core::H256; use sp_runtime::{ @@ -269,7 +272,6 @@ mod tests { ); parameter_types! { - pub const BlockHashCount: u64 = 250; pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max(1024); } @@ -288,7 +290,7 @@ mod tests { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; @@ -297,11 +299,9 @@ mod tests { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; - } - parameter_types! { - pub const ExistentialDeposit: u64 = 1; + type MaxConsumers = ConstU32<16>; } + impl pallet_balances::Config for Test { type MaxLocks = (); type MaxReserves = (); @@ -309,26 +309,22 @@ mod tests { type Balance = u64; type Event = Event; type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; + type ExistentialDeposit = ConstU64<1>; type AccountStore = System; type WeightInfo = (); } - parameter_types! { - pub const ReservationFee: u64 = 2; - pub const MinLength: u32 = 3; - pub const MaxLength: u32 = 16; - } + ord_parameter_types! { pub const One: u64 = 1; } impl Config for Test { type Event = Event; type Currency = Balances; - type ReservationFee = ReservationFee; + type ReservationFee = ConstU64<2>; type Slashed = (); type ForceOrigin = EnsureSignedBy; - type MinLength = MinLength; - type MaxLength = MaxLength; + type MinLength = ConstU32<3>; + type MaxLength = ConstU32<16>; } fn new_test_ext() -> sp_io::TestExternalities { diff --git a/frame/node-authorization/src/mock.rs b/frame/node-authorization/src/mock.rs index 8e2bc7cfd2a6..bb882c62abb6 100644 --- a/frame/node-authorization/src/mock.rs +++ b/frame/node-authorization/src/mock.rs @@ -20,7 +20,10 @@ use super::*; use crate as pallet_node_authorization; -use frame_support::{ord_parameter_types, parameter_types, traits::GenesisBuild}; +use frame_support::{ + ord_parameter_types, + traits::{ConstU32, ConstU64, GenesisBuild}, +}; use frame_system::EnsureSignedBy; use sp_core::H256; use sp_runtime::{ @@ -44,9 +47,6 @@ frame_support::construct_runtime!( } ); -parameter_types! { - pub const BlockHashCount: u64 = 250; -} impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type DbWeight = (); @@ -62,7 +62,7 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = (); @@ -71,7 +71,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type MaxConsumers = ConstU32<16>; } ord_parameter_types! { @@ -80,14 +80,11 @@ ord_parameter_types! { pub const Three: u64 = 3; pub const Four: u64 = 4; } -parameter_types! { - pub const MaxWellKnownNodes: u32 = 4; - pub const MaxPeerIdLength: u32 = 2; -} + impl Config for Test { type Event = Event; - type MaxWellKnownNodes = MaxWellKnownNodes; - type MaxPeerIdLength = MaxPeerIdLength; + type MaxWellKnownNodes = ConstU32<4>; + type MaxPeerIdLength = ConstU32<2>; type AddOrigin = EnsureSignedBy; type RemoveOrigin = EnsureSignedBy; type SwapOrigin = EnsureSignedBy; diff --git a/frame/offences/benchmarking/src/mock.rs b/frame/offences/benchmarking/src/mock.rs index ab2b3569228c..1a5fdcd61bee 100644 --- a/frame/offences/benchmarking/src/mock.rs +++ b/frame/offences/benchmarking/src/mock.rs @@ -21,7 +21,11 @@ use super::*; use frame_election_provider_support::onchain; -use frame_support::{parameter_types, weights::constants::WEIGHT_PER_SECOND}; +use frame_support::{ + parameter_types, + traits::{ConstU32, ConstU64}, + weights::constants::WEIGHT_PER_SECOND, +}; use frame_system as system; use pallet_session::historical as pallet_session_historical; use sp_runtime::{ @@ -80,13 +84,10 @@ impl pallet_balances::Config for Test { type WeightInfo = (); } -parameter_types! { - pub const MinimumPeriod: u64 = 5; -} impl pallet_timestamp::Config for Test { type Moment = u64; type OnTimestampSet = (); - type MinimumPeriod = MinimumPeriod; + type MinimumPeriod = ConstU64<5>; type WeightInfo = (); } impl pallet_session::historical::Config for Test { @@ -145,10 +146,6 @@ pallet_staking_reward_curve::build! { } parameter_types! { pub const RewardCurve: &'static sp_runtime::curve::PiecewiseLinear<'static> = &I_NPOS; - pub const MaxNominatorRewardedPerValidator: u32 = 64; - pub const MaxKeys: u32 = 10_000; - pub const MaxPeerInHeartbeats: u32 = 10_000; - pub const MaxPeerDataEncodingSize: u32 = 1_000; } pub type Extrinsic = sp_runtime::testing::TestXt; @@ -174,7 +171,7 @@ impl pallet_staking::Config for Test { type SessionInterface = Self; type EraPayout = pallet_staking::ConvertCurve; type NextNewSession = Session; - type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator; + type MaxNominatorRewardedPerValidator = ConstU32<64>; type OffendingValidatorsThreshold = (); type ElectionProvider = onchain::OnChainSequentialPhragmen; type GenesisElectionProvider = Self::ElectionProvider; @@ -191,9 +188,9 @@ impl pallet_im_online::Config for Test { type ReportUnresponsiveness = Offences; type UnsignedPriority = (); type WeightInfo = (); - type MaxKeys = MaxKeys; - type MaxPeerInHeartbeats = MaxPeerInHeartbeats; - type MaxPeerDataEncodingSize = MaxPeerDataEncodingSize; + type MaxKeys = ConstU32<10_000>; + type MaxPeerInHeartbeats = ConstU32<10_000>; + type MaxPeerDataEncodingSize = ConstU32<1_000>; } impl pallet_offences::Config for Test { diff --git a/frame/offences/src/mock.rs b/frame/offences/src/mock.rs index c2db42ec72fa..17d34d46e313 100644 --- a/frame/offences/src/mock.rs +++ b/frame/offences/src/mock.rs @@ -24,6 +24,7 @@ use crate::Config; use codec::Encode; use frame_support::{ parameter_types, + traits::{ConstU32, ConstU64}, weights::{ constants::{RocksDbWeight, WEIGHT_PER_SECOND}, Weight, @@ -84,7 +85,6 @@ frame_support::construct_runtime!( ); parameter_types! { - pub const BlockHashCount: u64 = 250; pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max(2 * WEIGHT_PER_SECOND); } @@ -103,7 +103,7 @@ impl frame_system::Config for Runtime { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = (); @@ -112,7 +112,7 @@ impl frame_system::Config for Runtime { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type MaxConsumers = ConstU32<16>; } impl Config for Runtime { diff --git a/frame/preimage/src/mock.rs b/frame/preimage/src/mock.rs index 601f72547237..3996d8425696 100644 --- a/frame/preimage/src/mock.rs +++ b/frame/preimage/src/mock.rs @@ -21,7 +21,9 @@ use super::*; use crate as pallet_preimage; use frame_support::{ - ord_parameter_types, parameter_types, traits::Everything, weights::constants::RocksDbWeight, + ord_parameter_types, parameter_types, + traits::{ConstU32, ConstU64, Everything}, + weights::constants::RocksDbWeight, }; use frame_system::EnsureSignedBy; use sp_core::H256; @@ -47,7 +49,6 @@ frame_support::construct_runtime!( ); parameter_types! { - pub const BlockHashCount: u64 = 250; pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max(2_000_000_000_000); } @@ -66,7 +67,7 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; @@ -75,32 +76,24 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; -} - -parameter_types! { - pub const ExistentialDeposit: u64 = 5; - pub const MaxReserves: u32 = 50; + type MaxConsumers = ConstU32<16>; } impl pallet_balances::Config for Test { type Balance = u64; type Event = Event; type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; + type ExistentialDeposit = ConstU64<5>; type AccountStore = System; type WeightInfo = (); type MaxLocks = (); - type MaxReserves = MaxReserves; + type MaxReserves = ConstU32<50>; type ReserveIdentifier = [u8; 8]; } parameter_types! { pub MaximumSchedulerWeight: Weight = Perbill::from_percent(80) * BlockWeights::get().max_block; pub const MaxScheduledPerBlock: u32 = 10; - pub const MaxSize: u32 = 1024; - pub const BaseDeposit: u64 = 2; - pub const ByteDeposit: u64 = 1; } ord_parameter_types! { @@ -112,9 +105,9 @@ impl Config for Test { type Event = Event; type Currency = Balances; type ManagerOrigin = EnsureSignedBy; - type MaxSize = MaxSize; - type BaseDeposit = BaseDeposit; - type ByteDeposit = ByteDeposit; + type MaxSize = ConstU32<1024>; + type BaseDeposit = ConstU64<2>; + type ByteDeposit = ConstU64<1>; } pub fn new_test_ext() -> sp_io::TestExternalities { diff --git a/frame/proxy/src/tests.rs b/frame/proxy/src/tests.rs index 538527d47ecd..902eae8fc320 100644 --- a/frame/proxy/src/tests.rs +++ b/frame/proxy/src/tests.rs @@ -24,7 +24,10 @@ use super::*; use crate as proxy; use codec::{Decode, Encode}; use frame_support::{ - assert_noop, assert_ok, dispatch::DispatchError, parameter_types, traits::Contains, + assert_noop, assert_ok, + dispatch::DispatchError, + parameter_types, + traits::{ConstU32, ConstU64, Contains}, RuntimeDebug, }; use sp_core::H256; @@ -50,7 +53,6 @@ frame_support::construct_runtime!( ); parameter_types! { - pub const BlockHashCount: u64 = 250; pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max(1024); } @@ -69,7 +71,7 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; @@ -78,11 +80,9 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; -} -parameter_types! { - pub const ExistentialDeposit: u64 = 1; + type MaxConsumers = ConstU32<16>; } + impl pallet_balances::Config for Test { type MaxLocks = (); type MaxReserves = (); @@ -90,7 +90,7 @@ impl pallet_balances::Config for Test { type Balance = u64; type Event = Event; type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; + type ExistentialDeposit = ConstU64<1>; type AccountStore = System; type WeightInfo = (); } @@ -100,14 +100,7 @@ impl pallet_utility::Config for Test { type PalletsOrigin = OriginCaller; type WeightInfo = (); } -parameter_types! { - pub const ProxyDepositBase: u64 = 1; - pub const ProxyDepositFactor: u64 = 1; - pub const MaxProxies: u16 = 4; - pub const MaxPending: u32 = 2; - pub const AnnouncementDepositBase: u64 = 1; - pub const AnnouncementDepositFactor: u64 = 1; -} + #[derive( Copy, Clone, @@ -161,14 +154,14 @@ impl Config for Test { type Call = Call; type Currency = Balances; type ProxyType = ProxyType; - type ProxyDepositBase = ProxyDepositBase; - type ProxyDepositFactor = ProxyDepositFactor; - type MaxProxies = MaxProxies; + type ProxyDepositBase = ConstU64<1>; + type ProxyDepositFactor = ConstU64<1>; + type MaxProxies = ConstU32<4>; type WeightInfo = (); type CallHasher = BlakeTwo256; - type MaxPending = MaxPending; - type AnnouncementDepositBase = AnnouncementDepositBase; - type AnnouncementDepositFactor = AnnouncementDepositFactor; + type MaxPending = ConstU32<2>; + type AnnouncementDepositBase = ConstU64<1>; + type AnnouncementDepositFactor = ConstU64<1>; } use super::{Call as ProxyCall, Event as ProxyEvent}; diff --git a/frame/randomness-collective-flip/src/lib.rs b/frame/randomness-collective-flip/src/lib.rs index eee70984f257..bf5920acff8e 100644 --- a/frame/randomness-collective-flip/src/lib.rs +++ b/frame/randomness-collective-flip/src/lib.rs @@ -169,7 +169,7 @@ mod tests { use frame_support::{ parameter_types, - traits::{OnInitialize, Randomness}, + traits::{ConstU32, ConstU64, OnInitialize, Randomness}, }; use frame_system::limits; @@ -188,7 +188,6 @@ mod tests { ); parameter_types! { - pub const BlockHashCount: u64 = 250; pub BlockWeights: limits::BlockWeights = limits::BlockWeights ::simple_max(1024); pub BlockLength: limits::BlockLength = limits::BlockLength @@ -210,7 +209,7 @@ mod tests { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = (); @@ -219,7 +218,7 @@ mod tests { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type MaxConsumers = ConstU32<16>; } impl pallet_randomness_collective_flip::Config for Test {} diff --git a/frame/recovery/src/mock.rs b/frame/recovery/src/mock.rs index 1bd7507436b7..778b966c76e8 100644 --- a/frame/recovery/src/mock.rs +++ b/frame/recovery/src/mock.rs @@ -22,7 +22,7 @@ use super::*; use crate as recovery; use frame_support::{ parameter_types, - traits::{OnFinalize, OnInitialize}, + traits::{ConstU16, ConstU32, ConstU64, OnFinalize, OnInitialize}, }; use sp_core::H256; use sp_runtime::{ @@ -46,7 +46,6 @@ frame_support::construct_runtime!( ); parameter_types! { - pub const BlockHashCount: u64 = 250; pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max(1024); } @@ -66,7 +65,7 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; @@ -75,7 +74,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type MaxConsumers = ConstU32<16>; } parameter_types! { @@ -97,7 +96,6 @@ impl pallet_balances::Config for Test { parameter_types! { pub const ConfigDepositBase: u64 = 10; pub const FriendDepositFactor: u64 = 1; - pub const MaxFriends: u16 = 3; pub const RecoveryDeposit: u64 = 10; } @@ -107,7 +105,7 @@ impl Config for Test { type Currency = Balances; type ConfigDepositBase = ConfigDepositBase; type FriendDepositFactor = FriendDepositFactor; - type MaxFriends = MaxFriends; + type MaxFriends = ConstU16<3>; type RecoveryDeposit = RecoveryDeposit; } diff --git a/frame/scheduler/src/mock.rs b/frame/scheduler/src/mock.rs index 535e91937e4d..014f473302ab 100644 --- a/frame/scheduler/src/mock.rs +++ b/frame/scheduler/src/mock.rs @@ -22,7 +22,9 @@ use super::*; use crate as scheduler; use frame_support::{ ord_parameter_types, parameter_types, - traits::{Contains, EnsureOneOf, EqualPrivilegeOnly, OnFinalize, OnInitialize}, + traits::{ + ConstU32, ConstU64, Contains, EnsureOneOf, EqualPrivilegeOnly, OnFinalize, OnInitialize, + }, weights::constants::RocksDbWeight, }; use frame_system::{EnsureRoot, EnsureSignedBy}; @@ -116,7 +118,6 @@ impl Contains for BaseFilter { } parameter_types! { - pub const BlockHashCount: u64 = 250; pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max(2_000_000_000_000); } @@ -135,7 +136,7 @@ impl system::Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = (); @@ -144,15 +145,13 @@ impl system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type MaxConsumers = ConstU32<16>; } impl logger::Config for Test { type Event = Event; } parameter_types! { pub MaximumSchedulerWeight: Weight = Perbill::from_percent(80) * BlockWeights::get().max_block; - pub const MaxScheduledPerBlock: u32 = 10; - pub const MaxSize: u32 = 1024; pub const NoPreimagePostponement: Option = Some(2); } ord_parameter_types! { @@ -164,7 +163,7 @@ impl pallet_preimage::Config for Test { type WeightInfo = (); type Currency = (); type ManagerOrigin = EnsureRoot; - type MaxSize = MaxSize; + type MaxSize = ConstU32<1024>; type BaseDeposit = (); type ByteDeposit = (); } @@ -176,7 +175,7 @@ impl Config for Test { type Call = Call; type MaximumWeight = MaximumSchedulerWeight; type ScheduleOrigin = EnsureOneOf, EnsureSignedBy>; - type MaxScheduledPerBlock = MaxScheduledPerBlock; + type MaxScheduledPerBlock = ConstU32<10>; type WeightInfo = (); type OriginPrivilegeCmp = EqualPrivilegeOnly; type PreimageProvider = Preimage; diff --git a/frame/scored-pool/src/mock.rs b/frame/scored-pool/src/mock.rs index 992aecba38e8..d5b3814fd97a 100644 --- a/frame/scored-pool/src/mock.rs +++ b/frame/scored-pool/src/mock.rs @@ -20,7 +20,10 @@ use super::*; use crate as pallet_scored_pool; -use frame_support::{ord_parameter_types, parameter_types, traits::GenesisBuild}; +use frame_support::{ + ord_parameter_types, parameter_types, + traits::{ConstU32, ConstU64, GenesisBuild}, +}; use frame_system::EnsureSignedBy; use sp_core::H256; use sp_runtime::{ @@ -46,9 +49,6 @@ frame_support::construct_runtime!( parameter_types! { pub const CandidateDeposit: u64 = 25; - pub const Period: u64 = 4; - pub const BlockHashCount: u64 = 250; - pub const ExistentialDeposit: u64 = 1; pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max(1024); } @@ -72,7 +72,7 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; @@ -81,7 +81,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type MaxConsumers = ConstU32<16>; } impl pallet_balances::Config for Test { @@ -91,7 +91,7 @@ impl pallet_balances::Config for Test { type Balance = u64; type Event = Event; type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; + type ExistentialDeposit = ConstU64<1>; type AccountStore = System; type WeightInfo = (); } @@ -130,7 +130,7 @@ impl Config for Test { type MembershipChanged = TestChangeMembers; type Currency = Balances; type CandidateDeposit = CandidateDeposit; - type Period = Period; + type Period = ConstU64<4>; type Score = u64; type ScoreOrigin = EnsureSignedBy; } diff --git a/frame/session/benchmarking/src/mock.rs b/frame/session/benchmarking/src/mock.rs index 3f3b103905b5..2560563511e6 100644 --- a/frame/session/benchmarking/src/mock.rs +++ b/frame/session/benchmarking/src/mock.rs @@ -20,7 +20,10 @@ #![cfg(test)] use frame_election_provider_support::onchain; -use frame_support::parameter_types; +use frame_support::{ + parameter_types, + traits::{ConstU32, ConstU64}, +}; use sp_runtime::traits::IdentityLookup; type AccountId = u64; @@ -68,7 +71,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type MaxConsumers = ConstU32<16>; } parameter_types! { pub const ExistentialDeposit: Balance = 10; @@ -85,13 +88,10 @@ impl pallet_balances::Config for Test { type WeightInfo = (); } -parameter_types! { - pub const MinimumPeriod: u64 = 5; -} impl pallet_timestamp::Config for Test { type Moment = u64; type OnTimestampSet = (); - type MinimumPeriod = MinimumPeriod; + type MinimumPeriod = ConstU64<5>; type WeightInfo = (); } impl pallet_session::historical::Config for Test { @@ -144,8 +144,6 @@ pallet_staking_reward_curve::build! { } parameter_types! { pub const RewardCurve: &'static sp_runtime::curve::PiecewiseLinear<'static> = &I_NPOS; - pub const MaxNominatorRewardedPerValidator: u32 = 64; - pub const UnsignedPriority: u64 = 1 << 20; } pub type Extrinsic = sp_runtime::testing::TestXt; @@ -179,7 +177,7 @@ impl pallet_staking::Config for Test { type SessionInterface = Self; type EraPayout = pallet_staking::ConvertCurve; type NextNewSession = Session; - type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator; + type MaxNominatorRewardedPerValidator = ConstU32<64>; type OffendingValidatorsThreshold = (); type ElectionProvider = onchain::OnChainSequentialPhragmen; type GenesisElectionProvider = Self::ElectionProvider; diff --git a/frame/session/src/mock.rs b/frame/session/src/mock.rs index d0511d393682..ec1f841f50b1 100644 --- a/frame/session/src/mock.rs +++ b/frame/session/src/mock.rs @@ -32,7 +32,11 @@ use sp_runtime::{ }; use sp_staking::SessionIndex; -use frame_support::{parameter_types, traits::GenesisBuild, BasicExternalities}; +use frame_support::{ + parameter_types, + traits::{ConstU32, ConstU64, GenesisBuild}, + BasicExternalities, +}; impl_opaque_keys! { pub struct MockSessionKeys { @@ -234,8 +238,6 @@ pub fn new_test_ext() -> sp_io::TestExternalities { } parameter_types! { - pub const MinimumPeriod: u64 = 5; - pub const BlockHashCount: u64 = 250; pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max(1024); } @@ -255,7 +257,7 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = (); @@ -264,13 +266,13 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type MaxConsumers = ConstU32<16>; } impl pallet_timestamp::Config for Test { type Moment = u64; type OnTimestampSet = (); - type MinimumPeriod = MinimumPeriod; + type MinimumPeriod = ConstU64<5>; type WeightInfo = (); } diff --git a/frame/session/src/tests.rs b/frame/session/src/tests.rs index cc0606edf499..199076c88244 100644 --- a/frame/session/src/tests.rs +++ b/frame/session/src/tests.rs @@ -29,7 +29,10 @@ use codec::Decode; use sp_core::crypto::key_types::DUMMY; use sp_runtime::testing::UintAuthorityId; -use frame_support::{assert_noop, assert_ok, traits::OnInitialize}; +use frame_support::{ + assert_noop, assert_ok, + traits::{ConstU64, OnInitialize}, +}; fn initialize_block(block: u64) { SESSION_CHANGED.with(|l| *l.borrow_mut() = false); @@ -291,12 +294,7 @@ fn session_changed_flag_works() { #[test] fn periodic_session_works() { - frame_support::parameter_types! { - const Period: u64 = 10; - const Offset: u64 = 3; - } - - type P = PeriodicSessions; + type P = PeriodicSessions, ConstU64<3>>; // make sure that offset phase behaves correctly for i in 0u64..3 { diff --git a/frame/society/src/mock.rs b/frame/society/src/mock.rs index 4348f2378c42..fbf3b2fd757a 100644 --- a/frame/society/src/mock.rs +++ b/frame/society/src/mock.rs @@ -20,7 +20,10 @@ use super::*; use crate as pallet_society; -use frame_support::{ord_parameter_types, parameter_types}; +use frame_support::{ + ord_parameter_types, parameter_types, + traits::{ConstU32, ConstU64}, +}; use frame_support_test::TestRandomness; use frame_system::EnsureSignedBy; use sp_core::H256; @@ -45,16 +48,6 @@ frame_support::construct_runtime!( ); parameter_types! { - pub const CandidateDeposit: u64 = 25; - pub const WrongSideDeduction: u64 = 2; - pub const MaxStrikes: u32 = 2; - pub const RotationPeriod: u64 = 4; - pub const PeriodSpend: u64 = 1000; - pub const MaxLockDuration: u64 = 100; - pub const ChallengePeriod: u64 = 8; - pub const BlockHashCount: u64 = 250; - pub const ExistentialDeposit: u64 = 1; - pub const MaxCandidateIntake: u32 = 10; pub const SocietyPalletId: PalletId = PalletId(*b"py/socie"); pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max(1024); @@ -80,7 +73,7 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type OnNewAccount = (); @@ -89,7 +82,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type MaxConsumers = ConstU32<16>; } impl pallet_balances::Config for Test { @@ -99,7 +92,7 @@ impl pallet_balances::Config for Test { type Balance = u64; type Event = Event; type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; + type ExistentialDeposit = ConstU64<1>; type AccountStore = System; type WeightInfo = (); } @@ -108,17 +101,17 @@ impl Config for Test { type Event = Event; type Currency = pallet_balances::Pallet; type Randomness = TestRandomness; - type CandidateDeposit = CandidateDeposit; - type WrongSideDeduction = WrongSideDeduction; - type MaxStrikes = MaxStrikes; - type PeriodSpend = PeriodSpend; + type CandidateDeposit = ConstU64<25>; + type WrongSideDeduction = ConstU64<2>; + type MaxStrikes = ConstU32<2>; + type PeriodSpend = ConstU64<1000>; type MembershipChanged = (); - type RotationPeriod = RotationPeriod; - type MaxLockDuration = MaxLockDuration; + type RotationPeriod = ConstU64<4>; + type MaxLockDuration = ConstU64<100>; type FounderSetOrigin = EnsureSignedBy; type SuspensionJudgementOrigin = EnsureSignedBy; - type ChallengePeriod = ChallengePeriod; - type MaxCandidateIntake = MaxCandidateIntake; + type ChallengePeriod = ConstU64<8>; + type MaxCandidateIntake = ConstU32<10>; type PalletId = SocietyPalletId; } diff --git a/frame/staking/src/benchmarking.rs b/frame/staking/src/benchmarking.rs index f96b7fd2f37b..cd9755366b0f 100644 --- a/frame/staking/src/benchmarking.rs +++ b/frame/staking/src/benchmarking.rs @@ -947,7 +947,7 @@ mod tests { let (validator_stash, nominators) = create_validator_with_nominators::( n, - ::MaxNominatorRewardedPerValidator::get() as u32, + ::MaxNominatorRewardedPerValidator::get(), false, RewardDestination::Staked, ) @@ -972,7 +972,7 @@ mod tests { let (validator_stash, _nominators) = create_validator_with_nominators::( n, - ::MaxNominatorRewardedPerValidator::get() as u32, + ::MaxNominatorRewardedPerValidator::get(), false, RewardDestination::Staked, ) diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index f6e2ce0e4bc1..ea9b9f05f105 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -22,7 +22,8 @@ use frame_election_provider_support::{onchain, SortedListProvider}; use frame_support::{ assert_ok, parameter_types, traits::{ - Currency, FindAuthor, GenesisBuild, Get, Hooks, Imbalance, OnUnbalanced, OneSessionHandler, + ConstU32, ConstU64, Currency, FindAuthor, GenesisBuild, Get, Hooks, Imbalance, + OnUnbalanced, OneSessionHandler, }, weights::constants::RocksDbWeight, }; @@ -113,12 +114,10 @@ impl FindAuthor for Author11 { } parameter_types! { - pub const BlockHashCount: u64 = 250; pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max( frame_support::weights::constants::WEIGHT_PER_SECOND * 2 ); - pub const MaxLocks: u32 = 1024; pub static SessionsPerEra: SessionIndex = 3; pub static ExistentialDeposit: Balance = 1; pub static SlashDeferDuration: EraIndex = 0; @@ -141,7 +140,7 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = frame_support::traits::ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; @@ -153,7 +152,7 @@ impl frame_system::Config for Test { type MaxConsumers = frame_support::traits::ConstU32<16>; } impl pallet_balances::Config for Test { - type MaxLocks = MaxLocks; + type MaxLocks = frame_support::traits::ConstU32<1024>; type MaxReserves = (); type ReserveIdentifier = [u8; 8]; type Balance = Balance; @@ -163,9 +162,7 @@ impl pallet_balances::Config for Test { type AccountStore = System; type WeightInfo = (); } -parameter_types! { - pub const UncleGenerations: u64 = 0; -} + sp_runtime::impl_opaque_keys! { pub struct SessionKeys { pub other: OtherSessionHandler, @@ -189,19 +186,18 @@ impl pallet_session::historical::Config for Test { } impl pallet_authorship::Config for Test { type FindAuthor = Author11; - type UncleGenerations = UncleGenerations; + type UncleGenerations = ConstU64<0>; type FilterUncle = (); type EventHandler = Pallet; } -parameter_types! { - pub const MinimumPeriod: u64 = 5; -} + impl pallet_timestamp::Config for Test { type Moment = u64; type OnTimestampSet = (); - type MinimumPeriod = MinimumPeriod; + type MinimumPeriod = ConstU64<5>; type WeightInfo = (); } + pallet_staking_reward_curve::build! { const I_NPOS: PiecewiseLinear<'static> = curve!( min_inflation: 0_025_000, @@ -215,7 +211,6 @@ pallet_staking_reward_curve::build! { parameter_types! { pub const BondingDuration: EraIndex = 3; pub const RewardCurve: &'static PiecewiseLinear<'static> = &I_NPOS; - pub const MaxNominatorRewardedPerValidator: u32 = 64; pub const OffendingValidatorsThreshold: Perbill = Perbill::from_percent(75); } @@ -269,7 +264,7 @@ impl crate::pallet::pallet::Config for Test { type SessionInterface = Self; type EraPayout = ConvertCurve; type NextNewSession = Session; - type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator; + type MaxNominatorRewardedPerValidator = ConstU32<64>; type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type ElectionProvider = onchain::OnChainSequentialPhragmen; type GenesisElectionProvider = Self::ElectionProvider; diff --git a/frame/sudo/src/mock.rs b/frame/sudo/src/mock.rs index 408cccc7de21..baea68788acf 100644 --- a/frame/sudo/src/mock.rs +++ b/frame/sudo/src/mock.rs @@ -21,7 +21,7 @@ use super::*; use crate as sudo; use frame_support::{ parameter_types, - traits::{Contains, GenesisBuild}, + traits::{ConstU32, ConstU64, Contains, GenesisBuild}, }; use frame_system::limits; use sp_core::H256; @@ -109,7 +109,6 @@ frame_support::construct_runtime!( ); parameter_types! { - pub const BlockHashCount: u64 = 250; pub BlockWeights: limits::BlockWeights = limits::BlockWeights::simple_max(1024); } @@ -135,7 +134,7 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = (); @@ -144,7 +143,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type MaxConsumers = ConstU32<16>; } // Implement the logger module's `Config` on the Test runtime. diff --git a/frame/support/src/storage/bounded_btree_map.rs b/frame/support/src/storage/bounded_btree_map.rs index 7a59206aeba0..224ff496a990 100644 --- a/frame/support/src/storage/bounded_btree_map.rs +++ b/frame/support/src/storage/bounded_btree_map.rs @@ -306,18 +306,14 @@ impl codec::EncodeLike> for BoundedBTreeMap whe pub mod test { use super::*; use crate::Twox128; + use frame_support::traits::ConstU32; use sp_io::TestExternalities; - crate::parameter_types! { - pub const Seven: u32 = 7; - pub const Four: u32 = 4; - } - - crate::generate_storage_alias! { Prefix, Foo => Value> } - crate::generate_storage_alias! { Prefix, FooMap => Map<(u32, Twox128), BoundedBTreeMap> } + crate::generate_storage_alias! { Prefix, Foo => Value>> } + crate::generate_storage_alias! { Prefix, FooMap => Map<(u32, Twox128), BoundedBTreeMap>> } crate::generate_storage_alias! { Prefix, - FooDoubleMap => DoubleMap<(u32, Twox128), (u32, Twox128), BoundedBTreeMap> + FooDoubleMap => DoubleMap<(u32, Twox128), (u32, Twox128), BoundedBTreeMap>> } fn map_from_keys(keys: &[K]) -> BTreeMap @@ -338,13 +334,13 @@ pub mod test { #[test] fn decode_len_works() { TestExternalities::default().execute_with(|| { - let bounded = boundedmap_from_keys::(&[1, 2, 3]); + let bounded = boundedmap_from_keys::>(&[1, 2, 3]); Foo::put(bounded); assert_eq!(Foo::decode_len().unwrap(), 3); }); TestExternalities::default().execute_with(|| { - let bounded = boundedmap_from_keys::(&[1, 2, 3]); + let bounded = boundedmap_from_keys::>(&[1, 2, 3]); FooMap::insert(1, bounded); assert_eq!(FooMap::decode_len(1).unwrap(), 3); assert!(FooMap::decode_len(0).is_none()); @@ -352,7 +348,7 @@ pub mod test { }); TestExternalities::default().execute_with(|| { - let bounded = boundedmap_from_keys::(&[1, 2, 3]); + let bounded = boundedmap_from_keys::>(&[1, 2, 3]); FooDoubleMap::insert(1, 1, bounded); assert_eq!(FooDoubleMap::decode_len(1, 1).unwrap(), 3); assert!(FooDoubleMap::decode_len(2, 1).is_none()); @@ -363,7 +359,7 @@ pub mod test { #[test] fn try_insert_works() { - let mut bounded = boundedmap_from_keys::(&[1, 2, 3]); + let mut bounded = boundedmap_from_keys::>(&[1, 2, 3]); bounded.try_insert(0, ()).unwrap(); assert_eq!(*bounded, map_from_keys(&[1, 0, 2, 3])); @@ -373,7 +369,7 @@ pub mod test { #[test] fn deref_coercion_works() { - let bounded = boundedmap_from_keys::(&[1, 2, 3]); + let bounded = boundedmap_from_keys::>(&[1, 2, 3]); // these methods come from deref-ed vec. assert_eq!(bounded.len(), 3); assert!(bounded.iter().next().is_some()); @@ -382,7 +378,7 @@ pub mod test { #[test] fn try_mutate_works() { - let bounded = boundedmap_from_keys::(&[1, 2, 3, 4, 5, 6]); + let bounded = boundedmap_from_keys::>(&[1, 2, 3, 4, 5, 6]); let bounded = bounded .try_mutate(|v| { v.insert(7, ()); @@ -398,7 +394,7 @@ pub mod test { #[test] fn btree_map_eq_works() { - let bounded = boundedmap_from_keys::(&[1, 2, 3, 4, 5, 6]); + let bounded = boundedmap_from_keys::>(&[1, 2, 3, 4, 5, 6]); assert_eq!(bounded, map_from_keys(&[1, 2, 3, 4, 5, 6])); } @@ -406,7 +402,7 @@ pub mod test { fn too_big_fail_to_decode() { let v: Vec<(u32, u32)> = vec![(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)]; assert_eq!( - BoundedBTreeMap::::decode(&mut &v.encode()[..]), + BoundedBTreeMap::>::decode(&mut &v.encode()[..]), Err("BoundedBTreeMap exceeds its limit".into()), ); } @@ -436,7 +432,7 @@ pub mod test { } } - let mut map = BoundedBTreeMap::::new(); + let mut map = BoundedBTreeMap::>::new(); // when the set is full diff --git a/frame/support/src/storage/bounded_btree_set.rs b/frame/support/src/storage/bounded_btree_set.rs index ecfb0bdbd261..af292aa1c8ff 100644 --- a/frame/support/src/storage/bounded_btree_set.rs +++ b/frame/support/src/storage/bounded_btree_set.rs @@ -287,19 +287,15 @@ impl codec::EncodeLike> for BoundedBTreeSet where BTreeS pub mod test { use super::*; use crate::Twox128; + use frame_support::traits::ConstU32; use sp_io::TestExternalities; use sp_std::convert::TryInto; - crate::parameter_types! { - pub const Seven: u32 = 7; - pub const Four: u32 = 4; - } - - crate::generate_storage_alias! { Prefix, Foo => Value> } - crate::generate_storage_alias! { Prefix, FooMap => Map<(u32, Twox128), BoundedBTreeSet> } + crate::generate_storage_alias! { Prefix, Foo => Value>> } + crate::generate_storage_alias! { Prefix, FooMap => Map<(u32, Twox128), BoundedBTreeSet>> } crate::generate_storage_alias! { Prefix, - FooDoubleMap => DoubleMap<(u32, Twox128), (u32, Twox128), BoundedBTreeSet> + FooDoubleMap => DoubleMap<(u32, Twox128), (u32, Twox128), BoundedBTreeSet>> } fn map_from_keys(keys: &[T]) -> BTreeSet @@ -320,13 +316,13 @@ pub mod test { #[test] fn decode_len_works() { TestExternalities::default().execute_with(|| { - let bounded = boundedmap_from_keys::(&[1, 2, 3]); + let bounded = boundedmap_from_keys::>(&[1, 2, 3]); Foo::put(bounded); assert_eq!(Foo::decode_len().unwrap(), 3); }); TestExternalities::default().execute_with(|| { - let bounded = boundedmap_from_keys::(&[1, 2, 3]); + let bounded = boundedmap_from_keys::>(&[1, 2, 3]); FooMap::insert(1, bounded); assert_eq!(FooMap::decode_len(1).unwrap(), 3); assert!(FooMap::decode_len(0).is_none()); @@ -334,7 +330,7 @@ pub mod test { }); TestExternalities::default().execute_with(|| { - let bounded = boundedmap_from_keys::(&[1, 2, 3]); + let bounded = boundedmap_from_keys::>(&[1, 2, 3]); FooDoubleMap::insert(1, 1, bounded); assert_eq!(FooDoubleMap::decode_len(1, 1).unwrap(), 3); assert!(FooDoubleMap::decode_len(2, 1).is_none()); @@ -345,7 +341,7 @@ pub mod test { #[test] fn try_insert_works() { - let mut bounded = boundedmap_from_keys::(&[1, 2, 3]); + let mut bounded = boundedmap_from_keys::>(&[1, 2, 3]); bounded.try_insert(0).unwrap(); assert_eq!(*bounded, map_from_keys(&[1, 0, 2, 3])); @@ -355,7 +351,7 @@ pub mod test { #[test] fn deref_coercion_works() { - let bounded = boundedmap_from_keys::(&[1, 2, 3]); + let bounded = boundedmap_from_keys::>(&[1, 2, 3]); // these methods come from deref-ed vec. assert_eq!(bounded.len(), 3); assert!(bounded.iter().next().is_some()); @@ -364,7 +360,7 @@ pub mod test { #[test] fn try_mutate_works() { - let bounded = boundedmap_from_keys::(&[1, 2, 3, 4, 5, 6]); + let bounded = boundedmap_from_keys::>(&[1, 2, 3, 4, 5, 6]); let bounded = bounded .try_mutate(|v| { v.insert(7); @@ -380,7 +376,7 @@ pub mod test { #[test] fn btree_map_eq_works() { - let bounded = boundedmap_from_keys::(&[1, 2, 3, 4, 5, 6]); + let bounded = boundedmap_from_keys::>(&[1, 2, 3, 4, 5, 6]); assert_eq!(bounded, map_from_keys(&[1, 2, 3, 4, 5, 6])); } @@ -388,7 +384,7 @@ pub mod test { fn too_big_fail_to_decode() { let v: Vec = vec![1, 2, 3, 4, 5]; assert_eq!( - BoundedBTreeSet::::decode(&mut &v.encode()[..]), + BoundedBTreeSet::>::decode(&mut &v.encode()[..]), Err("BoundedBTreeSet exceeds its limit".into()), ); } @@ -418,7 +414,7 @@ pub mod test { } } - let mut set = BoundedBTreeSet::::new(); + let mut set = BoundedBTreeSet::>::new(); // when the set is full diff --git a/frame/support/src/storage/bounded_vec.rs b/frame/support/src/storage/bounded_vec.rs index b9ece89bff28..decf2cb341bf 100644 --- a/frame/support/src/storage/bounded_vec.rs +++ b/frame/support/src/storage/bounded_vec.rs @@ -348,35 +348,31 @@ where pub mod test { use super::*; use crate::Twox128; + use frame_support::traits::ConstU32; use sp_io::TestExternalities; - crate::parameter_types! { - pub const Seven: u32 = 7; - pub const Four: u32 = 4; - } - - crate::generate_storage_alias! { Prefix, Foo => Value> } - crate::generate_storage_alias! { Prefix, FooMap => Map<(u32, Twox128), BoundedVec> } + crate::generate_storage_alias! { Prefix, Foo => Value>> } + crate::generate_storage_alias! { Prefix, FooMap => Map<(u32, Twox128), BoundedVec>> } crate::generate_storage_alias! { Prefix, - FooDoubleMap => DoubleMap<(u32, Twox128), (u32, Twox128), BoundedVec> + FooDoubleMap => DoubleMap<(u32, Twox128), (u32, Twox128), BoundedVec>> } #[test] fn try_append_is_correct() { - assert_eq!(BoundedVec::::bound(), 7); + assert_eq!(BoundedVec::>::bound(), 7); } #[test] fn decode_len_works() { TestExternalities::default().execute_with(|| { - let bounded: BoundedVec = vec![1, 2, 3].try_into().unwrap(); + let bounded: BoundedVec> = vec![1, 2, 3].try_into().unwrap(); Foo::put(bounded); assert_eq!(Foo::decode_len().unwrap(), 3); }); TestExternalities::default().execute_with(|| { - let bounded: BoundedVec = vec![1, 2, 3].try_into().unwrap(); + let bounded: BoundedVec> = vec![1, 2, 3].try_into().unwrap(); FooMap::insert(1, bounded); assert_eq!(FooMap::decode_len(1).unwrap(), 3); assert!(FooMap::decode_len(0).is_none()); @@ -384,7 +380,7 @@ pub mod test { }); TestExternalities::default().execute_with(|| { - let bounded: BoundedVec = vec![1, 2, 3].try_into().unwrap(); + let bounded: BoundedVec> = vec![1, 2, 3].try_into().unwrap(); FooDoubleMap::insert(1, 1, bounded); assert_eq!(FooDoubleMap::decode_len(1, 1).unwrap(), 3); assert!(FooDoubleMap::decode_len(2, 1).is_none()); @@ -395,7 +391,7 @@ pub mod test { #[test] fn try_insert_works() { - let mut bounded: BoundedVec = vec![1, 2, 3].try_into().unwrap(); + let mut bounded: BoundedVec> = vec![1, 2, 3].try_into().unwrap(); bounded.try_insert(1, 0).unwrap(); assert_eq!(*bounded, vec![1, 0, 2, 3]); @@ -406,13 +402,13 @@ pub mod test { #[test] #[should_panic(expected = "insertion index (is 9) should be <= len (is 3)")] fn try_inert_panics_if_oob() { - let mut bounded: BoundedVec = vec![1, 2, 3].try_into().unwrap(); + let mut bounded: BoundedVec> = vec![1, 2, 3].try_into().unwrap(); bounded.try_insert(9, 0).unwrap(); } #[test] fn try_push_works() { - let mut bounded: BoundedVec = vec![1, 2, 3].try_into().unwrap(); + let mut bounded: BoundedVec> = vec![1, 2, 3].try_into().unwrap(); bounded.try_push(0).unwrap(); assert_eq!(*bounded, vec![1, 2, 3, 0]); @@ -421,7 +417,7 @@ pub mod test { #[test] fn deref_coercion_works() { - let bounded: BoundedVec = vec![1, 2, 3].try_into().unwrap(); + let bounded: BoundedVec> = vec![1, 2, 3].try_into().unwrap(); // these methods come from deref-ed vec. assert_eq!(bounded.len(), 3); assert!(bounded.iter().next().is_some()); @@ -430,7 +426,7 @@ pub mod test { #[test] fn try_mutate_works() { - let bounded: BoundedVec = vec![1, 2, 3, 4, 5, 6].try_into().unwrap(); + let bounded: BoundedVec> = vec![1, 2, 3, 4, 5, 6].try_into().unwrap(); let bounded = bounded.try_mutate(|v| v.push(7)).unwrap(); assert_eq!(bounded.len(), 7); assert!(bounded.try_mutate(|v| v.push(8)).is_none()); @@ -438,13 +434,13 @@ pub mod test { #[test] fn slice_indexing_works() { - let bounded: BoundedVec = vec![1, 2, 3, 4, 5, 6].try_into().unwrap(); + let bounded: BoundedVec> = vec![1, 2, 3, 4, 5, 6].try_into().unwrap(); assert_eq!(&bounded[0..=2], &[1, 2, 3]); } #[test] fn vec_eq_works() { - let bounded: BoundedVec = vec![1, 2, 3, 4, 5, 6].try_into().unwrap(); + let bounded: BoundedVec> = vec![1, 2, 3, 4, 5, 6].try_into().unwrap(); assert_eq!(bounded, vec![1, 2, 3, 4, 5, 6]); } @@ -452,7 +448,7 @@ pub mod test { fn too_big_vec_fail_to_decode() { let v: Vec = vec![1, 2, 3, 4, 5]; assert_eq!( - BoundedVec::::decode(&mut &v.encode()[..]), + BoundedVec::>::decode(&mut &v.encode()[..]), Err("BoundedVec exceeds its limit".into()), ); } diff --git a/frame/support/src/storage/mod.rs b/frame/support/src/storage/mod.rs index 9217cf4e6d9e..3cfe2bfaa577 100644 --- a/frame/support/src/storage/mod.rs +++ b/frame/support/src/storage/mod.rs @@ -1404,6 +1404,7 @@ mod test { use super::*; use crate::{assert_ok, hash::Identity, Twox128}; use bounded_vec::BoundedVec; + use frame_support::traits::ConstU32; use generator::StorageValue as _; use sp_core::hashing::twox_128; use sp_io::TestExternalities; @@ -1714,22 +1715,17 @@ mod test { }); } - crate::parameter_types! { - pub const Seven: u32 = 7; - pub const Four: u32 = 4; - } - - crate::generate_storage_alias! { Prefix, Foo => Value> } - crate::generate_storage_alias! { Prefix, FooMap => Map<(u32, Twox128), BoundedVec> } + crate::generate_storage_alias! { Prefix, Foo => Value>> } + crate::generate_storage_alias! { Prefix, FooMap => Map<(u32, Twox128), BoundedVec>> } crate::generate_storage_alias! { Prefix, - FooDoubleMap => DoubleMap<(u32, Twox128), (u32, Twox128), BoundedVec> + FooDoubleMap => DoubleMap<(u32, Twox128), (u32, Twox128), BoundedVec>> } #[test] fn try_append_works() { TestExternalities::default().execute_with(|| { - let bounded: WeakBoundedVec = vec![1, 2, 3].try_into().unwrap(); + let bounded: WeakBoundedVec> = vec![1, 2, 3].try_into().unwrap(); Foo::put(bounded); assert_ok!(Foo::try_append(4)); assert_ok!(Foo::try_append(5)); @@ -1740,7 +1736,7 @@ mod test { }); TestExternalities::default().execute_with(|| { - let bounded: BoundedVec = vec![1, 2, 3].try_into().unwrap(); + let bounded: BoundedVec> = vec![1, 2, 3].try_into().unwrap(); FooMap::insert(1, bounded); assert_ok!(FooMap::try_append(1, 4)); @@ -1755,17 +1751,17 @@ mod test { assert_ok!(FooMap::try_append(2, 4)); assert_eq!( FooMap::get(2).unwrap(), - BoundedVec::::try_from(vec![4]).unwrap(), + BoundedVec::>::try_from(vec![4]).unwrap(), ); assert_ok!(FooMap::try_append(2, 5)); assert_eq!( FooMap::get(2).unwrap(), - BoundedVec::::try_from(vec![4, 5]).unwrap(), + BoundedVec::>::try_from(vec![4, 5]).unwrap(), ); }); TestExternalities::default().execute_with(|| { - let bounded: BoundedVec = vec![1, 2, 3].try_into().unwrap(); + let bounded: BoundedVec> = vec![1, 2, 3].try_into().unwrap(); FooDoubleMap::insert(1, 1, bounded); assert_ok!(FooDoubleMap::try_append(1, 1, 4)); @@ -1780,12 +1776,12 @@ mod test { assert_ok!(FooDoubleMap::try_append(2, 1, 4)); assert_eq!( FooDoubleMap::get(2, 1).unwrap(), - BoundedVec::::try_from(vec![4]).unwrap(), + BoundedVec::>::try_from(vec![4]).unwrap(), ); assert_ok!(FooDoubleMap::try_append(2, 1, 5)); assert_eq!( FooDoubleMap::get(2, 1).unwrap(), - BoundedVec::::try_from(vec![4, 5]).unwrap(), + BoundedVec::>::try_from(vec![4, 5]).unwrap(), ); }); } diff --git a/frame/support/src/storage/weak_bounded_vec.rs b/frame/support/src/storage/weak_bounded_vec.rs index 566889f5f192..641b62305393 100644 --- a/frame/support/src/storage/weak_bounded_vec.rs +++ b/frame/support/src/storage/weak_bounded_vec.rs @@ -318,36 +318,32 @@ where pub mod test { use super::*; use crate::Twox128; + use frame_support::traits::ConstU32; use sp_io::TestExternalities; use sp_std::convert::TryInto; - crate::parameter_types! { - pub const Seven: u32 = 7; - pub const Four: u32 = 4; - } - - crate::generate_storage_alias! { Prefix, Foo => Value> } - crate::generate_storage_alias! { Prefix, FooMap => Map<(u32, Twox128), WeakBoundedVec> } + crate::generate_storage_alias! { Prefix, Foo => Value>> } + crate::generate_storage_alias! { Prefix, FooMap => Map<(u32, Twox128), WeakBoundedVec>> } crate::generate_storage_alias! { Prefix, - FooDoubleMap => DoubleMap<(u32, Twox128), (u32, Twox128), WeakBoundedVec> + FooDoubleMap => DoubleMap<(u32, Twox128), (u32, Twox128), WeakBoundedVec>> } #[test] fn try_append_is_correct() { - assert_eq!(WeakBoundedVec::::bound(), 7); + assert_eq!(WeakBoundedVec::>::bound(), 7); } #[test] fn decode_len_works() { TestExternalities::default().execute_with(|| { - let bounded: WeakBoundedVec = vec![1, 2, 3].try_into().unwrap(); + let bounded: WeakBoundedVec> = vec![1, 2, 3].try_into().unwrap(); Foo::put(bounded); assert_eq!(Foo::decode_len().unwrap(), 3); }); TestExternalities::default().execute_with(|| { - let bounded: WeakBoundedVec = vec![1, 2, 3].try_into().unwrap(); + let bounded: WeakBoundedVec> = vec![1, 2, 3].try_into().unwrap(); FooMap::insert(1, bounded); assert_eq!(FooMap::decode_len(1).unwrap(), 3); assert!(FooMap::decode_len(0).is_none()); @@ -355,7 +351,7 @@ pub mod test { }); TestExternalities::default().execute_with(|| { - let bounded: WeakBoundedVec = vec![1, 2, 3].try_into().unwrap(); + let bounded: WeakBoundedVec> = vec![1, 2, 3].try_into().unwrap(); FooDoubleMap::insert(1, 1, bounded); assert_eq!(FooDoubleMap::decode_len(1, 1).unwrap(), 3); assert!(FooDoubleMap::decode_len(2, 1).is_none()); @@ -366,7 +362,7 @@ pub mod test { #[test] fn try_insert_works() { - let mut bounded: WeakBoundedVec = vec![1, 2, 3].try_into().unwrap(); + let mut bounded: WeakBoundedVec> = vec![1, 2, 3].try_into().unwrap(); bounded.try_insert(1, 0).unwrap(); assert_eq!(*bounded, vec![1, 0, 2, 3]); @@ -377,13 +373,13 @@ pub mod test { #[test] #[should_panic(expected = "insertion index (is 9) should be <= len (is 3)")] fn try_inert_panics_if_oob() { - let mut bounded: WeakBoundedVec = vec![1, 2, 3].try_into().unwrap(); + let mut bounded: WeakBoundedVec> = vec![1, 2, 3].try_into().unwrap(); bounded.try_insert(9, 0).unwrap(); } #[test] fn try_push_works() { - let mut bounded: WeakBoundedVec = vec![1, 2, 3].try_into().unwrap(); + let mut bounded: WeakBoundedVec> = vec![1, 2, 3].try_into().unwrap(); bounded.try_push(0).unwrap(); assert_eq!(*bounded, vec![1, 2, 3, 0]); @@ -392,7 +388,7 @@ pub mod test { #[test] fn deref_coercion_works() { - let bounded: WeakBoundedVec = vec![1, 2, 3].try_into().unwrap(); + let bounded: WeakBoundedVec> = vec![1, 2, 3].try_into().unwrap(); // these methods come from deref-ed vec. assert_eq!(bounded.len(), 3); assert!(bounded.iter().next().is_some()); @@ -401,7 +397,7 @@ pub mod test { #[test] fn try_mutate_works() { - let bounded: WeakBoundedVec = vec![1, 2, 3, 4, 5, 6].try_into().unwrap(); + let bounded: WeakBoundedVec> = vec![1, 2, 3, 4, 5, 6].try_into().unwrap(); let bounded = bounded.try_mutate(|v| v.push(7)).unwrap(); assert_eq!(bounded.len(), 7); assert!(bounded.try_mutate(|v| v.push(8)).is_none()); @@ -409,20 +405,20 @@ pub mod test { #[test] fn slice_indexing_works() { - let bounded: WeakBoundedVec = vec![1, 2, 3, 4, 5, 6].try_into().unwrap(); + let bounded: WeakBoundedVec> = vec![1, 2, 3, 4, 5, 6].try_into().unwrap(); assert_eq!(&bounded[0..=2], &[1, 2, 3]); } #[test] fn vec_eq_works() { - let bounded: WeakBoundedVec = vec![1, 2, 3, 4, 5, 6].try_into().unwrap(); + let bounded: WeakBoundedVec> = vec![1, 2, 3, 4, 5, 6].try_into().unwrap(); assert_eq!(bounded, vec![1, 2, 3, 4, 5, 6]); } #[test] fn too_big_succeed_to_decode() { let v: Vec = vec![1, 2, 3, 4, 5]; - let w = WeakBoundedVec::::decode(&mut &v.encode()[..]).unwrap(); + let w = WeakBoundedVec::>::decode(&mut &v.encode()[..]).unwrap(); assert_eq!(v, *w); } } diff --git a/frame/support/test/compile_pass/src/lib.rs b/frame/support/test/compile_pass/src/lib.rs index 06fb6345d3c8..a5586996215e 100644 --- a/frame/support/test/compile_pass/src/lib.rs +++ b/frame/support/test/compile_pass/src/lib.rs @@ -22,7 +22,10 @@ //! This crate tests that `construct_runtime!` expands the pallet parts //! correctly even when frame-support is renamed in Cargo.toml -use frame_support::{construct_runtime, parameter_types}; +use frame_support::{ + construct_runtime, parameter_types, + traits::{ConstU16, ConstU32}, +}; use sp_core::{sr25519, H256}; use sp_runtime::{ create_runtime_str, generic, @@ -48,7 +51,6 @@ pub type Index = u64; parameter_types! { pub const BlockHashCount: BlockNumber = 2400; pub const Version: RuntimeVersion = VERSION; - pub const SS58Prefix: u8 = 0; } impl frame_system::Config for Runtime { @@ -73,9 +75,9 @@ impl frame_system::Config for Runtime { type OnNewAccount = (); type OnKilledAccount = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type MaxConsumers = ConstU32<16>; type SystemWeightInfo = (); - type SS58Prefix = SS58Prefix; + type SS58Prefix = ConstU16<0>; } pub type Header = generic::Header; diff --git a/frame/support/test/tests/instance.rs b/frame/support/test/tests/instance.rs index 809edae14f80..5677b9ac14da 100644 --- a/frame/support/test/tests/instance.rs +++ b/frame/support/test/tests/instance.rs @@ -24,8 +24,7 @@ use frame_support::{ PalletStorageMetadata, StorageEntryMetadata, StorageEntryModifier, StorageEntryType, StorageHasher, }, - parameter_types, - traits::Get, + traits::{ConstU32, Get}, Parameter, StorageDoubleMap, StorageMap, StorageValue, }; use scale_info::TypeInfo; @@ -229,20 +228,16 @@ mod module3 { } } -parameter_types! { - pub const SomeValue: u32 = 100; -} - impl module1::Config for Runtime { type Event = Event; type Origin = Origin; - type SomeParameter = SomeValue; + type SomeParameter = ConstU32<100>; type GenericType = u32; } impl module1::Config for Runtime { type Event = Event; type Origin = Origin; - type SomeParameter = SomeValue; + type SomeParameter = ConstU32<100>; type GenericType = u32; } impl module2::Config for Runtime { diff --git a/frame/support/test/tests/pallet.rs b/frame/support/test/tests/pallet.rs index e9c6fe8be560..e57c3466e7ef 100644 --- a/frame/support/test/tests/pallet.rs +++ b/frame/support/test/tests/pallet.rs @@ -19,8 +19,8 @@ use frame_support::{ dispatch::{Parameter, UnfilteredDispatchable}, storage::unhashed, traits::{ - GetCallName, GetStorageVersion, OnFinalize, OnGenesis, OnInitialize, OnRuntimeUpgrade, - PalletInfoAccess, StorageVersion, + ConstU32, GetCallName, GetStorageVersion, OnFinalize, OnGenesis, OnInitialize, + OnRuntimeUpgrade, PalletInfoAccess, StorageVersion, }, weights::{DispatchClass, DispatchInfo, GetDispatchInfo, Pays, RuntimeDbWeight}, }; @@ -536,10 +536,7 @@ pub mod pallet4 { } frame_support::parameter_types!( - pub const MyGetParam: u32 = 10; - pub const MyGetParam2: u32 = 11; pub const MyGetParam3: u32 = 12; - pub const BlockHashCount: u32 = 250; ); impl frame_system::Config for Runtime { @@ -554,7 +551,7 @@ impl frame_system::Config for Runtime { type Lookup = sp_runtime::traits::IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU32<250>; type BlockWeights = (); type BlockLength = (); type DbWeight = (); @@ -566,12 +563,12 @@ impl frame_system::Config for Runtime { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type MaxConsumers = ConstU32<16>; } impl pallet::Config for Runtime { type Event = Event; - type MyGetParam = MyGetParam; - type MyGetParam2 = MyGetParam2; + type MyGetParam = ConstU32<10>; + type MyGetParam2 = ConstU32<11>; type MyGetParam3 = MyGetParam3; type Balance = u64; } diff --git a/frame/support/test/tests/pallet_compatibility.rs b/frame/support/test/tests/pallet_compatibility.rs index 0cd6a6e59cff..b1ed08051f24 100644 --- a/frame/support/test/tests/pallet_compatibility.rs +++ b/frame/support/test/tests/pallet_compatibility.rs @@ -15,6 +15,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +use frame_support::traits::{ConstU32, ConstU64}; + pub trait SomeAssociation { type A: frame_support::dispatch::Parameter + Default; } @@ -217,11 +219,6 @@ pub mod pallet { } } -frame_support::parameter_types!( - pub const SomeConst: u64 = 10; - pub const BlockHashCount: u32 = 250; -); - impl frame_system::Config for Runtime { type BaseCallFilter = frame_support::traits::Everything; type Origin = Origin; @@ -234,7 +231,7 @@ impl frame_system::Config for Runtime { type Lookup = sp_runtime::traits::IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU32<250>; type BlockWeights = (); type BlockLength = (); type DbWeight = (); @@ -246,16 +243,16 @@ impl frame_system::Config for Runtime { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type MaxConsumers = ConstU32<16>; } impl pallet::Config for Runtime { type Event = Event; - type SomeConst = SomeConst; + type SomeConst = ConstU64<10>; type Balance = u64; } impl pallet_old::Config for Runtime { type Event = Event; - type SomeConst = SomeConst; + type SomeConst = ConstU64<10>; type Balance = u64; } diff --git a/frame/support/test/tests/pallet_compatibility_instance.rs b/frame/support/test/tests/pallet_compatibility_instance.rs index 16f5e16cb873..81e16ee3624f 100644 --- a/frame/support/test/tests/pallet_compatibility_instance.rs +++ b/frame/support/test/tests/pallet_compatibility_instance.rs @@ -15,6 +15,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +use frame_support::traits::{ConstU32, ConstU64}; + mod pallet_old { use frame_support::{ decl_error, decl_event, decl_module, decl_storage, traits::Get, weights::Weight, Parameter, @@ -197,11 +199,6 @@ pub mod pallet { } } -frame_support::parameter_types!( - pub const SomeConst: u64 = 10; - pub const BlockHashCount: u32 = 250; -); - impl frame_system::Config for Runtime { type BlockWeights = (); type BlockLength = (); @@ -217,7 +214,7 @@ impl frame_system::Config for Runtime { type Lookup = sp_runtime::traits::IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU32<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = (); @@ -226,36 +223,36 @@ impl frame_system::Config for Runtime { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type MaxConsumers = ConstU32<16>; } impl pallet::Config for Runtime { type Event = Event; - type SomeConst = SomeConst; + type SomeConst = ConstU64<10>; type Balance = u64; } impl pallet::Config for Runtime { type Event = Event; - type SomeConst = SomeConst; + type SomeConst = ConstU64<10>; type Balance = u64; } impl pallet::Config for Runtime { type Event = Event; - type SomeConst = SomeConst; + type SomeConst = ConstU64<10>; type Balance = u64; } impl pallet_old::Config for Runtime { type Event = Event; - type SomeConst = SomeConst; + type SomeConst = ConstU64<10>; type Balance = u64; } impl pallet_old::Config for Runtime { type Event = Event; - type SomeConst = SomeConst; + type SomeConst = ConstU64<10>; type Balance = u64; } impl pallet_old::Config for Runtime { type Event = Event; - type SomeConst = SomeConst; + type SomeConst = ConstU64<10>; type Balance = u64; } diff --git a/frame/support/test/tests/pallet_instance.rs b/frame/support/test/tests/pallet_instance.rs index 9fd748eb332c..740bfe51d439 100644 --- a/frame/support/test/tests/pallet_instance.rs +++ b/frame/support/test/tests/pallet_instance.rs @@ -18,7 +18,7 @@ use frame_support::{ dispatch::UnfilteredDispatchable, storage::unhashed, - traits::{GetCallName, OnFinalize, OnGenesis, OnInitialize, OnRuntimeUpgrade}, + traits::{ConstU32, GetCallName, OnFinalize, OnGenesis, OnInitialize, OnRuntimeUpgrade}, weights::{DispatchClass, DispatchInfo, GetDispatchInfo, Pays}, }; use sp_io::{ @@ -245,11 +245,6 @@ pub mod pallet2 { } } -frame_support::parameter_types!( - pub const MyGetParam: u32 = 10; - pub const BlockHashCount: u32 = 250; -); - impl frame_system::Config for Runtime { type BaseCallFilter = frame_support::traits::Everything; type Origin = Origin; @@ -262,7 +257,7 @@ impl frame_system::Config for Runtime { type Lookup = sp_runtime::traits::IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU32<250>; type BlockWeights = (); type BlockLength = (); type DbWeight = (); @@ -274,16 +269,16 @@ impl frame_system::Config for Runtime { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type MaxConsumers = ConstU32<16>; } impl pallet::Config for Runtime { type Event = Event; - type MyGetParam = MyGetParam; + type MyGetParam = ConstU32<10>; type Balance = u64; } impl pallet::Config for Runtime { type Event = Event; - type MyGetParam = MyGetParam; + type MyGetParam = ConstU32<10>; type Balance = u64; } impl pallet2::Config for Runtime { diff --git a/frame/support/test/tests/pallet_with_name_trait_is_valid.rs b/frame/support/test/tests/pallet_with_name_trait_is_valid.rs index 170e515740b3..128960fdb1c3 100644 --- a/frame/support/test/tests/pallet_with_name_trait_is_valid.rs +++ b/frame/support/test/tests/pallet_with_name_trait_is_valid.rs @@ -97,7 +97,7 @@ impl frame_support::inherent::ProvideInherent for Module { mod tests { use crate as pallet_test; - use frame_support::parameter_types; + use frame_support::traits::ConstU64; type SignedExtra = ( frame_system::CheckEra, @@ -124,10 +124,6 @@ mod tests { } ); - parameter_types! { - pub const BlockHashCount: u64 = 250; - } - impl frame_system::Config for Runtime { type BaseCallFilter = frame_support::traits::Everything; type Origin = Origin; @@ -140,7 +136,7 @@ mod tests { type Lookup = sp_runtime::traits::IdentityLookup; type Header = TestHeader; type Event = (); - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type DbWeight = (); type BlockWeights = (); type BlockLength = (); diff --git a/frame/system/benches/bench.rs b/frame/system/benches/bench.rs index 0d513ff599d5..f1d819cb6525 100644 --- a/frame/system/benches/bench.rs +++ b/frame/system/benches/bench.rs @@ -16,6 +16,7 @@ // limitations under the License. use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use frame_support::traits::{ConstU32, ConstU64}; use sp_core::H256; use sp_runtime::{ testing::Header, @@ -58,7 +59,6 @@ frame_support::construct_runtime!( ); frame_support::parameter_types! { - pub const BlockHashCount: u64 = 250; pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::with_sensible_defaults( 4 * 1024 * 1024, Perbill::from_percent(75), @@ -83,7 +83,7 @@ impl frame_system::Config for Runtime { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = (); @@ -92,7 +92,7 @@ impl frame_system::Config for Runtime { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type MaxConsumers = ConstU32<16>; } impl module::Config for Runtime { diff --git a/frame/system/src/mock.rs b/frame/system/src/mock.rs index de89324ec9fb..d8d9e7323aed 100644 --- a/frame/system/src/mock.rs +++ b/frame/system/src/mock.rs @@ -16,7 +16,10 @@ // limitations under the License. use crate::{self as frame_system, *}; -use frame_support::parameter_types; +use frame_support::{ + parameter_types, + traits::{ConstU32, ConstU64}, +}; use sp_core::H256; use sp_runtime::{ testing::Header, @@ -42,7 +45,6 @@ const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); const MAX_BLOCK_WEIGHT: Weight = 1024; parameter_types! { - pub const BlockHashCount: u64 = 10; pub Version: RuntimeVersion = RuntimeVersion { spec_name: sp_version::create_runtime_str!("test"), impl_name: sp_version::create_runtime_str!("system-test"), @@ -101,7 +103,7 @@ impl Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<10>; type DbWeight = DbWeight; type Version = Version; type PalletInfo = PalletInfo; @@ -111,7 +113,7 @@ impl Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type MaxConsumers = ConstU32<16>; } pub type SysEvent = frame_system::Event; diff --git a/frame/timestamp/src/lib.rs b/frame/timestamp/src/lib.rs index ae9a3b5f69ad..0d2c3f385d17 100644 --- a/frame/timestamp/src/lib.rs +++ b/frame/timestamp/src/lib.rs @@ -316,7 +316,10 @@ mod tests { use super::*; use crate as pallet_timestamp; - use frame_support::{assert_ok, parameter_types}; + use frame_support::{ + assert_ok, parameter_types, + traits::{ConstU32, ConstU64}, + }; use sp_core::H256; use sp_io::TestExternalities; use sp_runtime::{ @@ -344,7 +347,6 @@ mod tests { ); parameter_types! { - pub const BlockHashCount: u64 = 250; pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max(1024); } @@ -363,7 +365,7 @@ mod tests { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = (); @@ -372,15 +374,13 @@ mod tests { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; - } - parameter_types! { - pub const MinimumPeriod: u64 = 5; + type MaxConsumers = ConstU32<16>; } + impl Config for Test { type Moment = u64; type OnTimestampSet = (); - type MinimumPeriod = MinimumPeriod; + type MinimumPeriod = ConstU64<5>; type WeightInfo = (); } diff --git a/frame/tips/src/tests.rs b/frame/tips/src/tests.rs index 7d6a71734731..5bab523b0393 100644 --- a/frame/tips/src/tests.rs +++ b/frame/tips/src/tests.rs @@ -30,8 +30,12 @@ use sp_runtime::{ use sp_storage::Storage; use frame_support::{ - assert_noop, assert_ok, pallet_prelude::GenesisBuild, parameter_types, - storage::StoragePrefixedMap, traits::SortedMembers, weights::Weight, PalletId, + assert_noop, assert_ok, + pallet_prelude::GenesisBuild, + parameter_types, + storage::StoragePrefixedMap, + traits::{ConstU32, ConstU64, SortedMembers}, + PalletId, }; use super::*; @@ -54,9 +58,6 @@ frame_support::construct_runtime!( ); parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: Weight = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Config for Test { @@ -74,7 +75,7 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; @@ -83,11 +84,9 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; -} -parameter_types! { - pub const ExistentialDeposit: u64 = 1; + type MaxConsumers = ConstU32<16>; } + impl pallet_balances::Config for Test { type MaxLocks = (); type MaxReserves = (); @@ -95,7 +94,7 @@ impl pallet_balances::Config for Test { type Balance = u64; type Event = Event; type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; + type ExistentialDeposit = ConstU64<1>; type AccountStore = System; type WeightInfo = (); } @@ -126,13 +125,8 @@ impl ContainsLengthBound for TenToFourteen { } parameter_types! { pub const ProposalBond: Permill = Permill::from_percent(5); - pub const ProposalBondMinimum: u64 = 1; - pub const SpendPeriod: u64 = 2; pub const Burn: Permill = Permill::from_percent(50); - pub const DataDepositPerByte: u64 = 1; pub const TreasuryPalletId: PalletId = PalletId(*b"py/trsry"); - pub const MaximumReasonLength: u32 = 16384; - pub const MaxApprovals: u32 = 100; } impl pallet_treasury::Config for Test { type PalletId = TreasuryPalletId; @@ -142,26 +136,24 @@ impl pallet_treasury::Config for Test { type Event = Event; type OnSlash = (); type ProposalBond = ProposalBond; - type ProposalBondMinimum = ProposalBondMinimum; - type SpendPeriod = SpendPeriod; + type ProposalBondMinimum = ConstU64<1>; + type SpendPeriod = ConstU64<2>; type Burn = Burn; type BurnDestination = (); // Just gets burned. type WeightInfo = (); type SpendFunds = (); - type MaxApprovals = MaxApprovals; + type MaxApprovals = ConstU32<100>; } parameter_types! { - pub const TipCountdown: u64 = 1; pub const TipFindersFee: Percent = Percent::from_percent(20); - pub const TipReportDepositBase: u64 = 1; } impl Config for Test { - type MaximumReasonLength = MaximumReasonLength; + type MaximumReasonLength = ConstU32<16384>; type Tippers = TenToFourteen; - type TipCountdown = TipCountdown; + type TipCountdown = ConstU64<1>; type TipFindersFee = TipFindersFee; - type TipReportDepositBase = TipReportDepositBase; - type DataDepositPerByte = DataDepositPerByte; + type TipReportDepositBase = ConstU64<1>; + type DataDepositPerByte = ConstU64<1>; type Event = Event; type WeightInfo = (); } diff --git a/frame/transaction-payment/asset-tx-payment/src/tests.rs b/frame/transaction-payment/asset-tx-payment/src/tests.rs index c6c60cfe237d..6292829d2148 100644 --- a/frame/transaction-payment/asset-tx-payment/src/tests.rs +++ b/frame/transaction-payment/asset-tx-payment/src/tests.rs @@ -20,7 +20,7 @@ use frame_support::{ assert_ok, pallet_prelude::*, parameter_types, - traits::{fungibles::Mutate, FindAuthor}, + traits::{fungibles::Mutate, ConstU32, ConstU64, ConstU8, FindAuthor}, weights::{ DispatchClass, DispatchInfo, PostDispatchInfo, Weight, WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, @@ -83,7 +83,6 @@ impl Get for BlockWeights { } parameter_types! { - pub const BlockHashCount: u64 = 250; pub static TransactionByteFee: u64 = 1; pub static WeightToFee: u64 = 1; } @@ -103,7 +102,7 @@ impl frame_system::Config for Runtime { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; @@ -112,23 +111,22 @@ impl frame_system::Config for Runtime { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type MaxConsumers = ConstU32<16>; } parameter_types! { pub const ExistentialDeposit: u64 = 10; - pub const MaxReserves: u32 = 50; } impl pallet_balances::Config for Runtime { type Balance = Balance; type Event = Event; type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; + type ExistentialDeposit = ConstU64<10>; type AccountStore = System; type MaxLocks = (); type WeightInfo = (); - type MaxReserves = MaxReserves; + type MaxReserves = ConstU32<50>; type ReserveIdentifier = [u8; 8]; } @@ -145,22 +143,12 @@ impl WeightToFeePolynomial for WeightToFee { } } -parameter_types! { - pub const OperationalFeeMultiplier: u8 = 5; -} - impl pallet_transaction_payment::Config for Runtime { type OnChargeTransaction = CurrencyAdapter; type TransactionByteFee = TransactionByteFee; type WeightToFee = WeightToFee; type FeeMultiplierUpdate = (); - type OperationalFeeMultiplier = OperationalFeeMultiplier; -} - -parameter_types! { - pub const AssetDeposit: u64 = 2; - pub const MetadataDeposit: u64 = 0; - pub const StringLimit: u32 = 20; + type OperationalFeeMultiplier = ConstU8<5>; } impl pallet_assets::Config for Runtime { @@ -169,12 +157,12 @@ impl pallet_assets::Config for Runtime { type AssetId = u32; type Currency = Balances; type ForceOrigin = EnsureRoot; - type AssetDeposit = AssetDeposit; - type AssetAccountDeposit = frame_support::traits::ConstU64<2>; - type MetadataDepositBase = MetadataDeposit; - type MetadataDepositPerByte = MetadataDeposit; - type ApprovalDeposit = MetadataDeposit; - type StringLimit = StringLimit; + type AssetDeposit = ConstU64<2>; + type AssetAccountDeposit = ConstU64<2>; + type MetadataDepositBase = ConstU64<0>; + type MetadataDepositPerByte = ConstU64<0>; + type ApprovalDeposit = ConstU64<0>; + type StringLimit = ConstU32<20>; type Freezer = (); type Extra = (); type WeightInfo = (); diff --git a/frame/transaction-payment/src/lib.rs b/frame/transaction-payment/src/lib.rs index c7ccdafc7828..fa8b0e9be0c1 100644 --- a/frame/transaction-payment/src/lib.rs +++ b/frame/transaction-payment/src/lib.rs @@ -789,7 +789,7 @@ mod tests { use frame_support::{ assert_noop, assert_ok, parameter_types, - traits::{Currency, Imbalance, OnUnbalanced}, + traits::{ConstU32, ConstU64, Currency, Imbalance, OnUnbalanced}, weights::{ DispatchClass, DispatchInfo, GetDispatchInfo, PostDispatchInfo, Weight, WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, @@ -836,7 +836,6 @@ mod tests { } parameter_types! { - pub const BlockHashCount: u64 = 250; pub static TransactionByteFee: u64 = 1; pub static WeightToFee: u64 = 1; pub static OperationalFeeMultiplier: u8 = 5; @@ -857,7 +856,7 @@ mod tests { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; @@ -866,18 +865,14 @@ mod tests { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; - } - - parameter_types! { - pub const ExistentialDeposit: u64 = 1; + type MaxConsumers = ConstU32<16>; } impl pallet_balances::Config for Runtime { type Balance = u64; type Event = Event; type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; + type ExistentialDeposit = ConstU64<1>; type AccountStore = System; type MaxLocks = (); type MaxReserves = (); diff --git a/frame/transaction-storage/src/mock.rs b/frame/transaction-storage/src/mock.rs index 49b81348e7d4..6356312ca500 100644 --- a/frame/transaction-storage/src/mock.rs +++ b/frame/transaction-storage/src/mock.rs @@ -19,10 +19,7 @@ use crate as pallet_transaction_storage; use crate::TransactionStorageProof; -use frame_support::{ - parameter_types, - traits::{OnFinalize, OnInitialize}, -}; +use frame_support::traits::{ConstU16, ConstU32, ConstU64, OnFinalize, OnInitialize}; use sp_core::H256; use sp_runtime::{ testing::Header, @@ -48,11 +45,6 @@ frame_support::construct_runtime!( } ); -parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const SS58Prefix: u8 = 42; -} - impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); @@ -67,7 +59,7 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type DbWeight = (); type Version = (); type PalletInfo = PalletInfo; @@ -75,20 +67,16 @@ impl frame_system::Config for Test { type OnNewAccount = (); type OnKilledAccount = (); type SystemWeightInfo = (); - type SS58Prefix = SS58Prefix; + type SS58Prefix = ConstU16<42>; type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; -} - -parameter_types! { - pub const ExistentialDeposit: u64 = 1; + type MaxConsumers = ConstU32<16>; } impl pallet_balances::Config for Test { type Balance = u64; type DustRemoval = (); type Event = Event; - type ExistentialDeposit = ExistentialDeposit; + type ExistentialDeposit = ConstU64<1>; type AccountStore = System; type WeightInfo = (); type MaxLocks = (); diff --git a/frame/treasury/src/tests.rs b/frame/treasury/src/tests.rs index c2b41e716523..765f71f5dae8 100644 --- a/frame/treasury/src/tests.rs +++ b/frame/treasury/src/tests.rs @@ -28,7 +28,10 @@ use sp_runtime::{ }; use frame_support::{ - assert_noop, assert_ok, pallet_prelude::GenesisBuild, parameter_types, traits::OnInitialize, + assert_noop, assert_ok, + pallet_prelude::GenesisBuild, + parameter_types, + traits::{ConstU32, ConstU64, OnInitialize}, PalletId, }; @@ -51,7 +54,6 @@ frame_support::construct_runtime!( ); parameter_types! { - pub const BlockHashCount: u64 = 250; pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max(1024); } @@ -70,7 +72,7 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; @@ -79,10 +81,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; -} -parameter_types! { - pub const ExistentialDeposit: u64 = 1; + type MaxConsumers = ConstU32<16>; } impl pallet_balances::Config for Test { type MaxLocks = (); @@ -91,7 +90,7 @@ impl pallet_balances::Config for Test { type Balance = u64; type Event = Event; type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; + type ExistentialDeposit = ConstU64<1>; type AccountStore = System; type WeightInfo = (); } @@ -100,8 +99,6 @@ thread_local! { } parameter_types! { pub const ProposalBond: Permill = Permill::from_percent(5); - pub const ProposalBondMinimum: u64 = 1; - pub const SpendPeriod: u64 = 2; pub const Burn: Permill = Permill::from_percent(50); pub const TreasuryPalletId: PalletId = PalletId(*b"py/trsry"); pub const BountyUpdatePeriod: u32 = 20; @@ -117,8 +114,8 @@ impl Config for Test { type Event = Event; type OnSlash = (); type ProposalBond = ProposalBond; - type ProposalBondMinimum = ProposalBondMinimum; - type SpendPeriod = SpendPeriod; + type ProposalBondMinimum = ConstU64<1>; + type SpendPeriod = ConstU64<2>; type Burn = Burn; type BurnDestination = (); // Just gets burned. type WeightInfo = (); diff --git a/frame/uniques/src/mock.rs b/frame/uniques/src/mock.rs index f65f69209b9e..679adf0424cf 100644 --- a/frame/uniques/src/mock.rs +++ b/frame/uniques/src/mock.rs @@ -20,7 +20,10 @@ use super::*; use crate as pallet_uniques; -use frame_support::{construct_runtime, parameter_types}; +use frame_support::{ + construct_runtime, + traits::{ConstU32, ConstU64}, +}; use sp_core::H256; use sp_runtime::{ testing::Header, @@ -42,9 +45,6 @@ construct_runtime!( } ); -parameter_types! { - pub const BlockHashCount: u64 = 250; -} impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); @@ -59,7 +59,7 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type DbWeight = (); type Version = (); type PalletInfo = PalletInfo; @@ -69,51 +69,35 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; -} - -parameter_types! { - pub const ExistentialDeposit: u64 = 1; - pub const MaxReserves: u32 = 50; + type MaxConsumers = ConstU32<16>; } impl pallet_balances::Config for Test { type Balance = u64; type DustRemoval = (); type Event = Event; - type ExistentialDeposit = ExistentialDeposit; + type ExistentialDeposit = ConstU64<1>; type AccountStore = System; type WeightInfo = (); type MaxLocks = (); - type MaxReserves = MaxReserves; + type MaxReserves = ConstU32<50>; type ReserveIdentifier = [u8; 8]; } -parameter_types! { - pub const ClassDeposit: u64 = 2; - pub const InstanceDeposit: u64 = 1; - pub const KeyLimit: u32 = 50; - pub const ValueLimit: u32 = 50; - pub const StringLimit: u32 = 50; - pub const MetadataDepositBase: u64 = 1; - pub const AttributeDepositBase: u64 = 1; - pub const MetadataDepositPerByte: u64 = 1; -} - impl Config for Test { type Event = Event; type ClassId = u32; type InstanceId = u32; type Currency = Balances; type ForceOrigin = frame_system::EnsureRoot; - type ClassDeposit = ClassDeposit; - type InstanceDeposit = InstanceDeposit; - type MetadataDepositBase = MetadataDepositBase; - type AttributeDepositBase = AttributeDepositBase; - type DepositPerByte = MetadataDepositPerByte; - type StringLimit = StringLimit; - type KeyLimit = KeyLimit; - type ValueLimit = ValueLimit; + type ClassDeposit = ConstU64<2>; + type InstanceDeposit = ConstU64<1>; + type MetadataDepositBase = ConstU64<1>; + type AttributeDepositBase = ConstU64<1>; + type DepositPerByte = ConstU64<1>; + type StringLimit = ConstU32<50>; + type KeyLimit = ConstU32<50>; + type ValueLimit = ConstU32<50>; type WeightInfo = (); } diff --git a/frame/utility/src/tests.rs b/frame/utility/src/tests.rs index 169ac6cfff89..11b63254eb40 100644 --- a/frame/utility/src/tests.rs +++ b/frame/utility/src/tests.rs @@ -26,7 +26,7 @@ use frame_support::{ assert_err_ignore_postinfo, assert_noop, assert_ok, dispatch::{DispatchError, DispatchErrorWithPostInfo, Dispatchable}, parameter_types, storage, - traits::Contains, + traits::{ConstU32, ConstU64, Contains}, weights::{Pays, Weight}, }; use sp_core::H256; @@ -99,7 +99,6 @@ frame_support::construct_runtime!( ); parameter_types! { - pub const BlockHashCount: u64 = 250; pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max(Weight::max_value()); } @@ -118,7 +117,7 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; @@ -127,11 +126,9 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; -} -parameter_types! { - pub const ExistentialDeposit: u64 = 1; + type MaxConsumers = ConstU32<16>; } + impl pallet_balances::Config for Test { type MaxLocks = (); type MaxReserves = (); @@ -139,7 +136,7 @@ impl pallet_balances::Config for Test { type Balance = u64; type DustRemoval = (); type Event = Event; - type ExistentialDeposit = ExistentialDeposit; + type ExistentialDeposit = ConstU64<1>; type AccountStore = System; type WeightInfo = (); } diff --git a/frame/vesting/src/mock.rs b/frame/vesting/src/mock.rs index 1e04875a7e07..2176716bf340 100644 --- a/frame/vesting/src/mock.rs +++ b/frame/vesting/src/mock.rs @@ -15,7 +15,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -use frame_support::parameter_types; +use frame_support::{ + parameter_types, + traits::{ConstU32, ConstU64}, +}; use sp_core::H256; use sp_runtime::{ testing::Header, @@ -41,7 +44,6 @@ frame_support::construct_runtime!( ); parameter_types! { - pub const BlockHashCount: u64 = 250; pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max(1024); } @@ -49,7 +51,7 @@ impl frame_system::Config for Test { type AccountData = pallet_balances::AccountData; type AccountId = u64; type BaseCallFilter = frame_support::traits::Everything; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type BlockLength = (); type BlockNumber = u64; type BlockWeights = (); @@ -71,16 +73,14 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type Version = (); } -parameter_types! { - pub const MaxLocks: u32 = 10; -} + impl pallet_balances::Config for Test { type AccountStore = System; type Balance = u64; type DustRemoval = (); type Event = Event; type ExistentialDeposit = ExistentialDeposit; - type MaxLocks = MaxLocks; + type MaxLocks = ConstU32<10>; type MaxReserves = (); type ReserveIdentifier = [u8; 8]; type WeightInfo = (); diff --git a/test-utils/runtime/src/lib.rs b/test-utils/runtime/src/lib.rs index 7b78880c2c3b..03e39be324e9 100644 --- a/test-utils/runtime/src/lib.rs +++ b/test-utils/runtime/src/lib.rs @@ -38,7 +38,7 @@ use trie_db::{Trie, TrieMut}; use cfg_if::cfg_if; use frame_support::{ parameter_types, - traits::{CrateVersion, KeyOwnerProofSystem}, + traits::{ConstU32, ConstU64, CrateVersion, KeyOwnerProofSystem}, weights::RuntimeDbWeight, }; use frame_system::limits::{BlockLength, BlockWeights}; @@ -556,7 +556,6 @@ impl frame_support::traits::PalletInfo for Runtime { parameter_types! { pub const BlockHashCount: BlockNumber = 2400; - pub const MinimumPeriod: u64 = 5; pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight { read: 100, write: 1000, @@ -591,26 +590,24 @@ impl frame_system::Config for Runtime { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type MaxConsumers = ConstU32<16>; } impl pallet_timestamp::Config for Runtime { /// A timestamp: milliseconds since the unix epoch. type Moment = u64; type OnTimestampSet = (); - type MinimumPeriod = MinimumPeriod; + type MinimumPeriod = ConstU64<5>; type WeightInfo = (); } parameter_types! { pub const EpochDuration: u64 = 6; - pub const ExpectedBlockTime: u64 = 10_000; - pub const MaxAuthorities: u32 = 10; } impl pallet_babe::Config for Runtime { type EpochDuration = EpochDuration; - type ExpectedBlockTime = ExpectedBlockTime; + type ExpectedBlockTime = ConstU64<10_000>; // there is no actual runtime in this test-runtime, so testing crates // are manually adding the digests. normally in this situation you'd use // pallet_babe::SameAuthoritiesForever. @@ -630,7 +627,7 @@ impl pallet_babe::Config for Runtime { type HandleEquivocation = (); type WeightInfo = (); - type MaxAuthorities = MaxAuthorities; + type MaxAuthorities = ConstU32<10>; } /// Adds one to the given input and returns the final result. From 7f68a8be62433949f04abc3ab9d98a10dab95c7d Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Thu, 16 Dec 2021 07:24:28 +0100 Subject: [PATCH 301/695] move generics of election trait to associated types (#10475) * move generics of election trait to associated types * fix doctest --- frame/bags-list/remote-tests/src/snapshot.rs | 7 +- .../src/benchmarking.rs | 2 +- .../election-provider-multi-phase/src/lib.rs | 26 +++--- .../election-provider-multi-phase/src/mock.rs | 8 +- frame/election-provider-support/src/lib.rs | 81 +++++++++++++------ .../election-provider-support/src/onchain.rs | 13 ++- frame/staking/src/pallet/impls.rs | 4 +- frame/staking/src/pallet/mod.rs | 8 +- frame/staking/src/tests.rs | 6 +- 9 files changed, 101 insertions(+), 54 deletions(-) diff --git a/frame/bags-list/remote-tests/src/snapshot.rs b/frame/bags-list/remote-tests/src/snapshot.rs index f05c00cd9a24..78f462e55b8f 100644 --- a/frame/bags-list/remote-tests/src/snapshot.rs +++ b/frame/bags-list/remote-tests/src/snapshot.rs @@ -55,11 +55,8 @@ pub async fn execute ::SortedListProvider::count(), ); - let voters = as ElectionDataProvider< - Runtime::AccountId, - Runtime::BlockNumber, - >>::voters(voter_limit) - .unwrap(); + let voters = + as ElectionDataProvider>::voters(voter_limit).unwrap(); let mut voters_nominator_only = voters .iter() diff --git a/frame/election-provider-multi-phase/src/benchmarking.rs b/frame/election-provider-multi-phase/src/benchmarking.rs index 1e0d3b1e9325..04101f886cec 100644 --- a/frame/election-provider-multi-phase/src/benchmarking.rs +++ b/frame/election-provider-multi-phase/src/benchmarking.rs @@ -289,7 +289,7 @@ frame_benchmarking::benchmarks! { assert!(>::get().is_some()); assert!(>::get().is_some()); }: { - assert_ok!( as ElectionProvider>::elect()); + assert_ok!( as ElectionProvider>::elect()); } verify { assert!(>::queued_solution().is_none()); assert!(>::get().is_none()); diff --git a/frame/election-provider-multi-phase/src/lib.rs b/frame/election-provider-multi-phase/src/lib.rs index 70668dbe9f67..175de0eeb0c6 100644 --- a/frame/election-provider-multi-phase/src/lib.rs +++ b/frame/election-provider-multi-phase/src/lib.rs @@ -139,7 +139,7 @@ //! To generate an emergency solution, one must only provide one argument: [`Supports`]. This is //! essentially a collection of elected winners for the election, and voters who support them. The //! supports can be generated by any means. In the simplest case, it could be manual. For example, -//! in the case of massive network failure or misbehaviour, [`Config::ForceOrigin`] might decide to +//! in the case of massive network failure or misbehavior, [`Config::ForceOrigin`] might decide to //! select only a small number of emergency winners (which would greatly restrict the next validator //! set, if this pallet is used with `pallet-staking`). If the failure is for other technical //! reasons, then a simple and safe way to generate supports is using the staking-miner binary @@ -286,10 +286,7 @@ pub type SolutionTargetIndexOf = as NposSolution>::TargetIndex /// The accuracy of the election, when submitted from offchain. Derived from [`SolutionOf`]. pub type SolutionAccuracyOf = as NposSolution>::Accuracy; /// The fallback election type. -pub type FallbackErrorOf = <::Fallback as ElectionProvider< - ::AccountId, - ::BlockNumber, ->>::Error; +pub type FallbackErrorOf = <::Fallback as ElectionProvider>::Error; /// Configuration for the benchmarks of the pallet. pub trait BenchmarkingConfig { @@ -312,7 +309,9 @@ pub trait BenchmarkingConfig { /// A fallback implementation that transitions the pallet to the emergency phase. pub struct NoFallback(sp_std::marker::PhantomData); -impl ElectionProvider for NoFallback { +impl ElectionProvider for NoFallback { + type AccountId = T::AccountId; + type BlockNumber = T::BlockNumber; type DataProvider = T::DataProvider; type Error = &'static str; @@ -654,7 +653,10 @@ pub mod pallet { type MinerMaxLength: Get; /// Something that will provide the election data. - type DataProvider: ElectionDataProvider; + type DataProvider: ElectionDataProvider< + AccountId = Self::AccountId, + BlockNumber = Self::BlockNumber, + >; /// The solution type. type Solution: codec::Codec @@ -669,8 +671,8 @@ pub mod pallet { /// Configuration for the fallback type Fallback: ElectionProvider< - Self::AccountId, - Self::BlockNumber, + AccountId = Self::AccountId, + BlockNumber = Self::BlockNumber, DataProvider = Self::DataProvider, >; @@ -818,7 +820,7 @@ pub mod pallet { // NOTE that this pallet does not really need to enforce this in runtime. The // solution cannot represent any voters more than `LIMIT` anyhow. assert_eq!( - >::MAXIMUM_VOTES_PER_VOTER, + ::MAXIMUM_VOTES_PER_VOTER, as NposSolution>::LIMIT as u32, ); } @@ -1492,7 +1494,9 @@ impl Pallet { } } -impl ElectionProvider for Pallet { +impl ElectionProvider for Pallet { + type AccountId = T::AccountId; + type BlockNumber = T::BlockNumber; type Error = ElectionError; type DataProvider = T::DataProvider; diff --git a/frame/election-provider-multi-phase/src/mock.rs b/frame/election-provider-multi-phase/src/mock.rs index d686df2a72f6..4e494322b062 100644 --- a/frame/election-provider-multi-phase/src/mock.rs +++ b/frame/election-provider-multi-phase/src/mock.rs @@ -285,7 +285,9 @@ impl onchain::Config for Runtime { } pub struct MockFallback; -impl ElectionProvider for MockFallback { +impl ElectionProvider for MockFallback { + type AccountId = AccountId; + type BlockNumber = u64; type Error = &'static str; type DataProvider = StakingMock; @@ -438,7 +440,9 @@ pub type Extrinsic = sp_runtime::testing::TestXt; pub struct ExtBuilder {} pub struct StakingMock; -impl ElectionDataProvider for StakingMock { +impl ElectionDataProvider for StakingMock { + type AccountId = AccountId; + type BlockNumber = u64; const MAXIMUM_VOTES_PER_VOTER: u32 = ::LIMIT as u32; fn targets(maybe_max_len: Option) -> data_provider::Result> { let targets = Targets::get(); diff --git a/frame/election-provider-support/src/lib.rs b/frame/election-provider-support/src/lib.rs index ac3bfccbbdb5..a4fce64ff1d7 100644 --- a/frame/election-provider-support/src/lib.rs +++ b/frame/election-provider-support/src/lib.rs @@ -90,21 +90,24 @@ //! //! pub trait Config: Sized { //! type ElectionProvider: ElectionProvider< -//! AccountId, -//! BlockNumber, -//! DataProvider = Module, +//! AccountId = AccountId, +//! BlockNumber = BlockNumber, +//! DataProvider = Pallet, //! >; //! } //! -//! pub struct Module(std::marker::PhantomData); +//! pub struct Pallet(std::marker::PhantomData); //! -//! impl ElectionDataProvider for Module { +//! impl ElectionDataProvider for Pallet { +//! type AccountId = AccountId; +//! type BlockNumber = BlockNumber; //! const MAXIMUM_VOTES_PER_VOTER: u32 = 1; +//! //! fn desired_targets() -> data_provider::Result { //! Ok(1) //! } //! fn voters(maybe_max_len: Option) -//! -> data_provider::Result)>> +//! -> data_provider::Result)>> //! { //! Ok(Default::default()) //! } @@ -124,10 +127,12 @@ //! pub struct GenericElectionProvider(std::marker::PhantomData); //! //! pub trait Config { -//! type DataProvider: ElectionDataProvider; +//! type DataProvider: ElectionDataProvider; //! } //! -//! impl ElectionProvider for GenericElectionProvider { +//! impl ElectionProvider for GenericElectionProvider { +//! type AccountId = AccountId; +//! type BlockNumber = BlockNumber; //! type Error = &'static str; //! type DataProvider = T::DataProvider; //! @@ -146,7 +151,7 @@ //! //! struct Runtime; //! impl generic_election_provider::Config for Runtime { -//! type DataProvider = data_provider_mod::Module; +//! type DataProvider = data_provider_mod::Pallet; //! } //! //! impl data_provider_mod::Config for Runtime { @@ -178,7 +183,13 @@ pub mod data_provider { } /// Something that can provide the data to an [`ElectionProvider`]. -pub trait ElectionDataProvider { +pub trait ElectionDataProvider { + /// The account identifier type. + type AccountId; + + /// The block number type. + type BlockNumber; + /// Maximum number of votes per voter that this data provider is providing. const MAXIMUM_VOTES_PER_VOTER: u32; @@ -189,7 +200,7 @@ pub trait ElectionDataProvider { /// /// This should be implemented as a self-weighing function. The implementor should register its /// appropriate weight at the end of execution with the system pallet directly. - fn targets(maybe_max_len: Option) -> data_provider::Result>; + fn targets(maybe_max_len: Option) -> data_provider::Result>; /// All possible voters for the election. /// @@ -202,7 +213,7 @@ pub trait ElectionDataProvider { /// appropriate weight at the end of execution with the system pallet directly. fn voters( maybe_max_len: Option, - ) -> data_provider::Result)>>; + ) -> data_provider::Result)>>; /// The number of targets to elect. /// @@ -216,14 +227,14 @@ pub trait ElectionDataProvider { /// [`ElectionProvider::elect`]. /// /// This is only useful for stateful election providers. - fn next_election_prediction(now: BlockNumber) -> BlockNumber; + fn next_election_prediction(now: Self::BlockNumber) -> Self::BlockNumber; /// Utility function only to be used in benchmarking scenarios, to be implemented optionally, /// else a noop. #[cfg(any(feature = "runtime-benchmarks", test))] fn put_snapshot( - _voters: Vec<(AccountId, VoteWeight, Vec)>, - _targets: Vec, + _voters: Vec<(Self::AccountId, VoteWeight, Vec)>, + _targets: Vec, _target_stake: Option, ) { } @@ -233,22 +244,29 @@ pub trait ElectionDataProvider { /// /// Same as `put_snapshot`, but can add a single voter one by one. #[cfg(any(feature = "runtime-benchmarks", test))] - fn add_voter(_voter: AccountId, _weight: VoteWeight, _targets: Vec) {} + fn add_voter(_voter: Self::AccountId, _weight: VoteWeight, _targets: Vec) {} /// Utility function only to be used in benchmarking scenarios, to be implemented optionally, /// else a noop. /// /// Same as `put_snapshot`, but can add a single voter one by one. #[cfg(any(feature = "runtime-benchmarks", test))] - fn add_target(_target: AccountId) {} + fn add_target(_target: Self::AccountId) {} /// Clear all voters and targets. #[cfg(any(feature = "runtime-benchmarks", test))] fn clear() {} } +/// An election data provider that should only be used for testing. #[cfg(feature = "std")] -impl ElectionDataProvider for () { +pub struct TestDataProvider(sp_std::marker::PhantomData); + +#[cfg(feature = "std")] +impl ElectionDataProvider for TestDataProvider<(AccountId, BlockNumber)> { + type AccountId = AccountId; + type BlockNumber = BlockNumber; + const MAXIMUM_VOTES_PER_VOTER: u32 = 0; fn targets(_maybe_max_len: Option) -> data_provider::Result> { Ok(Default::default()) @@ -271,12 +289,21 @@ impl ElectionDataProvider for () /// This trait only provides an interface to _request_ an election, i.e. /// [`ElectionProvider::elect`]. That data required for the election need to be passed to the /// implemented of this trait through [`ElectionProvider::DataProvider`]. -pub trait ElectionProvider { +pub trait ElectionProvider { + /// The account identifier type. + type AccountId; + + /// The block number type. + type BlockNumber; + /// The error type that is returned by the provider. type Error: Debug; /// The data provider of the election. - type DataProvider: ElectionDataProvider; + type DataProvider: ElectionDataProvider< + AccountId = Self::AccountId, + BlockNumber = Self::BlockNumber, + >; /// Elect a new set of winners. /// @@ -284,16 +311,22 @@ pub trait ElectionProvider { /// /// This should be implemented as a self-weighing function. The implementor should register its /// appropriate weight at the end of execution with the system pallet directly. - fn elect() -> Result, Self::Error>; + fn elect() -> Result, Self::Error>; } +/// An election provider to be used only for testing. #[cfg(feature = "std")] -impl ElectionProvider for () { +pub struct NoElection(sp_std::marker::PhantomData); + +#[cfg(feature = "std")] +impl ElectionProvider for NoElection<(AccountId, BlockNumber)> { + type AccountId = AccountId; + type BlockNumber = BlockNumber; type Error = &'static str; - type DataProvider = (); + type DataProvider = TestDataProvider<(AccountId, BlockNumber)>; fn elect() -> Result, Self::Error> { - Err("<() as ElectionProvider> cannot do anything.") + Err(" cannot do anything.") } } diff --git a/frame/election-provider-support/src/onchain.rs b/frame/election-provider-support/src/onchain.rs index a2eb53edcf84..ce15edd592ad 100644 --- a/frame/election-provider-support/src/onchain.rs +++ b/frame/election-provider-support/src/onchain.rs @@ -62,10 +62,15 @@ pub trait Config: frame_system::Config { /// The accuracy used to compute the election: type Accuracy: PerThing128; /// Something that provides the data for election. - type DataProvider: ElectionDataProvider; + type DataProvider: ElectionDataProvider< + AccountId = Self::AccountId, + BlockNumber = Self::BlockNumber, + >; } -impl ElectionProvider for OnChainSequentialPhragmen { +impl ElectionProvider for OnChainSequentialPhragmen { + type AccountId = T::AccountId; + type BlockNumber = T::BlockNumber; type Error = Error; type DataProvider = T::DataProvider; @@ -160,7 +165,9 @@ mod tests { use crate::data_provider; pub struct DataProvider; - impl ElectionDataProvider for DataProvider { + impl ElectionDataProvider for DataProvider { + type AccountId = AccountId; + type BlockNumber = BlockNumber; const MAXIMUM_VOTES_PER_VOTER: u32 = 2; fn voters( _: Option, diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 6c11e942106a..95af3d223e00 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -844,7 +844,9 @@ impl Pallet { } } -impl ElectionDataProvider> for Pallet { +impl ElectionDataProvider for Pallet { + type AccountId = T::AccountId; + type BlockNumber = BlockNumberFor; const MAXIMUM_VOTES_PER_VOTER: u32 = T::MAX_NOMINATIONS; fn desired_targets() -> data_provider::Result { diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 091df82e2817..d03a6198c7cc 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -79,16 +79,16 @@ pub mod pallet { /// Something that provides the election functionality. type ElectionProvider: frame_election_provider_support::ElectionProvider< - Self::AccountId, - Self::BlockNumber, + AccountId = Self::AccountId, + BlockNumber = Self::BlockNumber, // we only accept an election provider that has staking as data provider. DataProvider = Pallet, >; /// Something that provides the election functionality at genesis. type GenesisElectionProvider: frame_election_provider_support::ElectionProvider< - Self::AccountId, - Self::BlockNumber, + AccountId = Self::AccountId, + BlockNumber = Self::BlockNumber, DataProvider = Pallet, >; diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index aa806d4a15e2..74d5de7bf449 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -4013,7 +4013,7 @@ mod election_data_provider { ExtBuilder::default().build_and_execute(|| { assert_eq!(Staking::nominators(101).unwrap().targets, vec![11, 21]); assert_eq!( - >::voters(None) + ::voters(None) .unwrap() .iter() .find(|x| x.0 == 101) @@ -4028,7 +4028,7 @@ mod election_data_provider { // 11 is gone. start_active_era(2); assert_eq!( - >::voters(None) + ::voters(None) .unwrap() .iter() .find(|x| x.0 == 101) @@ -4040,7 +4040,7 @@ mod election_data_provider { // resubmit and it is back assert_ok!(Staking::nominate(Origin::signed(100), vec![11, 21])); assert_eq!( - >::voters(None) + ::voters(None) .unwrap() .iter() .find(|x| x.0 == 101) From 558e6d9a302518c0035d365351f4991f6e61d96c Mon Sep 17 00:00:00 2001 From: Nazar Mokrynskyi Date: Thu, 16 Dec 2021 12:01:30 +0200 Subject: [PATCH 302/695] Async block import params (#10488) * Make `SimpleSlotWorker::block_import_params()` return function that returns a future * Simplify `SimpleSlotWorker::block_import_params()` to just async method --- client/consensus/aura/src/lib.rs | 91 ++++++++++++++---------------- client/consensus/babe/src/lib.rs | 94 ++++++++++++++----------------- client/consensus/slots/src/lib.rs | 51 ++++++++--------- 3 files changed, 107 insertions(+), 129 deletions(-) diff --git a/client/consensus/aura/src/lib.rs b/client/consensus/aura/src/lib.rs index 0d79e3c4ecf0..ec577b084431 100644 --- a/client/consensus/aura/src/lib.rs +++ b/client/consensus/aura/src/lib.rs @@ -382,58 +382,51 @@ where vec![>::aura_pre_digest(slot)] } - fn block_import_params( + async fn block_import_params( &self, - ) -> Box< - dyn Fn( - B::Header, - &B::Hash, - Vec, - StorageChanges, B>, - Self::Claim, - Self::EpochData, - ) -> Result< - sc_consensus::BlockImportParams>, - sp_consensus::Error, - > + Send - + 'static, + header: B::Header, + header_hash: &B::Hash, + body: Vec, + storage_changes: StorageChanges<>::Transaction, B>, + public: Self::Claim, + _epoch: Self::EpochData, + ) -> Result< + sc_consensus::BlockImportParams>::Transaction>, + sp_consensus::Error, > { - let keystore = self.keystore.clone(); - Box::new(move |header, header_hash, body, storage_changes, public, _epoch| { - // sign the pre-sealed hash of the block and then - // add it to a digest item. - let public_type_pair = public.to_public_crypto_pair(); - let public = public.to_raw_vec(); - let signature = SyncCryptoStore::sign_with( - &*keystore, - as AppKey>::ID, - &public_type_pair, - header_hash.as_ref(), + // sign the pre-sealed hash of the block and then + // add it to a digest item. + let public_type_pair = public.to_public_crypto_pair(); + let public = public.to_raw_vec(); + let signature = SyncCryptoStore::sign_with( + &*self.keystore, + as AppKey>::ID, + &public_type_pair, + header_hash.as_ref(), + ) + .map_err(|e| sp_consensus::Error::CannotSign(public.clone(), e.to_string()))? + .ok_or_else(|| { + sp_consensus::Error::CannotSign( + public.clone(), + "Could not find key in keystore.".into(), ) - .map_err(|e| sp_consensus::Error::CannotSign(public.clone(), e.to_string()))? - .ok_or_else(|| { - sp_consensus::Error::CannotSign( - public.clone(), - "Could not find key in keystore.".into(), - ) - })?; - let signature = signature - .clone() - .try_into() - .map_err(|_| sp_consensus::Error::InvalidSignature(signature, public))?; - - let signature_digest_item = - >::aura_seal(signature); - - let mut import_block = BlockImportParams::new(BlockOrigin::Own, header); - import_block.post_digests.push(signature_digest_item); - import_block.body = Some(body); - import_block.state_action = - StateAction::ApplyChanges(sc_consensus::StorageChanges::Changes(storage_changes)); - import_block.fork_choice = Some(ForkChoiceStrategy::LongestChain); - - Ok(import_block) - }) + })?; + let signature = signature + .clone() + .try_into() + .map_err(|_| sp_consensus::Error::InvalidSignature(signature, public))?; + + let signature_digest_item = + >::aura_seal(signature); + + let mut import_block = BlockImportParams::new(BlockOrigin::Own, header); + import_block.post_digests.push(signature_digest_item); + import_block.body = Some(body); + import_block.state_action = + StateAction::ApplyChanges(sc_consensus::StorageChanges::Changes(storage_changes)); + import_block.fork_choice = Some(ForkChoiceStrategy::LongestChain); + + Ok(import_block) } fn force_authoring(&self) -> bool { diff --git a/client/consensus/babe/src/lib.rs b/client/consensus/babe/src/lib.rs index 168cdff43cda..21c3c883a39d 100644 --- a/client/consensus/babe/src/lib.rs +++ b/client/consensus/babe/src/lib.rs @@ -772,60 +772,52 @@ where vec![::babe_pre_digest(claim.0.clone())] } - fn block_import_params( + async fn block_import_params( &self, - ) -> Box< - dyn Fn( - B::Header, - &B::Hash, - Vec, - StorageChanges, - Self::Claim, - Self::EpochData, - ) -> Result, sp_consensus::Error> - + Send - + 'static, + header: B::Header, + header_hash: &B::Hash, + body: Vec, + storage_changes: StorageChanges<>::Transaction, B>, + (_, public): Self::Claim, + epoch_descriptor: Self::EpochData, + ) -> Result< + sc_consensus::BlockImportParams>::Transaction>, + sp_consensus::Error, > { - let keystore = self.keystore.clone(); - Box::new( - move |header, header_hash, body, storage_changes, (_, public), epoch_descriptor| { - // sign the pre-sealed hash of the block and then - // add it to a digest item. - let public_type_pair = public.clone().into(); - let public = public.to_raw_vec(); - let signature = SyncCryptoStore::sign_with( - &*keystore, - ::ID, - &public_type_pair, - header_hash.as_ref(), - ) - .map_err(|e| sp_consensus::Error::CannotSign(public.clone(), e.to_string()))? - .ok_or_else(|| { - sp_consensus::Error::CannotSign( - public.clone(), - "Could not find key in keystore.".into(), - ) - })?; - let signature: AuthoritySignature = signature - .clone() - .try_into() - .map_err(|_| sp_consensus::Error::InvalidSignature(signature, public))?; - let digest_item = ::babe_seal(signature.into()); - - let mut import_block = BlockImportParams::new(BlockOrigin::Own, header); - import_block.post_digests.push(digest_item); - import_block.body = Some(body); - import_block.state_action = StateAction::ApplyChanges( - sc_consensus::StorageChanges::Changes(storage_changes), - ); - import_block.intermediates.insert( - Cow::from(INTERMEDIATE_KEY), - Box::new(BabeIntermediate:: { epoch_descriptor }) as Box<_>, - ); - - Ok(import_block) - }, + // sign the pre-sealed hash of the block and then + // add it to a digest item. + let public_type_pair = public.clone().into(); + let public = public.to_raw_vec(); + let signature = SyncCryptoStore::sign_with( + &*self.keystore, + ::ID, + &public_type_pair, + header_hash.as_ref(), ) + .map_err(|e| sp_consensus::Error::CannotSign(public.clone(), e.to_string()))? + .ok_or_else(|| { + sp_consensus::Error::CannotSign( + public.clone(), + "Could not find key in keystore.".into(), + ) + })?; + let signature: AuthoritySignature = signature + .clone() + .try_into() + .map_err(|_| sp_consensus::Error::InvalidSignature(signature, public))?; + let digest_item = ::babe_seal(signature.into()); + + let mut import_block = BlockImportParams::new(BlockOrigin::Own, header); + import_block.post_digests.push(digest_item); + import_block.body = Some(body); + import_block.state_action = + StateAction::ApplyChanges(sc_consensus::StorageChanges::Changes(storage_changes)); + import_block.intermediates.insert( + Cow::from(INTERMEDIATE_KEY), + Box::new(BabeIntermediate:: { epoch_descriptor }) as Box<_>, + ); + + Ok(import_block) } fn force_authoring(&self) -> bool { diff --git a/client/consensus/slots/src/lib.rs b/client/consensus/slots/src/lib.rs index ead209ef86a6..3174eacaff4d 100644 --- a/client/consensus/slots/src/lib.rs +++ b/client/consensus/slots/src/lib.rs @@ -144,24 +144,17 @@ pub trait SimpleSlotWorker { fn pre_digest_data(&self, slot: Slot, claim: &Self::Claim) -> Vec; /// Returns a function which produces a `BlockImportParams`. - fn block_import_params( + async fn block_import_params( &self, - ) -> Box< - dyn Fn( - B::Header, - &B::Hash, - Vec, - StorageChanges<>::Transaction, B>, - Self::Claim, - Self::EpochData, - ) -> Result< - sc_consensus::BlockImportParams< - B, - >::Transaction, - >, - sp_consensus::Error, - > + Send - + 'static, + header: B::Header, + header_hash: &B::Hash, + body: Vec, + storage_changes: StorageChanges<>::Transaction, B>, + public: Self::Claim, + epoch: Self::EpochData, + ) -> Result< + sc_consensus::BlockImportParams>::Transaction>, + sp_consensus::Error, >; /// Whether to force authoring if offline. @@ -342,23 +335,23 @@ pub trait SimpleSlotWorker { }, }; - let block_import_params_maker = self.block_import_params(); - let block_import = self.block_import(); - let (block, storage_proof) = (proposal.block, proposal.proof); let (header, body) = block.deconstruct(); let header_num = *header.number(); let header_hash = header.hash(); let parent_hash = *header.parent_hash(); - let block_import_params = match block_import_params_maker( - header, - &header_hash, - body.clone(), - proposal.storage_changes, - claim, - epoch_data, - ) { + let block_import_params = match self + .block_import_params( + header, + &header_hash, + body.clone(), + proposal.storage_changes, + claim, + epoch_data, + ) + .await + { Ok(bi) => bi, Err(err) => { warn!(target: logging_target, "Failed to create block import params: {:?}", err); @@ -385,7 +378,7 @@ pub trait SimpleSlotWorker { ); let header = block_import_params.post_header(); - match block_import.import_block(block_import_params, Default::default()).await { + match self.block_import().import_block(block_import_params, Default::default()).await { Ok(res) => { res.handle_justification( &header.hash(), From 2db9eccff65d4fcb3eaf085bd3ea9c6b2357428f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Dec 2021 11:02:12 +0100 Subject: [PATCH 303/695] Bump backtrace from 0.3.61 to 0.3.63 (#10495) Bumps [backtrace](https://github.com/rust-lang/backtrace-rs) from 0.3.61 to 0.3.63. - [Release notes](https://github.com/rust-lang/backtrace-rs/releases) - [Commits](https://github.com/rust-lang/backtrace-rs/compare/0.3.61...0.3.63) --- updated-dependencies: - dependency-name: backtrace dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 36 +++++++++++++++++------------ primitives/panic-handler/Cargo.toml | 2 +- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4ff6fc1974fa..92844e51fb4a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -21,6 +21,15 @@ dependencies = [ "gimli 0.25.0", ] +[[package]] +name = "addr2line" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" +dependencies = [ + "gimli 0.26.1", +] + [[package]] name = "adler" version = "1.0.2" @@ -406,16 +415,16 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "backtrace" -version = "0.3.61" +version = "0.3.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7a905d892734eea339e896738c14b9afce22b5318f64b951e70bf3844419b01" +checksum = "321629d8ba6513061f26707241fa9bc89524ff1cd7a915a97ef0c62c666ce1b6" dependencies = [ - "addr2line", + "addr2line 0.17.0", "cc", "cfg-if 1.0.0", "libc", "miniz_oxide", - "object 0.26.0", + "object 0.27.1", "rustc-demangle", ] @@ -2494,6 +2503,12 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "gimli" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" + [[package]] name = "git2" version = "0.13.23" @@ -5007,15 +5022,6 @@ dependencies = [ "indexmap", ] -[[package]] -name = "object" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c55827317fb4c08822499848a14237d2874d6f139828893017237e7ab93eb386" -dependencies = [ - "memchr", -] - [[package]] name = "object" version = "0.27.1" @@ -10815,7 +10821,7 @@ dependencies = [ "chrono", "lazy_static", "matchers", - "parking_lot 0.9.0", + "parking_lot 0.11.2", "regex", "serde", "serde_json", @@ -11663,7 +11669,7 @@ version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "864ac8dfe4ce310ac59f16fdbd560c257389cb009ee5d030ac6e30523b023d11" dependencies = [ - "addr2line", + "addr2line 0.16.0", "anyhow", "bincode", "cfg-if 1.0.0", diff --git a/primitives/panic-handler/Cargo.toml b/primitives/panic-handler/Cargo.toml index 8c3578442a79..abab34d29519 100644 --- a/primitives/panic-handler/Cargo.toml +++ b/primitives/panic-handler/Cargo.toml @@ -14,6 +14,6 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -backtrace = "0.3.38" +backtrace = "0.3.63" regex = "1.5.4" lazy_static = "1.4.0" From fb08d15bcbea68415dd4ee90d11556b653096f10 Mon Sep 17 00:00:00 2001 From: sandreim <54316454+sandreim@users.noreply.github.com> Date: Thu, 16 Dec 2021 13:18:24 +0200 Subject: [PATCH 304/695] Add logger configuration hook (#10440) * Initial poc Signed-off-by: Andrei Sandu * Make config available to logger hook Signed-off-by: Andrei Sandu * fmt Signed-off-by: Andrei Sandu * Fix tests Signed-off-by: Andrei Sandu * fmt Signed-off-by: Andrei Sandu * Add metric prefix option in sc_cli::RunCmd Signed-off-by: Andrei Sandu * Remove print Signed-off-by: Andrei Sandu * Review fixes Signed-off-by: Andrei Sandu * fmt Signed-off-by: Andrei Sandu * fix docs Signed-off-by: Andrei Sandu --- client/cli/src/config.rs | 37 ++++++++++- client/cli/src/lib.rs | 40 +++++++++++- client/cli/src/runner.rs | 13 +--- client/executor/src/integration_tests/mod.rs | 6 +- client/service/src/config.rs | 2 - client/tracing/src/lib.rs | 66 ++++++++++++++------ client/tracing/src/logging/mod.rs | 25 +++++++- 7 files changed, 148 insertions(+), 41 deletions(-) diff --git a/client/cli/src/config.rs b/client/cli/src/config.rs index 6d5ac7118281..7ae31eba4245 100644 --- a/client/cli/src/config.rs +++ b/client/cli/src/config.rs @@ -581,10 +581,40 @@ pub trait CliConfiguration: Sized { /// This method: /// /// 1. Sets the panic handler + /// 2. Optionally customize logger/profiling /// 2. Initializes the logger /// 3. Raises the FD limit - fn init(&self) -> Result<()> { - sp_panic_handler::set(&C::support_url(), &C::impl_version()); + /// + /// The `logger_hook` closure is executed before the logger is constructed + /// and initialized. It is useful for setting up a custom profiler. + /// + /// Example: + /// ``` + /// use sc_tracing::{SpanDatum, TraceEvent}; + /// struct TestProfiler; + /// + /// impl sc_tracing::TraceHandler for TestProfiler { + /// fn handle_span(&self, sd: &SpanDatum) {} + /// fn handle_event(&self, _event: &TraceEvent) {} + /// }; + /// + /// fn logger_hook() -> impl FnOnce(&mut sc_cli::LoggerBuilder, &sc_service::Configuration) -> () { + /// |logger_builder, config| { + /// logger_builder.with_custom_profiling(Box::new(TestProfiler{})); + /// } + /// } + /// ``` + fn init( + &self, + support_url: &String, + impl_version: &String, + logger_hook: F, + config: &Configuration, + ) -> Result<()> + where + F: FnOnce(&mut LoggerBuilder, &Configuration), + { + sp_panic_handler::set(support_url, impl_version); let mut logger = LoggerBuilder::new(self.log_filters()?); logger @@ -600,6 +630,9 @@ pub trait CliConfiguration: Sized { logger.with_colors(false); } + // Call hook for custom profiling setup. + logger_hook(&mut logger, &config); + logger.init()?; if let Some(new_limit) = fdlimit::raise_fd_limit() { diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index bb1bff94145f..d20b6f136f1e 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -224,10 +224,46 @@ pub trait SubstrateCli: Sized { /// Create a runner for the command provided in argument. This will create a Configuration and /// a tokio runtime fn create_runner(&self, command: &T) -> error::Result> { - command.init::()?; - Runner::new(self, command) + let tokio_runtime = build_runtime()?; + let config = command.create_configuration(self, tokio_runtime.handle().clone())?; + + command.init(&Self::support_url(), &Self::impl_version(), |_, _| {}, &config)?; + Runner::new(config, tokio_runtime) } + /// Create a runner for the command provided in argument. The `logger_hook` can be used to setup + /// a custom profiler or update the logger configuration before it is initialized. + /// + /// Example: + /// ``` + /// use sc_tracing::{SpanDatum, TraceEvent}; + /// struct TestProfiler; + /// + /// impl sc_tracing::TraceHandler for TestProfiler { + /// fn handle_span(&self, sd: &SpanDatum) {} + /// fn handle_event(&self, _event: &TraceEvent) {} + /// }; + /// + /// fn logger_hook() -> impl FnOnce(&mut sc_cli::LoggerBuilder, &sc_service::Configuration) -> () { + /// |logger_builder, config| { + /// logger_builder.with_custom_profiling(Box::new(TestProfiler{})); + /// } + /// } + /// ``` + fn create_runner_with_logger_hook( + &self, + command: &T, + logger_hook: F, + ) -> error::Result> + where + F: FnOnce(&mut LoggerBuilder, &Configuration), + { + let tokio_runtime = build_runtime()?; + let config = command.create_configuration(self, tokio_runtime.handle().clone())?; + + command.init(&Self::support_url(), &Self::impl_version(), logger_hook, &config)?; + Runner::new(config, tokio_runtime) + } /// Native runtime version. fn native_runtime_version(chain_spec: &Box) -> &'static RuntimeVersion; } diff --git a/client/cli/src/runner.rs b/client/cli/src/runner.rs index 34c194801213..d55dfe253765 100644 --- a/client/cli/src/runner.rs +++ b/client/cli/src/runner.rs @@ -16,7 +16,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use crate::{error::Error as CliError, CliConfiguration, Result, SubstrateCli}; +use crate::{error::Error as CliError, Result, SubstrateCli}; use chrono::prelude::*; use futures::{future, future::FutureExt, pin_mut, select, Future}; use log::info; @@ -112,15 +112,8 @@ pub struct Runner { impl Runner { /// Create a new runtime with the command provided in argument - pub fn new(cli: &C, command: &T) -> Result> { - let tokio_runtime = build_runtime()?; - let runtime_handle = tokio_runtime.handle().clone(); - - Ok(Runner { - config: command.create_configuration(cli, runtime_handle)?, - tokio_runtime, - phantom: PhantomData, - }) + pub fn new(config: Configuration, tokio_runtime: tokio::runtime::Runtime) -> Result> { + Ok(Runner { config, tokio_runtime, phantom: PhantomData }) } /// Log information about the node itself. diff --git a/client/executor/src/integration_tests/mod.rs b/client/executor/src/integration_tests/mod.rs index b2b31679926c..89648e9bac69 100644 --- a/client/executor/src/integration_tests/mod.rs +++ b/client/executor/src/integration_tests/mod.rs @@ -622,11 +622,11 @@ fn wasm_tracing_should_work(wasm_method: WasmExecutionMethod) { struct TestTraceHandler(Arc>>); impl sc_tracing::TraceHandler for TestTraceHandler { - fn handle_span(&self, sd: SpanDatum) { - self.0.lock().unwrap().push(sd); + fn handle_span(&self, sd: &SpanDatum) { + self.0.lock().unwrap().push(sd.clone()); } - fn handle_event(&self, _event: TraceEvent) {} + fn handle_event(&self, _event: &TraceEvent) {} } let traces = Arc::new(Mutex::new(Vec::new())); diff --git a/client/service/src/config.rs b/client/service/src/config.rs index 61ef8233f8e3..db2041ed96f1 100644 --- a/client/service/src/config.rs +++ b/client/service/src/config.rs @@ -188,8 +188,6 @@ pub struct PrometheusConfig { impl PrometheusConfig { /// Create a new config using the default registry. - /// - /// The default registry prefixes metrics with `substrate`. pub fn new_with_default_registry(port: SocketAddr, chain_id: String) -> Self { let param = iter::once((String::from("chain"), chain_id)).collect(); Self { diff --git a/client/tracing/src/lib.rs b/client/tracing/src/lib.rs index bf6e3d780c6e..fc501bb9a432 100644 --- a/client/tracing/src/lib.rs +++ b/client/tracing/src/lib.rs @@ -58,7 +58,7 @@ const ZERO_DURATION: Duration = Duration::from_nanos(0); /// Responsible for assigning ids to new spans, which are not re-used. pub struct ProfilingLayer { targets: Vec<(String, Level)>, - trace_handler: Box, + trace_handlers: Vec>, } /// Used to configure how to receive the metrics @@ -76,14 +76,14 @@ impl Default for TracingReceiver { /// A handler for tracing `SpanDatum` pub trait TraceHandler: Send + Sync { - /// Process a `SpanDatum` - fn handle_span(&self, span: SpanDatum); - /// Process a `TraceEvent` - fn handle_event(&self, event: TraceEvent); + /// Process a `SpanDatum`. + fn handle_span(&self, span: &SpanDatum); + /// Process a `TraceEvent`. + fn handle_event(&self, event: &TraceEvent); } /// Represents a tracing event, complete with values -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct TraceEvent { /// Name of the event. pub name: String, @@ -98,7 +98,7 @@ pub struct TraceEvent { } /// Represents a single instance of a tracing span -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct SpanDatum { /// id for this span pub id: Id, @@ -213,6 +213,15 @@ impl fmt::Display for Values { } } +/// Trace handler event types. +#[derive(Debug)] +pub enum TraceHandlerEvents { + /// An event. + Event(TraceEvent), + /// A span. + Span(SpanDatum), +} + impl ProfilingLayer { /// Takes a `TracingReceiver` and a comma separated list of targets, /// either with a level: "pallet=trace,frame=debug" @@ -231,7 +240,12 @@ impl ProfilingLayer { /// wasm_tracing indicates whether to enable wasm traces pub fn new_with_handler(trace_handler: Box, targets: &str) -> Self { let targets: Vec<_> = targets.split(',').map(|s| parse_target(s)).collect(); - Self { targets, trace_handler } + Self { targets, trace_handlers: vec![trace_handler] } + } + + /// Attach additional handlers to allow handling of custom events/spans. + pub fn add_handler(&mut self, trace_handler: Box) { + self.trace_handlers.push(trace_handler); } fn check_target(&self, target: &str, level: &Level) -> bool { @@ -242,6 +256,18 @@ impl ProfilingLayer { } false } + + /// Sequentially dispatch a trace event to all handlers. + fn dispatch_event(&self, event: TraceHandlerEvents) { + match &event { + TraceHandlerEvents::Span(span_datum) => { + self.trace_handlers.iter().for_each(|handler| handler.handle_span(span_datum)); + }, + TraceHandlerEvents::Event(event) => { + self.trace_handlers.iter().for_each(|handler| handler.handle_event(event)); + }, + } + } } // Default to TRACE if no level given or unable to parse Level @@ -320,7 +346,7 @@ where values, parent_id, }; - self.trace_handler.handle_event(trace_event); + self.dispatch_event(TraceHandlerEvents::Event(trace_event)); } fn on_enter(&self, span: &Id, ctx: Context) { @@ -348,10 +374,10 @@ where span_datum.target = t; } if self.check_target(&span_datum.target, &span_datum.level) { - self.trace_handler.handle_span(span_datum); + self.dispatch_event(TraceHandlerEvents::Span(span_datum)); } } else { - self.trace_handler.handle_span(span_datum); + self.dispatch_event(TraceHandlerEvents::Span(span_datum)); } } } @@ -374,7 +400,7 @@ fn log_level(level: Level) -> log::Level { } impl TraceHandler for LogTraceHandler { - fn handle_span(&self, span_datum: SpanDatum) { + fn handle_span(&self, span_datum: &SpanDatum) { if span_datum.values.is_empty() { log::log!( log_level(span_datum.level), @@ -383,7 +409,7 @@ impl TraceHandler for LogTraceHandler { span_datum.name, span_datum.overall_time.as_nanos(), span_datum.id.into_u64(), - span_datum.parent_id.map(|s| s.into_u64()), + span_datum.parent_id.as_ref().map(|s| s.into_u64()), ); } else { log::log!( @@ -393,18 +419,18 @@ impl TraceHandler for LogTraceHandler { span_datum.name, span_datum.overall_time.as_nanos(), span_datum.id.into_u64(), - span_datum.parent_id.map(|s| s.into_u64()), + span_datum.parent_id.as_ref().map(|s| s.into_u64()), span_datum.values, ); } } - fn handle_event(&self, event: TraceEvent) { + fn handle_event(&self, event: &TraceEvent) { log::log!( log_level(event.level), "{}, parent_id: {:?}, {}", event.target, - event.parent_id.map(|s| s.into_u64()), + event.parent_id.as_ref().map(|s| s.into_u64()), event.values, ); } @@ -447,12 +473,12 @@ mod tests { } impl TraceHandler for TestTraceHandler { - fn handle_span(&self, sd: SpanDatum) { - self.spans.lock().push(sd); + fn handle_span(&self, sd: &SpanDatum) { + self.spans.lock().push(sd.clone()); } - fn handle_event(&self, event: TraceEvent) { - self.events.lock().push(event); + fn handle_event(&self, event: &TraceEvent) { + self.events.lock().push(event.clone()); } } diff --git a/client/tracing/src/logging/mod.rs b/client/tracing/src/logging/mod.rs index 521cfca30e29..72740715e55b 100644 --- a/client/tracing/src/logging/mod.rs +++ b/client/tracing/src/logging/mod.rs @@ -193,6 +193,7 @@ where pub struct LoggerBuilder { directives: String, profiling: Option<(crate::TracingReceiver, String)>, + custom_profiler: Option>, log_reloading: bool, force_colors: Option, detailed_output: bool, @@ -204,6 +205,7 @@ impl LoggerBuilder { Self { directives: directives.into(), profiling: None, + custom_profiler: None, log_reloading: false, force_colors: None, detailed_output: false, @@ -220,6 +222,15 @@ impl LoggerBuilder { self } + /// Add a custom profiler. + pub fn with_custom_profiling( + &mut self, + custom_profiler: Box, + ) -> &mut Self { + self.custom_profiler = Some(custom_profiler); + self + } + /// Wether or not to disable log reloading. pub fn with_log_reloading(&mut self, enabled: bool) -> &mut Self { self.log_reloading = enabled; @@ -256,7 +267,12 @@ impl LoggerBuilder { self.detailed_output, |builder| enable_log_reloading!(builder), )?; - let profiling = crate::ProfilingLayer::new(tracing_receiver, &profiling_targets); + let mut profiling = + crate::ProfilingLayer::new(tracing_receiver, &profiling_targets); + + self.custom_profiler + .into_iter() + .for_each(|profiler| profiling.add_handler(profiler)); tracing::subscriber::set_global_default(subscriber.with(profiling))?; @@ -269,7 +285,12 @@ impl LoggerBuilder { self.detailed_output, |builder| builder, )?; - let profiling = crate::ProfilingLayer::new(tracing_receiver, &profiling_targets); + let mut profiling = + crate::ProfilingLayer::new(tracing_receiver, &profiling_targets); + + self.custom_profiler + .into_iter() + .for_each(|profiler| profiling.add_handler(profiler)); tracing::subscriber::set_global_default(subscriber.with(profiling))?; From 2a7a734c373d0b28c6c658667effd3fb8c9e35bf Mon Sep 17 00:00:00 2001 From: Liu-Cheng Xu Date: Fri, 17 Dec 2021 07:19:30 +0800 Subject: [PATCH 305/695] Use intra doc in network-gossip (#10501) * Use intra doc in network-gossip So that we could jump to the definition easily. * cargo +nightly fmt --all --- client/network-gossip/src/bridge.rs | 4 ++-- client/network-gossip/src/lib.rs | 26 +++++++++++++------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/client/network-gossip/src/bridge.rs b/client/network-gossip/src/bridge.rs index 70b13983d8bd..477b0678fcc8 100644 --- a/client/network-gossip/src/bridge.rs +++ b/client/network-gossip/src/bridge.rs @@ -39,7 +39,7 @@ use std::{ task::{Context, Poll}, }; -/// Wraps around an implementation of the `Network` crate and provides gossiping capabilities on +/// Wraps around an implementation of the [`Network`] trait and provides gossiping capabilities on /// top of it. pub struct GossipEngine { state_machine: ConsensusGossip, @@ -56,7 +56,7 @@ pub struct GossipEngine { } /// A gossip engine receives messages from the network via the `network_event_stream` and forwards -/// them to upper layers via the `message sinks`. In the scenario where messages have been received +/// them to upper layers via the `message_sinks`. In the scenario where messages have been received /// from the network but a subscribed message sink is not yet ready to receive the messages, the /// messages are buffered. To model this process a gossip engine can be in two states. enum ForwardingState { diff --git a/client/network-gossip/src/lib.rs b/client/network-gossip/src/lib.rs index 5dc40471f138..4b8b4e39862b 100644 --- a/client/network-gossip/src/lib.rs +++ b/client/network-gossip/src/lib.rs @@ -26,32 +26,32 @@ //! message, assuming it is valid. //! //! Topics are a single 32-byte tag associated with a message, used to group those messages -//! in an opaque way. Consensus code can invoke `broadcast_topic` to attempt to send all messages -//! under a single topic to all peers who don't have them yet, and `send_topic` to -//! send all messages under a single topic to a specific peer. +//! in an opaque way. Consensus code can invoke [`ValidatorContext::broadcast_topic`] to +//! attempt to send all messages under a single topic to all peers who don't have them yet, and +//! [`ValidatorContext::send_topic`] to send all messages under a single topic to a specific peer. //! //! # Usage //! -//! - Implement the `Network` trait, representing the low-level networking primitives. It is already -//! implemented on `sc_network::NetworkService`. -//! - Implement the `Validator` trait. See the section below. +//! - Implement the [`Network`] trait, representing the low-level networking primitives. It is +//! already implemented on `sc_network::NetworkService`. +//! - Implement the [`Validator`] trait. See the section below. //! - Decide on a protocol name. Each gossiping protocol should have a different one. -//! - Build a `GossipEngine` using these three elements. -//! - Use the methods of the `GossipEngine` in order to send out messages and receive incoming +//! - Build a [`GossipEngine`] using these three elements. +//! - Use the methods of the [`GossipEngine`] in order to send out messages and receive incoming //! messages. //! -//! The `GossipEngine` will automatically use `Network::add_set_reserved` and -//! `Network::remove_set_reserved` to maintain a set of peers equal to the set of peers the +//! The [`GossipEngine`] will automatically use [`Network::add_set_reserved`] and +//! [`Network::remove_set_reserved`] to maintain a set of peers equal to the set of peers the //! node is syncing from. See the documentation of `sc-network` for more explanations about the //! concepts of peer sets. //! //! # What is a validator? //! -//! The primary role of a `Validator` is to process incoming messages from peers, and decide +//! The primary role of a [`Validator`] is to process incoming messages from peers, and decide //! whether to discard them or process them. It also decides whether to re-broadcast the message. //! -//! The secondary role of the `Validator` is to check if a message is allowed to be sent to a given -//! peer. All messages, before being sent, will be checked against this filter. +//! The secondary role of the [`Validator`] is to check if a message is allowed to be sent to a +//! given peer. All messages, before being sent, will be checked against this filter. //! This enables the validator to use information it's aware of about connected peers to decide //! whether to send messages to them at any given moment in time - In particular, to wait until //! peers can accept and process the message before sending it. From ce92e8060b179ea48f1e1b3edbe8c4d296a97e30 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Dec 2021 08:30:58 +0000 Subject: [PATCH 306/695] Bump serde from 1.0.130 to 1.0.131 (#10500) Bumps [serde](https://github.com/serde-rs/serde) from 1.0.130 to 1.0.131. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.130...v1.0.131) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- bin/node/bench/Cargo.toml | 2 +- bin/node/cli/Cargo.toml | 2 +- client/beefy/rpc/Cargo.toml | 2 +- client/chain-spec/Cargo.toml | 2 +- client/cli/Cargo.toml | 2 +- client/consensus/babe/Cargo.toml | 2 +- client/consensus/babe/rpc/Cargo.toml | 2 +- client/network/Cargo.toml | 2 +- client/rpc-api/Cargo.toml | 2 +- client/service/Cargo.toml | 2 +- client/sync-state-rpc/Cargo.toml | 2 +- client/telemetry/Cargo.toml | 2 +- client/tracing/Cargo.toml | 2 +- client/transaction-pool/Cargo.toml | 2 +- client/transaction-pool/api/Cargo.toml | 2 +- frame/beefy-mmr/Cargo.toml | 2 +- frame/beefy/Cargo.toml | 2 +- frame/democracy/Cargo.toml | 2 +- frame/merkle-mountain-range/primitives/Cargo.toml | 2 +- frame/merkle-mountain-range/rpc/Cargo.toml | 2 +- frame/offences/Cargo.toml | 2 +- frame/staking/Cargo.toml | 2 +- frame/support/Cargo.toml | 2 +- frame/support/test/Cargo.toml | 2 +- frame/system/Cargo.toml | 2 +- frame/tips/Cargo.toml | 2 +- frame/transaction-payment/Cargo.toml | 2 +- frame/transaction-payment/asset-tx-payment/Cargo.toml | 2 +- frame/transaction-storage/Cargo.toml | 2 +- frame/treasury/Cargo.toml | 2 +- primitives/application-crypto/Cargo.toml | 2 +- primitives/arithmetic/Cargo.toml | 2 +- primitives/consensus/babe/Cargo.toml | 2 +- primitives/core/Cargo.toml | 2 +- primitives/finality-grandpa/Cargo.toml | 2 +- primitives/npos-elections/Cargo.toml | 2 +- primitives/rpc/Cargo.toml | 2 +- primitives/runtime/Cargo.toml | 2 +- primitives/serializer/Cargo.toml | 2 +- primitives/storage/Cargo.toml | 2 +- primitives/test-primitives/Cargo.toml | 2 +- primitives/version/Cargo.toml | 2 +- test-utils/client/Cargo.toml | 2 +- test-utils/runtime/Cargo.toml | 2 +- utils/frame/benchmarking-cli/Cargo.toml | 2 +- utils/frame/remote-externalities/Cargo.toml | 2 +- utils/frame/try-runtime/cli/Cargo.toml | 2 +- 48 files changed, 51 insertions(+), 51 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 92844e51fb4a..0c70bbdf6efc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8893,9 +8893,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.130" +version = "1.0.131" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" +checksum = "b4ad69dfbd3e45369132cc64e6748c2d65cdfb001a2b1c232d128b4ad60561c1" dependencies = [ "serde_derive", ] @@ -8921,9 +8921,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.130" +version = "1.0.131" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b" +checksum = "b710a83c4e0dff6a3d511946b95274ad9ca9e5d3ae497b63fda866ac955358d2" dependencies = [ "proc-macro2", "quote", diff --git a/bin/node/bench/Cargo.toml b/bin/node/bench/Cargo.toml index 8d2ca810273c..3ffb0f92c843 100644 --- a/bin/node/bench/Cargo.toml +++ b/bin/node/bench/Cargo.toml @@ -16,7 +16,7 @@ node-runtime = { version = "3.0.0-dev", path = "../runtime" } sc-client-api = { version = "4.0.0-dev", path = "../../../client/api/" } sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } sp-state-machine = { version = "0.10.0", path = "../../../primitives/state-machine" } -serde = "1.0.126" +serde = "1.0.131" serde_json = "1.0.71" structopt = "0.3" derive_more = "0.99.16" diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index d7143b39816b..a967dd133211 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -35,7 +35,7 @@ crate-type = ["cdylib", "rlib"] [dependencies] # third-party dependencies codec = { package = "parity-scale-codec", version = "2.0.0" } -serde = { version = "1.0.126", features = ["derive"] } +serde = { version = "1.0.131", features = ["derive"] } futures = "0.3.16" hex-literal = "0.3.4" log = "0.4.8" diff --git a/client/beefy/rpc/Cargo.toml b/client/beefy/rpc/Cargo.toml index 9f4a1305f2d0..b5a8144faba8 100644 --- a/client/beefy/rpc/Cargo.toml +++ b/client/beefy/rpc/Cargo.toml @@ -10,7 +10,7 @@ description = "RPC for the BEEFY Client gadget for substrate" [dependencies] futures = "0.3.16" log = "0.4" -serde = { version = "1.0.130", features = ["derive"] } +serde = { version = "1.0.131", features = ["derive"] } jsonrpc-core = "18.0.0" jsonrpc-core-client = "18.0.0" diff --git a/client/chain-spec/Cargo.toml b/client/chain-spec/Cargo.toml index d06e0bce18c1..4ef14decf9eb 100644 --- a/client/chain-spec/Cargo.toml +++ b/client/chain-spec/Cargo.toml @@ -17,7 +17,7 @@ sc-chain-spec-derive = { version = "4.0.0-dev", path = "./derive" } impl-trait-for-tuples = "0.2.1" sc-network = { version = "0.10.0-dev", path = "../network" } sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } -serde = { version = "1.0.126", features = ["derive"] } +serde = { version = "1.0.131", features = ["derive"] } serde_json = "1.0.71" sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } sc-telemetry = { version = "4.0.0-dev", path = "../telemetry" } diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index 2e2b208923d5..cb9d09bbdbc7 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -41,7 +41,7 @@ names = { version = "0.12.0", default-features = false } structopt = "0.3.25" sc-tracing = { version = "4.0.0-dev", path = "../tracing" } chrono = "0.4.10" -serde = "1.0.126" +serde = "1.0.131" thiserror = "1.0.30" rpassword = "5.0.0" diff --git a/client/consensus/babe/Cargo.toml b/client/consensus/babe/Cargo.toml index c96d648846c5..654e47b72756 100644 --- a/client/consensus/babe/Cargo.toml +++ b/client/consensus/babe/Cargo.toml @@ -25,7 +25,7 @@ sp-keystore = { version = "0.10.0", path = "../../../primitives/keystore" } num-bigint = "0.2.3" num-rational = "0.2.2" num-traits = "0.2.8" -serde = { version = "1.0.126", features = ["derive"] } +serde = { version = "1.0.131", features = ["derive"] } sp-version = { version = "4.0.0-dev", path = "../../../primitives/version" } sp-io = { version = "4.0.0", path = "../../../primitives/io" } sp-inherents = { version = "4.0.0-dev", path = "../../../primitives/inherents" } diff --git a/client/consensus/babe/rpc/Cargo.toml b/client/consensus/babe/rpc/Cargo.toml index cea2aea4553b..28b27db82c7d 100644 --- a/client/consensus/babe/rpc/Cargo.toml +++ b/client/consensus/babe/rpc/Cargo.toml @@ -19,7 +19,7 @@ jsonrpc-core = "18.0.0" jsonrpc-core-client = "18.0.0" jsonrpc-derive = "18.0.0" sp-consensus-babe = { version = "0.10.0-dev", path = "../../../../primitives/consensus/babe" } -serde = { version = "1.0.126", features=["derive"] } +serde = { version = "1.0.131", features=["derive"] } sp-blockchain = { version = "4.0.0-dev", path = "../../../../primitives/blockchain" } sp-runtime = { version = "4.0.0", path = "../../../../primitives/runtime" } sc-consensus-epochs = { version = "0.10.0-dev", path = "../../epochs" } diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index 643b2440209f..d82d5b9574dd 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -46,7 +46,7 @@ rand = "0.7.2" sc-block-builder = { version = "0.10.0-dev", path = "../block-builder" } sc-client-api = { version = "4.0.0-dev", path = "../api" } sc-peerset = { version = "4.0.0-dev", path = "../peerset" } -serde = { version = "1.0.126", features = ["derive"] } +serde = { version = "1.0.131", features = ["derive"] } serde_json = "1.0.71" smallvec = "1.7.0" sp-arithmetic = { version = "4.0.0", path = "../../primitives/arithmetic" } diff --git a/client/rpc-api/Cargo.toml b/client/rpc-api/Cargo.toml index 2e75dd460bd3..8a2feb2581b0 100644 --- a/client/rpc-api/Cargo.toml +++ b/client/rpc-api/Cargo.toml @@ -27,7 +27,7 @@ sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } sp-runtime = { path = "../../primitives/runtime", version = "4.0.0" } sc-chain-spec = { path = "../chain-spec", version = "4.0.0-dev" } -serde = { version = "1.0.126", features = ["derive"] } +serde = { version = "1.0.131", features = ["derive"] } serde_json = "1.0.71" sc-transaction-pool-api = { version = "4.0.0-dev", path = "../transaction-pool/api" } sp-rpc = { version = "4.0.0-dev", path = "../../primitives/rpc" } diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index e81125fc9154..4d88f403005e 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -33,7 +33,7 @@ futures-timer = "3.0.1" exit-future = "0.2.0" pin-project = "1.0.8" hash-db = "0.15.2" -serde = "1.0.126" +serde = "1.0.131" serde_json = "1.0.71" sc-keystore = { version = "4.0.0-dev", path = "../keystore" } sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } diff --git a/client/sync-state-rpc/Cargo.toml b/client/sync-state-rpc/Cargo.toml index a7b632b81800..1566777009c3 100644 --- a/client/sync-state-rpc/Cargo.toml +++ b/client/sync-state-rpc/Cargo.toml @@ -24,7 +24,7 @@ sc-consensus-epochs = { version = "0.10.0-dev", path = "../consensus/epochs" } sc-finality-grandpa = { version = "0.10.0-dev", path = "../finality-grandpa" } sc-rpc-api = { version = "0.10.0-dev", path = "../rpc-api" } serde_json = "1.0.71" -serde = { version = "1.0.126", features = ["derive"] } +serde = { version = "1.0.131", features = ["derive"] } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } codec = { package = "parity-scale-codec", version = "2.0.0" } diff --git a/client/telemetry/Cargo.toml b/client/telemetry/Cargo.toml index af7b1d0a0669..c4e03e94a2b1 100644 --- a/client/telemetry/Cargo.toml +++ b/client/telemetry/Cargo.toml @@ -22,7 +22,7 @@ libp2p = { version = "0.40.0", default-features = false, features = ["dns-async- log = "0.4.8" pin-project = "1.0.8" rand = "0.7.2" -serde = { version = "1.0.126", features = ["derive"] } +serde = { version = "1.0.131", features = ["derive"] } serde_json = "1.0.71" chrono = "0.4.19" thiserror = "1.0.30" diff --git a/client/tracing/Cargo.toml b/client/tracing/Cargo.toml index c4fdcde3f067..861e1acc68c3 100644 --- a/client/tracing/Cargo.toml +++ b/client/tracing/Cargo.toml @@ -23,7 +23,7 @@ once_cell = "1.8.0" parking_lot = "0.11.2" regex = "1.5.4" rustc-hash = "1.1.0" -serde = "1.0.126" +serde = "1.0.131" thiserror = "1.0.30" tracing = "0.1.29" tracing-log = "0.1.2" diff --git a/client/transaction-pool/Cargo.toml b/client/transaction-pool/Cargo.toml index 6439a1854352..2399fb449c7f 100644 --- a/client/transaction-pool/Cargo.toml +++ b/client/transaction-pool/Cargo.toml @@ -30,7 +30,7 @@ sp-transaction-pool = { version = "4.0.0-dev", path = "../../primitives/transact sc-transaction-pool-api = { version = "4.0.0-dev", path = "./api" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sc-utils = { version = "4.0.0-dev", path = "../utils" } -serde = { version = "1.0.126", features = ["derive"] } +serde = { version = "1.0.131", features = ["derive"] } linked-hash-map = "0.5.4" retain_mut = "0.1.4" diff --git a/client/transaction-pool/api/Cargo.toml b/client/transaction-pool/api/Cargo.toml index 0c65234b0d68..39e126250a9e 100644 --- a/client/transaction-pool/api/Cargo.toml +++ b/client/transaction-pool/api/Cargo.toml @@ -11,7 +11,7 @@ description = "Transaction pool client facing API." [dependencies] futures = { version = "0.3.1" } log = { version = "0.4.8" } -serde = { version = "1.0.126", features = ["derive"] } +serde = { version = "1.0.131", features = ["derive"] } thiserror = { version = "1.0.30" } sp-runtime = { version = "4.0.0", default-features = false, path = "../../../primitives/runtime" } diff --git a/frame/beefy-mmr/Cargo.toml b/frame/beefy-mmr/Cargo.toml index 50c4fd3f7f3b..a4ba9d1fbdae 100644 --- a/frame/beefy-mmr/Cargo.toml +++ b/frame/beefy-mmr/Cargo.toml @@ -13,7 +13,7 @@ codec = { version = "2.2.0", package = "parity-scale-codec", default-features = libsecp256k1 = { version = "0.7.0", default-features = false } log = { version = "0.4.13", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -serde = { version = "1.0.130", optional = true } +serde = { version = "1.0.131", optional = true } frame-support = { version = "4.0.0-dev", path = "../support", default-features = false } frame-system = { version = "4.0.0-dev", path = "../system", default-features = false } diff --git a/frame/beefy/Cargo.toml b/frame/beefy/Cargo.toml index 2f7059d5156c..e9a748b2e80d 100644 --- a/frame/beefy/Cargo.toml +++ b/frame/beefy/Cargo.toml @@ -10,7 +10,7 @@ description = "BEEFY FRAME pallet" [dependencies] codec = { version = "2.2.0", package = "parity-scale-codec", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -serde = { version = "1.0.130", optional = true } +serde = { version = "1.0.131", optional = true } frame-support = { version = "4.0.0-dev", path = "../support", default-features = false } frame-system = { version = "4.0.0-dev", path = "../system", default-features = false } diff --git a/frame/democracy/Cargo.toml b/frame/democracy/Cargo.toml index b1b84d9ad03d..0c9306b8b5bd 100644 --- a/frame/democracy/Cargo.toml +++ b/frame/democracy/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -serde = { version = "1.0.126", optional = true, features = ["derive"] } +serde = { version = "1.0.131", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ "derive", ] } diff --git a/frame/merkle-mountain-range/primitives/Cargo.toml b/frame/merkle-mountain-range/primitives/Cargo.toml index 713da64e26d9..cda883ccf728 100644 --- a/frame/merkle-mountain-range/primitives/Cargo.toml +++ b/frame/merkle-mountain-range/primitives/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } log = { version = "0.4.14", default-features = false } -serde = { version = "1.0.126", optional = true, features = ["derive"] } +serde = { version = "1.0.131", optional = true, features = ["derive"] } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/api" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } diff --git a/frame/merkle-mountain-range/rpc/Cargo.toml b/frame/merkle-mountain-range/rpc/Cargo.toml index 13d60142dfc3..291fd5311aa5 100644 --- a/frame/merkle-mountain-range/rpc/Cargo.toml +++ b/frame/merkle-mountain-range/rpc/Cargo.toml @@ -17,7 +17,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0" } jsonrpc-core = "18.0.0" jsonrpc-core-client = "18.0.0" jsonrpc-derive = "18.0.0" -serde = { version = "1.0.126", features = ["derive"] } +serde = { version = "1.0.131", features = ["derive"] } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } diff --git a/frame/offences/Cargo.toml b/frame/offences/Cargo.toml index 02f36fab0a21..40b211a19cd0 100644 --- a/frame/offences/Cargo.toml +++ b/frame/offences/Cargo.toml @@ -17,7 +17,7 @@ pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -serde = { version = "1.0.126", optional = true } +serde = { version = "1.0.131", optional = true } sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/frame/staking/Cargo.toml b/frame/staking/Cargo.toml index c91db8c24fda..e09d5a57d5ca 100644 --- a/frame/staking/Cargo.toml +++ b/frame/staking/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -serde = { version = "1.0.126", optional = true } +serde = { version = "1.0.131", optional = true } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ "derive", ] } diff --git a/frame/support/Cargo.toml b/frame/support/Cargo.toml index 3cfce23dabe0..c049870ecb09 100644 --- a/frame/support/Cargo.toml +++ b/frame/support/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -serde = { version = "1.0.126", optional = true, features = ["derive"] } +serde = { version = "1.0.131", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } frame-metadata = { version = "14.0.0", default-features = false, features = ["v14"] } diff --git a/frame/support/test/Cargo.toml b/frame/support/test/Cargo.toml index d41b0fcacf23..ebee4515f3be 100644 --- a/frame/support/test/Cargo.toml +++ b/frame/support/test/Cargo.toml @@ -12,7 +12,7 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -serde = { version = "1.0.126", default-features = false, features = ["derive"] } +serde = { version = "1.0.131", default-features = false, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-arithmetic = { version = "4.0.0", default-features = false, path = "../../../primitives/arithmetic" } diff --git a/frame/system/Cargo.toml b/frame/system/Cargo.toml index 70a9b12c7a23..cc1378a35c62 100644 --- a/frame/system/Cargo.toml +++ b/frame/system/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -serde = { version = "1.0.126", optional = true, features = ["derive"] } +serde = { version = "1.0.131", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } diff --git a/frame/tips/Cargo.toml b/frame/tips/Cargo.toml index a637fa3928e0..935ab907a8a1 100644 --- a/frame/tips/Cargo.toml +++ b/frame/tips/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } log = { version = "0.4.0", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -serde = { version = "1.0.126", features = ["derive"], optional = true } +serde = { version = "1.0.131", features = ["derive"], optional = true } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } diff --git a/frame/transaction-payment/Cargo.toml b/frame/transaction-payment/Cargo.toml index ac6fc5c71c04..f4b9b9a18019 100644 --- a/frame/transaction-payment/Cargo.toml +++ b/frame/transaction-payment/Cargo.toml @@ -17,7 +17,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = "derive", ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -serde = { version = "1.0.126", optional = true } +serde = { version = "1.0.131", optional = true } smallvec = "1.7.0" sp-core = { version = "4.1.0-dev", path = "../../primitives/core", default-features = false } diff --git a/frame/transaction-payment/asset-tx-payment/Cargo.toml b/frame/transaction-payment/asset-tx-payment/Cargo.toml index 3f89a5c4b5f0..9c26fc8033f7 100644 --- a/frame/transaction-payment/asset-tx-payment/Cargo.toml +++ b/frame/transaction-payment/asset-tx-payment/Cargo.toml @@ -26,7 +26,7 @@ pallet-transaction-payment = { version = "4.0.0-dev", default-features = false, # Other dependencies codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -serde = { version = "1.0.126", optional = true } +serde = { version = "1.0.131", optional = true } [dev-dependencies] smallvec = "1.7.0" diff --git a/frame/transaction-storage/Cargo.toml b/frame/transaction-storage/Cargo.toml index 10f1d3d2e2b2..9bbc055dae1d 100644 --- a/frame/transaction-storage/Cargo.toml +++ b/frame/transaction-storage/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -serde = { version = "1.0.126", optional = true } +serde = { version = "1.0.131", optional = true } hex-literal = { version = "0.3.4", optional = true } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } diff --git a/frame/treasury/Cargo.toml b/frame/treasury/Cargo.toml index 5fe5734120d6..53cad5edffc3 100644 --- a/frame/treasury/Cargo.toml +++ b/frame/treasury/Cargo.toml @@ -18,7 +18,7 @@ codec = { package = "parity-scale-codec", version = "2.2.0", default-features = "max-encoded-len", ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -serde = { version = "1.0.126", features = ["derive"], optional = true } +serde = { version = "1.0.131", features = ["derive"], optional = true } impl-trait-for-tuples = "0.2.1" sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } diff --git a/primitives/application-crypto/Cargo.toml b/primitives/application-crypto/Cargo.toml index 8090203bbca0..750f8874493e 100644 --- a/primitives/application-crypto/Cargo.toml +++ b/primitives/application-crypto/Cargo.toml @@ -18,7 +18,7 @@ targets = ["x86_64-unknown-linux-gnu"] sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -serde = { version = "1.0.126", optional = true, features = ["derive"] } +serde = { version = "1.0.131", optional = true, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-io = { version = "4.0.0", default-features = false, path = "../io" } diff --git a/primitives/arithmetic/Cargo.toml b/primitives/arithmetic/Cargo.toml index 8db65342cfa0..a035b03b82a2 100644 --- a/primitives/arithmetic/Cargo.toml +++ b/primitives/arithmetic/Cargo.toml @@ -23,7 +23,7 @@ integer-sqrt = "0.1.2" static_assertions = "1.1.0" num-traits = { version = "0.2.8", default-features = false } sp-std = { version = "4.0.0", default-features = false, path = "../std" } -serde = { version = "1.0.126", optional = true, features = ["derive"] } +serde = { version = "1.0.131", optional = true, features = ["derive"] } sp-debug-derive = { version = "4.0.0", default-features = false, path = "../debug-derive" } [dev-dependencies] diff --git a/primitives/consensus/babe/Cargo.toml b/primitives/consensus/babe/Cargo.toml index fcfda410765e..19e94a8da21d 100644 --- a/primitives/consensus/babe/Cargo.toml +++ b/primitives/consensus/babe/Cargo.toml @@ -27,7 +27,7 @@ sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../ sp-keystore = { version = "0.10.0", default-features = false, path = "../../keystore", optional = true } sp-runtime = { version = "4.0.0", default-features = false, path = "../../runtime" } sp-timestamp = { version = "4.0.0-dev", path = "../../timestamp", optional = true } -serde = { version = "1.0.126", features = ["derive"], optional = true } +serde = { version = "1.0.131", features = ["derive"], optional = true } async-trait = { version = "0.1.50", optional = true } [features] diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index 2922c8b940ea..1ec9b5b46f1b 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -19,7 +19,7 @@ codec = { package = "parity-scale-codec", version = "2.2.0", default-features = ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } log = { version = "0.4.11", default-features = false } -serde = { version = "1.0.126", optional = true, features = ["derive"] } +serde = { version = "1.0.131", optional = true, features = ["derive"] } byteorder = { version = "1.3.2", default-features = false } primitive-types = { version = "0.10.1", default-features = false, features = [ "codec", diff --git a/primitives/finality-grandpa/Cargo.toml b/primitives/finality-grandpa/Cargo.toml index 8bcdf1462fc8..80607a0beb19 100644 --- a/primitives/finality-grandpa/Cargo.toml +++ b/primitives/finality-grandpa/Cargo.toml @@ -19,7 +19,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } grandpa = { package = "finality-grandpa", version = "0.14.1", default-features = false, features = ["derive-codec"] } log = { version = "0.4.8", optional = true } -serde = { version = "1.0.126", optional = true, features = ["derive"] } +serde = { version = "1.0.131", optional = true, features = ["derive"] } sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } sp-application-crypto = { version = "4.0.0", default-features = false, path = "../application-crypto" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } diff --git a/primitives/npos-elections/Cargo.toml b/primitives/npos-elections/Cargo.toml index 3a5b00dcdf77..3ee25f8ab816 100644 --- a/primitives/npos-elections/Cargo.toml +++ b/primitives/npos-elections/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -serde = { version = "1.0.126", optional = true, features = ["derive"] } +serde = { version = "1.0.131", optional = true, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-npos-elections-solution-type = { version = "4.0.0-dev", path = "./solution-type" } sp-arithmetic = { version = "4.0.0", default-features = false, path = "../arithmetic" } diff --git a/primitives/rpc/Cargo.toml b/primitives/rpc/Cargo.toml index e16280f95d35..fdc019bad4b6 100644 --- a/primitives/rpc/Cargo.toml +++ b/primitives/rpc/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -serde = { version = "1.0.126", features = ["derive"] } +serde = { version = "1.0.131", features = ["derive"] } sp-core = { version = "4.1.0-dev", path = "../core" } rustc-hash = "1.1.0" diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 6363a0a28631..a30bd08452d8 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] -serde = { version = "1.0.126", optional = true, features = ["derive"] } +serde = { version = "1.0.131", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } diff --git a/primitives/serializer/Cargo.toml b/primitives/serializer/Cargo.toml index 359217b9b4d5..89ddb28df272 100644 --- a/primitives/serializer/Cargo.toml +++ b/primitives/serializer/Cargo.toml @@ -14,5 +14,5 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -serde = "1.0.126" +serde = "1.0.131" serde_json = "1.0.71" diff --git a/primitives/storage/Cargo.toml b/primitives/storage/Cargo.toml index 918938273c62..98c8d693e9d6 100644 --- a/primitives/storage/Cargo.toml +++ b/primitives/storage/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-std = { version = "4.0.0", default-features = false, path = "../std" } -serde = { version = "1.0.126", optional = true, features = ["derive"] } +serde = { version = "1.0.131", optional = true, features = ["derive"] } impl-serde = { version = "0.3.1", optional = true } ref-cast = "1.0.0" sp-debug-derive = { version = "4.0.0", default-features = false, path = "../debug-derive" } diff --git a/primitives/test-primitives/Cargo.toml b/primitives/test-primitives/Cargo.toml index 5d0a3d440c46..5bc81637e82a 100644 --- a/primitives/test-primitives/Cargo.toml +++ b/primitives/test-primitives/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] sp-application-crypto = { version = "4.0.0", default-features = false, path = "../application-crypto" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } -serde = { version = "1.0.126", optional = true, features = ["derive"] } +serde = { version = "1.0.131", optional = true, features = ["derive"] } sp-runtime = { version = "4.0.0", default-features = false, path = "../runtime" } parity-util-mem = { version = "0.10.2", default-features = false, features = ["primitive-types"] } diff --git a/primitives/version/Cargo.toml b/primitives/version/Cargo.toml index b8a3a5bc3e30..b6ad02d4331f 100644 --- a/primitives/version/Cargo.toml +++ b/primitives/version/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] impl-serde = { version = "0.3.1", optional = true } -serde = { version = "1.0.126", optional = true, features = ["derive"] } +serde = { version = "1.0.131", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../std" } diff --git a/test-utils/client/Cargo.toml b/test-utils/client/Cargo.toml index 5d148ccd125e..c5a4a27c2ee9 100644 --- a/test-utils/client/Cargo.toml +++ b/test-utils/client/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0" } futures = "0.3.16" hex = "0.4" -serde = "1.0.126" +serde = "1.0.131" serde_json = "1.0.71" sc-client-api = { version = "4.0.0-dev", path = "../../client/api" } sc-client-db = { version = "0.10.0-dev", features = [ diff --git a/test-utils/runtime/Cargo.toml b/test-utils/runtime/Cargo.toml index 72e2c255c15c..ccaae6e69243 100644 --- a/test-utils/runtime/Cargo.toml +++ b/test-utils/runtime/Cargo.toml @@ -48,7 +48,7 @@ sp-externalities = { version = "0.10.0", default-features = false, path = "../.. # 3rd party cfg-if = "1.0" log = { version = "0.4.14", default-features = false } -serde = { version = "1.0.126", optional = true, features = ["derive"] } +serde = { version = "1.0.131", optional = true, features = ["derive"] } [dev-dependencies] sc-block-builder = { version = "0.10.0-dev", path = "../../client/block-builder" } diff --git a/utils/frame/benchmarking-cli/Cargo.toml b/utils/frame/benchmarking-cli/Cargo.toml index d61cf71aec38..fce53612e3ce 100644 --- a/utils/frame/benchmarking-cli/Cargo.toml +++ b/utils/frame/benchmarking-cli/Cargo.toml @@ -27,7 +27,7 @@ sp-state-machine = { version = "0.10.0", path = "../../../primitives/state-machi codec = { version = "2.0.0", package = "parity-scale-codec" } structopt = "0.3.25" chrono = "0.4" -serde = "1.0.126" +serde = "1.0.131" handlebars = "4.1.4" Inflector = "0.11.4" linked-hash-map = "0.5.4" diff --git a/utils/frame/remote-externalities/Cargo.toml b/utils/frame/remote-externalities/Cargo.toml index edd538baf562..969860c3df4b 100644 --- a/utils/frame/remote-externalities/Cargo.toml +++ b/utils/frame/remote-externalities/Cargo.toml @@ -20,7 +20,7 @@ frame-support = { path = "../../../frame/support", optional = true, version = "4 log = "0.4.11" codec = { package = "parity-scale-codec", version = "2.0.0" } serde_json = "1.0" -serde = "1.0.126" +serde = "1.0.131" sp-io = { version = "4.0.0-dev", path = "../../../primitives/io" } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } diff --git a/utils/frame/try-runtime/cli/Cargo.toml b/utils/frame/try-runtime/cli/Cargo.toml index a0eca3cc9e9c..8f84750f8ebf 100644 --- a/utils/frame/try-runtime/cli/Cargo.toml +++ b/utils/frame/try-runtime/cli/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] log = "0.4.8" parity-scale-codec = { version = "2.3.1" } -serde = "1.0.126" +serde = "1.0.131" structopt = "0.3.25" sc-service = { version = "0.10.0-dev", default-features = false, path = "../../../../client/service" } From a404abd3b38bd19627c7307597c99168a4f3b7bf Mon Sep 17 00:00:00 2001 From: Liu-Cheng Xu Date: Fri, 17 Dec 2021 17:43:51 +0800 Subject: [PATCH 307/695] Derive TypeInfo for OpaqueExtrinsic (#10504) --- primitives/runtime/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 26db5ef081a8..deea4a73c8e2 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -800,7 +800,7 @@ macro_rules! assert_eq_error_rate { /// Simple blob to hold an extrinsic without committing to its format and ensure it is serialized /// correctly. -#[derive(PartialEq, Eq, Clone, Default, Encode, Decode)] +#[derive(PartialEq, Eq, Clone, Default, Encode, Decode, TypeInfo)] pub struct OpaqueExtrinsic(Vec); impl OpaqueExtrinsic { From 5bd5b842d4ea520d281b1398e1f54907c9862fcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 17 Dec 2021 11:52:16 +0100 Subject: [PATCH 308/695] Remove offchain workers ownership. (#10506) --- docs/CODEOWNERS | 4 ---- 1 file changed, 4 deletions(-) diff --git a/docs/CODEOWNERS b/docs/CODEOWNERS index bf9e589ff487..70009d311f1c 100644 --- a/docs/CODEOWNERS +++ b/docs/CODEOWNERS @@ -27,10 +27,6 @@ /primitives/sr-sandbox/ @pepyakin /primitives/core/src/sandbox.rs @pepyakin -# Offchain -/client/offchain/ @tomusdrw -/primitives/offchain/ @tomusdrw - # GRANDPA, BABE, consensus stuff /frame/babe/ @andresilva /frame/grandpa/ @andresilva From efa4dfa97508b2fa3676da8fe99dbf6601fd04bf Mon Sep 17 00:00:00 2001 From: hamidra Date: Sat, 18 Dec 2021 07:41:05 -0800 Subject: [PATCH 309/695] Add ClassAccount storage to unique pallet (#9940) * add ClassAccount to uniques storage * add tests for Class and ClassAccount storage * fix format * fix description * add migration * remove extra iteration * Update frame/uniques/src/migration.rs Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> * cargo run --quiet --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_uniques --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/uniques/src/weights.rs --template=./.maintain/frame-weight-template.hbs * fix format Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Co-authored-by: Parity Bot Co-authored-by: Shawn Tabrizi --- Cargo.lock | 1 + frame/uniques/Cargo.toml | 1 + frame/uniques/src/functions.rs | 2 + frame/uniques/src/lib.rs | 29 ++++++- frame/uniques/src/migration.rs | 56 +++++++++++++ frame/uniques/src/tests.rs | 18 ++++- frame/uniques/src/weights.rs | 140 ++++++++++++++++++--------------- 7 files changed, 179 insertions(+), 68 deletions(-) create mode 100644 frame/uniques/src/migration.rs diff --git a/Cargo.lock b/Cargo.lock index 0c70bbdf6efc..797343de27f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6265,6 +6265,7 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", + "log 0.4.14", "pallet-balances", "parity-scale-codec", "scale-info", diff --git a/frame/uniques/Cargo.toml b/frame/uniques/Cargo.toml index c9892cac2697..a168c96778ad 100644 --- a/frame/uniques/Cargo.toml +++ b/frame/uniques/Cargo.toml @@ -20,6 +20,7 @@ sp-runtime = { version = "4.0.0", default-features = false, path = "../../primit frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } +log = { version = "0.4.14", default-features = false } [dev-dependencies] sp-std = { version = "4.0.0", path = "../../primitives/std" } diff --git a/frame/uniques/src/functions.rs b/frame/uniques/src/functions.rs index 43d634ad569e..e0ee09ab62d9 100644 --- a/frame/uniques/src/functions.rs +++ b/frame/uniques/src/functions.rs @@ -81,6 +81,7 @@ impl, I: 'static> Pallet { }, ); + ClassAccount::::insert(&owner, &class, ()); Self::deposit_event(event); Ok(()) } @@ -108,6 +109,7 @@ impl, I: 'static> Pallet { InstanceMetadataOf::::remove_prefix(&class, None); ClassMetadataOf::::remove(&class); Attribute::::remove_prefix((&class,), None); + ClassAccount::::remove(&class_details.owner, &class); T::Currency::unreserve(&class_details.owner, class_details.total_deposit); Self::deposit_event(Event::Destroyed { class }); diff --git a/frame/uniques/src/lib.rs b/frame/uniques/src/lib.rs index 7e380459252e..b5dada9ef645 100644 --- a/frame/uniques/src/lib.rs +++ b/frame/uniques/src/lib.rs @@ -40,6 +40,8 @@ mod impl_nonfungibles; mod types; pub use types::*; +mod migration; + use codec::{Decode, Encode, HasCompact}; use frame_support::traits::{BalanceStatus::Reserved, Currency, ReservableCurrency}; use frame_system::Config as SystemConfig; @@ -141,6 +143,19 @@ pub mod pallet { OptionQuery, >; + #[pallet::storage] + /// The classes owned by any given account; set out this way so that classes owned by a single + /// account can be enumerated. + pub(super) type ClassAccount, I: 'static = ()> = StorageDoubleMap< + _, + Blake2_128Concat, + T::AccountId, + Blake2_128Concat, + T::ClassId, + (), + OptionQuery, + >; + #[pallet::storage] /// The assets in existence and their ownership details. pub(super) type Asset, I: 'static = ()> = StorageDoubleMap< @@ -302,7 +317,11 @@ pub mod pallet { } #[pallet::hooks] - impl, I: 'static> Hooks> for Pallet {} + impl, I: 'static> Hooks> for Pallet { + fn on_runtime_upgrade() -> frame_support::weights::Weight { + migration::migrate_to_v1::() + } + } impl, I: 'static> Pallet { /// Get the owner of the asset instance, if the asset exists. @@ -731,6 +750,8 @@ pub mod pallet { details.total_deposit, Reserved, )?; + ClassAccount::::remove(&details.owner, &class); + ClassAccount::::insert(&owner, &class, ()); details.owner = owner.clone(); Self::deposit_event(Event::OwnerChanged { class, new_owner: owner }); @@ -906,13 +927,17 @@ pub mod pallet { Class::::try_mutate(class, |maybe_asset| { let mut asset = maybe_asset.take().ok_or(Error::::Unknown)?; - asset.owner = T::Lookup::lookup(owner)?; + let old_owner = asset.owner; + let new_owner = T::Lookup::lookup(owner)?; + asset.owner = new_owner.clone(); asset.issuer = T::Lookup::lookup(issuer)?; asset.admin = T::Lookup::lookup(admin)?; asset.freezer = T::Lookup::lookup(freezer)?; asset.free_holding = free_holding; asset.is_frozen = is_frozen; *maybe_asset = Some(asset); + ClassAccount::::remove(&old_owner, &class); + ClassAccount::::insert(&new_owner, &class, ()); Self::deposit_event(Event::AssetStatusChanged { class }); Ok(()) diff --git a/frame/uniques/src/migration.rs b/frame/uniques/src/migration.rs new file mode 100644 index 000000000000..76f78c2bc64e --- /dev/null +++ b/frame/uniques/src/migration.rs @@ -0,0 +1,56 @@ +// This file is part of Substrate. + +// Copyright (C) 2021 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. + +//! Various pieces of common functionality. +use super::*; +use frame_support::{ + traits::{Get, GetStorageVersion, PalletInfoAccess, StorageVersion}, + weights::Weight, +}; + +pub fn migrate_to_v1, I: 'static, P: GetStorageVersion + PalletInfoAccess>( +) -> frame_support::weights::Weight { + let on_chain_storage_version =

::on_chain_storage_version(); + log::info!( + target: "runtime::uniques", + "Running migration storage v1 for uniques with storage version {:?}", + on_chain_storage_version, + ); + + if on_chain_storage_version < 1 { + let mut count = 0; + for (class, detail) in Class::::iter() { + ClassAccount::::insert(&detail.owner, &class, ()); + count += 1; + } + StorageVersion::new(1).put::

(); + log::info!( + target: "runtime::uniques", + "Running migration storage v1 for uniques with storage version {:?} was complete", + on_chain_storage_version, + ); + // calculate and return migration weights + T::DbWeight::get().reads_writes(count as Weight + 1, count as Weight + 1) + } else { + log::warn!( + target: "runtime::uniques", + "Attempted to apply migration to v1 but failed because storage version is {:?}", + on_chain_storage_version, + ); + T::DbWeight::get().reads(1) + } +} diff --git a/frame/uniques/src/tests.rs b/frame/uniques/src/tests.rs index d23d694e949e..8d0d6fdf9af3 100644 --- a/frame/uniques/src/tests.rs +++ b/frame/uniques/src/tests.rs @@ -48,6 +48,15 @@ fn assets() -> Vec<(u64, u32, u32)> { r } +fn classes() -> Vec<(u64, u32)> { + let mut r: Vec<_> = ClassAccount::::iter().map(|x| (x.0, x.1)).collect(); + r.sort(); + let mut s: Vec<_> = Class::::iter().map(|x| (x.1.owner, x.0)).collect(); + s.sort(); + assert_eq!(r, s); + r +} + macro_rules! bvec { ($( $x:tt )*) => { vec![$( $x )*].try_into().unwrap() @@ -73,10 +82,12 @@ fn basic_setup_works() { fn basic_minting_should_work() { new_test_ext().execute_with(|| { assert_ok!(Uniques::force_create(Origin::root(), 0, 1, true)); + assert_eq!(classes(), vec![(1, 0)]); assert_ok!(Uniques::mint(Origin::signed(1), 0, 42, 1)); assert_eq!(assets(), vec![(1, 0, 42)]); assert_ok!(Uniques::force_create(Origin::root(), 1, 2, true)); + assert_eq!(classes(), vec![(1, 0), (2, 1)]); assert_ok!(Uniques::mint(Origin::signed(2), 1, 69, 1)); assert_eq!(assets(), vec![(1, 0, 42), (1, 1, 69)]); }); @@ -88,7 +99,7 @@ fn lifecycle_should_work() { Balances::make_free_balance_be(&1, 100); assert_ok!(Uniques::create(Origin::signed(1), 0, 1)); assert_eq!(Balances::reserved_balance(&1), 2); - + assert_eq!(classes(), vec![(1, 0)]); assert_ok!(Uniques::set_class_metadata(Origin::signed(1), 0, bvec![0, 0], false)); assert_eq!(Balances::reserved_balance(&1), 5); assert!(ClassMetadataOf::::contains_key(0)); @@ -120,6 +131,7 @@ fn lifecycle_should_work() { assert!(!ClassMetadataOf::::contains_key(0)); assert!(!InstanceMetadataOf::::contains_key(0, 42)); assert!(!InstanceMetadataOf::::contains_key(0, 69)); + assert_eq!(classes(), vec![]); assert_eq!(assets(), vec![]); }); } @@ -142,6 +154,7 @@ fn mint_should_work() { assert_ok!(Uniques::force_create(Origin::root(), 0, 1, true)); assert_ok!(Uniques::mint(Origin::signed(1), 0, 42, 1)); assert_eq!(Uniques::owner(0, 42).unwrap(), 1); + assert_eq!(classes(), vec![(1, 0)]); assert_eq!(assets(), vec![(1, 0, 42)]); }); } @@ -204,7 +217,9 @@ fn transfer_owner_should_work() { Balances::make_free_balance_be(&2, 100); Balances::make_free_balance_be(&3, 100); assert_ok!(Uniques::create(Origin::signed(1), 0, 1)); + assert_eq!(classes(), vec![(1, 0)]); assert_ok!(Uniques::transfer_ownership(Origin::signed(1), 0, 2)); + assert_eq!(classes(), vec![(2, 0)]); assert_eq!(Balances::total_balance(&1), 98); assert_eq!(Balances::total_balance(&2), 102); assert_eq!(Balances::reserved_balance(&1), 0); @@ -220,6 +235,7 @@ fn transfer_owner_should_work() { assert_ok!(Uniques::mint(Origin::signed(1), 0, 42, 1)); assert_ok!(Uniques::set_metadata(Origin::signed(2), 0, 42, bvec![0u8; 20], false)); assert_ok!(Uniques::transfer_ownership(Origin::signed(2), 0, 3)); + assert_eq!(classes(), vec![(3, 0)]); assert_eq!(Balances::total_balance(&2), 57); assert_eq!(Balances::total_balance(&3), 145); assert_eq!(Balances::reserved_balance(&2), 0); diff --git a/frame/uniques/src/weights.rs b/frame/uniques/src/weights.rs index 40d1ddfdc556..168e0fcc8015 100644 --- a/frame/uniques/src/weights.rs +++ b/frame/uniques/src/weights.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_uniques //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-08-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2021-11-02, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 // Executed Command: @@ -73,34 +73,37 @@ pub trait WeightInfo { pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { // Storage: Uniques Class (r:1 w:1) + // Storage: Uniques ClassAccount (r:0 w:1) fn create() -> Weight { - (42_138_000 as Weight) + (41_109_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Uniques Class (r:1 w:1) + // Storage: Uniques ClassAccount (r:0 w:1) fn force_create() -> Weight { - (22_238_000 as Weight) + (22_986_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Uniques Class (r:1 w:1) // Storage: Uniques Asset (r:1 w:0) + // Storage: Uniques ClassAccount (r:0 w:1) // Storage: Uniques Attribute (r:0 w:1000) // Storage: Uniques ClassMetadataOf (r:0 w:1) // Storage: Uniques InstanceMetadataOf (r:0 w:1000) // Storage: Uniques Account (r:0 w:20) fn destroy(n: u32, m: u32, a: u32, ) -> Weight { (0 as Weight) - // Standard Error: 12_000 - .saturating_add((16_171_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 12_000 + // Standard Error: 14_000 + .saturating_add((14_879_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 14_000 .saturating_add((1_058_000 as Weight).saturating_mul(m as Weight)) - // Standard Error: 12_000 - .saturating_add((953_000 as Weight).saturating_mul(a as Weight)) + // Standard Error: 14_000 + .saturating_add((956_000 as Weight).saturating_mul(a as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(n as Weight))) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) .saturating_add(T::DbWeight::get().writes((2 as Weight).saturating_mul(n as Weight))) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(m as Weight))) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(a as Weight))) @@ -109,7 +112,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Uniques Class (r:1 w:1) // Storage: Uniques Account (r:0 w:1) fn mint() -> Weight { - (55_359_000 as Weight) + (51_248_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -117,7 +120,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Uniques Asset (r:1 w:1) // Storage: Uniques Account (r:0 w:1) fn burn() -> Weight { - (58_254_000 as Weight) + (53_172_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -125,7 +128,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Uniques Asset (r:1 w:1) // Storage: Uniques Account (r:0 w:2) fn transfer() -> Weight { - (42_906_000 as Weight) + (39_680_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -133,8 +136,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Uniques Asset (r:100 w:100) fn redeposit(i: u32, ) -> Weight { (0 as Weight) - // Standard Error: 9_000 - .saturating_add((25_237_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 12_000 + .saturating_add((22_759_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -143,53 +146,55 @@ impl WeightInfo for SubstrateWeight { // Storage: Uniques Asset (r:1 w:1) // Storage: Uniques Class (r:1 w:0) fn freeze() -> Weight { - (30_153_000 as Weight) + (27_833_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Uniques Asset (r:1 w:1) // Storage: Uniques Class (r:1 w:0) fn thaw() -> Weight { - (31_212_000 as Weight) + (27_739_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Uniques Class (r:1 w:1) fn freeze_class() -> Weight { - (22_689_000 as Weight) + (20_890_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Uniques Class (r:1 w:1) fn thaw_class() -> Weight { - (22_647_000 as Weight) + (20_848_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Uniques Class (r:1 w:1) // Storage: System Account (r:1 w:1) + // Storage: Uniques ClassAccount (r:0 w:2) fn transfer_ownership() -> Weight { - (50_902_000 as Weight) + (51_523_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(4 as Weight)) } // Storage: Uniques Class (r:1 w:1) fn set_team() -> Weight { - (23_632_000 as Weight) + (22_034_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Uniques Class (r:1 w:1) + // Storage: Uniques ClassAccount (r:0 w:1) fn force_asset_status() -> Weight { - (22_508_000 as Weight) + (25_877_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Uniques Class (r:1 w:1) // Storage: Uniques InstanceMetadataOf (r:1 w:0) // Storage: Uniques Attribute (r:1 w:1) fn set_attribute() -> Weight { - (69_942_000 as Weight) + (63_365_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -197,49 +202,49 @@ impl WeightInfo for SubstrateWeight { // Storage: Uniques InstanceMetadataOf (r:1 w:0) // Storage: Uniques Attribute (r:1 w:1) fn clear_attribute() -> Weight { - (62_314_000 as Weight) + (56_849_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Uniques Class (r:1 w:1) // Storage: Uniques InstanceMetadataOf (r:1 w:1) fn set_metadata() -> Weight { - (52_647_000 as Weight) + (47_982_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Uniques Class (r:1 w:1) // Storage: Uniques InstanceMetadataOf (r:1 w:1) fn clear_metadata() -> Weight { - (50_391_000 as Weight) + (47_340_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Uniques Class (r:1 w:1) // Storage: Uniques ClassMetadataOf (r:1 w:1) fn set_class_metadata() -> Weight { - (50_928_000 as Weight) + (46_897_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Uniques Class (r:1 w:0) // Storage: Uniques ClassMetadataOf (r:1 w:1) fn clear_class_metadata() -> Weight { - (46_667_000 as Weight) + (41_745_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Uniques Class (r:1 w:0) // Storage: Uniques Asset (r:1 w:1) fn approve_transfer() -> Weight { - (32_111_000 as Weight) + (29_828_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Uniques Class (r:1 w:0) // Storage: Uniques Asset (r:1 w:1) fn cancel_approval() -> Weight { - (32_627_000 as Weight) + (29_759_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -248,34 +253,37 @@ impl WeightInfo for SubstrateWeight { // For backwards compatibility and tests impl WeightInfo for () { // Storage: Uniques Class (r:1 w:1) + // Storage: Uniques ClassAccount (r:0 w:1) fn create() -> Weight { - (42_138_000 as Weight) + (41_109_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Uniques Class (r:1 w:1) + // Storage: Uniques ClassAccount (r:0 w:1) fn force_create() -> Weight { - (22_238_000 as Weight) + (22_986_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Uniques Class (r:1 w:1) // Storage: Uniques Asset (r:1 w:0) + // Storage: Uniques ClassAccount (r:0 w:1) // Storage: Uniques Attribute (r:0 w:1000) // Storage: Uniques ClassMetadataOf (r:0 w:1) // Storage: Uniques InstanceMetadataOf (r:0 w:1000) // Storage: Uniques Account (r:0 w:20) fn destroy(n: u32, m: u32, a: u32, ) -> Weight { (0 as Weight) - // Standard Error: 12_000 - .saturating_add((16_171_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 12_000 + // Standard Error: 14_000 + .saturating_add((14_879_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 14_000 .saturating_add((1_058_000 as Weight).saturating_mul(m as Weight)) - // Standard Error: 12_000 - .saturating_add((953_000 as Weight).saturating_mul(a as Weight)) + // Standard Error: 14_000 + .saturating_add((956_000 as Weight).saturating_mul(a as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(n as Weight))) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) .saturating_add(RocksDbWeight::get().writes((2 as Weight).saturating_mul(n as Weight))) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(m as Weight))) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(a as Weight))) @@ -284,7 +292,7 @@ impl WeightInfo for () { // Storage: Uniques Class (r:1 w:1) // Storage: Uniques Account (r:0 w:1) fn mint() -> Weight { - (55_359_000 as Weight) + (51_248_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -292,7 +300,7 @@ impl WeightInfo for () { // Storage: Uniques Asset (r:1 w:1) // Storage: Uniques Account (r:0 w:1) fn burn() -> Weight { - (58_254_000 as Weight) + (53_172_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -300,7 +308,7 @@ impl WeightInfo for () { // Storage: Uniques Asset (r:1 w:1) // Storage: Uniques Account (r:0 w:2) fn transfer() -> Weight { - (42_906_000 as Weight) + (39_680_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -308,8 +316,8 @@ impl WeightInfo for () { // Storage: Uniques Asset (r:100 w:100) fn redeposit(i: u32, ) -> Weight { (0 as Weight) - // Standard Error: 9_000 - .saturating_add((25_237_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 12_000 + .saturating_add((22_759_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -318,53 +326,55 @@ impl WeightInfo for () { // Storage: Uniques Asset (r:1 w:1) // Storage: Uniques Class (r:1 w:0) fn freeze() -> Weight { - (30_153_000 as Weight) + (27_833_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Uniques Asset (r:1 w:1) // Storage: Uniques Class (r:1 w:0) fn thaw() -> Weight { - (31_212_000 as Weight) + (27_739_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Uniques Class (r:1 w:1) fn freeze_class() -> Weight { - (22_689_000 as Weight) + (20_890_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Uniques Class (r:1 w:1) fn thaw_class() -> Weight { - (22_647_000 as Weight) + (20_848_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Uniques Class (r:1 w:1) // Storage: System Account (r:1 w:1) + // Storage: Uniques ClassAccount (r:0 w:2) fn transfer_ownership() -> Weight { - (50_902_000 as Weight) + (51_523_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } // Storage: Uniques Class (r:1 w:1) fn set_team() -> Weight { - (23_632_000 as Weight) + (22_034_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Uniques Class (r:1 w:1) + // Storage: Uniques ClassAccount (r:0 w:1) fn force_asset_status() -> Weight { - (22_508_000 as Weight) + (25_877_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Uniques Class (r:1 w:1) // Storage: Uniques InstanceMetadataOf (r:1 w:0) // Storage: Uniques Attribute (r:1 w:1) fn set_attribute() -> Weight { - (69_942_000 as Weight) + (63_365_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -372,49 +382,49 @@ impl WeightInfo for () { // Storage: Uniques InstanceMetadataOf (r:1 w:0) // Storage: Uniques Attribute (r:1 w:1) fn clear_attribute() -> Weight { - (62_314_000 as Weight) + (56_849_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Uniques Class (r:1 w:1) // Storage: Uniques InstanceMetadataOf (r:1 w:1) fn set_metadata() -> Weight { - (52_647_000 as Weight) + (47_982_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Uniques Class (r:1 w:1) // Storage: Uniques InstanceMetadataOf (r:1 w:1) fn clear_metadata() -> Weight { - (50_391_000 as Weight) + (47_340_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Uniques Class (r:1 w:1) // Storage: Uniques ClassMetadataOf (r:1 w:1) fn set_class_metadata() -> Weight { - (50_928_000 as Weight) + (46_897_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Uniques Class (r:1 w:0) // Storage: Uniques ClassMetadataOf (r:1 w:1) fn clear_class_metadata() -> Weight { - (46_667_000 as Weight) + (41_745_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Uniques Class (r:1 w:0) // Storage: Uniques Asset (r:1 w:1) fn approve_transfer() -> Weight { - (32_111_000 as Weight) + (29_828_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Uniques Class (r:1 w:0) // Storage: Uniques Asset (r:1 w:1) fn cancel_approval() -> Weight { - (32_627_000 as Weight) + (29_759_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } From 8f4facada78e51dd7a16b332c2203b30c037d4d4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 19 Dec 2021 11:26:37 +0100 Subject: [PATCH 310/695] Bump syn from 1.0.81 to 1.0.82 (#10505) Bumps [syn](https://github.com/dtolnay/syn) from 1.0.81 to 1.0.82. - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/1.0.81...1.0.82) --- updated-dependencies: - dependency-name: syn dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- client/chain-spec/derive/Cargo.toml | 2 +- client/tracing/proc-macro/Cargo.toml | 2 +- frame/staking/reward-curve/Cargo.toml | 2 +- frame/support/procedural/Cargo.toml | 2 +- frame/support/procedural/tools/Cargo.toml | 2 +- frame/support/procedural/tools/derive/Cargo.toml | 2 +- primitives/api/proc-macro/Cargo.toml | 2 +- primitives/core/hashing/proc-macro/Cargo.toml | 2 +- primitives/debug-derive/Cargo.toml | 2 +- primitives/npos-elections/solution-type/Cargo.toml | 2 +- primitives/runtime-interface/proc-macro/Cargo.toml | 2 +- primitives/version/proc-macro/Cargo.toml | 2 +- test-utils/derive/Cargo.toml | 2 +- 14 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 797343de27f1..e7d2ae9d50d0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10330,9 +10330,9 @@ checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2" [[package]] name = "syn" -version = "1.0.81" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2afee18b8beb5a596ecb4a2dce128c719b4ba399d34126b9e4396e3f9860966" +checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" dependencies = [ "proc-macro2", "quote", diff --git a/client/chain-spec/derive/Cargo.toml b/client/chain-spec/derive/Cargo.toml index 3ffb70d50ef5..97573c8ca3b0 100644 --- a/client/chain-spec/derive/Cargo.toml +++ b/client/chain-spec/derive/Cargo.toml @@ -18,6 +18,6 @@ proc-macro = true proc-macro-crate = "1.1.0" proc-macro2 = "1.0.29" quote = "1.0.10" -syn = "1.0.81" +syn = "1.0.82" [dev-dependencies] diff --git a/client/tracing/proc-macro/Cargo.toml b/client/tracing/proc-macro/Cargo.toml index 39c22bf856b2..53d463a4f4e5 100644 --- a/client/tracing/proc-macro/Cargo.toml +++ b/client/tracing/proc-macro/Cargo.toml @@ -18,4 +18,4 @@ proc-macro = true proc-macro-crate = "1.1.0" proc-macro2 = "1.0.29" quote = { version = "1.0.10", features = ["proc-macro"] } -syn = { version = "1.0.81", features = ["proc-macro", "full", "extra-traits", "parsing"] } +syn = { version = "1.0.82", features = ["proc-macro", "full", "extra-traits", "parsing"] } diff --git a/frame/staking/reward-curve/Cargo.toml b/frame/staking/reward-curve/Cargo.toml index 82f0a6dde2be..7d95152ea65a 100644 --- a/frame/staking/reward-curve/Cargo.toml +++ b/frame/staking/reward-curve/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] proc-macro = true [dependencies] -syn = { version = "1.0.81", features = ["full", "visit"] } +syn = { version = "1.0.82", features = ["full", "visit"] } quote = "1.0.10" proc-macro2 = "1.0.29" proc-macro-crate = "1.1.0" diff --git a/frame/support/procedural/Cargo.toml b/frame/support/procedural/Cargo.toml index b47cf7f97956..7a1eaa3a0817 100644 --- a/frame/support/procedural/Cargo.toml +++ b/frame/support/procedural/Cargo.toml @@ -19,7 +19,7 @@ frame-support-procedural-tools = { version = "4.0.0-dev", path = "./tools" } proc-macro2 = "1.0.29" quote = "1.0.10" Inflector = "0.11.4" -syn = { version = "1.0.81", features = ["full"] } +syn = { version = "1.0.82", features = ["full"] } [features] default = ["std"] diff --git a/frame/support/procedural/tools/Cargo.toml b/frame/support/procedural/tools/Cargo.toml index c0a3b98632f5..265952ebc4b7 100644 --- a/frame/support/procedural/tools/Cargo.toml +++ b/frame/support/procedural/tools/Cargo.toml @@ -15,5 +15,5 @@ targets = ["x86_64-unknown-linux-gnu"] frame-support-procedural-tools-derive = { version = "3.0.0", path = "./derive" } proc-macro2 = "1.0.29" quote = "1.0.10" -syn = { version = "1.0.81", features = ["full", "visit", "extra-traits"] } +syn = { version = "1.0.82", features = ["full", "visit", "extra-traits"] } proc-macro-crate = "1.1.0" diff --git a/frame/support/procedural/tools/derive/Cargo.toml b/frame/support/procedural/tools/derive/Cargo.toml index 8327134b3fb4..df994e14226d 100644 --- a/frame/support/procedural/tools/derive/Cargo.toml +++ b/frame/support/procedural/tools/derive/Cargo.toml @@ -17,4 +17,4 @@ proc-macro = true [dependencies] proc-macro2 = "1.0.29" quote = { version = "1.0.10", features = ["proc-macro"] } -syn = { version = "1.0.81", features = ["proc-macro" ,"full", "extra-traits", "parsing"] } +syn = { version = "1.0.82", features = ["proc-macro" ,"full", "extra-traits", "parsing"] } diff --git a/primitives/api/proc-macro/Cargo.toml b/primitives/api/proc-macro/Cargo.toml index c8eaae7c02ab..4afc07833649 100644 --- a/primitives/api/proc-macro/Cargo.toml +++ b/primitives/api/proc-macro/Cargo.toml @@ -17,7 +17,7 @@ proc-macro = true [dependencies] quote = "1.0.10" -syn = { version = "1.0.81", features = ["full", "fold", "extra-traits", "visit"] } +syn = { version = "1.0.82", features = ["full", "fold", "extra-traits", "visit"] } proc-macro2 = "1.0.29" blake2-rfc = { version = "0.2.18", default-features = false } proc-macro-crate = "1.1.0" diff --git a/primitives/core/hashing/proc-macro/Cargo.toml b/primitives/core/hashing/proc-macro/Cargo.toml index dcd2f134519e..4df40e55bc90 100644 --- a/primitives/core/hashing/proc-macro/Cargo.toml +++ b/primitives/core/hashing/proc-macro/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] proc-macro = true [dependencies] -syn = { version = "1.0.81", features = ["full", "parsing"] } +syn = { version = "1.0.82", features = ["full", "parsing"] } quote = "1.0.6" proc-macro2 = "1.0.29" sp-core-hashing = { version = "4.0.0", path = "../", default-features = false } diff --git a/primitives/debug-derive/Cargo.toml b/primitives/debug-derive/Cargo.toml index a38cc186fb52..5852bd428d3e 100644 --- a/primitives/debug-derive/Cargo.toml +++ b/primitives/debug-derive/Cargo.toml @@ -18,7 +18,7 @@ proc-macro = true [dependencies] quote = "1.0.10" -syn = "1.0.81" +syn = "1.0.82" proc-macro2 = "1.0" [features] diff --git a/primitives/npos-elections/solution-type/Cargo.toml b/primitives/npos-elections/solution-type/Cargo.toml index 160778857f39..cf2a2016500a 100644 --- a/primitives/npos-elections/solution-type/Cargo.toml +++ b/primitives/npos-elections/solution-type/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] proc-macro = true [dependencies] -syn = { version = "1.0.81", features = ["full", "visit"] } +syn = { version = "1.0.82", features = ["full", "visit"] } quote = "1.0" proc-macro2 = "1.0.29" proc-macro-crate = "1.1.0" diff --git a/primitives/runtime-interface/proc-macro/Cargo.toml b/primitives/runtime-interface/proc-macro/Cargo.toml index 0b5929616bd3..031906486b55 100644 --- a/primitives/runtime-interface/proc-macro/Cargo.toml +++ b/primitives/runtime-interface/proc-macro/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] proc-macro = true [dependencies] -syn = { version = "1.0.81", features = ["full", "visit", "fold", "extra-traits"] } +syn = { version = "1.0.82", features = ["full", "visit", "fold", "extra-traits"] } quote = "1.0.10" proc-macro2 = "1.0.29" Inflector = "0.11.4" diff --git a/primitives/version/proc-macro/Cargo.toml b/primitives/version/proc-macro/Cargo.toml index 79fb9b18a238..df254e64f34c 100644 --- a/primitives/version/proc-macro/Cargo.toml +++ b/primitives/version/proc-macro/Cargo.toml @@ -17,7 +17,7 @@ proc-macro = true [dependencies] quote = "1.0.10" -syn = { version = "1.0.81", features = ["full", "fold", "extra-traits", "visit"] } +syn = { version = "1.0.82", features = ["full", "fold", "extra-traits", "visit"] } proc-macro2 = "1.0.29" codec = { package = "parity-scale-codec", version = "2.0.0", features = [ "derive" ] } diff --git a/test-utils/derive/Cargo.toml b/test-utils/derive/Cargo.toml index 0b894d92b2bc..83782a2ba5ff 100644 --- a/test-utils/derive/Cargo.toml +++ b/test-utils/derive/Cargo.toml @@ -10,7 +10,7 @@ description = "Substrate test utilities macros" [dependencies] quote = "1.0.10" -syn = { version = "1.0.81", features = ["full"] } +syn = { version = "1.0.82", features = ["full"] } proc-macro-crate = "1.1.0" proc-macro2 = "1.0.29" From 2c1eaaae147fae546c7d1e7cd7177cbaaf196f49 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Dec 2021 09:56:16 +0000 Subject: [PATCH 311/695] Bump tokio from 1.13.0 to 1.15.0 (#10512) Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.13.0 to 1.15.0. - [Release notes](https://github.com/tokio-rs/tokio/releases) - [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.13.0...tokio-1.15.0) --- updated-dependencies: - dependency-name: tokio dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 9 ++++----- bin/node/cli/Cargo.toml | 2 +- client/cli/Cargo.toml | 2 +- client/consensus/manual-seal/Cargo.toml | 2 +- client/finality-grandpa/Cargo.toml | 2 +- client/offchain/Cargo.toml | 2 +- client/rpc-servers/Cargo.toml | 2 +- client/service/Cargo.toml | 2 +- client/service/test/Cargo.toml | 2 +- test-utils/test-crate/Cargo.toml | 2 +- test-utils/test-runner/Cargo.toml | 2 +- utils/frame/remote-externalities/Cargo.toml | 2 +- utils/frame/rpc/support/Cargo.toml | 2 +- utils/prometheus/Cargo.toml | 4 ++-- 14 files changed, 18 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e7d2ae9d50d0..51fc8b9d8775 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10572,11 +10572,10 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.13.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "588b2d10a336da58d877567cd8fb8a14b463e2104910f8132cd054b4b96e29ee" +checksum = "fbbf1c778ec206785635ce8ad57fe52b3009ae9e0c9f574a728f3049d3e55838" dependencies = [ - "autocfg 1.0.1", "bytes 1.0.1", "libc", "memchr", @@ -10624,9 +10623,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "1.3.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54473be61f4ebe4efd09cec9bd5d16fa51d70ea0192213d754d2d500457db110" +checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" dependencies = [ "proc-macro2", "quote", diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index a967dd133211..671388d55d82 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -130,7 +130,7 @@ platforms = "2.0" async-std = { version = "1.10.0", features = ["attributes"] } soketto = "0.4.2" criterion = { version = "0.3.5", features = [ "async_tokio" ] } -tokio = { version = "1.13", features = ["macros", "time"] } +tokio = { version = "1.15", features = ["macros", "time"] } jsonrpsee-ws-client = "0.4.1" wait-timeout = "0.2" remote-externalities = { path = "../../../utils/frame/remote-externalities" } diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index cb9d09bbdbc7..84063fa8fc23 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] log = "0.4.11" regex = "1.5.4" -tokio = { version = "1.13", features = [ "signal", "rt-multi-thread" ] } +tokio = { version = "1.15", features = [ "signal", "rt-multi-thread" ] } futures = "0.3.9" fdlimit = "0.2.1" libp2p = "0.40.0" diff --git a/client/consensus/manual-seal/Cargo.toml b/client/consensus/manual-seal/Cargo.toml index c69ed21fb3a9..a4bb63a7a270 100644 --- a/client/consensus/manual-seal/Cargo.toml +++ b/client/consensus/manual-seal/Cargo.toml @@ -45,7 +45,7 @@ sp-timestamp = { path = "../../../primitives/timestamp", version = "4.0.0-dev" } prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.10.0-dev" } [dev-dependencies] -tokio = { version = "1.13.0", features = ["rt-multi-thread", "macros"] } +tokio = { version = "1.15.0", features = ["rt-multi-thread", "macros"] } sc-basic-authorship = { path = "../../basic-authorship", version = "0.10.0-dev" } substrate-test-runtime-client = { path = "../../../test-utils/runtime/client", version = "2.0.0" } substrate-test-runtime-transaction-pool = { path = "../../../test-utils/runtime/transaction-pool", version = "2.0.0" } diff --git a/client/finality-grandpa/Cargo.toml b/client/finality-grandpa/Cargo.toml index e296c5a4e3da..6e7463792e7b 100644 --- a/client/finality-grandpa/Cargo.toml +++ b/client/finality-grandpa/Cargo.toml @@ -57,5 +57,5 @@ sc-network-test = { version = "0.8.0", path = "../network/test" } sp-keyring = { version = "4.0.0-dev", path = "../../primitives/keyring" } substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } -tokio = "1.13" +tokio = "1.15" tempfile = "3.1.0" diff --git a/client/offchain/Cargo.toml b/client/offchain/Cargo.toml index 4271c7f5d2b2..36921944965f 100644 --- a/client/offchain/Cargo.toml +++ b/client/offchain/Cargo.toml @@ -43,7 +43,7 @@ sc-transaction-pool-api = { version = "4.0.0-dev", path = "../transaction-pool/a sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } -tokio = "1.13" +tokio = "1.15" lazy_static = "1.4.0" [features] diff --git a/client/rpc-servers/Cargo.toml b/client/rpc-servers/Cargo.toml index f6f08ac581d4..ae450c2ba9a2 100644 --- a/client/rpc-servers/Cargo.toml +++ b/client/rpc-servers/Cargo.toml @@ -19,7 +19,7 @@ pubsub = { package = "jsonrpc-pubsub", version = "18.0.0" } log = "0.4.8" prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.10.0-dev"} serde_json = "1.0.71" -tokio = "1.13" +tokio = "1.15" http = { package = "jsonrpc-http-server", version = "18.0.0" } ipc = { package = "jsonrpc-ipc-server", version = "18.0.0" } ws = { package = "jsonrpc-ws-server", version = "18.0.0" } diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index 4d88f403005e..0f093970e417 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -78,7 +78,7 @@ parity-util-mem = { version = "0.10.2", default-features = false, features = [ "primitive-types", ] } async-trait = "0.1.50" -tokio = { version = "1.13", features = ["time", "rt-multi-thread"] } +tokio = { version = "1.15", features = ["time", "rt-multi-thread"] } tempfile = "3.1.0" directories = "4.0.1" diff --git a/client/service/test/Cargo.toml b/client/service/test/Cargo.toml index a8088ebb08cb..5073f46eb0ef 100644 --- a/client/service/test/Cargo.toml +++ b/client/service/test/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] hex = "0.4" hex-literal = "0.3.4" tempfile = "3.1.0" -tokio = { version = "1.13.0", features = ["time"] } +tokio = { version = "1.15.0", features = ["time"] } log = "0.4.8" fdlimit = "0.2.1" parking_lot = "0.11.2" diff --git a/test-utils/test-crate/Cargo.toml b/test-utils/test-crate/Cargo.toml index 4621332ccc0c..4e07f92e86ea 100644 --- a/test-utils/test-crate/Cargo.toml +++ b/test-utils/test-crate/Cargo.toml @@ -12,6 +12,6 @@ publish = false targets = ["x86_64-unknown-linux-gnu"] [dev-dependencies] -tokio = { version = "1.13", features = ["macros"] } +tokio = { version = "1.15", features = ["macros"] } test-utils = { version = "4.0.0-dev", path = "..", package = "substrate-test-utils" } sc-service = { version = "0.10.0-dev", path = "../../client/service" } diff --git a/test-utils/test-runner/Cargo.toml b/test-utils/test-runner/Cargo.toml index eb565fd7b587..78e17d0f23b6 100644 --- a/test-utils/test-runner/Cargo.toml +++ b/test-utils/test-runner/Cargo.toml @@ -48,7 +48,7 @@ frame-system = { path = "../../frame/system" } log = "0.4.8" futures = "0.3.16" -tokio = { version = "1.13", features = ["signal"] } +tokio = { version = "1.15", features = ["signal"] } # Calling RPC jsonrpc-core = "18.0" num-traits = "0.2.14" diff --git a/utils/frame/remote-externalities/Cargo.toml b/utils/frame/remote-externalities/Cargo.toml index 969860c3df4b..df6ef5c70419 100644 --- a/utils/frame/remote-externalities/Cargo.toml +++ b/utils/frame/remote-externalities/Cargo.toml @@ -28,7 +28,7 @@ sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } sp-version = { version = "4.0.0-dev", path = "../../../primitives/version" } [dev-dependencies] -tokio = { version = "1.13", features = ["macros", "rt-multi-thread"] } +tokio = { version = "1.15", features = ["macros", "rt-multi-thread"] } pallet-elections-phragmen = { path = "../../../frame/elections-phragmen", version = "5.0.0-dev" } frame-support = { path = "../../../frame/support", version = "4.0.0-dev" } diff --git a/utils/frame/rpc/support/Cargo.toml b/utils/frame/rpc/support/Cargo.toml index 8e491cc634de..6ecaabd72059 100644 --- a/utils/frame/rpc/support/Cargo.toml +++ b/utils/frame/rpc/support/Cargo.toml @@ -26,4 +26,4 @@ sc-rpc-api = { version = "0.10.0-dev", path = "../../../../client/rpc-api" } [dev-dependencies] frame-system = { version = "4.0.0-dev", path = "../../../../frame/system" } scale-info = "1.0" -tokio = "1.13" +tokio = "1.15" diff --git a/utils/prometheus/Cargo.toml b/utils/prometheus/Cargo.toml index e2104ec5d55a..43f8b62b9c7b 100644 --- a/utils/prometheus/Cargo.toml +++ b/utils/prometheus/Cargo.toml @@ -18,9 +18,9 @@ prometheus = { version = "0.13.0", default-features = false } futures-util = { version = "0.3.17", default-features = false, features = ["io"] } derive_more = "0.99" async-std = { version = "1.10.0", features = ["unstable"] } -tokio = "1.13" +tokio = "1.15" hyper = { version = "0.14.14", default-features = false, features = ["http1", "server", "tcp"] } [dev-dependencies] hyper = { version = "0.14.14", features = ["client"] } -tokio = { version = "1.13", features = ["rt-multi-thread"] } +tokio = { version = "1.15", features = ["rt-multi-thread"] } From bd763f2809e501f561aea55eba1145bca93bd9a8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Dec 2021 13:08:23 +0100 Subject: [PATCH 312/695] Bump ss58-registry from 1.5.0 to 1.10.0 (#10515) Bumps [ss58-registry](https://github.com/paritytech/ss58-registry) from 1.5.0 to 1.10.0. - [Release notes](https://github.com/paritytech/ss58-registry/releases) - [Changelog](https://github.com/paritytech/ss58-registry/blob/main/CHANGELOG.md) - [Commits](https://github.com/paritytech/ss58-registry/compare/v1.5.0...v1.10.0) --- updated-dependencies: - dependency-name: ss58-registry dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- primitives/core/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 51fc8b9d8775..0e16ece4be62 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9987,9 +9987,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "ss58-registry" -version = "1.5.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66cd4c4bb7ee41dc5b0c13d600574ae825d3a02e8f31326b17ac71558f2c836" +checksum = "c83f0afe7e571565ef9aae7b0e4fb30fcaec4ebb9aea2f00489b772782aa03a4" dependencies = [ "Inflector", "proc-macro2", diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index 1ec9b5b46f1b..a74fc75cb203 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -67,7 +67,7 @@ hex = { version = "0.4", default-features = false, optional = true } twox-hash = { version = "1.6.1", default-features = false, optional = true } libsecp256k1 = { version = "0.7", default-features = false, features = ["hmac", "static-context"], optional = true } merlin = { version = "2.0", default-features = false, optional = true } -ss58-registry = { version = "1.5.0", default-features = false } +ss58-registry = { version = "1.10.0", default-features = false } sp-core-hashing = { version = "4.0.0", path = "./hashing", default-features = false, optional = true } sp-runtime-interface = { version = "4.1.0-dev", default-features = false, path = "../runtime-interface" } From 3fef614506aed18bb14d2036e70faa42f47c2c0f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Dec 2021 12:25:01 +0000 Subject: [PATCH 313/695] Bump bytes from 1.0.1 to 1.1.0 (#10223) Bumps [bytes](https://github.com/tokio-rs/bytes) from 1.0.1 to 1.1.0. - [Release notes](https://github.com/tokio-rs/bytes/releases) - [Changelog](https://github.com/tokio-rs/bytes/blob/master/CHANGELOG.md) - [Commits](https://github.com/tokio-rs/bytes/compare/v1.0.1...v1.1.0) --- updated-dependencies: - dependency-name: bytes dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 58 +++++++++++++++++++------------------- client/offchain/Cargo.toml | 2 +- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0e16ece4be62..84584dbab91c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -355,7 +355,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb4401f0a3622dad2e0763fa79e0eb328bc70fb7dccfdd645341f00d671247d6" dependencies = [ - "bytes 1.0.1", + "bytes 1.1.0", "futures-sink", "futures-util", "memchr", @@ -368,7 +368,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0de5164e5edbf51c45fb8c2d9664ae1c095cce1b265ecf7569093c0d66ef690" dependencies = [ - "bytes 1.0.1", + "bytes 1.1.0", "futures-sink", "futures-util", "memchr", @@ -799,9 +799,9 @@ checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" [[package]] name = "bytes" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040" +checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" [[package]] name = "cache-padded" @@ -2560,7 +2560,7 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fd819562fcebdac5afc5c113c3ec36f902840b70fd4fc458799c8ce4607ae55" dependencies = [ - "bytes 1.0.1", + "bytes 1.1.0", "fnv", "futures-core", "futures-sink", @@ -2718,7 +2718,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7245cd7449cc792608c3c8a9eaf69bd4eabbabf802713748fd739c98b82f0747" dependencies = [ - "bytes 1.0.1", + "bytes 1.1.0", "fnv", "itoa", ] @@ -2729,7 +2729,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60daa14be0e0786db0f03a9e57cb404c9d756eed2b6c62b9ea98ec5743ec75a9" dependencies = [ - "bytes 1.0.1", + "bytes 1.1.0", "http", "pin-project-lite 0.2.6", ] @@ -2786,7 +2786,7 @@ version = "0.14.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b91bb1f221b6ea1f1e4371216b70f40748774c2fb5971b450c07773fb92d26b" dependencies = [ - "bytes 1.0.1", + "bytes 1.1.0", "futures-channel", "futures-core", "futures-util", @@ -2827,7 +2827,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ - "bytes 1.0.1", + "bytes 1.1.0", "hyper 0.14.14", "native-tls", "tokio", @@ -3152,7 +3152,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa4fdea130485b572c39a460d50888beb00afb3e35de23ccd7fad8ff19f0e0d4" dependencies = [ - "bytes 1.0.1", + "bytes 1.1.0", "futures 0.3.16", "globset", "jsonrpc-core", @@ -3418,7 +3418,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3bec54343492ba5940a6c555e512c6721139835d28c59bc22febece72dfd0d9d" dependencies = [ "atomic", - "bytes 1.0.1", + "bytes 1.1.0", "futures 0.3.16", "lazy_static", "libp2p-core", @@ -3538,7 +3538,7 @@ dependencies = [ "asynchronous-codec 0.6.0", "base64 0.13.0", "byteorder", - "bytes 1.0.1", + "bytes 1.1.0", "fnv", "futures 0.3.16", "hex_fmt", @@ -3580,7 +3580,7 @@ checksum = "a2297dc0ca285f3a09d1368bde02449e539b46f94d32d53233f53f6625bcd3ba" dependencies = [ "arrayvec 0.5.2", "asynchronous-codec 0.6.0", - "bytes 1.0.1", + "bytes 1.1.0", "either", "fnv", "futures 0.3.16", @@ -3640,7 +3640,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f2cd64ef597f40e14bfce0497f50ecb63dd6d201c61796daeb4227078834fbf" dependencies = [ "asynchronous-codec 0.6.0", - "bytes 1.0.1", + "bytes 1.1.0", "futures 0.3.16", "libp2p-core", "log 0.4.14", @@ -3657,7 +3657,7 @@ version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8772c7a99088221bb7ca9c5c0574bf55046a7ab4c319f3619b275f28c8fb87a" dependencies = [ - "bytes 1.0.1", + "bytes 1.1.0", "curve25519-dalek 3.0.2", "futures 0.3.16", "lazy_static", @@ -3695,7 +3695,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5fba1a6ff33e4a274c89a3b1d78b9f34f32af13265cc5c46c16938262d4e945a" dependencies = [ "asynchronous-codec 0.6.0", - "bytes 1.0.1", + "bytes 1.1.0", "futures 0.3.16", "libp2p-core", "log 0.4.14", @@ -3726,7 +3726,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2852b61c90fa8ce3c8fcc2aba76e6cefc20d648f9df29157d6b3a916278ef3e3" dependencies = [ "asynchronous-codec 0.6.0", - "bytes 1.0.1", + "bytes 1.1.0", "futures 0.3.16", "futures-timer 3.0.2", "libp2p-core", @@ -3771,7 +3771,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a877a4ced6d46bf84677e1974e8cf61fb434af73b2e96fb48d6cb6223a4634d8" dependencies = [ "async-trait", - "bytes 1.0.1", + "bytes 1.1.0", "futures 0.3.16", "libp2p-core", "libp2p-swarm", @@ -4387,7 +4387,7 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d91ec0a2440aaff5f78ec35631a7027d50386c6163aa975f7caa0d5da4b6ff8" dependencies = [ - "bytes 1.0.1", + "bytes 1.1.0", "futures 0.3.16", "log 0.4.14", "pin-project 1.0.8", @@ -6880,7 +6880,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001" dependencies = [ - "bytes 1.0.1", + "bytes 1.1.0", "prost-derive", ] @@ -6890,7 +6890,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62941722fb675d463659e49c4f3fe1fe792ff24fe5bbaa9c08cd3b98a1c354f5" dependencies = [ - "bytes 1.0.1", + "bytes 1.1.0", "heck", "itertools", "lazy_static", @@ -6923,7 +6923,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "534b7a0e836e3c482d2693070f982e39e7611da9695d4d1f5a4b186b51faef0a" dependencies = [ - "bytes 1.0.1", + "bytes 1.1.0", "prost", ] @@ -8241,7 +8241,7 @@ dependencies = [ "async-trait", "asynchronous-codec 0.5.0", "bitflags", - "bytes 1.0.1", + "bytes 1.1.0", "cid", "derive_more", "either", @@ -8338,7 +8338,7 @@ dependencies = [ name = "sc-offchain" version = "4.0.0-dev" dependencies = [ - "bytes 1.0.1", + "bytes 1.1.0", "fnv", "futures 0.3.16", "futures-timer 3.0.2", @@ -9150,7 +9150,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "083624472e8817d44d02c0e55df043737ff11f279af924abdf93845717c2b75c" dependencies = [ "base64 0.13.0", - "bytes 1.0.1", + "bytes 1.1.0", "flate2", "futures 0.3.16", "httparse", @@ -10576,7 +10576,7 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbbf1c778ec206785635ce8ad57fe52b3009ae9e0c9f574a728f3049d3e55838" dependencies = [ - "bytes 1.0.1", + "bytes 1.1.0", "libc", "memchr", "mio 0.7.13", @@ -10724,7 +10724,7 @@ version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1caa0b0c8d94a049db56b5acf8cba99dc0623aab1b26d5b5f5e2d945846b3592" dependencies = [ - "bytes 1.0.1", + "bytes 1.1.0", "futures-core", "futures-io", "futures-sink", @@ -11106,7 +11106,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35581ff83d4101e58b582e607120c7f5ffb17e632a980b1f38334d76b36908b2" dependencies = [ "asynchronous-codec 0.5.0", - "bytes 1.0.1", + "bytes 1.1.0", "futures-io", "futures-util", ] @@ -11118,7 +11118,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f8d425fafb8cd76bc3f22aace4af471d3156301d7508f2107e98fbeae10bc7f" dependencies = [ "asynchronous-codec 0.6.0", - "bytes 1.0.1", + "bytes 1.1.0", "futures-io", "futures-util", ] diff --git a/client/offchain/Cargo.toml b/client/offchain/Cargo.toml index 36921944965f..b3d5ee045007 100644 --- a/client/offchain/Cargo.toml +++ b/client/offchain/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -bytes = "1.0" +bytes = "1.1" codec = { package = "parity-scale-codec", version = "2.0.0", features = ["derive"] } hex = "0.4" fnv = "1.0.6" From 47017abc3884ff1f309a4b98261a20caca7a2b21 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Dec 2021 14:10:21 +0100 Subject: [PATCH 314/695] Bump rustversion from 1.0.5 to 1.0.6 (#10516) Bumps [rustversion](https://github.com/dtolnay/rustversion) from 1.0.5 to 1.0.6. - [Release notes](https://github.com/dtolnay/rustversion/releases) - [Commits](https://github.com/dtolnay/rustversion/compare/1.0.5...1.0.6) --- updated-dependencies: - dependency-name: rustversion dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- frame/support/test/Cargo.toml | 2 +- primitives/api/test/Cargo.toml | 2 +- primitives/runtime-interface/Cargo.toml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 84584dbab91c..1dc9729f063e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7532,9 +7532,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61b3909d758bb75c79f23d4736fac9433868679d3ad2ea7a61e3c25cfda9a088" +checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" [[package]] name = "rw-stream-sink" diff --git a/frame/support/test/Cargo.toml b/frame/support/test/Cargo.toml index ebee4515f3be..890fa86f9768 100644 --- a/frame/support/test/Cargo.toml +++ b/frame/support/test/Cargo.toml @@ -25,7 +25,7 @@ sp-std = { version = "4.0.0", default-features = false, path = "../../../primiti sp-version = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/version" } trybuild = "1.0.53" pretty_assertions = "1.0.0" -rustversion = "1.0.5" +rustversion = "1.0.6" frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" } # The "std" feature for this pallet is never activated on purpose, in order to test construct_runtime error message test-pallet = { package = "frame-support-test-pallet", default-features = false, path = "pallet" } diff --git a/primitives/api/test/Cargo.toml b/primitives/api/test/Cargo.toml index 53d26c08c1d9..38845340027f 100644 --- a/primitives/api/test/Cargo.toml +++ b/primitives/api/test/Cargo.toml @@ -22,7 +22,7 @@ sc-block-builder = { version = "0.10.0-dev", path = "../../../client/block-build codec = { package = "parity-scale-codec", version = "2.0.0" } sp-state-machine = { version = "0.10.0", path = "../../state-machine" } trybuild = "1.0.53" -rustversion = "1.0.5" +rustversion = "1.0.6" [dev-dependencies] criterion = "0.3.0" diff --git a/primitives/runtime-interface/Cargo.toml b/primitives/runtime-interface/Cargo.toml index fb978fbbbac1..137780c3c91e 100644 --- a/primitives/runtime-interface/Cargo.toml +++ b/primitives/runtime-interface/Cargo.toml @@ -30,7 +30,7 @@ sp-runtime-interface-test-wasm = { version = "2.0.0", path = "test-wasm" } sp-state-machine = { version = "0.10.0", path = "../state-machine" } sp-core = { version = "4.1.0-dev", path = "../core" } sp-io = { version = "4.0.0-dev", path = "../io" } -rustversion = "1.0.5" +rustversion = "1.0.6" trybuild = "1.0.53" [features] From 0bc1da8a588c06bbfcf3fc23ea0f7c39b1321427 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 20 Dec 2021 14:57:32 +0100 Subject: [PATCH 315/695] Alter BEEFY primitives to prepare for potential BLS integration (#10466) * Generalize signature. * Fix tests. * Introduce VersionedFinalityProof. * cargo +nightly fmt --all * Rework packing a tad. --- client/beefy/src/notification.rs | 3 +- client/beefy/src/worker.rs | 4 +- primitives/beefy/src/commitment.rs | 91 ++++++++++++++++-------------- primitives/beefy/src/lib.rs | 3 +- primitives/beefy/src/witness.rs | 18 +++--- 5 files changed, 63 insertions(+), 56 deletions(-) diff --git a/client/beefy/src/notification.rs b/client/beefy/src/notification.rs index f394ae6c840a..7caaa5435240 100644 --- a/client/beefy/src/notification.rs +++ b/client/beefy/src/notification.rs @@ -24,7 +24,8 @@ use sp_runtime::traits::{Block, NumberFor}; use parking_lot::Mutex; /// Stream of signed commitments returned when subscribing. -pub type SignedCommitment = beefy_primitives::SignedCommitment>; +pub type SignedCommitment = + beefy_primitives::SignedCommitment, beefy_primitives::crypto::Signature>; /// Stream of signed commitments returned when subscribing. type SignedCommitmentStream = TracingUnboundedReceiver>; diff --git a/client/beefy/src/worker.rs b/client/beefy/src/worker.rs index fa48e64c12b4..bf29a50f1964 100644 --- a/client/beefy/src/worker.rs +++ b/client/beefy/src/worker.rs @@ -37,7 +37,7 @@ use sp_runtime::{ use beefy_primitives::{ crypto::{AuthorityId, Public, Signature}, known_payload_ids, BeefyApi, Commitment, ConsensusLog, MmrRootHash, Payload, SignedCommitment, - ValidatorSet, VersionedCommitment, VoteMessage, BEEFY_ENGINE_ID, GENESIS_AUTHORITY_SET_ID, + ValidatorSet, VersionedFinalityProof, VoteMessage, BEEFY_ENGINE_ID, GENESIS_AUTHORITY_SET_ID, }; use crate::{ @@ -330,7 +330,7 @@ where BlockId::Number(round.1), ( BEEFY_ENGINE_ID, - VersionedCommitment::V1(signed_commitment.clone()).encode(), + VersionedFinalityProof::V1(signed_commitment.clone()).encode(), ), ) .is_err() diff --git a/primitives/beefy/src/commitment.rs b/primitives/beefy/src/commitment.rs index ec1ceeded878..63c6520d8680 100644 --- a/primitives/beefy/src/commitment.rs +++ b/primitives/beefy/src/commitment.rs @@ -18,7 +18,7 @@ use codec::{Decode, Encode, Error, Input}; use sp_std::{cmp, prelude::*}; -use crate::{crypto::Signature, ValidatorSetId}; +use crate::ValidatorSetId; /// Id of different payloads in the [`Commitment`] data pub type BeefyPayloadId = [u8; 2]; @@ -139,17 +139,17 @@ where /// please take a look at custom [`Encode`] and [`Decode`] implementations and /// `CompactSignedCommitment` struct. #[derive(Clone, Debug, PartialEq, Eq)] -pub struct SignedCommitment { +pub struct SignedCommitment { /// The commitment signatures are collected for. pub commitment: Commitment, /// GRANDPA validators' signatures for the commitment. /// /// The length of this `Vec` must match number of validators in the current set (see /// [Commitment::validator_set_id]). - pub signatures: Vec>, + pub signatures: Vec>, } -impl SignedCommitment { +impl SignedCommitment { /// Return the number of collected signatures. pub fn no_of_signatures(&self) -> usize { self.signatures.iter().filter(|x| x.is_some()).count() @@ -163,9 +163,9 @@ const CONTAINER_BIT_SIZE: usize = 8; /// Compressed representation of [`SignedCommitment`], used for encoding efficiency. #[derive(Clone, Debug, PartialEq, Eq, Encode, Decode)] -struct CompactSignedCommitment { +struct CompactSignedCommitment { /// The commitment, unchanged compared to regular [`SignedCommitment`]. - commitment: TCommitment, + commitment: Commitment, /// A bitfield representing presence of a signature coming from a validator at some index. /// /// The bit at index `0` is set to `1` in case we have a signature coming from a validator at @@ -183,33 +183,29 @@ struct CompactSignedCommitment { /// Note that in order to associate a `Signature` from this `Vec` with a validator, one needs /// to look at the `signatures_from` bitfield, since some validators might have not produced a /// signature. - signatures_compact: Vec, + signatures_compact: Vec, } -impl<'a, TBlockNumber> CompactSignedCommitment<&'a Commitment> { +impl<'a, TBlockNumber: Clone, TSignature> CompactSignedCommitment { /// Packs a `SignedCommitment` into the compressed `CompactSignedCommitment` format for /// efficient network transport. - fn pack(signed_commitment: &'a SignedCommitment) -> Self { + fn pack(signed_commitment: &'a SignedCommitment) -> Self { let SignedCommitment { commitment, signatures } = signed_commitment; let validator_set_len = signatures.len() as u32; - let mut signatures_from: BitField = vec![]; - let mut signatures_compact: Vec = vec![]; - - for signature in signatures { - match signature { - Some(value) => signatures_compact.push(value.clone()), - None => (), - } - } - let mut bits: Vec = - signatures.iter().map(|x| if x.is_some() { 1 } else { 0 }).collect(); - - // Resize with excess bits for placement purposes - let excess_bits_len = - CONTAINER_BIT_SIZE - (validator_set_len as usize % CONTAINER_BIT_SIZE); - bits.resize(bits.len() + excess_bits_len, 0); + let signatures_compact: Vec<&'a TSignature> = + signatures.iter().filter_map(|x| x.as_ref()).collect(); + let bits = { + let mut bits: Vec = + signatures.iter().map(|x| if x.is_some() { 1 } else { 0 }).collect(); + // Resize with excess bits for placement purposes + let excess_bits_len = + CONTAINER_BIT_SIZE - (validator_set_len as usize % CONTAINER_BIT_SIZE); + bits.resize(bits.len() + excess_bits_len, 0); + bits + }; + let mut signatures_from: BitField = vec![]; let chunks = bits.chunks(CONTAINER_BIT_SIZE); for chunk in chunks { let mut iter = chunk.iter().copied(); @@ -223,13 +219,18 @@ impl<'a, TBlockNumber> CompactSignedCommitment<&'a Commitment> { signatures_from.push(v); } - Self { commitment, signatures_from, validator_set_len, signatures_compact } + Self { + commitment: commitment.clone(), + signatures_from, + validator_set_len, + signatures_compact, + } } /// Unpacks a `CompactSignedCommitment` into the uncompressed `SignedCommitment` form. fn unpack( - temporary_signatures: CompactSignedCommitment>, - ) -> SignedCommitment { + temporary_signatures: CompactSignedCommitment, + ) -> SignedCommitment { let CompactSignedCommitment { commitment, signatures_from, @@ -247,7 +248,7 @@ impl<'a, TBlockNumber> CompactSignedCommitment<&'a Commitment> { bits.truncate(validator_set_len as usize); let mut next_signature = signatures_compact.into_iter(); - let signatures: Vec> = bits + let signatures: Vec> = bits .iter() .map(|&x| if x == 1 { next_signature.next() } else { None }) .collect(); @@ -256,9 +257,10 @@ impl<'a, TBlockNumber> CompactSignedCommitment<&'a Commitment> { } } -impl Encode for SignedCommitment +impl Encode for SignedCommitment where - TBlockNumber: Encode, + TBlockNumber: Encode + Clone, + TSignature: Encode, { fn using_encoded R>(&self, f: F) -> R { let temp = CompactSignedCommitment::pack(self); @@ -266,9 +268,10 @@ where } } -impl Decode for SignedCommitment +impl Decode for SignedCommitment where - TBlockNumber: Decode, + TBlockNumber: Decode + Clone, + TSignature: Decode, { fn decode(input: &mut I) -> Result { let temp = CompactSignedCommitment::decode(input)?; @@ -276,14 +279,18 @@ where } } -/// A [SignedCommitment] with a version number. This variant will be appended -/// to the block justifications for the block for which the signed commitment -/// has been generated. +/// A [SignedCommitment] with a version number. +/// +/// This variant will be appended to the block justifications for the block +/// for which the signed commitment has been generated. +/// +/// Note that this enum is subject to change in the future with introduction +/// of additional cryptographic primitives to BEEFY. #[derive(Clone, Debug, PartialEq, codec::Encode, codec::Decode)] -pub enum VersionedCommitment { +pub enum VersionedFinalityProof { #[codec(index = 1)] /// Current active version - V1(SignedCommitment), + V1(SignedCommitment), } #[cfg(test)] @@ -298,8 +305,8 @@ mod tests { use crate::{crypto, KEY_TYPE}; type TestCommitment = Commitment; - type TestSignedCommitment = SignedCommitment; - type TestVersionedCommitment = VersionedCommitment; + type TestSignedCommitment = SignedCommitment; + type TestVersionedFinalityProof = VersionedFinalityProof; // The mock signatures are equivalent to the ones produced by the BEEFY keystore fn mock_signatures() -> (crypto::Signature, crypto::Signature) { @@ -435,14 +442,14 @@ mod tests { signatures: vec![None, None, Some(sigs.0), Some(sigs.1)], }; - let versioned = TestVersionedCommitment::V1(signed.clone()); + let versioned = TestVersionedFinalityProof::V1(signed.clone()); let encoded = codec::Encode::encode(&versioned); assert_eq!(1, encoded[0]); assert_eq!(encoded[1..], codec::Encode::encode(&signed)); - let decoded = TestVersionedCommitment::decode(&mut &*encoded); + let decoded = TestVersionedFinalityProof::decode(&mut &*encoded); assert_eq!(decoded, Ok(versioned)); } diff --git a/primitives/beefy/src/lib.rs b/primitives/beefy/src/lib.rs index cb3cf601a76b..20f6b9d0d8fb 100644 --- a/primitives/beefy/src/lib.rs +++ b/primitives/beefy/src/lib.rs @@ -36,7 +36,8 @@ pub mod mmr; pub mod witness; pub use commitment::{ - known_payload_ids, BeefyPayloadId, Commitment, Payload, SignedCommitment, VersionedCommitment, + known_payload_ids, BeefyPayloadId, Commitment, Payload, SignedCommitment, + VersionedFinalityProof, }; use codec::{Codec, Decode, Encode}; diff --git a/primitives/beefy/src/witness.rs b/primitives/beefy/src/witness.rs index 3ead08bdd7cb..102a6be09c78 100644 --- a/primitives/beefy/src/witness.rs +++ b/primitives/beefy/src/witness.rs @@ -25,10 +25,7 @@ use sp_std::prelude::*; -use crate::{ - commitment::{Commitment, SignedCommitment}, - crypto::Signature, -}; +use crate::commitment::{Commitment, SignedCommitment}; /// A light form of [SignedCommitment]. /// @@ -60,12 +57,12 @@ impl SignedCommitmentWitness( - signed: SignedCommitment, + pub fn from_signed( + signed: SignedCommitment, merkelize: TMerkelize, - ) -> (Self, Vec>) + ) -> (Self, Vec>) where - TMerkelize: FnOnce(&[Option]) -> TMerkleRoot, + TMerkelize: FnOnce(&[Option]) -> TMerkleRoot, { let SignedCommitment { commitment, signatures } = signed; let signed_by = signatures.iter().map(|s| s.is_some()).collect(); @@ -87,8 +84,9 @@ mod tests { use crate::{crypto, known_payload_ids, Payload, KEY_TYPE}; type TestCommitment = Commitment; - type TestSignedCommitment = SignedCommitment; - type TestSignedCommitmentWitness = SignedCommitmentWitness>>; + type TestSignedCommitment = SignedCommitment; + type TestSignedCommitmentWitness = + SignedCommitmentWitness>>; // The mock signatures are equivalent to the ones produced by the BEEFY keystore fn mock_signatures() -> (crypto::Signature, crypto::Signature) { From 680fc3feabc73869f58b31d8b48cb775fb7ff9b2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Dec 2021 15:27:14 +0100 Subject: [PATCH 316/695] Bump hyper from 0.14.14 to 0.14.16 (#10462) Bumps [hyper](https://github.com/hyperium/hyper) from 0.14.14 to 0.14.16. - [Release notes](https://github.com/hyperium/hyper/releases) - [Changelog](https://github.com/hyperium/hyper/blob/master/CHANGELOG.md) - [Commits](https://github.com/hyperium/hyper/compare/v0.14.14...v0.14.16) --- updated-dependencies: - dependency-name: hyper dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 22 +++++++++++----------- client/offchain/Cargo.toml | 2 +- utils/prometheus/Cargo.toml | 4 ++-- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1dc9729f063e..4af488ca98db 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2556,9 +2556,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.7" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fd819562fcebdac5afc5c113c3ec36f902840b70fd4fc458799c8ce4607ae55" +checksum = "8f072413d126e57991455e0a922b31e4c8ba7c2ffbebf6b78b4f8521397d65cd" dependencies = [ "bytes 1.1.0", "fnv", @@ -2782,9 +2782,9 @@ dependencies = [ [[package]] name = "hyper" -version = "0.14.14" +version = "0.14.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b91bb1f221b6ea1f1e4371216b70f40748774c2fb5971b450c07773fb92d26b" +checksum = "b7ec3e62bdc98a2f0393a5048e4c30ef659440ea6e0e572965103e72bd836f55" dependencies = [ "bytes 1.1.0", "futures-channel", @@ -2812,7 +2812,7 @@ checksum = "5f9f7a97316d44c0af9b0301e65010573a853a9fc97046d7331d7f6bc0fd5a64" dependencies = [ "ct-logs", "futures-util", - "hyper 0.14.14", + "hyper 0.14.16", "log 0.4.14", "rustls", "rustls-native-certs", @@ -2828,7 +2828,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ "bytes 1.1.0", - "hyper 0.14.14", + "hyper 0.14.16", "native-tls", "tokio", "tokio-native-tls", @@ -3051,7 +3051,7 @@ checksum = "d2b99d4207e2a04fb4581746903c2bb7eb376f88de9c699d0f3e10feeac0cd3a" dependencies = [ "derive_more", "futures 0.3.16", - "hyper 0.14.14", + "hyper 0.14.16", "hyper-tls", "jsonrpc-core", "jsonrpc-pubsub", @@ -3107,7 +3107,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1dea6e07251d9ce6a552abfb5d7ad6bc290a4596c8dcc3d795fae2bbdc1f3ff" dependencies = [ "futures 0.3.16", - "hyper 0.14.14", + "hyper 0.14.16", "jsonrpc-core", "jsonrpc-server-utils", "log 0.4.14", @@ -3215,7 +3215,7 @@ dependencies = [ "beef", "futures-channel", "futures-util", - "hyper 0.14.14", + "hyper 0.14.16", "log 0.4.14", "serde", "serde_json", @@ -8343,7 +8343,7 @@ dependencies = [ "futures 0.3.16", "futures-timer 3.0.2", "hex", - "hyper 0.14.14", + "hyper 0.14.16", "hyper-rustls", "lazy_static", "num_cpus", @@ -10168,7 +10168,7 @@ dependencies = [ "async-std", "derive_more", "futures-util", - "hyper 0.14.14", + "hyper 0.14.16", "log 0.4.14", "prometheus", "tokio", diff --git a/client/offchain/Cargo.toml b/client/offchain/Cargo.toml index b3d5ee045007..38834181b163 100644 --- a/client/offchain/Cargo.toml +++ b/client/offchain/Cargo.toml @@ -30,7 +30,7 @@ sp-offchain = { version = "4.0.0-dev", path = "../../primitives/offchain" } sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } sc-utils = { version = "4.0.0-dev", path = "../utils" } threadpool = "1.7" -hyper = { version = "0.14.14", features = ["stream", "http2"] } +hyper = { version = "0.14.16", features = ["stream", "http2"] } hyper-rustls = "0.22.1" once_cell = "1.8" tracing = "0.1.29" diff --git a/utils/prometheus/Cargo.toml b/utils/prometheus/Cargo.toml index 43f8b62b9c7b..b9a3a5a5d197 100644 --- a/utils/prometheus/Cargo.toml +++ b/utils/prometheus/Cargo.toml @@ -19,8 +19,8 @@ futures-util = { version = "0.3.17", default-features = false, features = ["io"] derive_more = "0.99" async-std = { version = "1.10.0", features = ["unstable"] } tokio = "1.15" -hyper = { version = "0.14.14", default-features = false, features = ["http1", "server", "tcp"] } +hyper = { version = "0.14.16", default-features = false, features = ["http1", "server", "tcp"] } [dev-dependencies] -hyper = { version = "0.14.14", features = ["client"] } +hyper = { version = "0.14.16", features = ["client"] } tokio = { version = "1.15", features = ["rt-multi-thread"] } From d18705ee7b5b654d3947558fea6dbd0701ac3ecc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Mon, 20 Dec 2021 20:49:18 +0100 Subject: [PATCH 317/695] SlotDuration: Always fetch the slot duration from the runtime (#10509) * SlotDuration: Always fetch the slot duration from the runtime The slot duration should always be fetched from the runtime instead of being cached in the db. The slot duration is only fetched on startup of the node, so the performance isn't that important. This is especially helpful for the case when the slot duration of a chain should be changed through a runtime upgrade (there be dragons, so take care). * Fix docs * Remove logging * Fix warning --- Cargo.lock | 1 - bin/node/cli/src/service.rs | 2 +- client/consensus/aura/src/lib.rs | 7 ++- client/consensus/babe/rpc/src/lib.rs | 2 +- client/consensus/babe/src/lib.rs | 50 ++++++++--------- client/consensus/babe/src/tests.rs | 2 +- .../manual-seal/src/consensus/babe.rs | 4 +- client/consensus/slots/Cargo.toml | 1 - client/consensus/slots/src/lib.rs | 55 ++----------------- primitives/consensus/aura/src/lib.rs | 2 - primitives/consensus/babe/src/lib.rs | 2 - primitives/consensus/common/src/lib.rs | 3 - test-utils/test-runner/src/client.rs | 2 +- test-utils/test-runner/src/lib.rs | 2 +- 14 files changed, 40 insertions(+), 95 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4af488ca98db..f4ab495c2450 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8014,7 +8014,6 @@ dependencies = [ "sc-client-api", "sc-consensus", "sc-telemetry", - "sp-api", "sp-arithmetic", "sp-blockchain", "sp-consensus", diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index fbc91c5f7d2e..fabf8d0adfdc 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -196,7 +196,7 @@ pub fn new_partial( let justification_import = grandpa_block_import.clone(); let (block_import, babe_link) = sc_consensus_babe::block_import( - sc_consensus_babe::Config::get_or_compute(&*client)?, + sc_consensus_babe::Config::get(&*client)?, grandpa_block_import, client.clone(), )?; diff --git a/client/consensus/aura/src/lib.rs b/client/consensus/aura/src/lib.rs index ec577b084431..4579b2d73da1 100644 --- a/client/consensus/aura/src/lib.rs +++ b/client/consensus/aura/src/lib.rs @@ -85,7 +85,7 @@ type AuthorityId

=

::Public; /// Slot duration type for Aura. pub type SlotDuration = sc_consensus_slots::SlotDuration; -/// Get type of `SlotDuration` for Aura. +/// Get the slot duration for Aura. pub fn slot_duration(client: &C) -> CResult where A: Codec, @@ -93,7 +93,10 @@ where C: AuxStore + ProvideRuntimeApi + UsageProvider, C::Api: AuraApi, { - SlotDuration::get_or_compute(client, |a, b| a.slot_duration(b).map_err(Into::into)) + let best_block_id = BlockId::Hash(client.usage_info().chain.best_hash); + let slot_duration = client.runtime_api().slot_duration(&best_block_id)?; + + Ok(SlotDuration::new(slot_duration)) } /// Get slot author for given block along with authorities. diff --git a/client/consensus/babe/rpc/src/lib.rs b/client/consensus/babe/rpc/src/lib.rs index eeec7b86b1f1..463b05ef9cd2 100644 --- a/client/consensus/babe/rpc/src/lib.rs +++ b/client/consensus/babe/rpc/src/lib.rs @@ -247,7 +247,7 @@ mod tests { let builder = TestClientBuilder::new(); let (client, longest_chain) = builder.build_with_longest_chain(); let client = Arc::new(client); - let config = Config::get_or_compute(&*client).expect("config available"); + let config = Config::get(&*client).expect("config available"); let (_, link) = block_import(config.clone(), client.clone(), client.clone()) .expect("can initialize block-import"); diff --git a/client/consensus/babe/src/lib.rs b/client/consensus/babe/src/lib.rs index 21c3c883a39d..7a05c7a92678 100644 --- a/client/consensus/babe/src/lib.rs +++ b/client/consensus/babe/src/lib.rs @@ -329,7 +329,9 @@ pub struct BabeIntermediate { /// Intermediate key for Babe engine. pub static INTERMEDIATE_KEY: &[u8] = b"babe1"; -/// A slot duration. Create with `get_or_compute`. +/// A slot duration. +/// +/// Create with [`Self::get`]. // FIXME: Once Rust has higher-kinded types, the duplication between this // and `super::babe::Config` can be eliminated. // https://github.com/paritytech/substrate/issues/2434 @@ -337,39 +339,33 @@ pub static INTERMEDIATE_KEY: &[u8] = b"babe1"; pub struct Config(sc_consensus_slots::SlotDuration); impl Config { - /// Either fetch the slot duration from disk or compute it from the genesis - /// state. - pub fn get_or_compute(client: &C) -> ClientResult + /// Fetch the config from the runtime. + pub fn get(client: &C) -> ClientResult where C: AuxStore + ProvideRuntimeApi + UsageProvider, C::Api: BabeApi, { trace!(target: "babe", "Getting slot duration"); - match sc_consensus_slots::SlotDuration::get_or_compute(client, |a, b| { - let has_api_v1 = a.has_api_with::, _>(&b, |v| v == 1)?; - let has_api_v2 = a.has_api_with::, _>(&b, |v| v == 2)?; - if has_api_v1 { - #[allow(deprecated)] - { - Ok(a.configuration_before_version_2(b)?.into()) - } - } else if has_api_v2 { - a.configuration(b).map_err(Into::into) - } else { - Err(sp_blockchain::Error::VersionInvalid( - "Unsupported or invalid BabeApi version".to_string(), - )) + let best_block_id = BlockId::Hash(client.usage_info().chain.best_hash); + let runtime_api = client.runtime_api(); + + let version = runtime_api.api_version::>(&best_block_id)?; + + let slot_duration = if version == Some(1) { + #[allow(deprecated)] + { + runtime_api.configuration_before_version_2(&best_block_id)?.into() } - }) - .map(Self) - { - Ok(s) => Ok(s), - Err(s) => { - warn!(target: "babe", "Failed to get slot duration"); - Err(s) - }, - } + } else if version == Some(2) { + runtime_api.configuration(&best_block_id)? + } else { + return Err(sp_blockchain::Error::VersionInvalid( + "Unsupported or invalid BabeApi version".to_string(), + )) + }; + + Ok(Self(sc_consensus_slots::SlotDuration::new(slot_duration))) } /// Get the inner slot duration diff --git a/client/consensus/babe/src/tests.rs b/client/consensus/babe/src/tests.rs index 73cc453812ea..23c34d21ec7b 100644 --- a/client/consensus/babe/src/tests.rs +++ b/client/consensus/babe/src/tests.rs @@ -297,7 +297,7 @@ impl TestNetFactory for BabeTestNet { ) { let client = client.as_client(); - let config = Config::get_or_compute(&*client).expect("config available"); + let config = Config::get(&*client).expect("config available"); let (block_import, link) = crate::block_import(config, client.clone(), client.clone()) .expect("can initialize block-import"); diff --git a/client/consensus/manual-seal/src/consensus/babe.rs b/client/consensus/manual-seal/src/consensus/babe.rs index e06c544aaedc..499a82c63e40 100644 --- a/client/consensus/manual-seal/src/consensus/babe.rs +++ b/client/consensus/manual-seal/src/consensus/babe.rs @@ -154,7 +154,7 @@ where return Err(Error::StringError("Cannot supply empty authority set!".into())) } - let config = Config::get_or_compute(&*client)?; + let config = Config::get(&*client)?; Ok(Self { config, client, keystore, epoch_changes, authorities }) } @@ -327,7 +327,7 @@ impl SlotTimestampProvider { C: AuxStore + HeaderBackend + ProvideRuntimeApi + UsageProvider, C::Api: BabeApi, { - let slot_duration = Config::get_or_compute(&*client)?.slot_duration; + let slot_duration = Config::get(&*client)?.slot_duration; let info = client.info(); // looks like this isn't the first block, rehydrate the fake time. diff --git a/client/consensus/slots/Cargo.toml b/client/consensus/slots/Cargo.toml index bf2bd59bb91e..782e979ed6ef 100644 --- a/client/consensus/slots/Cargo.toml +++ b/client/consensus/slots/Cargo.toml @@ -23,7 +23,6 @@ sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/commo sp-consensus-slots = { version = "0.10.0-dev", path = "../../../primitives/consensus/slots" } sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } sp-state-machine = { version = "0.10.0", path = "../../../primitives/state-machine" } -sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sc-telemetry = { version = "4.0.0-dev", path = "../../telemetry" } sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" } sp-inherents = { version = "4.0.0-dev", path = "../../../primitives/inherents" } diff --git a/client/consensus/slots/src/lib.rs b/client/consensus/slots/src/lib.rs index 3174eacaff4d..905165aa9e36 100644 --- a/client/consensus/slots/src/lib.rs +++ b/client/consensus/slots/src/lib.rs @@ -38,7 +38,6 @@ use futures_timer::Delay; use log::{debug, error, info, warn}; use sc_consensus::{BlockImport, JustificationSyncLink}; use sc_telemetry::{telemetry, TelemetryHandle, CONSENSUS_DEBUG, CONSENSUS_INFO, CONSENSUS_WARN}; -use sp_api::{ApiRef, ProvideRuntimeApi}; use sp_arithmetic::traits::BaseArithmetic; use sp_consensus::{CanAuthorWith, Proposer, SelectChain, SlotData, SyncOracle}; use sp_consensus_slots::Slot; @@ -537,9 +536,7 @@ where SlotDurationInvalid(SlotDuration), } -/// A slot duration. Create with [`get_or_compute`](Self::get_or_compute). -// The internal member should stay private here to maintain invariants of -// `get_or_compute`. +/// A slot duration. Create with [`Self::new`]. #[derive(Clone, Copy, Debug, Encode, Decode, Hash, PartialOrd, Ord, PartialEq, Eq)] pub struct SlotDuration(T); @@ -554,54 +551,12 @@ impl SlotData for SlotDuration { fn slot_duration(&self) -> std::time::Duration { self.0.slot_duration() } - - const SLOT_KEY: &'static [u8] = T::SLOT_KEY; } impl SlotDuration { - /// Either fetch the slot duration from disk or compute it from the - /// genesis state. - /// - /// `slot_key` is marked as `'static`, as it should really be a - /// compile-time constant. - pub fn get_or_compute(client: &C, cb: CB) -> sp_blockchain::Result - where - C: sc_client_api::backend::AuxStore + sc_client_api::UsageProvider, - C: ProvideRuntimeApi, - CB: FnOnce(ApiRef, &BlockId) -> sp_blockchain::Result, - T: SlotData + Encode + Decode + Debug, - { - let slot_duration = match client.get_aux(T::SLOT_KEY)? { - Some(v) => ::decode(&mut &v[..]).map(SlotDuration).map_err(|_| { - sp_blockchain::Error::Backend({ - error!(target: "slots", "slot duration kept in invalid format"); - "slot duration kept in invalid format".to_string() - }) - }), - None => { - let best_hash = client.usage_info().chain.best_hash; - let slot_duration = cb(client.runtime_api(), &BlockId::hash(best_hash))?; - - info!( - "⏱ Loaded block-time = {:?} from block {:?}", - slot_duration.slot_duration(), - best_hash, - ); - - slot_duration - .using_encoded(|s| client.insert_aux(&[(T::SLOT_KEY, &s[..])], &[]))?; - - Ok(SlotDuration(slot_duration)) - }, - }?; - - if slot_duration.slot_duration() == Default::default() { - return Err(sp_blockchain::Error::Application(Box::new(Error::SlotDurationInvalid( - slot_duration, - )))) - } - - Ok(slot_duration) + /// Create a new instance of `Self`. + pub fn new(val: T) -> Self { + Self(val) } /// Returns slot data value. @@ -875,7 +830,7 @@ impl BackoffAuthoringBlocksStrategy for () { #[cfg(test)] mod test { use super::*; - use sp_api::NumberFor; + use sp_runtime::traits::NumberFor; use std::time::{Duration, Instant}; use substrate_test_runtime_client::runtime::{Block, Header}; diff --git a/primitives/consensus/aura/src/lib.rs b/primitives/consensus/aura/src/lib.rs index e6a319c1d159..b85443e0917e 100644 --- a/primitives/consensus/aura/src/lib.rs +++ b/primitives/consensus/aura/src/lib.rs @@ -117,6 +117,4 @@ impl sp_consensus::SlotData for SlotDuration { fn slot_duration(&self) -> std::time::Duration { std::time::Duration::from_millis(self.0) } - - const SLOT_KEY: &'static [u8] = b"aura_slot_duration"; } diff --git a/primitives/consensus/babe/src/lib.rs b/primitives/consensus/babe/src/lib.rs index 560866cfb2ab..1971563ff198 100644 --- a/primitives/consensus/babe/src/lib.rs +++ b/primitives/consensus/babe/src/lib.rs @@ -242,8 +242,6 @@ impl sp_consensus::SlotData for BabeGenesisConfiguration { fn slot_duration(&self) -> std::time::Duration { std::time::Duration::from_millis(self.slot_duration) } - - const SLOT_KEY: &'static [u8] = b"babe_configuration"; } /// Configuration data used by the BABE consensus engine. diff --git a/primitives/consensus/common/src/lib.rs b/primitives/consensus/common/src/lib.rs index ce834fd0a47f..456ba965f4aa 100644 --- a/primitives/consensus/common/src/lib.rs +++ b/primitives/consensus/common/src/lib.rs @@ -332,7 +332,4 @@ impl CanAuthorWith for NeverCanAuthor { pub trait SlotData { /// Gets the slot duration. fn slot_duration(&self) -> sp_std::time::Duration; - - /// The static slot key - const SLOT_KEY: &'static [u8]; } diff --git a/test-utils/test-runner/src/client.rs b/test-utils/test-runner/src/client.rs index 21039d3bc4b1..b4a82b1c8950 100644 --- a/test-utils/test-runner/src/client.rs +++ b/test-utils/test-runner/src/client.rs @@ -127,7 +127,7 @@ where None, )?; - let slot_duration = sc_consensus_babe::Config::get_or_compute(&*client)?; + let slot_duration = sc_consensus_babe::Config::get(&*client)?; let (block_import, babe_link) = sc_consensus_babe::block_import( slot_duration.clone(), grandpa_block_import, diff --git a/test-utils/test-runner/src/lib.rs b/test-utils/test-runner/src/lib.rs index 9f51442ed743..d5e2873fe412 100644 --- a/test-utils/test-runner/src/lib.rs +++ b/test-utils/test-runner/src/lib.rs @@ -154,7 +154,7 @@ //! sc_finality_grandpa::block_import(client.clone(), &(client.clone() as Arc<_>), select_chain.clone())?; //! //! let (block_import, babe_link) = sc_consensus_babe::block_import( -//! sc_consensus_babe::Config::get_or_compute(&*client)?, +//! sc_consensus_babe::Config::get(&*client)?, //! grandpa_block_import, //! client.clone(), //! )?; From 433bcb1dc3739edcf55994e517b067d039757f17 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Dec 2021 11:17:06 +0100 Subject: [PATCH 318/695] Bump serde from 1.0.131 to 1.0.132 (#10517) Bumps [serde](https://github.com/serde-rs/serde) from 1.0.131 to 1.0.132. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.131...v1.0.132) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- bin/node/bench/Cargo.toml | 2 +- bin/node/cli/Cargo.toml | 2 +- client/beefy/rpc/Cargo.toml | 2 +- client/chain-spec/Cargo.toml | 2 +- client/cli/Cargo.toml | 2 +- client/consensus/babe/Cargo.toml | 2 +- client/consensus/babe/rpc/Cargo.toml | 2 +- client/network/Cargo.toml | 2 +- client/rpc-api/Cargo.toml | 2 +- client/service/Cargo.toml | 2 +- client/sync-state-rpc/Cargo.toml | 2 +- client/telemetry/Cargo.toml | 2 +- client/tracing/Cargo.toml | 2 +- client/transaction-pool/Cargo.toml | 2 +- client/transaction-pool/api/Cargo.toml | 2 +- frame/beefy-mmr/Cargo.toml | 2 +- frame/beefy/Cargo.toml | 2 +- frame/democracy/Cargo.toml | 2 +- frame/merkle-mountain-range/primitives/Cargo.toml | 2 +- frame/merkle-mountain-range/rpc/Cargo.toml | 2 +- frame/offences/Cargo.toml | 2 +- frame/staking/Cargo.toml | 2 +- frame/support/Cargo.toml | 2 +- frame/support/test/Cargo.toml | 2 +- frame/system/Cargo.toml | 2 +- frame/tips/Cargo.toml | 2 +- frame/transaction-payment/Cargo.toml | 2 +- frame/transaction-payment/asset-tx-payment/Cargo.toml | 2 +- frame/transaction-storage/Cargo.toml | 2 +- frame/treasury/Cargo.toml | 2 +- primitives/application-crypto/Cargo.toml | 2 +- primitives/arithmetic/Cargo.toml | 2 +- primitives/consensus/babe/Cargo.toml | 2 +- primitives/core/Cargo.toml | 2 +- primitives/finality-grandpa/Cargo.toml | 2 +- primitives/npos-elections/Cargo.toml | 2 +- primitives/rpc/Cargo.toml | 2 +- primitives/runtime/Cargo.toml | 2 +- primitives/serializer/Cargo.toml | 2 +- primitives/storage/Cargo.toml | 2 +- primitives/test-primitives/Cargo.toml | 2 +- primitives/version/Cargo.toml | 2 +- test-utils/client/Cargo.toml | 2 +- test-utils/runtime/Cargo.toml | 2 +- utils/frame/benchmarking-cli/Cargo.toml | 2 +- utils/frame/remote-externalities/Cargo.toml | 2 +- utils/frame/try-runtime/cli/Cargo.toml | 2 +- 48 files changed, 51 insertions(+), 51 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f4ab495c2450..f609823d59b9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8893,9 +8893,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.131" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ad69dfbd3e45369132cc64e6748c2d65cdfb001a2b1c232d128b4ad60561c1" +checksum = "8b9875c23cf305cd1fd7eb77234cbb705f21ea6a72c637a5c6db5fe4b8e7f008" dependencies = [ "serde_derive", ] @@ -8921,9 +8921,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.131" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b710a83c4e0dff6a3d511946b95274ad9ca9e5d3ae497b63fda866ac955358d2" +checksum = "ecc0db5cb2556c0e558887d9bbdcf6ac4471e83ff66cf696e5419024d1606276" dependencies = [ "proc-macro2", "quote", diff --git a/bin/node/bench/Cargo.toml b/bin/node/bench/Cargo.toml index 3ffb0f92c843..114742990bcd 100644 --- a/bin/node/bench/Cargo.toml +++ b/bin/node/bench/Cargo.toml @@ -16,7 +16,7 @@ node-runtime = { version = "3.0.0-dev", path = "../runtime" } sc-client-api = { version = "4.0.0-dev", path = "../../../client/api/" } sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } sp-state-machine = { version = "0.10.0", path = "../../../primitives/state-machine" } -serde = "1.0.131" +serde = "1.0.132" serde_json = "1.0.71" structopt = "0.3" derive_more = "0.99.16" diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index 671388d55d82..f955076e122b 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -35,7 +35,7 @@ crate-type = ["cdylib", "rlib"] [dependencies] # third-party dependencies codec = { package = "parity-scale-codec", version = "2.0.0" } -serde = { version = "1.0.131", features = ["derive"] } +serde = { version = "1.0.132", features = ["derive"] } futures = "0.3.16" hex-literal = "0.3.4" log = "0.4.8" diff --git a/client/beefy/rpc/Cargo.toml b/client/beefy/rpc/Cargo.toml index b5a8144faba8..847f054f4663 100644 --- a/client/beefy/rpc/Cargo.toml +++ b/client/beefy/rpc/Cargo.toml @@ -10,7 +10,7 @@ description = "RPC for the BEEFY Client gadget for substrate" [dependencies] futures = "0.3.16" log = "0.4" -serde = { version = "1.0.131", features = ["derive"] } +serde = { version = "1.0.132", features = ["derive"] } jsonrpc-core = "18.0.0" jsonrpc-core-client = "18.0.0" diff --git a/client/chain-spec/Cargo.toml b/client/chain-spec/Cargo.toml index 4ef14decf9eb..601fb5b4da9e 100644 --- a/client/chain-spec/Cargo.toml +++ b/client/chain-spec/Cargo.toml @@ -17,7 +17,7 @@ sc-chain-spec-derive = { version = "4.0.0-dev", path = "./derive" } impl-trait-for-tuples = "0.2.1" sc-network = { version = "0.10.0-dev", path = "../network" } sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } -serde = { version = "1.0.131", features = ["derive"] } +serde = { version = "1.0.132", features = ["derive"] } serde_json = "1.0.71" sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } sc-telemetry = { version = "4.0.0-dev", path = "../telemetry" } diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index 84063fa8fc23..f92f7b51c8b7 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -41,7 +41,7 @@ names = { version = "0.12.0", default-features = false } structopt = "0.3.25" sc-tracing = { version = "4.0.0-dev", path = "../tracing" } chrono = "0.4.10" -serde = "1.0.131" +serde = "1.0.132" thiserror = "1.0.30" rpassword = "5.0.0" diff --git a/client/consensus/babe/Cargo.toml b/client/consensus/babe/Cargo.toml index 654e47b72756..8d0ceb2b615b 100644 --- a/client/consensus/babe/Cargo.toml +++ b/client/consensus/babe/Cargo.toml @@ -25,7 +25,7 @@ sp-keystore = { version = "0.10.0", path = "../../../primitives/keystore" } num-bigint = "0.2.3" num-rational = "0.2.2" num-traits = "0.2.8" -serde = { version = "1.0.131", features = ["derive"] } +serde = { version = "1.0.132", features = ["derive"] } sp-version = { version = "4.0.0-dev", path = "../../../primitives/version" } sp-io = { version = "4.0.0", path = "../../../primitives/io" } sp-inherents = { version = "4.0.0-dev", path = "../../../primitives/inherents" } diff --git a/client/consensus/babe/rpc/Cargo.toml b/client/consensus/babe/rpc/Cargo.toml index 28b27db82c7d..61321e684fa9 100644 --- a/client/consensus/babe/rpc/Cargo.toml +++ b/client/consensus/babe/rpc/Cargo.toml @@ -19,7 +19,7 @@ jsonrpc-core = "18.0.0" jsonrpc-core-client = "18.0.0" jsonrpc-derive = "18.0.0" sp-consensus-babe = { version = "0.10.0-dev", path = "../../../../primitives/consensus/babe" } -serde = { version = "1.0.131", features=["derive"] } +serde = { version = "1.0.132", features=["derive"] } sp-blockchain = { version = "4.0.0-dev", path = "../../../../primitives/blockchain" } sp-runtime = { version = "4.0.0", path = "../../../../primitives/runtime" } sc-consensus-epochs = { version = "0.10.0-dev", path = "../../epochs" } diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index d82d5b9574dd..436f9227d35a 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -46,7 +46,7 @@ rand = "0.7.2" sc-block-builder = { version = "0.10.0-dev", path = "../block-builder" } sc-client-api = { version = "4.0.0-dev", path = "../api" } sc-peerset = { version = "4.0.0-dev", path = "../peerset" } -serde = { version = "1.0.131", features = ["derive"] } +serde = { version = "1.0.132", features = ["derive"] } serde_json = "1.0.71" smallvec = "1.7.0" sp-arithmetic = { version = "4.0.0", path = "../../primitives/arithmetic" } diff --git a/client/rpc-api/Cargo.toml b/client/rpc-api/Cargo.toml index 8a2feb2581b0..f8f8e333a9c6 100644 --- a/client/rpc-api/Cargo.toml +++ b/client/rpc-api/Cargo.toml @@ -27,7 +27,7 @@ sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } sp-runtime = { path = "../../primitives/runtime", version = "4.0.0" } sc-chain-spec = { path = "../chain-spec", version = "4.0.0-dev" } -serde = { version = "1.0.131", features = ["derive"] } +serde = { version = "1.0.132", features = ["derive"] } serde_json = "1.0.71" sc-transaction-pool-api = { version = "4.0.0-dev", path = "../transaction-pool/api" } sp-rpc = { version = "4.0.0-dev", path = "../../primitives/rpc" } diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index 0f093970e417..bfe053152ba4 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -33,7 +33,7 @@ futures-timer = "3.0.1" exit-future = "0.2.0" pin-project = "1.0.8" hash-db = "0.15.2" -serde = "1.0.131" +serde = "1.0.132" serde_json = "1.0.71" sc-keystore = { version = "4.0.0-dev", path = "../keystore" } sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } diff --git a/client/sync-state-rpc/Cargo.toml b/client/sync-state-rpc/Cargo.toml index 1566777009c3..859173ca77eb 100644 --- a/client/sync-state-rpc/Cargo.toml +++ b/client/sync-state-rpc/Cargo.toml @@ -24,7 +24,7 @@ sc-consensus-epochs = { version = "0.10.0-dev", path = "../consensus/epochs" } sc-finality-grandpa = { version = "0.10.0-dev", path = "../finality-grandpa" } sc-rpc-api = { version = "0.10.0-dev", path = "../rpc-api" } serde_json = "1.0.71" -serde = { version = "1.0.131", features = ["derive"] } +serde = { version = "1.0.132", features = ["derive"] } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } codec = { package = "parity-scale-codec", version = "2.0.0" } diff --git a/client/telemetry/Cargo.toml b/client/telemetry/Cargo.toml index c4e03e94a2b1..2001026a1201 100644 --- a/client/telemetry/Cargo.toml +++ b/client/telemetry/Cargo.toml @@ -22,7 +22,7 @@ libp2p = { version = "0.40.0", default-features = false, features = ["dns-async- log = "0.4.8" pin-project = "1.0.8" rand = "0.7.2" -serde = { version = "1.0.131", features = ["derive"] } +serde = { version = "1.0.132", features = ["derive"] } serde_json = "1.0.71" chrono = "0.4.19" thiserror = "1.0.30" diff --git a/client/tracing/Cargo.toml b/client/tracing/Cargo.toml index 861e1acc68c3..55ecd0a1481a 100644 --- a/client/tracing/Cargo.toml +++ b/client/tracing/Cargo.toml @@ -23,7 +23,7 @@ once_cell = "1.8.0" parking_lot = "0.11.2" regex = "1.5.4" rustc-hash = "1.1.0" -serde = "1.0.131" +serde = "1.0.132" thiserror = "1.0.30" tracing = "0.1.29" tracing-log = "0.1.2" diff --git a/client/transaction-pool/Cargo.toml b/client/transaction-pool/Cargo.toml index 2399fb449c7f..43a368145a93 100644 --- a/client/transaction-pool/Cargo.toml +++ b/client/transaction-pool/Cargo.toml @@ -30,7 +30,7 @@ sp-transaction-pool = { version = "4.0.0-dev", path = "../../primitives/transact sc-transaction-pool-api = { version = "4.0.0-dev", path = "./api" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sc-utils = { version = "4.0.0-dev", path = "../utils" } -serde = { version = "1.0.131", features = ["derive"] } +serde = { version = "1.0.132", features = ["derive"] } linked-hash-map = "0.5.4" retain_mut = "0.1.4" diff --git a/client/transaction-pool/api/Cargo.toml b/client/transaction-pool/api/Cargo.toml index 39e126250a9e..e79aa4c7f804 100644 --- a/client/transaction-pool/api/Cargo.toml +++ b/client/transaction-pool/api/Cargo.toml @@ -11,7 +11,7 @@ description = "Transaction pool client facing API." [dependencies] futures = { version = "0.3.1" } log = { version = "0.4.8" } -serde = { version = "1.0.131", features = ["derive"] } +serde = { version = "1.0.132", features = ["derive"] } thiserror = { version = "1.0.30" } sp-runtime = { version = "4.0.0", default-features = false, path = "../../../primitives/runtime" } diff --git a/frame/beefy-mmr/Cargo.toml b/frame/beefy-mmr/Cargo.toml index a4ba9d1fbdae..b36b3ba873ae 100644 --- a/frame/beefy-mmr/Cargo.toml +++ b/frame/beefy-mmr/Cargo.toml @@ -13,7 +13,7 @@ codec = { version = "2.2.0", package = "parity-scale-codec", default-features = libsecp256k1 = { version = "0.7.0", default-features = false } log = { version = "0.4.13", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -serde = { version = "1.0.131", optional = true } +serde = { version = "1.0.132", optional = true } frame-support = { version = "4.0.0-dev", path = "../support", default-features = false } frame-system = { version = "4.0.0-dev", path = "../system", default-features = false } diff --git a/frame/beefy/Cargo.toml b/frame/beefy/Cargo.toml index e9a748b2e80d..753e90faad2e 100644 --- a/frame/beefy/Cargo.toml +++ b/frame/beefy/Cargo.toml @@ -10,7 +10,7 @@ description = "BEEFY FRAME pallet" [dependencies] codec = { version = "2.2.0", package = "parity-scale-codec", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -serde = { version = "1.0.131", optional = true } +serde = { version = "1.0.132", optional = true } frame-support = { version = "4.0.0-dev", path = "../support", default-features = false } frame-system = { version = "4.0.0-dev", path = "../system", default-features = false } diff --git a/frame/democracy/Cargo.toml b/frame/democracy/Cargo.toml index 0c9306b8b5bd..ef8e1f3a2f17 100644 --- a/frame/democracy/Cargo.toml +++ b/frame/democracy/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -serde = { version = "1.0.131", optional = true, features = ["derive"] } +serde = { version = "1.0.132", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ "derive", ] } diff --git a/frame/merkle-mountain-range/primitives/Cargo.toml b/frame/merkle-mountain-range/primitives/Cargo.toml index cda883ccf728..6991ff16939b 100644 --- a/frame/merkle-mountain-range/primitives/Cargo.toml +++ b/frame/merkle-mountain-range/primitives/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } log = { version = "0.4.14", default-features = false } -serde = { version = "1.0.131", optional = true, features = ["derive"] } +serde = { version = "1.0.132", optional = true, features = ["derive"] } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/api" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } diff --git a/frame/merkle-mountain-range/rpc/Cargo.toml b/frame/merkle-mountain-range/rpc/Cargo.toml index 291fd5311aa5..c6f9124c2a27 100644 --- a/frame/merkle-mountain-range/rpc/Cargo.toml +++ b/frame/merkle-mountain-range/rpc/Cargo.toml @@ -17,7 +17,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0" } jsonrpc-core = "18.0.0" jsonrpc-core-client = "18.0.0" jsonrpc-derive = "18.0.0" -serde = { version = "1.0.131", features = ["derive"] } +serde = { version = "1.0.132", features = ["derive"] } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } diff --git a/frame/offences/Cargo.toml b/frame/offences/Cargo.toml index 40b211a19cd0..8084a63cc276 100644 --- a/frame/offences/Cargo.toml +++ b/frame/offences/Cargo.toml @@ -17,7 +17,7 @@ pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -serde = { version = "1.0.131", optional = true } +serde = { version = "1.0.132", optional = true } sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/frame/staking/Cargo.toml b/frame/staking/Cargo.toml index e09d5a57d5ca..c72a1c0ec662 100644 --- a/frame/staking/Cargo.toml +++ b/frame/staking/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -serde = { version = "1.0.131", optional = true } +serde = { version = "1.0.132", optional = true } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ "derive", ] } diff --git a/frame/support/Cargo.toml b/frame/support/Cargo.toml index c049870ecb09..7aea7a0058e9 100644 --- a/frame/support/Cargo.toml +++ b/frame/support/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -serde = { version = "1.0.131", optional = true, features = ["derive"] } +serde = { version = "1.0.132", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } frame-metadata = { version = "14.0.0", default-features = false, features = ["v14"] } diff --git a/frame/support/test/Cargo.toml b/frame/support/test/Cargo.toml index 890fa86f9768..975e0830ab0e 100644 --- a/frame/support/test/Cargo.toml +++ b/frame/support/test/Cargo.toml @@ -12,7 +12,7 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -serde = { version = "1.0.131", default-features = false, features = ["derive"] } +serde = { version = "1.0.132", default-features = false, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-arithmetic = { version = "4.0.0", default-features = false, path = "../../../primitives/arithmetic" } diff --git a/frame/system/Cargo.toml b/frame/system/Cargo.toml index cc1378a35c62..7c1526bbd9d4 100644 --- a/frame/system/Cargo.toml +++ b/frame/system/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -serde = { version = "1.0.131", optional = true, features = ["derive"] } +serde = { version = "1.0.132", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } diff --git a/frame/tips/Cargo.toml b/frame/tips/Cargo.toml index 935ab907a8a1..42d58ec38844 100644 --- a/frame/tips/Cargo.toml +++ b/frame/tips/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } log = { version = "0.4.0", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -serde = { version = "1.0.131", features = ["derive"], optional = true } +serde = { version = "1.0.132", features = ["derive"], optional = true } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } diff --git a/frame/transaction-payment/Cargo.toml b/frame/transaction-payment/Cargo.toml index f4b9b9a18019..7679dae8e6ea 100644 --- a/frame/transaction-payment/Cargo.toml +++ b/frame/transaction-payment/Cargo.toml @@ -17,7 +17,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = "derive", ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -serde = { version = "1.0.131", optional = true } +serde = { version = "1.0.132", optional = true } smallvec = "1.7.0" sp-core = { version = "4.1.0-dev", path = "../../primitives/core", default-features = false } diff --git a/frame/transaction-payment/asset-tx-payment/Cargo.toml b/frame/transaction-payment/asset-tx-payment/Cargo.toml index 9c26fc8033f7..3226ec09d014 100644 --- a/frame/transaction-payment/asset-tx-payment/Cargo.toml +++ b/frame/transaction-payment/asset-tx-payment/Cargo.toml @@ -26,7 +26,7 @@ pallet-transaction-payment = { version = "4.0.0-dev", default-features = false, # Other dependencies codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -serde = { version = "1.0.131", optional = true } +serde = { version = "1.0.132", optional = true } [dev-dependencies] smallvec = "1.7.0" diff --git a/frame/transaction-storage/Cargo.toml b/frame/transaction-storage/Cargo.toml index 9bbc055dae1d..68b391387f87 100644 --- a/frame/transaction-storage/Cargo.toml +++ b/frame/transaction-storage/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -serde = { version = "1.0.131", optional = true } +serde = { version = "1.0.132", optional = true } hex-literal = { version = "0.3.4", optional = true } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } diff --git a/frame/treasury/Cargo.toml b/frame/treasury/Cargo.toml index 53cad5edffc3..a4e211283e13 100644 --- a/frame/treasury/Cargo.toml +++ b/frame/treasury/Cargo.toml @@ -18,7 +18,7 @@ codec = { package = "parity-scale-codec", version = "2.2.0", default-features = "max-encoded-len", ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -serde = { version = "1.0.131", features = ["derive"], optional = true } +serde = { version = "1.0.132", features = ["derive"], optional = true } impl-trait-for-tuples = "0.2.1" sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } diff --git a/primitives/application-crypto/Cargo.toml b/primitives/application-crypto/Cargo.toml index 750f8874493e..75766905d14f 100644 --- a/primitives/application-crypto/Cargo.toml +++ b/primitives/application-crypto/Cargo.toml @@ -18,7 +18,7 @@ targets = ["x86_64-unknown-linux-gnu"] sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -serde = { version = "1.0.131", optional = true, features = ["derive"] } +serde = { version = "1.0.132", optional = true, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-io = { version = "4.0.0", default-features = false, path = "../io" } diff --git a/primitives/arithmetic/Cargo.toml b/primitives/arithmetic/Cargo.toml index a035b03b82a2..b1ec8639248e 100644 --- a/primitives/arithmetic/Cargo.toml +++ b/primitives/arithmetic/Cargo.toml @@ -23,7 +23,7 @@ integer-sqrt = "0.1.2" static_assertions = "1.1.0" num-traits = { version = "0.2.8", default-features = false } sp-std = { version = "4.0.0", default-features = false, path = "../std" } -serde = { version = "1.0.131", optional = true, features = ["derive"] } +serde = { version = "1.0.132", optional = true, features = ["derive"] } sp-debug-derive = { version = "4.0.0", default-features = false, path = "../debug-derive" } [dev-dependencies] diff --git a/primitives/consensus/babe/Cargo.toml b/primitives/consensus/babe/Cargo.toml index 19e94a8da21d..330ce775eb06 100644 --- a/primitives/consensus/babe/Cargo.toml +++ b/primitives/consensus/babe/Cargo.toml @@ -27,7 +27,7 @@ sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../ sp-keystore = { version = "0.10.0", default-features = false, path = "../../keystore", optional = true } sp-runtime = { version = "4.0.0", default-features = false, path = "../../runtime" } sp-timestamp = { version = "4.0.0-dev", path = "../../timestamp", optional = true } -serde = { version = "1.0.131", features = ["derive"], optional = true } +serde = { version = "1.0.132", features = ["derive"], optional = true } async-trait = { version = "0.1.50", optional = true } [features] diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index a74fc75cb203..a6b2e21ce77f 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -19,7 +19,7 @@ codec = { package = "parity-scale-codec", version = "2.2.0", default-features = ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } log = { version = "0.4.11", default-features = false } -serde = { version = "1.0.131", optional = true, features = ["derive"] } +serde = { version = "1.0.132", optional = true, features = ["derive"] } byteorder = { version = "1.3.2", default-features = false } primitive-types = { version = "0.10.1", default-features = false, features = [ "codec", diff --git a/primitives/finality-grandpa/Cargo.toml b/primitives/finality-grandpa/Cargo.toml index 80607a0beb19..e12d7a52695d 100644 --- a/primitives/finality-grandpa/Cargo.toml +++ b/primitives/finality-grandpa/Cargo.toml @@ -19,7 +19,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } grandpa = { package = "finality-grandpa", version = "0.14.1", default-features = false, features = ["derive-codec"] } log = { version = "0.4.8", optional = true } -serde = { version = "1.0.131", optional = true, features = ["derive"] } +serde = { version = "1.0.132", optional = true, features = ["derive"] } sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } sp-application-crypto = { version = "4.0.0", default-features = false, path = "../application-crypto" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } diff --git a/primitives/npos-elections/Cargo.toml b/primitives/npos-elections/Cargo.toml index 3ee25f8ab816..d255688b56c7 100644 --- a/primitives/npos-elections/Cargo.toml +++ b/primitives/npos-elections/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -serde = { version = "1.0.131", optional = true, features = ["derive"] } +serde = { version = "1.0.132", optional = true, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-npos-elections-solution-type = { version = "4.0.0-dev", path = "./solution-type" } sp-arithmetic = { version = "4.0.0", default-features = false, path = "../arithmetic" } diff --git a/primitives/rpc/Cargo.toml b/primitives/rpc/Cargo.toml index fdc019bad4b6..51aaa990456e 100644 --- a/primitives/rpc/Cargo.toml +++ b/primitives/rpc/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -serde = { version = "1.0.131", features = ["derive"] } +serde = { version = "1.0.132", features = ["derive"] } sp-core = { version = "4.1.0-dev", path = "../core" } rustc-hash = "1.1.0" diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index a30bd08452d8..deb877abcca0 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] -serde = { version = "1.0.131", optional = true, features = ["derive"] } +serde = { version = "1.0.132", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } diff --git a/primitives/serializer/Cargo.toml b/primitives/serializer/Cargo.toml index 89ddb28df272..40f4d19e047e 100644 --- a/primitives/serializer/Cargo.toml +++ b/primitives/serializer/Cargo.toml @@ -14,5 +14,5 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -serde = "1.0.131" +serde = "1.0.132" serde_json = "1.0.71" diff --git a/primitives/storage/Cargo.toml b/primitives/storage/Cargo.toml index 98c8d693e9d6..81e4140bbd36 100644 --- a/primitives/storage/Cargo.toml +++ b/primitives/storage/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-std = { version = "4.0.0", default-features = false, path = "../std" } -serde = { version = "1.0.131", optional = true, features = ["derive"] } +serde = { version = "1.0.132", optional = true, features = ["derive"] } impl-serde = { version = "0.3.1", optional = true } ref-cast = "1.0.0" sp-debug-derive = { version = "4.0.0", default-features = false, path = "../debug-derive" } diff --git a/primitives/test-primitives/Cargo.toml b/primitives/test-primitives/Cargo.toml index 5bc81637e82a..5a045185e7ce 100644 --- a/primitives/test-primitives/Cargo.toml +++ b/primitives/test-primitives/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] sp-application-crypto = { version = "4.0.0", default-features = false, path = "../application-crypto" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } -serde = { version = "1.0.131", optional = true, features = ["derive"] } +serde = { version = "1.0.132", optional = true, features = ["derive"] } sp-runtime = { version = "4.0.0", default-features = false, path = "../runtime" } parity-util-mem = { version = "0.10.2", default-features = false, features = ["primitive-types"] } diff --git a/primitives/version/Cargo.toml b/primitives/version/Cargo.toml index b6ad02d4331f..585d089a54b5 100644 --- a/primitives/version/Cargo.toml +++ b/primitives/version/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] impl-serde = { version = "0.3.1", optional = true } -serde = { version = "1.0.131", optional = true, features = ["derive"] } +serde = { version = "1.0.132", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../std" } diff --git a/test-utils/client/Cargo.toml b/test-utils/client/Cargo.toml index c5a4a27c2ee9..fa0ae85e706c 100644 --- a/test-utils/client/Cargo.toml +++ b/test-utils/client/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0" } futures = "0.3.16" hex = "0.4" -serde = "1.0.131" +serde = "1.0.132" serde_json = "1.0.71" sc-client-api = { version = "4.0.0-dev", path = "../../client/api" } sc-client-db = { version = "0.10.0-dev", features = [ diff --git a/test-utils/runtime/Cargo.toml b/test-utils/runtime/Cargo.toml index ccaae6e69243..35c1291f38fb 100644 --- a/test-utils/runtime/Cargo.toml +++ b/test-utils/runtime/Cargo.toml @@ -48,7 +48,7 @@ sp-externalities = { version = "0.10.0", default-features = false, path = "../.. # 3rd party cfg-if = "1.0" log = { version = "0.4.14", default-features = false } -serde = { version = "1.0.131", optional = true, features = ["derive"] } +serde = { version = "1.0.132", optional = true, features = ["derive"] } [dev-dependencies] sc-block-builder = { version = "0.10.0-dev", path = "../../client/block-builder" } diff --git a/utils/frame/benchmarking-cli/Cargo.toml b/utils/frame/benchmarking-cli/Cargo.toml index fce53612e3ce..bf231eb67713 100644 --- a/utils/frame/benchmarking-cli/Cargo.toml +++ b/utils/frame/benchmarking-cli/Cargo.toml @@ -27,7 +27,7 @@ sp-state-machine = { version = "0.10.0", path = "../../../primitives/state-machi codec = { version = "2.0.0", package = "parity-scale-codec" } structopt = "0.3.25" chrono = "0.4" -serde = "1.0.131" +serde = "1.0.132" handlebars = "4.1.4" Inflector = "0.11.4" linked-hash-map = "0.5.4" diff --git a/utils/frame/remote-externalities/Cargo.toml b/utils/frame/remote-externalities/Cargo.toml index df6ef5c70419..f4e26b4db39b 100644 --- a/utils/frame/remote-externalities/Cargo.toml +++ b/utils/frame/remote-externalities/Cargo.toml @@ -20,7 +20,7 @@ frame-support = { path = "../../../frame/support", optional = true, version = "4 log = "0.4.11" codec = { package = "parity-scale-codec", version = "2.0.0" } serde_json = "1.0" -serde = "1.0.131" +serde = "1.0.132" sp-io = { version = "4.0.0-dev", path = "../../../primitives/io" } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } diff --git a/utils/frame/try-runtime/cli/Cargo.toml b/utils/frame/try-runtime/cli/Cargo.toml index 8f84750f8ebf..0c96d727cee0 100644 --- a/utils/frame/try-runtime/cli/Cargo.toml +++ b/utils/frame/try-runtime/cli/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] log = "0.4.8" parity-scale-codec = { version = "2.3.1" } -serde = "1.0.131" +serde = "1.0.132" structopt = "0.3.25" sc-service = { version = "0.10.0-dev", default-features = false, path = "../../../../client/service" } From 7fd0430d74628ae33f2da3808684c5d2c1045145 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Dec 2021 12:38:58 +0100 Subject: [PATCH 319/695] Bump frame-metadata from 14.0.0 to 14.2.0 (#10519) Bumps [frame-metadata](https://github.com/paritytech/frame-metadata) from 14.0.0 to 14.2.0. - [Release notes](https://github.com/paritytech/frame-metadata/releases) - [Changelog](https://github.com/paritytech/frame-metadata/blob/main/CHANGELOG.md) - [Commits](https://github.com/paritytech/frame-metadata/commits) --- updated-dependencies: - dependency-name: frame-metadata dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- frame/support/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f609823d59b9..5eb29dd2c8b4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2039,9 +2039,9 @@ dependencies = [ [[package]] name = "frame-metadata" -version = "14.0.0" +version = "14.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96616f82e069102b95a72c87de4c84d2f87ef7f0f20630e78ce3824436483110" +checksum = "37ed5e5c346de62ca5c184b4325a6600d1eaca210666e4606fe4e449574978d0" dependencies = [ "cfg-if 1.0.0", "parity-scale-codec", diff --git a/frame/support/Cargo.toml b/frame/support/Cargo.toml index 7aea7a0058e9..efc7caab1bd4 100644 --- a/frame/support/Cargo.toml +++ b/frame/support/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] serde = { version = "1.0.132", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -frame-metadata = { version = "14.0.0", default-features = false, features = ["v14"] } +frame-metadata = { version = "14.2.0", default-features = false, features = ["v14"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } From bdfbbb9718a17a7cba504c2e5b56b6be6898c2f3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Dec 2021 12:41:45 +0100 Subject: [PATCH 320/695] Bump git2 from 0.13.23 to 0.13.25 (#10522) Bumps [git2](https://github.com/rust-lang/git2-rs) from 0.13.23 to 0.13.25. - [Release notes](https://github.com/rust-lang/git2-rs/releases) - [Commits](https://github.com/rust-lang/git2-rs/compare/0.13.23...0.13.25) --- updated-dependencies: - dependency-name: git2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- utils/frame/generate-bags/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5eb29dd2c8b4..18cfe1893551 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2511,9 +2511,9 @@ checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" [[package]] name = "git2" -version = "0.13.23" +version = "0.13.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a8057932925d3a9d9e4434ea016570d37420ddb1ceed45a174d577f24ed6700" +checksum = "f29229cc1b24c0e6062f6e742aa3e256492a5323365e5ed3413599f8a5eff7d6" dependencies = [ "bitflags", "libc", @@ -3365,9 +3365,9 @@ checksum = "869d572136620d55835903746bcb5cdc54cb2851fd0aeec53220b4bb65ef3013" [[package]] name = "libgit2-sys" -version = "0.12.24+1.3.0" +version = "0.12.26+1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddbd6021eef06fb289a8f54b3c2acfdd85ff2a585dfbb24b8576325373d2152c" +checksum = "19e1c899248e606fbfe68dcb31d8b0176ebab833b103824af31bddf4b7457494" dependencies = [ "cc", "libc", diff --git a/utils/frame/generate-bags/Cargo.toml b/utils/frame/generate-bags/Cargo.toml index 6a512842129e..594683938517 100644 --- a/utils/frame/generate-bags/Cargo.toml +++ b/utils/frame/generate-bags/Cargo.toml @@ -21,6 +21,6 @@ sp-io = { version = "4.0.0", path = "../../../primitives/io" } # third party chrono = { version = "0.4.19" } -git2 = { version = "0.13.23", default-features = false } +git2 = { version = "0.13.25", default-features = false } num-format = { version = "0.4.0" } structopt = "0.3.25" From 6605aed9f74cf90e6e4e0df38c1a2852b16913dd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Dec 2021 12:36:11 +0000 Subject: [PATCH 321/695] Bump clap from 2.33.3 to 2.34.0 (#10523) Bumps [clap](https://github.com/clap-rs/clap) from 2.33.3 to 2.34.0. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/v2.33.3...v2.34.0) --- updated-dependencies: - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 27 +++++++++---------------- frame/bags-list/remote-tests/Cargo.toml | 2 +- 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 18cfe1893551..44d4e9a60928 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -91,15 +91,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "ansi_term" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -dependencies = [ - "winapi 0.3.9", -] - [[package]] name = "ansi_term" version = "0.12.1" @@ -908,7 +899,7 @@ dependencies = [ name = "chain-spec-builder" version = "2.0.0" dependencies = [ - "ansi_term 0.12.1", + "ansi_term", "node-cli", "rand 0.7.3", "sc-chain-spec", @@ -973,11 +964,11 @@ dependencies = [ [[package]] name = "clap" -version = "2.33.3" +version = "2.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ - "ansi_term 0.11.0", + "ansi_term", "atty", "bitflags", "strsim 0.8.0", @@ -6777,7 +6768,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0cfe1b2403f172ba0f234e500906ee0a3e493fb81092dac23ebefe129301cc" dependencies = [ - "ansi_term 0.12.1", + "ansi_term", "ctor", "diff", "output_vt100", @@ -8204,7 +8195,7 @@ dependencies = [ name = "sc-informant" version = "0.10.0-dev" dependencies = [ - "ansi_term 0.12.1", + "ansi_term", "futures 0.3.16", "futures-timer 3.0.2", "log 0.4.14", @@ -8638,7 +8629,7 @@ dependencies = [ name = "sc-tracing" version = "4.0.0-dev" dependencies = [ - "ansi_term 0.12.1", + "ansi_term", "atty", "chrono", "criterion", @@ -10311,7 +10302,7 @@ dependencies = [ name = "substrate-wasm-builder" version = "5.0.0-dev" dependencies = [ - "ansi_term 0.12.1", + "ansi_term", "build-helper", "cargo_metadata", "sp-maybe-compressed-blob", @@ -10816,7 +10807,7 @@ version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e0d2eaa99c3c2e41547cfa109e910a68ea03823cccad4a0525dcbc9b01e8c71" dependencies = [ - "ansi_term 0.12.1", + "ansi_term", "chrono", "lazy_static", "matchers", diff --git a/frame/bags-list/remote-tests/Cargo.toml b/frame/bags-list/remote-tests/Cargo.toml index 8e6a24674d0a..b120b32d5d4b 100644 --- a/frame/bags-list/remote-tests/Cargo.toml +++ b/frame/bags-list/remote-tests/Cargo.toml @@ -34,4 +34,4 @@ remote-externalities = { path = "../../../utils/frame/remote-externalities", ver tokio = { version = "1", features = ["macros"] } log = "0.4.14" structopt = "0.3.25" -clap = "2.33.3" +clap = "2.34.0" From 82cc3746450ae9722a249f4ddf83b8de59ba6e0d Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Tue, 21 Dec 2021 16:34:32 +0200 Subject: [PATCH 322/695] Beefy: Provide well-formed `ValidatorSet` (#10445) * beefy: provide well-formed ValidatorSet * pallet-beefy: use well-formed ValidatorSet * pallet-beefy-mmr: use well-formed ValidatorSet * beefy-gadget: fail votes early when ValidatorSet empty * beefy: small efficiency improvements * address review comments Signed-off-by: acatangiu --- client/beefy/src/keystore.rs | 4 +-- client/beefy/src/round.rs | 58 ++++++++++++------------------ client/beefy/src/worker.rs | 69 ++++++++++++++++++++++-------------- frame/beefy-mmr/src/tests.rs | 7 ++-- frame/beefy/src/lib.rs | 20 ++++++----- frame/beefy/src/tests.rs | 31 ++++++++-------- primitives/beefy/src/lib.rs | 56 +++++++++++++++++++++++++---- 7 files changed, 146 insertions(+), 99 deletions(-) diff --git a/client/beefy/src/keystore.rs b/client/beefy/src/keystore.rs index 7ee1ceb46bc3..eaae17e2015a 100644 --- a/client/beefy/src/keystore.rs +++ b/client/beefy/src/keystore.rs @@ -89,8 +89,8 @@ impl BeefyKeystore { let store = self.0.clone().ok_or_else(|| error::Error::Keystore("no Keystore".into()))?; let pk: Vec = SyncCryptoStore::ecdsa_public_keys(&*store, KEY_TYPE) - .iter() - .map(|k| Public::from(k.clone())) + .drain(..) + .map(Public::from) .collect(); Ok(pk) diff --git a/client/beefy/src/round.rs b/client/beefy/src/round.rs index db41f0f465db..b0df365b4e6f 100644 --- a/client/beefy/src/round.rs +++ b/client/beefy/src/round.rs @@ -74,15 +74,15 @@ where N: Ord + AtLeast32BitUnsigned + MaybeDisplay + Clone, { pub(crate) fn validator_set_id(&self) -> ValidatorSetId { - self.validator_set.id + self.validator_set.id() } - pub(crate) fn validators(&self) -> Vec { - self.validator_set.validators.clone() + pub(crate) fn validators(&self) -> &[Public] { + self.validator_set.validators() } pub(crate) fn add_vote(&mut self, round: &(H, N), vote: (Public, Signature)) -> bool { - if self.validator_set.validators.iter().any(|id| vote.0 == *id) { + if self.validator_set.validators().iter().any(|id| vote.0 == *id) { self.rounds.entry(round.clone()).or_default().add_vote(vote) } else { false @@ -93,7 +93,7 @@ where let done = self .rounds .get(round) - .map(|tracker| tracker.is_done(threshold(self.validator_set.validators.len()))) + .map(|tracker| tracker.is_done(threshold(self.validator_set.len()))) .unwrap_or(false); debug!(target: "beefy", "🥩 Round #{} done: {}", round.1, done); @@ -108,7 +108,7 @@ where Some( self.validator_set - .validators + .validators() .iter() .map(|authority_id| { signatures.iter().find_map(|(id, sig)| { @@ -139,26 +139,18 @@ mod tests { fn new_rounds() { sp_tracing::try_init_simple(); - let rounds = Rounds::>::new(ValidatorSet::::empty()); - - assert_eq!(0, rounds.validator_set_id()); - assert!(rounds.validators().is_empty()); - - let validators = ValidatorSet:: { - validators: vec![ - Keyring::Alice.public(), - Keyring::Bob.public(), - Keyring::Charlie.public(), - ], - id: 42, - }; + let validators = ValidatorSet::::new( + vec![Keyring::Alice.public(), Keyring::Bob.public(), Keyring::Charlie.public()], + 42, + ) + .unwrap(); let rounds = Rounds::>::new(validators); assert_eq!(42, rounds.validator_set_id()); assert_eq!( - vec![Keyring::Alice.public(), Keyring::Bob.public(), Keyring::Charlie.public()], + &vec![Keyring::Alice.public(), Keyring::Bob.public(), Keyring::Charlie.public()], rounds.validators() ); } @@ -167,14 +159,11 @@ mod tests { fn add_vote() { sp_tracing::try_init_simple(); - let validators = ValidatorSet:: { - validators: vec![ - Keyring::Alice.public(), - Keyring::Bob.public(), - Keyring::Charlie.public(), - ], - id: Default::default(), - }; + let validators = ValidatorSet::::new( + vec![Keyring::Alice.public(), Keyring::Bob.public(), Keyring::Charlie.public()], + Default::default(), + ) + .unwrap(); let mut rounds = Rounds::>::new(validators); @@ -212,14 +201,11 @@ mod tests { fn drop() { sp_tracing::try_init_simple(); - let validators = ValidatorSet:: { - validators: vec![ - Keyring::Alice.public(), - Keyring::Bob.public(), - Keyring::Charlie.public(), - ], - id: Default::default(), - }; + let validators = ValidatorSet::::new( + vec![Keyring::Alice.public(), Keyring::Bob.public(), Keyring::Charlie.public()], + Default::default(), + ) + .unwrap(); let mut rounds = Rounds::>::new(validators); diff --git a/client/beefy/src/worker.rs b/client/beefy/src/worker.rs index bf29a50f1964..306540077ae2 100644 --- a/client/beefy/src/worker.rs +++ b/client/beefy/src/worker.rs @@ -20,7 +20,7 @@ use std::{collections::BTreeSet, fmt::Debug, marker::PhantomData, sync::Arc}; use codec::{Codec, Decode, Encode}; use futures::{future, FutureExt, StreamExt}; -use log::{debug, error, info, trace, warn}; +use log::{debug, error, info, log_enabled, trace, warn}; use parking_lot::Mutex; use sc_client_api::{Backend, FinalityNotification, FinalityNotifications}; @@ -79,7 +79,7 @@ where /// Min delta in block numbers between two blocks, BEEFY should vote on min_block_delta: u32, metrics: Option, - rounds: round::Rounds>, + rounds: Option>>, finality_notifications: FinalityNotifications, /// Best block we received a GRANDPA notification for best_grandpa_block: NumberFor, @@ -125,7 +125,7 @@ where gossip_validator, min_block_delta, metrics, - rounds: round::Rounds::new(ValidatorSet::empty()), + rounds: None, finality_notifications: client.finality_notification_stream(), best_grandpa_block: client.info().finalized_number, best_beefy_block: None, @@ -172,7 +172,7 @@ where Some(new) } else { let at = BlockId::hash(header.hash()); - self.client.runtime_api().validator_set(&at).ok() + self.client.runtime_api().validator_set(&at).ok().flatten() }; trace!(target: "beefy", "🥩 active validator set: {:?}", new); @@ -190,11 +190,12 @@ where fn verify_validator_set( &self, block: &NumberFor, - mut active: ValidatorSet, + active: &ValidatorSet, ) -> Result<(), error::Error> { - let active: BTreeSet = active.validators.drain(..).collect(); + let active: BTreeSet<&Public> = active.validators().iter().collect(); - let store: BTreeSet = self.key_store.public_keys()?.drain(..).collect(); + let public_keys = self.key_store.public_keys()?; + let store: BTreeSet<&Public> = public_keys.iter().collect(); let missing: Vec<_> = store.difference(&active).cloned().collect(); @@ -214,26 +215,31 @@ where if let Some(active) = self.validator_set(¬ification.header) { // Authority set change or genesis set id triggers new voting rounds // - // TODO: (adoerr) Enacting a new authority set will also implicitly 'conclude' - // the currently active BEEFY voting round by starting a new one. This is - // temporary and needs to be replaced by proper round life cycle handling. - if active.id != self.rounds.validator_set_id() || - (active.id == GENESIS_AUTHORITY_SET_ID && self.best_beefy_block.is_none()) + // TODO: (grandpa-bridge-gadget#366) Enacting a new authority set will also + // implicitly 'conclude' the currently active BEEFY voting round by starting a + // new one. This should be replaced by proper round life-cycle handling. + if self.rounds.is_none() || + active.id() != self.rounds.as_ref().unwrap().validator_set_id() || + (active.id() == GENESIS_AUTHORITY_SET_ID && self.best_beefy_block.is_none()) { debug!(target: "beefy", "🥩 New active validator set id: {:?}", active); - metric_set!(self, beefy_validator_set_id, active.id); + metric_set!(self, beefy_validator_set_id, active.id()); // BEEFY should produce a signed commitment for each session - if active.id != self.last_signed_id + 1 && active.id != GENESIS_AUTHORITY_SET_ID { + if active.id() != self.last_signed_id + 1 && active.id() != GENESIS_AUTHORITY_SET_ID + { metric_inc!(self, beefy_skipped_sessions); } - // verify the new validator set - let _ = self.verify_validator_set(notification.header.number(), active.clone()); + if log_enabled!(target: "beefy", log::Level::Debug) { + // verify the new validator set - only do it if we're also logging the warning + let _ = self.verify_validator_set(notification.header.number(), &active); + } - self.rounds = round::Rounds::new(active.clone()); + let id = active.id(); + self.rounds = Some(round::Rounds::new(active)); - debug!(target: "beefy", "🥩 New Rounds for id: {:?}", active.id); + debug!(target: "beefy", "🥩 New Rounds for id: {:?}", id); self.best_beefy_block = Some(*notification.header.number()); @@ -244,9 +250,13 @@ where } if self.should_vote_on(*notification.header.number()) { - let authority_id = if let Some(id) = - self.key_store.authority_id(self.rounds.validators().as_slice()) - { + let (validators, validator_set_id) = if let Some(rounds) = &self.rounds { + (rounds.validators(), rounds.validator_set_id()) + } else { + debug!(target: "beefy", "🥩 Missing validator set - can't vote for: {:?}", notification.header.hash()); + return + }; + let authority_id = if let Some(id) = self.key_store.authority_id(validators) { debug!(target: "beefy", "🥩 Local authority id: {:?}", id); id } else { @@ -266,7 +276,7 @@ where let commitment = Commitment { payload, block_number: notification.header.number(), - validator_set_id: self.rounds.validator_set_id(), + validator_set_id, }; let encoded_commitment = commitment.encode(); @@ -305,12 +315,19 @@ where fn handle_vote(&mut self, round: (Payload, NumberFor), vote: (Public, Signature)) { self.gossip_validator.note_round(round.1); - let vote_added = self.rounds.add_vote(&round, vote); + let rounds = if let Some(rounds) = self.rounds.as_mut() { + rounds + } else { + debug!(target: "beefy", "🥩 Missing validator set - can't handle vote {:?}", vote); + return + }; + + let vote_added = rounds.add_vote(&round, vote); - if vote_added && self.rounds.is_done(&round) { - if let Some(signatures) = self.rounds.drop(&round) { + if vote_added && rounds.is_done(&round) { + if let Some(signatures) = rounds.drop(&round) { // id is stored for skipped session metric calculation - self.last_signed_id = self.rounds.validator_set_id(); + self.last_signed_id = rounds.validator_set_id(); let commitment = Commitment { payload: round.0, diff --git a/frame/beefy-mmr/src/tests.rs b/frame/beefy-mmr/src/tests.rs index f27bc450ad14..9cfbd94b53bc 100644 --- a/frame/beefy-mmr/src/tests.rs +++ b/frame/beefy-mmr/src/tests.rs @@ -84,10 +84,9 @@ fn should_contain_mmr_digest() { beefy_log(ConsensusLog::MmrRoot( hex!("f3e3afbfa69e89cd1e99f8d3570155962f3346d1d8758dc079be49ef70387758").into() )), - beefy_log(ConsensusLog::AuthoritiesChange(ValidatorSet { - validators: vec![mock_beefy_id(3), mock_beefy_id(4),], - id: 1, - })), + beefy_log(ConsensusLog::AuthoritiesChange( + ValidatorSet::new(vec![mock_beefy_id(3), mock_beefy_id(4),], 1,).unwrap() + )), beefy_log(ConsensusLog::MmrRoot( hex!("7d4ae4524bae75d52b63f08eab173b0c263eb95ae2c55c3a1d871241bd0cc559").into() )), diff --git a/frame/beefy/src/lib.rs b/frame/beefy/src/lib.rs index c18b28901bb6..9ef0c0d69f30 100644 --- a/frame/beefy/src/lib.rs +++ b/frame/beefy/src/lib.rs @@ -97,8 +97,10 @@ pub mod pallet { impl Pallet { /// Return the current active BEEFY validator set. - pub fn validator_set() -> ValidatorSet { - ValidatorSet:: { validators: Self::authorities(), id: Self::validator_set_id() } + pub fn validator_set() -> Option> { + let validators: Vec = Self::authorities(); + let id: beefy_primitives::ValidatorSetId = Self::validator_set_id(); + ValidatorSet::::new(validators, id) } fn change_authorities(new: Vec, queued: Vec) { @@ -109,13 +111,13 @@ impl Pallet { let next_id = Self::validator_set_id() + 1u64; >::put(next_id); - - let log = DigestItem::Consensus( - BEEFY_ENGINE_ID, - ConsensusLog::AuthoritiesChange(ValidatorSet { validators: new, id: next_id }) - .encode(), - ); - >::deposit_log(log); + if let Some(validator_set) = ValidatorSet::::new(new, next_id) { + let log = DigestItem::Consensus( + BEEFY_ENGINE_ID, + ConsensusLog::AuthoritiesChange(validator_set).encode(), + ); + >::deposit_log(log); + } } >::put(&queued); diff --git a/frame/beefy/src/tests.rs b/frame/beefy/src/tests.rs index 252c03efb54a..900a3770279b 100644 --- a/frame/beefy/src/tests.rs +++ b/frame/beefy/src/tests.rs @@ -70,10 +70,9 @@ fn session_change_updates_authorities() { assert!(1 == Beefy::validator_set_id()); - let want = beefy_log(ConsensusLog::AuthoritiesChange(ValidatorSet { - validators: vec![mock_beefy_id(3), mock_beefy_id(4)], - id: 1, - })); + let want = beefy_log(ConsensusLog::AuthoritiesChange( + ValidatorSet::new(vec![mock_beefy_id(3), mock_beefy_id(4)], 1).unwrap(), + )); let log = System::digest().logs[0].clone(); @@ -109,11 +108,11 @@ fn validator_set_at_genesis() { let want = vec![mock_beefy_id(1), mock_beefy_id(2)]; new_test_ext(vec![1, 2, 3, 4]).execute_with(|| { - let vs = Beefy::validator_set(); + let vs = Beefy::validator_set().unwrap(); - assert_eq!(vs.id, 0u64); - assert_eq!(vs.validators[0], want[0]); - assert_eq!(vs.validators[1], want[1]); + assert_eq!(vs.id(), 0u64); + assert_eq!(vs.validators()[0], want[0]); + assert_eq!(vs.validators()[1], want[1]); }); } @@ -124,18 +123,18 @@ fn validator_set_updates_work() { new_test_ext(vec![1, 2, 3, 4]).execute_with(|| { init_block(1); - let vs = Beefy::validator_set(); + let vs = Beefy::validator_set().unwrap(); - assert_eq!(vs.id, 0u64); - assert_eq!(want[0], vs.validators[0]); - assert_eq!(want[1], vs.validators[1]); + assert_eq!(vs.id(), 0u64); + assert_eq!(want[0], vs.validators()[0]); + assert_eq!(want[1], vs.validators()[1]); init_block(2); - let vs = Beefy::validator_set(); + let vs = Beefy::validator_set().unwrap(); - assert_eq!(vs.id, 1u64); - assert_eq!(want[2], vs.validators[0]); - assert_eq!(want[3], vs.validators[1]); + assert_eq!(vs.id(), 1u64); + assert_eq!(want[2], vs.validators()[0]); + assert_eq!(want[3], vs.validators()[1]); }); } diff --git a/primitives/beefy/src/lib.rs b/primitives/beefy/src/lib.rs index 20f6b9d0d8fb..bf72b801eec0 100644 --- a/primitives/beefy/src/lib.rs +++ b/primitives/beefy/src/lib.rs @@ -84,15 +84,39 @@ pub type ValidatorSetId = u64; #[derive(Decode, Encode, Debug, PartialEq, Clone, TypeInfo)] pub struct ValidatorSet { /// Public keys of the validator set elements - pub validators: Vec, + validators: Vec, /// Identifier of the validator set - pub id: ValidatorSetId, + id: ValidatorSetId, } impl ValidatorSet { - /// Return an empty validator set with id of 0. - pub fn empty() -> Self { - Self { validators: Default::default(), id: Default::default() } + /// Return a validator set with the given validators and set id. + pub fn new(validators: I, id: ValidatorSetId) -> Option + where + I: IntoIterator, + { + let validators: Vec = validators.into_iter().collect(); + if validators.is_empty() { + // No validators; the set would be empty. + None + } else { + Some(Self { validators, id }) + } + } + + /// Return a reference to the vec of validators. + pub fn validators(&self) -> &[AuthorityId] { + &self.validators + } + + /// Return the validator set id. + pub fn id(&self) -> ValidatorSetId { + self.id + } + + /// Return the number of validators in the set. + pub fn len(&self) -> usize { + self.validators.len() } } @@ -135,6 +159,26 @@ sp_api::decl_runtime_apis! { pub trait BeefyApi { /// Return the current active BEEFY validator set - fn validator_set() -> ValidatorSet; + fn validator_set() -> Option>; + } +} + +#[cfg(test)] +mod tests { + use super::*; + use sp_application_crypto::ecdsa::{self, Public}; + use sp_core::Pair; + + #[test] + fn validator_set() { + // Empty set not allowed. + assert_eq!(ValidatorSet::::new(vec![], 0), None); + + let alice = ecdsa::Pair::from_string("//Alice", None).unwrap(); + let set_id = 0; + let validators = ValidatorSet::::new(vec![alice.public()], set_id).unwrap(); + + assert_eq!(validators.id(), set_id); + assert_eq!(validators.validators(), &vec![alice.public()]); } } From 5cd78cfeead8bddc79f12f6747a92233e14992ab Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 21 Dec 2021 15:09:37 +0000 Subject: [PATCH 323/695] Serialize CodeUploadReturnValue deposit correctly (#10526) --- frame/contracts/common/src/lib.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/frame/contracts/common/src/lib.rs b/frame/contracts/common/src/lib.rs index b5873869495e..7d99db42a2b9 100644 --- a/frame/contracts/common/src/lib.rs +++ b/frame/contracts/common/src/lib.rs @@ -151,11 +151,19 @@ pub struct InstantiateReturnValue { /// The result of succesfully uploading a contract. #[derive(PartialEq, Eq, Encode, Decode, RuntimeDebug)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "std", + serde( + rename_all = "camelCase", + bound(serialize = "CodeHash: Serialize, Balance: Copy + Into"), + bound(deserialize = "CodeHash: Deserialize<'de>, Balance: TryFrom") + ) +)] pub struct CodeUploadReturnValue { /// The key under which the new code is stored. pub code_hash: CodeHash, /// The deposit that was reserved at the caller. Is zero when the code already existed. + #[cfg_attr(feature = "std", serde(with = "as_hex"))] pub deposit: Balance, } From 3ce158c007ac030c2d2b43d0c34c849447d8eee5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Tue, 21 Dec 2021 18:36:46 +0100 Subject: [PATCH 324/695] Use exists host function (#10531) --- frame/support/src/storage/child.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/frame/support/src/storage/child.rs b/frame/support/src/storage/child.rs index 4b237aaa561f..5497f642067c 100644 --- a/frame/support/src/storage/child.rs +++ b/frame/support/src/storage/child.rs @@ -112,8 +112,7 @@ pub fn take_or_else T>( pub fn exists(child_info: &ChildInfo, key: &[u8]) -> bool { match child_info.child_type() { ChildType::ParentKeyId => - sp_io::default_child_storage::read(child_info.storage_key(), key, &mut [0; 0][..], 0) - .is_some(), + sp_io::default_child_storage::exists(child_info.storage_key(), key), } } From e2cab4ee66c594741a1db9c8f43177e4f0af0a55 Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Tue, 21 Dec 2021 18:42:15 +0100 Subject: [PATCH 325/695] add to (#10524) --- .../support/src/storage/types/counted_map.rs | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/frame/support/src/storage/types/counted_map.rs b/frame/support/src/storage/types/counted_map.rs index 01414d7019ae..c4230cafc40b 100644 --- a/frame/support/src/storage/types/counted_map.rs +++ b/frame/support/src/storage/types/counted_map.rs @@ -412,6 +412,23 @@ where res }) } + + /// Enumerate all elements in the counted map after a specified `starting_raw_key` in no + /// particular order. + /// + /// If you alter the map while doing this, you'll get undefined results. + pub fn iter_from( + starting_raw_key: Vec, + ) -> crate::storage::PrefixIterator<(Key, Value), OnRemovalCounterUpdate> { + let map_iterator = ::Map::iter_from(starting_raw_key); + crate::storage::PrefixIterator { + prefix: map_iterator.prefix, + previous_key: map_iterator.previous_key, + drain: map_iterator.drain, + closure: map_iterator.closure, + phantom: Default::default(), + } + } } impl StorageEntryMetadataBuilder @@ -1022,6 +1039,25 @@ mod test { }) } + #[test] + fn test_iter_from() { + type A = CountedStorageMap; + TestExternalities::default().execute_with(|| { + A::insert(1, 1); + A::insert(2, 2); + A::insert(3, 3); + A::insert(4, 4); + + // no prefix is same as normal iter. + assert_eq!(A::iter_from(vec![]).collect::>(), A::iter().collect::>()); + + let iter_all = A::iter().collect::>(); + let (before, after) = iter_all.split_at(2); + let last_key = before.last().map(|(k, _)| k).unwrap(); + assert_eq!(A::iter_from(A::hashed_key_for(last_key)).collect::>(), after); + }) + } + #[test] fn test_metadata() { type A = CountedStorageMap; From a230543899e5b161a2ca55e56f5493010390c9e9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Dec 2021 18:44:59 +0100 Subject: [PATCH 326/695] Bump handlebars from 4.1.4 to 4.1.6 (#10518) Bumps [handlebars](https://github.com/sunng87/handlebars-rust) from 4.1.4 to 4.1.6. - [Release notes](https://github.com/sunng87/handlebars-rust/releases) - [Changelog](https://github.com/sunng87/handlebars-rust/blob/master/CHANGELOG.md) - [Commits](https://github.com/sunng87/handlebars-rust/compare/v4.1.4...v4.1.6) --- updated-dependencies: - dependency-name: handlebars dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- utils/frame/benchmarking-cli/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 44d4e9a60928..89e4f3f832b0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2572,9 +2572,9 @@ checksum = "62aca2aba2d62b4a7f5b33f3712cb1b0692779a56fb510499d5c0aa594daeaf3" [[package]] name = "handlebars" -version = "4.1.4" +version = "4.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1874024f4a29f47d609014caec0b1c866f1c1eb0661a09c9733ecc4757f5f88" +checksum = "167fa173496c9eadd8749cca6f8339ac88e248f3ad2442791d0b743318a94fc0" dependencies = [ "log 0.4.14", "pest", diff --git a/utils/frame/benchmarking-cli/Cargo.toml b/utils/frame/benchmarking-cli/Cargo.toml index bf231eb67713..61988e24e3b0 100644 --- a/utils/frame/benchmarking-cli/Cargo.toml +++ b/utils/frame/benchmarking-cli/Cargo.toml @@ -28,7 +28,7 @@ codec = { version = "2.0.0", package = "parity-scale-codec" } structopt = "0.3.25" chrono = "0.4" serde = "1.0.132" -handlebars = "4.1.4" +handlebars = "4.1.6" Inflector = "0.11.4" linked-hash-map = "0.5.4" log = "0.4.8" From 5ddbcdd99ae6120f3f240920d683b8bcb55f437d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Dec 2021 09:21:54 +0100 Subject: [PATCH 327/695] Bump strum_macros from 0.22.0 to 0.23.1 (#10532) Bumps [strum_macros](https://github.com/Peternator7/strum) from 0.22.0 to 0.23.1. - [Release notes](https://github.com/Peternator7/strum/releases) - [Changelog](https://github.com/Peternator7/strum/blob/master/CHANGELOG.md) - [Commits](https://github.com/Peternator7/strum/commits) --- updated-dependencies: - dependency-name: strum_macros dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 17 +++++++++++++++-- frame/election-provider-multi-phase/Cargo.toml | 2 +- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 89e4f3f832b0..0b61fef54db8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5549,7 +5549,7 @@ dependencies = [ "sp-tracing", "static_assertions", "strum", - "strum_macros", + "strum_macros 0.23.1", ] [[package]] @@ -10056,7 +10056,7 @@ version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7ac893c7d471c8a21f31cfe213ec4f6d9afeed25537c772e08ef3f005f8729e" dependencies = [ - "strum_macros", + "strum_macros 0.22.0", ] [[package]] @@ -10071,6 +10071,19 @@ dependencies = [ "syn", ] +[[package]] +name = "strum_macros" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bb0dc7ee9c15cea6199cde9a127fa16a4c5819af85395457ad72d68edc85a38" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn", +] + [[package]] name = "subkey" version = "2.0.1" diff --git a/frame/election-provider-multi-phase/Cargo.toml b/frame/election-provider-multi-phase/Cargo.toml index 75a1ed083829..c8ed0c561b46 100644 --- a/frame/election-provider-multi-phase/Cargo.toml +++ b/frame/election-provider-multi-phase/Cargo.toml @@ -38,7 +38,7 @@ rand = { version = "0.7.3", default-features = false, optional = true, features "small_rng", ] } strum = { optional = true, version = "0.22.0" } -strum_macros = { optional = true, version = "0.22.0" } +strum_macros = { optional = true, version = "0.23.1" } [dev-dependencies] parking_lot = "0.11.2" From 1c67f8ec6e64e431f98d2c15ff1012aeada07996 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Dec 2021 11:47:51 +0100 Subject: [PATCH 328/695] Bump libc from 0.2.105 to 0.2.112 (#10537) Bumps [libc](https://github.com/rust-lang/libc) from 0.2.105 to 0.2.112. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.105...0.2.112) --- updated-dependencies: - dependency-name: libc dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- client/executor/wasmtime/Cargo.toml | 2 +- client/tracing/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0b61fef54db8..4ac0a977324c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3350,9 +3350,9 @@ checksum = "3576a87f2ba00f6f106fdfcd16db1d698d648a26ad8e0573cad8537c3c362d2a" [[package]] name = "libc" -version = "0.2.105" +version = "0.2.112" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "869d572136620d55835903746bcb5cdc54cb2851fd0aeec53220b4bb65ef3013" +checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" [[package]] name = "libgit2-sys" diff --git a/client/executor/wasmtime/Cargo.toml b/client/executor/wasmtime/Cargo.toml index 6718e6d13f3c..65efc2603509 100644 --- a/client/executor/wasmtime/Cargo.toml +++ b/client/executor/wasmtime/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -libc = "0.2.105" +libc = "0.2.112" cfg-if = "1.0" log = "0.4.8" parity-wasm = "0.42.0" diff --git a/client/tracing/Cargo.toml b/client/tracing/Cargo.toml index 55ecd0a1481a..7ea0d80ba1f2 100644 --- a/client/tracing/Cargo.toml +++ b/client/tracing/Cargo.toml @@ -17,7 +17,7 @@ ansi_term = "0.12.1" atty = "0.2.13" chrono = "0.4.19" lazy_static = "1.4.0" -libc = "0.2.105" +libc = "0.2.112" log = { version = "0.4.8" } once_cell = "1.8.0" parking_lot = "0.11.2" From 5b491e8d9172b69a3d77f81ab17434d440f85df5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Dec 2021 11:55:05 +0100 Subject: [PATCH 329/695] Bump futures-util from 0.3.17 to 0.3.19 (#10513) Bumps [futures-util](https://github.com/rust-lang/futures-rs) from 0.3.17 to 0.3.19. - [Release notes](https://github.com/rust-lang/futures-rs/releases) - [Changelog](https://github.com/rust-lang/futures-rs/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/futures-rs/compare/0.3.17...0.3.19) --- updated-dependencies: - dependency-name: futures-util dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 39 +++++++++++++------------------------ utils/prometheus/Cargo.toml | 2 +- 2 files changed, 15 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4ac0a977324c..a68476797497 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2279,9 +2279,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.17" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5da6ba8c3bb3c165d3c7319fc1cc8304facf1fb8db99c5de877183c08a273888" +checksum = "ba3dda0b6588335f360afc675d0564c17a77a2bda81ca178a4b6081bd86c7f0b" dependencies = [ "futures-core", "futures-sink", @@ -2289,9 +2289,9 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.17" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d1c26957f23603395cd326b0ffe64124b818f4449552f960d815cfba83a53d" +checksum = "d0c8ff0461b82559810cdccfde3215c3f373807f5e5232b71479bff7bb2583d7" [[package]] name = "futures-executor" @@ -2307,9 +2307,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.17" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "522de2a0fe3e380f1bc577ba0474108faf3f6b18321dbf60b3b9c39a75073377" +checksum = "b1f9d34af5a1aac6fb380f735fe510746c38067c5bf16c7fd250280503c971b2" [[package]] name = "futures-lite" @@ -2328,12 +2328,10 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.17" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18e4a4b95cea4b4ccbcf1c5675ca7c4ee4e9e75eb79944d07defde18068f79bb" +checksum = "6dbd947adfffb0efc70599b3ddcf7b5597bb5fa9e245eb99f62b3a5f7bb8bd3c" dependencies = [ - "autocfg 1.0.1", - "proc-macro-hack", "proc-macro2", "quote", "syn", @@ -2352,15 +2350,15 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.17" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36ea153c13024fe480590b3e3d4cad89a0cfacecc24577b68f86c6ced9c2bc11" +checksum = "e3055baccb68d74ff6480350f8d6eb8fcfa3aa11bdc1a1ae3afdd0514617d508" [[package]] name = "futures-task" -version = "0.3.17" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d3d00f4eddb73e498a54394f228cd55853bdf059259e8e7bc6e69d408892e99" +checksum = "6ee7c6485c30167ce4dfb83ac568a849fe53274c831081476ee13e0dce1aad72" [[package]] name = "futures-timer" @@ -2376,11 +2374,10 @@ checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" [[package]] name = "futures-util" -version = "0.3.17" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36568465210a3a6ee45e1f165136d68671471a501e632e9a98d96872222b5481" +checksum = "d9b5cf40b47a271f77a8b1bec03ca09044d99d2372c0de244e66430761127164" dependencies = [ - "autocfg 1.0.1", "futures 0.1.31", "futures-channel", "futures-core", @@ -2391,8 +2388,6 @@ dependencies = [ "memchr", "pin-project-lite 0.2.6", "pin-utils", - "proc-macro-hack", - "proc-macro-nested", "slab", ] @@ -6836,12 +6831,6 @@ version = "0.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" -[[package]] -name = "proc-macro-nested" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" - [[package]] name = "proc-macro2" version = "1.0.32" diff --git a/utils/prometheus/Cargo.toml b/utils/prometheus/Cargo.toml index b9a3a5a5d197..4ae38f645532 100644 --- a/utils/prometheus/Cargo.toml +++ b/utils/prometheus/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] log = "0.4.8" prometheus = { version = "0.13.0", default-features = false } -futures-util = { version = "0.3.17", default-features = false, features = ["io"] } +futures-util = { version = "0.3.19", default-features = false, features = ["io"] } derive_more = "0.99" async-std = { version = "1.10.0", features = ["unstable"] } tokio = "1.15" From 0b57148b55667c0802161607324ad9f517248ae1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Dec 2021 16:25:53 +0100 Subject: [PATCH 330/695] Bump num_cpus from 1.13.0 to 1.13.1 (#10539) Bumps [num_cpus](https://github.com/seanmonstar/num_cpus) from 1.13.0 to 1.13.1. - [Release notes](https://github.com/seanmonstar/num_cpus/releases) - [Changelog](https://github.com/seanmonstar/num_cpus/blob/master/CHANGELOG.md) - [Commits](https://github.com/seanmonstar/num_cpus/compare/v1.13.0...v1.13.1) --- updated-dependencies: - dependency-name: num_cpus dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- client/offchain/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a68476797497..32a52fb460d8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4990,9 +4990,9 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" dependencies = [ "hermit-abi", "libc", diff --git a/client/offchain/Cargo.toml b/client/offchain/Cargo.toml index 38834181b163..4ca1b242a48e 100644 --- a/client/offchain/Cargo.toml +++ b/client/offchain/Cargo.toml @@ -19,7 +19,7 @@ hex = "0.4" fnv = "1.0.6" futures = "0.3.16" futures-timer = "3.0.2" -num_cpus = "1.10" +num_cpus = "1.13" parking_lot = "0.11.2" rand = "0.7.2" sc-client-api = { version = "4.0.0-dev", path = "../api" } From e1a47ef9bd8badae77e7484b1aa5222a63f83be1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Dec 2021 16:22:55 +0000 Subject: [PATCH 331/695] Bump nix from 0.23.0 to 0.23.1 (#10542) Bumps [nix](https://github.com/nix-rust/nix) from 0.23.0 to 0.23.1. - [Release notes](https://github.com/nix-rust/nix/releases) - [Changelog](https://github.com/nix-rust/nix/blob/master/CHANGELOG.md) - [Commits](https://github.com/nix-rust/nix/compare/v0.23.0...v0.23.1) --- updated-dependencies: - dependency-name: nix dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 32a52fb460d8..5ed9325b43a3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4460,9 +4460,9 @@ dependencies = [ [[package]] name = "nix" -version = "0.23.0" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f305c2c2e4c39a82f7bf0bf65fb557f9070ce06781d4f2454295cc34b1c43188" +checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6" dependencies = [ "bitflags", "cc", From 50156013c9316cd8849cb3db34670d046b8d66ea Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Dec 2021 17:39:30 +0100 Subject: [PATCH 332/695] Bump zeroize from 1.4.2 to 1.4.3 (#10538) Bumps [zeroize](https://github.com/RustCrypto/utils) from 1.4.2 to 1.4.3. - [Release notes](https://github.com/RustCrypto/utils/releases) - [Commits](https://github.com/RustCrypto/utils/commits/zeroize-v1.4.3) --- updated-dependencies: - dependency-name: zeroize dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- client/network/Cargo.toml | 2 +- primitives/core/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5ed9325b43a3..96146f6f8bec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11925,9 +11925,9 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.4.2" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf68b08513768deaa790264a7fac27a58cbf2705cfcdc9448362229217d7e970" +checksum = "d68d9dcec5f9b43a30d38c49f91dfedfaac384cb8f085faca366c26207dd1619" dependencies = [ "zeroize_derive", ] diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index 436f9227d35a..4f3ea4e939b6 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -63,7 +63,7 @@ unsigned-varint = { version = "0.6.0", features = [ "asynchronous_codec", ] } void = "1.0.2" -zeroize = "1.4.2" +zeroize = "1.4.3" libp2p = "0.40.0" [dev-dependencies] diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index a6b2e21ce77f..05fc1240e274 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -35,7 +35,7 @@ substrate-bip39 = { version = "0.4.4", optional = true } tiny-bip39 = { version = "0.8.2", optional = true } regex = { version = "1.5.4", optional = true } num-traits = { version = "0.2.8", default-features = false } -zeroize = { version = "1.4.2", default-features = false } +zeroize = { version = "1.4.3", default-features = false } secrecy = { version = "0.8.0", default-features = false } lazy_static = { version = "1.4.0", default-features = false, optional = true } parking_lot = { version = "0.11.2", optional = true } From 0444ab7b4afbf4347d51e1e7352cda878e6a3df7 Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Thu, 23 Dec 2021 19:32:06 +0800 Subject: [PATCH 333/695] Customizable ink address (#10521) --- bin/node/runtime/src/lib.rs | 1 + frame/contracts/src/lib.rs | 71 ++++++++++++++++++++++++++++-------- frame/contracts/src/tests.rs | 4 +- 3 files changed, 60 insertions(+), 16 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 97de54fc21e8..a79d8997f4ce 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -957,6 +957,7 @@ impl pallet_contracts::Config for Runtime { type DeletionQueueDepth = DeletionQueueDepth; type DeletionWeightLimit = DeletionWeightLimit; type Schedule = Schedule; + type AddressGenerator = pallet_contracts::DefaultAddressGenerator; } impl pallet_sudo::Config for Runtime { diff --git a/frame/contracts/src/lib.rs b/frame/contracts/src/lib.rs index b604c9618c6a..ab7a0c254f56 100644 --- a/frame/contracts/src/lib.rs +++ b/frame/contracts/src/lib.rs @@ -136,6 +136,55 @@ type BalanceOf = /// The current storage version. const STORAGE_VERSION: StorageVersion = StorageVersion::new(6); +/// Provides the contract address generation method. +/// +/// See [`DefaultAddressGenerator`] for the default implementation. +pub trait AddressGenerator { + /// Generate the address of a contract based on the given instantiate parameters. + /// + /// # Note for implementors + /// 1. Make sure that there are no collisions, different inputs never lead to the same output. + /// 2. Make sure that the same inputs lead to the same output. + /// 3. Changing the implementation through a runtime upgrade without a proper storage migration + /// would lead to catastrophic misbehavior. + fn generate_address( + deploying_address: &T::AccountId, + code_hash: &CodeHash, + salt: &[u8], + ) -> T::AccountId; +} + +/// Default address generator. +/// +/// This is the default address generator used by contract instantiation. Its result +/// is only dependend on its inputs. It can therefore be used to reliably predict the +/// address of a contract. This is akin to the formular of eth's CREATE2 opcode. There +/// is no CREATE equivalent because CREATE2 is strictly more powerful. +/// +/// Formula: `hash(deploying_address ++ code_hash ++ salt)` +pub struct DefaultAddressGenerator; + +impl AddressGenerator for DefaultAddressGenerator +where + T: frame_system::Config, + T::AccountId: UncheckedFrom + AsRef<[u8]>, +{ + fn generate_address( + deploying_address: &T::AccountId, + code_hash: &CodeHash, + salt: &[u8], + ) -> T::AccountId { + let buf: Vec<_> = deploying_address + .as_ref() + .iter() + .chain(code_hash.as_ref()) + .chain(salt) + .cloned() + .collect(); + UncheckedFrom::unchecked_from(T::Hashing::hash(&buf)) + } +} + #[frame_support::pallet] pub mod pallet { use super::*; @@ -227,6 +276,9 @@ pub mod pallet { /// Changing this value for an existing chain might need a storage migration. #[pallet::constant] type DepositPerItem: Get>; + + /// The address generator used to generate the addresses of contracts. + type AddressGenerator: AddressGenerator; } #[pallet::pallet] @@ -728,27 +780,16 @@ where Ok(maybe_value) } - /// Determine the address of a contract, - /// - /// This is the address generation function used by contract instantiation. Its result - /// is only dependend on its inputs. It can therefore be used to reliably predict the - /// address of a contract. This is akin to the formular of eth's CREATE2 opcode. There - /// is no CREATE equivalent because CREATE2 is strictly more powerful. + /// Determine the address of a contract. /// - /// Formula: `hash(deploying_address ++ code_hash ++ salt)` + /// This is the address generation function used by contract instantiation. See + /// [`DefaultAddressGenerator`] for the default implementation. pub fn contract_address( deploying_address: &T::AccountId, code_hash: &CodeHash, salt: &[u8], ) -> T::AccountId { - let buf: Vec<_> = deploying_address - .as_ref() - .iter() - .chain(code_hash.as_ref()) - .chain(salt) - .cloned() - .collect(); - UncheckedFrom::unchecked_from(T::Hashing::hash(&buf)) + T::AddressGenerator::generate_address(deploying_address, code_hash, salt) } /// Store code for benchmarks which does not check nor instrument the code. diff --git a/frame/contracts/src/tests.rs b/frame/contracts/src/tests.rs index 584253aeaadf..6ca4e34f8aea 100644 --- a/frame/contracts/src/tests.rs +++ b/frame/contracts/src/tests.rs @@ -24,7 +24,8 @@ use crate::{ storage::Storage, wasm::{PrefabWasmModule, ReturnCode as RuntimeReturnCode}, weights::WeightInfo, - BalanceOf, Code, CodeStorage, Config, ContractInfoOf, Error, Pallet, Schedule, + BalanceOf, Code, CodeStorage, Config, ContractInfoOf, DefaultAddressGenerator, Error, Pallet, + Schedule, }; use assert_matches::assert_matches; use codec::Encode; @@ -285,6 +286,7 @@ impl Config for Test { type Schedule = MySchedule; type DepositPerByte = DepositPerByte; type DepositPerItem = DepositPerItem; + type AddressGenerator = DefaultAddressGenerator; } pub const ALICE: AccountId32 = AccountId32::new([1u8; 32]); From 026ec33ff7b9686055c45c1633cab2ed66dc59fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Thu, 23 Dec 2021 18:45:43 +0100 Subject: [PATCH 334/695] chain-spec: Make chain spec writing deterministic (#10550) * chain-spec: Make chain spec writing deterministic This switches the chain spec to use `BTreeMap` internally instead of `HashMap`. This ensures that reading and writing the same chain spec always results in the same file. * fmt --- client/chain-spec/src/chain_spec.rs | 63 +++++++++++++++++++++++++---- client/chain-spec/src/lib.rs | 2 +- 2 files changed, 56 insertions(+), 9 deletions(-) diff --git a/client/chain-spec/src/chain_spec.rs b/client/chain-spec/src/chain_spec.rs index e8247d731499..520c071d35ce 100644 --- a/client/chain-spec/src/chain_spec.rs +++ b/client/chain-spec/src/chain_spec.rs @@ -29,7 +29,7 @@ use sp_core::{ Bytes, }; use sp_runtime::BuildStorage; -use std::{borrow::Cow, collections::HashMap, fs::File, path::PathBuf, sync::Arc}; +use std::{borrow::Cow, collections::BTreeMap, fs::File, path::PathBuf, sync::Arc}; enum GenesisSource { File(PathBuf), @@ -131,7 +131,7 @@ impl BuildStorage for ChainSpec { } } -pub type GenesisStorage = HashMap; +pub type GenesisStorage = BTreeMap; /// Raw storage content for genesis block. #[derive(Serialize, Deserialize)] @@ -139,7 +139,7 @@ pub type GenesisStorage = HashMap; #[serde(deny_unknown_fields)] pub struct RawGenesis { pub top: GenesisStorage, - pub children_default: HashMap, + pub children_default: BTreeMap, } #[derive(Serialize, Deserialize)] @@ -180,7 +180,7 @@ struct ClientSpec { /// The given `wasm_code` will be used to substitute the on-chain wasm code from the given /// block hash onwards. #[serde(default)] - code_substitutes: HashMap, + code_substitutes: BTreeMap, } /// A type denoting empty extensions. @@ -271,7 +271,7 @@ impl ChainSpec { extensions, consensus_engine: (), genesis: Default::default(), - code_substitutes: HashMap::new(), + code_substitutes: BTreeMap::new(), }; ChainSpec { client_spec, genesis: GenesisSource::Factory(Arc::new(constructor)) } @@ -416,7 +416,7 @@ where self.genesis = GenesisSource::Storage(storage); } - fn code_substitutes(&self) -> std::collections::HashMap> { + fn code_substitutes(&self) -> std::collections::BTreeMap> { self.client_spec .code_substitutes .iter() @@ -430,7 +430,7 @@ mod tests { use super::*; #[derive(Debug, Serialize, Deserialize)] - struct Genesis(HashMap); + struct Genesis(BTreeMap); impl BuildStorage for Genesis { fn assimilate_storage(&self, storage: &mut Storage) -> Result<(), String> { @@ -455,12 +455,28 @@ mod tests { assert_eq!(spec2.chain_type(), ChainType::Live) } - #[derive(Debug, Serialize, Deserialize)] + #[derive(Debug, Serialize, Deserialize, Clone)] #[serde(rename_all = "camelCase")] struct Extension1 { my_property: String, } + impl crate::Extension for Extension1 { + type Forks = Option<()>; + + fn get(&self) -> Option<&T> { + None + } + + fn get_any(&self, _: std::any::TypeId) -> &dyn std::any::Any { + self + } + + fn get_any_mut(&mut self, _: std::any::TypeId) -> &mut dyn std::any::Any { + self + } + } + type TestSpec2 = ChainSpec; #[test] @@ -472,4 +488,35 @@ mod tests { assert_eq!(spec.extensions().my_property, "Test Extension"); } + + #[test] + fn chain_spec_raw_output_should_be_deterministic() { + let mut spec = TestSpec2::from_json_bytes(Cow::Owned( + include_bytes!("../res/chain_spec2.json").to_vec(), + )) + .unwrap(); + + let mut storage = spec.build_storage().unwrap(); + + // Add some extra data, so that storage "sorting" is tested. + let extra_data = &[("random_key", "val"), ("r@nd0m_key", "val"), ("aaarandom_key", "val")]; + storage + .top + .extend(extra_data.iter().map(|(k, v)| (k.as_bytes().to_vec(), v.as_bytes().to_vec()))); + crate::ChainSpec::set_storage(&mut spec, storage); + + let json = spec.as_json(true).unwrap(); + + // Check multiple times that decoding and encoding the chain spec leads always to the same + // output. + for _ in 0..10 { + assert_eq!( + json, + TestSpec2::from_json_bytes(json.as_bytes().to_vec()) + .unwrap() + .as_json(true) + .unwrap() + ); + } + } } diff --git a/client/chain-spec/src/lib.rs b/client/chain-spec/src/lib.rs index 334d8f8b3d7a..cbb1e85df3c1 100644 --- a/client/chain-spec/src/lib.rs +++ b/client/chain-spec/src/lib.rs @@ -186,7 +186,7 @@ pub trait ChainSpec: BuildStorage + Send + Sync { /// This will be used as storage at genesis. fn set_storage(&mut self, storage: Storage); /// Returns code substitutes that should be used for the on chain wasm. - fn code_substitutes(&self) -> std::collections::HashMap>; + fn code_substitutes(&self) -> std::collections::BTreeMap>; } impl std::fmt::Debug for dyn ChainSpec { From b03e8bcf151bbf4c20a7d7faa782366fc3554d58 Mon Sep 17 00:00:00 2001 From: cheme Date: Fri, 24 Dec 2021 09:54:07 +0100 Subject: [PATCH 335/695] Inner hashing of value in state trie (runtime versioning). (#9732) * starting * Updated from other branch. * setting flag * flag in storage struct * fix flagging to access and insert. * added todo to fix * also missing serialize meta to storage proof * extract meta. * Isolate old trie layout. * failing test that requires storing in meta when old hash scheme is used. * old hash compatibility * Db migrate. * runing tests with both states when interesting. * fix chain spec test with serde default. * export state (missing trie function). * Pending using new branch, lacking genericity on layout resolution. * extract and set global meta * Update to branch 4 * fix iterator with root flag (no longer insert node). * fix trie root hashing of root * complete basic backend. * Remove old_hash meta from proof that do not use inner_hashing. * fix trie test for empty (force layout on empty deltas). * Root update fix. * debug on meta * Use trie key iteration that do not include value in proofs. * switch default test ext to use inner hash. * small integration test, and fix tx cache mgmt in ext. test failing * Proof scenario at state-machine level. * trace for db upgrade * try different param * act more like iter_from. * Bigger batches. * Update trie dependency. * drafting codec changes and refact * before removing unused branch no value alt hashing. more work todo rename all flag var to alt_hash, and remove extrinsic replace by storage query at every storage_root call. * alt hashing only for branch with value. * fix trie tests * Hash of value include the encoded size. * removing fields(broken) * fix trie_stream to also include value length in inner hash. * triedbmut only using alt type if inner hashing. * trie_stream to also only use alt hashing type when actually alt hashing. * Refactor meta state, logic should work with change of trie treshold. * Remove NoMeta variant. * Remove state_hashed trigger specific functions. * pending switching to using threshold, new storage root api does not make much sense. * refactoring to use state from backend (not possible payload changes). * Applying from previous state * Remove default from storage, genesis need a special build. * rem empty space * Catch problem: when using triedb with default: we should not revert nodes: otherwhise thing as trie codec cannot decode-encode without changing state. * fix compilation * Right logic to avoid switch on reencode when default layout. * Clean up some todos * remove trie meta from root upstream * update upstream and fix benches. * split some long lines. * UPdate trie crate to work with new design. * Finish update to refactored upstream. * update to latest triedb changes. * Clean up. * fix executor test. * rust fmt from master. * rust format. * rustfmt * fix * start host function driven versioning * update state-machine part * still need access to state version from runtime * state hash in mem: wrong * direction likely correct, but passing call to code exec for genesis init seem awkward. * state version serialize in runtime, wrong approach, just initialize it with no threshold for core api < 4 seems more proper. * stateversion from runtime version (core api >= 4). * update trie, fix tests * unused import * clean some TODOs * Require RuntimeVersionOf for executor * use RuntimeVersionOf to resolve genesis state version. * update runtime version test * fix state-machine tests * TODO * Use runtime version from storage wasm with fast sync. * rustfmt * fmt * fix test * revert useless changes. * clean some unused changes * fmt * removing useless trait function. * remove remaining reference to state_hash * fix some imports * Follow chain state version management. * trie update, fix and constant threshold for trie layouts. * update deps * Update to latest trie pr changes. * fix benches * Verify proof requires right layout. * update trie_root * Update trie deps to latest * Update to latest trie versioning * Removing patch * update lock * extrinsic for sc-service-test using layout v0. * Adding RuntimeVersionOf to CallExecutor works. * fmt * error when resolving version and no wasm in storage. * use existing utils to instantiate runtime code. * Patch to delay runtime switch. * Revert "Patch to delay runtime switch." This reverts commit d35f273b7d67b1b85a9e72973cab13c5c156c1d3. * useless closure * remove remaining state_hash variables. * Remove outdated comment * useless inner hash * fmt * fmt and opt-in feature to apply state change. * feature gate core version, use new test feature for node and test node * Use a 'State' api version instead of Core one. * fix merge of test function * use blake macro. * Fix state api (require declaring the api in runtime). * Opt out feature, fix macro for io to select a given version instead of latest. * run test nodes on new state. * fix * Apply review change (docs and error). * fmt * use explicit runtime_interface in doc test * fix ui test * fix doc test * fmt * use default for path and specname when resolving version. * small review related changes. * doc value size requirement. * rename old_state feature * Remove macro changes * feature rename * state version as host function parameter * remove flag for client api * fix tests * switch storage chain proof to V1 * host functions, pass by state version enum * use WrappedRuntimeCode * start * state_version in runtime version * rust fmt * Update storage proof of max size. * fix runtime version rpc test * right intent of convert from compat * fix doc test * fix doc test * split proof * decode without replay, and remove some reexports. * Decode with compatibility by default. * switch state_version to u8. And remove RuntimeVersionBasis. * test * use api when reading embedded version * fix decode with apis * extract core version instead * test fix * unused import * review changes. Co-authored-by: kianenigma --- Cargo.lock | 34 ++- bin/node-template/runtime/src/lib.rs | 1 + bin/node/bench/src/generator.rs | 5 +- bin/node/bench/src/trie.rs | 6 +- bin/node/executor/benches/bench.rs | 4 +- bin/node/executor/tests/common.rs | 2 +- bin/node/runtime/src/lib.rs | 1 + client/api/src/backend.rs | 9 +- client/api/src/call_executor.rs | 4 +- client/api/src/in_mem.rs | 15 +- client/block-builder/src/lib.rs | 1 + client/db/src/bench.rs | 13 +- client/db/src/lib.rs | 108 +++++--- client/db/src/storage_cache.rs | 22 +- client/executor/runtime-test/src/lib.rs | 1 + client/executor/src/integration_tests/mod.rs | 11 +- client/executor/src/wasm_runtime.rs | 88 ++++--- client/network/src/protocol/sync.rs | 6 +- client/rpc/src/state/tests.rs | 4 +- client/service/src/client/call_executor.rs | 16 +- client/service/src/client/client.rs | 64 ++++- client/service/src/client/genesis.rs | 6 +- client/service/test/src/client/mod.rs | 16 +- frame/benchmarking/src/lib.rs | 5 +- frame/executive/src/lib.rs | 29 ++- frame/session/src/historical/mod.rs | 4 +- frame/support/src/lib.rs | 10 +- frame/support/src/storage/child.rs | 7 +- frame/support/test/compile_pass/src/lib.rs | 1 + frame/system/src/lib.rs | 11 +- frame/system/src/mock.rs | 1 + frame/transaction-storage/src/benchmarking.rs | 116 +++++---- frame/transaction-storage/src/lib.rs | 3 +- .../api/proc-macro/src/impl_runtime_apis.rs | 7 + primitives/api/src/lib.rs | 45 +--- primitives/externalities/src/lib.rs | 10 +- primitives/io/src/lib.rs | 144 ++++++++++- primitives/runtime-interface/src/impls.rs | 4 + primitives/runtime/src/lib.rs | 1 + primitives/runtime/src/traits.rs | 22 +- primitives/state-machine/Cargo.toml | 4 +- primitives/state-machine/src/backend.rs | 18 +- primitives/state-machine/src/basic.rs | 30 ++- primitives/state-machine/src/ext.rs | 169 +++++++----- .../state-machine/src/in_memory_backend.rs | 65 +++-- primitives/state-machine/src/lib.rs | 159 +++++++++--- .../src/overlayed_changes/mod.rs | 16 +- .../state-machine/src/proving_backend.rs | 99 ++++--- primitives/state-machine/src/read_only.rs | 10 +- primitives/state-machine/src/testing.rs | 58 ++++- primitives/state-machine/src/trie_backend.rs | 157 ++++++++---- .../state-machine/src/trie_backend_essence.rs | 157 +++++++----- primitives/storage/src/lib.rs | 51 ++++ primitives/tasks/src/async_externalities.rs | 10 +- .../transaction-storage-proof/src/lib.rs | 2 +- primitives/trie/Cargo.toml | 8 +- primitives/trie/benches/bench.rs | 4 +- primitives/trie/src/lib.rs | 242 ++++++++++++------ primitives/trie/src/node_codec.rs | 114 +++++++-- primitives/trie/src/node_header.rs | 93 +++++-- primitives/trie/src/storage_proof.rs | 11 +- primitives/trie/src/trie_codec.rs | 6 +- primitives/trie/src/trie_stream.rs | 81 +++--- primitives/version/Cargo.toml | 1 + .../proc-macro/src/decl_runtime_version.rs | 24 +- primitives/version/src/lib.rs | 78 +++++- test-utils/client/src/client_ext.rs | 2 +- test-utils/client/src/lib.rs | 4 +- test-utils/runtime/Cargo.toml | 2 +- test-utils/runtime/client/src/lib.rs | 2 + test-utils/runtime/src/genesismap.rs | 2 + test-utils/runtime/src/lib.rs | 14 +- test-utils/runtime/src/system.rs | 10 +- .../cli/src/commands/execute_block.rs | 2 +- .../cli/src/commands/follow_chain.rs | 17 +- .../cli/src/commands/offchain_worker.rs | 2 +- .../cli/src/commands/on_runtime_upgrade.rs | 2 +- utils/frame/try-runtime/cli/src/lib.rs | 7 +- 78 files changed, 1811 insertions(+), 779 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 96146f6f8bec..c6dd25ffd74a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4179,6 +4179,17 @@ dependencies = [ "parity-util-mem", ] +[[package]] +name = "memory-db" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d505169b746dacf02f7d14d8c80b34edfd8212159c63d23c977739a0d960c626" +dependencies = [ + "hash-db", + "hashbrown 0.11.2", + "parity-util-mem", +] + [[package]] name = "memory_units" version = "0.3.0" @@ -9908,7 +9919,7 @@ dependencies = [ "criterion", "hash-db", "hex-literal", - "memory-db", + "memory-db 0.28.0", "parity-scale-codec", "scale-info", "sp-core", @@ -9929,6 +9940,7 @@ dependencies = [ "parity-wasm 0.42.2", "scale-info", "serde", + "sp-core-hashing-proc-macro", "sp-runtime", "sp-std", "sp-version-proc-macro", @@ -10201,7 +10213,7 @@ dependencies = [ "frame-system-rpc-runtime-api", "futures 0.3.16", "log 0.4.14", - "memory-db", + "memory-db 0.27.0", "pallet-babe", "pallet-timestamp", "parity-scale-codec", @@ -10840,14 +10852,14 @@ checksum = "a7f741b240f1a48843f9b8e0444fb55fb2a4ff67293b50a9179dfd5ea67f8d41" [[package]] name = "trie-bench" -version = "0.28.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4edd9bdf0c2e08fd77c0fb2608179cac7ebed997ae18f58d47a2d96425ff51f0" +checksum = "36ac46f6503d0fa976193db46f9dbb1d454e5dbde76495f1316f576c7f3f0e6b" dependencies = [ "criterion", "hash-db", "keccak-hasher", - "memory-db", + "memory-db 0.28.0", "parity-scale-codec", "trie-db", "trie-root", @@ -10856,9 +10868,9 @@ dependencies = [ [[package]] name = "trie-db" -version = "0.22.6" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9eac131e334e81b6b3be07399482042838adcd7957aa0010231d0813e39e02fa" +checksum = "e3ddae50680c12ef75bfbf58416ca6622fa43d879553f6cb2ed1a817346e1ffe" dependencies = [ "hash-db", "hashbrown 0.11.2", @@ -10869,9 +10881,9 @@ dependencies = [ [[package]] name = "trie-root" -version = "0.16.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "652931506d2c1244d7217a70b99f56718a7b4161b37f04e7cd868072a99f68cd" +checksum = "9a36c5ca3911ed3c9a5416ee6c679042064b93fc637ded67e25f92e68d783891" dependencies = [ "hash-db", ] @@ -10986,8 +10998,8 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f559b464de2e2bdabcac6a210d12e9b5a5973c251e102c44c585c71d51bd78e" dependencies = [ - "cfg-if 1.0.0", - "rand 0.8.4", + "cfg-if 0.1.10", + "rand 0.6.5", "static_assertions", ] diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index 5c277a1bb794..08c6c8fb8bcb 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -102,6 +102,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, + state_version: 1, }; /// This determines the average expected block time that we are targeting. diff --git a/bin/node/bench/src/generator.rs b/bin/node/bench/src/generator.rs index e3aa1192b5d1..d57142893f38 100644 --- a/bin/node/bench/src/generator.rs +++ b/bin/node/bench/src/generator.rs @@ -20,7 +20,7 @@ use std::{collections::HashMap, sync::Arc}; use kvdb::KeyValueDB; use node_primitives::Hash; -use sp_trie::{trie_types::TrieDBMut, TrieMut}; +use sp_trie::{trie_types::TrieDBMutV1, TrieMut}; use crate::simple_trie::SimpleTrie; @@ -43,8 +43,7 @@ pub fn generate_trie( ); let mut trie = SimpleTrie { db, overlay: &mut overlay }; { - let mut trie_db = TrieDBMut::new(&mut trie, &mut root); - + let mut trie_db = TrieDBMutV1::::new(&mut trie, &mut root); for (key, value) in key_values { trie_db.insert(&key, &value).expect("trie insertion failed"); } diff --git a/bin/node/bench/src/trie.rs b/bin/node/bench/src/trie.rs index a17e386ca879..374ed3568475 100644 --- a/bin/node/bench/src/trie.rs +++ b/bin/node/bench/src/trie.rs @@ -23,7 +23,7 @@ use kvdb::KeyValueDB; use lazy_static::lazy_static; use rand::Rng; use sp_state_machine::Backend as _; -use sp_trie::{trie_types::TrieDBMut, TrieMut as _}; +use sp_trie::{trie_types::TrieDBMutV1, TrieMut as _}; use std::{borrow::Cow, collections::HashMap, sync::Arc}; use node_primitives::Hash; @@ -286,8 +286,8 @@ impl core::Benchmark for TrieWriteBenchmark { let mut overlay = HashMap::new(); let mut trie = SimpleTrie { db: kvdb.clone(), overlay: &mut overlay }; - let mut trie_db_mut = - TrieDBMut::from_existing(&mut trie, &mut new_root).expect("Failed to create TrieDBMut"); + let mut trie_db_mut = TrieDBMutV1::from_existing(&mut trie, &mut new_root) + .expect("Failed to create TrieDBMut"); for (warmup_key, warmup_value) in self.warmup_keys.iter() { let value = trie_db_mut diff --git a/bin/node/executor/benches/bench.rs b/bin/node/executor/benches/bench.rs index aea37b68d55b..f1f950182f70 100644 --- a/bin/node/executor/benches/bench.rs +++ b/bin/node/executor/benches/bench.rs @@ -83,14 +83,14 @@ fn construct_block( parent_hash: Hash, extrinsics: Vec, ) -> (Vec, Hash) { - use sp_trie::{trie_types::Layout, TrieConfiguration}; + use sp_trie::{LayoutV0, TrieConfiguration}; // sign extrinsics. let extrinsics = extrinsics.into_iter().map(sign).collect::>(); // calculate the header fields that we can. let extrinsics_root = - Layout::::ordered_trie_root(extrinsics.iter().map(Encode::encode)) + LayoutV0::::ordered_trie_root(extrinsics.iter().map(Encode::encode)) .to_fixed_bytes() .into(); diff --git a/bin/node/executor/tests/common.rs b/bin/node/executor/tests/common.rs index 84b5728a1a84..8d21f086795a 100644 --- a/bin/node/executor/tests/common.rs +++ b/bin/node/executor/tests/common.rs @@ -142,7 +142,7 @@ pub fn construct_block( extrinsics: Vec, babe_slot: Slot, ) -> (Vec, Hash) { - use sp_trie::{trie_types::Layout, TrieConfiguration}; + use sp_trie::{LayoutV1 as Layout, TrieConfiguration}; // sign extrinsics. let extrinsics = extrinsics.into_iter().map(sign).collect::>(); diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index a79d8997f4ce..1a4dad1071e1 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -126,6 +126,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 2, + state_version: 1, }; /// The BABE epoch configuration at genesis. diff --git a/client/api/src/backend.rs b/client/api/src/backend.rs index f300e31f826c..76f2f569814f 100644 --- a/client/api/src/backend.rs +++ b/client/api/src/backend.rs @@ -29,7 +29,7 @@ use sp_core::offchain::OffchainStorage; use sp_runtime::{ generic::BlockId, traits::{Block as BlockT, HashFor, NumberFor}, - Justification, Justifications, Storage, + Justification, Justifications, StateVersion, Storage, }; use sp_state_machine::{ ChildStorageCollection, IndexOperation, OffchainChangesCollection, StorageCollection, @@ -166,10 +166,15 @@ pub trait BlockImportOperation { &mut self, storage: Storage, commit: bool, + state_version: StateVersion, ) -> sp_blockchain::Result; /// Inject storage data into the database replacing any existing data. - fn reset_storage(&mut self, storage: Storage) -> sp_blockchain::Result; + fn reset_storage( + &mut self, + storage: Storage, + state_version: StateVersion, + ) -> sp_blockchain::Result; /// Set storage changes. fn update_storage( diff --git a/client/api/src/call_executor.rs b/client/api/src/call_executor.rs index 22af495c0654..b1fd731ca088 100644 --- a/client/api/src/call_executor.rs +++ b/client/api/src/call_executor.rs @@ -19,7 +19,7 @@ //! A method call executor interface. use codec::{Decode, Encode}; -use sc_executor::RuntimeVersion; +use sc_executor::{RuntimeVersion, RuntimeVersionOf}; use sp_core::NativeOrEncoded; use sp_externalities::Extensions; use sp_runtime::{generic::BlockId, traits::Block as BlockT}; @@ -42,7 +42,7 @@ pub trait ExecutorProvider { } /// Method call executor. -pub trait CallExecutor { +pub trait CallExecutor: RuntimeVersionOf { /// Externalities error type. type Error: sp_state_machine::Error; diff --git a/client/api/src/in_mem.rs b/client/api/src/in_mem.rs index 39fe9e063d20..c9650bf6db74 100644 --- a/client/api/src/in_mem.rs +++ b/client/api/src/in_mem.rs @@ -26,7 +26,7 @@ use sp_core::{ use sp_runtime::{ generic::BlockId, traits::{Block as BlockT, HashFor, Header as HeaderT, NumberFor, Zero}, - Justification, Justifications, Storage, + Justification, Justifications, StateVersion, Storage, }; use sp_state_machine::{ Backend as StateBackend, ChildStorageCollection, InMemoryBackend, IndexOperation, @@ -506,6 +506,7 @@ where &mut self, storage: Storage, commit: bool, + state_version: StateVersion, ) -> sp_blockchain::Result { check_genesis_storage(&storage)?; @@ -519,6 +520,7 @@ where let (root, transaction) = self.old_state.full_storage_root( storage.top.iter().map(|(k, v)| (k.as_ref(), Some(v.as_ref()))), child_delta, + state_version, ); if commit { @@ -566,12 +568,17 @@ where &mut self, storage: Storage, commit: bool, + state_version: StateVersion, ) -> sp_blockchain::Result { - self.apply_storage(storage, commit) + self.apply_storage(storage, commit, state_version) } - fn reset_storage(&mut self, storage: Storage) -> sp_blockchain::Result { - self.apply_storage(storage, true) + fn reset_storage( + &mut self, + storage: Storage, + state_version: StateVersion, + ) -> sp_blockchain::Result { + self.apply_storage(storage, true, state_version) } fn insert_aux(&mut self, ops: I) -> sp_blockchain::Result<()> diff --git a/client/block-builder/src/lib.rs b/client/block-builder/src/lib.rs index 01afaca0cacf..c3e91fa05540 100644 --- a/client/block-builder/src/lib.rs +++ b/client/block-builder/src/lib.rs @@ -232,6 +232,7 @@ where header.extrinsics_root().clone(), HashFor::::ordered_trie_root( self.extrinsics.iter().map(Encode::encode).collect(), + sp_runtime::StateVersion::V0, ), ); diff --git a/client/db/src/bench.rs b/client/db/src/bench.rs index d46aca8e8ff7..cafafca9b635 100644 --- a/client/db/src/bench.rs +++ b/client/db/src/bench.rs @@ -34,7 +34,7 @@ use sp_core::{ }; use sp_runtime::{ traits::{Block as BlockT, HashFor}, - Storage, + StateVersion, Storage, }; use sp_state_machine::{ backend::Backend as StateBackend, ChildStorageCollection, DBValue, ProofRecorder, @@ -73,6 +73,7 @@ impl sp_state_machine::Storage> for StorageDb { root: Cell, @@ -105,9 +106,10 @@ impl BenchmarkingState { record_proof: bool, enable_tracking: bool, ) -> Result { + let state_version = sp_runtime::StateVersion::default(); let mut root = B::Hash::default(); let mut mdb = MemoryDB::>::default(); - sp_state_machine::TrieDBMut::>::new(&mut mdb, &mut root); + sp_state_machine::TrieDBMutV1::>::new(&mut mdb, &mut root); let mut state = BenchmarkingState { state: RefCell::new(None), @@ -138,6 +140,7 @@ impl BenchmarkingState { state.state.borrow_mut().as_mut().unwrap().full_storage_root( genesis.top.iter().map(|(k, v)| (k.as_ref(), Some(v.as_ref()))), child_delta, + state_version, ); state.genesis = transaction.clone().drain(); state.genesis_root = root.clone(); @@ -415,6 +418,7 @@ impl StateBackend> for BenchmarkingState { fn storage_root<'a>( &self, delta: impl Iterator)>, + state_version: StateVersion, ) -> (B::Hash, Self::Transaction) where B::Hash: Ord, @@ -422,13 +426,14 @@ impl StateBackend> for BenchmarkingState { self.state .borrow() .as_ref() - .map_or(Default::default(), |s| s.storage_root(delta)) + .map_or(Default::default(), |s| s.storage_root(delta, state_version)) } fn child_storage_root<'a>( &self, child_info: &ChildInfo, delta: impl Iterator)>, + state_version: StateVersion, ) -> (B::Hash, bool, Self::Transaction) where B::Hash: Ord, @@ -436,7 +441,7 @@ impl StateBackend> for BenchmarkingState { self.state .borrow() .as_ref() - .map_or(Default::default(), |s| s.child_storage_root(child_info, delta)) + .map_or(Default::default(), |s| s.child_storage_root(child_info, delta, state_version)) } fn pairs(&self) -> Vec<(Vec, Vec)> { diff --git a/client/db/src/lib.rs b/client/db/src/lib.rs index 7d46b63da5bb..137c26fb8218 100644 --- a/client/db/src/lib.rs +++ b/client/db/src/lib.rs @@ -82,7 +82,7 @@ use sp_runtime::{ Block as BlockT, Hash, HashFor, Header as HeaderT, NumberFor, One, SaturatedConversion, Zero, }, - Justification, Justifications, Storage, + Justification, Justifications, StateVersion, Storage, }; use sp_state_machine::{ backend::Backend as StateBackend, ChildStorageCollection, DBValue, IndexOperation, @@ -235,22 +235,24 @@ impl StateBackend> for RefTrackingState { fn storage_root<'a>( &self, delta: impl Iterator)>, + state_version: StateVersion, ) -> (B::Hash, Self::Transaction) where B::Hash: Ord, { - self.state.storage_root(delta) + self.state.storage_root(delta, state_version) } fn child_storage_root<'a>( &self, child_info: &ChildInfo, delta: impl Iterator)>, + state_version: StateVersion, ) -> (B::Hash, bool, Self::Transaction) where B::Hash: Ord, { - self.state.child_storage_root(child_info, delta) + self.state.child_storage_root(child_info, delta, state_version) } fn pairs(&self) -> Vec<(Vec, Vec)> { @@ -760,7 +762,11 @@ impl BlockImportOperation { } } - fn apply_new_state(&mut self, storage: Storage) -> ClientResult { + fn apply_new_state( + &mut self, + storage: Storage, + state_version: StateVersion, + ) -> ClientResult { if storage.top.keys().any(|k| well_known_keys::is_child_storage_key(&k)) { return Err(sp_blockchain::Error::InvalidState.into()) } @@ -775,6 +781,7 @@ impl BlockImportOperation { let (root, transaction) = self.old_state.full_storage_root( storage.top.iter().map(|(k, v)| (&k[..], Some(&v[..]))), child_delta, + state_version, ); self.db_updates = transaction; @@ -814,14 +821,23 @@ impl sc_client_api::backend::BlockImportOperation Ok(()) } - fn reset_storage(&mut self, storage: Storage) -> ClientResult { - let root = self.apply_new_state(storage)?; + fn reset_storage( + &mut self, + storage: Storage, + state_version: StateVersion, + ) -> ClientResult { + let root = self.apply_new_state(storage, state_version)?; self.commit_state = true; Ok(root) } - fn set_genesis_state(&mut self, storage: Storage, commit: bool) -> ClientResult { - let root = self.apply_new_state(storage)?; + fn set_genesis_state( + &mut self, + storage: Storage, + commit: bool, + state_version: StateVersion, + ) -> ClientResult { + let root = self.apply_new_state(storage, state_version)?; self.commit_state = commit; Ok(root) } @@ -924,7 +940,8 @@ impl EmptyStorage { pub fn new() -> Self { let mut root = Block::Hash::default(); let mut mdb = MemoryDB::>::default(); - sp_state_machine::TrieDBMut::>::new(&mut mdb, &mut root); + // both triedbmut are the same on empty storage. + sp_state_machine::TrieDBMutV1::>::new(&mut mdb, &mut root); EmptyStorage(root) } } @@ -2262,7 +2279,7 @@ pub(crate) mod tests { use sp_runtime::{ testing::{Block as RawBlock, ExtrinsicWrapper, Header}, traits::{BlakeTwo256, Hash}, - ConsensusEngineId, + ConsensusEngineId, StateVersion, }; const CONS0_ENGINE_ID: ConsensusEngineId = *b"CON0"; @@ -2295,7 +2312,7 @@ pub(crate) mod tests { let header = Header { number, parent_hash, - state_root: BlakeTwo256::trie_root(Vec::new()), + state_root: BlakeTwo256::trie_root(Vec::new(), StateVersion::V1), digest, extrinsics_root, }; @@ -2375,6 +2392,10 @@ pub(crate) mod tests { #[test] fn set_state_data() { + set_state_data_inner(StateVersion::V0); + set_state_data_inner(StateVersion::V1); + } + fn set_state_data_inner(state_version: StateVersion) { let db = Backend::::new_test(2, 0); let hash = { let mut op = db.begin_operation().unwrap(); @@ -2390,15 +2411,18 @@ pub(crate) mod tests { header.state_root = op .old_state - .storage_root(storage.iter().map(|(x, y)| (&x[..], Some(&y[..])))) + .storage_root(storage.iter().map(|(x, y)| (&x[..], Some(&y[..]))), state_version) .0 .into(); let hash = header.hash(); - op.reset_storage(Storage { - top: storage.into_iter().collect(), - children_default: Default::default(), - }) + op.reset_storage( + Storage { + top: storage.into_iter().collect(), + children_default: Default::default(), + }, + state_version, + ) .unwrap(); op.set_block_data(header.clone(), Some(vec![]), None, None, NewBlockState::Best) .unwrap(); @@ -2427,9 +2451,10 @@ pub(crate) mod tests { let storage = vec![(vec![1, 3, 5], None), (vec![5, 5, 5], Some(vec![4, 5, 6]))]; - let (root, overlay) = op - .old_state - .storage_root(storage.iter().map(|(k, v)| (&k[..], v.as_ref().map(|v| &v[..])))); + let (root, overlay) = op.old_state.storage_root( + storage.iter().map(|(k, v)| (&k[..], v.as_ref().map(|v| &v[..]))), + state_version, + ); op.update_db_storage(overlay).unwrap(); header.state_root = root.into(); @@ -2450,6 +2475,7 @@ pub(crate) mod tests { #[test] fn delete_only_when_negative_rc() { sp_tracing::try_init_simple(); + let state_version = StateVersion::default(); let key; let backend = Backend::::new_test(1, 0); @@ -2466,13 +2492,14 @@ pub(crate) mod tests { extrinsics_root: Default::default(), }; - header.state_root = op.old_state.storage_root(std::iter::empty()).0.into(); + header.state_root = + op.old_state.storage_root(std::iter::empty(), state_version).0.into(); let hash = header.hash(); - op.reset_storage(Storage { - top: Default::default(), - children_default: Default::default(), - }) + op.reset_storage( + Storage { top: Default::default(), children_default: Default::default() }, + state_version, + ) .unwrap(); key = op.db_updates.insert(EMPTY_PREFIX, b"hello"); @@ -2506,7 +2533,7 @@ pub(crate) mod tests { header.state_root = op .old_state - .storage_root(storage.iter().cloned().map(|(x, y)| (x, Some(y)))) + .storage_root(storage.iter().cloned().map(|(x, y)| (x, Some(y))), state_version) .0 .into(); let hash = header.hash(); @@ -2543,7 +2570,7 @@ pub(crate) mod tests { header.state_root = op .old_state - .storage_root(storage.iter().cloned().map(|(x, y)| (x, Some(y)))) + .storage_root(storage.iter().cloned().map(|(x, y)| (x, Some(y))), state_version) .0 .into(); let hash = header.hash(); @@ -2577,7 +2604,7 @@ pub(crate) mod tests { header.state_root = op .old_state - .storage_root(storage.iter().cloned().map(|(x, y)| (x, Some(y)))) + .storage_root(storage.iter().cloned().map(|(x, y)| (x, Some(y))), state_version) .0 .into(); @@ -2912,6 +2939,7 @@ pub(crate) mod tests { #[test] fn storage_hash_is_cached_correctly() { + let state_version = StateVersion::default(); let backend = Backend::::new_test(10, 10); let hash0 = { @@ -2931,15 +2959,18 @@ pub(crate) mod tests { header.state_root = op .old_state - .storage_root(storage.iter().map(|(x, y)| (&x[..], Some(&y[..])))) + .storage_root(storage.iter().map(|(x, y)| (&x[..], Some(&y[..]))), state_version) .0 .into(); let hash = header.hash(); - op.reset_storage(Storage { - top: storage.into_iter().collect(), - children_default: Default::default(), - }) + op.reset_storage( + Storage { + top: storage.into_iter().collect(), + children_default: Default::default(), + }, + state_version, + ) .unwrap(); op.set_block_data(header.clone(), Some(vec![]), None, None, NewBlockState::Best) .unwrap(); @@ -2968,9 +2999,10 @@ pub(crate) mod tests { let storage = vec![(b"test".to_vec(), Some(b"test2".to_vec()))]; - let (root, overlay) = op - .old_state - .storage_root(storage.iter().map(|(k, v)| (&k[..], v.as_ref().map(|v| &v[..])))); + let (root, overlay) = op.old_state.storage_root( + storage.iter().map(|(k, v)| (&k[..], v.as_ref().map(|v| &v[..]))), + state_version, + ); op.update_db_storage(overlay).unwrap(); header.state_root = root.into(); let hash = header.hash(); @@ -3212,7 +3244,7 @@ pub(crate) mod tests { let header = Header { number: 1, parent_hash: block0, - state_root: BlakeTwo256::trie_root(Vec::new()), + state_root: BlakeTwo256::trie_root(Vec::new(), StateVersion::V1), digest: Default::default(), extrinsics_root: Default::default(), }; @@ -3224,7 +3256,7 @@ pub(crate) mod tests { let header = Header { number: 2, parent_hash: block1, - state_root: BlakeTwo256::trie_root(Vec::new()), + state_root: BlakeTwo256::trie_root(Vec::new(), StateVersion::V1), digest: Default::default(), extrinsics_root: Default::default(), }; @@ -3247,7 +3279,7 @@ pub(crate) mod tests { let header = Header { number: 1, parent_hash: block0, - state_root: BlakeTwo256::trie_root(Vec::new()), + state_root: BlakeTwo256::trie_root(Vec::new(), StateVersion::V1), digest: Default::default(), extrinsics_root: Default::default(), }; diff --git a/client/db/src/storage_cache.rs b/client/db/src/storage_cache.rs index 5fef0e5b12d0..579703ea9db8 100644 --- a/client/db/src/storage_cache.rs +++ b/client/db/src/storage_cache.rs @@ -26,7 +26,10 @@ use linked_hash_map::{Entry, LinkedHashMap}; use log::trace; use parking_lot::{RwLock, RwLockUpgradableReadGuard}; use sp_core::{hexdisplay::HexDisplay, storage::ChildInfo}; -use sp_runtime::traits::{Block as BlockT, HashFor, Header, NumberFor}; +use sp_runtime::{ + traits::{Block as BlockT, HashFor, Header, NumberFor}, + StateVersion, +}; use sp_state_machine::{ backend::Backend as StateBackend, ChildStorageCollection, StorageCollection, StorageKey, StorageValue, TrieBackend, @@ -673,22 +676,24 @@ impl>, B: BlockT> StateBackend> for Cachin fn storage_root<'a>( &self, delta: impl Iterator)>, + state_version: StateVersion, ) -> (B::Hash, Self::Transaction) where B::Hash: Ord, { - self.state.storage_root(delta) + self.state.storage_root(delta, state_version) } fn child_storage_root<'a>( &self, child_info: &ChildInfo, delta: impl Iterator)>, + state_version: StateVersion, ) -> (B::Hash, bool, Self::Transaction) where B::Hash: Ord, { - self.state.child_storage_root(child_info, delta) + self.state.child_storage_root(child_info, delta, state_version) } fn pairs(&self) -> Vec<(Vec, Vec)> { @@ -871,22 +876,24 @@ impl>, B: BlockT> StateBackend> fn storage_root<'a>( &self, delta: impl Iterator)>, + state_version: StateVersion, ) -> (B::Hash, Self::Transaction) where B::Hash: Ord, { - self.caching_state().storage_root(delta) + self.caching_state().storage_root(delta, state_version) } fn child_storage_root<'a>( &self, child_info: &ChildInfo, delta: impl Iterator)>, + state_version: StateVersion, ) -> (B::Hash, bool, Self::Transaction) where B::Hash: Ord, { - self.caching_state().child_storage_root(child_info, delta) + self.caching_state().child_storage_root(child_info, delta, state_version) } fn pairs(&self) -> Vec<(Vec, Vec)> { @@ -1182,7 +1189,10 @@ mod tests { let shared = new_shared_cache::(256 * 1024, (0, 1)); let mut backend = InMemoryBackend::::default(); - backend.insert(std::iter::once((None, vec![(key.clone(), Some(vec![1]))]))); + backend.insert( + std::iter::once((None, vec![(key.clone(), Some(vec![1]))])), + Default::default(), + ); let mut s = CachingState::new(backend.clone(), shared.clone(), Some(root_parent)); s.cache.sync_cache( diff --git a/client/executor/runtime-test/src/lib.rs b/client/executor/runtime-test/src/lib.rs index 01e46ab94635..0655160c1ab7 100644 --- a/client/executor/runtime-test/src/lib.rs +++ b/client/executor/runtime-test/src/lib.rs @@ -180,6 +180,7 @@ sp_core::wasm_export_functions! { b"one"[..].into(), b"two"[..].into(), ], + sp_core::storage::StateVersion::V1, ).as_ref().to_vec() } diff --git a/client/executor/src/integration_tests/mod.rs b/client/executor/src/integration_tests/mod.rs index 89648e9bac69..c480ad74ade6 100644 --- a/client/executor/src/integration_tests/mod.rs +++ b/client/executor/src/integration_tests/mod.rs @@ -33,7 +33,7 @@ use sp_core::{ }; use sp_runtime::traits::BlakeTwo256; use sp_state_machine::TestExternalities as CoreTestExternalities; -use sp_trie::{trie_types::Layout, TrieConfiguration}; +use sp_trie::{LayoutV1 as Layout, TrieConfiguration}; use std::sync::Arc; use tracing_subscriber::layer::SubscriberExt; @@ -215,21 +215,22 @@ fn panicking_should_work(wasm_method: WasmExecutionMethod) { test_wasm_execution!(storage_should_work); fn storage_should_work(wasm_method: WasmExecutionMethod) { let mut ext = TestExternalities::default(); + // Test value must be bigger than 32 bytes + // to test the trie versioning. + let value = vec![7u8; 60]; { let mut ext = ext.ext(); ext.set_storage(b"foo".to_vec(), b"bar".to_vec()); - let output = - call_in_wasm("test_data_in", &b"Hello world".to_vec().encode(), wasm_method, &mut ext) - .unwrap(); + let output = call_in_wasm("test_data_in", &value.encode(), wasm_method, &mut ext).unwrap(); assert_eq!(output, b"all ok!".to_vec().encode()); } let expected = TestExternalities::new(sp_core::storage::Storage { top: map![ - b"input".to_vec() => b"Hello world".to_vec(), + b"input".to_vec() => value, b"foo".to_vec() => b"bar".to_vec(), b"baz".to_vec() => b"bar".to_vec() ], diff --git a/client/executor/src/wasm_runtime.rs b/client/executor/src/wasm_runtime.rs index cebfc7b01b8d..94c4f431ef45 100644 --- a/client/executor/src/wasm_runtime.rs +++ b/client/executor/src/wasm_runtime.rs @@ -334,22 +334,11 @@ where } fn decode_version(mut version: &[u8]) -> Result { - let v: RuntimeVersion = sp_api::OldRuntimeVersion::decode(&mut &version[..]) - .map_err(|_| { - WasmError::Instantiation( - "failed to decode \"Core_version\" result using old runtime version".into(), - ) - })? - .into(); - - let core_api_id = sp_core_hashing_proc_macro::blake2b_64!(b"Core"); - if v.has_api_with(&core_api_id, |v| v >= 3) { - sp_api::RuntimeVersion::decode(&mut version).map_err(|_| { - WasmError::Instantiation("failed to decode \"Core_version\" result".into()) - }) - } else { - Ok(v) - } + Decode::decode(&mut version).map_err(|_| { + WasmError::Instantiation( + "failed to decode \"Core_version\" result using old runtime version".into(), + ) + }) } fn decode_runtime_apis(apis: &[u8]) -> Result, WasmError> { @@ -373,17 +362,25 @@ fn decode_runtime_apis(apis: &[u8]) -> Result, WasmError> { /// sections, `Err` will be returned. pub fn read_embedded_version(blob: &RuntimeBlob) -> Result, WasmError> { if let Some(mut version_section) = blob.custom_section_contents("runtime_version") { - // We do not use `decode_version` here because the runtime_version section is not supposed - // to ever contain a legacy version. Apart from that `decode_version` relies on presence - // of a special API in the `apis` field to treat the input as a non-legacy version. However - // the structure found in the `runtime_version` always contain an empty `apis` field. - // Therefore the version read will be mistakenly treated as an legacy one. - let mut decoded_version = sp_api::RuntimeVersion::decode(&mut version_section) - .map_err(|_| WasmError::Instantiation("failed to decode version section".into()))?; - - // Don't stop on this and check if there is a special section that encodes all runtime APIs. - if let Some(apis_section) = blob.custom_section_contents("runtime_apis") { - decoded_version.apis = decode_runtime_apis(apis_section)?.into(); + let apis = blob + .custom_section_contents("runtime_apis") + .map(decode_runtime_apis) + .transpose()? + .map(Into::into); + + let core_version = apis.as_ref().and_then(|apis| sp_version::core_version_from_apis(apis)); + // We do not use `RuntimeVersion::decode` here because that `decode_version` relies on + // presence of a special API in the `apis` field to treat the input as a non-legacy version. + // However the structure found in the `runtime_version` always contain an empty `apis` + // field. Therefore the version read will be mistakenly treated as an legacy one. + let mut decoded_version = sp_version::RuntimeVersion::decode_with_version_hint( + &mut version_section, + core_version, + ) + .map_err(|_| WasmError::Instantiation("failed to decode version section".into()))?; + + if let Some(apis) = apis { + decoded_version.apis = apis; } Ok(Some(decoded_version)) @@ -455,9 +452,20 @@ mod tests { use super::*; use codec::Encode; use sp_api::{Core, RuntimeApiInfo}; + use sp_runtime::RuntimeString; use sp_wasm_interface::HostFunctions; use substrate_test_runtime::Block; + #[derive(Encode)] + pub struct OldRuntimeVersion { + pub spec_name: RuntimeString, + pub impl_name: RuntimeString, + pub authoring_version: u32, + pub spec_version: u32, + pub impl_version: u32, + pub apis: sp_version::ApisVec, + } + #[test] fn host_functions_are_equal() { let host_functions = sp_io::SubstrateHostFunctions::host_functions(); @@ -468,7 +476,7 @@ mod tests { #[test] fn old_runtime_version_decodes() { - let old_runtime_version = sp_api::OldRuntimeVersion { + let old_runtime_version = OldRuntimeVersion { spec_name: "test".into(), impl_name: "test".into(), authoring_version: 1, @@ -479,11 +487,12 @@ mod tests { let version = decode_version(&old_runtime_version.encode()).unwrap(); assert_eq!(1, version.transaction_version); + assert_eq!(0, version.state_version); } #[test] fn old_runtime_version_decodes_fails_with_version_3() { - let old_runtime_version = sp_api::OldRuntimeVersion { + let old_runtime_version = OldRuntimeVersion { spec_name: "test".into(), impl_name: "test".into(), authoring_version: 1, @@ -505,10 +514,27 @@ mod tests { impl_version: 1, apis: sp_api::create_apis_vec!([(>::ID, 3)]), transaction_version: 3, + state_version: 4, + }; + + let version = decode_version(&old_runtime_version.encode()).unwrap(); + assert_eq!(3, version.transaction_version); + assert_eq!(0, version.state_version); + + let old_runtime_version = sp_api::RuntimeVersion { + spec_name: "test".into(), + impl_name: "test".into(), + authoring_version: 1, + spec_version: 1, + impl_version: 1, + apis: sp_api::create_apis_vec!([(>::ID, 4)]), + transaction_version: 3, + state_version: 4, }; let version = decode_version(&old_runtime_version.encode()).unwrap(); assert_eq!(3, version.transaction_version); + assert_eq!(4, version.state_version); } #[test] @@ -518,15 +544,15 @@ mod tests { sp_maybe_compressed_blob::CODE_BLOB_BOMB_LIMIT, ) .expect("Decompressing works"); - let runtime_version = RuntimeVersion { spec_name: "test_replace".into(), impl_name: "test_replace".into(), authoring_version: 100, spec_version: 100, impl_version: 100, - apis: sp_api::create_apis_vec!([(>::ID, 3)]), + apis: sp_api::create_apis_vec!([(>::ID, 4)]), transaction_version: 100, + state_version: 1, }; let embedded = sp_version::embed::embed_runtime_version(&wasm, runtime_version.clone()) diff --git a/client/network/src/protocol/sync.rs b/client/network/src/protocol/sync.rs index 37646875e3b1..a84f5131242e 100644 --- a/client/network/src/protocol/sync.rs +++ b/client/network/src/protocol/sync.rs @@ -2539,8 +2539,10 @@ fn validate_blocks( } if let (Some(header), Some(body)) = (&b.header, &b.body) { let expected = *header.extrinsics_root(); - let got = - HashFor::::ordered_trie_root(body.iter().map(Encode::encode).collect()); + let got = HashFor::::ordered_trie_root( + body.iter().map(Encode::encode).collect(), + sp_runtime::StateVersion::V0, + ); if expected != got { debug!( target:"sync", diff --git a/client/rpc/src/state/tests.rs b/client/rpc/src/state/tests.rs index d360701c88b2..12e1c449d3bd 100644 --- a/client/rpc/src/state/tests.rs +++ b/client/rpc/src/state/tests.rs @@ -526,11 +526,11 @@ fn should_return_runtime_version() { ); let result = "{\"specName\":\"test\",\"implName\":\"parity-test\",\"authoringVersion\":1,\ - \"specVersion\":2,\"implVersion\":2,\"apis\":[[\"0xdf6acb689907609b\",3],\ + \"specVersion\":2,\"implVersion\":2,\"apis\":[[\"0xdf6acb689907609b\",4],\ [\"0x37e397fc7c91f5e4\",1],[\"0xd2bc9897eed08f15\",3],[\"0x40fe3ad401f8959a\",5],\ [\"0xc6e9a76309f39b09\",1],[\"0xdd718d5cc53262d4\",1],[\"0xcbca25e39f142387\",2],\ [\"0xf78b278be53f454c\",2],[\"0xab3c0572291feb8b\",1],[\"0xbc9d89904f5b923f\",1]],\ - \"transactionVersion\":1}"; + \"transactionVersion\":1,\"stateVersion\":1}"; let runtime_version = executor::block_on(api.runtime_version(None.into())).unwrap(); let serialized = serde_json::to_string(&runtime_version).unwrap(); diff --git a/client/service/src/client/call_executor.rs b/client/service/src/client/call_executor.rs index 9f56424daf2f..2acbbb75dcb1 100644 --- a/client/service/src/client/call_executor.rs +++ b/client/service/src/client/call_executor.rs @@ -90,7 +90,7 @@ where Block: BlockT, B: backend::Backend, { - let spec = self.runtime_version(id)?; + let spec = CallExecutor::runtime_version(self, id)?; let code = if let Some(d) = self .wasm_override .as_ref() @@ -321,6 +321,20 @@ where } } +impl RuntimeVersionOf for LocalCallExecutor +where + E: RuntimeVersionOf, + Block: BlockT, +{ + fn runtime_version( + &self, + ext: &mut dyn sp_externalities::Externalities, + runtime_code: &sp_core::traits::RuntimeCode, + ) -> Result { + RuntimeVersionOf::runtime_version(&self.executor, ext, runtime_code) + } +} + impl sp_version::GetRuntimeVersionAt for LocalCallExecutor where B: backend::Backend, diff --git a/client/service/src/client/client.rs b/client/service/src/client/client.rs index 833d8b7bc225..1f76fe017ae0 100644 --- a/client/service/src/client/client.rs +++ b/client/service/src/client/client.rs @@ -45,7 +45,7 @@ use sc_client_api::{ use sc_consensus::{ BlockCheckParams, BlockImportParams, ForkChoiceStrategy, ImportResult, StateAction, }; -use sc_executor::RuntimeVersion; +use sc_executor::{RuntimeVersion, RuntimeVersionOf}; use sc_telemetry::{telemetry, TelemetryHandle, SUBSTRATE_INFO}; use sp_api::{ ApiExt, ApiRef, CallApiAt, CallApiAtParams, ConstructRuntimeApi, Core as CoreApi, @@ -60,8 +60,8 @@ use sp_consensus::{BlockOrigin, BlockStatus, Error as ConsensusError}; use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedSender}; use sp_core::{ storage::{ - well_known_keys, ChildInfo, ChildType, PrefixedStorageKey, StorageChild, StorageData, - StorageKey, + well_known_keys, ChildInfo, ChildType, PrefixedStorageKey, Storage, StorageChild, + StorageData, StorageKey, }, NativeOrEncoded, }; @@ -72,7 +72,7 @@ use sp_runtime::{ traits::{ Block as BlockT, HashFor, Header as HeaderT, NumberFor, One, SaturatedConversion, Zero, }, - BuildStorage, Digest, Justification, Justifications, + BuildStorage, Digest, Justification, Justifications, StateVersion, }; use sp_state_machine::{ prove_child_read, prove_range_read_with_child_with_size, prove_read, @@ -81,7 +81,7 @@ use sp_state_machine::{ }; use sp_trie::{CompactProof, StorageProof}; use std::{ - collections::{HashMap, HashSet}, + collections::{hash_map::DefaultHasher, HashMap, HashSet}, marker::PhantomData, panic::UnwindSafe, path::PathBuf, @@ -93,7 +93,6 @@ use std::{ use { super::call_executor::LocalCallExecutor, sc_client_api::in_mem, - sc_executor::RuntimeVersionOf, sp_core::traits::{CodeExecutor, SpawnNamed}, }; @@ -334,8 +333,11 @@ where if info.finalized_state.is_none() { let genesis_storage = build_genesis_storage.build_storage().map_err(sp_blockchain::Error::Storage)?; + let genesis_state_version = + Self::resolve_state_version_from_wasm(&genesis_storage, &executor)?; let mut op = backend.begin_operation()?; - let state_root = op.set_genesis_state(genesis_storage, !config.no_genesis)?; + let state_root = + op.set_genesis_state(genesis_storage, !config.no_genesis, genesis_state_version)?; let genesis_block = genesis::construct_genesis_block::(state_root.into()); info!( "🔨 Initializing Genesis block/state (state: {}, header-hash: {})", @@ -403,7 +405,7 @@ where /// Get the RuntimeVersion at a given block. pub fn runtime_version_at(&self, id: &BlockId) -> sp_blockchain::Result { - self.executor.runtime_version(id) + CallExecutor::runtime_version(&self.executor, id) } /// Apply a checked and validated block to an operation. If a justification is provided @@ -606,7 +608,11 @@ where } } - let state_root = operation.op.reset_storage(storage)?; + // This is use by fast sync for runtime version to be resolvable from + // changes. + let state_version = + Self::resolve_state_version_from_wasm(&storage, &self.executor)?; + let state_root = operation.op.reset_storage(storage, state_version)?; if state_root != *import_headers.post().state_root() { // State root mismatch when importing state. This should not happen in // safe fast sync mode, but may happen in unsafe mode. @@ -1041,6 +1047,35 @@ where trace!("Collected {} uncles", uncles.len()); Ok(uncles) } + + fn resolve_state_version_from_wasm( + storage: &Storage, + executor: &E, + ) -> sp_blockchain::Result { + if let Some(wasm) = storage.top.get(well_known_keys::CODE) { + let mut ext = sp_state_machine::BasicExternalities::new_empty(); // just to read runtime version. + + let code_fetcher = sp_core::traits::WrappedRuntimeCode(wasm.as_slice().into()); + let runtime_code = sp_core::traits::RuntimeCode { + code_fetcher: &code_fetcher, + heap_pages: None, + hash: { + use std::hash::{Hash, Hasher}; + let mut state = DefaultHasher::new(); + wasm.hash(&mut state); + state.finish().to_le_bytes().to_vec() + }, + }; + let runtime_version = + RuntimeVersionOf::runtime_version(executor, &mut ext, &runtime_code) + .map_err(|e| sp_blockchain::Error::VersionInvalid(format!("{:?}", e)))?; + Ok(runtime_version.state_version()) + } else { + Err(sp_blockchain::Error::VersionInvalid( + "Runtime missing from initial storage, could not read state version.".to_string(), + )) + } + } } impl UsageProvider for Client @@ -1095,12 +1130,14 @@ where size_limit: usize, ) -> sp_blockchain::Result<(CompactProof, u32)> { let state = self.state_at(id)?; - let root = state.storage_root(std::iter::empty()).0; + // this is a read proof, using version V0 or V1 is equivalent. + let root = state.storage_root(std::iter::empty(), StateVersion::V0).0; let (proof, count) = prove_range_read_with_child_with_size::<_, HashFor>( state, size_limit, start_key, )?; - let proof = sp_trie::encode_compact::>>(proof, root) + // This is read proof only, we can use either LayoutV0 or LayoutV1. + let proof = sp_trie::encode_compact::>>(proof, root) .map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))?; Ok((proof, count)) } @@ -1225,7 +1262,8 @@ where start_key: &[Vec], ) -> sp_blockchain::Result<(KeyValueStates, usize)> { let mut db = sp_state_machine::MemoryDB::>::new(&[]); - let _ = sp_trie::decode_compact::>, _, _>( + // Compact encoding + let _ = sp_trie::decode_compact::>, _, _>( &mut db, proof.iter_compact_encoded_nodes(), Some(&root), @@ -1594,7 +1632,7 @@ where } fn runtime_version_at(&self, at: &BlockId) -> Result { - self.runtime_version_at(at).map_err(Into::into) + CallExecutor::runtime_version(&self.executor, at).map_err(Into::into) } } diff --git a/client/service/src/client/genesis.rs b/client/service/src/client/genesis.rs index e764e8e24f10..b48ca2464b54 100644 --- a/client/service/src/client/genesis.rs +++ b/client/service/src/client/genesis.rs @@ -22,8 +22,10 @@ use sp_runtime::traits::{Block as BlockT, Hash as HashT, Header as HeaderT, Zero /// Create a genesis block, given the initial storage. pub fn construct_genesis_block(state_root: Block::Hash) -> Block { - let extrinsics_root = - <<::Header as HeaderT>::Hashing as HashT>::trie_root(Vec::new()); + let extrinsics_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root( + Vec::new(), + sp_runtime::StateVersion::V0, + ); Block::new( <::Header as HeaderT>::new( diff --git a/client/service/test/src/client/mod.rs b/client/service/test/src/client/mod.rs index 286d819a6ce5..cd4ce132b663 100644 --- a/client/service/test/src/client/mod.rs +++ b/client/service/test/src/client/mod.rs @@ -34,13 +34,13 @@ use sp_core::{testing::TaskExecutor, H256}; use sp_runtime::{ generic::BlockId, traits::{BlakeTwo256, Block as BlockT, Header as HeaderT}, - ConsensusEngineId, Justifications, + ConsensusEngineId, Justifications, StateVersion, }; use sp_state_machine::{ backend::Backend as _, ExecutionStrategy, InMemoryBackend, OverlayedChanges, StateMachine, }; use sp_storage::{ChildInfo, StorageKey}; -use sp_trie::{trie_types::Layout, TrieConfiguration}; +use sp_trie::{LayoutV0, TrieConfiguration}; use std::{collections::HashSet, sync::Arc}; use substrate_test_runtime::TestAPI; use substrate_test_runtime_client::{ @@ -90,7 +90,7 @@ fn construct_block( let transactions = txs.into_iter().map(|tx| tx.into_signed_tx()).collect::>(); let iter = transactions.iter().map(Encode::encode); - let extrinsics_root = Layout::::ordered_trie_root(iter).into(); + let extrinsics_root = LayoutV0::::ordered_trie_root(iter).into(); let mut header = Header { parent_hash, @@ -177,7 +177,7 @@ fn construct_genesis_should_work_with_native() { .genesis_map(); let genesis_hash = insert_genesis_block(&mut storage); - let backend = InMemoryBackend::from(storage); + let backend = InMemoryBackend::from((storage, StateVersion::default())); let (b1data, _b1hash) = block1(genesis_hash, &backend); let backend_runtime_code = sp_state_machine::backend::BackendRuntimeCode::new(&backend); let runtime_code = backend_runtime_code.runtime_code().expect("Code is part of the backend"); @@ -210,7 +210,7 @@ fn construct_genesis_should_work_with_wasm() { .genesis_map(); let genesis_hash = insert_genesis_block(&mut storage); - let backend = InMemoryBackend::from(storage); + let backend = InMemoryBackend::from((storage, StateVersion::default())); let (b1data, _b1hash) = block1(genesis_hash, &backend); let backend_runtime_code = sp_state_machine::backend::BackendRuntimeCode::new(&backend); let runtime_code = backend_runtime_code.runtime_code().expect("Code is part of the backend"); @@ -243,7 +243,7 @@ fn construct_genesis_with_bad_transaction_should_panic() { .genesis_map(); let genesis_hash = insert_genesis_block(&mut storage); - let backend = InMemoryBackend::from(storage); + let backend = InMemoryBackend::from((storage, StateVersion::default())); let (b1data, _b1hash) = block1(genesis_hash, &backend); let backend_runtime_code = sp_state_machine::backend::BackendRuntimeCode::new(&backend); let runtime_code = backend_runtime_code.runtime_code().expect("Code is part of the backend"); @@ -418,8 +418,8 @@ fn uncles_with_multiple_forks() { // block tree: // G -> A1 -> A2 -> A3 -> A4 -> A5 // A1 -> B2 -> B3 -> B4 - // B2 -> C3 - // A1 -> D2 + // B2 -> C3 + // A1 -> D2 let mut client = substrate_test_runtime_client::new(); // G -> A1 diff --git a/frame/benchmarking/src/lib.rs b/frame/benchmarking/src/lib.rs index 56545914dcba..3e1ed1ed2f11 100644 --- a/frame/benchmarking/src/lib.rs +++ b/frame/benchmarking/src/lib.rs @@ -42,8 +42,9 @@ pub use sp_io::storage::root as storage_root; #[doc(hidden)] pub use sp_runtime::traits::Zero; #[doc(hidden)] -pub use sp_std::{self, boxed::Box, prelude::Vec, str, vec}; +pub use sp_runtime::StateVersion; #[doc(hidden)] +pub use sp_std::{self, boxed::Box, prelude::Vec, str, vec}; pub use sp_storage::TrackedStorageKey; pub use utils::*; @@ -1079,7 +1080,7 @@ macro_rules! impl_benchmark { // Time the storage root recalculation. let start_storage_root = $crate::benchmarking::current_time(); - $crate::storage_root(); + $crate::storage_root($crate::StateVersion::V1); let finish_storage_root = $crate::benchmarking::current_time(); let elapsed_storage_root = finish_storage_root - start_storage_root; diff --git a/frame/executive/src/lib.rs b/frame/executive/src/lib.rs index cc013d4c333f..1b74bdc2fea0 100644 --- a/frame/executive/src/lib.rs +++ b/frame/executive/src/lib.rs @@ -671,7 +671,7 @@ mod tests { #[pallet::weight(0)] pub fn calculate_storage_root(_origin: OriginFor) -> DispatchResult { - let root = sp_io::storage::root(); + let root = sp_io::storage::root(sp_runtime::StateVersion::V1); sp_io::storage::set("storage_root".as_bytes(), &root); Ok(()) } @@ -897,17 +897,32 @@ mod tests { t.into() } + fn new_test_ext_v0(balance_factor: Balance) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + pallet_balances::GenesisConfig:: { balances: vec![(1, 111 * balance_factor)] } + .assimilate_storage(&mut t) + .unwrap(); + (t, sp_runtime::StateVersion::V0).into() + } + #[test] fn block_import_works() { - new_test_ext(1).execute_with(|| { + block_import_works_inner( + new_test_ext_v0(1), + hex!("1039e1a4bd0cf5deefe65f313577e70169c41c7773d6acf31ca8d671397559f5").into(), + ); + block_import_works_inner( + new_test_ext(1), + hex!("75e7d8f360d375bbe91bcf8019c01ab6362448b4a89e3b329717eb9d910340e5").into(), + ); + } + fn block_import_works_inner(mut ext: sp_io::TestExternalities, state_root: H256) { + ext.execute_with(|| { Executive::execute_block(Block { header: Header { parent_hash: [69u8; 32].into(), number: 1, - state_root: hex!( - "1039e1a4bd0cf5deefe65f313577e70169c41c7773d6acf31ca8d671397559f5" - ) - .into(), + state_root, extrinsics_root: hex!( "03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314" ) @@ -948,7 +963,7 @@ mod tests { parent_hash: [69u8; 32].into(), number: 1, state_root: hex!( - "49cd58a254ccf6abc4a023d9a22dcfc421e385527a250faec69f8ad0d8ed3e48" + "75e7d8f360d375bbe91bcf8019c01ab6362448b4a89e3b329717eb9d910340e5" ) .into(), extrinsics_root: [0u8; 32].into(), diff --git a/frame/session/src/historical/mod.rs b/frame/session/src/historical/mod.rs index a3e64f4f9efa..fa7cb9ee91c0 100644 --- a/frame/session/src/historical/mod.rs +++ b/frame/session/src/historical/mod.rs @@ -39,7 +39,7 @@ use sp_session::{MembershipProof, ValidatorCount}; use sp_staking::SessionIndex; use sp_std::prelude::*; use sp_trie::{ - trie_types::{TrieDB, TrieDBMut}, + trie_types::{TrieDB, TrieDBMutV0}, MemoryDB, Recorder, Trie, TrieMut, EMPTY_PREFIX, }; @@ -236,7 +236,7 @@ impl ProvingTrie { let mut root = Default::default(); { - let mut trie = TrieDBMut::new(&mut db, &mut root); + let mut trie = TrieDBMutV0::new(&mut db, &mut root); for (i, (validator, full_id)) in validators.into_iter().enumerate() { let i = i as u32; let keys = match >::load_keys(&validator) { diff --git a/frame/support/src/lib.rs b/frame/support/src/lib.rs index 2adcd8ce4efc..2a23d203adf6 100644 --- a/frame/support/src/lib.rs +++ b/frame/support/src/lib.rs @@ -46,7 +46,7 @@ pub use sp_core_hashing_proc_macro; #[doc(hidden)] pub use sp_io::{self, storage::root as storage_root}; #[doc(hidden)] -pub use sp_runtime::RuntimeDebug; +pub use sp_runtime::{RuntimeDebug, StateVersion}; #[cfg(feature = "std")] #[doc(hidden)] pub use sp_state_machine::BasicExternalities; @@ -751,9 +751,9 @@ macro_rules! assert_noop { $x:expr, $y:expr $(,)? ) => { - let h = $crate::storage_root(); + let h = $crate::storage_root($crate::StateVersion::V1); $crate::assert_err!($x, $y); - assert_eq!(h, $crate::storage_root()); + assert_eq!(h, $crate::storage_root($crate::StateVersion::V1)); }; } @@ -766,9 +766,9 @@ macro_rules! assert_storage_noop { ( $x:expr ) => { - let h = $crate::storage_root(); + let h = $crate::storage_root($crate::StateVersion::V1); $x; - assert_eq!(h, $crate::storage_root()); + assert_eq!(h, $crate::storage_root($crate::StateVersion::V1)); }; } diff --git a/frame/support/src/storage/child.rs b/frame/support/src/storage/child.rs index 5497f642067c..19b00d105136 100644 --- a/frame/support/src/storage/child.rs +++ b/frame/support/src/storage/child.rs @@ -24,7 +24,7 @@ pub use crate::sp_io::KillStorageResult; use crate::sp_std::prelude::*; use codec::{Codec, Decode, Encode}; -pub use sp_core::storage::{ChildInfo, ChildType}; +pub use sp_core::storage::{ChildInfo, ChildType, StateVersion}; /// Return the value of the item in storage under `key`, or `None` if there is no explicit entry. pub fn get(child_info: &ChildInfo, key: &[u8]) -> Option { @@ -167,9 +167,10 @@ pub fn put_raw(child_info: &ChildInfo, key: &[u8], value: &[u8]) { } /// Calculate current child root value. -pub fn root(child_info: &ChildInfo) -> Vec { +pub fn root(child_info: &ChildInfo, version: StateVersion) -> Vec { match child_info.child_type() { - ChildType::ParentKeyId => sp_io::default_child_storage::root(child_info.storage_key()), + ChildType::ParentKeyId => + sp_io::default_child_storage::root(child_info.storage_key(), version), } } diff --git a/frame/support/test/compile_pass/src/lib.rs b/frame/support/test/compile_pass/src/lib.rs index a5586996215e..47b81e102069 100644 --- a/frame/support/test/compile_pass/src/lib.rs +++ b/frame/support/test/compile_pass/src/lib.rs @@ -41,6 +41,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { impl_version: 0, apis: sp_version::create_apis_vec!([]), transaction_version: 0, + state_version: 0, }; pub type Signature = sr25519::Signature; diff --git a/frame/system/src/lib.rs b/frame/system/src/lib.rs index e167f44ffd88..8026f77902ba 100644 --- a/frame/system/src/lib.rs +++ b/frame/system/src/lib.rs @@ -127,13 +127,19 @@ pub use extensions::check_mortality::CheckMortality as CheckEra; pub use weights::WeightInfo; /// Compute the trie root of a list of extrinsics. +/// +/// The merkle proof is using the same trie as runtime state with +/// `state_version` 0. pub fn extrinsics_root(extrinsics: &[E]) -> H::Output { extrinsics_data_root::(extrinsics.iter().map(codec::Encode::encode).collect()) } /// Compute the trie root of a list of extrinsics. +/// +/// The merkle proof is using the same trie as runtime state with +/// `state_version` 0. pub fn extrinsics_data_root(xts: Vec>) -> H::Output { - H::ordered_trie_root(xts) + H::ordered_trie_root(xts, sp_core::storage::StateVersion::V0) } /// An object to track the currently used extrinsic weight in a block. @@ -1355,7 +1361,8 @@ impl Pallet { >::remove(to_remove); } - let storage_root = T::Hash::decode(&mut &sp_io::storage::root()[..]) + let version = T::Version::get().state_version(); + let storage_root = T::Hash::decode(&mut &sp_io::storage::root(version)[..]) .expect("Node is configured to use the same hash; qed"); ::new( diff --git a/frame/system/src/mock.rs b/frame/system/src/mock.rs index d8d9e7323aed..5d10962a8f40 100644 --- a/frame/system/src/mock.rs +++ b/frame/system/src/mock.rs @@ -53,6 +53,7 @@ parameter_types! { impl_version: 1, apis: sp_version::create_apis_vec!([]), transaction_version: 1, + state_version: 1, }; pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight { read: 10, diff --git a/frame/transaction-storage/src/benchmarking.rs b/frame/transaction-storage/src/benchmarking.rs index 0f90b51087ae..b03c75148fa1 100644 --- a/frame/transaction-storage/src/benchmarking.rs +++ b/frame/transaction-storage/src/benchmarking.rs @@ -29,54 +29,77 @@ use sp_transaction_storage_proof::TransactionStorageProof; use crate::Pallet as TransactionStorage; +// Proof generated from max size storage: +// ``` +// let mut transactions = Vec::new(); +// let tx_size = DEFAULT_MAX_TRANSACTION_SIZE; +// for _ in 0..DEFAULT_MAX_BLOCK_TRANSACTIONS { +// transactions.push(vec![0; tx_size]); +// } +// let hash = vec![0; 32]; +// build_proof(hash.as_slice(), transactions).unwrap().encode() +// ``` +// while hardforcing target chunk key in `build_proof` to [22, 21, 1, 0]. const PROOF: &[u8] = &hex_literal::hex!( " - 0104000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000014cd0780ffff80e316a478e2f1fcb13cf22fd0b2dbb54a6f53cff93f3ca2f3dfe8 - 7d12a3662c4c0080e316a478e2f1fcb13cf22fd0b2dbb54a6f53cff93f3ca2f3dfe87d12a3662c4c80e316a478e2f1fcb - 13cf22fd0b2dbb54a6f53cff93f3ca2f3dfe87d12a3662c4c80e316a478e2f1fcb13cf22fd0b2dbb54a6f53cff93f3ca2 - f3dfe87d12a3662c4c80e316a478e2f1fcb13cf22fd0b2dbb54a6f53cff93f3ca2f3dfe87d12a3662c4c80e316a478e2f - 1fcb13cf22fd0b2dbb54a6f53cff93f3ca2f3dfe87d12a3662c4c80e316a478e2f1fcb13cf22fd0b2dbb54a6f53cff93f - 3ca2f3dfe87d12a3662c4c80e316a478e2f1fcb13cf22fd0b2dbb54a6f53cff93f3ca2f3dfe87d12a3662c4c80e316a47 - 8e2f1fcb13cf22fd0b2dbb54a6f53cff93f3ca2f3dfe87d12a3662c4c80e316a478e2f1fcb13cf22fd0b2dbb54a6f53cf - f93f3ca2f3dfe87d12a3662c4c80e316a478e2f1fcb13cf22fd0b2dbb54a6f53cff93f3ca2f3dfe87d12a3662c4c80e31 - 6a478e2f1fcb13cf22fd0b2dbb54a6f53cff93f3ca2f3dfe87d12a3662c4c80e316a478e2f1fcb13cf22fd0b2dbb54a6f - 53cff93f3ca2f3dfe87d12a3662c4c80e316a478e2f1fcb13cf22fd0b2dbb54a6f53cff93f3ca2f3dfe87d12a3662c4c8 - 0e316a478e2f1fcb13cf22fd0b2dbb54a6f53cff93f3ca2f3dfe87d12a3662c4cbd05807777809a5d7a720ce5f9d9a012 - fbf25e92c30e732dadba8f312b05e02976313ea64d9f807d43bcbf8a3dc2f6b9e957d129e610c06d411e11743062dc1cf - 3ac289390ae4c8008592aa2d915f52941036afbe72bac4ebe7ce186c4ddc53f118e0ddd4decd8cc809a5d7a720ce5f9d9 - a012fbf25e92c30e732dadba8f312b05e02976313ea64d9f807d43bcbf8a3dc2f6b9e957d129e610c06d411e11743062d - c1cf3ac289390ae4c00809a5d7a720ce5f9d9a012fbf25e92c30e732dadba8f312b05e02976313ea64d9f807d43bcbf8a - 3dc2f6b9e957d129e610c06d411e11743062dc1cf3ac289390ae4c8008592aa2d915f52941036afbe72bac4ebe7ce186c - 4ddc53f118e0ddd4decd8cc809a5d7a720ce5f9d9a012fbf25e92c30e732dadba8f312b05e02976313ea64d9f807d43bc - bf8a3dc2f6b9e957d129e610c06d411e11743062dc1cf3ac289390ae4c8008592aa2d915f52941036afbe72bac4ebe7ce - 186c4ddc53f118e0ddd4decd8cccd0780ffff8081b825bfa9b2ba8f5f253515e7db09eb1ad3d4f02f322d3aa1398e0cb0 - 3bdb31008081b825bfa9b2ba8f5f253515e7db09eb1ad3d4f02f322d3aa1398e0cb03bdb318081b825bfa9b2ba8f5f253 - 515e7db09eb1ad3d4f02f322d3aa1398e0cb03bdb318081b825bfa9b2ba8f5f253515e7db09eb1ad3d4f02f322d3aa139 - 8e0cb03bdb318081b825bfa9b2ba8f5f253515e7db09eb1ad3d4f02f322d3aa1398e0cb03bdb318081b825bfa9b2ba8f5 - f253515e7db09eb1ad3d4f02f322d3aa1398e0cb03bdb318081b825bfa9b2ba8f5f253515e7db09eb1ad3d4f02f322d3a - a1398e0cb03bdb318081b825bfa9b2ba8f5f253515e7db09eb1ad3d4f02f322d3aa1398e0cb03bdb318081b825bfa9b2b - a8f5f253515e7db09eb1ad3d4f02f322d3aa1398e0cb03bdb318081b825bfa9b2ba8f5f253515e7db09eb1ad3d4f02f32 - 2d3aa1398e0cb03bdb318081b825bfa9b2ba8f5f253515e7db09eb1ad3d4f02f322d3aa1398e0cb03bdb318081b825bfa - 9b2ba8f5f253515e7db09eb1ad3d4f02f322d3aa1398e0cb03bdb318081b825bfa9b2ba8f5f253515e7db09eb1ad3d4f0 - 2f322d3aa1398e0cb03bdb318081b825bfa9b2ba8f5f253515e7db09eb1ad3d4f02f322d3aa1398e0cb03bdb318081b82 - 5bfa9b2ba8f5f253515e7db09eb1ad3d4f02f322d3aa1398e0cb03bdb31cd0780ffff80b4f23ac50c8e67d9b280f2b31a - 5707d52b892977acaac84d530bd188544c5f9b80b4f23ac50c8e67d9b280f2b31a5707d52b892977acaac84d530bd1885 - 44c5f9b80b4f23ac50c8e67d9b280f2b31a5707d52b892977acaac84d530bd188544c5f9b80b4f23ac50c8e67d9b280f2 - b31a5707d52b892977acaac84d530bd188544c5f9b80b4f23ac50c8e67d9b280f2b31a5707d52b892977acaac84d530bd - 188544c5f9b0080b4f23ac50c8e67d9b280f2b31a5707d52b892977acaac84d530bd188544c5f9b80b4f23ac50c8e67d9 - b280f2b31a5707d52b892977acaac84d530bd188544c5f9b80b4f23ac50c8e67d9b280f2b31a5707d52b892977acaac84 - d530bd188544c5f9b80b4f23ac50c8e67d9b280f2b31a5707d52b892977acaac84d530bd188544c5f9b80b4f23ac50c8e - 67d9b280f2b31a5707d52b892977acaac84d530bd188544c5f9b80b4f23ac50c8e67d9b280f2b31a5707d52b892977aca - ac84d530bd188544c5f9b80b4f23ac50c8e67d9b280f2b31a5707d52b892977acaac84d530bd188544c5f9b80b4f23ac5 - 0c8e67d9b280f2b31a5707d52b892977acaac84d530bd188544c5f9b80b4f23ac50c8e67d9b280f2b31a5707d52b89297 - 7acaac84d530bd188544c5f9b80b4f23ac50c8e67d9b280f2b31a5707d52b892977acaac84d530bd188544c5f9b104401 - 0000 -" + 0104000000000000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000000000000000000000000000000000000000000014cd0780ffff8030 + 2eb0a6d2f63b834d15f1e729d1c1004657e3048cf206d697eeb153f61a30ba0080302eb0a6d2 + f63b834d15f1e729d1c1004657e3048cf206d697eeb153f61a30ba80302eb0a6d2f63b834d15 + f1e729d1c1004657e3048cf206d697eeb153f61a30ba80302eb0a6d2f63b834d15f1e729d1c1 + 004657e3048cf206d697eeb153f61a30ba80302eb0a6d2f63b834d15f1e729d1c1004657e304 + 8cf206d697eeb153f61a30ba80302eb0a6d2f63b834d15f1e729d1c1004657e3048cf206d697 + eeb153f61a30ba80302eb0a6d2f63b834d15f1e729d1c1004657e3048cf206d697eeb153f61a + 30ba80302eb0a6d2f63b834d15f1e729d1c1004657e3048cf206d697eeb153f61a30ba80302e + b0a6d2f63b834d15f1e729d1c1004657e3048cf206d697eeb153f61a30ba80302eb0a6d2f63b + 834d15f1e729d1c1004657e3048cf206d697eeb153f61a30ba80302eb0a6d2f63b834d15f1e7 + 29d1c1004657e3048cf206d697eeb153f61a30ba80302eb0a6d2f63b834d15f1e729d1c10046 + 57e3048cf206d697eeb153f61a30ba80302eb0a6d2f63b834d15f1e729d1c1004657e3048cf2 + 06d697eeb153f61a30ba80302eb0a6d2f63b834d15f1e729d1c1004657e3048cf206d697eeb1 + 53f61a30ba80302eb0a6d2f63b834d15f1e729d1c1004657e3048cf206d697eeb153f61a30ba + bd058077778010fd81bc1359802f0b871aeb95e4410a8ec92b93af10ea767a2027cf4734e8de + 808da338e6b722f7bf2051901bd5bccee5e71d5cf6b1faff338ad7120b0256c28380221ce17f + 19117affa96e077905fe48a99723a065969c638593b7d9ab57b538438010fd81bc1359802f0b + 871aeb95e4410a8ec92b93af10ea767a2027cf4734e8de808da338e6b722f7bf2051901bd5bc + cee5e71d5cf6b1faff338ad7120b0256c283008010fd81bc1359802f0b871aeb95e4410a8ec9 + 2b93af10ea767a2027cf4734e8de808da338e6b722f7bf2051901bd5bccee5e71d5cf6b1faff + 338ad7120b0256c28380221ce17f19117affa96e077905fe48a99723a065969c638593b7d9ab + 57b538438010fd81bc1359802f0b871aeb95e4410a8ec92b93af10ea767a2027cf4734e8de80 + 8da338e6b722f7bf2051901bd5bccee5e71d5cf6b1faff338ad7120b0256c28380221ce17f19 + 117affa96e077905fe48a99723a065969c638593b7d9ab57b53843cd0780ffff804509f59593 + fd47b1a97189127ba65a5649cfb0346637f9836e155eaf891a939c00804509f59593fd47b1a9 + 7189127ba65a5649cfb0346637f9836e155eaf891a939c804509f59593fd47b1a97189127ba6 + 5a5649cfb0346637f9836e155eaf891a939c804509f59593fd47b1a97189127ba65a5649cfb0 + 346637f9836e155eaf891a939c804509f59593fd47b1a97189127ba65a5649cfb0346637f983 + 6e155eaf891a939c804509f59593fd47b1a97189127ba65a5649cfb0346637f9836e155eaf89 + 1a939c804509f59593fd47b1a97189127ba65a5649cfb0346637f9836e155eaf891a939c8045 + 09f59593fd47b1a97189127ba65a5649cfb0346637f9836e155eaf891a939c804509f59593fd + 47b1a97189127ba65a5649cfb0346637f9836e155eaf891a939c804509f59593fd47b1a97189 + 127ba65a5649cfb0346637f9836e155eaf891a939c804509f59593fd47b1a97189127ba65a56 + 49cfb0346637f9836e155eaf891a939c804509f59593fd47b1a97189127ba65a5649cfb03466 + 37f9836e155eaf891a939c804509f59593fd47b1a97189127ba65a5649cfb0346637f9836e15 + 5eaf891a939c804509f59593fd47b1a97189127ba65a5649cfb0346637f9836e155eaf891a93 + 9c804509f59593fd47b1a97189127ba65a5649cfb0346637f9836e155eaf891a939ccd0780ff + ff8078916e776c64ccea05e958559f015c082d9d06feafa3610fc44a5b2ef543cb818078916e + 776c64ccea05e958559f015c082d9d06feafa3610fc44a5b2ef543cb818078916e776c64ccea + 05e958559f015c082d9d06feafa3610fc44a5b2ef543cb818078916e776c64ccea05e958559f + 015c082d9d06feafa3610fc44a5b2ef543cb818078916e776c64ccea05e958559f015c082d9d + 06feafa3610fc44a5b2ef543cb81008078916e776c64ccea05e958559f015c082d9d06feafa3 + 610fc44a5b2ef543cb818078916e776c64ccea05e958559f015c082d9d06feafa3610fc44a5b + 2ef543cb818078916e776c64ccea05e958559f015c082d9d06feafa3610fc44a5b2ef543cb81 + 8078916e776c64ccea05e958559f015c082d9d06feafa3610fc44a5b2ef543cb818078916e77 + 6c64ccea05e958559f015c082d9d06feafa3610fc44a5b2ef543cb818078916e776c64ccea05 + e958559f015c082d9d06feafa3610fc44a5b2ef543cb818078916e776c64ccea05e958559f01 + 5c082d9d06feafa3610fc44a5b2ef543cb818078916e776c64ccea05e958559f015c082d9d06 + feafa3610fc44a5b2ef543cb818078916e776c64ccea05e958559f015c082d9d06feafa3610f + c44a5b2ef543cb818078916e776c64ccea05e958559f015c082d9d06feafa3610fc44a5b2ef5 + 43cb811044010000 + " ); type BalanceOf = @@ -136,7 +159,6 @@ benchmarks! { )?; } run_to_block::(StoragePeriod::::get() + T::BlockNumber::one()); - let random_hash = [0u8]; let mut encoded_proof = PROOF; let proof = TransactionStorageProof::decode(&mut encoded_proof).unwrap(); }: check_proof(RawOrigin::None, proof) diff --git a/frame/transaction-storage/src/lib.rs b/frame/transaction-storage/src/lib.rs index 94937c04ed5d..2cd47b1cd0db 100644 --- a/frame/transaction-storage/src/lib.rs +++ b/frame/transaction-storage/src/lib.rs @@ -188,7 +188,7 @@ pub mod pallet { // Chunk data and compute storage root let chunk_count = num_chunks(data.len() as u32); let chunks = data.chunks(CHUNK_SIZE).map(|c| c.to_vec()).collect(); - let root = sp_io::trie::blake2_256_ordered_root(chunks); + let root = sp_io::trie::blake2_256_ordered_root(chunks, sp_runtime::StateVersion::V1); let content_hash = sp_io::hashing::blake2_256(&data); let extrinsic_index = >::extrinsic_index() @@ -300,6 +300,7 @@ pub mod pallet { &proof.proof, &encode_index(chunk_index), &proof.chunk, + sp_runtime::StateVersion::V1, ), Error::::InvalidProof ); diff --git a/primitives/api/proc-macro/src/impl_runtime_apis.rs b/primitives/api/proc-macro/src/impl_runtime_apis.rs index dd2a7f6c1490..db3ab3b76850 100644 --- a/primitives/api/proc-macro/src/impl_runtime_apis.rs +++ b/primitives/api/proc-macro/src/impl_runtime_apis.rs @@ -293,10 +293,17 @@ fn generate_runtime_api_base_structures() -> Result { #crate_::StorageChanges, String > where Self: Sized { + let at = #crate_::BlockId::Hash(parent_hash.clone()); + let state_version = self.call + .runtime_version_at(&at) + .map(|v| v.state_version()) + .map_err(|e| format!("Failed to get state version: {:?}", e))?; + self.changes.replace(Default::default()).into_storage_changes( backend, parent_hash, self.storage_transaction_cache.replace(Default::default()), + state_version, ) } } diff --git a/primitives/api/src/lib.rs b/primitives/api/src/lib.rs index 7f64e191941f..41c0151d6c53 100644 --- a/primitives/api/src/lib.rs +++ b/primitives/api/src/lib.rs @@ -84,6 +84,8 @@ pub use sp_core::NativeOrEncoded; use sp_core::OpaqueMetadata; #[doc(hidden)] pub use sp_core::{offchain, ExecutionContext}; +#[cfg(feature = "std")] +pub use sp_runtime::StateVersion; #[doc(hidden)] pub use sp_runtime::{ generic::BlockId, @@ -269,6 +271,7 @@ pub use sp_api_proc_macro::decl_runtime_apis; /// // Here we are exposing the runtime api versions. /// apis: RUNTIME_API_VERSIONS, /// transaction_version: 1, +/// state_version: 1, /// }; /// /// # fn main() {} @@ -654,53 +657,13 @@ pub fn deserialize_runtime_api_info(bytes: [u8; RUNTIME_API_INFO_SIZE]) -> ([u8; (id, version) } -#[derive(codec::Encode, codec::Decode)] -pub struct OldRuntimeVersion { - pub spec_name: RuntimeString, - pub impl_name: RuntimeString, - pub authoring_version: u32, - pub spec_version: u32, - pub impl_version: u32, - pub apis: ApisVec, -} - -impl From for RuntimeVersion { - fn from(x: OldRuntimeVersion) -> Self { - Self { - spec_name: x.spec_name, - impl_name: x.impl_name, - authoring_version: x.authoring_version, - spec_version: x.spec_version, - impl_version: x.impl_version, - apis: x.apis, - transaction_version: 1, - } - } -} - -impl From for OldRuntimeVersion { - fn from(x: RuntimeVersion) -> Self { - Self { - spec_name: x.spec_name, - impl_name: x.impl_name, - authoring_version: x.authoring_version, - spec_version: x.spec_version, - impl_version: x.impl_version, - apis: x.apis, - } - } -} - decl_runtime_apis! { /// The `Core` runtime api that every Substrate runtime needs to implement. #[core_trait] - #[api_version(3)] + #[api_version(4)] pub trait Core { /// Returns the version of the runtime. fn version() -> RuntimeVersion; - /// Returns the version of the runtime. - #[changed_in(3)] - fn version() -> OldRuntimeVersion; /// Execute the given block. fn execute_block(block: Block); /// Initialize a block with the given header. diff --git a/primitives/externalities/src/lib.rs b/primitives/externalities/src/lib.rs index aac45234dead..6d560c3c7f11 100644 --- a/primitives/externalities/src/lib.rs +++ b/primitives/externalities/src/lib.rs @@ -31,7 +31,7 @@ use sp_std::{ vec::Vec, }; -use sp_storage::{ChildInfo, TrackedStorageKey}; +use sp_storage::{ChildInfo, StateVersion, TrackedStorageKey}; pub use extensions::{Extension, ExtensionStore, Extensions}; pub use scope_limited::{set_and_run_with_externalities, with_externalities}; @@ -157,7 +157,7 @@ pub trait Externalities: ExtensionStore { /// This will also update all child storage keys in the top-level storage map. /// /// The returned hash is defined by the `Block` and is SCALE encoded. - fn storage_root(&mut self) -> Vec; + fn storage_root(&mut self, state_version: StateVersion) -> Vec; /// Get the trie root of a child storage map. /// @@ -165,7 +165,11 @@ pub trait Externalities: ExtensionStore { /// /// If the storage root equals the default hash as defined by the trie, the key in the top-level /// storage map will be removed. - fn child_storage_root(&mut self, child_info: &ChildInfo) -> Vec; + fn child_storage_root( + &mut self, + child_info: &ChildInfo, + state_version: StateVersion, + ) -> Vec; /// Append storage item. /// diff --git a/primitives/io/src/lib.rs b/primitives/io/src/lib.rs index 1edf87703fbe..9025ae3d76f4 100644 --- a/primitives/io/src/lib.rs +++ b/primitives/io/src/lib.rs @@ -51,11 +51,13 @@ use sp_core::{ offchain::{ HttpError, HttpRequestId, HttpRequestStatus, OpaqueNetworkState, StorageKind, Timestamp, }, - sr25519, LogLevel, LogLevelFilter, OpaquePeerId, H256, + sr25519, + storage::StateVersion, + LogLevel, LogLevelFilter, OpaquePeerId, H256, }; #[cfg(feature = "std")] -use sp_trie::{trie_types::Layout, TrieConfiguration}; +use sp_trie::{LayoutV0, LayoutV1, TrieConfiguration}; use sp_runtime_interface::{ pass_by::{PassBy, PassByCodec}, @@ -192,7 +194,17 @@ pub trait Storage { /// /// Returns a `Vec` that holds the SCALE encoded hash. fn root(&mut self) -> Vec { - self.storage_root() + self.storage_root(StateVersion::V0) + } + + /// "Commit" all existing operations and compute the resulting storage root. + /// + /// The hashing algorithm is defined by the `Block`. + /// + /// Returns a `Vec` that holds the SCALE encoded hash. + #[version(2)] + fn root(&mut self, version: StateVersion) -> Vec { + self.storage_root(version) } /// Always returns `None`. This function exists for compatibility reasons. @@ -373,7 +385,19 @@ pub trait DefaultChildStorage { /// Returns a `Vec` that holds the SCALE encoded hash. fn root(&mut self, storage_key: &[u8]) -> Vec { let child_info = ChildInfo::new_default(storage_key); - self.child_storage_root(&child_info) + self.child_storage_root(&child_info, StateVersion::V0) + } + + /// Default child root calculation. + /// + /// "Commit" all existing operations and compute the resulting child storage root. + /// The hashing algorithm is defined by the `Block`. + /// + /// Returns a `Vec` that holds the SCALE encoded hash. + #[version(2)] + fn root(&mut self, storage_key: &[u8], version: StateVersion) -> Vec { + let child_info = ChildInfo::new_default(storage_key); + self.child_storage_root(&child_info, version) } /// Child storage key iteration. @@ -390,27 +414,63 @@ pub trait DefaultChildStorage { pub trait Trie { /// A trie root formed from the iterated items. fn blake2_256_root(input: Vec<(Vec, Vec)>) -> H256 { - Layout::::trie_root(input) + LayoutV0::::trie_root(input) + } + + /// A trie root formed from the iterated items. + #[version(2)] + fn blake2_256_root(input: Vec<(Vec, Vec)>, version: StateVersion) -> H256 { + match version { + StateVersion::V0 => LayoutV0::::trie_root(input), + StateVersion::V1 => LayoutV1::::trie_root(input), + } } /// A trie root formed from the enumerated items. fn blake2_256_ordered_root(input: Vec>) -> H256 { - Layout::::ordered_trie_root(input) + LayoutV0::::ordered_trie_root(input) + } + + /// A trie root formed from the enumerated items. + #[version(2)] + fn blake2_256_ordered_root(input: Vec>, version: StateVersion) -> H256 { + match version { + StateVersion::V0 => LayoutV0::::ordered_trie_root(input), + StateVersion::V1 => LayoutV1::::ordered_trie_root(input), + } } /// A trie root formed from the iterated items. fn keccak_256_root(input: Vec<(Vec, Vec)>) -> H256 { - Layout::::trie_root(input) + LayoutV0::::trie_root(input) + } + + /// A trie root formed from the iterated items. + #[version(2)] + fn keccak_256_root(input: Vec<(Vec, Vec)>, version: StateVersion) -> H256 { + match version { + StateVersion::V0 => LayoutV0::::trie_root(input), + StateVersion::V1 => LayoutV1::::trie_root(input), + } } /// A trie root formed from the enumerated items. fn keccak_256_ordered_root(input: Vec>) -> H256 { - Layout::::ordered_trie_root(input) + LayoutV0::::ordered_trie_root(input) + } + + /// A trie root formed from the enumerated items. + #[version(2)] + fn keccak_256_ordered_root(input: Vec>, version: StateVersion) -> H256 { + match version { + StateVersion::V0 => LayoutV0::::ordered_trie_root(input), + StateVersion::V1 => LayoutV1::::ordered_trie_root(input), + } } /// Verify trie proof fn blake2_256_verify_proof(root: H256, proof: &[Vec], key: &[u8], value: &[u8]) -> bool { - sp_trie::verify_trie_proof::, _, _, _>( + sp_trie::verify_trie_proof::, _, _, _>( &root, proof, &[(key, Some(value))], @@ -418,15 +478,69 @@ pub trait Trie { .is_ok() } + /// Verify trie proof + #[version(2)] + fn blake2_256_verify_proof( + root: H256, + proof: &[Vec], + key: &[u8], + value: &[u8], + version: StateVersion, + ) -> bool { + match version { + StateVersion::V0 => sp_trie::verify_trie_proof::< + LayoutV0, + _, + _, + _, + >(&root, proof, &[(key, Some(value))]) + .is_ok(), + StateVersion::V1 => sp_trie::verify_trie_proof::< + LayoutV1, + _, + _, + _, + >(&root, proof, &[(key, Some(value))]) + .is_ok(), + } + } + /// Verify trie proof fn keccak_256_verify_proof(root: H256, proof: &[Vec], key: &[u8], value: &[u8]) -> bool { - sp_trie::verify_trie_proof::, _, _, _>( + sp_trie::verify_trie_proof::, _, _, _>( &root, proof, &[(key, Some(value))], ) .is_ok() } + + /// Verify trie proof + #[version(2)] + fn keccak_256_verify_proof( + root: H256, + proof: &[Vec], + key: &[u8], + value: &[u8], + version: StateVersion, + ) -> bool { + match version { + StateVersion::V0 => sp_trie::verify_trie_proof::< + LayoutV0, + _, + _, + _, + >(&root, proof, &[(key, Some(value))]) + .is_ok(), + StateVersion::V1 => sp_trie::verify_trie_proof::< + LayoutV1, + _, + _, + _, + >(&root, proof, &[(key, Some(value))]) + .is_ok(), + } + } } /// Interface that provides miscellaneous functions for communicating between the runtime and the @@ -1570,6 +1684,16 @@ mod tests { assert_eq!(storage::get(b"hello"), None); assert_eq!(storage::get(b"foo"), Some(b"bar".to_vec())); }); + + let value = vec![7u8; 35]; + let storage = + Storage { top: map![b"foo00".to_vec() => value.clone()], children_default: map![] }; + t = BasicExternalities::new(storage); + + t.execute_with(|| { + assert_eq!(storage::get(b"hello"), None); + assert_eq!(storage::get(b"foo00"), Some(value.clone())); + }); } #[test] diff --git a/primitives/runtime-interface/src/impls.rs b/primitives/runtime-interface/src/impls.rs index 35badd27fa99..16eecbd021e0 100644 --- a/primitives/runtime-interface/src/impls.rs +++ b/primitives/runtime-interface/src/impls.rs @@ -544,3 +544,7 @@ impl PassBy for sp_wasm_interface::Value { impl PassBy for sp_storage::TrackedStorageKey { type PassBy = Codec; } + +impl PassBy for sp_storage::StateVersion { + type PassBy = Enum; +} diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index deea4a73c8e2..7fdc5dda5c74 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -40,6 +40,7 @@ pub use paste; #[doc(hidden)] pub use sp_application_crypto as app_crypto; +pub use sp_core::storage::StateVersion; #[cfg(feature = "std")] pub use sp_core::storage::{Storage, StorageChild}; diff --git a/primitives/runtime/src/traits.rs b/primitives/runtime/src/traits.rs index 0ddd8cae93ea..cc83f66ea463 100644 --- a/primitives/runtime/src/traits.rs +++ b/primitives/runtime/src/traits.rs @@ -36,7 +36,7 @@ pub use sp_arithmetic::traits::{ CheckedShr, CheckedSub, IntegerSquareRoot, One, SaturatedConversion, Saturating, UniqueSaturatedFrom, UniqueSaturatedInto, Zero, }; -use sp_core::{self, Hasher, RuntimeDebug, TypeId}; +use sp_core::{self, storage::StateVersion, Hasher, RuntimeDebug, TypeId}; use sp_std::{ self, convert::{TryFrom, TryInto}, @@ -459,10 +459,10 @@ pub trait Hash: } /// The ordered Patricia tree root of the given `input`. - fn ordered_trie_root(input: Vec>) -> Self::Output; + fn ordered_trie_root(input: Vec>, state_version: StateVersion) -> Self::Output; /// The Patricia tree root of the given mapping. - fn trie_root(input: Vec<(Vec, Vec)>) -> Self::Output; + fn trie_root(input: Vec<(Vec, Vec)>, state_version: StateVersion) -> Self::Output; } /// Blake2-256 Hash implementation. @@ -483,12 +483,12 @@ impl Hasher for BlakeTwo256 { impl Hash for BlakeTwo256 { type Output = sp_core::H256; - fn trie_root(input: Vec<(Vec, Vec)>) -> Self::Output { - sp_io::trie::blake2_256_root(input) + fn trie_root(input: Vec<(Vec, Vec)>, version: StateVersion) -> Self::Output { + sp_io::trie::blake2_256_root(input, version) } - fn ordered_trie_root(input: Vec>) -> Self::Output { - sp_io::trie::blake2_256_ordered_root(input) + fn ordered_trie_root(input: Vec>, version: StateVersion) -> Self::Output { + sp_io::trie::blake2_256_ordered_root(input, version) } } @@ -510,12 +510,12 @@ impl Hasher for Keccak256 { impl Hash for Keccak256 { type Output = sp_core::H256; - fn trie_root(input: Vec<(Vec, Vec)>) -> Self::Output { - sp_io::trie::keccak_256_root(input) + fn trie_root(input: Vec<(Vec, Vec)>, version: StateVersion) -> Self::Output { + sp_io::trie::keccak_256_root(input, version) } - fn ordered_trie_root(input: Vec>) -> Self::Output { - sp_io::trie::keccak_256_ordered_root(input) + fn ordered_trie_root(input: Vec>, version: StateVersion) -> Self::Output { + sp_io::trie::keccak_256_ordered_root(input, version) } } diff --git a/primitives/state-machine/Cargo.toml b/primitives/state-machine/Cargo.toml index 2c84b9186d0a..b9e5c1d4f3f0 100644 --- a/primitives/state-machine/Cargo.toml +++ b/primitives/state-machine/Cargo.toml @@ -18,8 +18,8 @@ log = { version = "0.4.11", optional = true } thiserror = { version = "1.0.30", optional = true } parking_lot = { version = "0.11.2", optional = true } hash-db = { version = "0.15.2", default-features = false } -trie-db = { version = "0.22.6", default-features = false } -trie-root = { version = "0.16.0", default-features = false } +trie-db = { version = "0.23.0", default-features = false } +trie-root = { version = "0.17.0", default-features = false } sp-trie = { version = "4.0.0", path = "../trie", default-features = false } sp-core = { version = "4.1.0-dev", path = "../core", default-features = false } sp-panic-handler = { version = "4.0.0", path = "../panic-handler", optional = true } diff --git a/primitives/state-machine/src/backend.rs b/primitives/state-machine/src/backend.rs index eb6e2939b83f..8a6ed4d3dba8 100644 --- a/primitives/state-machine/src/backend.rs +++ b/primitives/state-machine/src/backend.rs @@ -23,7 +23,7 @@ use crate::{ }; use codec::Encode; use hash_db::Hasher; -use sp_core::storage::{ChildInfo, TrackedStorageKey}; +use sp_core::storage::{ChildInfo, StateVersion, TrackedStorageKey}; #[cfg(feature = "std")] use sp_core::traits::RuntimeCode; use sp_std::vec::Vec; @@ -140,6 +140,7 @@ pub trait Backend: sp_std::fmt::Debug { fn storage_root<'a>( &self, delta: impl Iterator)>, + state_version: StateVersion, ) -> (H::Out, Self::Transaction) where H::Out: Ord; @@ -151,6 +152,7 @@ pub trait Backend: sp_std::fmt::Debug { &self, child_info: &ChildInfo, delta: impl Iterator)>, + state_version: StateVersion, ) -> (H::Out, bool, Self::Transaction) where H::Out: Ord; @@ -176,7 +178,6 @@ pub trait Backend: sp_std::fmt::Debug { fn as_trie_backend(&self) -> Option<&TrieBackend> { None } - /// Calculate the storage root, with given delta over what is already stored /// in the backend, and produce a "transaction" that can be used to commit. /// Does include child storage updates. @@ -186,6 +187,7 @@ pub trait Backend: sp_std::fmt::Debug { child_deltas: impl Iterator< Item = (&'a ChildInfo, impl Iterator)>), >, + state_version: StateVersion, ) -> (H::Out, Self::Transaction) where H::Out: Ord + Encode, @@ -194,7 +196,8 @@ pub trait Backend: sp_std::fmt::Debug { let mut child_roots: Vec<_> = Default::default(); // child first for (child_info, child_delta) in child_deltas { - let (child_root, empty, child_txs) = self.child_storage_root(&child_info, child_delta); + let (child_root, empty, child_txs) = + self.child_storage_root(&child_info, child_delta, state_version); let prefixed_storage_key = child_info.prefixed_storage_key(); txs.consolidate(child_txs); if empty { @@ -205,8 +208,9 @@ pub trait Backend: sp_std::fmt::Debug { } let (root, parent_txs) = self.storage_root( delta - .map(|(k, v)| (k, v.as_ref().map(|v| &v[..]))) + .map(|(k, v)| (&k[..], v.as_ref().map(|v| &v[..]))) .chain(child_roots.iter().map(|(k, v)| (&k[..], v.as_ref().map(|v| &v[..])))), + state_version, ); txs.consolidate(parent_txs); (root, txs) @@ -286,7 +290,11 @@ impl Consolidate for Vec<(Option, StorageCollection)> { } } -impl> Consolidate for sp_trie::GenericMemoryDB { +impl Consolidate for sp_trie::GenericMemoryDB +where + H: Hasher, + KF: sp_trie::KeyFunction, +{ fn consolidate(&mut self, other: Self) { sp_trie::GenericMemoryDB::consolidate(self, other) } diff --git a/primitives/state-machine/src/basic.rs b/primitives/state-machine/src/basic.rs index 3774adc5b036..c0bec8d08f00 100644 --- a/primitives/state-machine/src/basic.rs +++ b/primitives/state-machine/src/basic.rs @@ -23,13 +23,14 @@ use hash_db::Hasher; use log::warn; use sp_core::{ storage::{ - well_known_keys::is_child_storage_key, ChildInfo, Storage, StorageChild, TrackedStorageKey, + well_known_keys::is_child_storage_key, ChildInfo, StateVersion, Storage, StorageChild, + TrackedStorageKey, }, traits::Externalities, Blake2Hasher, }; use sp_externalities::{Extension, Extensions}; -use sp_trie::{empty_child_trie_root, trie_types::Layout, TrieConfiguration}; +use sp_trie::{empty_child_trie_root, LayoutV0, LayoutV1, TrieConfiguration}; use std::{ any::{Any, TypeId}, collections::BTreeMap, @@ -273,7 +274,7 @@ impl Externalities for BasicExternalities { crate::ext::StorageAppend::new(current).append(value); } - fn storage_root(&mut self) -> Vec { + fn storage_root(&mut self, state_version: StateVersion) -> Vec { let mut top = self.inner.top.clone(); let prefixed_keys: Vec<_> = self .inner @@ -284,9 +285,9 @@ impl Externalities for BasicExternalities { // Single child trie implementation currently allows using the same child // empty root for all child trie. Using null storage key until multiple // type of child trie support. - let empty_hash = empty_child_trie_root::>(); + let empty_hash = empty_child_trie_root::>(); for (prefixed_storage_key, child_info) in prefixed_keys { - let child_root = self.child_storage_root(&child_info); + let child_root = self.child_storage_root(&child_info, state_version); if &empty_hash[..] == &child_root[..] { top.remove(prefixed_storage_key.as_slice()); } else { @@ -294,17 +295,26 @@ impl Externalities for BasicExternalities { } } - Layout::::trie_root(self.inner.top.clone()).as_ref().into() + match state_version { + StateVersion::V0 => + LayoutV0::::trie_root(self.inner.top.clone()).as_ref().into(), + StateVersion::V1 => + LayoutV1::::trie_root(self.inner.top.clone()).as_ref().into(), + } } - fn child_storage_root(&mut self, child_info: &ChildInfo) -> Vec { + fn child_storage_root( + &mut self, + child_info: &ChildInfo, + state_version: StateVersion, + ) -> Vec { if let Some(child) = self.inner.children_default.get(child_info.storage_key()) { let delta = child.data.iter().map(|(k, v)| (k.as_ref(), Some(v.as_ref()))); crate::in_memory_backend::new_in_mem::() - .child_storage_root(&child.child_info, delta) + .child_storage_root(&child.child_info, delta, state_version) .0 } else { - empty_child_trie_root::>() + empty_child_trie_root::>() } .encode() } @@ -389,7 +399,7 @@ mod tests { const ROOT: [u8; 32] = hex!("39245109cef3758c2eed2ccba8d9b370a917850af3824bc8348d505df2c298fa"); - assert_eq!(&ext.storage_root()[..], &ROOT); + assert_eq!(&ext.storage_root(StateVersion::default())[..], &ROOT); } #[test] diff --git a/primitives/state-machine/src/ext.rs b/primitives/state-machine/src/ext.rs index 8f914ab3eee6..f5158acbc74d 100644 --- a/primitives/state-machine/src/ext.rs +++ b/primitives/state-machine/src/ext.rs @@ -24,9 +24,11 @@ use codec::{Decode, Encode, EncodeAppend}; use hash_db::Hasher; #[cfg(feature = "std")] use sp_core::hexdisplay::HexDisplay; -use sp_core::storage::{well_known_keys::is_child_storage_key, ChildInfo, TrackedStorageKey}; +use sp_core::storage::{ + well_known_keys::is_child_storage_key, ChildInfo, StateVersion, TrackedStorageKey, +}; use sp_externalities::{Extension, ExtensionStore, Externalities}; -use sp_trie::{empty_child_trie_root, trie_types::Layout}; +use sp_trie::{empty_child_trie_root, LayoutV1}; use crate::{log_error, trace, warn, StorageTransactionCache}; use sp_std::{ @@ -505,7 +507,7 @@ where StorageAppend::new(current_value).append(value); } - fn storage_root(&mut self) -> Vec { + fn storage_root(&mut self, state_version: StateVersion) -> Vec { let _guard = guard(); if let Some(ref root) = self.storage_transaction_cache.transaction_storage_root { trace!( @@ -518,7 +520,9 @@ where return root.encode() } - let root = self.overlay.storage_root(self.backend, self.storage_transaction_cache); + let root = + self.overlay + .storage_root(self.backend, self.storage_transaction_cache, state_version); trace!( target: "state", method = "StorageRoot", @@ -529,7 +533,11 @@ where root.encode() } - fn child_storage_root(&mut self, child_info: &ChildInfo) -> Vec { + fn child_storage_root( + &mut self, + child_info: &ChildInfo, + state_version: StateVersion, + ) -> Vec { let _guard = guard(); let storage_key = child_info.storage_key(); let prefixed_storage_key = child_info.prefixed_storage_key(); @@ -537,7 +545,8 @@ where let root = self .storage(prefixed_storage_key.as_slice()) .and_then(|k| Decode::decode(&mut &k[..]).ok()) - .unwrap_or_else(|| empty_child_trie_root::>()); + // V1 is equivalent to V0 on empty root. + .unwrap_or_else(|| empty_child_trie_root::>()); trace!( target: "state", method = "ChildStorageRoot", @@ -550,7 +559,7 @@ where } else { let root = if let Some((changes, info)) = self.overlay.child_changes(storage_key) { let delta = changes.map(|(k, v)| (k.as_ref(), v.value().map(AsRef::as_ref))); - Some(self.backend.child_storage_root(info, delta)) + Some(self.backend.child_storage_root(info, delta, state_version)) } else { None }; @@ -583,7 +592,8 @@ where let root = self .storage(prefixed_storage_key.as_slice()) .and_then(|k| Decode::decode(&mut &k[..]).ok()) - .unwrap_or_else(|| empty_child_trie_root::>()); + // V1 is equivalent to V0 on empty root. + .unwrap_or_else(|| empty_child_trie_root::>()); trace!( target: "state", @@ -648,7 +658,12 @@ where self.overlay.rollback_transaction().expect(BENCHMARKING_FN); } self.overlay - .drain_storage_changes(self.backend, Default::default(), self.storage_transaction_cache) + .drain_storage_changes( + self.backend, + Default::default(), + self.storage_transaction_cache, + Default::default(), // using any state + ) .expect(EXT_NOT_ALLOWED_TO_FAIL); self.backend.wipe().expect(EXT_NOT_ALLOWED_TO_FAIL); self.mark_dirty(); @@ -658,12 +673,19 @@ where } fn commit(&mut self) { + // Bench always use latest state. + let state_version = StateVersion::default(); for _ in 0..self.overlay.transaction_depth() { self.overlay.commit_transaction().expect(BENCHMARKING_FN); } let changes = self .overlay - .drain_storage_changes(self.backend, Default::default(), self.storage_transaction_cache) + .drain_storage_changes( + self.backend, + Default::default(), + self.storage_transaction_cache, + state_version, + ) .expect(EXT_NOT_ALLOWED_TO_FAIL); self.backend .commit( @@ -878,15 +900,18 @@ mod tests { let mut overlay = OverlayedChanges::default(); overlay.set_storage(vec![20], None); overlay.set_storage(vec![30], Some(vec![31])); - let backend = Storage { - top: map![ - vec![10] => vec![10], - vec![20] => vec![20], - vec![40] => vec![40] - ], - children_default: map![], - } - .into(); + let backend = ( + Storage { + top: map![ + vec![10] => vec![10], + vec![20] => vec![20], + vec![40] => vec![40] + ], + children_default: map![], + }, + StateVersion::default(), + ) + .into(); let ext = TestExt::new(&mut overlay, &mut cache, &backend, None); @@ -924,13 +949,16 @@ mod tests { overlay.set_storage(vec![27], None); overlay.set_storage(vec![28], None); overlay.set_storage(vec![29], None); - let backend = Storage { - top: map![ - vec![30] => vec![30] - ], - children_default: map![], - } - .into(); + let backend = ( + Storage { + top: map![ + vec![30] => vec![30] + ], + children_default: map![], + }, + StateVersion::default(), + ) + .into(); let ext = TestExt::new(&mut overlay, &mut cache, &backend, None); @@ -948,20 +976,23 @@ mod tests { let mut overlay = OverlayedChanges::default(); overlay.set_child_storage(child_info, vec![20], None); overlay.set_child_storage(child_info, vec![30], Some(vec![31])); - let backend = Storage { - top: map![], - children_default: map![ - child_info.storage_key().to_vec() => StorageChild { - data: map![ - vec![10] => vec![10], - vec![20] => vec![20], - vec![40] => vec![40] - ], - child_info: child_info.to_owned(), - } - ], - } - .into(); + let backend = ( + Storage { + top: map![], + children_default: map![ + child_info.storage_key().to_vec() => StorageChild { + data: map![ + vec![10] => vec![10], + vec![20] => vec![20], + vec![40] => vec![40] + ], + child_info: child_info.to_owned(), + } + ], + }, + StateVersion::default(), + ) + .into(); let ext = TestExt::new(&mut overlay, &mut cache, &backend, None); @@ -993,20 +1024,23 @@ mod tests { let mut overlay = OverlayedChanges::default(); overlay.set_child_storage(child_info, vec![20], None); overlay.set_child_storage(child_info, vec![30], Some(vec![31])); - let backend = Storage { - top: map![], - children_default: map![ - child_info.storage_key().to_vec() => StorageChild { - data: map![ - vec![10] => vec![10], - vec![20] => vec![20], - vec![30] => vec![40] - ], - child_info: child_info.to_owned(), - } - ], - } - .into(); + let backend = ( + Storage { + top: map![], + children_default: map![ + child_info.storage_key().to_vec() => StorageChild { + data: map![ + vec![10] => vec![10], + vec![20] => vec![20], + vec![30] => vec![40] + ], + child_info: child_info.to_owned(), + } + ], + }, + StateVersion::default(), + ) + .into(); let ext = TestExt::new(&mut overlay, &mut cache, &backend, None); @@ -1032,18 +1066,21 @@ mod tests { let child_info = &child_info; let mut cache = StorageTransactionCache::default(); let mut overlay = OverlayedChanges::default(); - let backend = Storage { - top: map![], - children_default: map![ - child_info.storage_key().to_vec() => StorageChild { - data: map![ - vec![30] => vec![40] - ], - child_info: child_info.to_owned(), - } - ], - } - .into(); + let backend = ( + Storage { + top: map![], + children_default: map![ + child_info.storage_key().to_vec() => StorageChild { + data: map![ + vec![30] => vec![40] + ], + child_info: child_info.to_owned(), + } + ], + }, + StateVersion::default(), + ) + .into(); let ext = TestExt::new(&mut overlay, &mut cache, &backend, None); diff --git a/primitives/state-machine/src/in_memory_backend.rs b/primitives/state-machine/src/in_memory_backend.rs index f9f94c0c50d6..f4ae0d01d5fb 100644 --- a/primitives/state-machine/src/in_memory_backend.rs +++ b/primitives/state-machine/src/in_memory_backend.rs @@ -22,8 +22,8 @@ use crate::{ }; use codec::Codec; use hash_db::Hasher; -use sp_core::storage::{ChildInfo, Storage}; -use sp_trie::{empty_trie_root, Layout, MemoryDB}; +use sp_core::storage::{ChildInfo, StateVersion, Storage}; +use sp_trie::{empty_trie_root, LayoutV1, MemoryDB}; use std::collections::{BTreeMap, HashMap}; /// Create a new empty instance of in-memory backend. @@ -32,7 +32,8 @@ where H::Out: Codec + Ord, { let db = MemoryDB::default(); - TrieBackend::new(db, empty_trie_root::>()) + // V1 is same as V0 for an empty trie. + TrieBackend::new(db, empty_trie_root::>()) } impl TrieBackend, H> @@ -43,9 +44,10 @@ where pub fn update, StorageCollection)>>( &self, changes: T, + state_version: StateVersion, ) -> Self { let mut clone = self.clone(); - clone.insert(changes); + clone.insert(changes, state_version); clone } @@ -53,6 +55,7 @@ where pub fn insert, StorageCollection)>>( &mut self, changes: T, + state_version: StateVersion, ) { let (top, child) = changes.into_iter().partition::, _>(|v| v.0.is_none()); let (root, transaction) = self.full_storage_root( @@ -60,6 +63,7 @@ where child.iter().filter_map(|v| { v.0.as_ref().map(|c| (c, v.1.iter().map(|(k, v)| (&k[..], v.as_deref())))) }), + state_version, ); self.apply_transaction(root, transaction); @@ -103,53 +107,63 @@ where } } -impl From, BTreeMap>> +impl From<(HashMap, BTreeMap>, StateVersion)> for TrieBackend, H> where H::Out: Codec + Ord, { - fn from(inner: HashMap, BTreeMap>) -> Self { + fn from( + (inner, state_version): ( + HashMap, BTreeMap>, + StateVersion, + ), + ) -> Self { let mut backend = new_in_mem(); backend.insert( inner .into_iter() .map(|(k, m)| (k, m.into_iter().map(|(k, v)| (k, Some(v))).collect())), + state_version, ); backend } } -impl From for TrieBackend, H> +impl From<(Storage, StateVersion)> for TrieBackend, H> where H::Out: Codec + Ord, { - fn from(inners: Storage) -> Self { + fn from((inners, state_version): (Storage, StateVersion)) -> Self { let mut inner: HashMap, BTreeMap> = inners .children_default .into_iter() .map(|(_k, c)| (Some(c.child_info), c.data)) .collect(); inner.insert(None, inners.top); - inner.into() + (inner, state_version).into() } } -impl From> for TrieBackend, H> +impl From<(BTreeMap, StateVersion)> + for TrieBackend, H> where H::Out: Codec + Ord, { - fn from(inner: BTreeMap) -> Self { + fn from((inner, state_version): (BTreeMap, StateVersion)) -> Self { let mut expanded = HashMap::new(); expanded.insert(None, inner); - expanded.into() + (expanded, state_version).into() } } -impl From, StorageCollection)>> for TrieBackend, H> +impl From<(Vec<(Option, StorageCollection)>, StateVersion)> + for TrieBackend, H> where H::Out: Codec + Ord, { - fn from(inner: Vec<(Option, StorageCollection)>) -> Self { + fn from( + (inner, state_version): (Vec<(Option, StorageCollection)>, StateVersion), + ) -> Self { let mut expanded: HashMap, BTreeMap> = HashMap::new(); for (child_info, key_values) in inner { @@ -160,7 +174,7 @@ where } } } - expanded.into() + (expanded, state_version).into() } } @@ -168,16 +182,20 @@ where mod tests { use super::*; use crate::backend::Backend; + use sp_core::storage::StateVersion; use sp_runtime::traits::BlakeTwo256; /// Assert in memory backend with only child trie keys works as trie backend. #[test] fn in_memory_with_child_trie_only() { + let state_version = StateVersion::default(); let storage = new_in_mem::(); let child_info = ChildInfo::new_default(b"1"); let child_info = &child_info; - let storage = storage - .update(vec![(Some(child_info.clone()), vec![(b"2".to_vec(), Some(b"3".to_vec()))])]); + let storage = storage.update( + vec![(Some(child_info.clone()), vec![(b"2".to_vec(), Some(b"3".to_vec()))])], + state_version, + ); let trie_backend = storage.as_trie_backend().unwrap(); assert_eq!(trie_backend.child_storage(child_info, b"2").unwrap(), Some(b"3".to_vec())); let storage_key = child_info.prefixed_storage_key(); @@ -186,13 +204,18 @@ mod tests { #[test] fn insert_multiple_times_child_data_works() { + let state_version = StateVersion::default(); let mut storage = new_in_mem::(); let child_info = ChildInfo::new_default(b"1"); - storage - .insert(vec![(Some(child_info.clone()), vec![(b"2".to_vec(), Some(b"3".to_vec()))])]); - storage - .insert(vec![(Some(child_info.clone()), vec![(b"1".to_vec(), Some(b"3".to_vec()))])]); + storage.insert( + vec![(Some(child_info.clone()), vec![(b"2".to_vec(), Some(b"3".to_vec()))])], + state_version, + ); + storage.insert( + vec![(Some(child_info.clone()), vec![(b"1".to_vec(), Some(b"3".to_vec()))])], + state_version, + ); assert_eq!(storage.child_storage(&child_info, &b"2"[..]), Ok(Some(b"3".to_vec()))); assert_eq!(storage.child_storage(&child_info, &b"1"[..]), Ok(Some(b"3".to_vec()))); diff --git a/primitives/state-machine/src/lib.rs b/primitives/state-machine/src/lib.rs index e5c19f3bb0d5..dff499981634 100644 --- a/primitives/state-machine/src/lib.rs +++ b/primitives/state-machine/src/lib.rs @@ -126,6 +126,7 @@ impl sp_std::fmt::Display for DefaultError { pub use crate::{ backend::Backend, + error::{Error, ExecutionError}, ext::Ext, overlayed_changes::{ ChildStorageCollection, IndexOperation, OffchainChangesCollection, @@ -136,7 +137,6 @@ pub use crate::{ trie_backend::TrieBackend, trie_backend_essence::{Storage, TrieBackendStorage}, }; -pub use error::{Error, ExecutionError}; #[cfg(feature = "std")] mod std_reexport { @@ -151,8 +151,8 @@ mod std_reexport { testing::TestExternalities, }; pub use sp_trie::{ - trie_types::{Layout, TrieDBMut}, - CompactProof, DBValue, MemoryDB, StorageProof, TrieMut, + trie_types::{TrieDBMutV0, TrieDBMutV1}, + CompactProof, DBValue, LayoutV0, LayoutV1, MemoryDB, StorageProof, TrieMut, }; } @@ -1353,7 +1353,7 @@ mod tests { use codec::{Decode, Encode}; use sp_core::{ map, - storage::ChildInfo, + storage::{ChildInfo, StateVersion}, testing::TaskExecutor, traits::{CodeExecutor, Externalities, RuntimeCode}, NativeOrEncoded, NeverNativeValue, @@ -1416,7 +1416,11 @@ mod tests { #[test] fn execute_works() { - let backend = trie_backend::tests::test_trie(); + execute_works_inner(StateVersion::V0); + execute_works_inner(StateVersion::V1); + } + fn execute_works_inner(state_version: StateVersion) { + let backend = trie_backend::tests::test_trie(state_version); let mut overlayed_changes = Default::default(); let wasm_code = RuntimeCode::empty(); @@ -1440,7 +1444,11 @@ mod tests { #[test] fn execute_works_with_native_else_wasm() { - let backend = trie_backend::tests::test_trie(); + execute_works_with_native_else_wasm_inner(StateVersion::V0); + execute_works_with_native_else_wasm_inner(StateVersion::V1); + } + fn execute_works_with_native_else_wasm_inner(state_version: StateVersion) { + let backend = trie_backend::tests::test_trie(state_version); let mut overlayed_changes = Default::default(); let wasm_code = RuntimeCode::empty(); @@ -1464,8 +1472,12 @@ mod tests { #[test] fn dual_execution_strategy_detects_consensus_failure() { + dual_execution_strategy_detects_consensus_failure_inner(StateVersion::V0); + dual_execution_strategy_detects_consensus_failure_inner(StateVersion::V1); + } + fn dual_execution_strategy_detects_consensus_failure_inner(state_version: StateVersion) { let mut consensus_failed = false; - let backend = trie_backend::tests::test_trie(); + let backend = trie_backend::tests::test_trie(state_version); let mut overlayed_changes = Default::default(); let wasm_code = RuntimeCode::empty(); @@ -1498,6 +1510,10 @@ mod tests { #[test] fn prove_execution_and_proof_check_works() { + prove_execution_and_proof_check_works_inner(StateVersion::V0); + prove_execution_and_proof_check_works_inner(StateVersion::V1); + } + fn prove_execution_and_proof_check_works_inner(state_version: StateVersion) { let executor = DummyCodeExecutor { native_available: true, native_succeeds: true, @@ -1505,8 +1521,8 @@ mod tests { }; // fetch execution proof from 'remote' full node - let mut remote_backend = trie_backend::tests::test_trie(); - let remote_root = remote_backend.storage_root(std::iter::empty()).0; + let mut remote_backend = trie_backend::tests::test_trie(state_version); + let remote_root = remote_backend.storage_root(std::iter::empty(), state_version).0; let (remote_result, remote_proof) = prove_execution( &mut remote_backend, &mut Default::default(), @@ -1544,7 +1560,7 @@ mod tests { b"abc".to_vec() => b"2".to_vec(), b"bbb".to_vec() => b"3".to_vec() ]; - let state = InMemoryBackend::::from(initial); + let state = InMemoryBackend::::from((initial, StateVersion::default())); let backend = state.as_trie_backend().unwrap(); let mut overlay = OverlayedChanges::default(); @@ -1613,7 +1629,7 @@ mod tests { b"d".to_vec() => b"3".to_vec() ], ]; - let backend = InMemoryBackend::::from(initial); + let backend = InMemoryBackend::::from((initial, StateVersion::default())); let mut overlay = OverlayedChanges::default(); overlay.set_child_storage(&child_info, b"1".to_vec(), Some(b"1312".to_vec())); @@ -1655,7 +1671,7 @@ mod tests { b"d".to_vec() => b"3".to_vec() ], ]; - let backend = InMemoryBackend::::from(initial); + let backend = InMemoryBackend::::from((initial, StateVersion::default())); let mut overlay = OverlayedChanges::default(); let mut cache = StorageTransactionCache::default(); let mut ext = Ext::new(&mut overlay, &mut cache, &backend, None); @@ -1789,13 +1805,17 @@ mod tests { #[test] fn prove_read_and_proof_check_works() { + prove_read_and_proof_check_works_inner(StateVersion::V0); + prove_read_and_proof_check_works_inner(StateVersion::V1); + } + fn prove_read_and_proof_check_works_inner(state_version: StateVersion) { let child_info = ChildInfo::new_default(b"sub1"); let missing_child_info = ChildInfo::new_default(b"sub1sub2"); // key will include other child root to proof. let child_info = &child_info; let missing_child_info = &missing_child_info; // fetch read proof from 'remote' full node - let remote_backend = trie_backend::tests::test_trie(); - let remote_root = remote_backend.storage_root(std::iter::empty()).0; + let remote_backend = trie_backend::tests::test_trie(state_version); + let remote_root = remote_backend.storage_root(std::iter::empty(), state_version).0; let remote_proof = prove_read(remote_backend, &[b"value2"]).unwrap(); let remote_proof = test_compact(remote_proof, &remote_root); // check proof locally @@ -1812,8 +1832,8 @@ mod tests { ); assert_eq!(local_result2, false); // on child trie - let remote_backend = trie_backend::tests::test_trie(); - let remote_root = remote_backend.storage_root(std::iter::empty()).0; + let remote_backend = trie_backend::tests::test_trie(state_version); + let remote_root = remote_backend.storage_root(std::iter::empty(), state_version).0; let remote_proof = prove_child_read(remote_backend, child_info, &[b"value3"]).unwrap(); let remote_proof = test_compact(remote_proof, &remote_root); let local_result1 = read_child_proof_check::( @@ -1877,7 +1897,8 @@ mod tests { storage.insert(Some(child_info), items); } - let trie: InMemoryBackend = storage.clone().into(); + let trie: InMemoryBackend = + (storage.clone(), StateVersion::default()).into(); let trie_root = trie.root().clone(); let backend = crate::ProvingBackend::new(&trie); let mut queries = Vec::new(); @@ -1940,15 +1961,16 @@ mod tests { #[test] fn prove_read_with_size_limit_works() { - let remote_backend = trie_backend::tests::test_trie(); - let remote_root = remote_backend.storage_root(::std::iter::empty()).0; + let state_version = StateVersion::V0; + let remote_backend = trie_backend::tests::test_trie(state_version); + let remote_root = remote_backend.storage_root(::std::iter::empty(), state_version).0; let (proof, count) = prove_range_read_with_size(remote_backend, None, None, 0, None).unwrap(); // Always contains at least some nodes. assert_eq!(proof.into_memory_db::().drain().len(), 3); assert_eq!(count, 1); - let remote_backend = trie_backend::tests::test_trie(); + let remote_backend = trie_backend::tests::test_trie(state_version); let (proof, count) = prove_range_read_with_size(remote_backend, None, None, 800, Some(&[])).unwrap(); assert_eq!(proof.clone().into_memory_db::().drain().len(), 9); @@ -1971,7 +1993,7 @@ mod tests { assert_eq!(results.len() as u32, 101); assert_eq!(completed, false); - let remote_backend = trie_backend::tests::test_trie(); + let remote_backend = trie_backend::tests::test_trie(state_version); let (proof, count) = prove_range_read_with_size(remote_backend, None, None, 50000, Some(&[])).unwrap(); assert_eq!(proof.clone().into_memory_db::().drain().len(), 11); @@ -1989,10 +2011,66 @@ mod tests { assert_eq!(completed, true); } + #[test] + fn inner_state_versioning_switch_proofs() { + let mut state_version = StateVersion::V0; + let (mut mdb, mut root) = trie_backend::tests::test_db(state_version); + { + let mut trie = TrieDBMutV0::from_existing(&mut mdb, &mut root).unwrap(); + trie.insert(b"foo", vec![1u8; 1_000].as_slice()) // big inner hash + .expect("insert failed"); + trie.insert(b"foo2", vec![3u8; 16].as_slice()) // no inner hash + .expect("insert failed"); + trie.insert(b"foo222", vec![5u8; 100].as_slice()) // inner hash + .expect("insert failed"); + } + + let check_proof = |mdb, root, state_version| -> StorageProof { + let remote_backend = TrieBackend::new(mdb, root); + let remote_root = remote_backend.storage_root(std::iter::empty(), state_version).0; + let remote_proof = prove_read(remote_backend, &[b"foo222"]).unwrap(); + // check proof locally + let local_result1 = + read_proof_check::(remote_root, remote_proof.clone(), &[b"foo222"]) + .unwrap(); + // check that results are correct + assert_eq!( + local_result1.into_iter().collect::>(), + vec![(b"foo222".to_vec(), Some(vec![5u8; 100]))], + ); + remote_proof + }; + + let remote_proof = check_proof(mdb.clone(), root.clone(), state_version); + // check full values in proof + assert!(remote_proof.encode().len() > 1_100); + assert!(remote_proof.encoded_size() > 1_100); + let root1 = root.clone(); + + // do switch + state_version = StateVersion::V1; + { + let mut trie = TrieDBMutV1::from_existing(&mut mdb, &mut root).unwrap(); + trie.insert(b"foo222", vec![5u8; 100].as_slice()) // inner hash + .expect("insert failed"); + // update with same value do change + trie.insert(b"foo", vec![1u8; 1000].as_slice()) // inner hash + .expect("insert failed"); + } + let root3 = root.clone(); + assert!(root1 != root3); + let remote_proof = check_proof(mdb.clone(), root.clone(), state_version); + // nodes foo is replaced by its hashed value form. + assert!(remote_proof.encode().len() < 1000); + assert!(remote_proof.encoded_size() < 1000); + assert_eq!(remote_proof.encode().len(), remote_proof.encoded_size()); + } + #[test] fn prove_range_with_child_works() { - let remote_backend = trie_backend::tests::test_trie(); - let remote_root = remote_backend.storage_root(::std::iter::empty()).0; + let state_version = StateVersion::V0; + let remote_backend = trie_backend::tests::test_trie(state_version); + let remote_root = remote_backend.storage_root(std::iter::empty(), state_version).0; let mut start_at = smallvec::SmallVec::<[Vec; 2]>::new(); let trie_backend = remote_backend.as_trie_backend().unwrap(); let max_iter = 1000; @@ -2030,20 +2108,34 @@ mod tests { #[test] fn compact_multiple_child_trie() { + let size_no_inner_hash = compact_multiple_child_trie_inner(StateVersion::V0); + let size_inner_hash = compact_multiple_child_trie_inner(StateVersion::V1); + assert!(size_inner_hash < size_no_inner_hash); + } + fn compact_multiple_child_trie_inner(state_version: StateVersion) -> usize { // this root will be queried let child_info1 = ChildInfo::new_default(b"sub1"); // this root will not be include in proof let child_info2 = ChildInfo::new_default(b"sub2"); // this root will be include in proof let child_info3 = ChildInfo::new_default(b"sub"); - let remote_backend = trie_backend::tests::test_trie(); + let remote_backend = trie_backend::tests::test_trie(state_version); + let long_vec: Vec = (0..1024usize).map(|_| 8u8).collect(); let (remote_root, transaction) = remote_backend.full_storage_root( std::iter::empty(), vec![ ( &child_info1, - vec![(&b"key1"[..], Some(&b"val2"[..])), (&b"key2"[..], Some(&b"val3"[..]))] - .into_iter(), + vec![ + // a inner hashable node + (&b"k"[..], Some(&long_vec[..])), + // need to ensure this is not an inline node + // otherwhise we do not know what is accessed when + // storing proof. + (&b"key1"[..], Some(&vec![5u8; 32][..])), + (&b"key2"[..], Some(&b"val3"[..])), + ] + .into_iter(), ), ( &child_info2, @@ -2057,11 +2149,13 @@ mod tests { ), ] .into_iter(), + state_version, ); let mut remote_storage = remote_backend.into_storage(); remote_storage.consolidate(transaction); let remote_backend = TrieBackend::new(remote_storage, remote_root); let remote_proof = prove_child_read(remote_backend, &child_info1, &[b"key1"]).unwrap(); + let size = remote_proof.encoded_size(); let remote_proof = test_compact(remote_proof, &remote_root); let local_result1 = read_child_proof_check::( remote_root, @@ -2071,11 +2165,13 @@ mod tests { ) .unwrap(); assert_eq!(local_result1.len(), 1); - assert_eq!(local_result1.get(&b"key1"[..]), Some(&Some(b"val2".to_vec()))); + assert_eq!(local_result1.get(&b"key1"[..]), Some(&Some(vec![5u8; 32]))); + size } #[test] fn child_storage_uuid() { + let state_version = StateVersion::V0; let child_info_1 = ChildInfo::new_default(b"sub_test1"); let child_info_2 = ChildInfo::new_default(b"sub_test2"); @@ -2083,12 +2179,12 @@ mod tests { let mut overlay = OverlayedChanges::default(); let mut transaction = { - let backend = test_trie(); + let backend = test_trie(state_version); let mut cache = StorageTransactionCache::default(); let mut ext = Ext::new(&mut overlay, &mut cache, &backend, None); ext.set_child_storage(&child_info_1, b"abc".to_vec(), b"def".to_vec()); ext.set_child_storage(&child_info_2, b"abc".to_vec(), b"def".to_vec()); - ext.storage_root(); + ext.storage_root(state_version); cache.transaction.unwrap() }; let mut duplicate = false; @@ -2108,7 +2204,7 @@ mod tests { b"aaa".to_vec() => b"0".to_vec(), b"bbb".to_vec() => b"".to_vec() ]; - let state = InMemoryBackend::::from(initial); + let state = InMemoryBackend::::from((initial, StateVersion::default())); let backend = state.as_trie_backend().unwrap(); let mut overlay = OverlayedChanges::default(); @@ -2134,12 +2230,13 @@ mod tests { #[test] fn runtime_registered_extensions_are_removed_after_execution() { + let state_version = StateVersion::default(); use sp_externalities::ExternalitiesExt; sp_externalities::decl_extension! { struct DummyExt(u32); } - let backend = trie_backend::tests::test_trie(); + let backend = trie_backend::tests::test_trie(state_version); let mut overlayed_changes = Default::default(); let wasm_code = RuntimeCode::empty(); diff --git a/primitives/state-machine/src/overlayed_changes/mod.rs b/primitives/state-machine/src/overlayed_changes/mod.rs index b7a535792aae..659b52e0a708 100644 --- a/primitives/state-machine/src/overlayed_changes/mod.rs +++ b/primitives/state-machine/src/overlayed_changes/mod.rs @@ -27,7 +27,7 @@ use hash_db::Hasher; pub use offchain::OffchainOverlayedChanges; use sp_core::{ offchain::OffchainOverlayedChange, - storage::{well_known_keys::EXTRINSIC_INDEX, ChildInfo}, + storage::{well_known_keys::EXTRINSIC_INDEX, ChildInfo, StateVersion}, }; #[cfg(feature = "std")] use sp_externalities::{Extension, Extensions}; @@ -502,11 +502,12 @@ impl OverlayedChanges { backend: &B, parent_hash: H::Out, mut cache: StorageTransactionCache, + state_version: StateVersion, ) -> Result, DefaultError> where H::Out: Ord + Encode + 'static, { - self.drain_storage_changes(backend, parent_hash, &mut cache) + self.drain_storage_changes(backend, parent_hash, &mut cache, state_version) } /// Drain all changes into a [`StorageChanges`] instance. Leave empty overlay in place. @@ -515,13 +516,14 @@ impl OverlayedChanges { backend: &B, _parent_hash: H::Out, mut cache: &mut StorageTransactionCache, + state_version: StateVersion, ) -> Result, DefaultError> where H::Out: Ord + Encode + 'static, { // If the transaction does not exist, we generate it. if cache.transaction.is_none() { - self.storage_root(backend, &mut cache); + self.storage_root(backend, &mut cache, state_version); } let (transaction, transaction_storage_root) = cache @@ -580,6 +582,7 @@ impl OverlayedChanges { &self, backend: &B, cache: &mut StorageTransactionCache, + state_version: StateVersion, ) -> H::Out where H::Out: Ord + Encode, @@ -589,7 +592,7 @@ impl OverlayedChanges { (info, changes.map(|(k, v)| (&k[..], v.value().map(|v| &v[..])))) }); - let (root, transaction) = backend.full_storage_root(delta, child_delta); + let (root, transaction) = backend.full_storage_root(delta, child_delta, state_version); cache.transaction = Some(transaction); cache.transaction_storage_root = Some(root); @@ -830,6 +833,7 @@ mod tests { #[test] fn overlayed_storage_root_works() { + let state_version = StateVersion::default(); let initial: BTreeMap<_, _> = vec![ (b"doe".to_vec(), b"reindeer".to_vec()), (b"dog".to_vec(), b"puppyXXX".to_vec()), @@ -838,7 +842,7 @@ mod tests { ] .into_iter() .collect(); - let backend = InMemoryBackend::::from(initial); + let backend = InMemoryBackend::::from((initial, state_version)); let mut overlay = OverlayedChanges::default(); overlay.start_transaction(); @@ -856,7 +860,7 @@ mod tests { const ROOT: [u8; 32] = hex!("39245109cef3758c2eed2ccba8d9b370a917850af3824bc8348d505df2c298fa"); - assert_eq!(&ext.storage_root()[..], &ROOT); + assert_eq!(&ext.storage_root(state_version)[..], &ROOT); } #[test] diff --git a/primitives/state-machine/src/proving_backend.rs b/primitives/state-machine/src/proving_backend.rs index a354adaf697d..4e1fd64da2b8 100644 --- a/primitives/state-machine/src/proving_backend.rs +++ b/primitives/state-machine/src/proving_backend.rs @@ -26,14 +26,11 @@ use codec::{Codec, Decode, Encode}; use hash_db::{HashDB, Hasher, Prefix, EMPTY_PREFIX}; use log::debug; use parking_lot::RwLock; -use sp_core::storage::ChildInfo; +use sp_core::storage::{ChildInfo, StateVersion}; +pub use sp_trie::trie_types::TrieError; use sp_trie::{ empty_child_trie_root, read_child_trie_value_with, read_trie_value_with, record_all_keys, - MemoryDB, StorageProof, -}; -pub use sp_trie::{ - trie_types::{Layout, TrieError}, - Recorder, + LayoutV1, MemoryDB, Recorder, StorageProof, }; use std::{ collections::{hash_map::Entry, HashMap}, @@ -59,7 +56,8 @@ where let map_e = |e| format!("Trie lookup error: {}", e); - read_trie_value_with::, _, Ephemeral>( + // V1 is equivalent to V0 on read. + read_trie_value_with::, _, Ephemeral>( &eph, self.backend.root(), key, @@ -78,14 +76,16 @@ where let root = self .storage(storage_key)? .and_then(|r| Decode::decode(&mut &r[..]).ok()) - .unwrap_or_else(|| empty_child_trie_root::>()); + // V1 is equivalent to V0 on empty trie + .unwrap_or_else(|| empty_child_trie_root::>()); let mut read_overlay = S::Overlay::default(); let eph = Ephemeral::new(self.backend.backend_storage(), &mut read_overlay); let map_e = |e| format!("Trie lookup error: {}", e); - read_child_trie_value_with::, _, _>( + // V1 is equivalent to V0 on read + read_child_trie_value_with::, _, _>( child_info.keyspace(), &eph, &root.as_ref(), @@ -102,7 +102,8 @@ where let mut iter = move || -> Result<(), Box>> { let root = self.backend.root(); - record_all_keys::, _>(&eph, root, &mut *self.proof_recorder) + // V1 and V is equivalent to V0 on read and recorder is key read. + record_all_keys::, _>(&eph, root, &mut *self.proof_recorder) }; if let Err(e) = iter() { @@ -338,22 +339,24 @@ where fn storage_root<'b>( &self, delta: impl Iterator)>, + state_version: StateVersion, ) -> (H::Out, Self::Transaction) where H::Out: Ord, { - self.0.storage_root(delta) + self.0.storage_root(delta, state_version) } fn child_storage_root<'b>( &self, child_info: &ChildInfo, delta: impl Iterator)>, + state_version: StateVersion, ) -> (H::Out, bool, Self::Transaction) where H::Out: Ord, { - self.0.child_storage_root(child_info, delta) + self.0.child_storage_root(child_info, delta, state_version) } fn register_overlay_stats(&self, _stats: &crate::stats::StateMachineStats) {} @@ -401,13 +404,21 @@ mod tests { #[test] fn proof_is_empty_until_value_is_read() { - let trie_backend = test_trie(); + proof_is_empty_until_value_is_read_inner(StateVersion::V0); + proof_is_empty_until_value_is_read_inner(StateVersion::V1); + } + fn proof_is_empty_until_value_is_read_inner(test_hash: StateVersion) { + let trie_backend = test_trie(test_hash); assert!(test_proving(&trie_backend).extract_proof().is_empty()); } #[test] fn proof_is_non_empty_after_value_is_read() { - let trie_backend = test_trie(); + proof_is_non_empty_after_value_is_read_inner(StateVersion::V0); + proof_is_non_empty_after_value_is_read_inner(StateVersion::V1); + } + fn proof_is_non_empty_after_value_is_read_inner(test_hash: StateVersion) { + let trie_backend = test_trie(test_hash); let backend = test_proving(&trie_backend); assert_eq!(backend.storage(b"key").unwrap(), Some(b"value".to_vec())); assert!(!backend.extract_proof().is_empty()); @@ -425,58 +436,82 @@ mod tests { #[test] fn passes_through_backend_calls() { - let trie_backend = test_trie(); + passes_through_backend_calls_inner(StateVersion::V0); + passes_through_backend_calls_inner(StateVersion::V1); + } + fn passes_through_backend_calls_inner(state_version: StateVersion) { + let trie_backend = test_trie(state_version); let proving_backend = test_proving(&trie_backend); assert_eq!(trie_backend.storage(b"key").unwrap(), proving_backend.storage(b"key").unwrap()); assert_eq!(trie_backend.pairs(), proving_backend.pairs()); - let (trie_root, mut trie_mdb) = trie_backend.storage_root(std::iter::empty()); - let (proving_root, mut proving_mdb) = proving_backend.storage_root(std::iter::empty()); + let (trie_root, mut trie_mdb) = + trie_backend.storage_root(std::iter::empty(), state_version); + let (proving_root, mut proving_mdb) = + proving_backend.storage_root(std::iter::empty(), state_version); assert_eq!(trie_root, proving_root); assert_eq!(trie_mdb.drain(), proving_mdb.drain()); } #[test] - fn proof_recorded_and_checked() { - let contents = (0..64).map(|i| (vec![i], Some(vec![i]))).collect::>(); + fn proof_recorded_and_checked_top() { + proof_recorded_and_checked_inner(StateVersion::V0); + proof_recorded_and_checked_inner(StateVersion::V1); + } + fn proof_recorded_and_checked_inner(state_version: StateVersion) { + let size_content = 34; // above hashable value treshold. + let value_range = 0..64; + let contents = value_range + .clone() + .map(|i| (vec![i], Some(vec![i; size_content]))) + .collect::>(); let in_memory = InMemoryBackend::::default(); - let in_memory = in_memory.update(vec![(None, contents)]); - let in_memory_root = in_memory.storage_root(::std::iter::empty()).0; - (0..64).for_each(|i| assert_eq!(in_memory.storage(&[i]).unwrap().unwrap(), vec![i])); + let in_memory = in_memory.update(vec![(None, contents)], state_version); + let in_memory_root = in_memory.storage_root(std::iter::empty(), state_version).0; + value_range.clone().for_each(|i| { + assert_eq!(in_memory.storage(&[i]).unwrap().unwrap(), vec![i; size_content]) + }); let trie = in_memory.as_trie_backend().unwrap(); - let trie_root = trie.storage_root(::std::iter::empty()).0; + let trie_root = trie.storage_root(std::iter::empty(), state_version).0; assert_eq!(in_memory_root, trie_root); - (0..64).for_each(|i| assert_eq!(trie.storage(&[i]).unwrap().unwrap(), vec![i])); + value_range + .clone() + .for_each(|i| assert_eq!(trie.storage(&[i]).unwrap().unwrap(), vec![i; size_content])); let proving = ProvingBackend::new(trie); - assert_eq!(proving.storage(&[42]).unwrap().unwrap(), vec![42]); + assert_eq!(proving.storage(&[42]).unwrap().unwrap(), vec![42; size_content]); let proof = proving.extract_proof(); let proof_check = create_proof_check_backend::(in_memory_root.into(), proof).unwrap(); - assert_eq!(proof_check.storage(&[42]).unwrap().unwrap(), vec![42]); + assert_eq!(proof_check.storage(&[42]).unwrap().unwrap(), vec![42; size_content]); } #[test] fn proof_recorded_and_checked_with_child() { + proof_recorded_and_checked_with_child_inner(StateVersion::V0); + proof_recorded_and_checked_with_child_inner(StateVersion::V1); + } + fn proof_recorded_and_checked_with_child_inner(state_version: StateVersion) { let child_info_1 = ChildInfo::new_default(b"sub1"); let child_info_2 = ChildInfo::new_default(b"sub2"); let child_info_1 = &child_info_1; let child_info_2 = &child_info_2; let contents = vec![ - (None, (0..64).map(|i| (vec![i], Some(vec![i]))).collect()), + (None, (0..64).map(|i| (vec![i], Some(vec![i]))).collect::>()), (Some(child_info_1.clone()), (28..65).map(|i| (vec![i], Some(vec![i]))).collect()), (Some(child_info_2.clone()), (10..15).map(|i| (vec![i], Some(vec![i]))).collect()), ]; let in_memory = InMemoryBackend::::default(); - let in_memory = in_memory.update(contents); + let in_memory = in_memory.update(contents, state_version); let child_storage_keys = vec![child_info_1.to_owned(), child_info_2.to_owned()]; let in_memory_root = in_memory .full_storage_root( std::iter::empty(), child_storage_keys.iter().map(|k| (k, std::iter::empty())), + state_version, ) .0; (0..64).for_each(|i| assert_eq!(in_memory.storage(&[i]).unwrap().unwrap(), vec![i])); @@ -488,7 +523,7 @@ mod tests { }); let trie = in_memory.as_trie_backend().unwrap(); - let trie_root = trie.storage_root(std::iter::empty()).0; + let trie_root = trie.storage_root(std::iter::empty(), state_version).0; assert_eq!(in_memory_root, trie_root); (0..64).for_each(|i| assert_eq!(trie.storage(&[i]).unwrap().unwrap(), vec![i])); @@ -516,7 +551,11 @@ mod tests { #[test] fn storage_proof_encoded_size_estimation_works() { - let trie_backend = test_trie(); + storage_proof_encoded_size_estimation_works_inner(StateVersion::V0); + storage_proof_encoded_size_estimation_works_inner(StateVersion::V1); + } + fn storage_proof_encoded_size_estimation_works_inner(state_version: StateVersion) { + let trie_backend = test_trie(state_version); let backend = test_proving(&trie_backend); let check_estimation = diff --git a/primitives/state-machine/src/read_only.rs b/primitives/state-machine/src/read_only.rs index b3e43d4c46e7..2039b39a0603 100644 --- a/primitives/state-machine/src/read_only.rs +++ b/primitives/state-machine/src/read_only.rs @@ -21,7 +21,7 @@ use crate::{Backend, StorageKey, StorageValue}; use codec::Encode; use hash_db::Hasher; use sp_core::{ - storage::{ChildInfo, TrackedStorageKey}, + storage::{ChildInfo, StateVersion, TrackedStorageKey}, traits::Externalities, Blake2Hasher, }; @@ -145,11 +145,15 @@ impl<'a, H: Hasher, B: 'a + Backend> Externalities for ReadOnlyExternalities< unimplemented!("storage_append is not supported in ReadOnlyExternalities") } - fn storage_root(&mut self) -> Vec { + fn storage_root(&mut self, _state_version: StateVersion) -> Vec { unimplemented!("storage_root is not supported in ReadOnlyExternalities") } - fn child_storage_root(&mut self, _child_info: &ChildInfo) -> Vec { + fn child_storage_root( + &mut self, + _child_info: &ChildInfo, + _state_version: StateVersion, + ) -> Vec { unimplemented!("child_storage_root is not supported in ReadOnlyExternalities") } diff --git a/primitives/state-machine/src/testing.rs b/primitives/state-machine/src/testing.rs index 890137c43d88..dbb0a25d3c39 100644 --- a/primitives/state-machine/src/testing.rs +++ b/primitives/state-machine/src/testing.rs @@ -32,7 +32,7 @@ use sp_core::{ offchain::testing::TestPersistentOffchainDB, storage::{ well_known_keys::{is_child_storage_key, CODE}, - Storage, + StateVersion, Storage, }, testing::TaskExecutor, traits::TaskExecutorExt, @@ -54,6 +54,8 @@ where pub backend: InMemoryBackend, /// Extensions. pub extensions: Extensions, + /// State version to use during tests. + pub state_version: StateVersion, } impl TestExternalities @@ -72,18 +74,31 @@ where /// Create a new instance of `TestExternalities` with storage. pub fn new(storage: Storage) -> Self { - Self::new_with_code(&[], storage) + Self::new_with_code_and_state(&[], storage, Default::default()) + } + + /// Create a new instance of `TestExternalities` with storage for a given state version. + pub fn new_with_state_version(storage: Storage, state_version: StateVersion) -> Self { + Self::new_with_code_and_state(&[], storage, state_version) } /// New empty test externalities. pub fn new_empty() -> Self { - Self::new_with_code(&[], Storage::default()) + Self::new_with_code_and_state(&[], Storage::default(), Default::default()) } /// Create a new instance of `TestExternalities` with code and storage. - pub fn new_with_code(code: &[u8], mut storage: Storage) -> Self { - let overlay = OverlayedChanges::default(); + pub fn new_with_code(code: &[u8], storage: Storage) -> Self { + Self::new_with_code_and_state(code, storage, Default::default()) + } + /// Create a new instance of `TestExternalities` with code and storage for a given state + /// version. + pub fn new_with_code_and_state( + code: &[u8], + mut storage: Storage, + state_version: StateVersion, + ) -> Self { assert!(storage.top.keys().all(|key| !is_child_storage_key(key))); assert!(storage.children_default.keys().all(|key| is_child_storage_key(key))); @@ -94,12 +109,15 @@ where let offchain_db = TestPersistentOffchainDB::new(); + let backend = (storage, state_version).into(); + TestExternalities { - overlay, + overlay: OverlayedChanges::default(), offchain_db, extensions, - backend: storage.into(), + backend, storage_transaction_cache: Default::default(), + state_version, } } @@ -120,14 +138,14 @@ where /// Insert key/value into backend pub fn insert(&mut self, k: StorageKey, v: StorageValue) { - self.backend.insert(vec![(None, vec![(k, Some(v))])]); + self.backend.insert(vec![(None, vec![(k, Some(v))])], self.state_version); } /// Insert key/value into backend. /// /// This only supports inserting keys in child tries. pub fn insert_child(&mut self, c: sp_core::storage::ChildInfo, k: StorageKey, v: StorageValue) { - self.backend.insert(vec![(Some(c), vec![(k, Some(v))])]); + self.backend.insert(vec![(Some(c), vec![(k, Some(v))])], self.state_version); } /// Registers the given extension for this instance. @@ -151,7 +169,7 @@ where )) } - self.backend.update(transaction) + self.backend.update(transaction, self.state_version) } /// Commit all pending changes to the underlying backend. @@ -164,6 +182,7 @@ where &self.backend, Default::default(), &mut Default::default(), + self.state_version, )?; self.backend @@ -240,7 +259,8 @@ where H::Out: Ord + 'static + codec::Codec, { fn default() -> Self { - Self::new(Default::default()) + // default to default version. + Self::new_with_state_version(Storage::default(), Default::default()) } } @@ -249,7 +269,16 @@ where H::Out: Ord + 'static + codec::Codec, { fn from(storage: Storage) -> Self { - Self::new(storage) + Self::new_with_state_version(storage, Default::default()) + } +} + +impl From<(Storage, StateVersion)> for TestExternalities +where + H::Out: Ord + 'static + codec::Codec, +{ + fn from((storage, state_version): (Storage, StateVersion)) -> Self { + Self::new_with_state_version(storage, state_version) } } @@ -309,14 +338,15 @@ mod tests { #[test] fn commit_should_work() { - let mut ext = TestExternalities::::default(); + let storage = Storage::default(); // avoid adding the trie threshold. + let mut ext = TestExternalities::::from((storage, Default::default())); let mut ext = ext.ext(); ext.set_storage(b"doe".to_vec(), b"reindeer".to_vec()); ext.set_storage(b"dog".to_vec(), b"puppy".to_vec()); ext.set_storage(b"dogglesworth".to_vec(), b"cat".to_vec()); let root = H256::from(hex!("ed4d8c799d996add422395a6abd7545491d40bd838d738afafa1b8a4de625489")); - assert_eq!(H256::from_slice(ext.storage_root().as_slice()), root); + assert_eq!(H256::from_slice(ext.storage_root(Default::default()).as_slice()), root); } #[test] diff --git a/primitives/state-machine/src/trie_backend.rs b/primitives/state-machine/src/trie_backend.rs index 7f9a02e05525..616a5512ea40 100644 --- a/primitives/state-machine/src/trie_backend.rs +++ b/primitives/state-machine/src/trie_backend.rs @@ -24,12 +24,12 @@ use crate::{ }; use codec::{Codec, Decode}; use hash_db::Hasher; -use sp_core::storage::{ChildInfo, ChildType}; +use sp_core::storage::{ChildInfo, ChildType, StateVersion}; use sp_std::{boxed::Box, vec::Vec}; use sp_trie::{ child_delta_trie_root, delta_trie_root, empty_child_trie_root, - trie_types::{Layout, TrieDB, TrieError}, - Trie, + trie_types::{TrieDB, TrieError}, + LayoutV0, LayoutV1, Trie, }; /// Patricia trie-based backend. Transaction type is an overlay of changes to commit. @@ -186,6 +186,7 @@ where fn storage_root<'a>( &self, delta: impl Iterator)>, + state_version: StateVersion, ) -> (H::Out, Self::Transaction) where H::Out: Ord, @@ -195,8 +196,14 @@ where { let mut eph = Ephemeral::new(self.essence.backend_storage(), &mut write_overlay); - - match delta_trie_root::, _, _, _, _, _>(&mut eph, root, delta) { + let res = match state_version { + StateVersion::V0 => + delta_trie_root::, _, _, _, _, _>(&mut eph, root, delta), + StateVersion::V1 => + delta_trie_root::, _, _, _, _, _>(&mut eph, root, delta), + }; + + match res { Ok(ret) => root = ret, Err(e) => warn!(target: "trie", "Failed to write to trie: {}", e), } @@ -209,14 +216,14 @@ where &self, child_info: &ChildInfo, delta: impl Iterator)>, + state_version: StateVersion, ) -> (H::Out, bool, Self::Transaction) where H::Out: Ord, { let default_root = match child_info.child_type() { - ChildType::ParentKeyId => empty_child_trie_root::>(), + ChildType::ParentKeyId => empty_child_trie_root::>(), }; - let mut write_overlay = S::Overlay::default(); let prefixed_storage_key = child_info.prefixed_storage_key(); let mut root = match self.storage(prefixed_storage_key.as_slice()) { @@ -231,13 +238,20 @@ where { let mut eph = Ephemeral::new(self.essence.backend_storage(), &mut write_overlay); - - match child_delta_trie_root::, _, _, _, _, _, _>( - child_info.keyspace(), - &mut eph, - root, - delta, - ) { + match match state_version { + StateVersion::V0 => child_delta_trie_root::, _, _, _, _, _, _>( + child_info.keyspace(), + &mut eph, + root, + delta, + ), + StateVersion::V1 => child_delta_trie_root::, _, _, _, _, _, _>( + child_info.keyspace(), + &mut eph, + root, + delta, + ), + } { Ok(ret) => root = ret, Err(e) => warn!(target: "trie", "Failed to write to trie: {}", e), } @@ -269,52 +283,91 @@ pub mod tests { use codec::Encode; use sp_core::H256; use sp_runtime::traits::BlakeTwo256; - use sp_trie::{trie_types::TrieDBMut, KeySpacedDBMut, PrefixedMemoryDB, TrieMut}; + use sp_trie::{ + trie_types::{TrieDBMutV0, TrieDBMutV1}, + KeySpacedDBMut, PrefixedMemoryDB, TrieMut, + }; use std::{collections::HashSet, iter}; const CHILD_KEY_1: &[u8] = b"sub1"; - fn test_db() -> (PrefixedMemoryDB, H256) { + pub(crate) fn test_db(state_version: StateVersion) -> (PrefixedMemoryDB, H256) { let child_info = ChildInfo::new_default(CHILD_KEY_1); let mut root = H256::default(); let mut mdb = PrefixedMemoryDB::::default(); { let mut mdb = KeySpacedDBMut::new(&mut mdb, child_info.keyspace()); - let mut trie = TrieDBMut::new(&mut mdb, &mut root); - trie.insert(b"value3", &[142; 33]).expect("insert failed"); - trie.insert(b"value4", &[124; 33]).expect("insert failed"); + match state_version { + StateVersion::V0 => { + let mut trie = TrieDBMutV0::new(&mut mdb, &mut root); + trie.insert(b"value3", &[142; 33]).expect("insert failed"); + trie.insert(b"value4", &[124; 33]).expect("insert failed"); + }, + StateVersion::V1 => { + let mut trie = TrieDBMutV1::new(&mut mdb, &mut root); + trie.insert(b"value3", &[142; 33]).expect("insert failed"); + trie.insert(b"value4", &[124; 33]).expect("insert failed"); + }, + }; }; { let mut sub_root = Vec::new(); root.encode_to(&mut sub_root); - let mut trie = TrieDBMut::new(&mut mdb, &mut root); - trie.insert(child_info.prefixed_storage_key().as_slice(), &sub_root[..]) - .expect("insert failed"); - trie.insert(b"key", b"value").expect("insert failed"); - trie.insert(b"value1", &[42]).expect("insert failed"); - trie.insert(b"value2", &[24]).expect("insert failed"); - trie.insert(b":code", b"return 42").expect("insert failed"); - for i in 128u8..255u8 { - trie.insert(&[i], &[i]).unwrap(); + + fn build( + mut trie: sp_trie::TrieDBMut, + child_info: &ChildInfo, + sub_root: &[u8], + ) { + trie.insert(child_info.prefixed_storage_key().as_slice(), sub_root) + .expect("insert failed"); + trie.insert(b"key", b"value").expect("insert failed"); + trie.insert(b"value1", &[42]).expect("insert failed"); + trie.insert(b"value2", &[24]).expect("insert failed"); + trie.insert(b":code", b"return 42").expect("insert failed"); + for i in 128u8..255u8 { + trie.insert(&[i], &[i]).unwrap(); + } } + + match state_version { + StateVersion::V0 => { + let trie = TrieDBMutV0::new(&mut mdb, &mut root); + build(trie, &child_info, &sub_root[..]) + }, + StateVersion::V1 => { + let trie = TrieDBMutV1::new(&mut mdb, &mut root); + build(trie, &child_info, &sub_root[..]) + }, + }; } (mdb, root) } - pub(crate) fn test_trie() -> TrieBackend, BlakeTwo256> { - let (mdb, root) = test_db(); + pub(crate) fn test_trie( + hashed_value: StateVersion, + ) -> TrieBackend, BlakeTwo256> { + let (mdb, root) = test_db(hashed_value); TrieBackend::new(mdb, root) } #[test] fn read_from_storage_returns_some() { - assert_eq!(test_trie().storage(b"key").unwrap(), Some(b"value".to_vec())); + read_from_storage_returns_some_inner(StateVersion::V0); + read_from_storage_returns_some_inner(StateVersion::V1); + } + fn read_from_storage_returns_some_inner(state_version: StateVersion) { + assert_eq!(test_trie(state_version).storage(b"key").unwrap(), Some(b"value".to_vec())); } #[test] fn read_from_child_storage_returns_some() { - let test_trie = test_trie(); + read_from_child_storage_returns_some_inner(StateVersion::V0); + read_from_child_storage_returns_some_inner(StateVersion::V1); + } + fn read_from_child_storage_returns_some_inner(state_version: StateVersion) { + let test_trie = test_trie(state_version); assert_eq!( test_trie .child_storage(&ChildInfo::new_default(CHILD_KEY_1), b"value3") @@ -341,12 +394,20 @@ pub mod tests { #[test] fn read_from_storage_returns_none() { - assert_eq!(test_trie().storage(b"non-existing-key").unwrap(), None); + read_from_storage_returns_none_inner(StateVersion::V0); + read_from_storage_returns_none_inner(StateVersion::V1); + } + fn read_from_storage_returns_none_inner(state_version: StateVersion) { + assert_eq!(test_trie(state_version).storage(b"non-existing-key").unwrap(), None); } #[test] fn pairs_are_not_empty_on_non_empty_storage() { - assert!(!test_trie().pairs().is_empty()); + pairs_are_not_empty_on_non_empty_storage_inner(StateVersion::V0); + pairs_are_not_empty_on_non_empty_storage_inner(StateVersion::V1); + } + fn pairs_are_not_empty_on_non_empty_storage_inner(state_version: StateVersion) { + assert!(!test_trie(state_version).pairs().is_empty()); } #[test] @@ -361,25 +422,35 @@ pub mod tests { #[test] fn storage_root_is_non_default() { - assert!(test_trie().storage_root(iter::empty()).0 != H256::repeat_byte(0)); + storage_root_is_non_default_inner(StateVersion::V0); + storage_root_is_non_default_inner(StateVersion::V1); } - - #[test] - fn storage_root_transaction_is_empty() { - assert!(test_trie().storage_root(iter::empty()).1.drain().is_empty()); + fn storage_root_is_non_default_inner(state_version: StateVersion) { + assert!( + test_trie(state_version).storage_root(iter::empty(), state_version).0 != + H256::repeat_byte(0) + ); } #[test] fn storage_root_transaction_is_non_empty() { - let (new_root, mut tx) = - test_trie().storage_root(iter::once((&b"new-key"[..], Some(&b"new-value"[..])))); + storage_root_transaction_is_non_empty_inner(StateVersion::V0); + storage_root_transaction_is_non_empty_inner(StateVersion::V1); + } + fn storage_root_transaction_is_non_empty_inner(state_version: StateVersion) { + let (new_root, mut tx) = test_trie(state_version) + .storage_root(iter::once((&b"new-key"[..], Some(&b"new-value"[..]))), state_version); assert!(!tx.drain().is_empty()); - assert!(new_root != test_trie().storage_root(iter::empty()).0); + assert!(new_root != test_trie(state_version).storage_root(iter::empty(), state_version).0); } #[test] fn prefix_walking_works() { - let trie = test_trie(); + prefix_walking_works_inner(StateVersion::V0); + prefix_walking_works_inner(StateVersion::V1); + } + fn prefix_walking_works_inner(state_version: StateVersion) { + let trie = test_trie(state_version); let mut seen = HashSet::new(); trie.for_keys_with_prefix(b"value", |key| { diff --git a/primitives/state-machine/src/trie_backend_essence.rs b/primitives/state-machine/src/trie_backend_essence.rs index 6c575f0d76bc..945fd05ebffb 100644 --- a/primitives/state-machine/src/trie_backend_essence.rs +++ b/primitives/state-machine/src/trie_backend_essence.rs @@ -20,20 +20,23 @@ use crate::{backend::Consolidate, debug, warn, StorageKey, StorageValue}; use codec::Encode; -use hash_db::{self, Hasher, Prefix}; +use hash_db::{self, AsHashDB, HashDB, HashDBRef, Hasher, Prefix}; #[cfg(feature = "std")] use parking_lot::RwLock; use sp_core::storage::ChildInfo; use sp_std::{boxed::Box, vec::Vec}; use sp_trie::{ empty_child_trie_root, read_child_trie_value, read_trie_value, - trie_types::{Layout, TrieDB, TrieError}, - DBValue, KeySpacedDB, MemoryDB, PrefixedMemoryDB, Trie, TrieDBIterator, + trie_types::{TrieDB, TrieError}, + DBValue, KeySpacedDB, PrefixedMemoryDB, Trie, TrieDBIterator, TrieDBKeyIterator, }; #[cfg(feature = "std")] use std::collections::HashMap; #[cfg(feature = "std")] use std::sync::Arc; +// In this module, we only use layout for read operation and empty root, +// where V1 and V0 are equivalent. +use sp_trie::LayoutV1 as Layout; #[cfg(not(feature = "std"))] macro_rules! format { @@ -178,7 +181,7 @@ where child_info: Option<&ChildInfo>, key: &[u8], ) -> Result> { - let dyn_eph: &dyn hash_db::HashDBRef<_, _>; + let dyn_eph: &dyn HashDBRef<_, _>; let keyspace_eph; if let Some(child_info) = child_info.as_ref() { keyspace_eph = KeySpacedDB::new(self, child_info.keyspace()); @@ -189,7 +192,7 @@ where let trie = TrieDB::::new(dyn_eph, root).map_err(|e| format!("TrieDB creation error: {}", e))?; - let mut iter = trie.iter().map_err(|e| format!("TrieDB iteration error: {}", e))?; + let mut iter = trie.key_iter().map_err(|e| format!("TrieDB iteration error: {}", e))?; // The key just after the one given in input, basically `key++0`. // Note: We are sure this is the next key if: @@ -205,7 +208,7 @@ where let next_element = iter.next(); let next_key = if let Some(next_element) = next_element { - let (next_key, _) = + let next_key = next_element.map_err(|e| format!("TrieDB iterator next error: {}", e))?; Some(next_key) } else { @@ -291,17 +294,7 @@ where &self.root }; - let _ = self.trie_iter_inner( - root, - prefix, - |k, _v| { - f(&k); - true - }, - child_info, - None, - false, - ); + self.trie_iter_key_inner(root, prefix, |k| f(k), child_info) } /// Execute given closure for all keys starting with prefix. @@ -320,32 +313,70 @@ where }; let mut root = H::Out::default(); root.as_mut().copy_from_slice(&root_vec); - let _ = self.trie_iter_inner( + self.trie_iter_key_inner( &root, Some(prefix), - |k, _v| { - f(&k); + |k| { + f(k); true }, Some(child_info), - None, - false, - ); + ) } /// Execute given closure for all keys starting with prefix. pub fn for_keys_with_prefix(&self, prefix: &[u8], mut f: F) { - let _ = self.trie_iter_inner( + self.trie_iter_key_inner( &self.root, Some(prefix), - |k, _v| { - f(&k); + |k| { + f(k); true }, None, - None, - false, - ); + ) + } + + fn trie_iter_key_inner bool>( + &self, + root: &H::Out, + prefix: Option<&[u8]>, + mut f: F, + child_info: Option<&ChildInfo>, + ) { + let mut iter = move |db| -> sp_std::result::Result<(), Box>> { + let trie = TrieDB::::new(db, root)?; + let iter = if let Some(prefix) = prefix.as_ref() { + TrieDBKeyIterator::new_prefixed(&trie, prefix)? + } else { + TrieDBKeyIterator::new(&trie)? + }; + + for x in iter { + let key = x?; + + debug_assert!(prefix + .as_ref() + .map(|prefix| key.starts_with(prefix)) + .unwrap_or(true)); + + if !f(&key) { + break + } + } + + Ok(()) + }; + + let result = if let Some(child_info) = child_info { + let db = KeySpacedDB::new(self, child_info.keyspace()); + iter(&db) + } else { + iter(self) + }; + if let Err(e) = result { + debug!(target: "trie", "Error while iterating by prefix: {}", e); + } } fn trie_iter_inner, Vec) -> bool>( @@ -414,13 +445,13 @@ pub(crate) struct Ephemeral<'a, S: 'a + TrieBackendStorage, H: 'a + Hasher> { overlay: &'a mut S::Overlay, } -impl<'a, S: 'a + TrieBackendStorage, H: 'a + Hasher> hash_db::AsHashDB +impl<'a, S: 'a + TrieBackendStorage, H: 'a + Hasher> AsHashDB for Ephemeral<'a, S, H> { - fn as_hash_db<'b>(&'b self) -> &'b (dyn hash_db::HashDB + 'b) { + fn as_hash_db<'b>(&'b self) -> &'b (dyn HashDB + 'b) { self } - fn as_hash_db_mut<'b>(&'b mut self) -> &'b mut (dyn hash_db::HashDB + 'b) { + fn as_hash_db_mut<'b>(&'b mut self) -> &'b mut (dyn HashDB + 'b) { self } } @@ -435,7 +466,7 @@ impl<'a, S: 'a + TrieBackendStorage, H: Hasher> hash_db::HashDB for Ephemeral<'a, S, H> { fn get(&self, key: &H::Out, prefix: Prefix) -> Option { - if let Some(val) = hash_db::HashDB::get(self.overlay, key, prefix) { + if let Some(val) = HashDB::get(self.overlay, key, prefix) { Some(val) } else { match self.storage.get(&key, prefix) { @@ -449,38 +480,37 @@ impl<'a, S: 'a + TrieBackendStorage, H: Hasher> hash_db::HashDB } fn contains(&self, key: &H::Out, prefix: Prefix) -> bool { - hash_db::HashDB::get(self, key, prefix).is_some() + HashDB::get(self, key, prefix).is_some() } fn insert(&mut self, prefix: Prefix, value: &[u8]) -> H::Out { - hash_db::HashDB::insert(self.overlay, prefix, value) + HashDB::insert(self.overlay, prefix, value) } fn emplace(&mut self, key: H::Out, prefix: Prefix, value: DBValue) { - hash_db::HashDB::emplace(self.overlay, key, prefix, value) + HashDB::emplace(self.overlay, key, prefix, value) } fn remove(&mut self, key: &H::Out, prefix: Prefix) { - hash_db::HashDB::remove(self.overlay, key, prefix) + HashDB::remove(self.overlay, key, prefix) } } -impl<'a, S: 'a + TrieBackendStorage, H: Hasher> hash_db::HashDBRef - for Ephemeral<'a, S, H> -{ +impl<'a, S: 'a + TrieBackendStorage, H: Hasher> HashDBRef for Ephemeral<'a, S, H> { fn get(&self, key: &H::Out, prefix: Prefix) -> Option { - hash_db::HashDB::get(self, key, prefix) + HashDB::get(self, key, prefix) } fn contains(&self, key: &H::Out, prefix: Prefix) -> bool { - hash_db::HashDB::contains(self, key, prefix) + HashDB::contains(self, key, prefix) } } /// Key-value pairs storage that is used by trie backend essence. pub trait TrieBackendStorage: Send + Sync { /// Type of in-memory overlay. - type Overlay: hash_db::HashDB + Default + Consolidate; + type Overlay: HashDB + Default + Consolidate; + /// Get the value stored at key. fn get(&self, key: &H::Out, prefix: Prefix) -> Result>; } @@ -495,35 +525,28 @@ impl TrieBackendStorage for Arc> { } } -// This implementation is used by test storage trie clients. -impl TrieBackendStorage for PrefixedMemoryDB { - type Overlay = PrefixedMemoryDB; - - fn get(&self, key: &H::Out, prefix: Prefix) -> Result> { - Ok(hash_db::HashDB::get(self, key, prefix)) - } -} - -impl TrieBackendStorage for MemoryDB { - type Overlay = MemoryDB; +impl TrieBackendStorage for sp_trie::GenericMemoryDB +where + H: Hasher, + KF: sp_trie::KeyFunction + Send + Sync, +{ + type Overlay = Self; fn get(&self, key: &H::Out, prefix: Prefix) -> Result> { Ok(hash_db::HashDB::get(self, key, prefix)) } } -impl, H: Hasher> hash_db::AsHashDB - for TrieBackendEssence -{ - fn as_hash_db<'b>(&'b self) -> &'b (dyn hash_db::HashDB + 'b) { +impl, H: Hasher> AsHashDB for TrieBackendEssence { + fn as_hash_db<'b>(&'b self) -> &'b (dyn HashDB + 'b) { self } - fn as_hash_db_mut<'b>(&'b mut self) -> &'b mut (dyn hash_db::HashDB + 'b) { + fn as_hash_db_mut<'b>(&'b mut self) -> &'b mut (dyn HashDB + 'b) { self } } -impl, H: Hasher> hash_db::HashDB for TrieBackendEssence { +impl, H: Hasher> HashDB for TrieBackendEssence { fn get(&self, key: &H::Out, prefix: Prefix) -> Option { if *key == self.empty { return Some([0u8].to_vec()) @@ -538,7 +561,7 @@ impl, H: Hasher> hash_db::HashDB for TrieBa } fn contains(&self, key: &H::Out, prefix: Prefix) -> bool { - hash_db::HashDB::get(self, key, prefix).is_some() + HashDB::get(self, key, prefix).is_some() } fn insert(&mut self, _prefix: Prefix, _value: &[u8]) -> H::Out { @@ -554,15 +577,13 @@ impl, H: Hasher> hash_db::HashDB for TrieBa } } -impl, H: Hasher> hash_db::HashDBRef - for TrieBackendEssence -{ +impl, H: Hasher> HashDBRef for TrieBackendEssence { fn get(&self, key: &H::Out, prefix: Prefix) -> Option { - hash_db::HashDB::get(self, key, prefix) + HashDB::get(self, key, prefix) } fn contains(&self, key: &H::Out, prefix: Prefix) -> bool { - hash_db::HashDB::contains(self, key, prefix) + HashDB::contains(self, key, prefix) } } @@ -570,7 +591,9 @@ impl, H: Hasher> hash_db::HashDBRef mod test { use super::*; use sp_core::{Blake2Hasher, H256}; - use sp_trie::{trie_types::TrieDBMut, KeySpacedDBMut, PrefixedMemoryDB, TrieMut}; + use sp_trie::{ + trie_types::TrieDBMutV1 as TrieDBMut, KeySpacedDBMut, PrefixedMemoryDB, TrieMut, + }; #[test] fn next_storage_key_and_next_child_storage_key_work() { diff --git a/primitives/storage/src/lib.rs b/primitives/storage/src/lib.rs index c655a9bdc1cf..eff74c4aac0b 100644 --- a/primitives/storage/src/lib.rs +++ b/primitives/storage/src/lib.rs @@ -237,6 +237,9 @@ pub mod well_known_keys { } } +/// Threshold size to start using trie value nodes in state. +pub const TRIE_VALUE_NODE_THRESHOLD: u32 = 33; + /// Information related to a child state. #[derive(Debug, Clone)] #[cfg_attr(feature = "std", derive(PartialEq, Eq, Hash, PartialOrd, Ord, Encode, Decode))] @@ -401,6 +404,54 @@ impl ChildTrieParentKeyId { } } +/// Different possible state version. +/// +/// V0 and V1 uses a same trie implementation, but V1 will write external value node in the trie for +/// value with size at least `TRIE_VALUE_NODE_THRESHOLD`. +#[derive(Debug, Clone, Copy, Eq, PartialEq)] +pub enum StateVersion { + /// Old state version, no value nodes. + V0 = 0, + /// New state version can use value nodes. + V1 = 1, +} + +impl Default for StateVersion { + fn default() -> Self { + StateVersion::V1 + } +} + +impl From for u8 { + fn from(version: StateVersion) -> u8 { + version as u8 + } +} + +impl sp_std::convert::TryFrom for StateVersion { + type Error = (); + fn try_from(val: u8) -> sp_std::result::Result { + match val { + 0 => Ok(StateVersion::V0), + 1 => Ok(StateVersion::V1), + _ => Err(()), + } + } +} + +impl StateVersion { + /// If defined, values in state of size bigger or equal + /// to this threshold will use a separate trie node. + /// Otherwhise, value will be inlined in branch or leaf + /// node. + pub fn state_value_threshold(&self) -> Option { + match self { + StateVersion::V0 => None, + StateVersion::V1 => Some(TRIE_VALUE_NODE_THRESHOLD), + } + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/primitives/tasks/src/async_externalities.rs b/primitives/tasks/src/async_externalities.rs index 59733490a18f..9f2fec299f59 100644 --- a/primitives/tasks/src/async_externalities.rs +++ b/primitives/tasks/src/async_externalities.rs @@ -19,7 +19,7 @@ //! Async externalities. use sp_core::{ - storage::{ChildInfo, TrackedStorageKey}, + storage::{ChildInfo, StateVersion, TrackedStorageKey}, traits::{Externalities, RuntimeSpawn, RuntimeSpawnExt, SpawnNamed, TaskExecutorExt}, }; use sp_externalities::{Extensions, ExternalitiesExt as _}; @@ -126,11 +126,15 @@ impl Externalities for AsyncExternalities { panic!("`storage_append`: should not be used in async externalities!") } - fn storage_root(&mut self) -> Vec { + fn storage_root(&mut self, _state_version: StateVersion) -> Vec { panic!("`storage_root`: should not be used in async externalities!") } - fn child_storage_root(&mut self, _child_info: &ChildInfo) -> Vec { + fn child_storage_root( + &mut self, + _child_info: &ChildInfo, + _state_version: StateVersion, + ) -> Vec { panic!("`child_storage_root`: should not be used in async externalities!") } diff --git a/primitives/transaction-storage-proof/src/lib.rs b/primitives/transaction-storage-proof/src/lib.rs index 4b01a8d45d45..f76ae7faac08 100644 --- a/primitives/transaction-storage-proof/src/lib.rs +++ b/primitives/transaction-storage-proof/src/lib.rs @@ -143,7 +143,7 @@ pub mod registration { use sp_trie::TrieMut; type Hasher = sp_core::Blake2Hasher; - type TrieLayout = sp_trie::Layout; + type TrieLayout = sp_trie::LayoutV1; /// Create a new inherent data provider instance for a given parent block hash. pub fn new_data_provider( diff --git a/primitives/trie/Cargo.toml b/primitives/trie/Cargo.toml index 02aaa75aa939..8e54035b3ae7 100644 --- a/primitives/trie/Cargo.toml +++ b/primitives/trie/Cargo.toml @@ -22,13 +22,13 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../std" } hash-db = { version = "0.15.2", default-features = false } -trie-db = { version = "0.22.6", default-features = false } -trie-root = { version = "0.16.0", default-features = false } -memory-db = { version = "0.27.0", default-features = false } +trie-db = { version = "0.23.0", default-features = false } +trie-root = { version = "0.17.0", default-features = false } +memory-db = { version = "0.28.0", default-features = false } sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } [dev-dependencies] -trie-bench = "0.28.0" +trie-bench = "0.29.0" trie-standardmap = "0.15.2" criterion = "0.3.3" hex-literal = "0.3.4" diff --git a/primitives/trie/benches/bench.rs b/primitives/trie/benches/bench.rs index 8c84c6354f2c..d78ceadff728 100644 --- a/primitives/trie/benches/bench.rs +++ b/primitives/trie/benches/bench.rs @@ -21,11 +21,11 @@ criterion_main!(benches); fn benchmark(c: &mut Criterion) { trie_bench::standard_benchmark::< - sp_trie::Layout, + sp_trie::LayoutV1, sp_trie::TrieStream, >(c, "substrate-blake2"); trie_bench::standard_benchmark::< - sp_trie::Layout, + sp_trie::LayoutV1, sp_trie::TrieStream, >(c, "substrate-keccak"); } diff --git a/primitives/trie/src/lib.rs b/primitives/trie/src/lib.rs index 8ba13284d379..399484143dbc 100644 --- a/primitives/trie/src/lib.rs +++ b/primitives/trie/src/lib.rs @@ -45,31 +45,43 @@ pub use trie_db::proof::VerifyError; use trie_db::proof::{generate_proof, verify_proof}; /// Various re-exports from the `trie-db` crate. pub use trie_db::{ - nibble_ops, CError, DBValue, Query, Recorder, Trie, TrieConfiguration, TrieDBIterator, + nibble_ops, + node::{NodePlan, ValuePlan}, + CError, DBValue, Query, Recorder, Trie, TrieConfiguration, TrieDBIterator, TrieDBKeyIterator, TrieLayout, TrieMut, }; /// The Substrate format implementation of `TrieStream`. pub use trie_stream::TrieStream; -#[derive(Default)] /// substrate trie layout -pub struct Layout(sp_std::marker::PhantomData); +pub struct LayoutV0(sp_std::marker::PhantomData); -impl TrieLayout for Layout { +/// substrate trie layout, with external value nodes. +pub struct LayoutV1(sp_std::marker::PhantomData); + +impl TrieLayout for LayoutV0 +where + H: Hasher, +{ const USE_EXTENSION: bool = false; const ALLOW_EMPTY: bool = true; + const MAX_INLINE_VALUE: Option = None; + type Hash = H; type Codec = NodeCodec; } -impl TrieConfiguration for Layout { +impl TrieConfiguration for LayoutV0 +where + H: Hasher, +{ fn trie_root(input: I) -> ::Out where I: IntoIterator, A: AsRef<[u8]> + Ord, B: AsRef<[u8]>, { - trie_root::trie_root_no_extension::(input) + trie_root::trie_root_no_extension::(input, Self::MAX_INLINE_VALUE) } fn trie_root_unhashed(input: I) -> Vec @@ -78,7 +90,52 @@ impl TrieConfiguration for Layout { A: AsRef<[u8]> + Ord, B: AsRef<[u8]>, { - trie_root::unhashed_trie_no_extension::(input) + trie_root::unhashed_trie_no_extension::( + input, + Self::MAX_INLINE_VALUE, + ) + } + + fn encode_index(input: u32) -> Vec { + codec::Encode::encode(&codec::Compact(input)) + } +} + +impl TrieLayout for LayoutV1 +where + H: Hasher, +{ + const USE_EXTENSION: bool = false; + const ALLOW_EMPTY: bool = true; + const MAX_INLINE_VALUE: Option = Some(sp_core::storage::TRIE_VALUE_NODE_THRESHOLD); + + type Hash = H; + type Codec = NodeCodec; +} + +impl TrieConfiguration for LayoutV1 +where + H: Hasher, +{ + fn trie_root(input: I) -> ::Out + where + I: IntoIterator, + A: AsRef<[u8]> + Ord, + B: AsRef<[u8]>, + { + trie_root::trie_root_no_extension::(input, Self::MAX_INLINE_VALUE) + } + + fn trie_root_unhashed(input: I) -> Vec + where + I: IntoIterator, + A: AsRef<[u8]> + Ord, + B: AsRef<[u8]>, + { + trie_root::unhashed_trie_no_extension::( + input, + Self::MAX_INLINE_VALUE, + ) } fn encode_index(input: u32) -> Vec { @@ -118,17 +175,22 @@ pub type TrieDBMut<'a, L> = trie_db::TrieDBMut<'a, L>; pub type Lookup<'a, L, Q> = trie_db::Lookup<'a, L, Q>; /// Hash type for a trie layout. pub type TrieHash = <::Hash as Hasher>::Out; - /// This module is for non generic definition of trie type. /// Only the `Hasher` trait is generic in this case. pub mod trie_types { - pub type Layout = super::Layout; + use super::*; + /// Persistent trie database read-access interface for the a given hasher. - pub type TrieDB<'a, H> = super::TrieDB<'a, Layout>; + /// Read only V1 and V0 are compatible, thus we always use V1. + pub type TrieDB<'a, H> = super::TrieDB<'a, LayoutV1>; /// Persistent trie database write-access interface for the a given hasher. - pub type TrieDBMut<'a, H> = super::TrieDBMut<'a, Layout>; + pub type TrieDBMutV0<'a, H> = super::TrieDBMut<'a, LayoutV0>; + /// Persistent trie database write-access interface for the a given hasher. + pub type TrieDBMutV1<'a, H> = super::TrieDBMut<'a, LayoutV1>; + /// Querying interface, as in `trie_db` but less generic. + pub type LookupV0<'a, H, Q> = trie_db::Lookup<'a, LayoutV0, Q>; /// Querying interface, as in `trie_db` but less generic. - pub type Lookup<'a, H, Q> = trie_db::Lookup<'a, Layout, Q>; + pub type LookupV1<'a, H, Q> = trie_db::Lookup<'a, LayoutV1, Q>; /// As in `trie_db`, but less generic, error type for the crate. pub type TrieError = trie_db::TrieError; } @@ -141,16 +203,18 @@ pub mod trie_types { /// For a key `K` that is included in the `db` a proof of inclusion is generated. /// For a key `K` that is not included in the `db` a proof of non-inclusion is generated. /// These can be later checked in `verify_trie_proof`. -pub fn generate_trie_proof<'a, L: TrieConfiguration, I, K, DB>( +pub fn generate_trie_proof<'a, L, I, K, DB>( db: &DB, root: TrieHash, keys: I, ) -> Result>, Box>> where + L: TrieConfiguration, I: IntoIterator, K: 'a + AsRef<[u8]>, DB: hash_db::HashDBRef, { + // Can use default layout (read only). let trie = TrieDB::::new(db, &root)?; generate_proof(&trie, keys) } @@ -163,17 +227,18 @@ where /// checked for inclusion in the proof. /// If the value is omitted (`(key, None)`), this key will be checked for non-inclusion in the /// proof. -pub fn verify_trie_proof<'a, L: TrieConfiguration, I, K, V>( +pub fn verify_trie_proof<'a, L, I, K, V>( root: &TrieHash, proof: &[Vec], items: I, -) -> Result<(), VerifyError, error::Error>> +) -> Result<(), VerifyError, CError>> where + L: TrieConfiguration, I: IntoIterator)>, K: 'a + AsRef<[u8]>, V: 'a + AsRef<[u8]>, { - verify_proof::, _, _, _>(root, proof, items) + verify_proof::(root, proof, items) } /// Determine a trie root given a hash DB and delta values. @@ -207,28 +272,33 @@ where } /// Read a value from the trie. -pub fn read_trie_value>( +pub fn read_trie_value( db: &DB, root: &TrieHash, key: &[u8], -) -> Result>, Box>> { - TrieDB::::new(&*db, root)?.get(key).map(|x| x.map(|val| val.to_vec())) +) -> Result>, Box>> +where + L: TrieConfiguration, + DB: hash_db::HashDBRef, +{ + Ok(TrieDB::::new(&*db, root)?.get(key).map(|x| x.map(|val| val.to_vec()))?) } /// Read a value from the trie with given Query. -pub fn read_trie_value_with< - L: TrieConfiguration, - Q: Query, - DB: hash_db::HashDBRef, ->( +pub fn read_trie_value_with( db: &DB, root: &TrieHash, key: &[u8], query: Q, -) -> Result>, Box>> { - TrieDB::::new(&*db, root)? +) -> Result>, Box>> +where + L: TrieConfiguration, + Q: Query, + DB: hash_db::HashDBRef, +{ + Ok(TrieDB::::new(&*db, root)? .get_with(key, query) - .map(|x| x.map(|val| val.to_vec())) + .map(|x| x.map(|val| val.to_vec()))?) } /// Determine the empty trie root. @@ -319,7 +389,7 @@ where } /// Read a value from the child trie with given query. -pub fn read_child_trie_value_with, DB>( +pub fn read_child_trie_value_with( keyspace: &[u8], db: &DB, root_slice: &[u8], @@ -327,6 +397,8 @@ pub fn read_child_trie_value_with Result>, Box>> where + L: TrieConfiguration, + Q: Query, DB: hash_db::HashDBRef, { let mut root = TrieHash::::default(); @@ -444,11 +516,15 @@ where /// Constants used into trie simplification codec. mod trie_constants { - pub const EMPTY_TRIE: u8 = 0; - pub const NIBBLE_SIZE_BOUND: usize = u16::MAX as usize; + const FIRST_PREFIX: u8 = 0b_00 << 6; + pub const NIBBLE_SIZE_BOUND: usize = u16::max_value() as usize; pub const LEAF_PREFIX_MASK: u8 = 0b_01 << 6; pub const BRANCH_WITHOUT_MASK: u8 = 0b_10 << 6; pub const BRANCH_WITH_MASK: u8 = 0b_11 << 6; + pub const EMPTY_TRIE: u8 = FIRST_PREFIX | (0b_00 << 4); + pub const ALT_HASHING_LEAF_PREFIX_MASK: u8 = FIRST_PREFIX | (0b_1 << 5); + pub const ALT_HASHING_BRANCH_WITH_MASK: u8 = FIRST_PREFIX | (0b_01 << 4); + pub const ESCAPE_COMPACT_HEADER: u8 = EMPTY_TRIE | 0b_00_01; } #[cfg(test)] @@ -461,7 +537,11 @@ mod tests { use trie_db::{DBValue, NodeCodec as NodeCodecT, Trie, TrieMut}; use trie_standardmap::{Alphabet, StandardMap, ValueMode}; - type Layout = super::Layout; + type LayoutV0 = super::LayoutV0; + type LayoutV1 = super::LayoutV1; + + type MemoryDBMeta = + memory_db::MemoryDB, trie_db::DBValue, MemTracker>; fn hashed_null_node() -> TrieHash { ::hashed_null_node() @@ -473,7 +553,7 @@ mod tests { let d = T::trie_root_unhashed(input.clone()); println!("Data: {:#x?}, {:#x?}", d, Blake2Hasher::hash(&d[..])); let persistent = { - let mut memdb = MemoryDB::default(); + let mut memdb = MemoryDBMeta::default(); let mut root = Default::default(); let mut t = TrieDBMut::::new(&mut memdb, &mut root); for (x, y) in input.iter().rev() { @@ -486,7 +566,7 @@ mod tests { } fn check_iteration(input: &Vec<(&[u8], &[u8])>) { - let mut memdb = MemoryDB::default(); + let mut memdb = MemoryDBMeta::default(); let mut root = Default::default(); { let mut t = TrieDBMut::::new(&mut memdb, &mut root); @@ -506,14 +586,21 @@ mod tests { } } + fn check_input(input: &Vec<(&[u8], &[u8])>) { + check_equivalent::(input); + check_iteration::(input); + check_equivalent::(input); + check_iteration::(input); + } + #[test] fn default_trie_root() { let mut db = MemoryDB::default(); - let mut root = TrieHash::::default(); - let mut empty = TrieDBMut::::new(&mut db, &mut root); + let mut root = TrieHash::::default(); + let mut empty = TrieDBMut::::new(&mut db, &mut root); empty.commit(); let root1 = empty.root().as_ref().to_vec(); - let root2: Vec = Layout::trie_root::<_, Vec, Vec>(std::iter::empty()) + let root2: Vec = LayoutV1::trie_root::<_, Vec, Vec>(std::iter::empty()) .as_ref() .iter() .cloned() @@ -525,31 +612,27 @@ mod tests { #[test] fn empty_is_equivalent() { let input: Vec<(&[u8], &[u8])> = vec![]; - check_equivalent::(&input); - check_iteration::(&input); + check_input(&input); } #[test] fn leaf_is_equivalent() { let input: Vec<(&[u8], &[u8])> = vec![(&[0xaa][..], &[0xbb][..])]; - check_equivalent::(&input); - check_iteration::(&input); + check_input(&input); } #[test] fn branch_is_equivalent() { let input: Vec<(&[u8], &[u8])> = vec![(&[0xaa][..], &[0x10][..]), (&[0xba][..], &[0x11][..])]; - check_equivalent::(&input); - check_iteration::(&input); + check_input(&input); } #[test] fn extension_and_branch_is_equivalent() { let input: Vec<(&[u8], &[u8])> = vec![(&[0xaa][..], &[0x10][..]), (&[0xab][..], &[0x11][..])]; - check_equivalent::(&input); - check_iteration::(&input); + check_input(&input); } #[test] @@ -564,8 +647,7 @@ mod tests { let mut d = st.make(); d.sort_by(|&(ref a, _), &(ref b, _)| a.cmp(b)); let dr = d.iter().map(|v| (&v.0[..], &v.1[..])).collect(); - check_equivalent::(&dr); - check_iteration::(&dr); + check_input(&dr); } #[test] @@ -575,8 +657,7 @@ mod tests { (&[0xaa, 0xaa][..], &[0xaa][..]), (&[0xaa, 0xbb][..], &[0xab][..]), ]; - check_equivalent::(&input); - check_iteration::(&input); + check_input(&input); } #[test] @@ -589,8 +670,7 @@ mod tests { (&[0xbb, 0xbb][..], &[0xbb][..]), (&[0xbb, 0xcc][..], &[0xbc][..]), ]; - check_equivalent::(&input); - check_iteration::(&input); + check_input(&input); } #[test] @@ -602,8 +682,7 @@ mod tests { ), (&[0xba][..], &[0x11][..]), ]; - check_equivalent::(&input); - check_iteration::(&input); + check_input(&input); } #[test] @@ -618,15 +697,17 @@ mod tests { &b"ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC"[..], ), ]; - check_equivalent::(&input); - check_iteration::(&input); + check_input(&input); } - fn populate_trie<'db, T: TrieConfiguration>( + fn populate_trie<'db, T>( db: &'db mut dyn HashDB, root: &'db mut TrieHash, v: &[(Vec, Vec)], - ) -> TrieDBMut<'db, T> { + ) -> TrieDBMut<'db, T> + where + T: TrieConfiguration, + { let mut t = TrieDBMut::::new(db, root); for i in 0..v.len() { let key: &[u8] = &v[i].0; @@ -648,8 +729,12 @@ mod tests { #[test] fn random_should_work() { + random_should_work_inner::(); + random_should_work_inner::(); + } + fn random_should_work_inner() { let mut seed = ::Out::zero(); - for test_i in 0..10000 { + for test_i in 0..10_000 { if test_i % 50 == 0 { println!("{:?} of 10000 stress tests done", test_i); } @@ -662,10 +747,11 @@ mod tests { } .make_with(seed.as_fixed_bytes_mut()); - let real = Layout::trie_root(x.clone()); + let real = L::trie_root(x.clone()); let mut memdb = MemoryDB::default(); let mut root = Default::default(); - let mut memtrie = populate_trie::(&mut memdb, &mut root, &x); + + let mut memtrie = populate_trie::(&mut memdb, &mut root, &x); memtrie.commit(); if *memtrie.root() != real { @@ -677,9 +763,9 @@ mod tests { } } assert_eq!(*memtrie.root(), real); - unpopulate_trie::(&mut memtrie, &x); + unpopulate_trie::(&mut memtrie, &x); memtrie.commit(); - let hashed_null_node = hashed_null_node::(); + let hashed_null_node = hashed_null_node::(); if *memtrie.root() != hashed_null_node { println!("- TRIE MISMATCH"); println!(""); @@ -699,7 +785,7 @@ mod tests { #[test] fn codec_trie_empty() { let input: Vec<(&[u8], &[u8])> = vec![]; - let trie = Layout::trie_root_unhashed::<_, _, _>(input); + let trie = LayoutV1::trie_root_unhashed(input); println!("trie: {:#x?}", trie); assert_eq!(trie, vec![0x0]); } @@ -707,7 +793,7 @@ mod tests { #[test] fn codec_trie_single_tuple() { let input = vec![(vec![0xaa], vec![0xbb])]; - let trie = Layout::trie_root_unhashed::<_, _, _>(input); + let trie = LayoutV1::trie_root_unhashed(input); println!("trie: {:#x?}", trie); assert_eq!( trie, @@ -723,7 +809,7 @@ mod tests { #[test] fn codec_trie_two_tuples_disjoint_keys() { let input = vec![(&[0x48, 0x19], &[0xfe]), (&[0x13, 0x14], &[0xff])]; - let trie = Layout::trie_root_unhashed::<_, _, _>(input); + let trie = LayoutV1::trie_root_unhashed(input); println!("trie: {:#x?}", trie); let mut ex = Vec::::new(); ex.push(0x80); // branch, no value (0b_10..) no nibble @@ -747,6 +833,10 @@ mod tests { #[test] fn iterator_works() { + iterator_works_inner::(); + iterator_works_inner::(); + } + fn iterator_works_inner() { let pairs = vec![ (hex!("0103000000000000000464").to_vec(), hex!("0400000000").to_vec()), (hex!("0103000000000000000469").to_vec(), hex!("0401000000").to_vec()), @@ -777,15 +867,15 @@ mod tests { let mut memdb = MemoryDB::default(); let mut root = Default::default(); - populate_trie::(&mut memdb, &mut root, &pairs); + populate_trie::(&mut memdb, &mut root, &pairs); let non_included_key: Vec = hex!("0909").to_vec(); let proof = - generate_trie_proof::(&memdb, root, &[non_included_key.clone()]) + generate_trie_proof::(&memdb, root, &[non_included_key.clone()]) .unwrap(); // Verifying that the K was not included into the trie should work. - assert!(verify_trie_proof::>( + assert!(verify_trie_proof::>( &root, &proof, &[(non_included_key.clone(), None)], @@ -793,7 +883,7 @@ mod tests { .is_ok()); // Verifying that the K was included into the trie should fail. - assert!(verify_trie_proof::>( + assert!(verify_trie_proof::>( &root, &proof, &[(non_included_key, Some(hex!("1010").to_vec()))], @@ -810,13 +900,13 @@ mod tests { let mut memdb = MemoryDB::default(); let mut root = Default::default(); - populate_trie::(&mut memdb, &mut root, &pairs); + populate_trie::(&mut memdb, &mut root, &pairs); let proof = - generate_trie_proof::(&memdb, root, &[pairs[0].0.clone()]).unwrap(); + generate_trie_proof::(&memdb, root, &[pairs[0].0.clone()]).unwrap(); // Check that a K, V included into the proof are verified. - assert!(verify_trie_proof::( + assert!(verify_trie_proof::( &root, &proof, &[(pairs[0].0.clone(), Some(pairs[0].1.clone()))] @@ -824,7 +914,7 @@ mod tests { .is_ok()); // Absence of the V is not verified with the proof that has K, V included. - assert!(verify_trie_proof::>( + assert!(verify_trie_proof::>( &root, &proof, &[(pairs[0].0.clone(), None)] @@ -832,7 +922,7 @@ mod tests { .is_err()); // K not included into the trie is not verified. - assert!(verify_trie_proof::( + assert!(verify_trie_proof::( &root, &proof, &[(hex!("4242").to_vec(), Some(pairs[0].1.clone()))] @@ -840,7 +930,7 @@ mod tests { .is_err()); // K included into the trie but not included into the proof is not verified. - assert!(verify_trie_proof::( + assert!(verify_trie_proof::( &root, &proof, &[(pairs[1].0.clone(), Some(pairs[1].1.clone()))] @@ -865,13 +955,13 @@ mod tests { .unwrap(); let proof_db = proof.into_memory_db::(); - let first_storage_root = delta_trie_root::( + let first_storage_root = delta_trie_root::( &mut proof_db.clone(), storage_root, valid_delta, ) .unwrap(); - let second_storage_root = delta_trie_root::( + let second_storage_root = delta_trie_root::( &mut proof_db.clone(), storage_root, invalid_delta, diff --git a/primitives/trie/src/node_codec.rs b/primitives/trie/src/node_codec.rs index d5ffb3219cf6..53a5de270a79 100644 --- a/primitives/trie/src/node_codec.rs +++ b/primitives/trie/src/node_codec.rs @@ -24,7 +24,7 @@ use hash_db::Hasher; use sp_std::{borrow::Borrow, marker::PhantomData, ops::Range, vec::Vec}; use trie_db::{ self, nibble_ops, - node::{NibbleSlicePlan, NodeHandlePlan, NodePlan}, + node::{NibbleSlicePlan, NodeHandlePlan, NodePlan, Value, ValuePlan}, ChildReference, NodeCodec as NodeCodecT, Partial, }; @@ -80,7 +80,11 @@ impl<'a> Input for ByteSliceInput<'a> { #[derive(Default, Clone)] pub struct NodeCodec(PhantomData); -impl NodeCodecT for NodeCodec { +impl NodeCodecT for NodeCodec +where + H: Hasher, +{ + const ESCAPE_HEADER: Option = Some(trie_constants::ESCAPE_COMPACT_HEADER); type Error = Error; type HashOut = H::Out; @@ -88,11 +92,22 @@ impl NodeCodecT for NodeCodec { H::hash(::empty_node()) } - fn decode_plan(data: &[u8]) -> sp_std::result::Result { + fn decode_plan(data: &[u8]) -> Result { let mut input = ByteSliceInput::new(data); - match NodeHeader::decode(&mut input)? { + + let header = NodeHeader::decode(&mut input)?; + let contains_hash = header.contains_hash_of_value(); + + let branch_has_value = if let NodeHeader::Branch(has_value, _) = &header { + *has_value + } else { + // hashed_value_branch + true + }; + + match header { NodeHeader::Null => Ok(NodePlan::Empty), - NodeHeader::Branch(has_value, nibble_count) => { + NodeHeader::HashedValueBranch(nibble_count) | NodeHeader::Branch(_, nibble_count) => { let padding = nibble_count % nibble_ops::NIBBLE_PER_BYTE != 0; // check that the padding is valid (if any) if padding && nibble_ops::pad_left(data[input.offset]) != 0 { @@ -105,9 +120,13 @@ impl NodeCodecT for NodeCodec { let partial_padding = nibble_ops::number_padding(nibble_count); let bitmap_range = input.take(BITMAP_LENGTH)?; let bitmap = Bitmap::decode(&data[bitmap_range])?; - let value = if has_value { - let count = >::decode(&mut input)?.0 as usize; - Some(input.take(count)?) + let value = if branch_has_value { + Some(if contains_hash { + ValuePlan::Node(input.take(H::LENGTH)?) + } else { + let count = >::decode(&mut input)?.0 as usize; + ValuePlan::Inline(input.take(count)?) + }) } else { None }; @@ -132,7 +151,7 @@ impl NodeCodecT for NodeCodec { children, }) }, - NodeHeader::Leaf(nibble_count) => { + NodeHeader::HashedValueLeaf(nibble_count) | NodeHeader::Leaf(nibble_count) => { let padding = nibble_count % nibble_ops::NIBBLE_PER_BYTE != 0; // check that the padding is valid (if any) if padding && nibble_ops::pad_left(data[input.offset]) != 0 { @@ -143,10 +162,16 @@ impl NodeCodecT for NodeCodec { nibble_ops::NIBBLE_PER_BYTE, )?; let partial_padding = nibble_ops::number_padding(nibble_count); - let count = >::decode(&mut input)?.0 as usize; + let value = if contains_hash { + ValuePlan::Node(input.take(H::LENGTH)?) + } else { + let count = >::decode(&mut input)?.0 as usize; + ValuePlan::Inline(input.take(count)?) + }; + Ok(NodePlan::Leaf { partial: NibbleSlicePlan::new(partial, partial_padding), - value: input.take(count)?, + value, }) }, } @@ -160,9 +185,23 @@ impl NodeCodecT for NodeCodec { &[trie_constants::EMPTY_TRIE] } - fn leaf_node(partial: Partial, value: &[u8]) -> Vec { - let mut output = partial_encode(partial, NodeKind::Leaf); - value.encode_to(&mut output); + fn leaf_node(partial: Partial, value: Value) -> Vec { + let contains_hash = matches!(&value, Value::Node(..)); + let mut output = if contains_hash { + partial_encode(partial, NodeKind::HashedValueLeaf) + } else { + partial_encode(partial, NodeKind::Leaf) + }; + match value { + Value::Inline(value) => { + Compact(value.len() as u32).encode_to(&mut output); + output.extend_from_slice(value); + }, + Value::Node(hash, _) => { + debug_assert!(hash.len() == H::LENGTH); + output.extend_from_slice(hash); + }, + } output } @@ -171,33 +210,46 @@ impl NodeCodecT for NodeCodec { _nbnibble: usize, _child: ChildReference<::Out>, ) -> Vec { - unreachable!() + unreachable!("No extension codec.") } fn branch_node( _children: impl Iterator::Out>>>>, - _maybe_value: Option<&[u8]>, + _maybe_value: Option, ) -> Vec { - unreachable!() + unreachable!("No extension codec.") } fn branch_node_nibbled( partial: impl Iterator, number_nibble: usize, children: impl Iterator::Out>>>>, - maybe_value: Option<&[u8]>, + value: Option, ) -> Vec { - let mut output = if maybe_value.is_some() { - partial_from_iterator_encode(partial, number_nibble, NodeKind::BranchWithValue) - } else { - partial_from_iterator_encode(partial, number_nibble, NodeKind::BranchNoValue) + let contains_hash = matches!(&value, Some(Value::Node(..))); + let mut output = match (&value, contains_hash) { + (&None, _) => + partial_from_iterator_encode(partial, number_nibble, NodeKind::BranchNoValue), + (_, false) => + partial_from_iterator_encode(partial, number_nibble, NodeKind::BranchWithValue), + (_, true) => + partial_from_iterator_encode(partial, number_nibble, NodeKind::HashedValueBranch), }; + let bitmap_index = output.len(); let mut bitmap: [u8; BITMAP_LENGTH] = [0; BITMAP_LENGTH]; (0..BITMAP_LENGTH).for_each(|_| output.push(0)); - if let Some(value) = maybe_value { - value.encode_to(&mut output); - }; + match value { + Some(Value::Inline(value)) => { + Compact(value.len() as u32).encode_to(&mut output); + output.extend_from_slice(value); + }, + Some(Value::Node(hash, _)) => { + debug_assert!(hash.len() == H::LENGTH); + output.extend_from_slice(hash); + }, + None => (), + } Bitmap::encode( children.map(|maybe_child| match maybe_child.borrow() { Some(ChildReference::Hash(h)) => { @@ -229,11 +281,15 @@ fn partial_from_iterator_encode>( ) -> Vec { let nibble_count = sp_std::cmp::min(trie_constants::NIBBLE_SIZE_BOUND, nibble_count); - let mut output = Vec::with_capacity(3 + (nibble_count / nibble_ops::NIBBLE_PER_BYTE)); + let mut output = Vec::with_capacity(4 + (nibble_count / nibble_ops::NIBBLE_PER_BYTE)); match node_kind { NodeKind::Leaf => NodeHeader::Leaf(nibble_count).encode_to(&mut output), NodeKind::BranchWithValue => NodeHeader::Branch(true, nibble_count).encode_to(&mut output), NodeKind::BranchNoValue => NodeHeader::Branch(false, nibble_count).encode_to(&mut output), + NodeKind::HashedValueLeaf => + NodeHeader::HashedValueLeaf(nibble_count).encode_to(&mut output), + NodeKind::HashedValueBranch => + NodeHeader::HashedValueBranch(nibble_count).encode_to(&mut output), }; output.extend(partial); output @@ -247,11 +303,15 @@ fn partial_encode(partial: Partial, node_kind: NodeKind) -> Vec { let nibble_count = sp_std::cmp::min(trie_constants::NIBBLE_SIZE_BOUND, nibble_count); - let mut output = Vec::with_capacity(3 + partial.1.len()); + let mut output = Vec::with_capacity(4 + partial.1.len()); match node_kind { NodeKind::Leaf => NodeHeader::Leaf(nibble_count).encode_to(&mut output), NodeKind::BranchWithValue => NodeHeader::Branch(true, nibble_count).encode_to(&mut output), NodeKind::BranchNoValue => NodeHeader::Branch(false, nibble_count).encode_to(&mut output), + NodeKind::HashedValueLeaf => + NodeHeader::HashedValueLeaf(nibble_count).encode_to(&mut output), + NodeKind::HashedValueBranch => + NodeHeader::HashedValueBranch(nibble_count).encode_to(&mut output), }; if number_nibble_encoded > 0 { output.push(nibble_ops::pad_right((partial.0).1)); diff --git a/primitives/trie/src/node_header.rs b/primitives/trie/src/node_header.rs index 9f05113a3593..895713ffd1f8 100644 --- a/primitives/trie/src/node_header.rs +++ b/primitives/trie/src/node_header.rs @@ -25,8 +25,20 @@ use sp_std::iter::once; #[derive(Copy, Clone, PartialEq, Eq, sp_core::RuntimeDebug)] pub(crate) enum NodeHeader { Null, + // contains wether there is a value and nibble count Branch(bool, usize), + // contains nibble count Leaf(usize), + // contains nibble count. + HashedValueBranch(usize), + // contains nibble count. + HashedValueLeaf(usize), +} + +impl NodeHeader { + pub(crate) fn contains_hash_of_value(&self) -> bool { + matches!(self, NodeHeader::HashedValueBranch(_) | NodeHeader::HashedValueLeaf(_)) + } } /// NodeHeader without content @@ -34,6 +46,8 @@ pub(crate) enum NodeKind { Leaf, BranchNoValue, BranchWithValue, + HashedValueLeaf, + HashedValueBranch, } impl Encode for NodeHeader { @@ -41,11 +55,27 @@ impl Encode for NodeHeader { match self { NodeHeader::Null => output.push_byte(trie_constants::EMPTY_TRIE), NodeHeader::Branch(true, nibble_count) => - encode_size_and_prefix(*nibble_count, trie_constants::BRANCH_WITH_MASK, output), - NodeHeader::Branch(false, nibble_count) => - encode_size_and_prefix(*nibble_count, trie_constants::BRANCH_WITHOUT_MASK, output), + encode_size_and_prefix(*nibble_count, trie_constants::BRANCH_WITH_MASK, 2, output), + NodeHeader::Branch(false, nibble_count) => encode_size_and_prefix( + *nibble_count, + trie_constants::BRANCH_WITHOUT_MASK, + 2, + output, + ), NodeHeader::Leaf(nibble_count) => - encode_size_and_prefix(*nibble_count, trie_constants::LEAF_PREFIX_MASK, output), + encode_size_and_prefix(*nibble_count, trie_constants::LEAF_PREFIX_MASK, 2, output), + NodeHeader::HashedValueBranch(nibble_count) => encode_size_and_prefix( + *nibble_count, + trie_constants::ALT_HASHING_BRANCH_WITH_MASK, + 4, + output, + ), + NodeHeader::HashedValueLeaf(nibble_count) => encode_size_and_prefix( + *nibble_count, + trie_constants::ALT_HASHING_LEAF_PREFIX_MASK, + 3, + output, + ), } } } @@ -59,13 +89,22 @@ impl Decode for NodeHeader { return Ok(NodeHeader::Null) } match i & (0b11 << 6) { - trie_constants::LEAF_PREFIX_MASK => Ok(NodeHeader::Leaf(decode_size(i, input)?)), - trie_constants::BRANCH_WITHOUT_MASK => - Ok(NodeHeader::Branch(false, decode_size(i, input)?)), + trie_constants::LEAF_PREFIX_MASK => Ok(NodeHeader::Leaf(decode_size(i, input, 2)?)), trie_constants::BRANCH_WITH_MASK => - Ok(NodeHeader::Branch(true, decode_size(i, input)?)), - // do not allow any special encoding - _ => Err("Unallowed encoding".into()), + Ok(NodeHeader::Branch(true, decode_size(i, input, 2)?)), + trie_constants::BRANCH_WITHOUT_MASK => + Ok(NodeHeader::Branch(false, decode_size(i, input, 2)?)), + trie_constants::EMPTY_TRIE => { + if i & (0b111 << 5) == trie_constants::ALT_HASHING_LEAF_PREFIX_MASK { + Ok(NodeHeader::HashedValueLeaf(decode_size(i, input, 3)?)) + } else if i & (0b1111 << 4) == trie_constants::ALT_HASHING_BRANCH_WITH_MASK { + Ok(NodeHeader::HashedValueBranch(decode_size(i, input, 4)?)) + } else { + // do not allow any special encoding + Err("Unallowed encoding".into()) + } + }, + _ => unreachable!(), } } } @@ -73,12 +112,20 @@ impl Decode for NodeHeader { /// Returns an iterator over encoded bytes for node header and size. /// Size encoding allows unlimited, length inefficient, representation, but /// is bounded to 16 bit maximum value to avoid possible DOS. -pub(crate) fn size_and_prefix_iterator(size: usize, prefix: u8) -> impl Iterator { +pub(crate) fn size_and_prefix_iterator( + size: usize, + prefix: u8, + prefix_mask: usize, +) -> impl Iterator { let size = sp_std::cmp::min(trie_constants::NIBBLE_SIZE_BOUND, size); - let l1 = sp_std::cmp::min(62, size); - let (first_byte, mut rem) = - if size == l1 { (once(prefix + l1 as u8), 0) } else { (once(prefix + 63), size - l1) }; + let max_value = 255u8 >> prefix_mask; + let l1 = sp_std::cmp::min((max_value as usize).saturating_sub(1), size); + let (first_byte, mut rem) = if size == l1 { + (once(prefix + l1 as u8), 0) + } else { + (once(prefix + max_value as u8), size - l1) + }; let next_bytes = move || { if rem > 0 { if rem < 256 { @@ -97,16 +144,24 @@ pub(crate) fn size_and_prefix_iterator(size: usize, prefix: u8) -> impl Iterator } /// Encodes size and prefix to a stream output. -fn encode_size_and_prefix(size: usize, prefix: u8, out: &mut W) { - for b in size_and_prefix_iterator(size, prefix) { +fn encode_size_and_prefix(size: usize, prefix: u8, prefix_mask: usize, out: &mut W) +where + W: Output + ?Sized, +{ + for b in size_and_prefix_iterator(size, prefix, prefix_mask) { out.push_byte(b) } } /// Decode size only from stream input and header byte. -fn decode_size(first: u8, input: &mut impl Input) -> Result { - let mut result = (first & 255u8 >> 2) as usize; - if result < 63 { +fn decode_size( + first: u8, + input: &mut impl Input, + prefix_mask: usize, +) -> Result { + let max_value = 255u8 >> prefix_mask; + let mut result = (first & max_value) as usize; + if result < max_value as usize { return Ok(result) } result -= 1; diff --git a/primitives/trie/src/storage_proof.rs b/primitives/trie/src/storage_proof.rs index 91f2159f2957..cd65fa5b26f2 100644 --- a/primitives/trie/src/storage_proof.rs +++ b/primitives/trie/src/storage_proof.rs @@ -19,6 +19,9 @@ use codec::{Decode, Encode}; use hash_db::{HashDB, Hasher}; use scale_info::TypeInfo; use sp_std::vec::Vec; +// Note that `LayoutV1` usage here (proof compaction) is compatible +// with `LayoutV0`. +use crate::LayoutV1 as Layout; /// A proof that some set of key-value pairs are included in the storage trie. The proof contains /// the storage values so that the partial storage backend can be reconstructed by a verifier that @@ -95,8 +98,8 @@ impl StorageProof { pub fn into_compact_proof( self, root: H::Out, - ) -> Result>> { - crate::encode_compact::>(self, root) + ) -> Result>> { + crate::encode_compact::>(self, root) } /// Returns the estimated encoded size of the compact proof. @@ -124,9 +127,9 @@ impl CompactProof { pub fn to_storage_proof( &self, expected_root: Option<&H::Out>, - ) -> Result<(StorageProof, H::Out), crate::CompactProofError>> { + ) -> Result<(StorageProof, H::Out), crate::CompactProofError>> { let mut db = crate::MemoryDB::::new(&[]); - let root = crate::decode_compact::, _, _>( + let root = crate::decode_compact::, _, _>( &mut db, self.iter_compact_encoded_nodes(), expected_root, diff --git a/primitives/trie/src/trie_codec.rs b/primitives/trie/src/trie_codec.rs index 1596229f2b5d..f485ee13e332 100644 --- a/primitives/trie/src/trie_codec.rs +++ b/primitives/trie/src/trie_codec.rs @@ -112,8 +112,7 @@ where I: IntoIterator, { let mut nodes_iter = encoded.into_iter(); - let (top_root, _nb_used) = - trie_db::decode_compact_from_iter::(db, &mut nodes_iter)?; + let (top_root, _nb_used) = trie_db::decode_compact_from_iter::(db, &mut nodes_iter)?; // Only check root if expected root is passed as argument. if let Some(expected_root) = expected_root { @@ -164,8 +163,7 @@ where let mut nodes_iter = nodes_iter.peekable(); for child_root in child_tries.into_iter() { if previous_extracted_child_trie.is_none() && nodes_iter.peek().is_some() { - let (top_root, _) = - trie_db::decode_compact_from_iter::(db, &mut nodes_iter)?; + let (top_root, _) = trie_db::decode_compact_from_iter::(db, &mut nodes_iter)?; previous_extracted_child_trie = Some(top_root); } diff --git a/primitives/trie/src/trie_stream.rs b/primitives/trie/src/trie_stream.rs index e0e26fea67c2..20f607c840d3 100644 --- a/primitives/trie/src/trie_stream.rs +++ b/primitives/trie/src/trie_stream.rs @@ -18,21 +18,18 @@ //! `TrieStream` implementation for Substrate's trie format. use crate::{ - node_codec::Bitmap, node_header::{size_and_prefix_iterator, NodeKind}, trie_constants, }; -use codec::Encode; +use codec::{Compact, Encode}; use hash_db::Hasher; use sp_std::vec::Vec; use trie_root; -const BRANCH_NODE_NO_VALUE: u8 = 254; -const BRANCH_NODE_WITH_VALUE: u8 = 255; - #[derive(Default, Clone)] /// Codec-flavored TrieStream. pub struct TrieStream { + /// Current node buffer. buffer: Vec, } @@ -60,51 +57,76 @@ fn fuse_nibbles_node<'a>(nibbles: &'a [u8], kind: NodeKind) -> impl Iterator size_and_prefix_iterator(size, trie_constants::LEAF_PREFIX_MASK), + NodeKind::Leaf => size_and_prefix_iterator(size, trie_constants::LEAF_PREFIX_MASK, 2), NodeKind::BranchNoValue => - size_and_prefix_iterator(size, trie_constants::BRANCH_WITHOUT_MASK), + size_and_prefix_iterator(size, trie_constants::BRANCH_WITHOUT_MASK, 2), NodeKind::BranchWithValue => - size_and_prefix_iterator(size, trie_constants::BRANCH_WITH_MASK), + size_and_prefix_iterator(size, trie_constants::BRANCH_WITH_MASK, 2), + NodeKind::HashedValueLeaf => + size_and_prefix_iterator(size, trie_constants::ALT_HASHING_LEAF_PREFIX_MASK, 3), + NodeKind::HashedValueBranch => + size_and_prefix_iterator(size, trie_constants::ALT_HASHING_BRANCH_WITH_MASK, 4), }; iter_start .chain(if nibbles.len() % 2 == 1 { Some(nibbles[0]) } else { None }) .chain(nibbles[nibbles.len() % 2..].chunks(2).map(|ch| ch[0] << 4 | ch[1])) } +use trie_root::Value as TrieStreamValue; impl trie_root::TrieStream for TrieStream { fn new() -> Self { - TrieStream { buffer: Vec::new() } + Self { buffer: Vec::new() } } fn append_empty_data(&mut self) { self.buffer.push(trie_constants::EMPTY_TRIE); } - fn append_leaf(&mut self, key: &[u8], value: &[u8]) { - self.buffer.extend(fuse_nibbles_node(key, NodeKind::Leaf)); - value.encode_to(&mut self.buffer); + fn append_leaf(&mut self, key: &[u8], value: TrieStreamValue) { + let kind = match &value { + TrieStreamValue::Inline(..) => NodeKind::Leaf, + TrieStreamValue::Node(..) => NodeKind::HashedValueLeaf, + }; + self.buffer.extend(fuse_nibbles_node(key, kind)); + match &value { + TrieStreamValue::Inline(value) => { + Compact(value.len() as u32).encode_to(&mut self.buffer); + self.buffer.extend_from_slice(value); + }, + TrieStreamValue::Node(hash) => { + self.buffer.extend_from_slice(hash.as_slice()); + }, + }; } fn begin_branch( &mut self, maybe_partial: Option<&[u8]>, - maybe_value: Option<&[u8]>, + maybe_value: Option, has_children: impl Iterator, ) { if let Some(partial) = maybe_partial { - if maybe_value.is_some() { - self.buffer.extend(fuse_nibbles_node(partial, NodeKind::BranchWithValue)); - } else { - self.buffer.extend(fuse_nibbles_node(partial, NodeKind::BranchNoValue)); - } + let kind = match &maybe_value { + None => NodeKind::BranchNoValue, + Some(TrieStreamValue::Inline(..)) => NodeKind::BranchWithValue, + Some(TrieStreamValue::Node(..)) => NodeKind::HashedValueBranch, + }; + + self.buffer.extend(fuse_nibbles_node(partial, kind)); let bm = branch_node_bit_mask(has_children); self.buffer.extend([bm.0, bm.1].iter()); } else { - debug_assert!(false, "trie stream codec only for no extension trie"); - self.buffer.extend(&branch_node(maybe_value.is_some(), has_children)); + unreachable!("trie stream codec only for no extension trie"); } - if let Some(value) = maybe_value { - value.encode_to(&mut self.buffer); + match maybe_value { + None => (), + Some(TrieStreamValue::Inline(value)) => { + Compact(value.len() as u32).encode_to(&mut self.buffer); + self.buffer.extend_from_slice(value); + }, + Some(TrieStreamValue::Node(hash)) => { + self.buffer.extend_from_slice(hash.as_slice()); + }, } } @@ -124,18 +146,3 @@ impl trie_root::TrieStream for TrieStream { self.buffer } } - -fn branch_node(has_value: bool, has_children: impl Iterator) -> [u8; 3] { - let mut result = [0, 0, 0]; - branch_node_buffered(has_value, has_children, &mut result[..]); - result -} - -fn branch_node_buffered(has_value: bool, has_children: I, output: &mut [u8]) -where - I: Iterator, -{ - let first = if has_value { BRANCH_NODE_WITH_VALUE } else { BRANCH_NODE_NO_VALUE }; - output[0] = first; - Bitmap::encode(has_children, &mut output[1..]); -} diff --git a/primitives/version/Cargo.toml b/primitives/version/Cargo.toml index 585d089a54b5..7fb55295088e 100644 --- a/primitives/version/Cargo.toml +++ b/primitives/version/Cargo.toml @@ -22,6 +22,7 @@ sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-runtime = { version = "4.0.0", default-features = false, path = "../runtime" } sp-version-proc-macro = { version = "4.0.0-dev", default-features = false, path = "proc-macro" } parity-wasm = { version = "0.42.2", optional = true } +sp-core-hashing-proc-macro = { version = "4.0.0-dev", path = "../core/hashing/proc-macro" } thiserror = { version = "1.0.30", optional = true } [features] diff --git a/primitives/version/proc-macro/src/decl_runtime_version.rs b/primitives/version/proc-macro/src/decl_runtime_version.rs index eef6314be4c8..7fcb716bbf60 100644 --- a/primitives/version/proc-macro/src/decl_runtime_version.rs +++ b/primitives/version/proc-macro/src/decl_runtime_version.rs @@ -63,6 +63,7 @@ struct RuntimeVersion { impl_version: u32, apis: u8, transaction_version: u32, + state_version: u8, } #[derive(Default, Debug)] @@ -73,6 +74,7 @@ struct ParseRuntimeVersion { spec_version: Option, impl_version: Option, transaction_version: Option, + state_version: Option, } impl ParseRuntimeVersion { @@ -122,6 +124,8 @@ impl ParseRuntimeVersion { parse_once(&mut self.impl_version, field_value, Self::parse_num_literal)?; } else if field_name == "transaction_version" { parse_once(&mut self.transaction_version, field_value, Self::parse_num_literal)?; + } else if field_name == "state_version" { + parse_once(&mut self.state_version, field_value, Self::parse_num_literal_u8)?; } else if field_name == "apis" { // Intentionally ignored // @@ -147,6 +151,18 @@ impl ParseRuntimeVersion { lit.base10_parse::() } + fn parse_num_literal_u8(expr: &Expr) -> Result { + let lit = match *expr { + Expr::Lit(ExprLit { lit: Lit::Int(ref lit), .. }) => lit, + _ => + return Err(Error::new( + expr.span(), + "only numeric literals (e.g. `10`) are supported here", + )), + }; + lit.base10_parse::() + } + fn parse_str_literal(expr: &Expr) -> Result { let mac = match *expr { Expr::Macro(syn::ExprMacro { ref mac, .. }) => mac, @@ -182,6 +198,7 @@ impl ParseRuntimeVersion { spec_version, impl_version, transaction_version, + state_version, } = self; Ok(RuntimeVersion { @@ -191,6 +208,7 @@ impl ParseRuntimeVersion { spec_version: required!(spec_version), impl_version: required!(impl_version), transaction_version: required!(transaction_version), + state_version: required!(state_version), apis: 0, }) } @@ -210,7 +228,6 @@ fn generate_emit_link_section_decl(contents: &[u8], section_name: &str) -> Token #[cfg(test)] mod tests { use super::*; - use codec::DecodeAll; use std::borrow::Cow; #[test] @@ -223,11 +240,13 @@ mod tests { impl_version: 1, apis: 0, transaction_version: 2, + state_version: 1, } .encode(); assert_eq!( - sp_version::RuntimeVersion::decode_all(&mut &version_bytes[..]).unwrap(), + sp_version::RuntimeVersion::decode_with_version_hint(&mut &version_bytes[..], Some(4)) + .unwrap(), sp_version::RuntimeVersion { spec_name: "hello".into(), impl_name: "world".into(), @@ -236,6 +255,7 @@ mod tests { impl_version: 1, apis: Cow::Owned(vec![]), transaction_version: 2, + state_version: 1, }, ); } diff --git a/primitives/version/src/lib.rs b/primitives/version/src/lib.rs index 0b72865e7b69..74251aa4320f 100644 --- a/primitives/version/src/lib.rs +++ b/primitives/version/src/lib.rs @@ -40,10 +40,10 @@ use std::collections::HashSet; #[cfg(feature = "std")] use std::fmt; -use codec::{Decode, Encode}; +use codec::{Decode, Encode, Input}; use scale_info::TypeInfo; -pub use sp_runtime::create_runtime_str; use sp_runtime::RuntimeString; +pub use sp_runtime::{create_runtime_str, StateVersion}; #[doc(hidden)] pub use sp_std; @@ -79,6 +79,7 @@ pub mod embed; /// impl_version: 1, /// apis: RUNTIME_API_VERSIONS, /// transaction_version: 2, +/// state_version: 1, /// }; /// /// # const RUNTIME_API_VERSIONS: sp_version::ApisVec = sp_version::create_apis_vec!([]); @@ -154,7 +155,7 @@ macro_rules! create_apis_vec { /// In particular: bug fixes should result in an increment of `spec_version` and possibly /// `authoring_version`, absolutely not `impl_version` since they change the semantics of the /// runtime. -#[derive(Clone, PartialEq, Eq, Encode, Decode, Default, sp_runtime::RuntimeDebug, TypeInfo)] +#[derive(Clone, PartialEq, Eq, Encode, Default, sp_runtime::RuntimeDebug, TypeInfo)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] #[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] pub struct RuntimeVersion { @@ -207,6 +208,53 @@ pub struct RuntimeVersion { /// /// It need *not* change when a new module is added or when a dispatchable is added. pub transaction_version: u32, + + /// Version of the state implementation used by this runtime. + /// Use of an incorrect version is consensus breaking. + pub state_version: u8, +} + +impl RuntimeVersion { + /// `Decode` while giving a "version hint" + /// + /// There exists multiple versions of [`RuntimeVersion`] and they are versioned using the `Core` + /// runtime api: + /// - `Core` version < 3 is a runtime version without a transaction version and state version. + /// - `Core` version 3 is a runtime version without a state version. + /// - `Core` version 4 is the latest runtime version. + pub fn decode_with_version_hint( + input: &mut I, + core_version: Option, + ) -> Result { + let spec_name = Decode::decode(input)?; + let impl_name = Decode::decode(input)?; + let authoring_version = Decode::decode(input)?; + let spec_version = Decode::decode(input)?; + let impl_version = Decode::decode(input)?; + let apis = Decode::decode(input)?; + let core_version = + if core_version.is_some() { core_version } else { core_version_from_apis(&apis) }; + let transaction_version = + if core_version.map(|v| v >= 3).unwrap_or(false) { Decode::decode(input)? } else { 1 }; + let state_version = + if core_version.map(|v| v >= 4).unwrap_or(false) { Decode::decode(input)? } else { 0 }; + Ok(RuntimeVersion { + spec_name, + impl_name, + authoring_version, + spec_version, + impl_version, + apis, + transaction_version, + state_version, + }) + } +} + +impl Decode for RuntimeVersion { + fn decode(input: &mut I) -> Result { + Self::decode_with_version_hint(input, None) + } } #[cfg(feature = "std")] @@ -225,6 +273,16 @@ impl fmt::Display for RuntimeVersion { } } +fn has_api_with bool>(apis: &ApisVec, id: &ApiId, predicate: P) -> bool { + apis.iter().any(|(s, v)| s == id && predicate(*v)) +} + +/// Returns the version of the `Core` runtime api. +pub fn core_version_from_apis(apis: &ApisVec) -> Option { + let id = sp_core_hashing_proc_macro::blake2b_64!(b"Core"); + apis.iter().find(|(s, _v)| s == &id).map(|(_s, v)| *v) +} + #[cfg(feature = "std")] impl RuntimeVersion { /// Check if this version matches other version for calling into runtime. @@ -237,7 +295,7 @@ impl RuntimeVersion { /// Check if the given api with `api_id` is implemented and the version passes the given /// `predicate`. pub fn has_api_with bool>(&self, id: &ApiId, predicate: P) -> bool { - self.apis.iter().any(|(s, v)| s == id && predicate(*v)) + has_api_with(&self.apis, id, predicate) } /// Returns the api version found for api with `id`. @@ -246,6 +304,18 @@ impl RuntimeVersion { } } +impl RuntimeVersion { + /// Returns state version to use for update. + /// + /// For runtime with core api version less than 4, + /// V0 trie version will be applied to state. + /// Otherwhise, V1 trie version will be use. + pub fn state_version(&self) -> StateVersion { + // If version > than 1, keep using latest version. + self.state_version.try_into().unwrap_or(StateVersion::V1) + } +} + /// The version of the native runtime. /// /// In contrast to the bare [`RuntimeVersion`] this also carries a list of `spec_version`s of diff --git a/test-utils/client/src/client_ext.rs b/test-utils/client/src/client_ext.rs index bf1c9898972c..72828fdcc918 100644 --- a/test-utils/client/src/client_ext.rs +++ b/test-utils/client/src/client_ext.rs @@ -69,7 +69,7 @@ pub trait ClientBlockImportExt: Sized { impl ClientExt for Client where B: sc_client_api::backend::Backend, - E: sc_client_api::CallExecutor + 'static, + E: sc_client_api::CallExecutor + sc_executor::RuntimeVersionOf + 'static, Self: BlockImport, Block: BlockT, { diff --git a/test-utils/client/src/lib.rs b/test-utils/client/src/lib.rs index 86231bb34c50..6ba28d8c124f 100644 --- a/test-utils/client/src/lib.rs +++ b/test-utils/client/src/lib.rs @@ -208,13 +208,13 @@ impl sc_consensus::LongestChain, ) where - ExecutorDispatch: sc_client_api::CallExecutor + 'static, + ExecutorDispatch: + sc_client_api::CallExecutor + sc_executor::RuntimeVersionOf + 'static, Backend: sc_client_api::backend::Backend, >::OffchainStorage: 'static, { let storage = { let mut storage = self.genesis_init.genesis_storage(); - // Add some child storage keys. for (key, child_content) in self.child_storage_extension { storage.children_default.insert( diff --git a/test-utils/runtime/Cargo.toml b/test-utils/runtime/Cargo.toml index 35c1291f38fb..c32586834f30 100644 --- a/test-utils/runtime/Cargo.toml +++ b/test-utils/runtime/Cargo.toml @@ -39,7 +39,7 @@ pallet-timestamp = { version = "4.0.0-dev", default-features = false, path = ".. sp-finality-grandpa = { version = "4.0.0-dev", default-features = false, path = "../../primitives/finality-grandpa" } sp-trie = { version = "4.0.0", default-features = false, path = "../../primitives/trie" } sp-transaction-pool = { version = "4.0.0-dev", default-features = false, path = "../../primitives/transaction-pool" } -trie-db = { version = "0.22.6", default-features = false } +trie-db = { version = "0.23.0", default-features = false } parity-util-mem = { version = "0.10.2", default-features = false, features = ["primitive-types"] } sc-service = { version = "0.10.0-dev", default-features = false, optional = true, features = ["test-helpers"], path = "../../client/service" } sp-state-machine = { version = "0.10.0", default-features = false, path = "../../primitives/state-machine" } diff --git a/test-utils/runtime/client/src/lib.rs b/test-utils/runtime/client/src/lib.rs index a5d1e1966e30..d5c8a4fcb8a4 100644 --- a/test-utils/runtime/client/src/lib.rs +++ b/test-utils/runtime/client/src/lib.rs @@ -138,6 +138,7 @@ impl substrate_test_client::GenesisInit for GenesisParameters { let state_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root( child_content.data.clone().into_iter().collect(), + sp_runtime::StateVersion::V1, ); let prefixed_storage_key = child_content.child_info.prefixed_storage_key(); (prefixed_storage_key.into_inner(), state_root.encode()) @@ -145,6 +146,7 @@ impl substrate_test_client::GenesisInit for GenesisParameters { let state_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root( storage.top.clone().into_iter().chain(child_roots).collect(), + sp_runtime::StateVersion::V1, ); let block: runtime::Block = client::genesis::construct_genesis_block(state_root); storage.top.extend(additional_storage_with_genesis(&block)); diff --git a/test-utils/runtime/src/genesismap.rs b/test-utils/runtime/src/genesismap.rs index a06d9f310fb0..b81ed91ca6df 100644 --- a/test-utils/runtime/src/genesismap.rs +++ b/test-utils/runtime/src/genesismap.rs @@ -95,6 +95,7 @@ pub fn insert_genesis_block(storage: &mut Storage) -> sp_core::hash::H256 { let state_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root( child_content.data.clone().into_iter().collect(), + sp_runtime::StateVersion::V1, ); (sk.clone(), state_root.encode()) }); @@ -102,6 +103,7 @@ pub fn insert_genesis_block(storage: &mut Storage) -> sp_core::hash::H256 { storage.top.extend(child_roots); let state_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root( storage.top.clone().into_iter().collect(), + sp_runtime::StateVersion::V1, ); let block: crate::Block = genesis::construct_genesis_block(state_root); let genesis_hash = block.header.hash(); diff --git a/test-utils/runtime/src/lib.rs b/test-utils/runtime/src/lib.rs index 03e39be324e9..bf224b43946c 100644 --- a/test-utils/runtime/src/lib.rs +++ b/test-utils/runtime/src/lib.rs @@ -29,10 +29,7 @@ use sp_std::{marker::PhantomData, prelude::*}; use sp_application_crypto::{ecdsa, ed25519, sr25519, RuntimeAppPublic}; use sp_core::{offchain::KeyTypeId, OpaqueMetadata, RuntimeDebug}; -use sp_trie::{ - trie_types::{TrieDB, TrieDBMut}, - PrefixedMemoryDB, StorageProof, -}; +use sp_trie::{trie_types::TrieDB, PrefixedMemoryDB, StorageProof}; use trie_db::{Trie, TrieMut}; use cfg_if::cfg_if; @@ -62,6 +59,8 @@ use sp_runtime::{ #[cfg(any(feature = "std", test))] use sp_version::NativeVersion; use sp_version::RuntimeVersion; +// bench on latest state. +use sp_trie::trie_types::TrieDBMutV1 as TrieDBMut; // Ensure Babe and Aura use the same crypto to simplify things a bit. pub use sp_consensus_babe::{AllowedSlots, AuthorityId, Slot}; @@ -105,6 +104,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { impl_version: 2, apis: RUNTIME_API_VERSIONS, transaction_version: 1, + state_version: 1, }; fn version() -> RuntimeVersion { @@ -1268,9 +1268,9 @@ fn test_witness(proof: StorageProof, root: crate::Hash) { None, ); assert!(ext.storage(b"value3").is_some()); - assert!(ext.storage_root().as_slice() == &root[..]); + assert!(ext.storage_root(Default::default()).as_slice() == &root[..]); ext.place_storage(vec![0], Some(vec![1])); - assert!(ext.storage_root().as_slice() != &root[..]); + assert!(ext.storage_root(Default::default()).as_slice() != &root[..]); } #[cfg(test)] @@ -1334,7 +1334,7 @@ mod tests { let mut root = crate::Hash::default(); let mut mdb = sp_trie::MemoryDB::::default(); { - let mut trie = sp_trie::trie_types::TrieDBMut::new(&mut mdb, &mut root); + let mut trie = sp_trie::trie_types::TrieDBMutV1::new(&mut mdb, &mut root); trie.insert(b"value3", &[142]).expect("insert failed"); trie.insert(b"value4", &[124]).expect("insert failed"); }; diff --git a/test-utils/runtime/src/system.rs b/test-utils/runtime/src/system.rs index 0c72c083baae..57eae0aecf04 100644 --- a/test-utils/runtime/src/system.rs +++ b/test-utils/runtime/src/system.rs @@ -194,9 +194,10 @@ pub fn execute_transaction(utx: Extrinsic) -> ApplyExtrinsicResult { /// Finalize the block. pub fn finalize_block() -> Header { + use sp_core::storage::StateVersion; let extrinsic_index: u32 = storage::unhashed::take(well_known_keys::EXTRINSIC_INDEX).unwrap(); let txs: Vec<_> = (0..extrinsic_index).map(ExtrinsicData::take).collect(); - let extrinsics_root = trie::blake2_256_ordered_root(txs).into(); + let extrinsics_root = trie::blake2_256_ordered_root(txs, StateVersion::V0).into(); let number = ::take().expect("Number is set by `initialize_block`"); let parent_hash = ::take(); let mut digest = ::take().expect("StorageDigest is set by `initialize_block`"); @@ -205,8 +206,8 @@ pub fn finalize_block() -> Header { // This MUST come after all changes to storage are done. Otherwise we will fail the // “Storage root does not match that calculated” assertion. - let storage_root = - Hash::decode(&mut &storage_root()[..]).expect("`storage_root` is a valid hash"); + let storage_root = Hash::decode(&mut &storage_root(StateVersion::V1)[..]) + .expect("`storage_root` is a valid hash"); if let Some(new_authorities) = o_new_authorities { digest.push(generic::DigestItem::Consensus(*b"aura", new_authorities.encode())); @@ -351,6 +352,7 @@ mod tests { Sr25519Keyring::Bob.to_raw_public(), Sr25519Keyring::Charlie.to_raw_public(), ]; + TestExternalities::new_with_code( wasm_binary_unwrap(), sp_core::storage::Storage { @@ -359,7 +361,7 @@ mod tests { twox_128(b"sys:auth").to_vec() => authorities.encode(), blake2_256(&AccountKeyring::Alice.to_raw_public().to_keyed_vec(b"balance:")).to_vec() => { vec![111u8, 0, 0, 0, 0, 0, 0, 0] - } + }, ], children_default: map![], }, diff --git a/utils/frame/try-runtime/cli/src/commands/execute_block.rs b/utils/frame/try-runtime/cli/src/commands/execute_block.rs index a717b410c2bf..f092f6eaf471 100644 --- a/utils/frame/try-runtime/cli/src/commands/execute_block.rs +++ b/utils/frame/try-runtime/cli/src/commands/execute_block.rs @@ -157,7 +157,7 @@ where header.digest_mut().pop(); let block = Block::new(header, extrinsics); - let (expected_spec_name, expected_spec_version) = + let (expected_spec_name, expected_spec_version, _) = local_spec::(&ext, &executor); ensure_matching_spec::( block_ws_uri.clone(), diff --git a/utils/frame/try-runtime/cli/src/commands/follow_chain.rs b/utils/frame/try-runtime/cli/src/commands/follow_chain.rs index 09f541c88753..dbc1c3005f06 100644 --- a/utils/frame/try-runtime/cli/src/commands/follow_chain.rs +++ b/utils/frame/try-runtime/cli/src/commands/follow_chain.rs @@ -123,7 +123,7 @@ where new_ext.as_backend().root() ); - let (expected_spec_name, expected_spec_version) = + let (expected_spec_name, expected_spec_version, spec_state_version) = local_spec::(&new_ext, &executor); ensure_matching_spec::( command.uri.clone(), @@ -133,10 +133,10 @@ where ) .await; - maybe_state_ext = Some(new_ext); + maybe_state_ext = Some((new_ext, spec_state_version)); } - let state_ext = + let (state_ext, spec_state_version) = maybe_state_ext.as_mut().expect("state_ext either existed or was just created"); let (mut changes, encoded_result) = state_machine_call_with_proof::( @@ -152,7 +152,16 @@ where .map_err(|e| format!("failed to decode output: {:?}", e))?; let storage_changes = changes - .drain_storage_changes(&state_ext.backend, Default::default(), &mut Default::default()) + .drain_storage_changes( + &state_ext.backend, + Default::default(), + &mut Default::default(), + // Note that in case a block contains a runtime upgrade, + // state version could potentially be incorrect here, + // this is very niche and would only result in unaligned + // roots, so this use case is ignored for now. + *spec_state_version, + ) .unwrap(); state_ext.backend.apply_transaction( storage_changes.transaction_storage_root, diff --git a/utils/frame/try-runtime/cli/src/commands/offchain_worker.rs b/utils/frame/try-runtime/cli/src/commands/offchain_worker.rs index 22120ef4b5fe..8839c5556900 100644 --- a/utils/frame/try-runtime/cli/src/commands/offchain_worker.rs +++ b/utils/frame/try-runtime/cli/src/commands/offchain_worker.rs @@ -140,7 +140,7 @@ where builder.build().await? }; - let (expected_spec_name, expected_spec_version) = + let (expected_spec_name, expected_spec_version, _) = local_spec::(&ext, &executor); ensure_matching_spec::( header_ws_uri, diff --git a/utils/frame/try-runtime/cli/src/commands/on_runtime_upgrade.rs b/utils/frame/try-runtime/cli/src/commands/on_runtime_upgrade.rs index 6343b2b2e3f0..3b5a3db72a8f 100644 --- a/utils/frame/try-runtime/cli/src/commands/on_runtime_upgrade.rs +++ b/utils/frame/try-runtime/cli/src/commands/on_runtime_upgrade.rs @@ -58,7 +58,7 @@ where }; if let Some(uri) = command.state.live_uri() { - let (expected_spec_name, expected_spec_version) = + let (expected_spec_name, expected_spec_version, _) = local_spec::(&ext, &executor); ensure_matching_spec::( uri, diff --git a/utils/frame/try-runtime/cli/src/lib.rs b/utils/frame/try-runtime/cli/src/lib.rs index 3872f84a62a4..9f8af6906a35 100644 --- a/utils/frame/try-runtime/cli/src/lib.rs +++ b/utils/frame/try-runtime/cli/src/lib.rs @@ -799,7 +799,7 @@ pub(crate) fn state_machine_call_with_proof( ext: &TestExternalities, executor: &NativeElseWasmExecutor, -) -> (String, u32) { +) -> (String, u32, sp_core::storage::StateVersion) { let (_, encoded) = state_machine_call::( &ext, &executor, @@ -811,6 +811,9 @@ pub(crate) fn local_spec( .expect("all runtimes should have version; qed"); ::decode(&mut &*encoded) .map_err(|e| format!("failed to decode output: {:?}", e)) - .map(|v| (v.spec_name.into(), v.spec_version)) + .map(|v| { + let state_version = v.state_version(); + (v.spec_name.into(), v.spec_version, state_version) + }) .expect("all runtimes should have version; qed") } From 82d87bcd8829aa1ba40b831e5ea2cac1a5efbdee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Sat, 25 Dec 2021 08:19:46 +0100 Subject: [PATCH 336/695] Improve SS58 related errors (#10541) * Improve SS58 related errors This improves the SS58 error, especially when it comes to parsing public keys with unknown SS58 address formats. * Make CI happy * More fixes * More * :facepalm: * fml... --- primitives/core/src/crypto.rs | 58 +++++++++++++++++++++--------- primitives/core/src/ecdsa.rs | 65 ++++------------------------------ primitives/core/src/ed25519.rs | 36 ++----------------- primitives/core/src/sr25519.rs | 18 ++-------- 4 files changed, 52 insertions(+), 125 deletions(-) diff --git a/primitives/core/src/crypto.rs b/primitives/core/src/crypto.rs index 671f526fde32..e6735c7745cf 100644 --- a/primitives/core/src/crypto.rs +++ b/primitives/core/src/crypto.rs @@ -198,25 +198,45 @@ impl> From for DeriveJunction { } /// An error type for SS58 decoding. +#[cfg_attr(feature = "std", derive(thiserror::Error))] +#[cfg_attr(not(feature = "std"), derive(Debug))] +#[derive(Clone, Copy, Eq, PartialEq)] +#[allow(missing_docs)] #[cfg(feature = "full_crypto")] -#[derive(Clone, Copy, Eq, PartialEq, Debug)] pub enum PublicError { - /// Bad alphabet. + #[cfg_attr(feature = "std", error("Base 58 requirement is violated"))] BadBase58, - /// Bad length. + #[cfg_attr(feature = "std", error("Length is bad"))] BadLength, - /// Unknown identifier for the encoding. - UnknownVersion, - /// Invalid checksum. + #[cfg_attr( + feature = "std", + error( + "Unknown SS58 address format `{}`. ` \ + `To support this address format, you need to call `set_default_ss58_version` at node start up.", + _0 + ) + )] + UnknownSs58AddressFormat(Ss58AddressFormat), + #[cfg_attr(feature = "std", error("Invalid checksum"))] InvalidChecksum, - /// Invalid format. + #[cfg_attr(feature = "std", error("Invalid SS58 prefix byte."))] + InvalidPrefix, + #[cfg_attr(feature = "std", error("Invalid SS58 format."))] InvalidFormat, - /// Invalid derivation path. + #[cfg_attr(feature = "std", error("Invalid derivation path."))] InvalidPath, - /// Disallowed SS58 Address Format for this datatype. + #[cfg_attr(feature = "std", error("Disallowed SS58 Address Format for this datatype."))] FormatNotAllowed, } +#[cfg(feature = "std")] +impl sp_std::fmt::Debug for PublicError { + fn fmt(&self, f: &mut sp_std::fmt::Formatter<'_>) -> sp_std::fmt::Result { + // Just use the `Display` implementation + write!(f, "{}", self) + } +} + /// Key that can be encoded to/from SS58. /// /// See @@ -235,7 +255,7 @@ pub trait Ss58Codec: Sized + AsMut<[u8]> + AsRef<[u8]> + ByteArray { Self::from_ss58check_with_version(s).and_then(|(r, v)| match v { v if !v.is_custom() => Ok(r), v if v == default_ss58_version() => Ok(r), - _ => Err(PublicError::UnknownVersion), + v => Err(PublicError::UnknownSs58AddressFormat(v)), }) } @@ -261,7 +281,7 @@ pub trait Ss58Codec: Sized + AsMut<[u8]> + AsRef<[u8]> + ByteArray { let upper = data[1] & 0b00111111; (2, (lower as u16) | ((upper as u16) << 8)) }, - _ => return Err(PublicError::UnknownVersion), + _ => return Err(PublicError::InvalidPrefix), }; if data.len() != prefix_len + body_len + CHECKSUM_LEN { return Err(PublicError::BadLength) @@ -290,7 +310,7 @@ pub trait Ss58Codec: Sized + AsMut<[u8]> + AsRef<[u8]> + ByteArray { Self::from_string_with_version(s).and_then(|(r, v)| match v { v if !v.is_custom() => Ok(r), v if v == default_ss58_version() => Ok(r), - _ => Err(PublicError::UnknownVersion), + v => Err(PublicError::UnknownSs58AddressFormat(v)), }) } @@ -359,7 +379,7 @@ static DEFAULT_VERSION: core::sync::atomic::AtomicU16 = std::sync::atomic::Atomi from_known_address_format(Ss58AddressFormatRegistry::SubstrateAccount), ); -/// Returns default ss58 format used by the current active process. +/// Returns default SS58 format used by the current active process. #[cfg(feature = "std")] pub fn default_ss58_version() -> Ss58AddressFormat { DEFAULT_VERSION.load(std::sync::atomic::Ordering::Relaxed).into() @@ -371,9 +391,15 @@ pub fn unwrap_or_default_ss58_version(network: Option) -> Ss5 network.unwrap_or_else(default_ss58_version) } -/// Set the default "version" (actually, this is a bit of a misnomer and the version byte is -/// typically used not just to encode format/version but also network identity) that is used for -/// encoding and decoding SS58 addresses. +/// Set the default SS58 "version". +/// +/// This SS58 version/format will be used when encoding/decoding SS58 addresses. +/// +/// If you want to support a custom SS58 prefix (that isn't yet registered in the `ss58-registry`), +/// you are required to call this function with your desired prefix [`Ss58AddressFormat::custom`]. +/// This will enable the node to decode ss58 addresses with this prefix. +/// +/// This SS58 version/format is also only used by the node and not by the runtime. #[cfg(feature = "std")] pub fn set_default_ss58_version(new_default: Ss58AddressFormat) { DEFAULT_VERSION.store(new_default.into(), std::sync::atomic::Ordering::Relaxed); diff --git a/primitives/core/src/ecdsa.rs b/primitives/core/src/ecdsa.rs index 827be8eb9aab..682f46c2a432 100644 --- a/primitives/core/src/ecdsa.rs +++ b/primitives/core/src/ecdsa.rs @@ -22,7 +22,6 @@ use codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; use sp_runtime_interface::pass_by::PassByInner; -use sp_std::cmp::Ordering; #[cfg(feature = "std")] use crate::crypto::Ss58Codec; @@ -56,43 +55,12 @@ pub const CRYPTO_ID: CryptoTypeId = CryptoTypeId(*b"ecds"); type Seed = [u8; 32]; /// The ECDSA compressed public key. -#[derive(Clone, Encode, Decode, PassByInner, MaxEncodedLen, TypeInfo)] +#[cfg_attr(feature = "full_crypto", derive(Hash))] +#[derive( + Clone, Encode, Decode, PassByInner, MaxEncodedLen, TypeInfo, Eq, PartialEq, PartialOrd, Ord, +)] pub struct Public(pub [u8; 33]); -impl PartialOrd for Public { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl Ord for Public { - fn cmp(&self, other: &Self) -> Ordering { - self.as_ref().cmp(&other.as_ref()) - } -} - -impl PartialEq for Public { - fn eq(&self, other: &Self) -> bool { - self.as_ref() == other.as_ref() - } -} - -impl Eq for Public {} - -/// An error type for SS58 decoding. -#[cfg(feature = "std")] -#[derive(Clone, Copy, Eq, PartialEq, Debug)] -pub enum PublicError { - /// Bad alphabet. - BadBase58, - /// Bad length. - BadLength, - /// Unknown version. - UnknownVersion, - /// Invalid checksum. - InvalidChecksum, -} - impl Public { /// A new instance from the given 33-byte `data`. /// @@ -217,15 +185,9 @@ impl<'de> Deserialize<'de> for Public { } } -#[cfg(feature = "full_crypto")] -impl sp_std::hash::Hash for Public { - fn hash(&self, state: &mut H) { - self.as_ref().hash(state); - } -} - /// A signature (a 512-bit value, plus 8 bits for recovery ID). -#[derive(Encode, Decode, PassByInner, TypeInfo)] +#[cfg_attr(feature = "full_crypto", derive(Hash))] +#[derive(Encode, Decode, PassByInner, TypeInfo, PartialEq, Eq)] pub struct Signature(pub [u8; 65]); impl sp_std::convert::TryFrom<&[u8]> for Signature { @@ -279,14 +241,6 @@ impl Default for Signature { } } -impl PartialEq for Signature { - fn eq(&self, b: &Self) -> bool { - self.0[..] == b.0[..] - } -} - -impl Eq for Signature {} - impl From for [u8; 65] { fn from(v: Signature) -> [u8; 65] { v.0 @@ -323,13 +277,6 @@ impl sp_std::fmt::Debug for Signature { } } -#[cfg(feature = "full_crypto")] -impl sp_std::hash::Hash for Signature { - fn hash(&self, state: &mut H) { - sp_std::hash::Hash::hash(&self.0[..], state); - } -} - impl UncheckedFrom<[u8; 65]> for Signature { fn unchecked_from(data: [u8; 65]) -> Signature { Signature(data) diff --git a/primitives/core/src/ed25519.rs b/primitives/core/src/ed25519.rs index 7d60998b15df..df9ec6a457c6 100644 --- a/primitives/core/src/ed25519.rs +++ b/primitives/core/src/ed25519.rs @@ -211,7 +211,8 @@ impl<'de> Deserialize<'de> for Public { } /// A signature (a 512-bit value). -#[derive(Encode, Decode, PassByInner, TypeInfo)] +#[cfg_attr(feature = "full_crypto", derive(Hash))] +#[derive(Encode, Decode, PassByInner, TypeInfo, PartialEq, Eq)] pub struct Signature(pub [u8; 64]); impl sp_std::convert::TryFrom<&[u8]> for Signature { @@ -259,14 +260,6 @@ impl Clone for Signature { } } -impl PartialEq for Signature { - fn eq(&self, b: &Self) -> bool { - self.0[..] == b.0[..] - } -} - -impl Eq for Signature {} - impl From for H512 { fn from(v: Signature) -> H512 { H512::from(v.0) @@ -309,13 +302,6 @@ impl sp_std::fmt::Debug for Signature { } } -#[cfg(feature = "full_crypto")] -impl sp_std::hash::Hash for Signature { - fn hash(&self, state: &mut H) { - sp_std::hash::Hash::hash(&self.0[..], state); - } -} - impl UncheckedFrom<[u8; 64]> for Signature { fn unchecked_from(data: [u8; 64]) -> Signature { Signature(data) @@ -360,24 +346,6 @@ pub struct LocalizedSignature { pub signature: Signature, } -/// An error type for SS58 decoding. -#[cfg(feature = "std")] -#[derive(Clone, Copy, Eq, PartialEq, Debug, thiserror::Error)] -pub enum PublicError { - /// Bad alphabet. - #[error("Base 58 requirement is violated")] - BadBase58, - /// Bad length. - #[error("Length is bad")] - BadLength, - /// Unknown version. - #[error("Unknown version")] - UnknownVersion, - /// Invalid checksum. - #[error("Invalid checksum")] - InvalidChecksum, -} - impl Public { /// A new instance from the given 32-byte `data`. /// diff --git a/primitives/core/src/sr25519.rs b/primitives/core/src/sr25519.rs index 97e9de5de09a..71379dfc66b9 100644 --- a/primitives/core/src/sr25519.rs +++ b/primitives/core/src/sr25519.rs @@ -211,7 +211,8 @@ impl<'de> Deserialize<'de> for Public { /// An Schnorrkel/Ristretto x25519 ("sr25519") signature. /// /// Instead of importing it for the local module, alias it to be available as a public type -#[derive(Encode, Decode, PassByInner, TypeInfo)] +#[cfg_attr(feature = "full_crypto", derive(Hash))] +#[derive(Encode, Decode, PassByInner, TypeInfo, PartialEq, Eq)] pub struct Signature(pub [u8; 64]); impl sp_std::convert::TryFrom<&[u8]> for Signature { @@ -259,14 +260,6 @@ impl Clone for Signature { } } -impl PartialEq for Signature { - fn eq(&self, b: &Self) -> bool { - self.0[..] == b.0[..] - } -} - -impl Eq for Signature {} - impl From for [u8; 64] { fn from(v: Signature) -> [u8; 64] { v.0 @@ -316,13 +309,6 @@ impl sp_std::fmt::Debug for Signature { } } -#[cfg(feature = "full_crypto")] -impl sp_std::hash::Hash for Signature { - fn hash(&self, state: &mut H) { - sp_std::hash::Hash::hash(&self.0[..], state); - } -} - /// A localized signature also contains sender information. /// NOTE: Encode and Decode traits are supported in ed25519 but not possible for now here. #[cfg(feature = "std")] From ba973636c86b8038ad0c8bfdbd4f4d496e86adaa Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Sun, 26 Dec 2021 16:48:51 +0200 Subject: [PATCH 337/695] Add beefy-gadget-rpc tests (#10555) * beefy: add RPC tests * beefy: add more RPC tests --- Cargo.lock | 2 + client/beefy/rpc/Cargo.toml | 8 +++ client/beefy/rpc/src/lib.rs | 132 ++++++++++++++++++++++++++++++++++++ 3 files changed, 142 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index c6dd25ffd74a..e58275738c92 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -516,8 +516,10 @@ dependencies = [ "parity-scale-codec", "sc-rpc", "serde", + "serde_json", "sp-core", "sp-runtime", + "substrate-test-runtime-client", ] [[package]] diff --git a/client/beefy/rpc/Cargo.toml b/client/beefy/rpc/Cargo.toml index 847f054f4663..c14d604990cb 100644 --- a/client/beefy/rpc/Cargo.toml +++ b/client/beefy/rpc/Cargo.toml @@ -26,3 +26,11 @@ sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } beefy-gadget = { version = "4.0.0-dev", path = "../." } beefy-primitives = { version = "4.0.0-dev", path = "../../../primitives/beefy" } + +[dev-dependencies] +serde_json = "1.0.50" + +sc-rpc = { version = "4.0.0-dev", path = "../../rpc", features = [ + "test-helpers", +] } +substrate-test-runtime-client = { version = "2.0.0", path = "../../../test-utils/runtime/client" } diff --git a/client/beefy/rpc/src/lib.rs b/client/beefy/rpc/src/lib.rs index c9a09525569b..7370ca092727 100644 --- a/client/beefy/rpc/src/lib.rs +++ b/client/beefy/rpc/src/lib.rs @@ -112,3 +112,135 @@ where Ok(self.manager.cancel(id)) } } + +#[cfg(test)] +mod tests { + use super::*; + use jsonrpc_core::{types::Params, Notification, Output}; + + use beefy_gadget::notification::{BeefySignedCommitmentSender, SignedCommitment}; + use beefy_primitives::{known_payload_ids, Payload}; + use codec::{Decode, Encode}; + use substrate_test_runtime_client::runtime::Block; + + fn setup_io_handler( + ) -> (jsonrpc_core::MetaIoHandler, BeefySignedCommitmentSender) { + let (commitment_sender, commitment_stream) = BeefySignedCommitmentStream::channel(); + + let handler = BeefyRpcHandler::new(commitment_stream, sc_rpc::testing::TaskExecutor); + + let mut io = jsonrpc_core::MetaIoHandler::default(); + io.extend_with(BeefyApi::to_delegate(handler)); + + (io, commitment_sender) + } + + fn setup_session() -> (sc_rpc::Metadata, futures::channel::mpsc::UnboundedReceiver) { + let (tx, rx) = futures::channel::mpsc::unbounded(); + let meta = sc_rpc::Metadata::new(tx); + (meta, rx) + } + + #[test] + fn subscribe_and_unsubscribe_to_justifications() { + let (io, _) = setup_io_handler(); + let (meta, _) = setup_session(); + + // Subscribe + let sub_request = + r#"{"jsonrpc":"2.0","method":"beefy_subscribeJustifications","params":[],"id":1}"#; + let resp = io.handle_request_sync(sub_request, meta.clone()); + let resp: Output = serde_json::from_str(&resp.unwrap()).unwrap(); + + let sub_id = match resp { + Output::Success(success) => success.result, + _ => panic!(), + }; + + // Unsubscribe + let unsub_req = format!( + "{{\"jsonrpc\":\"2.0\",\"method\":\"beefy_unsubscribeJustifications\",\"params\":[{}],\"id\":1}}", + sub_id + ); + assert_eq!( + io.handle_request_sync(&unsub_req, meta.clone()), + Some(r#"{"jsonrpc":"2.0","result":true,"id":1}"#.into()), + ); + + // Unsubscribe again and fail + assert_eq!( + io.handle_request_sync(&unsub_req, meta), + Some("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32602,\"message\":\"Invalid subscription id.\"},\"id\":1}".into()), + ); + } + + #[test] + fn subscribe_and_unsubscribe_with_wrong_id() { + let (io, _) = setup_io_handler(); + let (meta, _) = setup_session(); + + // Subscribe + let sub_request = + r#"{"jsonrpc":"2.0","method":"beefy_subscribeJustifications","params":[],"id":1}"#; + let resp = io.handle_request_sync(sub_request, meta.clone()); + let resp: Output = serde_json::from_str(&resp.unwrap()).unwrap(); + assert!(matches!(resp, Output::Success(_))); + + // Unsubscribe with wrong ID + assert_eq!( + io.handle_request_sync( + r#"{"jsonrpc":"2.0","method":"beefy_unsubscribeJustifications","params":["FOO"],"id":1}"#, + meta.clone() + ), + Some("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32602,\"message\":\"Invalid subscription id.\"},\"id\":1}".into()) + ); + } + + fn create_commitment() -> SignedCommitment { + let payload = Payload::new(known_payload_ids::MMR_ROOT_ID, "Hello World!".encode()); + SignedCommitment:: { + commitment: beefy_primitives::Commitment { + payload, + block_number: 5, + validator_set_id: 0, + }, + signatures: vec![], + } + } + + #[test] + fn subscribe_and_listen_to_one_justification() { + let (io, commitment_sender) = setup_io_handler(); + let (meta, receiver) = setup_session(); + + // Subscribe + let sub_request = + r#"{"jsonrpc":"2.0","method":"beefy_subscribeJustifications","params":[],"id":1}"#; + + let resp = io.handle_request_sync(sub_request, meta.clone()); + let mut resp: serde_json::Value = serde_json::from_str(&resp.unwrap()).unwrap(); + let sub_id: String = serde_json::from_value(resp["result"].take()).unwrap(); + + // Notify with commitment + let commitment = create_commitment(); + commitment_sender.notify(commitment.clone()); + + // Inspect what we received + let recv = futures::executor::block_on(receiver.take(1).collect::>()); + let recv: Notification = serde_json::from_str(&recv[0]).unwrap(); + let mut json_map = match recv.params { + Params::Map(json_map) => json_map, + _ => panic!(), + }; + + let recv_sub_id: String = serde_json::from_value(json_map["subscription"].take()).unwrap(); + let recv_commitment: sp_core::Bytes = + serde_json::from_value(json_map["result"].take()).unwrap(); + let recv_commitment: SignedCommitment = + Decode::decode(&mut &recv_commitment[..]).unwrap(); + + assert_eq!(recv.method, "beefy_justifications"); + assert_eq!(recv_sub_id, sub_id); + assert_eq!(recv_commitment, commitment); + } +} From a1fc5cff2ad979697384b24dd52671ccba0bf128 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Paulo=20Silva=20de=20Souza?= <77391175+joao-paulo-parity@users.noreply.github.com> Date: Mon, 27 Dec 2021 06:21:33 -0300 Subject: [PATCH 338/695] make check-dependent-* only be executed in PRs (#10545) Make check-dependent-* jobs only be executed in PRs instead of both PRs and master. Reason 1: The companion is not merged at the same time as the parent PR ([1](https://github.com/paritytech/parity-processbot/issues/347#issuecomment-994729950)), therefore the pipeline will fail on master since the companion PR is not yet merged in the other repository. This scenario is demonstrated by the pipeline of https://github.com/paritytech/substrate/commit/82cc3746450ae9722a249f4ddf83b8de59ba6e0d. Reason 2: The job can still fail on master due to a new commit on the companion PR's repository which was merged after `bot merge` happened, as demonstrated by the following scheme: 1. Parent PR is merged 2. Companion PR is updated and set to merge in the future 3. In the meantime a new commit is merged into the companion PR repository's master branch 4. The `check-dependent-*` job runs on master but, due to the new commit, it fails for unrelated reasons While "Reason 2" can be used as an argument against this PR, in that it would be useful to know if the integration is failing on master, "Reason 1" should be taken care of due to this inherent flaw of the current companion build system design. --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 589adeec5260..685d201d8598 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -575,7 +575,7 @@ cargo-check-macos: .check-dependent-project: &check-dependent-project stage: build <<: *docker-env - <<: *test-refs-no-trigger + <<: *test-refs-no-trigger-prs-only <<: *vault-secrets script: - git clone From e19dfaab053ed1d5ecf19bc25b004ec1fc2ba6c3 Mon Sep 17 00:00:00 2001 From: Squirrel Date: Tue, 28 Dec 2021 23:22:48 +0000 Subject: [PATCH 339/695] Tweak to pallet-nicks (#10565) * Slightly easier for humans to parse * cargo fmt * Use the simpler format for construct_runtime. --- frame/nicks/src/lib.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/frame/nicks/src/lib.rs b/frame/nicks/src/lib.rs index 91918ce84600..6d9c15fd3da1 100644 --- a/frame/nicks/src/lib.rs +++ b/frame/nicks/src/lib.rs @@ -43,11 +43,10 @@ pub use pallet::*; use sp_runtime::traits::{StaticLookup, Zero}; use sp_std::prelude::*; -type BalanceOf = - <::Currency as Currency<::AccountId>>::Balance; -type NegativeImbalanceOf = <::Currency as Currency< - ::AccountId, ->>::NegativeImbalance; +type AccountIdOf = ::AccountId; +type BalanceOf = <::Currency as Currency>>::Balance; +type NegativeImbalanceOf = + <::Currency as Currency>>::NegativeImbalance; #[frame_support::pallet] pub mod pallet { @@ -265,9 +264,9 @@ mod tests { NodeBlock = Block, UncheckedExtrinsic = UncheckedExtrinsic, { - System: frame_system::{Pallet, Call, Config, Storage, Event}, - Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, - Nicks: pallet_nicks::{Pallet, Call, Storage, Event}, + System: frame_system, + Balances: pallet_balances, + Nicks: pallet_nicks, } ); From f57c6447af83a1706041d462ca290b4f2a1bac4f Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Tue, 28 Dec 2021 19:42:58 -0400 Subject: [PATCH 340/695] Fix Places where AccountId Uses Default (#10556) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix places where accountid is default * Update frame/system/src/lib.rs * fmt * add simple test Co-authored-by: Bastian Köcher --- frame/system/src/lib.rs | 14 ++++++++++---- frame/system/src/tests.rs | 23 +++++++++++++++++++++++ 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/frame/system/src/lib.rs b/frame/system/src/lib.rs index 8026f77902ba..726837bf8267 100644 --- a/frame/system/src/lib.rs +++ b/frame/system/src/lib.rs @@ -820,7 +820,7 @@ impl, O>> + From>, Acco } pub struct EnsureSigned(sp_std::marker::PhantomData); -impl, O>> + From>, AccountId: Default> +impl, O>> + From>, AccountId: Decode> EnsureOrigin for EnsureSigned { type Success = AccountId; @@ -833,7 +833,10 @@ impl, O>> + From>, Acco #[cfg(feature = "runtime-benchmarks")] fn successful_origin() -> O { - O::from(RawOrigin::Signed(Default::default())) + let zero_account_id = + AccountId::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()) + .expect("infinite length input; no invalid inputs for type; qed"); + O::from(RawOrigin::Signed(zero_account_id)) } } @@ -841,7 +844,7 @@ pub struct EnsureSignedBy(sp_std::marker::PhantomData<(Who, Acco impl< O: Into, O>> + From>, Who: SortedMembers, - AccountId: PartialEq + Clone + Ord + Default, + AccountId: PartialEq + Clone + Ord + Decode, > EnsureOrigin for EnsureSignedBy { type Success = AccountId; @@ -854,10 +857,13 @@ impl< #[cfg(feature = "runtime-benchmarks")] fn successful_origin() -> O { + let zero_account_id = + AccountId::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()) + .expect("infinite length input; no invalid inputs for type; qed"); let members = Who::sorted_members(); let first_member = match members.get(0) { Some(account) => account.clone(), - None => Default::default(), + None => zero_account_id, }; O::from(RawOrigin::Signed(first_member.clone())) } diff --git a/frame/system/src/tests.rs b/frame/system/src/tests.rs index d8f9fd1af2bc..de3158562f49 100644 --- a/frame/system/src/tests.rs +++ b/frame/system/src/tests.rs @@ -486,3 +486,26 @@ fn runtime_updated_digest_emitted_when_heap_pages_changed() { assert_runtime_updated_digest(1); }); } + +#[test] +fn ensure_signed_stuff_works() { + struct Members; + impl SortedMembers for Members { + fn sorted_members() -> Vec { + (0..10).collect() + } + } + + let signed_origin = Origin::signed(0u64); + assert_ok!(EnsureSigned::try_origin(signed_origin.clone())); + assert_ok!(EnsureSignedBy::::try_origin(signed_origin)); + + #[cfg(feature = "runtime-benchmarks")] + { + let successful_origin: Origin = EnsureSigned::successful_origin(); + assert_ok!(EnsureSigned::try_origin(successful_origin)); + + let successful_origin: Origin = EnsureSignedBy::::successful_origin(); + assert_ok!(EnsureSignedBy::::try_origin(successful_origin)); + } +} From 88a003283c6279bec634ba1630e738a8d0fdf8de Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Andres Date: Thu, 30 Dec 2021 19:32:59 +0100 Subject: [PATCH 341/695] node-template README persistent db (#10558) --- bin/node-template/README.md | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/bin/node-template/README.md b/bin/node-template/README.md index 2397c57363b7..bb4df52f41a8 100644 --- a/bin/node-template/README.md +++ b/bin/node-template/README.md @@ -55,7 +55,7 @@ node. ### Single-Node Development Chain -This command will start the single-node development chain with persistent state: +This command will start the single-node development chain with non-persistent state: ```bash ./target/release/node-template --dev @@ -72,6 +72,36 @@ Start the development chain with detailed logging: ```bash RUST_BACKTRACE=1 ./target/release/node-template -ldebug --dev ``` +> Development chain means that the state of our chain will be in a tmp folder while the nodes are +> running. Also, **alice** account will be authority and sudo account as declared in the [genesis +> state](https://github.com/substrate-developer-hub/substrate-node-template/blob/main/node/src/chain_spec.rs#L49). +> At the same time the following accounts will be prefunded: +> - Alice +> - Bob +> - Alice//stash +> - Bob//stash + +In case of being interested in maintaining the chain' state futher in time a base path other than +a temporary directory must be added so the db can be stored in the provided folder. We could use +this folder to store different chain databases, as a different folder will be created per different + chain that is ran. The following commands shows how to use a newly created folder as our db base + path. + +```bash +// Create a folder to use as the db base path +$ mkdir my-chain-state + +// Use of that folder to store the chain state +$ ./target/release/node-template --dev --base-path ./my-chain-state/ + +// Check the folder structure created inside the base path after running the chain +$ ls ./my-chain-state +chains +$ ls ./my-chain-state/chains/ +dev +$ ls ./my-chain-state/chains/dev +db keystore network +``` ### Connect with Polkadot-JS Apps Front-end From 1ca6b68cf8cd35a1c58f790c28e51ae726272ee9 Mon Sep 17 00:00:00 2001 From: green-jay <75261756+green-jay@users.noreply.github.com> Date: Fri, 31 Dec 2021 11:49:04 +0100 Subject: [PATCH 342/695] Expose Uniques helper functions and DestroyWitness fields (#10529) --- frame/uniques/src/functions.rs | 10 +++++----- frame/uniques/src/types.rs | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/frame/uniques/src/functions.rs b/frame/uniques/src/functions.rs index e0ee09ab62d9..9c3a5c1b19f8 100644 --- a/frame/uniques/src/functions.rs +++ b/frame/uniques/src/functions.rs @@ -22,7 +22,7 @@ use frame_support::{ensure, traits::Get}; use sp_runtime::{DispatchError, DispatchResult}; impl, I: 'static> Pallet { - pub(crate) fn do_transfer( + pub fn do_transfer( class: T::ClassId, instance: T::InstanceId, dest: T::AccountId, @@ -53,7 +53,7 @@ impl, I: 'static> Pallet { Ok(()) } - pub(super) fn do_create_class( + pub fn do_create_class( class: T::ClassId, owner: T::AccountId, admin: T::AccountId, @@ -86,7 +86,7 @@ impl, I: 'static> Pallet { Ok(()) } - pub(super) fn do_destroy_class( + pub fn do_destroy_class( class: T::ClassId, witness: DestroyWitness, maybe_check_owner: Option, @@ -122,7 +122,7 @@ impl, I: 'static> Pallet { }) } - pub(super) fn do_mint( + pub fn do_mint( class: T::ClassId, instance: T::InstanceId, owner: T::AccountId, @@ -157,7 +157,7 @@ impl, I: 'static> Pallet { Ok(()) } - pub(super) fn do_burn( + pub fn do_burn( class: T::ClassId, instance: T::InstanceId, with_details: impl FnOnce(&ClassDetailsFor, &InstanceDetailsFor) -> DispatchResult, diff --git a/frame/uniques/src/types.rs b/frame/uniques/src/types.rs index 1e4405aa09c8..5ba443dba6c4 100644 --- a/frame/uniques/src/types.rs +++ b/frame/uniques/src/types.rs @@ -58,13 +58,13 @@ pub struct ClassDetails { pub struct DestroyWitness { /// The total number of outstanding instances of this asset class. #[codec(compact)] - pub(super) instances: u32, + pub instances: u32, /// The total number of outstanding instance metadata of this asset class. #[codec(compact)] - pub(super) instance_metadatas: u32, + pub instance_metadatas: u32, #[codec(compact)] /// The total number of attributes for this asset class. - pub(super) attributes: u32, + pub attributes: u32, } impl ClassDetails { From ded44948e2d5a398abcb4e342b0513cb690961bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Mon, 3 Jan 2022 09:22:14 +0100 Subject: [PATCH 343/695] Happy new year 2022 (#10573) --- .maintain/frame-weight-template.hbs | 2 +- HEADER-APACHE2 | 2 +- HEADER-GPL3 | 2 +- bin/node/bench/src/common.rs | 2 +- bin/node/bench/src/construct.rs | 2 +- bin/node/bench/src/core.rs | 2 +- bin/node/bench/src/generator.rs | 2 +- bin/node/bench/src/import.rs | 2 +- bin/node/bench/src/main.rs | 2 +- bin/node/bench/src/simple_trie.rs | 2 +- bin/node/bench/src/state_sizes.rs | 2 +- bin/node/bench/src/tempdb.rs | 2 +- bin/node/bench/src/trie.rs | 2 +- bin/node/bench/src/txpool.rs | 2 +- bin/node/cli/benches/block_production.rs | 2 +- bin/node/cli/benches/transaction_pool.rs | 2 +- bin/node/cli/bin/main.rs | 2 +- bin/node/cli/build.rs | 2 +- bin/node/cli/src/chain_spec.rs | 2 +- bin/node/cli/src/cli.rs | 2 +- bin/node/cli/src/command.rs | 2 +- bin/node/cli/src/lib.rs | 2 +- bin/node/cli/src/service.rs | 2 +- bin/node/cli/tests/build_spec_works.rs | 2 +- bin/node/cli/tests/check_block_works.rs | 2 +- bin/node/cli/tests/common.rs | 2 +- bin/node/cli/tests/export_import_flow.rs | 2 +- bin/node/cli/tests/inspect_works.rs | 2 +- bin/node/cli/tests/purge_chain_works.rs | 2 +- bin/node/cli/tests/running_the_node_and_interrupt.rs | 2 +- bin/node/cli/tests/telemetry.rs | 2 +- bin/node/cli/tests/temp_base_path_works.rs | 2 +- bin/node/cli/tests/version.rs | 2 +- bin/node/cli/tests/websocket_server.rs | 2 +- bin/node/executor/benches/bench.rs | 2 +- bin/node/executor/src/lib.rs | 2 +- bin/node/executor/tests/basic.rs | 2 +- bin/node/executor/tests/common.rs | 2 +- bin/node/executor/tests/fees.rs | 2 +- bin/node/executor/tests/submit_transaction.rs | 2 +- bin/node/inspect/src/cli.rs | 2 +- bin/node/inspect/src/command.rs | 2 +- bin/node/inspect/src/lib.rs | 2 +- bin/node/primitives/src/lib.rs | 2 +- bin/node/rpc/src/lib.rs | 2 +- bin/node/runtime/build.rs | 2 +- bin/node/runtime/src/constants.rs | 2 +- bin/node/runtime/src/impls.rs | 2 +- bin/node/runtime/src/lib.rs | 2 +- bin/node/runtime/src/voter_bags.rs | 2 +- bin/node/test-runner-example/src/lib.rs | 2 +- bin/node/testing/src/bench.rs | 2 +- bin/node/testing/src/client.rs | 2 +- bin/node/testing/src/genesis.rs | 2 +- bin/node/testing/src/keyring.rs | 2 +- bin/node/testing/src/lib.rs | 2 +- bin/utils/chain-spec-builder/build.rs | 2 +- bin/utils/chain-spec-builder/src/main.rs | 2 +- bin/utils/subkey/src/lib.rs | 2 +- bin/utils/subkey/src/main.rs | 2 +- client/allocator/src/error.rs | 2 +- client/allocator/src/freeing_bump.rs | 2 +- client/allocator/src/lib.rs | 2 +- client/api/src/backend.rs | 2 +- client/api/src/call_executor.rs | 2 +- client/api/src/client.rs | 2 +- client/api/src/execution_extensions.rs | 2 +- client/api/src/in_mem.rs | 2 +- client/api/src/leaves.rs | 2 +- client/api/src/lib.rs | 2 +- client/api/src/notifications.rs | 2 +- client/api/src/proof_provider.rs | 2 +- client/authority-discovery/src/error.rs | 2 +- client/authority-discovery/src/interval.rs | 2 +- client/authority-discovery/src/lib.rs | 2 +- client/authority-discovery/src/service.rs | 2 +- client/authority-discovery/src/tests.rs | 2 +- client/authority-discovery/src/worker.rs | 2 +- client/authority-discovery/src/worker/addr_cache.rs | 2 +- client/authority-discovery/src/worker/schema/tests.rs | 2 +- client/authority-discovery/src/worker/tests.rs | 2 +- client/basic-authorship/src/basic_authorship.rs | 2 +- client/basic-authorship/src/lib.rs | 2 +- client/beefy/rpc/src/lib.rs | 2 +- client/beefy/rpc/src/notification.rs | 2 +- client/beefy/src/error.rs | 2 +- client/beefy/src/gossip.rs | 2 +- client/beefy/src/keystore.rs | 2 +- client/beefy/src/lib.rs | 2 +- client/beefy/src/metrics.rs | 2 +- client/beefy/src/notification.rs | 2 +- client/beefy/src/round.rs | 2 +- client/beefy/src/worker.rs | 2 +- client/block-builder/src/lib.rs | 2 +- client/chain-spec/derive/src/impls.rs | 2 +- client/chain-spec/derive/src/lib.rs | 2 +- client/chain-spec/src/chain_spec.rs | 2 +- client/chain-spec/src/extension.rs | 2 +- client/chain-spec/src/lib.rs | 2 +- client/cli/src/arg_enums.rs | 2 +- client/cli/src/commands/build_spec_cmd.rs | 2 +- client/cli/src/commands/check_block_cmd.rs | 2 +- client/cli/src/commands/export_blocks_cmd.rs | 2 +- client/cli/src/commands/export_state_cmd.rs | 2 +- client/cli/src/commands/generate.rs | 2 +- client/cli/src/commands/generate_node_key.rs | 2 +- client/cli/src/commands/import_blocks_cmd.rs | 2 +- client/cli/src/commands/insert_key.rs | 2 +- client/cli/src/commands/inspect_key.rs | 2 +- client/cli/src/commands/inspect_node_key.rs | 2 +- client/cli/src/commands/key.rs | 2 +- client/cli/src/commands/mod.rs | 2 +- client/cli/src/commands/purge_chain_cmd.rs | 2 +- client/cli/src/commands/revert_cmd.rs | 2 +- client/cli/src/commands/run_cmd.rs | 2 +- client/cli/src/commands/sign.rs | 2 +- client/cli/src/commands/utils.rs | 2 +- client/cli/src/commands/vanity.rs | 2 +- client/cli/src/commands/verify.rs | 2 +- client/cli/src/config.rs | 2 +- client/cli/src/error.rs | 2 +- client/cli/src/lib.rs | 2 +- client/cli/src/params/database_params.rs | 2 +- client/cli/src/params/import_params.rs | 2 +- client/cli/src/params/keystore_params.rs | 2 +- client/cli/src/params/mod.rs | 2 +- client/cli/src/params/network_params.rs | 2 +- client/cli/src/params/node_key_params.rs | 2 +- client/cli/src/params/offchain_worker_params.rs | 2 +- client/cli/src/params/pruning_params.rs | 2 +- client/cli/src/params/shared_params.rs | 2 +- client/cli/src/params/transaction_pool_params.rs | 2 +- client/cli/src/runner.rs | 2 +- client/consensus/aura/src/import_queue.rs | 2 +- client/consensus/aura/src/lib.rs | 2 +- client/consensus/babe/rpc/src/lib.rs | 2 +- client/consensus/babe/src/authorship.rs | 2 +- client/consensus/babe/src/aux_schema.rs | 2 +- client/consensus/babe/src/lib.rs | 2 +- client/consensus/babe/src/migration.rs | 2 +- client/consensus/babe/src/tests.rs | 2 +- client/consensus/babe/src/verification.rs | 2 +- client/consensus/common/src/block_import.rs | 2 +- client/consensus/common/src/import_queue.rs | 2 +- client/consensus/common/src/import_queue/basic_queue.rs | 2 +- client/consensus/common/src/import_queue/buffered_link.rs | 2 +- client/consensus/common/src/lib.rs | 2 +- client/consensus/common/src/longest_chain.rs | 2 +- client/consensus/common/src/metrics.rs | 2 +- client/consensus/common/src/shared_data.rs | 2 +- client/consensus/epochs/src/lib.rs | 2 +- client/consensus/epochs/src/migration.rs | 2 +- client/consensus/manual-seal/src/consensus.rs | 2 +- client/consensus/manual-seal/src/consensus/babe.rs | 2 +- client/consensus/manual-seal/src/error.rs | 2 +- client/consensus/manual-seal/src/finalize_block.rs | 2 +- client/consensus/manual-seal/src/lib.rs | 2 +- client/consensus/manual-seal/src/rpc.rs | 2 +- client/consensus/manual-seal/src/seal_block.rs | 2 +- client/consensus/pow/src/lib.rs | 2 +- client/consensus/pow/src/worker.rs | 2 +- client/consensus/slots/build.rs | 2 +- client/consensus/slots/src/aux_schema.rs | 2 +- client/consensus/slots/src/lib.rs | 2 +- client/consensus/slots/src/slots.rs | 2 +- client/consensus/uncles/src/lib.rs | 2 +- client/db/src/bench.rs | 2 +- client/db/src/children.rs | 2 +- client/db/src/lib.rs | 2 +- client/db/src/offchain.rs | 2 +- client/db/src/parity_db.rs | 2 +- client/db/src/stats.rs | 2 +- client/db/src/storage_cache.rs | 2 +- client/db/src/upgrade.rs | 2 +- client/db/src/utils.rs | 2 +- client/executor/common/src/error.rs | 2 +- client/executor/common/src/lib.rs | 2 +- .../executor/common/src/runtime_blob/data_segments_snapshot.rs | 2 +- client/executor/common/src/runtime_blob/globals_snapshot.rs | 2 +- client/executor/common/src/runtime_blob/mod.rs | 2 +- client/executor/common/src/runtime_blob/runtime_blob.rs | 2 +- client/executor/common/src/sandbox.rs | 2 +- client/executor/common/src/util.rs | 2 +- client/executor/common/src/wasm_runtime.rs | 2 +- client/executor/runtime-test/build.rs | 2 +- client/executor/src/integration_tests/linux.rs | 2 +- client/executor/src/integration_tests/linux/smaps.rs | 2 +- client/executor/src/integration_tests/mod.rs | 2 +- client/executor/src/integration_tests/sandbox.rs | 2 +- client/executor/src/lib.rs | 2 +- client/executor/src/native_executor.rs | 2 +- client/executor/src/wasm_runtime.rs | 2 +- client/executor/wasmi/src/lib.rs | 2 +- client/executor/wasmtime/build.rs | 2 +- client/executor/wasmtime/src/host.rs | 2 +- client/executor/wasmtime/src/imports.rs | 2 +- client/executor/wasmtime/src/instance_wrapper.rs | 2 +- client/executor/wasmtime/src/lib.rs | 2 +- client/executor/wasmtime/src/runtime.rs | 2 +- client/executor/wasmtime/src/tests.rs | 2 +- client/executor/wasmtime/src/util.rs | 2 +- client/finality-grandpa/rpc/src/error.rs | 2 +- client/finality-grandpa/rpc/src/finality.rs | 2 +- client/finality-grandpa/rpc/src/lib.rs | 2 +- client/finality-grandpa/rpc/src/notification.rs | 2 +- client/finality-grandpa/rpc/src/report.rs | 2 +- client/finality-grandpa/src/authorities.rs | 2 +- client/finality-grandpa/src/aux_schema.rs | 2 +- client/finality-grandpa/src/communication/gossip.rs | 2 +- client/finality-grandpa/src/communication/mod.rs | 2 +- client/finality-grandpa/src/communication/periodic.rs | 2 +- client/finality-grandpa/src/communication/tests.rs | 2 +- client/finality-grandpa/src/environment.rs | 2 +- client/finality-grandpa/src/finality_proof.rs | 2 +- client/finality-grandpa/src/import.rs | 2 +- client/finality-grandpa/src/justification.rs | 2 +- client/finality-grandpa/src/lib.rs | 2 +- client/finality-grandpa/src/notification.rs | 2 +- client/finality-grandpa/src/observer.rs | 2 +- client/finality-grandpa/src/tests.rs | 2 +- client/finality-grandpa/src/until_imported.rs | 2 +- client/finality-grandpa/src/voting_rule.rs | 2 +- client/informant/src/display.rs | 2 +- client/informant/src/lib.rs | 2 +- client/keystore/src/lib.rs | 2 +- client/keystore/src/local.rs | 2 +- client/network-gossip/src/bridge.rs | 2 +- client/network-gossip/src/lib.rs | 2 +- client/network-gossip/src/state_machine.rs | 2 +- client/network-gossip/src/validator.rs | 2 +- client/network/src/behaviour.rs | 2 +- client/network/src/chain.rs | 2 +- client/network/src/config.rs | 2 +- client/network/src/discovery.rs | 2 +- client/network/src/error.rs | 2 +- client/network/src/lib.rs | 2 +- client/network/src/light_client_requests.rs | 2 +- client/network/src/light_client_requests/handler.rs | 2 +- client/network/src/network_state.rs | 2 +- client/network/src/peer_info.rs | 2 +- client/network/src/protocol.rs | 2 +- client/network/src/protocol/event.rs | 2 +- client/network/src/protocol/message.rs | 2 +- client/network/src/protocol/notifications.rs | 2 +- client/network/src/protocol/notifications/behaviour.rs | 2 +- client/network/src/protocol/notifications/handler.rs | 2 +- client/network/src/protocol/notifications/tests.rs | 2 +- client/network/src/protocol/notifications/upgrade.rs | 2 +- client/network/src/protocol/notifications/upgrade/collec.rs | 2 +- .../network/src/protocol/notifications/upgrade/notifications.rs | 2 +- client/network/src/protocol/sync.rs | 2 +- client/network/src/protocol/sync/blocks.rs | 2 +- client/network/src/protocol/sync/extra_requests.rs | 2 +- client/network/src/protocol/sync/state.rs | 2 +- client/network/src/protocol/sync/warp.rs | 2 +- client/network/src/request_responses.rs | 2 +- client/network/src/schema.rs | 2 +- client/network/src/service.rs | 2 +- client/network/src/service/metrics.rs | 2 +- client/network/src/service/out_events.rs | 2 +- client/network/src/service/signature.rs | 2 +- client/network/src/service/tests.rs | 2 +- client/network/src/transactions.rs | 2 +- client/network/src/transport.rs | 2 +- client/network/src/utils.rs | 2 +- client/network/test/src/block_import.rs | 2 +- client/network/test/src/lib.rs | 2 +- client/network/test/src/sync.rs | 2 +- client/offchain/src/api.rs | 2 +- client/offchain/src/api/http.rs | 2 +- client/offchain/src/api/timestamp.rs | 2 +- client/offchain/src/lib.rs | 2 +- client/peerset/src/lib.rs | 2 +- client/peerset/src/peersstate.rs | 2 +- client/peerset/tests/fuzz.rs | 2 +- client/proposer-metrics/src/lib.rs | 2 +- client/rpc-api/src/author/error.rs | 2 +- client/rpc-api/src/author/hash.rs | 2 +- client/rpc-api/src/author/mod.rs | 2 +- client/rpc-api/src/chain/error.rs | 2 +- client/rpc-api/src/chain/mod.rs | 2 +- client/rpc-api/src/child_state/mod.rs | 2 +- client/rpc-api/src/errors.rs | 2 +- client/rpc-api/src/helpers.rs | 2 +- client/rpc-api/src/lib.rs | 2 +- client/rpc-api/src/metadata.rs | 2 +- client/rpc-api/src/offchain/error.rs | 2 +- client/rpc-api/src/offchain/mod.rs | 2 +- client/rpc-api/src/policy.rs | 2 +- client/rpc-api/src/state/error.rs | 2 +- client/rpc-api/src/state/helpers.rs | 2 +- client/rpc-api/src/state/mod.rs | 2 +- client/rpc-api/src/system/error.rs | 2 +- client/rpc-api/src/system/helpers.rs | 2 +- client/rpc-api/src/system/mod.rs | 2 +- client/rpc-servers/src/lib.rs | 2 +- client/rpc-servers/src/middleware.rs | 2 +- client/rpc/src/author/mod.rs | 2 +- client/rpc/src/author/tests.rs | 2 +- client/rpc/src/chain/chain_full.rs | 2 +- client/rpc/src/chain/mod.rs | 2 +- client/rpc/src/chain/tests.rs | 2 +- client/rpc/src/lib.rs | 2 +- client/rpc/src/offchain/mod.rs | 2 +- client/rpc/src/offchain/tests.rs | 2 +- client/rpc/src/state/mod.rs | 2 +- client/rpc/src/state/state_full.rs | 2 +- client/rpc/src/state/tests.rs | 2 +- client/rpc/src/system/mod.rs | 2 +- client/rpc/src/system/tests.rs | 2 +- client/rpc/src/testing.rs | 2 +- client/service/src/builder.rs | 2 +- client/service/src/chain_ops/check_block.rs | 2 +- client/service/src/chain_ops/export_blocks.rs | 2 +- client/service/src/chain_ops/export_raw_state.rs | 2 +- client/service/src/chain_ops/import_blocks.rs | 2 +- client/service/src/chain_ops/mod.rs | 2 +- client/service/src/chain_ops/revert_chain.rs | 2 +- client/service/src/client/block_rules.rs | 2 +- client/service/src/client/call_executor.rs | 2 +- client/service/src/client/client.rs | 2 +- client/service/src/client/genesis.rs | 2 +- client/service/src/client/mod.rs | 2 +- client/service/src/client/wasm_override.rs | 2 +- client/service/src/client/wasm_substitutes.rs | 2 +- client/service/src/config.rs | 2 +- client/service/src/error.rs | 2 +- client/service/src/lib.rs | 2 +- client/service/src/metrics.rs | 2 +- client/service/src/task_manager/mod.rs | 2 +- client/service/src/task_manager/prometheus_future.rs | 2 +- client/service/src/task_manager/tests.rs | 2 +- client/service/test/src/client/db.rs | 2 +- client/service/test/src/client/mod.rs | 2 +- client/service/test/src/lib.rs | 2 +- client/state-db/src/lib.rs | 2 +- client/state-db/src/noncanonical.rs | 2 +- client/state-db/src/pruning.rs | 2 +- client/state-db/src/test.rs | 2 +- client/sync-state-rpc/src/lib.rs | 2 +- client/telemetry/src/endpoints.rs | 2 +- client/telemetry/src/error.rs | 2 +- client/telemetry/src/lib.rs | 2 +- client/telemetry/src/node.rs | 2 +- client/telemetry/src/transport.rs | 2 +- client/tracing/benches/bench.rs | 2 +- client/tracing/proc-macro/src/lib.rs | 2 +- client/tracing/src/lib.rs | 2 +- client/tracing/src/logging/event_format.rs | 2 +- client/tracing/src/logging/fast_local_time.rs | 2 +- client/tracing/src/logging/layers/mod.rs | 2 +- client/tracing/src/logging/layers/prefix_layer.rs | 2 +- client/tracing/src/logging/mod.rs | 2 +- client/tracing/src/logging/stderr_writer.rs | 2 +- client/transaction-pool/api/src/error.rs | 2 +- client/transaction-pool/api/src/lib.rs | 2 +- client/transaction-pool/benches/basics.rs | 2 +- client/transaction-pool/src/api.rs | 2 +- client/transaction-pool/src/error.rs | 2 +- client/transaction-pool/src/graph/base_pool.rs | 2 +- client/transaction-pool/src/graph/future.rs | 2 +- client/transaction-pool/src/graph/listener.rs | 2 +- client/transaction-pool/src/graph/mod.rs | 2 +- client/transaction-pool/src/graph/pool.rs | 2 +- client/transaction-pool/src/graph/ready.rs | 2 +- client/transaction-pool/src/graph/rotator.rs | 2 +- client/transaction-pool/src/graph/tracked_map.rs | 2 +- client/transaction-pool/src/graph/validated_pool.rs | 2 +- client/transaction-pool/src/graph/watcher.rs | 2 +- client/transaction-pool/src/lib.rs | 2 +- client/transaction-pool/src/metrics.rs | 2 +- client/transaction-pool/src/revalidation.rs | 2 +- client/transaction-pool/tests/pool.rs | 2 +- client/utils/src/lib.rs | 2 +- client/utils/src/metrics.rs | 2 +- client/utils/src/mpsc.rs | 2 +- client/utils/src/status_sinks.rs | 2 +- frame/assets/src/benchmarking.rs | 2 +- frame/assets/src/extra_mutator.rs | 2 +- frame/assets/src/functions.rs | 2 +- frame/assets/src/impl_fungibles.rs | 2 +- frame/assets/src/impl_stored_map.rs | 2 +- frame/assets/src/lib.rs | 2 +- frame/assets/src/mock.rs | 2 +- frame/assets/src/tests.rs | 2 +- frame/assets/src/types.rs | 2 +- frame/assets/src/weights.rs | 2 +- frame/atomic-swap/src/lib.rs | 2 +- frame/aura/src/lib.rs | 2 +- frame/aura/src/migrations.rs | 2 +- frame/aura/src/mock.rs | 2 +- frame/aura/src/tests.rs | 2 +- frame/authority-discovery/src/lib.rs | 2 +- frame/authorship/src/lib.rs | 2 +- frame/babe/src/benchmarking.rs | 2 +- frame/babe/src/default_weights.rs | 2 +- frame/babe/src/equivocation.rs | 2 +- frame/babe/src/lib.rs | 2 +- frame/babe/src/mock.rs | 2 +- frame/babe/src/randomness.rs | 2 +- frame/babe/src/tests.rs | 2 +- frame/bags-list/fuzzer/src/main.rs | 2 +- frame/bags-list/remote-tests/src/lib.rs | 2 +- frame/bags-list/src/benchmarks.rs | 2 +- frame/bags-list/src/lib.rs | 2 +- frame/bags-list/src/list/mod.rs | 2 +- frame/bags-list/src/list/tests.rs | 2 +- frame/bags-list/src/migrations.rs | 2 +- frame/bags-list/src/mock.rs | 2 +- frame/bags-list/src/tests.rs | 2 +- frame/bags-list/src/weights.rs | 2 +- frame/balances/src/benchmarking.rs | 2 +- frame/balances/src/lib.rs | 2 +- frame/balances/src/tests.rs | 2 +- frame/balances/src/tests_composite.rs | 2 +- frame/balances/src/tests_local.rs | 2 +- frame/balances/src/tests_reentrancy.rs | 2 +- frame/balances/src/weights.rs | 2 +- frame/beefy-mmr/primitives/src/lib.rs | 2 +- frame/beefy-mmr/src/lib.rs | 2 +- frame/beefy-mmr/src/mock.rs | 2 +- frame/beefy-mmr/src/tests.rs | 2 +- frame/beefy/src/lib.rs | 2 +- frame/beefy/src/mock.rs | 2 +- frame/beefy/src/tests.rs | 2 +- frame/benchmarking/src/analysis.rs | 2 +- frame/benchmarking/src/baseline.rs | 2 +- frame/benchmarking/src/lib.rs | 2 +- frame/benchmarking/src/tests.rs | 2 +- frame/benchmarking/src/tests_instance.rs | 2 +- frame/benchmarking/src/utils.rs | 2 +- frame/benchmarking/src/weights.rs | 2 +- frame/bounties/src/benchmarking.rs | 2 +- frame/bounties/src/lib.rs | 2 +- frame/bounties/src/migrations/mod.rs | 2 +- frame/bounties/src/migrations/v4.rs | 2 +- frame/bounties/src/tests.rs | 2 +- frame/bounties/src/weights.rs | 2 +- frame/child-bounties/src/benchmarking.rs | 2 +- frame/child-bounties/src/lib.rs | 2 +- frame/child-bounties/src/tests.rs | 2 +- frame/child-bounties/src/weights.rs | 2 +- frame/collective/src/benchmarking.rs | 2 +- frame/collective/src/lib.rs | 2 +- frame/collective/src/migrations/mod.rs | 2 +- frame/collective/src/migrations/v4.rs | 2 +- frame/collective/src/tests.rs | 2 +- frame/collective/src/weights.rs | 2 +- frame/contracts/common/src/lib.rs | 2 +- frame/contracts/proc-macro/src/lib.rs | 2 +- frame/contracts/rpc/runtime-api/src/lib.rs | 2 +- frame/contracts/rpc/src/lib.rs | 2 +- frame/contracts/src/benchmarking/code.rs | 2 +- frame/contracts/src/benchmarking/mod.rs | 2 +- frame/contracts/src/benchmarking/sandbox.rs | 2 +- frame/contracts/src/chain_extension.rs | 2 +- frame/contracts/src/exec.rs | 2 +- frame/contracts/src/gas.rs | 2 +- frame/contracts/src/lib.rs | 2 +- frame/contracts/src/migration.rs | 2 +- frame/contracts/src/schedule.rs | 2 +- frame/contracts/src/storage.rs | 2 +- frame/contracts/src/storage/meter.rs | 2 +- frame/contracts/src/tests.rs | 2 +- frame/contracts/src/wasm/code_cache.rs | 2 +- frame/contracts/src/wasm/env_def/macros.rs | 2 +- frame/contracts/src/wasm/env_def/mod.rs | 2 +- frame/contracts/src/wasm/mod.rs | 2 +- frame/contracts/src/wasm/prepare.rs | 2 +- frame/contracts/src/wasm/runtime.rs | 2 +- frame/contracts/src/weights.rs | 2 +- frame/democracy/src/benchmarking.rs | 2 +- frame/democracy/src/conviction.rs | 2 +- frame/democracy/src/lib.rs | 2 +- frame/democracy/src/tests.rs | 2 +- frame/democracy/src/tests/cancellation.rs | 2 +- frame/democracy/src/tests/decoders.rs | 2 +- frame/democracy/src/tests/delegation.rs | 2 +- frame/democracy/src/tests/external_proposing.rs | 2 +- frame/democracy/src/tests/fast_tracking.rs | 2 +- frame/democracy/src/tests/lock_voting.rs | 2 +- frame/democracy/src/tests/preimage.rs | 2 +- frame/democracy/src/tests/public_proposals.rs | 2 +- frame/democracy/src/tests/scheduling.rs | 2 +- frame/democracy/src/tests/voting.rs | 2 +- frame/democracy/src/types.rs | 2 +- frame/democracy/src/vote.rs | 2 +- frame/democracy/src/vote_threshold.rs | 2 +- frame/democracy/src/weights.rs | 2 +- frame/election-provider-multi-phase/src/benchmarking.rs | 2 +- frame/election-provider-multi-phase/src/helpers.rs | 2 +- frame/election-provider-multi-phase/src/lib.rs | 2 +- frame/election-provider-multi-phase/src/mock.rs | 2 +- frame/election-provider-multi-phase/src/signed.rs | 2 +- frame/election-provider-multi-phase/src/unsigned.rs | 2 +- frame/election-provider-multi-phase/src/weights.rs | 2 +- frame/election-provider-support/src/lib.rs | 2 +- frame/election-provider-support/src/onchain.rs | 2 +- frame/elections-phragmen/src/benchmarking.rs | 2 +- frame/elections-phragmen/src/lib.rs | 2 +- frame/elections-phragmen/src/migrations/mod.rs | 2 +- frame/elections-phragmen/src/migrations/v3.rs | 2 +- frame/elections-phragmen/src/migrations/v4.rs | 2 +- frame/elections-phragmen/src/weights.rs | 2 +- frame/examples/basic/src/benchmarking.rs | 2 +- frame/examples/basic/src/lib.rs | 2 +- frame/examples/basic/src/tests.rs | 2 +- frame/examples/basic/src/weights.rs | 2 +- frame/examples/offchain-worker/src/lib.rs | 2 +- frame/examples/offchain-worker/src/tests.rs | 2 +- frame/examples/parallel/src/lib.rs | 2 +- frame/examples/parallel/src/tests.rs | 2 +- frame/executive/src/lib.rs | 2 +- frame/gilt/src/benchmarking.rs | 2 +- frame/gilt/src/lib.rs | 2 +- frame/gilt/src/mock.rs | 2 +- frame/gilt/src/tests.rs | 2 +- frame/gilt/src/weights.rs | 2 +- frame/grandpa/src/benchmarking.rs | 2 +- frame/grandpa/src/default_weights.rs | 2 +- frame/grandpa/src/equivocation.rs | 2 +- frame/grandpa/src/lib.rs | 2 +- frame/grandpa/src/migrations.rs | 2 +- frame/grandpa/src/migrations/v4.rs | 2 +- frame/grandpa/src/mock.rs | 2 +- frame/grandpa/src/tests.rs | 2 +- frame/identity/src/benchmarking.rs | 2 +- frame/identity/src/lib.rs | 2 +- frame/identity/src/tests.rs | 2 +- frame/identity/src/types.rs | 2 +- frame/identity/src/weights.rs | 2 +- frame/im-online/src/benchmarking.rs | 2 +- frame/im-online/src/lib.rs | 2 +- frame/im-online/src/mock.rs | 2 +- frame/im-online/src/tests.rs | 2 +- frame/im-online/src/weights.rs | 2 +- frame/indices/src/benchmarking.rs | 2 +- frame/indices/src/lib.rs | 2 +- frame/indices/src/mock.rs | 2 +- frame/indices/src/tests.rs | 2 +- frame/indices/src/weights.rs | 2 +- frame/lottery/src/benchmarking.rs | 2 +- frame/lottery/src/lib.rs | 2 +- frame/lottery/src/mock.rs | 2 +- frame/lottery/src/tests.rs | 2 +- frame/lottery/src/weights.rs | 2 +- frame/membership/src/lib.rs | 2 +- frame/membership/src/migrations/mod.rs | 2 +- frame/membership/src/migrations/v4.rs | 2 +- frame/membership/src/weights.rs | 2 +- frame/merkle-mountain-range/primitives/src/lib.rs | 2 +- frame/merkle-mountain-range/rpc/src/lib.rs | 2 +- frame/merkle-mountain-range/src/benchmarking.rs | 2 +- frame/merkle-mountain-range/src/default_weights.rs | 2 +- frame/merkle-mountain-range/src/lib.rs | 2 +- frame/merkle-mountain-range/src/mmr/mmr.rs | 2 +- frame/merkle-mountain-range/src/mmr/mod.rs | 2 +- frame/merkle-mountain-range/src/mmr/storage.rs | 2 +- frame/merkle-mountain-range/src/mmr/utils.rs | 2 +- frame/merkle-mountain-range/src/mock.rs | 2 +- frame/merkle-mountain-range/src/tests.rs | 2 +- frame/multisig/src/benchmarking.rs | 2 +- frame/multisig/src/lib.rs | 2 +- frame/multisig/src/tests.rs | 2 +- frame/multisig/src/weights.rs | 2 +- frame/nicks/src/lib.rs | 2 +- frame/node-authorization/src/lib.rs | 2 +- frame/node-authorization/src/mock.rs | 2 +- frame/node-authorization/src/tests.rs | 2 +- frame/node-authorization/src/weights.rs | 2 +- frame/offences/benchmarking/src/lib.rs | 2 +- frame/offences/benchmarking/src/mock.rs | 2 +- frame/offences/src/lib.rs | 2 +- frame/offences/src/migration.rs | 2 +- frame/offences/src/mock.rs | 2 +- frame/offences/src/tests.rs | 2 +- frame/preimage/src/benchmarking.rs | 2 +- frame/preimage/src/lib.rs | 2 +- frame/preimage/src/mock.rs | 2 +- frame/preimage/src/tests.rs | 2 +- frame/preimage/src/weights.rs | 2 +- frame/proxy/src/benchmarking.rs | 2 +- frame/proxy/src/lib.rs | 2 +- frame/proxy/src/tests.rs | 2 +- frame/proxy/src/weights.rs | 2 +- frame/randomness-collective-flip/src/lib.rs | 2 +- frame/recovery/src/lib.rs | 2 +- frame/recovery/src/mock.rs | 2 +- frame/recovery/src/tests.rs | 2 +- frame/scheduler/src/benchmarking.rs | 2 +- frame/scheduler/src/lib.rs | 2 +- frame/scheduler/src/mock.rs | 2 +- frame/scheduler/src/tests.rs | 2 +- frame/scheduler/src/weights.rs | 2 +- frame/scored-pool/src/lib.rs | 2 +- frame/scored-pool/src/mock.rs | 2 +- frame/scored-pool/src/tests.rs | 2 +- frame/session/benchmarking/src/lib.rs | 2 +- frame/session/benchmarking/src/mock.rs | 2 +- frame/session/src/historical/mod.rs | 2 +- frame/session/src/historical/offchain.rs | 2 +- frame/session/src/historical/onchain.rs | 2 +- frame/session/src/historical/shared.rs | 2 +- frame/session/src/lib.rs | 2 +- frame/session/src/migrations/mod.rs | 2 +- frame/session/src/migrations/v1.rs | 2 +- frame/session/src/mock.rs | 2 +- frame/session/src/tests.rs | 2 +- frame/session/src/weights.rs | 2 +- frame/society/src/lib.rs | 2 +- frame/society/src/mock.rs | 2 +- frame/society/src/tests.rs | 2 +- frame/staking/reward-curve/src/lib.rs | 2 +- frame/staking/reward-curve/tests/test.rs | 2 +- frame/staking/reward-fn/src/lib.rs | 2 +- frame/staking/reward-fn/tests/test.rs | 2 +- frame/staking/src/benchmarking.rs | 2 +- frame/staking/src/inflation.rs | 2 +- frame/staking/src/lib.rs | 2 +- frame/staking/src/migrations.rs | 2 +- frame/staking/src/mock.rs | 2 +- frame/staking/src/pallet/impls.rs | 2 +- frame/staking/src/pallet/mod.rs | 2 +- frame/staking/src/slashing.rs | 2 +- frame/staking/src/testing_utils.rs | 2 +- frame/staking/src/tests.rs | 2 +- frame/staking/src/weights.rs | 2 +- frame/sudo/src/lib.rs | 2 +- frame/sudo/src/mock.rs | 2 +- frame/sudo/src/tests.rs | 2 +- frame/support/procedural/src/clone_no_bound.rs | 2 +- frame/support/procedural/src/construct_runtime/expand/call.rs | 2 +- frame/support/procedural/src/construct_runtime/expand/config.rs | 2 +- frame/support/procedural/src/construct_runtime/expand/event.rs | 2 +- .../support/procedural/src/construct_runtime/expand/inherent.rs | 2 +- .../support/procedural/src/construct_runtime/expand/metadata.rs | 2 +- frame/support/procedural/src/construct_runtime/expand/mod.rs | 2 +- frame/support/procedural/src/construct_runtime/expand/origin.rs | 2 +- .../support/procedural/src/construct_runtime/expand/unsigned.rs | 2 +- frame/support/procedural/src/construct_runtime/mod.rs | 2 +- frame/support/procedural/src/construct_runtime/parse.rs | 2 +- frame/support/procedural/src/crate_version.rs | 2 +- frame/support/procedural/src/debug_no_bound.rs | 2 +- frame/support/procedural/src/default_no_bound.rs | 2 +- frame/support/procedural/src/key_prefix.rs | 2 +- frame/support/procedural/src/lib.rs | 2 +- frame/support/procedural/src/match_and_insert.rs | 2 +- frame/support/procedural/src/pallet/expand/call.rs | 2 +- frame/support/procedural/src/pallet/expand/config.rs | 2 +- frame/support/procedural/src/pallet/expand/constants.rs | 2 +- frame/support/procedural/src/pallet/expand/error.rs | 2 +- frame/support/procedural/src/pallet/expand/event.rs | 2 +- frame/support/procedural/src/pallet/expand/genesis_build.rs | 2 +- frame/support/procedural/src/pallet/expand/genesis_config.rs | 2 +- frame/support/procedural/src/pallet/expand/hooks.rs | 2 +- frame/support/procedural/src/pallet/expand/inherent.rs | 2 +- frame/support/procedural/src/pallet/expand/instances.rs | 2 +- frame/support/procedural/src/pallet/expand/mod.rs | 2 +- frame/support/procedural/src/pallet/expand/origin.rs | 2 +- frame/support/procedural/src/pallet/expand/pallet_struct.rs | 2 +- frame/support/procedural/src/pallet/expand/storage.rs | 2 +- frame/support/procedural/src/pallet/expand/store_trait.rs | 2 +- frame/support/procedural/src/pallet/expand/tt_default_parts.rs | 2 +- frame/support/procedural/src/pallet/expand/type_value.rs | 2 +- frame/support/procedural/src/pallet/expand/validate_unsigned.rs | 2 +- frame/support/procedural/src/pallet/mod.rs | 2 +- frame/support/procedural/src/pallet/parse/call.rs | 2 +- frame/support/procedural/src/pallet/parse/config.rs | 2 +- frame/support/procedural/src/pallet/parse/error.rs | 2 +- frame/support/procedural/src/pallet/parse/event.rs | 2 +- frame/support/procedural/src/pallet/parse/extra_constants.rs | 2 +- frame/support/procedural/src/pallet/parse/genesis_build.rs | 2 +- frame/support/procedural/src/pallet/parse/genesis_config.rs | 2 +- frame/support/procedural/src/pallet/parse/helper.rs | 2 +- frame/support/procedural/src/pallet/parse/hooks.rs | 2 +- frame/support/procedural/src/pallet/parse/inherent.rs | 2 +- frame/support/procedural/src/pallet/parse/mod.rs | 2 +- frame/support/procedural/src/pallet/parse/origin.rs | 2 +- frame/support/procedural/src/pallet/parse/pallet_struct.rs | 2 +- frame/support/procedural/src/pallet/parse/storage.rs | 2 +- frame/support/procedural/src/pallet/parse/type_value.rs | 2 +- frame/support/procedural/src/pallet/parse/validate_unsigned.rs | 2 +- frame/support/procedural/src/partial_eq_no_bound.rs | 2 +- .../procedural/src/storage/genesis_config/builder_def.rs | 2 +- .../procedural/src/storage/genesis_config/genesis_config_def.rs | 2 +- frame/support/procedural/src/storage/genesis_config/mod.rs | 2 +- frame/support/procedural/src/storage/getters.rs | 2 +- frame/support/procedural/src/storage/instance_trait.rs | 2 +- frame/support/procedural/src/storage/metadata.rs | 2 +- frame/support/procedural/src/storage/mod.rs | 2 +- frame/support/procedural/src/storage/parse.rs | 2 +- frame/support/procedural/src/storage/storage_info.rs | 2 +- frame/support/procedural/src/storage/storage_struct.rs | 2 +- frame/support/procedural/src/storage/store_trait.rs | 2 +- frame/support/procedural/src/transactional.rs | 2 +- frame/support/procedural/tools/derive/src/lib.rs | 2 +- frame/support/procedural/tools/src/lib.rs | 2 +- frame/support/procedural/tools/src/syn_ext.rs | 2 +- frame/support/src/dispatch.rs | 2 +- frame/support/src/error.rs | 2 +- frame/support/src/event.rs | 2 +- frame/support/src/hash.rs | 2 +- frame/support/src/inherent.rs | 2 +- frame/support/src/instances.rs | 2 +- frame/support/src/lib.rs | 2 +- frame/support/src/migrations.rs | 2 +- frame/support/src/storage/bounded_btree_map.rs | 2 +- frame/support/src/storage/bounded_btree_set.rs | 2 +- frame/support/src/storage/bounded_vec.rs | 2 +- frame/support/src/storage/child.rs | 2 +- frame/support/src/storage/generator/double_map.rs | 2 +- frame/support/src/storage/generator/map.rs | 2 +- frame/support/src/storage/generator/mod.rs | 2 +- frame/support/src/storage/generator/nmap.rs | 2 +- frame/support/src/storage/generator/value.rs | 2 +- frame/support/src/storage/hashed.rs | 2 +- frame/support/src/storage/migration.rs | 2 +- frame/support/src/storage/mod.rs | 2 +- frame/support/src/storage/types/counted_map.rs | 2 +- frame/support/src/storage/types/double_map.rs | 2 +- frame/support/src/storage/types/key.rs | 2 +- frame/support/src/storage/types/map.rs | 2 +- frame/support/src/storage/types/mod.rs | 2 +- frame/support/src/storage/types/nmap.rs | 2 +- frame/support/src/storage/types/value.rs | 2 +- frame/support/src/storage/unhashed.rs | 2 +- frame/support/src/storage/weak_bounded_vec.rs | 2 +- frame/support/src/traits.rs | 2 +- frame/support/src/traits/dispatch.rs | 2 +- frame/support/src/traits/filter.rs | 2 +- frame/support/src/traits/hooks.rs | 2 +- frame/support/src/traits/members.rs | 2 +- frame/support/src/traits/metadata.rs | 2 +- frame/support/src/traits/misc.rs | 2 +- frame/support/src/traits/randomness.rs | 2 +- frame/support/src/traits/schedule.rs | 2 +- frame/support/src/traits/storage.rs | 2 +- frame/support/src/traits/stored_map.rs | 2 +- frame/support/src/traits/tokens.rs | 2 +- frame/support/src/traits/tokens/currency.rs | 2 +- frame/support/src/traits/tokens/currency/lockable.rs | 2 +- frame/support/src/traits/tokens/currency/reservable.rs | 2 +- frame/support/src/traits/tokens/fungible.rs | 2 +- frame/support/src/traits/tokens/fungible/balanced.rs | 2 +- frame/support/src/traits/tokens/fungible/imbalance.rs | 2 +- frame/support/src/traits/tokens/fungibles.rs | 2 +- frame/support/src/traits/tokens/fungibles/approvals.rs | 2 +- frame/support/src/traits/tokens/fungibles/balanced.rs | 2 +- frame/support/src/traits/tokens/fungibles/imbalance.rs | 2 +- frame/support/src/traits/tokens/fungibles/metadata.rs | 2 +- frame/support/src/traits/tokens/imbalance.rs | 2 +- frame/support/src/traits/tokens/imbalance/on_unbalanced.rs | 2 +- frame/support/src/traits/tokens/imbalance/signed_imbalance.rs | 2 +- frame/support/src/traits/tokens/imbalance/split_two_ways.rs | 2 +- frame/support/src/traits/tokens/misc.rs | 2 +- frame/support/src/traits/tokens/nonfungible.rs | 2 +- frame/support/src/traits/tokens/nonfungibles.rs | 2 +- frame/support/src/traits/validation.rs | 2 +- frame/support/src/traits/voting.rs | 2 +- frame/support/src/weights.rs | 2 +- frame/support/test/compile_pass/src/lib.rs | 2 +- frame/support/test/pallet/src/lib.rs | 2 +- frame/support/test/src/lib.rs | 2 +- frame/support/test/src/pallet_version.rs | 2 +- frame/support/test/tests/construct_runtime.rs | 2 +- frame/support/test/tests/construct_runtime_ui.rs | 2 +- frame/support/test/tests/decl_module_ui.rs | 2 +- frame/support/test/tests/decl_storage.rs | 2 +- frame/support/test/tests/decl_storage_ui.rs | 2 +- frame/support/test/tests/decl_storage_ui/config_duplicate.rs | 2 +- .../support/test/tests/decl_storage_ui/config_get_duplicate.rs | 2 +- frame/support/test/tests/decl_storage_ui/get_duplicate.rs | 2 +- frame/support/test/tests/derive_no_bound.rs | 2 +- frame/support/test/tests/derive_no_bound_ui.rs | 2 +- frame/support/test/tests/final_keys.rs | 2 +- frame/support/test/tests/genesisconfig.rs | 2 +- frame/support/test/tests/instance.rs | 2 +- frame/support/test/tests/issue2219.rs | 2 +- frame/support/test/tests/pallet.rs | 2 +- frame/support/test/tests/pallet_compatibility.rs | 2 +- frame/support/test/tests/pallet_compatibility_instance.rs | 2 +- frame/support/test/tests/pallet_instance.rs | 2 +- frame/support/test/tests/pallet_ui.rs | 2 +- frame/support/test/tests/pallet_with_name_trait_is_valid.rs | 2 +- frame/support/test/tests/storage_transaction.rs | 2 +- frame/support/test/tests/system.rs | 2 +- frame/system/benches/bench.rs | 2 +- frame/system/benchmarking/src/lib.rs | 2 +- frame/system/benchmarking/src/mock.rs | 2 +- frame/system/rpc/runtime-api/src/lib.rs | 2 +- frame/system/src/extensions/check_genesis.rs | 2 +- frame/system/src/extensions/check_mortality.rs | 2 +- frame/system/src/extensions/check_non_zero_sender.rs | 2 +- frame/system/src/extensions/check_nonce.rs | 2 +- frame/system/src/extensions/check_spec_version.rs | 2 +- frame/system/src/extensions/check_tx_version.rs | 2 +- frame/system/src/extensions/check_weight.rs | 2 +- frame/system/src/extensions/mod.rs | 2 +- frame/system/src/lib.rs | 2 +- frame/system/src/limits.rs | 2 +- frame/system/src/migrations/mod.rs | 2 +- frame/system/src/mock.rs | 2 +- frame/system/src/mocking.rs | 2 +- frame/system/src/offchain.rs | 2 +- frame/system/src/tests.rs | 2 +- frame/system/src/weights.rs | 2 +- frame/timestamp/src/benchmarking.rs | 2 +- frame/timestamp/src/lib.rs | 2 +- frame/timestamp/src/weights.rs | 2 +- frame/tips/src/benchmarking.rs | 2 +- frame/tips/src/lib.rs | 2 +- frame/tips/src/migrations/mod.rs | 2 +- frame/tips/src/migrations/v4.rs | 2 +- frame/tips/src/tests.rs | 2 +- frame/tips/src/weights.rs | 2 +- frame/transaction-payment/asset-tx-payment/src/lib.rs | 2 +- frame/transaction-payment/asset-tx-payment/src/payment.rs | 2 +- frame/transaction-payment/asset-tx-payment/src/tests.rs | 2 +- frame/transaction-payment/rpc/runtime-api/src/lib.rs | 2 +- frame/transaction-payment/rpc/src/lib.rs | 2 +- frame/transaction-payment/src/lib.rs | 2 +- frame/transaction-payment/src/types.rs | 2 +- frame/transaction-storage/src/benchmarking.rs | 2 +- frame/transaction-storage/src/lib.rs | 2 +- frame/transaction-storage/src/mock.rs | 2 +- frame/transaction-storage/src/tests.rs | 2 +- frame/transaction-storage/src/weights.rs | 2 +- frame/treasury/src/benchmarking.rs | 2 +- frame/treasury/src/lib.rs | 2 +- frame/treasury/src/tests.rs | 2 +- frame/treasury/src/weights.rs | 2 +- frame/try-runtime/src/lib.rs | 2 +- frame/uniques/src/benchmarking.rs | 2 +- frame/uniques/src/functions.rs | 2 +- frame/uniques/src/impl_nonfungibles.rs | 2 +- frame/uniques/src/lib.rs | 2 +- frame/uniques/src/migration.rs | 2 +- frame/uniques/src/mock.rs | 2 +- frame/uniques/src/tests.rs | 2 +- frame/uniques/src/types.rs | 2 +- frame/uniques/src/weights.rs | 2 +- frame/utility/src/benchmarking.rs | 2 +- frame/utility/src/lib.rs | 2 +- frame/utility/src/tests.rs | 2 +- frame/utility/src/weights.rs | 2 +- frame/vesting/src/benchmarking.rs | 2 +- frame/vesting/src/lib.rs | 2 +- frame/vesting/src/migrations.rs | 2 +- frame/vesting/src/mock.rs | 2 +- frame/vesting/src/tests.rs | 2 +- frame/vesting/src/vesting_info.rs | 2 +- frame/vesting/src/weights.rs | 2 +- primitives/api/proc-macro/src/decl_runtime_apis.rs | 2 +- primitives/api/proc-macro/src/impl_runtime_apis.rs | 2 +- primitives/api/proc-macro/src/lib.rs | 2 +- primitives/api/proc-macro/src/mock_impl_runtime_apis.rs | 2 +- primitives/api/proc-macro/src/utils.rs | 2 +- primitives/api/src/lib.rs | 2 +- primitives/api/test/benches/bench.rs | 2 +- primitives/api/test/tests/decl_and_impl.rs | 2 +- primitives/api/test/tests/runtime_calls.rs | 2 +- primitives/api/test/tests/trybuild.rs | 2 +- primitives/application-crypto/src/ecdsa.rs | 2 +- primitives/application-crypto/src/ed25519.rs | 2 +- primitives/application-crypto/src/lib.rs | 2 +- primitives/application-crypto/src/sr25519.rs | 2 +- primitives/application-crypto/src/traits.rs | 2 +- primitives/application-crypto/test/src/ecdsa.rs | 2 +- primitives/application-crypto/test/src/ed25519.rs | 2 +- primitives/application-crypto/test/src/lib.rs | 2 +- primitives/application-crypto/test/src/sr25519.rs | 2 +- primitives/arithmetic/benches/bench.rs | 2 +- primitives/arithmetic/fuzzer/src/biguint.rs | 2 +- primitives/arithmetic/fuzzer/src/fixed_point.rs | 2 +- primitives/arithmetic/fuzzer/src/multiply_by_rational.rs | 2 +- primitives/arithmetic/fuzzer/src/normalize.rs | 2 +- primitives/arithmetic/fuzzer/src/per_thing_rational.rs | 2 +- primitives/arithmetic/src/biguint.rs | 2 +- primitives/arithmetic/src/fixed_point.rs | 2 +- primitives/arithmetic/src/helpers_128bit.rs | 2 +- primitives/arithmetic/src/lib.rs | 2 +- primitives/arithmetic/src/per_things.rs | 2 +- primitives/arithmetic/src/rational.rs | 2 +- primitives/arithmetic/src/traits.rs | 2 +- primitives/authority-discovery/src/lib.rs | 2 +- primitives/authorship/src/lib.rs | 2 +- primitives/beefy/src/commitment.rs | 2 +- primitives/beefy/src/lib.rs | 2 +- primitives/beefy/src/mmr.rs | 2 +- primitives/beefy/src/witness.rs | 2 +- primitives/block-builder/src/lib.rs | 2 +- primitives/blockchain/src/backend.rs | 2 +- primitives/blockchain/src/error.rs | 2 +- primitives/blockchain/src/header_metadata.rs | 2 +- primitives/blockchain/src/lib.rs | 2 +- primitives/consensus/aura/src/digests.rs | 2 +- primitives/consensus/aura/src/inherents.rs | 2 +- primitives/consensus/aura/src/lib.rs | 2 +- primitives/consensus/babe/src/digests.rs | 2 +- primitives/consensus/babe/src/inherents.rs | 2 +- primitives/consensus/babe/src/lib.rs | 2 +- primitives/consensus/common/src/block_validation.rs | 2 +- primitives/consensus/common/src/error.rs | 2 +- primitives/consensus/common/src/evaluation.rs | 2 +- primitives/consensus/common/src/lib.rs | 2 +- primitives/consensus/common/src/select_chain.rs | 2 +- primitives/consensus/pow/src/lib.rs | 2 +- primitives/consensus/slots/src/lib.rs | 2 +- primitives/consensus/vrf/src/lib.rs | 2 +- primitives/consensus/vrf/src/schnorrkel.rs | 2 +- primitives/core/hashing/proc-macro/src/impls.rs | 2 +- primitives/core/hashing/proc-macro/src/lib.rs | 2 +- primitives/core/hashing/src/lib.rs | 2 +- primitives/core/src/crypto.rs | 2 +- primitives/core/src/ecdsa.rs | 2 +- primitives/core/src/ed25519.rs | 2 +- primitives/core/src/hash.rs | 2 +- primitives/core/src/hasher.rs | 2 +- primitives/core/src/hashing.rs | 2 +- primitives/core/src/hexdisplay.rs | 2 +- primitives/core/src/lib.rs | 2 +- primitives/core/src/offchain/mod.rs | 2 +- primitives/core/src/offchain/storage.rs | 2 +- primitives/core/src/offchain/testing.rs | 2 +- primitives/core/src/sandbox.rs | 2 +- primitives/core/src/sr25519.rs | 2 +- primitives/core/src/testing.rs | 2 +- primitives/core/src/traits.rs | 2 +- primitives/core/src/u32_trait.rs | 2 +- primitives/core/src/uint.rs | 2 +- primitives/database/src/error.rs | 2 +- primitives/database/src/kvdb.rs | 2 +- primitives/database/src/lib.rs | 2 +- primitives/database/src/mem.rs | 2 +- primitives/debug-derive/src/impls.rs | 2 +- primitives/debug-derive/src/lib.rs | 2 +- primitives/debug-derive/tests/tests.rs | 2 +- primitives/externalities/src/extensions.rs | 2 +- primitives/externalities/src/lib.rs | 2 +- primitives/externalities/src/scope_limited.rs | 2 +- primitives/finality-grandpa/src/lib.rs | 2 +- primitives/inherents/src/client_side.rs | 2 +- primitives/inherents/src/lib.rs | 2 +- primitives/io/src/batch_verifier.rs | 2 +- primitives/io/src/lib.rs | 2 +- primitives/keyring/src/ed25519.rs | 2 +- primitives/keyring/src/lib.rs | 2 +- primitives/keyring/src/sr25519.rs | 2 +- primitives/keystore/src/lib.rs | 2 +- primitives/keystore/src/testing.rs | 2 +- primitives/keystore/src/vrf.rs | 2 +- primitives/maybe-compressed-blob/src/lib.rs | 2 +- primitives/npos-elections/fuzzer/src/common.rs | 2 +- primitives/npos-elections/fuzzer/src/phragmen_balancing.rs | 2 +- primitives/npos-elections/fuzzer/src/phragmen_pjr.rs | 2 +- primitives/npos-elections/fuzzer/src/phragmms_balancing.rs | 2 +- primitives/npos-elections/fuzzer/src/reduce.rs | 2 +- primitives/npos-elections/solution-type/src/codec.rs | 2 +- .../npos-elections/solution-type/src/from_assignment_helpers.rs | 2 +- primitives/npos-elections/solution-type/src/index_assignment.rs | 2 +- primitives/npos-elections/solution-type/src/lib.rs | 2 +- primitives/npos-elections/solution-type/src/single_page.rs | 2 +- primitives/npos-elections/src/assignments.rs | 2 +- primitives/npos-elections/src/balancing.rs | 2 +- primitives/npos-elections/src/helpers.rs | 2 +- primitives/npos-elections/src/lib.rs | 2 +- primitives/npos-elections/src/mock.rs | 2 +- primitives/npos-elections/src/node.rs | 2 +- primitives/npos-elections/src/phragmen.rs | 2 +- primitives/npos-elections/src/phragmms.rs | 2 +- primitives/npos-elections/src/pjr.rs | 2 +- primitives/npos-elections/src/reduce.rs | 2 +- primitives/npos-elections/src/tests.rs | 2 +- primitives/npos-elections/src/traits.rs | 2 +- primitives/offchain/src/lib.rs | 2 +- primitives/panic-handler/src/lib.rs | 2 +- primitives/rpc/src/lib.rs | 2 +- primitives/rpc/src/list.rs | 2 +- primitives/rpc/src/number.rs | 2 +- primitives/rpc/src/tracing.rs | 2 +- primitives/runtime-interface/proc-macro/src/lib.rs | 2 +- primitives/runtime-interface/proc-macro/src/pass_by/codec.rs | 2 +- primitives/runtime-interface/proc-macro/src/pass_by/enum_.rs | 2 +- primitives/runtime-interface/proc-macro/src/pass_by/inner.rs | 2 +- primitives/runtime-interface/proc-macro/src/pass_by/mod.rs | 2 +- .../proc-macro/src/runtime_interface/bare_function_interface.rs | 2 +- .../proc-macro/src/runtime_interface/host_function_interface.rs | 2 +- .../runtime-interface/proc-macro/src/runtime_interface/mod.rs | 2 +- .../proc-macro/src/runtime_interface/trait_decl_impl.rs | 2 +- primitives/runtime-interface/proc-macro/src/utils.rs | 2 +- primitives/runtime-interface/src/host.rs | 2 +- primitives/runtime-interface/src/impls.rs | 2 +- primitives/runtime-interface/src/lib.rs | 2 +- primitives/runtime-interface/src/pass_by.rs | 2 +- primitives/runtime-interface/src/util.rs | 2 +- primitives/runtime-interface/src/wasm.rs | 2 +- primitives/runtime-interface/test-wasm-deprecated/build.rs | 2 +- primitives/runtime-interface/test-wasm-deprecated/src/lib.rs | 2 +- primitives/runtime-interface/test-wasm/build.rs | 2 +- primitives/runtime-interface/test-wasm/src/lib.rs | 2 +- primitives/runtime-interface/test/src/lib.rs | 2 +- primitives/runtime-interface/tests/ui.rs | 2 +- primitives/runtime/src/curve.rs | 2 +- primitives/runtime/src/generic/block.rs | 2 +- primitives/runtime/src/generic/checked_extrinsic.rs | 2 +- primitives/runtime/src/generic/digest.rs | 2 +- primitives/runtime/src/generic/era.rs | 2 +- primitives/runtime/src/generic/header.rs | 2 +- primitives/runtime/src/generic/mod.rs | 2 +- primitives/runtime/src/generic/tests.rs | 2 +- primitives/runtime/src/generic/unchecked_extrinsic.rs | 2 +- primitives/runtime/src/lib.rs | 2 +- primitives/runtime/src/multiaddress.rs | 2 +- primitives/runtime/src/offchain/http.rs | 2 +- primitives/runtime/src/offchain/mod.rs | 2 +- primitives/runtime/src/offchain/storage.rs | 2 +- primitives/runtime/src/offchain/storage_lock.rs | 2 +- primitives/runtime/src/runtime_logger.rs | 2 +- primitives/runtime/src/runtime_string.rs | 2 +- primitives/runtime/src/testing.rs | 2 +- primitives/runtime/src/traits.rs | 2 +- primitives/runtime/src/transaction_validity.rs | 2 +- primitives/sandbox/src/embedded_executor.rs | 2 +- primitives/sandbox/src/host_executor.rs | 2 +- primitives/sandbox/src/lib.rs | 2 +- primitives/serializer/src/lib.rs | 2 +- primitives/session/src/lib.rs | 2 +- primitives/staking/src/lib.rs | 2 +- primitives/staking/src/offence.rs | 2 +- primitives/state-machine/src/backend.rs | 2 +- primitives/state-machine/src/basic.rs | 2 +- primitives/state-machine/src/error.rs | 2 +- primitives/state-machine/src/ext.rs | 2 +- primitives/state-machine/src/in_memory_backend.rs | 2 +- primitives/state-machine/src/lib.rs | 2 +- primitives/state-machine/src/overlayed_changes/changeset.rs | 2 +- primitives/state-machine/src/overlayed_changes/mod.rs | 2 +- primitives/state-machine/src/overlayed_changes/offchain.rs | 2 +- primitives/state-machine/src/proving_backend.rs | 2 +- primitives/state-machine/src/read_only.rs | 2 +- primitives/state-machine/src/stats.rs | 2 +- primitives/state-machine/src/testing.rs | 2 +- primitives/state-machine/src/trie_backend.rs | 2 +- primitives/state-machine/src/trie_backend_essence.rs | 2 +- primitives/std/src/lib.rs | 2 +- primitives/std/with_std.rs | 2 +- primitives/std/without_std.rs | 2 +- primitives/storage/src/lib.rs | 2 +- primitives/tasks/src/async_externalities.rs | 2 +- primitives/tasks/src/lib.rs | 2 +- primitives/test-primitives/src/lib.rs | 2 +- primitives/timestamp/src/lib.rs | 2 +- primitives/tracing/src/lib.rs | 2 +- primitives/tracing/src/types.rs | 2 +- primitives/transaction-pool/src/lib.rs | 2 +- primitives/transaction-pool/src/runtime_api.rs | 2 +- primitives/transaction-storage-proof/src/lib.rs | 2 +- primitives/trie/benches/bench.rs | 2 +- primitives/trie/src/error.rs | 2 +- primitives/trie/src/lib.rs | 2 +- primitives/trie/src/node_codec.rs | 2 +- primitives/trie/src/node_header.rs | 2 +- primitives/trie/src/storage_proof.rs | 2 +- primitives/trie/src/trie_codec.rs | 2 +- primitives/trie/src/trie_stream.rs | 2 +- primitives/version/proc-macro/src/decl_runtime_version.rs | 2 +- primitives/version/proc-macro/src/lib.rs | 2 +- primitives/version/src/embed.rs | 2 +- primitives/version/src/lib.rs | 2 +- primitives/wasm-interface/src/lib.rs | 2 +- primitives/wasm-interface/src/wasmi_impl.rs | 2 +- test-utils/client/src/client_ext.rs | 2 +- test-utils/client/src/lib.rs | 2 +- test-utils/derive/src/lib.rs | 2 +- test-utils/runtime/build.rs | 2 +- test-utils/runtime/client/src/block_builder_ext.rs | 2 +- test-utils/runtime/client/src/lib.rs | 2 +- test-utils/runtime/client/src/trait_tests.rs | 2 +- test-utils/runtime/src/genesismap.rs | 2 +- test-utils/runtime/src/lib.rs | 2 +- test-utils/runtime/src/system.rs | 2 +- test-utils/runtime/transaction-pool/src/lib.rs | 2 +- test-utils/src/lib.rs | 2 +- test-utils/test-crate/src/main.rs | 2 +- test-utils/test-runner/src/client.rs | 2 +- test-utils/test-runner/src/host_functions.rs | 2 +- test-utils/test-runner/src/lib.rs | 2 +- test-utils/test-runner/src/node.rs | 2 +- test-utils/test-runner/src/utils.rs | 2 +- test-utils/tests/basic.rs | 2 +- test-utils/tests/ui.rs | 2 +- test-utils/tests/ui/too-many-func-parameters.rs | 2 +- utils/build-script-utils/src/git.rs | 2 +- utils/build-script-utils/src/lib.rs | 2 +- utils/build-script-utils/src/version.rs | 2 +- utils/fork-tree/src/lib.rs | 2 +- utils/frame/benchmarking-cli/src/command.rs | 2 +- utils/frame/benchmarking-cli/src/lib.rs | 2 +- utils/frame/benchmarking-cli/src/writer.rs | 2 +- utils/frame/frame-utilities-cli/src/lib.rs | 2 +- utils/frame/frame-utilities-cli/src/pallet_id.rs | 2 +- utils/frame/generate-bags/node-runtime/src/main.rs | 2 +- utils/frame/generate-bags/src/lib.rs | 2 +- utils/frame/remote-externalities/src/lib.rs | 2 +- utils/frame/remote-externalities/src/rpc_api.rs | 2 +- utils/frame/rpc/support/src/lib.rs | 2 +- utils/frame/rpc/system/src/lib.rs | 2 +- utils/frame/try-runtime/cli/src/commands/execute_block.rs | 2 +- utils/frame/try-runtime/cli/src/commands/follow_chain.rs | 2 +- utils/frame/try-runtime/cli/src/commands/mod.rs | 2 +- utils/frame/try-runtime/cli/src/commands/offchain_worker.rs | 2 +- utils/frame/try-runtime/cli/src/commands/on_runtime_upgrade.rs | 2 +- utils/frame/try-runtime/cli/src/lib.rs | 2 +- utils/frame/try-runtime/cli/src/parse.rs | 2 +- utils/prometheus/src/lib.rs | 2 +- utils/prometheus/src/networking.rs | 2 +- utils/prometheus/src/sourced.rs | 2 +- utils/wasm-builder/src/builder.rs | 2 +- utils/wasm-builder/src/lib.rs | 2 +- utils/wasm-builder/src/prerequisites.rs | 2 +- utils/wasm-builder/src/wasm_project.rs | 2 +- 1121 files changed, 1121 insertions(+), 1121 deletions(-) diff --git a/.maintain/frame-weight-template.hbs b/.maintain/frame-weight-template.hbs index 4f34707b9602..34852daf7d47 100644 --- a/.maintain/frame-weight-template.hbs +++ b/.maintain/frame-weight-template.hbs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/HEADER-APACHE2 b/HEADER-APACHE2 index f364f4bdf845..58baa53894ca 100644 --- a/HEADER-APACHE2 +++ b/HEADER-APACHE2 @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/HEADER-GPL3 b/HEADER-GPL3 index 0dd7e4f76028..9412b5a70bb3 100644 --- a/HEADER-GPL3 +++ b/HEADER-GPL3 @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2022 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 diff --git a/bin/node/bench/src/common.rs b/bin/node/bench/src/common.rs index d04d79e9907a..839e26f9f6d1 100644 --- a/bin/node/bench/src/common.rs +++ b/bin/node/bench/src/common.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/bin/node/bench/src/construct.rs b/bin/node/bench/src/construct.rs index ca1a1c18f9ea..50b9db9f019d 100644 --- a/bin/node/bench/src/construct.rs +++ b/bin/node/bench/src/construct.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/bin/node/bench/src/core.rs b/bin/node/bench/src/core.rs index 56c0f3526a4d..b6ad3ecd8006 100644 --- a/bin/node/bench/src/core.rs +++ b/bin/node/bench/src/core.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/bin/node/bench/src/generator.rs b/bin/node/bench/src/generator.rs index d57142893f38..2b26ed9089a5 100644 --- a/bin/node/bench/src/generator.rs +++ b/bin/node/bench/src/generator.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/bin/node/bench/src/import.rs b/bin/node/bench/src/import.rs index da9d0cdaf85b..faba85468b1f 100644 --- a/bin/node/bench/src/import.rs +++ b/bin/node/bench/src/import.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/bin/node/bench/src/main.rs b/bin/node/bench/src/main.rs index 4b006b387d0e..f1800214e3e8 100644 --- a/bin/node/bench/src/main.rs +++ b/bin/node/bench/src/main.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/bin/node/bench/src/simple_trie.rs b/bin/node/bench/src/simple_trie.rs index 651772c71575..c59389570e53 100644 --- a/bin/node/bench/src/simple_trie.rs +++ b/bin/node/bench/src/simple_trie.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/bin/node/bench/src/state_sizes.rs b/bin/node/bench/src/state_sizes.rs index 27112ed42d45..f97645423edc 100644 --- a/bin/node/bench/src/state_sizes.rs +++ b/bin/node/bench/src/state_sizes.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/bin/node/bench/src/tempdb.rs b/bin/node/bench/src/tempdb.rs index 518c0dd96127..1e5f3dfbce14 100644 --- a/bin/node/bench/src/tempdb.rs +++ b/bin/node/bench/src/tempdb.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/bin/node/bench/src/trie.rs b/bin/node/bench/src/trie.rs index 374ed3568475..1b4534cbd0f7 100644 --- a/bin/node/bench/src/trie.rs +++ b/bin/node/bench/src/trie.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/bin/node/bench/src/txpool.rs b/bin/node/bench/src/txpool.rs index b0db73453485..322dc352e897 100644 --- a/bin/node/bench/src/txpool.rs +++ b/bin/node/bench/src/txpool.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/bin/node/cli/benches/block_production.rs b/bin/node/cli/benches/block_production.rs index f2dbc1fff6be..69e9e0076a16 100644 --- a/bin/node/cli/benches/block_production.rs +++ b/bin/node/cli/benches/block_production.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 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 diff --git a/bin/node/cli/benches/transaction_pool.rs b/bin/node/cli/benches/transaction_pool.rs index 2965c6336f0f..9baa3e7fc117 100644 --- a/bin/node/cli/benches/transaction_pool.rs +++ b/bin/node/cli/benches/transaction_pool.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 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 diff --git a/bin/node/cli/bin/main.rs b/bin/node/cli/bin/main.rs index cf32a7cf2886..3ae295754561 100644 --- a/bin/node/cli/bin/main.rs +++ b/bin/node/cli/bin/main.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/bin/node/cli/build.rs b/bin/node/cli/build.rs index 90aec2222c9e..e0d5dcea62ed 100644 --- a/bin/node/cli/build.rs +++ b/bin/node/cli/build.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/bin/node/cli/src/chain_spec.rs b/bin/node/cli/src/chain_spec.rs index b29248519cc0..4d5054113ea0 100644 --- a/bin/node/cli/src/chain_spec.rs +++ b/bin/node/cli/src/chain_spec.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/bin/node/cli/src/cli.rs b/bin/node/cli/src/cli.rs index 850581748fde..59d219a01090 100644 --- a/bin/node/cli/src/cli.rs +++ b/bin/node/cli/src/cli.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/bin/node/cli/src/command.rs b/bin/node/cli/src/command.rs index dd8202eb71aa..d9ba53785ba0 100644 --- a/bin/node/cli/src/command.rs +++ b/bin/node/cli/src/command.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/bin/node/cli/src/lib.rs b/bin/node/cli/src/lib.rs index ae851c6cdf62..791140a25484 100644 --- a/bin/node/cli/src/lib.rs +++ b/bin/node/cli/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index fabf8d0adfdc..c899975c850c 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/bin/node/cli/tests/build_spec_works.rs b/bin/node/cli/tests/build_spec_works.rs index 6d863ea7f949..aecabed60c84 100644 --- a/bin/node/cli/tests/build_spec_works.rs +++ b/bin/node/cli/tests/build_spec_works.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/bin/node/cli/tests/check_block_works.rs b/bin/node/cli/tests/check_block_works.rs index 216bcc6d9fc1..ac853b201b8c 100644 --- a/bin/node/cli/tests/check_block_works.rs +++ b/bin/node/cli/tests/check_block_works.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/bin/node/cli/tests/common.rs b/bin/node/cli/tests/common.rs index 85effc858e15..8391cff35596 100644 --- a/bin/node/cli/tests/common.rs +++ b/bin/node/cli/tests/common.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/bin/node/cli/tests/export_import_flow.rs b/bin/node/cli/tests/export_import_flow.rs index 937f03b8e5da..2a2133bbfe4f 100644 --- a/bin/node/cli/tests/export_import_flow.rs +++ b/bin/node/cli/tests/export_import_flow.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/bin/node/cli/tests/inspect_works.rs b/bin/node/cli/tests/inspect_works.rs index 6f980d2acbfc..28ad88dd501d 100644 --- a/bin/node/cli/tests/inspect_works.rs +++ b/bin/node/cli/tests/inspect_works.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/bin/node/cli/tests/purge_chain_works.rs b/bin/node/cli/tests/purge_chain_works.rs index 8a8601c863d9..1a62aec28744 100644 --- a/bin/node/cli/tests/purge_chain_works.rs +++ b/bin/node/cli/tests/purge_chain_works.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/bin/node/cli/tests/running_the_node_and_interrupt.rs b/bin/node/cli/tests/running_the_node_and_interrupt.rs index fc5094c2d722..edce2bbc6e4c 100644 --- a/bin/node/cli/tests/running_the_node_and_interrupt.rs +++ b/bin/node/cli/tests/running_the_node_and_interrupt.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/bin/node/cli/tests/telemetry.rs b/bin/node/cli/tests/telemetry.rs index 78a306284c4a..212fec7a02cf 100644 --- a/bin/node/cli/tests/telemetry.rs +++ b/bin/node/cli/tests/telemetry.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 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 diff --git a/bin/node/cli/tests/temp_base_path_works.rs b/bin/node/cli/tests/temp_base_path_works.rs index 5d8e6c9ec453..a5b9b7499fc4 100644 --- a/bin/node/cli/tests/temp_base_path_works.rs +++ b/bin/node/cli/tests/temp_base_path_works.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/bin/node/cli/tests/version.rs b/bin/node/cli/tests/version.rs index 5ed3a9a8800c..133eb65f4ace 100644 --- a/bin/node/cli/tests/version.rs +++ b/bin/node/cli/tests/version.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/bin/node/cli/tests/websocket_server.rs b/bin/node/cli/tests/websocket_server.rs index 658b8de46345..6eecfaf6de53 100644 --- a/bin/node/cli/tests/websocket_server.rs +++ b/bin/node/cli/tests/websocket_server.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 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 diff --git a/bin/node/executor/benches/bench.rs b/bin/node/executor/benches/bench.rs index f1f950182f70..3d7c264a89d1 100644 --- a/bin/node/executor/benches/bench.rs +++ b/bin/node/executor/benches/bench.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/bin/node/executor/src/lib.rs b/bin/node/executor/src/lib.rs index 9a7a0c4d3c11..9f87c7d12623 100644 --- a/bin/node/executor/src/lib.rs +++ b/bin/node/executor/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/bin/node/executor/tests/basic.rs b/bin/node/executor/tests/basic.rs index 6406a04e8dc6..da0f4e6afb31 100644 --- a/bin/node/executor/tests/basic.rs +++ b/bin/node/executor/tests/basic.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/bin/node/executor/tests/common.rs b/bin/node/executor/tests/common.rs index 8d21f086795a..a2bb91056f47 100644 --- a/bin/node/executor/tests/common.rs +++ b/bin/node/executor/tests/common.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/bin/node/executor/tests/fees.rs b/bin/node/executor/tests/fees.rs index 4767c1bda1fc..a84ce1470d87 100644 --- a/bin/node/executor/tests/fees.rs +++ b/bin/node/executor/tests/fees.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/bin/node/executor/tests/submit_transaction.rs b/bin/node/executor/tests/submit_transaction.rs index d561e08762df..7df13a577006 100644 --- a/bin/node/executor/tests/submit_transaction.rs +++ b/bin/node/executor/tests/submit_transaction.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/bin/node/inspect/src/cli.rs b/bin/node/inspect/src/cli.rs index c054fedaf57c..6e019ca5b208 100644 --- a/bin/node/inspect/src/cli.rs +++ b/bin/node/inspect/src/cli.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/bin/node/inspect/src/command.rs b/bin/node/inspect/src/command.rs index e20c91456515..ce164e0768fb 100644 --- a/bin/node/inspect/src/command.rs +++ b/bin/node/inspect/src/command.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/bin/node/inspect/src/lib.rs b/bin/node/inspect/src/lib.rs index 30e7250ea2c6..722a7903da4c 100644 --- a/bin/node/inspect/src/lib.rs +++ b/bin/node/inspect/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. // -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/bin/node/primitives/src/lib.rs b/bin/node/primitives/src/lib.rs index fc3bd5f5114e..fd000af6b2f1 100644 --- a/bin/node/primitives/src/lib.rs +++ b/bin/node/primitives/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/bin/node/rpc/src/lib.rs b/bin/node/rpc/src/lib.rs index 51ab191d5e9a..30f7a0fdf023 100644 --- a/bin/node/rpc/src/lib.rs +++ b/bin/node/rpc/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/bin/node/runtime/build.rs b/bin/node/runtime/build.rs index a1c4b2d892cf..b773ed9cf6fb 100644 --- a/bin/node/runtime/build.rs +++ b/bin/node/runtime/build.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/bin/node/runtime/src/constants.rs b/bin/node/runtime/src/constants.rs index 7533025a70b0..23fb13cfb049 100644 --- a/bin/node/runtime/src/constants.rs +++ b/bin/node/runtime/src/constants.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/bin/node/runtime/src/impls.rs b/bin/node/runtime/src/impls.rs index 689dc8c23fb4..f73443920c21 100644 --- a/bin/node/runtime/src/impls.rs +++ b/bin/node/runtime/src/impls.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 1a4dad1071e1..aab813f29e0a 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/bin/node/runtime/src/voter_bags.rs b/bin/node/runtime/src/voter_bags.rs index c4c731a58bad..93790f028f45 100644 --- a/bin/node/runtime/src/voter_bags.rs +++ b/bin/node/runtime/src/voter_bags.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/bin/node/test-runner-example/src/lib.rs b/bin/node/test-runner-example/src/lib.rs index e247fca22320..8ac450ac12a1 100644 --- a/bin/node/test-runner-example/src/lib.rs +++ b/bin/node/test-runner-example/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 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 diff --git a/bin/node/testing/src/bench.rs b/bin/node/testing/src/bench.rs index 6a5c4b80e1fe..18333280bb8a 100644 --- a/bin/node/testing/src/bench.rs +++ b/bin/node/testing/src/bench.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/bin/node/testing/src/client.rs b/bin/node/testing/src/client.rs index 4852e33de607..8cb98511098f 100644 --- a/bin/node/testing/src/client.rs +++ b/bin/node/testing/src/client.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/bin/node/testing/src/genesis.rs b/bin/node/testing/src/genesis.rs index 52296230b055..2e2f3f9a5a80 100644 --- a/bin/node/testing/src/genesis.rs +++ b/bin/node/testing/src/genesis.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/bin/node/testing/src/keyring.rs b/bin/node/testing/src/keyring.rs index 3e6dff301fc4..41dd28bb8998 100644 --- a/bin/node/testing/src/keyring.rs +++ b/bin/node/testing/src/keyring.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/bin/node/testing/src/lib.rs b/bin/node/testing/src/lib.rs index a3392bcb29d5..ce3471e5b1f8 100644 --- a/bin/node/testing/src/lib.rs +++ b/bin/node/testing/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/bin/utils/chain-spec-builder/build.rs b/bin/utils/chain-spec-builder/build.rs index 57424f016f3e..b700b28e322c 100644 --- a/bin/utils/chain-spec-builder/build.rs +++ b/bin/utils/chain-spec-builder/build.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/bin/utils/chain-spec-builder/src/main.rs b/bin/utils/chain-spec-builder/src/main.rs index f45031f1eb81..bf58f3110170 100644 --- a/bin/utils/chain-spec-builder/src/main.rs +++ b/bin/utils/chain-spec-builder/src/main.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/bin/utils/subkey/src/lib.rs b/bin/utils/subkey/src/lib.rs index 5052d1b104c2..9a33ef2d2d6d 100644 --- a/bin/utils/subkey/src/lib.rs +++ b/bin/utils/subkey/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/bin/utils/subkey/src/main.rs b/bin/utils/subkey/src/main.rs index 2a0f0850713f..d85c6dbe9d04 100644 --- a/bin/utils/subkey/src/main.rs +++ b/bin/utils/subkey/src/main.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/allocator/src/error.rs b/client/allocator/src/error.rs index 9b9a55325f75..d9fc483224ad 100644 --- a/client/allocator/src/error.rs +++ b/client/allocator/src/error.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/client/allocator/src/freeing_bump.rs b/client/allocator/src/freeing_bump.rs index 741f4012cdcb..d7152f5a209e 100644 --- a/client/allocator/src/freeing_bump.rs +++ b/client/allocator/src/freeing_bump.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/client/allocator/src/lib.rs b/client/allocator/src/lib.rs index 4493db3c7d14..2c3e3b2ae841 100644 --- a/client/allocator/src/lib.rs +++ b/client/allocator/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/client/api/src/backend.rs b/client/api/src/backend.rs index 76f2f569814f..004c0574fcbe 100644 --- a/client/api/src/backend.rs +++ b/client/api/src/backend.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/api/src/call_executor.rs b/client/api/src/call_executor.rs index b1fd731ca088..738f932a47bf 100644 --- a/client/api/src/call_executor.rs +++ b/client/api/src/call_executor.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/api/src/client.rs b/client/api/src/client.rs index 21f8aecad053..b6a5fbfad47a 100644 --- a/client/api/src/client.rs +++ b/client/api/src/client.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/api/src/execution_extensions.rs b/client/api/src/execution_extensions.rs index 56e70cc2b6a6..92efafe91a17 100644 --- a/client/api/src/execution_extensions.rs +++ b/client/api/src/execution_extensions.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/api/src/in_mem.rs b/client/api/src/in_mem.rs index c9650bf6db74..d989004ee217 100644 --- a/client/api/src/in_mem.rs +++ b/client/api/src/in_mem.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/api/src/leaves.rs b/client/api/src/leaves.rs index 80216bc4664b..2a3b95188e68 100644 --- a/client/api/src/leaves.rs +++ b/client/api/src/leaves.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/api/src/lib.rs b/client/api/src/lib.rs index a7029d02cbd4..aab2fabd5e25 100644 --- a/client/api/src/lib.rs +++ b/client/api/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/api/src/notifications.rs b/client/api/src/notifications.rs index 88a709beb1f0..8199bc6b9710 100644 --- a/client/api/src/notifications.rs +++ b/client/api/src/notifications.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/api/src/proof_provider.rs b/client/api/src/proof_provider.rs index 6207139f9758..3aad4af1befb 100644 --- a/client/api/src/proof_provider.rs +++ b/client/api/src/proof_provider.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/authority-discovery/src/error.rs b/client/authority-discovery/src/error.rs index d37b6f3b43bc..26ee02ef8532 100644 --- a/client/authority-discovery/src/error.rs +++ b/client/authority-discovery/src/error.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/authority-discovery/src/interval.rs b/client/authority-discovery/src/interval.rs index f4e7c43e60d2..5ddf81fbccc3 100644 --- a/client/authority-discovery/src/interval.rs +++ b/client/authority-discovery/src/interval.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/authority-discovery/src/lib.rs b/client/authority-discovery/src/lib.rs index e619463fa1ad..8522da9984a6 100644 --- a/client/authority-discovery/src/lib.rs +++ b/client/authority-discovery/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/authority-discovery/src/service.rs b/client/authority-discovery/src/service.rs index 9b59a4ec8647..c240e5d0c228 100644 --- a/client/authority-discovery/src/service.rs +++ b/client/authority-discovery/src/service.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/authority-discovery/src/tests.rs b/client/authority-discovery/src/tests.rs index f1965907f4da..3b632d217400 100644 --- a/client/authority-discovery/src/tests.rs +++ b/client/authority-discovery/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/authority-discovery/src/worker.rs b/client/authority-discovery/src/worker.rs index 5ca93b73c813..ee5a15b9533b 100644 --- a/client/authority-discovery/src/worker.rs +++ b/client/authority-discovery/src/worker.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/authority-discovery/src/worker/addr_cache.rs b/client/authority-discovery/src/worker/addr_cache.rs index d4ba156d5fa1..3cac5a6bf034 100644 --- a/client/authority-discovery/src/worker/addr_cache.rs +++ b/client/authority-discovery/src/worker/addr_cache.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/authority-discovery/src/worker/schema/tests.rs b/client/authority-discovery/src/worker/schema/tests.rs index ef96078411e9..b85a4ce37447 100644 --- a/client/authority-discovery/src/worker/schema/tests.rs +++ b/client/authority-discovery/src/worker/schema/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/authority-discovery/src/worker/tests.rs b/client/authority-discovery/src/worker/tests.rs index 1129427ac868..904c674d269b 100644 --- a/client/authority-discovery/src/worker/tests.rs +++ b/client/authority-discovery/src/worker/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/basic-authorship/src/basic_authorship.rs b/client/basic-authorship/src/basic_authorship.rs index e79fc1f03a54..5ab207e39e58 100644 --- a/client/basic-authorship/src/basic_authorship.rs +++ b/client/basic-authorship/src/basic_authorship.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/basic-authorship/src/lib.rs b/client/basic-authorship/src/lib.rs index 2b2fe554efdf..4a26ebd9df97 100644 --- a/client/basic-authorship/src/lib.rs +++ b/client/basic-authorship/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/beefy/rpc/src/lib.rs b/client/beefy/rpc/src/lib.rs index 7370ca092727..be1c9b8691a2 100644 --- a/client/beefy/rpc/src/lib.rs +++ b/client/beefy/rpc/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 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 diff --git a/client/beefy/rpc/src/notification.rs b/client/beefy/rpc/src/notification.rs index 4830d72905a9..53c0bb618c5d 100644 --- a/client/beefy/rpc/src/notification.rs +++ b/client/beefy/rpc/src/notification.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 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 diff --git a/client/beefy/src/error.rs b/client/beefy/src/error.rs index db532d34c1e3..eacadeb7613a 100644 --- a/client/beefy/src/error.rs +++ b/client/beefy/src/error.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 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 diff --git a/client/beefy/src/gossip.rs b/client/beefy/src/gossip.rs index dc59f664caa9..37358441ef88 100644 --- a/client/beefy/src/gossip.rs +++ b/client/beefy/src/gossip.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/beefy/src/keystore.rs b/client/beefy/src/keystore.rs index eaae17e2015a..32478a11434f 100644 --- a/client/beefy/src/keystore.rs +++ b/client/beefy/src/keystore.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/beefy/src/lib.rs b/client/beefy/src/lib.rs index b2372b2a6c51..59a5ff08e16e 100644 --- a/client/beefy/src/lib.rs +++ b/client/beefy/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 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 diff --git a/client/beefy/src/metrics.rs b/client/beefy/src/metrics.rs index 55edee962a2e..4b2a5c8dfd5c 100644 --- a/client/beefy/src/metrics.rs +++ b/client/beefy/src/metrics.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 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 diff --git a/client/beefy/src/notification.rs b/client/beefy/src/notification.rs index 7caaa5435240..cd410ec60bb3 100644 --- a/client/beefy/src/notification.rs +++ b/client/beefy/src/notification.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 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 diff --git a/client/beefy/src/round.rs b/client/beefy/src/round.rs index b0df365b4e6f..e5404cfa6d21 100644 --- a/client/beefy/src/round.rs +++ b/client/beefy/src/round.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 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 diff --git a/client/beefy/src/worker.rs b/client/beefy/src/worker.rs index 306540077ae2..d3aa988b8ee2 100644 --- a/client/beefy/src/worker.rs +++ b/client/beefy/src/worker.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 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 diff --git a/client/block-builder/src/lib.rs b/client/block-builder/src/lib.rs index c3e91fa05540..a4c6f5aad2ae 100644 --- a/client/block-builder/src/lib.rs +++ b/client/block-builder/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/chain-spec/derive/src/impls.rs b/client/chain-spec/derive/src/impls.rs index 87a3db063c78..7af403d46ad1 100644 --- a/client/chain-spec/derive/src/impls.rs +++ b/client/chain-spec/derive/src/impls.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/chain-spec/derive/src/lib.rs b/client/chain-spec/derive/src/lib.rs index 53f0c69491ec..75356a225046 100644 --- a/client/chain-spec/derive/src/lib.rs +++ b/client/chain-spec/derive/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/chain-spec/src/chain_spec.rs b/client/chain-spec/src/chain_spec.rs index 520c071d35ce..98241255de55 100644 --- a/client/chain-spec/src/chain_spec.rs +++ b/client/chain-spec/src/chain_spec.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/chain-spec/src/extension.rs b/client/chain-spec/src/extension.rs index 4b59232cf577..c0b3e15a2df4 100644 --- a/client/chain-spec/src/extension.rs +++ b/client/chain-spec/src/extension.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/chain-spec/src/lib.rs b/client/chain-spec/src/lib.rs index cbb1e85df3c1..64d72760639d 100644 --- a/client/chain-spec/src/lib.rs +++ b/client/chain-spec/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/cli/src/arg_enums.rs b/client/cli/src/arg_enums.rs index 5221500f08b3..3e1ead609630 100644 --- a/client/cli/src/arg_enums.rs +++ b/client/cli/src/arg_enums.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/cli/src/commands/build_spec_cmd.rs b/client/cli/src/commands/build_spec_cmd.rs index 5e43a26a1e67..ad7cf455eb3b 100644 --- a/client/cli/src/commands/build_spec_cmd.rs +++ b/client/cli/src/commands/build_spec_cmd.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/cli/src/commands/check_block_cmd.rs b/client/cli/src/commands/check_block_cmd.rs index de0d1132ce8b..b5642cf4b629 100644 --- a/client/cli/src/commands/check_block_cmd.rs +++ b/client/cli/src/commands/check_block_cmd.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/cli/src/commands/export_blocks_cmd.rs b/client/cli/src/commands/export_blocks_cmd.rs index ca3069442a1d..af7de3c12e77 100644 --- a/client/cli/src/commands/export_blocks_cmd.rs +++ b/client/cli/src/commands/export_blocks_cmd.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/cli/src/commands/export_state_cmd.rs b/client/cli/src/commands/export_state_cmd.rs index 36eabd2c24f5..b322265aee2b 100644 --- a/client/cli/src/commands/export_state_cmd.rs +++ b/client/cli/src/commands/export_state_cmd.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/cli/src/commands/generate.rs b/client/cli/src/commands/generate.rs index 7032ebd72e0c..ce4c24fc7d8c 100644 --- a/client/cli/src/commands/generate.rs +++ b/client/cli/src/commands/generate.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/client/cli/src/commands/generate_node_key.rs b/client/cli/src/commands/generate_node_key.rs index cc26bb73240a..2221c8a99ded 100644 --- a/client/cli/src/commands/generate_node_key.rs +++ b/client/cli/src/commands/generate_node_key.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/client/cli/src/commands/import_blocks_cmd.rs b/client/cli/src/commands/import_blocks_cmd.rs index 19187f285962..d0a0b39a5bf8 100644 --- a/client/cli/src/commands/import_blocks_cmd.rs +++ b/client/cli/src/commands/import_blocks_cmd.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/cli/src/commands/insert_key.rs b/client/cli/src/commands/insert_key.rs index e85b85f111ad..631fc4ecef95 100644 --- a/client/cli/src/commands/insert_key.rs +++ b/client/cli/src/commands/insert_key.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/client/cli/src/commands/inspect_key.rs b/client/cli/src/commands/inspect_key.rs index 55dd5dfe80d8..34f51dc5ec42 100644 --- a/client/cli/src/commands/inspect_key.rs +++ b/client/cli/src/commands/inspect_key.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/client/cli/src/commands/inspect_node_key.rs b/client/cli/src/commands/inspect_node_key.rs index 7527fbe4315a..a5793873dd68 100644 --- a/client/cli/src/commands/inspect_node_key.rs +++ b/client/cli/src/commands/inspect_node_key.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/client/cli/src/commands/key.rs b/client/cli/src/commands/key.rs index 8e1103a8ca51..0bfc68f8c32e 100644 --- a/client/cli/src/commands/key.rs +++ b/client/cli/src/commands/key.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/client/cli/src/commands/mod.rs b/client/cli/src/commands/mod.rs index 9e7c5689b49c..2b46e1d99caa 100644 --- a/client/cli/src/commands/mod.rs +++ b/client/cli/src/commands/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/cli/src/commands/purge_chain_cmd.rs b/client/cli/src/commands/purge_chain_cmd.rs index e1bdb3a03cc5..eb19762df7d8 100644 --- a/client/cli/src/commands/purge_chain_cmd.rs +++ b/client/cli/src/commands/purge_chain_cmd.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/cli/src/commands/revert_cmd.rs b/client/cli/src/commands/revert_cmd.rs index 9ad49a03aa5f..a671469ba7fd 100644 --- a/client/cli/src/commands/revert_cmd.rs +++ b/client/cli/src/commands/revert_cmd.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/cli/src/commands/run_cmd.rs b/client/cli/src/commands/run_cmd.rs index 661b3ff38233..08b8fd87e2c8 100644 --- a/client/cli/src/commands/run_cmd.rs +++ b/client/cli/src/commands/run_cmd.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/cli/src/commands/sign.rs b/client/cli/src/commands/sign.rs index 20aacd9bf002..1b2fbba40ea1 100644 --- a/client/cli/src/commands/sign.rs +++ b/client/cli/src/commands/sign.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/cli/src/commands/utils.rs b/client/cli/src/commands/utils.rs index 39e5149404b2..7f0413f59601 100644 --- a/client/cli/src/commands/utils.rs +++ b/client/cli/src/commands/utils.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/cli/src/commands/vanity.rs b/client/cli/src/commands/vanity.rs index d2953c839607..f2959a33dbfd 100644 --- a/client/cli/src/commands/vanity.rs +++ b/client/cli/src/commands/vanity.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/cli/src/commands/verify.rs b/client/cli/src/commands/verify.rs index 0dce444a2859..bf03be1737d4 100644 --- a/client/cli/src/commands/verify.rs +++ b/client/cli/src/commands/verify.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/cli/src/config.rs b/client/cli/src/config.rs index 7ae31eba4245..cc3b0590566a 100644 --- a/client/cli/src/config.rs +++ b/client/cli/src/config.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/cli/src/error.rs b/client/cli/src/error.rs index 9a09e560063e..7f3bd84148d1 100644 --- a/client/cli/src/error.rs +++ b/client/cli/src/error.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index d20b6f136f1e..8760e955c69b 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/cli/src/params/database_params.rs b/client/cli/src/params/database_params.rs index 4d6cf5f1d367..f034ae00473c 100644 --- a/client/cli/src/params/database_params.rs +++ b/client/cli/src/params/database_params.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/cli/src/params/import_params.rs b/client/cli/src/params/import_params.rs index 3c87e91c220f..7e1478d71e3f 100644 --- a/client/cli/src/params/import_params.rs +++ b/client/cli/src/params/import_params.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/cli/src/params/keystore_params.rs b/client/cli/src/params/keystore_params.rs index 951f61bd1bc5..5dbab5d9e8e3 100644 --- a/client/cli/src/params/keystore_params.rs +++ b/client/cli/src/params/keystore_params.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/cli/src/params/mod.rs b/client/cli/src/params/mod.rs index dac832a1f897..c7181840a864 100644 --- a/client/cli/src/params/mod.rs +++ b/client/cli/src/params/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/cli/src/params/network_params.rs b/client/cli/src/params/network_params.rs index 6eaf068fdaec..6b7b2680513c 100644 --- a/client/cli/src/params/network_params.rs +++ b/client/cli/src/params/network_params.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/cli/src/params/node_key_params.rs b/client/cli/src/params/node_key_params.rs index 41f9033d282d..23f3fba1cdb0 100644 --- a/client/cli/src/params/node_key_params.rs +++ b/client/cli/src/params/node_key_params.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/cli/src/params/offchain_worker_params.rs b/client/cli/src/params/offchain_worker_params.rs index 685328ef1779..ac71d3a7580e 100644 --- a/client/cli/src/params/offchain_worker_params.rs +++ b/client/cli/src/params/offchain_worker_params.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/cli/src/params/pruning_params.rs b/client/cli/src/params/pruning_params.rs index 28c7fa301cc6..facf982ef8dd 100644 --- a/client/cli/src/params/pruning_params.rs +++ b/client/cli/src/params/pruning_params.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/cli/src/params/shared_params.rs b/client/cli/src/params/shared_params.rs index 4a6fe0d2743e..d385efad4278 100644 --- a/client/cli/src/params/shared_params.rs +++ b/client/cli/src/params/shared_params.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/cli/src/params/transaction_pool_params.rs b/client/cli/src/params/transaction_pool_params.rs index feea19c97c2d..dee8f57eb39c 100644 --- a/client/cli/src/params/transaction_pool_params.rs +++ b/client/cli/src/params/transaction_pool_params.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/cli/src/runner.rs b/client/cli/src/runner.rs index d55dfe253765..f6edd8444735 100644 --- a/client/cli/src/runner.rs +++ b/client/cli/src/runner.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/consensus/aura/src/import_queue.rs b/client/consensus/aura/src/import_queue.rs index d2c4ad4498d5..593ea193c3d1 100644 --- a/client/consensus/aura/src/import_queue.rs +++ b/client/consensus/aura/src/import_queue.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/consensus/aura/src/lib.rs b/client/consensus/aura/src/lib.rs index 4579b2d73da1..13f0d4e8f804 100644 --- a/client/consensus/aura/src/lib.rs +++ b/client/consensus/aura/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/consensus/babe/rpc/src/lib.rs b/client/consensus/babe/rpc/src/lib.rs index 463b05ef9cd2..c9d2f9b76c2a 100644 --- a/client/consensus/babe/rpc/src/lib.rs +++ b/client/consensus/babe/rpc/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/consensus/babe/src/authorship.rs b/client/consensus/babe/src/authorship.rs index 1bee73f40858..1f74afb0e78b 100644 --- a/client/consensus/babe/src/authorship.rs +++ b/client/consensus/babe/src/authorship.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/consensus/babe/src/aux_schema.rs b/client/consensus/babe/src/aux_schema.rs index d5b8a218a5a3..2ab84b9b132c 100644 --- a/client/consensus/babe/src/aux_schema.rs +++ b/client/consensus/babe/src/aux_schema.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/consensus/babe/src/lib.rs b/client/consensus/babe/src/lib.rs index 7a05c7a92678..612a05ffaa67 100644 --- a/client/consensus/babe/src/lib.rs +++ b/client/consensus/babe/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/consensus/babe/src/migration.rs b/client/consensus/babe/src/migration.rs index a248c9da24db..a8c3772bbefb 100644 --- a/client/consensus/babe/src/migration.rs +++ b/client/consensus/babe/src/migration.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/consensus/babe/src/tests.rs b/client/consensus/babe/src/tests.rs index 23c34d21ec7b..7c04dc03c2f2 100644 --- a/client/consensus/babe/src/tests.rs +++ b/client/consensus/babe/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/consensus/babe/src/verification.rs b/client/consensus/babe/src/verification.rs index 13d2f956c8d5..41d1e1bfa5d3 100644 --- a/client/consensus/babe/src/verification.rs +++ b/client/consensus/babe/src/verification.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/consensus/common/src/block_import.rs b/client/consensus/common/src/block_import.rs index aff16566e0de..af54d54770f7 100644 --- a/client/consensus/common/src/block_import.rs +++ b/client/consensus/common/src/block_import.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/consensus/common/src/import_queue.rs b/client/consensus/common/src/import_queue.rs index 3f2126ccadf6..f71996fe2b1f 100644 --- a/client/consensus/common/src/import_queue.rs +++ b/client/consensus/common/src/import_queue.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/consensus/common/src/import_queue/basic_queue.rs b/client/consensus/common/src/import_queue/basic_queue.rs index 0461d7cf954c..0f23d9b546bd 100644 --- a/client/consensus/common/src/import_queue/basic_queue.rs +++ b/client/consensus/common/src/import_queue/basic_queue.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/consensus/common/src/import_queue/buffered_link.rs b/client/consensus/common/src/import_queue/buffered_link.rs index 87ea6dde5c47..8fb5689075ab 100644 --- a/client/consensus/common/src/import_queue/buffered_link.rs +++ b/client/consensus/common/src/import_queue/buffered_link.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/consensus/common/src/lib.rs b/client/consensus/common/src/lib.rs index 640bad237e88..f291cc270481 100644 --- a/client/consensus/common/src/lib.rs +++ b/client/consensus/common/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/consensus/common/src/longest_chain.rs b/client/consensus/common/src/longest_chain.rs index 7ec91a5ad87e..b38183b8ac11 100644 --- a/client/consensus/common/src/longest_chain.rs +++ b/client/consensus/common/src/longest_chain.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/consensus/common/src/metrics.rs b/client/consensus/common/src/metrics.rs index ec6ef89f609f..8314049238b8 100644 --- a/client/consensus/common/src/metrics.rs +++ b/client/consensus/common/src/metrics.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/consensus/common/src/shared_data.rs b/client/consensus/common/src/shared_data.rs index 7a25660e08aa..17217d997e23 100644 --- a/client/consensus/common/src/shared_data.rs +++ b/client/consensus/common/src/shared_data.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 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 diff --git a/client/consensus/epochs/src/lib.rs b/client/consensus/epochs/src/lib.rs index c1d0bd1d0405..b380d8ed5490 100644 --- a/client/consensus/epochs/src/lib.rs +++ b/client/consensus/epochs/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/consensus/epochs/src/migration.rs b/client/consensus/epochs/src/migration.rs index e4b685c6ffb1..c4ed47e9c1c0 100644 --- a/client/consensus/epochs/src/migration.rs +++ b/client/consensus/epochs/src/migration.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/consensus/manual-seal/src/consensus.rs b/client/consensus/manual-seal/src/consensus.rs index 4284d40179d2..9bb1d2fe1fae 100644 --- a/client/consensus/manual-seal/src/consensus.rs +++ b/client/consensus/manual-seal/src/consensus.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/consensus/manual-seal/src/consensus/babe.rs b/client/consensus/manual-seal/src/consensus/babe.rs index 499a82c63e40..b16bee816b17 100644 --- a/client/consensus/manual-seal/src/consensus/babe.rs +++ b/client/consensus/manual-seal/src/consensus/babe.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/consensus/manual-seal/src/error.rs b/client/consensus/manual-seal/src/error.rs index 8585e6a70d64..28f1a6aed35b 100644 --- a/client/consensus/manual-seal/src/error.rs +++ b/client/consensus/manual-seal/src/error.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/consensus/manual-seal/src/finalize_block.rs b/client/consensus/manual-seal/src/finalize_block.rs index a5ddf1d162f7..bc242ad6085e 100644 --- a/client/consensus/manual-seal/src/finalize_block.rs +++ b/client/consensus/manual-seal/src/finalize_block.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/consensus/manual-seal/src/lib.rs b/client/consensus/manual-seal/src/lib.rs index 390c23fe032f..3e5ce5b2a401 100644 --- a/client/consensus/manual-seal/src/lib.rs +++ b/client/consensus/manual-seal/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/consensus/manual-seal/src/rpc.rs b/client/consensus/manual-seal/src/rpc.rs index 6755879ceedd..7b4063e9b2b1 100644 --- a/client/consensus/manual-seal/src/rpc.rs +++ b/client/consensus/manual-seal/src/rpc.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/consensus/manual-seal/src/seal_block.rs b/client/consensus/manual-seal/src/seal_block.rs index 502705b41162..ad840bd102b3 100644 --- a/client/consensus/manual-seal/src/seal_block.rs +++ b/client/consensus/manual-seal/src/seal_block.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/consensus/pow/src/lib.rs b/client/consensus/pow/src/lib.rs index 6ccdf53c0f04..0bcb9f3d00a5 100644 --- a/client/consensus/pow/src/lib.rs +++ b/client/consensus/pow/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/consensus/pow/src/worker.rs b/client/consensus/pow/src/worker.rs index 3faa18ece318..031cf7f6a294 100644 --- a/client/consensus/pow/src/worker.rs +++ b/client/consensus/pow/src/worker.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/consensus/slots/build.rs b/client/consensus/slots/build.rs index 57424f016f3e..b700b28e322c 100644 --- a/client/consensus/slots/build.rs +++ b/client/consensus/slots/build.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/consensus/slots/src/aux_schema.rs b/client/consensus/slots/src/aux_schema.rs index c2fe3f6f4e6b..275b12ff48f8 100644 --- a/client/consensus/slots/src/aux_schema.rs +++ b/client/consensus/slots/src/aux_schema.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/consensus/slots/src/lib.rs b/client/consensus/slots/src/lib.rs index 905165aa9e36..a1b335f7a594 100644 --- a/client/consensus/slots/src/lib.rs +++ b/client/consensus/slots/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/consensus/slots/src/slots.rs b/client/consensus/slots/src/slots.rs index c2ed986e1e7f..2b792af7da8c 100644 --- a/client/consensus/slots/src/slots.rs +++ b/client/consensus/slots/src/slots.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/consensus/uncles/src/lib.rs b/client/consensus/uncles/src/lib.rs index 368a994cfe52..d03c2f8aa6b4 100644 --- a/client/consensus/uncles/src/lib.rs +++ b/client/consensus/uncles/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/db/src/bench.rs b/client/db/src/bench.rs index cafafca9b635..a18e7942a54f 100644 --- a/client/db/src/bench.rs +++ b/client/db/src/bench.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/db/src/children.rs b/client/db/src/children.rs index c11e4204997d..538e51851f08 100644 --- a/client/db/src/children.rs +++ b/client/db/src/children.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/db/src/lib.rs b/client/db/src/lib.rs index 137c26fb8218..c570ca2f15fb 100644 --- a/client/db/src/lib.rs +++ b/client/db/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/db/src/offchain.rs b/client/db/src/offchain.rs index c31273ff07c6..c6351a66a235 100644 --- a/client/db/src/offchain.rs +++ b/client/db/src/offchain.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/db/src/parity_db.rs b/client/db/src/parity_db.rs index 61c0b94dc701..ebe2988e27f0 100644 --- a/client/db/src/parity_db.rs +++ b/client/db/src/parity_db.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/db/src/stats.rs b/client/db/src/stats.rs index 9223142ef5ab..f6c14568236e 100644 --- a/client/db/src/stats.rs +++ b/client/db/src/stats.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/db/src/storage_cache.rs b/client/db/src/storage_cache.rs index 579703ea9db8..504708737637 100644 --- a/client/db/src/storage_cache.rs +++ b/client/db/src/storage_cache.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/db/src/upgrade.rs b/client/db/src/upgrade.rs index 0f3578ad99a3..a42a1960a57c 100644 --- a/client/db/src/upgrade.rs +++ b/client/db/src/upgrade.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/db/src/utils.rs b/client/db/src/utils.rs index b098a7864baf..c3a60962a67d 100644 --- a/client/db/src/utils.rs +++ b/client/db/src/utils.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/executor/common/src/error.rs b/client/executor/common/src/error.rs index 6ad4802e57a8..90e658a89628 100644 --- a/client/executor/common/src/error.rs +++ b/client/executor/common/src/error.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/executor/common/src/lib.rs b/client/executor/common/src/lib.rs index 99b927e06203..b69883afbaac 100644 --- a/client/executor/common/src/lib.rs +++ b/client/executor/common/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/executor/common/src/runtime_blob/data_segments_snapshot.rs b/client/executor/common/src/runtime_blob/data_segments_snapshot.rs index 5c3fedbdc963..76f2ad2c345e 100644 --- a/client/executor/common/src/runtime_blob/data_segments_snapshot.rs +++ b/client/executor/common/src/runtime_blob/data_segments_snapshot.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 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 diff --git a/client/executor/common/src/runtime_blob/globals_snapshot.rs b/client/executor/common/src/runtime_blob/globals_snapshot.rs index a25fa6f9fd63..207fa751bc40 100644 --- a/client/executor/common/src/runtime_blob/globals_snapshot.rs +++ b/client/executor/common/src/runtime_blob/globals_snapshot.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/executor/common/src/runtime_blob/mod.rs b/client/executor/common/src/runtime_blob/mod.rs index 1af2708d3eb4..4b163bbaaf32 100644 --- a/client/executor/common/src/runtime_blob/mod.rs +++ b/client/executor/common/src/runtime_blob/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 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 diff --git a/client/executor/common/src/runtime_blob/runtime_blob.rs b/client/executor/common/src/runtime_blob/runtime_blob.rs index 6fb9303e0775..8318cce7a9ba 100644 --- a/client/executor/common/src/runtime_blob/runtime_blob.rs +++ b/client/executor/common/src/runtime_blob/runtime_blob.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 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 diff --git a/client/executor/common/src/sandbox.rs b/client/executor/common/src/sandbox.rs index b62729424125..34162b7dc497 100644 --- a/client/executor/common/src/sandbox.rs +++ b/client/executor/common/src/sandbox.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/executor/common/src/util.rs b/client/executor/common/src/util.rs index ffbeb8c7ab53..eddf4230504c 100644 --- a/client/executor/common/src/util.rs +++ b/client/executor/common/src/util.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/executor/common/src/wasm_runtime.rs b/client/executor/common/src/wasm_runtime.rs index 1e9f1225518a..d43ad758b144 100644 --- a/client/executor/common/src/wasm_runtime.rs +++ b/client/executor/common/src/wasm_runtime.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/executor/runtime-test/build.rs b/client/executor/runtime-test/build.rs index 9456d6bc90f4..27f931a542d4 100644 --- a/client/executor/runtime-test/build.rs +++ b/client/executor/runtime-test/build.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/executor/src/integration_tests/linux.rs b/client/executor/src/integration_tests/linux.rs index 38e57707e9e6..8775a35cb83c 100644 --- a/client/executor/src/integration_tests/linux.rs +++ b/client/executor/src/integration_tests/linux.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 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 diff --git a/client/executor/src/integration_tests/linux/smaps.rs b/client/executor/src/integration_tests/linux/smaps.rs index b23a188b93a2..665155ff81ea 100644 --- a/client/executor/src/integration_tests/linux/smaps.rs +++ b/client/executor/src/integration_tests/linux/smaps.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/executor/src/integration_tests/mod.rs b/client/executor/src/integration_tests/mod.rs index c480ad74ade6..36339c31871d 100644 --- a/client/executor/src/integration_tests/mod.rs +++ b/client/executor/src/integration_tests/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/executor/src/integration_tests/sandbox.rs b/client/executor/src/integration_tests/sandbox.rs index 2b536f541f08..643db5097c6a 100644 --- a/client/executor/src/integration_tests/sandbox.rs +++ b/client/executor/src/integration_tests/sandbox.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/executor/src/lib.rs b/client/executor/src/lib.rs index 8bac541afc37..fd127887dbc2 100644 --- a/client/executor/src/lib.rs +++ b/client/executor/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/executor/src/native_executor.rs b/client/executor/src/native_executor.rs index 60e661d10da6..b36d6f1297e9 100644 --- a/client/executor/src/native_executor.rs +++ b/client/executor/src/native_executor.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/executor/src/wasm_runtime.rs b/client/executor/src/wasm_runtime.rs index 94c4f431ef45..cb6fba4e4dee 100644 --- a/client/executor/src/wasm_runtime.rs +++ b/client/executor/src/wasm_runtime.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/executor/wasmi/src/lib.rs b/client/executor/wasmi/src/lib.rs index ceab07c2f71c..78fd300e05e3 100644 --- a/client/executor/wasmi/src/lib.rs +++ b/client/executor/wasmi/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/executor/wasmtime/build.rs b/client/executor/wasmtime/build.rs index 6ab581c9c268..c514b0041bc3 100644 --- a/client/executor/wasmtime/build.rs +++ b/client/executor/wasmtime/build.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 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 diff --git a/client/executor/wasmtime/src/host.rs b/client/executor/wasmtime/src/host.rs index ab8b4cf8b73c..5d02a836640a 100644 --- a/client/executor/wasmtime/src/host.rs +++ b/client/executor/wasmtime/src/host.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/executor/wasmtime/src/imports.rs b/client/executor/wasmtime/src/imports.rs index c18cf58ac722..636a5761c947 100644 --- a/client/executor/wasmtime/src/imports.rs +++ b/client/executor/wasmtime/src/imports.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/executor/wasmtime/src/instance_wrapper.rs b/client/executor/wasmtime/src/instance_wrapper.rs index 58f96eb26363..af21a8080cd5 100644 --- a/client/executor/wasmtime/src/instance_wrapper.rs +++ b/client/executor/wasmtime/src/instance_wrapper.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/executor/wasmtime/src/lib.rs b/client/executor/wasmtime/src/lib.rs index e0d6a262afda..c54c8305f3e4 100644 --- a/client/executor/wasmtime/src/lib.rs +++ b/client/executor/wasmtime/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/executor/wasmtime/src/runtime.rs b/client/executor/wasmtime/src/runtime.rs index b870405f92d3..6300163db50c 100644 --- a/client/executor/wasmtime/src/runtime.rs +++ b/client/executor/wasmtime/src/runtime.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/executor/wasmtime/src/tests.rs b/client/executor/wasmtime/src/tests.rs index 31fb5d3da1c7..c1e626f12d1a 100644 --- a/client/executor/wasmtime/src/tests.rs +++ b/client/executor/wasmtime/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 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 diff --git a/client/executor/wasmtime/src/util.rs b/client/executor/wasmtime/src/util.rs index 2c9379e9ce81..60ca598aee18 100644 --- a/client/executor/wasmtime/src/util.rs +++ b/client/executor/wasmtime/src/util.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/finality-grandpa/rpc/src/error.rs b/client/finality-grandpa/rpc/src/error.rs index c812b78f3fd8..1c1361bcaeda 100644 --- a/client/finality-grandpa/rpc/src/error.rs +++ b/client/finality-grandpa/rpc/src/error.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/finality-grandpa/rpc/src/finality.rs b/client/finality-grandpa/rpc/src/finality.rs index 62e3502fc718..f2be6d674b2f 100644 --- a/client/finality-grandpa/rpc/src/finality.rs +++ b/client/finality-grandpa/rpc/src/finality.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/finality-grandpa/rpc/src/lib.rs b/client/finality-grandpa/rpc/src/lib.rs index 3e7fddfddf2f..e509d435af4a 100644 --- a/client/finality-grandpa/rpc/src/lib.rs +++ b/client/finality-grandpa/rpc/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/finality-grandpa/rpc/src/notification.rs b/client/finality-grandpa/rpc/src/notification.rs index 68944e903e0f..6fb138357935 100644 --- a/client/finality-grandpa/rpc/src/notification.rs +++ b/client/finality-grandpa/rpc/src/notification.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/finality-grandpa/rpc/src/report.rs b/client/finality-grandpa/rpc/src/report.rs index fc97c176f34f..24d0b5ab0d1d 100644 --- a/client/finality-grandpa/rpc/src/report.rs +++ b/client/finality-grandpa/rpc/src/report.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/finality-grandpa/src/authorities.rs b/client/finality-grandpa/src/authorities.rs index 6ab36847fe3d..aa8be83b9529 100644 --- a/client/finality-grandpa/src/authorities.rs +++ b/client/finality-grandpa/src/authorities.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/finality-grandpa/src/aux_schema.rs b/client/finality-grandpa/src/aux_schema.rs index 9294fbc4161b..2ec48a804c93 100644 --- a/client/finality-grandpa/src/aux_schema.rs +++ b/client/finality-grandpa/src/aux_schema.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/finality-grandpa/src/communication/gossip.rs b/client/finality-grandpa/src/communication/gossip.rs index 74e7cc530065..51d832c3b27b 100644 --- a/client/finality-grandpa/src/communication/gossip.rs +++ b/client/finality-grandpa/src/communication/gossip.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/finality-grandpa/src/communication/mod.rs b/client/finality-grandpa/src/communication/mod.rs index c370e1d642d7..43b2f5463c8d 100644 --- a/client/finality-grandpa/src/communication/mod.rs +++ b/client/finality-grandpa/src/communication/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/finality-grandpa/src/communication/periodic.rs b/client/finality-grandpa/src/communication/periodic.rs index 77e55ad652f6..e6d63beafc36 100644 --- a/client/finality-grandpa/src/communication/periodic.rs +++ b/client/finality-grandpa/src/communication/periodic.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/finality-grandpa/src/communication/tests.rs b/client/finality-grandpa/src/communication/tests.rs index 1e88f8a93404..ed23415972f9 100644 --- a/client/finality-grandpa/src/communication/tests.rs +++ b/client/finality-grandpa/src/communication/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/finality-grandpa/src/environment.rs b/client/finality-grandpa/src/environment.rs index 1f5b381c1382..bbd739086ba5 100644 --- a/client/finality-grandpa/src/environment.rs +++ b/client/finality-grandpa/src/environment.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/finality-grandpa/src/finality_proof.rs b/client/finality-grandpa/src/finality_proof.rs index ac7be37eb20c..cc6853bee3b0 100644 --- a/client/finality-grandpa/src/finality_proof.rs +++ b/client/finality-grandpa/src/finality_proof.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/finality-grandpa/src/import.rs b/client/finality-grandpa/src/import.rs index 000f7397ac9d..71d74045f476 100644 --- a/client/finality-grandpa/src/import.rs +++ b/client/finality-grandpa/src/import.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/finality-grandpa/src/justification.rs b/client/finality-grandpa/src/justification.rs index a852c74d9d1a..5ee5f278ed8b 100644 --- a/client/finality-grandpa/src/justification.rs +++ b/client/finality-grandpa/src/justification.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/finality-grandpa/src/lib.rs b/client/finality-grandpa/src/lib.rs index 656d8ea43434..b8873d00efa7 100644 --- a/client/finality-grandpa/src/lib.rs +++ b/client/finality-grandpa/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/finality-grandpa/src/notification.rs b/client/finality-grandpa/src/notification.rs index 85d581bd5065..0d154fb3357e 100644 --- a/client/finality-grandpa/src/notification.rs +++ b/client/finality-grandpa/src/notification.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/finality-grandpa/src/observer.rs b/client/finality-grandpa/src/observer.rs index 70a94cd50472..ab0c69ef7fc2 100644 --- a/client/finality-grandpa/src/observer.rs +++ b/client/finality-grandpa/src/observer.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/finality-grandpa/src/tests.rs b/client/finality-grandpa/src/tests.rs index 7af02d066be3..f619c03cab6f 100644 --- a/client/finality-grandpa/src/tests.rs +++ b/client/finality-grandpa/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/finality-grandpa/src/until_imported.rs b/client/finality-grandpa/src/until_imported.rs index 430db23d6220..6adce0d92020 100644 --- a/client/finality-grandpa/src/until_imported.rs +++ b/client/finality-grandpa/src/until_imported.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/finality-grandpa/src/voting_rule.rs b/client/finality-grandpa/src/voting_rule.rs index 7c8d94d970f8..749c504a051c 100644 --- a/client/finality-grandpa/src/voting_rule.rs +++ b/client/finality-grandpa/src/voting_rule.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/informant/src/display.rs b/client/informant/src/display.rs index 6496172b8089..8d76939fddd6 100644 --- a/client/informant/src/display.rs +++ b/client/informant/src/display.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/informant/src/lib.rs b/client/informant/src/lib.rs index f421dbbb7e56..88a500a3a98f 100644 --- a/client/informant/src/lib.rs +++ b/client/informant/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/keystore/src/lib.rs b/client/keystore/src/lib.rs index 5e29f691997e..83641f267bc8 100644 --- a/client/keystore/src/lib.rs +++ b/client/keystore/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/keystore/src/local.rs b/client/keystore/src/local.rs index be9bb5e14597..9c8e3baab182 100644 --- a/client/keystore/src/local.rs +++ b/client/keystore/src/local.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/client/network-gossip/src/bridge.rs b/client/network-gossip/src/bridge.rs index 477b0678fcc8..f72cd1561651 100644 --- a/client/network-gossip/src/bridge.rs +++ b/client/network-gossip/src/bridge.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/network-gossip/src/lib.rs b/client/network-gossip/src/lib.rs index 4b8b4e39862b..4b8370870246 100644 --- a/client/network-gossip/src/lib.rs +++ b/client/network-gossip/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/network-gossip/src/state_machine.rs b/client/network-gossip/src/state_machine.rs index 63553f2f1602..7ad9853b3615 100644 --- a/client/network-gossip/src/state_machine.rs +++ b/client/network-gossip/src/state_machine.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/network-gossip/src/validator.rs b/client/network-gossip/src/validator.rs index 9a2652d03f64..7d60f7b31397 100644 --- a/client/network-gossip/src/validator.rs +++ b/client/network-gossip/src/validator.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/network/src/behaviour.rs b/client/network/src/behaviour.rs index a6a67d7bce2d..d0de50ef6189 100644 --- a/client/network/src/behaviour.rs +++ b/client/network/src/behaviour.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/network/src/chain.rs b/client/network/src/chain.rs index 7c131dd75370..c66cc2ce1daf 100644 --- a/client/network/src/chain.rs +++ b/client/network/src/chain.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/network/src/config.rs b/client/network/src/config.rs index 8ef52e46fd07..333ea41c8d80 100644 --- a/client/network/src/config.rs +++ b/client/network/src/config.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/network/src/discovery.rs b/client/network/src/discovery.rs index dc08ab57ed3f..cf75e2dcb4c6 100644 --- a/client/network/src/discovery.rs +++ b/client/network/src/discovery.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/network/src/error.rs b/client/network/src/error.rs index b8a31def7dc6..1dafddd7bcc5 100644 --- a/client/network/src/error.rs +++ b/client/network/src/error.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/network/src/lib.rs b/client/network/src/lib.rs index d07e9d3baaa4..27e9a7547b44 100644 --- a/client/network/src/lib.rs +++ b/client/network/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/network/src/light_client_requests.rs b/client/network/src/light_client_requests.rs index b1793ce9384e..c77416003f82 100644 --- a/client/network/src/light_client_requests.rs +++ b/client/network/src/light_client_requests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/network/src/light_client_requests/handler.rs b/client/network/src/light_client_requests/handler.rs index 5ecc85bdb0a0..b5c6ccb196d5 100644 --- a/client/network/src/light_client_requests/handler.rs +++ b/client/network/src/light_client_requests/handler.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/network/src/network_state.rs b/client/network/src/network_state.rs index 6f5f031bf35d..a5e2fbef421d 100644 --- a/client/network/src/network_state.rs +++ b/client/network/src/network_state.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/network/src/peer_info.rs b/client/network/src/peer_info.rs index 2c37fdb460a7..378c258820ff 100644 --- a/client/network/src/peer_info.rs +++ b/client/network/src/peer_info.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/network/src/protocol.rs b/client/network/src/protocol.rs index abd723f13d20..a5a826ed4748 100644 --- a/client/network/src/protocol.rs +++ b/client/network/src/protocol.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/network/src/protocol/event.rs b/client/network/src/protocol/event.rs index e0b35647c753..26c954496060 100644 --- a/client/network/src/protocol/event.rs +++ b/client/network/src/protocol/event.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/network/src/protocol/message.rs b/client/network/src/protocol/message.rs index 001f6cbd7e45..3fb57b1c824a 100644 --- a/client/network/src/protocol/message.rs +++ b/client/network/src/protocol/message.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/network/src/protocol/notifications.rs b/client/network/src/protocol/notifications.rs index e489970e987c..bf183abf160c 100644 --- a/client/network/src/protocol/notifications.rs +++ b/client/network/src/protocol/notifications.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/network/src/protocol/notifications/behaviour.rs b/client/network/src/protocol/notifications/behaviour.rs index 26a246f57690..97047201c308 100644 --- a/client/network/src/protocol/notifications/behaviour.rs +++ b/client/network/src/protocol/notifications/behaviour.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/network/src/protocol/notifications/handler.rs b/client/network/src/protocol/notifications/handler.rs index db0385bea8f6..158ab2ae379c 100644 --- a/client/network/src/protocol/notifications/handler.rs +++ b/client/network/src/protocol/notifications/handler.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/network/src/protocol/notifications/tests.rs b/client/network/src/protocol/notifications/tests.rs index ffc25194def0..73058598a1e3 100644 --- a/client/network/src/protocol/notifications/tests.rs +++ b/client/network/src/protocol/notifications/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/network/src/protocol/notifications/upgrade.rs b/client/network/src/protocol/notifications/upgrade.rs index 196b4f44f81f..c273361acabd 100644 --- a/client/network/src/protocol/notifications/upgrade.rs +++ b/client/network/src/protocol/notifications/upgrade.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/network/src/protocol/notifications/upgrade/collec.rs b/client/network/src/protocol/notifications/upgrade/collec.rs index 2462d2becf4b..db9850c8da74 100644 --- a/client/network/src/protocol/notifications/upgrade/collec.rs +++ b/client/network/src/protocol/notifications/upgrade/collec.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/network/src/protocol/notifications/upgrade/notifications.rs b/client/network/src/protocol/notifications/upgrade/notifications.rs index 997a1ccf1dec..5171d459fa40 100644 --- a/client/network/src/protocol/notifications/upgrade/notifications.rs +++ b/client/network/src/protocol/notifications/upgrade/notifications.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/network/src/protocol/sync.rs b/client/network/src/protocol/sync.rs index a84f5131242e..69722dac22bc 100644 --- a/client/network/src/protocol/sync.rs +++ b/client/network/src/protocol/sync.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/network/src/protocol/sync/blocks.rs b/client/network/src/protocol/sync/blocks.rs index ce4535dc0b45..43b70d17d8ad 100644 --- a/client/network/src/protocol/sync/blocks.rs +++ b/client/network/src/protocol/sync/blocks.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/network/src/protocol/sync/extra_requests.rs b/client/network/src/protocol/sync/extra_requests.rs index c00837169598..680094a74143 100644 --- a/client/network/src/protocol/sync/extra_requests.rs +++ b/client/network/src/protocol/sync/extra_requests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/network/src/protocol/sync/state.rs b/client/network/src/protocol/sync/state.rs index 43aa1c4629f0..3de165b83d9e 100644 --- a/client/network/src/protocol/sync/state.rs +++ b/client/network/src/protocol/sync/state.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/network/src/protocol/sync/warp.rs b/client/network/src/protocol/sync/warp.rs index bbf8a28da14a..6c51d4b3495f 100644 --- a/client/network/src/protocol/sync/warp.rs +++ b/client/network/src/protocol/sync/warp.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 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 diff --git a/client/network/src/request_responses.rs b/client/network/src/request_responses.rs index aa3e1701eee5..24b3d3df00b2 100644 --- a/client/network/src/request_responses.rs +++ b/client/network/src/request_responses.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/network/src/schema.rs b/client/network/src/schema.rs index d4572fca7594..032db5f1733c 100644 --- a/client/network/src/schema.rs +++ b/client/network/src/schema.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/network/src/service.rs b/client/network/src/service.rs index 8b153bc4edf5..9c8c58ef49e4 100644 --- a/client/network/src/service.rs +++ b/client/network/src/service.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/network/src/service/metrics.rs b/client/network/src/service/metrics.rs index 2550f255e848..bf94287d1291 100644 --- a/client/network/src/service/metrics.rs +++ b/client/network/src/service/metrics.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/network/src/service/out_events.rs b/client/network/src/service/out_events.rs index 90888c2371f9..5f088b85b1cf 100644 --- a/client/network/src/service/out_events.rs +++ b/client/network/src/service/out_events.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/network/src/service/signature.rs b/client/network/src/service/signature.rs index c2d6c4f7db6e..d21d28a3007b 100644 --- a/client/network/src/service/signature.rs +++ b/client/network/src/service/signature.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. // -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/network/src/service/tests.rs b/client/network/src/service/tests.rs index 8271da886fca..3dfd7392cd4d 100644 --- a/client/network/src/service/tests.rs +++ b/client/network/src/service/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/network/src/transactions.rs b/client/network/src/transactions.rs index 21fc55acd274..c09c6b88dab8 100644 --- a/client/network/src/transactions.rs +++ b/client/network/src/transactions.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/network/src/transport.rs b/client/network/src/transport.rs index 3f977a21b116..9a8e080234f3 100644 --- a/client/network/src/transport.rs +++ b/client/network/src/transport.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/network/src/utils.rs b/client/network/src/utils.rs index b23b7e0c101e..d0e61a0d0475 100644 --- a/client/network/src/utils.rs +++ b/client/network/src/utils.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/network/test/src/block_import.rs b/client/network/test/src/block_import.rs index 7a4c4f6c8308..a2bd5276c31d 100644 --- a/client/network/test/src/block_import.rs +++ b/client/network/test/src/block_import.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/network/test/src/lib.rs b/client/network/test/src/lib.rs index cfd42327b600..d9e27ce57511 100644 --- a/client/network/test/src/lib.rs +++ b/client/network/test/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/network/test/src/sync.rs b/client/network/test/src/sync.rs index 4828cae84221..5b607a7762b3 100644 --- a/client/network/test/src/sync.rs +++ b/client/network/test/src/sync.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/offchain/src/api.rs b/client/offchain/src/api.rs index c2830510b015..30c7969279ee 100644 --- a/client/offchain/src/api.rs +++ b/client/offchain/src/api.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/offchain/src/api/http.rs b/client/offchain/src/api/http.rs index 632c94b48107..bc8f81f25a64 100644 --- a/client/offchain/src/api/http.rs +++ b/client/offchain/src/api/http.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/offchain/src/api/timestamp.rs b/client/offchain/src/api/timestamp.rs index f1c8c004a019..6622331f570d 100644 --- a/client/offchain/src/api/timestamp.rs +++ b/client/offchain/src/api/timestamp.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/offchain/src/lib.rs b/client/offchain/src/lib.rs index f9230a1552e1..cc49c07bffcf 100644 --- a/client/offchain/src/lib.rs +++ b/client/offchain/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/peerset/src/lib.rs b/client/peerset/src/lib.rs index 7fbda1ba7b7f..c777cfec19d2 100644 --- a/client/peerset/src/lib.rs +++ b/client/peerset/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/peerset/src/peersstate.rs b/client/peerset/src/peersstate.rs index d7a9ef913587..272b903c1da2 100644 --- a/client/peerset/src/peersstate.rs +++ b/client/peerset/src/peersstate.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/peerset/tests/fuzz.rs b/client/peerset/tests/fuzz.rs index 3a9ba686ee95..af4838d724cb 100644 --- a/client/peerset/tests/fuzz.rs +++ b/client/peerset/tests/fuzz.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/proposer-metrics/src/lib.rs b/client/proposer-metrics/src/lib.rs index ca60cafef3f6..a34660faab5d 100644 --- a/client/proposer-metrics/src/lib.rs +++ b/client/proposer-metrics/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/rpc-api/src/author/error.rs b/client/rpc-api/src/author/error.rs index c7e3ccffabbb..5b6bec7ed4bd 100644 --- a/client/rpc-api/src/author/error.rs +++ b/client/rpc-api/src/author/error.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/rpc-api/src/author/hash.rs b/client/rpc-api/src/author/hash.rs index c4acfb819ddb..453947dd21f2 100644 --- a/client/rpc-api/src/author/hash.rs +++ b/client/rpc-api/src/author/hash.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/rpc-api/src/author/mod.rs b/client/rpc-api/src/author/mod.rs index 720598e0b32a..84167ee95d10 100644 --- a/client/rpc-api/src/author/mod.rs +++ b/client/rpc-api/src/author/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/rpc-api/src/chain/error.rs b/client/rpc-api/src/chain/error.rs index c7f14b2dfc16..a0cacb673915 100644 --- a/client/rpc-api/src/chain/error.rs +++ b/client/rpc-api/src/chain/error.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/rpc-api/src/chain/mod.rs b/client/rpc-api/src/chain/mod.rs index 79ae80d0c4d1..d7d598942f1e 100644 --- a/client/rpc-api/src/chain/mod.rs +++ b/client/rpc-api/src/chain/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/rpc-api/src/child_state/mod.rs b/client/rpc-api/src/child_state/mod.rs index de94790d0990..6b4cd20f2260 100644 --- a/client/rpc-api/src/child_state/mod.rs +++ b/client/rpc-api/src/child_state/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/rpc-api/src/errors.rs b/client/rpc-api/src/errors.rs index 8e4883a4cc20..42e563342fa4 100644 --- a/client/rpc-api/src/errors.rs +++ b/client/rpc-api/src/errors.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/rpc-api/src/helpers.rs b/client/rpc-api/src/helpers.rs index a26adbf2e903..2fbd2f504046 100644 --- a/client/rpc-api/src/helpers.rs +++ b/client/rpc-api/src/helpers.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/rpc-api/src/lib.rs b/client/rpc-api/src/lib.rs index 92de1e7fcb34..2b2e09e709aa 100644 --- a/client/rpc-api/src/lib.rs +++ b/client/rpc-api/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/rpc-api/src/metadata.rs b/client/rpc-api/src/metadata.rs index d493b92c11ac..3c798782062e 100644 --- a/client/rpc-api/src/metadata.rs +++ b/client/rpc-api/src/metadata.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/rpc-api/src/offchain/error.rs b/client/rpc-api/src/offchain/error.rs index 6b8e2bfe189b..41f1416bfb36 100644 --- a/client/rpc-api/src/offchain/error.rs +++ b/client/rpc-api/src/offchain/error.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/rpc-api/src/offchain/mod.rs b/client/rpc-api/src/offchain/mod.rs index 333892fc19c4..c76e83011072 100644 --- a/client/rpc-api/src/offchain/mod.rs +++ b/client/rpc-api/src/offchain/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/rpc-api/src/policy.rs b/client/rpc-api/src/policy.rs index 5d56c62bfece..4d1e1d7c4ce7 100644 --- a/client/rpc-api/src/policy.rs +++ b/client/rpc-api/src/policy.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/rpc-api/src/state/error.rs b/client/rpc-api/src/state/error.rs index d70086347632..4414629e2e29 100644 --- a/client/rpc-api/src/state/error.rs +++ b/client/rpc-api/src/state/error.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/rpc-api/src/state/helpers.rs b/client/rpc-api/src/state/helpers.rs index 718ad69ac232..25f07be1c97c 100644 --- a/client/rpc-api/src/state/helpers.rs +++ b/client/rpc-api/src/state/helpers.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/rpc-api/src/state/mod.rs b/client/rpc-api/src/state/mod.rs index 1cc191197232..453e954ce595 100644 --- a/client/rpc-api/src/state/mod.rs +++ b/client/rpc-api/src/state/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/rpc-api/src/system/error.rs b/client/rpc-api/src/system/error.rs index 4ba5125d82bc..050d79b6ad63 100644 --- a/client/rpc-api/src/system/error.rs +++ b/client/rpc-api/src/system/error.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/rpc-api/src/system/helpers.rs b/client/rpc-api/src/system/helpers.rs index 96e8aeb1ae3d..e17e0f518c3e 100644 --- a/client/rpc-api/src/system/helpers.rs +++ b/client/rpc-api/src/system/helpers.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/rpc-api/src/system/mod.rs b/client/rpc-api/src/system/mod.rs index 3ffc5f434650..b610094f5b58 100644 --- a/client/rpc-api/src/system/mod.rs +++ b/client/rpc-api/src/system/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/rpc-servers/src/lib.rs b/client/rpc-servers/src/lib.rs index 82da84834320..963d9aec072f 100644 --- a/client/rpc-servers/src/lib.rs +++ b/client/rpc-servers/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/rpc-servers/src/middleware.rs b/client/rpc-servers/src/middleware.rs index a78c0642cb58..4adc87866009 100644 --- a/client/rpc-servers/src/middleware.rs +++ b/client/rpc-servers/src/middleware.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/rpc/src/author/mod.rs b/client/rpc/src/author/mod.rs index 5046f2631920..2b604d2897c5 100644 --- a/client/rpc/src/author/mod.rs +++ b/client/rpc/src/author/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/rpc/src/author/tests.rs b/client/rpc/src/author/tests.rs index 5c1ade96f96b..c555465645a7 100644 --- a/client/rpc/src/author/tests.rs +++ b/client/rpc/src/author/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/rpc/src/chain/chain_full.rs b/client/rpc/src/chain/chain_full.rs index 96d5b86f4249..288a825eb5be 100644 --- a/client/rpc/src/chain/chain_full.rs +++ b/client/rpc/src/chain/chain_full.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/rpc/src/chain/mod.rs b/client/rpc/src/chain/mod.rs index c2f512c338b1..c20e5a188ad3 100644 --- a/client/rpc/src/chain/mod.rs +++ b/client/rpc/src/chain/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/rpc/src/chain/tests.rs b/client/rpc/src/chain/tests.rs index caa9f33138b8..fa4473d35f30 100644 --- a/client/rpc/src/chain/tests.rs +++ b/client/rpc/src/chain/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/rpc/src/lib.rs b/client/rpc/src/lib.rs index 8f951632698f..3966baf13c75 100644 --- a/client/rpc/src/lib.rs +++ b/client/rpc/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/rpc/src/offchain/mod.rs b/client/rpc/src/offchain/mod.rs index 9d1cc702b51e..67b97d31ab94 100644 --- a/client/rpc/src/offchain/mod.rs +++ b/client/rpc/src/offchain/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/rpc/src/offchain/tests.rs b/client/rpc/src/offchain/tests.rs index f9629e70198a..219eeb192dfd 100644 --- a/client/rpc/src/offchain/tests.rs +++ b/client/rpc/src/offchain/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/rpc/src/state/mod.rs b/client/rpc/src/state/mod.rs index bacf39124abc..071db5324c83 100644 --- a/client/rpc/src/state/mod.rs +++ b/client/rpc/src/state/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/rpc/src/state/state_full.rs b/client/rpc/src/state/state_full.rs index d3b41d2f1827..2c5a985a2b01 100644 --- a/client/rpc/src/state/state_full.rs +++ b/client/rpc/src/state/state_full.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/rpc/src/state/tests.rs b/client/rpc/src/state/tests.rs index 12e1c449d3bd..d3aca181a41e 100644 --- a/client/rpc/src/state/tests.rs +++ b/client/rpc/src/state/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/rpc/src/system/mod.rs b/client/rpc/src/system/mod.rs index f99994e41a1b..534e446e140a 100644 --- a/client/rpc/src/system/mod.rs +++ b/client/rpc/src/system/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/rpc/src/system/tests.rs b/client/rpc/src/system/tests.rs index c64449ff13aa..3e5241e2638b 100644 --- a/client/rpc/src/system/tests.rs +++ b/client/rpc/src/system/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/rpc/src/testing.rs b/client/rpc/src/testing.rs index 23071ba10e0d..bfb91adb81d3 100644 --- a/client/rpc/src/testing.rs +++ b/client/rpc/src/testing.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index 718cfce981f1..262ba53a33d4 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/service/src/chain_ops/check_block.rs b/client/service/src/chain_ops/check_block.rs index 5e2a9faaf0c4..e12766659d9a 100644 --- a/client/service/src/chain_ops/check_block.rs +++ b/client/service/src/chain_ops/check_block.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/service/src/chain_ops/export_blocks.rs b/client/service/src/chain_ops/export_blocks.rs index 888718010318..d442a11f2c39 100644 --- a/client/service/src/chain_ops/export_blocks.rs +++ b/client/service/src/chain_ops/export_blocks.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/service/src/chain_ops/export_raw_state.rs b/client/service/src/chain_ops/export_raw_state.rs index 975149c61cfa..ffe91d0d7355 100644 --- a/client/service/src/chain_ops/export_raw_state.rs +++ b/client/service/src/chain_ops/export_raw_state.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/service/src/chain_ops/import_blocks.rs b/client/service/src/chain_ops/import_blocks.rs index e4096afacdd3..aa72b745c7ca 100644 --- a/client/service/src/chain_ops/import_blocks.rs +++ b/client/service/src/chain_ops/import_blocks.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/service/src/chain_ops/mod.rs b/client/service/src/chain_ops/mod.rs index c213e745a5d6..98245eeb98d0 100644 --- a/client/service/src/chain_ops/mod.rs +++ b/client/service/src/chain_ops/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/service/src/chain_ops/revert_chain.rs b/client/service/src/chain_ops/revert_chain.rs index 63f1cbd15dd6..9a3ce6024ed9 100644 --- a/client/service/src/chain_ops/revert_chain.rs +++ b/client/service/src/chain_ops/revert_chain.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/service/src/client/block_rules.rs b/client/service/src/client/block_rules.rs index 4bdf33836296..519d5a13f516 100644 --- a/client/service/src/client/block_rules.rs +++ b/client/service/src/client/block_rules.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/service/src/client/call_executor.rs b/client/service/src/client/call_executor.rs index 2acbbb75dcb1..f2b45bc413e2 100644 --- a/client/service/src/client/call_executor.rs +++ b/client/service/src/client/call_executor.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/service/src/client/client.rs b/client/service/src/client/client.rs index 1f76fe017ae0..452450c71e78 100644 --- a/client/service/src/client/client.rs +++ b/client/service/src/client/client.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/service/src/client/genesis.rs b/client/service/src/client/genesis.rs index b48ca2464b54..35fb11f04972 100644 --- a/client/service/src/client/genesis.rs +++ b/client/service/src/client/genesis.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/service/src/client/mod.rs b/client/service/src/client/mod.rs index d10b3d16b813..eac744923d50 100644 --- a/client/service/src/client/mod.rs +++ b/client/service/src/client/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/service/src/client/wasm_override.rs b/client/service/src/client/wasm_override.rs index 88b2c3895b02..86365f2d0cab 100644 --- a/client/service/src/client/wasm_override.rs +++ b/client/service/src/client/wasm_override.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/service/src/client/wasm_substitutes.rs b/client/service/src/client/wasm_substitutes.rs index 28975790e9b5..6f9a6dff43c7 100644 --- a/client/service/src/client/wasm_substitutes.rs +++ b/client/service/src/client/wasm_substitutes.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 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 diff --git a/client/service/src/config.rs b/client/service/src/config.rs index db2041ed96f1..45a6f832f8ee 100644 --- a/client/service/src/config.rs +++ b/client/service/src/config.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/service/src/error.rs b/client/service/src/error.rs index 1acd33ead677..be2199de2643 100644 --- a/client/service/src/error.rs +++ b/client/service/src/error.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/service/src/lib.rs b/client/service/src/lib.rs index 9cf5cc69bdc3..9710ba9e3d84 100644 --- a/client/service/src/lib.rs +++ b/client/service/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/service/src/metrics.rs b/client/service/src/metrics.rs index 54550330d75e..02e3ab95f118 100644 --- a/client/service/src/metrics.rs +++ b/client/service/src/metrics.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/service/src/task_manager/mod.rs b/client/service/src/task_manager/mod.rs index e09a351b6092..2f9cd257c360 100644 --- a/client/service/src/task_manager/mod.rs +++ b/client/service/src/task_manager/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/service/src/task_manager/prometheus_future.rs b/client/service/src/task_manager/prometheus_future.rs index 43a76a0f596c..88296a67336f 100644 --- a/client/service/src/task_manager/prometheus_future.rs +++ b/client/service/src/task_manager/prometheus_future.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/service/src/task_manager/tests.rs b/client/service/src/task_manager/tests.rs index f14023f34f6b..323110a4e1b0 100644 --- a/client/service/src/task_manager/tests.rs +++ b/client/service/src/task_manager/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/service/test/src/client/db.rs b/client/service/test/src/client/db.rs index 5278c9a13a4d..5c1315fc870c 100644 --- a/client/service/test/src/client/db.rs +++ b/client/service/test/src/client/db.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/service/test/src/client/mod.rs b/client/service/test/src/client/mod.rs index cd4ce132b663..535edfadaf29 100644 --- a/client/service/test/src/client/mod.rs +++ b/client/service/test/src/client/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/service/test/src/lib.rs b/client/service/test/src/lib.rs index 7033001db43c..67b33dfd55d1 100644 --- a/client/service/test/src/lib.rs +++ b/client/service/test/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/state-db/src/lib.rs b/client/state-db/src/lib.rs index 44629975d781..b7d58bb808a7 100644 --- a/client/state-db/src/lib.rs +++ b/client/state-db/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/state-db/src/noncanonical.rs b/client/state-db/src/noncanonical.rs index c726ceae4b05..0509e54946e9 100644 --- a/client/state-db/src/noncanonical.rs +++ b/client/state-db/src/noncanonical.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/state-db/src/pruning.rs b/client/state-db/src/pruning.rs index 465c1ecda6cc..2631405cdffa 100644 --- a/client/state-db/src/pruning.rs +++ b/client/state-db/src/pruning.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/state-db/src/test.rs b/client/state-db/src/test.rs index ad5ce8e874cc..9fb97036b2f2 100644 --- a/client/state-db/src/test.rs +++ b/client/state-db/src/test.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/sync-state-rpc/src/lib.rs b/client/sync-state-rpc/src/lib.rs index a1621e3986d7..f416b3a0e8f7 100644 --- a/client/sync-state-rpc/src/lib.rs +++ b/client/sync-state-rpc/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/telemetry/src/endpoints.rs b/client/telemetry/src/endpoints.rs index 62e618031198..fba3822a9067 100644 --- a/client/telemetry/src/endpoints.rs +++ b/client/telemetry/src/endpoints.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 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 diff --git a/client/telemetry/src/error.rs b/client/telemetry/src/error.rs index 90a8018f4e1d..4d9cdc05c51b 100644 --- a/client/telemetry/src/error.rs +++ b/client/telemetry/src/error.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 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 diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 2e50bf5884fa..68128e020708 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/telemetry/src/node.rs b/client/telemetry/src/node.rs index 4d845c328fe8..ec857ede70fd 100644 --- a/client/telemetry/src/node.rs +++ b/client/telemetry/src/node.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 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 diff --git a/client/telemetry/src/transport.rs b/client/telemetry/src/transport.rs index 04ec79ebf564..23725b44a64d 100644 --- a/client/telemetry/src/transport.rs +++ b/client/telemetry/src/transport.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 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 diff --git a/client/tracing/benches/bench.rs b/client/tracing/benches/bench.rs index ee218958be9b..a939a2679739 100644 --- a/client/tracing/benches/bench.rs +++ b/client/tracing/benches/bench.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/client/tracing/proc-macro/src/lib.rs b/client/tracing/proc-macro/src/lib.rs index 005fcf4ba0f5..b1ffcb97b752 100644 --- a/client/tracing/proc-macro/src/lib.rs +++ b/client/tracing/proc-macro/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/tracing/src/lib.rs b/client/tracing/src/lib.rs index fc501bb9a432..cbbd8063c34f 100644 --- a/client/tracing/src/lib.rs +++ b/client/tracing/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/tracing/src/logging/event_format.rs b/client/tracing/src/logging/event_format.rs index 944901d803bd..aec6b76843da 100644 --- a/client/tracing/src/logging/event_format.rs +++ b/client/tracing/src/logging/event_format.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/tracing/src/logging/fast_local_time.rs b/client/tracing/src/logging/fast_local_time.rs index 288e44aa5e3a..47fc23340482 100644 --- a/client/tracing/src/logging/fast_local_time.rs +++ b/client/tracing/src/logging/fast_local_time.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 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 diff --git a/client/tracing/src/logging/layers/mod.rs b/client/tracing/src/logging/layers/mod.rs index 7dd0c4d120ad..382b79bc85d7 100644 --- a/client/tracing/src/logging/layers/mod.rs +++ b/client/tracing/src/logging/layers/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 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 diff --git a/client/tracing/src/logging/layers/prefix_layer.rs b/client/tracing/src/logging/layers/prefix_layer.rs index 2ad786a09223..836ffd2adda8 100644 --- a/client/tracing/src/logging/layers/prefix_layer.rs +++ b/client/tracing/src/logging/layers/prefix_layer.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 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 diff --git a/client/tracing/src/logging/mod.rs b/client/tracing/src/logging/mod.rs index 72740715e55b..c325a3f73c41 100644 --- a/client/tracing/src/logging/mod.rs +++ b/client/tracing/src/logging/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 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 diff --git a/client/tracing/src/logging/stderr_writer.rs b/client/tracing/src/logging/stderr_writer.rs index 9aab2491fb87..e62c5e82c1ac 100644 --- a/client/tracing/src/logging/stderr_writer.rs +++ b/client/tracing/src/logging/stderr_writer.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 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 diff --git a/client/transaction-pool/api/src/error.rs b/client/transaction-pool/api/src/error.rs index feee3b0a949c..f1ac2798e62d 100644 --- a/client/transaction-pool/api/src/error.rs +++ b/client/transaction-pool/api/src/error.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/transaction-pool/api/src/lib.rs b/client/transaction-pool/api/src/lib.rs index cd8784bfc83e..f19a994b1b94 100644 --- a/client/transaction-pool/api/src/lib.rs +++ b/client/transaction-pool/api/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/client/transaction-pool/benches/basics.rs b/client/transaction-pool/benches/basics.rs index cfb40c6cb2ab..c6b15ce4f177 100644 --- a/client/transaction-pool/benches/basics.rs +++ b/client/transaction-pool/benches/basics.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/transaction-pool/src/api.rs b/client/transaction-pool/src/api.rs index 08fe1e34edb8..de1c79534b38 100644 --- a/client/transaction-pool/src/api.rs +++ b/client/transaction-pool/src/api.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/transaction-pool/src/error.rs b/client/transaction-pool/src/error.rs index b14e0569f083..adc19d52c7e4 100644 --- a/client/transaction-pool/src/error.rs +++ b/client/transaction-pool/src/error.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/transaction-pool/src/graph/base_pool.rs b/client/transaction-pool/src/graph/base_pool.rs index cf634c3213a8..8e0422739cc6 100644 --- a/client/transaction-pool/src/graph/base_pool.rs +++ b/client/transaction-pool/src/graph/base_pool.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/transaction-pool/src/graph/future.rs b/client/transaction-pool/src/graph/future.rs index 6ed1f1014304..ae49e3f2d3ae 100644 --- a/client/transaction-pool/src/graph/future.rs +++ b/client/transaction-pool/src/graph/future.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/transaction-pool/src/graph/listener.rs b/client/transaction-pool/src/graph/listener.rs index b8149018f783..d4f42b32fdbb 100644 --- a/client/transaction-pool/src/graph/listener.rs +++ b/client/transaction-pool/src/graph/listener.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/transaction-pool/src/graph/mod.rs b/client/transaction-pool/src/graph/mod.rs index 3ecfb8fe68c6..42812897a954 100644 --- a/client/transaction-pool/src/graph/mod.rs +++ b/client/transaction-pool/src/graph/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/transaction-pool/src/graph/pool.rs b/client/transaction-pool/src/graph/pool.rs index 1032282af99d..3d0f8a017a97 100644 --- a/client/transaction-pool/src/graph/pool.rs +++ b/client/transaction-pool/src/graph/pool.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/transaction-pool/src/graph/ready.rs b/client/transaction-pool/src/graph/ready.rs index 92adf2e62d62..ebaa73f14924 100644 --- a/client/transaction-pool/src/graph/ready.rs +++ b/client/transaction-pool/src/graph/ready.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/transaction-pool/src/graph/rotator.rs b/client/transaction-pool/src/graph/rotator.rs index 910f86b5ed5b..b897fe788503 100644 --- a/client/transaction-pool/src/graph/rotator.rs +++ b/client/transaction-pool/src/graph/rotator.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/transaction-pool/src/graph/tracked_map.rs b/client/transaction-pool/src/graph/tracked_map.rs index 2f560d1c5624..32d04b006887 100644 --- a/client/transaction-pool/src/graph/tracked_map.rs +++ b/client/transaction-pool/src/graph/tracked_map.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/transaction-pool/src/graph/validated_pool.rs b/client/transaction-pool/src/graph/validated_pool.rs index dba586adc846..137c7298f515 100644 --- a/client/transaction-pool/src/graph/validated_pool.rs +++ b/client/transaction-pool/src/graph/validated_pool.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/transaction-pool/src/graph/watcher.rs b/client/transaction-pool/src/graph/watcher.rs index 975ee6608886..8cd78cfc7824 100644 --- a/client/transaction-pool/src/graph/watcher.rs +++ b/client/transaction-pool/src/graph/watcher.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/transaction-pool/src/lib.rs b/client/transaction-pool/src/lib.rs index 85af4f89d72b..065c83be3bfc 100644 --- a/client/transaction-pool/src/lib.rs +++ b/client/transaction-pool/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/transaction-pool/src/metrics.rs b/client/transaction-pool/src/metrics.rs index 7afed2150978..8bcefe246bff 100644 --- a/client/transaction-pool/src/metrics.rs +++ b/client/transaction-pool/src/metrics.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/transaction-pool/src/revalidation.rs b/client/transaction-pool/src/revalidation.rs index a8b2c1d32036..6b6ed858e7ec 100644 --- a/client/transaction-pool/src/revalidation.rs +++ b/client/transaction-pool/src/revalidation.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/client/transaction-pool/tests/pool.rs b/client/transaction-pool/tests/pool.rs index 6c34d05cd5dc..14ccacfb2692 100644 --- a/client/transaction-pool/tests/pool.rs +++ b/client/transaction-pool/tests/pool.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/utils/src/lib.rs b/client/utils/src/lib.rs index b49cd60d67b1..fab4365c8ed8 100644 --- a/client/utils/src/lib.rs +++ b/client/utils/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/utils/src/metrics.rs b/client/utils/src/metrics.rs index 6e85a66e62e5..457ef23e41ab 100644 --- a/client/utils/src/metrics.rs +++ b/client/utils/src/metrics.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/utils/src/mpsc.rs b/client/utils/src/mpsc.rs index 1739af5e9015..ee3fba4a5ee6 100644 --- a/client/utils/src/mpsc.rs +++ b/client/utils/src/mpsc.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/client/utils/src/status_sinks.rs b/client/utils/src/status_sinks.rs index a87f0e0ad6e8..a1d965d08085 100644 --- a/client/utils/src/status_sinks.rs +++ b/client/utils/src/status_sinks.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 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 diff --git a/frame/assets/src/benchmarking.rs b/frame/assets/src/benchmarking.rs index 475864bac943..33de190a8e36 100644 --- a/frame/assets/src/benchmarking.rs +++ b/frame/assets/src/benchmarking.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/assets/src/extra_mutator.rs b/frame/assets/src/extra_mutator.rs index 5ebfc3e54713..b72bfa86df5b 100644 --- a/frame/assets/src/extra_mutator.rs +++ b/frame/assets/src/extra_mutator.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/assets/src/functions.rs b/frame/assets/src/functions.rs index a34900e74bbb..e02cc7c8bb21 100644 --- a/frame/assets/src/functions.rs +++ b/frame/assets/src/functions.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/assets/src/impl_fungibles.rs b/frame/assets/src/impl_fungibles.rs index be534bfad57a..49caac83f4c4 100644 --- a/frame/assets/src/impl_fungibles.rs +++ b/frame/assets/src/impl_fungibles.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/assets/src/impl_stored_map.rs b/frame/assets/src/impl_stored_map.rs index 88e2203f046b..dfdcff37d1d6 100644 --- a/frame/assets/src/impl_stored_map.rs +++ b/frame/assets/src/impl_stored_map.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/assets/src/lib.rs b/frame/assets/src/lib.rs index 6643cc177460..be8df104dbf0 100644 --- a/frame/assets/src/lib.rs +++ b/frame/assets/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/assets/src/mock.rs b/frame/assets/src/mock.rs index 1e88421dd5ac..34a4cf9ef38f 100644 --- a/frame/assets/src/mock.rs +++ b/frame/assets/src/mock.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/assets/src/tests.rs b/frame/assets/src/tests.rs index a3eacdda4452..a9f4dafc910c 100644 --- a/frame/assets/src/tests.rs +++ b/frame/assets/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/assets/src/types.rs b/frame/assets/src/types.rs index ecf5f5edf417..f8172e0a4a51 100644 --- a/frame/assets/src/types.rs +++ b/frame/assets/src/types.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/assets/src/weights.rs b/frame/assets/src/weights.rs index 912ebcf7e851..423677cf1380 100644 --- a/frame/assets/src/weights.rs +++ b/frame/assets/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/atomic-swap/src/lib.rs b/frame/atomic-swap/src/lib.rs index 4775cd06b1af..8259f53f3950 100644 --- a/frame/atomic-swap/src/lib.rs +++ b/frame/atomic-swap/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/aura/src/lib.rs b/frame/aura/src/lib.rs index e98097055920..4b1d5aeb4a70 100644 --- a/frame/aura/src/lib.rs +++ b/frame/aura/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/aura/src/migrations.rs b/frame/aura/src/migrations.rs index e194c17406b6..d9b7cb8872a8 100644 --- a/frame/aura/src/migrations.rs +++ b/frame/aura/src/migrations.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/aura/src/mock.rs b/frame/aura/src/mock.rs index b9df2cfa0e4d..636a28692ba2 100644 --- a/frame/aura/src/mock.rs +++ b/frame/aura/src/mock.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/aura/src/tests.rs b/frame/aura/src/tests.rs index 596858aac7c9..30003632729e 100644 --- a/frame/aura/src/tests.rs +++ b/frame/aura/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/authority-discovery/src/lib.rs b/frame/authority-discovery/src/lib.rs index 5f905e92569f..d5f0a4c1d339 100644 --- a/frame/authority-discovery/src/lib.rs +++ b/frame/authority-discovery/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/authorship/src/lib.rs b/frame/authorship/src/lib.rs index 297f74ce8b48..6f825e4e7dff 100644 --- a/frame/authorship/src/lib.rs +++ b/frame/authorship/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/babe/src/benchmarking.rs b/frame/babe/src/benchmarking.rs index 7747c9bd1fc8..ac7ab28b5164 100644 --- a/frame/babe/src/benchmarking.rs +++ b/frame/babe/src/benchmarking.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/babe/src/default_weights.rs b/frame/babe/src/default_weights.rs index 20ac9b961fc8..57c74323b793 100644 --- a/frame/babe/src/default_weights.rs +++ b/frame/babe/src/default_weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/babe/src/equivocation.rs b/frame/babe/src/equivocation.rs index 9247acbb3b12..df46f3544b38 100644 --- a/frame/babe/src/equivocation.rs +++ b/frame/babe/src/equivocation.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/babe/src/lib.rs b/frame/babe/src/lib.rs index 6ae0796c866f..424f2df5c16d 100644 --- a/frame/babe/src/lib.rs +++ b/frame/babe/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/babe/src/mock.rs b/frame/babe/src/mock.rs index 90051770b80f..f0faa55e5b33 100644 --- a/frame/babe/src/mock.rs +++ b/frame/babe/src/mock.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/babe/src/randomness.rs b/frame/babe/src/randomness.rs index 7d1862905021..7be27f568e9f 100644 --- a/frame/babe/src/randomness.rs +++ b/frame/babe/src/randomness.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/babe/src/tests.rs b/frame/babe/src/tests.rs index 34d861d5d97f..89911efe4e8a 100644 --- a/frame/babe/src/tests.rs +++ b/frame/babe/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/bags-list/fuzzer/src/main.rs b/frame/bags-list/fuzzer/src/main.rs index 02a2003b9a71..3ff59b450bef 100644 --- a/frame/bags-list/fuzzer/src/main.rs +++ b/frame/bags-list/fuzzer/src/main.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/bags-list/remote-tests/src/lib.rs b/frame/bags-list/remote-tests/src/lib.rs index 3d555eb1f1e3..9a88ff24f2f3 100644 --- a/frame/bags-list/remote-tests/src/lib.rs +++ b/frame/bags-list/remote-tests/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/bags-list/src/benchmarks.rs b/frame/bags-list/src/benchmarks.rs index 41c65978e0d4..5f0bcd460386 100644 --- a/frame/bags-list/src/benchmarks.rs +++ b/frame/bags-list/src/benchmarks.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/bags-list/src/lib.rs b/frame/bags-list/src/lib.rs index 193a334cf08f..98261b6bbafc 100644 --- a/frame/bags-list/src/lib.rs +++ b/frame/bags-list/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/bags-list/src/list/mod.rs b/frame/bags-list/src/list/mod.rs index 4524101d793c..17844b51d4d5 100644 --- a/frame/bags-list/src/list/mod.rs +++ b/frame/bags-list/src/list/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/bags-list/src/list/tests.rs b/frame/bags-list/src/list/tests.rs index f3043589681e..aaa215b0af1c 100644 --- a/frame/bags-list/src/list/tests.rs +++ b/frame/bags-list/src/list/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/bags-list/src/migrations.rs b/frame/bags-list/src/migrations.rs index 8c907539c05f..696733e8c7ba 100644 --- a/frame/bags-list/src/migrations.rs +++ b/frame/bags-list/src/migrations.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/bags-list/src/mock.rs b/frame/bags-list/src/mock.rs index 90d5347b1242..aa3f549e12de 100644 --- a/frame/bags-list/src/mock.rs +++ b/frame/bags-list/src/mock.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/bags-list/src/tests.rs b/frame/bags-list/src/tests.rs index 8f1ccacaf117..43397b3c120f 100644 --- a/frame/bags-list/src/tests.rs +++ b/frame/bags-list/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/bags-list/src/weights.rs b/frame/bags-list/src/weights.rs index 7433c7ac564f..cd5aed0770ab 100644 --- a/frame/bags-list/src/weights.rs +++ b/frame/bags-list/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/balances/src/benchmarking.rs b/frame/balances/src/benchmarking.rs index 1c4882009418..4a874e4ffa1d 100644 --- a/frame/balances/src/benchmarking.rs +++ b/frame/balances/src/benchmarking.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/balances/src/lib.rs b/frame/balances/src/lib.rs index 6919c66f7211..a774cfd61edf 100644 --- a/frame/balances/src/lib.rs +++ b/frame/balances/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/balances/src/tests.rs b/frame/balances/src/tests.rs index e05ed5a3d689..638034d80cd5 100644 --- a/frame/balances/src/tests.rs +++ b/frame/balances/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/balances/src/tests_composite.rs b/frame/balances/src/tests_composite.rs index 15648d7356be..a24be4492737 100644 --- a/frame/balances/src/tests_composite.rs +++ b/frame/balances/src/tests_composite.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/balances/src/tests_local.rs b/frame/balances/src/tests_local.rs index 4ceaff26c4d0..ae56f3b1f0f2 100644 --- a/frame/balances/src/tests_local.rs +++ b/frame/balances/src/tests_local.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/balances/src/tests_reentrancy.rs b/frame/balances/src/tests_reentrancy.rs index 8067e5974caa..4303efc2322c 100644 --- a/frame/balances/src/tests_reentrancy.rs +++ b/frame/balances/src/tests_reentrancy.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/balances/src/weights.rs b/frame/balances/src/weights.rs index 6f333bfc0500..a272753b7346 100644 --- a/frame/balances/src/weights.rs +++ b/frame/balances/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/beefy-mmr/primitives/src/lib.rs b/frame/beefy-mmr/primitives/src/lib.rs index ee1484607563..04fa11760765 100644 --- a/frame/beefy-mmr/primitives/src/lib.rs +++ b/frame/beefy-mmr/primitives/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/beefy-mmr/src/lib.rs b/frame/beefy-mmr/src/lib.rs index cf65e39dba53..38d0a6ac9a7f 100644 --- a/frame/beefy-mmr/src/lib.rs +++ b/frame/beefy-mmr/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/beefy-mmr/src/mock.rs b/frame/beefy-mmr/src/mock.rs index d66385f8807b..88c182aa57ba 100644 --- a/frame/beefy-mmr/src/mock.rs +++ b/frame/beefy-mmr/src/mock.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/beefy-mmr/src/tests.rs b/frame/beefy-mmr/src/tests.rs index 9cfbd94b53bc..6a81c5f25252 100644 --- a/frame/beefy-mmr/src/tests.rs +++ b/frame/beefy-mmr/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/beefy/src/lib.rs b/frame/beefy/src/lib.rs index 9ef0c0d69f30..eb822915ee46 100644 --- a/frame/beefy/src/lib.rs +++ b/frame/beefy/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/beefy/src/mock.rs b/frame/beefy/src/mock.rs index 22330b29b670..0d820116d07b 100644 --- a/frame/beefy/src/mock.rs +++ b/frame/beefy/src/mock.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/beefy/src/tests.rs b/frame/beefy/src/tests.rs index 900a3770279b..7acb40f200df 100644 --- a/frame/beefy/src/tests.rs +++ b/frame/beefy/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/benchmarking/src/analysis.rs b/frame/benchmarking/src/analysis.rs index f655e8fa7632..52baec80e62e 100644 --- a/frame/benchmarking/src/analysis.rs +++ b/frame/benchmarking/src/analysis.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/benchmarking/src/baseline.rs b/frame/benchmarking/src/baseline.rs index e2f9f1f2975f..1ceb9a4f8904 100644 --- a/frame/benchmarking/src/baseline.rs +++ b/frame/benchmarking/src/baseline.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/benchmarking/src/lib.rs b/frame/benchmarking/src/lib.rs index 3e1ed1ed2f11..fcc3913cee78 100644 --- a/frame/benchmarking/src/lib.rs +++ b/frame/benchmarking/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/benchmarking/src/tests.rs b/frame/benchmarking/src/tests.rs index eded93c696bd..06f2b5bdc491 100644 --- a/frame/benchmarking/src/tests.rs +++ b/frame/benchmarking/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/benchmarking/src/tests_instance.rs b/frame/benchmarking/src/tests_instance.rs index 2ac01a052820..ef8351d37e95 100644 --- a/frame/benchmarking/src/tests_instance.rs +++ b/frame/benchmarking/src/tests_instance.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/benchmarking/src/utils.rs b/frame/benchmarking/src/utils.rs index 0bbe8156a9f9..bb0b8d36a752 100644 --- a/frame/benchmarking/src/utils.rs +++ b/frame/benchmarking/src/utils.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/benchmarking/src/weights.rs b/frame/benchmarking/src/weights.rs index af0a782e6b2c..a4d46d24b6e3 100644 --- a/frame/benchmarking/src/weights.rs +++ b/frame/benchmarking/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/bounties/src/benchmarking.rs b/frame/bounties/src/benchmarking.rs index 19f50fdf3931..04adacf6e4ae 100644 --- a/frame/bounties/src/benchmarking.rs +++ b/frame/bounties/src/benchmarking.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/bounties/src/lib.rs b/frame/bounties/src/lib.rs index 752697ce668f..d71b58f05882 100644 --- a/frame/bounties/src/lib.rs +++ b/frame/bounties/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/bounties/src/migrations/mod.rs b/frame/bounties/src/migrations/mod.rs index 26d07a0cd5ac..235d0f1c7cf1 100644 --- a/frame/bounties/src/migrations/mod.rs +++ b/frame/bounties/src/migrations/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/bounties/src/migrations/v4.rs b/frame/bounties/src/migrations/v4.rs index a1ca0e47680b..8f5f3ebe55bf 100644 --- a/frame/bounties/src/migrations/v4.rs +++ b/frame/bounties/src/migrations/v4.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/bounties/src/tests.rs b/frame/bounties/src/tests.rs index 209136dcda1e..912a78c97570 100644 --- a/frame/bounties/src/tests.rs +++ b/frame/bounties/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/bounties/src/weights.rs b/frame/bounties/src/weights.rs index 1383f69bed91..4cff3180ca79 100644 --- a/frame/bounties/src/weights.rs +++ b/frame/bounties/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/child-bounties/src/benchmarking.rs b/frame/child-bounties/src/benchmarking.rs index 3386245cbdca..d9edf14bbc9d 100644 --- a/frame/child-bounties/src/benchmarking.rs +++ b/frame/child-bounties/src/benchmarking.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/child-bounties/src/lib.rs b/frame/child-bounties/src/lib.rs index 3aa160277c82..6bdc1865b841 100644 --- a/frame/child-bounties/src/lib.rs +++ b/frame/child-bounties/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/child-bounties/src/tests.rs b/frame/child-bounties/src/tests.rs index ba68d73ceddc..4b713e699f4d 100644 --- a/frame/child-bounties/src/tests.rs +++ b/frame/child-bounties/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/child-bounties/src/weights.rs b/frame/child-bounties/src/weights.rs index 7a52495d980b..1662984aa7a3 100644 --- a/frame/child-bounties/src/weights.rs +++ b/frame/child-bounties/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/collective/src/benchmarking.rs b/frame/collective/src/benchmarking.rs index 9dcfa2a9c6c8..d5d0fc5f263e 100644 --- a/frame/collective/src/benchmarking.rs +++ b/frame/collective/src/benchmarking.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/collective/src/lib.rs b/frame/collective/src/lib.rs index 26b18b623257..3f423f35b7e5 100644 --- a/frame/collective/src/lib.rs +++ b/frame/collective/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/collective/src/migrations/mod.rs b/frame/collective/src/migrations/mod.rs index 26d07a0cd5ac..235d0f1c7cf1 100644 --- a/frame/collective/src/migrations/mod.rs +++ b/frame/collective/src/migrations/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/collective/src/migrations/v4.rs b/frame/collective/src/migrations/v4.rs index 68284ba4df91..4e6cd0558413 100644 --- a/frame/collective/src/migrations/v4.rs +++ b/frame/collective/src/migrations/v4.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/collective/src/tests.rs b/frame/collective/src/tests.rs index 2af8b1b97036..4f40e02732b4 100644 --- a/frame/collective/src/tests.rs +++ b/frame/collective/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/collective/src/weights.rs b/frame/collective/src/weights.rs index 40ac9eabdd6e..bdb07834a66c 100644 --- a/frame/collective/src/weights.rs +++ b/frame/collective/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/contracts/common/src/lib.rs b/frame/contracts/common/src/lib.rs index 7d99db42a2b9..49f91f676929 100644 --- a/frame/contracts/common/src/lib.rs +++ b/frame/contracts/common/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/contracts/proc-macro/src/lib.rs b/frame/contracts/proc-macro/src/lib.rs index 302a0d01a93d..43b59debc4ad 100644 --- a/frame/contracts/proc-macro/src/lib.rs +++ b/frame/contracts/proc-macro/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/contracts/rpc/runtime-api/src/lib.rs b/frame/contracts/rpc/runtime-api/src/lib.rs index 485040fd235c..59622a21a659 100644 --- a/frame/contracts/rpc/runtime-api/src/lib.rs +++ b/frame/contracts/rpc/runtime-api/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/contracts/rpc/src/lib.rs b/frame/contracts/rpc/src/lib.rs index c4a577196c99..580b74b5ca46 100644 --- a/frame/contracts/rpc/src/lib.rs +++ b/frame/contracts/rpc/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/contracts/src/benchmarking/code.rs b/frame/contracts/src/benchmarking/code.rs index 49df1c383821..d4828871dbbe 100644 --- a/frame/contracts/src/benchmarking/code.rs +++ b/frame/contracts/src/benchmarking/code.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/contracts/src/benchmarking/mod.rs b/frame/contracts/src/benchmarking/mod.rs index ae39d1feca11..49344373f97d 100644 --- a/frame/contracts/src/benchmarking/mod.rs +++ b/frame/contracts/src/benchmarking/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/contracts/src/benchmarking/sandbox.rs b/frame/contracts/src/benchmarking/sandbox.rs index 4412542b547d..451d2fe43391 100644 --- a/frame/contracts/src/benchmarking/sandbox.rs +++ b/frame/contracts/src/benchmarking/sandbox.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/contracts/src/chain_extension.rs b/frame/contracts/src/chain_extension.rs index 14080102933c..b0e08df3adbb 100644 --- a/frame/contracts/src/chain_extension.rs +++ b/frame/contracts/src/chain_extension.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/contracts/src/exec.rs b/frame/contracts/src/exec.rs index bd54c7a08c63..97f301d162af 100644 --- a/frame/contracts/src/exec.rs +++ b/frame/contracts/src/exec.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/contracts/src/gas.rs b/frame/contracts/src/gas.rs index 38d18c1e24c1..cdf0c1407c6b 100644 --- a/frame/contracts/src/gas.rs +++ b/frame/contracts/src/gas.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/contracts/src/lib.rs b/frame/contracts/src/lib.rs index ab7a0c254f56..62e79944bbe9 100644 --- a/frame/contracts/src/lib.rs +++ b/frame/contracts/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/contracts/src/migration.rs b/frame/contracts/src/migration.rs index 7751eb1a2c77..29712a528a72 100644 --- a/frame/contracts/src/migration.rs +++ b/frame/contracts/src/migration.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/contracts/src/schedule.rs b/frame/contracts/src/schedule.rs index b9acc9d49204..dd066bfbe41e 100644 --- a/frame/contracts/src/schedule.rs +++ b/frame/contracts/src/schedule.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/contracts/src/storage.rs b/frame/contracts/src/storage.rs index 6d67729a9a68..7b0671da1058 100644 --- a/frame/contracts/src/storage.rs +++ b/frame/contracts/src/storage.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/contracts/src/storage/meter.rs b/frame/contracts/src/storage/meter.rs index 96ce02fd83ae..2dbd7ede615d 100644 --- a/frame/contracts/src/storage/meter.rs +++ b/frame/contracts/src/storage/meter.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/contracts/src/tests.rs b/frame/contracts/src/tests.rs index 6ca4e34f8aea..4cbc37c57ff2 100644 --- a/frame/contracts/src/tests.rs +++ b/frame/contracts/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/contracts/src/wasm/code_cache.rs b/frame/contracts/src/wasm/code_cache.rs index 2cff043f64ef..e3fe48ac12c2 100644 --- a/frame/contracts/src/wasm/code_cache.rs +++ b/frame/contracts/src/wasm/code_cache.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/contracts/src/wasm/env_def/macros.rs b/frame/contracts/src/wasm/env_def/macros.rs index ea7f51da7526..a50290085df8 100644 --- a/frame/contracts/src/wasm/env_def/macros.rs +++ b/frame/contracts/src/wasm/env_def/macros.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/contracts/src/wasm/env_def/mod.rs b/frame/contracts/src/wasm/env_def/mod.rs index 6a55677f69a0..c74af80d3e4e 100644 --- a/frame/contracts/src/wasm/env_def/mod.rs +++ b/frame/contracts/src/wasm/env_def/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/contracts/src/wasm/mod.rs b/frame/contracts/src/wasm/mod.rs index 913894e8152d..ee7f557d34f0 100644 --- a/frame/contracts/src/wasm/mod.rs +++ b/frame/contracts/src/wasm/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/contracts/src/wasm/prepare.rs b/frame/contracts/src/wasm/prepare.rs index 6d13c097bd43..5e5f8e7e6fc9 100644 --- a/frame/contracts/src/wasm/prepare.rs +++ b/frame/contracts/src/wasm/prepare.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/contracts/src/wasm/runtime.rs b/frame/contracts/src/wasm/runtime.rs index ad13d18435a9..cae68208b31e 100644 --- a/frame/contracts/src/wasm/runtime.rs +++ b/frame/contracts/src/wasm/runtime.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/contracts/src/weights.rs b/frame/contracts/src/weights.rs index 5f61c1e4a346..d60a8ab82f3b 100644 --- a/frame/contracts/src/weights.rs +++ b/frame/contracts/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/democracy/src/benchmarking.rs b/frame/democracy/src/benchmarking.rs index 4068b55f6e7b..bce830b385a9 100644 --- a/frame/democracy/src/benchmarking.rs +++ b/frame/democracy/src/benchmarking.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/democracy/src/conviction.rs b/frame/democracy/src/conviction.rs index 59a5eccc616c..57d631e8c1f4 100644 --- a/frame/democracy/src/conviction.rs +++ b/frame/democracy/src/conviction.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/democracy/src/lib.rs b/frame/democracy/src/lib.rs index d80f8aa89ec3..1e5f3c403006 100644 --- a/frame/democracy/src/lib.rs +++ b/frame/democracy/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/democracy/src/tests.rs b/frame/democracy/src/tests.rs index 1e36313122f0..641014923c23 100644 --- a/frame/democracy/src/tests.rs +++ b/frame/democracy/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/democracy/src/tests/cancellation.rs b/frame/democracy/src/tests/cancellation.rs index 83822bf51829..9035e17c5c80 100644 --- a/frame/democracy/src/tests/cancellation.rs +++ b/frame/democracy/src/tests/cancellation.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/democracy/src/tests/decoders.rs b/frame/democracy/src/tests/decoders.rs index 3c1729c4355c..1fbb88060549 100644 --- a/frame/democracy/src/tests/decoders.rs +++ b/frame/democracy/src/tests/decoders.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/democracy/src/tests/delegation.rs b/frame/democracy/src/tests/delegation.rs index d3afa1c13f90..f644f2295174 100644 --- a/frame/democracy/src/tests/delegation.rs +++ b/frame/democracy/src/tests/delegation.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/democracy/src/tests/external_proposing.rs b/frame/democracy/src/tests/external_proposing.rs index 7442964584fa..5d4a9f2a7cbf 100644 --- a/frame/democracy/src/tests/external_proposing.rs +++ b/frame/democracy/src/tests/external_proposing.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/democracy/src/tests/fast_tracking.rs b/frame/democracy/src/tests/fast_tracking.rs index 9b2f2760bde1..7a15bb8de4da 100644 --- a/frame/democracy/src/tests/fast_tracking.rs +++ b/frame/democracy/src/tests/fast_tracking.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/democracy/src/tests/lock_voting.rs b/frame/democracy/src/tests/lock_voting.rs index 2e1440d8f44b..071873436731 100644 --- a/frame/democracy/src/tests/lock_voting.rs +++ b/frame/democracy/src/tests/lock_voting.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/democracy/src/tests/preimage.rs b/frame/democracy/src/tests/preimage.rs index 6d478fcaa68c..21303c8eddae 100644 --- a/frame/democracy/src/tests/preimage.rs +++ b/frame/democracy/src/tests/preimage.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/democracy/src/tests/public_proposals.rs b/frame/democracy/src/tests/public_proposals.rs index 34713c3e1572..aadc92d24f41 100644 --- a/frame/democracy/src/tests/public_proposals.rs +++ b/frame/democracy/src/tests/public_proposals.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/democracy/src/tests/scheduling.rs b/frame/democracy/src/tests/scheduling.rs index 5c857a632b97..d28f24d76bb5 100644 --- a/frame/democracy/src/tests/scheduling.rs +++ b/frame/democracy/src/tests/scheduling.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/democracy/src/tests/voting.rs b/frame/democracy/src/tests/voting.rs index e035c2d46c1b..d4fceaf0ee48 100644 --- a/frame/democracy/src/tests/voting.rs +++ b/frame/democracy/src/tests/voting.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/democracy/src/types.rs b/frame/democracy/src/types.rs index 2eb004ba61bc..52ab8a40eb3e 100644 --- a/frame/democracy/src/types.rs +++ b/frame/democracy/src/types.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/democracy/src/vote.rs b/frame/democracy/src/vote.rs index da74f7bd2fb6..e6a252dcf015 100644 --- a/frame/democracy/src/vote.rs +++ b/frame/democracy/src/vote.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/democracy/src/vote_threshold.rs b/frame/democracy/src/vote_threshold.rs index ad8bce290ed4..443d6b116619 100644 --- a/frame/democracy/src/vote_threshold.rs +++ b/frame/democracy/src/vote_threshold.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/democracy/src/weights.rs b/frame/democracy/src/weights.rs index 638852d3c7e1..aa8e68f57053 100644 --- a/frame/democracy/src/weights.rs +++ b/frame/democracy/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/election-provider-multi-phase/src/benchmarking.rs b/frame/election-provider-multi-phase/src/benchmarking.rs index 04101f886cec..d605c5131cf7 100644 --- a/frame/election-provider-multi-phase/src/benchmarking.rs +++ b/frame/election-provider-multi-phase/src/benchmarking.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/election-provider-multi-phase/src/helpers.rs b/frame/election-provider-multi-phase/src/helpers.rs index 98a14a93a25e..9bd5b5dbabd2 100644 --- a/frame/election-provider-multi-phase/src/helpers.rs +++ b/frame/election-provider-multi-phase/src/helpers.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/election-provider-multi-phase/src/lib.rs b/frame/election-provider-multi-phase/src/lib.rs index 175de0eeb0c6..8087d22cffe6 100644 --- a/frame/election-provider-multi-phase/src/lib.rs +++ b/frame/election-provider-multi-phase/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/election-provider-multi-phase/src/mock.rs b/frame/election-provider-multi-phase/src/mock.rs index 4e494322b062..409ebd3f1e10 100644 --- a/frame/election-provider-multi-phase/src/mock.rs +++ b/frame/election-provider-multi-phase/src/mock.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/election-provider-multi-phase/src/signed.rs b/frame/election-provider-multi-phase/src/signed.rs index 08cae62ef7d3..c2cb5cf44823 100644 --- a/frame/election-provider-multi-phase/src/signed.rs +++ b/frame/election-provider-multi-phase/src/signed.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/election-provider-multi-phase/src/unsigned.rs b/frame/election-provider-multi-phase/src/unsigned.rs index 1770f4343a0a..6ce0ddfe6764 100644 --- a/frame/election-provider-multi-phase/src/unsigned.rs +++ b/frame/election-provider-multi-phase/src/unsigned.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/election-provider-multi-phase/src/weights.rs b/frame/election-provider-multi-phase/src/weights.rs index 4d49f60fabfc..7bb3303cba2e 100644 --- a/frame/election-provider-multi-phase/src/weights.rs +++ b/frame/election-provider-multi-phase/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/election-provider-support/src/lib.rs b/frame/election-provider-support/src/lib.rs index a4fce64ff1d7..d10504c88cc6 100644 --- a/frame/election-provider-support/src/lib.rs +++ b/frame/election-provider-support/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/election-provider-support/src/onchain.rs b/frame/election-provider-support/src/onchain.rs index ce15edd592ad..d325daf51475 100644 --- a/frame/election-provider-support/src/onchain.rs +++ b/frame/election-provider-support/src/onchain.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/elections-phragmen/src/benchmarking.rs b/frame/elections-phragmen/src/benchmarking.rs index 9bc63848607a..ae98de4be7e4 100644 --- a/frame/elections-phragmen/src/benchmarking.rs +++ b/frame/elections-phragmen/src/benchmarking.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/elections-phragmen/src/lib.rs b/frame/elections-phragmen/src/lib.rs index 3a6c657a6f99..06474cd37bbd 100644 --- a/frame/elections-phragmen/src/lib.rs +++ b/frame/elections-phragmen/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/elections-phragmen/src/migrations/mod.rs b/frame/elections-phragmen/src/migrations/mod.rs index 9a1f86a1ad7c..e7f6429f2298 100644 --- a/frame/elections-phragmen/src/migrations/mod.rs +++ b/frame/elections-phragmen/src/migrations/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/elections-phragmen/src/migrations/v3.rs b/frame/elections-phragmen/src/migrations/v3.rs index 728e0c4b0c91..c6a7ce7e7ca1 100644 --- a/frame/elections-phragmen/src/migrations/v3.rs +++ b/frame/elections-phragmen/src/migrations/v3.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/elections-phragmen/src/migrations/v4.rs b/frame/elections-phragmen/src/migrations/v4.rs index 9acc1297294d..e0fc17ec2a12 100644 --- a/frame/elections-phragmen/src/migrations/v4.rs +++ b/frame/elections-phragmen/src/migrations/v4.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/elections-phragmen/src/weights.rs b/frame/elections-phragmen/src/weights.rs index b60308c4f0a6..0bfc3d2ea87a 100644 --- a/frame/elections-phragmen/src/weights.rs +++ b/frame/elections-phragmen/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/examples/basic/src/benchmarking.rs b/frame/examples/basic/src/benchmarking.rs index a031b15834d6..b823ccd07296 100644 --- a/frame/examples/basic/src/benchmarking.rs +++ b/frame/examples/basic/src/benchmarking.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/examples/basic/src/lib.rs b/frame/examples/basic/src/lib.rs index 2b443ff8e8dd..13c4591be28f 100644 --- a/frame/examples/basic/src/lib.rs +++ b/frame/examples/basic/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/examples/basic/src/tests.rs b/frame/examples/basic/src/tests.rs index 9f93c9053118..0f659e12fb44 100644 --- a/frame/examples/basic/src/tests.rs +++ b/frame/examples/basic/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/examples/basic/src/weights.rs b/frame/examples/basic/src/weights.rs index 048f7f5a8b8e..5fc6434e396e 100644 --- a/frame/examples/basic/src/weights.rs +++ b/frame/examples/basic/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/examples/offchain-worker/src/lib.rs b/frame/examples/offchain-worker/src/lib.rs index ec728e791295..764f6cb9e2d7 100644 --- a/frame/examples/offchain-worker/src/lib.rs +++ b/frame/examples/offchain-worker/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/examples/offchain-worker/src/tests.rs b/frame/examples/offchain-worker/src/tests.rs index 2c3e623e9c84..76f80deb12f9 100644 --- a/frame/examples/offchain-worker/src/tests.rs +++ b/frame/examples/offchain-worker/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/examples/parallel/src/lib.rs b/frame/examples/parallel/src/lib.rs index 55714abb4827..4ea52173a09a 100644 --- a/frame/examples/parallel/src/lib.rs +++ b/frame/examples/parallel/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/examples/parallel/src/tests.rs b/frame/examples/parallel/src/tests.rs index 82ce95d7a85b..67d823d8b204 100644 --- a/frame/examples/parallel/src/tests.rs +++ b/frame/examples/parallel/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/executive/src/lib.rs b/frame/executive/src/lib.rs index 1b74bdc2fea0..be944954eaa5 100644 --- a/frame/executive/src/lib.rs +++ b/frame/executive/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/gilt/src/benchmarking.rs b/frame/gilt/src/benchmarking.rs index 9c6d22a48398..3df08372f499 100644 --- a/frame/gilt/src/benchmarking.rs +++ b/frame/gilt/src/benchmarking.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/gilt/src/lib.rs b/frame/gilt/src/lib.rs index b494eed67445..4fd18626d931 100644 --- a/frame/gilt/src/lib.rs +++ b/frame/gilt/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/gilt/src/mock.rs b/frame/gilt/src/mock.rs index 6299f7c32031..369b34ba77f4 100644 --- a/frame/gilt/src/mock.rs +++ b/frame/gilt/src/mock.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/gilt/src/tests.rs b/frame/gilt/src/tests.rs index 80315141e232..486601b5b2f2 100644 --- a/frame/gilt/src/tests.rs +++ b/frame/gilt/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/gilt/src/weights.rs b/frame/gilt/src/weights.rs index f54d917cc160..fd4dcd1b5d5a 100644 --- a/frame/gilt/src/weights.rs +++ b/frame/gilt/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/grandpa/src/benchmarking.rs b/frame/grandpa/src/benchmarking.rs index 1e6be01ce8db..124085914992 100644 --- a/frame/grandpa/src/benchmarking.rs +++ b/frame/grandpa/src/benchmarking.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/grandpa/src/default_weights.rs b/frame/grandpa/src/default_weights.rs index edc18a7ff8c9..330e9bb25517 100644 --- a/frame/grandpa/src/default_weights.rs +++ b/frame/grandpa/src/default_weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/grandpa/src/equivocation.rs b/frame/grandpa/src/equivocation.rs index 77e38cb63b7d..804272c20480 100644 --- a/frame/grandpa/src/equivocation.rs +++ b/frame/grandpa/src/equivocation.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/grandpa/src/lib.rs b/frame/grandpa/src/lib.rs index b289da464a93..560c933f108c 100644 --- a/frame/grandpa/src/lib.rs +++ b/frame/grandpa/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/grandpa/src/migrations.rs b/frame/grandpa/src/migrations.rs index 05c24e11b393..7795afcd8034 100644 --- a/frame/grandpa/src/migrations.rs +++ b/frame/grandpa/src/migrations.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/grandpa/src/migrations/v4.rs b/frame/grandpa/src/migrations/v4.rs index 094f276efef3..ab43f7baef4e 100644 --- a/frame/grandpa/src/migrations/v4.rs +++ b/frame/grandpa/src/migrations/v4.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/grandpa/src/mock.rs b/frame/grandpa/src/mock.rs index 6f7c57cad0b5..ddfae3d7ea75 100644 --- a/frame/grandpa/src/mock.rs +++ b/frame/grandpa/src/mock.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/grandpa/src/tests.rs b/frame/grandpa/src/tests.rs index 6dc0a26da8bd..ab0a9c677b00 100644 --- a/frame/grandpa/src/tests.rs +++ b/frame/grandpa/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/identity/src/benchmarking.rs b/frame/identity/src/benchmarking.rs index db257fec43a1..2f52aff394b7 100644 --- a/frame/identity/src/benchmarking.rs +++ b/frame/identity/src/benchmarking.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/identity/src/lib.rs b/frame/identity/src/lib.rs index b4b52331618c..a2516a1e874e 100644 --- a/frame/identity/src/lib.rs +++ b/frame/identity/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/identity/src/tests.rs b/frame/identity/src/tests.rs index efbd1d984f33..bf41b451cbaa 100644 --- a/frame/identity/src/tests.rs +++ b/frame/identity/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/identity/src/types.rs b/frame/identity/src/types.rs index ed6aeb18e96a..ed3caafd3a11 100644 --- a/frame/identity/src/types.rs +++ b/frame/identity/src/types.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/identity/src/weights.rs b/frame/identity/src/weights.rs index 92bc4cbaae92..9f04007431be 100644 --- a/frame/identity/src/weights.rs +++ b/frame/identity/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/im-online/src/benchmarking.rs b/frame/im-online/src/benchmarking.rs index 012da53a183e..edc21043c34d 100644 --- a/frame/im-online/src/benchmarking.rs +++ b/frame/im-online/src/benchmarking.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/im-online/src/lib.rs b/frame/im-online/src/lib.rs index 3499078149f2..c9377cd274ad 100644 --- a/frame/im-online/src/lib.rs +++ b/frame/im-online/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/im-online/src/mock.rs b/frame/im-online/src/mock.rs index 8166bfc9119e..86904b38d834 100644 --- a/frame/im-online/src/mock.rs +++ b/frame/im-online/src/mock.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/im-online/src/tests.rs b/frame/im-online/src/tests.rs index bb2c4c7cae54..cab5df9ebe54 100644 --- a/frame/im-online/src/tests.rs +++ b/frame/im-online/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/im-online/src/weights.rs b/frame/im-online/src/weights.rs index 1eadd63cc9d6..19ac7e8ffc0f 100644 --- a/frame/im-online/src/weights.rs +++ b/frame/im-online/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/indices/src/benchmarking.rs b/frame/indices/src/benchmarking.rs index 873dc18b2026..cb06cd809f54 100644 --- a/frame/indices/src/benchmarking.rs +++ b/frame/indices/src/benchmarking.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/indices/src/lib.rs b/frame/indices/src/lib.rs index d8051bac0a3c..0aa931559e0a 100644 --- a/frame/indices/src/lib.rs +++ b/frame/indices/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/indices/src/mock.rs b/frame/indices/src/mock.rs index ef654833c3a3..6bd79708c3dd 100644 --- a/frame/indices/src/mock.rs +++ b/frame/indices/src/mock.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/indices/src/tests.rs b/frame/indices/src/tests.rs index 37df20e9b928..73d591c38bb2 100644 --- a/frame/indices/src/tests.rs +++ b/frame/indices/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/indices/src/weights.rs b/frame/indices/src/weights.rs index 97db58973953..590aa11dec84 100644 --- a/frame/indices/src/weights.rs +++ b/frame/indices/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/lottery/src/benchmarking.rs b/frame/lottery/src/benchmarking.rs index 5407e16cd633..f4a8e88e5e3f 100644 --- a/frame/lottery/src/benchmarking.rs +++ b/frame/lottery/src/benchmarking.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/lottery/src/lib.rs b/frame/lottery/src/lib.rs index b30bc1dc523a..5a985094dd1c 100644 --- a/frame/lottery/src/lib.rs +++ b/frame/lottery/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/lottery/src/mock.rs b/frame/lottery/src/mock.rs index 36b847d48d97..592551fb6b93 100644 --- a/frame/lottery/src/mock.rs +++ b/frame/lottery/src/mock.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/lottery/src/tests.rs b/frame/lottery/src/tests.rs index 623beea4a6b5..143a4b052877 100644 --- a/frame/lottery/src/tests.rs +++ b/frame/lottery/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/lottery/src/weights.rs b/frame/lottery/src/weights.rs index 5fbc61a32e57..5d252e9d5650 100644 --- a/frame/lottery/src/weights.rs +++ b/frame/lottery/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/membership/src/lib.rs b/frame/membership/src/lib.rs index b34051731f69..016c4b39851a 100644 --- a/frame/membership/src/lib.rs +++ b/frame/membership/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/membership/src/migrations/mod.rs b/frame/membership/src/migrations/mod.rs index 26d07a0cd5ac..235d0f1c7cf1 100644 --- a/frame/membership/src/migrations/mod.rs +++ b/frame/membership/src/migrations/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/membership/src/migrations/v4.rs b/frame/membership/src/migrations/v4.rs index c1c944be1fd4..b3b52751d959 100644 --- a/frame/membership/src/migrations/v4.rs +++ b/frame/membership/src/migrations/v4.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/membership/src/weights.rs b/frame/membership/src/weights.rs index 81a1b073faac..5b34529c7c18 100644 --- a/frame/membership/src/weights.rs +++ b/frame/membership/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/merkle-mountain-range/primitives/src/lib.rs b/frame/merkle-mountain-range/primitives/src/lib.rs index 9aae26508f3c..cc78dfefefe6 100644 --- a/frame/merkle-mountain-range/primitives/src/lib.rs +++ b/frame/merkle-mountain-range/primitives/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/merkle-mountain-range/rpc/src/lib.rs b/frame/merkle-mountain-range/rpc/src/lib.rs index 004a70a8e962..b256ccdd7d32 100644 --- a/frame/merkle-mountain-range/rpc/src/lib.rs +++ b/frame/merkle-mountain-range/rpc/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/merkle-mountain-range/src/benchmarking.rs b/frame/merkle-mountain-range/src/benchmarking.rs index 7c0dae26b337..b698e432534d 100644 --- a/frame/merkle-mountain-range/src/benchmarking.rs +++ b/frame/merkle-mountain-range/src/benchmarking.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/merkle-mountain-range/src/default_weights.rs b/frame/merkle-mountain-range/src/default_weights.rs index 6308975ce7d2..73d1963a4296 100644 --- a/frame/merkle-mountain-range/src/default_weights.rs +++ b/frame/merkle-mountain-range/src/default_weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/merkle-mountain-range/src/lib.rs b/frame/merkle-mountain-range/src/lib.rs index 12577880c560..0f5fe751bbd9 100644 --- a/frame/merkle-mountain-range/src/lib.rs +++ b/frame/merkle-mountain-range/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/merkle-mountain-range/src/mmr/mmr.rs b/frame/merkle-mountain-range/src/mmr/mmr.rs index a1963275a0cd..a1516ee8607f 100644 --- a/frame/merkle-mountain-range/src/mmr/mmr.rs +++ b/frame/merkle-mountain-range/src/mmr/mmr.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/merkle-mountain-range/src/mmr/mod.rs b/frame/merkle-mountain-range/src/mmr/mod.rs index ec2dfe245bd4..1a729b08b966 100644 --- a/frame/merkle-mountain-range/src/mmr/mod.rs +++ b/frame/merkle-mountain-range/src/mmr/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/merkle-mountain-range/src/mmr/storage.rs b/frame/merkle-mountain-range/src/mmr/storage.rs index 6e4bf91d802f..a48f60183d67 100644 --- a/frame/merkle-mountain-range/src/mmr/storage.rs +++ b/frame/merkle-mountain-range/src/mmr/storage.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/merkle-mountain-range/src/mmr/utils.rs b/frame/merkle-mountain-range/src/mmr/utils.rs index 77ce0e8ebbb3..d9f7e3b671be 100644 --- a/frame/merkle-mountain-range/src/mmr/utils.rs +++ b/frame/merkle-mountain-range/src/mmr/utils.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/merkle-mountain-range/src/mock.rs b/frame/merkle-mountain-range/src/mock.rs index 2adea420f03d..56d3c9c0d77d 100644 --- a/frame/merkle-mountain-range/src/mock.rs +++ b/frame/merkle-mountain-range/src/mock.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/merkle-mountain-range/src/tests.rs b/frame/merkle-mountain-range/src/tests.rs index 3faf2bfbd9c2..588a407d6d37 100644 --- a/frame/merkle-mountain-range/src/tests.rs +++ b/frame/merkle-mountain-range/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/multisig/src/benchmarking.rs b/frame/multisig/src/benchmarking.rs index cb98d8954030..43abb349b795 100644 --- a/frame/multisig/src/benchmarking.rs +++ b/frame/multisig/src/benchmarking.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/multisig/src/lib.rs b/frame/multisig/src/lib.rs index c02efdc0d371..16ee1c500096 100644 --- a/frame/multisig/src/lib.rs +++ b/frame/multisig/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/multisig/src/tests.rs b/frame/multisig/src/tests.rs index 2d6c02c559e8..d67d06e1bce0 100644 --- a/frame/multisig/src/tests.rs +++ b/frame/multisig/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/multisig/src/weights.rs b/frame/multisig/src/weights.rs index 1bc72d251808..eb78a88f1531 100644 --- a/frame/multisig/src/weights.rs +++ b/frame/multisig/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/nicks/src/lib.rs b/frame/nicks/src/lib.rs index 6d9c15fd3da1..24d80f5a9521 100644 --- a/frame/nicks/src/lib.rs +++ b/frame/nicks/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/node-authorization/src/lib.rs b/frame/node-authorization/src/lib.rs index 17b74053e668..87ec3973d0a8 100644 --- a/frame/node-authorization/src/lib.rs +++ b/frame/node-authorization/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/node-authorization/src/mock.rs b/frame/node-authorization/src/mock.rs index bb882c62abb6..d959d1b8610f 100644 --- a/frame/node-authorization/src/mock.rs +++ b/frame/node-authorization/src/mock.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/node-authorization/src/tests.rs b/frame/node-authorization/src/tests.rs index 530904fa7348..ba78d1491213 100644 --- a/frame/node-authorization/src/tests.rs +++ b/frame/node-authorization/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/node-authorization/src/weights.rs b/frame/node-authorization/src/weights.rs index dbb7956cff96..cf182f94273c 100644 --- a/frame/node-authorization/src/weights.rs +++ b/frame/node-authorization/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/offences/benchmarking/src/lib.rs b/frame/offences/benchmarking/src/lib.rs index 4d042cfd9997..4d6a182034c9 100644 --- a/frame/offences/benchmarking/src/lib.rs +++ b/frame/offences/benchmarking/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/offences/benchmarking/src/mock.rs b/frame/offences/benchmarking/src/mock.rs index 1a5fdcd61bee..598ba650dfff 100644 --- a/frame/offences/benchmarking/src/mock.rs +++ b/frame/offences/benchmarking/src/mock.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/offences/src/lib.rs b/frame/offences/src/lib.rs index c230eac88dce..25605d934d57 100644 --- a/frame/offences/src/lib.rs +++ b/frame/offences/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/offences/src/migration.rs b/frame/offences/src/migration.rs index d655f2cec539..1984db0b7af3 100644 --- a/frame/offences/src/migration.rs +++ b/frame/offences/src/migration.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/offences/src/mock.rs b/frame/offences/src/mock.rs index 17d34d46e313..b3dfbdd90b19 100644 --- a/frame/offences/src/mock.rs +++ b/frame/offences/src/mock.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/offences/src/tests.rs b/frame/offences/src/tests.rs index 8c4fdcc08f99..49bd2fb5a692 100644 --- a/frame/offences/src/tests.rs +++ b/frame/offences/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/preimage/src/benchmarking.rs b/frame/preimage/src/benchmarking.rs index c18c27555025..64326108420e 100644 --- a/frame/preimage/src/benchmarking.rs +++ b/frame/preimage/src/benchmarking.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/preimage/src/lib.rs b/frame/preimage/src/lib.rs index 2d227000c9ed..17fc543084c9 100644 --- a/frame/preimage/src/lib.rs +++ b/frame/preimage/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/preimage/src/mock.rs b/frame/preimage/src/mock.rs index 3996d8425696..109806049a0f 100644 --- a/frame/preimage/src/mock.rs +++ b/frame/preimage/src/mock.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/preimage/src/tests.rs b/frame/preimage/src/tests.rs index 528b26330371..721bb128de23 100644 --- a/frame/preimage/src/tests.rs +++ b/frame/preimage/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/preimage/src/weights.rs b/frame/preimage/src/weights.rs index 406ca99bfb79..fab5cdfb6736 100644 --- a/frame/preimage/src/weights.rs +++ b/frame/preimage/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/proxy/src/benchmarking.rs b/frame/proxy/src/benchmarking.rs index 224610b65185..ceed2e6ab22d 100644 --- a/frame/proxy/src/benchmarking.rs +++ b/frame/proxy/src/benchmarking.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/proxy/src/lib.rs b/frame/proxy/src/lib.rs index fefc66554f45..68aa580bfe7f 100644 --- a/frame/proxy/src/lib.rs +++ b/frame/proxy/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/proxy/src/tests.rs b/frame/proxy/src/tests.rs index 902eae8fc320..b4f30ab4029a 100644 --- a/frame/proxy/src/tests.rs +++ b/frame/proxy/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/proxy/src/weights.rs b/frame/proxy/src/weights.rs index 41aa3034bece..bde4fd761179 100644 --- a/frame/proxy/src/weights.rs +++ b/frame/proxy/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/randomness-collective-flip/src/lib.rs b/frame/randomness-collective-flip/src/lib.rs index bf5920acff8e..5f4994c47142 100644 --- a/frame/randomness-collective-flip/src/lib.rs +++ b/frame/randomness-collective-flip/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/recovery/src/lib.rs b/frame/recovery/src/lib.rs index 24090e9000fa..b0505cbb7daf 100644 --- a/frame/recovery/src/lib.rs +++ b/frame/recovery/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/recovery/src/mock.rs b/frame/recovery/src/mock.rs index 778b966c76e8..577aa7dee711 100644 --- a/frame/recovery/src/mock.rs +++ b/frame/recovery/src/mock.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/recovery/src/tests.rs b/frame/recovery/src/tests.rs index fe971319bc97..7d1da6353a3a 100644 --- a/frame/recovery/src/tests.rs +++ b/frame/recovery/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/scheduler/src/benchmarking.rs b/frame/scheduler/src/benchmarking.rs index 22e3e4f4530b..9c97bc597338 100644 --- a/frame/scheduler/src/benchmarking.rs +++ b/frame/scheduler/src/benchmarking.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/scheduler/src/lib.rs b/frame/scheduler/src/lib.rs index b4ee2575e23d..4fd5d50a4de0 100644 --- a/frame/scheduler/src/lib.rs +++ b/frame/scheduler/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/scheduler/src/mock.rs b/frame/scheduler/src/mock.rs index 014f473302ab..869425c2ff53 100644 --- a/frame/scheduler/src/mock.rs +++ b/frame/scheduler/src/mock.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/scheduler/src/tests.rs b/frame/scheduler/src/tests.rs index 4774cfe38704..7681ede136d9 100644 --- a/frame/scheduler/src/tests.rs +++ b/frame/scheduler/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/scheduler/src/weights.rs b/frame/scheduler/src/weights.rs index 3c2ed47110b6..b8209c6031c8 100644 --- a/frame/scheduler/src/weights.rs +++ b/frame/scheduler/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/scored-pool/src/lib.rs b/frame/scored-pool/src/lib.rs index 7c90d163dee1..e95786e0c08f 100644 --- a/frame/scored-pool/src/lib.rs +++ b/frame/scored-pool/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/scored-pool/src/mock.rs b/frame/scored-pool/src/mock.rs index d5b3814fd97a..e349d7a1cc9a 100644 --- a/frame/scored-pool/src/mock.rs +++ b/frame/scored-pool/src/mock.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/scored-pool/src/tests.rs b/frame/scored-pool/src/tests.rs index 0503e308e76a..7b431160ddfe 100644 --- a/frame/scored-pool/src/tests.rs +++ b/frame/scored-pool/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/session/benchmarking/src/lib.rs b/frame/session/benchmarking/src/lib.rs index 4e0e51b76fe1..7beb4631e051 100644 --- a/frame/session/benchmarking/src/lib.rs +++ b/frame/session/benchmarking/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/session/benchmarking/src/mock.rs b/frame/session/benchmarking/src/mock.rs index 2560563511e6..1f0023660513 100644 --- a/frame/session/benchmarking/src/mock.rs +++ b/frame/session/benchmarking/src/mock.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/session/src/historical/mod.rs b/frame/session/src/historical/mod.rs index fa7cb9ee91c0..76cefeb7b053 100644 --- a/frame/session/src/historical/mod.rs +++ b/frame/session/src/historical/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/session/src/historical/offchain.rs b/frame/session/src/historical/offchain.rs index 0b292b57658d..95813d0a7027 100644 --- a/frame/session/src/historical/offchain.rs +++ b/frame/session/src/historical/offchain.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/session/src/historical/onchain.rs b/frame/session/src/historical/onchain.rs index c80817c28d72..c7160e2fcf53 100644 --- a/frame/session/src/historical/onchain.rs +++ b/frame/session/src/historical/onchain.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/session/src/historical/shared.rs b/frame/session/src/historical/shared.rs index 182e9ecacee1..9e19b9df6d78 100644 --- a/frame/session/src/historical/shared.rs +++ b/frame/session/src/historical/shared.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/session/src/lib.rs b/frame/session/src/lib.rs index e88f14306505..cae9a6159b16 100644 --- a/frame/session/src/lib.rs +++ b/frame/session/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/session/src/migrations/mod.rs b/frame/session/src/migrations/mod.rs index ccc5ee3c2e52..5981e87b677c 100644 --- a/frame/session/src/migrations/mod.rs +++ b/frame/session/src/migrations/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/session/src/migrations/v1.rs b/frame/session/src/migrations/v1.rs index 1de199fe7bed..2a69cd6d6a55 100644 --- a/frame/session/src/migrations/v1.rs +++ b/frame/session/src/migrations/v1.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/session/src/mock.rs b/frame/session/src/mock.rs index ec1f841f50b1..7c6cc02c9e78 100644 --- a/frame/session/src/mock.rs +++ b/frame/session/src/mock.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/session/src/tests.rs b/frame/session/src/tests.rs index 199076c88244..4f2108a9a438 100644 --- a/frame/session/src/tests.rs +++ b/frame/session/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/session/src/weights.rs b/frame/session/src/weights.rs index 64e7ac19ea7a..35c9cc7230fb 100644 --- a/frame/session/src/weights.rs +++ b/frame/session/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/society/src/lib.rs b/frame/society/src/lib.rs index 0b9512903267..abc90d5186f2 100644 --- a/frame/society/src/lib.rs +++ b/frame/society/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/society/src/mock.rs b/frame/society/src/mock.rs index fbf3b2fd757a..04ea705eed55 100644 --- a/frame/society/src/mock.rs +++ b/frame/society/src/mock.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/society/src/tests.rs b/frame/society/src/tests.rs index 9f8e32dea508..d394ddc9011b 100644 --- a/frame/society/src/tests.rs +++ b/frame/society/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/staking/reward-curve/src/lib.rs b/frame/staking/reward-curve/src/lib.rs index 06e35d11350e..9b2f3100b487 100644 --- a/frame/staking/reward-curve/src/lib.rs +++ b/frame/staking/reward-curve/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/staking/reward-curve/tests/test.rs b/frame/staking/reward-curve/tests/test.rs index fda7df145d0f..aa19b1782453 100644 --- a/frame/staking/reward-curve/tests/test.rs +++ b/frame/staking/reward-curve/tests/test.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/staking/reward-fn/src/lib.rs b/frame/staking/reward-fn/src/lib.rs index 25e52051effa..cb0b660bf544 100644 --- a/frame/staking/reward-fn/src/lib.rs +++ b/frame/staking/reward-fn/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/staking/reward-fn/tests/test.rs b/frame/staking/reward-fn/tests/test.rs index dc5b661c4098..a79137716fd2 100644 --- a/frame/staking/reward-fn/tests/test.rs +++ b/frame/staking/reward-fn/tests/test.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/staking/src/benchmarking.rs b/frame/staking/src/benchmarking.rs index cd9755366b0f..8328adc00a97 100644 --- a/frame/staking/src/benchmarking.rs +++ b/frame/staking/src/benchmarking.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/staking/src/inflation.rs b/frame/staking/src/inflation.rs index 8e44a8c5482e..c7519683c75d 100644 --- a/frame/staking/src/inflation.rs +++ b/frame/staking/src/inflation.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 7bc3ac8aa707..f6e052691754 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/staking/src/migrations.rs b/frame/staking/src/migrations.rs index 33f45d80870a..3991c4a66076 100644 --- a/frame/staking/src/migrations.rs +++ b/frame/staking/src/migrations.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index ea9b9f05f105..3bf46588044a 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 95af3d223e00..dcbba6363205 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index d03a6198c7cc..e45a21ab2503 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/staking/src/slashing.rs b/frame/staking/src/slashing.rs index acfb30fb8148..4fa7d347da70 100644 --- a/frame/staking/src/slashing.rs +++ b/frame/staking/src/slashing.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/staking/src/testing_utils.rs b/frame/staking/src/testing_utils.rs index 1c9163bd5640..8e6bd8846893 100644 --- a/frame/staking/src/testing_utils.rs +++ b/frame/staking/src/testing_utils.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 74d5de7bf449..7990245068f9 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/staking/src/weights.rs b/frame/staking/src/weights.rs index 0ca819898fbb..4f5af6fcd5f8 100644 --- a/frame/staking/src/weights.rs +++ b/frame/staking/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/sudo/src/lib.rs b/frame/sudo/src/lib.rs index b6255da1d1c4..d57c75f23f5a 100644 --- a/frame/sudo/src/lib.rs +++ b/frame/sudo/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/sudo/src/mock.rs b/frame/sudo/src/mock.rs index baea68788acf..e6af6978f8c8 100644 --- a/frame/sudo/src/mock.rs +++ b/frame/sudo/src/mock.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/sudo/src/tests.rs b/frame/sudo/src/tests.rs index 882187906167..84c8e0c5c254 100644 --- a/frame/sudo/src/tests.rs +++ b/frame/sudo/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/clone_no_bound.rs b/frame/support/procedural/src/clone_no_bound.rs index 747900fd023f..bd2741c0d47a 100644 --- a/frame/support/procedural/src/clone_no_bound.rs +++ b/frame/support/procedural/src/clone_no_bound.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/construct_runtime/expand/call.rs b/frame/support/procedural/src/construct_runtime/expand/call.rs index 5658ec045433..b09ef126ac6d 100644 --- a/frame/support/procedural/src/construct_runtime/expand/call.rs +++ b/frame/support/procedural/src/construct_runtime/expand/call.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/construct_runtime/expand/config.rs b/frame/support/procedural/src/construct_runtime/expand/config.rs index 5e1b9d94700e..79176fa7385e 100644 --- a/frame/support/procedural/src/construct_runtime/expand/config.rs +++ b/frame/support/procedural/src/construct_runtime/expand/config.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/construct_runtime/expand/event.rs b/frame/support/procedural/src/construct_runtime/expand/event.rs index 798646bf2733..ef071a9fc7ef 100644 --- a/frame/support/procedural/src/construct_runtime/expand/event.rs +++ b/frame/support/procedural/src/construct_runtime/expand/event.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/construct_runtime/expand/inherent.rs b/frame/support/procedural/src/construct_runtime/expand/inherent.rs index fd3041678268..0f0d53864324 100644 --- a/frame/support/procedural/src/construct_runtime/expand/inherent.rs +++ b/frame/support/procedural/src/construct_runtime/expand/inherent.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/construct_runtime/expand/metadata.rs b/frame/support/procedural/src/construct_runtime/expand/metadata.rs index c8445e0bbc25..6e2dd5fc002c 100644 --- a/frame/support/procedural/src/construct_runtime/expand/metadata.rs +++ b/frame/support/procedural/src/construct_runtime/expand/metadata.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/construct_runtime/expand/mod.rs b/frame/support/procedural/src/construct_runtime/expand/mod.rs index cf8b5eef8d10..6c92d2c3444e 100644 --- a/frame/support/procedural/src/construct_runtime/expand/mod.rs +++ b/frame/support/procedural/src/construct_runtime/expand/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/construct_runtime/expand/origin.rs b/frame/support/procedural/src/construct_runtime/expand/origin.rs index 5c2b4c9f93b0..077bef3744a5 100644 --- a/frame/support/procedural/src/construct_runtime/expand/origin.rs +++ b/frame/support/procedural/src/construct_runtime/expand/origin.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/construct_runtime/expand/unsigned.rs b/frame/support/procedural/src/construct_runtime/expand/unsigned.rs index d51792dd4a8d..c03067680209 100644 --- a/frame/support/procedural/src/construct_runtime/expand/unsigned.rs +++ b/frame/support/procedural/src/construct_runtime/expand/unsigned.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/construct_runtime/mod.rs b/frame/support/procedural/src/construct_runtime/mod.rs index b32ecf1bccd5..249eb072001c 100644 --- a/frame/support/procedural/src/construct_runtime/mod.rs +++ b/frame/support/procedural/src/construct_runtime/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/construct_runtime/parse.rs b/frame/support/procedural/src/construct_runtime/parse.rs index 44db2c10fff6..a2cda6a0777b 100644 --- a/frame/support/procedural/src/construct_runtime/parse.rs +++ b/frame/support/procedural/src/construct_runtime/parse.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/crate_version.rs b/frame/support/procedural/src/crate_version.rs index cfa35c6190e1..e2be6dd889db 100644 --- a/frame/support/procedural/src/crate_version.rs +++ b/frame/support/procedural/src/crate_version.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/debug_no_bound.rs b/frame/support/procedural/src/debug_no_bound.rs index acfd8d0cabc8..56168edb87e8 100644 --- a/frame/support/procedural/src/debug_no_bound.rs +++ b/frame/support/procedural/src/debug_no_bound.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/default_no_bound.rs b/frame/support/procedural/src/default_no_bound.rs index 38d6e19b1732..192be0786d96 100644 --- a/frame/support/procedural/src/default_no_bound.rs +++ b/frame/support/procedural/src/default_no_bound.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/key_prefix.rs b/frame/support/procedural/src/key_prefix.rs index 3f424e8b8b8d..05582f1297ee 100644 --- a/frame/support/procedural/src/key_prefix.rs +++ b/frame/support/procedural/src/key_prefix.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/lib.rs b/frame/support/procedural/src/lib.rs index d01bbf6ace52..e2233fff7228 100644 --- a/frame/support/procedural/src/lib.rs +++ b/frame/support/procedural/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/match_and_insert.rs b/frame/support/procedural/src/match_and_insert.rs index 4ffc596e6dca..79d1da7549c1 100644 --- a/frame/support/procedural/src/match_and_insert.rs +++ b/frame/support/procedural/src/match_and_insert.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/pallet/expand/call.rs b/frame/support/procedural/src/pallet/expand/call.rs index 8f7bcdccaf22..58c4804558b0 100644 --- a/frame/support/procedural/src/pallet/expand/call.rs +++ b/frame/support/procedural/src/pallet/expand/call.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/pallet/expand/config.rs b/frame/support/procedural/src/pallet/expand/config.rs index dad26ccad6dc..8ad34361d684 100644 --- a/frame/support/procedural/src/pallet/expand/config.rs +++ b/frame/support/procedural/src/pallet/expand/config.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/pallet/expand/constants.rs b/frame/support/procedural/src/pallet/expand/constants.rs index 0fe8e467c10d..3f853902010f 100644 --- a/frame/support/procedural/src/pallet/expand/constants.rs +++ b/frame/support/procedural/src/pallet/expand/constants.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/pallet/expand/error.rs b/frame/support/procedural/src/pallet/expand/error.rs index c6925db07a26..3e6247e77f8c 100644 --- a/frame/support/procedural/src/pallet/expand/error.rs +++ b/frame/support/procedural/src/pallet/expand/error.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/pallet/expand/event.rs b/frame/support/procedural/src/pallet/expand/event.rs index 69d6b461206c..79a7acaf66a5 100644 --- a/frame/support/procedural/src/pallet/expand/event.rs +++ b/frame/support/procedural/src/pallet/expand/event.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/pallet/expand/genesis_build.rs b/frame/support/procedural/src/pallet/expand/genesis_build.rs index 06acaf324254..53d0695e5f97 100644 --- a/frame/support/procedural/src/pallet/expand/genesis_build.rs +++ b/frame/support/procedural/src/pallet/expand/genesis_build.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/pallet/expand/genesis_config.rs b/frame/support/procedural/src/pallet/expand/genesis_config.rs index b2eb2166165c..18fa87a26253 100644 --- a/frame/support/procedural/src/pallet/expand/genesis_config.rs +++ b/frame/support/procedural/src/pallet/expand/genesis_config.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/pallet/expand/hooks.rs b/frame/support/procedural/src/pallet/expand/hooks.rs index e0b7e3669da4..7a1a94cf46d3 100644 --- a/frame/support/procedural/src/pallet/expand/hooks.rs +++ b/frame/support/procedural/src/pallet/expand/hooks.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/pallet/expand/inherent.rs b/frame/support/procedural/src/pallet/expand/inherent.rs index 185211ecd4df..71d95f958fcd 100644 --- a/frame/support/procedural/src/pallet/expand/inherent.rs +++ b/frame/support/procedural/src/pallet/expand/inherent.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/pallet/expand/instances.rs b/frame/support/procedural/src/pallet/expand/instances.rs index 2ecb5ec481ac..52dc88763550 100644 --- a/frame/support/procedural/src/pallet/expand/instances.rs +++ b/frame/support/procedural/src/pallet/expand/instances.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/pallet/expand/mod.rs b/frame/support/procedural/src/pallet/expand/mod.rs index 21acd3c0dd32..83bef7a97af1 100644 --- a/frame/support/procedural/src/pallet/expand/mod.rs +++ b/frame/support/procedural/src/pallet/expand/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/pallet/expand/origin.rs b/frame/support/procedural/src/pallet/expand/origin.rs index 987512f69a02..721fc781a907 100644 --- a/frame/support/procedural/src/pallet/expand/origin.rs +++ b/frame/support/procedural/src/pallet/expand/origin.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/pallet/expand/pallet_struct.rs b/frame/support/procedural/src/pallet/expand/pallet_struct.rs index 96dfdbb4b6f2..5ec10d733e5e 100644 --- a/frame/support/procedural/src/pallet/expand/pallet_struct.rs +++ b/frame/support/procedural/src/pallet/expand/pallet_struct.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/pallet/expand/storage.rs b/frame/support/procedural/src/pallet/expand/storage.rs index a4f030722f1c..9d936dd50344 100644 --- a/frame/support/procedural/src/pallet/expand/storage.rs +++ b/frame/support/procedural/src/pallet/expand/storage.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/pallet/expand/store_trait.rs b/frame/support/procedural/src/pallet/expand/store_trait.rs index 36cc08b732fe..4fb4f46143a1 100644 --- a/frame/support/procedural/src/pallet/expand/store_trait.rs +++ b/frame/support/procedural/src/pallet/expand/store_trait.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/pallet/expand/tt_default_parts.rs b/frame/support/procedural/src/pallet/expand/tt_default_parts.rs index cfab7982bfdc..173dcc0e2ac3 100644 --- a/frame/support/procedural/src/pallet/expand/tt_default_parts.rs +++ b/frame/support/procedural/src/pallet/expand/tt_default_parts.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/pallet/expand/type_value.rs b/frame/support/procedural/src/pallet/expand/type_value.rs index af4f0b3a6794..abe52459a791 100644 --- a/frame/support/procedural/src/pallet/expand/type_value.rs +++ b/frame/support/procedural/src/pallet/expand/type_value.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/pallet/expand/validate_unsigned.rs b/frame/support/procedural/src/pallet/expand/validate_unsigned.rs index 5f30d712e9a5..b49ba2b5b02e 100644 --- a/frame/support/procedural/src/pallet/expand/validate_unsigned.rs +++ b/frame/support/procedural/src/pallet/expand/validate_unsigned.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/pallet/mod.rs b/frame/support/procedural/src/pallet/mod.rs index 93797906d04d..ff9f12286774 100644 --- a/frame/support/procedural/src/pallet/mod.rs +++ b/frame/support/procedural/src/pallet/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/pallet/parse/call.rs b/frame/support/procedural/src/pallet/parse/call.rs index 0563568f3331..5468b1352197 100644 --- a/frame/support/procedural/src/pallet/parse/call.rs +++ b/frame/support/procedural/src/pallet/parse/call.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/pallet/parse/config.rs b/frame/support/procedural/src/pallet/parse/config.rs index 9e0a0fd52cbf..526c7eda2fd5 100644 --- a/frame/support/procedural/src/pallet/parse/config.rs +++ b/frame/support/procedural/src/pallet/parse/config.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/pallet/parse/error.rs b/frame/support/procedural/src/pallet/parse/error.rs index 9c9a95105c53..419770386bf6 100644 --- a/frame/support/procedural/src/pallet/parse/error.rs +++ b/frame/support/procedural/src/pallet/parse/error.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/pallet/parse/event.rs b/frame/support/procedural/src/pallet/parse/event.rs index 33de4aca8b59..e046cacac88e 100644 --- a/frame/support/procedural/src/pallet/parse/event.rs +++ b/frame/support/procedural/src/pallet/parse/event.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/pallet/parse/extra_constants.rs b/frame/support/procedural/src/pallet/parse/extra_constants.rs index a5f3c0a8c2da..7163b4b63208 100644 --- a/frame/support/procedural/src/pallet/parse/extra_constants.rs +++ b/frame/support/procedural/src/pallet/parse/extra_constants.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/pallet/parse/genesis_build.rs b/frame/support/procedural/src/pallet/parse/genesis_build.rs index 82e297b4e26e..79ee08306982 100644 --- a/frame/support/procedural/src/pallet/parse/genesis_build.rs +++ b/frame/support/procedural/src/pallet/parse/genesis_build.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/pallet/parse/genesis_config.rs b/frame/support/procedural/src/pallet/parse/genesis_config.rs index a0cf7de1a846..875d15bdc061 100644 --- a/frame/support/procedural/src/pallet/parse/genesis_config.rs +++ b/frame/support/procedural/src/pallet/parse/genesis_config.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/pallet/parse/helper.rs b/frame/support/procedural/src/pallet/parse/helper.rs index f5a7dc233cac..824407917358 100644 --- a/frame/support/procedural/src/pallet/parse/helper.rs +++ b/frame/support/procedural/src/pallet/parse/helper.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/pallet/parse/hooks.rs b/frame/support/procedural/src/pallet/parse/hooks.rs index 1dd86498f22d..cacc149e4866 100644 --- a/frame/support/procedural/src/pallet/parse/hooks.rs +++ b/frame/support/procedural/src/pallet/parse/hooks.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/pallet/parse/inherent.rs b/frame/support/procedural/src/pallet/parse/inherent.rs index de5ad8f795db..2833b3ef5c72 100644 --- a/frame/support/procedural/src/pallet/parse/inherent.rs +++ b/frame/support/procedural/src/pallet/parse/inherent.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/pallet/parse/mod.rs b/frame/support/procedural/src/pallet/parse/mod.rs index 96d4776e805b..a436f7e09c1d 100644 --- a/frame/support/procedural/src/pallet/parse/mod.rs +++ b/frame/support/procedural/src/pallet/parse/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/pallet/parse/origin.rs b/frame/support/procedural/src/pallet/parse/origin.rs index c4e1197ac511..2d729376f5de 100644 --- a/frame/support/procedural/src/pallet/parse/origin.rs +++ b/frame/support/procedural/src/pallet/parse/origin.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/pallet/parse/pallet_struct.rs b/frame/support/procedural/src/pallet/parse/pallet_struct.rs index c528faf669ee..19d2811687d2 100644 --- a/frame/support/procedural/src/pallet/parse/pallet_struct.rs +++ b/frame/support/procedural/src/pallet/parse/pallet_struct.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/pallet/parse/storage.rs b/frame/support/procedural/src/pallet/parse/storage.rs index cd29baf93d84..ca48c568e158 100644 --- a/frame/support/procedural/src/pallet/parse/storage.rs +++ b/frame/support/procedural/src/pallet/parse/storage.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/pallet/parse/type_value.rs b/frame/support/procedural/src/pallet/parse/type_value.rs index d6cd4d02df8b..a3d004cd8a53 100644 --- a/frame/support/procedural/src/pallet/parse/type_value.rs +++ b/frame/support/procedural/src/pallet/parse/type_value.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/pallet/parse/validate_unsigned.rs b/frame/support/procedural/src/pallet/parse/validate_unsigned.rs index 87e2a326f186..a58671d9762d 100644 --- a/frame/support/procedural/src/pallet/parse/validate_unsigned.rs +++ b/frame/support/procedural/src/pallet/parse/validate_unsigned.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/partial_eq_no_bound.rs b/frame/support/procedural/src/partial_eq_no_bound.rs index 3dbabf3f5d39..31930c0c3dae 100644 --- a/frame/support/procedural/src/partial_eq_no_bound.rs +++ b/frame/support/procedural/src/partial_eq_no_bound.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/storage/genesis_config/builder_def.rs b/frame/support/procedural/src/storage/genesis_config/builder_def.rs index 001cea0f2b78..975791881da2 100644 --- a/frame/support/procedural/src/storage/genesis_config/builder_def.rs +++ b/frame/support/procedural/src/storage/genesis_config/builder_def.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/storage/genesis_config/genesis_config_def.rs b/frame/support/procedural/src/storage/genesis_config/genesis_config_def.rs index fbdaab06b489..d24e50096f25 100644 --- a/frame/support/procedural/src/storage/genesis_config/genesis_config_def.rs +++ b/frame/support/procedural/src/storage/genesis_config/genesis_config_def.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/storage/genesis_config/mod.rs b/frame/support/procedural/src/storage/genesis_config/mod.rs index daff8848364e..d4348ee19171 100644 --- a/frame/support/procedural/src/storage/genesis_config/mod.rs +++ b/frame/support/procedural/src/storage/genesis_config/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/storage/getters.rs b/frame/support/procedural/src/storage/getters.rs index d877969232f8..9fe3734e6889 100644 --- a/frame/support/procedural/src/storage/getters.rs +++ b/frame/support/procedural/src/storage/getters.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/storage/instance_trait.rs b/frame/support/procedural/src/storage/instance_trait.rs index 00a73d6fbd6e..14e968112029 100644 --- a/frame/support/procedural/src/storage/instance_trait.rs +++ b/frame/support/procedural/src/storage/instance_trait.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/storage/metadata.rs b/frame/support/procedural/src/storage/metadata.rs index c49a0dafdf5d..d1879d1509f8 100644 --- a/frame/support/procedural/src/storage/metadata.rs +++ b/frame/support/procedural/src/storage/metadata.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/storage/mod.rs b/frame/support/procedural/src/storage/mod.rs index 27964d7012a2..b89e75633498 100644 --- a/frame/support/procedural/src/storage/mod.rs +++ b/frame/support/procedural/src/storage/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/storage/parse.rs b/frame/support/procedural/src/storage/parse.rs index 3a11846181a8..54026b7d78b1 100644 --- a/frame/support/procedural/src/storage/parse.rs +++ b/frame/support/procedural/src/storage/parse.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/storage/storage_info.rs b/frame/support/procedural/src/storage/storage_info.rs index 4b1d3347b4a4..77515fa739b2 100644 --- a/frame/support/procedural/src/storage/storage_info.rs +++ b/frame/support/procedural/src/storage/storage_info.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/storage/storage_struct.rs b/frame/support/procedural/src/storage/storage_struct.rs index b318225681c1..649a41bab5ec 100644 --- a/frame/support/procedural/src/storage/storage_struct.rs +++ b/frame/support/procedural/src/storage/storage_struct.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/storage/store_trait.rs b/frame/support/procedural/src/storage/store_trait.rs index 5794c72d22c8..daf933b3b770 100644 --- a/frame/support/procedural/src/storage/store_trait.rs +++ b/frame/support/procedural/src/storage/store_trait.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/src/transactional.rs b/frame/support/procedural/src/transactional.rs index 403f1cd02bac..66a8d083fb56 100644 --- a/frame/support/procedural/src/transactional.rs +++ b/frame/support/procedural/src/transactional.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/tools/derive/src/lib.rs b/frame/support/procedural/tools/derive/src/lib.rs index 9ce88e7c4793..392a43834201 100644 --- a/frame/support/procedural/tools/derive/src/lib.rs +++ b/frame/support/procedural/tools/derive/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/tools/src/lib.rs b/frame/support/procedural/tools/src/lib.rs index d7aba4c7cbf1..3abde5957411 100644 --- a/frame/support/procedural/tools/src/lib.rs +++ b/frame/support/procedural/tools/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/procedural/tools/src/syn_ext.rs b/frame/support/procedural/tools/src/syn_ext.rs index a9e9ef573985..25c98faaf388 100644 --- a/frame/support/procedural/tools/src/syn_ext.rs +++ b/frame/support/procedural/tools/src/syn_ext.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/dispatch.rs b/frame/support/src/dispatch.rs index a492bc12f6a3..765fb5d9d7c3 100644 --- a/frame/support/src/dispatch.rs +++ b/frame/support/src/dispatch.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/error.rs b/frame/support/src/error.rs index 836428c6bc7d..abac4a53269a 100644 --- a/frame/support/src/error.rs +++ b/frame/support/src/error.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/event.rs b/frame/support/src/event.rs index 3d042a3122db..dc45f2bf69d9 100644 --- a/frame/support/src/event.rs +++ b/frame/support/src/event.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/hash.rs b/frame/support/src/hash.rs index f943bcf32309..9ce0968351a4 100644 --- a/frame/support/src/hash.rs +++ b/frame/support/src/hash.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/inherent.rs b/frame/support/src/inherent.rs index 2125f3e7f50a..59d55b1df3f3 100644 --- a/frame/support/src/inherent.rs +++ b/frame/support/src/inherent.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/instances.rs b/frame/support/src/instances.rs index 9908d16076a0..81139f867181 100644 --- a/frame/support/src/instances.rs +++ b/frame/support/src/instances.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/lib.rs b/frame/support/src/lib.rs index 2a23d203adf6..64bca7262829 100644 --- a/frame/support/src/lib.rs +++ b/frame/support/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/migrations.rs b/frame/support/src/migrations.rs index c61cbac62a16..05833e0515c0 100644 --- a/frame/support/src/migrations.rs +++ b/frame/support/src/migrations.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/storage/bounded_btree_map.rs b/frame/support/src/storage/bounded_btree_map.rs index 224ff496a990..201015e3a622 100644 --- a/frame/support/src/storage/bounded_btree_map.rs +++ b/frame/support/src/storage/bounded_btree_map.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/storage/bounded_btree_set.rs b/frame/support/src/storage/bounded_btree_set.rs index af292aa1c8ff..f51439f04d13 100644 --- a/frame/support/src/storage/bounded_btree_set.rs +++ b/frame/support/src/storage/bounded_btree_set.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/storage/bounded_vec.rs b/frame/support/src/storage/bounded_vec.rs index decf2cb341bf..5ea7a62c79c2 100644 --- a/frame/support/src/storage/bounded_vec.rs +++ b/frame/support/src/storage/bounded_vec.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/storage/child.rs b/frame/support/src/storage/child.rs index 19b00d105136..a0a673d4b041 100644 --- a/frame/support/src/storage/child.rs +++ b/frame/support/src/storage/child.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/storage/generator/double_map.rs b/frame/support/src/storage/generator/double_map.rs index 636a10feb1ab..d63dda7d5b32 100644 --- a/frame/support/src/storage/generator/double_map.rs +++ b/frame/support/src/storage/generator/double_map.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/storage/generator/map.rs b/frame/support/src/storage/generator/map.rs index 1a4225173c4a..4157edefeac4 100644 --- a/frame/support/src/storage/generator/map.rs +++ b/frame/support/src/storage/generator/map.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/storage/generator/mod.rs b/frame/support/src/storage/generator/mod.rs index 576bada2e262..ca893f44b3cb 100644 --- a/frame/support/src/storage/generator/mod.rs +++ b/frame/support/src/storage/generator/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/storage/generator/nmap.rs b/frame/support/src/storage/generator/nmap.rs index 4845673d3d8c..1ad308bb22c7 100755 --- a/frame/support/src/storage/generator/nmap.rs +++ b/frame/support/src/storage/generator/nmap.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/storage/generator/value.rs b/frame/support/src/storage/generator/value.rs index 3486eaa005c0..55b3487b1324 100644 --- a/frame/support/src/storage/generator/value.rs +++ b/frame/support/src/storage/generator/value.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/storage/hashed.rs b/frame/support/src/storage/hashed.rs index 241caff809b3..a07db73c947d 100644 --- a/frame/support/src/storage/hashed.rs +++ b/frame/support/src/storage/hashed.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/storage/migration.rs b/frame/support/src/storage/migration.rs index 59422a282aab..b2339efd0d20 100644 --- a/frame/support/src/storage/migration.rs +++ b/frame/support/src/storage/migration.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/storage/mod.rs b/frame/support/src/storage/mod.rs index 3cfe2bfaa577..d79ddf09b7cc 100644 --- a/frame/support/src/storage/mod.rs +++ b/frame/support/src/storage/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/storage/types/counted_map.rs b/frame/support/src/storage/types/counted_map.rs index c4230cafc40b..99d645fba329 100644 --- a/frame/support/src/storage/types/counted_map.rs +++ b/frame/support/src/storage/types/counted_map.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/storage/types/double_map.rs b/frame/support/src/storage/types/double_map.rs index d3595814d04b..1a4d979d98f8 100644 --- a/frame/support/src/storage/types/double_map.rs +++ b/frame/support/src/storage/types/double_map.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/storage/types/key.rs b/frame/support/src/storage/types/key.rs index da265fd6e6c8..182ddbedd9b8 100755 --- a/frame/support/src/storage/types/key.rs +++ b/frame/support/src/storage/types/key.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/storage/types/map.rs b/frame/support/src/storage/types/map.rs index 6532d47cfec6..e769daa49036 100644 --- a/frame/support/src/storage/types/map.rs +++ b/frame/support/src/storage/types/map.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/storage/types/mod.rs b/frame/support/src/storage/types/mod.rs index bcab996f6832..0706e9fb377e 100644 --- a/frame/support/src/storage/types/mod.rs +++ b/frame/support/src/storage/types/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/storage/types/nmap.rs b/frame/support/src/storage/types/nmap.rs index 96d6f383ae11..30e6fb563788 100755 --- a/frame/support/src/storage/types/nmap.rs +++ b/frame/support/src/storage/types/nmap.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/storage/types/value.rs b/frame/support/src/storage/types/value.rs index c5e7173bd0af..a368988f378b 100644 --- a/frame/support/src/storage/types/value.rs +++ b/frame/support/src/storage/types/value.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/storage/unhashed.rs b/frame/support/src/storage/unhashed.rs index f700771b2d5c..5e0b527acd13 100644 --- a/frame/support/src/storage/unhashed.rs +++ b/frame/support/src/storage/unhashed.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/storage/weak_bounded_vec.rs b/frame/support/src/storage/weak_bounded_vec.rs index 641b62305393..db62d7303539 100644 --- a/frame/support/src/storage/weak_bounded_vec.rs +++ b/frame/support/src/storage/weak_bounded_vec.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/traits.rs b/frame/support/src/traits.rs index 01817723e94e..d0719063ef3e 100644 --- a/frame/support/src/traits.rs +++ b/frame/support/src/traits.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/traits/dispatch.rs b/frame/support/src/traits/dispatch.rs index d7605593cd60..afac31e662e3 100644 --- a/frame/support/src/traits/dispatch.rs +++ b/frame/support/src/traits/dispatch.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/traits/filter.rs b/frame/support/src/traits/filter.rs index c67ffc3c3a11..95e5954184b4 100644 --- a/frame/support/src/traits/filter.rs +++ b/frame/support/src/traits/filter.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/traits/hooks.rs b/frame/support/src/traits/hooks.rs index 2a8b0a156247..ffb8dfb821ad 100644 --- a/frame/support/src/traits/hooks.rs +++ b/frame/support/src/traits/hooks.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/traits/members.rs b/frame/support/src/traits/members.rs index 06a4c759c46d..ba72b4819933 100644 --- a/frame/support/src/traits/members.rs +++ b/frame/support/src/traits/members.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/traits/metadata.rs b/frame/support/src/traits/metadata.rs index 50fb53fc5706..c76c53dbe8b2 100644 --- a/frame/support/src/traits/metadata.rs +++ b/frame/support/src/traits/metadata.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/traits/misc.rs b/frame/support/src/traits/misc.rs index 8bab1581a697..c68561367e3d 100644 --- a/frame/support/src/traits/misc.rs +++ b/frame/support/src/traits/misc.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/traits/randomness.rs b/frame/support/src/traits/randomness.rs index 865893f99b39..d68b95b1dfcf 100644 --- a/frame/support/src/traits/randomness.rs +++ b/frame/support/src/traits/randomness.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/traits/schedule.rs b/frame/support/src/traits/schedule.rs index 1cedb96cb14b..5ba233c29be1 100644 --- a/frame/support/src/traits/schedule.rs +++ b/frame/support/src/traits/schedule.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/traits/storage.rs b/frame/support/src/traits/storage.rs index 9a88a3ed4404..e484140cc2fd 100644 --- a/frame/support/src/traits/storage.rs +++ b/frame/support/src/traits/storage.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/traits/stored_map.rs b/frame/support/src/traits/stored_map.rs index 715a5211be43..5173eaeb5def 100644 --- a/frame/support/src/traits/stored_map.rs +++ b/frame/support/src/traits/stored_map.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/traits/tokens.rs b/frame/support/src/traits/tokens.rs index 91a9382d07fc..92f8ce12d912 100644 --- a/frame/support/src/traits/tokens.rs +++ b/frame/support/src/traits/tokens.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/traits/tokens/currency.rs b/frame/support/src/traits/tokens/currency.rs index 9fdb08b8bd6e..d5756ee84c47 100644 --- a/frame/support/src/traits/tokens/currency.rs +++ b/frame/support/src/traits/tokens/currency.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/traits/tokens/currency/lockable.rs b/frame/support/src/traits/tokens/currency/lockable.rs index 26463864a647..a10edd6e3e87 100644 --- a/frame/support/src/traits/tokens/currency/lockable.rs +++ b/frame/support/src/traits/tokens/currency/lockable.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/traits/tokens/currency/reservable.rs b/frame/support/src/traits/tokens/currency/reservable.rs index e2313a9d2550..35455aaecdb4 100644 --- a/frame/support/src/traits/tokens/currency/reservable.rs +++ b/frame/support/src/traits/tokens/currency/reservable.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/traits/tokens/fungible.rs b/frame/support/src/traits/tokens/fungible.rs index b033236d447b..712103a1e883 100644 --- a/frame/support/src/traits/tokens/fungible.rs +++ b/frame/support/src/traits/tokens/fungible.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/traits/tokens/fungible/balanced.rs b/frame/support/src/traits/tokens/fungible/balanced.rs index 7b33a595a1b5..196f3a35754a 100644 --- a/frame/support/src/traits/tokens/fungible/balanced.rs +++ b/frame/support/src/traits/tokens/fungible/balanced.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/traits/tokens/fungible/imbalance.rs b/frame/support/src/traits/tokens/fungible/imbalance.rs index 362e0c126d99..ca911cf12d44 100644 --- a/frame/support/src/traits/tokens/fungible/imbalance.rs +++ b/frame/support/src/traits/tokens/fungible/imbalance.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/traits/tokens/fungibles.rs b/frame/support/src/traits/tokens/fungibles.rs index b164a9967165..8e68b36d60c7 100644 --- a/frame/support/src/traits/tokens/fungibles.rs +++ b/frame/support/src/traits/tokens/fungibles.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/traits/tokens/fungibles/approvals.rs b/frame/support/src/traits/tokens/fungibles/approvals.rs index 06e81b8591a8..7a08f11cf042 100644 --- a/frame/support/src/traits/tokens/fungibles/approvals.rs +++ b/frame/support/src/traits/tokens/fungibles/approvals.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/traits/tokens/fungibles/balanced.rs b/frame/support/src/traits/tokens/fungibles/balanced.rs index 40a65305b87d..e07d45cc4717 100644 --- a/frame/support/src/traits/tokens/fungibles/balanced.rs +++ b/frame/support/src/traits/tokens/fungibles/balanced.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/traits/tokens/fungibles/imbalance.rs b/frame/support/src/traits/tokens/fungibles/imbalance.rs index c44c47164648..61bd4a43064e 100644 --- a/frame/support/src/traits/tokens/fungibles/imbalance.rs +++ b/frame/support/src/traits/tokens/fungibles/imbalance.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/traits/tokens/fungibles/metadata.rs b/frame/support/src/traits/tokens/fungibles/metadata.rs index 08bf5c4710a7..b736ab1489f5 100644 --- a/frame/support/src/traits/tokens/fungibles/metadata.rs +++ b/frame/support/src/traits/tokens/fungibles/metadata.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/traits/tokens/imbalance.rs b/frame/support/src/traits/tokens/imbalance.rs index eaa18be58f61..d721beb41494 100644 --- a/frame/support/src/traits/tokens/imbalance.rs +++ b/frame/support/src/traits/tokens/imbalance.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/traits/tokens/imbalance/on_unbalanced.rs b/frame/support/src/traits/tokens/imbalance/on_unbalanced.rs index bc7df0e2acf3..0125254cefc8 100644 --- a/frame/support/src/traits/tokens/imbalance/on_unbalanced.rs +++ b/frame/support/src/traits/tokens/imbalance/on_unbalanced.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/traits/tokens/imbalance/signed_imbalance.rs b/frame/support/src/traits/tokens/imbalance/signed_imbalance.rs index 3e76d069f50e..f969a4363405 100644 --- a/frame/support/src/traits/tokens/imbalance/signed_imbalance.rs +++ b/frame/support/src/traits/tokens/imbalance/signed_imbalance.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/traits/tokens/imbalance/split_two_ways.rs b/frame/support/src/traits/tokens/imbalance/split_two_ways.rs index 882b43c2e914..a5e42451d82e 100644 --- a/frame/support/src/traits/tokens/imbalance/split_two_ways.rs +++ b/frame/support/src/traits/tokens/imbalance/split_two_ways.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/traits/tokens/misc.rs b/frame/support/src/traits/tokens/misc.rs index 100138171abe..f30fd02bfe83 100644 --- a/frame/support/src/traits/tokens/misc.rs +++ b/frame/support/src/traits/tokens/misc.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/traits/tokens/nonfungible.rs b/frame/support/src/traits/tokens/nonfungible.rs index 821884f6e390..08e9a3a18a4b 100644 --- a/frame/support/src/traits/tokens/nonfungible.rs +++ b/frame/support/src/traits/tokens/nonfungible.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/traits/tokens/nonfungibles.rs b/frame/support/src/traits/tokens/nonfungibles.rs index b5a14761064f..1172fb602283 100644 --- a/frame/support/src/traits/tokens/nonfungibles.rs +++ b/frame/support/src/traits/tokens/nonfungibles.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/traits/validation.rs b/frame/support/src/traits/validation.rs index e5c81a149e4d..135dd927acbb 100644 --- a/frame/support/src/traits/validation.rs +++ b/frame/support/src/traits/validation.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/traits/voting.rs b/frame/support/src/traits/voting.rs index 62c6217ad59b..719ad7f0f71d 100644 --- a/frame/support/src/traits/voting.rs +++ b/frame/support/src/traits/voting.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/src/weights.rs b/frame/support/src/weights.rs index ec5f37823ad4..65087c85d326 100644 --- a/frame/support/src/weights.rs +++ b/frame/support/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/test/compile_pass/src/lib.rs b/frame/support/test/compile_pass/src/lib.rs index 47b81e102069..0c955c749613 100644 --- a/frame/support/test/compile_pass/src/lib.rs +++ b/frame/support/test/compile_pass/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/frame/support/test/pallet/src/lib.rs b/frame/support/test/pallet/src/lib.rs index f9f94b06a0a5..bd181ea5b81b 100644 --- a/frame/support/test/pallet/src/lib.rs +++ b/frame/support/test/pallet/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/test/src/lib.rs b/frame/support/test/src/lib.rs index 073f8c9c1935..dd3fbd1f3020 100644 --- a/frame/support/test/src/lib.rs +++ b/frame/support/test/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/test/src/pallet_version.rs b/frame/support/test/src/pallet_version.rs index bdea3859d65c..096289116c41 100644 --- a/frame/support/test/src/pallet_version.rs +++ b/frame/support/test/src/pallet_version.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/test/tests/construct_runtime.rs b/frame/support/test/tests/construct_runtime.rs index b2717b0f095c..267d560edf92 100644 --- a/frame/support/test/tests/construct_runtime.rs +++ b/frame/support/test/tests/construct_runtime.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/test/tests/construct_runtime_ui.rs b/frame/support/test/tests/construct_runtime_ui.rs index ee475e37605e..66636416c1f5 100644 --- a/frame/support/test/tests/construct_runtime_ui.rs +++ b/frame/support/test/tests/construct_runtime_ui.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/test/tests/decl_module_ui.rs b/frame/support/test/tests/decl_module_ui.rs index e84025b9f256..829850ec2d47 100644 --- a/frame/support/test/tests/decl_module_ui.rs +++ b/frame/support/test/tests/decl_module_ui.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/test/tests/decl_storage.rs b/frame/support/test/tests/decl_storage.rs index 347a3130daa7..be5d70be17f6 100644 --- a/frame/support/test/tests/decl_storage.rs +++ b/frame/support/test/tests/decl_storage.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/test/tests/decl_storage_ui.rs b/frame/support/test/tests/decl_storage_ui.rs index 400ddfc0f94f..d4db02ad19a0 100644 --- a/frame/support/test/tests/decl_storage_ui.rs +++ b/frame/support/test/tests/decl_storage_ui.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/test/tests/decl_storage_ui/config_duplicate.rs b/frame/support/test/tests/decl_storage_ui/config_duplicate.rs index 17f80c8c8475..db2cdbdc6549 100644 --- a/frame/support/test/tests/decl_storage_ui/config_duplicate.rs +++ b/frame/support/test/tests/decl_storage_ui/config_duplicate.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/test/tests/decl_storage_ui/config_get_duplicate.rs b/frame/support/test/tests/decl_storage_ui/config_get_duplicate.rs index fec6aeb64cec..b804bf898038 100644 --- a/frame/support/test/tests/decl_storage_ui/config_get_duplicate.rs +++ b/frame/support/test/tests/decl_storage_ui/config_get_duplicate.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/test/tests/decl_storage_ui/get_duplicate.rs b/frame/support/test/tests/decl_storage_ui/get_duplicate.rs index 13c57a638bb1..bc03ff6b4a4f 100644 --- a/frame/support/test/tests/decl_storage_ui/get_duplicate.rs +++ b/frame/support/test/tests/decl_storage_ui/get_duplicate.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/test/tests/derive_no_bound.rs b/frame/support/test/tests/derive_no_bound.rs index 1827844664fa..e1cf539f2ac5 100644 --- a/frame/support/test/tests/derive_no_bound.rs +++ b/frame/support/test/tests/derive_no_bound.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/test/tests/derive_no_bound_ui.rs b/frame/support/test/tests/derive_no_bound_ui.rs index 22c116931a47..91e530d1d8da 100644 --- a/frame/support/test/tests/derive_no_bound_ui.rs +++ b/frame/support/test/tests/derive_no_bound_ui.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/test/tests/final_keys.rs b/frame/support/test/tests/final_keys.rs index e89f961d893f..c1723c6ad7a1 100644 --- a/frame/support/test/tests/final_keys.rs +++ b/frame/support/test/tests/final_keys.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/test/tests/genesisconfig.rs b/frame/support/test/tests/genesisconfig.rs index d488e8bfbfaf..7895e863fd82 100644 --- a/frame/support/test/tests/genesisconfig.rs +++ b/frame/support/test/tests/genesisconfig.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/test/tests/instance.rs b/frame/support/test/tests/instance.rs index 5677b9ac14da..2fe8d0e0f22f 100644 --- a/frame/support/test/tests/instance.rs +++ b/frame/support/test/tests/instance.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/test/tests/issue2219.rs b/frame/support/test/tests/issue2219.rs index 68ad2a50a21b..196068ac2fa4 100644 --- a/frame/support/test/tests/issue2219.rs +++ b/frame/support/test/tests/issue2219.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/test/tests/pallet.rs b/frame/support/test/tests/pallet.rs index e57c3466e7ef..1e923a6fdd6e 100644 --- a/frame/support/test/tests/pallet.rs +++ b/frame/support/test/tests/pallet.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/test/tests/pallet_compatibility.rs b/frame/support/test/tests/pallet_compatibility.rs index b1ed08051f24..dc76f1fcbf03 100644 --- a/frame/support/test/tests/pallet_compatibility.rs +++ b/frame/support/test/tests/pallet_compatibility.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/test/tests/pallet_compatibility_instance.rs b/frame/support/test/tests/pallet_compatibility_instance.rs index 81e16ee3624f..80ab3c2267fd 100644 --- a/frame/support/test/tests/pallet_compatibility_instance.rs +++ b/frame/support/test/tests/pallet_compatibility_instance.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/test/tests/pallet_instance.rs b/frame/support/test/tests/pallet_instance.rs index 740bfe51d439..4a8636919b58 100644 --- a/frame/support/test/tests/pallet_instance.rs +++ b/frame/support/test/tests/pallet_instance.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/test/tests/pallet_ui.rs b/frame/support/test/tests/pallet_ui.rs index 6f56c1efd6d7..a77d76deff8d 100644 --- a/frame/support/test/tests/pallet_ui.rs +++ b/frame/support/test/tests/pallet_ui.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/test/tests/pallet_with_name_trait_is_valid.rs b/frame/support/test/tests/pallet_with_name_trait_is_valid.rs index 128960fdb1c3..7ed845466832 100644 --- a/frame/support/test/tests/pallet_with_name_trait_is_valid.rs +++ b/frame/support/test/tests/pallet_with_name_trait_is_valid.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/test/tests/storage_transaction.rs b/frame/support/test/tests/storage_transaction.rs index 4e97a87377b1..0f1c3a2e0c53 100644 --- a/frame/support/test/tests/storage_transaction.rs +++ b/frame/support/test/tests/storage_transaction.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/support/test/tests/system.rs b/frame/support/test/tests/system.rs index 9def12131dd1..0083835640cb 100644 --- a/frame/support/test/tests/system.rs +++ b/frame/support/test/tests/system.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/system/benches/bench.rs b/frame/system/benches/bench.rs index f1d819cb6525..0bc34fcbc5be 100644 --- a/frame/system/benches/bench.rs +++ b/frame/system/benches/bench.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/system/benchmarking/src/lib.rs b/frame/system/benchmarking/src/lib.rs index eddf78ce6b25..367e6c73c413 100644 --- a/frame/system/benchmarking/src/lib.rs +++ b/frame/system/benchmarking/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/system/benchmarking/src/mock.rs b/frame/system/benchmarking/src/mock.rs index ff00b76c45fd..08b043ae6274 100644 --- a/frame/system/benchmarking/src/mock.rs +++ b/frame/system/benchmarking/src/mock.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/system/rpc/runtime-api/src/lib.rs b/frame/system/rpc/runtime-api/src/lib.rs index 319883c36d74..6e01bdae2d15 100644 --- a/frame/system/rpc/runtime-api/src/lib.rs +++ b/frame/system/rpc/runtime-api/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/system/src/extensions/check_genesis.rs b/frame/system/src/extensions/check_genesis.rs index c758f9b6cb6e..4b52691a6d32 100644 --- a/frame/system/src/extensions/check_genesis.rs +++ b/frame/system/src/extensions/check_genesis.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/system/src/extensions/check_mortality.rs b/frame/system/src/extensions/check_mortality.rs index 140a06298df3..ed11c3759836 100644 --- a/frame/system/src/extensions/check_mortality.rs +++ b/frame/system/src/extensions/check_mortality.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/system/src/extensions/check_non_zero_sender.rs b/frame/system/src/extensions/check_non_zero_sender.rs index 349bc0bede0d..5910a865a776 100644 --- a/frame/system/src/extensions/check_non_zero_sender.rs +++ b/frame/system/src/extensions/check_non_zero_sender.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/system/src/extensions/check_nonce.rs b/frame/system/src/extensions/check_nonce.rs index 3c6f9a1b4dbd..476aa2fb7478 100644 --- a/frame/system/src/extensions/check_nonce.rs +++ b/frame/system/src/extensions/check_nonce.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/system/src/extensions/check_spec_version.rs b/frame/system/src/extensions/check_spec_version.rs index 1e1a31d4d870..dce70a940765 100644 --- a/frame/system/src/extensions/check_spec_version.rs +++ b/frame/system/src/extensions/check_spec_version.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/system/src/extensions/check_tx_version.rs b/frame/system/src/extensions/check_tx_version.rs index e1e7b070e831..69060729cccc 100644 --- a/frame/system/src/extensions/check_tx_version.rs +++ b/frame/system/src/extensions/check_tx_version.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/system/src/extensions/check_weight.rs b/frame/system/src/extensions/check_weight.rs index 8f83b7594cb5..774139054d08 100644 --- a/frame/system/src/extensions/check_weight.rs +++ b/frame/system/src/extensions/check_weight.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/system/src/extensions/mod.rs b/frame/system/src/extensions/mod.rs index 7eaff34c1d7f..9ba73c5f4d4e 100644 --- a/frame/system/src/extensions/mod.rs +++ b/frame/system/src/extensions/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/system/src/lib.rs b/frame/system/src/lib.rs index 726837bf8267..80d293491469 100644 --- a/frame/system/src/lib.rs +++ b/frame/system/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/system/src/limits.rs b/frame/system/src/limits.rs index 687fb6f3dd36..4942a5dace7d 100644 --- a/frame/system/src/limits.rs +++ b/frame/system/src/limits.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/system/src/migrations/mod.rs b/frame/system/src/migrations/mod.rs index 03547d200f4a..358ba55b7c81 100644 --- a/frame/system/src/migrations/mod.rs +++ b/frame/system/src/migrations/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/system/src/mock.rs b/frame/system/src/mock.rs index 5d10962a8f40..f3f542aa83a9 100644 --- a/frame/system/src/mock.rs +++ b/frame/system/src/mock.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/system/src/mocking.rs b/frame/system/src/mocking.rs index 7e6026b72618..ccb63f9bb236 100644 --- a/frame/system/src/mocking.rs +++ b/frame/system/src/mocking.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/system/src/offchain.rs b/frame/system/src/offchain.rs index c4986e67319f..bf52ab8e3791 100644 --- a/frame/system/src/offchain.rs +++ b/frame/system/src/offchain.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/system/src/tests.rs b/frame/system/src/tests.rs index de3158562f49..411925c70275 100644 --- a/frame/system/src/tests.rs +++ b/frame/system/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/system/src/weights.rs b/frame/system/src/weights.rs index d05ad2a867b5..ff6900032d96 100644 --- a/frame/system/src/weights.rs +++ b/frame/system/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/timestamp/src/benchmarking.rs b/frame/timestamp/src/benchmarking.rs index 98e05439df72..0da71dbdd1a5 100644 --- a/frame/timestamp/src/benchmarking.rs +++ b/frame/timestamp/src/benchmarking.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/timestamp/src/lib.rs b/frame/timestamp/src/lib.rs index 0d2c3f385d17..a0b9babcd984 100644 --- a/frame/timestamp/src/lib.rs +++ b/frame/timestamp/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/timestamp/src/weights.rs b/frame/timestamp/src/weights.rs index b4e7370ee761..fb452ebe3595 100644 --- a/frame/timestamp/src/weights.rs +++ b/frame/timestamp/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/tips/src/benchmarking.rs b/frame/tips/src/benchmarking.rs index 5b6f11de77dd..7abee6192f2e 100644 --- a/frame/tips/src/benchmarking.rs +++ b/frame/tips/src/benchmarking.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/tips/src/lib.rs b/frame/tips/src/lib.rs index 5edb5f042a61..7761800638d3 100644 --- a/frame/tips/src/lib.rs +++ b/frame/tips/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/tips/src/migrations/mod.rs b/frame/tips/src/migrations/mod.rs index 81139120da1c..719bb2f86fdd 100644 --- a/frame/tips/src/migrations/mod.rs +++ b/frame/tips/src/migrations/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/tips/src/migrations/v4.rs b/frame/tips/src/migrations/v4.rs index 69df1d08d2c8..34f7a43ec12d 100644 --- a/frame/tips/src/migrations/v4.rs +++ b/frame/tips/src/migrations/v4.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/tips/src/tests.rs b/frame/tips/src/tests.rs index 5bab523b0393..f9ad431c3948 100644 --- a/frame/tips/src/tests.rs +++ b/frame/tips/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/tips/src/weights.rs b/frame/tips/src/weights.rs index 3376afb06617..29e85ccad851 100644 --- a/frame/tips/src/weights.rs +++ b/frame/tips/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/transaction-payment/asset-tx-payment/src/lib.rs b/frame/transaction-payment/asset-tx-payment/src/lib.rs index be16fa45f953..83801c44d357 100644 --- a/frame/transaction-payment/asset-tx-payment/src/lib.rs +++ b/frame/transaction-payment/asset-tx-payment/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/transaction-payment/asset-tx-payment/src/payment.rs b/frame/transaction-payment/asset-tx-payment/src/payment.rs index 09482f96490c..9eafc43fc256 100644 --- a/frame/transaction-payment/asset-tx-payment/src/payment.rs +++ b/frame/transaction-payment/asset-tx-payment/src/payment.rs @@ -1,4 +1,4 @@ -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/transaction-payment/asset-tx-payment/src/tests.rs b/frame/transaction-payment/asset-tx-payment/src/tests.rs index 6292829d2148..f2a1ad140657 100644 --- a/frame/transaction-payment/asset-tx-payment/src/tests.rs +++ b/frame/transaction-payment/asset-tx-payment/src/tests.rs @@ -1,4 +1,4 @@ -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/transaction-payment/rpc/runtime-api/src/lib.rs b/frame/transaction-payment/rpc/runtime-api/src/lib.rs index 696550d3ef04..5a0c70138db2 100644 --- a/frame/transaction-payment/rpc/runtime-api/src/lib.rs +++ b/frame/transaction-payment/rpc/runtime-api/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/transaction-payment/rpc/src/lib.rs b/frame/transaction-payment/rpc/src/lib.rs index 78230ee6e468..b2ff31618f78 100644 --- a/frame/transaction-payment/rpc/src/lib.rs +++ b/frame/transaction-payment/rpc/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/transaction-payment/src/lib.rs b/frame/transaction-payment/src/lib.rs index fa8b0e9be0c1..8bda316c501a 100644 --- a/frame/transaction-payment/src/lib.rs +++ b/frame/transaction-payment/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/transaction-payment/src/types.rs b/frame/transaction-payment/src/types.rs index 3ce5bcf890bd..3faebfed4894 100644 --- a/frame/transaction-payment/src/types.rs +++ b/frame/transaction-payment/src/types.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/transaction-storage/src/benchmarking.rs b/frame/transaction-storage/src/benchmarking.rs index b03c75148fa1..285b5cba7ad2 100644 --- a/frame/transaction-storage/src/benchmarking.rs +++ b/frame/transaction-storage/src/benchmarking.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/transaction-storage/src/lib.rs b/frame/transaction-storage/src/lib.rs index 2cd47b1cd0db..23cc9ee0a238 100644 --- a/frame/transaction-storage/src/lib.rs +++ b/frame/transaction-storage/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/transaction-storage/src/mock.rs b/frame/transaction-storage/src/mock.rs index 6356312ca500..753d4baaf00e 100644 --- a/frame/transaction-storage/src/mock.rs +++ b/frame/transaction-storage/src/mock.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/transaction-storage/src/tests.rs b/frame/transaction-storage/src/tests.rs index c443f51ffb50..8825890ae67a 100644 --- a/frame/transaction-storage/src/tests.rs +++ b/frame/transaction-storage/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/transaction-storage/src/weights.rs b/frame/transaction-storage/src/weights.rs index 104b18d3f92c..ffea996b83d9 100644 --- a/frame/transaction-storage/src/weights.rs +++ b/frame/transaction-storage/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/treasury/src/benchmarking.rs b/frame/treasury/src/benchmarking.rs index 8570b0efdb94..a0dd58ee3d42 100644 --- a/frame/treasury/src/benchmarking.rs +++ b/frame/treasury/src/benchmarking.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/treasury/src/lib.rs b/frame/treasury/src/lib.rs index 5258426e2681..057ee0c6032a 100644 --- a/frame/treasury/src/lib.rs +++ b/frame/treasury/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/treasury/src/tests.rs b/frame/treasury/src/tests.rs index 765f71f5dae8..b6d23440a73f 100644 --- a/frame/treasury/src/tests.rs +++ b/frame/treasury/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/treasury/src/weights.rs b/frame/treasury/src/weights.rs index 126c8a176626..79635ac2a725 100644 --- a/frame/treasury/src/weights.rs +++ b/frame/treasury/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/try-runtime/src/lib.rs b/frame/try-runtime/src/lib.rs index 754fc1d2a330..bf08112bfc37 100644 --- a/frame/try-runtime/src/lib.rs +++ b/frame/try-runtime/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/uniques/src/benchmarking.rs b/frame/uniques/src/benchmarking.rs index 513509bda70e..f3f9b7b28df7 100644 --- a/frame/uniques/src/benchmarking.rs +++ b/frame/uniques/src/benchmarking.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/uniques/src/functions.rs b/frame/uniques/src/functions.rs index 9c3a5c1b19f8..5d573e42097e 100644 --- a/frame/uniques/src/functions.rs +++ b/frame/uniques/src/functions.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/uniques/src/impl_nonfungibles.rs b/frame/uniques/src/impl_nonfungibles.rs index 72aa1dd0d4cb..a9695e8e898a 100644 --- a/frame/uniques/src/impl_nonfungibles.rs +++ b/frame/uniques/src/impl_nonfungibles.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/uniques/src/lib.rs b/frame/uniques/src/lib.rs index b5dada9ef645..33a8866019cf 100644 --- a/frame/uniques/src/lib.rs +++ b/frame/uniques/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/uniques/src/migration.rs b/frame/uniques/src/migration.rs index 76f78c2bc64e..71ccc6b07bd7 100644 --- a/frame/uniques/src/migration.rs +++ b/frame/uniques/src/migration.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/uniques/src/mock.rs b/frame/uniques/src/mock.rs index 679adf0424cf..2a94fcbee347 100644 --- a/frame/uniques/src/mock.rs +++ b/frame/uniques/src/mock.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/uniques/src/tests.rs b/frame/uniques/src/tests.rs index 8d0d6fdf9af3..0e0dc413a01a 100644 --- a/frame/uniques/src/tests.rs +++ b/frame/uniques/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/uniques/src/types.rs b/frame/uniques/src/types.rs index 5ba443dba6c4..4d1afe694bd8 100644 --- a/frame/uniques/src/types.rs +++ b/frame/uniques/src/types.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/uniques/src/weights.rs b/frame/uniques/src/weights.rs index 168e0fcc8015..3a67eb09017b 100644 --- a/frame/uniques/src/weights.rs +++ b/frame/uniques/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/utility/src/benchmarking.rs b/frame/utility/src/benchmarking.rs index ce59d7e898eb..402128d00580 100644 --- a/frame/utility/src/benchmarking.rs +++ b/frame/utility/src/benchmarking.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/utility/src/lib.rs b/frame/utility/src/lib.rs index 2200d96da600..ec48087e2ef4 100644 --- a/frame/utility/src/lib.rs +++ b/frame/utility/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/utility/src/tests.rs b/frame/utility/src/tests.rs index 11b63254eb40..9a1e11f54d6e 100644 --- a/frame/utility/src/tests.rs +++ b/frame/utility/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/utility/src/weights.rs b/frame/utility/src/weights.rs index bce18271684b..15798007a9ba 100644 --- a/frame/utility/src/weights.rs +++ b/frame/utility/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/vesting/src/benchmarking.rs b/frame/vesting/src/benchmarking.rs index b52ddac3e885..1693fdd3f1cb 100644 --- a/frame/vesting/src/benchmarking.rs +++ b/frame/vesting/src/benchmarking.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/vesting/src/lib.rs b/frame/vesting/src/lib.rs index 6857918bc9a1..fcad0c57f937 100644 --- a/frame/vesting/src/lib.rs +++ b/frame/vesting/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/vesting/src/migrations.rs b/frame/vesting/src/migrations.rs index f8024926f34a..688ebf6ad1c9 100644 --- a/frame/vesting/src/migrations.rs +++ b/frame/vesting/src/migrations.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/vesting/src/mock.rs b/frame/vesting/src/mock.rs index 2176716bf340..8a830d72b26b 100644 --- a/frame/vesting/src/mock.rs +++ b/frame/vesting/src/mock.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/vesting/src/tests.rs b/frame/vesting/src/tests.rs index 2a6dd0520c3b..cbc2e09c8319 100644 --- a/frame/vesting/src/tests.rs +++ b/frame/vesting/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/vesting/src/vesting_info.rs b/frame/vesting/src/vesting_info.rs index 81bffa199fd7..9069b6948276 100644 --- a/frame/vesting/src/vesting_info.rs +++ b/frame/vesting/src/vesting_info.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frame/vesting/src/weights.rs b/frame/vesting/src/weights.rs index 3ccc1a5bda36..660f83965557 100644 --- a/frame/vesting/src/weights.rs +++ b/frame/vesting/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/api/proc-macro/src/decl_runtime_apis.rs b/primitives/api/proc-macro/src/decl_runtime_apis.rs index 34907d619728..6c6b8f453a26 100644 --- a/primitives/api/proc-macro/src/decl_runtime_apis.rs +++ b/primitives/api/proc-macro/src/decl_runtime_apis.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/api/proc-macro/src/impl_runtime_apis.rs b/primitives/api/proc-macro/src/impl_runtime_apis.rs index db3ab3b76850..7241a1c2610d 100644 --- a/primitives/api/proc-macro/src/impl_runtime_apis.rs +++ b/primitives/api/proc-macro/src/impl_runtime_apis.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/api/proc-macro/src/lib.rs b/primitives/api/proc-macro/src/lib.rs index b8731d70ca3c..20a2f76f2c83 100644 --- a/primitives/api/proc-macro/src/lib.rs +++ b/primitives/api/proc-macro/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/api/proc-macro/src/mock_impl_runtime_apis.rs b/primitives/api/proc-macro/src/mock_impl_runtime_apis.rs index 9483d018c4a4..ffc158ac94d2 100644 --- a/primitives/api/proc-macro/src/mock_impl_runtime_apis.rs +++ b/primitives/api/proc-macro/src/mock_impl_runtime_apis.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/api/proc-macro/src/utils.rs b/primitives/api/proc-macro/src/utils.rs index a3f21638751e..2aa6a657aa9c 100644 --- a/primitives/api/proc-macro/src/utils.rs +++ b/primitives/api/proc-macro/src/utils.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/api/src/lib.rs b/primitives/api/src/lib.rs index 41c0151d6c53..964ef15ce5f5 100644 --- a/primitives/api/src/lib.rs +++ b/primitives/api/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/api/test/benches/bench.rs b/primitives/api/test/benches/bench.rs index b3d96a2db6a5..2682c91f9410 100644 --- a/primitives/api/test/benches/bench.rs +++ b/primitives/api/test/benches/bench.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/api/test/tests/decl_and_impl.rs b/primitives/api/test/tests/decl_and_impl.rs index 8d1b04a37a9f..1db416a1d3db 100644 --- a/primitives/api/test/tests/decl_and_impl.rs +++ b/primitives/api/test/tests/decl_and_impl.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/api/test/tests/runtime_calls.rs b/primitives/api/test/tests/runtime_calls.rs index 5c9b25fa3186..e085b023b122 100644 --- a/primitives/api/test/tests/runtime_calls.rs +++ b/primitives/api/test/tests/runtime_calls.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/api/test/tests/trybuild.rs b/primitives/api/test/tests/trybuild.rs index 5a6025f463af..9e3af145dc56 100644 --- a/primitives/api/test/tests/trybuild.rs +++ b/primitives/api/test/tests/trybuild.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/application-crypto/src/ecdsa.rs b/primitives/application-crypto/src/ecdsa.rs index fba1fc03b253..6a0eb7ab2f84 100644 --- a/primitives/application-crypto/src/ecdsa.rs +++ b/primitives/application-crypto/src/ecdsa.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/application-crypto/src/ed25519.rs b/primitives/application-crypto/src/ed25519.rs index 35fcb2403a03..f5ec40233ca9 100644 --- a/primitives/application-crypto/src/ed25519.rs +++ b/primitives/application-crypto/src/ed25519.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/application-crypto/src/lib.rs b/primitives/application-crypto/src/lib.rs index a6bba4363222..b12fe72b271a 100644 --- a/primitives/application-crypto/src/lib.rs +++ b/primitives/application-crypto/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/application-crypto/src/sr25519.rs b/primitives/application-crypto/src/sr25519.rs index 6cd1bf35a235..81c5320efd71 100644 --- a/primitives/application-crypto/src/sr25519.rs +++ b/primitives/application-crypto/src/sr25519.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/application-crypto/src/traits.rs b/primitives/application-crypto/src/traits.rs index 376d12f0c7a3..7a99c144b69f 100644 --- a/primitives/application-crypto/src/traits.rs +++ b/primitives/application-crypto/src/traits.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/application-crypto/test/src/ecdsa.rs b/primitives/application-crypto/test/src/ecdsa.rs index c4aa6a2afbd6..e45a3d5f8f86 100644 --- a/primitives/application-crypto/test/src/ecdsa.rs +++ b/primitives/application-crypto/test/src/ecdsa.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/application-crypto/test/src/ed25519.rs b/primitives/application-crypto/test/src/ed25519.rs index 7cfd801388c7..ef2df9fe9196 100644 --- a/primitives/application-crypto/test/src/ed25519.rs +++ b/primitives/application-crypto/test/src/ed25519.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/application-crypto/test/src/lib.rs b/primitives/application-crypto/test/src/lib.rs index 6b7734764e79..7cc3f8b0780e 100644 --- a/primitives/application-crypto/test/src/lib.rs +++ b/primitives/application-crypto/test/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/application-crypto/test/src/sr25519.rs b/primitives/application-crypto/test/src/sr25519.rs index 12dfbc609fb0..e15ffe82a1c3 100644 --- a/primitives/application-crypto/test/src/sr25519.rs +++ b/primitives/application-crypto/test/src/sr25519.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/arithmetic/benches/bench.rs b/primitives/arithmetic/benches/bench.rs index 02db00aa0bf8..3e4fafe2a4a9 100644 --- a/primitives/arithmetic/benches/bench.rs +++ b/primitives/arithmetic/benches/bench.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/arithmetic/fuzzer/src/biguint.rs b/primitives/arithmetic/fuzzer/src/biguint.rs index ca5b8379afff..e4c088a2e8ab 100644 --- a/primitives/arithmetic/fuzzer/src/biguint.rs +++ b/primitives/arithmetic/fuzzer/src/biguint.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/arithmetic/fuzzer/src/fixed_point.rs b/primitives/arithmetic/fuzzer/src/fixed_point.rs index d8f058ae51e2..c1b93f8c63a1 100644 --- a/primitives/arithmetic/fuzzer/src/fixed_point.rs +++ b/primitives/arithmetic/fuzzer/src/fixed_point.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/arithmetic/fuzzer/src/multiply_by_rational.rs b/primitives/arithmetic/fuzzer/src/multiply_by_rational.rs index 3089d4b09218..019cf0ec39b7 100644 --- a/primitives/arithmetic/fuzzer/src/multiply_by_rational.rs +++ b/primitives/arithmetic/fuzzer/src/multiply_by_rational.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/arithmetic/fuzzer/src/normalize.rs b/primitives/arithmetic/fuzzer/src/normalize.rs index 2662565106e6..e4f90dbc1c41 100644 --- a/primitives/arithmetic/fuzzer/src/normalize.rs +++ b/primitives/arithmetic/fuzzer/src/normalize.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/arithmetic/fuzzer/src/per_thing_rational.rs b/primitives/arithmetic/fuzzer/src/per_thing_rational.rs index 7b90faa94069..7021c54c0ba0 100644 --- a/primitives/arithmetic/fuzzer/src/per_thing_rational.rs +++ b/primitives/arithmetic/fuzzer/src/per_thing_rational.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/arithmetic/src/biguint.rs b/primitives/arithmetic/src/biguint.rs index 17ed323dc0ce..b26ac4294d11 100644 --- a/primitives/arithmetic/src/biguint.rs +++ b/primitives/arithmetic/src/biguint.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/arithmetic/src/fixed_point.rs b/primitives/arithmetic/src/fixed_point.rs index 7a81f222c492..206e63af95b1 100644 --- a/primitives/arithmetic/src/fixed_point.rs +++ b/primitives/arithmetic/src/fixed_point.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/arithmetic/src/helpers_128bit.rs b/primitives/arithmetic/src/helpers_128bit.rs index bbf69ea359fe..af9729c9702c 100644 --- a/primitives/arithmetic/src/helpers_128bit.rs +++ b/primitives/arithmetic/src/helpers_128bit.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/arithmetic/src/lib.rs b/primitives/arithmetic/src/lib.rs index 8671ceb0396e..92f8a708316d 100644 --- a/primitives/arithmetic/src/lib.rs +++ b/primitives/arithmetic/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/arithmetic/src/per_things.rs b/primitives/arithmetic/src/per_things.rs index 783b331b3353..21ad0dd52099 100644 --- a/primitives/arithmetic/src/per_things.rs +++ b/primitives/arithmetic/src/per_things.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/arithmetic/src/rational.rs b/primitives/arithmetic/src/rational.rs index 225e1d952182..63ae6e65bc9e 100644 --- a/primitives/arithmetic/src/rational.rs +++ b/primitives/arithmetic/src/rational.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/arithmetic/src/traits.rs b/primitives/arithmetic/src/traits.rs index 53341117b1fe..447f8cef51f9 100644 --- a/primitives/arithmetic/src/traits.rs +++ b/primitives/arithmetic/src/traits.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/authority-discovery/src/lib.rs b/primitives/authority-discovery/src/lib.rs index 871a35e6bf48..95bb458b1be8 100644 --- a/primitives/authority-discovery/src/lib.rs +++ b/primitives/authority-discovery/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/authorship/src/lib.rs b/primitives/authorship/src/lib.rs index ac4b5fd315dc..25eaeaf9bc16 100644 --- a/primitives/authorship/src/lib.rs +++ b/primitives/authorship/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/beefy/src/commitment.rs b/primitives/beefy/src/commitment.rs index 63c6520d8680..ed392139de13 100644 --- a/primitives/beefy/src/commitment.rs +++ b/primitives/beefy/src/commitment.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/beefy/src/lib.rs b/primitives/beefy/src/lib.rs index bf72b801eec0..8dbdd66f3559 100644 --- a/primitives/beefy/src/lib.rs +++ b/primitives/beefy/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/beefy/src/mmr.rs b/primitives/beefy/src/mmr.rs index e428c0ea0121..215214bef294 100644 --- a/primitives/beefy/src/mmr.rs +++ b/primitives/beefy/src/mmr.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/beefy/src/witness.rs b/primitives/beefy/src/witness.rs index 102a6be09c78..aae060815053 100644 --- a/primitives/beefy/src/witness.rs +++ b/primitives/beefy/src/witness.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/block-builder/src/lib.rs b/primitives/block-builder/src/lib.rs index 3741b1920064..229f115c6667 100644 --- a/primitives/block-builder/src/lib.rs +++ b/primitives/block-builder/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/blockchain/src/backend.rs b/primitives/blockchain/src/backend.rs index 71c3f36a161b..3c6419648388 100644 --- a/primitives/blockchain/src/backend.rs +++ b/primitives/blockchain/src/backend.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/blockchain/src/error.rs b/primitives/blockchain/src/error.rs index ef3afa5bce94..bbd65e002a3b 100644 --- a/primitives/blockchain/src/error.rs +++ b/primitives/blockchain/src/error.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/blockchain/src/header_metadata.rs b/primitives/blockchain/src/header_metadata.rs index 928409963bcd..9f388dc58fbc 100644 --- a/primitives/blockchain/src/header_metadata.rs +++ b/primitives/blockchain/src/header_metadata.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/blockchain/src/lib.rs b/primitives/blockchain/src/lib.rs index cd36cabe1551..2fdef6cba9e5 100644 --- a/primitives/blockchain/src/lib.rs +++ b/primitives/blockchain/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/consensus/aura/src/digests.rs b/primitives/consensus/aura/src/digests.rs index 6925862d0ce9..b71930b6c6b8 100644 --- a/primitives/consensus/aura/src/digests.rs +++ b/primitives/consensus/aura/src/digests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 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 diff --git a/primitives/consensus/aura/src/inherents.rs b/primitives/consensus/aura/src/inherents.rs index 2a797b5d3f39..c3fa43bec02b 100644 --- a/primitives/consensus/aura/src/inherents.rs +++ b/primitives/consensus/aura/src/inherents.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/consensus/aura/src/lib.rs b/primitives/consensus/aura/src/lib.rs index b85443e0917e..cec89d0449d8 100644 --- a/primitives/consensus/aura/src/lib.rs +++ b/primitives/consensus/aura/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/consensus/babe/src/digests.rs b/primitives/consensus/babe/src/digests.rs index 4847adec37f1..0f21c913ac57 100644 --- a/primitives/consensus/babe/src/digests.rs +++ b/primitives/consensus/babe/src/digests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/consensus/babe/src/inherents.rs b/primitives/consensus/babe/src/inherents.rs index cecd61998a4d..1eadfd85d114 100644 --- a/primitives/consensus/babe/src/inherents.rs +++ b/primitives/consensus/babe/src/inherents.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/consensus/babe/src/lib.rs b/primitives/consensus/babe/src/lib.rs index 1971563ff198..e7dfc100825d 100644 --- a/primitives/consensus/babe/src/lib.rs +++ b/primitives/consensus/babe/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/consensus/common/src/block_validation.rs b/primitives/consensus/common/src/block_validation.rs index 54a70a402b06..71f3a80b27a6 100644 --- a/primitives/consensus/common/src/block_validation.rs +++ b/primitives/consensus/common/src/block_validation.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/consensus/common/src/error.rs b/primitives/consensus/common/src/error.rs index 546f30d3e820..280ff2322898 100644 --- a/primitives/consensus/common/src/error.rs +++ b/primitives/consensus/common/src/error.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/consensus/common/src/evaluation.rs b/primitives/consensus/common/src/evaluation.rs index 19be5e552634..d0ddbb6fab81 100644 --- a/primitives/consensus/common/src/evaluation.rs +++ b/primitives/consensus/common/src/evaluation.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/consensus/common/src/lib.rs b/primitives/consensus/common/src/lib.rs index 456ba965f4aa..492ad83ddf5b 100644 --- a/primitives/consensus/common/src/lib.rs +++ b/primitives/consensus/common/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/consensus/common/src/select_chain.rs b/primitives/consensus/common/src/select_chain.rs index fd8b06ecf8ab..f366cd34c51e 100644 --- a/primitives/consensus/common/src/select_chain.rs +++ b/primitives/consensus/common/src/select_chain.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/consensus/pow/src/lib.rs b/primitives/consensus/pow/src/lib.rs index ac8bc589c136..fe10ee808db9 100644 --- a/primitives/consensus/pow/src/lib.rs +++ b/primitives/consensus/pow/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/consensus/slots/src/lib.rs b/primitives/consensus/slots/src/lib.rs index 72b3c95068e3..e8ab98399414 100644 --- a/primitives/consensus/slots/src/lib.rs +++ b/primitives/consensus/slots/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/consensus/vrf/src/lib.rs b/primitives/consensus/vrf/src/lib.rs index 19391c6c1c84..07e3f2c31970 100644 --- a/primitives/consensus/vrf/src/lib.rs +++ b/primitives/consensus/vrf/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/consensus/vrf/src/schnorrkel.rs b/primitives/consensus/vrf/src/schnorrkel.rs index 687e0bd23182..1ef23427e0ed 100644 --- a/primitives/consensus/vrf/src/schnorrkel.rs +++ b/primitives/consensus/vrf/src/schnorrkel.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/core/hashing/proc-macro/src/impls.rs b/primitives/core/hashing/proc-macro/src/impls.rs index 0ce388762aa3..ff9593ea1844 100644 --- a/primitives/core/hashing/proc-macro/src/impls.rs +++ b/primitives/core/hashing/proc-macro/src/impls.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/core/hashing/proc-macro/src/lib.rs b/primitives/core/hashing/proc-macro/src/lib.rs index 2af8554f4ece..2db292d8dc0c 100644 --- a/primitives/core/hashing/proc-macro/src/lib.rs +++ b/primitives/core/hashing/proc-macro/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/core/hashing/src/lib.rs b/primitives/core/hashing/src/lib.rs index f806613c5b54..9fa433a32320 100644 --- a/primitives/core/hashing/src/lib.rs +++ b/primitives/core/hashing/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/core/src/crypto.rs b/primitives/core/src/crypto.rs index e6735c7745cf..d3dd8b92bd79 100644 --- a/primitives/core/src/crypto.rs +++ b/primitives/core/src/crypto.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/core/src/ecdsa.rs b/primitives/core/src/ecdsa.rs index 682f46c2a432..c5e53c7029e6 100644 --- a/primitives/core/src/ecdsa.rs +++ b/primitives/core/src/ecdsa.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/core/src/ed25519.rs b/primitives/core/src/ed25519.rs index df9ec6a457c6..bb99a4ae0200 100644 --- a/primitives/core/src/ed25519.rs +++ b/primitives/core/src/ed25519.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/core/src/hash.rs b/primitives/core/src/hash.rs index 55a9664c9dad..f2974e9372ad 100644 --- a/primitives/core/src/hash.rs +++ b/primitives/core/src/hash.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/core/src/hasher.rs b/primitives/core/src/hasher.rs index 01680de08376..173bd560ad1e 100644 --- a/primitives/core/src/hasher.rs +++ b/primitives/core/src/hasher.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/core/src/hashing.rs b/primitives/core/src/hashing.rs index 092cfc51b950..1c439355a33c 100644 --- a/primitives/core/src/hashing.rs +++ b/primitives/core/src/hashing.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/core/src/hexdisplay.rs b/primitives/core/src/hexdisplay.rs index 4d91db156792..e5262ba8f657 100644 --- a/primitives/core/src/hexdisplay.rs +++ b/primitives/core/src/hexdisplay.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/core/src/lib.rs b/primitives/core/src/lib.rs index 5fca42adde99..c794752e9d3d 100644 --- a/primitives/core/src/lib.rs +++ b/primitives/core/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/core/src/offchain/mod.rs b/primitives/core/src/offchain/mod.rs index 8058d4d05d6a..b9e310dc1fb1 100644 --- a/primitives/core/src/offchain/mod.rs +++ b/primitives/core/src/offchain/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/core/src/offchain/storage.rs b/primitives/core/src/offchain/storage.rs index ff72006cffd6..cf2c93641f24 100644 --- a/primitives/core/src/offchain/storage.rs +++ b/primitives/core/src/offchain/storage.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/core/src/offchain/testing.rs b/primitives/core/src/offchain/testing.rs index 29b9edb03deb..a2065eb17717 100644 --- a/primitives/core/src/offchain/testing.rs +++ b/primitives/core/src/offchain/testing.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/core/src/sandbox.rs b/primitives/core/src/sandbox.rs index acc3fda5e9b1..1f408a3b8cc0 100644 --- a/primitives/core/src/sandbox.rs +++ b/primitives/core/src/sandbox.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/core/src/sr25519.rs b/primitives/core/src/sr25519.rs index 71379dfc66b9..4094c4d1b440 100644 --- a/primitives/core/src/sr25519.rs +++ b/primitives/core/src/sr25519.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/core/src/testing.rs b/primitives/core/src/testing.rs index a40a37804c03..d5ca1dc45fa0 100644 --- a/primitives/core/src/testing.rs +++ b/primitives/core/src/testing.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/core/src/traits.rs b/primitives/core/src/traits.rs index e3d7d8e283e2..80e8963a2909 100644 --- a/primitives/core/src/traits.rs +++ b/primitives/core/src/traits.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/core/src/u32_trait.rs b/primitives/core/src/u32_trait.rs index 37837e7c0548..ff1508040034 100644 --- a/primitives/core/src/u32_trait.rs +++ b/primitives/core/src/u32_trait.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/core/src/uint.rs b/primitives/core/src/uint.rs index a74980332ad2..f4eb3a19ac36 100644 --- a/primitives/core/src/uint.rs +++ b/primitives/core/src/uint.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/database/src/error.rs b/primitives/database/src/error.rs index 4bf5a20aff40..78646427a2b5 100644 --- a/primitives/database/src/error.rs +++ b/primitives/database/src/error.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/database/src/kvdb.rs b/primitives/database/src/kvdb.rs index 1a2b0513dc28..5fe5fda307a1 100644 --- a/primitives/database/src/kvdb.rs +++ b/primitives/database/src/kvdb.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/database/src/lib.rs b/primitives/database/src/lib.rs index d30c7eb3323e..2d7c5fd6653e 100644 --- a/primitives/database/src/lib.rs +++ b/primitives/database/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/database/src/mem.rs b/primitives/database/src/mem.rs index d1b1861e98fd..6ecd44c6005b 100644 --- a/primitives/database/src/mem.rs +++ b/primitives/database/src/mem.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/debug-derive/src/impls.rs b/primitives/debug-derive/src/impls.rs index 0e67ef81bc85..bab0146e4682 100644 --- a/primitives/debug-derive/src/impls.rs +++ b/primitives/debug-derive/src/impls.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/debug-derive/src/lib.rs b/primitives/debug-derive/src/lib.rs index 7eaa3a0020e9..c98610ce4780 100644 --- a/primitives/debug-derive/src/lib.rs +++ b/primitives/debug-derive/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/debug-derive/tests/tests.rs b/primitives/debug-derive/tests/tests.rs index 4f4c7f4caabc..39414da86bf4 100644 --- a/primitives/debug-derive/tests/tests.rs +++ b/primitives/debug-derive/tests/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/externalities/src/extensions.rs b/primitives/externalities/src/extensions.rs index 37086a707b64..d58edb749e9e 100644 --- a/primitives/externalities/src/extensions.rs +++ b/primitives/externalities/src/extensions.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/externalities/src/lib.rs b/primitives/externalities/src/lib.rs index 6d560c3c7f11..49b190b4ae26 100644 --- a/primitives/externalities/src/lib.rs +++ b/primitives/externalities/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/externalities/src/scope_limited.rs b/primitives/externalities/src/scope_limited.rs index 15a670a9abee..1d2e6863c9e5 100644 --- a/primitives/externalities/src/scope_limited.rs +++ b/primitives/externalities/src/scope_limited.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/finality-grandpa/src/lib.rs b/primitives/finality-grandpa/src/lib.rs index b762a1596bf8..dd5cef85a2ba 100644 --- a/primitives/finality-grandpa/src/lib.rs +++ b/primitives/finality-grandpa/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/inherents/src/client_side.rs b/primitives/inherents/src/client_side.rs index 18877cae5f34..42068e24e029 100644 --- a/primitives/inherents/src/client_side.rs +++ b/primitives/inherents/src/client_side.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/inherents/src/lib.rs b/primitives/inherents/src/lib.rs index 90f4e455a42d..cd04a1bc3b3d 100644 --- a/primitives/inherents/src/lib.rs +++ b/primitives/inherents/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/io/src/batch_verifier.rs b/primitives/io/src/batch_verifier.rs index 05c8a63694eb..501d986758bf 100644 --- a/primitives/io/src/batch_verifier.rs +++ b/primitives/io/src/batch_verifier.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/io/src/lib.rs b/primitives/io/src/lib.rs index 9025ae3d76f4..76ced407090c 100644 --- a/primitives/io/src/lib.rs +++ b/primitives/io/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/keyring/src/ed25519.rs b/primitives/keyring/src/ed25519.rs index 4d99de6c59d7..6d56062d3473 100644 --- a/primitives/keyring/src/ed25519.rs +++ b/primitives/keyring/src/ed25519.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/keyring/src/lib.rs b/primitives/keyring/src/lib.rs index d7fb7c4fd2f2..170a4c3d01b2 100644 --- a/primitives/keyring/src/lib.rs +++ b/primitives/keyring/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/keyring/src/sr25519.rs b/primitives/keyring/src/sr25519.rs index d400cde035b7..86bcac9d58cb 100644 --- a/primitives/keyring/src/sr25519.rs +++ b/primitives/keyring/src/sr25519.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/keystore/src/lib.rs b/primitives/keystore/src/lib.rs index c45e8a6f5d2b..6c27e3df7ce0 100644 --- a/primitives/keystore/src/lib.rs +++ b/primitives/keystore/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/keystore/src/testing.rs b/primitives/keystore/src/testing.rs index 92a73eb98c90..eb5847207daa 100644 --- a/primitives/keystore/src/testing.rs +++ b/primitives/keystore/src/testing.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/keystore/src/vrf.rs b/primitives/keystore/src/vrf.rs index 383abb77e17c..7409353afe9f 100644 --- a/primitives/keystore/src/vrf.rs +++ b/primitives/keystore/src/vrf.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/maybe-compressed-blob/src/lib.rs b/primitives/maybe-compressed-blob/src/lib.rs index e8a7e42b4eac..402ed90be21c 100644 --- a/primitives/maybe-compressed-blob/src/lib.rs +++ b/primitives/maybe-compressed-blob/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/npos-elections/fuzzer/src/common.rs b/primitives/npos-elections/fuzzer/src/common.rs index e97f7f7df8b1..7ca66f72dd92 100644 --- a/primitives/npos-elections/fuzzer/src/common.rs +++ b/primitives/npos-elections/fuzzer/src/common.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/npos-elections/fuzzer/src/phragmen_balancing.rs b/primitives/npos-elections/fuzzer/src/phragmen_balancing.rs index 0c140a8ce6fa..2af6a4c0f815 100644 --- a/primitives/npos-elections/fuzzer/src/phragmen_balancing.rs +++ b/primitives/npos-elections/fuzzer/src/phragmen_balancing.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/npos-elections/fuzzer/src/phragmen_pjr.rs b/primitives/npos-elections/fuzzer/src/phragmen_pjr.rs index f1110da8ef8b..59763a58686d 100644 --- a/primitives/npos-elections/fuzzer/src/phragmen_pjr.rs +++ b/primitives/npos-elections/fuzzer/src/phragmen_pjr.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/npos-elections/fuzzer/src/phragmms_balancing.rs b/primitives/npos-elections/fuzzer/src/phragmms_balancing.rs index 7b2aacfa8588..0cd49c3f8044 100644 --- a/primitives/npos-elections/fuzzer/src/phragmms_balancing.rs +++ b/primitives/npos-elections/fuzzer/src/phragmms_balancing.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/npos-elections/fuzzer/src/reduce.rs b/primitives/npos-elections/fuzzer/src/reduce.rs index 5f8a4f0e1384..029bb18dc5b3 100644 --- a/primitives/npos-elections/fuzzer/src/reduce.rs +++ b/primitives/npos-elections/fuzzer/src/reduce.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/npos-elections/solution-type/src/codec.rs b/primitives/npos-elections/solution-type/src/codec.rs index 2dac076fcde4..71faa141f0b6 100644 --- a/primitives/npos-elections/solution-type/src/codec.rs +++ b/primitives/npos-elections/solution-type/src/codec.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/npos-elections/solution-type/src/from_assignment_helpers.rs b/primitives/npos-elections/solution-type/src/from_assignment_helpers.rs index dc194baa6d9e..e0613afc0d39 100644 --- a/primitives/npos-elections/solution-type/src/from_assignment_helpers.rs +++ b/primitives/npos-elections/solution-type/src/from_assignment_helpers.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/npos-elections/solution-type/src/index_assignment.rs b/primitives/npos-elections/solution-type/src/index_assignment.rs index d38dc3ec309d..ccdcb4ba25cd 100644 --- a/primitives/npos-elections/solution-type/src/index_assignment.rs +++ b/primitives/npos-elections/solution-type/src/index_assignment.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/npos-elections/solution-type/src/lib.rs b/primitives/npos-elections/solution-type/src/lib.rs index 967ead4400c3..6e632d19e171 100644 --- a/primitives/npos-elections/solution-type/src/lib.rs +++ b/primitives/npos-elections/solution-type/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/npos-elections/solution-type/src/single_page.rs b/primitives/npos-elections/solution-type/src/single_page.rs index 33017d558331..01a8a8eba5dc 100644 --- a/primitives/npos-elections/solution-type/src/single_page.rs +++ b/primitives/npos-elections/solution-type/src/single_page.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/npos-elections/src/assignments.rs b/primitives/npos-elections/src/assignments.rs index 330f7bd7e843..5641a33447ba 100644 --- a/primitives/npos-elections/src/assignments.rs +++ b/primitives/npos-elections/src/assignments.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/npos-elections/src/balancing.rs b/primitives/npos-elections/src/balancing.rs index 63164049e526..98f193e9e611 100644 --- a/primitives/npos-elections/src/balancing.rs +++ b/primitives/npos-elections/src/balancing.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/npos-elections/src/helpers.rs b/primitives/npos-elections/src/helpers.rs index ca97aeb996e4..76cfd59de6fb 100644 --- a/primitives/npos-elections/src/helpers.rs +++ b/primitives/npos-elections/src/helpers.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/npos-elections/src/lib.rs b/primitives/npos-elections/src/lib.rs index 0b10b4c7c1b8..bb1c38d3077c 100644 --- a/primitives/npos-elections/src/lib.rs +++ b/primitives/npos-elections/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2019-2022 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 diff --git a/primitives/npos-elections/src/mock.rs b/primitives/npos-elections/src/mock.rs index 36fd78b5757e..8e8e7ebc1c0c 100644 --- a/primitives/npos-elections/src/mock.rs +++ b/primitives/npos-elections/src/mock.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/npos-elections/src/node.rs b/primitives/npos-elections/src/node.rs index 62b728d52258..6642a9ae3973 100644 --- a/primitives/npos-elections/src/node.rs +++ b/primitives/npos-elections/src/node.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/npos-elections/src/phragmen.rs b/primitives/npos-elections/src/phragmen.rs index 5ed472284351..c582c5910d69 100644 --- a/primitives/npos-elections/src/phragmen.rs +++ b/primitives/npos-elections/src/phragmen.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/npos-elections/src/phragmms.rs b/primitives/npos-elections/src/phragmms.rs index e9135a13190c..7c51da9ee92e 100644 --- a/primitives/npos-elections/src/phragmms.rs +++ b/primitives/npos-elections/src/phragmms.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/npos-elections/src/pjr.rs b/primitives/npos-elections/src/pjr.rs index 50556ea9cc33..2d58ca49c8a2 100644 --- a/primitives/npos-elections/src/pjr.rs +++ b/primitives/npos-elections/src/pjr.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/npos-elections/src/reduce.rs b/primitives/npos-elections/src/reduce.rs index 8ff0244b4694..057ee339bd7d 100644 --- a/primitives/npos-elections/src/reduce.rs +++ b/primitives/npos-elections/src/reduce.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/npos-elections/src/tests.rs b/primitives/npos-elections/src/tests.rs index 0aac5c3c35df..e7d0078b1fbe 100644 --- a/primitives/npos-elections/src/tests.rs +++ b/primitives/npos-elections/src/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/npos-elections/src/traits.rs b/primitives/npos-elections/src/traits.rs index cb24f770cdea..0723948b6226 100644 --- a/primitives/npos-elections/src/traits.rs +++ b/primitives/npos-elections/src/traits.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/offchain/src/lib.rs b/primitives/offchain/src/lib.rs index 72ceca80cfbf..3e967f16d2a8 100644 --- a/primitives/offchain/src/lib.rs +++ b/primitives/offchain/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/panic-handler/src/lib.rs b/primitives/panic-handler/src/lib.rs index eddb31a7f22f..df1f78da1cbe 100644 --- a/primitives/panic-handler/src/lib.rs +++ b/primitives/panic-handler/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/rpc/src/lib.rs b/primitives/rpc/src/lib.rs index 0d716d5a07c1..915482e5fca7 100644 --- a/primitives/rpc/src/lib.rs +++ b/primitives/rpc/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/rpc/src/list.rs b/primitives/rpc/src/list.rs index b3d0a4f546e9..7ec4d3491c7e 100644 --- a/primitives/rpc/src/list.rs +++ b/primitives/rpc/src/list.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/rpc/src/number.rs b/primitives/rpc/src/number.rs index 916f2c3d8326..5a433a9598e0 100644 --- a/primitives/rpc/src/number.rs +++ b/primitives/rpc/src/number.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/rpc/src/tracing.rs b/primitives/rpc/src/tracing.rs index 737ace241037..a923ffcb69e0 100644 --- a/primitives/rpc/src/tracing.rs +++ b/primitives/rpc/src/tracing.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime-interface/proc-macro/src/lib.rs b/primitives/runtime-interface/proc-macro/src/lib.rs index 6b0669a298e1..afba38993fe7 100644 --- a/primitives/runtime-interface/proc-macro/src/lib.rs +++ b/primitives/runtime-interface/proc-macro/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime-interface/proc-macro/src/pass_by/codec.rs b/primitives/runtime-interface/proc-macro/src/pass_by/codec.rs index 2be455d17a47..4259b137d67c 100644 --- a/primitives/runtime-interface/proc-macro/src/pass_by/codec.rs +++ b/primitives/runtime-interface/proc-macro/src/pass_by/codec.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime-interface/proc-macro/src/pass_by/enum_.rs b/primitives/runtime-interface/proc-macro/src/pass_by/enum_.rs index f614e4d9f294..1fd22c6a2538 100644 --- a/primitives/runtime-interface/proc-macro/src/pass_by/enum_.rs +++ b/primitives/runtime-interface/proc-macro/src/pass_by/enum_.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime-interface/proc-macro/src/pass_by/inner.rs b/primitives/runtime-interface/proc-macro/src/pass_by/inner.rs index 6eaa689d6293..7a527af12946 100644 --- a/primitives/runtime-interface/proc-macro/src/pass_by/inner.rs +++ b/primitives/runtime-interface/proc-macro/src/pass_by/inner.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime-interface/proc-macro/src/pass_by/mod.rs b/primitives/runtime-interface/proc-macro/src/pass_by/mod.rs index 80ac3396759f..e32c2beb8b72 100644 --- a/primitives/runtime-interface/proc-macro/src/pass_by/mod.rs +++ b/primitives/runtime-interface/proc-macro/src/pass_by/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime-interface/proc-macro/src/runtime_interface/bare_function_interface.rs b/primitives/runtime-interface/proc-macro/src/runtime_interface/bare_function_interface.rs index c951dedb6771..cbb749a111a1 100644 --- a/primitives/runtime-interface/proc-macro/src/runtime_interface/bare_function_interface.rs +++ b/primitives/runtime-interface/proc-macro/src/runtime_interface/bare_function_interface.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime-interface/proc-macro/src/runtime_interface/host_function_interface.rs b/primitives/runtime-interface/proc-macro/src/runtime_interface/host_function_interface.rs index c79886d45b18..2416e6951fe2 100644 --- a/primitives/runtime-interface/proc-macro/src/runtime_interface/host_function_interface.rs +++ b/primitives/runtime-interface/proc-macro/src/runtime_interface/host_function_interface.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime-interface/proc-macro/src/runtime_interface/mod.rs b/primitives/runtime-interface/proc-macro/src/runtime_interface/mod.rs index 78feda663850..d14c1f67ecff 100644 --- a/primitives/runtime-interface/proc-macro/src/runtime_interface/mod.rs +++ b/primitives/runtime-interface/proc-macro/src/runtime_interface/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime-interface/proc-macro/src/runtime_interface/trait_decl_impl.rs b/primitives/runtime-interface/proc-macro/src/runtime_interface/trait_decl_impl.rs index c62e3ba87ccd..c48da3b78851 100644 --- a/primitives/runtime-interface/proc-macro/src/runtime_interface/trait_decl_impl.rs +++ b/primitives/runtime-interface/proc-macro/src/runtime_interface/trait_decl_impl.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime-interface/proc-macro/src/utils.rs b/primitives/runtime-interface/proc-macro/src/utils.rs index 42ce09c57393..593f8ecafa7a 100644 --- a/primitives/runtime-interface/proc-macro/src/utils.rs +++ b/primitives/runtime-interface/proc-macro/src/utils.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime-interface/src/host.rs b/primitives/runtime-interface/src/host.rs index a6ea96af9004..36492430266a 100644 --- a/primitives/runtime-interface/src/host.rs +++ b/primitives/runtime-interface/src/host.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime-interface/src/impls.rs b/primitives/runtime-interface/src/impls.rs index 16eecbd021e0..3c1927d6b361 100644 --- a/primitives/runtime-interface/src/impls.rs +++ b/primitives/runtime-interface/src/impls.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime-interface/src/lib.rs b/primitives/runtime-interface/src/lib.rs index e8e29329a980..d87b0d57a772 100644 --- a/primitives/runtime-interface/src/lib.rs +++ b/primitives/runtime-interface/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime-interface/src/pass_by.rs b/primitives/runtime-interface/src/pass_by.rs index 02cbe502f02c..fb2d6b818d17 100644 --- a/primitives/runtime-interface/src/pass_by.rs +++ b/primitives/runtime-interface/src/pass_by.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime-interface/src/util.rs b/primitives/runtime-interface/src/util.rs index 31045c83c9dc..fe8afe99508a 100644 --- a/primitives/runtime-interface/src/util.rs +++ b/primitives/runtime-interface/src/util.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime-interface/src/wasm.rs b/primitives/runtime-interface/src/wasm.rs index 28613f81a68b..4ed27687a10a 100644 --- a/primitives/runtime-interface/src/wasm.rs +++ b/primitives/runtime-interface/src/wasm.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime-interface/test-wasm-deprecated/build.rs b/primitives/runtime-interface/test-wasm-deprecated/build.rs index a1c4b2d892cf..b773ed9cf6fb 100644 --- a/primitives/runtime-interface/test-wasm-deprecated/build.rs +++ b/primitives/runtime-interface/test-wasm-deprecated/build.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime-interface/test-wasm-deprecated/src/lib.rs b/primitives/runtime-interface/test-wasm-deprecated/src/lib.rs index 4a59e4fe8aa5..512d52214c12 100644 --- a/primitives/runtime-interface/test-wasm-deprecated/src/lib.rs +++ b/primitives/runtime-interface/test-wasm-deprecated/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime-interface/test-wasm/build.rs b/primitives/runtime-interface/test-wasm/build.rs index a1c4b2d892cf..b773ed9cf6fb 100644 --- a/primitives/runtime-interface/test-wasm/build.rs +++ b/primitives/runtime-interface/test-wasm/build.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime-interface/test-wasm/src/lib.rs b/primitives/runtime-interface/test-wasm/src/lib.rs index 72acdd4ff8d6..982febb7b4fb 100644 --- a/primitives/runtime-interface/test-wasm/src/lib.rs +++ b/primitives/runtime-interface/test-wasm/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime-interface/test/src/lib.rs b/primitives/runtime-interface/test/src/lib.rs index bf82f3b4b52e..785215b87421 100644 --- a/primitives/runtime-interface/test/src/lib.rs +++ b/primitives/runtime-interface/test/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime-interface/tests/ui.rs b/primitives/runtime-interface/tests/ui.rs index 5a6025f463af..9e3af145dc56 100644 --- a/primitives/runtime-interface/tests/ui.rs +++ b/primitives/runtime-interface/tests/ui.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime/src/curve.rs b/primitives/runtime/src/curve.rs index d6bd94c2bff7..b5532c3d8cef 100644 --- a/primitives/runtime/src/curve.rs +++ b/primitives/runtime/src/curve.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime/src/generic/block.rs b/primitives/runtime/src/generic/block.rs index 68959cc514d9..2cd350b2c5ba 100644 --- a/primitives/runtime/src/generic/block.rs +++ b/primitives/runtime/src/generic/block.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime/src/generic/checked_extrinsic.rs b/primitives/runtime/src/generic/checked_extrinsic.rs index f65e4ead089f..5d6c657a6897 100644 --- a/primitives/runtime/src/generic/checked_extrinsic.rs +++ b/primitives/runtime/src/generic/checked_extrinsic.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime/src/generic/digest.rs b/primitives/runtime/src/generic/digest.rs index 978653efb93d..ca1daabb06d2 100644 --- a/primitives/runtime/src/generic/digest.rs +++ b/primitives/runtime/src/generic/digest.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime/src/generic/era.rs b/primitives/runtime/src/generic/era.rs index 9d831b679c5e..2ca50b12b2e1 100644 --- a/primitives/runtime/src/generic/era.rs +++ b/primitives/runtime/src/generic/era.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime/src/generic/header.rs b/primitives/runtime/src/generic/header.rs index 21c2a6eef73a..3e1a673d257a 100644 --- a/primitives/runtime/src/generic/header.rs +++ b/primitives/runtime/src/generic/header.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime/src/generic/mod.rs b/primitives/runtime/src/generic/mod.rs index 3d8e8a0ce7fa..049b0e1624e7 100644 --- a/primitives/runtime/src/generic/mod.rs +++ b/primitives/runtime/src/generic/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime/src/generic/tests.rs b/primitives/runtime/src/generic/tests.rs index a65e212bf07e..d0536a567312 100644 --- a/primitives/runtime/src/generic/tests.rs +++ b/primitives/runtime/src/generic/tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime/src/generic/unchecked_extrinsic.rs b/primitives/runtime/src/generic/unchecked_extrinsic.rs index 53e7c349f2a7..d919a67095d3 100644 --- a/primitives/runtime/src/generic/unchecked_extrinsic.rs +++ b/primitives/runtime/src/generic/unchecked_extrinsic.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 7fdc5dda5c74..cb9ba9ff297f 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime/src/multiaddress.rs b/primitives/runtime/src/multiaddress.rs index 629099d85d72..b2d46fb106cb 100644 --- a/primitives/runtime/src/multiaddress.rs +++ b/primitives/runtime/src/multiaddress.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime/src/offchain/http.rs b/primitives/runtime/src/offchain/http.rs index a8c82e616a47..c479062de5f1 100644 --- a/primitives/runtime/src/offchain/http.rs +++ b/primitives/runtime/src/offchain/http.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime/src/offchain/mod.rs b/primitives/runtime/src/offchain/mod.rs index c9d1eda0f873..bbff693dea03 100644 --- a/primitives/runtime/src/offchain/mod.rs +++ b/primitives/runtime/src/offchain/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime/src/offchain/storage.rs b/primitives/runtime/src/offchain/storage.rs index 3bc5b10f161f..38ad268e5894 100644 --- a/primitives/runtime/src/offchain/storage.rs +++ b/primitives/runtime/src/offchain/storage.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime/src/offchain/storage_lock.rs b/primitives/runtime/src/offchain/storage_lock.rs index b4833bf345fc..90f8df794557 100644 --- a/primitives/runtime/src/offchain/storage_lock.rs +++ b/primitives/runtime/src/offchain/storage_lock.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime/src/runtime_logger.rs b/primitives/runtime/src/runtime_logger.rs index ff0e531ed814..8b5a15762e1f 100644 --- a/primitives/runtime/src/runtime_logger.rs +++ b/primitives/runtime/src/runtime_logger.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime/src/runtime_string.rs b/primitives/runtime/src/runtime_string.rs index a69e85418d82..fcbdd2e787ff 100644 --- a/primitives/runtime/src/runtime_string.rs +++ b/primitives/runtime/src/runtime_string.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime/src/testing.rs b/primitives/runtime/src/testing.rs index 46e7ee634c25..003fa62c9e08 100644 --- a/primitives/runtime/src/testing.rs +++ b/primitives/runtime/src/testing.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime/src/traits.rs b/primitives/runtime/src/traits.rs index cc83f66ea463..84c35597b4b1 100644 --- a/primitives/runtime/src/traits.rs +++ b/primitives/runtime/src/traits.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/runtime/src/transaction_validity.rs b/primitives/runtime/src/transaction_validity.rs index cf5d92597599..29c8b542319b 100644 --- a/primitives/runtime/src/transaction_validity.rs +++ b/primitives/runtime/src/transaction_validity.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/sandbox/src/embedded_executor.rs b/primitives/sandbox/src/embedded_executor.rs index c521ff2cb63f..43967a0a3898 100755 --- a/primitives/sandbox/src/embedded_executor.rs +++ b/primitives/sandbox/src/embedded_executor.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/sandbox/src/host_executor.rs b/primitives/sandbox/src/host_executor.rs index 43484dd66a00..83721f40e3d9 100755 --- a/primitives/sandbox/src/host_executor.rs +++ b/primitives/sandbox/src/host_executor.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/sandbox/src/lib.rs b/primitives/sandbox/src/lib.rs index 79c56e70e2f4..537c7cbb31b6 100755 --- a/primitives/sandbox/src/lib.rs +++ b/primitives/sandbox/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/serializer/src/lib.rs b/primitives/serializer/src/lib.rs index ccdbbf27f179..d1e364a133ba 100644 --- a/primitives/serializer/src/lib.rs +++ b/primitives/serializer/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/session/src/lib.rs b/primitives/session/src/lib.rs index d85b6af4349e..1b25d285e3bc 100644 --- a/primitives/session/src/lib.rs +++ b/primitives/session/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/staking/src/lib.rs b/primitives/staking/src/lib.rs index 4bb8ed93f88a..e7db609e230a 100644 --- a/primitives/staking/src/lib.rs +++ b/primitives/staking/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/staking/src/offence.rs b/primitives/staking/src/offence.rs index fdff02d42065..4261063993a5 100644 --- a/primitives/staking/src/offence.rs +++ b/primitives/staking/src/offence.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/state-machine/src/backend.rs b/primitives/state-machine/src/backend.rs index 8a6ed4d3dba8..cde5011ce2d8 100644 --- a/primitives/state-machine/src/backend.rs +++ b/primitives/state-machine/src/backend.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/state-machine/src/basic.rs b/primitives/state-machine/src/basic.rs index c0bec8d08f00..1f257550fbf7 100644 --- a/primitives/state-machine/src/basic.rs +++ b/primitives/state-machine/src/basic.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/state-machine/src/error.rs b/primitives/state-machine/src/error.rs index acc5b6080c7a..a12b3eae71bd 100644 --- a/primitives/state-machine/src/error.rs +++ b/primitives/state-machine/src/error.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/state-machine/src/ext.rs b/primitives/state-machine/src/ext.rs index f5158acbc74d..93e6ac6e5c53 100644 --- a/primitives/state-machine/src/ext.rs +++ b/primitives/state-machine/src/ext.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/state-machine/src/in_memory_backend.rs b/primitives/state-machine/src/in_memory_backend.rs index f4ae0d01d5fb..4605d07b2ab6 100644 --- a/primitives/state-machine/src/in_memory_backend.rs +++ b/primitives/state-machine/src/in_memory_backend.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/state-machine/src/lib.rs b/primitives/state-machine/src/lib.rs index dff499981634..1a69d51d58ab 100644 --- a/primitives/state-machine/src/lib.rs +++ b/primitives/state-machine/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/state-machine/src/overlayed_changes/changeset.rs b/primitives/state-machine/src/overlayed_changes/changeset.rs index 818b7be99bc6..9e7f6ffeddfd 100644 --- a/primitives/state-machine/src/overlayed_changes/changeset.rs +++ b/primitives/state-machine/src/overlayed_changes/changeset.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/state-machine/src/overlayed_changes/mod.rs b/primitives/state-machine/src/overlayed_changes/mod.rs index 659b52e0a708..89bbb063ef9a 100644 --- a/primitives/state-machine/src/overlayed_changes/mod.rs +++ b/primitives/state-machine/src/overlayed_changes/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/state-machine/src/overlayed_changes/offchain.rs b/primitives/state-machine/src/overlayed_changes/offchain.rs index ac67ca330300..98457700013a 100644 --- a/primitives/state-machine/src/overlayed_changes/offchain.rs +++ b/primitives/state-machine/src/overlayed_changes/offchain.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/state-machine/src/proving_backend.rs b/primitives/state-machine/src/proving_backend.rs index 4e1fd64da2b8..934f08492dee 100644 --- a/primitives/state-machine/src/proving_backend.rs +++ b/primitives/state-machine/src/proving_backend.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/state-machine/src/read_only.rs b/primitives/state-machine/src/read_only.rs index 2039b39a0603..3c3e779c32f3 100644 --- a/primitives/state-machine/src/read_only.rs +++ b/primitives/state-machine/src/read_only.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/state-machine/src/stats.rs b/primitives/state-machine/src/stats.rs index affd71f9d2e5..863ea5cfed7e 100644 --- a/primitives/state-machine/src/stats.rs +++ b/primitives/state-machine/src/stats.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/state-machine/src/testing.rs b/primitives/state-machine/src/testing.rs index dbb0a25d3c39..e21644614c83 100644 --- a/primitives/state-machine/src/testing.rs +++ b/primitives/state-machine/src/testing.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/state-machine/src/trie_backend.rs b/primitives/state-machine/src/trie_backend.rs index 616a5512ea40..37db59416f10 100644 --- a/primitives/state-machine/src/trie_backend.rs +++ b/primitives/state-machine/src/trie_backend.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/state-machine/src/trie_backend_essence.rs b/primitives/state-machine/src/trie_backend_essence.rs index 945fd05ebffb..8f3c27f03c74 100644 --- a/primitives/state-machine/src/trie_backend_essence.rs +++ b/primitives/state-machine/src/trie_backend_essence.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/std/src/lib.rs b/primitives/std/src/lib.rs index 3d112a18edd0..6a59dcbe4929 100644 --- a/primitives/std/src/lib.rs +++ b/primitives/std/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/std/with_std.rs b/primitives/std/with_std.rs index 8a283e8fe333..b5fa3f85ed70 100644 --- a/primitives/std/with_std.rs +++ b/primitives/std/with_std.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/std/without_std.rs b/primitives/std/without_std.rs index 38c3a8421dac..7a6d5851dfac 100755 --- a/primitives/std/without_std.rs +++ b/primitives/std/without_std.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/storage/src/lib.rs b/primitives/storage/src/lib.rs index eff74c4aac0b..1e97454b2605 100644 --- a/primitives/storage/src/lib.rs +++ b/primitives/storage/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/tasks/src/async_externalities.rs b/primitives/tasks/src/async_externalities.rs index 9f2fec299f59..70e3437538e8 100644 --- a/primitives/tasks/src/async_externalities.rs +++ b/primitives/tasks/src/async_externalities.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/primitives/tasks/src/lib.rs b/primitives/tasks/src/lib.rs index c874bb98e1ae..3711fa71a2fa 100644 --- a/primitives/tasks/src/lib.rs +++ b/primitives/tasks/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/test-primitives/src/lib.rs b/primitives/test-primitives/src/lib.rs index 341839a1deb2..976bb9ddd9cd 100644 --- a/primitives/test-primitives/src/lib.rs +++ b/primitives/test-primitives/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/timestamp/src/lib.rs b/primitives/timestamp/src/lib.rs index 02a579497b52..9155cbd93b6c 100644 --- a/primitives/timestamp/src/lib.rs +++ b/primitives/timestamp/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/tracing/src/lib.rs b/primitives/tracing/src/lib.rs index 9522e6df633a..4cabbbaba6ec 100644 --- a/primitives/tracing/src/lib.rs +++ b/primitives/tracing/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/tracing/src/types.rs b/primitives/tracing/src/types.rs index 377bd0f42c6e..d175e1f8f17e 100644 --- a/primitives/tracing/src/types.rs +++ b/primitives/tracing/src/types.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/transaction-pool/src/lib.rs b/primitives/transaction-pool/src/lib.rs index 3c71149255ce..143958f06d16 100644 --- a/primitives/transaction-pool/src/lib.rs +++ b/primitives/transaction-pool/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/transaction-pool/src/runtime_api.rs b/primitives/transaction-pool/src/runtime_api.rs index be631ee03b9d..87a0c82e9133 100644 --- a/primitives/transaction-pool/src/runtime_api.rs +++ b/primitives/transaction-pool/src/runtime_api.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/transaction-storage-proof/src/lib.rs b/primitives/transaction-storage-proof/src/lib.rs index f76ae7faac08..bdfe16683ebc 100644 --- a/primitives/transaction-storage-proof/src/lib.rs +++ b/primitives/transaction-storage-proof/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/trie/benches/bench.rs b/primitives/trie/benches/bench.rs index d78ceadff728..f1670b0c2fa4 100644 --- a/primitives/trie/benches/bench.rs +++ b/primitives/trie/benches/bench.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2015-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2015-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/trie/src/error.rs b/primitives/trie/src/error.rs index 30a164c61475..b43412ebc7dc 100644 --- a/primitives/trie/src/error.rs +++ b/primitives/trie/src/error.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2015-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2015-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/trie/src/lib.rs b/primitives/trie/src/lib.rs index 399484143dbc..ffaee2037d1c 100644 --- a/primitives/trie/src/lib.rs +++ b/primitives/trie/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2015-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2015-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/trie/src/node_codec.rs b/primitives/trie/src/node_codec.rs index 53a5de270a79..4aaed2ec7e4e 100644 --- a/primitives/trie/src/node_codec.rs +++ b/primitives/trie/src/node_codec.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2015-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2015-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/trie/src/node_header.rs b/primitives/trie/src/node_header.rs index 895713ffd1f8..c2c9510c5ac4 100644 --- a/primitives/trie/src/node_header.rs +++ b/primitives/trie/src/node_header.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2015-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2015-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/trie/src/storage_proof.rs b/primitives/trie/src/storage_proof.rs index cd65fa5b26f2..8caae06d390c 100644 --- a/primitives/trie/src/storage_proof.rs +++ b/primitives/trie/src/storage_proof.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/trie/src/trie_codec.rs b/primitives/trie/src/trie_codec.rs index f485ee13e332..62edc82e4c54 100644 --- a/primitives/trie/src/trie_codec.rs +++ b/primitives/trie/src/trie_codec.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/trie/src/trie_stream.rs b/primitives/trie/src/trie_stream.rs index 20f607c840d3..7a5c7d003e03 100644 --- a/primitives/trie/src/trie_stream.rs +++ b/primitives/trie/src/trie_stream.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2015-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2015-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/version/proc-macro/src/decl_runtime_version.rs b/primitives/version/proc-macro/src/decl_runtime_version.rs index 7fcb716bbf60..9ca1a67cc7fd 100644 --- a/primitives/version/proc-macro/src/decl_runtime_version.rs +++ b/primitives/version/proc-macro/src/decl_runtime_version.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/version/proc-macro/src/lib.rs b/primitives/version/proc-macro/src/lib.rs index 9a6d4d60bbf9..8be18b15868f 100644 --- a/primitives/version/proc-macro/src/lib.rs +++ b/primitives/version/proc-macro/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/version/src/embed.rs b/primitives/version/src/embed.rs index 452762dcf687..e6b468e2e58c 100644 --- a/primitives/version/src/embed.rs +++ b/primitives/version/src/embed.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/version/src/lib.rs b/primitives/version/src/lib.rs index 74251aa4320f..46f8af9e22c5 100644 --- a/primitives/version/src/lib.rs +++ b/primitives/version/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/wasm-interface/src/lib.rs b/primitives/wasm-interface/src/lib.rs index 44afaf82ed4c..21dbf9609ecf 100644 --- a/primitives/wasm-interface/src/lib.rs +++ b/primitives/wasm-interface/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/primitives/wasm-interface/src/wasmi_impl.rs b/primitives/wasm-interface/src/wasmi_impl.rs index f7e0ec6f16d4..39afce4df4eb 100644 --- a/primitives/wasm-interface/src/wasmi_impl.rs +++ b/primitives/wasm-interface/src/wasmi_impl.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/test-utils/client/src/client_ext.rs b/test-utils/client/src/client_ext.rs index 72828fdcc918..f2b99a5b355f 100644 --- a/test-utils/client/src/client_ext.rs +++ b/test-utils/client/src/client_ext.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/test-utils/client/src/lib.rs b/test-utils/client/src/lib.rs index 6ba28d8c124f..277965655882 100644 --- a/test-utils/client/src/lib.rs +++ b/test-utils/client/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/test-utils/derive/src/lib.rs b/test-utils/derive/src/lib.rs index 3f14f67477fa..06b7d2463cbd 100644 --- a/test-utils/derive/src/lib.rs +++ b/test-utils/derive/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/test-utils/runtime/build.rs b/test-utils/runtime/build.rs index 50c455b4ad83..5a7b518d0bd7 100644 --- a/test-utils/runtime/build.rs +++ b/test-utils/runtime/build.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/test-utils/runtime/client/src/block_builder_ext.rs b/test-utils/runtime/client/src/block_builder_ext.rs index 4519dce65960..66b0b4c3b881 100644 --- a/test-utils/runtime/client/src/block_builder_ext.rs +++ b/test-utils/runtime/client/src/block_builder_ext.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/test-utils/runtime/client/src/lib.rs b/test-utils/runtime/client/src/lib.rs index d5c8a4fcb8a4..fe0fef351667 100644 --- a/test-utils/runtime/client/src/lib.rs +++ b/test-utils/runtime/client/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/test-utils/runtime/client/src/trait_tests.rs b/test-utils/runtime/client/src/trait_tests.rs index 938aeda36d31..65aa3e65e614 100644 --- a/test-utils/runtime/client/src/trait_tests.rs +++ b/test-utils/runtime/client/src/trait_tests.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/test-utils/runtime/src/genesismap.rs b/test-utils/runtime/src/genesismap.rs index b81ed91ca6df..71118b4183ef 100644 --- a/test-utils/runtime/src/genesismap.rs +++ b/test-utils/runtime/src/genesismap.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/test-utils/runtime/src/lib.rs b/test-utils/runtime/src/lib.rs index bf224b43946c..c6112db2374e 100644 --- a/test-utils/runtime/src/lib.rs +++ b/test-utils/runtime/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/test-utils/runtime/src/system.rs b/test-utils/runtime/src/system.rs index 57eae0aecf04..9f8612b69f33 100644 --- a/test-utils/runtime/src/system.rs +++ b/test-utils/runtime/src/system.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/test-utils/runtime/transaction-pool/src/lib.rs b/test-utils/runtime/transaction-pool/src/lib.rs index e80c24b17144..d43347bdcb6e 100644 --- a/test-utils/runtime/transaction-pool/src/lib.rs +++ b/test-utils/runtime/transaction-pool/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/test-utils/src/lib.rs b/test-utils/src/lib.rs index b68994926533..643985940792 100644 --- a/test-utils/src/lib.rs +++ b/test-utils/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/test-utils/test-crate/src/main.rs b/test-utils/test-crate/src/main.rs index 554adcb88406..4696e71779c1 100644 --- a/test-utils/test-crate/src/main.rs +++ b/test-utils/test-crate/src/main.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/test-utils/test-runner/src/client.rs b/test-utils/test-runner/src/client.rs index b4a82b1c8950..3fa3de3a87e0 100644 --- a/test-utils/test-runner/src/client.rs +++ b/test-utils/test-runner/src/client.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 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 diff --git a/test-utils/test-runner/src/host_functions.rs b/test-utils/test-runner/src/host_functions.rs index 6d9fa3534b34..8bc9597890d0 100644 --- a/test-utils/test-runner/src/host_functions.rs +++ b/test-utils/test-runner/src/host_functions.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 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 diff --git a/test-utils/test-runner/src/lib.rs b/test-utils/test-runner/src/lib.rs index d5e2873fe412..19e437e26da4 100644 --- a/test-utils/test-runner/src/lib.rs +++ b/test-utils/test-runner/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 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 diff --git a/test-utils/test-runner/src/node.rs b/test-utils/test-runner/src/node.rs index 421a4b641b59..f122e48d5392 100644 --- a/test-utils/test-runner/src/node.rs +++ b/test-utils/test-runner/src/node.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 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 diff --git a/test-utils/test-runner/src/utils.rs b/test-utils/test-runner/src/utils.rs index 4b44d12e1ed4..452dc600e4ae 100644 --- a/test-utils/test-runner/src/utils.rs +++ b/test-utils/test-runner/src/utils.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/test-utils/tests/basic.rs b/test-utils/tests/basic.rs index 527ca3e365ed..4daca836c7fd 100644 --- a/test-utils/tests/basic.rs +++ b/test-utils/tests/basic.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/test-utils/tests/ui.rs b/test-utils/tests/ui.rs index 119162fdc21b..be3b9c111b3e 100644 --- a/test-utils/tests/ui.rs +++ b/test-utils/tests/ui.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/test-utils/tests/ui/too-many-func-parameters.rs b/test-utils/tests/ui/too-many-func-parameters.rs index b1789b9d3ee7..51059f37ab62 100644 --- a/test-utils/tests/ui/too-many-func-parameters.rs +++ b/test-utils/tests/ui/too-many-func-parameters.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 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 diff --git a/utils/build-script-utils/src/git.rs b/utils/build-script-utils/src/git.rs index 66a15737f84c..db9a4b291ffd 100644 --- a/utils/build-script-utils/src/git.rs +++ b/utils/build-script-utils/src/git.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/utils/build-script-utils/src/lib.rs b/utils/build-script-utils/src/lib.rs index 0c45c4b34ebe..7e69f2ac85d4 100644 --- a/utils/build-script-utils/src/lib.rs +++ b/utils/build-script-utils/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/utils/build-script-utils/src/version.rs b/utils/build-script-utils/src/version.rs index 52336eb0b6a2..e4f1be93cbcc 100644 --- a/utils/build-script-utils/src/version.rs +++ b/utils/build-script-utils/src/version.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/utils/fork-tree/src/lib.rs b/utils/fork-tree/src/lib.rs index 9143da89a77e..a718ff26213e 100644 --- a/utils/fork-tree/src/lib.rs +++ b/utils/fork-tree/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/utils/frame/benchmarking-cli/src/command.rs b/utils/frame/benchmarking-cli/src/command.rs index 2a0429b27908..94e1e0c8c1b8 100644 --- a/utils/frame/benchmarking-cli/src/command.rs +++ b/utils/frame/benchmarking-cli/src/command.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/utils/frame/benchmarking-cli/src/lib.rs b/utils/frame/benchmarking-cli/src/lib.rs index 316ddfb8d0c1..c331dea34c47 100644 --- a/utils/frame/benchmarking-cli/src/lib.rs +++ b/utils/frame/benchmarking-cli/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/utils/frame/benchmarking-cli/src/writer.rs b/utils/frame/benchmarking-cli/src/writer.rs index e7e8b42fd8a6..1e31c4e98e56 100644 --- a/utils/frame/benchmarking-cli/src/writer.rs +++ b/utils/frame/benchmarking-cli/src/writer.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/utils/frame/frame-utilities-cli/src/lib.rs b/utils/frame/frame-utilities-cli/src/lib.rs index 4f5b1da5766a..9a18d39263c9 100644 --- a/utils/frame/frame-utilities-cli/src/lib.rs +++ b/utils/frame/frame-utilities-cli/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/utils/frame/frame-utilities-cli/src/pallet_id.rs b/utils/frame/frame-utilities-cli/src/pallet_id.rs index e4acdb2182f0..2e139c639fd4 100644 --- a/utils/frame/frame-utilities-cli/src/pallet_id.rs +++ b/utils/frame/frame-utilities-cli/src/pallet_id.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/utils/frame/generate-bags/node-runtime/src/main.rs b/utils/frame/generate-bags/node-runtime/src/main.rs index 5d36b381a7d0..72d1f0d8d22b 100644 --- a/utils/frame/generate-bags/node-runtime/src/main.rs +++ b/utils/frame/generate-bags/node-runtime/src/main.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/utils/frame/generate-bags/src/lib.rs b/utils/frame/generate-bags/src/lib.rs index 29afb9da395a..d4507c3be33e 100644 --- a/utils/frame/generate-bags/src/lib.rs +++ b/utils/frame/generate-bags/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/utils/frame/remote-externalities/src/lib.rs b/utils/frame/remote-externalities/src/lib.rs index 1b61f0711406..16aa60db1841 100644 --- a/utils/frame/remote-externalities/src/lib.rs +++ b/utils/frame/remote-externalities/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/utils/frame/remote-externalities/src/rpc_api.rs b/utils/frame/remote-externalities/src/rpc_api.rs index 024cbad3ca55..13254741c1ac 100644 --- a/utils/frame/remote-externalities/src/rpc_api.rs +++ b/utils/frame/remote-externalities/src/rpc_api.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/utils/frame/rpc/support/src/lib.rs b/utils/frame/rpc/support/src/lib.rs index 1b2453c361d9..9cf99ddf97b0 100644 --- a/utils/frame/rpc/support/src/lib.rs +++ b/utils/frame/rpc/support/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/utils/frame/rpc/system/src/lib.rs b/utils/frame/rpc/system/src/lib.rs index 41a5f3ba0eb3..df24e208b51a 100644 --- a/utils/frame/rpc/system/src/lib.rs +++ b/utils/frame/rpc/system/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/utils/frame/try-runtime/cli/src/commands/execute_block.rs b/utils/frame/try-runtime/cli/src/commands/execute_block.rs index f092f6eaf471..68c33b17b99d 100644 --- a/utils/frame/try-runtime/cli/src/commands/execute_block.rs +++ b/utils/frame/try-runtime/cli/src/commands/execute_block.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/utils/frame/try-runtime/cli/src/commands/follow_chain.rs b/utils/frame/try-runtime/cli/src/commands/follow_chain.rs index dbc1c3005f06..445756f9eed9 100644 --- a/utils/frame/try-runtime/cli/src/commands/follow_chain.rs +++ b/utils/frame/try-runtime/cli/src/commands/follow_chain.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/utils/frame/try-runtime/cli/src/commands/mod.rs b/utils/frame/try-runtime/cli/src/commands/mod.rs index bfd8290fb31c..4861d94f077c 100644 --- a/utils/frame/try-runtime/cli/src/commands/mod.rs +++ b/utils/frame/try-runtime/cli/src/commands/mod.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/utils/frame/try-runtime/cli/src/commands/offchain_worker.rs b/utils/frame/try-runtime/cli/src/commands/offchain_worker.rs index 8839c5556900..47af85560398 100644 --- a/utils/frame/try-runtime/cli/src/commands/offchain_worker.rs +++ b/utils/frame/try-runtime/cli/src/commands/offchain_worker.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/utils/frame/try-runtime/cli/src/commands/on_runtime_upgrade.rs b/utils/frame/try-runtime/cli/src/commands/on_runtime_upgrade.rs index 3b5a3db72a8f..30e638217448 100644 --- a/utils/frame/try-runtime/cli/src/commands/on_runtime_upgrade.rs +++ b/utils/frame/try-runtime/cli/src/commands/on_runtime_upgrade.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/utils/frame/try-runtime/cli/src/lib.rs b/utils/frame/try-runtime/cli/src/lib.rs index 9f8af6906a35..2cd0a18909c1 100644 --- a/utils/frame/try-runtime/cli/src/lib.rs +++ b/utils/frame/try-runtime/cli/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/utils/frame/try-runtime/cli/src/parse.rs b/utils/frame/try-runtime/cli/src/parse.rs index 7f205fbacd31..a12e37344c7a 100644 --- a/utils/frame/try-runtime/cli/src/parse.rs +++ b/utils/frame/try-runtime/cli/src/parse.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/utils/prometheus/src/lib.rs b/utils/prometheus/src/lib.rs index f81b82cb1764..f1d87ac9f729 100644 --- a/utils/prometheus/src/lib.rs +++ b/utils/prometheus/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/utils/prometheus/src/networking.rs b/utils/prometheus/src/networking.rs index a24216bd2362..fda20b75740b 100644 --- a/utils/prometheus/src/networking.rs +++ b/utils/prometheus/src/networking.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/utils/prometheus/src/sourced.rs b/utils/prometheus/src/sourced.rs index ca37eef021f6..9f52d1eff47c 100644 --- a/utils/prometheus/src/sourced.rs +++ b/utils/prometheus/src/sourced.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/utils/wasm-builder/src/builder.rs b/utils/wasm-builder/src/builder.rs index 113b5eb068da..81a869396818 100644 --- a/utils/wasm-builder/src/builder.rs +++ b/utils/wasm-builder/src/builder.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/utils/wasm-builder/src/lib.rs b/utils/wasm-builder/src/lib.rs index b13ecc4e4ab3..899903d96d16 100644 --- a/utils/wasm-builder/src/lib.rs +++ b/utils/wasm-builder/src/lib.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/utils/wasm-builder/src/prerequisites.rs b/utils/wasm-builder/src/prerequisites.rs index 88b1073a2951..fb04dc3c98fb 100644 --- a/utils/wasm-builder/src/prerequisites.rs +++ b/utils/wasm-builder/src/prerequisites.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/utils/wasm-builder/src/wasm_project.rs b/utils/wasm-builder/src/wasm_project.rs index 59214ab483c6..cf437ee7f0e6 100644 --- a/utils/wasm-builder/src/wasm_project.rs +++ b/utils/wasm-builder/src/wasm_project.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); From 7b9e14234314b65432459c25da1de1cd11852c71 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Jan 2022 08:46:53 +0000 Subject: [PATCH 344/695] Bump sha2 from 0.9.8 to 0.10.0 (#10547) Bumps [sha2](https://github.com/RustCrypto/hashes) from 0.9.8 to 0.10.0. - [Release notes](https://github.com/RustCrypto/hashes/releases) - [Commits](https://github.com/RustCrypto/hashes/compare/sha2-v0.9.8...sha2-v0.10.0) --- updated-dependencies: - dependency-name: sha2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 44 ++++++++++++++++++++++++++++-- primitives/core/Cargo.toml | 2 +- primitives/core/hashing/Cargo.toml | 2 +- 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e58275738c92..0f78fef7e5d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -694,6 +694,15 @@ dependencies = [ "generic-array 0.14.4", ] +[[package]] +name = "block-buffer" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1d36a02058e76b040de25a4464ba1c80935655595b661505c8b39b664828b95" +dependencies = [ + "generic-array 0.14.4", +] + [[package]] name = "block-padding" version = "0.1.5" @@ -1322,6 +1331,15 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +[[package]] +name = "crypto-common" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d6b536309245c849479fba3da410962a43ed8e51c26b729208ec0ac2798d0" +dependencies = [ + "generic-array 0.14.4", +] + [[package]] name = "crypto-mac" version = "0.8.0" @@ -1533,6 +1551,17 @@ dependencies = [ "generic-array 0.14.4", ] +[[package]] +name = "digest" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b697d66081d42af4fba142d56918a3cb21dc8eb63372c6b85d14f44fb9c5979b" +dependencies = [ + "block-buffer 0.10.0", + "crypto-common", + "generic-array 0.14.4", +] + [[package]] name = "directories" version = "4.0.1" @@ -8990,6 +9019,17 @@ dependencies = [ "opaque-debug 0.3.0", ] +[[package]] +name = "sha2" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900d964dd36bb15bcf2f2b35694c072feab74969a54f2bbeec7a2d725d2bdcb6" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures 0.2.1", + "digest 0.10.1", +] + [[package]] name = "sha3" version = "0.9.1" @@ -9426,7 +9466,7 @@ dependencies = [ "secrecy", "serde", "serde_json", - "sha2 0.9.8", + "sha2 0.10.0", "sp-core-hashing", "sp-core-hashing-proc-macro", "sp-debug-derive", @@ -9451,7 +9491,7 @@ version = "4.0.0" dependencies = [ "blake2-rfc", "byteorder", - "sha2 0.9.8", + "sha2 0.10.0", "sp-std", "tiny-keccak", "twox-hash", diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index 05fc1240e274..c1ca9f081570 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -62,7 +62,7 @@ schnorrkel = { version = "0.9.1", features = [ "preaudit_deprecated", "u64_backend", ], default-features = false, optional = true } -sha2 = { version = "0.9.8", default-features = false, optional = true } +sha2 = { version = "0.10.0", default-features = false, optional = true } hex = { version = "0.4", default-features = false, optional = true } twox-hash = { version = "1.6.1", default-features = false, optional = true } libsecp256k1 = { version = "0.7", default-features = false, features = ["hmac", "static-context"], optional = true } diff --git a/primitives/core/hashing/Cargo.toml b/primitives/core/hashing/Cargo.toml index 23ff01c0b34b..e9f3c8c714f7 100644 --- a/primitives/core/hashing/Cargo.toml +++ b/primitives/core/hashing/Cargo.toml @@ -18,7 +18,7 @@ byteorder = { version = "1.3.2", default-features = false } blake2-rfc = { version = "0.2.18", default-features = false } tiny-keccak = { version = "2.0.1", features = ["keccak"] } -sha2 = { version = "0.9.2", default-features = false } +sha2 = { version = "0.10.0", default-features = false } twox-hash = { version = "1.5.0", default-features = false } [features] From a798e290628030d9fcba9293994f3d66beba44af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Mon, 3 Jan 2022 16:08:42 +0100 Subject: [PATCH 345/695] Remove transaction-pool `test-helpers` feature (#10571) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Remove transaction-pool `test-helpers` feature `test-helpers` feature is a bad idea in general, because once the feature is enabled somewhere in the workspace, it is enabled anywhere. While removing the feature, the tests were also rewritten to get rid off other "only test" related code. Contributes towards: https://github.com/paritytech/substrate/issues/9727 * Apply suggestions from code review Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> * Fix benches Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> --- Cargo.lock | 56 ++---- client/transaction-pool/Cargo.toml | 5 +- client/transaction-pool/benches/basics.rs | 12 +- client/transaction-pool/src/graph/pool.rs | 171 ++-------------- .../src/graph/validated_pool.rs | 6 - client/transaction-pool/src/lib.rs | 25 +-- client/transaction-pool/src/revalidation.rs | 98 +++++----- client/transaction-pool/src/tests.rs | 185 ++++++++++++++++++ client/transaction-pool/tests/pool.rs | 156 +++++++-------- client/transaction-pool/tests/revalidation.rs | 32 --- .../runtime/transaction-pool/Cargo.toml | 2 +- .../runtime/transaction-pool/src/lib.rs | 17 +- 12 files changed, 364 insertions(+), 401 deletions(-) create mode 100644 client/transaction-pool/src/tests.rs delete mode 100644 client/transaction-pool/tests/revalidation.rs diff --git a/Cargo.lock b/Cargo.lock index 0f78fef7e5d6..ba80103c174b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1898,7 +1898,7 @@ checksum = "e8ac3ff5224ef91f3c97e03eb1de2db82743427e91aaa5ac635f454f0b164f5a" dependencies = [ "either", "futures 0.3.16", - "futures-timer 3.0.2", + "futures-timer", "log 0.4.14", "num-traits", "parity-scale-codec", @@ -2391,12 +2391,6 @@ version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ee7c6485c30167ce4dfb83ac568a849fe53274c831081476ee13e0dce1aad72" -[[package]] -name = "futures-timer" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1de7508b218029b0f01662ed8f61b1c964b3ae99d6f25462d0f55a595109df6" - [[package]] name = "futures-timer" version = "3.0.2" @@ -2974,16 +2968,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "intervalier" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64fa110ec7b8f493f416eed552740d10e7030ad5f63b2308f82c9608ec2df275" -dependencies = [ - "futures 0.3.16", - "futures-timer 2.0.2", -] - [[package]] name = "io-lifetimes" version = "0.3.1" @@ -3481,7 +3465,7 @@ dependencies = [ "either", "fnv", "futures 0.3.16", - "futures-timer 3.0.2", + "futures-timer", "lazy_static", "libsecp256k1", "log 0.4.14", @@ -3745,7 +3729,7 @@ dependencies = [ "asynchronous-codec 0.6.0", "bytes 1.1.0", "futures 0.3.16", - "futures-timer 3.0.2", + "futures-timer", "libp2p-core", "libp2p-swarm", "log 0.4.14", @@ -3834,7 +3818,7 @@ checksum = "7399c5b6361ef525d41c11fcf51635724f832baf5819b30d3d873eabb4fbae4b" dependencies = [ "async-io", "futures 0.3.16", - "futures-timer 3.0.2", + "futures-timer", "if-watch", "ipnet", "libc", @@ -7625,7 +7609,7 @@ dependencies = [ "async-trait", "derive_more", "futures 0.3.16", - "futures-timer 3.0.2", + "futures-timer", "ip_network", "libp2p", "log 0.4.14", @@ -7652,7 +7636,7 @@ name = "sc-basic-authorship" version = "0.10.0-dev" dependencies = [ "futures 0.3.16", - "futures-timer 3.0.2", + "futures-timer", "log 0.4.14", "parity-scale-codec", "parking_lot 0.11.2", @@ -7816,7 +7800,7 @@ version = "0.10.0-dev" dependencies = [ "async-trait", "futures 0.3.16", - "futures-timer 3.0.2", + "futures-timer", "libp2p", "log 0.4.14", "parking_lot 0.11.2", @@ -8007,7 +7991,7 @@ dependencies = [ "async-trait", "derive_more", "futures 0.3.16", - "futures-timer 3.0.2", + "futures-timer", "log 0.4.14", "parity-scale-codec", "parking_lot 0.11.2", @@ -8030,7 +8014,7 @@ version = "0.10.0-dev" dependencies = [ "async-trait", "futures 0.3.16", - "futures-timer 3.0.2", + "futures-timer", "log 0.4.14", "parity-scale-codec", "sc-client-api", @@ -8163,7 +8147,7 @@ dependencies = [ "finality-grandpa", "fork-tree", "futures 0.3.16", - "futures-timer 3.0.2", + "futures-timer", "log 0.4.14", "parity-scale-codec", "parking_lot 0.11.2", @@ -8228,7 +8212,7 @@ version = "0.10.0-dev" dependencies = [ "ansi_term", "futures 0.3.16", - "futures-timer 3.0.2", + "futures-timer", "log 0.4.14", "parity-util-mem", "sc-client-api", @@ -8269,7 +8253,7 @@ dependencies = [ "fnv", "fork-tree", "futures 0.3.16", - "futures-timer 3.0.2", + "futures-timer", "hex", "ip_network", "libp2p", @@ -8316,7 +8300,7 @@ version = "0.10.0-dev" dependencies = [ "async-std", "futures 0.3.16", - "futures-timer 3.0.2", + "futures-timer", "libp2p", "log 0.4.14", "lru 0.7.0", @@ -8335,7 +8319,7 @@ dependencies = [ "async-std", "async-trait", "futures 0.3.16", - "futures-timer 3.0.2", + "futures-timer", "libp2p", "log 0.4.14", "parking_lot 0.11.2", @@ -8362,7 +8346,7 @@ dependencies = [ "bytes 1.1.0", "fnv", "futures 0.3.16", - "futures-timer 3.0.2", + "futures-timer", "hex", "hyper 0.14.16", "hyper-rustls", @@ -8512,7 +8496,7 @@ dependencies = [ "directories", "exit-future", "futures 0.3.16", - "futures-timer 3.0.2", + "futures-timer", "hash-db", "jsonrpc-core", "jsonrpc-pubsub", @@ -8704,8 +8688,8 @@ dependencies = [ "assert_matches", "criterion", "futures 0.3.16", + "futures-timer", "hex", - "intervalier", "linked-hash-map", "log 0.4.14", "parity-scale-codec", @@ -8749,7 +8733,7 @@ name = "sc-utils" version = "4.0.0-dev" dependencies = [ "futures 0.3.16", - "futures-timer 3.0.2", + "futures-timer", "lazy_static", "prometheus", ] @@ -9348,7 +9332,7 @@ version = "0.10.0-dev" dependencies = [ "async-trait", "futures 0.3.16", - "futures-timer 3.0.2", + "futures-timer", "log 0.4.14", "parity-scale-codec", "sp-core", @@ -9910,7 +9894,7 @@ name = "sp-timestamp" version = "4.0.0-dev" dependencies = [ "async-trait", - "futures-timer 3.0.2", + "futures-timer", "log 0.4.14", "parity-scale-codec", "sp-api", diff --git a/client/transaction-pool/Cargo.toml b/client/transaction-pool/Cargo.toml index 43a368145a93..a98dfac620c1 100644 --- a/client/transaction-pool/Cargo.toml +++ b/client/transaction-pool/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0" } thiserror = "1.0.30" futures = "0.3.16" -intervalier = "0.4.0" +futures-timer = "3.0.2" log = "0.4.8" parity-util-mem = { version = "0.10.2", default-features = false, features = ["primitive-types"] } parking_lot = "0.11.2" @@ -48,6 +48,3 @@ criterion = "0.3" [[bench]] name = "basics" harness = false - -[features] -test-helpers = [] diff --git a/client/transaction-pool/benches/basics.rs b/client/transaction-pool/benches/basics.rs index c6b15ce4f177..c3577a45faf0 100644 --- a/client/transaction-pool/benches/basics.rs +++ b/client/transaction-pool/benches/basics.rs @@ -23,11 +23,11 @@ use futures::{ executor::block_on, future::{ready, Ready}, }; -use sc_transaction_pool::{test_helpers::*, *}; +use sc_transaction_pool::*; use sp_core::blake2_256; use sp_runtime::{ generic::BlockId, - traits::Block as BlockT, + traits::{Block as BlockT, NumberFor}, transaction_validity::{ InvalidTransaction, TransactionSource, TransactionTag as Tag, TransactionValidity, ValidTransaction, @@ -63,7 +63,7 @@ impl ChainApi for TestApi { &self, at: &BlockId, _source: TransactionSource, - uxt: test_helpers::ExtrinsicFor, + uxt: ::Extrinsic, ) -> Self::ValidationFuture { let nonce = uxt.transfer().nonce; let from = uxt.transfer().from.clone(); @@ -89,7 +89,7 @@ impl ChainApi for TestApi { fn block_id_to_number( &self, at: &BlockId, - ) -> Result>, Self::Error> { + ) -> Result>, Self::Error> { Ok(match at { BlockId::Number(num) => Some(*num), BlockId::Hash(_) => None, @@ -99,14 +99,14 @@ impl ChainApi for TestApi { fn block_id_to_hash( &self, at: &BlockId, - ) -> Result>, Self::Error> { + ) -> Result::Hash>, Self::Error> { Ok(match at { BlockId::Number(num) => Some(H256::from_low_u64_be(*num)).into(), BlockId::Hash(_) => None, }) } - fn hash_and_length(&self, uxt: &test_helpers::ExtrinsicFor) -> (H256, usize) { + fn hash_and_length(&self, uxt: &::Extrinsic) -> (H256, usize) { let encoded = uxt.encode(); (blake2_256(&encoded).into(), encoded.len()) } diff --git a/client/transaction-pool/src/graph/pool.rs b/client/transaction-pool/src/graph/pool.rs index 3d0f8a017a97..909ea559f552 100644 --- a/client/transaction-pool/src/graph/pool.rs +++ b/client/transaction-pool/src/graph/pool.rs @@ -444,163 +444,16 @@ impl Clone for Pool { #[cfg(test)] mod tests { use super::{super::base_pool::Limit, *}; + use crate::tests::{pool, uxt, TestApi, INVALID_NONCE}; use assert_matches::assert_matches; - use codec::Encode; use futures::executor::block_on; use parking_lot::Mutex; use sc_transaction_pool_api::TransactionStatus; - use sp_runtime::{ - traits::Hash, - transaction_validity::{InvalidTransaction, TransactionSource, ValidTransaction}, - }; - use std::{ - collections::{HashMap, HashSet}, - time::Instant, - }; - use substrate_test_runtime::{AccountId, Block, Extrinsic, Hashing, Transfer, H256}; - - const INVALID_NONCE: u64 = 254; - const SOURCE: TransactionSource = TransactionSource::External; - - #[derive(Clone, Debug, Default)] - struct TestApi { - delay: Arc>>>, - invalidate: Arc>>, - clear_requirements: Arc>>, - add_requirements: Arc>>, - } - - impl ChainApi for TestApi { - type Block = Block; - type Error = error::Error; - type ValidationFuture = futures::future::Ready>; - type BodyFuture = futures::future::Ready>>>; - - /// Verify extrinsic at given block. - fn validate_transaction( - &self, - at: &BlockId, - _source: TransactionSource, - uxt: ExtrinsicFor, - ) -> Self::ValidationFuture { - let hash = self.hash_and_length(&uxt).0; - let block_number = self.block_id_to_number(at).unwrap().unwrap(); - - let res = match uxt { - Extrinsic::Transfer { transfer, .. } => { - let nonce = transfer.nonce; - - // This is used to control the test flow. - if nonce > 0 { - let opt = self.delay.lock().take(); - if let Some(delay) = opt { - if delay.recv().is_err() { - println!("Error waiting for delay!"); - } - } - } - - if self.invalidate.lock().contains(&hash) { - InvalidTransaction::Custom(0).into() - } else if nonce < block_number { - InvalidTransaction::Stale.into() - } else { - let mut transaction = ValidTransaction { - priority: 4, - requires: if nonce > block_number { - vec![vec![nonce as u8 - 1]] - } else { - vec![] - }, - provides: if nonce == INVALID_NONCE { - vec![] - } else { - vec![vec![nonce as u8]] - }, - longevity: 3, - propagate: true, - }; - - if self.clear_requirements.lock().contains(&hash) { - transaction.requires.clear(); - } - - if self.add_requirements.lock().contains(&hash) { - transaction.requires.push(vec![128]); - } - - Ok(transaction) - } - }, - Extrinsic::IncludeData(_) => Ok(ValidTransaction { - priority: 9001, - requires: vec![], - provides: vec![vec![42]], - longevity: 9001, - propagate: false, - }), - Extrinsic::Store(_) => Ok(ValidTransaction { - priority: 9001, - requires: vec![], - provides: vec![vec![43]], - longevity: 9001, - propagate: false, - }), - _ => unimplemented!(), - }; - - futures::future::ready(Ok(res)) - } - - /// Returns a block number given the block id. - fn block_id_to_number( - &self, - at: &BlockId, - ) -> Result>, Self::Error> { - Ok(match at { - BlockId::Number(num) => Some(*num), - BlockId::Hash(_) => None, - }) - } + use sp_runtime::transaction_validity::TransactionSource; + use std::{collections::HashMap, time::Instant}; + use substrate_test_runtime::{AccountId, Extrinsic, Transfer, H256}; - /// Returns a block hash given the block id. - fn block_id_to_hash( - &self, - at: &BlockId, - ) -> Result::Hash>, Self::Error> { - Ok(match at { - BlockId::Number(num) => Some(H256::from_low_u64_be(*num)).into(), - BlockId::Hash(_) => None, - }) - } - - /// Hash the extrinsic. - fn hash_and_length(&self, uxt: &ExtrinsicFor) -> (BlockHash, usize) { - let encoded = uxt.encode(); - let len = encoded.len(); - (Hashing::hash(&encoded), len) - } - - fn block_body(&self, _id: &BlockId) -> Self::BodyFuture { - futures::future::ready(Ok(None)) - } - - fn block_header( - &self, - _: &BlockId, - ) -> Result::Header>, Self::Error> { - Ok(None) - } - } - - fn uxt(transfer: Transfer) -> Extrinsic { - let signature = TryFrom::try_from(&[0; 64][..]).unwrap(); - Extrinsic::Transfer { transfer, signature, exhaust_resources_when_not_first: false } - } - - fn pool() -> Pool { - Pool::new(Default::default(), true.into(), TestApi::default().into()) - } + const SOURCE: TransactionSource = TransactionSource::External; #[test] fn should_validate_and_import_transaction() { @@ -636,7 +489,7 @@ mod tests { }); // when - pool.validated_pool.rotator().ban(&Instant::now(), vec![pool.hash_of(&uxt)]); + pool.validated_pool.ban(&Instant::now(), vec![pool.hash_of(&uxt)]); let res = block_on(pool.submit_one(&BlockId::Number(0), SOURCE, uxt)); assert_eq!(pool.validated_pool().status().ready, 0); assert_eq!(pool.validated_pool().status().future, 0); @@ -767,9 +620,9 @@ mod tests { assert_eq!(pool.validated_pool().status().future, 0); assert_eq!(pool.validated_pool().status().ready, 0); // make sure they are temporarily banned as well - assert!(pool.validated_pool.rotator().is_banned(&hash1)); - assert!(pool.validated_pool.rotator().is_banned(&hash2)); - assert!(pool.validated_pool.rotator().is_banned(&hash3)); + assert!(pool.validated_pool.is_banned(&hash1)); + assert!(pool.validated_pool.is_banned(&hash2)); + assert!(pool.validated_pool.is_banned(&hash3)); } #[test] @@ -792,7 +645,7 @@ mod tests { block_on(pool.prune_tags(&BlockId::Number(1), vec![vec![0]], vec![hash1.clone()])).unwrap(); // then - assert!(pool.validated_pool.rotator().is_banned(&hash1)); + assert!(pool.validated_pool.is_banned(&hash1)); } #[test] @@ -832,8 +685,8 @@ mod tests { // then assert_eq!(pool.validated_pool().status().future, 1); - assert!(pool.validated_pool.rotator().is_banned(&hash1)); - assert!(!pool.validated_pool.rotator().is_banned(&hash2)); + assert!(pool.validated_pool.is_banned(&hash1)); + assert!(!pool.validated_pool.is_banned(&hash2)); } #[test] diff --git a/client/transaction-pool/src/graph/validated_pool.rs b/client/transaction-pool/src/graph/validated_pool.rs index 137c7298f515..7e19941b2568 100644 --- a/client/transaction-pool/src/graph/validated_pool.rs +++ b/client/transaction-pool/src/graph/validated_pool.rs @@ -569,12 +569,6 @@ impl ValidatedPool { Ok(()) } - /// Get rotator reference. - #[cfg(feature = "test-helpers")] - pub fn rotator(&self) -> &PoolRotator> { - &self.rotator - } - /// Get api reference. pub fn api(&self) -> &B { &self.api diff --git a/client/transaction-pool/src/lib.rs b/client/transaction-pool/src/lib.rs index 065c83be3bfc..2d07815e4baa 100644 --- a/client/transaction-pool/src/lib.rs +++ b/client/transaction-pool/src/lib.rs @@ -23,20 +23,12 @@ #![warn(unused_extern_crates)] mod api; +pub mod error; mod graph; mod metrics; mod revalidation; - -pub mod error; - -/// Common types for testing the transaction pool -#[cfg(feature = "test-helpers")] -pub mod test_helpers { - pub use super::{ - graph::{BlockHash, ChainApi, ExtrinsicFor, NumberFor, Pool}, - revalidation::RevalidationQueue, - }; -} +#[cfg(test)] +mod tests; pub use crate::api::FullChainApi; use futures::{ @@ -170,13 +162,10 @@ where PoolApi: graph::ChainApi + 'static, { /// Create new basic transaction pool with provided api, for tests. - #[cfg(feature = "test-helpers")] - pub fn new_test( - pool_api: Arc, - ) -> (Self, Pin + Send>>, intervalier::BackSignalControl) { + pub fn new_test(pool_api: Arc) -> (Self, Pin + Send>>) { let pool = Arc::new(graph::Pool::new(Default::default(), true.into(), pool_api.clone())); - let (revalidation_queue, background_task, notifier) = - revalidation::RevalidationQueue::new_test(pool_api.clone(), pool.clone()); + let (revalidation_queue, background_task) = + revalidation::RevalidationQueue::new_background(pool_api.clone(), pool.clone()); ( Self { api: pool_api, @@ -187,7 +176,6 @@ where metrics: Default::default(), }, background_task, - notifier, ) } @@ -237,7 +225,6 @@ where } /// Get access to the underlying api - #[cfg(feature = "test-helpers")] pub fn api(&self) -> &PoolApi { &self.api } diff --git a/client/transaction-pool/src/revalidation.rs b/client/transaction-pool/src/revalidation.rs index 6b6ed858e7ec..22b526e9dfc6 100644 --- a/client/transaction-pool/src/revalidation.rs +++ b/client/transaction-pool/src/revalidation.rs @@ -35,10 +35,7 @@ use sp_runtime::{ use futures::prelude::*; use std::time::Duration; -#[cfg(not(feature = "test-helpers"))] const BACKGROUND_REVALIDATION_INTERVAL: Duration = Duration::from_millis(200); -#[cfg(feature = "test-helpers")] -pub const BACKGROUND_REVALIDATION_INTERVAL: Duration = Duration::from_millis(1); const MIN_BACKGROUND_REVALIDATION_BATCH_SIZE: usize = 20; @@ -213,36 +210,25 @@ impl RevalidationWorker { /// It does two things: periodically tries to process some transactions /// from the queue and also accepts messages to enqueue some more /// transactions from the pool. - pub async fn run( + pub async fn run( mut self, from_queue: TracingUnboundedReceiver>, - interval: R, - ) where - R: Send, - R::Guard: Send, - { - let interval = interval.into_stream().fuse(); + interval: Duration, + ) { + let interval_fut = futures_timer::Delay::new(interval); let from_queue = from_queue.fuse(); - futures::pin_mut!(interval, from_queue); + futures::pin_mut!(interval_fut, from_queue); let this = &mut self; loop { futures::select! { - _guard = interval.next() => { + // Using `fuse()` in here is okay, because we reset the interval when it has fired. + _ = (&mut interval_fut).fuse() => { let next_batch = this.prepare_batch(); let batch_len = next_batch.len(); batch_revalidate(this.pool.clone(), this.api.clone(), this.best_block, next_batch).await; - #[cfg(feature = "test-helpers")] - { - use intervalier::Guard; - // only trigger test events if something was processed - if batch_len == 0 { - _guard.expect("Always some() in tests").skip(); - } - } - if batch_len > 0 || this.len() > 0 { log::debug!( target: "txpool", @@ -251,6 +237,8 @@ impl RevalidationWorker { this.len(), ); } + + interval_fut.reset(interval); }, workload = from_queue.next() => { match workload { @@ -298,15 +286,11 @@ where } /// New revalidation queue with background worker. - pub fn new_with_interval( + pub fn new_with_interval( api: Arc, pool: Arc>, - interval: R, - ) -> (Self, Pin + Send>>) - where - R: Send + 'static, - R::Guard: Send, - { + interval: Duration, + ) -> (Self, Pin + Send>>) { let (to_worker, from_queue) = tracing_unbounded("mpsc_revalidation_queue"); let worker = RevalidationWorker::new(api.clone(), pool.clone()); @@ -321,24 +305,7 @@ where api: Arc, pool: Arc>, ) -> (Self, Pin + Send>>) { - Self::new_with_interval( - api, - pool, - intervalier::Interval::new(BACKGROUND_REVALIDATION_INTERVAL), - ) - } - - /// New revalidation queue with background worker and test signal. - #[cfg(feature = "test-helpers")] - pub fn new_test( - api: Arc, - pool: Arc>, - ) -> (Self, Pin + Send>>, intervalier::BackSignalControl) { - let (interval, notifier) = - intervalier::BackSignalInterval::new(BACKGROUND_REVALIDATION_INTERVAL); - let (queue, background) = Self::new_with_interval(api, pool, interval); - - (queue, background, notifier) + Self::new_with_interval(api, pool, BACKGROUND_REVALIDATION_INTERVAL) } /// Queue some transaction for later revalidation. @@ -371,4 +338,41 @@ where } #[cfg(test)] -mod tests {} +mod tests { + use super::*; + use crate::{ + graph::Pool, + tests::{uxt, TestApi}, + }; + use futures::executor::block_on; + use sc_transaction_pool_api::TransactionSource; + use sp_runtime::generic::BlockId; + use substrate_test_runtime::{AccountId, Transfer, H256}; + + #[test] + fn revalidation_queue_works() { + let api = Arc::new(TestApi::default()); + let pool = Arc::new(Pool::new(Default::default(), true.into(), api.clone())); + let queue = Arc::new(RevalidationQueue::new(api.clone(), pool.clone())); + + let uxt = uxt(Transfer { + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), + amount: 5, + nonce: 0, + }); + let uxt_hash = block_on(pool.submit_one( + &BlockId::number(0), + TransactionSource::External, + uxt.clone(), + )) + .expect("Should be valid"); + + block_on(queue.revalidate_later(0, vec![uxt_hash])); + + // revalidated in sync offload 2nd time + assert_eq!(api.validation_requests().len(), 2); + // number of ready + assert_eq!(pool.validated_pool().status().ready, 1); + } +} diff --git a/client/transaction-pool/src/tests.rs b/client/transaction-pool/src/tests.rs new file mode 100644 index 000000000000..79142e16a1b3 --- /dev/null +++ b/client/transaction-pool/src/tests.rs @@ -0,0 +1,185 @@ +// This file is part of Substrate. + +// Copyright (C) 2018-2021 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 . + +//! Testing related primitives for internal usage in this crate. + +use crate::graph::{BlockHash, ChainApi, ExtrinsicFor, NumberFor, Pool}; +use codec::Encode; +use parking_lot::Mutex; +use sc_transaction_pool_api::error; +use sp_runtime::{ + generic::BlockId, + traits::{Block as BlockT, Hash}, + transaction_validity::{ + InvalidTransaction, TransactionSource, TransactionValidity, ValidTransaction, + }, +}; +use std::{collections::HashSet, sync::Arc}; +use substrate_test_runtime::{Block, Extrinsic, Hashing, Transfer, H256}; + +pub(crate) const INVALID_NONCE: u64 = 254; + +/// Test api that implements [`ChainApi`]. +#[derive(Clone, Debug, Default)] +pub(crate) struct TestApi { + pub delay: Arc>>>, + pub invalidate: Arc>>, + pub clear_requirements: Arc>>, + pub add_requirements: Arc>>, + pub validation_requests: Arc>>, +} + +impl TestApi { + /// Query validation requests received. + pub fn validation_requests(&self) -> Vec { + self.validation_requests.lock().clone() + } +} + +impl ChainApi for TestApi { + type Block = Block; + type Error = error::Error; + type ValidationFuture = futures::future::Ready>; + type BodyFuture = futures::future::Ready>>>; + + /// Verify extrinsic at given block. + fn validate_transaction( + &self, + at: &BlockId, + _source: TransactionSource, + uxt: ExtrinsicFor, + ) -> Self::ValidationFuture { + self.validation_requests.lock().push(uxt.clone()); + let hash = self.hash_and_length(&uxt).0; + let block_number = self.block_id_to_number(at).unwrap().unwrap(); + + let res = match uxt { + Extrinsic::Transfer { transfer, .. } => { + let nonce = transfer.nonce; + + // This is used to control the test flow. + if nonce > 0 { + let opt = self.delay.lock().take(); + if let Some(delay) = opt { + if delay.recv().is_err() { + println!("Error waiting for delay!"); + } + } + } + + if self.invalidate.lock().contains(&hash) { + InvalidTransaction::Custom(0).into() + } else if nonce < block_number { + InvalidTransaction::Stale.into() + } else { + let mut transaction = ValidTransaction { + priority: 4, + requires: if nonce > block_number { + vec![vec![nonce as u8 - 1]] + } else { + vec![] + }, + provides: if nonce == INVALID_NONCE { + vec![] + } else { + vec![vec![nonce as u8]] + }, + longevity: 3, + propagate: true, + }; + + if self.clear_requirements.lock().contains(&hash) { + transaction.requires.clear(); + } + + if self.add_requirements.lock().contains(&hash) { + transaction.requires.push(vec![128]); + } + + Ok(transaction) + } + }, + Extrinsic::IncludeData(_) => Ok(ValidTransaction { + priority: 9001, + requires: vec![], + provides: vec![vec![42]], + longevity: 9001, + propagate: false, + }), + Extrinsic::Store(_) => Ok(ValidTransaction { + priority: 9001, + requires: vec![], + provides: vec![vec![43]], + longevity: 9001, + propagate: false, + }), + _ => unimplemented!(), + }; + + futures::future::ready(Ok(res)) + } + + /// Returns a block number given the block id. + fn block_id_to_number( + &self, + at: &BlockId, + ) -> Result>, Self::Error> { + Ok(match at { + BlockId::Number(num) => Some(*num), + BlockId::Hash(_) => None, + }) + } + + /// Returns a block hash given the block id. + fn block_id_to_hash( + &self, + at: &BlockId, + ) -> Result::Hash>, Self::Error> { + Ok(match at { + BlockId::Number(num) => Some(H256::from_low_u64_be(*num)).into(), + BlockId::Hash(_) => None, + }) + } + + /// Hash the extrinsic. + fn hash_and_length(&self, uxt: &ExtrinsicFor) -> (BlockHash, usize) { + let encoded = uxt.encode(); + let len = encoded.len(); + (Hashing::hash(&encoded), len) + } + + fn block_body(&self, _id: &BlockId) -> Self::BodyFuture { + futures::future::ready(Ok(None)) + } + + fn block_header( + &self, + _: &BlockId, + ) -> Result::Header>, Self::Error> { + Ok(None) + } +} + +pub(crate) fn uxt(transfer: Transfer) -> Extrinsic { + let signature = TryFrom::try_from(&[0; 64][..]).unwrap(); + Extrinsic::Transfer { transfer, signature, exhaust_resources_when_not_first: false } +} + +pub(crate) fn pool() -> Pool { + Pool::new(Default::default(), true.into(), TestApi::default().into()) +} diff --git a/client/transaction-pool/tests/pool.rs b/client/transaction-pool/tests/pool.rs index 14ccacfb2692..4aeaf79a6154 100644 --- a/client/transaction-pool/tests/pool.rs +++ b/client/transaction-pool/tests/pool.rs @@ -17,6 +17,7 @@ // along with this program. If not, see . //! Tests for top-level transaction pool api + use codec::Encode; use futures::{ executor::{block_on, block_on_stream}, @@ -25,7 +26,7 @@ use futures::{ }; use sc_block_builder::BlockBuilderProvider; use sc_client_api::client::BlockchainEvents; -use sc_transaction_pool::{test_helpers::*, *}; +use sc_transaction_pool::*; use sc_transaction_pool_api::{ ChainEvent, MaintainedTransactionPool, TransactionPool, TransactionStatus, }; @@ -47,14 +48,13 @@ fn pool() -> Pool { Pool::new(Default::default(), true.into(), TestApi::with_alice_nonce(209).into()) } -fn maintained_pool( -) -> (BasicPool, futures::executor::ThreadPool, intervalier::BackSignalControl) { - let (pool, background_task, notifier) = - BasicPool::new_test(Arc::new(TestApi::with_alice_nonce(209))); +fn maintained_pool() -> (BasicPool, Arc, futures::executor::ThreadPool) { + let api = Arc::new(TestApi::with_alice_nonce(209)); + let (pool, background_task) = BasicPool::new_test(api.clone()); let thread_pool = futures::executor::ThreadPool::new().unwrap(); thread_pool.spawn_ok(background_task); - (pool, thread_pool, notifier) + (pool, api, thread_pool) } const SOURCE: TransactionSource = TransactionSource::External; @@ -135,7 +135,7 @@ fn should_ban_invalid_transactions() { #[test] fn only_prune_on_new_best() { - let pool = maintained_pool().0; + let (pool, api, _) = maintained_pool(); let uxt = uxt(Alice, 209); let _ = block_on(pool.submit_and_watch(&BlockId::number(0), SOURCE, uxt.clone())) @@ -143,7 +143,7 @@ fn only_prune_on_new_best() { pool.api().push_block(1, vec![uxt.clone()], true); assert_eq!(pool.status().ready, 1); - let header = pool.api().push_block(2, vec![uxt], true); + let header = api.push_block(2, vec![uxt], true); let event = ChainEvent::NewBestBlock { hash: header.hash(), tree_route: None }; block_on(pool.maintain(event)); assert_eq!(pool.status().ready, 0); @@ -205,12 +205,12 @@ fn block_event_with_retracted( fn should_prune_old_during_maintenance() { let xt = uxt(Alice, 209); - let (pool, _guard, _notifier) = maintained_pool(); + let (pool, api, _guard) = maintained_pool(); block_on(pool.submit_one(&BlockId::number(0), SOURCE, xt.clone())).expect("1. Imported"); assert_eq!(pool.status().ready, 1); - let header = pool.api().push_block(1, vec![xt.clone()], true); + let header = api.push_block(1, vec![xt.clone()], true); block_on(pool.maintain(block_event(header))); assert_eq!(pool.status().ready, 0); @@ -221,33 +221,38 @@ fn should_revalidate_during_maintenance() { let xt1 = uxt(Alice, 209); let xt2 = uxt(Alice, 210); - let (pool, _guard, mut notifier) = maintained_pool(); + let (pool, api, _guard) = maintained_pool(); block_on(pool.submit_one(&BlockId::number(0), SOURCE, xt1.clone())).expect("1. Imported"); - block_on(pool.submit_one(&BlockId::number(0), SOURCE, xt2.clone())).expect("2. Imported"); + let watcher = block_on(pool.submit_and_watch(&BlockId::number(0), SOURCE, xt2.clone())) + .expect("2. Imported"); assert_eq!(pool.status().ready, 2); - assert_eq!(pool.api().validation_requests().len(), 2); + assert_eq!(api.validation_requests().len(), 2); + + let header = api.push_block(1, vec![xt1.clone()], true); - let header = pool.api().push_block(1, vec![xt1.clone()], true); + api.add_invalid(&xt2); block_on(pool.maintain(block_event(header))); assert_eq!(pool.status().ready, 1); - block_on(notifier.next()); // test that pool revalidated transaction that left ready and not included in the block - assert_eq!(pool.api().validation_requests().len(), 3); + assert_eq!( + futures::executor::block_on_stream(watcher).collect::>(), + vec![TransactionStatus::Ready, TransactionStatus::Invalid], + ); } #[test] fn should_resubmit_from_retracted_during_maintenance() { let xt = uxt(Alice, 209); - let (pool, _guard, _notifier) = maintained_pool(); + let (pool, api, _guard) = maintained_pool(); block_on(pool.submit_one(&BlockId::number(0), SOURCE, xt.clone())).expect("1. Imported"); assert_eq!(pool.status().ready, 1); - let header = pool.api().push_block(1, vec![], true); - let fork_header = pool.api().push_block(1, vec![], false); + let header = api.push_block(1, vec![], true); + let fork_header = api.push_block(1, vec![], false); let event = block_event_with_retracted(header, fork_header.hash(), &*pool.api()); @@ -259,13 +264,13 @@ fn should_resubmit_from_retracted_during_maintenance() { fn should_not_resubmit_from_retracted_during_maintenance_if_tx_is_also_in_enacted() { let xt = uxt(Alice, 209); - let (pool, _guard, _notifier) = maintained_pool(); + let (pool, api, _guard) = maintained_pool(); block_on(pool.submit_one(&BlockId::number(0), SOURCE, xt.clone())).expect("1. Imported"); assert_eq!(pool.status().ready, 1); - let header = pool.api().push_block(1, vec![xt.clone()], true); - let fork_header = pool.api().push_block(1, vec![xt], false); + let header = api.push_block(1, vec![xt.clone()], true); + let fork_header = api.push_block(1, vec![xt], false); let event = block_event_with_retracted(header, fork_header.hash(), &*pool.api()); @@ -277,19 +282,23 @@ fn should_not_resubmit_from_retracted_during_maintenance_if_tx_is_also_in_enacte fn should_not_retain_invalid_hashes_from_retracted() { let xt = uxt(Alice, 209); - let (pool, _guard, mut notifier) = maintained_pool(); + let (pool, api, _guard) = maintained_pool(); - block_on(pool.submit_one(&BlockId::number(0), SOURCE, xt.clone())).expect("1. Imported"); + let watcher = block_on(pool.submit_and_watch(&BlockId::number(0), SOURCE, xt.clone())) + .expect("1. Imported"); assert_eq!(pool.status().ready, 1); - let header = pool.api().push_block(1, vec![], true); - let fork_header = pool.api().push_block(1, vec![xt.clone()], false); - pool.api().add_invalid(&xt); + let header = api.push_block(1, vec![], true); + let fork_header = api.push_block(1, vec![xt.clone()], false); + api.add_invalid(&xt); let event = block_event_with_retracted(header, fork_header.hash(), &*pool.api()); - block_on(pool.maintain(event)); - block_on(notifier.next()); + + assert_eq!( + futures::executor::block_on_stream(watcher).collect::>(), + vec![TransactionStatus::Ready, TransactionStatus::Invalid], + ); assert_eq!(pool.status().ready, 0); } @@ -300,26 +309,30 @@ fn should_revalidate_across_many_blocks() { let xt2 = uxt(Alice, 210); let xt3 = uxt(Alice, 211); - let (pool, _guard, mut notifier) = maintained_pool(); + let (pool, api, _guard) = maintained_pool(); - block_on(pool.submit_one(&BlockId::number(0), SOURCE, xt1.clone())).expect("1. Imported"); + let watcher1 = block_on(pool.submit_and_watch(&BlockId::number(0), SOURCE, xt1.clone())) + .expect("1. Imported"); block_on(pool.submit_one(&BlockId::number(0), SOURCE, xt2.clone())).expect("1. Imported"); assert_eq!(pool.status().ready, 2); - let header = pool.api().push_block(1, vec![], true); + let header = api.push_block(1, vec![], true); block_on(pool.maintain(block_event(header))); - block_on(notifier.next()); block_on(pool.submit_one(&BlockId::number(1), SOURCE, xt3.clone())).expect("1. Imported"); assert_eq!(pool.status().ready, 3); - let header = pool.api().push_block(2, vec![xt1.clone()], true); - block_on(pool.maintain(block_event(header))); - block_on(notifier.next()); + let header = api.push_block(2, vec![xt1.clone()], true); + let block_hash = header.hash(); + block_on(pool.maintain(block_event(header.clone()))); + + block_on( + watcher1 + .take_while(|s| future::ready(*s != TransactionStatus::InBlock(block_hash))) + .collect::>(), + ); assert_eq!(pool.status().ready, 2); - // xt1 and xt2 validated twice, then xt3 once, then xt2 and xt3 again - assert_eq!(pool.api().validation_requests().len(), 7); } #[test] @@ -329,7 +342,7 @@ fn should_push_watchers_during_maintenance() { } // given - let (pool, _guard, mut notifier) = maintained_pool(); + let (pool, api, _guard) = maintained_pool(); let tx0 = alice_uxt(0); let watcher0 = @@ -349,18 +362,16 @@ fn should_push_watchers_during_maintenance() { assert_eq!(pool.status().ready, 5); // when - pool.api().add_invalid(&tx3); - pool.api().add_invalid(&tx4); + api.add_invalid(&tx3); + api.add_invalid(&tx4); // clear timer events if any - let header = pool.api().push_block(1, vec![], true); + let header = api.push_block(1, vec![], true); block_on(pool.maintain(block_event(header))); - block_on(notifier.next()); // then // hash3 is now invalid // hash4 is now invalid - assert_eq!(pool.status().ready, 3); assert_eq!( futures::executor::block_on_stream(watcher3).collect::>(), vec![TransactionStatus::Ready, TransactionStatus::Invalid], @@ -369,9 +380,10 @@ fn should_push_watchers_during_maintenance() { futures::executor::block_on_stream(watcher4).collect::>(), vec![TransactionStatus::Ready, TransactionStatus::Invalid], ); + assert_eq!(pool.status().ready, 3); // when - let header = pool.api().push_block(2, vec![tx0, tx1, tx2], true); + let header = api.push_block(2, vec![tx0, tx1, tx2], true); let header_hash = header.hash(); block_on(pool.maintain(block_event(header))); @@ -410,7 +422,7 @@ fn should_push_watchers_during_maintenance() { #[test] fn can_track_heap_size() { - let (pool, _guard, _notifier) = maintained_pool(); + let (pool, _api, _guard) = maintained_pool(); block_on(pool.submit_one(&BlockId::number(0), SOURCE, uxt(Alice, 209))).expect("1. Imported"); block_on(pool.submit_one(&BlockId::number(0), SOURCE, uxt(Alice, 210))).expect("1. Imported"); block_on(pool.submit_one(&BlockId::number(0), SOURCE, uxt(Alice, 211))).expect("1. Imported"); @@ -424,7 +436,7 @@ fn finalization() { let xt = uxt(Alice, 209); let api = TestApi::with_alice_nonce(209); api.push_block(1, vec![], true); - let (pool, _background, _) = BasicPool::new_test(api.into()); + let (pool, _background) = BasicPool::new_test(api.into()); let watcher = block_on(pool.submit_and_watch(&BlockId::number(1), SOURCE, xt.clone())) .expect("1. Imported"); pool.api().push_block(2, vec![xt.clone()], true); @@ -449,7 +461,7 @@ fn fork_aware_finalization() { // starting block A1 (last finalized.) api.push_block(1, vec![], true); - let (pool, _background, _) = BasicPool::new_test(api.into()); + let (pool, _background) = BasicPool::new_test(api.into()); let mut canon_watchers = vec![]; let from_alice = uxt(Alice, 1); @@ -597,7 +609,7 @@ fn prune_and_retract_tx_at_same_time() { // starting block A1 (last finalized.) api.push_block(1, vec![], true); - let (pool, _background, _) = BasicPool::new_test(api.into()); + let (pool, _background) = BasicPool::new_test(api.into()); let from_alice = uxt(Alice, 1); pool.api().increment_nonce(Alice.into()); @@ -663,7 +675,7 @@ fn resubmit_tx_of_fork_that_is_not_part_of_retracted() { // starting block A1 (last finalized.) api.push_block(1, vec![], true); - let (pool, _background, _) = BasicPool::new_test(api.into()); + let (pool, _background) = BasicPool::new_test(api.into()); let tx0 = uxt(Alice, 1); let tx1 = uxt(Dave, 2); @@ -708,7 +720,7 @@ fn resubmit_from_retracted_fork() { // starting block A1 (last finalized.) api.push_block(1, vec![], true); - let (pool, _background, _) = BasicPool::new_test(api.into()); + let (pool, _background) = BasicPool::new_test(api.into()); let tx0 = uxt(Alice, 1); let tx1 = uxt(Dave, 2); @@ -800,7 +812,7 @@ fn resubmit_from_retracted_fork() { #[test] fn ready_set_should_not_resolve_before_block_update() { - let (pool, _guard, _notifier) = maintained_pool(); + let (pool, _api, _guard) = maintained_pool(); let xt1 = uxt(Alice, 209); block_on(pool.submit_one(&BlockId::number(0), SOURCE, xt1.clone())).expect("1. Imported"); @@ -809,8 +821,8 @@ fn ready_set_should_not_resolve_before_block_update() { #[test] fn ready_set_should_resolve_after_block_update() { - let (pool, _guard, _notifier) = maintained_pool(); - let header = pool.api().push_block(1, vec![], true); + let (pool, api, _guard) = maintained_pool(); + let header = api.push_block(1, vec![], true); let xt1 = uxt(Alice, 209); @@ -822,8 +834,8 @@ fn ready_set_should_resolve_after_block_update() { #[test] fn ready_set_should_eventually_resolve_when_block_update_arrives() { - let (pool, _guard, _notifier) = maintained_pool(); - let header = pool.api().push_block(1, vec![], true); + let (pool, api, _guard) = maintained_pool(); + let header = api.push_block(1, vec![], true); let xt1 = uxt(Alice, 209); @@ -833,7 +845,7 @@ fn ready_set_should_eventually_resolve_when_block_update_arrives() { let mut context = futures::task::Context::from_waker(&noop_waker); let mut ready_set_future = pool.ready_at(1); - if let Poll::Ready(_) = ready_set_future.poll_unpin(&mut context) { + if ready_set_future.poll_unpin(&mut context).is_ready() { panic!("Ready set should not be ready before block update!"); } @@ -929,13 +941,13 @@ fn import_notification_to_pool_maintain_works() { // When we prune transactions, we need to make sure that we remove #[test] fn pruning_a_transaction_should_remove_it_from_best_transaction() { - let (pool, _guard, _notifier) = maintained_pool(); + let (pool, api, _guard) = maintained_pool(); let xt1 = Extrinsic::IncludeData(Vec::new()); block_on(pool.submit_one(&BlockId::number(0), SOURCE, xt1.clone())).expect("1. Imported"); assert_eq!(pool.status().ready, 1); - let header = pool.api().push_block(1, vec![xt1.clone()], true); + let header = api.push_block(1, vec![xt1.clone()], true); // This will prune `xt1`. block_on(pool.maintain(block_event(header))); @@ -943,26 +955,6 @@ fn pruning_a_transaction_should_remove_it_from_best_transaction() { assert_eq!(pool.status().ready, 0); } -#[test] -fn only_revalidate_on_best_block() { - let xt = uxt(Alice, 209); - - let (pool, _guard, mut notifier) = maintained_pool(); - - block_on(pool.submit_one(&BlockId::number(0), SOURCE, xt.clone())).expect("1. Imported"); - assert_eq!(pool.status().ready, 1); - - let header = pool.api().push_block(1, vec![], true); - - pool.api().push_block(2, vec![], false); - pool.api().push_block(2, vec![], false); - - block_on(pool.maintain(block_event(header))); - block_on(notifier.next()); - - assert_eq!(pool.status().ready, 1); -} - #[test] fn stale_transactions_are_pruned() { sp_tracing::try_init_simple(); @@ -974,7 +966,7 @@ fn stale_transactions_are_pruned() { Transfer { from: Alice.into(), to: Bob.into(), nonce: 3, amount: 1 }, ]; - let (pool, _guard, _notifier) = maintained_pool(); + let (pool, api, _guard) = maintained_pool(); xts.into_iter().for_each(|xt| { block_on(pool.submit_one(&BlockId::number(0), SOURCE, xt.into_signed_tx())) @@ -992,7 +984,7 @@ fn stale_transactions_are_pruned() { ]; // Import block - let header = pool.api().push_block(1, xts, true); + let header = api.push_block(1, xts, true); block_on(pool.maintain(block_event(header))); // The imported transactions have a different hash and should not evict our initial // transactions. @@ -1000,7 +992,7 @@ fn stale_transactions_are_pruned() { // Import enough blocks to make our transactions stale for n in 1..66 { - let header = pool.api().push_block(n, vec![], true); + let header = api.push_block(n, vec![], true); block_on(pool.maintain(block_event(header))); } diff --git a/client/transaction-pool/tests/revalidation.rs b/client/transaction-pool/tests/revalidation.rs deleted file mode 100644 index b2c8225b78f5..000000000000 --- a/client/transaction-pool/tests/revalidation.rs +++ /dev/null @@ -1,32 +0,0 @@ -use futures::executor::block_on; -use sc_transaction_pool::test_helpers::{Pool, RevalidationQueue}; -use sc_transaction_pool_api::TransactionSource; -use sp_runtime::generic::BlockId; -use std::sync::Arc; -use substrate_test_runtime_client::AccountKeyring::*; -use substrate_test_runtime_transaction_pool::{uxt, TestApi}; - -fn setup() -> (Arc, Pool) { - let test_api = Arc::new(TestApi::empty()); - let pool = Pool::new(Default::default(), true.into(), test_api.clone()); - (test_api, pool) -} - -#[test] -fn smoky() { - let (api, pool) = setup(); - let pool = Arc::new(pool); - let queue = Arc::new(RevalidationQueue::new(api.clone(), pool.clone())); - - let uxt = uxt(Alice, 0); - let uxt_hash = - block_on(pool.submit_one(&BlockId::number(0), TransactionSource::External, uxt.clone())) - .expect("Should be valid"); - - block_on(queue.revalidate_later(0, vec![uxt_hash])); - - // revalidated in sync offload 2nd time - assert_eq!(api.validation_requests().len(), 2); - // number of ready - assert_eq!(pool.validated_pool().status().ready, 1); -} diff --git a/test-utils/runtime/transaction-pool/Cargo.toml b/test-utils/runtime/transaction-pool/Cargo.toml index a0d04bd70271..8eaaac62c556 100644 --- a/test-utils/runtime/transaction-pool/Cargo.toml +++ b/test-utils/runtime/transaction-pool/Cargo.toml @@ -17,7 +17,7 @@ parking_lot = "0.11.2" codec = { package = "parity-scale-codec", version = "2.0.0" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } -sc-transaction-pool = { version = "4.0.0-dev", path = "../../../client/transaction-pool", features = ["test-helpers"] } +sc-transaction-pool = { version = "4.0.0-dev", path = "../../../client/transaction-pool" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../../../client/transaction-pool/api" } futures = "0.3.16" derive_more = "0.99.16" diff --git a/test-utils/runtime/transaction-pool/src/lib.rs b/test-utils/runtime/transaction-pool/src/lib.rs index d43347bdcb6e..a339ce8c7f65 100644 --- a/test-utils/runtime/transaction-pool/src/lib.rs +++ b/test-utils/runtime/transaction-pool/src/lib.rs @@ -25,7 +25,9 @@ use parking_lot::RwLock; use sp_blockchain::CachedHeaderMetadata; use sp_runtime::{ generic::{self, BlockId}, - traits::{BlakeTwo256, Block as BlockT, Hash as HashT, Header as _, TrailingZeroInput}, + traits::{ + BlakeTwo256, Block as BlockT, Hash as HashT, Header as _, NumberFor, TrailingZeroInput, + }, transaction_validity::{ InvalidTransaction, TransactionSource, TransactionValidity, TransactionValidityError, ValidTransaction, @@ -227,7 +229,7 @@ impl TestApi { } } -impl sc_transaction_pool::test_helpers::ChainApi for TestApi { +impl sc_transaction_pool::ChainApi for TestApi { type Block = Block; type Error = Error; type ValidationFuture = futures::future::Ready>; @@ -237,7 +239,7 @@ impl sc_transaction_pool::test_helpers::ChainApi for TestApi { &self, at: &BlockId, _source: TransactionSource, - uxt: sc_transaction_pool::test_helpers::ExtrinsicFor, + uxt: ::Extrinsic, ) -> Self::ValidationFuture { self.validation_requests.write().push(uxt.clone()); @@ -297,7 +299,7 @@ impl sc_transaction_pool::test_helpers::ChainApi for TestApi { fn block_id_to_number( &self, at: &BlockId, - ) -> Result>, Error> { + ) -> Result>, Error> { Ok(match at { generic::BlockId::Hash(x) => self.chain.read().block_by_hash.get(x).map(|b| *b.header.number()), @@ -308,7 +310,7 @@ impl sc_transaction_pool::test_helpers::ChainApi for TestApi { fn block_id_to_hash( &self, at: &BlockId, - ) -> Result>, Error> { + ) -> Result::Hash>, Error> { Ok(match at { generic::BlockId::Hash(x) => Some(x.clone()), generic::BlockId::Number(num) => @@ -318,10 +320,7 @@ impl sc_transaction_pool::test_helpers::ChainApi for TestApi { }) } - fn hash_and_length( - &self, - ex: &sc_transaction_pool::test_helpers::ExtrinsicFor, - ) -> (Hash, usize) { + fn hash_and_length(&self, ex: &::Extrinsic) -> (Hash, usize) { Self::hash_and_length_inner(ex) } From 7e7045267f415c1e806ef6d7804743e0a8e44ddb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Jan 2022 23:07:02 +0100 Subject: [PATCH 346/695] Bump ip_network from 0.4.0 to 0.4.1 (#10525) Bumps [ip_network](https://github.com/JakubOnderka/ip_network) from 0.4.0 to 0.4.1. - [Release notes](https://github.com/JakubOnderka/ip_network/releases) - [Commits](https://github.com/JakubOnderka/ip_network/commits) --- updated-dependencies: - dependency-name: ip_network dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- client/authority-discovery/Cargo.toml | 2 +- client/network/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ba80103c174b..cc6b80221b25 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2989,9 +2989,9 @@ dependencies = [ [[package]] name = "ip_network" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09b746553d2f4a1ca26fab939943ddfb217a091f34f53571620a8e3d30691303" +checksum = "aa2f047c0a98b2f299aa5d6d7088443570faae494e9ae1305e48be000c9e0eb1" [[package]] name = "ipconfig" @@ -11024,8 +11024,8 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f559b464de2e2bdabcac6a210d12e9b5a5973c251e102c44c585c71d51bd78e" dependencies = [ - "cfg-if 0.1.10", - "rand 0.6.5", + "cfg-if 1.0.0", + "rand 0.8.4", "static_assertions", ] diff --git a/client/authority-discovery/Cargo.toml b/client/authority-discovery/Cargo.toml index fd94e71ceb84..ac9f0cdb1828 100644 --- a/client/authority-discovery/Cargo.toml +++ b/client/authority-discovery/Cargo.toml @@ -22,7 +22,7 @@ codec = { package = "parity-scale-codec", default-features = false, version = "2 derive_more = "0.99.16" futures = "0.3.9" futures-timer = "3.0.1" -ip_network = "0.4.0" +ip_network = "0.4.1" libp2p = { version = "0.40.0", default-features = false, features = ["kad"] } log = "0.4.8" prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.10.0-dev" } diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index 4f3ea4e939b6..1a77431b4b74 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -33,7 +33,7 @@ futures = "0.3.9" futures-timer = "3.0.2" asynchronous-codec = "0.5" hex = "0.4.0" -ip_network = "0.4.0" +ip_network = "0.4.1" linked-hash-map = "0.5.4" linked_hash_set = "0.1.3" lru = "0.7.0" From cd3d2b1b65929bafa699953094bcd8b9fe7d3dfc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Jan 2022 10:05:01 +0100 Subject: [PATCH 347/695] Bump serde_json from 1.0.71 to 1.0.74 (#10577) Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.71 to 1.0.74. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.71...v1.0.74) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 24 ++++++++++++------- bin/node/bench/Cargo.toml | 2 +- client/beefy/rpc/Cargo.toml | 2 +- client/chain-spec/Cargo.toml | 2 +- client/cli/Cargo.toml | 2 +- client/consensus/babe/rpc/Cargo.toml | 2 +- client/finality-grandpa/Cargo.toml | 2 +- client/keystore/Cargo.toml | 2 +- client/network/Cargo.toml | 2 +- client/peerset/Cargo.toml | 2 +- client/rpc-api/Cargo.toml | 2 +- client/rpc-servers/Cargo.toml | 2 +- client/rpc/Cargo.toml | 2 +- client/service/Cargo.toml | 2 +- client/sync-state-rpc/Cargo.toml | 2 +- client/telemetry/Cargo.toml | 2 +- frame/merkle-mountain-range/rpc/Cargo.toml | 2 +- frame/transaction-payment/Cargo.toml | 2 +- .../asset-tx-payment/Cargo.toml | 2 +- primitives/rpc/Cargo.toml | 2 +- primitives/runtime/Cargo.toml | 2 +- primitives/serializer/Cargo.toml | 2 +- test-utils/client/Cargo.toml | 2 +- 23 files changed, 37 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cc6b80221b25..d5e242cc22c9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1368,7 +1368,7 @@ checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" dependencies = [ "bstr", "csv-core", - "itoa", + "itoa 0.4.8", "ryu", "serde", ] @@ -2731,7 +2731,7 @@ checksum = "7245cd7449cc792608c3c8a9eaf69bd4eabbabf802713748fd739c98b82f0747" dependencies = [ "bytes 1.1.0", "fnv", - "itoa", + "itoa 0.4.8", ] [[package]] @@ -2806,7 +2806,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa", + "itoa 0.4.8", "pin-project-lite 0.2.6", "socket2 0.4.0", "tokio", @@ -3026,6 +3026,12 @@ version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" +[[package]] +name = "itoa" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" + [[package]] name = "jobserver" version = "0.1.21" @@ -4968,7 +4974,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bafe4179722c2894288ee77a9f044f02811c86af699344c498b0840c698a2465" dependencies = [ "arrayvec 0.4.12", - "itoa", + "itoa 0.4.8", ] [[package]] @@ -5076,7 +5082,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7337d80c23c2d8b1349563981bc4fb531220733743ba8115454a67b181173f0d" dependencies = [ "dtoa", - "itoa", + "itoa 0.4.8", "open-metrics-client-derive-text-encode", "owning_ref", ] @@ -7459,7 +7465,7 @@ dependencies = [ "cc", "errno", "io-lifetimes", - "itoa", + "itoa 0.4.8", "libc", "linux-raw-sys", "once_cell", @@ -8938,11 +8944,11 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.71" +version = "1.0.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "063bf466a64011ac24040a49009724ee60a57da1b437617ceb32e53ad61bfb19" +checksum = "ee2bb9cd061c5865d345bb02ca49fcef1391741b672b54a0bf7b679badec3142" dependencies = [ - "itoa", + "itoa 1.0.1", "ryu", "serde", ] diff --git a/bin/node/bench/Cargo.toml b/bin/node/bench/Cargo.toml index 114742990bcd..90951d75cfd2 100644 --- a/bin/node/bench/Cargo.toml +++ b/bin/node/bench/Cargo.toml @@ -17,7 +17,7 @@ sc-client-api = { version = "4.0.0-dev", path = "../../../client/api/" } sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } sp-state-machine = { version = "0.10.0", path = "../../../primitives/state-machine" } serde = "1.0.132" -serde_json = "1.0.71" +serde_json = "1.0.74" structopt = "0.3" derive_more = "0.99.16" kvdb = "0.10.0" diff --git a/client/beefy/rpc/Cargo.toml b/client/beefy/rpc/Cargo.toml index c14d604990cb..bc81732dcd41 100644 --- a/client/beefy/rpc/Cargo.toml +++ b/client/beefy/rpc/Cargo.toml @@ -28,7 +28,7 @@ beefy-gadget = { version = "4.0.0-dev", path = "../." } beefy-primitives = { version = "4.0.0-dev", path = "../../../primitives/beefy" } [dev-dependencies] -serde_json = "1.0.50" +serde_json = "1.0.74" sc-rpc = { version = "4.0.0-dev", path = "../../rpc", features = [ "test-helpers", diff --git a/client/chain-spec/Cargo.toml b/client/chain-spec/Cargo.toml index 601fb5b4da9e..769f502dd5ed 100644 --- a/client/chain-spec/Cargo.toml +++ b/client/chain-spec/Cargo.toml @@ -18,7 +18,7 @@ impl-trait-for-tuples = "0.2.1" sc-network = { version = "0.10.0-dev", path = "../network" } sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } serde = { version = "1.0.132", features = ["derive"] } -serde_json = "1.0.71" +serde_json = "1.0.74" sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } sc-telemetry = { version = "4.0.0-dev", path = "../telemetry" } codec = { package = "parity-scale-codec", version = "2.0.0" } diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index f92f7b51c8b7..7ef5ef9d6893 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -23,7 +23,7 @@ parity-scale-codec = "2.3.1" hex = "0.4.2" rand = "0.7.3" tiny-bip39 = "0.8.2" -serde_json = "1.0.71" +serde_json = "1.0.74" sc-keystore = { version = "4.0.0-dev", path = "../keystore" } sp-panic-handler = { version = "4.0.0", path = "../../primitives/panic-handler" } sc-client-api = { version = "4.0.0-dev", path = "../api" } diff --git a/client/consensus/babe/rpc/Cargo.toml b/client/consensus/babe/rpc/Cargo.toml index 61321e684fa9..dbc840d26c57 100644 --- a/client/consensus/babe/rpc/Cargo.toml +++ b/client/consensus/babe/rpc/Cargo.toml @@ -33,7 +33,7 @@ sp-keystore = { version = "0.10.0", path = "../../../../primitives/keystore" } [dev-dependencies] sc-consensus = { version = "0.10.0-dev", path = "../../../consensus/common" } -serde_json = "1.0.71" +serde_json = "1.0.74" sp-keyring = { version = "4.0.0-dev", path = "../../../../primitives/keyring" } sc-keystore = { version = "4.0.0-dev", path = "../../../keystore" } substrate-test-runtime-client = { version = "2.0.0", path = "../../../../test-utils/runtime/client" } diff --git a/client/finality-grandpa/Cargo.toml b/client/finality-grandpa/Cargo.toml index 6e7463792e7b..10344e09c685 100644 --- a/client/finality-grandpa/Cargo.toml +++ b/client/finality-grandpa/Cargo.toml @@ -35,7 +35,7 @@ sp-keystore = { version = "0.10.0", path = "../../primitives/keystore" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } sc-telemetry = { version = "4.0.0-dev", path = "../telemetry" } sc-keystore = { version = "4.0.0-dev", path = "../keystore" } -serde_json = "1.0.71" +serde_json = "1.0.74" sc-client-api = { version = "4.0.0-dev", path = "../api" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sc-network = { version = "0.10.0-dev", path = "../network" } diff --git a/client/keystore/Cargo.toml b/client/keystore/Cargo.toml index b4c684a206f3..7fe9e182efbd 100644 --- a/client/keystore/Cargo.toml +++ b/client/keystore/Cargo.toml @@ -22,7 +22,7 @@ sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-keystore = { version = "0.10.0", path = "../../primitives/keystore" } hex = "0.4.0" parking_lot = "0.11.2" -serde_json = "1.0.71" +serde_json = "1.0.74" [dev-dependencies] tempfile = "3.1.0" diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index 1a77431b4b74..d5304cf5fbf0 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -47,7 +47,7 @@ sc-block-builder = { version = "0.10.0-dev", path = "../block-builder" } sc-client-api = { version = "4.0.0-dev", path = "../api" } sc-peerset = { version = "4.0.0-dev", path = "../peerset" } serde = { version = "1.0.132", features = ["derive"] } -serde_json = "1.0.71" +serde_json = "1.0.74" smallvec = "1.7.0" sp-arithmetic = { version = "4.0.0", path = "../../primitives/arithmetic" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } diff --git a/client/peerset/Cargo.toml b/client/peerset/Cargo.toml index ec226b3d9bee..ac3590630a1e 100644 --- a/client/peerset/Cargo.toml +++ b/client/peerset/Cargo.toml @@ -18,7 +18,7 @@ futures = "0.3.9" libp2p = { version = "0.40.0", default-features = false } sc-utils = { version = "4.0.0-dev", path = "../utils"} log = "0.4.8" -serde_json = "1.0.71" +serde_json = "1.0.74" wasm-timer = "0.2" [dev-dependencies] diff --git a/client/rpc-api/Cargo.toml b/client/rpc-api/Cargo.toml index f8f8e333a9c6..aa560bc2e1c1 100644 --- a/client/rpc-api/Cargo.toml +++ b/client/rpc-api/Cargo.toml @@ -28,7 +28,7 @@ sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } sp-runtime = { path = "../../primitives/runtime", version = "4.0.0" } sc-chain-spec = { path = "../chain-spec", version = "4.0.0-dev" } serde = { version = "1.0.132", features = ["derive"] } -serde_json = "1.0.71" +serde_json = "1.0.74" sc-transaction-pool-api = { version = "4.0.0-dev", path = "../transaction-pool/api" } sp-rpc = { version = "4.0.0-dev", path = "../../primitives/rpc" } sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } diff --git a/client/rpc-servers/Cargo.toml b/client/rpc-servers/Cargo.toml index ae450c2ba9a2..4246168c3e66 100644 --- a/client/rpc-servers/Cargo.toml +++ b/client/rpc-servers/Cargo.toml @@ -18,7 +18,7 @@ jsonrpc-core = "18.0.0" pubsub = { package = "jsonrpc-pubsub", version = "18.0.0" } log = "0.4.8" prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.10.0-dev"} -serde_json = "1.0.71" +serde_json = "1.0.74" tokio = "1.15" http = { package = "jsonrpc-http-server", version = "18.0.0" } ipc = { package = "jsonrpc-ipc-server", version = "18.0.0" } diff --git a/client/rpc/Cargo.toml b/client/rpc/Cargo.toml index b8829dca870b..3a2af0bb211e 100644 --- a/client/rpc/Cargo.toml +++ b/client/rpc/Cargo.toml @@ -23,7 +23,7 @@ log = "0.4.8" sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } rpc = { package = "jsonrpc-core", version = "18.0.0" } sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } -serde_json = "1.0.71" +serde_json = "1.0.74" sp-session = { version = "4.0.0-dev", path = "../../primitives/session" } sp-offchain = { version = "4.0.0-dev", path = "../../primitives/offchain" } sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index bfe053152ba4..84e24634613f 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -34,7 +34,7 @@ exit-future = "0.2.0" pin-project = "1.0.8" hash-db = "0.15.2" serde = "1.0.132" -serde_json = "1.0.71" +serde_json = "1.0.74" sc-keystore = { version = "4.0.0-dev", path = "../keystore" } sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } sp-trie = { version = "4.0.0", path = "../../primitives/trie" } diff --git a/client/sync-state-rpc/Cargo.toml b/client/sync-state-rpc/Cargo.toml index 859173ca77eb..e5ac6550d213 100644 --- a/client/sync-state-rpc/Cargo.toml +++ b/client/sync-state-rpc/Cargo.toml @@ -23,7 +23,7 @@ sc-consensus-babe = { version = "0.10.0-dev", path = "../consensus/babe" } sc-consensus-epochs = { version = "0.10.0-dev", path = "../consensus/epochs" } sc-finality-grandpa = { version = "0.10.0-dev", path = "../finality-grandpa" } sc-rpc-api = { version = "0.10.0-dev", path = "../rpc-api" } -serde_json = "1.0.71" +serde_json = "1.0.74" serde = { version = "1.0.132", features = ["derive"] } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } diff --git a/client/telemetry/Cargo.toml b/client/telemetry/Cargo.toml index 2001026a1201..4e9a1f8938a9 100644 --- a/client/telemetry/Cargo.toml +++ b/client/telemetry/Cargo.toml @@ -23,6 +23,6 @@ log = "0.4.8" pin-project = "1.0.8" rand = "0.7.2" serde = { version = "1.0.132", features = ["derive"] } -serde_json = "1.0.71" +serde_json = "1.0.74" chrono = "0.4.19" thiserror = "1.0.30" diff --git a/frame/merkle-mountain-range/rpc/Cargo.toml b/frame/merkle-mountain-range/rpc/Cargo.toml index c6f9124c2a27..cf6aee670b5b 100644 --- a/frame/merkle-mountain-range/rpc/Cargo.toml +++ b/frame/merkle-mountain-range/rpc/Cargo.toml @@ -27,4 +27,4 @@ sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } pallet-mmr-primitives = { version = "4.0.0-dev", path = "../primitives" } [dev-dependencies] -serde_json = "1.0.71" +serde_json = "1.0.74" diff --git a/frame/transaction-payment/Cargo.toml b/frame/transaction-payment/Cargo.toml index 7679dae8e6ea..9cf6790de46d 100644 --- a/frame/transaction-payment/Cargo.toml +++ b/frame/transaction-payment/Cargo.toml @@ -29,7 +29,7 @@ frame-support = { version = "4.0.0-dev", default-features = false, path = "../su frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } [dev-dependencies] -serde_json = "1.0.71" +serde_json = "1.0.74" pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/frame/transaction-payment/asset-tx-payment/Cargo.toml b/frame/transaction-payment/asset-tx-payment/Cargo.toml index 3226ec09d014..820c8f00bb8f 100644 --- a/frame/transaction-payment/asset-tx-payment/Cargo.toml +++ b/frame/transaction-payment/asset-tx-payment/Cargo.toml @@ -30,7 +30,7 @@ serde = { version = "1.0.132", optional = true } [dev-dependencies] smallvec = "1.7.0" -serde_json = "1.0.71" +serde_json = "1.0.74" sp-storage = { version = "4.0.0", default-features = false, path = "../../../primitives/storage" } diff --git a/primitives/rpc/Cargo.toml b/primitives/rpc/Cargo.toml index 51aaa990456e..52fe09b2c789 100644 --- a/primitives/rpc/Cargo.toml +++ b/primitives/rpc/Cargo.toml @@ -18,4 +18,4 @@ sp-core = { version = "4.1.0-dev", path = "../core" } rustc-hash = "1.1.0" [dev-dependencies] -serde_json = "1.0.71" +serde_json = "1.0.74" diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index deb877abcca0..abf246eece9a 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -32,7 +32,7 @@ hash256-std-hasher = { version = "0.15.2", default-features = false } either = { version = "1.5", default-features = false } [dev-dependencies] -serde_json = "1.0.71" +serde_json = "1.0.74" rand = "0.7.2" sp-state-machine = { version = "0.10.0", path = "../state-machine" } sp-api = { version = "4.0.0-dev", path = "../api" } diff --git a/primitives/serializer/Cargo.toml b/primitives/serializer/Cargo.toml index 40f4d19e047e..a0413164eb57 100644 --- a/primitives/serializer/Cargo.toml +++ b/primitives/serializer/Cargo.toml @@ -15,4 +15,4 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = "1.0.132" -serde_json = "1.0.71" +serde_json = "1.0.74" diff --git a/test-utils/client/Cargo.toml b/test-utils/client/Cargo.toml index fa0ae85e706c..cb9f17f637dd 100644 --- a/test-utils/client/Cargo.toml +++ b/test-utils/client/Cargo.toml @@ -16,7 +16,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0" } futures = "0.3.16" hex = "0.4" serde = "1.0.132" -serde_json = "1.0.71" +serde_json = "1.0.74" sc-client-api = { version = "4.0.0-dev", path = "../../client/api" } sc-client-db = { version = "0.10.0-dev", features = [ "test-helpers", From 765cd2905b738b1079923f322e11b8cd8494661d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Jan 2022 13:18:16 +0000 Subject: [PATCH 348/695] Bump pin-project from 1.0.8 to 1.0.10 (#10578) Bumps [pin-project](https://github.com/taiki-e/pin-project) from 1.0.8 to 1.0.10. - [Release notes](https://github.com/taiki-e/pin-project/releases) - [Changelog](https://github.com/taiki-e/pin-project/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/pin-project/compare/v1.0.8...v1.0.10) --- updated-dependencies: - dependency-name: pin-project dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 30 +++++++++++++++--------------- client/network/Cargo.toml | 2 +- client/service/Cargo.toml | 2 +- client/telemetry/Cargo.toml | 2 +- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d5e242cc22c9..cdd2d0d11e45 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3254,7 +3254,7 @@ dependencies = [ "http", "jsonrpsee-types", "log 0.4.14", - "pin-project 1.0.8", + "pin-project 1.0.10", "rustls-native-certs", "serde", "serde_json", @@ -3454,7 +3454,7 @@ dependencies = [ "libp2p-yamux", "multiaddr", "parking_lot 0.11.2", - "pin-project 1.0.8", + "pin-project 1.0.10", "smallvec 1.7.0", "wasm-timer", ] @@ -3479,7 +3479,7 @@ dependencies = [ "multihash 0.14.0", "multistream-select", "parking_lot 0.11.2", - "pin-project 1.0.8", + "pin-project 1.0.10", "prost", "prost-build", "rand 0.8.4", @@ -3720,7 +3720,7 @@ checksum = "0f1a458bbda880107b5b36fcb9b5a1ef0c329685da0e203ed692a8ebe64cc92c" dependencies = [ "futures 0.3.16", "log 0.4.14", - "pin-project 1.0.8", + "pin-project 1.0.10", "rand 0.7.3", "salsa20", "sha3", @@ -3739,7 +3739,7 @@ dependencies = [ "libp2p-core", "libp2p-swarm", "log 0.4.14", - "pin-project 1.0.8", + "pin-project 1.0.10", "prost", "prost-build", "rand 0.7.3", @@ -4408,7 +4408,7 @@ dependencies = [ "bytes 1.1.0", "futures 0.3.16", "log 0.4.14", - "pin-project 1.0.8", + "pin-project 1.0.10", "smallvec 1.7.0", "unsigned-varint 0.7.0", ] @@ -6633,11 +6633,11 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576bc800220cc65dac09e99e97b08b358cfab6e17078de8dc5fee223bd2d0c08" +checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" dependencies = [ - "pin-project-internal 1.0.8", + "pin-project-internal 1.0.10", ] [[package]] @@ -6653,9 +6653,9 @@ dependencies = [ [[package]] name = "pin-project-internal" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e8fe8163d14ce7f0cdac2e040116f22eac817edabff0be91e8aff7e9accf389" +checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" dependencies = [ "proc-macro2", "quote", @@ -8269,7 +8269,7 @@ dependencies = [ "lru 0.7.0", "parity-scale-codec", "parking_lot 0.11.2", - "pin-project 1.0.8", + "pin-project 1.0.10", "prost", "prost-build", "quickcheck", @@ -8510,7 +8510,7 @@ dependencies = [ "parity-scale-codec", "parity-util-mem", "parking_lot 0.11.2", - "pin-project 1.0.8", + "pin-project 1.0.10", "rand 0.7.3", "sc-block-builder", "sc-chain-spec", @@ -8638,7 +8638,7 @@ dependencies = [ "libp2p", "log 0.4.14", "parking_lot 0.11.2", - "pin-project 1.0.8", + "pin-project 1.0.10", "rand 0.7.3", "serde", "serde_json", @@ -10822,7 +10822,7 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" dependencies = [ - "pin-project 1.0.8", + "pin-project 1.0.10", "tracing", ] diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index d5304cf5fbf0..2df700fae8a3 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -39,7 +39,7 @@ linked_hash_set = "0.1.3" lru = "0.7.0" log = "0.4.8" parking_lot = "0.11.2" -pin-project = "1.0.8" +pin-project = "1.0.10" prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.10.0-dev", path = "../../utils/prometheus" } prost = "0.9" rand = "0.7.2" diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index 84e24634613f..e9b05c0d28aa 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -31,7 +31,7 @@ parking_lot = "0.11.2" log = "0.4.11" futures-timer = "3.0.1" exit-future = "0.2.0" -pin-project = "1.0.8" +pin-project = "1.0.10" hash-db = "0.15.2" serde = "1.0.132" serde_json = "1.0.74" diff --git a/client/telemetry/Cargo.toml b/client/telemetry/Cargo.toml index 4e9a1f8938a9..2417f3c77b76 100644 --- a/client/telemetry/Cargo.toml +++ b/client/telemetry/Cargo.toml @@ -20,7 +20,7 @@ futures = "0.3.9" wasm-timer = "0.2.5" libp2p = { version = "0.40.0", default-features = false, features = ["dns-async-std", "tcp-async-io", "wasm-ext", "websocket"] } log = "0.4.8" -pin-project = "1.0.8" +pin-project = "1.0.10" rand = "0.7.2" serde = { version = "1.0.132", features = ["derive"] } serde_json = "1.0.74" From 823581c4adc2cf9ab6948f5337bbb3cc5cb43cc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Tue, 4 Jan 2022 20:48:43 +0100 Subject: [PATCH 349/695] Use storage transaction when running with proof recorder (#10581) This will enable parachains to re-import a block without re-executing it. --- client/service/src/client/call_executor.rs | 4 +++- primitives/state-machine/src/backend.rs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/client/service/src/client/call_executor.rs b/client/service/src/client/call_executor.rs index f2b45bc413e2..739ad029dc19 100644 --- a/client/service/src/client/call_executor.rs +++ b/client/service/src/client/call_executor.rs @@ -246,8 +246,10 @@ where &runtime_code, self.spawn_handle.clone(), ) + .with_storage_transaction_cache( + storage_transaction_cache.as_mut().map(|c| &mut **c), + ) .set_parent_hash(at_hash); - // TODO: https://github.com/paritytech/substrate/issues/4455 state_machine.execute_using_consensus_failure_handler( execution_manager, native_call.map(|n| || (n)().map_err(|e| Box::new(e) as Box<_>)), diff --git a/primitives/state-machine/src/backend.rs b/primitives/state-machine/src/backend.rs index cde5011ce2d8..215caaa17f30 100644 --- a/primitives/state-machine/src/backend.rs +++ b/primitives/state-machine/src/backend.rs @@ -40,7 +40,7 @@ pub trait Backend: sp_std::fmt::Debug { type Transaction: Consolidate + Default + Send; /// Type of trie backend storage. - type TrieBackendStorage: TrieBackendStorage; + type TrieBackendStorage: TrieBackendStorage; /// Get keyed storage or None if there is nothing associated. fn storage(&self, key: &[u8]) -> Result, Self::Error>; From 2ae62422298746828d3a8c5a8f401d8c6806b998 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Wed, 5 Jan 2022 13:09:01 +0100 Subject: [PATCH 350/695] sc-keystore: Improve weird error message (#10584) The keystore would print "Invalid password" when a key was stored using an incorrect public key. This pr improves the error message to communicate better to the user on what is wrong. --- client/keystore/src/lib.rs | 9 ++++++--- client/keystore/src/local.rs | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/client/keystore/src/lib.rs b/client/keystore/src/lib.rs index 83641f267bc8..359326bb4cae 100644 --- a/client/keystore/src/lib.rs +++ b/client/keystore/src/lib.rs @@ -35,8 +35,11 @@ pub enum Error { /// JSON error. Json(serde_json::Error), /// Invalid password. - #[display(fmt = "Invalid password")] - InvalidPassword, + #[display( + fmt = "Requested public key and public key of the loaded private key do not match. \n + This means either that the keystore password is incorrect or that the private key was stored under a wrong public key." + )] + PublicKeyMismatch, /// Invalid BIP39 phrase #[display(fmt = "Invalid recovery phrase (BIP39) data")] InvalidPhrase, @@ -58,7 +61,7 @@ impl From for TraitError { fn from(error: Error) -> Self { match error { Error::KeyNotSupported(id) => TraitError::KeyNotSupported(id), - Error::InvalidSeed | Error::InvalidPhrase | Error::InvalidPassword => + Error::InvalidSeed | Error::InvalidPhrase | Error::PublicKeyMismatch => TraitError::ValidationError(error.to_string()), Error::Unavailable => TraitError::Unavailable, Error::Io(e) => TraitError::Other(e.to_string()), diff --git a/client/keystore/src/local.rs b/client/keystore/src/local.rs index 9c8e3baab182..9f6f18d0c293 100644 --- a/client/keystore/src/local.rs +++ b/client/keystore/src/local.rs @@ -503,7 +503,7 @@ impl KeystoreInner { if &pair.public() == public { Ok(Some(pair)) } else { - Err(Error::InvalidPassword) + Err(Error::PublicKeyMismatch) } } From a2ae8a5702c782f1de05dae77b39f13c6ddda3a8 Mon Sep 17 00:00:00 2001 From: Squirrel Date: Wed, 5 Jan 2022 14:35:30 +0000 Subject: [PATCH 351/695] Make clippy _a little_ more annoying (#10570) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Clippy: +complexity * Update client/cli/src/arg_enums.rs Co-authored-by: Bastian Köcher * Update bin/node/inspect/src/lib.rs Co-authored-by: Bastian Köcher * Update primitives/keystore/src/testing.rs Co-authored-by: Bastian Köcher * Update frame/elections/src/lib.rs Co-authored-by: Keith Yeung * Update primitives/npos-elections/fuzzer/src/reduce.rs Co-authored-by: Keith Yeung * Incorporating feedback * No need for Ok * Additional * Needed slice * Wigy's suggestions on less derefs * fix count * reverting changes brought in by option_map_unit_fn * add --all-targets Co-authored-by: Bastian Köcher Co-authored-by: Keith Yeung --- .cargo/config.toml | 21 +++++++++- .gitlab-ci.yml | 2 +- bin/node-template/node/src/service.rs | 2 +- bin/node/inspect/src/lib.rs | 2 +- client/chain-spec/src/chain_spec.rs | 2 +- client/cli/src/arg_enums.rs | 2 +- client/cli/src/commands/sign.rs | 2 +- client/cli/src/commands/verify.rs | 2 +- client/cli/src/params/mod.rs | 4 +- client/consensus/common/src/block_import.rs | 4 +- .../manual-seal/src/consensus/babe.rs | 2 +- client/consensus/manual-seal/src/lib.rs | 6 +-- client/db/src/bench.rs | 1 - client/db/src/lib.rs | 6 +-- client/db/src/offchain.rs | 2 +- client/executor/src/integration_tests/mod.rs | 10 ++--- client/executor/src/lib.rs | 2 +- client/executor/src/wasm_runtime.rs | 2 +- client/executor/wasmtime/src/host.rs | 4 +- client/executor/wasmtime/src/tests.rs | 2 +- .../src/communication/gossip.rs | 5 +-- client/finality-grandpa/src/lib.rs | 2 +- client/rpc/src/state/state_full.rs | 5 +-- client/rpc/src/state/tests.rs | 2 +- client/rpc/src/system/tests.rs | 10 ++--- client/service/src/builder.rs | 4 +- client/service/src/client/call_executor.rs | 4 +- client/service/src/client/client.rs | 10 ++--- client/state-db/src/noncanonical.rs | 9 ++-- client/tracing/proc-macro/src/lib.rs | 2 +- client/tracing/src/block/mod.rs | 4 +- client/tracing/src/lib.rs | 9 ++-- client/transaction-pool/src/graph/pool.rs | 8 +--- frame/authority-discovery/src/lib.rs | 7 +--- frame/authorship/src/lib.rs | 8 ++-- frame/babe/src/lib.rs | 8 +--- frame/bags-list/src/list/mod.rs | 2 +- frame/balances/src/lib.rs | 9 +--- frame/contracts/src/storage/meter.rs | 9 ++-- frame/contracts/src/wasm/runtime.rs | 2 +- .../src/unsigned.rs | 2 +- frame/elections-phragmen/src/lib.rs | 2 +- frame/examples/basic/src/lib.rs | 2 +- frame/grandpa/src/lib.rs | 8 +--- frame/im-online/src/tests.rs | 2 +- frame/scored-pool/src/mock.rs | 1 - frame/session/src/lib.rs | 6 +-- frame/society/src/lib.rs | 8 ++-- frame/staking/src/lib.rs | 8 +--- frame/staking/src/pallet/impls.rs | 4 +- frame/staking/src/tests.rs | 7 ++-- .../procedural/src/pallet/parse/storage.rs | 4 +- frame/support/src/dispatch.rs | 2 +- frame/support/src/storage/migration.rs | 8 ++-- frame/support/src/storage/mod.rs | 8 ++-- frame/support/test/pallet/src/lib.rs | 8 +--- frame/support/test/tests/genesisconfig.rs | 2 +- frame/support/test/tests/issue2219.rs | 4 +- frame/support/test/tests/pallet.rs | 2 +- frame/system/src/extensions/check_genesis.rs | 2 +- .../system/src/extensions/check_mortality.rs | 2 +- .../src/extensions/check_non_zero_sender.rs | 2 +- .../src/extensions/check_spec_version.rs | 2 +- .../system/src/extensions/check_tx_version.rs | 2 +- frame/system/src/lib.rs | 8 +--- frame/uniques/src/tests.rs | 2 +- frame/vesting/src/lib.rs | 9 ++-- .../api/proc-macro/src/decl_runtime_apis.rs | 5 +-- primitives/authorship/src/lib.rs | 4 +- primitives/debug-derive/src/impls.rs | 2 +- primitives/keystore/src/testing.rs | 4 +- .../npos-elections/fuzzer/src/compact.rs | 2 +- .../npos-elections/fuzzer/src/reduce.rs | 2 +- primitives/npos-elections/src/reduce.rs | 5 +-- primitives/runtime-interface/test/src/lib.rs | 41 +++++++++---------- primitives/runtime/src/generic/digest.rs | 8 +--- .../src/generic/unchecked_extrinsic.rs | 2 +- primitives/runtime/src/traits.rs | 2 +- primitives/state-machine/src/backend.rs | 2 +- primitives/state-machine/src/ext.rs | 4 +- primitives/state-machine/src/testing.rs | 2 +- primitives/timestamp/src/lib.rs | 6 +-- .../transaction-storage-proof/src/lib.rs | 6 +-- primitives/trie/src/lib.rs | 6 +-- test-utils/runtime/src/lib.rs | 8 +--- utils/frame/benchmarking-cli/src/command.rs | 4 +- utils/frame/try-runtime/cli/src/lib.rs | 1 - utils/frame/try-runtime/cli/src/parse.rs | 7 +++- 88 files changed, 190 insertions(+), 249 deletions(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index 06328af71459..de299a90971e 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -10,5 +10,24 @@ rustflags = [ "-Aclippy::all", "-Dclippy::correctness", "-Aclippy::if-same-then-else", - "-Aclippy::clone-double-ref" + "-Aclippy::clone-double-ref", + "-Dclippy::complexity", + "-Aclippy::clone_on_copy", # Too common + "-Aclippy::needless_lifetimes", # Backward compat? + "-Aclippy::zero-prefixed-literal", # 00_1000_000 + "-Aclippy::type_complexity", # raison d'etre + "-Aclippy::nonminimal-bool", # maybe + "-Aclippy::borrowed-box", # Reasonable to fix this one + "-Aclippy::too-many-arguments", # (Turning this on would lead to) + "-Aclippy::unnecessary_cast", # Types may change + "-Aclippy::identity-op", # One case where we do 0 + + "-Aclippy::useless_conversion", # Types may change + "-Aclippy::unit_arg", # styalistic. + "-Aclippy::option-map-unit-fn", # styalistic + "-Aclippy::bind_instead_of_map", # styalistic + "-Aclippy::erasing_op", # E.g. 0 * DOLLARS + "-Aclippy::eq_op", # In tests we test equality. + "-Aclippy::while_immutable_condition", # false positives + "-Aclippy::needless_option_as_deref", # false positives + "-Aclippy::derivable_impls", # false positives ] diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 685d201d8598..2aee053ef4de 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -350,7 +350,7 @@ cargo-clippy: <<: *docker-env <<: *test-refs script: - - SKIP_WASM_BUILD=1 env -u RUSTFLAGS cargo +nightly clippy + - SKIP_WASM_BUILD=1 env -u RUSTFLAGS cargo +nightly clippy --all-targets cargo-check-benches: stage: test diff --git a/bin/node-template/node/src/service.rs b/bin/node-template/node/src/service.rs index 92bd059e528a..975a491cf4da 100644 --- a/bin/node-template/node/src/service.rs +++ b/bin/node-template/node/src/service.rs @@ -60,7 +60,7 @@ pub fn new_partial( ServiceError, > { if config.keystore_remote.is_some() { - return Err(ServiceError::Other(format!("Remote Keystores are not supported."))) + return Err(ServiceError::Other("Remote Keystores are not supported.".into())) } let telemetry = config diff --git a/bin/node/inspect/src/lib.rs b/bin/node/inspect/src/lib.rs index 722a7903da4c..ff1eecd219a9 100644 --- a/bin/node/inspect/src/lib.rs +++ b/bin/node/inspect/src/lib.rs @@ -261,7 +261,7 @@ impl FromStr for ExtrinsicAddres let index = it .next() - .ok_or_else(|| format!("Extrinsic index missing: example \"5:0\""))? + .ok_or("Extrinsic index missing: example \"5:0\"")? .parse() .map_err(|e| format!("Invalid index format: {}", e))?; diff --git a/client/chain-spec/src/chain_spec.rs b/client/chain-spec/src/chain_spec.rs index 98241255de55..11e5b73fe77f 100644 --- a/client/chain-spec/src/chain_spec.rs +++ b/client/chain-spec/src/chain_spec.rs @@ -223,7 +223,7 @@ impl ChainSpec { /// Network protocol id. pub fn protocol_id(&self) -> Option<&str> { - self.client_spec.protocol_id.as_ref().map(String::as_str) + self.client_spec.protocol_id.as_deref() } /// Additional loosly-typed properties of the chain. diff --git a/client/cli/src/arg_enums.rs b/client/cli/src/arg_enums.rs index 3e1ead609630..c13361a9ac2b 100644 --- a/client/cli/src/arg_enums.rs +++ b/client/cli/src/arg_enums.rs @@ -51,7 +51,7 @@ impl std::str::FromStr for WasmExecutionMethod { } #[cfg(not(feature = "wasmtime"))] { - Err(format!("`Compiled` variant requires the `wasmtime` feature to be enabled")) + Err("`Compiled` variant requires the `wasmtime` feature to be enabled".into()) } } else { Err(format!("Unknown variant `{}`, known variants: {:?}", s, Self::variants())) diff --git a/client/cli/src/commands/sign.rs b/client/cli/src/commands/sign.rs index 1b2fbba40ea1..8d331d799459 100644 --- a/client/cli/src/commands/sign.rs +++ b/client/cli/src/commands/sign.rs @@ -70,7 +70,7 @@ fn sign( message: Vec, ) -> error::Result { let pair = utils::pair_from_suri::

(suri, password)?; - Ok(format!("{}", hex::encode(pair.sign(&message)))) + Ok(hex::encode(pair.sign(&message))) } #[cfg(test)] diff --git a/client/cli/src/commands/verify.rs b/client/cli/src/commands/verify.rs index bf03be1737d4..9ffd5d9d4844 100644 --- a/client/cli/src/commands/verify.rs +++ b/client/cli/src/commands/verify.rs @@ -57,7 +57,7 @@ impl VerifyCmd { let message = utils::read_message(self.message.as_ref(), self.hex)?; let sig_data = utils::decode_hex(&self.sig)?; let uri = utils::read_uri(self.uri.as_ref())?; - let uri = if uri.starts_with("0x") { &uri[2..] } else { &uri }; + let uri = if let Some(uri) = uri.strip_prefix("0x") { uri } else { &uri }; with_crypto_scheme!(self.crypto_scheme.scheme, verify(sig_data, message, uri)) } diff --git a/client/cli/src/params/mod.rs b/client/cli/src/params/mod.rs index c7181840a864..e6f81079263d 100644 --- a/client/cli/src/params/mod.rs +++ b/client/cli/src/params/mod.rs @@ -79,8 +79,8 @@ impl FromStr for BlockNumberOrHash { type Err = String; fn from_str(block_number: &str) -> Result { - if block_number.starts_with("0x") { - if let Some(pos) = &block_number[2..].chars().position(|c| !c.is_ascii_hexdigit()) { + if let Some(rest) = block_number.strip_prefix("0x") { + if let Some(pos) = rest.chars().position(|c| !c.is_ascii_hexdigit()) { Err(format!( "Expected block hash, found illegal hex character at position: {}", 2 + pos, diff --git a/client/consensus/common/src/block_import.rs b/client/consensus/common/src/block_import.rs index af54d54770f7..24fec9b974a4 100644 --- a/client/consensus/common/src/block_import.rs +++ b/client/consensus/common/src/block_import.rs @@ -287,9 +287,9 @@ impl BlockImportParams { pub fn take_intermediate(&mut self, key: &[u8]) -> Result, Error> { let (k, v) = self.intermediates.remove_entry(key).ok_or(Error::NoIntermediate)?; - v.downcast::().or_else(|v| { + v.downcast::().map_err(|v| { self.intermediates.insert(k, v); - Err(Error::InvalidIntermediate) + Error::InvalidIntermediate }) } diff --git a/client/consensus/manual-seal/src/consensus/babe.rs b/client/consensus/manual-seal/src/consensus/babe.rs index b16bee816b17..6d86658cbf50 100644 --- a/client/consensus/manual-seal/src/consensus/babe.rs +++ b/client/consensus/manual-seal/src/consensus/babe.rs @@ -279,7 +279,7 @@ where // a quick check to see if we're in the authorities let epoch = self.epoch(parent, slot)?; let (authority, _) = self.authorities.first().expect("authorities is non-emptyp; qed"); - let has_authority = epoch.authorities.iter().find(|(id, _)| *id == *authority).is_some(); + let has_authority = epoch.authorities.iter().any(|(id, _)| *id == *authority); if !has_authority { log::info!(target: "manual-seal", "authority not found"); diff --git a/client/consensus/manual-seal/src/lib.rs b/client/consensus/manual-seal/src/lib.rs index 3e5ce5b2a401..a057190f6b37 100644 --- a/client/consensus/manual-seal/src/lib.rs +++ b/client/consensus/manual-seal/src/lib.rs @@ -173,7 +173,7 @@ pub async fn run_manual_seal( env: &mut env, select_chain: &select_chain, block_import: &mut block_import, - consensus_data_provider: consensus_data_provider.as_ref().map(|p| &**p), + consensus_data_provider: consensus_data_provider.as_deref(), pool: pool.clone(), client: client.clone(), create_inherent_data_providers: &create_inherent_data_providers, @@ -408,8 +408,8 @@ mod tests { }) .await .unwrap(); - // assert that the background task returns ok - assert_eq!(rx.await.unwrap().unwrap(), ()); + // check that the background task returns ok: + rx.await.unwrap().unwrap(); } #[tokio::test] diff --git a/client/db/src/bench.rs b/client/db/src/bench.rs index a18e7942a54f..fe31d31dfef9 100644 --- a/client/db/src/bench.rs +++ b/client/db/src/bench.rs @@ -672,7 +672,6 @@ mod test { assert_eq!(rw_tracker.1, 0); assert_eq!(rw_tracker.2, 2); assert_eq!(rw_tracker.3, 0); - drop(rw_tracker); bench_state.wipe().unwrap(); } } diff --git a/client/db/src/lib.rs b/client/db/src/lib.rs index c570ca2f15fb..19766d76048e 100644 --- a/client/db/src/lib.rs +++ b/client/db/src/lib.rs @@ -1993,7 +1993,7 @@ impl sc_client_api::backend::Backend for Backend { }); let database_cache = MemorySize::from_bytes(0); let state_cache = - MemorySize::from_bytes((*&self.shared_cache).read().used_storage_cache_size()); + MemorySize::from_bytes(self.shared_cache.read().used_storage_cache_size()); let state_db = self.storage.state_db.memory_info(); Some(UsageInfo { @@ -2452,7 +2452,7 @@ pub(crate) mod tests { let storage = vec![(vec![1, 3, 5], None), (vec![5, 5, 5], Some(vec![4, 5, 6]))]; let (root, overlay) = op.old_state.storage_root( - storage.iter().map(|(k, v)| (&k[..], v.as_ref().map(|v| &v[..]))), + storage.iter().map(|(k, v)| (k.as_slice(), v.as_ref().map(|v| &v[..]))), state_version, ); op.update_db_storage(overlay).unwrap(); @@ -3000,7 +3000,7 @@ pub(crate) mod tests { let storage = vec![(b"test".to_vec(), Some(b"test2".to_vec()))]; let (root, overlay) = op.old_state.storage_root( - storage.iter().map(|(k, v)| (&k[..], v.as_ref().map(|v| &v[..]))), + storage.iter().map(|(k, v)| (k.as_slice(), v.as_ref().map(|v| &v[..]))), state_version, ); op.update_db_storage(overlay).unwrap(); diff --git a/client/db/src/offchain.rs b/client/db/src/offchain.rs index c6351a66a235..4f0a77ce5756 100644 --- a/client/db/src/offchain.rs +++ b/client/db/src/offchain.rs @@ -92,7 +92,7 @@ impl sp_core::offchain::OffchainStorage for LocalStorage { { let _key_guard = key_lock.lock(); let val = self.db.get(columns::OFFCHAIN, &key); - is_set = val.as_ref().map(|x| &**x) == old_value; + is_set = val.as_deref() == old_value; if is_set { self.set(prefix, item_key, new_value) diff --git a/client/executor/src/integration_tests/mod.rs b/client/executor/src/integration_tests/mod.rs index 36339c31871d..67e9a96cd6ba 100644 --- a/client/executor/src/integration_tests/mod.rs +++ b/client/executor/src/integration_tests/mod.rs @@ -126,7 +126,7 @@ fn call_in_wasm( let executor = crate::WasmExecutor::::new(execution_method, Some(1024), 8, None, 2); executor.uncached_call( - RuntimeBlob::uncompress_if_needed(&wasm_binary_unwrap()[..]).unwrap(), + RuntimeBlob::uncompress_if_needed(wasm_binary_unwrap()).unwrap(), ext, true, function, @@ -479,7 +479,7 @@ fn should_trap_when_heap_exhausted(wasm_method: WasmExecutionMethod) { let err = executor .uncached_call( - RuntimeBlob::uncompress_if_needed(&wasm_binary_unwrap()[..]).unwrap(), + RuntimeBlob::uncompress_if_needed(wasm_binary_unwrap()).unwrap(), &mut ext.ext(), true, "test_exhaust_heap", @@ -491,7 +491,7 @@ fn should_trap_when_heap_exhausted(wasm_method: WasmExecutionMethod) { } fn mk_test_runtime(wasm_method: WasmExecutionMethod, pages: u64) -> Arc { - let blob = RuntimeBlob::uncompress_if_needed(&wasm_binary_unwrap()[..]) + let blob = RuntimeBlob::uncompress_if_needed(wasm_binary_unwrap()) .expect("failed to create a runtime blob out of test runtime"); crate::wasm_runtime::create_wasm_runtime_with_code::( @@ -597,7 +597,7 @@ fn parallel_execution(wasm_method: WasmExecutionMethod) { assert_eq!( executor .uncached_call( - RuntimeBlob::uncompress_if_needed(&wasm_binary_unwrap()[..]).unwrap(), + RuntimeBlob::uncompress_if_needed(wasm_binary_unwrap()).unwrap(), &mut ext, true, "test_twox_128", @@ -691,7 +691,7 @@ fn panic_in_spawned_instance_panics_on_joining_its_result(wasm_method: WasmExecu let error_result = call_in_wasm("test_panic_in_spawned", &[], wasm_method, &mut ext).unwrap_err(); - assert!(format!("{}", error_result).contains("Spawned task")); + assert!(error_result.contains("Spawned task")); } test_wasm_execution!(memory_is_cleared_between_invocations); diff --git a/client/executor/src/lib.rs b/client/executor/src/lib.rs index fd127887dbc2..5cd04b9e4ee6 100644 --- a/client/executor/src/lib.rs +++ b/client/executor/src/lib.rs @@ -82,7 +82,7 @@ mod tests { ); let res = executor .uncached_call( - RuntimeBlob::uncompress_if_needed(&wasm_binary_unwrap()[..]).unwrap(), + RuntimeBlob::uncompress_if_needed(wasm_binary_unwrap()).unwrap(), &mut ext, true, "test_empty_return", diff --git a/client/executor/src/wasm_runtime.rs b/client/executor/src/wasm_runtime.rs index cb6fba4e4dee..0775755aff7c 100644 --- a/client/executor/src/wasm_runtime.rs +++ b/client/executor/src/wasm_runtime.rs @@ -77,7 +77,7 @@ struct VersionedRuntime { impl VersionedRuntime { /// Run the given closure `f` with an instance of this runtime. - fn with_instance<'c, R, F>(&self, ext: &mut dyn Externalities, f: F) -> Result + fn with_instance(&self, ext: &mut dyn Externalities, f: F) -> Result where F: FnOnce( &Arc, diff --git a/client/executor/wasmtime/src/host.rs b/client/executor/wasmtime/src/host.rs index 5d02a836640a..5da8ff325903 100644 --- a/client/executor/wasmtime/src/host.rs +++ b/client/executor/wasmtime/src/host.rs @@ -195,7 +195,7 @@ impl<'a> Sandbox for HostContext<'a> { &mut self, instance_id: u32, export_name: &str, - args: &[u8], + mut args: &[u8], return_val: Pointer, return_val_len: u32, state: u32, @@ -203,7 +203,7 @@ impl<'a> Sandbox for HostContext<'a> { trace!(target: "sp-sandbox", "invoke, instance_idx={}", instance_id); // Deserialize arguments and convert them into wasmi types. - let args = Vec::::decode(&mut &args[..]) + let args = Vec::::decode(&mut args) .map_err(|_| "Can't decode serialized arguments for the invocation")? .into_iter() .map(Into::into) diff --git a/client/executor/wasmtime/src/tests.rs b/client/executor/wasmtime/src/tests.rs index c1e626f12d1a..08807f1dec41 100644 --- a/client/executor/wasmtime/src/tests.rs +++ b/client/executor/wasmtime/src/tests.rs @@ -313,7 +313,7 @@ fn test_max_memory_pages() { #[test] fn test_instances_without_reuse_are_not_leaked() { let runtime = crate::create_runtime::( - RuntimeBlob::uncompress_if_needed(&wasm_binary_unwrap()[..]).unwrap(), + RuntimeBlob::uncompress_if_needed(wasm_binary_unwrap()).unwrap(), crate::Config { heap_pages: 2048, max_memory_size: None, diff --git a/client/finality-grandpa/src/communication/gossip.rs b/client/finality-grandpa/src/communication/gossip.rs index 51d832c3b27b..4e8e047a9b64 100644 --- a/client/finality-grandpa/src/communication/gossip.rs +++ b/client/finality-grandpa/src/communication/gossip.rs @@ -615,8 +615,7 @@ impl Peers { // `LUCKY_PEERS / 2` is filled we start allocating to the second stage set. let half_lucky = LUCKY_PEERS / 2; let one_and_a_half_lucky = LUCKY_PEERS + half_lucky; - let mut n_authorities_added = 0; - for peer_id in shuffled_authorities { + for (n_authorities_added, peer_id) in shuffled_authorities.enumerate() { if n_authorities_added < half_lucky { first_stage_peers.insert(*peer_id); } else if n_authorities_added < one_and_a_half_lucky { @@ -624,8 +623,6 @@ impl Peers { } else { break } - - n_authorities_added += 1; } // fill up first and second sets with remaining peers (either full or authorities) diff --git a/client/finality-grandpa/src/lib.rs b/client/finality-grandpa/src/lib.rs index b8873d00efa7..af85965c53c1 100644 --- a/client/finality-grandpa/src/lib.rs +++ b/client/finality-grandpa/src/lib.rs @@ -267,7 +267,7 @@ pub struct Config { impl Config { fn name(&self) -> &str { - self.name.as_ref().map(|s| s.as_str()).unwrap_or("") + self.name.as_deref().unwrap_or("") } } diff --git a/client/rpc/src/state/state_full.rs b/client/rpc/src/state/state_full.rs index 2c5a985a2b01..b8132094fe8d 100644 --- a/client/rpc/src/state/state_full.rs +++ b/client/rpc/src/state/state_full.rs @@ -441,10 +441,7 @@ where keys: Option>, ) { let keys = Into::>>::into(keys); - let stream = match self - .client - .storage_changes_notification_stream(keys.as_ref().map(|x| &**x), None) - { + let stream = match self.client.storage_changes_notification_stream(keys.as_deref(), None) { Ok(stream) => stream, Err(err) => { let _ = subscriber.reject(client_err(err).into()); diff --git a/client/rpc/src/state/tests.rs b/client/rpc/src/state/tests.rs index d3aca181a41e..9dbe02cdb7d6 100644 --- a/client/rpc/src/state/tests.rs +++ b/client/rpc/src/state/tests.rs @@ -32,7 +32,7 @@ use substrate_test_runtime_client::{prelude::*, runtime}; const STORAGE_KEY: &[u8] = b"child"; fn prefixed_storage_key() -> PrefixedStorageKey { - let child_info = ChildInfo::new_default(&STORAGE_KEY[..]); + let child_info = ChildInfo::new_default(STORAGE_KEY); child_info.prefixed_storage_key() } diff --git a/client/rpc/src/system/tests.rs b/client/rpc/src/system/tests.rs index 3e5241e2638b..5d6945b71420 100644 --- a/client/rpc/src/system/tests.rs +++ b/client/rpc/src/system/tests.rs @@ -354,26 +354,26 @@ fn test_add_reset_log_filter() { }; // Initiate logs loop in child process - child_in.write(b"\n").unwrap(); + child_in.write_all(b"\n").unwrap(); assert!(read_line().contains(EXPECTED_BEFORE_ADD)); // Initiate add directive & reload in child process - child_in.write(b"add_reload\n").unwrap(); + child_in.write_all(b"add_reload\n").unwrap(); assert!(read_line().contains(EXPECTED_BEFORE_ADD)); assert!(read_line().contains(EXPECTED_AFTER_ADD)); // Check that increasing the max log level works - child_in.write(b"add_trace\n").unwrap(); + child_in.write_all(b"add_trace\n").unwrap(); assert!(read_line().contains(EXPECTED_WITH_TRACE)); assert!(read_line().contains(EXPECTED_BEFORE_ADD)); assert!(read_line().contains(EXPECTED_AFTER_ADD)); // Initiate logs filter reset in child process - child_in.write(b"reset\n").unwrap(); + child_in.write_all(b"reset\n").unwrap(); assert!(read_line().contains(EXPECTED_BEFORE_ADD)); // Return from child process - child_in.write(b"exit\n").unwrap(); + child_in.write_all(b"exit\n").unwrap(); assert!(child_process.wait().expect("Error waiting for child process").success()); // Check for EOF diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index 262ba53a33d4..c713b4936c6b 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -363,7 +363,7 @@ where spawn_handle, config.clone(), )?; - Ok(crate::client::Client::new( + crate::client::Client::new( backend, executor, genesis_storage, @@ -373,7 +373,7 @@ where prometheus_registry, telemetry, config, - )?) + ) } /// Parameters to pass into `build`. diff --git a/client/service/src/client/call_executor.rs b/client/service/src/client/call_executor.rs index 739ad029dc19..fedd3400488d 100644 --- a/client/service/src/client/call_executor.rs +++ b/client/service/src/client/call_executor.rs @@ -266,9 +266,7 @@ where &runtime_code, self.spawn_handle.clone(), ) - .with_storage_transaction_cache( - storage_transaction_cache.as_mut().map(|c| &mut **c), - ) + .with_storage_transaction_cache(storage_transaction_cache.as_deref_mut()) .set_parent_hash(at_hash); state_machine.execute_using_consensus_failure_handler( execution_manager, diff --git a/client/service/src/client/client.rs b/client/service/src/client/client.rs index 452450c71e78..9d898c7d1eb8 100644 --- a/client/service/src/client/client.rs +++ b/client/service/src/client/client.rs @@ -1409,10 +1409,9 @@ where id: &BlockId, key: &StorageKey, ) -> sp_blockchain::Result> { - Ok(self - .state_at(id)? + self.state_at(id)? .storage_hash(&key.0) - .map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))?) + .map_err(|e| sp_blockchain::Error::from_state(Box::new(e))) } fn child_storage_keys( @@ -1449,10 +1448,9 @@ where child_info: &ChildInfo, key: &StorageKey, ) -> sp_blockchain::Result> { - Ok(self - .state_at(id)? + self.state_at(id)? .child_storage_hash(child_info, &key.0) - .map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))?) + .map_err(|e| sp_blockchain::Error::from_state(Box::new(e))) } } diff --git a/client/state-db/src/noncanonical.rs b/client/state-db/src/noncanonical.rs index 0509e54946e9..d7c83492e563 100644 --- a/client/state-db/src/noncanonical.rs +++ b/client/state-db/src/noncanonical.rs @@ -134,12 +134,12 @@ fn discard_descendants( hash: &BlockHash, ) -> u32 { let (first, mut remainder) = if let Some((first, rest)) = levels.0.split_first_mut() { - (Some(first), (rest, &mut levels.1[..])) + (Some(first), (rest, &mut *levels.1)) } else { if let Some((first, rest)) = levels.1.split_first_mut() { - (Some(first), (&mut levels.0[..], rest)) + (Some(first), (&mut *levels.0, rest)) } else { - (None, (&mut levels.0[..], &mut levels.1[..])) + (None, (&mut *levels.0, &mut *levels.1)) } }; let mut pinned_children = 0; @@ -261,8 +261,7 @@ impl NonCanonicalOverlay { .push((to_meta_key(LAST_CANONICAL, &()), last_canonicalized.encode())); self.last_canonicalized = Some(last_canonicalized); } else if self.last_canonicalized.is_some() { - if number < front_block_number || - number >= front_block_number + self.levels.len() as u64 + 1 + if number < front_block_number || number > front_block_number + self.levels.len() as u64 { trace!(target: "state-db", "Failed to insert block {}, current is {} .. {})", number, diff --git a/client/tracing/proc-macro/src/lib.rs b/client/tracing/proc-macro/src/lib.rs index b1ffcb97b752..ba757619fb5a 100644 --- a/client/tracing/proc-macro/src/lib.rs +++ b/client/tracing/proc-macro/src/lib.rs @@ -119,7 +119,7 @@ pub fn prefix_logs_with(arg: TokenStream, item: TokenStream) -> TokenStream { let name = syn::parse_macro_input!(arg as Expr); let crate_name = match crate_name("sc-tracing") { - Ok(FoundCrate::Itself) => Ident::from(Ident::new("sc_tracing", Span::call_site())), + Ok(FoundCrate::Itself) => Ident::new("sc_tracing", Span::call_site()), Ok(FoundCrate::Name(crate_name)) => Ident::new(&crate_name, Span::call_site()), Err(e) => return Error::new(Span::call_site(), e).to_compile_error().into(), }; diff --git a/client/tracing/src/block/mod.rs b/client/tracing/src/block/mod.rs index 8280d4613a18..067cdafa0ae3 100644 --- a/client/tracing/src/block/mod.rs +++ b/client/tracing/src/block/mod.rs @@ -267,7 +267,7 @@ where .lock() .drain() // Patch wasm identifiers - .filter_map(|(_, s)| patch_and_filter(SpanDatum::from(s), targets)) + .filter_map(|(_, s)| patch_and_filter(s, targets)) .collect(); let events: Vec<_> = block_subscriber .events @@ -315,7 +315,7 @@ fn event_values_filter(event: &TraceEvent, filter_kind: &str, values: &str) -> b .values .string_values .get(filter_kind) - .and_then(|value| Some(check_target(values, value, &event.level))) + .map(|value| check_target(values, value, &event.level)) .unwrap_or(false) } diff --git a/client/tracing/src/lib.rs b/client/tracing/src/lib.rs index cbbd8063c34f..ff3723e0d1a9 100644 --- a/client/tracing/src/lib.rs +++ b/client/tracing/src/lib.rs @@ -464,7 +464,10 @@ impl From for sp_rpc::tracing::Span { mod tests { use super::*; use parking_lot::Mutex; - use std::sync::Arc; + use std::sync::{ + mpsc::{Receiver, Sender}, + Arc, + }; use tracing_subscriber::layer::SubscriberExt; struct TestTraceHandler { @@ -617,14 +620,14 @@ mod tests { let span1 = tracing::info_span!(target: "test_target", "test_span1"); let _guard1 = span1.enter(); - let (tx, rx) = mpsc::channel(); + let (tx, rx): (Sender, Receiver) = mpsc::channel(); let handle = thread::spawn(move || { let span2 = tracing::info_span!(target: "test_target", "test_span2"); let _guard2 = span2.enter(); // emit event tracing::event!(target: "test_target", tracing::Level::INFO, "test_event1"); for msg in rx.recv() { - if msg == false { + if !msg { break } } diff --git a/client/transaction-pool/src/graph/pool.rs b/client/transaction-pool/src/graph/pool.rs index 909ea559f552..39be43f82c8b 100644 --- a/client/transaction-pool/src/graph/pool.rs +++ b/client/transaction-pool/src/graph/pool.rs @@ -224,12 +224,8 @@ impl Pool { hashes: &[ExtrinsicHash], ) -> Result<(), B::Error> { // Get details of all extrinsics that are already in the pool - let in_pool_tags = self - .validated_pool - .extrinsics_tags(hashes) - .into_iter() - .filter_map(|x| x) - .flatten(); + let in_pool_tags = + self.validated_pool.extrinsics_tags(hashes).into_iter().flatten().flatten(); // Prune all transactions that provide given tags let prune_status = self.validated_pool.prune_tags(in_pool_tags)?; diff --git a/frame/authority-discovery/src/lib.rs b/frame/authority-discovery/src/lib.rs index d5f0a4c1d339..03f6e753fd47 100644 --- a/frame/authority-discovery/src/lib.rs +++ b/frame/authority-discovery/src/lib.rs @@ -61,17 +61,12 @@ pub mod pallet { pub(super) type NextKeys = StorageValue<_, WeakBoundedVec, ValueQuery>; + #[cfg_attr(feature = "std", derive(Default))] #[pallet::genesis_config] pub struct GenesisConfig { pub keys: Vec, } - #[cfg(feature = "std")] - impl Default for GenesisConfig { - fn default() -> Self { - Self { keys: Default::default() } - } - } #[pallet::genesis_build] impl GenesisBuild for GenesisConfig { fn build(&self) { diff --git a/frame/authorship/src/lib.rs b/frame/authorship/src/lib.rs index 6f825e4e7dff..db453fc57e9e 100644 --- a/frame/authorship/src/lib.rs +++ b/frame/authorship/src/lib.rs @@ -479,9 +479,9 @@ mod tests { where I: 'a + IntoIterator, { - for (id, data) in digests { + for (id, mut data) in digests { if id == TEST_ID { - return u64::decode(&mut &data[..]).ok() + return u64::decode(&mut data).ok() } } @@ -499,9 +499,9 @@ mod tests { let author = AuthorGiven::find_author(pre_runtime_digests).ok_or_else(|| "no author")?; - for (id, seal) in seals { + for (id, mut seal) in seals { if id == TEST_ID { - match u64::decode(&mut &seal[..]) { + match u64::decode(&mut seal) { Err(_) => return Err("wrong seal"), Ok(a) => { if a != author { diff --git a/frame/babe/src/lib.rs b/frame/babe/src/lib.rs index 424f2df5c16d..e2cc36ca098f 100644 --- a/frame/babe/src/lib.rs +++ b/frame/babe/src/lib.rs @@ -310,19 +310,13 @@ pub mod pallet { #[pallet::storage] pub(super) type NextEpochConfig = StorageValue<_, BabeEpochConfiguration>; + #[cfg_attr(feature = "std", derive(Default))] #[pallet::genesis_config] pub struct GenesisConfig { pub authorities: Vec<(AuthorityId, BabeAuthorityWeight)>, pub epoch_config: Option, } - #[cfg(feature = "std")] - impl Default for GenesisConfig { - fn default() -> Self { - GenesisConfig { authorities: Default::default(), epoch_config: Default::default() } - } - } - #[pallet::genesis_build] impl GenesisBuild for GenesisConfig { fn build(&self) { diff --git a/frame/bags-list/src/list/mod.rs b/frame/bags-list/src/list/mod.rs index 17844b51d4d5..aba31b67b286 100644 --- a/frame/bags-list/src/list/mod.rs +++ b/frame/bags-list/src/list/mod.rs @@ -742,7 +742,7 @@ impl Bag { /// Check if the bag contains a node with `id`. #[cfg(feature = "std")] fn contains(&self, id: &T::AccountId) -> bool { - self.iter().find(|n| n.id() == id).is_some() + self.iter().any(|n| n.id() == id) } } diff --git a/frame/balances/src/lib.rs b/frame/balances/src/lib.rs index a774cfd61edf..86e3f2ec0598 100644 --- a/frame/balances/src/lib.rs +++ b/frame/balances/src/lib.rs @@ -409,12 +409,7 @@ pub mod pallet { let reducible_balance = Self::reducible_balance(&transactor, keep_alive); let dest = T::Lookup::lookup(dest)?; let keep_alive = if keep_alive { KeepAlive } else { AllowDeath }; - >::transfer( - &transactor, - &dest, - reducible_balance, - keep_alive.into(), - )?; + >::transfer(&transactor, &dest, reducible_balance, keep_alive)?; Ok(()) } @@ -619,7 +614,7 @@ pub enum Reasons { impl From for Reasons { fn from(r: WithdrawReasons) -> Reasons { - if r == WithdrawReasons::from(WithdrawReasons::TRANSACTION_PAYMENT) { + if r == WithdrawReasons::TRANSACTION_PAYMENT { Reasons::Fee } else if r.contains(WithdrawReasons::TRANSACTION_PAYMENT) { Reasons::All diff --git a/frame/contracts/src/storage/meter.rs b/frame/contracts/src/storage/meter.rs index 2dbd7ede615d..28dc3356f714 100644 --- a/frame/contracts/src/storage/meter.rs +++ b/frame/contracts/src/storage/meter.rs @@ -592,8 +592,7 @@ mod tests { contract: BOB, amount: Deposit::Charge(::Currency::minimum_balance() * 2), terminated: false, - }], - ..Default::default() + }] } ) }); @@ -663,8 +662,7 @@ mod tests { amount: Deposit::Charge(2), terminated: false } - ], - ..Default::default() + ] } ) }); @@ -717,8 +715,7 @@ mod tests { amount: Deposit::Charge(12), terminated: false } - ], - ..Default::default() + ] } ) }); diff --git a/frame/contracts/src/wasm/runtime.rs b/frame/contracts/src/wasm/runtime.rs index cae68208b31e..7c9e19f6ef78 100644 --- a/frame/contracts/src/wasm/runtime.rs +++ b/frame/contracts/src/wasm/runtime.rs @@ -1592,7 +1592,7 @@ define_env!(Env, , output_len_ptr: u32 ) -> u32 => { use crate::chain_extension::{ChainExtension, Environment, RetVal}; - if ::ChainExtension::enabled() == false { + if !::ChainExtension::enabled() { Err(Error::::NoChainExtension)?; } let env = Environment::new(ctx, input_ptr, input_len, output_ptr, output_len_ptr); diff --git a/frame/election-provider-multi-phase/src/unsigned.rs b/frame/election-provider-multi-phase/src/unsigned.rs index 6ce0ddfe6764..da56dd4d073d 100644 --- a/frame/election-provider-multi-phase/src/unsigned.rs +++ b/frame/election-provider-multi-phase/src/unsigned.rs @@ -544,7 +544,7 @@ impl Pallet { // Time to finish. We might have reduced less than expected due to rounding error. Increase // one last time if we have any room left, the reduce until we are sure we are below limit. - while voters + 1 <= max_voters && weight_with(voters + 1) < max_weight { + while voters < max_voters && weight_with(voters + 1) < max_weight { voters += 1; } while voters.checked_sub(1).is_some() && weight_with(voters) > max_weight { diff --git a/frame/elections-phragmen/src/lib.rs b/frame/elections-phragmen/src/lib.rs index 06474cd37bbd..b0e0a6fb984e 100644 --- a/frame/elections-phragmen/src/lib.rs +++ b/frame/elections-phragmen/src/lib.rs @@ -836,7 +836,7 @@ impl Pallet { /// Check if `who` is currently an active runner-up. fn is_runner_up(who: &T::AccountId) -> bool { - Self::runners_up().iter().position(|r| &r.who == who).is_some() + Self::runners_up().iter().any(|r| &r.who == who) } /// Get the members' account ids. diff --git a/frame/examples/basic/src/lib.rs b/frame/examples/basic/src/lib.rs index 13c4591be28f..56e8db693624 100644 --- a/frame/examples/basic/src/lib.rs +++ b/frame/examples/basic/src/lib.rs @@ -738,7 +738,7 @@ where info: &DispatchInfoOf, len: usize, ) -> Result { - Ok(self.validate(who, call, info, len).map(|_| ())?) + self.validate(who, call, info, len).map(|_| ()) } fn validate( diff --git a/frame/grandpa/src/lib.rs b/frame/grandpa/src/lib.rs index 560c933f108c..1f6139cf81fd 100644 --- a/frame/grandpa/src/lib.rs +++ b/frame/grandpa/src/lib.rs @@ -327,18 +327,12 @@ pub mod pallet { #[pallet::getter(fn session_for_set)] pub(super) type SetIdSession = StorageMap<_, Twox64Concat, SetId, SessionIndex>; + #[cfg_attr(feature = "std", derive(Default))] #[pallet::genesis_config] pub struct GenesisConfig { pub authorities: AuthorityList, } - #[cfg(feature = "std")] - impl Default for GenesisConfig { - fn default() -> Self { - Self { authorities: Default::default() } - } - } - #[pallet::genesis_build] impl GenesisBuild for GenesisConfig { fn build(&self) { diff --git a/frame/im-online/src/tests.rs b/frame/im-online/src/tests.rs index cab5df9ebe54..288081556a08 100644 --- a/frame/im-online/src/tests.rs +++ b/frame/im-online/src/tests.rs @@ -341,7 +341,7 @@ fn should_not_send_a_report_if_already_online() { UintAuthorityId::set_all_keys(vec![1, 2, 3]); // we expect error, since the authority is already online. let mut res = ImOnline::send_heartbeats(4).unwrap(); - assert_eq!(res.next().unwrap().unwrap(), ()); + res.next().unwrap().unwrap(); assert_eq!(res.next().unwrap().unwrap_err(), OffchainErr::AlreadyOnline(1)); assert_eq!(res.next().unwrap().unwrap_err(), OffchainErr::AlreadyOnline(2)); assert_eq!(res.next(), None); diff --git a/frame/scored-pool/src/mock.rs b/frame/scored-pool/src/mock.rs index e349d7a1cc9a..4fef5385eb2c 100644 --- a/frame/scored-pool/src/mock.rs +++ b/frame/scored-pool/src/mock.rs @@ -153,7 +153,6 @@ pub fn new_test_ext() -> sp_io::TestExternalities { pallet_scored_pool::GenesisConfig:: { pool: vec![(5, None), (10, Some(1)), (20, Some(2)), (31, Some(2)), (40, Some(3))], member_count: 2, - ..Default::default() } .assimilate_storage(&mut t) .unwrap(); diff --git a/frame/session/src/lib.rs b/frame/session/src/lib.rs index cae9a6159b16..7a0783718705 100644 --- a/frame/session/src/lib.rs +++ b/frame/session/src/lib.rs @@ -480,11 +480,11 @@ pub mod pallet { let queued_keys: Vec<_> = initial_validators_1 .iter() .cloned() - .filter_map(|v| { - Some(( + .map(|v| { + ( v.clone(), Pallet::::load_keys(&v).expect("Validator in session 1 missing keys!"), - )) + ) }) .collect(); diff --git a/frame/society/src/lib.rs b/frame/society/src/lib.rs index abc90d5186f2..3d2814ad5232 100644 --- a/frame/society/src/lib.rs +++ b/frame/society/src/lib.rs @@ -1290,7 +1290,7 @@ fn pick_item<'a, R: RngCore, T>(rng: &mut R, items: &'a [T]) -> Option<&'a T> { } /// Pick a new PRN, in the range [0, `max`] (inclusive). -fn pick_usize<'a, R: RngCore>(rng: &mut R, max: usize) -> usize { +fn pick_usize(rng: &mut R, max: usize) -> usize { (rng.next_u32() % (max as u32 + 1)) as usize } @@ -1316,9 +1316,9 @@ impl, I: 'static> Pallet { // Skip ahead to the suggested position .skip(pos) // Keep skipping ahead until the position changes - .skip_while(|(_, x)| x.value <= bids[pos].value) // Get the element when things changed - .next(); + .find(|(_, x)| x.value > bids[pos].value); + // If the element is not at the end of the list, insert the new element // in the spot. if let Some((p, _)) = different_bid { @@ -1351,7 +1351,7 @@ impl, I: 'static> Pallet { /// Check a user is a bid. fn is_bid(bids: &Vec>>, who: &T::AccountId) -> bool { // Bids are ordered by `value`, so we cannot binary search for a user. - bids.iter().find(|bid| bid.who == *who).is_some() + bids.iter().any(|bid| bid.who == *who) } /// Check a user is a candidate. diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index f6e052691754..268618fb5f44 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -412,7 +412,7 @@ impl Default for RewardDestination { } /// Preference of what happens regarding validation. -#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo)] +#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo, Default)] pub struct ValidatorPrefs { /// Reward that validator takes up-front; only the rest is split between themselves and /// nominators. @@ -424,12 +424,6 @@ pub struct ValidatorPrefs { pub blocked: bool, } -impl Default for ValidatorPrefs { - fn default() -> Self { - ValidatorPrefs { commission: Default::default(), blocked: false } - } -} - /// Just a Balance/BlockNumber tuple to encode when a chunk of funds will be unlocked. #[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo)] pub struct UnlockChunk { diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index dcbba6363205..ea2c746ed717 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -224,7 +224,7 @@ impl Pallet { let dest = Self::payee(stash); match dest { RewardDestination::Controller => Self::bonded(stash) - .and_then(|controller| Some(T::Currency::deposit_creating(&controller, amount))), + .map(|controller| T::Currency::deposit_creating(&controller, amount)), RewardDestination::Stash => T::Currency::deposit_into_existing(stash, amount).ok(), RewardDestination::Staked => Self::bonded(stash) .and_then(|c| Self::ledger(&c).map(|l| (c, l))) @@ -1160,7 +1160,7 @@ where add_db_reads_writes(1, 0); // Reverse because it's more likely to find reports from recent eras. - match eras.iter().rev().filter(|&&(_, ref sesh)| sesh <= &slash_session).next() { + match eras.iter().rev().find(|&&(_, ref sesh)| sesh <= &slash_session) { Some(&(ref slash_era, _)) => *slash_era, // Before bonding period. defensive - should be filtered out. None => return consumed_weight, diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 7990245068f9..8d465c8c93dc 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -2262,7 +2262,7 @@ fn slash_in_old_span_does_not_deselect() { ); // the validator doesn't get chilled again - assert!(::Validators::iter().find(|(stash, _)| *stash == 11).is_some()); + assert!(::Validators::iter().any(|(stash, _)| stash == 11)); // but we are still forcing a new era assert_eq!(Staking::force_era(), Forcing::ForceNew); @@ -2279,7 +2279,7 @@ fn slash_in_old_span_does_not_deselect() { ); // the validator doesn't get chilled again - assert!(::Validators::iter().find(|(stash, _)| *stash == 11).is_some()); + assert!(::Validators::iter().any(|(stash, _)| stash == 11)); // but it's disabled assert!(is_disabled(10)); @@ -4003,8 +4003,7 @@ mod election_data_provider { assert!(>::iter().map(|(x, _)| x).all(|v| Staking::voters(None) .unwrap() .into_iter() - .find(|(w, _, t)| { v == *w && t[0] == *w }) - .is_some())) + .any(|(w, _, t)| { v == w && t[0] == w }))) }) } diff --git a/frame/support/procedural/src/pallet/parse/storage.rs b/frame/support/procedural/src/pallet/parse/storage.rs index ca48c568e158..effe0ce6c55d 100644 --- a/frame/support/procedural/src/pallet/parse/storage.rs +++ b/frame/support/procedural/src/pallet/parse/storage.rs @@ -704,11 +704,11 @@ impl StorageDef { }) .unwrap_or(Some(QueryKind::OptionQuery)); // This value must match the default generic. - if query_kind.is_none() && getter.is_some() { + if let (None, Some(getter)) = (query_kind.as_ref(), getter.as_ref()) { let msg = "Invalid pallet::storage, cannot generate getter because QueryKind is not \ identifiable. QueryKind must be `OptionQuery`, `ValueQuery`, or default one to be \ identifiable."; - return Err(syn::Error::new(getter.unwrap().span(), msg)) + return Err(syn::Error::new(getter.span(), msg)) } Ok(StorageDef { diff --git a/frame/support/src/dispatch.rs b/frame/support/src/dispatch.rs index 765fb5d9d7c3..b5f4ab97767c 100644 --- a/frame/support/src/dispatch.rs +++ b/frame/support/src/dispatch.rs @@ -1546,7 +1546,7 @@ macro_rules! decl_module { ::current_storage_version(), ); - (|| { $( $impl )* })() + { $( $impl )* } } #[cfg(feature = "try-runtime")] diff --git a/frame/support/src/storage/migration.rs b/frame/support/src/storage/migration.rs index b2339efd0d20..713c2b0f3fe0 100644 --- a/frame/support/src/storage/migration.rs +++ b/frame/support/src/storage/migration.rs @@ -181,8 +181,8 @@ pub fn storage_iter_with_suffix( prefix.extend_from_slice(&storage_prefix); prefix.extend_from_slice(suffix); let previous_key = prefix.clone(); - let closure = |raw_key_without_prefix: &[u8], raw_value: &[u8]| { - let value = T::decode(&mut &raw_value[..])?; + let closure = |raw_key_without_prefix: &[u8], mut raw_value: &[u8]| { + let value = T::decode(&mut raw_value)?; Ok((raw_key_without_prefix.to_vec(), value)) }; @@ -213,10 +213,10 @@ pub fn storage_key_iter_with_suffix< prefix.extend_from_slice(&storage_prefix); prefix.extend_from_slice(suffix); let previous_key = prefix.clone(); - let closure = |raw_key_without_prefix: &[u8], raw_value: &[u8]| { + let closure = |raw_key_without_prefix: &[u8], mut raw_value: &[u8]| { let mut key_material = H::reverse(raw_key_without_prefix); let key = K::decode(&mut key_material)?; - let value = T::decode(&mut &raw_value[..])?; + let value = T::decode(&mut raw_value)?; Ok((key, value)) }; PrefixIterator { prefix, previous_key, drain: false, closure, phantom: Default::default() } diff --git a/frame/support/src/storage/mod.rs b/frame/support/src/storage/mod.rs index d79ddf09b7cc..04876895dc49 100644 --- a/frame/support/src/storage/mod.rs +++ b/frame/support/src/storage/mod.rs @@ -1018,8 +1018,8 @@ impl ChildTriePrefixIterator<(Vec, T)> { pub fn with_prefix(child_info: &ChildInfo, prefix: &[u8]) -> Self { let prefix = prefix.to_vec(); let previous_key = prefix.clone(); - let closure = |raw_key_without_prefix: &[u8], raw_value: &[u8]| { - let value = T::decode(&mut &raw_value[..])?; + let closure = |raw_key_without_prefix: &[u8], mut raw_value: &[u8]| { + let value = T::decode(&mut raw_value)?; Ok((raw_key_without_prefix.to_vec(), value)) }; @@ -1045,10 +1045,10 @@ impl ChildTriePrefixIterator<(K, T)> { ) -> Self { let prefix = prefix.to_vec(); let previous_key = prefix.clone(); - let closure = |raw_key_without_prefix: &[u8], raw_value: &[u8]| { + let closure = |raw_key_without_prefix: &[u8], mut raw_value: &[u8]| { let mut key_material = H::reverse(raw_key_without_prefix); let key = K::decode(&mut key_material)?; - let value = T::decode(&mut &raw_value[..])?; + let value = T::decode(&mut raw_value)?; Ok((key, value)) }; diff --git a/frame/support/test/pallet/src/lib.rs b/frame/support/test/pallet/src/lib.rs index bd181ea5b81b..25741313c2a0 100644 --- a/frame/support/test/pallet/src/lib.rs +++ b/frame/support/test/pallet/src/lib.rs @@ -30,15 +30,9 @@ pub mod pallet { pub trait Config: frame_system::Config {} #[pallet::genesis_config] + #[cfg_attr(feature = "std", derive(Default))] pub struct GenesisConfig {} - #[cfg(feature = "std")] - impl Default for GenesisConfig { - fn default() -> Self { - Self {} - } - } - #[pallet::genesis_build] impl GenesisBuild for GenesisConfig { fn build(&self) {} diff --git a/frame/support/test/tests/genesisconfig.rs b/frame/support/test/tests/genesisconfig.rs index 7895e863fd82..367c7236d015 100644 --- a/frame/support/test/tests/genesisconfig.rs +++ b/frame/support/test/tests/genesisconfig.rs @@ -40,5 +40,5 @@ impl Config for Test {} #[test] fn init_genesis_config() { - GenesisConfig:: { t: Default::default() }; + GenesisConfig::::default(); } diff --git a/frame/support/test/tests/issue2219.rs b/frame/support/test/tests/issue2219.rs index 196068ac2fa4..d7e3d2cb5b13 100644 --- a/frame/support/test/tests/issue2219.rs +++ b/frame/support/test/tests/issue2219.rs @@ -184,7 +184,9 @@ frame_support::construct_runtime!( #[test] fn create_genesis_config() { - GenesisConfig { + let config = GenesisConfig { module: module::GenesisConfig { request_life_time: 0, enable_storage_role: true }, }; + assert_eq!(config.module.request_life_time, 0); + assert!(config.module.enable_storage_role); } diff --git a/frame/support/test/tests/pallet.rs b/frame/support/test/tests/pallet.rs index 1e923a6fdd6e..59b581eda58e 100644 --- a/frame/support/test/tests/pallet.rs +++ b/frame/support/test/tests/pallet.rs @@ -881,7 +881,7 @@ fn pallet_expand_deposit_event() { #[test] fn pallet_new_call_variant() { - Call::Example(pallet::Call::new_call_variant_foo(3, 4)); + pallet::Call::::new_call_variant_foo(3, 4); } #[test] diff --git a/frame/system/src/extensions/check_genesis.rs b/frame/system/src/extensions/check_genesis.rs index 4b52691a6d32..a0679b11487f 100644 --- a/frame/system/src/extensions/check_genesis.rs +++ b/frame/system/src/extensions/check_genesis.rs @@ -70,6 +70,6 @@ impl SignedExtension for CheckGenesis { info: &DispatchInfoOf, len: usize, ) -> Result { - Ok(self.validate(who, call, info, len).map(|_| ())?) + self.validate(who, call, info, len).map(|_| ()) } } diff --git a/frame/system/src/extensions/check_mortality.rs b/frame/system/src/extensions/check_mortality.rs index ed11c3759836..2fb99c9f45e2 100644 --- a/frame/system/src/extensions/check_mortality.rs +++ b/frame/system/src/extensions/check_mortality.rs @@ -93,7 +93,7 @@ impl SignedExtension for CheckMortality { info: &DispatchInfoOf, len: usize, ) -> Result { - Ok(self.validate(who, call, info, len).map(|_| ())?) + self.validate(who, call, info, len).map(|_| ()) } } diff --git a/frame/system/src/extensions/check_non_zero_sender.rs b/frame/system/src/extensions/check_non_zero_sender.rs index 5910a865a776..f517201fbebc 100644 --- a/frame/system/src/extensions/check_non_zero_sender.rs +++ b/frame/system/src/extensions/check_non_zero_sender.rs @@ -72,7 +72,7 @@ where info: &DispatchInfoOf, len: usize, ) -> Result { - Ok(self.validate(who, call, info, len).map(|_| ())?) + self.validate(who, call, info, len).map(|_| ()) } fn validate( diff --git a/frame/system/src/extensions/check_spec_version.rs b/frame/system/src/extensions/check_spec_version.rs index dce70a940765..0280d31f657a 100644 --- a/frame/system/src/extensions/check_spec_version.rs +++ b/frame/system/src/extensions/check_spec_version.rs @@ -70,6 +70,6 @@ impl SignedExtension for CheckSpecVersion { info: &DispatchInfoOf, len: usize, ) -> Result { - Ok(self.validate(who, call, info, len).map(|_| ())?) + self.validate(who, call, info, len).map(|_| ()) } } diff --git a/frame/system/src/extensions/check_tx_version.rs b/frame/system/src/extensions/check_tx_version.rs index 69060729cccc..b92d8978bde0 100644 --- a/frame/system/src/extensions/check_tx_version.rs +++ b/frame/system/src/extensions/check_tx_version.rs @@ -69,6 +69,6 @@ impl SignedExtension for CheckTxVersion { info: &DispatchInfoOf, len: usize, ) -> Result { - Ok(self.validate(who, call, info, len).map(|_| ())?) + self.validate(who, call, info, len).map(|_| ()) } } diff --git a/frame/system/src/lib.rs b/frame/system/src/lib.rs index 80d293491469..cec45a8aa1cb 100644 --- a/frame/system/src/lib.rs +++ b/frame/system/src/lib.rs @@ -637,19 +637,13 @@ pub mod pallet { #[pallet::storage] pub(super) type ExecutionPhase = StorageValue<_, Phase>; + #[cfg_attr(feature = "std", derive(Default))] #[pallet::genesis_config] pub struct GenesisConfig { #[serde(with = "sp_core::bytes")] pub code: Vec, } - #[cfg(feature = "std")] - impl Default for GenesisConfig { - fn default() -> Self { - Self { code: Default::default() } - } - } - #[pallet::genesis_build] impl GenesisBuild for GenesisConfig { fn build(&self) { diff --git a/frame/uniques/src/tests.rs b/frame/uniques/src/tests.rs index 0e0dc413a01a..293140d5eda1 100644 --- a/frame/uniques/src/tests.rs +++ b/frame/uniques/src/tests.rs @@ -39,7 +39,7 @@ fn assets() -> Vec<(u64, u32, u32)> { Some(Some(item)) } }) - .filter_map(|item| item) + .flatten() { let details = Class::::get(class).unwrap(); let instances = Asset::::iter_prefix(class).count() as u32; diff --git a/frame/vesting/src/lib.rs b/frame/vesting/src/lib.rs index fcad0c57f937..c823bccf38b1 100644 --- a/frame/vesting/src/lib.rs +++ b/frame/vesting/src/lib.rs @@ -572,14 +572,13 @@ impl Pallet { let mut total_locked_now: BalanceOf = Zero::zero(); let filtered_schedules = action .pick_schedules::(schedules) - .filter_map(|schedule| { + .filter(|schedule| { let locked_now = schedule.locked_at::(now); - if locked_now.is_zero() { - None - } else { + let keep = !locked_now.is_zero(); + if keep { total_locked_now = total_locked_now.saturating_add(locked_now); - Some(schedule) } + keep }) .collect::>(); diff --git a/primitives/api/proc-macro/src/decl_runtime_apis.rs b/primitives/api/proc-macro/src/decl_runtime_apis.rs index 6c6b8f453a26..8d90b09d0e8c 100644 --- a/primitives/api/proc-macro/src/decl_runtime_apis.rs +++ b/primitives/api/proc-macro/src/decl_runtime_apis.rs @@ -235,9 +235,7 @@ fn generate_native_call_generators(decl: &ItemTrait) -> Result { // compatible. To ensure that we forward it by ref/value, we use the value given by the // the user. Otherwise if it is not using the block, we don't need to add anything. let input_borrows = - params - .iter() - .map(|v| if type_is_using_block(&v.1) { v.2.clone() } else { None }); + params.iter().map(|v| if type_is_using_block(&v.1) { v.2 } else { None }); // Replace all `Block` with `NodeBlock`, add `'a` lifetime to references and collect // all the function inputs. @@ -380,7 +378,6 @@ fn generate_call_api_at_calls(decl: &ItemTrait) -> Result { // Generate the generator function result.push(quote!( #[cfg(any(feature = "std", test))] - #[allow(clippy::too_many_arguments)] pub fn #fn_name< R: #crate_::Encode + #crate_::Decode + PartialEq, NC: FnOnce() -> std::result::Result + std::panic::UnwindSafe, diff --git a/primitives/authorship/src/lib.rs b/primitives/authorship/src/lib.rs index 25eaeaf9bc16..7ea19d9ea5ff 100644 --- a/primitives/authorship/src/lib.rs +++ b/primitives/authorship/src/lib.rs @@ -88,13 +88,13 @@ impl sp_inherents::InherentDataProvider for InherentDataProvider async fn try_handle_error( &self, identifier: &InherentIdentifier, - error: &[u8], + mut error: &[u8], ) -> Option> { if *identifier != INHERENT_IDENTIFIER { return None } - let error = InherentError::decode(&mut &error[..]).ok()?; + let error = InherentError::decode(&mut error).ok()?; Some(Err(Error::Application(Box::from(format!("{:?}", error))))) } diff --git a/primitives/debug-derive/src/impls.rs b/primitives/debug-derive/src/impls.rs index bab0146e4682..060997fe9782 100644 --- a/primitives/debug-derive/src/impls.rs +++ b/primitives/debug-derive/src/impls.rs @@ -101,7 +101,7 @@ mod implementation { } } - fn derive_fields<'a>(name_str: &str, fields: Fields) -> TokenStream { + fn derive_fields(name_str: &str, fields: Fields) -> TokenStream { match fields { Fields::Named { names, this } => { let names_str: Vec<_> = names.iter().map(|x| x.to_string()).collect(); diff --git a/primitives/keystore/src/testing.rs b/primitives/keystore/src/testing.rs index eb5847207daa..2723b743c10d 100644 --- a/primitives/keystore/src/testing.rs +++ b/primitives/keystore/src/testing.rs @@ -482,9 +482,7 @@ mod tests { assert!(res.is_none()); // insert key, sign again - let res = - SyncCryptoStore::insert_unknown(&store, ECDSA, suri, pair.public().as_ref()).unwrap(); - assert_eq!((), res); + SyncCryptoStore::insert_unknown(&store, ECDSA, suri, pair.public().as_ref()).unwrap(); let res = SyncCryptoStore::ecdsa_sign_prehashed(&store, ECDSA, &pair.public(), &msg).unwrap(); diff --git a/primitives/npos-elections/fuzzer/src/compact.rs b/primitives/npos-elections/fuzzer/src/compact.rs index 4e78c94b8257..595048575d99 100644 --- a/primitives/npos-elections/fuzzer/src/compact.rs +++ b/primitives/npos-elections/fuzzer/src/compact.rs @@ -11,7 +11,7 @@ fn main() { loop { fuzz!(|fuzzer_data: &[u8]| { let result_decoded: Result = - ::decode(&mut &fuzzer_data[..]); + ::decode(&mut &*fuzzer_data); // Ignore errors as not every random sequence of bytes can be decoded as // InnerTestSolutionCompact if let Ok(decoded) = result_decoded { diff --git a/primitives/npos-elections/fuzzer/src/reduce.rs b/primitives/npos-elections/fuzzer/src/reduce.rs index 029bb18dc5b3..ad3f7dc260ef 100644 --- a/primitives/npos-elections/fuzzer/src/reduce.rs +++ b/primitives/npos-elections/fuzzer/src/reduce.rs @@ -90,7 +90,7 @@ fn generate_random_phragmen_assignment( .map(|_| { let target = targets_to_chose_from.remove(rng.gen_range(0, targets_to_chose_from.len())); - if winners.iter().find(|w| **w == target).is_none() { + if winners.iter().all(|w| *w != target) { winners.push(target.clone()); } (target, rng.gen_range(1 * KSM, 100 * KSM)) diff --git a/primitives/npos-elections/src/reduce.rs b/primitives/npos-elections/src/reduce.rs index 057ee339bd7d..f089a37e3fff 100644 --- a/primitives/npos-elections/src/reduce.rs +++ b/primitives/npos-elections/src/reduce.rs @@ -275,9 +275,8 @@ fn reduce_4(assignments: &mut Vec>) -> u32 { }); // remove either one of them. - let who_removed = remove_indices.iter().find(|i| **i < 2usize).is_some(); - let other_removed = - remove_indices.into_iter().find(|i| *i >= 2usize).is_some(); + let who_removed = remove_indices.iter().any(|i| *i < 2usize); + let other_removed = remove_indices.into_iter().any(|i| i >= 2usize); match (who_removed, other_removed) { (false, true) => { diff --git a/primitives/runtime-interface/test/src/lib.rs b/primitives/runtime-interface/test/src/lib.rs index 785215b87421..e76f54f69a80 100644 --- a/primitives/runtime-interface/test/src/lib.rs +++ b/primitives/runtime-interface/test/src/lib.rs @@ -62,17 +62,17 @@ fn call_wasm_method(binary: &[u8], method: &str) -> TestExte #[test] fn test_return_data() { - call_wasm_method::(&wasm_binary_unwrap()[..], "test_return_data"); + call_wasm_method::(wasm_binary_unwrap(), "test_return_data"); } #[test] fn test_return_option_data() { - call_wasm_method::(&wasm_binary_unwrap()[..], "test_return_option_data"); + call_wasm_method::(wasm_binary_unwrap(), "test_return_option_data"); } #[test] fn test_set_storage() { - let mut ext = call_wasm_method::(&wasm_binary_unwrap()[..], "test_set_storage"); + let mut ext = call_wasm_method::(wasm_binary_unwrap(), "test_set_storage"); let expected = "world"; assert_eq!(expected.as_bytes(), &ext.ext().storage("hello".as_bytes()).unwrap()[..]); @@ -81,30 +81,30 @@ fn test_set_storage() { #[test] fn test_return_value_into_mutable_reference() { call_wasm_method::( - &wasm_binary_unwrap()[..], + wasm_binary_unwrap(), "test_return_value_into_mutable_reference", ); } #[test] fn test_get_and_return_array() { - call_wasm_method::(&wasm_binary_unwrap()[..], "test_get_and_return_array"); + call_wasm_method::(wasm_binary_unwrap(), "test_get_and_return_array"); } #[test] fn test_array_as_mutable_reference() { - call_wasm_method::(&wasm_binary_unwrap()[..], "test_array_as_mutable_reference"); + call_wasm_method::(wasm_binary_unwrap(), "test_array_as_mutable_reference"); } #[test] fn test_return_input_public_key() { - call_wasm_method::(&wasm_binary_unwrap()[..], "test_return_input_public_key"); + call_wasm_method::(wasm_binary_unwrap(), "test_return_input_public_key"); } #[test] fn host_function_not_found() { - let err = call_wasm_method_with_result::<()>(&wasm_binary_unwrap()[..], "test_return_data") - .unwrap_err(); + let err = + call_wasm_method_with_result::<()>(wasm_binary_unwrap(), "test_return_data").unwrap_err(); assert!(err.contains("Instantiation: Export ")); assert!(err.contains(" not found")); @@ -114,7 +114,7 @@ fn host_function_not_found() { #[should_panic(expected = "Invalid utf8 data provided")] fn test_invalid_utf8_data_should_return_an_error() { call_wasm_method::( - &wasm_binary_unwrap()[..], + wasm_binary_unwrap(), "test_invalid_utf8_data_should_return_an_error", ); } @@ -122,7 +122,7 @@ fn test_invalid_utf8_data_should_return_an_error() { #[test] fn test_overwrite_native_function_implementation() { call_wasm_method::( - &wasm_binary_unwrap()[..], + wasm_binary_unwrap(), "test_overwrite_native_function_implementation", ); } @@ -130,7 +130,7 @@ fn test_overwrite_native_function_implementation() { #[test] fn test_u128_i128_as_parameter_and_return_value() { call_wasm_method::( - &wasm_binary_unwrap()[..], + wasm_binary_unwrap(), "test_u128_i128_as_parameter_and_return_value", ); } @@ -138,7 +138,7 @@ fn test_u128_i128_as_parameter_and_return_value() { #[test] fn test_vec_return_value_memory_is_freed() { call_wasm_method::( - &wasm_binary_unwrap()[..], + wasm_binary_unwrap(), "test_vec_return_value_memory_is_freed", ); } @@ -146,7 +146,7 @@ fn test_vec_return_value_memory_is_freed() { #[test] fn test_encoded_return_value_memory_is_freed() { call_wasm_method::( - &wasm_binary_unwrap()[..], + wasm_binary_unwrap(), "test_encoded_return_value_memory_is_freed", ); } @@ -154,7 +154,7 @@ fn test_encoded_return_value_memory_is_freed() { #[test] fn test_array_return_value_memory_is_freed() { call_wasm_method::( - &wasm_binary_unwrap()[..], + wasm_binary_unwrap(), "test_array_return_value_memory_is_freed", ); } @@ -162,14 +162,11 @@ fn test_array_return_value_memory_is_freed() { #[test] fn test_versionining_with_new_host_works() { // We call to the new wasm binary with new host function. - call_wasm_method::(&wasm_binary_unwrap()[..], "test_versionning_works"); + call_wasm_method::(wasm_binary_unwrap(), "test_versionning_works"); // we call to the old wasm binary with a new host functions // old versions of host functions should be called and test should be ok! - call_wasm_method::( - &wasm_binary_deprecated_unwrap()[..], - "test_versionning_works", - ); + call_wasm_method::(wasm_binary_deprecated_unwrap(), "test_versionning_works"); } #[test] @@ -224,7 +221,7 @@ fn test_tracing() { let _guard = tracing::subscriber::set_default(subscriber.clone()); // Call some method to generate a trace - call_wasm_method::(&wasm_binary_unwrap()[..], "test_return_data"); + call_wasm_method::(wasm_binary_unwrap(), "test_return_data"); let inner = subscriber.0.lock().unwrap(); assert!(inner.spans.contains("return_input_version_1")); @@ -232,5 +229,5 @@ fn test_tracing() { #[test] fn test_return_input_as_tuple() { - call_wasm_method::(&wasm_binary_unwrap()[..], "test_return_input_as_tuple"); + call_wasm_method::(wasm_binary_unwrap(), "test_return_input_as_tuple"); } diff --git a/primitives/runtime/src/generic/digest.rs b/primitives/runtime/src/generic/digest.rs index ca1daabb06d2..f3cb7b99efb6 100644 --- a/primitives/runtime/src/generic/digest.rs +++ b/primitives/runtime/src/generic/digest.rs @@ -33,19 +33,13 @@ use crate::{ use sp_core::RuntimeDebug; /// Generic header digest. -#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo)] +#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo, Default)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, parity_util_mem::MallocSizeOf))] pub struct Digest { /// A list of logs in the digest. pub logs: Vec, } -impl Default for Digest { - fn default() -> Self { - Self { logs: Vec::new() } - } -} - impl Digest { /// Get reference to all digest items. pub fn logs(&self) -> &[DigestItem] { diff --git a/primitives/runtime/src/generic/unchecked_extrinsic.rs b/primitives/runtime/src/generic/unchecked_extrinsic.rs index d919a67095d3..d444d0352d5a 100644 --- a/primitives/runtime/src/generic/unchecked_extrinsic.rs +++ b/primitives/runtime/src/generic/unchecked_extrinsic.rs @@ -395,7 +395,7 @@ mod tests { info: &DispatchInfoOf, len: usize, ) -> Result { - Ok(self.validate(who, call, info, len).map(|_| ())?) + self.validate(who, call, info, len).map(|_| ()) } } diff --git a/primitives/runtime/src/traits.rs b/primitives/runtime/src/traits.rs index 84c35597b4b1..b2e218cb9db7 100644 --- a/primitives/runtime/src/traits.rs +++ b/primitives/runtime/src/traits.rs @@ -1074,7 +1074,7 @@ impl SignedExtension for () { info: &DispatchInfoOf, len: usize, ) -> Result { - Ok(self.validate(who, call, info, len).map(|_| ())?) + self.validate(who, call, info, len).map(|_| ()) } } diff --git a/primitives/state-machine/src/backend.rs b/primitives/state-machine/src/backend.rs index 215caaa17f30..8d0ac2d1369c 100644 --- a/primitives/state-machine/src/backend.rs +++ b/primitives/state-machine/src/backend.rs @@ -208,7 +208,7 @@ pub trait Backend: sp_std::fmt::Debug { } let (root, parent_txs) = self.storage_root( delta - .map(|(k, v)| (&k[..], v.as_ref().map(|v| &v[..]))) + .map(|(k, v)| (k, v.as_ref().map(|v| &v[..]))) .chain(child_roots.iter().map(|(k, v)| (&k[..], v.as_ref().map(|v| &v[..])))), state_version, ); diff --git a/primitives/state-machine/src/ext.rs b/primitives/state-machine/src/ext.rs index 93e6ac6e5c53..e87b22d4f9b7 100644 --- a/primitives/state-machine/src/ext.rs +++ b/primitives/state-machine/src/ext.rs @@ -581,7 +581,7 @@ where target: "state", method = "ChildStorageRoot", ext_id = %HexDisplay::from(&self.id.to_le_bytes()), - child_info = %HexDisplay::from(&storage_key.as_ref()), + child_info = %HexDisplay::from(&storage_key), storage_root = %HexDisplay::from(&root.as_ref()), cached = false, ); @@ -599,7 +599,7 @@ where target: "state", method = "ChildStorageRoot", ext_id = %HexDisplay::from(&self.id.to_le_bytes()), - child_info = %HexDisplay::from(&storage_key.as_ref()), + child_info = %HexDisplay::from(&storage_key), storage_root = %HexDisplay::from(&root.as_ref()), cached = false, ); diff --git a/primitives/state-machine/src/testing.rs b/primitives/state-machine/src/testing.rs index e21644614c83..6be601aa72b3 100644 --- a/primitives/state-machine/src/testing.rs +++ b/primitives/state-machine/src/testing.rs @@ -203,7 +203,7 @@ where /// /// This implementation will wipe the proof recorded in between calls. Consecutive calls will /// get their own proof from scratch. - pub fn execute_and_prove<'a, R>(&mut self, execute: impl FnOnce() -> R) -> (R, StorageProof) { + pub fn execute_and_prove(&mut self, execute: impl FnOnce() -> R) -> (R, StorageProof) { let proving_backend = InMemoryProvingBackend::new(&self.backend); let mut proving_ext = Ext::new( &mut self.overlay, diff --git a/primitives/timestamp/src/lib.rs b/primitives/timestamp/src/lib.rs index 9155cbd93b6c..76725e28ac82 100644 --- a/primitives/timestamp/src/lib.rs +++ b/primitives/timestamp/src/lib.rs @@ -138,9 +138,9 @@ impl IsFatalError for InherentError { impl InherentError { /// Try to create an instance ouf of the given identifier and data. #[cfg(feature = "std")] - pub fn try_from(id: &InherentIdentifier, data: &[u8]) -> Option { + pub fn try_from(id: &InherentIdentifier, mut data: &[u8]) -> Option { if id == &INHERENT_IDENTIFIER { - ::decode(&mut &data[..]).ok() + ::decode(&mut data).ok() } else { None } @@ -227,7 +227,7 @@ impl sp_inherents::InherentDataProvider for InherentDataProvider { &self, inherent_data: &mut InherentData, ) -> Result<(), sp_inherents::Error> { - inherent_data.put_data(INHERENT_IDENTIFIER, &InherentType::from(self.timestamp)) + inherent_data.put_data(INHERENT_IDENTIFIER, &self.timestamp) } async fn try_handle_error( diff --git a/primitives/transaction-storage-proof/src/lib.rs b/primitives/transaction-storage-proof/src/lib.rs index bdfe16683ebc..2e5aa3b2b9c7 100644 --- a/primitives/transaction-storage-proof/src/lib.rs +++ b/primitives/transaction-storage-proof/src/lib.rs @@ -67,7 +67,7 @@ pub trait TransactionStorageProofInherentData { impl TransactionStorageProofInherentData for InherentData { fn storage_proof(&self) -> Result, Error> { - Ok(self.get_data(&INHERENT_IDENTIFIER)?) + self.get_data(&INHERENT_IDENTIFIER) } } @@ -98,13 +98,13 @@ impl sp_inherents::InherentDataProvider for InherentDataProvider { async fn try_handle_error( &self, identifier: &InherentIdentifier, - error: &[u8], + mut error: &[u8], ) -> Option> { if *identifier != INHERENT_IDENTIFIER { return None } - let error = InherentError::decode(&mut &error[..]).ok()?; + let error = InherentError::decode(&mut error).ok()?; Some(Err(Error::Application(Box::from(format!("{:?}", error))))) } diff --git a/primitives/trie/src/lib.rs b/primitives/trie/src/lib.rs index ffaee2037d1c..f598615be909 100644 --- a/primitives/trie/src/lib.rs +++ b/primitives/trie/src/lib.rs @@ -281,7 +281,7 @@ where L: TrieConfiguration, DB: hash_db::HashDBRef, { - Ok(TrieDB::::new(&*db, root)?.get(key).map(|x| x.map(|val| val.to_vec()))?) + TrieDB::::new(&*db, root)?.get(key).map(|x| x.map(|val| val.to_vec())) } /// Read a value from the trie with given Query. @@ -296,9 +296,9 @@ where Q: Query, DB: hash_db::HashDBRef, { - Ok(TrieDB::::new(&*db, root)? + TrieDB::::new(&*db, root)? .get_with(key, query) - .map(|x| x.map(|val| val.to_vec()))?) + .map(|x| x.map(|val| val.to_vec())) } /// Determine the empty trie root. diff --git a/test-utils/runtime/src/lib.rs b/test-utils/runtime/src/lib.rs index c6112db2374e..b03998621b31 100644 --- a/test-utils/runtime/src/lib.rs +++ b/test-utils/runtime/src/lib.rs @@ -665,13 +665,7 @@ fn code_using_trie() -> u64 { if let Ok(trie) = TrieDB::::new(&mdb, &root) { if let Ok(iter) = trie.iter() { - let mut iter_pairs = Vec::new(); - for pair in iter { - if let Ok((key, value)) = pair { - iter_pairs.push((key, value.to_vec())); - } - } - iter_pairs.len() as u64 + iter.flatten().count() as u64 } else { 102 } diff --git a/utils/frame/benchmarking-cli/src/command.rs b/utils/frame/benchmarking-cli/src/command.rs index 94e1e0c8c1b8..bd103862fe2c 100644 --- a/utils/frame/benchmarking-cli/src/command.rs +++ b/utils/frame/benchmarking-cli/src/command.rs @@ -176,9 +176,7 @@ impl BenchmarkCmd { .filter(|item| pallet.is_empty() || pallet == &b"*"[..] || pallet == &item.pallet[..]) .for_each(|item| { for benchmark in &item.benchmarks { - if extrinsic.is_empty() || - &extrinsic[..] == &b"*"[..] || - extrinsic == benchmark.name + if extrinsic.is_empty() || extrinsic == &b"*"[..] || extrinsic == benchmark.name { benchmarks_to_run.push(( item.pallet.clone(), diff --git a/utils/frame/try-runtime/cli/src/lib.rs b/utils/frame/try-runtime/cli/src/lib.rs index 2cd0a18909c1..32c814b0443d 100644 --- a/utils/frame/try-runtime/cli/src/lib.rs +++ b/utils/frame/try-runtime/cli/src/lib.rs @@ -496,7 +496,6 @@ impl State { state_snapshot: snapshot_path.as_ref().map(SnapshotConfig::new), pallets: pallets.clone().unwrap_or_default(), at, - ..Default::default() })) .inject_hashed_key( &[twox_128(b"System"), twox_128(b"LastRuntimeUpgrade")].concat(), diff --git a/utils/frame/try-runtime/cli/src/parse.rs b/utils/frame/try-runtime/cli/src/parse.rs index a12e37344c7a..15a0251ebc34 100644 --- a/utils/frame/try-runtime/cli/src/parse.rs +++ b/utils/frame/try-runtime/cli/src/parse.rs @@ -18,8 +18,11 @@ //! Utils for parsing user input pub(crate) fn hash(block_hash: &str) -> Result { - let (block_hash, offset) = - if block_hash.starts_with("0x") { (&block_hash[2..], 2) } else { (block_hash, 0) }; + let (block_hash, offset) = if let Some(block_hash) = block_hash.strip_prefix("0x") { + (block_hash, 2) + } else { + (block_hash, 0) + }; if let Some(pos) = block_hash.chars().position(|c| !c.is_ascii_hexdigit()) { Err(format!( From e4d7a24536f782a5e6410bdbd3a762facdf17c56 Mon Sep 17 00:00:00 2001 From: Robert Klotzner Date: Wed, 5 Jan 2022 17:02:32 +0100 Subject: [PATCH 352/695] Warn on chain selection error. (#10587) At least for Polkadot, this should not result in spam and a warning will very likely indicate some serious issue. --- client/finality-grandpa/src/environment.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/finality-grandpa/src/environment.rs b/client/finality-grandpa/src/environment.rs index bbd739086ba5..81bb24f1a5ee 100644 --- a/client/finality-grandpa/src/environment.rs +++ b/client/finality-grandpa/src/environment.rs @@ -1224,7 +1224,7 @@ where .or_else(|| Some((target_header.hash(), *target_header.number()))) }, Err(e) => { - debug!(target: "afg", "Encountered error finding best chain containing {:?}: {:?}", block, e); + warn!(target: "afg", "Encountered error finding best chain containing {:?}: {:?}", block, e); None }, }; From 0f070c8020fad552247fd4b43c1a6a4506e456b5 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Wed, 5 Jan 2022 19:01:44 +0200 Subject: [PATCH 353/695] Name changes for GrandPa and Beefy notifications protocols (#10463) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * grandpa: update notif protocol name * grandpa: add chain id prefix to protocol name * grandpa: beautify protocol name handling * grandpa: prepend genesis hash to protocol name * chain-spec: add optional 'fork_id' 'fork_id' is used to uniquely identify forks of the same chain/network 'ChainSpec' trait provides default 'None' implementation, meaning this chain hasn't been forked. * grandpa: protocol_name mod instead of struct * beefy: add genesis hash prefix to protocol name * chainspec: add fork_id * grandpa: simplify protocol name * grandpa: contain protocol name building logic * beefy: contain protocol name building logic * grandpa: fix tests * fix merge damage * fix docs reference visibility Signed-off-by: acatangiu * Update client/finality-grandpa/src/lib.rs Co-authored-by: Tomasz Drwięga * Update client/finality-grandpa/src/communication/mod.rs Co-authored-by: Tomasz Drwięga * Update client/beefy/src/lib.rs Co-authored-by: Tomasz Drwięga * Update client/beefy/src/lib.rs Co-authored-by: Tomasz Drwięga * avoid using hash default, even for protocol names Co-authored-by: Tomasz Drwięga --- Cargo.lock | 2 + bin/node-template/node/src/chain_spec.rs | 2 + bin/node-template/node/src/service.rs | 12 +++++- bin/node/cli/src/chain_spec.rs | 5 +++ bin/node/cli/src/service.rs | 10 ++++- bin/utils/chain-spec-builder/src/main.rs | 1 + client/beefy/Cargo.toml | 1 + client/beefy/src/lib.rs | 41 +++++++++++++++---- client/chain-spec/src/chain_spec.rs | 12 ++++++ client/chain-spec/src/lib.rs | 2 + client/cli/src/commands/insert_key.rs | 1 + client/finality-grandpa/Cargo.toml | 1 + .../src/communication/gossip.rs | 40 +++++++++--------- .../finality-grandpa/src/communication/mod.rs | 27 ++++++++++-- .../src/communication/tests.rs | 20 +++++---- client/finality-grandpa/src/lib.rs | 13 ++++-- client/finality-grandpa/src/tests.rs | 14 ++++++- client/network/src/config.rs | 7 ++++ 18 files changed, 164 insertions(+), 47 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cdd2d0d11e45..16a24f284dc4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -481,6 +481,7 @@ dependencies = [ "log 0.4.14", "parity-scale-codec", "parking_lot 0.11.2", + "sc-chain-spec", "sc-client-api", "sc-keystore", "sc-network", @@ -8159,6 +8160,7 @@ dependencies = [ "parking_lot 0.11.2", "rand 0.8.4", "sc-block-builder", + "sc-chain-spec", "sc-client-api", "sc-consensus", "sc-keystore", diff --git a/bin/node-template/node/src/chain_spec.rs b/bin/node-template/node/src/chain_spec.rs index af94a63335e0..ef34ec369a77 100644 --- a/bin/node-template/node/src/chain_spec.rs +++ b/bin/node-template/node/src/chain_spec.rs @@ -68,6 +68,7 @@ pub fn development_config() -> Result { None, // Protocol ID None, + None, // Properties None, // Extensions @@ -117,6 +118,7 @@ pub fn local_testnet_config() -> Result { None, // Properties None, + None, // Extensions None, )) diff --git a/bin/node-template/node/src/service.rs b/bin/node-template/node/src/service.rs index 975a491cf4da..4395718a6d68 100644 --- a/bin/node-template/node/src/service.rs +++ b/bin/node-template/node/src/service.rs @@ -1,7 +1,7 @@ //! Service and ServiceFactory implementation. Specialized wrapper over substrate service. use node_template_runtime::{self, opaque::Block, RuntimeApi}; -use sc_client_api::ExecutorProvider; +use sc_client_api::{BlockBackend, ExecutorProvider}; use sc_consensus_aura::{ImportQueueParams, SlotProportion, StartAuraParams}; pub use sc_executor::NativeElseWasmExecutor; use sc_finality_grandpa::SharedVoterState; @@ -180,8 +180,15 @@ pub fn new_full(mut config: Configuration) -> Result ))), }; } + let grandpa_protocol_name = sc_finality_grandpa::protocol_standard_name( + &client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"), + &config.chain_spec, + ); - config.network.extra_sets.push(sc_finality_grandpa::grandpa_peers_set_config()); + config + .network + .extra_sets + .push(sc_finality_grandpa::grandpa_peers_set_config(grandpa_protocol_name.clone())); let warp_sync = Arc::new(sc_finality_grandpa::warp_proof::NetworkProvider::new( backend.clone(), grandpa_link.shared_authority_set().clone(), @@ -306,6 +313,7 @@ pub fn new_full(mut config: Configuration) -> Result keystore, local_role: role, telemetry: telemetry.as_ref().map(|x| x.handle()), + protocol_name: grandpa_protocol_name, }; if enable_grandpa { diff --git a/bin/node/cli/src/chain_spec.rs b/bin/node/cli/src/chain_spec.rs index 4d5054113ea0..747bc71c5007 100644 --- a/bin/node/cli/src/chain_spec.rs +++ b/bin/node/cli/src/chain_spec.rs @@ -196,6 +196,7 @@ pub fn staging_testnet_config() -> ChainSpec { ), None, None, + None, Default::default(), ) } @@ -386,6 +387,7 @@ pub fn development_config() -> ChainSpec { None, None, None, + None, Default::default(), ) } @@ -410,6 +412,7 @@ pub fn local_testnet_config() -> ChainSpec { None, None, None, + None, Default::default(), ) } @@ -441,6 +444,7 @@ pub(crate) mod tests { None, None, None, + None, Default::default(), ) } @@ -456,6 +460,7 @@ pub(crate) mod tests { None, None, None, + None, Default::default(), ) } diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index c899975c850c..81c68bf5d3aa 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -326,8 +326,15 @@ pub fn new_full_base( let shared_voter_state = rpc_setup; let auth_disc_publish_non_global_ips = config.network.allow_non_globals_in_dht; + let grandpa_protocol_name = grandpa::protocol_standard_name( + &client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"), + &config.chain_spec, + ); - config.network.extra_sets.push(grandpa::grandpa_peers_set_config()); + config + .network + .extra_sets + .push(grandpa::grandpa_peers_set_config(grandpa_protocol_name.clone())); let warp_sync = Arc::new(grandpa::warp_proof::NetworkProvider::new( backend.clone(), import_setup.1.shared_authority_set().clone(), @@ -488,6 +495,7 @@ pub fn new_full_base( keystore, local_role: role, telemetry: telemetry.as_ref().map(|x| x.handle()), + protocol_name: grandpa_protocol_name, }; if enable_grandpa { diff --git a/bin/utils/chain-spec-builder/src/main.rs b/bin/utils/chain-spec-builder/src/main.rs index bf58f3110170..013fbeccfe0d 100644 --- a/bin/utils/chain-spec-builder/src/main.rs +++ b/bin/utils/chain-spec-builder/src/main.rs @@ -155,6 +155,7 @@ fn generate_chain_spec( None, None, None, + None, Default::default(), ); diff --git a/client/beefy/Cargo.toml b/client/beefy/Cargo.toml index 6c281deb85ea..d57d053c16f4 100644 --- a/client/beefy/Cargo.toml +++ b/client/beefy/Cargo.toml @@ -26,6 +26,7 @@ sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-keystore = { version = "0.10.0", path = "../../primitives/keystore" } sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } +sc-chain-spec = { version = "4.0.0-dev", path = "../../client/chain-spec" } sc-utils = { version = "4.0.0-dev", path = "../utils" } sc-client-api = { version = "4.0.0-dev", path = "../api" } sc-keystore = { version = "4.0.0-dev", path = "../keystore" } diff --git a/client/beefy/src/lib.rs b/client/beefy/src/lib.rs index 59a5ff08e16e..7d2c3b57b1f7 100644 --- a/client/beefy/src/lib.rs +++ b/client/beefy/src/lib.rs @@ -39,15 +39,40 @@ mod round; mod worker; pub mod notification; - -pub const BEEFY_PROTOCOL_NAME: &str = "/paritytech/beefy/1"; +pub use beefy_protocol_name::standard_name as protocol_standard_name; + +pub(crate) mod beefy_protocol_name { + use sc_chain_spec::ChainSpec; + + const NAME: &'static str = "/beefy/1"; + /// Old names for the notifications protocol, used for backward compatibility. + pub(crate) const LEGACY_NAMES: [&'static str; 1] = ["/paritytech/beefy/1"]; + + /// Name of the notifications protocol used by BEEFY. + /// + /// Must be registered towards the networking in order for BEEFY to properly function. + pub fn standard_name( + genesis_hash: &Hash, + chain_spec: &Box, + ) -> std::borrow::Cow<'static, str> { + let chain_prefix = match chain_spec.fork_id() { + Some(fork_id) => format!("/{}/{}", genesis_hash, fork_id), + None => format!("/{}", genesis_hash), + }; + format!("{}{}", chain_prefix, NAME).into() + } +} /// Returns the configuration value to put in /// [`sc_network::config::NetworkConfiguration::extra_sets`]. -pub fn beefy_peers_set_config() -> sc_network::config::NonDefaultSetConfig { - let mut cfg = - sc_network::config::NonDefaultSetConfig::new(BEEFY_PROTOCOL_NAME.into(), 1024 * 1024); +/// For standard protocol name see [`beefy_protocol_name::standard_name`]. +pub fn beefy_peers_set_config( + protocol_name: std::borrow::Cow<'static, str>, +) -> sc_network::config::NonDefaultSetConfig { + let mut cfg = sc_network::config::NonDefaultSetConfig::new(protocol_name, 1024 * 1024); + cfg.allow_non_reserved(25, 25); + cfg.add_fallback_names(beefy_protocol_name::LEGACY_NAMES.iter().map(|&n| n.into()).collect()); cfg } @@ -101,6 +126,8 @@ where pub min_block_delta: u32, /// Prometheus metric registry pub prometheus_registry: Option, + /// Chain specific GRANDPA protocol name. See [`beefy_protocol_name::standard_name`]. + pub protocol_name: std::borrow::Cow<'static, str>, } /// Start the BEEFY gadget. @@ -122,11 +149,11 @@ where signed_commitment_sender, min_block_delta, prometheus_registry, + protocol_name, } = beefy_params; let gossip_validator = Arc::new(gossip::GossipValidator::new()); - let gossip_engine = - GossipEngine::new(network, BEEFY_PROTOCOL_NAME, gossip_validator.clone(), None); + let gossip_engine = GossipEngine::new(network, protocol_name, gossip_validator.clone(), None); let metrics = prometheus_registry.as_ref().map(metrics::Metrics::register).and_then( diff --git a/client/chain-spec/src/chain_spec.rs b/client/chain-spec/src/chain_spec.rs index 11e5b73fe77f..9b672ce7c362 100644 --- a/client/chain-spec/src/chain_spec.rs +++ b/client/chain-spec/src/chain_spec.rs @@ -164,6 +164,7 @@ struct ClientSpec { boot_nodes: Vec, telemetry_endpoints: Option, protocol_id: Option, + fork_id: Option, properties: Option, #[serde(flatten)] extensions: E, @@ -226,6 +227,11 @@ impl ChainSpec { self.client_spec.protocol_id.as_deref() } + /// Optional network fork identifier. + pub fn fork_id(&self) -> Option<&str> { + self.client_spec.fork_id.as_ref().map(String::as_str) + } + /// Additional loosly-typed properties of the chain. /// /// Returns an empty JSON object if 'properties' not defined in config @@ -257,6 +263,7 @@ impl ChainSpec { boot_nodes: Vec, telemetry_endpoints: Option, protocol_id: Option<&str>, + fork_id: Option<&str>, properties: Option, extensions: E, ) -> Self { @@ -267,6 +274,7 @@ impl ChainSpec { boot_nodes, telemetry_endpoints, protocol_id: protocol_id.map(str::to_owned), + fork_id: fork_id.map(str::to_owned), properties, extensions, consensus_engine: (), @@ -384,6 +392,10 @@ where ChainSpec::protocol_id(self) } + fn fork_id(&self) -> Option<&str> { + ChainSpec::fork_id(self) + } + fn properties(&self) -> Properties { ChainSpec::properties(self) } diff --git a/client/chain-spec/src/lib.rs b/client/chain-spec/src/lib.rs index 64d72760639d..eb72592b54a9 100644 --- a/client/chain-spec/src/lib.rs +++ b/client/chain-spec/src/lib.rs @@ -165,6 +165,8 @@ pub trait ChainSpec: BuildStorage + Send + Sync { fn telemetry_endpoints(&self) -> &Option; /// Network protocol id. fn protocol_id(&self) -> Option<&str>; + /// Optional network fork identifier. `None` by default. + fn fork_id(&self) -> Option<&str>; /// Additional loosly-typed properties of the chain. /// /// Returns an empty JSON object if 'properties' not defined in config diff --git a/client/cli/src/commands/insert_key.rs b/client/cli/src/commands/insert_key.rs index 631fc4ecef95..cf40fb7ec4bf 100644 --- a/client/cli/src/commands/insert_key.rs +++ b/client/cli/src/commands/insert_key.rs @@ -144,6 +144,7 @@ mod tests { None, None, None, + None, NoExtension::None, ))) } diff --git a/client/finality-grandpa/Cargo.toml b/client/finality-grandpa/Cargo.toml index 10344e09c685..306311b0e3e5 100644 --- a/client/finality-grandpa/Cargo.toml +++ b/client/finality-grandpa/Cargo.toml @@ -27,6 +27,7 @@ parity-scale-codec = { version = "2.3.1", features = ["derive"] } sp-application-crypto = { version = "4.0.0", path = "../../primitives/application-crypto" } sp-arithmetic = { version = "4.0.0", path = "../../primitives/arithmetic" } sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } +sc-chain-spec = { version = "4.0.0-dev", path = "../../client/chain-spec" } sc-utils = { version = "4.0.0-dev", path = "../utils" } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } sc-consensus = { version = "0.10.0-dev", path = "../consensus/common" } diff --git a/client/finality-grandpa/src/communication/gossip.rs b/client/finality-grandpa/src/communication/gossip.rs index 4e8e047a9b64..ded918c34aa8 100644 --- a/client/finality-grandpa/src/communication/gossip.rs +++ b/client/finality-grandpa/src/communication/gossip.rs @@ -1664,6 +1664,7 @@ pub(super) struct PeerReport { #[cfg(test)] mod tests { use super::{environment::SharedVoterSetState, *}; + use crate::communication; use sc_network::config::Role; use sc_network_gossip::Validator as GossipValidatorT; use sc_network_test::Block; @@ -1679,6 +1680,7 @@ mod tests { local_role: Role::Authority, observer_enabled: true, telemetry: None, + protocol_name: communication::grandpa_protocol_name::NAME.into(), } } @@ -1840,13 +1842,13 @@ mod tests { // messages from old rounds are expired. for round_num in 1u64..last_kept_round { - let topic = crate::communication::round_topic::(round_num, 1); + let topic = communication::round_topic::(round_num, 1); assert!(is_expired(topic, &[1, 2, 3])); } // messages from not-too-old rounds are not expired. for round_num in last_kept_round..10 { - let topic = crate::communication::round_topic::(round_num, 1); + let topic = communication::round_topic::(round_num, 1); assert!(!is_expired(topic, &[1, 2, 3])); } } @@ -2262,7 +2264,7 @@ mod tests { // we accept messages from rounds 9, 10 and 11 // therefore neither of those should be considered expired for round in &[9, 10, 11] { - assert!(!is_expired(crate::communication::round_topic::(*round, 1), &[])) + assert!(!is_expired(communication::round_topic::(*round, 1), &[])) } } @@ -2310,7 +2312,7 @@ mod tests { if message_allowed( peer, MessageIntent::Broadcast, - &crate::communication::round_topic::(1, 0), + &communication::round_topic::(1, 0), &[], ) { allowed += 1; @@ -2374,7 +2376,7 @@ mod tests { assert!(!val.message_allowed()( &light_peer, MessageIntent::Broadcast, - &crate::communication::round_topic::(1, 0), + &communication::round_topic::(1, 0), &[], )); @@ -2388,7 +2390,7 @@ mod tests { assert!(!val.message_allowed()( &light_peer, MessageIntent::Broadcast, - &crate::communication::round_topic::(1, 0), + &communication::round_topic::(1, 0), &[], )); @@ -2412,8 +2414,8 @@ mod tests { auth_data: Vec::new(), }; - crate::communication::gossip::GossipMessage::::Commit( - crate::communication::gossip::FullCommitMessage { + communication::gossip::GossipMessage::::Commit( + communication::gossip::FullCommitMessage { round: Round(2), set_id: SetId(0), message: commit, @@ -2426,7 +2428,7 @@ mod tests { assert!(val.message_allowed()( &light_peer, MessageIntent::Broadcast, - &crate::communication::global_topic::(0), + &communication::global_topic::(0), &commit, )); } @@ -2466,8 +2468,8 @@ mod tests { auth_data: Vec::new(), }; - crate::communication::gossip::GossipMessage::::Commit( - crate::communication::gossip::FullCommitMessage { + communication::gossip::GossipMessage::::Commit( + communication::gossip::FullCommitMessage { round: Round(1), set_id: SetId(1), message: commit, @@ -2485,7 +2487,7 @@ mod tests { assert!(message_allowed( &peer1, MessageIntent::Broadcast, - &crate::communication::global_topic::(1), + &communication::global_topic::(1), &commit, )); @@ -2494,7 +2496,7 @@ mod tests { assert!(!message_allowed( &peer2, MessageIntent::Broadcast, - &crate::communication::global_topic::(1), + &communication::global_topic::(1), &commit, )); } @@ -2511,8 +2513,8 @@ mod tests { auth_data: Vec::new(), }; - crate::communication::gossip::GossipMessage::::Commit( - crate::communication::gossip::FullCommitMessage { + communication::gossip::GossipMessage::::Commit( + communication::gossip::FullCommitMessage { round: Round(round), set_id: SetId(set_id), message: commit, @@ -2532,15 +2534,13 @@ mod tests { // a commit message for round 1 that finalizes the same height as we // have observed previously should not be expired - assert!( - !message_expired(crate::communication::global_topic::(1), &commit(1, 1, 2),) - ); + assert!(!message_expired(communication::global_topic::(1), &commit(1, 1, 2),)); // it should be expired if it is for a lower block - assert!(message_expired(crate::communication::global_topic::(1), &commit(1, 1, 1))); + assert!(message_expired(communication::global_topic::(1), &commit(1, 1, 1))); // or the same block height but from the previous round - assert!(message_expired(crate::communication::global_topic::(1), &commit(0, 1, 2))); + assert!(message_expired(communication::global_topic::(1), &commit(0, 1, 2))); } #[test] diff --git a/client/finality-grandpa/src/communication/mod.rs b/client/finality-grandpa/src/communication/mod.rs index 43b2f5463c8d..809e721448bd 100644 --- a/client/finality-grandpa/src/communication/mod.rs +++ b/client/finality-grandpa/src/communication/mod.rs @@ -67,9 +67,27 @@ mod periodic; #[cfg(test)] pub(crate) mod tests; -/// Name of the notifications protocol used by Grandpa. Must be registered towards the networking -/// in order for Grandpa to properly function. -pub const GRANDPA_PROTOCOL_NAME: &'static str = "/paritytech/grandpa/1"; +pub mod grandpa_protocol_name { + use sc_chain_spec::ChainSpec; + + pub(crate) const NAME: &'static str = "/grandpa/1"; + /// Old names for the notifications protocol, used for backward compatibility. + pub(crate) const LEGACY_NAMES: [&'static str; 1] = ["/paritytech/grandpa/1"]; + + /// Name of the notifications protocol used by GRANDPA. + /// + /// Must be registered towards the networking in order for GRANDPA to properly function. + pub fn standard_name( + genesis_hash: &Hash, + chain_spec: &Box, + ) -> std::borrow::Cow<'static, str> { + let chain_prefix = match chain_spec.fork_id() { + Some(fork_id) => format!("/{}/{}", genesis_hash, fork_id), + None => format!("/{}", genesis_hash), + }; + format!("{}{}", chain_prefix, NAME).into() + } +} // cost scalars for reporting peers. mod cost { @@ -220,13 +238,14 @@ impl> NetworkBridge { prometheus_registry: Option<&Registry>, telemetry: Option, ) -> Self { + let protocol = config.protocol_name.clone(); let (validator, report_stream) = GossipValidator::new(config, set_state.clone(), prometheus_registry, telemetry.clone()); let validator = Arc::new(validator); let gossip_engine = Arc::new(Mutex::new(GossipEngine::new( service.clone(), - GRANDPA_PROTOCOL_NAME, + protocol, validator.clone(), prometheus_registry, ))); diff --git a/client/finality-grandpa/src/communication/tests.rs b/client/finality-grandpa/src/communication/tests.rs index ed23415972f9..c135f58a2eec 100644 --- a/client/finality-grandpa/src/communication/tests.rs +++ b/client/finality-grandpa/src/communication/tests.rs @@ -22,7 +22,7 @@ use super::{ gossip::{self, GossipValidator}, Round, SetId, VoterSet, }; -use crate::{communication::GRANDPA_PROTOCOL_NAME, environment::SharedVoterSetState}; +use crate::{communication::grandpa_protocol_name, environment::SharedVoterSetState}; use futures::prelude::*; use parity_scale_codec::Encode; use sc_network::{config::Role, Event as NetworkEvent, ObservedRole, PeerId}; @@ -97,7 +97,7 @@ impl sc_network_gossip::ValidatorContext for TestNetwork { >::write_notification( self, who.clone(), - GRANDPA_PROTOCOL_NAME.into(), + grandpa_protocol_name::NAME.into(), data, ); } @@ -148,6 +148,7 @@ fn config() -> crate::Config { local_role: Role::Authority, observer_enabled: true, telemetry: None, + protocol_name: grandpa_protocol_name::NAME.into(), } } @@ -286,7 +287,7 @@ fn good_commit_leads_to_relay() { // Add the sending peer and send the commit let _ = sender.unbounded_send(NetworkEvent::NotificationStreamOpened { remote: sender_id.clone(), - protocol: GRANDPA_PROTOCOL_NAME.into(), + protocol: grandpa_protocol_name::NAME.into(), negotiated_fallback: None, role: ObservedRole::Full, }); @@ -294,7 +295,7 @@ fn good_commit_leads_to_relay() { let _ = sender.unbounded_send(NetworkEvent::NotificationsReceived { remote: sender_id.clone(), messages: vec![( - GRANDPA_PROTOCOL_NAME.into(), + grandpa_protocol_name::NAME.into(), commit_to_send.clone().into(), )], }); @@ -303,7 +304,7 @@ fn good_commit_leads_to_relay() { let receiver_id = sc_network::PeerId::random(); let _ = sender.unbounded_send(NetworkEvent::NotificationStreamOpened { remote: receiver_id.clone(), - protocol: GRANDPA_PROTOCOL_NAME.into(), + protocol: grandpa_protocol_name::NAME.into(), negotiated_fallback: None, role: ObservedRole::Full, }); @@ -321,7 +322,10 @@ fn good_commit_leads_to_relay() { sender.unbounded_send(NetworkEvent::NotificationsReceived { remote: receiver_id, - messages: vec![(GRANDPA_PROTOCOL_NAME.into(), msg.encode().into())], + messages: vec![( + grandpa_protocol_name::NAME.into(), + msg.encode().into(), + )], }) }; @@ -433,14 +437,14 @@ fn bad_commit_leads_to_report() { Event::EventStream(sender) => { let _ = sender.unbounded_send(NetworkEvent::NotificationStreamOpened { remote: sender_id.clone(), - protocol: GRANDPA_PROTOCOL_NAME.into(), + protocol: grandpa_protocol_name::NAME.into(), negotiated_fallback: None, role: ObservedRole::Full, }); let _ = sender.unbounded_send(NetworkEvent::NotificationsReceived { remote: sender_id.clone(), messages: vec![( - GRANDPA_PROTOCOL_NAME.into(), + grandpa_protocol_name::NAME.into(), commit_to_send.clone().into(), )], }); diff --git a/client/finality-grandpa/src/lib.rs b/client/finality-grandpa/src/lib.rs index af85965c53c1..b99f6c054419 100644 --- a/client/finality-grandpa/src/lib.rs +++ b/client/finality-grandpa/src/lib.rs @@ -123,6 +123,7 @@ pub mod warp_proof; pub use authorities::{AuthoritySet, AuthoritySetChanges, SharedAuthoritySet}; pub use aux_schema::best_justification; +pub use communication::grandpa_protocol_name::standard_name as protocol_standard_name; pub use finality_grandpa::voter::report; pub use finality_proof::{FinalityProof, FinalityProofError, FinalityProofProvider}; pub use import::{find_forced_change, find_scheduled_change, GrandpaBlockImport}; @@ -263,6 +264,8 @@ pub struct Config { pub keystore: Option, /// TelemetryHandle instance. pub telemetry: Option, + /// Chain specific GRANDPA protocol name. See [`crate::protocol_standard_name`]. + pub protocol_name: std::borrow::Cow<'static, str>, } impl Config { @@ -714,10 +717,14 @@ pub struct GrandpaParams { /// Returns the configuration value to put in /// [`sc_network::config::NetworkConfiguration::extra_sets`]. -pub fn grandpa_peers_set_config() -> sc_network::config::NonDefaultSetConfig { +/// For standard protocol name see [`crate::protocol_standard_name`]. +pub fn grandpa_peers_set_config( + protocol_name: std::borrow::Cow<'static, str>, +) -> sc_network::config::NonDefaultSetConfig { + use communication::grandpa_protocol_name; sc_network::config::NonDefaultSetConfig { - notifications_protocol: communication::GRANDPA_PROTOCOL_NAME.into(), - fallback_names: Vec::new(), + notifications_protocol: protocol_name, + fallback_names: grandpa_protocol_name::LEGACY_NAMES.iter().map(|&n| n.into()).collect(), // Notifications reach ~256kiB in size at the time of writing on Kusama and Polkadot. max_notification_size: 1024 * 1024, set_config: sc_network::config::SetConfig { diff --git a/client/finality-grandpa/src/tests.rs b/client/finality-grandpa/src/tests.rs index f619c03cab6f..2e545b6e88eb 100644 --- a/client/finality-grandpa/src/tests.rs +++ b/client/finality-grandpa/src/tests.rs @@ -56,6 +56,7 @@ use substrate_test_runtime_client::runtime::BlockNumber; use tokio::runtime::{Handle, Runtime}; use authorities::AuthoritySet; +use communication::grandpa_protocol_name; use sc_block_builder::BlockBuilderProvider; use sc_consensus::LongestChain; use sc_keystore::LocalKeystore; @@ -97,7 +98,7 @@ impl GrandpaTestNet { impl GrandpaTestNet { fn add_authority_peer(&mut self) { self.add_full_peer_with_config(FullPeerConfig { - notifications_protocols: vec![communication::GRANDPA_PROTOCOL_NAME.into()], + notifications_protocols: vec![grandpa_protocol_name::NAME.into()], is_authority: true, ..Default::default() }) @@ -121,7 +122,7 @@ impl TestNetFactory for GrandpaTestNet { fn add_full_peer(&mut self) { self.add_full_peer_with_config(FullPeerConfig { - notifications_protocols: vec![communication::GRANDPA_PROTOCOL_NAME.into()], + notifications_protocols: vec![grandpa_protocol_name::NAME.into()], is_authority: false, ..Default::default() }) @@ -274,6 +275,7 @@ fn initialize_grandpa( local_role: Role::Authority, observer_enabled: true, telemetry: None, + protocol_name: grandpa_protocol_name::NAME.into(), }, link, network: net_service, @@ -423,6 +425,7 @@ fn finalize_3_voters_1_full_observer() { local_role: Role::Authority, observer_enabled: true, telemetry: None, + protocol_name: grandpa_protocol_name::NAME.into(), }, link, network: net_service, @@ -513,6 +516,7 @@ fn transition_3_voters_twice_1_full_observer() { local_role: Role::Authority, observer_enabled: true, telemetry: None, + protocol_name: grandpa_protocol_name::NAME.into(), }, link, network: net_service, @@ -971,6 +975,7 @@ fn voter_persists_its_votes() { local_role: Role::Authority, observer_enabled: true, telemetry: None, + protocol_name: grandpa_protocol_name::NAME.into(), }; let set_state = { @@ -1010,6 +1015,7 @@ fn voter_persists_its_votes() { local_role: Role::Authority, observer_enabled: true, telemetry: None, + protocol_name: grandpa_protocol_name::NAME.into(), }, link, network: net_service, @@ -1050,6 +1056,7 @@ fn voter_persists_its_votes() { local_role: Role::Authority, observer_enabled: true, telemetry: None, + protocol_name: grandpa_protocol_name::NAME.into(), }, link, network: net_service, @@ -1213,6 +1220,7 @@ fn finalize_3_voters_1_light_observer() { local_role: Role::Full, observer_enabled: true, telemetry: None, + protocol_name: grandpa_protocol_name::NAME.into(), }, net.peers[3].data.lock().take().expect("link initialized at startup; qed"), net.peers[3].network_service().clone(), @@ -1259,6 +1267,7 @@ fn voter_catches_up_to_latest_round_when_behind() { local_role: Role::Authority, observer_enabled: true, telemetry: None, + protocol_name: grandpa_protocol_name::NAME.into(), }, link, network: net.lock().peer(peer_id).network_service().clone(), @@ -1376,6 +1385,7 @@ where local_role: Role::Authority, observer_enabled: true, telemetry: None, + protocol_name: grandpa_protocol_name::NAME.into(), }; let network = diff --git a/client/network/src/config.rs b/client/network/src/config.rs index 333ea41c8d80..14411ef2aa18 100644 --- a/client/network/src/config.rs +++ b/client/network/src/config.rs @@ -603,6 +603,13 @@ impl NonDefaultSetConfig { pub fn add_reserved(&mut self, peer: MultiaddrWithPeerId) { self.set_config.reserved_nodes.push(peer); } + + /// Add a list of protocol names used for backward compatibility. + /// + /// See the explanations in [`NonDefaultSetConfig::fallback_names`]. + pub fn add_fallback_names(&mut self, fallback_names: Vec>) { + self.fallback_names.extend(fallback_names); + } } /// Configuration for the transport layer. From cfcdc10a0d37ba588b442332ab6f8153b358fa2b Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Wed, 5 Jan 2022 19:08:36 -0400 Subject: [PATCH 354/695] Fix Clippy (#10596) * fix clippy * fmt --- client/chain-spec/src/chain_spec.rs | 2 +- client/service/src/client/call_executor.rs | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/client/chain-spec/src/chain_spec.rs b/client/chain-spec/src/chain_spec.rs index 9b672ce7c362..59d3ac351381 100644 --- a/client/chain-spec/src/chain_spec.rs +++ b/client/chain-spec/src/chain_spec.rs @@ -229,7 +229,7 @@ impl ChainSpec { /// Optional network fork identifier. pub fn fork_id(&self) -> Option<&str> { - self.client_spec.fork_id.as_ref().map(String::as_str) + self.client_spec.fork_id.as_deref() } /// Additional loosly-typed properties of the chain. diff --git a/client/service/src/client/call_executor.rs b/client/service/src/client/call_executor.rs index fedd3400488d..a806b2dbb6d4 100644 --- a/client/service/src/client/call_executor.rs +++ b/client/service/src/client/call_executor.rs @@ -246,9 +246,7 @@ where &runtime_code, self.spawn_handle.clone(), ) - .with_storage_transaction_cache( - storage_transaction_cache.as_mut().map(|c| &mut **c), - ) + .with_storage_transaction_cache(storage_transaction_cache.as_deref_mut()) .set_parent_hash(at_hash); state_machine.execute_using_consensus_failure_handler( execution_manager, From cc3b082e9fa92fcd2e09836c59e113be1dcb0aa7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 6 Jan 2022 09:22:35 +0000 Subject: [PATCH 355/695] Bump proc-macro2 from 1.0.32 to 1.0.36 (#10564) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Bump proc-macro2 from 1.0.32 to 1.0.36 Bumps [proc-macro2](https://github.com/dtolnay/proc-macro2) from 1.0.32 to 1.0.36. - [Release notes](https://github.com/dtolnay/proc-macro2/releases) - [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.32...1.0.36) --- updated-dependencies: - dependency-name: proc-macro2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * Fix ui tests Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Bastian Köcher --- Cargo.lock | 4 ++-- client/chain-spec/derive/Cargo.toml | 2 +- client/tracing/proc-macro/Cargo.toml | 2 +- frame/staking/reward-curve/Cargo.toml | 2 +- frame/support/procedural/Cargo.toml | 2 +- frame/support/procedural/tools/Cargo.toml | 2 +- frame/support/procedural/tools/derive/Cargo.toml | 2 +- .../tests/construct_runtime_ui/missing_where_block.stderr | 4 ++-- .../tests/construct_runtime_ui/missing_where_param.stderr | 4 ++-- primitives/api/proc-macro/Cargo.toml | 2 +- primitives/core/hashing/proc-macro/Cargo.toml | 2 +- primitives/npos-elections/solution-type/Cargo.toml | 2 +- primitives/runtime-interface/proc-macro/Cargo.toml | 2 +- primitives/version/proc-macro/Cargo.toml | 2 +- test-utils/derive/Cargo.toml | 2 +- 15 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 16a24f284dc4..1dbd54049113 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6866,9 +6866,9 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro2" -version = "1.0.32" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43" +checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" dependencies = [ "unicode-xid", ] diff --git a/client/chain-spec/derive/Cargo.toml b/client/chain-spec/derive/Cargo.toml index 97573c8ca3b0..1ea9440572d4 100644 --- a/client/chain-spec/derive/Cargo.toml +++ b/client/chain-spec/derive/Cargo.toml @@ -16,7 +16,7 @@ proc-macro = true [dependencies] proc-macro-crate = "1.1.0" -proc-macro2 = "1.0.29" +proc-macro2 = "1.0.36" quote = "1.0.10" syn = "1.0.82" diff --git a/client/tracing/proc-macro/Cargo.toml b/client/tracing/proc-macro/Cargo.toml index 53d463a4f4e5..e939d0837b21 100644 --- a/client/tracing/proc-macro/Cargo.toml +++ b/client/tracing/proc-macro/Cargo.toml @@ -16,6 +16,6 @@ proc-macro = true [dependencies] proc-macro-crate = "1.1.0" -proc-macro2 = "1.0.29" +proc-macro2 = "1.0.36" quote = { version = "1.0.10", features = ["proc-macro"] } syn = { version = "1.0.82", features = ["proc-macro", "full", "extra-traits", "parsing"] } diff --git a/frame/staking/reward-curve/Cargo.toml b/frame/staking/reward-curve/Cargo.toml index 7d95152ea65a..bcbdffd6adc3 100644 --- a/frame/staking/reward-curve/Cargo.toml +++ b/frame/staking/reward-curve/Cargo.toml @@ -17,7 +17,7 @@ proc-macro = true [dependencies] syn = { version = "1.0.82", features = ["full", "visit"] } quote = "1.0.10" -proc-macro2 = "1.0.29" +proc-macro2 = "1.0.36" proc-macro-crate = "1.1.0" [dev-dependencies] diff --git a/frame/support/procedural/Cargo.toml b/frame/support/procedural/Cargo.toml index 7a1eaa3a0817..640fe436b185 100644 --- a/frame/support/procedural/Cargo.toml +++ b/frame/support/procedural/Cargo.toml @@ -16,7 +16,7 @@ proc-macro = true [dependencies] frame-support-procedural-tools = { version = "4.0.0-dev", path = "./tools" } -proc-macro2 = "1.0.29" +proc-macro2 = "1.0.36" quote = "1.0.10" Inflector = "0.11.4" syn = { version = "1.0.82", features = ["full"] } diff --git a/frame/support/procedural/tools/Cargo.toml b/frame/support/procedural/tools/Cargo.toml index 265952ebc4b7..ae2de2effd4a 100644 --- a/frame/support/procedural/tools/Cargo.toml +++ b/frame/support/procedural/tools/Cargo.toml @@ -13,7 +13,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] frame-support-procedural-tools-derive = { version = "3.0.0", path = "./derive" } -proc-macro2 = "1.0.29" +proc-macro2 = "1.0.36" quote = "1.0.10" syn = { version = "1.0.82", features = ["full", "visit", "extra-traits"] } proc-macro-crate = "1.1.0" diff --git a/frame/support/procedural/tools/derive/Cargo.toml b/frame/support/procedural/tools/derive/Cargo.toml index df994e14226d..5ed1b506dfb9 100644 --- a/frame/support/procedural/tools/derive/Cargo.toml +++ b/frame/support/procedural/tools/derive/Cargo.toml @@ -15,6 +15,6 @@ targets = ["x86_64-unknown-linux-gnu"] proc-macro = true [dependencies] -proc-macro2 = "1.0.29" +proc-macro2 = "1.0.36" quote = { version = "1.0.10", features = ["proc-macro"] } syn = { version = "1.0.82", features = ["proc-macro" ,"full", "extra-traits", "parsing"] } diff --git a/frame/support/test/tests/construct_runtime_ui/missing_where_block.stderr b/frame/support/test/tests/construct_runtime_ui/missing_where_block.stderr index 4af672a2610b..c6baf8fc24d0 100644 --- a/frame/support/test/tests/construct_runtime_ui/missing_where_block.stderr +++ b/frame/support/test/tests/construct_runtime_ui/missing_where_block.stderr @@ -1,5 +1,5 @@ error: expected `where` - --> $DIR/missing_where_block.rs:4:19 + --> tests/construct_runtime_ui/missing_where_block.rs:4:19 | 4 | pub enum Runtime {} - | ^^ + | ^ diff --git a/frame/support/test/tests/construct_runtime_ui/missing_where_param.stderr b/frame/support/test/tests/construct_runtime_ui/missing_where_param.stderr index ac7313523c0c..fb7e38b53dcd 100644 --- a/frame/support/test/tests/construct_runtime_ui/missing_where_param.stderr +++ b/frame/support/test/tests/construct_runtime_ui/missing_where_param.stderr @@ -1,5 +1,5 @@ error: Missing associated type for `UncheckedExtrinsic`. Add `UncheckedExtrinsic` = ... to where section. - --> $DIR/missing_where_param.rs:7:2 + --> tests/construct_runtime_ui/missing_where_param.rs:7:2 | 7 | {} - | ^^ + | ^ diff --git a/primitives/api/proc-macro/Cargo.toml b/primitives/api/proc-macro/Cargo.toml index 4afc07833649..30ab3ef9562b 100644 --- a/primitives/api/proc-macro/Cargo.toml +++ b/primitives/api/proc-macro/Cargo.toml @@ -18,7 +18,7 @@ proc-macro = true [dependencies] quote = "1.0.10" syn = { version = "1.0.82", features = ["full", "fold", "extra-traits", "visit"] } -proc-macro2 = "1.0.29" +proc-macro2 = "1.0.36" blake2-rfc = { version = "0.2.18", default-features = false } proc-macro-crate = "1.1.0" diff --git a/primitives/core/hashing/proc-macro/Cargo.toml b/primitives/core/hashing/proc-macro/Cargo.toml index 4df40e55bc90..fea865ab9e10 100644 --- a/primitives/core/hashing/proc-macro/Cargo.toml +++ b/primitives/core/hashing/proc-macro/Cargo.toml @@ -18,5 +18,5 @@ proc-macro = true [dependencies] syn = { version = "1.0.82", features = ["full", "parsing"] } quote = "1.0.6" -proc-macro2 = "1.0.29" +proc-macro2 = "1.0.36" sp-core-hashing = { version = "4.0.0", path = "../", default-features = false } diff --git a/primitives/npos-elections/solution-type/Cargo.toml b/primitives/npos-elections/solution-type/Cargo.toml index cf2a2016500a..cfb3af4552e2 100644 --- a/primitives/npos-elections/solution-type/Cargo.toml +++ b/primitives/npos-elections/solution-type/Cargo.toml @@ -17,7 +17,7 @@ proc-macro = true [dependencies] syn = { version = "1.0.82", features = ["full", "visit"] } quote = "1.0" -proc-macro2 = "1.0.29" +proc-macro2 = "1.0.36" proc-macro-crate = "1.1.0" [dev-dependencies] diff --git a/primitives/runtime-interface/proc-macro/Cargo.toml b/primitives/runtime-interface/proc-macro/Cargo.toml index 031906486b55..f69c49843c1d 100644 --- a/primitives/runtime-interface/proc-macro/Cargo.toml +++ b/primitives/runtime-interface/proc-macro/Cargo.toml @@ -18,6 +18,6 @@ proc-macro = true [dependencies] syn = { version = "1.0.82", features = ["full", "visit", "fold", "extra-traits"] } quote = "1.0.10" -proc-macro2 = "1.0.29" +proc-macro2 = "1.0.36" Inflector = "0.11.4" proc-macro-crate = "1.1.0" diff --git a/primitives/version/proc-macro/Cargo.toml b/primitives/version/proc-macro/Cargo.toml index df254e64f34c..a706f74f4522 100644 --- a/primitives/version/proc-macro/Cargo.toml +++ b/primitives/version/proc-macro/Cargo.toml @@ -18,7 +18,7 @@ proc-macro = true [dependencies] quote = "1.0.10" syn = { version = "1.0.82", features = ["full", "fold", "extra-traits", "visit"] } -proc-macro2 = "1.0.29" +proc-macro2 = "1.0.36" codec = { package = "parity-scale-codec", version = "2.0.0", features = [ "derive" ] } [dev-dependencies] diff --git a/test-utils/derive/Cargo.toml b/test-utils/derive/Cargo.toml index 83782a2ba5ff..166d9cc1eff1 100644 --- a/test-utils/derive/Cargo.toml +++ b/test-utils/derive/Cargo.toml @@ -12,7 +12,7 @@ description = "Substrate test utilities macros" quote = "1.0.10" syn = { version = "1.0.82", features = ["full"] } proc-macro-crate = "1.1.0" -proc-macro2 = "1.0.29" +proc-macro2 = "1.0.36" [lib] proc-macro = true From 3807a879241c4e43fe20fc5296239ad8d024c82c Mon Sep 17 00:00:00 2001 From: Zeke Mostov Date: Thu, 6 Jan 2022 01:41:18 -0800 Subject: [PATCH 356/695] Add benchmark tests for pallet bags list (#10593) * Add benchmark tests for pallet bags list * Make sure to set active balance for new ledgers * fmt * cargo run --quiet --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_bags_list --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/bags-list/src/weights.rs --template=./.maintain/frame-weight-template.hbs Co-authored-by: Parity Bot Co-authored-by: Shawn Tabrizi --- frame/bags-list/src/benchmarks.rs | 6 ++++++ frame/bags-list/src/weights.rs | 16 ++++++++-------- frame/staking/src/pallet/impls.rs | 9 ++++----- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/frame/bags-list/src/benchmarks.rs b/frame/bags-list/src/benchmarks.rs index 5f0bcd460386..cc575d7d1eff 100644 --- a/frame/bags-list/src/benchmarks.rs +++ b/frame/bags-list/src/benchmarks.rs @@ -175,3 +175,9 @@ frame_benchmarking::benchmarks! { ) } } + +frame_benchmarking::impl_benchmark_test_suite!( + Pallet, + crate::mock::ExtBuilder::default().skip_genesis_ids().build(), + crate::mock::Runtime +); diff --git a/frame/bags-list/src/weights.rs b/frame/bags-list/src/weights.rs index cd5aed0770ab..5a8f51cc07c7 100644 --- a/frame/bags-list/src/weights.rs +++ b/frame/bags-list/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. +// Copyright (C) 2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_bags_list //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-11-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-01-05, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 // Executed Command: @@ -57,7 +57,7 @@ impl WeightInfo for SubstrateWeight { // Storage: BagsList ListNodes (r:4 w:4) // Storage: BagsList ListBags (r:1 w:1) fn rebag_non_terminal() -> Weight { - (70_481_000 as Weight) + (62_060_000 as Weight) .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } @@ -66,7 +66,7 @@ impl WeightInfo for SubstrateWeight { // Storage: BagsList ListNodes (r:3 w:3) // Storage: BagsList ListBags (r:2 w:2) fn rebag_terminal() -> Weight { - (68_642_000 as Weight) + (60_585_000 as Weight) .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } @@ -76,7 +76,7 @@ impl WeightInfo for SubstrateWeight { // Storage: BagsList CounterForListNodes (r:1 w:1) // Storage: BagsList ListBags (r:1 w:1) fn put_in_front_of() -> Weight { - (82_341_000 as Weight) + (69_779_000 as Weight) .saturating_add(T::DbWeight::get().reads(10 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } @@ -89,7 +89,7 @@ impl WeightInfo for () { // Storage: BagsList ListNodes (r:4 w:4) // Storage: BagsList ListBags (r:1 w:1) fn rebag_non_terminal() -> Weight { - (70_481_000 as Weight) + (62_060_000 as Weight) .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } @@ -98,7 +98,7 @@ impl WeightInfo for () { // Storage: BagsList ListNodes (r:3 w:3) // Storage: BagsList ListBags (r:2 w:2) fn rebag_terminal() -> Weight { - (68_642_000 as Weight) + (60_585_000 as Weight) .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } @@ -108,7 +108,7 @@ impl WeightInfo for () { // Storage: BagsList CounterForListNodes (r:1 w:1) // Storage: BagsList ListBags (r:1 w:1) fn put_in_front_of() -> Weight { - (82_341_000 as Weight) + (69_779_000 as Weight) .saturating_add(RocksDbWeight::get().reads(10 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index ea2c746ed717..c97541de8196 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -1245,13 +1245,12 @@ impl VoteWeightProvider for Pallet { // this will clearly results in an inconsistent state, but it should not matter for a // benchmark. let active: BalanceOf = weight.try_into().map_err(|_| ()).unwrap(); - let ledger = match Self::ledger(who) { + let mut ledger = match Self::ledger(who) { None => StakingLedger::default_from(who.clone()), - Some(mut l) => { - l.active = active; - l - }, + Some(l) => l, }; + ledger.active = active; + >::insert(who, ledger); >::insert(who, who); From d642f5eb4aa8f3e4625eba94b868280b48b8fccd Mon Sep 17 00:00:00 2001 From: wigy <1888808+wigy-opensource-developer@users.noreply.github.com> Date: Thu, 6 Jan 2022 11:12:54 +0100 Subject: [PATCH 357/695] Exclude big changes from file annotations (#10588) --- .git-blame-ignore-revs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .git-blame-ignore-revs diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 000000000000..c99a3070231d --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,15 @@ +# You can easily exclude big automated code changes by running +# +# git config blame.ignoreRevsFile .git-blame-ignore-revs +# +# in your local repository. It will work also in IDE integrations. +# +# On versions of Git 2.20 and later comments (#), empty lines, and any leading and +# trailing whitespace is ignored. Everything but a SHA-1 per line will error out on +# older versions. +# +# You should add new commit hashes to this file when you create or find such big +# automated refactorings while reading code history. If you only know the short hash, +# use `git rev-parse 1d5abf01` to expand it to the full SHA1 hash needed in this file. + +1d5abf01abafdb6c15bcd0172f5de09fd87c5fbf # Run cargo fmt on the whole code base (#9394) From 55f7969720e003ce77697d26d5a965eb346f8018 Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Thu, 6 Jan 2022 11:55:21 +0100 Subject: [PATCH 358/695] some improvements to bounded vec API (#10590) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * some improvements to bounded vec * revert license tweak * more tests * fix * Update frame/support/src/storage/bounded_vec.rs Co-authored-by: Bastian Köcher * add the same stuff for btree map and set as well Co-authored-by: Bastian Köcher --- .../support/src/storage/bounded_btree_map.rs | 93 +++++++++++++- .../support/src/storage/bounded_btree_set.rs | 118 +++++++++++++++--- frame/support/src/storage/bounded_vec.rs | 109 ++++++++++++++-- frame/support/src/traits.rs | 3 +- frame/support/src/traits/misc.rs | 10 ++ 5 files changed, 301 insertions(+), 32 deletions(-) diff --git a/frame/support/src/storage/bounded_btree_map.rs b/frame/support/src/storage/bounded_btree_map.rs index 201015e3a622..ed132adac657 100644 --- a/frame/support/src/storage/bounded_btree_map.rs +++ b/frame/support/src/storage/bounded_btree_map.rs @@ -17,7 +17,10 @@ //! Traits, types and structs to support a bounded BTreeMap. -use crate::{storage::StorageDecodeLength, traits::Get}; +use crate::{ + storage::StorageDecodeLength, + traits::{Get, TryCollect}, +}; use codec::{Decode, Encode, MaxEncodedLen}; use sp_std::{ borrow::Borrow, collections::btree_map::BTreeMap, convert::TryFrom, marker::PhantomData, @@ -69,6 +72,11 @@ where K: Ord, S: Get, { + /// Create `Self` from `t` without any checks. + fn unchecked_from(t: BTreeMap) -> Self { + Self(t, Default::default()) + } + /// Create a new `BoundedBTreeMap`. /// /// Does not allocate. @@ -183,16 +191,23 @@ where } } -impl PartialEq for BoundedBTreeMap +impl PartialEq> for BoundedBTreeMap where BTreeMap: PartialEq, + S1: Get, + S2: Get, { - fn eq(&self, other: &Self) -> bool { - self.0 == other.0 + fn eq(&self, other: &BoundedBTreeMap) -> bool { + S1::get() == S2::get() && self.0 == other.0 } } -impl Eq for BoundedBTreeMap where BTreeMap: Eq {} +impl Eq for BoundedBTreeMap +where + BTreeMap: Eq, + S: Get, +{ +} impl PartialEq> for BoundedBTreeMap where @@ -206,6 +221,7 @@ where impl PartialOrd for BoundedBTreeMap where BTreeMap: PartialOrd, + S: Get, { fn partial_cmp(&self, other: &Self) -> Option { self.0.partial_cmp(&other.0) @@ -215,6 +231,7 @@ where impl Ord for BoundedBTreeMap where BTreeMap: Ord, + S: Get, { fn cmp(&self, other: &Self) -> sp_std::cmp::Ordering { self.0.cmp(&other.0) @@ -302,6 +319,23 @@ impl codec::EncodeLike> for BoundedBTreeMap whe { } +impl TryCollect> for I +where + K: Ord, + I: ExactSizeIterator + Iterator, + Bound: Get, +{ + type Error = &'static str; + + fn try_collect(self) -> Result, Self::Error> { + if self.len() > Bound::get() as usize { + Err("iterator length too big") + } else { + Ok(BoundedBTreeMap::::unchecked_from(self.collect::>())) + } + } +} + #[cfg(test)] pub mod test { use super::*; @@ -452,4 +486,53 @@ pub mod test { assert_eq!(zero_key.1, false); assert_eq!(*zero_value, 6); } + + #[test] + fn can_be_collected() { + let b1 = boundedmap_from_keys::>(&[1, 2, 3, 4]); + let b2: BoundedBTreeMap> = + b1.iter().map(|(k, v)| (k + 1, *v)).try_collect().unwrap(); + assert_eq!(b2.into_iter().map(|(k, _)| k).collect::>(), vec![2, 3, 4, 5]); + + // can also be collected into a collection of length 4. + let b2: BoundedBTreeMap> = + b1.iter().map(|(k, v)| (k + 1, *v)).try_collect().unwrap(); + assert_eq!(b2.into_iter().map(|(k, _)| k).collect::>(), vec![2, 3, 4, 5]); + + // can be mutated further into iterators that are `ExactSizedIterator`. + let b2: BoundedBTreeMap> = + b1.iter().map(|(k, v)| (k + 1, *v)).rev().skip(2).try_collect().unwrap(); + // note that the binary tree will re-sort this, so rev() is not really seen + assert_eq!(b2.into_iter().map(|(k, _)| k).collect::>(), vec![2, 3]); + + let b2: BoundedBTreeMap> = + b1.iter().map(|(k, v)| (k + 1, *v)).take(2).try_collect().unwrap(); + assert_eq!(b2.into_iter().map(|(k, _)| k).collect::>(), vec![2, 3]); + + // but these worn't work + let b2: Result>, _> = + b1.iter().map(|(k, v)| (k + 1, *v)).try_collect(); + assert!(b2.is_err()); + + let b2: Result>, _> = + b1.iter().map(|(k, v)| (k + 1, *v)).skip(2).try_collect(); + assert!(b2.is_err()); + } + + #[test] + fn eq_works() { + // of same type + let b1 = boundedmap_from_keys::>(&[1, 2]); + let b2 = boundedmap_from_keys::>(&[1, 2]); + assert_eq!(b1, b2); + + // of different type, but same value and bound. + crate::parameter_types! { + B1: u32 = 7; + B2: u32 = 7; + } + let b1 = boundedmap_from_keys::(&[1, 2]); + let b2 = boundedmap_from_keys::(&[1, 2]); + assert_eq!(b1, b2); + } } diff --git a/frame/support/src/storage/bounded_btree_set.rs b/frame/support/src/storage/bounded_btree_set.rs index f51439f04d13..7d543549c6ba 100644 --- a/frame/support/src/storage/bounded_btree_set.rs +++ b/frame/support/src/storage/bounded_btree_set.rs @@ -17,7 +17,10 @@ //! Traits, types and structs to support a bounded `BTreeSet`. -use crate::{storage::StorageDecodeLength, traits::Get}; +use crate::{ + storage::StorageDecodeLength, + traits::{Get, TryCollect}, +}; use codec::{Decode, Encode, MaxEncodedLen}; use sp_std::{ borrow::Borrow, collections::btree_set::BTreeSet, convert::TryFrom, marker::PhantomData, @@ -68,6 +71,11 @@ where T: Ord, S: Get, { + /// Create `Self` from `t` without any checks. + fn unchecked_from(t: BTreeSet) -> Self { + Self(t, Default::default()) + } + /// Create a new `BoundedBTreeSet`. /// /// Does not allocate. @@ -168,20 +176,28 @@ where } } -impl PartialEq for BoundedBTreeSet +impl PartialEq> for BoundedBTreeSet where BTreeSet: PartialEq, + S1: Get, + S2: Get, { - fn eq(&self, other: &Self) -> bool { - self.0 == other.0 + fn eq(&self, other: &BoundedBTreeSet) -> bool { + S1::get() == S2::get() && self.0 == other.0 } } -impl Eq for BoundedBTreeSet where BTreeSet: Eq {} +impl Eq for BoundedBTreeSet +where + BTreeSet: Eq, + S: Get, +{ +} impl PartialEq> for BoundedBTreeSet where BTreeSet: PartialEq, + S: Get, { fn eq(&self, other: &BTreeSet) -> bool { self.0 == *other @@ -191,6 +207,7 @@ where impl PartialOrd for BoundedBTreeSet where BTreeSet: PartialOrd, + S: Get, { fn partial_cmp(&self, other: &Self) -> Option { self.0.partial_cmp(&other.0) @@ -200,6 +217,7 @@ where impl Ord for BoundedBTreeSet where BTreeSet: Ord, + S: Get, { fn cmp(&self, other: &Self) -> sp_std::cmp::Ordering { self.0.cmp(&other.0) @@ -283,6 +301,23 @@ impl StorageDecodeLength for BoundedBTreeSet {} impl codec::EncodeLike> for BoundedBTreeSet where BTreeSet: Encode {} +impl TryCollect> for I +where + T: Ord, + I: ExactSizeIterator + Iterator, + Bound: Get, +{ + type Error = &'static str; + + fn try_collect(self) -> Result, Self::Error> { + if self.len() > Bound::get() as usize { + Err("iterator length too big") + } else { + Ok(BoundedBTreeSet::::unchecked_from(self.collect::>())) + } + } +} + #[cfg(test)] pub mod test { use super::*; @@ -298,31 +333,31 @@ pub mod test { FooDoubleMap => DoubleMap<(u32, Twox128), (u32, Twox128), BoundedBTreeSet>> } - fn map_from_keys(keys: &[T]) -> BTreeSet + fn set_from_keys(keys: &[T]) -> BTreeSet where T: Ord + Copy, { keys.iter().copied().collect() } - fn boundedmap_from_keys(keys: &[T]) -> BoundedBTreeSet + fn boundedset_from_keys(keys: &[T]) -> BoundedBTreeSet where T: Ord + Copy, S: Get, { - map_from_keys(keys).try_into().unwrap() + set_from_keys(keys).try_into().unwrap() } #[test] fn decode_len_works() { TestExternalities::default().execute_with(|| { - let bounded = boundedmap_from_keys::>(&[1, 2, 3]); + let bounded = boundedset_from_keys::>(&[1, 2, 3]); Foo::put(bounded); assert_eq!(Foo::decode_len().unwrap(), 3); }); TestExternalities::default().execute_with(|| { - let bounded = boundedmap_from_keys::>(&[1, 2, 3]); + let bounded = boundedset_from_keys::>(&[1, 2, 3]); FooMap::insert(1, bounded); assert_eq!(FooMap::decode_len(1).unwrap(), 3); assert!(FooMap::decode_len(0).is_none()); @@ -330,7 +365,7 @@ pub mod test { }); TestExternalities::default().execute_with(|| { - let bounded = boundedmap_from_keys::>(&[1, 2, 3]); + let bounded = boundedset_from_keys::>(&[1, 2, 3]); FooDoubleMap::insert(1, 1, bounded); assert_eq!(FooDoubleMap::decode_len(1, 1).unwrap(), 3); assert!(FooDoubleMap::decode_len(2, 1).is_none()); @@ -341,17 +376,17 @@ pub mod test { #[test] fn try_insert_works() { - let mut bounded = boundedmap_from_keys::>(&[1, 2, 3]); + let mut bounded = boundedset_from_keys::>(&[1, 2, 3]); bounded.try_insert(0).unwrap(); - assert_eq!(*bounded, map_from_keys(&[1, 0, 2, 3])); + assert_eq!(*bounded, set_from_keys(&[1, 0, 2, 3])); assert!(bounded.try_insert(9).is_err()); - assert_eq!(*bounded, map_from_keys(&[1, 0, 2, 3])); + assert_eq!(*bounded, set_from_keys(&[1, 0, 2, 3])); } #[test] fn deref_coercion_works() { - let bounded = boundedmap_from_keys::>(&[1, 2, 3]); + let bounded = boundedset_from_keys::>(&[1, 2, 3]); // these methods come from deref-ed vec. assert_eq!(bounded.len(), 3); assert!(bounded.iter().next().is_some()); @@ -360,7 +395,7 @@ pub mod test { #[test] fn try_mutate_works() { - let bounded = boundedmap_from_keys::>(&[1, 2, 3, 4, 5, 6]); + let bounded = boundedset_from_keys::>(&[1, 2, 3, 4, 5, 6]); let bounded = bounded .try_mutate(|v| { v.insert(7); @@ -376,8 +411,8 @@ pub mod test { #[test] fn btree_map_eq_works() { - let bounded = boundedmap_from_keys::>(&[1, 2, 3, 4, 5, 6]); - assert_eq!(bounded, map_from_keys(&[1, 2, 3, 4, 5, 6])); + let bounded = boundedset_from_keys::>(&[1, 2, 3, 4, 5, 6]); + assert_eq!(bounded, set_from_keys(&[1, 2, 3, 4, 5, 6])); } #[test] @@ -433,4 +468,51 @@ pub mod test { assert_eq!(zero_item.0, 0); assert_eq!(zero_item.1, false); } + + #[test] + fn can_be_collected() { + let b1 = boundedset_from_keys::>(&[1, 2, 3, 4]); + let b2: BoundedBTreeSet> = b1.iter().map(|k| k + 1).try_collect().unwrap(); + assert_eq!(b2.into_iter().collect::>(), vec![2, 3, 4, 5]); + + // can also be collected into a collection of length 4. + let b2: BoundedBTreeSet> = b1.iter().map(|k| k + 1).try_collect().unwrap(); + assert_eq!(b2.into_iter().collect::>(), vec![2, 3, 4, 5]); + + // can be mutated further into iterators that are `ExactSizedIterator`. + let b2: BoundedBTreeSet> = + b1.iter().map(|k| k + 1).rev().skip(2).try_collect().unwrap(); + // note that the binary tree will re-sort this, so rev() is not really seen + assert_eq!(b2.into_iter().collect::>(), vec![2, 3]); + + let b2: BoundedBTreeSet> = + b1.iter().map(|k| k + 1).take(2).try_collect().unwrap(); + assert_eq!(b2.into_iter().collect::>(), vec![2, 3]); + + // but these worn't work + let b2: Result>, _> = + b1.iter().map(|k| k + 1).try_collect(); + assert!(b2.is_err()); + + let b2: Result>, _> = + b1.iter().map(|k| k + 1).skip(2).try_collect(); + assert!(b2.is_err()); + } + + #[test] + fn eq_works() { + // of same type + let b1 = boundedset_from_keys::>(&[1, 2]); + let b2 = boundedset_from_keys::>(&[1, 2]); + assert_eq!(b1, b2); + + // of different type, but same value and bound. + crate::parameter_types! { + B1: u32 = 7; + B2: u32 = 7; + } + let b1 = boundedset_from_keys::(&[1, 2]); + let b2 = boundedset_from_keys::(&[1, 2]); + assert_eq!(b1, b2); + } } diff --git a/frame/support/src/storage/bounded_vec.rs b/frame/support/src/storage/bounded_vec.rs index 5ea7a62c79c2..bdac8f23d7c9 100644 --- a/frame/support/src/storage/bounded_vec.rs +++ b/frame/support/src/storage/bounded_vec.rs @@ -20,7 +20,7 @@ use crate::{ storage::{StorageDecodeLength, StorageTryAppend}, - traits::Get, + traits::{Get, TryCollect}, WeakBoundedVec, }; use codec::{Decode, Encode, EncodeLike, MaxEncodedLen}; @@ -146,11 +146,34 @@ impl> From> for Vec { } impl> BoundedVec { + /// Pre-allocate `capacity` items in self. + /// + /// If `capacity` is greater than [`Self::bound`], then the minimum of the two is used. + pub fn with_bounded_capacity(capacity: usize) -> Self { + let capacity = capacity.min(Self::bound()); + Self(Vec::with_capacity(capacity), Default::default()) + } + + /// Allocate self with the maximum possible capacity. + pub fn with_max_capacity() -> Self { + Self::with_bounded_capacity(Self::bound()) + } + /// Get the bound of the type in `usize`. pub fn bound() -> usize { S::get() as usize } + /// Same as `Vec::resize`, but if `size` is more than [`Self::bound`], then [`Self::bound`] is + /// used. + pub fn bounded_resize(&mut self, size: usize, value: T) + where + T: Clone, + { + let size = size.min(Self::bound()); + self.0.resize(size, value); + } + /// Consumes self and mutates self via the given `mutate` function. /// /// If the outcome of mutation is within bounds, `Some(Self)` is returned. Else, `None` is @@ -300,15 +323,14 @@ impl codec::DecodeLength for BoundedVec { } } -// NOTE: we could also implement this as: -// impl, S2: Get> PartialEq> for BoundedVec -// to allow comparison of bounded vectors with different bounds. -impl PartialEq for BoundedVec +impl PartialEq> for BoundedVec where T: PartialEq, + BoundSelf: Get, + BoundRhs: Get, { - fn eq(&self, rhs: &Self) -> bool { - self.0 == rhs.0 + fn eq(&self, rhs: &BoundedVec) -> bool { + BoundSelf::get() == BoundRhs::get() && self.0 == rhs.0 } } @@ -318,7 +340,7 @@ impl> PartialEq> for BoundedVec { } } -impl Eq for BoundedVec where T: Eq {} +impl> Eq for BoundedVec where T: Eq {} impl StorageDecodeLength for BoundedVec {} @@ -344,6 +366,22 @@ where } } +impl TryCollect> for I +where + I: ExactSizeIterator + Iterator, + Bound: Get, +{ + type Error = &'static str; + + fn try_collect(self) -> Result, Self::Error> { + if self.len() > Bound::get() as usize { + Err("iterator length too big") + } else { + Ok(BoundedVec::::unchecked_from(self.collect::>())) + } + } +} + #[cfg(test)] pub mod test { use super::*; @@ -452,4 +490,59 @@ pub mod test { Err("BoundedVec exceeds its limit".into()), ); } + + #[test] + fn can_be_collected() { + let b1: BoundedVec> = vec![1, 2, 3, 4].try_into().unwrap(); + let b2: BoundedVec> = b1.iter().map(|x| x + 1).try_collect().unwrap(); + assert_eq!(b2, vec![2, 3, 4, 5]); + + // can also be collected into a collection of length 4. + let b2: BoundedVec> = b1.iter().map(|x| x + 1).try_collect().unwrap(); + assert_eq!(b2, vec![2, 3, 4, 5]); + + // can be mutated further into iterators that are `ExactSizedIterator`. + let b2: BoundedVec> = + b1.iter().map(|x| x + 1).rev().try_collect().unwrap(); + assert_eq!(b2, vec![5, 4, 3, 2]); + + let b2: BoundedVec> = + b1.iter().map(|x| x + 1).rev().skip(2).try_collect().unwrap(); + assert_eq!(b2, vec![3, 2]); + let b2: BoundedVec> = + b1.iter().map(|x| x + 1).rev().skip(2).try_collect().unwrap(); + assert_eq!(b2, vec![3, 2]); + + let b2: BoundedVec> = + b1.iter().map(|x| x + 1).rev().take(2).try_collect().unwrap(); + assert_eq!(b2, vec![5, 4]); + let b2: BoundedVec> = + b1.iter().map(|x| x + 1).rev().take(2).try_collect().unwrap(); + assert_eq!(b2, vec![5, 4]); + + // but these worn't work + let b2: Result>, _> = b1.iter().map(|x| x + 1).try_collect(); + assert!(b2.is_err()); + + let b2: Result>, _> = + b1.iter().map(|x| x + 1).rev().take(2).try_collect(); + assert!(b2.is_err()); + } + + #[test] + fn eq_works() { + // of same type + let b1: BoundedVec> = vec![1, 2, 3].try_into().unwrap(); + let b2: BoundedVec> = vec![1, 2, 3].try_into().unwrap(); + assert_eq!(b1, b2); + + // of different type, but same value and bound. + crate::parameter_types! { + B1: u32 = 7; + B2: u32 = 7; + } + let b1: BoundedVec = vec![1, 2, 3].try_into().unwrap(); + let b2: BoundedVec = vec![1, 2, 3].try_into().unwrap(); + assert_eq!(b1, b2); + } } diff --git a/frame/support/src/traits.rs b/frame/support/src/traits.rs index d0719063ef3e..85a0698759b6 100644 --- a/frame/support/src/traits.rs +++ b/frame/support/src/traits.rs @@ -54,7 +54,8 @@ pub use misc::{ ConstU32, ConstU64, ConstU8, EnsureInherentsAreFirst, EqualPrivilegeOnly, EstimateCallFee, ExecuteBlock, ExtrinsicCall, Get, GetBacking, GetDefault, HandleLifetime, IsSubType, IsType, Len, OffchainWorker, OnKilledAccount, OnNewAccount, PreimageProvider, PreimageRecipient, - PrivilegeCmp, SameOrOther, Time, TryDrop, UnixTime, WrapperKeepOpaque, WrapperOpaque, + PrivilegeCmp, SameOrOther, Time, TryCollect, TryDrop, UnixTime, WrapperKeepOpaque, + WrapperOpaque, }; mod stored_map; diff --git a/frame/support/src/traits/misc.rs b/frame/support/src/traits/misc.rs index c68561367e3d..df21624c3cea 100644 --- a/frame/support/src/traits/misc.rs +++ b/frame/support/src/traits/misc.rs @@ -23,6 +23,16 @@ use scale_info::{build::Fields, meta_type, Path, Type, TypeInfo, TypeParameter}; use sp_runtime::{traits::Block as BlockT, DispatchError}; use sp_std::{cmp::Ordering, prelude::*}; +/// Try and collect into a collection `C`. +pub trait TryCollect { + type Error; + /// Consume self and try to collect the results into `C`. + /// + /// This is useful in preventing the undesirable `.collect().try_into()` call chain on + /// collections that need to be converted into a bounded type (e.g. `BoundedVec`). + fn try_collect(self) -> Result; +} + /// Anything that can have a `::len()` method. pub trait Len { /// Return the length of data type. From 2316fc9e8e88be70c80023d26ab0e7903d0f5668 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Thu, 6 Jan 2022 12:03:18 +0100 Subject: [PATCH 359/695] contracts: Improve documentation of lazy deletion config (#10582) * Improve documentation of lazy deletion config * Apply suggestions from code review Co-authored-by: Sacha Lansky * Update frame/contracts/src/lib.rs Co-authored-by: Andrew Jones * Improve wording Co-authored-by: Sacha Lansky Co-authored-by: Andrew Jones --- frame/contracts/src/lib.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/frame/contracts/src/lib.rs b/frame/contracts/src/lib.rs index 62e79944bbe9..e4a54362c90b 100644 --- a/frame/contracts/src/lib.rs +++ b/frame/contracts/src/lib.rs @@ -254,11 +254,30 @@ pub mod pallet { /// In other words only the origin called "root contract" is allowed to execute then. type CallStack: smallvec::Array>; - /// The maximum number of tries that can be queued for deletion. + /// The maximum number of contracts that can be pending for deletion. + /// + /// When a contract is deleted by calling `seal_terminate` it becomes inaccessible + /// immediately, but the deletion of the storage items it has accumulated is performed + /// later. The contract is put into the deletion queue. This defines how many + /// contracts can be queued up at the same time. If that limit is reached `seal_terminate` + /// will fail. The action must be retried in a later block in that case. + /// + /// The reasons for limiting the queue depth are: + /// + /// 1. The queue is in storage in order to be persistent between blocks. We want to limit + /// the amount of storage that can be consumed. + /// 2. The queue is stored in a vector and needs to be decoded as a whole when reading + /// it at the end of each block. Longer queues take more weight to decode and hence + /// limit the amount of items that can be deleted per block. #[pallet::constant] type DeletionQueueDepth: Get; /// The maximum amount of weight that can be consumed per block for lazy trie removal. + /// + /// The amount of weight that is dedicated per block to work on the deletion queue. Larger + /// values allow more trie keys to be deleted in each block but reduce the amount of + /// weight that is left for transactions. See [`Self::DeletionQueueDepth`] for more + /// information about the deletion queue. #[pallet::constant] type DeletionWeightLimit: Get; @@ -271,6 +290,7 @@ pub mod pallet { type DepositPerByte: Get>; /// The amount of balance a caller has to pay for each storage item. + /// /// # Note /// /// Changing this value for an existing chain might need a storage migration. From 7409589ab78e7cb508db873dd6384634d667b8f5 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Thu, 6 Jan 2022 15:43:11 +0200 Subject: [PATCH 360/695] Add BEEFY `latestFinalized` RPC and deduplicate code between BEEFY and GRANDPA (#10568) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * beefy: add dummy latest_finalized() RPC * beefy: rpc latest_best_beefy() using shared mem * beefy: rpc populate latest_best_beefy() * beefy: rpc handle readiness * beefy: best block over channel - wip Not working because channel can't be simply opened and receiver passed to `rpc_extensions_builder` because `rpc_extensions_builder` has to be `Fn` and not `FnOnce`... and and Receiver side of mpsc can't be cloned yay!.. * beefy: make notification channels payload-agnostic * beefy: use notification mechanism instead of custom channel * beefy: add tracing key to notif channels * sc-utils: add notification channel - wip * beefy: use sc-utils generic notification channel * grandpa: use sc-utils generic notification channel * fix grumbles * beefy-rpc: get best block header instead of number * beefy-rpc: rename to `beefy_getFinalizedHead` * fix nitpicks * client-rpc-notifications: move generic Error from struct to fn * beefy: use header from notification instead of getting from database * beefy-rpc: get best block hash instead of header * beefy-rpc: fix and improve latestHead test * beefy-rpc: bubble up errors from rpc-handler instantiation * update lockfile * Apply suggestions from code review Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> * fix errors and warnings * fix nit Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> --- Cargo.lock | 40 +++++ client/beefy/rpc/Cargo.toml | 4 + client/beefy/rpc/src/lib.rs | 184 ++++++++++++++++++-- client/beefy/rpc/src/notification.rs | 8 +- client/beefy/src/lib.rs | 8 +- client/beefy/src/notification.rs | 111 +++--------- client/beefy/src/worker.rs | 42 +++-- client/finality-grandpa/rpc/src/lib.rs | 2 +- client/finality-grandpa/src/notification.rs | 87 ++------- client/utils/Cargo.toml | 4 + client/utils/src/lib.rs | 1 + client/utils/src/notification.rs | 151 ++++++++++++++++ 12 files changed, 448 insertions(+), 194 deletions(-) create mode 100644 client/utils/src/notification.rs diff --git a/Cargo.lock b/Cargo.lock index 1dbd54049113..e5192d2c8fe1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -323,6 +323,27 @@ dependencies = [ "trust-dns-resolver", ] +[[package]] +name = "async-stream" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "171374e7e3b2504e0e5236e3b59260560f9fe94bfe9ac39ba5e4e929c5590625" +dependencies = [ + "async-stream-impl", + "futures-core", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "648ed8c8d2ce5409ccd57453d9d1b214b342a0d69376a6feda1fd6cae3299308" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "async-task" version = "4.0.3" @@ -508,6 +529,7 @@ version = "4.0.0-dev" dependencies = [ "beefy-gadget", "beefy-primitives", + "derive_more", "futures 0.3.16", "jsonrpc-core", "jsonrpc-core-client", @@ -515,12 +537,15 @@ dependencies = [ "jsonrpc-pubsub", "log 0.4.14", "parity-scale-codec", + "parking_lot 0.11.2", "sc-rpc", + "sc-utils", "serde", "serde_json", "sp-core", "sp-runtime", "substrate-test-runtime-client", + "thiserror", ] [[package]] @@ -8743,7 +8768,9 @@ dependencies = [ "futures 0.3.16", "futures-timer", "lazy_static", + "parking_lot 0.11.2", "prometheus", + "tokio-test", ] [[package]] @@ -10745,6 +10772,19 @@ dependencies = [ "tokio-reactor", ] +[[package]] +name = "tokio-test" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53474327ae5e166530d17f2d956afcb4f8a004de581b3cae10f12006bc8163e3" +dependencies = [ + "async-stream", + "bytes 1.1.0", + "futures-core", + "tokio", + "tokio-stream", +] + [[package]] name = "tokio-tls" version = "0.2.1" diff --git a/client/beefy/rpc/Cargo.toml b/client/beefy/rpc/Cargo.toml index bc81732dcd41..0f29804d6780 100644 --- a/client/beefy/rpc/Cargo.toml +++ b/client/beefy/rpc/Cargo.toml @@ -8,8 +8,11 @@ repository = "https://github.com/paritytech/substrate" description = "RPC for the BEEFY Client gadget for substrate" [dependencies] +derive_more = "0.99" futures = "0.3.16" log = "0.4" +parking_lot = "0.11" +thiserror = "1.0" serde = { version = "1.0.132", features = ["derive"] } jsonrpc-core = "18.0.0" @@ -20,6 +23,7 @@ jsonrpc-pubsub = "18.0.0" codec = { version = "2.2.0", package = "parity-scale-codec", features = ["derive"] } sc-rpc = { version = "4.0.0-dev", path = "../../rpc" } +sc-utils = { version = "4.0.0-dev", path = "../../utils" } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } diff --git a/client/beefy/rpc/src/lib.rs b/client/beefy/rpc/src/lib.rs index be1c9b8691a2..dc9ee8b94701 100644 --- a/client/beefy/rpc/src/lib.rs +++ b/client/beefy/rpc/src/lib.rs @@ -20,19 +20,62 @@ #![warn(missing_docs)] +use parking_lot::RwLock; use std::sync::Arc; use sp_runtime::traits::Block as BlockT; -use futures::{FutureExt, SinkExt, StreamExt}; +use futures::{task::SpawnError, FutureExt, SinkExt, StreamExt, TryFutureExt}; use jsonrpc_derive::rpc; use jsonrpc_pubsub::{manager::SubscriptionManager, typed::Subscriber, SubscriptionId}; use log::warn; -use beefy_gadget::notification::BeefySignedCommitmentStream; +use beefy_gadget::notification::{BeefyBestBlockStream, BeefySignedCommitmentStream}; mod notification; +type FutureResult = jsonrpc_core::BoxFuture>; + +#[derive(Debug, derive_more::Display, derive_more::From, thiserror::Error)] +/// Top-level error type for the RPC handler +pub enum Error { + /// The BEEFY RPC endpoint is not ready. + #[display(fmt = "BEEFY RPC endpoint not ready")] + EndpointNotReady, + /// The BEEFY RPC background task failed to spawn. + #[display(fmt = "BEEFY RPC background task failed to spawn")] + RpcTaskFailure(SpawnError), +} + +/// The error codes returned by jsonrpc. +pub enum ErrorCode { + /// Returned when BEEFY RPC endpoint is not ready. + NotReady = 1, + /// Returned on BEEFY RPC background task failure. + TaskFailure = 2, +} + +impl From for ErrorCode { + fn from(error: Error) -> Self { + match error { + Error::EndpointNotReady => ErrorCode::NotReady, + Error::RpcTaskFailure(_) => ErrorCode::TaskFailure, + } + } +} + +impl From for jsonrpc_core::Error { + fn from(error: Error) -> Self { + let message = format!("{}", error); + let code = ErrorCode::from(error); + jsonrpc_core::Error { + message, + code: jsonrpc_core::ErrorCode::ServerError(code as i64), + data: None, + } + } +} + /// Provides RPC methods for interacting with BEEFY. #[rpc] pub trait BeefyApi { @@ -62,26 +105,57 @@ pub trait BeefyApi { metadata: Option, id: SubscriptionId, ) -> jsonrpc_core::Result; + + /// Returns hash of the latest BEEFY finalized block as seen by this client. + /// + /// The latest BEEFY block might not be available if the BEEFY gadget is not running + /// in the network or if the client is still initializing or syncing with the network. + /// In such case an error would be returned. + #[rpc(name = "beefy_getFinalizedHead")] + fn latest_finalized(&self) -> FutureResult; } /// Implements the BeefyApi RPC trait for interacting with BEEFY. pub struct BeefyRpcHandler { signed_commitment_stream: BeefySignedCommitmentStream, + beefy_best_block: Arc>>, manager: SubscriptionManager, } impl BeefyRpcHandler { /// Creates a new BeefyRpcHandler instance. - pub fn new(signed_commitment_stream: BeefySignedCommitmentStream, executor: E) -> Self + pub fn new( + signed_commitment_stream: BeefySignedCommitmentStream, + best_block_stream: BeefyBestBlockStream, + executor: E, + ) -> Result where E: futures::task::Spawn + Send + Sync + 'static, { + let beefy_best_block = Arc::new(RwLock::new(None)); + + let stream = best_block_stream.subscribe(); + let closure_clone = beefy_best_block.clone(); + let future = stream.for_each(move |best_beefy| { + let async_clone = closure_clone.clone(); + async move { + *async_clone.write() = Some(best_beefy); + } + }); + + executor + .spawn_obj(futures::task::FutureObj::new(Box::pin(future))) + .map_err(|e| { + log::error!("Failed to spawn BEEFY RPC background task; err: {}", e); + e + })?; + let manager = SubscriptionManager::new(Arc::new(executor)); - Self { signed_commitment_stream, manager } + Ok(Self { signed_commitment_stream, beefy_best_block, manager }) } } -impl BeefyApi for BeefyRpcHandler +impl BeefyApi for BeefyRpcHandler where Block: BlockT, { @@ -90,12 +164,12 @@ where fn subscribe_justifications( &self, _metadata: Self::Metadata, - subscriber: Subscriber, + subscriber: Subscriber, ) { let stream = self .signed_commitment_stream .subscribe() - .map(|x| Ok::<_, ()>(Ok(notification::SignedCommitment::new::(x)))); + .map(|x| Ok::<_, ()>(Ok(notification::EncodedSignedCommitment::new::(x)))); self.manager.add(subscriber, |sink| { stream @@ -111,6 +185,17 @@ where ) -> jsonrpc_core::Result { Ok(self.manager.cancel(id)) } + + fn latest_finalized(&self) -> FutureResult { + let result: Result = self + .beefy_best_block + .read() + .as_ref() + .cloned() + .ok_or(Error::EndpointNotReady.into()); + let future = async move { result }.boxed(); + future.map_err(jsonrpc_core::Error::from).boxed() + } } #[cfg(test)] @@ -118,16 +203,30 @@ mod tests { use super::*; use jsonrpc_core::{types::Params, Notification, Output}; - use beefy_gadget::notification::{BeefySignedCommitmentSender, SignedCommitment}; + use beefy_gadget::notification::{BeefySignedCommitment, BeefySignedCommitmentSender}; use beefy_primitives::{known_payload_ids, Payload}; use codec::{Decode, Encode}; + use sp_runtime::traits::{BlakeTwo256, Hash}; use substrate_test_runtime_client::runtime::Block; fn setup_io_handler( ) -> (jsonrpc_core::MetaIoHandler, BeefySignedCommitmentSender) { - let (commitment_sender, commitment_stream) = BeefySignedCommitmentStream::channel(); + let (_, stream) = BeefyBestBlockStream::::channel(); + setup_io_handler_with_best_block_stream(stream) + } + + fn setup_io_handler_with_best_block_stream( + best_block_stream: BeefyBestBlockStream, + ) -> (jsonrpc_core::MetaIoHandler, BeefySignedCommitmentSender) { + let (commitment_sender, commitment_stream) = + BeefySignedCommitmentStream::::channel(); - let handler = BeefyRpcHandler::new(commitment_stream, sc_rpc::testing::TaskExecutor); + let handler: BeefyRpcHandler = BeefyRpcHandler::new( + commitment_stream, + best_block_stream, + sc_rpc::testing::TaskExecutor, + ) + .unwrap(); let mut io = jsonrpc_core::MetaIoHandler::default(); io.extend_with(BeefyApi::to_delegate(handler)); @@ -141,6 +240,56 @@ mod tests { (meta, rx) } + #[test] + fn uninitialized_rpc_handler() { + let (io, _) = setup_io_handler(); + + let request = r#"{"jsonrpc":"2.0","method":"beefy_getFinalizedHead","params":[],"id":1}"#; + let response = r#"{"jsonrpc":"2.0","error":{"code":1,"message":"BEEFY RPC endpoint not ready"},"id":1}"#; + + let meta = sc_rpc::Metadata::default(); + assert_eq!(Some(response.into()), io.handle_request_sync(request, meta)); + } + + #[test] + fn latest_finalized_rpc() { + let (sender, stream) = BeefyBestBlockStream::::channel(); + let (io, _) = setup_io_handler_with_best_block_stream(stream); + + let hash = BlakeTwo256::hash(b"42"); + let r: Result<(), ()> = sender.notify(|| Ok(hash)); + r.unwrap(); + + // Verify RPC `beefy_getFinalizedHead` returns expected hash. + let request = r#"{"jsonrpc":"2.0","method":"beefy_getFinalizedHead","params":[],"id":1}"#; + let expected = "{\ + \"jsonrpc\":\"2.0\",\ + \"result\":\"0x2f0039e93a27221fcf657fb877a1d4f60307106113e885096cb44a461cd0afbf\",\ + \"id\":1\ + }"; + let not_ready = "{\ + \"jsonrpc\":\"2.0\",\ + \"error\":{\"code\":1,\"message\":\"BEEFY RPC endpoint not ready\"},\ + \"id\":1\ + }"; + + let deadline = std::time::Instant::now() + std::time::Duration::from_secs(2); + while std::time::Instant::now() < deadline { + let meta = sc_rpc::Metadata::default(); + let response = io.handle_request_sync(request, meta); + // Retry "not ready" responses. + if response != Some(not_ready.into()) { + assert_eq!(response, Some(expected.into())); + // Success + return + } + std::thread::sleep(std::time::Duration::from_millis(50)); + } + panic!( + "Deadline reached while waiting for best BEEFY block to update. Perhaps the background task is broken?" + ); + } + #[test] fn subscribe_and_unsubscribe_to_justifications() { let (io, _) = setup_io_handler(); @@ -159,7 +308,7 @@ mod tests { // Unsubscribe let unsub_req = format!( - "{{\"jsonrpc\":\"2.0\",\"method\":\"beefy_unsubscribeJustifications\",\"params\":[{}],\"id\":1}}", + r#"{{"jsonrpc":"2.0","method":"beefy_unsubscribeJustifications","params":[{}],"id":1}}"#, sub_id ); assert_eq!( @@ -170,7 +319,7 @@ mod tests { // Unsubscribe again and fail assert_eq!( io.handle_request_sync(&unsub_req, meta), - Some("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32602,\"message\":\"Invalid subscription id.\"},\"id\":1}".into()), + Some(r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"Invalid subscription id."},"id":1}"#.into()), ); } @@ -192,13 +341,13 @@ mod tests { r#"{"jsonrpc":"2.0","method":"beefy_unsubscribeJustifications","params":["FOO"],"id":1}"#, meta.clone() ), - Some("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32602,\"message\":\"Invalid subscription id.\"},\"id\":1}".into()) + Some(r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"Invalid subscription id."},"id":1}"#.into()) ); } - fn create_commitment() -> SignedCommitment { + fn create_commitment() -> BeefySignedCommitment { let payload = Payload::new(known_payload_ids::MMR_ROOT_ID, "Hello World!".encode()); - SignedCommitment:: { + BeefySignedCommitment:: { commitment: beefy_primitives::Commitment { payload, block_number: 5, @@ -223,7 +372,8 @@ mod tests { // Notify with commitment let commitment = create_commitment(); - commitment_sender.notify(commitment.clone()); + let r: Result<(), ()> = commitment_sender.notify(|| Ok(commitment.clone())); + r.unwrap(); // Inspect what we received let recv = futures::executor::block_on(receiver.take(1).collect::>()); @@ -236,7 +386,7 @@ mod tests { let recv_sub_id: String = serde_json::from_value(json_map["subscription"].take()).unwrap(); let recv_commitment: sp_core::Bytes = serde_json::from_value(json_map["result"].take()).unwrap(); - let recv_commitment: SignedCommitment = + let recv_commitment: BeefySignedCommitment = Decode::decode(&mut &recv_commitment[..]).unwrap(); assert_eq!(recv.method, "beefy_justifications"); diff --git a/client/beefy/rpc/src/notification.rs b/client/beefy/rpc/src/notification.rs index 53c0bb618c5d..2f58c7c6bb5d 100644 --- a/client/beefy/rpc/src/notification.rs +++ b/client/beefy/rpc/src/notification.rs @@ -25,15 +25,15 @@ use sp_runtime::traits::Block as BlockT; /// The given bytes should be the SCALE-encoded representation of a /// `beefy_primitives::SignedCommitment`. #[derive(Clone, Serialize, Deserialize)] -pub struct SignedCommitment(sp_core::Bytes); +pub struct EncodedSignedCommitment(sp_core::Bytes); -impl SignedCommitment { +impl EncodedSignedCommitment { pub fn new( - signed_commitment: beefy_gadget::notification::SignedCommitment, + signed_commitment: beefy_gadget::notification::BeefySignedCommitment, ) -> Self where Block: BlockT, { - SignedCommitment(signed_commitment.encode().into()) + EncodedSignedCommitment(signed_commitment.encode().into()) } } diff --git a/client/beefy/src/lib.rs b/client/beefy/src/lib.rs index 7d2c3b57b1f7..9b2bf383df8e 100644 --- a/client/beefy/src/lib.rs +++ b/client/beefy/src/lib.rs @@ -31,6 +31,8 @@ use sp_runtime::traits::Block; use beefy_primitives::BeefyApi; +use crate::notification::{BeefyBestBlockSender, BeefySignedCommitmentSender}; + mod error; mod gossip; mod keystore; @@ -121,7 +123,9 @@ where /// Gossip network pub network: N, /// BEEFY signed commitment sender - pub signed_commitment_sender: notification::BeefySignedCommitmentSender, + pub signed_commitment_sender: BeefySignedCommitmentSender, + /// BEEFY best block sender + pub beefy_best_block_sender: BeefyBestBlockSender, /// Minimal delta between blocks, BEEFY should vote for pub min_block_delta: u32, /// Prometheus metric registry @@ -147,6 +151,7 @@ where key_store, network, signed_commitment_sender, + beefy_best_block_sender, min_block_delta, prometheus_registry, protocol_name, @@ -174,6 +179,7 @@ where backend, key_store: key_store.into(), signed_commitment_sender, + beefy_best_block_sender, gossip_engine, gossip_validator, min_block_delta, diff --git a/client/beefy/src/notification.rs b/client/beefy/src/notification.rs index cd410ec60bb3..7c18d809f6ef 100644 --- a/client/beefy/src/notification.rs +++ b/client/beefy/src/notification.rs @@ -16,98 +16,41 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::sync::Arc; +use sc_utils::notification::{NotificationSender, NotificationStream, TracingKeyStr}; +use sp_runtime::traits::{Block as BlockT, NumberFor}; -use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender}; -use sp_runtime::traits::{Block, NumberFor}; - -use parking_lot::Mutex; - -/// Stream of signed commitments returned when subscribing. -pub type SignedCommitment = +/// A commitment with matching BEEFY authorities' signatures. +pub type BeefySignedCommitment = beefy_primitives::SignedCommitment, beefy_primitives::crypto::Signature>; -/// Stream of signed commitments returned when subscribing. -type SignedCommitmentStream = TracingUnboundedReceiver>; - -/// Sending endpoint for notifying about signed commitments. -type SignedCommitmentSender = TracingUnboundedSender>; - -/// Collection of channel sending endpoints shared with the receiver side so they can register -/// themselves. -type SharedSignedCommitmentSenders = Arc>>>; - -/// The sending half of the signed commitment channel(s). -/// -/// Used to send notifications about signed commitments generated at the end of a BEEFY round. -#[derive(Clone)] -pub struct BeefySignedCommitmentSender -where - B: Block, -{ - subscribers: SharedSignedCommitmentSenders, -} - -impl BeefySignedCommitmentSender -where - B: Block, -{ - /// The `subscribers` should be shared with a corresponding `SignedCommitmentSender`. - fn new(subscribers: SharedSignedCommitmentSenders) -> Self { - Self { subscribers } - } +/// The sending half of the notifications channel(s) used to send +/// notifications about best BEEFY block from the gadget side. +pub type BeefyBestBlockSender = NotificationSender<::Hash>; - /// Send out a notification to all subscribers that a new signed commitment is available for a - /// block. - pub fn notify(&self, signed_commitment: SignedCommitment) { - let mut subscribers = self.subscribers.lock(); +/// The receiving half of a notifications channel used to receive +/// notifications about best BEEFY blocks determined on the gadget side. +pub type BeefyBestBlockStream = + NotificationStream<::Hash, BeefyBestBlockTracingKey>; - // do an initial prune on closed subscriptions - subscribers.retain(|n| !n.is_closed()); +/// The sending half of the notifications channel(s) used to send notifications +/// about signed commitments generated at the end of a BEEFY round. +pub type BeefySignedCommitmentSender = NotificationSender>; - if !subscribers.is_empty() { - subscribers.retain(|n| n.unbounded_send(signed_commitment.clone()).is_ok()); - } - } -} +/// The receiving half of a notifications channel used to receive notifications +/// about signed commitments generated at the end of a BEEFY round. +pub type BeefySignedCommitmentStream = + NotificationStream, BeefySignedCommitmentTracingKey>; -/// The receiving half of the signed commitments channel. -/// -/// Used to receive notifications about signed commitments generated at the end of a BEEFY round. -/// The `BeefySignedCommitmentStream` entity stores the `SharedSignedCommitmentSenders` so it can be -/// used to add more subscriptions. +/// Provides tracing key for BEEFY best block stream. #[derive(Clone)] -pub struct BeefySignedCommitmentStream -where - B: Block, -{ - subscribers: SharedSignedCommitmentSenders, +pub struct BeefyBestBlockTracingKey; +impl TracingKeyStr for BeefyBestBlockTracingKey { + const TRACING_KEY: &'static str = "mpsc_beefy_best_block_notification_stream"; } -impl BeefySignedCommitmentStream -where - B: Block, -{ - /// Creates a new pair of receiver and sender of signed commitment notifications. - pub fn channel() -> (BeefySignedCommitmentSender, Self) { - let subscribers = Arc::new(Mutex::new(vec![])); - let receiver = BeefySignedCommitmentStream::new(subscribers.clone()); - let sender = BeefySignedCommitmentSender::new(subscribers); - (sender, receiver) - } - - /// Create a new receiver of signed commitment notifications. - /// - /// The `subscribers` should be shared with a corresponding `BeefySignedCommitmentSender`. - fn new(subscribers: SharedSignedCommitmentSenders) -> Self { - Self { subscribers } - } - - /// Subscribe to a channel through which signed commitments are sent at the end of each BEEFY - /// voting round. - pub fn subscribe(&self) -> SignedCommitmentStream { - let (sender, receiver) = tracing_unbounded("mpsc_signed_commitments_notification_stream"); - self.subscribers.lock().push(sender); - receiver - } +/// Provides tracing key for BEEFY signed commitments stream. +#[derive(Clone)] +pub struct BeefySignedCommitmentTracingKey; +impl TracingKeyStr for BeefySignedCommitmentTracingKey { + const TRACING_KEY: &'static str = "mpsc_beefy_signed_commitments_notification_stream"; } diff --git a/client/beefy/src/worker.rs b/client/beefy/src/worker.rs index d3aa988b8ee2..0c7d8d4ffdc9 100644 --- a/client/beefy/src/worker.rs +++ b/client/beefy/src/worker.rs @@ -46,7 +46,8 @@ use crate::{ keystore::BeefyKeystore, metric_inc, metric_set, metrics::Metrics, - notification, round, Client, + notification::{BeefyBestBlockSender, BeefySignedCommitmentSender}, + round, Client, }; pub(crate) struct WorkerParams @@ -56,7 +57,8 @@ where pub client: Arc, pub backend: Arc, pub key_store: BeefyKeystore, - pub signed_commitment_sender: notification::BeefySignedCommitmentSender, + pub signed_commitment_sender: BeefySignedCommitmentSender, + pub beefy_best_block_sender: BeefyBestBlockSender, pub gossip_engine: GossipEngine, pub gossip_validator: Arc>, pub min_block_delta: u32, @@ -73,7 +75,7 @@ where client: Arc, backend: Arc, key_store: BeefyKeystore, - signed_commitment_sender: notification::BeefySignedCommitmentSender, + signed_commitment_sender: BeefySignedCommitmentSender, gossip_engine: Arc>>, gossip_validator: Arc>, /// Min delta in block numbers between two blocks, BEEFY should vote on @@ -85,6 +87,8 @@ where best_grandpa_block: NumberFor, /// Best block a BEEFY voting round has been concluded for best_beefy_block: Option>, + /// Used to keep RPC worker up to date on latest/best beefy + beefy_best_block_sender: BeefyBestBlockSender, /// Validator set id for the last signed commitment last_signed_id: u64, // keep rustc happy @@ -110,6 +114,7 @@ where backend, key_store, signed_commitment_sender, + beefy_best_block_sender, gossip_engine, gossip_validator, min_block_delta, @@ -130,6 +135,7 @@ where best_grandpa_block: client.info().finalized_number, best_beefy_block: None, last_signed_id: 0, + beefy_best_block_sender, _backend: PhantomData, } } @@ -242,6 +248,9 @@ where debug!(target: "beefy", "🥩 New Rounds for id: {:?}", id); self.best_beefy_block = Some(*notification.header.number()); + self.beefy_best_block_sender + .notify(|| Ok::<_, ()>(notification.hash.clone())) + .expect("forwards closure result; the closure always returns Ok; qed."); // this metric is kind of 'fake'. Best BEEFY block should only be updated once we // have a signed commitment for the block. Remove once the above TODO is done. @@ -329,22 +338,23 @@ where // id is stored for skipped session metric calculation self.last_signed_id = rounds.validator_set_id(); + let block_num = round.1; let commitment = Commitment { payload: round.0, - block_number: round.1, + block_number: block_num, validator_set_id: self.last_signed_id, }; let signed_commitment = SignedCommitment { commitment, signatures }; - metric_set!(self, beefy_round_concluded, round.1); + metric_set!(self, beefy_round_concluded, block_num); info!(target: "beefy", "🥩 Round #{} concluded, committed: {:?}.", round.1, signed_commitment); if self .backend .append_justification( - BlockId::Number(round.1), + BlockId::Number(block_num), ( BEEFY_ENGINE_ID, VersionedFinalityProof::V1(signed_commitment.clone()).encode(), @@ -356,11 +366,23 @@ where // conclude certain rounds multiple times. trace!(target: "beefy", "🥩 Failed to append justification: {:?}", signed_commitment); } + self.signed_commitment_sender + .notify(|| Ok::<_, ()>(signed_commitment)) + .expect("forwards closure result; the closure always returns Ok; qed."); + + self.best_beefy_block = Some(block_num); + if let Err(err) = self.client.hash(block_num).map(|h| { + if let Some(hash) = h { + self.beefy_best_block_sender + .notify(|| Ok::<_, ()>(hash)) + .expect("forwards closure result; the closure always returns Ok; qed."); + } + }) { + error!(target: "beefy", "🥩 Failed to get hash for block number {}; err: {:?}", + block_num, err); + } - self.signed_commitment_sender.notify(signed_commitment); - self.best_beefy_block = Some(round.1); - - metric_set!(self, beefy_best_block, round.1); + metric_set!(self, beefy_best_block, block_num); } } } diff --git a/client/finality-grandpa/rpc/src/lib.rs b/client/finality-grandpa/rpc/src/lib.rs index e509d435af4a..bde2e5612b2e 100644 --- a/client/finality-grandpa/rpc/src/lib.rs +++ b/client/finality-grandpa/rpc/src/lib.rs @@ -469,7 +469,7 @@ mod tests { // Notify with a header and justification let justification = create_justification(); - justification_sender.notify(|| Ok(justification.clone())).unwrap(); + justification_sender.notify(|| Ok::<_, ()>(justification.clone())).unwrap(); // Inspect what we received let recv = futures::executor::block_on(receiver.take(1).collect::>()); diff --git a/client/finality-grandpa/src/notification.rs b/client/finality-grandpa/src/notification.rs index 0d154fb3357e..1d6e25e55dc6 100644 --- a/client/finality-grandpa/src/notification.rs +++ b/client/finality-grandpa/src/notification.rs @@ -16,61 +16,15 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use parking_lot::Mutex; -use std::sync::Arc; +use sc_utils::notification::{NotificationSender, NotificationStream, TracingKeyStr}; -use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender}; -use sp_runtime::traits::Block as BlockT; - -use crate::{justification::GrandpaJustification, Error}; - -// Stream of justifications returned when subscribing. -type JustificationStream = TracingUnboundedReceiver>; - -// Sending endpoint for notifying about justifications. -type JustificationSender = TracingUnboundedSender>; - -// Collection of channel sending endpoints shared with the receiver side so they can register -// themselves. -type SharedJustificationSenders = Arc>>>; +use crate::justification::GrandpaJustification; /// The sending half of the Grandpa justification channel(s). /// /// Used to send notifications about justifications generated /// at the end of a Grandpa round. -#[derive(Clone)] -pub struct GrandpaJustificationSender { - subscribers: SharedJustificationSenders, -} - -impl GrandpaJustificationSender { - /// The `subscribers` should be shared with a corresponding - /// `GrandpaJustificationStream`. - fn new(subscribers: SharedJustificationSenders) -> Self { - Self { subscribers } - } - - /// Send out a notification to all subscribers that a new justification - /// is available for a block. - pub fn notify( - &self, - justification: impl FnOnce() -> Result, Error>, - ) -> Result<(), Error> { - let mut subscribers = self.subscribers.lock(); - - // do an initial prune on closed subscriptions - subscribers.retain(|n| !n.is_closed()); - - // if there's no subscribers we avoid creating - // the justification which is a costly operation - if !subscribers.is_empty() { - let justification = justification()?; - subscribers.retain(|n| n.unbounded_send(justification.clone()).is_ok()); - } - - Ok(()) - } -} +pub type GrandpaJustificationSender = NotificationSender>; /// The receiving half of the Grandpa justification channel. /// @@ -78,33 +32,12 @@ impl GrandpaJustificationSender { /// at the end of a Grandpa round. /// The `GrandpaJustificationStream` entity stores the `SharedJustificationSenders` /// so it can be used to add more subscriptions. -#[derive(Clone)] -pub struct GrandpaJustificationStream { - subscribers: SharedJustificationSenders, -} - -impl GrandpaJustificationStream { - /// Creates a new pair of receiver and sender of justification notifications. - pub fn channel() -> (GrandpaJustificationSender, Self) { - let subscribers = Arc::new(Mutex::new(vec![])); - let receiver = GrandpaJustificationStream::new(subscribers.clone()); - let sender = GrandpaJustificationSender::new(subscribers.clone()); - (sender, receiver) - } +pub type GrandpaJustificationStream = + NotificationStream, GrandpaJustificationsTracingKey>; - /// Create a new receiver of justification notifications. - /// - /// The `subscribers` should be shared with a corresponding - /// `GrandpaJustificationSender`. - fn new(subscribers: SharedJustificationSenders) -> Self { - Self { subscribers } - } - - /// Subscribe to a channel through which justifications are sent - /// at the end of each Grandpa voting round. - pub fn subscribe(&self) -> JustificationStream { - let (sender, receiver) = tracing_unbounded("mpsc_justification_notification_stream"); - self.subscribers.lock().push(sender); - receiver - } +/// Provides tracing key for GRANDPA justifications stream. +#[derive(Clone)] +pub struct GrandpaJustificationsTracingKey; +impl TracingKeyStr for GrandpaJustificationsTracingKey { + const TRACING_KEY: &'static str = "mpsc_grandpa_justification_notification_stream"; } diff --git a/client/utils/Cargo.toml b/client/utils/Cargo.toml index 827164b702c6..24075f932b50 100644 --- a/client/utils/Cargo.toml +++ b/client/utils/Cargo.toml @@ -12,9 +12,13 @@ readme = "README.md" [dependencies] futures = "0.3.9" lazy_static = "1.4.0" +parking_lot = "0.11" prometheus = { version = "0.13.0", default-features = false } futures-timer = "3.0.2" [features] default = ["metered"] metered = [] + +[dev-dependencies] +tokio-test = "0.4.2" diff --git a/client/utils/src/lib.rs b/client/utils/src/lib.rs index fab4365c8ed8..b3fb8400b12f 100644 --- a/client/utils/src/lib.rs +++ b/client/utils/src/lib.rs @@ -38,4 +38,5 @@ pub mod metrics; pub mod mpsc; +pub mod notification; pub mod status_sinks; diff --git a/client/utils/src/notification.rs b/client/utils/src/notification.rs new file mode 100644 index 000000000000..21d01c5f99fe --- /dev/null +++ b/client/utils/src/notification.rs @@ -0,0 +1,151 @@ +// This file is part of Substrate. + +// Copyright (C) 2021-2022 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 . + +//! Provides mpsc notification channel that can be instantiated +//! _after_ it's been shared to the consumer and producers entities. +//! +//! Useful when building RPC extensions where, at service definition time, we +//! don't know whether the specific interface where the RPC extension will be +//! exposed is safe or not and we want to lazily build the RPC extension +//! whenever we bind the service to an interface. +//! +//! See [`sc-service::builder::RpcExtensionBuilder`] for more details. + +use std::{marker::PhantomData, sync::Arc}; + +use crate::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender}; + +use parking_lot::Mutex; + +/// Collection of channel sending endpoints shared with the receiver side +/// so they can register themselves. +type SharedSenders = Arc>>>; + +/// Trait used to define the "tracing key" string used to tag +/// and identify the mpsc channels. +pub trait TracingKeyStr { + /// Const `str` representing the "tracing key" used to tag and identify + /// the mpsc channels owned by the object implemeting this trait. + const TRACING_KEY: &'static str; +} + +/// The sending half of the notifications channel(s). +/// +/// Used to send notifications from the BEEFY gadget side. +#[derive(Clone)] +pub struct NotificationSender { + subscribers: SharedSenders, +} + +impl NotificationSender { + /// The `subscribers` should be shared with a corresponding `NotificationStream`. + fn new(subscribers: SharedSenders) -> Self { + Self { subscribers } + } + + /// Send out a notification to all subscribers that a new payload is available for a + /// block. + pub fn notify( + &self, + payload: impl FnOnce() -> Result, + ) -> Result<(), Error> { + let mut subscribers = self.subscribers.lock(); + + // do an initial prune on closed subscriptions + subscribers.retain(|n| !n.is_closed()); + + if !subscribers.is_empty() { + let payload = payload()?; + subscribers.retain(|n| n.unbounded_send(payload.clone()).is_ok()); + } + + Ok(()) + } +} + +/// The receiving half of the notifications channel. +/// +/// The `NotificationStream` entity stores the `SharedSenders` so it can be +/// used to add more subscriptions. +#[derive(Clone)] +pub struct NotificationStream { + subscribers: SharedSenders, + _trace_key: PhantomData, +} + +impl NotificationStream { + /// Creates a new pair of receiver and sender of `Payload` notifications. + pub fn channel() -> (NotificationSender, Self) { + let subscribers = Arc::new(Mutex::new(vec![])); + let receiver = NotificationStream::new(subscribers.clone()); + let sender = NotificationSender::new(subscribers); + (sender, receiver) + } + + /// Create a new receiver of `Payload` notifications. + /// + /// The `subscribers` should be shared with a corresponding `NotificationSender`. + fn new(subscribers: SharedSenders) -> Self { + Self { subscribers, _trace_key: PhantomData } + } + + /// Subscribe to a channel through which the generic payload can be received. + pub fn subscribe(&self) -> TracingUnboundedReceiver { + let (sender, receiver) = tracing_unbounded(TK::TRACING_KEY); + self.subscribers.lock().push(sender); + receiver + } +} + +#[cfg(test)] +mod tests { + use super::*; + use futures::StreamExt; + + #[derive(Clone)] + pub struct DummyTracingKey; + impl TracingKeyStr for DummyTracingKey { + const TRACING_KEY: &'static str = "test_notification_stream"; + } + + type StringStream = NotificationStream; + + #[test] + fn notification_channel_simple() { + let (sender, stream) = StringStream::channel(); + + let test_payload = String::from("test payload"); + let closure_payload = test_payload.clone(); + + // Create a future to receive a single notification + // from the stream and verify its payload. + let future = stream.subscribe().take(1).for_each(move |payload| { + let test_payload = closure_payload.clone(); + async move { + assert_eq!(payload, test_payload); + } + }); + + // Send notification. + let r: std::result::Result<(), ()> = sender.notify(|| Ok(test_payload)); + r.unwrap(); + + // Run receiver future. + tokio_test::block_on(future); + } +} From c0f688d2c957d7a816b9abfad70d7d89a094996c Mon Sep 17 00:00:00 2001 From: Gavin Wood Date: Fri, 7 Jan 2022 19:33:52 +0000 Subject: [PATCH 361/695] Fix docs (#10606) --- frame/balances/src/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/frame/balances/src/lib.rs b/frame/balances/src/lib.rs index 86e3f2ec0598..5235dc97ccb4 100644 --- a/frame/balances/src/lib.rs +++ b/frame/balances/src/lib.rs @@ -250,7 +250,6 @@ pub mod pallet { /// Transfer some liquid free balance to another account. /// /// `transfer` will set the `FreeBalance` of the sender and receiver. - /// It will decrease the total issuance of the system by the `TransferFee`. /// If the sender's account is below the existential deposit as a result /// of the transfer, the account will be reaped. /// @@ -293,7 +292,7 @@ pub mod pallet { /// Set the balances of a given account. /// /// This will alter `FreeBalance` and `ReservedBalance` in storage. it will - /// also decrease the total issuance of the system (`TotalIssuance`). + /// also alter the total issuance of the system (`TotalIssuance`) appropriately. /// If the new free or reserved balance is below the existential deposit, /// it will reset the account nonce (`frame_system::AccountNonce`). /// From e0543096a82a8b48146bd7c48091ff0c857a0001 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Sat, 8 Jan 2022 13:19:23 +0100 Subject: [PATCH 362/695] Add additionally functionality to contracts storage interface (#10497) * Add new versions for storage access host functions * Improve docs --- frame/contracts/src/benchmarking/mod.rs | 177 +++- frame/contracts/src/exec.rs | 122 ++- frame/contracts/src/schedule.rs | 12 + frame/contracts/src/storage.rs | 39 +- frame/contracts/src/tests.rs | 9 +- frame/contracts/src/wasm/mod.rs | 314 +++++- frame/contracts/src/wasm/runtime.rs | 156 ++- frame/contracts/src/weights.rs | 1163 ++++++++++++----------- 8 files changed, 1392 insertions(+), 600 deletions(-) diff --git a/frame/contracts/src/benchmarking/mod.rs b/frame/contracts/src/benchmarking/mod.rs index 49344373f97d..a0f5ceb034f7 100644 --- a/frame/contracts/src/benchmarking/mod.rs +++ b/frame/contracts/src/benchmarking/mod.rs @@ -134,7 +134,7 @@ where fn store(&self, items: &Vec<(StorageKey, Vec)>) -> Result<(), &'static str> { let info = self.info()?; for item in items { - Storage::::write(&info.trie_id, &item.0, Some(item.1.clone()), None) + Storage::::write(&info.trie_id, &item.0, Some(item.1.clone()), None, false) .map_err(|_| "Failed to write storage to restoration dest")?; } >::insert(&self.account_id, info.clone()); @@ -784,10 +784,10 @@ benchmarks! { let code = WasmModule::::from(ModuleDefinition { memory: Some(ImportedMemory::max::()), imported_functions: vec![ImportedFunction { - module: "seal0", + module: "__unstable__", name: "seal_set_storage", params: vec![ValueType::I32, ValueType::I32, ValueType::I32], - return_type: None, + return_type: Some(ValueType::I32), }], data_segments: vec![ DataSegment { @@ -800,6 +800,7 @@ benchmarks! { Regular(Instruction::I32Const(0)), // value_ptr Regular(Instruction::I32Const(0)), // value_len Regular(Instruction::Call(0)), + Regular(Instruction::Drop), ])), .. Default::default() }); @@ -814,10 +815,10 @@ benchmarks! { let code = WasmModule::::from(ModuleDefinition { memory: Some(ImportedMemory::max::()), imported_functions: vec![ImportedFunction { - module: "seal0", + module: "__unstable__", name: "seal_set_storage", params: vec![ValueType::I32, ValueType::I32, ValueType::I32], - return_type: None, + return_type: Some(ValueType::I32), }], data_segments: vec![ DataSegment { @@ -830,6 +831,7 @@ benchmarks! { Instruction::I32Const(0), // value_ptr Instruction::I32Const((n * 1024) as i32), // value_len Instruction::Call(0), + Instruction::Drop, ])), .. Default::default() }); @@ -851,10 +853,10 @@ benchmarks! { let code = WasmModule::::from(ModuleDefinition { memory: Some(ImportedMemory::max::()), imported_functions: vec![ImportedFunction { - module: "seal0", + module: "__unstable__", name: "seal_clear_storage", params: vec![ValueType::I32], - return_type: None, + return_type: Some(ValueType::I32), }], data_segments: vec![ DataSegment { @@ -865,6 +867,7 @@ benchmarks! { call_body: Some(body::repeated_dyn(r * API_BENCHMARK_BATCH_SIZE, vec![ Counter(0, key_len as u32), Regular(Instruction::Call(0)), + Regular(Instruction::Drop), ])), .. Default::default() }); @@ -876,6 +879,7 @@ benchmarks! { key.as_slice().try_into().map_err(|e| "Key has wrong length")?, Some(vec![42; T::Schedule::get().limits.payload_len as usize]), None, + false, ) .map_err(|_| "Failed to write to storage during setup.")?; } @@ -906,6 +910,10 @@ benchmarks! { offset: 0, value: key_bytes, }, + DataSegment { + offset: key_bytes_len as u32, + value: T::Schedule::get().limits.payload_len.to_le_bytes().into(), + }, ], call_body: Some(body::repeated_dyn(r * API_BENCHMARK_BATCH_SIZE, vec![ Counter(0, key_len as u32), // key_ptr @@ -924,6 +932,54 @@ benchmarks! { key.as_slice().try_into().map_err(|e| "Key has wrong length")?, Some(vec![]), None, + false, + ) + .map_err(|_| "Failed to write to storage during setup.")?; + } + >::insert(&instance.account_id, info.clone()); + let origin = RawOrigin::Signed(instance.caller.clone()); + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + + // We make sure that all storage accesses are to unique keys. + #[skip_meta] + seal_contains_storage { + let r in 0 .. API_BENCHMARK_BATCHES; + let keys = (0 .. r * API_BENCHMARK_BATCH_SIZE) + .map(|n| T::Hashing::hash_of(&n).as_ref().to_vec()) + .collect::>(); + let key_len = sp_std::mem::size_of::<::Output>(); + let key_bytes = keys.iter().flatten().cloned().collect::>(); + let key_bytes_len = key_bytes.len(); + let code = WasmModule::::from(ModuleDefinition { + memory: Some(ImportedMemory::max::()), + imported_functions: vec![ImportedFunction { + module: "__unstable__", + name: "seal_contains_storage", + params: vec![ValueType::I32], + return_type: Some(ValueType::I32), + }], + data_segments: vec![ + DataSegment { + offset: 0, + value: key_bytes, + }, + ], + call_body: Some(body::repeated_dyn(r * API_BENCHMARK_BATCH_SIZE, vec![ + Counter(0, key_len as u32), // key_ptr + Regular(Instruction::Call(0)), + Regular(Instruction::Drop), + ])), + .. Default::default() + }); + let instance = Contract::::new(code, vec![])?; + let info = instance.info()?; + for key in keys { + Storage::::write( + &info.trie_id, + key.as_slice().try_into().map_err(|e| "Key has wrong length")?, + Some(vec![42; T::Schedule::get().limits.payload_len as usize]), + None, + false, ) .map_err(|_| "Failed to write to storage during setup.")?; } @@ -970,12 +1026,117 @@ benchmarks! { key.as_slice().try_into().map_err(|e| "Key has wrong length")?, Some(vec![42u8; (n * 1024) as usize]), None, + false, ) .map_err(|_| "Failed to write to storage during setup.")?; >::insert(&instance.account_id, info.clone()); let origin = RawOrigin::Signed(instance.caller.clone()); }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[skip_meta] + seal_take_storage { + let r in 0 .. API_BENCHMARK_BATCHES; + let keys = (0 .. r * API_BENCHMARK_BATCH_SIZE) + .map(|n| T::Hashing::hash_of(&n).as_ref().to_vec()) + .collect::>(); + let key_len = sp_std::mem::size_of::<::Output>(); + let key_bytes = keys.iter().flatten().cloned().collect::>(); + let key_bytes_len = key_bytes.len(); + let code = WasmModule::::from(ModuleDefinition { + memory: Some(ImportedMemory::max::()), + imported_functions: vec![ImportedFunction { + module: "__unstable__", + name: "seal_take_storage", + params: vec![ValueType::I32, ValueType::I32, ValueType::I32], + return_type: Some(ValueType::I32), + }], + data_segments: vec![ + DataSegment { + offset: 0, + value: key_bytes, + }, + DataSegment { + offset: key_bytes_len as u32, + value: T::Schedule::get().limits.payload_len.to_le_bytes().into(), + }, + ], + call_body: Some(body::repeated_dyn(r * API_BENCHMARK_BATCH_SIZE, vec![ + Counter(0, key_len as u32), // key_ptr + Regular(Instruction::I32Const((key_bytes_len + 4) as i32)), // out_ptr + Regular(Instruction::I32Const(key_bytes_len as i32)), // out_len_ptr + Regular(Instruction::Call(0)), + Regular(Instruction::Drop), + ])), + .. Default::default() + }); + let instance = Contract::::new(code, vec![])?; + let info = instance.info()?; + for key in keys { + Storage::::write( + &info.trie_id, + key.as_slice().try_into().map_err(|e| "Key has wrong length")?, + Some(vec![]), + None, + false, + ) + .map_err(|_| "Failed to write to storage during setup.")?; + } + >::insert(&instance.account_id, info.clone()); + let origin = RawOrigin::Signed(instance.caller.clone()); + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + + #[skip_meta] + seal_take_storage_per_kb { + let n in 0 .. T::Schedule::get().limits.payload_len / 1024; + let keys = (0 .. API_BENCHMARK_BATCH_SIZE) + .map(|n| T::Hashing::hash_of(&n).as_ref().to_vec()) + .collect::>(); + let key_len = sp_std::mem::size_of::<::Output>(); + let key_bytes = keys.iter().flatten().cloned().collect::>(); + let key_bytes_len = key_bytes.len(); + let code = WasmModule::::from(ModuleDefinition { + memory: Some(ImportedMemory::max::()), + imported_functions: vec![ImportedFunction { + module: "__unstable__", + name: "seal_take_storage", + params: vec![ValueType::I32, ValueType::I32, ValueType::I32], + return_type: Some(ValueType::I32), + }], + data_segments: vec![ + DataSegment { + offset: 0, + value: key_bytes, + }, + DataSegment { + offset: key_bytes_len as u32, + value: T::Schedule::get().limits.payload_len.to_le_bytes().into(), + }, + ], + call_body: Some(body::repeated_dyn(API_BENCHMARK_BATCH_SIZE, vec![ + Counter(0, key_len as u32), // key_ptr + Regular(Instruction::I32Const((key_bytes_len + 4) as i32)), // out_ptr + Regular(Instruction::I32Const(key_bytes_len as i32)), // out_len_ptr + Regular(Instruction::Call(0)), + Regular(Instruction::Drop), + ])), + .. Default::default() + }); + let instance = Contract::::new(code, vec![])?; + let info = instance.info()?; + for key in keys { + Storage::::write( + &info.trie_id, + key.as_slice().try_into().map_err(|e| "Key has wrong length")?, + Some(vec![42u8; (n * 1024) as usize]), + None, + false, + ) + .map_err(|_| "Failed to write to storage during setup.")?; + } + >::insert(&instance.account_id, info.clone()); + let origin = RawOrigin::Signed(instance.caller.clone()); + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + // We transfer to unique accounts. seal_transfer { let r in 0 .. API_BENCHMARK_BATCHES; @@ -2285,7 +2446,7 @@ benchmarks! { // configured `Schedule` during benchmark development. // It can be outputed using the following command: // cargo run --manifest-path=bin/node/cli/Cargo.toml --release \ - // --features runtime-benchmarks -- benchmark --dev --execution=native \ + // --features runtime-benchmarks -- benchmark --extra --dev --execution=native \ // -p pallet_contracts -e print_schedule --no-median-slopes --no-min-squares #[extra] print_schedule { diff --git a/frame/contracts/src/exec.rs b/frame/contracts/src/exec.rs index 97f301d162af..679a6adde922 100644 --- a/frame/contracts/src/exec.rs +++ b/frame/contracts/src/exec.rs @@ -17,7 +17,7 @@ use crate::{ gas::GasMeter, - storage::{self, Storage}, + storage::{self, Storage, WriteOutcome}, AccountCounter, BalanceOf, CodeHash, Config, ContractInfo, ContractInfoOf, Error, Event, Pallet as Contracts, Schedule, }; @@ -140,9 +140,20 @@ pub trait Ext: sealing::Sealed { /// was deleted. fn get_storage(&mut self, key: &StorageKey) -> Option>; + /// Returns true iff some storage entry exists under the supplied `key` + /// + /// Returns `false` if the `key` wasn't previously set by `set_storage` or + /// was deleted. + fn contains_storage(&mut self, key: &StorageKey) -> bool; + /// Sets the storage entry by the given key to the specified value. If `value` is `None` then /// the storage entry is deleted. - fn set_storage(&mut self, key: StorageKey, value: Option>) -> DispatchResult; + fn set_storage( + &mut self, + key: StorageKey, + value: Option>, + take_old: bool, + ) -> Result; /// Returns a reference to the account id of the caller. fn caller(&self) -> &AccountIdOf; @@ -985,13 +996,23 @@ where Storage::::read(&self.top_frame_mut().contract_info().trie_id, key) } - fn set_storage(&mut self, key: StorageKey, value: Option>) -> DispatchResult { + fn contains_storage(&mut self, key: &StorageKey) -> bool { + Storage::::contains(&self.top_frame_mut().contract_info().trie_id, key) + } + + fn set_storage( + &mut self, + key: StorageKey, + value: Option>, + take_old: bool, + ) -> Result { let frame = self.top_frame_mut(); Storage::::write( &frame.contract_info.get(&frame.account_id).trie_id, &key, value, Some(&mut frame.nested_storage), + take_old, ) } @@ -2349,4 +2370,99 @@ mod tests { assert_eq!(>::get(), 4); }); } + + #[test] + fn set_storage_works() { + let code_hash = MockLoader::insert(Call, |ctx, _| { + // Write + assert_eq!( + ctx.ext.set_storage([1; 32], Some(vec![1, 2, 3]), false), + Ok(WriteOutcome::New) + ); + assert_eq!( + ctx.ext.set_storage([2; 32], Some(vec![4, 5, 6]), true), + Ok(WriteOutcome::New) + ); + assert_eq!(ctx.ext.set_storage([3; 32], None, false), Ok(WriteOutcome::New)); + assert_eq!(ctx.ext.set_storage([4; 32], None, true), Ok(WriteOutcome::New)); + assert_eq!(ctx.ext.set_storage([5; 32], Some(vec![]), false), Ok(WriteOutcome::New)); + assert_eq!(ctx.ext.set_storage([6; 32], Some(vec![]), true), Ok(WriteOutcome::New)); + + // Overwrite + assert_eq!( + ctx.ext.set_storage([1; 32], Some(vec![42]), false), + Ok(WriteOutcome::Overwritten(3)) + ); + assert_eq!( + ctx.ext.set_storage([2; 32], Some(vec![48]), true), + Ok(WriteOutcome::Taken(vec![4, 5, 6])) + ); + assert_eq!(ctx.ext.set_storage([3; 32], None, false), Ok(WriteOutcome::New)); + assert_eq!(ctx.ext.set_storage([4; 32], None, true), Ok(WriteOutcome::New)); + assert_eq!( + ctx.ext.set_storage([5; 32], Some(vec![]), false), + Ok(WriteOutcome::Overwritten(0)) + ); + assert_eq!( + ctx.ext.set_storage([6; 32], Some(vec![]), true), + Ok(WriteOutcome::Taken(vec![])) + ); + + exec_success() + }); + + ExtBuilder::default().build().execute_with(|| { + let min_balance = ::Currency::minimum_balance(); + let schedule = ::Schedule::get(); + let mut gas_meter = GasMeter::::new(GAS_LIMIT); + set_balance(&ALICE, min_balance * 1000); + place_contract(&BOB, code_hash); + let mut storage_meter = storage::meter::Meter::new(&ALICE, None, 0).unwrap(); + assert_ok!(MockStack::run_call( + ALICE, + BOB, + &mut gas_meter, + &mut storage_meter, + &schedule, + 0, + vec![], + None, + )); + }); + } + + #[test] + fn contains_storage_works() { + let code_hash = MockLoader::insert(Call, |ctx, _| { + assert_eq!( + ctx.ext.set_storage([1; 32], Some(vec![1, 2, 3]), false), + Ok(WriteOutcome::New) + ); + assert_eq!(ctx.ext.set_storage([2; 32], Some(vec![]), false), Ok(WriteOutcome::New)); + assert_eq!(ctx.ext.contains_storage(&[1; 32]), true); + assert_eq!(ctx.ext.contains_storage(&[1; 32]), true); + assert_eq!(ctx.ext.contains_storage(&[3; 32]), false); + + exec_success() + }); + + ExtBuilder::default().build().execute_with(|| { + let min_balance = ::Currency::minimum_balance(); + let schedule = ::Schedule::get(); + let mut gas_meter = GasMeter::::new(GAS_LIMIT); + set_balance(&ALICE, min_balance * 1000); + place_contract(&BOB, code_hash); + let mut storage_meter = storage::meter::Meter::new(&ALICE, None, 0).unwrap(); + assert_ok!(MockStack::run_call( + ALICE, + BOB, + &mut gas_meter, + &mut storage_meter, + &schedule, + 0, + vec![], + None, + )); + }); + } } diff --git a/frame/contracts/src/schedule.rs b/frame/contracts/src/schedule.rs index dd066bfbe41e..f3bfaea24277 100644 --- a/frame/contracts/src/schedule.rs +++ b/frame/contracts/src/schedule.rs @@ -322,12 +322,21 @@ pub struct HostFnWeights { /// Weight of calling `seal_clear_storage`. pub clear_storage: Weight, + /// Weight of calling `seal_contains_storage`. + pub contains_storage: Weight, + /// Weight of calling `seal_get_storage`. pub get_storage: Weight, /// Weight per byte of an item received via `seal_get_storage`. pub get_storage_per_byte: Weight, + /// Weight of calling `seal_take_storage`. + pub take_storage: Weight, + + /// Weight per byte of an item received via `seal_take_storage`. + pub take_storage_per_byte: Weight, + /// Weight of calling `seal_transfer`. pub transfer: Weight, @@ -579,8 +588,11 @@ impl Default for HostFnWeights { set_storage: cost_batched!(seal_set_storage), set_storage_per_byte: cost_byte_batched!(seal_set_storage_per_kb), clear_storage: cost_batched!(seal_clear_storage), + contains_storage: cost_batched!(seal_contains_storage), get_storage: cost_batched!(seal_get_storage), get_storage_per_byte: cost_byte_batched!(seal_get_storage_per_kb), + take_storage: cost_batched!(seal_take_storage), + take_storage_per_byte: cost_byte_batched!(seal_take_storage_per_kb), transfer: cost_batched!(seal_transfer), call: cost_batched!(seal_call), call_transfer_surcharge: cost_batched_args!( diff --git a/frame/contracts/src/storage.rs b/frame/contracts/src/storage.rs index 7b0671da1058..b84cd1d2538e 100644 --- a/frame/contracts/src/storage.rs +++ b/frame/contracts/src/storage.rs @@ -72,6 +72,21 @@ pub struct DeletedContract { pub(crate) trie_id: TrieId, } +/// Information about what happended to the pre-existing value when calling [`Storage::write`]. +#[cfg_attr(test, derive(Debug, PartialEq))] +pub enum WriteOutcome { + /// No value existed at the specified key. + New, + /// A value of the returned length was overwritten. + Overwritten(u32), + /// The returned value was taken out of storage before being overwritten. + /// + /// This is only returned when specifically requested because it causes additional work + /// depending on the size of the pre-existing value. When not requested [`Self::Overwritten`] + /// is returned instead. + Taken(Vec), +} + pub struct Storage(PhantomData); impl Storage @@ -87,9 +102,15 @@ where child::get_raw(&child_trie_info(trie_id), &blake2_256(key)) } + /// Returns `true` iff the `key` exists in storage. + pub fn contains(trie_id: &TrieId, key: &StorageKey) -> bool { + child::exists(&child_trie_info(trie_id), &blake2_256(key)) + } + /// Update a storage entry into a contract's kv storage. /// - /// If the `new_value` is `None` then the kv pair is removed. + /// If the `new_value` is `None` then the kv pair is removed. If `take` is true + /// a [`WriteOutcome::Taken`] is returned instead of a [`WriteOutcome::Overwritten`]. /// /// This function also records how much storage was created or removed if a `storage_meter` /// is supplied. It should only be absent for testing or benchmarking code. @@ -98,13 +119,19 @@ where key: &StorageKey, new_value: Option>, storage_meter: Option<&mut meter::NestedMeter>, - ) -> DispatchResult { + take: bool, + ) -> Result { let hashed_key = blake2_256(key); let child_trie_info = &child_trie_info(trie_id); + let (old_len, old_value) = if take { + let val = child::get_raw(&child_trie_info, &hashed_key); + (val.as_ref().map(|v| v.len() as u32), val) + } else { + (child::len(&child_trie_info, &hashed_key), None) + }; if let Some(storage_meter) = storage_meter { let mut diff = meter::Diff::default(); - let old_len = child::len(&child_trie_info, &hashed_key); match (old_len, new_value.as_ref().map(|v| v.len() as u32)) { (Some(old_len), Some(new_len)) => if new_len > old_len { @@ -130,7 +157,11 @@ where None => child::kill(&child_trie_info, &hashed_key), } - Ok(()) + Ok(match (old_len, old_value) { + (None, _) => WriteOutcome::New, + (Some(old_len), None) => WriteOutcome::Overwritten(old_len), + (Some(_), Some(old_value)) => WriteOutcome::Taken(old_value), + }) } /// Creates a new contract descriptor in the storage with the given code hash at the given diff --git a/frame/contracts/src/tests.rs b/frame/contracts/src/tests.rs index 4cbc37c57ff2..17e8f746be1f 100644 --- a/frame/contracts/src/tests.rs +++ b/frame/contracts/src/tests.rs @@ -1545,7 +1545,8 @@ fn lazy_removal_partial_remove_works() { // Put value into the contracts child trie for val in &vals { - Storage::::write(&info.trie_id, &val.0, Some(val.2.clone()), None).unwrap(); + Storage::::write(&info.trie_id, &val.0, Some(val.2.clone()), None, false) + .unwrap(); } >::insert(&addr, info.clone()); @@ -1629,7 +1630,8 @@ fn lazy_removal_does_no_run_on_full_block() { // Put value into the contracts child trie for val in &vals { - Storage::::write(&info.trie_id, &val.0, Some(val.2.clone()), None).unwrap(); + Storage::::write(&info.trie_id, &val.0, Some(val.2.clone()), None, false) + .unwrap(); } >::insert(&addr, info.clone()); @@ -1712,7 +1714,8 @@ fn lazy_removal_does_not_use_all_weight() { // Put value into the contracts child trie for val in &vals { - Storage::::write(&info.trie_id, &val.0, Some(val.2.clone()), None).unwrap(); + Storage::::write(&info.trie_id, &val.0, Some(val.2.clone()), None, false) + .unwrap(); } >::insert(&addr, info.clone()); diff --git a/frame/contracts/src/wasm/mod.rs b/frame/contracts/src/wasm/mod.rs index ee7f557d34f0..f63361a03930 100644 --- a/frame/contracts/src/wasm/mod.rs +++ b/frame/contracts/src/wasm/mod.rs @@ -257,21 +257,22 @@ mod tests { AccountIdOf, BlockNumberOf, ErrorOrigin, ExecError, Executable, Ext, SeedOf, StorageKey, }, gas::GasMeter, + storage::WriteOutcome, tests::{Call, Test, ALICE, BOB}, BalanceOf, CodeHash, Error, Pallet as Contracts, }; use assert_matches::assert_matches; - use frame_support::{ - assert_ok, - dispatch::{DispatchResult, DispatchResultWithPostInfo}, - weights::Weight, - }; + use frame_support::{assert_ok, dispatch::DispatchResultWithPostInfo, weights::Weight}; use hex_literal::hex; use pallet_contracts_primitives::{ExecReturnValue, ReturnFlags}; use pretty_assertions::assert_eq; use sp_core::{Bytes, H256}; use sp_runtime::DispatchError; - use std::{borrow::BorrowMut, cell::RefCell, collections::HashMap}; + use std::{ + borrow::BorrowMut, + cell::RefCell, + collections::hash_map::{Entry, HashMap}, + }; #[derive(Debug, PartialEq, Eq)] struct InstantiateEntry { @@ -384,9 +385,26 @@ mod tests { fn get_storage(&mut self, key: &StorageKey) -> Option> { self.storage.get(key).cloned() } - fn set_storage(&mut self, key: StorageKey, value: Option>) -> DispatchResult { - *self.storage.entry(key).or_insert(Vec::new()) = value.unwrap_or(Vec::new()); - Ok(()) + fn contains_storage(&mut self, key: &StorageKey) -> bool { + self.storage.contains_key(key) + } + fn set_storage( + &mut self, + key: StorageKey, + value: Option>, + take_old: bool, + ) -> Result { + let entry = self.storage.entry(key); + let result = match (entry, take_old) { + (Entry::Vacant(_), _) => WriteOutcome::New, + (Entry::Occupied(entry), false) => + WriteOutcome::Overwritten(entry.remove().len() as u32), + (Entry::Occupied(entry), true) => WriteOutcome::Taken(entry.remove()), + }; + if let Some(value) = value { + self.storage.insert(key, value); + } + Ok(result) } fn caller(&self) -> &AccountIdOf { &ALICE @@ -932,8 +950,8 @@ mod tests { "\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11" ) - ;; [32, 36) buffer size = 128 bytes - (data (i32.const 32) "\80") + ;; [32, 36) buffer size = 4k in little endian + (data (i32.const 32) "\00\10") ;; [36; inf) buffer where the result is copied @@ -1957,4 +1975,278 @@ mod tests { ); assert_eq!(*ext.runtime_calls.borrow(), vec![]); } + + #[test] + #[cfg(feature = "unstable-interface")] + fn set_storage_works() { + const CODE: &str = r#" +(module + (import "seal0" "seal_input" (func $seal_input (param i32 i32))) + (import "seal0" "seal_return" (func $seal_return (param i32 i32 i32))) + (import "__unstable__" "seal_set_storage" (func $seal_set_storage (param i32 i32 i32) (result i32))) + (import "env" "memory" (memory 1 1)) + + ;; 0x1000 = 4k in little endian + ;; size of input buffer + (data (i32.const 0) "\00\10") + + (func (export "call") + ;; Receive (key ++ value_to_write) + (call $seal_input + (i32.const 4) ;; Pointer to the input buffer + (i32.const 0) ;; Size of the length buffer + ) + ;; Store the passed value to the passed key and store result to memory + (i32.store (i32.const 0) + (call $seal_set_storage + (i32.const 4) ;; key_ptr + (i32.const 36) ;; value_ptr + (i32.sub ;; value_len (input_size - key_size) + (i32.load (i32.const 0)) + (i32.const 32) + ) + ) + ) + (call $seal_return + (i32.const 0) ;; flags + (i32.const 0) ;; returned value + (i32.const 4) ;; length of returned value + ) + ) + + (func (export "deploy")) +) +"#; + + let mut ext = MockExt::default(); + + // value did not exist before -> sentinel returned + let input = ([1u8; 32], [42u8, 48]).encode(); + let result = execute(CODE, input, &mut ext).unwrap(); + assert_eq!(u32::from_le_bytes(result.data.0.try_into().unwrap()), u32::MAX); + assert_eq!(ext.storage.get(&[1u8; 32]).unwrap(), &[42u8, 48]); + + // value do exist -> length of old value returned + let input = ([1u8; 32], [0u8; 0]).encode(); + let result = execute(CODE, input, &mut ext).unwrap(); + assert_eq!(u32::from_le_bytes(result.data.0.try_into().unwrap()), 2); + assert_eq!(ext.storage.get(&[1u8; 32]).unwrap(), &[0u8; 0]); + + // value do exist -> length of old value returned (test for zero sized val) + let input = ([1u8; 32], [99u8]).encode(); + let result = execute(CODE, input, &mut ext).unwrap(); + assert_eq!(u32::from_le_bytes(result.data.0.try_into().unwrap()), 0); + assert_eq!(ext.storage.get(&[1u8; 32]).unwrap(), &[99u8]); + } + + #[test] + #[cfg(feature = "unstable-interface")] + fn clear_storage_works() { + const CODE: &str = r#" +(module + (import "seal0" "seal_input" (func $seal_input (param i32 i32))) + (import "seal0" "seal_return" (func $seal_return (param i32 i32 i32))) + (import "__unstable__" "seal_clear_storage" (func $seal_clear_storage (param i32) (result i32))) + (import "env" "memory" (memory 1 1)) + + ;; 0x1000 = 4k in little endian + ;; size of input buffer + (data (i32.const 0) "\00\10") + + (func (export "call") + ;; Receive key + (call $seal_input + (i32.const 4) ;; Pointer to the input buffer + (i32.const 0) ;; Size of the length buffer + ) + ;; Store the passed value to the passed key and store result to memory + (i32.store (i32.const 0) + (call $seal_clear_storage + (i32.const 4) ;; key_ptr + ) + ) + (call $seal_return + (i32.const 0) ;; flags + (i32.const 0) ;; returned value + (i32.const 4) ;; length of returned value + ) + ) + + (func (export "deploy")) +) +"#; + + let mut ext = MockExt::default(); + + ext.storage.insert([1u8; 32], vec![42u8]); + ext.storage.insert([2u8; 32], vec![]); + + // value does not exist -> sentinel returned + let result = execute(CODE, [3u8; 32].encode(), &mut ext).unwrap(); + assert_eq!(u32::from_le_bytes(result.data.0.try_into().unwrap()), u32::MAX); + assert_eq!(ext.storage.get(&[3u8; 32]), None); + + // value did exist -> length returned + let result = execute(CODE, [1u8; 32].encode(), &mut ext).unwrap(); + assert_eq!(u32::from_le_bytes(result.data.0.try_into().unwrap()), 1); + assert_eq!(ext.storage.get(&[1u8; 32]), None); + + // value did exist -> length returned (test for 0 sized) + let result = execute(CODE, [2u8; 32].encode(), &mut ext).unwrap(); + assert_eq!(u32::from_le_bytes(result.data.0.try_into().unwrap()), 0); + assert_eq!(ext.storage.get(&[2u8; 32]), None); + } + + #[test] + #[cfg(feature = "unstable-interface")] + fn take_storage_works() { + const CODE: &str = r#" +(module + (import "seal0" "seal_return" (func $seal_return (param i32 i32 i32))) + (import "seal0" "seal_input" (func $seal_input (param i32 i32))) + (import "__unstable__" "seal_take_storage" (func $seal_take_storage (param i32 i32 i32) (result i32))) + (import "env" "memory" (memory 1 1)) + + ;; [0, 32) size of input buffer (32 byte as we copy the key here) + (data (i32.const 0) "\20") + + ;; [32, 64) size of output buffer + ;; 4k in little endian + (data (i32.const 32) "\00\10") + + ;; [64, 96) input buffer + + ;; [96, inf) output buffer + + (func (export "call") + ;; Receive key + (call $seal_input + (i32.const 64) ;; Pointer to the input buffer + (i32.const 0) ;; Size of the length buffer + ) + + ;; Load a storage value and result of this call into the output buffer + (i32.store (i32.const 96) + (call $seal_take_storage + (i32.const 64) ;; The pointer to the storage key to fetch + (i32.const 100) ;; Pointer to the output buffer + (i32.const 32) ;; Pointer to the size of the buffer + ) + ) + + ;; Return the contents of the buffer + (call $seal_return + (i32.const 0) ;; flags + (i32.const 96) ;; output buffer ptr + (i32.add ;; length: storage size + 4 (retval) + (i32.load (i32.const 32)) + (i32.const 4) + ) + ) + ) + + (func (export "deploy")) +) +"#; + + let mut ext = MockExt::default(); + + ext.storage.insert([1u8; 32], vec![42u8]); + ext.storage.insert([2u8; 32], vec![]); + + // value does not exist -> error returned + let result = execute(CODE, [3u8; 32].encode(), &mut ext).unwrap(); + assert_eq!( + u32::from_le_bytes(result.data.0[0..4].try_into().unwrap()), + ReturnCode::KeyNotFound as u32 + ); + + // value did exist -> value returned + let result = execute(CODE, [1u8; 32].encode(), &mut ext).unwrap(); + assert_eq!( + u32::from_le_bytes(result.data.0[0..4].try_into().unwrap()), + ReturnCode::Success as u32 + ); + assert_eq!(ext.storage.get(&[1u8; 32]), None); + assert_eq!(&result.data.0[4..], &[42u8]); + + // value did exist -> length returned (test for 0 sized) + let result = execute(CODE, [2u8; 32].encode(), &mut ext).unwrap(); + assert_eq!( + u32::from_le_bytes(result.data.0[0..4].try_into().unwrap()), + ReturnCode::Success as u32 + ); + assert_eq!(ext.storage.get(&[2u8; 32]), None); + assert_eq!(&result.data.0[4..], &[0u8; 0]); + } + + #[test] + #[cfg(feature = "unstable-interface")] + fn contains_storage_works() { + const CODE: &str = r#" +(module + (import "seal0" "seal_return" (func $seal_return (param i32 i32 i32))) + (import "seal0" "seal_input" (func $seal_input (param i32 i32))) + (import "__unstable__" "seal_contains_storage" (func $seal_contains_storage (param i32) (result i32))) + (import "env" "memory" (memory 1 1)) + + ;; [0, 4) size of input buffer (32 byte as we copy the key here) + (data (i32.const 0) "\20") + + ;; [4, 36) input buffer + + ;; [36, inf) output buffer + + (func (export "call") + ;; Receive key + (call $seal_input + (i32.const 4) ;; Pointer to the input buffer + (i32.const 0) ;; Size of the length buffer + ) + + ;; Load the return value into the output buffer + (i32.store (i32.const 36) + (call $seal_contains_storage + (i32.const 4) ;; The pointer to the storage key to fetch + ) + ) + + ;; Return the contents of the buffer + (call $seal_return + (i32.const 0) ;; flags + (i32.const 36) ;; output buffer ptr + (i32.const 4) ;; result is integer (4 bytes) + ) + ) + + (func (export "deploy")) +) +"#; + + let mut ext = MockExt::default(); + + ext.storage.insert([1u8; 32], vec![42u8]); + ext.storage.insert([2u8; 32], vec![]); + + // value does not exist -> error returned + let result = execute(CODE, [3u8; 32].encode(), &mut ext).unwrap(); + assert_eq!( + u32::from_le_bytes(result.data.0.try_into().unwrap()), + ReturnCode::KeyNotFound as u32 + ); + + // value did exist -> success + let result = execute(CODE, [1u8; 32].encode(), &mut ext).unwrap(); + assert_eq!( + u32::from_le_bytes(result.data.0.try_into().unwrap()), + ReturnCode::Success as u32 + ); + + // value did exist -> success (zero sized type) + let result = execute(CODE, [2u8; 32].encode(), &mut ext).unwrap(); + assert_eq!( + u32::from_le_bytes(result.data.0.try_into().unwrap()), + ReturnCode::Success as u32 + ); + } } diff --git a/frame/contracts/src/wasm/runtime.rs b/frame/contracts/src/wasm/runtime.rs index 7c9e19f6ef78..8b07329e5db4 100644 --- a/frame/contracts/src/wasm/runtime.rs +++ b/frame/contracts/src/wasm/runtime.rs @@ -21,6 +21,7 @@ use crate::{ exec::{ExecError, ExecResult, Ext, StorageKey, TopicOf}, gas::{ChargedAmount, Token}, schedule::HostFnWeights, + storage::WriteOutcome, wasm::env_def::ConvertibleToWasm, BalanceOf, CodeHash, Config, Error, }; @@ -172,10 +173,19 @@ pub enum RuntimeCosts { SetStorage(u32), /// Weight of calling `seal_clear_storage`. ClearStorage, + /// Weight of calling `seal_contains_storage`. + #[cfg(feature = "unstable-interface")] + ContainsStorage, /// Weight of calling `seal_get_storage` without output weight. GetStorageBase, /// Weight of an item received via `seal_get_storage` for the given size. GetStorageCopyOut(u32), + /// Weight of calling `seal_take_storage` without output weight. + #[cfg(feature = "unstable-interface")] + TakeStorageBase, + /// Weight of an item received via `seal_take_storage` for the given size. + #[cfg(feature = "unstable-interface")] + TakeStorageCopyOut(u32), /// Weight of calling `seal_transfer`. Transfer, /// Weight of calling `seal_call` for the given input size. @@ -242,8 +252,14 @@ impl RuntimeCosts { SetStorage(len) => s.set_storage.saturating_add(s.set_storage_per_byte.saturating_mul(len.into())), ClearStorage => s.clear_storage, + #[cfg(feature = "unstable-interface")] + ContainsStorage => s.contains_storage, GetStorageBase => s.get_storage, GetStorageCopyOut(len) => s.get_storage_per_byte.saturating_mul(len.into()), + #[cfg(feature = "unstable-interface")] + TakeStorageBase => s.take_storage, + #[cfg(feature = "unstable-interface")] + TakeStorageCopyOut(len) => s.take_storage_per_byte.saturating_mul(len.into()), Transfer => s.transfer, CallBase(len) => s.call.saturating_add(s.call_per_input_byte.saturating_mul(len.into())), @@ -632,6 +648,50 @@ where } } + /// Extracts the size of the overwritten value or `u32::MAX` if there + /// was no value in storage. + /// + /// # Note + /// + /// We cannot use `0` as sentinel value because there could be a zero sized + /// storage entry which is different from a non existing one. + fn overwritten_len(outcome: WriteOutcome) -> u32 { + match outcome { + WriteOutcome::New => u32::MAX, + WriteOutcome::Overwritten(len) => len, + WriteOutcome::Taken(value) => value.len() as u32, + } + } + + fn set_storage( + &mut self, + key_ptr: u32, + value_ptr: u32, + value_len: u32, + ) -> Result { + self.charge_gas(RuntimeCosts::SetStorage(value_len))?; + if value_len > self.ext.max_value_size() { + Err(Error::::ValueTooLarge)?; + } + let mut key: StorageKey = [0; 32]; + self.read_sandbox_memory_into_buf(key_ptr, &mut key)?; + let value = Some(self.read_sandbox_memory(value_ptr, value_len)?); + self.ext + .set_storage(key, value, false) + .map(Self::overwritten_len) + .map_err(Into::into) + } + + fn clear_storage(&mut self, key_ptr: u32) -> Result { + self.charge_gas(RuntimeCosts::ClearStorage)?; + let mut key: StorageKey = [0; 32]; + self.read_sandbox_memory_into_buf(key_ptr, &mut key)?; + self.ext + .set_storage(key, None, false) + .map(Self::overwritten_len) + .map_err(Into::into) + } + fn call( &mut self, flags: CallFlags, @@ -745,10 +805,18 @@ define_env!(Env, , Ok(()) }, + // Set the value at the given key in the contract storage. + // + // Equivalent to the newer version of `seal_set_storage` with the exception of the return + // type. Still a valid thing to call when not interested in the return value. + [seal0] seal_set_storage(ctx, key_ptr: u32, value_ptr: u32, value_len: u32) => { + ctx.set_storage(key_ptr, value_ptr, value_len).map(|_| ()) + }, + // Set the value at the given key in the contract storage. // // The value length must not exceed the maximum defined by the contracts module parameters. - // Storing an empty value is disallowed. + // Specifying a `value_len` of zero will store an empty value. // // # Parameters // @@ -756,19 +824,20 @@ define_env!(Env, , // - `value_ptr`: pointer into the linear memory where the value to set is placed. // - `value_len`: the length of the value in bytes. // - // # Traps + // # Return Value // - // - If value length exceeds the configured maximum value length of a storage entry. - // - Upon trying to set an empty storage entry (value length is 0). - [seal0] seal_set_storage(ctx, key_ptr: u32, value_ptr: u32, value_len: u32) => { - ctx.charge_gas(RuntimeCosts::SetStorage(value_len))?; - if value_len > ctx.ext.max_value_size() { - Err(Error::::ValueTooLarge)?; - } - let mut key: StorageKey = [0; 32]; - ctx.read_sandbox_memory_into_buf(key_ptr, &mut key)?; - let value = Some(ctx.read_sandbox_memory(value_ptr, value_len)?); - ctx.ext.set_storage(key, value).map_err(Into::into) + // Returns the size of the pre-existing value at the specified key if any. Otherwise + // `u32::MAX` is returned as a sentinel value. + [__unstable__] seal_set_storage(ctx, key_ptr: u32, value_ptr: u32, value_len: u32) -> u32 => { + ctx.set_storage(key_ptr, value_ptr, value_len) + }, + + // Clear the value at the given key in the contract storage. + // + // Equivalent to the newer version of `seal_clear_storage` with the exception of the return + // type. Still a valid thing to call when not interested in the return value. + [seal0] seal_clear_storage(ctx, key_ptr: u32) => { + ctx.clear_storage(key_ptr).map(|_| ()).map_err(Into::into) }, // Clear the value at the given key in the contract storage. @@ -776,11 +845,13 @@ define_env!(Env, , // # Parameters // // - `key_ptr`: pointer into the linear memory where the location to clear the value is placed. - [seal0] seal_clear_storage(ctx, key_ptr: u32) => { - ctx.charge_gas(RuntimeCosts::ClearStorage)?; - let mut key: StorageKey = [0; 32]; - ctx.read_sandbox_memory_into_buf(key_ptr, &mut key)?; - ctx.ext.set_storage(key, None).map_err(Into::into) + // + // # Return Value + // + // Returns the size of the pre-existing value at the specified key if any. Otherwise + // `u32::MAX` is returned as a sentinel value. + [__unstable__] seal_clear_storage(ctx, key_ptr: u32) -> u32 => { + ctx.clear_storage(key_ptr).map_err(Into::into) }, // Retrieve the value under the given key from storage. @@ -809,6 +880,55 @@ define_env!(Env, , } }, + // Checks whether there is a value stored under the given key. + // + // Returns `ReturnCode::Success` if there is a key in storage. Otherwise an error + // is returned. + // + // # Parameters + // + // - `key_ptr`: pointer into the linear memory where the key of the requested value is placed. + // + // # Errors + // + // `ReturnCode::KeyNotFound` + [__unstable__] seal_contains_storage(ctx, key_ptr: u32) -> ReturnCode => { + ctx.charge_gas(RuntimeCosts::ContainsStorage)?; + let mut key: StorageKey = [0; 32]; + ctx.read_sandbox_memory_into_buf(key_ptr, &mut key)?; + if ctx.ext.contains_storage(&key) { + Ok(ReturnCode::Success) + } else { + Ok(ReturnCode::KeyNotFound) + } + }, + + // Retrieve and remove the value under the given key from storage. + // + // # Parameters + // + // - `key_ptr`: pointer into the linear memory where the key of the requested value is placed. + // - `out_ptr`: pointer to the linear memory where the value is written to. + // - `out_len_ptr`: in-out pointer into linear memory where the buffer length + // is read from and the value length is written to. + // + // # Errors + // + // `ReturnCode::KeyNotFound` + [__unstable__] seal_take_storage(ctx, key_ptr: u32, out_ptr: u32, out_len_ptr: u32) -> ReturnCode => { + ctx.charge_gas(RuntimeCosts::TakeStorageBase)?; + let mut key: StorageKey = [0; 32]; + ctx.read_sandbox_memory_into_buf(key_ptr, &mut key)?; + if let WriteOutcome::Taken(value) = ctx.ext.set_storage(key, None, true)? { + ctx.write_sandbox_output(out_ptr, out_len_ptr, &value, false, |len| { + Some(RuntimeCosts::TakeStorageCopyOut(len)) + })?; + Ok(ReturnCode::Success) + } else { + Ok(ReturnCode::KeyNotFound) + } + }, + // Transfer some value to another account. // // # Parameters diff --git a/frame/contracts/src/weights.rs b/frame/contracts/src/weights.rs index d60a8ab82f3b..17ee020f0113 100644 --- a/frame/contracts/src/weights.rs +++ b/frame/contracts/src/weights.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_contracts //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-12-09, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2021-12-20, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 // Executed Command: @@ -77,7 +77,10 @@ pub trait WeightInfo { fn seal_set_storage_per_kb(n: u32, ) -> Weight; fn seal_clear_storage(r: u32, ) -> Weight; fn seal_get_storage(r: u32, ) -> Weight; + fn seal_contains_storage(r: u32, ) -> Weight; fn seal_get_storage_per_kb(n: u32, ) -> Weight; + fn seal_take_storage(r: u32, ) -> Weight; + fn seal_take_storage_per_kb(n: u32, ) -> Weight; fn seal_transfer(r: u32, ) -> Weight; fn seal_call(r: u32, ) -> Weight; fn seal_call_per_transfer_input_output_kb(t: u32, i: u32, o: u32, ) -> Weight; @@ -150,32 +153,32 @@ pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize() -> Weight { - (2_720_000 as Weight) + (2_286_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn on_initialize_per_trie_key(k: u32, ) -> Weight { (0 as Weight) // Standard Error: 3_000 - .saturating_add((2_208_000 as Weight).saturating_mul(k as Weight)) + .saturating_add((2_219_000 as Weight).saturating_mul(k as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) } // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize_per_queue_item(q: u32, ) -> Weight { - (95_834_000 as Weight) + (95_627_000 as Weight) // Standard Error: 2_000 - .saturating_add((317_000 as Weight).saturating_mul(q as Weight)) + .saturating_add((242_000 as Weight).saturating_mul(q as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Contracts PristineCode (r:1 w:0) // Storage: Contracts CodeStorage (r:0 w:1) fn reinstrument(c: u32, ) -> Weight { - (17_177_000 as Weight) - // Standard Error: 85_000 - .saturating_add((91_306_000 as Weight).saturating_mul(c as Weight)) + (17_037_000 as Weight) + // Standard Error: 98_000 + .saturating_add((88_875_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -184,9 +187,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call_with_code_kb(c: u32, ) -> Weight { - (371_888_000 as Weight) - // Standard Error: 137_000 - .saturating_add((92_314_000 as Weight).saturating_mul(c as Weight)) + (348_110_000 as Weight) + // Standard Error: 136_000 + .saturating_add((81_086_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -198,11 +201,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn instantiate_with_code(c: u32, s: u32, ) -> Weight { - (429_131_000 as Weight) - // Standard Error: 154_000 - .saturating_add((208_736_000 as Weight).saturating_mul(c as Weight)) - // Standard Error: 10_000 - .saturating_add((2_203_000 as Weight).saturating_mul(s as Weight)) + (414_966_000 as Weight) + // Standard Error: 137_000 + .saturating_add((198_330_000 as Weight).saturating_mul(c as Weight)) + // Standard Error: 8_000 + .saturating_add((2_180_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } @@ -213,9 +216,9 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn instantiate(s: u32, ) -> Weight { - (241_132_000 as Weight) + (201_465_000 as Weight) // Standard Error: 2_000 - .saturating_add((1_986_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((1_993_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } @@ -224,7 +227,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call() -> Weight { - (173_649_000 as Weight) + (154_139_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -232,9 +235,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn upload_code(c: u32, ) -> Weight { - (84_508_000 as Weight) + (69_640_000 as Weight) // Standard Error: 93_000 - .saturating_add((91_690_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((89_969_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -242,7 +245,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:0 w:1) // Storage: Contracts PristineCode (r:0 w:1) fn remove_code() -> Weight { - (39_407_000 as Weight) + (31_567_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -251,9 +254,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_caller(r: u32, ) -> Weight { - (421_879_000 as Weight) - // Standard Error: 168_000 - .saturating_add((114_154_000 as Weight).saturating_mul(r as Weight)) + (405_395_000 as Weight) + // Standard Error: 167_000 + .saturating_add((79_867_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -262,9 +265,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_address(r: u32, ) -> Weight { - (428_124_000 as Weight) - // Standard Error: 167_000 - .saturating_add((113_196_000 as Weight).saturating_mul(r as Weight)) + (405_173_000 as Weight) + // Standard Error: 152_000 + .saturating_add((79_619_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -273,9 +276,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas_left(r: u32, ) -> Weight { - (424_405_000 as Weight) - // Standard Error: 182_000 - .saturating_add((112_511_000 as Weight).saturating_mul(r as Weight)) + (406_537_000 as Weight) + // Standard Error: 148_000 + .saturating_add((78_129_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -284,9 +287,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_balance(r: u32, ) -> Weight { - (433_901_000 as Weight) - // Standard Error: 206_000 - .saturating_add((307_273_000 as Weight).saturating_mul(r as Weight)) + (416_289_000 as Weight) + // Standard Error: 165_000 + .saturating_add((218_401_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -295,9 +298,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_value_transferred(r: u32, ) -> Weight { - (428_707_000 as Weight) - // Standard Error: 203_000 - .saturating_add((113_558_000 as Weight).saturating_mul(r as Weight)) + (408_205_000 as Weight) + // Standard Error: 154_000 + .saturating_add((79_563_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -306,9 +309,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_minimum_balance(r: u32, ) -> Weight { - (423_775_000 as Weight) - // Standard Error: 174_000 - .saturating_add((113_371_000 as Weight).saturating_mul(r as Weight)) + (408_124_000 as Weight) + // Standard Error: 149_000 + .saturating_add((79_032_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -317,9 +320,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_block_number(r: u32, ) -> Weight { - (423_282_000 as Weight) - // Standard Error: 220_000 - .saturating_add((113_709_000 as Weight).saturating_mul(r as Weight)) + (406_141_000 as Weight) + // Standard Error: 150_000 + .saturating_add((78_992_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -328,9 +331,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_now(r: u32, ) -> Weight { - (435_209_000 as Weight) - // Standard Error: 157_000 - .saturating_add((111_492_000 as Weight).saturating_mul(r as Weight)) + (418_112_000 as Weight) + // Standard Error: 155_000 + .saturating_add((77_902_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -340,9 +343,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0) fn seal_weight_to_fee(r: u32, ) -> Weight { - (432_886_000 as Weight) - // Standard Error: 193_000 - .saturating_add((260_787_000 as Weight).saturating_mul(r as Weight)) + (411_683_000 as Weight) + // Standard Error: 173_000 + .saturating_add((205_824_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -351,9 +354,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas(r: u32, ) -> Weight { - (147_315_000 as Weight) - // Standard Error: 124_000 - .saturating_add((52_336_000 as Weight).saturating_mul(r as Weight)) + (132_178_000 as Weight) + // Standard Error: 84_000 + .saturating_add((38_233_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -362,9 +365,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input(r: u32, ) -> Weight { - (422_074_000 as Weight) - // Standard Error: 199_000 - .saturating_add((100_398_000 as Weight).saturating_mul(r as Weight)) + (405_685_000 as Weight) + // Standard Error: 142_000 + .saturating_add((72_826_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -373,9 +376,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input_per_kb(n: u32, ) -> Weight { - (543_944_000 as Weight) - // Standard Error: 10_000 - .saturating_add((38_098_000 as Weight).saturating_mul(n as Weight)) + (490_336_000 as Weight) + // Standard Error: 7_000 + .saturating_add((38_070_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -384,9 +387,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return(r: u32, ) -> Weight { - (398_945_000 as Weight) - // Standard Error: 417_000 - .saturating_add((15_763_000 as Weight).saturating_mul(r as Weight)) + (384_543_000 as Weight) + // Standard Error: 105_000 + .saturating_add((15_793_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -395,9 +398,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return_per_kb(n: u32, ) -> Weight { - (416_850_000 as Weight) + (399_205_000 as Weight) // Standard Error: 1_000 - .saturating_add((635_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((637_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -408,9 +411,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts DeletionQueue (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_terminate(r: u32, ) -> Weight { - (408_445_000 as Weight) - // Standard Error: 248_000 - .saturating_add((102_109_000 as Weight).saturating_mul(r as Weight)) + (396_375_000 as Weight) + // Standard Error: 3_023_000 + .saturating_add((79_797_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((4 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -422,9 +425,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) fn seal_random(r: u32, ) -> Weight { - (410_845_000 as Weight) - // Standard Error: 289_000 - .saturating_add((341_867_000 as Weight).saturating_mul(r as Weight)) + (390_550_000 as Weight) + // Standard Error: 290_000 + .saturating_add((245_730_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -433,9 +436,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_deposit_event(r: u32, ) -> Weight { - (425_037_000 as Weight) - // Standard Error: 424_000 - .saturating_add((571_604_000 as Weight).saturating_mul(r as Weight)) + (408_011_000 as Weight) + // Standard Error: 273_000 + .saturating_add((406_522_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -445,11 +448,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: System EventTopics (r:100 w:100) fn seal_deposit_event_per_topic_and_kb(t: u32, n: u32, ) -> Weight { - (1_055_868_000 as Weight) - // Standard Error: 3_004_000 - .saturating_add((453_979_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 592_000 - .saturating_add((166_716_000 as Weight).saturating_mul(n as Weight)) + (890_741_000 as Weight) + // Standard Error: 2_072_000 + .saturating_add((382_953_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 408_000 + .saturating_add((162_320_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(t as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -460,17 +463,17 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_debug_message(r: u32, ) -> Weight { - (161_170_000 as Weight) - // Standard Error: 169_000 - .saturating_add((74_379_000 as Weight).saturating_mul(r as Weight)) + (153_163_000 as Weight) + // Standard Error: 137_000 + .saturating_add((59_081_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage(r: u32, ) -> Weight { - (500_168_000 as Weight) - // Standard Error: 473_000 - .saturating_add((371_239_000 as Weight).saturating_mul(r as Weight)) + (459_368_000 as Weight) + // Standard Error: 560_000 + .saturating_add((330_190_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -482,17 +485,17 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: unknown [0x7afa01283080ef247df84e0ba38ea5a587d25ce6633a6bfbba02068c14023441] (r:1 w:1) fn seal_set_storage_per_kb(n: u32, ) -> Weight { - (796_175_000 as Weight) - // Standard Error: 249_000 - .saturating_add((74_071_000 as Weight).saturating_mul(n as Weight)) + (727_394_000 as Weight) + // Standard Error: 247_000 + .saturating_add((73_350_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage(r: u32, ) -> Weight { - (178_237_000 as Weight) - // Standard Error: 1_652_000 - .saturating_add((835_947_000 as Weight).saturating_mul(r as Weight)) + (163_262_000 as Weight) + // Standard Error: 1_492_000 + .saturating_add((799_087_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -500,9 +503,18 @@ impl WeightInfo for SubstrateWeight { } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage(r: u32, ) -> Weight { - (305_702_000 as Weight) - // Standard Error: 750_000 - .saturating_add((493_580_000 as Weight).saturating_mul(r as Weight)) + (288_728_000 as Weight) + // Standard Error: 752_000 + .saturating_add((434_780_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + // Storage: Skipped Metadata (r:0 w:0) + fn seal_contains_storage(r: u32, ) -> Weight { + (209_606_000 as Weight) + // Standard Error: 1_137_000 + .saturating_add((680_187_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -513,20 +525,38 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: unknown [0x7afa01283080ef247df84e0ba38ea5a587d25ce6633a6bfbba02068c14023441] (r:1 w:0) fn seal_get_storage_per_kb(n: u32, ) -> Weight { - (697_017_000 as Weight) - // Standard Error: 216_000 - .saturating_add((111_743_000 as Weight).saturating_mul(n as Weight)) + (619_600_000 as Weight) + // Standard Error: 207_000 + .saturating_add((111_030_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } + // Storage: Skipped Metadata (r:0 w:0) + fn seal_take_storage(r: u32, ) -> Weight { + (279_528_000 as Weight) + // Standard Error: 932_000 + .saturating_add((541_965_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + .saturating_add(T::DbWeight::get().writes((100 as Weight).saturating_mul(r as Weight))) + } + // Storage: Skipped Metadata (r:0 w:0) + fn seal_take_storage_per_kb(n: u32, ) -> Weight { + (985_732_000 as Weight) + // Standard Error: 446_000 + .saturating_add((123_295_000 as Weight).saturating_mul(n as Weight)) + .saturating_add(T::DbWeight::get().reads(105 as Weight)) + .saturating_add(T::DbWeight::get().writes(103 as Weight)) + } // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_transfer(r: u32, ) -> Weight { - (243_124_000 as Weight) - // Standard Error: 1_718_000 - .saturating_add((3_530_873_000 as Weight).saturating_mul(r as Weight)) + (284_785_000 as Weight) + // Standard Error: 1_479_000 + .saturating_add((2_527_544_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -537,9 +567,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_call(r: u32, ) -> Weight { - (140_524_000 as Weight) - // Standard Error: 4_504_000 - .saturating_add((39_287_224_000 as Weight).saturating_mul(r as Weight)) + (0 as Weight) + // Standard Error: 5_742_000 + .saturating_add((37_993_391_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -550,13 +580,13 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:2 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_call_per_transfer_input_output_kb(t: u32, i: u32, o: u32, ) -> Weight { - (38_929_132_000 as Weight) - // Standard Error: 65_806_000 - .saturating_add((2_980_358_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 23_000 - .saturating_add((62_980_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 25_000 - .saturating_add((101_383_000 as Weight).saturating_mul(o as Weight)) + (37_404_660_000 as Weight) + // Standard Error: 92_661_000 + .saturating_add((2_486_257_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 33_000 + .saturating_add((63_001_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 35_000 + .saturating_add((101_347_000 as Weight).saturating_mul(o as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().reads((101 as Weight).saturating_mul(t as Weight))) .saturating_add(T::DbWeight::get().writes(101 as Weight)) @@ -570,8 +600,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts OwnerInfoOf (r:100 w:100) fn seal_instantiate(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 120_171_000 - .saturating_add((50_779_937_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 119_281_000 + .saturating_add((47_113_525_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().reads((400 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -584,13 +614,13 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts AccountCounter (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_instantiate_per_input_output_salt_kb(i: u32, o: u32, s: u32, ) -> Weight { - (45_749_415_000 as Weight) - // Standard Error: 34_000 - .saturating_add((64_650_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 34_000 - .saturating_add((101_902_000 as Weight).saturating_mul(o as Weight)) - // Standard Error: 34_000 - .saturating_add((201_402_000 as Weight).saturating_mul(s as Weight)) + (41_157_901_000 as Weight) + // Standard Error: 147_000 + .saturating_add((64_877_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 147_000 + .saturating_add((102_420_000 as Weight).saturating_mul(o as Weight)) + // Standard Error: 147_000 + .saturating_add((201_587_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(208 as Weight)) .saturating_add(T::DbWeight::get().writes(206 as Weight)) } @@ -599,9 +629,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256(r: u32, ) -> Weight { - (414_773_000 as Weight) - // Standard Error: 183_000 - .saturating_add((127_117_000 as Weight).saturating_mul(r as Weight)) + (402_224_000 as Weight) + // Standard Error: 166_000 + .saturating_add((103_985_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -610,9 +640,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256_per_kb(n: u32, ) -> Weight { - (581_981_000 as Weight) - // Standard Error: 38_000 - .saturating_add((505_754_000 as Weight).saturating_mul(n as Weight)) + (663_731_000 as Weight) + // Standard Error: 42_000 + .saturating_add((505_157_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -621,9 +651,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256(r: u32, ) -> Weight { - (424_421_000 as Weight) - // Standard Error: 223_000 - .saturating_add((137_068_000 as Weight).saturating_mul(r as Weight)) + (402_638_000 as Weight) + // Standard Error: 165_000 + .saturating_add((117_589_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -632,9 +662,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256_per_kb(n: u32, ) -> Weight { - (497_132_000 as Weight) - // Standard Error: 24_000 - .saturating_add((363_894_000 as Weight).saturating_mul(n as Weight)) + (491_978_000 as Weight) + // Standard Error: 23_000 + .saturating_add((363_687_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -643,9 +673,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256(r: u32, ) -> Weight { - (419_414_000 as Weight) - // Standard Error: 174_000 - .saturating_add((106_283_000 as Weight).saturating_mul(r as Weight)) + (402_254_000 as Weight) + // Standard Error: 154_000 + .saturating_add((86_403_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -654,9 +684,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256_per_kb(n: u32, ) -> Weight { - (572_206_000 as Weight) - // Standard Error: 24_000 - .saturating_add((163_930_000 as Weight).saturating_mul(n as Weight)) + (476_405_000 as Weight) + // Standard Error: 18_000 + .saturating_add((163_921_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -665,9 +695,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128(r: u32, ) -> Weight { - (417_971_000 as Weight) - // Standard Error: 180_000 - .saturating_add((106_016_000 as Weight).saturating_mul(r as Weight)) + (399_949_000 as Weight) + // Standard Error: 142_000 + .saturating_add((85_448_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -676,9 +706,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128_per_kb(n: u32, ) -> Weight { - (568_067_000 as Weight) - // Standard Error: 20_000 - .saturating_add((163_853_000 as Weight).saturating_mul(n as Weight)) + (475_437_000 as Weight) + // Standard Error: 15_000 + .saturating_add((163_921_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -687,266 +717,266 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_ecdsa_recover(r: u32, ) -> Weight { - (372_816_000 as Weight) - // Standard Error: 1_677_000 - .saturating_add((15_723_462_000 as Weight).saturating_mul(r as Weight)) + (373_575_000 as Weight) + // Standard Error: 1_639_000 + .saturating_add((15_530_027_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn instr_i64const(r: u32, ) -> Weight { - (53_407_000 as Weight) - // Standard Error: 14_000 - .saturating_add((885_000 as Weight).saturating_mul(r as Weight)) + (52_763_000 as Weight) + // Standard Error: 12_000 + .saturating_add((857_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64load(r: u32, ) -> Weight { - (48_061_000 as Weight) + (47_313_000 as Weight) // Standard Error: 10_000 - .saturating_add((2_947_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_935_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64store(r: u32, ) -> Weight { - (48_150_000 as Weight) + (47_147_000 as Weight) // Standard Error: 10_000 - .saturating_add((2_978_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_995_000 as Weight).saturating_mul(r as Weight)) } fn instr_select(r: u32, ) -> Weight { - (50_943_000 as Weight) + (50_124_000 as Weight) // Standard Error: 11_000 - .saturating_add((2_446_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_421_000 as Weight).saturating_mul(r as Weight)) } fn instr_if(r: u32, ) -> Weight { - (47_862_000 as Weight) - // Standard Error: 12_000 - .saturating_add((2_627_000 as Weight).saturating_mul(r as Weight)) + (47_288_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_523_000 as Weight).saturating_mul(r as Weight)) } fn instr_br(r: u32, ) -> Weight { - (51_291_000 as Weight) + (50_198_000 as Weight) // Standard Error: 16_000 - .saturating_add((1_467_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_473_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_if(r: u32, ) -> Weight { - (44_627_000 as Weight) - // Standard Error: 18_000 - .saturating_add((2_211_000 as Weight).saturating_mul(r as Weight)) + (44_008_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_174_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table(r: u32, ) -> Weight { - (38_208_000 as Weight) + (37_602_000 as Weight) // Standard Error: 16_000 - .saturating_add((2_914_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_820_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table_per_entry(e: u32, ) -> Weight { - (47_228_000 as Weight) + (46_232_000 as Weight) // Standard Error: 3_000 .saturating_add((17_000 as Weight).saturating_mul(e as Weight)) } fn instr_call(r: u32, ) -> Weight { - (39_507_000 as Weight) - // Standard Error: 26_000 - .saturating_add((20_544_000 as Weight).saturating_mul(r as Weight)) + (40_148_000 as Weight) + // Standard Error: 22_000 + .saturating_add((20_585_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect(r: u32, ) -> Weight { - (47_235_000 as Weight) + (43_948_000 as Weight) // Standard Error: 31_000 - .saturating_add((29_869_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((30_226_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect_per_param(p: u32, ) -> Weight { - (78_847_000 as Weight) - // Standard Error: 6_000 - .saturating_add((1_217_000 as Weight).saturating_mul(p as Weight)) + (78_722_000 as Weight) + // Standard Error: 5_000 + .saturating_add((1_199_000 as Weight).saturating_mul(p as Weight)) } fn instr_local_get(r: u32, ) -> Weight { - (48_441_000 as Weight) - // Standard Error: 11_000 - .saturating_add((816_000 as Weight).saturating_mul(r as Weight)) + (48_083_000 as Weight) + // Standard Error: 12_000 + .saturating_add((805_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_set(r: u32, ) -> Weight { - (48_324_000 as Weight) + (47_710_000 as Weight) // Standard Error: 11_000 - .saturating_add((861_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((843_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_tee(r: u32, ) -> Weight { - (45_372_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_488_000 as Weight).saturating_mul(r as Weight)) + (44_785_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_466_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_get(r: u32, ) -> Weight { - (58_465_000 as Weight) + (50_106_000 as Weight) // Standard Error: 20_000 - .saturating_add((1_655_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_641_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_set(r: u32, ) -> Weight { - (55_457_000 as Weight) + (47_058_000 as Weight) // Standard Error: 18_000 - .saturating_add((1_671_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_707_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_current(r: u32, ) -> Weight { - (52_615_000 as Weight) - // Standard Error: 14_000 - .saturating_add((905_000 as Weight).saturating_mul(r as Weight)) + (51_494_000 as Weight) + // Standard Error: 15_000 + .saturating_add((925_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_grow(r: u32, ) -> Weight { - (37_739_000 as Weight) - // Standard Error: 2_851_000 - .saturating_add((634_780_000 as Weight).saturating_mul(r as Weight)) + (36_983_000 as Weight) + // Standard Error: 3_602_000 + .saturating_add((634_259_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64clz(r: u32, ) -> Weight { - (54_830_000 as Weight) - // Standard Error: 9_000 - .saturating_add((1_309_000 as Weight).saturating_mul(r as Weight)) + (60_711_000 as Weight) + // Standard Error: 22_000 + .saturating_add((1_157_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ctz(r: u32, ) -> Weight { - (54_712_000 as Weight) + (53_908_000 as Weight) // Standard Error: 9_000 - .saturating_add((1_310_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_305_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64popcnt(r: u32, ) -> Weight { - (54_864_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_312_000 as Weight).saturating_mul(r as Weight)) + (53_939_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_314_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eqz(r: u32, ) -> Weight { - (54_596_000 as Weight) - // Standard Error: 9_000 - .saturating_add((1_314_000 as Weight).saturating_mul(r as Weight)) + (54_086_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_309_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendsi32(r: u32, ) -> Weight { - (44_536_000 as Weight) - // Standard Error: 12_000 - .saturating_add((1_514_000 as Weight).saturating_mul(r as Weight)) + (43_845_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_493_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendui32(r: u32, ) -> Weight { - (44_380_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_512_000 as Weight).saturating_mul(r as Weight)) + (43_518_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_501_000 as Weight).saturating_mul(r as Weight)) } fn instr_i32wrapi64(r: u32, ) -> Weight { - (54_968_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_310_000 as Weight).saturating_mul(r as Weight)) + (53_912_000 as Weight) + // Standard Error: 9_000 + .saturating_add((1_302_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eq(r: u32, ) -> Weight { - (50_161_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_917_000 as Weight).saturating_mul(r as Weight)) + (49_594_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_890_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ne(r: u32, ) -> Weight { - (50_417_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_911_000 as Weight).saturating_mul(r as Weight)) + (49_659_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_894_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64lts(r: u32, ) -> Weight { - (50_358_000 as Weight) + (49_401_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_914_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_902_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ltu(r: u32, ) -> Weight { - (49_864_000 as Weight) + (49_880_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_928_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_885_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gts(r: u32, ) -> Weight { - (50_159_000 as Weight) + (49_466_000 as Weight) // Standard Error: 10_000 - .saturating_add((1_917_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_894_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gtu(r: u32, ) -> Weight { - (50_037_000 as Weight) - // Standard Error: 16_000 - .saturating_add((1_945_000 as Weight).saturating_mul(r as Weight)) + (49_514_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_891_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64les(r: u32, ) -> Weight { - (50_482_000 as Weight) + (49_588_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_909_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_898_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64leu(r: u32, ) -> Weight { - (50_426_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_908_000 as Weight).saturating_mul(r as Weight)) + (49_589_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_891_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ges(r: u32, ) -> Weight { - (50_205_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_918_000 as Weight).saturating_mul(r as Weight)) + (49_685_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_892_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64geu(r: u32, ) -> Weight { - (50_189_000 as Weight) - // Standard Error: 12_000 - .saturating_add((1_928_000 as Weight).saturating_mul(r as Weight)) + (49_601_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_891_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64add(r: u32, ) -> Weight { - (50_205_000 as Weight) - // Standard Error: 12_000 - .saturating_add((1_922_000 as Weight).saturating_mul(r as Weight)) + (49_430_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_894_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64sub(r: u32, ) -> Weight { - (50_375_000 as Weight) - // Standard Error: 15_000 - .saturating_add((1_929_000 as Weight).saturating_mul(r as Weight)) + (49_533_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_893_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64mul(r: u32, ) -> Weight { - (50_343_000 as Weight) - // Standard Error: 12_000 - .saturating_add((1_916_000 as Weight).saturating_mul(r as Weight)) + (49_766_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_888_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divs(r: u32, ) -> Weight { - (50_707_000 as Weight) + (49_315_000 as Weight) // Standard Error: 11_000 - .saturating_add((2_667_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_552_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divu(r: u32, ) -> Weight { - (50_318_000 as Weight) + (49_786_000 as Weight) // Standard Error: 11_000 - .saturating_add((2_408_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_203_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rems(r: u32, ) -> Weight { - (50_214_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_702_000 as Weight).saturating_mul(r as Weight)) + (49_651_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_461_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64remu(r: u32, ) -> Weight { - (50_394_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_411_000 as Weight).saturating_mul(r as Weight)) + (49_747_000 as Weight) + // Standard Error: 10_000 + .saturating_add((2_196_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64and(r: u32, ) -> Weight { - (50_397_000 as Weight) + (49_719_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_910_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_892_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64or(r: u32, ) -> Weight { - (50_291_000 as Weight) - // Standard Error: 12_000 - .saturating_add((1_915_000 as Weight).saturating_mul(r as Weight)) + (49_463_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_896_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64xor(r: u32, ) -> Weight { - (50_684_000 as Weight) - // Standard Error: 12_000 + (49_379_000 as Weight) + // Standard Error: 11_000 .saturating_add((1_903_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shl(r: u32, ) -> Weight { - (49_638_000 as Weight) - // Standard Error: 17_000 - .saturating_add((1_967_000 as Weight).saturating_mul(r as Weight)) + (49_404_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_902_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shrs(r: u32, ) -> Weight { - (50_817_000 as Weight) - // Standard Error: 12_000 - .saturating_add((1_899_000 as Weight).saturating_mul(r as Weight)) + (49_498_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_900_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shru(r: u32, ) -> Weight { - (50_987_000 as Weight) - // Standard Error: 12_000 - .saturating_add((1_899_000 as Weight).saturating_mul(r as Weight)) + (49_541_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_897_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotl(r: u32, ) -> Weight { - (50_885_000 as Weight) - // Standard Error: 12_000 - .saturating_add((1_905_000 as Weight).saturating_mul(r as Weight)) + (49_452_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_900_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotr(r: u32, ) -> Weight { - (50_465_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_908_000 as Weight).saturating_mul(r as Weight)) + (49_350_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_902_000 as Weight).saturating_mul(r as Weight)) } } @@ -954,32 +984,32 @@ impl WeightInfo for SubstrateWeight { impl WeightInfo for () { // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize() -> Weight { - (2_720_000 as Weight) + (2_286_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn on_initialize_per_trie_key(k: u32, ) -> Weight { (0 as Weight) // Standard Error: 3_000 - .saturating_add((2_208_000 as Weight).saturating_mul(k as Weight)) + .saturating_add((2_219_000 as Weight).saturating_mul(k as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) } // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize_per_queue_item(q: u32, ) -> Weight { - (95_834_000 as Weight) + (95_627_000 as Weight) // Standard Error: 2_000 - .saturating_add((317_000 as Weight).saturating_mul(q as Weight)) + .saturating_add((242_000 as Weight).saturating_mul(q as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Contracts PristineCode (r:1 w:0) // Storage: Contracts CodeStorage (r:0 w:1) fn reinstrument(c: u32, ) -> Weight { - (17_177_000 as Weight) - // Standard Error: 85_000 - .saturating_add((91_306_000 as Weight).saturating_mul(c as Weight)) + (17_037_000 as Weight) + // Standard Error: 98_000 + .saturating_add((88_875_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -988,9 +1018,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call_with_code_kb(c: u32, ) -> Weight { - (371_888_000 as Weight) - // Standard Error: 137_000 - .saturating_add((92_314_000 as Weight).saturating_mul(c as Weight)) + (348_110_000 as Weight) + // Standard Error: 136_000 + .saturating_add((81_086_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -1002,11 +1032,11 @@ impl WeightInfo for () { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn instantiate_with_code(c: u32, s: u32, ) -> Weight { - (429_131_000 as Weight) - // Standard Error: 154_000 - .saturating_add((208_736_000 as Weight).saturating_mul(c as Weight)) - // Standard Error: 10_000 - .saturating_add((2_203_000 as Weight).saturating_mul(s as Weight)) + (414_966_000 as Weight) + // Standard Error: 137_000 + .saturating_add((198_330_000 as Weight).saturating_mul(c as Weight)) + // Standard Error: 8_000 + .saturating_add((2_180_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } @@ -1017,9 +1047,9 @@ impl WeightInfo for () { // Storage: System Account (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn instantiate(s: u32, ) -> Weight { - (241_132_000 as Weight) + (201_465_000 as Weight) // Standard Error: 2_000 - .saturating_add((1_986_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((1_993_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } @@ -1028,7 +1058,7 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call() -> Weight { - (173_649_000 as Weight) + (154_139_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -1036,9 +1066,9 @@ impl WeightInfo for () { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn upload_code(c: u32, ) -> Weight { - (84_508_000 as Weight) + (69_640_000 as Weight) // Standard Error: 93_000 - .saturating_add((91_690_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((89_969_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -1046,7 +1076,7 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:0 w:1) // Storage: Contracts PristineCode (r:0 w:1) fn remove_code() -> Weight { - (39_407_000 as Weight) + (31_567_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -1055,9 +1085,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_caller(r: u32, ) -> Weight { - (421_879_000 as Weight) - // Standard Error: 168_000 - .saturating_add((114_154_000 as Weight).saturating_mul(r as Weight)) + (405_395_000 as Weight) + // Standard Error: 167_000 + .saturating_add((79_867_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1066,9 +1096,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_address(r: u32, ) -> Weight { - (428_124_000 as Weight) - // Standard Error: 167_000 - .saturating_add((113_196_000 as Weight).saturating_mul(r as Weight)) + (405_173_000 as Weight) + // Standard Error: 152_000 + .saturating_add((79_619_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1077,9 +1107,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas_left(r: u32, ) -> Weight { - (424_405_000 as Weight) - // Standard Error: 182_000 - .saturating_add((112_511_000 as Weight).saturating_mul(r as Weight)) + (406_537_000 as Weight) + // Standard Error: 148_000 + .saturating_add((78_129_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1088,9 +1118,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_balance(r: u32, ) -> Weight { - (433_901_000 as Weight) - // Standard Error: 206_000 - .saturating_add((307_273_000 as Weight).saturating_mul(r as Weight)) + (416_289_000 as Weight) + // Standard Error: 165_000 + .saturating_add((218_401_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1099,9 +1129,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_value_transferred(r: u32, ) -> Weight { - (428_707_000 as Weight) - // Standard Error: 203_000 - .saturating_add((113_558_000 as Weight).saturating_mul(r as Weight)) + (408_205_000 as Weight) + // Standard Error: 154_000 + .saturating_add((79_563_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1110,9 +1140,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_minimum_balance(r: u32, ) -> Weight { - (423_775_000 as Weight) - // Standard Error: 174_000 - .saturating_add((113_371_000 as Weight).saturating_mul(r as Weight)) + (408_124_000 as Weight) + // Standard Error: 149_000 + .saturating_add((79_032_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1121,9 +1151,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_block_number(r: u32, ) -> Weight { - (423_282_000 as Weight) - // Standard Error: 220_000 - .saturating_add((113_709_000 as Weight).saturating_mul(r as Weight)) + (406_141_000 as Weight) + // Standard Error: 150_000 + .saturating_add((78_992_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1132,9 +1162,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_now(r: u32, ) -> Weight { - (435_209_000 as Weight) - // Standard Error: 157_000 - .saturating_add((111_492_000 as Weight).saturating_mul(r as Weight)) + (418_112_000 as Weight) + // Standard Error: 155_000 + .saturating_add((77_902_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1144,9 +1174,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0) fn seal_weight_to_fee(r: u32, ) -> Weight { - (432_886_000 as Weight) - // Standard Error: 193_000 - .saturating_add((260_787_000 as Weight).saturating_mul(r as Weight)) + (411_683_000 as Weight) + // Standard Error: 173_000 + .saturating_add((205_824_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1155,9 +1185,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas(r: u32, ) -> Weight { - (147_315_000 as Weight) - // Standard Error: 124_000 - .saturating_add((52_336_000 as Weight).saturating_mul(r as Weight)) + (132_178_000 as Weight) + // Standard Error: 84_000 + .saturating_add((38_233_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1166,9 +1196,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input(r: u32, ) -> Weight { - (422_074_000 as Weight) - // Standard Error: 199_000 - .saturating_add((100_398_000 as Weight).saturating_mul(r as Weight)) + (405_685_000 as Weight) + // Standard Error: 142_000 + .saturating_add((72_826_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1177,9 +1207,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input_per_kb(n: u32, ) -> Weight { - (543_944_000 as Weight) - // Standard Error: 10_000 - .saturating_add((38_098_000 as Weight).saturating_mul(n as Weight)) + (490_336_000 as Weight) + // Standard Error: 7_000 + .saturating_add((38_070_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1188,9 +1218,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return(r: u32, ) -> Weight { - (398_945_000 as Weight) - // Standard Error: 417_000 - .saturating_add((15_763_000 as Weight).saturating_mul(r as Weight)) + (384_543_000 as Weight) + // Standard Error: 105_000 + .saturating_add((15_793_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1199,9 +1229,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return_per_kb(n: u32, ) -> Weight { - (416_850_000 as Weight) + (399_205_000 as Weight) // Standard Error: 1_000 - .saturating_add((635_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((637_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1212,9 +1242,9 @@ impl WeightInfo for () { // Storage: Contracts DeletionQueue (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_terminate(r: u32, ) -> Weight { - (408_445_000 as Weight) - // Standard Error: 248_000 - .saturating_add((102_109_000 as Weight).saturating_mul(r as Weight)) + (396_375_000 as Weight) + // Standard Error: 3_023_000 + .saturating_add((79_797_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((4 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1226,9 +1256,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) fn seal_random(r: u32, ) -> Weight { - (410_845_000 as Weight) - // Standard Error: 289_000 - .saturating_add((341_867_000 as Weight).saturating_mul(r as Weight)) + (390_550_000 as Weight) + // Standard Error: 290_000 + .saturating_add((245_730_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1237,9 +1267,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_deposit_event(r: u32, ) -> Weight { - (425_037_000 as Weight) - // Standard Error: 424_000 - .saturating_add((571_604_000 as Weight).saturating_mul(r as Weight)) + (408_011_000 as Weight) + // Standard Error: 273_000 + .saturating_add((406_522_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1249,11 +1279,11 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: System EventTopics (r:100 w:100) fn seal_deposit_event_per_topic_and_kb(t: u32, n: u32, ) -> Weight { - (1_055_868_000 as Weight) - // Standard Error: 3_004_000 - .saturating_add((453_979_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 592_000 - .saturating_add((166_716_000 as Weight).saturating_mul(n as Weight)) + (890_741_000 as Weight) + // Standard Error: 2_072_000 + .saturating_add((382_953_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 408_000 + .saturating_add((162_320_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(t as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1264,17 +1294,17 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_debug_message(r: u32, ) -> Weight { - (161_170_000 as Weight) - // Standard Error: 169_000 - .saturating_add((74_379_000 as Weight).saturating_mul(r as Weight)) + (153_163_000 as Weight) + // Standard Error: 137_000 + .saturating_add((59_081_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage(r: u32, ) -> Weight { - (500_168_000 as Weight) - // Standard Error: 473_000 - .saturating_add((371_239_000 as Weight).saturating_mul(r as Weight)) + (459_368_000 as Weight) + // Standard Error: 560_000 + .saturating_add((330_190_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -1286,17 +1316,17 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: unknown [0x7afa01283080ef247df84e0ba38ea5a587d25ce6633a6bfbba02068c14023441] (r:1 w:1) fn seal_set_storage_per_kb(n: u32, ) -> Weight { - (796_175_000 as Weight) - // Standard Error: 249_000 - .saturating_add((74_071_000 as Weight).saturating_mul(n as Weight)) + (727_394_000 as Weight) + // Standard Error: 247_000 + .saturating_add((73_350_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage(r: u32, ) -> Weight { - (178_237_000 as Weight) - // Standard Error: 1_652_000 - .saturating_add((835_947_000 as Weight).saturating_mul(r as Weight)) + (163_262_000 as Weight) + // Standard Error: 1_492_000 + .saturating_add((799_087_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -1304,9 +1334,18 @@ impl WeightInfo for () { } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage(r: u32, ) -> Weight { - (305_702_000 as Weight) - // Standard Error: 750_000 - .saturating_add((493_580_000 as Weight).saturating_mul(r as Weight)) + (288_728_000 as Weight) + // Standard Error: 752_000 + .saturating_add((434_780_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + // Storage: Skipped Metadata (r:0 w:0) + fn seal_contains_storage(r: u32, ) -> Weight { + (209_606_000 as Weight) + // Standard Error: 1_137_000 + .saturating_add((680_187_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1317,20 +1356,38 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: unknown [0x7afa01283080ef247df84e0ba38ea5a587d25ce6633a6bfbba02068c14023441] (r:1 w:0) fn seal_get_storage_per_kb(n: u32, ) -> Weight { - (697_017_000 as Weight) - // Standard Error: 216_000 - .saturating_add((111_743_000 as Weight).saturating_mul(n as Weight)) + (619_600_000 as Weight) + // Standard Error: 207_000 + .saturating_add((111_030_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } + // Storage: Skipped Metadata (r:0 w:0) + fn seal_take_storage(r: u32, ) -> Weight { + (279_528_000 as Weight) + // Standard Error: 932_000 + .saturating_add((541_965_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes((100 as Weight).saturating_mul(r as Weight))) + } + // Storage: Skipped Metadata (r:0 w:0) + fn seal_take_storage_per_kb(n: u32, ) -> Weight { + (985_732_000 as Weight) + // Standard Error: 446_000 + .saturating_add((123_295_000 as Weight).saturating_mul(n as Weight)) + .saturating_add(RocksDbWeight::get().reads(105 as Weight)) + .saturating_add(RocksDbWeight::get().writes(103 as Weight)) + } // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_transfer(r: u32, ) -> Weight { - (243_124_000 as Weight) - // Standard Error: 1_718_000 - .saturating_add((3_530_873_000 as Weight).saturating_mul(r as Weight)) + (284_785_000 as Weight) + // Standard Error: 1_479_000 + .saturating_add((2_527_544_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) @@ -1341,9 +1398,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_call(r: u32, ) -> Weight { - (140_524_000 as Weight) - // Standard Error: 4_504_000 - .saturating_add((39_287_224_000 as Weight).saturating_mul(r as Weight)) + (0 as Weight) + // Standard Error: 5_742_000 + .saturating_add((37_993_391_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1354,13 +1411,13 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:2 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_call_per_transfer_input_output_kb(t: u32, i: u32, o: u32, ) -> Weight { - (38_929_132_000 as Weight) - // Standard Error: 65_806_000 - .saturating_add((2_980_358_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 23_000 - .saturating_add((62_980_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 25_000 - .saturating_add((101_383_000 as Weight).saturating_mul(o as Weight)) + (37_404_660_000 as Weight) + // Standard Error: 92_661_000 + .saturating_add((2_486_257_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 33_000 + .saturating_add((63_001_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 35_000 + .saturating_add((101_347_000 as Weight).saturating_mul(o as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().reads((101 as Weight).saturating_mul(t as Weight))) .saturating_add(RocksDbWeight::get().writes(101 as Weight)) @@ -1374,8 +1431,8 @@ impl WeightInfo for () { // Storage: Contracts OwnerInfoOf (r:100 w:100) fn seal_instantiate(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 120_171_000 - .saturating_add((50_779_937_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 119_281_000 + .saturating_add((47_113_525_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().reads((400 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -1388,13 +1445,13 @@ impl WeightInfo for () { // Storage: Contracts AccountCounter (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_instantiate_per_input_output_salt_kb(i: u32, o: u32, s: u32, ) -> Weight { - (45_749_415_000 as Weight) - // Standard Error: 34_000 - .saturating_add((64_650_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 34_000 - .saturating_add((101_902_000 as Weight).saturating_mul(o as Weight)) - // Standard Error: 34_000 - .saturating_add((201_402_000 as Weight).saturating_mul(s as Weight)) + (41_157_901_000 as Weight) + // Standard Error: 147_000 + .saturating_add((64_877_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 147_000 + .saturating_add((102_420_000 as Weight).saturating_mul(o as Weight)) + // Standard Error: 147_000 + .saturating_add((201_587_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(208 as Weight)) .saturating_add(RocksDbWeight::get().writes(206 as Weight)) } @@ -1403,9 +1460,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256(r: u32, ) -> Weight { - (414_773_000 as Weight) - // Standard Error: 183_000 - .saturating_add((127_117_000 as Weight).saturating_mul(r as Weight)) + (402_224_000 as Weight) + // Standard Error: 166_000 + .saturating_add((103_985_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1414,9 +1471,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256_per_kb(n: u32, ) -> Weight { - (581_981_000 as Weight) - // Standard Error: 38_000 - .saturating_add((505_754_000 as Weight).saturating_mul(n as Weight)) + (663_731_000 as Weight) + // Standard Error: 42_000 + .saturating_add((505_157_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1425,9 +1482,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256(r: u32, ) -> Weight { - (424_421_000 as Weight) - // Standard Error: 223_000 - .saturating_add((137_068_000 as Weight).saturating_mul(r as Weight)) + (402_638_000 as Weight) + // Standard Error: 165_000 + .saturating_add((117_589_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1436,9 +1493,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256_per_kb(n: u32, ) -> Weight { - (497_132_000 as Weight) - // Standard Error: 24_000 - .saturating_add((363_894_000 as Weight).saturating_mul(n as Weight)) + (491_978_000 as Weight) + // Standard Error: 23_000 + .saturating_add((363_687_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1447,9 +1504,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256(r: u32, ) -> Weight { - (419_414_000 as Weight) - // Standard Error: 174_000 - .saturating_add((106_283_000 as Weight).saturating_mul(r as Weight)) + (402_254_000 as Weight) + // Standard Error: 154_000 + .saturating_add((86_403_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1458,9 +1515,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256_per_kb(n: u32, ) -> Weight { - (572_206_000 as Weight) - // Standard Error: 24_000 - .saturating_add((163_930_000 as Weight).saturating_mul(n as Weight)) + (476_405_000 as Weight) + // Standard Error: 18_000 + .saturating_add((163_921_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1469,9 +1526,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128(r: u32, ) -> Weight { - (417_971_000 as Weight) - // Standard Error: 180_000 - .saturating_add((106_016_000 as Weight).saturating_mul(r as Weight)) + (399_949_000 as Weight) + // Standard Error: 142_000 + .saturating_add((85_448_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1480,9 +1537,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128_per_kb(n: u32, ) -> Weight { - (568_067_000 as Weight) - // Standard Error: 20_000 - .saturating_add((163_853_000 as Weight).saturating_mul(n as Weight)) + (475_437_000 as Weight) + // Standard Error: 15_000 + .saturating_add((163_921_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1491,265 +1548,265 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_ecdsa_recover(r: u32, ) -> Weight { - (372_816_000 as Weight) - // Standard Error: 1_677_000 - .saturating_add((15_723_462_000 as Weight).saturating_mul(r as Weight)) + (373_575_000 as Weight) + // Standard Error: 1_639_000 + .saturating_add((15_530_027_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn instr_i64const(r: u32, ) -> Weight { - (53_407_000 as Weight) - // Standard Error: 14_000 - .saturating_add((885_000 as Weight).saturating_mul(r as Weight)) + (52_763_000 as Weight) + // Standard Error: 12_000 + .saturating_add((857_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64load(r: u32, ) -> Weight { - (48_061_000 as Weight) + (47_313_000 as Weight) // Standard Error: 10_000 - .saturating_add((2_947_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_935_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64store(r: u32, ) -> Weight { - (48_150_000 as Weight) + (47_147_000 as Weight) // Standard Error: 10_000 - .saturating_add((2_978_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_995_000 as Weight).saturating_mul(r as Weight)) } fn instr_select(r: u32, ) -> Weight { - (50_943_000 as Weight) + (50_124_000 as Weight) // Standard Error: 11_000 - .saturating_add((2_446_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_421_000 as Weight).saturating_mul(r as Weight)) } fn instr_if(r: u32, ) -> Weight { - (47_862_000 as Weight) - // Standard Error: 12_000 - .saturating_add((2_627_000 as Weight).saturating_mul(r as Weight)) + (47_288_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_523_000 as Weight).saturating_mul(r as Weight)) } fn instr_br(r: u32, ) -> Weight { - (51_291_000 as Weight) + (50_198_000 as Weight) // Standard Error: 16_000 - .saturating_add((1_467_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_473_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_if(r: u32, ) -> Weight { - (44_627_000 as Weight) - // Standard Error: 18_000 - .saturating_add((2_211_000 as Weight).saturating_mul(r as Weight)) + (44_008_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_174_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table(r: u32, ) -> Weight { - (38_208_000 as Weight) + (37_602_000 as Weight) // Standard Error: 16_000 - .saturating_add((2_914_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_820_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table_per_entry(e: u32, ) -> Weight { - (47_228_000 as Weight) + (46_232_000 as Weight) // Standard Error: 3_000 .saturating_add((17_000 as Weight).saturating_mul(e as Weight)) } fn instr_call(r: u32, ) -> Weight { - (39_507_000 as Weight) - // Standard Error: 26_000 - .saturating_add((20_544_000 as Weight).saturating_mul(r as Weight)) + (40_148_000 as Weight) + // Standard Error: 22_000 + .saturating_add((20_585_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect(r: u32, ) -> Weight { - (47_235_000 as Weight) + (43_948_000 as Weight) // Standard Error: 31_000 - .saturating_add((29_869_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((30_226_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect_per_param(p: u32, ) -> Weight { - (78_847_000 as Weight) - // Standard Error: 6_000 - .saturating_add((1_217_000 as Weight).saturating_mul(p as Weight)) + (78_722_000 as Weight) + // Standard Error: 5_000 + .saturating_add((1_199_000 as Weight).saturating_mul(p as Weight)) } fn instr_local_get(r: u32, ) -> Weight { - (48_441_000 as Weight) - // Standard Error: 11_000 - .saturating_add((816_000 as Weight).saturating_mul(r as Weight)) + (48_083_000 as Weight) + // Standard Error: 12_000 + .saturating_add((805_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_set(r: u32, ) -> Weight { - (48_324_000 as Weight) + (47_710_000 as Weight) // Standard Error: 11_000 - .saturating_add((861_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((843_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_tee(r: u32, ) -> Weight { - (45_372_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_488_000 as Weight).saturating_mul(r as Weight)) + (44_785_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_466_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_get(r: u32, ) -> Weight { - (58_465_000 as Weight) + (50_106_000 as Weight) // Standard Error: 20_000 - .saturating_add((1_655_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_641_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_set(r: u32, ) -> Weight { - (55_457_000 as Weight) + (47_058_000 as Weight) // Standard Error: 18_000 - .saturating_add((1_671_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_707_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_current(r: u32, ) -> Weight { - (52_615_000 as Weight) - // Standard Error: 14_000 - .saturating_add((905_000 as Weight).saturating_mul(r as Weight)) + (51_494_000 as Weight) + // Standard Error: 15_000 + .saturating_add((925_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_grow(r: u32, ) -> Weight { - (37_739_000 as Weight) - // Standard Error: 2_851_000 - .saturating_add((634_780_000 as Weight).saturating_mul(r as Weight)) + (36_983_000 as Weight) + // Standard Error: 3_602_000 + .saturating_add((634_259_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64clz(r: u32, ) -> Weight { - (54_830_000 as Weight) - // Standard Error: 9_000 - .saturating_add((1_309_000 as Weight).saturating_mul(r as Weight)) + (60_711_000 as Weight) + // Standard Error: 22_000 + .saturating_add((1_157_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ctz(r: u32, ) -> Weight { - (54_712_000 as Weight) + (53_908_000 as Weight) // Standard Error: 9_000 - .saturating_add((1_310_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_305_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64popcnt(r: u32, ) -> Weight { - (54_864_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_312_000 as Weight).saturating_mul(r as Weight)) + (53_939_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_314_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eqz(r: u32, ) -> Weight { - (54_596_000 as Weight) - // Standard Error: 9_000 - .saturating_add((1_314_000 as Weight).saturating_mul(r as Weight)) + (54_086_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_309_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendsi32(r: u32, ) -> Weight { - (44_536_000 as Weight) - // Standard Error: 12_000 - .saturating_add((1_514_000 as Weight).saturating_mul(r as Weight)) + (43_845_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_493_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendui32(r: u32, ) -> Weight { - (44_380_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_512_000 as Weight).saturating_mul(r as Weight)) + (43_518_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_501_000 as Weight).saturating_mul(r as Weight)) } fn instr_i32wrapi64(r: u32, ) -> Weight { - (54_968_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_310_000 as Weight).saturating_mul(r as Weight)) + (53_912_000 as Weight) + // Standard Error: 9_000 + .saturating_add((1_302_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eq(r: u32, ) -> Weight { - (50_161_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_917_000 as Weight).saturating_mul(r as Weight)) + (49_594_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_890_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ne(r: u32, ) -> Weight { - (50_417_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_911_000 as Weight).saturating_mul(r as Weight)) + (49_659_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_894_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64lts(r: u32, ) -> Weight { - (50_358_000 as Weight) + (49_401_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_914_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_902_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ltu(r: u32, ) -> Weight { - (49_864_000 as Weight) + (49_880_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_928_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_885_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gts(r: u32, ) -> Weight { - (50_159_000 as Weight) + (49_466_000 as Weight) // Standard Error: 10_000 - .saturating_add((1_917_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_894_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gtu(r: u32, ) -> Weight { - (50_037_000 as Weight) - // Standard Error: 16_000 - .saturating_add((1_945_000 as Weight).saturating_mul(r as Weight)) + (49_514_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_891_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64les(r: u32, ) -> Weight { - (50_482_000 as Weight) + (49_588_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_909_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_898_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64leu(r: u32, ) -> Weight { - (50_426_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_908_000 as Weight).saturating_mul(r as Weight)) + (49_589_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_891_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ges(r: u32, ) -> Weight { - (50_205_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_918_000 as Weight).saturating_mul(r as Weight)) + (49_685_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_892_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64geu(r: u32, ) -> Weight { - (50_189_000 as Weight) - // Standard Error: 12_000 - .saturating_add((1_928_000 as Weight).saturating_mul(r as Weight)) + (49_601_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_891_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64add(r: u32, ) -> Weight { - (50_205_000 as Weight) - // Standard Error: 12_000 - .saturating_add((1_922_000 as Weight).saturating_mul(r as Weight)) + (49_430_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_894_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64sub(r: u32, ) -> Weight { - (50_375_000 as Weight) - // Standard Error: 15_000 - .saturating_add((1_929_000 as Weight).saturating_mul(r as Weight)) + (49_533_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_893_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64mul(r: u32, ) -> Weight { - (50_343_000 as Weight) - // Standard Error: 12_000 - .saturating_add((1_916_000 as Weight).saturating_mul(r as Weight)) + (49_766_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_888_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divs(r: u32, ) -> Weight { - (50_707_000 as Weight) + (49_315_000 as Weight) // Standard Error: 11_000 - .saturating_add((2_667_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_552_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divu(r: u32, ) -> Weight { - (50_318_000 as Weight) + (49_786_000 as Weight) // Standard Error: 11_000 - .saturating_add((2_408_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_203_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rems(r: u32, ) -> Weight { - (50_214_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_702_000 as Weight).saturating_mul(r as Weight)) + (49_651_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_461_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64remu(r: u32, ) -> Weight { - (50_394_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_411_000 as Weight).saturating_mul(r as Weight)) + (49_747_000 as Weight) + // Standard Error: 10_000 + .saturating_add((2_196_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64and(r: u32, ) -> Weight { - (50_397_000 as Weight) + (49_719_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_910_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_892_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64or(r: u32, ) -> Weight { - (50_291_000 as Weight) - // Standard Error: 12_000 - .saturating_add((1_915_000 as Weight).saturating_mul(r as Weight)) + (49_463_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_896_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64xor(r: u32, ) -> Weight { - (50_684_000 as Weight) - // Standard Error: 12_000 + (49_379_000 as Weight) + // Standard Error: 11_000 .saturating_add((1_903_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shl(r: u32, ) -> Weight { - (49_638_000 as Weight) - // Standard Error: 17_000 - .saturating_add((1_967_000 as Weight).saturating_mul(r as Weight)) + (49_404_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_902_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shrs(r: u32, ) -> Weight { - (50_817_000 as Weight) - // Standard Error: 12_000 - .saturating_add((1_899_000 as Weight).saturating_mul(r as Weight)) + (49_498_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_900_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shru(r: u32, ) -> Weight { - (50_987_000 as Weight) - // Standard Error: 12_000 - .saturating_add((1_899_000 as Weight).saturating_mul(r as Weight)) + (49_541_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_897_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotl(r: u32, ) -> Weight { - (50_885_000 as Weight) - // Standard Error: 12_000 - .saturating_add((1_905_000 as Weight).saturating_mul(r as Weight)) + (49_452_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_900_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotr(r: u32, ) -> Weight { - (50_465_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_908_000 as Weight).saturating_mul(r as Weight)) + (49_350_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_902_000 as Weight).saturating_mul(r as Weight)) } } From 617c36e0ab32cd593822d2dedacfb3d7dff9160c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Sat, 8 Jan 2022 17:13:54 +0100 Subject: [PATCH 363/695] frame-support: Use logging for printing corrupted state (#10612) `runtime_print!` is printed by default using `debug`, aka not being visible. With `log::error!` it will be printed directly to the user. Production networks like Polkadot disable logging, but for them we run special nodes that have logging enabled. --- frame/support/src/storage/child.rs | 5 +++-- frame/support/src/storage/unhashed.rs | 6 +++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/frame/support/src/storage/child.rs b/frame/support/src/storage/child.rs index a0a673d4b041..949df84e7e76 100644 --- a/frame/support/src/storage/child.rs +++ b/frame/support/src/storage/child.rs @@ -34,8 +34,9 @@ pub fn get(child_info: &ChildInfo, key: &[u8]) -> Option { sp_io::default_child_storage::get(storage_key, key).and_then(|v| { Decode::decode(&mut &v[..]).map(Some).unwrap_or_else(|_| { // TODO #3700: error should be handleable. - crate::runtime_print!( - "ERROR: Corrupted state in child trie at {:?}/{:?}", + log::error!( + target: "runtime::storage", + "Corrupted state in child trie at {:?}/{:?}", storage_key, key, ); diff --git a/frame/support/src/storage/unhashed.rs b/frame/support/src/storage/unhashed.rs index 5e0b527acd13..96bccc6ae0fe 100644 --- a/frame/support/src/storage/unhashed.rs +++ b/frame/support/src/storage/unhashed.rs @@ -25,7 +25,11 @@ pub fn get(key: &[u8]) -> Option { sp_io::storage::get(key).and_then(|val| { Decode::decode(&mut &val[..]).map(Some).unwrap_or_else(|_| { // TODO #3700: error should be handleable. - crate::runtime_print!("ERROR: Corrupted state at {:?}", key); + log::error!( + target: "runtime::storage", + "Corrupted state at {:?}", + key, + ); None }) }) From 42bac6770ea83ba1efe34e9677ccb2720031b312 Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Sun, 9 Jan 2022 10:03:21 +0100 Subject: [PATCH 364/695] Add Ord implementation for BoundedVec (#10615) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add Ord implementation for BoundedVec * Update frame/support/src/storage/bounded_vec.rs * Update frame/support/src/storage/bounded_vec.rs * Update frame/support/src/storage/bounded_vec.rs * Update frame/support/src/storage/bounded_vec.rs Co-authored-by: Bastian Köcher --- frame/support/src/storage/bounded_vec.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/frame/support/src/storage/bounded_vec.rs b/frame/support/src/storage/bounded_vec.rs index bdac8f23d7c9..9f43d37a2d7f 100644 --- a/frame/support/src/storage/bounded_vec.rs +++ b/frame/support/src/storage/bounded_vec.rs @@ -57,6 +57,18 @@ impl<'a, T: Encode + Decode, S: Get> EncodeLike> } impl<'a, T: Encode + Decode, S: Get> EncodeLike> for BoundedSlice<'a, T, S> {} +impl> PartialOrd for BoundedVec { + fn partial_cmp(&self, other: &Self) -> Option { + self.0.partial_cmp(&other.0) + } +} + +impl> Ord for BoundedVec { + fn cmp(&self, other: &Self) -> sp_std::cmp::Ordering { + self.0.cmp(&other.0) + } +} + impl<'a, T, S: Get> TryFrom<&'a [T]> for BoundedSlice<'a, T, S> { type Error = (); fn try_from(t: &'a [T]) -> Result { @@ -545,4 +557,15 @@ pub mod test { let b2: BoundedVec = vec![1, 2, 3].try_into().unwrap(); assert_eq!(b1, b2); } + + #[test] + fn ord_works() { + use std::cmp::Ordering; + let b1: BoundedVec> = vec![1, 2, 3].try_into().unwrap(); + let b2: BoundedVec> = vec![1, 3, 2].try_into().unwrap(); + + // ordering for vec is lexicographic. + assert_eq!(b1.cmp(&b2), Ordering::Less); + assert_eq!(b1.cmp(&b2), b1.into_inner().cmp(&b2.into_inner())); + } } From c623d1764638c44a85c7cb5417c32f5305884a24 Mon Sep 17 00:00:00 2001 From: Alex Pozhylenkov Date: Sun, 9 Jan 2022 21:12:21 +0200 Subject: [PATCH 365/695] add into function for PrefixIterator (#10614) * add into function for PrefixIterator * update with comments * update with comments --- frame/support/src/storage/mod.rs | 13 +++++++ .../support/src/storage/types/counted_map.rs | 36 +++---------------- 2 files changed, 17 insertions(+), 32 deletions(-) diff --git a/frame/support/src/storage/mod.rs b/frame/support/src/storage/mod.rs index 04876895dc49..e50577697a60 100644 --- a/frame/support/src/storage/mod.rs +++ b/frame/support/src/storage/mod.rs @@ -802,6 +802,19 @@ pub struct PrefixIterator { phantom: core::marker::PhantomData, } +impl PrefixIterator { + /// Converts to the same iterator but with the different 'OnRemoval' type + pub fn convert_on_removal(self) -> PrefixIterator { + PrefixIterator:: { + prefix: self.prefix, + previous_key: self.previous_key, + drain: self.drain, + closure: self.closure, + phantom: Default::default(), + } + } +} + /// Trait for specialising on removal logic of [`PrefixIterator`]. pub trait PrefixIteratorOnRemoval { /// This function is called whenever a key/value is removed. diff --git a/frame/support/src/storage/types/counted_map.rs b/frame/support/src/storage/types/counted_map.rs index 99d645fba329..341dedaef0ba 100644 --- a/frame/support/src/storage/types/counted_map.rs +++ b/frame/support/src/storage/types/counted_map.rs @@ -285,14 +285,7 @@ where /// /// NOTE: If a value failed to decode because storage is corrupted then it is skipped. pub fn iter_values() -> crate::storage::PrefixIterator> { - let map_iterator = ::Map::iter_values(); - crate::storage::PrefixIterator { - prefix: map_iterator.prefix, - previous_key: map_iterator.previous_key, - drain: map_iterator.drain, - closure: map_iterator.closure, - phantom: Default::default(), - } + ::Map::iter_values().convert_on_removal() } /// Translate the values of all elements by a function `f`, in the map in no particular order. @@ -374,28 +367,14 @@ where /// /// If you alter the map while doing this, you'll get undefined results. pub fn iter() -> crate::storage::PrefixIterator<(Key, Value), OnRemovalCounterUpdate> { - let map_iterator = ::Map::iter(); - crate::storage::PrefixIterator { - prefix: map_iterator.prefix, - previous_key: map_iterator.previous_key, - drain: map_iterator.drain, - closure: map_iterator.closure, - phantom: Default::default(), - } + ::Map::iter().convert_on_removal() } /// Remove all elements from the map and iterate through them in no particular order. /// /// If you add elements to the map while doing this, you'll get undefined results. pub fn drain() -> crate::storage::PrefixIterator<(Key, Value), OnRemovalCounterUpdate> { - let map_iterator = ::Map::drain(); - crate::storage::PrefixIterator { - prefix: map_iterator.prefix, - previous_key: map_iterator.previous_key, - drain: map_iterator.drain, - closure: map_iterator.closure, - phantom: Default::default(), - } + ::Map::drain().convert_on_removal() } /// Translate the values of all elements by a function `f`, in the map in no particular order. @@ -420,14 +399,7 @@ where pub fn iter_from( starting_raw_key: Vec, ) -> crate::storage::PrefixIterator<(Key, Value), OnRemovalCounterUpdate> { - let map_iterator = ::Map::iter_from(starting_raw_key); - crate::storage::PrefixIterator { - prefix: map_iterator.prefix, - previous_key: map_iterator.previous_key, - drain: map_iterator.drain, - closure: map_iterator.closure, - phantom: Default::default(), - } + ::Map::iter_from(starting_raw_key).convert_on_removal() } } From b54c21f354fd973e6a35a53c37b317ae293dbfc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Sun, 9 Jan 2022 20:48:24 +0100 Subject: [PATCH 366/695] code-substitute: Switch from `block_hash` to `block_number` (#10600) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * code-substitute: Switch from `block_hash` to `block_number` This will make it easier for light clients to work with the code-substitute. For more information on this see: https://github.com/paritytech/substrate/issues/10589 Closes: https://github.com/paritytech/substrate/issues/10589 * FMT * Update client/service/src/client/wasm_substitutes.rs Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> * Update client/service/src/builder.rs Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> --- client/chain-spec/src/chain_spec.rs | 6 +-- client/service/src/builder.rs | 16 +++---- client/service/src/client/client.rs | 2 +- client/service/src/client/wasm_substitutes.rs | 46 ++++--------------- 4 files changed, 20 insertions(+), 50 deletions(-) diff --git a/client/chain-spec/src/chain_spec.rs b/client/chain-spec/src/chain_spec.rs index 59d3ac351381..a22a68d2944f 100644 --- a/client/chain-spec/src/chain_spec.rs +++ b/client/chain-spec/src/chain_spec.rs @@ -176,10 +176,10 @@ struct ClientSpec { #[serde(skip_serializing)] #[allow(unused)] genesis: serde::de::IgnoredAny, - /// Mapping from `block_hash` to `wasm_code`. + /// Mapping from `block_number` to `wasm_code`. /// - /// The given `wasm_code` will be used to substitute the on-chain wasm code from the given - /// block hash onwards. + /// The given `wasm_code` will be used to substitute the on-chain wasm code starting with the + /// given block number until the `spec_version` on chain changes. #[serde(default)] code_substitutes: BTreeMap, } diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index c713b4936c6b..269b7be720be 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -57,7 +57,7 @@ use sp_core::traits::{CodeExecutor, SpawnNamed}; use sp_keystore::{CryptoStore, SyncCryptoStore, SyncCryptoStorePtr}; use sp_runtime::{ generic::BlockId, - traits::{Block as BlockT, BlockIdTo, Zero}, + traits::{Block as BlockT, BlockIdTo, NumberFor, Zero}, BuildStorage, }; use std::{str::FromStr, sync::Arc, time::SystemTime}; @@ -227,7 +227,6 @@ pub fn new_full_client( where TBl: BlockT, TExec: CodeExecutor + RuntimeVersionOf + Clone, - TBl::Hash: FromStr, { new_full_parts(config, telemetry, executor).map(|parts| parts.0) } @@ -241,7 +240,6 @@ pub fn new_full_parts( where TBl: BlockT, TExec: CodeExecutor + RuntimeVersionOf + Clone, - TBl::Hash: FromStr, { let keystore_container = KeystoreContainer::new(&config.keystore)?; @@ -281,14 +279,16 @@ where .chain_spec .code_substitutes() .into_iter() - .map(|(h, c)| { - let hash = TBl::Hash::from_str(&h).map_err(|_| { + .map(|(n, c)| { + let number = NumberFor::::from_str(&n).map_err(|_| { Error::Application(Box::from(format!( - "Failed to parse `{}` as block hash for code substitutes.", - h + "Failed to parse `{}` as block number for code substitutes. \ + In an old version the key for code substitute was a block hash. \ + Please update the chain spec to a version that is compatible with your node.", + n ))) })?; - Ok((hash, c)) + Ok((number, c)) }) .collect::, Error>>()?; diff --git a/client/service/src/client/client.rs b/client/service/src/client/client.rs index 9d898c7d1eb8..8769865978bf 100644 --- a/client/service/src/client/client.rs +++ b/client/service/src/client/client.rs @@ -194,7 +194,7 @@ pub struct ClientConfig { pub no_genesis: bool, /// Map of WASM runtime substitute starting at the child of the given block until the runtime /// version doesn't match anymore. - pub wasm_runtime_substitutes: HashMap>, + pub wasm_runtime_substitutes: HashMap, Vec>, } impl Default for ClientConfig { diff --git a/client/service/src/client/wasm_substitutes.rs b/client/service/src/client/wasm_substitutes.rs index 6f9a6dff43c7..a45eefb7b603 100644 --- a/client/service/src/client/wasm_substitutes.rs +++ b/client/service/src/client/wasm_substitutes.rs @@ -18,7 +18,6 @@ //! # WASM substitutes -use parking_lot::RwLock; use sc_client_api::backend; use sc_executor::RuntimeVersionOf; use sp_blockchain::{HeaderBackend, Result}; @@ -40,21 +39,14 @@ use std::{ struct WasmSubstitute { code: Vec, hash: Vec, - /// The hash of the block from that on we should use the substitute. - block_hash: Block::Hash, - /// The block number of `block_hash`. If `None`, the block is still unknown. - block_number: RwLock>>, + /// The block number on which we should start using the substitute. + block_number: NumberFor, } impl WasmSubstitute { - fn new( - code: Vec, - block_hash: Block::Hash, - backend: &impl backend::Backend, - ) -> Result { - let block_number = RwLock::new(backend.blockchain().number(block_hash)?); + fn new(code: Vec, block_number: NumberFor) -> Self { let hash = make_hash(&code); - Ok(Self { code, hash, block_hash, block_number }) + Self { code, hash, block_number } } fn runtime_code(&self, heap_pages: Option) -> RuntimeCode { @@ -63,32 +55,10 @@ impl WasmSubstitute { /// Returns `true` when the substitute matches for the given `block_id`. fn matches(&self, block_id: &BlockId, backend: &impl backend::Backend) -> bool { - let block_number = *self.block_number.read(); - let block_number = if let Some(block_number) = block_number { - block_number - } else { - let block_number = match backend.blockchain().number(self.block_hash) { - Ok(Some(n)) => n, - // still unknown - Ok(None) => return false, - Err(e) => { - log::debug!( - target: "wasm_substitutes", - "Failed to get block number for block hash {:?}: {:?}", - self.block_hash, - e, - ); - return false - }, - }; - *self.block_number.write() = Some(block_number); - block_number - }; - let requested_block_number = backend.blockchain().block_number_from_id(&block_id).ok().flatten(); - Some(block_number) <= requested_block_number + Some(self.block_number) <= requested_block_number } } @@ -145,14 +115,14 @@ where { /// Create a new instance. pub fn new( - substitutes: HashMap>, + substitutes: HashMap, Vec>, executor: Executor, backend: Arc, ) -> Result { let substitutes = substitutes .into_iter() - .map(|(parent_block_hash, code)| { - let substitute = WasmSubstitute::new(code, parent_block_hash, &*backend)?; + .map(|(block_number, code)| { + let substitute = WasmSubstitute::new(code, block_number); let version = Self::runtime_version(&executor, &substitute)?; Ok((version.spec_version, substitute)) }) From 15b154aea254d4f1fcd1bbe770b5eb593b9ff0b6 Mon Sep 17 00:00:00 2001 From: Joshy Orndorff Date: Mon, 10 Jan 2022 06:55:05 -0500 Subject: [PATCH 367/695] Manual Seal: Calculate the block's post hash (#10498) * calculate the post hash * Add test Co-authored-by: tgmichel --- client/consensus/manual-seal/src/lib.rs | 81 ++++++++++++++++++- .../consensus/manual-seal/src/seal_block.rs | 7 +- 2 files changed, 86 insertions(+), 2 deletions(-) diff --git a/client/consensus/manual-seal/src/lib.rs b/client/consensus/manual-seal/src/lib.rs index a057190f6b37..a8d2634ade56 100644 --- a/client/consensus/manual-seal/src/lib.rs +++ b/client/consensus/manual-seal/src/lib.rs @@ -253,7 +253,8 @@ mod tests { use sc_consensus::ImportedAux; use sc_transaction_pool::{BasicPool, Options, RevalidationType}; use sc_transaction_pool_api::{MaintainedTransactionPool, TransactionPool, TransactionSource}; - use sp_runtime::generic::BlockId; + use sp_inherents::InherentData; + use sp_runtime::generic::{BlockId, Digest, DigestItem}; use substrate_test_runtime_client::{ AccountKeyring::*, DefaultTestClientBuilderExt, TestClientBuilder, TestClientBuilderExt, }; @@ -265,6 +266,35 @@ mod tests { const SOURCE: TransactionSource = TransactionSource::External; + struct TestDigestProvider { + _client: Arc, + } + impl ConsensusDataProvider for TestDigestProvider + where + B: BlockT, + C: ProvideRuntimeApi + Send + Sync, + { + type Transaction = TransactionFor; + + fn create_digest( + &self, + _parent: &B::Header, + _inherents: &InherentData, + ) -> Result { + Ok(Digest { logs: vec![] }) + } + + fn append_block_import( + &self, + _parent: &B::Header, + params: &mut BlockImportParams, + _inherents: &InherentData, + ) -> Result<(), Error> { + params.post_digests.push(DigestItem::Other(vec![1])); + Ok(()) + } + } + #[tokio::test] async fn instant_seal() { let builder = TestClientBuilder::new(); @@ -519,4 +549,53 @@ mod tests { // assert that fork block is in the db assert!(client.header(&BlockId::Hash(imported.hash)).unwrap().is_some()) } + + #[tokio::test] + async fn manual_seal_post_hash() { + let builder = TestClientBuilder::new(); + let (client, select_chain) = builder.build_with_longest_chain(); + let client = Arc::new(client); + let spawner = sp_core::testing::TaskExecutor::new(); + let pool = Arc::new(BasicPool::with_revalidation_type( + Options::default(), + true.into(), + api(), + None, + RevalidationType::Full, + spawner.clone(), + 0, + )); + let env = ProposerFactory::new(spawner.clone(), client.clone(), pool.clone(), None, None); + + let (mut sink, commands_stream) = futures::channel::mpsc::channel(1024); + let future = run_manual_seal(ManualSealParams { + block_import: client.clone(), + env, + client: client.clone(), + pool: pool.clone(), + commands_stream, + select_chain, + // use a provider that pushes some post digest data + consensus_data_provider: Some(Box::new(TestDigestProvider { _client: client.clone() })), + create_inherent_data_providers: |_, _| async { Ok(()) }, + }); + std::thread::spawn(|| { + let rt = tokio::runtime::Runtime::new().unwrap(); + rt.block_on(future); + }); + let (tx, rx) = futures::channel::oneshot::channel(); + sink.send(EngineCommand::SealNewBlock { + parent_hash: None, + sender: Some(tx), + create_empty: true, + finalize: false, + }) + .await + .unwrap(); + let created_block = rx.await.unwrap().unwrap(); + + // assert that the background task returned the actual header hash + let header = client.header(&BlockId::Number(1)).unwrap().unwrap(); + assert_eq!(header.hash(), created_block.hash); + } } diff --git a/client/consensus/manual-seal/src/seal_block.rs b/client/consensus/manual-seal/src/seal_block.rs index ad840bd102b3..99b003c32f13 100644 --- a/client/consensus/manual-seal/src/seal_block.rs +++ b/client/consensus/manual-seal/src/seal_block.rs @@ -153,9 +153,14 @@ pub async fn seal_block( digest_provider.append_block_import(&parent, &mut params, &inherent_data)?; } + // Make sure we return the same post-hash that will be calculated when importing the block + // This is important in case the digest_provider added any signature, seal, ect. + let mut post_header = header.clone(); + post_header.digest_mut().logs.extend(params.post_digests.iter().cloned()); + match block_import.import_block(params, HashMap::new()).await? { ImportResult::Imported(aux) => - Ok(CreatedBlock { hash: ::Header::hash(&header), aux }), + Ok(CreatedBlock { hash: ::Header::hash(&post_header), aux }), other => Err(other.into()), } }; From 2cfd23559933eaf495fca4b8024cfaf5a98b7cd6 Mon Sep 17 00:00:00 2001 From: Seun Lanlege Date: Mon, 10 Jan 2022 15:39:04 +0100 Subject: [PATCH 368/695] Adds AuraConsensusDataProvider (#10503) * adds support for parachains to test-runner * adds file header * Apply suggestions from code review Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> * proper docs, remove unused _client * fixes * Update client/consensus/manual-seal/src/consensus/timestamp.rs Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> * Update client/consensus/manual-seal/src/consensus/timestamp.rs Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> * pr fixes Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> --- Cargo.lock | 69 +--- Cargo.toml | 2 - bin/node/test-runner-example/Cargo.toml | 29 -- bin/node/test-runner-example/src/lib.rs | 132 -------- client/consensus/aura/src/lib.rs | 15 +- client/consensus/manual-seal/Cargo.toml | 2 + client/consensus/manual-seal/src/consensus.rs | 2 + .../manual-seal/src/consensus/aura.rs | 97 ++++++ .../manual-seal/src/consensus/babe.rs | 79 +---- .../manual-seal/src/consensus/timestamp.rs | 156 +++++++++ client/consensus/manual-seal/src/error.rs | 1 - test-utils/test-runner/Cargo.toml | 59 ---- test-utils/test-runner/src/client.rs | 244 -------------- test-utils/test-runner/src/host_functions.rs | 53 --- test-utils/test-runner/src/lib.rs | 310 ------------------ test-utils/test-runner/src/node.rs | 278 ---------------- test-utils/test-runner/src/utils.rs | 118 ------- 17 files changed, 278 insertions(+), 1368 deletions(-) delete mode 100644 bin/node/test-runner-example/Cargo.toml delete mode 100644 bin/node/test-runner-example/src/lib.rs create mode 100644 client/consensus/manual-seal/src/consensus/aura.rs create mode 100644 client/consensus/manual-seal/src/consensus/timestamp.rs delete mode 100644 test-utils/test-runner/Cargo.toml delete mode 100644 test-utils/test-runner/src/client.rs delete mode 100644 test-utils/test-runner/src/host_functions.rs delete mode 100644 test-utils/test-runner/src/lib.rs delete mode 100644 test-utils/test-runner/src/node.rs delete mode 100644 test-utils/test-runner/src/utils.rs diff --git a/Cargo.lock b/Cargo.lock index e5192d2c8fe1..65b0897947f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7995,6 +7995,7 @@ dependencies = [ "sc-basic-authorship", "sc-client-api", "sc-consensus", + "sc-consensus-aura", "sc-consensus-babe", "sc-consensus-epochs", "sc-transaction-pool", @@ -8003,6 +8004,7 @@ dependencies = [ "sp-api", "sp-blockchain", "sp-consensus", + "sp-consensus-aura", "sp-consensus-babe", "sp-consensus-slots", "sp-core", @@ -10457,73 +10459,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "test-runner" -version = "0.9.0" -dependencies = [ - "frame-system", - "futures 0.3.16", - "jsonrpc-core", - "log 0.4.14", - "num-traits", - "sc-basic-authorship", - "sc-cli", - "sc-client-api", - "sc-consensus", - "sc-consensus-babe", - "sc-consensus-manual-seal", - "sc-executor", - "sc-finality-grandpa", - "sc-informant", - "sc-network", - "sc-rpc", - "sc-rpc-server", - "sc-service", - "sc-transaction-pool", - "sc-transaction-pool-api", - "sp-api", - "sp-block-builder", - "sp-blockchain", - "sp-consensus", - "sp-consensus-babe", - "sp-core", - "sp-externalities", - "sp-finality-grandpa", - "sp-inherents", - "sp-keyring", - "sp-offchain", - "sp-runtime", - "sp-runtime-interface", - "sp-session", - "sp-state-machine", - "sp-transaction-pool", - "sp-wasm-interface", - "tokio", -] - -[[package]] -name = "test-runner-example" -version = "0.1.0" -dependencies = [ - "frame-benchmarking", - "frame-system", - "node-cli", - "node-primitives", - "node-runtime", - "pallet-asset-tx-payment", - "pallet-transaction-payment", - "sc-consensus", - "sc-consensus-babe", - "sc-consensus-manual-seal", - "sc-executor", - "sc-finality-grandpa", - "sc-service", - "sp-consensus-babe", - "sp-keyring", - "sp-runtime", - "test-runner", -] - [[package]] name = "textwrap" version = "0.11.0" diff --git a/Cargo.toml b/Cargo.toml index 93f7d42c8238..b7051bdd44ef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,6 @@ members = [ "bin/node-template/runtime", "bin/node/bench", "bin/node/cli", - "bin/node/test-runner-example", "bin/node/executor", "bin/node/primitives", "bin/node/rpc", @@ -200,7 +199,6 @@ members = [ "test-utils/runtime", "test-utils/runtime/client", "test-utils/runtime/transaction-pool", - "test-utils/test-runner", "test-utils/test-crate", "utils/build-script-utils", "utils/fork-tree", diff --git a/bin/node/test-runner-example/Cargo.toml b/bin/node/test-runner-example/Cargo.toml deleted file mode 100644 index 831a68725440..000000000000 --- a/bin/node/test-runner-example/Cargo.toml +++ /dev/null @@ -1,29 +0,0 @@ -[package] -name = "test-runner-example" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -publish = false - -[dependencies] -test-runner = { path = "../../../test-utils/test-runner" } - -frame-system = { path = "../../../frame/system" } -frame-benchmarking = { path = "../../../frame/benchmarking" } -pallet-transaction-payment = { path = "../../../frame/transaction-payment" } -pallet-asset-tx-payment = { path = "../../../frame/transaction-payment/asset-tx-payment/" } - -node-runtime = { path = "../runtime" } -node-primitives = { path = "../primitives" } -node-cli = { path = "../cli" } - -grandpa = { package = "sc-finality-grandpa", path = "../../../client/finality-grandpa" } -sp-consensus-babe = { path = "../../../primitives/consensus/babe" } -sc-consensus-babe = { path = "../../../client/consensus/babe" } -sc-consensus-manual-seal = { path = "../../../client/consensus/manual-seal" } -sc-service = { default-features = false, path = "../../../client/service" } -sc-executor = { path = "../../../client/executor" } -sc-consensus = { path = "../../../client/consensus/common" } - -sp-runtime = { path = "../../../primitives/runtime" } -sp-keyring = { path = "../../../primitives/keyring" } diff --git a/bin/node/test-runner-example/src/lib.rs b/bin/node/test-runner-example/src/lib.rs deleted file mode 100644 index 8ac450ac12a1..000000000000 --- a/bin/node/test-runner-example/src/lib.rs +++ /dev/null @@ -1,132 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2021-2022 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 . -#![deny(unused_extern_crates, missing_docs)] - -//! Basic example of end to end runtime tests. - -use grandpa::GrandpaBlockImport; -use sc_consensus_babe::BabeBlockImport; -use sc_consensus_manual_seal::consensus::babe::SlotTimestampProvider; -use sc_executor::NativeElseWasmExecutor; -use sc_service::{TFullBackend, TFullClient}; -use sp_runtime::generic::Era; -use test_runner::{ChainInfo, SignatureVerificationOverride}; - -type BlockImport = BabeBlockImport>; - -/// A unit struct which implements `NativeExecutionDispatch` feeding in the -/// hard-coded runtime. -pub struct ExecutorDispatch; - -impl sc_executor::NativeExecutionDispatch for ExecutorDispatch { - type ExtendHostFunctions = - (frame_benchmarking::benchmarking::HostFunctions, SignatureVerificationOverride); - - fn dispatch(method: &str, data: &[u8]) -> Option> { - node_runtime::api::dispatch(method, data) - } - - fn native_version() -> sc_executor::NativeVersion { - node_runtime::native_version() - } -} - -/// ChainInfo implementation. -struct NodeTemplateChainInfo; - -impl ChainInfo for NodeTemplateChainInfo { - type Block = node_primitives::Block; - type ExecutorDispatch = ExecutorDispatch; - type Runtime = node_runtime::Runtime; - type RuntimeApi = node_runtime::RuntimeApi; - type SelectChain = sc_consensus::LongestChain, Self::Block>; - type BlockImport = BlockImport< - Self::Block, - TFullBackend, - TFullClient>, - Self::SelectChain, - >; - type SignedExtras = node_runtime::SignedExtra; - type InherentDataProviders = - (SlotTimestampProvider, sp_consensus_babe::inherents::InherentDataProvider); - - fn signed_extras( - from: ::AccountId, - ) -> Self::SignedExtras { - ( - frame_system::CheckNonZeroSender::::new(), - frame_system::CheckSpecVersion::::new(), - frame_system::CheckTxVersion::::new(), - frame_system::CheckGenesis::::new(), - frame_system::CheckMortality::::from(Era::Immortal), - frame_system::CheckNonce::::from( - frame_system::Pallet::::account_nonce(from), - ), - frame_system::CheckWeight::::new(), - pallet_asset_tx_payment::ChargeAssetTxPayment::::from(0, None), - ) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use node_cli::chain_spec::development_config; - use sp_keyring::sr25519::Keyring::Alice; - use sp_runtime::{traits::IdentifyAccount, MultiSigner}; - use test_runner::{build_runtime, client_parts, ConfigOrChainSpec, Node}; - - #[test] - fn test_runner() { - let tokio_runtime = build_runtime().unwrap(); - let (rpc, task_manager, client, pool, command_sink, backend) = - client_parts::(ConfigOrChainSpec::ChainSpec( - Box::new(development_config()), - tokio_runtime.handle().clone(), - )) - .unwrap(); - let node = Node::::new( - rpc, - task_manager, - client, - pool, - command_sink, - backend, - ); - - tokio_runtime.block_on(async { - // seals blocks - node.seal_blocks(1).await; - // submit extrinsics - let alice = MultiSigner::from(Alice.public()).into_account(); - let _hash = node - .submit_extrinsic( - frame_system::Call::remark { remark: (b"hello world").to_vec() }, - Some(alice), - ) - .await - .unwrap(); - - // look ma, I can read state. - let _events = - node.with_state(|| frame_system::Pallet::::events()); - // get access to the underlying client. - let _client = node.client(); - }) - } -} diff --git a/client/consensus/aura/src/lib.rs b/client/consensus/aura/src/lib.rs index 13f0d4e8f804..d7fe61313938 100644 --- a/client/consensus/aura/src/lib.rs +++ b/client/consensus/aura/src/lib.rs @@ -490,24 +490,34 @@ fn aura_err(error: Error) -> Error { error } +/// Aura Errors #[derive(derive_more::Display, Debug)] -enum Error { +pub enum Error { + /// Multiple Aura pre-runtime headers #[display(fmt = "Multiple Aura pre-runtime headers")] MultipleHeaders, + /// No Aura pre-runtime digest found #[display(fmt = "No Aura pre-runtime digest found")] NoDigestFound, + /// Header is unsealed #[display(fmt = "Header {:?} is unsealed", _0)] HeaderUnsealed(B::Hash), + /// Header has a bad seal #[display(fmt = "Header {:?} has a bad seal", _0)] HeaderBadSeal(B::Hash), + /// Slot Author not found #[display(fmt = "Slot Author not found")] SlotAuthorNotFound, + /// Bad signature #[display(fmt = "Bad signature on {:?}", _0)] BadSignature(B::Hash), + /// Client Error Client(sp_blockchain::Error), + /// Unknown inherent error for identifier #[display(fmt = "Unknown inherent error for identifier: {}", "String::from_utf8_lossy(_0)")] UnknownInherentError(sp_inherents::InherentIdentifier), #[display(fmt = "Inherent error: {}", _0)] + /// Inherents Error Inherent(sp_inherents::Error), } @@ -517,7 +527,8 @@ impl std::convert::From> for String { } } -fn find_pre_digest(header: &B::Header) -> Result> { +/// Get pre-digests from the header +pub fn find_pre_digest(header: &B::Header) -> Result> { if header.number().is_zero() { return Ok(0.into()) } diff --git a/client/consensus/manual-seal/Cargo.toml b/client/consensus/manual-seal/Cargo.toml index a4bb63a7a270..c55228abb527 100644 --- a/client/consensus/manual-seal/Cargo.toml +++ b/client/consensus/manual-seal/Cargo.toml @@ -27,8 +27,10 @@ async-trait = "0.1.50" sc-client-api = { path = "../../api", version = "4.0.0-dev" } sc-consensus = { version = "0.10.0-dev", path = "../../consensus/common" } sc-consensus-babe = { path = "../../consensus/babe", version = "0.10.0-dev" } +sc-consensus-aura = { path = "../../consensus/aura", version = "0.10.0-dev" } sc-consensus-epochs = { path = "../../consensus/epochs", version = "0.10.0-dev" } sp-consensus-babe = { path = "../../../primitives/consensus/babe", version = "0.10.0-dev" } +sp-consensus-aura = { path = "../../../primitives/consensus/aura", version = "0.10.0-dev" } sc-transaction-pool = { path = "../../transaction-pool", version = "4.0.0-dev" } sp-blockchain = { path = "../../../primitives/blockchain", version = "4.0.0-dev" } diff --git a/client/consensus/manual-seal/src/consensus.rs b/client/consensus/manual-seal/src/consensus.rs index 9bb1d2fe1fae..dfd3730fd342 100644 --- a/client/consensus/manual-seal/src/consensus.rs +++ b/client/consensus/manual-seal/src/consensus.rs @@ -23,7 +23,9 @@ use sc_consensus::BlockImportParams; use sp_inherents::InherentData; use sp_runtime::{traits::Block as BlockT, Digest}; +pub mod aura; pub mod babe; +pub mod timestamp; /// Consensus data provider, manual seal uses this trait object for authoring blocks valid /// for any runtime. diff --git a/client/consensus/manual-seal/src/consensus/aura.rs b/client/consensus/manual-seal/src/consensus/aura.rs new file mode 100644 index 000000000000..4497a94bdd42 --- /dev/null +++ b/client/consensus/manual-seal/src/consensus/aura.rs @@ -0,0 +1,97 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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 . + +//! Aura consensus data provider, This allows manual seal author blocks that are valid for +//! runtimes that expect the aura-specific digests. + +use crate::{ConsensusDataProvider, Error}; +use sc_client_api::{AuxStore, UsageProvider}; +use sc_consensus::BlockImportParams; +use sc_consensus_aura::slot_duration; +use sp_api::{ProvideRuntimeApi, TransactionFor}; +use sp_blockchain::{HeaderBackend, HeaderMetadata}; +use sp_consensus_aura::{ + digests::CompatibleDigestItem, + sr25519::{AuthorityId, AuthoritySignature}, + AuraApi, +}; +use sp_inherents::InherentData; +use sp_runtime::{traits::Block as BlockT, Digest, DigestItem}; +use sp_timestamp::TimestampInherentData; +use std::{marker::PhantomData, sync::Arc}; + +/// Consensus data provider for Aura. +pub struct AuraConsensusDataProvider { + // slot duration in milliseconds + slot_duration: u64, + // phantom data for required generics + _phantom: PhantomData<(B, C)>, +} + +impl AuraConsensusDataProvider +where + B: BlockT, + C: AuxStore + ProvideRuntimeApi + UsageProvider, + C::Api: AuraApi, +{ + /// Creates a new instance of the [`AuraConsensusDataProvider`], requires that `client` + /// implements [`sp_consensus_aura::AuraApi`] + pub fn new(client: Arc) -> Self { + let slot_duration = + (*slot_duration(&*client).expect("slot_duration is always present; qed.")).get(); + + Self { slot_duration, _phantom: PhantomData } + } +} + +impl ConsensusDataProvider for AuraConsensusDataProvider +where + B: BlockT, + C: AuxStore + + HeaderBackend + + HeaderMetadata + + UsageProvider + + ProvideRuntimeApi, + C::Api: AuraApi, +{ + type Transaction = TransactionFor; + + fn create_digest( + &self, + _parent: &B::Header, + inherents: &InherentData, + ) -> Result { + let time_stamp = + *inherents.timestamp_inherent_data()?.expect("Timestamp is always present; qed"); + // we always calculate the new slot number based on the current time-stamp and the slot + // duration. + let digest_item = >::aura_pre_digest( + (time_stamp / self.slot_duration).into(), + ); + Ok(Digest { logs: vec![digest_item] }) + } + + fn append_block_import( + &self, + _parent: &B::Header, + _params: &mut BlockImportParams, + _inherents: &InherentData, + ) -> Result<(), Error> { + Ok(()) + } +} diff --git a/client/consensus/manual-seal/src/consensus/babe.rs b/client/consensus/manual-seal/src/consensus/babe.rs index 6d86658cbf50..9c2a1638043a 100644 --- a/client/consensus/manual-seal/src/consensus/babe.rs +++ b/client/consensus/manual-seal/src/consensus/babe.rs @@ -16,7 +16,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -//! BABE consensus data provider +//! BABE consensus data provider, This allows manual seal author blocks that are valid for runtimes +//! that expect babe-specific digests. use super::ConsensusDataProvider; use crate::Error; @@ -30,11 +31,7 @@ use sc_consensus_epochs::{ descendent_query, EpochHeader, SharedEpochChanges, ViableEpochDescriptor, }; use sp_keystore::SyncCryptoStorePtr; -use std::{ - borrow::Cow, - sync::{atomic, Arc}, - time::SystemTime, -}; +use std::{borrow::Cow, sync::Arc}; use sc_consensus::{BlockImportParams, ForkChoiceStrategy, Verifier}; use sp_api::{ProvideRuntimeApi, TransactionFor}; @@ -46,13 +43,13 @@ use sp_consensus_babe::{ AuthorityId, BabeApi, BabeAuthorityWeight, ConsensusLog, BABE_ENGINE_ID, }; use sp_consensus_slots::Slot; -use sp_inherents::{InherentData, InherentDataProvider, InherentIdentifier}; +use sp_inherents::InherentData; use sp_runtime::{ generic::{BlockId, Digest}, - traits::{Block as BlockT, Header, Zero}, + traits::{Block as BlockT, Header}, DigestItem, }; -use sp_timestamp::{InherentType, TimestampInherentData, INHERENT_IDENTIFIER}; +use sp_timestamp::TimestampInherentData; /// Provides BABE-compatible predigests and BlockImportParams. /// Intended for use with BABE runtimes. @@ -311,67 +308,3 @@ where Ok(()) } } - -/// Provide duration since unix epoch in millisecond for timestamp inherent. -/// Mocks the timestamp inherent to always produce the timestamp for the next babe slot. -pub struct SlotTimestampProvider { - time: atomic::AtomicU64, - slot_duration: u64, -} - -impl SlotTimestampProvider { - /// Create a new mocked time stamp provider. - pub fn new(client: Arc) -> Result - where - B: BlockT, - C: AuxStore + HeaderBackend + ProvideRuntimeApi + UsageProvider, - C::Api: BabeApi, - { - let slot_duration = Config::get(&*client)?.slot_duration; - let info = client.info(); - - // looks like this isn't the first block, rehydrate the fake time. - // otherwise we'd be producing blocks for older slots. - let time = if info.best_number != Zero::zero() { - let header = client.header(BlockId::Hash(info.best_hash))?.unwrap(); - let slot = find_pre_digest::(&header).unwrap().slot(); - // add the slot duration so there's no collision of slots - (*slot * slot_duration) + slot_duration - } else { - // this is the first block, use the correct time. - let now = SystemTime::now(); - now.duration_since(SystemTime::UNIX_EPOCH) - .map_err(|err| Error::StringError(format!("{}", err)))? - .as_millis() as u64 - }; - - Ok(Self { time: atomic::AtomicU64::new(time), slot_duration }) - } - - /// Get the current slot number - pub fn slot(&self) -> u64 { - self.time.load(atomic::Ordering::SeqCst) / self.slot_duration - } -} - -#[async_trait::async_trait] -impl InherentDataProvider for SlotTimestampProvider { - fn provide_inherent_data( - &self, - inherent_data: &mut InherentData, - ) -> Result<(), sp_inherents::Error> { - // we update the time here. - let duration: InherentType = - self.time.fetch_add(self.slot_duration, atomic::Ordering::SeqCst).into(); - inherent_data.put_data(INHERENT_IDENTIFIER, &duration)?; - Ok(()) - } - - async fn try_handle_error( - &self, - _: &InherentIdentifier, - _: &[u8], - ) -> Option> { - None - } -} diff --git a/client/consensus/manual-seal/src/consensus/timestamp.rs b/client/consensus/manual-seal/src/consensus/timestamp.rs new file mode 100644 index 000000000000..908d218da05a --- /dev/null +++ b/client/consensus/manual-seal/src/consensus/timestamp.rs @@ -0,0 +1,156 @@ +// This file is part of Substrate. + +// Copyright (C) 2020-2021 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 . + +//! Mocked timestamp inherent, allows for manual seal to create blocks for runtimes +//! that expect this inherent. + +use crate::Error; +use sc_client_api::{AuxStore, UsageProvider}; +use sc_consensus_aura::slot_duration; +use sc_consensus_babe::Config; +use sp_api::ProvideRuntimeApi; +use sp_blockchain::HeaderBackend; +use sp_consensus_aura::{ + sr25519::{AuthorityId, AuthoritySignature}, + AuraApi, +}; +use sp_consensus_babe::BabeApi; +use sp_inherents::{InherentData, InherentDataProvider, InherentIdentifier}; +use sp_runtime::{ + generic::BlockId, + traits::{Block as BlockT, Zero}, +}; +use sp_timestamp::{InherentType, INHERENT_IDENTIFIER}; +use std::{ + sync::{atomic, Arc}, + time::SystemTime, +}; + +/// Provide duration since unix epoch in millisecond for timestamp inherent. +/// Mocks the timestamp inherent to always produce a valid timestamp for the next slot. +/// +/// This works by either fetching the `slot_number` from the most recent header and dividing +/// that value by `slot_duration` in order to fork chains that expect this inherent. +/// +/// It produces timestamp inherents that are increaed by `slot_duraation` whenever +/// `provide_inherent_data` is called. +pub struct SlotTimestampProvider { + // holds the unix millisecnd timestamp for the most recent block + unix_millis: atomic::AtomicU64, + // configured slot_duration in the runtime + slot_duration: u64, +} + +impl SlotTimestampProvider { + /// Create a new mocked time stamp provider, for babe. + pub fn new_babe(client: Arc) -> Result + where + B: BlockT, + C: AuxStore + HeaderBackend + ProvideRuntimeApi + UsageProvider, + C::Api: BabeApi, + { + let slot_duration = Config::get(&*client)?.slot_duration; + + let time = Self::with_header(&client, slot_duration, |header| { + let slot_number = *sc_consensus_babe::find_pre_digest::(&header) + .map_err(|err| format!("{}", err))? + .slot(); + Ok(slot_number) + })?; + + Ok(Self { unix_millis: atomic::AtomicU64::new(time), slot_duration }) + } + + /// Create a new mocked time stamp provider, for aura + pub fn new_aura(client: Arc) -> Result + where + B: BlockT, + C: AuxStore + HeaderBackend + ProvideRuntimeApi + UsageProvider, + C::Api: AuraApi, + { + let slot_duration = (*slot_duration(&*client)?).get(); + + let time = Self::with_header(&client, slot_duration, |header| { + let slot_number = *sc_consensus_aura::find_pre_digest::(&header) + .map_err(|err| format!("{}", err))?; + Ok(slot_number) + })?; + + Ok(Self { unix_millis: atomic::AtomicU64::new(time), slot_duration }) + } + + fn with_header(client: &Arc, slot_duration: u64, func: F) -> Result + where + B: BlockT, + C: AuxStore + HeaderBackend + UsageProvider, + F: Fn(B::Header) -> Result, + { + let info = client.info(); + + // looks like this isn't the first block, rehydrate the fake time. + // otherwise we'd be producing blocks for older slots. + let time = if info.best_number != Zero::zero() { + let header = client + .header(BlockId::Hash(info.best_hash))? + .ok_or_else(|| "best header not found in the db!".to_string())?; + let slot = func(header)?; + // add the slot duration so there's no collision of slots + (slot * slot_duration) + slot_duration + } else { + // this is the first block, use the correct time. + let now = SystemTime::now(); + now.duration_since(SystemTime::UNIX_EPOCH) + .map_err(|err| Error::StringError(format!("{}", err)))? + .as_millis() as u64 + }; + + Ok(time) + } + + /// Get the current slot number + pub fn slot(&self) -> u64 { + self.unix_millis.load(atomic::Ordering::SeqCst) / self.slot_duration + } + + /// Gets the current time stamp. + pub fn timestamp(&self) -> sp_timestamp::Timestamp { + sp_timestamp::Timestamp::new(self.unix_millis.load(atomic::Ordering::SeqCst)) + } +} + +#[async_trait::async_trait] +impl InherentDataProvider for SlotTimestampProvider { + fn provide_inherent_data( + &self, + inherent_data: &mut InherentData, + ) -> Result<(), sp_inherents::Error> { + // we update the time here. + let new_time: InherentType = + self.unix_millis.fetch_add(self.slot_duration, atomic::Ordering::SeqCst).into(); + inherent_data.put_data(INHERENT_IDENTIFIER, &new_time)?; + Ok(()) + } + + async fn try_handle_error( + &self, + _: &InherentIdentifier, + _: &[u8], + ) -> Option> { + None + } +} diff --git a/client/consensus/manual-seal/src/error.rs b/client/consensus/manual-seal/src/error.rs index 28f1a6aed35b..3a67b36bc62b 100644 --- a/client/consensus/manual-seal/src/error.rs +++ b/client/consensus/manual-seal/src/error.rs @@ -62,7 +62,6 @@ pub enum Error { BlockNotFound(String), /// Some string error #[display(fmt = "{}", _0)] - #[from(ignore)] StringError(String), /// send error #[display(fmt = "Consensus process is terminating")] diff --git a/test-utils/test-runner/Cargo.toml b/test-utils/test-runner/Cargo.toml deleted file mode 100644 index 78e17d0f23b6..000000000000 --- a/test-utils/test-runner/Cargo.toml +++ /dev/null @@ -1,59 +0,0 @@ -[package] -name = "test-runner" -version = "0.9.0" -authors = ["Parity Technologies "] -edition = "2021" -publish = false - -[dependencies] -# client deps -sc-executor = { path = "../../client/executor" } -sc-service = { path = "../../client/service" } -sc-informant = { path = "../../client/informant" } -sc-network = { path = "../../client/network" } -sc-cli = { path = "../../client/cli" } -sc-basic-authorship = { path = "../../client/basic-authorship" } -sc-rpc = { path = "../../client/rpc" } -sc-transaction-pool = { path = "../../client/transaction-pool" } -grandpa = { package = "sc-finality-grandpa", path = "../../client/finality-grandpa" } -sp-finality-grandpa = { path = "../../primitives/finality-grandpa" } -sp-consensus-babe = { path = "../../primitives/consensus/babe" } -sc-consensus-babe = { path = "../../client/consensus/babe" } -sc-consensus = { path = "../../client/consensus/common" } -sc-transaction-pool-api = { path = "../../client/transaction-pool/api" } -sc-client-api = { path = "../../client/api" } -sc-rpc-server = { path = "../../client/rpc-servers" } -manual-seal = { package = "sc-consensus-manual-seal", path = "../../client/consensus/manual-seal" } - -# primitive deps -sp-core = { path = "../../primitives/core" } -sp-blockchain = { path = "../../primitives/blockchain" } -sp-block-builder = { path = "../../primitives/block-builder" } -sp-api = { path = "../../primitives/api" } -sp-transaction-pool = { path = "../../primitives/transaction-pool" } -sp-consensus = { path = "../../primitives/consensus/common" } -sp-runtime = { path = "../../primitives/runtime" } -sp-session = { path = "../../primitives/session" } -sp-offchain = { path = "../../primitives/offchain" } -sp-inherents = { path = "../../primitives/inherents" } -sp-keyring = { path = "../../primitives/keyring" } - -sp-externalities = { path = "../../primitives/externalities" } -sp-state-machine = { path = "../../primitives/state-machine" } -sp-wasm-interface = { path = "../../primitives/wasm-interface" } -sp-runtime-interface = { path = "../../primitives/runtime-interface" } - -# pallets -frame-system = { path = "../../frame/system" } - -log = "0.4.8" -futures = "0.3.16" -tokio = { version = "1.15", features = ["signal"] } -# Calling RPC -jsonrpc-core = "18.0" -num-traits = "0.2.14" - -[features] -default = ["std"] -# This is here so that we can use the `runtime_interface` procedural macro -std = [] diff --git a/test-utils/test-runner/src/client.rs b/test-utils/test-runner/src/client.rs deleted file mode 100644 index 3fa3de3a87e0..000000000000 --- a/test-utils/test-runner/src/client.rs +++ /dev/null @@ -1,244 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2021-2022 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 . -//! Client parts -use crate::{default_config, ChainInfo}; -use futures::channel::mpsc; -use jsonrpc_core::MetaIoHandler; -use manual_seal::{ - consensus::babe::{BabeConsensusDataProvider, SlotTimestampProvider}, - import_queue, - rpc::{ManualSeal, ManualSealApi}, - run_manual_seal, EngineCommand, ManualSealParams, -}; -use sc_client_api::backend::Backend; -use sc_executor::NativeElseWasmExecutor; -use sc_service::{ - build_network, new_full_parts, spawn_tasks, BuildNetworkParams, ChainSpec, Configuration, - SpawnTasksParams, TFullBackend, TFullClient, TaskManager, -}; -use sc_transaction_pool::BasicPool; -use sc_transaction_pool_api::TransactionPool; -use sp_api::{ApiExt, ConstructRuntimeApi, Core, Metadata}; -use sp_block_builder::BlockBuilder; -use sp_consensus_babe::BabeApi; -use sp_finality_grandpa::GrandpaApi; -use sp_keyring::sr25519::Keyring::Alice; -use sp_offchain::OffchainWorkerApi; -use sp_runtime::traits::{Block as BlockT, Header}; -use sp_session::SessionKeys; -use sp_transaction_pool::runtime_api::TaggedTransactionQueue; -use std::{str::FromStr, sync::Arc}; - -type ClientParts = ( - Arc>, - TaskManager, - Arc< - TFullClient< - ::Block, - ::RuntimeApi, - NativeElseWasmExecutor<::ExecutorDispatch>, - >, - >, - Arc< - dyn TransactionPool< - Block = ::Block, - Hash = <::Block as BlockT>::Hash, - Error = sc_transaction_pool::error::Error, - InPoolTransaction = sc_transaction_pool::Transaction< - <::Block as BlockT>::Hash, - <::Block as BlockT>::Extrinsic, - >, - >, - >, - mpsc::Sender::Block as BlockT>::Hash>>, - Arc::Block>>, -); - -/// Provide the config or chain spec for a given chain -pub enum ConfigOrChainSpec { - /// Configuration object - Config(Configuration), - /// Chain spec object - ChainSpec(Box, tokio::runtime::Handle), -} -/// Creates all the client parts you need for [`Node`](crate::node::Node) -pub fn client_parts( - config_or_chain_spec: ConfigOrChainSpec, -) -> Result, sc_service::Error> -where - T: ChainInfo + 'static, - >, - >>::RuntimeApi: Core - + Metadata - + OffchainWorkerApi - + SessionKeys - + TaggedTransactionQueue - + BlockBuilder - + BabeApi - + ApiExt as Backend>::State> - + GrandpaApi, - ::Call: From>, - <::Block as BlockT>::Hash: FromStr + Unpin, - <::Block as BlockT>::Header: Unpin, - <<::Block as BlockT>::Header as Header>::Number: - num_traits::cast::AsPrimitive, -{ - use sp_consensus_babe::AuthorityId; - let config = match config_or_chain_spec { - ConfigOrChainSpec::Config(config) => config, - ConfigOrChainSpec::ChainSpec(chain_spec, tokio_handle) => - default_config(tokio_handle, chain_spec), - }; - - let executor = NativeElseWasmExecutor::::new( - config.wasm_method, - config.default_heap_pages, - config.max_runtime_instances, - config.runtime_cache_size, - ); - - let (client, backend, keystore, mut task_manager) = - new_full_parts::(&config, None, executor)?; - let client = Arc::new(client); - - let select_chain = sc_consensus::LongestChain::new(backend.clone()); - - let (grandpa_block_import, ..) = grandpa::block_import( - client.clone(), - &(client.clone() as Arc<_>), - select_chain.clone(), - None, - )?; - - let slot_duration = sc_consensus_babe::Config::get(&*client)?; - let (block_import, babe_link) = sc_consensus_babe::block_import( - slot_duration.clone(), - grandpa_block_import, - client.clone(), - )?; - - let consensus_data_provider = BabeConsensusDataProvider::new( - client.clone(), - keystore.sync_keystore(), - babe_link.epoch_changes().clone(), - vec![(AuthorityId::from(Alice.public()), 1000)], - ) - .expect("failed to create ConsensusDataProvider"); - - let import_queue = - import_queue(Box::new(block_import.clone()), &task_manager.spawn_essential_handle(), None); - - let transaction_pool = BasicPool::new_full( - config.transaction_pool.clone(), - true.into(), - config.prometheus_registry(), - task_manager.spawn_essential_handle(), - client.clone(), - ); - - let (network, system_rpc_tx, network_starter) = { - let params = BuildNetworkParams { - config: &config, - client: client.clone(), - transaction_pool: transaction_pool.clone(), - spawn_handle: task_manager.spawn_handle(), - import_queue, - block_announce_validator_builder: None, - warp_sync: None, - }; - build_network(params)? - }; - - // offchain workers - sc_service::build_offchain_workers( - &config, - task_manager.spawn_handle(), - client.clone(), - network.clone(), - ); - - // Proposer object for block authorship. - let env = sc_basic_authorship::ProposerFactory::new( - task_manager.spawn_handle(), - client.clone(), - transaction_pool.clone(), - config.prometheus_registry(), - None, - ); - - // Channel for the rpc handler to communicate with the authorship task. - let (command_sink, commands_stream) = mpsc::channel(10); - - let rpc_sink = command_sink.clone(); - - let rpc_handlers = { - let params = SpawnTasksParams { - config, - client: client.clone(), - backend: backend.clone(), - task_manager: &mut task_manager, - keystore: keystore.sync_keystore(), - transaction_pool: transaction_pool.clone(), - rpc_extensions_builder: Box::new(move |_, _| { - let mut io = jsonrpc_core::IoHandler::default(); - io.extend_with(ManualSealApi::to_delegate(ManualSeal::new(rpc_sink.clone()))); - Ok(io) - }), - network, - system_rpc_tx, - telemetry: None, - }; - spawn_tasks(params)? - }; - - let cloned_client = client.clone(); - let create_inherent_data_providers = Box::new(move |_, _| { - let client = cloned_client.clone(); - async move { - let timestamp = - SlotTimestampProvider::new(client.clone()).map_err(|err| format!("{:?}", err))?; - let babe = - sp_consensus_babe::inherents::InherentDataProvider::new(timestamp.slot().into()); - Ok((timestamp, babe)) - } - }); - - // Background authorship future. - let authorship_future = run_manual_seal(ManualSealParams { - block_import, - env, - client: client.clone(), - pool: transaction_pool.clone(), - commands_stream, - select_chain, - consensus_data_provider: Some(Box::new(consensus_data_provider)), - create_inherent_data_providers, - }); - - // spawn the authorship task as an essential task. - task_manager - .spawn_essential_handle() - .spawn("manual-seal", None, authorship_future); - - network_starter.start_network(); - let rpc_handler = rpc_handlers.io_handler(); - - Ok((rpc_handler, task_manager, client, transaction_pool, command_sink, backend)) -} diff --git a/test-utils/test-runner/src/host_functions.rs b/test-utils/test-runner/src/host_functions.rs deleted file mode 100644 index 8bc9597890d0..000000000000 --- a/test-utils/test-runner/src/host_functions.rs +++ /dev/null @@ -1,53 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2021-2022 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 . - -use sp_core::{ecdsa, ed25519, sr25519}; -use sp_runtime_interface::runtime_interface; - -#[runtime_interface] -trait Crypto { - fn ecdsa_verify(_sig: &ecdsa::Signature, _msg: &[u8], _pub_key: &ecdsa::Public) -> bool { - true - } - - #[version(2)] - fn ecdsa_verify(_sig: &ecdsa::Signature, _msg: &[u8], _pub_key: &ecdsa::Public) -> bool { - true - } - - fn ed25519_verify(_sig: &ed25519::Signature, _msg: &[u8], _pub_key: &ed25519::Public) -> bool { - true - } - - fn sr25519_verify(_sig: &sr25519::Signature, _msg: &[u8], _pub_key: &sr25519::Public) -> bool { - true - } - - #[version(2)] - fn sr25519_verify(_sig: &sr25519::Signature, _msg: &[u8], _pub_key: &sr25519::Public) -> bool { - true - } -} - -/// Provides host functions that overrides runtime signature verification -/// to always return true. -pub type SignatureVerificationOverride = crypto::HostFunctions; - -// This is here to get rid of the warnings. -#[allow(unused_imports, dead_code)] -use self::crypto::{ecdsa_verify, ed25519_verify, sr25519_verify}; diff --git a/test-utils/test-runner/src/lib.rs b/test-utils/test-runner/src/lib.rs deleted file mode 100644 index 19e437e26da4..000000000000 --- a/test-utils/test-runner/src/lib.rs +++ /dev/null @@ -1,310 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2021-2022 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 . -#![deny(missing_docs, unused_extern_crates)] - -//! Test runner -//! # Substrate Test Runner -//! -//! Allows you to test -//!
-//! -//! - Migrations -//! - Runtime Upgrades -//! - Pallets and general runtime functionality. -//! -//! This works by running a full node with a Manual Seal-BABE™ hybrid consensus for block authoring. -//! -//!

Note

-//! The running node has no signature verification, which allows us author extrinsics for any -//! account on chain.
-//!
-//! -//!

How do I Use this?

-//! -//! -//! ```rust,ignore -//! use test_runner::{Node, ChainInfo, SignatureVerificationOverride, base_path, NodeConfig}; -//! use sc_finality_grandpa::GrandpaBlockImport; -//! use sc_service::{ -//! TFullBackend, TFullClient, Configuration, TaskManager, new_full_parts, BasePath, -//! DatabaseSource, KeepBlocks, TransactionStorageMode, ChainSpec, Role, -//! config::{NetworkConfiguration, KeystoreConfig}, -//! }; -//! use std::sync::Arc; -//! use sp_inherents::InherentDataProviders; -//! use sc_consensus_babe::BabeBlockImport; -//! use sp_keystore::SyncCryptoStorePtr; -//! use sp_keyring::sr25519::Keyring::{Alice, Bob}; -//! use node_cli::chain_spec::development_config; -//! use sp_consensus_babe::AuthorityId; -//! use manual_seal::{ConsensusDataProvider, consensus::babe::BabeConsensusDataProvider}; -//! use sp_runtime::{traits::IdentifyAccount, MultiSigner, generic::Era}; -//! use sc_executor::WasmExecutionMethod; -//! use sc_network::{multiaddr, config::TransportConfig}; -//! use sc_client_api::execution_extensions::ExecutionStrategies; -//! use sc_informant::OutputFormat; -//! use sp_api::TransactionFor; -//! -//! type BlockImport = BabeBlockImport>; -//! -//! pub struct ExecutorDispatch; -//! -//! impl sc_executor::NativeExecutionDispatch for ExecutorDispatch { -//! type ExtendHostFunctions = SignatureVerificationOverride; -//! -//! fn dispatch(method: &str, data: &[u8]) -> Option> { -//! node_runtime::api::dispatch(method, data) -//! } -//! -//! fn native_version() -> sc_executor::NativeVersion { -//! node_runtime::native_version() -//! } -//! } -//! -//! struct Requirements; -//! -//! impl ChainInfo for Requirements { -//! /// Provide a Block type with an OpaqueExtrinsic -//! type Block = node_primitives::Block; -//! /// Provide an ExecutorDispatch type for the runtime -//! type ExecutorDispatch = ExecutorDispatch; -//! /// Provide the runtime itself -//! type Runtime = node_runtime::Runtime; -//! /// A touch of runtime api -//! type RuntimeApi = node_runtime::RuntimeApi; -//! /// A pinch of SelectChain implementation -//! type SelectChain = sc_consensus::LongestChain, Self::Block>; -//! /// A slice of concrete BlockImport type -//! type BlockImport = BlockImport< -//! Self::Block, -//! TFullBackend, -//! TFullClient>, -//! Self::SelectChain, -//! >; -//! /// and a dash of SignedExtensions -//! type SignedExtras = node_runtime::SignedExtra; -//! -//! /// Create your signed extras here. -//! fn signed_extras( -//! from: ::AccountId, -//! ) -> Self::SignedExtension { -//! let nonce = frame_system::Pallet::::account_nonce(from); -//! -//! ( -//! frame_system::CheckNonZeroSender::::new(), -//! frame_system::CheckSpecVersion::::new(), -//! frame_system::CheckTxVersion::::new(), -//! frame_system::CheckGenesis::::new(), -//! frame_system::CheckMortality::::from(Era::Immortal), -//! frame_system::CheckNonce::::from(nonce), -//! frame_system::CheckWeight::::new(), -//! pallet_transaction_payment::ChargeTransactionPayment::::from(0), -//! ) -//! } -//! -//! /// The function signature tells you all you need to know. ;) -//! fn create_client_parts(config: &Configuration) -> Result< -//! ( -//! Arc>>, -//! Arc>, -//! KeyStorePtr, -//! TaskManager, -//! InherentDataProviders, -//! Option>, -//! Self::Block -//! >, -//! > -//! >>, -//! Self::SelectChain, -//! Self::BlockImport -//! ), -//! sc_service::Error -//! > { -//! let ( -//! client, -//! backend, -//! keystore, -//! task_manager, -//! ) = new_full_parts::>(config)?; -//! let client = Arc::new(client); -//! -//! let inherent_providers = InherentDataProviders::new(); -//! let select_chain = sc_consensus::LongestChain::new(backend.clone()); -//! -//! let (grandpa_block_import, ..) = -//! sc_finality_grandpa::block_import(client.clone(), &(client.clone() as Arc<_>), select_chain.clone())?; -//! -//! let (block_import, babe_link) = sc_consensus_babe::block_import( -//! sc_consensus_babe::Config::get(&*client)?, -//! grandpa_block_import, -//! client.clone(), -//! )?; -//! -//! let consensus_data_provider = BabeConsensusDataProvider::new( -//! client.clone(), -//! keystore.clone(), -//! &inherent_providers, -//! babe_link.epoch_changes().clone(), -//! vec![(AuthorityId::from(Alice.public()), 1000)] -//! ) -//! .expect("failed to create ConsensusDataProvider"); -//! -//! Ok(( -//! client, -//! backend, -//! keystore, -//! task_manager, -//! inherent_providers, -//! Some(Box::new(consensus_data_provider)), -//! select_chain, -//! block_import -//! )) -//! } -//! -//! fn dispatch_with_root(call: ::Call, node: &mut Node) { -//! let alice = MultiSigner::from(Alice.public()).into_account(); -//! // for chains that support sudo, otherwise, you'd have to use pallet-democracy here. -//! let call = pallet_sudo::Call::sudo(Box::new(call)); -//! node.submit_extrinsic(call, alice); -//! node.seal_blocks(1); -//! } -//! } -//! -//! /// And now for the most basic test -//! -//! #[test] -//! fn simple_balances_test() { -//! // given -//! let config = NodeConfig { -//! execution_strategies: ExecutionStrategies { -//! syncing: sc_client_api::ExecutionStrategy::NativeWhenPossible, -//! importing: sc_client_api::ExecutionStrategy::NativeWhenPossible, -//! block_construction: sc_client_api::ExecutionStrategy::NativeWhenPossible, -//! offchain_worker: sc_client_api::ExecutionStrategy::NativeWhenPossible, -//! other: sc_client_api::ExecutionStrategy::NativeWhenPossible, -//! }, -//! chain_spec: Box::new(development_config()), -//! log_targets: vec![], -//! }; -//! let mut node = Node::::new(config).unwrap(); -//! -//! type Balances = pallet_balances::Pallet; -//! -//! let (alice, bob) = (Alice.pair(), Bob.pair()); -//! let (alice_account_id, bob_acount_id) = ( -//! MultiSigner::from(alice.public()).into_account(), -//! MultiSigner::from(bob.public()).into_account() -//! ); -//! -//! /// the function with_state allows us to read state, pretty cool right? :D -//! let old_balance = node.with_state(|| Balances::free_balance(alice_account_id.clone())); -//! -//! // 70 dots -//! let amount = 70_000_000_000_000; -//! -//! /// Send extrinsic in action. -//! node.submit_extrinsic(BalancesCall::transfer(bob_acount_id.clone(), amount), alice_account_id.clone()); -//! -//! /// Produce blocks in action, Powered by manual-seal™. -//! node.seal_blocks(1); -//! -//! /// we can check the new state :D -//! let new_balance = node.with_state(|| Balances::free_balance(alice_account_id)); -//! -//! /// we can now make assertions on how state has changed. -//! assert_eq!(old_balance + amount, new_balance); -//! } -//! ``` - -use sc_consensus::BlockImport; -use sc_executor::{NativeElseWasmExecutor, NativeExecutionDispatch}; -use sc_service::TFullClient; -use sp_api::{ConstructRuntimeApi, TransactionFor}; -use sp_consensus::SelectChain; -use sp_inherents::InherentDataProvider; -use sp_runtime::traits::{Block as BlockT, SignedExtension}; - -mod client; -mod host_functions; -mod node; -mod utils; - -pub use client::*; -pub use host_functions::*; -pub use node::*; -pub use utils::*; - -/// Wrapper trait for concrete type required by this testing framework. -pub trait ChainInfo: Sized { - /// Opaque block type - type Block: BlockT; - - /// ExecutorDispatch dispatch type - type ExecutorDispatch: NativeExecutionDispatch + 'static; - - /// Runtime - type Runtime: frame_system::Config; - - /// RuntimeApi - type RuntimeApi: Send - + Sync - + 'static - + ConstructRuntimeApi< - Self::Block, - TFullClient< - Self::Block, - Self::RuntimeApi, - NativeElseWasmExecutor, - >, - >; - - /// select chain type. - type SelectChain: SelectChain + 'static; - - /// Block import type. - type BlockImport: Send - + Sync - + Clone - + BlockImport< - Self::Block, - Error = sp_consensus::Error, - Transaction = TransactionFor< - TFullClient< - Self::Block, - Self::RuntimeApi, - NativeElseWasmExecutor, - >, - Self::Block, - >, - > + 'static; - - /// The signed extras required by the runtime - type SignedExtras: SignedExtension; - - /// The inherent data providers. - type InherentDataProviders: InherentDataProvider + 'static; - - /// Signed extras, this function is caled in an externalities provided environment. - fn signed_extras( - from: ::AccountId, - ) -> Self::SignedExtras; -} diff --git a/test-utils/test-runner/src/node.rs b/test-utils/test-runner/src/node.rs deleted file mode 100644 index f122e48d5392..000000000000 --- a/test-utils/test-runner/src/node.rs +++ /dev/null @@ -1,278 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2021-2022 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 . - -use std::sync::Arc; - -use crate::ChainInfo; -use futures::{ - channel::{mpsc, oneshot}, - FutureExt, SinkExt, -}; -use jsonrpc_core::MetaIoHandler; -use manual_seal::EngineCommand; -use sc_client_api::{backend::Backend, CallExecutor, ExecutorProvider}; -use sc_executor::NativeElseWasmExecutor; -use sc_service::{TFullBackend, TFullCallExecutor, TFullClient, TaskManager}; -use sc_transaction_pool_api::TransactionPool; -use sp_api::{OverlayedChanges, StorageTransactionCache}; -use sp_blockchain::HeaderBackend; -use sp_core::ExecutionContext; -use sp_runtime::{ - generic::{BlockId, UncheckedExtrinsic}, - traits::{Block as BlockT, Extrinsic, Header, NumberFor}, - transaction_validity::TransactionSource, - MultiAddress, MultiSignature, -}; -use sp_state_machine::Ext; - -/// This holds a reference to a running node on another thread, -/// the node process is dropped when this struct is dropped -/// also holds logs from the process. -pub struct Node { - /// rpc handler for communicating with the node over rpc. - rpc_handler: Arc>, - /// handle to the running node. - task_manager: Option, - /// client instance - client: Arc>>, - /// transaction pool - pool: Arc< - dyn TransactionPool< - Block = ::Block, - Hash = <::Block as BlockT>::Hash, - Error = sc_transaction_pool::error::Error, - InPoolTransaction = sc_transaction_pool::Transaction< - <::Block as BlockT>::Hash, - <::Block as BlockT>::Extrinsic, - >, - >, - >, - /// channel to communicate with manual seal on. - manual_seal_command_sink: mpsc::Sender::Hash>>, - /// backend type. - backend: Arc>, - /// Block number at initialization of this Node. - initial_block_number: NumberFor, -} - -type EventRecord = frame_system::EventRecord< - ::Event, - ::Hash, ->; - -impl Node -where - T: ChainInfo, - <::Header as Header>::Number: From, -{ - /// Creates a new node. - pub fn new( - rpc_handler: Arc>, - task_manager: TaskManager, - client: Arc< - TFullClient>, - >, - pool: Arc< - dyn TransactionPool< - Block = ::Block, - Hash = <::Block as BlockT>::Hash, - Error = sc_transaction_pool::error::Error, - InPoolTransaction = sc_transaction_pool::Transaction< - <::Block as BlockT>::Hash, - <::Block as BlockT>::Extrinsic, - >, - >, - >, - command_sink: mpsc::Sender::Hash>>, - backend: Arc>, - ) -> Self { - Self { - rpc_handler, - task_manager: Some(task_manager), - client: client.clone(), - pool, - backend, - manual_seal_command_sink: command_sink, - initial_block_number: client.info().best_number, - } - } - - /// Returns a reference to the rpc handlers, use this to send rpc requests. - /// eg - /// ```ignore - /// let request = r#"{"jsonrpc":"2.0","method":"engine_createBlock","params": [true, true],"id":1}"#; - /// let response = node.rpc_handler() - /// .handle_request_sync(request, Default::default()); - /// ``` - pub fn rpc_handler( - &self, - ) -> Arc> { - self.rpc_handler.clone() - } - - /// Return a reference to the Client - pub fn client( - &self, - ) -> Arc>> { - self.client.clone() - } - - /// Return a reference to the pool. - pub fn pool( - &self, - ) -> Arc< - dyn TransactionPool< - Block = ::Block, - Hash = <::Block as BlockT>::Hash, - Error = sc_transaction_pool::error::Error, - InPoolTransaction = sc_transaction_pool::Transaction< - <::Block as BlockT>::Hash, - <::Block as BlockT>::Extrinsic, - >, - >, - > { - self.pool.clone() - } - - /// Executes closure in an externalities provided environment. - pub fn with_state(&self, closure: impl FnOnce() -> R) -> R - where - > as CallExecutor>::Error: - std::fmt::Debug, - { - let id = BlockId::Hash(self.client.info().best_hash); - let mut overlay = OverlayedChanges::default(); - let mut cache = StorageTransactionCache::< - T::Block, - as Backend>::State, - >::default(); - let mut extensions = self - .client - .execution_extensions() - .extensions(&id, ExecutionContext::BlockConstruction); - let state_backend = self - .backend - .state_at(id.clone()) - .expect(&format!("State at block {} not found", id)); - - let mut ext = Ext::new(&mut overlay, &mut cache, &state_backend, Some(&mut extensions)); - sp_externalities::set_and_run_with_externalities(&mut ext, closure) - } - - /// submit some extrinsic to the node. if signer is None, will submit unsigned_extrinsic. - pub async fn submit_extrinsic( - &self, - call: impl Into<::Call>, - signer: Option<::AccountId>, - ) -> Result<::Hash, sc_transaction_pool::error::Error> - where - ::Extrinsic: From< - UncheckedExtrinsic< - MultiAddress< - ::AccountId, - ::Index, - >, - ::Call, - MultiSignature, - T::SignedExtras, - >, - >, - { - let signed_data = if let Some(signer) = signer { - let extra = self.with_state(|| T::signed_extras(signer.clone())); - Some(( - signer.into(), - MultiSignature::Sr25519(sp_core::sr25519::Signature::from_raw([0u8; 64])), - extra, - )) - } else { - None - }; - let ext = UncheckedExtrinsic::< - MultiAddress< - ::AccountId, - ::Index, - >, - ::Call, - MultiSignature, - T::SignedExtras, - >::new(call.into(), signed_data) - .expect("UncheckedExtrinsic::new() always returns Some"); - let at = self.client.info().best_hash; - - self.pool - .submit_one(&BlockId::Hash(at), TransactionSource::Local, ext.into()) - .await - } - - /// Get the events of the most recently produced block - pub fn events(&self) -> Vec> { - self.with_state(|| frame_system::Pallet::::events()) - } - - /// Instructs manual seal to seal new, possibly empty blocks. - pub async fn seal_blocks(&self, num: usize) { - let mut sink = self.manual_seal_command_sink.clone(); - - for count in 0..num { - let (sender, future_block) = oneshot::channel(); - let future = sink.send(EngineCommand::SealNewBlock { - create_empty: true, - finalize: false, - parent_hash: None, - sender: Some(sender), - }); - - const ERROR: &'static str = "manual-seal authorship task is shutting down"; - future.await.expect(ERROR); - - match future_block.await.expect(ERROR) { - Ok(block) => { - log::info!("sealed {} (hash: {}) of {} blocks", count + 1, block.hash, num) - }, - Err(err) => { - log::error!("failed to seal block {} of {}, error: {:?}", count + 1, num, err) - }, - } - } - } - - /// Revert count number of blocks from the chain. - pub fn revert_blocks(&self, count: NumberFor) { - self.backend.revert(count, true).expect("Failed to revert blocks: "); - } - - /// so you've decided to run the test runner as a binary, use this to shutdown gracefully. - pub async fn until_shutdown(mut self) { - let manager = self.task_manager.take(); - if let Some(mut task_manager) = manager { - let task = task_manager.future().fuse(); - let signal = tokio::signal::ctrl_c(); - futures::pin_mut!(signal); - futures::future::select(task, signal).await; - } - } -} - -impl Drop for Node { - fn drop(&mut self) { - // Revert all blocks added since creation of the node. - let diff = self.client.info().best_number - self.initial_block_number; - self.revert_blocks(diff); - } -} diff --git a/test-utils/test-runner/src/utils.rs b/test-utils/test-runner/src/utils.rs deleted file mode 100644 index 452dc600e4ae..000000000000 --- a/test-utils/test-runner/src/utils.rs +++ /dev/null @@ -1,118 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2020-2022 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 . - -use sc_client_api::execution_extensions::ExecutionStrategies; -use sc_executor::WasmExecutionMethod; -use sc_informant::OutputFormat; -use sc_network::{ - config::{NetworkConfiguration, Role, TransportConfig}, - multiaddr, -}; -use sc_service::{ - config::KeystoreConfig, BasePath, ChainSpec, Configuration, DatabaseSource, KeepBlocks, - TransactionStorageMode, -}; -use sp_keyring::sr25519::Keyring::Alice; -use tokio::runtime::Handle; - -pub use sc_cli::build_runtime; - -/// Base db path gotten from env -pub fn base_path() -> BasePath { - if let Some(base) = std::env::var("DB_BASE_PATH").ok() { - BasePath::new(base) - } else { - BasePath::new_temp_dir().expect("couldn't create a temp dir") - } -} - -/// Produces a default configuration object, suitable for use with most set ups. -pub fn default_config(tokio_handle: Handle, mut chain_spec: Box) -> Configuration { - let base_path = base_path(); - let root_path = base_path.path().to_path_buf().join("chains").join(chain_spec.id()); - - let storage = chain_spec - .as_storage_builder() - .build_storage() - .expect("could not build storage"); - - chain_spec.set_storage(storage); - let key_seed = Alice.to_seed(); - - let mut network_config = NetworkConfiguration::new( - format!("Test Node for: {}", key_seed), - "network/test/0.1", - Default::default(), - None, - ); - let informant_output_format = OutputFormat { enable_color: false }; - network_config.allow_non_globals_in_dht = true; - - network_config.listen_addresses.push(multiaddr::Protocol::Memory(0).into()); - - network_config.transport = TransportConfig::MemoryOnly; - - Configuration { - impl_name: "test-node".to_string(), - impl_version: "0.1".to_string(), - role: Role::Authority, - tokio_handle, - transaction_pool: Default::default(), - network: network_config, - keystore: KeystoreConfig::Path { path: root_path.join("key"), password: None }, - database: DatabaseSource::RocksDb { path: root_path.join("db"), cache_size: 128 }, - state_cache_size: 16777216, - state_cache_child_ratio: None, - chain_spec, - wasm_method: WasmExecutionMethod::Interpreted, - execution_strategies: ExecutionStrategies { - syncing: sc_client_api::ExecutionStrategy::AlwaysWasm, - importing: sc_client_api::ExecutionStrategy::AlwaysWasm, - block_construction: sc_client_api::ExecutionStrategy::AlwaysWasm, - offchain_worker: sc_client_api::ExecutionStrategy::AlwaysWasm, - other: sc_client_api::ExecutionStrategy::AlwaysWasm, - }, - rpc_http: None, - rpc_ws: None, - rpc_ipc: None, - rpc_ws_max_connections: None, - rpc_cors: None, - rpc_methods: Default::default(), - rpc_max_payload: None, - ws_max_out_buffer_capacity: None, - prometheus_config: None, - telemetry_endpoints: None, - default_heap_pages: None, - offchain_worker: Default::default(), - force_authoring: false, - disable_grandpa: false, - dev_key_seed: Some(key_seed), - tracing_targets: None, - tracing_receiver: Default::default(), - max_runtime_instances: 8, - announce_block: true, - base_path: Some(base_path), - wasm_runtime_overrides: None, - informant_output_format, - keystore_remote: None, - keep_blocks: KeepBlocks::All, - state_pruning: Default::default(), - transaction_storage: TransactionStorageMode::BlockBody, - runtime_cache_size: 2, - } -} From daa411864031bb19ebf66521b2780b786e60799e Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Tue, 11 Jan 2022 04:18:30 +0100 Subject: [PATCH 369/695] frame/bench-cli: fix log formatting (#10627) Signed-off-by: Oliver Tale-Yazdi --- utils/frame/benchmarking-cli/src/command.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/utils/frame/benchmarking-cli/src/command.rs b/utils/frame/benchmarking-cli/src/command.rs index bd103862fe2c..368b5ce59c95 100644 --- a/utils/frame/benchmarking-cli/src/command.rs +++ b/utils/frame/benchmarking-cli/src/command.rs @@ -333,14 +333,14 @@ impl BenchmarkCmd { if elapsed >= time::Duration::from_secs(5) { timer = time::SystemTime::now(); log::info!( - "Running Benchmark:\t{}\t{}\t{}/{}\t{}/{}", + "Running Benchmark: {}.{} {}/{} {}/{}", String::from_utf8(pallet.clone()) .expect("Encoded from String; qed"), String::from_utf8(extrinsic.clone()) .expect("Encoded from String; qed"), - s, // todo show step + s + 1, // s starts at 0. todo show step self.steps, - r, + r + 1, self.external_repeat, ); } From 835a8b0fe194c62dbf35d4b2d52237e52fad66ba Mon Sep 17 00:00:00 2001 From: Vladimir Istyufeev Date: Tue, 11 Jan 2022 13:29:35 +0300 Subject: [PATCH 370/695] Remove the `bench-test-full-crypto-feature` GHA & GitLab jobs (#10628) * Remove the `bench-test-full-crypto-feature` job * Remove the relevant GHA job --- .github/workflows/bench_gh_gl.yaml | 75 ------------------------------ .gitlab-ci.yml | 29 ------------ 2 files changed, 104 deletions(-) delete mode 100644 .github/workflows/bench_gh_gl.yaml diff --git a/.github/workflows/bench_gh_gl.yaml b/.github/workflows/bench_gh_gl.yaml deleted file mode 100644 index b243f7f66141..000000000000 --- a/.github/workflows/bench_gh_gl.yaml +++ /dev/null @@ -1,75 +0,0 @@ -# Please do not tamper with this job, it's a part of benchmarking experiment. -# However, you absolutely can copy it into another file and redo the last job in the pipeline. -# Just make sure you won't introduce long queues to the GHA runner, we have just one at the moment. - -name: bench GHA against GitLab - -on: - push: - branches: [ master ] - -jobs: - bench_gh: - runs-on: self-hosted - env: - CARGO_INCREMENTAL: 0 - RUSTUP_HOME: /usr/local/rustup - CARGO_HOME: /usr/local/cargo - CC: clang - CXX: clang - - steps: - - - name: Cancel Previous Runs - uses: styfle/cancel-workflow-action@0.9.1 - with: - access_token: ${{ github.token }} - - - name: Install dependencies - # Template job, one can copy it to another pipeline. - run: | - apt-get update - apt-get install -y --no-install-recommends time clang - update-alternatives --install /usr/bin/cc cc /usr/bin/clang 100 - - - name: Install Rust - # Template job, one can copy it to another pipeline. - # Referance code https://github.com/paritytech/scripts/blob/master/dockerfiles/base-ci-linux/Dockerfile - # Better keep Rust versions here in sync with the CI image, otherwise the results will conflict. - run: | - curl -L "https://static.rust-lang.org/rustup/dist/x86_64-unknown-linux-gnu/rustup-init" -o rustup-init - chmod +x rustup-init - ./rustup-init -y --no-modify-path --profile minimal --default-toolchain stable - rm rustup-init - # add rustup tp PATH so it's usable right away - echo "/usr/local/cargo/bin" >> $GITHUB_PATH - source /usr/local/cargo/env - chmod -R a+w ${RUSTUP_HOME} ${CARGO_HOME} - # install nightly toolchain - rustup toolchain install nightly-2021-11-08 --profile minimal --component rustfmt clippy - # link the pinned toolchain to nightly - ln -s /usr/local/rustup/toolchains/nightly-2021-11-08-x86_64-unknown-linux-gnu /usr/local/rustup/toolchains/nightly-x86_64-unknown-linux-gnu - rustup target add wasm32-unknown-unknown - rustup target add wasm32-unknown-unknown --toolchain nightly - # show versions - rustup show - cargo --version - # remove clutter from the installations - rm -rf "${CARGO_HOME}/registry" "${CARGO_HOME}/git" - - - name: Checkout sources - uses: actions/checkout@v2 - - - name: bench-GHA-test-full-crypto-feature - # GitHub env variables reference: https://docs.github.com/en/actions/learn-github-actions/environment-variables - # The important part of the experiment is the line with `curl`: it sends the job's timing to Prometheus. - run: | - START_TIME=`date '+%s'` - cd primitives/core/ - time cargo +nightly build --verbose --no-default-features --features full_crypto - cd ../application-crypto - time cargo +nightly build --verbose --no-default-features --features full_crypto - END_TIME=`date '+%s'` - TOTAL_TIME=`expr $END_TIME - $START_TIME` - # please remove this line if you want to play with GHA runner. - curl -d "parity_github_job_time{project=\"$GITHUB_REPOSITORY\",job=\"$GITHUB_WORKFLOW\",runner=\"github\"} $TOTAL_TIME" -X POST http://vm-longterm.parity-build.parity.io/api/v1/import/prometheus diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2aee053ef4de..19d3f63dc5fe 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -520,35 +520,6 @@ test-full-crypto-feature: - time cargo +nightly build --verbose --no-default-features --features full_crypto - sccache -s - -# Mostly same as the job above, additional instrumentation was added to push test run times -# to the time series database. -# This is temporary and will be eventually removed. -bench-test-full-crypto-feature: - stage: test - <<: *docker-env - <<: *build-refs - variables: - <<: *default-vars - RUSTFLAGS: "-Cdebug-assertions=y" - RUST_BACKTRACE: 1 - before_script: [""] - script: - # disable sccache for the bench purposes - - unset RUSTC_WRAPPER - - START_TIME=`date '+%s'` - - cd primitives/core/ - - time cargo +nightly build --verbose --no-default-features --features full_crypto - - cd ../application-crypto - - time cargo +nightly build --verbose --no-default-features --features full_crypto - - END_TIME=`date '+%s'` - - TOTAL_TIME=`expr $END_TIME - $START_TIME` - # send the job time measuring to the prometheus endpoint - - curl -d "parity_gitlab_job_time{project=\"$CI_PROJECT_PATH\",job=\"$CI_JOB_NAME\",runner=\"gitlab\"} $TOTAL_TIME" -X POST $VM_LONGTERM_URI/api/v1/import/prometheus - tags: - - linux-docker-compare - - test-wasmer-sandbox: stage: test <<: *docker-env From 004412194a73741866b9fedc9931a69e6f21de34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Paulo=20Silva=20de=20Souza?= <77391175+joao-paulo-parity@users.noreply.github.com> Date: Tue, 11 Jan 2022 08:29:42 -0300 Subject: [PATCH 371/695] delete process.json (#10629) The feature was removed in https://github.com/paritytech/parity-processbot/pull/358 --- Process.json | 29 ----------------------------- 1 file changed, 29 deletions(-) delete mode 100644 Process.json diff --git a/Process.json b/Process.json deleted file mode 100644 index 540bd644311c..000000000000 --- a/Process.json +++ /dev/null @@ -1,29 +0,0 @@ -[{ - "project_name": "Networking", - "owner": "tomaka", - "matrix_room_id": "!vUADSGcyXmxhKLeDsW:matrix.parity.io" -}, -{ "project_name": "Client", - "owner": "gnunicorn", - "matrix_room_id": "!aenJixaHcSKbJOWxYk:matrix.parity.io" -}, -{ - "project_name": "Runtime", - "owner": "gavofyork", - "matrix_room_id": "!yBKstWVBkwzUkPslsp:matrix.parity.io" -}, -{ - "project_name": "Consensus", - "owner": "andresilva", - "matrix_room_id": "!XdNWDTfVNFVixljKZU:matrix.parity.io" -}, -{ - "project_name": "Smart Contracts", - "owner": "pepyakin", - "matrix_room_id": "!yBKstWVBkwzUkPslsp:matrix.parity.io" -}, -{ - "project_name": "Benchmarking and Weights", - "owner": "shawntabrizi", - "matrix_room_id": "!pZPWqCRLVtORZTEsEf:matrix.parity.io" -}] From a6b79439ae95ba4e673c1b733881dcab85885522 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Tue, 11 Jan 2022 15:22:27 +0100 Subject: [PATCH 372/695] pallet-lottery: add generate_storage_info (#10594) * pallet-lottery: add generate_storage_info Signed-off-by: Oliver Tale-Yazdi * pallet-lottery: test call_to_indices with TooManyCalls Signed-off-by: Oliver Tale-Yazdi * review: move try_push above transfer Signed-off-by: Oliver Tale-Yazdi * pallet-lottery: test stop_repeat Signed-off-by: Oliver Tale-Yazdi * pallet-lottery: test do_buy_ticket as white-box Signed-off-by: Oliver Tale-Yazdi * pallet-lottery: use BoundedVec in bechmarks Signed-off-by: Oliver Tale-Yazdi * pallet-lottery: fix zero div panic Signed-off-by: Oliver Tale-Yazdi * review: extend buy_ticket tests Signed-off-by: Oliver Tale-Yazdi * review: test buy_ticket AlreadyParticipating Signed-off-by: Oliver Tale-Yazdi * fmt Signed-off-by: Oliver Tale-Yazdi * review: use /// comments on private functions Signed-off-by: Oliver Tale-Yazdi * review: use with_bounded_capacity Signed-off-by: Oliver Tale-Yazdi --- frame/lottery/src/benchmarking.rs | 11 +- frame/lottery/src/lib.rs | 77 ++++++++----- frame/lottery/src/tests.rs | 179 +++++++++++++++++++++++++++++- 3 files changed, 235 insertions(+), 32 deletions(-) diff --git a/frame/lottery/src/benchmarking.rs b/frame/lottery/src/benchmarking.rs index f4a8e88e5e3f..1c850e66f9c6 100644 --- a/frame/lottery/src/benchmarking.rs +++ b/frame/lottery/src/benchmarking.rs @@ -22,7 +22,10 @@ use super::*; use frame_benchmarking::{account, benchmarks, whitelisted_caller}; -use frame_support::traits::{EnsureOrigin, OnInitialize}; +use frame_support::{ + storage::bounded_vec::BoundedVec, + traits::{EnsureOrigin, OnInitialize}, +}; use frame_system::RawOrigin; use sp_runtime::traits::{Bounded, Zero}; @@ -55,12 +58,12 @@ benchmarks! { let set_code_index: CallIndex = Lottery::::call_to_index( &frame_system::Call::::set_code{ code: vec![] }.into() )?; - let already_called: (u32, Vec) = ( + let already_called: (u32, BoundedVec) = ( LotteryIndex::::get(), - vec![ + BoundedVec::::try_from(vec![ set_code_index; T::MaxCalls::get().saturating_sub(1) as usize - ], + ]).unwrap(), ); Participants::::insert(&caller, already_called); diff --git a/frame/lottery/src/lib.rs b/frame/lottery/src/lib.rs index 5a985094dd1c..b04dbc845568 100644 --- a/frame/lottery/src/lib.rs +++ b/frame/lottery/src/lib.rs @@ -28,7 +28,7 @@ //! users to make those calls on your network. An example of how this could be //! used is to set validator nominations as a valid lottery call. If the lottery //! is set to repeat every month, then users would be encouraged to re-nominate -//! validators every month. A user can ony purchase one ticket per valid call +//! validators every month. A user can only purchase one ticket per valid call //! per lottery. //! //! This pallet can be configured to use dynamically set calls or statically set @@ -58,6 +58,8 @@ use codec::{Decode, Encode}; use frame_support::{ dispatch::{DispatchResult, Dispatchable, GetDispatchInfo}, ensure, + pallet_prelude::MaxEncodedLen, + storage::bounded_vec::BoundedVec, traits::{Currency, ExistenceRequirement::KeepAlive, Get, Randomness, ReservableCurrency}, PalletId, RuntimeDebug, }; @@ -76,7 +78,9 @@ type BalanceOf = // We use this to uniquely match someone's incoming call with the calls configured for the lottery. type CallIndex = (u8, u8); -#[derive(Encode, Decode, Default, Eq, PartialEq, RuntimeDebug, scale_info::TypeInfo)] +#[derive( + Encode, Decode, Default, Eq, PartialEq, RuntimeDebug, scale_info::TypeInfo, MaxEncodedLen, +)] pub struct LotteryConfig { /// Price per entry. price: Balance, @@ -120,6 +124,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::generate_storage_info] pub struct Pallet(_); /// The pallet's config trait. @@ -209,8 +214,13 @@ pub mod pallet { /// Users who have purchased a ticket. (Lottery Index, Tickets Purchased) #[pallet::storage] - pub(crate) type Participants = - StorageMap<_, Twox64Concat, T::AccountId, (u32, Vec), ValueQuery>; + pub(crate) type Participants = StorageMap< + _, + Twox64Concat, + T::AccountId, + (u32, BoundedVec), + ValueQuery, + >; /// Total number of tickets sold. #[pallet::storage] @@ -226,7 +236,8 @@ pub mod pallet { /// The calls stored in this pallet to be used in an active lottery if configured /// by `Config::ValidateCall`. #[pallet::storage] - pub(crate) type CallIndices = StorageValue<_, Vec, ValueQuery>; + pub(crate) type CallIndices = + StorageValue<_, BoundedVec, ValueQuery>; #[pallet::hooks] impl Hooks> for Pallet { @@ -237,10 +248,8 @@ pub mod pallet { config.start.saturating_add(config.length).saturating_add(config.delay); if payout_block <= n { let (lottery_account, lottery_balance) = Self::pot(); - let ticket_count = TicketsCount::::get(); - let winning_number = Self::choose_winner(ticket_count); - let winner = Tickets::::get(winning_number).unwrap_or(lottery_account); + let winner = Self::choose_account().unwrap_or(lottery_account); // Not much we can do if this fails... let res = T::Currency::transfer( &Self::account_id(), @@ -385,7 +394,7 @@ impl Pallet { } /// Return the pot account and amount of money in the pot. - // The existential deposit is not part of the pot so lottery account never gets deleted. + /// The existential deposit is not part of the pot so lottery account never gets deleted. fn pot() -> (T::AccountId, BalanceOf) { let account_id = Self::account_id(); let balance = @@ -394,17 +403,19 @@ impl Pallet { (account_id, balance) } - // Converts a vector of calls into a vector of call indices. - fn calls_to_indices(calls: &[::Call]) -> Result, DispatchError> { - let mut indices = Vec::with_capacity(calls.len()); + /// Converts a vector of calls into a vector of call indices. + fn calls_to_indices( + calls: &[::Call], + ) -> Result, DispatchError> { + let mut indices = BoundedVec::::with_bounded_capacity(calls.len()); for c in calls.iter() { let index = Self::call_to_index(c)?; - indices.push(index) + indices.try_push(index).map_err(|_| Error::::TooManyCalls)?; } Ok(indices) } - // Convert a call to it's call index by encoding the call and taking the first two bytes. + /// Convert a call to it's call index by encoding the call and taking the first two bytes. fn call_to_index(call: &::Call) -> Result { let encoded_call = call.encode(); if encoded_call.len() < 2 { @@ -413,7 +424,7 @@ impl Pallet { return Ok((encoded_call[0], encoded_call[1])) } - // Logic for buying a ticket. + /// Logic for buying a ticket. fn do_buy_ticket(caller: &T::AccountId, call: &::Call) -> DispatchResult { // Check the call is valid lottery let config = Lottery::::get().ok_or(Error::::NotConfigured)?; @@ -433,7 +444,7 @@ impl Pallet { let index = LotteryIndex::::get(); // If lottery index doesn't match, then reset participating calls and index. if *lottery_index != index { - *participating_calls = Vec::new(); + *participating_calls = Default::default(); *lottery_index = index; } else { // Check that user is not already participating under this call. @@ -442,12 +453,12 @@ impl Pallet { Error::::AlreadyParticipating ); } + participating_calls.try_push(call_index).map_err(|_| Error::::TooManyCalls)?; // Check user has enough funds and send it to the Lottery account. T::Currency::transfer(caller, &Self::account_id(), config.price, KeepAlive)?; // Create a new ticket. TicketsCount::::put(new_ticket_count); Tickets::::insert(ticket_count, caller.clone()); - participating_calls.push(call_index); Ok(()) }, )?; @@ -457,8 +468,22 @@ impl Pallet { Ok(()) } - // Randomly choose a winner from among the total number of participants. - fn choose_winner(total: u32) -> u32 { + /// Randomly choose a winning ticket and return the account that purchased it. + /// The more tickets an account bought, the higher are its chances of winning. + /// Returns `None` if there is no winner. + fn choose_account() -> Option { + match Self::choose_ticket(TicketsCount::::get()) { + None => None, + Some(ticket) => Tickets::::get(ticket), + } + } + + /// Randomly choose a winning ticket from among the total number of tickets. + /// Returns `None` if there are no tickets. + fn choose_ticket(total: u32) -> Option { + if total == 0 { + return None + } let mut random_number = Self::generate_random_number(0); // Best effort attempt to remove bias from modulus operator. @@ -470,15 +495,15 @@ impl Pallet { random_number = Self::generate_random_number(i); } - random_number % total + Some(random_number % total) } - // Generate a random number from a given seed. - // Note that there is potential bias introduced by using modulus operator. - // You should call this function with different seed values until the random - // number lies within `u32::MAX - u32::MAX % n`. - // TODO: deal with randomness freshness - // https://github.com/paritytech/substrate/issues/8311 + /// Generate a random number from a given seed. + /// Note that there is potential bias introduced by using modulus operator. + /// You should call this function with different seed values until the random + /// number lies within `u32::MAX - u32::MAX % n`. + /// TODO: deal with randomness freshness + /// https://github.com/paritytech/substrate/issues/8311 fn generate_random_number(seed: u32) -> u32 { let (random_seed, _) = T::Randomness::random(&(T::PalletId::get(), seed).encode()); let random_number = ::decode(&mut random_seed.as_ref()) diff --git a/frame/lottery/src/tests.rs b/frame/lottery/src/tests.rs index 143a4b052877..d8dd6e4b7fe6 100644 --- a/frame/lottery/src/tests.rs +++ b/frame/lottery/src/tests.rs @@ -18,7 +18,7 @@ //! Tests for the module. use super::*; -use frame_support::{assert_noop, assert_ok}; +use frame_support::{assert_noop, assert_ok, assert_storage_noop}; use mock::{ new_test_ext, run_to_block, Balances, BalancesCall, Call, Lottery, Origin, SystemCall, Test, }; @@ -30,7 +30,7 @@ fn initial_state() { new_test_ext().execute_with(|| { assert_eq!(Balances::free_balance(Lottery::account_id()), 0); assert!(crate::Lottery::::get().is_none()); - assert_eq!(Participants::::get(&1), (0, vec![])); + assert_eq!(Participants::::get(&1), (0, Default::default())); assert_eq!(TicketsCount::::get(), 0); assert!(Tickets::::get(0).is_none()); }); @@ -90,6 +90,37 @@ fn basic_end_to_end_works() { }); } +/// Only the manager can stop the Lottery from repeating via `stop_repeat`. +#[test] +fn stop_repeat_works() { + new_test_ext().execute_with(|| { + let price = 10; + let length = 20; + let delay = 5; + + // Set no calls for the lottery. + assert_ok!(Lottery::set_calls(Origin::root(), vec![])); + // Start lottery, it repeats. + assert_ok!(Lottery::start_lottery(Origin::root(), price, length, delay, true)); + + // Non-manager fails to `stop_repeat`. + assert_noop!(Lottery::stop_repeat(Origin::signed(1)), DispatchError::BadOrigin); + // Manager can `stop_repeat`, even twice. + assert_ok!(Lottery::stop_repeat(Origin::root())); + assert_ok!(Lottery::stop_repeat(Origin::root())); + + // Lottery still exists. + assert!(crate::Lottery::::get().is_some()); + // End and pick a winner. + run_to_block(length + delay); + + // Lottery stays dead and does not repeat. + assert!(crate::Lottery::::get().is_none()); + run_to_block(length + delay + 1); + assert!(crate::Lottery::::get().is_none()); + }); +} + #[test] fn set_calls_works() { new_test_ext().execute_with(|| { @@ -120,6 +151,27 @@ fn set_calls_works() { }); } +#[test] +fn call_to_indices_works() { + new_test_ext().execute_with(|| { + let calls = vec![ + Call::Balances(BalancesCall::force_transfer { source: 0, dest: 0, value: 0 }), + Call::Balances(BalancesCall::transfer { dest: 0, value: 0 }), + ]; + let indices = Lottery::calls_to_indices(&calls).unwrap().into_inner(); + // Only comparing the length since it is otherwise dependant on the API + // of `BalancesCall`. + assert_eq!(indices.len(), calls.len()); + + let too_many_calls = vec![ + Call::Balances(BalancesCall::force_transfer { source: 0, dest: 0, value: 0 }), + Call::Balances(BalancesCall::transfer { dest: 0, value: 0 }), + Call::System(SystemCall::remark { remark: vec![] }), + ]; + assert_noop!(Lottery::calls_to_indices(&too_many_calls), Error::::TooManyCalls); + }); +} + #[test] fn start_lottery_works() { new_test_ext().execute_with(|| { @@ -239,6 +291,106 @@ fn buy_ticket_works() { }); } +/// Test that `do_buy_ticket` returns an `AlreadyParticipating` error. +/// Errors of `do_buy_ticket` are ignored by `buy_ticket`, therefore this white-box test. +#[test] +fn do_buy_ticket_already_participating() { + new_test_ext().execute_with(|| { + let calls = vec![Call::Balances(BalancesCall::transfer { dest: 0, value: 0 })]; + assert_ok!(Lottery::set_calls(Origin::root(), calls.clone())); + assert_ok!(Lottery::start_lottery(Origin::root(), 1, 10, 10, false)); + + // Buying once works. + assert_ok!(Lottery::do_buy_ticket(&1, &calls[0])); + // Buying the same ticket again fails. + assert_noop!(Lottery::do_buy_ticket(&1, &calls[0]), Error::::AlreadyParticipating); + }); +} + +/// `buy_ticket` is a storage noop when called with the same ticket again. +#[test] +fn buy_ticket_already_participating() { + new_test_ext().execute_with(|| { + let calls = vec![Call::Balances(BalancesCall::transfer { dest: 0, value: 0 })]; + assert_ok!(Lottery::set_calls(Origin::root(), calls.clone())); + assert_ok!(Lottery::start_lottery(Origin::root(), 1, 10, 10, false)); + + // Buying once works. + let call = Box::new(calls[0].clone()); + assert_ok!(Lottery::buy_ticket(Origin::signed(1), call.clone())); + + // Buying the same ticket again returns Ok, but changes nothing. + assert_storage_noop!(Lottery::buy_ticket(Origin::signed(1), call).unwrap()); + + // Exactly one ticket exists. + assert_eq!(TicketsCount::::get(), 1); + }); +} + +/// `buy_ticket` is a storage noop when called with insufficient balance. +#[test] +fn buy_ticket_insufficient_balance() { + new_test_ext().execute_with(|| { + let calls = vec![Call::Balances(BalancesCall::transfer { dest: 0, value: 0 })]; + assert_ok!(Lottery::set_calls(Origin::root(), calls.clone())); + // Price set to 100. + assert_ok!(Lottery::start_lottery(Origin::root(), 100, 10, 10, false)); + let call = Box::new(calls[0].clone()); + + // Buying a ticket returns Ok, but changes nothing. + assert_storage_noop!(Lottery::buy_ticket(Origin::signed(1), call).unwrap()); + assert!(TicketsCount::::get().is_zero()); + }); +} + +#[test] +fn do_buy_ticket_insufficient_balance() { + new_test_ext().execute_with(|| { + let calls = vec![Call::Balances(BalancesCall::transfer { dest: 0, value: 0 })]; + assert_ok!(Lottery::set_calls(Origin::root(), calls.clone())); + // Price set to 101. + assert_ok!(Lottery::start_lottery(Origin::root(), 101, 10, 10, false)); + + // Buying fails with InsufficientBalance. + assert_noop!( + Lottery::do_buy_ticket(&1, &calls[0]), + BalancesError::::InsufficientBalance + ); + assert!(TicketsCount::::get().is_zero()); + }); +} + +#[test] +fn do_buy_ticket_keep_alive() { + new_test_ext().execute_with(|| { + let calls = vec![Call::Balances(BalancesCall::transfer { dest: 0, value: 0 })]; + assert_ok!(Lottery::set_calls(Origin::root(), calls.clone())); + // Price set to 100. + assert_ok!(Lottery::start_lottery(Origin::root(), 100, 10, 10, false)); + + // Buying fails with KeepAlive. + assert_noop!(Lottery::do_buy_ticket(&1, &calls[0]), BalancesError::::KeepAlive); + assert!(TicketsCount::::get().is_zero()); + }); +} + +/// The lottery handles the case that no one participated. +#[test] +fn no_participants_works() { + new_test_ext().execute_with(|| { + let length = 20; + let delay = 5; + + // Set no calls for the lottery. + assert_ok!(Lottery::set_calls(Origin::root(), vec![])); + // Start lottery. + assert_ok!(Lottery::start_lottery(Origin::root(), 10, length, delay, false)); + + // End the lottery, no one wins. + run_to_block(length + delay); + }); +} + #[test] fn start_lottery_will_create_account() { new_test_ext().execute_with(|| { @@ -251,3 +403,26 @@ fn start_lottery_will_create_account() { assert_eq!(Balances::total_balance(&Lottery::account_id()), 1); }); } + +#[test] +fn choose_ticket_trivial_cases() { + new_test_ext().execute_with(|| { + assert!(Lottery::choose_ticket(0).is_none()); + assert_eq!(Lottery::choose_ticket(1).unwrap(), 0); + }); +} + +#[test] +fn choose_account_one_participant() { + new_test_ext().execute_with(|| { + let calls = vec![Call::Balances(BalancesCall::transfer { dest: 0, value: 0 })]; + assert_ok!(Lottery::set_calls(Origin::root(), calls.clone())); + assert_ok!(Lottery::start_lottery(Origin::root(), 10, 10, 10, false)); + let call = Box::new(calls[0].clone()); + + // Buy one ticket with account 1. + assert_ok!(Lottery::buy_ticket(Origin::signed(1), call)); + // Account 1 is always the winner. + assert_eq!(Lottery::choose_account().unwrap(), 1); + }); +} From 75c960922d9cf24627e2b3b53e2925f23316c0b6 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Tue, 11 Jan 2022 19:13:06 +0100 Subject: [PATCH 373/695] followup #10594: re-benchmark pallet-lottery (#10637) * pallet-preimage: fix crate doc Signed-off-by: Oliver Tale-Yazdi * cargo run --quiet --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_lottery --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/lottery/src/weights.rs --template=./.maintain/frame-weight-template.hbs Co-authored-by: Parity Bot --- frame/lottery/src/weights.rs | 37 ++++++++++++++++++------------------ frame/preimage/src/lib.rs | 2 +- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/frame/lottery/src/weights.rs b/frame/lottery/src/weights.rs index 5d252e9d5650..53ec2aa23156 100644 --- a/frame/lottery/src/weights.rs +++ b/frame/lottery/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. +// Copyright (C) 2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_lottery //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-08-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-01-11, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 // Executed Command: @@ -35,7 +35,6 @@ // --output=./frame/lottery/src/weights.rs // --template=./.maintain/frame-weight-template.hbs - #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] #![allow(unused_imports)] @@ -64,28 +63,28 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:1 w:1) // Storage: Lottery Tickets (r:0 w:1) fn buy_ticket() -> Weight { - (70_034_000 as Weight) + (52_219_000 as Weight) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } // Storage: Lottery CallIndices (r:0 w:1) fn set_calls(n: u32, ) -> Weight { - (15_243_000 as Weight) - // Standard Error: 8_000 - .saturating_add((312_000 as Weight).saturating_mul(n as Weight)) + (13_249_000 as Weight) + // Standard Error: 7_000 + .saturating_add((378_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Lottery Lottery (r:1 w:1) // Storage: Lottery LotteryIndex (r:1 w:1) // Storage: System Account (r:1 w:1) fn start_lottery() -> Weight { - (57_312_000 as Weight) + (44_636_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Lottery Lottery (r:1 w:1) fn stop_repeat() -> Weight { - (6_964_000 as Weight) + (5_654_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -95,7 +94,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Lottery TicketsCount (r:1 w:1) // Storage: Lottery Tickets (r:1 w:0) fn on_initialize_end() -> Weight { - (110_470_000 as Weight) + (72_990_000 as Weight) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } @@ -106,7 +105,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Lottery Tickets (r:1 w:0) // Storage: Lottery LotteryIndex (r:1 w:1) fn on_initialize_repeat() -> Weight { - (114_794_000 as Weight) + (75_323_000 as Weight) .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } @@ -122,28 +121,28 @@ impl WeightInfo for () { // Storage: System Account (r:1 w:1) // Storage: Lottery Tickets (r:0 w:1) fn buy_ticket() -> Weight { - (70_034_000 as Weight) + (52_219_000 as Weight) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } // Storage: Lottery CallIndices (r:0 w:1) fn set_calls(n: u32, ) -> Weight { - (15_243_000 as Weight) - // Standard Error: 8_000 - .saturating_add((312_000 as Weight).saturating_mul(n as Weight)) + (13_249_000 as Weight) + // Standard Error: 7_000 + .saturating_add((378_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Lottery Lottery (r:1 w:1) // Storage: Lottery LotteryIndex (r:1 w:1) // Storage: System Account (r:1 w:1) fn start_lottery() -> Weight { - (57_312_000 as Weight) + (44_636_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } // Storage: Lottery Lottery (r:1 w:1) fn stop_repeat() -> Weight { - (6_964_000 as Weight) + (5_654_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -153,7 +152,7 @@ impl WeightInfo for () { // Storage: Lottery TicketsCount (r:1 w:1) // Storage: Lottery Tickets (r:1 w:0) fn on_initialize_end() -> Weight { - (110_470_000 as Weight) + (72_990_000 as Weight) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } @@ -164,7 +163,7 @@ impl WeightInfo for () { // Storage: Lottery Tickets (r:1 w:0) // Storage: Lottery LotteryIndex (r:1 w:1) fn on_initialize_repeat() -> Weight { - (114_794_000 as Weight) + (75_323_000 as Weight) .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } diff --git a/frame/preimage/src/lib.rs b/frame/preimage/src/lib.rs index 17fc543084c9..7564629bad29 100644 --- a/frame/preimage/src/lib.rs +++ b/frame/preimage/src/lib.rs @@ -23,7 +23,7 @@ //! ## Overview //! //! The Preimage pallet allows for the users and the runtime to store the preimage -//! of a hash on chain. This can be used by other pallets where storing and managing +//! of a hash on chain. This can be used by other pallets for storing and managing //! large byte-blobs. #![cfg_attr(not(feature = "std"), no_std)] From 3541490fefd1049afb8219b1053cdd653a9225f2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 Jan 2022 09:18:23 +0100 Subject: [PATCH 374/695] Bump twox-hash from 1.6.1 to 1.6.2 (#10575) Bumps [twox-hash](https://github.com/shepmaster/twox-hash) from 1.6.1 to 1.6.2. - [Release notes](https://github.com/shepmaster/twox-hash/releases) - [Commits](https://github.com/shepmaster/twox-hash/compare/v1.6.1...v1.6.2) --- updated-dependencies: - dependency-name: twox-hash dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- primitives/core/Cargo.toml | 2 +- primitives/core/hashing/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 65b0897947f1..b65795a373b3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11003,9 +11003,9 @@ checksum = "5e66dcbec4290c69dd03c57e76c2469ea5c7ce109c6dd4351c13055cf71ea055" [[package]] name = "twox-hash" -version = "1.6.1" +version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f559b464de2e2bdabcac6a210d12e9b5a5973c251e102c44c585c71d51bd78e" +checksum = "4ee73e6e4924fe940354b8d4d98cad5231175d615cd855b758adc658c0aac6a0" dependencies = [ "cfg-if 1.0.0", "rand 0.8.4", diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index c1ca9f081570..83228b9251dd 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -64,7 +64,7 @@ schnorrkel = { version = "0.9.1", features = [ ], default-features = false, optional = true } sha2 = { version = "0.10.0", default-features = false, optional = true } hex = { version = "0.4", default-features = false, optional = true } -twox-hash = { version = "1.6.1", default-features = false, optional = true } +twox-hash = { version = "1.6.2", default-features = false, optional = true } libsecp256k1 = { version = "0.7", default-features = false, features = ["hmac", "static-context"], optional = true } merlin = { version = "2.0", default-features = false, optional = true } ss58-registry = { version = "1.10.0", default-features = false } diff --git a/primitives/core/hashing/Cargo.toml b/primitives/core/hashing/Cargo.toml index e9f3c8c714f7..8a84e585dad2 100644 --- a/primitives/core/hashing/Cargo.toml +++ b/primitives/core/hashing/Cargo.toml @@ -19,7 +19,7 @@ byteorder = { version = "1.3.2", default-features = false } blake2-rfc = { version = "0.2.18", default-features = false } tiny-keccak = { version = "2.0.1", features = ["keccak"] } sha2 = { version = "0.10.0", default-features = false } -twox-hash = { version = "1.5.0", default-features = false } +twox-hash = { version = "1.6.2", default-features = false } [features] default = ["std"] From 306be17524ac0cd28cbb048dc2f73e43a39cba19 Mon Sep 17 00:00:00 2001 From: Xiliang Chen Date: Wed, 12 Jan 2022 21:22:29 +1300 Subject: [PATCH 375/695] reset events before apply runtime upgrade (#10620) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * reset events before apply runtime upgrade * fix tests * add test * update comment * Update frame/system/src/lib.rs * trigger CI Co-authored-by: Bastian Köcher --- frame/aura/src/tests.rs | 4 +- frame/authorship/src/lib.rs | 6 ++- frame/babe/src/mock.rs | 7 ++-- frame/babe/src/tests.rs | 17 ++++---- frame/contracts/src/tests.rs | 3 +- frame/executive/src/lib.rs | 45 +++++++++++++++------ frame/grandpa/src/mock.rs | 6 ++- frame/merkle-mountain-range/src/tests.rs | 8 +--- frame/randomness-collective-flip/src/lib.rs | 3 +- frame/system/src/lib.rs | 42 +++---------------- frame/system/src/tests.rs | 21 ++++++---- 11 files changed, 79 insertions(+), 83 deletions(-) diff --git a/frame/aura/src/tests.rs b/frame/aura/src/tests.rs index 30003632729e..ce09f85678c0 100644 --- a/frame/aura/src/tests.rs +++ b/frame/aura/src/tests.rs @@ -22,7 +22,6 @@ use crate::mock::{new_test_ext, Aura, MockDisabledValidators, System}; use codec::Encode; use frame_support::traits::OnInitialize; -use frame_system::InitKind; use sp_consensus_aura::{Slot, AURA_ENGINE_ID}; use sp_runtime::{Digest, DigestItem}; @@ -45,7 +44,8 @@ fn disabled_validators_cannot_author_blocks() { let pre_digest = Digest { logs: vec![DigestItem::PreRuntime(AURA_ENGINE_ID, slot.encode())] }; - System::initialize(&42, &System::parent_hash(), &pre_digest, InitKind::Full); + System::reset_events(); + System::initialize(&42, &System::parent_hash(), &pre_digest); // let's disable the validator MockDisabledValidators::disable_validator(1); diff --git a/frame/authorship/src/lib.rs b/frame/authorship/src/lib.rs index db453fc57e9e..3fa081f5263e 100644 --- a/frame/authorship/src/lib.rs +++ b/frame/authorship/src/lib.rs @@ -596,7 +596,8 @@ mod tests { }; let initialize_block = |number, hash: H256| { - System::initialize(&number, &hash, &Default::default(), Default::default()) + System::reset_events(); + System::initialize(&number, &hash, &Default::default()) }; for number in 1..8 { @@ -689,7 +690,8 @@ mod tests { seal_header(create_header(1, Default::default(), [1; 32].into()), author); header.digest_mut().pop(); // pop the seal off. - System::initialize(&1, &Default::default(), header.digest(), Default::default()); + System::reset_events(); + System::initialize(&1, &Default::default(), header.digest()); assert_eq!(Authorship::author(), Some(author)); }); diff --git a/frame/babe/src/mock.rs b/frame/babe/src/mock.rs index f0faa55e5b33..22d7befab668 100644 --- a/frame/babe/src/mock.rs +++ b/frame/babe/src/mock.rs @@ -24,7 +24,6 @@ use frame_support::{ parameter_types, traits::{ConstU128, ConstU32, ConstU64, GenesisBuild, KeyOwnerProofSystem, OnInitialize}, }; -use frame_system::InitKind; use pallet_session::historical as pallet_session_historical; use pallet_staking::EraIndex; use sp_consensus_babe::{AuthorityId, AuthorityPair, Slot}; @@ -255,7 +254,8 @@ pub fn go_to_block(n: u64, s: u64) { let pre_digest = make_secondary_plain_pre_digest(0, s.into()); - System::initialize(&n, &parent_hash, &pre_digest, InitKind::Full); + System::reset_events(); + System::initialize(&n, &parent_hash, &pre_digest); Babe::on_initialize(n); Session::on_initialize(n); @@ -421,7 +421,8 @@ pub fn generate_equivocation_proof( let make_header = || { let parent_hash = System::parent_hash(); let pre_digest = make_secondary_plain_pre_digest(offender_authority_index, slot); - System::initialize(¤t_block, &parent_hash, &pre_digest, InitKind::Full); + System::reset_events(); + System::initialize(¤t_block, &parent_hash, &pre_digest); System::set_block_number(current_block); Timestamp::set_timestamp(current_block); System::finalize() diff --git a/frame/babe/src/tests.rs b/frame/babe/src/tests.rs index 89911efe4e8a..65c9de85586e 100644 --- a/frame/babe/src/tests.rs +++ b/frame/babe/src/tests.rs @@ -67,7 +67,8 @@ fn first_block_epoch_zero_start() { let pre_digest = make_primary_pre_digest(0, genesis_slot, first_vrf.clone(), vrf_proof); assert_eq!(Babe::genesis_slot(), Slot::from(0)); - System::initialize(&1, &Default::default(), &pre_digest, Default::default()); + System::reset_events(); + System::initialize(&1, &Default::default(), &pre_digest); // see implementation of the function for details why: we issue an // epoch-change digest but don't do it via the normal session mechanism. @@ -112,7 +113,8 @@ fn author_vrf_output_for_primary() { let (vrf_output, vrf_proof, vrf_randomness) = make_vrf_output(genesis_slot, &pairs[0]); let primary_pre_digest = make_primary_pre_digest(0, genesis_slot, vrf_output, vrf_proof); - System::initialize(&1, &Default::default(), &primary_pre_digest, Default::default()); + System::reset_events(); + System::initialize(&1, &Default::default(), &primary_pre_digest); Babe::do_initialize(1); assert_eq!(Babe::author_vrf_randomness(), Some(vrf_randomness)); @@ -133,7 +135,8 @@ fn author_vrf_output_for_secondary_vrf() { let secondary_vrf_pre_digest = make_secondary_vrf_pre_digest(0, genesis_slot, vrf_output, vrf_proof); - System::initialize(&1, &Default::default(), &secondary_vrf_pre_digest, Default::default()); + System::reset_events(); + System::initialize(&1, &Default::default(), &secondary_vrf_pre_digest); Babe::do_initialize(1); assert_eq!(Babe::author_vrf_randomness(), Some(vrf_randomness)); @@ -150,12 +153,8 @@ fn no_author_vrf_output_for_secondary_plain() { let genesis_slot = Slot::from(10); let secondary_plain_pre_digest = make_secondary_plain_pre_digest(0, genesis_slot); - System::initialize( - &1, - &Default::default(), - &secondary_plain_pre_digest, - Default::default(), - ); + System::reset_events(); + System::initialize(&1, &Default::default(), &secondary_plain_pre_digest); assert_eq!(Babe::author_vrf_randomness(), None); Babe::do_initialize(1); diff --git a/frame/contracts/src/tests.rs b/frame/contracts/src/tests.rs index 17e8f746be1f..be9904e71c5c 100644 --- a/frame/contracts/src/tests.rs +++ b/frame/contracts/src/tests.rs @@ -533,7 +533,8 @@ fn run_out_of_gas() { } fn initialize_block(number: u64) { - System::initialize(&number, &[0u8; 32].into(), &Default::default(), Default::default()); + System::reset_events(); + System::initialize(&number, &[0u8; 32].into(), &Default::default()); } #[test] diff --git a/frame/executive/src/lib.rs b/frame/executive/src/lib.rs index be944954eaa5..d19ea8127bad 100644 --- a/frame/executive/src/lib.rs +++ b/frame/executive/src/lib.rs @@ -294,16 +294,16 @@ where parent_hash: &System::Hash, digest: &Digest, ) { + // Reset events before apply runtime upgrade hook. + // This is required to preserve events from runtime upgrade hook. + // This means the format of all the event related storages must always be compatible. + >::reset_events(); + let mut weight = 0; if Self::runtime_upgraded() { weight = weight.saturating_add(Self::execute_on_runtime_upgrade()); } - >::initialize( - block_number, - parent_hash, - digest, - frame_system::InitKind::Full, - ); + >::initialize(block_number, parent_hash, digest); weight = weight.saturating_add(>::on_initialize(*block_number)); @@ -510,7 +510,6 @@ where &(frame_system::Pallet::::block_number() + One::one()), &block_hash, &Default::default(), - frame_system::InitKind::Inspection, ); enter_span! { sp_tracing::Level::TRACE, "validate_transaction" }; @@ -541,12 +540,7 @@ where // OffchainWorker RuntimeApi should skip initialization. let digests = header.digest().clone(); - >::initialize( - header.number(), - header.parent_hash(), - &digests, - frame_system::InitKind::Inspection, - ); + >::initialize(header.number(), header.parent_hash(), &digests); // Frame system only inserts the parent hash into the block hashes as normally we don't know // the hash for the header before. However, here we are aware of the hash and we can add it @@ -830,6 +824,7 @@ mod tests { fn on_runtime_upgrade() -> Weight { sp_io::storage::set(TEST_KEY, "custom_upgrade".as_bytes()); sp_io::storage::set(CUSTOM_ON_RUNTIME_KEY, &true.encode()); + System::deposit_event(frame_system::Event::CodeUpdated); 100 } } @@ -1296,6 +1291,30 @@ mod tests { }); } + #[test] + fn event_from_runtime_upgrade_is_included() { + new_test_ext(1).execute_with(|| { + // Make sure `on_runtime_upgrade` is called. + RUNTIME_VERSION.with(|v| { + *v.borrow_mut() = + sp_version::RuntimeVersion { spec_version: 1, ..Default::default() } + }); + + // set block number to non zero so events are not exlcuded + System::set_block_number(1); + + Executive::initialize_block(&Header::new( + 2, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); + + System::assert_last_event(frame_system::Event::::CodeUpdated.into()); + }); + } + /// Regression test that ensures that the custom on runtime upgrade is called when executive is /// used through the `ExecuteBlock` trait. #[test] diff --git a/frame/grandpa/src/mock.rs b/frame/grandpa/src/mock.rs index ddfae3d7ea75..91006d66b7de 100644 --- a/frame/grandpa/src/mock.rs +++ b/frame/grandpa/src/mock.rs @@ -326,7 +326,8 @@ pub fn start_session(session_index: SessionIndex) { System::parent_hash() }; - System::initialize(&(i as u64 + 1), &parent_hash, &Default::default(), Default::default()); + System::reset_events(); + System::initialize(&(i as u64 + 1), &parent_hash, &Default::default()); System::set_block_number((i + 1).into()); Timestamp::set_timestamp(System::block_number() * 6000); @@ -345,7 +346,8 @@ pub fn start_era(era_index: EraIndex) { } pub fn initialize_block(number: u64, parent_hash: H256) { - System::initialize(&number, &parent_hash, &Default::default(), Default::default()); + System::reset_events(); + System::initialize(&number, &parent_hash, &Default::default()); } pub fn generate_equivocation_proof( diff --git a/frame/merkle-mountain-range/src/tests.rs b/frame/merkle-mountain-range/src/tests.rs index 588a407d6d37..576a7ace8f1c 100644 --- a/frame/merkle-mountain-range/src/tests.rs +++ b/frame/merkle-mountain-range/src/tests.rs @@ -40,12 +40,8 @@ fn new_block() -> u64 { let hash = H256::repeat_byte(number as u8); LEAF_DATA.with(|r| r.borrow_mut().a = number); - frame_system::Pallet::::initialize( - &number, - &hash, - &Default::default(), - frame_system::InitKind::Full, - ); + frame_system::Pallet::::reset_events(); + frame_system::Pallet::::initialize(&number, &hash, &Default::default()); MMR::on_initialize(number) } diff --git a/frame/randomness-collective-flip/src/lib.rs b/frame/randomness-collective-flip/src/lib.rs index 5f4994c47142..fbc8aaaa7ec5 100644 --- a/frame/randomness-collective-flip/src/lib.rs +++ b/frame/randomness-collective-flip/src/lib.rs @@ -239,7 +239,8 @@ mod tests { let mut parent_hash = System::parent_hash(); for i in 1..(blocks + 1) { - System::initialize(&i, &parent_hash, &Default::default(), frame_system::InitKind::Full); + System::reset_events(); + System::initialize(&i, &parent_hash, &Default::default()); CollectiveFlip::on_initialize(i); let header = System::finalize(); diff --git a/frame/system/src/lib.rs b/frame/system/src/lib.rs index cec45a8aa1cb..7615424ba57e 100644 --- a/frame/system/src/lib.rs +++ b/frame/system/src/lib.rs @@ -944,27 +944,6 @@ where } } -/// A type of block initialization to perform. -pub enum InitKind { - /// Leave inspectable storage entries in state. - /// - /// i.e. `Events` are not being reset. - /// Should only be used for off-chain calls, - /// regular block execution should clear those. - Inspection, - - /// Reset also inspectable storage entries. - /// - /// This should be used for regular block execution. - Full, -} - -impl Default for InitKind { - fn default() -> Self { - InitKind::Full - } -} - /// Reference status; can be either referenced or unreferenced. #[derive(RuntimeDebug)] pub enum RefStatus { @@ -1302,12 +1281,7 @@ impl Pallet { } /// Start the execution of a particular block. - pub fn initialize( - number: &T::BlockNumber, - parent_hash: &T::Hash, - digest: &generic::Digest, - kind: InitKind, - ) { + pub fn initialize(number: &T::BlockNumber, parent_hash: &T::Hash, digest: &generic::Digest) { // populate environment ExecutionPhase::::put(Phase::Initialization); storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &0u32); @@ -1318,13 +1292,6 @@ impl Pallet { // Remove previous block data from storage BlockWeight::::kill(); - - // Kill inspectable storage entries in state when `InitKind::Full`. - if let InitKind::Full = kind { - >::kill(); - EventCount::::kill(); - >::remove_all(None); - } } /// Remove temporary "environment" entries in storage, compute the storage root and return the @@ -1444,9 +1411,10 @@ impl Pallet { AllExtrinsicsLen::::put(len as u32); } - /// Reset events. Can be used as an alternative to - /// `initialize` for tests that don't need to bother with the other environment entries. - #[cfg(any(feature = "std", feature = "runtime-benchmarks", test))] + /// Reset events. + /// + /// This needs to be used in prior calling [`initialize`](Self::initialize) for each new block + /// to clear events from previous block. pub fn reset_events() { >::kill(); EventCount::::kill(); diff --git a/frame/system/src/tests.rs b/frame/system/src/tests.rs index 411925c70275..0facd796b2a0 100644 --- a/frame/system/src/tests.rs +++ b/frame/system/src/tests.rs @@ -154,7 +154,8 @@ fn provider_required_to_support_consumer() { #[test] fn deposit_event_should_work() { new_test_ext().execute_with(|| { - System::initialize(&1, &[0u8; 32].into(), &Default::default(), InitKind::Full); + System::reset_events(); + System::initialize(&1, &[0u8; 32].into(), &Default::default()); System::note_finished_extrinsics(); System::deposit_event(SysEvent::CodeUpdated); System::finalize(); @@ -167,7 +168,8 @@ fn deposit_event_should_work() { }] ); - System::initialize(&2, &[0u8; 32].into(), &Default::default(), InitKind::Full); + System::reset_events(); + System::initialize(&2, &[0u8; 32].into(), &Default::default()); System::deposit_event(SysEvent::NewAccount { account: 32 }); System::note_finished_initialize(); System::deposit_event(SysEvent::KilledAccount { account: 42 }); @@ -216,7 +218,8 @@ fn deposit_event_should_work() { #[test] fn deposit_event_uses_actual_weight() { new_test_ext().execute_with(|| { - System::initialize(&1, &[0u8; 32].into(), &Default::default(), InitKind::Full); + System::reset_events(); + System::initialize(&1, &[0u8; 32].into(), &Default::default()); System::note_finished_initialize(); let pre_info = DispatchInfo { weight: 1000, ..Default::default() }; @@ -275,7 +278,8 @@ fn deposit_event_topics() { new_test_ext().execute_with(|| { const BLOCK_NUMBER: u64 = 1; - System::initialize(&BLOCK_NUMBER, &[0u8; 32].into(), &Default::default(), InitKind::Full); + System::reset_events(); + System::initialize(&BLOCK_NUMBER, &[0u8; 32].into(), &Default::default()); System::note_finished_extrinsics(); let topics = vec![H256::repeat_byte(1), H256::repeat_byte(2), H256::repeat_byte(3)]; @@ -333,7 +337,8 @@ fn prunes_block_hash_mappings() { new_test_ext().execute_with(|| { // simulate import of 15 blocks for n in 1..=15 { - System::initialize(&n, &[n as u8 - 1; 32].into(), &Default::default(), InitKind::Full); + System::reset_events(); + System::initialize(&n, &[n as u8 - 1; 32].into(), &Default::default()); System::finalize(); } @@ -464,7 +469,8 @@ fn events_not_emitted_during_genesis() { #[test] fn extrinsics_root_is_calculated_correctly() { new_test_ext().execute_with(|| { - System::initialize(&1, &[0u8; 32].into(), &Default::default(), InitKind::Full); + System::reset_events(); + System::initialize(&1, &[0u8; 32].into(), &Default::default()); System::note_finished_initialize(); System::note_extrinsic(vec![1]); System::note_applied_extrinsic(&Ok(().into()), Default::default()); @@ -481,7 +487,8 @@ fn extrinsics_root_is_calculated_correctly() { #[test] fn runtime_updated_digest_emitted_when_heap_pages_changed() { new_test_ext().execute_with(|| { - System::initialize(&1, &[0u8; 32].into(), &Default::default(), InitKind::Full); + System::reset_events(); + System::initialize(&1, &[0u8; 32].into(), &Default::default()); System::set_heap_pages(RawOrigin::Root.into(), 5).unwrap(); assert_runtime_updated_digest(1); }); From fb24fda76d613305ebb2e5728c75362c94b64aa1 Mon Sep 17 00:00:00 2001 From: Alexander Samusev <41779041+alvicsam@users.noreply.github.com> Date: Wed, 12 Jan 2022 09:33:25 +0100 Subject: [PATCH 376/695] [ci] pipeline chores (#10624) * [Do not merge] pipeline chores * disable condition publish-rustdoc * revert rules * remove PIPELINE_SCRIPTS_TAG --- .gitlab-ci.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 19d3f63dc5fe..43674da4627a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -42,7 +42,6 @@ variables: &default-vars VAULT_SERVER_URL: "https://vault.parity-mgmt-vault.parity.io" VAULT_AUTH_PATH: "gitlab-parity-io-jwt" VAULT_AUTH_ROLE: "cicd_gitlab_parity_${CI_PROJECT_NAME}" - PIPELINE_SCRIPTS_TAG: "v0.4" default: cache: {} @@ -543,6 +542,8 @@ cargo-check-macos: #### stage: build +# PIPELINE_SCRIPTS_TAG can be found in the project variables + .check-dependent-project: &check-dependent-project stage: build <<: *docker-env @@ -772,8 +773,6 @@ publish-rustdoc: # whole space-separated value. - '[[ " ${RUSTDOCS_DEPLOY_REFS} " =~ " ${CI_COMMIT_REF_NAME} " ]] || exit 0' # setup ssh - # FIXME: add ssh to docker image - - apt-get update && apt-get install -y ssh - eval $(ssh-agent) - ssh-add - <<< ${GITHUB_SSH_PRIV_KEY} - mkdir ~/.ssh && touch ~/.ssh/known_hosts From 61482c0acf81176d781984a720e2f48c2a777d24 Mon Sep 17 00:00:00 2001 From: driemworks Date: Wed, 12 Jan 2022 15:22:41 -0600 Subject: [PATCH 377/695] WIP: integrate with sessions (with aura) --- Cargo.lock | 2 + bin/node-template/node/src/chain_spec.rs | 13 +- bin/node-template/pallets/template/Cargo.toml | 2 + bin/node-template/pallets/template/src/lib.rs | 542 +++++++++++++++++- bin/node-template/runtime/Cargo.toml | 6 +- bin/node-template/runtime/src/lib.rs | 36 +- 6 files changed, 593 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b48dc9e22b67..ea77256ccb2b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5043,6 +5043,7 @@ dependencies = [ "pallet-iris", "pallet-iris-rpc-runtime-api", "pallet-randomness-collective-flip", + "pallet-session", "pallet-sudo", "pallet-timestamp", "pallet-transaction-payment", @@ -5858,6 +5859,7 @@ dependencies = [ "log 0.4.14", "pallet-assets", "pallet-balances", + "pallet-session", "parity-scale-codec", "scale-info", "sp-core", diff --git a/bin/node-template/node/src/chain_spec.rs b/bin/node-template/node/src/chain_spec.rs index 7009b3be5c27..159efe9fa8bc 100644 --- a/bin/node-template/node/src/chain_spec.rs +++ b/bin/node-template/node/src/chain_spec.rs @@ -1,4 +1,4 @@ -use node_template_runtime::{ +:use node_template_runtime::{ AccountId, AuraConfig, BalancesConfig, GenesisConfig, GrandpaConfig, Signature, SudoConfig, SystemConfig, WASM_BINARY, }; @@ -32,8 +32,8 @@ where } /// Generate an Aura authority key. -pub fn authority_keys_from_seed(s: &str) -> (AuraId, GrandpaId) { - (get_from_seed::(s), get_from_seed::(s)) +pub fn authority_keys_from_seed(s: &str) -> (AccountId, AuraId, GrandpaId) { + (get_account_id_from_seed::(s), get_from_seed::(s), get_from_seed::(s)) } pub fn development_config() -> Result { @@ -125,7 +125,7 @@ pub fn local_testnet_config() -> Result { /// Configure initial storage state for FRAME modules. fn testnet_genesis( wasm_binary: &[u8], - initial_authorities: Vec<(AuraId, GrandpaId)>, + initial_authorities: Vec<(AccountId, AuraId, GrandpaId)>, root_key: AccountId, endowed_accounts: Vec, _enable_println: bool, @@ -146,6 +146,11 @@ fn testnet_genesis( grandpa: GrandpaConfig { authorities: initial_authorities.iter().map(|x| (x.1.clone(), 1)).collect(), }, + session: Some(SessionConfig { + keys: initial_authorities.iter().map(|x| { + (x.0.clone(), x.0.clone(), session_keys(x.1.clone(), x.2.clone())) + }).collect::>(), + }), sudo: SudoConfig { // Assign network admin rights. key: root_key, diff --git a/bin/node-template/pallets/template/Cargo.toml b/bin/node-template/pallets/template/Cargo.toml index e2996acf1f95..abd20649db0e 100644 --- a/bin/node-template/pallets/template/Cargo.toml +++ b/bin/node-template/pallets/template/Cargo.toml @@ -32,6 +32,7 @@ log = { version = "0.4.14", default-features = false } pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../../../../frame/balances" } pallet-assets = { version = "4.0.0-dev", default-features = false, path = "../../../../frame/assets" } +pallet-session = { version = "4.0.0-dev", default-features = false, features = ["historical"], path = "../../../../frame/session" } [features] default = ['std'] @@ -48,6 +49,7 @@ std = [ 'log/std', 'pallet-assets/std', 'pallet-balances/std', + 'pallet-session/std', ] runtime-benchmarks = ["frame-benchmarking"] diff --git a/bin/node-template/pallets/template/src/lib.rs b/bin/node-template/pallets/template/src/lib.rs index 8d7dcdf6e32e..b05d2ffaedf4 100644 --- a/bin/node-template/pallets/template/src/lib.rs +++ b/bin/node-template/pallets/template/src/lib.rs @@ -51,17 +51,110 @@ use sp_runtime::{ ipfs, }, RuntimeDebug, - traits::StaticLookup, + traits::{ + StaticLookup, + Convert, + }, }; use sp_std::{ str, vec::Vec, prelude::*, convert::TryInto, + collections::btree_map::BTreeMap, }; +use pallet_session::historical; + pub const KEY_TYPE: KeyTypeId = KeyTypeId(*b"iris"); +pub type SessionIndex = u32; +pub type EraIndex = u32; +pub type RewardPoint = u32; + +/// Information regarding the active era (era in used in session). +#[derive(Encode, Decode, RuntimeDebug, TypeInfo)] +pub struct ActiveEraInfo { + /// Index of era. + pub index: EraIndex, + /// Anchor era number of this era. + pub set_id: u32, + /// Moment of start expressed as millisecond from `$UNIX_EPOCH`. + /// + /// Start can be none if start hasn't been set for the era yet, + /// Start is set on the first on_finalize of the era to guarantee usage of `Time`. + start: Option, +} + +/// Reward points of an era. Used to split era total payout between validators. +/// +/// This points will be used to reward validators and their respective nominators. +#[derive(PartialEq, Encode, Decode, Default, RuntimeDebug, TypeInfo)] +pub struct EraRewardPoints { + /// Total number of points. Equals the sum of reward points for each validator. + total: RewardPoint, + /// The reward points earned by a given validator. + individual: BTreeMap, +} + +/// Means for interacting with a specialized version of the `session` trait. +/// +/// This is needed because `Staking` sets the `ValidatorIdOf` of the `pallet_session::Config` +pub trait SessionInterface: frame_system::Config { + /// Disable a given validator by stash ID. + /// + /// Returns `true` if new era should be forced at the end of this session. + /// This allows preventing a situation where there is too many validators + /// disabled and block production stalls. + fn disable_validator(validator: &AccountId) -> Result; + /// Get the validators from session. + fn validators() -> Vec; + /// Prune historical session tries up to but not including the given index. + fn prune_historical_up_to(up_to: SessionIndex); + + fn is_active_validator(id: KeyTypeId, key_data: &[u8]) -> Option; +} + +impl SessionInterface<::AccountId> for T +where + T: pallet_session::Config::AccountId>, + T: pallet_session::historical::Config< + FullIdentification = u128, + FullIdentificationOf = ExposureOf, + >, + T::SessionHandler: pallet_session::SessionHandler<::AccountId>, + T::SessionManager: pallet_session::SessionManager<::AccountId>, + T::ValidatorIdOf: Convert< + ::AccountId, + Option<::AccountId>, + >, +{ + fn disable_validator(validator: &::AccountId) -> Result { + >::disable(validator) + } + + fn validators() -> Vec<::AccountId> { + >::validators() + } + + fn prune_historical_up_to(up_to: SessionIndex) { + >::prune_up_to(up_to); + } + + fn is_active_validator( + id: KeyTypeId, + key_data: &[u8], + ) -> Option<::AccountId> { + let who = >::key_owner(id, key_data); + if who.is_none() { + return None; + } + Self::validators().into_iter().find(|v| { + log::info!("check {:#?} == {:#?}", v, who); + T::ValidatorIdOf::convert(v.clone()) == who + }) + } +} pub mod crypto { use crate::KEY_TYPE; @@ -97,6 +190,12 @@ pub enum DataCommand { CatBytes(AccountId, Vec, AccountId), } +/// Something that can provide a set of validators for the next era. +pub trait ValidatorsProvider { + /// A new set of validators. + fn validators() -> Vec<(AccountId, u128)>; +} + pub use pallet::*; #[cfg(test)] @@ -133,12 +232,20 @@ pub mod pallet { type Call: From>; /// the currency used type Currency: ReservableCurrency; + /// interface for interacting with the session pallet + type SessionInterface: self::SessionInterface; } #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] pub struct Pallet(_); + + #[pallet::type_value] + pub(crate) fn HistoryDepthOnEmpty() -> u32 { + 84u32 + } + /// map the public key to a list of multiaddresses #[pallet::storage] #[pallet::getter(fn bootstrap_nodes)] @@ -194,6 +301,99 @@ pub mod pallet { ValueQuery, >; + /* + START: SESSION STORAGE STUFF + */ + + /// Number of eras to keep in history. + /// + /// Information is kept for eras in `[current_era - history_depth; current_era]`. + /// + /// Must be more than the number of eras delayed by session otherwise. I.e. active era must + /// always be in history. I.e. `active_era > current_era - history_depth` must be + /// guaranteed. + #[pallet::storage] + #[pallet::getter(fn history_depth)] + pub(crate) type HistoryDepth = StorageValue<_, u32, ValueQuery, HistoryDepthOnEmpty>; + + /// The current era index. + /// + /// This is the latest planned era, depending on how the Session pallet queues the validator + /// set, it might be active or not. + #[pallet::storage] + #[pallet::getter(fn current_era)] + pub type CurrentEra = StorageValue<_, EraIndex>; + + /// The active era information, it holds index and start. + /// + /// The active era is the era being currently rewarded. Validator set of this era must be + /// equal to [`SessionInterface::validators`]. + #[pallet::storage] + #[pallet::getter(fn active_era)] + pub type ActiveEra = StorageValue<_, ActiveEraInfo>; + + /// The session index at which the era start for the last `HISTORY_DEPTH` eras. + /// + /// Note: This tracks the starting session (i.e. session index when era start being active) + /// for the eras in `[CurrentEra - HISTORY_DEPTH, CurrentEra]`. + #[pallet::storage] + #[pallet::getter(fn eras_start_session_index)] + pub type ErasStartSessionIndex = StorageMap<_, Twox64Concat, EraIndex, SessionIndex>; + + /// Exposure of validator at era. + /// + /// This is keyed first by the era index to allow bulk deletion and then the stash account. + /// + /// Is it removed after `HISTORY_DEPTH` eras. + /// If stakers hasn't been set or has been removed then empty exposure is returned. + #[pallet::storage] + #[pallet::getter(fn eras_stakers)] + pub type ErasStakers = + StorageDoubleMap<_, Twox64Concat, EraIndex, Twox64Concat, T::AccountId, u128, ValueQuery>; + + /// The total validator era payout for the last `HISTORY_DEPTH` eras. + /// + /// Eras that haven't finished yet or has been removed doesn't have reward. + #[pallet::storage] + #[pallet::getter(fn eras_validator_reward)] + pub type ErasValidatorReward = StorageMap<_, Twox64Concat, EraIndex, u128>; + + /// Rewards for the last `HISTORY_DEPTH` eras. + /// If reward hasn't been set or has been removed then 0 reward is returned. + #[pallet::storage] + #[pallet::getter(fn eras_reward_points)] + pub type ErasRewardPoints = + StorageMap<_, Twox64Concat, EraIndex, EraRewardPoints, ValueQuery>; + + /// The total amount staked for the last `HISTORY_DEPTH` eras. + /// If total hasn't been set or has been removed then 0 stake is returned. + #[pallet::storage] + #[pallet::getter(fn eras_total_stake)] + pub type ErasTotalStake = StorageMap<_, Twox64Concat, EraIndex, u128, ValueQuery>; + + /// A mapping from still-bonded eras to the first session index of that era. + /// + /// Must contains information for eras for the range: + /// `[active_era - bounding_duration; active_era]` + #[pallet::storage] + pub(crate) type BondedEras = + StorageValue<_, Vec<(EraIndex, SessionIndex)>, ValueQuery>; + + /// The last planned session scheduled by the session pallet. + /// + /// This is basically in sync with the call to [`SessionManager::new_session`]. + #[pallet::storage] + #[pallet::getter(fn current_planned_session)] + pub type CurrentPlannedSession = StorageValue<_, SessionIndex, ValueQuery>; + + /// The payout for validators and the system for the current era. + #[pallet::storage] + #[pallet::getter(fn era_payout)] + pub type EraPayout = StorageValue<_, u128, ValueQuery>; + + /* + END + */ #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { @@ -678,4 +878,344 @@ impl Pallet { ); Ok(()) } + + /* + START: SESSION STUFF + */ + + /// Plan a new session potentially trigger a new era. + fn new_session(session_index: SessionIndex, is_genesis: bool) -> Option> { + if let Some(current_era) = Self::current_era() { + // Initial era has been set. + let current_era_start_session_index = Self::eras_start_session_index(current_era) + .unwrap_or_else(|| { + frame_support::print("Error: start_session_index must be set for current_era"); + 0 + }); + + let era_length = + session_index.checked_sub(current_era_start_session_index).unwrap_or(0); // Must never happen. + + // log!(info, "Era length: {:?}", era_length); + // if era_length < T::SessionsPerEra::get() { + // // The 5th session of the era. + // if T::AppchainInterface::is_activated() + // && (era_length == T::SessionsPerEra::get() - 1) + // { + // let next_set_id = T::AppchainInterface::next_set_id(); + // let message = PlanNewEraPayload { new_era: next_set_id }; + + // let res = T::UpwardMessagesInterface::submit( + // &T::AccountId::default(), + // PayloadType::PlanNewEra, + // &message.try_to_vec().unwrap(), + // ); + // log!(info, "UpwardMessage::PlanNewEra: {:?}", res); + // if res.is_ok() { + // Self::deposit_event(Event::::PlanNewEra(next_set_id)); + // } else { + // Self::deposit_event(Event::::PlanNewEraFailed); + // } + // } + // return None; + // } + + // New era. + Self::try_trigger_new_era(session_index) + } else { + // Set initial era. + log::info!("Starting the first era."); + Self::try_trigger_new_era(session_index) + } + } + + /// Start a session potentially starting an era. + fn start_session(start_session: SessionIndex) { + let next_active_era = Self::active_era().map(|e| e.index + 1).unwrap_or(0); + // This is only `Some` when current era has already progressed to the next era, while the + // active era is one behind (i.e. in the *last session of the active era*, or *first session + // of the new current era*, depending on how you look at it). + if let Some(next_active_era_start_session_index) = + Self::eras_start_session_index(next_active_era) + { + if next_active_era_start_session_index == start_session { + Self::start_era(start_session); + } else if next_active_era_start_session_index < start_session { + // This arm should never happen, but better handle it than to stall the staking + // pallet. + frame_support::print("Warning: A session appears to have been skipped."); + Self::start_era(start_session); + } + } + } + + /// End a session potentially ending an era. + fn end_session(session_index: SessionIndex) { + if let Some(active_era) = Self::active_era() { + if let Some(next_active_era_start_session_index) = + Self::eras_start_session_index(active_era.index + 1) + { + if next_active_era_start_session_index == session_index + 1 { + Self::end_era(active_era, session_index); + } + } + } + } + + /// * Increment `active_era.index`, + /// * reset `active_era.start`, + /// * update `BondedEras` and apply slashes. + fn start_era(start_session: SessionIndex) { + // let active_era = ActiveEra::::mutate(|active_era| { + // let next_set_id = T::AppchainInterface::next_set_id(); + // let new_index = active_era.as_ref().map(|info| info.index + 1).unwrap_or(0); + // *active_era = Some(ActiveEraInfo { + // index: new_index, + // set_id: next_set_id - 1, + // // Set new active era start in next `on_finalize`. To guarantee usage of `Time` + // start: None, + // }); + // new_index + // }); + + // let bonding_duration = T::BondingDuration::get(); + + // BondedEras::::mutate(|bonded| { + // bonded.push((active_era, start_session)); + + // if active_era > bonding_duration { + // let first_kept = active_era - bonding_duration; + + // // Prune out everything that's from before the first-kept index. + // let n_to_prune = + // bonded.iter().take_while(|&&(era_idx, _)| era_idx < first_kept).count(); + + // if let Some(&(_, first_session)) = bonded.first() { + // T::SessionInterface::prune_historical_up_to(first_session); + // } + // } + // }); + } + + /// Compute payout for era. + fn end_era(active_era: ActiveEraInfo, _session_index: SessionIndex) { + return; + // if !T::AppchainInterface::is_activated() || >::get() == 0 { + // return; + // } + + // // Note: active_era_start can be None if end era is called during genesis config. + // if let Some(active_era_start) = active_era.start { + // if >::get(&active_era.index).is_some() { + // log!(warn, "era reward {:?} has already been paid", active_era.index); + // return; + // } + + // let now_as_millis_u64 = T::UnixTime::now().as_millis().saturated_into::(); + // let _era_duration = (now_as_millis_u64 - active_era_start).saturated_into::(); + // let validator_payout = Self::era_payout(); + + // // Set ending era reward. + // >::insert(&active_era.index, validator_payout); + + // let excluded_validators = Self::get_exclude_validators(active_era.index); + + // let excluded_validators_str = excluded_validators + // .iter() + // .map(|validator| { + // let prefix = String::from("0x"); + // let hex_validator = prefix + &hex::encode(validator.encode()); + // hex_validator + // }) + // .collect::>(); + + // log!(debug, "Exclude validators: {:?}", excluded_validators_str.clone()); + + // let message = EraPayoutPayload { + // end_era: active_era.set_id, + // excluded_validators: excluded_validators_str.clone(), + // }; + + // let amount = validator_payout.checked_into().ok_or(Error::::AmountOverflow).unwrap(); + // T::Currency::deposit_creating(&Self::account_id(), amount); + // log!(debug, "Will send EraPayout message, era_payout is {:?}", >::get()); + + // let res = T::UpwardMessagesInterface::submit( + // &T::AccountId::default(), + // PayloadType::EraPayout, + // &message.try_to_vec().unwrap(), + // ); + // log!(info, "UpwardMessage::EraPayout: {:?}", res); + // if res.is_ok() { + // Self::deposit_event(Event::::EraPayout(active_era.set_id, excluded_validators)); + // } else { + // Self::deposit_event(Event::::EraPayoutFailed(active_era.set_id)); + // } + // } + } + + + /// Plan a new era. + /// + /// * Bump the current era storage (which holds the latest planned era). + /// * Store start session index for the new planned era. + /// * Clean old era information. + /// * Store staking information for the new planned era + /// + /// Returns the new validator set. + pub fn trigger_new_era( + start_session_index: SessionIndex, + validators: Vec<(T::AccountId, u128)>, + ) -> Vec { + // Increment or set current era. + let new_planned_era = CurrentEra::::mutate(|s| { + *s = Some(s.map(|s| s + 1).unwrap_or(0)); + s.unwrap() + }); + ErasStartSessionIndex::::insert(&new_planned_era, &start_session_index); + + // Clean old era information. + if let Some(old_era) = new_planned_era.checked_sub(Self::history_depth() + 1) { + Self::clear_era_information(old_era); + } + + // Set staking information for the new era. + Self::store_stakers_info(validators, new_planned_era) + } + + /// Potentially plan a new era. + /// + /// Get planned validator set from `T::ValidatorsProvider`. + fn try_trigger_new_era(start_session_index: SessionIndex) -> Option> { + let validators = T::ValidatorsProvider::validators(); + log!(info, "Next validator set: {:?}", validators); + + >::deposit_event(Event::::TriggerNewEra); + Some(Self::trigger_new_era(start_session_index, validators)) + } + + /// Process the output of the validators provider. + /// + /// Store staking information for the new planned era + pub fn store_stakers_info( + validators: Vec<(T::AccountId, u128)>, + new_planned_era: EraIndex, + ) -> Vec { + let elected_stashes = validators.iter().cloned().map(|(x, _)| x).collect::>(); + + let mut total_stake: u128 = 0; + validators.into_iter().for_each(|(who, weight)| { + total_stake = total_stake.saturating_add(weight); + >::insert(new_planned_era, &who, weight); + }); + + // Insert current era staking information + >::insert(&new_planned_era, total_stake); + + if new_planned_era > 0 { + log::info!( + "New validator set of size {:?} has been processed for era {:?}", + elected_stashes.len(), + new_planned_era, + ); + } + + elected_stashes + } + + /// Clear all era information for given era. + fn clear_era_information(era_index: EraIndex) { + >::remove_prefix(era_index, None); + >::remove(era_index); + >::remove(era_index); + >::remove(era_index); + ErasStartSessionIndex::::remove(era_index); + } + + + /* + END: SESSION STUFF + */ +} + + +/// A typed conversion from stash account ID to the active exposure of nominators +/// on that account. +/// +/// Active exposure is the exposure of the validator set currently validating, i.e. in +/// `active_era`. It can differ from the latest planned exposure in `current_era`. +pub struct ExposureOf(sp_std::marker::PhantomData); + +impl Convert> for ExposureOf { + fn convert(validator: T::AccountId) -> Option { + >::active_era() + .map(|active_era| >::eras_stakers(active_era.index, &validator)) + } +} + +/// In this implementation `new_session(session)` must be called before `end_session(session-1)` +/// i.e. the new session must be planned before the ending of the previous session. +/// +/// Once the first new_session is planned, all session must start and then end in order, though +/// some session can lag in between the newest session planned and the latest session started. +impl pallet_session::SessionManager for Pallet { + fn new_session(new_index: SessionIndex) -> Option> { + log::info!("planning new session {}", new_index); + CurrentPlannedSession::::put(new_index); + Self::new_session(new_index, false) + } + fn new_session_genesis(new_index: SessionIndex) -> Option> { + log::info!("planning new session {} at genesis", new_index); + CurrentPlannedSession::::put(new_index); + Self::new_session(new_index, true) + } + fn start_session(start_index: SessionIndex) { + log::info!("starting session {}", start_index); + Self::start_session(start_index) + } + fn end_session(end_index: SessionIndex) { + log::info!("ending session {}", end_index); + Self::end_session(end_index) + } +} + +impl historical::SessionManager for Pallet { + fn new_session(new_index: SessionIndex) -> Option> { + >::new_session(new_index).map(|validators| { + let current_era = Self::current_era() + // Must be some as a new era has been created. + .unwrap_or(0); + + validators + .into_iter() + .map(|v| { + let exposure = Self::eras_stakers(current_era, &v); + (v, exposure) + }) + .collect() + }) + } + fn new_session_genesis(new_index: SessionIndex) -> Option> { + >::new_session_genesis(new_index).map( + |validators| { + let current_era = Self::current_era() + // Must be some as a new era has been created. + .unwrap_or(0); + + validators + .into_iter() + .map(|v| { + let exposure = Self::eras_stakers(current_era, &v); + (v, exposure) + }) + .collect() + }, + ) + } + fn start_session(start_index: SessionIndex) { + >::start_session(start_index) + } + fn end_session(end_index: SessionIndex) { + >::end_session(end_index) + } } \ No newline at end of file diff --git a/bin/node-template/runtime/Cargo.toml b/bin/node-template/runtime/Cargo.toml index 99301897b29d..1b8ad595d692 100644 --- a/bin/node-template/runtime/Cargo.toml +++ b/bin/node-template/runtime/Cargo.toml @@ -22,6 +22,10 @@ pallet-grandpa = { version = "4.0.0-dev", default-features = false, path = "../. pallet-randomness-collective-flip = { version = "4.0.0-dev", default-features = false, path = "../../../frame/randomness-collective-flip" } pallet-sudo = { version = "4.0.0-dev", default-features = false, path = "../../../frame/sudo" } pallet-assets = { version = "4.0.0-dev", default-features = false, path = "../../../frame/assets" } +pallet-session = { version = "4.0.0-dev", default-features = false, features = ["historical"], path = "../../../frame/session" } +pallet-iris = { version = "3.0.0", default-features = false, path = "../pallets/template" } + + frame-system = { version = "4.0.0-dev", default-features = false, path = "../../../frame/system" } pallet-timestamp = { version = "4.0.0-dev", default-features = false, path = "../../../frame/timestamp" } pallet-transaction-payment = { version = "4.0.0-dev", default-features = false, path = "../../../frame/transaction-payment" } @@ -48,7 +52,6 @@ frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = " frame-system-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../../../frame/system/benchmarking", optional = true } hex-literal = { version = "0.3.1", optional = true } -pallet-iris = { version = "3.0.0", default-features = false, path = "../pallets/template" } log = { version = "0.4.14", default-features = false } [build-dependencies] @@ -74,6 +77,7 @@ std = [ "pallet-iris-rpc-runtime-api/std", "pallet-transaction-payment/std", "pallet-assets/std", + "pallet-session/std", "sp-api/std", "sp-block-builder/std", "sp-consensus-aura/std", diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index 584ee692735e..bb82968cd380 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -14,7 +14,7 @@ use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::{crypto::KeyTypeId, OpaqueMetadata, Encode, Bytes}; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, - traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, IdentifyAccount, NumberFor, Verify, SaturatedConversion }, + traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, IdentifyAccount, NumberFor, Verify, SaturatedConversion, OpaqueKeys, ConvertInto }, transaction_validity::{TransactionSource, TransactionValidity}, ApplyExtrinsicResult, MultiSignature, }; @@ -23,6 +23,7 @@ use sp_std::prelude::*; use sp_version::NativeVersion; use sp_version::RuntimeVersion; use frame_system::EnsureRoot; +use pallet_session::historical as pallet_session_historical; // A few exports that help ease life for downstream crates. pub use frame_support::{ @@ -42,6 +43,7 @@ use pallet_transaction_payment::CurrencyAdapter; pub use sp_runtime::BuildStorage; pub use sp_runtime::{Perbill, Permill}; + /// Import the template pallet. pub use pallet_iris; @@ -201,6 +203,33 @@ impl frame_system::Config for Runtime { impl pallet_randomness_collective_flip::Config for Runtime {} +parameter_types! { + pub const Period: u32 = 5; + pub const Offset: u32 = 0; +} + +impl pallet_session::Config for Runtime { + type SessionHandler = ::KeyTypeIdProviders; + // type ShouldEndSession = ValidatorSet; + // type SessionManager = ValidatorSet; + type SessionManager = pallet_session::historical::NoteHistoricalRoot; + type Event = Event; + type Keys = opaque::SessionKeys; + type NextSessionRotation = pallet_session::PeriodicSessions; + type ShouldEndSession = pallet_session::PeriodicSessions; + // type ValidatorId = ::AccountId; + // type ValidatorIdOf = validatorset::ValidatorOf; + type ValidatorId = u64; + type ValidatorIdOf = ConvertInto; + type DisabledValidatorsThreshold = (); +} + + +impl pallet_session::historical::Config for Runtime { + type FullIdentification = u128; + type FullIdentificationOf = pallet_iris::ExposureOf; +} + parameter_types! { pub const MaxAuthorities: u32 = 32; } @@ -215,7 +244,7 @@ impl pallet_grandpa::Config for Runtime { type Event = Event; type Call = Call; - type KeyOwnerProofSystem = (); + type KeyOwnerProofSystem = Historical; type KeyOwnerProof = >::Proof; @@ -312,6 +341,7 @@ impl pallet_iris::Config for Runtime { type Call = Call; type AuthorityId = pallet_iris::crypto::TestAuthId; type Currency = Balances; + type SessionInterface = Self; } impl frame_system::offchain::CreateSignedTransaction for Runtime @@ -388,6 +418,8 @@ construct_runtime!( Iris: pallet_iris::{Pallet, Call, Storage, Event}, // removed call to make extrinsics uncallable Assets: pallet_assets::{Pallet, Storage, Event}, + Session: pallet_session::{Pallet, Storage, Event, Config}, + Historical: pallet_session_historical::{Pallet}, } ); // Iris: pallet_iris::{Pallet, Call, Storage, Event, ValidateUnsigned}, From f2822169f8b05234ceadae590bb09dd7df9e2f50 Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Thu, 13 Jan 2022 16:26:06 +0100 Subject: [PATCH 378/695] Fast/warp sync fixes (#10562) * Fast sync fixes * Fix gap blocks validation * Updated test * Formatting * Networking test --- client/consensus/babe/src/lib.rs | 6 +- client/db/src/lib.rs | 59 +++++++++++++------- client/network/src/protocol/sync.rs | 56 +++++++++++++++++-- client/service/src/client/client.rs | 3 +- client/state-db/src/lib.rs | 3 + client/state-db/src/noncanonical.rs | 22 +++++++- primitives/blockchain/src/header_metadata.rs | 9 ++- 7 files changed, 126 insertions(+), 32 deletions(-) diff --git a/client/consensus/babe/src/lib.rs b/client/consensus/babe/src/lib.rs index 612a05ffaa67..a86eac35a100 100644 --- a/client/consensus/babe/src/lib.rs +++ b/client/consensus/babe/src/lib.rs @@ -347,7 +347,11 @@ impl Config { { trace!(target: "babe", "Getting slot duration"); - let best_block_id = BlockId::Hash(client.usage_info().chain.best_hash); + let mut best_block_id = BlockId::Hash(client.usage_info().chain.best_hash); + if client.usage_info().chain.finalized_state.is_none() { + debug!(target: "babe", "No finalized state is available. Reading config from genesis"); + best_block_id = BlockId::Hash(client.usage_info().chain.genesis_hash); + } let runtime_api = client.runtime_api(); let version = runtime_api.api_version::>(&best_block_id)?; diff --git a/client/db/src/lib.rs b/client/db/src/lib.rs index 19766d76048e..d7550ff9aea1 100644 --- a/client/db/src/lib.rs +++ b/client/db/src/lib.rs @@ -477,7 +477,6 @@ impl BlockchainDb { let mut meta = self.meta.write(); if number.is_zero() { meta.genesis_hash = hash; - meta.finalized_hash = hash; } if is_best { @@ -1347,11 +1346,6 @@ impl Backend { } if number.is_zero() { - transaction.set_from_vec( - columns::META, - meta_keys::FINALIZED_BLOCK, - lookup_key.clone(), - ); transaction.set(columns::META, meta_keys::GENESIS_HASH, hash.as_ref()); if operation.commit_state { @@ -1447,14 +1441,15 @@ impl Backend { let finalized = number_u64 == 0 || pending_block.leaf_state.is_final(); finalized } else { - number.is_zero() || pending_block.leaf_state.is_final() + (number.is_zero() && last_finalized_num.is_zero()) || + pending_block.leaf_state.is_final() }; let header = &pending_block.header; let is_best = pending_block.leaf_state.is_best(); debug!(target: "db", - "DB Commit {:?} ({}), best={}, state={}, existing={}", - hash, number, is_best, operation.commit_state, existing_header, + "DB Commit {:?} ({}), best={}, state={}, existing={}, finalized={}", + hash, number, is_best, operation.commit_state, existing_header, finalized, ); self.state_usage.merge_sm(operation.old_state.usage_info()); @@ -2295,6 +2290,7 @@ pub(crate) mod tests { extrinsics_root: H256, ) -> H256 { insert_block(backend, number, parent_hash, changes, extrinsics_root, Vec::new(), None) + .unwrap() } pub fn insert_block( @@ -2305,7 +2301,7 @@ pub(crate) mod tests { extrinsics_root: H256, body: Vec>, transaction_index: Option>, - ) -> H256 { + ) -> Result { use sp_runtime::testing::Digest; let digest = Digest::default(); @@ -2329,9 +2325,9 @@ pub(crate) mod tests { if let Some(index) = transaction_index { op.update_transaction_index(index).unwrap(); } - backend.commit_operation(op).unwrap(); + backend.commit_operation(op)?; - header_hash + Ok(header_hash) } #[test] @@ -3019,7 +3015,6 @@ pub(crate) mod tests { { let header = backend.blockchain().header(BlockId::Hash(hash1)).unwrap().unwrap(); let mut op = backend.begin_operation().unwrap(); - backend.begin_state_operation(&mut op, BlockId::Hash(hash0)).unwrap(); op.set_block_data(header, None, None, None, NewBlockState::Best).unwrap(); backend.commit_operation(op).unwrap(); } @@ -3063,7 +3058,8 @@ pub(crate) mod tests { Default::default(), vec![i.into()], None, - ); + ) + .unwrap(); blocks.push(hash); prev_hash = hash; } @@ -3100,7 +3096,8 @@ pub(crate) mod tests { Default::default(), vec![i.into()], None, - ); + ) + .unwrap(); blocks.push(hash); prev_hash = hash; } @@ -3114,7 +3111,8 @@ pub(crate) mod tests { sp_core::H256::random(), vec![2.into()], None, - ); + ) + .unwrap(); insert_block( &backend, 3, @@ -3123,7 +3121,8 @@ pub(crate) mod tests { H256::random(), vec![3.into(), 11.into()], None, - ); + ) + .unwrap(); let mut op = backend.begin_operation().unwrap(); backend.begin_state_operation(&mut op, BlockId::Hash(blocks[4])).unwrap(); op.mark_head(BlockId::Hash(blocks[4])).unwrap(); @@ -3172,7 +3171,8 @@ pub(crate) mod tests { Default::default(), vec![i.into()], Some(index), - ); + ) + .unwrap(); blocks.push(hash); prev_hash = hash; } @@ -3206,7 +3206,8 @@ pub(crate) mod tests { Default::default(), vec![i.into()], None, - ); + ) + .unwrap(); blocks.push(hash); prev_hash = hash; } @@ -3220,7 +3221,8 @@ pub(crate) mod tests { sp_core::H256::random(), vec![42.into()], None, - ); + ) + .unwrap(); assert!(backend.remove_leaf_block(&best_hash).is_err()); assert!(backend.have_state_at(&prev_hash, 1)); backend.remove_leaf_block(&prev_hash).unwrap(); @@ -3290,4 +3292,21 @@ pub(crate) mod tests { assert_eq!(backend.blockchain().info().finalized_hash, block1); } + + #[test] + fn test_import_existing_state_fails() { + let backend: Backend = Backend::new_test(10, 10); + let genesis = + insert_block(&backend, 0, Default::default(), None, Default::default(), vec![], None) + .unwrap(); + + insert_block(&backend, 1, genesis, None, Default::default(), vec![], None).unwrap(); + let err = insert_block(&backend, 1, genesis, None, Default::default(), vec![], None) + .err() + .unwrap(); + match err { + sp_blockchain::Error::StateDatabase(m) if m == "Block already exists" => (), + e @ _ => panic!("Unexpected error {:?}", e), + } + } } diff --git a/client/network/src/protocol/sync.rs b/client/network/src/protocol/sync.rs index 69722dac22bc..af65dec1c3fe 100644 --- a/client/network/src/protocol/sync.rs +++ b/client/network/src/protocol/sync.rs @@ -1095,15 +1095,17 @@ impl ChainSync { } self.drain_blocks() }, - PeerSyncState::DownloadingGap(start_block) => { - let start_block = *start_block; + PeerSyncState::DownloadingGap(_) => { peer.state = PeerSyncState::Available; if let Some(gap_sync) = &mut self.gap_sync { gap_sync.blocks.clear_peer_download(who); - validate_blocks::(&blocks, who, Some(request))?; - gap_sync.blocks.insert(start_block, blocks, who.clone()); + if let Some(start_block) = + validate_blocks::(&blocks, who, Some(request))? + { + gap_sync.blocks.insert(start_block, blocks, who.clone()); + } gap = true; - gap_sync + let blocks: Vec<_> = gap_sync .blocks .drain(gap_sync.best_queued_number + One::one()) .into_iter() @@ -1126,7 +1128,9 @@ impl ChainSync { state: None, } }) - .collect() + .collect(); + debug!(target: "sync", "Drained {} gap blocks from {}", blocks.len(), gap_sync.best_queued_number); + blocks } else { debug!(target: "sync", "Unexpected gap block response from {}", who); return Err(BadPeer(who.clone(), rep::NO_BLOCK)) @@ -3169,4 +3173,44 @@ mod test { sync.peer_disconnected(&peer_id1); assert!(sync.fork_targets.len() == 0); } + + #[test] + fn can_import_response_with_missing_blocks() { + sp_tracing::try_init_simple(); + let mut client2 = Arc::new(TestClientBuilder::new().build()); + let blocks = (0..4).map(|_| build_block(&mut client2, None, false)).collect::>(); + + let empty_client = Arc::new(TestClientBuilder::new().build()); + + let mut sync = ChainSync::new( + SyncMode::Full, + empty_client.clone(), + Box::new(DefaultBlockAnnounceValidator), + 1, + None, + ) + .unwrap(); + + let peer_id1 = PeerId::random(); + let best_block = blocks[3].clone(); + sync.new_peer(peer_id1.clone(), best_block.hash(), *best_block.header().number()) + .unwrap(); + + sync.peers.get_mut(&peer_id1).unwrap().state = PeerSyncState::Available; + sync.peers.get_mut(&peer_id1).unwrap().common_number = 0; + + // Request all missing blocks and respond only with some. + let request = + get_block_request(&mut sync, FromBlock::Hash(best_block.hash()), 4, &peer_id1); + let response = + create_block_response(vec![blocks[3].clone(), blocks[2].clone(), blocks[1].clone()]); + sync.on_block_data(&peer_id1, Some(request.clone()), response).unwrap(); + assert_eq!(sync.best_queued_number, 0); + + // Request should only contain the missing block. + let request = get_block_request(&mut sync, FromBlock::Number(1), 1, &peer_id1); + let response = create_block_response(vec![blocks[0].clone()]); + sync.on_block_data(&peer_id1, Some(request), response).unwrap(); + assert_eq!(sync.best_queued_number, 4); + } } diff --git a/client/service/src/client/client.rs b/client/service/src/client/client.rs index 8769865978bf..7673a7b4c538 100644 --- a/client/service/src/client/client.rs +++ b/client/service/src/client/client.rs @@ -1726,9 +1726,8 @@ where .block_status(&BlockId::Hash(hash)) .map_err(|e| ConsensusError::ClientImport(e.to_string()))? { - BlockStatus::InChainWithState | BlockStatus::Queued if !import_existing => + BlockStatus::InChainWithState | BlockStatus::Queued => return Ok(ImportResult::AlreadyInChain), - BlockStatus::InChainWithState | BlockStatus::Queued => {}, BlockStatus::InChainPruned if !import_existing => return Ok(ImportResult::AlreadyInChain), BlockStatus::InChainPruned => {}, diff --git a/client/state-db/src/lib.rs b/client/state-db/src/lib.rs index b7d58bb808a7..74f218e88f86 100644 --- a/client/state-db/src/lib.rs +++ b/client/state-db/src/lib.rs @@ -130,6 +130,8 @@ pub enum Error { InvalidPruningMode(String), /// Too many unfinalized sibling blocks inserted. TooManySiblingBlocks, + /// Trying to insert existing block. + BlockAlreadyExists, } /// Pinning error type. @@ -154,6 +156,7 @@ impl fmt::Debug for Error { Error::InvalidParent => write!(f, "Trying to insert block with unknown parent"), Error::InvalidPruningMode(e) => write!(f, "Expected pruning mode: {}", e), Error::TooManySiblingBlocks => write!(f, "Too many sibling blocks inserted"), + Error::BlockAlreadyExists => write!(f, "Block already exists"), } } } diff --git a/client/state-db/src/noncanonical.rs b/client/state-db/src/noncanonical.rs index d7c83492e563..7d6fcbced786 100644 --- a/client/state-db/src/noncanonical.rs +++ b/client/state-db/src/noncanonical.rs @@ -210,9 +210,10 @@ impl NonCanonicalOverlay { insert_values(&mut values, record.inserted); trace!( target: "state-db", - "Uncanonicalized journal entry {}.{} ({} inserted, {} deleted)", + "Uncanonicalized journal entry {}.{} ({:?}) ({} inserted, {} deleted)", block, index, + record.hash, overlay.inserted.len(), overlay.deleted.len() ); @@ -296,6 +297,9 @@ impl NonCanonicalOverlay { if level.blocks.len() >= MAX_BLOCKS_PER_LEVEL as usize { return Err(Error::TooManySiblingBlocks) } + if level.blocks.iter().any(|b| b.hash == *hash) { + return Err(Error::BlockAlreadyExists) + } let index = level.available_index(); let journal_key = to_journal_key(number, index); @@ -641,7 +645,7 @@ mod tests { use super::{to_journal_key, NonCanonicalOverlay}; use crate::{ test::{make_changeset, make_db}, - ChangeSet, CommitSet, MetaDb, + ChangeSet, CommitSet, Error, MetaDb, }; use sp_core::H256; use std::io; @@ -710,6 +714,20 @@ mod tests { .unwrap(); } + #[test] + fn insert_existing_fails() { + let db = make_db(&[]); + let h1 = H256::random(); + let mut overlay = NonCanonicalOverlay::::new(&db).unwrap(); + overlay + .insert::(&h1, 2, &H256::default(), ChangeSet::default()) + .unwrap(); + assert!(matches!( + overlay.insert::(&h1, 2, &H256::default(), ChangeSet::default()), + Err(Error::BlockAlreadyExists) + )); + } + #[test] #[should_panic] fn canonicalize_unknown_panics() { diff --git a/primitives/blockchain/src/header_metadata.rs b/primitives/blockchain/src/header_metadata.rs index 9f388dc58fbc..6e8dc562473d 100644 --- a/primitives/blockchain/src/header_metadata.rs +++ b/primitives/blockchain/src/header_metadata.rs @@ -20,7 +20,7 @@ use lru::LruCache; use parking_lot::RwLock; -use sp_runtime::traits::{Block as BlockT, Header, NumberFor}; +use sp_runtime::traits::{Block as BlockT, Header, NumberFor, One}; /// Set to the expected max difference between `best` and `finalized` blocks at sync. const LRU_CACHE_SIZE: usize = 5_000; @@ -37,7 +37,14 @@ pub fn lowest_common_ancestor + ?Sized>( id_two: Block::Hash, ) -> Result, T::Error> { let mut header_one = backend.header_metadata(id_one)?; + if header_one.parent == id_two { + return Ok(HashAndNumber { hash: id_two, number: header_one.number - One::one() }) + } + let mut header_two = backend.header_metadata(id_two)?; + if header_two.parent == id_one { + return Ok(HashAndNumber { hash: id_one, number: header_one.number }) + } let mut orig_header_one = header_one.clone(); let mut orig_header_two = header_two.clone(); From 970a46aa188ed85f19fe84098d5cb2f4610da8ee Mon Sep 17 00:00:00 2001 From: driemworks Date: Thu, 13 Jan 2022 10:35:49 -0600 Subject: [PATCH 379/695] add iris session pallet --- Cargo.lock | 22 + bin/node-template/node/src/chain_spec.rs | 39 +- .../pallets/iris-session/Cargo.toml | 58 ++ .../pallets/iris-session/README.md | 1 + .../pallets/iris-session/src/benchmarking.rs | 20 + .../pallets/iris-session/src/lib.rs | 333 +++++++++++ .../pallets/iris-session/src/mock.rs | 200 +++++++ .../pallets/iris-session/src/tests.rs | 59 ++ bin/node-template/pallets/template/src/lib.rs | 542 +----------------- .../pallets/template/src/types.rs | 16 - bin/node-template/runtime/Cargo.toml | 3 + bin/node-template/runtime/src/lib.rs | 63 +- 12 files changed, 763 insertions(+), 593 deletions(-) create mode 100644 bin/node-template/pallets/iris-session/Cargo.toml create mode 100644 bin/node-template/pallets/iris-session/README.md create mode 100644 bin/node-template/pallets/iris-session/src/benchmarking.rs create mode 100644 bin/node-template/pallets/iris-session/src/lib.rs create mode 100644 bin/node-template/pallets/iris-session/src/mock.rs create mode 100644 bin/node-template/pallets/iris-session/src/tests.rs delete mode 100644 bin/node-template/pallets/template/src/types.rs diff --git a/Cargo.lock b/Cargo.lock index ea77256ccb2b..bd7ea5e76845 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5042,6 +5042,7 @@ dependencies = [ "pallet-grandpa", "pallet-iris", "pallet-iris-rpc-runtime-api", + "pallet-iris-session", "pallet-randomness-collective-flip", "pallet-session", "pallet-sudo", @@ -5896,6 +5897,27 @@ dependencies = [ "sp-runtime", ] +[[package]] +name = "pallet-iris-session" +version = "3.0.0" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log 0.4.14", + "pallet-assets", + "pallet-balances", + "pallet-session", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-keystore", + "sp-runtime", + "sp-staking", + "sp-std", +] + [[package]] name = "pallet-lottery" version = "4.0.0-dev" diff --git a/bin/node-template/node/src/chain_spec.rs b/bin/node-template/node/src/chain_spec.rs index 159efe9fa8bc..324f3d12c370 100644 --- a/bin/node-template/node/src/chain_spec.rs +++ b/bin/node-template/node/src/chain_spec.rs @@ -1,6 +1,9 @@ -:use node_template_runtime::{ - AccountId, AuraConfig, BalancesConfig, GenesisConfig, GrandpaConfig, Signature, SudoConfig, +use node_template_runtime::{ + AccountId, AuraConfig, BalancesConfig, + GenesisConfig, GrandpaConfig, Signature, + SudoConfig, SessionConfig, IrisSessionConfig, SystemConfig, WASM_BINARY, + opaque::SessionKeys, }; use sc_service::ChainType; use sp_consensus_aura::sr25519::AuthorityId as AuraId; @@ -14,6 +17,11 @@ use sp_runtime::traits::{IdentifyAccount, Verify}; /// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type. pub type ChainSpec = sc_service::GenericChainSpec; + +fn session_keys(aura: AuraId, grandpa: GrandpaId) -> SessionKeys { + SessionKeys { aura, grandpa } +} + /// Generate a crypto pair from seed. pub fn get_from_seed(seed: &str) -> ::Public { TPublic::Pair::from_string(&format!("//{}", seed), None) @@ -33,7 +41,11 @@ where /// Generate an Aura authority key. pub fn authority_keys_from_seed(s: &str) -> (AccountId, AuraId, GrandpaId) { - (get_account_id_from_seed::(s), get_from_seed::(s), get_from_seed::(s)) + ( + get_account_id_from_seed::(s), + get_from_seed::(s), + get_from_seed::(s) + ) } pub fn development_config() -> Result { @@ -49,7 +61,7 @@ pub fn development_config() -> Result { testnet_genesis( wasm_binary, // Initial PoA authorities - vec![authority_keys_from_seed("Alice")], + vec![authority_keys_from_seed("Alice"), authority_keys_from_seed("Bob")], // Sudo account get_account_id_from_seed::("Alice"), // Pre-funded accounts @@ -140,17 +152,22 @@ fn testnet_genesis( // Configure endowed accounts with initial balance of 1 << 60. balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 60)).collect(), }, - aura: AuraConfig { - authorities: initial_authorities.iter().map(|x| (x.0.clone())).collect(), - }, - grandpa: GrandpaConfig { - authorities: initial_authorities.iter().map(|x| (x.1.clone(), 1)).collect(), + iris_session: IrisSessionConfig { + initial_validators: initial_authorities.iter().map(|x| x.0.clone()).collect::>(), }, - session: Some(SessionConfig { + session: SessionConfig { keys: initial_authorities.iter().map(|x| { (x.0.clone(), x.0.clone(), session_keys(x.1.clone(), x.2.clone())) }).collect::>(), - }), + }, + aura: AuraConfig { + // authorities: initial_authorities.iter().map(|x| (x.1.clone())).collect(), + authorities: vec![], + }, + grandpa: GrandpaConfig { + // authorities: initial_authorities.iter().map(|x| (x.2.clone(), 1)).collect(), + authorities: vec![], + }, sudo: SudoConfig { // Assign network admin rights. key: root_key, diff --git a/bin/node-template/pallets/iris-session/Cargo.toml b/bin/node-template/pallets/iris-session/Cargo.toml new file mode 100644 index 000000000000..9d04bb8d8679 --- /dev/null +++ b/bin/node-template/pallets/iris-session/Cargo.toml @@ -0,0 +1,58 @@ +[package] +authors = ['Iridium '] +edition = '2018' +name = 'pallet-iris-session' +version = "3.0.0" +license = "Unlicense" +homepage = "https://substrate.dev" +repository = "https://github.com/substrate-developer-hub/substrate-node-template/" +description = "FRAME pallet template for Iris storage providers." +readme = "README.md" +publish = false + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ + "derive", +] } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } + +sp-io = { default-features = false, version = "4.0.0-dev", path = "../../../../primitives/io" } +sp-std = { default-features = false, version = "4.0.0-dev", path = "../../../../primitives/std" } +sp-core = { default-features = false, version = "4.0.0-dev", path = "../../../../primitives/core" } +sp-runtime = { default-features = false, version = "4.0.0-dev", path = "../../../../primitives/runtime" } +sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/staking" } +sp-keystore = { version = "0.10.0-dev", path = "../../../../primitives/keystore", optional = true } + +frame-support = { default-features = false, version = "4.0.0-dev", path = "../../../../frame/support" } +frame-system = { default-features = false, version = "4.0.0-dev", path = "../../../../frame/system" } +frame-benchmarking = { default-features = false, version = "4.0.0-dev", path = "../../../../frame/benchmarking", optional = true } +log = { version = "0.4.14", default-features = false } + +pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../../../../frame/balances" } +pallet-assets = { version = "4.0.0-dev", default-features = false, path = "../../../../frame/assets" } +pallet-session = { version = "4.0.0-dev", default-features = false, features = ["historical"], path = "../../../../frame/session" } + +[features] +default = ['std'] +std = [ + 'codec/std', + 'scale-info/std', + 'frame-support/std', + 'frame-system/std', + 'frame-benchmarking/std', + 'sp-io/std', + 'sp-std/std', + 'sp-keystore/std', + 'sp-runtime/std', + 'sp-staking/std', + 'log/std', + 'pallet-assets/std', + 'pallet-balances/std', + 'pallet-session/std', +] + +runtime-benchmarks = ["frame-benchmarking"] +try-runtime = ["frame-support/try-runtime"] diff --git a/bin/node-template/pallets/iris-session/README.md b/bin/node-template/pallets/iris-session/README.md new file mode 100644 index 000000000000..8d751a42207d --- /dev/null +++ b/bin/node-template/pallets/iris-session/README.md @@ -0,0 +1 @@ +License: Unlicense \ No newline at end of file diff --git a/bin/node-template/pallets/iris-session/src/benchmarking.rs b/bin/node-template/pallets/iris-session/src/benchmarking.rs new file mode 100644 index 000000000000..2117c048cfbd --- /dev/null +++ b/bin/node-template/pallets/iris-session/src/benchmarking.rs @@ -0,0 +1,20 @@ +//! Benchmarking setup for pallet-template + +use super::*; + +#[allow(unused)] +use crate::Pallet as Template; +use frame_benchmarking::{benchmarks, impl_benchmark_test_suite, whitelisted_caller}; +use frame_system::RawOrigin; + +benchmarks! { + do_something { + let s in 0 .. 100; + let caller: T::AccountId = whitelisted_caller(); + }: _(RawOrigin::Signed(caller), s) + verify { + assert_eq!(Something::::get(), Some(s)); + } +} + +impl_benchmark_test_suite!(Template, crate::mock::new_test_ext(), crate::mock::Test); diff --git a/bin/node-template/pallets/iris-session/src/lib.rs b/bin/node-template/pallets/iris-session/src/lib.rs new file mode 100644 index 000000000000..aaa21dd8a446 --- /dev/null +++ b/bin/node-template/pallets/iris-session/src/lib.rs @@ -0,0 +1,333 @@ +//! # Iris Session Pallet +//! +//! The Iris Session Pallet allows addition and removal of +//! storage providers via extrinsics (transaction calls), in +//! Substrate-based PoA networks. It also integrates with the im-online pallet +//! to automatically remove offline storage providers. +//! +//! The pallet uses the Session pallet and implements related traits for session +//! management. Currently it uses periodic session rotation provided by the +//! session pallet to automatically rotate sessions. For this reason, the +//! validator addition and removal becomes effective only after 2 sessions +//! (queuing + applying). + +#![cfg_attr(not(feature = "std"), no_std)] + +mod mock; +mod tests; + +use frame_support::{ + ensure, + pallet_prelude::*, + traits::{EstimateNextSessionRotation, Get, ValidatorSet, ValidatorSetWithIdentification}, +}; +use log; +pub use pallet::*; +use sp_runtime::traits::{Convert, Zero}; +use sp_staking::offence::{Offence, OffenceError, ReportOffence}; +use sp_std::{collections::btree_set::BTreeSet, prelude::*}; + +pub const LOG_TARGET: &'static str = "runtime::validator-set"; + +#[frame_support::pallet] +pub mod pallet { + use super::*; + use frame_system::pallet_prelude::*; + + /// Configure the pallet by specifying the parameters and types on which it + /// depends. + #[pallet::config] + pub trait Config: frame_system::Config + pallet_session::Config { + /// The Event type. + type Event: From> + IsType<::Event>; + + /// Origin for adding or removing a validator. + type AddRemoveOrigin: EnsureOrigin; + + /// Minimum number of validators to leave in the validator set during + /// auto removal. + type MinAuthorities: Get; + } + + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet(_); + + #[pallet::storage] + #[pallet::getter(fn validators)] + pub type Validators = StorageValue<_, Vec, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn approved_validators)] + pub type ApprovedValidators = StorageValue<_, Vec, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn validators_to_remove)] + pub type OfflineValidators = StorageValue<_, Vec, ValueQuery>; + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + /// New validator addition initiated. Effective in ~2 sessions. + ValidatorAdditionInitiated(T::AccountId), + + /// Validator removal initiated. Effective in ~2 sessions. + ValidatorRemovalInitiated(T::AccountId), + } + + // Errors inform users that something went wrong. + #[pallet::error] + pub enum Error { + /// Target (post-removal) validator count is below the minimum. + TooLowValidatorCount, + /// Validator is already in the validator set. + Duplicate, + /// Validator is not approved for re-addition. + ValidatorNotApproved, + /// Only the validator can add itself back after coming online. + BadOrigin, + } + + #[pallet::hooks] + impl Hooks> for Pallet {} + + #[pallet::genesis_config] + pub struct GenesisConfig { + pub initial_validators: Vec, + } + + #[cfg(feature = "std")] + impl Default for GenesisConfig { + fn default() -> Self { + Self { initial_validators: Default::default() } + } + } + + #[pallet::genesis_build] + impl GenesisBuild for GenesisConfig { + fn build(&self) { + Pallet::::initialize_validators(&self.initial_validators); + } + } + + #[pallet::call] + impl Pallet { + /// Add a new validator. + /// + /// New validator's session keys should be set in Session pallet before + /// calling this. + /// + /// The origin can be configured using the `AddRemoveOrigin` type in the + /// host runtime. Can also be set to sudo/root. + #[pallet::weight(0)] + pub fn add_validator(origin: OriginFor, validator_id: T::AccountId) -> DispatchResult { + T::AddRemoveOrigin::ensure_origin(origin)?; + + Self::do_add_validator(validator_id.clone())?; + Self::approve_validator(validator_id)?; + + Ok(()) + } + + /// Remove a validator. + /// + /// The origin can be configured using the `AddRemoveOrigin` type in the + /// host runtime. Can also be set to sudo/root. + #[pallet::weight(0)] + pub fn remove_validator( + origin: OriginFor, + validator_id: T::AccountId, + ) -> DispatchResult { + T::AddRemoveOrigin::ensure_origin(origin)?; + + Self::do_remove_validator(validator_id.clone())?; + Self::unapprove_validator(validator_id)?; + + Ok(()) + } + + /// Add an approved validator again when it comes back online. + /// + /// For this call, the dispatch origin must be the validator itself. + #[pallet::weight(0)] + pub fn add_validator_again( + origin: OriginFor, + validator_id: T::AccountId, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + ensure!(who == validator_id, Error::::BadOrigin); + + let approved_set: BTreeSet<_> = >::get().into_iter().collect(); + ensure!(approved_set.contains(&validator_id), Error::::ValidatorNotApproved); + + Self::do_add_validator(validator_id)?; + + Ok(()) + } + } +} + +impl Pallet { + fn initialize_validators(validators: &[T::AccountId]) { + assert!(validators.len() > 1, "At least 2 validators should be initialized"); + assert!(>::get().is_empty(), "Validators are already initialized!"); + >::put(validators); + >::put(validators); + } + + fn do_add_validator(validator_id: T::AccountId) -> DispatchResult { + let validator_set: BTreeSet<_> = >::get().into_iter().collect(); + ensure!(!validator_set.contains(&validator_id), Error::::Duplicate); + >::mutate(|v| v.push(validator_id.clone())); + + Self::deposit_event(Event::ValidatorAdditionInitiated(validator_id.clone())); + log::debug!(target: LOG_TARGET, "Validator addition initiated."); + + Ok(()) + } + + fn do_remove_validator(validator_id: T::AccountId) -> DispatchResult { + let mut validators = >::get(); + + // Ensuring that the post removal, target validator count doesn't go + // below the minimum. + ensure!( + validators.len().saturating_sub(1) as u32 >= T::MinAuthorities::get(), + Error::::TooLowValidatorCount + ); + + validators.retain(|v| *v != validator_id); + + >::put(validators); + + Self::deposit_event(Event::ValidatorRemovalInitiated(validator_id.clone())); + log::debug!(target: LOG_TARGET, "Validator removal initiated."); + + Ok(()) + } + + fn approve_validator(validator_id: T::AccountId) -> DispatchResult { + let approved_set: BTreeSet<_> = >::get().into_iter().collect(); + ensure!(!approved_set.contains(&validator_id), Error::::Duplicate); + >::mutate(|v| v.push(validator_id.clone())); + Ok(()) + } + + fn unapprove_validator(validator_id: T::AccountId) -> DispatchResult { + let mut approved_set = >::get(); + approved_set.retain(|v| *v != validator_id); + Ok(()) + } + + // Adds offline validators to a local cache for removal at new session. + fn mark_for_removal(validator_id: T::AccountId) { + >::mutate(|v| v.push(validator_id)); + log::debug!(target: LOG_TARGET, "Offline validator marked for auto removal."); + } + + // Removes offline validators from the validator set and clears the offline + // cache. It is called in the session change hook and removes the validators + // who were reported offline during the session that is ending. We do not + // check for `MinAuthorities` here, because the offline validators will not + // produce blocks and will have the same overall effect on the runtime. + fn remove_offline_validators() { + let validators_to_remove: BTreeSet<_> = >::get().into_iter().collect(); + + // Delete from active validator set. + >::mutate(|vs| vs.retain(|v| !validators_to_remove.contains(v))); + log::debug!( + target: LOG_TARGET, + "Initiated removal of {:?} offline validators.", + validators_to_remove.len() + ); + + // Clear the offline validator list to avoid repeated deletion. + >::put(Vec::::new()); + } +} + +// Provides the new set of validators to the session module when session is +// being rotated. +impl pallet_session::SessionManager for Pallet { + // Plan a new session and provide new validator set. + fn new_session(_new_index: u32) -> Option> { + // Remove any offline validators. This will only work when the runtime + // also has the im-online pallet. + Self::remove_offline_validators(); + + log::debug!(target: LOG_TARGET, "New session called; updated validator set provided."); + + Some(Self::validators()) + } + + fn end_session(_end_index: u32) {} + + fn start_session(_start_index: u32) {} +} + +impl EstimateNextSessionRotation for Pallet { + fn average_session_length() -> T::BlockNumber { + Zero::zero() + } + + fn estimate_current_session_progress( + _now: T::BlockNumber, + ) -> (Option, frame_support::dispatch::Weight) { + (None, Zero::zero()) + } + + fn estimate_next_session_rotation( + _now: T::BlockNumber, + ) -> (Option, frame_support::dispatch::Weight) { + (None, Zero::zero()) + } +} + +// Implementation of Convert trait for mapping ValidatorId with AccountId. +pub struct ValidatorOf(sp_std::marker::PhantomData); + +impl Convert> for ValidatorOf { + fn convert(account: T::ValidatorId) -> Option { + Some(account) + } +} + +impl ValidatorSet for Pallet { + type ValidatorId = T::ValidatorId; + type ValidatorIdOf = T::ValidatorIdOf; + + fn session_index() -> sp_staking::SessionIndex { + pallet_session::Pallet::::current_index() + } + + fn validators() -> Vec { + pallet_session::Pallet::::validators() + } +} + +impl ValidatorSetWithIdentification for Pallet { + type Identification = T::ValidatorId; + type IdentificationOf = ValidatorOf; +} + +// Offence reporting and unresponsiveness management. +impl> + ReportOffence for Pallet +{ + fn report_offence(_reporters: Vec, offence: O) -> Result<(), OffenceError> { + let offenders = offence.offenders(); + + for (v, _) in offenders.into_iter() { + Self::mark_for_removal(v); + } + + Ok(()) + } + + fn is_known_offence( + _offenders: &[(T::AccountId, T::AccountId)], + _time_slot: &O::TimeSlot, + ) -> bool { + false + } +} diff --git a/bin/node-template/pallets/iris-session/src/mock.rs b/bin/node-template/pallets/iris-session/src/mock.rs new file mode 100644 index 000000000000..754ee8b0aaca --- /dev/null +++ b/bin/node-template/pallets/iris-session/src/mock.rs @@ -0,0 +1,200 @@ +//! Mock helpers for Validator Set pallet. + +#![cfg(test)] + +use super::*; +use crate as validator_set; +use frame_support::{parameter_types, traits::GenesisBuild, BasicExternalities}; +use frame_system::EnsureRoot; +use pallet_session::*; +use sp_core::{crypto::key_types::DUMMY, H256}; +use sp_runtime::{ + impl_opaque_keys, + testing::{Header, UintAuthorityId}, + traits::{BlakeTwo256, IdentityLookup, OpaqueKeys}, + KeyTypeId, RuntimeAppPublic, +}; +use std::cell::RefCell; + +impl_opaque_keys! { + pub struct MockSessionKeys { + pub dummy: UintAuthorityId, + } +} + +impl From for MockSessionKeys { + fn from(dummy: UintAuthorityId) -> Self { + Self { dummy } + } +} + +pub const KEY_ID_A: KeyTypeId = KeyTypeId([4; 4]); +pub const KEY_ID_B: KeyTypeId = KeyTypeId([9; 4]); + +#[derive(Debug, Clone, codec::Encode, codec::Decode, PartialEq, Eq)] +pub struct PreUpgradeMockSessionKeys { + pub a: [u8; 32], + pub b: [u8; 64], +} + +impl OpaqueKeys for PreUpgradeMockSessionKeys { + type KeyTypeIdProviders = (); + + fn key_ids() -> &'static [KeyTypeId] { + &[KEY_ID_A, KEY_ID_B] + } + + fn get_raw(&self, i: KeyTypeId) -> &[u8] { + match i { + i if i == KEY_ID_A => &self.a[..], + i if i == KEY_ID_B => &self.b[..], + _ => &[], + } + } +} + +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlock; + +frame_support::construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + ValidatorSet: validator_set::{Pallet, Call, Storage, Event, Config}, + Session: pallet_session::{Pallet, Call, Storage, Event, Config}, + } +); + +thread_local! { + pub static VALIDATORS: RefCell> = RefCell::new(vec![1, 2, 3]); + pub static NEXT_VALIDATORS: RefCell> = RefCell::new(vec![1, 2, 3]); + pub static AUTHORITIES: RefCell> = + RefCell::new(vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); + pub static FORCE_SESSION_END: RefCell = RefCell::new(false); + pub static SESSION_LENGTH: RefCell = RefCell::new(2); + pub static SESSION_CHANGED: RefCell = RefCell::new(false); + pub static DISABLED: RefCell = RefCell::new(false); + pub static BEFORE_SESSION_END_CALLED: RefCell = RefCell::new(false); +} + +pub struct TestSessionHandler; +impl SessionHandler for TestSessionHandler { + const KEY_TYPE_IDS: &'static [sp_runtime::KeyTypeId] = &[UintAuthorityId::ID]; + fn on_genesis_session(_validators: &[(u64, T)]) {} + fn on_new_session( + changed: bool, + validators: &[(u64, T)], + _queued_validators: &[(u64, T)], + ) { + SESSION_CHANGED.with(|l| *l.borrow_mut() = changed); + AUTHORITIES.with(|l| { + *l.borrow_mut() = validators + .iter() + .map(|(_, id)| id.get::(DUMMY).unwrap_or_default()) + .collect() + }); + } + fn on_disabled(_validator_index: u32) { + DISABLED.with(|l| *l.borrow_mut() = true) + } + fn on_before_session_ending() { + BEFORE_SESSION_END_CALLED.with(|b| *b.borrow_mut() = true); + } +} + +pub struct TestShouldEndSession; +impl ShouldEndSession for TestShouldEndSession { + fn should_end_session(now: u64) -> bool { + let l = SESSION_LENGTH.with(|l| *l.borrow()); + now % l == 0 || + FORCE_SESSION_END.with(|l| { + let r = *l.borrow(); + *l.borrow_mut() = false; + r + }) + } +} + +pub fn authorities() -> Vec { + AUTHORITIES.with(|l| l.borrow().to_vec()) +} + +pub fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + let keys: Vec<_> = NEXT_VALIDATORS + .with(|l| l.borrow().iter().cloned().map(|i| (i, i, UintAuthorityId(i).into())).collect()); + BasicExternalities::execute_with_storage(&mut t, || { + for (ref k, ..) in &keys { + frame_system::Pallet::::inc_providers(k); + } + frame_system::Pallet::::inc_providers(&4); + frame_system::Pallet::::inc_providers(&69); + }); + validator_set::GenesisConfig:: { + initial_validators: keys.iter().map(|x| x.0).collect::>(), + } + .assimilate_storage(&mut t) + .unwrap(); + pallet_session::GenesisConfig:: { keys: keys.clone() } + .assimilate_storage(&mut t) + .unwrap(); + sp_io::TestExternalities::new(t) +} + +parameter_types! { + pub const MinimumPeriod: u64 = 5; + pub const BlockHashCount: u64 = 250; + pub BlockWeights: frame_system::limits::BlockWeights = + frame_system::limits::BlockWeights::simple_max(1024); +} + +impl frame_system::Config for Test { + type BaseCallFilter = frame_support::traits::Everything; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Call = Call; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = Event; + type BlockHashCount = BlockHashCount; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); +} + +parameter_types! { + pub const MinAuthorities: u32 = 2; +} + +impl validator_set::Config for Test { + type AddRemoveOrigin = EnsureRoot; + type Event = Event; + type MinAuthorities = MinAuthorities; +} + +impl pallet_session::Config for Test { + type ValidatorId = ::AccountId; + type ValidatorIdOf = validator_set::ValidatorOf; + type ShouldEndSession = TestShouldEndSession; + type NextSessionRotation = (); + type SessionManager = ValidatorSet; + type SessionHandler = TestSessionHandler; + type Keys = MockSessionKeys; + type WeightInfo = (); + type Event = Event; +} diff --git a/bin/node-template/pallets/iris-session/src/tests.rs b/bin/node-template/pallets/iris-session/src/tests.rs new file mode 100644 index 000000000000..3feb309fd38d --- /dev/null +++ b/bin/node-template/pallets/iris-session/src/tests.rs @@ -0,0 +1,59 @@ +//! Tests for the Validator Set pallet. + +#![cfg(test)] + +use super::*; +use crate::mock::{authorities, new_test_ext, Origin, Session, Test, ValidatorSet}; +use frame_support::{assert_noop, assert_ok, pallet_prelude::*}; +use sp_runtime::testing::UintAuthorityId; + +#[test] +fn simple_setup_should_work() { + new_test_ext().execute_with(|| { + assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); + assert_eq!(ValidatorSet::validators(), vec![1u64, 2u64, 3u64]); + assert_eq!(Session::validators(), vec![1, 2, 3]); + }); +} + +#[test] +fn add_validator_updates_validators_list() { + new_test_ext().execute_with(|| { + assert_ok!(ValidatorSet::add_validator(Origin::root(), 4)); + assert_eq!(ValidatorSet::validators(), vec![1u64, 2u64, 3u64, 4u64]) + }); +} + +#[test] +fn remove_validator_updates_validators_list() { + new_test_ext().execute_with(|| { + assert_ok!(ValidatorSet::remove_validator(Origin::root(), 2)); + assert_eq!(ValidatorSet::validators(), vec![1u64, 3u64]); + }); +} + +#[test] +fn add_validator_fails_with_invalid_origin() { + new_test_ext().execute_with(|| { + assert_noop!(ValidatorSet::add_validator(Origin::signed(1), 4), DispatchError::BadOrigin); + }); +} + +#[test] +fn remove_validator_fails_with_invalid_origin() { + new_test_ext().execute_with(|| { + assert_noop!( + ValidatorSet::remove_validator(Origin::signed(1), 4), + DispatchError::BadOrigin + ); + }); +} + +#[test] +fn duplicate_check() { + new_test_ext().execute_with(|| { + assert_ok!(ValidatorSet::add_validator(Origin::root(), 4)); + assert_eq!(ValidatorSet::validators(), vec![1u64, 2u64, 3u64, 4u64]); + assert_noop!(ValidatorSet::add_validator(Origin::root(), 4), Error::::Duplicate); + }); +} diff --git a/bin/node-template/pallets/template/src/lib.rs b/bin/node-template/pallets/template/src/lib.rs index b05d2ffaedf4..8d7dcdf6e32e 100644 --- a/bin/node-template/pallets/template/src/lib.rs +++ b/bin/node-template/pallets/template/src/lib.rs @@ -51,110 +51,17 @@ use sp_runtime::{ ipfs, }, RuntimeDebug, - traits::{ - StaticLookup, - Convert, - }, + traits::StaticLookup, }; use sp_std::{ str, vec::Vec, prelude::*, convert::TryInto, - collections::btree_map::BTreeMap, }; -use pallet_session::historical; - pub const KEY_TYPE: KeyTypeId = KeyTypeId(*b"iris"); -pub type SessionIndex = u32; -pub type EraIndex = u32; -pub type RewardPoint = u32; - -/// Information regarding the active era (era in used in session). -#[derive(Encode, Decode, RuntimeDebug, TypeInfo)] -pub struct ActiveEraInfo { - /// Index of era. - pub index: EraIndex, - /// Anchor era number of this era. - pub set_id: u32, - /// Moment of start expressed as millisecond from `$UNIX_EPOCH`. - /// - /// Start can be none if start hasn't been set for the era yet, - /// Start is set on the first on_finalize of the era to guarantee usage of `Time`. - start: Option, -} - -/// Reward points of an era. Used to split era total payout between validators. -/// -/// This points will be used to reward validators and their respective nominators. -#[derive(PartialEq, Encode, Decode, Default, RuntimeDebug, TypeInfo)] -pub struct EraRewardPoints { - /// Total number of points. Equals the sum of reward points for each validator. - total: RewardPoint, - /// The reward points earned by a given validator. - individual: BTreeMap, -} - -/// Means for interacting with a specialized version of the `session` trait. -/// -/// This is needed because `Staking` sets the `ValidatorIdOf` of the `pallet_session::Config` -pub trait SessionInterface: frame_system::Config { - /// Disable a given validator by stash ID. - /// - /// Returns `true` if new era should be forced at the end of this session. - /// This allows preventing a situation where there is too many validators - /// disabled and block production stalls. - fn disable_validator(validator: &AccountId) -> Result; - /// Get the validators from session. - fn validators() -> Vec; - /// Prune historical session tries up to but not including the given index. - fn prune_historical_up_to(up_to: SessionIndex); - - fn is_active_validator(id: KeyTypeId, key_data: &[u8]) -> Option; -} - -impl SessionInterface<::AccountId> for T -where - T: pallet_session::Config::AccountId>, - T: pallet_session::historical::Config< - FullIdentification = u128, - FullIdentificationOf = ExposureOf, - >, - T::SessionHandler: pallet_session::SessionHandler<::AccountId>, - T::SessionManager: pallet_session::SessionManager<::AccountId>, - T::ValidatorIdOf: Convert< - ::AccountId, - Option<::AccountId>, - >, -{ - fn disable_validator(validator: &::AccountId) -> Result { - >::disable(validator) - } - - fn validators() -> Vec<::AccountId> { - >::validators() - } - - fn prune_historical_up_to(up_to: SessionIndex) { - >::prune_up_to(up_to); - } - - fn is_active_validator( - id: KeyTypeId, - key_data: &[u8], - ) -> Option<::AccountId> { - let who = >::key_owner(id, key_data); - if who.is_none() { - return None; - } - Self::validators().into_iter().find(|v| { - log::info!("check {:#?} == {:#?}", v, who); - T::ValidatorIdOf::convert(v.clone()) == who - }) - } -} pub mod crypto { use crate::KEY_TYPE; @@ -190,12 +97,6 @@ pub enum DataCommand { CatBytes(AccountId, Vec, AccountId), } -/// Something that can provide a set of validators for the next era. -pub trait ValidatorsProvider { - /// A new set of validators. - fn validators() -> Vec<(AccountId, u128)>; -} - pub use pallet::*; #[cfg(test)] @@ -232,20 +133,12 @@ pub mod pallet { type Call: From>; /// the currency used type Currency: ReservableCurrency; - /// interface for interacting with the session pallet - type SessionInterface: self::SessionInterface; } #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] pub struct Pallet(_); - - #[pallet::type_value] - pub(crate) fn HistoryDepthOnEmpty() -> u32 { - 84u32 - } - /// map the public key to a list of multiaddresses #[pallet::storage] #[pallet::getter(fn bootstrap_nodes)] @@ -301,99 +194,6 @@ pub mod pallet { ValueQuery, >; - /* - START: SESSION STORAGE STUFF - */ - - /// Number of eras to keep in history. - /// - /// Information is kept for eras in `[current_era - history_depth; current_era]`. - /// - /// Must be more than the number of eras delayed by session otherwise. I.e. active era must - /// always be in history. I.e. `active_era > current_era - history_depth` must be - /// guaranteed. - #[pallet::storage] - #[pallet::getter(fn history_depth)] - pub(crate) type HistoryDepth = StorageValue<_, u32, ValueQuery, HistoryDepthOnEmpty>; - - /// The current era index. - /// - /// This is the latest planned era, depending on how the Session pallet queues the validator - /// set, it might be active or not. - #[pallet::storage] - #[pallet::getter(fn current_era)] - pub type CurrentEra = StorageValue<_, EraIndex>; - - /// The active era information, it holds index and start. - /// - /// The active era is the era being currently rewarded. Validator set of this era must be - /// equal to [`SessionInterface::validators`]. - #[pallet::storage] - #[pallet::getter(fn active_era)] - pub type ActiveEra = StorageValue<_, ActiveEraInfo>; - - /// The session index at which the era start for the last `HISTORY_DEPTH` eras. - /// - /// Note: This tracks the starting session (i.e. session index when era start being active) - /// for the eras in `[CurrentEra - HISTORY_DEPTH, CurrentEra]`. - #[pallet::storage] - #[pallet::getter(fn eras_start_session_index)] - pub type ErasStartSessionIndex = StorageMap<_, Twox64Concat, EraIndex, SessionIndex>; - - /// Exposure of validator at era. - /// - /// This is keyed first by the era index to allow bulk deletion and then the stash account. - /// - /// Is it removed after `HISTORY_DEPTH` eras. - /// If stakers hasn't been set or has been removed then empty exposure is returned. - #[pallet::storage] - #[pallet::getter(fn eras_stakers)] - pub type ErasStakers = - StorageDoubleMap<_, Twox64Concat, EraIndex, Twox64Concat, T::AccountId, u128, ValueQuery>; - - /// The total validator era payout for the last `HISTORY_DEPTH` eras. - /// - /// Eras that haven't finished yet or has been removed doesn't have reward. - #[pallet::storage] - #[pallet::getter(fn eras_validator_reward)] - pub type ErasValidatorReward = StorageMap<_, Twox64Concat, EraIndex, u128>; - - /// Rewards for the last `HISTORY_DEPTH` eras. - /// If reward hasn't been set or has been removed then 0 reward is returned. - #[pallet::storage] - #[pallet::getter(fn eras_reward_points)] - pub type ErasRewardPoints = - StorageMap<_, Twox64Concat, EraIndex, EraRewardPoints, ValueQuery>; - - /// The total amount staked for the last `HISTORY_DEPTH` eras. - /// If total hasn't been set or has been removed then 0 stake is returned. - #[pallet::storage] - #[pallet::getter(fn eras_total_stake)] - pub type ErasTotalStake = StorageMap<_, Twox64Concat, EraIndex, u128, ValueQuery>; - - /// A mapping from still-bonded eras to the first session index of that era. - /// - /// Must contains information for eras for the range: - /// `[active_era - bounding_duration; active_era]` - #[pallet::storage] - pub(crate) type BondedEras = - StorageValue<_, Vec<(EraIndex, SessionIndex)>, ValueQuery>; - - /// The last planned session scheduled by the session pallet. - /// - /// This is basically in sync with the call to [`SessionManager::new_session`]. - #[pallet::storage] - #[pallet::getter(fn current_planned_session)] - pub type CurrentPlannedSession = StorageValue<_, SessionIndex, ValueQuery>; - - /// The payout for validators and the system for the current era. - #[pallet::storage] - #[pallet::getter(fn era_payout)] - pub type EraPayout = StorageValue<_, u128, ValueQuery>; - - /* - END - */ #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { @@ -878,344 +678,4 @@ impl Pallet { ); Ok(()) } - - /* - START: SESSION STUFF - */ - - /// Plan a new session potentially trigger a new era. - fn new_session(session_index: SessionIndex, is_genesis: bool) -> Option> { - if let Some(current_era) = Self::current_era() { - // Initial era has been set. - let current_era_start_session_index = Self::eras_start_session_index(current_era) - .unwrap_or_else(|| { - frame_support::print("Error: start_session_index must be set for current_era"); - 0 - }); - - let era_length = - session_index.checked_sub(current_era_start_session_index).unwrap_or(0); // Must never happen. - - // log!(info, "Era length: {:?}", era_length); - // if era_length < T::SessionsPerEra::get() { - // // The 5th session of the era. - // if T::AppchainInterface::is_activated() - // && (era_length == T::SessionsPerEra::get() - 1) - // { - // let next_set_id = T::AppchainInterface::next_set_id(); - // let message = PlanNewEraPayload { new_era: next_set_id }; - - // let res = T::UpwardMessagesInterface::submit( - // &T::AccountId::default(), - // PayloadType::PlanNewEra, - // &message.try_to_vec().unwrap(), - // ); - // log!(info, "UpwardMessage::PlanNewEra: {:?}", res); - // if res.is_ok() { - // Self::deposit_event(Event::::PlanNewEra(next_set_id)); - // } else { - // Self::deposit_event(Event::::PlanNewEraFailed); - // } - // } - // return None; - // } - - // New era. - Self::try_trigger_new_era(session_index) - } else { - // Set initial era. - log::info!("Starting the first era."); - Self::try_trigger_new_era(session_index) - } - } - - /// Start a session potentially starting an era. - fn start_session(start_session: SessionIndex) { - let next_active_era = Self::active_era().map(|e| e.index + 1).unwrap_or(0); - // This is only `Some` when current era has already progressed to the next era, while the - // active era is one behind (i.e. in the *last session of the active era*, or *first session - // of the new current era*, depending on how you look at it). - if let Some(next_active_era_start_session_index) = - Self::eras_start_session_index(next_active_era) - { - if next_active_era_start_session_index == start_session { - Self::start_era(start_session); - } else if next_active_era_start_session_index < start_session { - // This arm should never happen, but better handle it than to stall the staking - // pallet. - frame_support::print("Warning: A session appears to have been skipped."); - Self::start_era(start_session); - } - } - } - - /// End a session potentially ending an era. - fn end_session(session_index: SessionIndex) { - if let Some(active_era) = Self::active_era() { - if let Some(next_active_era_start_session_index) = - Self::eras_start_session_index(active_era.index + 1) - { - if next_active_era_start_session_index == session_index + 1 { - Self::end_era(active_era, session_index); - } - } - } - } - - /// * Increment `active_era.index`, - /// * reset `active_era.start`, - /// * update `BondedEras` and apply slashes. - fn start_era(start_session: SessionIndex) { - // let active_era = ActiveEra::::mutate(|active_era| { - // let next_set_id = T::AppchainInterface::next_set_id(); - // let new_index = active_era.as_ref().map(|info| info.index + 1).unwrap_or(0); - // *active_era = Some(ActiveEraInfo { - // index: new_index, - // set_id: next_set_id - 1, - // // Set new active era start in next `on_finalize`. To guarantee usage of `Time` - // start: None, - // }); - // new_index - // }); - - // let bonding_duration = T::BondingDuration::get(); - - // BondedEras::::mutate(|bonded| { - // bonded.push((active_era, start_session)); - - // if active_era > bonding_duration { - // let first_kept = active_era - bonding_duration; - - // // Prune out everything that's from before the first-kept index. - // let n_to_prune = - // bonded.iter().take_while(|&&(era_idx, _)| era_idx < first_kept).count(); - - // if let Some(&(_, first_session)) = bonded.first() { - // T::SessionInterface::prune_historical_up_to(first_session); - // } - // } - // }); - } - - /// Compute payout for era. - fn end_era(active_era: ActiveEraInfo, _session_index: SessionIndex) { - return; - // if !T::AppchainInterface::is_activated() || >::get() == 0 { - // return; - // } - - // // Note: active_era_start can be None if end era is called during genesis config. - // if let Some(active_era_start) = active_era.start { - // if >::get(&active_era.index).is_some() { - // log!(warn, "era reward {:?} has already been paid", active_era.index); - // return; - // } - - // let now_as_millis_u64 = T::UnixTime::now().as_millis().saturated_into::(); - // let _era_duration = (now_as_millis_u64 - active_era_start).saturated_into::(); - // let validator_payout = Self::era_payout(); - - // // Set ending era reward. - // >::insert(&active_era.index, validator_payout); - - // let excluded_validators = Self::get_exclude_validators(active_era.index); - - // let excluded_validators_str = excluded_validators - // .iter() - // .map(|validator| { - // let prefix = String::from("0x"); - // let hex_validator = prefix + &hex::encode(validator.encode()); - // hex_validator - // }) - // .collect::>(); - - // log!(debug, "Exclude validators: {:?}", excluded_validators_str.clone()); - - // let message = EraPayoutPayload { - // end_era: active_era.set_id, - // excluded_validators: excluded_validators_str.clone(), - // }; - - // let amount = validator_payout.checked_into().ok_or(Error::::AmountOverflow).unwrap(); - // T::Currency::deposit_creating(&Self::account_id(), amount); - // log!(debug, "Will send EraPayout message, era_payout is {:?}", >::get()); - - // let res = T::UpwardMessagesInterface::submit( - // &T::AccountId::default(), - // PayloadType::EraPayout, - // &message.try_to_vec().unwrap(), - // ); - // log!(info, "UpwardMessage::EraPayout: {:?}", res); - // if res.is_ok() { - // Self::deposit_event(Event::::EraPayout(active_era.set_id, excluded_validators)); - // } else { - // Self::deposit_event(Event::::EraPayoutFailed(active_era.set_id)); - // } - // } - } - - - /// Plan a new era. - /// - /// * Bump the current era storage (which holds the latest planned era). - /// * Store start session index for the new planned era. - /// * Clean old era information. - /// * Store staking information for the new planned era - /// - /// Returns the new validator set. - pub fn trigger_new_era( - start_session_index: SessionIndex, - validators: Vec<(T::AccountId, u128)>, - ) -> Vec { - // Increment or set current era. - let new_planned_era = CurrentEra::::mutate(|s| { - *s = Some(s.map(|s| s + 1).unwrap_or(0)); - s.unwrap() - }); - ErasStartSessionIndex::::insert(&new_planned_era, &start_session_index); - - // Clean old era information. - if let Some(old_era) = new_planned_era.checked_sub(Self::history_depth() + 1) { - Self::clear_era_information(old_era); - } - - // Set staking information for the new era. - Self::store_stakers_info(validators, new_planned_era) - } - - /// Potentially plan a new era. - /// - /// Get planned validator set from `T::ValidatorsProvider`. - fn try_trigger_new_era(start_session_index: SessionIndex) -> Option> { - let validators = T::ValidatorsProvider::validators(); - log!(info, "Next validator set: {:?}", validators); - - >::deposit_event(Event::::TriggerNewEra); - Some(Self::trigger_new_era(start_session_index, validators)) - } - - /// Process the output of the validators provider. - /// - /// Store staking information for the new planned era - pub fn store_stakers_info( - validators: Vec<(T::AccountId, u128)>, - new_planned_era: EraIndex, - ) -> Vec { - let elected_stashes = validators.iter().cloned().map(|(x, _)| x).collect::>(); - - let mut total_stake: u128 = 0; - validators.into_iter().for_each(|(who, weight)| { - total_stake = total_stake.saturating_add(weight); - >::insert(new_planned_era, &who, weight); - }); - - // Insert current era staking information - >::insert(&new_planned_era, total_stake); - - if new_planned_era > 0 { - log::info!( - "New validator set of size {:?} has been processed for era {:?}", - elected_stashes.len(), - new_planned_era, - ); - } - - elected_stashes - } - - /// Clear all era information for given era. - fn clear_era_information(era_index: EraIndex) { - >::remove_prefix(era_index, None); - >::remove(era_index); - >::remove(era_index); - >::remove(era_index); - ErasStartSessionIndex::::remove(era_index); - } - - - /* - END: SESSION STUFF - */ -} - - -/// A typed conversion from stash account ID to the active exposure of nominators -/// on that account. -/// -/// Active exposure is the exposure of the validator set currently validating, i.e. in -/// `active_era`. It can differ from the latest planned exposure in `current_era`. -pub struct ExposureOf(sp_std::marker::PhantomData); - -impl Convert> for ExposureOf { - fn convert(validator: T::AccountId) -> Option { - >::active_era() - .map(|active_era| >::eras_stakers(active_era.index, &validator)) - } -} - -/// In this implementation `new_session(session)` must be called before `end_session(session-1)` -/// i.e. the new session must be planned before the ending of the previous session. -/// -/// Once the first new_session is planned, all session must start and then end in order, though -/// some session can lag in between the newest session planned and the latest session started. -impl pallet_session::SessionManager for Pallet { - fn new_session(new_index: SessionIndex) -> Option> { - log::info!("planning new session {}", new_index); - CurrentPlannedSession::::put(new_index); - Self::new_session(new_index, false) - } - fn new_session_genesis(new_index: SessionIndex) -> Option> { - log::info!("planning new session {} at genesis", new_index); - CurrentPlannedSession::::put(new_index); - Self::new_session(new_index, true) - } - fn start_session(start_index: SessionIndex) { - log::info!("starting session {}", start_index); - Self::start_session(start_index) - } - fn end_session(end_index: SessionIndex) { - log::info!("ending session {}", end_index); - Self::end_session(end_index) - } -} - -impl historical::SessionManager for Pallet { - fn new_session(new_index: SessionIndex) -> Option> { - >::new_session(new_index).map(|validators| { - let current_era = Self::current_era() - // Must be some as a new era has been created. - .unwrap_or(0); - - validators - .into_iter() - .map(|v| { - let exposure = Self::eras_stakers(current_era, &v); - (v, exposure) - }) - .collect() - }) - } - fn new_session_genesis(new_index: SessionIndex) -> Option> { - >::new_session_genesis(new_index).map( - |validators| { - let current_era = Self::current_era() - // Must be some as a new era has been created. - .unwrap_or(0); - - validators - .into_iter() - .map(|v| { - let exposure = Self::eras_stakers(current_era, &v); - (v, exposure) - }) - .collect() - }, - ) - } - fn start_session(start_index: SessionIndex) { - >::start_session(start_index) - } - fn end_session(end_index: SessionIndex) { - >::end_session(end_index) - } } \ No newline at end of file diff --git a/bin/node-template/pallets/template/src/types.rs b/bin/node-template/pallets/template/src/types.rs deleted file mode 100644 index 1353f3f1166e..000000000000 --- a/bin/node-template/pallets/template/src/types.rs +++ /dev/null @@ -1,16 +0,0 @@ -use codec::{Decode, Encode}; -#[cfg(feature = "std")] -use serde::{Deserialize, Serialize}; - -use sp_runtime::traits::{AtLeast32BitUnsigned, Zero}; -use sp_std::prelude::*; -use sp_core::Bytes; - -use frame_support::weights::{DispatchClass, Weight}; - -#[derive(Eq, PartialEq, Encode, Decode, Default)] -#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] -#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] -pub struct DataResponse { - pub data: Bytes, -} \ No newline at end of file diff --git a/bin/node-template/runtime/Cargo.toml b/bin/node-template/runtime/Cargo.toml index 1b8ad595d692..64ce8e3bf12c 100644 --- a/bin/node-template/runtime/Cargo.toml +++ b/bin/node-template/runtime/Cargo.toml @@ -24,6 +24,7 @@ pallet-sudo = { version = "4.0.0-dev", default-features = false, path = "../../. pallet-assets = { version = "4.0.0-dev", default-features = false, path = "../../../frame/assets" } pallet-session = { version = "4.0.0-dev", default-features = false, features = ["historical"], path = "../../../frame/session" } pallet-iris = { version = "3.0.0", default-features = false, path = "../pallets/template" } +pallet-iris-session = { version = "3.0.0", default-features = false, path = "../pallets/iris-session" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../../frame/system" } @@ -78,6 +79,7 @@ std = [ "pallet-transaction-payment/std", "pallet-assets/std", "pallet-session/std", + "pallet-iris-session/std", "sp-api/std", "sp-block-builder/std", "sp-consensus-aura/std", @@ -98,6 +100,7 @@ runtime-benchmarks = [ "hex-literal", "pallet-balances/runtime-benchmarks", "pallet-iris/runtime-benchmarks", + "pallet-iris-session/std", "pallet-timestamp/runtime-benchmarks", "pallet-assets/runtime-benchmarks", "sp-runtime/runtime-benchmarks", diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index bb82968cd380..58fb9b601558 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -14,7 +14,17 @@ use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::{crypto::KeyTypeId, OpaqueMetadata, Encode, Bytes}; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, - traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, IdentifyAccount, NumberFor, Verify, SaturatedConversion, OpaqueKeys, ConvertInto }, + traits::{ + AccountIdLookup, + BlakeTwo256, + Block as BlockT, + IdentifyAccount, + NumberFor, + Verify, + SaturatedConversion, + OpaqueKeys, + ConvertInto, + }, transaction_validity::{TransactionSource, TransactionValidity}, ApplyExtrinsicResult, MultiSignature, }; @@ -46,6 +56,7 @@ pub use sp_runtime::{Perbill, Permill}; /// Import the template pallet. pub use pallet_iris; +pub use pallet_iris_session; /// An index to a block. pub type BlockNumber = u32; @@ -204,30 +215,32 @@ impl frame_system::Config for Runtime { impl pallet_randomness_collective_flip::Config for Runtime {} parameter_types! { - pub const Period: u32 = 5; + // TODO: Increase this when done testing + pub const MinAuthorities: u32 = 1; +} + +impl pallet_iris_session::Config for Runtime { + type Event = Event; + type AddRemoveOrigin = EnsureRoot; + type MinAuthorities = MinAuthorities; +} + +parameter_types! { + pub const Period: u32 = 2 * MINUTES; pub const Offset: u32 = 0; } impl pallet_session::Config for Runtime { + type ValidatorId = ::AccountId; + type ValidatorIdOf = pallet_iris_session::ValidatorOf; + type ShouldEndSession = pallet_session::PeriodicSessions; + type NextSessionRotation = pallet_session::PeriodicSessions; + type SessionManager = IrisSession; type SessionHandler = ::KeyTypeIdProviders; - // type ShouldEndSession = ValidatorSet; - // type SessionManager = ValidatorSet; - type SessionManager = pallet_session::historical::NoteHistoricalRoot; - type Event = Event; type Keys = opaque::SessionKeys; - type NextSessionRotation = pallet_session::PeriodicSessions; - type ShouldEndSession = pallet_session::PeriodicSessions; - // type ValidatorId = ::AccountId; - // type ValidatorIdOf = validatorset::ValidatorOf; - type ValidatorId = u64; - type ValidatorIdOf = ConvertInto; + type WeightInfo = (); type DisabledValidatorsThreshold = (); -} - - -impl pallet_session::historical::Config for Runtime { - type FullIdentification = u128; - type FullIdentificationOf = pallet_iris::ExposureOf; + type Event = Event; } parameter_types! { @@ -244,7 +257,7 @@ impl pallet_grandpa::Config for Runtime { type Event = Event; type Call = Call; - type KeyOwnerProofSystem = Historical; + type KeyOwnerProofSystem = (); type KeyOwnerProof = >::Proof; @@ -341,7 +354,6 @@ impl pallet_iris::Config for Runtime { type Call = Call; type AuthorityId = pallet_iris::crypto::TestAuthId; type Currency = Balances; - type SessionInterface = Self; } impl frame_system::offchain::CreateSignedTransaction for Runtime @@ -409,17 +421,18 @@ construct_runtime!( System: frame_system::{Pallet, Call, Config, Storage, Event}, // RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage}, Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, - Aura: pallet_aura::{Pallet, Config}, - Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event}, Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, TransactionPayment: pallet_transaction_payment::{Pallet, Storage}, Sudo: pallet_sudo::{Pallet, Call, Config, Storage, Event}, // Include the custom logic from the pallet-template in the runtime. + IrisSession: pallet_iris_session::{Pallet, Call, Storage, Event, Config}, Iris: pallet_iris::{Pallet, Call, Storage, Event}, - // removed call to make extrinsics uncallable - Assets: pallet_assets::{Pallet, Storage, Event}, Session: pallet_session::{Pallet, Storage, Event, Config}, - Historical: pallet_session_historical::{Pallet}, + Assets: pallet_assets::{Pallet, Storage, Event}, + // removed call to make extrinsics uncallable + Aura: pallet_aura::{Pallet, Config}, + Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event}, + // Historical: pallet_session_historical::{Pallet}, } ); // Iris: pallet_iris::{Pallet, Call, Storage, Event, ValidateUnsigned}, From a672684076c3a9f4214e5f5ebadd71835ac1bae6 Mon Sep 17 00:00:00 2001 From: driemworks Date: Thu, 13 Jan 2022 15:46:04 -0600 Subject: [PATCH 380/695] refactoring, WIP validtors as storage providers --- bin/node-template/node/src/chain_spec.rs | 2 -- .../{template => iris-asset}/Cargo.toml | 4 +-- .../{template => iris-asset}/README.md | 0 .../{template => iris-asset}/rpc/Cargo.toml | 0 .../{template => iris-asset}/rpc/README.md | 0 .../rpc/runtime-api/Cargo.toml | 0 .../rpc/runtime-api/README.md | 0 .../rpc/runtime-api/src/lib.rs | 0 .../{template => iris-asset}/rpc/src/lib.rs | 0 .../src/benchmarking.rs | 0 .../{template => iris-asset}/src/lib.rs | 5 +-- .../{template => iris-asset}/src/mock.rs | 0 .../{template => iris-asset}/src/tests.rs | 0 .../pallets/iris-session/src/lib.rs | 31 ++++++++++++++++--- .../pallets/iris-session/src/mock.rs | 12 +++---- .../pallets/iris-session/src/tests.rs | 12 +++---- bin/node-template/runtime/Cargo.toml | 6 ++-- bin/node-template/runtime/src/lib.rs | 15 +++++---- 18 files changed, 53 insertions(+), 34 deletions(-) rename bin/node-template/pallets/{template => iris-asset}/Cargo.toml (95%) rename bin/node-template/pallets/{template => iris-asset}/README.md (100%) rename bin/node-template/pallets/{template => iris-asset}/rpc/Cargo.toml (100%) rename bin/node-template/pallets/{template => iris-asset}/rpc/README.md (100%) rename bin/node-template/pallets/{template => iris-asset}/rpc/runtime-api/Cargo.toml (100%) rename bin/node-template/pallets/{template => iris-asset}/rpc/runtime-api/README.md (100%) rename bin/node-template/pallets/{template => iris-asset}/rpc/runtime-api/src/lib.rs (100%) rename bin/node-template/pallets/{template => iris-asset}/rpc/src/lib.rs (100%) rename bin/node-template/pallets/{template => iris-asset}/src/benchmarking.rs (100%) rename bin/node-template/pallets/{template => iris-asset}/src/lib.rs (99%) rename bin/node-template/pallets/{template => iris-asset}/src/mock.rs (100%) rename bin/node-template/pallets/{template => iris-asset}/src/tests.rs (100%) diff --git a/bin/node-template/node/src/chain_spec.rs b/bin/node-template/node/src/chain_spec.rs index 324f3d12c370..69d4b42609fa 100644 --- a/bin/node-template/node/src/chain_spec.rs +++ b/bin/node-template/node/src/chain_spec.rs @@ -161,11 +161,9 @@ fn testnet_genesis( }).collect::>(), }, aura: AuraConfig { - // authorities: initial_authorities.iter().map(|x| (x.1.clone())).collect(), authorities: vec![], }, grandpa: GrandpaConfig { - // authorities: initial_authorities.iter().map(|x| (x.2.clone(), 1)).collect(), authorities: vec![], }, sudo: SudoConfig { diff --git a/bin/node-template/pallets/template/Cargo.toml b/bin/node-template/pallets/iris-asset/Cargo.toml similarity index 95% rename from bin/node-template/pallets/template/Cargo.toml rename to bin/node-template/pallets/iris-asset/Cargo.toml index abd20649db0e..011f7c9efe82 100644 --- a/bin/node-template/pallets/template/Cargo.toml +++ b/bin/node-template/pallets/iris-asset/Cargo.toml @@ -1,12 +1,12 @@ [package] authors = ['Substrate DevHub '] edition = '2018' -name = 'pallet-iris' +name = 'pallet-iris-asset' version = "3.0.0" license = "Unlicense" homepage = "https://substrate.dev" repository = "https://github.com/substrate-developer-hub/substrate-node-template/" -description = "FRAME pallet template for Iris." +description = "FRAME pallet template for Iris Asset management." readme = "README.md" publish = false diff --git a/bin/node-template/pallets/template/README.md b/bin/node-template/pallets/iris-asset/README.md similarity index 100% rename from bin/node-template/pallets/template/README.md rename to bin/node-template/pallets/iris-asset/README.md diff --git a/bin/node-template/pallets/template/rpc/Cargo.toml b/bin/node-template/pallets/iris-asset/rpc/Cargo.toml similarity index 100% rename from bin/node-template/pallets/template/rpc/Cargo.toml rename to bin/node-template/pallets/iris-asset/rpc/Cargo.toml diff --git a/bin/node-template/pallets/template/rpc/README.md b/bin/node-template/pallets/iris-asset/rpc/README.md similarity index 100% rename from bin/node-template/pallets/template/rpc/README.md rename to bin/node-template/pallets/iris-asset/rpc/README.md diff --git a/bin/node-template/pallets/template/rpc/runtime-api/Cargo.toml b/bin/node-template/pallets/iris-asset/rpc/runtime-api/Cargo.toml similarity index 100% rename from bin/node-template/pallets/template/rpc/runtime-api/Cargo.toml rename to bin/node-template/pallets/iris-asset/rpc/runtime-api/Cargo.toml diff --git a/bin/node-template/pallets/template/rpc/runtime-api/README.md b/bin/node-template/pallets/iris-asset/rpc/runtime-api/README.md similarity index 100% rename from bin/node-template/pallets/template/rpc/runtime-api/README.md rename to bin/node-template/pallets/iris-asset/rpc/runtime-api/README.md diff --git a/bin/node-template/pallets/template/rpc/runtime-api/src/lib.rs b/bin/node-template/pallets/iris-asset/rpc/runtime-api/src/lib.rs similarity index 100% rename from bin/node-template/pallets/template/rpc/runtime-api/src/lib.rs rename to bin/node-template/pallets/iris-asset/rpc/runtime-api/src/lib.rs diff --git a/bin/node-template/pallets/template/rpc/src/lib.rs b/bin/node-template/pallets/iris-asset/rpc/src/lib.rs similarity index 100% rename from bin/node-template/pallets/template/rpc/src/lib.rs rename to bin/node-template/pallets/iris-asset/rpc/src/lib.rs diff --git a/bin/node-template/pallets/template/src/benchmarking.rs b/bin/node-template/pallets/iris-asset/src/benchmarking.rs similarity index 100% rename from bin/node-template/pallets/template/src/benchmarking.rs rename to bin/node-template/pallets/iris-asset/src/benchmarking.rs diff --git a/bin/node-template/pallets/template/src/lib.rs b/bin/node-template/pallets/iris-asset/src/lib.rs similarity index 99% rename from bin/node-template/pallets/template/src/lib.rs rename to bin/node-template/pallets/iris-asset/src/lib.rs index 8d7dcdf6e32e..a9d5c975b806 100644 --- a/bin/node-template/pallets/template/src/lib.rs +++ b/bin/node-template/pallets/iris-asset/src/lib.rs @@ -72,7 +72,7 @@ pub mod crypto { app_crypto!(sr25519, KEY_TYPE); pub struct TestAuthId; - // implemented for untime + // implemented for runtime impl frame_system::offchain::AppCrypto for TestAuthId { type RuntimeAppPublic = Public; type GenericSignature = sp_core::sr25519::Signature; @@ -139,7 +139,8 @@ pub mod pallet { #[pallet::generate_store(pub(super) trait Store)] pub struct Pallet(_); - /// map the public key to a list of multiaddresses + /// map the ipfs public key to a list of multiaddresses + /// this could be moved to the session pallet #[pallet::storage] #[pallet::getter(fn bootstrap_nodes)] pub(super) type BootstrapNodes = StorageMap< diff --git a/bin/node-template/pallets/template/src/mock.rs b/bin/node-template/pallets/iris-asset/src/mock.rs similarity index 100% rename from bin/node-template/pallets/template/src/mock.rs rename to bin/node-template/pallets/iris-asset/src/mock.rs diff --git a/bin/node-template/pallets/template/src/tests.rs b/bin/node-template/pallets/iris-asset/src/tests.rs similarity index 100% rename from bin/node-template/pallets/template/src/tests.rs rename to bin/node-template/pallets/iris-asset/src/tests.rs diff --git a/bin/node-template/pallets/iris-session/src/lib.rs b/bin/node-template/pallets/iris-session/src/lib.rs index aaa21dd8a446..5dee754a2e5f 100644 --- a/bin/node-template/pallets/iris-session/src/lib.rs +++ b/bin/node-template/pallets/iris-session/src/lib.rs @@ -27,7 +27,7 @@ use sp_runtime::traits::{Convert, Zero}; use sp_staking::offence::{Offence, OffenceError, ReportOffence}; use sp_std::{collections::btree_set::BTreeSet, prelude::*}; -pub const LOG_TARGET: &'static str = "runtime::validator-set"; +pub const LOG_TARGET: &'static str = "runtime::iris-session"; #[frame_support::pallet] pub mod pallet { @@ -119,6 +119,7 @@ pub mod pallet { /// /// The origin can be configured using the `AddRemoveOrigin` type in the /// host runtime. Can also be set to sudo/root. + /// #[pallet::weight(0)] pub fn add_validator(origin: OriginFor, validator_id: T::AccountId) -> DispatchResult { T::AddRemoveOrigin::ensure_origin(origin)?; @@ -164,6 +165,16 @@ pub mod pallet { Ok(()) } + + /// Add a storage provider to a storage pool + /// new storage providers must already be approved validators + #[pallet::weight(0)] + pub fn join_storage_pool( + origin: OriginFor, + sp_id: T::AssetId, + ) -> DispatchResult { + Ok(()) + } } } @@ -206,6 +217,9 @@ impl Pallet { Ok(()) } + /// Ensure the candidate validator is eligible to be a validator + /// 1) Check that it is not a duplicate + /// 2) fn approve_validator(validator_id: T::AccountId) -> DispatchResult { let approved_set: BTreeSet<_> = >::get().into_iter().collect(); ensure!(!approved_set.contains(&validator_id), Error::::Duplicate); @@ -213,6 +227,7 @@ impl Pallet { Ok(()) } + /// Remote a validator from the list of approved validators fn unapprove_validator(validator_id: T::AccountId) -> DispatchResult { let mut approved_set = >::get(); approved_set.retain(|v| *v != validator_id); @@ -250,19 +265,25 @@ impl Pallet { // being rotated. impl pallet_session::SessionManager for Pallet { // Plan a new session and provide new validator set. - fn new_session(_new_index: u32) -> Option> { + fn new_session(new_index: u32) -> Option> { + log::info!("Starting new session with index: {:?}", new_index); // Remove any offline validators. This will only work when the runtime // also has the im-online pallet. Self::remove_offline_validators(); - log::debug!(target: LOG_TARGET, "New session called; updated validator set provided."); + // TODO: Need to verify that storage providers have data pinned... + Some(Self::validators()) } - fn end_session(_end_index: u32) {} + fn end_session(end_index: u32) { + log::info!("Ending session with index: {:?}", end_index) + } - fn start_session(_start_index: u32) {} + fn start_session(start_index: u32) { + log::info!("Starting session with index: {:?}", start_index); + } } impl EstimateNextSessionRotation for Pallet { diff --git a/bin/node-template/pallets/iris-session/src/mock.rs b/bin/node-template/pallets/iris-session/src/mock.rs index 754ee8b0aaca..eea24893ae30 100644 --- a/bin/node-template/pallets/iris-session/src/mock.rs +++ b/bin/node-template/pallets/iris-session/src/mock.rs @@ -3,7 +3,7 @@ #![cfg(test)] use super::*; -use crate as validator_set; +use crate as pallet_iris_session; use frame_support::{parameter_types, traits::GenesisBuild, BasicExternalities}; use frame_system::EnsureRoot; use pallet_session::*; @@ -63,7 +63,7 @@ frame_support::construct_runtime!( UncheckedExtrinsic = UncheckedExtrinsic, { System: frame_system::{Pallet, Call, Config, Storage, Event}, - ValidatorSet: validator_set::{Pallet, Call, Storage, Event, Config}, + IrisSession: pallet_iris_session::{Pallet, Call, Storage, Event, Config}, Session: pallet_session::{Pallet, Call, Storage, Event, Config}, } ); @@ -133,7 +133,7 @@ pub fn new_test_ext() -> sp_io::TestExternalities { frame_system::Pallet::::inc_providers(&4); frame_system::Pallet::::inc_providers(&69); }); - validator_set::GenesisConfig:: { + pallet_iris_session::GenesisConfig:: { initial_validators: keys.iter().map(|x| x.0).collect::>(), } .assimilate_storage(&mut t) @@ -181,7 +181,7 @@ parameter_types! { pub const MinAuthorities: u32 = 2; } -impl validator_set::Config for Test { +impl pallet_iris_session::Config for Test { type AddRemoveOrigin = EnsureRoot; type Event = Event; type MinAuthorities = MinAuthorities; @@ -189,10 +189,10 @@ impl validator_set::Config for Test { impl pallet_session::Config for Test { type ValidatorId = ::AccountId; - type ValidatorIdOf = validator_set::ValidatorOf; + type ValidatorIdOf = pallet_iris_session::ValidatorOf; type ShouldEndSession = TestShouldEndSession; type NextSessionRotation = (); - type SessionManager = ValidatorSet; + type SessionManager = IrisSession; type SessionHandler = TestSessionHandler; type Keys = MockSessionKeys; type WeightInfo = (); diff --git a/bin/node-template/pallets/iris-session/src/tests.rs b/bin/node-template/pallets/iris-session/src/tests.rs index 3feb309fd38d..6f838211ce27 100644 --- a/bin/node-template/pallets/iris-session/src/tests.rs +++ b/bin/node-template/pallets/iris-session/src/tests.rs @@ -8,7 +8,7 @@ use frame_support::{assert_noop, assert_ok, pallet_prelude::*}; use sp_runtime::testing::UintAuthorityId; #[test] -fn simple_setup_should_work() { +fn iris_session_simple_setup_should_work() { new_test_ext().execute_with(|| { assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); assert_eq!(ValidatorSet::validators(), vec![1u64, 2u64, 3u64]); @@ -17,7 +17,7 @@ fn simple_setup_should_work() { } #[test] -fn add_validator_updates_validators_list() { +fn iris_session_add_validator_updates_validators_list() { new_test_ext().execute_with(|| { assert_ok!(ValidatorSet::add_validator(Origin::root(), 4)); assert_eq!(ValidatorSet::validators(), vec![1u64, 2u64, 3u64, 4u64]) @@ -25,7 +25,7 @@ fn add_validator_updates_validators_list() { } #[test] -fn remove_validator_updates_validators_list() { +fn iris_session_remove_validator_updates_validators_list() { new_test_ext().execute_with(|| { assert_ok!(ValidatorSet::remove_validator(Origin::root(), 2)); assert_eq!(ValidatorSet::validators(), vec![1u64, 3u64]); @@ -33,14 +33,14 @@ fn remove_validator_updates_validators_list() { } #[test] -fn add_validator_fails_with_invalid_origin() { +fn iris_session_add_validator_fails_with_invalid_origin() { new_test_ext().execute_with(|| { assert_noop!(ValidatorSet::add_validator(Origin::signed(1), 4), DispatchError::BadOrigin); }); } #[test] -fn remove_validator_fails_with_invalid_origin() { +fn iris_session_remove_validator_fails_with_invalid_origin() { new_test_ext().execute_with(|| { assert_noop!( ValidatorSet::remove_validator(Origin::signed(1), 4), @@ -50,7 +50,7 @@ fn remove_validator_fails_with_invalid_origin() { } #[test] -fn duplicate_check() { +fn iris_session_duplicate_check() { new_test_ext().execute_with(|| { assert_ok!(ValidatorSet::add_validator(Origin::root(), 4)); assert_eq!(ValidatorSet::validators(), vec![1u64, 2u64, 3u64, 4u64]); diff --git a/bin/node-template/runtime/Cargo.toml b/bin/node-template/runtime/Cargo.toml index 64ce8e3bf12c..422fef3afb24 100644 --- a/bin/node-template/runtime/Cargo.toml +++ b/bin/node-template/runtime/Cargo.toml @@ -23,7 +23,7 @@ pallet-randomness-collective-flip = { version = "4.0.0-dev", default-features = pallet-sudo = { version = "4.0.0-dev", default-features = false, path = "../../../frame/sudo" } pallet-assets = { version = "4.0.0-dev", default-features = false, path = "../../../frame/assets" } pallet-session = { version = "4.0.0-dev", default-features = false, features = ["historical"], path = "../../../frame/session" } -pallet-iris = { version = "3.0.0", default-features = false, path = "../pallets/template" } +pallet-iris-asset = { version = "3.0.0", default-features = false, path = "../pallets/iris-asset" } pallet-iris-session = { version = "3.0.0", default-features = false, path = "../pallets/iris-session" } @@ -72,7 +72,7 @@ std = [ "pallet-grandpa/std", "pallet-randomness-collective-flip/std", "pallet-sudo/std", - "pallet-iris/std", + "pallet-iris-asset/std", "pallet-timestamp/std", "pallet-transaction-payment-rpc-runtime-api/std", "pallet-iris-rpc-runtime-api/std", @@ -99,7 +99,7 @@ runtime-benchmarks = [ "frame-system/runtime-benchmarks", "hex-literal", "pallet-balances/runtime-benchmarks", - "pallet-iris/runtime-benchmarks", + "pallet-iris-asset/runtime-benchmarks", "pallet-iris-session/std", "pallet-timestamp/runtime-benchmarks", "pallet-assets/runtime-benchmarks", diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index 58fb9b601558..b811beb4023a 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -55,7 +55,7 @@ pub use sp_runtime::{Perbill, Permill}; /// Import the template pallet. -pub use pallet_iris; +pub use pallet_iris_asset; pub use pallet_iris_session; /// An index to a block. @@ -226,7 +226,7 @@ impl pallet_iris_session::Config for Runtime { } parameter_types! { - pub const Period: u32 = 2 * MINUTES; + pub const Period: u32 = 1 * MINUTES; pub const Offset: u32 = 0; } @@ -349,10 +349,10 @@ impl pallet_assets::Config for Runtime { pub type SignedPayload = generic::SignedPayload; /// Configure the pallet-template in pallets/template. -impl pallet_iris::Config for Runtime { +impl pallet_iris_asset::Config for Runtime { type Event = Event; type Call = Call; - type AuthorityId = pallet_iris::crypto::TestAuthId; + type AuthorityId = pallet_iris_asset::crypto::TestAuthId; type Currency = Balances; } @@ -426,8 +426,8 @@ construct_runtime!( Sudo: pallet_sudo::{Pallet, Call, Config, Storage, Event}, // Include the custom logic from the pallet-template in the runtime. IrisSession: pallet_iris_session::{Pallet, Call, Storage, Event, Config}, - Iris: pallet_iris::{Pallet, Call, Storage, Event}, - Session: pallet_session::{Pallet, Storage, Event, Config}, + Iris: pallet_iris_asset::{Pallet, Call, Storage, Event}, + Session: pallet_session::{Pallet, Call, Storage, Event, Config}, Assets: pallet_assets::{Pallet, Storage, Event}, // removed call to make extrinsics uncallable Aura: pallet_aura::{Pallet, Config}, @@ -435,7 +435,6 @@ construct_runtime!( // Historical: pallet_session_historical::{Pallet}, } ); -// Iris: pallet_iris::{Pallet, Call, Storage, Event, ValidateUnsigned}, /// The address format for describing accounts. pub type Address = sp_runtime::MultiAddress; @@ -659,7 +658,7 @@ impl_runtime_apis! { add_benchmark!(params, batches, frame_system, SystemBench::); add_benchmark!(params, batches, pallet_balances, Balances); add_benchmark!(params, batches, pallet_timestamp, Timestamp); - add_benchmark!(params, batches, pallet_iris, Iris); + add_benchmark!(params, batches, pallet_iris_asset, Iris); if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } Ok(batches) From 961666a2cb26c2aadf34f2b559967fac1392e4d8 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Thu, 13 Jan 2022 21:43:00 -0400 Subject: [PATCH 381/695] Use free balance rather than total balance for elections phragmen (#10646) * use free balance rather than total balance * Docs Co-authored-by: emostov <32168567+emostov@users.noreply.github.com> --- frame/elections-phragmen/src/lib.rs | 75 +++++++++++++++++------------ 1 file changed, 43 insertions(+), 32 deletions(-) diff --git a/frame/elections-phragmen/src/lib.rs b/frame/elections-phragmen/src/lib.rs index b0e0a6fb984e..1e8f61f6b268 100644 --- a/frame/elections-phragmen/src/lib.rs +++ b/frame/elections-phragmen/src/lib.rs @@ -280,7 +280,7 @@ pub mod pallet { /// - be less than the number of possible candidates. Note that all current members and /// runners-up are also automatically candidates for the next round. /// - /// If `value` is more than `who`'s total balance, then the maximum of the two is used. + /// If `value` is more than `who`'s free balance, then the maximum of the two is used. /// /// The dispatch origin of this call must be signed. /// @@ -342,7 +342,7 @@ pub mod pallet { }; // Amount to be locked up. - let locked_stake = value.min(T::Currency::total_balance(&who)); + let locked_stake = value.min(T::Currency::free_balance(&who)); T::Currency::set_lock(T::PalletId::get(), &who, locked_stake, WithdrawReasons::all()); Voting::::insert(&who, Voter { votes, deposit: new_deposit, stake: locked_stake }); @@ -1667,11 +1667,13 @@ mod tests { System::set_block_number(5); Elections::on_initialize(System::block_number()); + assert_eq!(balances(&4), (34, 6)); + assert_eq!(balances(&5), (45, 5)); assert_eq!( Elections::members(), vec![ - SeatHolder { who: 4, stake: 40, deposit: 4 }, - SeatHolder { who: 5, stake: 50, deposit: 3 }, + SeatHolder { who: 4, stake: 34, deposit: 4 }, + SeatHolder { who: 5, stake: 45, deposit: 3 }, ] ); }) @@ -1762,7 +1764,7 @@ mod tests { assert_ok!(vote(Origin::signed(2), vec![5], 20)); assert_eq!(balances(&2), (18, 2)); - assert_eq!(has_lock(&2), 20); + assert_eq!(has_lock(&2), 18); }); } @@ -1789,9 +1791,10 @@ mod tests { assert_ok!(submit_candidacy(Origin::signed(4))); assert_ok!(vote(Origin::signed(2), vec![5], 20)); + // User only locks up to their free balance. assert_eq!(balances(&2), (18, 2)); - assert_eq!(has_lock(&2), 20); - assert_eq!(locked_stake_of(&2), 20); + assert_eq!(has_lock(&2), 18); + assert_eq!(locked_stake_of(&2), 18); // can update; different stake; different lock and reserve. assert_ok!(vote(Origin::signed(2), vec![5, 4], 15)); @@ -1856,8 +1859,8 @@ mod tests { // 2 + 2 assert_eq!(balances(&2), (16, 4)); assert_eq!(Elections::voting(&2).deposit, 4); - assert_eq!(has_lock(&2), 18); - assert_eq!(locked_stake_of(&2), 18); + assert_eq!(has_lock(&2), 16); + assert_eq!(locked_stake_of(&2), 16); // back to 1 vote. assert_ok!(vote(Origin::signed(2), vec![4], 12)); @@ -2031,15 +2034,18 @@ mod tests { } #[test] - fn can_vote_for_more_than_total_balance_but_moot() { + fn can_vote_for_more_than_free_balance_but_moot() { ExtBuilder::default().build_and_execute(|| { assert_ok!(submit_candidacy(Origin::signed(5))); assert_ok!(submit_candidacy(Origin::signed(4))); - assert_ok!(vote(Origin::signed(2), vec![4, 5], 30)); - // you can lie but won't get away with it. - assert_eq!(locked_stake_of(&2), 20); - assert_eq!(has_lock(&2), 20); + // User has 100 free and 50 reserved. + assert_ok!(Balances::set_balance(Origin::root(), 2, 100, 50)); + // User tries to vote with 150 tokens. + assert_ok!(vote(Origin::signed(2), vec![4, 5], 150)); + // We truncate to only their free balance, after reserving additional for voting. + assert_eq!(locked_stake_of(&2), 98); + assert_eq!(has_lock(&2), 98); }); } @@ -2052,8 +2058,10 @@ mod tests { assert_ok!(vote(Origin::signed(3), vec![5], 30)); assert_eq_uvec!(all_voters(), vec![2, 3]); - assert_eq!(locked_stake_of(&2), 20); - assert_eq!(locked_stake_of(&3), 30); + assert_eq!(balances(&2), (12, 8)); + assert_eq!(locked_stake_of(&2), 12); + assert_eq!(balances(&3), (22, 8)); + assert_eq!(locked_stake_of(&3), 22); assert_eq!(votes_of(&2), vec![5]); assert_eq!(votes_of(&3), vec![5]); @@ -2133,7 +2141,10 @@ mod tests { System::set_block_number(5); Elections::on_initialize(System::block_number()); - assert_eq!(members_and_stake(), vec![(3, 30), (5, 20)]); + assert_eq!(balances(&3), (25, 5)); + // votes for 5 + assert_eq!(balances(&2), (18, 2)); + assert_eq!(members_and_stake(), vec![(3, 25), (5, 18)]); assert!(Elections::runners_up().is_empty()); assert_eq_uvec!(all_voters(), vec![2, 3, 4]); @@ -2168,10 +2179,10 @@ mod tests { Elections::on_initialize(System::block_number()); System::assert_last_event(Event::Elections(super::Event::NewTerm { - new_members: vec![(4, 40), (5, 50)], + new_members: vec![(4, 35), (5, 45)], })); - assert_eq!(members_and_stake(), vec![(4, 40), (5, 50)]); + assert_eq!(members_and_stake(), vec![(4, 35), (5, 45)]); assert_eq!(runners_up_and_stake(), vec![]); assert_ok!(Elections::remove_voter(Origin::signed(5))); @@ -2202,7 +2213,7 @@ mod tests { System::set_block_number(5); Elections::on_initialize(System::block_number()); - assert_eq!(members_and_stake(), vec![(5, 50)]); + assert_eq!(members_and_stake(), vec![(5, 45)]); assert_eq!(Elections::election_rounds(), 1); // but now it has a valid target. @@ -2212,7 +2223,7 @@ mod tests { Elections::on_initialize(System::block_number()); // candidate 4 is affected by an old vote. - assert_eq!(members_and_stake(), vec![(4, 30), (5, 50)]); + assert_eq!(members_and_stake(), vec![(4, 28), (5, 45)]); assert_eq!(Elections::election_rounds(), 2); assert_eq_uvec!(all_voters(), vec![3, 5]); }); @@ -2300,16 +2311,16 @@ mod tests { System::set_block_number(5); Elections::on_initialize(System::block_number()); - assert_eq!(members_and_stake(), vec![(4, 40), (5, 50)]); - assert_eq!(runners_up_and_stake(), vec![(2, 20), (3, 30)]); + assert_eq!(members_and_stake(), vec![(4, 35), (5, 45)]); + assert_eq!(runners_up_and_stake(), vec![(2, 15), (3, 25)]); - assert_ok!(vote(Origin::signed(5), vec![5], 15)); + assert_ok!(vote(Origin::signed(5), vec![5], 10)); System::set_block_number(10); Elections::on_initialize(System::block_number()); - assert_eq!(members_and_stake(), vec![(3, 30), (4, 40)]); - assert_eq!(runners_up_and_stake(), vec![(5, 15), (2, 20)]); + assert_eq!(members_and_stake(), vec![(3, 25), (4, 35)]); + assert_eq!(runners_up_and_stake(), vec![(5, 10), (2, 15)]); }); } @@ -2443,8 +2454,8 @@ mod tests { System::set_block_number(b.into()); Elections::on_initialize(System::block_number()); // we keep re-electing the same folks. - assert_eq!(members_and_stake(), vec![(4, 40), (5, 50)]); - assert_eq!(runners_up_and_stake(), vec![(2, 20), (3, 30)]); + assert_eq!(members_and_stake(), vec![(4, 35), (5, 45)]); + assert_eq!(runners_up_and_stake(), vec![(2, 15), (3, 25)]); // no new candidates but old members and runners-up are always added. assert!(candidate_ids().is_empty()); assert_eq!(Elections::election_rounds(), b / 5); @@ -2596,7 +2607,7 @@ mod tests { Elections::on_initialize(System::block_number()); // 3, 4 are new members, must still be bonded, nothing slashed. - assert_eq!(members_and_stake(), vec![(3, 30), (4, 48)]); + assert_eq!(members_and_stake(), vec![(3, 25), (4, 43)]); assert_eq!(balances(&3), (25, 5)); assert_eq!(balances(&4), (35, 5)); @@ -2607,7 +2618,7 @@ mod tests { assert_eq!(balances(&5), (45, 2)); System::assert_has_event(Event::Elections(super::Event::NewTerm { - new_members: vec![(4, 40), (5, 50)], + new_members: vec![(4, 35), (5, 45)], })); }) } @@ -2646,9 +2657,9 @@ mod tests { System::set_block_number(5); Elections::on_initialize(System::block_number()); // id: low -> high. - assert_eq!(members_and_stake(), vec![(4, 50), (5, 40)]); + assert_eq!(members_and_stake(), vec![(4, 45), (5, 35)]); // merit: low -> high. - assert_eq!(runners_up_and_stake(), vec![(3, 20), (2, 30)]); + assert_eq!(runners_up_and_stake(), vec![(3, 15), (2, 25)]); }); } From 9eddaec3b8f15eec0c458e7bb3a1c16db91d8199 Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Fri, 14 Jan 2022 12:02:53 +0100 Subject: [PATCH 382/695] Increase default rocksdb cache (#10659) --- client/cli/src/config.rs | 2 +- utils/frame/benchmarking-cli/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/cli/src/config.rs b/client/cli/src/config.rs index cc3b0590566a..b5470db91db3 100644 --- a/client/cli/src/config.rs +++ b/client/cli/src/config.rs @@ -485,7 +485,7 @@ pub trait CliConfiguration: Sized { let config_dir = base_path.config_dir(chain_spec.id()); let net_config_dir = config_dir.join(DEFAULT_NETWORK_CONFIG_PATH); let client_id = C::client_id(); - let database_cache_size = self.database_cache_size()?.unwrap_or(128); + let database_cache_size = self.database_cache_size()?.unwrap_or(1024); let database = self.database()?.unwrap_or(Database::RocksDb); let node_key = self.node_key(&net_config_dir)?; let role = self.role(is_dev)?; diff --git a/utils/frame/benchmarking-cli/src/lib.rs b/utils/frame/benchmarking-cli/src/lib.rs index c331dea34c47..664e526ae0d7 100644 --- a/utils/frame/benchmarking-cli/src/lib.rs +++ b/utils/frame/benchmarking-cli/src/lib.rs @@ -133,7 +133,7 @@ pub struct BenchmarkCmd { pub wasm_method: WasmExecutionMethod, /// Limit the memory the database cache can use. - #[structopt(long = "db-cache", value_name = "MiB", default_value = "128")] + #[structopt(long = "db-cache", value_name = "MiB", default_value = "1024")] pub database_cache_size: u32, /// List the benchmarks that match your query rather than running them. From e62d47e7aa7a980d3b104384360844e3b9342d33 Mon Sep 17 00:00:00 2001 From: driemworks Date: Fri, 14 Jan 2022 15:03:54 -0600 Subject: [PATCH 383/695] WIP: move ipfs functionality to new pallet --- Cargo.lock | 8 +- Cargo.toml | 2 +- bin/node-template/node/Cargo.toml | 2 +- .../pallets/iris-asset/src/lib.rs | 682 ------------------ .../{iris-asset => iris-assets}/Cargo.toml | 2 +- .../{iris-asset => iris-assets}/README.md | 0 .../rpc/Cargo.toml | 0 .../{iris-asset => iris-assets}/rpc/README.md | 0 .../rpc/runtime-api/Cargo.toml | 4 +- .../rpc/runtime-api/README.md | 0 .../rpc/runtime-api/src/lib.rs | 0 .../rpc/src/lib.rs | 0 .../src/benchmarking.rs | 0 .../pallets/iris-assets/src/lib.rs | 659 +++++++++++++++++ .../{iris-asset => iris-assets}/src/mock.rs | 0 .../{iris-asset => iris-assets}/src/tests.rs | 0 .../pallets/iris-session/Cargo.toml | 7 +- .../pallets/iris-session/src/lib.rs | 332 ++++++++- bin/node-template/runtime/Cargo.toml | 9 +- bin/node-template/runtime/src/lib.rs | 13 +- bin/node/rpc/Cargo.toml | 2 +- 21 files changed, 1001 insertions(+), 721 deletions(-) delete mode 100644 bin/node-template/pallets/iris-asset/src/lib.rs rename bin/node-template/pallets/{iris-asset => iris-assets}/Cargo.toml (98%) rename bin/node-template/pallets/{iris-asset => iris-assets}/README.md (100%) rename bin/node-template/pallets/{iris-asset => iris-assets}/rpc/Cargo.toml (100%) rename bin/node-template/pallets/{iris-asset => iris-assets}/rpc/README.md (100%) rename bin/node-template/pallets/{iris-asset => iris-assets}/rpc/runtime-api/Cargo.toml (88%) rename bin/node-template/pallets/{iris-asset => iris-assets}/rpc/runtime-api/README.md (100%) rename bin/node-template/pallets/{iris-asset => iris-assets}/rpc/runtime-api/src/lib.rs (100%) rename bin/node-template/pallets/{iris-asset => iris-assets}/rpc/src/lib.rs (100%) rename bin/node-template/pallets/{iris-asset => iris-assets}/src/benchmarking.rs (100%) create mode 100644 bin/node-template/pallets/iris-assets/src/lib.rs rename bin/node-template/pallets/{iris-asset => iris-assets}/src/mock.rs (100%) rename bin/node-template/pallets/{iris-asset => iris-assets}/src/tests.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index bd7ea5e76845..539ecf6b2ebc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5040,7 +5040,7 @@ dependencies = [ "pallet-aura", "pallet-balances", "pallet-grandpa", - "pallet-iris", + "pallet-iris-assets", "pallet-iris-rpc-runtime-api", "pallet-iris-session", "pallet-randomness-collective-flip", @@ -5851,7 +5851,7 @@ dependencies = [ ] [[package]] -name = "pallet-iris" +name = "pallet-iris-assets" version = "3.0.0" dependencies = [ "frame-benchmarking", @@ -5890,7 +5890,7 @@ dependencies = [ name = "pallet-iris-rpc-runtime-api" version = "4.0.0-dev" dependencies = [ - "pallet-iris", + "pallet-iris-assets", "parity-scale-codec", "sp-api", "sp-core", @@ -5906,7 +5906,7 @@ dependencies = [ "frame-system", "log 0.4.14", "pallet-assets", - "pallet-balances", + "pallet-iris-assets", "pallet-session", "parity-scale-codec", "scale-info", diff --git a/Cargo.toml b/Cargo.toml index 71473a4bc568..3f428bcccc7a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ resolver = "2" members = [ "bin/node-template/node", - "bin/node-template/pallets/template", + "bin/node-template/pallets/iris-assets", "bin/node-template/runtime", "bin/node/bench", "bin/node/cli", diff --git a/bin/node-template/node/Cargo.toml b/bin/node-template/node/Cargo.toml index 242323c63381..d5731d9f0d1b 100644 --- a/bin/node-template/node/Cargo.toml +++ b/bin/node-template/node/Cargo.toml @@ -48,7 +48,7 @@ sp-block-builder = { version = "4.0.0-dev", path = "../../../primitives/block-bu sc-basic-authorship = { version = "0.10.0-dev", path = "../../../client/basic-authorship" } substrate-frame-rpc-system = { version = "4.0.0-dev", path = "../../../utils/frame/rpc/system" } pallet-transaction-payment-rpc = { version = "4.0.0-dev", path = "../../../frame/transaction-payment/rpc/" } -pallet-iris-rpc = { version = "4.0.0-dev", path = "../pallets/template/rpc/" } +pallet-iris-rpc = { version = "4.0.0-dev", path = "../pallets/iris-assets/rpc/" } # These dependencies are used for runtime benchmarking frame-benchmarking = { version = "4.0.0-dev", path = "../../../frame/benchmarking" } diff --git a/bin/node-template/pallets/iris-asset/src/lib.rs b/bin/node-template/pallets/iris-asset/src/lib.rs deleted file mode 100644 index a9d5c975b806..000000000000 --- a/bin/node-template/pallets/iris-asset/src/lib.rs +++ /dev/null @@ -1,682 +0,0 @@ -#![cfg_attr(not(feature = "std"), no_std)] - -//! # Iris Storage Pallet -//! -//! -//! ## Overview -//! Disclaimer: This pallet is in the tadpole state -//! -//! ### Goals -//! The Iris module provides functionality for creation and management of storage assets and access management -//! -//! ### Dispatchable Functions -//! -//! #### Permissionless functions -//! * create_storage_asset -//! * request_data -//! -//! #### Permissioned Functions -//! * submit_ipfs_add_results -//! * submit_ipfs_identity -//! * submit_rpc_ready -//! * destroy_ticket -//! * mint_tickets -//! - -use scale_info::TypeInfo; -use codec::{Encode, Decode}; -use frame_support::{ - ensure, - traits::ReservableCurrency, -}; -use frame_system::{ - self as system, ensure_signed, - offchain::{ - SendSignedTransaction, - Signer, - }, -}; - -use sp_core::{ - offchain::{ - Duration, IpfsRequest, IpfsResponse, OpaqueMultiaddr, Timestamp, StorageKind, - }, - crypto::KeyTypeId, - Bytes, -}; - -use sp_io::offchain::timestamp; -use sp_runtime::{ - offchain::{ - ipfs, - }, - RuntimeDebug, - traits::StaticLookup, -}; -use sp_std::{ - str, - vec::Vec, - prelude::*, - convert::TryInto, -}; - -pub const KEY_TYPE: KeyTypeId = KeyTypeId(*b"iris"); - - -pub mod crypto { - use crate::KEY_TYPE; - use sp_core::sr25519::Signature as Sr25519Signature; - use sp_runtime::app_crypto::{app_crypto, sr25519}; - use sp_runtime::{traits::Verify, MultiSignature, MultiSigner}; - - app_crypto!(sr25519, KEY_TYPE); - - pub struct TestAuthId; - // implemented for runtime - impl frame_system::offchain::AppCrypto for TestAuthId { - type RuntimeAppPublic = Public; - type GenericSignature = sp_core::sr25519::Signature; - type GenericPublic = sp_core::sr25519::Public; - } - - // implemented for mock runtime in test - impl frame_system::offchain::AppCrypto<::Signer, Sr25519Signature> - for TestAuthId - { - type RuntimeAppPublic = Public; - type GenericSignature = sp_core::sr25519::Signature; - type GenericPublic = sp_core::sr25519::Public; - } -} - -#[derive(Encode, Decode, RuntimeDebug, PartialEq, TypeInfo)] -pub enum DataCommand { - /// (ipfs_address, cid, requesting node address, filename, asset id, balance) - AddBytes(OpaqueMultiaddr, Vec, LookupSource, Vec, AssetId, Balance), - // /// owner, cid - CatBytes(AccountId, Vec, AccountId), -} - -pub use pallet::*; - -#[cfg(test)] -mod mock; - -#[cfg(test)] -mod tests; - -#[cfg(feature = "runtime-benchmarks")] -mod benchmarking; - -#[frame_support::pallet] -pub mod pallet { - use super::*; - use frame_support::{dispatch::DispatchResult, pallet_prelude::*}; - use frame_system::{ - pallet_prelude::*, - offchain::{ - AppCrypto, - CreateSignedTransaction, - }, - }; - use sp_core::offchain::OpaqueMultiaddr; - use sp_std::{str, vec::Vec}; - - #[pallet::config] - /// the module configuration trait - pub trait Config:CreateSignedTransaction> + frame_system::Config + pallet_assets::Config { - /// The overarching event type - type Event: From> + IsType<::Event>; - /// the authority id used for sending signed txs - type AuthorityId: AppCrypto; - /// the overarching call type - type Call: From>; - /// the currency used - type Currency: ReservableCurrency; - } - - #[pallet::pallet] - #[pallet::generate_store(pub(super) trait Store)] - pub struct Pallet(_); - - /// map the ipfs public key to a list of multiaddresses - /// this could be moved to the session pallet - #[pallet::storage] - #[pallet::getter(fn bootstrap_nodes)] - pub(super) type BootstrapNodes = StorageMap< - _, - Blake2_128Concat, - Vec, - Vec, - ValueQuery, - >; - - /// A queue of data to publish or obtain on IPFS. - #[pallet::storage] - #[pallet::getter(fn data_queue)] - pub(super) type DataQueue = StorageValue< - _, - Vec::Source, - T::AssetId, - T::Balance, - T::AccountId> - >, - ValueQuery - >; - - /// Store the map associating owned CID to a specific asset ID - /// - /// asset_admin_accountid -> CID -> asset id - #[pallet::storage] - #[pallet::getter(fn created_asset_classes)] - pub(super) type AssetClassOwnership = StorageDoubleMap< - _, - Blake2_128Concat, - T::AccountId, - Blake2_128Concat, - Vec, - T::AssetId, - ValueQuery, - >; - - /// Store the map associated a node with the assets to which they have access - /// - /// asset_owner_accountid -> CID -> asset_class_owner_accountid - #[pallet::storage] - #[pallet::getter(fn asset_access)] - pub(super) type AssetAccess = StorageDoubleMap< - _, - Blake2_128Concat, - T::AccountId, - Blake2_128Concat, - Vec, - T::AccountId, - ValueQuery, - >; - - #[pallet::event] - #[pallet::generate_deposit(pub(super) fn deposit_event)] - pub enum Event { - /// A request to add bytes was queued - QueuedDataToAdd(T::AccountId), - /// A request to retrieve bytes was queued - QueuedDataToCat(T::AccountId), - /// A new asset class was created (add bytes command processed) - AssetClassCreated(T::AssetId), - /// A new asset was created (tickets minted) - AssetCreated(T::AssetId), - /// A node's request to access data via the RPC endpoint has been processed - DataReady(T::AccountId), - /// A node has published ipfs identity results on chain - PublishedIdentity(T::AccountId), - } - - #[pallet::error] - pub enum Error { - /// could not build the ipfs request - CantCreateRequest, - /// the request to IPFS timed out - RequestTimeout, - /// the request to IPFS failed - RequestFailed, - /// The tx could not be signed - OffchainSignedTxError, - /// you cannot sign a tx - NoLocalAcctForSigning, - /// could not create a new asset - CantCreateAssetClass, - /// could not mint a new asset - CantMintAssets, - /// there is no asset associated with the specified cid - NoSuchOwnedContent, - /// the specified asset class does not exist - NoSuchAssetClass, - /// the account does not have a sufficient balance - InsufficientBalance, - } - - #[pallet::hooks] - impl Hooks> for Pallet { - fn on_initialize(block_number: T::BlockNumber) -> Weight { - // needs to be synchronized with offchain_worker actitivies - if block_number % 2u32.into() == 1u32.into() { - >::kill(); - } - - 0 - } - fn offchain_worker(block_number: T::BlockNumber) { - // every 5 blocks - if block_number % 5u32.into() == 0u32.into() { - if let Err(e) = Self::connection_housekeeping() { - log::error!("IPFS: Encountered an error while processing data requests: {:?}", e); - } - } - - // handle data requests each block - if let Err(e) = Self::handle_data_requests() { - log::error!("IPFS: Encountered an error while processing data requests: {:?}", e); - } - - // every 5 blocks - if block_number % 5u32.into() == 0u32.into() { - if let Err(e) = Self::print_metadata() { - log::error!("IPFS: Encountered an error while obtaining metadata: {:?}", e); - } - } - } - } - - #[pallet::call] - impl Pallet { - - /// submits an on-chain request to fetch data and add it to iris - /// - /// * `addr`: the multiaddress where the data exists - /// example: /ip4/192.168.1.170/tcp/4001/p2p/12D3KooWMvyvKxYcy9mjbFbXcogFSCvENzQ62ogRxHKZaksFCkAp - /// * `cid`: the cid to fetch from the multiaddress - /// example: QmPZv7P8nQUSh2CpqTvUeYemFyjvMjgWEs8H1Tm8b3zAm9 - /// * `id`: (temp) the unique id of the asset class -> should be generated instead - /// * `balance`: the balance the owner is willing to use to back the asset class which will be created - /// - #[pallet::weight(0)] - pub fn create_storage_asset( - origin: OriginFor, - admin: ::Source, - addr: Vec, - cid: Vec, - name: Vec, - id: T::AssetId, - balance: T::Balance, - ) -> DispatchResult { - let who = ensure_signed(origin)?; - let multiaddr = OpaqueMultiaddr(addr); - >::mutate( - |queue| queue.push(DataCommand::AddBytes( - multiaddr, - cid, - admin.clone(), - name.clone(), - id.clone(), - balance.clone(), - ))); - Self::deposit_event(Event::QueuedDataToAdd(who.clone())); - Ok(()) - } - - /// Queue a request to retrieve data behind some owned CID from the IPFS network - /// - /// * owner: The owner node - /// * cid: the cid to which you are requesting access - /// - #[pallet::weight(0)] - pub fn request_data( - origin: OriginFor, - owner: ::Source, - cid: Vec, - ) -> DispatchResult { - let who = ensure_signed(origin)?; - let owner_account = T::Lookup::lookup(owner)?; - - >::mutate( - |queue| queue.push(DataCommand::CatBytes( - owner_account.clone(), - cid.clone(), - who.clone(), - ) - )); - - Self::deposit_event(Event::QueuedDataToCat(who.clone())); - - Ok(()) - } - - /// should only be called by offchain workers... how to ensure this? - /// submits IPFS results on chain and creates new ticket config in runtime storage - /// - /// * `admin`: The admin account - /// * `cid`: The cid generated by the OCW - /// * `id`: The AssetId (passed through from the create_storage_asset call) - /// * `balance`: The balance (passed through from the create_storage_asset call) - /// - #[pallet::weight(0)] - pub fn submit_ipfs_add_results( - origin: OriginFor, - admin: ::Source, - cid: Vec, - id: T::AssetId, - balance: T::Balance, - ) -> DispatchResult { - // DANGER: This can currently be called by anyone, not just an OCW. - // if we send an unsigned transaction then we can ensure there is no origin - // however, the call to create the asset requires an origin, which is a little problematic - // ensure_none(origin)?; - let who = ensure_signed(origin)?; - let new_origin = system::RawOrigin::Signed(who).into(); - - >::create(new_origin, id.clone(), admin.clone(), balance) - .map_err(|_| Error::::CantCreateAssetClass)?; - - let which_admin = T::Lookup::lookup(admin.clone())?; - >::insert(which_admin, cid.clone(), id.clone()); - - Self::deposit_event(Event::AssetClassCreated(id.clone())); - - Ok(()) - } - - /// Should only be callable by OCWs (TODO) - /// Submit the results of an `ipfs identity` call to be stored on chain - /// - /// * origin: a validator node - /// * public_key: The IPFS node's public key - /// * multiaddresses: A vector of multiaddresses associate with the public key - /// - #[pallet::weight(0)] - pub fn submit_ipfs_identity( - origin: OriginFor, - public_key: Vec, - multiaddresses: Vec, - ) -> DispatchResult { - let who = ensure_signed(origin)?; - >::insert(public_key.clone(), multiaddresses.clone()); - Self::deposit_event(Event::PublishedIdentity(who.clone())); - Ok(()) - } - - /// Should only be callable by OCWs (TODO) - /// Submit the results onchain to notify a beneficiary that their data is available: TODO: how to safely share host? spam protection on rpc endpoints? - /// - /// * `beneficiary`: The account that requested the data - /// * `host`: The node's host where the data has been made available (RPC endpoint) - /// - #[pallet::weight(0)] - pub fn submit_rpc_ready( - origin: OriginFor, - beneficiary: T::AccountId, - // host: Vec, - ) -> DispatchResult { - ensure_signed(origin)?; - Self::deposit_event(Event::DataReady(beneficiary)); - Ok(()) - } - - /// Only callable by the owner of the asset class - /// mint a static number of assets (tickets) for some asset class - /// - /// * origin: should be the owner of the asset class - /// * beneficiary: the address to which the newly minted assets are assigned - /// * cid: a cid owned by the origin, for which an asset class exists - /// * amount: the number of tickets to mint - /// - #[pallet::weight(0)] - pub fn mint_tickets( - origin: OriginFor, - beneficiary: ::Source, - cid: Vec, - #[pallet::compact] amount: T::Balance, - ) -> DispatchResult { - let who = ensure_signed(origin)?; - let new_origin = system::RawOrigin::Signed(who.clone()).into(); - let beneficiary_accountid = T::Lookup::lookup(beneficiary.clone())?; - - ensure!(AssetClassOwnership::::contains_key(who.clone(), cid.clone()), Error::::NoSuchOwnedContent); - - let asset_id = AssetClassOwnership::::get(who.clone(), cid.clone(),); - >::mint(new_origin, asset_id.clone(), beneficiary.clone(), amount) - .map_err(|_| Error::::CantMintAssets)?; - - >::insert(beneficiary_accountid.clone(), cid.clone(), who.clone()); - - Self::deposit_event(Event::AssetCreated(asset_id.clone())); - Ok(()) - } - - /// TODO: leaving this as is for now... I feel like this will require some further thought. We almost need a dex-like feature - /// Purchase a ticket to access some content. - /// - /// * origin: any origin - /// * owner: The owner to identify the asset class for which a ticket is to be purchased - /// * cid: The CID to identify the asset class for which a ticket is to be purchased - /// * amount: The number of tickets to purchase - /// - #[pallet::weight(0)] - pub fn purchase_ticket( - origin: OriginFor, - _owner: ::Source, - _cid: Vec, - #[pallet::compact] _amount: T::Balance, - _test: T::Signature, - ) -> DispatchResult { - ensure_signed(origin)?; - // determine price for amount of asset and verify origin has a min balance - // transfer native currency to asset class admin - // admin transfers the requested amount of tokens to the buyer - Ok(()) - } - } -} - -impl Pallet { - /// implementation for RPC runtime aPI to retrieve bytes from the node's local storage - /// - /// * public_key: The account's public key as bytes - /// * signature: The signer's signature as bytes - /// * message: The signed message as bytes - /// - pub fn retrieve_bytes( - _public_key: Bytes, - _signature: Bytes, - message: Bytes, - ) -> Bytes { - // TODO: Verify signature, update offchain storage keys... - let message_vec: Vec = message.to_vec(); - if let Some(data) = sp_io::offchain::local_storage_get(StorageKind::PERSISTENT, &message_vec) { - Bytes(data.clone()) - } else { - Bytes(Vec::new()) - } - } - - /// send a request to the local IPFS node; can only be called be an off-chain worker - fn ipfs_request( - req: IpfsRequest, - deadline: impl Into>, - ) -> Result> { - let ipfs_request = ipfs::PendingRequest::new(req).map_err(|_| Error::::CantCreateRequest)?; - ipfs_request.try_wait(deadline) - .map_err(|_| Error::::RequestTimeout)? - .map(|r| r.response) - .map_err(|e| { - if let ipfs::Error::IoError(err) = e { - log::error!("IPFS: request failed: {}", str::from_utf8(&err).unwrap()); - } else { - log::error!("IPFS: request failed: {:?}", e); - } - Error::::RequestFailed - }) - } - - /// manage connection to the iris ipfs swarm - /// - /// If the node is already a bootstrap node, do nothing. Otherwise submits a signed tx - /// containing the public key and multiaddresses of the embedded ipfs node. - /// - /// Returns an error if communication with the embedded IPFS fails - fn connection_housekeeping() -> Result<(), Error> { - let deadline = Some(timestamp().add(Duration::from_millis(5_000))); - - let (public_key, addrs) = if let IpfsResponse::Identity(public_key, addrs) = Self::ipfs_request(IpfsRequest::Identity, deadline)? { - (public_key, addrs) - } else { - unreachable!("only `Identity` is a valid response type."); - }; - - if !>::contains_key(public_key.clone()) { - if let Some(bootstrap_node) = &>::iter().nth(0) { - if let Some(bootnode_maddr) = bootstrap_node.1.clone().pop() { - if let IpfsResponse::Success = Self::ipfs_request(IpfsRequest::Connect(bootnode_maddr.clone()), deadline)? { - log::info!("Succesfully connected to a bootstrap node: {:?}", &bootnode_maddr.0); - } else { - log::info!("Failed to connect to the bootstrap node with multiaddress: {:?}", &bootnode_maddr.0); - // TODO: this should probably be some recursive function? but we should never exceed a depth of 2 so maybe not - if let Some(next_bootnode_maddr) = bootstrap_node.1.clone().pop() { - if let IpfsResponse::Success = Self::ipfs_request(IpfsRequest::Connect(next_bootnode_maddr.clone()), deadline)? { - log::info!("Succesfully connected to a bootstrap node: {:?}", &next_bootnode_maddr.0); - } else { - log::info!("Failed to connect to the bootstrap node with multiaddress: {:?}", &next_bootnode_maddr.0); - } - } - } - } - } - // TODO: should create func to encompass the below logic - let signer = Signer::::all_accounts(); - if !signer.can_sign() { - log::error!( - "No local accounts available. Consider adding one via `author_insertKey` RPC.", - ); - } - - let results = signer.send_signed_transaction(|_account| { - Call::submit_ipfs_identity{ - public_key: public_key.clone(), - multiaddresses: addrs.clone(), - } - }); - - for (_, res) in &results { - match res { - Ok(()) => log::info!("Submitted ipfs identity results"), - Err(e) => log::error!("Failed to submit transaction: {:?}", e), - } - } - - } - Ok(()) - } - - /// process any requests in the DataQueue - fn handle_data_requests() -> Result<(), Error> { - let data_queue = DataQueue::::get(); - let len = data_queue.len(); - if len != 0 { - log::info!("IPFS: {} entr{} in the data queue", len, if len == 1 { "y" } else { "ies" }); - } - // TODO: Needs refactoring - let deadline = Some(timestamp().add(Duration::from_millis(5_000))); - for cmd in data_queue.into_iter() { - match cmd { - DataCommand::AddBytes(addr, cid, admin, _name, id, balance) => { - Self::ipfs_request(IpfsRequest::Connect(addr.clone()), deadline)?; - log::info!( - "IPFS: connected to {}", - str::from_utf8(&addr.0).expect("our own calls can be trusted to be UTF-8; qed") - ); - match Self::ipfs_request(IpfsRequest::CatBytes(cid.clone()), deadline) { - Ok(IpfsResponse::CatBytes(data)) => { - log::info!("IPFS: fetched data"); - Self::ipfs_request(IpfsRequest::Disconnect(addr.clone()), deadline)?; - log::info!( - "IPFS: disconnected from {}", - str::from_utf8(&addr.0).expect("our own calls can be trusted to be UTF-8; qed") - ); - match Self::ipfs_request(IpfsRequest::AddBytes(data.clone()), deadline) { - Ok(IpfsResponse::AddBytes(new_cid)) => { - log::info!( - "IPFS: added data with Cid {}", - str::from_utf8(&new_cid).expect("our own IPFS node can be trusted here; qed") - ); - let signer = Signer::::all_accounts(); - if !signer.can_sign() { - log::error!( - "No local accounts available. Consider adding one via `author_insertKey` RPC.", - ); - } - let results = signer.send_signed_transaction(|_account| { - Call::submit_ipfs_add_results{ - admin: admin.clone(), - cid: new_cid.clone(), - id: id.clone(), - balance: balance.clone(), - } - }); - - for (_, res) in &results { - match res { - Ok(()) => log::info!("Submitted ipfs results"), - Err(e) => log::error!("Failed to submit transaction: {:?}", e), - } - } - }, - Ok(_) => unreachable!("only AddBytes can be a response for that request type."), - Err(e) => log::error!("IPFS: add error: {:?}", e), - } - }, - Ok(_) => unreachable!("only CatBytes can be a response for that request type."), - Err(e) => log::error!("IPFS: cat error: {:?}", e), - } - }, - DataCommand::CatBytes(owner, cid, recipient) => { - ensure!(AssetClassOwnership::::contains_key(owner.clone(), cid.clone()), Error::::NoSuchOwnedContent); - let asset_id = AssetClassOwnership::::get(owner.clone(), cid.clone()); - let balance = >::balance(asset_id.clone(), recipient.clone()); - let balance_primitive = TryInto::::try_into(balance).ok(); - ensure!(balance_primitive != Some(0), Error::::InsufficientBalance); - match Self::ipfs_request(IpfsRequest::CatBytes(cid.clone()), deadline) { - Ok(IpfsResponse::CatBytes(data)) => { - log::info!("IPFS: Fetched data from IPFS."); - // add to offchain index - sp_io::offchain::local_storage_set( - StorageKind::PERSISTENT, - &cid, - &data, - ); - let signer = Signer::::all_accounts(); - if !signer.can_sign() { - log::error!( - "No local accounts available. Consider adding one via `author_insertKey` RPC.", - ); - } - let results = signer.send_signed_transaction(|_account| { - Call::submit_rpc_ready { - beneficiary: recipient.clone(), - } - }); - - for (_, res) in &results { - match res { - Ok(()) => log::info!("Submitted ipfs results"), - Err(e) => log::error!("Failed to submit transaction: {:?}", e), - } - } - }, - Ok(_) => unreachable!("only CatBytes can be a response for that request type."), - Err(e) => log::error!("IPFS: cat error: {:?}", e), - } - } - } - } - - Ok(()) - } - - fn print_metadata() -> Result<(), Error> { - let deadline = Some(timestamp().add(Duration::from_millis(5_000))); - - let peers = if let IpfsResponse::Peers(peers) = Self::ipfs_request(IpfsRequest::Peers, deadline)? { - peers - } else { - unreachable!("only Peers can be a response for that request type; qed"); - }; - let peer_count = peers.len(); - - log::info!( - "IPFS: currently connected to {} peer{}", - peer_count, - if peer_count == 1 { "" } else { "s" }, - ); - Ok(()) - } -} \ No newline at end of file diff --git a/bin/node-template/pallets/iris-asset/Cargo.toml b/bin/node-template/pallets/iris-assets/Cargo.toml similarity index 98% rename from bin/node-template/pallets/iris-asset/Cargo.toml rename to bin/node-template/pallets/iris-assets/Cargo.toml index 011f7c9efe82..e8a6d4c77b70 100644 --- a/bin/node-template/pallets/iris-asset/Cargo.toml +++ b/bin/node-template/pallets/iris-assets/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ['Substrate DevHub '] edition = '2018' -name = 'pallet-iris-asset' +name = 'pallet-iris-assets' version = "3.0.0" license = "Unlicense" homepage = "https://substrate.dev" diff --git a/bin/node-template/pallets/iris-asset/README.md b/bin/node-template/pallets/iris-assets/README.md similarity index 100% rename from bin/node-template/pallets/iris-asset/README.md rename to bin/node-template/pallets/iris-assets/README.md diff --git a/bin/node-template/pallets/iris-asset/rpc/Cargo.toml b/bin/node-template/pallets/iris-assets/rpc/Cargo.toml similarity index 100% rename from bin/node-template/pallets/iris-asset/rpc/Cargo.toml rename to bin/node-template/pallets/iris-assets/rpc/Cargo.toml diff --git a/bin/node-template/pallets/iris-asset/rpc/README.md b/bin/node-template/pallets/iris-assets/rpc/README.md similarity index 100% rename from bin/node-template/pallets/iris-asset/rpc/README.md rename to bin/node-template/pallets/iris-assets/rpc/README.md diff --git a/bin/node-template/pallets/iris-asset/rpc/runtime-api/Cargo.toml b/bin/node-template/pallets/iris-assets/rpc/runtime-api/Cargo.toml similarity index 88% rename from bin/node-template/pallets/iris-asset/rpc/runtime-api/Cargo.toml rename to bin/node-template/pallets/iris-assets/rpc/runtime-api/Cargo.toml index 21fe3e04c421..00d906df8ae6 100644 --- a/bin/node-template/pallets/iris-asset/rpc/runtime-api/Cargo.toml +++ b/bin/node-template/pallets/iris-assets/rpc/runtime-api/Cargo.toml @@ -17,7 +17,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../../../../primitives/api" } sp-core = { version = "4.0.0-dev", default-features = false, path = "../../../../../../primitives/core" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../../../../primitives/runtime" } -pallet-iris = { version = "3.0.0", default-features = false, path = "../../../template" } +pallet-iris-assets = { version = "3.0.0", default-features = false, path = "../../../iris-assets" } [features] default = ["std"] @@ -26,5 +26,5 @@ std = [ "sp-api/std", "sp-core/std", "sp-runtime/std", - "pallet-iris/std", + "pallet-iris-assets/std", ] diff --git a/bin/node-template/pallets/iris-asset/rpc/runtime-api/README.md b/bin/node-template/pallets/iris-assets/rpc/runtime-api/README.md similarity index 100% rename from bin/node-template/pallets/iris-asset/rpc/runtime-api/README.md rename to bin/node-template/pallets/iris-assets/rpc/runtime-api/README.md diff --git a/bin/node-template/pallets/iris-asset/rpc/runtime-api/src/lib.rs b/bin/node-template/pallets/iris-assets/rpc/runtime-api/src/lib.rs similarity index 100% rename from bin/node-template/pallets/iris-asset/rpc/runtime-api/src/lib.rs rename to bin/node-template/pallets/iris-assets/rpc/runtime-api/src/lib.rs diff --git a/bin/node-template/pallets/iris-asset/rpc/src/lib.rs b/bin/node-template/pallets/iris-assets/rpc/src/lib.rs similarity index 100% rename from bin/node-template/pallets/iris-asset/rpc/src/lib.rs rename to bin/node-template/pallets/iris-assets/rpc/src/lib.rs diff --git a/bin/node-template/pallets/iris-asset/src/benchmarking.rs b/bin/node-template/pallets/iris-assets/src/benchmarking.rs similarity index 100% rename from bin/node-template/pallets/iris-asset/src/benchmarking.rs rename to bin/node-template/pallets/iris-assets/src/benchmarking.rs diff --git a/bin/node-template/pallets/iris-assets/src/lib.rs b/bin/node-template/pallets/iris-assets/src/lib.rs new file mode 100644 index 000000000000..91487292d002 --- /dev/null +++ b/bin/node-template/pallets/iris-assets/src/lib.rs @@ -0,0 +1,659 @@ +#![cfg_attr(not(feature = "std"), no_std)] + +//! # Iris Storage Pallet +//! +//! +//! ## Overview +//! Disclaimer: This pallet is in the tadpole state +//! +//! ### Goals +//! The Iris module provides functionality for creation and management of storage assets and access management +//! +//! ### Dispatchable Functions +//! +//! #### Permissionless functions +//! * create_storage_asset +//! * request_data +//! +//! #### Permissioned Functions +//! * submit_ipfs_add_results +//! * submit_ipfs_identity +//! * submit_rpc_ready +//! * destroy_ticket +//! * mint_tickets +//! + +use scale_info::TypeInfo; +use codec::{Encode, Decode}; +use frame_support::{ + ensure, + traits::ReservableCurrency, +}; +use frame_system::{ + self as system, ensure_signed, + offchain::{ + SendSignedTransaction, + Signer, + }, +}; + +use sp_core::{ + offchain::{ + Duration, IpfsRequest, IpfsResponse, OpaqueMultiaddr, Timestamp, StorageKind, + }, + crypto::KeyTypeId, + Bytes, +}; + +use sp_io::offchain::timestamp; +use sp_runtime::{ + offchain::{ + ipfs, + }, + RuntimeDebug, + traits::StaticLookup, +}; +use sp_std::{ + str, + vec::Vec, + prelude::*, + convert::TryInto, +}; + +pub const KEY_TYPE: KeyTypeId = KeyTypeId(*b"iris"); + + +pub mod crypto { + use crate::KEY_TYPE; + use sp_core::sr25519::Signature as Sr25519Signature; + use sp_runtime::app_crypto::{app_crypto, sr25519}; + use sp_runtime::{traits::Verify, MultiSignature, MultiSigner}; + + app_crypto!(sr25519, KEY_TYPE); + + pub struct TestAuthId; + // implemented for runtime + impl frame_system::offchain::AppCrypto for TestAuthId { + type RuntimeAppPublic = Public; + type GenericSignature = sp_core::sr25519::Signature; + type GenericPublic = sp_core::sr25519::Public; + } + + // implemented for mock runtime in test + impl frame_system::offchain::AppCrypto<::Signer, Sr25519Signature> + for TestAuthId + { + type RuntimeAppPublic = Public; + type GenericSignature = sp_core::sr25519::Signature; + type GenericPublic = sp_core::sr25519::Public; + } +} + +#[derive(Encode, Decode, RuntimeDebug, PartialEq, TypeInfo)] +pub enum DataCommand { + /// (ipfs_address, cid, requesting node address, filename, asset id, balance) + AddBytes(OpaqueMultiaddr, Vec, LookupSource, Vec, AssetId, Balance), + // /// owner, cid + CatBytes(AccountId, Vec, AccountId), +} + +pub use pallet::*; + +#[cfg(test)] +mod mock; + +#[cfg(test)] +mod tests; + +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; + +#[frame_support::pallet] +pub mod pallet { + use super::*; + use frame_support::{dispatch::DispatchResult, pallet_prelude::*}; + use frame_system::{ + pallet_prelude::*, + offchain::{ + AppCrypto, + CreateSignedTransaction, + }, + }; + use sp_core::offchain::OpaqueMultiaddr; + use sp_std::{str, vec::Vec}; + + #[pallet::config] + /// the module configuration trait + pub trait Config:CreateSignedTransaction> + frame_system::Config + pallet_assets::Config { + /// The overarching event type + type Event: From> + IsType<::Event>; + /// the authority id used for sending signed txs + type AuthorityId: AppCrypto; + /// the overarching call type + type Call: From>; + /// the currency used + type Currency: ReservableCurrency; + } + + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet(_); + + // /// map the ipfs public key to a list of multiaddresses + // /// this could be moved to the session pallet + // #[pallet::storage] + // #[pallet::getter(fn bootstrap_nodes)] + // pub(super) type BootstrapNodes = StorageMap< + // _, + // Blake2_128Concat, + // Vec, + // Vec, + // ValueQuery, + // >; + + /// A queue of data to publish or obtain on IPFS. + #[pallet::storage] + #[pallet::getter(fn data_queue)] + pub(super) type DataQueue = StorageValue< + _, + Vec::Source, + T::AssetId, + T::Balance, + T::AccountId> + >, + ValueQuery + >; + + /// Store the map associating owned CID to a specific asset ID + /// + /// asset_admin_accountid -> CID -> asset id + #[pallet::storage] + #[pallet::getter(fn asset_class_ownership)] + pub(super) type AssetClassOwnership = StorageDoubleMap< + _, + Blake2_128Concat, + T::AccountId, + Blake2_128Concat, + Vec, + T::AssetId, + ValueQuery, + >; + + /// Store the map associated a node with the assets to which they have access + /// + /// asset_owner_accountid -> CID -> asset_class_owner_accountid + #[pallet::storage] + #[pallet::getter(fn asset_access)] + pub(super) type AssetAccess = StorageDoubleMap< + _, + Blake2_128Concat, + T::AccountId, + Blake2_128Concat, + Vec, + T::AccountId, + ValueQuery, + >; + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + /// A request to add bytes was queued + QueuedDataToAdd(T::AccountId), + /// A request to retrieve bytes was queued + QueuedDataToCat(T::AccountId), + /// A new asset class was created (add bytes command processed) + AssetClassCreated(T::AssetId), + /// A new asset was created (tickets minted) + AssetCreated(T::AssetId), + /// A node's request to access data via the RPC endpoint has been processed + DataReady(T::AccountId), + /// A node has published ipfs identity results on chain + PublishedIdentity(T::AccountId), + } + + #[pallet::error] + pub enum Error { + /// could not build the ipfs request + CantCreateRequest, + /// the request to IPFS timed out + RequestTimeout, + /// the request to IPFS failed + RequestFailed, + /// The tx could not be signed + OffchainSignedTxError, + /// you cannot sign a tx + NoLocalAcctForSigning, + /// could not create a new asset + CantCreateAssetClass, + /// could not mint a new asset + CantMintAssets, + /// there is no asset associated with the specified cid + NoSuchOwnedContent, + /// the specified asset class does not exist + NoSuchAssetClass, + /// the account does not have a sufficient balance + InsufficientBalance, + } + + #[pallet::hooks] + impl Hooks> for Pallet { + fn on_initialize(block_number: T::BlockNumber) -> Weight { + // needs to be synchronized with offchain_worker actitivies + if block_number % 2u32.into() == 1u32.into() { + >::kill(); + } + + 0 + } + fn offchain_worker(block_number: T::BlockNumber) { + // // every 5 blocks + // if block_number % 5u32.into() == 0u32.into() { + // if let Err(e) = Self::connection_housekeeping() { + // log::error!("IPFS: Encountered an error while processing data requests: {:?}", e); + // } + // } + + // // handle data requests each block + // if let Err(e) = Self::handle_data_requests() { + // log::error!("IPFS: Encountered an error while processing data requests: {:?}", e); + // } + + // // every 5 blocks + // if block_number % 5u32.into() == 0u32.into() { + // if let Err(e) = Self::print_metadata() { + // log::error!("IPFS: Encountered an error while obtaining metadata: {:?}", e); + // } + // } + } + } + + #[pallet::call] + impl Pallet { + + /// submits an on-chain request to fetch data and add it to iris + /// + /// * `addr`: the multiaddress where the data exists + /// example: /ip4/192.168.1.170/tcp/4001/p2p/12D3KooWMvyvKxYcy9mjbFbXcogFSCvENzQ62ogRxHKZaksFCkAp + /// * `cid`: the cid to fetch from the multiaddress + /// example: QmPZv7P8nQUSh2CpqTvUeYemFyjvMjgWEs8H1Tm8b3zAm9 + /// * `id`: (temp) the unique id of the asset class -> should be generated instead + /// * `balance`: the balance the owner is willing to use to back the asset class which will be created + /// + #[pallet::weight(0)] + pub fn create_storage_asset( + origin: OriginFor, + admin: ::Source, + addr: Vec, + cid: Vec, + name: Vec, + id: T::AssetId, + balance: T::Balance, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + let multiaddr = OpaqueMultiaddr(addr); + >::mutate( + |queue| queue.push(DataCommand::AddBytes( + multiaddr, + cid, + admin.clone(), + name.clone(), + id.clone(), + balance.clone(), + ))); + Self::deposit_event(Event::QueuedDataToAdd(who.clone())); + Ok(()) + } + + /// Queue a request to retrieve data behind some owned CID from the IPFS network + /// + /// * owner: The owner node + /// * cid: the cid to which you are requesting access + /// + #[pallet::weight(0)] + pub fn request_data( + origin: OriginFor, + owner: ::Source, + cid: Vec, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + let owner_account = T::Lookup::lookup(owner)?; + + >::mutate( + |queue| queue.push(DataCommand::CatBytes( + owner_account.clone(), + cid.clone(), + who.clone(), + ) + )); + + Self::deposit_event(Event::QueuedDataToCat(who.clone())); + + Ok(()) + } + + /// should only be called by offchain workers... how to ensure this? + /// submits IPFS results on chain and creates new ticket config in runtime storage + /// + /// * `admin`: The admin account + /// * `cid`: The cid generated by the OCW + /// * `id`: The AssetId (passed through from the create_storage_asset call) + /// * `balance`: The balance (passed through from the create_storage_asset call) + /// + #[pallet::weight(0)] + pub fn submit_ipfs_add_results( + origin: OriginFor, + admin: ::Source, + cid: Vec, + id: T::AssetId, + balance: T::Balance, + ) -> DispatchResult { + // DANGER: This can currently be called by anyone, not just an OCW. + // if we send an unsigned transaction then we can ensure there is no origin + // however, the call to create the asset requires an origin, which is a little problematic + // ensure_none(origin)?; + let who = ensure_signed(origin)?; + let new_origin = system::RawOrigin::Signed(who).into(); + + >::create(new_origin, id.clone(), admin.clone(), balance) + .map_err(|_| Error::::CantCreateAssetClass)?; + + let which_admin = T::Lookup::lookup(admin.clone())?; + >::insert(which_admin, cid.clone(), id.clone()); + + Self::deposit_event(Event::AssetClassCreated(id.clone())); + + Ok(()) + } + + // /// Should only be callable by OCWs (TODO) + // /// Submit the results of an `ipfs identity` call to be stored on chain + // /// + // /// * origin: a validator node + // /// * public_key: The IPFS node's public key + // /// * multiaddresses: A vector of multiaddresses associate with the public key + // /// + // #[pallet::weight(0)] + // pub fn submit_ipfs_identity( + // origin: OriginFor, + // public_key: Vec, + // multiaddresses: Vec, + // ) -> DispatchResult { + // let who = ensure_signed(origin)?; + // >::insert(public_key.clone(), multiaddresses.clone()); + // Self::deposit_event(Event::PublishedIdentity(who.clone())); + // Ok(()) + // } + + /// Should only be callable by OCWs (TODO) + /// Submit the results onchain to notify a beneficiary that their data is available: TODO: how to safely share host? spam protection on rpc endpoints? + /// + /// * `beneficiary`: The account that requested the data + /// * `host`: The node's host where the data has been made available (RPC endpoint) + /// + #[pallet::weight(0)] + pub fn submit_rpc_ready( + origin: OriginFor, + beneficiary: T::AccountId, + // host: Vec, + ) -> DispatchResult { + ensure_signed(origin)?; + Self::deposit_event(Event::DataReady(beneficiary)); + Ok(()) + } + + /// Only callable by the owner of the asset class + /// mint a static number of assets (tickets) for some asset class + /// + /// * origin: should be the owner of the asset class + /// * beneficiary: the address to which the newly minted assets are assigned + /// * cid: a cid owned by the origin, for which an asset class exists + /// * amount: the number of tickets to mint + /// + #[pallet::weight(0)] + pub fn mint_tickets( + origin: OriginFor, + beneficiary: ::Source, + cid: Vec, + #[pallet::compact] amount: T::Balance, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + let new_origin = system::RawOrigin::Signed(who.clone()).into(); + let beneficiary_accountid = T::Lookup::lookup(beneficiary.clone())?; + + ensure!(AssetClassOwnership::::contains_key(who.clone(), cid.clone()), Error::::NoSuchOwnedContent); + + let asset_id = AssetClassOwnership::::get(who.clone(), cid.clone(),); + >::mint(new_origin, asset_id.clone(), beneficiary.clone(), amount) + .map_err(|_| Error::::CantMintAssets)?; + + >::insert(beneficiary_accountid.clone(), cid.clone(), who.clone()); + + Self::deposit_event(Event::AssetCreated(asset_id.clone())); + Ok(()) + } + } +} + +impl Pallet { + // /// implementation for RPC runtime aPI to retrieve bytes from the node's local storage + // /// + // /// * public_key: The account's public key as bytes + // /// * signature: The signer's signature as bytes + // /// * message: The signed message as bytes + // /// + // pub fn retrieve_bytes( + // _public_key: Bytes, + // _signature: Bytes, + // message: Bytes, + // ) -> Bytes { + // // TODO: Verify signature, update offchain storage keys... + // let message_vec: Vec = message.to_vec(); + // if let Some(data) = sp_io::offchain::local_storage_get(StorageKind::PERSISTENT, &message_vec) { + // Bytes(data.clone()) + // } else { + // Bytes(Vec::new()) + // } + // } + + // /// send a request to the local IPFS node; can only be called be an off-chain worker + // fn ipfs_request( + // req: IpfsRequest, + // deadline: impl Into>, + // ) -> Result> { + // let ipfs_request = ipfs::PendingRequest::new(req).map_err(|_| Error::::CantCreateRequest)?; + // ipfs_request.try_wait(deadline) + // .map_err(|_| Error::::RequestTimeout)? + // .map(|r| r.response) + // .map_err(|e| { + // if let ipfs::Error::IoError(err) = e { + // log::error!("IPFS: request failed: {}", str::from_utf8(&err).unwrap()); + // } else { + // log::error!("IPFS: request failed: {:?}", e); + // } + // Error::::RequestFailed + // }) + // } + + // /// manage connection to the iris ipfs swarm + // /// + // /// If the node is already a bootstrap node, do nothing. Otherwise submits a signed tx + // /// containing the public key and multiaddresses of the embedded ipfs node. + // /// + // /// Returns an error if communication with the embedded IPFS fails + // fn connection_housekeeping() -> Result<(), Error> { + // let deadline = Some(timestamp().add(Duration::from_millis(5_000))); + + // let (public_key, addrs) = if let IpfsResponse::Identity(public_key, addrs) = Self::ipfs_request(IpfsRequest::Identity, deadline)? { + // (public_key, addrs) + // } else { + // unreachable!("only `Identity` is a valid response type."); + // }; + + // if !>::contains_key(public_key.clone()) { + // if let Some(bootstrap_node) = &>::iter().nth(0) { + // if let Some(bootnode_maddr) = bootstrap_node.1.clone().pop() { + // if let IpfsResponse::Success = Self::ipfs_request(IpfsRequest::Connect(bootnode_maddr.clone()), deadline)? { + // log::info!("Succesfully connected to a bootstrap node: {:?}", &bootnode_maddr.0); + // } else { + // log::info!("Failed to connect to the bootstrap node with multiaddress: {:?}", &bootnode_maddr.0); + // // TODO: this should probably be some recursive function? but we should never exceed a depth of 2 so maybe not + // if let Some(next_bootnode_maddr) = bootstrap_node.1.clone().pop() { + // if let IpfsResponse::Success = Self::ipfs_request(IpfsRequest::Connect(next_bootnode_maddr.clone()), deadline)? { + // log::info!("Succesfully connected to a bootstrap node: {:?}", &next_bootnode_maddr.0); + // } else { + // log::info!("Failed to connect to the bootstrap node with multiaddress: {:?}", &next_bootnode_maddr.0); + // } + // } + // } + // } + // } + // // TODO: should create func to encompass the below logic + // let signer = Signer::::all_accounts(); + // if !signer.can_sign() { + // log::error!( + // "No local accounts available. Consider adding one via `author_insertKey` RPC.", + // ); + // } + + // let results = signer.send_signed_transaction(|_account| { + // Call::submit_ipfs_identity{ + // public_key: public_key.clone(), + // multiaddresses: addrs.clone(), + // } + // }); + + // for (_, res) in &results { + // match res { + // Ok(()) => log::info!("Submitted ipfs identity results"), + // Err(e) => log::error!("Failed to submit transaction: {:?}", e), + // } + // } + + // } + // Ok(()) + // } + + // /// process any requests in the DataQueue + // fn handle_data_requests() -> Result<(), Error> { + // let data_queue = DataQueue::::get(); + // let len = data_queue.len(); + // if len != 0 { + // log::info!("IPFS: {} entr{} in the data queue", len, if len == 1 { "y" } else { "ies" }); + // } + // // TODO: Needs refactoring + // let deadline = Some(timestamp().add(Duration::from_millis(5_000))); + // for cmd in data_queue.into_iter() { + // match cmd { + // DataCommand::AddBytes(addr, cid, admin, _name, id, balance) => { + // Self::ipfs_request(IpfsRequest::Connect(addr.clone()), deadline)?; + // log::info!( + // "IPFS: connected to {}", + // str::from_utf8(&addr.0).expect("our own calls can be trusted to be UTF-8; qed") + // ); + // match Self::ipfs_request(IpfsRequest::CatBytes(cid.clone()), deadline) { + // Ok(IpfsResponse::CatBytes(data)) => { + // log::info!("IPFS: fetched data"); + // Self::ipfs_request(IpfsRequest::Disconnect(addr.clone()), deadline)?; + // log::info!( + // "IPFS: disconnected from {}", + // str::from_utf8(&addr.0).expect("our own calls can be trusted to be UTF-8; qed") + // ); + // match Self::ipfs_request(IpfsRequest::AddBytes(data.clone()), deadline) { + // Ok(IpfsResponse::AddBytes(new_cid)) => { + // log::info!( + // "IPFS: added data with Cid {}", + // str::from_utf8(&new_cid).expect("our own IPFS node can be trusted here; qed") + // ); + // let signer = Signer::::all_accounts(); + // if !signer.can_sign() { + // log::error!( + // "No local accounts available. Consider adding one via `author_insertKey` RPC.", + // ); + // } + // let results = signer.send_signed_transaction(|_account| { + // Call::submit_ipfs_add_results{ + // admin: admin.clone(), + // cid: new_cid.clone(), + // id: id.clone(), + // balance: balance.clone(), + // } + // }); + + // for (_, res) in &results { + // match res { + // Ok(()) => log::info!("Submitted ipfs results"), + // Err(e) => log::error!("Failed to submit transaction: {:?}", e), + // } + // } + // }, + // Ok(_) => unreachable!("only AddBytes can be a response for that request type."), + // Err(e) => log::error!("IPFS: add error: {:?}", e), + // } + // }, + // Ok(_) => unreachable!("only CatBytes can be a response for that request type."), + // Err(e) => log::error!("IPFS: cat error: {:?}", e), + // } + // }, + // DataCommand::CatBytes(owner, cid, recipient) => { + // ensure!(AssetClassOwnership::::contains_key(owner.clone(), cid.clone()), Error::::NoSuchOwnedContent); + // let asset_id = AssetClassOwnership::::get(owner.clone(), cid.clone()); + // let balance = >::balance(asset_id.clone(), recipient.clone()); + // let balance_primitive = TryInto::::try_into(balance).ok(); + // ensure!(balance_primitive != Some(0), Error::::InsufficientBalance); + // match Self::ipfs_request(IpfsRequest::CatBytes(cid.clone()), deadline) { + // Ok(IpfsResponse::CatBytes(data)) => { + // log::info!("IPFS: Fetched data from IPFS."); + // // add to offchain index + // sp_io::offchain::local_storage_set( + // StorageKind::PERSISTENT, + // &cid, + // &data, + // ); + // let signer = Signer::::all_accounts(); + // if !signer.can_sign() { + // log::error!( + // "No local accounts available. Consider adding one via `author_insertKey` RPC.", + // ); + // } + // let results = signer.send_signed_transaction(|_account| { + // Call::submit_rpc_ready { + // beneficiary: recipient.clone(), + // } + // }); + + // for (_, res) in &results { + // match res { + // Ok(()) => log::info!("Submitted ipfs results"), + // Err(e) => log::error!("Failed to submit transaction: {:?}", e), + // } + // } + // }, + // Ok(_) => unreachable!("only CatBytes can be a response for that request type."), + // Err(e) => log::error!("IPFS: cat error: {:?}", e), + // } + // } + // } + // } + + // Ok(()) + // } + + // fn print_metadata() -> Result<(), Error> { + // let deadline = Some(timestamp().add(Duration::from_millis(5_000))); + + // let peers = if let IpfsResponse::Peers(peers) = Self::ipfs_request(IpfsRequest::Peers, deadline)? { + // peers + // } else { + // unreachable!("only Peers can be a response for that request type; qed"); + // }; + // let peer_count = peers.len(); + + // log::info!( + // "IPFS: currently connected to {} peer{}", + // peer_count, + // if peer_count == 1 { "" } else { "s" }, + // ); + // Ok(()) + // } +} \ No newline at end of file diff --git a/bin/node-template/pallets/iris-asset/src/mock.rs b/bin/node-template/pallets/iris-assets/src/mock.rs similarity index 100% rename from bin/node-template/pallets/iris-asset/src/mock.rs rename to bin/node-template/pallets/iris-assets/src/mock.rs diff --git a/bin/node-template/pallets/iris-asset/src/tests.rs b/bin/node-template/pallets/iris-assets/src/tests.rs similarity index 100% rename from bin/node-template/pallets/iris-asset/src/tests.rs rename to bin/node-template/pallets/iris-assets/src/tests.rs diff --git a/bin/node-template/pallets/iris-session/Cargo.toml b/bin/node-template/pallets/iris-session/Cargo.toml index 9d04bb8d8679..476897b13fb3 100644 --- a/bin/node-template/pallets/iris-session/Cargo.toml +++ b/bin/node-template/pallets/iris-session/Cargo.toml @@ -31,9 +31,10 @@ frame-system = { default-features = false, version = "4.0.0-dev", path = "../../ frame-benchmarking = { default-features = false, version = "4.0.0-dev", path = "../../../../frame/benchmarking", optional = true } log = { version = "0.4.14", default-features = false } -pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../../../../frame/balances" } +# pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../../../../frame/balances" } pallet-assets = { version = "4.0.0-dev", default-features = false, path = "../../../../frame/assets" } pallet-session = { version = "4.0.0-dev", default-features = false, features = ["historical"], path = "../../../../frame/session" } +pallet-iris-assets = { version = "3.0.0", default-features = false, path = "../iris-assets" } [features] default = ['std'] @@ -49,9 +50,9 @@ std = [ 'sp-runtime/std', 'sp-staking/std', 'log/std', - 'pallet-assets/std', - 'pallet-balances/std', 'pallet-session/std', + 'pallet-assets/std', + 'pallet-iris-assets/std', ] runtime-benchmarks = ["frame-benchmarking"] diff --git a/bin/node-template/pallets/iris-session/src/lib.rs b/bin/node-template/pallets/iris-session/src/lib.rs index 5dee754a2e5f..39d8add80299 100644 --- a/bin/node-template/pallets/iris-session/src/lib.rs +++ b/bin/node-template/pallets/iris-session/src/lib.rs @@ -25,7 +25,31 @@ use log; pub use pallet::*; use sp_runtime::traits::{Convert, Zero}; use sp_staking::offence::{Offence, OffenceError, ReportOffence}; -use sp_std::{collections::btree_set::BTreeSet, prelude::*}; +use sp_std::{ + collections::btree_set::BTreeSet, + convert::TryInto, + str, + vec::Vec, + prelude::* +}; +use sp_core::{ + offchain::{ + Duration, IpfsRequest, IpfsResponse, OpaqueMultiaddr, Timestamp, StorageKind, + }, + Bytes, +}; +use frame_system::{ + self as system, ensure_signed, + offchain::{ + SendSignedTransaction, + Signer, + } +}; +use sp_io::offchain::timestamp; +use sp_runtime::offchain::ipfs; +use pallet_iris_assets::{ + DataCommand, +}; pub const LOG_TARGET: &'static str = "runtime::iris-session"; @@ -37,7 +61,7 @@ pub mod pallet { /// Configure the pallet by specifying the parameters and types on which it /// depends. #[pallet::config] - pub trait Config: frame_system::Config + pallet_session::Config { + pub trait Config: frame_system::Config + pallet_session::Config + pallet_iris_assets::Config { /// The Event type. type Event: From> + IsType<::Event>; @@ -53,6 +77,18 @@ pub mod pallet { #[pallet::generate_store(pub(super) trait Store)] pub struct Pallet(_); + /// map the ipfs public key to a list of multiaddresses + /// this could be moved to the session pallet + #[pallet::storage] + #[pallet::getter(fn bootstrap_nodes)] + pub(super) type BootstrapNodes = StorageMap< + _, + Blake2_128Concat, + Vec, + Vec, + ValueQuery, + >; + #[pallet::storage] #[pallet::getter(fn validators)] pub type Validators = StorageValue<_, Vec, ValueQuery>; @@ -70,9 +106,10 @@ pub mod pallet { pub enum Event { /// New validator addition initiated. Effective in ~2 sessions. ValidatorAdditionInitiated(T::AccountId), - /// Validator removal initiated. Effective in ~2 sessions. ValidatorRemovalInitiated(T::AccountId), + /// Validator published their ipfs public key and maddrs + PublishedIdentity(T::AccountId), } // Errors inform users that something went wrong. @@ -86,10 +123,36 @@ pub mod pallet { ValidatorNotApproved, /// Only the validator can add itself back after coming online. BadOrigin, + /// could not build the ipfs request + CantCreateRequest, + /// the request to IPFS timed out + RequestTimeout, + /// the request to IPFS failed + RequestFailed, } #[pallet::hooks] - impl Hooks> for Pallet {} + impl Hooks> for Pallet { + fn offchain_worker(block_number: T::BlockNumber) { + // every 5 blocks + if block_number % 5u32.into() == 0u32.into() { + if let Err(e) = Self::connection_housekeeping() { + log::error!("IPFS: Encountered an error while processing data requests: {:?}", e); + } + } + // handle data requests each block + if let Err(e) = Self::handle_data_requests() { + log::error!("IPFS: Encountered an error while processing data requests: {:?}", e); + } + + // every 5 blocks + if block_number % 5u32.into() == 0u32.into() { + if let Err(e) = Self::print_metadata() { + log::error!("IPFS: Encountered an error while obtaining metadata: {:?}", e); + } + } + } + } #[pallet::genesis_config] pub struct GenesisConfig { @@ -126,7 +189,7 @@ pub mod pallet { Self::do_add_validator(validator_id.clone())?; Self::approve_validator(validator_id)?; - + Ok(()) } @@ -166,15 +229,24 @@ pub mod pallet { Ok(()) } - /// Add a storage provider to a storage pool - /// new storage providers must already be approved validators - #[pallet::weight(0)] - pub fn join_storage_pool( - origin: OriginFor, - sp_id: T::AssetId, - ) -> DispatchResult { - Ok(()) - } + /// Should only be callable by OCWs (TODO) + /// Submit the results of an `ipfs identity` call to be stored on chain + /// + /// * origin: a validator node + /// * public_key: The IPFS node's public key + /// * multiaddresses: A vector of multiaddresses associate with the public key + /// + #[pallet::weight(0)] + pub fn submit_ipfs_identity( + origin: OriginFor, + public_key: Vec, + multiaddresses: Vec, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + BootstrapNodes::::insert(public_key.clone(), multiaddresses.clone()); + Self::deposit_event(Event::PublishedIdentity(who.clone())); + Ok(()) + } } } @@ -192,7 +264,7 @@ impl Pallet { >::mutate(|v| v.push(validator_id.clone())); Self::deposit_event(Event::ValidatorAdditionInitiated(validator_id.clone())); - log::debug!(target: LOG_TARGET, "Validator addition initiated."); + log::debug!(target: LOG_TARGET, "Validator addition initiated."); Ok(()) } @@ -259,6 +331,236 @@ impl Pallet { // Clear the offline validator list to avoid repeated deletion. >::put(Vec::::new()); } + + /// implementation for RPC runtime aPI to retrieve bytes from the node's local storage + /// + /// * public_key: The account's public key as bytes + /// * signature: The signer's signature as bytes + /// * message: The signed message as bytes + /// + pub fn retrieve_bytes( + _public_key: Bytes, + _signature: Bytes, + message: Bytes, + ) -> Bytes { + // TODO: Verify signature, update offchain storage keys... + let message_vec: Vec = message.to_vec(); + if let Some(data) = sp_io::offchain::local_storage_get(StorageKind::PERSISTENT, &message_vec) { + Bytes(data.clone()) + } else { + Bytes(Vec::new()) + } + } + + /// send a request to the local IPFS node; can only be called be an off-chain worker + fn ipfs_request( + req: IpfsRequest, + deadline: impl Into>, + ) -> Result> { + let ipfs_request = ipfs::PendingRequest::new(req) + .map_err(|_| Error::::CantCreateRequest)?; + ipfs_request.try_wait(deadline) + .map_err(|_| Error::::RequestTimeout)? + .map(|r| r.response) + .map_err(|e| { + if let ipfs::Error::IoError(err) = e { + log::error!("IPFS: request failed: {}", str::from_utf8(&err).unwrap()); + } else { + log::error!("IPFS: request failed: {:?}", e); + } + Error::::RequestFailed + }) + } + + /// manage connection to the iris ipfs swarm + /// + /// If the node is already a bootstrap node, do nothing. Otherwise submits a signed tx + /// containing the public key and multiaddresses of the embedded ipfs node. + /// + /// Returns an error if communication with the embedded IPFS fails + fn connection_housekeeping() -> Result<(), Error> { + let deadline = Some(timestamp().add(Duration::from_millis(5_000))); + + let (public_key, addrs) = if let IpfsResponse::Identity(public_key, addrs) = Self::ipfs_request(IpfsRequest::Identity, deadline)? { + (public_key, addrs) + } else { + unreachable!("only `Identity` is a valid response type."); + }; + + if !BootstrapNodes::::contains_key(public_key.clone()) { + if let Some(bootstrap_node) = &BootstrapNodes::::iter().nth(0) { + if let Some(bootnode_maddr) = bootstrap_node.1.clone().pop() { + if let IpfsResponse::Success = Self::ipfs_request(IpfsRequest::Connect(bootnode_maddr.clone()), deadline)? { + log::info!("Succesfully connected to a bootstrap node: {:?}", &bootnode_maddr.0); + } else { + log::info!("Failed to connect to the bootstrap node with multiaddress: {:?}", &bootnode_maddr.0); + // TODO: this should probably be some recursive function? but we should never exceed a depth of 2 so maybe not + if let Some(next_bootnode_maddr) = bootstrap_node.1.clone().pop() { + if let IpfsResponse::Success = Self::ipfs_request(IpfsRequest::Connect(next_bootnode_maddr.clone()), deadline)? { + log::info!("Succesfully connected to a bootstrap node: {:?}", &next_bootnode_maddr.0); + } else { + log::info!("Failed to connect to the bootstrap node with multiaddress: {:?}", &next_bootnode_maddr.0); + } + } + } + } + } + let signer = Signer::::all_accounts(); + if !signer.can_sign() { + log::error!( + "No local accounts available. Consider adding one via `author_insertKey` RPC.", + ); + } + + let results = signer.send_signed_transaction(|_account| { + Call::submit_ipfs_identity{ + public_key: public_key.clone(), + multiaddresses: addrs.clone(), + } + }); + + for (_, res) in &results { + match res { + Ok(()) => log::info!("Submitted ipfs identity results"), + Err(e) => log::error!("Failed to submit transaction: {:?}", e), + } + } + + } + Ok(()) + } + + /// process any requests in the DataQueue + fn handle_data_requests() -> Result<(), Error> { + let data_queue = >::DataQueue::::get(); + let len = data_queue.len(); + if len != 0 { + log::info!("IPFS: {} entr{} in the data queue", len, if len == 1 { "y" } else { "ies" }); + } + // TODO: Needs refactoring + let deadline = Some(timestamp().add(Duration::from_millis(5_000))); + for cmd in data_queue.into_iter() { + match cmd { + DataCommand::AddBytes(addr, cid, admin, _name, id, balance) => { + Self::ipfs_request(IpfsRequest::Connect(addr.clone()), deadline)?; + log::info!( + "IPFS: connected to {}", + str::from_utf8(&addr.0).expect("our own calls can be trusted to be UTF-8; qed") + ); + match Self::ipfs_request(IpfsRequest::CatBytes(cid.clone()), deadline) { + Ok(IpfsResponse::CatBytes(data)) => { + log::info!("IPFS: fetched data"); + Self::ipfs_request(IpfsRequest::Disconnect(addr.clone()), deadline)?; + log::info!( + "IPFS: disconnected from {}", + str::from_utf8(&addr.0).expect("our own calls can be trusted to be UTF-8; qed") + ); + match Self::ipfs_request(IpfsRequest::AddBytes(data.clone()), deadline) { + Ok(IpfsResponse::AddBytes(new_cid)) => { + log::info!( + "IPFS: added data with Cid {}", + str::from_utf8(&new_cid).expect("our own IPFS node can be trusted here; qed") + ); + let signer = Signer::::all_accounts(); + if !signer.can_sign() { + log::error!( + "No local accounts available. Consider adding one via `author_insertKey` RPC.", + ); + } + let results = signer.send_signed_transaction(|_account| { + Call::submit_ipfs_add_results{ + admin: admin.clone(), + cid: new_cid.clone(), + id: id.clone(), + balance: balance.clone(), + } + }); + + for (_, res) in &results { + match res { + Ok(()) => log::info!("Submitted ipfs results"), + Err(e) => log::error!("Failed to submit transaction: {:?}", e), + } + } + }, + Ok(_) => unreachable!("only AddBytes can be a response for that request type."), + Err(e) => log::error!("IPFS: add error: {:?}", e), + } + }, + Ok(_) => unreachable!("only CatBytes can be a response for that request type."), + Err(e) => log::error!("IPFS: cat error: {:?}", e), + } + }, + DataCommand::CatBytes(owner, cid, recipient) => { + ensure!( + >::AssetClassOwnership::::contains_key( + owner.clone(), cid.clone() + ), + >::Error::::NoSuchOwnedContent + ); + + let asset_id = >::AssetClassOwnership::::get(owner.clone(), cid.clone()); + // TODO: Don't want to also depend on the assets pallet here, need to fold this into the iris-assets runtime + let balance = >::balance(asset_id.clone(), recipient.clone()); + let balance_primitive = TryInto::::try_into(balance).ok(); + + ensure!(balance_primitive != Some(0), >::Error::::InsufficientBalance); + match Self::ipfs_request(IpfsRequest::CatBytes(cid.clone()), deadline) { + Ok(IpfsResponse::CatBytes(data)) => { + log::info!("IPFS: Fetched data from IPFS."); + // add to offchain index + sp_io::offchain::local_storage_set( + StorageKind::PERSISTENT, + &cid, + &data, + ); + let signer = Signer::::all_accounts(); + if !signer.can_sign() { + log::error!( + "No local accounts available. Consider adding one via `author_insertKey` RPC.", + ); + } + let results = signer.send_signed_transaction(|_account| { + pallet_iris_assets::Call::submit_rpc_ready { + beneficiary: recipient.clone(), + } + }); + + for (_, res) in &results { + match res { + Ok(()) => log::info!("Submitted ipfs results"), + Err(e) => log::error!("Failed to submit transaction: {:?}", e), + } + } + }, + Ok(_) => unreachable!("only CatBytes can be a response for that request type."), + Err(e) => log::error!("IPFS: cat error: {:?}", e), + } + } + } + } + + Ok(()) + } + + fn print_metadata() -> Result<(), Error> { + let deadline = Some(timestamp().add(Duration::from_millis(5_000))); + + let peers = if let IpfsResponse::Peers(peers) = Self::ipfs_request(IpfsRequest::Peers, deadline)? { + peers + } else { + unreachable!("only Peers can be a response for that request type; qed"); + }; + let peer_count = peers.len(); + + log::info!( + "IPFS: currently connected to {} peer{}", + peer_count, + if peer_count == 1 { "" } else { "s" }, + ); + Ok(()) + } + } // Provides the new set of validators to the session module when session is diff --git a/bin/node-template/runtime/Cargo.toml b/bin/node-template/runtime/Cargo.toml index 422fef3afb24..f4144271eae5 100644 --- a/bin/node-template/runtime/Cargo.toml +++ b/bin/node-template/runtime/Cargo.toml @@ -23,7 +23,7 @@ pallet-randomness-collective-flip = { version = "4.0.0-dev", default-features = pallet-sudo = { version = "4.0.0-dev", default-features = false, path = "../../../frame/sudo" } pallet-assets = { version = "4.0.0-dev", default-features = false, path = "../../../frame/assets" } pallet-session = { version = "4.0.0-dev", default-features = false, features = ["historical"], path = "../../../frame/session" } -pallet-iris-asset = { version = "3.0.0", default-features = false, path = "../pallets/iris-asset" } +pallet-iris-assets = { version = "3.0.0", default-features = false, path = "../pallets/iris-assets" } pallet-iris-session = { version = "3.0.0", default-features = false, path = "../pallets/iris-session" } @@ -46,8 +46,7 @@ sp-version = { version = "4.0.0-dev", default-features = false, path = "../../.. # Used for the node template's RPCs frame-system-rpc-runtime-api = { version = "4.0.0-dev", default-features = false, path = "../../../frame/system/rpc/runtime-api/" } pallet-transaction-payment-rpc-runtime-api = { version = "4.0.0-dev", default-features = false, path = "../../../frame/transaction-payment/rpc/runtime-api/" } -pallet-iris-rpc-runtime-api = { version = "4.0.0-dev", default-features = false, path = "../pallets/template/rpc/runtime-api/" } - +pallet-iris-rpc-runtime-api = { version = "4.0.0-dev", default-features = false, path = "../pallets/iris-assets/rpc/runtime-api/" } # Used for runtime benchmarking frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../../../frame/benchmarking", optional = true } frame-system-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../../../frame/system/benchmarking", optional = true } @@ -72,7 +71,7 @@ std = [ "pallet-grandpa/std", "pallet-randomness-collective-flip/std", "pallet-sudo/std", - "pallet-iris-asset/std", + "pallet-iris-assets/std", "pallet-timestamp/std", "pallet-transaction-payment-rpc-runtime-api/std", "pallet-iris-rpc-runtime-api/std", @@ -99,7 +98,7 @@ runtime-benchmarks = [ "frame-system/runtime-benchmarks", "hex-literal", "pallet-balances/runtime-benchmarks", - "pallet-iris-asset/runtime-benchmarks", + "pallet-iris-assets/runtime-benchmarks", "pallet-iris-session/std", "pallet-timestamp/runtime-benchmarks", "pallet-assets/runtime-benchmarks", diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index b811beb4023a..9d4b2468017d 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -55,7 +55,7 @@ pub use sp_runtime::{Perbill, Permill}; /// Import the template pallet. -pub use pallet_iris_asset; +pub use pallet_iris_assets; pub use pallet_iris_session; /// An index to a block. @@ -223,6 +223,7 @@ impl pallet_iris_session::Config for Runtime { type Event = Event; type AddRemoveOrigin = EnsureRoot; type MinAuthorities = MinAuthorities; + type AuthorityId = pallet_iris_assets::crypto::TestAuthId; } parameter_types! { @@ -348,11 +349,11 @@ impl pallet_assets::Config for Runtime { /// inside `create_transaction` function. pub type SignedPayload = generic::SignedPayload; -/// Configure the pallet-template in pallets/template. -impl pallet_iris_asset::Config for Runtime { +/// configure the iris assets pallet +impl pallet_iris_assets::Config for Runtime { type Event = Event; type Call = Call; - type AuthorityId = pallet_iris_asset::crypto::TestAuthId; + type AuthorityId = pallet_iris_assets::crypto::TestAuthId; type Currency = Balances; } @@ -426,7 +427,7 @@ construct_runtime!( Sudo: pallet_sudo::{Pallet, Call, Config, Storage, Event}, // Include the custom logic from the pallet-template in the runtime. IrisSession: pallet_iris_session::{Pallet, Call, Storage, Event, Config}, - Iris: pallet_iris_asset::{Pallet, Call, Storage, Event}, + Iris: pallet_iris_assets::{Pallet, Call, Storage, Event}, Session: pallet_session::{Pallet, Call, Storage, Event, Config}, Assets: pallet_assets::{Pallet, Storage, Event}, // removed call to make extrinsics uncallable @@ -658,7 +659,7 @@ impl_runtime_apis! { add_benchmark!(params, batches, frame_system, SystemBench::); add_benchmark!(params, batches, pallet_balances, Balances); add_benchmark!(params, batches, pallet_timestamp, Timestamp); - add_benchmark!(params, batches, pallet_iris_asset, Iris); + add_benchmark!(params, batches, pallet_iris_assets, Iris); if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } Ok(batches) diff --git a/bin/node/rpc/Cargo.toml b/bin/node/rpc/Cargo.toml index 23cdb56e076f..06c0cee87886 100644 --- a/bin/node/rpc/Cargo.toml +++ b/bin/node/rpc/Cargo.toml @@ -16,7 +16,7 @@ node-primitives = { version = "2.0.0", path = "../primitives" } pallet-contracts-rpc = { version = "4.0.0-dev", path = "../../../frame/contracts/rpc/" } pallet-mmr-rpc = { version = "3.0.0", path = "../../../frame/merkle-mountain-range/rpc/" } pallet-transaction-payment-rpc = { version = "4.0.0-dev", path = "../../../frame/transaction-payment/rpc/" } -pallet-iris-rpc = { version = "4.0.0-dev", path = "../../node-template/pallets/template/rpc/" } +pallet-iris-rpc = { version = "4.0.0-dev", path = "../../node-template/pallets/iris-assets/rpc/" } sc-client-api = { version = "4.0.0-dev", path = "../../../client/api" } sc-consensus-babe = { version = "0.10.0-dev", path = "../../../client/consensus/babe" } sc-consensus-babe-rpc = { version = "0.10.0-dev", path = "../../../client/consensus/babe/rpc" } From 3168e10f6576a28930554bbf903ff9900b833a14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Sat, 15 Jan 2022 11:46:20 +0100 Subject: [PATCH 384/695] runtime-interface: Implement `register_only` functions (#10640) * runtime-interface: Implement `register_only` functions The runtime interface supports versioning of functions. Currently, if you add a new function it will be used by the runtime automatically. This results in requiring all nodes of a network to upgrade before the runtime is upgraded, otherwise they will fail to instantiate the new runtime because of missing host functions. This pr introduces `register_only` functions. This can be used when a new runtime interface function should be introduced, but the actual usage can be deferred. This means that nodes will have the host function for this, but the runtime will still use the old version of the function when being compiled for wasm. However, when a runtime is enacted that uses the new host function, the "old nodes" will already have the host function and will continue to work. * Update primitives/runtime-interface/src/lib.rs Co-authored-by: cheme * Update primitives/runtime-interface/proc-macro/src/utils.rs Co-authored-by: cheme * FMT Co-authored-by: cheme --- .../bare_function_interface.rs | 2 +- .../host_function_interface.rs | 17 +- .../runtime-interface/proc-macro/src/utils.rs | 157 +++++++++++------- primitives/runtime-interface/src/lib.rs | 26 ++- .../runtime-interface/test-wasm/src/lib.rs | 16 ++ primitives/runtime-interface/test/src/lib.rs | 5 + 6 files changed, 155 insertions(+), 68 deletions(-) diff --git a/primitives/runtime-interface/proc-macro/src/runtime_interface/bare_function_interface.rs b/primitives/runtime-interface/proc-macro/src/runtime_interface/bare_function_interface.rs index cbb749a111a1..a06a1f9bda73 100644 --- a/primitives/runtime-interface/proc-macro/src/runtime_interface/bare_function_interface.rs +++ b/primitives/runtime-interface/proc-macro/src/runtime_interface/bare_function_interface.rs @@ -52,7 +52,7 @@ pub fn generate(trait_def: &ItemTrait, is_wasm_only: bool, tracing: bool) -> Res let runtime_interface = get_runtime_interface(trait_def)?; // latest version dispatch - let token_stream: Result = runtime_interface.latest_versions().try_fold( + let token_stream: Result = runtime_interface.latest_versions_to_call().try_fold( TokenStream::new(), |mut t, (latest_version, method)| { t.extend(function_for_method(method, latest_version, is_wasm_only)?); diff --git a/primitives/runtime-interface/proc-macro/src/runtime_interface/host_function_interface.rs b/primitives/runtime-interface/proc-macro/src/runtime_interface/host_function_interface.rs index 2416e6951fe2..626e309cc0e1 100644 --- a/primitives/runtime-interface/proc-macro/src/runtime_interface/host_function_interface.rs +++ b/primitives/runtime-interface/proc-macro/src/runtime_interface/host_function_interface.rs @@ -45,19 +45,18 @@ use std::iter::Iterator; /// implementations for the host functions on the host. pub fn generate(trait_def: &ItemTrait, is_wasm_only: bool) -> Result { let trait_name = &trait_def.ident; - let extern_host_function_impls = get_runtime_interface(trait_def)?.latest_versions().try_fold( - TokenStream::new(), - |mut t, (version, method)| { + let extern_host_function_impls = get_runtime_interface(trait_def)? + .latest_versions_to_call() + .try_fold(TokenStream::new(), |mut t, (version, method)| { t.extend(generate_extern_host_function(method, version, trait_name)?); Ok::<_, Error>(t) - }, - )?; + })?; let exchangeable_host_functions = get_runtime_interface(trait_def)? - .latest_versions() + .latest_versions_to_call() .try_fold(TokenStream::new(), |mut t, (_, m)| { - t.extend(generate_exchangeable_host_function(m)?); - Ok::<_, Error>(t) - })?; + t.extend(generate_exchangeable_host_function(m)?); + Ok::<_, Error>(t) + })?; let host_functions_struct = generate_host_functions_struct(trait_def, is_wasm_only)?; Ok(quote! { diff --git a/primitives/runtime-interface/proc-macro/src/utils.rs b/primitives/runtime-interface/proc-macro/src/utils.rs index 593f8ecafa7a..bc690eb21a9b 100644 --- a/primitives/runtime-interface/proc-macro/src/utils.rs +++ b/primitives/runtime-interface/proc-macro/src/utils.rs @@ -20,8 +20,8 @@ use proc_macro2::{Span, TokenStream}; use syn::{ - parse_quote, spanned::Spanned, token, Attribute, Error, FnArg, Ident, ItemTrait, Lit, Meta, - NestedMeta, Pat, PatType, Result, Signature, TraitItem, TraitItemMethod, Type, + parse::Parse, parse_quote, spanned::Spanned, token, Error, FnArg, Ident, ItemTrait, LitInt, + Pat, PatType, Result, Signature, TraitItem, TraitItemMethod, Type, }; use proc_macro_crate::{crate_name, FoundCrate}; @@ -35,31 +35,65 @@ use quote::quote; use inflector::Inflector; +mod attributes { + syn::custom_keyword!(register_only); +} + /// Runtime interface function with all associated versions of this function. pub struct RuntimeInterfaceFunction<'a> { - latest_version: u32, + latest_version_to_call: Option, versions: BTreeMap, } impl<'a> RuntimeInterfaceFunction<'a> { - fn new(version: u32, trait_item: &'a TraitItemMethod) -> Self { + fn new(version: VersionAttribute, trait_item: &'a TraitItemMethod) -> Self { Self { - latest_version: version, - versions: { - let mut res = BTreeMap::new(); - res.insert(version, trait_item); - res - }, + latest_version_to_call: version.is_callable().then(|| version.version), + versions: BTreeMap::from([(version.version, trait_item)]), } } - pub fn latest_version(&self) -> (u32, &TraitItemMethod) { - ( - self.latest_version, - self.versions.get(&self.latest_version).expect( - "If latest_version has a value, the key with this value is in the versions; qed", + /// Returns the latest version of this runtime interface function plus the actual function + /// implementation. + /// + /// This isn't required to be the latest version, because a runtime interface function can be + /// annotated with `register_only` to ensure that the host exposes the host function but it + /// isn't used when compiling the runtime. + pub fn latest_version_to_call(&self) -> Option<(u32, &TraitItemMethod)> { + self.latest_version_to_call.map(|v| { + ( + v, + *self.versions.get(&v).expect( + "If latest_version_to_call has a value, the key with this value is in the versions; qed", ), ) + }) + } + + /// Add a different version of the function. + fn add_version( + &mut self, + version: VersionAttribute, + trait_item: &'a TraitItemMethod, + ) -> Result<()> { + if let Some(existing_item) = self.versions.get(&version.version) { + let mut err = Error::new(trait_item.span(), "Duplicated version attribute"); + err.combine(Error::new( + existing_item.span(), + "Previous version with the same number defined here", + )); + + return Err(err) + } + + self.versions.insert(version.version, trait_item); + if self.latest_version_to_call.map_or(true, |v| v < version.version) && + version.is_callable() + { + self.latest_version_to_call = Some(version.version); + } + + Ok(()) } } @@ -69,8 +103,10 @@ pub struct RuntimeInterface<'a> { } impl<'a> RuntimeInterface<'a> { - pub fn latest_versions(&self) -> impl Iterator { - self.items.iter().map(|(_, item)| item.latest_version()) + /// Returns an iterator over all runtime interface function + /// [`latest_version_to_call`](RuntimeInterfaceFunction::latest_version). + pub fn latest_versions_to_call(&self) -> impl Iterator { + self.items.iter().filter_map(|(_, item)| item.latest_version_to_call()) } pub fn all_versions(&self) -> impl Iterator { @@ -199,36 +235,55 @@ fn get_trait_methods<'a>(trait_def: &'a ItemTrait) -> impl Iterator Result { - let meta = version.parse_meta()?; - - let err = Err(Error::new( - meta.span(), - "Unexpected `version` attribute. The supported format is `#[version(1)]`", - )); - - match meta { - Meta::List(list) => - if list.nested.len() != 1 { - err - } else if let Some(NestedMeta::Lit(Lit::Int(i))) = list.nested.first() { - i.base10_parse() - } else { - err - }, - _ => err, +/// Supports the following formats: +/// - `#[version(1)]` +/// - `#[version(1, register_only)]` +/// +/// While this struct is only for parsing the inner parts inside the `()`. +struct VersionAttribute { + version: u32, + register_only: Option, +} + +impl VersionAttribute { + /// Is this function version callable? + fn is_callable(&self) -> bool { + self.register_only.is_none() + } +} + +impl Default for VersionAttribute { + fn default() -> Self { + Self { version: 1, register_only: None } + } +} + +impl Parse for VersionAttribute { + fn parse(input: syn::parse::ParseStream) -> Result { + let version: LitInt = input.parse()?; + let register_only = if input.peek(token::Comma) { + let _ = input.parse::(); + Some(input.parse()?) + } else { + if !input.is_empty() { + return Err(Error::new(input.span(), "Unexpected token, expected `,`.")) + } + + None + }; + + Ok(Self { version: version.base10_parse()?, register_only }) } } -/// Return item version (`#[version(X)]`) attribute, if present. -fn get_item_version(item: &TraitItemMethod) -> Result> { +/// Return [`VersionAttribute`], if present. +fn get_item_version(item: &TraitItemMethod) -> Result> { item.attrs .iter() .find(|attr| attr.path.is_ident("version")) - .map(|attr| parse_version_attribute(attr)) + .map(|attr| attr.parse_args()) .transpose() } @@ -238,28 +293,18 @@ pub fn get_runtime_interface<'a>(trait_def: &'a ItemTrait) -> Result { entry.insert(RuntimeInterfaceFunction::new(version, item)); }, Entry::Occupied(mut entry) => { - if let Some(existing_item) = entry.get().versions.get(&version) { - let mut err = Error::new(item.span(), "Duplicated version attribute"); - err.combine(Error::new( - existing_item.span(), - "Previous version with the same number defined here", - )); - - return Err(err) - } - - let interface_item = entry.get_mut(); - if interface_item.latest_version < version { - interface_item.latest_version = version; - } - interface_item.versions.insert(version, item); + entry.get_mut().add_version(version, item)?; }, } } diff --git a/primitives/runtime-interface/src/lib.rs b/primitives/runtime-interface/src/lib.rs index d87b0d57a772..f9bf8825f948 100644 --- a/primitives/runtime-interface/src/lib.rs +++ b/primitives/runtime-interface/src/lib.rs @@ -153,6 +153,22 @@ pub use sp_std; /// [17].to_vec() /// } /// +/// /// Call function, different version and only being registered. +/// /// +/// /// This `register_only` version is only being registered, aka exposed to the runtime, +/// /// but the runtime will still use the version 2 of this function. This is useful for when +/// /// new host functions should be introduced. Adding new host functions requires that all +/// /// nodes have the host functions available, because otherwise they fail at instantiation +/// /// of the runtime. With `register_only` the function will not be used when compiling the +/// /// runtime, but it will already be there for a future version of the runtime that will +/// /// switch to using these host function. +/// #[version(3, register_only)] +/// fn call(data: &[u8]) -> Vec { +/// // Here you could call some rather complex code that only compiles on native or +/// // is way faster in native than executing it in wasm. +/// [18].to_vec() +/// } +/// /// /// A function can take a `&self` or `&mut self` argument to get access to the /// /// `Externalities`. (The generated method does not require /// /// this argument, so the function can be called just with the `optional` argument) @@ -177,12 +193,14 @@ pub use sp_std; /// trait Interface { /// fn call_version_1(data: &[u8]) -> Vec; /// fn call_version_2(data: &[u8]) -> Vec; +/// fn call_version_3(data: &[u8]) -> Vec; /// fn set_or_clear_version_1(&mut self, optional: Option>); /// } /// /// impl Interface for &mut dyn sp_externalities::Externalities { /// fn call_version_1(data: &[u8]) -> Vec { Vec::new() } /// fn call_version_2(data: &[u8]) -> Vec { [17].to_vec() } +/// fn call_version_3(data: &[u8]) -> Vec { [18].to_vec() } /// fn set_or_clear_version_1(&mut self, optional: Option>) { /// match optional { /// Some(value) => self.set_storage([1, 2, 3, 4].to_vec(), value), @@ -204,6 +222,10 @@ pub use sp_std; /// <&mut dyn sp_externalities::Externalities as Interface>::call_version_2(data) /// } /// +/// fn call_version_3(data: &[u8]) -> Vec { +/// <&mut dyn sp_externalities::Externalities as Interface>::call_version_3(data) +/// } +/// /// pub fn set_or_clear(optional: Option>) { /// set_or_clear_version_1(optional) /// } @@ -285,8 +307,8 @@ pub use sp_std; /// This instructs the macro to make two significant changes to the generated code: /// /// 1. The generated functions are not callable from the native side. -/// 2. The trait as shown above is not implemented for `Externalities` and is instead -/// implemented for `FunctionExecutor` (from `sp-wasm-interface`). +/// 2. The trait as shown above is not implemented for [`Externalities`] and is instead +/// implemented for `FunctionExecutor` (from `sp-wasm-interface`). /// /// # Disable tracing /// By addding `no_tracing` to the list of options you can prevent the wasm-side interface from diff --git a/primitives/runtime-interface/test-wasm/src/lib.rs b/primitives/runtime-interface/test-wasm/src/lib.rs index 982febb7b4fb..0c8a9c04ab1e 100644 --- a/primitives/runtime-interface/test-wasm/src/lib.rs +++ b/primitives/runtime-interface/test-wasm/src/lib.rs @@ -123,6 +123,15 @@ pub trait TestApi { data == 42 } + fn test_versionning_register_only(&self, data: u32) -> bool { + data == 80 + } + + #[version(2, register_only)] + fn test_versionning_register_only(&self, data: u32) -> bool { + data == 42 + } + /// Returns the input values as tuple. fn return_input_as_tuple( a: Vec, @@ -271,6 +280,13 @@ wasm_export_functions! { assert!(!test_api::test_versionning(102)); } + fn test_versionning_register_only_works() { + // Ensure that we will import the version of the runtime interface function that + // isn't tagged with `register_only`. + assert!(!test_api::test_versionning_register_only(42)); + assert!(test_api::test_versionning_register_only(80)); + } + fn test_return_input_as_tuple() { let a = vec![1, 3, 4, 5]; let b = 10000; diff --git a/primitives/runtime-interface/test/src/lib.rs b/primitives/runtime-interface/test/src/lib.rs index e76f54f69a80..1ab8dbfbbff2 100644 --- a/primitives/runtime-interface/test/src/lib.rs +++ b/primitives/runtime-interface/test/src/lib.rs @@ -169,6 +169,11 @@ fn test_versionining_with_new_host_works() { call_wasm_method::(wasm_binary_deprecated_unwrap(), "test_versionning_works"); } +#[test] +fn test_versionining_register_only() { + call_wasm_method::(wasm_binary_unwrap(), "test_versionning_register_only_works"); +} + #[test] fn test_tracing() { use std::fmt; From 04c7c6abef1e0c6b4126427159090a44f3221333 Mon Sep 17 00:00:00 2001 From: Nazar Mokrynskyi Date: Sat, 15 Jan 2022 22:00:12 +0200 Subject: [PATCH 385/695] Minor tweaks suggested by clippy (#10673) * Minor tweaks suggested by clippy * Fix typo caused by last commit * Apply review suggestions --- .../api/proc-macro/src/decl_runtime_apis.rs | 1 + primitives/api/test/tests/runtime_calls.rs | 2 +- test-utils/runtime/src/lib.rs | 31 ++++++++----------- test-utils/runtime/src/system.rs | 10 +++--- .../runtime/transaction-pool/src/lib.rs | 18 +++++------ 5 files changed, 27 insertions(+), 35 deletions(-) diff --git a/primitives/api/proc-macro/src/decl_runtime_apis.rs b/primitives/api/proc-macro/src/decl_runtime_apis.rs index 8d90b09d0e8c..85b66eca7061 100644 --- a/primitives/api/proc-macro/src/decl_runtime_apis.rs +++ b/primitives/api/proc-macro/src/decl_runtime_apis.rs @@ -378,6 +378,7 @@ fn generate_call_api_at_calls(decl: &ItemTrait) -> Result { // Generate the generator function result.push(quote!( #[cfg(any(feature = "std", test))] + #[allow(clippy::too_many_arguments)] pub fn #fn_name< R: #crate_::Encode + #crate_::Decode + PartialEq, NC: FnOnce() -> std::result::Result + std::panic::UnwindSafe, diff --git a/primitives/api/test/tests/runtime_calls.rs b/primitives/api/test/tests/runtime_calls.rs index e085b023b122..ba42b342377c 100644 --- a/primitives/api/test/tests/runtime_calls.rs +++ b/primitives/api/test/tests/runtime_calls.rs @@ -59,7 +59,7 @@ fn calling_native_runtime_function_with_non_decodable_parameter() { .build(); let runtime_api = client.runtime_api(); let block_id = BlockId::Number(client.chain_info().best_number); - runtime_api.fail_convert_parameter(&block_id, DecodeFails::new()).unwrap(); + runtime_api.fail_convert_parameter(&block_id, DecodeFails::default()).unwrap(); } #[test] diff --git a/test-utils/runtime/src/lib.rs b/test-utils/runtime/src/lib.rs index b03998621b31..5c9dfeca0a33 100644 --- a/test-utils/runtime/src/lib.rs +++ b/test-utils/runtime/src/lib.rs @@ -132,8 +132,7 @@ impl Transfer { pub fn into_signed_tx(self) -> Extrinsic { let signature = sp_keyring::AccountKeyring::from_public(&self.from) .expect("Creates keyring from public key.") - .sign(&self.encode()) - .into(); + .sign(&self.encode()); Extrinsic::Transfer { transfer: self, signature, exhaust_resources_when_not_first: false } } @@ -144,8 +143,7 @@ impl Transfer { pub fn into_resources_exhausting_tx(self) -> Extrinsic { let signature = sp_keyring::AccountKeyring::from_public(&self.from) .expect("Creates keyring from public key.") - .sign(&self.encode()) - .into(); + .sign(&self.encode()); Extrinsic::Transfer { transfer: self, signature, exhaust_resources_when_not_first: true } } } @@ -277,9 +275,9 @@ pub fn run_tests(mut input: &[u8]) -> Vec { print("run_tests..."); let block = Block::decode(&mut input).unwrap(); print("deserialized block."); - let stxs = block.extrinsics.iter().map(Encode::encode).collect::>(); + let stxs = block.extrinsics.iter().map(Encode::encode); print("reserialized transactions."); - [stxs.len() as u8].encode() + [stxs.count() as u8].encode() } /// A type that can not be decoded. @@ -296,9 +294,9 @@ impl Encode for DecodeFails { impl codec::EncodeLike for DecodeFails {} -impl DecodeFails { - /// Create a new instance. - pub fn new() -> DecodeFails { +impl Default for DecodeFails { + /// Create a default instance. + fn default() -> DecodeFails { DecodeFails { _phantom: Default::default() } } } @@ -436,8 +434,8 @@ impl From> for Origin { unimplemented!("Not required in tests!") } } -impl Into, Origin>> for Origin { - fn into(self) -> Result, Origin> { +impl From for Result, Origin> { + fn from(_origin: Origin) -> Result, Origin> { unimplemented!("Not required in tests!") } } @@ -651,12 +649,9 @@ fn code_using_trie() -> u64 { let mut mdb = PrefixedMemoryDB::default(); let mut root = sp_std::default::Default::default(); let _ = { - let v = &pairs; let mut t = TrieDBMut::::new(&mut mdb, &mut root); - for i in 0..v.len() { - let key: &[u8] = &v[i].0; - let val: &[u8] = &v[i].1; - if !t.insert(key, val).is_ok() { + for (key, value) in &pairs { + if t.insert(key, value).is_err() { return 101 } } @@ -761,7 +756,7 @@ cfg_if! { fn fail_convert_parameter(_: DecodeFails) {} fn fail_convert_return_value() -> DecodeFails { - DecodeFails::new() + DecodeFails::default() } fn function_signature_changed() -> u64 { @@ -1015,7 +1010,7 @@ cfg_if! { fn fail_convert_parameter(_: DecodeFails) {} fn fail_convert_return_value() -> DecodeFails { - DecodeFails::new() + DecodeFails::default() } fn function_signature_changed() -> Vec { diff --git a/test-utils/runtime/src/system.rs b/test-utils/runtime/src/system.rs index 9f8612b69f33..6df35421d361 100644 --- a/test-utils/runtime/src/system.rs +++ b/test-utils/runtime/src/system.rs @@ -197,7 +197,7 @@ pub fn finalize_block() -> Header { use sp_core::storage::StateVersion; let extrinsic_index: u32 = storage::unhashed::take(well_known_keys::EXTRINSIC_INDEX).unwrap(); let txs: Vec<_> = (0..extrinsic_index).map(ExtrinsicData::take).collect(); - let extrinsics_root = trie::blake2_256_ordered_root(txs, StateVersion::V0).into(); + let extrinsics_root = trie::blake2_256_ordered_root(txs, StateVersion::V0); let number = ::take().expect("Number is set by `initialize_block`"); let parent_hash = ::take(); let mut digest = ::take().expect("StorageDigest is set by `initialize_block`"); @@ -235,11 +235,11 @@ fn execute_transaction_backend(utx: &Extrinsic, extrinsic_index: u32) -> ApplyEx Extrinsic::StorageChange(key, value) => execute_storage_change(key, value.as_ref().map(|v| &**v)), Extrinsic::OffchainIndexSet(key, value) => { - sp_io::offchain_index::set(&key, &value); + sp_io::offchain_index::set(key, value); Ok(Ok(())) }, Extrinsic::OffchainIndexClear(key) => { - sp_io::offchain_index::clear(&key); + sp_io::offchain_index::clear(key); Ok(Ok(())) }, Extrinsic::Store(data) => execute_store(data.clone()), @@ -250,7 +250,7 @@ fn execute_transfer_backend(tx: &Transfer) -> ApplyExtrinsicResult { // check nonce let nonce_key = tx.from.to_keyed_vec(NONCE_OF); let expected_nonce: u64 = storage::hashed::get_or(&blake2_256, &nonce_key, 0); - if !(tx.nonce == expected_nonce) { + if tx.nonce != expected_nonce { return Err(InvalidTransaction::Stale.into()) } @@ -262,7 +262,7 @@ fn execute_transfer_backend(tx: &Transfer) -> ApplyExtrinsicResult { let from_balance: u64 = storage::hashed::get_or(&blake2_256, &from_balance_key, 0); // enact transfer - if !(tx.amount <= from_balance) { + if tx.amount > from_balance { return Err(InvalidTransaction::Payment.into()) } let to_balance_key = tx.to.to_keyed_vec(BALANCE_OF); diff --git a/test-utils/runtime/transaction-pool/src/lib.rs b/test-utils/runtime/transaction-pool/src/lib.rs index a339ce8c7f65..ba317f57f531 100644 --- a/test-utils/runtime/transaction-pool/src/lib.rs +++ b/test-utils/runtime/transaction-pool/src/lib.rs @@ -179,13 +179,13 @@ impl TestApi { /// Add a block to the internal state. pub fn add_block(&self, block: Block, is_best_block: bool) { let hash = block.header.hash(); - let block_number = block.header.number().clone(); + let block_number = block.header.number(); let mut chain = self.chain.write(); chain.block_by_hash.insert(hash, block.clone()); chain .block_by_number - .entry(block_number) + .entry(*block_number) .or_default() .push((block, is_best_block.into())); } @@ -259,15 +259,13 @@ impl sc_transaction_pool::ChainApi for TestApi { if !found_best { return ready(Ok(Err(TransactionValidityError::Invalid( InvalidTransaction::Custom(1), - ) - .into()))) + )))) } }, Ok(None) => return ready(Ok(Err(TransactionValidityError::Invalid( InvalidTransaction::Custom(2), - ) - .into()))), + )))), Err(e) => return ready(Err(e)), } @@ -283,9 +281,7 @@ impl sc_transaction_pool::ChainApi for TestApi { }; if self.chain.read().invalid_hashes.contains(&self.hash_and_length(&uxt).0) { - return ready(Ok(Err( - TransactionValidityError::Invalid(InvalidTransaction::Custom(0)).into() - ))) + return ready(Ok(Err(TransactionValidityError::Invalid(InvalidTransaction::Custom(0))))) } let mut validity = @@ -312,7 +308,7 @@ impl sc_transaction_pool::ChainApi for TestApi { at: &BlockId, ) -> Result::Hash>, Error> { Ok(match at { - generic::BlockId::Hash(x) => Some(x.clone()), + generic::BlockId::Hash(x) => Some(*x), generic::BlockId::Number(num) => self.chain.read().block_by_number.get(num).and_then(|blocks| { blocks.iter().find(|b| b.1.is_best()).map(|b| b.0.header().hash()) @@ -371,6 +367,6 @@ impl sp_blockchain::HeaderMetadata for TestApi { pub fn uxt(who: AccountKeyring, nonce: Index) -> Extrinsic { let dummy = codec::Decode::decode(&mut TrailingZeroInput::zeroes()).unwrap(); let transfer = Transfer { from: who.into(), to: dummy, nonce, amount: 1 }; - let signature = transfer.using_encoded(|e| who.sign(e)).into(); + let signature = transfer.using_encoded(|e| who.sign(e)); Extrinsic::Transfer { transfer, signature, exhaust_resources_when_not_first: false } } From 537bed312037f12e00b52be8d77a7c62731f7fc5 Mon Sep 17 00:00:00 2001 From: Zeke Mostov Date: Sun, 16 Jan 2022 18:15:18 -0800 Subject: [PATCH 386/695] Move `EraIndex` to sp-staking (#10671) * Move `EraIndex` to sp-staking * Fix imports in mocks * Run cargo +nightly-2021-10-29 fmt --- bin/node/runtime/src/lib.rs | 4 ++-- frame/babe/src/mock.rs | 3 +-- frame/grandpa/src/mock.rs | 3 +-- frame/staking/src/lib.rs | 5 +---- frame/staking/src/pallet/impls.rs | 6 +++--- frame/staking/src/pallet/mod.rs | 4 ++-- frame/staking/src/slashing.rs | 6 +++--- primitives/staking/src/lib.rs | 3 +++ 8 files changed, 16 insertions(+), 18 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index aab813f29e0a..b2c98e6be139 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -520,8 +520,8 @@ pallet_staking_reward_curve::build! { parameter_types! { pub const SessionsPerEra: sp_staking::SessionIndex = 6; - pub const BondingDuration: pallet_staking::EraIndex = 24 * 28; - pub const SlashDeferDuration: pallet_staking::EraIndex = 24 * 7; // 1/4 the bonding duration. + pub const BondingDuration: sp_staking::EraIndex = 24 * 28; + pub const SlashDeferDuration: sp_staking::EraIndex = 24 * 7; // 1/4 the bonding duration. pub const RewardCurve: &'static PiecewiseLinear<'static> = &REWARD_CURVE; pub const MaxNominatorRewardedPerValidator: u32 = 256; pub const OffendingValidatorsThreshold: Perbill = Perbill::from_percent(17); diff --git a/frame/babe/src/mock.rs b/frame/babe/src/mock.rs index 22d7befab668..fa7a7b185b34 100644 --- a/frame/babe/src/mock.rs +++ b/frame/babe/src/mock.rs @@ -25,7 +25,6 @@ use frame_support::{ traits::{ConstU128, ConstU32, ConstU64, GenesisBuild, KeyOwnerProofSystem, OnInitialize}, }; use pallet_session::historical as pallet_session_historical; -use pallet_staking::EraIndex; use sp_consensus_babe::{AuthorityId, AuthorityPair, Slot}; use sp_consensus_vrf::schnorrkel::{VRFOutput, VRFProof}; use sp_core::{ @@ -40,7 +39,7 @@ use sp_runtime::{ traits::{Header as _, IdentityLookup, OpaqueKeys}, Perbill, }; -use sp_staking::SessionIndex; +use sp_staking::{EraIndex, SessionIndex}; type DummyValidatorId = u64; diff --git a/frame/grandpa/src/mock.rs b/frame/grandpa/src/mock.rs index 91006d66b7de..34787c93bb9c 100644 --- a/frame/grandpa/src/mock.rs +++ b/frame/grandpa/src/mock.rs @@ -30,7 +30,6 @@ use frame_support::{ }, }; use pallet_session::historical as pallet_session_historical; -use pallet_staking::EraIndex; use sp_core::{crypto::KeyTypeId, H256}; use sp_finality_grandpa::{RoundNumber, SetId, GRANDPA_ENGINE_ID}; use sp_keyring::Ed25519Keyring; @@ -41,7 +40,7 @@ use sp_runtime::{ traits::{IdentityLookup, OpaqueKeys}, DigestItem, Perbill, }; -use sp_staking::SessionIndex; +use sp_staking::{EraIndex, SessionIndex}; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; type Block = frame_system::mocking::MockBlock; diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 268618fb5f44..efe67c8b00c8 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -312,7 +312,7 @@ use sp_runtime::{ }; use sp_staking::{ offence::{Offence, OffenceError, ReportOffence}, - SessionIndex, + EraIndex, SessionIndex, }; use sp_std::{collections::btree_map::BTreeMap, convert::From, prelude::*}; pub use weights::WeightInfo; @@ -332,9 +332,6 @@ macro_rules! log { }; } -/// Counter for the number of eras that have passed. -pub type EraIndex = u32; - /// Counter for the number of "reward" points earned by a given validator. pub type RewardPoint = u32; diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index c97541de8196..68b5c19027a9 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -37,13 +37,13 @@ use sp_runtime::{ }; use sp_staking::{ offence::{DisableStrategy, OffenceDetails, OnOffenceHandler}, - SessionIndex, + EraIndex, SessionIndex, }; use sp_std::{collections::btree_map::BTreeMap, prelude::*}; use crate::{ - log, slashing, weights::WeightInfo, ActiveEraInfo, BalanceOf, EraIndex, EraPayout, Exposure, - ExposureOf, Forcing, IndividualExposure, Nominations, PositiveImbalanceOf, RewardDestination, + log, slashing, weights::WeightInfo, ActiveEraInfo, BalanceOf, EraPayout, Exposure, ExposureOf, + Forcing, IndividualExposure, Nominations, PositiveImbalanceOf, RewardDestination, SessionInterface, StakingLedger, ValidatorPrefs, }; diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index e45a21ab2503..fc70d523ac9c 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -31,7 +31,7 @@ use sp_runtime::{ traits::{CheckedSub, SaturatedConversion, StaticLookup, Zero}, DispatchError, Perbill, Percent, }; -use sp_staking::SessionIndex; +use sp_staking::{EraIndex, SessionIndex}; use sp_std::{convert::From, prelude::*, result}; mod impls; @@ -39,7 +39,7 @@ mod impls; pub use impls::*; use crate::{ - log, migrations, slashing, weights::WeightInfo, ActiveEraInfo, BalanceOf, EraIndex, EraPayout, + log, migrations, slashing, weights::WeightInfo, ActiveEraInfo, BalanceOf, EraPayout, EraRewardPoints, Exposure, Forcing, NegativeImbalanceOf, Nominations, PositiveImbalanceOf, Releases, RewardDestination, SessionInterface, StakingLedger, UnappliedSlash, UnlockChunk, ValidatorPrefs, diff --git a/frame/staking/src/slashing.rs b/frame/staking/src/slashing.rs index 4fa7d347da70..2f381ad631fe 100644 --- a/frame/staking/src/slashing.rs +++ b/frame/staking/src/slashing.rs @@ -50,8 +50,8 @@ //! Based on research at use crate::{ - BalanceOf, Config, EraIndex, Error, Exposure, NegativeImbalanceOf, Pallet, Perbill, - SessionInterface, Store, UnappliedSlash, + BalanceOf, Config, Error, Exposure, NegativeImbalanceOf, Pallet, Perbill, SessionInterface, + Store, UnappliedSlash, }; use codec::{Decode, Encode}; use frame_support::{ @@ -63,7 +63,7 @@ use sp_runtime::{ traits::{Saturating, Zero}, DispatchResult, RuntimeDebug, }; -use sp_staking::offence::DisableStrategy; +use sp_staking::{offence::DisableStrategy, EraIndex}; use sp_std::vec::Vec; /// The proportion of the slashing reward to be paid out on the first slashing detection. diff --git a/primitives/staking/src/lib.rs b/primitives/staking/src/lib.rs index e7db609e230a..15208df62cc6 100644 --- a/primitives/staking/src/lib.rs +++ b/primitives/staking/src/lib.rs @@ -24,3 +24,6 @@ pub mod offence; /// Simple index type with which we can count sessions. pub type SessionIndex = u32; + +/// Counter for the number of eras that have passed. +pub type EraIndex = u32; From fe3f379a105d4be72963a0f2fbe654b86e92a5ec Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Mon, 17 Jan 2022 05:28:11 -0400 Subject: [PATCH 387/695] Improve BoundedVec API (extracted from #10195) (#10656) * Gav wrote this code in pull #10195. Extracting to simplify that PR. * fix potential panics * prevent panics in slide * update doc * fmt * Update frame/support/src/storage/bounded_vec.rs Co-authored-by: Keith Yeung Co-authored-by: Gav Wood Co-authored-by: Keith Yeung --- frame/support/src/storage/bounded_vec.rs | 218 ++++++++++++++++++++++- 1 file changed, 216 insertions(+), 2 deletions(-) diff --git a/frame/support/src/storage/bounded_vec.rs b/frame/support/src/storage/bounded_vec.rs index 9f43d37a2d7f..6d7206df6db1 100644 --- a/frame/support/src/storage/bounded_vec.rs +++ b/frame/support/src/storage/bounded_vec.rs @@ -149,6 +149,16 @@ impl BoundedVec { ) -> Option<&mut >::Output> { self.0.get_mut(index) } + + /// Exactly the same semantics as [`Vec::truncate`]. + pub fn truncate(&mut self, s: usize) { + self.0.truncate(s); + } + + /// Exactly the same semantics as [`Vec::pop`]. + pub fn pop(&mut self) -> Option { + self.0.pop() + } } impl> From> for Vec { @@ -176,6 +186,115 @@ impl> BoundedVec { S::get() as usize } + /// Forces the insertion of `s` into `self` retaining all items with index at least `index`. + /// + /// If `index == 0` and `self.len() == Self::bound()`, then this is a no-op. + /// + /// If `Self::bound() < index` or `self.len() < index`, then this is also a no-op. + /// + /// Returns `true` if the item was inserted. + pub fn force_insert_keep_right(&mut self, index: usize, element: T) -> bool { + // Check against panics. + if Self::bound() < index || self.len() < index { + return false + } + if self.len() < Self::bound() { + // Cannot panic since self.len() >= index; + self.0.insert(index, element); + } else { + if index == 0 { + return false + } + self[0] = element; + // `[0..index] cannot panic since self.len() >= index. + // `rotate_left(1)` cannot panic because there is at least 1 element. + self[0..index].rotate_left(1); + } + true + } + + /// Forces the insertion of `s` into `self` retaining all items with index at most `index`. + /// + /// If `index == Self::bound()` and `self.len() == Self::bound()`, then this is a no-op. + /// + /// If `Self::bound() < index` or `self.len() < index`, then this is also a no-op. + /// + /// Returns `true` if the item was inserted. + pub fn force_insert_keep_left(&mut self, index: usize, element: T) -> bool { + // Check against panics. + if Self::bound() < index || self.len() < index { + return false + } + // Noop condition. + if Self::bound() == index && self.len() <= Self::bound() { + return false + } + // Cannot panic since self.len() >= index; + self.0.insert(index, element); + self.0.truncate(Self::bound()); + true + } + + /// Move the position of an item from one location to another in the slice. + /// + /// Except for the item being moved, the order of the slice remains the same. + /// + /// - `index` is the location of the item to be moved. + /// - `insert_position` is the index of the item in the slice which should *immediately follow* + /// the item which is being moved. + /// + /// Returns `true` of the operation was successful, otherwise `false` if a noop. + pub fn slide(&mut self, index: usize, insert_position: usize) -> bool { + // Check against panics. + if self.len() <= index || self.len() < insert_position || index == usize::MAX { + return false + } + // Noop conditions. + if index == insert_position || index + 1 == insert_position { + return false + } + if insert_position < index && index < self.len() { + // --- --- --- === === === === @@@ --- --- --- + // ^-- N ^O^ + // ... + // /-----<<<-----\ + // --- --- --- === === === === @@@ --- --- --- + // >>> >>> >>> >>> + // ... + // --- --- --- @@@ === === === === --- --- --- + // ^N^ + self[insert_position..index + 1].rotate_right(1); + return true + } else if insert_position > 0 && index + 1 < insert_position { + // Note that the apparent asymmetry of these two branches is due to the + // fact that the "new" position is the position to be inserted *before*. + // --- --- --- @@@ === === === === --- --- --- + // ^O^ ^-- N + // ... + // /----->>>-----\ + // --- --- --- @@@ === === === === --- --- --- + // <<< <<< <<< <<< + // ... + // --- --- --- === === === === @@@ --- --- --- + // ^N^ + self[index..insert_position].rotate_left(1); + return true + } + + debug_assert!(false, "all noop conditions should have been covered above"); + false + } + + /// Forces the insertion of `s` into `self` truncating first if necessary. + /// + /// Infallible, but if the bound is zero, then it's a no-op. + pub fn force_push(&mut self, element: T) { + if Self::bound() > 0 { + self.0.truncate(Self::bound() as usize - 1); + self.0.push(element); + } + } + /// Same as `Vec::resize`, but if `size` is more than [`Self::bound`], then [`Self::bound`] is /// used. pub fn bounded_resize(&mut self, size: usize, value: T) @@ -397,8 +516,7 @@ where #[cfg(test)] pub mod test { use super::*; - use crate::Twox128; - use frame_support::traits::ConstU32; + use crate::{traits::ConstU32, Twox128}; use sp_io::TestExternalities; crate::generate_storage_alias! { Prefix, Foo => Value>> } @@ -408,6 +526,102 @@ pub mod test { FooDoubleMap => DoubleMap<(u32, Twox128), (u32, Twox128), BoundedVec>> } + #[test] + fn slide_works() { + let mut b: BoundedVec> = vec![0, 1, 2, 3, 4, 5].try_into().unwrap(); + assert!(b.slide(1, 5)); + assert_eq!(*b, vec![0, 2, 3, 4, 1, 5]); + assert!(b.slide(4, 0)); + assert_eq!(*b, vec![1, 0, 2, 3, 4, 5]); + assert!(b.slide(0, 2)); + assert_eq!(*b, vec![0, 1, 2, 3, 4, 5]); + assert!(b.slide(1, 6)); + assert_eq!(*b, vec![0, 2, 3, 4, 5, 1]); + assert!(b.slide(0, 6)); + assert_eq!(*b, vec![2, 3, 4, 5, 1, 0]); + assert!(b.slide(5, 0)); + assert_eq!(*b, vec![0, 2, 3, 4, 5, 1]); + assert!(!b.slide(6, 0)); + assert!(!b.slide(7, 0)); + assert_eq!(*b, vec![0, 2, 3, 4, 5, 1]); + + let mut c: BoundedVec> = vec![0, 1, 2].try_into().unwrap(); + assert!(!c.slide(1, 5)); + assert_eq!(*c, vec![0, 1, 2]); + assert!(!c.slide(4, 0)); + assert_eq!(*c, vec![0, 1, 2]); + assert!(!c.slide(3, 0)); + assert_eq!(*c, vec![0, 1, 2]); + assert!(c.slide(2, 0)); + assert_eq!(*c, vec![2, 0, 1]); + } + + #[test] + fn slide_noops_work() { + let mut b: BoundedVec> = vec![0, 1, 2, 3, 4, 5].try_into().unwrap(); + assert!(!b.slide(3, 3)); + assert_eq!(*b, vec![0, 1, 2, 3, 4, 5]); + assert!(!b.slide(3, 4)); + assert_eq!(*b, vec![0, 1, 2, 3, 4, 5]); + } + + #[test] + fn force_insert_keep_left_works() { + let mut b: BoundedVec> = vec![].try_into().unwrap(); + assert!(!b.force_insert_keep_left(1, 10)); + assert!(b.is_empty()); + + assert!(b.force_insert_keep_left(0, 30)); + assert!(b.force_insert_keep_left(0, 10)); + assert!(b.force_insert_keep_left(1, 20)); + assert!(b.force_insert_keep_left(3, 40)); + assert_eq!(*b, vec![10, 20, 30, 40]); + // at capacity. + assert!(!b.force_insert_keep_left(4, 41)); + assert_eq!(*b, vec![10, 20, 30, 40]); + assert!(b.force_insert_keep_left(3, 31)); + assert_eq!(*b, vec![10, 20, 30, 31]); + assert!(b.force_insert_keep_left(1, 11)); + assert_eq!(*b, vec![10, 11, 20, 30]); + assert!(b.force_insert_keep_left(0, 1)); + assert_eq!(*b, vec![1, 10, 11, 20]); + + let mut z: BoundedVec> = vec![].try_into().unwrap(); + assert!(z.is_empty()); + assert!(!z.force_insert_keep_left(0, 10)); + assert!(z.is_empty()); + } + + #[test] + fn force_insert_keep_right_works() { + let mut b: BoundedVec> = vec![].try_into().unwrap(); + assert!(!b.force_insert_keep_right(1, 10)); + assert!(b.is_empty()); + + assert!(b.force_insert_keep_right(0, 30)); + assert!(b.force_insert_keep_right(0, 10)); + assert!(b.force_insert_keep_right(1, 20)); + assert!(b.force_insert_keep_right(3, 40)); + assert_eq!(*b, vec![10, 20, 30, 40]); + // at capacity. + assert!(!b.force_insert_keep_right(0, 0)); + assert_eq!(*b, vec![10, 20, 30, 40]); + assert!(b.force_insert_keep_right(1, 11)); + assert_eq!(*b, vec![11, 20, 30, 40]); + assert!(b.force_insert_keep_right(3, 31)); + assert_eq!(*b, vec![20, 30, 31, 40]); + assert!(b.force_insert_keep_right(4, 41)); + assert_eq!(*b, vec![30, 31, 40, 41]); + + assert!(!b.force_insert_keep_right(5, 69)); + assert_eq!(*b, vec![30, 31, 40, 41]); + + let mut z: BoundedVec> = vec![].try_into().unwrap(); + assert!(z.is_empty()); + assert!(!z.force_insert_keep_right(0, 10)); + assert!(z.is_empty()); + } + #[test] fn try_append_is_correct() { assert_eq!(BoundedVec::>::bound(), 7); From 9d1790636e55a3456bdab91ff2d0e059878d3c42 Mon Sep 17 00:00:00 2001 From: Joey Date: Mon, 17 Jan 2022 17:31:45 +0800 Subject: [PATCH 388/695] the report mod and REPORTING keyType is no longer used (#10679) --- bin/node/primitives/src/lib.rs | 31 ------------------------------- primitives/core/src/crypto.rs | 2 -- 2 files changed, 33 deletions(-) diff --git a/bin/node/primitives/src/lib.rs b/bin/node/primitives/src/lib.rs index fd000af6b2f1..feb9ee60d311 100644 --- a/bin/node/primitives/src/lib.rs +++ b/bin/node/primitives/src/lib.rs @@ -64,34 +64,3 @@ pub type Header = generic::Header; pub type Block = generic::Block; /// Block ID. pub type BlockId = generic::BlockId; - -/// App-specific crypto used for reporting equivocation/misbehavior in BABE and -/// GRANDPA. Any rewards for misbehavior reporting will be paid out to this -/// account. -pub mod report { - use super::{Signature, Verify}; - use frame_system::offchain::AppCrypto; - use sp_core::crypto::{key_types, KeyTypeId}; - - /// Key type for the reporting module. Used for reporting BABE and GRANDPA - /// equivocations. - pub const KEY_TYPE: KeyTypeId = key_types::REPORTING; - - mod app { - use sp_application_crypto::{app_crypto, sr25519}; - app_crypto!(sr25519, super::KEY_TYPE); - } - - /// Identity of the equivocation/misbehavior reporter. - pub type ReporterId = app::Public; - - /// An `AppCrypto` type to allow submitting signed transactions using the reporting - /// application key as signer. - pub struct ReporterAppCrypto; - - impl AppCrypto<::Signer, Signature> for ReporterAppCrypto { - type RuntimeAppPublic = ReporterId; - type GenericSignature = sp_core::sr25519::Signature; - type GenericPublic = sp_core::sr25519::Public; - } -} diff --git a/primitives/core/src/crypto.rs b/primitives/core/src/crypto.rs index d3dd8b92bd79..41ee9466ad93 100644 --- a/primitives/core/src/crypto.rs +++ b/primitives/core/src/crypto.rs @@ -1121,8 +1121,6 @@ pub mod key_types { pub const AUTHORITY_DISCOVERY: KeyTypeId = KeyTypeId(*b"audi"); /// Key type for staking, built-in. Identified as `stak`. pub const STAKING: KeyTypeId = KeyTypeId(*b"stak"); - /// Key type for equivocation reporting, built-in. Identified as `fish`. - pub const REPORTING: KeyTypeId = KeyTypeId(*b"fish"); /// A key type ID useful for tests. pub const DUMMY: KeyTypeId = KeyTypeId(*b"dumy"); } From 02bdc57655d18ea24b7a9bda6377bd0f134f7d8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Mon, 17 Jan 2022 11:45:28 +0200 Subject: [PATCH 389/695] contracts: Get rid of the dreaded `Other` error (#10595) * Print more detailed error when instrumentation fails * Apply suggestions from code review Co-authored-by: Hernando Castano * Check contents of debug buffer * Fix test Co-authored-by: Hernando Castano --- frame/contracts/fixtures/invalid_import.wat | 6 +++ frame/contracts/src/lib.rs | 16 +++++-- frame/contracts/src/tests.rs | 31 ++++++++++++- frame/contracts/src/wasm/mod.rs | 4 +- frame/contracts/src/wasm/prepare.rs | 48 ++++++++++++--------- 5 files changed, 78 insertions(+), 27 deletions(-) create mode 100644 frame/contracts/fixtures/invalid_import.wat diff --git a/frame/contracts/fixtures/invalid_import.wat b/frame/contracts/fixtures/invalid_import.wat new file mode 100644 index 000000000000..011f1a40e76d --- /dev/null +++ b/frame/contracts/fixtures/invalid_import.wat @@ -0,0 +1,6 @@ +;; A valid contract which does nothing at all but imports an invalid function +(module + (import "invalid" "invalid_88_99" (func (param i32 i32 i32))) + (func (export "deploy")) + (func (export "call")) +) diff --git a/frame/contracts/src/lib.rs b/frame/contracts/src/lib.rs index e4a54362c90b..24d3a7f10ef9 100644 --- a/frame/contracts/src/lib.rs +++ b/frame/contracts/src/lib.rs @@ -632,6 +632,10 @@ pub mod pallet { /// or via RPC an `Ok` will be returned. In this case the caller needs to inspect the flags /// to determine whether a reversion has taken place. ContractReverted, + /// The contract's code was found to be invalid during validation or instrumentation. + /// A more detailed error can be found on the node console if debug messages are enabled + /// or in the debug buffer which is returned to RPC clients. + CodeRejected, } /// A mapping from an original code hash to the original code, untouched by instrumentation. @@ -781,7 +785,8 @@ where storage_deposit_limit: Option>, ) -> CodeUploadResult, BalanceOf> { let schedule = T::Schedule::get(); - let module = PrefabWasmModule::from_code(code, &schedule, origin)?; + let module = PrefabWasmModule::from_code(code, &schedule, origin) + .map_err(|_| >::CodeRejected)?; let deposit = module.open_deposit(); if let Some(storage_deposit_limit) = storage_deposit_limit { ensure!(storage_deposit_limit >= deposit, >::StorageDepositLimitExhausted); @@ -879,7 +884,7 @@ where code: Code>, data: Vec, salt: Vec, - debug_message: Option<&mut Vec>, + mut debug_message: Option<&mut Vec>, ) -> InternalInstantiateOutput { let mut storage_deposit = Default::default(); let mut gas_meter = GasMeter::new(gas_limit); @@ -891,8 +896,11 @@ where binary.len() as u32 <= schedule.limits.code_len, >::CodeTooLarge ); - let executable = - PrefabWasmModule::from_code(binary, &schedule, origin.clone())?; + let executable = PrefabWasmModule::from_code(binary, &schedule, origin.clone()) + .map_err(|msg| { + debug_message.as_mut().map(|buffer| buffer.extend(msg.as_bytes())); + >::CodeRejected + })?; ensure!( executable.code_len() <= schedule.limits.code_len, >::CodeTooLarge diff --git a/frame/contracts/src/tests.rs b/frame/contracts/src/tests.rs index be9904e71c5c..fd5c8cfd34ec 100644 --- a/frame/contracts/src/tests.rs +++ b/frame/contracts/src/tests.rs @@ -1386,7 +1386,7 @@ fn disabled_chain_extension_wont_deploy() { vec![], vec![], ), - "module uses chain extensions but chain extensions are disabled", + >::CodeRejected, ); }); } @@ -2903,3 +2903,32 @@ fn contract_reverted() { assert_eq!(result.data.0, buffer); }); } + +#[test] +fn code_rejected_error_works() { + let (wasm, _) = compile_module::("invalid_import").unwrap(); + ExtBuilder::default().existential_deposit(200).build().execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + + assert_noop!( + Contracts::upload_code(Origin::signed(ALICE), wasm.clone(), None), + >::CodeRejected, + ); + + let result = Contracts::bare_instantiate( + ALICE, + 0, + GAS_LIMIT, + None, + Code::Upload(Bytes(wasm)), + vec![], + vec![], + true, + ); + assert_err!(result.result, >::CodeRejected); + assert_eq!( + std::str::from_utf8(&result.debug_message).unwrap(), + "module imports a non-existent function" + ); + }); +} diff --git a/frame/contracts/src/wasm/mod.rs b/frame/contracts/src/wasm/mod.rs index f63361a03930..ee778982cdbd 100644 --- a/frame/contracts/src/wasm/mod.rs +++ b/frame/contracts/src/wasm/mod.rs @@ -122,8 +122,8 @@ where original_code: Vec, schedule: &Schedule, owner: AccountIdOf, - ) -> Result { - prepare::prepare_contract(original_code, schedule, owner).map_err(Into::into) + ) -> Result { + prepare::prepare_contract(original_code, schedule, owner) } /// Store the code without instantiating it. diff --git a/frame/contracts/src/wasm/prepare.rs b/frame/contracts/src/wasm/prepare.rs index 5e5f8e7e6fc9..a57e9aabf8bf 100644 --- a/frame/contracts/src/wasm/prepare.rs +++ b/frame/contracts/src/wasm/prepare.rs @@ -372,26 +372,34 @@ fn check_and_instrument( original_code: &[u8], schedule: &Schedule, ) -> Result<(Vec, (u32, u32)), &'static str> { - let contract_module = ContractModule::new(&original_code, schedule)?; - contract_module.scan_exports()?; - contract_module.ensure_no_internal_memory()?; - contract_module.ensure_table_size_limit(schedule.limits.table_size)?; - contract_module.ensure_global_variable_limit(schedule.limits.globals)?; - contract_module.ensure_no_floating_types()?; - contract_module.ensure_parameter_limit(schedule.limits.parameters)?; - contract_module.ensure_br_table_size_limit(schedule.limits.br_table_size)?; - - // We disallow importing `gas` function here since it is treated as implementation detail. - let disallowed_imports = [b"gas".as_ref()]; - let memory_limits = - get_memory_limits(contract_module.scan_imports::(&disallowed_imports)?, schedule)?; - - let code = contract_module - .inject_gas_metering()? - .inject_stack_height_metering()? - .into_wasm_code()?; - - Ok((code, memory_limits)) + let result = (|| { + let contract_module = ContractModule::new(&original_code, schedule)?; + contract_module.scan_exports()?; + contract_module.ensure_no_internal_memory()?; + contract_module.ensure_table_size_limit(schedule.limits.table_size)?; + contract_module.ensure_global_variable_limit(schedule.limits.globals)?; + contract_module.ensure_no_floating_types()?; + contract_module.ensure_parameter_limit(schedule.limits.parameters)?; + contract_module.ensure_br_table_size_limit(schedule.limits.br_table_size)?; + + // We disallow importing `gas` function here since it is treated as implementation detail. + let disallowed_imports = [b"gas".as_ref()]; + let memory_limits = + get_memory_limits(contract_module.scan_imports::(&disallowed_imports)?, schedule)?; + + let code = contract_module + .inject_gas_metering()? + .inject_stack_height_metering()? + .into_wasm_code()?; + + Ok((code, memory_limits)) + })(); + + if let Err(msg) = &result { + log::debug!(target: "runtime::contracts", "CodeRejected: {}", msg); + } + + result } fn do_preparation( From 08d2ed16ecfe35ab44214112ebc911aa6fed6c1e Mon Sep 17 00:00:00 2001 From: James Wilson Date: Mon, 17 Jan 2022 12:52:10 +0000 Subject: [PATCH 390/695] Bump sp-keyring to 4.1.0-dev (#10681) --- Cargo.lock | 2 +- bin/node/cli/Cargo.toml | 2 +- bin/node/executor/Cargo.toml | 2 +- bin/node/runtime/Cargo.toml | 2 +- bin/node/testing/Cargo.toml | 2 +- client/cli/Cargo.toml | 2 +- client/consensus/aura/Cargo.toml | 2 +- client/consensus/babe/rpc/Cargo.toml | 2 +- client/finality-grandpa/Cargo.toml | 2 +- client/finality-grandpa/rpc/Cargo.toml | 2 +- frame/grandpa/Cargo.toml | 2 +- frame/indices/Cargo.toml | 2 +- primitives/keyring/Cargo.toml | 2 +- test-utils/client/Cargo.toml | 2 +- test-utils/runtime/Cargo.toml | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b65795a373b3..cbc99d726eb1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9611,7 +9611,7 @@ dependencies = [ [[package]] name = "sp-keyring" -version = "4.0.0-dev" +version = "4.1.0-dev" dependencies = [ "lazy_static", "sp-core", diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index f955076e122b..58b4d9806846 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -52,7 +52,7 @@ sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } sp-timestamp = { version = "4.0.0-dev", path = "../../../primitives/timestamp" } sp-authorship = { version = "4.0.0-dev", path = "../../../primitives/authorship" } sp-inherents = { version = "4.0.0-dev", path = "../../../primitives/inherents" } -sp-keyring = { version = "4.0.0-dev", path = "../../../primitives/keyring" } +sp-keyring = { version = "4.1.0-dev", path = "../../../primitives/keyring" } sp-keystore = { version = "0.10.0", path = "../../../primitives/keystore" } sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" } sp-transaction-pool = { version = "4.0.0-dev", path = "../../../primitives/transaction-pool" } diff --git a/bin/node/executor/Cargo.toml b/bin/node/executor/Cargo.toml index 531e53d2048a..9796ef6c0ad7 100644 --- a/bin/node/executor/Cargo.toml +++ b/bin/node/executor/Cargo.toml @@ -38,7 +38,7 @@ sp-application-crypto = { version = "4.0.0", path = "../../../primitives/applica sp-consensus-babe = { version = "0.10.0-dev", path = "../../../primitives/consensus/babe" } sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } sp-externalities = { version = "0.10.0", path = "../../../primitives/externalities" } -sp-keyring = { version = "4.0.0-dev", path = "../../../primitives/keyring" } +sp-keyring = { version = "4.1.0-dev", path = "../../../primitives/keyring" } wat = "1.0" futures = "0.3.9" diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index fa879adf5cbb..1cffabe09ae6 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -35,7 +35,7 @@ sp-std = { version = "4.0.0", default-features = false, path = "../../../primiti sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/api" } sp-runtime = { version = "4.0.0", default-features = false, path = "../../../primitives/runtime" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/staking" } -sp-keyring = { version = "4.0.0-dev", optional = true, path = "../../../primitives/keyring" } +sp-keyring = { version = "4.1.0-dev", optional = true, path = "../../../primitives/keyring" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/session" } sp-transaction-pool = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/transaction-pool" } sp-version = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/version" } diff --git a/bin/node/testing/Cargo.toml b/bin/node/testing/Cargo.toml index bee6f92d1280..d0348b3096bb 100644 --- a/bin/node/testing/Cargo.toml +++ b/bin/node/testing/Cargo.toml @@ -24,7 +24,7 @@ sc-client-db = { version = "0.10.0-dev", path = "../../../client/db/", features sc-client-api = { version = "4.0.0-dev", path = "../../../client/api/" } sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/common" } codec = { package = "parity-scale-codec", version = "2.0.0" } -sp-keyring = { version = "4.0.0-dev", path = "../../../primitives/keyring" } +sp-keyring = { version = "4.1.0-dev", path = "../../../primitives/keyring" } node-executor = { version = "3.0.0-dev", path = "../executor" } node-primitives = { version = "2.0.0", path = "../primitives" } node-runtime = { version = "3.0.0-dev", path = "../runtime" } diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index 7ef5ef9d6893..5b7825182b38 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -36,7 +36,7 @@ sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-keystore = { version = "0.10.0", path = "../../primitives/keystore" } sc-service = { version = "0.10.0-dev", default-features = false, path = "../service" } sc-telemetry = { version = "4.0.0-dev", path = "../telemetry" } -sp-keyring = { version = "4.0.0-dev", path = "../../primitives/keyring" } +sp-keyring = { version = "4.1.0-dev", path = "../../primitives/keyring" } names = { version = "0.12.0", default-features = false } structopt = "0.3.25" sc-tracing = { version = "4.0.0-dev", path = "../tracing" } diff --git a/client/consensus/aura/Cargo.toml b/client/consensus/aura/Cargo.toml index e9c897de5dcb..534aa28920ae 100644 --- a/client/consensus/aura/Cargo.toml +++ b/client/consensus/aura/Cargo.toml @@ -41,7 +41,7 @@ getrandom = { version = "0.2", features = ["js"], optional = true } [dev-dependencies] sp-timestamp = { version = "4.0.0-dev", path = "../../../primitives/timestamp" } -sp-keyring = { version = "4.0.0-dev", path = "../../../primitives/keyring" } +sp-keyring = { version = "4.1.0-dev", path = "../../../primitives/keyring" } sp-tracing = { version = "4.0.0", path = "../../../primitives/tracing" } sc-keystore = { version = "4.0.0-dev", path = "../../keystore" } sc-network = { version = "0.10.0-dev", path = "../../network" } diff --git a/client/consensus/babe/rpc/Cargo.toml b/client/consensus/babe/rpc/Cargo.toml index dbc840d26c57..0806f72e688e 100644 --- a/client/consensus/babe/rpc/Cargo.toml +++ b/client/consensus/babe/rpc/Cargo.toml @@ -34,7 +34,7 @@ sp-keystore = { version = "0.10.0", path = "../../../../primitives/keystore" } [dev-dependencies] sc-consensus = { version = "0.10.0-dev", path = "../../../consensus/common" } serde_json = "1.0.74" -sp-keyring = { version = "4.0.0-dev", path = "../../../../primitives/keyring" } +sp-keyring = { version = "4.1.0-dev", path = "../../../../primitives/keyring" } sc-keystore = { version = "4.0.0-dev", path = "../../../keystore" } substrate-test-runtime-client = { version = "2.0.0", path = "../../../../test-utils/runtime/client" } tempfile = "3.1.0" diff --git a/client/finality-grandpa/Cargo.toml b/client/finality-grandpa/Cargo.toml index 306311b0e3e5..83ebe617973b 100644 --- a/client/finality-grandpa/Cargo.toml +++ b/client/finality-grandpa/Cargo.toml @@ -55,7 +55,7 @@ finality-grandpa = { version = "0.14.1", features = [ ] } sc-network = { version = "0.10.0-dev", path = "../network" } sc-network-test = { version = "0.8.0", path = "../network/test" } -sp-keyring = { version = "4.0.0-dev", path = "../../primitives/keyring" } +sp-keyring = { version = "4.1.0-dev", path = "../../primitives/keyring" } substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } tokio = "1.15" diff --git a/client/finality-grandpa/rpc/Cargo.toml b/client/finality-grandpa/rpc/Cargo.toml index b923ec41d33f..2fe7d3683159 100644 --- a/client/finality-grandpa/rpc/Cargo.toml +++ b/client/finality-grandpa/rpc/Cargo.toml @@ -34,5 +34,5 @@ sc-rpc = { version = "4.0.0-dev", path = "../../rpc", features = [ ] } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sp-finality-grandpa = { version = "4.0.0-dev", path = "../../../primitives/finality-grandpa" } -sp-keyring = { version = "4.0.0-dev", path = "../../../primitives/keyring" } +sp-keyring = { version = "4.1.0-dev", path = "../../../primitives/keyring" } substrate-test-runtime-client = { version = "2.0.0", path = "../../../test-utils/runtime/client" } diff --git a/frame/grandpa/Cargo.toml b/frame/grandpa/Cargo.toml index f123fdbb61ee..8604c678bf64 100644 --- a/frame/grandpa/Cargo.toml +++ b/frame/grandpa/Cargo.toml @@ -33,7 +33,7 @@ log = { version = "0.4.14", default-features = false } [dev-dependencies] frame-benchmarking = { version = "4.0.0-dev", path = "../benchmarking" } grandpa = { package = "finality-grandpa", version = "0.14.1", features = ["derive-codec"] } -sp-keyring = { version = "4.0.0-dev", path = "../../primitives/keyring" } +sp-keyring = { version = "4.1.0-dev", path = "../../primitives/keyring" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } pallet-offences = { version = "4.0.0-dev", path = "../offences" } pallet-staking = { version = "4.0.0-dev", path = "../staking" } diff --git a/frame/indices/Cargo.toml b/frame/indices/Cargo.toml index da56606ed2f6..d2c114e60519 100644 --- a/frame/indices/Cargo.toml +++ b/frame/indices/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-keyring = { version = "4.0.0-dev", optional = true, path = "../../primitives/keyring" } +sp-keyring = { version = "4.1.0-dev", optional = true, path = "../../primitives/keyring" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } diff --git a/primitives/keyring/Cargo.toml b/primitives/keyring/Cargo.toml index a8529716b712..d9250d0011f1 100644 --- a/primitives/keyring/Cargo.toml +++ b/primitives/keyring/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-keyring" -version = "4.0.0-dev" +version = "4.1.0-dev" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" diff --git a/test-utils/client/Cargo.toml b/test-utils/client/Cargo.toml index cb9f17f637dd..91504df481df 100644 --- a/test-utils/client/Cargo.toml +++ b/test-utils/client/Cargo.toml @@ -31,7 +31,7 @@ sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-keystore = { version = "0.10.0", path = "../../primitives/keystore" } -sp-keyring = { version = "4.0.0-dev", path = "../../primitives/keyring" } +sp-keyring = { version = "4.1.0-dev", path = "../../primitives/keyring" } sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } sp-state-machine = { version = "0.10.0", path = "../../primitives/state-machine" } async-trait = "0.1.50" diff --git a/test-utils/runtime/Cargo.toml b/test-utils/runtime/Cargo.toml index c32586834f30..ee38cfd250dc 100644 --- a/test-utils/runtime/Cargo.toml +++ b/test-utils/runtime/Cargo.toml @@ -20,7 +20,7 @@ sp-block-builder = { version = "4.0.0-dev", default-features = false, path = ".. codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../primitives/inherents" } -sp-keyring = { version = "4.0.0-dev", optional = true, path = "../../primitives/keyring" } +sp-keyring = { version = "4.1.0-dev", optional = true, path = "../../primitives/keyring" } memory-db = { version = "0.27.0", default-features = false } sp-offchain = { version = "4.0.0-dev", default-features = false, path = "../../primitives/offchain" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } From 249dbbba6a1a277a3098c2a5b302645da16451ad Mon Sep 17 00:00:00 2001 From: Nazar Mokrynskyi Date: Mon, 17 Jan 2022 15:39:24 +0200 Subject: [PATCH 391/695] Update wasmtime to 0.33.0 (#10674) Also disable memory64 support in wasmtime --- Cargo.lock | 183 ++++++++++-------------- client/executor/wasmtime/Cargo.toml | 2 +- client/executor/wasmtime/src/runtime.rs | 1 + client/executor/wasmtime/src/tests.rs | 6 +- primitives/wasm-interface/Cargo.toml | 2 +- 5 files changed, 81 insertions(+), 113 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cbc99d726eb1..12b825375631 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12,15 +12,6 @@ dependencies = [ "regex", ] -[[package]] -name = "addr2line" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e61f2b7f93d2c7d2b08263acaa4a363b3e276806c68af6134c44f523bf1aacd" -dependencies = [ - "gimli 0.25.0", -] - [[package]] name = "addr2line" version = "0.17.0" @@ -431,7 +422,7 @@ version = "0.3.63" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "321629d8ba6513061f26707241fa9bc89524ff1cd7a915a97ef0c62c666ce1b6" dependencies = [ - "addr2line 0.17.0", + "addr2line", "cc", "cfg-if 1.0.0", "libc", @@ -1105,11 +1096,11 @@ dependencies = [ [[package]] name = "cranelift-bforest" -version = "0.78.0" +version = "0.80.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc0cb7df82c8cf8f2e6a8dd394a0932a71369c160cc9b027dca414fced242513" +checksum = "9516ba6b2ba47b4cbf63b713f75b432fafa0a0e0464ec8381ec76e6efe931ab3" dependencies = [ - "cranelift-entity 0.78.0", + "cranelift-entity 0.80.0", ] [[package]] @@ -1133,17 +1124,17 @@ dependencies = [ [[package]] name = "cranelift-codegen" -version = "0.78.0" +version = "0.80.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe4463c15fa42eee909e61e5eac4866b7c6d22d0d8c621e57a0c5380753bfa8c" +checksum = "489e5d0081f7edff6be12d71282a8bf387b5df64d5592454b75d662397f2d642" dependencies = [ - "cranelift-bforest 0.78.0", - "cranelift-codegen-meta 0.78.0", - "cranelift-codegen-shared 0.78.0", - "cranelift-entity 0.78.0", - "gimli 0.25.0", + "cranelift-bforest 0.80.0", + "cranelift-codegen-meta 0.80.0", + "cranelift-codegen-shared 0.80.0", + "cranelift-entity 0.80.0", + "gimli 0.26.1", "log 0.4.14", - "regalloc 0.0.32", + "regalloc 0.0.33", "smallvec 1.7.0", "target-lexicon 0.12.0", ] @@ -1160,12 +1151,11 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.78.0" +version = "0.80.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793f6a94a053a55404ea16e1700202a88101672b8cd6b4df63e13cde950852bf" +checksum = "d36ee1140371bb0f69100e734b30400157a4adf7b86148dee8b0a438763ead48" dependencies = [ - "cranelift-codegen-shared 0.78.0", - "cranelift-entity 0.78.0", + "cranelift-codegen-shared 0.80.0", ] [[package]] @@ -1176,9 +1166,9 @@ checksum = "6759012d6d19c4caec95793f052613e9d4113e925e7f14154defbac0f1d4c938" [[package]] name = "cranelift-codegen-shared" -version = "0.78.0" +version = "0.80.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44aa1846df275bce5eb30379d65964c7afc63c05a117076e62a119c25fe174be" +checksum = "981da52d8f746af1feb96290c83977ff8d41071a7499e991d8abae0d4869f564" [[package]] name = "cranelift-entity" @@ -1191,9 +1181,9 @@ dependencies = [ [[package]] name = "cranelift-entity" -version = "0.78.0" +version = "0.80.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3a45d8d6318bf8fc518154d9298eab2a8154ec068a8885ff113f6db8d69bb3a" +checksum = "a2906740053dd3bcf95ce53df0fd9b5649c68ae4bd9adada92b406f059eae461" dependencies = [ "serde", ] @@ -1212,11 +1202,11 @@ dependencies = [ [[package]] name = "cranelift-frontend" -version = "0.78.0" +version = "0.80.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e07339bd461766deb7605169de039e01954768ff730fa1254e149001884a8525" +checksum = "b7cb156de1097f567d46bf57a0cd720a72c3e15e1a2bd8b1041ba2fc894471b7" dependencies = [ - "cranelift-codegen 0.78.0", + "cranelift-codegen 0.80.0", "log 0.4.14", "smallvec 1.7.0", "target-lexicon 0.12.0", @@ -1224,24 +1214,24 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.78.0" +version = "0.80.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03e2fca76ff57e0532936a71e3fc267eae6a19a86656716479c66e7f912e3d7b" +checksum = "166028ca0343a6ee7bddac0e70084e142b23f99c701bd6f6ea9123afac1a7a46" dependencies = [ - "cranelift-codegen 0.78.0", + "cranelift-codegen 0.80.0", "libc", "target-lexicon 0.12.0", ] [[package]] name = "cranelift-wasm" -version = "0.78.0" +version = "0.80.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f46fec547a1f8a32c54ea61c28be4f4ad234ad95342b718a9a9adcaadb0c778" +checksum = "5012a1cde0c8b3898770b711490d803018ae9bec2d60674ba0e5b2058a874f80" dependencies = [ - "cranelift-codegen 0.78.0", - "cranelift-entity 0.78.0", - "cranelift-frontend 0.78.0", + "cranelift-codegen 0.80.0", + "cranelift-entity 0.80.0", + "cranelift-frontend 0.80.0", "itertools", "log 0.4.14", "smallvec 1.7.0", @@ -1842,9 +1832,9 @@ checksum = "68b91989ae21441195d7d9b9993a2f9295c7e1a8c96255d8b729accddc124797" [[package]] name = "errno" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa68f2fb9cae9d37c9b2b3584aba698a2e97f72d7aef7b9f7aa71d8b54ce46fe" +checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" dependencies = [ "errno-dragonfly", "libc", @@ -2531,21 +2521,15 @@ dependencies = [ [[package]] name = "gimli" -version = "0.25.0" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0a01e0497841a3b2db4f8afa483cce65f7e96a3498bd6c541734792aeac8fe7" +checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" dependencies = [ "fallible-iterator", "indexmap", "stable_deref_trait", ] -[[package]] -name = "gimli" -version = "0.26.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" - [[package]] name = "git2" version = "0.13.25" @@ -2996,11 +2980,10 @@ dependencies = [ [[package]] name = "io-lifetimes" -version = "0.3.1" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47f5ce4afb9bf504b9f496a3307676bc232122f91a93c4da6d540aa99a0a0e0b" +checksum = "f6ef6787e7f0faedc040f95716bdd0e62bcfcf4ba93da053b62dea2691c13864" dependencies = [ - "rustc_version 0.4.0", "winapi 0.3.9", ] @@ -4015,9 +3998,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.0.28" +version = "0.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "687387ff42ec7ea4f2149035a5675fedb675d26f98db90a1846ac63d3addb5f5" +checksum = "a261afc61b7a5e323933b402ca6a1765183687c614789b1e4db7762ed4230bca" [[package]] name = "lite-json" @@ -7354,9 +7337,9 @@ dependencies = [ [[package]] name = "regalloc" -version = "0.0.32" +version = "0.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6304468554ed921da3d32c355ea107b8d13d7b8996c3adfb7aab48d3bc321f4" +checksum = "7d808cff91dfca7b239d40b972ba628add94892b1d9e19a842aedc5cfae8ab1a" dependencies = [ "log 0.4.14", "rustc-hash", @@ -7481,23 +7464,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "rsix" -version = "0.23.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f64c5788d5aab8b75441499d99576a24eb09f76fb267b36fec7e3d970c66431" -dependencies = [ - "bitflags", - "cc", - "errno", - "io-lifetimes", - "itoa 0.4.8", - "libc", - "linux-raw-sys", - "once_cell", - "rustc_version 0.4.0", -] - [[package]] name = "rustc-demangle" version = "0.1.18" @@ -7535,12 +7501,17 @@ dependencies = [ ] [[package]] -name = "rustc_version" -version = "0.4.0" +name = "rustix" +version = "0.31.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "b2dcfc2778a90e38f56a708bfc90572422e11d6c7ee233d053d1f782cf9df6d2" dependencies = [ - "semver 1.0.4", + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "winapi 0.3.9", ] [[package]] @@ -11583,9 +11554,9 @@ checksum = "98930446519f63d00a836efdc22f67766ceae8dbcc1571379f2bcabc6b2b9abc" [[package]] name = "wasmtime" -version = "0.31.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "311d06b0c49346d1fbf48a17052e844036b95a7753c1afb34e8c0af3f6b5bb13" +checksum = "414be1bc5ca12e755ffd3ff7acc3a6d1979922f8237fc34068b2156cebcc3270" dependencies = [ "anyhow", "backtrace", @@ -11615,9 +11586,9 @@ dependencies = [ [[package]] name = "wasmtime-cache" -version = "0.31.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36147930a4995137dc096e5b17a573b446799be2bbaea433e821ce6a80abe2c5" +checksum = "8b9b4cd1949206fda9241faf8c460a7d797aa1692594d3dd6bc1cbfa57ee20d0" dependencies = [ "anyhow", "base64 0.13.0", @@ -11625,7 +11596,7 @@ dependencies = [ "directories-next", "file-per-thread-logger", "log 0.4.14", - "rsix", + "rustix", "serde", "sha2 0.9.8", "toml", @@ -11635,17 +11606,17 @@ dependencies = [ [[package]] name = "wasmtime-cranelift" -version = "0.31.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3083a47e1ede38aac06a1d9831640d673f9aeda0b82a64e4ce002f3432e2e7" +checksum = "a4693d33725773615a4c9957e4aa731af57b27dca579702d1d8ed5750760f1a9" dependencies = [ "anyhow", - "cranelift-codegen 0.78.0", - "cranelift-entity 0.78.0", - "cranelift-frontend 0.78.0", + "cranelift-codegen 0.80.0", + "cranelift-entity 0.80.0", + "cranelift-frontend 0.80.0", "cranelift-native", "cranelift-wasm", - "gimli 0.25.0", + "gimli 0.26.1", "log 0.4.14", "more-asserts", "object 0.27.1", @@ -11657,14 +11628,13 @@ dependencies = [ [[package]] name = "wasmtime-environ" -version = "0.31.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c2d194b655321053bc4111a1aa4ead552655c8a17d17264bc97766e70073510" +checksum = "5b17e47116a078b9770e6fb86cff8b9a660826623cebcfff251b047c8d8993ef" dependencies = [ "anyhow", - "cfg-if 1.0.0", - "cranelift-entity 0.78.0", - "gimli 0.25.0", + "cranelift-entity 0.80.0", + "gimli 0.26.1", "indexmap", "log 0.4.14", "more-asserts", @@ -11678,24 +11648,21 @@ dependencies = [ [[package]] name = "wasmtime-jit" -version = "0.31.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "864ac8dfe4ce310ac59f16fdbd560c257389cb009ee5d030ac6e30523b023d11" +checksum = "60ea5b380bdf92e32911400375aeefb900ac9d3f8e350bb6ba555a39315f2ee7" dependencies = [ - "addr2line 0.16.0", + "addr2line", "anyhow", "bincode", "cfg-if 1.0.0", - "gimli 0.25.0", - "log 0.4.14", - "more-asserts", + "gimli 0.26.1", "object 0.27.1", "region", - "rsix", + "rustix", "serde", "target-lexicon 0.12.0", "thiserror", - "wasmparser 0.81.0", "wasmtime-environ", "wasmtime-runtime", "winapi 0.3.9", @@ -11703,9 +11670,9 @@ dependencies = [ [[package]] name = "wasmtime-runtime" -version = "0.31.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab97da813a26b98c9abfd3b0c2d99e42f6b78b749c0646344e2e262d212d8c8b" +checksum = "abc7cd79937edd6e238b337608ebbcaf9c086a8457f01dfd598324f7fa56d81a" dependencies = [ "anyhow", "backtrace", @@ -11720,7 +11687,7 @@ dependencies = [ "more-asserts", "rand 0.8.4", "region", - "rsix", + "rustix", "thiserror", "wasmtime-environ", "winapi 0.3.9", @@ -11728,11 +11695,11 @@ dependencies = [ [[package]] name = "wasmtime-types" -version = "0.31.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff94409cc3557bfbbcce6b14520ccd6bd3727e965c0fe68d63ef2c185bf379c6" +checksum = "d9e5e51a461a2cf2b69e1fc48f325b17d78a8582816e18479e8ead58844b23f8" dependencies = [ - "cranelift-entity 0.78.0", + "cranelift-entity 0.80.0", "serde", "thiserror", "wasmparser 0.81.0", diff --git a/client/executor/wasmtime/Cargo.toml b/client/executor/wasmtime/Cargo.toml index 65efc2603509..8b3cd1a58e75 100644 --- a/client/executor/wasmtime/Cargo.toml +++ b/client/executor/wasmtime/Cargo.toml @@ -23,7 +23,7 @@ sp-wasm-interface = { version = "4.1.0-dev", path = "../../../primitives/wasm-in sp-runtime-interface = { version = "4.1.0-dev", path = "../../../primitives/runtime-interface" } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sc-allocator = { version = "4.1.0-dev", path = "../../allocator" } -wasmtime = { version = "0.31.0", default-features = false, features = [ +wasmtime = { version = "0.33.0", default-features = false, features = [ "cache", "cranelift", "jitdump", diff --git a/client/executor/wasmtime/src/runtime.rs b/client/executor/wasmtime/src/runtime.rs index 6300163db50c..6533aa194e4c 100644 --- a/client/executor/wasmtime/src/runtime.rs +++ b/client/executor/wasmtime/src/runtime.rs @@ -344,6 +344,7 @@ fn common_config(semantics: &Semantics) -> std::result::Result Date: Mon, 17 Jan 2022 17:00:17 +0200 Subject: [PATCH 392/695] Switch from `pwasm-utils` to `wasm-instrument` (#10680) * Switch executor to wasm-instrument * Switch pallet-contracts to wasm-instrument --- Cargo.lock | 24 +++++++++---------- client/executor/common/Cargo.toml | 2 +- .../runtime_blob/data_segments_snapshot.rs | 2 +- .../common/src/runtime_blob/runtime_blob.rs | 4 ++-- frame/contracts/Cargo.toml | 4 ++-- frame/contracts/src/benchmarking/code.rs | 18 +++++++------- frame/contracts/src/benchmarking/mod.rs | 2 +- frame/contracts/src/schedule.rs | 10 ++++---- frame/contracts/src/wasm/env_def/macros.rs | 8 +++---- frame/contracts/src/wasm/env_def/mod.rs | 2 +- frame/contracts/src/wasm/prepare.rs | 17 ++++++------- frame/contracts/src/wasm/runtime.rs | 2 +- 12 files changed, 47 insertions(+), 48 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 12b825375631..1a43c9ded813 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5475,7 +5475,6 @@ dependencies = [ "pallet-utility", "parity-scale-codec", "pretty_assertions", - "pwasm-utils", "rand 0.8.4", "rand_pcg 0.3.1", "scale-info", @@ -5486,6 +5485,7 @@ dependencies = [ "sp-runtime", "sp-sandbox", "sp-std", + "wasm-instrument", "wasmi-validation", "wat", ] @@ -6957,17 +6957,6 @@ dependencies = [ "cc", ] -[[package]] -name = "pwasm-utils" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "880b3384fb00b8f6ecccd5d358b93bd2201900ae3daad213791d1864f6441f5c" -dependencies = [ - "byteorder", - "log 0.4.14", - "parity-wasm 0.42.2", -] - [[package]] name = "quick-error" version = "1.2.3" @@ -8094,13 +8083,13 @@ dependencies = [ "derive_more", "environmental", "parity-scale-codec", - "pwasm-utils", "sc-allocator", "sp-core", "sp-maybe-compressed-blob", "sp-serializer", "sp-wasm-interface", "thiserror", + "wasm-instrument", "wasmer", "wasmer-compiler-singlepass", "wasmi", @@ -11306,6 +11295,15 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "wasm-instrument" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e67369bb53d409b67e57ef31797b1b2d628955fc82f86f2ea78bb403acc7c73" +dependencies = [ + "parity-wasm 0.42.2", +] + [[package]] name = "wasm-timer" version = "0.2.5" diff --git a/client/executor/common/Cargo.toml b/client/executor/common/Cargo.toml index 5edf179c056a..8e4b11f8f8fa 100644 --- a/client/executor/common/Cargo.toml +++ b/client/executor/common/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] derive_more = "0.99.16" -pwasm-utils = "0.18.2" +wasm-instrument = "0.1" codec = { package = "parity-scale-codec", version = "2.0.0" } wasmi = "0.9.1" sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } diff --git a/client/executor/common/src/runtime_blob/data_segments_snapshot.rs b/client/executor/common/src/runtime_blob/data_segments_snapshot.rs index 76f2ad2c345e..b44370e681b1 100644 --- a/client/executor/common/src/runtime_blob/data_segments_snapshot.rs +++ b/client/executor/common/src/runtime_blob/data_segments_snapshot.rs @@ -18,8 +18,8 @@ use super::RuntimeBlob; use crate::error::{self, Error}; -use pwasm_utils::parity_wasm::elements::Instruction; use std::mem; +use wasm_instrument::parity_wasm::elements::Instruction; /// This is a snapshot of data segments specialzied for a particular instantiation. /// diff --git a/client/executor/common/src/runtime_blob/runtime_blob.rs b/client/executor/common/src/runtime_blob/runtime_blob.rs index 8318cce7a9ba..d95dcda1a877 100644 --- a/client/executor/common/src/runtime_blob/runtime_blob.rs +++ b/client/executor/common/src/runtime_blob/runtime_blob.rs @@ -17,7 +17,7 @@ // along with this program. If not, see . use crate::error::WasmError; -use pwasm_utils::{ +use wasm_instrument::{ export_mutable_globals, parity_wasm::elements::{deserialize_buffer, serialize, DataSegment, Internal, Module}, }; @@ -84,7 +84,7 @@ impl RuntimeBlob { /// depth of the wasm operand stack. pub fn inject_stack_depth_metering(self, stack_depth_limit: u32) -> Result { let injected_module = - pwasm_utils::stack_height::inject_limiter(self.raw_module, stack_depth_limit).map_err( + wasm_instrument::inject_stack_limiter(self.raw_module, stack_depth_limit).map_err( |e| WasmError::Other(format!("cannot inject the stack limiter: {:?}", e)), )?; diff --git a/frame/contracts/Cargo.toml b/frame/contracts/Cargo.toml index 4067148e13e1..64c1de220155 100644 --- a/frame/contracts/Cargo.toml +++ b/frame/contracts/Cargo.toml @@ -20,7 +20,7 @@ codec = { package = "parity-scale-codec", version = "2.2.0", default-features = ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } log = { version = "0.4", default-features = false } -pwasm-utils = { version = "0.18.2", default-features = false } +wasm-instrument = { version = "0.1", default-features = false } serde = { version = "1", optional = true, features = ["derive"] } smallvec = { version = "1", default-features = false, features = [ "const_generics", @@ -71,7 +71,7 @@ std = [ "frame-benchmarking/std", "frame-support/std", "frame-system/std", - "pwasm-utils/std", + "wasm-instrument/std", "wasmi-validation/std", "pallet-contracts-primitives/std", "pallet-contracts-proc-macro/full", diff --git a/frame/contracts/src/benchmarking/code.rs b/frame/contracts/src/benchmarking/code.rs index d4828871dbbe..4d42349f82a1 100644 --- a/frame/contracts/src/benchmarking/code.rs +++ b/frame/contracts/src/benchmarking/code.rs @@ -26,13 +26,6 @@ use crate::Config; use frame_support::traits::Get; -use pwasm_utils::parity_wasm::{ - builder, - elements::{ - self, BlockType, CustomSection, External, FuncBody, Instruction, Instructions, Module, - Section, ValueType, - }, -}; use sp_core::crypto::UncheckedFrom; use sp_runtime::traits::Hash; use sp_sandbox::{ @@ -40,6 +33,13 @@ use sp_sandbox::{ SandboxEnvironmentBuilder, SandboxMemory, }; use sp_std::{borrow::ToOwned, prelude::*}; +use wasm_instrument::parity_wasm::{ + builder, + elements::{ + self, BlockType, CustomSection, External, FuncBody, Instruction, Instructions, Module, + Section, ValueType, + }, +}; /// The location where to put the genrated code. pub enum Location { @@ -562,10 +562,10 @@ where fn inject_gas_metering(module: Module) -> Module { let schedule = T::Schedule::get(); let gas_rules = schedule.rules(&module); - pwasm_utils::inject_gas_counter(module, &gas_rules, "seal0").unwrap() + wasm_instrument::gas_metering::inject(module, &gas_rules, "seal0").unwrap() } fn inject_stack_metering(module: Module) -> Module { let height = T::Schedule::get().limits.stack_height; - pwasm_utils::stack_height::inject_limiter(module, height).unwrap() + wasm_instrument::inject_stack_limiter(module, height).unwrap() } diff --git a/frame/contracts/src/benchmarking/mod.rs b/frame/contracts/src/benchmarking/mod.rs index a0f5ceb034f7..6d4ae959f31e 100644 --- a/frame/contracts/src/benchmarking/mod.rs +++ b/frame/contracts/src/benchmarking/mod.rs @@ -39,12 +39,12 @@ use codec::Encode; use frame_benchmarking::{account, benchmarks, whitelisted_caller}; use frame_support::weights::Weight; use frame_system::RawOrigin; -use pwasm_utils::parity_wasm::elements::{BlockType, BrTableData, Instruction, ValueType}; use sp_runtime::{ traits::{Bounded, Hash}, Perbill, }; use sp_std::prelude::*; +use wasm_instrument::parity_wasm::elements::{BlockType, BrTableData, Instruction, ValueType}; /// How many batches we do per API benchmark. const API_BENCHMARK_BATCHES: u32 = 20; diff --git a/frame/contracts/src/schedule.rs b/frame/contracts/src/schedule.rs index f3bfaea24277..459bd950ce46 100644 --- a/frame/contracts/src/schedule.rs +++ b/frame/contracts/src/schedule.rs @@ -23,12 +23,12 @@ use crate::{weights::WeightInfo, Config}; use codec::{Decode, Encode}; use frame_support::{weights::Weight, DefaultNoBound}; use pallet_contracts_proc_macro::{ScheduleDebug, WeightDebug}; -use pwasm_utils::{parity_wasm::elements, rules}; use scale_info::TypeInfo; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; use sp_runtime::RuntimeDebug; use sp_std::{marker::PhantomData, vec::Vec}; +use wasm_instrument::{gas_metering, parity_wasm::elements}; /// How many API calls are executed in a single batch. The reason for increasing the amount /// of API calls in batches (per benchmark component increase) is so that the linear regression @@ -652,7 +652,7 @@ struct ScheduleRules<'a, T: Config> { } impl Schedule { - pub(crate) fn rules(&self, module: &elements::Module) -> impl rules::Rules + '_ { + pub(crate) fn rules(&self, module: &elements::Module) -> impl gas_metering::Rules + '_ { ScheduleRules { schedule: &self, params: module @@ -668,7 +668,7 @@ impl Schedule { } } -impl<'a, T: Config> rules::Rules for ScheduleRules<'a, T> { +impl<'a, T: Config> gas_metering::Rules for ScheduleRules<'a, T> { fn instruction_cost(&self, instruction: &elements::Instruction) -> Option { use self::elements::Instruction::*; let w = &self.schedule.instruction_weights; @@ -752,10 +752,10 @@ impl<'a, T: Config> rules::Rules for ScheduleRules<'a, T> { Some(weight) } - fn memory_grow_cost(&self) -> Option { + fn memory_grow_cost(&self) -> gas_metering::MemoryGrowCost { // We benchmarked the memory.grow instruction with the maximum allowed pages. // The cost for growing is therefore already included in the instruction cost. - None + gas_metering::MemoryGrowCost::Free } } diff --git a/frame/contracts/src/wasm/env_def/macros.rs b/frame/contracts/src/wasm/env_def/macros.rs index a50290085df8..aa5a1626681f 100644 --- a/frame/contracts/src/wasm/env_def/macros.rs +++ b/frame/contracts/src/wasm/env_def/macros.rs @@ -28,7 +28,7 @@ macro_rules! convert_args { macro_rules! gen_signature { ( ( $( $params: ty ),* ) ) => ( { - pwasm_utils::parity_wasm::elements::FunctionType::new( + wasm_instrument::parity_wasm::elements::FunctionType::new( convert_args!($($params),*), vec![], ) } @@ -36,7 +36,7 @@ macro_rules! gen_signature { ( ( $( $params: ty ),* ) -> $returns: ty ) => ( { - pwasm_utils::parity_wasm::elements::FunctionType::new( + wasm_instrument::parity_wasm::elements::FunctionType::new( convert_args!($($params),*), vec![{use $crate::wasm::env_def::ConvertibleToWasm; <$returns>::VALUE_TYPE}], ) @@ -220,7 +220,7 @@ macro_rules! define_env { fn can_satisfy( module: &[u8], name: &[u8], - func_type: &pwasm_utils::parity_wasm::elements::FunctionType, + func_type: &wasm_instrument::parity_wasm::elements::FunctionType, ) -> bool { #[cfg(not(feature = "unstable-interface"))] @@ -260,9 +260,9 @@ mod tests { wasm::{runtime::TrapReason, tests::MockExt, Runtime}, Weight, }; - use pwasm_utils::parity_wasm::elements::{FunctionType, ValueType}; use sp_runtime::traits::Zero; use sp_sandbox::{ReturnValue, Value}; + use wasm_instrument::parity_wasm::elements::{FunctionType, ValueType}; struct TestRuntime { value: u32, diff --git a/frame/contracts/src/wasm/env_def/mod.rs b/frame/contracts/src/wasm/env_def/mod.rs index c74af80d3e4e..b4c5ffe81e7c 100644 --- a/frame/contracts/src/wasm/env_def/mod.rs +++ b/frame/contracts/src/wasm/env_def/mod.rs @@ -18,8 +18,8 @@ use super::Runtime; use crate::exec::Ext; -use pwasm_utils::parity_wasm::elements::{FunctionType, ValueType}; use sp_sandbox::Value; +use wasm_instrument::parity_wasm::elements::{FunctionType, ValueType}; #[macro_use] pub mod macros; diff --git a/frame/contracts/src/wasm/prepare.rs b/frame/contracts/src/wasm/prepare.rs index a57e9aabf8bf..70c15cb8c4e6 100644 --- a/frame/contracts/src/wasm/prepare.rs +++ b/frame/contracts/src/wasm/prepare.rs @@ -26,9 +26,11 @@ use crate::{ AccountIdOf, Config, Schedule, }; use codec::{Encode, MaxEncodedLen}; -use pwasm_utils::parity_wasm::elements::{self, External, Internal, MemoryType, Type, ValueType}; use sp_runtime::traits::Hash; use sp_std::prelude::*; +use wasm_instrument::parity_wasm::elements::{ + self, External, Internal, MemoryType, Type, ValueType, +}; /// Imported memory must be located inside this module. The reason for hardcoding is that current /// compiler toolchains might not support specifying other modules than "env" for memory imports. @@ -182,17 +184,16 @@ impl<'a, T: Config> ContractModule<'a, T> { fn inject_gas_metering(self) -> Result { let gas_rules = self.schedule.rules(&self.module); - let contract_module = pwasm_utils::inject_gas_counter(self.module, &gas_rules, "seal0") - .map_err(|_| "gas instrumentation failed")?; + let contract_module = + wasm_instrument::gas_metering::inject(self.module, &gas_rules, "seal0") + .map_err(|_| "gas instrumentation failed")?; Ok(ContractModule { module: contract_module, schedule: self.schedule }) } fn inject_stack_height_metering(self) -> Result { - let contract_module = pwasm_utils::stack_height::inject_limiter( - self.module, - self.schedule.limits.stack_height, - ) - .map_err(|_| "stack height instrumentation failed")?; + let contract_module = + wasm_instrument::inject_stack_limiter(self.module, self.schedule.limits.stack_height) + .map_err(|_| "stack height instrumentation failed")?; Ok(ContractModule { module: contract_module, schedule: self.schedule }) } diff --git a/frame/contracts/src/wasm/runtime.rs b/frame/contracts/src/wasm/runtime.rs index 8b07329e5db4..98d9d9a40cda 100644 --- a/frame/contracts/src/wasm/runtime.rs +++ b/frame/contracts/src/wasm/runtime.rs @@ -29,12 +29,12 @@ use bitflags::bitflags; use codec::{Decode, DecodeAll, Encode, MaxEncodedLen}; use frame_support::{dispatch::DispatchError, ensure, weights::Weight}; use pallet_contracts_primitives::{ExecReturnValue, ReturnFlags}; -use pwasm_utils::parity_wasm::elements::ValueType; use sp_core::{crypto::UncheckedFrom, Bytes}; use sp_io::hashing::{blake2_128, blake2_256, keccak_256, sha2_256}; use sp_runtime::traits::{Bounded, Zero}; use sp_sandbox::SandboxMemory; use sp_std::prelude::*; +use wasm_instrument::parity_wasm::elements::ValueType; /// Every error that can be returned to a contract when it calls any of the host functions. /// From 963ee8a37130f6d76b2859e76164a01607a306cf Mon Sep 17 00:00:00 2001 From: Guillaume Thiolliere Date: Tue, 18 Jan 2022 06:21:19 +0900 Subject: [PATCH 393/695] Add feature: `no-metadata-doc` which removes doc from metadata and `full-metadata` which build metadata with all doc (#10493) * add features to remove or add doc * fmt * add test for event/error/call * fmt --- .gitlab-ci.yml | 2 +- frame/support/Cargo.toml | 6 ++++ frame/support/procedural/Cargo.toml | 1 + .../procedural/src/pallet/expand/call.rs | 4 ++- .../procedural/src/pallet/expand/constants.rs | 4 ++- .../procedural/src/pallet/expand/error.rs | 5 ++- .../procedural/src/pallet/expand/event.rs | 6 ++-- .../procedural/src/pallet/expand/storage.rs | 3 +- .../support/src/storage/types/counted_map.rs | 12 +++++-- frame/support/src/storage/types/double_map.rs | 2 ++ frame/support/src/storage/types/map.rs | 2 ++ frame/support/src/storage/types/nmap.rs | 2 ++ frame/support/src/storage/types/value.rs | 2 ++ frame/support/test/Cargo.toml | 1 + frame/support/test/tests/pallet.rs | 32 +++++++++++++++---- .../test/tests/pallet_compatibility.rs | 4 +++ .../tests/pallet_compatibility_instance.rs | 4 +++ 17 files changed, 76 insertions(+), 16 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 43674da4627a..b68dd303841d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -450,7 +450,7 @@ test-linux-stable: &test-linux script: # this job runs all tests in former runtime-benchmarks, frame-staking and wasmtime tests - time cargo test --workspace --locked --release --verbose --features runtime-benchmarks --manifest-path bin/node/cli/Cargo.toml - - time cargo test -p frame-support-test --features=conditional-storage --manifest-path frame/support/test/Cargo.toml --test pallet # does not reuse cache 1 min 44 sec + - time cargo test -p frame-support-test --features=conditional-storage,no-metadata-docs --manifest-path frame/support/test/Cargo.toml --test pallet # does not reuse cache 1 min 44 sec - SUBSTRATE_TEST_TIMEOUT=1 time cargo test -p substrate-test-utils --release --verbose --locked -- --ignored timeout - sccache -s diff --git a/frame/support/Cargo.toml b/frame/support/Cargo.toml index efc7caab1bd4..a6bbc73f9ddb 100644 --- a/frame/support/Cargo.toml +++ b/frame/support/Cargo.toml @@ -63,3 +63,9 @@ std = [ ] runtime-benchmarks = [] try-runtime = [] +# By default some types have documentation, `no-metadata-docs` allows to reduce the documentation +# in the metadata. +no-metadata-docs = ["frame-support-procedural/no-metadata-docs"] +# By default some types have documentation, `full-metadata-docs` allows to add documentation to +# more types in the metadata. +full-metadata-docs = ["scale-info/docs"] diff --git a/frame/support/procedural/Cargo.toml b/frame/support/procedural/Cargo.toml index 640fe436b185..4e9618b5bc16 100644 --- a/frame/support/procedural/Cargo.toml +++ b/frame/support/procedural/Cargo.toml @@ -24,3 +24,4 @@ syn = { version = "1.0.82", features = ["full"] } [features] default = ["std"] std = [] +no-metadata-docs = [] diff --git a/frame/support/procedural/src/pallet/expand/call.rs b/frame/support/procedural/src/pallet/expand/call.rs index 58c4804558b0..355d4f87d3db 100644 --- a/frame/support/procedural/src/pallet/expand/call.rs +++ b/frame/support/procedural/src/pallet/expand/call.rs @@ -137,6 +137,8 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream { let count = COUNTER.with(|counter| counter.borrow_mut().inc()); let macro_ident = syn::Ident::new(&format!("__is_call_part_defined_{}", count), span); + let capture_docs = if cfg!(feature = "no-metadata-docs") { "never" } else { "always" }; + quote::quote_spanned!(span => #[doc(hidden)] pub mod __substrate_call_check { @@ -164,7 +166,7 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream { )] #[codec(encode_bound())] #[codec(decode_bound())] - #[scale_info(skip_type_params(#type_use_gen), capture_docs = "always")] + #[scale_info(skip_type_params(#type_use_gen), capture_docs = #capture_docs)] #[allow(non_camel_case_types)] pub enum #call_ident<#type_decl_bounded_gen> #where_clause { #[doc(hidden)] diff --git a/frame/support/procedural/src/pallet/expand/constants.rs b/frame/support/procedural/src/pallet/expand/constants.rs index 3f853902010f..1f9526f9cebe 100644 --- a/frame/support/procedural/src/pallet/expand/constants.rs +++ b/frame/support/procedural/src/pallet/expand/constants.rs @@ -79,7 +79,9 @@ pub fn expand_constants(def: &mut Def) -> proc_macro2::TokenStream { let const_type = &const_.type_; let ident_str = format!("{}", const_.metadata_name.unwrap_or(const_.ident)); - let doc = const_.doc.clone().into_iter(); + let no_docs = vec![]; + let doc = if cfg!(feature = "no-metadata-docs") { &no_docs } else { &const_.doc }; + let default_byte_impl = &const_.default_byte_impl; quote::quote!({ diff --git a/frame/support/procedural/src/pallet/expand/error.rs b/frame/support/procedural/src/pallet/expand/error.rs index 3e6247e77f8c..4cf572c1797f 100644 --- a/frame/support/procedural/src/pallet/expand/error.rs +++ b/frame/support/procedural/src/pallet/expand/error.rs @@ -58,12 +58,15 @@ pub fn expand_error(def: &mut Def) -> proc_macro2::TokenStream { }; error_item.variants.insert(0, phantom_variant); + + let capture_docs = if cfg!(feature = "no-metadata-docs") { "never" } else { "always" }; + // derive TypeInfo for error metadata error_item .attrs .push(syn::parse_quote!( #[derive(#frame_support::scale_info::TypeInfo)] )); error_item.attrs.push(syn::parse_quote!( - #[scale_info(skip_type_params(#type_use_gen), capture_docs = "always")] + #[scale_info(skip_type_params(#type_use_gen), capture_docs = #capture_docs)] )); if get_doc_literals(&error_item.attrs).is_empty() { diff --git a/frame/support/procedural/src/pallet/expand/event.rs b/frame/support/procedural/src/pallet/expand/event.rs index 79a7acaf66a5..acd60ab959c6 100644 --- a/frame/support/procedural/src/pallet/expand/event.rs +++ b/frame/support/procedural/src/pallet/expand/event.rs @@ -117,9 +117,11 @@ pub fn expand_event(def: &mut Def) -> proc_macro2::TokenStream { )] )); - // skip requirement for type params to implement `TypeInfo`, and require docs capture + let capture_docs = if cfg!(feature = "no-metadata-docs") { "never" } else { "always" }; + + // skip requirement for type params to implement `TypeInfo`, and set docs capture event_item.attrs.push(syn::parse_quote!( - #[scale_info(skip_type_params(#event_use_gen), capture_docs = "always")] + #[scale_info(skip_type_params(#event_use_gen), capture_docs = #capture_docs)] )); let deposit_event = if let Some(deposit_event) = &event.deposit_event { diff --git a/frame/support/procedural/src/pallet/expand/storage.rs b/frame/support/procedural/src/pallet/expand/storage.rs index 9d936dd50344..f45223c1cc84 100644 --- a/frame/support/procedural/src/pallet/expand/storage.rs +++ b/frame/support/procedural/src/pallet/expand/storage.rs @@ -234,7 +234,8 @@ pub fn expand_storages(def: &mut Def) -> proc_macro2::TokenStream { let pallet_ident = &def.pallet_struct.pallet; let entries_builder = def.storages.iter().map(|storage| { - let docs = &storage.docs; + let no_docs = vec![]; + let docs = if cfg!(feature = "no-metadata-docs") { &no_docs } else { &storage.docs }; let ident = &storage.ident; let gen = &def.type_use_generics(storage.attr_span); diff --git a/frame/support/src/storage/types/counted_map.rs b/frame/support/src/storage/types/counted_map.rs index 341dedaef0ba..0f98b13282a7 100644 --- a/frame/support/src/storage/types/counted_map.rs +++ b/frame/support/src/storage/types/counted_map.rs @@ -417,7 +417,11 @@ where fn build_metadata(docs: Vec<&'static str>, entries: &mut Vec) { ::Map::build_metadata(docs, entries); CounterFor::::build_metadata( - vec![&"Counter for the related counted storage map"], + if cfg!(feature = "no-metadata-docs") { + vec![] + } else { + vec![&"Counter for the related counted storage map"] + }, entries, ); } @@ -1054,7 +1058,11 @@ mod test { modifier: StorageEntryModifier::Default, ty: StorageEntryType::Plain(scale_info::meta_type::()), default: vec![0, 0, 0, 0], - docs: vec!["Counter for the related counted storage map"], + docs: if cfg!(feature = "no-metadata-docs") { + vec![] + } else { + vec!["Counter for the related counted storage map"] + }, }, ] ); diff --git a/frame/support/src/storage/types/double_map.rs b/frame/support/src/storage/types/double_map.rs index 1a4d979d98f8..07da0f2239b3 100644 --- a/frame/support/src/storage/types/double_map.rs +++ b/frame/support/src/storage/types/double_map.rs @@ -530,6 +530,8 @@ where MaxValues: Get>, { fn build_metadata(docs: Vec<&'static str>, entries: &mut Vec) { + let docs = if cfg!(feature = "no-metadata-docs") { vec![] } else { docs }; + let entry = StorageEntryMetadata { name: Prefix::STORAGE_PREFIX, modifier: QueryKind::METADATA, diff --git a/frame/support/src/storage/types/map.rs b/frame/support/src/storage/types/map.rs index e769daa49036..d0b82e1a84e5 100644 --- a/frame/support/src/storage/types/map.rs +++ b/frame/support/src/storage/types/map.rs @@ -352,6 +352,8 @@ where MaxValues: Get>, { fn build_metadata(docs: Vec<&'static str>, entries: &mut Vec) { + let docs = if cfg!(feature = "no-metadata-docs") { vec![] } else { docs }; + let entry = StorageEntryMetadata { name: Prefix::STORAGE_PREFIX, modifier: QueryKind::METADATA, diff --git a/frame/support/src/storage/types/nmap.rs b/frame/support/src/storage/types/nmap.rs index 30e6fb563788..03f15e335389 100755 --- a/frame/support/src/storage/types/nmap.rs +++ b/frame/support/src/storage/types/nmap.rs @@ -451,6 +451,8 @@ where MaxValues: Get>, { fn build_metadata(docs: Vec<&'static str>, entries: &mut Vec) { + let docs = if cfg!(feature = "no-metadata-docs") { vec![] } else { docs }; + let entry = StorageEntryMetadata { name: Prefix::STORAGE_PREFIX, modifier: QueryKind::METADATA, diff --git a/frame/support/src/storage/types/value.rs b/frame/support/src/storage/types/value.rs index a368988f378b..f145e9fb3041 100644 --- a/frame/support/src/storage/types/value.rs +++ b/frame/support/src/storage/types/value.rs @@ -210,6 +210,8 @@ where OnEmpty: crate::traits::Get + 'static, { fn build_metadata(docs: Vec<&'static str>, entries: &mut Vec) { + let docs = if cfg!(feature = "no-metadata-docs") { vec![] } else { docs }; + let entry = StorageEntryMetadata { name: Prefix::STORAGE_PREFIX, modifier: QueryKind::METADATA, diff --git a/frame/support/test/Cargo.toml b/frame/support/test/Cargo.toml index 975e0830ab0e..f7275cbe2e85 100644 --- a/frame/support/test/Cargo.toml +++ b/frame/support/test/Cargo.toml @@ -52,3 +52,4 @@ try-runtime = ["frame-support/try-runtime"] conditional-storage = [] # Disable ui tests disable-ui-tests = [] +no-metadata-docs = ["frame-support/no-metadata-docs"] diff --git a/frame/support/test/tests/pallet.rs b/frame/support/test/tests/pallet.rs index 59b581eda58e..5f9e886dbb67 100644 --- a/frame/support/test/tests/pallet.rs +++ b/frame/support/test/tests/pallet.rs @@ -1100,6 +1100,14 @@ fn migrate_from_pallet_version_to_storage_version() { fn metadata() { use frame_support::metadata::*; + fn maybe_docs(doc: Vec<&'static str>) -> Vec<&'static str> { + if cfg!(feature = "no-metadata-docs") { + vec![] + } else { + doc + } + } + let pallets = vec![ PalletMetadata { index: 1, @@ -1269,7 +1277,7 @@ fn metadata() { modifier: StorageEntryModifier::Default, ty: StorageEntryType::Plain(meta_type::()), default: vec![0, 0, 0, 0], - docs: vec!["Counter for the related counted storage map"], + docs: maybe_docs(vec!["Counter for the related counted storage map"]), }, StorageEntryMetadata { name: "Unbounded", @@ -1287,13 +1295,13 @@ fn metadata() { name: "MyGetParam", ty: meta_type::(), value: vec![10, 0, 0, 0], - docs: vec![" Some comment", " Some comment"], + docs: maybe_docs(vec![" Some comment", " Some comment"]), }, PalletConstantMetadata { name: "MyGetParam2", ty: meta_type::(), value: vec![11, 0, 0, 0], - docs: vec![" Some comment", " Some comment"], + docs: maybe_docs(vec![" Some comment", " Some comment"]), }, PalletConstantMetadata { name: "MyGetParam3", @@ -1305,19 +1313,19 @@ fn metadata() { name: "some_extra", ty: meta_type::(), value: vec![100, 0, 0, 0, 0, 0, 0, 0], - docs: vec![" Some doc", " Some doc"], + docs: maybe_docs(vec![" Some doc", " Some doc"]), }, PalletConstantMetadata { name: "some_extra_extra", ty: meta_type::(), value: vec![0, 0, 0, 0, 0, 0, 0, 0], - docs: vec![" Some doc"], + docs: maybe_docs(vec![" Some doc"]), }, PalletConstantMetadata { name: "SomeExtraRename", ty: meta_type::(), value: vec![0, 0, 0, 0, 0, 0, 0, 0], - docs: vec![" Some doc"], + docs: maybe_docs(vec![" Some doc"]), }, ], error: Some(PalletErrorMetadata { ty: meta_type::>() }), @@ -1351,7 +1359,7 @@ fn metadata() { modifier: StorageEntryModifier::Default, ty: StorageEntryType::Plain(meta_type::()), default: vec![0, 0, 0, 0], - docs: vec!["Counter for the related counted storage map"], + docs: maybe_docs(vec!["Counter for the related counted storage map"]), }, ], }), @@ -1362,6 +1370,16 @@ fn metadata() { }, ]; + let empty_doc = pallets[0].event.as_ref().unwrap().ty.type_info().docs().is_empty() && + pallets[0].error.as_ref().unwrap().ty.type_info().docs().is_empty() && + pallets[0].calls.as_ref().unwrap().ty.type_info().docs().is_empty(); + + if cfg!(feature = "no-metadata-docs") { + assert!(empty_doc) + } else { + assert!(!empty_doc) + } + let extrinsic = ExtrinsicMetadata { ty: meta_type::(), version: 4, diff --git a/frame/support/test/tests/pallet_compatibility.rs b/frame/support/test/tests/pallet_compatibility.rs index dc76f1fcbf03..339a8b6b0924 100644 --- a/frame/support/test/tests/pallet_compatibility.rs +++ b/frame/support/test/tests/pallet_compatibility.rs @@ -15,6 +15,10 @@ // See the License for the specific language governing permissions and // limitations under the License. +// Old macros don't support the flag `no-metadata-docs` so the result differs when the feature is +// activated. +#![cfg(not(feature = "no-metadata-docs"))] + use frame_support::traits::{ConstU32, ConstU64}; pub trait SomeAssociation { diff --git a/frame/support/test/tests/pallet_compatibility_instance.rs b/frame/support/test/tests/pallet_compatibility_instance.rs index 80ab3c2267fd..4fe577f520fa 100644 --- a/frame/support/test/tests/pallet_compatibility_instance.rs +++ b/frame/support/test/tests/pallet_compatibility_instance.rs @@ -15,6 +15,10 @@ // See the License for the specific language governing permissions and // limitations under the License. +// Old macros don't support the flag `no-metadata-docs` so the result differs when the feature is +// activated. +#![cfg(not(feature = "no-metadata-docs"))] + use frame_support::traits::{ConstU32, ConstU64}; mod pallet_old { From 584d094b3cc46eeea29917b3cd3be77aec0cda7b Mon Sep 17 00:00:00 2001 From: driemworks Date: Mon, 17 Jan 2022 16:45:18 -0600 Subject: [PATCH 394/695] update extrinsics, call iris assets from iris session --- .../pallets/iris-assets/src/lib.rs | 338 +++++------------- .../pallets/iris-session/src/lib.rs | 195 +++++----- bin/node-template/runtime/src/lib.rs | 7 +- useful commands.txt | 170 +++++++++ 4 files changed, 375 insertions(+), 335 deletions(-) create mode 100644 useful commands.txt diff --git a/bin/node-template/pallets/iris-assets/src/lib.rs b/bin/node-template/pallets/iris-assets/src/lib.rs index 91487292d002..ad20023c6cec 100644 --- a/bin/node-template/pallets/iris-assets/src/lib.rs +++ b/bin/node-template/pallets/iris-assets/src/lib.rs @@ -97,6 +97,14 @@ pub enum DataCommand { CatBytes(AccountId, Vec, AccountId), } +#[derive(Encode, Decode, RuntimeDebug, PartialEq, TypeInfo)] +pub struct StoragePool { + max_redundancy: u32, + candidate_storage_providers: Vec, + current_session_storage_providers: Vec, + owner: AccountId, +} + pub use pallet::*; #[cfg(test)] @@ -139,17 +147,17 @@ pub mod pallet { #[pallet::generate_store(pub(super) trait Store)] pub struct Pallet(_); - // /// map the ipfs public key to a list of multiaddresses - // /// this could be moved to the session pallet - // #[pallet::storage] - // #[pallet::getter(fn bootstrap_nodes)] - // pub(super) type BootstrapNodes = StorageMap< - // _, - // Blake2_128Concat, - // Vec, - // Vec, - // ValueQuery, - // >; + /// map the ipfs public key to a list of multiaddresses + /// this could be moved to the session pallet + #[pallet::storage] + #[pallet::getter(fn bootstrap_nodes)] + pub(super) type BootstrapNodes = StorageMap< + _, + Blake2_128Concat, + Vec, + Vec, + ValueQuery, + >; /// A queue of data to publish or obtain on IPFS. #[pallet::storage] @@ -180,6 +188,16 @@ pub mod pallet { ValueQuery, >; + // /// maps an asset id to a CID + // #[pallet::storage] + // #[pallet::getter(fn asset_class_config)] + // pub(super) type AssetClassConfig = StorageMap< + // _, + // Blake2_128Concat, + // T::AssetId, + // Vec, + // >; + /// Store the map associated a node with the assets to which they have access /// /// asset_owner_accountid -> CID -> asset_class_owner_accountid @@ -195,6 +213,15 @@ pub mod pallet { ValueQuery, >; + #[pallet::storage] + #[pallet::getter(fn storage_pool_config)] + pub(super) type StoragePoolConfig = StorageMap< + _, + Blake2_128Concat, + T::AssetId, + StoragePool, + >; + #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { @@ -210,6 +237,8 @@ pub mod pallet { DataReady(T::AccountId), /// A node has published ipfs identity results on chain PublishedIdentity(T::AccountId), + /// a storage pool was configured succesfully for some asset class + StoragePoolConfigurationSuccess(T::AccountId, T::AssetId), } #[pallet::error] @@ -366,24 +395,24 @@ pub mod pallet { Ok(()) } - // /// Should only be callable by OCWs (TODO) - // /// Submit the results of an `ipfs identity` call to be stored on chain - // /// - // /// * origin: a validator node - // /// * public_key: The IPFS node's public key - // /// * multiaddresses: A vector of multiaddresses associate with the public key - // /// - // #[pallet::weight(0)] - // pub fn submit_ipfs_identity( - // origin: OriginFor, - // public_key: Vec, - // multiaddresses: Vec, - // ) -> DispatchResult { - // let who = ensure_signed(origin)?; - // >::insert(public_key.clone(), multiaddresses.clone()); - // Self::deposit_event(Event::PublishedIdentity(who.clone())); - // Ok(()) - // } + /// Should only be callable by OCWs (TODO) + /// Submit the results of an `ipfs identity` call to be stored on chain + /// + /// * origin: a validator node + /// * public_key: The IPFS node's public key + /// * multiaddresses: A vector of multiaddresses associate with the public key + /// + #[pallet::weight(0)] + pub fn submit_ipfs_identity( + origin: OriginFor, + public_key: Vec, + multiaddresses: Vec, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + >::insert(public_key.clone(), multiaddresses.clone()); + Self::deposit_event(Event::PublishedIdentity(who.clone())); + Ok(()) + } /// Should only be callable by OCWs (TODO) /// Submit the results onchain to notify a beneficiary that their data is available: TODO: how to safely share host? spam protection on rpc endpoints? @@ -432,228 +461,47 @@ pub mod pallet { Self::deposit_event(Event::AssetCreated(asset_id.clone())); Ok(()) } + + #[pallet::weight(0)] + pub fn configure_storage_pool( + origin: OriginFor, + asset_id: T::AssetId, + max_redundancy: u32, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + // TODO: Ensure asset is owned by origin -> maybe restructure runtime storage? + let new_sp_config = StoragePool { + max_redundancy: max_redundancy, + candidate_storage_providers: Vec::new(), + current_session_storage_providers: Vec::new(), + owner: who.clone(), + }; + >::insert(asset_id.clone(), new_sp_config); + Self::deposit_event( + Event::StoragePoolConfigurationSuccess( + who.clone(), asset_id.clone())); + Ok(()) + } + + #[pallet::weight(0)] + pub fn try_add_candidate_storage_provider( + origin: OriginFor, + pool_id: T::AssetId, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + + Ok(()) + } } } impl Pallet { - // /// implementation for RPC runtime aPI to retrieve bytes from the node's local storage - // /// - // /// * public_key: The account's public key as bytes - // /// * signature: The signer's signature as bytes - // /// * message: The signed message as bytes - // /// - // pub fn retrieve_bytes( - // _public_key: Bytes, - // _signature: Bytes, - // message: Bytes, - // ) -> Bytes { - // // TODO: Verify signature, update offchain storage keys... - // let message_vec: Vec = message.to_vec(); - // if let Some(data) = sp_io::offchain::local_storage_get(StorageKind::PERSISTENT, &message_vec) { - // Bytes(data.clone()) - // } else { - // Bytes(Vec::new()) - // } - // } - - // /// send a request to the local IPFS node; can only be called be an off-chain worker - // fn ipfs_request( - // req: IpfsRequest, - // deadline: impl Into>, - // ) -> Result> { - // let ipfs_request = ipfs::PendingRequest::new(req).map_err(|_| Error::::CantCreateRequest)?; - // ipfs_request.try_wait(deadline) - // .map_err(|_| Error::::RequestTimeout)? - // .map(|r| r.response) - // .map_err(|e| { - // if let ipfs::Error::IoError(err) = e { - // log::error!("IPFS: request failed: {}", str::from_utf8(&err).unwrap()); - // } else { - // log::error!("IPFS: request failed: {:?}", e); - // } - // Error::::RequestFailed - // }) - // } - // /// manage connection to the iris ipfs swarm - // /// - // /// If the node is already a bootstrap node, do nothing. Otherwise submits a signed tx - // /// containing the public key and multiaddresses of the embedded ipfs node. - // /// - // /// Returns an error if communication with the embedded IPFS fails - // fn connection_housekeeping() -> Result<(), Error> { - // let deadline = Some(timestamp().add(Duration::from_millis(5_000))); - - // let (public_key, addrs) = if let IpfsResponse::Identity(public_key, addrs) = Self::ipfs_request(IpfsRequest::Identity, deadline)? { - // (public_key, addrs) - // } else { - // unreachable!("only `Identity` is a valid response type."); - // }; - - // if !>::contains_key(public_key.clone()) { - // if let Some(bootstrap_node) = &>::iter().nth(0) { - // if let Some(bootnode_maddr) = bootstrap_node.1.clone().pop() { - // if let IpfsResponse::Success = Self::ipfs_request(IpfsRequest::Connect(bootnode_maddr.clone()), deadline)? { - // log::info!("Succesfully connected to a bootstrap node: {:?}", &bootnode_maddr.0); - // } else { - // log::info!("Failed to connect to the bootstrap node with multiaddress: {:?}", &bootnode_maddr.0); - // // TODO: this should probably be some recursive function? but we should never exceed a depth of 2 so maybe not - // if let Some(next_bootnode_maddr) = bootstrap_node.1.clone().pop() { - // if let IpfsResponse::Success = Self::ipfs_request(IpfsRequest::Connect(next_bootnode_maddr.clone()), deadline)? { - // log::info!("Succesfully connected to a bootstrap node: {:?}", &next_bootnode_maddr.0); - // } else { - // log::info!("Failed to connect to the bootstrap node with multiaddress: {:?}", &next_bootnode_maddr.0); - // } - // } - // } - // } - // } - // // TODO: should create func to encompass the below logic - // let signer = Signer::::all_accounts(); - // if !signer.can_sign() { - // log::error!( - // "No local accounts available. Consider adding one via `author_insertKey` RPC.", - // ); - // } - - // let results = signer.send_signed_transaction(|_account| { - // Call::submit_ipfs_identity{ - // public_key: public_key.clone(), - // multiaddresses: addrs.clone(), - // } - // }); - - // for (_, res) in &results { - // match res { - // Ok(()) => log::info!("Submitted ipfs identity results"), - // Err(e) => log::error!("Failed to submit transaction: {:?}", e), - // } - // } - - // } + // fn try_add_candidate_storage_provider( + // pool_id: T::AssetId, + // candidate_storage_provider: T::AccountId, + // ) -> Result<(), Error> { // Ok(()) // } - // /// process any requests in the DataQueue - // fn handle_data_requests() -> Result<(), Error> { - // let data_queue = DataQueue::::get(); - // let len = data_queue.len(); - // if len != 0 { - // log::info!("IPFS: {} entr{} in the data queue", len, if len == 1 { "y" } else { "ies" }); - // } - // // TODO: Needs refactoring - // let deadline = Some(timestamp().add(Duration::from_millis(5_000))); - // for cmd in data_queue.into_iter() { - // match cmd { - // DataCommand::AddBytes(addr, cid, admin, _name, id, balance) => { - // Self::ipfs_request(IpfsRequest::Connect(addr.clone()), deadline)?; - // log::info!( - // "IPFS: connected to {}", - // str::from_utf8(&addr.0).expect("our own calls can be trusted to be UTF-8; qed") - // ); - // match Self::ipfs_request(IpfsRequest::CatBytes(cid.clone()), deadline) { - // Ok(IpfsResponse::CatBytes(data)) => { - // log::info!("IPFS: fetched data"); - // Self::ipfs_request(IpfsRequest::Disconnect(addr.clone()), deadline)?; - // log::info!( - // "IPFS: disconnected from {}", - // str::from_utf8(&addr.0).expect("our own calls can be trusted to be UTF-8; qed") - // ); - // match Self::ipfs_request(IpfsRequest::AddBytes(data.clone()), deadline) { - // Ok(IpfsResponse::AddBytes(new_cid)) => { - // log::info!( - // "IPFS: added data with Cid {}", - // str::from_utf8(&new_cid).expect("our own IPFS node can be trusted here; qed") - // ); - // let signer = Signer::::all_accounts(); - // if !signer.can_sign() { - // log::error!( - // "No local accounts available. Consider adding one via `author_insertKey` RPC.", - // ); - // } - // let results = signer.send_signed_transaction(|_account| { - // Call::submit_ipfs_add_results{ - // admin: admin.clone(), - // cid: new_cid.clone(), - // id: id.clone(), - // balance: balance.clone(), - // } - // }); - - // for (_, res) in &results { - // match res { - // Ok(()) => log::info!("Submitted ipfs results"), - // Err(e) => log::error!("Failed to submit transaction: {:?}", e), - // } - // } - // }, - // Ok(_) => unreachable!("only AddBytes can be a response for that request type."), - // Err(e) => log::error!("IPFS: add error: {:?}", e), - // } - // }, - // Ok(_) => unreachable!("only CatBytes can be a response for that request type."), - // Err(e) => log::error!("IPFS: cat error: {:?}", e), - // } - // }, - // DataCommand::CatBytes(owner, cid, recipient) => { - // ensure!(AssetClassOwnership::::contains_key(owner.clone(), cid.clone()), Error::::NoSuchOwnedContent); - // let asset_id = AssetClassOwnership::::get(owner.clone(), cid.clone()); - // let balance = >::balance(asset_id.clone(), recipient.clone()); - // let balance_primitive = TryInto::::try_into(balance).ok(); - // ensure!(balance_primitive != Some(0), Error::::InsufficientBalance); - // match Self::ipfs_request(IpfsRequest::CatBytes(cid.clone()), deadline) { - // Ok(IpfsResponse::CatBytes(data)) => { - // log::info!("IPFS: Fetched data from IPFS."); - // // add to offchain index - // sp_io::offchain::local_storage_set( - // StorageKind::PERSISTENT, - // &cid, - // &data, - // ); - // let signer = Signer::::all_accounts(); - // if !signer.can_sign() { - // log::error!( - // "No local accounts available. Consider adding one via `author_insertKey` RPC.", - // ); - // } - // let results = signer.send_signed_transaction(|_account| { - // Call::submit_rpc_ready { - // beneficiary: recipient.clone(), - // } - // }); - - // for (_, res) in &results { - // match res { - // Ok(()) => log::info!("Submitted ipfs results"), - // Err(e) => log::error!("Failed to submit transaction: {:?}", e), - // } - // } - // }, - // Ok(_) => unreachable!("only CatBytes can be a response for that request type."), - // Err(e) => log::error!("IPFS: cat error: {:?}", e), - // } - // } - // } - // } - - // Ok(()) - // } - - // fn print_metadata() -> Result<(), Error> { - // let deadline = Some(timestamp().add(Duration::from_millis(5_000))); - - // let peers = if let IpfsResponse::Peers(peers) = Self::ipfs_request(IpfsRequest::Peers, deadline)? { - // peers - // } else { - // unreachable!("only Peers can be a response for that request type; qed"); - // }; - // let peer_count = peers.len(); - - // log::info!( - // "IPFS: currently connected to {} peer{}", - // peer_count, - // if peer_count == 1 { "" } else { "s" }, - // ); - // Ok(()) - // } } \ No newline at end of file diff --git a/bin/node-template/pallets/iris-session/src/lib.rs b/bin/node-template/pallets/iris-session/src/lib.rs index 39d8add80299..0e35dfc42182 100644 --- a/bin/node-template/pallets/iris-session/src/lib.rs +++ b/bin/node-template/pallets/iris-session/src/lib.rs @@ -56,7 +56,13 @@ pub const LOG_TARGET: &'static str = "runtime::iris-session"; #[frame_support::pallet] pub mod pallet { use super::*; - use frame_system::pallet_prelude::*; + use frame_system::{ + pallet_prelude::*, + offchain::{ + AppCrypto, + CreateSignedTransaction, + } + }; /// Configure the pallet by specifying the parameters and types on which it /// depends. @@ -64,13 +70,15 @@ pub mod pallet { pub trait Config: frame_system::Config + pallet_session::Config + pallet_iris_assets::Config { /// The Event type. type Event: From> + IsType<::Event>; - + /// the overarching call type + type Call: From>; /// Origin for adding or removing a validator. type AddRemoveOrigin: EnsureOrigin; - /// Minimum number of validators to leave in the validator set during /// auto removal. type MinAuthorities: Get; + /// the authority id used for sending signed txs + type AuthorityId: AppCrypto; } #[pallet::pallet] @@ -110,6 +118,8 @@ pub mod pallet { ValidatorRemovalInitiated(T::AccountId), /// Validator published their ipfs public key and maddrs PublishedIdentity(T::AccountId), + /// A validator requested to join a storage pool + RequestJoinStoragePoolSuccess(T::AccountId, T::AssetId), } // Errors inform users that something went wrong. @@ -129,6 +139,10 @@ pub mod pallet { RequestTimeout, /// the request to IPFS failed RequestFailed, + /// the specified asset id does not correspond to any owned content + NoSuchOwnedContent, + /// the nodes balance is insufficient to complete this operation + InsufficientBalance, } #[pallet::hooks] @@ -229,24 +243,23 @@ pub mod pallet { Ok(()) } - /// Should only be callable by OCWs (TODO) - /// Submit the results of an `ipfs identity` call to be stored on chain - /// - /// * origin: a validator node - /// * public_key: The IPFS node's public key - /// * multiaddresses: A vector of multiaddresses associate with the public key - /// - #[pallet::weight(0)] - pub fn submit_ipfs_identity( - origin: OriginFor, - public_key: Vec, - multiaddresses: Vec, - ) -> DispatchResult { - let who = ensure_signed(origin)?; - BootstrapNodes::::insert(public_key.clone(), multiaddresses.clone()); - Self::deposit_event(Event::PublishedIdentity(who.clone())); - Ok(()) - } + #[pallet::weight(0)] + pub fn request_join_storage_pool( + origin: OriginFor, + pool_owner: ::Source, + pool_id: T::AssetId, + ) -> DispatchResult { + // submit a request to join a storage pool in the next session + let who = ensure_signed(origin)?; + let new_origin = system::RawOrigin::Signed(who.clone()).into(); + >::try_add_candidate_storage_provider( + new_origin, + pool_id.clone(), + )?; + + Self::deposit_event(Event::RequestJoinStoragePoolSuccess(who.clone(), pool_id.clone())); + Ok(()) + } } } @@ -296,6 +309,7 @@ impl Pallet { let approved_set: BTreeSet<_> = >::get().into_iter().collect(); ensure!(!approved_set.contains(&validator_id), Error::::Duplicate); >::mutate(|v| v.push(validator_id.clone())); + // In storage pool -> move from candidate storage provider to storage provider Ok(()) } @@ -381,7 +395,9 @@ impl Pallet { fn connection_housekeeping() -> Result<(), Error> { let deadline = Some(timestamp().add(Duration::from_millis(5_000))); - let (public_key, addrs) = if let IpfsResponse::Identity(public_key, addrs) = Self::ipfs_request(IpfsRequest::Identity, deadline)? { + let (public_key, addrs) = + if let IpfsResponse::Identity(public_key, addrs) = + Self::ipfs_request(IpfsRequest::Identity, deadline)? { (public_key, addrs) } else { unreachable!("only `Identity` is a valid response type."); @@ -396,7 +412,8 @@ impl Pallet { log::info!("Failed to connect to the bootstrap node with multiaddress: {:?}", &bootnode_maddr.0); // TODO: this should probably be some recursive function? but we should never exceed a depth of 2 so maybe not if let Some(next_bootnode_maddr) = bootstrap_node.1.clone().pop() { - if let IpfsResponse::Success = Self::ipfs_request(IpfsRequest::Connect(next_bootnode_maddr.clone()), deadline)? { + if let IpfsResponse::Success + = Self::ipfs_request(IpfsRequest::Connect(next_bootnode_maddr.clone()), deadline)? { log::info!("Succesfully connected to a bootstrap node: {:?}", &next_bootnode_maddr.0); } else { log::info!("Failed to connect to the bootstrap node with multiaddress: {:?}", &next_bootnode_maddr.0); @@ -405,34 +422,35 @@ impl Pallet { } } } - let signer = Signer::::all_accounts(); - if !signer.can_sign() { - log::error!( - "No local accounts available. Consider adding one via `author_insertKey` RPC.", - ); - } + // let signer = Signer::::AuthorityId>::all_accounts(); + // if !signer.can_sign() { + // log::error!( + // "No local accounts available. Consider adding one via `author_insertKey` RPC.", + // ); + // } - let results = signer.send_signed_transaction(|_account| { - Call::submit_ipfs_identity{ - public_key: public_key.clone(), - multiaddresses: addrs.clone(), - } - }); + // let results = signer.send_signed_transaction(|_account| { + // pallet_iris_assets::Call::submit_ipfs_identity { + // public_key: public_key.clone(), + // multiaddresses: addrs.clone(), + // } + // }); - for (_, res) in &results { - match res { - Ok(()) => log::info!("Submitted ipfs identity results"), - Err(e) => log::error!("Failed to submit transaction: {:?}", e), - } - } + // for (_, res) in &results { + // match res { + // Ok(()) => log::info!("Submitted ipfs identity results"), + // Err(e) => log::error!("Failed to submit transaction: {:?}", e), + // } + // } } Ok(()) + } /// process any requests in the DataQueue fn handle_data_requests() -> Result<(), Error> { - let data_queue = >::DataQueue::::get(); + let data_queue = >::data_queue(); let len = data_queue.len(); if len != 0 { log::info!("IPFS: {} entr{} in the data queue", len, if len == 1 { "y" } else { "ies" }); @@ -461,14 +479,20 @@ impl Pallet { "IPFS: added data with Cid {}", str::from_utf8(&new_cid).expect("our own IPFS node can be trusted here; qed") ); - let signer = Signer::::all_accounts(); + let signer = Signer::::AuthorityId>::all_accounts(); if !signer.can_sign() { log::error!( "No local accounts available. Consider adding one via `author_insertKey` RPC.", ); } let results = signer.send_signed_transaction(|_account| { - Call::submit_ipfs_add_results{ + // Ca::submit_ipfs_add_results{ + // admin: admin.clone(), + // cid: new_cid.clone(), + // id: id.clone(), + // balance: balance.clone(), + // } + pallet_iris_assets::Call::submit_ipfs_add_results{ admin: admin.clone(), cid: new_cid.clone(), id: id.clone(), @@ -492,50 +516,47 @@ impl Pallet { } }, DataCommand::CatBytes(owner, cid, recipient) => { - ensure!( - >::AssetClassOwnership::::contains_key( - owner.clone(), cid.clone() - ), - >::Error::::NoSuchOwnedContent - ); - - let asset_id = >::AssetClassOwnership::::get(owner.clone(), cid.clone()); - // TODO: Don't want to also depend on the assets pallet here, need to fold this into the iris-assets runtime - let balance = >::balance(asset_id.clone(), recipient.clone()); - let balance_primitive = TryInto::::try_into(balance).ok(); + if let asset_id = >::asset_class_ownership( + owner.clone(), cid.clone() + ) { + let balance = >::balance(asset_id.clone(), recipient.clone()); + let balance_primitive = TryInto::::try_into(balance).ok(); - ensure!(balance_primitive != Some(0), >::Error::::InsufficientBalance); - match Self::ipfs_request(IpfsRequest::CatBytes(cid.clone()), deadline) { - Ok(IpfsResponse::CatBytes(data)) => { - log::info!("IPFS: Fetched data from IPFS."); - // add to offchain index - sp_io::offchain::local_storage_set( - StorageKind::PERSISTENT, - &cid, - &data, - ); - let signer = Signer::::all_accounts(); - if !signer.can_sign() { - log::error!( - "No local accounts available. Consider adding one via `author_insertKey` RPC.", - ); - } - let results = signer.send_signed_transaction(|_account| { - pallet_iris_assets::Call::submit_rpc_ready { - beneficiary: recipient.clone(), - } - }); - - for (_, res) in &results { - match res { - Ok(()) => log::info!("Submitted ipfs results"), - Err(e) => log::error!("Failed to submit transaction: {:?}", e), - } - } - }, - Ok(_) => unreachable!("only CatBytes can be a response for that request type."), - Err(e) => log::error!("IPFS: cat error: {:?}", e), - } + ensure!(balance_primitive != Some(0), Error::::InsufficientBalance); + match Self::ipfs_request(IpfsRequest::CatBytes(cid.clone()), deadline) { + Ok(IpfsResponse::CatBytes(data)) => { + log::info!("IPFS: Fetched data from IPFS."); + // add to offchain index + sp_io::offchain::local_storage_set( + StorageKind::PERSISTENT, + &cid, + &data, + ); + let signer = Signer::::AuthorityId>::all_accounts(); + if !signer.can_sign() { + log::error!( + "No local accounts available. Consider adding one via `author_insertKey` RPC.", + ); + } + let results = signer.send_signed_transaction(|_account| { + pallet_iris_assets::Call::submit_rpc_ready { + beneficiary: recipient.clone(), + } + }); + + for (_, res) in &results { + match res { + Ok(()) => log::info!("Submitted ipfs results"), + Err(e) => log::error!("Failed to submit transaction: {:?}", e), + } + } + }, + Ok(_) => unreachable!("only CatBytes can be a response for that request type."), + Err(e) => log::error!("IPFS: cat error: {:?}", e), + } + } else { + log::error!("the provided owner/cid does not map to a valid asset id: {:?}, {:?}", owner, cid) + } } } } diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index 9d4b2468017d..eb4b64120165 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -48,6 +48,7 @@ pub use frame_support::{ pub use pallet_balances::Call as BalancesCall; pub use pallet_timestamp::Call as TimestampCall; pub use pallet_assets::Call as AssetsCall; +// pub use pallet_iris_asset::Call as IrisAssetsCall; use pallet_transaction_payment::CurrencyAdapter; #[cfg(any(feature = "std", test))] pub use sp_runtime::BuildStorage; @@ -221,6 +222,8 @@ parameter_types! { impl pallet_iris_session::Config for Runtime { type Event = Event; + type Call = Call; + // type IrisAssetsCall = IrisAssetsCall; type AddRemoveOrigin = EnsureRoot; type MinAuthorities = MinAuthorities; type AuthorityId = pallet_iris_assets::crypto::TestAuthId; @@ -425,12 +428,10 @@ construct_runtime!( Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, TransactionPayment: pallet_transaction_payment::{Pallet, Storage}, Sudo: pallet_sudo::{Pallet, Call, Config, Storage, Event}, - // Include the custom logic from the pallet-template in the runtime. IrisSession: pallet_iris_session::{Pallet, Call, Storage, Event, Config}, Iris: pallet_iris_assets::{Pallet, Call, Storage, Event}, Session: pallet_session::{Pallet, Call, Storage, Event, Config}, Assets: pallet_assets::{Pallet, Storage, Event}, - // removed call to make extrinsics uncallable Aura: pallet_aura::{Pallet, Config}, Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event}, // Historical: pallet_session_historical::{Pallet}, @@ -604,7 +605,7 @@ impl_runtime_apis! { signature: Bytes, message: Bytes ) -> Bytes { - Iris::retrieve_bytes(public_key, signature, message) + IrisSession::retrieve_bytes(public_key, signature, message) } } diff --git a/useful commands.txt b/useful commands.txt new file mode 100644 index 000000000000..c399a21783e9 --- /dev/null +++ b/useful commands.txt @@ -0,0 +1,170 @@ +docker build -t iridiumlabs/iris-ui -f Dockerfile.dev . + +docker build -t iridiumlabs/iris-ui -f Dockerfile.prod . + +to run the dev image +docker run -it --rm -p 3000:3000 -e "REACT_APP_IPV4=192.168.101.47" iridiumlabs/iris-ui:latest + +to run the prod image +docker run -it --rm -p 3000:80 -e REACT_APP_IPV4="10.0.0.131" iridiumlabs/iris-ui + + +docker build -t iridiumlabs/iris -f ./.maintain/Dockerfile . + +--dev + + +docker run -p 9944:9944 \ + -p 9933:9933 \ + -p 30333:30333 \ + -p 9615:9615 \ + -it \ + --rm \ + --name iris-node0 \ + iridiumlabs/iris \ + --alice --ws-external --rpc-external --validator --rpc-methods=unsafe --dev \ + --node-key 0000000000000000000000000000000000000000000000000000000000000001 + + +docker run -p 9945:9944 \ + -p 9934:9933 \ + -p 30334:30333 \ + -p 9616:9615 \ + -it \ + --rm \ + --name iris-node1 \ + iridiumlabs/iris \ + --bob --dev --ws-external --rpc-external --rpc-methods=unsafe \ + --bootnodes /ip4/172.17.0.2/tcp/30333/p2p/12D3KooWEyoppNCUx8Yx66oV9fJnriXwCcXwDDUA2kj6vnc6iDEp + + + +docker run -p 9944:9944 \ + -p 9933:9933 \ + -p 30333:30333 \ + -p 9615:9615 \ + -it \ + --rm \ +--mount type=bind,source=/run/desktop/mnt/d/work/driemworks/substrate/customSpecRaw.json,target=/app/spec.json \ + --name iris-alice \ + iridiumlabs/iris \ + --ws-external --rpc-external --validator --rpc-methods=unsafe --chain local \ + --node-key 0000000000000000000000000000000000000000000000000000000000000001 + + +--mount type=bind,source=d/work/driemworks/substrate/customSpecRaw.json,target=/app/spec.json \ +-v /d/work/driemworks/substrate/customSpecRaw.json:/data/customSpecRaw.json:ro \ + +docker run -p 9944:9944 \ + -p 9933:9933 \ + -p 30333:30333 \ + -p 9615:9615 \ + --rm \ +-v /d/work/driemworks/substrate/:/data/:ro \ + --name iris-alice \ + iridiumlabs/iris \ + --ws-external --rpc-external --validator --rpc-methods=unsafe --chain local \ + --node-key 0000000000000000000000000000000000000000000000000000000000000001 + +docker run -p 9945:9944 \ + -p 9934:9933 \ + -p 30334:30333 \ + -p 9616:9615 \ + -it \ + --rm \ + --name iris-bob \ + iridiumlabs/iris \ + --ws-external --rpc-external --validator --rpc-methods=unsafe --chain ./customSpecRaw.json \ + --node-key 0000000000000000000000000000000000000000000000000000000000000002 \ + --bootnodes /ip4/172.17.0.2/tcp/30333/p2p/12D3KooWEyoppNCUx8Yx66oV9fJnriXwCcXwDDUA2kj6vnc6iDEp +--dev + + +./target/release/node-template purge-chain --base-path /tmp/alice --dev -y +./target/release/node-template \ + --tmp \ +--dev \ +--alice \ +--port 30333 \ +--ws-port 9944 \ +--rpc-port 9933 \ +--rpc-cors all \ +--ws-external \ +--rpc-external \ +--rpc-methods=unsafe + \ +--validator + +c +./target/release/node-template purge-chain --base-path /tmp/bob --dev -y +./target/release/node-template \ +--tmp \ +--dev \ +--bob \ +--port 30334 \ +--ws-port 9945 \ +--rpc-port 9934 \ +--rpc-cors all \ +--ws-external \ +--rpc-external \ +--rpc-methods=unsafe \ +--bootnodes /ip4/127.0.0.1/tcp/30333/p2p/12D3KooWMsPMyEFkb7DbyBE7WNhU8iUFfoq7DLybMe4ZzRmwZ5QT + +To generate new keys +``` +./target/release/node-template key generate --scheme Sr25519 --password-interactive +output: + Key password: +Secret phrase: embrace side business buzz maple photo merry flash uncle equal manage country + Secret seed: 0xcb950daa86c795a824f7360c9bd6b8cce4177f1daeaa8867633c5a4471184982 + Public key (hex): 0x965bfbbfac942bc532619ef05ed42ed68ad70c2260b0b65409c8046cad3c272b + Account ID: 0x965bfbbfac942bc532619ef05ed42ed68ad70c2260b0b65409c8046cad3c272b + Public key (SS58): 5FTrN6uanEycLVNBwhNhqR82NcMYHFCcXLAXsERKt1ARE2tE + SS58 Address: 5FTrN6uanEycLVNBwhNhqR82NcMYHFCcXLAXsERKt1ARE2tE + + +./target/release/node-template key inspect --password-interactive --scheme Ed25519 +``` +./target/release/node-template key inspect --password-interactive --scheme Ed25519 0xcb950daa86c795a824f7360c9bd6b8cce4177f1daeaa8867633c5a4471184982 + +output: +Secret Key URI `0xcb950daa86c795a824f7360c9bd6b8cce4177f1daeaa8867633c5a4471184982` is account: + Secret seed: 0xcb950daa86c795a824f7360c9bd6b8cce4177f1daeaa8867633c5a4471184982 + Public key (hex): 0xe2942589d9e3845353cf17b44e3e14dc1f069491d4960a34ce7e3d1d172952d6 + Account ID: 0xe2942589d9e3845353cf17b44e3e14dc1f069491d4960a34ce7e3d1d172952d6 + Public key (SS58): 5HBngrAn1eBbybHydEw7dErtd9bpwAz46pHBU9BTb8JobwWZ + SS58 Address: 5HBngrAn1eBbybHydEw7dErtd9bpwAz46pHBU9BTb8JobwWZ + + +--- + +5DoJJAMZYtKP868F2r7cPPJZeknYyfeYLYXsQ4MTaGiMKsDN +5CdaMT4b2BLh4zCdjtW5gbFErYkv8aQEvFsYBHXRYdsVHcyN +--- +./target/release/node-template key inspect --password-interactive --scheme Ed25519 0xd8a895b25f622ed9fdca0d36fadafc5be465b92e0d5f91c66157718177b81d30 + + +https://docs.substrate.io/tutorials/v3/private-network/ + + +to insert keys to create blocks +./target/release/node-template key insert --base-path /tmp/node01 --chain customSpecRaw.json --suri 0xcb950daa86c795a824f7360c9bd6b8cce4177f1daeaa8867633c5a4471184982 --password-interactive --key-type aura + +to finalize blocks +./target/release/node-template key insert --base-path /tmp/node01 --chain customSpecRaw.json --suri 0xcb950daa86c795a824f7360c9bd6b8cce4177f1daeaa8867633c5a4471184982 --password-interactive --key-type gran + + + + + + curl http://localhost:9933 -H "Content-Type:application/json;charset=utf-8" -d '{"jsonrpc": "2.0", "id": "1", "method": "iris_retrieveBytes", "params": ["", "", "0x516d505a763750386e51555368324370715476556559656d46796a764d6a67574573384831546d3862337a416d39"]}' + + curl http://localhost:9933 -H "Content-Type:application/json;charset=utf-8" -d '{"jsonrpc": "2.0", "id": "1", "method": "system_localListenAddresses", "params": []}' + + + {\"jsonrpc\": \"2.0\", \"id\": \"1\", \"method\": \"system_localListeningAddresses\", \"params\": []} + + + + IRIS 0x6dcf6f039825861149726973 + BootstrapNodes 8aadd98b1699270c426f6f7473747261704e6f646573 \ No newline at end of file From 7e87c08b71ce2247b504fb2ea7d1f979f98705a2 Mon Sep 17 00:00:00 2001 From: Zeke Mostov Date: Mon, 17 Jan 2022 19:06:25 -0800 Subject: [PATCH 395/695] Migration for over locked accounts in phgragmen elections (#10649) * use free balance rather than total balance * Docs * Migration for over-locked phrag voters * New line * comment * Update frame/elections-phragmen/src/migrations/v5.rs Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> * Only set lock, don't remove it * delete commented out * docs * Update migration to just take a set of accounts Co-authored-by: Shawn Tabrizi Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> --- .../elections-phragmen/src/migrations/mod.rs | 2 + frame/elections-phragmen/src/migrations/v5.rs | 70 +++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 frame/elections-phragmen/src/migrations/v5.rs diff --git a/frame/elections-phragmen/src/migrations/mod.rs b/frame/elections-phragmen/src/migrations/mod.rs index e7f6429f2298..7c62e8fa9306 100644 --- a/frame/elections-phragmen/src/migrations/mod.rs +++ b/frame/elections-phragmen/src/migrations/mod.rs @@ -21,3 +21,5 @@ pub mod v3; /// Version 4. pub mod v4; +/// Version 5. +pub mod v5; diff --git a/frame/elections-phragmen/src/migrations/v5.rs b/frame/elections-phragmen/src/migrations/v5.rs new file mode 100644 index 000000000000..1898668cd07b --- /dev/null +++ b/frame/elections-phragmen/src/migrations/v5.rs @@ -0,0 +1,70 @@ +use super::super::*; + +/// Migrate the locks and vote stake on accounts (as specified with param `to_migrate`) that have +/// more than their free balance locked. +/// +/// This migration addresses a bug were a voter could lock up to their reserved balance + free +/// balance. Since locks are only designed to operate on free balance, this put those affected in a +/// situation where they could increase their free balance but still not be able to use their funds +/// because they were less than the lock. +pub fn migrate(to_migrate: Vec) -> Weight { + let mut weight = 0; + + for who in to_migrate.iter() { + if let Ok(mut voter) = Voting::::try_get(who) { + let free_balance = T::Currency::free_balance(&who); + + weight = weight.saturating_add(T::DbWeight::get().reads(2)); + + if voter.stake > free_balance { + voter.stake = free_balance; + Voting::::insert(&who, voter); + + let pallet_id = T::PalletId::get(); + T::Currency::set_lock(pallet_id, &who, free_balance, WithdrawReasons::all()); + + weight = weight.saturating_add(T::DbWeight::get().writes(2)); + } + } + } + + weight +} + +/// Given the list of voters to migrate return a function that does some checks and information +/// prior to migration. This can be linked to [`frame_support::traits::OnRuntimeUpgrade:: +/// pre_upgrade`] for further testing. +pub fn pre_migrate_fn(to_migrate: Vec) -> Box ()> { + Box::new(move || { + for who in to_migrate.iter() { + if let Ok(voter) = Voting::::try_get(who) { + let free_balance = T::Currency::free_balance(&who); + + if voter.stake > free_balance { + // all good + } else { + log::warn!("pre-migrate elections-phragmen: voter={:?} has less stake then free balance", who); + } + } else { + log::warn!("pre-migrate elections-phragmen: cannot find voter={:?}", who); + } + } + log::info!("pre-migrate elections-phragmen complete"); + }) +} + +/// Some checks for after migration. This can be linked to +/// [`frame_support::traits::OnRuntimeUpgrade::post_upgrade`] for further testing. +/// +/// Panics if anything goes wrong. +pub fn post_migrate() { + for (who, voter) in Voting::::iter() { + let free_balance = T::Currency::free_balance(&who); + + assert!(voter.stake <= free_balance, "migration should have made locked <= free_balance"); + // Ideally we would also check that the locks and AccountData.misc_frozen where correctly + // updated, but since both of those are generic we can't do that without further bounding T. + } + + log::info!("post-migrate elections-phragmen complete"); +} From 787bb8711a031bb5a38a9deb82416d8ed14d69a0 Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Tue, 18 Jan 2022 09:18:52 +0100 Subject: [PATCH 396/695] bench/cli: extend --extrinsic name filtering (#10677) * implement benchmarking multiple extrinsics * ran cargo +nightly fmt * remove contains check and made it an equals check --- utils/frame/benchmarking-cli/src/command.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/utils/frame/benchmarking-cli/src/command.rs b/utils/frame/benchmarking-cli/src/command.rs index 368b5ce59c95..a5046dbaad2a 100644 --- a/utils/frame/benchmarking-cli/src/command.rs +++ b/utils/frame/benchmarking-cli/src/command.rs @@ -120,7 +120,8 @@ impl BenchmarkCmd { let pallet = self.pallet.clone().unwrap_or_else(|| String::new()); let pallet = pallet.as_bytes(); let extrinsic = self.extrinsic.clone().unwrap_or_else(|| String::new()); - let extrinsic = extrinsic.as_bytes(); + let extrinsic_split: Vec<&str> = extrinsic.split(',').collect(); + let extrinsics: Vec<_> = extrinsic_split.iter().map(|x| x.trim().as_bytes()).collect(); let genesis_storage = spec.build_storage()?; let mut changes = Default::default(); @@ -176,7 +177,10 @@ impl BenchmarkCmd { .filter(|item| pallet.is_empty() || pallet == &b"*"[..] || pallet == &item.pallet[..]) .for_each(|item| { for benchmark in &item.benchmarks { - if extrinsic.is_empty() || extrinsic == &b"*"[..] || extrinsic == benchmark.name + let benchmark_name = &benchmark.name; + if extrinsic.is_empty() || + extrinsic.as_bytes() == &b"*"[..] || + extrinsics.contains(&&benchmark_name[..]) { benchmarks_to_run.push(( item.pallet.clone(), From 4cd2cc958f5a078d87e4eae877167c40cf2ebf9e Mon Sep 17 00:00:00 2001 From: Sacha Lansky Date: Tue, 18 Jan 2022 20:05:12 +0100 Subject: [PATCH 397/695] Minor syntax and typo edits (#10693) --- client/transaction-pool/README.md | 59 ++++++++++++++++--------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/client/transaction-pool/README.md b/client/transaction-pool/README.md index e4f8ccb3d810..4a2bbb8838f9 100644 --- a/client/transaction-pool/README.md +++ b/client/transaction-pool/README.md @@ -39,7 +39,7 @@ runtime (queried at current best imported block). Since the blockchain is not always linear, forks need to be correctly handled by the transaction pool as well. In case of a fork, some blocks are *retracted* from the canonical chain, and some other blocks get *enacted* on top of some -common ancestor. The transactions from retrated blocks could simply be discarded, +common ancestor. The transactions from retracted blocks could simply be discarded, but it's desirable to make sure they are still considered for inclusion in case they are deemed valid by the runtime state at best, recently enacted block (fork the chain re-organized to). @@ -49,7 +49,7 @@ pool, it's broadcasting status, block inclusion, finality, etc. ## Transaction Validity details -Information retrieved from the the runtime are encapsulated in `TransactionValidity` +Information retrieved from the the runtime are encapsulated in the `TransactionValidity` type. ```rust @@ -147,7 +147,7 @@ choosing the ones with highest priority to include to the next block first. - `priority` of transaction may change over time - on-chain conditions may affect `priority` -- Given two transactions with overlapping `provides` tags, the one with higher +- given two transactions with overlapping `provides` tags, the one with higher `priority` should be preferred. However we can also look at the total priority of a subtree rooted at that transaction and compare that instead (i.e. even though the transaction itself has lower `priority` it "unlocks" other high priority transactions). @@ -163,7 +163,7 @@ the transaction is valid all that time though. - `longevity` of transaction may change over time - on-chain conditions may affect `longevity` -- After `longevity` lapses the transaction may still be valid +- after `longevity` lapses, the transaction may still be valid ### `propagate` @@ -231,15 +231,16 @@ to instead of gossiping everyting have other peers request transactions they are interested in. Since the pool is expected to store more transactions than what can fit -to a single block. Validating the entire pool on every block might not be -feasible, so the actual implementation might need to take some shortcuts. +in a single block, validating the entire pool on every block might not be +feasible. This means that the actual implementation might need to take some +shortcuts. ## Suggestions & caveats -1. The validity of transaction should not change significantly from block to +1. The validity of a transaction should not change significantly from block to block. I.e. changes in validity should happen predictably, e.g. `longevity` decrements by 1, `priority` stays the same, `requires` changes if transaction - that provided a tag was included in block. `provides` does not change, etc. + that provided a tag was included in block, `provides` does not change, etc. 1. That means we don't have to revalidate every transaction after every block import, but we need to take care of removing potentially stale transactions. @@ -253,9 +254,9 @@ feasible, so the actual implementation might need to take some shortcuts. 1. In the past there were many issues found when running small networks with a lot of re-orgs. Make sure that transactions are never lost. -1. UTXO model is quite challenging. The transaction becomes valid right after - it's included in block, however it is waiting for exactly the same inputs to - be spent, so it will never really be included again. +1. The UTXO model is quite challenging. A transaction becomes valid right after + it's included in a block, however it is waiting for exactly the same inputs + to be spent, so it will never really be included again. 1. Note that in a non-ideal implementation the state of the pool will most likely always be a bit off, i.e. some transactions might be still in the pool, @@ -277,8 +278,8 @@ feasible, so the actual implementation might need to take some shortcuts. 1. We periodically validate all transactions in the pool in batches. -1. To minimize runtime calls, we introduce batch-verify call. Note it should reset - the state (overlay) after every verification. +1. To minimize runtime calls, we introduce the batch-verify call. Note it should + reset the state (overlay) after every verification. 1. Consider leveraging finality. Maybe we could verify against latest finalised block instead. With this the pool in different nodes can be more similar @@ -286,16 +287,16 @@ feasible, so the actual implementation might need to take some shortcuts. is not a strict requirement for a Substrate chain to have though. 1. Perhaps we could avoid maintaining ready/future queues as currently, but - rather if transaction doesn't have all requirements satisfied by existing + rather if a transaction doesn't have all requirements satisfied by existing transactions we attempt to re-import it in the future. 1. Instead of maintaining a full pool with total ordering we attempt to maintain a set of next (couple of) blocks. We could introduce batch-validate runtime - api method that pretty much attempts to simulate actual block inclusion of + api method that pretty much attempts to simulate actual block inclusion of a set of such transactions (without necessarily fully running/dispatching them). Importing a transaction would consist of figuring out which next block - this transaction have a chance to be included in and then attempting to - either push it back or replace some of existing transactions. + this transaction has a chance to be included in and then attempting to + either push it back or replace some existing transactions. 1. Perhaps we could use some immutable graph structure to easily add/remove transactions. We need some traversal method that takes priority and @@ -320,7 +321,7 @@ The pool consists of basically two independent parts: The pool is split into `ready` pool and `future` pool. The latter contains transactions that don't have their requirements satisfied, and the former holds transactions that can be used to build a graph of dependencies. Note that the -graph is build ad-hoc during the traversal process (getting the `ready` +graph is built ad-hoc during the traversal process (using the `ready` iterator). This makes the importing process cheaper (we don't need to find the exact position in the queue or graph), but traversal process slower (logarithmic). However most of the time we will only need the beginning of the @@ -342,26 +343,26 @@ to limit number of runtime verification calls. Each time a transaction is imported, we first verify it's validity and later find if the tags it `requires` can be satisfied by transactions already in `ready` pool. In case the transaction is imported to the `ready` pool we -additionally *promote* transactions from `future` pool if the transaction +additionally *promote* transactions from the `future` pool if the transaction happened to fulfill their requirements. -Note we need to cater for cases where transaction might replace a already +Note we need to cater for cases where a transaction might replace an already existing transaction in the pool. In such case we check the entire sub-tree of transactions that we are about to replace, compare their cumulative priority to determine which subtree to keep. -After a block is imported we kick-off pruning procedure. We first attempt to -figure out what tags were satisfied by transaction in that block. For each block -transaction we either call into runtime to get it's `ValidTransaction` object, +After a block is imported we kick-off the pruning procedure. We first attempt to +figure out what tags were satisfied by a transaction in that block. For each block +transaction we either call into the runtime to get it's `ValidTransaction` object, or we check the pool if that transaction is already known to spare the runtime -call. From this we gather full set of `provides` tags and perform pruning of -`ready` pool based on that. Also we promote all transactions from `future` that -have their tags satisfied. +call. From this we gather the full set of `provides` tags and perform pruning of +the `ready` pool based on that. Also, we promote all transactions from `future` +that have their tags satisfied. In case we remove transactions that we are unsure if they were already included -in current block or some block in the past, it is being added to revalidation -queue and attempted to be re-imported by the background task in the future. +in the current block or some block in the past, it gets added to the revalidation +queue and attempts to be re-imported by the background task in the future. Runtime calls to verify transactions are performed from a separate (limited) -thread pool to avoid interferring too much with other subsystems of the node. We +thread pool to avoid interfering too much with other subsystems of the node. We definitely don't want to have all cores validating network transactions, because all of these transactions need to be considered untrusted (potentially DoS). From 1bdd85d784467914cd04d0d19aa188609a14bd5d Mon Sep 17 00:00:00 2001 From: driemworks Date: Tue, 18 Jan 2022 14:52:23 -0600 Subject: [PATCH 398/695] move rpc to session, update version and cargo files, create storage pool --- Cargo.lock | 7 +- bin/node-template/node/Cargo.toml | 2 +- .../pallets/iris-assets/Cargo.toml | 4 +- .../pallets/iris-assets/src/lib.rs | 137 +++++++-------- .../pallets/iris-session/Cargo.toml | 4 +- .../rpc/Cargo.toml | 0 .../rpc/README.md | 0 .../rpc/runtime-api/Cargo.toml | 4 +- .../rpc/runtime-api/README.md | 0 .../rpc/runtime-api/src/lib.rs | 0 .../rpc/src/lib.rs | 0 .../pallets/iris-session/src/lib.rs | 161 +++++++++++++++--- bin/node-template/runtime/Cargo.toml | 6 +- bin/node-template/runtime/src/lib.rs | 8 +- bin/node/rpc/Cargo.toml | 2 +- 15 files changed, 210 insertions(+), 125 deletions(-) rename bin/node-template/pallets/{iris-assets => iris-session}/rpc/Cargo.toml (100%) rename bin/node-template/pallets/{iris-assets => iris-session}/rpc/README.md (100%) rename bin/node-template/pallets/{iris-assets => iris-session}/rpc/runtime-api/Cargo.toml (88%) rename bin/node-template/pallets/{iris-assets => iris-session}/rpc/runtime-api/README.md (100%) rename bin/node-template/pallets/{iris-assets => iris-session}/rpc/runtime-api/src/lib.rs (100%) rename bin/node-template/pallets/{iris-assets => iris-session}/rpc/src/lib.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index 539ecf6b2ebc..db114c68e76d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5852,7 +5852,7 @@ dependencies = [ [[package]] name = "pallet-iris-assets" -version = "3.0.0" +version = "1.0.0" dependencies = [ "frame-benchmarking", "frame-support", @@ -5860,7 +5860,6 @@ dependencies = [ "log 0.4.14", "pallet-assets", "pallet-balances", - "pallet-session", "parity-scale-codec", "scale-info", "sp-core", @@ -5890,7 +5889,7 @@ dependencies = [ name = "pallet-iris-rpc-runtime-api" version = "4.0.0-dev" dependencies = [ - "pallet-iris-assets", + "pallet-iris-session", "parity-scale-codec", "sp-api", "sp-core", @@ -5899,7 +5898,7 @@ dependencies = [ [[package]] name = "pallet-iris-session" -version = "3.0.0" +version = "1.0.0" dependencies = [ "frame-benchmarking", "frame-support", diff --git a/bin/node-template/node/Cargo.toml b/bin/node-template/node/Cargo.toml index d5731d9f0d1b..d6b819b50df1 100644 --- a/bin/node-template/node/Cargo.toml +++ b/bin/node-template/node/Cargo.toml @@ -48,7 +48,7 @@ sp-block-builder = { version = "4.0.0-dev", path = "../../../primitives/block-bu sc-basic-authorship = { version = "0.10.0-dev", path = "../../../client/basic-authorship" } substrate-frame-rpc-system = { version = "4.0.0-dev", path = "../../../utils/frame/rpc/system" } pallet-transaction-payment-rpc = { version = "4.0.0-dev", path = "../../../frame/transaction-payment/rpc/" } -pallet-iris-rpc = { version = "4.0.0-dev", path = "../pallets/iris-assets/rpc/" } +pallet-iris-rpc = { version = "4.0.0-dev", path = "../pallets/iris-session/rpc/" } # These dependencies are used for runtime benchmarking frame-benchmarking = { version = "4.0.0-dev", path = "../../../frame/benchmarking" } diff --git a/bin/node-template/pallets/iris-assets/Cargo.toml b/bin/node-template/pallets/iris-assets/Cargo.toml index e8a6d4c77b70..ae017ba59de4 100644 --- a/bin/node-template/pallets/iris-assets/Cargo.toml +++ b/bin/node-template/pallets/iris-assets/Cargo.toml @@ -2,7 +2,7 @@ authors = ['Substrate DevHub '] edition = '2018' name = 'pallet-iris-assets' -version = "3.0.0" +version = "1.0.0" license = "Unlicense" homepage = "https://substrate.dev" repository = "https://github.com/substrate-developer-hub/substrate-node-template/" @@ -32,7 +32,6 @@ log = { version = "0.4.14", default-features = false } pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../../../../frame/balances" } pallet-assets = { version = "4.0.0-dev", default-features = false, path = "../../../../frame/assets" } -pallet-session = { version = "4.0.0-dev", default-features = false, features = ["historical"], path = "../../../../frame/session" } [features] default = ['std'] @@ -49,7 +48,6 @@ std = [ 'log/std', 'pallet-assets/std', 'pallet-balances/std', - 'pallet-session/std', ] runtime-benchmarks = ["frame-benchmarking"] diff --git a/bin/node-template/pallets/iris-assets/src/lib.rs b/bin/node-template/pallets/iris-assets/src/lib.rs index ad20023c6cec..7153314eb2f6 100644 --- a/bin/node-template/pallets/iris-assets/src/lib.rs +++ b/bin/node-template/pallets/iris-assets/src/lib.rs @@ -60,35 +60,6 @@ use sp_std::{ convert::TryInto, }; -pub const KEY_TYPE: KeyTypeId = KeyTypeId(*b"iris"); - - -pub mod crypto { - use crate::KEY_TYPE; - use sp_core::sr25519::Signature as Sr25519Signature; - use sp_runtime::app_crypto::{app_crypto, sr25519}; - use sp_runtime::{traits::Verify, MultiSignature, MultiSigner}; - - app_crypto!(sr25519, KEY_TYPE); - - pub struct TestAuthId; - // implemented for runtime - impl frame_system::offchain::AppCrypto for TestAuthId { - type RuntimeAppPublic = Public; - type GenericSignature = sp_core::sr25519::Signature; - type GenericPublic = sp_core::sr25519::Public; - } - - // implemented for mock runtime in test - impl frame_system::offchain::AppCrypto<::Signer, Sr25519Signature> - for TestAuthId - { - type RuntimeAppPublic = Public; - type GenericSignature = sp_core::sr25519::Signature; - type GenericPublic = sp_core::sr25519::Public; - } -} - #[derive(Encode, Decode, RuntimeDebug, PartialEq, TypeInfo)] pub enum DataCommand { /// (ipfs_address, cid, requesting node address, filename, asset id, balance) @@ -97,7 +68,7 @@ pub enum DataCommand { CatBytes(AccountId, Vec, AccountId), } -#[derive(Encode, Decode, RuntimeDebug, PartialEq, TypeInfo)] +#[derive(Encode, Decode, RuntimeDebug, Clone, Default, Eq, PartialEq, TypeInfo)] pub struct StoragePool { max_redundancy: u32, candidate_storage_providers: Vec, @@ -132,11 +103,9 @@ pub mod pallet { #[pallet::config] /// the module configuration trait - pub trait Config:CreateSignedTransaction> + frame_system::Config + pallet_assets::Config { + pub trait Config: frame_system::Config + pallet_assets::Config { /// The overarching event type type Event: From> + IsType<::Event>; - /// the authority id used for sending signed txs - type AuthorityId: AppCrypto; /// the overarching call type type Call: From>; /// the currency used @@ -215,11 +184,14 @@ pub mod pallet { #[pallet::storage] #[pallet::getter(fn storage_pool_config)] - pub(super) type StoragePoolConfig = StorageMap< + pub(super) type StoragePoolConfig = StorageDoubleMap< _, Blake2_128Concat, + T::AccountId, + Blake2_128Concat, T::AssetId, StoragePool, + ValueQuery, >; #[pallet::event] @@ -395,41 +367,41 @@ pub mod pallet { Ok(()) } - /// Should only be callable by OCWs (TODO) - /// Submit the results of an `ipfs identity` call to be stored on chain - /// - /// * origin: a validator node - /// * public_key: The IPFS node's public key - /// * multiaddresses: A vector of multiaddresses associate with the public key - /// - #[pallet::weight(0)] - pub fn submit_ipfs_identity( - origin: OriginFor, - public_key: Vec, - multiaddresses: Vec, - ) -> DispatchResult { - let who = ensure_signed(origin)?; - >::insert(public_key.clone(), multiaddresses.clone()); - Self::deposit_event(Event::PublishedIdentity(who.clone())); - Ok(()) - } - - /// Should only be callable by OCWs (TODO) - /// Submit the results onchain to notify a beneficiary that their data is available: TODO: how to safely share host? spam protection on rpc endpoints? - /// - /// * `beneficiary`: The account that requested the data - /// * `host`: The node's host where the data has been made available (RPC endpoint) - /// - #[pallet::weight(0)] - pub fn submit_rpc_ready( - origin: OriginFor, - beneficiary: T::AccountId, - // host: Vec, - ) -> DispatchResult { - ensure_signed(origin)?; - Self::deposit_event(Event::DataReady(beneficiary)); - Ok(()) - } + // /// Should only be callable by OCWs (TODO) + // /// Submit the results of an `ipfs identity` call to be stored on chain + // /// + // /// * origin: a validator node + // /// * public_key: The IPFS node's public key + // /// * multiaddresses: A vector of multiaddresses associate with the public key + // /// + // #[pallet::weight(0)] + // pub fn submit_ipfs_identity( + // origin: OriginFor, + // public_key: Vec, + // multiaddresses: Vec, + // ) -> DispatchResult { + // let who = ensure_signed(origin)?; + // >::insert(public_key.clone(), multiaddresses.clone()); + // Self::deposit_event(Event::PublishedIdentity(who.clone())); + // Ok(()) + // } + + // /// Should only be callable by OCWs (TODO) + // /// Submit the results onchain to notify a beneficiary that their data is available: TODO: how to safely share host? spam protection on rpc endpoints? + // /// + // /// * `beneficiary`: The account that requested the data + // /// * `host`: The node's host where the data has been made available (RPC endpoint) + // /// + // #[pallet::weight(0)] + // pub fn submit_rpc_ready( + // origin: OriginFor, + // beneficiary: T::AccountId, + // // host: Vec, + // ) -> DispatchResult { + // ensure_signed(origin)?; + // Self::deposit_event(Event::DataReady(beneficiary)); + // Ok(()) + // } /// Only callable by the owner of the asset class /// mint a static number of assets (tickets) for some asset class @@ -476,7 +448,7 @@ pub mod pallet { current_session_storage_providers: Vec::new(), owner: who.clone(), }; - >::insert(asset_id.clone(), new_sp_config); + >::insert(who.clone(), asset_id.clone(), new_sp_config); Self::deposit_event( Event::StoragePoolConfigurationSuccess( who.clone(), asset_id.clone())); @@ -486,10 +458,15 @@ pub mod pallet { #[pallet::weight(0)] pub fn try_add_candidate_storage_provider( origin: OriginFor, + pool_owner: T::AccountId, pool_id: T::AssetId, ) -> DispatchResult { let who = ensure_signed(origin)?; + Self::do_add_candidate_storage_provider( + pool_owner.clone(), pool_id.clone(), who.clone() + ); + Ok(()) } } @@ -497,11 +474,19 @@ pub mod pallet { impl Pallet { - // fn try_add_candidate_storage_provider( - // pool_id: T::AssetId, - // candidate_storage_provider: T::AccountId, - // ) -> Result<(), Error> { - // Ok(()) - // } + fn do_add_candidate_storage_provider( + pool_admin: T::AccountId, + pool_id: T::AssetId, + candidate_storage_provider: T::AccountId, + ) -> Result<(), Error> { + let mut sp = StoragePoolConfig::::get(pool_admin.clone(), pool_id.clone()); + // TODO: check duplicates + sp.candidate_storage_providers.push(candidate_storage_provider); + >::insert( + pool_admin.clone(), pool_id.clone(), sp + ); + + Ok(()) + } } \ No newline at end of file diff --git a/bin/node-template/pallets/iris-session/Cargo.toml b/bin/node-template/pallets/iris-session/Cargo.toml index 476897b13fb3..fecd303c64a6 100644 --- a/bin/node-template/pallets/iris-session/Cargo.toml +++ b/bin/node-template/pallets/iris-session/Cargo.toml @@ -2,7 +2,7 @@ authors = ['Iridium '] edition = '2018' name = 'pallet-iris-session' -version = "3.0.0" +version = "1.0.0" license = "Unlicense" homepage = "https://substrate.dev" repository = "https://github.com/substrate-developer-hub/substrate-node-template/" @@ -34,7 +34,7 @@ log = { version = "0.4.14", default-features = false } # pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../../../../frame/balances" } pallet-assets = { version = "4.0.0-dev", default-features = false, path = "../../../../frame/assets" } pallet-session = { version = "4.0.0-dev", default-features = false, features = ["historical"], path = "../../../../frame/session" } -pallet-iris-assets = { version = "3.0.0", default-features = false, path = "../iris-assets" } +pallet-iris-assets = { version = "1.0.0", default-features = false, path = "../iris-assets" } [features] default = ['std'] diff --git a/bin/node-template/pallets/iris-assets/rpc/Cargo.toml b/bin/node-template/pallets/iris-session/rpc/Cargo.toml similarity index 100% rename from bin/node-template/pallets/iris-assets/rpc/Cargo.toml rename to bin/node-template/pallets/iris-session/rpc/Cargo.toml diff --git a/bin/node-template/pallets/iris-assets/rpc/README.md b/bin/node-template/pallets/iris-session/rpc/README.md similarity index 100% rename from bin/node-template/pallets/iris-assets/rpc/README.md rename to bin/node-template/pallets/iris-session/rpc/README.md diff --git a/bin/node-template/pallets/iris-assets/rpc/runtime-api/Cargo.toml b/bin/node-template/pallets/iris-session/rpc/runtime-api/Cargo.toml similarity index 88% rename from bin/node-template/pallets/iris-assets/rpc/runtime-api/Cargo.toml rename to bin/node-template/pallets/iris-session/rpc/runtime-api/Cargo.toml index 00d906df8ae6..33d6e1bb675b 100644 --- a/bin/node-template/pallets/iris-assets/rpc/runtime-api/Cargo.toml +++ b/bin/node-template/pallets/iris-session/rpc/runtime-api/Cargo.toml @@ -17,7 +17,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../../../../primitives/api" } sp-core = { version = "4.0.0-dev", default-features = false, path = "../../../../../../primitives/core" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../../../../primitives/runtime" } -pallet-iris-assets = { version = "3.0.0", default-features = false, path = "../../../iris-assets" } +pallet-iris-session = { version = "1.0.0", default-features = false, path = "../../../iris-session" } [features] default = ["std"] @@ -26,5 +26,5 @@ std = [ "sp-api/std", "sp-core/std", "sp-runtime/std", - "pallet-iris-assets/std", + "pallet-iris-session/std", ] diff --git a/bin/node-template/pallets/iris-assets/rpc/runtime-api/README.md b/bin/node-template/pallets/iris-session/rpc/runtime-api/README.md similarity index 100% rename from bin/node-template/pallets/iris-assets/rpc/runtime-api/README.md rename to bin/node-template/pallets/iris-session/rpc/runtime-api/README.md diff --git a/bin/node-template/pallets/iris-assets/rpc/runtime-api/src/lib.rs b/bin/node-template/pallets/iris-session/rpc/runtime-api/src/lib.rs similarity index 100% rename from bin/node-template/pallets/iris-assets/rpc/runtime-api/src/lib.rs rename to bin/node-template/pallets/iris-session/rpc/runtime-api/src/lib.rs diff --git a/bin/node-template/pallets/iris-assets/rpc/src/lib.rs b/bin/node-template/pallets/iris-session/rpc/src/lib.rs similarity index 100% rename from bin/node-template/pallets/iris-assets/rpc/src/lib.rs rename to bin/node-template/pallets/iris-session/rpc/src/lib.rs diff --git a/bin/node-template/pallets/iris-session/src/lib.rs b/bin/node-template/pallets/iris-session/src/lib.rs index 0e35dfc42182..a569fb95985e 100644 --- a/bin/node-template/pallets/iris-session/src/lib.rs +++ b/bin/node-template/pallets/iris-session/src/lib.rs @@ -19,7 +19,9 @@ mod tests; use frame_support::{ ensure, pallet_prelude::*, - traits::{EstimateNextSessionRotation, Get, ValidatorSet, ValidatorSetWithIdentification}, + traits::{ + EstimateNextSessionRotation, Get, ValidatorSet, ValidatorSetWithIdentification, + }, }; use log; pub use pallet::*; @@ -36,22 +38,55 @@ use sp_core::{ offchain::{ Duration, IpfsRequest, IpfsResponse, OpaqueMultiaddr, Timestamp, StorageKind, }, + crypto::KeyTypeId, Bytes, }; use frame_system::{ - self as system, ensure_signed, + self as system, + ensure_signed, offchain::{ SendSignedTransaction, Signer, } }; use sp_io::offchain::timestamp; -use sp_runtime::offchain::ipfs; +use sp_runtime::{ + offchain::ipfs, + traits::StaticLookup, +}; use pallet_iris_assets::{ DataCommand, }; pub const LOG_TARGET: &'static str = "runtime::iris-session"; +pub const KEY_TYPE: KeyTypeId = KeyTypeId(*b"iris"); + +pub mod crypto { + use crate::KEY_TYPE; + use sp_core::sr25519::Signature as Sr25519Signature; + use sp_runtime::app_crypto::{app_crypto, sr25519}; + use sp_runtime::{traits::Verify, MultiSignature, MultiSigner}; + + app_crypto!(sr25519, KEY_TYPE); + + pub struct TestAuthId; + // implemented for runtime + impl frame_system::offchain::AppCrypto for TestAuthId { + type RuntimeAppPublic = Public; + type GenericSignature = sp_core::sr25519::Signature; + type GenericPublic = sp_core::sr25519::Public; + } + + // implemented for mock runtime in test + impl frame_system::offchain::AppCrypto<::Signer, Sr25519Signature> + for TestAuthId + { + type RuntimeAppPublic = Public; + type GenericSignature = sp_core::sr25519::Signature; + type GenericPublic = sp_core::sr25519::Public; + } +} + #[frame_support::pallet] pub mod pallet { @@ -67,7 +102,11 @@ pub mod pallet { /// Configure the pallet by specifying the parameters and types on which it /// depends. #[pallet::config] - pub trait Config: frame_system::Config + pallet_session::Config + pallet_iris_assets::Config { + pub trait Config: CreateSignedTransaction> + + frame_system::Config + + pallet_session::Config + + pallet_iris_assets::Config + { /// The Event type. type Event: From> + IsType<::Event>; /// the overarching call type @@ -252,14 +291,80 @@ pub mod pallet { // submit a request to join a storage pool in the next session let who = ensure_signed(origin)?; let new_origin = system::RawOrigin::Signed(who.clone()).into(); + let owner = T::Lookup::lookup(pool_owner)?; >::try_add_candidate_storage_provider( new_origin, + owner, pool_id.clone(), )?; Self::deposit_event(Event::RequestJoinStoragePoolSuccess(who.clone(), pool_id.clone())); Ok(()) } + + /// should only be called by offchain workers... how to ensure this? + /// submits IPFS results on chain and creates new ticket config in runtime storage + /// + /// * `admin`: The admin account + /// * `cid`: The cid generated by the OCW + /// * `id`: The AssetId (passed through from the create_storage_asset call) + /// * `balance`: The balance (passed through from the create_storage_asset call) + /// + #[pallet::weight(0)] + pub fn submit_ipfs_add_results( + origin: OriginFor, + admin: ::Source, + cid: Vec, + id: T::AssetId, + balance: T::Balance, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + let new_origin = system::RawOrigin::Signed(who.clone()).into(); + >::submit_ipfs_add_results( + new_origin, + admin, + cid, + id, + balance, + )?; + Ok(()) + } + + /// Should only be callable by OCWs (TODO) + /// Submit the results of an `ipfs identity` call to be stored on chain + /// + /// * origin: a validator node + /// * public_key: The IPFS node's public key + /// * multiaddresses: A vector of multiaddresses associate with the public key + /// + #[pallet::weight(0)] + pub fn submit_ipfs_identity( + origin: OriginFor, + public_key: Vec, + multiaddresses: Vec, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + >::insert(public_key.clone(), multiaddresses.clone()); + Self::deposit_event(Event::PublishedIdentity(who.clone())); + Ok(()) + } + + /// Should only be callable by OCWs (TODO) + /// Submit the results onchain to notify a beneficiary that their data is available: TODO: how to safely share host? spam protection on rpc endpoints? + /// + /// * `beneficiary`: The account that requested the data + /// * `host`: The node's host where the data has been made available (RPC endpoint) + /// + #[pallet::weight(0)] + pub fn submit_rpc_ready( + origin: OriginFor, + beneficiary: T::AccountId, + // host: Vec, + ) -> DispatchResult { + ensure_signed(origin)?; + // Self::deposit_event(Event::DataReady(beneficiary)); + Ok(()) + } } } @@ -277,7 +382,7 @@ impl Pallet { >::mutate(|v| v.push(validator_id.clone())); Self::deposit_event(Event::ValidatorAdditionInitiated(validator_id.clone())); - log::debug!(target: LOG_TARGET, "Validator addition initiated."); + log::debug!(target: LOG_TARGET, "Validator addition initiated."); Ok(()) } @@ -422,26 +527,26 @@ impl Pallet { } } } - // let signer = Signer::::AuthorityId>::all_accounts(); - // if !signer.can_sign() { - // log::error!( - // "No local accounts available. Consider adding one via `author_insertKey` RPC.", - // ); - // } + let signer = Signer::::all_accounts(); + if !signer.can_sign() { + log::error!( + "No local accounts available. Consider adding one via `author_insertKey` RPC.", + ); + } - // let results = signer.send_signed_transaction(|_account| { - // pallet_iris_assets::Call::submit_ipfs_identity { - // public_key: public_key.clone(), - // multiaddresses: addrs.clone(), - // } - // }); + let results = signer.send_signed_transaction(|_account| { + Call::submit_ipfs_identity { + public_key: public_key.clone(), + multiaddresses: addrs.clone(), + } + }); - // for (_, res) in &results { - // match res { - // Ok(()) => log::info!("Submitted ipfs identity results"), - // Err(e) => log::error!("Failed to submit transaction: {:?}", e), - // } - // } + for (_, res) in &results { + match res { + Ok(()) => log::info!("Submitted ipfs identity results"), + Err(e) => log::error!("Failed to submit transaction: {:?}", e), + } + } } Ok(()) @@ -479,7 +584,7 @@ impl Pallet { "IPFS: added data with Cid {}", str::from_utf8(&new_cid).expect("our own IPFS node can be trusted here; qed") ); - let signer = Signer::::AuthorityId>::all_accounts(); + let signer = Signer::::all_accounts(); if !signer.can_sign() { log::error!( "No local accounts available. Consider adding one via `author_insertKey` RPC.", @@ -492,7 +597,7 @@ impl Pallet { // id: id.clone(), // balance: balance.clone(), // } - pallet_iris_assets::Call::submit_ipfs_add_results{ + Call::submit_ipfs_add_results{ admin: admin.clone(), cid: new_cid.clone(), id: id.clone(), @@ -532,14 +637,14 @@ impl Pallet { &cid, &data, ); - let signer = Signer::::AuthorityId>::all_accounts(); + let signer = Signer::::all_accounts(); if !signer.can_sign() { log::error!( "No local accounts available. Consider adding one via `author_insertKey` RPC.", ); } let results = signer.send_signed_transaction(|_account| { - pallet_iris_assets::Call::submit_rpc_ready { + Call::submit_rpc_ready { beneficiary: recipient.clone(), } }); @@ -596,7 +701,7 @@ impl pallet_session::SessionManager for Pallet { log::debug!(target: LOG_TARGET, "New session called; updated validator set provided."); // TODO: Need to verify that storage providers have data pinned... - + Some(Self::validators()) } diff --git a/bin/node-template/runtime/Cargo.toml b/bin/node-template/runtime/Cargo.toml index f4144271eae5..cf08c924978c 100644 --- a/bin/node-template/runtime/Cargo.toml +++ b/bin/node-template/runtime/Cargo.toml @@ -23,8 +23,8 @@ pallet-randomness-collective-flip = { version = "4.0.0-dev", default-features = pallet-sudo = { version = "4.0.0-dev", default-features = false, path = "../../../frame/sudo" } pallet-assets = { version = "4.0.0-dev", default-features = false, path = "../../../frame/assets" } pallet-session = { version = "4.0.0-dev", default-features = false, features = ["historical"], path = "../../../frame/session" } -pallet-iris-assets = { version = "3.0.0", default-features = false, path = "../pallets/iris-assets" } -pallet-iris-session = { version = "3.0.0", default-features = false, path = "../pallets/iris-session" } +pallet-iris-assets = { version = "1.0.0", default-features = false, path = "../pallets/iris-assets" } +pallet-iris-session = { version = "1.0.0", default-features = false, path = "../pallets/iris-session" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../../frame/system" } @@ -46,7 +46,7 @@ sp-version = { version = "4.0.0-dev", default-features = false, path = "../../.. # Used for the node template's RPCs frame-system-rpc-runtime-api = { version = "4.0.0-dev", default-features = false, path = "../../../frame/system/rpc/runtime-api/" } pallet-transaction-payment-rpc-runtime-api = { version = "4.0.0-dev", default-features = false, path = "../../../frame/transaction-payment/rpc/runtime-api/" } -pallet-iris-rpc-runtime-api = { version = "4.0.0-dev", default-features = false, path = "../pallets/iris-assets/rpc/runtime-api/" } +pallet-iris-rpc-runtime-api = { version = "4.0.0-dev", default-features = false, path = "../pallets/iris-session/rpc/runtime-api/" } # Used for runtime benchmarking frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../../../frame/benchmarking", optional = true } frame-system-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../../../frame/system/benchmarking", optional = true } diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index eb4b64120165..ceb30e68ee4e 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -226,7 +226,7 @@ impl pallet_iris_session::Config for Runtime { // type IrisAssetsCall = IrisAssetsCall; type AddRemoveOrigin = EnsureRoot; type MinAuthorities = MinAuthorities; - type AuthorityId = pallet_iris_assets::crypto::TestAuthId; + type AuthorityId = pallet_iris_session::crypto::TestAuthId; } parameter_types! { @@ -356,7 +356,7 @@ pub type SignedPayload = generic::SignedPayload; impl pallet_iris_assets::Config for Runtime { type Event = Event; type Call = Call; - type AuthorityId = pallet_iris_assets::crypto::TestAuthId; + // type AuthorityId = pallet_iris_assets::crypto::TestAuthId; type Currency = Balances; } @@ -423,18 +423,16 @@ construct_runtime!( UncheckedExtrinsic = UncheckedExtrinsic { System: frame_system::{Pallet, Call, Config, Storage, Event}, - // RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage}, Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, TransactionPayment: pallet_transaction_payment::{Pallet, Storage}, Sudo: pallet_sudo::{Pallet, Call, Config, Storage, Event}, - IrisSession: pallet_iris_session::{Pallet, Call, Storage, Event, Config}, Iris: pallet_iris_assets::{Pallet, Call, Storage, Event}, + IrisSession: pallet_iris_session::{Pallet, Call, Storage, Event, Config}, Session: pallet_session::{Pallet, Call, Storage, Event, Config}, Assets: pallet_assets::{Pallet, Storage, Event}, Aura: pallet_aura::{Pallet, Config}, Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event}, - // Historical: pallet_session_historical::{Pallet}, } ); diff --git a/bin/node/rpc/Cargo.toml b/bin/node/rpc/Cargo.toml index 06c0cee87886..ecb581955f0b 100644 --- a/bin/node/rpc/Cargo.toml +++ b/bin/node/rpc/Cargo.toml @@ -16,7 +16,7 @@ node-primitives = { version = "2.0.0", path = "../primitives" } pallet-contracts-rpc = { version = "4.0.0-dev", path = "../../../frame/contracts/rpc/" } pallet-mmr-rpc = { version = "3.0.0", path = "../../../frame/merkle-mountain-range/rpc/" } pallet-transaction-payment-rpc = { version = "4.0.0-dev", path = "../../../frame/transaction-payment/rpc/" } -pallet-iris-rpc = { version = "4.0.0-dev", path = "../../node-template/pallets/iris-assets/rpc/" } +pallet-iris-rpc = { version = "4.0.0-dev", path = "../../node-template/pallets/iris-session/rpc/" } sc-client-api = { version = "4.0.0-dev", path = "../../../client/api" } sc-consensus-babe = { version = "0.10.0-dev", path = "../../../client/consensus/babe" } sc-consensus-babe-rpc = { version = "0.10.0-dev", path = "../../../client/consensus/babe/rpc" } From 104c2cd917b84cf3499c14a4ffa5fee8d8c5c7b5 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Wed, 19 Jan 2022 11:58:40 +0100 Subject: [PATCH 399/695] Split peer slots between full and light nodes (#10688) * Split peer slots between full and light nodes * Rustfmt * Oops, accidentally removed a comma * Remove else --- client/cli/src/params/network_params.rs | 8 +++++-- client/network/src/config.rs | 9 +++++++- client/network/src/protocol.rs | 29 ++++++++++++++++++++++++- client/network/src/protocol/sync.rs | 5 +++++ client/service/src/builder.rs | 3 +-- 5 files changed, 48 insertions(+), 6 deletions(-) diff --git a/client/cli/src/params/network_params.rs b/client/cli/src/params/network_params.rs index 6b7b2680513c..86060486144a 100644 --- a/client/cli/src/params/network_params.rs +++ b/client/cli/src/params/network_params.rs @@ -86,9 +86,12 @@ pub struct NetworkParams { #[structopt(long = "out-peers", value_name = "COUNT", default_value = "25")] pub out_peers: u32, - /// Specify the maximum number of incoming connections we're accepting. + /// Maximum number of inbound full nodes peers. #[structopt(long = "in-peers", value_name = "COUNT", default_value = "25")] pub in_peers: u32, + /// Maximum number of inbound light nodes peers. + #[structopt(long = "in-peers-light", value_name = "COUNT", default_value = "100")] + pub in_peers_light: u32, /// Disable mDNS discovery. /// @@ -203,7 +206,7 @@ impl NetworkParams { boot_nodes, net_config_path, default_peers_set: SetConfig { - in_peers: self.in_peers, + in_peers: self.in_peers + self.in_peers_light, out_peers: self.out_peers, reserved_nodes: self.reserved_nodes.clone(), non_reserved_mode: if self.reserved_only { @@ -212,6 +215,7 @@ impl NetworkParams { NonReservedPeerMode::Accept }, }, + default_peers_set_num_full: self.in_peers + self.out_peers, listen_addresses, public_addresses, extra_sets: Vec::new(), diff --git a/client/network/src/config.rs b/client/network/src/config.rs index 14411ef2aa18..3b9c864c3792 100644 --- a/client/network/src/config.rs +++ b/client/network/src/config.rs @@ -416,6 +416,11 @@ pub struct NetworkConfiguration { pub request_response_protocols: Vec, /// Configuration for the default set of nodes used for block syncing and transactions. pub default_peers_set: SetConfig, + /// Number of substreams to reserve for full nodes for block syncing and transactions. + /// Any other slot will be dedicated to light nodes. + /// + /// This value is implicitly capped to `default_set.out_peers + default_set.in_peers`. + pub default_peers_set_num_full: u32, /// Configuration for extra sets of nodes. pub extra_sets: Vec, /// Client identifier. Sent over the wire for debugging purposes. @@ -473,6 +478,7 @@ impl NetworkConfiguration { node_key: NodeKeyConfig, net_config_path: Option, ) -> Self { + let default_peers_set = SetConfig::default(); Self { net_config_path, listen_addresses: Vec::new(), @@ -480,7 +486,8 @@ impl NetworkConfiguration { boot_nodes: Vec::new(), node_key, request_response_protocols: Vec::new(), - default_peers_set: Default::default(), + default_peers_set_num_full: default_peers_set.in_peers + default_peers_set.out_peers, + default_peers_set, extra_sets: Vec::new(), client_version: client_version.into(), node_name: node_name.into(), diff --git a/client/network/src/protocol.rs b/client/network/src/protocol.rs index a5a826ed4748..3fb40b7199d6 100644 --- a/client/network/src/protocol.rs +++ b/client/network/src/protocol.rs @@ -166,13 +166,19 @@ pub struct Protocol { pending_messages: VecDeque>, config: ProtocolConfig, genesis_hash: B::Hash, + /// State machine that handles the list of in-progress requests. Only full node peers are + /// registered. sync: ChainSync, - // All connected peers + // All connected peers. Contains both full and light node peers. peers: HashMap>, chain: Arc>, /// List of nodes for which we perform additional logging because they are important for the /// user. important_peers: HashSet, + /// Value that was passed as part of the configuration. Used to cap the number of full nodes. + default_peers_set_num_full: usize, + /// Number of slots to allocate to light nodes. + default_peers_set_num_light: usize, /// Used to report reputation changes. peerset_handle: sc_peerset::PeersetHandle, /// Handles opening the unique substream and sending and receiving raw messages. @@ -428,6 +434,12 @@ impl Protocol { genesis_hash: info.genesis_hash, sync, important_peers, + default_peers_set_num_full: network_config.default_peers_set_num_full as usize, + default_peers_set_num_light: { + let total = network_config.default_peers_set.out_peers + + network_config.default_peers_set.in_peers; + total.saturating_sub(network_config.default_peers_set_num_full) as usize + }, peerset_handle: peerset_handle.clone(), behaviour, notification_protocols: network_config @@ -808,6 +820,21 @@ impl Protocol { } } + if status.roles.is_full() && self.sync.num_peers() >= self.default_peers_set_num_full { + debug!(target: "sync", "Too many full nodes, rejecting {}", who); + self.behaviour.disconnect_peer(&who, HARDCODED_PEERSETS_SYNC); + return Err(()) + } + + if status.roles.is_light() && + (self.peers.len() - self.sync.num_peers()) < self.default_peers_set_num_light + { + // Make sure that not all slots are occupied by light clients. + debug!(target: "sync", "Too many light nodes, rejecting {}", who); + self.behaviour.disconnect_peer(&who, HARDCODED_PEERSETS_SYNC); + return Err(()) + } + let peer = Peer { info: PeerInfo { roles: status.roles, diff --git a/client/network/src/protocol/sync.rs b/client/network/src/protocol/sync.rs index af65dec1c3fe..d6513ca2e5b9 100644 --- a/client/network/src/protocol/sync.rs +++ b/client/network/src/protocol/sync.rs @@ -648,6 +648,11 @@ impl ChainSync { self.downloaded_blocks } + /// Returns the current number of peers stored within this state machine. + pub fn num_peers(&self) -> usize { + self.peers.len() + } + /// Handle a new connected peer. /// /// Call this method whenever we connect to a new peer. diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index 269b7be720be..bf681aec94c7 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -808,8 +808,7 @@ where let (handler, protocol_config) = StateRequestHandler::new( &protocol_id, client.clone(), - config.network.default_peers_set.in_peers as usize + - config.network.default_peers_set.out_peers as usize, + config.network.default_peers_set_num_full as usize, ); spawn_handle.spawn("state-request-handler", Some("networking"), handler.run()); protocol_config From fed456fbd73253686f965f4d426776037420637e Mon Sep 17 00:00:00 2001 From: Gavin Wood Date: Wed, 19 Jan 2022 15:08:53 +0100 Subject: [PATCH 400/695] Allow the treasury to have a maximum bound on the bond (#10689) * Allow the treasury to have a maximum bound on the bond * Update frame/treasury/src/lib.rs Co-authored-by: Keith Yeung Co-authored-by: Keith Yeung --- bin/node/runtime/src/lib.rs | 1 + docs/Upgrading-2.0-to-3.0.md | 1 + frame/bounties/src/tests.rs | 1 + frame/child-bounties/src/tests.rs | 1 + frame/tips/src/tests.rs | 1 + frame/treasury/src/lib.rs | 10 +++++++++- frame/treasury/src/tests.rs | 1 + 7 files changed, 15 insertions(+), 1 deletion(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index b2c98e6be139..1f0a33756fe8 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -880,6 +880,7 @@ impl pallet_treasury::Config for Runtime { type OnSlash = (); type ProposalBond = ProposalBond; type ProposalBondMinimum = ProposalBondMinimum; + type ProposalBondMaximum = (); type SpendPeriod = SpendPeriod; type Burn = Burn; type BurnDestination = (); diff --git a/docs/Upgrading-2.0-to-3.0.md b/docs/Upgrading-2.0-to-3.0.md index 45da3811220f..017467ede2d7 100644 --- a/docs/Upgrading-2.0-to-3.0.md +++ b/docs/Upgrading-2.0-to-3.0.md @@ -199,6 +199,7 @@ As mentioned above, Bounties, Tips and Lottery have been extracted out of treasu type OnSlash = (); type ProposalBond = ProposalBond; type ProposalBondMinimum = ProposalBondMinimum; + type ProposalBondMaximum = (); type SpendPeriod = SpendPeriod; type Burn = Burn; + type BurnDestination = (); diff --git a/frame/bounties/src/tests.rs b/frame/bounties/src/tests.rs index 912a78c97570..3206fce9912f 100644 --- a/frame/bounties/src/tests.rs +++ b/frame/bounties/src/tests.rs @@ -117,6 +117,7 @@ impl pallet_treasury::Config for Test { type OnSlash = (); type ProposalBond = ProposalBond; type ProposalBondMinimum = ConstU64<1>; + type ProposalBondMaximum = (); type SpendPeriod = ConstU64<2>; type Burn = Burn; type BurnDestination = (); // Just gets burned. diff --git a/frame/child-bounties/src/tests.rs b/frame/child-bounties/src/tests.rs index 4b713e699f4d..a6748c47b73d 100644 --- a/frame/child-bounties/src/tests.rs +++ b/frame/child-bounties/src/tests.rs @@ -121,6 +121,7 @@ impl pallet_treasury::Config for Test { type OnSlash = (); type ProposalBond = ProposalBond; type ProposalBondMinimum = ConstU64<1>; + type ProposalBondMaximum = (); type SpendPeriod = ConstU64<2>; type Burn = Burn; type BurnDestination = (); diff --git a/frame/tips/src/tests.rs b/frame/tips/src/tests.rs index f9ad431c3948..0c58a949958f 100644 --- a/frame/tips/src/tests.rs +++ b/frame/tips/src/tests.rs @@ -137,6 +137,7 @@ impl pallet_treasury::Config for Test { type OnSlash = (); type ProposalBond = ProposalBond; type ProposalBondMinimum = ConstU64<1>; + type ProposalBondMaximum = (); type SpendPeriod = ConstU64<2>; type Burn = Burn; type BurnDestination = (); // Just gets burned. diff --git a/frame/treasury/src/lib.rs b/frame/treasury/src/lib.rs index 057ee0c6032a..c2dd59953be3 100644 --- a/frame/treasury/src/lib.rs +++ b/frame/treasury/src/lib.rs @@ -168,6 +168,10 @@ pub mod pallet { #[pallet::constant] type ProposalBondMinimum: Get>; + /// Maximum amount of funds that should be placed in a deposit for making a proposal. + #[pallet::constant] + type ProposalBondMaximum: Get>>; + /// Period between successive spends. #[pallet::constant] type SpendPeriod: Get; @@ -404,7 +408,11 @@ impl, I: 'static> Pallet { /// The needed bond for a proposal whose spend is `value`. fn calculate_bond(value: BalanceOf) -> BalanceOf { - T::ProposalBondMinimum::get().max(T::ProposalBond::get() * value) + let mut r = T::ProposalBondMinimum::get().max(T::ProposalBond::get() * value); + if let Some(m) = T::ProposalBondMaximum::get() { + r = r.min(m); + } + r } /// Spend some money! returns number of approvals before spend. diff --git a/frame/treasury/src/tests.rs b/frame/treasury/src/tests.rs index b6d23440a73f..26189f520149 100644 --- a/frame/treasury/src/tests.rs +++ b/frame/treasury/src/tests.rs @@ -115,6 +115,7 @@ impl Config for Test { type OnSlash = (); type ProposalBond = ProposalBond; type ProposalBondMinimum = ConstU64<1>; + type ProposalBondMaximum = (); type SpendPeriod = ConstU64<2>; type Burn = Burn; type BurnDestination = (); // Just gets burned. From bea8f32e7807233ab53045fe8214427e0f136230 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Wed, 19 Jan 2022 16:31:14 +0100 Subject: [PATCH 401/695] Improve usability of `add`+`list_benchmark!` (#10592) * Improve usability of add_benchmark and list_benchmark. Signed-off-by: Oliver Tale-Yazdi * node-template: use new define_benchmarks syntax Signed-off-by: Oliver Tale-Yazdi * make CI happy Signed-off-by: Oliver Tale-Yazdi * remove old imports Signed-off-by: Oliver Tale-Yazdi * fix TryBuild tests Signed-off-by: Oliver Tale-Yazdi * Revert "fix TryBuild tests" This reverts commit 82ea52fd25c0ef5efa46669217694835a7404d4e. * review: remove blank lines Signed-off-by: Oliver Tale-Yazdi --- bin/node-template/runtime/src/lib.rs | 33 ++++--- bin/node/runtime/src/lib.rs | 123 +++++++++++---------------- frame/benchmarking/src/lib.rs | 67 ++++++++++++++- 3 files changed, 133 insertions(+), 90 deletions(-) diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index 08c6c8fb8bcb..2aa6bf1f1ae7 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -318,6 +318,21 @@ pub type Executive = frame_executive::Executive< AllPalletsWithSystem, >; +#[cfg(feature = "runtime-benchmarks")] +#[macro_use] +extern crate frame_benchmarking; + +#[cfg(feature = "runtime-benchmarks")] +mod benches { + define_benchmarks!( + [frame_benchmarking, BaselineBench::] + [frame_system, SystemBench::] + [pallet_balances, Balances] + [pallet_timestamp, Timestamp] + [pallet_template, TemplateModule] + ); +} + impl_runtime_apis! { impl sp_api::Core for Runtime { fn version() -> RuntimeVersion { @@ -455,18 +470,13 @@ impl_runtime_apis! { Vec, Vec, ) { - use frame_benchmarking::{list_benchmark, baseline, Benchmarking, BenchmarkList}; + use frame_benchmarking::{baseline, Benchmarking, BenchmarkList}; use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; use baseline::Pallet as BaselineBench; let mut list = Vec::::new(); - - list_benchmark!(list, extra, frame_benchmarking, BaselineBench::); - list_benchmark!(list, extra, frame_system, SystemBench::); - list_benchmark!(list, extra, pallet_balances, Balances); - list_benchmark!(list, extra, pallet_timestamp, Timestamp); - list_benchmark!(list, extra, pallet_template, TemplateModule); + list_benchmarks!(list, extra); let storage_info = AllPalletsWithSystem::storage_info(); @@ -476,7 +486,7 @@ impl_runtime_apis! { fn dispatch_benchmark( config: frame_benchmarking::BenchmarkConfig ) -> Result, sp_runtime::RuntimeString> { - use frame_benchmarking::{baseline, Benchmarking, BenchmarkBatch, add_benchmark, TrackedStorageKey}; + use frame_benchmarking::{baseline, Benchmarking, BenchmarkBatch, TrackedStorageKey}; use frame_system_benchmarking::Pallet as SystemBench; use baseline::Pallet as BaselineBench; @@ -499,12 +509,7 @@ impl_runtime_apis! { let mut batches = Vec::::new(); let params = (&config, &whitelist); - - add_benchmark!(params, batches, frame_benchmarking, BaselineBench::); - add_benchmark!(params, batches, frame_system, SystemBench::); - add_benchmark!(params, batches, pallet_balances, Balances); - add_benchmark!(params, batches, pallet_timestamp, Timestamp); - add_benchmark!(params, batches, pallet_template, TemplateModule); + add_benchmarks!(params, batches); Ok(batches) } diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 1f0a33756fe8..6034b86987ff 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -1386,6 +1386,51 @@ mod mmr { pub type Hashing = ::Hashing; } +#[cfg(feature = "runtime-benchmarks")] +#[macro_use] +extern crate frame_benchmarking; + +#[cfg(feature = "runtime-benchmarks")] +mod benches { + define_benchmarks!( + [frame_benchmarking, BaselineBench::] + [pallet_assets, Assets] + [pallet_babe, Babe] + [pallet_bags_list, BagsList] + [pallet_balances, Balances] + [pallet_bounties, Bounties] + [pallet_child_bounties, ChildBounties] + [pallet_collective, Council] + [pallet_contracts, Contracts] + [pallet_democracy, Democracy] + [pallet_election_provider_multi_phase, ElectionProviderMultiPhase] + [pallet_elections_phragmen, Elections] + [pallet_gilt, Gilt] + [pallet_grandpa, Grandpa] + [pallet_identity, Identity] + [pallet_im_online, ImOnline] + [pallet_indices, Indices] + [pallet_lottery, Lottery] + [pallet_membership, TechnicalMembership] + [pallet_mmr, Mmr] + [pallet_multisig, Multisig] + [pallet_offences, OffencesBench::] + [pallet_preimage, Preimage] + [pallet_proxy, Proxy] + [pallet_scheduler, Scheduler] + [pallet_session, SessionBench::] + [pallet_staking, Staking] + [frame_system, SystemBench::] + [pallet_timestamp, Timestamp] + [pallet_tips, Tips] + [pallet_transaction_storage, TransactionStorage] + [pallet_treasury, Treasury] + [pallet_uniques, Uniques] + [pallet_utility, Utility] + [pallet_vesting, Vesting] + ); +} + impl_runtime_apis! { impl sp_api::Core for Runtime { fn version() -> RuntimeVersion { @@ -1664,7 +1709,7 @@ impl_runtime_apis! { Vec, Vec, ) { - use frame_benchmarking::{list_benchmark, baseline, Benchmarking, BenchmarkList}; + use frame_benchmarking::{baseline, Benchmarking, BenchmarkList}; use frame_support::traits::StorageInfoTrait; // Trying to add benchmarks directly to the Session Pallet caused cyclic dependency @@ -1676,42 +1721,7 @@ impl_runtime_apis! { use baseline::Pallet as BaselineBench; let mut list = Vec::::new(); - - list_benchmark!(list, extra, frame_benchmarking, BaselineBench::); - list_benchmark!(list, extra, pallet_assets, Assets); - list_benchmark!(list, extra, pallet_babe, Babe); - list_benchmark!(list, extra, pallet_bags_list, BagsList); - list_benchmark!(list, extra, pallet_balances, Balances); - list_benchmark!(list, extra, pallet_bounties, Bounties); - list_benchmark!(list, extra, pallet_child_bounties, ChildBounties); - list_benchmark!(list, extra, pallet_collective, Council); - list_benchmark!(list, extra, pallet_contracts, Contracts); - list_benchmark!(list, extra, pallet_democracy, Democracy); - list_benchmark!(list, extra, pallet_election_provider_multi_phase, ElectionProviderMultiPhase); - list_benchmark!(list, extra, pallet_elections_phragmen, Elections); - list_benchmark!(list, extra, pallet_gilt, Gilt); - list_benchmark!(list, extra, pallet_grandpa, Grandpa); - list_benchmark!(list, extra, pallet_identity, Identity); - list_benchmark!(list, extra, pallet_im_online, ImOnline); - list_benchmark!(list, extra, pallet_indices, Indices); - list_benchmark!(list, extra, pallet_lottery, Lottery); - list_benchmark!(list, extra, pallet_membership, TechnicalMembership); - list_benchmark!(list, extra, pallet_mmr, Mmr); - list_benchmark!(list, extra, pallet_multisig, Multisig); - list_benchmark!(list, extra, pallet_offences, OffencesBench::); - list_benchmark!(list, extra, pallet_preimage, Preimage); - list_benchmark!(list, extra, pallet_proxy, Proxy); - list_benchmark!(list, extra, pallet_scheduler, Scheduler); - list_benchmark!(list, extra, pallet_session, SessionBench::); - list_benchmark!(list, extra, pallet_staking, Staking); - list_benchmark!(list, extra, frame_system, SystemBench::); - list_benchmark!(list, extra, pallet_timestamp, Timestamp); - list_benchmark!(list, extra, pallet_tips, Tips); - list_benchmark!(list, extra, pallet_transaction_storage, TransactionStorage); - list_benchmark!(list, extra, pallet_treasury, Treasury); - list_benchmark!(list, extra, pallet_uniques, Uniques); - list_benchmark!(list, extra, pallet_utility, Utility); - list_benchmark!(list, extra, pallet_vesting, Vesting); + list_benchmarks!(list, extra); let storage_info = AllPalletsWithSystem::storage_info(); @@ -1721,7 +1731,7 @@ impl_runtime_apis! { fn dispatch_benchmark( config: frame_benchmarking::BenchmarkConfig ) -> Result, sp_runtime::RuntimeString> { - use frame_benchmarking::{baseline, Benchmarking, BenchmarkBatch, add_benchmark, TrackedStorageKey}; + use frame_benchmarking::{baseline, Benchmarking, BenchmarkBatch, TrackedStorageKey}; // Trying to add benchmarks directly to the Session Pallet caused cyclic dependency // issues. To get around that, we separated the Session benchmarks into its own crate, @@ -1755,42 +1765,7 @@ impl_runtime_apis! { let mut batches = Vec::::new(); let params = (&config, &whitelist); - - add_benchmark!(params, batches, frame_benchmarking, BaselineBench::); - add_benchmark!(params, batches, pallet_assets, Assets); - add_benchmark!(params, batches, pallet_babe, Babe); - add_benchmark!(params, batches, pallet_balances, Balances); - add_benchmark!(params, batches, pallet_bags_list, BagsList); - add_benchmark!(params, batches, pallet_bounties, Bounties); - add_benchmark!(params, batches, pallet_child_bounties, ChildBounties); - add_benchmark!(params, batches, pallet_collective, Council); - add_benchmark!(params, batches, pallet_contracts, Contracts); - add_benchmark!(params, batches, pallet_democracy, Democracy); - add_benchmark!(params, batches, pallet_election_provider_multi_phase, ElectionProviderMultiPhase); - add_benchmark!(params, batches, pallet_elections_phragmen, Elections); - add_benchmark!(params, batches, pallet_gilt, Gilt); - add_benchmark!(params, batches, pallet_grandpa, Grandpa); - add_benchmark!(params, batches, pallet_identity, Identity); - add_benchmark!(params, batches, pallet_im_online, ImOnline); - add_benchmark!(params, batches, pallet_indices, Indices); - add_benchmark!(params, batches, pallet_lottery, Lottery); - add_benchmark!(params, batches, pallet_membership, TechnicalMembership); - add_benchmark!(params, batches, pallet_mmr, Mmr); - add_benchmark!(params, batches, pallet_multisig, Multisig); - add_benchmark!(params, batches, pallet_offences, OffencesBench::); - add_benchmark!(params, batches, pallet_preimage, Preimage); - add_benchmark!(params, batches, pallet_proxy, Proxy); - add_benchmark!(params, batches, pallet_scheduler, Scheduler); - add_benchmark!(params, batches, pallet_session, SessionBench::); - add_benchmark!(params, batches, pallet_staking, Staking); - add_benchmark!(params, batches, frame_system, SystemBench::); - add_benchmark!(params, batches, pallet_timestamp, Timestamp); - add_benchmark!(params, batches, pallet_tips, Tips); - add_benchmark!(params, batches, pallet_transaction_storage, TransactionStorage); - add_benchmark!(params, batches, pallet_treasury, Treasury); - add_benchmark!(params, batches, pallet_uniques, Uniques); - add_benchmark!(params, batches, pallet_utility, Utility); - add_benchmark!(params, batches, pallet_vesting, Vesting); + add_benchmarks!(params, batches); Ok(batches) } diff --git a/frame/benchmarking/src/lib.rs b/frame/benchmarking/src/lib.rs index fcc3913cee78..ca836e431e5e 100644 --- a/frame/benchmarking/src/lib.rs +++ b/frame/benchmarking/src/lib.rs @@ -1701,7 +1701,6 @@ pub fn show_benchmark_debug_info( /// type Council2 = TechnicalCommittee; /// add_benchmark!(params, batches, pallet_collective, Council2); // pallet_collective_council_2.rs /// ``` - #[macro_export] macro_rules! add_benchmark { ( $params:ident, $batches:ident, $name:path, $( $location:tt )* ) => ( @@ -1770,6 +1769,20 @@ macro_rules! add_benchmark { ) } +/// Callback for `define_benchmarks` to call `add_benchmark`. +#[macro_export] +macro_rules! cb_add_benchmarks { + // anchor + ( $params:ident, $batches:ident, [ $name:path, $( $location:tt )* ] ) => { + add_benchmark!( $params, $batches, $name, $( $location )* ); + }; + // recursion tail + ( $params:ident, $batches:ident, [ $name:path, $( $location:tt )* ] $([ $names:path, $( $locations:tt )* ])+ ) => { + cb_add_benchmarks!( $params, $batches, [ $name, $( $location )* ] ); + cb_add_benchmarks!( $params, $batches, $([ $names, $( $locations )* ])+ ); + } +} + /// This macro allows users to easily generate a list of benchmarks for the pallets configured /// in the runtime. /// @@ -1789,7 +1802,6 @@ macro_rules! add_benchmark { /// ``` /// /// This should match what exists with the `add_benchmark!` macro. - #[macro_export] macro_rules! list_benchmark { ( $list:ident, $extra:ident, $name:path, $( $location:tt )* ) => ( @@ -1804,3 +1816,54 @@ macro_rules! list_benchmark { $list.push(pallet_benchmarks) ) } + +/// Callback for `define_benchmarks` to call `list_benchmark`. +#[macro_export] +macro_rules! cb_list_benchmarks { + // anchor + ( $list:ident, $extra:ident, [ $name:path, $( $location:tt )* ] ) => { + list_benchmark!( $list, $extra, $name, $( $location )* ); + }; + // recursion tail + ( $list:ident, $extra:ident, [ $name:path, $( $location:tt )* ] $([ $names:path, $( $locations:tt )* ])+ ) => { + cb_list_benchmarks!( $list, $extra, [ $name, $( $location )* ] ); + cb_list_benchmarks!( $list, $extra, $([ $names, $( $locations )* ])+ ); + } +} + +/// Defines pallet configs that `add_benchmarks` and `list_benchmarks` use. +/// Should be preferred instead of having a repetitive list of configs +/// in `add_benchmark` and `list_benchmark`. + +#[macro_export] +macro_rules! define_benchmarks { + ( $([ $names:path, $( $locations:tt )* ])* ) => { + /// Calls `list_benchmark` with all configs from `define_benchmarks` + /// and passes the first two parameters on. + /// + /// Use as: + /// ```ignore + /// list_benchmarks!(list, extra); + /// ``` + #[macro_export] + macro_rules! list_benchmarks { + ( $list:ident, $extra:ident ) => { + cb_list_benchmarks!( $list, $extra, $([ $names, $( $locations )* ])+ ); + } + } + + /// Calls `add_benchmark` with all configs from `define_benchmarks` + /// and passes the first two parameters on. + /// + /// Use as: + /// ```ignore + /// add_benchmarks!(params, batches); + /// ``` + #[macro_export] + macro_rules! add_benchmarks { + ( $params:ident, $batches:ident ) => { + cb_add_benchmarks!( $params, $batches, $([ $names, $( $locations )* ])+ ); + } + } + } +} From 33c518ebbe43d38228ac47e793e4d1c76738a56d Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Wed, 19 Jan 2022 20:58:47 +0100 Subject: [PATCH 402/695] Remove all stale `on_runtime_upgrade` hooks in the runtime (#10650) * Remove all stale on_runtime_upgrade hooks in the runtime * add docs * cleanup * fix warn * fix more warnings * fix offence test * overwrite the damn UItest --- frame/contracts/src/lib.rs | 6 +---- frame/contracts/src/migration.rs | 1 + frame/offences/src/lib.rs | 10 +------ frame/offences/src/migration.rs | 5 ++-- frame/staking/src/pallet/mod.rs | 23 +++------------- frame/support/src/traits/hooks.rs | 9 +++++-- .../genesis_default_not_satisfied.stderr | 6 ++--- frame/uniques/src/lib.rs | 13 +++------- frame/uniques/src/migration.rs | 1 + frame/vesting/src/lib.rs | 26 ++----------------- frame/vesting/src/migrations.rs | 8 +++--- 11 files changed, 28 insertions(+), 80 deletions(-) diff --git a/frame/contracts/src/lib.rs b/frame/contracts/src/lib.rs index 24d3a7f10ef9..36b0e12dcd7f 100644 --- a/frame/contracts/src/lib.rs +++ b/frame/contracts/src/lib.rs @@ -87,12 +87,12 @@ mod gas; mod benchmarking; mod exec; -mod migration; mod schedule; mod storage; mod wasm; pub mod chain_extension; +pub mod migration; pub mod weights; #[cfg(test)] @@ -321,10 +321,6 @@ pub mod pallet { Storage::::process_deletion_queue_batch(weight_limit) .saturating_add(T::WeightInfo::on_initialize()) } - - fn on_runtime_upgrade() -> Weight { - migration::migrate::() - } } #[pallet::call] diff --git a/frame/contracts/src/migration.rs b/frame/contracts/src/migration.rs index 29712a528a72..59d3721ab13c 100644 --- a/frame/contracts/src/migration.rs +++ b/frame/contracts/src/migration.rs @@ -25,6 +25,7 @@ use frame_support::{ }; use sp_std::{marker::PhantomData, prelude::*}; +/// Wrapper for all migrations of this pallet, based on `StorageVersion`. pub fn migrate() -> Weight { use frame_support::traits::StorageVersion; diff --git a/frame/offences/src/lib.rs b/frame/offences/src/lib.rs index 25605d934d57..c12f0d1bcc78 100644 --- a/frame/offences/src/lib.rs +++ b/frame/offences/src/lib.rs @@ -22,7 +22,7 @@ // Ensure we're `no_std` when compiling for Wasm. #![cfg_attr(not(feature = "std"), no_std)] -mod migration; +pub mod migration; mod mock; mod tests; @@ -47,7 +47,6 @@ type ReportIdOf = ::Hash; pub mod pallet { use super::*; use frame_support::pallet_prelude::*; - use frame_system::pallet_prelude::*; #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] @@ -110,13 +109,6 @@ pub mod pallet { /// \[kind, timeslot\]. Offence { kind: Kind, timeslot: OpaqueTimeSlot }, } - - #[pallet::hooks] - impl Hooks> for Pallet { - fn on_runtime_upgrade() -> Weight { - migration::remove_deferred_storage::() - } - } } impl> diff --git a/frame/offences/src/migration.rs b/frame/offences/src/migration.rs index 1984db0b7af3..72c24ef7c3e5 100644 --- a/frame/offences/src/migration.rs +++ b/frame/offences/src/migration.rs @@ -56,8 +56,7 @@ pub fn remove_deferred_storage() -> Weight { #[cfg(test)] mod test { use super::*; - use crate::mock::{new_test_ext, with_on_offence_fractions, Offences, Runtime as T}; - use frame_support::traits::OnRuntimeUpgrade; + use crate::mock::{new_test_ext, with_on_offence_fractions, Runtime as T}; use sp_runtime::Perbill; use sp_staking::offence::OffenceDetails; @@ -87,7 +86,7 @@ mod test { // when assert_eq!( - Offences::on_runtime_upgrade(), + remove_deferred_storage::(), ::DbWeight::get().reads_writes(1, 1), ); diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index fc70d523ac9c..8444034ad49d 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -39,9 +39,9 @@ mod impls; pub use impls::*; use crate::{ - log, migrations, slashing, weights::WeightInfo, ActiveEraInfo, BalanceOf, EraPayout, - EraRewardPoints, Exposure, Forcing, NegativeImbalanceOf, Nominations, PositiveImbalanceOf, - Releases, RewardDestination, SessionInterface, StakingLedger, UnappliedSlash, UnlockChunk, + log, slashing, weights::WeightInfo, ActiveEraInfo, BalanceOf, EraPayout, EraRewardPoints, + Exposure, Forcing, NegativeImbalanceOf, Nominations, PositiveImbalanceOf, Releases, + RewardDestination, SessionInterface, StakingLedger, UnappliedSlash, UnlockChunk, ValidatorPrefs, }; @@ -660,23 +660,6 @@ pub mod pallet { #[pallet::hooks] impl Hooks> for Pallet { - fn on_runtime_upgrade() -> Weight { - if StorageVersion::::get() == Releases::V6_0_0 { - migrations::v7::migrate::() - } else { - T::DbWeight::get().reads(1) - } - } - - #[cfg(feature = "try-runtime")] - fn pre_upgrade() -> Result<(), &'static str> { - if StorageVersion::::get() == Releases::V6_0_0 { - migrations::v7::pre_migrate::() - } else { - Ok(()) - } - } - fn on_initialize(_now: BlockNumberFor) -> Weight { // just return the weight of the on_finalize. T::DbWeight::get().reads(1) diff --git a/frame/support/src/traits/hooks.rs b/frame/support/src/traits/hooks.rs index ffb8dfb821ad..385db4e4d1ad 100644 --- a/frame/support/src/traits/hooks.rs +++ b/frame/support/src/traits/hooks.rs @@ -244,10 +244,15 @@ pub trait Hooks { /// # Warning /// /// This function will be called before we initialized any runtime state, aka `on_initialize` - /// wasn't called yet. So, information like the block number and any other - /// block local data are not accessible. + /// wasn't called yet. So, information like the block number and any other block local data are + /// not accessible. /// /// Return the non-negotiable weight consumed for runtime upgrade. + /// + /// While this function can be freely implemented, using `on_runtime_upgrade` from inside the + /// pallet is discouraged and might get deprecated in the future. Alternatively, export the same + /// logic as a free-function from your pallet, and pass it to `type Executive` from the + /// top-level runtime. fn on_runtime_upgrade() -> crate::weights::Weight { 0 } diff --git a/frame/support/test/tests/pallet_ui/genesis_default_not_satisfied.stderr b/frame/support/test/tests/pallet_ui/genesis_default_not_satisfied.stderr index 057611367fe5..e01f66fa3d19 100644 --- a/frame/support/test/tests/pallet_ui/genesis_default_not_satisfied.stderr +++ b/frame/support/test/tests/pallet_ui/genesis_default_not_satisfied.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `pallet::GenesisConfig: std::default::Default` is not satisfied - --> $DIR/genesis_default_not_satisfied.rs:22:18 + --> tests/pallet_ui/genesis_default_not_satisfied.rs:22:18 | 22 | impl GenesisBuild for GenesisConfig {} | ^^^^^^^^^^^^^^^ the trait `std::default::Default` is not implemented for `pallet::GenesisConfig` | note: required by a bound in `GenesisBuild` - --> $DIR/hooks.rs:297:36 + --> $WORKSPACE/frame/support/src/traits/hooks.rs | -297 | pub trait GenesisBuild: Default + sp_runtime::traits::MaybeSerializeDeserialize { + | pub trait GenesisBuild: Default + sp_runtime::traits::MaybeSerializeDeserialize { | ^^^^^^^ required by this bound in `GenesisBuild` diff --git a/frame/uniques/src/lib.rs b/frame/uniques/src/lib.rs index 33a8866019cf..dde30920b227 100644 --- a/frame/uniques/src/lib.rs +++ b/frame/uniques/src/lib.rs @@ -33,14 +33,13 @@ mod benchmarking; pub mod mock; #[cfg(test)] mod tests; -pub mod weights; mod functions; mod impl_nonfungibles; mod types; -pub use types::*; -mod migration; +pub mod migration; +pub mod weights; use codec::{Decode, Encode, HasCompact}; use frame_support::traits::{BalanceStatus::Reserved, Currency, ReservableCurrency}; @@ -52,6 +51,7 @@ use sp_runtime::{ use sp_std::prelude::*; pub use pallet::*; +pub use types::*; pub use weights::WeightInfo; #[frame_support::pallet] @@ -316,13 +316,6 @@ pub mod pallet { Unapproved, } - #[pallet::hooks] - impl, I: 'static> Hooks> for Pallet { - fn on_runtime_upgrade() -> frame_support::weights::Weight { - migration::migrate_to_v1::() - } - } - impl, I: 'static> Pallet { /// Get the owner of the asset instance, if the asset exists. pub fn owner(class: T::ClassId, instance: T::InstanceId) -> Option { diff --git a/frame/uniques/src/migration.rs b/frame/uniques/src/migration.rs index 71ccc6b07bd7..2bacfc8f43b6 100644 --- a/frame/uniques/src/migration.rs +++ b/frame/uniques/src/migration.rs @@ -22,6 +22,7 @@ use frame_support::{ weights::Weight, }; +/// Migrate the pallet storage to v1. pub fn migrate_to_v1, I: 'static, P: GetStorageVersion + PalletInfoAccess>( ) -> frame_support::weights::Weight { let on_chain_storage_version =

for SnapshotConfig { } /// Description of the transport protocol (for online execution). -#[derive(Debug)] -pub struct Transport { - uri: String, - client: Option, +#[derive(Debug, Clone)] +pub enum Transport { + /// Use the `URI` to open a new WebSocket connection. + Uri(String), + /// Use existing WebSocket connection. + RemoteClient(Arc), } -impl Clone for Transport { - fn clone(&self) -> Self { - Self { uri: self.uri.clone(), client: None } +impl Transport { + fn as_client(&self) -> Option<&WsClient> { + match self { + Self::RemoteClient(client) => Some(&*client), + _ => None, + } + } + + // Open a new WebSocket connection if it's not connected. + async fn map_uri(&mut self) -> Result<(), &'static str> { + if let Self::Uri(uri) = self { + log::debug!(target: LOG_TARGET, "initializing remote client to {:?}", uri); + + let ws_client = WsClientBuilder::default() + .max_request_body_size(u32::MAX) + .build(&uri) + .await + .map_err(|e| { + log::error!(target: LOG_TARGET, "error: {:?}", e); + "failed to build ws client" + })?; + + *self = Self::RemoteClient(Arc::new(ws_client)) + } + + Ok(()) } } impl From for Transport { - fn from(t: String) -> Self { - Self { uri: t, client: None } + fn from(uri: String) -> Self { + Transport::Uri(uri) + } +} + +impl From> for Transport { + fn from(client: Arc) -> Self { + Transport::RemoteClient(client) } } @@ -161,8 +193,7 @@ impl OnlineConfig { /// Return rpc (ws) client. fn rpc_client(&self) -> &WsClient { self.transport - .client - .as_ref() + .as_client() .expect("ws client must have been initialized by now; qed.") } } @@ -170,7 +201,7 @@ impl OnlineConfig { impl Default for OnlineConfig { fn default() -> Self { Self { - transport: Transport { uri: DEFAULT_TARGET.to_owned(), client: None }, + transport: Transport::Uri(DEFAULT_TARGET.to_owned()), at: None, state_snapshot: None, pallets: vec![], @@ -629,19 +660,8 @@ impl Builder { } pub(crate) async fn init_remote_client(&mut self) -> Result<(), &'static str> { - let mut online = self.as_online_mut(); - log::debug!(target: LOG_TARGET, "initializing remote client to {:?}", online.transport.uri); - // First, initialize the ws client. - let ws_client = WsClientBuilder::default() - .max_request_body_size(u32::MAX) - .build(&online.transport.uri) - .await - .map_err(|e| { - log::error!(target: LOG_TARGET, "error: {:?}", e); - "failed to build ws client" - })?; - online.transport.client = Some(ws_client); + self.as_online_mut().transport.map_uri().await?; // Then, if `at` is not set, set it. if self.as_online().at.is_none() { diff --git a/utils/frame/remote-externalities/src/rpc_api.rs b/utils/frame/remote-externalities/src/rpc_api.rs index 13254741c1ac..37555de480d4 100644 --- a/utils/frame/remote-externalities/src/rpc_api.rs +++ b/utils/frame/remote-externalities/src/rpc_api.rs @@ -19,8 +19,8 @@ // TODO: Consolidate one off RPC calls https://github.com/paritytech/substrate/issues/8988 use jsonrpsee::{ + core::client::ClientT, rpc_params, - types::traits::Client, ws_client::{WsClient, WsClientBuilder}, }; use sp_runtime::{ @@ -73,7 +73,7 @@ where Ok(signed_block.block) } -/// Build a website client that connects to `from`. +/// Build a websocket client that connects to `from`. async fn build_client>(from: S) -> Result { WsClientBuilder::default() .max_request_body_size(u32::MAX) From 13076478968818443b9bb97425b7db09e00e2fc0 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Fri, 28 Jan 2022 13:25:12 +0100 Subject: [PATCH 433/695] Add attributes and documentation to fork_id (#10746) * Add attributes and documentation to fork_id * Update client/chain-spec/src/chain_spec.rs Co-authored-by: Sacha Lansky Co-authored-by: Sacha Lansky --- client/chain-spec/src/chain_spec.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/client/chain-spec/src/chain_spec.rs b/client/chain-spec/src/chain_spec.rs index a22a68d2944f..2412a7cdf83f 100644 --- a/client/chain-spec/src/chain_spec.rs +++ b/client/chain-spec/src/chain_spec.rs @@ -164,6 +164,10 @@ struct ClientSpec { boot_nodes: Vec, telemetry_endpoints: Option, protocol_id: Option, + /// Arbitrary string. Nodes will only synchronize with other nodes that have the same value + /// in their `fork_id`. This can be used in order to segregate nodes in cases when multiple + /// chains have the same genesis hash. + #[serde(default = "Default::default", skip_serializing_if = "Option::is_none")] fork_id: Option, properties: Option, #[serde(flatten)] From fb4f3ecb89ce4c3f144636a9ce9766325946dd58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Miko=C5=82ajczyk?= Date: Fri, 28 Jan 2022 19:37:54 +0100 Subject: [PATCH 434/695] Fix lazy batch contract removal (#10728) * Fix lazy batch contract removal * Apply suggestions * Qualify ChildInfo * Negligible change to restart pipeline * Revert "Negligible change to restart pipeline" This reverts commit b38abb622a17de9f0d19b3eadcea611ead1a7251. * cargo run --quiet --profile=production --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_contracts --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/contracts/src/weights.rs --template=./.maintain/frame-weight-template.hbs Co-authored-by: Parity Bot --- frame/contracts/src/storage.rs | 6 +- frame/contracts/src/tests.rs | 53 ++ frame/contracts/src/weights.rs | 1154 ++++++++++++++++---------------- 3 files changed, 634 insertions(+), 579 deletions(-) diff --git a/frame/contracts/src/storage.rs b/frame/contracts/src/storage.rs index de65059b5b17..51a43a178242 100644 --- a/frame/contracts/src/storage.rs +++ b/frame/contracts/src/storage.rs @@ -268,7 +268,9 @@ where let mut queue = >::get(); - if let (Some(trie), true) = (queue.get(0), remaining_key_budget > 0) { + while !queue.is_empty() && remaining_key_budget > 0 { + // Cannot panic due to loop condition + let trie = &mut queue[0]; let outcome = child::kill_storage(&child_trie_info(&trie.trie_id), Some(remaining_key_budget)); let keys_removed = match outcome { @@ -276,7 +278,7 @@ where KillStorageResult::SomeRemaining(count) => count, KillStorageResult::AllRemoved(count) => { // We do not care to preserve order. The contract is deleted already and - // noone waits for the trie to be deleted. + // no one waits for the trie to be deleted. queue.swap_remove(0); count }, diff --git a/frame/contracts/src/tests.rs b/frame/contracts/src/tests.rs index 3d39bc6d78d9..f0bb8f5ffd11 100644 --- a/frame/contracts/src/tests.rs +++ b/frame/contracts/src/tests.rs @@ -1513,6 +1513,59 @@ fn lazy_removal_works() { }); } +#[test] +fn lazy_batch_removal_works() { + let (code, hash) = compile_module::("self_destruct").unwrap(); + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + let min_balance = ::Currency::minimum_balance(); + let _ = Balances::deposit_creating(&ALICE, 1000 * min_balance); + let mut tries: Vec = vec![]; + + for i in 0..3u8 { + assert_ok!(Contracts::instantiate_with_code( + Origin::signed(ALICE), + min_balance * 100, + GAS_LIMIT, + None, + code.clone(), + vec![], + vec![i], + ),); + + let addr = Contracts::contract_address(&ALICE, &hash, &[i]); + let info = >::get(&addr).unwrap(); + let trie = &info.child_trie_info(); + + // Put value into the contracts child trie + child::put(trie, &[99], &42); + + // Terminate the contract. Contract info should be gone, but value should be still there + // as the lazy removal did not run, yet. + assert_ok!(Contracts::call( + Origin::signed(ALICE), + addr.clone(), + 0, + GAS_LIMIT, + None, + vec![] + )); + + assert!(!>::contains_key(&addr)); + assert_matches!(child::get(trie, &[99]), Some(42)); + + tries.push(trie.clone()) + } + + // Run single lazy removal + Contracts::on_initialize(Weight::max_value()); + + // The single lazy removal should have removed all queued tries + for trie in tries.iter() { + assert_matches!(child::get::(trie, &[99]), None); + } + }); +} + #[test] fn lazy_removal_partial_remove_works() { let (code, hash) = compile_module::("self_destruct").unwrap(); diff --git a/frame/contracts/src/weights.rs b/frame/contracts/src/weights.rs index 2d74df9627db..acc13104d928 100644 --- a/frame/contracts/src/weights.rs +++ b/frame/contracts/src/weights.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_contracts //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-01-28, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -156,32 +156,32 @@ pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize() -> Weight { - (1_636_000 as Weight) + (1_601_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn on_initialize_per_trie_key(k: u32, ) -> Weight { - (7_840_000 as Weight) + (10_543_000 as Weight) // Standard Error: 0 - .saturating_add((752_000 as Weight).saturating_mul(k as Weight)) + .saturating_add((739_000 as Weight).saturating_mul(k as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) } // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize_per_queue_item(q: u32, ) -> Weight { - (31_915_000 as Weight) - // Standard Error: 1_000 - .saturating_add((98_000 as Weight).saturating_mul(q as Weight)) + (0 as Weight) + // Standard Error: 3_000 + .saturating_add((2_285_000 as Weight).saturating_mul(q as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Contracts PristineCode (r:1 w:0) // Storage: Contracts CodeStorage (r:0 w:1) fn reinstrument(c: u32, ) -> Weight { - (18_897_000 as Weight) - // Standard Error: 32_000 - .saturating_add((69_663_000 as Weight).saturating_mul(c as Weight)) + (16_846_000 as Weight) + // Standard Error: 33_000 + .saturating_add((71_629_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -190,9 +190,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call_with_code_kb(c: u32, ) -> Weight { - (204_947_000 as Weight) - // Standard Error: 54_000 - .saturating_add((58_293_000 as Weight).saturating_mul(c as Weight)) + (160_645_000 as Weight) + // Standard Error: 51_000 + .saturating_add((60_029_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -204,11 +204,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn instantiate_with_code(c: u32, s: u32, ) -> Weight { - (211_187_000 as Weight) - // Standard Error: 114_000 - .saturating_add((156_529_000 as Weight).saturating_mul(c as Weight)) - // Standard Error: 7_000 - .saturating_add((1_830_000 as Weight).saturating_mul(s as Weight)) + (160_721_000 as Weight) + // Standard Error: 200_000 + .saturating_add((156_185_000 as Weight).saturating_mul(c as Weight)) + // Standard Error: 13_000 + .saturating_add((1_785_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } @@ -219,9 +219,9 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn instantiate(s: u32, ) -> Weight { - (150_485_000 as Weight) + (145_929_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_769_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((1_743_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } @@ -230,7 +230,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call() -> Weight { - (117_274_000 as Weight) + (114_204_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -238,9 +238,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn upload_code(c: u32, ) -> Weight { - (51_126_000 as Weight) - // Standard Error: 49_000 - .saturating_add((72_622_000 as Weight).saturating_mul(c as Weight)) + (51_131_000 as Weight) + // Standard Error: 48_000 + .saturating_add((70_405_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -248,7 +248,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:0 w:1) // Storage: Contracts PristineCode (r:0 w:1) fn remove_code() -> Weight { - (24_221_000 as Weight) + (24_452_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -257,9 +257,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_caller(r: u32, ) -> Weight { - (219_790_000 as Weight) - // Standard Error: 126_000 - .saturating_add((56_383_000 as Weight).saturating_mul(r as Weight)) + (168_803_000 as Weight) + // Standard Error: 119_000 + .saturating_add((56_278_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -268,9 +268,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_address(r: u32, ) -> Weight { - (218_377_000 as Weight) - // Standard Error: 117_000 - .saturating_add((57_243_000 as Weight).saturating_mul(r as Weight)) + (170_921_000 as Weight) + // Standard Error: 150_000 + .saturating_add((56_973_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -279,9 +279,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas_left(r: u32, ) -> Weight { - (217_999_000 as Weight) - // Standard Error: 104_000 - .saturating_add((56_674_000 as Weight).saturating_mul(r as Weight)) + (168_953_000 as Weight) + // Standard Error: 116_000 + .saturating_add((56_032_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -290,9 +290,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_balance(r: u32, ) -> Weight { - (226_932_000 as Weight) - // Standard Error: 155_000 - .saturating_add((147_401_000 as Weight).saturating_mul(r as Weight)) + (170_043_000 as Weight) + // Standard Error: 147_000 + .saturating_add((152_039_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -301,9 +301,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_value_transferred(r: u32, ) -> Weight { - (233_107_000 as Weight) - // Standard Error: 110_000 - .saturating_add((55_334_000 as Weight).saturating_mul(r as Weight)) + (183_371_000 as Weight) + // Standard Error: 111_000 + .saturating_add((54_799_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -312,9 +312,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_minimum_balance(r: u32, ) -> Weight { - (235_364_000 as Weight) - // Standard Error: 122_000 - .saturating_add((54_700_000 as Weight).saturating_mul(r as Weight)) + (181_993_000 as Weight) + // Standard Error: 127_000 + .saturating_add((54_617_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -323,9 +323,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_block_number(r: u32, ) -> Weight { - (232_875_000 as Weight) - // Standard Error: 108_000 - .saturating_add((54_510_000 as Weight).saturating_mul(r as Weight)) + (179_543_000 as Weight) + // Standard Error: 96_000 + .saturating_add((54_526_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -334,9 +334,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_now(r: u32, ) -> Weight { - (226_089_000 as Weight) - // Standard Error: 126_000 - .saturating_add((54_899_000 as Weight).saturating_mul(r as Weight)) + (174_365_000 as Weight) + // Standard Error: 117_000 + .saturating_add((54_433_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -346,9 +346,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0) fn seal_weight_to_fee(r: u32, ) -> Weight { - (234_746_000 as Weight) - // Standard Error: 146_000 - .saturating_add((132_861_000 as Weight).saturating_mul(r as Weight)) + (186_003_000 as Weight) + // Standard Error: 187_000 + .saturating_add((133_644_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -357,9 +357,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas(r: u32, ) -> Weight { - (96_247_000 as Weight) - // Standard Error: 70_000 - .saturating_add((27_918_000 as Weight).saturating_mul(r as Weight)) + (91_771_000 as Weight) + // Standard Error: 68_000 + .saturating_add((28_003_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -368,9 +368,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input(r: u32, ) -> Weight { - (221_631_000 as Weight) - // Standard Error: 139_000 - .saturating_add((54_382_000 as Weight).saturating_mul(r as Weight)) + (170_110_000 as Weight) + // Standard Error: 104_000 + .saturating_add((53_937_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -379,9 +379,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input_per_kb(n: u32, ) -> Weight { - (306_449_000 as Weight) - // Standard Error: 3_000 - .saturating_add((11_919_000 as Weight).saturating_mul(n as Weight)) + (251_576_000 as Weight) + // Standard Error: 9_000 + .saturating_add((10_613_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -390,9 +390,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return(r: u32, ) -> Weight { - (222_176_000 as Weight) - // Standard Error: 72_000 - .saturating_add((3_223_000 as Weight).saturating_mul(r as Weight)) + (176_897_000 as Weight) + // Standard Error: 119_000 + .saturating_add((3_095_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -401,9 +401,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return_per_kb(n: u32, ) -> Weight { - (211_079_000 as Weight) + (161_820_000 as Weight) // Standard Error: 0 - .saturating_add((237_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((184_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -414,9 +414,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts DeletionQueue (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_terminate(r: u32, ) -> Weight { - (213_994_000 as Weight) - // Standard Error: 104_000 - .saturating_add((64_453_000 as Weight).saturating_mul(r as Weight)) + (163_213_000 as Weight) + // Standard Error: 922_000 + .saturating_add((65_249_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((4 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -428,9 +428,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) fn seal_random(r: u32, ) -> Weight { - (228_281_000 as Weight) - // Standard Error: 150_000 - .saturating_add((166_949_000 as Weight).saturating_mul(r as Weight)) + (178_636_000 as Weight) + // Standard Error: 189_000 + .saturating_add((166_008_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -439,9 +439,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_deposit_event(r: u32, ) -> Weight { - (230_348_000 as Weight) - // Standard Error: 163_000 - .saturating_add((288_679_000 as Weight).saturating_mul(r as Weight)) + (187_377_000 as Weight) + // Standard Error: 186_000 + .saturating_add((289_005_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -451,11 +451,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: System EventTopics (r:100 w:100) fn seal_deposit_event_per_topic_and_kb(t: u32, n: u32, ) -> Weight { - (601_613_000 as Weight) - // Standard Error: 1_566_000 - .saturating_add((279_038_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 308_000 - .saturating_add((84_818_000 as Weight).saturating_mul(n as Weight)) + (487_726_000 as Weight) + // Standard Error: 1_980_000 + .saturating_add((291_760_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 390_000 + .saturating_add((78_950_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(t as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -466,17 +466,17 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_debug_message(r: u32, ) -> Weight { - (113_578_000 as Weight) - // Standard Error: 67_000 - .saturating_add((44_899_000 as Weight).saturating_mul(r as Weight)) + (105_118_000 as Weight) + // Standard Error: 80_000 + .saturating_add((45_277_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage(r: u32, ) -> Weight { - (59_019_000 as Weight) - // Standard Error: 995_000 - .saturating_add((414_759_000 as Weight).saturating_mul(r as Weight)) + (0 as Weight) + // Standard Error: 1_084_000 + .saturating_add((423_125_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -484,25 +484,25 @@ impl WeightInfo for SubstrateWeight { } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage_per_new_kb(n: u32, ) -> Weight { - (620_483_000 as Weight) - // Standard Error: 242_000 - .saturating_add((30_945_000 as Weight).saturating_mul(n as Weight)) + (565_293_000 as Weight) + // Standard Error: 257_000 + .saturating_add((26_134_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage_per_old_kb(n: u32, ) -> Weight { - (632_391_000 as Weight) - // Standard Error: 317_000 - .saturating_add((11_431_000 as Weight).saturating_mul(n as Weight)) + (582_851_000 as Weight) + // Standard Error: 306_000 + .saturating_add((11_991_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage(r: u32, ) -> Weight { - (96_628_000 as Weight) - // Standard Error: 878_000 - .saturating_add((387_212_000 as Weight).saturating_mul(r as Weight)) + (51_270_000 as Weight) + // Standard Error: 883_000 + .saturating_add((394_518_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -510,51 +510,51 @@ impl WeightInfo for SubstrateWeight { } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage_per_kb(n: u32, ) -> Weight { - (625_960_000 as Weight) - // Standard Error: 270_000 - .saturating_add((11_170_000 as Weight).saturating_mul(n as Weight)) + (585_361_000 as Weight) + // Standard Error: 263_000 + .saturating_add((10_855_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage(r: u32, ) -> Weight { - (115_155_000 as Weight) - // Standard Error: 741_000 - .saturating_add((331_711_000 as Weight).saturating_mul(r as Weight)) + (60_404_000 as Weight) + // Standard Error: 667_000 + .saturating_add((335_130_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage_per_kb(n: u32, ) -> Weight { - (582_560_000 as Weight) - // Standard Error: 360_000 - .saturating_add((68_427_000 as Weight).saturating_mul(n as Weight)) + (539_500_000 as Weight) + // Standard Error: 378_000 + .saturating_add((62_855_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(104 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_contains_storage(r: u32, ) -> Weight { - (130_096_000 as Weight) - // Standard Error: 555_000 - .saturating_add((294_514_000 as Weight).saturating_mul(r as Weight)) + (58_301_000 as Weight) + // Standard Error: 701_000 + .saturating_add((301_511_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_contains_storage_per_kb(n: u32, ) -> Weight { - (528_701_000 as Weight) - // Standard Error: 246_000 - .saturating_add((10_375_000 as Weight).saturating_mul(n as Weight)) + (485_967_000 as Weight) + // Standard Error: 266_000 + .saturating_add((10_314_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(104 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage(r: u32, ) -> Weight { - (95_349_000 as Weight) - // Standard Error: 906_000 - .saturating_add((430_051_000 as Weight).saturating_mul(r as Weight)) + (42_688_000 as Weight) + // Standard Error: 889_000 + .saturating_add((436_932_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -562,9 +562,9 @@ impl WeightInfo for SubstrateWeight { } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage_per_kb(n: u32, ) -> Weight { - (676_606_000 as Weight) - // Standard Error: 389_000 - .saturating_add((70_517_000 as Weight).saturating_mul(n as Weight)) + (638_201_000 as Weight) + // Standard Error: 373_000 + .saturating_add((64_277_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().writes(103 as Weight)) } @@ -573,9 +573,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_transfer(r: u32, ) -> Weight { - (131_194_000 as Weight) - // Standard Error: 1_256_000 - .saturating_add((1_772_590_000 as Weight).saturating_mul(r as Weight)) + (49_486_000 as Weight) + // Standard Error: 1_275_000 + .saturating_add((1_790_231_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -586,9 +586,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_call(r: u32, ) -> Weight { - (2_463_174_000 as Weight) - // Standard Error: 19_404_000 - .saturating_add((19_548_986_000 as Weight).saturating_mul(r as Weight)) + (2_498_893_000 as Weight) + // Standard Error: 20_838_000 + .saturating_add((14_474_373_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -599,13 +599,13 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:2 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_call_per_transfer_input_output_kb(t: u32, i: u32, o: u32, ) -> Weight { - (21_356_548_000 as Weight) - // Standard Error: 31_719_000 - .saturating_add((1_874_230_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 11_000 - .saturating_add((23_243_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 12_000 - .saturating_add((34_825_000 as Weight).saturating_mul(o as Weight)) + (16_423_215_000 as Weight) + // Standard Error: 43_595_000 + .saturating_add((1_644_304_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 15_000 + .saturating_add((17_700_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 16_000 + .saturating_add((28_564_000 as Weight).saturating_mul(o as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().reads((101 as Weight).saturating_mul(t as Weight))) .saturating_add(T::DbWeight::get().writes(101 as Weight)) @@ -619,8 +619,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts OwnerInfoOf (r:100 w:100) fn seal_instantiate(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 49_981_000 - .saturating_add((28_988_348_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 52_924_000 + .saturating_add((24_062_215_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().reads((400 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -633,13 +633,13 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts AccountCounter (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_instantiate_per_input_output_salt_kb(i: u32, o: u32, s: u32, ) -> Weight { - (24_726_887_000 as Weight) - // Standard Error: 32_000 - .saturating_add((23_702_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 32_000 - .saturating_add((35_841_000 as Weight).saturating_mul(o as Weight)) - // Standard Error: 32_000 - .saturating_add((161_159_000 as Weight).saturating_mul(s as Weight)) + (19_940_217_000 as Weight) + // Standard Error: 36_000 + .saturating_add((17_853_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 36_000 + .saturating_add((29_592_000 as Weight).saturating_mul(o as Weight)) + // Standard Error: 36_000 + .saturating_add((155_914_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(208 as Weight)) .saturating_add(T::DbWeight::get().writes(206 as Weight)) } @@ -648,9 +648,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256(r: u32, ) -> Weight { - (221_804_000 as Weight) + (166_372_000 as Weight) // Standard Error: 150_000 - .saturating_add((84_131_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((85_445_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -659,9 +659,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256_per_kb(n: u32, ) -> Weight { - (357_186_000 as Weight) - // Standard Error: 23_000 - .saturating_add((469_081_000 as Weight).saturating_mul(n as Weight)) + (323_005_000 as Weight) + // Standard Error: 28_000 + .saturating_add((464_801_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -670,9 +670,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256(r: u32, ) -> Weight { - (220_729_000 as Weight) - // Standard Error: 166_000 - .saturating_add((101_538_000 as Weight).saturating_mul(r as Weight)) + (167_869_000 as Weight) + // Standard Error: 156_000 + .saturating_add((96_037_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -681,9 +681,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256_per_kb(n: u32, ) -> Weight { - (272_756_000 as Weight) - // Standard Error: 18_000 - .saturating_add((311_130_000 as Weight).saturating_mul(n as Weight)) + (235_448_000 as Weight) + // Standard Error: 30_000 + .saturating_add((306_489_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -692,9 +692,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256(r: u32, ) -> Weight { - (215_784_000 as Weight) - // Standard Error: 150_000 - .saturating_add((68_809_000 as Weight).saturating_mul(r as Weight)) + (166_113_000 as Weight) + // Standard Error: 128_000 + .saturating_add((68_810_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -703,9 +703,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256_per_kb(n: u32, ) -> Weight { - (256_009_000 as Weight) - // Standard Error: 12_000 - .saturating_add((124_552_000 as Weight).saturating_mul(n as Weight)) + (276_885_000 as Weight) + // Standard Error: 16_000 + .saturating_add((120_098_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -714,9 +714,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128(r: u32, ) -> Weight { - (216_413_000 as Weight) - // Standard Error: 134_000 - .saturating_add((68_281_000 as Weight).saturating_mul(r as Weight)) + (168_106_000 as Weight) + // Standard Error: 131_000 + .saturating_add((68_109_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -725,9 +725,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128_per_kb(n: u32, ) -> Weight { - (254_477_000 as Weight) - // Standard Error: 13_000 - .saturating_add((124_483_000 as Weight).saturating_mul(n as Weight)) + (244_443_000 as Weight) + // Standard Error: 19_000 + .saturating_add((120_286_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -736,265 +736,265 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_ecdsa_recover(r: u32, ) -> Weight { - (179_001_000 as Weight) - // Standard Error: 1_674_000 - .saturating_add((15_397_995_000 as Weight).saturating_mul(r as Weight)) + (207_765_000 as Weight) + // Standard Error: 1_529_000 + .saturating_add((15_403_795_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn instr_i64const(r: u32, ) -> Weight { - (46_905_000 as Weight) - // Standard Error: 12_000 - .saturating_add((794_000 as Weight).saturating_mul(r as Weight)) + (46_110_000 as Weight) + // Standard Error: 11_000 + .saturating_add((813_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64load(r: u32, ) -> Weight { - (53_636_000 as Weight) + (52_944_000 as Weight) // Standard Error: 12_000 - .saturating_add((2_476_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_501_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64store(r: u32, ) -> Weight { - (53_199_000 as Weight) + (52_968_000 as Weight) // Standard Error: 12_000 - .saturating_add((2_547_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_528_000 as Weight).saturating_mul(r as Weight)) } fn instr_select(r: u32, ) -> Weight { - (37_268_000 as Weight) + (36_871_000 as Weight) // Standard Error: 17_000 - .saturating_add((2_987_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_994_000 as Weight).saturating_mul(r as Weight)) } fn instr_if(r: u32, ) -> Weight { - (37_138_000 as Weight) + (36_834_000 as Weight) // Standard Error: 16_000 - .saturating_add((3_057_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((3_060_000 as Weight).saturating_mul(r as Weight)) } fn instr_br(r: u32, ) -> Weight { - (39_353_000 as Weight) - // Standard Error: 17_000 - .saturating_add((1_939_000 as Weight).saturating_mul(r as Weight)) + (39_250_000 as Weight) + // Standard Error: 16_000 + .saturating_add((1_933_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_if(r: u32, ) -> Weight { - (38_883_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_495_000 as Weight).saturating_mul(r as Weight)) + (38_302_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_496_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table(r: u32, ) -> Weight { - (45_030_000 as Weight) + (44_800_000 as Weight) // Standard Error: 21_000 - .saturating_add((2_398_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_407_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table_per_entry(e: u32, ) -> Weight { - (47_281_000 as Weight) + (46_996_000 as Weight) // Standard Error: 3_000 - .saturating_add((29_000 as Weight).saturating_mul(e as Weight)) + .saturating_add((27_000 as Weight).saturating_mul(e as Weight)) } fn instr_call(r: u32, ) -> Weight { - (49_074_000 as Weight) - // Standard Error: 20_000 - .saturating_add((19_991_000 as Weight).saturating_mul(r as Weight)) + (48_704_000 as Weight) + // Standard Error: 24_000 + .saturating_add((20_212_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect(r: u32, ) -> Weight { - (50_071_000 as Weight) - // Standard Error: 29_000 - .saturating_add((30_156_000 as Weight).saturating_mul(r as Weight)) + (52_546_000 as Weight) + // Standard Error: 32_000 + .saturating_add((29_995_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect_per_param(p: u32, ) -> Weight { - (84_902_000 as Weight) + (85_521_000 as Weight) // Standard Error: 5_000 - .saturating_add((1_124_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((1_117_000 as Weight).saturating_mul(p as Weight)) } fn instr_local_get(r: u32, ) -> Weight { - (39_054_000 as Weight) + (39_081_000 as Weight) // Standard Error: 14_000 - .saturating_add((1_352_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_338_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_set(r: u32, ) -> Weight { - (39_190_000 as Weight) + (39_014_000 as Weight) // Standard Error: 14_000 - .saturating_add((1_370_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_365_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_tee(r: u32, ) -> Weight { - (41_830_000 as Weight) - // Standard Error: 13_000 - .saturating_add((1_878_000 as Weight).saturating_mul(r as Weight)) + (41_269_000 as Weight) + // Standard Error: 12_000 + .saturating_add((1_879_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_get(r: u32, ) -> Weight { - (40_764_000 as Weight) - // Standard Error: 13_000 - .saturating_add((1_931_000 as Weight).saturating_mul(r as Weight)) + (40_341_000 as Weight) + // Standard Error: 12_000 + .saturating_add((1_944_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_set(r: u32, ) -> Weight { - (46_309_000 as Weight) + (45_833_000 as Weight) // Standard Error: 12_000 - .saturating_add((1_745_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_757_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_current(r: u32, ) -> Weight { - (47_071_000 as Weight) + (46_780_000 as Weight) // Standard Error: 12_000 - .saturating_add((797_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((806_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_grow(r: u32, ) -> Weight { - (49_773_000 as Weight) - // Standard Error: 1_442_000 - .saturating_add((227_666_000 as Weight).saturating_mul(r as Weight)) + (49_585_000 as Weight) + // Standard Error: 1_723_000 + .saturating_add((166_106_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64clz(r: u32, ) -> Weight { - (43_879_000 as Weight) - // Standard Error: 12_000 - .saturating_add((1_486_000 as Weight).saturating_mul(r as Weight)) + (43_423_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_494_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ctz(r: u32, ) -> Weight { - (43_883_000 as Weight) - // Standard Error: 12_000 - .saturating_add((1_484_000 as Weight).saturating_mul(r as Weight)) + (43_237_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_499_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64popcnt(r: u32, ) -> Weight { - (43_415_000 as Weight) + (43_308_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_495_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_505_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eqz(r: u32, ) -> Weight { - (43_567_000 as Weight) + (43_440_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_493_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_503_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendsi32(r: u32, ) -> Weight { - (41_332_000 as Weight) - // Standard Error: 12_000 - .saturating_add((1_912_000 as Weight).saturating_mul(r as Weight)) + (40_782_000 as Weight) + // Standard Error: 13_000 + .saturating_add((1_948_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendui32(r: u32, ) -> Weight { - (41_331_000 as Weight) + (41_210_000 as Weight) // Standard Error: 12_000 - .saturating_add((1_911_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_925_000 as Weight).saturating_mul(r as Weight)) } fn instr_i32wrapi64(r: u32, ) -> Weight { - (43_704_000 as Weight) + (43_108_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_487_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_506_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eq(r: u32, ) -> Weight { - (37_103_000 as Weight) + (36_501_000 as Weight) // Standard Error: 16_000 - .saturating_add((2_467_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_490_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ne(r: u32, ) -> Weight { - (36_680_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_487_000 as Weight).saturating_mul(r as Weight)) + (36_289_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_494_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64lts(r: u32, ) -> Weight { - (36_659_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_494_000 as Weight).saturating_mul(r as Weight)) + (36_414_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_492_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ltu(r: u32, ) -> Weight { - (36_491_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_495_000 as Weight).saturating_mul(r as Weight)) + (36_205_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_498_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gts(r: u32, ) -> Weight { - (36_440_000 as Weight) + (36_648_000 as Weight) // Standard Error: 16_000 - .saturating_add((2_499_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_473_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gtu(r: u32, ) -> Weight { - (36_477_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_500_000 as Weight).saturating_mul(r as Weight)) + (36_530_000 as Weight) + // Standard Error: 18_000 + .saturating_add((2_488_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64les(r: u32, ) -> Weight { - (36_561_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_498_000 as Weight).saturating_mul(r as Weight)) + (36_622_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_483_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64leu(r: u32, ) -> Weight { - (36_418_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_501_000 as Weight).saturating_mul(r as Weight)) + (36_465_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_490_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ges(r: u32, ) -> Weight { - (36_835_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_484_000 as Weight).saturating_mul(r as Weight)) + (36_291_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_494_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64geu(r: u32, ) -> Weight { - (36_873_000 as Weight) + (36_454_000 as Weight) // Standard Error: 16_000 - .saturating_add((2_469_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_483_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64add(r: u32, ) -> Weight { - (37_013_000 as Weight) + (36_801_000 as Weight) // Standard Error: 16_000 - .saturating_add((2_466_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_468_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64sub(r: u32, ) -> Weight { - (36_885_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_469_000 as Weight).saturating_mul(r as Weight)) + (36_670_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_483_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64mul(r: u32, ) -> Weight { - (36_696_000 as Weight) + (36_388_000 as Weight) // Standard Error: 17_000 - .saturating_add((2_487_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_494_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divs(r: u32, ) -> Weight { - (36_924_000 as Weight) + (36_952_000 as Weight) // Standard Error: 16_000 - .saturating_add((3_118_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((3_113_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divu(r: u32, ) -> Weight { - (36_819_000 as Weight) + (36_634_000 as Weight) // Standard Error: 16_000 - .saturating_add((2_784_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_789_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rems(r: u32, ) -> Weight { - (36_855_000 as Weight) - // Standard Error: 17_000 - .saturating_add((3_047_000 as Weight).saturating_mul(r as Weight)) + (36_686_000 as Weight) + // Standard Error: 16_000 + .saturating_add((3_104_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64remu(r: u32, ) -> Weight { - (36_890_000 as Weight) + (36_447_000 as Weight) // Standard Error: 16_000 - .saturating_add((2_816_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_836_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64and(r: u32, ) -> Weight { - (36_749_000 as Weight) + (36_587_000 as Weight) // Standard Error: 16_000 - .saturating_add((2_475_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_481_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64or(r: u32, ) -> Weight { - (36_928_000 as Weight) + (36_889_000 as Weight) // Standard Error: 16_000 - .saturating_add((2_469_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_471_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64xor(r: u32, ) -> Weight { - (36_868_000 as Weight) + (36_628_000 as Weight) // Standard Error: 16_000 - .saturating_add((2_470_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_476_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shl(r: u32, ) -> Weight { - (36_919_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_470_000 as Weight).saturating_mul(r as Weight)) + (37_136_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_475_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shrs(r: u32, ) -> Weight { - (36_934_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_471_000 as Weight).saturating_mul(r as Weight)) + (32_543_000 as Weight) + // Standard Error: 25_000 + .saturating_add((2_751_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shru(r: u32, ) -> Weight { - (36_705_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_492_000 as Weight).saturating_mul(r as Weight)) + (36_378_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_499_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotl(r: u32, ) -> Weight { - (36_684_000 as Weight) + (36_563_000 as Weight) // Standard Error: 16_000 - .saturating_add((2_477_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_483_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotr(r: u32, ) -> Weight { - (36_844_000 as Weight) - // Standard Error: 17_000 + (36_625_000 as Weight) + // Standard Error: 16_000 .saturating_add((2_477_000 as Weight).saturating_mul(r as Weight)) } } @@ -1003,32 +1003,32 @@ impl WeightInfo for SubstrateWeight { impl WeightInfo for () { // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize() -> Weight { - (1_636_000 as Weight) + (1_601_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn on_initialize_per_trie_key(k: u32, ) -> Weight { - (7_840_000 as Weight) + (10_543_000 as Weight) // Standard Error: 0 - .saturating_add((752_000 as Weight).saturating_mul(k as Weight)) + .saturating_add((739_000 as Weight).saturating_mul(k as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) } // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize_per_queue_item(q: u32, ) -> Weight { - (31_915_000 as Weight) - // Standard Error: 1_000 - .saturating_add((98_000 as Weight).saturating_mul(q as Weight)) + (0 as Weight) + // Standard Error: 3_000 + .saturating_add((2_285_000 as Weight).saturating_mul(q as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Contracts PristineCode (r:1 w:0) // Storage: Contracts CodeStorage (r:0 w:1) fn reinstrument(c: u32, ) -> Weight { - (18_897_000 as Weight) - // Standard Error: 32_000 - .saturating_add((69_663_000 as Weight).saturating_mul(c as Weight)) + (16_846_000 as Weight) + // Standard Error: 33_000 + .saturating_add((71_629_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1037,9 +1037,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call_with_code_kb(c: u32, ) -> Weight { - (204_947_000 as Weight) - // Standard Error: 54_000 - .saturating_add((58_293_000 as Weight).saturating_mul(c as Weight)) + (160_645_000 as Weight) + // Standard Error: 51_000 + .saturating_add((60_029_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -1051,11 +1051,11 @@ impl WeightInfo for () { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn instantiate_with_code(c: u32, s: u32, ) -> Weight { - (211_187_000 as Weight) - // Standard Error: 114_000 - .saturating_add((156_529_000 as Weight).saturating_mul(c as Weight)) - // Standard Error: 7_000 - .saturating_add((1_830_000 as Weight).saturating_mul(s as Weight)) + (160_721_000 as Weight) + // Standard Error: 200_000 + .saturating_add((156_185_000 as Weight).saturating_mul(c as Weight)) + // Standard Error: 13_000 + .saturating_add((1_785_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } @@ -1066,9 +1066,9 @@ impl WeightInfo for () { // Storage: System Account (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn instantiate(s: u32, ) -> Weight { - (150_485_000 as Weight) + (145_929_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_769_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((1_743_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } @@ -1077,7 +1077,7 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call() -> Weight { - (117_274_000 as Weight) + (114_204_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -1085,9 +1085,9 @@ impl WeightInfo for () { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn upload_code(c: u32, ) -> Weight { - (51_126_000 as Weight) - // Standard Error: 49_000 - .saturating_add((72_622_000 as Weight).saturating_mul(c as Weight)) + (51_131_000 as Weight) + // Standard Error: 48_000 + .saturating_add((70_405_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -1095,7 +1095,7 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:0 w:1) // Storage: Contracts PristineCode (r:0 w:1) fn remove_code() -> Weight { - (24_221_000 as Weight) + (24_452_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -1104,9 +1104,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_caller(r: u32, ) -> Weight { - (219_790_000 as Weight) - // Standard Error: 126_000 - .saturating_add((56_383_000 as Weight).saturating_mul(r as Weight)) + (168_803_000 as Weight) + // Standard Error: 119_000 + .saturating_add((56_278_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1115,9 +1115,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_address(r: u32, ) -> Weight { - (218_377_000 as Weight) - // Standard Error: 117_000 - .saturating_add((57_243_000 as Weight).saturating_mul(r as Weight)) + (170_921_000 as Weight) + // Standard Error: 150_000 + .saturating_add((56_973_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1126,9 +1126,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas_left(r: u32, ) -> Weight { - (217_999_000 as Weight) - // Standard Error: 104_000 - .saturating_add((56_674_000 as Weight).saturating_mul(r as Weight)) + (168_953_000 as Weight) + // Standard Error: 116_000 + .saturating_add((56_032_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1137,9 +1137,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_balance(r: u32, ) -> Weight { - (226_932_000 as Weight) - // Standard Error: 155_000 - .saturating_add((147_401_000 as Weight).saturating_mul(r as Weight)) + (170_043_000 as Weight) + // Standard Error: 147_000 + .saturating_add((152_039_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1148,9 +1148,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_value_transferred(r: u32, ) -> Weight { - (233_107_000 as Weight) - // Standard Error: 110_000 - .saturating_add((55_334_000 as Weight).saturating_mul(r as Weight)) + (183_371_000 as Weight) + // Standard Error: 111_000 + .saturating_add((54_799_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1159,9 +1159,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_minimum_balance(r: u32, ) -> Weight { - (235_364_000 as Weight) - // Standard Error: 122_000 - .saturating_add((54_700_000 as Weight).saturating_mul(r as Weight)) + (181_993_000 as Weight) + // Standard Error: 127_000 + .saturating_add((54_617_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1170,9 +1170,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_block_number(r: u32, ) -> Weight { - (232_875_000 as Weight) - // Standard Error: 108_000 - .saturating_add((54_510_000 as Weight).saturating_mul(r as Weight)) + (179_543_000 as Weight) + // Standard Error: 96_000 + .saturating_add((54_526_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1181,9 +1181,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_now(r: u32, ) -> Weight { - (226_089_000 as Weight) - // Standard Error: 126_000 - .saturating_add((54_899_000 as Weight).saturating_mul(r as Weight)) + (174_365_000 as Weight) + // Standard Error: 117_000 + .saturating_add((54_433_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1193,9 +1193,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0) fn seal_weight_to_fee(r: u32, ) -> Weight { - (234_746_000 as Weight) - // Standard Error: 146_000 - .saturating_add((132_861_000 as Weight).saturating_mul(r as Weight)) + (186_003_000 as Weight) + // Standard Error: 187_000 + .saturating_add((133_644_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1204,9 +1204,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas(r: u32, ) -> Weight { - (96_247_000 as Weight) - // Standard Error: 70_000 - .saturating_add((27_918_000 as Weight).saturating_mul(r as Weight)) + (91_771_000 as Weight) + // Standard Error: 68_000 + .saturating_add((28_003_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1215,9 +1215,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input(r: u32, ) -> Weight { - (221_631_000 as Weight) - // Standard Error: 139_000 - .saturating_add((54_382_000 as Weight).saturating_mul(r as Weight)) + (170_110_000 as Weight) + // Standard Error: 104_000 + .saturating_add((53_937_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1226,9 +1226,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input_per_kb(n: u32, ) -> Weight { - (306_449_000 as Weight) - // Standard Error: 3_000 - .saturating_add((11_919_000 as Weight).saturating_mul(n as Weight)) + (251_576_000 as Weight) + // Standard Error: 9_000 + .saturating_add((10_613_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1237,9 +1237,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return(r: u32, ) -> Weight { - (222_176_000 as Weight) - // Standard Error: 72_000 - .saturating_add((3_223_000 as Weight).saturating_mul(r as Weight)) + (176_897_000 as Weight) + // Standard Error: 119_000 + .saturating_add((3_095_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1248,9 +1248,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return_per_kb(n: u32, ) -> Weight { - (211_079_000 as Weight) + (161_820_000 as Weight) // Standard Error: 0 - .saturating_add((237_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((184_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1261,9 +1261,9 @@ impl WeightInfo for () { // Storage: Contracts DeletionQueue (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_terminate(r: u32, ) -> Weight { - (213_994_000 as Weight) - // Standard Error: 104_000 - .saturating_add((64_453_000 as Weight).saturating_mul(r as Weight)) + (163_213_000 as Weight) + // Standard Error: 922_000 + .saturating_add((65_249_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((4 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1275,9 +1275,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) fn seal_random(r: u32, ) -> Weight { - (228_281_000 as Weight) - // Standard Error: 150_000 - .saturating_add((166_949_000 as Weight).saturating_mul(r as Weight)) + (178_636_000 as Weight) + // Standard Error: 189_000 + .saturating_add((166_008_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1286,9 +1286,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_deposit_event(r: u32, ) -> Weight { - (230_348_000 as Weight) - // Standard Error: 163_000 - .saturating_add((288_679_000 as Weight).saturating_mul(r as Weight)) + (187_377_000 as Weight) + // Standard Error: 186_000 + .saturating_add((289_005_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1298,11 +1298,11 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: System EventTopics (r:100 w:100) fn seal_deposit_event_per_topic_and_kb(t: u32, n: u32, ) -> Weight { - (601_613_000 as Weight) - // Standard Error: 1_566_000 - .saturating_add((279_038_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 308_000 - .saturating_add((84_818_000 as Weight).saturating_mul(n as Weight)) + (487_726_000 as Weight) + // Standard Error: 1_980_000 + .saturating_add((291_760_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 390_000 + .saturating_add((78_950_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(t as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1313,17 +1313,17 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_debug_message(r: u32, ) -> Weight { - (113_578_000 as Weight) - // Standard Error: 67_000 - .saturating_add((44_899_000 as Weight).saturating_mul(r as Weight)) + (105_118_000 as Weight) + // Standard Error: 80_000 + .saturating_add((45_277_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage(r: u32, ) -> Weight { - (59_019_000 as Weight) - // Standard Error: 995_000 - .saturating_add((414_759_000 as Weight).saturating_mul(r as Weight)) + (0 as Weight) + // Standard Error: 1_084_000 + .saturating_add((423_125_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1331,25 +1331,25 @@ impl WeightInfo for () { } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage_per_new_kb(n: u32, ) -> Weight { - (620_483_000 as Weight) - // Standard Error: 242_000 - .saturating_add((30_945_000 as Weight).saturating_mul(n as Weight)) + (565_293_000 as Weight) + // Standard Error: 257_000 + .saturating_add((26_134_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage_per_old_kb(n: u32, ) -> Weight { - (632_391_000 as Weight) - // Standard Error: 317_000 - .saturating_add((11_431_000 as Weight).saturating_mul(n as Weight)) + (582_851_000 as Weight) + // Standard Error: 306_000 + .saturating_add((11_991_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage(r: u32, ) -> Weight { - (96_628_000 as Weight) - // Standard Error: 878_000 - .saturating_add((387_212_000 as Weight).saturating_mul(r as Weight)) + (51_270_000 as Weight) + // Standard Error: 883_000 + .saturating_add((394_518_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -1357,51 +1357,51 @@ impl WeightInfo for () { } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage_per_kb(n: u32, ) -> Weight { - (625_960_000 as Weight) - // Standard Error: 270_000 - .saturating_add((11_170_000 as Weight).saturating_mul(n as Weight)) + (585_361_000 as Weight) + // Standard Error: 263_000 + .saturating_add((10_855_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage(r: u32, ) -> Weight { - (115_155_000 as Weight) - // Standard Error: 741_000 - .saturating_add((331_711_000 as Weight).saturating_mul(r as Weight)) + (60_404_000 as Weight) + // Standard Error: 667_000 + .saturating_add((335_130_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage_per_kb(n: u32, ) -> Weight { - (582_560_000 as Weight) - // Standard Error: 360_000 - .saturating_add((68_427_000 as Weight).saturating_mul(n as Weight)) + (539_500_000 as Weight) + // Standard Error: 378_000 + .saturating_add((62_855_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(104 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_contains_storage(r: u32, ) -> Weight { - (130_096_000 as Weight) - // Standard Error: 555_000 - .saturating_add((294_514_000 as Weight).saturating_mul(r as Weight)) + (58_301_000 as Weight) + // Standard Error: 701_000 + .saturating_add((301_511_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_contains_storage_per_kb(n: u32, ) -> Weight { - (528_701_000 as Weight) - // Standard Error: 246_000 - .saturating_add((10_375_000 as Weight).saturating_mul(n as Weight)) + (485_967_000 as Weight) + // Standard Error: 266_000 + .saturating_add((10_314_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(104 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage(r: u32, ) -> Weight { - (95_349_000 as Weight) - // Standard Error: 906_000 - .saturating_add((430_051_000 as Weight).saturating_mul(r as Weight)) + (42_688_000 as Weight) + // Standard Error: 889_000 + .saturating_add((436_932_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -1409,9 +1409,9 @@ impl WeightInfo for () { } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage_per_kb(n: u32, ) -> Weight { - (676_606_000 as Weight) - // Standard Error: 389_000 - .saturating_add((70_517_000 as Weight).saturating_mul(n as Weight)) + (638_201_000 as Weight) + // Standard Error: 373_000 + .saturating_add((64_277_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().writes(103 as Weight)) } @@ -1420,9 +1420,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_transfer(r: u32, ) -> Weight { - (131_194_000 as Weight) - // Standard Error: 1_256_000 - .saturating_add((1_772_590_000 as Weight).saturating_mul(r as Weight)) + (49_486_000 as Weight) + // Standard Error: 1_275_000 + .saturating_add((1_790_231_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) @@ -1433,9 +1433,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_call(r: u32, ) -> Weight { - (2_463_174_000 as Weight) - // Standard Error: 19_404_000 - .saturating_add((19_548_986_000 as Weight).saturating_mul(r as Weight)) + (2_498_893_000 as Weight) + // Standard Error: 20_838_000 + .saturating_add((14_474_373_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1446,13 +1446,13 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:2 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_call_per_transfer_input_output_kb(t: u32, i: u32, o: u32, ) -> Weight { - (21_356_548_000 as Weight) - // Standard Error: 31_719_000 - .saturating_add((1_874_230_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 11_000 - .saturating_add((23_243_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 12_000 - .saturating_add((34_825_000 as Weight).saturating_mul(o as Weight)) + (16_423_215_000 as Weight) + // Standard Error: 43_595_000 + .saturating_add((1_644_304_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 15_000 + .saturating_add((17_700_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 16_000 + .saturating_add((28_564_000 as Weight).saturating_mul(o as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().reads((101 as Weight).saturating_mul(t as Weight))) .saturating_add(RocksDbWeight::get().writes(101 as Weight)) @@ -1466,8 +1466,8 @@ impl WeightInfo for () { // Storage: Contracts OwnerInfoOf (r:100 w:100) fn seal_instantiate(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 49_981_000 - .saturating_add((28_988_348_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 52_924_000 + .saturating_add((24_062_215_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().reads((400 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -1480,13 +1480,13 @@ impl WeightInfo for () { // Storage: Contracts AccountCounter (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_instantiate_per_input_output_salt_kb(i: u32, o: u32, s: u32, ) -> Weight { - (24_726_887_000 as Weight) - // Standard Error: 32_000 - .saturating_add((23_702_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 32_000 - .saturating_add((35_841_000 as Weight).saturating_mul(o as Weight)) - // Standard Error: 32_000 - .saturating_add((161_159_000 as Weight).saturating_mul(s as Weight)) + (19_940_217_000 as Weight) + // Standard Error: 36_000 + .saturating_add((17_853_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 36_000 + .saturating_add((29_592_000 as Weight).saturating_mul(o as Weight)) + // Standard Error: 36_000 + .saturating_add((155_914_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(208 as Weight)) .saturating_add(RocksDbWeight::get().writes(206 as Weight)) } @@ -1495,9 +1495,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256(r: u32, ) -> Weight { - (221_804_000 as Weight) + (166_372_000 as Weight) // Standard Error: 150_000 - .saturating_add((84_131_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((85_445_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1506,9 +1506,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256_per_kb(n: u32, ) -> Weight { - (357_186_000 as Weight) - // Standard Error: 23_000 - .saturating_add((469_081_000 as Weight).saturating_mul(n as Weight)) + (323_005_000 as Weight) + // Standard Error: 28_000 + .saturating_add((464_801_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1517,9 +1517,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256(r: u32, ) -> Weight { - (220_729_000 as Weight) - // Standard Error: 166_000 - .saturating_add((101_538_000 as Weight).saturating_mul(r as Weight)) + (167_869_000 as Weight) + // Standard Error: 156_000 + .saturating_add((96_037_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1528,9 +1528,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256_per_kb(n: u32, ) -> Weight { - (272_756_000 as Weight) - // Standard Error: 18_000 - .saturating_add((311_130_000 as Weight).saturating_mul(n as Weight)) + (235_448_000 as Weight) + // Standard Error: 30_000 + .saturating_add((306_489_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1539,9 +1539,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256(r: u32, ) -> Weight { - (215_784_000 as Weight) - // Standard Error: 150_000 - .saturating_add((68_809_000 as Weight).saturating_mul(r as Weight)) + (166_113_000 as Weight) + // Standard Error: 128_000 + .saturating_add((68_810_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1550,9 +1550,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256_per_kb(n: u32, ) -> Weight { - (256_009_000 as Weight) - // Standard Error: 12_000 - .saturating_add((124_552_000 as Weight).saturating_mul(n as Weight)) + (276_885_000 as Weight) + // Standard Error: 16_000 + .saturating_add((120_098_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1561,9 +1561,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128(r: u32, ) -> Weight { - (216_413_000 as Weight) - // Standard Error: 134_000 - .saturating_add((68_281_000 as Weight).saturating_mul(r as Weight)) + (168_106_000 as Weight) + // Standard Error: 131_000 + .saturating_add((68_109_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1572,9 +1572,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128_per_kb(n: u32, ) -> Weight { - (254_477_000 as Weight) - // Standard Error: 13_000 - .saturating_add((124_483_000 as Weight).saturating_mul(n as Weight)) + (244_443_000 as Weight) + // Standard Error: 19_000 + .saturating_add((120_286_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1583,265 +1583,265 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_ecdsa_recover(r: u32, ) -> Weight { - (179_001_000 as Weight) - // Standard Error: 1_674_000 - .saturating_add((15_397_995_000 as Weight).saturating_mul(r as Weight)) + (207_765_000 as Weight) + // Standard Error: 1_529_000 + .saturating_add((15_403_795_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn instr_i64const(r: u32, ) -> Weight { - (46_905_000 as Weight) - // Standard Error: 12_000 - .saturating_add((794_000 as Weight).saturating_mul(r as Weight)) + (46_110_000 as Weight) + // Standard Error: 11_000 + .saturating_add((813_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64load(r: u32, ) -> Weight { - (53_636_000 as Weight) + (52_944_000 as Weight) // Standard Error: 12_000 - .saturating_add((2_476_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_501_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64store(r: u32, ) -> Weight { - (53_199_000 as Weight) + (52_968_000 as Weight) // Standard Error: 12_000 - .saturating_add((2_547_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_528_000 as Weight).saturating_mul(r as Weight)) } fn instr_select(r: u32, ) -> Weight { - (37_268_000 as Weight) + (36_871_000 as Weight) // Standard Error: 17_000 - .saturating_add((2_987_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_994_000 as Weight).saturating_mul(r as Weight)) } fn instr_if(r: u32, ) -> Weight { - (37_138_000 as Weight) + (36_834_000 as Weight) // Standard Error: 16_000 - .saturating_add((3_057_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((3_060_000 as Weight).saturating_mul(r as Weight)) } fn instr_br(r: u32, ) -> Weight { - (39_353_000 as Weight) - // Standard Error: 17_000 - .saturating_add((1_939_000 as Weight).saturating_mul(r as Weight)) + (39_250_000 as Weight) + // Standard Error: 16_000 + .saturating_add((1_933_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_if(r: u32, ) -> Weight { - (38_883_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_495_000 as Weight).saturating_mul(r as Weight)) + (38_302_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_496_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table(r: u32, ) -> Weight { - (45_030_000 as Weight) + (44_800_000 as Weight) // Standard Error: 21_000 - .saturating_add((2_398_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_407_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table_per_entry(e: u32, ) -> Weight { - (47_281_000 as Weight) + (46_996_000 as Weight) // Standard Error: 3_000 - .saturating_add((29_000 as Weight).saturating_mul(e as Weight)) + .saturating_add((27_000 as Weight).saturating_mul(e as Weight)) } fn instr_call(r: u32, ) -> Weight { - (49_074_000 as Weight) - // Standard Error: 20_000 - .saturating_add((19_991_000 as Weight).saturating_mul(r as Weight)) + (48_704_000 as Weight) + // Standard Error: 24_000 + .saturating_add((20_212_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect(r: u32, ) -> Weight { - (50_071_000 as Weight) - // Standard Error: 29_000 - .saturating_add((30_156_000 as Weight).saturating_mul(r as Weight)) + (52_546_000 as Weight) + // Standard Error: 32_000 + .saturating_add((29_995_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect_per_param(p: u32, ) -> Weight { - (84_902_000 as Weight) + (85_521_000 as Weight) // Standard Error: 5_000 - .saturating_add((1_124_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((1_117_000 as Weight).saturating_mul(p as Weight)) } fn instr_local_get(r: u32, ) -> Weight { - (39_054_000 as Weight) + (39_081_000 as Weight) // Standard Error: 14_000 - .saturating_add((1_352_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_338_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_set(r: u32, ) -> Weight { - (39_190_000 as Weight) + (39_014_000 as Weight) // Standard Error: 14_000 - .saturating_add((1_370_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_365_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_tee(r: u32, ) -> Weight { - (41_830_000 as Weight) - // Standard Error: 13_000 - .saturating_add((1_878_000 as Weight).saturating_mul(r as Weight)) + (41_269_000 as Weight) + // Standard Error: 12_000 + .saturating_add((1_879_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_get(r: u32, ) -> Weight { - (40_764_000 as Weight) - // Standard Error: 13_000 - .saturating_add((1_931_000 as Weight).saturating_mul(r as Weight)) + (40_341_000 as Weight) + // Standard Error: 12_000 + .saturating_add((1_944_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_set(r: u32, ) -> Weight { - (46_309_000 as Weight) + (45_833_000 as Weight) // Standard Error: 12_000 - .saturating_add((1_745_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_757_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_current(r: u32, ) -> Weight { - (47_071_000 as Weight) + (46_780_000 as Weight) // Standard Error: 12_000 - .saturating_add((797_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((806_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_grow(r: u32, ) -> Weight { - (49_773_000 as Weight) - // Standard Error: 1_442_000 - .saturating_add((227_666_000 as Weight).saturating_mul(r as Weight)) + (49_585_000 as Weight) + // Standard Error: 1_723_000 + .saturating_add((166_106_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64clz(r: u32, ) -> Weight { - (43_879_000 as Weight) - // Standard Error: 12_000 - .saturating_add((1_486_000 as Weight).saturating_mul(r as Weight)) + (43_423_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_494_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ctz(r: u32, ) -> Weight { - (43_883_000 as Weight) - // Standard Error: 12_000 - .saturating_add((1_484_000 as Weight).saturating_mul(r as Weight)) + (43_237_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_499_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64popcnt(r: u32, ) -> Weight { - (43_415_000 as Weight) + (43_308_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_495_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_505_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eqz(r: u32, ) -> Weight { - (43_567_000 as Weight) + (43_440_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_493_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_503_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendsi32(r: u32, ) -> Weight { - (41_332_000 as Weight) - // Standard Error: 12_000 - .saturating_add((1_912_000 as Weight).saturating_mul(r as Weight)) + (40_782_000 as Weight) + // Standard Error: 13_000 + .saturating_add((1_948_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendui32(r: u32, ) -> Weight { - (41_331_000 as Weight) + (41_210_000 as Weight) // Standard Error: 12_000 - .saturating_add((1_911_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_925_000 as Weight).saturating_mul(r as Weight)) } fn instr_i32wrapi64(r: u32, ) -> Weight { - (43_704_000 as Weight) + (43_108_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_487_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_506_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eq(r: u32, ) -> Weight { - (37_103_000 as Weight) + (36_501_000 as Weight) // Standard Error: 16_000 - .saturating_add((2_467_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_490_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ne(r: u32, ) -> Weight { - (36_680_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_487_000 as Weight).saturating_mul(r as Weight)) + (36_289_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_494_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64lts(r: u32, ) -> Weight { - (36_659_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_494_000 as Weight).saturating_mul(r as Weight)) + (36_414_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_492_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ltu(r: u32, ) -> Weight { - (36_491_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_495_000 as Weight).saturating_mul(r as Weight)) + (36_205_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_498_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gts(r: u32, ) -> Weight { - (36_440_000 as Weight) + (36_648_000 as Weight) // Standard Error: 16_000 - .saturating_add((2_499_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_473_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gtu(r: u32, ) -> Weight { - (36_477_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_500_000 as Weight).saturating_mul(r as Weight)) + (36_530_000 as Weight) + // Standard Error: 18_000 + .saturating_add((2_488_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64les(r: u32, ) -> Weight { - (36_561_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_498_000 as Weight).saturating_mul(r as Weight)) + (36_622_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_483_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64leu(r: u32, ) -> Weight { - (36_418_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_501_000 as Weight).saturating_mul(r as Weight)) + (36_465_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_490_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ges(r: u32, ) -> Weight { - (36_835_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_484_000 as Weight).saturating_mul(r as Weight)) + (36_291_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_494_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64geu(r: u32, ) -> Weight { - (36_873_000 as Weight) + (36_454_000 as Weight) // Standard Error: 16_000 - .saturating_add((2_469_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_483_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64add(r: u32, ) -> Weight { - (37_013_000 as Weight) + (36_801_000 as Weight) // Standard Error: 16_000 - .saturating_add((2_466_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_468_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64sub(r: u32, ) -> Weight { - (36_885_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_469_000 as Weight).saturating_mul(r as Weight)) + (36_670_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_483_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64mul(r: u32, ) -> Weight { - (36_696_000 as Weight) + (36_388_000 as Weight) // Standard Error: 17_000 - .saturating_add((2_487_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_494_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divs(r: u32, ) -> Weight { - (36_924_000 as Weight) + (36_952_000 as Weight) // Standard Error: 16_000 - .saturating_add((3_118_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((3_113_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divu(r: u32, ) -> Weight { - (36_819_000 as Weight) + (36_634_000 as Weight) // Standard Error: 16_000 - .saturating_add((2_784_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_789_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rems(r: u32, ) -> Weight { - (36_855_000 as Weight) - // Standard Error: 17_000 - .saturating_add((3_047_000 as Weight).saturating_mul(r as Weight)) + (36_686_000 as Weight) + // Standard Error: 16_000 + .saturating_add((3_104_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64remu(r: u32, ) -> Weight { - (36_890_000 as Weight) + (36_447_000 as Weight) // Standard Error: 16_000 - .saturating_add((2_816_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_836_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64and(r: u32, ) -> Weight { - (36_749_000 as Weight) + (36_587_000 as Weight) // Standard Error: 16_000 - .saturating_add((2_475_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_481_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64or(r: u32, ) -> Weight { - (36_928_000 as Weight) + (36_889_000 as Weight) // Standard Error: 16_000 - .saturating_add((2_469_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_471_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64xor(r: u32, ) -> Weight { - (36_868_000 as Weight) + (36_628_000 as Weight) // Standard Error: 16_000 - .saturating_add((2_470_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_476_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shl(r: u32, ) -> Weight { - (36_919_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_470_000 as Weight).saturating_mul(r as Weight)) + (37_136_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_475_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shrs(r: u32, ) -> Weight { - (36_934_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_471_000 as Weight).saturating_mul(r as Weight)) + (32_543_000 as Weight) + // Standard Error: 25_000 + .saturating_add((2_751_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shru(r: u32, ) -> Weight { - (36_705_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_492_000 as Weight).saturating_mul(r as Weight)) + (36_378_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_499_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotl(r: u32, ) -> Weight { - (36_684_000 as Weight) + (36_563_000 as Weight) // Standard Error: 16_000 - .saturating_add((2_477_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_483_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotr(r: u32, ) -> Weight { - (36_844_000 as Weight) - // Standard Error: 17_000 + (36_625_000 as Weight) + // Standard Error: 16_000 .saturating_add((2_477_000 as Weight).saturating_mul(r as Weight)) } } From fa80c9e4838f93d7376de6cb3e90835e43f198bb Mon Sep 17 00:00:00 2001 From: driemworks Date: Fri, 28 Jan 2022 18:20:14 -0500 Subject: [PATCH 435/695] update runtime storage, update rpc params, update docs --- Cargo.lock | 1 - .../pallets/iris-assets/src/lib.rs | 138 +++------ .../pallets/iris-assets/src/tests.rs | 14 - .../pallets/iris-session/Cargo.toml | 2 - .../iris-session/rpc/runtime-api/src/lib.rs | 2 - .../pallets/iris-session/rpc/src/lib.rs | 6 +- .../pallets/iris-session/src/lib.rs | 288 +++++++++--------- bin/node-template/runtime/src/lib.rs | 4 +- 8 files changed, 197 insertions(+), 258 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index db114c68e76d..fbc8eee53a93 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5904,7 +5904,6 @@ dependencies = [ "frame-support", "frame-system", "log 0.4.14", - "pallet-assets", "pallet-iris-assets", "pallet-session", "parity-scale-codec", diff --git a/bin/node-template/pallets/iris-assets/src/lib.rs b/bin/node-template/pallets/iris-assets/src/lib.rs index 5d0304bea8a7..4567f90b166e 100644 --- a/bin/node-template/pallets/iris-assets/src/lib.rs +++ b/bin/node-template/pallets/iris-assets/src/lib.rs @@ -4,7 +4,6 @@ //! //! //! ## Overview -//! Disclaimer: This pallet is in the tadpole state //! //! ### Goals //! The Iris module provides functionality for creation and management of storage assets and access management @@ -13,13 +12,8 @@ //! //! #### Permissionless functions //! * create_storage_asset -//! * request_data //! //! #### Permissioned Functions -//! * submit_ipfs_add_results -//! * submit_ipfs_identity -//! * submit_rpc_ready -//! * destroy_ticket //! * mint_tickets //! @@ -64,20 +58,12 @@ use sp_std::{ pub enum DataCommand { /// (ipfs_address, cid, requesting node address, filename, asset id, balance) AddBytes(OpaqueMultiaddr, Vec, LookupSource, Vec, AssetId, Balance), - /// (owner, assetid, recipient) - CatBytes(AccountId, AssetId, AccountId), + /// (requestor, owner, assetid) + CatBytes(AccountId, AccountId, AssetId), /// (node, assetid, CID) PinCID(AccountId, AssetId, Vec), } -#[derive(Encode, Decode, RuntimeDebug, Clone, Default, Eq, PartialEq, TypeInfo)] -pub struct StoragePool { - max_redundancy: u32, - candidate_storage_providers: Vec, - current_session_storage_providers: Vec, - owner: AccountId, -} - pub use pallet::*; #[cfg(test)] @@ -118,18 +104,6 @@ pub mod pallet { #[pallet::generate_store(pub(super) trait Store)] pub struct Pallet(_); - /// map the ipfs public key to a list of multiaddresses - /// this could be moved to the session pallet - #[pallet::storage] - #[pallet::getter(fn bootstrap_nodes)] - pub(super) type BootstrapNodes = StorageMap< - _, - Blake2_128Concat, - Vec, - Vec, - ValueQuery, - >; - /// A queue of data to publish or obtain on IPFS. #[pallet::storage] #[pallet::getter(fn data_queue)] @@ -144,9 +118,9 @@ pub mod pallet { ValueQuery >; - /// not readlly sure if this will stay forever, - /// using this for now until I come up with an actual solution for - /// moving candidate storage providers map to the active storage providers map + /// A collection of asset ids + /// TODO: currently allows customized asset ids but in the future + /// we can use this to dynamically generate unique asset ids for content #[pallet::storage] #[pallet::getter(fn asset_ids)] pub(super) type AssetIds = StorageValue< @@ -170,17 +144,7 @@ pub mod pallet { ValueQuery, >; - // /// maps an asset id to a CID - // #[pallet::storage] - // #[pallet::getter(fn asset_class_config)] - // pub(super) type AssetClassConfig = StorageMap< - // _, - // Blake2_128Concat, - // T::AssetId, - // Vec, - // >; - - /// Store the map associated a node with the assets to which they have access + /// Store the map associating a node with the assets to which they have access /// /// asset_owner_accountid -> CID -> asset_class_owner_accountid #[pallet::storage] @@ -190,7 +154,7 @@ pub mod pallet { Blake2_128Concat, T::AccountId, Blake2_128Concat, - Vec, + T::AssetId, T::AccountId, ValueQuery, >; @@ -285,32 +249,52 @@ pub mod pallet { Ok(()) } - /// Queue a request to retrieve data behind some owned CID from the IPFS network + /// Only callable by the owner of the asset class + /// mint a static number of assets (tickets) for some asset class /// - /// * owner: The owner node - /// * cid: the cid to which you are requesting access + /// * origin: should be the owner of the asset class + /// * beneficiary: the address to which the newly minted assets are assigned + /// * cid: a cid owned by the origin, for which an asset class exists + /// * amount: the number of tickets to mint /// - #[pallet::weight(0)] - pub fn request_data( + #[pallet::weight(0)] + pub fn mint_tickets( origin: OriginFor, - owner: ::Source, + beneficiary: ::Source, asset_id: T::AssetId, + #[pallet::compact] amount: T::Balance, ) -> DispatchResult { let who = ensure_signed(origin)?; - let owner_account = T::Lookup::lookup(owner)?; + ensure!(AssetClassOwnership::::contains_key(who.clone(), asset_id.clone()), Error::::NoSuchOwnedContent); + + let new_origin = system::RawOrigin::Signed(who.clone()).into(); + let beneficiary_accountid = T::Lookup::lookup(beneficiary.clone())?; + // let asset_id = AssetClassOwnership::::get(who.clone(), cid.clone(),); + >::mint(new_origin, asset_id.clone(), beneficiary.clone(), amount) + .map_err(|_| Error::::CantMintAssets)?; + >::insert(beneficiary_accountid.clone(), asset_id.clone(), who.clone()); + + Self::deposit_event(Event::AssetCreated(asset_id.clone())); + Ok(()) + } + + #[pallet::weight(0)] + pub fn request_bytes( + origin: OriginFor, + owner: ::Source, + asset_id: T::AssetId, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + let owner_account = T::Lookup::lookup(owner)?; >::mutate( |queue| queue.push(DataCommand::CatBytes( + who.clone(), owner_account.clone(), asset_id.clone(), - who.clone(), - ) - )); - - Self::deposit_event(Event::QueuedDataToCat(who.clone())); - - Ok(()) - } + ))); + Ok(()) + } /// should only be called by offchain workers... how to ensure this? /// submits IPFS results on chain and creates new ticket config in runtime storage @@ -328,10 +312,6 @@ pub mod pallet { id: T::AssetId, balance: T::Balance, ) -> DispatchResult { - // DANGER: This can currently be called by anyone, not just an OCW. - // if we send an unsigned transaction then we can ensure there is no origin - // however, the call to create the asset requires an origin, which is a little problematic - // ensure_none(origin)?; let who = ensure_signed(origin)?; let new_origin = system::RawOrigin::Signed(who).into(); @@ -347,37 +327,11 @@ pub mod pallet { Ok(()) } - /// Only callable by the owner of the asset class - /// mint a static number of assets (tickets) for some asset class - /// - /// * origin: should be the owner of the asset class - /// * beneficiary: the address to which the newly minted assets are assigned - /// * cid: a cid owned by the origin, for which an asset class exists - /// * amount: the number of tickets to mint + /// Add a request to pin a cid to the DataQueue for your embedded IPFS node + /// + /// * asset_owner: The owner of the asset class + /// * asset_id: The asset id of some asset class /// - #[pallet::weight(0)] - pub fn mint_tickets( - origin: OriginFor, - beneficiary: ::Source, - asset_id: T::AssetId, - #[pallet::compact] amount: T::Balance, - ) -> DispatchResult { - let who = ensure_signed(origin)?; - let new_origin = system::RawOrigin::Signed(who.clone()).into(); - let beneficiary_accountid = T::Lookup::lookup(beneficiary.clone())?; - - ensure!(AssetClassOwnership::::contains_key(who.clone(), asset_id.clone()), Error::::NoSuchOwnedContent); - - // let asset_id = AssetClassOwnership::::get(who.clone(), cid.clone(),); - >::mint(new_origin, asset_id.clone(), beneficiary.clone(), amount) - .map_err(|_| Error::::CantMintAssets)?; - let cid = >::get(who.clone(), asset_id.clone()); - >::insert(beneficiary_accountid.clone(), cid.clone(), who.clone()); - - Self::deposit_event(Event::AssetCreated(asset_id.clone())); - Ok(()) - } - #[pallet::weight(0)] pub fn insert_pin_request( origin: OriginFor, diff --git a/bin/node-template/pallets/iris-assets/src/tests.rs b/bin/node-template/pallets/iris-assets/src/tests.rs index ff51417b590d..4ddbe012b0b3 100644 --- a/bin/node-template/pallets/iris-assets/src/tests.rs +++ b/bin/node-template/pallets/iris-assets/src/tests.rs @@ -3,20 +3,6 @@ use frame_support::{assert_noop, assert_ok}; use mock::*; use sp_core::Pair; -// fn new_block() -> u64 { -// let number = frame_system::Pallet::::block_number() + 1; -// let hash = H256::repeat_byte(number as u8); -// LEAF_DATA.with(|r| r.borrow_mut().a = number); - -// frame_system::Pallet::::initialize( -// &number, -// &hash, -// &Default::default(), -// frame_system::InitKind::Full, -// ); -// Iris::on_initialize(number) -// } - #[test] fn iris_initial_state() { new_test_ext().execute_with(|| { diff --git a/bin/node-template/pallets/iris-session/Cargo.toml b/bin/node-template/pallets/iris-session/Cargo.toml index fecd303c64a6..27305506c269 100644 --- a/bin/node-template/pallets/iris-session/Cargo.toml +++ b/bin/node-template/pallets/iris-session/Cargo.toml @@ -32,7 +32,6 @@ frame-benchmarking = { default-features = false, version = "4.0.0-dev", path = " log = { version = "0.4.14", default-features = false } # pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../../../../frame/balances" } -pallet-assets = { version = "4.0.0-dev", default-features = false, path = "../../../../frame/assets" } pallet-session = { version = "4.0.0-dev", default-features = false, features = ["historical"], path = "../../../../frame/session" } pallet-iris-assets = { version = "1.0.0", default-features = false, path = "../iris-assets" } @@ -51,7 +50,6 @@ std = [ 'sp-staking/std', 'log/std', 'pallet-session/std', - 'pallet-assets/std', 'pallet-iris-assets/std', ] diff --git a/bin/node-template/pallets/iris-session/rpc/runtime-api/src/lib.rs b/bin/node-template/pallets/iris-session/rpc/runtime-api/src/lib.rs index 89e7627dde56..33f0dc29eff1 100644 --- a/bin/node-template/pallets/iris-session/rpc/runtime-api/src/lib.rs +++ b/bin/node-template/pallets/iris-session/rpc/runtime-api/src/lib.rs @@ -10,8 +10,6 @@ sp_api::decl_runtime_apis! { pub trait IrisApi { fn retrieve_bytes( - public_key: Bytes, - signature: Bytes, message: Bytes, ) -> Bytes; } diff --git a/bin/node-template/pallets/iris-session/rpc/src/lib.rs b/bin/node-template/pallets/iris-session/rpc/src/lib.rs index 481de02d9fcd..a6c4a30c2c65 100644 --- a/bin/node-template/pallets/iris-session/rpc/src/lib.rs +++ b/bin/node-template/pallets/iris-session/rpc/src/lib.rs @@ -16,8 +16,6 @@ pub trait IrisApi { #[rpc(name = "iris_retrieveBytes")] fn retrieve_bytes( &self, - public_key: Bytes, - signature: Bytes, message: Bytes, at: Option, ) -> Result; @@ -61,8 +59,6 @@ where { fn retrieve_bytes( &self, - public_key: Bytes, - signature: Bytes, message: Bytes, at: Option<::Hash>, ) -> Result { @@ -70,7 +66,7 @@ where let at = BlockId::hash(at.unwrap_or_else(|| self.client.info().best_hash )); - let runtime_api_result = api.retrieve_bytes(&at, public_key, signature, message); + let runtime_api_result = api.retrieve_bytes(&at, message); runtime_api_result.map_err(|e| RpcError{ code: ErrorCode::ServerError(Error::DecodeError.into()), message: "unable to query runtime api".into(), diff --git a/bin/node-template/pallets/iris-session/src/lib.rs b/bin/node-template/pallets/iris-session/src/lib.rs index 537b0411155c..f4f188fae0aa 100644 --- a/bin/node-template/pallets/iris-session/src/lib.rs +++ b/bin/node-template/pallets/iris-session/src/lib.rs @@ -235,23 +235,21 @@ pub mod pallet { #[pallet::hooks] impl Hooks> for Pallet { fn offchain_worker(block_number: T::BlockNumber) { - if sp_io::offchain::is_validator() { - // every 5 blocks - if block_number % 5u32.into() == 0u32.into() { - if let Err(e) = Self::connection_housekeeping() { - log::error!("IPFS: Encountered an error while processing data requests: {:?}", e); - } - } - // handle data requests each block - if let Err(e) = Self::handle_data_requests() { + // every 5 blocks + if block_number % 5u32.into() == 0u32.into() { + if let Err(e) = Self::connection_housekeeping() { log::error!("IPFS: Encountered an error while processing data requests: {:?}", e); } + } + // handle data requests each block + if let Err(e) = Self::handle_data_requests() { + log::error!("IPFS: Encountered an error while processing data requests: {:?}", e); + } - // every 5 blocks - if block_number % 5u32.into() == 0u32.into() { - if let Err(e) = Self::print_metadata() { - log::error!("IPFS: Encountered an error while obtaining metadata: {:?}", e); - } + // every 5 blocks + if block_number % 5u32.into() == 0u32.into() { + if let Err(e) = Self::print_metadata() { + log::error!("IPFS: Encountered an error while obtaining metadata: {:?}", e); } } } @@ -333,7 +331,7 @@ pub mod pallet { } #[pallet::weight(0)] - pub fn request_join_storage_pool( + pub fn request_store_content( origin: OriginFor, pool_owner: ::Source, pool_id: T::AssetId, @@ -535,24 +533,21 @@ impl Pallet { } } - /// implementation for RPC runtime aPI to retrieve bytes from the node's local storage + /// implementation for RPC runtime API to retrieve bytes from the node's local storage /// /// * public_key: The account's public key as bytes /// * signature: The signer's signature as bytes /// * message: The signed message as bytes /// pub fn retrieve_bytes( - _public_key: Bytes, - _signature: Bytes, message: Bytes, ) -> Bytes { - // TODO: Verify signature, update offchain storage keys... let message_vec: Vec = message.to_vec(); - if let Some(data) = sp_io::offchain::local_storage_get(StorageKind::PERSISTENT, &message_vec) { - Bytes(data.clone()) - } else { - Bytes(Vec::new()) - } + if let Some(data) = sp_io::offchain::local_storage_get(StorageKind::PERSISTENT, &message_vec) { + Bytes(data.clone()) + } else { + Bytes(Vec::new()) + } } /// send a request to the local IPFS node; can only be called be an off-chain worker @@ -638,125 +633,138 @@ impl Pallet { } /// process any requests in the DataQueue + /// TODO: This needs some *major* refactoring fn handle_data_requests() -> Result<(), Error> { - let data_queue = >::data_queue(); - let len = data_queue.len(); - if len != 0 { - log::info!("IPFS: {} entr{} in the data queue", len, if len == 1 { "y" } else { "ies" }); - } - // TODO: Needs refactoring - let deadline = Some(timestamp().add(Duration::from_millis(5_000))); - for cmd in data_queue.into_iter() { - match cmd { - DataCommand::AddBytes(addr, cid, admin, _name, id, balance) => { - Self::ipfs_request(IpfsRequest::Connect(addr.clone()), deadline)?; - log::info!( - "IPFS: connected to {}", - str::from_utf8(&addr.0).expect("our own calls can be trusted to be UTF-8; qed") - ); - match Self::ipfs_request(IpfsRequest::CatBytes(cid.clone()), deadline) { - Ok(IpfsResponse::CatBytes(data)) => { - log::info!("IPFS: fetched data"); - Self::ipfs_request(IpfsRequest::Disconnect(addr.clone()), deadline)?; - log::info!( - "IPFS: disconnected from {}", - str::from_utf8(&addr.0).expect("our own calls can be trusted to be UTF-8; qed") - ); - match Self::ipfs_request(IpfsRequest::AddBytes(data.clone()), deadline) { - Ok(IpfsResponse::AddBytes(new_cid)) => { - log::info!( - "IPFS: added data with Cid {}", - str::from_utf8(&new_cid).expect("our own IPFS node can be trusted here; qed") - ); - let signer = Signer::::all_accounts(); - if !signer.can_sign() { - log::error!( - "No local accounts available. Consider adding one via `author_insertKey` RPC.", - ); - } - let results = signer.send_signed_transaction(|_account| { - Call::submit_ipfs_add_results{ - admin: admin.clone(), - cid: new_cid.clone(), - id: id.clone(), - balance: balance.clone(), - } - }); - - for (_, res) in &results { - match res { - Ok(()) => log::info!("Submitted ipfs results"), - Err(e) => log::error!("Failed to submit transaction: {:?}", e), - } - } - }, - Ok(_) => unreachable!("only AddBytes can be a response for that request type."), - Err(e) => log::error!("IPFS: add error: {:?}", e), - } - }, - Ok(_) => unreachable!("only CatBytes can be a response for that request type."), - Err(e) => log::error!("IPFS: cat error: {:?}", e), - } - }, - DataCommand::CatBytes(owner, asset_id, recipient) => { - // TODO: Could potentially remove the owner here by restructuring runtime storage -> would need unique asset ids - if let cid = >::asset_class_ownership( - owner.clone(), asset_id.clone() - ) { - let balance = >::balance(asset_id.clone(), recipient.clone()); - let balance_primitive = TryInto::::try_into(balance).ok(); - - ensure!(balance_primitive != Some(0), Error::::InsufficientBalance); + if sp_io::offchain::is_validator() { + let data_queue = >::data_queue(); + let len = data_queue.len(); + if len != 0 { + log::info!("IPFS: {} entr{} in the data queue", len, if len == 1 { "y" } else { "ies" }); + } + // TODO: Needs refactoring + let deadline = Some(timestamp().add(Duration::from_millis(5_000))); + for cmd in data_queue.into_iter() { + match cmd { + DataCommand::AddBytes(addr, cid, admin, _name, id, balance) => { + Self::ipfs_request(IpfsRequest::Connect(addr.clone()), deadline)?; + log::info!( + "IPFS: connected to {}", + str::from_utf8(&addr.0).expect("our own calls can be trusted to be UTF-8; qed") + ); match Self::ipfs_request(IpfsRequest::CatBytes(cid.clone()), deadline) { Ok(IpfsResponse::CatBytes(data)) => { - log::info!("IPFS: Fetched data from IPFS."); - // add to offchain index - sp_io::offchain::local_storage_set( - StorageKind::PERSISTENT, - &cid, - &data, + log::info!("IPFS: fetched data"); + Self::ipfs_request(IpfsRequest::Disconnect(addr.clone()), deadline)?; + log::info!( + "IPFS: disconnected from {}", + str::from_utf8(&addr.0).expect("our own calls can be trusted to be UTF-8; qed") ); - let signer = Signer::::all_accounts(); - if !signer.can_sign() { - log::error!( - "No local accounts available. Consider adding one via `author_insertKey` RPC.", - ); - } - let results = signer.send_signed_transaction(|_account| { - Call::submit_rpc_ready { - beneficiary: recipient.clone(), - } - }); - - for (_, res) in &results { - match res { - Ok(()) => log::info!("Submitted ipfs results"), - Err(e) => log::error!("Failed to submit transaction: {:?}", e), - } + match Self::ipfs_request(IpfsRequest::AddBytes(data.clone()), deadline) { + Ok(IpfsResponse::AddBytes(new_cid)) => { + log::info!( + "IPFS: added data with Cid {}", + str::from_utf8(&new_cid).expect("our own IPFS node can be trusted here; qed") + ); + let signer = Signer::::all_accounts(); + if !signer.can_sign() { + log::error!( + "No local accounts available. Consider adding one via `author_insertKey` RPC.", + ); + } + let results = signer.send_signed_transaction(|_account| { + Call::submit_ipfs_add_results{ + admin: admin.clone(), + cid: new_cid.clone(), + id: id.clone(), + balance: balance.clone(), + } + }); + + for (_, res) in &results { + match res { + Ok(()) => log::info!("Submitted ipfs results"), + Err(e) => log::error!("Failed to submit transaction: {:?}", e), + } + } + }, + Ok(_) => unreachable!("only AddBytes can be a response for that request type."), + Err(e) => log::error!("IPFS: add error: {:?}", e), } }, Ok(_) => unreachable!("only CatBytes can be a response for that request type."), Err(e) => log::error!("IPFS: cat error: {:?}", e), } - } else { - log::error!("the provided owner/cid does not map to a valid asset id: {:?}, {:?}", owner, asset_id) - } - }, - DataCommand::PinCID(acct, asset_id, cid) => { - let (public_key, addrs) = - if let IpfsResponse::Identity(public_key, addrs) = - Self::ipfs_request(IpfsRequest::Identity, deadline)? { - (public_key, addrs) - } else { - unreachable!("only `Identity` is a valid response type."); - }; - let expected_pub_key = >::get(acct); - // todo: create new error enum if this is the route i choose - ensure!(public_key == expected_pub_key, Error::::BadOrigin); - match Self::ipfs_request(IpfsRequest::InsertPin(cid.clone(), false), deadline) { - Ok(IpfsResponse::Success) => { - log::info!("IPFS: Pinned CID {:?}", cid.clone()); - let signer = Signer::::all_accounts(); + }, + DataCommand::CatBytes(requestor, owner, asset_id) => { + let (public_key, addrs) = + if let IpfsResponse::Identity(public_key, addrs) = + Self::ipfs_request(IpfsRequest::Identity, deadline)? { + (public_key, addrs) + } else { + unreachable!("only `Identity` is a valid response type."); + }; + let expected_pub_key = >::get(requestor.clone()); + // todo: create new error enum if this is the route i choose + ensure!(public_key == expected_pub_key, Error::::BadOrigin); + + if let cid = >::asset_class_ownership( + owner.clone(), asset_id.clone() + ) { + ensure!( + owner.clone() == >::asset_access(requestor.clone(), asset_id.clone()), + Error::::InsufficientBalance + ); + match Self::ipfs_request(IpfsRequest::CatBytes(cid.clone()), deadline) { + Ok(IpfsResponse::CatBytes(data)) => { + log::info!("IPFS: Fetched data from IPFS."); + // add to offchain index + sp_io::offchain::local_storage_set( + StorageKind::PERSISTENT, + &cid, + &data, + ); + + let signer = Signer::::all_accounts(); + if !signer.can_sign() { + log::error!( + "No local accounts available. Consider adding one via `author_insertKey` RPC.", + ); + } + let results = signer.send_signed_transaction(|_account| { + Call::submit_rpc_ready { + beneficiary: requestor.clone(), + } + }); + + for (_, res) in &results { + match res { + Ok(()) => log::info!("Submitted ipfs results"), + Err(e) => log::error!("Failed to submit transaction: {:?}", e), + } + } + }, + Ok(_) => unreachable!("only CatBytes can be a response for that request type."), + Err(e) => log::error!("IPFS: cat error: {:?}", e), + } + } else { + log::error!("the provided owner/cid does not map to a valid asset id: {:?}, {:?}", owner, asset_id) + } + }, + DataCommand::PinCID(acct, asset_id, cid) => { + let (public_key, addrs) = + if let IpfsResponse::Identity(public_key, addrs) = + Self::ipfs_request(IpfsRequest::Identity, deadline)? { + (public_key, addrs) + } else { + unreachable!("only `Identity` is a valid response type."); + }; + let expected_pub_key = >::get(acct); + // todo: create new error enum if this is the route i choose + ensure!(public_key == expected_pub_key, Error::::BadOrigin); + match Self::ipfs_request(IpfsRequest::InsertPin(cid.clone(), false), deadline) { + Ok(IpfsResponse::Success) => { + log::info!("IPFS: Pinned CID {:?}", cid.clone()); + let signer = Signer::::all_accounts(); if !signer.can_sign() { log::error!( "No local accounts available. Consider adding one via `author_insertKey` RPC.", @@ -774,13 +782,14 @@ impl Pallet { Err(e) => log::error!("Failed to submit transaction: {:?}", e), } } - }, - Ok(_) => unreachable!("only Success can be a response for that request type"), - Err(e) => log::error!("IPFS: insert pin error: {:?}", e), + }, + Ok(_) => unreachable!("only Success can be a response for that request type"), + Err(e) => log::error!("IPFS: insert pin error: {:?}", e), + } } } - } - } + } + } Ok(()) } @@ -814,6 +823,7 @@ impl pallet_session::SessionManager for Pallet { // Remove any offline validators. This will only work when the runtime // also has the im-online pallet. Self::remove_offline_validators(); + // TODO: Clear active storage providers here Self::select_candidate_storage_providers(); log::debug!(target: LOG_TARGET, "New session called; updated validator set provided."); Some(Self::validators()) diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index ceb30e68ee4e..659c2ea37ca9 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -599,11 +599,9 @@ impl_runtime_apis! { */ impl pallet_iris_rpc_runtime_api::IrisApi for Runtime { fn retrieve_bytes( - public_key: Bytes, - signature: Bytes, message: Bytes ) -> Bytes { - IrisSession::retrieve_bytes(public_key, signature, message) + IrisSession::retrieve_bytes(message) } } From 59857f1fabbc93169206e4013e985adbc00ba25c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Mon, 31 Jan 2022 11:05:30 +0100 Subject: [PATCH 436/695] Bump `wasm-instrument` 0.1.0 -> 0.1.1 (#10749) * Bump wasm-instrument 0.1.0 -> 0.1.1 * Fix benchmark --- Cargo.lock | 4 ++-- frame/contracts/src/benchmarking/mod.rs | 2 +- frame/contracts/src/tests.rs | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b57f06c50ed2..c2f24bd839ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11444,9 +11444,9 @@ dependencies = [ [[package]] name = "wasm-instrument" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e67369bb53d409b67e57ef31797b1b2d628955fc82f86f2ea78bb403acc7c73" +checksum = "962e5b0401bbb6c887f54e69b8c496ea36f704df65db73e81fd5ff8dc3e63a9f" dependencies = [ "parity-wasm 0.42.2", ] diff --git a/frame/contracts/src/benchmarking/mod.rs b/frame/contracts/src/benchmarking/mod.rs index 3537af3d0cf7..83be846465e4 100644 --- a/frame/contracts/src/benchmarking/mod.rs +++ b/frame/contracts/src/benchmarking/mod.rs @@ -270,7 +270,7 @@ benchmarks! { // We cannot let `c` grow to the maximum code size because the code is not allowed // to be larger than the maximum size **after instrumentation**. instantiate_with_code { - let c in 0 .. Perbill::from_percent(50).mul_ceil(T::Schedule::get().limits.code_len / 1024); + let c in 0 .. Perbill::from_percent(49).mul_ceil(T::Schedule::get().limits.code_len) / 1024; let s in 0 .. code::max_pages::() * 64; let salt = vec![42u8; (s * 1024) as usize]; let value = T::Currency::minimum_balance(); diff --git a/frame/contracts/src/tests.rs b/frame/contracts/src/tests.rs index f0bb8f5ffd11..d95d434e6a74 100644 --- a/frame/contracts/src/tests.rs +++ b/frame/contracts/src/tests.rs @@ -2249,7 +2249,7 @@ fn upload_code_works() { phase: Phase::Initialization, event: Event::Balances(pallet_balances::Event::Reserved { who: ALICE, - amount: 180, + amount: 240, }), topics: vec![], }, @@ -2328,7 +2328,7 @@ fn remove_code_works() { phase: Phase::Initialization, event: Event::Balances(pallet_balances::Event::Reserved { who: ALICE, - amount: 180, + amount: 240, }), topics: vec![], }, @@ -2341,7 +2341,7 @@ fn remove_code_works() { phase: Phase::Initialization, event: Event::Balances(pallet_balances::Event::Unreserved { who: ALICE, - amount: 180, + amount: 240, }), topics: vec![], }, @@ -2383,7 +2383,7 @@ fn remove_code_wrong_origin() { phase: Phase::Initialization, event: Event::Balances(pallet_balances::Event::Reserved { who: ALICE, - amount: 180, + amount: 240, }), topics: vec![], }, @@ -2514,7 +2514,7 @@ fn instantiate_with_zero_balance_works() { phase: Phase::Initialization, event: Event::Balances(pallet_balances::Event::Reserved { who: ALICE, - amount: 180, + amount: 240, }), topics: vec![], }, @@ -2614,7 +2614,7 @@ fn instantiate_with_below_existential_deposit_works() { phase: Phase::Initialization, event: Event::Balances(pallet_balances::Event::Reserved { who: ALICE, - amount: 180, + amount: 240, }), topics: vec![], }, From b07765f9ecc4c508fb4d0fba930b476c8509f5c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Mon, 31 Jan 2022 12:43:42 +0100 Subject: [PATCH 437/695] pallet-scheduler: Fix migrations V2 to V3 (#10757) * pallet-scheduler: Fix migrations V2 to V3 V2 already supported origins, so we need to move them over instead of setting it to `Root`. Besides that it also removes the custom `Releases` enum and moves it over to `StorageVersion`. * Fixes * Fixes * :facepalm: --- bin/node/cli/src/chain_spec.rs | 1 - bin/node/testing/src/genesis.rs | 1 - frame/democracy/src/tests.rs | 2 +- frame/scheduler/src/lib.rs | 139 +++++++++++++------------------- frame/scheduler/src/tests.rs | 8 +- 5 files changed, 61 insertions(+), 90 deletions(-) diff --git a/bin/node/cli/src/chain_spec.rs b/bin/node/cli/src/chain_spec.rs index 6fd57e31e466..11516f964903 100644 --- a/bin/node/cli/src/chain_spec.rs +++ b/bin/node/cli/src/chain_spec.rs @@ -362,7 +362,6 @@ pub fn testnet_genesis( assets: Default::default(), gilt: Default::default(), transaction_storage: Default::default(), - scheduler: Default::default(), transaction_payment: Default::default(), } } diff --git a/bin/node/testing/src/genesis.rs b/bin/node/testing/src/genesis.rs index 2e2f3f9a5a80..8d2b53b0b721 100644 --- a/bin/node/testing/src/genesis.rs +++ b/bin/node/testing/src/genesis.rs @@ -91,7 +91,6 @@ pub fn config_endowed(code: Option<&[u8]>, extra_endowed: Vec) -> Gen assets: Default::default(), gilt: Default::default(), transaction_storage: Default::default(), - scheduler: Default::default(), transaction_payment: Default::default(), } } diff --git a/frame/democracy/src/tests.rs b/frame/democracy/src/tests.rs index 641014923c23..0fe83a07610d 100644 --- a/frame/democracy/src/tests.rs +++ b/frame/democracy/src/tests.rs @@ -63,7 +63,7 @@ frame_support::construct_runtime!( { System: frame_system::{Pallet, Call, Config, Storage, Event}, Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, - Scheduler: pallet_scheduler::{Pallet, Call, Storage, Config, Event}, + Scheduler: pallet_scheduler::{Pallet, Call, Storage, Event}, Democracy: pallet_democracy::{Pallet, Call, Storage, Config, Event}, } ); diff --git a/frame/scheduler/src/lib.rs b/frame/scheduler/src/lib.rs index 7ecd9024e9f9..f9077d4c8c8f 100644 --- a/frame/scheduler/src/lib.rs +++ b/frame/scheduler/src/lib.rs @@ -63,7 +63,7 @@ use frame_support::{ dispatch::{DispatchError, DispatchResult, Dispatchable, Parameter}, traits::{ schedule::{self, DispatchTime, MaybeHashed}, - EnsureOrigin, Get, IsType, OriginTrait, PrivilegeCmp, + EnsureOrigin, Get, IsType, OriginTrait, PalletInfoAccess, PrivilegeCmp, StorageVersion, }, weights::{GetDispatchInfo, Weight}, }; @@ -132,22 +132,6 @@ pub type ScheduledOf = ScheduledV3Of; pub type Scheduled = ScheduledV2; -// A value placed in storage that represents the current version of the Scheduler storage. -// This value is used by the `on_runtime_upgrade` logic to determine whether we run -// storage migration logic. -#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug, TypeInfo)] -enum Releases { - V1, - V2, - V3, -} - -impl Default for Releases { - fn default() -> Self { - Releases::V1 - } -} - #[cfg(feature = "runtime-benchmarks")] mod preimage_provider { use frame_support::traits::PreimageRecipient; @@ -201,8 +185,12 @@ pub mod pallet { }; use frame_system::pallet_prelude::*; + /// The current storage version. + const STORAGE_VERSION: StorageVersion = StorageVersion::new(3); + #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::storage_version(STORAGE_VERSION)] #[pallet::without_storage_info] pub struct Pallet(_); @@ -268,12 +256,6 @@ pub mod pallet { pub(crate) type Lookup = StorageMap<_, Twox64Concat, Vec, TaskAddress>; - /// Storage version of the pallet. - /// - /// New networks start with last version. - #[pallet::storage] - pub(crate) type StorageVersion = StorageValue<_, Releases, ValueQuery>; - /// Events type. #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] @@ -308,23 +290,6 @@ pub mod pallet { RescheduleNoChange, } - #[pallet::genesis_config] - pub struct GenesisConfig; - - #[cfg(feature = "std")] - impl Default for GenesisConfig { - fn default() -> Self { - Self - } - } - - #[pallet::genesis_build] - impl GenesisBuild for GenesisConfig { - fn build(&self) { - StorageVersion::::put(Releases::V3); - } - } - #[pallet::hooks] impl Hooks> for Pallet { /// Execute the scheduled calls @@ -573,19 +538,19 @@ pub mod pallet { impl Pallet { /// Migrate storage format from V1 to V3. - /// Return true if migration is performed. - pub fn migrate_v1_to_v3() -> bool { - if StorageVersion::::get() == Releases::V1 { - StorageVersion::::put(Releases::V3); - - Agenda::::translate::< - Vec::Call, T::BlockNumber>>>, - _, - >(|_, agenda| { + /// + /// Returns the weight consumed by this migration. + pub fn migrate_v1_to_v3() -> Weight { + let mut weight = T::DbWeight::get().reads_writes(1, 1); + + Agenda::::translate::::Call, T::BlockNumber>>>, _>( + |_, agenda| { Some( agenda .into_iter() .map(|schedule| { + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); + schedule.map(|schedule| ScheduledV3 { maybe_id: schedule.maybe_id, priority: schedule.priority, @@ -597,56 +562,66 @@ impl Pallet { }) .collect::>(), ) - }); + }, + ); - true - } else { - false - } + frame_support::storage::migration::remove_storage_prefix( + Self::name().as_bytes(), + b"StorageVersion", + &[], + ); + + StorageVersion::new(3).put::(); + + weight + T::DbWeight::get().writes(2) } /// Migrate storage format from V2 to V3. - /// Return true if migration is performed. + /// + /// Returns the weight consumed by this migration. pub fn migrate_v2_to_v3() -> Weight { - if StorageVersion::::get() == Releases::V2 { - StorageVersion::::put(Releases::V3); - - let mut weight = T::DbWeight::get().reads_writes(1, 1); + let mut weight = T::DbWeight::get().reads_writes(1, 1); - Agenda::::translate::>>, _>(|_, agenda| { - Some( - agenda - .into_iter() - .map(|schedule| { - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); - schedule.map(|schedule| ScheduledV3 { - maybe_id: schedule.maybe_id, - priority: schedule.priority, - call: schedule.call.into(), - maybe_periodic: schedule.maybe_periodic, - origin: system::RawOrigin::Root.into(), - _phantom: Default::default(), - }) + Agenda::::translate::>>, _>(|_, agenda| { + Some( + agenda + .into_iter() + .map(|schedule| { + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); + schedule.map(|schedule| ScheduledV3 { + maybe_id: schedule.maybe_id, + priority: schedule.priority, + call: schedule.call.into(), + maybe_periodic: schedule.maybe_periodic, + origin: schedule.origin, + _phantom: Default::default(), }) - .collect::>(), - ) - }); + }) + .collect::>(), + ) + }); - weight - } else { - 0 - } + frame_support::storage::migration::remove_storage_prefix( + Self::name().as_bytes(), + b"StorageVersion", + &[], + ); + + StorageVersion::new(3).put::(); + + weight + T::DbWeight::get().writes(2) } #[cfg(feature = "try-runtime")] pub fn pre_migrate_to_v3() -> Result<(), &'static str> { - assert!(StorageVersion::::get() < Releases::V3); Ok(()) } #[cfg(feature = "try-runtime")] pub fn post_migrate_to_v3() -> Result<(), &'static str> { - assert!(StorageVersion::::get() == Releases::V3); + use frame_support::dispatch::GetStorageVersion; + + assert!(Self::current_storage_version() == 3); for k in Agenda::::iter_keys() { let _ = Agenda::::try_get(k).map_err(|()| "Invalid item in Agenda")?; } diff --git a/frame/scheduler/src/tests.rs b/frame/scheduler/src/tests.rs index 7681ede136d9..d2a795cb19fa 100644 --- a/frame/scheduler/src/tests.rs +++ b/frame/scheduler/src/tests.rs @@ -21,7 +21,7 @@ use super::*; use crate::mock::{logger, new_test_ext, root, run_to_block, Call, LoggerCall, Scheduler, Test, *}; use frame_support::{ assert_err, assert_noop, assert_ok, - traits::{Contains, OnInitialize, PreimageProvider}, + traits::{Contains, GetStorageVersion, OnInitialize, PreimageProvider}, Hashable, }; use sp_runtime::traits::Hash; @@ -707,9 +707,7 @@ fn migration_to_v3_works() { frame_support::migration::put_storage_value(b"Scheduler", b"Agenda", &k, old); } - assert_eq!(StorageVersion::::get(), Releases::V1); - - assert!(Scheduler::migrate_v1_to_v3()); + Scheduler::migrate_v1_to_v3(); assert_eq_uvec!( Agenda::::iter().collect::>(), @@ -783,7 +781,7 @@ fn migration_to_v3_works() { ] ); - assert_eq!(StorageVersion::::get(), Releases::V3); + assert_eq!(Scheduler::current_storage_version(), 3); }); } From 4b48e8ec7dffcb599248040f4da5be3de3c09318 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Mon, 31 Jan 2022 15:16:26 +0100 Subject: [PATCH 438/695] Add production profile to `substrate-wasm-builder` (#10747) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add production profile to wasm builder * Fix profile detection * Apply suggestions from code review Co-authored-by: Bastian Köcher * Replace panic! by println! + exit * Default to `release` for wasm on debug builds * Replaced unwrap by expect * Update all weights Rerun on the bm2 server. Signed-off-by: Oliver Tale-Yazdi * cargo run --quiet --profile=production --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_contracts --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/contracts/src/weights.rs --template=./.maintain/frame-weight-template.hbs Co-authored-by: Bastian Köcher Co-authored-by: Oliver Tale-Yazdi Co-authored-by: Parity Bot --- Cargo.lock | 16 +- frame/assets/src/weights.rs | 138 +- frame/bags-list/src/weights.rs | 18 +- frame/balances/src/weights.rs | 34 +- frame/benchmarking/src/weights.rs | 38 +- frame/bounties/src/weights.rs | 54 +- frame/child-bounties/src/weights.rs | 46 +- frame/collective/src/weights.rs | 130 +- frame/contracts/src/weights.rs | 1258 ++++++++--------- frame/democracy/src/weights.rs | 190 +-- .../src/weights.rs | 134 +- frame/elections-phragmen/src/weights.rs | 102 +- frame/gilt/src/weights.rs | 54 +- frame/identity/src/weights.rs | 182 +-- frame/im-online/src/weights.rs | 18 +- frame/indices/src/weights.rs | 26 +- frame/lottery/src/weights.rs | 38 +- frame/membership/src/weights.rs | 62 +- frame/multisig/src/weights.rs | 86 +- frame/preimage/src/weights.rs | 42 +- frame/proxy/src/weights.rs | 110 +- frame/scheduler/src/weights.rs | 150 +- frame/session/src/weights.rs | 14 +- frame/staking/src/weights.rs | 218 +-- frame/system/src/weights.rs | 26 +- frame/timestamp/src/weights.rs | 14 +- frame/tips/src/weights.rs | 62 +- frame/transaction-storage/src/weights.rs | 14 +- frame/treasury/src/weights.rs | 34 +- frame/uniques/src/weights.rs | 118 +- frame/utility/src/weights.rs | 30 +- frame/vesting/src/weights.rs | 106 +- utils/wasm-builder/Cargo.toml | 1 + utils/wasm-builder/src/lib.rs | 6 +- utils/wasm-builder/src/wasm_project.rs | 151 +- 35 files changed, 1915 insertions(+), 1805 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c2f24bd839ab..773b77036225 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -508,7 +508,7 @@ dependencies = [ "sp-keystore", "sp-runtime", "sp-tracing", - "strum", + "strum 0.22.0", "substrate-prometheus-endpoint", "thiserror", "wasm-timer", @@ -5710,7 +5710,7 @@ dependencies = [ "sp-std", "sp-tracing", "static_assertions", - "strum", + "strum 0.22.0", "strum_macros 0.23.1", ] @@ -9742,7 +9742,7 @@ dependencies = [ "lazy_static", "sp-core", "sp-runtime", - "strum", + "strum 0.22.0", ] [[package]] @@ -10219,6 +10219,15 @@ dependencies = [ "strum_macros 0.22.0", ] +[[package]] +name = "strum" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cae14b91c7d11c9a851d3fbc80a963198998c2a64eec840477fa92d8ce9b70bb" +dependencies = [ + "strum_macros 0.23.1", +] + [[package]] name = "strum_macros" version = "0.22.0" @@ -10479,6 +10488,7 @@ dependencies = [ "build-helper", "cargo_metadata", "sp-maybe-compressed-blob", + "strum 0.23.0", "tempfile", "toml", "walkdir", diff --git a/frame/assets/src/weights.rs b/frame/assets/src/weights.rs index fb6e68dfc772..a1cd77faee82 100644 --- a/frame/assets/src/weights.rs +++ b/frame/assets/src/weights.rs @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_assets //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-17, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-01-30, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/lto-fat-cg1/substrate +// ./target/production/substrate // benchmark // --chain=dev // --steps=50 @@ -34,7 +34,7 @@ // --heap-pages=4096 // --output=./frame/assets/src/weights.rs // --template=.maintain/frame-weight-template.hbs -// --header=LICENSE-APACHE2 +// --header=HEADER-APACHE2 // --raw #![cfg_attr(rustfmt, rustfmt_skip)] @@ -76,13 +76,13 @@ pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { // Storage: Assets Asset (r:1 w:1) fn create() -> Weight { - (22_050_000 as Weight) + (22_102_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:1) fn force_create() -> Weight { - (11_673_000 as Weight) + (12_124_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -93,12 +93,12 @@ impl WeightInfo for SubstrateWeight { // Storage: Assets Approvals (r:501 w:500) fn destroy(c: u32, s: u32, a: u32, ) -> Weight { (0 as Weight) - // Standard Error: 36_000 - .saturating_add((14_657_000 as Weight).saturating_mul(c as Weight)) - // Standard Error: 36_000 - .saturating_add((17_018_000 as Weight).saturating_mul(s as Weight)) - // Standard Error: 362_000 - .saturating_add((16_620_000 as Weight).saturating_mul(a as Weight)) + // Standard Error: 34_000 + .saturating_add((14_683_000 as Weight).saturating_mul(c as Weight)) + // Standard Error: 34_000 + .saturating_add((17_080_000 as Weight).saturating_mul(s as Weight)) + // Standard Error: 342_000 + .saturating_add((16_533_000 as Weight).saturating_mul(a as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(c as Weight))) .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(s as Weight))) @@ -111,14 +111,14 @@ impl WeightInfo for SubstrateWeight { // Storage: Assets Asset (r:1 w:1) // Storage: Assets Account (r:1 w:1) fn mint() -> Weight { - (26_254_000 as Weight) + (26_632_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Assets Asset (r:1 w:1) // Storage: Assets Account (r:1 w:1) fn burn() -> Weight { - (30_407_000 as Weight) + (30_048_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -126,7 +126,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Assets Account (r:2 w:2) // Storage: System Account (r:1 w:1) fn transfer() -> Weight { - (44_220_000 as Weight) + (44_000_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } @@ -134,7 +134,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Assets Account (r:2 w:2) // Storage: System Account (r:1 w:1) fn transfer_keep_alive() -> Weight { - (36_910_000 as Weight) + (37_286_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } @@ -142,93 +142,95 @@ impl WeightInfo for SubstrateWeight { // Storage: Assets Account (r:2 w:2) // Storage: System Account (r:1 w:1) fn force_transfer() -> Weight { - (44_330_000 as Weight) + (44_120_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } // Storage: Assets Asset (r:1 w:0) // Storage: Assets Account (r:1 w:1) fn freeze() -> Weight { - (17_937_000 as Weight) + (18_309_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:0) // Storage: Assets Account (r:1 w:1) fn thaw() -> Weight { - (18_224_000 as Weight) + (18_290_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:1) fn freeze_asset() -> Weight { - (14_875_000 as Weight) + (14_744_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:1) fn thaw_asset() -> Weight { - (14_792_000 as Weight) + (14_833_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:1) // Storage: Assets Metadata (r:1 w:0) fn transfer_ownership() -> Weight { - (15_794_000 as Weight) + (16_654_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:1) fn set_team() -> Weight { - (14_702_000 as Weight) + (15_351_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:0) // Storage: Assets Metadata (r:1 w:1) fn set_metadata(n: u32, s: u32, ) -> Weight { - (27_368_000 as Weight) + (27_588_000 as Weight) // Standard Error: 0 - .saturating_add((4_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((6_000 as Weight).saturating_mul(n as Weight)) // Standard Error: 0 - .saturating_add((4_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((3_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:0) // Storage: Assets Metadata (r:1 w:1) fn clear_metadata() -> Weight { - (28_222_000 as Weight) + (27_710_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:0) // Storage: Assets Metadata (r:1 w:1) - fn force_set_metadata(_n: u32, s: u32, ) -> Weight { - (15_139_000 as Weight) + fn force_set_metadata(n: u32, s: u32, ) -> Weight { + (15_345_000 as Weight) // Standard Error: 0 - .saturating_add((3_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((2_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 0 + .saturating_add((2_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:0) // Storage: Assets Metadata (r:1 w:1) fn force_clear_metadata() -> Weight { - (28_065_000 as Weight) + (27_552_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:1) fn force_asset_status() -> Weight { - (13_808_000 as Weight) + (13_755_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:1) // Storage: Assets Approvals (r:1 w:1) fn approve_transfer() -> Weight { - (31_261_000 as Weight) + (30_831_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -237,21 +239,21 @@ impl WeightInfo for SubstrateWeight { // Storage: Assets Account (r:2 w:2) // Storage: System Account (r:1 w:1) fn transfer_approved() -> Weight { - (56_329_000 as Weight) + (56_267_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } // Storage: Assets Asset (r:1 w:1) // Storage: Assets Approvals (r:1 w:1) fn cancel_approval() -> Weight { - (32_086_000 as Weight) + (31_964_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Assets Asset (r:1 w:1) // Storage: Assets Approvals (r:1 w:1) fn force_cancel_approval() -> Weight { - (32_502_000 as Weight) + (31_806_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -261,13 +263,13 @@ impl WeightInfo for SubstrateWeight { impl WeightInfo for () { // Storage: Assets Asset (r:1 w:1) fn create() -> Weight { - (22_050_000 as Weight) + (22_102_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:1) fn force_create() -> Weight { - (11_673_000 as Weight) + (12_124_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -278,12 +280,12 @@ impl WeightInfo for () { // Storage: Assets Approvals (r:501 w:500) fn destroy(c: u32, s: u32, a: u32, ) -> Weight { (0 as Weight) - // Standard Error: 36_000 - .saturating_add((14_657_000 as Weight).saturating_mul(c as Weight)) - // Standard Error: 36_000 - .saturating_add((17_018_000 as Weight).saturating_mul(s as Weight)) - // Standard Error: 362_000 - .saturating_add((16_620_000 as Weight).saturating_mul(a as Weight)) + // Standard Error: 34_000 + .saturating_add((14_683_000 as Weight).saturating_mul(c as Weight)) + // Standard Error: 34_000 + .saturating_add((17_080_000 as Weight).saturating_mul(s as Weight)) + // Standard Error: 342_000 + .saturating_add((16_533_000 as Weight).saturating_mul(a as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(c as Weight))) .saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(s as Weight))) @@ -296,14 +298,14 @@ impl WeightInfo for () { // Storage: Assets Asset (r:1 w:1) // Storage: Assets Account (r:1 w:1) fn mint() -> Weight { - (26_254_000 as Weight) + (26_632_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Assets Asset (r:1 w:1) // Storage: Assets Account (r:1 w:1) fn burn() -> Weight { - (30_407_000 as Weight) + (30_048_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -311,7 +313,7 @@ impl WeightInfo for () { // Storage: Assets Account (r:2 w:2) // Storage: System Account (r:1 w:1) fn transfer() -> Weight { - (44_220_000 as Weight) + (44_000_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } @@ -319,7 +321,7 @@ impl WeightInfo for () { // Storage: Assets Account (r:2 w:2) // Storage: System Account (r:1 w:1) fn transfer_keep_alive() -> Weight { - (36_910_000 as Weight) + (37_286_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } @@ -327,93 +329,95 @@ impl WeightInfo for () { // Storage: Assets Account (r:2 w:2) // Storage: System Account (r:1 w:1) fn force_transfer() -> Weight { - (44_330_000 as Weight) + (44_120_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } // Storage: Assets Asset (r:1 w:0) // Storage: Assets Account (r:1 w:1) fn freeze() -> Weight { - (17_937_000 as Weight) + (18_309_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:0) // Storage: Assets Account (r:1 w:1) fn thaw() -> Weight { - (18_224_000 as Weight) + (18_290_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:1) fn freeze_asset() -> Weight { - (14_875_000 as Weight) + (14_744_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:1) fn thaw_asset() -> Weight { - (14_792_000 as Weight) + (14_833_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:1) // Storage: Assets Metadata (r:1 w:0) fn transfer_ownership() -> Weight { - (15_794_000 as Weight) + (16_654_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:1) fn set_team() -> Weight { - (14_702_000 as Weight) + (15_351_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:0) // Storage: Assets Metadata (r:1 w:1) fn set_metadata(n: u32, s: u32, ) -> Weight { - (27_368_000 as Weight) + (27_588_000 as Weight) // Standard Error: 0 - .saturating_add((4_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((6_000 as Weight).saturating_mul(n as Weight)) // Standard Error: 0 - .saturating_add((4_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((3_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:0) // Storage: Assets Metadata (r:1 w:1) fn clear_metadata() -> Weight { - (28_222_000 as Weight) + (27_710_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:0) // Storage: Assets Metadata (r:1 w:1) - fn force_set_metadata(_n: u32, s: u32, ) -> Weight { - (15_139_000 as Weight) + fn force_set_metadata(n: u32, s: u32, ) -> Weight { + (15_345_000 as Weight) // Standard Error: 0 - .saturating_add((3_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((2_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 0 + .saturating_add((2_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:0) // Storage: Assets Metadata (r:1 w:1) fn force_clear_metadata() -> Weight { - (28_065_000 as Weight) + (27_552_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:1) fn force_asset_status() -> Weight { - (13_808_000 as Weight) + (13_755_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:1) // Storage: Assets Approvals (r:1 w:1) fn approve_transfer() -> Weight { - (31_261_000 as Weight) + (30_831_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -422,21 +426,21 @@ impl WeightInfo for () { // Storage: Assets Account (r:2 w:2) // Storage: System Account (r:1 w:1) fn transfer_approved() -> Weight { - (56_329_000 as Weight) + (56_267_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } // Storage: Assets Asset (r:1 w:1) // Storage: Assets Approvals (r:1 w:1) fn cancel_approval() -> Weight { - (32_086_000 as Weight) + (31_964_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Assets Asset (r:1 w:1) // Storage: Assets Approvals (r:1 w:1) fn force_cancel_approval() -> Weight { - (32_502_000 as Weight) + (31_806_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } diff --git a/frame/bags-list/src/weights.rs b/frame/bags-list/src/weights.rs index 6cd9449b4286..f35c0aaee6d6 100644 --- a/frame/bags-list/src/weights.rs +++ b/frame/bags-list/src/weights.rs @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_bags_list //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-19, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-01-30, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/optimized/substrate +// ./target/production/substrate // benchmark // --chain=dev // --steps=50 @@ -32,7 +32,7 @@ // --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./weights-optimized/frame/bags-list/src//weights.rs +// --output=./frame/bags-list/src/weights.rs // --template=.maintain/frame-weight-template.hbs // --header=HEADER-APACHE2 // --raw @@ -59,7 +59,7 @@ impl WeightInfo for SubstrateWeight { // Storage: BagsList ListNodes (r:4 w:4) // Storage: BagsList ListBags (r:1 w:1) fn rebag_non_terminal() -> Weight { - (50_222_000 as Weight) + (46_965_000 as Weight) .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } @@ -68,7 +68,7 @@ impl WeightInfo for SubstrateWeight { // Storage: BagsList ListNodes (r:3 w:3) // Storage: BagsList ListBags (r:2 w:2) fn rebag_terminal() -> Weight { - (47_975_000 as Weight) + (45_952_000 as Weight) .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } @@ -78,7 +78,7 @@ impl WeightInfo for SubstrateWeight { // Storage: BagsList CounterForListNodes (r:1 w:1) // Storage: BagsList ListBags (r:1 w:1) fn put_in_front_of() -> Weight { - (55_539_000 as Weight) + (52_928_000 as Weight) .saturating_add(T::DbWeight::get().reads(10 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } @@ -91,7 +91,7 @@ impl WeightInfo for () { // Storage: BagsList ListNodes (r:4 w:4) // Storage: BagsList ListBags (r:1 w:1) fn rebag_non_terminal() -> Weight { - (50_222_000 as Weight) + (46_965_000 as Weight) .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } @@ -100,7 +100,7 @@ impl WeightInfo for () { // Storage: BagsList ListNodes (r:3 w:3) // Storage: BagsList ListBags (r:2 w:2) fn rebag_terminal() -> Weight { - (47_975_000 as Weight) + (45_952_000 as Weight) .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } @@ -110,7 +110,7 @@ impl WeightInfo for () { // Storage: BagsList CounterForListNodes (r:1 w:1) // Storage: BagsList ListBags (r:1 w:1) fn put_in_front_of() -> Weight { - (55_539_000 as Weight) + (52_928_000 as Weight) .saturating_add(RocksDbWeight::get().reads(10 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } diff --git a/frame/balances/src/weights.rs b/frame/balances/src/weights.rs index f34dd65191e4..435438055b33 100644 --- a/frame/balances/src/weights.rs +++ b/frame/balances/src/weights.rs @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_balances //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-17, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-01-30, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/lto-fat-cg1/substrate +// ./target/production/substrate // benchmark // --chain=dev // --steps=50 @@ -34,7 +34,7 @@ // --heap-pages=4096 // --output=./frame/balances/src/weights.rs // --template=.maintain/frame-weight-template.hbs -// --header=LICENSE-APACHE2 +// --header=HEADER-APACHE2 // --raw #![cfg_attr(rustfmt, rustfmt_skip)] @@ -60,43 +60,43 @@ pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { // Storage: System Account (r:1 w:1) fn transfer() -> Weight { - (34_668_000 as Weight) + (34_200_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: System Account (r:1 w:1) fn transfer_keep_alive() -> Weight { - (26_826_000 as Weight) + (27_263_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: System Account (r:1 w:1) fn set_balance_creating() -> Weight { - (17_292_000 as Weight) + (17_425_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: System Account (r:1 w:1) fn set_balance_killing() -> Weight { - (19_988_000 as Weight) + (19_979_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: System Account (r:2 w:2) fn force_transfer() -> Weight { - (34_646_000 as Weight) + (34_783_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: System Account (r:1 w:1) fn transfer_all() -> Weight { - (32_040_000 as Weight) + (31_620_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: System Account (r:1 w:1) fn force_unreserve() -> Weight { - (15_743_000 as Weight) + (15_750_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -106,43 +106,43 @@ impl WeightInfo for SubstrateWeight { impl WeightInfo for () { // Storage: System Account (r:1 w:1) fn transfer() -> Weight { - (34_668_000 as Weight) + (34_200_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: System Account (r:1 w:1) fn transfer_keep_alive() -> Weight { - (26_826_000 as Weight) + (27_263_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: System Account (r:1 w:1) fn set_balance_creating() -> Weight { - (17_292_000 as Weight) + (17_425_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: System Account (r:1 w:1) fn set_balance_killing() -> Weight { - (19_988_000 as Weight) + (19_979_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: System Account (r:2 w:2) fn force_transfer() -> Weight { - (34_646_000 as Weight) + (34_783_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: System Account (r:1 w:1) fn transfer_all() -> Weight { - (32_040_000 as Weight) + (31_620_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: System Account (r:1 w:1) fn force_unreserve() -> Weight { - (15_743_000 as Weight) + (15_750_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } diff --git a/frame/benchmarking/src/weights.rs b/frame/benchmarking/src/weights.rs index 2945daeaf312..a49204fbf0b9 100644 --- a/frame/benchmarking/src/weights.rs +++ b/frame/benchmarking/src/weights.rs @@ -18,11 +18,11 @@ //! Autogenerated weights for frame_benchmarking //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-17, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-01-30, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/lto-fat-cg1/substrate +// ./target/production/substrate // benchmark // --chain=dev // --steps=50 @@ -34,7 +34,7 @@ // --heap-pages=4096 // --output=./frame/benchmarking/src/weights.rs // --template=.maintain/frame-weight-template.hbs -// --header=LICENSE-APACHE2 +// --header=HEADER-APACHE2 // --raw #![cfg_attr(rustfmt, rustfmt_skip)] @@ -60,37 +60,37 @@ pub trait WeightInfo { pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { fn addition(_i: u32, ) -> Weight { - (141_000 as Weight) + (106_000 as Weight) } fn subtraction(_i: u32, ) -> Weight { - (136_000 as Weight) + (111_000 as Weight) } fn multiplication(_i: u32, ) -> Weight { - (136_000 as Weight) + (119_000 as Weight) } fn division(_i: u32, ) -> Weight { - (134_000 as Weight) + (111_000 as Weight) } fn hashing(_i: u32, ) -> Weight { - (21_681_881_000 as Weight) + (21_203_386_000 as Weight) } fn sr25519_verification(i: u32, ) -> Weight { (0 as Weight) // Standard Error: 6_000 - .saturating_add((42_000_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((47_077_000 as Weight).saturating_mul(i as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn storage_read(i: u32, ) -> Weight { (0 as Weight) // Standard Error: 3_000 - .saturating_add((1_984_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((1_963_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) } // Storage: Skipped Metadata (r:0 w:0) fn storage_write(i: u32, ) -> Weight { (0 as Weight) // Standard Error: 0 - .saturating_add((363_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((364_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(i as Weight))) } } @@ -98,37 +98,37 @@ impl WeightInfo for SubstrateWeight { // For backwards compatibility and tests impl WeightInfo for () { fn addition(_i: u32, ) -> Weight { - (141_000 as Weight) + (106_000 as Weight) } fn subtraction(_i: u32, ) -> Weight { - (136_000 as Weight) + (111_000 as Weight) } fn multiplication(_i: u32, ) -> Weight { - (136_000 as Weight) + (119_000 as Weight) } fn division(_i: u32, ) -> Weight { - (134_000 as Weight) + (111_000 as Weight) } fn hashing(_i: u32, ) -> Weight { - (21_681_881_000 as Weight) + (21_203_386_000 as Weight) } fn sr25519_verification(i: u32, ) -> Weight { (0 as Weight) // Standard Error: 6_000 - .saturating_add((42_000_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((47_077_000 as Weight).saturating_mul(i as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn storage_read(i: u32, ) -> Weight { (0 as Weight) // Standard Error: 3_000 - .saturating_add((1_984_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((1_963_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) } // Storage: Skipped Metadata (r:0 w:0) fn storage_write(i: u32, ) -> Weight { (0 as Weight) // Standard Error: 0 - .saturating_add((363_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((364_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(i as Weight))) } } diff --git a/frame/bounties/src/weights.rs b/frame/bounties/src/weights.rs index 9c1ce532dff7..405e11acea5a 100644 --- a/frame/bounties/src/weights.rs +++ b/frame/bounties/src/weights.rs @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_bounties //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-17, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-01-30, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/lto-fat-cg1/substrate +// ./target/production/substrate // benchmark // --chain=dev // --steps=50 @@ -34,7 +34,7 @@ // --heap-pages=4096 // --output=./frame/bounties/src/weights.rs // --template=.maintain/frame-weight-template.hbs -// --header=LICENSE-APACHE2 +// --header=HEADER-APACHE2 // --raw #![cfg_attr(rustfmt, rustfmt_skip)] @@ -67,43 +67,43 @@ impl WeightInfo for SubstrateWeight { // Storage: Bounties BountyDescriptions (r:0 w:1) // Storage: Bounties Bounties (r:0 w:1) fn propose_bounty(d: u32, ) -> Weight { - (23_165_000 as Weight) + (23_620_000 as Weight) // Standard Error: 0 - .saturating_add((1_000 as Weight).saturating_mul(d as Weight)) + .saturating_add((2_000 as Weight).saturating_mul(d as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } // Storage: Bounties Bounties (r:1 w:1) // Storage: Bounties BountyApprovals (r:1 w:1) fn approve_bounty() -> Weight { - (6_876_000 as Weight) + (6_655_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Bounties Bounties (r:1 w:1) fn propose_curator() -> Weight { - (5_718_000 as Weight) + (5_720_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Bounties Bounties (r:1 w:1) // Storage: System Account (r:1 w:1) fn unassign_curator() -> Weight { - (27_021_000 as Weight) + (26_958_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Bounties Bounties (r:1 w:1) // Storage: System Account (r:1 w:1) fn accept_curator() -> Weight { - (20_933_000 as Weight) + (21_457_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Bounties Bounties (r:1 w:1) // Storage: ChildBounties ParentChildBounties (r:1 w:0) fn award_bounty() -> Weight { - (17_285_000 as Weight) + (17_483_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -112,7 +112,7 @@ impl WeightInfo for SubstrateWeight { // Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) // Storage: Bounties BountyDescriptions (r:0 w:1) fn claim_bounty() -> Weight { - (61_264_000 as Weight) + (61_763_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } @@ -121,7 +121,7 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:1 w:1) // Storage: Bounties BountyDescriptions (r:0 w:1) fn close_bounty_proposed() -> Weight { - (28_218_000 as Weight) + (28_862_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -130,13 +130,13 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:2 w:2) // Storage: Bounties BountyDescriptions (r:0 w:1) fn close_bounty_active() -> Weight { - (45_577_000 as Weight) + (45_129_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } // Storage: Bounties Bounties (r:1 w:1) fn extend_bounty_expiry() -> Weight { - (14_983_000 as Weight) + (15_169_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -146,7 +146,7 @@ impl WeightInfo for SubstrateWeight { fn spend_funds(b: u32, ) -> Weight { (0 as Weight) // Standard Error: 14_000 - .saturating_add((28_380_000 as Weight).saturating_mul(b as Weight)) + .saturating_add((28_850_000 as Weight).saturating_mul(b as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(b as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -161,43 +161,43 @@ impl WeightInfo for () { // Storage: Bounties BountyDescriptions (r:0 w:1) // Storage: Bounties Bounties (r:0 w:1) fn propose_bounty(d: u32, ) -> Weight { - (23_165_000 as Weight) + (23_620_000 as Weight) // Standard Error: 0 - .saturating_add((1_000 as Weight).saturating_mul(d as Weight)) + .saturating_add((2_000 as Weight).saturating_mul(d as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } // Storage: Bounties Bounties (r:1 w:1) // Storage: Bounties BountyApprovals (r:1 w:1) fn approve_bounty() -> Weight { - (6_876_000 as Weight) + (6_655_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Bounties Bounties (r:1 w:1) fn propose_curator() -> Weight { - (5_718_000 as Weight) + (5_720_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Bounties Bounties (r:1 w:1) // Storage: System Account (r:1 w:1) fn unassign_curator() -> Weight { - (27_021_000 as Weight) + (26_958_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Bounties Bounties (r:1 w:1) // Storage: System Account (r:1 w:1) fn accept_curator() -> Weight { - (20_933_000 as Weight) + (21_457_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Bounties Bounties (r:1 w:1) // Storage: ChildBounties ParentChildBounties (r:1 w:0) fn award_bounty() -> Weight { - (17_285_000 as Weight) + (17_483_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -206,7 +206,7 @@ impl WeightInfo for () { // Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) // Storage: Bounties BountyDescriptions (r:0 w:1) fn claim_bounty() -> Weight { - (61_264_000 as Weight) + (61_763_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } @@ -215,7 +215,7 @@ impl WeightInfo for () { // Storage: System Account (r:1 w:1) // Storage: Bounties BountyDescriptions (r:0 w:1) fn close_bounty_proposed() -> Weight { - (28_218_000 as Weight) + (28_862_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -224,13 +224,13 @@ impl WeightInfo for () { // Storage: System Account (r:2 w:2) // Storage: Bounties BountyDescriptions (r:0 w:1) fn close_bounty_active() -> Weight { - (45_577_000 as Weight) + (45_129_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } // Storage: Bounties Bounties (r:1 w:1) fn extend_bounty_expiry() -> Weight { - (14_983_000 as Weight) + (15_169_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -240,7 +240,7 @@ impl WeightInfo for () { fn spend_funds(b: u32, ) -> Weight { (0 as Weight) // Standard Error: 14_000 - .saturating_add((28_380_000 as Weight).saturating_mul(b as Weight)) + .saturating_add((28_850_000 as Weight).saturating_mul(b as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(b as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) diff --git a/frame/child-bounties/src/weights.rs b/frame/child-bounties/src/weights.rs index 73bc535cb300..002388810b8a 100644 --- a/frame/child-bounties/src/weights.rs +++ b/frame/child-bounties/src/weights.rs @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_child_bounties //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-19, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-01-30, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/optimized/substrate +// ./target/production/substrate // benchmark // --chain=dev // --steps=50 @@ -32,7 +32,7 @@ // --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./weights-optimized/frame/child-bounties/src//weights.rs +// --output=./frame/child-bounties/src/weights.rs // --template=.maintain/frame-weight-template.hbs // --header=HEADER-APACHE2 // --raw @@ -65,8 +65,10 @@ impl WeightInfo for SubstrateWeight { // Storage: ChildBounties ChildBountyCount (r:1 w:1) // Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) // Storage: ChildBounties ChildBounties (r:0 w:1) - fn add_child_bounty(_d: u32, ) -> Weight { - (44_997_000 as Weight) + fn add_child_bounty(d: u32, ) -> Weight { + (44_503_000 as Weight) + // Standard Error: 0 + .saturating_add((3_000 as Weight).saturating_mul(d as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } @@ -74,7 +76,7 @@ impl WeightInfo for SubstrateWeight { // Storage: ChildBounties ChildBounties (r:1 w:1) // Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) fn propose_curator() -> Weight { - (11_848_000 as Weight) + (11_661_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -82,7 +84,7 @@ impl WeightInfo for SubstrateWeight { // Storage: ChildBounties ChildBounties (r:1 w:1) // Storage: System Account (r:1 w:1) fn accept_curator() -> Weight { - (24_490_000 as Weight) + (24_162_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -90,14 +92,14 @@ impl WeightInfo for SubstrateWeight { // Storage: Bounties Bounties (r:1 w:0) // Storage: System Account (r:1 w:1) fn unassign_curator() -> Weight { - (28_605_000 as Weight) + (27_924_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Bounties Bounties (r:1 w:0) // Storage: ChildBounties ChildBounties (r:1 w:1) fn award_child_bounty() -> Weight { - (19_471_000 as Weight) + (19_332_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -106,7 +108,7 @@ impl WeightInfo for SubstrateWeight { // Storage: ChildBounties ParentChildBounties (r:1 w:1) // Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) fn claim_child_bounty() -> Weight { - (60_737_000 as Weight) + (60_363_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } @@ -117,7 +119,7 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:2 w:2) // Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) fn close_child_bounty_added() -> Weight { - (43_120_000 as Weight) + (42_415_000 as Weight) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } @@ -128,7 +130,7 @@ impl WeightInfo for SubstrateWeight { // Storage: ChildBounties ParentChildBounties (r:1 w:1) // Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) fn close_child_bounty_active() -> Weight { - (53_610_000 as Weight) + (52_743_000 as Weight) .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(7 as Weight)) } @@ -142,8 +144,10 @@ impl WeightInfo for () { // Storage: ChildBounties ChildBountyCount (r:1 w:1) // Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) // Storage: ChildBounties ChildBounties (r:0 w:1) - fn add_child_bounty(_d: u32, ) -> Weight { - (44_997_000 as Weight) + fn add_child_bounty(d: u32, ) -> Weight { + (44_503_000 as Weight) + // Standard Error: 0 + .saturating_add((3_000 as Weight).saturating_mul(d as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } @@ -151,7 +155,7 @@ impl WeightInfo for () { // Storage: ChildBounties ChildBounties (r:1 w:1) // Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) fn propose_curator() -> Weight { - (11_848_000 as Weight) + (11_661_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -159,7 +163,7 @@ impl WeightInfo for () { // Storage: ChildBounties ChildBounties (r:1 w:1) // Storage: System Account (r:1 w:1) fn accept_curator() -> Weight { - (24_490_000 as Weight) + (24_162_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -167,14 +171,14 @@ impl WeightInfo for () { // Storage: Bounties Bounties (r:1 w:0) // Storage: System Account (r:1 w:1) fn unassign_curator() -> Weight { - (28_605_000 as Weight) + (27_924_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Bounties Bounties (r:1 w:0) // Storage: ChildBounties ChildBounties (r:1 w:1) fn award_child_bounty() -> Weight { - (19_471_000 as Weight) + (19_332_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -183,7 +187,7 @@ impl WeightInfo for () { // Storage: ChildBounties ParentChildBounties (r:1 w:1) // Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) fn claim_child_bounty() -> Weight { - (60_737_000 as Weight) + (60_363_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } @@ -194,7 +198,7 @@ impl WeightInfo for () { // Storage: System Account (r:2 w:2) // Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) fn close_child_bounty_added() -> Weight { - (43_120_000 as Weight) + (42_415_000 as Weight) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } @@ -205,7 +209,7 @@ impl WeightInfo for () { // Storage: ChildBounties ParentChildBounties (r:1 w:1) // Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) fn close_child_bounty_active() -> Weight { - (53_610_000 as Weight) + (52_743_000 as Weight) .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(7 as Weight)) } diff --git a/frame/collective/src/weights.rs b/frame/collective/src/weights.rs index a559261fdea0..1280ced89eee 100644 --- a/frame/collective/src/weights.rs +++ b/frame/collective/src/weights.rs @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_collective //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-17, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-01-30, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/lto-fat-cg1/substrate +// ./target/production/substrate // benchmark // --chain=dev // --steps=50 @@ -34,7 +34,7 @@ // --heap-pages=4096 // --output=./frame/collective/src/weights.rs // --template=.maintain/frame-weight-template.hbs -// --header=LICENSE-APACHE2 +// --header=HEADER-APACHE2 // --raw #![cfg_attr(rustfmt, rustfmt_skip)] @@ -67,12 +67,12 @@ impl WeightInfo for SubstrateWeight { // Storage: Council Prime (r:0 w:1) fn set_members(m: u32, n: u32, p: u32, ) -> Weight { (0 as Weight) - // Standard Error: 7_000 - .saturating_add((12_933_000 as Weight).saturating_mul(m as Weight)) - // Standard Error: 7_000 - .saturating_add((81_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 7_000 - .saturating_add((15_645_000 as Weight).saturating_mul(p as Weight)) + // Standard Error: 10_000 + .saturating_add((14_493_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 10_000 + .saturating_add((23_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 10_000 + .saturating_add((16_909_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(p as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -80,21 +80,21 @@ impl WeightInfo for SubstrateWeight { } // Storage: Council Members (r:1 w:0) fn execute(b: u32, m: u32, ) -> Weight { - (12_975_000 as Weight) + (12_790_000 as Weight) // Standard Error: 0 .saturating_add((2_000 as Weight).saturating_mul(b as Weight)) // Standard Error: 0 - .saturating_add((74_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((73_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) } // Storage: Council Members (r:1 w:0) // Storage: Council ProposalOf (r:1 w:0) fn propose_execute(b: u32, m: u32, ) -> Weight { - (15_120_000 as Weight) + (15_087_000 as Weight) // Standard Error: 0 .saturating_add((2_000 as Weight).saturating_mul(b as Weight)) // Standard Error: 0 - .saturating_add((139_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((135_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) } // Storage: Council Members (r:1 w:0) @@ -103,22 +103,22 @@ impl WeightInfo for SubstrateWeight { // Storage: Council ProposalCount (r:1 w:1) // Storage: Council Voting (r:0 w:1) fn propose_proposed(b: u32, m: u32, p: u32, ) -> Weight { - (18_343_000 as Weight) + (18_269_000 as Weight) // Standard Error: 0 .saturating_add((8_000 as Weight).saturating_mul(b as Weight)) // Standard Error: 1_000 - .saturating_add((83_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((77_000 as Weight).saturating_mul(m as Weight)) // Standard Error: 1_000 - .saturating_add((211_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((203_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } // Storage: Council Members (r:1 w:0) // Storage: Council Voting (r:1 w:1) fn vote(m: u32, ) -> Weight { - (26_675_000 as Weight) + (26_624_000 as Weight) // Standard Error: 2_000 - .saturating_add((166_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((161_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -127,11 +127,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Council Proposals (r:1 w:1) // Storage: Council ProposalOf (r:0 w:1) fn close_early_disapproved(m: u32, p: u32, ) -> Weight { - (28_535_000 as Weight) + (26_527_000 as Weight) // Standard Error: 1_000 - .saturating_add((123_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((127_000 as Weight).saturating_mul(m as Weight)) // Standard Error: 1_000 - .saturating_add((154_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((155_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -140,13 +140,13 @@ impl WeightInfo for SubstrateWeight { // Storage: Council ProposalOf (r:1 w:1) // Storage: Council Proposals (r:1 w:1) fn close_early_approved(b: u32, m: u32, p: u32, ) -> Weight { - (27_235_000 as Weight) + (26_352_000 as Weight) // Standard Error: 0 .saturating_add((6_000 as Weight).saturating_mul(b as Weight)) // Standard Error: 1_000 - .saturating_add((158_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((154_000 as Weight).saturating_mul(m as Weight)) // Standard Error: 1_000 - .saturating_add((201_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((203_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -156,11 +156,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Council Proposals (r:1 w:1) // Storage: Council ProposalOf (r:0 w:1) fn close_disapproved(m: u32, p: u32, ) -> Weight { - (29_502_000 as Weight) + (28_638_000 as Weight) // Standard Error: 1_000 - .saturating_add((139_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((133_000 as Weight).saturating_mul(m as Weight)) // Standard Error: 1_000 - .saturating_add((163_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((162_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -170,13 +170,13 @@ impl WeightInfo for SubstrateWeight { // Storage: Council ProposalOf (r:1 w:1) // Storage: Council Proposals (r:1 w:1) fn close_approved(b: u32, m: u32, p: u32, ) -> Weight { - (28_944_000 as Weight) + (29_946_000 as Weight) // Standard Error: 0 .saturating_add((5_000 as Weight).saturating_mul(b as Weight)) - // Standard Error: 1_000 - .saturating_add((170_000 as Weight).saturating_mul(m as Weight)) - // Standard Error: 1_000 - .saturating_add((208_000 as Weight).saturating_mul(p as Weight)) + // Standard Error: 2_000 + .saturating_add((151_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 2_000 + .saturating_add((201_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -184,9 +184,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Council Voting (r:0 w:1) // Storage: Council ProposalOf (r:0 w:1) fn disapprove_proposal(p: u32, ) -> Weight { - (16_215_000 as Weight) + (15_778_000 as Weight) // Standard Error: 1_000 - .saturating_add((212_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((206_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -200,12 +200,12 @@ impl WeightInfo for () { // Storage: Council Prime (r:0 w:1) fn set_members(m: u32, n: u32, p: u32, ) -> Weight { (0 as Weight) - // Standard Error: 7_000 - .saturating_add((12_933_000 as Weight).saturating_mul(m as Weight)) - // Standard Error: 7_000 - .saturating_add((81_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 7_000 - .saturating_add((15_645_000 as Weight).saturating_mul(p as Weight)) + // Standard Error: 10_000 + .saturating_add((14_493_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 10_000 + .saturating_add((23_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 10_000 + .saturating_add((16_909_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(p as Weight))) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) @@ -213,21 +213,21 @@ impl WeightInfo for () { } // Storage: Council Members (r:1 w:0) fn execute(b: u32, m: u32, ) -> Weight { - (12_975_000 as Weight) + (12_790_000 as Weight) // Standard Error: 0 .saturating_add((2_000 as Weight).saturating_mul(b as Weight)) // Standard Error: 0 - .saturating_add((74_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((73_000 as Weight).saturating_mul(m as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) } // Storage: Council Members (r:1 w:0) // Storage: Council ProposalOf (r:1 w:0) fn propose_execute(b: u32, m: u32, ) -> Weight { - (15_120_000 as Weight) + (15_087_000 as Weight) // Standard Error: 0 .saturating_add((2_000 as Weight).saturating_mul(b as Weight)) // Standard Error: 0 - .saturating_add((139_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((135_000 as Weight).saturating_mul(m as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) } // Storage: Council Members (r:1 w:0) @@ -236,22 +236,22 @@ impl WeightInfo for () { // Storage: Council ProposalCount (r:1 w:1) // Storage: Council Voting (r:0 w:1) fn propose_proposed(b: u32, m: u32, p: u32, ) -> Weight { - (18_343_000 as Weight) + (18_269_000 as Weight) // Standard Error: 0 .saturating_add((8_000 as Weight).saturating_mul(b as Weight)) // Standard Error: 1_000 - .saturating_add((83_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((77_000 as Weight).saturating_mul(m as Weight)) // Standard Error: 1_000 - .saturating_add((211_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((203_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } // Storage: Council Members (r:1 w:0) // Storage: Council Voting (r:1 w:1) fn vote(m: u32, ) -> Weight { - (26_675_000 as Weight) + (26_624_000 as Weight) // Standard Error: 2_000 - .saturating_add((166_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((161_000 as Weight).saturating_mul(m as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -260,11 +260,11 @@ impl WeightInfo for () { // Storage: Council Proposals (r:1 w:1) // Storage: Council ProposalOf (r:0 w:1) fn close_early_disapproved(m: u32, p: u32, ) -> Weight { - (28_535_000 as Weight) + (26_527_000 as Weight) // Standard Error: 1_000 - .saturating_add((123_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((127_000 as Weight).saturating_mul(m as Weight)) // Standard Error: 1_000 - .saturating_add((154_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((155_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -273,13 +273,13 @@ impl WeightInfo for () { // Storage: Council ProposalOf (r:1 w:1) // Storage: Council Proposals (r:1 w:1) fn close_early_approved(b: u32, m: u32, p: u32, ) -> Weight { - (27_235_000 as Weight) + (26_352_000 as Weight) // Standard Error: 0 .saturating_add((6_000 as Weight).saturating_mul(b as Weight)) // Standard Error: 1_000 - .saturating_add((158_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((154_000 as Weight).saturating_mul(m as Weight)) // Standard Error: 1_000 - .saturating_add((201_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((203_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -289,11 +289,11 @@ impl WeightInfo for () { // Storage: Council Proposals (r:1 w:1) // Storage: Council ProposalOf (r:0 w:1) fn close_disapproved(m: u32, p: u32, ) -> Weight { - (29_502_000 as Weight) + (28_638_000 as Weight) // Standard Error: 1_000 - .saturating_add((139_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((133_000 as Weight).saturating_mul(m as Weight)) // Standard Error: 1_000 - .saturating_add((163_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((162_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -303,13 +303,13 @@ impl WeightInfo for () { // Storage: Council ProposalOf (r:1 w:1) // Storage: Council Proposals (r:1 w:1) fn close_approved(b: u32, m: u32, p: u32, ) -> Weight { - (28_944_000 as Weight) + (29_946_000 as Weight) // Standard Error: 0 .saturating_add((5_000 as Weight).saturating_mul(b as Weight)) - // Standard Error: 1_000 - .saturating_add((170_000 as Weight).saturating_mul(m as Weight)) - // Standard Error: 1_000 - .saturating_add((208_000 as Weight).saturating_mul(p as Weight)) + // Standard Error: 2_000 + .saturating_add((151_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 2_000 + .saturating_add((201_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -317,9 +317,9 @@ impl WeightInfo for () { // Storage: Council Voting (r:0 w:1) // Storage: Council ProposalOf (r:0 w:1) fn disapprove_proposal(p: u32, ) -> Weight { - (16_215_000 as Weight) + (15_778_000 as Weight) // Standard Error: 1_000 - .saturating_add((212_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((206_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } diff --git a/frame/contracts/src/weights.rs b/frame/contracts/src/weights.rs index acc13104d928..24a42cc10649 100644 --- a/frame/contracts/src/weights.rs +++ b/frame/contracts/src/weights.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_contracts //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-28, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-01-31, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -156,14 +156,14 @@ pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize() -> Weight { - (1_601_000 as Weight) + (1_642_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn on_initialize_per_trie_key(k: u32, ) -> Weight { - (10_543_000 as Weight) + (7_854_000 as Weight) // Standard Error: 0 - .saturating_add((739_000 as Weight).saturating_mul(k as Weight)) + .saturating_add((742_000 as Weight).saturating_mul(k as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) @@ -171,17 +171,17 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize_per_queue_item(q: u32, ) -> Weight { (0 as Weight) - // Standard Error: 3_000 - .saturating_add((2_285_000 as Weight).saturating_mul(q as Weight)) + // Standard Error: 6_000 + .saturating_add((2_216_000 as Weight).saturating_mul(q as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Contracts PristineCode (r:1 w:0) // Storage: Contracts CodeStorage (r:0 w:1) fn reinstrument(c: u32, ) -> Weight { - (16_846_000 as Weight) - // Standard Error: 33_000 - .saturating_add((71_629_000 as Weight).saturating_mul(c as Weight)) + (17_413_000 as Weight) + // Standard Error: 39_000 + .saturating_add((64_495_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -190,9 +190,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call_with_code_kb(c: u32, ) -> Weight { - (160_645_000 as Weight) - // Standard Error: 51_000 - .saturating_add((60_029_000 as Weight).saturating_mul(c as Weight)) + (209_071_000 as Weight) + // Standard Error: 47_000 + .saturating_add((56_555_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -204,11 +204,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn instantiate_with_code(c: u32, s: u32, ) -> Weight { - (160_721_000 as Weight) - // Standard Error: 200_000 - .saturating_add((156_185_000 as Weight).saturating_mul(c as Weight)) - // Standard Error: 13_000 - .saturating_add((1_785_000 as Weight).saturating_mul(s as Weight)) + (210_420_000 as Weight) + // Standard Error: 133_000 + .saturating_add((145_601_000 as Weight).saturating_mul(c as Weight)) + // Standard Error: 8_000 + .saturating_add((1_760_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } @@ -219,9 +219,9 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn instantiate(s: u32, ) -> Weight { - (145_929_000 as Weight) + (173_397_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_743_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((1_714_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } @@ -230,7 +230,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call() -> Weight { - (114_204_000 as Weight) + (140_169_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -238,9 +238,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn upload_code(c: u32, ) -> Weight { - (51_131_000 as Weight) - // Standard Error: 48_000 - .saturating_add((70_405_000 as Weight).saturating_mul(c as Weight)) + (49_076_000 as Weight) + // Standard Error: 37_000 + .saturating_add((67_150_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -248,7 +248,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:0 w:1) // Storage: Contracts PristineCode (r:0 w:1) fn remove_code() -> Weight { - (24_452_000 as Weight) + (24_318_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -257,9 +257,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_caller(r: u32, ) -> Weight { - (168_803_000 as Weight) - // Standard Error: 119_000 - .saturating_add((56_278_000 as Weight).saturating_mul(r as Weight)) + (208_256_000 as Weight) + // Standard Error: 116_000 + .saturating_add((49_878_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -268,9 +268,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_address(r: u32, ) -> Weight { - (170_921_000 as Weight) - // Standard Error: 150_000 - .saturating_add((56_973_000 as Weight).saturating_mul(r as Weight)) + (230_530_000 as Weight) + // Standard Error: 132_000 + .saturating_add((47_902_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -279,9 +279,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas_left(r: u32, ) -> Weight { - (168_953_000 as Weight) - // Standard Error: 116_000 - .saturating_add((56_032_000 as Weight).saturating_mul(r as Weight)) + (219_027_000 as Weight) + // Standard Error: 108_000 + .saturating_add((48_039_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -290,9 +290,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_balance(r: u32, ) -> Weight { - (170_043_000 as Weight) - // Standard Error: 147_000 - .saturating_add((152_039_000 as Weight).saturating_mul(r as Weight)) + (219_036_000 as Weight) + // Standard Error: 152_000 + .saturating_add((137_047_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -301,9 +301,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_value_transferred(r: u32, ) -> Weight { - (183_371_000 as Weight) - // Standard Error: 111_000 - .saturating_add((54_799_000 as Weight).saturating_mul(r as Weight)) + (214_401_000 as Weight) + // Standard Error: 96_000 + .saturating_add((48_435_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -312,9 +312,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_minimum_balance(r: u32, ) -> Weight { - (181_993_000 as Weight) - // Standard Error: 127_000 - .saturating_add((54_617_000 as Weight).saturating_mul(r as Weight)) + (216_939_000 as Weight) + // Standard Error: 106_000 + .saturating_add((48_198_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -323,9 +323,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_block_number(r: u32, ) -> Weight { - (179_543_000 as Weight) - // Standard Error: 96_000 - .saturating_add((54_526_000 as Weight).saturating_mul(r as Weight)) + (216_637_000 as Weight) + // Standard Error: 86_000 + .saturating_add((47_819_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -334,9 +334,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_now(r: u32, ) -> Weight { - (174_365_000 as Weight) - // Standard Error: 117_000 - .saturating_add((54_433_000 as Weight).saturating_mul(r as Weight)) + (214_863_000 as Weight) + // Standard Error: 110_000 + .saturating_add((48_208_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -346,9 +346,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0) fn seal_weight_to_fee(r: u32, ) -> Weight { - (186_003_000 as Weight) - // Standard Error: 187_000 - .saturating_add((133_644_000 as Weight).saturating_mul(r as Weight)) + (216_494_000 as Weight) + // Standard Error: 141_000 + .saturating_add((120_736_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -357,9 +357,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas(r: u32, ) -> Weight { - (91_771_000 as Weight) - // Standard Error: 68_000 - .saturating_add((28_003_000 as Weight).saturating_mul(r as Weight)) + (123_867_000 as Weight) + // Standard Error: 33_000 + .saturating_add((24_578_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -368,9 +368,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input(r: u32, ) -> Weight { - (170_110_000 as Weight) - // Standard Error: 104_000 - .saturating_add((53_937_000 as Weight).saturating_mul(r as Weight)) + (215_578_000 as Weight) + // Standard Error: 108_000 + .saturating_add((47_512_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -379,9 +379,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input_per_kb(n: u32, ) -> Weight { - (251_576_000 as Weight) - // Standard Error: 9_000 - .saturating_add((10_613_000 as Weight).saturating_mul(n as Weight)) + (297_663_000 as Weight) + // Standard Error: 3_000 + .saturating_add((11_863_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -390,9 +390,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return(r: u32, ) -> Weight { - (176_897_000 as Weight) - // Standard Error: 119_000 - .saturating_add((3_095_000 as Weight).saturating_mul(r as Weight)) + (209_709_000 as Weight) + // Standard Error: 75_000 + .saturating_add((1_783_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -401,9 +401,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return_per_kb(n: u32, ) -> Weight { - (161_820_000 as Weight) + (214_403_000 as Weight) // Standard Error: 0 - .saturating_add((184_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((197_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -414,9 +414,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts DeletionQueue (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_terminate(r: u32, ) -> Weight { - (163_213_000 as Weight) - // Standard Error: 922_000 - .saturating_add((65_249_000 as Weight).saturating_mul(r as Weight)) + (214_454_000 as Weight) + // Standard Error: 656_000 + .saturating_add((50_641_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((4 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -428,9 +428,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) fn seal_random(r: u32, ) -> Weight { - (178_636_000 as Weight) - // Standard Error: 189_000 - .saturating_add((166_008_000 as Weight).saturating_mul(r as Weight)) + (214_140_000 as Weight) + // Standard Error: 169_000 + .saturating_add((158_778_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -439,9 +439,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_deposit_event(r: u32, ) -> Weight { - (187_377_000 as Weight) - // Standard Error: 186_000 - .saturating_add((289_005_000 as Weight).saturating_mul(r as Weight)) + (225_998_000 as Weight) + // Standard Error: 171_000 + .saturating_add((280_296_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -451,11 +451,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: System EventTopics (r:100 w:100) fn seal_deposit_event_per_topic_and_kb(t: u32, n: u32, ) -> Weight { - (487_726_000 as Weight) - // Standard Error: 1_980_000 - .saturating_add((291_760_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 390_000 - .saturating_add((78_950_000 as Weight).saturating_mul(n as Weight)) + (491_432_000 as Weight) + // Standard Error: 1_992_000 + .saturating_add((288_376_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 392_000 + .saturating_add((82_805_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(t as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -466,17 +466,17 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_debug_message(r: u32, ) -> Weight { - (105_118_000 as Weight) - // Standard Error: 80_000 - .saturating_add((45_277_000 as Weight).saturating_mul(r as Weight)) + (130_861_000 as Weight) + // Standard Error: 74_000 + .saturating_add((40_268_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage(r: u32, ) -> Weight { - (0 as Weight) - // Standard Error: 1_084_000 - .saturating_add((423_125_000 as Weight).saturating_mul(r as Weight)) + (38_843_000 as Weight) + // Standard Error: 1_044_000 + .saturating_add((408_027_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -484,25 +484,25 @@ impl WeightInfo for SubstrateWeight { } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage_per_new_kb(n: u32, ) -> Weight { - (565_293_000 as Weight) - // Standard Error: 257_000 - .saturating_add((26_134_000 as Weight).saturating_mul(n as Weight)) + (610_782_000 as Weight) + // Standard Error: 265_000 + .saturating_add((28_221_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage_per_old_kb(n: u32, ) -> Weight { - (582_851_000 as Weight) - // Standard Error: 306_000 - .saturating_add((11_991_000 as Weight).saturating_mul(n as Weight)) + (625_031_000 as Weight) + // Standard Error: 319_000 + .saturating_add((11_126_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage(r: u32, ) -> Weight { - (51_270_000 as Weight) - // Standard Error: 883_000 - .saturating_add((394_518_000 as Weight).saturating_mul(r as Weight)) + (78_566_000 as Weight) + // Standard Error: 970_000 + .saturating_add((384_877_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -510,51 +510,51 @@ impl WeightInfo for SubstrateWeight { } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage_per_kb(n: u32, ) -> Weight { - (585_361_000 as Weight) - // Standard Error: 263_000 - .saturating_add((10_855_000 as Weight).saturating_mul(n as Weight)) + (601_558_000 as Weight) + // Standard Error: 280_000 + .saturating_add((11_378_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage(r: u32, ) -> Weight { - (60_404_000 as Weight) - // Standard Error: 667_000 - .saturating_add((335_130_000 as Weight).saturating_mul(r as Weight)) + (112_328_000 as Weight) + // Standard Error: 668_000 + .saturating_add((323_031_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage_per_kb(n: u32, ) -> Weight { - (539_500_000 as Weight) - // Standard Error: 378_000 - .saturating_add((62_855_000 as Weight).saturating_mul(n as Weight)) + (556_303_000 as Weight) + // Standard Error: 346_000 + .saturating_add((64_170_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(104 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_contains_storage(r: u32, ) -> Weight { - (58_301_000 as Weight) - // Standard Error: 701_000 - .saturating_add((301_511_000 as Weight).saturating_mul(r as Weight)) + (106_572_000 as Weight) + // Standard Error: 691_000 + .saturating_add((294_964_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_contains_storage_per_kb(n: u32, ) -> Weight { - (485_967_000 as Weight) - // Standard Error: 266_000 - .saturating_add((10_314_000 as Weight).saturating_mul(n as Weight)) + (508_339_000 as Weight) + // Standard Error: 245_000 + .saturating_add((10_675_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(104 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage(r: u32, ) -> Weight { - (42_688_000 as Weight) - // Standard Error: 889_000 - .saturating_add((436_932_000 as Weight).saturating_mul(r as Weight)) + (88_096_000 as Weight) + // Standard Error: 927_000 + .saturating_add((415_543_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -562,9 +562,9 @@ impl WeightInfo for SubstrateWeight { } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage_per_kb(n: u32, ) -> Weight { - (638_201_000 as Weight) - // Standard Error: 373_000 - .saturating_add((64_277_000 as Weight).saturating_mul(n as Weight)) + (650_912_000 as Weight) + // Standard Error: 359_000 + .saturating_add((65_030_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().writes(103 as Weight)) } @@ -573,9 +573,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_transfer(r: u32, ) -> Weight { - (49_486_000 as Weight) - // Standard Error: 1_275_000 - .saturating_add((1_790_231_000 as Weight).saturating_mul(r as Weight)) + (102_673_000 as Weight) + // Standard Error: 1_159_000 + .saturating_add((1_711_312_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -586,9 +586,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_call(r: u32, ) -> Weight { - (2_498_893_000 as Weight) - // Standard Error: 20_838_000 - .saturating_add((14_474_373_000 as Weight).saturating_mul(r as Weight)) + (0 as Weight) + // Standard Error: 3_592_000 + .saturating_add((19_565_726_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -599,13 +599,13 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:2 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_call_per_transfer_input_output_kb(t: u32, i: u32, o: u32, ) -> Weight { - (16_423_215_000 as Weight) - // Standard Error: 43_595_000 - .saturating_add((1_644_304_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 15_000 - .saturating_add((17_700_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 16_000 - .saturating_add((28_564_000 as Weight).saturating_mul(o as Weight)) + (19_665_171_000 as Weight) + // Standard Error: 27_641_000 + .saturating_add((2_089_637_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 9_000 + .saturating_add((20_165_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 10_000 + .saturating_add((31_728_000 as Weight).saturating_mul(o as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().reads((101 as Weight).saturating_mul(t as Weight))) .saturating_add(T::DbWeight::get().writes(101 as Weight)) @@ -619,8 +619,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts OwnerInfoOf (r:100 w:100) fn seal_instantiate(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 52_924_000 - .saturating_add((24_062_215_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 48_640_000 + .saturating_add((27_307_450_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().reads((400 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -633,13 +633,13 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts AccountCounter (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_instantiate_per_input_output_salt_kb(i: u32, o: u32, s: u32, ) -> Weight { - (19_940_217_000 as Weight) - // Standard Error: 36_000 - .saturating_add((17_853_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 36_000 - .saturating_add((29_592_000 as Weight).saturating_mul(o as Weight)) - // Standard Error: 36_000 - .saturating_add((155_914_000 as Weight).saturating_mul(s as Weight)) + (24_821_248_000 as Weight) + // Standard Error: 26_000 + .saturating_add((20_118_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 26_000 + .saturating_add((31_616_000 as Weight).saturating_mul(o as Weight)) + // Standard Error: 26_000 + .saturating_add((157_567_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(208 as Weight)) .saturating_add(T::DbWeight::get().writes(206 as Weight)) } @@ -648,9 +648,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256(r: u32, ) -> Weight { - (166_372_000 as Weight) - // Standard Error: 150_000 - .saturating_add((85_445_000 as Weight).saturating_mul(r as Weight)) + (213_816_000 as Weight) + // Standard Error: 147_000 + .saturating_add((80_336_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -659,9 +659,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256_per_kb(n: u32, ) -> Weight { - (323_005_000 as Weight) - // Standard Error: 28_000 - .saturating_add((464_801_000 as Weight).saturating_mul(n as Weight)) + (309_038_000 as Weight) + // Standard Error: 23_000 + .saturating_add((465_306_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -670,9 +670,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256(r: u32, ) -> Weight { - (167_869_000 as Weight) - // Standard Error: 156_000 - .saturating_add((96_037_000 as Weight).saturating_mul(r as Weight)) + (212_825_000 as Weight) + // Standard Error: 143_000 + .saturating_add((91_947_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -681,9 +681,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256_per_kb(n: u32, ) -> Weight { - (235_448_000 as Weight) - // Standard Error: 30_000 - .saturating_add((306_489_000 as Weight).saturating_mul(n as Weight)) + (329_548_000 as Weight) + // Standard Error: 19_000 + .saturating_add((306_729_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -692,9 +692,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256(r: u32, ) -> Weight { - (166_113_000 as Weight) - // Standard Error: 128_000 - .saturating_add((68_810_000 as Weight).saturating_mul(r as Weight)) + (215_907_000 as Weight) + // Standard Error: 129_000 + .saturating_add((63_477_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -703,9 +703,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256_per_kb(n: u32, ) -> Weight { - (276_885_000 as Weight) + (423_811_000 as Weight) // Standard Error: 16_000 - .saturating_add((120_098_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((119_607_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -714,9 +714,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128(r: u32, ) -> Weight { - (168_106_000 as Weight) - // Standard Error: 131_000 - .saturating_add((68_109_000 as Weight).saturating_mul(r as Weight)) + (214_747_000 as Weight) + // Standard Error: 115_000 + .saturating_add((62_904_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -725,9 +725,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128_per_kb(n: u32, ) -> Weight { - (244_443_000 as Weight) + (437_217_000 as Weight) // Standard Error: 19_000 - .saturating_add((120_286_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((120_126_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -736,266 +736,266 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_ecdsa_recover(r: u32, ) -> Weight { - (207_765_000 as Weight) - // Standard Error: 1_529_000 - .saturating_add((15_403_795_000 as Weight).saturating_mul(r as Weight)) + (195_980_000 as Weight) + // Standard Error: 1_262_000 + .saturating_add((15_428_805_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn instr_i64const(r: u32, ) -> Weight { - (46_110_000 as Weight) - // Standard Error: 11_000 - .saturating_add((813_000 as Weight).saturating_mul(r as Weight)) + (74_569_000 as Weight) + // Standard Error: 1_000 + .saturating_add((589_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64load(r: u32, ) -> Weight { - (52_944_000 as Weight) - // Standard Error: 12_000 - .saturating_add((2_501_000 as Weight).saturating_mul(r as Weight)) + (74_212_000 as Weight) + // Standard Error: 0 + .saturating_add((1_325_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64store(r: u32, ) -> Weight { - (52_968_000 as Weight) - // Standard Error: 12_000 - .saturating_add((2_528_000 as Weight).saturating_mul(r as Weight)) + (74_505_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_423_000 as Weight).saturating_mul(r as Weight)) } fn instr_select(r: u32, ) -> Weight { - (36_871_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_994_000 as Weight).saturating_mul(r as Weight)) + (74_005_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_785_000 as Weight).saturating_mul(r as Weight)) } fn instr_if(r: u32, ) -> Weight { - (36_834_000 as Weight) - // Standard Error: 16_000 - .saturating_add((3_060_000 as Weight).saturating_mul(r as Weight)) + (74_212_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_890_000 as Weight).saturating_mul(r as Weight)) } fn instr_br(r: u32, ) -> Weight { - (39_250_000 as Weight) - // Standard Error: 16_000 - .saturating_add((1_933_000 as Weight).saturating_mul(r as Weight)) + (74_102_000 as Weight) + // Standard Error: 2_000 + .saturating_add((896_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_if(r: u32, ) -> Weight { - (38_302_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_496_000 as Weight).saturating_mul(r as Weight)) + (73_523_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_456_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table(r: u32, ) -> Weight { - (44_800_000 as Weight) - // Standard Error: 21_000 - .saturating_add((2_407_000 as Weight).saturating_mul(r as Weight)) + (73_307_000 as Weight) + // Standard Error: 4_000 + .saturating_add((1_594_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table_per_entry(e: u32, ) -> Weight { - (46_996_000 as Weight) - // Standard Error: 3_000 - .saturating_add((27_000 as Weight).saturating_mul(e as Weight)) + (76_272_000 as Weight) + // Standard Error: 0 + .saturating_add((5_000 as Weight).saturating_mul(e as Weight)) } fn instr_call(r: u32, ) -> Weight { - (48_704_000 as Weight) - // Standard Error: 24_000 - .saturating_add((20_212_000 as Weight).saturating_mul(r as Weight)) + (73_390_000 as Weight) + // Standard Error: 23_000 + .saturating_add((16_936_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect(r: u32, ) -> Weight { - (52_546_000 as Weight) - // Standard Error: 32_000 - .saturating_add((29_995_000 as Weight).saturating_mul(r as Weight)) + (89_331_000 as Weight) + // Standard Error: 30_000 + .saturating_add((28_104_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect_per_param(p: u32, ) -> Weight { - (85_521_000 as Weight) - // Standard Error: 5_000 - .saturating_add((1_117_000 as Weight).saturating_mul(p as Weight)) + (117_023_000 as Weight) + // Standard Error: 3_000 + .saturating_add((914_000 as Weight).saturating_mul(p as Weight)) } fn instr_local_get(r: u32, ) -> Weight { - (39_081_000 as Weight) - // Standard Error: 14_000 - .saturating_add((1_338_000 as Weight).saturating_mul(r as Weight)) + (74_727_000 as Weight) + // Standard Error: 1_000 + .saturating_add((618_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_set(r: u32, ) -> Weight { - (39_014_000 as Weight) - // Standard Error: 14_000 - .saturating_add((1_365_000 as Weight).saturating_mul(r as Weight)) + (74_893_000 as Weight) + // Standard Error: 1_000 + .saturating_add((674_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_tee(r: u32, ) -> Weight { - (41_269_000 as Weight) - // Standard Error: 12_000 - .saturating_add((1_879_000 as Weight).saturating_mul(r as Weight)) + (74_552_000 as Weight) + // Standard Error: 1_000 + .saturating_add((898_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_get(r: u32, ) -> Weight { - (40_341_000 as Weight) - // Standard Error: 12_000 - .saturating_add((1_944_000 as Weight).saturating_mul(r as Weight)) + (77_355_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_146_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_set(r: u32, ) -> Weight { - (45_833_000 as Weight) - // Standard Error: 12_000 - .saturating_add((1_757_000 as Weight).saturating_mul(r as Weight)) + (77_055_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_363_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_current(r: u32, ) -> Weight { - (46_780_000 as Weight) - // Standard Error: 12_000 - .saturating_add((806_000 as Weight).saturating_mul(r as Weight)) + (74_648_000 as Weight) + // Standard Error: 2_000 + .saturating_add((652_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_grow(r: u32, ) -> Weight { - (49_585_000 as Weight) - // Standard Error: 1_723_000 - .saturating_add((166_106_000 as Weight).saturating_mul(r as Weight)) + (73_777_000 as Weight) + // Standard Error: 226_000 + .saturating_add((187_252_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64clz(r: u32, ) -> Weight { - (43_423_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_494_000 as Weight).saturating_mul(r as Weight)) + (74_332_000 as Weight) + // Standard Error: 1_000 + .saturating_add((897_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ctz(r: u32, ) -> Weight { - (43_237_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_499_000 as Weight).saturating_mul(r as Weight)) + (74_265_000 as Weight) + // Standard Error: 1_000 + .saturating_add((898_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64popcnt(r: u32, ) -> Weight { - (43_308_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_505_000 as Weight).saturating_mul(r as Weight)) + (74_475_000 as Weight) + // Standard Error: 2_000 + .saturating_add((892_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eqz(r: u32, ) -> Weight { - (43_440_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_503_000 as Weight).saturating_mul(r as Weight)) + (74_297_000 as Weight) + // Standard Error: 1_000 + .saturating_add((918_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendsi32(r: u32, ) -> Weight { - (40_782_000 as Weight) - // Standard Error: 13_000 - .saturating_add((1_948_000 as Weight).saturating_mul(r as Weight)) + (74_146_000 as Weight) + // Standard Error: 1_000 + .saturating_add((884_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendui32(r: u32, ) -> Weight { - (41_210_000 as Weight) - // Standard Error: 12_000 - .saturating_add((1_925_000 as Weight).saturating_mul(r as Weight)) + (74_361_000 as Weight) + // Standard Error: 1_000 + .saturating_add((877_000 as Weight).saturating_mul(r as Weight)) } fn instr_i32wrapi64(r: u32, ) -> Weight { - (43_108_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_506_000 as Weight).saturating_mul(r as Weight)) + (74_554_000 as Weight) + // Standard Error: 1_000 + .saturating_add((884_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eq(r: u32, ) -> Weight { - (36_501_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_490_000 as Weight).saturating_mul(r as Weight)) + (74_169_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_357_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ne(r: u32, ) -> Weight { - (36_289_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_494_000 as Weight).saturating_mul(r as Weight)) + (74_164_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_357_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64lts(r: u32, ) -> Weight { - (36_414_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_492_000 as Weight).saturating_mul(r as Weight)) + (74_058_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_362_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ltu(r: u32, ) -> Weight { - (36_205_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_498_000 as Weight).saturating_mul(r as Weight)) + (74_039_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_362_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gts(r: u32, ) -> Weight { - (36_648_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_473_000 as Weight).saturating_mul(r as Weight)) + (75_055_000 as Weight) + // Standard Error: 4_000 + .saturating_add((1_338_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gtu(r: u32, ) -> Weight { - (36_530_000 as Weight) - // Standard Error: 18_000 - .saturating_add((2_488_000 as Weight).saturating_mul(r as Weight)) + (74_536_000 as Weight) + // Standard Error: 4_000 + .saturating_add((1_367_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64les(r: u32, ) -> Weight { - (36_622_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_483_000 as Weight).saturating_mul(r as Weight)) + (74_177_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_358_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64leu(r: u32, ) -> Weight { - (36_465_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_490_000 as Weight).saturating_mul(r as Weight)) + (74_080_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_370_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ges(r: u32, ) -> Weight { - (36_291_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_494_000 as Weight).saturating_mul(r as Weight)) + (74_237_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_356_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64geu(r: u32, ) -> Weight { - (36_454_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_483_000 as Weight).saturating_mul(r as Weight)) + (74_049_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_362_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64add(r: u32, ) -> Weight { - (36_801_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_468_000 as Weight).saturating_mul(r as Weight)) + (74_186_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_335_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64sub(r: u32, ) -> Weight { - (36_670_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_483_000 as Weight).saturating_mul(r as Weight)) + (74_268_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_339_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64mul(r: u32, ) -> Weight { - (36_388_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_494_000 as Weight).saturating_mul(r as Weight)) + (74_334_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_331_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divs(r: u32, ) -> Weight { - (36_952_000 as Weight) - // Standard Error: 16_000 - .saturating_add((3_113_000 as Weight).saturating_mul(r as Weight)) + (74_285_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_997_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divu(r: u32, ) -> Weight { - (36_634_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_789_000 as Weight).saturating_mul(r as Weight)) + (74_002_000 as Weight) + // Standard Error: 1_000 + .saturating_add((2_027_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rems(r: u32, ) -> Weight { - (36_686_000 as Weight) - // Standard Error: 16_000 - .saturating_add((3_104_000 as Weight).saturating_mul(r as Weight)) + (74_281_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_977_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64remu(r: u32, ) -> Weight { - (36_447_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_836_000 as Weight).saturating_mul(r as Weight)) + (74_160_000 as Weight) + // Standard Error: 1_000 + .saturating_add((2_038_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64and(r: u32, ) -> Weight { - (36_587_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_481_000 as Weight).saturating_mul(r as Weight)) + (74_097_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_339_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64or(r: u32, ) -> Weight { - (36_889_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_471_000 as Weight).saturating_mul(r as Weight)) + (74_020_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_341_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64xor(r: u32, ) -> Weight { - (36_628_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_476_000 as Weight).saturating_mul(r as Weight)) + (73_890_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_351_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shl(r: u32, ) -> Weight { - (37_136_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_475_000 as Weight).saturating_mul(r as Weight)) + (74_139_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_355_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shrs(r: u32, ) -> Weight { - (32_543_000 as Weight) - // Standard Error: 25_000 - .saturating_add((2_751_000 as Weight).saturating_mul(r as Weight)) + (74_189_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_352_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shru(r: u32, ) -> Weight { - (36_378_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_499_000 as Weight).saturating_mul(r as Weight)) + (74_055_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_359_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotl(r: u32, ) -> Weight { - (36_563_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_483_000 as Weight).saturating_mul(r as Weight)) + (74_074_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_357_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotr(r: u32, ) -> Weight { - (36_625_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_477_000 as Weight).saturating_mul(r as Weight)) + (74_005_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_357_000 as Weight).saturating_mul(r as Weight)) } } @@ -1003,14 +1003,14 @@ impl WeightInfo for SubstrateWeight { impl WeightInfo for () { // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize() -> Weight { - (1_601_000 as Weight) + (1_642_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn on_initialize_per_trie_key(k: u32, ) -> Weight { - (10_543_000 as Weight) + (7_854_000 as Weight) // Standard Error: 0 - .saturating_add((739_000 as Weight).saturating_mul(k as Weight)) + .saturating_add((742_000 as Weight).saturating_mul(k as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) @@ -1018,17 +1018,17 @@ impl WeightInfo for () { // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize_per_queue_item(q: u32, ) -> Weight { (0 as Weight) - // Standard Error: 3_000 - .saturating_add((2_285_000 as Weight).saturating_mul(q as Weight)) + // Standard Error: 6_000 + .saturating_add((2_216_000 as Weight).saturating_mul(q as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Contracts PristineCode (r:1 w:0) // Storage: Contracts CodeStorage (r:0 w:1) fn reinstrument(c: u32, ) -> Weight { - (16_846_000 as Weight) - // Standard Error: 33_000 - .saturating_add((71_629_000 as Weight).saturating_mul(c as Weight)) + (17_413_000 as Weight) + // Standard Error: 39_000 + .saturating_add((64_495_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1037,9 +1037,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call_with_code_kb(c: u32, ) -> Weight { - (160_645_000 as Weight) - // Standard Error: 51_000 - .saturating_add((60_029_000 as Weight).saturating_mul(c as Weight)) + (209_071_000 as Weight) + // Standard Error: 47_000 + .saturating_add((56_555_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -1051,11 +1051,11 @@ impl WeightInfo for () { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn instantiate_with_code(c: u32, s: u32, ) -> Weight { - (160_721_000 as Weight) - // Standard Error: 200_000 - .saturating_add((156_185_000 as Weight).saturating_mul(c as Weight)) - // Standard Error: 13_000 - .saturating_add((1_785_000 as Weight).saturating_mul(s as Weight)) + (210_420_000 as Weight) + // Standard Error: 133_000 + .saturating_add((145_601_000 as Weight).saturating_mul(c as Weight)) + // Standard Error: 8_000 + .saturating_add((1_760_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } @@ -1066,9 +1066,9 @@ impl WeightInfo for () { // Storage: System Account (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn instantiate(s: u32, ) -> Weight { - (145_929_000 as Weight) + (173_397_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_743_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((1_714_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } @@ -1077,7 +1077,7 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call() -> Weight { - (114_204_000 as Weight) + (140_169_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -1085,9 +1085,9 @@ impl WeightInfo for () { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn upload_code(c: u32, ) -> Weight { - (51_131_000 as Weight) - // Standard Error: 48_000 - .saturating_add((70_405_000 as Weight).saturating_mul(c as Weight)) + (49_076_000 as Weight) + // Standard Error: 37_000 + .saturating_add((67_150_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -1095,7 +1095,7 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:0 w:1) // Storage: Contracts PristineCode (r:0 w:1) fn remove_code() -> Weight { - (24_452_000 as Weight) + (24_318_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -1104,9 +1104,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_caller(r: u32, ) -> Weight { - (168_803_000 as Weight) - // Standard Error: 119_000 - .saturating_add((56_278_000 as Weight).saturating_mul(r as Weight)) + (208_256_000 as Weight) + // Standard Error: 116_000 + .saturating_add((49_878_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1115,9 +1115,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_address(r: u32, ) -> Weight { - (170_921_000 as Weight) - // Standard Error: 150_000 - .saturating_add((56_973_000 as Weight).saturating_mul(r as Weight)) + (230_530_000 as Weight) + // Standard Error: 132_000 + .saturating_add((47_902_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1126,9 +1126,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas_left(r: u32, ) -> Weight { - (168_953_000 as Weight) - // Standard Error: 116_000 - .saturating_add((56_032_000 as Weight).saturating_mul(r as Weight)) + (219_027_000 as Weight) + // Standard Error: 108_000 + .saturating_add((48_039_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1137,9 +1137,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_balance(r: u32, ) -> Weight { - (170_043_000 as Weight) - // Standard Error: 147_000 - .saturating_add((152_039_000 as Weight).saturating_mul(r as Weight)) + (219_036_000 as Weight) + // Standard Error: 152_000 + .saturating_add((137_047_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1148,9 +1148,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_value_transferred(r: u32, ) -> Weight { - (183_371_000 as Weight) - // Standard Error: 111_000 - .saturating_add((54_799_000 as Weight).saturating_mul(r as Weight)) + (214_401_000 as Weight) + // Standard Error: 96_000 + .saturating_add((48_435_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1159,9 +1159,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_minimum_balance(r: u32, ) -> Weight { - (181_993_000 as Weight) - // Standard Error: 127_000 - .saturating_add((54_617_000 as Weight).saturating_mul(r as Weight)) + (216_939_000 as Weight) + // Standard Error: 106_000 + .saturating_add((48_198_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1170,9 +1170,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_block_number(r: u32, ) -> Weight { - (179_543_000 as Weight) - // Standard Error: 96_000 - .saturating_add((54_526_000 as Weight).saturating_mul(r as Weight)) + (216_637_000 as Weight) + // Standard Error: 86_000 + .saturating_add((47_819_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1181,9 +1181,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_now(r: u32, ) -> Weight { - (174_365_000 as Weight) - // Standard Error: 117_000 - .saturating_add((54_433_000 as Weight).saturating_mul(r as Weight)) + (214_863_000 as Weight) + // Standard Error: 110_000 + .saturating_add((48_208_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1193,9 +1193,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0) fn seal_weight_to_fee(r: u32, ) -> Weight { - (186_003_000 as Weight) - // Standard Error: 187_000 - .saturating_add((133_644_000 as Weight).saturating_mul(r as Weight)) + (216_494_000 as Weight) + // Standard Error: 141_000 + .saturating_add((120_736_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1204,9 +1204,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas(r: u32, ) -> Weight { - (91_771_000 as Weight) - // Standard Error: 68_000 - .saturating_add((28_003_000 as Weight).saturating_mul(r as Weight)) + (123_867_000 as Weight) + // Standard Error: 33_000 + .saturating_add((24_578_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1215,9 +1215,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input(r: u32, ) -> Weight { - (170_110_000 as Weight) - // Standard Error: 104_000 - .saturating_add((53_937_000 as Weight).saturating_mul(r as Weight)) + (215_578_000 as Weight) + // Standard Error: 108_000 + .saturating_add((47_512_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1226,9 +1226,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input_per_kb(n: u32, ) -> Weight { - (251_576_000 as Weight) - // Standard Error: 9_000 - .saturating_add((10_613_000 as Weight).saturating_mul(n as Weight)) + (297_663_000 as Weight) + // Standard Error: 3_000 + .saturating_add((11_863_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1237,9 +1237,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return(r: u32, ) -> Weight { - (176_897_000 as Weight) - // Standard Error: 119_000 - .saturating_add((3_095_000 as Weight).saturating_mul(r as Weight)) + (209_709_000 as Weight) + // Standard Error: 75_000 + .saturating_add((1_783_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1248,9 +1248,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return_per_kb(n: u32, ) -> Weight { - (161_820_000 as Weight) + (214_403_000 as Weight) // Standard Error: 0 - .saturating_add((184_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((197_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1261,9 +1261,9 @@ impl WeightInfo for () { // Storage: Contracts DeletionQueue (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_terminate(r: u32, ) -> Weight { - (163_213_000 as Weight) - // Standard Error: 922_000 - .saturating_add((65_249_000 as Weight).saturating_mul(r as Weight)) + (214_454_000 as Weight) + // Standard Error: 656_000 + .saturating_add((50_641_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((4 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1275,9 +1275,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) fn seal_random(r: u32, ) -> Weight { - (178_636_000 as Weight) - // Standard Error: 189_000 - .saturating_add((166_008_000 as Weight).saturating_mul(r as Weight)) + (214_140_000 as Weight) + // Standard Error: 169_000 + .saturating_add((158_778_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1286,9 +1286,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_deposit_event(r: u32, ) -> Weight { - (187_377_000 as Weight) - // Standard Error: 186_000 - .saturating_add((289_005_000 as Weight).saturating_mul(r as Weight)) + (225_998_000 as Weight) + // Standard Error: 171_000 + .saturating_add((280_296_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1298,11 +1298,11 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: System EventTopics (r:100 w:100) fn seal_deposit_event_per_topic_and_kb(t: u32, n: u32, ) -> Weight { - (487_726_000 as Weight) - // Standard Error: 1_980_000 - .saturating_add((291_760_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 390_000 - .saturating_add((78_950_000 as Weight).saturating_mul(n as Weight)) + (491_432_000 as Weight) + // Standard Error: 1_992_000 + .saturating_add((288_376_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 392_000 + .saturating_add((82_805_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(t as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1313,17 +1313,17 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_debug_message(r: u32, ) -> Weight { - (105_118_000 as Weight) - // Standard Error: 80_000 - .saturating_add((45_277_000 as Weight).saturating_mul(r as Weight)) + (130_861_000 as Weight) + // Standard Error: 74_000 + .saturating_add((40_268_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage(r: u32, ) -> Weight { - (0 as Weight) - // Standard Error: 1_084_000 - .saturating_add((423_125_000 as Weight).saturating_mul(r as Weight)) + (38_843_000 as Weight) + // Standard Error: 1_044_000 + .saturating_add((408_027_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1331,25 +1331,25 @@ impl WeightInfo for () { } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage_per_new_kb(n: u32, ) -> Weight { - (565_293_000 as Weight) - // Standard Error: 257_000 - .saturating_add((26_134_000 as Weight).saturating_mul(n as Weight)) + (610_782_000 as Weight) + // Standard Error: 265_000 + .saturating_add((28_221_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage_per_old_kb(n: u32, ) -> Weight { - (582_851_000 as Weight) - // Standard Error: 306_000 - .saturating_add((11_991_000 as Weight).saturating_mul(n as Weight)) + (625_031_000 as Weight) + // Standard Error: 319_000 + .saturating_add((11_126_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage(r: u32, ) -> Weight { - (51_270_000 as Weight) - // Standard Error: 883_000 - .saturating_add((394_518_000 as Weight).saturating_mul(r as Weight)) + (78_566_000 as Weight) + // Standard Error: 970_000 + .saturating_add((384_877_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -1357,51 +1357,51 @@ impl WeightInfo for () { } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage_per_kb(n: u32, ) -> Weight { - (585_361_000 as Weight) - // Standard Error: 263_000 - .saturating_add((10_855_000 as Weight).saturating_mul(n as Weight)) + (601_558_000 as Weight) + // Standard Error: 280_000 + .saturating_add((11_378_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage(r: u32, ) -> Weight { - (60_404_000 as Weight) - // Standard Error: 667_000 - .saturating_add((335_130_000 as Weight).saturating_mul(r as Weight)) + (112_328_000 as Weight) + // Standard Error: 668_000 + .saturating_add((323_031_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage_per_kb(n: u32, ) -> Weight { - (539_500_000 as Weight) - // Standard Error: 378_000 - .saturating_add((62_855_000 as Weight).saturating_mul(n as Weight)) + (556_303_000 as Weight) + // Standard Error: 346_000 + .saturating_add((64_170_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(104 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_contains_storage(r: u32, ) -> Weight { - (58_301_000 as Weight) - // Standard Error: 701_000 - .saturating_add((301_511_000 as Weight).saturating_mul(r as Weight)) + (106_572_000 as Weight) + // Standard Error: 691_000 + .saturating_add((294_964_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_contains_storage_per_kb(n: u32, ) -> Weight { - (485_967_000 as Weight) - // Standard Error: 266_000 - .saturating_add((10_314_000 as Weight).saturating_mul(n as Weight)) + (508_339_000 as Weight) + // Standard Error: 245_000 + .saturating_add((10_675_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(104 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage(r: u32, ) -> Weight { - (42_688_000 as Weight) - // Standard Error: 889_000 - .saturating_add((436_932_000 as Weight).saturating_mul(r as Weight)) + (88_096_000 as Weight) + // Standard Error: 927_000 + .saturating_add((415_543_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -1409,9 +1409,9 @@ impl WeightInfo for () { } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage_per_kb(n: u32, ) -> Weight { - (638_201_000 as Weight) - // Standard Error: 373_000 - .saturating_add((64_277_000 as Weight).saturating_mul(n as Weight)) + (650_912_000 as Weight) + // Standard Error: 359_000 + .saturating_add((65_030_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().writes(103 as Weight)) } @@ -1420,9 +1420,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_transfer(r: u32, ) -> Weight { - (49_486_000 as Weight) - // Standard Error: 1_275_000 - .saturating_add((1_790_231_000 as Weight).saturating_mul(r as Weight)) + (102_673_000 as Weight) + // Standard Error: 1_159_000 + .saturating_add((1_711_312_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) @@ -1433,9 +1433,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_call(r: u32, ) -> Weight { - (2_498_893_000 as Weight) - // Standard Error: 20_838_000 - .saturating_add((14_474_373_000 as Weight).saturating_mul(r as Weight)) + (0 as Weight) + // Standard Error: 3_592_000 + .saturating_add((19_565_726_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1446,13 +1446,13 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:2 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_call_per_transfer_input_output_kb(t: u32, i: u32, o: u32, ) -> Weight { - (16_423_215_000 as Weight) - // Standard Error: 43_595_000 - .saturating_add((1_644_304_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 15_000 - .saturating_add((17_700_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 16_000 - .saturating_add((28_564_000 as Weight).saturating_mul(o as Weight)) + (19_665_171_000 as Weight) + // Standard Error: 27_641_000 + .saturating_add((2_089_637_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 9_000 + .saturating_add((20_165_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 10_000 + .saturating_add((31_728_000 as Weight).saturating_mul(o as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().reads((101 as Weight).saturating_mul(t as Weight))) .saturating_add(RocksDbWeight::get().writes(101 as Weight)) @@ -1466,8 +1466,8 @@ impl WeightInfo for () { // Storage: Contracts OwnerInfoOf (r:100 w:100) fn seal_instantiate(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 52_924_000 - .saturating_add((24_062_215_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 48_640_000 + .saturating_add((27_307_450_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().reads((400 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -1480,13 +1480,13 @@ impl WeightInfo for () { // Storage: Contracts AccountCounter (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_instantiate_per_input_output_salt_kb(i: u32, o: u32, s: u32, ) -> Weight { - (19_940_217_000 as Weight) - // Standard Error: 36_000 - .saturating_add((17_853_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 36_000 - .saturating_add((29_592_000 as Weight).saturating_mul(o as Weight)) - // Standard Error: 36_000 - .saturating_add((155_914_000 as Weight).saturating_mul(s as Weight)) + (24_821_248_000 as Weight) + // Standard Error: 26_000 + .saturating_add((20_118_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 26_000 + .saturating_add((31_616_000 as Weight).saturating_mul(o as Weight)) + // Standard Error: 26_000 + .saturating_add((157_567_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(208 as Weight)) .saturating_add(RocksDbWeight::get().writes(206 as Weight)) } @@ -1495,9 +1495,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256(r: u32, ) -> Weight { - (166_372_000 as Weight) - // Standard Error: 150_000 - .saturating_add((85_445_000 as Weight).saturating_mul(r as Weight)) + (213_816_000 as Weight) + // Standard Error: 147_000 + .saturating_add((80_336_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1506,9 +1506,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256_per_kb(n: u32, ) -> Weight { - (323_005_000 as Weight) - // Standard Error: 28_000 - .saturating_add((464_801_000 as Weight).saturating_mul(n as Weight)) + (309_038_000 as Weight) + // Standard Error: 23_000 + .saturating_add((465_306_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1517,9 +1517,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256(r: u32, ) -> Weight { - (167_869_000 as Weight) - // Standard Error: 156_000 - .saturating_add((96_037_000 as Weight).saturating_mul(r as Weight)) + (212_825_000 as Weight) + // Standard Error: 143_000 + .saturating_add((91_947_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1528,9 +1528,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256_per_kb(n: u32, ) -> Weight { - (235_448_000 as Weight) - // Standard Error: 30_000 - .saturating_add((306_489_000 as Weight).saturating_mul(n as Weight)) + (329_548_000 as Weight) + // Standard Error: 19_000 + .saturating_add((306_729_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1539,9 +1539,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256(r: u32, ) -> Weight { - (166_113_000 as Weight) - // Standard Error: 128_000 - .saturating_add((68_810_000 as Weight).saturating_mul(r as Weight)) + (215_907_000 as Weight) + // Standard Error: 129_000 + .saturating_add((63_477_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1550,9 +1550,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256_per_kb(n: u32, ) -> Weight { - (276_885_000 as Weight) + (423_811_000 as Weight) // Standard Error: 16_000 - .saturating_add((120_098_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((119_607_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1561,9 +1561,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128(r: u32, ) -> Weight { - (168_106_000 as Weight) - // Standard Error: 131_000 - .saturating_add((68_109_000 as Weight).saturating_mul(r as Weight)) + (214_747_000 as Weight) + // Standard Error: 115_000 + .saturating_add((62_904_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1572,9 +1572,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128_per_kb(n: u32, ) -> Weight { - (244_443_000 as Weight) + (437_217_000 as Weight) // Standard Error: 19_000 - .saturating_add((120_286_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((120_126_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1583,265 +1583,265 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_ecdsa_recover(r: u32, ) -> Weight { - (207_765_000 as Weight) - // Standard Error: 1_529_000 - .saturating_add((15_403_795_000 as Weight).saturating_mul(r as Weight)) + (195_980_000 as Weight) + // Standard Error: 1_262_000 + .saturating_add((15_428_805_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn instr_i64const(r: u32, ) -> Weight { - (46_110_000 as Weight) - // Standard Error: 11_000 - .saturating_add((813_000 as Weight).saturating_mul(r as Weight)) + (74_569_000 as Weight) + // Standard Error: 1_000 + .saturating_add((589_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64load(r: u32, ) -> Weight { - (52_944_000 as Weight) - // Standard Error: 12_000 - .saturating_add((2_501_000 as Weight).saturating_mul(r as Weight)) + (74_212_000 as Weight) + // Standard Error: 0 + .saturating_add((1_325_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64store(r: u32, ) -> Weight { - (52_968_000 as Weight) - // Standard Error: 12_000 - .saturating_add((2_528_000 as Weight).saturating_mul(r as Weight)) + (74_505_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_423_000 as Weight).saturating_mul(r as Weight)) } fn instr_select(r: u32, ) -> Weight { - (36_871_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_994_000 as Weight).saturating_mul(r as Weight)) + (74_005_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_785_000 as Weight).saturating_mul(r as Weight)) } fn instr_if(r: u32, ) -> Weight { - (36_834_000 as Weight) - // Standard Error: 16_000 - .saturating_add((3_060_000 as Weight).saturating_mul(r as Weight)) + (74_212_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_890_000 as Weight).saturating_mul(r as Weight)) } fn instr_br(r: u32, ) -> Weight { - (39_250_000 as Weight) - // Standard Error: 16_000 - .saturating_add((1_933_000 as Weight).saturating_mul(r as Weight)) + (74_102_000 as Weight) + // Standard Error: 2_000 + .saturating_add((896_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_if(r: u32, ) -> Weight { - (38_302_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_496_000 as Weight).saturating_mul(r as Weight)) + (73_523_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_456_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table(r: u32, ) -> Weight { - (44_800_000 as Weight) - // Standard Error: 21_000 - .saturating_add((2_407_000 as Weight).saturating_mul(r as Weight)) + (73_307_000 as Weight) + // Standard Error: 4_000 + .saturating_add((1_594_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table_per_entry(e: u32, ) -> Weight { - (46_996_000 as Weight) - // Standard Error: 3_000 - .saturating_add((27_000 as Weight).saturating_mul(e as Weight)) + (76_272_000 as Weight) + // Standard Error: 0 + .saturating_add((5_000 as Weight).saturating_mul(e as Weight)) } fn instr_call(r: u32, ) -> Weight { - (48_704_000 as Weight) - // Standard Error: 24_000 - .saturating_add((20_212_000 as Weight).saturating_mul(r as Weight)) + (73_390_000 as Weight) + // Standard Error: 23_000 + .saturating_add((16_936_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect(r: u32, ) -> Weight { - (52_546_000 as Weight) - // Standard Error: 32_000 - .saturating_add((29_995_000 as Weight).saturating_mul(r as Weight)) + (89_331_000 as Weight) + // Standard Error: 30_000 + .saturating_add((28_104_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect_per_param(p: u32, ) -> Weight { - (85_521_000 as Weight) - // Standard Error: 5_000 - .saturating_add((1_117_000 as Weight).saturating_mul(p as Weight)) + (117_023_000 as Weight) + // Standard Error: 3_000 + .saturating_add((914_000 as Weight).saturating_mul(p as Weight)) } fn instr_local_get(r: u32, ) -> Weight { - (39_081_000 as Weight) - // Standard Error: 14_000 - .saturating_add((1_338_000 as Weight).saturating_mul(r as Weight)) + (74_727_000 as Weight) + // Standard Error: 1_000 + .saturating_add((618_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_set(r: u32, ) -> Weight { - (39_014_000 as Weight) - // Standard Error: 14_000 - .saturating_add((1_365_000 as Weight).saturating_mul(r as Weight)) + (74_893_000 as Weight) + // Standard Error: 1_000 + .saturating_add((674_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_tee(r: u32, ) -> Weight { - (41_269_000 as Weight) - // Standard Error: 12_000 - .saturating_add((1_879_000 as Weight).saturating_mul(r as Weight)) + (74_552_000 as Weight) + // Standard Error: 1_000 + .saturating_add((898_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_get(r: u32, ) -> Weight { - (40_341_000 as Weight) - // Standard Error: 12_000 - .saturating_add((1_944_000 as Weight).saturating_mul(r as Weight)) + (77_355_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_146_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_set(r: u32, ) -> Weight { - (45_833_000 as Weight) - // Standard Error: 12_000 - .saturating_add((1_757_000 as Weight).saturating_mul(r as Weight)) + (77_055_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_363_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_current(r: u32, ) -> Weight { - (46_780_000 as Weight) - // Standard Error: 12_000 - .saturating_add((806_000 as Weight).saturating_mul(r as Weight)) + (74_648_000 as Weight) + // Standard Error: 2_000 + .saturating_add((652_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_grow(r: u32, ) -> Weight { - (49_585_000 as Weight) - // Standard Error: 1_723_000 - .saturating_add((166_106_000 as Weight).saturating_mul(r as Weight)) + (73_777_000 as Weight) + // Standard Error: 226_000 + .saturating_add((187_252_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64clz(r: u32, ) -> Weight { - (43_423_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_494_000 as Weight).saturating_mul(r as Weight)) + (74_332_000 as Weight) + // Standard Error: 1_000 + .saturating_add((897_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ctz(r: u32, ) -> Weight { - (43_237_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_499_000 as Weight).saturating_mul(r as Weight)) + (74_265_000 as Weight) + // Standard Error: 1_000 + .saturating_add((898_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64popcnt(r: u32, ) -> Weight { - (43_308_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_505_000 as Weight).saturating_mul(r as Weight)) + (74_475_000 as Weight) + // Standard Error: 2_000 + .saturating_add((892_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eqz(r: u32, ) -> Weight { - (43_440_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_503_000 as Weight).saturating_mul(r as Weight)) + (74_297_000 as Weight) + // Standard Error: 1_000 + .saturating_add((918_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendsi32(r: u32, ) -> Weight { - (40_782_000 as Weight) - // Standard Error: 13_000 - .saturating_add((1_948_000 as Weight).saturating_mul(r as Weight)) + (74_146_000 as Weight) + // Standard Error: 1_000 + .saturating_add((884_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendui32(r: u32, ) -> Weight { - (41_210_000 as Weight) - // Standard Error: 12_000 - .saturating_add((1_925_000 as Weight).saturating_mul(r as Weight)) + (74_361_000 as Weight) + // Standard Error: 1_000 + .saturating_add((877_000 as Weight).saturating_mul(r as Weight)) } fn instr_i32wrapi64(r: u32, ) -> Weight { - (43_108_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_506_000 as Weight).saturating_mul(r as Weight)) + (74_554_000 as Weight) + // Standard Error: 1_000 + .saturating_add((884_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eq(r: u32, ) -> Weight { - (36_501_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_490_000 as Weight).saturating_mul(r as Weight)) + (74_169_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_357_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ne(r: u32, ) -> Weight { - (36_289_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_494_000 as Weight).saturating_mul(r as Weight)) + (74_164_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_357_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64lts(r: u32, ) -> Weight { - (36_414_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_492_000 as Weight).saturating_mul(r as Weight)) + (74_058_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_362_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ltu(r: u32, ) -> Weight { - (36_205_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_498_000 as Weight).saturating_mul(r as Weight)) + (74_039_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_362_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gts(r: u32, ) -> Weight { - (36_648_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_473_000 as Weight).saturating_mul(r as Weight)) + (75_055_000 as Weight) + // Standard Error: 4_000 + .saturating_add((1_338_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gtu(r: u32, ) -> Weight { - (36_530_000 as Weight) - // Standard Error: 18_000 - .saturating_add((2_488_000 as Weight).saturating_mul(r as Weight)) + (74_536_000 as Weight) + // Standard Error: 4_000 + .saturating_add((1_367_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64les(r: u32, ) -> Weight { - (36_622_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_483_000 as Weight).saturating_mul(r as Weight)) + (74_177_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_358_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64leu(r: u32, ) -> Weight { - (36_465_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_490_000 as Weight).saturating_mul(r as Weight)) + (74_080_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_370_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ges(r: u32, ) -> Weight { - (36_291_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_494_000 as Weight).saturating_mul(r as Weight)) + (74_237_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_356_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64geu(r: u32, ) -> Weight { - (36_454_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_483_000 as Weight).saturating_mul(r as Weight)) + (74_049_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_362_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64add(r: u32, ) -> Weight { - (36_801_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_468_000 as Weight).saturating_mul(r as Weight)) + (74_186_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_335_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64sub(r: u32, ) -> Weight { - (36_670_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_483_000 as Weight).saturating_mul(r as Weight)) + (74_268_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_339_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64mul(r: u32, ) -> Weight { - (36_388_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_494_000 as Weight).saturating_mul(r as Weight)) + (74_334_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_331_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divs(r: u32, ) -> Weight { - (36_952_000 as Weight) - // Standard Error: 16_000 - .saturating_add((3_113_000 as Weight).saturating_mul(r as Weight)) + (74_285_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_997_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divu(r: u32, ) -> Weight { - (36_634_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_789_000 as Weight).saturating_mul(r as Weight)) + (74_002_000 as Weight) + // Standard Error: 1_000 + .saturating_add((2_027_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rems(r: u32, ) -> Weight { - (36_686_000 as Weight) - // Standard Error: 16_000 - .saturating_add((3_104_000 as Weight).saturating_mul(r as Weight)) + (74_281_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_977_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64remu(r: u32, ) -> Weight { - (36_447_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_836_000 as Weight).saturating_mul(r as Weight)) + (74_160_000 as Weight) + // Standard Error: 1_000 + .saturating_add((2_038_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64and(r: u32, ) -> Weight { - (36_587_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_481_000 as Weight).saturating_mul(r as Weight)) + (74_097_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_339_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64or(r: u32, ) -> Weight { - (36_889_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_471_000 as Weight).saturating_mul(r as Weight)) + (74_020_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_341_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64xor(r: u32, ) -> Weight { - (36_628_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_476_000 as Weight).saturating_mul(r as Weight)) + (73_890_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_351_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shl(r: u32, ) -> Weight { - (37_136_000 as Weight) - // Standard Error: 17_000 - .saturating_add((2_475_000 as Weight).saturating_mul(r as Weight)) + (74_139_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_355_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shrs(r: u32, ) -> Weight { - (32_543_000 as Weight) - // Standard Error: 25_000 - .saturating_add((2_751_000 as Weight).saturating_mul(r as Weight)) + (74_189_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_352_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shru(r: u32, ) -> Weight { - (36_378_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_499_000 as Weight).saturating_mul(r as Weight)) + (74_055_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_359_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotl(r: u32, ) -> Weight { - (36_563_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_483_000 as Weight).saturating_mul(r as Weight)) + (74_074_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_357_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotr(r: u32, ) -> Weight { - (36_625_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_477_000 as Weight).saturating_mul(r as Weight)) + (74_005_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_357_000 as Weight).saturating_mul(r as Weight)) } } diff --git a/frame/democracy/src/weights.rs b/frame/democracy/src/weights.rs index 22743124253b..19bf602c5d29 100644 --- a/frame/democracy/src/weights.rs +++ b/frame/democracy/src/weights.rs @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_democracy //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-17, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-01-30, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/lto-fat-cg1/substrate +// ./target/production/substrate // benchmark // --chain=dev // --steps=50 @@ -34,7 +34,7 @@ // --heap-pages=4096 // --output=./frame/democracy/src/weights.rs // --template=.maintain/frame-weight-template.hbs -// --header=LICENSE-APACHE2 +// --header=HEADER-APACHE2 // --raw #![cfg_attr(rustfmt, rustfmt_skip)] @@ -82,15 +82,15 @@ impl WeightInfo for SubstrateWeight { // Storage: Democracy Blacklist (r:1 w:0) // Storage: Democracy DepositOf (r:0 w:1) fn propose() -> Weight { - (42_599_000 as Weight) + (42_560_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Democracy DepositOf (r:1 w:1) fn second(s: u32, ) -> Weight { - (25_521_000 as Weight) + (25_603_000 as Weight) // Standard Error: 1_000 - .saturating_add((171_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((167_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -98,9 +98,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Democracy VotingOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_new(r: u32, ) -> Weight { - (34_035_000 as Weight) - // Standard Error: 1_000 - .saturating_add((142_000 as Weight).saturating_mul(r as Weight)) + (34_248_000 as Weight) + // Standard Error: 2_000 + .saturating_add((135_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -108,16 +108,16 @@ impl WeightInfo for SubstrateWeight { // Storage: Democracy VotingOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_existing(r: u32, ) -> Weight { - (33_910_000 as Weight) - // Standard Error: 1_000 - .saturating_add((147_000 as Weight).saturating_mul(r as Weight)) + (33_927_000 as Weight) + // Standard Error: 2_000 + .saturating_add((138_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy Cancellations (r:1 w:1) fn emergency_cancel() -> Weight { - (14_874_000 as Weight) + (14_714_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -128,45 +128,45 @@ impl WeightInfo for SubstrateWeight { // Storage: Democracy DepositOf (r:1 w:1) // Storage: System Account (r:1 w:1) fn blacklist(p: u32, ) -> Weight { - (49_557_000 as Weight) + (49_423_000 as Weight) // Standard Error: 3_000 - .saturating_add((267_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((275_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy Blacklist (r:1 w:0) fn external_propose(v: u32, ) -> Weight { - (7_540_000 as Weight) + (7_321_000 as Weight) // Standard Error: 0 - .saturating_add((76_000 as Weight).saturating_mul(v as Weight)) + .saturating_add((75_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Democracy NextExternal (r:0 w:1) fn external_propose_majority() -> Weight { - (1_272_000 as Weight) + (1_325_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Democracy NextExternal (r:0 w:1) fn external_propose_default() -> Weight { - (1_274_000 as Weight) + (1_283_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy ReferendumCount (r:1 w:1) // Storage: Democracy ReferendumInfoOf (r:0 w:1) fn fast_track() -> Weight { - (15_216_000 as Weight) + (15_355_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy Blacklist (r:1 w:1) fn veto_external(v: u32, ) -> Weight { - (16_713_000 as Weight) + (16_597_000 as Weight) // Standard Error: 0 - .saturating_add((92_000 as Weight).saturating_mul(v as Weight)) + .saturating_add((90_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -174,23 +174,23 @@ impl WeightInfo for SubstrateWeight { // Storage: Democracy DepositOf (r:1 w:1) // Storage: System Account (r:1 w:1) fn cancel_proposal(p: u32, ) -> Weight { - (37_990_000 as Weight) + (37_695_000 as Weight) // Standard Error: 2_000 - .saturating_add((259_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((258_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Democracy ReferendumInfoOf (r:0 w:1) fn cancel_referendum() -> Weight { - (9_756_000 as Weight) + (9_456_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Scheduler Lookup (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) fn cancel_queued(r: u32, ) -> Weight { - (19_408_000 as Weight) + (19_915_000 as Weight) // Standard Error: 1_000 - .saturating_add((650_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((609_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -198,9 +198,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Democracy ReferendumCount (r:1 w:0) // Storage: Democracy ReferendumInfoOf (r:1 w:0) fn on_initialize_base(r: u32, ) -> Weight { - (2_134_000 as Weight) - // Standard Error: 3_000 - .saturating_add((3_041_000 as Weight).saturating_mul(r as Weight)) + (3_787_000 as Weight) + // Standard Error: 2_000 + .saturating_add((2_852_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -212,9 +212,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Democracy PublicProps (r:1 w:0) // Storage: Democracy ReferendumInfoOf (r:1 w:0) fn on_initialize_base_with_launch_period(r: u32, ) -> Weight { - (6_357_000 as Weight) - // Standard Error: 3_000 - .saturating_add((3_054_000 as Weight).saturating_mul(r as Weight)) + (7_890_000 as Weight) + // Standard Error: 2_000 + .saturating_add((2_856_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -223,9 +223,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn delegate(r: u32, ) -> Weight { - (30_822_000 as Weight) + (31_190_000 as Weight) // Standard Error: 3_000 - .saturating_add((3_826_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((3_753_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(4 as Weight)) @@ -234,9 +234,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Democracy VotingOf (r:2 w:2) // Storage: Democracy ReferendumInfoOf (r:1 w:1) fn undelegate(r: u32, ) -> Weight { - (15_307_000 as Weight) + (15_121_000 as Weight) // Standard Error: 3_000 - .saturating_add((3_827_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((3_852_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -244,12 +244,12 @@ impl WeightInfo for SubstrateWeight { } // Storage: Democracy PublicProps (r:0 w:1) fn clear_public_proposals() -> Weight { - (1_624_000 as Weight) + (1_583_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Democracy Preimages (r:1 w:1) fn note_preimage(b: u32, ) -> Weight { - (22_731_000 as Weight) + (22_681_000 as Weight) // Standard Error: 0 .saturating_add((2_000 as Weight).saturating_mul(b as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) @@ -257,7 +257,7 @@ impl WeightInfo for SubstrateWeight { } // Storage: Democracy Preimages (r:1 w:1) fn note_imminent_preimage(b: u32, ) -> Weight { - (15_518_000 as Weight) + (15_599_000 as Weight) // Standard Error: 0 .saturating_add((2_000 as Weight).saturating_mul(b as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) @@ -266,7 +266,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Democracy Preimages (r:1 w:1) // Storage: System Account (r:1 w:0) fn reap_preimage(b: u32, ) -> Weight { - (23_749_000 as Weight) + (23_663_000 as Weight) // Standard Error: 0 .saturating_add((1_000 as Weight).saturating_mul(b as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) @@ -276,9 +276,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn unlock_remove(r: u32, ) -> Weight { - (21_818_000 as Weight) + (21_928_000 as Weight) // Standard Error: 1_000 - .saturating_add((66_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((61_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -286,27 +286,27 @@ impl WeightInfo for SubstrateWeight { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn unlock_set(r: u32, ) -> Weight { - (21_491_000 as Weight) + (21_548_000 as Weight) // Standard Error: 1_000 - .saturating_add((121_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((123_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy VotingOf (r:1 w:1) fn remove_vote(r: u32, ) -> Weight { - (11_767_000 as Weight) + (11_797_000 as Weight) // Standard Error: 1_000 - .saturating_add((115_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((117_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy VotingOf (r:1 w:1) fn remove_other_vote(r: u32, ) -> Weight { - (11_959_000 as Weight) + (11_930_000 as Weight) // Standard Error: 1_000 - .saturating_add((111_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((122_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -319,15 +319,15 @@ impl WeightInfo for () { // Storage: Democracy Blacklist (r:1 w:0) // Storage: Democracy DepositOf (r:0 w:1) fn propose() -> Weight { - (42_599_000 as Weight) + (42_560_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } // Storage: Democracy DepositOf (r:1 w:1) fn second(s: u32, ) -> Weight { - (25_521_000 as Weight) + (25_603_000 as Weight) // Standard Error: 1_000 - .saturating_add((171_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((167_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -335,9 +335,9 @@ impl WeightInfo for () { // Storage: Democracy VotingOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_new(r: u32, ) -> Weight { - (34_035_000 as Weight) - // Standard Error: 1_000 - .saturating_add((142_000 as Weight).saturating_mul(r as Weight)) + (34_248_000 as Weight) + // Standard Error: 2_000 + .saturating_add((135_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -345,16 +345,16 @@ impl WeightInfo for () { // Storage: Democracy VotingOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_existing(r: u32, ) -> Weight { - (33_910_000 as Weight) - // Standard Error: 1_000 - .saturating_add((147_000 as Weight).saturating_mul(r as Weight)) + (33_927_000 as Weight) + // Standard Error: 2_000 + .saturating_add((138_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy Cancellations (r:1 w:1) fn emergency_cancel() -> Weight { - (14_874_000 as Weight) + (14_714_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -365,45 +365,45 @@ impl WeightInfo for () { // Storage: Democracy DepositOf (r:1 w:1) // Storage: System Account (r:1 w:1) fn blacklist(p: u32, ) -> Weight { - (49_557_000 as Weight) + (49_423_000 as Weight) // Standard Error: 3_000 - .saturating_add((267_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((275_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy Blacklist (r:1 w:0) fn external_propose(v: u32, ) -> Weight { - (7_540_000 as Weight) + (7_321_000 as Weight) // Standard Error: 0 - .saturating_add((76_000 as Weight).saturating_mul(v as Weight)) + .saturating_add((75_000 as Weight).saturating_mul(v as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Democracy NextExternal (r:0 w:1) fn external_propose_majority() -> Weight { - (1_272_000 as Weight) + (1_325_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Democracy NextExternal (r:0 w:1) fn external_propose_default() -> Weight { - (1_274_000 as Weight) + (1_283_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy ReferendumCount (r:1 w:1) // Storage: Democracy ReferendumInfoOf (r:0 w:1) fn fast_track() -> Weight { - (15_216_000 as Weight) + (15_355_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy Blacklist (r:1 w:1) fn veto_external(v: u32, ) -> Weight { - (16_713_000 as Weight) + (16_597_000 as Weight) // Standard Error: 0 - .saturating_add((92_000 as Weight).saturating_mul(v as Weight)) + .saturating_add((90_000 as Weight).saturating_mul(v as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -411,23 +411,23 @@ impl WeightInfo for () { // Storage: Democracy DepositOf (r:1 w:1) // Storage: System Account (r:1 w:1) fn cancel_proposal(p: u32, ) -> Weight { - (37_990_000 as Weight) + (37_695_000 as Weight) // Standard Error: 2_000 - .saturating_add((259_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((258_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } // Storage: Democracy ReferendumInfoOf (r:0 w:1) fn cancel_referendum() -> Weight { - (9_756_000 as Weight) + (9_456_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Scheduler Lookup (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) fn cancel_queued(r: u32, ) -> Weight { - (19_408_000 as Weight) + (19_915_000 as Weight) // Standard Error: 1_000 - .saturating_add((650_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((609_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -435,9 +435,9 @@ impl WeightInfo for () { // Storage: Democracy ReferendumCount (r:1 w:0) // Storage: Democracy ReferendumInfoOf (r:1 w:0) fn on_initialize_base(r: u32, ) -> Weight { - (2_134_000 as Weight) - // Standard Error: 3_000 - .saturating_add((3_041_000 as Weight).saturating_mul(r as Weight)) + (3_787_000 as Weight) + // Standard Error: 2_000 + .saturating_add((2_852_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -449,9 +449,9 @@ impl WeightInfo for () { // Storage: Democracy PublicProps (r:1 w:0) // Storage: Democracy ReferendumInfoOf (r:1 w:0) fn on_initialize_base_with_launch_period(r: u32, ) -> Weight { - (6_357_000 as Weight) - // Standard Error: 3_000 - .saturating_add((3_054_000 as Weight).saturating_mul(r as Weight)) + (7_890_000 as Weight) + // Standard Error: 2_000 + .saturating_add((2_856_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -460,9 +460,9 @@ impl WeightInfo for () { // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn delegate(r: u32, ) -> Weight { - (30_822_000 as Weight) + (31_190_000 as Weight) // Standard Error: 3_000 - .saturating_add((3_826_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((3_753_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) @@ -471,9 +471,9 @@ impl WeightInfo for () { // Storage: Democracy VotingOf (r:2 w:2) // Storage: Democracy ReferendumInfoOf (r:1 w:1) fn undelegate(r: u32, ) -> Weight { - (15_307_000 as Weight) + (15_121_000 as Weight) // Standard Error: 3_000 - .saturating_add((3_827_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((3_852_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) @@ -481,12 +481,12 @@ impl WeightInfo for () { } // Storage: Democracy PublicProps (r:0 w:1) fn clear_public_proposals() -> Weight { - (1_624_000 as Weight) + (1_583_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Democracy Preimages (r:1 w:1) fn note_preimage(b: u32, ) -> Weight { - (22_731_000 as Weight) + (22_681_000 as Weight) // Standard Error: 0 .saturating_add((2_000 as Weight).saturating_mul(b as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) @@ -494,7 +494,7 @@ impl WeightInfo for () { } // Storage: Democracy Preimages (r:1 w:1) fn note_imminent_preimage(b: u32, ) -> Weight { - (15_518_000 as Weight) + (15_599_000 as Weight) // Standard Error: 0 .saturating_add((2_000 as Weight).saturating_mul(b as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) @@ -503,7 +503,7 @@ impl WeightInfo for () { // Storage: Democracy Preimages (r:1 w:1) // Storage: System Account (r:1 w:0) fn reap_preimage(b: u32, ) -> Weight { - (23_749_000 as Weight) + (23_663_000 as Weight) // Standard Error: 0 .saturating_add((1_000 as Weight).saturating_mul(b as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) @@ -513,9 +513,9 @@ impl WeightInfo for () { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn unlock_remove(r: u32, ) -> Weight { - (21_818_000 as Weight) + (21_928_000 as Weight) // Standard Error: 1_000 - .saturating_add((66_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((61_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -523,27 +523,27 @@ impl WeightInfo for () { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn unlock_set(r: u32, ) -> Weight { - (21_491_000 as Weight) + (21_548_000 as Weight) // Standard Error: 1_000 - .saturating_add((121_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((123_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy VotingOf (r:1 w:1) fn remove_vote(r: u32, ) -> Weight { - (11_767_000 as Weight) + (11_797_000 as Weight) // Standard Error: 1_000 - .saturating_add((115_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((117_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy VotingOf (r:1 w:1) fn remove_other_vote(r: u32, ) -> Weight { - (11_959_000 as Weight) + (11_930_000 as Weight) // Standard Error: 1_000 - .saturating_add((111_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((122_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } diff --git a/frame/election-provider-multi-phase/src/weights.rs b/frame/election-provider-multi-phase/src/weights.rs index 8e627b246d37..99e149eff241 100644 --- a/frame/election-provider-multi-phase/src/weights.rs +++ b/frame/election-provider-multi-phase/src/weights.rs @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_election_provider_multi_phase //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-19, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-01-30, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/optimized/substrate +// ./target/production/substrate // benchmark // --chain=dev // --steps=50 @@ -32,7 +32,7 @@ // --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./weights-optimized/frame/election-provider-multi-phase/src//weights.rs +// --output=./frame/election-provider-multi-phase/src/weights.rs // --template=.maintain/frame-weight-template.hbs // --header=HEADER-APACHE2 // --raw @@ -70,33 +70,33 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking ForceEra (r:1 w:0) // Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) fn on_initialize_nothing() -> Weight { - (12_360_000 as Weight) + (12_763_000 as Weight) .saturating_add(T::DbWeight::get().reads(8 as Weight)) } // Storage: ElectionProviderMultiPhase Round (r:1 w:0) // Storage: ElectionProviderMultiPhase CurrentPhase (r:0 w:1) fn on_initialize_open_signed() -> Weight { - (12_981_000 as Weight) + (13_195_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: ElectionProviderMultiPhase Round (r:1 w:0) // Storage: ElectionProviderMultiPhase CurrentPhase (r:0 w:1) fn on_initialize_open_unsigned() -> Weight { - (12_684_000 as Weight) + (12_782_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: System Account (r:1 w:1) // Storage: ElectionProviderMultiPhase QueuedSolution (r:0 w:1) fn finalize_signed_phase_accept_solution() -> Weight { - (27_272_000 as Weight) + (27_421_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: System Account (r:1 w:1) fn finalize_signed_phase_reject_solution() -> Weight { - (20_798_000 as Weight) + (21_325_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -104,11 +104,11 @@ impl WeightInfo for SubstrateWeight { // Storage: ElectionProviderMultiPhase DesiredTargets (r:0 w:1) // Storage: ElectionProviderMultiPhase Snapshot (r:0 w:1) fn create_snapshot_internal(v: u32, t: u32, ) -> Weight { - (13_760_000 as Weight) + (0 as Weight) // Standard Error: 1_000 - .saturating_add((201_000 as Weight).saturating_mul(v as Weight)) + .saturating_add((216_000 as Weight).saturating_mul(v as Weight)) // Standard Error: 3_000 - .saturating_add((49_000 as Weight).saturating_mul(t as Weight)) + .saturating_add((51_000 as Weight).saturating_mul(t as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: ElectionProviderMultiPhase SignedSubmissionIndices (r:1 w:1) @@ -121,11 +121,11 @@ impl WeightInfo for SubstrateWeight { // Storage: ElectionProviderMultiPhase Snapshot (r:0 w:1) // Storage: ElectionProviderMultiPhase CurrentPhase (r:0 w:1) fn elect_queued(a: u32, d: u32, ) -> Weight { - (108_461_000 as Weight) - // Standard Error: 3_000 - .saturating_add((1_318_000 as Weight).saturating_mul(a as Weight)) - // Standard Error: 5_000 - .saturating_add((194_000 as Weight).saturating_mul(d as Weight)) + (38_368_000 as Weight) + // Standard Error: 4_000 + .saturating_add((1_414_000 as Weight).saturating_mul(a as Weight)) + // Standard Error: 7_000 + .saturating_add((175_000 as Weight).saturating_mul(d as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(8 as Weight)) } @@ -136,9 +136,9 @@ impl WeightInfo for SubstrateWeight { // Storage: ElectionProviderMultiPhase SignedSubmissionNextIndex (r:1 w:1) // Storage: ElectionProviderMultiPhase SignedSubmissionsMap (r:0 w:1) fn submit(c: u32, ) -> Weight { - (39_721_000 as Weight) - // Standard Error: 24_000 - .saturating_add((298_000 as Weight).saturating_mul(c as Weight)) + (39_488_000 as Weight) + // Standard Error: 22_000 + .saturating_add((230_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -151,14 +151,14 @@ impl WeightInfo for SubstrateWeight { // Storage: ElectionProviderMultiPhase Snapshot (r:1 w:0) fn submit_unsigned(v: u32, t: u32, a: u32, d: u32, ) -> Weight { (0 as Weight) - // Standard Error: 4_000 - .saturating_add((1_612_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 8_000 - .saturating_add((105_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 13_000 - .saturating_add((7_024_000 as Weight).saturating_mul(a as Weight)) - // Standard Error: 20_000 - .saturating_add((1_361_000 as Weight).saturating_mul(d as Weight)) + // Standard Error: 2_000 + .saturating_add((1_544_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 5_000 + .saturating_add((60_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 9_000 + .saturating_add((6_555_000 as Weight).saturating_mul(a as Weight)) + // Standard Error: 14_000 + .saturating_add((1_318_000 as Weight).saturating_mul(d as Weight)) .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -168,14 +168,14 @@ impl WeightInfo for SubstrateWeight { // Storage: ElectionProviderMultiPhase Snapshot (r:1 w:0) fn feasibility_check(v: u32, t: u32, a: u32, d: u32, ) -> Weight { (0 as Weight) - // Standard Error: 2_000 - .saturating_add((1_639_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 5_000 - .saturating_add((138_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 8_000 - .saturating_add((5_665_000 as Weight).saturating_mul(a as Weight)) - // Standard Error: 13_000 - .saturating_add((980_000 as Weight).saturating_mul(d as Weight)) + // Standard Error: 3_000 + .saturating_add((1_527_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 6_000 + .saturating_add((151_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 10_000 + .saturating_add((5_433_000 as Weight).saturating_mul(a as Weight)) + // Standard Error: 15_000 + .saturating_add((1_420_000 as Weight).saturating_mul(d as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) } } @@ -191,33 +191,33 @@ impl WeightInfo for () { // Storage: Staking ForceEra (r:1 w:0) // Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) fn on_initialize_nothing() -> Weight { - (12_360_000 as Weight) + (12_763_000 as Weight) .saturating_add(RocksDbWeight::get().reads(8 as Weight)) } // Storage: ElectionProviderMultiPhase Round (r:1 w:0) // Storage: ElectionProviderMultiPhase CurrentPhase (r:0 w:1) fn on_initialize_open_signed() -> Weight { - (12_981_000 as Weight) + (13_195_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: ElectionProviderMultiPhase Round (r:1 w:0) // Storage: ElectionProviderMultiPhase CurrentPhase (r:0 w:1) fn on_initialize_open_unsigned() -> Weight { - (12_684_000 as Weight) + (12_782_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: System Account (r:1 w:1) // Storage: ElectionProviderMultiPhase QueuedSolution (r:0 w:1) fn finalize_signed_phase_accept_solution() -> Weight { - (27_272_000 as Weight) + (27_421_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: System Account (r:1 w:1) fn finalize_signed_phase_reject_solution() -> Weight { - (20_798_000 as Weight) + (21_325_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -225,11 +225,11 @@ impl WeightInfo for () { // Storage: ElectionProviderMultiPhase DesiredTargets (r:0 w:1) // Storage: ElectionProviderMultiPhase Snapshot (r:0 w:1) fn create_snapshot_internal(v: u32, t: u32, ) -> Weight { - (13_760_000 as Weight) + (0 as Weight) // Standard Error: 1_000 - .saturating_add((201_000 as Weight).saturating_mul(v as Weight)) + .saturating_add((216_000 as Weight).saturating_mul(v as Weight)) // Standard Error: 3_000 - .saturating_add((49_000 as Weight).saturating_mul(t as Weight)) + .saturating_add((51_000 as Weight).saturating_mul(t as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } // Storage: ElectionProviderMultiPhase SignedSubmissionIndices (r:1 w:1) @@ -242,11 +242,11 @@ impl WeightInfo for () { // Storage: ElectionProviderMultiPhase Snapshot (r:0 w:1) // Storage: ElectionProviderMultiPhase CurrentPhase (r:0 w:1) fn elect_queued(a: u32, d: u32, ) -> Weight { - (108_461_000 as Weight) - // Standard Error: 3_000 - .saturating_add((1_318_000 as Weight).saturating_mul(a as Weight)) - // Standard Error: 5_000 - .saturating_add((194_000 as Weight).saturating_mul(d as Weight)) + (38_368_000 as Weight) + // Standard Error: 4_000 + .saturating_add((1_414_000 as Weight).saturating_mul(a as Weight)) + // Standard Error: 7_000 + .saturating_add((175_000 as Weight).saturating_mul(d as Weight)) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(8 as Weight)) } @@ -257,9 +257,9 @@ impl WeightInfo for () { // Storage: ElectionProviderMultiPhase SignedSubmissionNextIndex (r:1 w:1) // Storage: ElectionProviderMultiPhase SignedSubmissionsMap (r:0 w:1) fn submit(c: u32, ) -> Weight { - (39_721_000 as Weight) - // Standard Error: 24_000 - .saturating_add((298_000 as Weight).saturating_mul(c as Weight)) + (39_488_000 as Weight) + // Standard Error: 22_000 + .saturating_add((230_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -272,14 +272,14 @@ impl WeightInfo for () { // Storage: ElectionProviderMultiPhase Snapshot (r:1 w:0) fn submit_unsigned(v: u32, t: u32, a: u32, d: u32, ) -> Weight { (0 as Weight) - // Standard Error: 4_000 - .saturating_add((1_612_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 8_000 - .saturating_add((105_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 13_000 - .saturating_add((7_024_000 as Weight).saturating_mul(a as Weight)) - // Standard Error: 20_000 - .saturating_add((1_361_000 as Weight).saturating_mul(d as Weight)) + // Standard Error: 2_000 + .saturating_add((1_544_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 5_000 + .saturating_add((60_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 9_000 + .saturating_add((6_555_000 as Weight).saturating_mul(a as Weight)) + // Standard Error: 14_000 + .saturating_add((1_318_000 as Weight).saturating_mul(d as Weight)) .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -289,14 +289,14 @@ impl WeightInfo for () { // Storage: ElectionProviderMultiPhase Snapshot (r:1 w:0) fn feasibility_check(v: u32, t: u32, a: u32, d: u32, ) -> Weight { (0 as Weight) - // Standard Error: 2_000 - .saturating_add((1_639_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 5_000 - .saturating_add((138_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 8_000 - .saturating_add((5_665_000 as Weight).saturating_mul(a as Weight)) - // Standard Error: 13_000 - .saturating_add((980_000 as Weight).saturating_mul(d as Weight)) + // Standard Error: 3_000 + .saturating_add((1_527_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 6_000 + .saturating_add((151_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 10_000 + .saturating_add((5_433_000 as Weight).saturating_mul(a as Weight)) + // Standard Error: 15_000 + .saturating_add((1_420_000 as Weight).saturating_mul(d as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) } } diff --git a/frame/elections-phragmen/src/weights.rs b/frame/elections-phragmen/src/weights.rs index 57cb1b718fb7..22c1c1cbeb40 100644 --- a/frame/elections-phragmen/src/weights.rs +++ b/frame/elections-phragmen/src/weights.rs @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_elections_phragmen //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-19, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-01-30, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/optimized/substrate +// ./target/production/substrate // benchmark // --chain=dev // --steps=50 @@ -32,7 +32,7 @@ // --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./weights-optimized/frame/elections-phragmen/src//weights.rs +// --output=./frame/elections-phragmen/src/weights.rs // --template=.maintain/frame-weight-template.hbs // --header=HEADER-APACHE2 // --raw @@ -70,9 +70,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Elections Voting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_equal(v: u32, ) -> Weight { - (24_231_000 as Weight) - // Standard Error: 4_000 - .saturating_add((305_000 as Weight).saturating_mul(v as Weight)) + (23_406_000 as Weight) + // Standard Error: 6_000 + .saturating_add((270_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -82,9 +82,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Elections Voting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_more(v: u32, ) -> Weight { - (37_524_000 as Weight) + (35_660_000 as Weight) // Standard Error: 6_000 - .saturating_add((285_000 as Weight).saturating_mul(v as Weight)) + .saturating_add((316_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -94,16 +94,16 @@ impl WeightInfo for SubstrateWeight { // Storage: Elections Voting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_less(v: u32, ) -> Weight { - (37_350_000 as Weight) - // Standard Error: 7_000 - .saturating_add((311_000 as Weight).saturating_mul(v as Weight)) + (35_999_000 as Weight) + // Standard Error: 6_000 + .saturating_add((299_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Elections Voting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn remove_voter() -> Weight { - (35_119_000 as Weight) + (33_692_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -111,17 +111,17 @@ impl WeightInfo for SubstrateWeight { // Storage: Elections Members (r:1 w:0) // Storage: Elections RunnersUp (r:1 w:0) fn submit_candidacy(c: u32, ) -> Weight { - (36_110_000 as Weight) + (35_506_000 as Weight) // Standard Error: 1_000 - .saturating_add((193_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((192_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Elections Candidates (r:1 w:1) fn renounce_candidacy_candidate(c: u32, ) -> Weight { - (30_976_000 as Weight) + (31_402_000 as Weight) // Standard Error: 1_000 - .saturating_add((129_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((113_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -131,13 +131,13 @@ impl WeightInfo for SubstrateWeight { // Storage: Council Proposals (r:1 w:0) // Storage: Council Members (r:0 w:1) fn renounce_candidacy_members() -> Weight { - (44_456_000 as Weight) + (42_727_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } // Storage: Elections RunnersUp (r:1 w:1) fn renounce_candidacy_runners_up() -> Weight { - (31_990_000 as Weight) + (30_638_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -152,13 +152,13 @@ impl WeightInfo for SubstrateWeight { // Storage: Council Proposals (r:1 w:0) // Storage: Council Members (r:0 w:1) fn remove_member_with_replacement() -> Weight { - (51_221_000 as Weight) + (49_317_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } // Storage: Elections RunnersUp (r:1 w:0) fn remove_member_wrong_refund() -> Weight { - (4_773_000 as Weight) + (4_688_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) } // Storage: Elections Voting (r:251 w:250) @@ -169,8 +169,8 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:250 w:250) fn clean_defunct_voters(v: u32, _d: u32, ) -> Weight { (0 as Weight) - // Standard Error: 31_000 - .saturating_add((51_744_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 36_000 + .saturating_add((51_016_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(v as Weight))) .saturating_add(T::DbWeight::get().writes((3 as Weight).saturating_mul(v as Weight))) @@ -186,12 +186,12 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:2 w:2) fn election_phragmen(c: u32, v: u32, e: u32, ) -> Weight { (0 as Weight) - // Standard Error: 1_744_000 - .saturating_add((29_677_000 as Weight).saturating_mul(c as Weight)) - // Standard Error: 725_000 - .saturating_add((51_480_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 1_760_000 + .saturating_add((29_569_000 as Weight).saturating_mul(c as Weight)) + // Standard Error: 732_000 + .saturating_add((51_842_000 as Weight).saturating_mul(v as Weight)) // Standard Error: 49_000 - .saturating_add((3_491_000 as Weight).saturating_mul(e as Weight)) + .saturating_add((3_546_000 as Weight).saturating_mul(e as Weight)) .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(c as Weight))) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(v as Weight))) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(c as Weight))) @@ -206,9 +206,9 @@ impl WeightInfo for () { // Storage: Elections Voting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_equal(v: u32, ) -> Weight { - (24_231_000 as Weight) - // Standard Error: 4_000 - .saturating_add((305_000 as Weight).saturating_mul(v as Weight)) + (23_406_000 as Weight) + // Standard Error: 6_000 + .saturating_add((270_000 as Weight).saturating_mul(v as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -218,9 +218,9 @@ impl WeightInfo for () { // Storage: Elections Voting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_more(v: u32, ) -> Weight { - (37_524_000 as Weight) + (35_660_000 as Weight) // Standard Error: 6_000 - .saturating_add((285_000 as Weight).saturating_mul(v as Weight)) + .saturating_add((316_000 as Weight).saturating_mul(v as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -230,16 +230,16 @@ impl WeightInfo for () { // Storage: Elections Voting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_less(v: u32, ) -> Weight { - (37_350_000 as Weight) - // Standard Error: 7_000 - .saturating_add((311_000 as Weight).saturating_mul(v as Weight)) + (35_999_000 as Weight) + // Standard Error: 6_000 + .saturating_add((299_000 as Weight).saturating_mul(v as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Elections Voting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn remove_voter() -> Weight { - (35_119_000 as Weight) + (33_692_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -247,17 +247,17 @@ impl WeightInfo for () { // Storage: Elections Members (r:1 w:0) // Storage: Elections RunnersUp (r:1 w:0) fn submit_candidacy(c: u32, ) -> Weight { - (36_110_000 as Weight) + (35_506_000 as Weight) // Standard Error: 1_000 - .saturating_add((193_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((192_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Elections Candidates (r:1 w:1) fn renounce_candidacy_candidate(c: u32, ) -> Weight { - (30_976_000 as Weight) + (31_402_000 as Weight) // Standard Error: 1_000 - .saturating_add((129_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((113_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -267,13 +267,13 @@ impl WeightInfo for () { // Storage: Council Proposals (r:1 w:0) // Storage: Council Members (r:0 w:1) fn renounce_candidacy_members() -> Weight { - (44_456_000 as Weight) + (42_727_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } // Storage: Elections RunnersUp (r:1 w:1) fn renounce_candidacy_runners_up() -> Weight { - (31_990_000 as Weight) + (30_638_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -288,13 +288,13 @@ impl WeightInfo for () { // Storage: Council Proposals (r:1 w:0) // Storage: Council Members (r:0 w:1) fn remove_member_with_replacement() -> Weight { - (51_221_000 as Weight) + (49_317_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } // Storage: Elections RunnersUp (r:1 w:0) fn remove_member_wrong_refund() -> Weight { - (4_773_000 as Weight) + (4_688_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) } // Storage: Elections Voting (r:251 w:250) @@ -305,8 +305,8 @@ impl WeightInfo for () { // Storage: System Account (r:250 w:250) fn clean_defunct_voters(v: u32, _d: u32, ) -> Weight { (0 as Weight) - // Standard Error: 31_000 - .saturating_add((51_744_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 36_000 + .saturating_add((51_016_000 as Weight).saturating_mul(v as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(v as Weight))) .saturating_add(RocksDbWeight::get().writes((3 as Weight).saturating_mul(v as Weight))) @@ -322,12 +322,12 @@ impl WeightInfo for () { // Storage: System Account (r:2 w:2) fn election_phragmen(c: u32, v: u32, e: u32, ) -> Weight { (0 as Weight) - // Standard Error: 1_744_000 - .saturating_add((29_677_000 as Weight).saturating_mul(c as Weight)) - // Standard Error: 725_000 - .saturating_add((51_480_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 1_760_000 + .saturating_add((29_569_000 as Weight).saturating_mul(c as Weight)) + // Standard Error: 732_000 + .saturating_add((51_842_000 as Weight).saturating_mul(v as Weight)) // Standard Error: 49_000 - .saturating_add((3_491_000 as Weight).saturating_mul(e as Weight)) + .saturating_add((3_546_000 as Weight).saturating_mul(e as Weight)) .saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(c as Weight))) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(v as Weight))) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(c as Weight))) diff --git a/frame/gilt/src/weights.rs b/frame/gilt/src/weights.rs index b56b6051a9ae..6084d494c5c3 100644 --- a/frame/gilt/src/weights.rs +++ b/frame/gilt/src/weights.rs @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_gilt //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-17, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-01-31, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/lto-fat-cg1/substrate +// ./target/production/substrate // benchmark // --chain=dev // --steps=50 @@ -34,7 +34,7 @@ // --heap-pages=4096 // --output=./frame/gilt/src/weights.rs // --template=.maintain/frame-weight-template.hbs -// --header=LICENSE-APACHE2 +// --header=HEADER-APACHE2 // --raw #![cfg_attr(rustfmt, rustfmt_skip)] @@ -62,44 +62,44 @@ impl WeightInfo for SubstrateWeight { // Storage: Gilt Queues (r:1 w:1) // Storage: Gilt QueueTotals (r:1 w:1) fn place_bid(l: u32, ) -> Weight { - (32_876_000 as Weight) + (32_753_000 as Weight) // Standard Error: 0 - .saturating_add((97_000 as Weight).saturating_mul(l as Weight)) + .saturating_add((96_000 as Weight).saturating_mul(l as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Gilt Queues (r:1 w:1) // Storage: Gilt QueueTotals (r:1 w:1) fn place_bid_max() -> Weight { - (125_854_000 as Weight) + (124_814_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Gilt Queues (r:1 w:1) // Storage: Gilt QueueTotals (r:1 w:1) fn retract_bid(l: u32, ) -> Weight { - (33_643_000 as Weight) + (33_544_000 as Weight) // Standard Error: 0 - .saturating_add((88_000 as Weight).saturating_mul(l as Weight)) + .saturating_add((86_000 as Weight).saturating_mul(l as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Gilt ActiveTotal (r:1 w:1) fn set_target() -> Weight { - (2_570_000 as Weight) + (2_648_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Gilt Active (r:1 w:1) // Storage: Gilt ActiveTotal (r:1 w:1) fn thaw() -> Weight { - (40_854_000 as Weight) + (41_549_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Gilt ActiveTotal (r:1 w:0) fn pursue_target_noop() -> Weight { - (1_598_000 as Weight) + (1_583_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) } // Storage: Gilt ActiveTotal (r:1 w:1) @@ -107,9 +107,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Gilt Queues (r:1 w:1) // Storage: Gilt Active (r:0 w:1) fn pursue_target_per_item(b: u32, ) -> Weight { - (34_848_000 as Weight) + (35_836_000 as Weight) // Standard Error: 1_000 - .saturating_add((3_951_000 as Weight).saturating_mul(b as Weight)) + .saturating_add((4_008_000 as Weight).saturating_mul(b as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(b as Weight))) @@ -119,9 +119,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Gilt Queues (r:1 w:1) // Storage: Gilt Active (r:0 w:1) fn pursue_target_per_queue(q: u32, ) -> Weight { - (9_735_000 as Weight) + (12_139_000 as Weight) // Standard Error: 6_000 - .saturating_add((7_873_000 as Weight).saturating_mul(q as Weight)) + .saturating_add((7_819_000 as Weight).saturating_mul(q as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(q as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -134,44 +134,44 @@ impl WeightInfo for () { // Storage: Gilt Queues (r:1 w:1) // Storage: Gilt QueueTotals (r:1 w:1) fn place_bid(l: u32, ) -> Weight { - (32_876_000 as Weight) + (32_753_000 as Weight) // Standard Error: 0 - .saturating_add((97_000 as Weight).saturating_mul(l as Weight)) + .saturating_add((96_000 as Weight).saturating_mul(l as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Gilt Queues (r:1 w:1) // Storage: Gilt QueueTotals (r:1 w:1) fn place_bid_max() -> Weight { - (125_854_000 as Weight) + (124_814_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Gilt Queues (r:1 w:1) // Storage: Gilt QueueTotals (r:1 w:1) fn retract_bid(l: u32, ) -> Weight { - (33_643_000 as Weight) + (33_544_000 as Weight) // Standard Error: 0 - .saturating_add((88_000 as Weight).saturating_mul(l as Weight)) + .saturating_add((86_000 as Weight).saturating_mul(l as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Gilt ActiveTotal (r:1 w:1) fn set_target() -> Weight { - (2_570_000 as Weight) + (2_648_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Gilt Active (r:1 w:1) // Storage: Gilt ActiveTotal (r:1 w:1) fn thaw() -> Weight { - (40_854_000 as Weight) + (41_549_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Gilt ActiveTotal (r:1 w:0) fn pursue_target_noop() -> Weight { - (1_598_000 as Weight) + (1_583_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) } // Storage: Gilt ActiveTotal (r:1 w:1) @@ -179,9 +179,9 @@ impl WeightInfo for () { // Storage: Gilt Queues (r:1 w:1) // Storage: Gilt Active (r:0 w:1) fn pursue_target_per_item(b: u32, ) -> Weight { - (34_848_000 as Weight) + (35_836_000 as Weight) // Standard Error: 1_000 - .saturating_add((3_951_000 as Weight).saturating_mul(b as Weight)) + .saturating_add((4_008_000 as Weight).saturating_mul(b as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(b as Weight))) @@ -191,9 +191,9 @@ impl WeightInfo for () { // Storage: Gilt Queues (r:1 w:1) // Storage: Gilt Active (r:0 w:1) fn pursue_target_per_queue(q: u32, ) -> Weight { - (9_735_000 as Weight) + (12_139_000 as Weight) // Standard Error: 6_000 - .saturating_add((7_873_000 as Weight).saturating_mul(q as Weight)) + .saturating_add((7_819_000 as Weight).saturating_mul(q as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(q as Weight))) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) diff --git a/frame/identity/src/weights.rs b/frame/identity/src/weights.rs index 1d0a7825ec40..cf164d3cbd73 100644 --- a/frame/identity/src/weights.rs +++ b/frame/identity/src/weights.rs @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_identity //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-17, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-01-31, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/lto-fat-cg1/substrate +// ./target/production/substrate // benchmark // --chain=dev // --steps=50 @@ -34,7 +34,7 @@ // --heap-pages=4096 // --output=./frame/identity/src/weights.rs // --template=.maintain/frame-weight-template.hbs -// --header=LICENSE-APACHE2 +// --header=HEADER-APACHE2 // --raw #![cfg_attr(rustfmt, rustfmt_skip)] @@ -69,19 +69,19 @@ pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { // Storage: Identity Registrars (r:1 w:1) fn add_registrar(r: u32, ) -> Weight { - (12_513_000 as Weight) - // Standard Error: 4_000 - .saturating_add((257_000 as Weight).saturating_mul(r as Weight)) + (13_150_000 as Weight) + // Standard Error: 3_000 + .saturating_add((253_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Identity IdentityOf (r:1 w:1) fn set_identity(r: u32, x: u32, ) -> Weight { - (27_904_000 as Weight) + (27_745_000 as Weight) // Standard Error: 7_000 - .saturating_add((215_000 as Weight).saturating_mul(r as Weight)) - // Standard Error: 0 - .saturating_add((294_000 as Weight).saturating_mul(x as Weight)) + .saturating_add((210_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 1_000 + .saturating_add((289_000 as Weight).saturating_mul(x as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -89,9 +89,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Identity SubsOf (r:1 w:1) // Storage: Identity SuperOf (r:1 w:1) fn set_subs_new(s: u32, ) -> Weight { - (24_530_000 as Weight) + (25_184_000 as Weight) // Standard Error: 1_000 - .saturating_add((2_914_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((2_722_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -101,9 +101,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Identity SubsOf (r:1 w:1) // Storage: Identity SuperOf (r:0 w:1) fn set_subs_old(p: u32, ) -> Weight { - (23_957_000 as Weight) + (24_144_000 as Weight) // Standard Error: 0 - .saturating_add((954_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((890_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(p as Weight))) @@ -112,13 +112,13 @@ impl WeightInfo for SubstrateWeight { // Storage: Identity IdentityOf (r:1 w:1) // Storage: Identity SuperOf (r:0 w:100) fn clear_identity(r: u32, s: u32, x: u32, ) -> Weight { - (31_213_000 as Weight) + (32_167_000 as Weight) // Standard Error: 8_000 - .saturating_add((99_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((46_000 as Weight).saturating_mul(r as Weight)) // Standard Error: 0 - .saturating_add((931_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((875_000 as Weight).saturating_mul(s as Weight)) // Standard Error: 0 - .saturating_add((188_000 as Weight).saturating_mul(x as Weight)) + .saturating_add((184_000 as Weight).saturating_mul(x as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) @@ -126,27 +126,27 @@ impl WeightInfo for SubstrateWeight { // Storage: Identity Registrars (r:1 w:0) // Storage: Identity IdentityOf (r:1 w:1) fn request_judgement(r: u32, x: u32, ) -> Weight { - (30_691_000 as Weight) - // Standard Error: 4_000 - .saturating_add((269_000 as Weight).saturating_mul(r as Weight)) + (30_009_000 as Weight) + // Standard Error: 3_000 + .saturating_add((287_000 as Weight).saturating_mul(r as Weight)) // Standard Error: 0 - .saturating_add((338_000 as Weight).saturating_mul(x as Weight)) + .saturating_add((331_000 as Weight).saturating_mul(x as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Identity IdentityOf (r:1 w:1) fn cancel_request(r: u32, x: u32, ) -> Weight { - (27_356_000 as Weight) + (28_195_000 as Weight) // Standard Error: 3_000 - .saturating_add((179_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((137_000 as Weight).saturating_mul(r as Weight)) // Standard Error: 0 - .saturating_add((335_000 as Weight).saturating_mul(x as Weight)) + .saturating_add((328_000 as Weight).saturating_mul(x as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Identity Registrars (r:1 w:1) fn set_fee(r: u32, ) -> Weight { - (4_761_000 as Weight) + (5_080_000 as Weight) // Standard Error: 2_000 .saturating_add((202_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) @@ -154,28 +154,28 @@ impl WeightInfo for SubstrateWeight { } // Storage: Identity Registrars (r:1 w:1) fn set_account_id(r: u32, ) -> Weight { - (4_801_000 as Weight) - // Standard Error: 3_000 - .saturating_add((211_000 as Weight).saturating_mul(r as Weight)) + (5_298_000 as Weight) + // Standard Error: 2_000 + .saturating_add((195_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Identity Registrars (r:1 w:1) fn set_fields(r: u32, ) -> Weight { - (4_756_000 as Weight) + (5_263_000 as Weight) // Standard Error: 2_000 - .saturating_add((204_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((191_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Identity Registrars (r:1 w:0) // Storage: Identity IdentityOf (r:1 w:1) fn provide_judgement(r: u32, x: u32, ) -> Weight { - (21_047_000 as Weight) + (21_511_000 as Weight) // Standard Error: 3_000 - .saturating_add((246_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((219_000 as Weight).saturating_mul(r as Weight)) // Standard Error: 0 - .saturating_add((341_000 as Weight).saturating_mul(x as Weight)) + .saturating_add((327_000 as Weight).saturating_mul(x as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -184,11 +184,11 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:1 w:1) // Storage: Identity SuperOf (r:0 w:100) fn kill_identity(r: u32, s: u32, _x: u32, ) -> Weight { - (41_324_000 as Weight) - // Standard Error: 7_000 - .saturating_add((192_000 as Weight).saturating_mul(r as Weight)) + (40_654_000 as Weight) + // Standard Error: 6_000 + .saturating_add((179_000 as Weight).saturating_mul(r as Weight)) // Standard Error: 0 - .saturating_add((951_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((908_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) @@ -197,18 +197,18 @@ impl WeightInfo for SubstrateWeight { // Storage: Identity SuperOf (r:1 w:1) // Storage: Identity SubsOf (r:1 w:1) fn add_sub(s: u32, ) -> Weight { - (31_405_000 as Weight) + (31_573_000 as Weight) // Standard Error: 1_000 - .saturating_add((160_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((151_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Identity IdentityOf (r:1 w:0) // Storage: Identity SuperOf (r:1 w:1) fn rename_sub(s: u32, ) -> Weight { - (10_622_000 as Weight) + (10_452_000 as Weight) // Standard Error: 0 - .saturating_add((47_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((45_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -216,18 +216,18 @@ impl WeightInfo for SubstrateWeight { // Storage: Identity SuperOf (r:1 w:1) // Storage: Identity SubsOf (r:1 w:1) fn remove_sub(s: u32, ) -> Weight { - (32_765_000 as Weight) + (32_711_000 as Weight) // Standard Error: 1_000 - .saturating_add((158_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((150_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Identity SuperOf (r:1 w:1) // Storage: Identity SubsOf (r:1 w:1) fn quit_sub(s: u32, ) -> Weight { - (21_925_000 as Weight) - // Standard Error: 1_000 - .saturating_add((156_000 as Weight).saturating_mul(s as Weight)) + (21_975_000 as Weight) + // Standard Error: 0 + .saturating_add((149_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -237,19 +237,19 @@ impl WeightInfo for SubstrateWeight { impl WeightInfo for () { // Storage: Identity Registrars (r:1 w:1) fn add_registrar(r: u32, ) -> Weight { - (12_513_000 as Weight) - // Standard Error: 4_000 - .saturating_add((257_000 as Weight).saturating_mul(r as Weight)) + (13_150_000 as Weight) + // Standard Error: 3_000 + .saturating_add((253_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Identity IdentityOf (r:1 w:1) fn set_identity(r: u32, x: u32, ) -> Weight { - (27_904_000 as Weight) + (27_745_000 as Weight) // Standard Error: 7_000 - .saturating_add((215_000 as Weight).saturating_mul(r as Weight)) - // Standard Error: 0 - .saturating_add((294_000 as Weight).saturating_mul(x as Weight)) + .saturating_add((210_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 1_000 + .saturating_add((289_000 as Weight).saturating_mul(x as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -257,9 +257,9 @@ impl WeightInfo for () { // Storage: Identity SubsOf (r:1 w:1) // Storage: Identity SuperOf (r:1 w:1) fn set_subs_new(s: u32, ) -> Weight { - (24_530_000 as Weight) + (25_184_000 as Weight) // Standard Error: 1_000 - .saturating_add((2_914_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((2_722_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -269,9 +269,9 @@ impl WeightInfo for () { // Storage: Identity SubsOf (r:1 w:1) // Storage: Identity SuperOf (r:0 w:1) fn set_subs_old(p: u32, ) -> Weight { - (23_957_000 as Weight) + (24_144_000 as Weight) // Standard Error: 0 - .saturating_add((954_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((890_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(p as Weight))) @@ -280,13 +280,13 @@ impl WeightInfo for () { // Storage: Identity IdentityOf (r:1 w:1) // Storage: Identity SuperOf (r:0 w:100) fn clear_identity(r: u32, s: u32, x: u32, ) -> Weight { - (31_213_000 as Weight) + (32_167_000 as Weight) // Standard Error: 8_000 - .saturating_add((99_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((46_000 as Weight).saturating_mul(r as Weight)) // Standard Error: 0 - .saturating_add((931_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((875_000 as Weight).saturating_mul(s as Weight)) // Standard Error: 0 - .saturating_add((188_000 as Weight).saturating_mul(x as Weight)) + .saturating_add((184_000 as Weight).saturating_mul(x as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) @@ -294,27 +294,27 @@ impl WeightInfo for () { // Storage: Identity Registrars (r:1 w:0) // Storage: Identity IdentityOf (r:1 w:1) fn request_judgement(r: u32, x: u32, ) -> Weight { - (30_691_000 as Weight) - // Standard Error: 4_000 - .saturating_add((269_000 as Weight).saturating_mul(r as Weight)) + (30_009_000 as Weight) + // Standard Error: 3_000 + .saturating_add((287_000 as Weight).saturating_mul(r as Weight)) // Standard Error: 0 - .saturating_add((338_000 as Weight).saturating_mul(x as Weight)) + .saturating_add((331_000 as Weight).saturating_mul(x as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Identity IdentityOf (r:1 w:1) fn cancel_request(r: u32, x: u32, ) -> Weight { - (27_356_000 as Weight) + (28_195_000 as Weight) // Standard Error: 3_000 - .saturating_add((179_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((137_000 as Weight).saturating_mul(r as Weight)) // Standard Error: 0 - .saturating_add((335_000 as Weight).saturating_mul(x as Weight)) + .saturating_add((328_000 as Weight).saturating_mul(x as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Identity Registrars (r:1 w:1) fn set_fee(r: u32, ) -> Weight { - (4_761_000 as Weight) + (5_080_000 as Weight) // Standard Error: 2_000 .saturating_add((202_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) @@ -322,28 +322,28 @@ impl WeightInfo for () { } // Storage: Identity Registrars (r:1 w:1) fn set_account_id(r: u32, ) -> Weight { - (4_801_000 as Weight) - // Standard Error: 3_000 - .saturating_add((211_000 as Weight).saturating_mul(r as Weight)) + (5_298_000 as Weight) + // Standard Error: 2_000 + .saturating_add((195_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Identity Registrars (r:1 w:1) fn set_fields(r: u32, ) -> Weight { - (4_756_000 as Weight) + (5_263_000 as Weight) // Standard Error: 2_000 - .saturating_add((204_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((191_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Identity Registrars (r:1 w:0) // Storage: Identity IdentityOf (r:1 w:1) fn provide_judgement(r: u32, x: u32, ) -> Weight { - (21_047_000 as Weight) + (21_511_000 as Weight) // Standard Error: 3_000 - .saturating_add((246_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((219_000 as Weight).saturating_mul(r as Weight)) // Standard Error: 0 - .saturating_add((341_000 as Weight).saturating_mul(x as Weight)) + .saturating_add((327_000 as Weight).saturating_mul(x as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -352,11 +352,11 @@ impl WeightInfo for () { // Storage: System Account (r:1 w:1) // Storage: Identity SuperOf (r:0 w:100) fn kill_identity(r: u32, s: u32, _x: u32, ) -> Weight { - (41_324_000 as Weight) - // Standard Error: 7_000 - .saturating_add((192_000 as Weight).saturating_mul(r as Weight)) + (40_654_000 as Weight) + // Standard Error: 6_000 + .saturating_add((179_000 as Weight).saturating_mul(r as Weight)) // Standard Error: 0 - .saturating_add((951_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((908_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) @@ -365,18 +365,18 @@ impl WeightInfo for () { // Storage: Identity SuperOf (r:1 w:1) // Storage: Identity SubsOf (r:1 w:1) fn add_sub(s: u32, ) -> Weight { - (31_405_000 as Weight) + (31_573_000 as Weight) // Standard Error: 1_000 - .saturating_add((160_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((151_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Identity IdentityOf (r:1 w:0) // Storage: Identity SuperOf (r:1 w:1) fn rename_sub(s: u32, ) -> Weight { - (10_622_000 as Weight) + (10_452_000 as Weight) // Standard Error: 0 - .saturating_add((47_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((45_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -384,18 +384,18 @@ impl WeightInfo for () { // Storage: Identity SuperOf (r:1 w:1) // Storage: Identity SubsOf (r:1 w:1) fn remove_sub(s: u32, ) -> Weight { - (32_765_000 as Weight) + (32_711_000 as Weight) // Standard Error: 1_000 - .saturating_add((158_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((150_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Identity SuperOf (r:1 w:1) // Storage: Identity SubsOf (r:1 w:1) fn quit_sub(s: u32, ) -> Weight { - (21_925_000 as Weight) - // Standard Error: 1_000 - .saturating_add((156_000 as Weight).saturating_mul(s as Weight)) + (21_975_000 as Weight) + // Standard Error: 0 + .saturating_add((149_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } diff --git a/frame/im-online/src/weights.rs b/frame/im-online/src/weights.rs index 4fa5727251b3..f7d4d1441da2 100644 --- a/frame/im-online/src/weights.rs +++ b/frame/im-online/src/weights.rs @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_im_online //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-19, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-01-31, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/optimized/substrate +// ./target/production/substrate // benchmark // --chain=dev // --steps=50 @@ -32,7 +32,7 @@ // --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./weights-optimized/frame/im-online/src//weights.rs +// --output=./frame/im-online/src/weights.rs // --template=.maintain/frame-weight-template.hbs // --header=HEADER-APACHE2 // --raw @@ -58,11 +58,11 @@ impl WeightInfo for SubstrateWeight { // Storage: ImOnline AuthoredBlocks (r:1 w:0) // Storage: ImOnline Keys (r:1 w:0) fn validate_unsigned_and_then_heartbeat(k: u32, e: u32, ) -> Weight { - (73_594_000 as Weight) + (74_137_000 as Weight) // Standard Error: 0 - .saturating_add((128_000 as Weight).saturating_mul(k as Weight)) + .saturating_add((125_000 as Weight).saturating_mul(k as Weight)) // Standard Error: 0 - .saturating_add((295_000 as Weight).saturating_mul(e as Weight)) + .saturating_add((291_000 as Weight).saturating_mul(e as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -76,11 +76,11 @@ impl WeightInfo for () { // Storage: ImOnline AuthoredBlocks (r:1 w:0) // Storage: ImOnline Keys (r:1 w:0) fn validate_unsigned_and_then_heartbeat(k: u32, e: u32, ) -> Weight { - (73_594_000 as Weight) + (74_137_000 as Weight) // Standard Error: 0 - .saturating_add((128_000 as Weight).saturating_mul(k as Weight)) + .saturating_add((125_000 as Weight).saturating_mul(k as Weight)) // Standard Error: 0 - .saturating_add((295_000 as Weight).saturating_mul(e as Weight)) + .saturating_add((291_000 as Weight).saturating_mul(e as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } diff --git a/frame/indices/src/weights.rs b/frame/indices/src/weights.rs index 569af75af6dc..1687237394fb 100644 --- a/frame/indices/src/weights.rs +++ b/frame/indices/src/weights.rs @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_indices //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-17, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-01-31, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/lto-fat-cg1/substrate +// ./target/production/substrate // benchmark // --chain=dev // --steps=50 @@ -34,7 +34,7 @@ // --heap-pages=4096 // --output=./frame/indices/src/weights.rs // --template=.maintain/frame-weight-template.hbs -// --header=LICENSE-APACHE2 +// --header=HEADER-APACHE2 // --raw #![cfg_attr(rustfmt, rustfmt_skip)] @@ -58,33 +58,33 @@ pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { // Storage: Indices Accounts (r:1 w:1) fn claim() -> Weight { - (20_754_000 as Weight) + (21_121_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Indices Accounts (r:1 w:1) // Storage: System Account (r:1 w:1) fn transfer() -> Weight { - (26_655_000 as Weight) + (26_843_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Indices Accounts (r:1 w:1) fn free() -> Weight { - (22_112_000 as Weight) + (22_174_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Indices Accounts (r:1 w:1) // Storage: System Account (r:1 w:1) fn force_transfer() -> Weight { - (22_175_000 as Weight) + (22_191_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Indices Accounts (r:1 w:1) fn freeze() -> Weight { - (24_344_000 as Weight) + (24_813_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -94,33 +94,33 @@ impl WeightInfo for SubstrateWeight { impl WeightInfo for () { // Storage: Indices Accounts (r:1 w:1) fn claim() -> Weight { - (20_754_000 as Weight) + (21_121_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Indices Accounts (r:1 w:1) // Storage: System Account (r:1 w:1) fn transfer() -> Weight { - (26_655_000 as Weight) + (26_843_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Indices Accounts (r:1 w:1) fn free() -> Weight { - (22_112_000 as Weight) + (22_174_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Indices Accounts (r:1 w:1) // Storage: System Account (r:1 w:1) fn force_transfer() -> Weight { - (22_175_000 as Weight) + (22_191_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Indices Accounts (r:1 w:1) fn freeze() -> Weight { - (24_344_000 as Weight) + (24_813_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } diff --git a/frame/lottery/src/weights.rs b/frame/lottery/src/weights.rs index 080222125c84..3b6114a73cfa 100644 --- a/frame/lottery/src/weights.rs +++ b/frame/lottery/src/weights.rs @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_lottery //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-17, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-01-31, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/lto-fat-cg1/substrate +// ./target/production/substrate // benchmark // --chain=dev // --steps=50 @@ -34,7 +34,7 @@ // --heap-pages=4096 // --output=./frame/lottery/src/weights.rs // --template=.maintain/frame-weight-template.hbs -// --header=LICENSE-APACHE2 +// --header=HEADER-APACHE2 // --raw #![cfg_attr(rustfmt, rustfmt_skip)] @@ -65,28 +65,28 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:1 w:1) // Storage: Lottery Tickets (r:0 w:1) fn buy_ticket() -> Weight { - (38_270_000 as Weight) + (37_257_000 as Weight) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } // Storage: Lottery CallIndices (r:0 w:1) fn set_calls(n: u32, ) -> Weight { - (8_830_000 as Weight) - // Standard Error: 7_000 - .saturating_add((291_000 as Weight).saturating_mul(n as Weight)) + (8_966_000 as Weight) + // Standard Error: 5_000 + .saturating_add((302_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Lottery Lottery (r:1 w:1) // Storage: Lottery LotteryIndex (r:1 w:1) // Storage: System Account (r:1 w:1) fn start_lottery() -> Weight { - (31_404_000 as Weight) + (32_282_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Lottery Lottery (r:1 w:1) fn stop_repeat() -> Weight { - (3_825_000 as Weight) + (3_903_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -96,7 +96,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Lottery TicketsCount (r:1 w:1) // Storage: Lottery Tickets (r:1 w:0) fn on_initialize_end() -> Weight { - (49_760_000 as Weight) + (51_489_000 as Weight) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } @@ -107,7 +107,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Lottery Tickets (r:1 w:0) // Storage: Lottery LotteryIndex (r:1 w:1) fn on_initialize_repeat() -> Weight { - (53_159_000 as Weight) + (53_046_000 as Weight) .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } @@ -123,28 +123,28 @@ impl WeightInfo for () { // Storage: System Account (r:1 w:1) // Storage: Lottery Tickets (r:0 w:1) fn buy_ticket() -> Weight { - (38_270_000 as Weight) + (37_257_000 as Weight) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } // Storage: Lottery CallIndices (r:0 w:1) fn set_calls(n: u32, ) -> Weight { - (8_830_000 as Weight) - // Standard Error: 7_000 - .saturating_add((291_000 as Weight).saturating_mul(n as Weight)) + (8_966_000 as Weight) + // Standard Error: 5_000 + .saturating_add((302_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Lottery Lottery (r:1 w:1) // Storage: Lottery LotteryIndex (r:1 w:1) // Storage: System Account (r:1 w:1) fn start_lottery() -> Weight { - (31_404_000 as Weight) + (32_282_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } // Storage: Lottery Lottery (r:1 w:1) fn stop_repeat() -> Weight { - (3_825_000 as Weight) + (3_903_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -154,7 +154,7 @@ impl WeightInfo for () { // Storage: Lottery TicketsCount (r:1 w:1) // Storage: Lottery Tickets (r:1 w:0) fn on_initialize_end() -> Weight { - (49_760_000 as Weight) + (51_489_000 as Weight) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } @@ -165,7 +165,7 @@ impl WeightInfo for () { // Storage: Lottery Tickets (r:1 w:0) // Storage: Lottery LotteryIndex (r:1 w:1) fn on_initialize_repeat() -> Weight { - (53_159_000 as Weight) + (53_046_000 as Weight) .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } diff --git a/frame/membership/src/weights.rs b/frame/membership/src/weights.rs index 59215d3a5bff..0d4936cfba1f 100644 --- a/frame/membership/src/weights.rs +++ b/frame/membership/src/weights.rs @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_membership //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-17, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-01-31, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/lto-fat-cg1/substrate +// ./target/production/substrate // benchmark // --chain=dev // --steps=50 @@ -34,7 +34,7 @@ // --heap-pages=4096 // --output=./frame/membership/src/weights.rs // --template=.maintain/frame-weight-template.hbs -// --header=LICENSE-APACHE2 +// --header=HEADER-APACHE2 // --raw #![cfg_attr(rustfmt, rustfmt_skip)] @@ -63,9 +63,9 @@ impl WeightInfo for SubstrateWeight { // Storage: TechnicalCommittee Members (r:0 w:1) // Storage: TechnicalCommittee Prime (r:0 w:1) fn add_member(m: u32, ) -> Weight { - (14_403_000 as Weight) - // Standard Error: 1_000 - .saturating_add((94_000 as Weight).saturating_mul(m as Weight)) + (14_884_000 as Weight) + // Standard Error: 0 + .saturating_add((95_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -75,9 +75,9 @@ impl WeightInfo for SubstrateWeight { // Storage: TechnicalCommittee Members (r:0 w:1) // Storage: TechnicalCommittee Prime (r:0 w:1) fn remove_member(m: u32, ) -> Weight { - (17_005_000 as Weight) + (17_612_000 as Weight) // Standard Error: 0 - .saturating_add((90_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((86_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -87,7 +87,7 @@ impl WeightInfo for SubstrateWeight { // Storage: TechnicalCommittee Members (r:0 w:1) // Storage: TechnicalCommittee Prime (r:0 w:1) fn swap_member(m: u32, ) -> Weight { - (17_210_000 as Weight) + (17_580_000 as Weight) // Standard Error: 0 .saturating_add((98_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) @@ -99,9 +99,9 @@ impl WeightInfo for SubstrateWeight { // Storage: TechnicalCommittee Members (r:0 w:1) // Storage: TechnicalCommittee Prime (r:0 w:1) fn reset_member(m: u32, ) -> Weight { - (17_425_000 as Weight) + (17_610_000 as Weight) // Standard Error: 0 - .saturating_add((194_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((199_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -111,9 +111,9 @@ impl WeightInfo for SubstrateWeight { // Storage: TechnicalCommittee Members (r:0 w:1) // Storage: TechnicalCommittee Prime (r:0 w:1) fn change_key(m: u32, ) -> Weight { - (17_948_000 as Weight) + (18_208_000 as Weight) // Standard Error: 0 - .saturating_add((95_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((96_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } @@ -121,18 +121,18 @@ impl WeightInfo for SubstrateWeight { // Storage: TechnicalMembership Prime (r:0 w:1) // Storage: TechnicalCommittee Prime (r:0 w:1) fn set_prime(m: u32, ) -> Weight { - (4_579_000 as Weight) + (4_661_000 as Weight) // Standard Error: 0 - .saturating_add((71_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((70_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: TechnicalMembership Prime (r:0 w:1) // Storage: TechnicalCommittee Prime (r:0 w:1) fn clear_prime(m: u32, ) -> Weight { - (1_481_000 as Weight) + (1_574_000 as Weight) // Standard Error: 0 - .saturating_add((2_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((1_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } } @@ -144,9 +144,9 @@ impl WeightInfo for () { // Storage: TechnicalCommittee Members (r:0 w:1) // Storage: TechnicalCommittee Prime (r:0 w:1) fn add_member(m: u32, ) -> Weight { - (14_403_000 as Weight) - // Standard Error: 1_000 - .saturating_add((94_000 as Weight).saturating_mul(m as Weight)) + (14_884_000 as Weight) + // Standard Error: 0 + .saturating_add((95_000 as Weight).saturating_mul(m as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -156,9 +156,9 @@ impl WeightInfo for () { // Storage: TechnicalCommittee Members (r:0 w:1) // Storage: TechnicalCommittee Prime (r:0 w:1) fn remove_member(m: u32, ) -> Weight { - (17_005_000 as Weight) + (17_612_000 as Weight) // Standard Error: 0 - .saturating_add((90_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((86_000 as Weight).saturating_mul(m as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -168,7 +168,7 @@ impl WeightInfo for () { // Storage: TechnicalCommittee Members (r:0 w:1) // Storage: TechnicalCommittee Prime (r:0 w:1) fn swap_member(m: u32, ) -> Weight { - (17_210_000 as Weight) + (17_580_000 as Weight) // Standard Error: 0 .saturating_add((98_000 as Weight).saturating_mul(m as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) @@ -180,9 +180,9 @@ impl WeightInfo for () { // Storage: TechnicalCommittee Members (r:0 w:1) // Storage: TechnicalCommittee Prime (r:0 w:1) fn reset_member(m: u32, ) -> Weight { - (17_425_000 as Weight) + (17_610_000 as Weight) // Standard Error: 0 - .saturating_add((194_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((199_000 as Weight).saturating_mul(m as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -192,9 +192,9 @@ impl WeightInfo for () { // Storage: TechnicalCommittee Members (r:0 w:1) // Storage: TechnicalCommittee Prime (r:0 w:1) fn change_key(m: u32, ) -> Weight { - (17_948_000 as Weight) + (18_208_000 as Weight) // Standard Error: 0 - .saturating_add((95_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((96_000 as Weight).saturating_mul(m as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } @@ -202,18 +202,18 @@ impl WeightInfo for () { // Storage: TechnicalMembership Prime (r:0 w:1) // Storage: TechnicalCommittee Prime (r:0 w:1) fn set_prime(m: u32, ) -> Weight { - (4_579_000 as Weight) + (4_661_000 as Weight) // Standard Error: 0 - .saturating_add((71_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((70_000 as Weight).saturating_mul(m as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: TechnicalMembership Prime (r:0 w:1) // Storage: TechnicalCommittee Prime (r:0 w:1) fn clear_prime(m: u32, ) -> Weight { - (1_481_000 as Weight) + (1_574_000 as Weight) // Standard Error: 0 - .saturating_add((2_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((1_000 as Weight).saturating_mul(m as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } } diff --git a/frame/multisig/src/weights.rs b/frame/multisig/src/weights.rs index 5dc40197db55..501fb9c18419 100644 --- a/frame/multisig/src/weights.rs +++ b/frame/multisig/src/weights.rs @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_multisig //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-17, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-01-31, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/lto-fat-cg1/substrate +// ./target/production/substrate // benchmark // --chain=dev // --steps=50 @@ -34,7 +34,7 @@ // --heap-pages=4096 // --output=./frame/multisig/src/weights.rs // --template=.maintain/frame-weight-template.hbs -// --header=LICENSE-APACHE2 +// --header=HEADER-APACHE2 // --raw #![cfg_attr(rustfmt, rustfmt_skip)] @@ -62,16 +62,16 @@ pub trait WeightInfo { pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { fn as_multi_threshold_1(z: u32, ) -> Weight { - (16_904_000 as Weight) + (16_534_000 as Weight) // Standard Error: 0 .saturating_add((1_000 as Weight).saturating_mul(z as Weight)) } // Storage: Multisig Multisigs (r:1 w:1) // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) fn as_multi_create(s: u32, z: u32, ) -> Weight { - (30_172_000 as Weight) - // Standard Error: 0 - .saturating_add((142_000 as Weight).saturating_mul(s as Weight)) + (30_917_000 as Weight) + // Standard Error: 1_000 + .saturating_add((131_000 as Weight).saturating_mul(s as Weight)) // Standard Error: 0 .saturating_add((1_000 as Weight).saturating_mul(z as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) @@ -81,9 +81,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Multisig Calls (r:1 w:1) // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) fn as_multi_create_store(s: u32, z: u32, ) -> Weight { - (33_039_000 as Weight) + (33_570_000 as Weight) // Standard Error: 1_000 - .saturating_add((140_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((138_000 as Weight).saturating_mul(s as Weight)) // Standard Error: 0 .saturating_add((2_000 as Weight).saturating_mul(z as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) @@ -91,9 +91,9 @@ impl WeightInfo for SubstrateWeight { } // Storage: Multisig Multisigs (r:1 w:1) fn as_multi_approve(s: u32, z: u32, ) -> Weight { - (20_752_000 as Weight) + (21_051_000 as Weight) // Standard Error: 0 - .saturating_add((133_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((126_000 as Weight).saturating_mul(s as Weight)) // Standard Error: 0 .saturating_add((1_000 as Weight).saturating_mul(z as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) @@ -102,7 +102,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Multisig Multisigs (r:1 w:1) // Storage: Multisig Calls (r:1 w:1) fn as_multi_approve_store(s: u32, z: u32, ) -> Weight { - (33_198_000 as Weight) + (32_581_000 as Weight) // Standard Error: 1_000 .saturating_add((135_000 as Weight).saturating_mul(s as Weight)) // Standard Error: 0 @@ -114,9 +114,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Multisig Calls (r:1 w:1) // Storage: System Account (r:1 w:1) fn as_multi_complete(s: u32, z: u32, ) -> Weight { - (39_407_000 as Weight) + (39_215_000 as Weight) // Standard Error: 1_000 - .saturating_add((230_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((221_000 as Weight).saturating_mul(s as Weight)) // Standard Error: 0 .saturating_add((2_000 as Weight).saturating_mul(z as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) @@ -125,18 +125,18 @@ impl WeightInfo for SubstrateWeight { // Storage: Multisig Multisigs (r:1 w:1) // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) fn approve_as_multi_create(s: u32, ) -> Weight { - (28_365_000 as Weight) + (28_572_000 as Weight) // Standard Error: 1_000 - .saturating_add((156_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((146_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Multisig Multisigs (r:1 w:1) // Storage: Multisig Calls (r:1 w:0) fn approve_as_multi_approve(s: u32, ) -> Weight { - (17_960_000 as Weight) + (18_032_000 as Weight) // Standard Error: 0 - .saturating_add((158_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((151_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -144,18 +144,18 @@ impl WeightInfo for SubstrateWeight { // Storage: Multisig Calls (r:1 w:1) // Storage: System Account (r:1 w:1) fn approve_as_multi_complete(s: u32, ) -> Weight { - (56_920_000 as Weight) + (56_353_000 as Weight) // Standard Error: 1_000 - .saturating_add((243_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((239_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Multisig Multisigs (r:1 w:1) // Storage: Multisig Calls (r:1 w:1) fn cancel_as_multi(s: u32, ) -> Weight { - (45_336_000 as Weight) - // Standard Error: 1_000 - .saturating_add((155_000 as Weight).saturating_mul(s as Weight)) + (44_544_000 as Weight) + // Standard Error: 0 + .saturating_add((158_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -164,16 +164,16 @@ impl WeightInfo for SubstrateWeight { // For backwards compatibility and tests impl WeightInfo for () { fn as_multi_threshold_1(z: u32, ) -> Weight { - (16_904_000 as Weight) + (16_534_000 as Weight) // Standard Error: 0 .saturating_add((1_000 as Weight).saturating_mul(z as Weight)) } // Storage: Multisig Multisigs (r:1 w:1) // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) fn as_multi_create(s: u32, z: u32, ) -> Weight { - (30_172_000 as Weight) - // Standard Error: 0 - .saturating_add((142_000 as Weight).saturating_mul(s as Weight)) + (30_917_000 as Weight) + // Standard Error: 1_000 + .saturating_add((131_000 as Weight).saturating_mul(s as Weight)) // Standard Error: 0 .saturating_add((1_000 as Weight).saturating_mul(z as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) @@ -183,9 +183,9 @@ impl WeightInfo for () { // Storage: Multisig Calls (r:1 w:1) // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) fn as_multi_create_store(s: u32, z: u32, ) -> Weight { - (33_039_000 as Weight) + (33_570_000 as Weight) // Standard Error: 1_000 - .saturating_add((140_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((138_000 as Weight).saturating_mul(s as Weight)) // Standard Error: 0 .saturating_add((2_000 as Weight).saturating_mul(z as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) @@ -193,9 +193,9 @@ impl WeightInfo for () { } // Storage: Multisig Multisigs (r:1 w:1) fn as_multi_approve(s: u32, z: u32, ) -> Weight { - (20_752_000 as Weight) + (21_051_000 as Weight) // Standard Error: 0 - .saturating_add((133_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((126_000 as Weight).saturating_mul(s as Weight)) // Standard Error: 0 .saturating_add((1_000 as Weight).saturating_mul(z as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) @@ -204,7 +204,7 @@ impl WeightInfo for () { // Storage: Multisig Multisigs (r:1 w:1) // Storage: Multisig Calls (r:1 w:1) fn as_multi_approve_store(s: u32, z: u32, ) -> Weight { - (33_198_000 as Weight) + (32_581_000 as Weight) // Standard Error: 1_000 .saturating_add((135_000 as Weight).saturating_mul(s as Weight)) // Standard Error: 0 @@ -216,9 +216,9 @@ impl WeightInfo for () { // Storage: Multisig Calls (r:1 w:1) // Storage: System Account (r:1 w:1) fn as_multi_complete(s: u32, z: u32, ) -> Weight { - (39_407_000 as Weight) + (39_215_000 as Weight) // Standard Error: 1_000 - .saturating_add((230_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((221_000 as Weight).saturating_mul(s as Weight)) // Standard Error: 0 .saturating_add((2_000 as Weight).saturating_mul(z as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) @@ -227,18 +227,18 @@ impl WeightInfo for () { // Storage: Multisig Multisigs (r:1 w:1) // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) fn approve_as_multi_create(s: u32, ) -> Weight { - (28_365_000 as Weight) + (28_572_000 as Weight) // Standard Error: 1_000 - .saturating_add((156_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((146_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Multisig Multisigs (r:1 w:1) // Storage: Multisig Calls (r:1 w:0) fn approve_as_multi_approve(s: u32, ) -> Weight { - (17_960_000 as Weight) + (18_032_000 as Weight) // Standard Error: 0 - .saturating_add((158_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((151_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -246,18 +246,18 @@ impl WeightInfo for () { // Storage: Multisig Calls (r:1 w:1) // Storage: System Account (r:1 w:1) fn approve_as_multi_complete(s: u32, ) -> Weight { - (56_920_000 as Weight) + (56_353_000 as Weight) // Standard Error: 1_000 - .saturating_add((243_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((239_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } // Storage: Multisig Multisigs (r:1 w:1) // Storage: Multisig Calls (r:1 w:1) fn cancel_as_multi(s: u32, ) -> Weight { - (45_336_000 as Weight) - // Standard Error: 1_000 - .saturating_add((155_000 as Weight).saturating_mul(s as Weight)) + (44_544_000 as Weight) + // Standard Error: 0 + .saturating_add((158_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } diff --git a/frame/preimage/src/weights.rs b/frame/preimage/src/weights.rs index b0f22a49297b..0d7f583727c9 100644 --- a/frame/preimage/src/weights.rs +++ b/frame/preimage/src/weights.rs @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_preimage //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-17, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-01-31, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/lto-fat-cg1/substrate +// ./target/production/substrate // benchmark // --chain=dev // --steps=50 @@ -34,7 +34,7 @@ // --heap-pages=4096 // --output=./frame/preimage/src/weights.rs // --template=.maintain/frame-weight-template.hbs -// --header=LICENSE-APACHE2 +// --header=HEADER-APACHE2 // --raw #![cfg_attr(rustfmt, rustfmt_skip)] @@ -93,58 +93,58 @@ impl WeightInfo for SubstrateWeight { // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:0 w:1) fn unnote_preimage() -> Weight { - (38_155_000 as Weight) + (39_239_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:0 w:1) fn unnote_no_deposit_preimage() -> Weight { - (24_132_000 as Weight) + (24_905_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Preimage StatusFor (r:1 w:1) fn request_preimage() -> Weight { - (36_703_000 as Weight) + (37_451_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Preimage StatusFor (r:1 w:1) fn request_no_deposit_preimage() -> Weight { - (23_056_000 as Weight) + (23_397_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Preimage StatusFor (r:1 w:1) fn request_unnoted_preimage() -> Weight { - (12_937_000 as Weight) + (13_407_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Preimage StatusFor (r:1 w:1) fn request_requested_preimage() -> Weight { - (4_460_000 as Weight) + (4_202_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:0 w:1) fn unrequest_preimage() -> Weight { - (23_761_000 as Weight) + (24_858_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:0 w:1) fn unrequest_unnoted_preimage() -> Weight { - (13_829_000 as Weight) + (13_763_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Preimage StatusFor (r:1 w:1) fn unrequest_multi_referenced_preimage() -> Weight { - (4_595_000 as Weight) + (4_262_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -182,58 +182,58 @@ impl WeightInfo for () { // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:0 w:1) fn unnote_preimage() -> Weight { - (38_155_000 as Weight) + (39_239_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:0 w:1) fn unnote_no_deposit_preimage() -> Weight { - (24_132_000 as Weight) + (24_905_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Preimage StatusFor (r:1 w:1) fn request_preimage() -> Weight { - (36_703_000 as Weight) + (37_451_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Preimage StatusFor (r:1 w:1) fn request_no_deposit_preimage() -> Weight { - (23_056_000 as Weight) + (23_397_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Preimage StatusFor (r:1 w:1) fn request_unnoted_preimage() -> Weight { - (12_937_000 as Weight) + (13_407_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Preimage StatusFor (r:1 w:1) fn request_requested_preimage() -> Weight { - (4_460_000 as Weight) + (4_202_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:0 w:1) fn unrequest_preimage() -> Weight { - (23_761_000 as Weight) + (24_858_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:0 w:1) fn unrequest_unnoted_preimage() -> Weight { - (13_829_000 as Weight) + (13_763_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Preimage StatusFor (r:1 w:1) fn unrequest_multi_referenced_preimage() -> Weight { - (4_595_000 as Weight) + (4_262_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } diff --git a/frame/proxy/src/weights.rs b/frame/proxy/src/weights.rs index 4628ada8d3c8..176f8683e0b5 100644 --- a/frame/proxy/src/weights.rs +++ b/frame/proxy/src/weights.rs @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_proxy //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-17, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-01-31, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/lto-fat-cg1/substrate +// ./target/production/substrate // benchmark // --chain=dev // --steps=50 @@ -34,7 +34,7 @@ // --heap-pages=4096 // --output=./frame/proxy/src/weights.rs // --template=.maintain/frame-weight-template.hbs -// --header=LICENSE-APACHE2 +// --header=HEADER-APACHE2 // --raw #![cfg_attr(rustfmt, rustfmt_skip)] @@ -63,42 +63,42 @@ pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { // Storage: Proxy Proxies (r:1 w:0) fn proxy(p: u32, ) -> Weight { - (13_623_000 as Weight) - // Standard Error: 2_000 - .saturating_add((121_000 as Weight).saturating_mul(p as Weight)) + (13_323_000 as Weight) + // Standard Error: 1_000 + .saturating_add((114_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) } // Storage: Proxy Proxies (r:1 w:0) // Storage: Proxy Announcements (r:1 w:1) // Storage: System Account (r:1 w:1) fn proxy_announced(a: u32, p: u32, ) -> Weight { - (29_560_000 as Weight) - // Standard Error: 2_000 - .saturating_add((259_000 as Weight).saturating_mul(a as Weight)) + (28_825_000 as Weight) + // Standard Error: 1_000 + .saturating_add((254_000 as Weight).saturating_mul(a as Weight)) // Standard Error: 2_000 - .saturating_add((121_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((120_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Proxy Announcements (r:1 w:1) // Storage: System Account (r:1 w:1) fn remove_announcement(a: u32, p: u32, ) -> Weight { - (21_004_000 as Weight) + (20_594_000 as Weight) // Standard Error: 1_000 - .saturating_add((266_000 as Weight).saturating_mul(a as Weight)) + .saturating_add((259_000 as Weight).saturating_mul(a as Weight)) // Standard Error: 1_000 - .saturating_add((13_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((15_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Proxy Announcements (r:1 w:1) // Storage: System Account (r:1 w:1) fn reject_announcement(a: u32, p: u32, ) -> Weight { - (20_992_000 as Weight) + (20_316_000 as Weight) // Standard Error: 1_000 - .saturating_add((266_000 as Weight).saturating_mul(a as Weight)) + .saturating_add((265_000 as Weight).saturating_mul(a as Weight)) // Standard Error: 1_000 - .saturating_add((14_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((18_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -106,52 +106,52 @@ impl WeightInfo for SubstrateWeight { // Storage: Proxy Announcements (r:1 w:1) // Storage: System Account (r:1 w:1) fn announce(a: u32, p: u32, ) -> Weight { - (28_118_000 as Weight) + (27_696_000 as Weight) // Standard Error: 2_000 - .saturating_add((250_000 as Weight).saturating_mul(a as Weight)) + .saturating_add((241_000 as Weight).saturating_mul(a as Weight)) // Standard Error: 2_000 - .saturating_add((118_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((111_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Proxy Proxies (r:1 w:1) fn add_proxy(p: u32, ) -> Weight { - (23_077_000 as Weight) + (22_849_000 as Weight) // Standard Error: 2_000 - .saturating_add((159_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((140_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Proxy Proxies (r:1 w:1) fn remove_proxy(p: u32, ) -> Weight { - (19_919_000 as Weight) + (19_350_000 as Weight) // Standard Error: 2_000 - .saturating_add((155_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((147_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Proxy Proxies (r:1 w:1) fn remove_proxies(p: u32, ) -> Weight { - (19_625_000 as Weight) + (18_878_000 as Weight) // Standard Error: 2_000 - .saturating_add((120_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((112_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) // Storage: Proxy Proxies (r:1 w:1) fn anonymous(p: u32, ) -> Weight { - (26_066_000 as Weight) + (25_743_000 as Weight) // Standard Error: 2_000 - .saturating_add((37_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((25_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Proxy Proxies (r:1 w:1) fn kill_anonymous(p: u32, ) -> Weight { - (21_294_000 as Weight) + (20_484_000 as Weight) // Standard Error: 2_000 - .saturating_add((112_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((105_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -161,42 +161,42 @@ impl WeightInfo for SubstrateWeight { impl WeightInfo for () { // Storage: Proxy Proxies (r:1 w:0) fn proxy(p: u32, ) -> Weight { - (13_623_000 as Weight) - // Standard Error: 2_000 - .saturating_add((121_000 as Weight).saturating_mul(p as Weight)) + (13_323_000 as Weight) + // Standard Error: 1_000 + .saturating_add((114_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) } // Storage: Proxy Proxies (r:1 w:0) // Storage: Proxy Announcements (r:1 w:1) // Storage: System Account (r:1 w:1) fn proxy_announced(a: u32, p: u32, ) -> Weight { - (29_560_000 as Weight) - // Standard Error: 2_000 - .saturating_add((259_000 as Weight).saturating_mul(a as Weight)) + (28_825_000 as Weight) + // Standard Error: 1_000 + .saturating_add((254_000 as Weight).saturating_mul(a as Weight)) // Standard Error: 2_000 - .saturating_add((121_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((120_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Proxy Announcements (r:1 w:1) // Storage: System Account (r:1 w:1) fn remove_announcement(a: u32, p: u32, ) -> Weight { - (21_004_000 as Weight) + (20_594_000 as Weight) // Standard Error: 1_000 - .saturating_add((266_000 as Weight).saturating_mul(a as Weight)) + .saturating_add((259_000 as Weight).saturating_mul(a as Weight)) // Standard Error: 1_000 - .saturating_add((13_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((15_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Proxy Announcements (r:1 w:1) // Storage: System Account (r:1 w:1) fn reject_announcement(a: u32, p: u32, ) -> Weight { - (20_992_000 as Weight) + (20_316_000 as Weight) // Standard Error: 1_000 - .saturating_add((266_000 as Weight).saturating_mul(a as Weight)) + .saturating_add((265_000 as Weight).saturating_mul(a as Weight)) // Standard Error: 1_000 - .saturating_add((14_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((18_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -204,52 +204,52 @@ impl WeightInfo for () { // Storage: Proxy Announcements (r:1 w:1) // Storage: System Account (r:1 w:1) fn announce(a: u32, p: u32, ) -> Weight { - (28_118_000 as Weight) + (27_696_000 as Weight) // Standard Error: 2_000 - .saturating_add((250_000 as Weight).saturating_mul(a as Weight)) + .saturating_add((241_000 as Weight).saturating_mul(a as Weight)) // Standard Error: 2_000 - .saturating_add((118_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((111_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Proxy Proxies (r:1 w:1) fn add_proxy(p: u32, ) -> Weight { - (23_077_000 as Weight) + (22_849_000 as Weight) // Standard Error: 2_000 - .saturating_add((159_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((140_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Proxy Proxies (r:1 w:1) fn remove_proxy(p: u32, ) -> Weight { - (19_919_000 as Weight) + (19_350_000 as Weight) // Standard Error: 2_000 - .saturating_add((155_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((147_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Proxy Proxies (r:1 w:1) fn remove_proxies(p: u32, ) -> Weight { - (19_625_000 as Weight) + (18_878_000 as Weight) // Standard Error: 2_000 - .saturating_add((120_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((112_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) // Storage: Proxy Proxies (r:1 w:1) fn anonymous(p: u32, ) -> Weight { - (26_066_000 as Weight) + (25_743_000 as Weight) // Standard Error: 2_000 - .saturating_add((37_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((25_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Proxy Proxies (r:1 w:1) fn kill_anonymous(p: u32, ) -> Weight { - (21_294_000 as Weight) + (20_484_000 as Weight) // Standard Error: 2_000 - .saturating_add((112_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((105_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } diff --git a/frame/scheduler/src/weights.rs b/frame/scheduler/src/weights.rs index 281b25977cf4..dd00b8dfe6cd 100644 --- a/frame/scheduler/src/weights.rs +++ b/frame/scheduler/src/weights.rs @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_scheduler //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-17, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-01-31, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/lto-fat-cg1/substrate +// ./target/production/substrate // benchmark // --chain=dev // --steps=50 @@ -34,7 +34,7 @@ // --heap-pages=4096 // --output=./frame/scheduler/src/weights.rs // --template=.maintain/frame-weight-template.hbs -// --header=LICENSE-APACHE2 +// --header=HEADER-APACHE2 // --raw #![cfg_attr(rustfmt, rustfmt_skip)] @@ -70,9 +70,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Preimage StatusFor (r:1 w:1) // Storage: Scheduler Lookup (r:0 w:1) fn on_initialize_periodic_named_resolved(s: u32, ) -> Weight { - (10_798_000 as Weight) - // Standard Error: 13_000 - .saturating_add((17_708_000 as Weight).saturating_mul(s as Weight)) + (11_587_000 as Weight) + // Standard Error: 17_000 + .saturating_add((17_428_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(s as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -83,9 +83,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Preimage StatusFor (r:1 w:1) // Storage: Scheduler Lookup (r:0 w:1) fn on_initialize_named_resolved(s: u32, ) -> Weight { - (8_722_000 as Weight) - // Standard Error: 10_000 - .saturating_add((13_706_000 as Weight).saturating_mul(s as Weight)) + (8_965_000 as Weight) + // Standard Error: 11_000 + .saturating_add((13_410_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(s as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -95,9 +95,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Preimage PreimageFor (r:1 w:1) // Storage: Preimage StatusFor (r:1 w:1) fn on_initialize_periodic_resolved(s: u32, ) -> Weight { - (9_414_000 as Weight) - // Standard Error: 9_000 - .saturating_add((15_176_000 as Weight).saturating_mul(s as Weight)) + (8_654_000 as Weight) + // Standard Error: 17_000 + .saturating_add((14_990_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(s as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -107,9 +107,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Preimage PreimageFor (r:1 w:1) // Storage: Preimage StatusFor (r:1 w:1) fn on_initialize_resolved(s: u32, ) -> Weight { - (9_572_000 as Weight) - // Standard Error: 12_000 - .saturating_add((12_505_000 as Weight).saturating_mul(s as Weight)) + (9_303_000 as Weight) + // Standard Error: 10_000 + .saturating_add((12_244_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(s as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -119,9 +119,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Preimage PreimageFor (r:1 w:0) // Storage: Scheduler Lookup (r:0 w:1) fn on_initialize_named_aborted(s: u32, ) -> Weight { - (6_900_000 as Weight) - // Standard Error: 4_000 - .saturating_add((5_486_000 as Weight).saturating_mul(s as Weight)) + (7_506_000 as Weight) + // Standard Error: 3_000 + .saturating_add((5_208_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -130,9 +130,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Scheduler Agenda (r:2 w:2) // Storage: Preimage PreimageFor (r:1 w:0) fn on_initialize_aborted(s: u32, ) -> Weight { - (8_346_000 as Weight) + (8_046_000 as Weight) // Standard Error: 3_000 - .saturating_add((3_079_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((2_914_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -140,9 +140,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Scheduler Agenda (r:2 w:2) // Storage: Scheduler Lookup (r:0 w:1) fn on_initialize_periodic_named(s: u32, ) -> Weight { - (13_462_000 as Weight) - // Standard Error: 5_000 - .saturating_add((8_230_000 as Weight).saturating_mul(s as Weight)) + (13_704_000 as Weight) + // Standard Error: 4_000 + .saturating_add((8_186_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -150,9 +150,9 @@ impl WeightInfo for SubstrateWeight { } // Storage: Scheduler Agenda (r:2 w:2) fn on_initialize_periodic(s: u32, ) -> Weight { - (13_046_000 as Weight) - // Standard Error: 4_000 - .saturating_add((5_782_000 as Weight).saturating_mul(s as Weight)) + (12_668_000 as Weight) + // Standard Error: 5_000 + .saturating_add((5_868_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -161,53 +161,53 @@ impl WeightInfo for SubstrateWeight { // Storage: Scheduler Agenda (r:1 w:1) // Storage: Scheduler Lookup (r:0 w:1) fn on_initialize_named(s: u32, ) -> Weight { - (13_481_000 as Weight) - // Standard Error: 3_000 - .saturating_add((4_385_000 as Weight).saturating_mul(s as Weight)) + (13_946_000 as Weight) + // Standard Error: 4_000 + .saturating_add((4_367_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) } // Storage: Scheduler Agenda (r:1 w:1) fn on_initialize(s: u32, ) -> Weight { - (13_081_000 as Weight) + (13_151_000 as Weight) // Standard Error: 4_000 - .saturating_add((3_434_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((3_455_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Scheduler Agenda (r:1 w:1) fn schedule(s: u32, ) -> Weight { - (13_863_000 as Weight) + (14_040_000 as Weight) // Standard Error: 1_000 - .saturating_add((87_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((89_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Scheduler Agenda (r:1 w:1) // Storage: Scheduler Lookup (r:0 w:1) fn cancel(s: u32, ) -> Weight { - (13_695_000 as Weight) + (14_376_000 as Weight) // Standard Error: 1_000 - .saturating_add((594_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((576_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Scheduler Lookup (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) fn schedule_named(s: u32, ) -> Weight { - (16_506_000 as Weight) + (16_806_000 as Weight) // Standard Error: 1_000 - .saturating_add((99_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((102_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Scheduler Lookup (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) fn cancel_named(s: u32, ) -> Weight { - (15_685_000 as Weight) + (15_852_000 as Weight) // Standard Error: 2_000 - .saturating_add((604_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((590_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -220,9 +220,9 @@ impl WeightInfo for () { // Storage: Preimage StatusFor (r:1 w:1) // Storage: Scheduler Lookup (r:0 w:1) fn on_initialize_periodic_named_resolved(s: u32, ) -> Weight { - (10_798_000 as Weight) - // Standard Error: 13_000 - .saturating_add((17_708_000 as Weight).saturating_mul(s as Weight)) + (11_587_000 as Weight) + // Standard Error: 17_000 + .saturating_add((17_428_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(s as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -233,9 +233,9 @@ impl WeightInfo for () { // Storage: Preimage StatusFor (r:1 w:1) // Storage: Scheduler Lookup (r:0 w:1) fn on_initialize_named_resolved(s: u32, ) -> Weight { - (8_722_000 as Weight) - // Standard Error: 10_000 - .saturating_add((13_706_000 as Weight).saturating_mul(s as Weight)) + (8_965_000 as Weight) + // Standard Error: 11_000 + .saturating_add((13_410_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(s as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -245,9 +245,9 @@ impl WeightInfo for () { // Storage: Preimage PreimageFor (r:1 w:1) // Storage: Preimage StatusFor (r:1 w:1) fn on_initialize_periodic_resolved(s: u32, ) -> Weight { - (9_414_000 as Weight) - // Standard Error: 9_000 - .saturating_add((15_176_000 as Weight).saturating_mul(s as Weight)) + (8_654_000 as Weight) + // Standard Error: 17_000 + .saturating_add((14_990_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(s as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -257,9 +257,9 @@ impl WeightInfo for () { // Storage: Preimage PreimageFor (r:1 w:1) // Storage: Preimage StatusFor (r:1 w:1) fn on_initialize_resolved(s: u32, ) -> Weight { - (9_572_000 as Weight) - // Standard Error: 12_000 - .saturating_add((12_505_000 as Weight).saturating_mul(s as Weight)) + (9_303_000 as Weight) + // Standard Error: 10_000 + .saturating_add((12_244_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(s as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -269,9 +269,9 @@ impl WeightInfo for () { // Storage: Preimage PreimageFor (r:1 w:0) // Storage: Scheduler Lookup (r:0 w:1) fn on_initialize_named_aborted(s: u32, ) -> Weight { - (6_900_000 as Weight) - // Standard Error: 4_000 - .saturating_add((5_486_000 as Weight).saturating_mul(s as Weight)) + (7_506_000 as Weight) + // Standard Error: 3_000 + .saturating_add((5_208_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) @@ -280,9 +280,9 @@ impl WeightInfo for () { // Storage: Scheduler Agenda (r:2 w:2) // Storage: Preimage PreimageFor (r:1 w:0) fn on_initialize_aborted(s: u32, ) -> Weight { - (8_346_000 as Weight) + (8_046_000 as Weight) // Standard Error: 3_000 - .saturating_add((3_079_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((2_914_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) @@ -290,9 +290,9 @@ impl WeightInfo for () { // Storage: Scheduler Agenda (r:2 w:2) // Storage: Scheduler Lookup (r:0 w:1) fn on_initialize_periodic_named(s: u32, ) -> Weight { - (13_462_000 as Weight) - // Standard Error: 5_000 - .saturating_add((8_230_000 as Weight).saturating_mul(s as Weight)) + (13_704_000 as Weight) + // Standard Error: 4_000 + .saturating_add((8_186_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -300,9 +300,9 @@ impl WeightInfo for () { } // Storage: Scheduler Agenda (r:2 w:2) fn on_initialize_periodic(s: u32, ) -> Weight { - (13_046_000 as Weight) - // Standard Error: 4_000 - .saturating_add((5_782_000 as Weight).saturating_mul(s as Weight)) + (12_668_000 as Weight) + // Standard Error: 5_000 + .saturating_add((5_868_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -311,53 +311,53 @@ impl WeightInfo for () { // Storage: Scheduler Agenda (r:1 w:1) // Storage: Scheduler Lookup (r:0 w:1) fn on_initialize_named(s: u32, ) -> Weight { - (13_481_000 as Weight) - // Standard Error: 3_000 - .saturating_add((4_385_000 as Weight).saturating_mul(s as Weight)) + (13_946_000 as Weight) + // Standard Error: 4_000 + .saturating_add((4_367_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) } // Storage: Scheduler Agenda (r:1 w:1) fn on_initialize(s: u32, ) -> Weight { - (13_081_000 as Weight) + (13_151_000 as Weight) // Standard Error: 4_000 - .saturating_add((3_434_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((3_455_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Scheduler Agenda (r:1 w:1) fn schedule(s: u32, ) -> Weight { - (13_863_000 as Weight) + (14_040_000 as Weight) // Standard Error: 1_000 - .saturating_add((87_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((89_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Scheduler Agenda (r:1 w:1) // Storage: Scheduler Lookup (r:0 w:1) fn cancel(s: u32, ) -> Weight { - (13_695_000 as Weight) + (14_376_000 as Weight) // Standard Error: 1_000 - .saturating_add((594_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((576_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Scheduler Lookup (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) fn schedule_named(s: u32, ) -> Weight { - (16_506_000 as Weight) + (16_806_000 as Weight) // Standard Error: 1_000 - .saturating_add((99_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((102_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Scheduler Lookup (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) fn cancel_named(s: u32, ) -> Weight { - (15_685_000 as Weight) + (15_852_000 as Weight) // Standard Error: 2_000 - .saturating_add((604_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((590_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } diff --git a/frame/session/src/weights.rs b/frame/session/src/weights.rs index 2cf5cd9c4192..39276fb0b17e 100644 --- a/frame/session/src/weights.rs +++ b/frame/session/src/weights.rs @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_session //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-17, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-01-31, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/lto-fat-cg1/substrate +// ./target/production/substrate // benchmark // --chain=dev // --steps=50 @@ -34,7 +34,7 @@ // --heap-pages=4096 // --output=./frame/session/src/weights.rs // --template=.maintain/frame-weight-template.hbs -// --header=LICENSE-APACHE2 +// --header=HEADER-APACHE2 // --raw #![cfg_attr(rustfmt, rustfmt_skip)] @@ -57,7 +57,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Session NextKeys (r:1 w:1) // Storage: Session KeyOwner (r:4 w:4) fn set_keys() -> Weight { - (42_449_000 as Weight) + (42_131_000 as Weight) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } @@ -65,7 +65,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Session NextKeys (r:1 w:1) // Storage: Session KeyOwner (r:0 w:4) fn purge_keys() -> Weight { - (32_778_000 as Weight) + (32_374_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } @@ -77,7 +77,7 @@ impl WeightInfo for () { // Storage: Session NextKeys (r:1 w:1) // Storage: Session KeyOwner (r:4 w:4) fn set_keys() -> Weight { - (42_449_000 as Weight) + (42_131_000 as Weight) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } @@ -85,7 +85,7 @@ impl WeightInfo for () { // Storage: Session NextKeys (r:1 w:1) // Storage: Session KeyOwner (r:0 w:4) fn purge_keys() -> Weight { - (32_778_000 as Weight) + (32_374_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } diff --git a/frame/staking/src/weights.rs b/frame/staking/src/weights.rs index 7721fbbd2371..42f762c721e4 100644 --- a/frame/staking/src/weights.rs +++ b/frame/staking/src/weights.rs @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_staking //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-01-31, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/lto-fat-cg1/substrate +// ./target/production/substrate // benchmark // --chain=dev // --steps=50 @@ -34,7 +34,7 @@ // --heap-pages=4096 // --output=./frame/staking/src/weights.rs // --template=.maintain/frame-weight-template.hbs -// --header=LICENSE-APACHE2 +// --header=HEADER-APACHE2 // --raw #![cfg_attr(rustfmt, rustfmt_skip)] @@ -86,7 +86,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Balances Locks (r:1 w:1) // Storage: Staking Payee (r:0 w:1) fn bond() -> Weight { - (38_457_000 as Weight) + (37_688_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } @@ -96,7 +96,7 @@ impl WeightInfo for SubstrateWeight { // Storage: BagsList ListNodes (r:3 w:3) // Storage: BagsList ListBags (r:2 w:2) fn bond_extra() -> Weight { - (65_678_000 as Weight) + (63_507_000 as Weight) .saturating_add(T::DbWeight::get().reads(8 as Weight)) .saturating_add(T::DbWeight::get().writes(7 as Weight)) } @@ -110,7 +110,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking Bonded (r:1 w:0) // Storage: BagsList ListBags (r:2 w:2) fn unbond() -> Weight { - (71_544_000 as Weight) + (70_634_000 as Weight) .saturating_add(T::DbWeight::get().reads(12 as Weight)) .saturating_add(T::DbWeight::get().writes(8 as Weight)) } @@ -119,9 +119,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn withdraw_unbonded_update(s: u32, ) -> Weight { - (30_127_000 as Weight) + (30_002_000 as Weight) // Standard Error: 0 - .saturating_add((59_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((55_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -139,7 +139,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Balances Locks (r:1 w:1) // Storage: Staking Payee (r:0 w:1) fn withdraw_unbonded_kill(_s: u32, ) -> Weight { - (59_131_000 as Weight) + (58_077_000 as Weight) .saturating_add(T::DbWeight::get().reads(13 as Weight)) .saturating_add(T::DbWeight::get().writes(11 as Weight)) } @@ -155,16 +155,16 @@ impl WeightInfo for SubstrateWeight { // Storage: BagsList CounterForListNodes (r:1 w:1) // Storage: Staking CounterForValidators (r:1 w:1) fn validate() -> Weight { - (45_519_000 as Weight) + (44_603_000 as Weight) .saturating_add(T::DbWeight::get().reads(12 as Weight)) .saturating_add(T::DbWeight::get().writes(8 as Weight)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking Nominators (r:1 w:1) fn kick(k: u32, ) -> Weight { - (16_645_000 as Weight) - // Standard Error: 12_000 - .saturating_add((8_194_000 as Weight).saturating_mul(k as Weight)) + (14_580_000 as Weight) + // Standard Error: 13_000 + .saturating_add((8_076_000 as Weight).saturating_mul(k as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(k as Weight))) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) @@ -181,9 +181,9 @@ impl WeightInfo for SubstrateWeight { // Storage: BagsList CounterForListNodes (r:1 w:1) // Storage: Staking CounterForNominators (r:1 w:1) fn nominate(n: u32, ) -> Weight { - (50_227_000 as Weight) - // Standard Error: 12_000 - .saturating_add((3_546_000 as Weight).saturating_mul(n as Weight)) + (49_856_000 as Weight) + // Standard Error: 8_000 + .saturating_add((3_430_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(12 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(n as Weight))) .saturating_add(T::DbWeight::get().writes(6 as Weight)) @@ -196,49 +196,49 @@ impl WeightInfo for SubstrateWeight { // Storage: BagsList ListBags (r:1 w:1) // Storage: BagsList CounterForListNodes (r:1 w:1) fn chill() -> Weight { - (44_294_000 as Weight) + (43_815_000 as Weight) .saturating_add(T::DbWeight::get().reads(8 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking Payee (r:0 w:1) fn set_payee() -> Weight { - (7_556_000 as Weight) + (7_553_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Staking Bonded (r:1 w:1) // Storage: Staking Ledger (r:2 w:2) fn set_controller() -> Weight { - (15_826_000 as Weight) + (15_177_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Staking ValidatorCount (r:0 w:1) fn set_validator_count() -> Weight { - (1_141_000 as Weight) + (1_090_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Staking ForceEra (r:0 w:1) fn force_no_eras() -> Weight { - (1_152_000 as Weight) + (1_169_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Staking ForceEra (r:0 w:1) fn force_new_era() -> Weight { - (1_169_000 as Weight) + (1_089_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Staking ForceEra (r:0 w:1) fn force_new_era_always() -> Weight { - (1_134_000 as Weight) + (1_144_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Staking Invulnerables (r:0 w:1) fn set_invulnerables(v: u32, ) -> Weight { - (1_641_000 as Weight) + (1_612_000 as Weight) // Standard Error: 0 - .saturating_add((52_000 as Weight).saturating_mul(v as Weight)) + .saturating_add((50_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Staking Bonded (r:1 w:1) @@ -255,18 +255,18 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking Payee (r:0 w:1) // Storage: Staking SpanSlash (r:0 w:2) fn force_unstake(s: u32, ) -> Weight { - (57_227_000 as Weight) + (56_103_000 as Weight) // Standard Error: 1_000 - .saturating_add((817_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((798_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(11 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) } // Storage: Staking UnappliedSlashes (r:1 w:1) fn cancel_deferred_slash(s: u32, ) -> Weight { - (950_241_000 as Weight) - // Standard Error: 56_000 - .saturating_add((4_960_000 as Weight).saturating_mul(s as Weight)) + (942_911_000 as Weight) + // Standard Error: 55_000 + .saturating_add((4_973_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -281,9 +281,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking Payee (r:2 w:0) // Storage: System Account (r:2 w:2) fn payout_stakers_dead_controller(n: u32, ) -> Weight { - (73_561_000 as Weight) + (77_948_000 as Weight) // Standard Error: 13_000 - .saturating_add((24_039_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((23_507_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(10 as Weight)) .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(n as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -301,9 +301,9 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:2 w:2) // Storage: Balances Locks (r:2 w:2) fn payout_stakers_alive_staked(n: u32, ) -> Weight { - (105_296_000 as Weight) - // Standard Error: 18_000 - .saturating_add((33_989_000 as Weight).saturating_mul(n as Weight)) + (94_386_000 as Weight) + // Standard Error: 19_000 + .saturating_add((32_763_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(11 as Weight)) .saturating_add(T::DbWeight::get().reads((5 as Weight).saturating_mul(n as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -316,9 +316,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking Bonded (r:1 w:0) // Storage: BagsList ListBags (r:2 w:2) fn rebond(l: u32, ) -> Weight { - (65_108_000 as Weight) - // Standard Error: 3_000 - .saturating_add((72_000 as Weight).saturating_mul(l as Weight)) + (63_577_000 as Weight) + // Standard Error: 2_000 + .saturating_add((47_000 as Weight).saturating_mul(l as Weight)) .saturating_add(T::DbWeight::get().reads(9 as Weight)) .saturating_add(T::DbWeight::get().writes(8 as Weight)) } @@ -333,8 +333,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking ErasStartSessionIndex (r:0 w:1) fn set_history_depth(e: u32, ) -> Weight { (0 as Weight) - // Standard Error: 54_000 - .saturating_add((19_731_000 as Weight).saturating_mul(e as Weight)) + // Standard Error: 57_000 + .saturating_add((19_691_000 as Weight).saturating_mul(e as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) .saturating_add(T::DbWeight::get().writes((7 as Weight).saturating_mul(e as Weight))) @@ -353,9 +353,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking Payee (r:0 w:1) // Storage: Staking SpanSlash (r:0 w:1) fn reap_stash(s: u32, ) -> Weight { - (63_115_000 as Weight) + (61_871_000 as Weight) // Standard Error: 0 - .saturating_add((812_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((796_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(12 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) @@ -380,10 +380,10 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking ErasStartSessionIndex (r:0 w:1) fn new_era(v: u32, n: u32, ) -> Weight { (0 as Weight) - // Standard Error: 800_000 - .saturating_add((219_877_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 40_000 - .saturating_add((31_701_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 823_000 + .saturating_add((218_725_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 41_000 + .saturating_add((31_349_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(208 as Weight)) .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(v as Weight))) .saturating_add(T::DbWeight::get().reads((4 as Weight).saturating_mul(n as Weight))) @@ -401,10 +401,12 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking Nominators (r:1000 w:0) fn get_npos_voters(v: u32, n: u32, s: u32, ) -> Weight { (0 as Weight) - // Standard Error: 88_000 - .saturating_add((18_183_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 88_000 - .saturating_add((21_345_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 86_000 + .saturating_add((18_168_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 86_000 + .saturating_add((21_061_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 2_951_000 + .saturating_add((8_164_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(204 as Weight)) .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(v as Weight))) .saturating_add(T::DbWeight::get().reads((4 as Weight).saturating_mul(n as Weight))) @@ -413,8 +415,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking Validators (r:501 w:0) fn get_npos_targets(v: u32, ) -> Weight { (0 as Weight) - // Standard Error: 25_000 - .saturating_add((7_691_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 29_000 + .saturating_add((7_761_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(v as Weight))) } @@ -425,12 +427,12 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking MaxNominatorsCount (r:0 w:1) // Storage: Staking MinNominatorBond (r:0 w:1) fn set_staking_configs() -> Weight { - (3_324_000 as Weight) + (3_586_000 as Weight) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } // Storage: Staking Ledger (r:1 w:0) - // Storage: Staking ChillThreshold (r:1 w:0) // Storage: Staking Nominators (r:1 w:1) + // Storage: Staking ChillThreshold (r:1 w:0) // Storage: Staking MaxNominatorsCount (r:1 w:0) // Storage: Staking CounterForNominators (r:1 w:1) // Storage: Staking MinNominatorBond (r:1 w:0) @@ -439,7 +441,7 @@ impl WeightInfo for SubstrateWeight { // Storage: BagsList ListBags (r:1 w:1) // Storage: BagsList CounterForListNodes (r:1 w:1) fn chill_other() -> Weight { - (54_254_000 as Weight) + (54_681_000 as Weight) .saturating_add(T::DbWeight::get().reads(11 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } @@ -454,7 +456,7 @@ impl WeightInfo for () { // Storage: Balances Locks (r:1 w:1) // Storage: Staking Payee (r:0 w:1) fn bond() -> Weight { - (38_457_000 as Weight) + (37_688_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } @@ -464,7 +466,7 @@ impl WeightInfo for () { // Storage: BagsList ListNodes (r:3 w:3) // Storage: BagsList ListBags (r:2 w:2) fn bond_extra() -> Weight { - (65_678_000 as Weight) + (63_507_000 as Weight) .saturating_add(RocksDbWeight::get().reads(8 as Weight)) .saturating_add(RocksDbWeight::get().writes(7 as Weight)) } @@ -478,7 +480,7 @@ impl WeightInfo for () { // Storage: Staking Bonded (r:1 w:0) // Storage: BagsList ListBags (r:2 w:2) fn unbond() -> Weight { - (71_544_000 as Weight) + (70_634_000 as Weight) .saturating_add(RocksDbWeight::get().reads(12 as Weight)) .saturating_add(RocksDbWeight::get().writes(8 as Weight)) } @@ -487,9 +489,9 @@ impl WeightInfo for () { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn withdraw_unbonded_update(s: u32, ) -> Weight { - (30_127_000 as Weight) + (30_002_000 as Weight) // Standard Error: 0 - .saturating_add((59_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((55_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -507,7 +509,7 @@ impl WeightInfo for () { // Storage: Balances Locks (r:1 w:1) // Storage: Staking Payee (r:0 w:1) fn withdraw_unbonded_kill(_s: u32, ) -> Weight { - (59_131_000 as Weight) + (58_077_000 as Weight) .saturating_add(RocksDbWeight::get().reads(13 as Weight)) .saturating_add(RocksDbWeight::get().writes(11 as Weight)) } @@ -523,16 +525,16 @@ impl WeightInfo for () { // Storage: BagsList CounterForListNodes (r:1 w:1) // Storage: Staking CounterForValidators (r:1 w:1) fn validate() -> Weight { - (45_519_000 as Weight) + (44_603_000 as Weight) .saturating_add(RocksDbWeight::get().reads(12 as Weight)) .saturating_add(RocksDbWeight::get().writes(8 as Weight)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking Nominators (r:1 w:1) fn kick(k: u32, ) -> Weight { - (16_645_000 as Weight) - // Standard Error: 12_000 - .saturating_add((8_194_000 as Weight).saturating_mul(k as Weight)) + (14_580_000 as Weight) + // Standard Error: 13_000 + .saturating_add((8_076_000 as Weight).saturating_mul(k as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(k as Weight))) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) @@ -549,9 +551,9 @@ impl WeightInfo for () { // Storage: BagsList CounterForListNodes (r:1 w:1) // Storage: Staking CounterForNominators (r:1 w:1) fn nominate(n: u32, ) -> Weight { - (50_227_000 as Weight) - // Standard Error: 12_000 - .saturating_add((3_546_000 as Weight).saturating_mul(n as Weight)) + (49_856_000 as Weight) + // Standard Error: 8_000 + .saturating_add((3_430_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(12 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(n as Weight))) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) @@ -564,49 +566,49 @@ impl WeightInfo for () { // Storage: BagsList ListBags (r:1 w:1) // Storage: BagsList CounterForListNodes (r:1 w:1) fn chill() -> Weight { - (44_294_000 as Weight) + (43_815_000 as Weight) .saturating_add(RocksDbWeight::get().reads(8 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking Payee (r:0 w:1) fn set_payee() -> Weight { - (7_556_000 as Weight) + (7_553_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Staking Bonded (r:1 w:1) // Storage: Staking Ledger (r:2 w:2) fn set_controller() -> Weight { - (15_826_000 as Weight) + (15_177_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } // Storage: Staking ValidatorCount (r:0 w:1) fn set_validator_count() -> Weight { - (1_141_000 as Weight) + (1_090_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Staking ForceEra (r:0 w:1) fn force_no_eras() -> Weight { - (1_152_000 as Weight) + (1_169_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Staking ForceEra (r:0 w:1) fn force_new_era() -> Weight { - (1_169_000 as Weight) + (1_089_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Staking ForceEra (r:0 w:1) fn force_new_era_always() -> Weight { - (1_134_000 as Weight) + (1_144_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Staking Invulnerables (r:0 w:1) fn set_invulnerables(v: u32, ) -> Weight { - (1_641_000 as Weight) + (1_612_000 as Weight) // Standard Error: 0 - .saturating_add((52_000 as Weight).saturating_mul(v as Weight)) + .saturating_add((50_000 as Weight).saturating_mul(v as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Staking Bonded (r:1 w:1) @@ -623,18 +625,18 @@ impl WeightInfo for () { // Storage: Staking Payee (r:0 w:1) // Storage: Staking SpanSlash (r:0 w:2) fn force_unstake(s: u32, ) -> Weight { - (57_227_000 as Weight) + (56_103_000 as Weight) // Standard Error: 1_000 - .saturating_add((817_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((798_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(11 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) } // Storage: Staking UnappliedSlashes (r:1 w:1) fn cancel_deferred_slash(s: u32, ) -> Weight { - (950_241_000 as Weight) - // Standard Error: 56_000 - .saturating_add((4_960_000 as Weight).saturating_mul(s as Weight)) + (942_911_000 as Weight) + // Standard Error: 55_000 + .saturating_add((4_973_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -649,9 +651,9 @@ impl WeightInfo for () { // Storage: Staking Payee (r:2 w:0) // Storage: System Account (r:2 w:2) fn payout_stakers_dead_controller(n: u32, ) -> Weight { - (73_561_000 as Weight) + (77_948_000 as Weight) // Standard Error: 13_000 - .saturating_add((24_039_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((23_507_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(10 as Weight)) .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(n as Weight))) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) @@ -669,9 +671,9 @@ impl WeightInfo for () { // Storage: System Account (r:2 w:2) // Storage: Balances Locks (r:2 w:2) fn payout_stakers_alive_staked(n: u32, ) -> Weight { - (105_296_000 as Weight) - // Standard Error: 18_000 - .saturating_add((33_989_000 as Weight).saturating_mul(n as Weight)) + (94_386_000 as Weight) + // Standard Error: 19_000 + .saturating_add((32_763_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(11 as Weight)) .saturating_add(RocksDbWeight::get().reads((5 as Weight).saturating_mul(n as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -684,9 +686,9 @@ impl WeightInfo for () { // Storage: Staking Bonded (r:1 w:0) // Storage: BagsList ListBags (r:2 w:2) fn rebond(l: u32, ) -> Weight { - (65_108_000 as Weight) - // Standard Error: 3_000 - .saturating_add((72_000 as Weight).saturating_mul(l as Weight)) + (63_577_000 as Weight) + // Standard Error: 2_000 + .saturating_add((47_000 as Weight).saturating_mul(l as Weight)) .saturating_add(RocksDbWeight::get().reads(9 as Weight)) .saturating_add(RocksDbWeight::get().writes(8 as Weight)) } @@ -701,8 +703,8 @@ impl WeightInfo for () { // Storage: Staking ErasStartSessionIndex (r:0 w:1) fn set_history_depth(e: u32, ) -> Weight { (0 as Weight) - // Standard Error: 54_000 - .saturating_add((19_731_000 as Weight).saturating_mul(e as Weight)) + // Standard Error: 57_000 + .saturating_add((19_691_000 as Weight).saturating_mul(e as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) .saturating_add(RocksDbWeight::get().writes((7 as Weight).saturating_mul(e as Weight))) @@ -721,9 +723,9 @@ impl WeightInfo for () { // Storage: Staking Payee (r:0 w:1) // Storage: Staking SpanSlash (r:0 w:1) fn reap_stash(s: u32, ) -> Weight { - (63_115_000 as Weight) + (61_871_000 as Weight) // Standard Error: 0 - .saturating_add((812_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((796_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(12 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) @@ -748,10 +750,10 @@ impl WeightInfo for () { // Storage: Staking ErasStartSessionIndex (r:0 w:1) fn new_era(v: u32, n: u32, ) -> Weight { (0 as Weight) - // Standard Error: 800_000 - .saturating_add((219_877_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 40_000 - .saturating_add((31_701_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 823_000 + .saturating_add((218_725_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 41_000 + .saturating_add((31_349_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(208 as Weight)) .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(v as Weight))) .saturating_add(RocksDbWeight::get().reads((4 as Weight).saturating_mul(n as Weight))) @@ -769,10 +771,12 @@ impl WeightInfo for () { // Storage: Staking Nominators (r:1000 w:0) fn get_npos_voters(v: u32, n: u32, s: u32, ) -> Weight { (0 as Weight) - // Standard Error: 88_000 - .saturating_add((18_183_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 88_000 - .saturating_add((21_345_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 86_000 + .saturating_add((18_168_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 86_000 + .saturating_add((21_061_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 2_951_000 + .saturating_add((8_164_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(204 as Weight)) .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(v as Weight))) .saturating_add(RocksDbWeight::get().reads((4 as Weight).saturating_mul(n as Weight))) @@ -781,8 +785,8 @@ impl WeightInfo for () { // Storage: Staking Validators (r:501 w:0) fn get_npos_targets(v: u32, ) -> Weight { (0 as Weight) - // Standard Error: 25_000 - .saturating_add((7_691_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 29_000 + .saturating_add((7_761_000 as Weight).saturating_mul(v as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(v as Weight))) } @@ -793,12 +797,12 @@ impl WeightInfo for () { // Storage: Staking MaxNominatorsCount (r:0 w:1) // Storage: Staking MinNominatorBond (r:0 w:1) fn set_staking_configs() -> Weight { - (3_324_000 as Weight) + (3_586_000 as Weight) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } // Storage: Staking Ledger (r:1 w:0) - // Storage: Staking ChillThreshold (r:1 w:0) // Storage: Staking Nominators (r:1 w:1) + // Storage: Staking ChillThreshold (r:1 w:0) // Storage: Staking MaxNominatorsCount (r:1 w:0) // Storage: Staking CounterForNominators (r:1 w:1) // Storage: Staking MinNominatorBond (r:1 w:0) @@ -807,7 +811,7 @@ impl WeightInfo for () { // Storage: BagsList ListBags (r:1 w:1) // Storage: BagsList CounterForListNodes (r:1 w:1) fn chill_other() -> Weight { - (54_254_000 as Weight) + (54_681_000 as Weight) .saturating_add(RocksDbWeight::get().reads(11 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } diff --git a/frame/system/src/weights.rs b/frame/system/src/weights.rs index 1fc35a41752a..a016fe6e7d03 100644 --- a/frame/system/src/weights.rs +++ b/frame/system/src/weights.rs @@ -18,11 +18,11 @@ //! Autogenerated weights for frame_system //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-19, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-01-31, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/optimized/substrate +// ./target/production/substrate // benchmark // --chain=dev // --steps=50 @@ -32,7 +32,7 @@ // --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./weights-optimized/frame/system/src//weights.rs +// --output=./frame/system/src/weights.rs // --template=.maintain/frame-weight-template.hbs // --header=HEADER-APACHE2 // --raw @@ -68,7 +68,7 @@ impl WeightInfo for SubstrateWeight { // Storage: System Digest (r:1 w:1) // Storage: unknown [0x3a686561707061676573] (r:0 w:1) fn set_heap_pages() -> Weight { - (2_821_000 as Weight) + (2_864_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -76,21 +76,21 @@ impl WeightInfo for SubstrateWeight { fn set_storage(i: u32, ) -> Weight { (0 as Weight) // Standard Error: 0 - .saturating_add((385_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((389_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(i as Weight))) } // Storage: Skipped Metadata (r:0 w:0) fn kill_storage(i: u32, ) -> Weight { (0 as Weight) // Standard Error: 0 - .saturating_add((286_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((285_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(i as Weight))) } // Storage: Skipped Metadata (r:0 w:0) fn kill_prefix(p: u32, ) -> Weight { - (1_292_000 as Weight) + (753_000 as Weight) // Standard Error: 0 - .saturating_add((633_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((630_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(p as Weight))) } } @@ -108,7 +108,7 @@ impl WeightInfo for () { // Storage: System Digest (r:1 w:1) // Storage: unknown [0x3a686561707061676573] (r:0 w:1) fn set_heap_pages() -> Weight { - (2_821_000 as Weight) + (2_864_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -116,21 +116,21 @@ impl WeightInfo for () { fn set_storage(i: u32, ) -> Weight { (0 as Weight) // Standard Error: 0 - .saturating_add((385_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((389_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(i as Weight))) } // Storage: Skipped Metadata (r:0 w:0) fn kill_storage(i: u32, ) -> Weight { (0 as Weight) // Standard Error: 0 - .saturating_add((286_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((285_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(i as Weight))) } // Storage: Skipped Metadata (r:0 w:0) fn kill_prefix(p: u32, ) -> Weight { - (1_292_000 as Weight) + (753_000 as Weight) // Standard Error: 0 - .saturating_add((633_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((630_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(p as Weight))) } } diff --git a/frame/timestamp/src/weights.rs b/frame/timestamp/src/weights.rs index b0f4b9d30588..33d7d6a4b9e3 100644 --- a/frame/timestamp/src/weights.rs +++ b/frame/timestamp/src/weights.rs @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_timestamp //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-01-31, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/lto-fat-cg1/substrate +// ./target/production/substrate // benchmark // --chain=dev // --steps=50 @@ -34,7 +34,7 @@ // --heap-pages=4096 // --output=./frame/timestamp/src/weights.rs // --template=.maintain/frame-weight-template.hbs -// --header=LICENSE-APACHE2 +// --header=HEADER-APACHE2 // --raw #![cfg_attr(rustfmt, rustfmt_skip)] @@ -56,12 +56,12 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:1) // Storage: Babe CurrentSlot (r:1 w:0) fn set() -> Weight { - (5_191_000 as Weight) + (5_247_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn on_finalize() -> Weight { - (2_563_000 as Weight) + (2_604_000 as Weight) } } @@ -70,11 +70,11 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:1) // Storage: Babe CurrentSlot (r:1 w:0) fn set() -> Weight { - (5_191_000 as Weight) + (5_247_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn on_finalize() -> Weight { - (2_563_000 as Weight) + (2_604_000 as Weight) } } diff --git a/frame/tips/src/weights.rs b/frame/tips/src/weights.rs index 154b6a67d854..2ba15a0c2fcc 100644 --- a/frame/tips/src/weights.rs +++ b/frame/tips/src/weights.rs @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_tips //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-01-31, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/lto-fat-cg1/substrate +// ./target/production/substrate // benchmark // --chain=dev // --steps=50 @@ -34,7 +34,7 @@ // --heap-pages=4096 // --output=./frame/tips/src/weights.rs // --template=.maintain/frame-weight-template.hbs -// --header=LICENSE-APACHE2 +// --header=HEADER-APACHE2 // --raw #![cfg_attr(rustfmt, rustfmt_skip)] @@ -60,7 +60,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Tips Reasons (r:1 w:1) // Storage: Tips Tips (r:1 w:1) fn report_awesome(r: u32, ) -> Weight { - (26_318_000 as Weight) + (25_262_000 as Weight) // Standard Error: 0 .saturating_add((2_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) @@ -69,7 +69,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Tips Tips (r:1 w:1) // Storage: Tips Reasons (r:0 w:1) fn retract_tip() -> Weight { - (24_688_000 as Weight) + (24_162_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -77,20 +77,20 @@ impl WeightInfo for SubstrateWeight { // Storage: Tips Reasons (r:1 w:1) // Storage: Tips Tips (r:0 w:1) fn tip_new(r: u32, t: u32, ) -> Weight { - (17_395_000 as Weight) + (16_435_000 as Weight) // Standard Error: 0 - .saturating_add((3_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_000 as Weight).saturating_mul(r as Weight)) // Standard Error: 4_000 - .saturating_add((197_000 as Weight).saturating_mul(t as Weight)) + .saturating_add((231_000 as Weight).saturating_mul(t as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Elections Members (r:1 w:0) // Storage: Tips Tips (r:1 w:1) fn tip(t: u32, ) -> Weight { - (10_783_000 as Weight) - // Standard Error: 6_000 - .saturating_add((568_000 as Weight).saturating_mul(t as Weight)) + (10_427_000 as Weight) + // Standard Error: 7_000 + .saturating_add((507_000 as Weight).saturating_mul(t as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -99,18 +99,18 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:1 w:1) // Storage: Tips Reasons (r:0 w:1) fn close_tip(t: u32, ) -> Weight { - (41_658_000 as Weight) - // Standard Error: 13_000 - .saturating_add((391_000 as Weight).saturating_mul(t as Weight)) + (40_901_000 as Weight) + // Standard Error: 10_000 + .saturating_add((281_000 as Weight).saturating_mul(t as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Tips Tips (r:1 w:1) // Storage: Tips Reasons (r:0 w:1) fn slash_tip(t: u32, ) -> Weight { - (14_935_000 as Weight) - // Standard Error: 6_000 - .saturating_add((40_000 as Weight).saturating_mul(t as Weight)) + (14_636_000 as Weight) + // Standard Error: 4_000 + .saturating_add((29_000 as Weight).saturating_mul(t as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -121,7 +121,7 @@ impl WeightInfo for () { // Storage: Tips Reasons (r:1 w:1) // Storage: Tips Tips (r:1 w:1) fn report_awesome(r: u32, ) -> Weight { - (26_318_000 as Weight) + (25_262_000 as Weight) // Standard Error: 0 .saturating_add((2_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) @@ -130,7 +130,7 @@ impl WeightInfo for () { // Storage: Tips Tips (r:1 w:1) // Storage: Tips Reasons (r:0 w:1) fn retract_tip() -> Weight { - (24_688_000 as Weight) + (24_162_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -138,20 +138,20 @@ impl WeightInfo for () { // Storage: Tips Reasons (r:1 w:1) // Storage: Tips Tips (r:0 w:1) fn tip_new(r: u32, t: u32, ) -> Weight { - (17_395_000 as Weight) + (16_435_000 as Weight) // Standard Error: 0 - .saturating_add((3_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_000 as Weight).saturating_mul(r as Weight)) // Standard Error: 4_000 - .saturating_add((197_000 as Weight).saturating_mul(t as Weight)) + .saturating_add((231_000 as Weight).saturating_mul(t as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Elections Members (r:1 w:0) // Storage: Tips Tips (r:1 w:1) fn tip(t: u32, ) -> Weight { - (10_783_000 as Weight) - // Standard Error: 6_000 - .saturating_add((568_000 as Weight).saturating_mul(t as Weight)) + (10_427_000 as Weight) + // Standard Error: 7_000 + .saturating_add((507_000 as Weight).saturating_mul(t as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -160,18 +160,18 @@ impl WeightInfo for () { // Storage: System Account (r:1 w:1) // Storage: Tips Reasons (r:0 w:1) fn close_tip(t: u32, ) -> Weight { - (41_658_000 as Weight) - // Standard Error: 13_000 - .saturating_add((391_000 as Weight).saturating_mul(t as Weight)) + (40_901_000 as Weight) + // Standard Error: 10_000 + .saturating_add((281_000 as Weight).saturating_mul(t as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } // Storage: Tips Tips (r:1 w:1) // Storage: Tips Reasons (r:0 w:1) fn slash_tip(t: u32, ) -> Weight { - (14_935_000 as Weight) - // Standard Error: 6_000 - .saturating_add((40_000 as Weight).saturating_mul(t as Weight)) + (14_636_000 as Weight) + // Standard Error: 4_000 + .saturating_add((29_000 as Weight).saturating_mul(t as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } diff --git a/frame/transaction-storage/src/weights.rs b/frame/transaction-storage/src/weights.rs index bdf4d2cf6222..a7033da7b80c 100644 --- a/frame/transaction-storage/src/weights.rs +++ b/frame/transaction-storage/src/weights.rs @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_transaction_storage //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-19, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-01-31, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/optimized/substrate +// ./target/production/substrate // benchmark // --chain=dev // --steps=50 @@ -32,7 +32,7 @@ // --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./weights-optimized/frame/transaction-storage/src//weights.rs +// --output=./frame/transaction-storage/src/weights.rs // --template=.maintain/frame-weight-template.hbs // --header=HEADER-APACHE2 // --raw @@ -74,7 +74,7 @@ impl WeightInfo for SubstrateWeight { // Storage: TransactionStorage BlockTransactions (r:1 w:1) // Storage: TransactionStorage MaxBlockTransactions (r:1 w:0) fn renew() -> Weight { - (43_773_000 as Weight) + (41_286_000 as Weight) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -84,7 +84,7 @@ impl WeightInfo for SubstrateWeight { // Storage: System ParentHash (r:1 w:0) // Storage: TransactionStorage Transactions (r:1 w:0) fn check_proof_max() -> Weight { - (139_490_000 as Weight) + (136_957_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -112,7 +112,7 @@ impl WeightInfo for () { // Storage: TransactionStorage BlockTransactions (r:1 w:1) // Storage: TransactionStorage MaxBlockTransactions (r:1 w:0) fn renew() -> Weight { - (43_773_000 as Weight) + (41_286_000 as Weight) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -122,7 +122,7 @@ impl WeightInfo for () { // Storage: System ParentHash (r:1 w:0) // Storage: TransactionStorage Transactions (r:1 w:0) fn check_proof_max() -> Weight { - (139_490_000 as Weight) + (136_957_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } diff --git a/frame/treasury/src/weights.rs b/frame/treasury/src/weights.rs index ebe823ddb8ce..dcbf5983fa65 100644 --- a/frame/treasury/src/weights.rs +++ b/frame/treasury/src/weights.rs @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_treasury //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-01-31, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/lto-fat-cg1/substrate +// ./target/production/substrate // benchmark // --chain=dev // --steps=50 @@ -34,7 +34,7 @@ // --heap-pages=4096 // --output=./frame/treasury/src/weights.rs // --template=.maintain/frame-weight-template.hbs -// --header=LICENSE-APACHE2 +// --header=HEADER-APACHE2 // --raw #![cfg_attr(rustfmt, rustfmt_skip)] @@ -58,23 +58,23 @@ impl WeightInfo for SubstrateWeight { // Storage: Treasury ProposalCount (r:1 w:1) // Storage: Treasury Proposals (r:0 w:1) fn propose_spend() -> Weight { - (21_666_000 as Weight) + (21_673_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Treasury Proposals (r:1 w:1) // Storage: System Account (r:1 w:1) fn reject_proposal() -> Weight { - (25_008_000 as Weight) + (25_353_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Treasury Proposals (r:1 w:0) // Storage: Treasury Approvals (r:1 w:1) fn approve_proposal(p: u32, ) -> Weight { - (8_032_000 as Weight) + (8_164_000 as Weight) // Standard Error: 1_000 - .saturating_add((66_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((57_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -83,9 +83,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Treasury Proposals (r:2 w:2) // Storage: System Account (r:4 w:4) fn on_initialize_proposals(p: u32, ) -> Weight { - (25_541_000 as Weight) - // Standard Error: 19_000 - .saturating_add((27_399_000 as Weight).saturating_mul(p as Weight)) + (20_762_000 as Weight) + // Standard Error: 21_000 + .saturating_add((26_835_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(p as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -98,23 +98,23 @@ impl WeightInfo for () { // Storage: Treasury ProposalCount (r:1 w:1) // Storage: Treasury Proposals (r:0 w:1) fn propose_spend() -> Weight { - (21_666_000 as Weight) + (21_673_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Treasury Proposals (r:1 w:1) // Storage: System Account (r:1 w:1) fn reject_proposal() -> Weight { - (25_008_000 as Weight) + (25_353_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Treasury Proposals (r:1 w:0) // Storage: Treasury Approvals (r:1 w:1) fn approve_proposal(p: u32, ) -> Weight { - (8_032_000 as Weight) + (8_164_000 as Weight) // Standard Error: 1_000 - .saturating_add((66_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((57_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -123,9 +123,9 @@ impl WeightInfo for () { // Storage: Treasury Proposals (r:2 w:2) // Storage: System Account (r:4 w:4) fn on_initialize_proposals(p: u32, ) -> Weight { - (25_541_000 as Weight) - // Standard Error: 19_000 - .saturating_add((27_399_000 as Weight).saturating_mul(p as Weight)) + (20_762_000 as Weight) + // Standard Error: 21_000 + .saturating_add((26_835_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(p as Weight))) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) diff --git a/frame/uniques/src/weights.rs b/frame/uniques/src/weights.rs index 190ce74bbaa5..1df8fe0ff665 100644 --- a/frame/uniques/src/weights.rs +++ b/frame/uniques/src/weights.rs @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_uniques //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-01-31, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/lto-fat-cg1/substrate +// ./target/production/substrate // benchmark // --chain=dev // --steps=50 @@ -34,7 +34,7 @@ // --heap-pages=4096 // --output=./frame/uniques/src/weights.rs // --template=.maintain/frame-weight-template.hbs -// --header=LICENSE-APACHE2 +// --header=HEADER-APACHE2 // --raw #![cfg_attr(rustfmt, rustfmt_skip)] @@ -76,14 +76,14 @@ impl WeightInfo for SubstrateWeight { // Storage: Uniques Class (r:1 w:1) // Storage: Uniques ClassAccount (r:0 w:1) fn create() -> Weight { - (23_715_000 as Weight) + (24_063_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Uniques Class (r:1 w:1) // Storage: Uniques ClassAccount (r:0 w:1) fn force_create() -> Weight { - (12_854_000 as Weight) + (13_017_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -96,12 +96,12 @@ impl WeightInfo for SubstrateWeight { // Storage: Uniques Account (r:0 w:20) fn destroy(n: u32, m: u32, a: u32, ) -> Weight { (0 as Weight) - // Standard Error: 13_000 - .saturating_add((9_291_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 13_000 - .saturating_add((957_000 as Weight).saturating_mul(m as Weight)) - // Standard Error: 13_000 - .saturating_add((862_000 as Weight).saturating_mul(a as Weight)) + // Standard Error: 14_000 + .saturating_add((9_248_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 14_000 + .saturating_add((854_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 14_000 + .saturating_add((758_000 as Weight).saturating_mul(a as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(n as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -113,7 +113,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Uniques Class (r:1 w:1) // Storage: Uniques Account (r:0 w:1) fn mint() -> Weight { - (29_659_000 as Weight) + (29_865_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -121,7 +121,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Uniques Asset (r:1 w:1) // Storage: Uniques Account (r:0 w:1) fn burn() -> Weight { - (31_363_000 as Weight) + (31_603_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -129,7 +129,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Uniques Asset (r:1 w:1) // Storage: Uniques Account (r:0 w:2) fn transfer() -> Weight { - (23_596_000 as Weight) + (23_331_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -137,8 +137,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Uniques Asset (r:100 w:100) fn redeposit(i: u32, ) -> Weight { (0 as Weight) - // Standard Error: 11_000 - .saturating_add((11_793_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 12_000 + .saturating_add((11_527_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -147,26 +147,26 @@ impl WeightInfo for SubstrateWeight { // Storage: Uniques Asset (r:1 w:1) // Storage: Uniques Class (r:1 w:0) fn freeze() -> Weight { - (17_708_000 as Weight) + (18_617_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Uniques Asset (r:1 w:1) // Storage: Uniques Class (r:1 w:0) fn thaw() -> Weight { - (17_959_000 as Weight) + (18_618_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Uniques Class (r:1 w:1) fn freeze_class() -> Weight { - (14_034_000 as Weight) + (13_570_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Uniques Class (r:1 w:1) fn thaw_class() -> Weight { - (13_751_000 as Weight) + (13_937_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -174,20 +174,20 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:1 w:1) // Storage: Uniques ClassAccount (r:0 w:2) fn transfer_ownership() -> Weight { - (31_328_000 as Weight) + (31_021_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } // Storage: Uniques Class (r:1 w:1) fn set_team() -> Weight { - (14_586_000 as Weight) + (14_739_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Uniques Class (r:1 w:1) // Storage: Uniques ClassAccount (r:0 w:1) fn force_asset_status() -> Weight { - (16_374_000 as Weight) + (16_826_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -195,7 +195,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Uniques InstanceMetadataOf (r:1 w:0) // Storage: Uniques Attribute (r:1 w:1) fn set_attribute() -> Weight { - (36_952_000 as Weight) + (37_010_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -203,49 +203,49 @@ impl WeightInfo for SubstrateWeight { // Storage: Uniques InstanceMetadataOf (r:1 w:0) // Storage: Uniques Attribute (r:1 w:1) fn clear_attribute() -> Weight { - (35_230_000 as Weight) + (34_432_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Uniques Class (r:1 w:1) // Storage: Uniques InstanceMetadataOf (r:1 w:1) fn set_metadata() -> Weight { - (28_148_000 as Weight) + (28_575_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Uniques Class (r:1 w:1) // Storage: Uniques InstanceMetadataOf (r:1 w:1) fn clear_metadata() -> Weight { - (29_027_000 as Weight) + (28_730_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Uniques Class (r:1 w:1) // Storage: Uniques ClassMetadataOf (r:1 w:1) fn set_class_metadata() -> Weight { - (27_535_000 as Weight) + (28_225_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Uniques Class (r:1 w:0) // Storage: Uniques ClassMetadataOf (r:1 w:1) fn clear_class_metadata() -> Weight { - (26_707_000 as Weight) + (26_455_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Uniques Class (r:1 w:0) // Storage: Uniques Asset (r:1 w:1) fn approve_transfer() -> Weight { - (19_108_000 as Weight) + (19_587_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Uniques Class (r:1 w:0) // Storage: Uniques Asset (r:1 w:1) fn cancel_approval() -> Weight { - (19_779_000 as Weight) + (19_417_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -256,14 +256,14 @@ impl WeightInfo for () { // Storage: Uniques Class (r:1 w:1) // Storage: Uniques ClassAccount (r:0 w:1) fn create() -> Weight { - (23_715_000 as Weight) + (24_063_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Uniques Class (r:1 w:1) // Storage: Uniques ClassAccount (r:0 w:1) fn force_create() -> Weight { - (12_854_000 as Weight) + (13_017_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -276,12 +276,12 @@ impl WeightInfo for () { // Storage: Uniques Account (r:0 w:20) fn destroy(n: u32, m: u32, a: u32, ) -> Weight { (0 as Weight) - // Standard Error: 13_000 - .saturating_add((9_291_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 13_000 - .saturating_add((957_000 as Weight).saturating_mul(m as Weight)) - // Standard Error: 13_000 - .saturating_add((862_000 as Weight).saturating_mul(a as Weight)) + // Standard Error: 14_000 + .saturating_add((9_248_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 14_000 + .saturating_add((854_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 14_000 + .saturating_add((758_000 as Weight).saturating_mul(a as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(n as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -293,7 +293,7 @@ impl WeightInfo for () { // Storage: Uniques Class (r:1 w:1) // Storage: Uniques Account (r:0 w:1) fn mint() -> Weight { - (29_659_000 as Weight) + (29_865_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -301,7 +301,7 @@ impl WeightInfo for () { // Storage: Uniques Asset (r:1 w:1) // Storage: Uniques Account (r:0 w:1) fn burn() -> Weight { - (31_363_000 as Weight) + (31_603_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -309,7 +309,7 @@ impl WeightInfo for () { // Storage: Uniques Asset (r:1 w:1) // Storage: Uniques Account (r:0 w:2) fn transfer() -> Weight { - (23_596_000 as Weight) + (23_331_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -317,8 +317,8 @@ impl WeightInfo for () { // Storage: Uniques Asset (r:100 w:100) fn redeposit(i: u32, ) -> Weight { (0 as Weight) - // Standard Error: 11_000 - .saturating_add((11_793_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 12_000 + .saturating_add((11_527_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -327,26 +327,26 @@ impl WeightInfo for () { // Storage: Uniques Asset (r:1 w:1) // Storage: Uniques Class (r:1 w:0) fn freeze() -> Weight { - (17_708_000 as Weight) + (18_617_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Uniques Asset (r:1 w:1) // Storage: Uniques Class (r:1 w:0) fn thaw() -> Weight { - (17_959_000 as Weight) + (18_618_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Uniques Class (r:1 w:1) fn freeze_class() -> Weight { - (14_034_000 as Weight) + (13_570_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Uniques Class (r:1 w:1) fn thaw_class() -> Weight { - (13_751_000 as Weight) + (13_937_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -354,20 +354,20 @@ impl WeightInfo for () { // Storage: System Account (r:1 w:1) // Storage: Uniques ClassAccount (r:0 w:2) fn transfer_ownership() -> Weight { - (31_328_000 as Weight) + (31_021_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } // Storage: Uniques Class (r:1 w:1) fn set_team() -> Weight { - (14_586_000 as Weight) + (14_739_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Uniques Class (r:1 w:1) // Storage: Uniques ClassAccount (r:0 w:1) fn force_asset_status() -> Weight { - (16_374_000 as Weight) + (16_826_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -375,7 +375,7 @@ impl WeightInfo for () { // Storage: Uniques InstanceMetadataOf (r:1 w:0) // Storage: Uniques Attribute (r:1 w:1) fn set_attribute() -> Weight { - (36_952_000 as Weight) + (37_010_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -383,49 +383,49 @@ impl WeightInfo for () { // Storage: Uniques InstanceMetadataOf (r:1 w:0) // Storage: Uniques Attribute (r:1 w:1) fn clear_attribute() -> Weight { - (35_230_000 as Weight) + (34_432_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Uniques Class (r:1 w:1) // Storage: Uniques InstanceMetadataOf (r:1 w:1) fn set_metadata() -> Weight { - (28_148_000 as Weight) + (28_575_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Uniques Class (r:1 w:1) // Storage: Uniques InstanceMetadataOf (r:1 w:1) fn clear_metadata() -> Weight { - (29_027_000 as Weight) + (28_730_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Uniques Class (r:1 w:1) // Storage: Uniques ClassMetadataOf (r:1 w:1) fn set_class_metadata() -> Weight { - (27_535_000 as Weight) + (28_225_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Uniques Class (r:1 w:0) // Storage: Uniques ClassMetadataOf (r:1 w:1) fn clear_class_metadata() -> Weight { - (26_707_000 as Weight) + (26_455_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Uniques Class (r:1 w:0) // Storage: Uniques Asset (r:1 w:1) fn approve_transfer() -> Weight { - (19_108_000 as Weight) + (19_587_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Uniques Class (r:1 w:0) // Storage: Uniques Asset (r:1 w:1) fn cancel_approval() -> Weight { - (19_779_000 as Weight) + (19_417_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } diff --git a/frame/utility/src/weights.rs b/frame/utility/src/weights.rs index 3d80691210de..e5f3cb0f58fd 100644 --- a/frame/utility/src/weights.rs +++ b/frame/utility/src/weights.rs @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_utility //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-01-31, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/lto-fat-cg1/substrate +// ./target/production/substrate // benchmark // --chain=dev // --steps=50 @@ -34,7 +34,7 @@ // --heap-pages=4096 // --output=./frame/utility/src/weights.rs // --template=.maintain/frame-weight-template.hbs -// --header=LICENSE-APACHE2 +// --header=HEADER-APACHE2 // --raw #![cfg_attr(rustfmt, rustfmt_skip)] @@ -56,39 +56,39 @@ pub trait WeightInfo { pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { fn batch(c: u32, ) -> Weight { - (15_877_000 as Weight) + (18_598_000 as Weight) // Standard Error: 1_000 - .saturating_add((2_341_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((2_374_000 as Weight).saturating_mul(c as Weight)) } fn as_derivative() -> Weight { - (1_754_000 as Weight) + (1_650_000 as Weight) } fn batch_all(c: u32, ) -> Weight { - (16_581_000 as Weight) + (13_988_000 as Weight) // Standard Error: 1_000 - .saturating_add((2_476_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((2_481_000 as Weight).saturating_mul(c as Weight)) } fn dispatch_as() -> Weight { - (8_294_000 as Weight) + (8_463_000 as Weight) } } // For backwards compatibility and tests impl WeightInfo for () { fn batch(c: u32, ) -> Weight { - (15_877_000 as Weight) + (18_598_000 as Weight) // Standard Error: 1_000 - .saturating_add((2_341_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((2_374_000 as Weight).saturating_mul(c as Weight)) } fn as_derivative() -> Weight { - (1_754_000 as Weight) + (1_650_000 as Weight) } fn batch_all(c: u32, ) -> Weight { - (16_581_000 as Weight) + (13_988_000 as Weight) // Standard Error: 1_000 - .saturating_add((2_476_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((2_481_000 as Weight).saturating_mul(c as Weight)) } fn dispatch_as() -> Weight { - (8_294_000 as Weight) + (8_463_000 as Weight) } } diff --git a/frame/vesting/src/weights.rs b/frame/vesting/src/weights.rs index caf1880daefd..140c1889d6e5 100644 --- a/frame/vesting/src/weights.rs +++ b/frame/vesting/src/weights.rs @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_vesting //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-01-31, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/lto-fat-cg1/substrate +// ./target/production/substrate // benchmark // --chain=dev // --steps=50 @@ -34,7 +34,7 @@ // --heap-pages=4096 // --output=./frame/vesting/src/weights.rs // --template=.maintain/frame-weight-template.hbs -// --header=LICENSE-APACHE2 +// --header=HEADER-APACHE2 // --raw #![cfg_attr(rustfmt, rustfmt_skip)] @@ -62,22 +62,22 @@ impl WeightInfo for SubstrateWeight { // Storage: Vesting Vesting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vest_locked(l: u32, s: u32, ) -> Weight { - (27_545_000 as Weight) + (27_037_000 as Weight) // Standard Error: 1_000 - .saturating_add((111_000 as Weight).saturating_mul(l as Weight)) + .saturating_add((88_000 as Weight).saturating_mul(l as Weight)) // Standard Error: 2_000 - .saturating_add((78_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((69_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Vesting Vesting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vest_unlocked(l: u32, s: u32, ) -> Weight { - (27_638_000 as Weight) + (26_627_000 as Weight) // Standard Error: 1_000 - .saturating_add((102_000 as Weight).saturating_mul(l as Weight)) + .saturating_add((82_000 as Weight).saturating_mul(l as Weight)) // Standard Error: 2_000 - .saturating_add((41_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((53_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -85,11 +85,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn vest_other_locked(l: u32, s: u32, ) -> Weight { - (27_571_000 as Weight) + (26_672_000 as Weight) // Standard Error: 1_000 - .saturating_add((105_000 as Weight).saturating_mul(l as Weight)) + .saturating_add((85_000 as Weight).saturating_mul(l as Weight)) // Standard Error: 2_000 - .saturating_add((76_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((77_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -97,11 +97,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn vest_other_unlocked(l: u32, s: u32, ) -> Weight { - (27_470_000 as Weight) + (26_682_000 as Weight) // Standard Error: 1_000 - .saturating_add((99_000 as Weight).saturating_mul(l as Weight)) + .saturating_add((74_000 as Weight).saturating_mul(l as Weight)) // Standard Error: 2_000 - .saturating_add((48_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((51_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -109,11 +109,11 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vested_transfer(l: u32, s: u32, ) -> Weight { - (42_886_000 as Weight) + (42_066_000 as Weight) // Standard Error: 1_000 - .saturating_add((100_000 as Weight).saturating_mul(l as Weight)) + .saturating_add((83_000 as Weight).saturating_mul(l as Weight)) // Standard Error: 3_000 - .saturating_add((49_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((43_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -121,9 +121,9 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:2 w:2) // Storage: Balances Locks (r:1 w:1) fn force_vested_transfer(l: u32, s: u32, ) -> Weight { - (42_528_000 as Weight) + (41_672_000 as Weight) // Standard Error: 1_000 - .saturating_add((104_000 as Weight).saturating_mul(l as Weight)) + .saturating_add((84_000 as Weight).saturating_mul(l as Weight)) // Standard Error: 3_000 .saturating_add((46_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) @@ -133,11 +133,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn not_unlocking_merge_schedules(l: u32, s: u32, ) -> Weight { - (28_372_000 as Weight) - // Standard Error: 1_000 - .saturating_add((110_000 as Weight).saturating_mul(l as Weight)) + (27_627_000 as Weight) + // Standard Error: 0 + .saturating_add((86_000 as Weight).saturating_mul(l as Weight)) // Standard Error: 2_000 - .saturating_add((71_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((68_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -145,11 +145,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn unlocking_merge_schedules(l: u32, s: u32, ) -> Weight { - (28_117_000 as Weight) + (27_143_000 as Weight) + // Standard Error: 0 + .saturating_add((88_000 as Weight).saturating_mul(l as Weight)) // Standard Error: 1_000 - .saturating_add((108_000 as Weight).saturating_mul(l as Weight)) - // Standard Error: 2_000 - .saturating_add((76_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((72_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -160,22 +160,22 @@ impl WeightInfo for () { // Storage: Vesting Vesting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vest_locked(l: u32, s: u32, ) -> Weight { - (27_545_000 as Weight) + (27_037_000 as Weight) // Standard Error: 1_000 - .saturating_add((111_000 as Weight).saturating_mul(l as Weight)) + .saturating_add((88_000 as Weight).saturating_mul(l as Weight)) // Standard Error: 2_000 - .saturating_add((78_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((69_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Vesting Vesting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vest_unlocked(l: u32, s: u32, ) -> Weight { - (27_638_000 as Weight) + (26_627_000 as Weight) // Standard Error: 1_000 - .saturating_add((102_000 as Weight).saturating_mul(l as Weight)) + .saturating_add((82_000 as Weight).saturating_mul(l as Weight)) // Standard Error: 2_000 - .saturating_add((41_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((53_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -183,11 +183,11 @@ impl WeightInfo for () { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn vest_other_locked(l: u32, s: u32, ) -> Weight { - (27_571_000 as Weight) + (26_672_000 as Weight) // Standard Error: 1_000 - .saturating_add((105_000 as Weight).saturating_mul(l as Weight)) + .saturating_add((85_000 as Weight).saturating_mul(l as Weight)) // Standard Error: 2_000 - .saturating_add((76_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((77_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -195,11 +195,11 @@ impl WeightInfo for () { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn vest_other_unlocked(l: u32, s: u32, ) -> Weight { - (27_470_000 as Weight) + (26_682_000 as Weight) // Standard Error: 1_000 - .saturating_add((99_000 as Weight).saturating_mul(l as Weight)) + .saturating_add((74_000 as Weight).saturating_mul(l as Weight)) // Standard Error: 2_000 - .saturating_add((48_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((51_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -207,11 +207,11 @@ impl WeightInfo for () { // Storage: System Account (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vested_transfer(l: u32, s: u32, ) -> Weight { - (42_886_000 as Weight) + (42_066_000 as Weight) // Standard Error: 1_000 - .saturating_add((100_000 as Weight).saturating_mul(l as Weight)) + .saturating_add((83_000 as Weight).saturating_mul(l as Weight)) // Standard Error: 3_000 - .saturating_add((49_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((43_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -219,9 +219,9 @@ impl WeightInfo for () { // Storage: System Account (r:2 w:2) // Storage: Balances Locks (r:1 w:1) fn force_vested_transfer(l: u32, s: u32, ) -> Weight { - (42_528_000 as Weight) + (41_672_000 as Weight) // Standard Error: 1_000 - .saturating_add((104_000 as Weight).saturating_mul(l as Weight)) + .saturating_add((84_000 as Weight).saturating_mul(l as Weight)) // Standard Error: 3_000 .saturating_add((46_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) @@ -231,11 +231,11 @@ impl WeightInfo for () { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn not_unlocking_merge_schedules(l: u32, s: u32, ) -> Weight { - (28_372_000 as Weight) - // Standard Error: 1_000 - .saturating_add((110_000 as Weight).saturating_mul(l as Weight)) + (27_627_000 as Weight) + // Standard Error: 0 + .saturating_add((86_000 as Weight).saturating_mul(l as Weight)) // Standard Error: 2_000 - .saturating_add((71_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((68_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -243,11 +243,11 @@ impl WeightInfo for () { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn unlocking_merge_schedules(l: u32, s: u32, ) -> Weight { - (28_117_000 as Weight) + (27_143_000 as Weight) + // Standard Error: 0 + .saturating_add((88_000 as Weight).saturating_mul(l as Weight)) // Standard Error: 1_000 - .saturating_add((108_000 as Weight).saturating_mul(l as Weight)) - // Standard Error: 2_000 - .saturating_add((76_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((72_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } diff --git a/utils/wasm-builder/Cargo.toml b/utils/wasm-builder/Cargo.toml index a2a56a5bf22c..ce9687f9ae0e 100644 --- a/utils/wasm-builder/Cargo.toml +++ b/utils/wasm-builder/Cargo.toml @@ -21,3 +21,4 @@ walkdir = "2.3.2" wasm-gc-api = "0.1.11" ansi_term = "0.12.1" sp-maybe-compressed-blob = { version = "4.1.0-dev", path = "../../primitives/maybe-compressed-blob" } +strum = { version = "0.23.0", features = ["derive"] } diff --git a/utils/wasm-builder/src/lib.rs b/utils/wasm-builder/src/lib.rs index f5e04dd7d774..6a7f0d7ca3cd 100644 --- a/utils/wasm-builder/src/lib.rs +++ b/utils/wasm-builder/src/lib.rs @@ -120,9 +120,11 @@ pub use builder::{WasmBuilder, WasmBuilderSelectProject}; const SKIP_BUILD_ENV: &str = "SKIP_WASM_BUILD"; /// Environment variable to force a certain build type when building the wasm binary. -/// Expects "debug" or "release" as value. +/// Expects "debug", "release" or "production" as value. /// -/// By default the WASM binary uses the same build type as the main cargo build. +/// When unset the WASM binary uses the same build type as the main cargo build with +/// the exception of a debug build: In this case the wasm build defaults to `release` in +/// order to avoid a slowdown when not explicitly requested. const WASM_BUILD_TYPE_ENV: &str = "WASM_BUILD_TYPE"; /// Environment variable to extend the `RUSTFLAGS` variable given to the wasm build. diff --git a/utils/wasm-builder/src/wasm_project.rs b/utils/wasm-builder/src/wasm_project.rs index 9b5a33b6a623..541c6290166c 100644 --- a/utils/wasm-builder/src/wasm_project.rs +++ b/utils/wasm-builder/src/wasm_project.rs @@ -17,6 +17,8 @@ use crate::{write_file_if_changed, CargoCommandVersioned}; +use build_helper::rerun_if_changed; +use cargo_metadata::{CargoOpt, Metadata, MetadataCommand}; use std::{ borrow::ToOwned, collections::HashSet, @@ -26,13 +28,8 @@ use std::{ path::{Path, PathBuf}, process, }; - +use strum::{EnumIter, IntoEnumIterator}; use toml::value::Table; - -use build_helper::rerun_if_changed; - -use cargo_metadata::{CargoOpt, Metadata, MetadataCommand}; - use walkdir::WalkDir; /// Colorize an info message. @@ -128,9 +125,9 @@ pub(crate) fn create_and_compile( features_to_enable, ); - build_project(&project, default_rustflags, cargo_cmd); + let profile = build_project(&project, default_rustflags, cargo_cmd); let (wasm_binary, wasm_binary_compressed, bloaty) = - compact_wasm_file(&project, project_cargo_toml, wasm_binary_name); + compact_wasm_file(&project, profile, project_cargo_toml, wasm_binary_name); wasm_binary .as_ref() @@ -246,16 +243,22 @@ fn create_project_cargo_toml( let mut wasm_workspace_toml = Table::new(); - // Add `profile` with release and dev + // Add different profiles which are selected by setting `WASM_BUILD_TYPE`. let mut release_profile = Table::new(); release_profile.insert("panic".into(), "abort".into()); - release_profile.insert("lto".into(), true.into()); + release_profile.insert("lto".into(), "thin".into()); + + let mut production_profile = Table::new(); + production_profile.insert("inherits".into(), "release".into()); + production_profile.insert("lto".into(), "fat".into()); + production_profile.insert("codegen-units".into(), 1.into()); let mut dev_profile = Table::new(); dev_profile.insert("panic".into(), "abort".into()); let mut profile = Table::new(); profile.insert("release".into(), release_profile.into()); + profile.insert("production".into(), production_profile.into()); profile.insert("dev".into(), dev_profile.into()); wasm_workspace_toml.insert("profile".into(), profile.into()); @@ -420,25 +423,106 @@ fn create_project( wasm_project_folder } -/// Returns if the project should be built as a release. -fn is_release_build() -> bool { - if let Ok(var) = env::var(crate::WASM_BUILD_TYPE_ENV) { - match var.as_str() { - "release" => true, - "debug" => false, - var => panic!( - "Unexpected value for `{}` env variable: {}\nOne of the following are expected: `debug` or `release`.", - crate::WASM_BUILD_TYPE_ENV, - var, - ), +/// The cargo profile that is used to build the wasm project. +#[derive(Debug, EnumIter)] +enum Profile { + /// The `--profile dev` profile. + Debug, + /// The `--profile release` profile. + Release, + /// The `--profile production` profile. + Production, +} + +impl Profile { + /// Create a profile by detecting which profile is used for the main build. + /// + /// We cannot easily determine the profile that is used by the main cargo invocation + /// because the `PROFILE` environment variable won't contain any custom profiles like + /// "production". It would only contain the builtin profile where the custom profile + /// inherits from. This is why we inspect the build path to learn which profile is used. + /// + /// # Note + /// + /// Can be overriden by setting [`crate::WASM_BUILD_TYPE_ENV`]. + fn detect(wasm_project: &Path) -> Profile { + let (name, overriden) = if let Ok(name) = env::var(crate::WASM_BUILD_TYPE_ENV) { + (name, true) + } else { + // First go backwards to the beginning of the target directory. + // Then go forwards to find the "wbuild" directory. + // We need to go backwards first because when starting from the root there + // might be a chance that someone has a "wbuild" directory somewhere in the path. + let name = wasm_project + .components() + .rev() + .take_while(|c| c.as_os_str() != "target") + .collect::>() + .iter() + .rev() + .take_while(|c| c.as_os_str() != "wbuild") + .last() + .expect("We put the wasm project within a `target/.../wbuild` path; qed") + .as_os_str() + .to_str() + .expect("All our profile directory names are ascii; qed") + .to_string(); + (name, false) + }; + match (Profile::iter().find(|p| p.directory() == name), overriden) { + // When not overriden by a env variable we default to using the `Release` profile + // for the wasm build even when the main build uses the debug build. This + // is because the `Debug` profile is too slow for normal development activities. + (Some(Profile::Debug), false) => Profile::Release, + // For any other profile or when overriden we take it at face value. + (Some(profile), _) => profile, + // Invalid profile specified. + (None, _) => { + // We use println! + exit instead of a panic in order to have a cleaner output. + println!( + "Unexpected profile name: `{}`. One of the following is expected: {:?}", + name, + Profile::iter().map(|p| p.directory()).collect::>(), + ); + process::exit(1); + }, } - } else { - true + } + + /// The name of the profile as supplied to the cargo `--profile` cli option. + fn name(&self) -> &'static str { + match self { + Self::Debug => "dev", + Self::Release => "release", + Self::Production => "production", + } + } + + /// The sub directory within `target` where cargo places the build output. + /// + /// # Note + /// + /// Usually this is the same as [`Self::name`] with the exception of the debug + /// profile which is called `dev`. + fn directory(&self) -> &'static str { + match self { + Self::Debug => "debug", + _ => self.name(), + } + } + + /// Whether the resulting binary should be compacted and compressed. + fn wants_compact(&self) -> bool { + !matches!(self, Self::Debug) } } /// Build the project to create the WASM binary. -fn build_project(project: &Path, default_rustflags: &str, cargo_cmd: CargoCommandVersioned) { +fn build_project( + project: &Path, + default_rustflags: &str, + cargo_cmd: CargoCommandVersioned, +) -> Profile { let manifest_path = project.join("Cargo.toml"); let mut build_cmd = cargo_cmd.command(); @@ -467,16 +551,16 @@ fn build_project(project: &Path, default_rustflags: &str, cargo_cmd: CargoComman build_cmd.arg("--color=always"); } - if is_release_build() { - build_cmd.arg("--release"); - }; + let profile = Profile::detect(project); + build_cmd.arg("--profile"); + build_cmd.arg(profile.name()); println!("{}", colorize_info_message("Information that should be included in a bug report.")); println!("{} {:?}", colorize_info_message("Executing build command:"), build_cmd); println!("{} {}", colorize_info_message("Using rustc version:"), cargo_cmd.rustc_version()); match build_cmd.status().map(|s| s.success()) { - Ok(true) => {}, + Ok(true) => profile, // Use `process.exit(1)` to have a clean error output. _ => process::exit(1), } @@ -485,18 +569,17 @@ fn build_project(project: &Path, default_rustflags: &str, cargo_cmd: CargoComman /// Compact the WASM binary using `wasm-gc` and compress it using zstd. fn compact_wasm_file( project: &Path, + profile: Profile, cargo_manifest: &Path, wasm_binary_name: Option, ) -> (Option, Option, WasmBinaryBloaty) { - let is_release_build = is_release_build(); - let target = if is_release_build { "release" } else { "debug" }; let default_wasm_binary_name = get_wasm_binary_name(cargo_manifest); let wasm_file = project .join("target/wasm32-unknown-unknown") - .join(target) + .join(profile.directory()) .join(format!("{}.wasm", default_wasm_binary_name)); - let wasm_compact_file = if is_release_build { + let wasm_compact_file = if profile.wants_compact() { let wasm_compact_file = project.join(format!( "{}.compact.wasm", wasm_binary_name.clone().unwrap_or_else(|| default_wasm_binary_name.clone()), @@ -687,11 +770,13 @@ fn copy_wasm_to_target_directory(cargo_manifest: &Path, wasm_binary: &WasmBinary }; if !target_dir.is_absolute() { - panic!( + // We use println! + exit instead of a panic in order to have a cleaner output. + println!( "Environment variable `{}` with `{}` is not an absolute path!", crate::WASM_TARGET_DIRECTORY, target_dir.display(), ); + process::exit(1); } fs::create_dir_all(&target_dir).expect("Creates `WASM_TARGET_DIRECTORY`."); From 2c4549689dbb86c23725dac2f82af35faa07c9f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Mon, 31 Jan 2022 21:04:12 +0100 Subject: [PATCH 439/695] Bump `strum` from 0.22 -> 0.23 (#10758) --- Cargo.lock | 32 +++---------------- client/beefy/Cargo.toml | 2 +- .../election-provider-multi-phase/Cargo.toml | 8 +++-- .../election-provider-multi-phase/src/lib.rs | 4 +-- primitives/keyring/Cargo.toml | 2 +- 5 files changed, 14 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 773b77036225..a45b3bf3289c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -508,7 +508,7 @@ dependencies = [ "sp-keystore", "sp-runtime", "sp-tracing", - "strum 0.22.0", + "strum", "substrate-prometheus-endpoint", "thiserror", "wasm-timer", @@ -5710,8 +5710,7 @@ dependencies = [ "sp-std", "sp-tracing", "static_assertions", - "strum 0.22.0", - "strum_macros 0.23.1", + "strum", ] [[package]] @@ -9742,7 +9741,7 @@ dependencies = [ "lazy_static", "sp-core", "sp-runtime", - "strum 0.22.0", + "strum", ] [[package]] @@ -10210,34 +10209,13 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" -[[package]] -name = "strum" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7ac893c7d471c8a21f31cfe213ec4f6d9afeed25537c772e08ef3f005f8729e" -dependencies = [ - "strum_macros 0.22.0", -] - [[package]] name = "strum" version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cae14b91c7d11c9a851d3fbc80a963198998c2a64eec840477fa92d8ce9b70bb" dependencies = [ - "strum_macros 0.23.1", -] - -[[package]] -name = "strum_macros" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "339f799d8b549e3744c7ac7feb216383e4005d94bdb22561b3ab8f3b808ae9fb" -dependencies = [ - "heck 0.3.2", - "proc-macro2", - "quote", - "syn", + "strum_macros", ] [[package]] @@ -10488,7 +10466,7 @@ dependencies = [ "build-helper", "cargo_metadata", "sp-maybe-compressed-blob", - "strum 0.23.0", + "strum", "tempfile", "toml", "walkdir", diff --git a/client/beefy/Cargo.toml b/client/beefy/Cargo.toml index 9761f18d7845..3bef549938cc 100644 --- a/client/beefy/Cargo.toml +++ b/client/beefy/Cargo.toml @@ -39,4 +39,4 @@ beefy-primitives = { version = "4.0.0-dev", path = "../../primitives/beefy" } sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } sc-network-test = { version = "0.8.0", path = "../network/test" } -strum = { version = "0.22", features = ["derive"] } +strum = { version = "0.23", features = ["derive"] } diff --git a/frame/election-provider-multi-phase/Cargo.toml b/frame/election-provider-multi-phase/Cargo.toml index 7add94dc76c8..062e63f5fdf1 100644 --- a/frame/election-provider-multi-phase/Cargo.toml +++ b/frame/election-provider-multi-phase/Cargo.toml @@ -37,8 +37,7 @@ rand = { version = "0.7.3", default-features = false, optional = true, features "alloc", "small_rng", ] } -strum = { optional = true, version = "0.22.0" } -strum_macros = { optional = true, version = "0.23.1" } +strum = { optional = true, default-features = false, version = "0.23.0", features = ["derive"] } [dev-dependencies] parking_lot = "0.11.2" @@ -70,12 +69,15 @@ std = [ "sp-arithmetic/std", "frame-election-provider-support/std", "log/std", + + "frame-benchmarking/std", + "rand/std", + "strum/std", ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-election-provider-support/runtime-benchmarks", "rand", "strum", - "strum_macros", ] try-runtime = ["frame-support/try-runtime"] diff --git a/frame/election-provider-multi-phase/src/lib.rs b/frame/election-provider-multi-phase/src/lib.rs index 2b48373c5b0e..0a620e6c1282 100644 --- a/frame/election-provider-multi-phase/src/lib.rs +++ b/frame/election-provider-multi-phase/src/lib.rs @@ -488,7 +488,7 @@ pub struct SolutionOrSnapshotSize { /// /// Note that this is different from [`pallet::Error`]. #[derive(frame_support::DebugNoBound)] -#[cfg_attr(feature = "runtime-benchmarks", derive(strum_macros::IntoStaticStr))] +#[cfg_attr(feature = "runtime-benchmarks", derive(strum::IntoStaticStr))] pub enum ElectionError { /// An error happened in the feasibility check sub-system. Feasibility(FeasibilityError), @@ -533,7 +533,7 @@ impl From> for ElectionError { /// Errors that can happen in the feasibility check. #[derive(Debug, Eq, PartialEq)] -#[cfg_attr(feature = "runtime-benchmarks", derive(strum_macros::IntoStaticStr))] +#[cfg_attr(feature = "runtime-benchmarks", derive(strum::IntoStaticStr))] pub enum FeasibilityError { /// Wrong number of winners presented. WrongWinnerCount, diff --git a/primitives/keyring/Cargo.toml b/primitives/keyring/Cargo.toml index a457f4983c16..a31dcc51d0fb 100644 --- a/primitives/keyring/Cargo.toml +++ b/primitives/keyring/Cargo.toml @@ -18,4 +18,4 @@ targets = ["x86_64-unknown-linux-gnu"] sp-core = { version = "4.1.0-dev", path = "../core" } sp-runtime = { version = "4.1.0-dev", path = "../runtime" } lazy_static = "1.4.0" -strum = { version = "0.22.0", features = ["derive"] } +strum = { version = "0.23.0", features = ["derive"] } From 13ab8c76a6aa7f6c82c31ee38da685528bc7d67f Mon Sep 17 00:00:00 2001 From: driemworks Date: Mon, 31 Jan 2022 21:27:55 -0500 Subject: [PATCH 440/695] iris_assets test work --- Cargo.lock | 3 + .../pallets/iris-assets/src/lib.rs | 2 - .../pallets/iris-assets/src/mock.rs | 39 +--- .../pallets/iris-assets/src/tests.rs | 58 ++--- .../pallets/iris-session/Cargo.toml | 9 +- .../pallets/iris-session/src/lib.rs | 4 +- .../pallets/iris-session/src/mock.rs | 218 +++++++++++++++--- .../pallets/iris-session/src/tests.rs | 196 +++++++++++++++- bin/node-template/runtime/src/lib.rs | 1 - 9 files changed, 412 insertions(+), 118 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fbc8eee53a93..21d7e7b6bf83 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5904,10 +5904,13 @@ dependencies = [ "frame-support", "frame-system", "log 0.4.14", + "pallet-assets", + "pallet-balances", "pallet-iris-assets", "pallet-session", "parity-scale-codec", "scale-info", + "sp-authority-discovery", "sp-core", "sp-io", "sp-keystore", diff --git a/bin/node-template/pallets/iris-assets/src/lib.rs b/bin/node-template/pallets/iris-assets/src/lib.rs index 4567f90b166e..c59d2f6aebce 100644 --- a/bin/node-template/pallets/iris-assets/src/lib.rs +++ b/bin/node-template/pallets/iris-assets/src/lib.rs @@ -170,8 +170,6 @@ pub mod pallet { AssetClassCreated(T::AssetId), /// A new asset was created (tickets minted) AssetCreated(T::AssetId), - /// A node's request to access data via the RPC endpoint has been processed - DataReady(T::AccountId), /// A node has published ipfs identity results on chain PublishedIdentity(T::AccountId), } diff --git a/bin/node-template/pallets/iris-assets/src/mock.rs b/bin/node-template/pallets/iris-assets/src/mock.rs index 83713f0513da..5198c428690f 100644 --- a/bin/node-template/pallets/iris-assets/src/mock.rs +++ b/bin/node-template/pallets/iris-assets/src/mock.rs @@ -1,5 +1,5 @@ #![cfg(test)] -use crate::{self as pallet_iris, Config}; +use crate::{self as pallet_iris_assets, Config}; use frame_support::{construct_runtime, parameter_types}; use sp_core::{ Pair, @@ -12,8 +12,6 @@ use sp_runtime::{ testing::{Header, TestXt}, traits::{BlakeTwo256, Extrinsic as ExtrinsicT, IdentityLookup, IdentifyAccount, Verify}, }; -// use pallet_balances::Call as BalancesCall; -// use pallet_assets; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; type Block = frame_system::mocking::MockBlock; @@ -28,7 +26,7 @@ construct_runtime!( System: frame_system::{Pallet, Call, Config, Storage, Event}, Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, Assets: pallet_assets::{Pallet, Storage, Event}, - Iris: pallet_iris::{Pallet, Call, Storage, Event, ValidateUnsigned}, + Iris: pallet_iris_assets::{Pallet, Call, Storage, Event}, } ); @@ -62,6 +60,7 @@ impl frame_system::Config for Test { type SS58Prefix = (); type OnSetCode = (); } + // SS58Prefix parameter_types! { pub const ExistentialDeposit: u64 = 1; @@ -103,42 +102,10 @@ impl pallet_assets::Config for Test { type Extra = (); } -type Extrinsic = TestXt; -type AccountId = <::Signer as IdentifyAccount>::AccountId; - -impl frame_system::offchain::SigningTypes for Test { - type Public = ::Signer; - type Signature = Signature; -} - -impl frame_system::offchain::SendTransactionTypes for Test -where - Call: From, -{ - type OverarchingCall = Call; - type Extrinsic = Extrinsic; -} - - -impl frame_system::offchain::CreateSignedTransaction for Test -where - Call: From, -{ - fn create_transaction>( - call: Call, - _public: ::Signer, - _account: AccountId, - nonce: u64, - ) -> Option<(Call, ::SignaturePayload)> { - Some((call, (nonce, ()))) - } -} - impl Config for Test { type Currency = Balances; type Call = Call; type Event = Event; - type AuthorityId = pallet_iris::crypto::TestAuthId; } pub fn new_test_ext() -> sp_io::TestExternalities { diff --git a/bin/node-template/pallets/iris-assets/src/tests.rs b/bin/node-template/pallets/iris-assets/src/tests.rs index 4ddbe012b0b3..062fcd7609e8 100644 --- a/bin/node-template/pallets/iris-assets/src/tests.rs +++ b/bin/node-template/pallets/iris-assets/src/tests.rs @@ -1,10 +1,15 @@ use super::*; -use frame_support::{assert_noop, assert_ok}; +use frame_support::{assert_ok}; use mock::*; use sp_core::Pair; +use sp_core::{ + offchain::{testing, OffchainWorkerExt, TransactionPoolExt, OffchainDbExt} +}; +use sp_keystore::{testing::KeyStore, KeystoreExt, SyncCryptoStore}; +use std::sync::Arc; #[test] -fn iris_initial_state() { +fn iris_assets_initial_state() { new_test_ext().execute_with(|| { // Given: The node is initialized at block 0 // When: I query runtime storagey @@ -16,7 +21,7 @@ fn iris_initial_state() { } #[test] -fn iris_ipfs_add_bytes_works_for_valid_value() { +fn iris_assets_ipfs_add_bytes_works_for_valid_value() { // Given: I am a valid node with a positive balance let (p, _) = sp_core::sr25519::Pair::generate(); let multiaddr_vec = "/ip4/127.0.0.1/tcp/4001/p2p/12D3KooWMvyvKxYcy9mjbFbXcogFSCvENzQ62ogRxHKZaksFCkAp".as_bytes().to_vec(); @@ -58,22 +63,22 @@ fn iris_ipfs_add_bytes_works_for_valid_value() { } #[test] -fn iris_request_data_works_for_valid_values() { +fn iris_assets_request_data_works_for_valid_values() { // GIVEN: I am a valid Iris node with a positive balance let (p, _) = sp_core::sr25519::Pair::generate(); - let cid_vec = "QmPZv7P8nQUSh2CpqTvUeYemFyjvMjgWEs8H1Tm8b3zAm9".as_bytes().to_vec(); - + // let cid_vec = "QmPZv7P8nQUSh2CpqTvUeYemFyjvMjgWEs8H1Tm8b3zAm9".as_bytes().to_vec(); + let asset_id = 1; let expected_data_command = crate::DataCommand::CatBytes( p.clone().public(), - cid_vec.clone(), p.clone().public(), + asset_id.clone(), ); new_test_ext_funded(p.clone()).execute_with(|| { // WHEN: I invoke the request_data extrinsic - assert_ok!(Iris::request_data( + assert_ok!(Iris::request_bytes( Origin::signed(p.clone().public()), p.clone().public(), - cid_vec.clone(), + asset_id.clone(), )); // THEN: There should be a single DataCommand::CatBytes in the DataQueue @@ -86,7 +91,7 @@ fn iris_request_data_works_for_valid_values() { } #[test] -fn iris_submit_ipfs_add_results_works_for_valid_values() { +fn iris_assets_submit_ipfs_add_results_works_for_valid_values() { // GIVEN: I am a valid Iris node with a positive valance let (p, _) = sp_core::sr25519::Pair::generate(); let cid_vec = "QmPZv7P8nQUSh2CpqTvUeYemFyjvMjgWEs8H1Tm8b3zAm9".as_bytes().to_vec(); @@ -105,16 +110,15 @@ fn iris_submit_ipfs_add_results_works_for_valid_values() { // THEN: a new asset class is created // AND: A new entry is added to the AssetClassOwnership StorageDoubleMap - let admin_asset_class_id = crate::AssetClassOwnership::::get(p.clone().public(), cid_vec.clone()); - assert_eq!(admin_asset_class_id, id.clone()); + let admin_asset_class_cid = crate::AssetClassOwnership::::get(p.clone().public(), id.clone()); + assert_eq!(admin_asset_class_cid, cid_vec.clone()); }); } #[test] -fn iris_mint_tickets_works_for_valid_values() { +fn iris_assets_mint_tickets_works_for_valid_values() { // GIVEN: I am a valid Iris node with a positive valance let (p, _) = sp_core::sr25519::Pair::generate(); - let (p, _) = sp_core::sr25519::Pair::generate(); let cid_vec = "QmPZv7P8nQUSh2CpqTvUeYemFyjvMjgWEs8H1Tm8b3zAm9".as_bytes().to_vec(); let balance = 1; let id = 1; @@ -132,34 +136,12 @@ fn iris_mint_tickets_works_for_valid_values() { assert_ok!(Iris::mint_tickets( Origin::signed(p.clone().public()), p.clone().public(), - cid_vec.clone(), + id.clone(), balance.clone(), )); // THEN: new assets are created and awarded to the benficiary // AND: A new entry is added to the AssetAccess StorageDoubleMap - let asset_class_owner = crate::AssetAccess::::get(p.clone().public(), cid_vec.clone()); + let asset_class_owner = crate::AssetAccess::::get(p.clone().public(), id.clone()); assert_eq!(asset_class_owner, p.clone().public()) }); } - -#[test] -fn iris_submit_rpc_ready_works_for_valid_values() { - let (p, _) = sp_core::sr25519::Pair::generate(); - new_test_ext_funded(p.clone()).execute_with(|| { - assert_ok!(Iris::submit_rpc_ready( - Origin::signed(p.clone().public()), - p.clone().public(), - )); - }); -} - -// #[test] -// fn iris_purchase_tickets_works_for_valid_values() { -// let (p, _) = sp_core::sr25519::Pair::generate(); -// new_test_ext_funded(p.clone()).execute_with(|| { -// assert_ok!(Iris::purchase_ticket( -// Origin::signed(p.clone().public()), -// p.clone().public(), -// )); -// }); -// } diff --git a/bin/node-template/pallets/iris-session/Cargo.toml b/bin/node-template/pallets/iris-session/Cargo.toml index 27305506c269..d25769c10216 100644 --- a/bin/node-template/pallets/iris-session/Cargo.toml +++ b/bin/node-template/pallets/iris-session/Cargo.toml @@ -25,16 +25,21 @@ sp-core = { default-features = false, version = "4.0.0-dev", path = "../../../.. sp-runtime = { default-features = false, version = "4.0.0-dev", path = "../../../../primitives/runtime" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/staking" } sp-keystore = { version = "0.10.0-dev", path = "../../../../primitives/keystore", optional = true } +sp-authority-discovery = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/authority-discovery" } frame-support = { default-features = false, version = "4.0.0-dev", path = "../../../../frame/support" } frame-system = { default-features = false, version = "4.0.0-dev", path = "../../../../frame/system" } frame-benchmarking = { default-features = false, version = "4.0.0-dev", path = "../../../../frame/benchmarking", optional = true } log = { version = "0.4.14", default-features = false } -# pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../../../../frame/balances" } + pallet-session = { version = "4.0.0-dev", default-features = false, features = ["historical"], path = "../../../../frame/session" } pallet-iris-assets = { version = "1.0.0", default-features = false, path = "../iris-assets" } +[dev-dependencies] +pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../../../../frame/balances" } +pallet-assets = { version = "4.0.0-dev", default-features = false, path = "../../../../frame/assets" } + [features] default = ['std'] std = [ @@ -47,7 +52,9 @@ std = [ 'sp-std/std', 'sp-keystore/std', 'sp-runtime/std', + # todo: can remove this dependency 'sp-staking/std', + 'sp-authority-discovery/std', 'log/std', 'pallet-session/std', 'pallet-iris-assets/std', diff --git a/bin/node-template/pallets/iris-session/src/lib.rs b/bin/node-template/pallets/iris-session/src/lib.rs index f4f188fae0aa..673ae34e8b5a 100644 --- a/bin/node-template/pallets/iris-session/src/lib.rs +++ b/bin/node-template/pallets/iris-session/src/lib.rs @@ -346,7 +346,7 @@ pub mod pallet { sp.push(who.clone()); }); let owner = T::Lookup::lookup(pool_owner)?; - >::insert_pin_request(new_origin, owner, pool_id); + >::insert_pin_request(new_origin, owner, pool_id)?; Self::deposit_event(Event::RequestJoinStoragePoolSuccess(who.clone(), pool_id.clone())); Ok(()) } @@ -704,7 +704,6 @@ impl Pallet { unreachable!("only `Identity` is a valid response type."); }; let expected_pub_key = >::get(requestor.clone()); - // todo: create new error enum if this is the route i choose ensure!(public_key == expected_pub_key, Error::::BadOrigin); if let cid = >::asset_class_ownership( @@ -823,7 +822,6 @@ impl pallet_session::SessionManager for Pallet { // Remove any offline validators. This will only work when the runtime // also has the im-online pallet. Self::remove_offline_validators(); - // TODO: Clear active storage providers here Self::select_candidate_storage_providers(); log::debug!(target: LOG_TARGET, "New session called; updated validator set provided."); Some(Self::validators()) diff --git a/bin/node-template/pallets/iris-session/src/mock.rs b/bin/node-template/pallets/iris-session/src/mock.rs index eea24893ae30..a860890d8a30 100644 --- a/bin/node-template/pallets/iris-session/src/mock.rs +++ b/bin/node-template/pallets/iris-session/src/mock.rs @@ -3,18 +3,29 @@ #![cfg(test)] use super::*; -use crate as pallet_iris_session; +use crate::{self as pallet_iris_session, Config}; +use pallet_iris_assets; use frame_support::{parameter_types, traits::GenesisBuild, BasicExternalities}; use frame_system::EnsureRoot; use pallet_session::*; -use sp_core::{crypto::key_types::DUMMY, H256}; use sp_runtime::{ impl_opaque_keys, - testing::{Header, UintAuthorityId}, - traits::{BlakeTwo256, IdentityLookup, OpaqueKeys}, - KeyTypeId, RuntimeAppPublic, + testing::{Header, UintAuthorityId, TestXt}, + traits::{BlakeTwo256, IdentityLookup, OpaqueKeys, IdentifyAccount, Verify, Extrinsic as ExtrinsicT}, + KeyTypeId, RuntimeAppPublic, Perbill, }; +use sp_core::{ + crypto::key_types::DUMMY, + offchain::{testing, OffchainWorkerExt, TransactionPoolExt}, + sr25519::Signature, + H256, +}; +use sp_keystore::{testing::KeyStore, KeystoreExt, SyncCryptoStore}; +// use sp_authority_discovery::AuthorityId; + + use std::cell::RefCell; +use std::sync::Arc; impl_opaque_keys! { pub struct MockSessionKeys { @@ -63,8 +74,11 @@ frame_support::construct_runtime!( UncheckedExtrinsic = UncheckedExtrinsic, { System: frame_system::{Pallet, Call, Config, Storage, Event}, - IrisSession: pallet_iris_session::{Pallet, Call, Storage, Event, Config}, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, Session: pallet_session::{Pallet, Call, Storage, Event, Config}, + Assets: pallet_assets::{Pallet, Storage, Event}, + IrisAssets: pallet_iris_assets::{Pallet, Call, Storage, Event}, + IrisSession: pallet_iris_session::{Pallet, Call, Storage, Event, Config}, } ); @@ -81,7 +95,7 @@ thread_local! { } pub struct TestSessionHandler; -impl SessionHandler for TestSessionHandler { +impl pallet_session::SessionHandler for TestSessionHandler { const KEY_TYPE_IDS: &'static [sp_runtime::KeyTypeId] = &[UintAuthorityId::ID]; fn on_genesis_session(_validators: &[(u64, T)]) {} fn on_new_session( @@ -97,7 +111,7 @@ impl SessionHandler for TestSessionHandler { .collect() }); } - fn on_disabled(_validator_index: u32) { + fn on_disabled(_validator_index: usize) { DISABLED.with(|l| *l.borrow_mut() = true) } fn on_before_session_ending() { @@ -122,28 +136,6 @@ pub fn authorities() -> Vec { AUTHORITIES.with(|l| l.borrow().to_vec()) } -pub fn new_test_ext() -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - let keys: Vec<_> = NEXT_VALIDATORS - .with(|l| l.borrow().iter().cloned().map(|i| (i, i, UintAuthorityId(i).into())).collect()); - BasicExternalities::execute_with_storage(&mut t, || { - for (ref k, ..) in &keys { - frame_system::Pallet::::inc_providers(k); - } - frame_system::Pallet::::inc_providers(&4); - frame_system::Pallet::::inc_providers(&69); - }); - pallet_iris_session::GenesisConfig:: { - initial_validators: keys.iter().map(|x| x.0).collect::>(), - } - .assimilate_storage(&mut t) - .unwrap(); - pallet_session::GenesisConfig:: { keys: keys.clone() } - .assimilate_storage(&mut t) - .unwrap(); - sp_io::TestExternalities::new(t) -} - parameter_types! { pub const MinimumPeriod: u64 = 5; pub const BlockHashCount: u64 = 250; @@ -162,6 +154,7 @@ impl frame_system::Config for Test { type Call = Call; type Hash = H256; type Hashing = BlakeTwo256; + // type AccountId = sp_core::sr25519::Public; type AccountId = u64; type Lookup = IdentityLookup; type Header = Header; @@ -169,7 +162,8 @@ impl frame_system::Config for Test { type BlockHashCount = BlockHashCount; type Version = (); type PalletInfo = PalletInfo; - type AccountData = (); + type AccountData = pallet_balances::AccountData; + // type AccountData = sp_core::sr25519::Public; type OnNewAccount = (); type OnKilledAccount = (); type SystemWeightInfo = (); @@ -177,19 +171,79 @@ impl frame_system::Config for Test { type OnSetCode = (); } +// SS58Prefix +parameter_types! { + pub const ExistentialDeposit: u64 = 1; +} + +impl pallet_balances::Config for Test { + type MaxLocks = (); + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; + type Balance = u64; + type DustRemoval = (); + type Event = Event; + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); +} + parameter_types! { pub const MinAuthorities: u32 = 2; } -impl pallet_iris_session::Config for Test { - type AddRemoveOrigin = EnsureRoot; +// implement assets pallet for iris_assets +parameter_types! { + pub const AssetDeposit: u64 = 1; + pub const ApprovalDeposit: u64 = 1; + pub const StringLimit: u32 = 50; + pub const MetadataDepositBase: u64 = 1; + pub const MetadataDepositPerByte: u64 = 1; +} + +impl pallet_assets::Config for Test { + type Event = Event; + type Balance = u64; + type AssetId = u32; + type Currency = Balances; + // type ForceOrigin = frame_system::EnsureRoot; + type ForceOrigin = EnsureRoot; + type AssetDeposit = AssetDeposit; + type MetadataDepositBase = MetadataDepositBase; + type MetadataDepositPerByte = MetadataDepositPerByte; + type ApprovalDeposit = ApprovalDeposit; + type StringLimit = StringLimit; + type Freezer = (); + type WeightInfo = (); + type Extra = (); +} + + +/// configure the iris assets pallet +impl pallet_iris_assets::Config for Test { + type Event = Event; + type Call = Call; + type Currency = Balances; +} + + +impl Config for Test { + // type AddRemoveOrigin = (); + type AddRemoveOrigin = EnsureRoot; + type Call = Call; + type AuthorityId = pallet_iris_session::crypto::TestAuthId; type Event = Event; type MinAuthorities = MinAuthorities; } +parameter_types! { + pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(33); +} + impl pallet_session::Config for Test { type ValidatorId = ::AccountId; type ValidatorIdOf = pallet_iris_session::ValidatorOf; + type DisabledValidatorsThreshold = DisabledValidatorsThreshold; type ShouldEndSession = TestShouldEndSession; type NextSessionRotation = (); type SessionManager = IrisSession; @@ -198,3 +252,101 @@ impl pallet_session::Config for Test { type WeightInfo = (); type Event = Event; } + +type Extrinsic = TestXt; +type AccountId = <::Signer as IdentifyAccount>::AccountId; + +impl frame_system::offchain::SigningTypes for Test { + type Public = ::Signer; + type Signature = Signature; +} + +impl frame_system::offchain::SendTransactionTypes for Test +where + Call: From, +{ + type OverarchingCall = Call; + type Extrinsic = Extrinsic; +} + +impl frame_system::offchain::CreateSignedTransaction for Test +where + Call: From, +{ + fn create_transaction>( + call: Call, + _public: ::Signer, + _account: AccountId, + nonce: u64, + ) -> Option<(Call, ::SignaturePayload)> { + Some((call, (nonce, ()))) + } +} + +pub fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + let keys: Vec<_> = NEXT_VALIDATORS + .with(|l| l.borrow().iter().cloned().map(|i| (i, i, UintAuthorityId(i).into())).collect()); + BasicExternalities::execute_with_storage(&mut t, || { + for (ref k, ..) in &keys { + frame_system::Pallet::::inc_providers(k); + } + frame_system::Pallet::::inc_providers(&4); + frame_system::Pallet::::inc_providers(&69); + }); + + pallet_iris_session::GenesisConfig:: { + initial_validators: keys.iter().map(|x| x.0).collect::>(), + } + .assimilate_storage(&mut t) + .unwrap(); + + pallet_session::GenesisConfig:: { keys: keys.clone() } + .assimilate_storage(&mut t) + .unwrap(); + + // let (pair1, _) = sp_core::sr25519::Pair::generate(); + // let (pair2, _) = sp_core::sr25519::Pair::generate(); + // let (pair3, _) = sp_core::sr25519::Pair::generate(); + // pallet_balances::GenesisConfig:: { + // balances: vec![(pair1.public(), 10), (pair2.public(), 20), (pair3.public(), 30)], + // } + // .assimilate_storage(&mut t) + // .unwrap(); + + sp_io::TestExternalities::new(t) +} + +// Build genesis storage according to the mock runtime. +// pub fn new_test_ext_funded(pair1_funded: sp_core::sr25519::Pair) -> sp_io::TestExternalities { +// let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); +// let keys: Vec<_> = NEXT_VALIDATORS +// .with(|l| l.borrow().iter().cloned().map(|i| (i, i, UintAuthorityId(i).into())).collect()); +// BasicExternalities::execute_with_storage(&mut t, || { +// for (ref k, ..) in &keys { +// frame_system::Pallet::::inc_providers(k); +// } +// frame_system::Pallet::::inc_providers(&4); +// frame_system::Pallet::::inc_providers(&69); +// }); + +// pallet_iris_session::GenesisConfig:: { +// initial_validators: keys.iter().map(|x| x.0).collect::>(), +// } +// .assimilate_storage(&mut t) +// .unwrap(); + +// pallet_session::GenesisConfig:: { keys: keys.clone() } +// .assimilate_storage(&mut t) +// .unwrap(); + +// let (pair2, _) = sp_core::sr25519::Pair::generate(); +// let (pair3, _) = sp_core::sr25519::Pair::generate(); +// pallet_balances::GenesisConfig:: { +// balances: vec![(pair1_funded.public(), 10), (pair2.public(), 20), (pair3.public(), 30)], +// } +// .assimilate_storage(&mut t) +// .unwrap(); + +// sp_io::TestExternalities::new(t) +// } diff --git a/bin/node-template/pallets/iris-session/src/tests.rs b/bin/node-template/pallets/iris-session/src/tests.rs index 6f838211ce27..9e9581e24a9a 100644 --- a/bin/node-template/pallets/iris-session/src/tests.rs +++ b/bin/node-template/pallets/iris-session/src/tests.rs @@ -3,15 +3,21 @@ #![cfg(test)] use super::*; -use crate::mock::{authorities, new_test_ext, Origin, Session, Test, ValidatorSet}; +use crate::mock::{authorities, new_test_ext, Origin, Session, Test, IrisSession}; use frame_support::{assert_noop, assert_ok, pallet_prelude::*}; use sp_runtime::testing::UintAuthorityId; +use sp_core::Pair; +use sp_core::{ + offchain::{testing, OffchainWorkerExt, TransactionPoolExt, OffchainDbExt} +}; +use sp_keystore::{testing::KeyStore, KeystoreExt, SyncCryptoStore}; +use std::sync::Arc; #[test] fn iris_session_simple_setup_should_work() { new_test_ext().execute_with(|| { assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); - assert_eq!(ValidatorSet::validators(), vec![1u64, 2u64, 3u64]); + assert_eq!(crate::Validators::::get(), vec![1u64, 2u64, 3u64]); assert_eq!(Session::validators(), vec![1, 2, 3]); }); } @@ -19,8 +25,8 @@ fn iris_session_simple_setup_should_work() { #[test] fn iris_session_add_validator_updates_validators_list() { new_test_ext().execute_with(|| { - assert_ok!(ValidatorSet::add_validator(Origin::root(), 4)); - assert_eq!(ValidatorSet::validators(), vec![1u64, 2u64, 3u64, 4u64]) + assert_ok!(IrisSession::add_validator(Origin::root(), 4)); + assert_eq!(crate::Validators::::get(), vec![1u64, 2u64, 3u64, 4u64]) }); } @@ -57,3 +63,185 @@ fn iris_session_duplicate_check() { assert_noop!(ValidatorSet::add_validator(Origin::root(), 4), Error::::Duplicate); }); } + +// RPC tests + +// #[test] +// fn iris_session_submit_rpc_ready_works_for_valid_values() { +// let (p, _) = sp_core::sr25519::Pair::generate(); +// new_test_ext_funded(p.clone()).execute_with(|| { +// assert_ok!(Iris::submit_rpc_ready( +// Origin::signed(p.clone().public()), +// p.clone().public(), +// )); +// }); +// } + +// // test OCW functionality +// // can add bytes to network + +// #[test] +// fn iris_can_add_bytes_to_ipfs() { +// let (p, _) = sp_core::sr25519::Pair::generate(); +// let (offchain, state) = testing::TestOffchainExt::new(); +// let (pool, _) = testing::TestTransactionPoolExt::new(); +// const PHRASE: &str = +// "news slush supreme milk chapter athlete soap sausage put clutch what kitten"; +// let keystore = KeyStore::new(); +// SyncCryptoStore::sr25519_generate_new( +// &keystore, +// crate::KEY_TYPE, +// Some(&format!("{}/hunter1", PHRASE)), +// ) +// .unwrap(); + +// let mut t = new_test_ext_funded(p.clone()); +// t.register_extension(OffchainWorkerExt::new(offchain)); +// t.register_extension(TransactionPoolExt::new(pool)); +// t.register_extension(KeystoreExt(Arc::new(keystore))); + +// let multiaddr_vec = "/ip4/127.0.0.1/tcp/4001/p2p/12D3KooWMvyvKxYcy9mjbFbXcogFSCvENzQ62ogRxHKZaksFCkAp".as_bytes().to_vec(); +// let cid_vec = "QmPZv7P8nQUSh2CpqTvUeYemFyjvMjgWEs8H1Tm8b3zAm9".as_bytes().to_vec(); +// let bytes = "hello test".as_bytes().to_vec(); +// let name: Vec = "test.txt".as_bytes().to_vec(); +// let id = 1; +// let balance = 1; +// // mock IPFS calls +// { +// let mut state = state.write(); +// // connect to external node +// state.expect_ipfs_request(testing::IpfsPendingRequest { +// response: Some(IpfsResponse::Success), +// ..Default::default() +// }); +// // fetch data +// state.expect_ipfs_request(testing::IpfsPendingRequest { +// id: sp_core::offchain::IpfsRequestId(0), +// response: Some(IpfsResponse::CatBytes(bytes.clone())), +// ..Default::default() +// }); +// // disconnect from the external node +// state.expect_ipfs_request(testing::IpfsPendingRequest { +// response: Some(IpfsResponse::Success), +// ..Default::default() +// }); +// // add bytes to your local node +// state.expect_ipfs_request(testing::IpfsPendingRequest { +// response: Some(IpfsResponse::AddBytes(cid_vec.clone())), +// ..Default::default() +// }); +// } + +// t.execute_with(|| { +// // WHEN: I invoke the create_storage_assets extrinsic +// assert_ok!(Iris::create_storage_asset( +// Origin::signed(p.clone().public()), +// p.clone().public(), +// multiaddr_vec.clone(), +// cid_vec.clone(), +// name.clone(), +// id.clone(), +// balance.clone(), +// )); +// // THEN: the offchain worker adds data to IPFS +// assert_ok!(Iris::handle_data_requests()); +// }); +// } + +// // can fetch bytes and add to offchain storage +// #[test] +// fn iris_can_fetch_bytes_and_add_to_offchain_storage() { +// let (p, _) = sp_core::sr25519::Pair::generate(); +// let (offchain, state) = testing::TestOffchainExt::new(); +// let (pool, _) = testing::TestTransactionPoolExt::new(); +// const PHRASE: &str = +// "news slush supreme milk chapter athlete soap sausage put clutch what kitten"; +// let keystore = KeyStore::new(); +// SyncCryptoStore::sr25519_generate_new( +// &keystore, +// crate::KEY_TYPE, +// Some(&format!("{}/hunter1", PHRASE)), +// ) +// .unwrap(); + +// let mut t = new_test_ext_funded(p.clone()); +// t.register_extension(OffchainWorkerExt::new(offchain.clone())); +// t.register_extension(OffchainDbExt::new(offchain)); +// t.register_extension(TransactionPoolExt::new(pool)); +// t.register_extension(KeystoreExt(Arc::new(keystore))); + +// let multiaddr_vec = "/ip4/127.0.0.1/tcp/4001/p2p/12D3KooWMvyvKxYcy9mjbFbXcogFSCvENzQ62ogRxHKZaksFCkAp".as_bytes().to_vec(); +// let cid_vec = "QmPZv7P8nQUSh2CpqTvUeYemFyjvMjgWEs8H1Tm8b3zAm9".as_bytes().to_vec(); +// let bytes = "hello test".as_bytes().to_vec(); +// let name: Vec = "test.txt".as_bytes().to_vec(); +// let id = 1; +// let balance = 1; +// // mock IPFS calls +// { +// let mut state = state.write(); +// // connect to external node +// state.expect_ipfs_request(testing::IpfsPendingRequest { +// response: Some(IpfsResponse::Success), +// ..Default::default() +// }); +// // fetch data +// state.expect_ipfs_request(testing::IpfsPendingRequest { +// id: sp_core::offchain::IpfsRequestId(0), +// response: Some(IpfsResponse::CatBytes(bytes.clone())), +// ..Default::default() +// }); +// // disconnect from the external node +// state.expect_ipfs_request(testing::IpfsPendingRequest { +// response: Some(IpfsResponse::Success), +// ..Default::default() +// }); +// // add bytes to your local node +// state.expect_ipfs_request(testing::IpfsPendingRequest { +// response: Some(IpfsResponse::AddBytes(cid_vec.clone())), +// ..Default::default() +// }); +// // fetch data +// state.expect_ipfs_request(testing::IpfsPendingRequest { +// id: sp_core::offchain::IpfsRequestId(0), +// response: Some(IpfsResponse::CatBytes(bytes.clone())), +// ..Default::default() +// }); +// } + +// t.execute_with(|| { +// // WHEN: I invoke the create_storage_assets extrinsic +// assert_ok!(Iris::create_storage_asset( +// Origin::signed(p.clone().public()), +// p.clone().public(), +// multiaddr_vec.clone(), +// cid_vec.clone(), +// name.clone(), +// id.clone(), +// balance.clone(), +// )); +// // AND: I create an owned asset class +// assert_ok!(Iris::submit_ipfs_add_results( +// Origin::signed(p.clone().public()), +// p.clone().public(), +// cid_vec.clone(), +// id.clone(), +// balance.clone(), +// )); +// // AND: I invoke the mint_tickets extrinsic +// assert_ok!(Iris::mint_tickets( +// Origin::signed(p.clone().public()), +// p.clone().public(), +// cid_vec.clone(), +// balance.clone(), +// )); +// // AND: I request the owned content from iris +// assert_ok!(Iris::request_data( +// Origin::signed(p.clone().public()), +// p.clone().public(), +// cid_vec.clone(), +// )); +// // THEN: the offchain worker adds data to IPFS +// assert_ok!(Iris::handle_data_requests()); +// // AND: The data is available in local offchain storage +// }); +// } diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index 659c2ea37ca9..774f462df87a 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -356,7 +356,6 @@ pub type SignedPayload = generic::SignedPayload; impl pallet_iris_assets::Config for Runtime { type Event = Event; type Call = Call; - // type AuthorityId = pallet_iris_assets::crypto::TestAuthId; type Currency = Balances; } From 7daddf614bd743e331cfeed28101b68181f37593 Mon Sep 17 00:00:00 2001 From: Hussein Ait-Lahcen Date: Tue, 1 Feb 2022 10:34:53 +0100 Subject: [PATCH 441/695] derive `MaxEncodedLen` for `MultiSignature` (#10765) --- primitives/core/src/ecdsa.rs | 2 +- primitives/core/src/ed25519.rs | 2 +- primitives/core/src/sr25519.rs | 2 +- primitives/runtime/src/lib.rs | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/primitives/core/src/ecdsa.rs b/primitives/core/src/ecdsa.rs index c5e53c7029e6..4d2cae97ef14 100644 --- a/primitives/core/src/ecdsa.rs +++ b/primitives/core/src/ecdsa.rs @@ -187,7 +187,7 @@ impl<'de> Deserialize<'de> for Public { /// A signature (a 512-bit value, plus 8 bits for recovery ID). #[cfg_attr(feature = "full_crypto", derive(Hash))] -#[derive(Encode, Decode, PassByInner, TypeInfo, PartialEq, Eq)] +#[derive(Encode, Decode, MaxEncodedLen, PassByInner, TypeInfo, PartialEq, Eq)] pub struct Signature(pub [u8; 65]); impl sp_std::convert::TryFrom<&[u8]> for Signature { diff --git a/primitives/core/src/ed25519.rs b/primitives/core/src/ed25519.rs index bb99a4ae0200..be7547201e84 100644 --- a/primitives/core/src/ed25519.rs +++ b/primitives/core/src/ed25519.rs @@ -212,7 +212,7 @@ impl<'de> Deserialize<'de> for Public { /// A signature (a 512-bit value). #[cfg_attr(feature = "full_crypto", derive(Hash))] -#[derive(Encode, Decode, PassByInner, TypeInfo, PartialEq, Eq)] +#[derive(Encode, Decode, MaxEncodedLen, PassByInner, TypeInfo, PartialEq, Eq)] pub struct Signature(pub [u8; 64]); impl sp_std::convert::TryFrom<&[u8]> for Signature { diff --git a/primitives/core/src/sr25519.rs b/primitives/core/src/sr25519.rs index 4094c4d1b440..5e18e02c0ffd 100644 --- a/primitives/core/src/sr25519.rs +++ b/primitives/core/src/sr25519.rs @@ -212,7 +212,7 @@ impl<'de> Deserialize<'de> for Public { /// /// Instead of importing it for the local module, alias it to be available as a public type #[cfg_attr(feature = "full_crypto", derive(Hash))] -#[derive(Encode, Decode, PassByInner, TypeInfo, PartialEq, Eq)] +#[derive(Encode, Decode, MaxEncodedLen, PassByInner, TypeInfo, PartialEq, Eq)] pub struct Signature(pub [u8; 64]); impl sp_std::convert::TryFrom<&[u8]> for Signature { diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index cb9ba9ff297f..84817a6be5d7 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -52,7 +52,7 @@ use sp_core::{ }; use sp_std::{convert::TryFrom, prelude::*}; -use codec::{Decode, Encode}; +use codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; pub mod curve; @@ -224,7 +224,7 @@ pub type ConsensusEngineId = [u8; 4]; /// Signature verify that can work with any known signature types.. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -#[derive(Eq, PartialEq, Clone, Encode, Decode, RuntimeDebug, TypeInfo)] +#[derive(Eq, PartialEq, Clone, Encode, Decode, MaxEncodedLen, RuntimeDebug, TypeInfo)] pub enum MultiSignature { /// An Ed25519 signature. Ed25519(ed25519::Signature), From 70925041649ace60f7f8996f3928617bab0bb7d5 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Tue, 1 Feb 2022 14:45:16 +0100 Subject: [PATCH 442/695] Add `MaxEncodedLen` to `implement_fixed!` (#10768) Signed-off-by: Oliver Tale-Yazdi --- primitives/arithmetic/src/fixed_point.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/primitives/arithmetic/src/fixed_point.rs b/primitives/arithmetic/src/fixed_point.rs index 206e63af95b1..1c61d6c3806a 100644 --- a/primitives/arithmetic/src/fixed_point.rs +++ b/primitives/arithmetic/src/fixed_point.rs @@ -369,6 +369,7 @@ macro_rules! implement_fixed { Default, Copy, Clone, + codec::MaxEncodedLen, PartialEq, Eq, PartialOrd, @@ -667,6 +668,15 @@ macro_rules! implement_fixed { assert!($name::DIV > 0); } + #[test] + fn has_max_encoded_len() { + struct AsMaxEncodedLen { + _data: T, + } + + let _ = AsMaxEncodedLen { _data: $name::min_value() }; + } + #[test] fn from_i129_works() { let a = I129 { value: 1, negative: true }; From 6611740479b52e4c52e178dc1af62c34d0c69e12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Tue, 1 Feb 2022 20:38:02 +0100 Subject: [PATCH 443/695] Release `pallet-contracts-primitives` (#10772) * Bump sp-storage * Bump sp-rpc * Bump sp-io * Bump sp-trie * Bump sp-state-machine * Bump sp-externalities * Bump sp-keystore * Bump sp-application-crypto * Bump pallet-contracts-primitives * Bump sp-core * Bump sp-runtime-interface * Bump sp-wasm-interface * Bump sp-runtime * Bump sp-storage * Update lock file * Revert "Bump sp-storage" This reverts commit f86c6db1ae334e28207b658fd90714ade0332e3b. * Update lock file --- Cargo.lock | 26 +++++++++---------- bin/node-template/node/Cargo.toml | 4 +-- bin/node-template/pallets/template/Cargo.toml | 6 ++--- bin/node-template/runtime/Cargo.toml | 4 +-- bin/node/bench/Cargo.toml | 8 +++--- bin/node/cli/Cargo.toml | 8 +++--- bin/node/executor/Cargo.toml | 14 +++++----- bin/node/inspect/Cargo.toml | 4 +-- bin/node/primitives/Cargo.toml | 6 ++--- bin/node/rpc/Cargo.toml | 4 +-- bin/node/runtime/Cargo.toml | 8 +++--- bin/node/testing/Cargo.toml | 6 ++--- bin/utils/chain-spec-builder/Cargo.toml | 4 +-- client/allocator/Cargo.toml | 4 +-- client/api/Cargo.toml | 14 +++++----- client/authority-discovery/Cargo.toml | 6 ++--- client/basic-authorship/Cargo.toml | 4 +-- client/beefy/Cargo.toml | 8 +++--- client/beefy/rpc/Cargo.toml | 4 +-- client/block-builder/Cargo.toml | 6 ++--- client/chain-spec/Cargo.toml | 4 +-- client/cli/Cargo.toml | 6 ++--- client/consensus/aura/Cargo.toml | 8 +++--- client/consensus/babe/Cargo.toml | 10 +++---- client/consensus/babe/rpc/Cargo.toml | 8 +++--- client/consensus/common/Cargo.toml | 6 ++--- client/consensus/epochs/Cargo.toml | 2 +- client/consensus/manual-seal/Cargo.toml | 6 ++--- client/consensus/pow/Cargo.toml | 4 +-- client/consensus/slots/Cargo.toml | 6 ++--- client/consensus/uncles/Cargo.toml | 2 +- client/db/Cargo.toml | 8 +++--- client/executor/Cargo.toml | 16 ++++++------ client/executor/common/Cargo.toml | 4 +-- client/executor/runtime-test/Cargo.toml | 6 ++--- client/executor/wasmi/Cargo.toml | 6 ++--- client/executor/wasmtime/Cargo.toml | 8 +++--- client/finality-grandpa/Cargo.toml | 8 +++--- client/finality-grandpa/rpc/Cargo.toml | 6 ++--- client/informant/Cargo.toml | 2 +- client/keystore/Cargo.toml | 6 ++--- client/network-gossip/Cargo.toml | 2 +- client/network/Cargo.toml | 4 +-- client/network/test/Cargo.toml | 4 +-- client/offchain/Cargo.toml | 4 +-- client/rpc-api/Cargo.toml | 6 ++--- client/rpc/Cargo.toml | 10 +++---- client/service/Cargo.toml | 16 ++++++------ client/service/test/Cargo.toml | 12 ++++----- client/state-db/Cargo.toml | 2 +- client/sync-state-rpc/Cargo.toml | 2 +- client/tracing/Cargo.toml | 6 ++--- client/transaction-pool/Cargo.toml | 4 +-- client/transaction-pool/api/Cargo.toml | 2 +- frame/assets/Cargo.toml | 6 ++--- frame/atomic-swap/Cargo.toml | 6 ++--- frame/aura/Cargo.toml | 8 +++--- frame/authority-discovery/Cargo.toml | 8 +++--- frame/authorship/Cargo.toml | 6 ++--- frame/babe/Cargo.toml | 8 +++--- frame/bags-list/Cargo.toml | 10 +++---- frame/bags-list/remote-tests/Cargo.toml | 6 ++--- frame/balances/Cargo.toml | 6 ++--- frame/beefy-mmr/Cargo.toml | 6 ++--- frame/beefy/Cargo.toml | 6 ++--- frame/benchmarking/Cargo.toml | 12 ++++----- frame/bounties/Cargo.toml | 6 ++--- frame/child-bounties/Cargo.toml | 6 ++--- frame/collective/Cargo.toml | 6 ++--- frame/contracts/Cargo.toml | 8 +++--- frame/contracts/common/Cargo.toml | 8 +++--- frame/contracts/rpc/Cargo.toml | 8 +++--- frame/contracts/rpc/runtime-api/Cargo.toml | 4 +-- frame/democracy/Cargo.toml | 6 ++--- .../election-provider-multi-phase/Cargo.toml | 10 +++---- frame/election-provider-support/Cargo.toml | 6 ++--- frame/elections-phragmen/Cargo.toml | 8 +++--- frame/examples/basic/Cargo.toml | 6 ++--- frame/examples/offchain-worker/Cargo.toml | 8 +++--- frame/examples/parallel/Cargo.toml | 6 ++--- frame/executive/Cargo.toml | 10 +++---- frame/gilt/Cargo.toml | 6 ++--- frame/grandpa/Cargo.toml | 8 +++--- frame/identity/Cargo.toml | 6 ++--- frame/im-online/Cargo.toml | 8 +++--- frame/indices/Cargo.toml | 6 ++--- frame/lottery/Cargo.toml | 6 ++--- frame/membership/Cargo.toml | 6 ++--- frame/merkle-mountain-range/Cargo.toml | 6 ++--- .../primitives/Cargo.toml | 4 +-- frame/merkle-mountain-range/rpc/Cargo.toml | 4 +-- frame/multisig/Cargo.toml | 6 ++--- frame/nicks/Cargo.toml | 6 ++--- frame/node-authorization/Cargo.toml | 6 ++--- frame/offences/Cargo.toml | 6 ++--- frame/offences/benchmarking/Cargo.toml | 6 ++--- frame/preimage/Cargo.toml | 8 +++--- frame/proxy/Cargo.toml | 6 ++--- frame/randomness-collective-flip/Cargo.toml | 6 ++--- frame/recovery/Cargo.toml | 6 ++--- frame/scheduler/Cargo.toml | 6 ++--- frame/scored-pool/Cargo.toml | 6 ++--- frame/session/Cargo.toml | 8 +++--- frame/session/benchmarking/Cargo.toml | 6 ++--- frame/society/Cargo.toml | 6 ++--- frame/staking/Cargo.toml | 8 +++--- frame/staking/reward-curve/Cargo.toml | 2 +- frame/sudo/Cargo.toml | 6 ++--- frame/support/Cargo.toml | 8 +++--- frame/support/test/Cargo.toml | 8 +++--- frame/support/test/compile_pass/Cargo.toml | 4 +-- frame/system/Cargo.toml | 8 +++--- frame/system/benchmarking/Cargo.toml | 6 ++--- frame/timestamp/Cargo.toml | 8 +++--- frame/tips/Cargo.toml | 8 +++--- frame/transaction-payment/Cargo.toml | 6 ++--- .../asset-tx-payment/Cargo.toml | 8 +++--- frame/transaction-payment/rpc/Cargo.toml | 6 ++--- .../rpc/runtime-api/Cargo.toml | 2 +- frame/transaction-storage/Cargo.toml | 6 ++--- frame/treasury/Cargo.toml | 6 ++--- frame/try-runtime/Cargo.toml | 2 +- frame/uniques/Cargo.toml | 6 ++--- frame/utility/Cargo.toml | 8 +++--- frame/vesting/Cargo.toml | 6 ++--- primitives/api/Cargo.toml | 6 ++--- primitives/api/test/Cargo.toml | 6 ++--- primitives/application-crypto/Cargo.toml | 6 ++--- primitives/application-crypto/test/Cargo.toml | 8 +++--- primitives/authority-discovery/Cargo.toml | 4 +-- primitives/authorship/Cargo.toml | 2 +- primitives/beefy/Cargo.toml | 8 +++--- primitives/block-builder/Cargo.toml | 2 +- primitives/blockchain/Cargo.toml | 4 +-- primitives/consensus/aura/Cargo.toml | 4 +-- primitives/consensus/babe/Cargo.toml | 8 +++--- primitives/consensus/common/Cargo.toml | 6 ++--- primitives/consensus/pow/Cargo.toml | 4 +-- primitives/consensus/slots/Cargo.toml | 2 +- primitives/consensus/vrf/Cargo.toml | 4 +-- primitives/core/Cargo.toml | 8 +++--- primitives/externalities/Cargo.toml | 4 +-- primitives/finality-grandpa/Cargo.toml | 8 +++--- primitives/inherents/Cargo.toml | 4 +-- primitives/io/Cargo.toml | 16 ++++++------ primitives/keyring/Cargo.toml | 4 +-- primitives/keystore/Cargo.toml | 6 ++--- primitives/npos-elections/Cargo.toml | 4 +-- primitives/npos-elections/fuzzer/Cargo.toml | 2 +- primitives/offchain/Cargo.toml | 4 +-- primitives/rpc/Cargo.toml | 4 +-- primitives/runtime-interface/Cargo.toml | 14 +++++----- .../test-wasm-deprecated/Cargo.toml | 6 ++--- .../runtime-interface/test-wasm/Cargo.toml | 6 ++--- primitives/runtime-interface/test/Cargo.toml | 8 +++--- primitives/runtime/Cargo.toml | 10 +++---- primitives/sandbox/Cargo.toml | 6 ++--- primitives/session/Cargo.toml | 4 +-- primitives/staking/Cargo.toml | 2 +- primitives/state-machine/Cargo.toml | 10 +++---- primitives/storage/Cargo.toml | 2 +- primitives/tasks/Cargo.toml | 8 +++--- primitives/test-primitives/Cargo.toml | 6 ++--- primitives/timestamp/Cargo.toml | 2 +- primitives/transaction-pool/Cargo.toml | 2 +- .../transaction-storage-proof/Cargo.toml | 6 ++--- primitives/trie/Cargo.toml | 6 ++--- primitives/version/Cargo.toml | 2 +- primitives/wasm-interface/Cargo.toml | 2 +- test-utils/client/Cargo.toml | 8 +++--- test-utils/runtime/Cargo.toml | 16 ++++++------ test-utils/runtime/client/Cargo.toml | 4 +-- .../runtime/transaction-pool/Cargo.toml | 2 +- utils/frame/benchmarking-cli/Cargo.toml | 10 +++---- utils/frame/frame-utilities-cli/Cargo.toml | 4 +-- utils/frame/generate-bags/Cargo.toml | 2 +- utils/frame/remote-externalities/Cargo.toml | 6 ++--- utils/frame/rpc/support/Cargo.toml | 2 +- utils/frame/rpc/system/Cargo.toml | 4 +-- utils/frame/try-runtime/cli/Cargo.toml | 12 ++++----- 180 files changed, 564 insertions(+), 564 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a45b3bf3289c..963082a7e3af 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5618,7 +5618,7 @@ dependencies = [ [[package]] name = "pallet-contracts-primitives" -version = "4.0.0-dev" +version = "5.0.0" dependencies = [ "bitflags", "parity-scale-codec", @@ -9388,7 +9388,7 @@ dependencies = [ [[package]] name = "sp-application-crypto" -version = "4.0.0" +version = "5.0.0" dependencies = [ "parity-scale-codec", "scale-info", @@ -9581,7 +9581,7 @@ dependencies = [ [[package]] name = "sp-core" -version = "4.1.0-dev" +version = "5.0.0" dependencies = [ "base58", "bitflags", @@ -9672,7 +9672,7 @@ dependencies = [ [[package]] name = "sp-externalities" -version = "0.10.0" +version = "0.11.0" dependencies = [ "environmental", "parity-scale-codec", @@ -9713,7 +9713,7 @@ dependencies = [ [[package]] name = "sp-io" -version = "4.0.0" +version = "5.0.0" dependencies = [ "futures 0.3.16", "hash-db", @@ -9746,7 +9746,7 @@ dependencies = [ [[package]] name = "sp-keystore" -version = "0.10.0" +version = "0.11.0" dependencies = [ "async-trait", "futures 0.3.16", @@ -9833,7 +9833,7 @@ dependencies = [ [[package]] name = "sp-rpc" -version = "4.0.0-dev" +version = "5.0.0" dependencies = [ "rustc-hash", "serde", @@ -9843,7 +9843,7 @@ dependencies = [ [[package]] name = "sp-runtime" -version = "4.1.0-dev" +version = "5.0.0" dependencies = [ "either", "hash256-std-hasher", @@ -9870,7 +9870,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface" -version = "4.1.0-dev" +version = "5.0.0" dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", @@ -9987,7 +9987,7 @@ dependencies = [ [[package]] name = "sp-state-machine" -version = "0.10.0" +version = "0.11.0" dependencies = [ "hash-db", "hex-literal", @@ -10016,7 +10016,7 @@ version = "4.0.0" [[package]] name = "sp-storage" -version = "4.0.0" +version = "5.0.0" dependencies = [ "impl-serde", "parity-scale-codec", @@ -10102,7 +10102,7 @@ dependencies = [ [[package]] name = "sp-trie" -version = "4.0.0" +version = "5.0.0" dependencies = [ "criterion", "hash-db", @@ -10148,7 +10148,7 @@ dependencies = [ [[package]] name = "sp-wasm-interface" -version = "4.1.0-dev" +version = "5.0.0" dependencies = [ "impl-trait-for-tuples", "log 0.4.14", diff --git a/bin/node-template/node/Cargo.toml b/bin/node-template/node/Cargo.toml index 300a35252c05..1f8ff0ae1e0d 100644 --- a/bin/node-template/node/Cargo.toml +++ b/bin/node-template/node/Cargo.toml @@ -20,7 +20,7 @@ name = "node-template" clap = { version = "3.0", features = ["derive"] } sc-cli = { version = "0.10.0-dev", path = "../../../client/cli", features = ["wasmtime"] } -sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } +sp-core = { version = "5.0.0", path = "../../../primitives/core" } sc-executor = { version = "0.10.0-dev", path = "../../../client/executor", features = ["wasmtime"] } sc-service = { version = "0.10.0-dev", path = "../../../client/service", features = ["wasmtime"] } sc-telemetry = { version = "4.0.0-dev", path = "../../../client/telemetry" } @@ -34,7 +34,7 @@ sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/commo sc-finality-grandpa = { version = "0.10.0-dev", path = "../../../client/finality-grandpa" } sp-finality-grandpa = { version = "4.0.0-dev", path = "../../../primitives/finality-grandpa" } sc-client-api = { version = "4.0.0-dev", path = "../../../client/api" } -sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } +sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } sp-timestamp = { version = "4.0.0-dev", path = "../../../primitives/timestamp" } # These dependencies are used for the node template's RPCs diff --git a/bin/node-template/pallets/template/Cargo.toml b/bin/node-template/pallets/template/Cargo.toml index 4dc4fb3c6e52..0a9d0eb27a2c 100644 --- a/bin/node-template/pallets/template/Cargo.toml +++ b/bin/node-template/pallets/template/Cargo.toml @@ -22,9 +22,9 @@ frame-system = { default-features = false, version = "4.0.0-dev", path = "../../ frame-benchmarking = { default-features = false, version = "4.0.0-dev", path = "../../../../frame/benchmarking", optional = true } [dev-dependencies] -sp-core = { default-features = false, version = "4.1.0-dev", path = "../../../../primitives/core" } -sp-io = { default-features = false, version = "4.0.0-dev", path = "../../../../primitives/io" } -sp-runtime = { default-features = false, version = "4.1.0-dev", path = "../../../../primitives/runtime" } +sp-core = { default-features = false, version = "5.0.0", path = "../../../../primitives/core" } +sp-io = { default-features = false, version = "5.0.0", path = "../../../../primitives/io" } +sp-runtime = { default-features = false, version = "5.0.0", path = "../../../../primitives/runtime" } [features] default = ["std"] diff --git a/bin/node-template/runtime/Cargo.toml b/bin/node-template/runtime/Cargo.toml index eb8fb9eb52a8..98da28c4476d 100644 --- a/bin/node-template/runtime/Cargo.toml +++ b/bin/node-template/runtime/Cargo.toml @@ -29,10 +29,10 @@ frame-executive = { version = "4.0.0-dev", default-features = false, path = "../ sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/api" } sp-block-builder = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/block-builder"} sp-consensus-aura = { version = "0.10.0-dev", default-features = false, path = "../../../primitives/consensus/aura" } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } +sp-core = { version = "5.0.0", default-features = false, path = "../../../primitives/core" } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/inherents"} sp-offchain = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/offchain" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../../primitives/runtime" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/session" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } sp-transaction-pool = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/transaction-pool" } diff --git a/bin/node/bench/Cargo.toml b/bin/node/bench/Cargo.toml index 6c28f14793a9..9939f188d5d8 100644 --- a/bin/node/bench/Cargo.toml +++ b/bin/node/bench/Cargo.toml @@ -15,15 +15,15 @@ node-primitives = { version = "2.0.0", path = "../primitives" } node-testing = { version = "3.0.0-dev", path = "../testing" } node-runtime = { version = "3.0.0-dev", path = "../runtime" } sc-client-api = { version = "4.0.0-dev", path = "../../../client/api/" } -sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } -sp-state-machine = { version = "0.10.0", path = "../../../primitives/state-machine" } +sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } +sp-state-machine = { version = "0.11.0", path = "../../../primitives/state-machine" } serde = "1.0.132" serde_json = "1.0.74" derive_more = "0.99.16" kvdb = "0.10.0" kvdb-rocksdb = "0.14.0" -sp-trie = { version = "4.0.0", path = "../../../primitives/trie" } -sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } +sp-trie = { version = "5.0.0", path = "../../../primitives/trie" } +sp-core = { version = "5.0.0", path = "../../../primitives/core" } sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" } sc-basic-authorship = { version = "0.10.0-dev", path = "../../../client/basic-authorship" } sp-inherents = { version = "4.0.0-dev", path = "../../../primitives/inherents" } diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index 2eb1618a7c98..db198592b37b 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -47,13 +47,13 @@ sp-authority-discovery = { version = "4.0.0-dev", path = "../../../primitives/au sp-consensus-babe = { version = "0.10.0-dev", path = "../../../primitives/consensus/babe" } grandpa-primitives = { version = "4.0.0-dev", package = "sp-finality-grandpa", path = "../../../primitives/finality-grandpa" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } -sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } -sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } +sp-core = { version = "5.0.0", path = "../../../primitives/core" } +sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } sp-timestamp = { version = "4.0.0-dev", path = "../../../primitives/timestamp" } sp-authorship = { version = "4.0.0-dev", path = "../../../primitives/authorship" } sp-inherents = { version = "4.0.0-dev", path = "../../../primitives/inherents" } sp-keyring = { version = "4.1.0-dev", path = "../../../primitives/keyring" } -sp-keystore = { version = "0.10.0", path = "../../../primitives/keystore" } +sp-keystore = { version = "0.11.0", path = "../../../primitives/keystore" } sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" } sp-transaction-pool = { version = "4.0.0-dev", path = "../../../primitives/transaction-pool" } sp-transaction-storage-proof = { version = "4.0.0-dev", path = "../../../primitives/transaction-storage-proof" } @@ -102,7 +102,7 @@ sc-cli = { version = "0.10.0-dev", optional = true, path = "../../../client/cli" sc-service = { version = "0.10.0-dev", default-features = false, path = "../../../client/service", features = [ "wasmtime", ] } -sp-trie = { version = "4.0.0", default-features = false, path = "../../../primitives/trie", features = [ +sp-trie = { version = "5.0.0", default-features = false, path = "../../../primitives/trie", features = [ "memory-tracker", ] } diff --git a/bin/node/executor/Cargo.toml b/bin/node/executor/Cargo.toml index e23152e00e5e..39cf1ee8d893 100644 --- a/bin/node/executor/Cargo.toml +++ b/bin/node/executor/Cargo.toml @@ -17,11 +17,11 @@ scale-info = { version = "1.0", features = ["derive"] } node-primitives = { version = "2.0.0", path = "../primitives" } node-runtime = { version = "3.0.0-dev", path = "../runtime" } sc-executor = { version = "0.10.0-dev", path = "../../../client/executor" } -sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } -sp-keystore = { version = "0.10.0", path = "../../../primitives/keystore" } -sp-state-machine = { version = "0.10.0", path = "../../../primitives/state-machine" } +sp-core = { version = "5.0.0", path = "../../../primitives/core" } +sp-keystore = { version = "0.11.0", path = "../../../primitives/keystore" } +sp-state-machine = { version = "0.11.0", path = "../../../primitives/state-machine" } sp-tracing = { version = "4.0.0", path = "../../../primitives/tracing" } -sp-trie = { version = "4.0.0", path = "../../../primitives/trie" } +sp-trie = { version = "5.0.0", path = "../../../primitives/trie" } frame-benchmarking = { version = "4.0.0-dev", path = "../../../frame/benchmarking" } [dev-dependencies] @@ -34,10 +34,10 @@ pallet-contracts = { version = "4.0.0-dev", path = "../../../frame/contracts" } pallet-im-online = { version = "4.0.0-dev", path = "../../../frame/im-online" } pallet-timestamp = { version = "4.0.0-dev", path = "../../../frame/timestamp" } pallet-treasury = { version = "4.0.0-dev", path = "../../../frame/treasury" } -sp-application-crypto = { version = "4.0.0", path = "../../../primitives/application-crypto" } +sp-application-crypto = { version = "5.0.0", path = "../../../primitives/application-crypto" } sp-consensus-babe = { version = "0.10.0-dev", path = "../../../primitives/consensus/babe" } -sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } -sp-externalities = { version = "0.10.0", path = "../../../primitives/externalities" } +sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } +sp-externalities = { version = "0.11.0", path = "../../../primitives/externalities" } sp-keyring = { version = "4.1.0-dev", path = "../../../primitives/keyring" } wat = "1.0" futures = "0.3.9" diff --git a/bin/node/inspect/Cargo.toml b/bin/node/inspect/Cargo.toml index bb9af8c66988..e5b4c41c91b7 100644 --- a/bin/node/inspect/Cargo.toml +++ b/bin/node/inspect/Cargo.toml @@ -19,5 +19,5 @@ sc-client-api = { version = "4.0.0-dev", path = "../../../client/api" } sc-executor = { version = "0.10.0-dev", path = "../../../client/executor" } sc-service = { version = "0.10.0-dev", default-features = false, path = "../../../client/service" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } -sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } +sp-core = { version = "5.0.0", path = "../../../primitives/core" } +sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } diff --git a/bin/node/primitives/Cargo.toml b/bin/node/primitives/Cargo.toml index e00f46720c94..5664318513a0 100644 --- a/bin/node/primitives/Cargo.toml +++ b/bin/node/primitives/Cargo.toml @@ -16,9 +16,9 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../../frame/system" } -sp-application-crypto = { version = "4.0.0", default-features = false, path = "../../../primitives/application-crypto" } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/runtime" } +sp-application-crypto = { version = "5.0.0", default-features = false, path = "../../../primitives/application-crypto" } +sp-core = { version = "5.0.0", default-features = false, path = "../../../primitives/core" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../../primitives/runtime" } [features] default = ["std"] diff --git a/bin/node/rpc/Cargo.toml b/bin/node/rpc/Cargo.toml index 36d313ebc30a..c6ba0c9f992d 100644 --- a/bin/node/rpc/Cargo.toml +++ b/bin/node/rpc/Cargo.toml @@ -29,9 +29,9 @@ sc-sync-state-rpc = { version = "0.10.0-dev", path = "../../../client/sync-state sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-block-builder = { version = "4.0.0-dev", path = "../../../primitives/block-builder" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-keystore = { version = "0.10.0", path = "../../../primitives/keystore" } +sp-keystore = { version = "0.11.0", path = "../../../primitives/keystore" } sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" } sp-consensus-babe = { version = "0.10.0-dev", path = "../../../primitives/consensus/babe" } -sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } +sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../../../client/transaction-pool/api" } substrate-frame-rpc-system = { version = "4.0.0-dev", path = "../../../utils/frame/rpc/system" } diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index ef1b73aed854..84eec7662361 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -30,17 +30,17 @@ sp-block-builder = { path = "../../../primitives/block-builder", default-feature sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/inherents" } node-primitives = { version = "2.0.0", default-features = false, path = "../primitives" } sp-offchain = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/offchain" } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } +sp-core = { version = "5.0.0", default-features = false, path = "../../../primitives/core" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/api" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../../primitives/runtime" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/staking" } sp-keyring = { version = "4.1.0-dev", optional = true, path = "../../../primitives/keyring" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/session" } sp-transaction-pool = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/transaction-pool" } sp-version = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/version" } sp-npos-elections = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/npos-elections" } -sp-io = { version = "4.0.0", default-features = false, path = "../../../primitives/io" } +sp-io = { version = "5.0.0", default-features = false, path = "../../../primitives/io" } sp-sandbox = { version = "0.10.0-dev", default-features = false, path = "../../../primitives/sandbox" } # frame dependencies @@ -62,7 +62,7 @@ pallet-bounties = { version = "4.0.0-dev", default-features = false, path = "../ pallet-child-bounties = { version = "4.0.0-dev", default-features = false, path = "../../../frame/child-bounties" } pallet-collective = { version = "4.0.0-dev", default-features = false, path = "../../../frame/collective" } pallet-contracts = { version = "4.0.0-dev", default-features = false, path = "../../../frame/contracts" } -pallet-contracts-primitives = { version = "4.0.0-dev", default-features = false, path = "../../../frame/contracts/common/" } +pallet-contracts-primitives = { version = "5.0.0", default-features = false, path = "../../../frame/contracts/common/" } pallet-contracts-rpc-runtime-api = { version = "4.0.0-dev", default-features = false, path = "../../../frame/contracts/rpc/runtime-api/" } pallet-democracy = { version = "4.0.0-dev", default-features = false, path = "../../../frame/democracy" } pallet-election-provider-multi-phase = { version = "4.0.0-dev", default-features = false, path = "../../../frame/election-provider-multi-phase" } diff --git a/bin/node/testing/Cargo.toml b/bin/node/testing/Cargo.toml index 29efc0028c15..55ae52b50d9d 100644 --- a/bin/node/testing/Cargo.toml +++ b/bin/node/testing/Cargo.toml @@ -28,9 +28,9 @@ sp-keyring = { version = "4.1.0-dev", path = "../../../primitives/keyring" } node-executor = { version = "3.0.0-dev", path = "../executor" } node-primitives = { version = "2.0.0", path = "../primitives" } node-runtime = { version = "3.0.0-dev", path = "../runtime" } -sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } -sp-io = { version = "4.0.0-dev", path = "../../../primitives/io" } -sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } +sp-core = { version = "5.0.0", path = "../../../primitives/core" } +sp-io = { version = "5.0.0", path = "../../../primitives/io" } +sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } sc-executor = { version = "0.10.0-dev", path = "../../../client/executor", features = [ "wasmtime", ] } diff --git a/bin/utils/chain-spec-builder/Cargo.toml b/bin/utils/chain-spec-builder/Cargo.toml index 452221ff6e13..f6af82ba42eb 100644 --- a/bin/utils/chain-spec-builder/Cargo.toml +++ b/bin/utils/chain-spec-builder/Cargo.toml @@ -21,5 +21,5 @@ rand = "0.8" sc-keystore = { version = "4.0.0-dev", path = "../../../client/keystore" } sc-chain-spec = { version = "4.0.0-dev", path = "../../../client/chain-spec" } node-cli = { version = "3.0.0-dev", path = "../../node/cli" } -sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } -sp-keystore = { version = "0.10.0", path = "../../../primitives/keystore" } +sp-core = { version = "5.0.0", path = "../../../primitives/core" } +sp-keystore = { version = "0.11.0", path = "../../../primitives/keystore" } diff --git a/client/allocator/Cargo.toml b/client/allocator/Cargo.toml index eb8d298e1ec2..6f20449b38bc 100644 --- a/client/allocator/Cargo.toml +++ b/client/allocator/Cargo.toml @@ -14,7 +14,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } -sp-wasm-interface = { version = "4.1.0-dev", path = "../../primitives/wasm-interface" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-wasm-interface = { version = "5.0.0", path = "../../primitives/wasm-interface" } log = "0.4.11" thiserror = "1.0.30" diff --git a/client/api/Cargo.toml b/client/api/Cargo.toml index c18b920cace8..ab6ad96e286f 100644 --- a/client/api/Cargo.toml +++ b/client/api/Cargo.toml @@ -19,7 +19,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = ] } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } sc-executor = { version = "0.10.0-dev", path = "../executor" } -sp-externalities = { version = "0.10.0", path = "../../primitives/externalities" } +sp-externalities = { version = "0.11.0", path = "../../primitives/externalities" } fnv = "1.0.6" futures = "0.3.1" hash-db = { version = "0.15.2", default-features = false } @@ -27,14 +27,14 @@ sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } log = "0.4.8" parking_lot = "0.11.2" sp-database = { version = "4.0.0-dev", path = "../../primitives/database" } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } -sp-keystore = { version = "0.10.0", default-features = false, path = "../../primitives/keystore" } +sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } +sp-keystore = { version = "0.11.0", default-features = false, path = "../../primitives/keystore" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } sc-utils = { version = "4.0.0-dev", path = "../utils" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-state-machine = { version = "0.10.0", path = "../../primitives/state-machine" } -sp-trie = { version = "4.0.0", path = "../../primitives/trie" } -sp-storage = { version = "4.0.0", path = "../../primitives/storage" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-state-machine = { version = "0.11.0", path = "../../primitives/state-machine" } +sp-trie = { version = "5.0.0", path = "../../primitives/trie" } +sp-storage = { version = "5.0.0", path = "../../primitives/storage" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../transaction-pool/api" } prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.10.0-dev", path = "../../utils/prometheus" } diff --git a/client/authority-discovery/Cargo.toml b/client/authority-discovery/Cargo.toml index ec43112a7145..e3a3ef2a3591 100644 --- a/client/authority-discovery/Cargo.toml +++ b/client/authority-discovery/Cargo.toml @@ -32,9 +32,9 @@ sc-client-api = { version = "4.0.0-dev", path = "../api" } sc-network = { version = "0.10.0-dev", path = "../network" } sp-authority-discovery = { version = "4.0.0-dev", path = "../../primitives/authority-discovery" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } -sp-keystore = { version = "0.10.0", path = "../../primitives/keystore" } -sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-keystore = { version = "0.11.0", path = "../../primitives/keystore" } +sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } [dev-dependencies] diff --git a/client/basic-authorship/Cargo.toml b/client/basic-authorship/Cargo.toml index e1083b15a970..85592c7c549c 100644 --- a/client/basic-authorship/Cargo.toml +++ b/client/basic-authorship/Cargo.toml @@ -19,8 +19,8 @@ futures-timer = "3.0.1" log = "0.4.8" prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.10.0-dev"} sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } -sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } +sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sc-client-api = { version = "4.0.0-dev", path = "../api" } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } diff --git a/client/beefy/Cargo.toml b/client/beefy/Cargo.toml index 3bef549938cc..3ce556e85239 100644 --- a/client/beefy/Cargo.toml +++ b/client/beefy/Cargo.toml @@ -19,12 +19,12 @@ codec = { version = "2.2.0", package = "parity-scale-codec", features = ["derive prometheus = { version = "0.10.0-dev", package = "substrate-prometheus-endpoint", path = "../../utils/prometheus" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } -sp-application-crypto = { version = "4.0.0", path = "../../primitives/application-crypto" } +sp-application-crypto = { version = "5.0.0", path = "../../primitives/application-crypto" } sp-arithmetic = { version = "4.0.0", path = "../../primitives/arithmetic" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } -sp-keystore = { version = "0.10.0", path = "../../primitives/keystore" } -sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-keystore = { version = "0.11.0", path = "../../primitives/keystore" } +sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } sc-chain-spec = { version = "4.0.0-dev", path = "../../client/chain-spec" } sc-utils = { version = "4.0.0-dev", path = "../utils" } diff --git a/client/beefy/rpc/Cargo.toml b/client/beefy/rpc/Cargo.toml index 444f1ff4aaf9..4a300b26e123 100644 --- a/client/beefy/rpc/Cargo.toml +++ b/client/beefy/rpc/Cargo.toml @@ -24,8 +24,8 @@ codec = { version = "2.2.0", package = "parity-scale-codec", features = ["derive sc-rpc = { version = "4.0.0-dev", path = "../../rpc" } sc-utils = { version = "4.0.0-dev", path = "../../utils" } -sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } -sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } +sp-core = { version = "5.0.0", path = "../../../primitives/core" } +sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } beefy-gadget = { version = "4.0.0-dev", path = "../." } beefy-primitives = { version = "4.0.0-dev", path = "../../../primitives/beefy" } diff --git a/client/block-builder/Cargo.toml b/client/block-builder/Cargo.toml index 19b8839c1228..e41ab0a5caf1 100644 --- a/client/block-builder/Cargo.toml +++ b/client/block-builder/Cargo.toml @@ -14,11 +14,11 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-state-machine = { version = "0.10.0", path = "../../primitives/state-machine" } -sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } +sp-state-machine = { version = "0.11.0", path = "../../primitives/state-machine" } +sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } sp-block-builder = { version = "4.0.0-dev", path = "../../primitives/block-builder" } sp-inherents = { version = "4.0.0-dev", path = "../../primitives/inherents" } sc-client-api = { version = "4.0.0-dev", path = "../api" } diff --git a/client/chain-spec/Cargo.toml b/client/chain-spec/Cargo.toml index 0110e82532a5..d103c2414331 100644 --- a/client/chain-spec/Cargo.toml +++ b/client/chain-spec/Cargo.toml @@ -16,10 +16,10 @@ targets = ["x86_64-unknown-linux-gnu"] sc-chain-spec-derive = { version = "4.0.0-dev", path = "./derive" } impl-trait-for-tuples = "0.2.1" sc-network = { version = "0.10.0-dev", path = "../network" } -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } serde = { version = "1.0.132", features = ["derive"] } serde_json = "1.0.74" -sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } +sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } sc-telemetry = { version = "4.0.0-dev", path = "../telemetry" } codec = { package = "parity-scale-codec", version = "2.0.0" } memmap2 = "0.5.0" diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index a33b3e13af35..ca7e0ac768f9 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -39,11 +39,11 @@ sc-telemetry = { version = "4.0.0-dev", path = "../telemetry" } sc-tracing = { version = "4.0.0-dev", path = "../tracing" } sc-utils = { version = "4.0.0-dev", path = "../utils" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } sp-keyring = { version = "4.1.0-dev", path = "../../primitives/keyring" } -sp-keystore = { version = "0.10.0", path = "../../primitives/keystore" } +sp-keystore = { version = "0.11.0", path = "../../primitives/keystore" } sp-panic-handler = { version = "4.0.0", path = "../../primitives/panic-handler" } -sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } +sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } [dev-dependencies] diff --git a/client/consensus/aura/Cargo.toml b/client/consensus/aura/Cargo.toml index bcae7648ce2e..4fb621d716a8 100644 --- a/client/consensus/aura/Cargo.toml +++ b/client/consensus/aura/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-application-crypto = { version = "4.0.0", path = "../../../primitives/application-crypto" } +sp-application-crypto = { version = "5.0.0", path = "../../../primitives/application-crypto" } sp-consensus-aura = { version = "0.10.0-dev", path = "../../../primitives/consensus/aura" } sp-block-builder = { version = "4.0.0-dev", path = "../../../primitives/block-builder" } sc-block-builder = { version = "0.10.0-dev", path = "../../block-builder" } @@ -26,12 +26,12 @@ thiserror = "1.0" futures = "0.3.9" sp-inherents = { version = "4.0.0-dev", path = "../../../primitives/inherents" } log = "0.4.8" -sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } +sp-core = { version = "5.0.0", path = "../../../primitives/core" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sc-consensus-slots = { version = "0.10.0-dev", path = "../slots" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } -sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } -sp-keystore = { version = "0.10.0", path = "../../../primitives/keystore" } +sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } +sp-keystore = { version = "0.11.0", path = "../../../primitives/keystore" } sc-telemetry = { version = "4.0.0-dev", path = "../../telemetry" } prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.10.0-dev" } async-trait = "0.1.50" diff --git a/client/consensus/babe/Cargo.toml b/client/consensus/babe/Cargo.toml index 5dd029f0ad4a..79cb3a52038a 100644 --- a/client/consensus/babe/Cargo.toml +++ b/client/consensus/babe/Cargo.toml @@ -19,15 +19,15 @@ codec = { package = "parity-scale-codec", version = "2.0.0", features = [ ] } sp-consensus-babe = { version = "0.10.0-dev", path = "../../../primitives/consensus/babe" } sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/common" } -sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } -sp-application-crypto = { version = "4.0.0", path = "../../../primitives/application-crypto" } -sp-keystore = { version = "0.10.0", path = "../../../primitives/keystore" } +sp-core = { version = "5.0.0", path = "../../../primitives/core" } +sp-application-crypto = { version = "5.0.0", path = "../../../primitives/application-crypto" } +sp-keystore = { version = "0.11.0", path = "../../../primitives/keystore" } num-bigint = "0.2.3" num-rational = "0.2.2" num-traits = "0.2.8" serde = { version = "1.0.132", features = ["derive"] } sp-version = { version = "4.0.0-dev", path = "../../../primitives/version" } -sp-io = { version = "4.0.0", path = "../../../primitives/io" } +sp-io = { version = "5.0.0", path = "../../../primitives/io" } sp-inherents = { version = "4.0.0-dev", path = "../../../primitives/inherents" } sc-telemetry = { version = "4.0.0-dev", path = "../../telemetry" } sc-keystore = { version = "4.0.0-dev", path = "../../keystore" } @@ -40,7 +40,7 @@ sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/c sp-consensus-slots = { version = "0.10.0-dev", path = "../../../primitives/consensus/slots" } sp-consensus-vrf = { version = "0.10.0-dev", path = "../../../primitives/consensus/vrf" } sc-consensus-slots = { version = "0.10.0-dev", path = "../slots" } -sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } +sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } fork-tree = { version = "3.0.0", path = "../../../utils/fork-tree" } prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.10.0-dev" } futures = "0.3.9" diff --git a/client/consensus/babe/rpc/Cargo.toml b/client/consensus/babe/rpc/Cargo.toml index 4997cfdd1eec..87ef265ffd9b 100644 --- a/client/consensus/babe/rpc/Cargo.toml +++ b/client/consensus/babe/rpc/Cargo.toml @@ -21,15 +21,15 @@ jsonrpc-derive = "18.0.0" sp-consensus-babe = { version = "0.10.0-dev", path = "../../../../primitives/consensus/babe" } serde = { version = "1.0.132", features = ["derive"] } sp-blockchain = { version = "4.0.0-dev", path = "../../../../primitives/blockchain" } -sp-runtime = { version = "4.1.0-dev", path = "../../../../primitives/runtime" } +sp-runtime = { version = "5.0.0", path = "../../../../primitives/runtime" } sc-consensus-epochs = { version = "0.10.0-dev", path = "../../epochs" } futures = "0.3.16" thiserror = "1.0" sp-api = { version = "4.0.0-dev", path = "../../../../primitives/api" } sp-consensus = { version = "0.10.0-dev", path = "../../../../primitives/consensus/common" } -sp-core = { version = "4.1.0-dev", path = "../../../../primitives/core" } -sp-application-crypto = { version = "4.0.0", path = "../../../../primitives/application-crypto" } -sp-keystore = { version = "0.10.0", path = "../../../../primitives/keystore" } +sp-core = { version = "5.0.0", path = "../../../../primitives/core" } +sp-application-crypto = { version = "5.0.0", path = "../../../../primitives/application-crypto" } +sp-keystore = { version = "0.11.0", path = "../../../../primitives/keystore" } [dev-dependencies] sc-consensus = { version = "0.10.0-dev", path = "../../../consensus/common" } diff --git a/client/consensus/common/Cargo.toml b/client/consensus/common/Cargo.toml index 72a0544535ad..a14a36769033 100644 --- a/client/consensus/common/Cargo.toml +++ b/client/consensus/common/Cargo.toml @@ -20,10 +20,10 @@ futures = { version = "0.3.1", features = ["thread-pool"] } futures-timer = "3.0.1" sc-client-api = { version = "4.0.0-dev", path = "../../api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-core = { path = "../../../primitives/core", version = "4.1.0-dev" } +sp-core = { path = "../../../primitives/core", version = "5.0.0"} sp-consensus = { path = "../../../primitives/consensus/common", version = "0.10.0-dev" } -sp-state-machine = { version = "0.10.0", path = "../../../primitives/state-machine" } -sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } +sp-state-machine = { version = "0.11.0", path = "../../../primitives/state-machine" } +sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } sc-utils = { version = "4.0.0-dev", path = "../../utils" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } parking_lot = "0.11.2" diff --git a/client/consensus/epochs/Cargo.toml b/client/consensus/epochs/Cargo.toml index bb4a77b559e0..b377dccfd368 100644 --- a/client/consensus/epochs/Cargo.toml +++ b/client/consensus/epochs/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", features = ["derive"] } fork-tree = { version = "3.0.0", path = "../../../utils/fork-tree" } -sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } +sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sc-client-api = { path = "../../api" , version = "4.0.0-dev"} sc-consensus = { path = "../common" , version = "0.10.0-dev"} diff --git a/client/consensus/manual-seal/Cargo.toml b/client/consensus/manual-seal/Cargo.toml index ff2264e64174..c2c36b1fc586 100644 --- a/client/consensus/manual-seal/Cargo.toml +++ b/client/consensus/manual-seal/Cargo.toml @@ -37,9 +37,9 @@ sp-blockchain = { path = "../../../primitives/blockchain", version = "4.0.0-dev" sp-consensus = { path = "../../../primitives/consensus/common", version = "0.10.0-dev" } sp-consensus-slots = { path = "../../../primitives/consensus/slots", version = "0.10.0-dev" } sp-inherents = { path = "../../../primitives/inherents", version = "4.0.0-dev" } -sp-runtime = { path = "../../../primitives/runtime", version = "4.1.0-dev" } -sp-core = { path = "../../../primitives/core", version = "4.1.0-dev" } -sp-keystore = { path = "../../../primitives/keystore", version = "0.10.0" } +sp-runtime = { path = "../../../primitives/runtime", version = "5.0.0"} +sp-core = { path = "../../../primitives/core", version = "5.0.0"} +sp-keystore = { path = "../../../primitives/keystore", version = "0.11.0"} sp-api = { path = "../../../primitives/api", version = "4.0.0-dev" } sc-transaction-pool-api = { path = "../../../client/transaction-pool/api", version = "4.0.0-dev" } sp-timestamp = { path = "../../../primitives/timestamp", version = "4.0.0-dev" } diff --git a/client/consensus/pow/Cargo.toml b/client/consensus/pow/Cargo.toml index e5bf87487c71..eb609489290a 100644 --- a/client/consensus/pow/Cargo.toml +++ b/client/consensus/pow/Cargo.toml @@ -14,9 +14,9 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", features = ["derive"] } -sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } +sp-core = { version = "5.0.0", path = "../../../primitives/core" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } +sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sc-client-api = { version = "4.0.0-dev", path = "../../api" } sp-block-builder = { version = "4.0.0-dev", path = "../../../primitives/block-builder" } diff --git a/client/consensus/slots/Cargo.toml b/client/consensus/slots/Cargo.toml index 60f57449a3a3..b13c1bb6b5b3 100644 --- a/client/consensus/slots/Cargo.toml +++ b/client/consensus/slots/Cargo.toml @@ -16,13 +16,13 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0" } sc-client-api = { version = "4.0.0-dev", path = "../../api" } -sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } +sp-core = { version = "5.0.0", path = "../../../primitives/core" } sp-arithmetic = { version = "4.0.0", path = "../../../primitives/arithmetic" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/common" } sp-consensus-slots = { version = "0.10.0-dev", path = "../../../primitives/consensus/slots" } -sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } -sp-state-machine = { version = "0.10.0", path = "../../../primitives/state-machine" } +sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } +sp-state-machine = { version = "0.11.0", path = "../../../primitives/state-machine" } sc-telemetry = { version = "4.0.0-dev", path = "../../telemetry" } sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" } sp-inherents = { version = "4.0.0-dev", path = "../../../primitives/inherents" } diff --git a/client/consensus/uncles/Cargo.toml b/client/consensus/uncles/Cargo.toml index b9eaae4773a6..7482fdc12d08 100644 --- a/client/consensus/uncles/Cargo.toml +++ b/client/consensus/uncles/Cargo.toml @@ -14,6 +14,6 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sc-client-api = { version = "4.0.0-dev", path = "../../api" } -sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } +sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } sp-authorship = { version = "4.0.0-dev", path = "../../../primitives/authorship" } thiserror = "1.0.30" diff --git a/client/db/Cargo.toml b/client/db/Cargo.toml index 0db0f8309e2e..f2c21abf6c1d 100644 --- a/client/db/Cargo.toml +++ b/client/db/Cargo.toml @@ -26,11 +26,11 @@ codec = { package = "parity-scale-codec", version = "2.0.0", features = [ sc-client-api = { version = "4.0.0-dev", path = "../api" } sp-arithmetic = { version = "4.0.0", path = "../../primitives/arithmetic" } -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } -sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } -sp-state-machine = { version = "0.10.0", path = "../../primitives/state-machine" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } +sp-state-machine = { version = "0.11.0", path = "../../primitives/state-machine" } sc-state-db = { version = "0.10.0-dev", path = "../state-db" } -sp-trie = { version = "4.0.0", path = "../../primitives/trie" } +sp-trie = { version = "5.0.0", path = "../../primitives/trie" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-database = { version = "4.0.0-dev", path = "../../primitives/database" } parity-db = { version = "0.3.5", optional = true } diff --git a/client/executor/Cargo.toml b/client/executor/Cargo.toml index e10cbf347db5..0d0f2a8bd92e 100644 --- a/client/executor/Cargo.toml +++ b/client/executor/Cargo.toml @@ -15,18 +15,18 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0" } -sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } +sp-io = { version = "5.0.0", path = "../../primitives/io" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } sp-tasks = { version = "4.0.0-dev", path = "../../primitives/tasks" } -sp-trie = { version = "4.0.0", path = "../../primitives/trie" } +sp-trie = { version = "5.0.0", path = "../../primitives/trie" } sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } sp-panic-handler = { version = "4.0.0", path = "../../primitives/panic-handler" } wasmi = "0.9.1" lazy_static = "1.4.0" sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } -sp-wasm-interface = { version = "4.1.0-dev", path = "../../primitives/wasm-interface" } -sp-runtime-interface = { version = "4.1.0-dev", path = "../../primitives/runtime-interface" } -sp-externalities = { version = "0.10.0", path = "../../primitives/externalities" } +sp-wasm-interface = { version = "5.0.0", path = "../../primitives/wasm-interface" } +sp-runtime-interface = { version = "5.0.0", path = "../../primitives/runtime-interface" } +sp-externalities = { version = "0.11.0", path = "../../primitives/externalities" } sc-executor-common = { version = "0.10.0-dev", path = "common" } sc-executor-wasmi = { version = "0.10.0-dev", path = "wasmi" } sc-executor-wasmtime = { version = "0.10.0-dev", path = "wasmtime", optional = true } @@ -41,8 +41,8 @@ wat = "1.0" hex-literal = "0.3.4" sc-runtime-test = { version = "2.0.0", path = "runtime-test" } substrate-test-runtime = { version = "2.0.0", path = "../../test-utils/runtime" } -sp-state-machine = { version = "0.10.0", path = "../../primitives/state-machine" } -sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } +sp-state-machine = { version = "0.11.0", path = "../../primitives/state-machine" } +sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } sp-maybe-compressed-blob = { version = "4.1.0-dev", path = "../../primitives/maybe-compressed-blob" } sc-tracing = { version = "4.0.0-dev", path = "../tracing" } tracing = "0.1.29" diff --git a/client/executor/common/Cargo.toml b/client/executor/common/Cargo.toml index 104d24876d9a..e23db203b3a4 100644 --- a/client/executor/common/Cargo.toml +++ b/client/executor/common/Cargo.toml @@ -17,9 +17,9 @@ targets = ["x86_64-unknown-linux-gnu"] wasm-instrument = "0.1" codec = { package = "parity-scale-codec", version = "2.0.0" } wasmi = "0.9.1" -sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } +sp-core = { version = "5.0.0", path = "../../../primitives/core" } sc-allocator = { version = "4.1.0-dev", path = "../../allocator" } -sp-wasm-interface = { version = "4.1.0-dev", path = "../../../primitives/wasm-interface" } +sp-wasm-interface = { version = "5.0.0", path = "../../../primitives/wasm-interface" } sp-maybe-compressed-blob = { version = "4.1.0-dev", path = "../../../primitives/maybe-compressed-blob" } sp-serializer = { version = "4.0.0-dev", path = "../../../primitives/serializer" } thiserror = "1.0.30" diff --git a/client/executor/runtime-test/Cargo.toml b/client/executor/runtime-test/Cargo.toml index 1318c7246a84..b6fbe8685e35 100644 --- a/client/executor/runtime-test/Cargo.toml +++ b/client/executor/runtime-test/Cargo.toml @@ -13,9 +13,9 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/io" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/runtime" } +sp-core = { version = "5.0.0", default-features = false, path = "../../../primitives/core" } +sp-io = { version = "5.0.0", default-features = false, path = "../../../primitives/io" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../../primitives/runtime" } sp-sandbox = { version = "0.10.0-dev", default-features = false, path = "../../../primitives/sandbox" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } sp-tasks = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/tasks" } diff --git a/client/executor/wasmi/Cargo.toml b/client/executor/wasmi/Cargo.toml index 9dc63747166b..d333e98bf6cf 100644 --- a/client/executor/wasmi/Cargo.toml +++ b/client/executor/wasmi/Cargo.toml @@ -19,7 +19,7 @@ wasmi = "0.9.1" codec = { package = "parity-scale-codec", version = "2.0.0" } sc-executor-common = { version = "0.10.0-dev", path = "../common" } sc-allocator = { version = "4.1.0-dev", path = "../../allocator" } -sp-wasm-interface = { version = "4.1.0-dev", path = "../../../primitives/wasm-interface" } -sp-runtime-interface = { version = "4.1.0-dev", path = "../../../primitives/runtime-interface" } -sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } +sp-wasm-interface = { version = "5.0.0", path = "../../../primitives/wasm-interface" } +sp-runtime-interface = { version = "5.0.0", path = "../../../primitives/runtime-interface" } +sp-core = { version = "5.0.0", path = "../../../primitives/core" } scoped-tls = "1.0" diff --git a/client/executor/wasmtime/Cargo.toml b/client/executor/wasmtime/Cargo.toml index 8b3cd1a58e75..0423b384943e 100644 --- a/client/executor/wasmtime/Cargo.toml +++ b/client/executor/wasmtime/Cargo.toml @@ -19,9 +19,9 @@ log = "0.4.8" parity-wasm = "0.42.0" codec = { package = "parity-scale-codec", version = "2.0.0" } sc-executor-common = { version = "0.10.0-dev", path = "../common" } -sp-wasm-interface = { version = "4.1.0-dev", path = "../../../primitives/wasm-interface", features = ["wasmtime"] } -sp-runtime-interface = { version = "4.1.0-dev", path = "../../../primitives/runtime-interface" } -sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } +sp-wasm-interface = { version = "5.0.0", path = "../../../primitives/wasm-interface", features = ["wasmtime"] } +sp-runtime-interface = { version = "5.0.0", path = "../../../primitives/runtime-interface" } +sp-core = { version = "5.0.0", path = "../../../primitives/core" } sc-allocator = { version = "4.1.0-dev", path = "../../allocator" } wasmtime = { version = "0.33.0", default-features = false, features = [ "cache", @@ -32,5 +32,5 @@ wasmtime = { version = "0.33.0", default-features = false, features = [ [dev-dependencies] sc-runtime-test = { version = "2.0.0", path = "../runtime-test" } -sp-io = { version = "4.0.0", path = "../../../primitives/io" } +sp-io = { version = "5.0.0", path = "../../../primitives/io" } wat = "1.0" diff --git a/client/finality-grandpa/Cargo.toml b/client/finality-grandpa/Cargo.toml index 2e6d3407a191..e6b0b6396681 100644 --- a/client/finality-grandpa/Cargo.toml +++ b/client/finality-grandpa/Cargo.toml @@ -23,15 +23,15 @@ log = "0.4.8" parking_lot = "0.11.2" rand = "0.8.4" parity-scale-codec = { version = "2.3.1", features = ["derive"] } -sp-application-crypto = { version = "4.0.0", path = "../../primitives/application-crypto" } +sp-application-crypto = { version = "5.0.0", path = "../../primitives/application-crypto" } sp-arithmetic = { version = "4.0.0", path = "../../primitives/arithmetic" } -sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } +sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } sc-chain-spec = { version = "4.0.0-dev", path = "../../client/chain-spec" } sc-utils = { version = "4.0.0-dev", path = "../utils" } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } sc-consensus = { version = "0.10.0-dev", path = "../consensus/common" } -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } -sp-keystore = { version = "0.10.0", path = "../../primitives/keystore" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-keystore = { version = "0.11.0", path = "../../primitives/keystore" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } sc-telemetry = { version = "4.0.0-dev", path = "../telemetry" } sc-keystore = { version = "4.0.0-dev", path = "../keystore" } diff --git a/client/finality-grandpa/rpc/Cargo.toml b/client/finality-grandpa/rpc/Cargo.toml index 39bf398fe312..2845621cadd6 100644 --- a/client/finality-grandpa/rpc/Cargo.toml +++ b/client/finality-grandpa/rpc/Cargo.toml @@ -12,8 +12,8 @@ readme = "README.md" sc-finality-grandpa = { version = "0.10.0-dev", path = "../" } sc-rpc = { version = "4.0.0-dev", path = "../../rpc" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } -sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } +sp-core = { version = "5.0.0", path = "../../../primitives/core" } +sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } finality-grandpa = { version = "0.14.4", features = ["derive-codec"] } jsonrpc-core = "18.0.0" jsonrpc-core-client = "18.0.0" @@ -32,7 +32,7 @@ sc-block-builder = { version = "0.10.0-dev", path = "../../block-builder" } sc-rpc = { version = "4.0.0-dev", path = "../../rpc", features = [ "test-helpers", ] } -sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } +sp-core = { version = "5.0.0", path = "../../../primitives/core" } sp-finality-grandpa = { version = "4.0.0-dev", path = "../../../primitives/finality-grandpa" } sp-keyring = { version = "4.1.0-dev", path = "../../../primitives/keyring" } substrate-test-runtime-client = { version = "2.0.0", path = "../../../test-utils/runtime/client" } diff --git a/client/informant/Cargo.toml b/client/informant/Cargo.toml index ce7fe31648a1..78ee90823f22 100644 --- a/client/informant/Cargo.toml +++ b/client/informant/Cargo.toml @@ -21,5 +21,5 @@ parity-util-mem = { version = "0.10.2", default-features = false, features = ["p sc-client-api = { version = "4.0.0-dev", path = "../api" } sc-network = { version = "0.10.0-dev", path = "../network" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } -sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } +sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../transaction-pool/api" } diff --git a/client/keystore/Cargo.toml b/client/keystore/Cargo.toml index 56d4ee0d556f..4d67be4167dd 100644 --- a/client/keystore/Cargo.toml +++ b/client/keystore/Cargo.toml @@ -17,9 +17,9 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] async-trait = "0.1.50" thiserror = "1.0" -sp-application-crypto = { version = "4.0.0", path = "../../primitives/application-crypto" } -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } -sp-keystore = { version = "0.10.0", path = "../../primitives/keystore" } +sp-application-crypto = { version = "5.0.0", path = "../../primitives/application-crypto" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-keystore = { version = "0.11.0", path = "../../primitives/keystore" } hex = "0.4.0" parking_lot = "0.11.2" serde_json = "1.0.74" diff --git a/client/network-gossip/Cargo.toml b/client/network-gossip/Cargo.toml index 9523e32f99e0..7952d97193ea 100644 --- a/client/network-gossip/Cargo.toml +++ b/client/network-gossip/Cargo.toml @@ -22,7 +22,7 @@ log = "0.4.8" lru = "0.7.0" prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.10.0-dev", path = "../../utils/prometheus" } sc-network = { version = "0.10.0-dev", path = "../network" } -sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } +sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } tracing = "0.1.29" [dev-dependencies] diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index 354991b32ba5..fa1cc715e151 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -52,8 +52,8 @@ sp-arithmetic = { version = "4.0.0", path = "../../primitives/arithmetic" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } sc-consensus = { version = "0.10.0-dev", path = "../consensus/common" } -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } -sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } sc-utils = { version = "4.0.0-dev", path = "../utils" } sp-finality-grandpa = { version = "4.0.0-dev", path = "../../primitives/finality-grandpa" } thiserror = "1.0" diff --git a/client/network/test/Cargo.toml b/client/network/test/Cargo.toml index 6b6d777e7396..2750c613d42a 100644 --- a/client/network/test/Cargo.toml +++ b/client/network/test/Cargo.toml @@ -25,8 +25,8 @@ sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/c sc-consensus = { version = "0.10.0-dev", path = "../../consensus/common" } sc-client-api = { version = "4.0.0-dev", path = "../../api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } -sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } +sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } +sp-core = { version = "5.0.0", path = "../../../primitives/core" } sc-block-builder = { version = "0.10.0-dev", path = "../../block-builder" } sp-consensus-babe = { version = "0.10.0-dev", path = "../../../primitives/consensus/babe" } substrate-test-runtime-client = { version = "2.0.0", path = "../../../test-utils/runtime/client" } diff --git a/client/offchain/Cargo.toml b/client/offchain/Cargo.toml index dd4bdb71f93b..5cd823958eed 100644 --- a/client/offchain/Cargo.toml +++ b/client/offchain/Cargo.toml @@ -25,9 +25,9 @@ rand = "0.7.2" sc-client-api = { version = "4.0.0-dev", path = "../api" } sc-network = { version = "0.10.0-dev", path = "../network" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } sp-offchain = { version = "4.0.0-dev", path = "../../primitives/offchain" } -sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } +sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } sc-utils = { version = "4.0.0-dev", path = "../utils" } threadpool = "1.7" hyper = { version = "0.14.16", features = ["stream", "http2"] } diff --git a/client/rpc-api/Cargo.toml b/client/rpc-api/Cargo.toml index 4b2882ee827f..8b8b70b9747c 100644 --- a/client/rpc-api/Cargo.toml +++ b/client/rpc-api/Cargo.toml @@ -23,12 +23,12 @@ log = "0.4.8" parking_lot = "0.11.2" thiserror = "1.0" -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } -sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } +sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } sc-chain-spec = { path = "../chain-spec", version = "4.0.0-dev" } serde = { version = "1.0.132", features = ["derive"] } serde_json = "1.0.74" sc-transaction-pool-api = { version = "4.0.0-dev", path = "../transaction-pool/api" } -sp-rpc = { version = "4.0.0-dev", path = "../../primitives/rpc" } +sp-rpc = { version = "5.0.0", path = "../../primitives/rpc" } sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } diff --git a/client/rpc/Cargo.toml b/client/rpc/Cargo.toml index 87fc263356a7..308d99bc4f37 100644 --- a/client/rpc/Cargo.toml +++ b/client/rpc/Cargo.toml @@ -20,16 +20,16 @@ codec = { package = "parity-scale-codec", version = "2.0.0" } futures = "0.3.16" jsonrpc-pubsub = "18.0.0" log = "0.4.8" -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } rpc = { package = "jsonrpc-core", version = "18.0.0" } sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } serde_json = "1.0.74" sp-session = { version = "4.0.0-dev", path = "../../primitives/session" } sp-offchain = { version = "4.0.0-dev", path = "../../primitives/offchain" } -sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } +sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } sc-utils = { version = "4.0.0-dev", path = "../utils" } -sp-rpc = { version = "4.0.0-dev", path = "../../primitives/rpc" } -sp-keystore = { version = "0.10.0", path = "../../primitives/keystore" } +sp-rpc = { version = "5.0.0", path = "../../primitives/rpc" } +sp-keystore = { version = "0.11.0", path = "../../primitives/keystore" } sc-chain-spec = { version = "4.0.0-dev", path = "../chain-spec" } sc-block-builder = { version = "0.10.0-dev", path = "../block-builder" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } @@ -43,7 +43,7 @@ sc-transaction-pool-api = { version = "4.0.0-dev", path = "../transaction-pool/a assert_matches = "1.3.0" lazy_static = "1.4.0" sc-network = { version = "0.10.0-dev", path = "../network" } -sp-io = { version = "4.0.0", path = "../../primitives/io" } +sp-io = { version = "5.0.0", path = "../../primitives/io" } substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } sc-transaction-pool = { version = "4.0.0-dev", path = "../transaction-pool" } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index f23bf3f55bbf..fb6c4a083761 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -36,21 +36,21 @@ hash-db = "0.15.2" serde = "1.0.132" serde_json = "1.0.74" sc-keystore = { version = "4.0.0-dev", path = "../keystore" } -sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } -sp-trie = { version = "4.0.0", path = "../../primitives/trie" } -sp-externalities = { version = "0.10.0", path = "../../primitives/externalities" } +sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } +sp-trie = { version = "5.0.0", path = "../../primitives/trie" } +sp-externalities = { version = "0.11.0", path = "../../primitives/externalities" } sc-utils = { version = "4.0.0-dev", path = "../utils" } sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } -sp-keystore = { version = "0.10.0", path = "../../primitives/keystore" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-keystore = { version = "0.11.0", path = "../../primitives/keystore" } sp-session = { version = "4.0.0-dev", path = "../../primitives/session" } -sp-state-machine = { version = "0.10.0", path = "../../primitives/state-machine" } -sp-application-crypto = { version = "4.0.0", path = "../../primitives/application-crypto" } +sp-state-machine = { version = "0.11.0", path = "../../primitives/state-machine" } +sp-application-crypto = { version = "5.0.0", path = "../../primitives/application-crypto" } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } sc-consensus = { version = "0.10.0-dev", path = "../../client/consensus/common" } sp-inherents = { version = "4.0.0-dev", path = "../../primitives/inherents" } -sp-storage = { version = "4.0.0", path = "../../primitives/storage" } +sp-storage = { version = "5.0.0", path = "../../primitives/storage" } sc-network = { version = "0.10.0-dev", path = "../network" } sc-chain-spec = { version = "4.0.0-dev", path = "../chain-spec" } sc-client-api = { version = "4.0.0-dev", path = "../api" } diff --git a/client/service/test/Cargo.toml b/client/service/test/Cargo.toml index 84b1d44e7bde..6395f9d9877d 100644 --- a/client/service/test/Cargo.toml +++ b/client/service/test/Cargo.toml @@ -21,18 +21,18 @@ fdlimit = "0.2.1" parking_lot = "0.11.2" sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } -sp-state-machine = { version = "0.10.0", path = "../../../primitives/state-machine" } -sp-externalities = { version = "0.10.0", path = "../../../primitives/externalities" } -sp-trie = { version = "4.0.0", path = "../../../primitives/trie" } -sp-storage = { version = "4.0.0", path = "../../../primitives/storage" } +sp-state-machine = { version = "0.11.0", path = "../../../primitives/state-machine" } +sp-externalities = { version = "0.11.0", path = "../../../primitives/externalities" } +sp-trie = { version = "5.0.0", path = "../../../primitives/trie" } +sp-storage = { version = "5.0.0", path = "../../../primitives/storage" } sc-client-db = { version = "0.10.0-dev", default-features = false, path = "../../db" } futures = "0.3.16" sc-service = { version = "0.10.0-dev", features = ["test-helpers"], path = "../../service" } sc-network = { version = "0.10.0-dev", path = "../../network" } sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" } sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/common" } -sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } -sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } +sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } +sp-core = { version = "5.0.0", path = "../../../primitives/core" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../../../client/transaction-pool/api" } substrate-test-runtime = { version = "2.0.0", path = "../../../test-utils/runtime" } substrate-test-runtime-client = { version = "2.0.0", path = "../../../test-utils/runtime/client" } diff --git a/client/state-db/Cargo.toml b/client/state-db/Cargo.toml index fbde840fbb8e..fa0c5ed9810c 100644 --- a/client/state-db/Cargo.toml +++ b/client/state-db/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] parking_lot = "0.11.2" log = "0.4.11" sc-client-api = { version = "4.0.0-dev", path = "../api" } -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } codec = { package = "parity-scale-codec", version = "2.0.0", features = ["derive"] } parity-util-mem = { version = "0.10.2", default-features = false, features = ["primitive-types"] } parity-util-mem-derive = "0.1.0" diff --git a/client/sync-state-rpc/Cargo.toml b/client/sync-state-rpc/Cargo.toml index 0aae985319d4..eab6ffa88f15 100644 --- a/client/sync-state-rpc/Cargo.toml +++ b/client/sync-state-rpc/Cargo.toml @@ -26,5 +26,5 @@ sc-rpc-api = { version = "0.10.0-dev", path = "../rpc-api" } serde_json = "1.0.74" serde = { version = "1.0.132", features = ["derive"] } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } -sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } +sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } codec = { package = "parity-scale-codec", version = "2.0.0" } diff --git a/client/tracing/Cargo.toml b/client/tracing/Cargo.toml index 62c7f7a4becc..b8910199c0ee 100644 --- a/client/tracing/Cargo.toml +++ b/client/tracing/Cargo.toml @@ -29,11 +29,11 @@ tracing = "0.1.29" tracing-log = "0.1.2" tracing-subscriber = { version = "0.2.25", features = ["parking_lot"] } sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } -sp-rpc = { version = "4.0.0-dev", path = "../../primitives/rpc" } -sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } +sp-rpc = { version = "5.0.0", path = "../../primitives/rpc" } +sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } sc-client-api = { version = "4.0.0-dev", path = "../api" } sc-tracing-proc-macro = { version = "4.0.0-dev", path = "./proc-macro" } sc-rpc-server = { version = "4.0.0-dev", path = "../rpc-servers" } diff --git a/client/transaction-pool/Cargo.toml b/client/transaction-pool/Cargo.toml index 73ec7cfff7f3..06fc8298f01c 100644 --- a/client/transaction-pool/Cargo.toml +++ b/client/transaction-pool/Cargo.toml @@ -23,8 +23,8 @@ parking_lot = "0.11.2" prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.10.0-dev"} sc-client-api = { version = "4.0.0-dev", path = "../api" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } -sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } sp-transaction-pool = { version = "4.0.0-dev", path = "../../primitives/transaction-pool" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "./api" } diff --git a/client/transaction-pool/api/Cargo.toml b/client/transaction-pool/api/Cargo.toml index a544248a4f2c..9d7e6ea5e0f8 100644 --- a/client/transaction-pool/api/Cargo.toml +++ b/client/transaction-pool/api/Cargo.toml @@ -14,5 +14,5 @@ log = "0.4.8" serde = { version = "1.0.132", features = ["derive"] } thiserror = "1.0.30" -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../../primitives/runtime" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } diff --git a/frame/assets/Cargo.toml b/frame/assets/Cargo.toml index c250a75d4c2f..c5d60291fc43 100644 --- a/frame/assets/Cargo.toml +++ b/frame/assets/Cargo.toml @@ -17,7 +17,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } # Needed for various traits. In our case, `OnFinalize`. -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } # Needed for type-safe access to storage DB. frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } # `system` module provides us with all sorts of useful stuff and macros depend on it being around. @@ -25,9 +25,9 @@ frame-system = { version = "4.0.0-dev", default-features = false, path = "../sys frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } sp-std = { version = "4.0.0", path = "../../primitives/std" } -sp-io = { version = "4.0.0", path = "../../primitives/io" } +sp-io = { version = "5.0.0", path = "../../primitives/io" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/frame/atomic-swap/Cargo.toml b/frame/atomic-swap/Cargo.toml index 0f478ab5602f..1dcd6154d0be 100644 --- a/frame/atomic-swap/Cargo.toml +++ b/frame/atomic-swap/Cargo.toml @@ -17,10 +17,10 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } +sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } +sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } [dev-dependencies] pallet-balances = { version = "4.0.0-dev", path = "../balances" } diff --git a/frame/aura/Cargo.toml b/frame/aura/Cargo.toml index f5c71a308858..f869ddb41702 100644 --- a/frame/aura/Cargo.toml +++ b/frame/aura/Cargo.toml @@ -13,19 +13,19 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-application-crypto = { version = "4.0.0", default-features = false, path = "../../primitives/application-crypto" } +sp-application-crypto = { version = "5.0.0", default-features = false, path = "../../primitives/application-crypto" } codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } sp-consensus-aura = { version = "0.10.0-dev", path = "../../primitives/consensus/aura", default-features = false } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } pallet-timestamp = { version = "4.0.0-dev", default-features = false, path = "../timestamp" } [dev-dependencies] -sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } -sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } +sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } +sp-io = { version = "5.0.0", path = "../../primitives/io" } [features] default = ["std"] diff --git a/frame/authority-discovery/Cargo.toml b/frame/authority-discovery/Cargo.toml index c1233028df4e..b6e8a400f865 100644 --- a/frame/authority-discovery/Cargo.toml +++ b/frame/authority-discovery/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-authority-discovery = { version = "4.0.0-dev", default-features = false, path = "../../primitives/authority-discovery" } -sp-application-crypto = { version = "4.0.0", default-features = false, path = "../../primitives/application-crypto" } +sp-application-crypto = { version = "5.0.0", default-features = false, path = "../../primitives/application-crypto" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ "derive", ] } @@ -23,13 +23,13 @@ sp-std = { version = "4.0.0", default-features = false, path = "../../primitives pallet-session = { version = "4.0.0-dev", features = [ "historical", ], path = "../session", default-features = false } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } -sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-io = { version = "5.0.0", path = "../../primitives/io" } [features] default = ["std"] diff --git a/frame/authorship/Cargo.toml b/frame/authorship/Cargo.toml index c17fc49ecdcc..31daa74553c2 100644 --- a/frame/authorship/Cargo.toml +++ b/frame/authorship/Cargo.toml @@ -19,14 +19,14 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-authorship = { version = "4.0.0-dev", default-features = false, path = "../../primitives/authorship" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } impl-trait-for-tuples = "0.2.1" [dev-dependencies] -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } -sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-io = { version = "5.0.0", path = "../../primitives/io" } [features] default = ["std"] diff --git a/frame/babe/Cargo.toml b/frame/babe/Cargo.toml index 673af5c30ed6..f48877746b88 100644 --- a/frame/babe/Cargo.toml +++ b/frame/babe/Cargo.toml @@ -21,11 +21,11 @@ frame-system = { version = "4.0.0-dev", default-features = false, path = "../sys pallet-authorship = { version = "4.0.0-dev", default-features = false, path = "../authorship" } pallet-session = { version = "4.0.0-dev", default-features = false, path = "../session" } pallet-timestamp = { version = "4.0.0-dev", default-features = false, path = "../timestamp" } -sp-application-crypto = { version = "4.0.0", default-features = false, path = "../../primitives/application-crypto" } +sp-application-crypto = { version = "5.0.0", default-features = false, path = "../../primitives/application-crypto" } sp-consensus-babe = { version = "0.10.0-dev", default-features = false, path = "../../primitives/consensus/babe" } sp-consensus-vrf = { version = "0.10.0-dev", default-features = false, path = "../../primitives/consensus/vrf" } -sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../primitives/session" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } @@ -36,7 +36,7 @@ pallet-balances = { version = "4.0.0-dev", path = "../balances" } pallet-offences = { version = "4.0.0-dev", path = "../offences" } pallet-staking = { version = "4.0.0-dev", path = "../staking" } pallet-staking-reward-curve = { version = "4.0.0-dev", path = "../staking/reward-curve" } -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } frame-election-provider-support = { version = "4.0.0-dev", path = "../election-provider-support" } [features] diff --git a/frame/bags-list/Cargo.toml b/frame/bags-list/Cargo.toml index 9e802527f18d..c35ff6fc6c39 100644 --- a/frame/bags-list/Cargo.toml +++ b/frame/bags-list/Cargo.toml @@ -18,7 +18,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } # primitives -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } # FRAME @@ -32,13 +32,13 @@ log = { version = "0.4.14", default-features = false } # Optional imports for benchmarking frame-benchmarking = { version = "4.0.0-dev", path = "../benchmarking", optional = true, default-features = false } pallet-balances = { version = "4.0.0-dev", path = "../balances", optional = true, default-features = false } -sp-core = { version = "4.1.0-dev", path = "../../primitives/core", optional = true, default-features = false } -sp-io = { version = "4.0.0-dev", path = "../../primitives/io", optional = true, default-features = false } +sp-core = { version = "5.0.0", path = "../../primitives/core", optional = true, default-features = false } +sp-io = { version = "5.0.0", path = "../../primitives/io", optional = true, default-features = false } sp-tracing = { version = "4.0.0", path = "../../primitives/tracing", optional = true, default-features = false } [dev-dependencies] -sp-core = { version = "4.1.0-dev", path = "../../primitives/core"} -sp-io = { version = "4.0.0-dev", path = "../../primitives/io"} +sp-core = { version = "5.0.0", path = "../../primitives/core"} +sp-io = { version = "5.0.0", path = "../../primitives/io"} sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } frame-election-provider-support = { version = "4.0.0-dev", path = "../election-provider-support", features = ["runtime-benchmarks"] } diff --git a/frame/bags-list/remote-tests/Cargo.toml b/frame/bags-list/remote-tests/Cargo.toml index b5122ebbafe7..8f3ce53f8ebb 100644 --- a/frame/bags-list/remote-tests/Cargo.toml +++ b/frame/bags-list/remote-tests/Cargo.toml @@ -21,10 +21,10 @@ frame-system = { path = "../../system", version = "4.0.0-dev" } frame-support = { path = "../../support", version = "4.0.0-dev" } # core -sp-storage = { path = "../../../primitives/storage", version = "4.0.0" } -sp-core = { path = "../../../primitives/core", version = "4.1.0-dev" } +sp-storage = { path = "../../../primitives/storage", version = "5.0.0"} +sp-core = { path = "../../../primitives/core", version = "5.0.0"} sp-tracing = { path = "../../../primitives/tracing", version = "4.0.0" } -sp-runtime = { path = "../../../primitives/runtime", version = "4.1.0-dev" } +sp-runtime = { path = "../../../primitives/runtime", version = "5.0.0"} sp-std = { path = "../../../primitives/std", version = "4.0.0" } # utils diff --git a/frame/balances/Cargo.toml b/frame/balances/Cargo.toml index 02b94fe606c4..f594e67ab861 100644 --- a/frame/balances/Cargo.toml +++ b/frame/balances/Cargo.toml @@ -16,15 +16,15 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } log = { version = "0.4.14", default-features = false } [dev-dependencies] -sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } +sp-io = { version = "5.0.0", path = "../../primitives/io" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } pallet-transaction-payment = { version = "4.0.0-dev", path = "../transaction-payment" } [features] diff --git a/frame/beefy-mmr/Cargo.toml b/frame/beefy-mmr/Cargo.toml index c793173cc22d..cfd18b26f9c7 100644 --- a/frame/beefy-mmr/Cargo.toml +++ b/frame/beefy-mmr/Cargo.toml @@ -21,9 +21,9 @@ pallet-mmr = { version = "4.0.0-dev", path = "../merkle-mountain-range", default pallet-mmr-primitives = { version = "4.0.0-dev", path = "../merkle-mountain-range/primitives", default-features = false } pallet-session = { version = "4.0.0-dev", path = "../session", default-features = false } -sp-core = { version = "4.1.0-dev", path = "../../primitives/core", default-features = false } -sp-io = { version = "4.0.0-dev", path = "../../primitives/io", default-features = false } -sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime", default-features = false } +sp-core = { version = "5.0.0", path = "../../primitives/core", default-features = false } +sp-io = { version = "5.0.0", path = "../../primitives/io", default-features = false } +sp-runtime = { version = "5.0.0", path = "../../primitives/runtime", default-features = false } sp-std = { version = "4.0.0", path = "../../primitives/std", default-features = false } beefy-merkle-tree = { version = "4.0.0-dev", path = "./primitives", default-features = false } diff --git a/frame/beefy/Cargo.toml b/frame/beefy/Cargo.toml index 52471a332dd7..13ccfb938010 100644 --- a/frame/beefy/Cargo.toml +++ b/frame/beefy/Cargo.toml @@ -15,7 +15,7 @@ serde = { version = "1.0.132", optional = true } frame-support = { version = "4.0.0-dev", path = "../support", default-features = false } frame-system = { version = "4.0.0-dev", path = "../system", default-features = false } -sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime", default-features = false } +sp-runtime = { version = "5.0.0", path = "../../primitives/runtime", default-features = false } sp-std = { version = "4.0.0", path = "../../primitives/std", default-features = false } pallet-session = { version = "4.0.0-dev", path = "../session", default-features = false } @@ -23,8 +23,8 @@ pallet-session = { version = "4.0.0-dev", path = "../session", default-features beefy-primitives = { version = "4.0.0-dev", path = "../../primitives/beefy", default-features = false } [dev-dependencies] -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } -sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-io = { version = "5.0.0", path = "../../primitives/io" } sp-staking = { version = "4.0.0-dev", path = "../../primitives/staking" } [features] diff --git a/frame/benchmarking/Cargo.toml b/frame/benchmarking/Cargo.toml index ce110d8ba511..9afdc79fae65 100644 --- a/frame/benchmarking/Cargo.toml +++ b/frame/benchmarking/Cargo.toml @@ -18,19 +18,19 @@ paste = "1.0" codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-api = { version = "4.0.0-dev", path = "../../primitives/api", default-features = false } -sp-runtime-interface = { version = "4.1.0-dev", path = "../../primitives/runtime-interface", default-features = false } -sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime", default-features = false } +sp-runtime-interface = { version = "5.0.0", path = "../../primitives/runtime-interface", default-features = false } +sp-runtime = { version = "5.0.0", path = "../../primitives/runtime", default-features = false } sp-std = { version = "4.0.0", path = "../../primitives/std", default-features = false } -sp-io = { version = "4.0.0", path = "../../primitives/io", default-features = false } -sp-application-crypto = { version = "4.0.0", path = "../../primitives/application-crypto", default-features = false } -sp-storage = { version = "4.0.0", path = "../../primitives/storage", default-features = false } +sp-io = { version = "5.0.0", path = "../../primitives/io", default-features = false } +sp-application-crypto = { version = "5.0.0", path = "../../primitives/application-crypto", default-features = false } +sp-storage = { version = "5.0.0", path = "../../primitives/storage", default-features = false } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } log = { version = "0.4.14", default-features = false } [dev-dependencies] hex-literal = "0.3.4" -sp-keystore = { version = "0.10.0", path = "../../primitives/keystore" } +sp-keystore = { version = "0.11.0", path = "../../primitives/keystore" } [features] default = ["std"] diff --git a/frame/bounties/Cargo.toml b/frame/bounties/Cargo.toml index 73973ab18caa..477815a306f3 100644 --- a/frame/bounties/Cargo.toml +++ b/frame/bounties/Cargo.toml @@ -18,12 +18,12 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } pallet-treasury = { version = "4.0.0-dev", default-features = false, path = "../treasury" } -sp-io = { version = "4.0.0", path = "../../primitives/io", default-features = false } -sp-core = { version = "4.1.0-dev", path = "../../primitives/core", default-features = false } +sp-io = { version = "5.0.0", path = "../../primitives/io", default-features = false } +sp-core = { version = "5.0.0", path = "../../primitives/core", default-features = false } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } log = { version = "0.4.14", default-features = false } diff --git a/frame/child-bounties/Cargo.toml b/frame/child-bounties/Cargo.toml index 742110a58bff..0eeefd4de459 100644 --- a/frame/child-bounties/Cargo.toml +++ b/frame/child-bounties/Cargo.toml @@ -18,13 +18,13 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } pallet-treasury = { version = "4.0.0-dev", default-features = false, path = "../treasury" } pallet-bounties = { version = "4.0.0-dev", default-features = false, path = "../bounties" } -sp-io = { version = "4.0.0-dev", path = "../../primitives/io", default-features = false } -sp-core = { version = "4.1.0-dev", path = "../../primitives/core", default-features = false } +sp-io = { version = "5.0.0", path = "../../primitives/io", default-features = false } +sp-core = { version = "5.0.0", path = "../../primitives/core", default-features = false } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } log = { version = "0.4.14", default-features = false } diff --git a/frame/collective/Cargo.toml b/frame/collective/Cargo.toml index bd0573bace66..334b4945afa2 100644 --- a/frame/collective/Cargo.toml +++ b/frame/collective/Cargo.toml @@ -17,9 +17,9 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = log = { version = "0.4.14", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } +sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } diff --git a/frame/contracts/Cargo.toml b/frame/contracts/Cargo.toml index f0d2833c61fd..f24e393daa2e 100644 --- a/frame/contracts/Cargo.toml +++ b/frame/contracts/Cargo.toml @@ -36,11 +36,11 @@ rand_pcg = { version = "0.3", optional = true } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } -pallet-contracts-primitives = { version = "4.0.0-dev", default-features = false, path = "common" } +pallet-contracts-primitives = { version = "5.0.0", default-features = false, path = "common" } pallet-contracts-proc-macro = { version = "4.0.0-dev", path = "proc-macro" } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } +sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } sp-sandbox = { version = "0.10.0-dev", default-features = false, path = "../../primitives/sandbox" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } diff --git a/frame/contracts/common/Cargo.toml b/frame/contracts/common/Cargo.toml index 05bfc212e305..ad934c41a71f 100644 --- a/frame/contracts/common/Cargo.toml +++ b/frame/contracts/common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pallet-contracts-primitives" -version = "4.0.0-dev" +version = "5.0.0" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" @@ -19,10 +19,10 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] serde = { version = "1", features = ["derive"], optional = true } # Substrate Dependencies (This crate should not rely on frame) -sp-core = { version = "4.1.0-dev", path = "../../../primitives/core", default-features = false } +sp-core = { version = "5.0.0", path = "../../../primitives/core", default-features = false } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } -sp-rpc = { version = "4.0.0-dev", path = "../../../primitives/rpc", optional = true } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/runtime" } +sp-rpc = { version = "5.0.0", path = "../../../primitives/rpc", optional = true } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../../primitives/runtime" } [features] default = ["std"] diff --git a/frame/contracts/rpc/Cargo.toml b/frame/contracts/rpc/Cargo.toml index 9a88013c3408..52ca0e6d8345 100644 --- a/frame/contracts/rpc/Cargo.toml +++ b/frame/contracts/rpc/Cargo.toml @@ -20,13 +20,13 @@ jsonrpc-derive = "18.0.0" serde = { version = "1", features = ["derive"] } # Substrate Dependencies -pallet-contracts-primitives = { version = "4.0.0-dev", path = "../common" } +pallet-contracts-primitives = { version = "5.0.0", path = "../common" } pallet-contracts-rpc-runtime-api = { version = "4.0.0-dev", path = "./runtime-api" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } -sp-rpc = { version = "4.0.0-dev", path = "../../../primitives/rpc" } -sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } +sp-core = { version = "5.0.0", path = "../../../primitives/core" } +sp-rpc = { version = "5.0.0", path = "../../../primitives/rpc" } +sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } [dev-dependencies] serde_json = "1" diff --git a/frame/contracts/rpc/runtime-api/Cargo.toml b/frame/contracts/rpc/runtime-api/Cargo.toml index bb70d0835d26..8ecdff517537 100644 --- a/frame/contracts/rpc/runtime-api/Cargo.toml +++ b/frame/contracts/rpc/runtime-api/Cargo.toml @@ -17,9 +17,9 @@ codec = { package = "parity-scale-codec", version = "2", default-features = fals scale-info = { version = "1.0", default-features = false, features = ["derive"] } # Substrate Dependencies -pallet-contracts-primitives = { version = "4.0.0-dev", default-features = false, path = "../../common" } +pallet-contracts-primitives = { version = "5.0.0", default-features = false, path = "../../common" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/api" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../../primitives/runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../../../primitives/std" } [features] diff --git a/frame/democracy/Cargo.toml b/frame/democracy/Cargo.toml index 730bc6fffbdf..125decaca824 100644 --- a/frame/democracy/Cargo.toml +++ b/frame/democracy/Cargo.toml @@ -19,14 +19,14 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } pallet-scheduler = { version = "4.0.0-dev", path = "../scheduler" } diff --git a/frame/election-provider-multi-phase/Cargo.toml b/frame/election-provider-multi-phase/Cargo.toml index 062e63f5fdf1..c0d85737ec22 100644 --- a/frame/election-provider-multi-phase/Cargo.toml +++ b/frame/election-provider-multi-phase/Cargo.toml @@ -23,10 +23,10 @@ log = { version = "0.4.14", default-features = false } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } -sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } +sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } sp-npos-elections = { version = "4.0.0-dev", default-features = false, path = "../../primitives/npos-elections" } sp-arithmetic = { version = "4.0.0", default-features = false, path = "../../primitives/arithmetic" } frame-election-provider-support = { version = "4.0.0-dev", default-features = false, path = "../election-provider-support" } @@ -42,8 +42,8 @@ strum = { optional = true, default-features = false, version = "0.23.0", feature [dev-dependencies] parking_lot = "0.11.2" rand = { version = "0.7.3" } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } -sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } +sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } +sp-io = { version = "5.0.0", path = "../../primitives/io" } sp-npos-elections = { version = "4.0.0-dev", default-features = false, path = "../../primitives/npos-elections" } sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } frame-election-provider-support = { version = "4.0.0-dev", features = [ diff --git a/frame/election-provider-support/Cargo.toml b/frame/election-provider-support/Cargo.toml index 1cb477d6c79c..662762ef6306 100644 --- a/frame/election-provider-support/Cargo.toml +++ b/frame/election-provider-support/Cargo.toml @@ -23,9 +23,9 @@ frame-system = { version = "4.0.0-dev", default-features = false, path = "../sys [dev-dependencies] sp-npos-elections = { version = "4.0.0-dev", path = "../../primitives/npos-elections" } -sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } -sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } +sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-io = { version = "5.0.0", path = "../../primitives/io" } [features] default = ["std"] diff --git a/frame/elections-phragmen/Cargo.toml b/frame/elections-phragmen/Cargo.toml index 867b1627272a..f70eb568349b 100644 --- a/frame/elections-phragmen/Cargo.toml +++ b/frame/elections-phragmen/Cargo.toml @@ -17,19 +17,19 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = "derive", ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } sp-npos-elections = { version = "4.0.0-dev", default-features = false, path = "../../primitives/npos-elections" } -sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } +sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } +sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } log = { version = "0.4.14", default-features = false } [dev-dependencies] pallet-balances = { version = "4.0.0-dev", path = "../balances" } -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } substrate-test-utils = { version = "4.0.0-dev", path = "../../test-utils" } [features] diff --git a/frame/examples/basic/Cargo.toml b/frame/examples/basic/Cargo.toml index 894b9b4d5010..73c11475fdf6 100644 --- a/frame/examples/basic/Cargo.toml +++ b/frame/examples/basic/Cargo.toml @@ -21,12 +21,12 @@ frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = " frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" } pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../../balances" } -sp-io = { version = "4.0.0", default-features = false, path = "../../../primitives/io" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/runtime" } +sp-io = { version = "5.0.0", default-features = false, path = "../../../primitives/io" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } [dev-dependencies] -sp-core = { version = "4.1.0-dev", path = "../../../primitives/core", default-features = false } +sp-core = { version = "5.0.0", path = "../../../primitives/core", default-features = false } [features] default = ["std"] diff --git a/frame/examples/offchain-worker/Cargo.toml b/frame/examples/offchain-worker/Cargo.toml index 68ad2125eef4..e7ae323050ee 100644 --- a/frame/examples/offchain-worker/Cargo.toml +++ b/frame/examples/offchain-worker/Cargo.toml @@ -20,10 +20,10 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/io" } -sp-keystore = { version = "0.10.0", path = "../../../primitives/keystore", optional = true } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/runtime" } +sp-core = { version = "5.0.0", default-features = false, path = "../../../primitives/core" } +sp-io = { version = "5.0.0", default-features = false, path = "../../../primitives/io" } +sp-keystore = { version = "0.11.0", path = "../../../primitives/keystore", optional = true } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } [features] diff --git a/frame/examples/parallel/Cargo.toml b/frame/examples/parallel/Cargo.toml index b3ec1a72506b..8d291df19136 100644 --- a/frame/examples/parallel/Cargo.toml +++ b/frame/examples/parallel/Cargo.toml @@ -17,9 +17,9 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/io" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/runtime" } +sp-core = { version = "5.0.0", default-features = false, path = "../../../primitives/core" } +sp-io = { version = "5.0.0", default-features = false, path = "../../../primitives/io" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } sp-tasks = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/tasks" } diff --git a/frame/executive/Cargo.toml b/frame/executive/Cargo.toml index 1b6a237f3b93..b261aecdf926 100644 --- a/frame/executive/Cargo.toml +++ b/frame/executive/Cargo.toml @@ -19,16 +19,16 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } sp-tracing = { version = "4.0.0", default-features = false, path = "../../primitives/tracing" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } +sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } +sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } [dev-dependencies] hex-literal = "0.3.4" -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } -sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-io = { version = "5.0.0", path = "../../primitives/io" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } pallet-transaction-payment = { version = "4.0.0-dev", path = "../transaction-payment" } sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } diff --git a/frame/gilt/Cargo.toml b/frame/gilt/Cargo.toml index b958b7ba337f..7ed17d152a01 100644 --- a/frame/gilt/Cargo.toml +++ b/frame/gilt/Cargo.toml @@ -16,15 +16,15 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } sp-arithmetic = { version = "4.0.0", default-features = false, path = "../../primitives/arithmetic" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } [dev-dependencies] -sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } +sp-io = { version = "5.0.0", path = "../../primitives/io" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/frame/grandpa/Cargo.toml b/frame/grandpa/Cargo.toml index 4b2ab7eca871..002ceed36929 100644 --- a/frame/grandpa/Cargo.toml +++ b/frame/grandpa/Cargo.toml @@ -15,13 +15,13 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-application-crypto = { version = "4.0.0", default-features = false, path = "../../primitives/application-crypto" } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } +sp-application-crypto = { version = "5.0.0", default-features = false, path = "../../primitives/application-crypto" } +sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } sp-finality-grandpa = { version = "4.0.0-dev", default-features = false, path = "../../primitives/finality-grandpa" } -sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } +sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../primitives/session" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/frame/identity/Cargo.toml b/frame/identity/Cargo.toml index 00be4d767ec2..209896ec0e55 100644 --- a/frame/identity/Cargo.toml +++ b/frame/identity/Cargo.toml @@ -17,14 +17,14 @@ codec = { package = "parity-scale-codec", version = "2.2.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } enumflags2 = { version = "0.6.2" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/frame/im-online/Cargo.toml b/frame/im-online/Cargo.toml index 9d659d304dbb..d223e5e8502d 100644 --- a/frame/im-online/Cargo.toml +++ b/frame/im-online/Cargo.toml @@ -13,14 +13,14 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-application-crypto = { version = "4.0.0", default-features = false, path = "../../primitives/application-crypto" } +sp-application-crypto = { version = "5.0.0", default-features = false, path = "../../primitives/application-crypto" } pallet-authorship = { version = "4.0.0-dev", default-features = false, path = "../authorship" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } +sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/indices/Cargo.toml b/frame/indices/Cargo.toml index a2998c7cfae9..487eb4716422 100644 --- a/frame/indices/Cargo.toml +++ b/frame/indices/Cargo.toml @@ -17,9 +17,9 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-keyring = { version = "4.1.0-dev", optional = true, path = "../../primitives/keyring" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } +sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/lottery/Cargo.toml b/frame/lottery/Cargo.toml index cef152a18588..2e2c2287a2ab 100644 --- a/frame/lottery/Cargo.toml +++ b/frame/lottery/Cargo.toml @@ -18,7 +18,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } @@ -27,8 +27,8 @@ frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = " [dev-dependencies] frame-support-test = { version = "3.0.0", path = "../support/test" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } -sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-io = { version = "5.0.0", path = "../../primitives/io" } [features] default = ["std"] diff --git a/frame/membership/Cargo.toml b/frame/membership/Cargo.toml index 7ded2fd586e1..f2f7607ce9a5 100644 --- a/frame/membership/Cargo.toml +++ b/frame/membership/Cargo.toml @@ -17,9 +17,9 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } log = { version = "0.4.0", default-features = false } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } +sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } diff --git a/frame/merkle-mountain-range/Cargo.toml b/frame/merkle-mountain-range/Cargo.toml index 495b0add5b1c..a614ffa97715 100644 --- a/frame/merkle-mountain-range/Cargo.toml +++ b/frame/merkle-mountain-range/Cargo.toml @@ -16,9 +16,9 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } mmr-lib = { package = "ckb-merkle-mountain-range", default-features = false, version = "0.3.2" } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } +sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } diff --git a/frame/merkle-mountain-range/primitives/Cargo.toml b/frame/merkle-mountain-range/primitives/Cargo.toml index 2e483360facc..9df5094abd81 100644 --- a/frame/merkle-mountain-range/primitives/Cargo.toml +++ b/frame/merkle-mountain-range/primitives/Cargo.toml @@ -17,8 +17,8 @@ log = { version = "0.4.14", default-features = false } serde = { version = "1.0.132", optional = true, features = ["derive"] } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/api" } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/runtime" } +sp-core = { version = "5.0.0", default-features = false, path = "../../../primitives/core" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" } diff --git a/frame/merkle-mountain-range/rpc/Cargo.toml b/frame/merkle-mountain-range/rpc/Cargo.toml index d6bf66cefefb..575b2a79fcd2 100644 --- a/frame/merkle-mountain-range/rpc/Cargo.toml +++ b/frame/merkle-mountain-range/rpc/Cargo.toml @@ -21,8 +21,8 @@ serde = { version = "1.0.132", features = ["derive"] } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } -sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } +sp-core = { version = "5.0.0", path = "../../../primitives/core" } +sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } pallet-mmr-primitives = { version = "4.0.0-dev", path = "../primitives" } diff --git a/frame/multisig/Cargo.toml b/frame/multisig/Cargo.toml index 696f8afe0d85..dfc05888b1aa 100644 --- a/frame/multisig/Cargo.toml +++ b/frame/multisig/Cargo.toml @@ -17,14 +17,14 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } +sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/frame/nicks/Cargo.toml b/frame/nicks/Cargo.toml index 221a386c752a..bf5afd26ebb5 100644 --- a/frame/nicks/Cargo.toml +++ b/frame/nicks/Cargo.toml @@ -16,13 +16,13 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/frame/node-authorization/Cargo.toml b/frame/node-authorization/Cargo.toml index 610e536a2c81..0d6425188538 100644 --- a/frame/node-authorization/Cargo.toml +++ b/frame/node-authorization/Cargo.toml @@ -16,9 +16,9 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } +sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } log = { version = "0.4.14", default-features = false } diff --git a/frame/offences/Cargo.toml b/frame/offences/Cargo.toml index 49aa1d770e5b..6fe36aea89ee 100644 --- a/frame/offences/Cargo.toml +++ b/frame/offences/Cargo.toml @@ -18,15 +18,15 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } serde = { version = "1.0.132", optional = true } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } log = { version = "0.4.14", default-features = false } [dev-dependencies] -sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } +sp-io = { version = "5.0.0", path = "../../primitives/io" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } [features] default = ["std"] diff --git a/frame/offences/benchmarking/Cargo.toml b/frame/offences/benchmarking/Cargo.toml index 2764eedc1191..974254538322 100644 --- a/frame/offences/benchmarking/Cargo.toml +++ b/frame/offences/benchmarking/Cargo.toml @@ -29,7 +29,7 @@ pallet-session = { version = "4.0.0-dev", default-features = false, path = "../. pallet-staking = { version = "4.0.0-dev", default-features = false, features = [ "runtime-benchmarks", ], path = "../../staking" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../../primitives/runtime" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/staking" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } frame-election-provider-support = { version = "4.0.0-dev", default-features = false, path = "../../election-provider-support" } @@ -37,8 +37,8 @@ frame-election-provider-support = { version = "4.0.0-dev", default-features = fa [dev-dependencies] pallet-staking-reward-curve = { version = "4.0.0-dev", path = "../../staking/reward-curve" } pallet-timestamp = { version = "4.0.0-dev", path = "../../timestamp" } -sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } -sp-io = { version = "4.0.0-dev", path = "../../../primitives/io" } +sp-core = { version = "5.0.0", path = "../../../primitives/core" } +sp-io = { version = "5.0.0", path = "../../../primitives/io" } [features] default = ["std"] diff --git a/frame/preimage/Cargo.toml b/frame/preimage/Cargo.toml index 17fed986f757..66ef8467be28 100644 --- a/frame/preimage/Cargo.toml +++ b/frame/preimage/Cargo.toml @@ -14,15 +14,15 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-core = { version = "4.1.0-dev", default-features = false, optional = true, path = "../../primitives/core" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } +sp-core = { version = "5.0.0", default-features = false, optional = true, path = "../../primitives/core" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -sp-core = { version = "4.1.0-dev", path = "../../primitives/core", default-features = false } +sp-core = { version = "5.0.0", path = "../../primitives/core", default-features = false } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/frame/proxy/Cargo.toml b/frame/proxy/Cargo.toml index a07ecb499774..f0bd9391789b 100644 --- a/frame/proxy/Cargo.toml +++ b/frame/proxy/Cargo.toml @@ -17,14 +17,14 @@ codec = { package = "parity-scale-codec", version = "2.2.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } -sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } pallet-utility = { version = "4.0.0-dev", path = "../utility" } diff --git a/frame/randomness-collective-flip/Cargo.toml b/frame/randomness-collective-flip/Cargo.toml index a29e7ac7b326..a93585700f2b 100644 --- a/frame/randomness-collective-flip/Cargo.toml +++ b/frame/randomness-collective-flip/Cargo.toml @@ -16,15 +16,15 @@ targets = ["x86_64-unknown-linux-gnu"] safe-mix = { version = "1.0", default-features = false } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } -sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-io = { version = "5.0.0", path = "../../primitives/io" } [features] default = ["std"] diff --git a/frame/recovery/Cargo.toml b/frame/recovery/Cargo.toml index 53fe6851564d..88da65327e2f 100644 --- a/frame/recovery/Cargo.toml +++ b/frame/recovery/Cargo.toml @@ -16,13 +16,13 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/frame/scheduler/Cargo.toml b/frame/scheduler/Cargo.toml index 424c3852862e..d88063d69c5b 100644 --- a/frame/scheduler/Cargo.toml +++ b/frame/scheduler/Cargo.toml @@ -14,15 +14,15 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } log = { version = "0.4.14", default-features = false } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } +sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -sp-core = { version = "4.1.0-dev", path = "../../primitives/core", default-features = false } +sp-core = { version = "5.0.0", path = "../../primitives/core", default-features = false } substrate-test-utils = { version = "4.0.0-dev", path = "../../test-utils" } pallet-preimage = { version = "4.0.0-dev", path = "../preimage" } diff --git a/frame/scored-pool/Cargo.toml b/frame/scored-pool/Cargo.toml index b97a7e366490..af8b0f6aa264 100644 --- a/frame/scored-pool/Cargo.toml +++ b/frame/scored-pool/Cargo.toml @@ -15,15 +15,15 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } [dev-dependencies] pallet-balances = { version = "4.0.0-dev", path = "../balances" } -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } [features] default = ["std"] diff --git a/frame/session/Cargo.toml b/frame/session/Cargo.toml index db6f10c72888..a342865615d9 100644 --- a/frame/session/Cargo.toml +++ b/frame/session/Cargo.toml @@ -20,12 +20,12 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } +sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../primitives/session" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" } -sp-trie = { version = "4.0.0", default-features = false, path = "../../primitives/trie", optional = true } +sp-trie = { version = "5.0.0", default-features = false, path = "../../primitives/trie", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/session/benchmarking/Cargo.toml b/frame/session/benchmarking/Cargo.toml index 10a430d52b0a..cd33c5b18649 100644 --- a/frame/session/benchmarking/Cargo.toml +++ b/frame/session/benchmarking/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] rand = { version = "0.7.2", default-features = false } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../../primitives/runtime" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/session" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../../benchmarking" } @@ -28,8 +28,8 @@ pallet-staking = { version = "4.0.0-dev", default-features = false, features = [ [dev-dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", features = ["derive"] } scale-info = "1.0" -sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } -sp-io = { version = "4.0.0-dev", path = "../../../primitives/io" } +sp-core = { version = "5.0.0", path = "../../../primitives/core" } +sp-io = { version = "5.0.0", path = "../../../primitives/io" } pallet-balances = { version = "4.0.0-dev", path = "../../balances" } pallet-timestamp = { version = "4.0.0-dev", path = "../../timestamp" } pallet-staking-reward-curve = { version = "4.0.0-dev", path = "../../staking/reward-curve" } diff --git a/frame/society/Cargo.toml b/frame/society/Cargo.toml index fa3f981f19d4..2787453d49d3 100644 --- a/frame/society/Cargo.toml +++ b/frame/society/Cargo.toml @@ -15,15 +15,15 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } rand_chacha = { version = "0.2", default-features = false } [dev-dependencies] -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } -sp-io ={ version = "4.0.0-dev", path = "../../primitives/io" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-io ={ version = "5.0.0", path = "../../primitives/io" } frame-support-test = { version = "3.0.0", path = "../support/test" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } diff --git a/frame/staking/Cargo.toml b/frame/staking/Cargo.toml index e0d5dabaa892..cd1e238dbd01 100644 --- a/frame/staking/Cargo.toml +++ b/frame/staking/Cargo.toml @@ -19,8 +19,8 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } @@ -28,7 +28,7 @@ pallet-session = { version = "4.0.0-dev", default-features = false, features = [ "historical", ], path = "../session" } pallet-authorship = { version = "4.0.0-dev", default-features = false, path = "../authorship" } -sp-application-crypto = { version = "4.0.0", default-features = false, path = "../../primitives/application-crypto" } +sp-application-crypto = { version = "5.0.0", default-features = false, path = "../../primitives/application-crypto" } frame-election-provider-support = { version = "4.0.0-dev", default-features = false, path = "../election-provider-support" } log = { version = "0.4.14", default-features = false } @@ -38,7 +38,7 @@ rand_chacha = { version = "0.2", default-features = false, optional = true } [dev-dependencies] sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } sp-npos-elections = { version = "4.0.0-dev", path = "../../primitives/npos-elections" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } pallet-timestamp = { version = "4.0.0-dev", path = "../timestamp" } diff --git a/frame/staking/reward-curve/Cargo.toml b/frame/staking/reward-curve/Cargo.toml index 4c1d2b922f6d..86fdd09076e5 100644 --- a/frame/staking/reward-curve/Cargo.toml +++ b/frame/staking/reward-curve/Cargo.toml @@ -21,4 +21,4 @@ proc-macro2 = "1.0.36" proc-macro-crate = "1.1.0" [dev-dependencies] -sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } +sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } diff --git a/frame/sudo/Cargo.toml b/frame/sudo/Cargo.toml index 504eb37b8d00..063ea52d5b8b 100644 --- a/frame/sudo/Cargo.toml +++ b/frame/sudo/Cargo.toml @@ -16,13 +16,13 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } [features] default = ["std"] diff --git a/frame/support/Cargo.toml b/frame/support/Cargo.toml index d652e5ea4344..5e8c26b6ae54 100644 --- a/frame/support/Cargo.toml +++ b/frame/support/Cargo.toml @@ -18,10 +18,10 @@ codec = { package = "parity-scale-codec", version = "2.2.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } frame-metadata = { version = "14.2.0", default-features = false, features = ["v14"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } sp-tracing = { version = "4.0.0", default-features = false, path = "../../primitives/tracing" } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } +sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } sp-arithmetic = { version = "4.0.0", default-features = false, path = "../../primitives/arithmetic" } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../primitives/inherents" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" } @@ -29,7 +29,7 @@ tt-call = "1.0.8" frame-support-procedural = { version = "4.0.0-dev", default-features = false, path = "./procedural" } paste = "1.0" once_cell = { version = "1", default-features = false, optional = true } -sp-state-machine = { version = "0.10.0", optional = true, path = "../../primitives/state-machine" } +sp-state-machine = { version = "0.11.0", optional = true, path = "../../primitives/state-machine" } bitflags = "1.3" impl-trait-for-tuples = "0.2.1" smallvec = "1.7.0" diff --git a/frame/support/test/Cargo.toml b/frame/support/test/Cargo.toml index 257cca3218da..5a27f4f46e10 100644 --- a/frame/support/test/Cargo.toml +++ b/frame/support/test/Cargo.toml @@ -16,11 +16,11 @@ serde = { version = "1.0.132", default-features = false, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-arithmetic = { version = "4.0.0", default-features = false, path = "../../../primitives/arithmetic" } -sp-io = { version = "4.0.0", path = "../../../primitives/io", default-features = false } -sp-state-machine = { version = "0.10.0", optional = true, path = "../../../primitives/state-machine" } +sp-io = { version = "5.0.0", path = "../../../primitives/io", default-features = false } +sp-state-machine = { version = "0.11.0", optional = true, path = "../../../primitives/state-machine" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/runtime" } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../../primitives/runtime" } +sp-core = { version = "5.0.0", default-features = false, path = "../../../primitives/core" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } sp-version = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/version" } trybuild = "1.0.53" diff --git a/frame/support/test/compile_pass/Cargo.toml b/frame/support/test/compile_pass/Cargo.toml index 93443e33503c..aaa080f84f1a 100644 --- a/frame/support/test/compile_pass/Cargo.toml +++ b/frame/support/test/compile_pass/Cargo.toml @@ -14,8 +14,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../../primitives/core" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../../primitives/runtime" } +sp-core = { version = "5.0.0", default-features = false, path = "../../../../primitives/core" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../../../primitives/runtime" } sp-version = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/version" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../../" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../../system" } diff --git a/frame/system/Cargo.toml b/frame/system/Cargo.toml index ae9242087f1a..f1e7e4e20755 100644 --- a/frame/system/Cargo.toml +++ b/frame/system/Cargo.toml @@ -16,17 +16,17 @@ targets = ["x86_64-unknown-linux-gnu"] serde = { version = "1.0.132", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } +sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "4.0.0", path = "../../primitives/io", default-features = false } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "5.0.0", path = "../../primitives/io", default-features = false } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } sp-version = { version = "4.0.0-dev", default-features = false, path = "../../primitives/version" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } log = { version = "0.4.14", default-features = false } [dev-dependencies] criterion = "0.3.3" -sp-externalities = { version = "0.10.0", path = "../../primitives/externalities" } +sp-externalities = { version = "0.11.0", path = "../../primitives/externalities" } substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } [features] diff --git a/frame/system/benchmarking/Cargo.toml b/frame/system/benchmarking/Cargo.toml index 4ca250fa0ec7..fa86250c199e 100644 --- a/frame/system/benchmarking/Cargo.toml +++ b/frame/system/benchmarking/Cargo.toml @@ -16,14 +16,14 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../../primitives/runtime" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../../benchmarking" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } +sp-core = { version = "5.0.0", default-features = false, path = "../../../primitives/core" } [dev-dependencies] -sp-io = { version = "4.0.0", path = "../../../primitives/io" } +sp-io = { version = "5.0.0", path = "../../../primitives/io" } [features] default = ["std"] diff --git a/frame/timestamp/Cargo.toml b/frame/timestamp/Cargo.toml index b66a91acebaa..f42a95010587 100644 --- a/frame/timestamp/Cargo.toml +++ b/frame/timestamp/Cargo.toml @@ -18,8 +18,8 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io", optional = true } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io", optional = true } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../primitives/inherents" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } @@ -28,8 +28,8 @@ sp-timestamp = { version = "4.0.0-dev", default-features = false, path = "../../ log = { version = "0.4.14", default-features = false } [dev-dependencies] -sp-io ={ version = "4.0.0-dev", path = "../../primitives/io" } -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } +sp-io ={ version = "5.0.0", path = "../../primitives/io" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } [features] default = ["std"] diff --git a/frame/tips/Cargo.toml b/frame/tips/Cargo.toml index bbe78fd30a56..182a87048d35 100644 --- a/frame/tips/Cargo.toml +++ b/frame/tips/Cargo.toml @@ -18,9 +18,9 @@ log = { version = "0.4.0", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } serde = { version = "1.0.132", features = ["derive"], optional = true } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } +sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } @@ -30,7 +30,7 @@ pallet-treasury = { version = "4.0.0-dev", default-features = false, path = "../ frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -sp-storage = { version = "4.0.0", path = "../../primitives/storage" } +sp-storage = { version = "5.0.0", path = "../../primitives/storage" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/frame/transaction-payment/Cargo.toml b/frame/transaction-payment/Cargo.toml index 8cb544159dd7..b9b46380a386 100644 --- a/frame/transaction-payment/Cargo.toml +++ b/frame/transaction-payment/Cargo.toml @@ -20,9 +20,9 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] serde = { version = "1.0.132", optional = true } smallvec = "1.7.0" -sp-core = { version = "4.1.0-dev", path = "../../primitives/core", default-features = false } -sp-io = { version = "4.0.0-dev", path = "../../primitives/io", default-features = false } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-core = { version = "5.0.0", path = "../../primitives/core", default-features = false } +sp-io = { version = "5.0.0", path = "../../primitives/io", default-features = false } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/frame/transaction-payment/asset-tx-payment/Cargo.toml b/frame/transaction-payment/asset-tx-payment/Cargo.toml index ab2d3302f95b..300d05d0ed9a 100644 --- a/frame/transaction-payment/asset-tx-payment/Cargo.toml +++ b/frame/transaction-payment/asset-tx-payment/Cargo.toml @@ -14,9 +14,9 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] # Substrate dependencies -sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/io" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/runtime" } +sp-core = { version = "5.0.0", default-features = false, path = "../../../primitives/core" } +sp-io = { version = "5.0.0", default-features = false, path = "../../../primitives/io" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" } @@ -32,7 +32,7 @@ serde = { version = "1.0.132", optional = true } smallvec = "1.7.0" serde_json = "1.0.74" -sp-storage = { version = "4.0.0", default-features = false, path = "../../../primitives/storage" } +sp-storage = { version = "5.0.0", default-features = false, path = "../../../primitives/storage" } pallet-assets = { version = "4.0.0-dev", path = "../../assets" } pallet-authorship = { version = "4.0.0-dev", path = "../../authorship" } diff --git a/frame/transaction-payment/rpc/Cargo.toml b/frame/transaction-payment/rpc/Cargo.toml index 2486654404ae..844e898ed867 100644 --- a/frame/transaction-payment/rpc/Cargo.toml +++ b/frame/transaction-payment/rpc/Cargo.toml @@ -20,7 +20,7 @@ jsonrpc-derive = "18.0.0" sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } -sp-rpc = { version = "4.0.0-dev", path = "../../../primitives/rpc" } -sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } +sp-core = { version = "5.0.0", path = "../../../primitives/core" } +sp-rpc = { version = "5.0.0", path = "../../../primitives/rpc" } +sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } pallet-transaction-payment-rpc-runtime-api = { version = "4.0.0-dev", path = "./runtime-api" } diff --git a/frame/transaction-payment/rpc/runtime-api/Cargo.toml b/frame/transaction-payment/rpc/runtime-api/Cargo.toml index 1ad56280ac08..fed57eb5bf73 100644 --- a/frame/transaction-payment/rpc/runtime-api/Cargo.toml +++ b/frame/transaction-payment/rpc/runtime-api/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/api" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../../primitives/runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../../../primitives/runtime" } pallet-transaction-payment = { version = "4.0.0-dev", default-features = false, path = "../../../transaction-payment" } [features] diff --git a/frame/transaction-storage/Cargo.toml b/frame/transaction-storage/Cargo.toml index e4351438811f..5adf5fd2c1f0 100644 --- a/frame/transaction-storage/Cargo.toml +++ b/frame/transaction-storage/Cargo.toml @@ -20,16 +20,16 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../balances" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } +sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../primitives/inherents" } sp-transaction-storage-proof = { version = "4.0.0-dev", default-features = false, path = "../../primitives/transaction-storage-proof" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] sp-transaction-storage-proof = { version = "4.0.0-dev", default-features = true, path = "../../primitives/transaction-storage-proof" } -sp-core = { version = "4.1.0-dev", path = "../../primitives/core", default-features = false } +sp-core = { version = "5.0.0", path = "../../primitives/core", default-features = false } [features] default = ["std"] diff --git a/frame/treasury/Cargo.toml b/frame/treasury/Cargo.toml index 0a2dab417e34..d126d0ffa34b 100644 --- a/frame/treasury/Cargo.toml +++ b/frame/treasury/Cargo.toml @@ -22,7 +22,7 @@ serde = { version = "1.0.132", features = ["derive"], optional = true } impl-trait-for-tuples = "0.2.1" sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } @@ -31,8 +31,8 @@ pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../ [dev-dependencies] -sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } +sp-io = { version = "5.0.0", path = "../../primitives/io" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } [features] default = ["std"] diff --git a/frame/try-runtime/Cargo.toml b/frame/try-runtime/Cargo.toml index 905c58ab00be..0546c0a898fb 100644 --- a/frame/try-runtime/Cargo.toml +++ b/frame/try-runtime/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-api = { version = "4.0.0-dev", path = "../../primitives/api", default-features = false } sp-std = { version = "4.0.0", path = "../../primitives/std" , default-features = false } -sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" , default-features = false } +sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" , default-features = false } frame-support = { version = "4.0.0-dev", path = "../support", default-features = false } diff --git a/frame/uniques/Cargo.toml b/frame/uniques/Cargo.toml index 38c519f80167..4e0194b17acb 100644 --- a/frame/uniques/Cargo.toml +++ b/frame/uniques/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } @@ -24,8 +24,8 @@ log = { version = "0.4.14", default-features = false } [dev-dependencies] sp-std = { version = "4.0.0", path = "../../primitives/std" } -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } -sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-io = { version = "5.0.0", path = "../../primitives/io" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/frame/utility/Cargo.toml b/frame/utility/Cargo.toml index 85f522975dbb..ea3977c1b8b2 100644 --- a/frame/utility/Cargo.toml +++ b/frame/utility/Cargo.toml @@ -17,15 +17,15 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } +sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/frame/vesting/Cargo.toml b/frame/vesting/Cargo.toml index e488e282cd45..f7dcfd9fa442 100644 --- a/frame/vesting/Cargo.toml +++ b/frame/vesting/Cargo.toml @@ -18,15 +18,15 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } log = { version = "0.4.0", default-features = false } [dev-dependencies] -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } +sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/primitives/api/Cargo.toml b/primitives/api/Cargo.toml index f2c3e67800dc..ab81ed85f188 100644 --- a/primitives/api/Cargo.toml +++ b/primitives/api/Cargo.toml @@ -15,11 +15,11 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } sp-api-proc-macro = { version = "4.0.0-dev", path = "proc-macro" } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } +sp-core = { version = "5.0.0", default-features = false, path = "../core" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../runtime" } sp-version = { version = "4.0.0-dev", default-features = false, path = "../version" } -sp-state-machine = { version = "0.10.0", optional = true, path = "../state-machine" } +sp-state-machine = { version = "0.11.0", optional = true, path = "../state-machine" } hash-db = { version = "0.15.2", optional = true } thiserror = { version = "1.0.30", optional = true } diff --git a/primitives/api/test/Cargo.toml b/primitives/api/test/Cargo.toml index 79e302c4c065..064e6a6c9818 100644 --- a/primitives/api/test/Cargo.toml +++ b/primitives/api/test/Cargo.toml @@ -16,11 +16,11 @@ sp-api = { version = "4.0.0-dev", path = "../" } substrate-test-runtime-client = { version = "2.0.0", path = "../../../test-utils/runtime/client" } sp-version = { version = "4.0.0-dev", path = "../../version" } sp-tracing = { version = "4.0.0", path = "../../tracing" } -sp-runtime = { version = "4.1.0-dev", path = "../../runtime" } +sp-runtime = { version = "5.0.0", path = "../../runtime" } sp-consensus = { version = "0.10.0-dev", path = "../../consensus/common" } sc-block-builder = { version = "0.10.0-dev", path = "../../../client/block-builder" } codec = { package = "parity-scale-codec", version = "2.0.0" } -sp-state-machine = { version = "0.10.0", path = "../../state-machine" } +sp-state-machine = { version = "0.11.0", path = "../../state-machine" } trybuild = "1.0.53" rustversion = "1.0.6" @@ -28,7 +28,7 @@ rustversion = "1.0.6" criterion = "0.3.0" futures = "0.3.9" log = "0.4.14" -sp-core = { version = "4.1.0-dev", path = "../../core" } +sp-core = { version = "5.0.0", path = "../../core" } [[bench]] name = "bench" diff --git a/primitives/application-crypto/Cargo.toml b/primitives/application-crypto/Cargo.toml index 75766905d14f..a3dfa8646e79 100644 --- a/primitives/application-crypto/Cargo.toml +++ b/primitives/application-crypto/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-application-crypto" -version = "4.0.0" +version = "5.0.0" authors = ["Parity Technologies "] edition = "2021" description = "Provides facilities for generating application specific crypto wrapper types." @@ -15,12 +15,12 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } +sp-core = { version = "5.0.0", default-features = false, path = "../core" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } serde = { version = "1.0.132", optional = true, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../std" } -sp-io = { version = "4.0.0", default-features = false, path = "../io" } +sp-io = { version = "5.0.0", default-features = false, path = "../io" } [features] default = [ "std" ] diff --git a/primitives/application-crypto/test/Cargo.toml b/primitives/application-crypto/test/Cargo.toml index 178932869611..515be41be3d2 100644 --- a/primitives/application-crypto/test/Cargo.toml +++ b/primitives/application-crypto/test/Cargo.toml @@ -13,9 +13,9 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-core = { version = "4.1.0-dev", default-features = false, path = "../../core" } -sp-keystore = { version = "0.10.0", path = "../../keystore", default-features = false } +sp-core = { version = "5.0.0", default-features = false, path = "../../core" } +sp-keystore = { version = "0.11.0", path = "../../keystore", default-features = false } substrate-test-runtime-client = { version = "2.0.0", path = "../../../test-utils/runtime/client" } -sp-runtime = { version = "4.1.0-dev", path = "../../runtime" } +sp-runtime = { version = "5.0.0", path = "../../runtime" } sp-api = { version = "4.0.0-dev", path = "../../api" } -sp-application-crypto = { version = "4.0.0", path = "../" } +sp-application-crypto = { version = "5.0.0", path = "../" } diff --git a/primitives/authority-discovery/Cargo.toml b/primitives/authority-discovery/Cargo.toml index 2fd2c4847692..7c6aa7a6ea00 100644 --- a/primitives/authority-discovery/Cargo.toml +++ b/primitives/authority-discovery/Cargo.toml @@ -13,12 +13,12 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-application-crypto = { version = "4.0.0", default-features = false, path = "../application-crypto" } +sp-application-crypto = { version = "5.0.0", default-features = false, path = "../application-crypto" } codec = { package = "parity-scale-codec", default-features = false, version = "2.0.0" } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../runtime" } [features] default = ["std"] diff --git a/primitives/authorship/Cargo.toml b/primitives/authorship/Cargo.toml index 8e97942499aa..4cf8e6e9522d 100644 --- a/primitives/authorship/Cargo.toml +++ b/primitives/authorship/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../inherents" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } async-trait = { version = "0.1.50", optional = true } diff --git a/primitives/beefy/Cargo.toml b/primitives/beefy/Cargo.toml index edcb2244e58f..9d8ec2a653ea 100644 --- a/primitives/beefy/Cargo.toml +++ b/primitives/beefy/Cargo.toml @@ -12,15 +12,15 @@ codec = { version = "2.2.0", package = "parity-scale-codec", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-api = { version = "4.0.0-dev", path = "../api", default-features = false } -sp-application-crypto = { version = "4.0.0", path = "../application-crypto", default-features = false } -sp-core = { version = "4.1.0-dev", path = "../core", default-features = false } -sp-runtime = { version = "4.1.0-dev", path = "../runtime", default-features = false } +sp-application-crypto = { version = "5.0.0", path = "../application-crypto", default-features = false } +sp-core = { version = "5.0.0", path = "../core", default-features = false } +sp-runtime = { version = "5.0.0", path = "../runtime", default-features = false } sp-std = { version = "4.0.0", path = "../std", default-features = false } [dev-dependencies] hex = "0.4.3" hex-literal = "0.3" -sp-keystore = { version = "0.10.0", path = "../keystore" } +sp-keystore = { version = "0.11.0", path = "../keystore" } [features] default = ["std"] diff --git a/primitives/block-builder/Cargo.toml b/primitives/block-builder/Cargo.toml index 5009207a3f5c..28f76343c7e9 100644 --- a/primitives/block-builder/Cargo.toml +++ b/primitives/block-builder/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../runtime" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } diff --git a/primitives/blockchain/Cargo.toml b/primitives/blockchain/Cargo.toml index 366d0f3c373e..89737dbac0c6 100644 --- a/primitives/blockchain/Cargo.toml +++ b/primitives/blockchain/Cargo.toml @@ -21,7 +21,7 @@ thiserror = "1.0.30" futures = "0.3.9" codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } sp-consensus = { version = "0.10.0-dev", path = "../consensus/common" } -sp-runtime = { version = "4.1.0-dev", path = "../runtime" } -sp-state-machine = { version = "0.10.0", path = "../state-machine" } +sp-runtime = { version = "5.0.0", path = "../runtime" } +sp-state-machine = { version = "0.11.0", path = "../state-machine" } sp-database = { version = "4.0.0-dev", path = "../database" } sp-api = { version = "4.0.0-dev", path = "../api" } diff --git a/primitives/consensus/aura/Cargo.toml b/primitives/consensus/aura/Cargo.toml index f15f0008164d..e78de2db17b3 100644 --- a/primitives/consensus/aura/Cargo.toml +++ b/primitives/consensus/aura/Cargo.toml @@ -13,12 +13,12 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-application-crypto = { version = "4.0.0", default-features = false, path = "../../application-crypto" } +sp-application-crypto = { version = "5.0.0", default-features = false, path = "../../application-crypto" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../std" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../api" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../runtime" } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../inherents" } sp-timestamp = { version = "4.0.0-dev", default-features = false, path = "../../timestamp" } sp-consensus-slots = { version = "0.10.0-dev", default-features = false, path = "../slots" } diff --git a/primitives/consensus/babe/Cargo.toml b/primitives/consensus/babe/Cargo.toml index 1471ca05f591..b114d182c730 100644 --- a/primitives/consensus/babe/Cargo.toml +++ b/primitives/consensus/babe/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-application-crypto = { version = "4.0.0", default-features = false, path = "../../application-crypto" } +sp-application-crypto = { version = "5.0.0", default-features = false, path = "../../application-crypto" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } merlin = { version = "2.0", default-features = false } @@ -22,10 +22,10 @@ sp-api = { version = "4.0.0-dev", default-features = false, path = "../../api" } sp-consensus = { version = "0.10.0-dev", optional = true, path = "../common" } sp-consensus-slots = { version = "0.10.0-dev", default-features = false, path = "../slots" } sp-consensus-vrf = { version = "0.10.0-dev", path = "../vrf", default-features = false } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../../core" } +sp-core = { version = "5.0.0", default-features = false, path = "../../core" } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../inherents" } -sp-keystore = { version = "0.10.0", default-features = false, path = "../../keystore", optional = true } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../runtime" } +sp-keystore = { version = "0.11.0", default-features = false, path = "../../keystore", optional = true } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../runtime" } sp-timestamp = { version = "4.0.0-dev", path = "../../timestamp", optional = true } serde = { version = "1.0.132", features = ["derive"], optional = true } async-trait = { version = "0.1.50", optional = true } diff --git a/primitives/consensus/common/Cargo.toml b/primitives/consensus/common/Cargo.toml index 93338d62cfc0..2717de72d1e3 100644 --- a/primitives/consensus/common/Cargo.toml +++ b/primitives/consensus/common/Cargo.toml @@ -20,13 +20,13 @@ codec = { package = "parity-scale-codec", version = "2.0.0", features = [ ] } futures = { version = "0.3.1", features = ["thread-pool"] } log = "0.4.8" -sp-core = { path = "../../core", version = "4.1.0-dev" } +sp-core = { path = "../../core", version = "5.0.0"} sp-inherents = { version = "4.0.0-dev", path = "../../inherents" } -sp-state-machine = { version = "0.10.0", path = "../../state-machine" } +sp-state-machine = { version = "0.11.0", path = "../../state-machine" } futures-timer = "3.0.1" sp-std = { version = "4.0.0", path = "../../std" } sp-version = { version = "4.0.0-dev", path = "../../version" } -sp-runtime = { version = "4.1.0-dev", path = "../../runtime" } +sp-runtime = { version = "5.0.0", path = "../../runtime" } thiserror = "1.0.30" [dev-dependencies] diff --git a/primitives/consensus/pow/Cargo.toml b/primitives/consensus/pow/Cargo.toml index 810e9c23a659..f70af90afd6d 100644 --- a/primitives/consensus/pow/Cargo.toml +++ b/primitives/consensus/pow/Cargo.toml @@ -15,8 +15,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-api = { version = "4.0.0-dev", default-features = false, path = "../../api" } sp-std = { version = "4.0.0", default-features = false, path = "../../std" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../runtime" } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../../core" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../runtime" } +sp-core = { version = "5.0.0", default-features = false, path = "../../core" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } [features] diff --git a/primitives/consensus/slots/Cargo.toml b/primitives/consensus/slots/Cargo.toml index ea2a86218982..18506980ae85 100644 --- a/primitives/consensus/slots/Cargo.toml +++ b/primitives/consensus/slots/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } serde = { version = "1.0", features = ["derive"], optional = true } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../runtime" } sp-arithmetic = { version = "4.0.0", default-features = false, path = "../../arithmetic" } [features] diff --git a/primitives/consensus/vrf/Cargo.toml b/primitives/consensus/vrf/Cargo.toml index 7504a159a3db..3277a3ff9691 100644 --- a/primitives/consensus/vrf/Cargo.toml +++ b/primitives/consensus/vrf/Cargo.toml @@ -16,8 +16,8 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { version = "2.0.0", package = "parity-scale-codec", default-features = false } schnorrkel = { version = "0.9.1", features = ["preaudit_deprecated", "u64_backend"], default-features = false } sp-std = { version = "4.0.0", path = "../../std", default-features = false } -sp-core = { version = "4.1.0-dev", path = "../../core", default-features = false } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../runtime" } +sp-core = { version = "5.0.0", path = "../../core", default-features = false } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../runtime" } [features] default = ["std"] diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index 43f2b54044c9..90138ded4cb1 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-core" -version = "4.1.0-dev" +version = "5.0.0" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" @@ -38,8 +38,8 @@ lazy_static = { version = "1.4.0", default-features = false, optional = true } parking_lot = { version = "0.11.2", optional = true } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-debug-derive = { version = "4.0.0", default-features = false, path = "../debug-derive" } -sp-storage = { version = "4.0.0", default-features = false, path = "../storage" } -sp-externalities = { version = "0.10.0", optional = true, path = "../externalities" } +sp-storage = { version = "5.0.0", default-features = false, path = "../storage" } +sp-externalities = { version = "0.11.0", optional = true, path = "../externalities" } parity-util-mem = { version = "0.10.2", default-features = false, features = ["primitive-types"] } futures = { version = "0.3.1", optional = true } dyn-clonable = { version = "0.9.0", optional = true } @@ -61,7 +61,7 @@ libsecp256k1 = { version = "0.7", default-features = false, features = ["hmac", merlin = { version = "2.0", default-features = false, optional = true } ss58-registry = { version = "1.11.0", default-features = false } sp-core-hashing = { version = "4.0.0", path = "./hashing", default-features = false, optional = true } -sp-runtime-interface = { version = "4.1.0-dev", default-features = false, path = "../runtime-interface" } +sp-runtime-interface = { version = "5.0.0", default-features = false, path = "../runtime-interface" } [dev-dependencies] sp-serializer = { version = "4.0.0-dev", path = "../serializer" } diff --git a/primitives/externalities/Cargo.toml b/primitives/externalities/Cargo.toml index 6c26b436796e..7b7beb51e780 100644 --- a/primitives/externalities/Cargo.toml +++ b/primitives/externalities/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-externalities" -version = "0.10.0" +version = "0.11.0" license = "Apache-2.0" authors = ["Parity Technologies "] edition = "2021" @@ -14,7 +14,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-storage = { version = "4.0.0", path = "../storage", default-features = false } +sp-storage = { version = "5.0.0", path = "../storage", default-features = false } sp-std = { version = "4.0.0", path = "../std", default-features = false } environmental = { version = "1.1.3", default-features = false } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } diff --git a/primitives/finality-grandpa/Cargo.toml b/primitives/finality-grandpa/Cargo.toml index e36c088c3583..bb0b8b8509ac 100644 --- a/primitives/finality-grandpa/Cargo.toml +++ b/primitives/finality-grandpa/Cargo.toml @@ -21,10 +21,10 @@ grandpa = { package = "finality-grandpa", version = "0.14.1", default-features = log = { version = "0.4.8", optional = true } serde = { version = "1.0.132", optional = true, features = ["derive"] } sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } -sp-application-crypto = { version = "4.0.0", default-features = false, path = "../application-crypto" } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } -sp-keystore = { version = "0.10.0", default-features = false, path = "../keystore", optional = true } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../runtime" } +sp-application-crypto = { version = "5.0.0", default-features = false, path = "../application-crypto" } +sp-core = { version = "5.0.0", default-features = false, path = "../core" } +sp-keystore = { version = "0.11.0", default-features = false, path = "../keystore", optional = true } +sp-runtime = { version = "5.0.0", default-features = false, path = "../runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } [features] diff --git a/primitives/inherents/Cargo.toml b/primitives/inherents/Cargo.toml index 02f084b6e634..f78f4aea14e4 100644 --- a/primitives/inherents/Cargo.toml +++ b/primitives/inherents/Cargo.toml @@ -16,8 +16,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-std = { version = "4.0.0", default-features = false, path = "../std" } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } -sp-runtime = { version = "4.1.0-dev", path = "../runtime", optional = true } +sp-core = { version = "5.0.0", default-features = false, path = "../core" } +sp-runtime = { version = "5.0.0", path = "../runtime", optional = true } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } thiserror = { version = "1.0.30", optional = true } impl-trait-for-tuples = "0.2.0" diff --git a/primitives/io/Cargo.toml b/primitives/io/Cargo.toml index ee3c9e8945eb..207a1a23e81d 100644 --- a/primitives/io/Cargo.toml +++ b/primitives/io/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-io" -version = "4.0.0" +version = "5.0.0" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" @@ -17,15 +17,15 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } hash-db = { version = "0.15.2", default-features = false } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } -sp-keystore = { version = "0.10.0", default-features = false, optional = true, path = "../keystore" } +sp-core = { version = "5.0.0", default-features = false, path = "../core" } +sp-keystore = { version = "0.11.0", default-features = false, optional = true, path = "../keystore" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } libsecp256k1 = { version = "0.7", optional = true } -sp-state-machine = { version = "0.10.0", optional = true, path = "../state-machine" } -sp-wasm-interface = { version = "4.1.0-dev", path = "../wasm-interface", default-features = false } -sp-runtime-interface = { version = "4.1.0-dev", default-features = false, path = "../runtime-interface" } -sp-trie = { version = "4.0.0", optional = true, path = "../trie" } -sp-externalities = { version = "0.10.0", optional = true, path = "../externalities" } +sp-state-machine = { version = "0.11.0", optional = true, path = "../state-machine" } +sp-wasm-interface = { version = "5.0.0", path = "../wasm-interface", default-features = false } +sp-runtime-interface = { version = "5.0.0", default-features = false, path = "../runtime-interface" } +sp-trie = { version = "5.0.0", optional = true, path = "../trie" } +sp-externalities = { version = "0.11.0", optional = true, path = "../externalities" } sp-tracing = { version = "4.0.0", default-features = false, path = "../tracing" } log = { version = "0.4.8", optional = true } futures = { version = "0.3.1", features = ["thread-pool"], optional = true } diff --git a/primitives/keyring/Cargo.toml b/primitives/keyring/Cargo.toml index a31dcc51d0fb..2f8e935b2457 100644 --- a/primitives/keyring/Cargo.toml +++ b/primitives/keyring/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-core = { version = "4.1.0-dev", path = "../core" } -sp-runtime = { version = "4.1.0-dev", path = "../runtime" } +sp-core = { version = "5.0.0", path = "../core" } +sp-runtime = { version = "5.0.0", path = "../runtime" } lazy_static = "1.4.0" strum = { version = "0.23.0", features = ["derive"] } diff --git a/primitives/keystore/Cargo.toml b/primitives/keystore/Cargo.toml index 28802cbec35e..26748d3227d6 100644 --- a/primitives/keystore/Cargo.toml +++ b/primitives/keystore/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-keystore" -version = "0.10.0" +version = "0.11.0" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" @@ -22,8 +22,8 @@ thiserror = "1.0" codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } schnorrkel = { version = "0.9.1", features = ["preaudit_deprecated", "u64_backend"], default-features = false } merlin = { version = "2.0", default-features = false } -sp-core = { version = "4.1.0-dev", path = "../core" } -sp-externalities = { version = "0.10.0", path = "../externalities", default-features = false } +sp-core = { version = "5.0.0", path = "../core" } +sp-externalities = { version = "0.11.0", path = "../externalities", default-features = false } [dev-dependencies] rand = "0.7.2" diff --git a/primitives/npos-elections/Cargo.toml b/primitives/npos-elections/Cargo.toml index 062f786aaef1..f392895a945e 100644 --- a/primitives/npos-elections/Cargo.toml +++ b/primitives/npos-elections/Cargo.toml @@ -19,8 +19,8 @@ serde = { version = "1.0.132", optional = true, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-npos-elections-solution-type = { version = "4.0.0-dev", path = "./solution-type" } sp-arithmetic = { version = "4.0.0", default-features = false, path = "../arithmetic" } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } -sp-runtime = { version = "4.1.0-dev", path = "../runtime", default-features = false } +sp-core = { version = "5.0.0", default-features = false, path = "../core" } +sp-runtime = { version = "5.0.0", path = "../runtime", default-features = false } [dev-dependencies] substrate-test-utils = { version = "4.0.0-dev", path = "../../test-utils" } diff --git a/primitives/npos-elections/fuzzer/Cargo.toml b/primitives/npos-elections/fuzzer/Cargo.toml index 3b6103552e21..335195e9bf5b 100644 --- a/primitives/npos-elections/fuzzer/Cargo.toml +++ b/primitives/npos-elections/fuzzer/Cargo.toml @@ -21,7 +21,7 @@ rand = { version = "0.8", features = ["std", "small_rng"] } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-npos-elections = { version = "4.0.0-dev", path = ".." } -sp-runtime = { version = "4.1.0-dev", path = "../../runtime" } +sp-runtime = { version = "5.0.0", path = "../../runtime" } [[bin]] name = "reduce" diff --git a/primitives/offchain/Cargo.toml b/primitives/offchain/Cargo.toml index 7e0ce31d5d0c..a96cd852bf24 100644 --- a/primitives/offchain/Cargo.toml +++ b/primitives/offchain/Cargo.toml @@ -13,9 +13,9 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } +sp-core = { version = "5.0.0", default-features = false, path = "../core" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../runtime" } [features] default = ["std"] diff --git a/primitives/rpc/Cargo.toml b/primitives/rpc/Cargo.toml index 52fe09b2c789..137be2c6eee2 100644 --- a/primitives/rpc/Cargo.toml +++ b/primitives/rpc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-rpc" -version = "4.0.0-dev" +version = "5.0.0" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.132", features = ["derive"] } -sp-core = { version = "4.1.0-dev", path = "../core" } +sp-core = { version = "5.0.0", path = "../core" } rustc-hash = "1.1.0" [dev-dependencies] diff --git a/primitives/runtime-interface/Cargo.toml b/primitives/runtime-interface/Cargo.toml index 137780c3c91e..89805a9db36d 100644 --- a/primitives/runtime-interface/Cargo.toml +++ b/primitives/runtime-interface/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-runtime-interface" -version = "4.1.0-dev" +version = "5.0.0" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" @@ -14,22 +14,22 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-wasm-interface = { version = "4.1.0-dev", path = "../wasm-interface", default-features = false } +sp-wasm-interface = { version = "5.0.0", path = "../wasm-interface", default-features = false } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-tracing = { version = "4.0.0", default-features = false, path = "../tracing" } sp-runtime-interface-proc-macro = { version = "4.0.0", path = "proc-macro" } -sp-externalities = { version = "0.10.0", optional = true, path = "../externalities" } +sp-externalities = { version = "0.11.0", optional = true, path = "../externalities" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } static_assertions = "1.0.0" primitive-types = { version = "0.10.1", default-features = false } -sp-storage = { version = "4.0.0", default-features = false, path = "../storage" } +sp-storage = { version = "5.0.0", default-features = false, path = "../storage" } impl-trait-for-tuples = "0.2.1" [dev-dependencies] sp-runtime-interface-test-wasm = { version = "2.0.0", path = "test-wasm" } -sp-state-machine = { version = "0.10.0", path = "../state-machine" } -sp-core = { version = "4.1.0-dev", path = "../core" } -sp-io = { version = "4.0.0-dev", path = "../io" } +sp-state-machine = { version = "0.11.0", path = "../state-machine" } +sp-core = { version = "5.0.0", path = "../core" } +sp-io = { version = "5.0.0", path = "../io" } rustversion = "1.0.6" trybuild = "1.0.53" diff --git a/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml b/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml index 032de1d215f2..18046626f650 100644 --- a/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml +++ b/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml @@ -13,10 +13,10 @@ publish = false targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-runtime-interface = { version = "4.1.0-dev", default-features = false, path = "../" } +sp-runtime-interface = { version = "5.0.0", default-features = false, path = "../" } sp-std = { version = "4.0.0", default-features = false, path = "../../std" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../io" } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../../core" } +sp-io = { version = "5.0.0", default-features = false, path = "../../io" } +sp-core = { version = "5.0.0", default-features = false, path = "../../core" } [build-dependencies] substrate-wasm-builder = { version = "5.0.0-dev", path = "../../../utils/wasm-builder" } diff --git a/primitives/runtime-interface/test-wasm/Cargo.toml b/primitives/runtime-interface/test-wasm/Cargo.toml index 80ad44569e99..9b6bdf39eb4c 100644 --- a/primitives/runtime-interface/test-wasm/Cargo.toml +++ b/primitives/runtime-interface/test-wasm/Cargo.toml @@ -13,10 +13,10 @@ publish = false targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-runtime-interface = { version = "4.1.0-dev", default-features = false, path = "../" } +sp-runtime-interface = { version = "5.0.0", default-features = false, path = "../" } sp-std = { version = "4.0.0", default-features = false, path = "../../std" } -sp-io = { version = "4.0.0-dev", default-features = false, path = "../../io" } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../../core" } +sp-io = { version = "5.0.0", default-features = false, path = "../../io" } +sp-core = { version = "5.0.0", default-features = false, path = "../../core" } [build-dependencies] substrate-wasm-builder = { version = "5.0.0-dev", path = "../../../utils/wasm-builder" } diff --git a/primitives/runtime-interface/test/Cargo.toml b/primitives/runtime-interface/test/Cargo.toml index 82c6a21b995c..107a8fcc7f2a 100644 --- a/primitives/runtime-interface/test/Cargo.toml +++ b/primitives/runtime-interface/test/Cargo.toml @@ -12,13 +12,13 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-runtime-interface = { version = "4.1.0-dev", path = "../" } +sp-runtime-interface = { version = "5.0.0", path = "../" } sc-executor = { version = "0.10.0-dev", path = "../../../client/executor" } sc-executor-common = { version = "0.10.0-dev", path = "../../../client/executor/common" } sp-runtime-interface-test-wasm = { version = "2.0.0", path = "../test-wasm" } sp-runtime-interface-test-wasm-deprecated = { version = "2.0.0", path = "../test-wasm-deprecated" } -sp-state-machine = { version = "0.10.0", path = "../../state-machine" } -sp-runtime = { version = "4.1.0-dev", path = "../../runtime" } -sp-io = { version = "4.0.0", path = "../../io" } +sp-state-machine = { version = "0.11.0", path = "../../state-machine" } +sp-runtime = { version = "5.0.0", path = "../../runtime" } +sp-io = { version = "5.0.0", path = "../../io" } tracing = "0.1.29" tracing-core = "0.1.17" diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index e6bb5a1c842e..4f793c8faa94 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-runtime" -version = "4.1.0-dev" +version = "5.0.0" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" @@ -18,11 +18,11 @@ targets = ["x86_64-unknown-linux-gnu"] serde = { version = "1.0.132", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } -sp-application-crypto = { version = "4.0.0", default-features = false, path = "../application-crypto" } +sp-core = { version = "5.0.0", default-features = false, path = "../core" } +sp-application-crypto = { version = "5.0.0", default-features = false, path = "../application-crypto" } sp-arithmetic = { version = "4.0.0", default-features = false, path = "../arithmetic" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } -sp-io = { version = "4.0.0", default-features = false, path = "../io" } +sp-io = { version = "5.0.0", default-features = false, path = "../io" } log = { version = "0.4.14", default-features = false } paste = "1.0" rand = { version = "0.7.2", optional = true } @@ -34,7 +34,7 @@ either = { version = "1.5", default-features = false } [dev-dependencies] serde_json = "1.0.74" rand = "0.7.2" -sp-state-machine = { version = "0.10.0", path = "../state-machine" } +sp-state-machine = { version = "0.11.0", path = "../state-machine" } sp-api = { version = "4.0.0-dev", path = "../api" } substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } diff --git a/primitives/sandbox/Cargo.toml b/primitives/sandbox/Cargo.toml index 59941c9648dd..a72786807330 100644 --- a/primitives/sandbox/Cargo.toml +++ b/primitives/sandbox/Cargo.toml @@ -20,10 +20,10 @@ wasmi = "0.9.0" [dependencies] wasmi = { version = "0.9.0", optional = true } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } +sp-core = { version = "5.0.0", default-features = false, path = "../core" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } -sp-io = { version = "4.0.0", default-features = false, path = "../io" } -sp-wasm-interface = { version = "4.1.0-dev", default-features = false, path = "../wasm-interface" } +sp-io = { version = "5.0.0", default-features = false, path = "../io" } +sp-wasm-interface = { version = "5.0.0", default-features = false, path = "../wasm-interface" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } log = { version = "0.4", default-features = false } diff --git a/primitives/session/Cargo.toml b/primitives/session/Cargo.toml index 293f3642b7f3..4138ecb519df 100644 --- a/primitives/session/Cargo.toml +++ b/primitives/session/Cargo.toml @@ -16,10 +16,10 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } +sp-core = { version = "5.0.0", default-features = false, path = "../core" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../staking" } -sp-runtime = { version = "4.1.0-dev", optional = true, path = "../runtime" } +sp-runtime = { version = "5.0.0", optional = true, path = "../runtime" } [features] default = [ "std" ] diff --git a/primitives/staking/Cargo.toml b/primitives/staking/Cargo.toml index 6ae972f1814b..54e556dfae12 100644 --- a/primitives/staking/Cargo.toml +++ b/primitives/staking/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } [features] diff --git a/primitives/state-machine/Cargo.toml b/primitives/state-machine/Cargo.toml index c885f99fdb83..15720688c058 100644 --- a/primitives/state-machine/Cargo.toml +++ b/primitives/state-machine/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-state-machine" -version = "0.10.0" +version = "0.11.0" authors = ["Parity Technologies "] description = "Substrate State Machine" edition = "2021" @@ -20,20 +20,20 @@ parking_lot = { version = "0.11.2", optional = true } hash-db = { version = "0.15.2", default-features = false } trie-db = { version = "0.23.0", default-features = false } trie-root = { version = "0.17.0", default-features = false } -sp-trie = { version = "4.0.0", path = "../trie", default-features = false } -sp-core = { version = "4.1.0-dev", path = "../core", default-features = false } +sp-trie = { version = "5.0.0", path = "../trie", default-features = false } +sp-core = { version = "5.0.0", path = "../core", default-features = false } sp-panic-handler = { version = "4.0.0", path = "../panic-handler", optional = true } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } num-traits = { version = "0.2.8", default-features = false } rand = { version = "0.7.2", optional = true } -sp-externalities = { version = "0.10.0", path = "../externalities", default-features = false } +sp-externalities = { version = "0.11.0", path = "../externalities", default-features = false } smallvec = "1.7.0" sp-std = { version = "4.0.0", default-features = false, path = "../std" } tracing = { version = "0.1.29", optional = true } [dev-dependencies] hex-literal = "0.3.4" -sp-runtime = { version = "4.1.0-dev", path = "../runtime" } +sp-runtime = { version = "5.0.0", path = "../runtime" } pretty_assertions = "1.0.0" rand = "0.7.2" diff --git a/primitives/storage/Cargo.toml b/primitives/storage/Cargo.toml index 81e4140bbd36..d3c22ce70651 100644 --- a/primitives/storage/Cargo.toml +++ b/primitives/storage/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-storage" -version = "4.0.0" +version = "5.0.0" authors = ["Parity Technologies "] edition = "2021" description = "Storage related primitives" diff --git a/primitives/tasks/Cargo.toml b/primitives/tasks/Cargo.toml index 6ac6c6aa98be..00943e865720 100644 --- a/primitives/tasks/Cargo.toml +++ b/primitives/tasks/Cargo.toml @@ -15,10 +15,10 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] log = { version = "0.4.8", optional = true } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } -sp-externalities = { version = "0.10.0", optional = true, path = "../externalities" } -sp-io = { version = "4.0.0", default-features = false, path = "../io" } -sp-runtime-interface = { version = "4.1.0-dev", default-features = false, path = "../runtime-interface" } +sp-core = { version = "5.0.0", default-features = false, path = "../core" } +sp-externalities = { version = "0.11.0", optional = true, path = "../externalities" } +sp-io = { version = "5.0.0", default-features = false, path = "../io" } +sp-runtime-interface = { version = "5.0.0", default-features = false, path = "../runtime-interface" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } [dev-dependencies] diff --git a/primitives/test-primitives/Cargo.toml b/primitives/test-primitives/Cargo.toml index ab2ef0d54ca4..41fd6173cd8a 100644 --- a/primitives/test-primitives/Cargo.toml +++ b/primitives/test-primitives/Cargo.toml @@ -12,11 +12,11 @@ publish = false targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-application-crypto = { version = "4.0.0", default-features = false, path = "../application-crypto" } +sp-application-crypto = { version = "5.0.0", default-features = false, path = "../application-crypto" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } +sp-core = { version = "5.0.0", default-features = false, path = "../core" } serde = { version = "1.0.132", optional = true, features = ["derive"] } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../runtime" } parity-util-mem = { version = "0.10.2", default-features = false, features = ["primitive-types"] } [features] diff --git a/primitives/timestamp/Cargo.toml b/primitives/timestamp/Cargo.toml index e42ca738cd55..f7ac2e663e39 100644 --- a/primitives/timestamp/Cargo.toml +++ b/primitives/timestamp/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../runtime" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../inherents" } thiserror = { version = "1.0.30", optional = true } diff --git a/primitives/transaction-pool/Cargo.toml b/primitives/transaction-pool/Cargo.toml index fab5f90ffffc..c8f70bdce9de 100644 --- a/primitives/transaction-pool/Cargo.toml +++ b/primitives/transaction-pool/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../runtime" } [features] default = [ "std" ] diff --git a/primitives/transaction-storage-proof/Cargo.toml b/primitives/transaction-storage-proof/Cargo.toml index 87f7f81cd586..9e2898fe267e 100644 --- a/primitives/transaction-storage-proof/Cargo.toml +++ b/primitives/transaction-storage-proof/Cargo.toml @@ -14,10 +14,10 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../inherents" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } -sp-trie = { version = "4.0.0", optional = true, path = "../trie" } -sp-core = { version = "4.1.0-dev", path = "../core", optional = true } +sp-trie = { version = "5.0.0", optional = true, path = "../trie" } +sp-core = { version = "5.0.0", path = "../core", optional = true } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } log = { version = "0.4.8", optional = true } diff --git a/primitives/trie/Cargo.toml b/primitives/trie/Cargo.toml index 4564fa86ced9..e79f2ffb7f84 100644 --- a/primitives/trie/Cargo.toml +++ b/primitives/trie/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-trie" -version = "4.0.0" +version = "5.0.0" authors = ["Parity Technologies "] description = "Patricia trie stuff using a parity-scale-codec node format" repository = "https://github.com/paritytech/substrate/" @@ -25,14 +25,14 @@ hash-db = { version = "0.15.2", default-features = false } trie-db = { version = "0.23.0", default-features = false } trie-root = { version = "0.17.0", default-features = false } memory-db = { version = "0.28.0", default-features = false } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } +sp-core = { version = "5.0.0", default-features = false, path = "../core" } [dev-dependencies] trie-bench = "0.29.0" trie-standardmap = "0.15.2" criterion = "0.3.3" hex-literal = "0.3.4" -sp-runtime = { version = "4.1.0-dev", path = "../runtime" } +sp-runtime = { version = "5.0.0", path = "../runtime" } [features] default = ["std"] diff --git a/primitives/version/Cargo.toml b/primitives/version/Cargo.toml index 1bb39eca1364..48091ba709cb 100644 --- a/primitives/version/Cargo.toml +++ b/primitives/version/Cargo.toml @@ -19,7 +19,7 @@ serde = { version = "1.0.132", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../std" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../runtime" } sp-version-proc-macro = { version = "4.0.0-dev", default-features = false, path = "proc-macro" } parity-wasm = { version = "0.42.2", optional = true } sp-core-hashing-proc-macro = { version = "4.0.0-dev", path = "../core/hashing/proc-macro" } diff --git a/primitives/wasm-interface/Cargo.toml b/primitives/wasm-interface/Cargo.toml index 200c686243e0..bb82629ba01e 100644 --- a/primitives/wasm-interface/Cargo.toml +++ b/primitives/wasm-interface/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-wasm-interface" -version = "4.1.0-dev" +version = "5.0.0" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" diff --git a/test-utils/client/Cargo.toml b/test-utils/client/Cargo.toml index 902a14b1b3bd..5f687b24896d 100644 --- a/test-utils/client/Cargo.toml +++ b/test-utils/client/Cargo.toml @@ -29,9 +29,9 @@ sc-service = { version = "0.10.0-dev", default-features = false, features = [ ], path = "../../client/service" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } -sp-keystore = { version = "0.10.0", path = "../../primitives/keystore" } +sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-keystore = { version = "0.11.0", path = "../../primitives/keystore" } sp-keyring = { version = "4.1.0-dev", path = "../../primitives/keyring" } -sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } -sp-state-machine = { version = "0.10.0", path = "../../primitives/state-machine" } +sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } +sp-state-machine = { version = "0.11.0", path = "../../primitives/state-machine" } async-trait = "0.1.50" diff --git a/test-utils/runtime/Cargo.toml b/test-utils/runtime/Cargo.toml index e88f57136602..f1b06d3b3ec2 100644 --- a/test-utils/runtime/Cargo.toml +++ b/test-utils/runtime/Cargo.toml @@ -13,7 +13,7 @@ publish = false targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-application-crypto = { version = "4.0.0", default-features = false, path = "../../primitives/application-crypto" } +sp-application-crypto = { version = "5.0.0", default-features = false, path = "../../primitives/application-crypto" } sp-consensus-aura = { version = "0.10.0-dev", default-features = false, path = "../../primitives/consensus/aura" } sp-consensus-babe = { version = "0.10.0-dev", default-features = false, path = "../../primitives/consensus/babe" } sp-block-builder = { version = "4.0.0-dev", default-features = false, path = "../../primitives/block-builder" } @@ -23,27 +23,27 @@ sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../ sp-keyring = { version = "4.1.0-dev", optional = true, path = "../../primitives/keyring" } memory-db = { version = "0.27.0", default-features = false } sp-offchain = { version = "4.0.0-dev", default-features = false, path = "../../primitives/offchain" } -sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } +sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime-interface = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime-interface" } -sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime-interface = { version = "5.0.0", default-features = false, path = "../../primitives/runtime-interface" } +sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../../frame/support" } sp-version = { version = "4.0.0-dev", default-features = false, path = "../../primitives/version" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../primitives/session" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../primitives/api" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } pallet-babe = { version = "4.0.0-dev", default-features = false, path = "../../frame/babe" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../frame/system" } frame-system-rpc-runtime-api = { version = "4.0.0-dev", default-features = false, path = "../../frame/system/rpc/runtime-api" } pallet-timestamp = { version = "4.0.0-dev", default-features = false, path = "../../frame/timestamp" } sp-finality-grandpa = { version = "4.0.0-dev", default-features = false, path = "../../primitives/finality-grandpa" } -sp-trie = { version = "4.0.0", default-features = false, path = "../../primitives/trie" } +sp-trie = { version = "5.0.0", default-features = false, path = "../../primitives/trie" } sp-transaction-pool = { version = "4.0.0-dev", default-features = false, path = "../../primitives/transaction-pool" } trie-db = { version = "0.23.0", default-features = false } parity-util-mem = { version = "0.10.2", default-features = false, features = ["primitive-types"] } sc-service = { version = "0.10.0-dev", default-features = false, optional = true, features = ["test-helpers"], path = "../../client/service" } -sp-state-machine = { version = "0.10.0", default-features = false, path = "../../primitives/state-machine" } -sp-externalities = { version = "0.10.0", default-features = false, path = "../../primitives/externalities" } +sp-state-machine = { version = "0.11.0", default-features = false, path = "../../primitives/state-machine" } +sp-externalities = { version = "0.11.0", default-features = false, path = "../../primitives/externalities" } # 3rd party cfg-if = "1.0" diff --git a/test-utils/runtime/client/Cargo.toml b/test-utils/runtime/client/Cargo.toml index ba0f01cfced9..fd260453ca18 100644 --- a/test-utils/runtime/client/Cargo.toml +++ b/test-utils/runtime/client/Cargo.toml @@ -16,9 +16,9 @@ sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/c sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/common" } sc-block-builder = { version = "0.10.0-dev", path = "../../../client/block-builder" } substrate-test-client = { version = "2.0.0", path = "../../client" } -sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } +sp-core = { version = "5.0.0", path = "../../../primitives/core" } substrate-test-runtime = { version = "2.0.0", path = "../../runtime" } -sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } +sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } codec = { package = "parity-scale-codec", version = "2.0.0" } diff --git a/test-utils/runtime/transaction-pool/Cargo.toml b/test-utils/runtime/transaction-pool/Cargo.toml index 2a94f2484587..ef2ebd64fb22 100644 --- a/test-utils/runtime/transaction-pool/Cargo.toml +++ b/test-utils/runtime/transaction-pool/Cargo.toml @@ -16,7 +16,7 @@ substrate-test-runtime-client = { version = "2.0.0", path = "../client" } parking_lot = "0.11.2" codec = { package = "parity-scale-codec", version = "2.0.0" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } +sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } sc-transaction-pool = { version = "4.0.0-dev", path = "../../../client/transaction-pool" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../../../client/transaction-pool/api" } futures = "0.3.16" diff --git a/utils/frame/benchmarking-cli/Cargo.toml b/utils/frame/benchmarking-cli/Cargo.toml index a7e5b76ad97a..971fb31a3f8c 100644 --- a/utils/frame/benchmarking-cli/Cargo.toml +++ b/utils/frame/benchmarking-cli/Cargo.toml @@ -15,15 +15,15 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] frame-benchmarking = { version = "4.0.0-dev", path = "../../../frame/benchmarking" } frame-support = { version = "4.0.0-dev", path = "../../../frame/support" } -sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } +sp-core = { version = "5.0.0", path = "../../../primitives/core" } sc-service = { version = "0.10.0-dev", default-features = false, path = "../../../client/service" } sc-cli = { version = "0.10.0-dev", path = "../../../client/cli" } sc-client-db = { version = "0.10.0-dev", path = "../../../client/db" } sc-executor = { version = "0.10.0-dev", path = "../../../client/executor" } -sp-externalities = { version = "0.10.0", path = "../../../primitives/externalities" } -sp-keystore = { version = "0.10.0", path = "../../../primitives/keystore" } -sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } -sp-state-machine = { version = "0.10.0", path = "../../../primitives/state-machine" } +sp-externalities = { version = "0.11.0", path = "../../../primitives/externalities" } +sp-keystore = { version = "0.11.0", path = "../../../primitives/keystore" } +sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } +sp-state-machine = { version = "0.11.0", path = "../../../primitives/state-machine" } codec = { version = "2.0.0", package = "parity-scale-codec" } clap = { version = "3.0", features = ["derive"] } chrono = "0.4" diff --git a/utils/frame/frame-utilities-cli/Cargo.toml b/utils/frame/frame-utilities-cli/Cargo.toml index f330b205ea27..50a00db1d4d3 100644 --- a/utils/frame/frame-utilities-cli/Cargo.toml +++ b/utils/frame/frame-utilities-cli/Cargo.toml @@ -13,9 +13,9 @@ readme = "README.md" [dependencies] clap = { version = "3.0", features = ["derive"] } -sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } +sp-core = { version = "5.0.0", path = "../../../primitives/core" } sc-cli = { version = "0.10.0-dev", path = "../../../client/cli" } -sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } +sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } frame-system = { version = "4.0.0-dev", path = "../../../frame/system" } frame-support = { version = "4.0.0-dev", path = "../../../frame/support" } diff --git a/utils/frame/generate-bags/Cargo.toml b/utils/frame/generate-bags/Cargo.toml index 55670c96f792..5bda705a581a 100644 --- a/utils/frame/generate-bags/Cargo.toml +++ b/utils/frame/generate-bags/Cargo.toml @@ -17,7 +17,7 @@ frame-system = { version = "4.0.0-dev", path = "../../../frame/system" } pallet-staking = { version = "4.0.0-dev", path = "../../../frame/staking" } # primitives -sp-io = { version = "4.0.0", path = "../../../primitives/io" } +sp-io = { version = "5.0.0", path = "../../../primitives/io" } # third party chrono = { version = "0.4.19" } diff --git a/utils/frame/remote-externalities/Cargo.toml b/utils/frame/remote-externalities/Cargo.toml index 9e0b17a7b58f..c1d6f1b1c5f5 100644 --- a/utils/frame/remote-externalities/Cargo.toml +++ b/utils/frame/remote-externalities/Cargo.toml @@ -22,9 +22,9 @@ codec = { package = "parity-scale-codec", version = "2.0.0" } serde_json = "1.0" serde = "1.0.132" -sp-io = { version = "4.0.0-dev", path = "../../../primitives/io" } -sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } -sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } +sp-io = { version = "5.0.0", path = "../../../primitives/io" } +sp-core = { version = "5.0.0", path = "../../../primitives/core" } +sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } sp-version = { version = "4.0.0-dev", path = "../../../primitives/version" } [dev-dependencies] diff --git a/utils/frame/rpc/support/Cargo.toml b/utils/frame/rpc/support/Cargo.toml index 6ecaabd72059..fcb5a4367386 100644 --- a/utils/frame/rpc/support/Cargo.toml +++ b/utils/frame/rpc/support/Cargo.toml @@ -20,7 +20,7 @@ jsonrpc-client-transports = { version = "18.0.0", features = ["http"] } codec = { package = "parity-scale-codec", version = "2.0.0" } serde = "1" frame-support = { version = "4.0.0-dev", path = "../../../../frame/support" } -sp-storage = { version = "4.0.0", path = "../../../../primitives/storage" } +sp-storage = { version = "5.0.0", path = "../../../../primitives/storage" } sc-rpc-api = { version = "0.10.0-dev", path = "../../../../client/rpc-api" } [dev-dependencies] diff --git a/utils/frame/rpc/system/Cargo.toml b/utils/frame/rpc/system/Cargo.toml index cb801c6cbf27..8ce72416dac2 100644 --- a/utils/frame/rpc/system/Cargo.toml +++ b/utils/frame/rpc/system/Cargo.toml @@ -20,10 +20,10 @@ jsonrpc-core = "18.0.0" jsonrpc-core-client = "18.0.0" jsonrpc-derive = "18.0.0" log = "0.4.8" -sp-runtime = { version = "4.1.0-dev", path = "../../../../primitives/runtime" } +sp-runtime = { version = "5.0.0", path = "../../../../primitives/runtime" } sp-api = { version = "4.0.0-dev", path = "../../../../primitives/api" } frame-system-rpc-runtime-api = { version = "4.0.0-dev", path = "../../../../frame/system/rpc/runtime-api" } -sp-core = { version = "4.1.0-dev", path = "../../../../primitives/core" } +sp-core = { version = "5.0.0", path = "../../../../primitives/core" } sp-blockchain = { version = "4.0.0-dev", path = "../../../../primitives/blockchain" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../../../../client/transaction-pool/api" } sp-block-builder = { version = "4.0.0-dev", path = "../../../../primitives/block-builder" } diff --git a/utils/frame/try-runtime/cli/Cargo.toml b/utils/frame/try-runtime/cli/Cargo.toml index 812310ff17d2..541706257ba1 100644 --- a/utils/frame/try-runtime/cli/Cargo.toml +++ b/utils/frame/try-runtime/cli/Cargo.toml @@ -23,12 +23,12 @@ sc-service = { version = "0.10.0-dev", default-features = false, path = "../../. sc-cli = { version = "0.10.0-dev", path = "../../../../client/cli" } sc-executor = { version = "0.10.0-dev", path = "../../../../client/executor" } sc-chain-spec = { version = "4.0.0-dev", path = "../../../../client/chain-spec" } -sp-state-machine = { version = "0.10.0", path = "../../../../primitives/state-machine" } -sp-runtime = { version = "4.1.0-dev", path = "../../../../primitives/runtime" } -sp-core = { version = "4.1.0-dev", path = "../../../../primitives/core" } -sp-io = { version = "4.0.0-dev", path = "../../../../primitives/io" } -sp-keystore = { version = "0.10.0", path = "../../../../primitives/keystore" } -sp-externalities = { version = "0.10.0", path = "../../../../primitives/externalities" } +sp-state-machine = { version = "0.11.0", path = "../../../../primitives/state-machine" } +sp-runtime = { version = "5.0.0", path = "../../../../primitives/runtime" } +sp-core = { version = "5.0.0", path = "../../../../primitives/core" } +sp-io = { version = "5.0.0", path = "../../../../primitives/io" } +sp-keystore = { version = "0.11.0", path = "../../../../primitives/keystore" } +sp-externalities = { version = "0.11.0", path = "../../../../primitives/externalities" } sp-version = { version = "4.0.0-dev", path = "../../../../primitives/version" } remote-externalities = { version = "0.10.0-dev", path = "../../remote-externalities" } From 5948416d0ebd5d3a154088b7be0adf05c16a0812 Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Wed, 2 Feb 2022 12:29:36 +0100 Subject: [PATCH 444/695] Enable download of future forks (#10739) * Enable download of future forks * Fixed external tests --- client/network/src/protocol/sync.rs | 8 +++- client/network/test/src/lib.rs | 58 ++++++++++++++++---------- client/network/test/src/sync.rs | 63 ++++++++++++++++++++++++----- 3 files changed, 97 insertions(+), 32 deletions(-) diff --git a/client/network/src/protocol/sync.rs b/client/network/src/protocol/sync.rs index d6513ca2e5b9..fbb4e376b1b4 100644 --- a/client/network/src/protocol/sync.rs +++ b/client/network/src/protocol/sync.rs @@ -2418,7 +2418,11 @@ fn fork_sync_request( if !r.peers.contains(id) { continue } - if r.number <= best_num { + // Download the fork only if it is behind or not too far ahead our tip of the chain + // Otherwise it should be downloaded in full sync mode. + if r.number <= best_num || + (r.number - best_num).saturated_into::() < MAX_BLOCKS_TO_REQUEST as u32 + { let parent_status = r.parent_hash.as_ref().map_or(BlockStatus::Unknown, check_block); let count = if parent_status == BlockStatus::Unknown { (r.number - finalized).saturated_into::() // up to the last finalized block @@ -2438,6 +2442,8 @@ fn fork_sync_request( max: Some(count), }, )) + } else { + trace!(target: "sync", "Fork too far in the future: {:?} (#{})", hash, r.number); } } None diff --git a/client/network/test/src/lib.rs b/client/network/test/src/lib.rs index b2345f3701b0..3986ac47f361 100644 --- a/client/network/test/src/lib.rs +++ b/client/network/test/src/lib.rs @@ -86,7 +86,6 @@ type AuthorityId = sp_consensus_babe::AuthorityId; #[derive(Clone)] pub struct PassThroughVerifier { finalized: bool, - fork_choice: ForkChoiceStrategy, } impl PassThroughVerifier { @@ -94,15 +93,7 @@ impl PassThroughVerifier { /// /// Every verified block will use `finalized` for the `BlockImportParams`. pub fn new(finalized: bool) -> Self { - Self { finalized, fork_choice: ForkChoiceStrategy::LongestChain } - } - - /// Create a new instance. - /// - /// Every verified block will use `finalized` for the `BlockImportParams` and - /// the given [`ForkChoiceStrategy`]. - pub fn new_with_fork_choice(finalized: bool, fork_choice: ForkChoiceStrategy) -> Self { - Self { finalized, fork_choice } + Self { finalized } } } @@ -121,8 +112,10 @@ impl Verifier for PassThroughVerifier { .or_else(|| l.try_as_raw(OpaqueDigestItemId::Consensus(b"babe"))) }) .map(|blob| vec![(well_known_cache_keys::AUTHORITIES, blob.to_vec())]); + if block.fork_choice.is_none() { + block.fork_choice = Some(ForkChoiceStrategy::LongestChain); + }; block.finalized = self.finalized; - block.fork_choice = Some(self.fork_choice.clone()); Ok((block, maybe_keys)) } } @@ -309,6 +302,33 @@ where false, true, true, + ForkChoiceStrategy::LongestChain, + ) + } + + /// Add blocks to the peer -- edit the block before adding and use custom fork choice rule. + pub fn generate_blocks_with_fork_choice( + &mut self, + count: usize, + origin: BlockOrigin, + edit_block: F, + fork_choice: ForkChoiceStrategy, + ) -> H256 + where + F: FnMut( + BlockBuilder, + ) -> Block, + { + let best_hash = self.client.info().best_hash; + self.generate_blocks_at( + BlockId::Hash(best_hash), + count, + origin, + edit_block, + false, + true, + true, + fork_choice, ) } @@ -323,6 +343,7 @@ where headers_only: bool, inform_sync_about_new_best_block: bool, announce_block: bool, + fork_choice: ForkChoiceStrategy, ) -> H256 where F: FnMut( @@ -346,6 +367,7 @@ where let header = block.header.clone(); let mut import_block = BlockImportParams::new(origin, header.clone()); import_block.body = if headers_only { None } else { Some(block.extrinsics) }; + import_block.fork_choice = Some(fork_choice); let (import_block, cache) = futures::executor::block_on(self.verifier.verify(import_block)).unwrap(); let cache = if let Some(cache) = cache { @@ -442,6 +464,7 @@ where headers_only, inform_sync_about_new_best_block, announce_block, + ForkChoiceStrategy::LongestChain, ) } else { self.generate_blocks_at( @@ -452,6 +475,7 @@ where headers_only, inform_sync_about_new_best_block, announce_block, + ForkChoiceStrategy::LongestChain, ) } } @@ -989,14 +1013,6 @@ where pub struct TestNet { peers: Vec>, - fork_choice: ForkChoiceStrategy, -} - -impl TestNet { - /// Create a `TestNet` that used the given fork choice rule. - pub fn with_fork_choice(fork_choice: ForkChoiceStrategy) -> Self { - Self { peers: Vec::new(), fork_choice } - } } impl TestNetFactory for TestNet { @@ -1006,7 +1022,7 @@ impl TestNetFactory for TestNet { /// Create new test network with peers and given config. fn from_config(_config: &ProtocolConfig) -> Self { - TestNet { peers: Vec::new(), fork_choice: ForkChoiceStrategy::LongestChain } + TestNet { peers: Vec::new() } } fn make_verifier( @@ -1015,7 +1031,7 @@ impl TestNetFactory for TestNet { _config: &ProtocolConfig, _peer_data: &(), ) -> Self::Verifier { - PassThroughVerifier::new_with_fork_choice(false, self.fork_choice.clone()) + PassThroughVerifier::new(false) } fn make_block_import( diff --git a/client/network/test/src/sync.rs b/client/network/test/src/sync.rs index 5b607a7762b3..84a5c2ca13fa 100644 --- a/client/network/test/src/sync.rs +++ b/client/network/test/src/sync.rs @@ -453,6 +453,38 @@ fn can_sync_small_non_best_forks() { })); } +#[test] +fn can_sync_forks_ahead_of_the_best_chain() { + sp_tracing::try_init_simple(); + let mut net = TestNet::new(2); + net.peer(0).push_blocks(1, false); + net.peer(1).push_blocks(1, false); + + net.block_until_connected(); + // Peer 0 is on 2-block fork which is announced with is_best=false + let fork_hash = net.peer(0).generate_blocks_with_fork_choice( + 2, + BlockOrigin::Own, + |builder| builder.build().unwrap().block, + ForkChoiceStrategy::Custom(false), + ); + // Peer 1 is on 1-block fork + net.peer(1).push_blocks(1, false); + assert!(net.peer(0).client().header(&BlockId::Hash(fork_hash)).unwrap().is_some()); + assert_eq!(net.peer(0).client().info().best_number, 1); + assert_eq!(net.peer(1).client().info().best_number, 2); + + // after announcing, peer 1 downloads the block. + block_on(futures::future::poll_fn::<(), _>(|cx| { + net.poll(cx); + + if net.peer(1).client().header(&BlockId::Hash(fork_hash)).unwrap().is_none() { + return Poll::Pending + } + Poll::Ready(()) + })); +} + #[test] fn can_sync_explicit_forks() { sp_tracing::try_init_simple(); @@ -678,7 +710,7 @@ impl BlockAnnounceValidator for FailingBlockAnnounceValidator { #[test] fn sync_blocks_when_block_announce_validator_says_it_is_new_best() { sp_tracing::try_init_simple(); - let mut net = TestNet::with_fork_choice(ForkChoiceStrategy::Custom(false)); + let mut net = TestNet::new(0); net.add_full_peer_with_config(Default::default()); net.add_full_peer_with_config(Default::default()); net.add_full_peer_with_config(FullPeerConfig { @@ -688,16 +720,17 @@ fn sync_blocks_when_block_announce_validator_says_it_is_new_best() { net.block_until_connected(); - let block_hash = net.peer(0).push_blocks(1, false); + // Add blocks but don't set them as best + let block_hash = net.peer(0).generate_blocks_with_fork_choice( + 1, + BlockOrigin::Own, + |builder| builder.build().unwrap().block, + ForkChoiceStrategy::Custom(false), + ); while !net.peer(2).has_block(&block_hash) { net.block_until_idle(); } - - // Peer1 should not have the block, because peer 0 did not reported the block - // as new best. However, peer2 has a special block announcement validator - // that flags all blocks as `is_new_best` and thus, it should have synced the blocks. - assert!(!net.peer(1).has_block(&block_hash)); } /// Waits for some time until the validation is successfull. @@ -721,7 +754,7 @@ impl BlockAnnounceValidator for DeferredBlockAnnounceValidator { #[test] fn wait_until_deferred_block_announce_validation_is_ready() { sp_tracing::try_init_simple(); - let mut net = TestNet::with_fork_choice(ForkChoiceStrategy::Custom(false)); + let mut net = TestNet::new(0); net.add_full_peer_with_config(Default::default()); net.add_full_peer_with_config(FullPeerConfig { block_announce_validator: Some(Box::new(NewBestBlockAnnounceValidator)), @@ -730,7 +763,13 @@ fn wait_until_deferred_block_announce_validation_is_ready() { net.block_until_connected(); - let block_hash = net.peer(0).push_blocks(1, true); + // Add blocks but don't set them as best + let block_hash = net.peer(0).generate_blocks_with_fork_choice( + 1, + BlockOrigin::Own, + |builder| builder.build().unwrap().block, + ForkChoiceStrategy::Custom(false), + ); while !net.peer(1).has_block(&block_hash) { net.block_until_idle(); @@ -847,7 +886,10 @@ fn block_announce_data_is_propagated() { // Wait until peer 1 is connected to both nodes. block_on(futures::future::poll_fn::<(), _>(|cx| { net.poll(cx); - if net.peer(1).num_peers() == 2 { + if net.peer(1).num_peers() == 2 && + net.peer(0).num_peers() == 1 && + net.peer(2).num_peers() == 1 + { Poll::Ready(()) } else { Poll::Pending @@ -1109,6 +1151,7 @@ fn syncs_indexed_blocks() { false, true, true, + ForkChoiceStrategy::LongestChain, ); let indexed_key = sp_runtime::traits::BlakeTwo256::hash(&42u64.to_le_bytes()); assert!(net From 529c2fd27d3d584951f73ba05bdea357117eadec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Wed, 2 Feb 2022 12:34:52 +0100 Subject: [PATCH 445/695] wasm-builder: Fall back to `release` profile for unknown profiles (#10775) --- utils/wasm-builder/src/wasm_project.rs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/utils/wasm-builder/src/wasm_project.rs b/utils/wasm-builder/src/wasm_project.rs index 541c6290166c..20e176444c62 100644 --- a/utils/wasm-builder/src/wasm_project.rs +++ b/utils/wasm-builder/src/wasm_project.rs @@ -476,8 +476,21 @@ impl Profile { (Some(Profile::Debug), false) => Profile::Release, // For any other profile or when overriden we take it at face value. (Some(profile), _) => profile, + // For non overriden unknown profiles we fall back to `Release`. + // This allows us to continue building when a custom profile is used for the + // main builds cargo. When explicitly passing a profile via env variable we are + // not doing a fallback. + (None, false) => { + let profile = Profile::Release; + build_helper::warning!( + "Unknown cargo profile `{}`. Defaulted to `{:?}` for the runtime build.", + name, + profile, + ); + profile + }, // Invalid profile specified. - (None, _) => { + (None, true) => { // We use println! + exit instead of a panic in order to have a cleaner output. println!( "Unexpected profile name: `{}`. One of the following is expected: {:?}", @@ -627,8 +640,8 @@ fn compress_wasm(wasm_binary_path: &Path, compressed_binary_out_path: &Path) -> true } else { - println!( - "cargo:warning=Writing uncompressed wasm. Exceeded maximum size {}", + build_helper::warning!( + "Writing uncompressed wasm. Exceeded maximum size {}", CODE_BLOB_BOMB_LIMIT, ); From e570d2ee4225972db1c28a318a04211a65dd8e87 Mon Sep 17 00:00:00 2001 From: Pierre Besson Date: Wed, 2 Feb 2022 13:06:25 +0100 Subject: [PATCH 446/695] Substrate alerts rules update (#10642) * .maintain/monitoring: Update substrate prometheus alert rules * match the `substrate_` metrics prefix in alerts instead of `polkadot_`, following changes in #9543 * remove the filtering on polkadot|kusama domain for NumberOfFileDescriptorsHigh alert * .maintain/monitoring: Update substrate Grafana dashboards * match the `substrate_` metrics prefix instead of `polkadot_` in dashboards, following changes in #9543 * .maintain/monitoring: make the NumberOfFileDescriptorsHigh alert only apply for metrics tagged with 'chain' --- .../alerting-rules/alerting-rule-tests.yaml | 144 +++++++++--------- .../alerting-rules/alerting-rules.yaml | 50 +++--- .../substrate-networking.json | 2 +- .../substrate-service-tasks.json | 2 +- 4 files changed, 99 insertions(+), 99 deletions(-) diff --git a/.maintain/monitoring/alerting-rules/alerting-rule-tests.yaml b/.maintain/monitoring/alerting-rules/alerting-rule-tests.yaml index 7ad916f02215..df5e020d067e 100644 --- a/.maintain/monitoring/alerting-rules/alerting-rule-tests.yaml +++ b/.maintain/monitoring/alerting-rules/alerting-rule-tests.yaml @@ -6,39 +6,39 @@ evaluation_interval: 1m tests: - interval: 1m input_series: - - series: 'polkadot_sub_libp2p_peers_count{ - job="polkadot", - pod="polkadot-abcdef01234-abcdef", - instance="polkadot-abcdef01234-abcdef", + - series: 'substrate_sub_libp2p_peers_count{ + job="substrate", + pod="substrate-abcdef01234-abcdef", + instance="substrate-abcdef01234-abcdef", }' values: '3 2+0x4 1+0x9' # 3 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - - series: 'polkadot_sub_txpool_validations_scheduled{ - job="polkadot", - pod="polkadot-abcdef01234-abcdef", - instance="polkadot-abcdef01234-abcdef", + - series: 'substrate_sub_txpool_validations_scheduled{ + job="substrate", + pod="substrate-abcdef01234-abcdef", + instance="substrate-abcdef01234-abcdef", }' values: '11+1x10 22+2x30 10043x5' - - series: 'polkadot_sub_txpool_validations_finished{ - job="polkadot", - pod="polkadot-abcdef01234-abcdef", - instance="polkadot-abcdef01234-abcdef", + - series: 'substrate_sub_txpool_validations_finished{ + job="substrate", + pod="substrate-abcdef01234-abcdef", + instance="substrate-abcdef01234-abcdef", }' values: '0+1x42 42x5' - - series: 'polkadot_block_height{ - status="best", job="polkadot", - pod="polkadot-abcdef01234-abcdef", - instance="polkadot-abcdef01234-abcdef", + - series: 'substrate_block_height{ + status="best", job="substrate", + pod="substrate-abcdef01234-abcdef", + instance="substrate-abcdef01234-abcdef", }' values: '1+1x3 4+0x13' # 1 2 3 4 4 4 4 4 4 4 4 4 ... - - series: 'polkadot_block_height{ + - series: 'substrate_block_height{ status="finalized", - job="polkadot", - pod="polkadot-abcdef01234-abcdef", - instance="polkadot-abcdef01234-abcdef", + job="substrate", + pod="substrate-abcdef01234-abcdef", + instance="substrate-abcdef01234-abcdef", }' values: '1+1x3 4+0x13' # 1 2 3 4 4 4 4 4 4 4 4 4 ... @@ -56,13 +56,13 @@ tests: exp_alerts: - exp_labels: severity: warning - pod: polkadot-abcdef01234-abcdef - instance: polkadot-abcdef01234-abcdef - job: polkadot + pod: substrate-abcdef01234-abcdef + instance: substrate-abcdef01234-abcdef + job: substrate status: best exp_annotations: message: "Best block on instance - polkadot-abcdef01234-abcdef increases by less than 1 per + substrate-abcdef01234-abcdef increases by less than 1 per minute for more than 3 minutes." - eval_time: 14m @@ -70,23 +70,23 @@ tests: exp_alerts: - exp_labels: severity: warning - pod: polkadot-abcdef01234-abcdef - instance: polkadot-abcdef01234-abcdef - job: polkadot + pod: substrate-abcdef01234-abcdef + instance: substrate-abcdef01234-abcdef + job: substrate status: best exp_annotations: message: "Best block on instance - polkadot-abcdef01234-abcdef increases by less than 1 per + substrate-abcdef01234-abcdef increases by less than 1 per minute for more than 3 minutes." - exp_labels: severity: critical - pod: polkadot-abcdef01234-abcdef - instance: polkadot-abcdef01234-abcdef - job: polkadot + pod: substrate-abcdef01234-abcdef + instance: substrate-abcdef01234-abcdef + job: substrate status: best exp_annotations: message: "Best block on instance - polkadot-abcdef01234-abcdef increases by less than 1 per + substrate-abcdef01234-abcdef increases by less than 1 per minute for more than 10 minutes." ###################################################################### @@ -101,13 +101,13 @@ tests: exp_alerts: - exp_labels: severity: warning - pod: polkadot-abcdef01234-abcdef - instance: polkadot-abcdef01234-abcdef - job: polkadot + pod: substrate-abcdef01234-abcdef + instance: substrate-abcdef01234-abcdef + job: substrate status: finalized exp_annotations: message: "Finalized block on instance - polkadot-abcdef01234-abcdef increases by less than 1 per + substrate-abcdef01234-abcdef increases by less than 1 per minute for more than 3 minutes." - eval_time: 14m @@ -115,23 +115,23 @@ tests: exp_alerts: - exp_labels: severity: warning - pod: polkadot-abcdef01234-abcdef - instance: polkadot-abcdef01234-abcdef - job: polkadot + pod: substrate-abcdef01234-abcdef + instance: substrate-abcdef01234-abcdef + job: substrate status: finalized exp_annotations: message: "Finalized block on instance - polkadot-abcdef01234-abcdef increases by less than 1 per + substrate-abcdef01234-abcdef increases by less than 1 per minute for more than 3 minutes." - exp_labels: severity: critical - pod: polkadot-abcdef01234-abcdef - instance: polkadot-abcdef01234-abcdef - job: polkadot + pod: substrate-abcdef01234-abcdef + instance: substrate-abcdef01234-abcdef + job: substrate status: finalized exp_annotations: message: "Finalized block on instance - polkadot-abcdef01234-abcdef increases by less than 1 per + substrate-abcdef01234-abcdef increases by less than 1 per minute for more than 10 minutes." ###################################################################### @@ -152,12 +152,12 @@ tests: exp_alerts: - exp_labels: severity: warning - pod: polkadot-abcdef01234-abcdef - instance: polkadot-abcdef01234-abcdef - job: polkadot + pod: substrate-abcdef01234-abcdef + instance: substrate-abcdef01234-abcdef + job: substrate exp_annotations: message: "The transaction pool size on node - polkadot-abcdef01234-abcdef has been monotonically + substrate-abcdef01234-abcdef has been monotonically increasing for more than 10 minutes." - eval_time: 43m alertname: TransactionQueueSizeIncreasing @@ -167,21 +167,21 @@ tests: exp_alerts: - exp_labels: severity: warning - pod: polkadot-abcdef01234-abcdef - instance: polkadot-abcdef01234-abcdef - job: polkadot + pod: substrate-abcdef01234-abcdef + instance: substrate-abcdef01234-abcdef + job: substrate exp_annotations: message: "The transaction pool size on node - polkadot-abcdef01234-abcdef has been monotonically + substrate-abcdef01234-abcdef has been monotonically increasing for more than 10 minutes." - exp_labels: severity: warning - pod: polkadot-abcdef01234-abcdef - instance: polkadot-abcdef01234-abcdef - job: polkadot + pod: substrate-abcdef01234-abcdef + instance: substrate-abcdef01234-abcdef + job: substrate exp_annotations: message: "The transaction pool size on node - polkadot-abcdef01234-abcdef has been monotonically + substrate-abcdef01234-abcdef has been monotonically increasing for more than 30 minutes." - eval_time: 49m alertname: TransactionQueueSizeHigh @@ -191,12 +191,12 @@ tests: exp_alerts: - exp_labels: severity: warning - pod: polkadot-abcdef01234-abcdef - instance: polkadot-abcdef01234-abcdef - job: polkadot + pod: substrate-abcdef01234-abcdef + instance: substrate-abcdef01234-abcdef + job: substrate exp_annotations: message: "The transaction pool size on node - polkadot-abcdef01234-abcdef has been above 10_000 for more + substrate-abcdef01234-abcdef has been above 10_000 for more than 5 minutes." ###################################################################### @@ -211,11 +211,11 @@ tests: exp_alerts: - exp_labels: severity: warning - pod: polkadot-abcdef01234-abcdef - instance: polkadot-abcdef01234-abcdef - job: polkadot + pod: substrate-abcdef01234-abcdef + instance: substrate-abcdef01234-abcdef + job: substrate exp_annotations: - message: "The node polkadot-abcdef01234-abcdef has less + message: "The node substrate-abcdef01234-abcdef has less than 3 peers for more than 3 minutes" - eval_time: 16m # Values: 3 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 @@ -223,17 +223,17 @@ tests: exp_alerts: - exp_labels: severity: warning - pod: polkadot-abcdef01234-abcdef - instance: polkadot-abcdef01234-abcdef - job: polkadot + pod: substrate-abcdef01234-abcdef + instance: substrate-abcdef01234-abcdef + job: substrate exp_annotations: - message: "The node polkadot-abcdef01234-abcdef has less + message: "The node substrate-abcdef01234-abcdef has less than 3 peers for more than 3 minutes" - exp_labels: severity: critical - pod: polkadot-abcdef01234-abcdef - instance: polkadot-abcdef01234-abcdef - job: polkadot + pod: substrate-abcdef01234-abcdef + instance: substrate-abcdef01234-abcdef + job: substrate exp_annotations: - message: "The node polkadot-abcdef01234-abcdef has less + message: "The node substrate-abcdef01234-abcdef has less than 3 peers for more than 15 minutes" diff --git a/.maintain/monitoring/alerting-rules/alerting-rules.yaml b/.maintain/monitoring/alerting-rules/alerting-rules.yaml index 271161002433..4171f92f68fe 100644 --- a/.maintain/monitoring/alerting-rules/alerting-rules.yaml +++ b/.maintain/monitoring/alerting-rules/alerting-rules.yaml @@ -1,5 +1,5 @@ groups: -- name: polkadot.rules +- name: substrate.rules rules: ############################################################################## @@ -10,7 +10,7 @@ groups: annotations: message: 'Best block on instance {{ $labels.instance }} increases by less than 1 per minute for more than 3 minutes.' - expr: increase(polkadot_block_height{status="best"}[1m]) < 1 + expr: increase(substrate_block_height{status="best"}[1m]) < 1 for: 3m labels: severity: warning @@ -18,7 +18,7 @@ groups: annotations: message: 'Best block on instance {{ $labels.instance }} increases by less than 1 per minute for more than 10 minutes.' - expr: increase(polkadot_block_height{status="best"}[1m]) < 1 + expr: increase(substrate_block_height{status="best"}[1m]) < 1 for: 10m labels: severity: critical @@ -28,7 +28,7 @@ groups: ############################################################################## - alert: BlockFinalizationSlow - expr: increase(polkadot_block_height{status="finalized"}[1m]) < 1 + expr: increase(substrate_block_height{status="finalized"}[1m]) < 1 for: 3m labels: severity: warning @@ -36,7 +36,7 @@ groups: message: 'Finalized block on instance {{ $labels.instance }} increases by less than 1 per minute for more than 3 minutes.' - alert: BlockFinalizationSlow - expr: increase(polkadot_block_height{status="finalized"}[1m]) < 1 + expr: increase(substrate_block_height{status="finalized"}[1m]) < 1 for: 10m labels: severity: critical @@ -47,8 +47,8 @@ groups: # Under the assumption of an average block production of 6 seconds, # "best" and "finalized" being more than 10 blocks apart would imply # more than a 1 minute delay between block production and finalization. - expr: '(polkadot_block_height{status="best"} - ignoring(status) - polkadot_block_height{status="finalized"}) > 10' + expr: '(substrate_block_height{status="best"} - ignoring(status) + substrate_block_height{status="finalized"}) > 10' for: 8m labels: severity: critical @@ -61,8 +61,8 @@ groups: ############################################################################## - alert: TransactionQueueSizeIncreasing - expr: 'increase(polkadot_sub_txpool_validations_scheduled[5m]) - - increase(polkadot_sub_txpool_validations_finished[5m]) > 0' + expr: 'increase(substrate_sub_txpool_validations_scheduled[5m]) - + increase(substrate_sub_txpool_validations_finished[5m]) > 0' for: 10m labels: severity: warning @@ -70,8 +70,8 @@ groups: message: 'The transaction pool size on node {{ $labels.instance }} has been monotonically increasing for more than 10 minutes.' - alert: TransactionQueueSizeIncreasing - expr: 'increase(polkadot_sub_txpool_validations_scheduled[5m]) - - increase(polkadot_sub_txpool_validations_finished[5m]) > 0' + expr: 'increase(substrate_sub_txpool_validations_scheduled[5m]) - + increase(substrate_sub_txpool_validations_finished[5m]) > 0' for: 30m labels: severity: warning @@ -79,8 +79,8 @@ groups: message: 'The transaction pool size on node {{ $labels.instance }} has been monotonically increasing for more than 30 minutes.' - alert: TransactionQueueSizeHigh - expr: 'polkadot_sub_txpool_validations_scheduled - - polkadot_sub_txpool_validations_finished > 10000' + expr: 'substrate_sub_txpool_validations_scheduled - + substrate_sub_txpool_validations_finished > 10000' for: 5m labels: severity: warning @@ -93,7 +93,7 @@ groups: ############################################################################## - alert: NumberOfPeersLow - expr: polkadot_sub_libp2p_peers_count < 3 + expr: substrate_sub_libp2p_peers_count < 3 for: 3m labels: severity: warning @@ -101,7 +101,7 @@ groups: message: 'The node {{ $labels.instance }} has less than 3 peers for more than 3 minutes' - alert: NumberOfPeersLow - expr: polkadot_sub_libp2p_peers_count < 3 + expr: substrate_sub_libp2p_peers_count < 3 for: 15m labels: severity: critical @@ -109,7 +109,7 @@ groups: message: 'The node {{ $labels.instance }} has less than 3 peers for more than 15 minutes' - alert: NoIncomingConnection - expr: increase(polkadot_sub_libp2p_incoming_connections_total[20m]) == 0 + expr: increase(substrate_sub_libp2p_incoming_connections_total[20m]) == 0 labels: severity: warning annotations: @@ -121,7 +121,7 @@ groups: ############################################################################## - alert: NumberOfFileDescriptorsHigh - expr: 'node_filefd_allocated{domain=~"kusama|polkadot"} > 10000' + expr: 'node_filefd_allocated{chain!=""} > 10000' for: 3m labels: severity: warning @@ -134,9 +134,9 @@ groups: ############################################################################## - alert: AuthorityDiscoveryDiscoveryFailureHigh - expr: 'polkadot_authority_discovery_handle_value_found_event_failure / + expr: 'substrate_authority_discovery_handle_value_found_event_failure / ignoring(name) - polkadot_authority_discovery_dht_event_received{name="value_found"} > 0.5' + substrate_authority_discovery_dht_event_received{name="value_found"} > 0.5' for: 2h labels: severity: warning @@ -147,9 +147,9 @@ groups: - alert: UnboundedChannelPersistentlyLarge expr: '( - (polkadot_unbounded_channel_len{action = "send"} - - ignoring(action) polkadot_unbounded_channel_len{action = "received"}) - or on(instance) polkadot_unbounded_channel_len{action = "send"} + (substrate_unbounded_channel_len{action = "send"} - + ignoring(action) substrate_unbounded_channel_len{action = "received"}) + or on(instance) substrate_unbounded_channel_len{action = "send"} ) >= 200' for: 5m labels: @@ -160,9 +160,9 @@ groups: - alert: UnboundedChannelVeryLarge expr: '( - (polkadot_unbounded_channel_len{action = "send"} - - ignoring(action) polkadot_unbounded_channel_len{action = "received"}) - or on(instance) polkadot_unbounded_channel_len{action = "send"} + (substrate_unbounded_channel_len{action = "send"} - + ignoring(action) substrate_unbounded_channel_len{action = "received"}) + or on(instance) substrate_unbounded_channel_len{action = "send"} ) > 15000' labels: severity: warning diff --git a/.maintain/monitoring/grafana-dashboards/substrate-networking.json b/.maintain/monitoring/grafana-dashboards/substrate-networking.json index 46942cf582fc..abd675ed13ec 100644 --- a/.maintain/monitoring/grafana-dashboards/substrate-networking.json +++ b/.maintain/monitoring/grafana-dashboards/substrate-networking.json @@ -4,7 +4,7 @@ "name": "VAR_METRIC_NAMESPACE", "type": "constant", "label": "Prefix of the metrics", - "value": "polkadot", + "value": "substrate", "description": "" } ], diff --git a/.maintain/monitoring/grafana-dashboards/substrate-service-tasks.json b/.maintain/monitoring/grafana-dashboards/substrate-service-tasks.json index 2f08ac7bb34c..ce7e9f78cd8a 100644 --- a/.maintain/monitoring/grafana-dashboards/substrate-service-tasks.json +++ b/.maintain/monitoring/grafana-dashboards/substrate-service-tasks.json @@ -4,7 +4,7 @@ "name": "VAR_METRIC_NAMESPACE", "type": "constant", "label": "Prefix of the metrics", - "value": "polkadot", + "value": "substrate", "description": "" } ], From 7c6342047c992b6f3fa917d0d0448eb7e89afa6c Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Wed, 2 Feb 2022 15:25:13 +0100 Subject: [PATCH 447/695] bench-cli: Support `JSON` output (#10771) * Add dependencies Signed-off-by: Oliver Tale-Yazdi * Make benchmark results serializable Signed-off-by: Oliver Tale-Yazdi * Add `--json[-file]` options Signed-off-by: Oliver Tale-Yazdi * Enable JSON output Signed-off-by: Oliver Tale-Yazdi * Use specific serde version Polkadot does not compile otherwise. Signed-off-by: Oliver Tale-Yazdi * Review comments Signed-off-by: Oliver Tale-Yazdi * Review comment: fs::write Signed-off-by: Oliver Tale-Yazdi --- Cargo.lock | 2 + frame/benchmarking/Cargo.toml | 2 + frame/benchmarking/src/utils.rs | 25 +++++++ utils/frame/benchmarking-cli/Cargo.toml | 1 + utils/frame/benchmarking-cli/src/command.rs | 82 +++++++++++---------- utils/frame/benchmarking-cli/src/lib.rs | 18 +++-- 6 files changed, 84 insertions(+), 46 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 963082a7e3af..af6cb045f7a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2038,6 +2038,7 @@ dependencies = [ "parity-scale-codec", "paste 1.0.6", "scale-info", + "serde", "sp-api", "sp-application-crypto", "sp-io", @@ -2066,6 +2067,7 @@ dependencies = [ "sc-executor", "sc-service", "serde", + "serde_json", "sp-core", "sp-externalities", "sp-keystore", diff --git a/frame/benchmarking/Cargo.toml b/frame/benchmarking/Cargo.toml index 9afdc79fae65..0283b3f7c948 100644 --- a/frame/benchmarking/Cargo.toml +++ b/frame/benchmarking/Cargo.toml @@ -27,6 +27,7 @@ sp-storage = { version = "5.0.0", path = "../../primitives/storage", default-fea frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } log = { version = "0.4.14", default-features = false } +serde = { version = "1.0.132", optional = true } [dev-dependencies] hex-literal = "0.3.4" @@ -37,6 +38,7 @@ default = ["std"] std = [ "codec/std", "scale-info/std", + "serde", "sp-runtime-interface/std", "sp-runtime/std", "sp-api/std", diff --git a/frame/benchmarking/src/utils.rs b/frame/benchmarking/src/utils.rs index bb0b8d36a752..8c642f74358d 100644 --- a/frame/benchmarking/src/utils.rs +++ b/frame/benchmarking/src/utils.rs @@ -22,12 +22,15 @@ use frame_support::{ pallet_prelude::*, traits::StorageInfo, }; +#[cfg(feature = "std")] +use serde::Serialize; use sp_io::hashing::blake2_256; use sp_runtime::traits::TrailingZeroInput; use sp_std::{prelude::Box, vec::Vec}; use sp_storage::TrackedStorageKey; /// An alphabet of possible parameters to use for benchmarking. +#[cfg_attr(feature = "std", derive(Serialize))] #[derive(Encode, Decode, Clone, Copy, PartialEq, Debug)] #[allow(missing_docs)] #[allow(non_camel_case_types)] @@ -68,13 +71,17 @@ impl std::fmt::Display for BenchmarkParameter { } /// The results of a single of benchmark. +#[cfg_attr(feature = "std", derive(Serialize))] #[derive(Encode, Decode, Clone, PartialEq, Debug)] pub struct BenchmarkBatch { /// The pallet containing this benchmark. + #[cfg_attr(feature = "std", serde(with = "serde_as_str"))] pub pallet: Vec, /// The instance of this pallet being benchmarked. + #[cfg_attr(feature = "std", serde(with = "serde_as_str"))] pub instance: Vec, /// The extrinsic (or benchmark name) of this benchmark. + #[cfg_attr(feature = "std", serde(with = "serde_as_str"))] pub benchmark: Vec, /// The results from this benchmark. pub results: Vec, @@ -82,13 +89,17 @@ pub struct BenchmarkBatch { // TODO: could probably make API cleaner here. /// The results of a single of benchmark, where time and db results are separated. +#[cfg_attr(feature = "std", derive(Serialize))] #[derive(Encode, Decode, Clone, PartialEq, Debug)] pub struct BenchmarkBatchSplitResults { /// The pallet containing this benchmark. + #[cfg_attr(feature = "std", serde(with = "serde_as_str"))] pub pallet: Vec, /// The instance of this pallet being benchmarked. + #[cfg_attr(feature = "std", serde(with = "serde_as_str"))] pub instance: Vec, /// The extrinsic (or benchmark name) of this benchmark. + #[cfg_attr(feature = "std", serde(with = "serde_as_str"))] pub benchmark: Vec, /// The extrinsic timing results from this benchmark. pub time_results: Vec, @@ -99,6 +110,7 @@ pub struct BenchmarkBatchSplitResults { /// Result from running benchmarks on a FRAME pallet. /// Contains duration of the function call in nanoseconds along with the benchmark parameters /// used for that benchmark result. +#[cfg_attr(feature = "std", derive(Serialize))] #[derive(Encode, Decode, Default, Clone, PartialEq, Debug)] pub struct BenchmarkResult { pub components: Vec<(BenchmarkParameter, u32)>, @@ -109,6 +121,7 @@ pub struct BenchmarkResult { pub writes: u32, pub repeat_writes: u32, pub proof_size: u32, + #[cfg_attr(feature = "std", serde(skip_serializing))] pub keys: Vec<(Vec, u32, u32, bool)>, } @@ -118,6 +131,18 @@ impl BenchmarkResult { } } +/// Helper module to make serde serialize `Vec` as strings. +#[cfg(feature = "std")] +mod serde_as_str { + pub fn serialize(value: &Vec, serializer: S) -> Result + where + S: serde::Serializer, + { + let s = std::str::from_utf8(value).map_err(serde::ser::Error::custom)?; + serializer.collect_str(s) + } +} + /// Possible errors returned from the benchmarking pipeline. #[derive(Clone, PartialEq, Debug)] pub enum BenchmarkError { diff --git a/utils/frame/benchmarking-cli/Cargo.toml b/utils/frame/benchmarking-cli/Cargo.toml index 971fb31a3f8c..03a625a155dc 100644 --- a/utils/frame/benchmarking-cli/Cargo.toml +++ b/utils/frame/benchmarking-cli/Cargo.toml @@ -28,6 +28,7 @@ codec = { version = "2.0.0", package = "parity-scale-codec" } clap = { version = "3.0", features = ["derive"] } chrono = "0.4" serde = "1.0.132" +serde_json = "1.0.74" handlebars = "4.1.6" Inflector = "0.11.4" linked-hash-map = "0.5.4" diff --git a/utils/frame/benchmarking-cli/src/command.rs b/utils/frame/benchmarking-cli/src/command.rs index a5046dbaad2a..a5b53bcf99c7 100644 --- a/utils/frame/benchmarking-cli/src/command.rs +++ b/utils/frame/benchmarking-cli/src/command.rs @@ -35,7 +35,7 @@ use sp_externalities::Extensions; use sp_keystore::{testing::KeyStore, KeystoreExt, SyncCryptoStorePtr}; use sp_runtime::traits::{Block as BlockT, Header as HeaderT}; use sp_state_machine::StateMachine; -use std::{fmt::Debug, sync::Arc, time}; +use std::{fmt::Debug, fs, sync::Arc, time}; // This takes multiple benchmark batches and combines all the results where the pallet, instance, // and benchmark are the same. @@ -357,55 +357,61 @@ impl BenchmarkCmd { // are together. let batches: Vec = combine_batches(batches, batches_db); + // Create the weights.rs file. if let Some(output_path) = &self.output { crate::writer::write_results(&batches, &storage_info, output_path, self)?; } + // Jsonify the result and write it to a file or stdout if desired. + if !self.jsonify(&batches)? { + // Print the summary only if `jsonify` did not write to stdout. + self.print_summary(&batches, &storage_info) + } + Ok(()) + } + + /// Jsonifies the passed batches and writes them to stdout or into a file. + /// Can be configured via `--json` and `--json-file`. + /// Returns whether it wrote to stdout. + fn jsonify(&self, batches: &Vec) -> Result { + if self.json_output || self.json_file.is_some() { + let json = serde_json::to_string_pretty(&batches) + .map_err(|e| format!("Serializing into JSON: {:?}", e))?; + + if let Some(path) = &self.json_file { + fs::write(path, json)?; + } else { + println!("{}", json); + return Ok(true) + } + } + + Ok(false) + } + + /// Prints the results as human-readable summary without raw timing data. + fn print_summary( + &self, + batches: &Vec, + storage_info: &Vec, + ) { for batch in batches.into_iter() { // Print benchmark metadata println!( - "Pallet: {:?}, Extrinsic: {:?}, Lowest values: {:?}, Highest values: {:?}, Steps: {:?}, Repeat: {:?}", - String::from_utf8(batch.pallet).expect("Encoded from String; qed"), - String::from_utf8(batch.benchmark).expect("Encoded from String; qed"), - self.lowest_range_values, - self.highest_range_values, - self.steps, - self.repeat, - ); + "Pallet: {:?}, Extrinsic: {:?}, Lowest values: {:?}, Highest values: {:?}, Steps: {:?}, Repeat: {:?}", + String::from_utf8(batch.pallet.clone()).expect("Encoded from String; qed"), + String::from_utf8(batch.benchmark.clone()).expect("Encoded from String; qed"), + self.lowest_range_values, + self.highest_range_values, + self.steps, + self.repeat, + ); // Skip raw data + analysis if there are no results if batch.time_results.is_empty() { continue } - if self.raw_data { - // Print the table header - batch.time_results[0] - .components - .iter() - .for_each(|param| print!("{:?},", param.0)); - - print!("extrinsic_time_ns,storage_root_time_ns,reads,repeat_reads,writes,repeat_writes,proof_size_bytes\n"); - // Print the values - batch.time_results.iter().for_each(|result| { - let parameters = &result.components; - parameters.iter().for_each(|param| print!("{:?},", param.1)); - // Print extrinsic time and storage root time - print!( - "{:?},{:?},{:?},{:?},{:?},{:?},{:?}\n", - result.extrinsic_time, - result.storage_root_time, - result.reads, - result.repeat_reads, - result.writes, - result.repeat_writes, - result.proof_size, - ); - }); - - println!(); - } - if !self.no_storage_info { let mut comments: Vec = Default::default(); crate::writer::add_storage_comments( @@ -460,8 +466,6 @@ impl BenchmarkCmd { println!(""); } } - - Ok(()) } } diff --git a/utils/frame/benchmarking-cli/src/lib.rs b/utils/frame/benchmarking-cli/src/lib.rs index 6afaa2b249fc..3b0f4843d206 100644 --- a/utils/frame/benchmarking-cli/src/lib.rs +++ b/utils/frame/benchmarking-cli/src/lib.rs @@ -19,7 +19,7 @@ mod command; mod writer; use sc_cli::{ExecutionStrategy, WasmExecutionMethod}; -use std::fmt::Debug; +use std::{fmt::Debug, path::PathBuf}; // Add a more relaxed parsing for pallet names by allowing pallet directory names with `-` to be // used like crate names with `_` @@ -60,9 +60,13 @@ pub struct BenchmarkCmd { #[clap(long, default_value = "1")] pub external_repeat: u32, - /// Print the raw results. - #[clap(long = "raw")] - pub raw_data: bool, + /// Print the raw results in JSON format. + #[clap(long = "json")] + pub json_output: bool, + + /// Write the raw results in JSON format into the give file. + #[clap(long, conflicts_with = "json-output")] + pub json_file: Option, /// Don't print the median-slopes linear regression analysis. #[clap(long)] @@ -74,15 +78,15 @@ pub struct BenchmarkCmd { /// Output the benchmarks to a Rust file at the given path. #[clap(long)] - pub output: Option, + pub output: Option, /// Add a header file to your outputted benchmarks #[clap(long)] - pub header: Option, + pub header: Option, /// Path to Handlebars template file used for outputting benchmark results. (Optional) #[clap(long)] - pub template: Option, + pub template: Option, /// Which analysis function to use when outputting benchmarks: /// * min-squares (default) From cd7a0563866db4e12fefb62f261a6242eb31afef Mon Sep 17 00:00:00 2001 From: driemworks Date: Wed, 2 Feb 2022 13:29:20 -0500 Subject: [PATCH 448/695] update extrinsic names --- bin/node-template/pallets/iris-assets/src/lib.rs | 7 +++---- bin/node-template/pallets/iris-session/src/lib.rs | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/bin/node-template/pallets/iris-assets/src/lib.rs b/bin/node-template/pallets/iris-assets/src/lib.rs index c59d2f6aebce..1885350bd933 100644 --- a/bin/node-template/pallets/iris-assets/src/lib.rs +++ b/bin/node-template/pallets/iris-assets/src/lib.rs @@ -223,7 +223,7 @@ pub mod pallet { /// * `balance`: the balance the owner is willing to use to back the asset class which will be created /// #[pallet::weight(0)] - pub fn create_storage_asset( + pub fn create( origin: OriginFor, admin: ::Source, addr: Vec, @@ -256,7 +256,7 @@ pub mod pallet { /// * amount: the number of tickets to mint /// #[pallet::weight(0)] - pub fn mint_tickets( + pub fn mint( origin: OriginFor, beneficiary: ::Source, asset_id: T::AssetId, @@ -266,8 +266,7 @@ pub mod pallet { ensure!(AssetClassOwnership::::contains_key(who.clone(), asset_id.clone()), Error::::NoSuchOwnedContent); let new_origin = system::RawOrigin::Signed(who.clone()).into(); - let beneficiary_accountid = T::Lookup::lookup(beneficiary.clone())?; - // let asset_id = AssetClassOwnership::::get(who.clone(), cid.clone(),); + let beneficiary_accountid = T::Lookup::lookup(beneficiary.clone())?; >::mint(new_origin, asset_id.clone(), beneficiary.clone(), amount) .map_err(|_| Error::::CantMintAssets)?; >::insert(beneficiary_accountid.clone(), asset_id.clone(), who.clone()); diff --git a/bin/node-template/pallets/iris-session/src/lib.rs b/bin/node-template/pallets/iris-session/src/lib.rs index 673ae34e8b5a..a40cfb2d8812 100644 --- a/bin/node-template/pallets/iris-session/src/lib.rs +++ b/bin/node-template/pallets/iris-session/src/lib.rs @@ -331,7 +331,7 @@ pub mod pallet { } #[pallet::weight(0)] - pub fn request_store_content( + pub fn join_storage_pool( origin: OriginFor, pool_owner: ::Source, pool_id: T::AssetId, From d161d54353b64c24fdc458913471f40c2683af32 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Thu, 3 Feb 2022 14:02:45 +0100 Subject: [PATCH 449/695] Introduce ModuleError struct (#10776) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * better partial eq impl * introduce module error * fmt * import module error * Apply suggestions from code review Co-authored-by: Bastian Köcher * fixes * fmt Co-authored-by: Bastian Köcher --- .../election-provider-multi-phase/src/lib.rs | 4 +- .../src/unsigned.rs | 10 +-- frame/elections-phragmen/src/lib.rs | 6 +- .../procedural/src/pallet/expand/error.rs | 4 +- frame/support/src/error.rs | 4 +- frame/support/test/tests/construct_runtime.rs | 24 ++--- frame/support/test/tests/pallet.rs | 8 +- frame/support/test/tests/pallet_instance.rs | 14 ++- primitives/runtime/src/lib.rs | 87 +++++++++---------- 9 files changed, 84 insertions(+), 77 deletions(-) diff --git a/frame/election-provider-multi-phase/src/lib.rs b/frame/election-provider-multi-phase/src/lib.rs index 0a620e6c1282..a5ed593e1a4e 100644 --- a/frame/election-provider-multi-phase/src/lib.rs +++ b/frame/election-provider-multi-phase/src/lib.rs @@ -255,7 +255,7 @@ use sp_runtime::{ InvalidTransaction, TransactionPriority, TransactionSource, TransactionValidity, TransactionValidityError, ValidTransaction, }, - DispatchError, PerThing, Perbill, RuntimeDebug, SaturatedConversion, + DispatchError, ModuleError, PerThing, Perbill, RuntimeDebug, SaturatedConversion, }; use sp_std::prelude::*; @@ -1579,7 +1579,7 @@ impl ElectionProvider for Pallet { /// number. pub fn dispatch_error_to_invalid(error: DispatchError) -> InvalidTransaction { let error_number = match error { - DispatchError::Module { error, .. } => error, + DispatchError::Module(ModuleError { error, .. }) => error, _ => 0, }; InvalidTransaction::Custom(error_number) diff --git a/frame/election-provider-multi-phase/src/unsigned.rs b/frame/election-provider-multi-phase/src/unsigned.rs index 936993b41fb6..196147f8a470 100644 --- a/frame/election-provider-multi-phase/src/unsigned.rs +++ b/frame/election-provider-multi-phase/src/unsigned.rs @@ -752,7 +752,7 @@ mod tests { use sp_runtime::{ offchain::storage_lock::{BlockAndTime, StorageLock}, traits::ValidateUnsigned, - PerU16, + ModuleError, PerU16, }; type Assignment = crate::unsigned::Assignment; @@ -922,8 +922,8 @@ mod tests { #[test] #[should_panic(expected = "Invalid unsigned submission must produce invalid block and \ deprive validator from their authoring reward.: \ - Module { index: 2, error: 1, message: \ - Some(\"PreDispatchWrongWinnerCount\") }")] + Module(ModuleError { index: 2, error: 1, message: \ + Some(\"PreDispatchWrongWinnerCount\") })")] fn unfeasible_solution_panics() { ExtBuilder::default().build_and_execute(|| { roll_to(25); @@ -1033,11 +1033,11 @@ mod tests { assert_eq!( MultiPhase::mine_check_save_submit().unwrap_err(), - MinerError::PreDispatchChecksFailed(DispatchError::Module { + MinerError::PreDispatchChecksFailed(DispatchError::Module(ModuleError { index: 2, error: 1, message: Some("PreDispatchWrongWinnerCount"), - }), + })), ); }) } diff --git a/frame/elections-phragmen/src/lib.rs b/frame/elections-phragmen/src/lib.rs index bc6a81125e8b..4758c793cfef 100644 --- a/frame/elections-phragmen/src/lib.rs +++ b/frame/elections-phragmen/src/lib.rs @@ -1132,7 +1132,7 @@ mod tests { use sp_runtime::{ testing::Header, traits::{BlakeTwo256, IdentityLookup}, - BuildStorage, + BuildStorage, ModuleError, }; use substrate_test_utils::assert_eq_uvec; @@ -2514,7 +2514,7 @@ mod tests { let unwrapped_error = Elections::remove_member(Origin::root(), 4, true).unwrap_err(); assert!(matches!( unwrapped_error.error, - DispatchError::Module { message: Some("InvalidReplacement"), .. } + DispatchError::Module(ModuleError { message: Some("InvalidReplacement"), .. }) )); assert!(unwrapped_error.post_info.actual_weight.is_some()); }); @@ -2537,7 +2537,7 @@ mod tests { let unwrapped_error = Elections::remove_member(Origin::root(), 4, false).unwrap_err(); assert!(matches!( unwrapped_error.error, - DispatchError::Module { message: Some("InvalidReplacement"), .. } + DispatchError::Module(ModuleError { message: Some("InvalidReplacement"), .. }) )); assert!(unwrapped_error.post_info.actual_weight.is_some()); }); diff --git a/frame/support/procedural/src/pallet/expand/error.rs b/frame/support/procedural/src/pallet/expand/error.rs index 4cf572c1797f..9e2b801083e4 100644 --- a/frame/support/procedural/src/pallet/expand/error.rs +++ b/frame/support/procedural/src/pallet/expand/error.rs @@ -124,11 +124,11 @@ pub fn expand_error(def: &mut Def) -> proc_macro2::TokenStream { >::index::>() .expect("Every active module has an index in the runtime; qed") as u8; - #frame_support::sp_runtime::DispatchError::Module { + #frame_support::sp_runtime::DispatchError::Module(#frame_support::sp_runtime::ModuleError { index, error: err.as_u8(), message: Some(err.as_str()), - } + }) } } ) diff --git a/frame/support/src/error.rs b/frame/support/src/error.rs index abac4a53269a..4880bba5c5e9 100644 --- a/frame/support/src/error.rs +++ b/frame/support/src/error.rs @@ -153,11 +153,11 @@ macro_rules! decl_error { ::index::<$module<$generic $(, $inst_generic)?>>() .expect("Every active module has an index in the runtime; qed") as u8; - $crate::sp_runtime::DispatchError::Module { + $crate::sp_runtime::DispatchError::Module($crate::sp_runtime::ModuleError { index, error: err.as_u8(), message: Some(err.as_str()), - } + }) } } }; diff --git a/frame/support/test/tests/construct_runtime.rs b/frame/support/test/tests/construct_runtime.rs index 267d560edf92..b3f8feb8aa4b 100644 --- a/frame/support/test/tests/construct_runtime.rs +++ b/frame/support/test/tests/construct_runtime.rs @@ -27,7 +27,7 @@ use sp_core::{sr25519, H256}; use sp_runtime::{ generic, traits::{BlakeTwo256, Verify}, - DispatchError, + DispatchError, ModuleError, }; use sp_std::cell::RefCell; @@ -363,47 +363,47 @@ mod origin_test { fn check_modules_error_type() { assert_eq!( Module1_1::fail(system::Origin::::Root.into()), - Err(DispatchError::Module { index: 31, error: 0, message: Some("Something") }), + Err(DispatchError::Module(ModuleError { index: 31, error: 0, message: Some("Something") })), ); assert_eq!( Module2::fail(system::Origin::::Root.into()), - Err(DispatchError::Module { index: 32, error: 0, message: Some("Something") }), + Err(DispatchError::Module(ModuleError { index: 32, error: 0, message: Some("Something") })), ); assert_eq!( Module1_2::fail(system::Origin::::Root.into()), - Err(DispatchError::Module { index: 33, error: 0, message: Some("Something") }), + Err(DispatchError::Module(ModuleError { index: 33, error: 0, message: Some("Something") })), ); assert_eq!( NestedModule3::fail(system::Origin::::Root.into()), - Err(DispatchError::Module { index: 34, error: 0, message: Some("Something") }), + Err(DispatchError::Module(ModuleError { index: 34, error: 0, message: Some("Something") })), ); assert_eq!( Module1_3::fail(system::Origin::::Root.into()), - Err(DispatchError::Module { index: 6, error: 0, message: Some("Something") }), + Err(DispatchError::Module(ModuleError { index: 6, error: 0, message: Some("Something") })), ); assert_eq!( Module1_4::fail(system::Origin::::Root.into()), - Err(DispatchError::Module { index: 3, error: 0, message: Some("Something") }), + Err(DispatchError::Module(ModuleError { index: 3, error: 0, message: Some("Something") })), ); assert_eq!( Module1_5::fail(system::Origin::::Root.into()), - Err(DispatchError::Module { index: 4, error: 0, message: Some("Something") }), + Err(DispatchError::Module(ModuleError { index: 4, error: 0, message: Some("Something") })), ); assert_eq!( Module1_6::fail(system::Origin::::Root.into()), - Err(DispatchError::Module { index: 1, error: 0, message: Some("Something") }), + Err(DispatchError::Module(ModuleError { index: 1, error: 0, message: Some("Something") })), ); assert_eq!( Module1_7::fail(system::Origin::::Root.into()), - Err(DispatchError::Module { index: 2, error: 0, message: Some("Something") }), + Err(DispatchError::Module(ModuleError { index: 2, error: 0, message: Some("Something") })), ); assert_eq!( Module1_8::fail(system::Origin::::Root.into()), - Err(DispatchError::Module { index: 12, error: 0, message: Some("Something") }), + Err(DispatchError::Module(ModuleError { index: 12, error: 0, message: Some("Something") })), ); assert_eq!( Module1_9::fail(system::Origin::::Root.into()), - Err(DispatchError::Module { index: 13, error: 0, message: Some("Something") }), + Err(DispatchError::Module(ModuleError { index: 13, error: 0, message: Some("Something") })), ); } diff --git a/frame/support/test/tests/pallet.rs b/frame/support/test/tests/pallet.rs index cf882556088e..451cb2e7b889 100644 --- a/frame/support/test/tests/pallet.rs +++ b/frame/support/test/tests/pallet.rs @@ -29,7 +29,7 @@ use sp_io::{ hashing::{blake2_128, twox_128, twox_64}, TestExternalities, }; -use sp_runtime::DispatchError; +use sp_runtime::{DispatchError, ModuleError}; pub struct SomeType1; impl From for u64 { @@ -654,7 +654,11 @@ fn error_expand() { ); assert_eq!( DispatchError::from(pallet::Error::::InsufficientProposersBalance), - DispatchError::Module { index: 1, error: 0, message: Some("InsufficientProposersBalance") }, + DispatchError::Module(ModuleError { + index: 1, + error: 0, + message: Some("InsufficientProposersBalance") + }), ); } diff --git a/frame/support/test/tests/pallet_instance.rs b/frame/support/test/tests/pallet_instance.rs index 4a8636919b58..30b9bcda88d1 100644 --- a/frame/support/test/tests/pallet_instance.rs +++ b/frame/support/test/tests/pallet_instance.rs @@ -25,7 +25,7 @@ use sp_io::{ hashing::{blake2_128, twox_128, twox_64}, TestExternalities, }; -use sp_runtime::DispatchError; +use sp_runtime::{DispatchError, ModuleError}; #[frame_support::pallet] pub mod pallet { @@ -341,7 +341,11 @@ fn error_expand() { ); assert_eq!( DispatchError::from(pallet::Error::::InsufficientProposersBalance), - DispatchError::Module { index: 1, error: 0, message: Some("InsufficientProposersBalance") }, + DispatchError::Module(ModuleError { + index: 1, + error: 0, + message: Some("InsufficientProposersBalance") + }), ); assert_eq!( @@ -358,7 +362,11 @@ fn error_expand() { DispatchError::from( pallet::Error::::InsufficientProposersBalance ), - DispatchError::Module { index: 2, error: 0, message: Some("InsufficientProposersBalance") }, + DispatchError::Module(ModuleError { + index: 2, + error: 0, + message: Some("InsufficientProposersBalance") + }), ); } diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 84817a6be5d7..6d32d2322c76 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -461,9 +461,29 @@ pub type DispatchResult = sp_std::result::Result<(), DispatchError>; /// about the `Dispatchable` that is only known post dispatch. pub type DispatchResultWithInfo = sp_std::result::Result>; -/// Reason why a dispatch call failed. +/// Reason why a pallet call failed. #[derive(Eq, Clone, Copy, Encode, Decode, Debug, TypeInfo)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct ModuleError { + /// Module index, matching the metadata module index. + pub index: u8, + /// Module specific error value. + pub error: u8, + /// Optional error message. + #[codec(skip)] + #[cfg_attr(feature = "std", serde(skip_deserializing))] + pub message: Option<&'static str>, +} + +impl PartialEq for ModuleError { + fn eq(&self, other: &Self) -> bool { + (self.index == other.index) && (self.error == other.error) + } +} + +/// Reason why a dispatch call failed. +#[derive(Eq, Clone, Copy, Encode, Decode, Debug, TypeInfo, PartialEq)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub enum DispatchError { /// Some error occurred. Other( @@ -476,16 +496,7 @@ pub enum DispatchError { /// A bad origin. BadOrigin, /// A custom error in a module. - Module { - /// Module index, matching the metadata module index. - index: u8, - /// Module specific error value. - error: u8, - /// Optional error message. - #[codec(skip)] - #[cfg_attr(feature = "std", serde(skip_deserializing))] - message: Option<&'static str>, - }, + Module(ModuleError), /// At least one consumer is remaining so the account cannot be destroyed. ConsumerRemaining, /// There are no providers so the account cannot be created. @@ -515,8 +526,8 @@ impl DispatchError { /// Return the same error but without the attached message. pub fn stripped(self) -> Self { match self { - DispatchError::Module { index, error, message: Some(_) } => - DispatchError::Module { index, error, message: None }, + DispatchError::Module(ModuleError { index, error, message: Some(_) }) => + DispatchError::Module(ModuleError { index, error, message: None }), m => m, } } @@ -624,7 +635,8 @@ impl From for &'static str { DispatchError::Other(msg) => msg, DispatchError::CannotLookup => "Cannot lookup", DispatchError::BadOrigin => "Bad origin", - DispatchError::Module { message, .. } => message.unwrap_or("Unknown module error"), + DispatchError::Module(ModuleError { message, .. }) => + message.unwrap_or("Unknown module error"), DispatchError::ConsumerRemaining => "Consumer remaining", DispatchError::NoProviders => "No providers", DispatchError::TooManyConsumers => "Too many consumers", @@ -650,7 +662,7 @@ impl traits::Printable for DispatchError { Self::Other(err) => err.print(), Self::CannotLookup => "Cannot lookup".print(), Self::BadOrigin => "Bad origin".print(), - Self::Module { index, error, message } => { + Self::Module(ModuleError { index, error, message }) => { index.print(); error.print(); if let Some(msg) = message { @@ -683,30 +695,6 @@ where } } -impl PartialEq for DispatchError { - fn eq(&self, other: &Self) -> bool { - use DispatchError::*; - - match (self, other) { - (CannotLookup, CannotLookup) | - (BadOrigin, BadOrigin) | - (ConsumerRemaining, ConsumerRemaining) | - (NoProviders, NoProviders) => true, - - (Token(l), Token(r)) => l == r, - (Other(l), Other(r)) => l == r, - (Arithmetic(l), Arithmetic(r)) => l == r, - - ( - Module { index: index_l, error: error_l, .. }, - Module { index: index_r, error: error_r, .. }, - ) => (index_l == index_r) && (error_l == error_r), - - _ => false, - } - } -} - /// This type specifies the outcome of dispatching a call to a module. /// /// In case of failure an error specific to the module is returned. @@ -932,11 +920,18 @@ mod tests { #[test] fn dispatch_error_encoding() { - let error = DispatchError::Module { index: 1, error: 2, message: Some("error message") }; + let error = DispatchError::Module(ModuleError { + index: 1, + error: 2, + message: Some("error message"), + }); let encoded = error.encode(); let decoded = DispatchError::decode(&mut &encoded[..]).unwrap(); assert_eq!(encoded, vec![3, 1, 2]); - assert_eq!(decoded, DispatchError::Module { index: 1, error: 2, message: None }); + assert_eq!( + decoded, + DispatchError::Module(ModuleError { index: 1, error: 2, message: None }) + ); } #[test] @@ -948,9 +943,9 @@ mod tests { Other("bar"), CannotLookup, BadOrigin, - Module { index: 1, error: 1, message: None }, - Module { index: 1, error: 2, message: None }, - Module { index: 2, error: 1, message: None }, + Module(ModuleError { index: 1, error: 1, message: None }), + Module(ModuleError { index: 1, error: 2, message: None }), + Module(ModuleError { index: 2, error: 1, message: None }), ConsumerRemaining, NoProviders, Token(TokenError::NoFunds), @@ -975,8 +970,8 @@ mod tests { // Ignores `message` field in `Module` variant. assert_eq!( - Module { index: 1, error: 1, message: Some("foo") }, - Module { index: 1, error: 1, message: None }, + Module(ModuleError { index: 1, error: 1, message: Some("foo") }), + Module(ModuleError { index: 1, error: 1, message: None }), ); } From 59649dd117969467d8046df86afe56810f596545 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Thu, 3 Feb 2022 16:58:16 +0000 Subject: [PATCH 450/695] Bump sp-keyring (#10790) --- Cargo.lock | 2 +- bin/node/cli/Cargo.toml | 2 +- bin/node/executor/Cargo.toml | 2 +- bin/node/runtime/Cargo.toml | 2 +- bin/node/testing/Cargo.toml | 2 +- client/cli/Cargo.toml | 2 +- client/consensus/aura/Cargo.toml | 2 +- client/consensus/babe/rpc/Cargo.toml | 2 +- client/finality-grandpa/Cargo.toml | 2 +- client/finality-grandpa/rpc/Cargo.toml | 2 +- frame/grandpa/Cargo.toml | 2 +- frame/indices/Cargo.toml | 2 +- primitives/keyring/Cargo.toml | 2 +- test-utils/client/Cargo.toml | 2 +- test-utils/runtime/Cargo.toml | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index af6cb045f7a6..2e254e7d1184 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9738,7 +9738,7 @@ dependencies = [ [[package]] name = "sp-keyring" -version = "4.1.0-dev" +version = "5.0.0" dependencies = [ "lazy_static", "sp-core", diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index db198592b37b..211311c3dac2 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -52,7 +52,7 @@ sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } sp-timestamp = { version = "4.0.0-dev", path = "../../../primitives/timestamp" } sp-authorship = { version = "4.0.0-dev", path = "../../../primitives/authorship" } sp-inherents = { version = "4.0.0-dev", path = "../../../primitives/inherents" } -sp-keyring = { version = "4.1.0-dev", path = "../../../primitives/keyring" } +sp-keyring = { version = "5.0.0", path = "../../../primitives/keyring" } sp-keystore = { version = "0.11.0", path = "../../../primitives/keystore" } sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" } sp-transaction-pool = { version = "4.0.0-dev", path = "../../../primitives/transaction-pool" } diff --git a/bin/node/executor/Cargo.toml b/bin/node/executor/Cargo.toml index 39cf1ee8d893..531fffe35529 100644 --- a/bin/node/executor/Cargo.toml +++ b/bin/node/executor/Cargo.toml @@ -38,7 +38,7 @@ sp-application-crypto = { version = "5.0.0", path = "../../../primitives/applica sp-consensus-babe = { version = "0.10.0-dev", path = "../../../primitives/consensus/babe" } sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } sp-externalities = { version = "0.11.0", path = "../../../primitives/externalities" } -sp-keyring = { version = "4.1.0-dev", path = "../../../primitives/keyring" } +sp-keyring = { version = "5.0.0", path = "../../../primitives/keyring" } wat = "1.0" futures = "0.3.9" diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 84eec7662361..647562caff30 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -35,7 +35,7 @@ sp-std = { version = "4.0.0", default-features = false, path = "../../../primiti sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/api" } sp-runtime = { version = "5.0.0", default-features = false, path = "../../../primitives/runtime" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/staking" } -sp-keyring = { version = "4.1.0-dev", optional = true, path = "../../../primitives/keyring" } +sp-keyring = { version = "5.0.0", optional = true, path = "../../../primitives/keyring" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/session" } sp-transaction-pool = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/transaction-pool" } sp-version = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/version" } diff --git a/bin/node/testing/Cargo.toml b/bin/node/testing/Cargo.toml index 55ae52b50d9d..3275aac0ef1d 100644 --- a/bin/node/testing/Cargo.toml +++ b/bin/node/testing/Cargo.toml @@ -24,7 +24,7 @@ sc-client-db = { version = "0.10.0-dev", path = "../../../client/db/", features sc-client-api = { version = "4.0.0-dev", path = "../../../client/api/" } sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/common" } codec = { package = "parity-scale-codec", version = "2.0.0" } -sp-keyring = { version = "4.1.0-dev", path = "../../../primitives/keyring" } +sp-keyring = { version = "5.0.0", path = "../../../primitives/keyring" } node-executor = { version = "3.0.0-dev", path = "../executor" } node-primitives = { version = "2.0.0", path = "../primitives" } node-runtime = { version = "3.0.0-dev", path = "../runtime" } diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index ca7e0ac768f9..f7af649d3bf3 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -40,7 +40,7 @@ sc-tracing = { version = "4.0.0-dev", path = "../tracing" } sc-utils = { version = "4.0.0-dev", path = "../utils" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-core = { version = "5.0.0", path = "../../primitives/core" } -sp-keyring = { version = "4.1.0-dev", path = "../../primitives/keyring" } +sp-keyring = { version = "5.0.0", path = "../../primitives/keyring" } sp-keystore = { version = "0.11.0", path = "../../primitives/keystore" } sp-panic-handler = { version = "4.0.0", path = "../../primitives/panic-handler" } sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } diff --git a/client/consensus/aura/Cargo.toml b/client/consensus/aura/Cargo.toml index 4fb621d716a8..156842c35842 100644 --- a/client/consensus/aura/Cargo.toml +++ b/client/consensus/aura/Cargo.toml @@ -41,7 +41,7 @@ getrandom = { version = "0.2", features = ["js"], optional = true } [dev-dependencies] sp-timestamp = { version = "4.0.0-dev", path = "../../../primitives/timestamp" } -sp-keyring = { version = "4.1.0-dev", path = "../../../primitives/keyring" } +sp-keyring = { version = "5.0.0", path = "../../../primitives/keyring" } sp-tracing = { version = "4.0.0", path = "../../../primitives/tracing" } sc-keystore = { version = "4.0.0-dev", path = "../../keystore" } sc-network = { version = "0.10.0-dev", path = "../../network" } diff --git a/client/consensus/babe/rpc/Cargo.toml b/client/consensus/babe/rpc/Cargo.toml index 87ef265ffd9b..56276f07dcde 100644 --- a/client/consensus/babe/rpc/Cargo.toml +++ b/client/consensus/babe/rpc/Cargo.toml @@ -34,7 +34,7 @@ sp-keystore = { version = "0.11.0", path = "../../../../primitives/keystore" } [dev-dependencies] sc-consensus = { version = "0.10.0-dev", path = "../../../consensus/common" } serde_json = "1.0.74" -sp-keyring = { version = "4.1.0-dev", path = "../../../../primitives/keyring" } +sp-keyring = { version = "5.0.0", path = "../../../../primitives/keyring" } sc-keystore = { version = "4.0.0-dev", path = "../../../keystore" } substrate-test-runtime-client = { version = "2.0.0", path = "../../../../test-utils/runtime/client" } tempfile = "3.1.0" diff --git a/client/finality-grandpa/Cargo.toml b/client/finality-grandpa/Cargo.toml index e6b0b6396681..6d4c3b13662d 100644 --- a/client/finality-grandpa/Cargo.toml +++ b/client/finality-grandpa/Cargo.toml @@ -54,7 +54,7 @@ finality-grandpa = { version = "0.14.1", features = [ ] } sc-network = { version = "0.10.0-dev", path = "../network" } sc-network-test = { version = "0.8.0", path = "../network/test" } -sp-keyring = { version = "4.1.0-dev", path = "../../primitives/keyring" } +sp-keyring = { version = "5.0.0", path = "../../primitives/keyring" } substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } tokio = "1.15" diff --git a/client/finality-grandpa/rpc/Cargo.toml b/client/finality-grandpa/rpc/Cargo.toml index 2845621cadd6..b544287a6002 100644 --- a/client/finality-grandpa/rpc/Cargo.toml +++ b/client/finality-grandpa/rpc/Cargo.toml @@ -34,5 +34,5 @@ sc-rpc = { version = "4.0.0-dev", path = "../../rpc", features = [ ] } sp-core = { version = "5.0.0", path = "../../../primitives/core" } sp-finality-grandpa = { version = "4.0.0-dev", path = "../../../primitives/finality-grandpa" } -sp-keyring = { version = "4.1.0-dev", path = "../../../primitives/keyring" } +sp-keyring = { version = "5.0.0", path = "../../../primitives/keyring" } substrate-test-runtime-client = { version = "2.0.0", path = "../../../test-utils/runtime/client" } diff --git a/frame/grandpa/Cargo.toml b/frame/grandpa/Cargo.toml index 002ceed36929..eda9d630d4f9 100644 --- a/frame/grandpa/Cargo.toml +++ b/frame/grandpa/Cargo.toml @@ -33,7 +33,7 @@ log = { version = "0.4.14", default-features = false } [dev-dependencies] frame-benchmarking = { version = "4.0.0-dev", path = "../benchmarking" } grandpa = { package = "finality-grandpa", version = "0.14.1", features = ["derive-codec"] } -sp-keyring = { version = "4.1.0-dev", path = "../../primitives/keyring" } +sp-keyring = { version = "5.0.0", path = "../../primitives/keyring" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } pallet-offences = { version = "4.0.0-dev", path = "../offences" } pallet-staking = { version = "4.0.0-dev", path = "../staking" } diff --git a/frame/indices/Cargo.toml b/frame/indices/Cargo.toml index 487eb4716422..28a6427f520b 100644 --- a/frame/indices/Cargo.toml +++ b/frame/indices/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-keyring = { version = "4.1.0-dev", optional = true, path = "../../primitives/keyring" } +sp-keyring = { version = "5.0.0", optional = true, path = "../../primitives/keyring" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } diff --git a/primitives/keyring/Cargo.toml b/primitives/keyring/Cargo.toml index 2f8e935b2457..5cf8a574505a 100644 --- a/primitives/keyring/Cargo.toml +++ b/primitives/keyring/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-keyring" -version = "4.1.0-dev" +version = "5.0.0" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" diff --git a/test-utils/client/Cargo.toml b/test-utils/client/Cargo.toml index 5f687b24896d..640623aba6aa 100644 --- a/test-utils/client/Cargo.toml +++ b/test-utils/client/Cargo.toml @@ -31,7 +31,7 @@ sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } sp-core = { version = "5.0.0", path = "../../primitives/core" } sp-keystore = { version = "0.11.0", path = "../../primitives/keystore" } -sp-keyring = { version = "4.1.0-dev", path = "../../primitives/keyring" } +sp-keyring = { version = "5.0.0", path = "../../primitives/keyring" } sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } sp-state-machine = { version = "0.11.0", path = "../../primitives/state-machine" } async-trait = "0.1.50" diff --git a/test-utils/runtime/Cargo.toml b/test-utils/runtime/Cargo.toml index f1b06d3b3ec2..2a9fcaf32426 100644 --- a/test-utils/runtime/Cargo.toml +++ b/test-utils/runtime/Cargo.toml @@ -20,7 +20,7 @@ sp-block-builder = { version = "4.0.0-dev", default-features = false, path = ".. codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../primitives/inherents" } -sp-keyring = { version = "4.1.0-dev", optional = true, path = "../../primitives/keyring" } +sp-keyring = { version = "5.0.0", optional = true, path = "../../primitives/keyring" } memory-db = { version = "0.27.0", default-features = false } sp-offchain = { version = "4.0.0-dev", default-features = false, path = "../../primitives/offchain" } sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } From 4c7c0191c82f18ae2795b00e1c1972aa8c363417 Mon Sep 17 00:00:00 2001 From: driemworks Date: Thu, 3 Feb 2022 15:47:50 -0500 Subject: [PATCH 451/695] session based reward points --- .../pallets/iris-assets/src/lib.rs | 6 +- .../pallets/iris-session/src/lib.rs | 147 ++++++++++++++++-- bin/node-template/runtime/src/lib.rs | 1 - 3 files changed, 140 insertions(+), 14 deletions(-) diff --git a/bin/node-template/pallets/iris-assets/src/lib.rs b/bin/node-template/pallets/iris-assets/src/lib.rs index 1885350bd933..26ea1e847373 100644 --- a/bin/node-template/pallets/iris-assets/src/lib.rs +++ b/bin/node-template/pallets/iris-assets/src/lib.rs @@ -274,8 +274,12 @@ pub mod pallet { Self::deposit_event(Event::AssetCreated(asset_id.clone())); Ok(()) } - + /// request to fetch bytes from ipfs and add to offchain storage + /// + /// * `owner`: The owner of the content to be fetched + /// * `asset_id`: The asset id identifying the content + /// #[pallet::weight(0)] pub fn request_bytes( origin: OriginFor, diff --git a/bin/node-template/pallets/iris-session/src/lib.rs b/bin/node-template/pallets/iris-session/src/lib.rs index a40cfb2d8812..d3586696283b 100644 --- a/bin/node-template/pallets/iris-session/src/lib.rs +++ b/bin/node-template/pallets/iris-session/src/lib.rs @@ -1,5 +1,18 @@ //! # Iris Session Pallet //! +//! @author driemworks +//! +//! ## Description +//! +//! validators and storage providers +//! are treated as seprate roles, where you must first be a validator after which you can +//! request to join a storage pool for some asset id (become a storage provider). If the ipfs +//! node has sufficient storage capacity to successfully pin the underlying CID of the asset class, +//! then that node is considered a storage provider as long as it is online. +//! +//! Temporaraily, this pallet is in a weird limbo between proof of authority and proof of stake +//! without actually verifying any quantitative measure of storage capacity +//! //! The Iris Session Pallet allows addition and removal of //! storage providers via extrinsics (transaction calls), in //! Substrate-based PoA networks. It also integrates with the im-online pallet @@ -10,6 +23,8 @@ //! session pallet to automatically rotate sessions. For this reason, the //! validator addition and removal becomes effective only after 2 sessions //! (queuing + applying). +//! +//! #![cfg_attr(not(feature = "std"), no_std)] @@ -20,15 +35,17 @@ use frame_support::{ ensure, pallet_prelude::*, traits::{ - EstimateNextSessionRotation, Get, ValidatorSet, ValidatorSetWithIdentification, + EstimateNextSessionRotation, Get, + ValidatorSet, ValidatorSetWithIdentification, }, }; use log; +use scale_info::TypeInfo; pub use pallet::*; use sp_runtime::traits::{Convert, Zero}; use sp_staking::offence::{Offence, OffenceError, ReportOffence}; use sp_std::{ - collections::btree_set::BTreeSet, + collections::{ btree_set::BTreeSet, btree_map::BTreeMap }, convert::TryInto, str, vec::Vec, @@ -59,7 +76,7 @@ use pallet_iris_assets::{ }; pub const LOG_TARGET: &'static str = "runtime::iris-session"; -// pub const KEY_TYPE: KeyTypeId = KeyTypeId(*b"iris"); +// TODO: should a new KeyTypeId be defined? e.g. b"iris" pub const KEY_TYPE: KeyTypeId = KeyTypeId(*b"aura"); pub mod crypto { @@ -88,6 +105,35 @@ pub mod crypto { } } +/// Counter for the number of eras that have passed. +pub type EraIndex = u32; +/// counter for the number of "reward" points earned by a given storage provider +pub type RewardPoint = u32; + +/// Reward points for storage providers of some specific assest id during an era. +#[derive(PartialEq, Encode, Decode, Default, RuntimeDebug, TypeInfo)] +pub struct EraRewardPoints { + /// the total number of points + total: RewardPoint, + /// the reward points for individual validators (sum(i.rewardPoint in individual) = total) + individual: BTreeMap, + /// the unallocated reward points are distributed evenly among storage providers + /// at the end of a session. These reward points are added when a consumer node + /// requests data from IPFS + unallocated: RewardPoint, +} + +/// Information regarding the active era (era in used in session). +#[derive(Encode, Decode, RuntimeDebug, TypeInfo)] +pub struct ActiveEraInfo { + /// Index of era. + pub index: EraIndex, + /// Moment of start expressed as millisecond from `$UNIX_EPOCH`. + /// + /// Start can be none if start hasn't been set for the era yet, + /// Start is set on the first on_finalize of the era to guarantee usage of `Time`. + start: Option, +} #[frame_support::pallet] pub mod pallet { @@ -150,6 +196,7 @@ pub mod pallet { /// Maps an asset id to a collection of nodes that want to provider storage #[pallet::storage] #[pallet::getter(fn candidate_storage_providers)] + // TODO: Change to QueuedStorageProviders pub(super) type CandidateStorageProviders = StorageMap< _, Blake2_128Concat, @@ -180,6 +227,37 @@ pub mod pallet { ValueQuery, >; + /// The current era index. + /// + /// This is the latest planned era, depending on how the Session pallet queues the validator + /// set, it might be active or not. + #[pallet::storage] + #[pallet::getter(fn current_era)] + pub type CurrentEra = StorageValue<_, EraIndex>; + + /// The active era information, it holds index and start. + /// + /// The active era is the era being currently rewarded. Validator set of this era must be + /// equal to [`SessionInterface::validators`]. + #[pallet::storage] + #[pallet::getter(fn active_era)] + // TODO: Do I need the ActiveEraInfo? + pub type ActiveEra = StorageValue<_, EraIndex>; + + /// Rewards for the last `HISTORY_DEPTH` eras. + /// If reward hasn't been set or has been removed then 0 reward is returned. + #[pallet::storage] + #[pallet::getter(fn eras_reward_points)] + pub type ErasRewardPoints = StorageDoubleMap< + _, + Blake2_128Concat, + EraIndex, + Blake2_128Concat, + T::AssetId, + EraRewardPoints, + ValueQuery, + >; + #[pallet::storage] #[pallet::getter(fn validators)] pub type Validators = StorageValue<_, Vec, ValueQuery>; @@ -230,6 +308,8 @@ pub mod pallet { AlreadyACandidate, /// the node has already pinned the CID AlreadyPinned, + /// the node is not a candidate storage provider for some asset id + NotACandidate, } #[pallet::hooks] @@ -287,10 +367,8 @@ pub mod pallet { #[pallet::weight(0)] pub fn add_validator(origin: OriginFor, validator_id: T::AccountId) -> DispatchResult { T::AddRemoveOrigin::ensure_origin(origin)?; - Self::do_add_validator(validator_id.clone())?; Self::approve_validator(validator_id)?; - Ok(()) } @@ -304,10 +382,8 @@ pub mod pallet { validator_id: T::AccountId, ) -> DispatchResult { T::AddRemoveOrigin::ensure_origin(origin)?; - Self::do_remove_validator(validator_id.clone())?; Self::unapprove_validator(validator_id)?; - Ok(()) } @@ -351,7 +427,10 @@ pub mod pallet { Ok(()) } - /// should only be called by offchain workers... how to ensure this? + /// TODO: I really need to address the fact that this is callable by anyone + /// Someone could randomly make an asset class on your behalf, making you the admin + /// + /// should only be called by offchain workers... how to ensure this? /// submits IPFS results on chain and creates new ticket config in runtime storage /// /// * `admin`: The admin account @@ -368,6 +447,7 @@ pub mod pallet { balance: T::Balance, ) -> DispatchResult { let who = ensure_signed(origin)?; + // TODO: Need some type of verification to prove the caller pinned the content let new_origin = system::RawOrigin::Signed(who.clone()).into(); // creates the asset class >::submit_ipfs_add_results( @@ -377,6 +457,15 @@ pub mod pallet { id, balance, )?; + // award point to self + if let Some(active_era) = ActiveEra::::get() { + >::mutate(active_era, id, |era_rewards| { + *era_rewards.individual.entry(who.clone()).or_default() += 1; + era_rewards.total += 1; + }); + } else { + // error + } Ok(()) } @@ -406,12 +495,23 @@ pub mod pallet { asset_id: T::AssetId, ) -> DispatchResult { let who = ensure_signed(origin)?; + // verify they are a candidate storage provider + let candidate_storage_providers = >::get(asset_id.clone()); + ensure!(candidate_storage_providers.contains(&who), Error::::NotACandidate); + // verify not already pinning the content let current_pinners = >::get(asset_id.clone()); ensure!(!current_pinners.contains(&who), Error::::AlreadyPinned); // TODO: we need a better scheme for *generating* pool ids -> should always be unique (cid + owner maybe?) >::mutate(asset_id.clone(), |p| { p.push(who.clone()); }); + // award point to self + if let Some(active_era) = ActiveEra::::get() { + >::mutate(active_era, asset_id, |era_rewards| { + *era_rewards.individual.entry(who.clone()).or_default() += 1; + era_rewards.total += 1; + }); + } Ok(()) } @@ -424,10 +524,17 @@ pub mod pallet { #[pallet::weight(0)] pub fn submit_rpc_ready( origin: OriginFor, - beneficiary: T::AccountId, - // host: Vec, + asset_id: T::AssetId, ) -> DispatchResult { ensure_signed(origin)?; + if let Some(active_era) = ActiveEra::::get() { + >::mutate(active_era, asset_id, |era_rewards| { + era_rewards.total += 1; + era_rewards.unallocated += 1; + }); + } else { + // error -> no active era found + } // Self::deposit_event(Event::DataReady(beneficiary)); Ok(()) } @@ -533,6 +640,16 @@ impl Pallet { } } + // distribute unallocated reward points to storage providers + fn distribute_unallocated_reward_points() { + // get unallocated rps in active era and disburse to storage providers + if let Some(active_era) = ActiveEra::::get() { + // fetch reward points for the era + + + } + } + /// implementation for RPC runtime API to retrieve bytes from the node's local storage /// /// * public_key: The account's public key as bytes @@ -731,7 +848,8 @@ impl Pallet { } let results = signer.send_signed_transaction(|_account| { Call::submit_rpc_ready { - beneficiary: requestor.clone(), + // beneficiary: requestor.clone(), + asset_id: asset_id.clone(), } }); @@ -819,20 +937,25 @@ impl pallet_session::SessionManager for Pallet { // Plan a new session and provide new validator set. fn new_session(new_index: u32) -> Option> { log::info!("Starting new session with index: {:?}", new_index); + // TODO: how staking pallet uses this, 'trigger_new_era' + CurrentEra::::mutate(|s| *s = Some(new_index)); // Remove any offline validators. This will only work when the runtime // also has the im-online pallet. Self::remove_offline_validators(); + // TODO: REMOVE OFFLINE STORAGE PROVIDERS Self::select_candidate_storage_providers(); log::debug!(target: LOG_TARGET, "New session called; updated validator set provided."); Some(Self::validators()) } fn end_session(end_index: u32) { - log::info!("Ending session with index: {:?}", end_index) + log::info!("Ending session with index: {:?}", end_index); + Self::distribute_unallocated_reward_points(); } fn start_session(start_index: u32) { log::info!("Starting session with index: {:?}", start_index); + ActiveEra::::mutate(|s| *s = Some(start_index)); } } diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index 774f462df87a..90a53c811345 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -223,7 +223,6 @@ parameter_types! { impl pallet_iris_session::Config for Runtime { type Event = Event; type Call = Call; - // type IrisAssetsCall = IrisAssetsCall; type AddRemoveOrigin = EnsureRoot; type MinAuthorities = MinAuthorities; type AuthorityId = pallet_iris_session::crypto::TestAuthId; From 70d9ea0f8192911c2ee555103a15ae605ae220ec Mon Sep 17 00:00:00 2001 From: driemworks Date: Thu, 3 Feb 2022 19:39:42 -0500 Subject: [PATCH 452/695] update tests WIP, add im_online pallet --- Cargo.lock | 5 +- bin/node-template/node/Cargo.toml | 1 + bin/node-template/node/src/chain_spec.rs | 18 +++--- bin/node-template/node/src/service.rs | 6 -- .../pallets/iris-assets/src/tests.rs | 4 +- .../pallets/iris-session/Cargo.toml | 5 +- .../pallets/iris-session/src/lib.rs | 2 +- .../pallets/iris-session/src/mock.rs | 6 +- .../pallets/iris-session/src/tests.rs | 60 +++++++++---------- bin/node-template/runtime/Cargo.toml | 8 ++- bin/node-template/runtime/src/lib.rs | 31 +++++++++- 11 files changed, 87 insertions(+), 59 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 21d7e7b6bf83..c1ce16cde26c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4993,6 +4993,7 @@ dependencies = [ "frame-benchmarking-cli", "jsonrpc-core", "node-template-runtime", + "pallet-im-online", "pallet-iris-rpc", "pallet-transaction-payment-rpc", "sc-basic-authorship", @@ -5040,9 +5041,11 @@ dependencies = [ "pallet-aura", "pallet-balances", "pallet-grandpa", + "pallet-im-online", "pallet-iris-assets", "pallet-iris-rpc-runtime-api", "pallet-iris-session", + "pallet-offences", "pallet-randomness-collective-flip", "pallet-session", "pallet-sudo", @@ -5906,11 +5909,11 @@ dependencies = [ "log 0.4.14", "pallet-assets", "pallet-balances", + "pallet-im-online", "pallet-iris-assets", "pallet-session", "parity-scale-codec", "scale-info", - "sp-authority-discovery", "sp-core", "sp-io", "sp-keystore", diff --git a/bin/node-template/node/Cargo.toml b/bin/node-template/node/Cargo.toml index d6b819b50df1..4cf7fef0e47d 100644 --- a/bin/node-template/node/Cargo.toml +++ b/bin/node-template/node/Cargo.toml @@ -37,6 +37,7 @@ sc-client-api = { version = "4.0.0-dev", path = "../../../client/api" } sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" } sp-timestamp = { version = "4.0.0-dev", path = "../../../primitives/timestamp" } sp-keystore = { version = "0.10.0-dev", path = "../../../primitives/keystore" } +pallet-im-online = { version = "4.0.0-dev", default-features = false, path = "../../../frame/im-online" } # These dependencies are used for the node template's RPCs jsonrpc-core = "18.0.0" diff --git a/bin/node-template/node/src/chain_spec.rs b/bin/node-template/node/src/chain_spec.rs index 69d4b42609fa..8140e6e48a61 100644 --- a/bin/node-template/node/src/chain_spec.rs +++ b/bin/node-template/node/src/chain_spec.rs @@ -1,7 +1,7 @@ use node_template_runtime::{ AccountId, AuraConfig, BalancesConfig, GenesisConfig, GrandpaConfig, Signature, - SudoConfig, SessionConfig, IrisSessionConfig, + SudoConfig, SessionConfig, IrisSessionConfig, ImOnlineConfig, SystemConfig, WASM_BINARY, opaque::SessionKeys, }; @@ -11,6 +11,8 @@ use sp_core::{sr25519, Pair, Public}; use sp_finality_grandpa::AuthorityId as GrandpaId; use sp_runtime::traits::{IdentifyAccount, Verify}; +use pallet_im_online::sr25519::AuthorityId as ImOnlineId; + // The URL for the telemetry server. // const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/"; @@ -18,8 +20,8 @@ use sp_runtime::traits::{IdentifyAccount, Verify}; pub type ChainSpec = sc_service::GenericChainSpec; -fn session_keys(aura: AuraId, grandpa: GrandpaId) -> SessionKeys { - SessionKeys { aura, grandpa } +fn session_keys(aura: AuraId, grandpa: GrandpaId, im_online: ImOnlineId) -> SessionKeys { + SessionKeys { aura, grandpa, im_online } } /// Generate a crypto pair from seed. @@ -40,11 +42,12 @@ where } /// Generate an Aura authority key. -pub fn authority_keys_from_seed(s: &str) -> (AccountId, AuraId, GrandpaId) { +pub fn authority_keys_from_seed(s: &str) -> (AccountId, AuraId, GrandpaId, ImOnlineId) { ( get_account_id_from_seed::(s), get_from_seed::(s), - get_from_seed::(s) + get_from_seed::(s), + get_from_seed::(s) ) } @@ -137,7 +140,7 @@ pub fn local_testnet_config() -> Result { /// Configure initial storage state for FRAME modules. fn testnet_genesis( wasm_binary: &[u8], - initial_authorities: Vec<(AccountId, AuraId, GrandpaId)>, + initial_authorities: Vec<(AccountId, AuraId, GrandpaId, ImOnlineId)>, root_key: AccountId, endowed_accounts: Vec, _enable_println: bool, @@ -157,7 +160,7 @@ fn testnet_genesis( }, session: SessionConfig { keys: initial_authorities.iter().map(|x| { - (x.0.clone(), x.0.clone(), session_keys(x.1.clone(), x.2.clone())) + (x.0.clone(), x.0.clone(), session_keys(x.1.clone(), x.2.clone(), x.3.clone())) }).collect::>(), }, aura: AuraConfig { @@ -166,6 +169,7 @@ fn testnet_genesis( grandpa: GrandpaConfig { authorities: vec![], }, + im_online: ImOnlineConfig { keys: vec![] }, sudo: SudoConfig { // Assign network admin rights. key: root_key, diff --git a/bin/node-template/node/src/service.rs b/bin/node-template/node/src/service.rs index 6c0a12bf4b85..31b228040441 100644 --- a/bin/node-template/node/src/service.rs +++ b/bin/node-template/node/src/service.rs @@ -11,7 +11,6 @@ use sc_telemetry::{Telemetry, TelemetryWorker}; use sp_consensus::SlotData; use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; use std::{sync::Arc, time::Duration}; -use sp_core::crypto::KeyTypeId; // Our native executor instance. pub struct ExecutorDispatch; @@ -195,11 +194,6 @@ pub fn new_full(mut config: Configuration) -> Result })?; let keystore = keystore_container.sync_keystore(); if config.offchain_worker.enabled { - // sp_keystore::SyncCryptoStore::sr25519_generate_new( - // &*keystore, - // KeyTypeId(*b"iris"), - // Some("//Alice"), - // ).expect("Creating key with account Alice should succeed."); sc_service::build_offchain_workers( &config, task_manager.spawn_handle(), diff --git a/bin/node-template/pallets/iris-assets/src/tests.rs b/bin/node-template/pallets/iris-assets/src/tests.rs index 062fcd7609e8..ddd9228bd466 100644 --- a/bin/node-template/pallets/iris-assets/src/tests.rs +++ b/bin/node-template/pallets/iris-assets/src/tests.rs @@ -43,7 +43,7 @@ fn iris_assets_ipfs_add_bytes_works_for_valid_value() { new_test_ext_funded(p.clone()).execute_with(|| { // WHEN: I invoke the create_storage_assets extrinsic - assert_ok!(Iris::create_storage_asset( + assert_ok!(Iris::create( Origin::signed(p.clone().public()), p.clone().public(), multiaddr_vec.clone(), @@ -133,7 +133,7 @@ fn iris_assets_mint_tickets_works_for_valid_values() { balance.clone(), )); // WHEN: I invoke the mint_tickets extrinsic - assert_ok!(Iris::mint_tickets( + assert_ok!(Iris::mint( Origin::signed(p.clone().public()), p.clone().public(), id.clone(), diff --git a/bin/node-template/pallets/iris-session/Cargo.toml b/bin/node-template/pallets/iris-session/Cargo.toml index d25769c10216..12bcecd73f8a 100644 --- a/bin/node-template/pallets/iris-session/Cargo.toml +++ b/bin/node-template/pallets/iris-session/Cargo.toml @@ -25,14 +25,13 @@ sp-core = { default-features = false, version = "4.0.0-dev", path = "../../../.. sp-runtime = { default-features = false, version = "4.0.0-dev", path = "../../../../primitives/runtime" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/staking" } sp-keystore = { version = "0.10.0-dev", path = "../../../../primitives/keystore", optional = true } -sp-authority-discovery = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/authority-discovery" } frame-support = { default-features = false, version = "4.0.0-dev", path = "../../../../frame/support" } frame-system = { default-features = false, version = "4.0.0-dev", path = "../../../../frame/system" } frame-benchmarking = { default-features = false, version = "4.0.0-dev", path = "../../../../frame/benchmarking", optional = true } log = { version = "0.4.14", default-features = false } - +pallet-im-online = { version = "4.0.0-dev", default-features = false, path = "../../../../frame/im-online" } pallet-session = { version = "4.0.0-dev", default-features = false, features = ["historical"], path = "../../../../frame/session" } pallet-iris-assets = { version = "1.0.0", default-features = false, path = "../iris-assets" } @@ -54,8 +53,8 @@ std = [ 'sp-runtime/std', # todo: can remove this dependency 'sp-staking/std', - 'sp-authority-discovery/std', 'log/std', + 'pallet-im-online/std', 'pallet-session/std', 'pallet-iris-assets/std', ] diff --git a/bin/node-template/pallets/iris-session/src/lib.rs b/bin/node-template/pallets/iris-session/src/lib.rs index d3586696283b..4f8a750260f3 100644 --- a/bin/node-template/pallets/iris-session/src/lib.rs +++ b/bin/node-template/pallets/iris-session/src/lib.rs @@ -950,7 +950,7 @@ impl pallet_session::SessionManager for Pallet { fn end_session(end_index: u32) { log::info!("Ending session with index: {:?}", end_index); - Self::distribute_unallocated_reward_points(); + // Self::distribute_unallocated_reward_points(); } fn start_session(start_index: u32) { diff --git a/bin/node-template/pallets/iris-session/src/mock.rs b/bin/node-template/pallets/iris-session/src/mock.rs index a860890d8a30..8f91f33a619e 100644 --- a/bin/node-template/pallets/iris-session/src/mock.rs +++ b/bin/node-template/pallets/iris-session/src/mock.rs @@ -21,8 +21,6 @@ use sp_core::{ H256, }; use sp_keystore::{testing::KeyStore, KeystoreExt, SyncCryptoStore}; -// use sp_authority_discovery::AuthorityId; - use std::cell::RefCell; use std::sync::Arc; @@ -154,8 +152,8 @@ impl frame_system::Config for Test { type Call = Call; type Hash = H256; type Hashing = BlakeTwo256; - // type AccountId = sp_core::sr25519::Public; - type AccountId = u64; + type AccountId = sp_core::sr25519::Public; + // type AccountId = u64; type Lookup = IdentityLookup; type Header = Header; type Event = Event; diff --git a/bin/node-template/pallets/iris-session/src/tests.rs b/bin/node-template/pallets/iris-session/src/tests.rs index 9e9581e24a9a..3fa747463d80 100644 --- a/bin/node-template/pallets/iris-session/src/tests.rs +++ b/bin/node-template/pallets/iris-session/src/tests.rs @@ -30,39 +30,39 @@ fn iris_session_add_validator_updates_validators_list() { }); } -#[test] -fn iris_session_remove_validator_updates_validators_list() { - new_test_ext().execute_with(|| { - assert_ok!(ValidatorSet::remove_validator(Origin::root(), 2)); - assert_eq!(ValidatorSet::validators(), vec![1u64, 3u64]); - }); -} +// #[test] +// fn iris_session_remove_validator_updates_validators_list() { +// new_test_ext().execute_with(|| { +// assert_ok!(ValidatorSet::remove_validator(Origin::root(), 2)); +// assert_eq!(ValidatorSet::validators(), vec![1u64, 3u64]); +// }); +// } -#[test] -fn iris_session_add_validator_fails_with_invalid_origin() { - new_test_ext().execute_with(|| { - assert_noop!(ValidatorSet::add_validator(Origin::signed(1), 4), DispatchError::BadOrigin); - }); -} +// #[test] +// fn iris_session_add_validator_fails_with_invalid_origin() { +// new_test_ext().execute_with(|| { +// assert_noop!(ValidatorSet::add_validator(Origin::signed(1), 4), DispatchError::BadOrigin); +// }); +// } -#[test] -fn iris_session_remove_validator_fails_with_invalid_origin() { - new_test_ext().execute_with(|| { - assert_noop!( - ValidatorSet::remove_validator(Origin::signed(1), 4), - DispatchError::BadOrigin - ); - }); -} +// #[test] +// fn iris_session_remove_validator_fails_with_invalid_origin() { +// new_test_ext().execute_with(|| { +// assert_noop!( +// ValidatorSet::remove_validator(Origin::signed(1), 4), +// DispatchError::BadOrigin +// ); +// }); +// } -#[test] -fn iris_session_duplicate_check() { - new_test_ext().execute_with(|| { - assert_ok!(ValidatorSet::add_validator(Origin::root(), 4)); - assert_eq!(ValidatorSet::validators(), vec![1u64, 2u64, 3u64, 4u64]); - assert_noop!(ValidatorSet::add_validator(Origin::root(), 4), Error::::Duplicate); - }); -} +// #[test] +// fn iris_session_duplicate_check() { +// new_test_ext().execute_with(|| { +// assert_ok!(ValidatorSet::add_validator(Origin::root(), 4)); +// assert_eq!(ValidatorSet::validators(), vec![1u64, 2u64, 3u64, 4u64]); +// assert_noop!(ValidatorSet::add_validator(Origin::root(), 4), Error::::Duplicate); +// }); +// } // RPC tests diff --git a/bin/node-template/runtime/Cargo.toml b/bin/node-template/runtime/Cargo.toml index cf08c924978c..76f7e95bc6b6 100644 --- a/bin/node-template/runtime/Cargo.toml +++ b/bin/node-template/runtime/Cargo.toml @@ -19,17 +19,18 @@ pallet-aura = { version = "4.0.0-dev", default-features = false, path = "../../. pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../../../frame/balances" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../../../frame/support" } pallet-grandpa = { version = "4.0.0-dev", default-features = false, path = "../../../frame/grandpa" } +# TODO: REMOVE THIS pallet-randomness-collective-flip = { version = "4.0.0-dev", default-features = false, path = "../../../frame/randomness-collective-flip" } pallet-sudo = { version = "4.0.0-dev", default-features = false, path = "../../../frame/sudo" } +pallet-im-online = { version = "4.0.0-dev", default-features = false, path = "../../../frame/im-online" } pallet-assets = { version = "4.0.0-dev", default-features = false, path = "../../../frame/assets" } pallet-session = { version = "4.0.0-dev", default-features = false, features = ["historical"], path = "../../../frame/session" } pallet-iris-assets = { version = "1.0.0", default-features = false, path = "../pallets/iris-assets" } pallet-iris-session = { version = "1.0.0", default-features = false, path = "../pallets/iris-session" } - - -frame-system = { version = "4.0.0-dev", default-features = false, path = "../../../frame/system" } pallet-timestamp = { version = "4.0.0-dev", default-features = false, path = "../../../frame/timestamp" } pallet-transaction-payment = { version = "4.0.0-dev", default-features = false, path = "../../../frame/transaction-payment" } + +frame-system = { version = "4.0.0-dev", default-features = false, path = "../../../frame/system" } frame-executive = { version = "4.0.0-dev", default-features = false, path = "../../../frame/executive" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/api" } sp-block-builder = { path = "../../../primitives/block-builder", default-features = false, version = "4.0.0-dev"} @@ -71,6 +72,7 @@ std = [ "pallet-grandpa/std", "pallet-randomness-collective-flip/std", "pallet-sudo/std", + "pallet-im-online/std", "pallet-iris-assets/std", "pallet-timestamp/std", "pallet-transaction-payment-rpc-runtime-api/std", diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index 90a53c811345..f9c6ee0b50ab 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -25,7 +25,7 @@ use sp_runtime::{ OpaqueKeys, ConvertInto, }, - transaction_validity::{TransactionSource, TransactionValidity}, + transaction_validity::{TransactionSource, TransactionValidity, TransactionPriority}, ApplyExtrinsicResult, MultiSignature, }; use sp_std::prelude::*; @@ -34,6 +34,7 @@ use sp_version::NativeVersion; use sp_version::RuntimeVersion; use frame_system::EnsureRoot; use pallet_session::historical as pallet_session_historical; +use pallet_im_online::sr25519::AuthorityId as ImOnlineId; // A few exports that help ease life for downstream crates. pub use frame_support::{ @@ -102,6 +103,7 @@ pub mod opaque { pub struct SessionKeys { pub aura: Aura, pub grandpa: Grandpa, + pub im_online: ImOnline, } } } @@ -241,11 +243,31 @@ impl pallet_session::Config for Runtime { type SessionManager = IrisSession; type SessionHandler = ::KeyTypeIdProviders; type Keys = opaque::SessionKeys; - type WeightInfo = (); + type WeightInfo = pallet_session::weights::SubstrateWeight; type DisabledValidatorsThreshold = (); type Event = Event; } +parameter_types! { + pub const ImOnlineUnsignedPriority: TransactionPriority = TransactionPriority::max_value(); + pub const MaxKeys: u32 = 10_000; + pub const MaxPeerInHeartbeats: u32 = 10_000; + pub const MaxPeerDataEncodingSize: u32 = 1_000; +} + +impl pallet_im_online::Config for Runtime { + type AuthorityId = ImOnlineId; + type Event = Event; + type NextSessionRotation = pallet_session::PeriodicSessions; + type ValidatorSet = IrisSession; + type ReportUnresponsiveness = IrisSession; + type UnsignedPriority = ImOnlineUnsignedPriority; + type WeightInfo = pallet_im_online::weights::SubstrateWeight; + type MaxKeys = MaxKeys; + type MaxPeerInHeartbeats = MaxPeerInHeartbeats; + type MaxPeerDataEncodingSize = MaxPeerDataEncodingSize; +} + parameter_types! { pub const MaxAuthorities: u32 = 32; } @@ -307,6 +329,8 @@ impl pallet_balances::Config for Runtime { type WeightInfo = pallet_balances::weights::SubstrateWeight; } + + parameter_types! { pub const TransactionByteFee: Balance = 1; } @@ -429,6 +453,9 @@ construct_runtime!( IrisSession: pallet_iris_session::{Pallet, Call, Storage, Event, Config}, Session: pallet_session::{Pallet, Call, Storage, Event, Config}, Assets: pallet_assets::{Pallet, Storage, Event}, + ImOnline: pallet_im_online::{Pallet, Call, Storage, Event, ValidateUnsigned, Config}, + // Offences: pallet_offences::{Pallet, Storage, Event}, + // Historical: pallet_session_historical::{Pallet}, Aura: pallet_aura::{Pallet, Config}, Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event}, } From 4f672d4efc70d001cc2ee619a5a93fe643c8aa98 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Fri, 4 Feb 2022 13:03:28 +0100 Subject: [PATCH 453/695] Make `offences` benchmark runnable (#10782) * Make offences benchmark runnable Signed-off-by: Oliver Tale-Yazdi * cargo run --quiet --profile=production --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_offences --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/offences/src/weights.rs --template=./.maintain/frame-weight-template.hbs * Revert bench-bot This reverts commit 73d0cb2e47e93e035af80013991b6a2e5fe2b1ed. Co-authored-by: Parity Bot --- frame/offences/benchmarking/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frame/offences/benchmarking/src/lib.rs b/frame/offences/benchmarking/src/lib.rs index c2e29f0d0fdd..8688090206c3 100644 --- a/frame/offences/benchmarking/src/lib.rs +++ b/frame/offences/benchmarking/src/lib.rs @@ -405,6 +405,7 @@ benchmarks! { } verify { // make sure that all slashes have been applied + #[cfg(test)] assert_eq!( System::::event_count(), 0 + 1 // offence @@ -440,6 +441,7 @@ benchmarks! { } verify { // make sure that all slashes have been applied + #[cfg(test)] assert_eq!( System::::event_count(), 0 + 1 // offence From 929cf109ba692d69f60439147d1e8af14942c64b Mon Sep 17 00:00:00 2001 From: Keith Yeung Date: Fri, 4 Feb 2022 07:42:13 -0800 Subject: [PATCH 454/695] Make some UI test expectations crisper (#10791) * Make some UI test expectations crisper * Update frame/support/test/tests/construct_runtime_ui/undefined_genesis_config_part.rs * Update UI test expectations * Missing newlines * More whitespace issues --- .../no_std_genesis_config.rs | 31 +++- .../no_std_genesis_config.stderr | 104 +++++-------- .../undefined_call_part.rs | 31 +++- .../undefined_call_part.stderr | 74 +-------- .../undefined_event_part.rs | 31 +++- .../undefined_event_part.stderr | 102 +++---------- .../undefined_genesis_config_part.rs | 31 +++- .../undefined_genesis_config_part.stderr | 106 +++++-------- .../undefined_inherent_part.rs | 31 +++- .../undefined_inherent_part.stderr | 140 +++++++++++------- .../undefined_origin_part.rs | 31 +++- .../undefined_origin_part.stderr | 106 ++++--------- .../undefined_validate_unsigned_part.rs | 31 +++- .../undefined_validate_unsigned_part.stderr | 105 ++++++------- 14 files changed, 465 insertions(+), 489 deletions(-) diff --git a/frame/support/test/tests/construct_runtime_ui/no_std_genesis_config.rs b/frame/support/test/tests/construct_runtime_ui/no_std_genesis_config.rs index 89774eb8a770..c06333795e3c 100644 --- a/frame/support/test/tests/construct_runtime_ui/no_std_genesis_config.rs +++ b/frame/support/test/tests/construct_runtime_ui/no_std_genesis_config.rs @@ -3,20 +3,47 @@ use sp_runtime::{generic, traits::BlakeTwo256}; use sp_core::sr25519; pub type Signature = sr25519::Signature; -pub type BlockNumber = u64; +pub type BlockNumber = u32; pub type Header = generic::Header; pub type Block = generic::Block; pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; impl test_pallet::Config for Runtime {} +impl frame_system::Config for Runtime { + type BaseCallFilter = frame_support::traits::Everything; + type Origin = Origin; + type Index = u64; + type BlockNumber = u32; + type Call = Call; + type Hash = sp_runtime::testing::H256; + type Hashing = sp_runtime::traits::BlakeTwo256; + type AccountId = u64; + type Lookup = sp_runtime::traits::IdentityLookup; + type Header = Header; + type Event = Event; + type BlockHashCount = frame_support::traits::ConstU32<250>; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + construct_runtime! { pub enum Runtime where Block = Block, NodeBlock = Block, UncheckedExtrinsic = UncheckedExtrinsic { - System: system::{Pallet, Call, Storage, Config, Event}, + System: frame_system::{Pallet, Call, Storage, Config, Event}, Pallet: test_pallet::{Pallet, Config}, } } diff --git a/frame/support/test/tests/construct_runtime_ui/no_std_genesis_config.stderr b/frame/support/test/tests/construct_runtime_ui/no_std_genesis_config.stderr index e458265a07ca..6d5a48bf0909 100644 --- a/frame/support/test/tests/construct_runtime_ui/no_std_genesis_config.stderr +++ b/frame/support/test/tests/construct_runtime_ui/no_std_genesis_config.stderr @@ -1,73 +1,27 @@ error: `Pallet` does not have the std feature enabled, this will cause the `test_pallet::GenesisConfig` type to be undefined. - --> $DIR/no_std_genesis_config.rs:13:1 + --> tests/construct_runtime_ui/no_std_genesis_config.rs:40:1 | -13 | / construct_runtime! { -14 | | pub enum Runtime where -15 | | Block = Block, -16 | | NodeBlock = Block, +40 | / construct_runtime! { +41 | | pub enum Runtime where +42 | | Block = Block, +43 | | NodeBlock = Block, ... | -21 | | } -22 | | } +48 | | } +49 | | } | |_^ | = note: this error originates in the macro `test_pallet::__substrate_genesis_config_check::is_std_enabled_for_genesis` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0433]: failed to resolve: use of undeclared crate or module `system` - --> $DIR/no_std_genesis_config.rs:19:11 - | -19 | System: system::{Pallet, Call, Storage, Config, Event}, - | ^^^^^^ use of undeclared crate or module `system` - -error[E0433]: failed to resolve: use of undeclared crate or module `system` - --> $DIR/no_std_genesis_config.rs:13:1 - | -13 | / construct_runtime! { -14 | | pub enum Runtime where -15 | | Block = Block, -16 | | NodeBlock = Block, -... | -21 | | } -22 | | } - | |_^ not found in `system` - | - = note: this error originates in the macro `construct_runtime` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider importing this enum - | -1 | use frame_system::RawOrigin; - | - -error[E0433]: failed to resolve: use of undeclared crate or module `system` - --> $DIR/no_std_genesis_config.rs:13:1 - | -13 | / construct_runtime! { -14 | | pub enum Runtime where -15 | | Block = Block, -16 | | NodeBlock = Block, -... | -21 | | } -22 | | } - | |_^ not found in `system` - | - = note: this error originates in the macro `construct_runtime` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider importing one of these items - | -1 | use frame_support_test::Pallet; - | -1 | use frame_system::Pallet; - | -1 | use test_pallet::Pallet; - | - error[E0412]: cannot find type `GenesisConfig` in crate `test_pallet` - --> $DIR/no_std_genesis_config.rs:13:1 + --> tests/construct_runtime_ui/no_std_genesis_config.rs:40:1 | -13 | / construct_runtime! { -14 | | pub enum Runtime where -15 | | Block = Block, -16 | | NodeBlock = Block, +40 | / construct_runtime! { +41 | | pub enum Runtime where +42 | | Block = Block, +43 | | NodeBlock = Block, ... | -21 | | } -22 | | } +48 | | } +49 | | } | |_^ not found in `test_pallet` | = note: this error originates in the macro `construct_runtime` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -76,14 +30,22 @@ help: consider importing this struct 1 | use frame_system::GenesisConfig; | -error[E0277]: the trait bound `Runtime: frame_system::pallet::Config` is not satisfied - --> $DIR/no_std_genesis_config.rs:11:6 - | -11 | impl test_pallet::Config for Runtime {} - | ^^^^^^^^^^^^^^^^^^^ the trait `frame_system::pallet::Config` is not implemented for `Runtime` - | -note: required by a bound in `Config` - --> $DIR/lib.rs:30:20 - | -30 | pub trait Config: frame_system::Config {} - | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `Config` +error[E0283]: type annotations needed + --> tests/construct_runtime_ui/no_std_genesis_config.rs:40:1 + | +40 | / construct_runtime! { +41 | | pub enum Runtime where +42 | | Block = Block, +43 | | NodeBlock = Block, +... | +48 | | } +49 | | } + | |_^ cannot infer type + | + = note: cannot satisfy `_: std::default::Default` +note: required by `std::default::Default::default` + --> $RUST/core/src/default.rs + | + | fn default() -> Self; + | ^^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/frame/support/test/tests/construct_runtime_ui/undefined_call_part.rs b/frame/support/test/tests/construct_runtime_ui/undefined_call_part.rs index c5b9fcca1f31..1653e830f0b4 100644 --- a/frame/support/test/tests/construct_runtime_ui/undefined_call_part.rs +++ b/frame/support/test/tests/construct_runtime_ui/undefined_call_part.rs @@ -12,20 +12,47 @@ mod pallet { } pub type Signature = sr25519::Signature; -pub type BlockNumber = u64; +pub type BlockNumber = u32; pub type Header = generic::Header; pub type Block = generic::Block; pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; impl pallet::Config for Runtime {} +impl frame_system::Config for Runtime { + type BaseCallFilter = frame_support::traits::Everything; + type Origin = Origin; + type Index = u64; + type BlockNumber = u32; + type Call = Call; + type Hash = sp_runtime::testing::H256; + type Hashing = sp_runtime::traits::BlakeTwo256; + type AccountId = u64; + type Lookup = sp_runtime::traits::IdentityLookup; + type Header = Header; + type Event = Event; + type BlockHashCount = frame_support::traits::ConstU32<250>; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + construct_runtime! { pub enum Runtime where Block = Block, NodeBlock = Block, UncheckedExtrinsic = UncheckedExtrinsic { - System: system::{Pallet, Call, Storage, Config, Event}, + System: frame_system::{Pallet, Call, Storage, Config, Event}, Pallet: pallet::{Pallet, Call}, } } diff --git a/frame/support/test/tests/construct_runtime_ui/undefined_call_part.stderr b/frame/support/test/tests/construct_runtime_ui/undefined_call_part.stderr index c4e567102a89..c162a22bb87b 100644 --- a/frame/support/test/tests/construct_runtime_ui/undefined_call_part.stderr +++ b/frame/support/test/tests/construct_runtime_ui/undefined_call_part.stderr @@ -1,76 +1,16 @@ error: `Pallet` does not have #[pallet::call] defined, perhaps you should remove `Call` from construct_runtime? - --> $DIR/undefined_call_part.rs:5:1 + --> tests/construct_runtime_ui/undefined_call_part.rs:5:1 | 5 | #[frame_support::pallet] | ^^^^^^^^^^^^^^^^^^^^^^^^ ... -22 | / construct_runtime! { -23 | | pub enum Runtime where -24 | | Block = Block, -25 | | NodeBlock = Block, +49 | / construct_runtime! { +50 | | pub enum Runtime where +51 | | Block = Block, +52 | | NodeBlock = Block, ... | -30 | | } -31 | | } +57 | | } +58 | | } | |_- in this macro invocation | = note: this error originates in the macro `pallet::__substrate_call_check::is_call_part_defined` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0433]: failed to resolve: use of undeclared crate or module `system` - --> $DIR/undefined_call_part.rs:28:11 - | -28 | System: system::{Pallet, Call, Storage, Config, Event}, - | ^^^^^^ use of undeclared crate or module `system` - -error[E0433]: failed to resolve: use of undeclared crate or module `system` - --> $DIR/undefined_call_part.rs:22:1 - | -22 | / construct_runtime! { -23 | | pub enum Runtime where -24 | | Block = Block, -25 | | NodeBlock = Block, -... | -30 | | } -31 | | } - | |_^ not found in `system` - | - = note: this error originates in the macro `construct_runtime` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider importing this enum - | -1 | use frame_system::RawOrigin; - | - -error[E0433]: failed to resolve: use of undeclared crate or module `system` - --> $DIR/undefined_call_part.rs:22:1 - | -22 | / construct_runtime! { -23 | | pub enum Runtime where -24 | | Block = Block, -25 | | NodeBlock = Block, -... | -30 | | } -31 | | } - | |_^ not found in `system` - | - = note: this error originates in the macro `construct_runtime` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider importing one of these items - | -1 | use crate::pallet::Pallet; - | -1 | use frame_support_test::Pallet; - | -1 | use frame_system::Pallet; - | -1 | use test_pallet::Pallet; - | - -error[E0277]: the trait bound `Runtime: frame_system::Config` is not satisfied - --> $DIR/undefined_call_part.rs:20:6 - | -20 | impl pallet::Config for Runtime {} - | ^^^^^^^^^^^^^^ the trait `frame_system::Config` is not implemented for `Runtime` - | -note: required by a bound in `pallet::Config` - --> $DIR/undefined_call_part.rs:8:20 - | -8 | pub trait Config: frame_system::Config {} - | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `pallet::Config` diff --git a/frame/support/test/tests/construct_runtime_ui/undefined_event_part.rs b/frame/support/test/tests/construct_runtime_ui/undefined_event_part.rs index 6aec45f240c9..b8f91cf4bc69 100644 --- a/frame/support/test/tests/construct_runtime_ui/undefined_event_part.rs +++ b/frame/support/test/tests/construct_runtime_ui/undefined_event_part.rs @@ -12,20 +12,47 @@ mod pallet { } pub type Signature = sr25519::Signature; -pub type BlockNumber = u64; +pub type BlockNumber = u32; pub type Header = generic::Header; pub type Block = generic::Block; pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; impl pallet::Config for Runtime {} +impl frame_system::Config for Runtime { + type BaseCallFilter = frame_support::traits::Everything; + type Origin = Origin; + type Index = u64; + type BlockNumber = u32; + type Call = Call; + type Hash = sp_runtime::testing::H256; + type Hashing = sp_runtime::traits::BlakeTwo256; + type AccountId = u64; + type Lookup = sp_runtime::traits::IdentityLookup; + type Header = Header; + type Event = Event; + type BlockHashCount = frame_support::traits::ConstU32<250>; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + construct_runtime! { pub enum Runtime where Block = Block, NodeBlock = Block, UncheckedExtrinsic = UncheckedExtrinsic { - System: system::{Pallet, Call, Storage, Config, Event}, + System: frame_system::{Pallet, Call, Storage, Config, Event}, Pallet: pallet::{Pallet, Event}, } } diff --git a/frame/support/test/tests/construct_runtime_ui/undefined_event_part.stderr b/frame/support/test/tests/construct_runtime_ui/undefined_event_part.stderr index da972f6f4b2f..31229f8c93cb 100644 --- a/frame/support/test/tests/construct_runtime_ui/undefined_event_part.stderr +++ b/frame/support/test/tests/construct_runtime_ui/undefined_event_part.stderr @@ -1,36 +1,30 @@ error: `Pallet` does not have #[pallet::event] defined, perhaps you should remove `Event` from construct_runtime? - --> $DIR/undefined_event_part.rs:5:1 + --> tests/construct_runtime_ui/undefined_event_part.rs:5:1 | 5 | #[frame_support::pallet] | ^^^^^^^^^^^^^^^^^^^^^^^^ ... -22 | / construct_runtime! { -23 | | pub enum Runtime where -24 | | Block = Block, -25 | | NodeBlock = Block, +49 | / construct_runtime! { +50 | | pub enum Runtime where +51 | | Block = Block, +52 | | NodeBlock = Block, ... | -30 | | } -31 | | } +57 | | } +58 | | } | |_- in this macro invocation | = note: this error originates in the macro `pallet::__substrate_event_check::is_event_part_defined` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0433]: failed to resolve: use of undeclared crate or module `system` - --> $DIR/undefined_event_part.rs:28:11 - | -28 | System: system::{Pallet, Call, Storage, Config, Event}, - | ^^^^^^ use of undeclared crate or module `system` - error[E0412]: cannot find type `Event` in module `pallet` - --> $DIR/undefined_event_part.rs:22:1 + --> tests/construct_runtime_ui/undefined_event_part.rs:49:1 | -22 | / construct_runtime! { -23 | | pub enum Runtime where -24 | | Block = Block, -25 | | NodeBlock = Block, +49 | / construct_runtime! { +50 | | pub enum Runtime where +51 | | Block = Block, +52 | | NodeBlock = Block, ... | -30 | | } -31 | | } +57 | | } +58 | | } | |_^ not found in `pallet` | = note: this error originates in the macro `construct_runtime` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -40,15 +34,15 @@ help: consider importing this enum | error[E0412]: cannot find type `Event` in module `pallet` - --> $DIR/undefined_event_part.rs:22:1 + --> tests/construct_runtime_ui/undefined_event_part.rs:49:1 | -22 | / construct_runtime! { -23 | | pub enum Runtime where -24 | | Block = Block, -25 | | NodeBlock = Block, +49 | / construct_runtime! { +50 | | pub enum Runtime where +51 | | Block = Block, +52 | | NodeBlock = Block, ... | -30 | | } -31 | | } +57 | | } +58 | | } | |_^ not found in `pallet` | = note: this error originates in the macro `construct_runtime` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -58,57 +52,3 @@ help: consider importing one of these items | 1 | use frame_system::Event; | - -error[E0433]: failed to resolve: use of undeclared crate or module `system` - --> $DIR/undefined_event_part.rs:22:1 - | -22 | / construct_runtime! { -23 | | pub enum Runtime where -24 | | Block = Block, -25 | | NodeBlock = Block, -... | -30 | | } -31 | | } - | |_^ not found in `system` - | - = note: this error originates in the macro `construct_runtime` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider importing this enum - | -1 | use frame_system::RawOrigin; - | - -error[E0433]: failed to resolve: use of undeclared crate or module `system` - --> $DIR/undefined_event_part.rs:22:1 - | -22 | / construct_runtime! { -23 | | pub enum Runtime where -24 | | Block = Block, -25 | | NodeBlock = Block, -... | -30 | | } -31 | | } - | |_^ not found in `system` - | - = note: this error originates in the macro `construct_runtime` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider importing one of these items - | -1 | use crate::pallet::Pallet; - | -1 | use frame_support_test::Pallet; - | -1 | use frame_system::Pallet; - | -1 | use test_pallet::Pallet; - | - -error[E0277]: the trait bound `Runtime: frame_system::Config` is not satisfied - --> $DIR/undefined_event_part.rs:20:6 - | -20 | impl pallet::Config for Runtime {} - | ^^^^^^^^^^^^^^ the trait `frame_system::Config` is not implemented for `Runtime` - | -note: required by a bound in `pallet::Config` - --> $DIR/undefined_event_part.rs:8:20 - | -8 | pub trait Config: frame_system::Config {} - | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `pallet::Config` diff --git a/frame/support/test/tests/construct_runtime_ui/undefined_genesis_config_part.rs b/frame/support/test/tests/construct_runtime_ui/undefined_genesis_config_part.rs index 5e08fd96fa1a..a61d545b3279 100644 --- a/frame/support/test/tests/construct_runtime_ui/undefined_genesis_config_part.rs +++ b/frame/support/test/tests/construct_runtime_ui/undefined_genesis_config_part.rs @@ -12,20 +12,47 @@ mod pallet { } pub type Signature = sr25519::Signature; -pub type BlockNumber = u64; +pub type BlockNumber = u32; pub type Header = generic::Header; pub type Block = generic::Block; pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; impl pallet::Config for Runtime {} +impl frame_system::Config for Runtime { + type BaseCallFilter = frame_support::traits::Everything; + type Origin = Origin; + type Index = u64; + type BlockNumber = u32; + type Call = Call; + type Hash = sp_runtime::testing::H256; + type Hashing = sp_runtime::traits::BlakeTwo256; + type AccountId = u64; + type Lookup = sp_runtime::traits::IdentityLookup; + type Header = Header; + type Event = Event; + type BlockHashCount = frame_support::traits::ConstU32<250>; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + construct_runtime! { pub enum Runtime where Block = Block, NodeBlock = Block, UncheckedExtrinsic = UncheckedExtrinsic { - System: system::{Pallet, Call, Storage, Config, Event}, + System: frame_system::{Pallet, Call, Storage, Config, Event}, Pallet: pallet::{Pallet, Config}, } } diff --git a/frame/support/test/tests/construct_runtime_ui/undefined_genesis_config_part.stderr b/frame/support/test/tests/construct_runtime_ui/undefined_genesis_config_part.stderr index 8e40773b6573..e8532aa9a064 100644 --- a/frame/support/test/tests/construct_runtime_ui/undefined_genesis_config_part.stderr +++ b/frame/support/test/tests/construct_runtime_ui/undefined_genesis_config_part.stderr @@ -1,78 +1,30 @@ error: `Pallet` does not have #[pallet::genesis_config] defined, perhaps you should remove `Config` from construct_runtime? - --> $DIR/undefined_genesis_config_part.rs:5:1 + --> tests/construct_runtime_ui/undefined_genesis_config_part.rs:5:1 | 5 | #[frame_support::pallet] | ^^^^^^^^^^^^^^^^^^^^^^^^ ... -22 | / construct_runtime! { -23 | | pub enum Runtime where -24 | | Block = Block, -25 | | NodeBlock = Block, +49 | / construct_runtime! { +50 | | pub enum Runtime where +51 | | Block = Block, +52 | | NodeBlock = Block, ... | -30 | | } -31 | | } +57 | | } +58 | | } | |_- in this macro invocation | = note: this error originates in the macro `pallet::__substrate_genesis_config_check::is_genesis_config_defined` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0433]: failed to resolve: use of undeclared crate or module `system` - --> $DIR/undefined_genesis_config_part.rs:28:17 - | -28 | System: system::{Pallet, Call, Storage, Config, Event}, - | ^^^^^^ use of undeclared crate or module `system` - -error[E0433]: failed to resolve: use of undeclared crate or module `system` - --> $DIR/undefined_genesis_config_part.rs:22:1 - | -22 | / construct_runtime! { -23 | | pub enum Runtime where -24 | | Block = Block, -25 | | NodeBlock = Block, -... | -30 | | } -31 | | } - | |_^ not found in `system` - | - = note: this error originates in the macro `construct_runtime` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider importing this enum - | -1 | use frame_system::RawOrigin; - | - -error[E0433]: failed to resolve: use of undeclared crate or module `system` - --> $DIR/undefined_genesis_config_part.rs:22:1 - | -22 | / construct_runtime! { -23 | | pub enum Runtime where -24 | | Block = Block, -25 | | NodeBlock = Block, -... | -30 | | } -31 | | } - | |_^ not found in `system` - | - = note: this error originates in the macro `construct_runtime` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider importing one of these items - | -1 | use crate::pallet::Pallet; - | -1 | use frame_support_test::Pallet; - | -1 | use frame_system::Pallet; - | -1 | use test_pallet::Pallet; - | - error[E0412]: cannot find type `GenesisConfig` in module `pallet` - --> $DIR/undefined_genesis_config_part.rs:22:1 + --> tests/construct_runtime_ui/undefined_genesis_config_part.rs:49:1 | -22 | / construct_runtime! { -23 | | pub enum Runtime where -24 | | Block = Block, -25 | | NodeBlock = Block, +49 | / construct_runtime! { +50 | | pub enum Runtime where +51 | | Block = Block, +52 | | NodeBlock = Block, ... | -30 | | } -31 | | } +57 | | } +58 | | } | |_^ not found in `pallet` | = note: this error originates in the macro `construct_runtime` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -81,14 +33,22 @@ help: consider importing this struct 1 | use frame_system::GenesisConfig; | -error[E0277]: the trait bound `Runtime: frame_system::Config` is not satisfied - --> $DIR/undefined_genesis_config_part.rs:20:6 - | -20 | impl pallet::Config for Runtime {} - | ^^^^^^^^^^^^^^ the trait `frame_system::Config` is not implemented for `Runtime` - | -note: required by a bound in `pallet::Config` - --> $DIR/undefined_genesis_config_part.rs:8:20 - | -8 | pub trait Config: frame_system::Config {} - | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `pallet::Config` +error[E0283]: type annotations needed + --> tests/construct_runtime_ui/undefined_genesis_config_part.rs:49:1 + | +49 | / construct_runtime! { +50 | | pub enum Runtime where +51 | | Block = Block, +52 | | NodeBlock = Block, +... | +57 | | } +58 | | } + | |_^ cannot infer type + | + = note: cannot satisfy `_: std::default::Default` +note: required by `std::default::Default::default` + --> $RUST/core/src/default.rs + | + | fn default() -> Self; + | ^^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/frame/support/test/tests/construct_runtime_ui/undefined_inherent_part.rs b/frame/support/test/tests/construct_runtime_ui/undefined_inherent_part.rs index 06c36a30f550..6e4764286ab4 100644 --- a/frame/support/test/tests/construct_runtime_ui/undefined_inherent_part.rs +++ b/frame/support/test/tests/construct_runtime_ui/undefined_inherent_part.rs @@ -12,20 +12,47 @@ mod pallet { } pub type Signature = sr25519::Signature; -pub type BlockNumber = u64; +pub type BlockNumber = u32; pub type Header = generic::Header; pub type Block = generic::Block; pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; impl pallet::Config for Runtime {} +impl frame_system::Config for Runtime { + type BaseCallFilter = frame_support::traits::Everything; + type Origin = Origin; + type Index = u64; + type BlockNumber = u32; + type Call = Call; + type Hash = sp_runtime::testing::H256; + type Hashing = sp_runtime::traits::BlakeTwo256; + type AccountId = u64; + type Lookup = sp_runtime::traits::IdentityLookup; + type Header = Header; + type Event = Event; + type BlockHashCount = frame_support::traits::ConstU32<250>; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + construct_runtime! { pub enum Runtime where Block = Block, NodeBlock = Block, UncheckedExtrinsic = UncheckedExtrinsic { - System: system::{Pallet, Call, Storage, Config, Event}, + System: frame_system::{Pallet, Call, Storage, Config, Event}, Pallet: pallet::{Pallet, Inherent}, } } diff --git a/frame/support/test/tests/construct_runtime_ui/undefined_inherent_part.stderr b/frame/support/test/tests/construct_runtime_ui/undefined_inherent_part.stderr index ae461473c3b1..9f646469d86a 100644 --- a/frame/support/test/tests/construct_runtime_ui/undefined_inherent_part.stderr +++ b/frame/support/test/tests/construct_runtime_ui/undefined_inherent_part.stderr @@ -1,76 +1,116 @@ error: `Pallet` does not have #[pallet::inherent] defined, perhaps you should remove `Inherent` from construct_runtime? - --> $DIR/undefined_inherent_part.rs:5:1 + --> tests/construct_runtime_ui/undefined_inherent_part.rs:5:1 | 5 | #[frame_support::pallet] | ^^^^^^^^^^^^^^^^^^^^^^^^ ... -22 | / construct_runtime! { -23 | | pub enum Runtime where -24 | | Block = Block, -25 | | NodeBlock = Block, +49 | / construct_runtime! { +50 | | pub enum Runtime where +51 | | Block = Block, +52 | | NodeBlock = Block, ... | -30 | | } -31 | | } +57 | | } +58 | | } | |_- in this macro invocation | = note: this error originates in the macro `pallet::__substrate_inherent_check::is_inherent_part_defined` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0433]: failed to resolve: use of undeclared crate or module `system` - --> $DIR/undefined_inherent_part.rs:28:11 +error[E0599]: no function or associated item named `create_inherent` found for struct `pallet::Pallet` in the current scope + --> tests/construct_runtime_ui/undefined_inherent_part.rs:49:1 | -28 | System: system::{Pallet, Call, Storage, Config, Event}, - | ^^^^^^ use of undeclared crate or module `system` - -error[E0433]: failed to resolve: use of undeclared crate or module `system` - --> $DIR/undefined_inherent_part.rs:22:1 - | -22 | / construct_runtime! { -23 | | pub enum Runtime where -24 | | Block = Block, -25 | | NodeBlock = Block, +11 | pub struct Pallet(_); + | ------------------------ function or associated item `create_inherent` not found for this +... +49 | / construct_runtime! { +50 | | pub enum Runtime where +51 | | Block = Block, +52 | | NodeBlock = Block, ... | -30 | | } -31 | | } - | |_^ not found in `system` +57 | | } +58 | | } + | |_^ function or associated item not found in `pallet::Pallet` | + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `create_inherent`, perhaps you need to implement it: + candidate #1: `ProvideInherent` = note: this error originates in the macro `construct_runtime` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider importing this enum - | -1 | use frame_system::RawOrigin; - | -error[E0433]: failed to resolve: use of undeclared crate or module `system` - --> $DIR/undefined_inherent_part.rs:22:1 +error[E0599]: no function or associated item named `is_inherent` found for struct `pallet::Pallet` in the current scope + --> tests/construct_runtime_ui/undefined_inherent_part.rs:49:1 | -22 | / construct_runtime! { -23 | | pub enum Runtime where -24 | | Block = Block, -25 | | NodeBlock = Block, +11 | pub struct Pallet(_); + | ------------------------ function or associated item `is_inherent` not found for this +... +49 | / construct_runtime! { +50 | | pub enum Runtime where +51 | | Block = Block, +52 | | NodeBlock = Block, ... | -30 | | } -31 | | } - | |_^ not found in `system` +57 | | } +58 | | } + | |_^ function or associated item not found in `pallet::Pallet` | + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `is_inherent`, perhaps you need to implement it: + candidate #1: `ProvideInherent` = note: this error originates in the macro `construct_runtime` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider importing one of these items - | -1 | use crate::pallet::Pallet; + +error[E0599]: no function or associated item named `check_inherent` found for struct `pallet::Pallet` in the current scope + --> tests/construct_runtime_ui/undefined_inherent_part.rs:49:1 | -1 | use frame_support_test::Pallet; +11 | pub struct Pallet(_); + | ------------------------ function or associated item `check_inherent` not found for this +... +49 | / construct_runtime! { +50 | | pub enum Runtime where +51 | | Block = Block, +52 | | NodeBlock = Block, +... | +57 | | } +58 | | } + | |_^ function or associated item not found in `pallet::Pallet` | -1 | use frame_system::Pallet; + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `check_inherent`, perhaps you need to implement it: + candidate #1: `ProvideInherent` + = note: this error originates in the macro `construct_runtime` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0599]: no associated item named `INHERENT_IDENTIFIER` found for struct `pallet::Pallet` in the current scope + --> tests/construct_runtime_ui/undefined_inherent_part.rs:49:1 | -1 | use test_pallet::Pallet; +11 | pub struct Pallet(_); + | ------------------------ associated item `INHERENT_IDENTIFIER` not found for this +... +49 | / construct_runtime! { +50 | | pub enum Runtime where +51 | | Block = Block, +52 | | NodeBlock = Block, +... | +57 | | } +58 | | } + | |_^ associated item not found in `pallet::Pallet` | + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `INHERENT_IDENTIFIER`, perhaps you need to implement it: + candidate #1: `ProvideInherent` + = note: this error originates in the macro `construct_runtime` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0277]: the trait bound `Runtime: frame_system::Config` is not satisfied - --> $DIR/undefined_inherent_part.rs:20:6 +error[E0599]: no function or associated item named `is_inherent_required` found for struct `pallet::Pallet` in the current scope + --> tests/construct_runtime_ui/undefined_inherent_part.rs:49:1 | -20 | impl pallet::Config for Runtime {} - | ^^^^^^^^^^^^^^ the trait `frame_system::Config` is not implemented for `Runtime` - | -note: required by a bound in `pallet::Config` - --> $DIR/undefined_inherent_part.rs:8:20 +11 | pub struct Pallet(_); + | ------------------------ function or associated item `is_inherent_required` not found for this +... +49 | / construct_runtime! { +50 | | pub enum Runtime where +51 | | Block = Block, +52 | | NodeBlock = Block, +... | +57 | | } +58 | | } + | |_^ function or associated item not found in `pallet::Pallet` | -8 | pub trait Config: frame_system::Config {} - | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `pallet::Config` + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `is_inherent_required`, perhaps you need to implement it: + candidate #1: `ProvideInherent` + = note: this error originates in the macro `construct_runtime` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/frame/support/test/tests/construct_runtime_ui/undefined_origin_part.rs b/frame/support/test/tests/construct_runtime_ui/undefined_origin_part.rs index bec5c27ec034..9233404a865b 100644 --- a/frame/support/test/tests/construct_runtime_ui/undefined_origin_part.rs +++ b/frame/support/test/tests/construct_runtime_ui/undefined_origin_part.rs @@ -12,20 +12,47 @@ mod pallet { } pub type Signature = sr25519::Signature; -pub type BlockNumber = u64; +pub type BlockNumber = u32; pub type Header = generic::Header; pub type Block = generic::Block; pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; impl pallet::Config for Runtime {} +impl frame_system::Config for Runtime { + type BaseCallFilter = frame_support::traits::Everything; + type Origin = Origin; + type Index = u64; + type BlockNumber = u32; + type Call = Call; + type Hash = sp_runtime::testing::H256; + type Hashing = sp_runtime::traits::BlakeTwo256; + type AccountId = u64; + type Lookup = sp_runtime::traits::IdentityLookup; + type Header = Header; + type Event = Event; + type BlockHashCount = frame_support::traits::ConstU32<250>; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + construct_runtime! { pub enum Runtime where Block = Block, NodeBlock = Block, UncheckedExtrinsic = UncheckedExtrinsic { - System: system::{Pallet, Call, Storage, Config, Event}, + System: frame_system::{Pallet, Call, Storage, Config, Event}, Pallet: pallet::{Pallet, Origin}, } } diff --git a/frame/support/test/tests/construct_runtime_ui/undefined_origin_part.stderr b/frame/support/test/tests/construct_runtime_ui/undefined_origin_part.stderr index dbdd9f869a2e..06e845618d44 100644 --- a/frame/support/test/tests/construct_runtime_ui/undefined_origin_part.stderr +++ b/frame/support/test/tests/construct_runtime_ui/undefined_origin_part.stderr @@ -1,54 +1,30 @@ error: `Pallet` does not have #[pallet::origin] defined, perhaps you should remove `Origin` from construct_runtime? - --> $DIR/undefined_origin_part.rs:5:1 + --> tests/construct_runtime_ui/undefined_origin_part.rs:5:1 | 5 | #[frame_support::pallet] | ^^^^^^^^^^^^^^^^^^^^^^^^ ... -22 | / construct_runtime! { -23 | | pub enum Runtime where -24 | | Block = Block, -25 | | NodeBlock = Block, +49 | / construct_runtime! { +50 | | pub enum Runtime where +51 | | Block = Block, +52 | | NodeBlock = Block, ... | -30 | | } -31 | | } +57 | | } +58 | | } | |_- in this macro invocation | = note: this error originates in the macro `pallet::__substrate_origin_check::is_origin_part_defined` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0433]: failed to resolve: use of undeclared crate or module `system` - --> $DIR/undefined_origin_part.rs:28:11 - | -28 | System: system::{Pallet, Call, Storage, Config, Event}, - | ^^^^^^ use of undeclared crate or module `system` - -error[E0433]: failed to resolve: use of undeclared crate or module `system` - --> $DIR/undefined_origin_part.rs:22:1 - | -22 | / construct_runtime! { -23 | | pub enum Runtime where -24 | | Block = Block, -25 | | NodeBlock = Block, -... | -30 | | } -31 | | } - | |_^ not found in `system` - | - = note: this error originates in the macro `construct_runtime` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider importing this enum - | -1 | use frame_system::RawOrigin; - | - error[E0412]: cannot find type `Origin` in module `pallet` - --> $DIR/undefined_origin_part.rs:22:1 + --> tests/construct_runtime_ui/undefined_origin_part.rs:49:1 | -22 | / construct_runtime! { -23 | | pub enum Runtime where -24 | | Block = Block, -25 | | NodeBlock = Block, +49 | / construct_runtime! { +50 | | pub enum Runtime where +51 | | Block = Block, +52 | | NodeBlock = Block, ... | -30 | | } -31 | | } +57 | | } +58 | | } | |_^ not found in `pallet` | = note: this error originates in the macro `construct_runtime` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -58,15 +34,15 @@ help: consider importing this type alias | error[E0412]: cannot find type `Origin` in module `pallet` - --> $DIR/undefined_origin_part.rs:22:1 + --> tests/construct_runtime_ui/undefined_origin_part.rs:49:1 | -22 | / construct_runtime! { -23 | | pub enum Runtime where -24 | | Block = Block, -25 | | NodeBlock = Block, +49 | / construct_runtime! { +50 | | pub enum Runtime where +51 | | Block = Block, +52 | | NodeBlock = Block, ... | -30 | | } -31 | | } +57 | | } +58 | | } | |_^ not found in `pallet` | = note: this error originates in the macro `construct_runtime` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -77,38 +53,16 @@ help: consider importing one of these items 1 | use frame_system::Origin; | -error[E0433]: failed to resolve: use of undeclared crate or module `system` - --> $DIR/undefined_origin_part.rs:22:1 +error[E0282]: type annotations needed + --> tests/construct_runtime_ui/undefined_origin_part.rs:49:1 | -22 | / construct_runtime! { -23 | | pub enum Runtime where -24 | | Block = Block, -25 | | NodeBlock = Block, +49 | / construct_runtime! { +50 | | pub enum Runtime where +51 | | Block = Block, +52 | | NodeBlock = Block, ... | -30 | | } -31 | | } - | |_^ not found in `system` +57 | | } +58 | | } + | |_^ cannot infer type for type parameter `AccountId` declared on the enum `RawOrigin` | = note: this error originates in the macro `construct_runtime` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider importing one of these items - | -1 | use crate::pallet::Pallet; - | -1 | use frame_support_test::Pallet; - | -1 | use frame_system::Pallet; - | -1 | use test_pallet::Pallet; - | - -error[E0277]: the trait bound `Runtime: frame_system::Config` is not satisfied - --> $DIR/undefined_origin_part.rs:20:6 - | -20 | impl pallet::Config for Runtime {} - | ^^^^^^^^^^^^^^ the trait `frame_system::Config` is not implemented for `Runtime` - | -note: required by a bound in `pallet::Config` - --> $DIR/undefined_origin_part.rs:8:20 - | -8 | pub trait Config: frame_system::Config {} - | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `pallet::Config` diff --git a/frame/support/test/tests/construct_runtime_ui/undefined_validate_unsigned_part.rs b/frame/support/test/tests/construct_runtime_ui/undefined_validate_unsigned_part.rs index 816f52b91ccc..621683aca375 100644 --- a/frame/support/test/tests/construct_runtime_ui/undefined_validate_unsigned_part.rs +++ b/frame/support/test/tests/construct_runtime_ui/undefined_validate_unsigned_part.rs @@ -12,20 +12,47 @@ mod pallet { } pub type Signature = sr25519::Signature; -pub type BlockNumber = u64; +pub type BlockNumber = u32; pub type Header = generic::Header; pub type Block = generic::Block; pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; impl pallet::Config for Runtime {} +impl frame_system::Config for Runtime { + type BaseCallFilter = frame_support::traits::Everything; + type Origin = Origin; + type Index = u64; + type BlockNumber = u32; + type Call = Call; + type Hash = sp_runtime::testing::H256; + type Hashing = sp_runtime::traits::BlakeTwo256; + type AccountId = u64; + type Lookup = sp_runtime::traits::IdentityLookup; + type Header = Header; + type Event = Event; + type BlockHashCount = frame_support::traits::ConstU32<250>; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + construct_runtime! { pub enum Runtime where Block = Block, NodeBlock = Block, UncheckedExtrinsic = UncheckedExtrinsic { - System: system::{Pallet, Call, Storage, Config, Event}, + System: frame_system::{Pallet, Call, Storage, Config, Event}, Pallet: pallet::{Pallet, ValidateUnsigned}, } } diff --git a/frame/support/test/tests/construct_runtime_ui/undefined_validate_unsigned_part.stderr b/frame/support/test/tests/construct_runtime_ui/undefined_validate_unsigned_part.stderr index 8126d2f9a3e0..94226075d9a4 100644 --- a/frame/support/test/tests/construct_runtime_ui/undefined_validate_unsigned_part.stderr +++ b/frame/support/test/tests/construct_runtime_ui/undefined_validate_unsigned_part.stderr @@ -1,76 +1,67 @@ error: `Pallet` does not have #[pallet::validate_unsigned] defined, perhaps you should remove `ValidateUnsigned` from construct_runtime? - --> $DIR/undefined_validate_unsigned_part.rs:5:1 + --> tests/construct_runtime_ui/undefined_validate_unsigned_part.rs:5:1 | 5 | #[frame_support::pallet] | ^^^^^^^^^^^^^^^^^^^^^^^^ ... -22 | / construct_runtime! { -23 | | pub enum Runtime where -24 | | Block = Block, -25 | | NodeBlock = Block, +49 | / construct_runtime! { +50 | | pub enum Runtime where +51 | | Block = Block, +52 | | NodeBlock = Block, ... | -30 | | } -31 | | } +57 | | } +58 | | } | |_- in this macro invocation | = note: this error originates in the macro `pallet::__substrate_validate_unsigned_check::is_validate_unsigned_part_defined` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0433]: failed to resolve: use of undeclared crate or module `system` - --> $DIR/undefined_validate_unsigned_part.rs:28:11 +error[E0599]: no variant or associated item named `Pallet` found for enum `Call` in the current scope + --> tests/construct_runtime_ui/undefined_validate_unsigned_part.rs:56:3 | -28 | System: system::{Pallet, Call, Storage, Config, Event}, - | ^^^^^^ use of undeclared crate or module `system` +49 | construct_runtime! { + | ------------------ variant or associated item `Pallet` not found here +... +56 | Pallet: pallet::{Pallet, ValidateUnsigned}, + | ^^^^^^ variant or associated item not found in `Call` -error[E0433]: failed to resolve: use of undeclared crate or module `system` - --> $DIR/undefined_validate_unsigned_part.rs:22:1 +error[E0599]: no function or associated item named `pre_dispatch` found for struct `pallet::Pallet` in the current scope + --> tests/construct_runtime_ui/undefined_validate_unsigned_part.rs:49:1 | -22 | / construct_runtime! { -23 | | pub enum Runtime where -24 | | Block = Block, -25 | | NodeBlock = Block, +11 | pub struct Pallet(_); + | ------------------------ function or associated item `pre_dispatch` not found for this +... +49 | / construct_runtime! { +50 | | pub enum Runtime where +51 | | Block = Block, +52 | | NodeBlock = Block, ... | -30 | | } -31 | | } - | |_^ not found in `system` - | +57 | | } +58 | | } + | |_^ function or associated item not found in `pallet::Pallet` + | + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following traits define an item `pre_dispatch`, perhaps you need to implement one of them: + candidate #1: `SignedExtension` + candidate #2: `ValidateUnsigned` = note: this error originates in the macro `construct_runtime` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider importing this enum - | -1 | use frame_system::RawOrigin; - | -error[E0433]: failed to resolve: use of undeclared crate or module `system` - --> $DIR/undefined_validate_unsigned_part.rs:22:1 +error[E0599]: no function or associated item named `validate_unsigned` found for struct `pallet::Pallet` in the current scope + --> tests/construct_runtime_ui/undefined_validate_unsigned_part.rs:49:1 | -22 | / construct_runtime! { -23 | | pub enum Runtime where -24 | | Block = Block, -25 | | NodeBlock = Block, +11 | pub struct Pallet(_); + | ------------------------ function or associated item `validate_unsigned` not found for this +... +49 | / construct_runtime! { +50 | | pub enum Runtime where +51 | | Block = Block, +52 | | NodeBlock = Block, ... | -30 | | } -31 | | } - | |_^ not found in `system` - | +57 | | } +58 | | } + | |_^ function or associated item not found in `pallet::Pallet` + | + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following traits define an item `validate_unsigned`, perhaps you need to implement one of them: + candidate #1: `SignedExtension` + candidate #2: `ValidateUnsigned` = note: this error originates in the macro `construct_runtime` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider importing one of these items - | -1 | use crate::pallet::Pallet; - | -1 | use frame_support_test::Pallet; - | -1 | use frame_system::Pallet; - | -1 | use test_pallet::Pallet; - | - -error[E0277]: the trait bound `Runtime: frame_system::Config` is not satisfied - --> $DIR/undefined_validate_unsigned_part.rs:20:6 - | -20 | impl pallet::Config for Runtime {} - | ^^^^^^^^^^^^^^ the trait `frame_system::Config` is not implemented for `Runtime` - | -note: required by a bound in `pallet::Config` - --> $DIR/undefined_validate_unsigned_part.rs:8:20 - | -8 | pub trait Config: frame_system::Config {} - | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `pallet::Config` From 7cb0e76b847a49e2a9227e0c039bcbb335c83309 Mon Sep 17 00:00:00 2001 From: Alexander Gryaznov Date: Fri, 4 Feb 2022 20:13:00 +0100 Subject: [PATCH 455/695] contracts: `is_contract(address)` and `caller_is_origin()` are added to API (#10789) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * is_contract() and caller_is_origin() added to Ext API * is_contract() exposed in wasm runtime.rs * + test for is_contract() * + seal_is_contract benchmark * caller_is_origin() exposed to wasm/runtime.rs and covered by a test * + seal_caller_is_origin benchmark * Update frame/contracts/src/exec.rs Co-authored-by: Alexander Theißen * Update frame/contracts/src/exec.rs Co-authored-by: Alexander Theißen * Update frame/contracts/src/exec.rs Co-authored-by: Alexander Theißen * Update frame/contracts/src/wasm/runtime.rs Co-authored-by: Alexander Theißen * Update frame/contracts/src/wasm/runtime.rs Co-authored-by: Alexander Theißen * Update frame/contracts/src/wasm/runtime.rs Co-authored-by: Alexander Theißen * Update frame/contracts/src/exec.rs Co-authored-by: Alexander Theißen * identation fix for benchmark macroses; test cosmetic improvement * benchmark fix * + is_contract() wasm test * + caller_is_origin() wasm test * Apply suggestions from code review Co-authored-by: Alexander Theißen * is_contract() to borrow param instead of taking ownership * phrasing improved Co-authored-by: Hernando Castano * fixed wasm tests according to @athei feedback * dead code warnings suppressed by unstable-interface attributes * cargo run --quiet --profile=production --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_contracts --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/contracts/src/weights.rs --template=./.maintain/frame-weight-template.hbs Co-authored-by: Alexander Theißen Co-authored-by: Hernando Castano Co-authored-by: Parity Bot --- frame/contracts/src/benchmarking/mod.rs | 57 ++ frame/contracts/src/exec.rs | 83 +- frame/contracts/src/schedule.rs | 8 + frame/contracts/src/wasm/mod.rs | 82 ++ frame/contracts/src/wasm/runtime.rs | 41 + frame/contracts/src/weights.rs | 1250 ++++++++++++----------- 6 files changed, 917 insertions(+), 604 deletions(-) diff --git a/frame/contracts/src/benchmarking/mod.rs b/frame/contracts/src/benchmarking/mod.rs index 83be846465e4..71045bde2152 100644 --- a/frame/contracts/src/benchmarking/mod.rs +++ b/frame/contracts/src/benchmarking/mod.rs @@ -398,6 +398,63 @@ benchmarks! { let origin = RawOrigin::Signed(instance.caller.clone()); }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + seal_is_contract { + let r in 0 .. API_BENCHMARK_BATCHES; + let accounts = (0 .. r * API_BENCHMARK_BATCH_SIZE) + .map(|n| account::("account", n, 0)) + .collect::>(); + let account_len = accounts.get(0).map(|i| i.encode().len()).unwrap_or(0); + let accounts_bytes = accounts.iter().map(|a| a.encode()).flatten().collect::>(); + let code = WasmModule::::from(ModuleDefinition { + memory: Some(ImportedMemory::max::()), + imported_functions: vec![ImportedFunction { + module: "__unstable__", + name: "seal_is_contract", + params: vec![ValueType::I32], + return_type: Some(ValueType::I32), + }], + data_segments: vec![ + DataSegment { + offset: 0, + value: accounts_bytes + }, + ], + call_body: Some(body::repeated_dyn(r * API_BENCHMARK_BATCH_SIZE, vec![ + Counter(0, account_len as u32), // address_ptr + Regular(Instruction::Call(0)), + Regular(Instruction::Drop), + ])), + .. Default::default() + }); + let instance = Contract::::new(code, vec![])?; + let info = instance.info()?; + // every account would be a contract (worst case) + for acc in accounts.iter() { + >::insert(acc, info.clone()); + } + let origin = RawOrigin::Signed(instance.caller.clone()); + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + + seal_caller_is_origin { + let r in 0 .. API_BENCHMARK_BATCHES; + let code = WasmModule::::from(ModuleDefinition { + memory: Some(ImportedMemory::max::()), + imported_functions: vec![ImportedFunction { + module: "__unstable__", + name: "seal_caller_is_origin", + params: vec![], + return_type: Some(ValueType::I32), + }], + call_body: Some(body::repeated(r * API_BENCHMARK_BATCH_SIZE, &[ + Instruction::Call(0), + Instruction::Drop, + ])), + .. Default::default() + }); + let instance = Contract::::new(code, vec![])?; + let origin = RawOrigin::Signed(instance.caller.clone()); + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + seal_address { let r in 0 .. API_BENCHMARK_BATCHES; let instance = Contract::::new(WasmModule::getter( diff --git a/frame/contracts/src/exec.rs b/frame/contracts/src/exec.rs index e4988eea51d0..befdf592f51c 100644 --- a/frame/contracts/src/exec.rs +++ b/frame/contracts/src/exec.rs @@ -158,6 +158,15 @@ pub trait Ext: sealing::Sealed { /// Returns a reference to the account id of the caller. fn caller(&self) -> &AccountIdOf; + /// Check if a contract lives at the specified `address`. + fn is_contract(&self, address: &AccountIdOf) -> bool; + + /// Check if the caller of the current contract is the origin of the whole call stack. + /// + /// This can be checked with `is_contract(self.caller())` as well. + /// However, this function does not require any storage lookup and therefore uses less weight. + fn caller_is_origin(&self) -> bool; + /// Returns a reference to the account id of the current contract. fn address(&self) -> &AccountIdOf; @@ -483,7 +492,7 @@ where T::AccountId: UncheckedFrom + AsRef<[u8]>, E: Executable, { - /// Create an run a new call stack by calling into `dest`. + /// Create and run a new call stack by calling into `dest`. /// /// # Note /// @@ -1024,6 +1033,14 @@ where self.frames().nth(1).map(|f| &f.account_id).unwrap_or(&self.origin) } + fn is_contract(&self, address: &T::AccountId) -> bool { + ContractInfoOf::::contains_key(&address) + } + + fn caller_is_origin(&self) -> bool { + self.caller() == &self.origin + } + fn balance(&self) -> BalanceOf { T::Currency::free_balance(&self.top_frame().account_id) } @@ -1620,6 +1637,70 @@ mod tests { WITNESSED_CALLER_CHARLIE.with(|caller| assert_eq!(*caller.borrow(), Some(dest))); } + #[test] + fn is_contract_returns_proper_values() { + let bob_ch = MockLoader::insert(Call, |ctx, _| { + // Verify that BOB is a contract + assert!(ctx.ext.is_contract(&BOB)); + // Verify that ALICE is not a contract + assert!(!ctx.ext.is_contract(&ALICE)); + exec_success() + }); + + ExtBuilder::default().build().execute_with(|| { + let schedule = ::Schedule::get(); + place_contract(&BOB, bob_ch); + + let mut storage_meter = storage::meter::Meter::new(&ALICE, Some(0), 0).unwrap(); + let result = MockStack::run_call( + ALICE, + BOB, + &mut GasMeter::::new(GAS_LIMIT), + &mut storage_meter, + &schedule, + 0, + vec![], + None, + ); + assert_matches!(result, Ok(_)); + }); + } + + #[test] + fn caller_is_origin_returns_proper_values() { + let code_charlie = MockLoader::insert(Call, |ctx, _| { + // BOB is not the origin of the stack call + assert!(!ctx.ext.caller_is_origin()); + exec_success() + }); + + let code_bob = MockLoader::insert(Call, |ctx, _| { + // ALICE is the origin of the call stack + assert!(ctx.ext.caller_is_origin()); + // BOB calls CHARLIE + ctx.ext.call(0, CHARLIE, 0, vec![], true) + }); + + ExtBuilder::default().build().execute_with(|| { + let schedule = ::Schedule::get(); + place_contract(&BOB, code_bob); + place_contract(&CHARLIE, code_charlie); + let mut storage_meter = storage::meter::Meter::new(&ALICE, Some(0), 0).unwrap(); + // ALICE -> BOB (caller is origin) -> CHARLIE (caller is not origin) + let result = MockStack::run_call( + ALICE, + BOB, + &mut GasMeter::::new(GAS_LIMIT), + &mut storage_meter, + &schedule, + 0, + vec![0], + None, + ); + assert_matches!(result, Ok(_)); + }); + } + #[test] fn address_returns_proper_values() { let bob_ch = MockLoader::insert(Call, |ctx, _| { diff --git a/frame/contracts/src/schedule.rs b/frame/contracts/src/schedule.rs index f8ca182aea58..266c0a6e2748 100644 --- a/frame/contracts/src/schedule.rs +++ b/frame/contracts/src/schedule.rs @@ -256,6 +256,12 @@ pub struct HostFnWeights { /// Weight of calling `seal_caller`. pub caller: Weight, + /// Weight of calling `seal_is_contract`. + pub is_contract: Weight, + + /// Weight of calling `seal_caller_is_origin`. + pub caller_is_origin: Weight, + /// Weight of calling `seal_address`. pub address: Weight, @@ -571,6 +577,8 @@ impl Default for HostFnWeights { fn default() -> Self { Self { caller: cost_batched!(seal_caller), + is_contract: cost_batched!(seal_is_contract), + caller_is_origin: cost_batched!(seal_caller_is_origin), address: cost_batched!(seal_address), gas_left: cost_batched!(seal_gas_left), balance: cost_batched!(seal_balance), diff --git a/frame/contracts/src/wasm/mod.rs b/frame/contracts/src/wasm/mod.rs index 41e940bcd9b6..7c98ee7cf5b1 100644 --- a/frame/contracts/src/wasm/mod.rs +++ b/frame/contracts/src/wasm/mod.rs @@ -409,6 +409,12 @@ mod tests { fn caller(&self) -> &AccountIdOf { &ALICE } + fn is_contract(&self, _address: &AccountIdOf) -> bool { + true + } + fn caller_is_origin(&self) -> bool { + false + } fn address(&self) -> &AccountIdOf { &BOB } @@ -2240,4 +2246,80 @@ mod tests { let result = execute(CODE, [2u8; 32].encode(), &mut ext).unwrap(); assert_eq!(u32::from_le_bytes(result.data.0.try_into().unwrap()), 0,); } + + #[test] + #[cfg(feature = "unstable-interface")] + fn is_contract_works() { + const CODE_IS_CONTRACT: &str = r#" +;; This runs `is_contract` check on zero account address +(module + (import "__unstable__" "seal_is_contract" (func $seal_is_contract (param i32) (result i32))) + (import "seal0" "seal_return" (func $seal_return (param i32 i32 i32))) + (import "env" "memory" (memory 1 1)) + + ;; [0, 32) zero-adress + (data (i32.const 0) + "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00" + "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00" + ) + + ;; [32, 36) here we store the return code of the `seal_is_contract` + + (func (export "deploy")) + + (func (export "call") + (i32.store + (i32.const 32) + (call $seal_is_contract + (i32.const 0) ;; ptr to destination address + ) + ) + ;; exit with success and take `seal_is_contract` return code to the output buffer + (call $seal_return (i32.const 0) (i32.const 32) (i32.const 4)) + ) +) +"#; + let output = execute(CODE_IS_CONTRACT, vec![], MockExt::default()).unwrap(); + + // The mock ext just always returns 1u32 (`true`). + assert_eq!( + output, + ExecReturnValue { flags: ReturnFlags::empty(), data: Bytes(1u32.encode()) }, + ); + } + + #[test] + #[cfg(feature = "unstable-interface")] + fn caller_is_origin_works() { + const CODE_CALLER_IS_ORIGIN: &str = r#" +;; This runs `caller_is_origin` check on zero account address +(module + (import "__unstable__" "seal_caller_is_origin" (func $seal_caller_is_origin (result i32))) + (import "seal0" "seal_return" (func $seal_return (param i32 i32 i32))) + (import "env" "memory" (memory 1 1)) + + ;; [0, 4) here the return code of the `seal_caller_is_origin` will be stored + ;; we initialize it with non-zero value to be sure that it's being overwritten below + (data (i32.const 0) "\10\10\10\10") + + (func (export "deploy")) + + (func (export "call") + (i32.store + (i32.const 0) + (call $seal_caller_is_origin) + ) + ;; exit with success and take `seal_caller_is_origin` return code to the output buffer + (call $seal_return (i32.const 0) (i32.const 0) (i32.const 4)) + ) +) +"#; + let output = execute(CODE_CALLER_IS_ORIGIN, vec![], MockExt::default()).unwrap(); + + // The mock ext just always returns 0u32 (`false`) + assert_eq!( + output, + ExecReturnValue { flags: ReturnFlags::empty(), data: Bytes(0u32.encode()) }, + ); + } } diff --git a/frame/contracts/src/wasm/runtime.rs b/frame/contracts/src/wasm/runtime.rs index 13aa93430697..194d5ffbaaf4 100644 --- a/frame/contracts/src/wasm/runtime.rs +++ b/frame/contracts/src/wasm/runtime.rs @@ -138,6 +138,12 @@ pub enum RuntimeCosts { MeteringBlock(u32), /// Weight of calling `seal_caller`. Caller, + /// Weight of calling `seal_is_contract`. + #[cfg(feature = "unstable-interface")] + IsContract, + /// Weight of calling `seal_caller_is_origin`. + #[cfg(feature = "unstable-interface")] + CallerIsOrigin, /// Weight of calling `seal_address`. Address, /// Weight of calling `seal_gas_left`. @@ -225,6 +231,10 @@ impl RuntimeCosts { let weight = match *self { MeteringBlock(amount) => s.gas.saturating_add(amount.into()), Caller => s.caller, + #[cfg(feature = "unstable-interface")] + IsContract => s.is_contract, + #[cfg(feature = "unstable-interface")] + CallerIsOrigin => s.caller_is_origin, Address => s.address, GasLeft => s.gas_left, Balance => s.balance, @@ -1254,6 +1264,37 @@ define_env!(Env, , )?) }, + // Checks whether a specified address belongs to a contract. + // + // # Parameters + // + // - account_ptr: a pointer to the address of the beneficiary account + // Should be decodable as an `T::AccountId`. Traps otherwise. + // + // Returned value is a u32-encoded boolean: (0 = false, 1 = true). + [__unstable__] seal_is_contract(ctx, account_ptr: u32) -> u32 => { + ctx.charge_gas(RuntimeCosts::IsContract)?; + let address: <::T as frame_system::Config>::AccountId = + ctx.read_sandbox_memory_as(account_ptr)?; + + Ok(ctx.ext.is_contract(&address) as u32) + }, + + // Checks whether the caller of the current contract is the origin of the whole call stack. + // + // Prefer this over `seal_is_contract` when checking whether your contract is being called by a contract + // or a plain account. The reason is that it performs better since it does not need to + // do any storage lookups. + // + // A return value of`true` indicates that this contract is being called by a plain account + // and `false` indicates that the caller is another contract. + // + // Returned value is a u32-encoded boolean: (0 = false, 1 = true). + [__unstable__] seal_caller_is_origin(ctx) -> u32 => { + ctx.charge_gas(RuntimeCosts::CallerIsOrigin)?; + Ok(ctx.ext.caller_is_origin() as u32) + }, + // Stores the address of the current contract into the supplied buffer. // // The value is stored to linear memory at the address pointed to by `out_ptr`. diff --git a/frame/contracts/src/weights.rs b/frame/contracts/src/weights.rs index 24a42cc10649..b58660b694ca 100644 --- a/frame/contracts/src/weights.rs +++ b/frame/contracts/src/weights.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_contracts //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-31, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-02-04, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -55,6 +55,8 @@ pub trait WeightInfo { fn upload_code(c: u32, ) -> Weight; fn remove_code() -> Weight; fn seal_caller(r: u32, ) -> Weight; + fn seal_is_contract(r: u32, ) -> Weight; + fn seal_caller_is_origin(r: u32, ) -> Weight; fn seal_address(r: u32, ) -> Weight; fn seal_gas_left(r: u32, ) -> Weight; fn seal_balance(r: u32, ) -> Weight; @@ -156,14 +158,14 @@ pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize() -> Weight { - (1_642_000 as Weight) + (1_640_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn on_initialize_per_trie_key(k: u32, ) -> Weight { - (7_854_000 as Weight) + (6_385_000 as Weight) // Standard Error: 0 - .saturating_add((742_000 as Weight).saturating_mul(k as Weight)) + .saturating_add((748_000 as Weight).saturating_mul(k as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) @@ -171,17 +173,17 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize_per_queue_item(q: u32, ) -> Weight { (0 as Weight) - // Standard Error: 6_000 - .saturating_add((2_216_000 as Weight).saturating_mul(q as Weight)) + // Standard Error: 5_000 + .saturating_add((2_304_000 as Weight).saturating_mul(q as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Contracts PristineCode (r:1 w:0) // Storage: Contracts CodeStorage (r:0 w:1) fn reinstrument(c: u32, ) -> Weight { - (17_413_000 as Weight) - // Standard Error: 39_000 - .saturating_add((64_495_000 as Weight).saturating_mul(c as Weight)) + (22_923_000 as Weight) + // Standard Error: 33_000 + .saturating_add((65_851_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -190,9 +192,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call_with_code_kb(c: u32, ) -> Weight { - (209_071_000 as Weight) - // Standard Error: 47_000 - .saturating_add((56_555_000 as Weight).saturating_mul(c as Weight)) + (209_577_000 as Weight) + // Standard Error: 53_000 + .saturating_add((61_341_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -204,11 +206,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn instantiate_with_code(c: u32, s: u32, ) -> Weight { - (210_420_000 as Weight) - // Standard Error: 133_000 - .saturating_add((145_601_000 as Weight).saturating_mul(c as Weight)) - // Standard Error: 8_000 - .saturating_add((1_760_000 as Weight).saturating_mul(s as Weight)) + (240_302_000 as Weight) + // Standard Error: 119_000 + .saturating_add((151_894_000 as Weight).saturating_mul(c as Weight)) + // Standard Error: 7_000 + .saturating_add((1_740_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } @@ -219,9 +221,9 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn instantiate(s: u32, ) -> Weight { - (173_397_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_714_000 as Weight).saturating_mul(s as Weight)) + (172_047_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_729_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } @@ -230,7 +232,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call() -> Weight { - (140_169_000 as Weight) + (139_349_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -238,9 +240,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn upload_code(c: u32, ) -> Weight { - (49_076_000 as Weight) - // Standard Error: 37_000 - .saturating_add((67_150_000 as Weight).saturating_mul(c as Weight)) + (50_449_000 as Weight) + // Standard Error: 45_000 + .saturating_add((68_254_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -248,7 +250,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:0 w:1) // Storage: Contracts PristineCode (r:0 w:1) fn remove_code() -> Weight { - (24_318_000 as Weight) + (24_576_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -257,9 +259,32 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_caller(r: u32, ) -> Weight { - (208_256_000 as Weight) - // Standard Error: 116_000 - .saturating_add((49_878_000 as Weight).saturating_mul(r as Weight)) + (220_059_000 as Weight) + // Standard Error: 128_000 + .saturating_add((49_607_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + // Storage: System Account (r:1 w:0) + // Storage: Contracts ContractInfoOf (r:1 w:1) + // Storage: Contracts CodeStorage (r:1 w:0) + // Storage: Timestamp Now (r:1 w:0) + fn seal_is_contract(r: u32, ) -> Weight { + (84_138_000 as Weight) + // Standard Error: 896_000 + .saturating_add((375_553_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + // Storage: System Account (r:1 w:0) + // Storage: Contracts ContractInfoOf (r:1 w:1) + // Storage: Contracts CodeStorage (r:1 w:0) + // Storage: Timestamp Now (r:1 w:0) + fn seal_caller_is_origin(r: u32, ) -> Weight { + (222_496_000 as Weight) + // Standard Error: 119_000 + .saturating_add((22_340_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -268,9 +293,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_address(r: u32, ) -> Weight { - (230_530_000 as Weight) - // Standard Error: 132_000 - .saturating_add((47_902_000 as Weight).saturating_mul(r as Weight)) + (221_446_000 as Weight) + // Standard Error: 131_000 + .saturating_add((49_401_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -279,9 +304,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas_left(r: u32, ) -> Weight { - (219_027_000 as Weight) - // Standard Error: 108_000 - .saturating_add((48_039_000 as Weight).saturating_mul(r as Weight)) + (220_964_000 as Weight) + // Standard Error: 132_000 + .saturating_add((49_230_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -290,9 +315,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_balance(r: u32, ) -> Weight { - (219_036_000 as Weight) - // Standard Error: 152_000 - .saturating_add((137_047_000 as Weight).saturating_mul(r as Weight)) + (229_399_000 as Weight) + // Standard Error: 166_000 + .saturating_add((137_407_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -301,9 +326,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_value_transferred(r: u32, ) -> Weight { - (214_401_000 as Weight) - // Standard Error: 96_000 - .saturating_add((48_435_000 as Weight).saturating_mul(r as Weight)) + (220_103_000 as Weight) + // Standard Error: 133_000 + .saturating_add((49_410_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -312,9 +337,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_minimum_balance(r: u32, ) -> Weight { - (216_939_000 as Weight) - // Standard Error: 106_000 - .saturating_add((48_198_000 as Weight).saturating_mul(r as Weight)) + (228_143_000 as Weight) + // Standard Error: 151_000 + .saturating_add((48_608_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -323,9 +348,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_block_number(r: u32, ) -> Weight { - (216_637_000 as Weight) - // Standard Error: 86_000 - .saturating_add((47_819_000 as Weight).saturating_mul(r as Weight)) + (223_899_000 as Weight) + // Standard Error: 142_000 + .saturating_add((48_841_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -334,9 +359,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_now(r: u32, ) -> Weight { - (214_863_000 as Weight) - // Standard Error: 110_000 - .saturating_add((48_208_000 as Weight).saturating_mul(r as Weight)) + (224_974_000 as Weight) + // Standard Error: 148_000 + .saturating_add((48_902_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -346,9 +371,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0) fn seal_weight_to_fee(r: u32, ) -> Weight { - (216_494_000 as Weight) - // Standard Error: 141_000 - .saturating_add((120_736_000 as Weight).saturating_mul(r as Weight)) + (227_556_000 as Weight) + // Standard Error: 151_000 + .saturating_add((121_252_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -357,9 +382,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas(r: u32, ) -> Weight { - (123_867_000 as Weight) - // Standard Error: 33_000 - .saturating_add((24_578_000 as Weight).saturating_mul(r as Weight)) + (127_975_000 as Weight) + // Standard Error: 57_000 + .saturating_add((24_843_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -368,9 +393,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input(r: u32, ) -> Weight { - (215_578_000 as Weight) - // Standard Error: 108_000 - .saturating_add((47_512_000 as Weight).saturating_mul(r as Weight)) + (224_592_000 as Weight) + // Standard Error: 141_000 + .saturating_add((48_296_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -379,9 +404,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input_per_kb(n: u32, ) -> Weight { - (297_663_000 as Weight) + (296_995_000 as Weight) // Standard Error: 3_000 - .saturating_add((11_863_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((11_884_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -389,10 +414,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) - fn seal_return(r: u32, ) -> Weight { - (209_709_000 as Weight) - // Standard Error: 75_000 - .saturating_add((1_783_000 as Weight).saturating_mul(r as Weight)) + fn seal_return(_r: u32, ) -> Weight { + (224_322_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -401,9 +424,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return_per_kb(n: u32, ) -> Weight { - (214_403_000 as Weight) - // Standard Error: 0 - .saturating_add((197_000 as Weight).saturating_mul(n as Weight)) + (216_240_000 as Weight) + // Standard Error: 1_000 + .saturating_add((206_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -414,9 +437,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts DeletionQueue (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_terminate(r: u32, ) -> Weight { - (214_454_000 as Weight) - // Standard Error: 656_000 - .saturating_add((50_641_000 as Weight).saturating_mul(r as Weight)) + (219_637_000 as Weight) + // Standard Error: 3_916_000 + .saturating_add((51_769_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((4 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -428,9 +451,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) fn seal_random(r: u32, ) -> Weight { - (214_140_000 as Weight) - // Standard Error: 169_000 - .saturating_add((158_778_000 as Weight).saturating_mul(r as Weight)) + (221_470_000 as Weight) + // Standard Error: 154_000 + .saturating_add((158_758_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -439,9 +462,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_deposit_event(r: u32, ) -> Weight { - (225_998_000 as Weight) - // Standard Error: 171_000 - .saturating_add((280_296_000 as Weight).saturating_mul(r as Weight)) + (228_674_000 as Weight) + // Standard Error: 203_000 + .saturating_add((287_195_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -451,11 +474,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: System EventTopics (r:100 w:100) fn seal_deposit_event_per_topic_and_kb(t: u32, n: u32, ) -> Weight { - (491_432_000 as Weight) - // Standard Error: 1_992_000 - .saturating_add((288_376_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 392_000 - .saturating_add((82_805_000 as Weight).saturating_mul(n as Weight)) + (507_091_000 as Weight) + // Standard Error: 1_863_000 + .saturating_add((291_858_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 367_000 + .saturating_add((83_459_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(t as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -466,17 +489,17 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_debug_message(r: u32, ) -> Weight { - (130_861_000 as Weight) - // Standard Error: 74_000 - .saturating_add((40_268_000 as Weight).saturating_mul(r as Weight)) + (133_592_000 as Weight) + // Standard Error: 87_000 + .saturating_add((41_718_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage(r: u32, ) -> Weight { - (38_843_000 as Weight) - // Standard Error: 1_044_000 - .saturating_add((408_027_000 as Weight).saturating_mul(r as Weight)) + (44_719_000 as Weight) + // Standard Error: 1_036_000 + .saturating_add((407_521_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -484,25 +507,25 @@ impl WeightInfo for SubstrateWeight { } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage_per_new_kb(n: u32, ) -> Weight { - (610_782_000 as Weight) - // Standard Error: 265_000 - .saturating_add((28_221_000 as Weight).saturating_mul(n as Weight)) + (606_108_000 as Weight) + // Standard Error: 315_000 + .saturating_add((29_136_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage_per_old_kb(n: u32, ) -> Weight { - (625_031_000 as Weight) - // Standard Error: 319_000 - .saturating_add((11_126_000 as Weight).saturating_mul(n as Weight)) + (634_330_000 as Weight) + // Standard Error: 281_000 + .saturating_add((10_741_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage(r: u32, ) -> Weight { - (78_566_000 as Weight) - // Standard Error: 970_000 - .saturating_add((384_877_000 as Weight).saturating_mul(r as Weight)) + (89_750_000 as Weight) + // Standard Error: 924_000 + .saturating_add((382_525_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -510,51 +533,51 @@ impl WeightInfo for SubstrateWeight { } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage_per_kb(n: u32, ) -> Weight { - (601_558_000 as Weight) - // Standard Error: 280_000 - .saturating_add((11_378_000 as Weight).saturating_mul(n as Weight)) + (616_463_000 as Weight) + // Standard Error: 260_000 + .saturating_add((10_373_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage(r: u32, ) -> Weight { - (112_328_000 as Weight) - // Standard Error: 668_000 - .saturating_add((323_031_000 as Weight).saturating_mul(r as Weight)) + (116_340_000 as Weight) + // Standard Error: 633_000 + .saturating_add((322_054_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage_per_kb(n: u32, ) -> Weight { - (556_303_000 as Weight) - // Standard Error: 346_000 - .saturating_add((64_170_000 as Weight).saturating_mul(n as Weight)) + (563_077_000 as Weight) + // Standard Error: 340_000 + .saturating_add((63_889_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(104 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_contains_storage(r: u32, ) -> Weight { - (106_572_000 as Weight) - // Standard Error: 691_000 - .saturating_add((294_964_000 as Weight).saturating_mul(r as Weight)) + (118_832_000 as Weight) + // Standard Error: 595_000 + .saturating_add((291_817_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_contains_storage_per_kb(n: u32, ) -> Weight { - (508_339_000 as Weight) - // Standard Error: 245_000 - .saturating_add((10_675_000 as Weight).saturating_mul(n as Weight)) + (520_386_000 as Weight) + // Standard Error: 297_000 + .saturating_add((10_076_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(104 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage(r: u32, ) -> Weight { - (88_096_000 as Weight) - // Standard Error: 927_000 - .saturating_add((415_543_000 as Weight).saturating_mul(r as Weight)) + (85_377_000 as Weight) + // Standard Error: 847_000 + .saturating_add((419_438_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -562,9 +585,9 @@ impl WeightInfo for SubstrateWeight { } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage_per_kb(n: u32, ) -> Weight { - (650_912_000 as Weight) - // Standard Error: 359_000 - .saturating_add((65_030_000 as Weight).saturating_mul(n as Weight)) + (666_218_000 as Weight) + // Standard Error: 294_000 + .saturating_add((64_627_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().writes(103 as Weight)) } @@ -573,9 +596,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_transfer(r: u32, ) -> Weight { - (102_673_000 as Weight) - // Standard Error: 1_159_000 - .saturating_add((1_711_312_000 as Weight).saturating_mul(r as Weight)) + (108_224_000 as Weight) + // Standard Error: 1_042_000 + .saturating_add((1_723_539_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -587,8 +610,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) fn seal_call(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 3_592_000 - .saturating_add((19_565_726_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 7_843_000 + .saturating_add((19_825_093_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -599,13 +622,13 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:2 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_call_per_transfer_input_output_kb(t: u32, i: u32, o: u32, ) -> Weight { - (19_665_171_000 as Weight) - // Standard Error: 27_641_000 - .saturating_add((2_089_637_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 9_000 - .saturating_add((20_165_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 10_000 - .saturating_add((31_728_000 as Weight).saturating_mul(o as Weight)) + (20_190_331_000 as Weight) + // Standard Error: 75_647_000 + .saturating_add((2_369_225_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 27_000 + .saturating_add((19_831_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 28_000 + .saturating_add((31_191_000 as Weight).saturating_mul(o as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().reads((101 as Weight).saturating_mul(t as Weight))) .saturating_add(T::DbWeight::get().writes(101 as Weight)) @@ -619,8 +642,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts OwnerInfoOf (r:100 w:100) fn seal_instantiate(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 48_640_000 - .saturating_add((27_307_450_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 50_368_000 + .saturating_add((27_757_564_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().reads((400 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -633,13 +656,13 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts AccountCounter (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_instantiate_per_input_output_salt_kb(i: u32, o: u32, s: u32, ) -> Weight { - (24_821_248_000 as Weight) - // Standard Error: 26_000 - .saturating_add((20_118_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 26_000 - .saturating_add((31_616_000 as Weight).saturating_mul(o as Weight)) - // Standard Error: 26_000 - .saturating_add((157_567_000 as Weight).saturating_mul(s as Weight)) + (25_199_228_000 as Weight) + // Standard Error: 36_000 + .saturating_add((19_598_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 36_000 + .saturating_add((30_986_000 as Weight).saturating_mul(o as Weight)) + // Standard Error: 36_000 + .saturating_add((158_016_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(208 as Weight)) .saturating_add(T::DbWeight::get().writes(206 as Weight)) } @@ -648,9 +671,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256(r: u32, ) -> Weight { - (213_816_000 as Weight) - // Standard Error: 147_000 - .saturating_add((80_336_000 as Weight).saturating_mul(r as Weight)) + (222_984_000 as Weight) + // Standard Error: 155_000 + .saturating_add((80_649_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -659,9 +682,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256_per_kb(n: u32, ) -> Weight { - (309_038_000 as Weight) - // Standard Error: 23_000 - .saturating_add((465_306_000 as Weight).saturating_mul(n as Weight)) + (393_726_000 as Weight) + // Standard Error: 36_000 + .saturating_add((463_983_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -670,9 +693,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256(r: u32, ) -> Weight { - (212_825_000 as Weight) - // Standard Error: 143_000 - .saturating_add((91_947_000 as Weight).saturating_mul(r as Weight)) + (217_461_000 as Weight) + // Standard Error: 146_000 + .saturating_add((92_540_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -681,9 +704,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256_per_kb(n: u32, ) -> Weight { - (329_548_000 as Weight) + (271_742_000 as Weight) // Standard Error: 19_000 - .saturating_add((306_729_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((307_055_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -692,9 +715,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256(r: u32, ) -> Weight { - (215_907_000 as Weight) - // Standard Error: 129_000 - .saturating_add((63_477_000 as Weight).saturating_mul(r as Weight)) + (220_664_000 as Weight) + // Standard Error: 145_000 + .saturating_add((64_516_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -703,9 +726,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256_per_kb(n: u32, ) -> Weight { - (423_811_000 as Weight) - // Standard Error: 16_000 - .saturating_add((119_607_000 as Weight).saturating_mul(n as Weight)) + (287_500_000 as Weight) + // Standard Error: 12_000 + .saturating_add((119_931_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -714,9 +737,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128(r: u32, ) -> Weight { - (214_747_000 as Weight) - // Standard Error: 115_000 - .saturating_add((62_904_000 as Weight).saturating_mul(r as Weight)) + (214_922_000 as Weight) + // Standard Error: 122_000 + .saturating_add((64_236_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -725,9 +748,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128_per_kb(n: u32, ) -> Weight { - (437_217_000 as Weight) - // Standard Error: 19_000 - .saturating_add((120_126_000 as Weight).saturating_mul(n as Weight)) + (251_648_000 as Weight) + // Standard Error: 13_000 + .saturating_add((120_105_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -736,266 +759,266 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_ecdsa_recover(r: u32, ) -> Weight { - (195_980_000 as Weight) - // Standard Error: 1_262_000 - .saturating_add((15_428_805_000 as Weight).saturating_mul(r as Weight)) + (124_760_000 as Weight) + // Standard Error: 1_397_000 + .saturating_add((15_387_180_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn instr_i64const(r: u32, ) -> Weight { - (74_569_000 as Weight) - // Standard Error: 1_000 - .saturating_add((589_000 as Weight).saturating_mul(r as Weight)) + (75_287_000 as Weight) + // Standard Error: 11_000 + .saturating_add((569_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64load(r: u32, ) -> Weight { - (74_212_000 as Weight) - // Standard Error: 0 - .saturating_add((1_325_000 as Weight).saturating_mul(r as Weight)) + (74_251_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_306_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64store(r: u32, ) -> Weight { - (74_505_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_423_000 as Weight).saturating_mul(r as Weight)) + (75_072_000 as Weight) + // Standard Error: 4_000 + .saturating_add((1_386_000 as Weight).saturating_mul(r as Weight)) } fn instr_select(r: u32, ) -> Weight { - (74_005_000 as Weight) - // Standard Error: 3_000 - .saturating_add((1_785_000 as Weight).saturating_mul(r as Weight)) + (73_811_000 as Weight) + // Standard Error: 0 + .saturating_add((1_783_000 as Weight).saturating_mul(r as Weight)) } fn instr_if(r: u32, ) -> Weight { - (74_212_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_890_000 as Weight).saturating_mul(r as Weight)) + (73_901_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_886_000 as Weight).saturating_mul(r as Weight)) } fn instr_br(r: u32, ) -> Weight { - (74_102_000 as Weight) - // Standard Error: 2_000 - .saturating_add((896_000 as Weight).saturating_mul(r as Weight)) + (73_720_000 as Weight) + // Standard Error: 1_000 + .saturating_add((903_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_if(r: u32, ) -> Weight { - (73_523_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_456_000 as Weight).saturating_mul(r as Weight)) + (73_534_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_459_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table(r: u32, ) -> Weight { - (73_307_000 as Weight) - // Standard Error: 4_000 - .saturating_add((1_594_000 as Weight).saturating_mul(r as Weight)) + (73_281_000 as Weight) + // Standard Error: 8_000 + .saturating_add((1_584_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table_per_entry(e: u32, ) -> Weight { - (76_272_000 as Weight) - // Standard Error: 0 - .saturating_add((5_000 as Weight).saturating_mul(e as Weight)) + (76_135_000 as Weight) + // Standard Error: 1_000 + .saturating_add((6_000 as Weight).saturating_mul(e as Weight)) } fn instr_call(r: u32, ) -> Weight { - (73_390_000 as Weight) + (75_938_000 as Weight) // Standard Error: 23_000 - .saturating_add((16_936_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((17_156_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect(r: u32, ) -> Weight { - (89_331_000 as Weight) - // Standard Error: 30_000 - .saturating_add((28_104_000 as Weight).saturating_mul(r as Weight)) + (85_864_000 as Weight) + // Standard Error: 28_000 + .saturating_add((28_343_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect_per_param(p: u32, ) -> Weight { - (117_023_000 as Weight) - // Standard Error: 3_000 - .saturating_add((914_000 as Weight).saturating_mul(p as Weight)) + (119_795_000 as Weight) + // Standard Error: 1_000 + .saturating_add((911_000 as Weight).saturating_mul(p as Weight)) } fn instr_local_get(r: u32, ) -> Weight { - (74_727_000 as Weight) + (74_750_000 as Weight) // Standard Error: 1_000 - .saturating_add((618_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((613_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_set(r: u32, ) -> Weight { - (74_893_000 as Weight) - // Standard Error: 1_000 - .saturating_add((674_000 as Weight).saturating_mul(r as Weight)) + (74_831_000 as Weight) + // Standard Error: 2_000 + .saturating_add((672_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_tee(r: u32, ) -> Weight { - (74_552_000 as Weight) + (74_314_000 as Weight) // Standard Error: 1_000 - .saturating_add((898_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((902_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_get(r: u32, ) -> Weight { - (77_355_000 as Weight) + (77_040_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_146_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_161_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_set(r: u32, ) -> Weight { - (77_055_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_363_000 as Weight).saturating_mul(r as Weight)) + (76_770_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_372_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_current(r: u32, ) -> Weight { - (74_648_000 as Weight) - // Standard Error: 2_000 - .saturating_add((652_000 as Weight).saturating_mul(r as Weight)) + (74_010_000 as Weight) + // Standard Error: 1_000 + .saturating_add((665_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_grow(r: u32, ) -> Weight { - (73_777_000 as Weight) - // Standard Error: 226_000 - .saturating_add((187_252_000 as Weight).saturating_mul(r as Weight)) + (73_597_000 as Weight) + // Standard Error: 929_000 + .saturating_add((183_940_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64clz(r: u32, ) -> Weight { - (74_332_000 as Weight) - // Standard Error: 1_000 - .saturating_add((897_000 as Weight).saturating_mul(r as Weight)) + (74_488_000 as Weight) + // Standard Error: 4_000 + .saturating_add((893_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ctz(r: u32, ) -> Weight { - (74_265_000 as Weight) - // Standard Error: 1_000 - .saturating_add((898_000 as Weight).saturating_mul(r as Weight)) + (74_024_000 as Weight) + // Standard Error: 5_000 + .saturating_add((908_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64popcnt(r: u32, ) -> Weight { - (74_475_000 as Weight) - // Standard Error: 2_000 - .saturating_add((892_000 as Weight).saturating_mul(r as Weight)) + (74_084_000 as Weight) + // Standard Error: 1_000 + .saturating_add((895_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eqz(r: u32, ) -> Weight { - (74_297_000 as Weight) - // Standard Error: 1_000 - .saturating_add((918_000 as Weight).saturating_mul(r as Weight)) + (74_250_000 as Weight) + // Standard Error: 2_000 + .saturating_add((916_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendsi32(r: u32, ) -> Weight { - (74_146_000 as Weight) + (74_027_000 as Weight) // Standard Error: 1_000 - .saturating_add((884_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((883_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendui32(r: u32, ) -> Weight { - (74_361_000 as Weight) + (74_201_000 as Weight) // Standard Error: 1_000 - .saturating_add((877_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((879_000 as Weight).saturating_mul(r as Weight)) } fn instr_i32wrapi64(r: u32, ) -> Weight { - (74_554_000 as Weight) + (74_116_000 as Weight) // Standard Error: 1_000 - .saturating_add((884_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((892_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eq(r: u32, ) -> Weight { - (74_169_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_357_000 as Weight).saturating_mul(r as Weight)) + (74_109_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_358_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ne(r: u32, ) -> Weight { - (74_164_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_357_000 as Weight).saturating_mul(r as Weight)) + (73_962_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_363_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64lts(r: u32, ) -> Weight { - (74_058_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_362_000 as Weight).saturating_mul(r as Weight)) + (73_977_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_360_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ltu(r: u32, ) -> Weight { - (74_039_000 as Weight) + (74_046_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_362_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_360_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gts(r: u32, ) -> Weight { - (75_055_000 as Weight) - // Standard Error: 4_000 - .saturating_add((1_338_000 as Weight).saturating_mul(r as Weight)) + (73_912_000 as Weight) + // Standard Error: 0 + .saturating_add((1_362_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gtu(r: u32, ) -> Weight { - (74_536_000 as Weight) - // Standard Error: 4_000 + (73_918_000 as Weight) + // Standard Error: 2_000 .saturating_add((1_367_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64les(r: u32, ) -> Weight { - (74_177_000 as Weight) + (73_953_000 as Weight) // Standard Error: 2_000 - .saturating_add((1_358_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_363_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64leu(r: u32, ) -> Weight { - (74_080_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_370_000 as Weight).saturating_mul(r as Weight)) + (74_855_000 as Weight) + // Standard Error: 4_000 + .saturating_add((1_347_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ges(r: u32, ) -> Weight { - (74_237_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_356_000 as Weight).saturating_mul(r as Weight)) + (73_917_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_364_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64geu(r: u32, ) -> Weight { - (74_049_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_362_000 as Weight).saturating_mul(r as Weight)) + (73_949_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_361_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64add(r: u32, ) -> Weight { - (74_186_000 as Weight) + (73_726_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_335_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_347_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64sub(r: u32, ) -> Weight { - (74_268_000 as Weight) + (73_921_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_339_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_345_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64mul(r: u32, ) -> Weight { - (74_334_000 as Weight) + (73_924_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_331_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_341_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divs(r: u32, ) -> Weight { - (74_285_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_997_000 as Weight).saturating_mul(r as Weight)) + (73_842_000 as Weight) + // Standard Error: 2_000 + .saturating_add((2_011_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divu(r: u32, ) -> Weight { - (74_002_000 as Weight) + (73_932_000 as Weight) // Standard Error: 1_000 - .saturating_add((2_027_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_057_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rems(r: u32, ) -> Weight { - (74_281_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_977_000 as Weight).saturating_mul(r as Weight)) + (74_028_000 as Weight) + // Standard Error: 2_000 + .saturating_add((2_001_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64remu(r: u32, ) -> Weight { - (74_160_000 as Weight) - // Standard Error: 1_000 - .saturating_add((2_038_000 as Weight).saturating_mul(r as Weight)) + (73_784_000 as Weight) + // Standard Error: 2_000 + .saturating_add((2_059_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64and(r: u32, ) -> Weight { - (74_097_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_339_000 as Weight).saturating_mul(r as Weight)) + (74_169_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_334_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64or(r: u32, ) -> Weight { - (74_020_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_341_000 as Weight).saturating_mul(r as Weight)) + (73_982_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_340_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64xor(r: u32, ) -> Weight { - (73_890_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_351_000 as Weight).saturating_mul(r as Weight)) + (74_310_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_329_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shl(r: u32, ) -> Weight { - (74_139_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_355_000 as Weight).saturating_mul(r as Weight)) + (73_861_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_362_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shrs(r: u32, ) -> Weight { - (74_189_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_352_000 as Weight).saturating_mul(r as Weight)) + (73_787_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_364_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shru(r: u32, ) -> Weight { - (74_055_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_359_000 as Weight).saturating_mul(r as Weight)) + (73_886_000 as Weight) + // Standard Error: 7_000 + .saturating_add((1_372_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotl(r: u32, ) -> Weight { - (74_074_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_357_000 as Weight).saturating_mul(r as Weight)) + (73_860_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_362_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotr(r: u32, ) -> Weight { - (74_005_000 as Weight) + (73_917_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_357_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_356_000 as Weight).saturating_mul(r as Weight)) } } @@ -1003,14 +1026,14 @@ impl WeightInfo for SubstrateWeight { impl WeightInfo for () { // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize() -> Weight { - (1_642_000 as Weight) + (1_640_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn on_initialize_per_trie_key(k: u32, ) -> Weight { - (7_854_000 as Weight) + (6_385_000 as Weight) // Standard Error: 0 - .saturating_add((742_000 as Weight).saturating_mul(k as Weight)) + .saturating_add((748_000 as Weight).saturating_mul(k as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) @@ -1018,17 +1041,17 @@ impl WeightInfo for () { // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize_per_queue_item(q: u32, ) -> Weight { (0 as Weight) - // Standard Error: 6_000 - .saturating_add((2_216_000 as Weight).saturating_mul(q as Weight)) + // Standard Error: 5_000 + .saturating_add((2_304_000 as Weight).saturating_mul(q as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Contracts PristineCode (r:1 w:0) // Storage: Contracts CodeStorage (r:0 w:1) fn reinstrument(c: u32, ) -> Weight { - (17_413_000 as Weight) - // Standard Error: 39_000 - .saturating_add((64_495_000 as Weight).saturating_mul(c as Weight)) + (22_923_000 as Weight) + // Standard Error: 33_000 + .saturating_add((65_851_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1037,9 +1060,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call_with_code_kb(c: u32, ) -> Weight { - (209_071_000 as Weight) - // Standard Error: 47_000 - .saturating_add((56_555_000 as Weight).saturating_mul(c as Weight)) + (209_577_000 as Weight) + // Standard Error: 53_000 + .saturating_add((61_341_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -1051,11 +1074,11 @@ impl WeightInfo for () { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn instantiate_with_code(c: u32, s: u32, ) -> Weight { - (210_420_000 as Weight) - // Standard Error: 133_000 - .saturating_add((145_601_000 as Weight).saturating_mul(c as Weight)) - // Standard Error: 8_000 - .saturating_add((1_760_000 as Weight).saturating_mul(s as Weight)) + (240_302_000 as Weight) + // Standard Error: 119_000 + .saturating_add((151_894_000 as Weight).saturating_mul(c as Weight)) + // Standard Error: 7_000 + .saturating_add((1_740_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } @@ -1066,9 +1089,9 @@ impl WeightInfo for () { // Storage: System Account (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn instantiate(s: u32, ) -> Weight { - (173_397_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_714_000 as Weight).saturating_mul(s as Weight)) + (172_047_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_729_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } @@ -1077,7 +1100,7 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call() -> Weight { - (140_169_000 as Weight) + (139_349_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -1085,9 +1108,9 @@ impl WeightInfo for () { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn upload_code(c: u32, ) -> Weight { - (49_076_000 as Weight) - // Standard Error: 37_000 - .saturating_add((67_150_000 as Weight).saturating_mul(c as Weight)) + (50_449_000 as Weight) + // Standard Error: 45_000 + .saturating_add((68_254_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -1095,7 +1118,7 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:0 w:1) // Storage: Contracts PristineCode (r:0 w:1) fn remove_code() -> Weight { - (24_318_000 as Weight) + (24_576_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -1104,9 +1127,32 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_caller(r: u32, ) -> Weight { - (208_256_000 as Weight) - // Standard Error: 116_000 - .saturating_add((49_878_000 as Weight).saturating_mul(r as Weight)) + (220_059_000 as Weight) + // Standard Error: 128_000 + .saturating_add((49_607_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + // Storage: System Account (r:1 w:0) + // Storage: Contracts ContractInfoOf (r:1 w:1) + // Storage: Contracts CodeStorage (r:1 w:0) + // Storage: Timestamp Now (r:1 w:0) + fn seal_is_contract(r: u32, ) -> Weight { + (84_138_000 as Weight) + // Standard Error: 896_000 + .saturating_add((375_553_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + // Storage: System Account (r:1 w:0) + // Storage: Contracts ContractInfoOf (r:1 w:1) + // Storage: Contracts CodeStorage (r:1 w:0) + // Storage: Timestamp Now (r:1 w:0) + fn seal_caller_is_origin(r: u32, ) -> Weight { + (222_496_000 as Weight) + // Standard Error: 119_000 + .saturating_add((22_340_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1115,9 +1161,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_address(r: u32, ) -> Weight { - (230_530_000 as Weight) - // Standard Error: 132_000 - .saturating_add((47_902_000 as Weight).saturating_mul(r as Weight)) + (221_446_000 as Weight) + // Standard Error: 131_000 + .saturating_add((49_401_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1126,9 +1172,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas_left(r: u32, ) -> Weight { - (219_027_000 as Weight) - // Standard Error: 108_000 - .saturating_add((48_039_000 as Weight).saturating_mul(r as Weight)) + (220_964_000 as Weight) + // Standard Error: 132_000 + .saturating_add((49_230_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1137,9 +1183,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_balance(r: u32, ) -> Weight { - (219_036_000 as Weight) - // Standard Error: 152_000 - .saturating_add((137_047_000 as Weight).saturating_mul(r as Weight)) + (229_399_000 as Weight) + // Standard Error: 166_000 + .saturating_add((137_407_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1148,9 +1194,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_value_transferred(r: u32, ) -> Weight { - (214_401_000 as Weight) - // Standard Error: 96_000 - .saturating_add((48_435_000 as Weight).saturating_mul(r as Weight)) + (220_103_000 as Weight) + // Standard Error: 133_000 + .saturating_add((49_410_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1159,9 +1205,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_minimum_balance(r: u32, ) -> Weight { - (216_939_000 as Weight) - // Standard Error: 106_000 - .saturating_add((48_198_000 as Weight).saturating_mul(r as Weight)) + (228_143_000 as Weight) + // Standard Error: 151_000 + .saturating_add((48_608_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1170,9 +1216,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_block_number(r: u32, ) -> Weight { - (216_637_000 as Weight) - // Standard Error: 86_000 - .saturating_add((47_819_000 as Weight).saturating_mul(r as Weight)) + (223_899_000 as Weight) + // Standard Error: 142_000 + .saturating_add((48_841_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1181,9 +1227,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_now(r: u32, ) -> Weight { - (214_863_000 as Weight) - // Standard Error: 110_000 - .saturating_add((48_208_000 as Weight).saturating_mul(r as Weight)) + (224_974_000 as Weight) + // Standard Error: 148_000 + .saturating_add((48_902_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1193,9 +1239,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0) fn seal_weight_to_fee(r: u32, ) -> Weight { - (216_494_000 as Weight) - // Standard Error: 141_000 - .saturating_add((120_736_000 as Weight).saturating_mul(r as Weight)) + (227_556_000 as Weight) + // Standard Error: 151_000 + .saturating_add((121_252_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1204,9 +1250,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas(r: u32, ) -> Weight { - (123_867_000 as Weight) - // Standard Error: 33_000 - .saturating_add((24_578_000 as Weight).saturating_mul(r as Weight)) + (127_975_000 as Weight) + // Standard Error: 57_000 + .saturating_add((24_843_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1215,9 +1261,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input(r: u32, ) -> Weight { - (215_578_000 as Weight) - // Standard Error: 108_000 - .saturating_add((47_512_000 as Weight).saturating_mul(r as Weight)) + (224_592_000 as Weight) + // Standard Error: 141_000 + .saturating_add((48_296_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1226,9 +1272,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input_per_kb(n: u32, ) -> Weight { - (297_663_000 as Weight) + (296_995_000 as Weight) // Standard Error: 3_000 - .saturating_add((11_863_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((11_884_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1236,10 +1282,8 @@ impl WeightInfo for () { // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) - fn seal_return(r: u32, ) -> Weight { - (209_709_000 as Weight) - // Standard Error: 75_000 - .saturating_add((1_783_000 as Weight).saturating_mul(r as Weight)) + fn seal_return(_r: u32, ) -> Weight { + (224_322_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1248,9 +1292,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return_per_kb(n: u32, ) -> Weight { - (214_403_000 as Weight) - // Standard Error: 0 - .saturating_add((197_000 as Weight).saturating_mul(n as Weight)) + (216_240_000 as Weight) + // Standard Error: 1_000 + .saturating_add((206_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1261,9 +1305,9 @@ impl WeightInfo for () { // Storage: Contracts DeletionQueue (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_terminate(r: u32, ) -> Weight { - (214_454_000 as Weight) - // Standard Error: 656_000 - .saturating_add((50_641_000 as Weight).saturating_mul(r as Weight)) + (219_637_000 as Weight) + // Standard Error: 3_916_000 + .saturating_add((51_769_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((4 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1275,9 +1319,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) fn seal_random(r: u32, ) -> Weight { - (214_140_000 as Weight) - // Standard Error: 169_000 - .saturating_add((158_778_000 as Weight).saturating_mul(r as Weight)) + (221_470_000 as Weight) + // Standard Error: 154_000 + .saturating_add((158_758_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1286,9 +1330,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_deposit_event(r: u32, ) -> Weight { - (225_998_000 as Weight) - // Standard Error: 171_000 - .saturating_add((280_296_000 as Weight).saturating_mul(r as Weight)) + (228_674_000 as Weight) + // Standard Error: 203_000 + .saturating_add((287_195_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1298,11 +1342,11 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: System EventTopics (r:100 w:100) fn seal_deposit_event_per_topic_and_kb(t: u32, n: u32, ) -> Weight { - (491_432_000 as Weight) - // Standard Error: 1_992_000 - .saturating_add((288_376_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 392_000 - .saturating_add((82_805_000 as Weight).saturating_mul(n as Weight)) + (507_091_000 as Weight) + // Standard Error: 1_863_000 + .saturating_add((291_858_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 367_000 + .saturating_add((83_459_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(t as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1313,17 +1357,17 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_debug_message(r: u32, ) -> Weight { - (130_861_000 as Weight) - // Standard Error: 74_000 - .saturating_add((40_268_000 as Weight).saturating_mul(r as Weight)) + (133_592_000 as Weight) + // Standard Error: 87_000 + .saturating_add((41_718_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage(r: u32, ) -> Weight { - (38_843_000 as Weight) - // Standard Error: 1_044_000 - .saturating_add((408_027_000 as Weight).saturating_mul(r as Weight)) + (44_719_000 as Weight) + // Standard Error: 1_036_000 + .saturating_add((407_521_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1331,25 +1375,25 @@ impl WeightInfo for () { } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage_per_new_kb(n: u32, ) -> Weight { - (610_782_000 as Weight) - // Standard Error: 265_000 - .saturating_add((28_221_000 as Weight).saturating_mul(n as Weight)) + (606_108_000 as Weight) + // Standard Error: 315_000 + .saturating_add((29_136_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage_per_old_kb(n: u32, ) -> Weight { - (625_031_000 as Weight) - // Standard Error: 319_000 - .saturating_add((11_126_000 as Weight).saturating_mul(n as Weight)) + (634_330_000 as Weight) + // Standard Error: 281_000 + .saturating_add((10_741_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage(r: u32, ) -> Weight { - (78_566_000 as Weight) - // Standard Error: 970_000 - .saturating_add((384_877_000 as Weight).saturating_mul(r as Weight)) + (89_750_000 as Weight) + // Standard Error: 924_000 + .saturating_add((382_525_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -1357,51 +1401,51 @@ impl WeightInfo for () { } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage_per_kb(n: u32, ) -> Weight { - (601_558_000 as Weight) - // Standard Error: 280_000 - .saturating_add((11_378_000 as Weight).saturating_mul(n as Weight)) + (616_463_000 as Weight) + // Standard Error: 260_000 + .saturating_add((10_373_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage(r: u32, ) -> Weight { - (112_328_000 as Weight) - // Standard Error: 668_000 - .saturating_add((323_031_000 as Weight).saturating_mul(r as Weight)) + (116_340_000 as Weight) + // Standard Error: 633_000 + .saturating_add((322_054_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage_per_kb(n: u32, ) -> Weight { - (556_303_000 as Weight) - // Standard Error: 346_000 - .saturating_add((64_170_000 as Weight).saturating_mul(n as Weight)) + (563_077_000 as Weight) + // Standard Error: 340_000 + .saturating_add((63_889_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(104 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_contains_storage(r: u32, ) -> Weight { - (106_572_000 as Weight) - // Standard Error: 691_000 - .saturating_add((294_964_000 as Weight).saturating_mul(r as Weight)) + (118_832_000 as Weight) + // Standard Error: 595_000 + .saturating_add((291_817_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_contains_storage_per_kb(n: u32, ) -> Weight { - (508_339_000 as Weight) - // Standard Error: 245_000 - .saturating_add((10_675_000 as Weight).saturating_mul(n as Weight)) + (520_386_000 as Weight) + // Standard Error: 297_000 + .saturating_add((10_076_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(104 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage(r: u32, ) -> Weight { - (88_096_000 as Weight) - // Standard Error: 927_000 - .saturating_add((415_543_000 as Weight).saturating_mul(r as Weight)) + (85_377_000 as Weight) + // Standard Error: 847_000 + .saturating_add((419_438_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -1409,9 +1453,9 @@ impl WeightInfo for () { } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage_per_kb(n: u32, ) -> Weight { - (650_912_000 as Weight) - // Standard Error: 359_000 - .saturating_add((65_030_000 as Weight).saturating_mul(n as Weight)) + (666_218_000 as Weight) + // Standard Error: 294_000 + .saturating_add((64_627_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().writes(103 as Weight)) } @@ -1420,9 +1464,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_transfer(r: u32, ) -> Weight { - (102_673_000 as Weight) - // Standard Error: 1_159_000 - .saturating_add((1_711_312_000 as Weight).saturating_mul(r as Weight)) + (108_224_000 as Weight) + // Standard Error: 1_042_000 + .saturating_add((1_723_539_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) @@ -1434,8 +1478,8 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) fn seal_call(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 3_592_000 - .saturating_add((19_565_726_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 7_843_000 + .saturating_add((19_825_093_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1446,13 +1490,13 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:2 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_call_per_transfer_input_output_kb(t: u32, i: u32, o: u32, ) -> Weight { - (19_665_171_000 as Weight) - // Standard Error: 27_641_000 - .saturating_add((2_089_637_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 9_000 - .saturating_add((20_165_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 10_000 - .saturating_add((31_728_000 as Weight).saturating_mul(o as Weight)) + (20_190_331_000 as Weight) + // Standard Error: 75_647_000 + .saturating_add((2_369_225_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 27_000 + .saturating_add((19_831_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 28_000 + .saturating_add((31_191_000 as Weight).saturating_mul(o as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().reads((101 as Weight).saturating_mul(t as Weight))) .saturating_add(RocksDbWeight::get().writes(101 as Weight)) @@ -1466,8 +1510,8 @@ impl WeightInfo for () { // Storage: Contracts OwnerInfoOf (r:100 w:100) fn seal_instantiate(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 48_640_000 - .saturating_add((27_307_450_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 50_368_000 + .saturating_add((27_757_564_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().reads((400 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -1480,13 +1524,13 @@ impl WeightInfo for () { // Storage: Contracts AccountCounter (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_instantiate_per_input_output_salt_kb(i: u32, o: u32, s: u32, ) -> Weight { - (24_821_248_000 as Weight) - // Standard Error: 26_000 - .saturating_add((20_118_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 26_000 - .saturating_add((31_616_000 as Weight).saturating_mul(o as Weight)) - // Standard Error: 26_000 - .saturating_add((157_567_000 as Weight).saturating_mul(s as Weight)) + (25_199_228_000 as Weight) + // Standard Error: 36_000 + .saturating_add((19_598_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 36_000 + .saturating_add((30_986_000 as Weight).saturating_mul(o as Weight)) + // Standard Error: 36_000 + .saturating_add((158_016_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(208 as Weight)) .saturating_add(RocksDbWeight::get().writes(206 as Weight)) } @@ -1495,9 +1539,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256(r: u32, ) -> Weight { - (213_816_000 as Weight) - // Standard Error: 147_000 - .saturating_add((80_336_000 as Weight).saturating_mul(r as Weight)) + (222_984_000 as Weight) + // Standard Error: 155_000 + .saturating_add((80_649_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1506,9 +1550,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256_per_kb(n: u32, ) -> Weight { - (309_038_000 as Weight) - // Standard Error: 23_000 - .saturating_add((465_306_000 as Weight).saturating_mul(n as Weight)) + (393_726_000 as Weight) + // Standard Error: 36_000 + .saturating_add((463_983_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1517,9 +1561,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256(r: u32, ) -> Weight { - (212_825_000 as Weight) - // Standard Error: 143_000 - .saturating_add((91_947_000 as Weight).saturating_mul(r as Weight)) + (217_461_000 as Weight) + // Standard Error: 146_000 + .saturating_add((92_540_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1528,9 +1572,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256_per_kb(n: u32, ) -> Weight { - (329_548_000 as Weight) + (271_742_000 as Weight) // Standard Error: 19_000 - .saturating_add((306_729_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((307_055_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1539,9 +1583,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256(r: u32, ) -> Weight { - (215_907_000 as Weight) - // Standard Error: 129_000 - .saturating_add((63_477_000 as Weight).saturating_mul(r as Weight)) + (220_664_000 as Weight) + // Standard Error: 145_000 + .saturating_add((64_516_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1550,9 +1594,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256_per_kb(n: u32, ) -> Weight { - (423_811_000 as Weight) - // Standard Error: 16_000 - .saturating_add((119_607_000 as Weight).saturating_mul(n as Weight)) + (287_500_000 as Weight) + // Standard Error: 12_000 + .saturating_add((119_931_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1561,9 +1605,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128(r: u32, ) -> Weight { - (214_747_000 as Weight) - // Standard Error: 115_000 - .saturating_add((62_904_000 as Weight).saturating_mul(r as Weight)) + (214_922_000 as Weight) + // Standard Error: 122_000 + .saturating_add((64_236_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1572,9 +1616,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128_per_kb(n: u32, ) -> Weight { - (437_217_000 as Weight) - // Standard Error: 19_000 - .saturating_add((120_126_000 as Weight).saturating_mul(n as Weight)) + (251_648_000 as Weight) + // Standard Error: 13_000 + .saturating_add((120_105_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1583,265 +1627,265 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_ecdsa_recover(r: u32, ) -> Weight { - (195_980_000 as Weight) - // Standard Error: 1_262_000 - .saturating_add((15_428_805_000 as Weight).saturating_mul(r as Weight)) + (124_760_000 as Weight) + // Standard Error: 1_397_000 + .saturating_add((15_387_180_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn instr_i64const(r: u32, ) -> Weight { - (74_569_000 as Weight) - // Standard Error: 1_000 - .saturating_add((589_000 as Weight).saturating_mul(r as Weight)) + (75_287_000 as Weight) + // Standard Error: 11_000 + .saturating_add((569_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64load(r: u32, ) -> Weight { - (74_212_000 as Weight) - // Standard Error: 0 - .saturating_add((1_325_000 as Weight).saturating_mul(r as Weight)) + (74_251_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_306_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64store(r: u32, ) -> Weight { - (74_505_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_423_000 as Weight).saturating_mul(r as Weight)) + (75_072_000 as Weight) + // Standard Error: 4_000 + .saturating_add((1_386_000 as Weight).saturating_mul(r as Weight)) } fn instr_select(r: u32, ) -> Weight { - (74_005_000 as Weight) - // Standard Error: 3_000 - .saturating_add((1_785_000 as Weight).saturating_mul(r as Weight)) + (73_811_000 as Weight) + // Standard Error: 0 + .saturating_add((1_783_000 as Weight).saturating_mul(r as Weight)) } fn instr_if(r: u32, ) -> Weight { - (74_212_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_890_000 as Weight).saturating_mul(r as Weight)) + (73_901_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_886_000 as Weight).saturating_mul(r as Weight)) } fn instr_br(r: u32, ) -> Weight { - (74_102_000 as Weight) - // Standard Error: 2_000 - .saturating_add((896_000 as Weight).saturating_mul(r as Weight)) + (73_720_000 as Weight) + // Standard Error: 1_000 + .saturating_add((903_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_if(r: u32, ) -> Weight { - (73_523_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_456_000 as Weight).saturating_mul(r as Weight)) + (73_534_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_459_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table(r: u32, ) -> Weight { - (73_307_000 as Weight) - // Standard Error: 4_000 - .saturating_add((1_594_000 as Weight).saturating_mul(r as Weight)) + (73_281_000 as Weight) + // Standard Error: 8_000 + .saturating_add((1_584_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table_per_entry(e: u32, ) -> Weight { - (76_272_000 as Weight) - // Standard Error: 0 - .saturating_add((5_000 as Weight).saturating_mul(e as Weight)) + (76_135_000 as Weight) + // Standard Error: 1_000 + .saturating_add((6_000 as Weight).saturating_mul(e as Weight)) } fn instr_call(r: u32, ) -> Weight { - (73_390_000 as Weight) + (75_938_000 as Weight) // Standard Error: 23_000 - .saturating_add((16_936_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((17_156_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect(r: u32, ) -> Weight { - (89_331_000 as Weight) - // Standard Error: 30_000 - .saturating_add((28_104_000 as Weight).saturating_mul(r as Weight)) + (85_864_000 as Weight) + // Standard Error: 28_000 + .saturating_add((28_343_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect_per_param(p: u32, ) -> Weight { - (117_023_000 as Weight) - // Standard Error: 3_000 - .saturating_add((914_000 as Weight).saturating_mul(p as Weight)) + (119_795_000 as Weight) + // Standard Error: 1_000 + .saturating_add((911_000 as Weight).saturating_mul(p as Weight)) } fn instr_local_get(r: u32, ) -> Weight { - (74_727_000 as Weight) + (74_750_000 as Weight) // Standard Error: 1_000 - .saturating_add((618_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((613_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_set(r: u32, ) -> Weight { - (74_893_000 as Weight) - // Standard Error: 1_000 - .saturating_add((674_000 as Weight).saturating_mul(r as Weight)) + (74_831_000 as Weight) + // Standard Error: 2_000 + .saturating_add((672_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_tee(r: u32, ) -> Weight { - (74_552_000 as Weight) + (74_314_000 as Weight) // Standard Error: 1_000 - .saturating_add((898_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((902_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_get(r: u32, ) -> Weight { - (77_355_000 as Weight) + (77_040_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_146_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_161_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_set(r: u32, ) -> Weight { - (77_055_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_363_000 as Weight).saturating_mul(r as Weight)) + (76_770_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_372_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_current(r: u32, ) -> Weight { - (74_648_000 as Weight) - // Standard Error: 2_000 - .saturating_add((652_000 as Weight).saturating_mul(r as Weight)) + (74_010_000 as Weight) + // Standard Error: 1_000 + .saturating_add((665_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_grow(r: u32, ) -> Weight { - (73_777_000 as Weight) - // Standard Error: 226_000 - .saturating_add((187_252_000 as Weight).saturating_mul(r as Weight)) + (73_597_000 as Weight) + // Standard Error: 929_000 + .saturating_add((183_940_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64clz(r: u32, ) -> Weight { - (74_332_000 as Weight) - // Standard Error: 1_000 - .saturating_add((897_000 as Weight).saturating_mul(r as Weight)) + (74_488_000 as Weight) + // Standard Error: 4_000 + .saturating_add((893_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ctz(r: u32, ) -> Weight { - (74_265_000 as Weight) - // Standard Error: 1_000 - .saturating_add((898_000 as Weight).saturating_mul(r as Weight)) + (74_024_000 as Weight) + // Standard Error: 5_000 + .saturating_add((908_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64popcnt(r: u32, ) -> Weight { - (74_475_000 as Weight) - // Standard Error: 2_000 - .saturating_add((892_000 as Weight).saturating_mul(r as Weight)) + (74_084_000 as Weight) + // Standard Error: 1_000 + .saturating_add((895_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eqz(r: u32, ) -> Weight { - (74_297_000 as Weight) - // Standard Error: 1_000 - .saturating_add((918_000 as Weight).saturating_mul(r as Weight)) + (74_250_000 as Weight) + // Standard Error: 2_000 + .saturating_add((916_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendsi32(r: u32, ) -> Weight { - (74_146_000 as Weight) + (74_027_000 as Weight) // Standard Error: 1_000 - .saturating_add((884_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((883_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendui32(r: u32, ) -> Weight { - (74_361_000 as Weight) + (74_201_000 as Weight) // Standard Error: 1_000 - .saturating_add((877_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((879_000 as Weight).saturating_mul(r as Weight)) } fn instr_i32wrapi64(r: u32, ) -> Weight { - (74_554_000 as Weight) + (74_116_000 as Weight) // Standard Error: 1_000 - .saturating_add((884_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((892_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eq(r: u32, ) -> Weight { - (74_169_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_357_000 as Weight).saturating_mul(r as Weight)) + (74_109_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_358_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ne(r: u32, ) -> Weight { - (74_164_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_357_000 as Weight).saturating_mul(r as Weight)) + (73_962_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_363_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64lts(r: u32, ) -> Weight { - (74_058_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_362_000 as Weight).saturating_mul(r as Weight)) + (73_977_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_360_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ltu(r: u32, ) -> Weight { - (74_039_000 as Weight) + (74_046_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_362_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_360_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gts(r: u32, ) -> Weight { - (75_055_000 as Weight) - // Standard Error: 4_000 - .saturating_add((1_338_000 as Weight).saturating_mul(r as Weight)) + (73_912_000 as Weight) + // Standard Error: 0 + .saturating_add((1_362_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gtu(r: u32, ) -> Weight { - (74_536_000 as Weight) - // Standard Error: 4_000 + (73_918_000 as Weight) + // Standard Error: 2_000 .saturating_add((1_367_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64les(r: u32, ) -> Weight { - (74_177_000 as Weight) + (73_953_000 as Weight) // Standard Error: 2_000 - .saturating_add((1_358_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_363_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64leu(r: u32, ) -> Weight { - (74_080_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_370_000 as Weight).saturating_mul(r as Weight)) + (74_855_000 as Weight) + // Standard Error: 4_000 + .saturating_add((1_347_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ges(r: u32, ) -> Weight { - (74_237_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_356_000 as Weight).saturating_mul(r as Weight)) + (73_917_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_364_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64geu(r: u32, ) -> Weight { - (74_049_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_362_000 as Weight).saturating_mul(r as Weight)) + (73_949_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_361_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64add(r: u32, ) -> Weight { - (74_186_000 as Weight) + (73_726_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_335_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_347_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64sub(r: u32, ) -> Weight { - (74_268_000 as Weight) + (73_921_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_339_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_345_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64mul(r: u32, ) -> Weight { - (74_334_000 as Weight) + (73_924_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_331_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_341_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divs(r: u32, ) -> Weight { - (74_285_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_997_000 as Weight).saturating_mul(r as Weight)) + (73_842_000 as Weight) + // Standard Error: 2_000 + .saturating_add((2_011_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divu(r: u32, ) -> Weight { - (74_002_000 as Weight) + (73_932_000 as Weight) // Standard Error: 1_000 - .saturating_add((2_027_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_057_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rems(r: u32, ) -> Weight { - (74_281_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_977_000 as Weight).saturating_mul(r as Weight)) + (74_028_000 as Weight) + // Standard Error: 2_000 + .saturating_add((2_001_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64remu(r: u32, ) -> Weight { - (74_160_000 as Weight) - // Standard Error: 1_000 - .saturating_add((2_038_000 as Weight).saturating_mul(r as Weight)) + (73_784_000 as Weight) + // Standard Error: 2_000 + .saturating_add((2_059_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64and(r: u32, ) -> Weight { - (74_097_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_339_000 as Weight).saturating_mul(r as Weight)) + (74_169_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_334_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64or(r: u32, ) -> Weight { - (74_020_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_341_000 as Weight).saturating_mul(r as Weight)) + (73_982_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_340_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64xor(r: u32, ) -> Weight { - (73_890_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_351_000 as Weight).saturating_mul(r as Weight)) + (74_310_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_329_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shl(r: u32, ) -> Weight { - (74_139_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_355_000 as Weight).saturating_mul(r as Weight)) + (73_861_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_362_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shrs(r: u32, ) -> Weight { - (74_189_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_352_000 as Weight).saturating_mul(r as Weight)) + (73_787_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_364_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shru(r: u32, ) -> Weight { - (74_055_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_359_000 as Weight).saturating_mul(r as Weight)) + (73_886_000 as Weight) + // Standard Error: 7_000 + .saturating_add((1_372_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotl(r: u32, ) -> Weight { - (74_074_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_357_000 as Weight).saturating_mul(r as Weight)) + (73_860_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_362_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotr(r: u32, ) -> Weight { - (74_005_000 as Weight) + (73_917_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_357_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_356_000 as Weight).saturating_mul(r as Weight)) } } From 36c38fb26b362ee0666d655ad5d6ad7279ba7e07 Mon Sep 17 00:00:00 2001 From: girazoki Date: Sat, 5 Feb 2022 12:06:44 +0100 Subject: [PATCH 456/695] maybe_total_supply in pallet-assets (#10799) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * maybe_total_supply in pallet-assets * Update frame/assets/src/functions.rs Co-authored-by: Bastian Köcher --- frame/assets/src/functions.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/frame/assets/src/functions.rs b/frame/assets/src/functions.rs index e02cc7c8bb21..73804fc832c9 100644 --- a/frame/assets/src/functions.rs +++ b/frame/assets/src/functions.rs @@ -55,7 +55,12 @@ impl, I: 'static> Pallet { /// Get the total supply of an asset `id`. pub fn total_supply(id: T::AssetId) -> T::Balance { - Asset::::get(id).map(|x| x.supply).unwrap_or_else(Zero::zero) + Self::maybe_total_supply(id).unwrap_or_default() + } + + /// Get the total supply of an asset `id` if the asset exists. + pub fn maybe_total_supply(id: T::AssetId) -> Option { + Asset::::get(id).map(|x| x.supply) } pub(super) fn new_account( From 7e643ceabf11858cd3c059579ab45794793f2a78 Mon Sep 17 00:00:00 2001 From: Gavin Wood Date: Sun, 6 Feb 2022 12:51:12 +0100 Subject: [PATCH 457/695] Referenda and Conviction Voting pallets (#10195) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Initial draft of new referendum state machine. * Docs * Fixes * Fixes * Add conviction-voting pallet * Basic build * Building * Some TODOs * Tests building * Add missing file * Basic lifecycle test * Add couple of tests * Another test * More tests * Fixes * Fixes * Formatting * Fixes * Tests * Fixes * Fixes * More tests * Formatting * First few benchmarks * First few benchmarks * Defered queue servicing * More testing * Benchmarks * Fiddly benchmark * Final nudge benchmarks * Formatting * Formatting * Finished up benchmarks * cargo run --quiet --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_referenda --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/referenda/src/weights.rs --template=./.maintain/frame-weight-template.hbs * Events finished * Missing file * No GenesisConfig for Referenda * Formatting * Docs * Docs * Docs * Per-class conviction voting * New test & mock utils * More tests * Tests * Tests finished 🎉 * Benchmarking stuff * Fixes * Test harness * Test harness * Benchmarks for Conviction=Voting * Benchmarking pipeline complete * Docs * Formatting * Remove unneeded warning * Fix UI tests * cargo run --quiet --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_conviction_voting --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/conviction-voting/src/weights.rs --template=./.maintain/frame-weight-template.hbs * Docs * Update frame/conviction-voting/src/vote.rs Co-authored-by: Shawn Tabrizi * update sp-runtime version * MEL Fixes for Referenda and Conviction Voting (#10725) * free maxencodedlen * more maxencodedlen * more MEL * more mel * disable storage info * More Referenda Patches (#10760) * basic fixes * fix benchmarking * fix license * prevent panic in curve math * fmt * bump crate versions * Update mock.rs Co-authored-by: Parity Bot Co-authored-by: Shawn Tabrizi --- Cargo.lock | 41 + Cargo.toml | 8 +- bin/node/runtime/Cargo.toml | 32 +- bin/node/runtime/src/lib.rs | 81 ++ frame/balances/src/lib.rs | 2 +- frame/conviction-voting/Cargo.toml | 53 + frame/conviction-voting/README.md | 8 + frame/conviction-voting/src/benchmarking.rs | 278 +++++ frame/conviction-voting/src/conviction.rs | 131 +++ frame/conviction-voting/src/lib.rs | 632 +++++++++++ frame/conviction-voting/src/tests.rs | 820 ++++++++++++++ frame/conviction-voting/src/types.rs | 236 ++++ frame/conviction-voting/src/vote.rs | 254 +++++ frame/conviction-voting/src/weights.rs | 201 ++++ frame/democracy/src/lib.rs | 8 - frame/referenda/Cargo.toml | 56 + frame/referenda/README.md | 8 + frame/referenda/src/benchmarking.rs | 520 +++++++++ frame/referenda/src/branch.rs | 172 +++ frame/referenda/src/lib.rs | 1065 +++++++++++++++++++ frame/referenda/src/mock.rs | 460 ++++++++ frame/referenda/src/tests.rs | 511 +++++++++ frame/referenda/src/types.rs | 358 +++++++ frame/referenda/src/weights.rs | 491 +++++++++ frame/scheduler/src/lib.rs | 14 - frame/support/src/dispatch.rs | 50 +- frame/support/src/traits.rs | 6 +- frame/support/src/traits/dispatch.rs | 9 +- frame/support/src/traits/schedule.rs | 4 +- frame/support/src/traits/tokens/currency.rs | 14 +- frame/support/src/traits/voting.rs | 80 +- frame/support/test/tests/system.rs | 18 +- frame/system/src/lib.rs | 25 +- test-utils/runtime/src/lib.rs | 2 +- 34 files changed, 6542 insertions(+), 106 deletions(-) create mode 100644 frame/conviction-voting/Cargo.toml create mode 100644 frame/conviction-voting/README.md create mode 100644 frame/conviction-voting/src/benchmarking.rs create mode 100644 frame/conviction-voting/src/conviction.rs create mode 100644 frame/conviction-voting/src/lib.rs create mode 100644 frame/conviction-voting/src/tests.rs create mode 100644 frame/conviction-voting/src/types.rs create mode 100644 frame/conviction-voting/src/vote.rs create mode 100644 frame/conviction-voting/src/weights.rs create mode 100644 frame/referenda/Cargo.toml create mode 100644 frame/referenda/README.md create mode 100644 frame/referenda/src/benchmarking.rs create mode 100644 frame/referenda/src/branch.rs create mode 100644 frame/referenda/src/lib.rs create mode 100644 frame/referenda/src/mock.rs create mode 100644 frame/referenda/src/tests.rs create mode 100644 frame/referenda/src/types.rs create mode 100644 frame/referenda/src/weights.rs diff --git a/Cargo.lock b/Cargo.lock index 2e254e7d1184..45158288298b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4871,6 +4871,7 @@ dependencies = [ "pallet-contracts", "pallet-contracts-primitives", "pallet-contracts-rpc-runtime-api", + "pallet-conviction-voting", "pallet-democracy", "pallet-election-provider-multi-phase", "pallet-elections-phragmen", @@ -4889,6 +4890,7 @@ dependencies = [ "pallet-proxy", "pallet-randomness-collective-flip", "pallet-recovery", + "pallet-referenda", "pallet-scheduler", "pallet-session", "pallet-session-benchmarking", @@ -5672,6 +5674,25 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-conviction-voting" +version = "4.0.0-dev" +dependencies = [ + "assert_matches", + "frame-benchmarking", + "frame-support", + "frame-system", + "pallet-balances", + "pallet-scheduler", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-democracy" version = "4.0.0-dev" @@ -6122,6 +6143,26 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-referenda" +version = "4.0.0-dev" +dependencies = [ + "assert_matches", + "frame-benchmarking", + "frame-support", + "frame-system", + "pallet-balances", + "pallet-preimage", + "pallet-scheduler", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-scheduler" version = "4.0.0-dev" diff --git a/Cargo.toml b/Cargo.toml index 48a36419eb74..a31d8011a9f4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -67,6 +67,9 @@ members = [ "frame/authority-discovery", "frame/authorship", "frame/babe", + "frame/bags-list", + "frame/bags-list/fuzzer", + "frame/bags-list/remote-tests", "frame/balances", "frame/beefy", "frame/beefy-mmr", @@ -78,6 +81,7 @@ members = [ "frame/contracts", "frame/contracts/rpc", "frame/contracts/rpc/runtime-api", + "frame/conviction-voting", "frame/democracy", "frame/try-runtime", "frame/election-provider-multi-phase", @@ -104,6 +108,7 @@ members = [ "frame/proxy", "frame/randomness-collective-flip", "frame/recovery", + "frame/referenda", "frame/scheduler", "frame/scored-pool", "frame/session", @@ -133,9 +138,6 @@ members = [ "frame/uniques", "frame/utility", "frame/vesting", - "frame/bags-list", - "frame/bags-list/remote-tests", - "frame/bags-list/fuzzer", "primitives/api", "primitives/api/proc-macro", "primitives/api/test", diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 647562caff30..2aad40b4f121 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -64,6 +64,7 @@ pallet-collective = { version = "4.0.0-dev", default-features = false, path = ". pallet-contracts = { version = "4.0.0-dev", default-features = false, path = "../../../frame/contracts" } pallet-contracts-primitives = { version = "5.0.0", default-features = false, path = "../../../frame/contracts/common/" } pallet-contracts-rpc-runtime-api = { version = "4.0.0-dev", default-features = false, path = "../../../frame/contracts/rpc/runtime-api/" } +pallet-conviction-voting = { version = "4.0.0-dev", default-features = false, path = "../../../frame/conviction-voting" } pallet-democracy = { version = "4.0.0-dev", default-features = false, path = "../../../frame/democracy" } pallet-election-provider-multi-phase = { version = "4.0.0-dev", default-features = false, path = "../../../frame/election-provider-multi-phase" } pallet-elections-phragmen = { version = "5.0.0-dev", default-features = false, path = "../../../frame/elections-phragmen" } @@ -82,9 +83,8 @@ pallet-preimage = { version = "4.0.0-dev", default-features = false, path = "../ pallet-proxy = { version = "4.0.0-dev", default-features = false, path = "../../../frame/proxy" } pallet-randomness-collective-flip = { version = "4.0.0-dev", default-features = false, path = "../../../frame/randomness-collective-flip" } pallet-recovery = { version = "4.0.0-dev", default-features = false, path = "../../../frame/recovery" } -pallet-session = { version = "4.0.0-dev", features = [ - "historical", -], path = "../../../frame/session", default-features = false } +pallet-referenda = { version = "4.0.0-dev", default-features = false, path = "../../../frame/referenda" } +pallet-session = { version = "4.0.0-dev", features = [ "historical" ], path = "../../../frame/session", default-features = false } pallet-session-benchmarking = { version = "4.0.0-dev", path = "../../../frame/session/benchmarking", default-features = false, optional = true } pallet-staking = { version = "4.0.0-dev", default-features = false, path = "../../../frame/staking" } pallet-staking-reward-curve = { version = "4.0.0-dev", default-features = false, path = "../../../frame/staking/reward-curve" } @@ -125,6 +125,7 @@ std = [ "pallet-contracts/std", "pallet-contracts-primitives/std", "pallet-contracts-rpc-runtime-api/std", + "pallet-conviction-voting/std", "pallet-democracy/std", "pallet-elections-phragmen/std", "frame-executive/std", @@ -170,6 +171,7 @@ std = [ "pallet-utility/std", "sp-version/std", "pallet-society/std", + "pallet-referenda/std", "pallet-recovery/std", "pallet-uniques/std", "pallet-vesting/std", @@ -183,7 +185,6 @@ runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", - "pallet-election-provider-multi-phase/runtime-benchmarks", "sp-runtime/runtime-benchmarks", "pallet-assets/runtime-benchmarks", "pallet-babe/runtime-benchmarks", @@ -193,7 +194,9 @@ runtime-benchmarks = [ "pallet-child-bounties/runtime-benchmarks", "pallet-collective/runtime-benchmarks", "pallet-contracts/runtime-benchmarks", + "pallet-conviction-voting/runtime-benchmarks", "pallet-democracy/runtime-benchmarks", + "pallet-election-provider-multi-phase/runtime-benchmarks", "pallet-elections-phragmen/runtime-benchmarks", "pallet-gilt/runtime-benchmarks", "pallet-grandpa/runtime-benchmarks", @@ -204,9 +207,12 @@ runtime-benchmarks = [ "pallet-membership/runtime-benchmarks", "pallet-mmr/runtime-benchmarks", "pallet-multisig/runtime-benchmarks", + "pallet-offences-benchmarking", "pallet-preimage/runtime-benchmarks", "pallet-proxy/runtime-benchmarks", "pallet-scheduler/runtime-benchmarks", + "pallet-referenda/runtime-benchmarks", + "pallet-session-benchmarking", "pallet-society/runtime-benchmarks", "pallet-staking/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", @@ -216,8 +222,6 @@ runtime-benchmarks = [ "pallet-utility/runtime-benchmarks", "pallet-uniques/runtime-benchmarks", "pallet-vesting/runtime-benchmarks", - "pallet-offences-benchmarking", - "pallet-session-benchmarking", "frame-system-benchmarking", "hex-literal", ] @@ -234,35 +238,37 @@ try-runtime = [ "pallet-child-bounties/try-runtime", "pallet-collective/try-runtime", "pallet-contracts/try-runtime", + "pallet-conviction-voting/try-runtime", "pallet-democracy/try-runtime", + "pallet-election-provider-multi-phase/try-runtime", "pallet-elections-phragmen/try-runtime", + "pallet-gilt/try-runtime", "pallet-grandpa/try-runtime", + "pallet-identity/try-runtime", "pallet-im-online/try-runtime", "pallet-indices/try-runtime", "pallet-lottery/try-runtime", "pallet-membership/try-runtime", "pallet-mmr/try-runtime", "pallet-multisig/try-runtime", - "pallet-identity/try-runtime", - "pallet-scheduler/try-runtime", "pallet-offences/try-runtime", "pallet-preimage/try-runtime", "pallet-proxy/try-runtime", "pallet-randomness-collective-flip/try-runtime", + "pallet-recovery/try-runtime", + "pallet-referenda/try-runtime", + "pallet-scheduler/try-runtime", "pallet-session/try-runtime", + "pallet-society/try-runtime", "pallet-staking/try-runtime", "pallet-sudo/try-runtime", - "pallet-election-provider-multi-phase/try-runtime", "pallet-timestamp/try-runtime", "pallet-tips/try-runtime", "pallet-transaction-payment/try-runtime", "pallet-treasury/try-runtime", - "pallet-utility/try-runtime", - "pallet-society/try-runtime", - "pallet-recovery/try-runtime", "pallet-uniques/try-runtime", + "pallet-utility/try-runtime", "pallet-vesting/try-runtime", - "pallet-gilt/try-runtime", ] # Make contract callable functions marked as __unstable__ available. Do not enable # on live chains as those are subject to change. diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index e70adc6aa723..0a13b795919c 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -698,6 +698,83 @@ impl pallet_bags_list::Config for Runtime { type BagThresholds = BagThresholds; } +parameter_types! { + pub const VoteLockingPeriod: BlockNumber = 30 * DAYS; +} + +impl pallet_conviction_voting::Config for Runtime { + type WeightInfo = pallet_conviction_voting::weights::SubstrateWeight; + type Event = Event; + type Currency = Balances; + type VoteLockingPeriod = VoteLockingPeriod; + type MaxVotes = ConstU32<512>; + type MaxTurnout = frame_support::traits::TotalIssuanceOf; + type Polls = Referenda; +} + +parameter_types! { + pub const AlarmInterval: BlockNumber = 1; + pub const SubmissionDeposit: Balance = 100 * DOLLARS; + pub const UndecidingTimeout: BlockNumber = 28 * DAYS; +} + +pub struct TracksInfo; +impl pallet_referenda::TracksInfo for TracksInfo { + type Id = u8; + type Origin = ::PalletsOrigin; + fn tracks() -> &'static [(Self::Id, pallet_referenda::TrackInfo)] { + static DATA: [(u8, pallet_referenda::TrackInfo); 1] = [( + 0u8, + pallet_referenda::TrackInfo { + name: "root", + max_deciding: 1, + decision_deposit: 10, + prepare_period: 4, + decision_period: 4, + confirm_period: 2, + min_enactment_period: 4, + min_approval: pallet_referenda::Curve::LinearDecreasing { + begin: Perbill::from_percent(100), + delta: Perbill::from_percent(50), + }, + min_turnout: pallet_referenda::Curve::LinearDecreasing { + begin: Perbill::from_percent(100), + delta: Perbill::from_percent(100), + }, + }, + )]; + &DATA[..] + } + fn track_for(id: &Self::Origin) -> Result { + if let Ok(system_origin) = frame_system::RawOrigin::try_from(id.clone()) { + match system_origin { + frame_system::RawOrigin::Root => Ok(0), + _ => Err(()), + } + } else { + Err(()) + } + } +} + +impl pallet_referenda::Config for Runtime { + type WeightInfo = pallet_referenda::weights::SubstrateWeight; + type Call = Call; + type Event = Event; + type Scheduler = Scheduler; + type Currency = pallet_balances::Pallet; + type CancelOrigin = EnsureRoot; + type KillOrigin = EnsureRoot; + type Slash = (); + type Votes = pallet_conviction_voting::VotesOf; + type Tally = pallet_conviction_voting::TallyOf; + type SubmissionDeposit = SubmissionDeposit; + type MaxQueued = ConstU32<100>; + type UndecidingTimeout = UndecidingTimeout; + type AlarmInterval = AlarmInterval; + type Tracks = TracksInfo; +} + parameter_types! { pub const LaunchPeriod: BlockNumber = 28 * 24 * 60 * MINUTES; pub const VotingPeriod: BlockNumber = 28 * 24 * 60 * MINUTES; @@ -1336,6 +1413,8 @@ construct_runtime!( TransactionStorage: pallet_transaction_storage, BagsList: pallet_bags_list, ChildBounties: pallet_child_bounties, + Referenda: pallet_referenda, + ConvictionVoting: pallet_conviction_voting, } ); @@ -1405,6 +1484,7 @@ mod benches { [pallet_bounties, Bounties] [pallet_child_bounties, ChildBounties] [pallet_collective, Council] + [pallet_conviction_voting, ConvictionVoting] [pallet_contracts, Contracts] [pallet_democracy, Democracy] [pallet_election_provider_multi_phase, ElectionProviderMultiPhase] @@ -1421,6 +1501,7 @@ mod benches { [pallet_offences, OffencesBench::] [pallet_preimage, Preimage] [pallet_proxy, Proxy] + [pallet_referenda, Referenda] [pallet_scheduler, Scheduler] [pallet_session, SessionBench::] [pallet_staking, Staking] diff --git a/frame/balances/src/lib.rs b/frame/balances/src/lib.rs index 80e8bf577abe..37114f385aa7 100644 --- a/frame/balances/src/lib.rs +++ b/frame/balances/src/lib.rs @@ -1517,7 +1517,7 @@ where .map_err(|_| Error::::LiquidityRestrictions)?; // TODO: This is over-conservative. There may now be other providers, and - // this pallet may not even be a provider. + // this pallet may not even be a provider. let allow_death = existence_requirement == ExistenceRequirement::AllowDeath; let allow_death = allow_death && system::Pallet::::can_dec_provider(transactor); diff --git a/frame/conviction-voting/Cargo.toml b/frame/conviction-voting/Cargo.toml new file mode 100644 index 000000000000..ab62065c1c54 --- /dev/null +++ b/frame/conviction-voting/Cargo.toml @@ -0,0 +1,53 @@ +[package] +name = "pallet-conviction-voting" +version = "4.0.0-dev" +authors = ["Parity Technologies "] +edition = "2018" +license = "Apache-2.0" +homepage = "https://substrate.io" +repository = "https://github.com/paritytech/substrate/" +description = "FRAME pallet for conviction voting in referenda" +readme = "README.md" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +serde = { version = "1.0.126", optional = true, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ + "derive", +] } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } +sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } +frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } +frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } +assert_matches = "1.3.0" + +[dev-dependencies] +sp-core = { version = "5.0.0", path = "../../primitives/core" } +pallet-balances = { version = "4.0.0-dev", path = "../balances" } +pallet-scheduler = { version = "4.0.0-dev", path = "../scheduler" } + +[features] +default = ["std"] +std = [ + "serde", + "codec/std", + "scale-info/std", + "sp-std/std", + "sp-io/std", + "frame-benchmarking/std", + "frame-support/std", + "sp-runtime/std", + "frame-system/std", +] +runtime-benchmarks = [ + "frame-benchmarking", + "frame-system/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", +] +try-runtime = ["frame-support/try-runtime"] diff --git a/frame/conviction-voting/README.md b/frame/conviction-voting/README.md new file mode 100644 index 000000000000..5dc5d526d5c2 --- /dev/null +++ b/frame/conviction-voting/README.md @@ -0,0 +1,8 @@ +# Voting Pallet + +- [`assembly::Config`](https://docs.rs/pallet-assembly/latest/pallet_assembly/trait.Config.html) +- [`Call`](https://docs.rs/pallet-assembly/latest/pallet_assembly/enum.Call.html) + +## Overview + +Pallet for voting in referenda. diff --git a/frame/conviction-voting/src/benchmarking.rs b/frame/conviction-voting/src/benchmarking.rs new file mode 100644 index 000000000000..2beee4f3b49d --- /dev/null +++ b/frame/conviction-voting/src/benchmarking.rs @@ -0,0 +1,278 @@ +// This file is part of Substrate. + +// Copyright (C) 2020-2021 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. + +//! ConvictionVoting pallet benchmarking. + +use super::*; + +use assert_matches::assert_matches; +use frame_benchmarking::{account, benchmarks, whitelist_account}; +use frame_support::{ + dispatch::RawOrigin, + traits::{fungible, Currency, Get}, +}; +use sp_runtime::traits::Bounded; +use sp_std::collections::btree_map::BTreeMap; + +use crate::Pallet as ConvictionVoting; + +const SEED: u32 = 0; + +/// Fill all classes as much as possible up to `MaxVotes` and return the Class with the most votes +/// ongoing. +fn fill_voting() -> (ClassOf, BTreeMap, Vec>>) { + let mut r = BTreeMap::, Vec>>::new(); + for class in T::Polls::classes().into_iter() { + for _ in 0..T::MaxVotes::get() { + match T::Polls::create_ongoing(class.clone()) { + Ok(i) => r.entry(class.clone()).or_default().push(i), + Err(()) => break, + } + } + } + let c = r.iter().max_by_key(|(_, ref v)| v.len()).unwrap().0.clone(); + (c, r) +} + +fn funded_account(name: &'static str, index: u32) -> T::AccountId { + let caller: T::AccountId = account(name, index, SEED); + T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); + caller +} + +fn account_vote(b: BalanceOf) -> AccountVote> { + let v = Vote { aye: true, conviction: Conviction::Locked1x }; + + AccountVote::Standard { vote: v, balance: b } +} + +benchmarks! { + where_clause { where T::MaxVotes: core::fmt::Debug } + + vote_new { + let caller = funded_account::("caller", 0); + whitelist_account!(caller); + let account_vote = account_vote::(100u32.into()); + + let (class, all_polls) = fill_voting::(); + let polls = &all_polls[&class]; + let r = polls.len() - 1; + // We need to create existing votes + for i in polls.iter().skip(1) { + ConvictionVoting::::vote(RawOrigin::Signed(caller.clone()).into(), *i, account_vote.clone())?; + } + let votes = match VotingFor::::get(&caller, &class) { + Voting::Casting(Casting { votes, .. }) => votes, + _ => return Err("Votes are not direct".into()), + }; + assert_eq!(votes.len(), r as usize, "Votes were not recorded."); + + let index = polls[0]; + }: vote(RawOrigin::Signed(caller.clone()), index, account_vote) + verify { + assert_matches!( + VotingFor::::get(&caller, &class), + Voting::Casting(Casting { votes, .. }) if votes.len() == (r + 1) as usize + ); + } + + vote_existing { + let caller = funded_account::("caller", 0); + whitelist_account!(caller); + let old_account_vote = account_vote::(100u32.into()); + + let (class, all_polls) = fill_voting::(); + let polls = &all_polls[&class]; + let r = polls.len(); + // We need to create existing votes + for i in polls.iter() { + ConvictionVoting::::vote(RawOrigin::Signed(caller.clone()).into(), *i, old_account_vote.clone())?; + } + let votes = match VotingFor::::get(&caller, &class) { + Voting::Casting(Casting { votes, .. }) => votes, + _ => return Err("Votes are not direct".into()), + }; + assert_eq!(votes.len(), r, "Votes were not recorded."); + + let new_account_vote = account_vote::(200u32.into()); + let index = polls[0]; + }: vote(RawOrigin::Signed(caller.clone()), index, new_account_vote) + verify { + assert_matches!( + VotingFor::::get(&caller, &class), + Voting::Casting(Casting { votes, .. }) if votes.len() == r as usize + ); + } + + remove_vote { + let caller = funded_account::("caller", 0); + whitelist_account!(caller); + let old_account_vote = account_vote::(100u32.into()); + + let (class, all_polls) = fill_voting::(); + let polls = &all_polls[&class]; + let r = polls.len(); + // We need to create existing votes + for i in polls.iter() { + ConvictionVoting::::vote(RawOrigin::Signed(caller.clone()).into(), *i, old_account_vote.clone())?; + } + let votes = match VotingFor::::get(&caller, &class) { + Voting::Casting(Casting { votes, .. }) => votes, + _ => return Err("Votes are not direct".into()), + }; + assert_eq!(votes.len(), r, "Votes were not recorded."); + + let index = polls[0]; + }: _(RawOrigin::Signed(caller.clone()), Some(class.clone()), index) + verify { + assert_matches!( + VotingFor::::get(&caller, &class), + Voting::Casting(Casting { votes, .. }) if votes.len() == (r - 1) as usize + ); + } + + remove_other_vote { + let caller = funded_account::("caller", 0); + let voter = funded_account::("caller", 0); + whitelist_account!(caller); + let old_account_vote = account_vote::(100u32.into()); + + let (class, all_polls) = fill_voting::(); + let polls = &all_polls[&class]; + let r = polls.len(); + // We need to create existing votes + for i in polls.iter() { + ConvictionVoting::::vote(RawOrigin::Signed(voter.clone()).into(), *i, old_account_vote.clone())?; + } + let votes = match VotingFor::::get(&caller, &class) { + Voting::Casting(Casting { votes, .. }) => votes, + _ => return Err("Votes are not direct".into()), + }; + assert_eq!(votes.len(), r, "Votes were not recorded."); + + let index = polls[0]; + assert!(T::Polls::end_ongoing(index, false).is_ok()); + }: _(RawOrigin::Signed(caller.clone()), voter.clone(), class.clone(), index) + verify { + assert_matches!( + VotingFor::::get(&voter, &class), + Voting::Casting(Casting { votes, .. }) if votes.len() == (r - 1) as usize + ); + } + + delegate { + let r in 0 .. T::MaxVotes::get().min(T::Polls::max_ongoing().1); + + let all_polls = fill_voting::().1; + let class = T::Polls::max_ongoing().0; + let polls = &all_polls[&class]; + let voter = funded_account::("voter", 0); + let caller = funded_account::("caller", 0); + whitelist_account!(caller); + + let delegated_balance: BalanceOf = 1000u32.into(); + let delegate_vote = account_vote::(delegated_balance); + + // We need to create existing delegations + for i in polls.iter().take(r as usize) { + ConvictionVoting::::vote(RawOrigin::Signed(voter.clone()).into(), *i, delegate_vote.clone())?; + } + assert_matches!( + VotingFor::::get(&voter, &class), + Voting::Casting(Casting { votes, .. }) if votes.len() == r as usize + ); + + }: _(RawOrigin::Signed(caller.clone()), class.clone(), voter.clone(), Conviction::Locked1x, delegated_balance) + verify { + assert_matches!(VotingFor::::get(&caller, &class), Voting::Delegating(_)); + } + + undelegate { + let r in 0 .. T::MaxVotes::get().min(T::Polls::max_ongoing().1); + + let all_polls = fill_voting::().1; + let class = T::Polls::max_ongoing().0; + let polls = &all_polls[&class]; + let voter = funded_account::("voter", 0); + let caller = funded_account::("caller", 0); + whitelist_account!(caller); + + let delegated_balance: BalanceOf = 1000u32.into(); + let delegate_vote = account_vote::(delegated_balance); + + ConvictionVoting::::delegate( + RawOrigin::Signed(caller.clone()).into(), + class.clone(), + voter.clone(), + Conviction::Locked1x, + delegated_balance, + )?; + + // We need to create delegations + for i in polls.iter().take(r as usize) { + ConvictionVoting::::vote(RawOrigin::Signed(voter.clone()).into(), *i, delegate_vote.clone())?; + } + assert_matches!( + VotingFor::::get(&voter, &class), + Voting::Casting(Casting { votes, .. }) if votes.len() == r as usize + ); + assert_matches!(VotingFor::::get(&caller, &class), Voting::Delegating(_)); + }: _(RawOrigin::Signed(caller.clone()), class.clone()) + verify { + assert_matches!(VotingFor::::get(&caller, &class), Voting::Casting(_)); + } + + unlock { + let caller = funded_account::("caller", 0); + whitelist_account!(caller); + let normal_account_vote = account_vote::(T::Currency::free_balance(&caller) - 100u32.into()); + let big_account_vote = account_vote::(T::Currency::free_balance(&caller)); + + // Fill everything up to the max by filling all classes with votes and voting on them all. + let (class, all_polls) = fill_voting::(); + assert!(all_polls.len() > 0); + for (class, polls) in all_polls.iter() { + assert!(polls.len() > 0); + for i in polls.iter() { + ConvictionVoting::::vote(RawOrigin::Signed(caller.clone()).into(), *i, normal_account_vote.clone())?; + } + } + + let orig_usable = >::reducible_balance(&caller, false); + let polls = &all_polls[&class]; + + // Vote big on the class with the most ongoing votes of them to bump the lock and make it + // hard to recompute when removed. + ConvictionVoting::::vote(RawOrigin::Signed(caller.clone()).into(), polls[0], big_account_vote.clone())?; + let now_usable = >::reducible_balance(&caller, false); + assert_eq!(orig_usable - now_usable, 100u32.into()); + + // Remove the vote + ConvictionVoting::::remove_vote(RawOrigin::Signed(caller.clone()).into(), Some(class.clone()), polls[0])?; + + // We can now unlock on `class` from 200 to 100... + }: _(RawOrigin::Signed(caller.clone()), class, caller.clone()) + verify { + assert_eq!(orig_usable, >::reducible_balance(&caller, false)); + } + + impl_benchmark_test_suite!( + ConvictionVoting, + crate::tests::new_test_ext(), + crate::tests::Test + ); +} diff --git a/frame/conviction-voting/src/conviction.rs b/frame/conviction-voting/src/conviction.rs new file mode 100644 index 000000000000..129f2771124b --- /dev/null +++ b/frame/conviction-voting/src/conviction.rs @@ -0,0 +1,131 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2022 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. + +//! The conviction datatype. + +use crate::types::Delegations; +use codec::{Decode, Encode, MaxEncodedLen}; +use scale_info::TypeInfo; +use sp_runtime::{ + traits::{Bounded, CheckedDiv, CheckedMul, Zero}, + RuntimeDebug, +}; +use sp_std::{convert::TryFrom, result::Result}; + +/// A value denoting the strength of conviction of a vote. +#[derive( + Encode, + Decode, + Copy, + Clone, + Eq, + PartialEq, + Ord, + PartialOrd, + RuntimeDebug, + TypeInfo, + MaxEncodedLen, +)] +pub enum Conviction { + /// 0.1x votes, unlocked. + None, + /// 1x votes, locked for an enactment period following a successful vote. + Locked1x, + /// 2x votes, locked for 2x enactment periods following a successful vote. + Locked2x, + /// 3x votes, locked for 4x... + Locked3x, + /// 4x votes, locked for 8x... + Locked4x, + /// 5x votes, locked for 16x... + Locked5x, + /// 6x votes, locked for 32x... + Locked6x, +} + +impl Default for Conviction { + fn default() -> Self { + Conviction::None + } +} + +impl From for u8 { + fn from(c: Conviction) -> u8 { + match c { + Conviction::None => 0, + Conviction::Locked1x => 1, + Conviction::Locked2x => 2, + Conviction::Locked3x => 3, + Conviction::Locked4x => 4, + Conviction::Locked5x => 5, + Conviction::Locked6x => 6, + } + } +} + +impl TryFrom for Conviction { + type Error = (); + fn try_from(i: u8) -> Result { + Ok(match i { + 0 => Conviction::None, + 1 => Conviction::Locked1x, + 2 => Conviction::Locked2x, + 3 => Conviction::Locked3x, + 4 => Conviction::Locked4x, + 5 => Conviction::Locked5x, + 6 => Conviction::Locked6x, + _ => return Err(()), + }) + } +} + +impl Conviction { + /// The amount of time (in number of periods) that our conviction implies a successful voter's + /// balance should be locked for. + pub fn lock_periods(self) -> u32 { + match self { + Conviction::None => 0, + Conviction::Locked1x => 1, + Conviction::Locked2x => 2, + Conviction::Locked3x => 4, + Conviction::Locked4x => 8, + Conviction::Locked5x => 16, + Conviction::Locked6x => 32, + } + } + + /// The votes of a voter of the given `balance` with our conviction. + pub fn votes + Zero + Copy + CheckedMul + CheckedDiv + Bounded>( + self, + capital: B, + ) -> Delegations { + let votes = match self { + Conviction::None => capital.checked_div(&10u8.into()).unwrap_or_else(Zero::zero), + x => capital.checked_mul(&u8::from(x).into()).unwrap_or_else(B::max_value), + }; + Delegations { votes, capital } + } +} + +impl Bounded for Conviction { + fn min_value() -> Self { + Conviction::None + } + fn max_value() -> Self { + Conviction::Locked6x + } +} diff --git a/frame/conviction-voting/src/lib.rs b/frame/conviction-voting/src/lib.rs new file mode 100644 index 000000000000..8e7e0d91b1cf --- /dev/null +++ b/frame/conviction-voting/src/lib.rs @@ -0,0 +1,632 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2022 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. + +//! # Voting Pallet +//! +//! - [`Config`] +//! - [`Call`] +//! +//! ## Overview +//! +//! Pallet for managing actual voting in polls. + +#![recursion_limit = "256"] +#![cfg_attr(not(feature = "std"), no_std)] + +use frame_support::{ + ensure, + traits::{ + fungible, Currency, Get, LockIdentifier, LockableCurrency, PollStatus, Polling, + ReservableCurrency, WithdrawReasons, + }, +}; +use sp_runtime::{ + traits::{AtLeast32BitUnsigned, Saturating, Zero}, + ArithmeticError, DispatchError, DispatchResult, Perbill, +}; +use sp_std::prelude::*; + +mod conviction; +mod types; +mod vote; +pub mod weights; +pub use conviction::Conviction; +pub use pallet::*; +pub use types::{Delegations, Tally, UnvoteScope}; +pub use vote::{AccountVote, Casting, Delegating, Vote, Voting}; +pub use weights::WeightInfo; + +#[cfg(test)] +mod tests; + +#[cfg(feature = "runtime-benchmarks")] +pub mod benchmarking; + +const CONVICTION_VOTING_ID: LockIdentifier = *b"pyconvot"; + +type BalanceOf = + <::Currency as Currency<::AccountId>>::Balance; +type VotingOf = Voting< + BalanceOf, + ::AccountId, + ::BlockNumber, + PollIndexOf, + ::MaxVotes, +>; +#[allow(dead_code)] +type DelegatingOf = Delegating< + BalanceOf, + ::AccountId, + ::BlockNumber, +>; +pub type TallyOf = Tally, ::MaxTurnout>; +pub type VotesOf = BalanceOf; +type PollIndexOf = <::Polls as Polling>>::Index; +#[cfg(feature = "runtime-benchmarks")] +type IndexOf = <::Polls as Polling>>::Index; +type ClassOf = <::Polls as Polling>>::Class; + +#[frame_support::pallet] +pub mod pallet { + use super::*; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + use sp_runtime::DispatchResult; + + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] + pub struct Pallet(_); + + #[pallet::config] + pub trait Config: frame_system::Config + Sized { + // System level stuff. + type Event: From> + IsType<::Event>; + /// Weight information for extrinsics in this pallet. + type WeightInfo: WeightInfo; + /// Currency type with which voting happens. + type Currency: ReservableCurrency + + LockableCurrency + + fungible::Inspect; + + /// The implementation of the logic which conducts polls. + type Polls: Polling, Votes = BalanceOf, Moment = Self::BlockNumber>; + + /// The maximum amount of tokens which may be used for voting. May just be + /// `Currency::total_issuance`, but you might want to reduce this in order to account for + /// funds in the system which are unable to vote (e.g. parachain auction deposits). + type MaxTurnout: Get>; + + /// The maximum number of concurrent votes an account may have. + /// + /// Also used to compute weight, an overly large value can + /// lead to extrinsic with large weight estimation: see `delegate` for instance. + #[pallet::constant] + type MaxVotes: Get; + + /// The minimum period of vote locking. + /// + /// It should be no shorter than enactment period to ensure that in the case of an approval, + /// those successful voters are locked into the consequences that their votes entail. + #[pallet::constant] + type VoteLockingPeriod: Get; + } + + /// All voting for a particular voter in a particular voting class. We store the balance for the + /// number of votes that we have recorded. + #[pallet::storage] + pub type VotingFor = StorageDoubleMap< + _, + Twox64Concat, + T::AccountId, + Twox64Concat, + ClassOf, + VotingOf, + ValueQuery, + >; + + /// The voting classes which have a non-zero lock requirement and the lock amounts which they + /// require. The actual amount locked on behalf of this pallet should always be the maximum of + /// this list. + #[pallet::storage] + pub type ClassLocksFor = + StorageMap<_, Twox64Concat, T::AccountId, Vec<(ClassOf, BalanceOf)>, ValueQuery>; + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + /// An account has delegated their vote to another account. \[who, target\] + Delegated(T::AccountId, T::AccountId), + /// An \[account\] has cancelled a previous delegation operation. + Undelegated(T::AccountId), + } + + #[pallet::error] + pub enum Error { + /// Poll is not ongoing. + NotOngoing, + /// The given account did not vote on the poll. + NotVoter, + /// The actor has no permission to conduct the action. + NoPermission, + /// The actor has no permission to conduct the action right now but will do in the future. + NoPermissionYet, + /// The account is already delegating. + AlreadyDelegating, + /// The account currently has votes attached to it and the operation cannot succeed until + /// these are removed, either through `unvote` or `reap_vote`. + AlreadyVoting, + /// Too high a balance was provided that the account cannot afford. + InsufficientFunds, + /// The account is not currently delegating. + NotDelegating, + /// Delegation to oneself makes no sense. + Nonsense, + /// Maximum number of votes reached. + MaxVotesReached, + /// The class must be supplied since it is not easily determinable from the state. + ClassNeeded, + /// The class ID supplied is invalid. + BadClass, + } + + #[pallet::call] + impl Pallet { + /// Vote in a poll. If `vote.is_aye()`, the vote is to enact the proposal; + /// otherwise it is a vote to keep the status quo. + /// + /// The dispatch origin of this call must be _Signed_. + /// + /// - `poll_index`: The index of the poll to vote for. + /// - `vote`: The vote configuration. + /// + /// Weight: `O(R)` where R is the number of polls the voter has voted on. + #[pallet::weight(T::WeightInfo::vote_new().max(T::WeightInfo::vote_existing()))] + pub fn vote( + origin: OriginFor, + #[pallet::compact] poll_index: PollIndexOf, + vote: AccountVote>, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + Self::try_vote(&who, poll_index, vote) + } + + /// Delegate the voting power (with some given conviction) of the sending account for a + /// particular class of polls. + /// + /// The balance delegated is locked for as long as it's delegated, and thereafter for the + /// time appropriate for the conviction's lock period. + /// + /// The dispatch origin of this call must be _Signed_, and the signing account must either: + /// - be delegating already; or + /// - have no voting activity (if there is, then it will need to be removed/consolidated + /// through `reap_vote` or `unvote`). + /// + /// - `to`: The account whose voting the `target` account's voting power will follow. + /// - `class`: The class of polls to delegate. To delegate multiple classes, multiple calls + /// to this function are required. + /// - `conviction`: The conviction that will be attached to the delegated votes. When the + /// account is undelegated, the funds will be locked for the corresponding period. + /// - `balance`: The amount of the account's balance to be used in delegating. This must not + /// be more than the account's current balance. + /// + /// Emits `Delegated`. + /// + /// Weight: `O(R)` where R is the number of polls the voter delegating to has + /// voted on. Weight is initially charged as if maximum votes, but is refunded later. + // NOTE: weight must cover an incorrect voting of origin with max votes, this is ensure + // because a valid delegation cover decoding a direct voting with max votes. + #[pallet::weight(T::WeightInfo::delegate(T::MaxVotes::get()))] + pub fn delegate( + origin: OriginFor, + class: ClassOf, + to: T::AccountId, + conviction: Conviction, + balance: BalanceOf, + ) -> DispatchResultWithPostInfo { + let who = ensure_signed(origin)?; + let votes = Self::try_delegate(who, class, to, conviction, balance)?; + + Ok(Some(T::WeightInfo::delegate(votes)).into()) + } + + /// Undelegate the voting power of the sending account for a particular class of polls. + /// + /// Tokens may be unlocked following once an amount of time consistent with the lock period + /// of the conviction with which the delegation was issued. + /// + /// The dispatch origin of this call must be _Signed_ and the signing account must be + /// currently delegating. + /// + /// - `class`: The class of polls to remove the delegation from. + /// + /// Emits `Undelegated`. + /// + /// Weight: `O(R)` where R is the number of polls the voter delegating to has + /// voted on. Weight is initially charged as if maximum votes, but is refunded later. + // NOTE: weight must cover an incorrect voting of origin with max votes, this is ensure + // because a valid delegation cover decoding a direct voting with max votes. + #[pallet::weight(T::WeightInfo::undelegate(T::MaxVotes::get().into()))] + pub fn undelegate(origin: OriginFor, class: ClassOf) -> DispatchResultWithPostInfo { + let who = ensure_signed(origin)?; + let votes = Self::try_undelegate(who, class)?; + Ok(Some(T::WeightInfo::undelegate(votes)).into()) + } + + /// Remove the lock caused prior voting/delegating which has expired within a particluar + /// class. + /// + /// The dispatch origin of this call must be _Signed_. + /// + /// - `class`: The class of polls to unlock. + /// - `target`: The account to remove the lock on. + /// + /// Weight: `O(R)` with R number of vote of target. + #[pallet::weight(T::WeightInfo::unlock())] + pub fn unlock( + origin: OriginFor, + class: ClassOf, + target: T::AccountId, + ) -> DispatchResult { + ensure_signed(origin)?; + Self::update_lock(&class, &target); + Ok(()) + } + + /// Remove a vote for a poll. + /// + /// If: + /// - the poll was cancelled, or + /// - the poll is ongoing, or + /// - the poll has ended such that + /// - the vote of the account was in opposition to the result; or + /// - there was no conviction to the account's vote; or + /// - the account made a split vote + /// ...then the vote is removed cleanly and a following call to `unlock` may result in more + /// funds being available. + /// + /// If, however, the poll has ended and: + /// - it finished corresponding to the vote of the account, and + /// - the account made a standard vote with conviction, and + /// - the lock period of the conviction is not over + /// ...then the lock will be aggregated into the overall account's lock, which may involve + /// *overlocking* (where the two locks are combined into a single lock that is the maximum + /// of both the amount locked and the time is it locked for). + /// + /// The dispatch origin of this call must be _Signed_, and the signer must have a vote + /// registered for poll `index`. + /// + /// - `index`: The index of poll of the vote to be removed. + /// - `class`: Optional parameter, if given it indicates the class of the poll. For polls + /// which have finished or are cancelled, this must be `Some`. + /// + /// Weight: `O(R + log R)` where R is the number of polls that `target` has voted on. + /// Weight is calculated for the maximum number of vote. + #[pallet::weight(T::WeightInfo::remove_vote())] + pub fn remove_vote( + origin: OriginFor, + class: Option>, + index: PollIndexOf, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + Self::try_remove_vote(&who, index, class, UnvoteScope::Any) + } + + /// Remove a vote for a poll. + /// + /// If the `target` is equal to the signer, then this function is exactly equivalent to + /// `remove_vote`. If not equal to the signer, then the vote must have expired, + /// either because the poll was cancelled, because the voter lost the poll or + /// because the conviction period is over. + /// + /// The dispatch origin of this call must be _Signed_. + /// + /// - `target`: The account of the vote to be removed; this account must have voted for poll + /// `index`. + /// - `index`: The index of poll of the vote to be removed. + /// - `class`: The class of the poll. + /// + /// Weight: `O(R + log R)` where R is the number of polls that `target` has voted on. + /// Weight is calculated for the maximum number of vote. + #[pallet::weight(T::WeightInfo::remove_other_vote())] + pub fn remove_other_vote( + origin: OriginFor, + target: T::AccountId, + class: ClassOf, + index: PollIndexOf, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + let scope = if target == who { UnvoteScope::Any } else { UnvoteScope::OnlyExpired }; + Self::try_remove_vote(&target, index, Some(class), scope)?; + Ok(()) + } + } +} + +impl Pallet { + /// Actually enact a vote, if legit. + fn try_vote( + who: &T::AccountId, + poll_index: PollIndexOf, + vote: AccountVote>, + ) -> DispatchResult { + ensure!(vote.balance() <= T::Currency::free_balance(who), Error::::InsufficientFunds); + T::Polls::try_access_poll(poll_index, |poll_status| { + let (tally, class) = poll_status.ensure_ongoing().ok_or(Error::::NotOngoing)?; + VotingFor::::try_mutate(who, &class, |voting| { + if let Voting::Casting(Casting { ref mut votes, delegations, .. }) = voting { + match votes.binary_search_by_key(&poll_index, |i| i.0) { + Ok(i) => { + // Shouldn't be possible to fail, but we handle it gracefully. + tally.remove(votes[i].1).ok_or(ArithmeticError::Underflow)?; + if let Some(approve) = votes[i].1.as_standard() { + tally.reduce(approve, *delegations); + } + votes[i].1 = vote; + }, + Err(i) => { + votes + .try_insert(i, (poll_index, vote)) + .map_err(|()| Error::::MaxVotesReached)?; + }, + } + // Shouldn't be possible to fail, but we handle it gracefully. + tally.add(vote).ok_or(ArithmeticError::Overflow)?; + if let Some(approve) = vote.as_standard() { + tally.increase(approve, *delegations); + } + } else { + return Err(Error::::AlreadyDelegating.into()) + } + // Extend the lock to `balance` (rather than setting it) since we don't know what + // other votes are in place. + Self::extend_lock(who, &class, vote.balance()); + Ok(()) + }) + }) + } + + /// Remove the account's vote for the given poll if possible. This is possible when: + /// - The poll has not finished. + /// - The poll has finished and the voter lost their direction. + /// - The poll has finished and the voter's lock period is up. + /// + /// This will generally be combined with a call to `unlock`. + fn try_remove_vote( + who: &T::AccountId, + poll_index: PollIndexOf, + class_hint: Option>, + scope: UnvoteScope, + ) -> DispatchResult { + let class = class_hint + .or_else(|| Some(T::Polls::as_ongoing(poll_index)?.1)) + .ok_or(Error::::ClassNeeded)?; + VotingFor::::try_mutate(who, class, |voting| { + if let Voting::Casting(Casting { ref mut votes, delegations, ref mut prior }) = voting { + let i = votes + .binary_search_by_key(&poll_index, |i| i.0) + .map_err(|_| Error::::NotVoter)?; + let v = votes.remove(i); + + T::Polls::try_access_poll(poll_index, |poll_status| match poll_status { + PollStatus::Ongoing(tally, _) => { + ensure!(matches!(scope, UnvoteScope::Any), Error::::NoPermission); + // Shouldn't be possible to fail, but we handle it gracefully. + tally.remove(v.1).ok_or(ArithmeticError::Underflow)?; + if let Some(approve) = v.1.as_standard() { + tally.reduce(approve, *delegations); + } + Ok(()) + }, + PollStatus::Completed(end, approved) => { + if let Some((lock_periods, balance)) = v.1.locked_if(approved) { + let unlock_at = end.saturating_add( + T::VoteLockingPeriod::get().saturating_mul(lock_periods.into()), + ); + let now = frame_system::Pallet::::block_number(); + if now < unlock_at { + ensure!( + matches!(scope, UnvoteScope::Any), + Error::::NoPermissionYet + ); + prior.accumulate(unlock_at, balance) + } + } + Ok(()) + }, + PollStatus::None => Ok(()), // Poll was cancelled. + }) + } else { + Ok(()) + } + }) + } + + /// Return the number of votes for `who` + fn increase_upstream_delegation( + who: &T::AccountId, + class: &ClassOf, + amount: Delegations>, + ) -> u32 { + VotingFor::::mutate(who, class, |voting| match voting { + Voting::Delegating(Delegating { delegations, .. }) => { + // We don't support second level delegating, so we don't need to do anything more. + *delegations = delegations.saturating_add(amount); + 1 + }, + Voting::Casting(Casting { votes, delegations, .. }) => { + *delegations = delegations.saturating_add(amount); + for &(poll_index, account_vote) in votes.iter() { + if let AccountVote::Standard { vote, .. } = account_vote { + T::Polls::access_poll(poll_index, |poll_status| { + if let PollStatus::Ongoing(tally, _) = poll_status { + tally.increase(vote.aye, amount); + } + }); + } + } + votes.len() as u32 + }, + }) + } + + /// Return the number of votes for `who` + fn reduce_upstream_delegation( + who: &T::AccountId, + class: &ClassOf, + amount: Delegations>, + ) -> u32 { + VotingFor::::mutate(who, class, |voting| match voting { + Voting::Delegating(Delegating { delegations, .. }) => { + // We don't support second level delegating, so we don't need to do anything more. + *delegations = delegations.saturating_sub(amount); + 1 + }, + Voting::Casting(Casting { votes, delegations, .. }) => { + *delegations = delegations.saturating_sub(amount); + for &(poll_index, account_vote) in votes.iter() { + if let AccountVote::Standard { vote, .. } = account_vote { + T::Polls::access_poll(poll_index, |poll_status| { + if let PollStatus::Ongoing(tally, _) = poll_status { + tally.reduce(vote.aye, amount); + } + }); + } + } + votes.len() as u32 + }, + }) + } + + /// Attempt to delegate `balance` times `conviction` of voting power from `who` to `target`. + /// + /// Return the upstream number of votes. + fn try_delegate( + who: T::AccountId, + class: ClassOf, + target: T::AccountId, + conviction: Conviction, + balance: BalanceOf, + ) -> Result { + ensure!(who != target, Error::::Nonsense); + T::Polls::classes().binary_search(&class).map_err(|_| Error::::BadClass)?; + ensure!(balance <= T::Currency::free_balance(&who), Error::::InsufficientFunds); + let votes = + VotingFor::::try_mutate(&who, &class, |voting| -> Result { + let old = sp_std::mem::replace( + voting, + Voting::Delegating(Delegating { + balance, + target: target.clone(), + conviction, + delegations: Default::default(), + prior: Default::default(), + }), + ); + match old { + Voting::Delegating(Delegating { .. }) => Err(Error::::AlreadyDelegating)?, + Voting::Casting(Casting { votes, delegations, prior }) => { + // here we just ensure that we're currently idling with no votes recorded. + ensure!(votes.is_empty(), Error::::AlreadyVoting); + voting.set_common(delegations, prior); + }, + } + + let votes = + Self::increase_upstream_delegation(&target, &class, conviction.votes(balance)); + // Extend the lock to `balance` (rather than setting it) since we don't know what + // other votes are in place. + Self::extend_lock(&who, &class, balance); + Ok(votes) + })?; + Self::deposit_event(Event::::Delegated(who, target)); + Ok(votes) + } + + /// Attempt to end the current delegation. + /// + /// Return the number of votes of upstream. + fn try_undelegate(who: T::AccountId, class: ClassOf) -> Result { + let votes = + VotingFor::::try_mutate(&who, &class, |voting| -> Result { + match sp_std::mem::replace(voting, Voting::default()) { + Voting::Delegating(Delegating { + balance, + target, + conviction, + delegations, + mut prior, + }) => { + // remove any delegation votes to our current target. + let votes = Self::reduce_upstream_delegation( + &target, + &class, + conviction.votes(balance), + ); + let now = frame_system::Pallet::::block_number(); + let lock_periods = conviction.lock_periods().into(); + prior.accumulate( + now.saturating_add( + T::VoteLockingPeriod::get().saturating_mul(lock_periods), + ), + balance, + ); + voting.set_common(delegations, prior); + + Ok(votes) + }, + Voting::Casting(_) => Err(Error::::NotDelegating.into()), + } + })?; + Self::deposit_event(Event::::Undelegated(who)); + Ok(votes) + } + + fn extend_lock(who: &T::AccountId, class: &ClassOf, amount: BalanceOf) { + ClassLocksFor::::mutate(who, |locks| match locks.iter().position(|x| &x.0 == class) { + Some(i) => locks[i].1 = locks[i].1.max(amount), + None => locks.push((class.clone(), amount)), + }); + T::Currency::extend_lock(CONVICTION_VOTING_ID, who, amount, WithdrawReasons::TRANSFER); + } + + /// Rejig the lock on an account. It will never get more stringent (since that would indicate + /// a security hole) but may be reduced from what they are currently. + fn update_lock(class: &ClassOf, who: &T::AccountId) { + let class_lock_needed = VotingFor::::mutate(who, class, |voting| { + voting.rejig(frame_system::Pallet::::block_number()); + voting.locked_balance() + }); + let lock_needed = ClassLocksFor::::mutate(who, |locks| { + locks.retain(|x| &x.0 != class); + if !class_lock_needed.is_zero() { + locks.push((class.clone(), class_lock_needed)); + } + locks.iter().map(|x| x.1).max().unwrap_or(Zero::zero()) + }); + if lock_needed.is_zero() { + T::Currency::remove_lock(CONVICTION_VOTING_ID, who); + } else { + T::Currency::set_lock( + CONVICTION_VOTING_ID, + who, + lock_needed, + WithdrawReasons::TRANSFER, + ); + } + } +} diff --git a/frame/conviction-voting/src/tests.rs b/frame/conviction-voting/src/tests.rs new file mode 100644 index 000000000000..cedb23b02a8d --- /dev/null +++ b/frame/conviction-voting/src/tests.rs @@ -0,0 +1,820 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2022 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. + +//! The crate's tests. + +use std::collections::BTreeMap; + +use super::*; +use crate as pallet_conviction_voting; +use frame_support::{ + assert_noop, assert_ok, parameter_types, + traits::{ConstU32, ConstU64, Contains, Polling}, +}; +use sp_core::H256; +use sp_runtime::{ + testing::Header, + traits::{BlakeTwo256, IdentityLookup}, +}; + +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlock; + +frame_support::construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + Voting: pallet_conviction_voting::{Pallet, Call, Storage, Event}, + } +); + +// Test that a fitlered call can be dispatched. +pub struct BaseFilter; +impl Contains for BaseFilter { + fn contains(call: &Call) -> bool { + !matches!(call, &Call::Balances(pallet_balances::Call::set_balance { .. })) + } +} + +parameter_types! { + pub BlockWeights: frame_system::limits::BlockWeights = + frame_system::limits::BlockWeights::simple_max(1_000_000); +} +impl frame_system::Config for Test { + type BaseCallFilter = BaseFilter; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Call = Call; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = Event; + type BlockHashCount = ConstU64<250>; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = ConstU32<16>; +} + +impl pallet_balances::Config for Test { + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; + type MaxLocks = ConstU32<10>; + type Balance = u64; + type Event = Event; + type DustRemoval = (); + type ExistentialDeposit = ConstU64<1>; + type AccountStore = System; + type WeightInfo = (); +} + +#[derive(Clone, PartialEq, Eq, Debug)] +pub enum TestPollState { + Ongoing(TallyOf, u8), + Completed(u64, bool), +} +use TestPollState::*; + +parameter_types! { + pub static Polls: BTreeMap = vec![ + (1, Completed(1, true)), + (2, Completed(2, false)), + (3, Ongoing(Tally::from_parts(0, 0, 0), 0)), + ].into_iter().collect(); +} + +pub struct TestPolls; +impl Polling> for TestPolls { + type Index = u8; + type Votes = u64; + type Moment = u64; + type Class = u8; + fn classes() -> Vec { + vec![0, 1, 2] + } + fn as_ongoing(index: u8) -> Option<(TallyOf, Self::Class)> { + Polls::get().remove(&index).and_then(|x| { + if let TestPollState::Ongoing(t, c) = x { + Some((t, c)) + } else { + None + } + }) + } + fn access_poll( + index: Self::Index, + f: impl FnOnce(PollStatus<&mut TallyOf, u64, u8>) -> R, + ) -> R { + let mut polls = Polls::get(); + let entry = polls.get_mut(&index); + let r = match entry { + Some(Ongoing(ref mut tally_mut_ref, class)) => + f(PollStatus::Ongoing(tally_mut_ref, *class)), + Some(Completed(when, succeeded)) => f(PollStatus::Completed(*when, *succeeded)), + None => f(PollStatus::None), + }; + Polls::set(polls); + r + } + fn try_access_poll( + index: Self::Index, + f: impl FnOnce(PollStatus<&mut TallyOf, u64, u8>) -> Result, + ) -> Result { + let mut polls = Polls::get(); + let entry = polls.get_mut(&index); + let r = match entry { + Some(Ongoing(ref mut tally_mut_ref, class)) => + f(PollStatus::Ongoing(tally_mut_ref, *class)), + Some(Completed(when, succeeded)) => f(PollStatus::Completed(*when, *succeeded)), + None => f(PollStatus::None), + }?; + Polls::set(polls); + Ok(r) + } + + #[cfg(feature = "runtime-benchmarks")] + fn create_ongoing(class: Self::Class) -> Result { + let mut polls = Polls::get(); + let i = polls.keys().rev().next().map_or(0, |x| x + 1); + polls.insert(i, Ongoing(Tally::default(), class)); + Polls::set(polls); + Ok(i) + } + + #[cfg(feature = "runtime-benchmarks")] + fn end_ongoing(index: Self::Index, approved: bool) -> Result<(), ()> { + let mut polls = Polls::get(); + match polls.get(&index) { + Some(Ongoing(..)) => {}, + _ => return Err(()), + } + let now = frame_system::Pallet::::block_number(); + polls.insert(index, Completed(now, approved)); + Polls::set(polls); + Ok(()) + } +} + +impl Config for Test { + type Event = Event; + type Currency = pallet_balances::Pallet; + type VoteLockingPeriod = ConstU64<3>; + type MaxVotes = ConstU32<3>; + type WeightInfo = (); + type MaxTurnout = frame_support::traits::TotalIssuanceOf; + type Polls = TestPolls; +} + +pub fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + pallet_balances::GenesisConfig:: { + balances: vec![(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)], + } + .assimilate_storage(&mut t) + .unwrap(); + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| System::set_block_number(1)); + ext +} + +#[test] +fn params_should_work() { + new_test_ext().execute_with(|| { + assert_eq!(Balances::free_balance(42), 0); + assert_eq!(Balances::total_issuance(), 210); + }); +} + +fn next_block() { + System::set_block_number(System::block_number() + 1); +} + +#[allow(dead_code)] +fn run_to(n: u64) { + while System::block_number() < n { + next_block(); + } +} + +fn aye(amount: u64, conviction: u8) -> AccountVote { + let vote = Vote { aye: true, conviction: conviction.try_into().unwrap() }; + AccountVote::Standard { vote, balance: amount } +} + +fn nay(amount: u64, conviction: u8) -> AccountVote { + let vote = Vote { aye: false, conviction: conviction.try_into().unwrap() }; + AccountVote::Standard { vote, balance: amount } +} + +fn tally(index: u8) -> TallyOf { + >>::as_ongoing(index).expect("No poll").0 +} + +fn class(index: u8) -> u8 { + >>::as_ongoing(index).expect("No poll").1 +} + +#[test] +#[ignore] +#[should_panic(expected = "No poll")] +fn unknown_poll_should_panic() { + let _ = tally(0); +} + +#[test] +#[ignore] +#[should_panic(expected = "No poll")] +fn completed_poll_should_panic() { + let _ = tally(1); +} + +#[test] +fn basic_stuff() { + new_test_ext().execute_with(|| { + assert_eq!(tally(3), Tally::from_parts(0, 0, 0)); + }); +} + +#[test] +fn basic_voting_works() { + new_test_ext().execute_with(|| { + assert_ok!(Voting::vote(Origin::signed(1), 3, aye(2, 5))); + assert_eq!(tally(3), Tally::from_parts(10, 0, 2)); + assert_ok!(Voting::vote(Origin::signed(1), 3, nay(2, 5))); + assert_eq!(tally(3), Tally::from_parts(0, 10, 2)); + assert_eq!(Balances::usable_balance(1), 8); + + assert_ok!(Voting::vote(Origin::signed(1), 3, aye(5, 1))); + assert_eq!(tally(3), Tally::from_parts(5, 0, 5)); + assert_ok!(Voting::vote(Origin::signed(1), 3, nay(5, 1))); + assert_eq!(tally(3), Tally::from_parts(0, 5, 5)); + assert_eq!(Balances::usable_balance(1), 5); + + assert_ok!(Voting::vote(Origin::signed(1), 3, aye(10, 0))); + assert_eq!(tally(3), Tally::from_parts(1, 0, 10)); + assert_ok!(Voting::vote(Origin::signed(1), 3, nay(10, 0))); + assert_eq!(tally(3), Tally::from_parts(0, 1, 10)); + assert_eq!(Balances::usable_balance(1), 0); + + assert_ok!(Voting::remove_vote(Origin::signed(1), None, 3)); + assert_eq!(tally(3), Tally::from_parts(0, 0, 0)); + + assert_ok!(Voting::unlock(Origin::signed(1), class(3), 1)); + assert_eq!(Balances::usable_balance(1), 10); + }); +} + +#[test] +fn voting_balance_gets_locked() { + new_test_ext().execute_with(|| { + assert_ok!(Voting::vote(Origin::signed(1), 3, aye(2, 5))); + assert_eq!(tally(3), Tally::from_parts(10, 0, 2)); + assert_ok!(Voting::vote(Origin::signed(1), 3, nay(2, 5))); + assert_eq!(tally(3), Tally::from_parts(0, 10, 2)); + assert_eq!(Balances::usable_balance(1), 8); + + assert_ok!(Voting::vote(Origin::signed(1), 3, aye(5, 1))); + assert_eq!(tally(3), Tally::from_parts(5, 0, 5)); + assert_ok!(Voting::vote(Origin::signed(1), 3, nay(5, 1))); + assert_eq!(tally(3), Tally::from_parts(0, 5, 5)); + assert_eq!(Balances::usable_balance(1), 5); + + assert_ok!(Voting::vote(Origin::signed(1), 3, aye(10, 0))); + assert_eq!(tally(3), Tally::from_parts(1, 0, 10)); + assert_ok!(Voting::vote(Origin::signed(1), 3, nay(10, 0))); + assert_eq!(tally(3), Tally::from_parts(0, 1, 10)); + assert_eq!(Balances::usable_balance(1), 0); + + assert_ok!(Voting::remove_vote(Origin::signed(1), None, 3)); + assert_eq!(tally(3), Tally::from_parts(0, 0, 0)); + + assert_ok!(Voting::unlock(Origin::signed(1), class(3), 1)); + assert_eq!(Balances::usable_balance(1), 10); + }); +} + +#[test] +fn successful_but_zero_conviction_vote_balance_can_be_unlocked() { + new_test_ext().execute_with(|| { + assert_ok!(Voting::vote(Origin::signed(1), 3, aye(1, 1))); + assert_ok!(Voting::vote(Origin::signed(2), 3, nay(20, 0))); + let c = class(3); + Polls::set(vec![(3, Completed(3, false))].into_iter().collect()); + assert_ok!(Voting::remove_vote(Origin::signed(2), Some(c), 3)); + assert_ok!(Voting::unlock(Origin::signed(2), c, 2)); + assert_eq!(Balances::usable_balance(2), 20); + }); +} + +#[test] +fn unsuccessful_conviction_vote_balance_can_be_unlocked() { + new_test_ext().execute_with(|| { + assert_ok!(Voting::vote(Origin::signed(1), 3, aye(1, 1))); + assert_ok!(Voting::vote(Origin::signed(2), 3, nay(20, 0))); + let c = class(3); + Polls::set(vec![(3, Completed(3, false))].into_iter().collect()); + assert_ok!(Voting::remove_vote(Origin::signed(1), Some(c), 3)); + assert_ok!(Voting::unlock(Origin::signed(1), c, 1)); + assert_eq!(Balances::usable_balance(1), 10); + }); +} + +#[test] +fn successful_conviction_vote_balance_stays_locked_for_correct_time() { + new_test_ext().execute_with(|| { + for i in 1..=5 { + assert_ok!(Voting::vote(Origin::signed(i), 3, aye(10, i as u8))); + } + let c = class(3); + Polls::set(vec![(3, Completed(3, true))].into_iter().collect()); + for i in 1..=5 { + assert_ok!(Voting::remove_vote(Origin::signed(i), Some(c), 3)); + } + for block in 1..=(3 + 5 * 3) { + run_to(block); + for i in 1..=5 { + assert_ok!(Voting::unlock(Origin::signed(i), c, i)); + let expired = block >= (3 << (i - 1)) + 3; + assert_eq!(Balances::usable_balance(i), i * 10 - if expired { 0 } else { 10 }); + } + } + }); +} + +#[test] +fn classwise_delegation_works() { + new_test_ext().execute_with(|| { + Polls::set( + vec![ + (0, Ongoing(Tally::default(), 0)), + (1, Ongoing(Tally::default(), 1)), + (2, Ongoing(Tally::default(), 2)), + (3, Ongoing(Tally::default(), 2)), + ] + .into_iter() + .collect(), + ); + assert_ok!(Voting::delegate(Origin::signed(1), 0, 2, Conviction::Locked1x, 5)); + assert_ok!(Voting::delegate(Origin::signed(1), 1, 3, Conviction::Locked1x, 5)); + assert_ok!(Voting::delegate(Origin::signed(1), 2, 4, Conviction::Locked1x, 5)); + assert_eq!(Balances::usable_balance(1), 5); + + assert_ok!(Voting::vote(Origin::signed(2), 0, aye(10, 0))); + assert_ok!(Voting::vote(Origin::signed(2), 1, nay(10, 0))); + assert_ok!(Voting::vote(Origin::signed(2), 2, nay(10, 0))); + assert_ok!(Voting::vote(Origin::signed(3), 0, nay(10, 0))); + assert_ok!(Voting::vote(Origin::signed(3), 1, aye(10, 0))); + assert_ok!(Voting::vote(Origin::signed(3), 2, nay(10, 0))); + assert_ok!(Voting::vote(Origin::signed(4), 0, nay(10, 0))); + assert_ok!(Voting::vote(Origin::signed(4), 1, nay(10, 0))); + assert_ok!(Voting::vote(Origin::signed(4), 2, aye(10, 0))); + // 4 hasn't voted yet + + assert_eq!( + Polls::get(), + vec![ + (0, Ongoing(Tally::from_parts(6, 2, 35), 0)), + (1, Ongoing(Tally::from_parts(6, 2, 35), 1)), + (2, Ongoing(Tally::from_parts(6, 2, 35), 2)), + (3, Ongoing(Tally::from_parts(0, 0, 0), 2)), + ] + .into_iter() + .collect() + ); + + // 4 votes nay to 3. + assert_ok!(Voting::vote(Origin::signed(4), 3, nay(10, 0))); + assert_eq!( + Polls::get(), + vec![ + (0, Ongoing(Tally::from_parts(6, 2, 35), 0)), + (1, Ongoing(Tally::from_parts(6, 2, 35), 1)), + (2, Ongoing(Tally::from_parts(6, 2, 35), 2)), + (3, Ongoing(Tally::from_parts(0, 6, 15), 2)), + ] + .into_iter() + .collect() + ); + + // Redelegate for class 2 to account 3. + assert_ok!(Voting::undelegate(Origin::signed(1), 2)); + assert_ok!(Voting::delegate(Origin::signed(1), 2, 3, Conviction::Locked1x, 5)); + assert_eq!( + Polls::get(), + vec![ + (0, Ongoing(Tally::from_parts(6, 2, 35), 0)), + (1, Ongoing(Tally::from_parts(6, 2, 35), 1)), + (2, Ongoing(Tally::from_parts(1, 7, 35), 2)), + (3, Ongoing(Tally::from_parts(0, 1, 10), 2)), + ] + .into_iter() + .collect() + ); + + // Redelegating with a lower lock does not forget previous lock and updates correctly. + assert_ok!(Voting::undelegate(Origin::signed(1), 0)); + assert_ok!(Voting::undelegate(Origin::signed(1), 1)); + assert_ok!(Voting::undelegate(Origin::signed(1), 2)); + assert_ok!(Voting::delegate(Origin::signed(1), 0, 2, Conviction::Locked1x, 3)); + assert_ok!(Voting::delegate(Origin::signed(1), 1, 3, Conviction::Locked1x, 3)); + assert_ok!(Voting::delegate(Origin::signed(1), 2, 4, Conviction::Locked1x, 3)); + assert_eq!( + Polls::get(), + vec![ + (0, Ongoing(Tally::from_parts(4, 2, 33), 0)), + (1, Ongoing(Tally::from_parts(4, 2, 33), 1)), + (2, Ongoing(Tally::from_parts(4, 2, 33), 2)), + (3, Ongoing(Tally::from_parts(0, 4, 13), 2)), + ] + .into_iter() + .collect() + ); + assert_eq!(Balances::usable_balance(1), 5); + + assert_ok!(Voting::unlock(Origin::signed(1), 0, 1)); + assert_ok!(Voting::unlock(Origin::signed(1), 1, 1)); + assert_ok!(Voting::unlock(Origin::signed(1), 2, 1)); + // unlock does nothing since the delegation already took place. + assert_eq!(Balances::usable_balance(1), 5); + + // Redelegating with higher amount extends previous lock. + assert_ok!(Voting::undelegate(Origin::signed(1), 0)); + assert_ok!(Voting::delegate(Origin::signed(1), 0, 2, Conviction::Locked1x, 6)); + assert_ok!(Voting::unlock(Origin::signed(1), 0, 1)); + assert_eq!(Balances::usable_balance(1), 4); + assert_ok!(Voting::undelegate(Origin::signed(1), 1)); + assert_ok!(Voting::delegate(Origin::signed(1), 1, 3, Conviction::Locked1x, 7)); + assert_ok!(Voting::unlock(Origin::signed(1), 1, 1)); + assert_eq!(Balances::usable_balance(1), 3); + assert_ok!(Voting::undelegate(Origin::signed(1), 2)); + assert_ok!(Voting::delegate(Origin::signed(1), 2, 4, Conviction::Locked1x, 8)); + assert_ok!(Voting::unlock(Origin::signed(1), 2, 1)); + assert_eq!(Balances::usable_balance(1), 2); + assert_eq!( + Polls::get(), + vec![ + (0, Ongoing(Tally::from_parts(7, 2, 36), 0)), + (1, Ongoing(Tally::from_parts(8, 2, 37), 1)), + (2, Ongoing(Tally::from_parts(9, 2, 38), 2)), + (3, Ongoing(Tally::from_parts(0, 9, 18), 2)), + ] + .into_iter() + .collect() + ); + }); +} + +#[test] +fn redelegation_after_vote_ending_should_keep_lock() { + new_test_ext().execute_with(|| { + Polls::set(vec![(0, Ongoing(Tally::default(), 0))].into_iter().collect()); + assert_ok!(Voting::delegate(Origin::signed(1), 0, 2, Conviction::Locked1x, 5)); + assert_ok!(Voting::vote(Origin::signed(2), 0, aye(10, 1))); + Polls::set(vec![(0, Completed(1, true))].into_iter().collect()); + assert_eq!(Balances::usable_balance(1), 5); + assert_ok!(Voting::undelegate(Origin::signed(1), 0)); + assert_ok!(Voting::delegate(Origin::signed(1), 0, 3, Conviction::Locked1x, 3)); + assert_eq!(Balances::usable_balance(1), 5); + assert_ok!(Voting::unlock(Origin::signed(1), 0, 1)); + assert_eq!(Balances::usable_balance(1), 5); + }); +} + +#[test] +fn lock_amalgamation_valid_with_multiple_removed_votes() { + new_test_ext().execute_with(|| { + Polls::set( + vec![ + (0, Ongoing(Tally::default(), 0)), + (1, Ongoing(Tally::default(), 0)), + (2, Ongoing(Tally::default(), 0)), + ] + .into_iter() + .collect(), + ); + assert_ok!(Voting::vote(Origin::signed(1), 0, aye(5, 1))); + assert_ok!(Voting::vote(Origin::signed(1), 1, aye(10, 1))); + assert_ok!(Voting::vote(Origin::signed(1), 2, aye(5, 2))); + assert_eq!(Balances::usable_balance(1), 0); + + Polls::set( + vec![(0, Completed(1, true)), (1, Completed(1, true)), (2, Completed(1, true))] + .into_iter() + .collect(), + ); + assert_ok!(Voting::remove_vote(Origin::signed(1), Some(0), 0)); + assert_ok!(Voting::unlock(Origin::signed(1), 0, 1)); + assert_eq!(Balances::usable_balance(1), 0); + + assert_ok!(Voting::remove_vote(Origin::signed(1), Some(0), 1)); + assert_ok!(Voting::unlock(Origin::signed(1), 0, 1)); + assert_eq!(Balances::usable_balance(1), 0); + + assert_ok!(Voting::remove_vote(Origin::signed(1), Some(0), 2)); + assert_ok!(Voting::unlock(Origin::signed(1), 0, 1)); + assert_eq!(Balances::usable_balance(1), 0); + + run_to(3); + assert_ok!(Voting::unlock(Origin::signed(1), 0, 1)); + assert_eq!(Balances::usable_balance(1), 0); + + run_to(6); + assert_ok!(Voting::unlock(Origin::signed(1), 0, 1)); + assert!(Balances::usable_balance(1) <= 5); + + run_to(7); + assert_ok!(Voting::unlock(Origin::signed(1), 0, 1)); + assert_eq!(Balances::usable_balance(1), 10); + }); +} + +#[test] +fn lock_amalgamation_valid_with_multiple_delegations() { + new_test_ext().execute_with(|| { + assert_ok!(Voting::delegate(Origin::signed(1), 0, 2, Conviction::Locked1x, 5)); + assert_ok!(Voting::undelegate(Origin::signed(1), 0)); + assert_ok!(Voting::delegate(Origin::signed(1), 0, 2, Conviction::Locked1x, 10)); + assert_ok!(Voting::undelegate(Origin::signed(1), 0)); + assert_ok!(Voting::delegate(Origin::signed(1), 0, 2, Conviction::Locked2x, 5)); + assert_ok!(Voting::unlock(Origin::signed(1), 0, 1)); + assert_eq!(Balances::usable_balance(1), 0); + assert_ok!(Voting::undelegate(Origin::signed(1), 0)); + + run_to(3); + assert_ok!(Voting::unlock(Origin::signed(1), 0, 1)); + assert_eq!(Balances::usable_balance(1), 0); + + run_to(6); + assert_ok!(Voting::unlock(Origin::signed(1), 0, 1)); + assert!(Balances::usable_balance(1) <= 5); + + run_to(7); + assert_ok!(Voting::unlock(Origin::signed(1), 0, 1)); + assert_eq!(Balances::usable_balance(1), 10); + }); +} + +#[test] +fn lock_amalgamation_valid_with_move_roundtrip_to_delegation() { + new_test_ext().execute_with(|| { + Polls::set(vec![(0, Ongoing(Tally::default(), 0))].into_iter().collect()); + assert_ok!(Voting::vote(Origin::signed(1), 0, aye(5, 1))); + Polls::set(vec![(0, Completed(1, true))].into_iter().collect()); + assert_ok!(Voting::remove_vote(Origin::signed(1), Some(0), 0)); + assert_ok!(Voting::unlock(Origin::signed(1), 0, 1)); + assert_eq!(Balances::usable_balance(1), 5); + + assert_ok!(Voting::delegate(Origin::signed(1), 0, 2, Conviction::Locked1x, 10)); + assert_ok!(Voting::undelegate(Origin::signed(1), 0)); + assert_ok!(Voting::unlock(Origin::signed(1), 0, 1)); + assert_eq!(Balances::usable_balance(1), 0); + + Polls::set(vec![(1, Ongoing(Tally::default(), 0))].into_iter().collect()); + assert_ok!(Voting::vote(Origin::signed(1), 1, aye(5, 2))); + Polls::set(vec![(1, Completed(1, true))].into_iter().collect()); + assert_ok!(Voting::remove_vote(Origin::signed(1), Some(0), 1)); + + run_to(3); + assert_ok!(Voting::unlock(Origin::signed(1), 0, 1)); + assert_eq!(Balances::usable_balance(1), 0); + + run_to(6); + assert_ok!(Voting::unlock(Origin::signed(1), 0, 1)); + assert!(Balances::usable_balance(1) <= 5); + + run_to(7); + assert_ok!(Voting::unlock(Origin::signed(1), 0, 1)); + assert_eq!(Balances::usable_balance(1), 10); + }); +} + +#[test] +fn lock_amalgamation_valid_with_move_roundtrip_to_casting() { + new_test_ext().execute_with(|| { + assert_ok!(Voting::delegate(Origin::signed(1), 0, 2, Conviction::Locked1x, 5)); + assert_ok!(Voting::undelegate(Origin::signed(1), 0)); + + assert_ok!(Voting::unlock(Origin::signed(1), 0, 1)); + assert_eq!(Balances::usable_balance(1), 5); + + Polls::set(vec![(0, Ongoing(Tally::default(), 0))].into_iter().collect()); + assert_ok!(Voting::vote(Origin::signed(1), 0, aye(10, 1))); + Polls::set(vec![(0, Completed(1, true))].into_iter().collect()); + assert_ok!(Voting::remove_vote(Origin::signed(1), Some(0), 0)); + + assert_ok!(Voting::unlock(Origin::signed(1), 0, 1)); + assert_eq!(Balances::usable_balance(1), 0); + + assert_ok!(Voting::delegate(Origin::signed(1), 0, 2, Conviction::Locked2x, 10)); + assert_ok!(Voting::undelegate(Origin::signed(1), 0)); + + run_to(3); + assert_ok!(Voting::unlock(Origin::signed(1), 0, 1)); + assert_eq!(Balances::usable_balance(1), 0); + + run_to(6); + assert_ok!(Voting::unlock(Origin::signed(1), 0, 1)); + assert!(Balances::usable_balance(1) <= 5); + + run_to(7); + assert_ok!(Voting::unlock(Origin::signed(1), 0, 1)); + assert_eq!(Balances::usable_balance(1), 10); + }); +} + +#[test] +fn lock_aggregation_over_different_classes_with_delegation_works() { + new_test_ext().execute_with(|| { + assert_ok!(Voting::delegate(Origin::signed(1), 0, 2, Conviction::Locked1x, 5)); + assert_ok!(Voting::delegate(Origin::signed(1), 1, 2, Conviction::Locked2x, 5)); + assert_ok!(Voting::delegate(Origin::signed(1), 2, 2, Conviction::Locked1x, 10)); + + assert_ok!(Voting::undelegate(Origin::signed(1), 0)); + assert_ok!(Voting::undelegate(Origin::signed(1), 1)); + assert_ok!(Voting::undelegate(Origin::signed(1), 2)); + + run_to(3); + assert_ok!(Voting::unlock(Origin::signed(1), 0, 1)); + assert_ok!(Voting::unlock(Origin::signed(1), 1, 1)); + assert_ok!(Voting::unlock(Origin::signed(1), 2, 1)); + assert_eq!(Balances::usable_balance(1), 0); + + run_to(6); + assert_ok!(Voting::unlock(Origin::signed(1), 0, 1)); + assert_ok!(Voting::unlock(Origin::signed(1), 1, 1)); + assert_ok!(Voting::unlock(Origin::signed(1), 2, 1)); + assert_eq!(Balances::usable_balance(1), 5); + + run_to(7); + assert_ok!(Voting::unlock(Origin::signed(1), 0, 1)); + assert_ok!(Voting::unlock(Origin::signed(1), 1, 1)); + assert_ok!(Voting::unlock(Origin::signed(1), 2, 1)); + assert_eq!(Balances::usable_balance(1), 10); + }); +} + +#[test] +fn lock_aggregation_over_different_classes_with_casting_works() { + new_test_ext().execute_with(|| { + Polls::set( + vec![ + (0, Ongoing(Tally::default(), 0)), + (1, Ongoing(Tally::default(), 1)), + (2, Ongoing(Tally::default(), 2)), + ] + .into_iter() + .collect(), + ); + assert_ok!(Voting::vote(Origin::signed(1), 0, aye(5, 1))); + assert_ok!(Voting::vote(Origin::signed(1), 1, aye(10, 1))); + assert_ok!(Voting::vote(Origin::signed(1), 2, aye(5, 2))); + Polls::set( + vec![(0, Completed(1, true)), (1, Completed(1, true)), (2, Completed(1, true))] + .into_iter() + .collect(), + ); + assert_ok!(Voting::remove_vote(Origin::signed(1), Some(0), 0)); + assert_ok!(Voting::remove_vote(Origin::signed(1), Some(1), 1)); + assert_ok!(Voting::remove_vote(Origin::signed(1), Some(2), 2)); + + run_to(3); + assert_ok!(Voting::unlock(Origin::signed(1), 0, 1)); + assert_ok!(Voting::unlock(Origin::signed(1), 1, 1)); + assert_ok!(Voting::unlock(Origin::signed(1), 2, 1)); + assert_eq!(Balances::usable_balance(1), 0); + + run_to(6); + assert_ok!(Voting::unlock(Origin::signed(1), 0, 1)); + assert_ok!(Voting::unlock(Origin::signed(1), 1, 1)); + assert_ok!(Voting::unlock(Origin::signed(1), 2, 1)); + assert_eq!(Balances::usable_balance(1), 5); + + run_to(7); + assert_ok!(Voting::unlock(Origin::signed(1), 0, 1)); + assert_ok!(Voting::unlock(Origin::signed(1), 1, 1)); + assert_ok!(Voting::unlock(Origin::signed(1), 2, 1)); + assert_eq!(Balances::usable_balance(1), 10); + }); +} + +#[test] +fn errors_with_vote_work() { + new_test_ext().execute_with(|| { + assert_noop!(Voting::vote(Origin::signed(1), 0, aye(10, 0)), Error::::NotOngoing); + assert_noop!(Voting::vote(Origin::signed(1), 1, aye(10, 0)), Error::::NotOngoing); + assert_noop!(Voting::vote(Origin::signed(1), 2, aye(10, 0)), Error::::NotOngoing); + assert_noop!( + Voting::vote(Origin::signed(1), 3, aye(11, 0)), + Error::::InsufficientFunds + ); + + assert_ok!(Voting::delegate(Origin::signed(1), 0, 2, Conviction::None, 10)); + assert_noop!( + Voting::vote(Origin::signed(1), 3, aye(10, 0)), + Error::::AlreadyDelegating + ); + + assert_ok!(Voting::undelegate(Origin::signed(1), 0)); + Polls::set( + vec![ + (0, Ongoing(Tally::default(), 0)), + (1, Ongoing(Tally::default(), 0)), + (2, Ongoing(Tally::default(), 0)), + (3, Ongoing(Tally::default(), 0)), + ] + .into_iter() + .collect(), + ); + assert_ok!(Voting::vote(Origin::signed(1), 0, aye(10, 0))); + assert_ok!(Voting::vote(Origin::signed(1), 1, aye(10, 0))); + assert_ok!(Voting::vote(Origin::signed(1), 2, aye(10, 0))); + assert_noop!( + Voting::vote(Origin::signed(1), 3, aye(10, 0)), + Error::::MaxVotesReached + ); + }); +} + +#[test] +fn errors_with_delegating_work() { + new_test_ext().execute_with(|| { + assert_noop!( + Voting::delegate(Origin::signed(1), 0, 2, Conviction::None, 11), + Error::::InsufficientFunds + ); + assert_noop!( + Voting::delegate(Origin::signed(1), 3, 2, Conviction::None, 10), + Error::::BadClass + ); + + assert_ok!(Voting::vote(Origin::signed(1), 3, aye(10, 0))); + assert_noop!( + Voting::delegate(Origin::signed(1), 0, 2, Conviction::None, 10), + Error::::AlreadyVoting + ); + + assert_noop!(Voting::undelegate(Origin::signed(1), 0), Error::::NotDelegating); + }); +} + +#[test] +fn remove_other_vote_works() { + new_test_ext().execute_with(|| { + assert_noop!( + Voting::remove_other_vote(Origin::signed(2), 1, 0, 3), + Error::::NotVoter + ); + assert_ok!(Voting::vote(Origin::signed(1), 3, aye(10, 2))); + assert_noop!( + Voting::remove_other_vote(Origin::signed(2), 1, 0, 3), + Error::::NoPermission + ); + Polls::set(vec![(3, Completed(1, true))].into_iter().collect()); + run_to(6); + assert_noop!( + Voting::remove_other_vote(Origin::signed(2), 1, 0, 3), + Error::::NoPermissionYet + ); + run_to(7); + assert_ok!(Voting::remove_other_vote(Origin::signed(2), 1, 0, 3)); + }); +} + +#[test] +fn errors_with_remove_vote_work() { + new_test_ext().execute_with(|| { + assert_noop!(Voting::remove_vote(Origin::signed(1), Some(0), 3), Error::::NotVoter); + assert_ok!(Voting::vote(Origin::signed(1), 3, aye(10, 2))); + Polls::set(vec![(3, Completed(1, true))].into_iter().collect()); + assert_noop!(Voting::remove_vote(Origin::signed(1), None, 3), Error::::ClassNeeded); + }); +} diff --git a/frame/conviction-voting/src/types.rs b/frame/conviction-voting/src/types.rs new file mode 100644 index 000000000000..2ad1a164dd14 --- /dev/null +++ b/frame/conviction-voting/src/types.rs @@ -0,0 +1,236 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2022 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. + +//! Miscellaneous additional datatypes. + +use sp_std::marker::PhantomData; + +use super::*; +use crate::{AccountVote, Conviction, Vote}; +use codec::{Codec, Decode, Encode, MaxEncodedLen}; +use frame_support::{ + traits::VoteTally, CloneNoBound, DefaultNoBound, EqNoBound, PartialEqNoBound, + RuntimeDebugNoBound, +}; +use scale_info::TypeInfo; +use sp_runtime::{ + traits::{Saturating, Zero}, + RuntimeDebug, +}; + +/// Info regarding an ongoing referendum. +#[derive( + CloneNoBound, + DefaultNoBound, + PartialEqNoBound, + EqNoBound, + RuntimeDebugNoBound, + TypeInfo, + Encode, + Decode, + MaxEncodedLen, +)] +#[scale_info(skip_type_params(Total))] +pub struct Tally< + Votes: Clone + Default + PartialEq + Eq + sp_std::fmt::Debug + TypeInfo + Codec, + Total, +> { + /// The number of aye votes, expressed in terms of post-conviction lock-vote. + pub ayes: Votes, + /// The number of nay votes, expressed in terms of post-conviction lock-vote. + pub nays: Votes, + /// The amount of funds currently expressing its opinion. Pre-conviction. + pub turnout: Votes, + /// Dummy. + dummy: PhantomData, +} + +impl< + Votes: Clone + + Default + + PartialEq + + Eq + + sp_std::fmt::Debug + + Copy + + AtLeast32BitUnsigned + + TypeInfo + + Codec, + Total: Get, + > VoteTally for Tally +{ + fn ayes(&self) -> Votes { + self.ayes + } + + fn turnout(&self) -> Perbill { + Perbill::from_rational(self.turnout, Total::get()) + } + + fn approval(&self) -> Perbill { + Perbill::from_rational(self.ayes, self.ayes.saturating_add(self.nays)) + } + + #[cfg(feature = "runtime-benchmarks")] + fn unanimity() -> Self { + Self { ayes: Total::get(), nays: Zero::zero(), turnout: Total::get(), dummy: PhantomData } + } + + #[cfg(feature = "runtime-benchmarks")] + fn from_requirements(turnout: Perbill, approval: Perbill) -> Self { + let turnout = turnout.mul_ceil(Total::get()); + let ayes = approval.mul_ceil(turnout); + Self { ayes, nays: turnout - ayes, turnout, dummy: PhantomData } + } +} + +impl< + Votes: Clone + + Default + + PartialEq + + Eq + + sp_std::fmt::Debug + + Copy + + AtLeast32BitUnsigned + + TypeInfo + + Codec, + Total: Get, + > Tally +{ + /// Create a new tally. + pub fn new(vote: Vote, balance: Votes) -> Self { + let Delegations { votes, capital } = vote.conviction.votes(balance); + Self { + ayes: if vote.aye { votes } else { Zero::zero() }, + nays: if vote.aye { Zero::zero() } else { votes }, + turnout: capital, + dummy: PhantomData, + } + } + + pub fn from_parts(ayes: Votes, nays: Votes, turnout: Votes) -> Self { + Self { ayes, nays, turnout, dummy: PhantomData } + } + + /// Add an account's vote into the tally. + pub fn add(&mut self, vote: AccountVote) -> Option<()> { + match vote { + AccountVote::Standard { vote, balance } => { + let Delegations { votes, capital } = vote.conviction.votes(balance); + self.turnout = self.turnout.checked_add(&capital)?; + match vote.aye { + true => self.ayes = self.ayes.checked_add(&votes)?, + false => self.nays = self.nays.checked_add(&votes)?, + } + }, + AccountVote::Split { aye, nay } => { + let aye = Conviction::None.votes(aye); + let nay = Conviction::None.votes(nay); + self.turnout = self.turnout.checked_add(&aye.capital)?.checked_add(&nay.capital)?; + self.ayes = self.ayes.checked_add(&aye.votes)?; + self.nays = self.nays.checked_add(&nay.votes)?; + }, + } + Some(()) + } + + /// Remove an account's vote from the tally. + pub fn remove(&mut self, vote: AccountVote) -> Option<()> { + match vote { + AccountVote::Standard { vote, balance } => { + let Delegations { votes, capital } = vote.conviction.votes(balance); + self.turnout = self.turnout.checked_sub(&capital)?; + match vote.aye { + true => self.ayes = self.ayes.checked_sub(&votes)?, + false => self.nays = self.nays.checked_sub(&votes)?, + } + }, + AccountVote::Split { aye, nay } => { + let aye = Conviction::None.votes(aye); + let nay = Conviction::None.votes(nay); + self.turnout = self.turnout.checked_sub(&aye.capital)?.checked_sub(&nay.capital)?; + self.ayes = self.ayes.checked_sub(&aye.votes)?; + self.nays = self.nays.checked_sub(&nay.votes)?; + }, + } + Some(()) + } + + /// Increment some amount of votes. + pub fn increase(&mut self, approve: bool, delegations: Delegations) { + self.turnout = self.turnout.saturating_add(delegations.capital); + match approve { + true => self.ayes = self.ayes.saturating_add(delegations.votes), + false => self.nays = self.nays.saturating_add(delegations.votes), + } + } + + /// Decrement some amount of votes. + pub fn reduce(&mut self, approve: bool, delegations: Delegations) { + self.turnout = self.turnout.saturating_sub(delegations.capital); + match approve { + true => self.ayes = self.ayes.saturating_sub(delegations.votes), + false => self.nays = self.nays.saturating_sub(delegations.votes), + } + } +} + +/// Amount of votes and capital placed in delegation for an account. +#[derive( + Encode, Decode, Default, Copy, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen, +)] +pub struct Delegations { + /// The number of votes (this is post-conviction). + pub votes: Balance, + /// The amount of raw capital, used for the turnout. + pub capital: Balance, +} + +impl Saturating for Delegations { + fn saturating_add(self, o: Self) -> Self { + Self { + votes: self.votes.saturating_add(o.votes), + capital: self.capital.saturating_add(o.capital), + } + } + + fn saturating_sub(self, o: Self) -> Self { + Self { + votes: self.votes.saturating_sub(o.votes), + capital: self.capital.saturating_sub(o.capital), + } + } + + fn saturating_mul(self, o: Self) -> Self { + Self { + votes: self.votes.saturating_mul(o.votes), + capital: self.capital.saturating_mul(o.capital), + } + } + + fn saturating_pow(self, exp: usize) -> Self { + Self { votes: self.votes.saturating_pow(exp), capital: self.capital.saturating_pow(exp) } + } +} + +/// Whether an `unvote` operation is able to make actions that are not strictly always in the +/// interest of an account. +pub enum UnvoteScope { + /// Permitted to do everything. + Any, + /// Permitted to do only the changes that do not need the owner's permission. + OnlyExpired, +} diff --git a/frame/conviction-voting/src/vote.rs b/frame/conviction-voting/src/vote.rs new file mode 100644 index 000000000000..d7ca931de35a --- /dev/null +++ b/frame/conviction-voting/src/vote.rs @@ -0,0 +1,254 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2022 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. + +//! The vote datatype. + +use crate::{Conviction, Delegations}; +use codec::{Decode, Encode, EncodeLike, Input, MaxEncodedLen, Output}; +use frame_support::{pallet_prelude::Get, BoundedVec}; +use scale_info::TypeInfo; +use sp_runtime::{ + traits::{Saturating, Zero}, + RuntimeDebug, +}; +use sp_std::{convert::TryFrom, prelude::*, result::Result}; + +/// A number of lock periods, plus a vote, one way or the other. +#[derive(Copy, Clone, Eq, PartialEq, Default, RuntimeDebug, MaxEncodedLen)] +pub struct Vote { + pub aye: bool, + pub conviction: Conviction, +} + +impl Encode for Vote { + fn encode_to(&self, output: &mut T) { + output.push_byte(u8::from(self.conviction) | if self.aye { 0b1000_0000 } else { 0 }); + } +} + +impl EncodeLike for Vote {} + +impl Decode for Vote { + fn decode(input: &mut I) -> Result { + let b = input.read_byte()?; + Ok(Vote { + aye: (b & 0b1000_0000) == 0b1000_0000, + conviction: Conviction::try_from(b & 0b0111_1111) + .map_err(|_| codec::Error::from("Invalid conviction"))?, + }) + } +} + +impl TypeInfo for Vote { + type Identity = Self; + + fn type_info() -> scale_info::Type { + scale_info::Type::builder() + .path(scale_info::Path::new("Vote", module_path!())) + .composite( + scale_info::build::Fields::unnamed() + .field(|f| f.ty::().docs(&["Raw vote byte, encodes aye + conviction"])), + ) + } +} + +/// A vote for a referendum of a particular account. +#[derive(Encode, Decode, Copy, Clone, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub enum AccountVote { + /// A standard vote, one-way (approve or reject) with a given amount of conviction. + Standard { vote: Vote, balance: Balance }, + /// A split vote with balances given for both ways, and with no conviction, useful for + /// parachains when voting. + Split { aye: Balance, nay: Balance }, +} + +impl AccountVote { + /// Returns `Some` of the lock periods that the account is locked for, assuming that the + /// referendum passed iff `approved` is `true`. + pub fn locked_if(self, approved: bool) -> Option<(u32, Balance)> { + // winning side: can only be removed after the lock period ends. + match self { + AccountVote::Standard { vote: Vote { conviction: Conviction::None, .. }, .. } => None, + AccountVote::Standard { vote, balance } if vote.aye == approved => + Some((vote.conviction.lock_periods(), balance)), + _ => None, + } + } + + /// The total balance involved in this vote. + pub fn balance(self) -> Balance { + match self { + AccountVote::Standard { balance, .. } => balance, + AccountVote::Split { aye, nay } => aye.saturating_add(nay), + } + } + + /// Returns `Some` with whether the vote is an aye vote if it is standard, otherwise `None` if + /// it is split. + pub fn as_standard(self) -> Option { + match self { + AccountVote::Standard { vote, .. } => Some(vote.aye), + _ => None, + } + } +} + +/// A "prior" lock, i.e. a lock for some now-forgotten reason. +#[derive( + Encode, + Decode, + Default, + Copy, + Clone, + Eq, + PartialEq, + Ord, + PartialOrd, + RuntimeDebug, + TypeInfo, + MaxEncodedLen, +)] +pub struct PriorLock(BlockNumber, Balance); + +impl PriorLock { + /// Accumulates an additional lock. + pub fn accumulate(&mut self, until: BlockNumber, amount: Balance) { + self.0 = self.0.max(until); + self.1 = self.1.max(amount); + } + + pub fn locked(&self) -> Balance { + self.1 + } + + pub fn rejig(&mut self, now: BlockNumber) { + if now >= self.0 { + self.0 = Zero::zero(); + self.1 = Zero::zero(); + } + } +} + +/// Information concerning the delegation of some voting power. +#[derive(Encode, Decode, Clone, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub struct Delegating { + /// The amount of balance delegated. + pub balance: Balance, + /// The account to which the voting power is delegated. + pub target: AccountId, + /// The conviction with which the voting power is delegated. When this gets undelegated, the + /// relevant lock begins. + pub conviction: Conviction, + /// The total amount of delegations that this account has received, post-conviction-weighting. + pub delegations: Delegations, + /// Any pre-existing locks from past voting/delegating activity. + pub prior: PriorLock, +} + +/// Information concerning the direct vote-casting of some voting power. +#[derive(Encode, Decode, Clone, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +#[scale_info(skip_type_params(MaxVotes))] +pub struct Casting +where + MaxVotes: Get, +{ + /// The current votes of the account. + pub votes: BoundedVec<(PollIndex, AccountVote), MaxVotes>, + /// The total amount of delegations that this account has received, post-conviction-weighting. + pub delegations: Delegations, + /// Any pre-existing locks from past voting/delegating activity. + pub prior: PriorLock, +} + +/// An indicator for what an account is doing; it can either be delegating or voting. +#[derive(Encode, Decode, Clone, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +#[scale_info(skip_type_params(MaxVotes))] +pub enum Voting +where + MaxVotes: Get, +{ + /// The account is voting directly. + Casting(Casting), + /// The account is delegating `balance` of its balance to a `target` account with `conviction`. + Delegating(Delegating), +} + +impl Default + for Voting +where + MaxVotes: Get, +{ + fn default() -> Self { + Voting::Casting(Casting { + votes: Default::default(), + delegations: Default::default(), + prior: PriorLock(Zero::zero(), Default::default()), + }) + } +} + +impl AsMut> + for Voting +where + MaxVotes: Get, +{ + fn as_mut(&mut self) -> &mut PriorLock { + match self { + Voting::Casting(Casting { prior, .. }) => prior, + Voting::Delegating(Delegating { prior, .. }) => prior, + } + } +} + +impl< + Balance: Saturating + Ord + Zero + Copy, + BlockNumber: Ord + Copy + Zero, + AccountId, + PollIndex, + MaxVotes, + > Voting +where + MaxVotes: Get, +{ + pub fn rejig(&mut self, now: BlockNumber) { + AsMut::>::as_mut(self).rejig(now); + } + + /// The amount of this account's balance that much currently be locked due to voting. + pub fn locked_balance(&self) -> Balance { + match self { + Voting::Casting(Casting { votes, prior, .. }) => + votes.iter().map(|i| i.1.balance()).fold(prior.locked(), |a, i| a.max(i)), + Voting::Delegating(Delegating { balance, prior, .. }) => *balance.max(&prior.locked()), + } + } + + pub fn set_common( + &mut self, + delegations: Delegations, + prior: PriorLock, + ) { + let (d, p) = match self { + Voting::Casting(Casting { ref mut delegations, ref mut prior, .. }) => + (delegations, prior), + Voting::Delegating(Delegating { ref mut delegations, ref mut prior, .. }) => + (delegations, prior), + }; + *d = delegations; + *p = prior; + } +} diff --git a/frame/conviction-voting/src/weights.rs b/frame/conviction-voting/src/weights.rs new file mode 100644 index 000000000000..da15aac0b47c --- /dev/null +++ b/frame/conviction-voting/src/weights.rs @@ -0,0 +1,201 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +//! Autogenerated weights for pallet_conviction_voting +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2022-01-09, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 + +// Executed Command: +// target/release/substrate +// benchmark +// --chain=dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_conviction_voting +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 +// --output=./frame/conviction-voting/src/weights.rs +// --template=./.maintain/frame-weight-template.hbs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +/// Weight functions needed for pallet_conviction_voting. +pub trait WeightInfo { + fn vote_new() -> Weight; + fn vote_existing() -> Weight; + fn remove_vote() -> Weight; + fn remove_other_vote() -> Weight; + fn delegate(r: u32, ) -> Weight; + fn undelegate(r: u32, ) -> Weight; + fn unlock() -> Weight; +} + +/// Weights for pallet_conviction_voting using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: ConvictionVoting VotingFor (r:1 w:1) + // Storage: ConvictionVoting ClassLocksFor (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: Scheduler Agenda (r:2 w:2) + fn vote_new() -> Weight { + (159_647_000 as Weight) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) + .saturating_add(T::DbWeight::get().writes(6 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: ConvictionVoting VotingFor (r:1 w:1) + // Storage: ConvictionVoting ClassLocksFor (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: Scheduler Agenda (r:2 w:2) + fn vote_existing() -> Weight { + (339_851_000 as Weight) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) + .saturating_add(T::DbWeight::get().writes(6 as Weight)) + } + // Storage: ConvictionVoting VotingFor (r:1 w:1) + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Scheduler Agenda (r:2 w:2) + fn remove_vote() -> Weight { + (317_673_000 as Weight) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(4 as Weight)) + } + // Storage: ConvictionVoting VotingFor (r:1 w:1) + // Storage: Referenda ReferendumInfoFor (r:1 w:0) + fn remove_other_vote() -> Weight { + (52_222_000 as Weight) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + // Storage: ConvictionVoting VotingFor (r:2 w:2) + // Storage: ConvictionVoting ClassLocksFor (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Scheduler Agenda (r:2 w:2) + fn delegate(r: u32, ) -> Weight { + (61_553_000 as Weight) + // Standard Error: 123_000 + .saturating_add((33_092_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(r as Weight))) + .saturating_add(T::DbWeight::get().writes(4 as Weight)) + .saturating_add(T::DbWeight::get().writes((3 as Weight).saturating_mul(r as Weight))) + } + // Storage: ConvictionVoting VotingFor (r:2 w:2) + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Scheduler Agenda (r:2 w:2) + fn undelegate(r: u32, ) -> Weight { + (42_037_000 as Weight) + // Standard Error: 582_000 + .saturating_add((32_296_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(r as Weight))) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes((3 as Weight).saturating_mul(r as Weight))) + } + // Storage: ConvictionVoting VotingFor (r:1 w:1) + // Storage: ConvictionVoting ClassLocksFor (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + fn unlock() -> Weight { + (69_017_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } +} + +// For backwards compatibility and tests +impl WeightInfo for () { + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: ConvictionVoting VotingFor (r:1 w:1) + // Storage: ConvictionVoting ClassLocksFor (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: Scheduler Agenda (r:2 w:2) + fn vote_new() -> Weight { + (159_647_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(6 as Weight)) + .saturating_add(RocksDbWeight::get().writes(6 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: ConvictionVoting VotingFor (r:1 w:1) + // Storage: ConvictionVoting ClassLocksFor (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: Scheduler Agenda (r:2 w:2) + fn vote_existing() -> Weight { + (339_851_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(6 as Weight)) + .saturating_add(RocksDbWeight::get().writes(6 as Weight)) + } + // Storage: ConvictionVoting VotingFor (r:1 w:1) + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Scheduler Agenda (r:2 w:2) + fn remove_vote() -> Weight { + (317_673_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(4 as Weight)) + } + // Storage: ConvictionVoting VotingFor (r:1 w:1) + // Storage: Referenda ReferendumInfoFor (r:1 w:0) + fn remove_other_vote() -> Weight { + (52_222_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + // Storage: ConvictionVoting VotingFor (r:2 w:2) + // Storage: ConvictionVoting ClassLocksFor (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Scheduler Agenda (r:2 w:2) + fn delegate(r: u32, ) -> Weight { + (61_553_000 as Weight) + // Standard Error: 123_000 + .saturating_add((33_092_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(r as Weight))) + .saturating_add(RocksDbWeight::get().writes(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes((3 as Weight).saturating_mul(r as Weight))) + } + // Storage: ConvictionVoting VotingFor (r:2 w:2) + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Scheduler Agenda (r:2 w:2) + fn undelegate(r: u32, ) -> Weight { + (42_037_000 as Weight) + // Standard Error: 582_000 + .saturating_add((32_296_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(RocksDbWeight::get().reads(2 as Weight)) + .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(r as Weight))) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes((3 as Weight).saturating_mul(r as Weight))) + } + // Storage: ConvictionVoting VotingFor (r:1 w:1) + // Storage: ConvictionVoting ClassLocksFor (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + fn unlock() -> Weight { + (69_017_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + } +} diff --git a/frame/democracy/src/lib.rs b/frame/democracy/src/lib.rs index 4580767d875c..b578df590930 100644 --- a/frame/democracy/src/lib.rs +++ b/frame/democracy/src/lib.rs @@ -439,14 +439,6 @@ pub mod pallet { ValueQuery, >; - /// Accounts for which there are locks in action which may be removed at some point in the - /// future. The value is the block number at which the lock expires and may be removed. - /// - /// TWOX-NOTE: OK ― `AccountId` is a secure hash. - #[pallet::storage] - #[pallet::getter(fn locks)] - pub type Locks = StorageMap<_, Twox64Concat, T::AccountId, T::BlockNumber>; - /// True if the last referendum tabled was submitted externally. False if it was a public /// proposal. // TODO: There should be any number of tabling origins, not just public and "external" diff --git a/frame/referenda/Cargo.toml b/frame/referenda/Cargo.toml new file mode 100644 index 000000000000..e979f2b0c4a3 --- /dev/null +++ b/frame/referenda/Cargo.toml @@ -0,0 +1,56 @@ +[package] +name = "pallet-referenda" +version = "4.0.0-dev" +authors = ["Parity Technologies "] +edition = "2018" +license = "Apache-2.0" +homepage = "https://substrate.io" +repository = "https://github.com/paritytech/substrate/" +description = "FRAME pallet for inclusive on-chain decisions" +readme = "README.md" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +serde = { version = "1.0.126", optional = true, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ + "derive", +] } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } +sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } +frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } +frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } +assert_matches = { version = "1.5", optional = true } + +[dev-dependencies] +sp-core = { version = "5.0.0", path = "../../primitives/core" } +pallet-balances = { version = "4.0.0-dev", path = "../balances" } +pallet-scheduler = { version = "4.0.0-dev", path = "../scheduler" } +pallet-preimage = { version = "4.0.0-dev", path = "../preimage" } +assert_matches = { version = "1.5" } + +[features] +default = ["std"] +std = [ + "serde", + "codec/std", + "scale-info/std", + "sp-std/std", + "sp-io/std", + "frame-benchmarking/std", + "frame-support/std", + "sp-runtime/std", + "frame-system/std", +] +runtime-benchmarks = [ + "frame-benchmarking", + "frame-system/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", + "assert_matches", +] +try-runtime = ["frame-support/try-runtime"] diff --git a/frame/referenda/README.md b/frame/referenda/README.md new file mode 100644 index 000000000000..85031a011303 --- /dev/null +++ b/frame/referenda/README.md @@ -0,0 +1,8 @@ +# Referenda Pallet + +- [`assembly::Config`](https://docs.rs/pallet-assembly/latest/pallet_assembly/trait.Config.html) +- [`Call`](https://docs.rs/pallet-assembly/latest/pallet_assembly/enum.Call.html) + +## Overview + +The Assembly pallet handles the administration of general stakeholder voting. diff --git a/frame/referenda/src/benchmarking.rs b/frame/referenda/src/benchmarking.rs new file mode 100644 index 000000000000..76a8173f16c9 --- /dev/null +++ b/frame/referenda/src/benchmarking.rs @@ -0,0 +1,520 @@ +// This file is part of Substrate. + +// Copyright (C) 2020-2021 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. + +//! Democracy pallet benchmarking. + +use super::*; +use crate::Pallet as Referenda; +use assert_matches::assert_matches; +use frame_benchmarking::{account, benchmarks, whitelist_account}; +use frame_support::{ + assert_ok, + traits::{Currency, EnsureOrigin}, +}; +use frame_system::RawOrigin; +use sp_runtime::traits::{Bounded, Hash}; + +const SEED: u32 = 0; + +#[allow(dead_code)] +fn assert_last_event(generic_event: ::Event) { + frame_system::Pallet::::assert_last_event(generic_event.into()); +} + +fn funded_account(name: &'static str, index: u32) -> T::AccountId { + let caller: T::AccountId = account(name, index, SEED); + T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); + caller +} + +fn create_referendum() -> (T::AccountId, ReferendumIndex) { + let caller = funded_account::("caller", 0); + whitelist_account!(caller); + assert_ok!(Referenda::::submit( + RawOrigin::Signed(caller.clone()).into(), + RawOrigin::Root.into(), + T::Hashing::hash_of(&0), + AtOrAfter::After(0u32.into()) + )); + let index = ReferendumCount::::get() - 1; + (caller, index) +} + +fn place_deposit(index: ReferendumIndex) { + let caller = funded_account::("caller", 0); + whitelist_account!(caller); + assert_ok!(Referenda::::place_decision_deposit( + RawOrigin::Signed(caller.clone()).into(), + index, + )); +} + +fn nudge(index: ReferendumIndex) { + assert_ok!(Referenda::::nudge_referendum(RawOrigin::Root.into(), index)); +} + +fn fill_queue( + index: ReferendumIndex, + spaces: u32, + pass_after: u32, +) -> Vec { + // First, create enough other referendums to fill the track. + let mut others = vec![]; + for _ in 0..info::(index).max_deciding { + let (_caller, index) = create_referendum::(); + place_deposit::(index); + others.push(index); + } + + // We will also need enough referenda which are queued and passing, we want `MaxQueued - 1` + // in order to force the maximum amount of work to insert ours into the queue. + for _ in spaces..T::MaxQueued::get() { + let (_caller, index) = create_referendum::(); + place_deposit::(index); + make_passing_after::(index, Perbill::from_percent(pass_after)); + others.push(index); + } + + // Skip to when they can start being decided. + skip_prepare_period::(index); + + // Manually nudge the other referenda first to ensure that they begin. + others.iter().for_each(|&i| nudge::(i)); + + others +} + +fn info(index: ReferendumIndex) -> &'static TrackInfoOf { + let status = Referenda::::ensure_ongoing(index).unwrap(); + T::Tracks::info(status.track).expect("Id value returned from T::Tracks") +} + +fn make_passing_after(index: ReferendumIndex, period_portion: Perbill) { + let turnout = info::(index).min_turnout.threshold(period_portion); + let approval = info::(index).min_approval.threshold(period_portion); + Referenda::::access_poll(index, |status| { + if let PollStatus::Ongoing(tally, ..) = status { + *tally = T::Tally::from_requirements(turnout, approval); + } + }); +} + +fn make_passing(index: ReferendumIndex) { + Referenda::::access_poll(index, |status| { + if let PollStatus::Ongoing(tally, ..) = status { + *tally = T::Tally::unanimity(); + } + }); +} + +fn make_failing(index: ReferendumIndex) { + Referenda::::access_poll(index, |status| { + if let PollStatus::Ongoing(tally, ..) = status { + *tally = T::Tally::default(); + } + }); +} + +fn skip_prepare_period(index: ReferendumIndex) { + let status = Referenda::::ensure_ongoing(index).unwrap(); + let prepare_period_over = status.submitted + info::(index).prepare_period; + frame_system::Pallet::::set_block_number(prepare_period_over); +} + +fn skip_decision_period(index: ReferendumIndex) { + let status = Referenda::::ensure_ongoing(index).unwrap(); + let decision_period_over = status.deciding.unwrap().since + info::(index).decision_period; + frame_system::Pallet::::set_block_number(decision_period_over); +} + +fn skip_confirm_period(index: ReferendumIndex) { + let status = Referenda::::ensure_ongoing(index).unwrap(); + let confirm_period_over = status.deciding.unwrap().confirming.unwrap(); + frame_system::Pallet::::set_block_number(confirm_period_over); +} + +fn skip_timeout_period(index: ReferendumIndex) { + let status = Referenda::::ensure_ongoing(index).unwrap(); + let timeout_period_over = status.submitted + T::UndecidingTimeout::get(); + frame_system::Pallet::::set_block_number(timeout_period_over); +} + +fn alarm_time(index: ReferendumIndex) -> T::BlockNumber { + let status = Referenda::::ensure_ongoing(index).unwrap(); + status.alarm.unwrap().0 +} + +fn is_confirming(index: ReferendumIndex) -> bool { + let status = Referenda::::ensure_ongoing(index).unwrap(); + matches!( + status, + ReferendumStatus { deciding: Some(DecidingStatus { confirming: Some(_), .. }), .. } + ) +} + +fn is_not_confirming(index: ReferendumIndex) -> bool { + let status = Referenda::::ensure_ongoing(index).unwrap(); + matches!( + status, + ReferendumStatus { deciding: Some(DecidingStatus { confirming: None, .. }), .. } + ) +} + +benchmarks! { + submit { + let caller = funded_account::("caller", 0); + whitelist_account!(caller); + }: _( + RawOrigin::Signed(caller), + RawOrigin::Root.into(), + T::Hashing::hash_of(&0), + AtOrAfter::After(0u32.into()) + ) verify { + let index = ReferendumCount::::get().checked_sub(1).unwrap(); + assert_matches!(ReferendumInfoFor::::get(index), Some(ReferendumInfo::Ongoing(_))); + } + + place_decision_deposit_preparing { + let (caller, index) = create_referendum::(); + }: place_decision_deposit(RawOrigin::Signed(caller), index) + verify { + assert!(Referenda::::ensure_ongoing(index).unwrap().decision_deposit.is_some()); + } + + place_decision_deposit_queued { + let (caller, index) = create_referendum::(); + fill_queue::(index, 1, 90); + }: place_decision_deposit(RawOrigin::Signed(caller), index) + verify { + let track = Referenda::::ensure_ongoing(index).unwrap().track; + assert_eq!(TrackQueue::::get(&track).len() as u32, T::MaxQueued::get()); + assert_eq!(TrackQueue::::get(&track)[0], (index, 0u32.into())); + } + + place_decision_deposit_not_queued { + let (caller, index) = create_referendum::(); + fill_queue::(index, 0, 90); + }: place_decision_deposit(RawOrigin::Signed(caller), index) + verify { + let track = Referenda::::ensure_ongoing(index).unwrap().track; + assert_eq!(TrackQueue::::get(&track).len() as u32, T::MaxQueued::get()); + assert!(TrackQueue::::get(&track).into_iter().all(|(i, _)| i != index)); + } + + place_decision_deposit_passing { + let (caller, index) = create_referendum::(); + skip_prepare_period::(index); + make_passing::(index); + }: place_decision_deposit(RawOrigin::Signed(caller), index) + verify { + assert!(is_confirming::(index)); + } + + place_decision_deposit_failing { + let (caller, index) = create_referendum::(); + skip_prepare_period::(index); + }: place_decision_deposit(RawOrigin::Signed(caller), index) + verify { + assert!(is_not_confirming::(index)); + } + + refund_decision_deposit { + let (caller, index) = create_referendum::(); + place_deposit::(index); + assert_ok!(Referenda::::cancel(T::CancelOrigin::successful_origin(), index)); + }: _(RawOrigin::Signed(caller), index) + verify { + assert_matches!(ReferendumInfoFor::::get(index), Some(ReferendumInfo::Cancelled(_, _, None))); + } + + cancel { + let (_caller, index) = create_referendum::(); + place_deposit::(index); + }: _(T::CancelOrigin::successful_origin(), index) + verify { + assert_matches!(ReferendumInfoFor::::get(index), Some(ReferendumInfo::Cancelled(..))); + } + + kill { + let (_caller, index) = create_referendum::(); + place_deposit::(index); + }: _(T::KillOrigin::successful_origin(), index) + verify { + assert_matches!(ReferendumInfoFor::::get(index), Some(ReferendumInfo::Killed(..))); + } + + one_fewer_deciding_queue_empty { + let (_caller, index) = create_referendum::(); + place_deposit::(index); + skip_prepare_period::(index); + nudge::(index); + let track = Referenda::::ensure_ongoing(index).unwrap().track; + assert_ok!(Referenda::::cancel(T::CancelOrigin::successful_origin(), index)); + assert_eq!(DecidingCount::::get(&track), 1); + }: one_fewer_deciding(RawOrigin::Root, track.clone()) + verify { + assert_eq!(DecidingCount::::get(&track), 0); + } + + one_fewer_deciding_failing { + let (_caller, index) = create_referendum::(); + // No spaces free in the queue. + let queued = fill_queue::(index, 0, 90); + let track = Referenda::::ensure_ongoing(index).unwrap().track; + assert_ok!(Referenda::::cancel(T::CancelOrigin::successful_origin(), queued[0])); + assert_eq!(TrackQueue::::get(&track).len() as u32, T::MaxQueued::get()); + let deciding_count = DecidingCount::::get(&track); + }: one_fewer_deciding(RawOrigin::Root, track.clone()) + verify { + assert_eq!(DecidingCount::::get(&track), deciding_count); + assert_eq!(TrackQueue::::get(&track).len() as u32, T::MaxQueued::get() - 1); + assert!(queued.into_iter().skip(1).all(|i| Referenda::::ensure_ongoing(i) + .unwrap() + .deciding + .map_or(true, |d| d.confirming.is_none()) + )); + } + + one_fewer_deciding_passing { + let (_caller, index) = create_referendum::(); + // No spaces free in the queue. + let queued = fill_queue::(index, 0, 0); + let track = Referenda::::ensure_ongoing(index).unwrap().track; + assert_ok!(Referenda::::cancel(T::CancelOrigin::successful_origin(), queued[0])); + assert_eq!(TrackQueue::::get(&track).len() as u32, T::MaxQueued::get()); + let deciding_count = DecidingCount::::get(&track); + }: one_fewer_deciding(RawOrigin::Root, track.clone()) + verify { + assert_eq!(DecidingCount::::get(&track), deciding_count); + assert_eq!(TrackQueue::::get(&track).len() as u32, T::MaxQueued::get() - 1); + assert!(queued.into_iter().skip(1).all(|i| Referenda::::ensure_ongoing(i) + .unwrap() + .deciding + .map_or(true, |d| d.confirming.is_some()) + )); + } + + nudge_referendum_requeued_insertion { + // First create our referendum and place the deposit. It will be failing. + let (_caller, index) = create_referendum::(); + place_deposit::(index); + fill_queue::(index, 0, 90); + + // Now nudge ours, with the track now full and the queue full of referenda with votes, + // ours will not be in the queue. + nudge::(index); + let track = Referenda::::ensure_ongoing(index).unwrap().track; + assert!(TrackQueue::::get(&track).into_iter().all(|(i, _)| i != index)); + + // Now alter the voting, so that ours goes into pole-position and shifts others down. + make_passing::(index); + }: nudge_referendum(RawOrigin::Root, index) + verify { + let t = TrackQueue::::get(&track); + assert_eq!(t.len() as u32, T::MaxQueued::get()); + assert_eq!(t[t.len() - 1].0, index); + } + + nudge_referendum_requeued_slide { + // First create our referendum and place the deposit. It will be failing. + let (_caller, index) = create_referendum::(); + place_deposit::(index); + fill_queue::(index, 1, 90); + + // Now nudge ours, with the track now full, ours will be queued, but with no votes, it + // will have the worst position. + nudge::(index); + let track = Referenda::::ensure_ongoing(index).unwrap().track; + assert_eq!(TrackQueue::::get(&track).len() as u32, T::MaxQueued::get()); + assert_eq!(TrackQueue::::get(&track)[0], (index, 0u32.into())); + + // Now alter the voting, so that ours leap-frogs all into the best position. + make_passing::(index); + }: nudge_referendum(RawOrigin::Root, index) + verify { + let t = TrackQueue::::get(&track); + assert_eq!(t.len() as u32, T::MaxQueued::get()); + assert_eq!(t[t.len() - 1].0, index); + } + + nudge_referendum_queued { + // NOTE: worst possible queue situation is with a queue full of passing refs with one slot + // free and this failing. It would result in `QUEUE_SIZE - 1` items being shifted for the + // insertion at the beginning. + + // First create our referendum and place the deposit. It will be failing. + let (_caller, index) = create_referendum::(); + place_deposit::(index); + fill_queue::(index, 1, 0); + + let track = Referenda::::ensure_ongoing(index).unwrap().track; + assert_eq!(TrackQueue::::get(&track).len() as u32, T::MaxQueued::get() - 1); + assert!(TrackQueue::::get(&track).into_iter().all(|(_, v)| v > 0u32.into())); + + // Then nudge ours, with the track now full, ours will be queued. + }: nudge_referendum(RawOrigin::Root, index) + verify { + assert_eq!(TrackQueue::::get(&track).len() as u32, T::MaxQueued::get()); + assert_eq!(TrackQueue::::get(&track)[0], (index, 0u32.into())); + } + + nudge_referendum_not_queued { + // First create our referendum and place the deposit. It will be failing. + let (_caller, index) = create_referendum::(); + place_deposit::(index); + fill_queue::(index, 0, 0); + + let track = Referenda::::ensure_ongoing(index).unwrap().track; + assert_eq!(TrackQueue::::get(&track).len() as u32, T::MaxQueued::get()); + assert!(TrackQueue::::get(&track).into_iter().all(|(_, v)| v > 0u32.into())); + + // Then nudge ours, with the track now full, ours will be queued. + }: nudge_referendum(RawOrigin::Root, index) + verify { + assert_eq!(TrackQueue::::get(&track).len() as u32, T::MaxQueued::get()); + assert!(TrackQueue::::get(&track).into_iter().all(|(i, _)| i != index)); + } + + nudge_referendum_no_deposit { + let (_caller, index) = create_referendum::(); + skip_prepare_period::(index); + }: nudge_referendum(RawOrigin::Root, index) + verify { + let status = Referenda::::ensure_ongoing(index).unwrap(); + assert_matches!(status, ReferendumStatus { deciding: None, .. }); + } + + nudge_referendum_preparing { + let (_caller, index) = create_referendum::(); + place_deposit::(index); + }: nudge_referendum(RawOrigin::Root, index) + verify { + let status = Referenda::::ensure_ongoing(index).unwrap(); + assert_matches!(status, ReferendumStatus { deciding: None, .. }); + } + + nudge_referendum_timed_out { + let (_caller, index) = create_referendum::(); + skip_timeout_period::(index); + }: nudge_referendum(RawOrigin::Root, index) + verify { + let info = ReferendumInfoFor::::get(index).unwrap(); + assert_matches!(info, ReferendumInfo::TimedOut(..)); + } + + nudge_referendum_begin_deciding_failing { + let (_caller, index) = create_referendum::(); + place_deposit::(index); + skip_prepare_period::(index); + }: nudge_referendum(RawOrigin::Root, index) + verify { + assert!(is_not_confirming::(index)); + } + + nudge_referendum_begin_deciding_passing { + let (_caller, index) = create_referendum::(); + place_deposit::(index); + make_passing::(index); + skip_prepare_period::(index); + }: nudge_referendum(RawOrigin::Root, index) + verify { + assert!(is_confirming::(index)); + } + + nudge_referendum_begin_confirming { + let (_caller, index) = create_referendum::(); + place_deposit::(index); + skip_prepare_period::(index); + nudge::(index); + assert!(!is_confirming::(index)); + make_passing::(index); + }: nudge_referendum(RawOrigin::Root, index) + verify { + assert!(is_confirming::(index)); + } + + nudge_referendum_end_confirming { + let (_caller, index) = create_referendum::(); + place_deposit::(index); + skip_prepare_period::(index); + make_passing::(index); + nudge::(index); + assert!(is_confirming::(index)); + make_failing::(index); + }: nudge_referendum(RawOrigin::Root, index) + verify { + assert!(!is_confirming::(index)); + } + + nudge_referendum_continue_not_confirming { + let (_caller, index) = create_referendum::(); + place_deposit::(index); + skip_prepare_period::(index); + nudge::(index); + assert!(!is_confirming::(index)); + let old_alarm = alarm_time::(index); + make_passing_after::(index, Perbill::from_percent(50)); + }: nudge_referendum(RawOrigin::Root, index) + verify { + assert_ne!(old_alarm, alarm_time::(index)); + assert!(!is_confirming::(index)); + } + + nudge_referendum_continue_confirming { + let (_caller, index) = create_referendum::(); + place_deposit::(index); + make_passing::(index); + skip_prepare_period::(index); + nudge::(index); + assert!(is_confirming::(index)); + let old_alarm = alarm_time::(index); + }: nudge_referendum(RawOrigin::Root, index) + verify { + assert!(is_confirming::(index)); + } + + nudge_referendum_approved { + let (_caller, index) = create_referendum::(); + place_deposit::(index); + skip_prepare_period::(index); + make_passing::(index); + nudge::(index); + skip_confirm_period::(index); + }: nudge_referendum(RawOrigin::Root, index) + verify { + let info = ReferendumInfoFor::::get(index).unwrap(); + assert_matches!(info, ReferendumInfo::Approved(..)); + } + + nudge_referendum_rejected { + let (_caller, index) = create_referendum::(); + place_deposit::(index); + skip_prepare_period::(index); + nudge::(index); + skip_decision_period::(index); + }: nudge_referendum(RawOrigin::Root, index) + verify { + let info = ReferendumInfoFor::::get(index).unwrap(); + assert_matches!(info, ReferendumInfo::Rejected(..)); + } + + impl_benchmark_test_suite!( + Referenda, + crate::mock::new_test_ext(), + crate::mock::Test + ); +} diff --git a/frame/referenda/src/branch.rs b/frame/referenda/src/branch.rs new file mode 100644 index 000000000000..6a4efa31e15e --- /dev/null +++ b/frame/referenda/src/branch.rs @@ -0,0 +1,172 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2022 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. + +//! Helpers for managing the different weights in various algorithmic branches. + +use super::Config; +use crate::weights::WeightInfo; + +/// Branches within the `begin_deciding` function. +pub enum BeginDecidingBranch { + Passing, + Failing, +} + +/// Branches within the `service_referendum` function. +pub enum ServiceBranch { + Fail, + NoDeposit, + Preparing, + Queued, + NotQueued, + RequeuedInsertion, + RequeuedSlide, + BeginDecidingPassing, + BeginDecidingFailing, + BeginConfirming, + ContinueConfirming, + EndConfirming, + ContinueNotConfirming, + Approved, + Rejected, + TimedOut, +} + +impl From for ServiceBranch { + fn from(x: BeginDecidingBranch) -> Self { + use BeginDecidingBranch::*; + use ServiceBranch::*; + match x { + Passing => BeginDecidingPassing, + Failing => BeginDecidingFailing, + } + } +} + +impl ServiceBranch { + /// Return the weight of the `nudge` function when it takes the branch denoted by `self`. + pub fn weight_of_nudge(self) -> frame_support::weights::Weight { + use ServiceBranch::*; + match self { + NoDeposit => T::WeightInfo::nudge_referendum_no_deposit(), + Preparing => T::WeightInfo::nudge_referendum_preparing(), + Queued => T::WeightInfo::nudge_referendum_queued(), + NotQueued => T::WeightInfo::nudge_referendum_not_queued(), + RequeuedInsertion => T::WeightInfo::nudge_referendum_requeued_insertion(), + RequeuedSlide => T::WeightInfo::nudge_referendum_requeued_slide(), + BeginDecidingPassing => T::WeightInfo::nudge_referendum_begin_deciding_passing(), + BeginDecidingFailing => T::WeightInfo::nudge_referendum_begin_deciding_failing(), + BeginConfirming => T::WeightInfo::nudge_referendum_begin_confirming(), + ContinueConfirming => T::WeightInfo::nudge_referendum_continue_confirming(), + EndConfirming => T::WeightInfo::nudge_referendum_end_confirming(), + ContinueNotConfirming => T::WeightInfo::nudge_referendum_continue_not_confirming(), + Approved => T::WeightInfo::nudge_referendum_approved(), + Rejected => T::WeightInfo::nudge_referendum_rejected(), + TimedOut | Fail => T::WeightInfo::nudge_referendum_timed_out(), + } + } + + /// Return the maximum possible weight of the `nudge` function. + pub fn max_weight_of_nudge() -> frame_support::weights::Weight { + 0.max(T::WeightInfo::nudge_referendum_no_deposit()) + .max(T::WeightInfo::nudge_referendum_preparing()) + .max(T::WeightInfo::nudge_referendum_queued()) + .max(T::WeightInfo::nudge_referendum_not_queued()) + .max(T::WeightInfo::nudge_referendum_requeued_insertion()) + .max(T::WeightInfo::nudge_referendum_requeued_slide()) + .max(T::WeightInfo::nudge_referendum_begin_deciding_passing()) + .max(T::WeightInfo::nudge_referendum_begin_deciding_failing()) + .max(T::WeightInfo::nudge_referendum_begin_confirming()) + .max(T::WeightInfo::nudge_referendum_continue_confirming()) + .max(T::WeightInfo::nudge_referendum_end_confirming()) + .max(T::WeightInfo::nudge_referendum_continue_not_confirming()) + .max(T::WeightInfo::nudge_referendum_approved()) + .max(T::WeightInfo::nudge_referendum_rejected()) + .max(T::WeightInfo::nudge_referendum_timed_out()) + } + + /// Return the weight of the `place_decision_deposit` function when it takes the branch denoted + /// by `self`. + pub fn weight_of_deposit(self) -> Option { + use ServiceBranch::*; + Some(match self { + Preparing => T::WeightInfo::place_decision_deposit_preparing(), + Queued => T::WeightInfo::place_decision_deposit_queued(), + NotQueued => T::WeightInfo::place_decision_deposit_not_queued(), + BeginDecidingPassing => T::WeightInfo::place_decision_deposit_passing(), + BeginDecidingFailing => T::WeightInfo::place_decision_deposit_failing(), + BeginConfirming | + ContinueConfirming | + EndConfirming | + ContinueNotConfirming | + Approved | + Rejected | + RequeuedInsertion | + RequeuedSlide | + TimedOut | + Fail | + NoDeposit => return None, + }) + } + + /// Return the maximum possible weight of the `place_decision_deposit` function. + pub fn max_weight_of_deposit() -> frame_support::weights::Weight { + 0.max(T::WeightInfo::place_decision_deposit_preparing()) + .max(T::WeightInfo::place_decision_deposit_queued()) + .max(T::WeightInfo::place_decision_deposit_not_queued()) + .max(T::WeightInfo::place_decision_deposit_passing()) + .max(T::WeightInfo::place_decision_deposit_failing()) + } +} + +/// Branches that the `one_fewer_deciding` function may take. +pub enum OneFewerDecidingBranch { + QueueEmpty, + BeginDecidingPassing, + BeginDecidingFailing, +} + +impl From for OneFewerDecidingBranch { + fn from(x: BeginDecidingBranch) -> Self { + use BeginDecidingBranch::*; + use OneFewerDecidingBranch::*; + match x { + Passing => BeginDecidingPassing, + Failing => BeginDecidingFailing, + } + } +} + +impl OneFewerDecidingBranch { + /// Return the weight of the `one_fewer_deciding` function when it takes the branch denoted + /// by `self`. + pub fn weight(self) -> frame_support::weights::Weight { + use OneFewerDecidingBranch::*; + match self { + QueueEmpty => T::WeightInfo::one_fewer_deciding_queue_empty(), + BeginDecidingPassing => T::WeightInfo::one_fewer_deciding_passing(), + BeginDecidingFailing => T::WeightInfo::one_fewer_deciding_failing(), + } + } + + /// Return the maximum possible weight of the `one_fewer_deciding` function. + pub fn max_weight() -> frame_support::weights::Weight { + 0.max(T::WeightInfo::one_fewer_deciding_queue_empty()) + .max(T::WeightInfo::one_fewer_deciding_passing()) + .max(T::WeightInfo::one_fewer_deciding_failing()) + } +} diff --git a/frame/referenda/src/lib.rs b/frame/referenda/src/lib.rs new file mode 100644 index 000000000000..fb8e9aa6a6db --- /dev/null +++ b/frame/referenda/src/lib.rs @@ -0,0 +1,1065 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2022 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. + +//! # Referenda Pallet +//! +//! ## Overview +//! +//! A pallet for executing referenda. No voting logic is present here, and the `Polling` and +//! `PollStatus` traits are used to allow the voting logic (likely in a pallet) to be utilized. +//! +//! A referendum is a vote on whether a proposal should be dispatched from a particular origin. The +//! origin is used to determine which one of several _tracks_ that a referendum happens under. +//! Tracks each have their own configuration which governs the voting process and parameters. +//! +//! A referendum's lifecycle has three main stages: Preparation, deciding and conclusion. +//! Referenda are considered "ongoing" immediately after submission until their eventual +//! conclusion, and votes may be cast throughout. +//! +//! In order to progress from preparating to being decided, three things must be in place: +//! - There must have been a *Decision Deposit* placed, an amount determined by the track. Anyone +//! may place this deposit. +//! - A period must have elapsed since submission of the referendum. This period is known as the +//! *Preparation Period* and is determined by the track. +//! - The track must not already be at capacity with referendum being decided. The maximum number of +//! referenda which may be being decided simultaneously is determined by the track. +//! +//! In order to become concluded, one of three things must happen: +//! - The referendum should remain in an unbroken _Passing_ state for a period of time. This +//! is known as the _Confirmation Period_ and is determined by the track. A referendum is considered +//! _Passing_ when there is a sufficiently high turnout and approval, given the amount of time it +//! has been being decided. Generally the threshold for what counts as being "sufficiently high" +//! will reduce over time. The curves setting these thresholds are determined by the track. In this +//! case, the referendum is considered _Approved_ and the proposal is scheduled for dispatch. +//! - The referendum reaches the end of its deciding phase outside not _Passing_. It ends in +//! rejection and the proposal is not dispatched. +//! - The referendum is cancelled. +//! +//! A general time-out is also in place and referenda which exist in preparation for too long may +//! conclude without ever entering into a deciding stage. +//! +//! Once a referendum is concluded, the decision deposit may be refunded. +//! +//! - [`Config`] +//! - [`Call`] + +#![recursion_limit = "256"] +#![cfg_attr(not(feature = "std"), no_std)] + +use codec::{Codec, Encode}; +use frame_support::{ + ensure, + traits::{ + schedule::{ + v2::{Anon as ScheduleAnon, Named as ScheduleNamed}, + DispatchTime, MaybeHashed, + }, + Currency, Get, LockIdentifier, LockableCurrency, OnUnbalanced, OriginTrait, PollStatus, + Polling, ReservableCurrency, VoteTally, + }, + BoundedVec, +}; +use scale_info::TypeInfo; +use sp_runtime::{ + traits::{AtLeast32BitUnsigned, Dispatchable, One, Saturating, Zero}, + DispatchError, Perbill, +}; +use sp_std::{fmt::Debug, prelude::*}; + +mod branch; +mod types; +pub mod weights; +use branch::{BeginDecidingBranch, OneFewerDecidingBranch, ServiceBranch}; +pub use pallet::*; +pub use types::{ + AtOrAfter, BalanceOf, CallOf, Curve, DecidingStatus, DecidingStatusOf, Deposit, InsertSorted, + NegativeImbalanceOf, PalletsOriginOf, ReferendumIndex, ReferendumInfo, ReferendumInfoOf, + ReferendumStatus, ReferendumStatusOf, ScheduleAddressOf, TallyOf, TrackIdOf, TrackInfo, + TrackInfoOf, TracksInfo, VotesOf, +}; +pub use weights::WeightInfo; + +#[cfg(test)] +mod mock; +#[cfg(test)] +mod tests; + +#[cfg(feature = "runtime-benchmarks")] +pub mod benchmarking; + +const ASSEMBLY_ID: LockIdentifier = *b"assembly"; + +#[frame_support::pallet] +pub mod pallet { + use super::*; + use frame_support::{pallet_prelude::*, traits::EnsureOrigin, Parameter}; + use frame_system::pallet_prelude::*; + use sp_runtime::DispatchResult; + + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] + pub struct Pallet(_); + + #[pallet::config] + pub trait Config: frame_system::Config + Sized { + // System level stuff. + type Call: Parameter + Dispatchable + From>; + type Event: From> + IsType<::Event>; + /// Weight information for extrinsics in this pallet. + type WeightInfo: WeightInfo; + /// The Scheduler. + type Scheduler: ScheduleAnon, PalletsOriginOf, Hash = Self::Hash> + + ScheduleNamed, PalletsOriginOf, Hash = Self::Hash>; + /// Currency type for this pallet. + type Currency: ReservableCurrency + + LockableCurrency; + + // Origins and unbalances. + /// Origin from which any vote may be cancelled. + type CancelOrigin: EnsureOrigin; + /// Origin from which any vote may be killed. + type KillOrigin: EnsureOrigin; + /// Handler for the unbalanced reduction when slashing a preimage deposit. + type Slash: OnUnbalanced>; + /// The counting type for votes. Usually just balance. + type Votes: AtLeast32BitUnsigned + Copy + Parameter + Member; + /// The tallying type. + type Tally: VoteTally + Default + Clone + Codec + Eq + Debug + TypeInfo; + + // Constants + /// The minimum amount to be used as a deposit for a public referendum proposal. + #[pallet::constant] + type SubmissionDeposit: Get>; + + /// Maximum size of the referendum queue for a single track. + #[pallet::constant] + type MaxQueued: Get; + + /// The number of blocks after submission that a referendum must begin being decided by. + /// Once this passes, then anyone may cancel the referendum. + #[pallet::constant] + type UndecidingTimeout: Get; + + /// Quantization level for the referendum wakeup scheduler. A higher number will result in + /// fewer storage reads/writes needed for smaller voters, but also result in delays to the + /// automatic referendum status changes. Explicit servicing instructions are unaffected. + #[pallet::constant] + type AlarmInterval: Get; + + // The other stuff. + /// Information concerning the different referendum tracks. + type Tracks: TracksInfo< + BalanceOf, + Self::BlockNumber, + Origin = ::PalletsOrigin, + >; + } + + /// The next free referendum index, aka the number of referenda started so far. + #[pallet::storage] + pub type ReferendumCount = StorageValue<_, ReferendumIndex, ValueQuery>; + + /// Information concerning any given referendum. + /// + /// TWOX-NOTE: SAFE as indexes are not under an attacker’s control. + #[pallet::storage] + pub type ReferendumInfoFor = + StorageMap<_, Blake2_128Concat, ReferendumIndex, ReferendumInfoOf>; + + /// The sorted list of referenda ready to be decided but not yet being decided, ordered by + /// conviction-weighted approvals. + /// + /// This should be empty if `DecidingCount` is less than `TrackInfo::max_deciding`. + #[pallet::storage] + pub type TrackQueue = StorageMap< + _, + Twox64Concat, + TrackIdOf, + BoundedVec<(ReferendumIndex, T::Votes), T::MaxQueued>, + ValueQuery, + >; + + /// The number of referenda being decided currently. + #[pallet::storage] + pub type DecidingCount = StorageMap<_, Twox64Concat, TrackIdOf, u32, ValueQuery>; + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + /// A referendum has being submitted. + Submitted { + /// Index of the referendum. + index: ReferendumIndex, + /// The track (and by extension proposal dispatch origin) of this referendum. + track: TrackIdOf, + /// The hash of the proposal up for referendum. + proposal_hash: T::Hash, + }, + /// The decision deposit has been placed. + DecisionDepositPlaced { + /// Index of the referendum. + index: ReferendumIndex, + /// The account who placed the deposit. + who: T::AccountId, + /// The amount placed by the account. + amount: BalanceOf, + }, + /// The decision deposit has been refunded. + DecisionDepositRefunded { + /// Index of the referendum. + index: ReferendumIndex, + /// The account who placed the deposit. + who: T::AccountId, + /// The amount placed by the account. + amount: BalanceOf, + }, + /// A deposit has been slashaed. + DepositSlashed { + /// The account who placed the deposit. + who: T::AccountId, + /// The amount placed by the account. + amount: BalanceOf, + }, + /// A referendum has moved into the deciding phase. + DecisionStarted { + /// Index of the referendum. + index: ReferendumIndex, + /// The track (and by extension proposal dispatch origin) of this referendum. + track: TrackIdOf, + /// The hash of the proposal up for referendum. + proposal_hash: T::Hash, + /// The current tally of votes in this referendum. + tally: T::Tally, + }, + ConfirmStarted { + /// Index of the referendum. + index: ReferendumIndex, + }, + ConfirmAborted { + /// Index of the referendum. + index: ReferendumIndex, + }, + /// A referendum has ended its confirmation phase and is ready for approval. + Confirmed { + /// Index of the referendum. + index: ReferendumIndex, + /// The final tally of votes in this referendum. + tally: T::Tally, + }, + /// A referendum has been approved and its proposal has been scheduled. + Approved { + /// Index of the referendum. + index: ReferendumIndex, + }, + /// A proposal has been rejected by referendum. + Rejected { + /// Index of the referendum. + index: ReferendumIndex, + /// The final tally of votes in this referendum. + tally: T::Tally, + }, + /// A referendum has been timed out without being decided. + TimedOut { + /// Index of the referendum. + index: ReferendumIndex, + /// The final tally of votes in this referendum. + tally: T::Tally, + }, + /// A referendum has been cancelled. + Cancelled { + /// Index of the referendum. + index: ReferendumIndex, + /// The final tally of votes in this referendum. + tally: T::Tally, + }, + /// A referendum has been killed. + Killed { + /// Index of the referendum. + index: ReferendumIndex, + /// The final tally of votes in this referendum. + tally: T::Tally, + }, + } + + #[pallet::error] + pub enum Error { + /// Referendum is not ongoing. + NotOngoing, + /// Referendum's decision deposit is already paid. + HaveDeposit, + /// The track identifier given was invalid. + BadTrack, + /// There are already a full complement of referendums in progress for this track. + Full, + /// The queue of the track is empty. + QueueEmpty, + /// The referendum index provided is invalid in this context. + BadReferendum, + /// There was nothing to do in the advancement. + NothingToDo, + /// No track exists for the proposal origin. + NoTrack, + /// Any deposit cannot be refunded until after the decision is over. + Unfinished, + /// The deposit refunder is not the depositor. + NoPermission, + /// The deposit cannot be refunded since none was made. + NoDeposit, + } + + #[pallet::call] + impl Pallet { + /// Propose a referendum on a privileged action. + /// + /// - `origin`: must be `Signed` and the account must have `SubmissionDeposit` funds + /// available. + /// - `proposal_origin`: The origin from which the proposal should be executed. + /// - `proposal_hash`: The hash of the proposal preimage. + /// - `enactment_moment`: The moment that the proposal should be enacted. + /// + /// Emits `Submitted`. + #[pallet::weight(T::WeightInfo::submit())] + pub fn submit( + origin: OriginFor, + proposal_origin: PalletsOriginOf, + proposal_hash: T::Hash, + enactment_moment: AtOrAfter, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + + let track = T::Tracks::track_for(&proposal_origin).map_err(|_| Error::::NoTrack)?; + let submission_deposit = Self::take_deposit(who, T::SubmissionDeposit::get())?; + let index = ReferendumCount::::mutate(|x| { + let r = *x; + *x += 1; + r + }); + let now = frame_system::Pallet::::block_number(); + let nudge_call = Call::nudge_referendum { index }; + let status = ReferendumStatus { + track, + origin: proposal_origin, + proposal_hash: proposal_hash.clone(), + enactment: enactment_moment, + submitted: now, + submission_deposit, + decision_deposit: None, + deciding: None, + tally: Default::default(), + in_queue: false, + alarm: Self::set_alarm(nudge_call, now.saturating_add(T::UndecidingTimeout::get())), + }; + ReferendumInfoFor::::insert(index, ReferendumInfo::Ongoing(status)); + + Self::deposit_event(Event::::Submitted { index, track, proposal_hash }); + Ok(()) + } + + /// Post the Decision Deposit for a referendum. + /// + /// - `origin`: must be `Signed` and the account must have funds available for the + /// referendum's track's Decision Deposit. + /// - `index`: The index of the submitted referendum whose Decision Deposit is yet to be + /// posted. + /// + /// Emits `DecisionDepositPlaced`. + #[pallet::weight(ServiceBranch::max_weight_of_deposit::())] + pub fn place_decision_deposit( + origin: OriginFor, + index: ReferendumIndex, + ) -> DispatchResultWithPostInfo { + let who = ensure_signed(origin)?; + let mut status = Self::ensure_ongoing(index)?; + ensure!(status.decision_deposit.is_none(), Error::::HaveDeposit); + let track = Self::track(status.track).ok_or(Error::::NoTrack)?; + status.decision_deposit = + Some(Self::take_deposit(who.clone(), track.decision_deposit)?); + let now = frame_system::Pallet::::block_number(); + let (info, _, branch) = Self::service_referendum(now, index, status); + ReferendumInfoFor::::insert(index, info); + let e = + Event::::DecisionDepositPlaced { index, who, amount: track.decision_deposit }; + Self::deposit_event(e); + Ok(branch.weight_of_deposit::().into()) + } + + /// Refund the Decision Deposit for a closed referendum back to the depositor. + /// + /// - `origin`: must be `Signed` or `Root`. + /// - `index`: The index of a closed referendum whose Decision Deposit has not yet been + /// refunded. + /// + /// Emits `DecisionDepositRefunded`. + #[pallet::weight(T::WeightInfo::refund_decision_deposit())] + pub fn refund_decision_deposit( + origin: OriginFor, + index: ReferendumIndex, + ) -> DispatchResult { + ensure_signed_or_root(origin)?; + let mut info = ReferendumInfoFor::::get(index).ok_or(Error::::BadReferendum)?; + let deposit = info + .take_decision_deposit() + .map_err(|_| Error::::Unfinished)? + .ok_or(Error::::NoDeposit)?; + Self::refund_deposit(Some(deposit.clone())); + ReferendumInfoFor::::insert(index, info); + let e = Event::::DecisionDepositRefunded { + index, + who: deposit.who, + amount: deposit.amount, + }; + Self::deposit_event(e); + Ok(()) + } + + /// Cancel an ongoing referendum. + /// + /// - `origin`: must be the `CancelOrigin`. + /// - `index`: The index of the referendum to be cancelled. + /// + /// Emits `Cancelled`. + #[pallet::weight(T::WeightInfo::cancel())] + pub fn cancel(origin: OriginFor, index: ReferendumIndex) -> DispatchResult { + T::CancelOrigin::ensure_origin(origin)?; + let status = Self::ensure_ongoing(index)?; + if let Some((_, last_alarm)) = status.alarm { + let _ = T::Scheduler::cancel(last_alarm); + } + Self::note_one_fewer_deciding(status.track); + Self::deposit_event(Event::::Cancelled { index, tally: status.tally }); + let info = ReferendumInfo::Cancelled( + frame_system::Pallet::::block_number(), + status.submission_deposit, + status.decision_deposit, + ); + ReferendumInfoFor::::insert(index, info); + Ok(()) + } + + /// Cancel an ongoing referendum and slash the deposits. + /// + /// - `origin`: must be the `KillOrigin`. + /// - `index`: The index of the referendum to be cancelled. + /// + /// Emits `Killed` and `DepositSlashed`. + #[pallet::weight(T::WeightInfo::kill())] + pub fn kill(origin: OriginFor, index: ReferendumIndex) -> DispatchResult { + T::KillOrigin::ensure_origin(origin)?; + let status = Self::ensure_ongoing(index)?; + if let Some((_, last_alarm)) = status.alarm { + let _ = T::Scheduler::cancel(last_alarm); + } + Self::note_one_fewer_deciding(status.track); + Self::deposit_event(Event::::Killed { index, tally: status.tally }); + Self::slash_deposit(Some(status.submission_deposit.clone())); + Self::slash_deposit(status.decision_deposit.clone()); + let info = ReferendumInfo::Killed(frame_system::Pallet::::block_number()); + ReferendumInfoFor::::insert(index, info); + Ok(()) + } + + /// Advance a referendum onto its next logical state. Only used internally. + /// + /// - `origin`: must be `Root`. + /// - `index`: the referendum to be advanced. + #[pallet::weight(ServiceBranch::max_weight_of_nudge::())] + pub fn nudge_referendum( + origin: OriginFor, + index: ReferendumIndex, + ) -> DispatchResultWithPostInfo { + ensure_root(origin)?; + let now = frame_system::Pallet::::block_number(); + let mut status = Self::ensure_ongoing(index)?; + // This is our wake-up, so we can disregard the alarm. + status.alarm = None; + let (info, dirty, branch) = Self::service_referendum(now, index, status); + if dirty { + ReferendumInfoFor::::insert(index, info); + } + Ok(Some(branch.weight_of_nudge::()).into()) + } + + /// Advance a track onto its next logical state. Only used internally. + /// + /// - `origin`: must be `Root`. + /// - `track`: the track to be advanced. + /// + /// Action item for when there is now one fewer referendum in the deciding phase and the + /// `DecidingCount` is not yet updated. This means that we should either: + /// - begin deciding another referendum (and leave `DecidingCount` alone); or + /// - decrement `DecidingCount`. + #[pallet::weight(OneFewerDecidingBranch::max_weight::())] + pub fn one_fewer_deciding( + origin: OriginFor, + track: TrackIdOf, + ) -> DispatchResultWithPostInfo { + ensure_root(origin)?; + let track_info = T::Tracks::info(track).ok_or(Error::::BadTrack)?; + let mut track_queue = TrackQueue::::get(track); + let branch = + if let Some((index, mut status)) = Self::next_for_deciding(&mut track_queue) { + let now = frame_system::Pallet::::block_number(); + let (maybe_alarm, branch) = + Self::begin_deciding(&mut status, index, now, track_info); + if let Some(set_alarm) = maybe_alarm { + Self::ensure_alarm_at(&mut status, index, set_alarm); + } + ReferendumInfoFor::::insert(index, ReferendumInfo::Ongoing(status)); + TrackQueue::::insert(track, track_queue); + branch.into() + } else { + DecidingCount::::mutate(track, |x| x.saturating_dec()); + OneFewerDecidingBranch::QueueEmpty + }; + Ok(Some(branch.weight::()).into()) + } + } +} + +impl Polling for Pallet { + type Index = ReferendumIndex; + type Votes = VotesOf; + type Moment = T::BlockNumber; + type Class = TrackIdOf; + + fn classes() -> Vec { + T::Tracks::tracks().iter().map(|x| x.0).collect() + } + + fn access_poll( + index: Self::Index, + f: impl FnOnce(PollStatus<&mut T::Tally, T::BlockNumber, TrackIdOf>) -> R, + ) -> R { + match ReferendumInfoFor::::get(index) { + Some(ReferendumInfo::Ongoing(mut status)) => { + let result = f(PollStatus::Ongoing(&mut status.tally, status.track)); + let now = frame_system::Pallet::::block_number(); + Self::ensure_alarm_at(&mut status, index, now + One::one()); + ReferendumInfoFor::::insert(index, ReferendumInfo::Ongoing(status)); + result + }, + Some(ReferendumInfo::Approved(end, ..)) => f(PollStatus::Completed(end, true)), + Some(ReferendumInfo::Rejected(end, ..)) => f(PollStatus::Completed(end, false)), + _ => f(PollStatus::None), + } + } + + fn try_access_poll( + index: Self::Index, + f: impl FnOnce( + PollStatus<&mut T::Tally, T::BlockNumber, TrackIdOf>, + ) -> Result, + ) -> Result { + match ReferendumInfoFor::::get(index) { + Some(ReferendumInfo::Ongoing(mut status)) => { + let result = f(PollStatus::Ongoing(&mut status.tally, status.track))?; + let now = frame_system::Pallet::::block_number(); + Self::ensure_alarm_at(&mut status, index, now + One::one()); + ReferendumInfoFor::::insert(index, ReferendumInfo::Ongoing(status)); + Ok(result) + }, + Some(ReferendumInfo::Approved(end, ..)) => f(PollStatus::Completed(end, true)), + Some(ReferendumInfo::Rejected(end, ..)) => f(PollStatus::Completed(end, false)), + _ => f(PollStatus::None), + } + } + + fn as_ongoing(index: Self::Index) -> Option<(T::Tally, TrackIdOf)> { + Self::ensure_ongoing(index).ok().map(|x| (x.tally, x.track)) + } + + #[cfg(feature = "runtime-benchmarks")] + fn create_ongoing(class: Self::Class) -> Result { + let index = ReferendumCount::::mutate(|x| { + let r = *x; + *x += 1; + r + }); + let now = frame_system::Pallet::::block_number(); + let dummy_account_id = + codec::Decode::decode(&mut sp_runtime::traits::TrailingZeroInput::new(&b"dummy"[..])) + .expect("infinite length input; no invalid inputs for type; qed"); + let mut status = ReferendumStatusOf:: { + track: class, + origin: frame_support::dispatch::RawOrigin::Root.into(), + proposal_hash: ::hash_of(&index), + enactment: AtOrAfter::After(Zero::zero()), + submitted: now, + submission_deposit: Deposit { who: dummy_account_id, amount: Zero::zero() }, + decision_deposit: None, + deciding: None, + tally: Default::default(), + in_queue: false, + alarm: None, + }; + Self::ensure_alarm_at(&mut status, index, sp_runtime::traits::Bounded::max_value()); + ReferendumInfoFor::::insert(index, ReferendumInfo::Ongoing(status)); + Ok(index) + } + + #[cfg(feature = "runtime-benchmarks")] + fn end_ongoing(index: Self::Index, approved: bool) -> Result<(), ()> { + let mut status = Self::ensure_ongoing(index).map_err(|_| ())?; + Self::ensure_no_alarm(&mut status); + Self::note_one_fewer_deciding(status.track); + let now = frame_system::Pallet::::block_number(); + let info = if approved { + ReferendumInfo::Approved(now, status.submission_deposit, status.decision_deposit) + } else { + ReferendumInfo::Rejected(now, status.submission_deposit, status.decision_deposit) + }; + ReferendumInfoFor::::insert(index, info); + Ok(()) + } + + #[cfg(feature = "runtime-benchmarks")] + fn max_ongoing() -> (Self::Class, u32) { + let r = T::Tracks::tracks() + .iter() + .max_by_key(|(_, info)| info.max_deciding) + .expect("Always one class"); + (r.0.clone(), r.1.max_deciding) + } +} + +impl Pallet { + /// Check that referendum `index` is in the `Ongoing` state and return the `ReferendumStatus` + /// value, or `Err` otherwise. + pub fn ensure_ongoing(index: ReferendumIndex) -> Result, DispatchError> { + match ReferendumInfoFor::::get(index) { + Some(ReferendumInfo::Ongoing(status)) => Ok(status), + _ => Err(Error::::NotOngoing.into()), + } + } + + // Enqueue a proposal from a referendum which has presumably passed. + fn schedule_enactment( + index: ReferendumIndex, + track: &TrackInfoOf, + desired: AtOrAfter, + origin: PalletsOriginOf, + call_hash: T::Hash, + ) { + let now = frame_system::Pallet::::block_number(); + let earliest_allowed = now.saturating_add(track.min_enactment_period); + let desired = desired.evaluate(now); + let ok = T::Scheduler::schedule_named( + (ASSEMBLY_ID, "enactment", index).encode(), + DispatchTime::At(desired.max(earliest_allowed)), + None, + 63, + origin, + MaybeHashed::Hash(call_hash), + ) + .is_ok(); + debug_assert!(ok, "LOGIC ERROR: bake_referendum/schedule_named failed"); + } + + /// Set an alarm to dispatch `call` at block number `when`. + fn set_alarm( + call: impl Into>, + when: T::BlockNumber, + ) -> Option<(T::BlockNumber, ScheduleAddressOf)> { + let alarm_interval = T::AlarmInterval::get().max(One::one()); + let when = (when + alarm_interval - One::one()) / alarm_interval * alarm_interval; + let maybe_result = T::Scheduler::schedule( + DispatchTime::At(when), + None, + 128u8, + frame_system::RawOrigin::Root.into(), + MaybeHashed::Value(call.into()), + ) + .ok() + .map(|x| (when, x)); + debug_assert!( + maybe_result.is_some(), + "Unable to schedule a new alarm at #{:?} (now: #{:?})?!", + when, + frame_system::Pallet::::block_number() + ); + maybe_result + } + + /// Mutate a referendum's `status` into the correct deciding state. + /// + /// - `now` is the current block number. + /// - `track` is the track info for the referendum. + /// + /// This will properly set up the `confirming` item. + fn begin_deciding( + status: &mut ReferendumStatusOf, + index: ReferendumIndex, + now: T::BlockNumber, + track: &TrackInfoOf, + ) -> (Option, BeginDecidingBranch) { + let is_passing = Self::is_passing( + &status.tally, + Zero::zero(), + track.decision_period, + &track.min_turnout, + &track.min_approval, + ); + status.in_queue = false; + Self::deposit_event(Event::::DecisionStarted { + index, + tally: status.tally.clone(), + proposal_hash: status.proposal_hash.clone(), + track: status.track.clone(), + }); + let confirming = if is_passing { + Self::deposit_event(Event::::ConfirmStarted { index }); + Some(now.saturating_add(track.confirm_period)) + } else { + None + }; + let deciding_status = DecidingStatus { since: now, confirming }; + let alarm = Self::decision_time(&deciding_status, &status.tally, track); + status.deciding = Some(deciding_status); + let branch = + if is_passing { BeginDecidingBranch::Passing } else { BeginDecidingBranch::Failing }; + (Some(alarm), branch) + } + + /// If it returns `Some`, deciding has begun and it needs waking at the given block number. The + /// second item is the flag for whether it is confirming or not. + /// + /// If `None`, then it is queued and should be nudged automatically as the queue gets drained. + fn ready_for_deciding( + now: T::BlockNumber, + track: &TrackInfoOf, + index: ReferendumIndex, + status: &mut ReferendumStatusOf, + ) -> (Option, ServiceBranch) { + let deciding_count = DecidingCount::::get(status.track); + if deciding_count < track.max_deciding { + // Begin deciding. + DecidingCount::::insert(status.track, deciding_count.saturating_add(1)); + let r = Self::begin_deciding(status, index, now, track); + (r.0, r.1.into()) + } else { + // Add to queue. + let item = (index, status.tally.ayes()); + status.in_queue = true; + TrackQueue::::mutate(status.track, |q| q.insert_sorted_by_key(item, |x| x.1)); + (None, ServiceBranch::Queued) + } + } + + /// Grab the index and status for the referendum which is the highest priority of those for the + /// given track which are ready for being decided. + fn next_for_deciding( + track_queue: &mut BoundedVec<(u32, VotesOf), T::MaxQueued>, + ) -> Option<(ReferendumIndex, ReferendumStatusOf)> { + loop { + let (index, _) = track_queue.pop()?; + match Self::ensure_ongoing(index) { + Ok(s) => return Some((index, s)), + Err(_) => {}, // referendum already timedout or was cancelled. + } + } + } + + /// Schedule a call to `one_fewer_deciding` function via the dispatchable + /// `defer_one_fewer_deciding`. We could theoretically call it immediately (and it would be + /// overall more efficient), however the weights become rather less easy to measure. + fn note_one_fewer_deciding(track: TrackIdOf) { + // Set an alarm call for the next block to nudge the track along. + let now = frame_system::Pallet::::block_number(); + let next_block = now + One::one(); + let alarm_interval = T::AlarmInterval::get().max(One::one()); + let when = (next_block + alarm_interval - One::one()) / alarm_interval * alarm_interval; + + let maybe_result = T::Scheduler::schedule( + DispatchTime::At(when), + None, + 128u8, + frame_system::RawOrigin::Root.into(), + MaybeHashed::Value(Call::one_fewer_deciding { track }.into()), + ); + debug_assert!( + maybe_result.is_ok(), + "Unable to schedule a new alarm at #{:?} (now: #{:?})?!", + when, + now + ); + } + + /// Ensure that a `service_referendum` alarm happens for the referendum `index` at `alarm`. + /// + /// This will do nothing if the alarm is already set. + /// + /// Returns `false` if nothing changed. + fn ensure_alarm_at( + status: &mut ReferendumStatusOf, + index: ReferendumIndex, + alarm: T::BlockNumber, + ) -> bool { + if status.alarm.as_ref().map_or(true, |&(when, _)| when != alarm) { + // Either no alarm or one that was different + Self::ensure_no_alarm(status); + status.alarm = Self::set_alarm(Call::nudge_referendum { index }, alarm); + true + } else { + false + } + } + + /// Advance the state of a referendum, which comes down to: + /// - If it's ready to be decided, start deciding; + /// - If it's not ready to be decided and non-deciding timeout has passed, fail; + /// - If it's ongoing and passing, ensure confirming; if at end of confirmation period, pass. + /// - If it's ongoing and not passing, stop confirning; if it has reached end time, fail. + /// + /// Weight will be a bit different depending on what it does, but it's designed so as not to + /// differ dramatically, especially if `MaxQueue` is kept small. In particular _there are no + /// balance operations in here_. + /// + /// In terms of storage, every call to it is expected to access: + /// - The scheduler, either to insert, remove or alter an entry; + /// - `TrackQueue`, which should be a `BoundedVec` with a low limit (8-16). + /// - `DecidingCount`. + /// + /// Both of the two storage items will only have as many items as there are different tracks, + /// perhaps around 10 and should be whitelisted. + /// + /// The heaviest branch is likely to be when a proposal is placed into, or moved within, the + /// `TrackQueue`. Basically this happens when a referendum is in the deciding queue and receives + /// a vote, or when it moves into the deciding queue. + fn service_referendum( + now: T::BlockNumber, + index: ReferendumIndex, + mut status: ReferendumStatusOf, + ) -> (ReferendumInfoOf, bool, ServiceBranch) { + let mut dirty = false; + // Should it begin being decided? + let track = match Self::track(status.track) { + Some(x) => x, + None => return (ReferendumInfo::Ongoing(status), false, ServiceBranch::Fail), + }; + let timeout = status.submitted + T::UndecidingTimeout::get(); + // Default the alarm to the submission timeout. + let mut alarm = timeout; + let branch; + match &mut status.deciding { + None => { + // Are we already queued for deciding? + if status.in_queue { + // Does our position in the queue need updating? + let ayes = status.tally.ayes(); + let mut queue = TrackQueue::::get(status.track); + let maybe_old_pos = queue.iter().position(|(x, _)| *x == index); + let new_pos = queue.binary_search_by_key(&ayes, |x| x.1).unwrap_or_else(|x| x); + branch = if maybe_old_pos.is_none() && new_pos > 0 { + // Just insert. + queue.force_insert_keep_right(new_pos, (index, ayes)); + ServiceBranch::RequeuedInsertion + } else if let Some(old_pos) = maybe_old_pos { + // We were in the queue - slide into the correct position. + queue[old_pos].1 = ayes; + queue.slide(old_pos, new_pos); + ServiceBranch::RequeuedSlide + } else { + ServiceBranch::NotQueued + }; + TrackQueue::::insert(status.track, queue); + } else { + // Are we ready for deciding? + branch = if status.decision_deposit.is_some() { + let prepare_end = status.submitted.saturating_add(track.prepare_period); + if now >= prepare_end { + let (maybe_alarm, branch) = + Self::ready_for_deciding(now, &track, index, &mut status); + if let Some(set_alarm) = maybe_alarm { + alarm = alarm.min(set_alarm); + } + dirty = true; + branch + } else { + alarm = alarm.min(prepare_end); + ServiceBranch::Preparing + } + } else { + ServiceBranch::NoDeposit + } + } + // If we didn't move into being decided, then check the timeout. + if status.deciding.is_none() && now >= timeout { + // Too long without being decided - end it. + Self::ensure_no_alarm(&mut status); + Self::deposit_event(Event::::TimedOut { index, tally: status.tally }); + return ( + ReferendumInfo::TimedOut( + now, + status.submission_deposit, + status.decision_deposit, + ), + true, + ServiceBranch::TimedOut, + ) + } + }, + Some(deciding) => { + let is_passing = Self::is_passing( + &status.tally, + now.saturating_sub(deciding.since), + track.decision_period, + &track.min_turnout, + &track.min_approval, + ); + branch = if is_passing { + match deciding.confirming.clone() { + Some(t) if now >= t => { + // Passed! + Self::ensure_no_alarm(&mut status); + Self::note_one_fewer_deciding(status.track); + let (desired, call_hash) = (status.enactment, status.proposal_hash); + Self::schedule_enactment( + index, + track, + desired, + status.origin, + call_hash, + ); + Self::deposit_event(Event::::Confirmed { + index, + tally: status.tally, + }); + return ( + ReferendumInfo::Approved( + now, + status.submission_deposit, + status.decision_deposit, + ), + true, + ServiceBranch::Approved, + ) + }, + Some(_) => ServiceBranch::ContinueConfirming, + None => { + // Start confirming + dirty = true; + deciding.confirming = Some(now.saturating_add(track.confirm_period)); + Self::deposit_event(Event::::ConfirmStarted { index }); + ServiceBranch::BeginConfirming + }, + } + } else { + if now >= deciding.since.saturating_add(track.decision_period) { + // Failed! + Self::ensure_no_alarm(&mut status); + Self::note_one_fewer_deciding(status.track); + Self::deposit_event(Event::::Rejected { index, tally: status.tally }); + return ( + ReferendumInfo::Rejected( + now, + status.submission_deposit, + status.decision_deposit, + ), + true, + ServiceBranch::Rejected, + ) + } + if deciding.confirming.is_some() { + // Stop confirming + dirty = true; + deciding.confirming = None; + Self::deposit_event(Event::::ConfirmAborted { index }); + ServiceBranch::EndConfirming + } else { + ServiceBranch::ContinueNotConfirming + } + }; + alarm = Self::decision_time(&deciding, &status.tally, track); + }, + } + + let dirty_alarm = Self::ensure_alarm_at(&mut status, index, alarm); + (ReferendumInfo::Ongoing(status), dirty_alarm || dirty, branch) + } + + /// Determine the point at which a referendum will be accepted, move into confirmation with the + /// given `tally` or end with rejection (whichever happens sooner). + fn decision_time( + deciding: &DecidingStatusOf, + tally: &T::Tally, + track: &TrackInfoOf, + ) -> T::BlockNumber { + deciding.confirming.unwrap_or_else(|| { + // Set alarm to the point where the current voting would make it pass. + let approval = tally.approval(); + let turnout = tally.turnout(); + let until_approval = track.min_approval.delay(approval); + let until_turnout = track.min_turnout.delay(turnout); + let offset = until_turnout.max(until_approval); + deciding.since.saturating_add(offset * track.decision_period) + }) + } + + /// Cancel the alarm in `status`, if one exists. + fn ensure_no_alarm(status: &mut ReferendumStatusOf) { + if let Some((_, last_alarm)) = status.alarm.take() { + // Incorrect alarm - cancel it. + let _ = T::Scheduler::cancel(last_alarm); + } + } + + /// Reserve a deposit and return the `Deposit` instance. + fn take_deposit( + who: T::AccountId, + amount: BalanceOf, + ) -> Result>, DispatchError> { + T::Currency::reserve(&who, amount)?; + Ok(Deposit { who, amount }) + } + + /// Return a deposit, if `Some`. + fn refund_deposit(deposit: Option>>) { + if let Some(Deposit { who, amount }) = deposit { + T::Currency::unreserve(&who, amount); + } + } + + /// Slash a deposit, if `Some`. + fn slash_deposit(deposit: Option>>) { + if let Some(Deposit { who, amount }) = deposit { + T::Slash::on_unbalanced(T::Currency::slash_reserved(&who, amount).0); + Self::deposit_event(Event::::DepositSlashed { who, amount }); + } + } + + /// Get the track info value for the track `id`. + fn track(id: TrackIdOf) -> Option<&'static TrackInfoOf> { + let tracks = T::Tracks::tracks(); + let index = tracks.binary_search_by_key(&id, |x| x.0).unwrap_or_else(|x| x); + Some(&tracks[index].1) + } + + /// Determine whether the given `tally` would result in a referendum passing at `elapsed` blocks + /// into a total decision `period`, given the two curves for `turnout_needed` and + /// `approval_needed`. + fn is_passing( + tally: &T::Tally, + elapsed: T::BlockNumber, + period: T::BlockNumber, + turnout_needed: &Curve, + approval_needed: &Curve, + ) -> bool { + let x = Perbill::from_rational(elapsed.min(period), period); + turnout_needed.passing(x, tally.turnout()) && approval_needed.passing(x, tally.approval()) + } +} diff --git a/frame/referenda/src/mock.rs b/frame/referenda/src/mock.rs new file mode 100644 index 000000000000..063b124f2b71 --- /dev/null +++ b/frame/referenda/src/mock.rs @@ -0,0 +1,460 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2022 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. + +//! The crate's tests. + +use super::*; +use crate as pallet_referenda; +use codec::{Decode, Encode, MaxEncodedLen}; +use frame_support::{ + assert_ok, ord_parameter_types, parameter_types, + traits::{ + ConstU32, ConstU64, Contains, EqualPrivilegeOnly, OnInitialize, OriginTrait, Polling, + PreimageRecipient, SortedMembers, + }, + weights::Weight, +}; +use frame_system::{EnsureRoot, EnsureSignedBy}; +use sp_core::H256; +use sp_runtime::{ + testing::Header, + traits::{BlakeTwo256, Hash, IdentityLookup}, + DispatchResult, Perbill, +}; + +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlock; + +frame_support::construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system, + Balances: pallet_balances, + Preimage: pallet_preimage, + Scheduler: pallet_scheduler, + Referenda: pallet_referenda, + } +); + +// Test that a fitlered call can be dispatched. +pub struct BaseFilter; +impl Contains for BaseFilter { + fn contains(call: &Call) -> bool { + !matches!(call, &Call::Balances(pallet_balances::Call::set_balance { .. })) + } +} + +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub BlockWeights: frame_system::limits::BlockWeights = + frame_system::limits::BlockWeights::simple_max(1_000_000); +} +impl frame_system::Config for Test { + type BaseCallFilter = BaseFilter; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Call = Call; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = Event; + type BlockHashCount = BlockHashCount; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = ConstU32<16>; +} +impl pallet_preimage::Config for Test { + type Event = Event; + type WeightInfo = (); + type Currency = Balances; + type ManagerOrigin = EnsureRoot; + type MaxSize = ConstU32<4096>; + type BaseDeposit = (); + type ByteDeposit = (); +} +parameter_types! { + pub MaximumSchedulerWeight: Weight = 2_000_000_000_000; +} +impl pallet_scheduler::Config for Test { + type Event = Event; + type Origin = Origin; + type PalletsOrigin = OriginCaller; + type Call = Call; + type MaximumWeight = MaximumSchedulerWeight; + type ScheduleOrigin = EnsureRoot; + type MaxScheduledPerBlock = ConstU32<100>; + type WeightInfo = (); + type OriginPrivilegeCmp = EqualPrivilegeOnly; + type PreimageProvider = Preimage; + type NoPreimagePostponement = ConstU64<10>; +} +parameter_types! { + pub const ExistentialDeposit: u64 = 1; + pub const MaxLocks: u32 = 10; +} +impl pallet_balances::Config for Test { + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; + type MaxLocks = MaxLocks; + type Balance = u64; + type Event = Event; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); +} +parameter_types! { + pub static AlarmInterval: u64 = 1; + pub const SubmissionDeposit: u64 = 2; + pub const MaxQueued: u32 = 3; + pub const UndecidingTimeout: u64 = 20; +} +ord_parameter_types! { + pub const One: u64 = 1; + pub const Two: u64 = 2; + pub const Three: u64 = 3; + pub const Four: u64 = 4; + pub const Five: u64 = 5; + pub const Six: u64 = 6; +} +pub struct OneToFive; +impl SortedMembers for OneToFive { + fn sorted_members() -> Vec { + vec![1, 2, 3, 4, 5] + } + #[cfg(feature = "runtime-benchmarks")] + fn add(_m: &u64) {} +} + +pub struct TestTracksInfo; +impl TracksInfo for TestTracksInfo { + type Id = u8; + type Origin = ::PalletsOrigin; + fn tracks() -> &'static [(Self::Id, TrackInfo)] { + static DATA: [(u8, TrackInfo); 2] = [ + ( + 0u8, + TrackInfo { + name: "root", + max_deciding: 1, + decision_deposit: 10, + prepare_period: 4, + decision_period: 4, + confirm_period: 2, + min_enactment_period: 4, + min_approval: Curve::LinearDecreasing { + begin: Perbill::from_percent(100), + delta: Perbill::from_percent(50), + }, + min_turnout: Curve::LinearDecreasing { + begin: Perbill::from_percent(100), + delta: Perbill::from_percent(100), + }, + }, + ), + ( + 1u8, + TrackInfo { + name: "none", + max_deciding: 3, + decision_deposit: 1, + prepare_period: 2, + decision_period: 2, + confirm_period: 1, + min_enactment_period: 2, + min_approval: Curve::LinearDecreasing { + begin: Perbill::from_percent(55), + delta: Perbill::from_percent(5), + }, + min_turnout: Curve::LinearDecreasing { + begin: Perbill::from_percent(10), + delta: Perbill::from_percent(10), + }, + }, + ), + ]; + &DATA[..] + } + fn track_for(id: &Self::Origin) -> Result { + if let Ok(system_origin) = frame_system::RawOrigin::try_from(id.clone()) { + match system_origin { + frame_system::RawOrigin::Root => Ok(0), + frame_system::RawOrigin::None => Ok(1), + _ => Err(()), + } + } else { + Err(()) + } + } +} + +impl Config for Test { + type WeightInfo = (); + type Call = Call; + type Event = Event; + type Scheduler = Scheduler; + type Currency = pallet_balances::Pallet; + type CancelOrigin = EnsureSignedBy; + type KillOrigin = EnsureRoot; + type Slash = (); + type Votes = u32; + type Tally = Tally; + type SubmissionDeposit = SubmissionDeposit; + type MaxQueued = MaxQueued; + type UndecidingTimeout = UndecidingTimeout; + type AlarmInterval = AlarmInterval; + type Tracks = TestTracksInfo; +} + +pub fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + let balances = vec![(1, 100), (2, 100), (3, 100), (4, 100), (5, 100), (6, 100)]; + pallet_balances::GenesisConfig:: { balances } + .assimilate_storage(&mut t) + .unwrap(); + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| System::set_block_number(1)); + ext +} + +/// Execute the function two times, with `true` and with `false`. +#[allow(dead_code)] +pub fn new_test_ext_execute_with_cond(execute: impl FnOnce(bool) -> () + Clone) { + new_test_ext().execute_with(|| (execute.clone())(false)); + new_test_ext().execute_with(|| execute(true)); +} + +#[derive(Encode, Debug, Decode, TypeInfo, Eq, PartialEq, Clone, Default, MaxEncodedLen)] +pub struct Tally { + pub ayes: u32, + pub nays: u32, +} + +impl VoteTally for Tally { + fn ayes(&self) -> u32 { + self.ayes + } + + fn turnout(&self) -> Perbill { + Perbill::from_percent(self.ayes + self.nays) + } + + fn approval(&self) -> Perbill { + Perbill::from_rational(self.ayes, self.ayes + self.nays) + } + + #[cfg(feature = "runtime-benchmarks")] + fn unanimity() -> Self { + Self { ayes: 100, nays: 0 } + } + + #[cfg(feature = "runtime-benchmarks")] + fn from_requirements(turnout: Perbill, approval: Perbill) -> Self { + let turnout = turnout.mul_ceil(100u32); + let ayes = approval.mul_ceil(turnout); + Self { ayes, nays: turnout - ayes } + } +} + +pub fn set_balance_proposal(value: u64) -> Vec { + Call::Balances(pallet_balances::Call::set_balance { who: 42, new_free: value, new_reserved: 0 }) + .encode() +} + +pub fn set_balance_proposal_hash(value: u64) -> H256 { + let c = Call::Balances(pallet_balances::Call::set_balance { + who: 42, + new_free: value, + new_reserved: 0, + }); + >::note_preimage(c.encode().try_into().unwrap()); + BlakeTwo256::hash_of(&c) +} + +#[allow(dead_code)] +pub fn propose_set_balance(who: u64, value: u64, delay: u64) -> DispatchResult { + Referenda::submit( + Origin::signed(who), + frame_system::RawOrigin::Root.into(), + set_balance_proposal_hash(value), + AtOrAfter::After(delay), + ) +} + +pub fn next_block() { + System::set_block_number(System::block_number() + 1); + Scheduler::on_initialize(System::block_number()); +} + +pub fn run_to(n: u64) { + while System::block_number() < n { + next_block(); + } +} + +#[allow(dead_code)] +pub fn begin_referendum() -> ReferendumIndex { + System::set_block_number(0); + assert_ok!(propose_set_balance(1, 2, 1)); + run_to(2); + 0 +} + +#[allow(dead_code)] +pub fn tally(r: ReferendumIndex) -> Tally { + Referenda::ensure_ongoing(r).unwrap().tally +} + +pub fn set_tally(index: ReferendumIndex, ayes: u32, nays: u32) { + >::access_poll(index, |status| { + let tally = status.ensure_ongoing().unwrap().0; + tally.ayes = ayes; + tally.nays = nays; + }); +} + +pub fn waiting_since(i: ReferendumIndex) -> u64 { + match ReferendumInfoFor::::get(i).unwrap() { + ReferendumInfo::Ongoing(ReferendumStatus { submitted, deciding: None, .. }) => submitted, + _ => panic!("Not waiting"), + } +} + +pub fn deciding_since(i: ReferendumIndex) -> u64 { + match ReferendumInfoFor::::get(i).unwrap() { + ReferendumInfo::Ongoing(ReferendumStatus { + deciding: Some(DecidingStatus { since, .. }), + .. + }) => since, + _ => panic!("Not deciding"), + } +} + +pub fn deciding_and_failing_since(i: ReferendumIndex) -> u64 { + match ReferendumInfoFor::::get(i).unwrap() { + ReferendumInfo::Ongoing(ReferendumStatus { + deciding: Some(DecidingStatus { since, confirming: None, .. }), + .. + }) => since, + _ => panic!("Not deciding"), + } +} + +pub fn confirming_until(i: ReferendumIndex) -> u64 { + match ReferendumInfoFor::::get(i).unwrap() { + ReferendumInfo::Ongoing(ReferendumStatus { + deciding: Some(DecidingStatus { confirming: Some(until), .. }), + .. + }) => until, + _ => panic!("Not confirming"), + } +} + +pub fn approved_since(i: ReferendumIndex) -> u64 { + match ReferendumInfoFor::::get(i).unwrap() { + ReferendumInfo::Approved(since, ..) => since, + _ => panic!("Not approved"), + } +} + +pub fn rejected_since(i: ReferendumIndex) -> u64 { + match ReferendumInfoFor::::get(i).unwrap() { + ReferendumInfo::Rejected(since, ..) => since, + _ => panic!("Not rejected"), + } +} + +pub fn cancelled_since(i: ReferendumIndex) -> u64 { + match ReferendumInfoFor::::get(i).unwrap() { + ReferendumInfo::Cancelled(since, ..) => since, + _ => panic!("Not cancelled"), + } +} + +pub fn killed_since(i: ReferendumIndex) -> u64 { + match ReferendumInfoFor::::get(i).unwrap() { + ReferendumInfo::Killed(since, ..) => since, + _ => panic!("Not killed"), + } +} + +pub fn timed_out_since(i: ReferendumIndex) -> u64 { + match ReferendumInfoFor::::get(i).unwrap() { + ReferendumInfo::TimedOut(since, ..) => since, + _ => panic!("Not timed out"), + } +} + +fn is_deciding(i: ReferendumIndex) -> bool { + matches!( + ReferendumInfoFor::::get(i), + Some(ReferendumInfo::Ongoing(ReferendumStatus { deciding: Some(_), .. })) + ) +} + +#[derive(Clone, Copy)] +pub enum RefState { + Failing, + Passing, + Confirming { immediate: bool }, +} + +impl RefState { + pub fn create(self) -> ReferendumIndex { + assert_ok!(Referenda::submit( + Origin::signed(1), + frame_support::dispatch::RawOrigin::Root.into(), + set_balance_proposal_hash(1), + AtOrAfter::At(10), + )); + assert_ok!(Referenda::place_decision_deposit(Origin::signed(2), 0)); + if matches!(self, RefState::Confirming { immediate: true }) { + set_tally(0, 100, 0); + } + let index = ReferendumCount::::get() - 1; + while !is_deciding(index) { + run_to(System::block_number() + 1); + } + if matches!(self, RefState::Confirming { immediate: false }) { + set_tally(0, 100, 0); + run_to(System::block_number() + 1); + } + if matches!(self, RefState::Confirming { .. }) { + assert_eq!(confirming_until(index), System::block_number() + 2); + } + if matches!(self, RefState::Passing) { + set_tally(0, 100, 99); + run_to(System::block_number() + 1); + } + index + } +} diff --git a/frame/referenda/src/tests.rs b/frame/referenda/src/tests.rs new file mode 100644 index 000000000000..cea071ced12f --- /dev/null +++ b/frame/referenda/src/tests.rs @@ -0,0 +1,511 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2022 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. + +//! The crate's tests. + +use super::*; +use crate::mock::{RefState::*, *}; +use assert_matches::assert_matches; +use codec::Decode; +use frame_support::{ + assert_noop, assert_ok, + dispatch::{DispatchError::BadOrigin, RawOrigin}, + traits::Contains, +}; +use pallet_balances::Error as BalancesError; + +// TODO: Scheduler should re-use `None` items in its `Agenda`. + +#[test] +fn params_should_work() { + new_test_ext().execute_with(|| { + assert_eq!(ReferendumCount::::get(), 0); + assert_eq!(Balances::free_balance(42), 0); + assert_eq!(Balances::total_issuance(), 600); + }); +} + +#[test] +fn basic_happy_path_works() { + new_test_ext().execute_with(|| { + // #1: submit + assert_ok!(Referenda::submit( + Origin::signed(1), + RawOrigin::Root.into(), + set_balance_proposal_hash(1), + AtOrAfter::At(10), + )); + assert_eq!(Balances::reserved_balance(&1), 2); + assert_eq!(ReferendumCount::::get(), 1); + assert_ok!(Referenda::place_decision_deposit(Origin::signed(2), 0)); + run_to(4); + assert_eq!(DecidingCount::::get(0), 0); + run_to(5); + // #5: 4 blocks after submit - vote should now be deciding. + assert_eq!(DecidingCount::::get(0), 1); + run_to(6); + // #6: Lots of ayes. Should now be confirming. + set_tally(0, 100, 0); + run_to(7); + assert_eq!(confirming_until(0), 9); + run_to(9); + // #8: Should be confirmed & ended. + assert_eq!(approved_since(0), 9); + assert_ok!(Referenda::refund_decision_deposit(Origin::signed(2), 0)); + run_to(12); + // #9: Should not yet be enacted. + assert_eq!(Balances::free_balance(&42), 0); + run_to(13); + // #10: Proposal should be executed. + assert_eq!(Balances::free_balance(&42), 1); + }); +} + +#[test] +fn insta_confirm_then_kill_works() { + new_test_ext().execute_with(|| { + let r = Confirming { immediate: true }.create(); + run_to(6); + assert_ok!(Referenda::kill(Origin::root(), r)); + assert_eq!(killed_since(r), 6); + }); +} + +#[test] +fn confirm_then_reconfirm_with_elapsed_trigger_works() { + new_test_ext().execute_with(|| { + let r = Confirming { immediate: false }.create(); + assert_eq!(confirming_until(r), 8); + run_to(7); + set_tally(r, 100, 99); + run_to(8); + assert_eq!(deciding_and_failing_since(r), 5); + run_to(11); + assert_eq!(approved_since(r), 11); + }); +} + +#[test] +fn instaconfirm_then_reconfirm_with_elapsed_trigger_works() { + new_test_ext().execute_with(|| { + let r = Confirming { immediate: true }.create(); + run_to(6); + assert_eq!(confirming_until(r), 7); + set_tally(r, 100, 99); + run_to(7); + assert_eq!(deciding_and_failing_since(r), 5); + run_to(11); + assert_eq!(approved_since(r), 11); + }); +} + +#[test] +fn instaconfirm_then_reconfirm_with_voting_trigger_works() { + new_test_ext().execute_with(|| { + let r = Confirming { immediate: true }.create(); + run_to(6); + assert_eq!(confirming_until(r), 7); + set_tally(r, 100, 99); + run_to(7); + assert_eq!(deciding_and_failing_since(r), 5); + run_to(8); + set_tally(r, 100, 0); + run_to(9); + assert_eq!(confirming_until(r), 11); + run_to(11); + assert_eq!(approved_since(r), 11); + }); +} + +#[test] +fn voting_should_extend_for_late_confirmation() { + new_test_ext().execute_with(|| { + let r = Passing.create(); + run_to(10); + assert_eq!(confirming_until(r), 11); + run_to(11); + assert_eq!(approved_since(r), 11); + }); +} + +#[test] +fn should_instafail_during_extension_confirmation() { + new_test_ext().execute_with(|| { + let r = Passing.create(); + run_to(10); + assert_eq!(confirming_until(r), 11); + // Should insta-fail since it's now past the normal voting time. + set_tally(r, 100, 101); + run_to(11); + assert_eq!(rejected_since(r), 11); + }); +} + +#[test] +fn confirming_then_fail_works() { + new_test_ext().execute_with(|| { + let r = Failing.create(); + // Normally ends at 5 + 4 (voting period) = 9. + assert_eq!(deciding_and_failing_since(r), 5); + set_tally(r, 100, 0); + run_to(6); + assert_eq!(confirming_until(r), 8); + set_tally(r, 100, 101); + run_to(9); + assert_eq!(rejected_since(r), 9); + }); +} + +#[test] +fn queueing_works() { + new_test_ext().execute_with(|| { + // Submit a proposal into a track with a queue len of 1. + assert_ok!(Referenda::submit( + Origin::signed(5), + RawOrigin::Root.into(), + set_balance_proposal_hash(0), + AtOrAfter::After(0), + )); + assert_ok!(Referenda::place_decision_deposit(Origin::signed(5), 0)); + + run_to(2); + + // Submit 3 more proposals into the same queue. + for i in 1..=4 { + assert_ok!(Referenda::submit( + Origin::signed(i), + RawOrigin::Root.into(), + set_balance_proposal_hash(i), + AtOrAfter::After(0), + )); + assert_ok!(Referenda::place_decision_deposit(Origin::signed(i), i as u32)); + // TODO: decision deposit after some initial votes with a non-highest voted coming + // first. + } + assert_eq!(ReferendumCount::::get(), 5); + + run_to(5); + // One should be being decided. + assert_eq!(DecidingCount::::get(0), 1); + assert_eq!(deciding_and_failing_since(0), 5); + for i in 1..=4 { + assert_eq!(waiting_since(i), 2); + } + + // Vote to set order. + set_tally(1, 1, 10); + set_tally(2, 2, 20); + set_tally(3, 3, 30); + set_tally(4, 100, 0); + println!("Agenda #6: {:?}", pallet_scheduler::Agenda::::get(6)); + run_to(6); + println!("{:?}", Vec::<_>::from(TrackQueue::::get(0))); + + // Cancel the first. + assert_ok!(Referenda::cancel(Origin::signed(4), 0)); + assert_eq!(cancelled_since(0), 6); + + // The other with the most approvals (#4) should be being decided. + run_to(7); + assert_eq!(DecidingCount::::get(0), 1); + assert_eq!(deciding_since(4), 7); + assert_eq!(confirming_until(4), 9); + + // Vote on the remaining two to change order. + println!("Set tally #1"); + set_tally(1, 30, 31); + println!("{:?}", Vec::<_>::from(TrackQueue::::get(0))); + println!("Set tally #2"); + set_tally(2, 20, 20); + println!("{:?}", Vec::<_>::from(TrackQueue::::get(0))); + + // Let confirmation period end. + run_to(9); + + // #4 should have been confirmed. + assert_eq!(approved_since(4), 9); + + // On to the next block to select the new referendum + run_to(10); + // #1 (the one with the most approvals) should now be being decided. + assert_eq!(deciding_since(1), 10); + + // Let it end unsuccessfully. + run_to(14); + assert_eq!(rejected_since(1), 14); + + // Service queue. + run_to(15); + // #2 should now be being decided. It will (barely) pass. + assert_eq!(deciding_and_failing_since(2), 15); + + // #2 moves into confirming at the last moment with a 50% approval. + run_to(19); + assert_eq!(confirming_until(2), 21); + + // #2 gets approved. + run_to(21); + assert_eq!(approved_since(2), 21); + + // The final one has since timed out. + run_to(22); + assert_eq!(timed_out_since(3), 22); + }); +} + +#[test] +fn auto_timeout_should_happen_with_nothing_but_submit() { + new_test_ext().execute_with(|| { + // #1: submit + assert_ok!(Referenda::submit( + Origin::signed(1), + RawOrigin::Root.into(), + set_balance_proposal_hash(1), + AtOrAfter::At(20), + )); + run_to(20); + assert_matches!(ReferendumInfoFor::::get(0), Some(ReferendumInfo::Ongoing(..))); + run_to(21); + // #11: Timed out - ended. + assert_matches!( + ReferendumInfoFor::::get(0), + Some(ReferendumInfo::TimedOut(21, _, None)) + ); + }); +} + +#[test] +fn tracks_are_distinguished() { + new_test_ext().execute_with(|| { + assert_ok!(Referenda::submit( + Origin::signed(1), + RawOrigin::Root.into(), + set_balance_proposal_hash(1), + AtOrAfter::At(10), + )); + assert_ok!(Referenda::submit( + Origin::signed(2), + RawOrigin::None.into(), + set_balance_proposal_hash(2), + AtOrAfter::At(20), + )); + + assert_ok!(Referenda::place_decision_deposit(Origin::signed(3), 0)); + assert_ok!(Referenda::place_decision_deposit(Origin::signed(4), 1)); + + let mut i = ReferendumInfoFor::::iter().collect::>(); + i.sort_by_key(|x| x.0); + assert_eq!( + i, + vec![ + ( + 0, + ReferendumInfo::Ongoing(ReferendumStatus { + track: 0, + origin: OriginCaller::system(RawOrigin::Root), + proposal_hash: set_balance_proposal_hash(1), + enactment: AtOrAfter::At(10), + submitted: 1, + submission_deposit: Deposit { who: 1, amount: 2 }, + decision_deposit: Some(Deposit { who: 3, amount: 10 }), + deciding: None, + tally: Tally { ayes: 0, nays: 0 }, + in_queue: false, + alarm: Some((5, (5, 0))), + }) + ), + ( + 1, + ReferendumInfo::Ongoing(ReferendumStatus { + track: 1, + origin: OriginCaller::system(RawOrigin::None), + proposal_hash: set_balance_proposal_hash(2), + enactment: AtOrAfter::At(20), + submitted: 1, + submission_deposit: Deposit { who: 2, amount: 2 }, + decision_deposit: Some(Deposit { who: 4, amount: 1 }), + deciding: None, + tally: Tally { ayes: 0, nays: 0 }, + in_queue: false, + alarm: Some((3, (3, 0))), + }) + ), + ] + ); + }); +} + +#[test] +fn submit_errors_work() { + new_test_ext().execute_with(|| { + let h = set_balance_proposal_hash(1); + // No track for Signed origins. + assert_noop!( + Referenda::submit(Origin::signed(1), RawOrigin::Signed(2).into(), h, AtOrAfter::At(10),), + Error::::NoTrack + ); + + // No funds for deposit + assert_noop!( + Referenda::submit(Origin::signed(10), RawOrigin::Root.into(), h, AtOrAfter::At(10),), + BalancesError::::InsufficientBalance + ); + }); +} + +#[test] +fn decision_deposit_errors_work() { + new_test_ext().execute_with(|| { + let e = Error::::NotOngoing; + assert_noop!(Referenda::place_decision_deposit(Origin::signed(2), 0), e); + + let h = set_balance_proposal_hash(1); + assert_ok!(Referenda::submit( + Origin::signed(1), + RawOrigin::Root.into(), + h, + AtOrAfter::At(10), + )); + let e = BalancesError::::InsufficientBalance; + assert_noop!(Referenda::place_decision_deposit(Origin::signed(10), 0), e); + + assert_ok!(Referenda::place_decision_deposit(Origin::signed(2), 0)); + let e = Error::::HaveDeposit; + assert_noop!(Referenda::place_decision_deposit(Origin::signed(2), 0), e); + }); +} + +#[test] +fn refund_deposit_works() { + new_test_ext().execute_with(|| { + let e = Error::::BadReferendum; + assert_noop!(Referenda::refund_decision_deposit(Origin::signed(1), 0), e); + + let h = set_balance_proposal_hash(1); + assert_ok!(Referenda::submit( + Origin::signed(1), + RawOrigin::Root.into(), + h, + AtOrAfter::At(10), + )); + let e = Error::::NoDeposit; + assert_noop!(Referenda::refund_decision_deposit(Origin::signed(2), 0), e); + + assert_ok!(Referenda::place_decision_deposit(Origin::signed(2), 0)); + let e = Error::::Unfinished; + assert_noop!(Referenda::refund_decision_deposit(Origin::signed(3), 0), e); + + run_to(11); + assert_ok!(Referenda::refund_decision_deposit(Origin::signed(3), 0)); + }); +} + +#[test] +fn cancel_works() { + new_test_ext().execute_with(|| { + let h = set_balance_proposal_hash(1); + assert_ok!(Referenda::submit( + Origin::signed(1), + RawOrigin::Root.into(), + h, + AtOrAfter::At(10), + )); + assert_ok!(Referenda::place_decision_deposit(Origin::signed(2), 0)); + + run_to(8); + assert_ok!(Referenda::cancel(Origin::signed(4), 0)); + assert_ok!(Referenda::refund_decision_deposit(Origin::signed(3), 0)); + assert_eq!(cancelled_since(0), 8); + }); +} + +#[test] +fn cancel_errors_works() { + new_test_ext().execute_with(|| { + let h = set_balance_proposal_hash(1); + assert_ok!(Referenda::submit( + Origin::signed(1), + RawOrigin::Root.into(), + h, + AtOrAfter::At(10), + )); + assert_ok!(Referenda::place_decision_deposit(Origin::signed(2), 0)); + assert_noop!(Referenda::cancel(Origin::signed(1), 0), BadOrigin); + + run_to(11); + assert_noop!(Referenda::cancel(Origin::signed(4), 0), Error::::NotOngoing); + }); +} + +#[test] +fn kill_works() { + new_test_ext().execute_with(|| { + let h = set_balance_proposal_hash(1); + assert_ok!(Referenda::submit( + Origin::signed(1), + RawOrigin::Root.into(), + h, + AtOrAfter::At(10), + )); + assert_ok!(Referenda::place_decision_deposit(Origin::signed(2), 0)); + + run_to(8); + assert_ok!(Referenda::kill(Origin::root(), 0)); + let e = Error::::NoDeposit; + assert_noop!(Referenda::refund_decision_deposit(Origin::signed(3), 0), e); + assert_eq!(killed_since(0), 8); + }); +} + +#[test] +fn kill_errors_works() { + new_test_ext().execute_with(|| { + let h = set_balance_proposal_hash(1); + assert_ok!(Referenda::submit( + Origin::signed(1), + RawOrigin::Root.into(), + h, + AtOrAfter::At(10), + )); + assert_ok!(Referenda::place_decision_deposit(Origin::signed(2), 0)); + assert_noop!(Referenda::kill(Origin::signed(4), 0), BadOrigin); + + run_to(11); + assert_noop!(Referenda::kill(Origin::root(), 0), Error::::NotOngoing); + }); +} + +#[test] +fn set_balance_proposal_is_correctly_filtered_out() { + for i in 0..10 { + let call = crate::mock::Call::decode(&mut &set_balance_proposal(i)[..]).unwrap(); + assert!(!::BaseCallFilter::contains(&call)); + } +} + +#[test] +fn curve_handles_all_inputs() { + let test_curve = Curve::LinearDecreasing { begin: Perbill::zero(), delta: Perbill::zero() }; + + let delay = test_curve.delay(Perbill::zero()); + assert_eq!(delay, Perbill::zero()); + + let test_curve = Curve::LinearDecreasing { begin: Perbill::zero(), delta: Perbill::one() }; + + let threshold = test_curve.threshold(Perbill::one()); + assert_eq!(threshold, Perbill::zero()); +} diff --git a/frame/referenda/src/types.rs b/frame/referenda/src/types.rs new file mode 100644 index 000000000000..1b028fdfe9f7 --- /dev/null +++ b/frame/referenda/src/types.rs @@ -0,0 +1,358 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2022 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. + +//! Miscellaneous additional datatypes. + +use super::*; +use codec::{Decode, Encode, EncodeLike, MaxEncodedLen}; +use frame_support::{traits::schedule::Anon, Parameter}; +use scale_info::TypeInfo; +use sp_runtime::RuntimeDebug; +use sp_std::fmt::Debug; + +pub type BalanceOf = + <::Currency as Currency<::AccountId>>::Balance; +pub type NegativeImbalanceOf = <::Currency as Currency< + ::AccountId, +>>::NegativeImbalance; +pub type CallOf = ::Call; +pub type VotesOf = ::Votes; +pub type TallyOf = ::Tally; +pub type PalletsOriginOf = <::Origin as OriginTrait>::PalletsOrigin; +pub type ReferendumInfoOf = ReferendumInfo< + TrackIdOf, + PalletsOriginOf, + ::BlockNumber, + ::Hash, + BalanceOf, + TallyOf, + ::AccountId, + ScheduleAddressOf, +>; +pub type ReferendumStatusOf = ReferendumStatus< + TrackIdOf, + PalletsOriginOf, + ::BlockNumber, + ::Hash, + BalanceOf, + TallyOf, + ::AccountId, + ScheduleAddressOf, +>; +pub type DecidingStatusOf = DecidingStatus<::BlockNumber>; +pub type TrackInfoOf = TrackInfo, ::BlockNumber>; +pub type TrackIdOf = <::Tracks as TracksInfo< + BalanceOf, + ::BlockNumber, +>>::Id; +pub type ScheduleAddressOf = <::Scheduler as Anon< + ::BlockNumber, + CallOf, + PalletsOriginOf, +>>::Address; + +/// A referendum index. +pub type ReferendumIndex = u32; + +pub trait InsertSorted { + /// Inserts an item into a sorted series. + /// + /// Returns `true` if it was inserted, `false` if it would belong beyond the bound of the + /// series. + fn insert_sorted_by_key K, K: PartialOrd + Ord>( + &mut self, + t: T, + f: F, + ) -> bool; +} +impl> InsertSorted for BoundedVec { + fn insert_sorted_by_key K, K: PartialOrd + Ord>( + &mut self, + t: T, + mut f: F, + ) -> bool { + let index = self.binary_search_by_key::(&f(&t), f).unwrap_or_else(|x| x); + self.force_insert_keep_right(index, t) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use frame_support::traits::ConstU32; + + #[test] + fn insert_sorted_works() { + let mut b: BoundedVec> = vec![20, 30, 40].try_into().unwrap(); + assert!(b.insert_sorted_by_key(10, |&x| x)); + assert_eq!(&b[..], &[10, 20, 30, 40][..]); + + assert!(b.insert_sorted_by_key(60, |&x| x)); + assert_eq!(&b[..], &[10, 20, 30, 40, 60][..]); + + assert!(b.insert_sorted_by_key(50, |&x| x)); + assert_eq!(&b[..], &[10, 20, 30, 40, 50, 60][..]); + + assert!(!b.insert_sorted_by_key(9, |&x| x)); + assert_eq!(&b[..], &[10, 20, 30, 40, 50, 60][..]); + + assert!(b.insert_sorted_by_key(11, |&x| x)); + assert_eq!(&b[..], &[11, 20, 30, 40, 50, 60][..]); + + assert!(b.insert_sorted_by_key(21, |&x| x)); + assert_eq!(&b[..], &[20, 21, 30, 40, 50, 60][..]); + + assert!(b.insert_sorted_by_key(61, |&x| x)); + assert_eq!(&b[..], &[21, 30, 40, 50, 60, 61][..]); + + assert!(b.insert_sorted_by_key(51, |&x| x)); + assert_eq!(&b[..], &[30, 40, 50, 51, 60, 61][..]); + } +} + +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub struct DecidingStatus { + /// When this referendum began being "decided". If confirming, then the + /// end will actually be delayed until the end of the confirmation period. + pub(crate) since: BlockNumber, + /// If `Some`, then the referendum has entered confirmation stage and will end at + /// the block number as long as it doesn't lose its approval in the meantime. + pub(crate) confirming: Option, +} + +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub struct Deposit { + pub(crate) who: AccountId, + pub(crate) amount: Balance, +} + +#[derive(Clone, Encode, TypeInfo)] +pub struct TrackInfo { + /// Name of this track. TODO was &'static str + pub name: &'static str, + /// A limit for the number of referenda on this track that can be being decided at once. + /// For Root origin this should generally be just one. + pub max_deciding: u32, + /// Amount that must be placed on deposit before a decision can be made. + pub decision_deposit: Balance, + /// Amount of time this must be submitted for before a decision can be made. + pub prepare_period: Moment, + /// Amount of time that a decision may take to be approved prior to cancellation. + pub decision_period: Moment, + /// Amount of time that the approval criteria must hold before it can be approved. + pub confirm_period: Moment, + /// Minimum amount of time that an approved proposal must be in the dispatch queue. + pub min_enactment_period: Moment, + /// Minimum aye votes as percentage of overall conviction-weighted votes needed for + /// approval as a function of time into decision period. + pub min_approval: Curve, + /// Minimum turnout as percentage of overall population that is needed for + /// approval as a function of time into decision period. + pub min_turnout: Curve, +} + +/// Information on the voting tracks. +pub trait TracksInfo { + /// The identifier for a track. + type Id: Copy + Parameter + Ord + PartialOrd + Send + Sync + 'static; + + /// The origin type from which a track is implied. + type Origin; + + /// Return the array of known tracks and their information. + fn tracks() -> &'static [(Self::Id, TrackInfo)]; + + /// Determine the voting track for the given `origin`. + fn track_for(origin: &Self::Origin) -> Result; + + /// Return the track info for track `id`, by default this just looks it up in `Self::tracks()`. + fn info(id: Self::Id) -> Option<&'static TrackInfo> { + Self::tracks().iter().find(|x| &x.0 == &id).map(|x| &x.1) + } +} + +/// Indication of either a specific moment or a delay from a implicitly defined moment. +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub enum AtOrAfter { + /// Indiciates that the event should occur at the moment given. + At(Moment), + /// Indiciates that the event should occur some period of time (defined by the parameter) after + /// a prior event. The prior event is defined by the context, but for the purposes of + /// referendum proposals, the "prior event" is the passing of the referendum. + After(Moment), +} + +impl AtOrAfter { + pub fn evaluate(&self, since: Moment) -> Moment { + match &self { + Self::At(m) => *m, + Self::After(m) => m.saturating_add(since), + } + } +} + +/// Info regarding an ongoing referendum. +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub struct ReferendumStatus< + TrackId: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone, + Origin: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone, + Moment: Parameter + Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone + EncodeLike, + Hash: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone, + Balance: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone, + Tally: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone, + AccountId: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone, + ScheduleAddress: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone, +> { + /// The track of this referendum. + pub(crate) track: TrackId, + /// The origin for this referendum. + pub(crate) origin: Origin, + /// The hash of the proposal up for referendum. + pub(crate) proposal_hash: Hash, + /// The time the proposal should be scheduled for enactment. + pub(crate) enactment: AtOrAfter, + /// The time of submission. Once `UndecidingTimeout` passes, it may be closed by anyone if it + /// `deciding` is `None`. + pub(crate) submitted: Moment, + /// The deposit reserved for the submission of this referendum. + pub(crate) submission_deposit: Deposit, + /// The deposit reserved for this referendum to be decided. + pub(crate) decision_deposit: Option>, + /// The status of a decision being made. If `None`, it has not entered the deciding period. + pub(crate) deciding: Option>, + /// The current tally of votes in this referendum. + pub(crate) tally: Tally, + /// Whether we have been placed in the queue for being decided or not. + pub(crate) in_queue: bool, + /// The next scheduled wake-up, if `Some`. + pub(crate) alarm: Option<(Moment, ScheduleAddress)>, +} + +/// Info regarding a referendum, present or past. +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub enum ReferendumInfo< + TrackId: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone, + Origin: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone, + Moment: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone + EncodeLike, + Hash: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone, + Balance: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone, + Tally: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone, + AccountId: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone, + ScheduleAddress: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone, +> { + /// Referendum has been submitted and is being voted on. + Ongoing( + ReferendumStatus, + ), + /// Referendum finished with approval. Submission deposit is held. + Approved(Moment, Deposit, Option>), + /// Referendum finished with rejection. Submission deposit is held. + Rejected(Moment, Deposit, Option>), + /// Referendum finished with cancelation. Submission deposit is held. + Cancelled(Moment, Deposit, Option>), + /// Referendum finished and was never decided. Submission deposit is held. + TimedOut(Moment, Deposit, Option>), + /// Referendum finished with a kill. + Killed(Moment), +} + +impl< + TrackId: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone, + Origin: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone, + Moment: Parameter + Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone + EncodeLike, + Hash: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone, + Balance: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone, + Tally: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone, + AccountId: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone, + ScheduleAddress: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone, + > ReferendumInfo +{ + /// Take the Decision Deposit from `self`, if there is one. Returns an `Err` if `self` is not + /// in a valid state for the Decision Deposit to be refunded. + pub fn take_decision_deposit(&mut self) -> Result>, ()> { + use ReferendumInfo::*; + match self { + Ongoing(x) if x.decision_deposit.is_none() => Ok(None), + // Cannot refund deposit if Ongoing as this breaks assumptions. + Ongoing(_) => Err(()), + Approved(_, _, d) | Rejected(_, _, d) | TimedOut(_, _, d) | Cancelled(_, _, d) => + Ok(d.take()), + Killed(_) => Ok(None), + } + } +} + +/// Type for describing a curve over the 2-dimensional space of axes between 0-1, as represented +/// by `(Perbill, Perbill)`. +#[derive(Clone, Eq, PartialEq, Encode, Decode, TypeInfo, MaxEncodedLen)] +#[cfg_attr(not(feature = "std"), derive(RuntimeDebug))] +pub enum Curve { + /// Linear curve starting at `(0, begin)`, ending at `(period, begin - delta)`. + LinearDecreasing { begin: Perbill, delta: Perbill }, +} + +impl Curve { + /// Determine the `y` value for the given `x` value. + pub(crate) fn threshold(&self, x: Perbill) -> Perbill { + match self { + Self::LinearDecreasing { begin, delta } => *begin - (*delta * x).min(*begin), + } + } + + /// Determine the smallest `x` value such that `passing` returns `true` when passed along with + /// the given `y` value. + /// + /// ```nocompile + /// let c = Curve::LinearDecreasing { begin: Perbill::one(), delta: Perbill::one() }; + /// // ^^^ Can be any curve. + /// let y = Perbill::from_percent(50); + /// // ^^^ Can be any value. + /// let x = c.delay(y); + /// assert!(c.passing(x, y)); + /// ``` + pub fn delay(&self, y: Perbill) -> Perbill { + match self { + Self::LinearDecreasing { begin, delta } => + if delta.is_zero() { + return *delta + } else { + return (*begin - y.min(*begin)).min(*delta) / *delta + }, + } + } + + /// Return `true` iff the `y` value is greater than the curve at the `x`. + pub fn passing(&self, x: Perbill, y: Perbill) -> bool { + y >= self.threshold(x) + } +} + +#[cfg(feature = "std")] +impl Debug for Curve { + fn fmt(&self, f: &mut sp_std::fmt::Formatter<'_>) -> sp_std::fmt::Result { + match self { + Self::LinearDecreasing { begin, delta } => { + write!( + f, + "Linear[(0%, {}%) -> (100%, {}%)]", + *begin * 100u32, + (*begin - *delta) * 100u32, + ) + }, + } + } +} diff --git a/frame/referenda/src/weights.rs b/frame/referenda/src/weights.rs new file mode 100644 index 000000000000..202901bdd10b --- /dev/null +++ b/frame/referenda/src/weights.rs @@ -0,0 +1,491 @@ +// This file is part of Substrate. + +// Copyright (C) 2021 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. + +//! Autogenerated weights for pallet_referenda +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2021-12-19, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 + +// Executed Command: +// target/release/substrate +// benchmark +// --chain=dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_referenda +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 +// --output=./frame/referenda/src/weights.rs +// --template=./.maintain/frame-weight-template.hbs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +/// Weight functions needed for pallet_referenda. +pub trait WeightInfo { + fn submit() -> Weight; + fn place_decision_deposit_preparing() -> Weight; + fn place_decision_deposit_queued() -> Weight; + fn place_decision_deposit_not_queued() -> Weight; + fn place_decision_deposit_passing() -> Weight; + fn place_decision_deposit_failing() -> Weight; + fn refund_decision_deposit() -> Weight; + fn cancel() -> Weight; + fn kill() -> Weight; + fn one_fewer_deciding_queue_empty() -> Weight; + fn one_fewer_deciding_failing() -> Weight; + fn one_fewer_deciding_passing() -> Weight; + fn nudge_referendum_requeued_insertion() -> Weight; + fn nudge_referendum_requeued_slide() -> Weight; + fn nudge_referendum_queued() -> Weight; + fn nudge_referendum_not_queued() -> Weight; + fn nudge_referendum_no_deposit() -> Weight; + fn nudge_referendum_preparing() -> Weight; + fn nudge_referendum_timed_out() -> Weight; + fn nudge_referendum_begin_deciding_failing() -> Weight; + fn nudge_referendum_begin_deciding_passing() -> Weight; + fn nudge_referendum_begin_confirming() -> Weight; + fn nudge_referendum_end_confirming() -> Weight; + fn nudge_referendum_continue_not_confirming() -> Weight; + fn nudge_referendum_continue_confirming() -> Weight; + fn nudge_referendum_approved() -> Weight; + fn nudge_referendum_rejected() -> Weight; +} + +/// Weights for pallet_referenda using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + // Storage: Referenda ReferendumCount (r:1 w:1) + // Storage: Scheduler Agenda (r:1 w:1) + // Storage: Referenda ReferendumInfoFor (r:0 w:1) + fn submit() -> Weight { + (42_395_000 as Weight) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Scheduler Agenda (r:2 w:2) + fn place_decision_deposit_preparing() -> Weight { + (48_113_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Referenda DecidingCount (r:1 w:0) + // Storage: Referenda TrackQueue (r:1 w:1) + fn place_decision_deposit_queued() -> Weight { + (53_624_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Referenda DecidingCount (r:1 w:0) + // Storage: Referenda TrackQueue (r:1 w:1) + fn place_decision_deposit_not_queued() -> Weight { + (52_560_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Referenda DecidingCount (r:1 w:1) + // Storage: Scheduler Agenda (r:2 w:2) + fn place_decision_deposit_passing() -> Weight { + (54_067_000 as Weight) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(4 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Referenda DecidingCount (r:1 w:1) + // Storage: Scheduler Agenda (r:2 w:2) + fn place_decision_deposit_failing() -> Weight { + (52_457_000 as Weight) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(4 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + fn refund_decision_deposit() -> Weight { + (28_504_000 as Weight) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Scheduler Agenda (r:2 w:2) + fn cancel() -> Weight { + (40_425_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Scheduler Agenda (r:2 w:2) + fn kill() -> Weight { + (65_974_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } + // Storage: Referenda TrackQueue (r:1 w:0) + // Storage: Referenda DecidingCount (r:1 w:1) + fn one_fewer_deciding_queue_empty() -> Weight { + (8_904_000 as Weight) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + // Storage: Referenda TrackQueue (r:1 w:1) + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Scheduler Agenda (r:2 w:2) + fn one_fewer_deciding_failing() -> Weight { + (181_387_000 as Weight) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(4 as Weight)) + } + // Storage: Referenda TrackQueue (r:1 w:1) + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Scheduler Agenda (r:2 w:2) + fn one_fewer_deciding_passing() -> Weight { + (179_753_000 as Weight) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(4 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Referenda TrackQueue (r:1 w:1) + // Storage: Scheduler Agenda (r:1 w:1) + fn nudge_referendum_requeued_insertion() -> Weight { + (53_592_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Referenda TrackQueue (r:1 w:1) + // Storage: Scheduler Agenda (r:1 w:1) + fn nudge_referendum_requeued_slide() -> Weight { + (53_173_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Referenda DecidingCount (r:1 w:0) + // Storage: Referenda TrackQueue (r:1 w:1) + // Storage: Scheduler Agenda (r:1 w:1) + fn nudge_referendum_queued() -> Weight { + (55_770_000 as Weight) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Referenda DecidingCount (r:1 w:0) + // Storage: Referenda TrackQueue (r:1 w:1) + // Storage: Scheduler Agenda (r:1 w:1) + fn nudge_referendum_not_queued() -> Weight { + (53_922_000 as Weight) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Scheduler Agenda (r:1 w:1) + fn nudge_referendum_no_deposit() -> Weight { + (26_906_000 as Weight) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Scheduler Agenda (r:1 w:1) + fn nudge_referendum_preparing() -> Weight { + (27_943_000 as Weight) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + fn nudge_referendum_timed_out() -> Weight { + (20_256_000 as Weight) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Referenda DecidingCount (r:1 w:1) + // Storage: Scheduler Agenda (r:1 w:1) + fn nudge_referendum_begin_deciding_failing() -> Weight { + (30_964_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Referenda DecidingCount (r:1 w:1) + // Storage: Scheduler Agenda (r:1 w:1) + fn nudge_referendum_begin_deciding_passing() -> Weight { + (31_763_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Scheduler Agenda (r:1 w:1) + fn nudge_referendum_begin_confirming() -> Weight { + (28_892_000 as Weight) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Scheduler Agenda (r:1 w:1) + fn nudge_referendum_end_confirming() -> Weight { + (29_666_000 as Weight) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Scheduler Agenda (r:1 w:1) + fn nudge_referendum_continue_not_confirming() -> Weight { + (29_740_000 as Weight) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Scheduler Agenda (r:1 w:1) + fn nudge_referendum_continue_confirming() -> Weight { + (29_661_000 as Weight) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Scheduler Agenda (r:2 w:2) + // Storage: Scheduler Lookup (r:1 w:1) + // Storage: Preimage StatusFor (r:1 w:1) + fn nudge_referendum_approved() -> Weight { + (55_736_000 as Weight) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(5 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Scheduler Agenda (r:1 w:1) + fn nudge_referendum_rejected() -> Weight { + (32_726_000 as Weight) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + } +} + +// For backwards compatibility and tests +impl WeightInfo for () { + // Storage: Referenda ReferendumCount (r:1 w:1) + // Storage: Scheduler Agenda (r:1 w:1) + // Storage: Referenda ReferendumInfoFor (r:0 w:1) + fn submit() -> Weight { + (42_395_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Scheduler Agenda (r:2 w:2) + fn place_decision_deposit_preparing() -> Weight { + (48_113_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Referenda DecidingCount (r:1 w:0) + // Storage: Referenda TrackQueue (r:1 w:1) + fn place_decision_deposit_queued() -> Weight { + (53_624_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Referenda DecidingCount (r:1 w:0) + // Storage: Referenda TrackQueue (r:1 w:1) + fn place_decision_deposit_not_queued() -> Weight { + (52_560_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Referenda DecidingCount (r:1 w:1) + // Storage: Scheduler Agenda (r:2 w:2) + fn place_decision_deposit_passing() -> Weight { + (54_067_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(4 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Referenda DecidingCount (r:1 w:1) + // Storage: Scheduler Agenda (r:2 w:2) + fn place_decision_deposit_failing() -> Weight { + (52_457_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(4 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + fn refund_decision_deposit() -> Weight { + (28_504_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Scheduler Agenda (r:2 w:2) + fn cancel() -> Weight { + (40_425_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Scheduler Agenda (r:2 w:2) + fn kill() -> Weight { + (65_974_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + } + // Storage: Referenda TrackQueue (r:1 w:0) + // Storage: Referenda DecidingCount (r:1 w:1) + fn one_fewer_deciding_queue_empty() -> Weight { + (8_904_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + // Storage: Referenda TrackQueue (r:1 w:1) + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Scheduler Agenda (r:2 w:2) + fn one_fewer_deciding_failing() -> Weight { + (181_387_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(4 as Weight)) + } + // Storage: Referenda TrackQueue (r:1 w:1) + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Scheduler Agenda (r:2 w:2) + fn one_fewer_deciding_passing() -> Weight { + (179_753_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(4 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Referenda TrackQueue (r:1 w:1) + // Storage: Scheduler Agenda (r:1 w:1) + fn nudge_referendum_requeued_insertion() -> Weight { + (53_592_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Referenda TrackQueue (r:1 w:1) + // Storage: Scheduler Agenda (r:1 w:1) + fn nudge_referendum_requeued_slide() -> Weight { + (53_173_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Referenda DecidingCount (r:1 w:0) + // Storage: Referenda TrackQueue (r:1 w:1) + // Storage: Scheduler Agenda (r:1 w:1) + fn nudge_referendum_queued() -> Weight { + (55_770_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Referenda DecidingCount (r:1 w:0) + // Storage: Referenda TrackQueue (r:1 w:1) + // Storage: Scheduler Agenda (r:1 w:1) + fn nudge_referendum_not_queued() -> Weight { + (53_922_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Scheduler Agenda (r:1 w:1) + fn nudge_referendum_no_deposit() -> Weight { + (26_906_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Scheduler Agenda (r:1 w:1) + fn nudge_referendum_preparing() -> Weight { + (27_943_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + fn nudge_referendum_timed_out() -> Weight { + (20_256_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Referenda DecidingCount (r:1 w:1) + // Storage: Scheduler Agenda (r:1 w:1) + fn nudge_referendum_begin_deciding_failing() -> Weight { + (30_964_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Referenda DecidingCount (r:1 w:1) + // Storage: Scheduler Agenda (r:1 w:1) + fn nudge_referendum_begin_deciding_passing() -> Weight { + (31_763_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Scheduler Agenda (r:1 w:1) + fn nudge_referendum_begin_confirming() -> Weight { + (28_892_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Scheduler Agenda (r:1 w:1) + fn nudge_referendum_end_confirming() -> Weight { + (29_666_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Scheduler Agenda (r:1 w:1) + fn nudge_referendum_continue_not_confirming() -> Weight { + (29_740_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Scheduler Agenda (r:1 w:1) + fn nudge_referendum_continue_confirming() -> Weight { + (29_661_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Scheduler Agenda (r:2 w:2) + // Storage: Scheduler Lookup (r:1 w:1) + // Storage: Preimage StatusFor (r:1 w:1) + fn nudge_referendum_approved() -> Weight { + (55_736_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + .saturating_add(RocksDbWeight::get().writes(5 as Weight)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Scheduler Agenda (r:1 w:1) + fn nudge_referendum_rejected() -> Weight { + (32_726_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + } +} diff --git a/frame/scheduler/src/lib.rs b/frame/scheduler/src/lib.rs index f9077d4c8c8f..ec60cedc280b 100644 --- a/frame/scheduler/src/lib.rs +++ b/frame/scheduler/src/lib.rs @@ -694,13 +694,6 @@ impl Pallet { }); Agenda::::append(when, s); let index = Agenda::::decode_len(when).unwrap_or(1) as u32 - 1; - if index > T::MaxScheduledPerBlock::get() { - log::warn!( - target: "runtime::scheduler", - "Warning: There are more items queued in the Scheduler than \ - expected from the runtime configuration. An update might be needed.", - ); - } Self::deposit_event(Event::Scheduled { when, index }); Ok((when, index)) @@ -795,13 +788,6 @@ impl Pallet { }; Agenda::::append(when, Some(s)); let index = Agenda::::decode_len(when).unwrap_or(1) as u32 - 1; - if index > T::MaxScheduledPerBlock::get() { - log::warn!( - target: "runtime::scheduler", - "Warning: There are more items queued in the Scheduler than \ - expected from the runtime configuration. An update might be needed.", - ); - } let address = (when, index); Lookup::::insert(&id, &address); Self::deposit_event(Event::Scheduled { when, index }); diff --git a/frame/support/src/dispatch.rs b/frame/support/src/dispatch.rs index b5f4ab97767c..ece5173f2f4c 100644 --- a/frame/support/src/dispatch.rs +++ b/frame/support/src/dispatch.rs @@ -20,6 +20,7 @@ pub use crate::{ codec::{Codec, Decode, Encode, EncodeAsRef, EncodeLike, HasCompact, Input, Output}, + scale_info::TypeInfo, sp_std::{ fmt, marker, prelude::{Clone, Eq, PartialEq, Vec}, @@ -33,7 +34,7 @@ pub use crate::{ TransactionPriority, WeighData, Weight, WithPostDispatchInfo, }, }; -pub use sp_runtime::{traits::Dispatchable, DispatchError}; +pub use sp_runtime::{traits::Dispatchable, DispatchError, RuntimeDebug}; /// The return type of a `Dispatchable` in frame. When returned explicitly from /// a dispatchable function it allows overriding the default `PostDispatchInfo` @@ -60,6 +61,28 @@ pub trait Callable { // https://github.com/rust-lang/rust/issues/51331 pub type CallableCallFor = >::Call; +/// Origin for the System pallet. +#[derive(PartialEq, Eq, Clone, RuntimeDebug, Encode, Decode, TypeInfo)] +pub enum RawOrigin { + /// The system itself ordained this dispatch to happen: this is the highest privilege level. + Root, + /// It is signed by some public key and we provide the `AccountId`. + Signed(AccountId), + /// It is signed by nobody, can be either: + /// * included and agreed upon by the validators anyway, + /// * or unsigned transaction validated by a pallet. + None, +} + +impl From> for RawOrigin { + fn from(s: Option) -> RawOrigin { + match s { + Some(who) => RawOrigin::Signed(who), + None => RawOrigin::None, + } + } +} + /// A type that can be used as a parameter in a dispatchable function. /// /// When using `decl_module` all arguments for call functions must implement this trait. @@ -2582,21 +2605,7 @@ mod tests { type DbWeight: Get; } - #[derive(Clone, PartialEq, Eq, Debug, Encode, Decode, scale_info::TypeInfo)] - pub enum RawOrigin { - Root, - Signed(AccountId), - None, - } - - impl From> for RawOrigin { - fn from(s: Option) -> RawOrigin { - match s { - Some(who) => RawOrigin::Signed(who), - None => RawOrigin::None, - } - } - } + pub use super::super::RawOrigin; pub type Origin = RawOrigin<::AccountId>; } @@ -2638,7 +2647,7 @@ mod tests { } } - #[derive(scale_info::TypeInfo)] + #[derive(Eq, PartialEq, Clone, crate::RuntimeDebug, scale_info::TypeInfo)] pub struct TraitImpl {} impl Config for TraitImpl {} @@ -2679,8 +2688,15 @@ mod tests { } } + #[derive(TypeInfo, crate::RuntimeDebug, Eq, PartialEq, Clone, Encode, Decode)] pub struct OuterOrigin; + impl From::AccountId>> for OuterOrigin { + fn from(_: RawOrigin<::AccountId>) -> Self { + unimplemented!("Not required in tests!") + } + } + impl crate::traits::OriginTrait for OuterOrigin { type Call = ::Call; type PalletsOrigin = OuterOrigin; diff --git a/frame/support/src/traits.rs b/frame/support/src/traits.rs index 1928023cfe66..5ee2952e445b 100644 --- a/frame/support/src/traits.rs +++ b/frame/support/src/traits.rs @@ -23,7 +23,7 @@ pub mod tokens; pub use tokens::{ currency::{ Currency, LockIdentifier, LockableCurrency, NamedReservableCurrency, ReservableCurrency, - VestingSchedule, + TotalIssuanceOf, VestingSchedule, }, fungible, fungibles, imbalance::{Imbalance, OnUnbalanced, SignedImbalance}, @@ -90,4 +90,6 @@ mod dispatch; pub use dispatch::{EnsureOneOf, EnsureOrigin, OriginTrait, UnfilteredDispatchable}; mod voting; -pub use voting::{CurrencyToVote, SaturatingCurrencyToVote, U128CurrencyToVote}; +pub use voting::{ + CurrencyToVote, PollStatus, Polling, SaturatingCurrencyToVote, U128CurrencyToVote, VoteTally, +}; diff --git a/frame/support/src/traits/dispatch.rs b/frame/support/src/traits/dispatch.rs index afac31e662e3..1a4e9f6f7cc2 100644 --- a/frame/support/src/traits/dispatch.rs +++ b/frame/support/src/traits/dispatch.rs @@ -17,8 +17,11 @@ //! Traits for dealing with dispatching calls and the origin from which they are dispatched. -use crate::dispatch::DispatchResultWithPostInfo; -use sp_runtime::{traits::BadOrigin, Either}; +use crate::dispatch::{DispatchResultWithPostInfo, Parameter, RawOrigin}; +use sp_runtime::{ + traits::{BadOrigin, Member}, + Either, +}; /// Some sort of check on the origin is performed by this object. pub trait EnsureOrigin { @@ -56,7 +59,7 @@ pub trait OriginTrait: Sized { type Call; /// The caller origin, overarching type of all pallets origins. - type PalletsOrigin; + type PalletsOrigin: Parameter + Member + Into + From>; /// The AccountId used across the system. type AccountId; diff --git a/frame/support/src/traits/schedule.rs b/frame/support/src/traits/schedule.rs index 5ba233c29be1..3b8e6da3e2ef 100644 --- a/frame/support/src/traits/schedule.rs +++ b/frame/support/src/traits/schedule.rs @@ -125,7 +125,7 @@ pub mod v1 { /// A type that can be used as a scheduler. pub trait Anon { /// An address which can be used for removing a scheduled task. - type Address: Codec + Clone + Eq + EncodeLike + Debug; + type Address: Codec + Clone + Eq + EncodeLike + Debug + TypeInfo; /// Schedule a dispatch to happen at the beginning of some block in the future. /// @@ -280,7 +280,7 @@ pub mod v2 { /// A type that can be used as a scheduler. pub trait Anon { /// An address which can be used for removing a scheduled task. - type Address: Codec + Clone + Eq + EncodeLike + Debug; + type Address: Codec + Clone + Eq + EncodeLike + Debug + TypeInfo; /// A means of expressing a call by the hash of its encoded data. type Hash; diff --git a/frame/support/src/traits/tokens/currency.rs b/frame/support/src/traits/tokens/currency.rs index d5756ee84c47..d4b5c0c184f8 100644 --- a/frame/support/src/traits/tokens/currency.rs +++ b/frame/support/src/traits/tokens/currency.rs @@ -21,7 +21,10 @@ use super::{ imbalance::{Imbalance, SignedImbalance}, misc::{Balance, ExistenceRequirement, WithdrawReasons}, }; -use crate::dispatch::{DispatchError, DispatchResult}; +use crate::{ + dispatch::{DispatchError, DispatchResult}, + traits::Get, +}; use codec::MaxEncodedLen; use sp_runtime::traits::MaybeSerializeDeserialize; use sp_std::fmt::Debug; @@ -200,6 +203,15 @@ pub trait Currency { ) -> SignedImbalance; } +/// A non-const `Get` implementation parameterised by a `Currency` impl which provides the result +/// of `total_issuance`. +pub struct TotalIssuanceOf, A>(sp_std::marker::PhantomData<(C, A)>); +impl, A> Get for TotalIssuanceOf { + fn get() -> C::Balance { + C::total_issuance() + } +} + #[cfg(feature = "std")] impl Currency for () { type Balance = u32; diff --git a/frame/support/src/traits/voting.rs b/frame/support/src/traits/voting.rs index 719ad7f0f71d..978c5ce4f6a0 100644 --- a/frame/support/src/traits/voting.rs +++ b/frame/support/src/traits/voting.rs @@ -18,7 +18,14 @@ //! Traits and associated data structures concerned with voting, and moving between tokens and //! votes. -use sp_arithmetic::traits::{SaturatedConversion, UniqueSaturatedFrom, UniqueSaturatedInto}; +use crate::dispatch::{DispatchError, Parameter}; +use codec::HasCompact; +use sp_arithmetic::{ + traits::{SaturatedConversion, UniqueSaturatedFrom, UniqueSaturatedInto}, + Perbill, +}; +use sp_runtime::traits::Member; +use sp_std::prelude::*; /// A trait similar to `Convert` to convert values from `B` an abstract balance type /// into u64 and back from u128. (This conversion is used in election and other places where complex @@ -87,3 +94,74 @@ impl + UniqueSaturatedFrom> CurrencyToVote B::unique_saturated_from(value) } } + +pub trait VoteTally { + fn ayes(&self) -> Votes; + fn turnout(&self) -> Perbill; + fn approval(&self) -> Perbill; + #[cfg(feature = "runtime-benchmarks")] + fn unanimity() -> Self; + #[cfg(feature = "runtime-benchmarks")] + fn from_requirements(turnout: Perbill, approval: Perbill) -> Self; +} + +pub enum PollStatus { + None, + Ongoing(Tally, Class), + Completed(Moment, bool), +} + +impl PollStatus { + pub fn ensure_ongoing(self) -> Option<(Tally, Class)> { + match self { + Self::Ongoing(t, c) => Some((t, c)), + _ => None, + } + } +} + +pub trait Polling { + type Index: Parameter + Member + Ord + PartialOrd + Copy + HasCompact; + type Votes: Parameter + Member + Ord + PartialOrd + Copy + HasCompact; + type Class: Parameter + Member + Ord + PartialOrd; + type Moment; + + /// Provides a vec of values that `T` may take. + fn classes() -> Vec; + + /// `Some` if the referendum `index` can be voted on, along with the tally and class of + /// referendum. + /// + /// Don't use this if you might mutate - use `try_access_poll` instead. + fn as_ongoing(index: Self::Index) -> Option<(Tally, Self::Class)>; + + fn access_poll( + index: Self::Index, + f: impl FnOnce(PollStatus<&mut Tally, Self::Moment, Self::Class>) -> R, + ) -> R; + + fn try_access_poll( + index: Self::Index, + f: impl FnOnce(PollStatus<&mut Tally, Self::Moment, Self::Class>) -> Result, + ) -> Result; + + /// Create an ongoing majority-carries poll of given class lasting given period for the purpose + /// of benchmarking. + /// + /// May return `Err` if it is impossible. + #[cfg(feature = "runtime-benchmarks")] + fn create_ongoing(class: Self::Class) -> Result; + + /// End the given ongoing poll and return the result. + /// + /// Returns `Err` if `index` is not an ongoing poll. + #[cfg(feature = "runtime-benchmarks")] + fn end_ongoing(index: Self::Index, approved: bool) -> Result<(), ()>; + + /// The maximum amount of ongoing polls within any single class. By default it practically + /// unlimited (`u32::max_value()`). + #[cfg(feature = "runtime-benchmarks")] + fn max_ongoing() -> (Self::Class, u32) { + (Self::classes().into_iter().next().expect("Always one class"), u32::max_value()) + } +} diff --git a/frame/support/test/tests/system.rs b/frame/support/test/tests/system.rs index 0083835640cb..b30fd8d5ec56 100644 --- a/frame/support/test/tests/system.rs +++ b/frame/support/test/tests/system.rs @@ -69,23 +69,7 @@ frame_support::decl_error! { } } -/// Origin for the system module. -#[derive(PartialEq, Eq, Clone, sp_runtime::RuntimeDebug, Encode, Decode, scale_info::TypeInfo)] -pub enum RawOrigin { - Root, - Signed(AccountId), - None, -} - -impl From> for RawOrigin { - fn from(s: Option) -> RawOrigin { - match s { - Some(who) => RawOrigin::Signed(who), - None => RawOrigin::None, - } - } -} - +pub use frame_support::dispatch::RawOrigin; pub type Origin = RawOrigin<::AccountId>; #[allow(dead_code)] diff --git a/frame/system/src/lib.rs b/frame/system/src/lib.rs index 878edd7840e7..3b4de0c472c4 100644 --- a/frame/system/src/lib.rs +++ b/frame/system/src/lib.rs @@ -124,6 +124,7 @@ pub use extensions::{ }; // Backward compatible re-export. pub use extensions::check_mortality::CheckMortality as CheckEra; +pub use frame_support::dispatch::RawOrigin; pub use weights::WeightInfo; /// Compute the trie root of a list of extrinsics. @@ -708,28 +709,6 @@ pub struct EventRecord { pub topics: Vec, } -/// Origin for the System pallet. -#[derive(PartialEq, Eq, Clone, RuntimeDebug, Encode, Decode, TypeInfo)] -pub enum RawOrigin { - /// The system itself ordained this dispatch to happen: this is the highest privilege level. - Root, - /// It is signed by some public key and we provide the `AccountId`. - Signed(AccountId), - /// It is signed by nobody, can be either: - /// * included and agreed upon by the validators anyway, - /// * or unsigned transaction validated by a pallet. - None, -} - -impl From> for RawOrigin { - fn from(s: Option) -> RawOrigin { - match s { - Some(who) => RawOrigin::Signed(who), - None => RawOrigin::None, - } - } -} - // Create a Hash with 69 for each byte, // only used to build genesis config. #[cfg(feature = "std")] @@ -1641,7 +1620,7 @@ impl Lookup for ChainContext { /// Prelude to be used alongside pallet macro, for ease of use. pub mod pallet_prelude { - pub use crate::{ensure_none, ensure_root, ensure_signed}; + pub use crate::{ensure_none, ensure_root, ensure_signed, ensure_signed_or_root}; /// Type alias for the `Origin` associated type of system config. pub type OriginFor = ::Origin; diff --git a/test-utils/runtime/src/lib.rs b/test-utils/runtime/src/lib.rs index 5c9dfeca0a33..861d95efb308 100644 --- a/test-utils/runtime/src/lib.rs +++ b/test-utils/runtime/src/lib.rs @@ -426,7 +426,7 @@ impl GetRuntimeBlockType for Runtime { type RuntimeBlock = Block; } -#[derive(Clone, RuntimeDebug)] +#[derive(Clone, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo)] pub struct Origin; impl From> for Origin { From dc4cf6c2c73ef5af9197b3e73fb590b1a045d93e Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Mon, 7 Feb 2022 10:14:52 +0100 Subject: [PATCH 458/695] More efficient WASM instance memory decommit on macos (#10801) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * More efficient WASM instance memory decommit on macos * Apply suggestions from code review Co-authored-by: Alexander Theißen * Updated error message Co-authored-by: Alexander Theißen --- .../executor/wasmtime/src/instance_wrapper.rs | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/client/executor/wasmtime/src/instance_wrapper.rs b/client/executor/wasmtime/src/instance_wrapper.rs index af21a8080cd5..e27de7817b2b 100644 --- a/client/executor/wasmtime/src/instance_wrapper.rs +++ b/client/executor/wasmtime/src/instance_wrapper.rs @@ -361,6 +361,33 @@ impl InstanceWrapper { return; } } + } else if #[cfg(target_os = "macos")] { + use std::sync::Once; + + unsafe { + let ptr = self.memory.data_ptr(&self.store); + let len = self.memory.data_size(&self.store); + + // On MacOS we can simply overwrite memory mapping. + if libc::mmap( + ptr as _, + len, + libc::PROT_READ | libc::PROT_WRITE, + libc::MAP_FIXED | libc::MAP_PRIVATE | libc::MAP_ANONYMOUS, + -1, + 0, + ) == libc::MAP_FAILED { + static LOGGED: Once = Once::new(); + LOGGED.call_once(|| { + log::warn!( + "Failed to decommit WASM instance memory through mmap: {}", + std::io::Error::last_os_error(), + ); + }); + } else { + return; + } + } } } @@ -377,3 +404,15 @@ impl InstanceWrapper { &mut self.store } } + +#[test] +fn decommit_works() { + let engine = wasmtime::Engine::default(); + let code = wat::parse_str("(module (memory (export \"memory\") 1 4))").unwrap(); + let module = Module::new(&engine, code).unwrap(); + let mut wrapper = InstanceWrapper::new::<()>(&module, 2, true, None).unwrap(); + unsafe { *wrapper.memory.data_ptr(&wrapper.store) = 42 }; + assert_eq!(unsafe { *wrapper.memory.data_ptr(&wrapper.store) }, 42); + wrapper.decommit(); + assert_eq!(unsafe { *wrapper.memory.data_ptr(&wrapper.store) }, 0); +} From 0e9b6e4250a32e021c281d85e5790b7180bdb752 Mon Sep 17 00:00:00 2001 From: nanocryk <6422796+nanocryk@users.noreply.github.com> Date: Mon, 7 Feb 2022 13:33:24 +0100 Subject: [PATCH 459/695] make inner field of IdentityFields pub (#10773) --- frame/identity/src/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frame/identity/src/types.rs b/frame/identity/src/types.rs index ed3caafd3a11..d91adc8cdd76 100644 --- a/frame/identity/src/types.rs +++ b/frame/identity/src/types.rs @@ -245,7 +245,7 @@ pub enum IdentityField { /// Wrapper type for `BitFlags` that implements `Codec`. #[derive(Clone, Copy, PartialEq, Default, RuntimeDebug)] -pub struct IdentityFields(pub(crate) BitFlags); +pub struct IdentityFields(pub BitFlags); impl MaxEncodedLen for IdentityFields { fn max_encoded_len() -> usize { From 57bf92e42c2ca7f3444567b5ce50d2744fe90b4d Mon Sep 17 00:00:00 2001 From: Heorhii Lutsenko Date: Mon, 7 Feb 2022 14:47:56 +0200 Subject: [PATCH 460/695] Corrected description of clear_attribute extrinsic (#10729) --- frame/uniques/src/lib.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/frame/uniques/src/lib.rs b/frame/uniques/src/lib.rs index 6b05aaeec296..3a0b34e5bf40 100644 --- a/frame/uniques/src/lib.rs +++ b/frame/uniques/src/lib.rs @@ -1003,21 +1003,18 @@ pub mod pallet { Ok(()) } - /// Set an attribute for an asset class or instance. + /// Clear an attribute for an asset class or instance. /// /// Origin must be either `ForceOrigin` or Signed and the sender should be the Owner of the /// asset `class`. /// - /// If the origin is Signed, then funds of signer are reserved according to the formula: - /// `MetadataDepositBase + DepositPerByte * (key.len + value.len)` taking into - /// account any already reserved funds. + /// Any deposit is freed for the asset class owner. /// - /// - `class`: The identifier of the asset class whose instance's metadata to set. - /// - `instance`: The identifier of the asset instance whose metadata to set. + /// - `class`: The identifier of the asset class whose instance's metadata to clear. + /// - `maybe_instance`: The identifier of the asset instance whose metadata to clear. /// - `key`: The key of the attribute. - /// - `value`: The value to which to set the attribute. /// - /// Emits `AttributeSet`. + /// Emits `AttributeCleared`. /// /// Weight: `O(1)` #[pallet::weight(T::WeightInfo::clear_attribute())] From 2b14c837133e17a738a5a0d935d7f3040061e60a Mon Sep 17 00:00:00 2001 From: driemworks Date: Mon, 7 Feb 2022 20:44:08 -0500 Subject: [PATCH 461/695] block validators after X sessions, update mock runtime for test --- Cargo.lock | 1 - .../pallets/iris-session/src/lib.rs | 288 ++++++++++-------- .../pallets/iris-session/src/mock.rs | 44 ++- .../pallets/iris-session/src/tests.rs | 38 ++- bin/node-template/runtime/src/lib.rs | 2 + client/service/src/task_manager/tests.rs | 2 +- 6 files changed, 221 insertions(+), 154 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c1ce16cde26c..d963ee0a0580 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5045,7 +5045,6 @@ dependencies = [ "pallet-iris-assets", "pallet-iris-rpc-runtime-api", "pallet-iris-session", - "pallet-offences", "pallet-randomness-collective-flip", "pallet-session", "pallet-sudo", diff --git a/bin/node-template/pallets/iris-session/src/lib.rs b/bin/node-template/pallets/iris-session/src/lib.rs index 4f8a750260f3..333ed118fb1e 100644 --- a/bin/node-template/pallets/iris-session/src/lib.rs +++ b/bin/node-template/pallets/iris-session/src/lib.rs @@ -115,12 +115,8 @@ pub type RewardPoint = u32; pub struct EraRewardPoints { /// the total number of points total: RewardPoint, - /// the reward points for individual validators (sum(i.rewardPoint in individual) = total) + /// the reward points for individual validators, sum(i.rewardPoint in individual) = total individual: BTreeMap, - /// the unallocated reward points are distributed evenly among storage providers - /// at the end of a session. These reward points are added when a consumer node - /// requests data from IPFS - unallocated: RewardPoint, } /// Information regarding the active era (era in used in session). @@ -163,6 +159,8 @@ pub mod pallet { /// Minimum number of validators to leave in the validator set during /// auto removal. type MinAuthorities: Get; + /// the maximum number of session that a node can earn less than MinEraRewardPoints before suspension + type MaxDeadSession: Get; /// the authority id used for sending signed txs type AuthorityId: AppCrypto; } @@ -175,56 +173,35 @@ pub mod pallet { #[pallet::storage] #[pallet::getter(fn bootstrap_nodes)] pub(super) type BootstrapNodes = StorageMap< - _, - Blake2_128Concat, - Vec, - Vec, - ValueQuery, + _, Blake2_128Concat, Vec, Vec, ValueQuery, >; /// map substrate public key to ipfs public key #[pallet::storage] #[pallet::getter(fn substrate_ipfs_bridge)] pub(super) type SubstrateIpfsBridge = StorageMap< - _, - Blake2_128Concat, - T::AccountId, - Vec, - ValueQuery, + _, Blake2_128Concat, T::AccountId, Vec, ValueQuery, >; /// Maps an asset id to a collection of nodes that want to provider storage #[pallet::storage] #[pallet::getter(fn candidate_storage_providers)] - // TODO: Change to QueuedStorageProviders - pub(super) type CandidateStorageProviders = StorageMap< - _, - Blake2_128Concat, - T::AssetId, - Vec, - ValueQuery, + pub(super) type QueuedStorageProviders = StorageMap< + _, Blake2_128Concat, T::AssetId, Vec, ValueQuery, >; /// maps an asset id to a collection of nodes that are providing storage #[pallet::storage] #[pallet::getter(fn storage_providers)] pub(super) type StorageProviders = StorageMap< - _, - Blake2_128Concat, - T::AssetId, - Vec, - ValueQuery, + _, Blake2_128Concat, T::AssetId, Vec, ValueQuery, >; /// maps an asset id to a collection of nodes that have inserted the pin for the underlying cid #[pallet::storage] #[pallet::getter(fn pinners)] pub(super) type Pinners = StorageMap< - _, - Blake2_128Concat, - T::AssetId, - Vec, - ValueQuery, + _, Blake2_128Concat, T::AssetId, Vec, ValueQuery, >; /// The current era index. @@ -233,7 +210,9 @@ pub mod pallet { /// set, it might be active or not. #[pallet::storage] #[pallet::getter(fn current_era)] - pub type CurrentEra = StorageValue<_, EraIndex>; + pub type CurrentEra = StorageValue< + _, EraIndex + >; /// The active era information, it holds index and start. /// @@ -242,33 +221,57 @@ pub mod pallet { #[pallet::storage] #[pallet::getter(fn active_era)] // TODO: Do I need the ActiveEraInfo? - pub type ActiveEra = StorageValue<_, EraIndex>; + pub type ActiveEra = StorageValue< + _, EraIndex + >; /// Rewards for the last `HISTORY_DEPTH` eras. /// If reward hasn't been set or has been removed then 0 reward is returned. #[pallet::storage] #[pallet::getter(fn eras_reward_points)] pub type ErasRewardPoints = StorageDoubleMap< - _, - Blake2_128Concat, - EraIndex, - Blake2_128Concat, - T::AssetId, - EraRewardPoints, - ValueQuery, + _, Blake2_128Concat, EraIndex, Blake2_128Concat, T::AssetId, EraRewardPoints, ValueQuery, >; + /// + /// #[pallet::storage] #[pallet::getter(fn validators)] - pub type Validators = StorageValue<_, Vec, ValueQuery>; + pub type Validators = StorageValue< + _, Vec, ValueQuery>; + /// + /// #[pallet::storage] #[pallet::getter(fn approved_validators)] - pub type ApprovedValidators = StorageValue<_, Vec, ValueQuery>; + pub type ApprovedValidators = StorageValue< + _, Vec, ValueQuery>; + /// + /// #[pallet::storage] #[pallet::getter(fn validators_to_remove)] - pub type OfflineValidators = StorageValue<_, Vec, ValueQuery>; + pub type OfflineValidators = StorageValue< + _, Vec, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn total_session_rewards)] + pub type SessionParticipation = StorageMap< + _, Blake2_128Concat, EraIndex, Vec, ValueQuery, + >; + + #[pallet::storage] + #[pallet::getter(fn unproductive_sessions)] + pub type UnproductiveSessions = StorageMap< + _, Blake2_128Concat, T::AccountId, u32, ValueQuery, + >; + + /// + /// + // #[pallet::storage] + // #[pallet::getter(fn dead_validator)] + // pub type DeadValidators = StorageMap< + // _, Blake2_128Concat, u32, Vec, ValueQuery>; #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] @@ -415,10 +418,10 @@ pub mod pallet { // submit a request to join a storage pool in the next session let who = ensure_signed(origin)?; let new_origin = system::RawOrigin::Signed(who.clone()).into(); - let candidate_storage_providers = >::get(pool_id.clone()); + let candidate_storage_providers = >::get(pool_id.clone()); ensure!(!candidate_storage_providers.contains(&who), Error::::AlreadyACandidate); // TODO: we need a better scheme for *generating* pool ids -> should always be unique (cid + owner maybe?) - >::mutate(pool_id.clone(), |sp| { + >::mutate(pool_id.clone(), |sp| { sp.push(who.clone()); }); let owner = T::Lookup::lookup(pool_owner)?; @@ -459,7 +462,11 @@ pub mod pallet { )?; // award point to self if let Some(active_era) = ActiveEra::::get() { - >::mutate(active_era, id, |era_rewards| { + >::mutate(active_era.clone(), id, |era_rewards| { + // increment total session rewards (used to find non-contributing validators) + SessionParticipation::::mutate(active_era.clone(), |participants| { + participants.push(who.clone()); + }); *era_rewards.individual.entry(who.clone()).or_default() += 1; era_rewards.total += 1; }); @@ -496,7 +503,7 @@ pub mod pallet { ) -> DispatchResult { let who = ensure_signed(origin)?; // verify they are a candidate storage provider - let candidate_storage_providers = >::get(asset_id.clone()); + let candidate_storage_providers = >::get(asset_id.clone()); ensure!(candidate_storage_providers.contains(&who), Error::::NotACandidate); // verify not already pinning the content let current_pinners = >::get(asset_id.clone()); @@ -507,6 +514,9 @@ pub mod pallet { }); // award point to self if let Some(active_era) = ActiveEra::::get() { + SessionParticipation::::mutate(active_era.clone(), |p| { + p.push(who.clone()); + }); >::mutate(active_era, asset_id, |era_rewards| { *era_rewards.individual.entry(who.clone()).or_default() += 1; era_rewards.total += 1; @@ -528,9 +538,15 @@ pub mod pallet { ) -> DispatchResult { ensure_signed(origin)?; if let Some(active_era) = ActiveEra::::get() { - >::mutate(active_era, asset_id, |era_rewards| { + >::mutate(active_era.clone(), asset_id.clone(), |era_rewards| { + // reward all active storage providers + for k in StorageProviders::::get(asset_id.clone()).into_iter() { + SessionParticipation::::mutate(active_era.clone(), |p| { + p.push(k.clone()); + }); + *era_rewards.individual.entry(k.clone()).or_default() += 1; + } era_rewards.total += 1; - era_rewards.unallocated += 1; }); } else { // error -> no active era found @@ -553,6 +569,9 @@ impl Pallet { let validator_set: BTreeSet<_> = >::get().into_iter().collect(); ensure!(!validator_set.contains(&validator_id), Error::::Duplicate); >::mutate(|v| v.push(validator_id.clone())); + UnproductiveSessions::::mutate(validator_id.clone(), |v| { + *v = 0; + }); Self::deposit_event(Event::ValidatorAdditionInitiated(validator_id.clone())); log::debug!(target: LOG_TARGET, "Validator addition initiated."); @@ -610,27 +629,27 @@ impl Pallet { let validators_to_remove: BTreeSet<_> = >::get().into_iter().collect(); // Delete from active validator set. - >::mutate(|vs| vs.retain(|v| !validators_to_remove.contains(v))); + >::mutate(|vs| vs.retain(|v| !validators_to_remove.contains(v))); log::debug!( target: LOG_TARGET, "Initiated removal of {:?} offline validators.", validators_to_remove.len() ); + // remove as storage provider + // remove from pinners (and unpin the cid) // Clear the offline validator list to avoid repeated deletion. >::put(Vec::::new()); } /// move candidates to the active provider pool for some asset id + /// TODO: this undoubtedly will not scale very well fn select_candidate_storage_providers() { - // TODO: for now, we will just copy the candidates to the active providers map - // no real selection is happening yet, just doing this to get it in place for now - // iterate over asset ids // if there are candidate storage providers => for each candidate that pinned the file, move them to storage providers for assetid in >::asset_ids().into_iter() { // if there are candidates for the asset id - if >::contains_key(assetid.clone()) { - let candidates = >::get(assetid.clone()); + if >::contains_key(assetid.clone()) { + let candidates = >::get(assetid.clone()); let pinners = >::get(assetid.clone()); let pinner_candidate_intersection = candidates.into_iter().filter(|c| pinners.contains(c)).collect::>(); @@ -640,13 +659,19 @@ impl Pallet { } } - // distribute unallocated reward points to storage providers - fn distribute_unallocated_reward_points() { - // get unallocated rps in active era and disburse to storage providers - if let Some(active_era) = ActiveEra::::get() { - // fetch reward points for the era - - + fn mark_dead_validators(era_index: EraIndex) { + // for each validator that didn't participate, mark for removal + let partipating_validators = SessionParticipation::::get(era_index.clone()); + for acct in Validators::::get() { + if !partipating_validators.contains(&acct) { + if UnproductiveSessions::::get(acct.clone()) <= T::MaxDeadSession::get() { + UnproductiveSessions::::mutate(acct.clone(), |v| { + *v += 1; + }); + } else { + Self::mark_for_removal(acct); + } + } } } @@ -752,17 +777,17 @@ impl Pallet { /// process any requests in the DataQueue /// TODO: This needs some *major* refactoring fn handle_data_requests() -> Result<(), Error> { - if sp_io::offchain::is_validator() { - let data_queue = >::data_queue(); - let len = data_queue.len(); - if len != 0 { - log::info!("IPFS: {} entr{} in the data queue", len, if len == 1 { "y" } else { "ies" }); - } - // TODO: Needs refactoring - let deadline = Some(timestamp().add(Duration::from_millis(5_000))); - for cmd in data_queue.into_iter() { - match cmd { - DataCommand::AddBytes(addr, cid, admin, _name, id, balance) => { + let data_queue = >::data_queue(); + let len = data_queue.len(); + if len != 0 { + log::info!("IPFS: {} entr{} in the data queue", len, if len == 1 { "y" } else { "ies" }); + } + // TODO: Needs refactoring + let deadline = Some(timestamp().add(Duration::from_millis(5_000))); + for cmd in data_queue.into_iter() { + match cmd { + DataCommand::AddBytes(addr, cid, admin, _name, id, balance) => { + if sp_io::offchain::is_validator() { Self::ipfs_request(IpfsRequest::Connect(addr.clone()), deadline)?; log::info!( "IPFS: connected to {}", @@ -811,63 +836,67 @@ impl Pallet { Ok(_) => unreachable!("only CatBytes can be a response for that request type."), Err(e) => log::error!("IPFS: cat error: {:?}", e), } - }, - DataCommand::CatBytes(requestor, owner, asset_id) => { - let (public_key, addrs) = - if let IpfsResponse::Identity(public_key, addrs) = - Self::ipfs_request(IpfsRequest::Identity, deadline)? { - (public_key, addrs) - } else { - unreachable!("only `Identity` is a valid response type."); - }; - let expected_pub_key = >::get(requestor.clone()); - ensure!(public_key == expected_pub_key, Error::::BadOrigin); - - if let cid = >::asset_class_ownership( - owner.clone(), asset_id.clone() - ) { - ensure!( - owner.clone() == >::asset_access(requestor.clone(), asset_id.clone()), - Error::::InsufficientBalance - ); - match Self::ipfs_request(IpfsRequest::CatBytes(cid.clone()), deadline) { - Ok(IpfsResponse::CatBytes(data)) => { - log::info!("IPFS: Fetched data from IPFS."); - // add to offchain index - sp_io::offchain::local_storage_set( - StorageKind::PERSISTENT, - &cid, - &data, + } + }, + DataCommand::CatBytes(requestor, owner, asset_id) => { + // fetch ipfs id + let (public_key, addrs) = + if let IpfsResponse::Identity(public_key, addrs) = + Self::ipfs_request(IpfsRequest::Identity, deadline)? { + (public_key, addrs) + } else { + unreachable!("only `Identity` is a valid response type."); + }; + // verify ipfs pub key + let expected_pub_key = >::get(requestor.clone()); + ensure!(public_key == expected_pub_key, Error::::BadOrigin); + + if let cid = >::asset_class_ownership( + owner.clone(), asset_id.clone() + ) { + ensure!( + owner.clone() == >::asset_access(requestor.clone(), asset_id.clone()), + Error::::InsufficientBalance + ); + match Self::ipfs_request(IpfsRequest::CatBytes(cid.clone()), deadline) { + Ok(IpfsResponse::CatBytes(data)) => { + log::info!("IPFS: Fetched data from IPFS."); + // add to offchain index + sp_io::offchain::local_storage_set( + StorageKind::PERSISTENT, + &cid, + &data, + ); + + let signer = Signer::::all_accounts(); + if !signer.can_sign() { + log::error!( + "No local accounts available. Consider adding one via `author_insertKey` RPC.", ); - - let signer = Signer::::all_accounts(); - if !signer.can_sign() { - log::error!( - "No local accounts available. Consider adding one via `author_insertKey` RPC.", - ); + } + let results = signer.send_signed_transaction(|_account| { + Call::submit_rpc_ready { + // beneficiary: requestor.clone(), + asset_id: asset_id.clone(), } - let results = signer.send_signed_transaction(|_account| { - Call::submit_rpc_ready { - // beneficiary: requestor.clone(), - asset_id: asset_id.clone(), - } - }); - - for (_, res) in &results { - match res { - Ok(()) => log::info!("Submitted ipfs results"), - Err(e) => log::error!("Failed to submit transaction: {:?}", e), - } + }); + + for (_, res) in &results { + match res { + Ok(()) => log::info!("Submitted ipfs results"), + Err(e) => log::error!("Failed to submit transaction: {:?}", e), } - }, - Ok(_) => unreachable!("only CatBytes can be a response for that request type."), - Err(e) => log::error!("IPFS: cat error: {:?}", e), - } - } else { - log::error!("the provided owner/cid does not map to a valid asset id: {:?}, {:?}", owner, asset_id) + } + }, + Ok(_) => unreachable!("only CatBytes can be a response for that request type."), + Err(e) => log::error!("IPFS: cat error: {:?}", e), } - }, - DataCommand::PinCID(acct, asset_id, cid) => { + } else { + log::error!("the provided owner/cid does not map to a valid asset id: {:?}, {:?}", owner, asset_id) + } + }, + DataCommand::PinCID(acct, asset_id, cid) => { + if sp_io::offchain::is_validator() { let (public_key, addrs) = if let IpfsResponse::Identity(public_key, addrs) = Self::ipfs_request(IpfsRequest::Identity, deadline)? { @@ -928,7 +957,6 @@ impl Pallet { ); Ok(()) } - } // Provides the new set of validators to the session module when session is @@ -939,8 +967,6 @@ impl pallet_session::SessionManager for Pallet { log::info!("Starting new session with index: {:?}", new_index); // TODO: how staking pallet uses this, 'trigger_new_era' CurrentEra::::mutate(|s| *s = Some(new_index)); - // Remove any offline validators. This will only work when the runtime - // also has the im-online pallet. Self::remove_offline_validators(); // TODO: REMOVE OFFLINE STORAGE PROVIDERS Self::select_candidate_storage_providers(); @@ -950,7 +976,7 @@ impl pallet_session::SessionManager for Pallet { fn end_session(end_index: u32) { log::info!("Ending session with index: {:?}", end_index); - // Self::distribute_unallocated_reward_points(); + Self::mark_dead_validators(end_index); } fn start_session(start_index: u32) { diff --git a/bin/node-template/pallets/iris-session/src/mock.rs b/bin/node-template/pallets/iris-session/src/mock.rs index 8f91f33a619e..504e1ecb5844 100644 --- a/bin/node-template/pallets/iris-session/src/mock.rs +++ b/bin/node-template/pallets/iris-session/src/mock.rs @@ -19,6 +19,7 @@ use sp_core::{ offchain::{testing, OffchainWorkerExt, TransactionPoolExt}, sr25519::Signature, H256, + Pair, }; use sp_keystore::{testing::KeyStore, KeystoreExt, SyncCryptoStore}; @@ -80,9 +81,19 @@ frame_support::construct_runtime!( } ); +// pub static V0: (sp_core::sr25519::Public, UintAuthorityId) = (sp_core::sr25519::Pair::generate_with_phrase(Some("0")).0.public(), UintAuthorityId(0)); +// pub static V1: (sp_core::sr25519::Public, UintAuthorityId) = (sp_core::sr25519::Pair::generate_with_phrase(Some("1")).0.public(), UintAuthorityId(1)); +// pub static V2: (sp_core::sr25519::Public, UintAuthorityId) = (sp_core::sr25519::Pair::generate_with_phrase(Some("2")).0.public(), UintAuthorityId(2)); + thread_local! { - pub static VALIDATORS: RefCell> = RefCell::new(vec![1, 2, 3]); - pub static NEXT_VALIDATORS: RefCell> = RefCell::new(vec![1, 2, 3]); + pub static VALIDATORS: RefCell> = RefCell::new( + vec![(sp_core::sr25519::Pair::generate_with_phrase(Some("0")).0.public(), UintAuthorityId(0)), + (sp_core::sr25519::Pair::generate_with_phrase(Some("1")).0.public(), UintAuthorityId(1)), + (sp_core::sr25519::Pair::generate_with_phrase(Some("2")).0.public(), UintAuthorityId(2))]); + pub static NEXT_VALIDATORS: RefCell> = RefCell::new( + vec![(sp_core::sr25519::Pair::generate_with_phrase(Some("0")).0.public(), UintAuthorityId(0)), + (sp_core::sr25519::Pair::generate_with_phrase(Some("1")).0.public(), UintAuthorityId(1)), + (sp_core::sr25519::Pair::generate_with_phrase(Some("2")).0.public(), UintAuthorityId(2))]); pub static AUTHORITIES: RefCell> = RefCell::new(vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); pub static FORCE_SESSION_END: RefCell = RefCell::new(false); @@ -93,13 +104,13 @@ thread_local! { } pub struct TestSessionHandler; -impl pallet_session::SessionHandler for TestSessionHandler { +impl pallet_session::SessionHandler for TestSessionHandler { const KEY_TYPE_IDS: &'static [sp_runtime::KeyTypeId] = &[UintAuthorityId::ID]; - fn on_genesis_session(_validators: &[(u64, T)]) {} + fn on_genesis_session(_validators: &[(sp_core::sr25519::Public, T)]) {} fn on_new_session( changed: bool, - validators: &[(u64, T)], - _queued_validators: &[(u64, T)], + validators: &[(sp_core::sr25519::Public, T)], + _queued_validators: &[(sp_core::sr25519::Public, T)], ) { SESSION_CHANGED.with(|l| *l.borrow_mut() = changed); AUTHORITIES.with(|l| { @@ -186,10 +197,6 @@ impl pallet_balances::Config for Test { type WeightInfo = (); } -parameter_types! { - pub const MinAuthorities: u32 = 2; -} - // implement assets pallet for iris_assets parameter_types! { pub const AssetDeposit: u64 = 1; @@ -204,8 +211,8 @@ impl pallet_assets::Config for Test { type Balance = u64; type AssetId = u32; type Currency = Balances; - // type ForceOrigin = frame_system::EnsureRoot; - type ForceOrigin = EnsureRoot; + type ForceOrigin = frame_system::EnsureRoot; + // type ForceOrigin = EnsureRoot; type AssetDeposit = AssetDeposit; type MetadataDepositBase = MetadataDepositBase; type MetadataDepositPerByte = MetadataDepositPerByte; @@ -224,14 +231,19 @@ impl pallet_iris_assets::Config for Test { type Currency = Balances; } +parameter_types! { + pub const MinAuthorities: u32 = 2; + pub const MaxDeadSession: u32 = 3; +} impl Config for Test { // type AddRemoveOrigin = (); - type AddRemoveOrigin = EnsureRoot; + type AddRemoveOrigin = EnsureRoot; type Call = Call; type AuthorityId = pallet_iris_session::crypto::TestAuthId; type Event = Event; type MinAuthorities = MinAuthorities; + type MaxDeadSession = MaxDeadSession; } parameter_types! { @@ -284,13 +296,13 @@ where pub fn new_test_ext() -> sp_io::TestExternalities { let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); let keys: Vec<_> = NEXT_VALIDATORS - .with(|l| l.borrow().iter().cloned().map(|i| (i, i, UintAuthorityId(i).into())).collect()); + .with(|l| l.borrow().iter().cloned().map(|i| (i.0, i.0, i.1.into())).collect()); BasicExternalities::execute_with_storage(&mut t, || { for (ref k, ..) in &keys { frame_system::Pallet::::inc_providers(k); } - frame_system::Pallet::::inc_providers(&4); - frame_system::Pallet::::inc_providers(&69); + // frame_system::Pallet::::inc_providers(&4); + // frame_system::Pallet::::inc_providers(&69); }); pallet_iris_session::GenesisConfig:: { diff --git a/bin/node-template/pallets/iris-session/src/tests.rs b/bin/node-template/pallets/iris-session/src/tests.rs index 3fa747463d80..4748fdf1fc9c 100644 --- a/bin/node-template/pallets/iris-session/src/tests.rs +++ b/bin/node-template/pallets/iris-session/src/tests.rs @@ -15,18 +15,46 @@ use std::sync::Arc; #[test] fn iris_session_simple_setup_should_work() { + let V0: (sp_core::sr25519::Public, UintAuthorityId) = ( + sp_core::sr25519::Pair::generate_with_phrase(Some("0")).0.public(), + UintAuthorityId(0) + ); + let V1: (sp_core::sr25519::Public, UintAuthorityId) = ( + sp_core::sr25519::Pair::generate_with_phrase(Some("1")).0.public(), + UintAuthorityId(1) + ); + let V2: (sp_core::sr25519::Public, UintAuthorityId) = ( + sp_core::sr25519::Pair::generate_with_phrase(Some("2")).0.public(), + UintAuthorityId(2) + ); new_test_ext().execute_with(|| { - assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); - assert_eq!(crate::Validators::::get(), vec![1u64, 2u64, 3u64]); - assert_eq!(Session::validators(), vec![1, 2, 3]); + assert_eq!(authorities(), vec![V0.1, V1.1, V2.1]); + assert_eq!(crate::Validators::::get(), vec![V0.0, V1.0, V2.0]); + assert_eq!(Session::validators(), vec![V0.0, V1.0, V2.0]); }); } #[test] fn iris_session_add_validator_updates_validators_list() { + let V0: (sp_core::sr25519::Public, UintAuthorityId) = ( + sp_core::sr25519::Pair::generate_with_phrase(Some("0")).0.public(), + UintAuthorityId(0) + ); + let V1: (sp_core::sr25519::Public, UintAuthorityId) = ( + sp_core::sr25519::Pair::generate_with_phrase(Some("1")).0.public(), + UintAuthorityId(1) + ); + let V2: (sp_core::sr25519::Public, UintAuthorityId) = ( + sp_core::sr25519::Pair::generate_with_phrase(Some("2")).0.public(), + UintAuthorityId(2) + ); + let V3: (sp_core::sr25519::Public, UintAuthorityId) = ( + sp_core::sr25519::Pair::generate_with_phrase(Some("3")).0.public(), + UintAuthorityId(3) + ); new_test_ext().execute_with(|| { - assert_ok!(IrisSession::add_validator(Origin::root(), 4)); - assert_eq!(crate::Validators::::get(), vec![1u64, 2u64, 3u64, 4u64]) + assert_ok!(IrisSession::add_validator(Origin::root(), V3.0)); + assert_eq!(crate::Validators::::get(), vec![V0.0, V1.0, V2.0, V3.0]); }); } diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index f9c6ee0b50ab..55f2c93c7c67 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -220,6 +220,7 @@ impl pallet_randomness_collective_flip::Config for Runtime {} parameter_types! { // TODO: Increase this when done testing pub const MinAuthorities: u32 = 1; + pub const MaxDeadSession: u32 = 3; } impl pallet_iris_session::Config for Runtime { @@ -227,6 +228,7 @@ impl pallet_iris_session::Config for Runtime { type Call = Call; type AddRemoveOrigin = EnsureRoot; type MinAuthorities = MinAuthorities; + type MaxDeadSession = MaxDeadSession; type AuthorityId = pallet_iris_session::crypto::TestAuthId; } diff --git a/client/service/src/task_manager/tests.rs b/client/service/src/task_manager/tests.rs index 291d71ebaf03..400b1f24356c 100644 --- a/client/service/src/task_manager/tests.rs +++ b/client/service/src/task_manager/tests.rs @@ -85,7 +85,7 @@ async fn run_background_task_blocking(duration: Duration, _keep_alive: impl Any) } fn new_task_manager(tokio_handle: tokio::runtime::Handle) -> TaskManager { - TaskManager::new(tokio_handle, None).unwrap() + TaskManager::new(tokio_handle, None, None).unwrap() } #[test] From c8bef76781fad6e88aa85397ece5058db780f12c Mon Sep 17 00:00:00 2001 From: Qinxuan Chen Date: Tue, 8 Feb 2022 16:52:20 +0800 Subject: [PATCH 462/695] sp-maybe-compressed-blob: reduce boilerplate code (#10814) Signed-off-by: koushiro --- Cargo.lock | 1 + primitives/maybe-compressed-blob/Cargo.toml | 1 + primitives/maybe-compressed-blob/src/lib.rs | 23 +++++++-------------- 3 files changed, 9 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 45158288298b..553da394386c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9809,6 +9809,7 @@ dependencies = [ name = "sp-maybe-compressed-blob" version = "4.1.0-dev" dependencies = [ + "thiserror", "zstd", ] diff --git a/primitives/maybe-compressed-blob/Cargo.toml b/primitives/maybe-compressed-blob/Cargo.toml index dbed41571b14..d8814356df4b 100644 --- a/primitives/maybe-compressed-blob/Cargo.toml +++ b/primitives/maybe-compressed-blob/Cargo.toml @@ -11,4 +11,5 @@ documentation = "https://docs.rs/sp-maybe-compressed-blob" readme = "README.md" [dependencies] +thiserror = "1.0" zstd = { version = "0.9.0", default-features = false } diff --git a/primitives/maybe-compressed-blob/src/lib.rs b/primitives/maybe-compressed-blob/src/lib.rs index 402ed90be21c..99c12ed39bc0 100644 --- a/primitives/maybe-compressed-blob/src/lib.rs +++ b/primitives/maybe-compressed-blob/src/lib.rs @@ -18,7 +18,10 @@ //! Handling of blobs that may be compressed, based on an 8-byte magic identifier //! at the head. -use std::{borrow::Cow, io::Read}; +use std::{ + borrow::Cow, + io::{Read, Write}, +}; // An arbitrary prefix, that indicates a blob beginning with should be decompressed with // Zstd compression. @@ -34,25 +37,16 @@ const ZSTD_PREFIX: [u8; 8] = [82, 188, 83, 118, 70, 219, 142, 5]; pub const CODE_BLOB_BOMB_LIMIT: usize = 50 * 1024 * 1024; /// A possible bomb was encountered. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, thiserror::Error)] pub enum Error { /// Decoded size was too large, and the code payload may be a bomb. + #[error("Possible compression bomb encountered")] PossibleBomb, /// The compressed value had an invalid format. + #[error("Blob had invalid format")] Invalid, } -impl std::fmt::Display for Error { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - match *self { - Error::PossibleBomb => write!(f, "Possible compression bomb encountered"), - Error::Invalid => write!(f, "Blob had invalid format"), - } - } -} - -impl std::error::Error for Error {} - fn read_from_decoder( decoder: impl Read, blob_len: usize, @@ -90,8 +84,6 @@ pub fn decompress(blob: &[u8], bomb_limit: usize) -> Result, Error> { /// this will not compress the blob, as the decoder will not be able to be /// able to differentiate it from a compression bomb. pub fn compress(blob: &[u8], bomb_limit: usize) -> Option> { - use std::io::Write; - if blob.len() > bomb_limit { return None } @@ -109,7 +101,6 @@ pub fn compress(blob: &[u8], bomb_limit: usize) -> Option> { #[cfg(test)] mod tests { use super::*; - use std::io::Write; const BOMB_LIMIT: usize = 10; From aa7a7563bf8cdd3e60a5b1b379f287ae1457b864 Mon Sep 17 00:00:00 2001 From: Yarik Bratashchuk Date: Tue, 8 Feb 2022 13:43:32 +0200 Subject: [PATCH 463/695] `seal_delegate_call` api function (support for library contracts) (#10617) * seal_call_code implementation - tests - benchmark * Addressing @xgreenx's comments * Fix test-linux-stable-int * Rename seal_call_code to seal_delegate_call * Pass value unchanged into lib contract * Address @athei's comments - whitespace .wat issues - wrong/missing .wat comments - redundant .wat calls/declarations - change order of functions (seal_delegate_call right after seal_call) in decls, tests, benchmark - fix comments, move doc comments to enum variants - remove unnecessary empty lines - rename runtime cost DelegateCall to DelegateCallBase - do not set CallFlags::ALLOW_REENTRY for delegate_call * Do not pass CallFlags::ALLOWS_REENTRY for delegate_call * Update comment for seal_delegate_call and CallFlags * Addressing @athei's comments (minor) * Allow reentry for a new frame after delegate_call (revert) * Same seal_caller and seal_value_transferred for lib contract - test - refactor frame args due to review - logic for seal_caller (please review) * Put caller on frame for delegate_call, minor fixes * Update comment for delegate_call * Addressing @athei's comments * Update weights generated by benchmark * Improve comments * Address @HCastano's comments * Update weights, thanks @joao-paulo-parity * Improve InvalidCallFlags error comment --- frame/contracts/fixtures/delegate_call.wat | 111 +++++++++++++++ .../contracts/fixtures/delegate_call_lib.wat | 79 +++++++++++ frame/contracts/src/benchmarking/mod.rs | 52 +++++++ frame/contracts/src/exec.rs | 127 +++++++++++++---- frame/contracts/src/lib.rs | 2 + frame/contracts/src/schedule.rs | 4 + frame/contracts/src/tests.rs | 38 ++++++ frame/contracts/src/wasm/mod.rs | 63 +++++++++ frame/contracts/src/wasm/runtime.rs | 128 +++++++++++++++--- frame/contracts/src/weights.rs | 23 ++++ 10 files changed, 576 insertions(+), 51 deletions(-) create mode 100644 frame/contracts/fixtures/delegate_call.wat create mode 100644 frame/contracts/fixtures/delegate_call_lib.wat diff --git a/frame/contracts/fixtures/delegate_call.wat b/frame/contracts/fixtures/delegate_call.wat new file mode 100644 index 000000000000..e1c5fa813e59 --- /dev/null +++ b/frame/contracts/fixtures/delegate_call.wat @@ -0,0 +1,111 @@ +(module + (import "seal0" "seal_input" (func $seal_input (param i32 i32))) + (import "seal0" "seal_get_storage" (func $seal_get_storage (param i32 i32 i32) (result i32))) + (import "seal0" "seal_set_storage" (func $seal_set_storage (param i32 i32 i32))) + (import "__unstable__" "seal_delegate_call" (func $seal_delegate_call (param i32 i32 i32 i32 i32 i32) (result i32))) + (import "env" "memory" (memory 3 3)) + + ;; [0, 32) storage key + (data (i32.const 0) "\01") + + ;; [32, 64) storage key + (data (i32.const 32) "\02") + + ;; [64, 96) buffer where input is copied + + ;; [96, 100) size of the input buffer + (data (i32.const 96) "\20") + + ;; [100, 104) size of buffer for seal_get_storage + (data (i32.const 100) "\20") + + ;; [104, 136) seal_get_storage buffer + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func (export "call") + (local $exit_code i32) + + ;; Reading "callee" code_hash + (call $seal_input (i32.const 64) (i32.const 96)) + + ;; assert input size == 32 + (call $assert + (i32.eq + (i32.load (i32.const 96)) + (i32.const 32) + ) + ) + + ;; place a value in storage, the size of which is specified by the call input. + (call $seal_set_storage + (i32.const 0) ;; Pointer to storage key + (i32.const 32) ;; Pointer to initial value + (i32.load (i32.const 100)) ;; Size of value + ) + + (call $assert + (i32.eq + (call $seal_get_storage + (i32.const 0) ;; Pointer to storage key + (i32.const 104) ;; buffer where to copy result + (i32.const 100) ;; pointer to size of buffer + ) + (i32.const 0) ;; ReturnCode::Success + ) + ) + + (call $assert + (i32.eq + (i32.load (i32.const 104)) ;; value received from storage + (i32.load (i32.const 32)) ;; initial value + ) + ) + + ;; Call deployed library contract code. + (set_local $exit_code + (call $seal_delegate_call + (i32.const 0) ;; Set no call flags + (i32.const 64) ;; Pointer to "callee" code_hash. + (i32.const 0) ;; Input is ignored + (i32.const 0) ;; Length of the input + (i32.const 4294967295) ;; u32 max sentinel value: do not copy output + (i32.const 0) ;; Length is ignored in this case + ) + ) + + ;; Check for success exit status. + (call $assert + (i32.eq (get_local $exit_code) (i32.const 0)) ;; ReturnCode::Success + ) + + (call $assert + (i32.eq + (call $seal_get_storage + (i32.const 0) ;; Pointer to storage key + (i32.const 104) ;; buffer where to copy result + (i32.const 100) ;; pointer to size of buffer + ) + (i32.const 0) ;; ReturnCode::Success + ) + ) + + ;; Make sure that 'callee' code changed the value + (call $assert + (i32.eq + (i32.load (i32.const 104)) + (i32.const 1) + ) + ) + ) + + (func (export "deploy")) + +) diff --git a/frame/contracts/fixtures/delegate_call_lib.wat b/frame/contracts/fixtures/delegate_call_lib.wat new file mode 100644 index 000000000000..340b9699f875 --- /dev/null +++ b/frame/contracts/fixtures/delegate_call_lib.wat @@ -0,0 +1,79 @@ +(module + (import "seal0" "seal_set_storage" (func $seal_set_storage (param i32 i32 i32))) + (import "seal0" "seal_caller" (func $seal_caller (param i32 i32))) + (import "seal0" "seal_value_transferred" (func $seal_value_transferred (param i32 i32))) + (import "env" "memory" (memory 1 1)) + + ;; [0, 32) storage key + (data (i32.const 0) "\01") + + ;; [32, 64) buffer for transferred value + + ;; [64, 96) size of the buffer for transferred value + (data (i32.const 64) "\20") + + ;; [96, 128) buffer for the caller + + ;; [128, 160) size of the buffer for caller + (data (i32.const 128) "\20") + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func (export "call") + ;; place a value in storage + (call $seal_set_storage + (i32.const 0) ;; Pointer to storage key + (i32.const 0) ;; Pointer to value + (i32.const 32) ;; Size of value + ) + + ;; This stores the value transferred in the buffer + (call $seal_value_transferred (i32.const 32) (i32.const 64)) + + ;; assert len == 8 + (call $assert + (i32.eq + (i32.load (i32.const 64)) + (i32.const 8) + ) + ) + + ;; assert that contents of the buffer is equal to the value + ;; passed to the `caller` contract: 1337 + (call $assert + (i64.eq + (i64.load (i32.const 32)) + (i64.const 1337) + ) + ) + + ;; fill the buffer with the caller. + (call $seal_caller (i32.const 96) (i32.const 128)) + + ;; assert len == 32 + (call $assert + (i32.eq + (i32.load (i32.const 128)) + (i32.const 32) + ) + ) + + ;; assert that the first 64 byte are the beginning of "ALICE", + ;; who is the caller of the `caller` contract + (call $assert + (i64.eq + (i64.load (i32.const 96)) + (i64.const 0x0101010101010101) + ) + ) + ) + + (func (export "deploy")) +) diff --git a/frame/contracts/src/benchmarking/mod.rs b/frame/contracts/src/benchmarking/mod.rs index 71045bde2152..88405eba4420 100644 --- a/frame/contracts/src/benchmarking/mod.rs +++ b/frame/contracts/src/benchmarking/mod.rs @@ -1474,6 +1474,58 @@ benchmarks! { let origin = RawOrigin::Signed(instance.caller.clone()); }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + seal_delegate_call { + let r in 0 .. API_BENCHMARK_BATCHES; + let hashes = (0..r * API_BENCHMARK_BATCH_SIZE) + .map(|i| { + let code = WasmModule::::dummy_with_bytes(i); + Contracts::::store_code_raw(code.code, whitelisted_caller())?; + Ok(code.hash) + }) + .collect::, &'static str>>()?; + let hash_len = hashes.get(0).map(|x| x.encode().len()).unwrap_or(0); + let hashes_bytes = hashes.iter().flat_map(|x| x.encode()).collect::>(); + let hashes_len = hashes_bytes.len(); + let hashes_offset = 0; + + let code = WasmModule::::from(ModuleDefinition { + memory: Some(ImportedMemory::max::()), + imported_functions: vec![ImportedFunction { + module: "__unstable__", + name: "seal_delegate_call", + params: vec![ + ValueType::I32, + ValueType::I32, + ValueType::I32, + ValueType::I32, + ValueType::I32, + ValueType::I32, + ], + return_type: Some(ValueType::I32), + }], + data_segments: vec![ + DataSegment { + offset: hashes_offset as u32, + value: hashes_bytes, + }, + ], + call_body: Some(body::repeated_dyn(r * API_BENCHMARK_BATCH_SIZE, vec![ + Regular(Instruction::I32Const(0)), // flags + Counter(hashes_offset as u32, hash_len as u32), // code_hash_ptr + Regular(Instruction::I32Const(0)), // input_data_ptr + Regular(Instruction::I32Const(0)), // input_data_len + Regular(Instruction::I32Const(u32::max_value() as i32)), // output_ptr + Regular(Instruction::I32Const(0)), // output_len_ptr + Regular(Instruction::Call(0)), + Regular(Instruction::Drop), + ])), + .. Default::default() + }); + let instance = Contract::::new(code, vec![])?; + let callee = instance.addr.clone(); + let origin = RawOrigin::Signed(instance.caller.clone()); + }: call(origin, callee, 0u32.into(), Weight::MAX, None, vec![]) + seal_call_per_transfer_input_output_kb { let t in 0 .. 1; let i in 0 .. code::max_pages::() * 64; diff --git a/frame/contracts/src/exec.rs b/frame/contracts/src/exec.rs index befdf592f51c..c6e647e0c8d9 100644 --- a/frame/contracts/src/exec.rs +++ b/frame/contracts/src/exec.rs @@ -104,6 +104,19 @@ pub trait Ext: sealing::Sealed { allows_reentry: bool, ) -> Result; + /// Execute code in the current frame. + /// + /// Returns the original code size of the called contract. + /// + /// # Return Value + /// + /// Result + fn delegate_call( + &mut self, + code: CodeHash, + input_data: Vec, + ) -> Result; + /// Instantiate a contract from the given code. /// /// Returns the original code size of the called contract. @@ -347,6 +360,16 @@ pub struct Frame { nested_storage: storage::meter::NestedMeter, /// If `false` the contract enabled its defense against reentrance attacks. allows_reentry: bool, + /// The caller of the currently executing frame which was spawned by `delegate_call`. + delegate_caller: Option, +} + +/// Used in a delegate call frame arguments in order to override the executable and caller. +struct DelegatedCall { + /// The executable which is run instead of the contracts own `executable`. + executable: E, + /// The account id of the caller contract. + caller: T::AccountId, } /// Parameter passed in when creating a new `Frame`. @@ -358,6 +381,10 @@ enum FrameArgs<'a, T: Config, E> { dest: T::AccountId, /// If `None` the contract info needs to be reloaded from storage. cached_info: Option>, + /// This frame was created by `seal_delegate_call` and hence uses different code than + /// what is stored at [`Self::dest`]. Its caller ([`Frame::delegated_caller`]) is the + /// account which called the caller contract + delegated_call: Option>, }, Instantiate { /// The contract or signed origin which instantiates the new contract. @@ -513,7 +540,7 @@ where debug_message: Option<&'a mut Vec>, ) -> Result { let (mut stack, executable) = Self::new( - FrameArgs::Call { dest, cached_info: None }, + FrameArgs::Call { dest, cached_info: None, delegated_call: None }, origin, gas_meter, storage_meter, @@ -604,33 +631,46 @@ where gas_limit: Weight, schedule: &Schedule, ) -> Result<(Frame, E, Option), ExecError> { - let (account_id, contract_info, executable, entry_point, account_counter) = match frame_args - { - FrameArgs::Call { dest, cached_info } => { - let contract = if let Some(contract) = cached_info { - contract - } else { - >::get(&dest).ok_or(>::ContractNotFound)? - }; - - let executable = E::from_storage(contract.code_hash, schedule, gas_meter)?; - - (dest, contract, executable, ExportedFunction::Call, None) - }, - FrameArgs::Instantiate { sender, trie_seed, executable, salt } => { - let account_id = - >::contract_address(&sender, executable.code_hash(), &salt); - let trie_id = Storage::::generate_trie_id(&account_id, trie_seed); - let contract = Storage::::new_contract( - &account_id, - trie_id, - executable.code_hash().clone(), - )?; - (account_id, contract, executable, ExportedFunction::Constructor, Some(trie_seed)) - }, - }; + let (account_id, contract_info, executable, delegate_caller, entry_point, account_counter) = + match frame_args { + FrameArgs::Call { dest, cached_info, delegated_call } => { + let contract = if let Some(contract) = cached_info { + contract + } else { + >::get(&dest).ok_or(>::ContractNotFound)? + }; + + let (executable, delegate_caller) = + if let Some(DelegatedCall { executable, caller }) = delegated_call { + (executable, Some(caller)) + } else { + (E::from_storage(contract.code_hash, schedule, gas_meter)?, None) + }; + + (dest, contract, executable, delegate_caller, ExportedFunction::Call, None) + }, + FrameArgs::Instantiate { sender, trie_seed, executable, salt } => { + let account_id = + >::contract_address(&sender, executable.code_hash(), &salt); + let trie_id = Storage::::generate_trie_id(&account_id, trie_seed); + let contract = Storage::::new_contract( + &account_id, + trie_id, + executable.code_hash().clone(), + )?; + ( + account_id, + contract, + executable, + None, + ExportedFunction::Constructor, + Some(trie_seed), + ) + }, + }; let frame = Frame { + delegate_caller, value_transferred, contract_info: CachedContract::Cached(contract_info), account_id, @@ -936,8 +976,11 @@ where CachedContract::Cached(contract) => Some(contract.clone()), _ => None, }); - let executable = - self.push_frame(FrameArgs::Call { dest: to, cached_info }, value, gas_limit)?; + let executable = self.push_frame( + FrameArgs::Call { dest: to, cached_info, delegated_call: None }, + value, + gas_limit, + )?; self.run(executable, input_data) }; @@ -950,6 +993,28 @@ where result } + fn delegate_call( + &mut self, + code_hash: CodeHash, + input_data: Vec, + ) -> Result { + let executable = E::from_storage(code_hash, &self.schedule, self.gas_meter())?; + let top_frame = self.top_frame_mut(); + let contract_info = top_frame.contract_info().clone(); + let account_id = top_frame.account_id.clone(); + let value = top_frame.value_transferred.clone(); + let executable = self.push_frame( + FrameArgs::Call { + dest: account_id, + cached_info: Some(contract_info), + delegated_call: Some(DelegatedCall { executable, caller: self.caller().clone() }), + }, + value, + 0, + )?; + self.run(executable, input_data) + } + fn instantiate( &mut self, gas_limit: Weight, @@ -1030,7 +1095,11 @@ where } fn caller(&self) -> &T::AccountId { - self.frames().nth(1).map(|f| &f.account_id).unwrap_or(&self.origin) + if let Some(caller) = &self.top_frame().delegate_caller { + &caller + } else { + self.frames().nth(1).map(|f| &f.account_id).unwrap_or(&self.origin) + } } fn is_contract(&self, address: &T::AccountId) -> bool { diff --git a/frame/contracts/src/lib.rs b/frame/contracts/src/lib.rs index 9f9cc09f6430..7e4515868b74 100644 --- a/frame/contracts/src/lib.rs +++ b/frame/contracts/src/lib.rs @@ -570,6 +570,8 @@ pub mod pallet { pub enum Error { /// A new schedule must have a greater version than the current one. InvalidScheduleVersion, + /// Invalid combination of flags supplied to `seal_call` or `seal_delegate_call`. + InvalidCallFlags, /// The executed contract exhausted its gas limit. OutOfGas, /// The output buffer supplied to a contract API call was too small. diff --git a/frame/contracts/src/schedule.rs b/frame/contracts/src/schedule.rs index 266c0a6e2748..e599bdc3125b 100644 --- a/frame/contracts/src/schedule.rs +++ b/frame/contracts/src/schedule.rs @@ -358,6 +358,9 @@ pub struct HostFnWeights { /// Weight of calling `seal_call`. pub call: Weight, + /// Weight of calling `seal_delegate_call`. + pub delegate_call: Weight, + /// Weight surcharge that is claimed if `seal_call` does a balance transfer. pub call_transfer_surcharge: Weight, @@ -615,6 +618,7 @@ impl Default for HostFnWeights { take_storage_per_byte: cost_byte_batched!(seal_take_storage_per_kb), transfer: cost_batched!(seal_transfer), call: cost_batched!(seal_call), + delegate_call: cost_batched!(seal_delegate_call), call_transfer_surcharge: cost_batched_args!( seal_call_per_transfer_input_output_kb, 1, diff --git a/frame/contracts/src/tests.rs b/frame/contracts/src/tests.rs index d95d434e6a74..6919705206d4 100644 --- a/frame/contracts/src/tests.rs +++ b/frame/contracts/src/tests.rs @@ -692,6 +692,44 @@ fn deploy_and_call_other_contract() { }); } +#[test] +#[cfg(feature = "unstable-interface")] +fn delegate_call() { + let (caller_wasm, caller_code_hash) = compile_module::("delegate_call").unwrap(); + let (callee_wasm, callee_code_hash) = compile_module::("delegate_call_lib").unwrap(); + let caller_addr = Contracts::contract_address(&ALICE, &caller_code_hash, &[]); + + ExtBuilder::default().existential_deposit(500).build().execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + + // Instantiate the 'caller' + assert_ok!(Contracts::instantiate_with_code( + Origin::signed(ALICE), + 300_000, + GAS_LIMIT, + None, + caller_wasm, + vec![], + vec![], + )); + // Only upload 'callee' code + assert_ok!(Contracts::upload_code( + Origin::signed(ALICE), + callee_wasm, + Some(codec::Compact(100_000)), + )); + + assert_ok!(Contracts::call( + Origin::signed(ALICE), + caller_addr.clone(), + 1337, + GAS_LIMIT, + None, + callee_code_hash.as_ref().to_vec(), + )); + }); +} + #[test] fn cannot_self_destruct_through_draning() { let (wasm, code_hash) = compile_module::("drain").unwrap(); diff --git a/frame/contracts/src/wasm/mod.rs b/frame/contracts/src/wasm/mod.rs index 7c98ee7cf5b1..3be1062ce969 100644 --- a/frame/contracts/src/wasm/mod.rs +++ b/frame/contracts/src/wasm/mod.rs @@ -302,11 +302,18 @@ mod tests { allows_reentry: bool, } + #[derive(Debug, PartialEq, Eq)] + struct CallCodeEntry { + code_hash: H256, + data: Vec, + } + pub struct MockExt { storage: HashMap>, instantiates: Vec, terminations: Vec, calls: Vec, + code_calls: Vec, transfers: Vec, // (topics, data) events: Vec<(Vec, Vec)>, @@ -329,6 +336,7 @@ mod tests { instantiates: Default::default(), terminations: Default::default(), calls: Default::default(), + code_calls: Default::default(), transfers: Default::default(), events: Default::default(), runtime_calls: Default::default(), @@ -354,6 +362,14 @@ mod tests { self.calls.push(CallEntry { to, value, data, allows_reentry }); Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: call_return_data() }) } + fn delegate_call( + &mut self, + code_hash: CodeHash, + data: Vec, + ) -> Result { + self.code_calls.push(CallCodeEntry { code_hash, data }); + Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: call_return_data() }) + } fn instantiate( &mut self, gas_limit: Weight, @@ -579,6 +595,53 @@ mod tests { ); } + #[test] + #[cfg(feature = "unstable-interface")] + fn contract_delegate_call() { + const CODE: &str = r#" +(module + ;; seal_delegate_call( + ;; flags: u32, + ;; code_hash_ptr: u32, + ;; input_data_ptr: u32, + ;; input_data_len: u32, + ;; output_ptr: u32, + ;; output_len_ptr: u32 + ;;) -> u32 + (import "__unstable__" "seal_delegate_call" (func $seal_delegate_call (param i32 i32 i32 i32 i32 i32) (result i32))) + (import "env" "memory" (memory 1 1)) + (func (export "call") + (drop + (call $seal_delegate_call + (i32.const 0) ;; No flags are set + (i32.const 4) ;; Pointer to "callee" code_hash. + (i32.const 36) ;; Pointer to input data buffer address + (i32.const 4) ;; Length of input data buffer + (i32.const 4294967295) ;; u32 max value is the sentinel value: do not copy output + (i32.const 0) ;; Length is ignored in this case + ) + ) + ) + (func (export "deploy")) + + ;; Callee code_hash + (data (i32.const 4) + "\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11" + "\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11" + ) + + (data (i32.const 36) "\01\02\03\04") +) +"#; + let mut mock_ext = MockExt::default(); + assert_ok!(execute(CODE, vec![], &mut mock_ext)); + + assert_eq!( + &mock_ext.code_calls, + &[CallCodeEntry { code_hash: [0x11; 32].into(), data: vec![1, 2, 3, 4] }] + ); + } + #[test] fn contract_call_forward_input() { const CODE: &str = r#" diff --git a/frame/contracts/src/wasm/runtime.rs b/frame/contracts/src/wasm/runtime.rs index 194d5ffbaaf4..55ab0dfa0ade 100644 --- a/frame/contracts/src/wasm/runtime.rs +++ b/frame/contracts/src/wasm/runtime.rs @@ -190,6 +190,9 @@ pub enum RuntimeCosts { Transfer, /// Weight of calling `seal_call` for the given input size. CallBase(u32), + /// Weight of calling `seal_delegate_call` for the given input size. + #[cfg(feature = "unstable-interface")] + DelegateCallBase(u32), /// Weight of the transfer performed during a call. CallSurchargeTransfer, /// Weight of output received through `seal_call` for the given size. @@ -275,6 +278,9 @@ impl RuntimeCosts { s.call.saturating_add(s.call_per_input_byte.saturating_mul(len.into())), CallSurchargeTransfer => s.call_transfer_surcharge, CallCopyOut(len) => s.call_per_output_byte.saturating_mul(len.into()), + #[cfg(feature = "unstable-interface")] + DelegateCallBase(len) => + s.delegate_call.saturating_add(s.call_per_input_byte.saturating_mul(len.into())), InstantiateBase { input_data_len, salt_len } => s .instantiate .saturating_add(s.instantiate_per_input_byte.saturating_mul(input_data_len.into())) @@ -327,7 +333,7 @@ where } bitflags! { - /// Flags used to change the behaviour of `seal_call`. + /// Flags used to change the behaviour of `seal_call` and `seal_delegate_call`. struct CallFlags: u32 { /// Forward the input of current function to the callee. /// @@ -363,10 +369,34 @@ bitflags! { /// Without this flag any reentrancy into the current contract that originates from /// the callee (or any of its callees) is denied. This includes the first callee: /// You cannot call into yourself with this flag set. + /// + /// # Note + /// + /// For `seal_delegate_call` should be always unset, otherwise + /// [`Error::InvalidCallFlags`] is returned. const ALLOW_REENTRY = 0b0000_1000; } } +/// The kind of call that should be performed. +enum CallType { + /// Execute another instantiated contract + Call { callee_ptr: u32, value_ptr: u32, gas: u64 }, + #[cfg(feature = "unstable-interface")] + /// Execute deployed code in the context (storage, account ID, value) of the caller contract + DelegateCall { code_hash_ptr: u32 }, +} + +impl CallType { + fn cost(&self, input_data_len: u32) -> RuntimeCosts { + match self { + CallType::Call { .. } => RuntimeCosts::CallBase(input_data_len), + #[cfg(feature = "unstable-interface")] + CallType::DelegateCall { .. } => RuntimeCosts::DelegateCallBase(input_data_len), + } + } +} + /// This is only appropriate when writing out data of constant size that does not depend on user /// input. In this case the costs for this copy was already charged as part of the token at /// the beginning of the API entry point. @@ -411,7 +441,7 @@ where // The trap was the result of the execution `return` host function. TrapReason::Return(ReturnData { flags, data }) => { let flags = ReturnFlags::from_bits(flags) - .ok_or_else(|| "used reserved bit in return flags")?; + .ok_or_else(|| Error::::InvalidCallFlags)?; Ok(ExecReturnValue { flags, data: Bytes(data) }) }, TrapReason::Termination => @@ -693,18 +723,13 @@ where fn call( &mut self, flags: CallFlags, - callee_ptr: u32, - gas: u64, - value_ptr: u32, + call_type: CallType, input_data_ptr: u32, input_data_len: u32, output_ptr: u32, output_len_ptr: u32, ) -> Result { - self.charge_gas(RuntimeCosts::CallBase(input_data_len))?; - let callee: <::T as frame_system::Config>::AccountId = - self.read_sandbox_memory_as(callee_ptr)?; - let value: BalanceOf<::T> = self.read_sandbox_memory_as(value_ptr)?; + self.charge_gas(call_type.cost(input_data_len))?; let input_data = if flags.contains(CallFlags::CLONE_INPUT) { self.input_data.as_ref().ok_or_else(|| Error::::InputForwarded)?.clone() } else if flags.contains(CallFlags::FORWARD_INPUT) { @@ -712,12 +737,32 @@ where } else { self.read_sandbox_memory(input_data_ptr, input_data_len)? }; - if value > 0u32.into() { - self.charge_gas(RuntimeCosts::CallSurchargeTransfer)?; - } - let ext = &mut self.ext; - let call_outcome = - ext.call(gas, callee, value, input_data, flags.contains(CallFlags::ALLOW_REENTRY)); + + let call_outcome = match call_type { + CallType::Call { callee_ptr, value_ptr, gas } => { + let callee: <::T as frame_system::Config>::AccountId = + self.read_sandbox_memory_as(callee_ptr)?; + let value: BalanceOf<::T> = self.read_sandbox_memory_as(value_ptr)?; + if value > 0u32.into() { + self.charge_gas(RuntimeCosts::CallSurchargeTransfer)?; + } + self.ext.call( + gas, + callee, + value, + input_data, + flags.contains(CallFlags::ALLOW_REENTRY), + ) + }, + #[cfg(feature = "unstable-interface")] + CallType::DelegateCall { code_hash_ptr } => { + if flags.contains(CallFlags::ALLOW_REENTRY) { + return Err(Error::::InvalidCallFlags.into()) + } + let code_hash = self.read_sandbox_memory_as(code_hash_ptr)?; + self.ext.delegate_call(code_hash, input_data) + }, + }; // `TAIL_CALL` only matters on an `OK` result. Otherwise the call stack comes to // a halt anyways without anymore code being executed. @@ -990,9 +1035,7 @@ define_env!(Env, , ) -> ReturnCode => { ctx.call( CallFlags::ALLOW_REENTRY, - callee_ptr, - gas, - value_ptr, + CallType::Call{callee_ptr, value_ptr, gas}, input_data_ptr, input_data_len, output_ptr, @@ -1041,10 +1084,51 @@ define_env!(Env, , output_len_ptr: u32 ) -> ReturnCode => { ctx.call( - CallFlags::from_bits(flags).ok_or_else(|| "used reserved bit in CallFlags")?, - callee_ptr, - gas, - value_ptr, + CallFlags::from_bits(flags).ok_or_else(|| Error::::InvalidCallFlags)?, + CallType::Call{callee_ptr, value_ptr, gas}, + input_data_ptr, + input_data_len, + output_ptr, + output_len_ptr, + ) + }, + + // Execute code in the context (storage, caller, value) of the current contract. + // + // Reentrancy protection is always disabled since the callee is allowed + // to modify the callers storage. This makes going through a reentrancy attack + // unnecessary for the callee when it wants to exploit the caller. + // + // # Parameters + // + // - flags: See [`CallFlags`] for a documentation of the supported flags. + // - code_hash: a pointer to the hash of the code to be called. + // - input_data_ptr: a pointer to a buffer to be used as input data to the callee. + // - input_data_len: length of the input data buffer. + // - output_ptr: a pointer where the output buffer is copied to. + // - output_len_ptr: in-out pointer to where the length of the buffer is read from + // and the actual length is written to. + // + // # Errors + // + // An error means that the call wasn't successful and no output buffer is returned unless + // stated otherwise. + // + // `ReturnCode::CalleeReverted`: Output buffer is returned. + // `ReturnCode::CalleeTrapped` + // `ReturnCode::CodeNotFound` + [__unstable__] seal_delegate_call( + ctx, + flags: u32, + code_hash_ptr: u32, + input_data_ptr: u32, + input_data_len: u32, + output_ptr: u32, + output_len_ptr: u32 + ) -> ReturnCode => { + ctx.call( + CallFlags::from_bits(flags).ok_or_else(|| Error::::InvalidCallFlags)?, + CallType::DelegateCall{code_hash_ptr}, input_data_ptr, input_data_len, output_ptr, diff --git a/frame/contracts/src/weights.rs b/frame/contracts/src/weights.rs index b58660b694ca..ec6dcd2eee89 100644 --- a/frame/contracts/src/weights.rs +++ b/frame/contracts/src/weights.rs @@ -88,6 +88,7 @@ pub trait WeightInfo { fn seal_take_storage_per_kb(n: u32, ) -> Weight; fn seal_transfer(r: u32, ) -> Weight; fn seal_call(r: u32, ) -> Weight; + fn seal_delegate_call(r: u32, ) -> Weight; fn seal_call_per_transfer_input_output_kb(t: u32, i: u32, o: u32, ) -> Weight; fn seal_instantiate(r: u32, ) -> Weight; fn seal_instantiate_per_input_output_salt_kb(i: u32, o: u32, s: u32, ) -> Weight; @@ -618,6 +619,17 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().writes((100 as Weight).saturating_mul(r as Weight))) } // Storage: System Account (r:1 w:0) + // Storage: Contracts ContractInfoOf (r:1 w:1) + // Storage: Contracts CodeStorage (r:1 w:0) + // Storage: Timestamp Now (r:1 w:0) + fn seal_delegate_call(r: u32, ) -> Weight { + (0 as Weight) + // Standard Error: 11_788_000 + .saturating_add((19_855_594_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(T::DbWeight::get().reads((99 as Weight).saturating_mul(r as Weight))) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:101 w:101) // Storage: Contracts CodeStorage (r:2 w:0) // Storage: Timestamp Now (r:1 w:0) @@ -1486,6 +1498,17 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().writes((100 as Weight).saturating_mul(r as Weight))) } // Storage: System Account (r:1 w:0) + // Storage: Contracts ContractInfoOf (r:1 w:1) + // Storage: Contracts CodeStorage (r:1 w:0) + // Storage: Timestamp Now (r:1 w:0) + fn seal_delegate_call(r: u32, ) -> Weight { + (0 as Weight) + // Standard Error: 11_788_000 + .saturating_add((19_855_594_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(RocksDbWeight::get().reads((99 as Weight).saturating_mul(r as Weight))) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:101 w:101) // Storage: Contracts CodeStorage (r:2 w:0) // Storage: Timestamp Now (r:1 w:0) From 1532b72162240edf0d41ecb39e66e2a1f5a73b6f Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Tue, 8 Feb 2022 15:10:35 +0100 Subject: [PATCH 464/695] Add Storage Info to Various Pallets (#10810) * atomic swap * bounties * bounties fmt * gilt * indices * nicks * randomness-collective-flip * recovery * reuse maxapprovals * Update tests.rs * Update frame/randomness-collective-flip/src/lib.rs Co-authored-by: Oliver Tale-Yazdi * use the correct bound * complete recovery * use `bounded_vec` macro * Update tests.rs * transaction payment * uniques * mmr * example offchain worker * beefy-mmr * Update frame/recovery/src/lib.rs Co-authored-by: Oliver Tale-Yazdi * Use BoundedVec instead of a type-parameterized BoundedString * cargo fmt * Update frame/atomic-swap/src/lib.rs * use config const * Update lib.rs * update mel_bound * fmt Co-authored-by: Oliver Tale-Yazdi Co-authored-by: Keith Yeung --- frame/atomic-swap/src/lib.rs | 13 +++-- frame/bags-list/src/list/mod.rs | 4 +- frame/beefy-mmr/src/lib.rs | 1 - frame/bounties/src/lib.rs | 26 ++++----- frame/contracts/src/wasm/mod.rs | 2 +- .../election-provider-multi-phase/src/lib.rs | 2 +- frame/examples/offchain-worker/src/lib.rs | 15 +++--- frame/examples/offchain-worker/src/tests.rs | 1 + frame/gilt/src/lib.rs | 43 ++++++++++----- frame/grandpa/src/lib.rs | 8 +-- frame/identity/src/types.rs | 8 +-- frame/im-online/src/lib.rs | 3 +- frame/indices/src/lib.rs | 4 +- frame/merkle-mountain-range/src/lib.rs | 4 +- frame/nicks/src/lib.rs | 24 ++++++--- frame/randomness-collective-flip/src/lib.rs | 8 ++- frame/recovery/src/lib.rs | 53 ++++++++++++------- frame/recovery/src/mock.rs | 4 +- frame/recovery/src/tests.rs | 16 ++++-- frame/staking/src/lib.rs | 2 +- frame/transaction-payment/src/lib.rs | 5 +- frame/treasury/src/lib.rs | 2 + frame/uniques/src/lib.rs | 11 ++-- frame/uniques/src/types.rs | 17 +++--- primitives/beefy/src/mmr.rs | 4 +- 25 files changed, 165 insertions(+), 115 deletions(-) diff --git a/frame/atomic-swap/src/lib.rs b/frame/atomic-swap/src/lib.rs index e83055b4d283..e57496954a57 100644 --- a/frame/atomic-swap/src/lib.rs +++ b/frame/atomic-swap/src/lib.rs @@ -45,6 +45,7 @@ mod tests; use codec::{Decode, Encode}; use frame_support::{ dispatch::DispatchResult, + pallet_prelude::MaxEncodedLen, traits::{BalanceStatus, Currency, Get, ReservableCurrency}, weights::Weight, RuntimeDebugNoBound, @@ -59,8 +60,9 @@ use sp_std::{ }; /// Pending atomic swap operation. -#[derive(Clone, Eq, PartialEq, RuntimeDebugNoBound, Encode, Decode, TypeInfo)] +#[derive(Clone, Eq, PartialEq, RuntimeDebugNoBound, Encode, Decode, TypeInfo, MaxEncodedLen)] #[scale_info(skip_type_params(T))] +#[codec(mel_bound())] pub struct PendingSwap { /// Source of the swap. pub source: T::AccountId, @@ -93,8 +95,9 @@ pub trait SwapAction { } /// A swap action that only allows transferring balances. -#[derive(Clone, RuntimeDebug, Eq, PartialEq, Encode, Decode, TypeInfo)] +#[derive(Clone, RuntimeDebug, Eq, PartialEq, Encode, Decode, TypeInfo, MaxEncodedLen)] #[scale_info(skip_type_params(C))] +#[codec(mel_bound())] pub struct BalanceSwapAction> { value: >::Balance, _marker: PhantomData, @@ -165,7 +168,7 @@ pub mod pallet { /// The overarching event type. type Event: From> + IsType<::Event>; /// Swap action. - type SwapAction: SwapAction + Parameter; + type SwapAction: SwapAction + Parameter + MaxEncodedLen; /// Limit of proof size. /// /// Atomic swap is only atomic if once the proof is revealed, both parties can submit the @@ -182,7 +185,6 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] - #[pallet::without_storage_info] pub struct Pallet(PhantomData); #[pallet::storage] @@ -193,6 +195,9 @@ pub mod pallet { Blake2_128Concat, HashedProof, PendingSwap, + OptionQuery, + GetDefault, + ConstU32<300_000>, >; #[pallet::error] diff --git a/frame/bags-list/src/list/mod.rs b/frame/bags-list/src/list/mod.rs index aba31b67b286..8cd89b8fff1c 100644 --- a/frame/bags-list/src/list/mod.rs +++ b/frame/bags-list/src/list/mod.rs @@ -545,7 +545,7 @@ impl List { /// iteration so that there's no incentive to churn ids positioning to improve the chances of /// appearing within the ids set. #[derive(DefaultNoBound, Encode, Decode, MaxEncodedLen, TypeInfo)] -#[codec(mel_bound(T: Config))] +#[codec(mel_bound())] #[scale_info(skip_type_params(T))] #[cfg_attr(feature = "std", derive(frame_support::DebugNoBound, Clone, PartialEq))] pub struct Bag { @@ -748,7 +748,7 @@ impl Bag { /// A Node is the fundamental element comprising the doubly-linked list described by `Bag`. #[derive(Encode, Decode, MaxEncodedLen, TypeInfo)] -#[codec(mel_bound(T: Config))] +#[codec(mel_bound())] #[scale_info(skip_type_params(T))] #[cfg_attr(feature = "std", derive(frame_support::DebugNoBound, Clone, PartialEq))] pub struct Node { diff --git a/frame/beefy-mmr/src/lib.rs b/frame/beefy-mmr/src/lib.rs index d66de51d9af2..38d0a6ac9a7f 100644 --- a/frame/beefy-mmr/src/lib.rs +++ b/frame/beefy-mmr/src/lib.rs @@ -119,7 +119,6 @@ pub mod pallet { /// BEEFY-MMR pallet. #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] - #[pallet::without_storage_info] pub struct Pallet(_); /// The module's configuration trait. diff --git a/frame/bounties/src/lib.rs b/frame/bounties/src/lib.rs index d46180f6bbe1..988b15c58a13 100644 --- a/frame/bounties/src/lib.rs +++ b/frame/bounties/src/lib.rs @@ -107,7 +107,7 @@ type PositiveImbalanceOf = pallet_treasury::PositiveImbalanceOf; pub type BountyIndex = u32; /// A bounty proposal. -#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] pub struct Bounty { /// The account proposing it. proposer: AccountId, @@ -133,7 +133,7 @@ impl } /// The status of a bounty proposal. -#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] pub enum BountyStatus { /// The bounty is proposed and waiting for approval. Proposed, @@ -180,7 +180,6 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] - #[pallet::without_storage_info] pub struct Pallet(_); #[pallet::config] @@ -249,6 +248,8 @@ pub mod pallet { Premature, /// The bounty cannot be closed because it has active child-bounties. HasActiveChildBounty, + /// Too many approvals are already queued. + TooManyQueued, } #[pallet::event] @@ -288,12 +289,14 @@ pub mod pallet { /// The description of each bounty. #[pallet::storage] #[pallet::getter(fn bounty_descriptions)] - pub type BountyDescriptions = StorageMap<_, Twox64Concat, BountyIndex, Vec>; + pub type BountyDescriptions = + StorageMap<_, Twox64Concat, BountyIndex, BoundedVec>; /// Bounty indices that have been approved but not yet funded. #[pallet::storage] #[pallet::getter(fn bounty_approvals)] - pub type BountyApprovals = StorageValue<_, Vec, ValueQuery>; + pub type BountyApprovals = + StorageValue<_, BoundedVec, ValueQuery>; #[pallet::call] impl Pallet { @@ -341,7 +344,8 @@ pub mod pallet { bounty.status = BountyStatus::Approved; - BountyApprovals::::append(bounty_id); + BountyApprovals::::try_append(bounty_id) + .map_err(|()| Error::::TooManyQueued)?; Ok(()) })?; @@ -780,17 +784,15 @@ impl Pallet { description: Vec, value: BalanceOf, ) -> DispatchResult { - ensure!( - description.len() <= T::MaximumReasonLength::get() as usize, - Error::::ReasonTooBig - ); + let bounded_description: BoundedVec<_, _> = + description.try_into().map_err(|()| Error::::ReasonTooBig)?; ensure!(value >= T::BountyValueMinimum::get(), Error::::InvalidValue); let index = Self::bounty_count(); // reserve deposit for new bounty let bond = T::BountyDepositBase::get() + - T::DataDepositPerByte::get() * (description.len() as u32).into(); + T::DataDepositPerByte::get() * (bounded_description.len() as u32).into(); T::Currency::reserve(&proposer, bond) .map_err(|_| Error::::InsufficientProposersBalance)?; @@ -806,7 +808,7 @@ impl Pallet { }; Bounties::::insert(index, &bounty); - BountyDescriptions::::insert(index, description); + BountyDescriptions::::insert(index, bounded_description); Self::deposit_event(Event::::BountyProposed { index }); diff --git a/frame/contracts/src/wasm/mod.rs b/frame/contracts/src/wasm/mod.rs index 3be1062ce969..491daa58523e 100644 --- a/frame/contracts/src/wasm/mod.rs +++ b/frame/contracts/src/wasm/mod.rs @@ -87,7 +87,7 @@ pub struct PrefabWasmModule { /// /// It is stored in a separate storage entry to avoid loading the code when not necessary. #[derive(Clone, Encode, Decode, scale_info::TypeInfo, MaxEncodedLen)] -#[codec(mel_bound(T: Config))] +#[codec(mel_bound())] #[scale_info(skip_type_params(T))] pub struct OwnerInfo { /// The account that has deployed the contract and hence is allowed to remove it. diff --git a/frame/election-provider-multi-phase/src/lib.rs b/frame/election-provider-multi-phase/src/lib.rs index a5ed593e1a4e..cad3d12605e4 100644 --- a/frame/election-provider-multi-phase/src/lib.rs +++ b/frame/election-provider-multi-phase/src/lib.rs @@ -460,7 +460,7 @@ pub struct ReadySolution { /// /// These are stored together because they are often accessed together. #[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, Default, TypeInfo)] -#[codec(mel_bound(T: Config))] +#[codec(mel_bound())] #[scale_info(skip_type_params(T))] pub struct RoundSnapshot { /// All of the voters. diff --git a/frame/examples/offchain-worker/src/lib.rs b/frame/examples/offchain-worker/src/lib.rs index 08f449f8d51d..3cf718217b06 100644 --- a/frame/examples/offchain-worker/src/lib.rs +++ b/frame/examples/offchain-worker/src/lib.rs @@ -154,11 +154,14 @@ pub mod pallet { /// multiple pallets send unsigned transactions. #[pallet::constant] type UnsignedPriority: Get; + + /// Maximum number of prices. + #[pallet::constant] + type MaxPrices: Get; } #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] - #[pallet::without_storage_info] pub struct Pallet(_); #[pallet::hooks] @@ -330,7 +333,7 @@ pub mod pallet { /// This is used to calculate average price, should have bounded size. #[pallet::storage] #[pallet::getter(fn prices)] - pub(super) type Prices = StorageValue<_, Vec, ValueQuery>; + pub(super) type Prices = StorageValue<_, BoundedVec, ValueQuery>; /// Defines the block when next unsigned transaction will be accepted. /// @@ -645,12 +648,8 @@ impl Pallet { fn add_price(maybe_who: Option, price: u32) { log::info!("Adding to the average: {}", price); >::mutate(|prices| { - const MAX_LEN: usize = 64; - - if prices.len() < MAX_LEN { - prices.push(price); - } else { - prices[price as usize % MAX_LEN] = price; + if prices.try_push(price).is_err() { + prices[(price % T::MaxPrices::get()) as usize] = price; } }); diff --git a/frame/examples/offchain-worker/src/tests.rs b/frame/examples/offchain-worker/src/tests.rs index 76f80deb12f9..e5bd9fabc629 100644 --- a/frame/examples/offchain-worker/src/tests.rs +++ b/frame/examples/offchain-worker/src/tests.rs @@ -123,6 +123,7 @@ impl Config for Test { type GracePeriod = ConstU64<5>; type UnsignedInterval = ConstU64<128>; type UnsignedPriority = UnsignedPriority; + type MaxPrices = ConstU32<64>; } fn test_pub() -> sp_core::sr25519::Public { diff --git a/frame/gilt/src/lib.rs b/frame/gilt/src/lib.rs index ac56dc108b2f..8956e04857f2 100644 --- a/frame/gilt/src/lib.rs +++ b/frame/gilt/src/lib.rs @@ -112,7 +112,8 @@ pub mod pallet { + sp_std::fmt::Debug + Default + From - + TypeInfo; + + TypeInfo + + MaxEncodedLen; /// Origin required for setting the target proportion to be under gilt. type AdminOrigin: EnsureOrigin; @@ -178,11 +179,12 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] - #[pallet::without_storage_info] pub struct Pallet(_); /// A single bid on a gilt, an item of a *queue* in `Queues`. - #[derive(Clone, Eq, PartialEq, Default, Encode, Decode, RuntimeDebug, TypeInfo)] + #[derive( + Clone, Eq, PartialEq, Default, Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen, + )] pub struct GiltBid { /// The amount bid. pub amount: Balance, @@ -191,7 +193,9 @@ pub mod pallet { } /// Information representing an active gilt. - #[derive(Clone, Eq, PartialEq, Default, Encode, Decode, RuntimeDebug, TypeInfo)] + #[derive( + Clone, Eq, PartialEq, Default, Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen, + )] pub struct ActiveGilt { /// The proportion of the effective total issuance (i.e. accounting for any eventual gilt /// expansion or contraction that may eventually be claimed). @@ -215,7 +219,9 @@ pub mod pallet { /// `issuance - frozen + proportion * issuance` /// /// where `issuance = total_issuance - IgnoredIssuance` - #[derive(Clone, Eq, PartialEq, Default, Encode, Decode, RuntimeDebug, TypeInfo)] + #[derive( + Clone, Eq, PartialEq, Default, Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen, + )] pub struct ActiveGiltsTotal { /// The total amount of funds held in reserve for all active gilts. pub frozen: Balance, @@ -233,12 +239,18 @@ pub mod pallet { /// The vector is indexed by duration in `Period`s, offset by one, so information on the queue /// whose duration is one `Period` would be storage `0`. #[pallet::storage] - pub type QueueTotals = StorageValue<_, Vec<(u32, BalanceOf)>, ValueQuery>; + pub type QueueTotals = + StorageValue<_, BoundedVec<(u32, BalanceOf), T::QueueCount>, ValueQuery>; /// The queues of bids ready to become gilts. Indexed by duration (in `Period`s). #[pallet::storage] - pub type Queues = - StorageMap<_, Blake2_128Concat, u32, Vec, T::AccountId>>, ValueQuery>; + pub type Queues = StorageMap< + _, + Blake2_128Concat, + u32, + BoundedVec, T::AccountId>, T::MaxQueueLen>, + ValueQuery, + >; /// Information relating to the gilts currently active. #[pallet::storage] @@ -265,7 +277,11 @@ pub mod pallet { #[pallet::genesis_build] impl GenesisBuild for GenesisConfig { fn build(&self) { - QueueTotals::::put(vec![(0, BalanceOf::::zero()); T::QueueCount::get() as usize]); + let unbounded = vec![(0, BalanceOf::::zero()); T::QueueCount::get() as usize]; + let bounded: BoundedVec<_, _> = unbounded + .try_into() + .expect("QueueTotals should support up to QueueCount items. qed"); + QueueTotals::::put(bounded); } } @@ -366,7 +382,7 @@ pub mod pallet { T::Currency::unreserve(&bid.who, bid.amount); (0, amount - bid.amount) } else { - q.insert(0, bid); + q.try_insert(0, bid).expect("verified queue was not full above. qed."); (1, amount) }; @@ -379,7 +395,7 @@ pub mod pallet { }, )?; QueueTotals::::mutate(|qs| { - qs.resize(queue_count, (0, Zero::zero())); + qs.bounded_resize(queue_count, (0, Zero::zero())); qs[queue_index].0 += net.0; qs[queue_index].1 = qs[queue_index].1.saturating_add(net.1); }); @@ -415,7 +431,7 @@ pub mod pallet { })?; QueueTotals::::mutate(|qs| { - qs.resize(queue_count, (0, Zero::zero())); + qs.bounded_resize(queue_count, (0, Zero::zero())); qs[queue_index].0 = new_len; qs[queue_index].1 = qs[queue_index].1.saturating_sub(bid.amount); }); @@ -592,7 +608,8 @@ pub mod pallet { if remaining < bid.amount { let overflow = bid.amount - remaining; bid.amount = remaining; - q.push(GiltBid { amount: overflow, who: bid.who.clone() }); + q.try_push(GiltBid { amount: overflow, who: bid.who.clone() }) + .expect("just popped, so there must be space. qed"); } let amount = bid.amount; // Can never overflow due to block above. diff --git a/frame/grandpa/src/lib.rs b/frame/grandpa/src/lib.rs index 0aaf0f679ce1..68d4cf26a2e2 100644 --- a/frame/grandpa/src/lib.rs +++ b/frame/grandpa/src/lib.rs @@ -364,13 +364,9 @@ pub type BoundedAuthorityList = WeakBoundedVec<(AuthorityId, AuthorityWei /// A stored pending change. /// `Limit` is the bound for `next_authorities` #[derive(Encode, Decode, TypeInfo, MaxEncodedLen)] -#[codec(mel_bound(Limit: Get))] +#[codec(mel_bound(N: MaxEncodedLen, Limit: Get))] #[scale_info(skip_type_params(Limit))] -pub struct StoredPendingChange -where - Limit: Get, - N: MaxEncodedLen, -{ +pub struct StoredPendingChange { /// The block number this was scheduled at. pub scheduled_at: N, /// The delay in blocks until it will be applied. diff --git a/frame/identity/src/types.rs b/frame/identity/src/types.rs index d91adc8cdd76..cb79ace98d81 100644 --- a/frame/identity/src/types.rs +++ b/frame/identity/src/types.rs @@ -283,7 +283,7 @@ impl TypeInfo for IdentityFields { #[derive( CloneNoBound, Encode, Decode, Eq, MaxEncodedLen, PartialEqNoBound, RuntimeDebugNoBound, TypeInfo, )] -#[codec(mel_bound(FieldLimit: Get))] +#[codec(mel_bound())] #[cfg_attr(test, derive(frame_support::DefaultNoBound))] #[scale_info(skip_type_params(FieldLimit))] pub struct IdentityInfo> { @@ -339,11 +339,7 @@ pub struct IdentityInfo> { #[derive( CloneNoBound, Encode, Eq, MaxEncodedLen, PartialEqNoBound, RuntimeDebugNoBound, TypeInfo, )] -#[codec(mel_bound( - Balance: Encode + Decode + MaxEncodedLen + Copy + Clone + Debug + Eq + PartialEq + Zero + Add, - MaxJudgements: Get, - MaxAdditionalFields: Get, -))] +#[codec(mel_bound())] #[scale_info(skip_type_params(MaxJudgements, MaxAdditionalFields))] pub struct Registration< Balance: Encode + Decode + MaxEncodedLen + Copy + Clone + Debug + Eq + PartialEq, diff --git a/frame/im-online/src/lib.rs b/frame/im-online/src/lib.rs index 5ad27850a2c1..e2213ef4169b 100644 --- a/frame/im-online/src/lib.rs +++ b/frame/im-online/src/lib.rs @@ -238,8 +238,7 @@ where /// `MultiAddrEncodingLimit` represents the size limit of the encoding of `MultiAddr` /// `AddressesLimit` represents the size limit of the vector of peers connected #[derive(Clone, Eq, PartialEq, Encode, Decode, MaxEncodedLen, TypeInfo)] -#[codec(mel_bound(PeerIdEncodingLimit: Get, - MultiAddrEncodingLimit: Get, AddressesLimit: Get))] +#[codec(mel_bound())] #[scale_info(skip_type_params(PeerIdEncodingLimit, MultiAddrEncodingLimit, AddressesLimit))] pub struct BoundedOpaqueNetworkState where diff --git a/frame/indices/src/lib.rs b/frame/indices/src/lib.rs index 7d23fa5e8c7f..9c9e3580f2c0 100644 --- a/frame/indices/src/lib.rs +++ b/frame/indices/src/lib.rs @@ -56,7 +56,8 @@ pub mod pallet { + Codec + Default + AtLeast32Bit - + Copy; + + Copy + + MaxEncodedLen; /// The currency trait. type Currency: ReservableCurrency; @@ -74,7 +75,6 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] - #[pallet::without_storage_info] pub struct Pallet(PhantomData); #[pallet::call] diff --git a/frame/merkle-mountain-range/src/lib.rs b/frame/merkle-mountain-range/src/lib.rs index 2a93dc7af289..f904428e0204 100644 --- a/frame/merkle-mountain-range/src/lib.rs +++ b/frame/merkle-mountain-range/src/lib.rs @@ -84,7 +84,6 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] - #[pallet::without_storage_info] pub struct Pallet(PhantomData<(T, I)>); /// This pallet's configuration trait @@ -126,7 +125,8 @@ pub mod pallet { + Default + codec::Codec + codec::EncodeLike - + scale_info::TypeInfo; + + scale_info::TypeInfo + + MaxEncodedLen; /// Data stored in the leaf nodes. /// diff --git a/frame/nicks/src/lib.rs b/frame/nicks/src/lib.rs index 9e4ecf8b2b1a..c7c2c675bc01 100644 --- a/frame/nicks/src/lib.rs +++ b/frame/nicks/src/lib.rs @@ -110,11 +110,10 @@ pub mod pallet { /// The lookup table for names. #[pallet::storage] pub(super) type NameOf = - StorageMap<_, Twox64Concat, T::AccountId, (Vec, BalanceOf)>; + StorageMap<_, Twox64Concat, T::AccountId, (BoundedVec, BalanceOf)>; #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] - #[pallet::without_storage_info] pub struct Pallet(_); #[pallet::call] @@ -139,8 +138,9 @@ pub mod pallet { pub fn set_name(origin: OriginFor, name: Vec) -> DispatchResult { let sender = ensure_signed(origin)?; - ensure!(name.len() >= T::MinLength::get() as usize, Error::::TooShort); - ensure!(name.len() <= T::MaxLength::get() as usize, Error::::TooLong); + let bounded_name: BoundedVec<_, _> = + name.try_into().map_err(|()| Error::::TooLong)?; + ensure!(bounded_name.len() >= T::MinLength::get() as usize, Error::::TooShort); let deposit = if let Some((_, deposit)) = >::get(&sender) { Self::deposit_event(Event::::NameChanged { who: sender.clone() }); @@ -152,7 +152,7 @@ pub mod pallet { deposit }; - >::insert(&sender, (name, deposit)); + >::insert(&sender, (bounded_name, deposit)); Ok(()) } @@ -230,9 +230,11 @@ pub mod pallet { ) -> DispatchResult { T::ForceOrigin::ensure_origin(origin)?; + let bounded_name: BoundedVec<_, _> = + name.try_into().map_err(|()| Error::::TooLong)?; let target = T::Lookup::lookup(target)?; let deposit = >::get(&target).map(|x| x.1).unwrap_or_else(Zero::zero); - >::insert(&target, (name, deposit)); + >::insert(&target, (bounded_name, deposit)); Self::deposit_event(Event::::NameForced { target }); Ok(()) @@ -356,9 +358,15 @@ mod tests { assert_ok!(Nicks::set_name(Origin::signed(2), b"Dave".to_vec())); assert_eq!(Balances::reserved_balance(2), 2); - assert_ok!(Nicks::force_name(Origin::signed(1), 2, b"Dr. David Brubeck, III".to_vec())); + assert_noop!( + Nicks::force_name(Origin::signed(1), 2, b"Dr. David Brubeck, III".to_vec()), + Error::::TooLong, + ); + assert_ok!(Nicks::force_name(Origin::signed(1), 2, b"Dr. Brubeck, III".to_vec())); assert_eq!(Balances::reserved_balance(2), 2); - assert_eq!(>::get(2).unwrap(), (b"Dr. David Brubeck, III".to_vec(), 2)); + let (name, amount) = >::get(2).unwrap(); + assert_eq!(name, b"Dr. Brubeck, III".to_vec()); + assert_eq!(amount, 2); }); } diff --git a/frame/randomness-collective-flip/src/lib.rs b/frame/randomness-collective-flip/src/lib.rs index a74c58405de4..b72aa665550c 100644 --- a/frame/randomness-collective-flip/src/lib.rs +++ b/frame/randomness-collective-flip/src/lib.rs @@ -91,7 +91,6 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] - #[pallet::without_storage_info] pub struct Pallet(_); #[pallet::config] @@ -103,9 +102,7 @@ pub mod pallet { let parent_hash = >::parent_hash(); >::mutate(|ref mut values| { - if values.len() < RANDOM_MATERIAL_LEN as usize { - values.push(parent_hash) - } else { + if values.try_push(parent_hash).is_err() { let index = block_number_to_index::(block_number); values[index] = parent_hash; } @@ -120,7 +117,8 @@ pub mod pallet { /// the oldest hash. #[pallet::storage] #[pallet::getter(fn random_material)] - pub(super) type RandomMaterial = StorageValue<_, Vec, ValueQuery>; + pub(super) type RandomMaterial = + StorageValue<_, BoundedVec>, ValueQuery>; } impl Randomness for Pallet { diff --git a/frame/recovery/src/lib.rs b/frame/recovery/src/lib.rs index f5a57843a983..adc5c0b895c5 100644 --- a/frame/recovery/src/lib.rs +++ b/frame/recovery/src/lib.rs @@ -154,7 +154,7 @@ // Ensure we're `no_std` when compiling for Wasm. #![cfg_attr(not(feature = "std"), no_std)] -use codec::{Decode, Encode}; +use codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; use sp_runtime::traits::{CheckedAdd, CheckedMul, Dispatchable, SaturatedConversion}; use sp_std::prelude::*; @@ -163,7 +163,7 @@ use frame_support::{ dispatch::PostDispatchInfo, traits::{BalanceStatus, Currency, ReservableCurrency}, weights::GetDispatchInfo, - RuntimeDebug, + BoundedVec, RuntimeDebug, }; pub use pallet::*; @@ -176,21 +176,23 @@ mod tests; type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; +type FriendsOf = BoundedVec<::AccountId, ::MaxFriends>; + /// An active recovery process. -#[derive(Clone, Eq, PartialEq, Encode, Decode, Default, RuntimeDebug, TypeInfo)] -pub struct ActiveRecovery { +#[derive(Clone, Eq, PartialEq, Encode, Decode, Default, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub struct ActiveRecovery { /// The block number when the recovery process started. created: BlockNumber, /// The amount held in reserve of the `depositor`, /// To be returned once this recovery process is closed. deposit: Balance, /// The friends which have vouched so far. Always sorted. - friends: Vec, + friends: Friends, } /// Configuration for recovering an account. -#[derive(Clone, Eq, PartialEq, Encode, Decode, Default, RuntimeDebug, TypeInfo)] -pub struct RecoveryConfig { +#[derive(Clone, Eq, PartialEq, Encode, Decode, Default, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub struct RecoveryConfig { /// The minimum number of blocks since the start of the recovery process before the account /// can be recovered. delay_period: BlockNumber, @@ -198,7 +200,7 @@ pub struct RecoveryConfig { /// to be returned once this configuration is removed. deposit: Balance, /// The list of friends which can help recover an account. Always sorted. - friends: Vec, + friends: Friends, /// The number of approving friends needed to recover an account. threshold: u16, } @@ -212,7 +214,6 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] - #[pallet::without_storage_info] pub struct Pallet(_); /// Configuration trait. @@ -245,8 +246,13 @@ pub mod pallet { type FriendDepositFactor: Get>; /// The maximum amount of friends allowed in a recovery configuration. + /// + /// NOTE: The threshold programmed in this Pallet uses u16, so it does + /// not really make sense to have a limit here greater than u16::MAX. + /// But also, that is a lot more than you should probably set this value + /// to anyway... #[pallet::constant] - type MaxFriends: Get; + type MaxFriends: Get; /// The base amount of currency needed to reserve for starting a recovery. /// @@ -324,7 +330,7 @@ pub mod pallet { _, Twox64Concat, T::AccountId, - RecoveryConfig, T::AccountId>, + RecoveryConfig, FriendsOf>, >; /// Active recovery attempts. @@ -339,7 +345,7 @@ pub mod pallet { T::AccountId, Twox64Concat, T::AccountId, - ActiveRecovery, T::AccountId>, + ActiveRecovery, FriendsOf>, >; /// The list of allowed proxy accounts. @@ -458,12 +464,12 @@ pub mod pallet { ensure!(threshold >= 1, Error::::ZeroThreshold); ensure!(!friends.is_empty(), Error::::NotEnoughFriends); ensure!(threshold as usize <= friends.len(), Error::::NotEnoughFriends); - let max_friends = T::MaxFriends::get() as usize; - ensure!(friends.len() <= max_friends, Error::::MaxFriends); - ensure!(Self::is_sorted_and_unique(&friends), Error::::NotSorted); + let bounded_friends: FriendsOf = + friends.try_into().map_err(|()| Error::::MaxFriends)?; + ensure!(Self::is_sorted_and_unique(&bounded_friends), Error::::NotSorted); // Total deposit is base fee + number of friends * factor fee let friend_deposit = T::FriendDepositFactor::get() - .checked_mul(&friends.len().saturated_into()) + .checked_mul(&bounded_friends.len().saturated_into()) .ok_or(ArithmeticError::Overflow)?; let total_deposit = T::ConfigDepositBase::get() .checked_add(&friend_deposit) @@ -471,8 +477,12 @@ pub mod pallet { // Reserve the deposit T::Currency::reserve(&who, total_deposit)?; // Create the recovery configuration - let recovery_config = - RecoveryConfig { delay_period, deposit: total_deposit, friends, threshold }; + let recovery_config = RecoveryConfig { + delay_period, + deposit: total_deposit, + friends: bounded_friends, + threshold, + }; // Create the recovery configuration storage item >::insert(&who, recovery_config); @@ -519,7 +529,7 @@ pub mod pallet { let recovery_status = ActiveRecovery { created: >::block_number(), deposit: recovery_deposit, - friends: vec![], + friends: Default::default(), }; // Create the active recovery storage item >::insert(&account, &who, recovery_status); @@ -571,7 +581,10 @@ pub mod pallet { // Either insert the vouch, or return an error that the user already vouched. match active_recovery.friends.binary_search(&who) { Ok(_pos) => Err(Error::::AlreadyVouched)?, - Err(pos) => active_recovery.friends.insert(pos, who.clone()), + Err(pos) => active_recovery + .friends + .try_insert(pos, who.clone()) + .map_err(|()| Error::::MaxFriends)?, } // Update storage with the latest details >::insert(&lost, &rescuer, active_recovery); diff --git a/frame/recovery/src/mock.rs b/frame/recovery/src/mock.rs index 577aa7dee711..2088f9eb0937 100644 --- a/frame/recovery/src/mock.rs +++ b/frame/recovery/src/mock.rs @@ -22,7 +22,7 @@ use super::*; use crate as recovery; use frame_support::{ parameter_types, - traits::{ConstU16, ConstU32, ConstU64, OnFinalize, OnInitialize}, + traits::{ConstU32, ConstU64, OnFinalize, OnInitialize}, }; use sp_core::H256; use sp_runtime::{ @@ -105,7 +105,7 @@ impl Config for Test { type Currency = Balances; type ConfigDepositBase = ConfigDepositBase; type FriendDepositFactor = FriendDepositFactor; - type MaxFriends = ConstU16<3>; + type MaxFriends = ConstU32<3>; type RecoveryDeposit = RecoveryDeposit; } diff --git a/frame/recovery/src/tests.rs b/frame/recovery/src/tests.rs index 7d1da6353a3a..16fc678d357b 100644 --- a/frame/recovery/src/tests.rs +++ b/frame/recovery/src/tests.rs @@ -18,7 +18,7 @@ //! Tests for the module. use super::*; -use frame_support::{assert_noop, assert_ok, traits::Currency}; +use frame_support::{assert_noop, assert_ok, bounded_vec, traits::Currency}; use mock::{ new_test_ext, run_to_block, Balances, BalancesCall, Call, Origin, Recovery, RecoveryCall, Test, }; @@ -201,8 +201,12 @@ fn create_recovery_works() { // Base 10 + 1 per friends = 13 total reserved assert_eq!(Balances::reserved_balance(5), 13); // Recovery configuration is correctly stored - let recovery_config = - RecoveryConfig { delay_period, deposit: 13, friends: friends.clone(), threshold }; + let recovery_config = RecoveryConfig { + delay_period, + deposit: 13, + friends: friends.try_into().unwrap(), + threshold, + }; assert_eq!(Recovery::recovery_config(5), Some(recovery_config)); }); } @@ -254,7 +258,8 @@ fn initiate_recovery_works() { // Deposit is reserved assert_eq!(Balances::reserved_balance(1), 10); // Recovery status object is created correctly - let recovery_status = ActiveRecovery { created: 0, deposit: 10, friends: vec![] }; + let recovery_status = + ActiveRecovery { created: 0, deposit: 10, friends: Default::default() }; assert_eq!(>::get(&5, &1), Some(recovery_status)); // Multiple users can attempt to recover the same account assert_ok!(Recovery::initiate_recovery(Origin::signed(2), 5)); @@ -314,7 +319,8 @@ fn vouch_recovery_works() { assert_ok!(Recovery::vouch_recovery(Origin::signed(4), 5, 1)); assert_ok!(Recovery::vouch_recovery(Origin::signed(3), 5, 1)); // Final recovery status object is updated correctly - let recovery_status = ActiveRecovery { created: 0, deposit: 10, friends: vec![2, 3, 4] }; + let recovery_status = + ActiveRecovery { created: 0, deposit: 10, friends: bounded_vec![2, 3, 4] }; assert_eq!(>::get(&5, &1), Some(recovery_status)); }); } diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index f1d4cd1e07c2..17af4829c0ea 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -576,7 +576,7 @@ where /// A record of the nominations made by a specific account. #[derive(PartialEqNoBound, EqNoBound, Clone, Encode, Decode, RuntimeDebugNoBound, TypeInfo)] -#[codec(mel_bound(T: Config))] +#[codec(mel_bound())] #[scale_info(skip_type_params(T))] pub struct Nominations { /// The targets of nomination. diff --git a/frame/transaction-payment/src/lib.rs b/frame/transaction-payment/src/lib.rs index 16d2ff5827c4..e4d77a05f284 100644 --- a/frame/transaction-payment/src/lib.rs +++ b/frame/transaction-payment/src/lib.rs @@ -47,7 +47,7 @@ #![cfg_attr(not(feature = "std"), no_std)] -use codec::{Decode, Encode}; +use codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; use sp_runtime::{ @@ -226,7 +226,7 @@ where } /// Storage releases of the pallet. -#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo)] +#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] enum Releases { /// Original version of the pallet. V1Ancient, @@ -248,7 +248,6 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] - #[pallet::without_storage_info] pub struct Pallet(_); #[pallet::config] diff --git a/frame/treasury/src/lib.rs b/frame/treasury/src/lib.rs index 762c0e592d89..81fca5243afa 100644 --- a/frame/treasury/src/lib.rs +++ b/frame/treasury/src/lib.rs @@ -193,6 +193,8 @@ pub mod pallet { type SpendFunds: SpendFunds; /// The maximum number of approvals that can wait in the spending queue. + /// + /// NOTE: This parameter is also used within the Bounties Pallet extension if enabled. #[pallet::constant] type MaxApprovals: Get; } diff --git a/frame/uniques/src/lib.rs b/frame/uniques/src/lib.rs index 3a0b34e5bf40..2956735e5ec3 100644 --- a/frame/uniques/src/lib.rs +++ b/frame/uniques/src/lib.rs @@ -62,7 +62,6 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] - #[pallet::without_storage_info] pub struct Pallet(_); #[pallet::config] @@ -72,10 +71,16 @@ pub mod pallet { type Event: From> + IsType<::Event>; /// Identifier for the class of asset. - type ClassId: Member + Parameter + Default + Copy + HasCompact; + type ClassId: Member + Parameter + Default + Copy + HasCompact + MaxEncodedLen; /// The type used to identify a unique asset within an asset class. - type InstanceId: Member + Parameter + Default + Copy + HasCompact + From; + type InstanceId: Member + + Parameter + + Default + + Copy + + HasCompact + + From + + MaxEncodedLen; /// The currency mechanism, used for paying for reserves. type Currency: ReservableCurrency; diff --git a/frame/uniques/src/types.rs b/frame/uniques/src/types.rs index 4d1afe694bd8..b5aee6912fec 100644 --- a/frame/uniques/src/types.rs +++ b/frame/uniques/src/types.rs @@ -18,7 +18,10 @@ //! Various basic types for use in the assets pallet. use super::*; -use frame_support::{traits::Get, BoundedVec}; +use frame_support::{ + pallet_prelude::{BoundedVec, MaxEncodedLen}, + traits::Get, +}; use scale_info::TypeInfo; pub(super) type DepositBalanceOf = @@ -28,7 +31,7 @@ pub(super) type ClassDetailsFor = pub(super) type InstanceDetailsFor = InstanceDetails<::AccountId, DepositBalanceOf>; -#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo)] +#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)] pub struct ClassDetails { /// Can change `owner`, `issuer`, `freezer` and `admin` accounts. pub(super) owner: AccountId, @@ -54,7 +57,7 @@ pub struct ClassDetails { } /// Witness data for the destroy transactions. -#[derive(Copy, Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo)] +#[derive(Copy, Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)] pub struct DestroyWitness { /// The total number of outstanding instances of this asset class. #[codec(compact)] @@ -78,7 +81,7 @@ impl ClassDetails { } /// Information concerning the ownership of a single unique asset. -#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, Default, TypeInfo)] +#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, Default, TypeInfo, MaxEncodedLen)] pub struct InstanceDetails { /// The owner of this asset. pub(super) owner: AccountId, @@ -91,8 +94,9 @@ pub struct InstanceDetails { pub(super) deposit: DepositBalance, } -#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, Default, TypeInfo)] +#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, Default, TypeInfo, MaxEncodedLen)] #[scale_info(skip_type_params(StringLimit))] +#[codec(mel_bound(DepositBalance: MaxEncodedLen))] pub struct ClassMetadata> { /// The balance deposited for this metadata. /// @@ -106,8 +110,9 @@ pub struct ClassMetadata> { pub(super) is_frozen: bool, } -#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, Default, TypeInfo)] +#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, Default, TypeInfo, MaxEncodedLen)] #[scale_info(skip_type_params(StringLimit))] +#[codec(mel_bound(DepositBalance: MaxEncodedLen))] pub struct InstanceMetadata> { /// The balance deposited for this metadata. /// diff --git a/primitives/beefy/src/mmr.rs b/primitives/beefy/src/mmr.rs index 215214bef294..29f513629d01 100644 --- a/primitives/beefy/src/mmr.rs +++ b/primitives/beefy/src/mmr.rs @@ -26,7 +26,7 @@ //! but we imagine they will be useful for other chains that either want to bridge with Polkadot //! or are completely standalone, but heavily inspired by Polkadot. -use codec::{Decode, Encode}; +use codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; /// A standard leaf that gets added every block to the MMR constructed by Substrate's `pallet_mmr`. @@ -81,7 +81,7 @@ impl MmrLeafVersion { } /// Details of the next BEEFY authority set. -#[derive(Debug, Default, PartialEq, Eq, Clone, Encode, Decode, TypeInfo)] +#[derive(Debug, Default, PartialEq, Eq, Clone, Encode, Decode, TypeInfo, MaxEncodedLen)] pub struct BeefyNextAuthoritySet { /// Id of the next set. /// From 8c4002f330f0be837040960409e65bb49f81bee8 Mon Sep 17 00:00:00 2001 From: S E R A Y A Date: Tue, 8 Feb 2022 15:24:20 +0100 Subject: [PATCH 465/695] fixed regression in inline docs (#10819) --- frame/nicks/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frame/nicks/src/lib.rs b/frame/nicks/src/lib.rs index c7c2c675bc01..632ff7b0a808 100644 --- a/frame/nicks/src/lib.rs +++ b/frame/nicks/src/lib.rs @@ -181,7 +181,7 @@ pub mod pallet { /// Remove an account's name and take charge of the deposit. /// - /// Fails if `who` has not been named. The deposit is dealt with through `T::Slashed` + /// Fails if `target` has not been named. The deposit is dealt with through `T::Slashed` /// imbalance handler. /// /// The dispatch origin for this call must match `T::ForceOrigin`. From 9b5b5721a1952c0fe2ef2465eb4dd1085b7edf8e Mon Sep 17 00:00:00 2001 From: Zeke Mostov Date: Tue, 8 Feb 2022 11:05:34 -0800 Subject: [PATCH 466/695] try-runtime-cli: Add to docs (#10822) * try-runtime-cli: Add to docs of pre/post hooks * Add note about --ws-max-out-buffer-capacity 1000 --- utils/frame/try-runtime/cli/src/lib.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/utils/frame/try-runtime/cli/src/lib.rs b/utils/frame/try-runtime/cli/src/lib.rs index 9a016b2e5369..4c7103328851 100644 --- a/utils/frame/try-runtime/cli/src/lib.rs +++ b/utils/frame/try-runtime/cli/src/lib.rs @@ -113,6 +113,8 @@ //! well with try-runtime's expensive RPC queries: //! //! - set `--rpc-max-payload 1000` to ensure large RPC queries can work. +//! - set `--ws-max-out-buffer-capacity 1000` to ensure the websocket connection can handle large +//! RPC queries. //! - set `--rpc-cors all` to ensure ws connections can come through. //! //! Note that *none* of the try-runtime operations need unsafe RPCs. @@ -141,7 +143,9 @@ //! //! These hooks allow you to execute some code, only within the `on-runtime-upgrade` command, before //! and after the migration. If any data needs to be temporarily stored between the pre/post -//! migration hooks, `OnRuntimeUpgradeHelpersExt` can help with that. +//! migration hooks, `OnRuntimeUpgradeHelpersExt` can help with that. Note that you should be +//! mindful with any mutable storage ops in the pre/post migration checks, as you almost certainly +//! will not want to mutate any of the storage that is to be migrated. //! //! #### Logging //! From 4eb7758750fd47bc9da194ee30a7eaf941f99360 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 8 Feb 2022 19:27:08 +0000 Subject: [PATCH 467/695] Bump serde from 1.0.132 to 1.0.136 (#10816) Bumps [serde](https://github.com/serde-rs/serde) from 1.0.132 to 1.0.136. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.132...v1.0.136) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- bin/node/bench/Cargo.toml | 2 +- bin/node/cli/Cargo.toml | 2 +- client/beefy/rpc/Cargo.toml | 2 +- client/chain-spec/Cargo.toml | 2 +- client/cli/Cargo.toml | 2 +- client/consensus/babe/Cargo.toml | 2 +- client/consensus/babe/rpc/Cargo.toml | 2 +- client/network/Cargo.toml | 2 +- client/rpc-api/Cargo.toml | 2 +- client/service/Cargo.toml | 2 +- client/sync-state-rpc/Cargo.toml | 2 +- client/telemetry/Cargo.toml | 2 +- client/tracing/Cargo.toml | 2 +- client/transaction-pool/Cargo.toml | 2 +- client/transaction-pool/api/Cargo.toml | 2 +- frame/beefy-mmr/Cargo.toml | 2 +- frame/beefy/Cargo.toml | 2 +- frame/benchmarking/Cargo.toml | 2 +- frame/conviction-voting/Cargo.toml | 2 +- frame/democracy/Cargo.toml | 2 +- frame/merkle-mountain-range/primitives/Cargo.toml | 2 +- frame/merkle-mountain-range/rpc/Cargo.toml | 2 +- frame/offences/Cargo.toml | 2 +- frame/referenda/Cargo.toml | 2 +- frame/staking/Cargo.toml | 2 +- frame/support/Cargo.toml | 2 +- frame/support/test/Cargo.toml | 2 +- frame/system/Cargo.toml | 2 +- frame/tips/Cargo.toml | 2 +- frame/transaction-payment/Cargo.toml | 2 +- frame/transaction-payment/asset-tx-payment/Cargo.toml | 2 +- frame/transaction-storage/Cargo.toml | 2 +- frame/treasury/Cargo.toml | 2 +- primitives/application-crypto/Cargo.toml | 2 +- primitives/arithmetic/Cargo.toml | 2 +- primitives/consensus/babe/Cargo.toml | 2 +- primitives/core/Cargo.toml | 2 +- primitives/finality-grandpa/Cargo.toml | 2 +- primitives/npos-elections/Cargo.toml | 2 +- primitives/rpc/Cargo.toml | 2 +- primitives/runtime/Cargo.toml | 2 +- primitives/serializer/Cargo.toml | 2 +- primitives/storage/Cargo.toml | 2 +- primitives/test-primitives/Cargo.toml | 2 +- primitives/version/Cargo.toml | 2 +- test-utils/client/Cargo.toml | 2 +- test-utils/runtime/Cargo.toml | 2 +- utils/frame/benchmarking-cli/Cargo.toml | 2 +- utils/frame/remote-externalities/Cargo.toml | 2 +- utils/frame/try-runtime/cli/Cargo.toml | 2 +- 51 files changed, 54 insertions(+), 54 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 553da394386c..feb721e6092c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9104,9 +9104,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.132" +version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9875c23cf305cd1fd7eb77234cbb705f21ea6a72c637a5c6db5fe4b8e7f008" +checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" dependencies = [ "serde_derive", ] @@ -9132,9 +9132,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.132" +version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc0db5cb2556c0e558887d9bbdcf6ac4471e83ff66cf696e5419024d1606276" +checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" dependencies = [ "proc-macro2", "quote", diff --git a/bin/node/bench/Cargo.toml b/bin/node/bench/Cargo.toml index 9939f188d5d8..18951179235c 100644 --- a/bin/node/bench/Cargo.toml +++ b/bin/node/bench/Cargo.toml @@ -17,7 +17,7 @@ node-runtime = { version = "3.0.0-dev", path = "../runtime" } sc-client-api = { version = "4.0.0-dev", path = "../../../client/api/" } sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } sp-state-machine = { version = "0.11.0", path = "../../../primitives/state-machine" } -serde = "1.0.132" +serde = "1.0.136" serde_json = "1.0.74" derive_more = "0.99.16" kvdb = "0.10.0" diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index 211311c3dac2..4b14fe31e5a5 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -36,7 +36,7 @@ crate-type = ["cdylib", "rlib"] # third-party dependencies clap = { version = "3.0", features = ["derive"], optional = true } codec = { package = "parity-scale-codec", version = "2.0.0" } -serde = { version = "1.0.132", features = ["derive"] } +serde = { version = "1.0.136", features = ["derive"] } futures = "0.3.16" hex-literal = "0.3.4" log = "0.4.8" diff --git a/client/beefy/rpc/Cargo.toml b/client/beefy/rpc/Cargo.toml index 4a300b26e123..44837fb0e41f 100644 --- a/client/beefy/rpc/Cargo.toml +++ b/client/beefy/rpc/Cargo.toml @@ -12,7 +12,7 @@ futures = "0.3.16" log = "0.4" parking_lot = "0.11" thiserror = "1.0" -serde = { version = "1.0.132", features = ["derive"] } +serde = { version = "1.0.136", features = ["derive"] } jsonrpc-core = "18.0.0" jsonrpc-core-client = "18.0.0" diff --git a/client/chain-spec/Cargo.toml b/client/chain-spec/Cargo.toml index d103c2414331..9b299f00a214 100644 --- a/client/chain-spec/Cargo.toml +++ b/client/chain-spec/Cargo.toml @@ -17,7 +17,7 @@ sc-chain-spec-derive = { version = "4.0.0-dev", path = "./derive" } impl-trait-for-tuples = "0.2.1" sc-network = { version = "0.10.0-dev", path = "../network" } sp-core = { version = "5.0.0", path = "../../primitives/core" } -serde = { version = "1.0.132", features = ["derive"] } +serde = { version = "1.0.136", features = ["derive"] } serde_json = "1.0.74" sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } sc-telemetry = { version = "4.0.0-dev", path = "../telemetry" } diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index f7af649d3bf3..5375400056fa 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -24,7 +24,7 @@ names = { version = "0.12.0", default-features = false } rand = "0.7.3" regex = "1.5.4" rpassword = "5.0.0" -serde = "1.0.132" +serde = "1.0.136" serde_json = "1.0.74" thiserror = "1.0.30" tiny-bip39 = "0.8.2" diff --git a/client/consensus/babe/Cargo.toml b/client/consensus/babe/Cargo.toml index 79cb3a52038a..76ec6a25879f 100644 --- a/client/consensus/babe/Cargo.toml +++ b/client/consensus/babe/Cargo.toml @@ -25,7 +25,7 @@ sp-keystore = { version = "0.11.0", path = "../../../primitives/keystore" } num-bigint = "0.2.3" num-rational = "0.2.2" num-traits = "0.2.8" -serde = { version = "1.0.132", features = ["derive"] } +serde = { version = "1.0.136", features = ["derive"] } sp-version = { version = "4.0.0-dev", path = "../../../primitives/version" } sp-io = { version = "5.0.0", path = "../../../primitives/io" } sp-inherents = { version = "4.0.0-dev", path = "../../../primitives/inherents" } diff --git a/client/consensus/babe/rpc/Cargo.toml b/client/consensus/babe/rpc/Cargo.toml index 56276f07dcde..8ceada5fe1f1 100644 --- a/client/consensus/babe/rpc/Cargo.toml +++ b/client/consensus/babe/rpc/Cargo.toml @@ -19,7 +19,7 @@ jsonrpc-core = "18.0.0" jsonrpc-core-client = "18.0.0" jsonrpc-derive = "18.0.0" sp-consensus-babe = { version = "0.10.0-dev", path = "../../../../primitives/consensus/babe" } -serde = { version = "1.0.132", features = ["derive"] } +serde = { version = "1.0.136", features = ["derive"] } sp-blockchain = { version = "4.0.0-dev", path = "../../../../primitives/blockchain" } sp-runtime = { version = "5.0.0", path = "../../../../primitives/runtime" } sc-consensus-epochs = { version = "0.10.0-dev", path = "../../epochs" } diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index fa1cc715e151..86a038028047 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -45,7 +45,7 @@ rand = "0.7.2" sc-block-builder = { version = "0.10.0-dev", path = "../block-builder" } sc-client-api = { version = "4.0.0-dev", path = "../api" } sc-peerset = { version = "4.0.0-dev", path = "../peerset" } -serde = { version = "1.0.132", features = ["derive"] } +serde = { version = "1.0.136", features = ["derive"] } serde_json = "1.0.74" smallvec = "1.7.0" sp-arithmetic = { version = "4.0.0", path = "../../primitives/arithmetic" } diff --git a/client/rpc-api/Cargo.toml b/client/rpc-api/Cargo.toml index 8b8b70b9747c..00b2fa787ca6 100644 --- a/client/rpc-api/Cargo.toml +++ b/client/rpc-api/Cargo.toml @@ -27,7 +27,7 @@ sp-core = { version = "5.0.0", path = "../../primitives/core" } sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } sc-chain-spec = { path = "../chain-spec", version = "4.0.0-dev" } -serde = { version = "1.0.132", features = ["derive"] } +serde = { version = "1.0.136", features = ["derive"] } serde_json = "1.0.74" sc-transaction-pool-api = { version = "4.0.0-dev", path = "../transaction-pool/api" } sp-rpc = { version = "5.0.0", path = "../../primitives/rpc" } diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index fb6c4a083761..8424fe31a810 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -33,7 +33,7 @@ futures-timer = "3.0.1" exit-future = "0.2.0" pin-project = "1.0.10" hash-db = "0.15.2" -serde = "1.0.132" +serde = "1.0.136" serde_json = "1.0.74" sc-keystore = { version = "4.0.0-dev", path = "../keystore" } sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } diff --git a/client/sync-state-rpc/Cargo.toml b/client/sync-state-rpc/Cargo.toml index eab6ffa88f15..b413446c321f 100644 --- a/client/sync-state-rpc/Cargo.toml +++ b/client/sync-state-rpc/Cargo.toml @@ -24,7 +24,7 @@ sc-consensus-epochs = { version = "0.10.0-dev", path = "../consensus/epochs" } sc-finality-grandpa = { version = "0.10.0-dev", path = "../finality-grandpa" } sc-rpc-api = { version = "0.10.0-dev", path = "../rpc-api" } serde_json = "1.0.74" -serde = { version = "1.0.132", features = ["derive"] } +serde = { version = "1.0.136", features = ["derive"] } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } codec = { package = "parity-scale-codec", version = "2.0.0" } diff --git a/client/telemetry/Cargo.toml b/client/telemetry/Cargo.toml index 2417f3c77b76..595a57402159 100644 --- a/client/telemetry/Cargo.toml +++ b/client/telemetry/Cargo.toml @@ -22,7 +22,7 @@ libp2p = { version = "0.40.0", default-features = false, features = ["dns-async- log = "0.4.8" pin-project = "1.0.10" rand = "0.7.2" -serde = { version = "1.0.132", features = ["derive"] } +serde = { version = "1.0.136", features = ["derive"] } serde_json = "1.0.74" chrono = "0.4.19" thiserror = "1.0.30" diff --git a/client/tracing/Cargo.toml b/client/tracing/Cargo.toml index b8910199c0ee..5f7e0831a536 100644 --- a/client/tracing/Cargo.toml +++ b/client/tracing/Cargo.toml @@ -23,7 +23,7 @@ once_cell = "1.8.0" parking_lot = "0.11.2" regex = "1.5.4" rustc-hash = "1.1.0" -serde = "1.0.132" +serde = "1.0.136" thiserror = "1.0.30" tracing = "0.1.29" tracing-log = "0.1.2" diff --git a/client/transaction-pool/Cargo.toml b/client/transaction-pool/Cargo.toml index 06fc8298f01c..42172ce723e1 100644 --- a/client/transaction-pool/Cargo.toml +++ b/client/transaction-pool/Cargo.toml @@ -30,7 +30,7 @@ sp-transaction-pool = { version = "4.0.0-dev", path = "../../primitives/transact sc-transaction-pool-api = { version = "4.0.0-dev", path = "./api" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sc-utils = { version = "4.0.0-dev", path = "../utils" } -serde = { version = "1.0.132", features = ["derive"] } +serde = { version = "1.0.136", features = ["derive"] } linked-hash-map = "0.5.4" retain_mut = "0.1.4" diff --git a/client/transaction-pool/api/Cargo.toml b/client/transaction-pool/api/Cargo.toml index 9d7e6ea5e0f8..70f18c345e05 100644 --- a/client/transaction-pool/api/Cargo.toml +++ b/client/transaction-pool/api/Cargo.toml @@ -11,7 +11,7 @@ description = "Transaction pool client facing API." [dependencies] futures = "0.3.1" log = "0.4.8" -serde = { version = "1.0.132", features = ["derive"] } +serde = { version = "1.0.136", features = ["derive"] } thiserror = "1.0.30" sp-runtime = { version = "5.0.0", default-features = false, path = "../../../primitives/runtime" } diff --git a/frame/beefy-mmr/Cargo.toml b/frame/beefy-mmr/Cargo.toml index cfd18b26f9c7..f381d4c97577 100644 --- a/frame/beefy-mmr/Cargo.toml +++ b/frame/beefy-mmr/Cargo.toml @@ -13,7 +13,7 @@ codec = { version = "2.2.0", package = "parity-scale-codec", default-features = libsecp256k1 = { version = "0.7.0", default-features = false } log = { version = "0.4.13", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -serde = { version = "1.0.132", optional = true } +serde = { version = "1.0.136", optional = true } frame-support = { version = "4.0.0-dev", path = "../support", default-features = false } frame-system = { version = "4.0.0-dev", path = "../system", default-features = false } diff --git a/frame/beefy/Cargo.toml b/frame/beefy/Cargo.toml index 13ccfb938010..5844657dd50c 100644 --- a/frame/beefy/Cargo.toml +++ b/frame/beefy/Cargo.toml @@ -10,7 +10,7 @@ description = "BEEFY FRAME pallet" [dependencies] codec = { version = "2.2.0", package = "parity-scale-codec", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -serde = { version = "1.0.132", optional = true } +serde = { version = "1.0.136", optional = true } frame-support = { version = "4.0.0-dev", path = "../support", default-features = false } frame-system = { version = "4.0.0-dev", path = "../system", default-features = false } diff --git a/frame/benchmarking/Cargo.toml b/frame/benchmarking/Cargo.toml index 0283b3f7c948..ad6f99c64517 100644 --- a/frame/benchmarking/Cargo.toml +++ b/frame/benchmarking/Cargo.toml @@ -27,7 +27,7 @@ sp-storage = { version = "5.0.0", path = "../../primitives/storage", default-fea frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } log = { version = "0.4.14", default-features = false } -serde = { version = "1.0.132", optional = true } +serde = { version = "1.0.136", optional = true } [dev-dependencies] hex-literal = "0.3.4" diff --git a/frame/conviction-voting/Cargo.toml b/frame/conviction-voting/Cargo.toml index ab62065c1c54..7b51e3f8c91a 100644 --- a/frame/conviction-voting/Cargo.toml +++ b/frame/conviction-voting/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -serde = { version = "1.0.126", optional = true, features = ["derive"] } +serde = { version = "1.0.136", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ "derive", ] } diff --git a/frame/democracy/Cargo.toml b/frame/democracy/Cargo.toml index 125decaca824..743cea074ee2 100644 --- a/frame/democracy/Cargo.toml +++ b/frame/democracy/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -serde = { version = "1.0.132", optional = true, features = ["derive"] } +serde = { version = "1.0.136", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ "derive", ] } diff --git a/frame/merkle-mountain-range/primitives/Cargo.toml b/frame/merkle-mountain-range/primitives/Cargo.toml index 9df5094abd81..d281f159beba 100644 --- a/frame/merkle-mountain-range/primitives/Cargo.toml +++ b/frame/merkle-mountain-range/primitives/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } log = { version = "0.4.14", default-features = false } -serde = { version = "1.0.132", optional = true, features = ["derive"] } +serde = { version = "1.0.136", optional = true, features = ["derive"] } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/api" } sp-core = { version = "5.0.0", default-features = false, path = "../../../primitives/core" } diff --git a/frame/merkle-mountain-range/rpc/Cargo.toml b/frame/merkle-mountain-range/rpc/Cargo.toml index 575b2a79fcd2..7dc891267ceb 100644 --- a/frame/merkle-mountain-range/rpc/Cargo.toml +++ b/frame/merkle-mountain-range/rpc/Cargo.toml @@ -17,7 +17,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0" } jsonrpc-core = "18.0.0" jsonrpc-core-client = "18.0.0" jsonrpc-derive = "18.0.0" -serde = { version = "1.0.132", features = ["derive"] } +serde = { version = "1.0.136", features = ["derive"] } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } diff --git a/frame/offences/Cargo.toml b/frame/offences/Cargo.toml index 6fe36aea89ee..053708c8b247 100644 --- a/frame/offences/Cargo.toml +++ b/frame/offences/Cargo.toml @@ -17,7 +17,7 @@ pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -serde = { version = "1.0.132", optional = true } +serde = { version = "1.0.136", optional = true } sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/frame/referenda/Cargo.toml b/frame/referenda/Cargo.toml index e979f2b0c4a3..46ede8c1eed0 100644 --- a/frame/referenda/Cargo.toml +++ b/frame/referenda/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -serde = { version = "1.0.126", optional = true, features = ["derive"] } +serde = { version = "1.0.136", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ "derive", ] } diff --git a/frame/staking/Cargo.toml b/frame/staking/Cargo.toml index cd1e238dbd01..363ffe4428fb 100644 --- a/frame/staking/Cargo.toml +++ b/frame/staking/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -serde = { version = "1.0.132", optional = true } +serde = { version = "1.0.136", optional = true } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ "derive", ] } diff --git a/frame/support/Cargo.toml b/frame/support/Cargo.toml index 5e8c26b6ae54..a5ba2fad18b3 100644 --- a/frame/support/Cargo.toml +++ b/frame/support/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -serde = { version = "1.0.132", optional = true, features = ["derive"] } +serde = { version = "1.0.136", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } frame-metadata = { version = "14.2.0", default-features = false, features = ["v14"] } diff --git a/frame/support/test/Cargo.toml b/frame/support/test/Cargo.toml index 5a27f4f46e10..9f26df4869af 100644 --- a/frame/support/test/Cargo.toml +++ b/frame/support/test/Cargo.toml @@ -12,7 +12,7 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -serde = { version = "1.0.132", default-features = false, features = ["derive"] } +serde = { version = "1.0.136", default-features = false, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-arithmetic = { version = "4.0.0", default-features = false, path = "../../../primitives/arithmetic" } diff --git a/frame/system/Cargo.toml b/frame/system/Cargo.toml index f1e7e4e20755..5d45544fe7bb 100644 --- a/frame/system/Cargo.toml +++ b/frame/system/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -serde = { version = "1.0.132", optional = true, features = ["derive"] } +serde = { version = "1.0.136", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } diff --git a/frame/tips/Cargo.toml b/frame/tips/Cargo.toml index 182a87048d35..f898a255b87c 100644 --- a/frame/tips/Cargo.toml +++ b/frame/tips/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } log = { version = "0.4.0", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -serde = { version = "1.0.132", features = ["derive"], optional = true } +serde = { version = "1.0.136", features = ["derive"], optional = true } sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } diff --git a/frame/transaction-payment/Cargo.toml b/frame/transaction-payment/Cargo.toml index b9b46380a386..1f27e355b1d9 100644 --- a/frame/transaction-payment/Cargo.toml +++ b/frame/transaction-payment/Cargo.toml @@ -17,7 +17,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = "derive", ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -serde = { version = "1.0.132", optional = true } +serde = { version = "1.0.136", optional = true } smallvec = "1.7.0" sp-core = { version = "5.0.0", path = "../../primitives/core", default-features = false } diff --git a/frame/transaction-payment/asset-tx-payment/Cargo.toml b/frame/transaction-payment/asset-tx-payment/Cargo.toml index 300d05d0ed9a..6f42595d200c 100644 --- a/frame/transaction-payment/asset-tx-payment/Cargo.toml +++ b/frame/transaction-payment/asset-tx-payment/Cargo.toml @@ -26,7 +26,7 @@ pallet-transaction-payment = { version = "4.0.0-dev", default-features = false, # Other dependencies codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -serde = { version = "1.0.132", optional = true } +serde = { version = "1.0.136", optional = true } [dev-dependencies] smallvec = "1.7.0" diff --git a/frame/transaction-storage/Cargo.toml b/frame/transaction-storage/Cargo.toml index 5adf5fd2c1f0..f33607058f37 100644 --- a/frame/transaction-storage/Cargo.toml +++ b/frame/transaction-storage/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -serde = { version = "1.0.132", optional = true } +serde = { version = "1.0.136", optional = true } hex-literal = { version = "0.3.4", optional = true } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } diff --git a/frame/treasury/Cargo.toml b/frame/treasury/Cargo.toml index d126d0ffa34b..a7a210457f02 100644 --- a/frame/treasury/Cargo.toml +++ b/frame/treasury/Cargo.toml @@ -18,7 +18,7 @@ codec = { package = "parity-scale-codec", version = "2.2.0", default-features = "max-encoded-len", ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -serde = { version = "1.0.132", features = ["derive"], optional = true } +serde = { version = "1.0.136", features = ["derive"], optional = true } impl-trait-for-tuples = "0.2.1" sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } diff --git a/primitives/application-crypto/Cargo.toml b/primitives/application-crypto/Cargo.toml index a3dfa8646e79..818ddbdcc182 100644 --- a/primitives/application-crypto/Cargo.toml +++ b/primitives/application-crypto/Cargo.toml @@ -18,7 +18,7 @@ targets = ["x86_64-unknown-linux-gnu"] sp-core = { version = "5.0.0", default-features = false, path = "../core" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -serde = { version = "1.0.132", optional = true, features = ["derive"] } +serde = { version = "1.0.136", optional = true, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-io = { version = "5.0.0", default-features = false, path = "../io" } diff --git a/primitives/arithmetic/Cargo.toml b/primitives/arithmetic/Cargo.toml index b1ec8639248e..e3294ff74985 100644 --- a/primitives/arithmetic/Cargo.toml +++ b/primitives/arithmetic/Cargo.toml @@ -23,7 +23,7 @@ integer-sqrt = "0.1.2" static_assertions = "1.1.0" num-traits = { version = "0.2.8", default-features = false } sp-std = { version = "4.0.0", default-features = false, path = "../std" } -serde = { version = "1.0.132", optional = true, features = ["derive"] } +serde = { version = "1.0.136", optional = true, features = ["derive"] } sp-debug-derive = { version = "4.0.0", default-features = false, path = "../debug-derive" } [dev-dependencies] diff --git a/primitives/consensus/babe/Cargo.toml b/primitives/consensus/babe/Cargo.toml index b114d182c730..b677f4470284 100644 --- a/primitives/consensus/babe/Cargo.toml +++ b/primitives/consensus/babe/Cargo.toml @@ -27,7 +27,7 @@ sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../ sp-keystore = { version = "0.11.0", default-features = false, path = "../../keystore", optional = true } sp-runtime = { version = "5.0.0", default-features = false, path = "../../runtime" } sp-timestamp = { version = "4.0.0-dev", path = "../../timestamp", optional = true } -serde = { version = "1.0.132", features = ["derive"], optional = true } +serde = { version = "1.0.136", features = ["derive"], optional = true } async-trait = { version = "0.1.50", optional = true } [features] diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index 90138ded4cb1..bd41635a1d7a 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -19,7 +19,7 @@ codec = { package = "parity-scale-codec", version = "2.2.0", default-features = ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } log = { version = "0.4.11", default-features = false } -serde = { version = "1.0.132", optional = true, features = ["derive"] } +serde = { version = "1.0.136", optional = true, features = ["derive"] } byteorder = { version = "1.3.2", default-features = false } primitive-types = { version = "0.10.1", default-features = false, features = ["codec", "scale-info"] } impl-serde = { version = "0.3.0", optional = true } diff --git a/primitives/finality-grandpa/Cargo.toml b/primitives/finality-grandpa/Cargo.toml index bb0b8b8509ac..a05636d44a56 100644 --- a/primitives/finality-grandpa/Cargo.toml +++ b/primitives/finality-grandpa/Cargo.toml @@ -19,7 +19,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } grandpa = { package = "finality-grandpa", version = "0.14.1", default-features = false, features = ["derive-codec"] } log = { version = "0.4.8", optional = true } -serde = { version = "1.0.132", optional = true, features = ["derive"] } +serde = { version = "1.0.136", optional = true, features = ["derive"] } sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } sp-application-crypto = { version = "5.0.0", default-features = false, path = "../application-crypto" } sp-core = { version = "5.0.0", default-features = false, path = "../core" } diff --git a/primitives/npos-elections/Cargo.toml b/primitives/npos-elections/Cargo.toml index f392895a945e..88475e10f732 100644 --- a/primitives/npos-elections/Cargo.toml +++ b/primitives/npos-elections/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -serde = { version = "1.0.132", optional = true, features = ["derive"] } +serde = { version = "1.0.136", optional = true, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-npos-elections-solution-type = { version = "4.0.0-dev", path = "./solution-type" } sp-arithmetic = { version = "4.0.0", default-features = false, path = "../arithmetic" } diff --git a/primitives/rpc/Cargo.toml b/primitives/rpc/Cargo.toml index 137be2c6eee2..240b74baf474 100644 --- a/primitives/rpc/Cargo.toml +++ b/primitives/rpc/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -serde = { version = "1.0.132", features = ["derive"] } +serde = { version = "1.0.136", features = ["derive"] } sp-core = { version = "5.0.0", path = "../core" } rustc-hash = "1.1.0" diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 4f793c8faa94..7b58482b2c36 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] -serde = { version = "1.0.132", optional = true, features = ["derive"] } +serde = { version = "1.0.136", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-core = { version = "5.0.0", default-features = false, path = "../core" } diff --git a/primitives/serializer/Cargo.toml b/primitives/serializer/Cargo.toml index a0413164eb57..6a9fb5d90ddb 100644 --- a/primitives/serializer/Cargo.toml +++ b/primitives/serializer/Cargo.toml @@ -14,5 +14,5 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -serde = "1.0.132" +serde = "1.0.136" serde_json = "1.0.74" diff --git a/primitives/storage/Cargo.toml b/primitives/storage/Cargo.toml index d3c22ce70651..7d1a8c03c0a0 100644 --- a/primitives/storage/Cargo.toml +++ b/primitives/storage/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-std = { version = "4.0.0", default-features = false, path = "../std" } -serde = { version = "1.0.132", optional = true, features = ["derive"] } +serde = { version = "1.0.136", optional = true, features = ["derive"] } impl-serde = { version = "0.3.1", optional = true } ref-cast = "1.0.0" sp-debug-derive = { version = "4.0.0", default-features = false, path = "../debug-derive" } diff --git a/primitives/test-primitives/Cargo.toml b/primitives/test-primitives/Cargo.toml index 41fd6173cd8a..101a9249bf70 100644 --- a/primitives/test-primitives/Cargo.toml +++ b/primitives/test-primitives/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] sp-application-crypto = { version = "5.0.0", default-features = false, path = "../application-crypto" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } sp-core = { version = "5.0.0", default-features = false, path = "../core" } -serde = { version = "1.0.132", optional = true, features = ["derive"] } +serde = { version = "1.0.136", optional = true, features = ["derive"] } sp-runtime = { version = "5.0.0", default-features = false, path = "../runtime" } parity-util-mem = { version = "0.10.2", default-features = false, features = ["primitive-types"] } diff --git a/primitives/version/Cargo.toml b/primitives/version/Cargo.toml index 48091ba709cb..053ba49fd82f 100644 --- a/primitives/version/Cargo.toml +++ b/primitives/version/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] impl-serde = { version = "0.3.1", optional = true } -serde = { version = "1.0.132", optional = true, features = ["derive"] } +serde = { version = "1.0.136", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../std" } diff --git a/test-utils/client/Cargo.toml b/test-utils/client/Cargo.toml index 640623aba6aa..a74d7b583527 100644 --- a/test-utils/client/Cargo.toml +++ b/test-utils/client/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0" } futures = "0.3.16" hex = "0.4" -serde = "1.0.132" +serde = "1.0.136" serde_json = "1.0.74" sc-client-api = { version = "4.0.0-dev", path = "../../client/api" } sc-client-db = { version = "0.10.0-dev", features = [ diff --git a/test-utils/runtime/Cargo.toml b/test-utils/runtime/Cargo.toml index 2a9fcaf32426..6529fa71106e 100644 --- a/test-utils/runtime/Cargo.toml +++ b/test-utils/runtime/Cargo.toml @@ -48,7 +48,7 @@ sp-externalities = { version = "0.11.0", default-features = false, path = "../.. # 3rd party cfg-if = "1.0" log = { version = "0.4.14", default-features = false } -serde = { version = "1.0.132", optional = true, features = ["derive"] } +serde = { version = "1.0.136", optional = true, features = ["derive"] } [dev-dependencies] sc-block-builder = { version = "0.10.0-dev", path = "../../client/block-builder" } diff --git a/utils/frame/benchmarking-cli/Cargo.toml b/utils/frame/benchmarking-cli/Cargo.toml index 03a625a155dc..9e2de0e8c358 100644 --- a/utils/frame/benchmarking-cli/Cargo.toml +++ b/utils/frame/benchmarking-cli/Cargo.toml @@ -27,7 +27,7 @@ sp-state-machine = { version = "0.11.0", path = "../../../primitives/state-machi codec = { version = "2.0.0", package = "parity-scale-codec" } clap = { version = "3.0", features = ["derive"] } chrono = "0.4" -serde = "1.0.132" +serde = "1.0.136" serde_json = "1.0.74" handlebars = "4.1.6" Inflector = "0.11.4" diff --git a/utils/frame/remote-externalities/Cargo.toml b/utils/frame/remote-externalities/Cargo.toml index c1d6f1b1c5f5..cf8a0f606987 100644 --- a/utils/frame/remote-externalities/Cargo.toml +++ b/utils/frame/remote-externalities/Cargo.toml @@ -20,7 +20,7 @@ frame-support = { path = "../../../frame/support", optional = true, version = "4 log = "0.4.11" codec = { package = "parity-scale-codec", version = "2.0.0" } serde_json = "1.0" -serde = "1.0.132" +serde = "1.0.136" sp-io = { version = "5.0.0", path = "../../../primitives/io" } sp-core = { version = "5.0.0", path = "../../../primitives/core" } diff --git a/utils/frame/try-runtime/cli/Cargo.toml b/utils/frame/try-runtime/cli/Cargo.toml index 541706257ba1..12380e2d3272 100644 --- a/utils/frame/try-runtime/cli/Cargo.toml +++ b/utils/frame/try-runtime/cli/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] clap = { version = "3.0", features = ["derive"] } log = "0.4.8" parity-scale-codec = { version = "2.3.1" } -serde = "1.0.132" +serde = "1.0.136" zstd = "0.9.0" sc-service = { version = "0.10.0-dev", default-features = false, path = "../../../../client/service" } From 934e0c07fd72f185a8f2a5d7866c4e6f02dbbac3 Mon Sep 17 00:00:00 2001 From: driemworks Date: Tue, 8 Feb 2022 21:28:29 -0500 Subject: [PATCH 468/695] uodate tests, ipfs tests failing --- .../pallets/iris-session/src/tests.rs | 34 +++++++++++------- client/offchain/src/api.rs | 2 +- client/service/src/task_manager/tests.rs | 36 +++++++++---------- primitives/runtime/src/offchain/ipfs.rs | 4 +-- 4 files changed, 42 insertions(+), 34 deletions(-) diff --git a/bin/node-template/pallets/iris-session/src/tests.rs b/bin/node-template/pallets/iris-session/src/tests.rs index 4748fdf1fc9c..8c8c06946898 100644 --- a/bin/node-template/pallets/iris-session/src/tests.rs +++ b/bin/node-template/pallets/iris-session/src/tests.rs @@ -58,20 +58,28 @@ fn iris_session_add_validator_updates_validators_list() { }); } -// #[test] -// fn iris_session_remove_validator_updates_validators_list() { -// new_test_ext().execute_with(|| { -// assert_ok!(ValidatorSet::remove_validator(Origin::root(), 2)); -// assert_eq!(ValidatorSet::validators(), vec![1u64, 3u64]); -// }); -// } +#[test] +fn iris_session_remove_validator_updates_validators_list() { + let V0: (sp_core::sr25519::Public, UintAuthorityId) = ( + sp_core::sr25519::Pair::generate_with_phrase(Some("0")).0.public(), + UintAuthorityId(0) + ); + let V2: (sp_core::sr25519::Public, UintAuthorityId) = ( + sp_core::sr25519::Pair::generate_with_phrase(Some("2")).0.public(), + UintAuthorityId(2) + ); + new_test_ext().execute_with(|| { + assert_ok!(crate::ValidatorSet::remove_validator(Origin::root(), 2)); + assert_eq!(crate::ValidatorSet::validators(), vec![V0.0, V2.0]); + }); +} -// #[test] -// fn iris_session_add_validator_fails_with_invalid_origin() { -// new_test_ext().execute_with(|| { -// assert_noop!(ValidatorSet::add_validator(Origin::signed(1), 4), DispatchError::BadOrigin); -// }); -// } +#[test] +fn iris_session_add_validator_fails_with_invalid_origin() { + new_test_ext().execute_with(|| { + assert_noop!(crate::ValidatorSet::add_validator(Origin::signed(1), 4), DispatchError::BadOrigin); + }); +} // #[test] // fn iris_session_remove_validator_fails_with_invalid_origin() { diff --git a/client/offchain/src/api.rs b/client/offchain/src/api.rs index 94c5d87ac89c..5f5b2a91cf51 100644 --- a/client/offchain/src/api.rs +++ b/client/offchain/src/api.rs @@ -374,7 +374,7 @@ mod tests { } } - fn offchain_api() -> (Api, AsyncApi) { + fn offchain_api() -> (Api, AsyncApi) { sp_tracing::try_init_simple(); let mock = Arc::new(TestNetwork()); let shared_client = SharedClient::new(); diff --git a/client/service/src/task_manager/tests.rs b/client/service/src/task_manager/tests.rs index 400b1f24356c..d84cf59c78f0 100644 --- a/client/service/src/task_manager/tests.rs +++ b/client/service/src/task_manager/tests.rs @@ -1,25 +1,25 @@ -// This file is part of Substrate. +// // This file is part of Substrate. -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 +// // Copyright (C) 2020-2021 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 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. +// // 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 . +// // You should have received a copy of the GNU General Public License +// // along with this program. If not, see . -use crate::task_manager::TaskManager; -use futures::{future::FutureExt, pin_mut, select}; -use parking_lot::Mutex; -use std::{any::Any, sync::Arc, time::Duration}; +// use crate::task_manager::TaskManager; +// use futures::{future::FutureExt, pin_mut, select}; +// use parking_lot::Mutex; +// use std::{any::Any, sync::Arc, time::Duration}; #[derive(Clone, Debug)] struct DropTester(Arc>); @@ -85,7 +85,7 @@ async fn run_background_task_blocking(duration: Duration, _keep_alive: impl Any) } fn new_task_manager(tokio_handle: tokio::runtime::Handle) -> TaskManager { - TaskManager::new(tokio_handle, None, None).unwrap() + TaskManager::new(tokio_handle, None).unwrap() } #[test] diff --git a/primitives/runtime/src/offchain/ipfs.rs b/primitives/runtime/src/offchain/ipfs.rs index e132187fad84..7ad81abe0aa6 100644 --- a/primitives/runtime/src/offchain/ipfs.rs +++ b/primitives/runtime/src/offchain/ipfs.rs @@ -147,7 +147,7 @@ mod tests { use super::*; use sp_io::TestExternalities; use sp_core::offchain::{ - OffchainExt, + OffchainWorkerExt, testing, }; @@ -155,7 +155,7 @@ mod tests { fn basic_metadata_request_and_response() { let (offchain, _state) = testing::TestOffchainExt::new(); let mut t = TestExternalities::default(); - t.register_extension(OffchainExt::new(offchain)); + t.register_extension(OffchainWorkerExt::new(offchain)); t.execute_with(|| { let identity_request = PendingRequest::new(IpfsRequest::Identity).unwrap(); From 8a1b8701cbbae1528681d02e73f684db42dbc3d0 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Wed, 9 Feb 2022 09:37:43 +0100 Subject: [PATCH 469/695] --dev implies --tmp (#10828) --- bin/node-template/README.md | 6 +++--- frame/contracts/README.md | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bin/node-template/README.md b/bin/node-template/README.md index a04f6a12ed73..52b117b8a782 100644 --- a/bin/node-template/README.md +++ b/bin/node-template/README.md @@ -26,7 +26,7 @@ First, complete the [basic Rust setup instructions](./docs/rust-setup.md). Use Rust's native `cargo` command to build and launch the template node: ```sh -cargo run --release -- --dev --tmp +cargo run --release -- --dev ``` ### Build @@ -78,12 +78,12 @@ RUST_BACKTRACE=1 ./target/release/node-template -ldebug --dev > [genesis state](https://github.com/substrate-developer-hub/substrate-node-template/blob/main/node/src/chain_spec.rs#L49). > At the same time the following accounts will be pre-funded: > - Alice -> - Bob +> - Bob > - Alice//stash > - Bob//stash In case of being interested in maintaining the chain' state between runs a base path must be added -so the db can be stored in the provided folder instead of a temporal one. We could use this folder +so the db can be stored in the provided folder instead of a temporal one. We could use this folder to store different chain databases, as a different folder will be created per different chain that is ran. The following commands shows how to use a newly created folder as our db base path. diff --git a/frame/contracts/README.md b/frame/contracts/README.md index 50e43ddb998a..8a8e4918f2e4 100644 --- a/frame/contracts/README.md +++ b/frame/contracts/README.md @@ -101,7 +101,7 @@ by block production. A good starting point for observing them on the console is command line in the root directory of the substrate repository: ```bash -cargo run --release -- --dev --tmp -lerror,runtime::contracts=debug +cargo run --release -- --dev -lerror,runtime::contracts=debug ``` This raises the log level of `runtime::contracts` to `debug` and all other targets From e9d79daaa782f41680ada04719151371a737c6fb Mon Sep 17 00:00:00 2001 From: Koute Date: Wed, 9 Feb 2022 18:12:55 +0900 Subject: [PATCH 470/695] Add a new host function for reporting fatal errors; make WASM backtraces readable when printing out errors (#10741) * Add a new host function for reporting fatal errors * Fix one of the wasmtime executor tests * Have `#[runtime_interface(wasm_only)]` actually mean WASM-only, and not no_std-only * Print out errors through `Display` instead of `Debug` * Switch one more trait to require `Error` for its error instead of only `Debug` * Align to review comments --- client/authority-discovery/src/error.rs | 2 +- client/authority-discovery/src/worker.rs | 8 +- client/beefy/src/worker.rs | 2 +- client/consensus/aura/src/import_queue.rs | 4 +- client/consensus/babe/rpc/src/lib.rs | 4 +- client/consensus/babe/src/lib.rs | 18 ++-- client/consensus/common/src/import_queue.rs | 17 +++- .../common/src/import_queue/basic_queue.rs | 4 +- .../manual-seal/src/consensus/babe.rs | 2 +- .../manual-seal/src/finalize_block.rs | 2 +- client/consensus/manual-seal/src/rpc.rs | 5 +- .../consensus/manual-seal/src/seal_block.rs | 7 +- client/consensus/pow/src/lib.rs | 24 ++--- client/consensus/pow/src/worker.rs | 4 +- client/consensus/slots/src/lib.rs | 17 ++-- client/consensus/slots/src/slots.rs | 2 +- client/executor/common/src/error.rs | 44 ++++++++- client/executor/runtime-test/Cargo.toml | 2 +- client/executor/runtime-test/src/lib.rs | 8 ++ client/executor/src/integration_tests/mod.rs | 92 +++++++++++-------- client/executor/src/native_executor.rs | 27 +++--- client/executor/src/wasm_runtime.rs | 4 +- client/executor/wasmi/src/lib.rs | 46 ++++++++-- client/executor/wasmtime/src/host.rs | 15 +++ .../executor/wasmtime/src/instance_wrapper.rs | 44 +++++++-- client/executor/wasmtime/src/tests.rs | 14 +-- client/finality-grandpa/src/aux_schema.rs | 2 +- client/finality-grandpa/src/environment.rs | 12 +-- client/finality-grandpa/src/import.rs | 10 +- client/finality-grandpa/src/lib.rs | 23 ++++- client/finality-grandpa/src/observer.rs | 2 +- client/network/src/protocol.rs | 2 +- client/network/src/protocol/sync.rs | 10 +- .../src/protocol/sync/extra_requests.rs | 2 +- client/network/src/protocol/sync/state.rs | 2 +- client/network/src/protocol/sync/warp.rs | 2 +- client/offchain/src/lib.rs | 2 +- client/rpc-api/src/author/error.rs | 2 +- client/rpc-api/src/errors.rs | 6 +- client/service/src/chain_ops/check_block.rs | 2 +- client/service/src/chain_ops/import_blocks.rs | 2 +- client/service/src/client/call_executor.rs | 4 +- client/service/src/client/client.rs | 6 +- client/service/src/client/wasm_override.rs | 2 +- client/service/src/client/wasm_substitutes.rs | 2 +- client/service/src/lib.rs | 2 +- client/tracing/src/block/mod.rs | 2 +- client/transaction-pool/api/src/lib.rs | 2 +- client/transaction-pool/src/api.rs | 12 +-- client/transaction-pool/src/lib.rs | 10 +- client/transaction-pool/src/revalidation.rs | 2 +- frame/contracts/rpc/src/lib.rs | 4 +- frame/merkle-mountain-range/rpc/src/lib.rs | 4 +- frame/transaction-payment/rpc/src/lib.rs | 4 +- .../api/proc-macro/src/impl_runtime_apis.rs | 2 +- primitives/blockchain/src/error.rs | 2 +- primitives/consensus/common/src/lib.rs | 4 +- primitives/io/Cargo.toml | 19 ++++ primitives/io/src/lib.rs | 40 ++++++-- .../bare_function_interface.rs | 39 ++++++-- .../host_function_interface.rs | 4 +- .../src/runtime_interface/trait_decl_impl.rs | 2 +- .../runtime-interface/proc-macro/src/utils.rs | 91 +++++++++++++----- primitives/runtime/src/traits.rs | 2 +- primitives/wasm-interface/src/lib.rs | 23 +++++ utils/frame/benchmarking-cli/src/command.rs | 8 +- utils/frame/rpc/system/src/lib.rs | 4 +- utils/frame/try-runtime/cli/src/lib.rs | 4 +- 68 files changed, 552 insertions(+), 247 deletions(-) diff --git a/client/authority-discovery/src/error.rs b/client/authority-discovery/src/error.rs index bad53e905cb9..bce39069ef7c 100644 --- a/client/authority-discovery/src/error.rs +++ b/client/authority-discovery/src/error.rs @@ -38,7 +38,7 @@ pub enum Error { #[error("Failed to hash the authority id to be used as a dht key.")] HashingAuthorityId(#[from] libp2p::core::multiaddr::multihash::Error), - #[error("Failed calling into the Substrate runtime.")] + #[error("Failed calling into the Substrate runtime: {0}")] CallingRuntime(#[from] sp_blockchain::Error), #[error("Received a dht record with a key that does not match any in-flight awaited keys.")] diff --git a/client/authority-discovery/src/worker.rs b/client/authority-discovery/src/worker.rs index ee5a15b9533b..019abaac3cfc 100644 --- a/client/authority-discovery/src/worker.rs +++ b/client/authority-discovery/src/worker.rs @@ -187,7 +187,7 @@ where Some(registry) => match Metrics::register(®istry) { Ok(metrics) => Some(metrics), Err(e) => { - error!(target: LOG_TARGET, "Failed to register metrics: {:?}", e); + error!(target: LOG_TARGET, "Failed to register metrics: {}", e); None }, }, @@ -242,7 +242,7 @@ where if let Err(e) = self.publish_ext_addresses(only_if_changed).await { error!( target: LOG_TARGET, - "Failed to publish external addresses: {:?}", e, + "Failed to publish external addresses: {}", e, ); } }, @@ -251,7 +251,7 @@ where if let Err(e) = self.refill_pending_lookups_queue().await { error!( target: LOG_TARGET, - "Failed to request addresses of authorities: {:?}", e, + "Failed to request addresses of authorities: {}", e, ); } }, @@ -426,7 +426,7 @@ where metrics.handle_value_found_event_failure.inc(); } - debug!(target: LOG_TARGET, "Failed to handle Dht value found event: {:?}", e); + debug!(target: LOG_TARGET, "Failed to handle Dht value found event: {}", e); } }, DhtEvent::ValueNotFound(hash) => { diff --git a/client/beefy/src/worker.rs b/client/beefy/src/worker.rs index 0c7d8d4ffdc9..3f23638758ec 100644 --- a/client/beefy/src/worker.rs +++ b/client/beefy/src/worker.rs @@ -378,7 +378,7 @@ where .expect("forwards closure result; the closure always returns Ok; qed."); } }) { - error!(target: "beefy", "🥩 Failed to get hash for block number {}; err: {:?}", + error!(target: "beefy", "🥩 Failed to get hash for block number {}: {}", block_num, err); } diff --git a/client/consensus/aura/src/import_queue.rs b/client/consensus/aura/src/import_queue.rs index 593ea193c3d1..56eb45c621a1 100644 --- a/client/consensus/aura/src/import_queue.rs +++ b/client/consensus/aura/src/import_queue.rs @@ -205,7 +205,7 @@ where let hash = block.header.hash(); let parent_hash = *block.header.parent_hash(); let authorities = authorities(self.client.as_ref(), &BlockId::Hash(parent_hash)) - .map_err(|e| format!("Could not fetch authorities at {:?}: {:?}", parent_hash, e))?; + .map_err(|e| format!("Could not fetch authorities at {:?}: {}", parent_hash, e))?; let create_inherent_data_providers = self .create_inherent_data_providers @@ -249,7 +249,7 @@ where &BlockId::Hash(parent_hash), |v| v >= 2, ) - .map_err(|e| format!("{:?}", e))? + .map_err(|e| e.to_string())? { self.check_inherents( new_block.clone(), diff --git a/client/consensus/babe/rpc/src/lib.rs b/client/consensus/babe/rpc/src/lib.rs index 462620f26e5b..88a176e2de10 100644 --- a/client/consensus/babe/rpc/src/lib.rs +++ b/client/consensus/babe/rpc/src/lib.rs @@ -104,7 +104,7 @@ where let epoch_start = client .runtime_api() .current_epoch_start(&BlockId::Hash(header.hash())) - .map_err(|err| Error::StringError(format!("{:?}", err)))?; + .map_err(|err| Error::StringError(err.to_string()))?; let epoch = epoch_data(&shared_epoch, &client, &babe_config, *epoch_start, &select_chain) .await?; @@ -209,7 +209,7 @@ where slot.into(), |slot| Epoch::genesis(&babe_config, slot), ) - .map_err(|e| Error::Consensus(ConsensusError::ChainLookup(format!("{:?}", e))))? + .map_err(|e| Error::Consensus(ConsensusError::ChainLookup(e.to_string())))? .ok_or(Error::Consensus(ConsensusError::InvalidAuthoritiesSet)) } diff --git a/client/consensus/babe/src/lib.rs b/client/consensus/babe/src/lib.rs index 3e9cf5aab649..9ad50eb9c0e5 100644 --- a/client/consensus/babe/src/lib.rs +++ b/client/consensus/babe/src/lib.rs @@ -232,7 +232,7 @@ pub enum Error { #[error("Multiple BABE config change digests, rejecting!")] MultipleConfigChangeDigests, /// Could not extract timestamp and slot - #[error("Could not extract timestamp and slot: {0:?}")] + #[error("Could not extract timestamp and slot: {0}")] Extraction(sp_consensus::Error), /// Could not fetch epoch #[error("Could not fetch epoch at {0:?}")] @@ -274,7 +274,7 @@ pub enum Error { #[error("VRF verification failed: {0:?}")] VRFVerificationFailed(SignatureError), /// Could not fetch parent header - #[error("Could not fetch parent header: {0:?}")] + #[error("Could not fetch parent header: {0}")] FetchParentHeader(sp_blockchain::Error), /// Expected epoch change to happen. #[error("Expected epoch change to happen at {0:?}, s{1}")] @@ -713,7 +713,7 @@ where parent.number().clone(), slot, ) - .map_err(|e| ConsensusError::ChainLookup(format!("{:?}", e)))? + .map_err(|e| ConsensusError::ChainLookup(e.to_string()))? .ok_or(sp_consensus::Error::InvalidAuthoritiesSet) } @@ -1201,7 +1201,7 @@ where ) .await { - warn!(target: "babe", "Error checking/reporting BABE equivocation: {:?}", err); + warn!(target: "babe", "Error checking/reporting BABE equivocation: {}", err); } // if the body is passed through, we need to use the runtime @@ -1551,7 +1551,7 @@ where ) .map_err(|e| { ConsensusError::ClientImport(format!( - "Error importing epoch changes: {:?}", + "Error importing epoch changes: {}", e )) })?; @@ -1559,7 +1559,7 @@ where }; if let Err(e) = prune_and_import() { - debug!(target: "babe", "Failed to launch next epoch: {:?}", e); + debug!(target: "babe", "Failed to launch next epoch: {}", e); *epoch_changes = old_epoch_changes.expect("set `Some` above and not taken; qed"); return Err(e) @@ -1590,7 +1590,7 @@ where parent_weight } else { aux_schema::load_block_weight(&*self.client, last_best) - .map_err(|e| ConsensusError::ChainLookup(format!("{:?}", e)))? + .map_err(|e| ConsensusError::ChainLookup(e.to_string()))? .ok_or_else(|| { ConsensusError::ChainLookup( "No block weight for parent header.".to_string(), @@ -1649,7 +1649,7 @@ where let finalized_slot = { let finalized_header = client .header(BlockId::Hash(info.finalized_hash)) - .map_err(|e| ConsensusError::ClientImport(format!("{:?}", e)))? + .map_err(|e| ConsensusError::ClientImport(e.to_string()))? .expect( "best finalized hash was given by client; finalized headers must exist in db; qed", ); @@ -1666,7 +1666,7 @@ where info.finalized_number, finalized_slot, ) - .map_err(|e| ConsensusError::ClientImport(format!("{:?}", e)))?; + .map_err(|e| ConsensusError::ClientImport(e.to_string()))?; Ok(()) } diff --git a/client/consensus/common/src/import_queue.rs b/client/consensus/common/src/import_queue.rs index f71996fe2b1f..8b560d044741 100644 --- a/client/consensus/common/src/import_queue.rs +++ b/client/consensus/common/src/import_queue.rs @@ -161,21 +161,34 @@ pub enum BlockImportStatus { } /// Block import error. -#[derive(Debug)] +#[derive(Debug, thiserror::Error)] pub enum BlockImportError { /// Block missed header, can't be imported + #[error("block is missing a header (origin = {0:?})")] IncompleteHeader(Option), + /// Block verification failed, can't be imported + #[error("block verification failed (origin = {0:?}): {1}")] VerificationFailed(Option, String), + /// Block is known to be Bad + #[error("bad block (origin = {0:?})")] BadBlock(Option), + /// Parent state is missing. + #[error("block is missing parent state")] MissingState, + /// Block has an unknown parent + #[error("block has an unknown parent")] UnknownParent, + /// Block import has been cancelled. This can happen if the parent block fails to be imported. + #[error("import has been cancelled")] Cancelled, + /// Other error. + #[error("consensus error: {0}")] Other(ConsensusError), } @@ -245,7 +258,7 @@ pub(crate) async fn import_single_block_metered< Err(BlockImportError::BadBlock(peer.clone())) }, Err(e) => { - debug!(target: "sync", "Error importing block {}: {:?}: {:?}", number, hash, e); + debug!(target: "sync", "Error importing block {}: {:?}: {}", number, hash, e); Err(BlockImportError::Other(e)) }, }; diff --git a/client/consensus/common/src/import_queue/basic_queue.rs b/client/consensus/common/src/import_queue/basic_queue.rs index 0f23d9b546bd..5134dc041c26 100644 --- a/client/consensus/common/src/import_queue/basic_queue.rs +++ b/client/consensus/common/src/import_queue/basic_queue.rs @@ -303,11 +303,11 @@ impl BlockImportWorker { .map_err(|e| { debug!( target: "sync", - "Justification import failed with {:?} for hash: {:?} number: {:?} coming from node: {:?}", - e, + "Justification import failed for hash = {:?} with number = {:?} coming from node = {:?} with error: {}", hash, number, who, + e, ); e }) diff --git a/client/consensus/manual-seal/src/consensus/babe.rs b/client/consensus/manual-seal/src/consensus/babe.rs index 9c2a1638043a..dd3f9a253478 100644 --- a/client/consensus/manual-seal/src/consensus/babe.rs +++ b/client/consensus/manual-seal/src/consensus/babe.rs @@ -118,7 +118,7 @@ where pre_digest.slot(), ) .map_err(|e| format!("failed to fetch epoch_descriptor: {}", e))? - .ok_or_else(|| format!("{:?}", sp_consensus::Error::InvalidAuthoritiesSet))?; + .ok_or_else(|| format!("{}", sp_consensus::Error::InvalidAuthoritiesSet))?; // drop the lock drop(epoch_changes); diff --git a/client/consensus/manual-seal/src/finalize_block.rs b/client/consensus/manual-seal/src/finalize_block.rs index bc242ad6085e..d134ce773457 100644 --- a/client/consensus/manual-seal/src/finalize_block.rs +++ b/client/consensus/manual-seal/src/finalize_block.rs @@ -48,7 +48,7 @@ where match finalizer.finalize_block(BlockId::Hash(hash), justification, true) { Err(e) => { - log::warn!("Failed to finalize block {:?}", e); + log::warn!("Failed to finalize block {}", e); rpc::send_result(&mut sender, Err(e.into())) }, Ok(()) => { diff --git a/client/consensus/manual-seal/src/rpc.rs b/client/consensus/manual-seal/src/rpc.rs index 7b4063e9b2b1..4a8dcbc0cb76 100644 --- a/client/consensus/manual-seal/src/rpc.rs +++ b/client/consensus/manual-seal/src/rpc.rs @@ -155,7 +155,10 @@ pub fn send_result( ) { if let Some(sender) = sender.take() { if let Err(err) = sender.send(result) { - log::warn!("Server is shutting down: {:?}", err) + match err { + Ok(value) => log::warn!("Server is shutting down: {:?}", value), + Err(error) => log::warn!("Server is shutting down with error: {}", error), + } } } else { // instant seal doesn't report errors over rpc, simply log them. diff --git a/client/consensus/manual-seal/src/seal_block.rs b/client/consensus/manual-seal/src/seal_block.rs index 99b003c32f13..202b54fe5d0c 100644 --- a/client/consensus/manual-seal/src/seal_block.rs +++ b/client/consensus/manual-seal/src/seal_block.rs @@ -114,10 +114,7 @@ pub async fn seal_block( let inherent_data = inherent_data_providers.create_inherent_data()?; - let proposer = env - .init(&parent) - .map_err(|err| Error::StringError(format!("{:?}", err))) - .await?; + let proposer = env.init(&parent).map_err(|err| Error::StringError(err.to_string())).await?; let inherents_len = inherent_data.len(); let digest = if let Some(digest_provider) = digest_provider { @@ -133,7 +130,7 @@ pub async fn seal_block( Duration::from_secs(MAX_PROPOSAL_DURATION), None, ) - .map_err(|err| Error::StringError(format!("{:?}", err))) + .map_err(|err| Error::StringError(err.to_string())) .await?; if proposal.block.extrinsics().len() == inherents_len && !create_empty { diff --git a/client/consensus/pow/src/lib.rs b/client/consensus/pow/src/lib.rs index ef81faff46a9..6d0bc3fc5a19 100644 --- a/client/consensus/pow/src/lib.rs +++ b/client/consensus/pow/src/lib.rs @@ -84,24 +84,24 @@ pub enum Error { FailedPreliminaryVerify, #[error("Rejecting block too far in future")] TooFarInFuture, - #[error("Fetching best header failed using select chain: {0:?}")] + #[error("Fetching best header failed using select chain: {0}")] BestHeaderSelectChain(ConsensusError), - #[error("Fetching best header failed: {0:?}")] + #[error("Fetching best header failed: {0}")] BestHeader(sp_blockchain::Error), #[error("Best header does not exist")] NoBestHeader, - #[error("Block proposing error: {0:?}")] + #[error("Block proposing error: {0}")] BlockProposingError(String), - #[error("Fetch best hash failed via select chain: {0:?}")] + #[error("Fetch best hash failed via select chain: {0}")] BestHashSelectChain(ConsensusError), - #[error("Error with block built on {0:?}: {1:?}")] + #[error("Error with block built on {0:?}: {1}")] BlockBuiltError(B::Hash, ConsensusError), #[error("Creating inherents failed: {0}")] CreateInherents(sp_inherents::Error), #[error("Checking inherents failed: {0}")] CheckInherents(sp_inherents::Error), #[error( - "Checking inherents unknown error for identifier: {:?}", + "Checking inherents unknown error for identifier: {}", String::from_utf8_lossy(.0) )] CheckInherentsUnknownError(sp_inherents::InherentIdentifier), @@ -350,7 +350,7 @@ where .select_chain .best_chain() .await - .map_err(|e| format!("Fetch best chain failed via select chain: {:?}", e))?; + .map_err(|e| format!("Fetch best chain failed via select chain: {}", e))?; let best_hash = best_header.hash(); let parent_hash = *block.header.parent_hash(); @@ -565,7 +565,7 @@ where warn!( target: "pow", "Unable to pull new block for authoring. \ - Select best chain error: {:?}", + Select best chain error: {}", err ); continue @@ -596,7 +596,7 @@ where warn!( target: "pow", "Unable to propose new block for authoring. \ - Fetch difficulty failed: {:?}", + Fetch difficulty failed: {}", err, ); continue @@ -612,7 +612,7 @@ where warn!( target: "pow", "Unable to propose new block for authoring. \ - Creating inherent data providers failed: {:?}", + Creating inherent data providers failed: {}", err, ); continue @@ -625,7 +625,7 @@ where warn!( target: "pow", "Unable to propose new block for authoring. \ - Creating inherent data failed: {:?}", + Creating inherent data failed: {}", e, ); continue @@ -661,7 +661,7 @@ where warn!( target: "pow", "Unable to propose new block for authoring. \ - Creating proposal failed: {:?}", + Creating proposal failed: {}", err, ); continue diff --git a/client/consensus/pow/src/worker.rs b/client/consensus/pow/src/worker.rs index 031cf7f6a294..42f82fb43ef7 100644 --- a/client/consensus/pow/src/worker.rs +++ b/client/consensus/pow/src/worker.rs @@ -169,7 +169,7 @@ where Err(err) => { warn!( target: "pow", - "Unable to import mined block: {:?}", + "Unable to import mined block: {}", err, ); return false @@ -238,7 +238,7 @@ where Err(err) => { warn!( target: "pow", - "Unable to import mined block: {:?}", + "Unable to import mined block: {}", err, ); false diff --git a/client/consensus/slots/src/lib.rs b/client/consensus/slots/src/lib.rs index a1b335f7a594..9fc93788a33e 100644 --- a/client/consensus/slots/src/lib.rs +++ b/client/consensus/slots/src/lib.rs @@ -214,7 +214,7 @@ pub trait SimpleSlotWorker { Err(err) => { warn!( target: logging_target, - "Unable to fetch epoch data at block {:?}: {:?}", + "Unable to fetch epoch data at block {:?}: {}", slot_info.chain_head.hash(), err, ); @@ -274,10 +274,7 @@ pub trait SimpleSlotWorker { let proposer = match self.proposer(&slot_info.chain_head).await { Ok(p) => p, Err(err) => { - warn!( - target: logging_target, - "Unable to author block in slot {:?}: {:?}", slot, err, - ); + warn!(target: logging_target, "Unable to author block in slot {:?}: {}", slot, err,); telemetry!( telemetry; @@ -303,12 +300,12 @@ pub trait SimpleSlotWorker { proposing_remaining_duration.mul_f32(0.98), None, ) - .map_err(|e| sp_consensus::Error::ClientImport(format!("{:?}", e))); + .map_err(|e| sp_consensus::Error::ClientImport(e.to_string())); let proposal = match futures::future::select(proposing, proposing_remaining).await { Either::Left((Ok(p), _)) => p, Either::Left((Err(err), _)) => { - warn!(target: logging_target, "Proposing failed: {:?}", err); + warn!(target: logging_target, "Proposing failed: {}", err); return None }, @@ -353,7 +350,7 @@ pub trait SimpleSlotWorker { { Ok(bi) => bi, Err(err) => { - warn!(target: logging_target, "Failed to create block import params: {:?}", err); + warn!(target: logging_target, "Failed to create block import params: {}", err); return None }, @@ -388,7 +385,7 @@ pub trait SimpleSlotWorker { Err(err) => { warn!( target: logging_target, - "Error with block built on {:?}: {:?}", parent_hash, err, + "Error with block built on {:?}: {}", parent_hash, err, ); telemetry!( @@ -488,7 +485,7 @@ pub async fn start_slot_worker( let slot_info = match slots.next_slot().await { Ok(r) => r, Err(e) => { - warn!(target: "slots", "Error while polling for next slot: {:?}", e); + warn!(target: "slots", "Error while polling for next slot: {}", e); return }, }; diff --git a/client/consensus/slots/src/slots.rs b/client/consensus/slots/src/slots.rs index 2b792af7da8c..a7b9f3e3ff61 100644 --- a/client/consensus/slots/src/slots.rs +++ b/client/consensus/slots/src/slots.rs @@ -150,7 +150,7 @@ where Err(e) => { log::warn!( target: "slots", - "Unable to author block in slot. No best block header: {:?}", + "Unable to author block in slot. No best block header: {}", e, ); // Let's try at the next slot.. diff --git a/client/executor/common/src/error.rs b/client/executor/common/src/error.rs index 606f97317b9a..c5de737376c1 100644 --- a/client/executor/common/src/error.rs +++ b/client/executor/common/src/error.rs @@ -31,9 +31,6 @@ pub enum Error { #[error("Unserializable data encountered")] InvalidData(#[from] sp_serializer::Error), - #[error(transparent)] - Trap(#[from] wasmi::Trap), - #[error(transparent)] Wasmi(#[from] wasmi::Error), @@ -108,6 +105,12 @@ pub enum Error { #[error("Invalid initializer expression provided {0}")] InvalidInitializerExpression(String), + + #[error("Execution aborted due to panic: {0}")] + AbortedDueToPanic(MessageWithBacktrace), + + #[error("Execution aborted due to trap: {0}")] + AbortedDueToTrap(MessageWithBacktrace), } impl wasmi::HostError for Error {} @@ -160,3 +163,38 @@ pub enum WasmError { #[error("{0}")] Other(String), } + +/// An error message with an attached backtrace. +#[derive(Debug)] +pub struct MessageWithBacktrace { + /// The error message. + pub message: String, + + /// The backtrace associated with the error message. + pub backtrace: Option, +} + +impl std::fmt::Display for MessageWithBacktrace { + fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { + fmt.write_str(&self.message)?; + if let Some(ref backtrace) = self.backtrace { + fmt.write_str("\nWASM backtrace:\n")?; + backtrace.backtrace_string.fmt(fmt)?; + } + + Ok(()) + } +} + +/// A WASM backtrace. +#[derive(Debug)] +pub struct Backtrace { + /// The string containing the backtrace. + pub backtrace_string: String, +} + +impl std::fmt::Display for Backtrace { + fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { + fmt.write_str(&self.backtrace_string) + } +} diff --git a/client/executor/runtime-test/Cargo.toml b/client/executor/runtime-test/Cargo.toml index b6fbe8685e35..ca1746c842e1 100644 --- a/client/executor/runtime-test/Cargo.toml +++ b/client/executor/runtime-test/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-core = { version = "5.0.0", default-features = false, path = "../../../primitives/core" } -sp-io = { version = "5.0.0", default-features = false, path = "../../../primitives/io" } +sp-io = { version = "5.0.0", default-features = false, path = "../../../primitives/io", features = ["improved_panic_error_reporting"] } sp-runtime = { version = "5.0.0", default-features = false, path = "../../../primitives/runtime" } sp-sandbox = { version = "0.10.0-dev", default-features = false, path = "../../../primitives/sandbox" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } diff --git a/client/executor/runtime-test/src/lib.rs b/client/executor/runtime-test/src/lib.rs index 0655160c1ab7..bf9f76edd945 100644 --- a/client/executor/runtime-test/src/lib.rs +++ b/client/executor/runtime-test/src/lib.rs @@ -341,6 +341,14 @@ sp_core::wasm_export_functions! { fn test_take_i8(value: i8) { assert_eq!(value, -66); } + + fn test_abort_on_panic() { + sp_io::panic_handler::abort_on_panic("test_abort_on_panic called"); + } + + fn test_unreachable_intrinsic() { + core::arch::wasm32::unreachable() + } } #[cfg(not(feature = "std"))] diff --git a/client/executor/src/integration_tests/mod.rs b/client/executor/src/integration_tests/mod.rs index 67e9a96cd6ba..462a8ba1b876 100644 --- a/client/executor/src/integration_tests/mod.rs +++ b/client/executor/src/integration_tests/mod.rs @@ -22,7 +22,7 @@ mod sandbox; use codec::{Decode, Encode}; use hex_literal::hex; -use sc_executor_common::{runtime_blob::RuntimeBlob, wasm_runtime::WasmModule}; +use sc_executor_common::{error::Error, runtime_blob::RuntimeBlob, wasm_runtime::WasmModule}; use sc_runtime_test::wasm_binary_unwrap; use sp_core::{ blake2_128, blake2_256, ed25519, map, @@ -122,7 +122,7 @@ fn call_in_wasm( call_data: &[u8], execution_method: WasmExecutionMethod, ext: &mut E, -) -> Result, String> { +) -> Result, Error> { let executor = crate::WasmExecutor::::new(execution_method, Some(1024), 8, None, 2); executor.uncached_call( @@ -148,25 +148,16 @@ fn call_not_existing_function(wasm_method: WasmExecutionMethod) { let mut ext = TestExternalities::default(); let mut ext = ext.ext(); - match call_in_wasm( - "test_calling_missing_external", - &[], - wasm_method, - &mut ext, - ) { - Ok(_) => panic!("was expected an `Err`"), - Err(e) => { - match wasm_method { - WasmExecutionMethod::Interpreted => assert_eq!( - &format!("{:?}", e), - "\"Trap: Trap { kind: Host(Other(\\\"Function `missing_external` is only a stub. Calling a stub is not allowed.\\\")) }\"" - ), + match call_in_wasm("test_calling_missing_external", &[], wasm_method, &mut ext).unwrap_err() { + Error::AbortedDueToTrap(error) => { + let expected = match wasm_method { + WasmExecutionMethod::Interpreted => "Trap: Host(Other(\"Function `missing_external` is only a stub. Calling a stub is not allowed.\"))", #[cfg(feature = "wasmtime")] - WasmExecutionMethod::Compiled => assert!( - format!("{:?}", e).contains("Wasm execution trapped: call to a missing function env:missing_external") - ), - } - } + WasmExecutionMethod::Compiled => "call to a missing function env:missing_external" + }; + assert_eq!(error.message, expected); + }, + error => panic!("unexpected error: {:?}", error), } } @@ -175,25 +166,18 @@ fn call_yet_another_not_existing_function(wasm_method: WasmExecutionMethod) { let mut ext = TestExternalities::default(); let mut ext = ext.ext(); - match call_in_wasm( - "test_calling_yet_another_missing_external", - &[], - wasm_method, - &mut ext, - ) { - Ok(_) => panic!("was expected an `Err`"), - Err(e) => { - match wasm_method { - WasmExecutionMethod::Interpreted => assert_eq!( - &format!("{:?}", e), - "\"Trap: Trap { kind: Host(Other(\\\"Function `yet_another_missing_external` is only a stub. Calling a stub is not allowed.\\\")) }\"" - ), + match call_in_wasm("test_calling_yet_another_missing_external", &[], wasm_method, &mut ext) + .unwrap_err() + { + Error::AbortedDueToTrap(error) => { + let expected = match wasm_method { + WasmExecutionMethod::Interpreted => "Trap: Host(Other(\"Function `yet_another_missing_external` is only a stub. Calling a stub is not allowed.\"))", #[cfg(feature = "wasmtime")] - WasmExecutionMethod::Compiled => assert!( - format!("{:?}", e).contains("Wasm execution trapped: call to a missing function env:yet_another_missing_external") - ), - } - } + WasmExecutionMethod::Compiled => "call to a missing function env:yet_another_missing_external" + }; + assert_eq!(error.message, expected); + }, + error => panic!("unexpected error: {:?}", error), } } @@ -485,6 +469,7 @@ fn should_trap_when_heap_exhausted(wasm_method: WasmExecutionMethod) { "test_exhaust_heap", &[0], ) + .map_err(|e| e.to_string()) .unwrap_err(); assert!(err.contains("Allocator ran out of space")); @@ -691,7 +676,7 @@ fn panic_in_spawned_instance_panics_on_joining_its_result(wasm_method: WasmExecu let error_result = call_in_wasm("test_panic_in_spawned", &[], wasm_method, &mut ext).unwrap_err(); - assert!(error_result.contains("Spawned task")); + assert!(error_result.to_string().contains("Spawned task")); } test_wasm_execution!(memory_is_cleared_between_invocations); @@ -789,3 +774,32 @@ fn take_i8(wasm_method: WasmExecutionMethod) { call_in_wasm("test_take_i8", &(-66_i8).encode(), wasm_method, &mut ext).unwrap(); } + +test_wasm_execution!(abort_on_panic); +fn abort_on_panic(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + let mut ext = ext.ext(); + + match call_in_wasm("test_abort_on_panic", &[], wasm_method, &mut ext).unwrap_err() { + Error::AbortedDueToPanic(error) => assert_eq!(error.message, "test_abort_on_panic called"), + error => panic!("unexpected error: {:?}", error), + } +} + +test_wasm_execution!(unreachable_intrinsic); +fn unreachable_intrinsic(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + let mut ext = ext.ext(); + + match call_in_wasm("test_unreachable_intrinsic", &[], wasm_method, &mut ext).unwrap_err() { + Error::AbortedDueToTrap(error) => { + let expected = match wasm_method { + WasmExecutionMethod::Interpreted => "Trap: Unreachable", + #[cfg(feature = "wasmtime")] + WasmExecutionMethod::Compiled => "wasm trap: wasm `unreachable` instruction executed", + }; + assert_eq!(error.message, expected); + }, + error => panic!("unexpected error: {:?}", error), + } +} diff --git a/client/executor/src/native_executor.rs b/client/executor/src/native_executor.rs index b36d6f1297e9..1bc87840ba35 100644 --- a/client/executor/src/native_executor.rs +++ b/client/executor/src/native_executor.rs @@ -220,7 +220,7 @@ where allow_missing_host_functions: bool, export_name: &str, call_data: &[u8], - ) -> std::result::Result, String> { + ) -> std::result::Result, Error> { let module = crate::wasm_runtime::create_wasm_runtime_with_code::( self.method, self.default_heap_pages, @@ -228,11 +228,10 @@ where allow_missing_host_functions, self.cache_path.as_deref(), ) - .map_err(|e| format!("Failed to create module: {:?}", e))?; + .map_err(|e| format!("Failed to create module: {}", e))?; - let instance = module - .new_instance() - .map_err(|e| format!("Failed to create instance: {:?}", e))?; + let instance = + module.new_instance().map_err(|e| format!("Failed to create instance: {}", e))?; let mut instance = AssertUnwindSafe(instance); let mut ext = AssertUnwindSafe(ext); @@ -243,7 +242,6 @@ where instance.call_export(export_name, call_data) }) .and_then(|r| r) - .map_err(|e| e.to_string()) } } @@ -281,6 +279,7 @@ where "Core_version", &[], ) + .map_err(|e| e.to_string()) } } @@ -456,12 +455,18 @@ impl RuntimeSpawn for RuntimeInstanceSpawn { // pool of instances should be used. // // https://github.com/paritytech/substrate/issues/7354 - let mut instance = - module.new_instance().expect("Failed to create new instance from module"); + let mut instance = match module.new_instance() { + Ok(instance) => instance, + Err(error) => + panic!("failed to create new instance from module: {}", error), + }; - instance + match instance .call(InvokeMethod::TableWithWrapper { dispatcher_ref, func }, &data[..]) - .expect("Failed to invoke instance.") + { + Ok(result) => result, + Err(error) => panic!("failed to invoke instance: {}", error), + } }); match result { @@ -471,7 +476,7 @@ impl RuntimeSpawn for RuntimeInstanceSpawn { Err(error) => { // If execution is panicked, the `join` in the original runtime code will // panic as well, since the sender is dropped without sending anything. - log::error!("Call error in spawned task: {:?}", error); + log::error!("Call error in spawned task: {}", error); }, } }), diff --git a/client/executor/src/wasm_runtime.rs b/client/executor/src/wasm_runtime.rs index 0775755aff7c..2cccb6f9c38b 100644 --- a/client/executor/src/wasm_runtime.rs +++ b/client/executor/src/wasm_runtime.rs @@ -105,13 +105,13 @@ impl VersionedRuntime { if new_inst { log::warn!( target: "wasm-runtime", - "Fresh runtime instance failed with {:?}", + "Fresh runtime instance failed with {}", e, ) } else { log::warn!( target: "wasm-runtime", - "Evicting failed runtime instance: {:?}", + "Evicting failed runtime instance: {}", e, ); } diff --git a/client/executor/wasmi/src/lib.rs b/client/executor/wasmi/src/lib.rs index 78fd300e05e3..f0488972daca 100644 --- a/client/executor/wasmi/src/lib.rs +++ b/client/executor/wasmi/src/lib.rs @@ -21,7 +21,7 @@ use codec::{Decode, Encode}; use log::{debug, error, trace}; use sc_executor_common::{ - error::{Error, WasmError}, + error::{Error, MessageWithBacktrace, WasmError}, runtime_blob::{DataSegmentsSnapshot, RuntimeBlob}, sandbox, util::MemoryTransfer, @@ -48,6 +48,7 @@ struct FunctionExecutor { host_functions: Arc>, allow_missing_func_imports: bool, missing_functions: Arc>, + panic_message: Option, } impl FunctionExecutor { @@ -69,6 +70,7 @@ impl FunctionExecutor { host_functions, allow_missing_func_imports, missing_functions, + panic_message: None, }) } } @@ -100,7 +102,10 @@ impl<'a> sandbox::SandboxContext for SandboxContext<'a> { match result { Ok(Some(RuntimeValue::I64(val))) => Ok(val), Ok(_) => return Err("Supervisor function returned unexpected result!".into()), - Err(err) => Err(Error::Trap(err)), + Err(err) => Err(Error::AbortedDueToTrap(MessageWithBacktrace { + message: err.to_string(), + backtrace: None, + })), } } @@ -133,6 +138,10 @@ impl FunctionContext for FunctionExecutor { fn sandbox(&mut self) -> &mut dyn Sandbox { self } + + fn register_panic_error_message(&mut self, message: &str) { + self.panic_message = Some(message.to_owned()); + } } impl Sandbox for FunctionExecutor { @@ -502,12 +511,31 @@ fn call_in_wasm_module( let offset = function_executor.allocate_memory(data.len() as u32)?; function_executor.write_memory(offset, data)?; + fn convert_trap(executor: &mut FunctionExecutor, trap: wasmi::Trap) -> Error { + if let Some(message) = executor.panic_message.take() { + Error::AbortedDueToPanic(MessageWithBacktrace { message, backtrace: None }) + } else { + Error::AbortedDueToTrap(MessageWithBacktrace { + message: trap.to_string(), + backtrace: None, + }) + } + } + let result = match method { - InvokeMethod::Export(method) => module_instance.invoke_export( - method, - &[I32(u32::from(offset) as i32), I32(data.len() as i32)], - &mut function_executor, - ), + InvokeMethod::Export(method) => module_instance + .invoke_export( + method, + &[I32(u32::from(offset) as i32), I32(data.len() as i32)], + &mut function_executor, + ) + .map_err(|error| { + if let wasmi::Error::Trap(trap) = error { + convert_trap(&mut function_executor, trap) + } else { + error.into() + } + }), InvokeMethod::Table(func_ref) => { let func = table .ok_or(Error::NoTable)? @@ -518,7 +546,7 @@ fn call_in_wasm_module( &[I32(u32::from(offset) as i32), I32(data.len() as i32)], &mut function_executor, ) - .map_err(Into::into) + .map_err(|trap| convert_trap(&mut function_executor, trap)) }, InvokeMethod::TableWithWrapper { dispatcher_ref, func } => { let dispatcher = table @@ -531,7 +559,7 @@ fn call_in_wasm_module( &[I32(func as _), I32(u32::from(offset) as i32), I32(data.len() as i32)], &mut function_executor, ) - .map_err(Into::into) + .map_err(|trap| convert_trap(&mut function_executor, trap)) }, }; diff --git a/client/executor/wasmtime/src/host.rs b/client/executor/wasmtime/src/host.rs index 5da8ff325903..b310ada24b62 100644 --- a/client/executor/wasmtime/src/host.rs +++ b/client/executor/wasmtime/src/host.rs @@ -45,6 +45,7 @@ unsafe impl Send for SandboxStore {} pub struct HostState { sandbox_store: SandboxStore, allocator: FreeingBumpHeapAllocator, + panic_message: Option, } impl HostState { @@ -55,8 +56,14 @@ impl HostState { sandbox::SandboxBackend::TryWasmer, )))), allocator, + panic_message: None, } } + + /// Takes the error message out of the host state, leaving a `None` in its place. + pub fn take_panic_message(&mut self) -> Option { + self.panic_message.take() + } } /// A `HostContext` implements `FunctionContext` for making host calls from a Wasmtime @@ -134,6 +141,14 @@ impl<'a> sp_wasm_interface::FunctionContext for HostContext<'a> { fn sandbox(&mut self) -> &mut dyn Sandbox { self } + + fn register_panic_error_message(&mut self, message: &str) { + self.caller + .data_mut() + .host_state_mut() + .expect("host state is not empty when calling a function in wasm; qed") + .panic_message = Some(message.to_owned()); + } } impl<'a> Sandbox for HostContext<'a> { diff --git a/client/executor/wasmtime/src/instance_wrapper.rs b/client/executor/wasmtime/src/instance_wrapper.rs index e27de7817b2b..896b71cea21d 100644 --- a/client/executor/wasmtime/src/instance_wrapper.rs +++ b/client/executor/wasmtime/src/instance_wrapper.rs @@ -21,7 +21,7 @@ use crate::runtime::{Store, StoreData}; use sc_executor_common::{ - error::{Error, Result}, + error::{Backtrace, Error, MessageWithBacktrace, Result}, wasm_runtime::InvokeMethod, }; use sp_wasm_interface::{HostFunctions, Pointer, Value, WordSize}; @@ -53,25 +53,51 @@ pub struct EntryPoint { impl EntryPoint { /// Call this entry point. - pub fn call( + pub(crate) fn call( &self, - ctx: impl AsContextMut, + store: &mut Store, data_ptr: Pointer, data_len: WordSize, ) -> Result { let data_ptr = u32::from(data_ptr); let data_len = u32::from(data_len); - fn handle_trap(err: wasmtime::Trap) -> Error { - Error::from(format!("Wasm execution trapped: {}", err)) - } - match self.call_type { EntryPointType::Direct { ref entrypoint } => - entrypoint.call(ctx, (data_ptr, data_len)).map_err(handle_trap), + entrypoint.call(&mut *store, (data_ptr, data_len)), EntryPointType::Wrapped { func, ref dispatcher } => - dispatcher.call(ctx, (func, data_ptr, data_len)).map_err(handle_trap), + dispatcher.call(&mut *store, (func, data_ptr, data_len)), } + .map_err(|trap| { + let host_state = store + .data_mut() + .host_state + .as_mut() + .expect("host state cannot be empty while a function is being called; qed"); + + // The logic to print out a backtrace is somewhat complicated, + // so let's get wasmtime to print it out for us. + let mut backtrace_string = trap.to_string(); + let suffix = "\nwasm backtrace:"; + if let Some(index) = backtrace_string.find(suffix) { + // Get rid of the error message and just grab the backtrace, + // since we're storing the error message ourselves separately. + backtrace_string.replace_range(0..index + suffix.len(), ""); + } + + let backtrace = Backtrace { backtrace_string }; + if let Some(error) = host_state.take_panic_message() { + Error::AbortedDueToPanic(MessageWithBacktrace { + message: error, + backtrace: Some(backtrace), + }) + } else { + Error::AbortedDueToTrap(MessageWithBacktrace { + message: trap.display_reason().to_string(), + backtrace: Some(backtrace), + }) + } + }) } pub fn direct( diff --git a/client/executor/wasmtime/src/tests.rs b/client/executor/wasmtime/src/tests.rs index 773e1d707a35..664d05f5387f 100644 --- a/client/executor/wasmtime/src/tests.rs +++ b/client/executor/wasmtime/src/tests.rs @@ -17,7 +17,7 @@ // along with this program. If not, see . use codec::{Decode as _, Encode as _}; -use sc_executor_common::{runtime_blob::RuntimeBlob, wasm_runtime::WasmModule}; +use sc_executor_common::{error::Error, runtime_blob::RuntimeBlob, wasm_runtime::WasmModule}; use sc_runtime_test::wasm_binary_unwrap; use std::sync::Arc; @@ -158,11 +158,13 @@ fn test_stack_depth_reaching() { }; let mut instance = runtime.new_instance().expect("failed to instantiate a runtime"); - let err = instance.call_export("test-many-locals", &[]).unwrap_err(); - - assert!(format!("{:?}", err).starts_with( - "Other(\"Wasm execution trapped: wasm trap: wasm `unreachable` instruction executed" - )); + match instance.call_export("test-many-locals", &[]).unwrap_err() { + Error::AbortedDueToTrap(error) => { + let expected = "wasm trap: wasm `unreachable` instruction executed"; + assert_eq!(error.message, expected); + }, + error => panic!("unexpected error: {:?}", error), + } } #[test] diff --git a/client/finality-grandpa/src/aux_schema.rs b/client/finality-grandpa/src/aux_schema.rs index 2ec48a804c93..0ac9ba9e64bd 100644 --- a/client/finality-grandpa/src/aux_schema.rs +++ b/client/finality-grandpa/src/aux_schema.rs @@ -100,7 +100,7 @@ where // previously we only supported at most one pending change per fork &|_, _| Ok(false), ) { - warn!(target: "afg", "Error migrating pending authority set change: {:?}.", err); + warn!(target: "afg", "Error migrating pending authority set change: {}", err); warn!(target: "afg", "Node is in a potentially inconsistent state."); } } diff --git a/client/finality-grandpa/src/environment.rs b/client/finality-grandpa/src/environment.rs index 81bb24f1a5ee..6ffcdc719a16 100644 --- a/client/finality-grandpa/src/environment.rs +++ b/client/finality-grandpa/src/environment.rs @@ -609,7 +609,7 @@ where let tree_route = match tree_route_res { Ok(tree_route) => tree_route, Err(e) => { - debug!(target: "afg", "Encountered error computing ancestry between block {:?} and base {:?}: {:?}", + debug!(target: "afg", "Encountered error computing ancestry between block {:?} and base {:?}: {}", block, base, e); return Err(GrandpaError::NotDescendent) @@ -1098,7 +1098,7 @@ where ) { warn!(target: "afg", "Detected prevote equivocation in the finality worker: {:?}", equivocation); if let Err(err) = self.report_equivocation(equivocation.into()) { - warn!(target: "afg", "Error reporting prevote equivocation: {:?}", err); + warn!(target: "afg", "Error reporting prevote equivocation: {}", err); } } @@ -1109,7 +1109,7 @@ where ) { warn!(target: "afg", "Detected precommit equivocation in the finality worker: {:?}", equivocation); if let Err(err) = self.report_equivocation(equivocation.into()) { - warn!(target: "afg", "Error reporting precommit equivocation: {:?}", err); + warn!(target: "afg", "Error reporting precommit equivocation: {}", err); } } } @@ -1224,7 +1224,7 @@ where .or_else(|| Some((target_header.hash(), *target_header.number()))) }, Err(e) => { - warn!(target: "afg", "Encountered error finding best chain containing {:?}: {:?}", block, e); + warn!(target: "afg", "Encountered error finding best chain containing {:?}: {}", block, e); None }, }; @@ -1293,7 +1293,7 @@ where ) { if let Some(sender) = justification_sender { if let Err(err) = sender.notify(justification) { - warn!(target: "afg", "Error creating justification for subscriber: {:?}", err); + warn!(target: "afg", "Error creating justification for subscriber: {}", err); } } } @@ -1344,7 +1344,7 @@ where client .apply_finality(import_op, BlockId::Hash(hash), persisted_justification, true) .map_err(|e| { - warn!(target: "afg", "Error applying finality to block {:?}: {:?}", (hash, number), e); + warn!(target: "afg", "Error applying finality to block {:?}: {}", (hash, number), e); e })?; diff --git a/client/finality-grandpa/src/import.rs b/client/finality-grandpa/src/import.rs index 71d74045f476..ae5839d0c24e 100644 --- a/client/finality-grandpa/src/import.rs +++ b/client/finality-grandpa/src/import.rs @@ -598,7 +598,7 @@ where Err(e) => { debug!( target: "afg", - "Restoring old authority set after block import error: {:?}", + "Restoring old authority set after block import error: {}", e, ); pending_changes.revert(); @@ -663,8 +663,12 @@ where import_res.unwrap_or_else(|err| { if needs_justification { - debug!(target: "afg", "Imported block #{} that enacts authority set change with \ - invalid justification: {:?}, requesting justification from peers.", number, err); + debug!( + target: "afg", + "Requesting justification from peers due to imported block #{} that enacts authority set change with invalid justification: {}", + number, + err + ); imported_aux.bad_justification = true; imported_aux.needs_justification = true; } diff --git a/client/finality-grandpa/src/lib.rs b/client/finality-grandpa/src/lib.rs index b99f6c054419..8316e56b5b5e 100644 --- a/client/finality-grandpa/src/lib.rs +++ b/client/finality-grandpa/src/lib.rs @@ -275,23 +275,38 @@ impl Config { } /// Errors that can occur while voting in GRANDPA. -#[derive(Debug)] +#[derive(Debug, thiserror::Error)] pub enum Error { /// An error within grandpa. + #[error("grandpa error: {0}")] Grandpa(GrandpaError), + /// A network error. + #[error("network error: {0}")] Network(String), + /// A blockchain error. + #[error("blockchain error: {0}")] Blockchain(String), + /// Could not complete a round on disk. + #[error("could not complete a round on disk: {0}")] Client(ClientError), + /// Could not sign outgoing message + #[error("could not sign outgoing message: {0}")] Signing(String), + /// An invariant has been violated (e.g. not finalizing pending change blocks in-order) + #[error("safety invariant has been violated: {0}")] Safety(String), + /// A timer failed to fire. + #[error("a timer failed to fire: {0}")] Timer(io::Error), + /// A runtime api request failed. + #[error("runtime API request failed: {0}")] RuntimeApi(sp_api::ApiError), } @@ -322,7 +337,7 @@ where { fn block_number(&self, hash: Block::Hash) -> Result>, Error> { self.block_number_from_id(&BlockId::Hash(hash)) - .map_err(|e| Error::Blockchain(format!("{:?}", e))) + .map_err(|e| Error::Blockchain(e.to_string())) } } @@ -459,7 +474,7 @@ impl ::std::error::Error for CommandOrError impl fmt::Display for CommandOrError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - CommandOrError::Error(ref e) => write!(f, "{:?}", e), + CommandOrError::Error(ref e) => write!(f, "{}", e), CommandOrError::VoterCommand(ref cmd) => write!(f, "{}", cmd), } } @@ -838,7 +853,7 @@ where Ok(()) => error!(target: "afg", "GRANDPA voter future has concluded naturally, this should be unreachable." ), - Err(e) => error!(target: "afg", "GRANDPA voter error: {:?}", e), + Err(e) => error!(target: "afg", "GRANDPA voter error: {}", e), }); // Make sure that `telemetry_task` doesn't accidentally finish and kill grandpa. diff --git a/client/finality-grandpa/src/observer.rs b/client/finality-grandpa/src/observer.rs index ab0c69ef7fc2..a7c951cc33db 100644 --- a/client/finality-grandpa/src/observer.rs +++ b/client/finality-grandpa/src/observer.rs @@ -203,7 +203,7 @@ where ); let observer_work = observer_work.map_ok(|_| ()).map_err(|e| { - warn!("GRANDPA Observer failed: {:?}", e); + warn!("GRANDPA Observer failed: {}", e); }); Ok(observer_work.map(drop)) diff --git a/client/network/src/protocol.rs b/client/network/src/protocol.rs index 5541a0145366..b39d0d1b8428 100644 --- a/client/network/src/protocol.rs +++ b/client/network/src/protocol.rs @@ -886,7 +886,7 @@ impl Protocol { return }, Err(e) => { - warn!("Error reading block header {}: {:?}", hash, e); + warn!("Error reading block header {}: {}", hash, e); return }, }; diff --git a/client/network/src/protocol/sync.rs b/client/network/src/protocol/sync.rs index fbb4e376b1b4..d98c0d2c04ab 100644 --- a/client/network/src/protocol/sync.rs +++ b/client/network/src/protocol/sync.rs @@ -665,7 +665,7 @@ impl ChainSync { // There is nothing sync can get from the node that has no blockchain data. match self.block_status(&best_hash) { Err(e) => { - debug!(target:"sync", "Error reading blockchain: {:?}", e); + debug!(target:"sync", "Error reading blockchain: {}", e); Err(BadPeer(who, rep::BLOCKCHAIN_READ_ERROR)) }, Ok(BlockStatus::KnownBad) => { @@ -1192,7 +1192,7 @@ impl ChainSync { (_, Err(e)) => { info!( target: "sync", - "❌ Error answering legitimate blockchain query: {:?}", + "❌ Error answering legitimate blockchain query: {}", e, ); return Err(BadPeer(*who, rep::BLOCKCHAIN_READ_ERROR)) @@ -1629,7 +1629,7 @@ impl ChainSync { trace!(target: "sync", "Obsolete block {:?}", hash); }, e @ Err(BlockImportError::UnknownParent) | e @ Err(BlockImportError::Other(_)) => { - warn!(target: "sync", "💔 Error importing block {:?}: {:?}", hash, e); + warn!(target: "sync", "💔 Error importing block {:?}: {}", hash, e.unwrap_err()); self.state_sync = None; self.warp_sync = None; output.extend(self.restart()); @@ -1683,7 +1683,7 @@ impl ChainSync { if let Err(err) = r { warn!( target: "sync", - "💔 Error cleaning up pending extra justification data requests: {:?}", + "💔 Error cleaning up pending extra justification data requests: {}", err, ); } @@ -2081,7 +2081,7 @@ impl ChainSync { ) -> impl Iterator), BadPeer>> + 'a { self.blocks.clear(); if let Err(e) = self.reset_sync_start_point() { - warn!(target: "sync", "💔 Unable to restart sync. :{:?}", e); + warn!(target: "sync", "💔 Unable to restart sync: {}", e); } self.pending_requests.set_all(); debug!(target:"sync", "Restarted with {} ({})", self.best_queued_number, self.best_queued_hash); diff --git a/client/network/src/protocol/sync/extra_requests.rs b/client/network/src/protocol/sync/extra_requests.rs index 224fbd1a1e01..d0bfebab6601 100644 --- a/client/network/src/protocol/sync/extra_requests.rs +++ b/client/network/src/protocol/sync/extra_requests.rs @@ -108,7 +108,7 @@ impl ExtraRequests { // ignore the `Revert` error. }, Err(err) => { - debug!(target: "sync", "Failed to insert request {:?} into tree: {:?}", request, err); + debug!(target: "sync", "Failed to insert request {:?} into tree: {}", request, err); }, _ => (), } diff --git a/client/network/src/protocol/sync/state.rs b/client/network/src/protocol/sync/state.rs index 3de165b83d9e..0df862a48333 100644 --- a/client/network/src/protocol/sync/state.rs +++ b/client/network/src/protocol/sync/state.rs @@ -99,7 +99,7 @@ impl StateSync { Err(e) => { debug!( target: "sync", - "StateResponse failed proof verification: {:?}", + "StateResponse failed proof verification: {}", e, ); return ImportResult::BadResponse diff --git a/client/network/src/protocol/sync/warp.rs b/client/network/src/protocol/sync/warp.rs index 6c51d4b3495f..f12deb2dbb43 100644 --- a/client/network/src/protocol/sync/warp.rs +++ b/client/network/src/protocol/sync/warp.rs @@ -88,7 +88,7 @@ impl WarpSync { Phase::WarpProof { set_id, authorities, last_hash } => { match self.warp_sync_provider.verify(&response, *set_id, authorities.clone()) { Err(e) => { - log::debug!(target: "sync", "Bad warp proof response: {:?}", e); + log::debug!(target: "sync", "Bad warp proof response: {}", e); return WarpProofImportResult::BadResponse }, Ok(VerificationResult::Partial(new_set_id, new_authorities, new_last_hash)) => { diff --git a/client/offchain/src/lib.rs b/client/offchain/src/lib.rs index cc49c07bffcf..8d016e945453 100644 --- a/client/offchain/src/lib.rs +++ b/client/offchain/src/lib.rs @@ -194,7 +194,7 @@ where if let Err(e) = run { tracing::error!( target: LOG_TARGET, - "Error running offchain workers at {:?}: {:?}", + "Error running offchain workers at {:?}: {}", at, e ); diff --git a/client/rpc-api/src/author/error.rs b/client/rpc-api/src/author/error.rs index 5b6bec7ed4bd..eee77edd5e20 100644 --- a/client/rpc-api/src/author/error.rs +++ b/client/rpc-api/src/author/error.rs @@ -103,7 +103,7 @@ impl From for rpc::Error { Error::Verification(e) => rpc::Error { code: rpc::ErrorCode::ServerError(VERIFICATION_ERROR), message: format!("Verification Error: {}", e).into(), - data: Some(format!("{:?}", e).into()), + data: Some(e.to_string().into()), }, Error::Pool(PoolError::InvalidTransaction(InvalidTransaction::Custom(e))) => rpc::Error { code: rpc::ErrorCode::ServerError(POOL_INVALID_TX), diff --git a/client/rpc-api/src/errors.rs b/client/rpc-api/src/errors.rs index 42e563342fa4..e59b1b0eda5c 100644 --- a/client/rpc-api/src/errors.rs +++ b/client/rpc-api/src/errors.rs @@ -18,11 +18,11 @@ use log::warn; -pub fn internal(e: E) -> jsonrpc_core::Error { - warn!("Unknown error: {:?}", e); +pub fn internal(e: E) -> jsonrpc_core::Error { + warn!("Unknown error: {}", e); jsonrpc_core::Error { code: jsonrpc_core::ErrorCode::InternalError, message: "Unknown error occurred".into(), - data: Some(format!("{:?}", e).into()), + data: Some(e.to_string().into()), } } diff --git a/client/service/src/chain_ops/check_block.rs b/client/service/src/chain_ops/check_block.rs index e12766659d9a..41a6c73c5f47 100644 --- a/client/service/src/chain_ops/check_block.rs +++ b/client/service/src/chain_ops/check_block.rs @@ -46,6 +46,6 @@ where import_blocks(client, import_queue, reader, true, true) }, Ok(None) => Box::pin(future::err("Unknown block".into())), - Err(e) => Box::pin(future::err(format!("Error reading block: {:?}", e).into())), + Err(e) => Box::pin(future::err(format!("Error reading block: {}", e).into())), } } diff --git a/client/service/src/chain_ops/import_blocks.rs b/client/service/src/chain_ops/import_blocks.rs index aa72b745c7ca..9d74fa1c276f 100644 --- a/client/service/src/chain_ops/import_blocks.rs +++ b/client/service/src/chain_ops/import_blocks.rs @@ -322,7 +322,7 @@ where for result in results { if let (Err(err), hash) = result { - warn!("There was an error importing block with hash {:?}: {:?}", hash, err); + warn!("There was an error importing block with hash {:?}: {}", hash, err); self.has_error = true; break } diff --git a/client/service/src/client/call_executor.rs b/client/service/src/client/call_executor.rs index a806b2dbb6d4..f271b35a69ce 100644 --- a/client/service/src/client/call_executor.rs +++ b/client/service/src/client/call_executor.rs @@ -285,7 +285,7 @@ where state_runtime_code.runtime_code().map_err(sp_blockchain::Error::RuntimeCode)?; self.executor .runtime_version(&mut ext, &runtime_code) - .map_err(|e| sp_blockchain::Error::VersionInvalid(format!("{:?}", e)).into()) + .map_err(|e| sp_blockchain::Error::VersionInvalid(e.to_string()).into()) } fn prove_execution( @@ -340,7 +340,7 @@ where Block: BlockT, { fn runtime_version(&self, at: &BlockId) -> Result { - CallExecutor::runtime_version(self, at).map_err(|e| format!("{:?}", e)) + CallExecutor::runtime_version(self, at).map_err(|e| e.to_string()) } } diff --git a/client/service/src/client/client.rs b/client/service/src/client/client.rs index e8ca5343aa0d..071af36a23f9 100644 --- a/client/service/src/client/client.rs +++ b/client/service/src/client/client.rs @@ -1116,7 +1116,7 @@ where }; let runtime_version = RuntimeVersionOf::runtime_version(executor, &mut ext, &runtime_code) - .map_err(|e| sp_blockchain::Error::VersionInvalid(format!("{:?}", e)))?; + .map_err(|e| sp_blockchain::Error::VersionInvalid(e.to_string()))?; Ok(runtime_version.state_version()) } else { Err(sp_blockchain::Error::VersionInvalid( @@ -1719,7 +1719,7 @@ where let storage_changes = match self.prepare_block_storage_changes(&mut import_block).map_err(|e| { - warn!("Block prepare storage changes error:\n{:?}", e); + warn!("Block prepare storage changes error: {}", e); ConsensusError::ClientImport(e.to_string()) })? { PrepareStorageChangesResult::Discard(res) => return Ok(res), @@ -1730,7 +1730,7 @@ where self.apply_block(operation, import_block, new_cache, storage_changes) }) .map_err(|e| { - warn!("Block import error:\n{:?}", e); + warn!("Block import error: {}", e); ConsensusError::ClientImport(e.to_string()).into() }) } diff --git a/client/service/src/client/wasm_override.rs b/client/service/src/client/wasm_override.rs index 86365f2d0cab..267aea070987 100644 --- a/client/service/src/client/wasm_override.rs +++ b/client/service/src/client/wasm_override.rs @@ -243,7 +243,7 @@ impl WasmOverride { hash: code_hash.into(), }, ) - .map_err(|e| WasmOverrideError::VersionInvalid(format!("{:?}", e)).into()) + .map_err(|e| WasmOverrideError::VersionInvalid(e.to_string()).into()) } } diff --git a/client/service/src/client/wasm_substitutes.rs b/client/service/src/client/wasm_substitutes.rs index a45eefb7b603..369067251267 100644 --- a/client/service/src/client/wasm_substitutes.rs +++ b/client/service/src/client/wasm_substitutes.rs @@ -151,6 +151,6 @@ where let mut ext = BasicExternalities::default(); executor .runtime_version(&mut ext, &code.runtime_code(None)) - .map_err(|e| WasmSubstituteError::VersionInvalid(format!("{:?}", e)).into()) + .map_err(|e| WasmSubstituteError::VersionInvalid(e.to_string()).into()) } } diff --git a/client/service/src/lib.rs b/client/service/src/lib.rs index 430a818c0f47..d158bbc42e94 100644 --- a/client/service/src/lib.rs +++ b/client/service/src/lib.rs @@ -509,7 +509,7 @@ where TransactionImport::Bad }, Err(e) => { - debug!("Error converting pool error: {:?}", e); + debug!("Error converting pool error: {}", e); // it is not bad at least, just some internal node logic error, so peer is // innocent. TransactionImport::KnownGood diff --git a/client/tracing/src/block/mod.rs b/client/tracing/src/block/mod.rs index 067cdafa0ae3..259827e4b47d 100644 --- a/client/tracing/src/block/mod.rs +++ b/client/tracing/src/block/mod.rs @@ -253,7 +253,7 @@ where self.client.runtime_api().execute_block(&parent_id, block) }) { return Err(Error::Dispatch( - format!("Failed to collect traces and execute block: {:?}", e).to_string(), + format!("Failed to collect traces and execute block: {}", e).to_string(), )) } } diff --git a/client/transaction-pool/api/src/lib.rs b/client/transaction-pool/api/src/lib.rs index 757674a03e85..7c90cd79ccae 100644 --- a/client/transaction-pool/api/src/lib.rs +++ b/client/transaction-pool/api/src/lib.rs @@ -355,7 +355,7 @@ impl OffchainSubmitTransaction for TP result.map(|_| ()).map_err(|e| { log::warn!( target: "txpool", - "(offchain call) Error submitting a transaction to the pool: {:?}", + "(offchain call) Error submitting a transaction to the pool: {}", e ) }) diff --git a/client/transaction-pool/src/api.rs b/client/transaction-pool/src/api.rs index de1c79534b38..12909f313d10 100644 --- a/client/transaction-pool/src/api.rs +++ b/client/transaction-pool/src/api.rs @@ -167,18 +167,14 @@ where &self, at: &BlockId, ) -> error::Result>> { - self.client - .to_number(at) - .map_err(|e| Error::BlockIdConversion(format!("{:?}", e))) + self.client.to_number(at).map_err(|e| Error::BlockIdConversion(e.to_string())) } fn block_id_to_hash( &self, at: &BlockId, ) -> error::Result>> { - self.client - .to_hash(at) - .map_err(|e| Error::BlockIdConversion(format!("{:?}", e))) + self.client.to_hash(at).map_err(|e| Error::BlockIdConversion(e.to_string())) } fn hash_and_length( @@ -224,7 +220,7 @@ where }?; let block_hash = client.to_hash(at) - .map_err(|e| Error::RuntimeApi(format!("{:?}", e)))? + .map_err(|e| Error::RuntimeApi(e.to_string()))? .ok_or_else(|| Error::RuntimeApi(format!("Could not get hash for block `{:?}`.", at)))?; use sp_api::Core; @@ -237,7 +233,7 @@ where .map_err(|e| Error::RuntimeApi(e.to_string())) } else { let block_number = client.to_number(at) - .map_err(|e| Error::RuntimeApi(format!("{:?}", e)))? + .map_err(|e| Error::RuntimeApi(e.to_string()))? .ok_or_else(|| Error::RuntimeApi(format!("Could not get number for block `{:?}`.", at)) )?; diff --git a/client/transaction-pool/src/lib.rs b/client/transaction-pool/src/lib.rs index 260d938217ad..ec93d1f7c51f 100644 --- a/client/transaction-pool/src/lib.rs +++ b/client/transaction-pool/src/lib.rs @@ -534,7 +534,7 @@ async fn prune_known_txs_for_block { - log::debug!(target: "txpool", "Error retrieving header for {:?}: {:?}", block_id, e); + log::debug!(target: "txpool", "Error retrieving header for {:?}: {}", block_id, e); return hashes }, }; if let Err(e) = pool.prune(&block_id, &BlockId::hash(*header.parent_hash()), &extrinsics).await { - log::error!("Cannot prune known in the pool {:?}!", e); + log::error!("Cannot prune known in the pool: {}", e); } hashes @@ -639,7 +639,7 @@ where .block_body(&BlockId::hash(hash)) .await .unwrap_or_else(|e| { - log::warn!("Failed to fetch block body {:?}!", e); + log::warn!("Failed to fetch block body: {}", e); None }) .unwrap_or_default() @@ -685,7 +685,7 @@ where { log::debug!( target: "txpool", - "[{:?}] Error re-submitting transactions: {:?}", + "[{:?}] Error re-submitting transactions: {}", id, e, ) diff --git a/client/transaction-pool/src/revalidation.rs b/client/transaction-pool/src/revalidation.rs index 22b526e9dfc6..e3641008a706 100644 --- a/client/transaction-pool/src/revalidation.rs +++ b/client/transaction-pool/src/revalidation.rs @@ -106,7 +106,7 @@ async fn batch_revalidate( Err(validation_err) => { log::debug!( target: "txpool", - "[{:?}]: Error during revalidation: {:?}. Removing.", + "[{:?}]: Removing due to error during revalidation: {}", ext_hash, validation_err ); diff --git a/frame/contracts/rpc/src/lib.rs b/frame/contracts/rpc/src/lib.rs index 580b74b5ca46..e83e4e6249b9 100644 --- a/frame/contracts/rpc/src/lib.rs +++ b/frame/contracts/rpc/src/lib.rs @@ -302,11 +302,11 @@ where } /// Converts a runtime trap into an RPC error. -fn runtime_error_into_rpc_err(err: impl std::fmt::Debug) -> Error { +fn runtime_error_into_rpc_err(err: impl std::fmt::Display) -> Error { Error { code: ErrorCode::ServerError(RUNTIME_ERROR), message: "Runtime error".into(), - data: Some(format!("{:?}", err).into()), + data: Some(err.to_string().into()), } } diff --git a/frame/merkle-mountain-range/rpc/src/lib.rs b/frame/merkle-mountain-range/rpc/src/lib.rs index b256ccdd7d32..bf3eb3b694e3 100644 --- a/frame/merkle-mountain-range/rpc/src/lib.rs +++ b/frame/merkle-mountain-range/rpc/src/lib.rs @@ -144,11 +144,11 @@ fn mmr_error_into_rpc_error(err: MmrError) -> Error { } /// Converts a runtime trap into an RPC error. -fn runtime_error_into_rpc_error(err: impl std::fmt::Debug) -> Error { +fn runtime_error_into_rpc_error(err: impl std::fmt::Display) -> Error { Error { code: ErrorCode::ServerError(RUNTIME_ERROR), message: "Runtime trapped".into(), - data: Some(format!("{:?}", err).into()), + data: Some(err.to_string().into()), } } diff --git a/frame/transaction-payment/rpc/src/lib.rs b/frame/transaction-payment/rpc/src/lib.rs index b2ff31618f78..29d94fa26010 100644 --- a/frame/transaction-payment/rpc/src/lib.rs +++ b/frame/transaction-payment/rpc/src/lib.rs @@ -103,7 +103,7 @@ where api.query_info(&at, uxt, encoded_len).map_err(|e| RpcError { code: ErrorCode::ServerError(Error::RuntimeError.into()), message: "Unable to query dispatch info.".into(), - data: Some(format!("{:?}", e).into()), + data: Some(e.to_string().into()), }) } @@ -127,7 +127,7 @@ where let fee_details = api.query_fee_details(&at, uxt, encoded_len).map_err(|e| RpcError { code: ErrorCode::ServerError(Error::RuntimeError.into()), message: "Unable to query fee details.".into(), - data: Some(format!("{:?}", e).into()), + data: Some(e.to_string().into()), })?; let try_into_rpc_balance = |value: Balance| { diff --git a/primitives/api/proc-macro/src/impl_runtime_apis.rs b/primitives/api/proc-macro/src/impl_runtime_apis.rs index 7241a1c2610d..f6de60e1c99b 100644 --- a/primitives/api/proc-macro/src/impl_runtime_apis.rs +++ b/primitives/api/proc-macro/src/impl_runtime_apis.rs @@ -297,7 +297,7 @@ fn generate_runtime_api_base_structures() -> Result { let state_version = self.call .runtime_version_at(&at) .map(|v| v.state_version()) - .map_err(|e| format!("Failed to get state version: {:?}", e))?; + .map_err(|e| format!("Failed to get state version: {}", e))?; self.changes.replace(Default::default()).into_storage_changes( backend, diff --git a/primitives/blockchain/src/error.rs b/primitives/blockchain/src/error.rs index bbd65e002a3b..c82fb9bebf4e 100644 --- a/primitives/blockchain/src/error.rs +++ b/primitives/blockchain/src/error.rs @@ -69,7 +69,7 @@ pub enum Error { ExtrinsicRootInvalid { received: String, expected: String }, // `inner` cannot be made member, since it lacks `std::error::Error` trait bounds. - #[error("Execution failed: {0:?}")] + #[error("Execution failed: {0}")] Execution(Box), #[error("Blockchain")] diff --git a/primitives/consensus/common/src/lib.rs b/primitives/consensus/common/src/lib.rs index 492ad83ddf5b..edf393fa229a 100644 --- a/primitives/consensus/common/src/lib.rs +++ b/primitives/consensus/common/src/lib.rs @@ -98,7 +98,7 @@ pub trait Environment { + Unpin + 'static; /// Error which can occur upon creation. - type Error: From + std::fmt::Debug + 'static; + type Error: From + std::error::Error + 'static; /// Initialize the proposal logic on top of a specific header. Provide /// the authorities at that header. @@ -191,7 +191,7 @@ mod private { /// Proposers are generic over bits of "consensus data" which are engine-specific. pub trait Proposer { /// Error type which can occur when proposing or evaluating. - type Error: From + std::fmt::Debug + 'static; + type Error: From + std::error::Error + 'static; /// The transaction type used by the backend. type Transaction: Default + Send + 'static; /// Future that resolves to a committed proposal with an optional proof. diff --git a/primitives/io/Cargo.toml b/primitives/io/Cargo.toml index 207a1a23e81d..b9cbdbaa70e7 100644 --- a/primitives/io/Cargo.toml +++ b/primitives/io/Cargo.toml @@ -66,3 +66,22 @@ with-tracing = [ disable_panic_handler = [] disable_oom = [] disable_allocator = [] + +# This feature flag controls the runtime's behavior when encountering +# a panic or when it runs out of memory, improving the diagnostics. +# +# When enabled the runtime will marshal the relevant error message +# to the host through the `PanicHandler::abort_on_panic` runtime interface. +# This gives the caller direct programmatic access to the error message. +# +# When disabled the error message will only be printed out in the +# logs, with the caller receving a generic "wasm `unreachable` instruction executed" +# error message. +# +# This has no effect if both `disable_panic_handler` and `disable_oom` +# are enabled. +# +# WARNING: Enabling this feature flag requires the `PanicHandler::abort_on_panic` +# host function to be supported by the host. Do *not* enable it for your +# runtime without first upgrading your host client! +improved_panic_error_reporting = [] diff --git a/primitives/io/src/lib.rs b/primitives/io/src/lib.rs index 76ced407090c..db86fe096415 100644 --- a/primitives/io/src/lib.rs +++ b/primitives/io/src/lib.rs @@ -1290,6 +1290,17 @@ pub trait Allocator { } } +/// WASM-only interface which allows for aborting the execution in case +/// of an unrecoverable error. +#[runtime_interface(wasm_only)] +pub trait PanicHandler { + /// Aborts the current execution with the given error message. + #[trap_on_return] + fn abort_on_panic(&mut self, message: &str) { + self.register_panic_error_message(message); + } +} + /// Interface that provides functions for logging from within the runtime. #[runtime_interface] pub trait Logging { @@ -1588,14 +1599,14 @@ pub trait RuntimeTasks { } /// Allocator used by Substrate when executing the Wasm runtime. -#[cfg(not(feature = "std"))] +#[cfg(all(target_arch = "wasm32", not(feature = "std")))] struct WasmAllocator; -#[cfg(all(not(feature = "disable_allocator"), not(feature = "std")))] +#[cfg(all(target_arch = "wasm32", not(feature = "disable_allocator"), not(feature = "std")))] #[global_allocator] static ALLOCATOR: WasmAllocator = WasmAllocator; -#[cfg(not(feature = "std"))] +#[cfg(all(target_arch = "wasm32", not(feature = "std")))] mod allocator_impl { use super::*; use core::alloc::{GlobalAlloc, Layout}; @@ -1617,16 +1628,30 @@ mod allocator_impl { #[no_mangle] pub fn panic(info: &core::panic::PanicInfo) -> ! { let message = sp_std::alloc::format!("{}", info); - logging::log(LogLevel::Error, "runtime", message.as_bytes()); - core::arch::wasm32::unreachable(); + #[cfg(feature = "improved_panic_error_reporting")] + { + panic_handler::abort_on_panic(&message); + } + #[cfg(not(feature = "improved_panic_error_reporting"))] + { + logging::log(LogLevel::Error, "runtime", message.as_bytes()); + core::arch::wasm32::unreachable(); + } } /// A default OOM handler for WASM environment. #[cfg(all(not(feature = "disable_oom"), not(feature = "std")))] #[alloc_error_handler] pub fn oom(_: core::alloc::Layout) -> ! { - logging::log(LogLevel::Error, "runtime", b"Runtime memory exhausted. Aborting"); - core::arch::wasm32::unreachable(); + #[cfg(feature = "improved_panic_error_reporting")] + { + panic_handler::abort_on_panic("Runtime memory exhausted."); + } + #[cfg(not(feature = "improved_panic_error_reporting"))] + { + logging::log(LogLevel::Error, "runtime", b"Runtime memory exhausted. Aborting"); + core::arch::wasm32::unreachable(); + } } /// Type alias for Externalities implementation used in tests. @@ -1646,6 +1671,7 @@ pub type SubstrateHostFunctions = ( crypto::HostFunctions, hashing::HostFunctions, allocator::HostFunctions, + panic_handler::HostFunctions, logging::HostFunctions, sandbox::HostFunctions, crate::trie::HostFunctions, diff --git a/primitives/runtime-interface/proc-macro/src/runtime_interface/bare_function_interface.rs b/primitives/runtime-interface/proc-macro/src/runtime_interface/bare_function_interface.rs index a06a1f9bda73..b5745e25deb4 100644 --- a/primitives/runtime-interface/proc-macro/src/runtime_interface/bare_function_interface.rs +++ b/primitives/runtime-interface/proc-macro/src/runtime_interface/bare_function_interface.rs @@ -32,11 +32,12 @@ use crate::utils::{ create_exchangeable_host_function_ident, create_function_ident_with_version, generate_crate_access, get_function_argument_names, get_function_arguments, - get_runtime_interface, + get_runtime_interface, RuntimeInterfaceFunction, }; use syn::{ - parse_quote, spanned::Spanned, FnArg, Ident, ItemTrait, Result, Signature, TraitItemMethod, + parse_quote, spanned::Spanned, FnArg, Ident, ItemTrait, Result, Signature, Token, + TraitItemMethod, }; use proc_macro2::{Span, TokenStream}; @@ -74,14 +75,14 @@ pub fn generate(trait_def: &ItemTrait, is_wasm_only: bool, tracing: bool) -> Res /// Generates the bare function implementation for the given method for the host and wasm side. fn function_for_method( - method: &TraitItemMethod, + method: &RuntimeInterfaceFunction, latest_version: u32, is_wasm_only: bool, ) -> Result { let std_impl = if !is_wasm_only { function_std_latest_impl(method, latest_version)? } else { quote!() }; - let no_std_impl = function_no_std_impl(method)?; + let no_std_impl = function_no_std_impl(method, is_wasm_only)?; Ok(quote! { #std_impl @@ -91,20 +92,46 @@ fn function_for_method( } /// Generates the bare function implementation for `cfg(not(feature = "std"))`. -fn function_no_std_impl(method: &TraitItemMethod) -> Result { +fn function_no_std_impl( + method: &RuntimeInterfaceFunction, + is_wasm_only: bool, +) -> Result { let function_name = &method.sig.ident; let host_function_name = create_exchangeable_host_function_ident(&method.sig.ident); let args = get_function_arguments(&method.sig); let arg_names = get_function_argument_names(&method.sig); - let return_value = &method.sig.output; + let return_value = if method.should_trap_on_return() { + syn::ReturnType::Type( + ]>::default(), + Box::new(syn::TypeNever { bang_token: ::default() }.into()), + ) + } else { + method.sig.output.clone() + }; + let maybe_unreachable = if method.should_trap_on_return() { + quote! { + ; core::arch::wasm32::unreachable(); + } + } else { + quote! {} + }; + let attrs = method.attrs.iter().filter(|a| !a.path.is_ident("version")); + let cfg_wasm_only = if is_wasm_only { + quote! { #[cfg(target_arch = "wasm32")] } + } else { + quote! {} + }; + Ok(quote! { + #cfg_wasm_only #[cfg(not(feature = "std"))] #( #attrs )* pub fn #function_name( #( #args, )* ) #return_value { // Call the host function #host_function_name.get()( #( #arg_names, )* ) + #maybe_unreachable } }) } diff --git a/primitives/runtime-interface/proc-macro/src/runtime_interface/host_function_interface.rs b/primitives/runtime-interface/proc-macro/src/runtime_interface/host_function_interface.rs index 626e309cc0e1..1566bbf302c3 100644 --- a/primitives/runtime-interface/proc-macro/src/runtime_interface/host_function_interface.rs +++ b/primitives/runtime-interface/proc-macro/src/runtime_interface/host_function_interface.rs @@ -26,7 +26,7 @@ use crate::utils::{ create_host_function_ident, generate_crate_access, get_function_argument_names, get_function_argument_names_and_types_without_ref, get_function_argument_types, get_function_argument_types_ref_and_mut, get_function_argument_types_without_ref, - get_function_arguments, get_runtime_interface, + get_function_arguments, get_runtime_interface, RuntimeInterfaceFunction, }; use syn::{ @@ -205,7 +205,7 @@ fn generate_host_functions_struct( /// implementation of the function. fn generate_host_function_implementation( trait_name: &Ident, - method: &TraitItemMethod, + method: &RuntimeInterfaceFunction, version: u32, is_wasm_only: bool, ) -> Result<(TokenStream, Ident, TokenStream)> { diff --git a/primitives/runtime-interface/proc-macro/src/runtime_interface/trait_decl_impl.rs b/primitives/runtime-interface/proc-macro/src/runtime_interface/trait_decl_impl.rs index c48da3b78851..0ae0f5260286 100644 --- a/primitives/runtime-interface/proc-macro/src/runtime_interface/trait_decl_impl.rs +++ b/primitives/runtime-interface/proc-macro/src/runtime_interface/trait_decl_impl.rs @@ -153,7 +153,7 @@ fn impl_trait_for_externalities(trait_def: &ItemTrait, is_wasm_only: bool) -> Re let crate_ = generate_crate_access(); let interface = get_runtime_interface(trait_def)?; let methods = interface.all_versions().map(|(version, method)| { - let mut cloned = method.clone(); + let mut cloned = (*method).clone(); cloned.attrs.retain(|a| !a.path.is_ident("version")); cloned.sig.ident = create_function_ident_with_version(&cloned.sig.ident, version); cloned diff --git a/primitives/runtime-interface/proc-macro/src/utils.rs b/primitives/runtime-interface/proc-macro/src/utils.rs index bc690eb21a9b..19f7fea023c3 100644 --- a/primitives/runtime-interface/proc-macro/src/utils.rs +++ b/primitives/runtime-interface/proc-macro/src/utils.rs @@ -39,18 +39,64 @@ mod attributes { syn::custom_keyword!(register_only); } +/// A concrete, specific version of a runtime interface function. +pub struct RuntimeInterfaceFunction { + item: TraitItemMethod, + should_trap_on_return: bool, +} + +impl std::ops::Deref for RuntimeInterfaceFunction { + type Target = TraitItemMethod; + fn deref(&self) -> &Self::Target { + &self.item + } +} + +impl RuntimeInterfaceFunction { + fn new(item: &TraitItemMethod) -> Result { + let mut item = item.clone(); + let mut should_trap_on_return = false; + item.attrs.retain(|attr| { + if attr.path.is_ident("trap_on_return") { + should_trap_on_return = true; + false + } else { + true + } + }); + + if should_trap_on_return { + if !matches!(item.sig.output, syn::ReturnType::Default) { + return Err(Error::new( + item.sig.ident.span(), + "Methods marked as #[trap_on_return] cannot return anything", + )) + } + } + + Ok(Self { item, should_trap_on_return }) + } + + pub fn should_trap_on_return(&self) -> bool { + self.should_trap_on_return + } +} + /// Runtime interface function with all associated versions of this function. -pub struct RuntimeInterfaceFunction<'a> { +struct RuntimeInterfaceFunctionSet { latest_version_to_call: Option, - versions: BTreeMap, + versions: BTreeMap, } -impl<'a> RuntimeInterfaceFunction<'a> { - fn new(version: VersionAttribute, trait_item: &'a TraitItemMethod) -> Self { - Self { +impl RuntimeInterfaceFunctionSet { + fn new(version: VersionAttribute, trait_item: &TraitItemMethod) -> Result { + Ok(Self { latest_version_to_call: version.is_callable().then(|| version.version), - versions: BTreeMap::from([(version.version, trait_item)]), - } + versions: BTreeMap::from([( + version.version, + RuntimeInterfaceFunction::new(trait_item)?, + )]), + }) } /// Returns the latest version of this runtime interface function plus the actual function @@ -59,11 +105,11 @@ impl<'a> RuntimeInterfaceFunction<'a> { /// This isn't required to be the latest version, because a runtime interface function can be /// annotated with `register_only` to ensure that the host exposes the host function but it /// isn't used when compiling the runtime. - pub fn latest_version_to_call(&self) -> Option<(u32, &TraitItemMethod)> { + pub fn latest_version_to_call(&self) -> Option<(u32, &RuntimeInterfaceFunction)> { self.latest_version_to_call.map(|v| { ( v, - *self.versions.get(&v).expect( + self.versions.get(&v).expect( "If latest_version_to_call has a value, the key with this value is in the versions; qed", ), ) @@ -74,7 +120,7 @@ impl<'a> RuntimeInterfaceFunction<'a> { fn add_version( &mut self, version: VersionAttribute, - trait_item: &'a TraitItemMethod, + trait_item: &TraitItemMethod, ) -> Result<()> { if let Some(existing_item) = self.versions.get(&version.version) { let mut err = Error::new(trait_item.span(), "Duplicated version attribute"); @@ -86,7 +132,8 @@ impl<'a> RuntimeInterfaceFunction<'a> { return Err(err) } - self.versions.insert(version.version, trait_item); + self.versions + .insert(version.version, RuntimeInterfaceFunction::new(trait_item)?); if self.latest_version_to_call.map_or(true, |v| v < version.version) && version.is_callable() { @@ -98,22 +145,24 @@ impl<'a> RuntimeInterfaceFunction<'a> { } /// All functions of a runtime interface grouped by the function names. -pub struct RuntimeInterface<'a> { - items: BTreeMap>, +pub struct RuntimeInterface { + items: BTreeMap, } -impl<'a> RuntimeInterface<'a> { +impl RuntimeInterface { /// Returns an iterator over all runtime interface function - /// [`latest_version_to_call`](RuntimeInterfaceFunction::latest_version). - pub fn latest_versions_to_call(&self) -> impl Iterator { + /// [`latest_version_to_call`](RuntimeInterfaceFunctionSet::latest_version). + pub fn latest_versions_to_call( + &self, + ) -> impl Iterator { self.items.iter().filter_map(|(_, item)| item.latest_version_to_call()) } - pub fn all_versions(&self) -> impl Iterator { + pub fn all_versions(&self) -> impl Iterator { self.items .iter() .flat_map(|(_, item)| item.versions.iter()) - .map(|(v, i)| (*v, *i)) + .map(|(v, i)| (*v, i)) } } @@ -288,8 +337,8 @@ fn get_item_version(item: &TraitItemMethod) -> Result> } /// Returns all runtime interface members, with versions. -pub fn get_runtime_interface<'a>(trait_def: &'a ItemTrait) -> Result> { - let mut functions: BTreeMap> = BTreeMap::new(); +pub fn get_runtime_interface(trait_def: &ItemTrait) -> Result { + let mut functions: BTreeMap = BTreeMap::new(); for item in get_trait_methods(trait_def) { let name = item.sig.ident.clone(); @@ -301,7 +350,7 @@ pub fn get_runtime_interface<'a>(trait_def: &'a ItemTrait) -> Result { - entry.insert(RuntimeInterfaceFunction::new(version, item)); + entry.insert(RuntimeInterfaceFunctionSet::new(version, item)?); }, Entry::Occupied(mut entry) => { entry.get_mut().add_version(version, item)?; diff --git a/primitives/runtime/src/traits.rs b/primitives/runtime/src/traits.rs index b2e218cb9db7..6a829ea6bba7 100644 --- a/primitives/runtime/src/traits.rs +++ b/primitives/runtime/src/traits.rs @@ -1585,7 +1585,7 @@ impl Printable for Tuple { #[cfg(feature = "std")] pub trait BlockIdTo { /// The error type that will be returned by the functions. - type Error: std::fmt::Debug; + type Error: std::error::Error; /// Convert the given `block_id` to the corresponding block hash. fn to_hash( diff --git a/primitives/wasm-interface/src/lib.rs b/primitives/wasm-interface/src/lib.rs index 21dbf9609ecf..d57666f12689 100644 --- a/primitives/wasm-interface/src/lib.rs +++ b/primitives/wasm-interface/src/lib.rs @@ -305,6 +305,29 @@ pub trait FunctionContext { fn deallocate_memory(&mut self, ptr: Pointer) -> Result<()>; /// Provides access to the sandbox. fn sandbox(&mut self) -> &mut dyn Sandbox; + + /// Registers a panic error message within the executor. + /// + /// This is meant to be used in situations where the runtime + /// encounters an unrecoverable error and intends to panic. + /// + /// Panicking in WASM is done through the [`unreachable`](https://webassembly.github.io/spec/core/syntax/instructions.html#syntax-instr-control) + /// instruction which causes an unconditional trap and immediately aborts + /// the execution. It does not however allow for any diagnostics to be + /// passed through to the host, so while we do know that *something* went + /// wrong we don't have any direct indication of what *exactly* went wrong. + /// + /// As a workaround we use this method right before the execution is + /// actually aborted to pass an error message to the host so that it + /// can associate it with the next trap, and return that to the caller. + /// + /// A WASM trap should be triggered immediately after calling this method; + /// otherwise the error message might be associated with a completely + /// unrelated trap. + /// + /// It should only be called once, however calling it more than once + /// is harmless and will overwrite the previously set error message. + fn register_panic_error_message(&mut self, message: &str); } /// Sandbox memory identifier. diff --git a/utils/frame/benchmarking-cli/src/command.rs b/utils/frame/benchmarking-cli/src/command.rs index a5b53bcf99c7..0ced8b28ce01 100644 --- a/utils/frame/benchmarking-cli/src/command.rs +++ b/utils/frame/benchmarking-cli/src/command.rs @@ -165,7 +165,7 @@ impl BenchmarkCmd { sp_core::testing::TaskExecutor::new(), ) .execute(strategy.into()) - .map_err(|e| format!("Error getting benchmark list: {:?}", e))?; + .map_err(|e| format!("Error getting benchmark list: {}", e))?; let (list, storage_info) = <(Vec, Vec) as Decode>::decode(&mut &result[..]) @@ -265,7 +265,7 @@ impl BenchmarkCmd { ) .execute(strategy.into()) .map_err(|e| { - format!("Error executing and verifying runtime benchmark: {:?}", e) + format!("Error executing and verifying runtime benchmark: {}", e) })?; } // Do one loop of DB tracking. @@ -290,7 +290,7 @@ impl BenchmarkCmd { sp_core::testing::TaskExecutor::new(), ) .execute(strategy.into()) - .map_err(|e| format!("Error executing runtime benchmark: {:?}", e))?; + .map_err(|e| format!("Error executing runtime benchmark: {}", e))?; let batch = , String> as Decode>::decode( @@ -322,7 +322,7 @@ impl BenchmarkCmd { sp_core::testing::TaskExecutor::new(), ) .execute(strategy.into()) - .map_err(|e| format!("Error executing runtime benchmark: {:?}", e))?; + .map_err(|e| format!("Error executing runtime benchmark: {}", e))?; let batch = , String> as Decode>::decode( diff --git a/utils/frame/rpc/system/src/lib.rs b/utils/frame/rpc/system/src/lib.rs index df24e208b51a..eb1b258c97ec 100644 --- a/utils/frame/rpc/system/src/lib.rs +++ b/utils/frame/rpc/system/src/lib.rs @@ -106,7 +106,7 @@ where let nonce = api.account_nonce(&at, account.clone()).map_err(|e| RpcError { code: ErrorCode::ServerError(Error::RuntimeError.into()), message: "Unable to query nonce.".into(), - data: Some(format!("{:?}", e).into()), + data: Some(e.to_string().into()), })?; Ok(adjust_nonce(&*self.pool, account, nonce)) @@ -141,7 +141,7 @@ where let result = api.apply_extrinsic(&at, uxt).map_err(|e| RpcError { code: ErrorCode::ServerError(Error::RuntimeError.into()), message: "Unable to dry run extrinsic.".into(), - data: Some(format!("{:?}", e).into()), + data: Some(e.to_string().into()), })?; Ok(Encode::encode(&result).into()) diff --git a/utils/frame/try-runtime/cli/src/lib.rs b/utils/frame/try-runtime/cli/src/lib.rs index 4c7103328851..ae7a1c3ae87c 100644 --- a/utils/frame/try-runtime/cli/src/lib.rs +++ b/utils/frame/try-runtime/cli/src/lib.rs @@ -707,7 +707,7 @@ pub(crate) fn state_machine_call(Into::into)?; Ok((changes, encoded_results)) @@ -748,7 +748,7 @@ pub(crate) fn state_machine_call_with_proof(Into::into)?; let proof = proving_backend.extract_proof(); From 1539807cfb76fac662046e9ba32c04920ff32e6d Mon Sep 17 00:00:00 2001 From: driemworks Date: Wed, 9 Feb 2022 16:33:28 -0500 Subject: [PATCH 471/695] specify ipfs version, update tests --- Cargo.lock | 12 +- .../pallets/iris-session/src/mock.rs | 78 +++--- .../pallets/iris-session/src/tests.rs | 222 ++++++++++-------- client/offchain/Cargo.toml | 3 +- client/service/src/task_manager/tests.rs | 55 +++-- 5 files changed, 206 insertions(+), 164 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d963ee0a0580..131e69b5b8ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3032,7 +3032,7 @@ dependencies = [ [[package]] name = "ipfs" version = "0.2.1" -source = "git+https://github.com/rs-ipfs/rust-ipfs?branch=master#111f116e366e8f3f9b409d1c92be6ac51f7009f4" +source = "git+https://github.com/rs-ipfs/rust-ipfs?rev=ed430faed019e693a2e66844e6d9ded7624230f5#ed430faed019e693a2e66844e6d9ded7624230f5" dependencies = [ "anyhow", "async-stream", @@ -3045,8 +3045,8 @@ dependencies = [ "fs2", "futures 0.3.17", "hash_hasher", - "ipfs-bitswap 0.1.0 (git+https://github.com/rs-ipfs/rust-ipfs?branch=master)", - "ipfs-unixfs 0.2.0 (git+https://github.com/rs-ipfs/rust-ipfs?branch=master)", + "ipfs-bitswap 0.1.0 (git+https://github.com/rs-ipfs/rust-ipfs?rev=ed430faed019e693a2e66844e6d9ded7624230f5)", + "ipfs-unixfs 0.2.0 (git+https://github.com/rs-ipfs/rust-ipfs?rev=ed430faed019e693a2e66844e6d9ded7624230f5)", "libp2p", "multibase 0.9.1", "multihash 0.11.4", @@ -3106,7 +3106,7 @@ dependencies = [ [[package]] name = "ipfs-bitswap" version = "0.1.0" -source = "git+https://github.com/rs-ipfs/rust-ipfs?branch=master#111f116e366e8f3f9b409d1c92be6ac51f7009f4" +source = "git+https://github.com/rs-ipfs/rust-ipfs?rev=ed430faed019e693a2e66844e6d9ded7624230f5#ed430faed019e693a2e66844e6d9ded7624230f5" dependencies = [ "cid 0.5.1", "fnv", @@ -3146,7 +3146,7 @@ dependencies = [ [[package]] name = "ipfs-unixfs" version = "0.2.0" -source = "git+https://github.com/rs-ipfs/rust-ipfs?branch=master#111f116e366e8f3f9b409d1c92be6ac51f7009f4" +source = "git+https://github.com/rs-ipfs/rust-ipfs?rev=ed430faed019e693a2e66844e6d9ded7624230f5#ed430faed019e693a2e66844e6d9ded7624230f5" dependencies = [ "cid 0.5.1", "either", @@ -8551,7 +8551,7 @@ dependencies = [ "hex", "hyper 0.14.13", "hyper-rustls", - "ipfs 0.2.1 (git+https://github.com/rs-ipfs/rust-ipfs?branch=master)", + "ipfs 0.2.1 (git+https://github.com/rs-ipfs/rust-ipfs?rev=ed430faed019e693a2e66844e6d9ded7624230f5)", "lazy_static", "log 0.4.14", "num_cpus", diff --git a/bin/node-template/pallets/iris-session/src/mock.rs b/bin/node-template/pallets/iris-session/src/mock.rs index 504e1ecb5844..fb1565e8505a 100644 --- a/bin/node-template/pallets/iris-session/src/mock.rs +++ b/bin/node-template/pallets/iris-session/src/mock.rs @@ -315,48 +315,48 @@ pub fn new_test_ext() -> sp_io::TestExternalities { .assimilate_storage(&mut t) .unwrap(); - // let (pair1, _) = sp_core::sr25519::Pair::generate(); - // let (pair2, _) = sp_core::sr25519::Pair::generate(); - // let (pair3, _) = sp_core::sr25519::Pair::generate(); - // pallet_balances::GenesisConfig:: { - // balances: vec![(pair1.public(), 10), (pair2.public(), 20), (pair3.public(), 30)], - // } - // .assimilate_storage(&mut t) - // .unwrap(); + let (pair1, _) = sp_core::sr25519::Pair::generate(); + let (pair2, _) = sp_core::sr25519::Pair::generate(); + let (pair3, _) = sp_core::sr25519::Pair::generate(); + pallet_balances::GenesisConfig:: { + balances: vec![(pair1.public(), 10), (pair2.public(), 20), (pair3.public(), 30)], + } + .assimilate_storage(&mut t) + .unwrap(); sp_io::TestExternalities::new(t) } // Build genesis storage according to the mock runtime. -// pub fn new_test_ext_funded(pair1_funded: sp_core::sr25519::Pair) -> sp_io::TestExternalities { -// let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); -// let keys: Vec<_> = NEXT_VALIDATORS -// .with(|l| l.borrow().iter().cloned().map(|i| (i, i, UintAuthorityId(i).into())).collect()); -// BasicExternalities::execute_with_storage(&mut t, || { -// for (ref k, ..) in &keys { -// frame_system::Pallet::::inc_providers(k); -// } -// frame_system::Pallet::::inc_providers(&4); -// frame_system::Pallet::::inc_providers(&69); -// }); - -// pallet_iris_session::GenesisConfig:: { -// initial_validators: keys.iter().map(|x| x.0).collect::>(), -// } -// .assimilate_storage(&mut t) -// .unwrap(); +pub fn new_test_ext_funded(pair1_funded: sp_core::sr25519::Pair) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + let keys: Vec<_> = NEXT_VALIDATORS + .with(|l| l.borrow().iter().cloned().map(|i| (i.0, i.0, i.1.into())).collect()); + BasicExternalities::execute_with_storage(&mut t, || { + for (ref k, ..) in &keys { + frame_system::Pallet::::inc_providers(k); + } + // frame_system::Pallet::::inc_providers(&4); + // frame_system::Pallet::::inc_providers(&69); + }); + + pallet_iris_session::GenesisConfig:: { + initial_validators: keys.iter().map(|x| x.0).collect::>(), + } + .assimilate_storage(&mut t) + .unwrap(); -// pallet_session::GenesisConfig:: { keys: keys.clone() } -// .assimilate_storage(&mut t) -// .unwrap(); - -// let (pair2, _) = sp_core::sr25519::Pair::generate(); -// let (pair3, _) = sp_core::sr25519::Pair::generate(); -// pallet_balances::GenesisConfig:: { -// balances: vec![(pair1_funded.public(), 10), (pair2.public(), 20), (pair3.public(), 30)], -// } -// .assimilate_storage(&mut t) -// .unwrap(); - -// sp_io::TestExternalities::new(t) -// } + pallet_session::GenesisConfig:: { keys: keys.clone() } + .assimilate_storage(&mut t) + .unwrap(); + + let (pair2, _) = sp_core::sr25519::Pair::generate(); + let (pair3, _) = sp_core::sr25519::Pair::generate(); + pallet_balances::GenesisConfig:: { + balances: vec![(pair1_funded.public(), 10), (pair2.public(), 20), (pair3.public(), 30)], + } + .assimilate_storage(&mut t) + .unwrap(); + + sp_io::TestExternalities::new(t) +} diff --git a/bin/node-template/pallets/iris-session/src/tests.rs b/bin/node-template/pallets/iris-session/src/tests.rs index 8c8c06946898..c2dbf2e57b82 100644 --- a/bin/node-template/pallets/iris-session/src/tests.rs +++ b/bin/node-template/pallets/iris-session/src/tests.rs @@ -3,7 +3,7 @@ #![cfg(test)] use super::*; -use crate::mock::{authorities, new_test_ext, Origin, Session, Test, IrisSession}; +use crate::mock::{authorities, new_test_ext, new_test_ext_funded, Origin, Session, Test, IrisSession, IrisAssets}; use frame_support::{assert_noop, assert_ok, pallet_prelude::*}; use sp_runtime::testing::UintAuthorityId; use sp_core::Pair; @@ -64,125 +64,153 @@ fn iris_session_remove_validator_updates_validators_list() { sp_core::sr25519::Pair::generate_with_phrase(Some("0")).0.public(), UintAuthorityId(0) ); + let V1: (sp_core::sr25519::Public, UintAuthorityId) = ( + sp_core::sr25519::Pair::generate_with_phrase(Some("1")).0.public(), + UintAuthorityId(1) + ); let V2: (sp_core::sr25519::Public, UintAuthorityId) = ( sp_core::sr25519::Pair::generate_with_phrase(Some("2")).0.public(), UintAuthorityId(2) ); new_test_ext().execute_with(|| { - assert_ok!(crate::ValidatorSet::remove_validator(Origin::root(), 2)); - assert_eq!(crate::ValidatorSet::validators(), vec![V0.0, V2.0]); + assert_ok!(IrisSession::remove_validator(Origin::root(), V1.0)); + assert_eq!(IrisSession::validators(), vec![V0.0, V2.0]); }); } #[test] fn iris_session_add_validator_fails_with_invalid_origin() { + let V3: (sp_core::sr25519::Public, UintAuthorityId) = ( + sp_core::sr25519::Pair::generate_with_phrase(Some("3")).0.public(), + UintAuthorityId(3) + ); new_test_ext().execute_with(|| { - assert_noop!(crate::ValidatorSet::add_validator(Origin::signed(1), 4), DispatchError::BadOrigin); + assert_noop!(IrisSession::add_validator(Origin::signed(V3.0.clone()), V3.0), DispatchError::BadOrigin); }); } -// #[test] -// fn iris_session_remove_validator_fails_with_invalid_origin() { -// new_test_ext().execute_with(|| { -// assert_noop!( -// ValidatorSet::remove_validator(Origin::signed(1), 4), -// DispatchError::BadOrigin -// ); -// }); -// } +#[test] +fn iris_session_remove_validator_fails_with_invalid_origin() { + let V3: (sp_core::sr25519::Public, UintAuthorityId) = ( + sp_core::sr25519::Pair::generate_with_phrase(Some("3")).0.public(), + UintAuthorityId(3) + ); + new_test_ext().execute_with(|| { + assert_noop!( + IrisSession::remove_validator(Origin::signed(V3.0.clone()), V3.0), + DispatchError::BadOrigin + ); + }); +} -// #[test] -// fn iris_session_duplicate_check() { -// new_test_ext().execute_with(|| { -// assert_ok!(ValidatorSet::add_validator(Origin::root(), 4)); -// assert_eq!(ValidatorSet::validators(), vec![1u64, 2u64, 3u64, 4u64]); -// assert_noop!(ValidatorSet::add_validator(Origin::root(), 4), Error::::Duplicate); -// }); -// } +#[test] +fn iris_session_duplicate_check() { + let V0: (sp_core::sr25519::Public, UintAuthorityId) = ( + sp_core::sr25519::Pair::generate_with_phrase(Some("0")).0.public(), + UintAuthorityId(0) + ); + let V1: (sp_core::sr25519::Public, UintAuthorityId) = ( + sp_core::sr25519::Pair::generate_with_phrase(Some("1")).0.public(), + UintAuthorityId(1) + ); + let V2: (sp_core::sr25519::Public, UintAuthorityId) = ( + sp_core::sr25519::Pair::generate_with_phrase(Some("2")).0.public(), + UintAuthorityId(2) + ); + let V3: (sp_core::sr25519::Public, UintAuthorityId) = ( + sp_core::sr25519::Pair::generate_with_phrase(Some("3")).0.public(), + UintAuthorityId(3) + ); + new_test_ext().execute_with(|| { + assert_ok!(IrisSession::add_validator(Origin::root(), V3.0)); + assert_eq!(IrisSession::validators(), vec![V0.0, V1.0, V2.0, V3.0]); + assert_noop!(IrisSession::add_validator(Origin::root(), V3.0), Error::::Duplicate); + }); +} // RPC tests -// #[test] -// fn iris_session_submit_rpc_ready_works_for_valid_values() { -// let (p, _) = sp_core::sr25519::Pair::generate(); -// new_test_ext_funded(p.clone()).execute_with(|| { -// assert_ok!(Iris::submit_rpc_ready( -// Origin::signed(p.clone().public()), -// p.clone().public(), -// )); -// }); -// } +#[test] +fn iris_session_submit_rpc_ready_works_for_valid_values() { + let (p, _) = sp_core::sr25519::Pair::generate(); + new_test_ext_funded(p.clone()).execute_with(|| { + assert_ok!(IrisSession::submit_rpc_ready( + Origin::signed(p.clone().public()), + 1, + )); + }); +} -// // test OCW functionality -// // can add bytes to network +// test OCW functionality +// can add bytes to network -// #[test] -// fn iris_can_add_bytes_to_ipfs() { -// let (p, _) = sp_core::sr25519::Pair::generate(); -// let (offchain, state) = testing::TestOffchainExt::new(); -// let (pool, _) = testing::TestTransactionPoolExt::new(); -// const PHRASE: &str = -// "news slush supreme milk chapter athlete soap sausage put clutch what kitten"; -// let keystore = KeyStore::new(); -// SyncCryptoStore::sr25519_generate_new( -// &keystore, -// crate::KEY_TYPE, -// Some(&format!("{}/hunter1", PHRASE)), -// ) -// .unwrap(); +#[test] +fn iris_can_add_bytes_to_ipfs() { + let (p, _) = sp_core::sr25519::Pair::generate(); + let (offchain, state) = testing::TestOffchainExt::new(); + let (pool, _) = testing::TestTransactionPoolExt::new(); + const PHRASE: &str = + "news slush supreme milk chapter athlete soap sausage put clutch what kitten"; + let keystore = KeyStore::new(); + SyncCryptoStore::sr25519_generate_new( + &keystore, + crate::KEY_TYPE, + Some(&format!("{}/hunter1", PHRASE)), + ) + .unwrap(); -// let mut t = new_test_ext_funded(p.clone()); -// t.register_extension(OffchainWorkerExt::new(offchain)); -// t.register_extension(TransactionPoolExt::new(pool)); -// t.register_extension(KeystoreExt(Arc::new(keystore))); + let mut t = new_test_ext_funded(p.clone()); + t.register_extension(OffchainWorkerExt::new(offchain)); + t.register_extension(TransactionPoolExt::new(pool)); + t.register_extension(KeystoreExt(Arc::new(keystore))); -// let multiaddr_vec = "/ip4/127.0.0.1/tcp/4001/p2p/12D3KooWMvyvKxYcy9mjbFbXcogFSCvENzQ62ogRxHKZaksFCkAp".as_bytes().to_vec(); -// let cid_vec = "QmPZv7P8nQUSh2CpqTvUeYemFyjvMjgWEs8H1Tm8b3zAm9".as_bytes().to_vec(); -// let bytes = "hello test".as_bytes().to_vec(); -// let name: Vec = "test.txt".as_bytes().to_vec(); -// let id = 1; -// let balance = 1; -// // mock IPFS calls -// { -// let mut state = state.write(); -// // connect to external node -// state.expect_ipfs_request(testing::IpfsPendingRequest { -// response: Some(IpfsResponse::Success), -// ..Default::default() -// }); -// // fetch data -// state.expect_ipfs_request(testing::IpfsPendingRequest { -// id: sp_core::offchain::IpfsRequestId(0), -// response: Some(IpfsResponse::CatBytes(bytes.clone())), -// ..Default::default() -// }); -// // disconnect from the external node -// state.expect_ipfs_request(testing::IpfsPendingRequest { -// response: Some(IpfsResponse::Success), -// ..Default::default() -// }); -// // add bytes to your local node -// state.expect_ipfs_request(testing::IpfsPendingRequest { -// response: Some(IpfsResponse::AddBytes(cid_vec.clone())), -// ..Default::default() -// }); -// } + let multiaddr_vec = "/ip4/127.0.0.1/tcp/4001/p2p/12D3KooWMvyvKxYcy9mjbFbXcogFSCvENzQ62ogRxHKZaksFCkAp".as_bytes().to_vec(); + let cid_vec = "QmPZv7P8nQUSh2CpqTvUeYemFyjvMjgWEs8H1Tm8b3zAm9".as_bytes().to_vec(); + let bytes = "hello test".as_bytes().to_vec(); + let name: Vec = "test.txt".as_bytes().to_vec(); + let id = 1; + let balance = 1; + // mock IPFS calls + { + let mut state = state.write(); + // connect to external node + state.expect_ipfs_request(testing::IpfsPendingRequest { + response: Some(IpfsResponse::Success), + ..Default::default() + }); + // fetch data + state.expect_ipfs_request(testing::IpfsPendingRequest { + id: sp_core::offchain::IpfsRequestId(0), + response: Some(IpfsResponse::CatBytes(bytes.clone())), + ..Default::default() + }); + // disconnect from the external node + state.expect_ipfs_request(testing::IpfsPendingRequest { + response: Some(IpfsResponse::Success), + ..Default::default() + }); + // add bytes to your local node + state.expect_ipfs_request(testing::IpfsPendingRequest { + response: Some(IpfsResponse::AddBytes(cid_vec.clone())), + ..Default::default() + }); + } -// t.execute_with(|| { -// // WHEN: I invoke the create_storage_assets extrinsic -// assert_ok!(Iris::create_storage_asset( -// Origin::signed(p.clone().public()), -// p.clone().public(), -// multiaddr_vec.clone(), -// cid_vec.clone(), -// name.clone(), -// id.clone(), -// balance.clone(), -// )); -// // THEN: the offchain worker adds data to IPFS -// assert_ok!(Iris::handle_data_requests()); -// }); -// } + t.execute_with(|| { + // WHEN: I invoke the create_storage_assets extrinsic + assert_ok!(IrisAssets::create( + Origin::signed(p.clone().public()), + p.clone().public(), + multiaddr_vec.clone(), + cid_vec.clone(), + name.clone(), + id.clone(), + balance.clone(), + )); + // THEN: the offchain worker adds data to IPFS + assert_ok!(IrisSession::handle_data_requests()); + }); +} // // can fetch bytes and add to offchain storage // #[test] diff --git a/client/offchain/Cargo.toml b/client/offchain/Cargo.toml index 2ae9e6e496df..119c230283e3 100644 --- a/client/offchain/Cargo.toml +++ b/client/offchain/Cargo.toml @@ -32,7 +32,8 @@ sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } sc-utils = { version = "4.0.0-dev", path = "../utils" } threadpool = "1.7" cid = "0.5" -ipfs = { git = "https://github.com/rs-ipfs/rust-ipfs", branch="master" } +ipfs = { git = "https://github.com/rs-ipfs/rust-ipfs", rev="ed430faed019e693a2e66844e6d9ded7624230f5" } +# ipfs = { git = "https://github.com/rs-ipfs/rust-ipfs", branch="master" } tokio = { version = "1.10", default-features = false } [target.'cfg(not(target_os = "unknown"))'.dependencies] diff --git a/client/service/src/task_manager/tests.rs b/client/service/src/task_manager/tests.rs index d84cf59c78f0..48bee00a299d 100644 --- a/client/service/src/task_manager/tests.rs +++ b/client/service/src/task_manager/tests.rs @@ -16,10 +16,10 @@ // // You should have received a copy of the GNU General Public License // // along with this program. If not, see . -// use crate::task_manager::TaskManager; -// use futures::{future::FutureExt, pin_mut, select}; -// use parking_lot::Mutex; -// use std::{any::Any, sync::Arc, time::Duration}; +use crate::task_manager::TaskManager; +use futures::{future::FutureExt, pin_mut, select}; +use parking_lot::Mutex; +use std::{any::Any, sync::Arc, time::Duration}; #[derive(Clone, Debug)] struct DropTester(Arc>); @@ -84,8 +84,8 @@ async fn run_background_task_blocking(duration: Duration, _keep_alive: impl Any) } } -fn new_task_manager(tokio_handle: tokio::runtime::Handle) -> TaskManager { - TaskManager::new(tokio_handle, None).unwrap() +fn new_task_manager(tokio_handle: tokio::runtime::Handle, ipfs_rt: tokio::runtime::Runtime) -> TaskManager { + TaskManager::new(tokio_handle, ipfs_rt, None).unwrap() } #[test] @@ -93,7 +93,9 @@ fn ensure_tasks_are_awaited_on_shutdown() { let runtime = tokio::runtime::Runtime::new().unwrap(); let handle = runtime.handle().clone(); - let task_manager = new_task_manager(handle); + let ipfs_rt = tokio::runtime::Runtime::new(); + + let task_manager = new_task_manager(handle, ipfs_rt); let spawn_handle = task_manager.spawn_handle(); let drop_tester = DropTester::new(); spawn_handle.spawn("task1", run_background_task(drop_tester.new_ref())); @@ -111,7 +113,9 @@ fn ensure_keep_alive_during_shutdown() { let runtime = tokio::runtime::Runtime::new().unwrap(); let handle = runtime.handle().clone(); - let mut task_manager = new_task_manager(handle); + let ipfs_rt = tokio::runtime::Runtime::new(); + + let mut task_manager = new_task_manager(handle, ipfs_rt); let spawn_handle = task_manager.spawn_handle(); let drop_tester = DropTester::new(); task_manager.keep_alive(drop_tester.new_ref()); @@ -128,8 +132,9 @@ fn ensure_keep_alive_during_shutdown() { fn ensure_blocking_futures_are_awaited_on_shutdown() { let runtime = tokio::runtime::Runtime::new().unwrap(); let handle = runtime.handle().clone(); + let ipfs_rt = tokio::runtime::Runtime::new(); - let task_manager = new_task_manager(handle); + let task_manager = new_task_manager(handle, ipfs_rt); let spawn_handle = task_manager.spawn_handle(); let drop_tester = DropTester::new(); spawn_handle.spawn( @@ -152,8 +157,9 @@ fn ensure_blocking_futures_are_awaited_on_shutdown() { fn ensure_no_task_can_be_spawn_after_terminate() { let runtime = tokio::runtime::Runtime::new().unwrap(); let handle = runtime.handle().clone(); + let ipfs_rt = tokio::runtime::Runtime::new(); - let mut task_manager = new_task_manager(handle); + let mut task_manager = new_task_manager(handle, ipfs_rt); let spawn_handle = task_manager.spawn_handle(); let drop_tester = DropTester::new(); spawn_handle.spawn("task1", run_background_task(drop_tester.new_ref())); @@ -172,8 +178,9 @@ fn ensure_no_task_can_be_spawn_after_terminate() { fn ensure_task_manager_future_ends_when_task_manager_terminated() { let runtime = tokio::runtime::Runtime::new().unwrap(); let handle = runtime.handle().clone(); + let ipfs_rt = tokio::runtime::Runtime::new(); - let mut task_manager = new_task_manager(handle); + let mut task_manager = new_task_manager(handle, ipfs_rt); let spawn_handle = task_manager.spawn_handle(); let drop_tester = DropTester::new(); spawn_handle.spawn("task1", run_background_task(drop_tester.new_ref())); @@ -192,8 +199,9 @@ fn ensure_task_manager_future_ends_when_task_manager_terminated() { fn ensure_task_manager_future_ends_with_error_when_essential_task_fails() { let runtime = tokio::runtime::Runtime::new().unwrap(); let handle = runtime.handle().clone(); + let ipfs_rt = tokio::runtime::Runtime::new(); - let mut task_manager = new_task_manager(handle); + let mut task_manager = new_task_manager(handle, ipfs_rt); let spawn_handle = task_manager.spawn_handle(); let spawn_essential_handle = task_manager.spawn_essential_handle(); let drop_tester = DropTester::new(); @@ -216,11 +224,12 @@ fn ensure_task_manager_future_ends_with_error_when_essential_task_fails() { fn ensure_children_tasks_ends_when_task_manager_terminated() { let runtime = tokio::runtime::Runtime::new().unwrap(); let handle = runtime.handle().clone(); + let ipfs_rt = tokio::runtime::Runtime::new(); - let mut task_manager = new_task_manager(handle.clone()); - let child_1 = new_task_manager(handle.clone()); + let mut task_manager = new_task_manager(handle.clone(), ipfs_rt.clone()); + let child_1 = new_task_manager(handle.clone(), ipfs_rt.clone()); let spawn_handle_child_1 = child_1.spawn_handle(); - let child_2 = new_task_manager(handle.clone()); + let child_2 = new_task_manager(handle.clone(), ipfs_rt.clone()); let spawn_handle_child_2 = child_2.spawn_handle(); task_manager.add_child(child_1); task_manager.add_child(child_2); @@ -245,11 +254,13 @@ fn ensure_task_manager_future_ends_with_error_when_childs_essential_task_fails() let runtime = tokio::runtime::Runtime::new().unwrap(); let handle = runtime.handle().clone(); - let mut task_manager = new_task_manager(handle.clone()); - let child_1 = new_task_manager(handle.clone()); + let ipfs_rt = tokio::runtime::Runtime::new(); + + let mut task_manager = new_task_manager(handle.clone(), ipfs_rt.clone()); + let child_1 = new_task_manager(handle.clone(), ipfs_rt.clone()); let spawn_handle_child_1 = child_1.spawn_handle(); let spawn_essential_handle_child_1 = child_1.spawn_essential_handle(); - let child_2 = new_task_manager(handle.clone()); + let child_2 = new_task_manager(handle.clone(), ipfs_rt.clone()); let spawn_handle_child_2 = child_2.spawn_handle(); task_manager.add_child(child_1); task_manager.add_child(child_2); @@ -277,10 +288,12 @@ fn ensure_task_manager_future_continues_when_childs_not_essential_task_fails() { let runtime = tokio::runtime::Runtime::new().unwrap(); let handle = runtime.handle().clone(); - let mut task_manager = new_task_manager(handle.clone()); - let child_1 = new_task_manager(handle.clone()); + let ipfs_rt = tokio::runtime::Runtime::new(); + + let mut task_manager = new_task_manager(handle.clon, ipfs_rt.clone()); + let child_1 = new_task_manager(handle.clone(), ipfs_rt.clone()); let spawn_handle_child_1 = child_1.spawn_handle(); - let child_2 = new_task_manager(handle.clone()); + let child_2 = new_task_manager(handle.clone(), ipfs_rt.clone()); let spawn_handle_child_2 = child_2.spawn_handle(); task_manager.add_child(child_1); task_manager.add_child(child_2); From 3aecef7ee350db9cf53369481ebd1cee26ecc7ff Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Wed, 9 Feb 2022 23:55:26 +0100 Subject: [PATCH 472/695] Add db params for export-state CLI command (#10830) --- client/cli/src/commands/export_blocks_cmd.rs | 2 +- client/cli/src/commands/export_state_cmd.rs | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/client/cli/src/commands/export_blocks_cmd.rs b/client/cli/src/commands/export_blocks_cmd.rs index 4e0e155dd51c..ff35b5a51fca 100644 --- a/client/cli/src/commands/export_blocks_cmd.rs +++ b/client/cli/src/commands/export_blocks_cmd.rs @@ -76,7 +76,7 @@ impl ExportBlocksCmd { C: BlockBackend + UsageProvider + 'static, <::Number as FromStr>::Err: Debug, { - if let DatabaseSource::RocksDb { ref path, .. } = database_config { + if let Some(path) = database_config.path() { info!("DB path: {}", path.display()); } diff --git a/client/cli/src/commands/export_state_cmd.rs b/client/cli/src/commands/export_state_cmd.rs index 4d67ab5d13c9..b76724caf0fe 100644 --- a/client/cli/src/commands/export_state_cmd.rs +++ b/client/cli/src/commands/export_state_cmd.rs @@ -18,7 +18,7 @@ use crate::{ error, - params::{BlockNumberOrHash, PruningParams, SharedParams}, + params::{BlockNumberOrHash, DatabaseParams, PruningParams, SharedParams}, CliConfiguration, }; use clap::Parser; @@ -42,6 +42,10 @@ pub struct ExportStateCmd { #[allow(missing_docs)] #[clap(flatten)] pub pruning_params: PruningParams, + + #[allow(missing_docs)] + #[clap(flatten)] + pub database_params: DatabaseParams, } impl ExportStateCmd { @@ -81,4 +85,8 @@ impl CliConfiguration for ExportStateCmd { fn pruning_params(&self) -> Option<&PruningParams> { Some(&self.pruning_params) } + + fn database_params(&self) -> Option<&DatabaseParams> { + Some(&self.database_params) + } } From 70bd35682a8f651e7e6e13fa110badd79ef4bde7 Mon Sep 17 00:00:00 2001 From: driemworks Date: Wed, 9 Feb 2022 21:16:35 -0500 Subject: [PATCH 473/695] update tests, cleanup --- Cargo.lock | 12 +- .../pallets/iris-session/src/tests.rs | 367 ++++++++++-------- client/offchain/Cargo.toml | 3 +- client/service/src/task_manager/tests.rs | 20 +- 4 files changed, 221 insertions(+), 181 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 131e69b5b8ba..7ca8d3e85aec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3032,7 +3032,7 @@ dependencies = [ [[package]] name = "ipfs" version = "0.2.1" -source = "git+https://github.com/rs-ipfs/rust-ipfs?rev=ed430faed019e693a2e66844e6d9ded7624230f5#ed430faed019e693a2e66844e6d9ded7624230f5" +source = "git+https://github.com/rs-ipfs/rust-ipfs?branch=master#3eff4e15342d430870bfa4fad7c2604c865266b2" dependencies = [ "anyhow", "async-stream", @@ -3045,8 +3045,8 @@ dependencies = [ "fs2", "futures 0.3.17", "hash_hasher", - "ipfs-bitswap 0.1.0 (git+https://github.com/rs-ipfs/rust-ipfs?rev=ed430faed019e693a2e66844e6d9ded7624230f5)", - "ipfs-unixfs 0.2.0 (git+https://github.com/rs-ipfs/rust-ipfs?rev=ed430faed019e693a2e66844e6d9ded7624230f5)", + "ipfs-bitswap 0.1.0 (git+https://github.com/rs-ipfs/rust-ipfs?branch=master)", + "ipfs-unixfs 0.2.0 (git+https://github.com/rs-ipfs/rust-ipfs?branch=master)", "libp2p", "multibase 0.9.1", "multihash 0.11.4", @@ -3106,7 +3106,7 @@ dependencies = [ [[package]] name = "ipfs-bitswap" version = "0.1.0" -source = "git+https://github.com/rs-ipfs/rust-ipfs?rev=ed430faed019e693a2e66844e6d9ded7624230f5#ed430faed019e693a2e66844e6d9ded7624230f5" +source = "git+https://github.com/rs-ipfs/rust-ipfs?branch=master#3eff4e15342d430870bfa4fad7c2604c865266b2" dependencies = [ "cid 0.5.1", "fnv", @@ -3146,7 +3146,7 @@ dependencies = [ [[package]] name = "ipfs-unixfs" version = "0.2.0" -source = "git+https://github.com/rs-ipfs/rust-ipfs?rev=ed430faed019e693a2e66844e6d9ded7624230f5#ed430faed019e693a2e66844e6d9ded7624230f5" +source = "git+https://github.com/rs-ipfs/rust-ipfs?branch=master#3eff4e15342d430870bfa4fad7c2604c865266b2" dependencies = [ "cid 0.5.1", "either", @@ -8551,7 +8551,7 @@ dependencies = [ "hex", "hyper 0.14.13", "hyper-rustls", - "ipfs 0.2.1 (git+https://github.com/rs-ipfs/rust-ipfs?rev=ed430faed019e693a2e66844e6d9ded7624230f5)", + "ipfs 0.2.1 (git+https://github.com/rs-ipfs/rust-ipfs?branch=master)", "lazy_static", "log 0.4.14", "num_cpus", diff --git a/bin/node-template/pallets/iris-session/src/tests.rs b/bin/node-template/pallets/iris-session/src/tests.rs index c2dbf2e57b82..0f0fa342ad0a 100644 --- a/bin/node-template/pallets/iris-session/src/tests.rs +++ b/bin/node-template/pallets/iris-session/src/tests.rs @@ -13,91 +13,67 @@ use sp_core::{ use sp_keystore::{testing::KeyStore, KeystoreExt, SyncCryptoStore}; use std::sync::Arc; +// validator tests + #[test] fn iris_session_simple_setup_should_work() { - let V0: (sp_core::sr25519::Public, UintAuthorityId) = ( + let v0: (sp_core::sr25519::Public, UintAuthorityId) = ( sp_core::sr25519::Pair::generate_with_phrase(Some("0")).0.public(), UintAuthorityId(0) ); - let V1: (sp_core::sr25519::Public, UintAuthorityId) = ( + let v1: (sp_core::sr25519::Public, UintAuthorityId) = ( sp_core::sr25519::Pair::generate_with_phrase(Some("1")).0.public(), UintAuthorityId(1) ); - let V2: (sp_core::sr25519::Public, UintAuthorityId) = ( + let v2: (sp_core::sr25519::Public, UintAuthorityId) = ( sp_core::sr25519::Pair::generate_with_phrase(Some("2")).0.public(), UintAuthorityId(2) ); new_test_ext().execute_with(|| { - assert_eq!(authorities(), vec![V0.1, V1.1, V2.1]); - assert_eq!(crate::Validators::::get(), vec![V0.0, V1.0, V2.0]); - assert_eq!(Session::validators(), vec![V0.0, V1.0, V2.0]); + assert_eq!(authorities(), vec![v0.1, v1.1, v2.1]); + assert_eq!(crate::Validators::::get(), vec![v0.0, v1.0, v2.0]); + assert_eq!(Session::validators(), vec![v0.0, v1.0, v2.0]); }); } #[test] fn iris_session_add_validator_updates_validators_list() { - let V0: (sp_core::sr25519::Public, UintAuthorityId) = ( - sp_core::sr25519::Pair::generate_with_phrase(Some("0")).0.public(), - UintAuthorityId(0) - ); - let V1: (sp_core::sr25519::Public, UintAuthorityId) = ( - sp_core::sr25519::Pair::generate_with_phrase(Some("1")).0.public(), - UintAuthorityId(1) - ); - let V2: (sp_core::sr25519::Public, UintAuthorityId) = ( - sp_core::sr25519::Pair::generate_with_phrase(Some("2")).0.public(), - UintAuthorityId(2) - ); - let V3: (sp_core::sr25519::Public, UintAuthorityId) = ( - sp_core::sr25519::Pair::generate_with_phrase(Some("3")).0.public(), - UintAuthorityId(3) - ); + let v0 = sp_core::sr25519::Pair::generate_with_phrase(Some("0")).0.public(); + let v1 = sp_core::sr25519::Pair::generate_with_phrase(Some("1")).0.public(); + let v2 = sp_core::sr25519::Pair::generate_with_phrase(Some("2")).0.public(); + let v3 = sp_core::sr25519::Pair::generate_with_phrase(Some("3")).0.public(); + new_test_ext().execute_with(|| { - assert_ok!(IrisSession::add_validator(Origin::root(), V3.0)); - assert_eq!(crate::Validators::::get(), vec![V0.0, V1.0, V2.0, V3.0]); + assert_ok!(IrisSession::add_validator(Origin::root(), v3)); + assert_eq!(crate::Validators::::get(), vec![v0, v1, v2, v3]); }); } #[test] fn iris_session_remove_validator_updates_validators_list() { - let V0: (sp_core::sr25519::Public, UintAuthorityId) = ( - sp_core::sr25519::Pair::generate_with_phrase(Some("0")).0.public(), - UintAuthorityId(0) - ); - let V1: (sp_core::sr25519::Public, UintAuthorityId) = ( - sp_core::sr25519::Pair::generate_with_phrase(Some("1")).0.public(), - UintAuthorityId(1) - ); - let V2: (sp_core::sr25519::Public, UintAuthorityId) = ( - sp_core::sr25519::Pair::generate_with_phrase(Some("2")).0.public(), - UintAuthorityId(2) - ); + let v0 = sp_core::sr25519::Pair::generate_with_phrase(Some("0")).0.public(); + let v1 = sp_core::sr25519::Pair::generate_with_phrase(Some("1")).0.public(); + let v2 = sp_core::sr25519::Pair::generate_with_phrase(Some("2")).0.public(); new_test_ext().execute_with(|| { - assert_ok!(IrisSession::remove_validator(Origin::root(), V1.0)); - assert_eq!(IrisSession::validators(), vec![V0.0, V2.0]); + assert_ok!(IrisSession::remove_validator(Origin::root(), v1)); + assert_eq!(IrisSession::validators(), vec![v0, v2]); }); } #[test] fn iris_session_add_validator_fails_with_invalid_origin() { - let V3: (sp_core::sr25519::Public, UintAuthorityId) = ( - sp_core::sr25519::Pair::generate_with_phrase(Some("3")).0.public(), - UintAuthorityId(3) - ); + let v3 = sp_core::sr25519::Pair::generate_with_phrase(Some("3")).0.public(); new_test_ext().execute_with(|| { - assert_noop!(IrisSession::add_validator(Origin::signed(V3.0.clone()), V3.0), DispatchError::BadOrigin); + assert_noop!(IrisSession::add_validator(Origin::signed(v3.clone()), v3), DispatchError::BadOrigin); }); } #[test] fn iris_session_remove_validator_fails_with_invalid_origin() { - let V3: (sp_core::sr25519::Public, UintAuthorityId) = ( - sp_core::sr25519::Pair::generate_with_phrase(Some("3")).0.public(), - UintAuthorityId(3) - ); + let v3 = sp_core::sr25519::Pair::generate_with_phrase(Some("3")).0.public(); new_test_ext().execute_with(|| { assert_noop!( - IrisSession::remove_validator(Origin::signed(V3.0.clone()), V3.0), + IrisSession::remove_validator(Origin::signed(v3.clone()), v3), DispatchError::BadOrigin ); }); @@ -105,26 +81,89 @@ fn iris_session_remove_validator_fails_with_invalid_origin() { #[test] fn iris_session_duplicate_check() { - let V0: (sp_core::sr25519::Public, UintAuthorityId) = ( - sp_core::sr25519::Pair::generate_with_phrase(Some("0")).0.public(), - UintAuthorityId(0) - ); - let V1: (sp_core::sr25519::Public, UintAuthorityId) = ( - sp_core::sr25519::Pair::generate_with_phrase(Some("1")).0.public(), - UintAuthorityId(1) - ); - let V2: (sp_core::sr25519::Public, UintAuthorityId) = ( - sp_core::sr25519::Pair::generate_with_phrase(Some("2")).0.public(), - UintAuthorityId(2) - ); - let V3: (sp_core::sr25519::Public, UintAuthorityId) = ( - sp_core::sr25519::Pair::generate_with_phrase(Some("3")).0.public(), - UintAuthorityId(3) - ); + let v0 = sp_core::sr25519::Pair::generate_with_phrase(Some("0")).0.public(); + let v1 = sp_core::sr25519::Pair::generate_with_phrase(Some("1")).0.public(); + let v2 = sp_core::sr25519::Pair::generate_with_phrase(Some("2")).0.public(); + let v3 = sp_core::sr25519::Pair::generate_with_phrase(Some("3")).0.public(); new_test_ext().execute_with(|| { - assert_ok!(IrisSession::add_validator(Origin::root(), V3.0)); - assert_eq!(IrisSession::validators(), vec![V0.0, V1.0, V2.0, V3.0]); - assert_noop!(IrisSession::add_validator(Origin::root(), V3.0), Error::::Duplicate); + assert_ok!(IrisSession::add_validator(Origin::root(), v3)); + assert_eq!(IrisSession::validators(), vec![v0, v1, v2, v3]); + assert_noop!(IrisSession::add_validator(Origin::root(), v3), Error::::Duplicate); + }); +} + +// storage provider tests + +#[test] +fn iris_session_join_storage_pool() { + let (p, _) = sp_core::sr25519::Pair::generate(); + let (offchain, state) = testing::TestOffchainExt::new(); + let (pool, _) = testing::TestTransactionPoolExt::new(); + const PHRASE: &str = + "news slush supreme milk chapter athlete soap sausage put clutch what kitten"; + let keystore = KeyStore::new(); + SyncCryptoStore::sr25519_generate_new( + &keystore, + crate::KEY_TYPE, + Some(&format!("{}/geralt1", PHRASE)), + ) + .unwrap(); + + let mut t = new_test_ext_funded(p.clone()); + t.register_extension(OffchainWorkerExt::new(offchain)); + t.register_extension(TransactionPoolExt::new(pool)); + t.register_extension(KeystoreExt(Arc::new(keystore))); + + let multiaddr_vec = "/ip4/127.0.0.1/tcp/4001/p2p/12D3KooWMvyvKxYcy9mjbFbXcogFSCvENzQ62ogRxHKZaksFCkAp".as_bytes().to_vec(); + let cid_vec = "QmPZv7P8nQUSh2CpqTvUeYemFyjvMjgWEs8H1Tm8b3zAm9".as_bytes().to_vec(); + let bytes = "hello test".as_bytes().to_vec(); + let name: Vec = "test.txt".as_bytes().to_vec(); + let id = 1; + let balance = 1; + // mock IPFS calls + { + let mut state = state.write(); + // connect to external node + state.expect_ipfs_request(testing::IpfsPendingRequest { + response: Some(IpfsResponse::Success), + ..Default::default() + }); + // fetch data + state.expect_ipfs_request(testing::IpfsPendingRequest { + id: sp_core::offchain::IpfsRequestId(0), + response: Some(IpfsResponse::CatBytes(bytes.clone())), + ..Default::default() + }); + // disconnect from the external node + state.expect_ipfs_request(testing::IpfsPendingRequest { + response: Some(IpfsResponse::Success), + ..Default::default() + }); + // add bytes to your local node + state.expect_ipfs_request(testing::IpfsPendingRequest { + response: Some(IpfsResponse::AddBytes(cid_vec.clone())), + ..Default::default() + }); + } + + t.execute_with(|| { + // WHEN: I invoke the create_storage_assets extrinsic + assert_ok!(IrisAssets::create( + Origin::signed(p.clone().public()), + p.clone().public(), + multiaddr_vec.clone(), + cid_vec.clone(), + name.clone(), + id.clone(), + balance.clone(), + )); + // THEN: the offchain worker adds data to IPFS + assert_ok!(IrisSession::handle_data_requests()); + assert_ok!(IrisSession::join_storage_pool( + Origin::signed(p.clone().public()), + p.clone().public(), + id.clone(), + )); }); } @@ -143,9 +182,9 @@ fn iris_session_submit_rpc_ready_works_for_valid_values() { // test OCW functionality // can add bytes to network - #[test] fn iris_can_add_bytes_to_ipfs() { + let v0 = sp_core::sr25519::Pair::generate_with_phrase(Some("0")).0.public(); let (p, _) = sp_core::sr25519::Pair::generate(); let (offchain, state) = testing::TestOffchainExt::new(); let (pool, _) = testing::TestTransactionPoolExt::new(); @@ -155,7 +194,7 @@ fn iris_can_add_bytes_to_ipfs() { SyncCryptoStore::sr25519_generate_new( &keystore, crate::KEY_TYPE, - Some(&format!("{}/hunter1", PHRASE)), + Some(&format!("{}/geralt1", PHRASE)), ) .unwrap(); @@ -209,103 +248,105 @@ fn iris_can_add_bytes_to_ipfs() { )); // THEN: the offchain worker adds data to IPFS assert_ok!(IrisSession::handle_data_requests()); + // AND: each validator is given a reward point + let eras_reward_points = crate::ErasRewardPoints::::get(0, id.clone()); + assert_eq!(1, eras_reward_points.total); }); } -// // can fetch bytes and add to offchain storage -// #[test] -// fn iris_can_fetch_bytes_and_add_to_offchain_storage() { -// let (p, _) = sp_core::sr25519::Pair::generate(); -// let (offchain, state) = testing::TestOffchainExt::new(); -// let (pool, _) = testing::TestTransactionPoolExt::new(); -// const PHRASE: &str = -// "news slush supreme milk chapter athlete soap sausage put clutch what kitten"; -// let keystore = KeyStore::new(); -// SyncCryptoStore::sr25519_generate_new( -// &keystore, -// crate::KEY_TYPE, -// Some(&format!("{}/hunter1", PHRASE)), -// ) -// .unwrap(); +// can fetch bytes and add to offchain storage +#[test] +fn iris_can_fetch_bytes_and_add_to_offchain_storage() { + let (p, _) = sp_core::sr25519::Pair::generate(); + let (offchain, state) = testing::TestOffchainExt::new(); + let (pool, _) = testing::TestTransactionPoolExt::new(); + const PHRASE: &str = + "news slush supreme milk chapter athlete soap sausage put clutch what kitten"; + let keystore = KeyStore::new(); + SyncCryptoStore::sr25519_generate_new( + &keystore, + crate::KEY_TYPE, + Some(&format!("{}/geralt1", PHRASE)), + ) + .unwrap(); -// let mut t = new_test_ext_funded(p.clone()); -// t.register_extension(OffchainWorkerExt::new(offchain.clone())); -// t.register_extension(OffchainDbExt::new(offchain)); -// t.register_extension(TransactionPoolExt::new(pool)); -// t.register_extension(KeystoreExt(Arc::new(keystore))); + let mut t = new_test_ext_funded(p.clone()); + t.register_extension(OffchainWorkerExt::new(offchain.clone())); + t.register_extension(OffchainDbExt::new(offchain)); + t.register_extension(TransactionPoolExt::new(pool)); + t.register_extension(KeystoreExt(Arc::new(keystore))); -// let multiaddr_vec = "/ip4/127.0.0.1/tcp/4001/p2p/12D3KooWMvyvKxYcy9mjbFbXcogFSCvENzQ62ogRxHKZaksFCkAp".as_bytes().to_vec(); -// let cid_vec = "QmPZv7P8nQUSh2CpqTvUeYemFyjvMjgWEs8H1Tm8b3zAm9".as_bytes().to_vec(); -// let bytes = "hello test".as_bytes().to_vec(); -// let name: Vec = "test.txt".as_bytes().to_vec(); -// let id = 1; -// let balance = 1; -// // mock IPFS calls -// { -// let mut state = state.write(); -// // connect to external node -// state.expect_ipfs_request(testing::IpfsPendingRequest { -// response: Some(IpfsResponse::Success), -// ..Default::default() -// }); -// // fetch data -// state.expect_ipfs_request(testing::IpfsPendingRequest { -// id: sp_core::offchain::IpfsRequestId(0), -// response: Some(IpfsResponse::CatBytes(bytes.clone())), -// ..Default::default() -// }); -// // disconnect from the external node -// state.expect_ipfs_request(testing::IpfsPendingRequest { -// response: Some(IpfsResponse::Success), -// ..Default::default() -// }); -// // add bytes to your local node -// state.expect_ipfs_request(testing::IpfsPendingRequest { -// response: Some(IpfsResponse::AddBytes(cid_vec.clone())), -// ..Default::default() -// }); -// // fetch data -// state.expect_ipfs_request(testing::IpfsPendingRequest { -// id: sp_core::offchain::IpfsRequestId(0), -// response: Some(IpfsResponse::CatBytes(bytes.clone())), -// ..Default::default() -// }); -// } + let multiaddr_vec = "/ip4/127.0.0.1/tcp/4001/p2p/12D3KooWMvyvKxYcy9mjbFbXcogFSCvENzQ62ogRxHKZaksFCkAp".as_bytes().to_vec(); + let cid_vec = "QmPZv7P8nQUSh2CpqTvUeYemFyjvMjgWEs8H1Tm8b3zAm9".as_bytes().to_vec(); + let bytes = "hello test".as_bytes().to_vec(); + let name: Vec = "test.txt".as_bytes().to_vec(); + let id = 1; + let balance = 1; + // mock IPFS calls + { + let mut state = state.write(); + // connect to external node + state.expect_ipfs_request(testing::IpfsPendingRequest { + response: Some(IpfsResponse::Success), + ..Default::default() + }); + // fetch data + state.expect_ipfs_request(testing::IpfsPendingRequest { + id: sp_core::offchain::IpfsRequestId(0), + response: Some(IpfsResponse::CatBytes(bytes.clone())), + ..Default::default() + }); + // disconnect from the external node + state.expect_ipfs_request(testing::IpfsPendingRequest { + response: Some(IpfsResponse::Success), + ..Default::default() + }); + // add bytes to your local node + state.expect_ipfs_request(testing::IpfsPendingRequest { + response: Some(IpfsResponse::AddBytes(cid_vec.clone())), + ..Default::default() + }); + // fetch data + state.expect_ipfs_request(testing::IpfsPendingRequest { + id: sp_core::offchain::IpfsRequestId(0), + response: Some(IpfsResponse::CatBytes(bytes.clone())), + ..Default::default() + }); + } -// t.execute_with(|| { -// // WHEN: I invoke the create_storage_assets extrinsic -// assert_ok!(Iris::create_storage_asset( -// Origin::signed(p.clone().public()), -// p.clone().public(), -// multiaddr_vec.clone(), -// cid_vec.clone(), -// name.clone(), -// id.clone(), -// balance.clone(), -// )); -// // AND: I create an owned asset class -// assert_ok!(Iris::submit_ipfs_add_results( -// Origin::signed(p.clone().public()), -// p.clone().public(), -// cid_vec.clone(), -// id.clone(), -// balance.clone(), -// )); -// // AND: I invoke the mint_tickets extrinsic -// assert_ok!(Iris::mint_tickets( -// Origin::signed(p.clone().public()), -// p.clone().public(), -// cid_vec.clone(), -// balance.clone(), -// )); -// // AND: I request the owned content from iris -// assert_ok!(Iris::request_data( -// Origin::signed(p.clone().public()), -// p.clone().public(), -// cid_vec.clone(), -// )); -// // THEN: the offchain worker adds data to IPFS -// assert_ok!(Iris::handle_data_requests()); -// // AND: The data is available in local offchain storage -// }); -// } + t.execute_with(|| { + // WHEN: I invoke the create_storage_assetsrust- extrinsic + assert_ok!(IrisAssets::create( + Origin::signed(p.clone().public()), + p.clone().public(), + multiaddr_vec.clone(), + cid_vec.clone(), + name.clone(), + id.clone(), + balance.clone(), + )); + // AND: I create an owned asset class + assert_ok!(IrisSession::submit_ipfs_add_results( + Origin::signed(p.clone().public()), + p.clone().public(), + cid_vec.clone(), + id.clone(), + balance.clone(), + )); + // AND: I invoke the mint_tickets extrinsic + assert_ok!(IrisAssets::mint( + Origin::signed(p.clone().public()), + p.clone().public(), + id.clone(), + balance.clone(), + )); + // AND: I request the owned content from iris + assert_ok!(IrisAssets::request_bytes( + Origin::signed(p.clone().public()), + p.clone().public(), + id.clone(), + )); + // THEN: the offchain worker adds data to IPFS + assert_ok!(IrisSession::handle_data_requests()); + }); +} diff --git a/client/offchain/Cargo.toml b/client/offchain/Cargo.toml index 119c230283e3..2ae9e6e496df 100644 --- a/client/offchain/Cargo.toml +++ b/client/offchain/Cargo.toml @@ -32,8 +32,7 @@ sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } sc-utils = { version = "4.0.0-dev", path = "../utils" } threadpool = "1.7" cid = "0.5" -ipfs = { git = "https://github.com/rs-ipfs/rust-ipfs", rev="ed430faed019e693a2e66844e6d9ded7624230f5" } -# ipfs = { git = "https://github.com/rs-ipfs/rust-ipfs", branch="master" } +ipfs = { git = "https://github.com/rs-ipfs/rust-ipfs", branch="master" } tokio = { version = "1.10", default-features = false } [target.'cfg(not(target_os = "unknown"))'.dependencies] diff --git a/client/service/src/task_manager/tests.rs b/client/service/src/task_manager/tests.rs index 48bee00a299d..b38cabc42251 100644 --- a/client/service/src/task_manager/tests.rs +++ b/client/service/src/task_manager/tests.rs @@ -93,7 +93,7 @@ fn ensure_tasks_are_awaited_on_shutdown() { let runtime = tokio::runtime::Runtime::new().unwrap(); let handle = runtime.handle().clone(); - let ipfs_rt = tokio::runtime::Runtime::new(); + let ipfs_rt = tokio::runtime::Runtime::new().unwrap(); let task_manager = new_task_manager(handle, ipfs_rt); let spawn_handle = task_manager.spawn_handle(); @@ -113,7 +113,7 @@ fn ensure_keep_alive_during_shutdown() { let runtime = tokio::runtime::Runtime::new().unwrap(); let handle = runtime.handle().clone(); - let ipfs_rt = tokio::runtime::Runtime::new(); + let ipfs_rt = tokio::runtime::Runtime::new().unwrap(); let mut task_manager = new_task_manager(handle, ipfs_rt); let spawn_handle = task_manager.spawn_handle(); @@ -132,7 +132,7 @@ fn ensure_keep_alive_during_shutdown() { fn ensure_blocking_futures_are_awaited_on_shutdown() { let runtime = tokio::runtime::Runtime::new().unwrap(); let handle = runtime.handle().clone(); - let ipfs_rt = tokio::runtime::Runtime::new(); + let ipfs_rt = tokio::runtime::Runtime::new().unwrap(); let task_manager = new_task_manager(handle, ipfs_rt); let spawn_handle = task_manager.spawn_handle(); @@ -157,7 +157,7 @@ fn ensure_blocking_futures_are_awaited_on_shutdown() { fn ensure_no_task_can_be_spawn_after_terminate() { let runtime = tokio::runtime::Runtime::new().unwrap(); let handle = runtime.handle().clone(); - let ipfs_rt = tokio::runtime::Runtime::new(); + let ipfs_rt = tokio::runtime::Runtime::new().unwrap(); let mut task_manager = new_task_manager(handle, ipfs_rt); let spawn_handle = task_manager.spawn_handle(); @@ -178,7 +178,7 @@ fn ensure_no_task_can_be_spawn_after_terminate() { fn ensure_task_manager_future_ends_when_task_manager_terminated() { let runtime = tokio::runtime::Runtime::new().unwrap(); let handle = runtime.handle().clone(); - let ipfs_rt = tokio::runtime::Runtime::new(); + let ipfs_rt = tokio::runtime::Runtime::new().unwrap(); let mut task_manager = new_task_manager(handle, ipfs_rt); let spawn_handle = task_manager.spawn_handle(); @@ -199,7 +199,7 @@ fn ensure_task_manager_future_ends_when_task_manager_terminated() { fn ensure_task_manager_future_ends_with_error_when_essential_task_fails() { let runtime = tokio::runtime::Runtime::new().unwrap(); let handle = runtime.handle().clone(); - let ipfs_rt = tokio::runtime::Runtime::new(); + let ipfs_rt = tokio::runtime::Runtime::new().unwrap(); let mut task_manager = new_task_manager(handle, ipfs_rt); let spawn_handle = task_manager.spawn_handle(); @@ -224,7 +224,7 @@ fn ensure_task_manager_future_ends_with_error_when_essential_task_fails() { fn ensure_children_tasks_ends_when_task_manager_terminated() { let runtime = tokio::runtime::Runtime::new().unwrap(); let handle = runtime.handle().clone(); - let ipfs_rt = tokio::runtime::Runtime::new(); + let ipfs_rt = tokio::runtime::Runtime::new().unwrap(); let mut task_manager = new_task_manager(handle.clone(), ipfs_rt.clone()); let child_1 = new_task_manager(handle.clone(), ipfs_rt.clone()); @@ -254,7 +254,7 @@ fn ensure_task_manager_future_ends_with_error_when_childs_essential_task_fails() let runtime = tokio::runtime::Runtime::new().unwrap(); let handle = runtime.handle().clone(); - let ipfs_rt = tokio::runtime::Runtime::new(); + let ipfs_rt = tokio::runtime::Runtime::new().unwrap(); let mut task_manager = new_task_manager(handle.clone(), ipfs_rt.clone()); let child_1 = new_task_manager(handle.clone(), ipfs_rt.clone()); @@ -288,9 +288,9 @@ fn ensure_task_manager_future_continues_when_childs_not_essential_task_fails() { let runtime = tokio::runtime::Runtime::new().unwrap(); let handle = runtime.handle().clone(); - let ipfs_rt = tokio::runtime::Runtime::new(); + let ipfs_rt = tokio::runtime::Runtime::new().unwrap(); - let mut task_manager = new_task_manager(handle.clon, ipfs_rt.clone()); + let mut task_manager = new_task_manager(handle.clone(), ipfs_rt.clone()); let child_1 = new_task_manager(handle.clone(), ipfs_rt.clone()); let spawn_handle_child_1 = child_1.spawn_handle(); let child_2 = new_task_manager(handle.clone(), ipfs_rt.clone()); From 8b2f5379653d9d741f666634ed7f751dd6870381 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Thu, 10 Feb 2022 12:08:05 +0100 Subject: [PATCH 474/695] Allow `SetBalance` to handle error when trying to kill acount with reference counter. (#10826) * bug found * fix logic * a little simpler * add test --- frame/balances/src/lib.rs | 35 +++++++++++++++++++++-------------- frame/balances/src/tests.rs | 24 ++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 14 deletions(-) diff --git a/frame/balances/src/lib.rs b/frame/balances/src/lib.rs index 37114f385aa7..6bf37dfda037 100644 --- a/frame/balances/src/lib.rs +++ b/frame/balances/src/lib.rs @@ -314,25 +314,32 @@ pub mod pallet { let new_free = if wipeout { Zero::zero() } else { new_free }; let new_reserved = if wipeout { Zero::zero() } else { new_reserved }; - let (free, reserved) = Self::mutate_account(&who, |account| { - if new_free > account.free { - mem::drop(PositiveImbalance::::new(new_free - account.free)); - } else if new_free < account.free { - mem::drop(NegativeImbalance::::new(account.free - new_free)); - } - - if new_reserved > account.reserved { - mem::drop(PositiveImbalance::::new(new_reserved - account.reserved)); - } else if new_reserved < account.reserved { - mem::drop(NegativeImbalance::::new(account.reserved - new_reserved)); - } + // First we try to modify the account's balance to the forced balance. + let (old_free, old_reserved) = Self::mutate_account(&who, |account| { + let old_free = account.free; + let old_reserved = account.reserved; account.free = new_free; account.reserved = new_reserved; - (account.free, account.reserved) + (old_free, old_reserved) })?; - Self::deposit_event(Event::BalanceSet { who, free, reserved }); + + // This will adjust the total issuance, which was not done by the `mutate_account` + // above. + if new_free > old_free { + mem::drop(PositiveImbalance::::new(new_free - old_free)); + } else if new_free < old_free { + mem::drop(NegativeImbalance::::new(old_free - new_free)); + } + + if new_reserved > old_reserved { + mem::drop(PositiveImbalance::::new(new_reserved - old_reserved)); + } else if new_reserved < old_reserved { + mem::drop(NegativeImbalance::::new(old_reserved - new_reserved)); + } + + Self::deposit_event(Event::BalanceSet { who, free: new_free, reserved: new_reserved }); Ok(().into()) } diff --git a/frame/balances/src/tests.rs b/frame/balances/src/tests.rs index 638034d80cd5..8f5470ae3cac 100644 --- a/frame/balances/src/tests.rs +++ b/frame/balances/src/tests.rs @@ -1239,5 +1239,29 @@ macro_rules! decl_tests { assert_eq!(Balances::free_balance(&3), 25); }); } + + #[test] + fn set_balance_handles_killing_account() { + <$ext_builder>::default().build().execute_with(|| { + let _ = Balances::deposit_creating(&1, 111); + assert_ok!(frame_system::Pallet::::inc_consumers(&1)); + assert_noop!( + Balances::set_balance(Origin::root(), 1, 0, 0), + DispatchError::ConsumerRemaining, + ); + }); + } + + #[test] + fn set_balance_handles_total_issuance() { + <$ext_builder>::default().build().execute_with(|| { + let old_total_issuance = Balances::total_issuance(); + assert_ok!(Balances::set_balance(Origin::root(), 1337, 69, 42)); + assert_eq!(Balances::total_issuance(), old_total_issuance + 69 + 42); + assert_eq!(Balances::total_balance(&1337), 69 + 42); + assert_eq!(Balances::free_balance(&1337), 69); + assert_eq!(Balances::reserved_balance(&1337), 42); + }); + } } } From 9a6d706d8db00abb6ba183839ec98ecd9924b1f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Thu, 10 Feb 2022 13:34:35 +0100 Subject: [PATCH 475/695] UncheckedExtrinsic: Harden decode and clarify `EXTRINSIC_FORMAT_VERSION` (#10829) * UncheckedExtrinsic: Harden decode and clarify `EXTRINSIC_FORMAT_VERSION` * Apply suggestions from code review --- .../src/generic/unchecked_extrinsic.rs | 53 ++++++++++++++----- primitives/runtime/src/traits.rs | 4 +- 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/primitives/runtime/src/generic/unchecked_extrinsic.rs b/primitives/runtime/src/generic/unchecked_extrinsic.rs index d444d0352d5a..fb333abd6ac6 100644 --- a/primitives/runtime/src/generic/unchecked_extrinsic.rs +++ b/primitives/runtime/src/generic/unchecked_extrinsic.rs @@ -31,8 +31,12 @@ use scale_info::{build::Fields, meta_type, Path, StaticTypeInfo, Type, TypeInfo, use sp_io::hashing::blake2_256; use sp_std::{fmt, prelude::*}; -/// Current version of the [`UncheckedExtrinsic`] format. -const EXTRINSIC_VERSION: u8 = 4; +/// Current version of the [`UncheckedExtrinsic`] encoded format. +/// +/// This version needs to be bumped if the encoded representation changes. +/// It ensures that if the representation is changed and the format is not known, +/// the decoding fails. +const EXTRINSIC_FORMAT_VERSION: u8 = 4; /// A extrinsic right from the external world. This is unchecked and so /// can contain a signature. @@ -164,7 +168,7 @@ impl ExtrinsicMetadata where Extra: SignedExtension, { - const VERSION: u8 = EXTRINSIC_VERSION; + const VERSION: u8 = EXTRINSIC_FORMAT_VERSION; type SignedExtensions = Extra; } @@ -235,23 +239,33 @@ where { fn decode(input: &mut I) -> Result { // This is a little more complicated than usual since the binary format must be compatible - // with substrate's generic `Vec` type. Basically this just means accepting that there - // will be a prefix of vector length (we don't need - // to use this). - let _length_do_not_remove_me_see_above: Compact = Decode::decode(input)?; + // with SCALE's generic `Vec` type. Basically this just means accepting that there + // will be a prefix of vector length. + let expected_length: Compact = Decode::decode(input)?; + let before_length = input.remaining_len()?; let version = input.read_byte()?; let is_signed = version & 0b1000_0000 != 0; let version = version & 0b0111_1111; - if version != EXTRINSIC_VERSION { + if version != EXTRINSIC_FORMAT_VERSION { return Err("Invalid transaction version".into()) } - Ok(Self { - signature: if is_signed { Some(Decode::decode(input)?) } else { None }, - function: Decode::decode(input)?, - }) + let signature = is_signed.then(|| Decode::decode(input)).transpose()?; + let function = Decode::decode(input)?; + + if let Some((before_length, after_length)) = + input.remaining_len()?.and_then(|a| before_length.map(|b| (b, a))) + { + let length = before_length.saturating_sub(after_length); + + if length != expected_length.0 as usize { + return Err("Invalid length prefix".into()) + } + } + + Ok(Self { signature, function }) } } @@ -268,11 +282,11 @@ where // 1 byte version id. match self.signature.as_ref() { Some(s) => { - tmp.push(EXTRINSIC_VERSION | 0b1000_0000); + tmp.push(EXTRINSIC_FORMAT_VERSION | 0b1000_0000); s.encode_to(&mut tmp); }, None => { - tmp.push(EXTRINSIC_VERSION & 0b0111_1111); + tmp.push(EXTRINSIC_FORMAT_VERSION & 0b0111_1111); }, } self.function.encode_to(&mut tmp); @@ -409,6 +423,17 @@ mod tests { assert_eq!(Ex::decode(&mut &encoded[..]), Ok(ux)); } + #[test] + fn invalid_length_prefix_is_detected() { + let ux = Ex::new_unsigned(vec![0u8; 0]); + let mut encoded = ux.encode(); + + let length = Compact::::decode(&mut &encoded[..]).unwrap(); + Compact(length.0 + 10).encode_to(&mut &mut encoded[..1]); + + assert_eq!(Ex::decode(&mut &encoded[..]), Err("Invalid length prefix".into())); + } + #[test] fn signed_codec_should_work() { let ux = Ex::new_signed( diff --git a/primitives/runtime/src/traits.rs b/primitives/runtime/src/traits.rs index 6a829ea6bba7..1cea7c4e805c 100644 --- a/primitives/runtime/src/traits.rs +++ b/primitives/runtime/src/traits.rs @@ -748,7 +748,9 @@ pub trait Extrinsic: Sized + MaybeMallocSizeOf { /// Implementor is an [`Extrinsic`] and provides metadata about this extrinsic. pub trait ExtrinsicMetadata { - /// The version of the `Extrinsic`. + /// The format version of the `Extrinsic`. + /// + /// By format is meant the encoded representation of the `Extrinsic`. const VERSION: u8; /// Signed extensions attached to this `Extrinsic`. From 6c20860bfe503abc2817856c0076eecf437f5379 Mon Sep 17 00:00:00 2001 From: driemworks Date: Thu, 10 Feb 2022 15:46:04 -0500 Subject: [PATCH 476/695] fix typo --- bin/node-template/pallets/iris-session/src/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/node-template/pallets/iris-session/src/tests.rs b/bin/node-template/pallets/iris-session/src/tests.rs index 0f0fa342ad0a..2f98c1ac0b8f 100644 --- a/bin/node-template/pallets/iris-session/src/tests.rs +++ b/bin/node-template/pallets/iris-session/src/tests.rs @@ -315,7 +315,7 @@ fn iris_can_fetch_bytes_and_add_to_offchain_storage() { } t.execute_with(|| { - // WHEN: I invoke the create_storage_assetsrust- extrinsic + // WHEN: I invoke the create extrinsic assert_ok!(IrisAssets::create( Origin::signed(p.clone().public()), p.clone().public(), From 27b8806ed82844bb5283a4dadf853ee518fd042f Mon Sep 17 00:00:00 2001 From: Zeke Mostov Date: Thu, 10 Feb 2022 13:22:26 -0800 Subject: [PATCH 477/695] pallet-staking: Add extrinsic `force_apply_min_commission` (#10786) * pallet-staking: Add extrinsic `force_apply_min_commission` * Add benchmarks * cargo run --quiet --profile=production --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_staking --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/staking/src/weights.rs --template=./.maintain/frame-weight-template.hbs * Bound iteration by max_validator_count * cargo run --quiet --profile=production --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_staking --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/staking/src/weights.rs --template=./.maintain/frame-weight-template.hbs * Only apply to 1 validator * Update doc comments * Uncomment tests * cargo run --quiet --profile=production --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_staking --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/staking/src/weights.rs --template=./.maintain/frame-weight-template.hbs * Accept signed origins * cargo run --quiet --profile=production --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_staking --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/staking/src/weights.rs --template=./.maintain/frame-weight-template.hbs * Remove contains_key check * Add test for try_mutate_exists * Impove try_mutate_exists docs * Delete redundant try_mutate_exists tests; * Delete residual from removed test * cargo run --quiet --profile=production --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_staking --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/staking/src/weights.rs --template=./.maintain/frame-weight-template.hbs * Return an error when the stash does not exist * Update try_mutate_exist doc wording * Update frame/staking/src/pallet/mod.rs * Apply suggestions from code review Co-authored-by: Parity Bot Co-authored-by: Shawn Tabrizi --- frame/staking/src/benchmarking.rs | 29 +++ frame/staking/src/pallet/mod.rs | 22 ++ frame/staking/src/tests.rs | 35 +++ frame/staking/src/weights.rs | 231 +++++++++--------- frame/support/src/storage/mod.rs | 6 + .../support/src/storage/types/counted_map.rs | 2 + frame/support/src/storage/types/double_map.rs | 2 + frame/support/src/storage/types/map.rs | 2 + frame/support/src/storage/types/nmap.rs | 2 + frame/support/src/traits/stored_map.rs | 4 +- 10 files changed, 225 insertions(+), 110 deletions(-) diff --git a/frame/staking/src/benchmarking.rs b/frame/staking/src/benchmarking.rs index 564172d91241..65a1ee92e2ea 100644 --- a/frame/staking/src/benchmarking.rs +++ b/frame/staking/src/benchmarking.rs @@ -900,6 +900,35 @@ benchmarks! { assert!(!T::SortedListProvider::contains(&stash)); } + force_apply_min_commission { + // Clean up any existing state + clear_validators_and_nominators::(); + + // Create a validator with a commission of 50% + let (stash, controller) = + create_stash_controller::(1, 1, RewardDestination::Staked)?; + let validator_prefs = + ValidatorPrefs { commission: Perbill::from_percent(50), ..Default::default() }; + Staking::::validate(RawOrigin::Signed(controller).into(), validator_prefs)?; + + // Sanity check + assert_eq!( + Validators::::get(&stash), + ValidatorPrefs { commission: Perbill::from_percent(50), ..Default::default() } + ); + + // Set the min commission to 75% + MinCommission::::set(Perbill::from_percent(75)); + let caller = whitelisted_caller(); + }: _(RawOrigin::Signed(caller), stash.clone()) + verify { + // The validators commission has been bumped to 75% + assert_eq!( + Validators::::get(&stash), + ValidatorPrefs { commission: Perbill::from_percent(75), ..Default::default() } + ); + } + impl_benchmark_test_suite!( Staking, crate::mock::ExtBuilder::default().has_stakers(true), diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 2a870fda063d..2be75752f101 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -1616,6 +1616,28 @@ pub mod pallet { Self::chill_stash(&stash); Ok(()) } + + /// Force a validator to have at least the minimum commission. This will not affect a + /// validator who already has a commission greater than or equal to the minimum. Any account + /// can call this. + #[pallet::weight(T::WeightInfo::force_apply_min_commission())] + pub fn force_apply_min_commission( + origin: OriginFor, + validator_stash: T::AccountId, + ) -> DispatchResult { + ensure_signed(origin)?; + let min_commission = MinCommission::::get(); + Validators::::try_mutate_exists(validator_stash, |maybe_prefs| { + maybe_prefs + .as_mut() + .map(|prefs| { + (prefs.commission < min_commission) + .then(|| prefs.commission = min_commission) + }) + .ok_or(Error::::NotStash) + })?; + Ok(()) + } } } diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 538b75ead340..4073c069fb6b 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -4711,3 +4711,38 @@ mod sorted_list_provider { }); } } + +#[test] +fn force_apply_min_commission_works() { + let prefs = |c| ValidatorPrefs { commission: Perbill::from_percent(c), blocked: false }; + let validators = || Validators::::iter().collect::>(); + ExtBuilder::default().build_and_execute(|| { + assert_ok!(Staking::validate(Origin::signed(30), prefs(10))); + assert_ok!(Staking::validate(Origin::signed(20), prefs(5))); + + // Given + assert_eq!(validators(), vec![(31, prefs(10)), (21, prefs(5)), (11, prefs(0))]); + MinCommission::::set(Perbill::from_percent(5)); + + // When applying to a commission greater than min + assert_ok!(Staking::force_apply_min_commission(Origin::signed(1), 31)); + // Then the commission is not changed + assert_eq!(validators(), vec![(31, prefs(10)), (21, prefs(5)), (11, prefs(0))]); + + // When applying to a commission that is equal to min + assert_ok!(Staking::force_apply_min_commission(Origin::signed(1), 21)); + // Then the commission is not changed + assert_eq!(validators(), vec![(31, prefs(10)), (21, prefs(5)), (11, prefs(0))]); + + // When applying to a commission that is less than the min + assert_ok!(Staking::force_apply_min_commission(Origin::signed(1), 11)); + // Then the commission is bumped to the min + assert_eq!(validators(), vec![(31, prefs(10)), (21, prefs(5)), (11, prefs(5))]); + + // When applying commission to a validator that doesn't exist then storage is not altered + assert_noop!( + Staking::force_apply_min_commission(Origin::signed(1), 420), + Error::::NotStash + ); + }); +} diff --git a/frame/staking/src/weights.rs b/frame/staking/src/weights.rs index 42f762c721e4..dcb544283c22 100644 --- a/frame/staking/src/weights.rs +++ b/frame/staking/src/weights.rs @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_staking //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-31, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-02-09, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate +// target/production/substrate // benchmark // --chain=dev // --steps=50 @@ -33,9 +33,7 @@ // --wasm-execution=compiled // --heap-pages=4096 // --output=./frame/staking/src/weights.rs -// --template=.maintain/frame-weight-template.hbs -// --header=HEADER-APACHE2 -// --raw +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -74,6 +72,7 @@ pub trait WeightInfo { fn get_npos_targets(v: u32, ) -> Weight; fn set_staking_configs() -> Weight; fn chill_other() -> Weight; + fn force_apply_min_commission() -> Weight; } /// Weights for pallet_staking using the Substrate node and recommended hardware. @@ -86,7 +85,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Balances Locks (r:1 w:1) // Storage: Staking Payee (r:0 w:1) fn bond() -> Weight { - (37_688_000 as Weight) + (37_772_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } @@ -96,7 +95,7 @@ impl WeightInfo for SubstrateWeight { // Storage: BagsList ListNodes (r:3 w:3) // Storage: BagsList ListBags (r:2 w:2) fn bond_extra() -> Weight { - (63_507_000 as Weight) + (64_816_000 as Weight) .saturating_add(T::DbWeight::get().reads(8 as Weight)) .saturating_add(T::DbWeight::get().writes(7 as Weight)) } @@ -110,7 +109,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking Bonded (r:1 w:0) // Storage: BagsList ListBags (r:2 w:2) fn unbond() -> Weight { - (70_634_000 as Weight) + (71_635_000 as Weight) .saturating_add(T::DbWeight::get().reads(12 as Weight)) .saturating_add(T::DbWeight::get().writes(8 as Weight)) } @@ -119,9 +118,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn withdraw_unbonded_update(s: u32, ) -> Weight { - (30_002_000 as Weight) + (30_612_000 as Weight) // Standard Error: 0 - .saturating_add((55_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((59_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -139,7 +138,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Balances Locks (r:1 w:1) // Storage: Staking Payee (r:0 w:1) fn withdraw_unbonded_kill(_s: u32, ) -> Weight { - (58_077_000 as Weight) + (59_116_000 as Weight) .saturating_add(T::DbWeight::get().reads(13 as Weight)) .saturating_add(T::DbWeight::get().writes(11 as Weight)) } @@ -155,16 +154,16 @@ impl WeightInfo for SubstrateWeight { // Storage: BagsList CounterForListNodes (r:1 w:1) // Storage: Staking CounterForValidators (r:1 w:1) fn validate() -> Weight { - (44_603_000 as Weight) + (45_505_000 as Weight) .saturating_add(T::DbWeight::get().reads(12 as Weight)) .saturating_add(T::DbWeight::get().writes(8 as Weight)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking Nominators (r:1 w:1) fn kick(k: u32, ) -> Weight { - (14_580_000 as Weight) - // Standard Error: 13_000 - .saturating_add((8_076_000 as Weight).saturating_mul(k as Weight)) + (12_764_000 as Weight) + // Standard Error: 15_000 + .saturating_add((8_301_000 as Weight).saturating_mul(k as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(k as Weight))) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) @@ -181,9 +180,9 @@ impl WeightInfo for SubstrateWeight { // Storage: BagsList CounterForListNodes (r:1 w:1) // Storage: Staking CounterForNominators (r:1 w:1) fn nominate(n: u32, ) -> Weight { - (49_856_000 as Weight) - // Standard Error: 8_000 - .saturating_add((3_430_000 as Weight).saturating_mul(n as Weight)) + (51_439_000 as Weight) + // Standard Error: 10_000 + .saturating_add((3_323_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(12 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(n as Weight))) .saturating_add(T::DbWeight::get().writes(6 as Weight)) @@ -196,47 +195,47 @@ impl WeightInfo for SubstrateWeight { // Storage: BagsList ListBags (r:1 w:1) // Storage: BagsList CounterForListNodes (r:1 w:1) fn chill() -> Weight { - (43_815_000 as Weight) + (44_847_000 as Weight) .saturating_add(T::DbWeight::get().reads(8 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking Payee (r:0 w:1) fn set_payee() -> Weight { - (7_553_000 as Weight) + (7_795_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Staking Bonded (r:1 w:1) // Storage: Staking Ledger (r:2 w:2) fn set_controller() -> Weight { - (15_177_000 as Weight) + (16_051_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Staking ValidatorCount (r:0 w:1) fn set_validator_count() -> Weight { - (1_090_000 as Weight) + (1_107_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Staking ForceEra (r:0 w:1) fn force_no_eras() -> Weight { - (1_169_000 as Weight) + (1_126_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Staking ForceEra (r:0 w:1) fn force_new_era() -> Weight { - (1_089_000 as Weight) + (1_183_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Staking ForceEra (r:0 w:1) fn force_new_era_always() -> Weight { - (1_144_000 as Weight) + (1_181_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Staking Invulnerables (r:0 w:1) fn set_invulnerables(v: u32, ) -> Weight { - (1_612_000 as Weight) + (1_705_000 as Weight) // Standard Error: 0 .saturating_add((50_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -255,18 +254,18 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking Payee (r:0 w:1) // Storage: Staking SpanSlash (r:0 w:2) fn force_unstake(s: u32, ) -> Weight { - (56_103_000 as Weight) + (57_431_000 as Weight) // Standard Error: 1_000 - .saturating_add((798_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((801_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(11 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) } // Storage: Staking UnappliedSlashes (r:1 w:1) fn cancel_deferred_slash(s: u32, ) -> Weight { - (942_911_000 as Weight) - // Standard Error: 55_000 - .saturating_add((4_973_000 as Weight).saturating_mul(s as Weight)) + (950_258_000 as Weight) + // Standard Error: 56_000 + .saturating_add((5_001_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -281,9 +280,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking Payee (r:2 w:0) // Storage: System Account (r:2 w:2) fn payout_stakers_dead_controller(n: u32, ) -> Weight { - (77_948_000 as Weight) - // Standard Error: 13_000 - .saturating_add((23_507_000 as Weight).saturating_mul(n as Weight)) + (94_238_000 as Weight) + // Standard Error: 15_000 + .saturating_add((23_978_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(10 as Weight)) .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(n as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -301,9 +300,9 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:2 w:2) // Storage: Balances Locks (r:2 w:2) fn payout_stakers_alive_staked(n: u32, ) -> Weight { - (94_386_000 as Weight) - // Standard Error: 19_000 - .saturating_add((32_763_000 as Weight).saturating_mul(n as Weight)) + (109_323_000 as Weight) + // Standard Error: 22_000 + .saturating_add((33_887_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(11 as Weight)) .saturating_add(T::DbWeight::get().reads((5 as Weight).saturating_mul(n as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -316,9 +315,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking Bonded (r:1 w:0) // Storage: BagsList ListBags (r:2 w:2) fn rebond(l: u32, ) -> Weight { - (63_577_000 as Weight) + (64_807_000 as Weight) // Standard Error: 2_000 - .saturating_add((47_000 as Weight).saturating_mul(l as Weight)) + .saturating_add((50_000 as Weight).saturating_mul(l as Weight)) .saturating_add(T::DbWeight::get().reads(9 as Weight)) .saturating_add(T::DbWeight::get().writes(8 as Weight)) } @@ -333,8 +332,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking ErasStartSessionIndex (r:0 w:1) fn set_history_depth(e: u32, ) -> Weight { (0 as Weight) - // Standard Error: 57_000 - .saturating_add((19_691_000 as Weight).saturating_mul(e as Weight)) + // Standard Error: 61_000 + .saturating_add((20_457_000 as Weight).saturating_mul(e as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) .saturating_add(T::DbWeight::get().writes((7 as Weight).saturating_mul(e as Weight))) @@ -353,9 +352,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking Payee (r:0 w:1) // Storage: Staking SpanSlash (r:0 w:1) fn reap_stash(s: u32, ) -> Weight { - (61_871_000 as Weight) + (62_856_000 as Weight) // Standard Error: 0 - .saturating_add((796_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((802_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(12 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) @@ -380,10 +379,10 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking ErasStartSessionIndex (r:0 w:1) fn new_era(v: u32, n: u32, ) -> Weight { (0 as Weight) - // Standard Error: 823_000 - .saturating_add((218_725_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 41_000 - .saturating_add((31_349_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 804_000 + .saturating_add((226_855_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 40_000 + .saturating_add((31_928_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(208 as Weight)) .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(v as Weight))) .saturating_add(T::DbWeight::get().reads((4 as Weight).saturating_mul(n as Weight))) @@ -401,12 +400,12 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking Nominators (r:1000 w:0) fn get_npos_voters(v: u32, n: u32, s: u32, ) -> Weight { (0 as Weight) - // Standard Error: 86_000 - .saturating_add((18_168_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 86_000 - .saturating_add((21_061_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 2_951_000 - .saturating_add((8_164_000 as Weight).saturating_mul(s as Weight)) + // Standard Error: 87_000 + .saturating_add((18_771_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 87_000 + .saturating_add((21_895_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 2_984_000 + .saturating_add((8_282_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(204 as Weight)) .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(v as Weight))) .saturating_add(T::DbWeight::get().reads((4 as Weight).saturating_mul(n as Weight))) @@ -415,8 +414,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking Validators (r:501 w:0) fn get_npos_targets(v: u32, ) -> Weight { (0 as Weight) - // Standard Error: 29_000 - .saturating_add((7_761_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 28_000 + .saturating_add((7_801_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(v as Weight))) } @@ -427,7 +426,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking MaxNominatorsCount (r:0 w:1) // Storage: Staking MinNominatorBond (r:0 w:1) fn set_staking_configs() -> Weight { - (3_586_000 as Weight) + (3_680_000 as Weight) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } // Storage: Staking Ledger (r:1 w:0) @@ -441,10 +440,17 @@ impl WeightInfo for SubstrateWeight { // Storage: BagsList ListBags (r:1 w:1) // Storage: BagsList CounterForListNodes (r:1 w:1) fn chill_other() -> Weight { - (54_681_000 as Weight) + (55_459_000 as Weight) .saturating_add(T::DbWeight::get().reads(11 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } + // Storage: Staking MinCommission (r:1 w:0) + // Storage: Staking Validators (r:1 w:1) + fn force_apply_min_commission() -> Weight { + (8_939_000 as Weight) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } } // For backwards compatibility and tests @@ -456,7 +462,7 @@ impl WeightInfo for () { // Storage: Balances Locks (r:1 w:1) // Storage: Staking Payee (r:0 w:1) fn bond() -> Weight { - (37_688_000 as Weight) + (37_772_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } @@ -466,7 +472,7 @@ impl WeightInfo for () { // Storage: BagsList ListNodes (r:3 w:3) // Storage: BagsList ListBags (r:2 w:2) fn bond_extra() -> Weight { - (63_507_000 as Weight) + (64_816_000 as Weight) .saturating_add(RocksDbWeight::get().reads(8 as Weight)) .saturating_add(RocksDbWeight::get().writes(7 as Weight)) } @@ -480,7 +486,7 @@ impl WeightInfo for () { // Storage: Staking Bonded (r:1 w:0) // Storage: BagsList ListBags (r:2 w:2) fn unbond() -> Weight { - (70_634_000 as Weight) + (71_635_000 as Weight) .saturating_add(RocksDbWeight::get().reads(12 as Weight)) .saturating_add(RocksDbWeight::get().writes(8 as Weight)) } @@ -489,9 +495,9 @@ impl WeightInfo for () { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn withdraw_unbonded_update(s: u32, ) -> Weight { - (30_002_000 as Weight) + (30_612_000 as Weight) // Standard Error: 0 - .saturating_add((55_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((59_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -509,7 +515,7 @@ impl WeightInfo for () { // Storage: Balances Locks (r:1 w:1) // Storage: Staking Payee (r:0 w:1) fn withdraw_unbonded_kill(_s: u32, ) -> Weight { - (58_077_000 as Weight) + (59_116_000 as Weight) .saturating_add(RocksDbWeight::get().reads(13 as Weight)) .saturating_add(RocksDbWeight::get().writes(11 as Weight)) } @@ -525,16 +531,16 @@ impl WeightInfo for () { // Storage: BagsList CounterForListNodes (r:1 w:1) // Storage: Staking CounterForValidators (r:1 w:1) fn validate() -> Weight { - (44_603_000 as Weight) + (45_505_000 as Weight) .saturating_add(RocksDbWeight::get().reads(12 as Weight)) .saturating_add(RocksDbWeight::get().writes(8 as Weight)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking Nominators (r:1 w:1) fn kick(k: u32, ) -> Weight { - (14_580_000 as Weight) - // Standard Error: 13_000 - .saturating_add((8_076_000 as Weight).saturating_mul(k as Weight)) + (12_764_000 as Weight) + // Standard Error: 15_000 + .saturating_add((8_301_000 as Weight).saturating_mul(k as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(k as Weight))) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) @@ -551,9 +557,9 @@ impl WeightInfo for () { // Storage: BagsList CounterForListNodes (r:1 w:1) // Storage: Staking CounterForNominators (r:1 w:1) fn nominate(n: u32, ) -> Weight { - (49_856_000 as Weight) - // Standard Error: 8_000 - .saturating_add((3_430_000 as Weight).saturating_mul(n as Weight)) + (51_439_000 as Weight) + // Standard Error: 10_000 + .saturating_add((3_323_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(12 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(n as Weight))) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) @@ -566,47 +572,47 @@ impl WeightInfo for () { // Storage: BagsList ListBags (r:1 w:1) // Storage: BagsList CounterForListNodes (r:1 w:1) fn chill() -> Weight { - (43_815_000 as Weight) + (44_847_000 as Weight) .saturating_add(RocksDbWeight::get().reads(8 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking Payee (r:0 w:1) fn set_payee() -> Weight { - (7_553_000 as Weight) + (7_795_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Staking Bonded (r:1 w:1) // Storage: Staking Ledger (r:2 w:2) fn set_controller() -> Weight { - (15_177_000 as Weight) + (16_051_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } // Storage: Staking ValidatorCount (r:0 w:1) fn set_validator_count() -> Weight { - (1_090_000 as Weight) + (1_107_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Staking ForceEra (r:0 w:1) fn force_no_eras() -> Weight { - (1_169_000 as Weight) + (1_126_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Staking ForceEra (r:0 w:1) fn force_new_era() -> Weight { - (1_089_000 as Weight) + (1_183_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Staking ForceEra (r:0 w:1) fn force_new_era_always() -> Weight { - (1_144_000 as Weight) + (1_181_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Staking Invulnerables (r:0 w:1) fn set_invulnerables(v: u32, ) -> Weight { - (1_612_000 as Weight) + (1_705_000 as Weight) // Standard Error: 0 .saturating_add((50_000 as Weight).saturating_mul(v as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -625,18 +631,18 @@ impl WeightInfo for () { // Storage: Staking Payee (r:0 w:1) // Storage: Staking SpanSlash (r:0 w:2) fn force_unstake(s: u32, ) -> Weight { - (56_103_000 as Weight) + (57_431_000 as Weight) // Standard Error: 1_000 - .saturating_add((798_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((801_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(11 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) } // Storage: Staking UnappliedSlashes (r:1 w:1) fn cancel_deferred_slash(s: u32, ) -> Weight { - (942_911_000 as Weight) - // Standard Error: 55_000 - .saturating_add((4_973_000 as Weight).saturating_mul(s as Weight)) + (950_258_000 as Weight) + // Standard Error: 56_000 + .saturating_add((5_001_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -651,9 +657,9 @@ impl WeightInfo for () { // Storage: Staking Payee (r:2 w:0) // Storage: System Account (r:2 w:2) fn payout_stakers_dead_controller(n: u32, ) -> Weight { - (77_948_000 as Weight) - // Standard Error: 13_000 - .saturating_add((23_507_000 as Weight).saturating_mul(n as Weight)) + (94_238_000 as Weight) + // Standard Error: 15_000 + .saturating_add((23_978_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(10 as Weight)) .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(n as Weight))) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) @@ -671,9 +677,9 @@ impl WeightInfo for () { // Storage: System Account (r:2 w:2) // Storage: Balances Locks (r:2 w:2) fn payout_stakers_alive_staked(n: u32, ) -> Weight { - (94_386_000 as Weight) - // Standard Error: 19_000 - .saturating_add((32_763_000 as Weight).saturating_mul(n as Weight)) + (109_323_000 as Weight) + // Standard Error: 22_000 + .saturating_add((33_887_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(11 as Weight)) .saturating_add(RocksDbWeight::get().reads((5 as Weight).saturating_mul(n as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -686,9 +692,9 @@ impl WeightInfo for () { // Storage: Staking Bonded (r:1 w:0) // Storage: BagsList ListBags (r:2 w:2) fn rebond(l: u32, ) -> Weight { - (63_577_000 as Weight) + (64_807_000 as Weight) // Standard Error: 2_000 - .saturating_add((47_000 as Weight).saturating_mul(l as Weight)) + .saturating_add((50_000 as Weight).saturating_mul(l as Weight)) .saturating_add(RocksDbWeight::get().reads(9 as Weight)) .saturating_add(RocksDbWeight::get().writes(8 as Weight)) } @@ -703,8 +709,8 @@ impl WeightInfo for () { // Storage: Staking ErasStartSessionIndex (r:0 w:1) fn set_history_depth(e: u32, ) -> Weight { (0 as Weight) - // Standard Error: 57_000 - .saturating_add((19_691_000 as Weight).saturating_mul(e as Weight)) + // Standard Error: 61_000 + .saturating_add((20_457_000 as Weight).saturating_mul(e as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) .saturating_add(RocksDbWeight::get().writes((7 as Weight).saturating_mul(e as Weight))) @@ -723,9 +729,9 @@ impl WeightInfo for () { // Storage: Staking Payee (r:0 w:1) // Storage: Staking SpanSlash (r:0 w:1) fn reap_stash(s: u32, ) -> Weight { - (61_871_000 as Weight) + (62_856_000 as Weight) // Standard Error: 0 - .saturating_add((796_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((802_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(12 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) @@ -750,10 +756,10 @@ impl WeightInfo for () { // Storage: Staking ErasStartSessionIndex (r:0 w:1) fn new_era(v: u32, n: u32, ) -> Weight { (0 as Weight) - // Standard Error: 823_000 - .saturating_add((218_725_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 41_000 - .saturating_add((31_349_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 804_000 + .saturating_add((226_855_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 40_000 + .saturating_add((31_928_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(208 as Weight)) .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(v as Weight))) .saturating_add(RocksDbWeight::get().reads((4 as Weight).saturating_mul(n as Weight))) @@ -771,12 +777,12 @@ impl WeightInfo for () { // Storage: Staking Nominators (r:1000 w:0) fn get_npos_voters(v: u32, n: u32, s: u32, ) -> Weight { (0 as Weight) - // Standard Error: 86_000 - .saturating_add((18_168_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 86_000 - .saturating_add((21_061_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 2_951_000 - .saturating_add((8_164_000 as Weight).saturating_mul(s as Weight)) + // Standard Error: 87_000 + .saturating_add((18_771_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 87_000 + .saturating_add((21_895_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 2_984_000 + .saturating_add((8_282_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(204 as Weight)) .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(v as Weight))) .saturating_add(RocksDbWeight::get().reads((4 as Weight).saturating_mul(n as Weight))) @@ -785,8 +791,8 @@ impl WeightInfo for () { // Storage: Staking Validators (r:501 w:0) fn get_npos_targets(v: u32, ) -> Weight { (0 as Weight) - // Standard Error: 29_000 - .saturating_add((7_761_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 28_000 + .saturating_add((7_801_000 as Weight).saturating_mul(v as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(v as Weight))) } @@ -797,7 +803,7 @@ impl WeightInfo for () { // Storage: Staking MaxNominatorsCount (r:0 w:1) // Storage: Staking MinNominatorBond (r:0 w:1) fn set_staking_configs() -> Weight { - (3_586_000 as Weight) + (3_680_000 as Weight) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } // Storage: Staking Ledger (r:1 w:0) @@ -811,8 +817,15 @@ impl WeightInfo for () { // Storage: BagsList ListBags (r:1 w:1) // Storage: BagsList CounterForListNodes (r:1 w:1) fn chill_other() -> Weight { - (54_681_000 as Weight) + (55_459_000 as Weight) .saturating_add(RocksDbWeight::get().reads(11 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } + // Storage: Staking MinCommission (r:1 w:0) + // Storage: Staking Validators (r:1 w:1) + fn force_apply_min_commission() -> Weight { + (8_939_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } } diff --git a/frame/support/src/storage/mod.rs b/frame/support/src/storage/mod.rs index e50577697a60..3d777fa3ace5 100644 --- a/frame/support/src/storage/mod.rs +++ b/frame/support/src/storage/mod.rs @@ -266,6 +266,8 @@ pub trait StorageMap { ) -> R; /// Mutate the item, only if an `Ok` value is returned. Deletes the item if mutated to a `None`. + /// `f` will always be called with an option representing if the storage item exists (`Some`) + /// or if the storage item does not exist (`None`), independent of the `QueryType`. fn try_mutate_exists, R, E, F: FnOnce(&mut Option) -> Result>( key: KeyArg, f: F, @@ -608,6 +610,8 @@ pub trait StorageDoubleMap { F: FnOnce(&mut Option) -> R; /// Mutate the item, only if an `Ok` value is returned. Deletes the item if mutated to a `None`. + /// `f` will always be called with an option representing if the storage item exists (`Some`) + /// or if the storage item does not exist (`None`), independent of the `QueryType`. fn try_mutate_exists(k1: KArg1, k2: KArg2, f: F) -> Result where KArg1: EncodeLike, @@ -735,6 +739,8 @@ pub trait StorageNMap { F: FnOnce(&mut Option) -> R; /// Mutate the item, only if an `Ok` value is returned. Deletes the item if mutated to a `None`. + /// `f` will always be called with an option representing if the storage item exists (`Some`) + /// or if the storage item does not exist (`None`), independent of the `QueryType`. fn try_mutate_exists(key: KArg, f: F) -> Result where KArg: EncodeLikeTuple + TupleToEncodedIter, diff --git a/frame/support/src/storage/types/counted_map.rs b/frame/support/src/storage/types/counted_map.rs index 7f53b196c815..9c48267af86e 100644 --- a/frame/support/src/storage/types/counted_map.rs +++ b/frame/support/src/storage/types/counted_map.rs @@ -190,6 +190,8 @@ where } /// Mutate the item, only if an `Ok` value is returned. Deletes the item if mutated to a `None`. + /// `f` will always be called with an option representing if the storage item exists (`Some`) + /// or if the storage item does not exist (`None`), independent of the `QueryType`. pub fn try_mutate_exists(key: KeyArg, f: F) -> Result where KeyArg: EncodeLike + Clone, diff --git a/frame/support/src/storage/types/double_map.rs b/frame/support/src/storage/types/double_map.rs index 07da0f2239b3..e864920e488f 100644 --- a/frame/support/src/storage/types/double_map.rs +++ b/frame/support/src/storage/types/double_map.rs @@ -264,6 +264,8 @@ where } /// Mutate the item, only if an `Ok` value is returned. Deletes the item if mutated to a `None`. + /// `f` will always be called with an option representing if the storage item exists (`Some`) + /// or if the storage item does not exist (`None`), independent of the `QueryType`. pub fn try_mutate_exists(k1: KArg1, k2: KArg2, f: F) -> Result where KArg1: EncodeLike, diff --git a/frame/support/src/storage/types/map.rs b/frame/support/src/storage/types/map.rs index d0b82e1a84e5..01aa2f44abe5 100644 --- a/frame/support/src/storage/types/map.rs +++ b/frame/support/src/storage/types/map.rs @@ -174,6 +174,8 @@ where } /// Mutate the item, only if an `Ok` value is returned. Deletes the item if mutated to a `None`. + /// `f` will always be called with an option representing if the storage item exists (`Some`) + /// or if the storage item does not exist (`None`), independent of the `QueryType`. pub fn try_mutate_exists(key: KeyArg, f: F) -> Result where KeyArg: EncodeLike, diff --git a/frame/support/src/storage/types/nmap.rs b/frame/support/src/storage/types/nmap.rs index 03f15e335389..5b51ed1ffdf4 100755 --- a/frame/support/src/storage/types/nmap.rs +++ b/frame/support/src/storage/types/nmap.rs @@ -217,6 +217,8 @@ where } /// Mutate the item, only if an `Ok` value is returned. Deletes the item if mutated to a `None`. + /// `f` will always be called with an option representing if the storage item exists (`Some`) + /// or if the storage item does not exist (`None`), independent of the `QueryType`. pub fn try_mutate_exists(key: KArg, f: F) -> Result where KArg: EncodeLikeTuple + TupleToEncodedIter, diff --git a/frame/support/src/traits/stored_map.rs b/frame/support/src/traits/stored_map.rs index 5173eaeb5def..3c3ff2eb0ed9 100644 --- a/frame/support/src/traits/stored_map.rs +++ b/frame/support/src/traits/stored_map.rs @@ -29,7 +29,9 @@ pub trait StoredMap { fn get(k: &K) -> T; /// Maybe mutate the item only if an `Ok` value is returned from `f`. Do nothing if an `Err` is - /// returned. It is removed or reset to default value if it has been mutated to `None` + /// returned. It is removed or reset to default value if it has been mutated to `None`. + /// `f` will always be called with an option representing if the storage item exists (`Some`) + /// or if the storage item does not exist (`None`), independent of the `QueryType`. fn try_mutate_exists>( k: &K, f: impl FnOnce(&mut Option) -> Result, From 665fc06def5a5aaba8c2661597f2add7bc3991ce Mon Sep 17 00:00:00 2001 From: Yarik Bratashchuk Date: Fri, 11 Feb 2022 09:46:51 +0200 Subject: [PATCH 478/695] Upgradable contracts using `set_code` function (#10690) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * poc logic * set_code_hash impl, tests, benchmark * Address @xgreenx's comments * Move func defs closer to set_storage * Check if code exists - increment/decrement codehash refcount * Document error for non-existing code hash * Revert unrelated change * Changes due to @athei's review * Fix error handling - comment errors: ReturnCodes - update mock ext implementation - return Error::CodeNotFound when no code for such hash * Emit ContractCodeUpdated when setting new code_hash * Address @athei's comments * Move related defs to the bottom * Minor comment update Co-authored-by: Alexander Theißen * Improve docs * Improve docs * Update frame/contracts/src/wasm/runtime.rs Co-authored-by: Alexander Theißen * Refactor set_code_hash test * Minor change to benchmark Co-authored-by: Alexander Theißen * Minor change to benchmark Co-authored-by: Alexander Theißen * Minor comment refactor Co-authored-by: Alexander Theißen * Address @HCastano's comments * Update seal_set_code_hash comment Co-authored-by: Hernando Castano * Move set_code_hash after delegate_call * Move function to the bottom * Moved and changed banchmark, added verify block * Bring back previous benchmark * Remove skip_meta for seal_set_code_hash * Bring back skip_meta for seal_set_storage_per_new_kb * Apply weights Co-authored-by: Alexander Theißen Co-authored-by: Hernando Castano --- .../fixtures/new_set_code_hash_contract.wat | 13 + frame/contracts/fixtures/set_code_hash.wat | 43 + frame/contracts/src/benchmarking/mod.rs | 40 + frame/contracts/src/exec.rs | 18 + frame/contracts/src/lib.rs | 10 + frame/contracts/src/schedule.rs | 4 + frame/contracts/src/tests.rs | 61 + frame/contracts/src/wasm/code_cache.rs | 16 + frame/contracts/src/wasm/mod.rs | 174 ++- frame/contracts/src/wasm/runtime.rs | 42 + frame/contracts/src/weights.rs | 1251 +++++++++-------- 11 files changed, 999 insertions(+), 673 deletions(-) create mode 100644 frame/contracts/fixtures/new_set_code_hash_contract.wat create mode 100644 frame/contracts/fixtures/set_code_hash.wat diff --git a/frame/contracts/fixtures/new_set_code_hash_contract.wat b/frame/contracts/fixtures/new_set_code_hash_contract.wat new file mode 100644 index 000000000000..86ab2737be48 --- /dev/null +++ b/frame/contracts/fixtures/new_set_code_hash_contract.wat @@ -0,0 +1,13 @@ +(module + (import "seal0" "seal_return" (func $seal_return (param i32 i32 i32))) + (import "env" "memory" (memory 1 1)) + + ;; [0, 32) return value + (data (i32.const 0) "\02") + + (func (export "deploy")) + + (func (export "call") + (call $seal_return (i32.const 0) (i32.const 0) (i32.const 4)) + ) +) diff --git a/frame/contracts/fixtures/set_code_hash.wat b/frame/contracts/fixtures/set_code_hash.wat new file mode 100644 index 000000000000..0a7b2e7cbedf --- /dev/null +++ b/frame/contracts/fixtures/set_code_hash.wat @@ -0,0 +1,43 @@ +(module + (import "seal0" "seal_input" (func $seal_input (param i32 i32))) + (import "seal0" "seal_return" (func $seal_return (param i32 i32 i32))) + (import "__unstable__" "seal_set_code_hash" (func $seal_set_code_hash (param i32) (result i32))) + + (import "env" "memory" (memory 1 1)) + + ;; [0, 32) here we store input + + ;; [32, 36) input size + (data (i32.const 32) "\20") + + ;; [36, 40) return value + (data (i32.const 36) "\01") + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func (export "call") + (local $exit_code i32) + + (call $seal_input (i32.const 0) (i32.const 32)) + + (set_local $exit_code + (call $seal_set_code_hash (i32.const 0)) ;; Pointer to the input data. + ) + (call $assert + (i32.eq (get_local $exit_code) (i32.const 0)) ;; ReturnCode::Success + ) + + ;; we return 1 after setting new code_hash + ;; next `call` will NOT return this value, because contract code has been changed + (call $seal_return (i32.const 0) (i32.const 36) (i32.const 4)) + ) + + (func (export "deploy")) +) diff --git a/frame/contracts/src/benchmarking/mod.rs b/frame/contracts/src/benchmarking/mod.rs index 88405eba4420..b18b40d0b334 100644 --- a/frame/contracts/src/benchmarking/mod.rs +++ b/frame/contracts/src/benchmarking/mod.rs @@ -1971,6 +1971,46 @@ benchmarks! { let origin = RawOrigin::Signed(instance.caller.clone()); }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + seal_set_code_hash { + let r in 0 .. API_BENCHMARK_BATCHES; + let code_hashes = (0..r * API_BENCHMARK_BATCH_SIZE) + .map(|i| { + let new_code = WasmModule::::dummy_with_bytes(i); + Contracts::::store_code_raw(new_code.code, whitelisted_caller())?; + Ok(new_code.hash) + }) + .collect::, &'static str>>()?; + let code_hash_len = code_hashes.get(0).map(|x| x.encode().len()).unwrap_or(0); + let code_hashes_bytes = code_hashes.iter().flat_map(|x| x.encode()).collect::>(); + let code_hashes_len = code_hashes_bytes.len(); + + let code = WasmModule::::from(ModuleDefinition { + memory: Some(ImportedMemory::max::()), + imported_functions: vec![ImportedFunction { + module: "__unstable__", + name: "seal_set_code_hash", + params: vec![ + ValueType::I32, + ], + return_type: Some(ValueType::I32), + }], + data_segments: vec![ + DataSegment { + offset: 0, + value: code_hashes_bytes, + }, + ], + call_body: Some(body::repeated_dyn(r * API_BENCHMARK_BATCH_SIZE, vec![ + Counter(0, code_hash_len as u32), // code_hash_ptr + Regular(Instruction::Call(0)), + Regular(Instruction::Drop), + ])), + .. Default::default() + }); + let instance = Contract::::new(code, vec![])?; + let origin = RawOrigin::Signed(instance.caller.clone()); + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + // We make the assumption that pushing a constant and dropping a value takes roughly // the same amount of time. We follow that `t.load` and `drop` both have the weight // of this benchmark / 2. We need to make this assumption because there is no way diff --git a/frame/contracts/src/exec.rs b/frame/contracts/src/exec.rs index c6e647e0c8d9..bca74cd66ced 100644 --- a/frame/contracts/src/exec.rs +++ b/frame/contracts/src/exec.rs @@ -18,6 +18,7 @@ use crate::{ gas::GasMeter, storage::{self, Storage, WriteOutcome}, + wasm::{decrement_refcount, increment_refcount}, AccountCounter, BalanceOf, CodeHash, Config, ContractInfo, ContractInfoOf, Error, Event, Pallet as Contracts, Schedule, }; @@ -239,6 +240,9 @@ pub trait Ext: sealing::Sealed { /// Tests sometimes need to modify and inspect the contract info directly. #[cfg(test)] fn contract_info(&mut self) -> &mut ContractInfo; + + /// Sets new code hash for existing contract. + fn set_code_hash(&mut self, hash: CodeHash) -> Result<(), DispatchError>; } /// Describes the different functions that can be exported by an [`Executable`]. @@ -1182,6 +1186,20 @@ where fn contract_info(&mut self) -> &mut ContractInfo { self.top_frame_mut().contract_info() } + + fn set_code_hash(&mut self, hash: CodeHash) -> Result<(), DispatchError> { + increment_refcount::(hash)?; + let top_frame = self.top_frame_mut(); + let prev_hash = top_frame.contract_info().code_hash.clone(); + decrement_refcount::(prev_hash.clone())?; + top_frame.contract_info().code_hash = hash; + Contracts::::deposit_event(Event::ContractCodeUpdated { + contract: top_frame.account_id.clone(), + new_code_hash: hash, + old_code_hash: prev_hash, + }); + Ok(()) + } } fn deposit_event(topics: Vec, event: Event) { diff --git a/frame/contracts/src/lib.rs b/frame/contracts/src/lib.rs index 7e4515868b74..9e7b61301e7d 100644 --- a/frame/contracts/src/lib.rs +++ b/frame/contracts/src/lib.rs @@ -564,6 +564,16 @@ pub mod pallet { /// A code with the specified hash was removed. CodeRemoved { code_hash: T::Hash }, + + /// A contract's code was updated. + ContractCodeUpdated { + /// The contract that has been updated. + contract: T::AccountId, + /// New code hash that was set for the contract. + new_code_hash: T::Hash, + /// Previous code hash of the contract. + old_code_hash: T::Hash, + }, } #[pallet::error] diff --git a/frame/contracts/src/schedule.rs b/frame/contracts/src/schedule.rs index e599bdc3125b..c92d2dd61610 100644 --- a/frame/contracts/src/schedule.rs +++ b/frame/contracts/src/schedule.rs @@ -328,6 +328,9 @@ pub struct HostFnWeights { /// Weight per overwritten byte of an item stored with `seal_set_storage`. pub set_storage_per_old_byte: Weight, + /// Weight of calling `seal_set_code_hash`. + pub set_code_hash: Weight, + /// Weight of calling `seal_clear_storage`. pub clear_storage: Weight, @@ -606,6 +609,7 @@ impl Default for HostFnWeights { ), debug_message: cost_batched!(seal_debug_message), set_storage: cost_batched!(seal_set_storage), + set_code_hash: cost_batched!(seal_set_code_hash), set_storage_per_new_byte: cost_byte_batched!(seal_set_storage_per_new_kb), set_storage_per_old_byte: cost_byte_batched!(seal_set_storage_per_old_kb), clear_storage: cost_batched!(seal_clear_storage), diff --git a/frame/contracts/src/tests.rs b/frame/contracts/src/tests.rs index 6919705206d4..486e84da7547 100644 --- a/frame/contracts/src/tests.rs +++ b/frame/contracts/src/tests.rs @@ -3023,3 +3023,64 @@ fn code_rejected_error_works() { ); }); } + +#[test] +#[cfg(feature = "unstable-interface")] +fn set_code_hash() { + let (wasm, code_hash) = compile_module::("set_code_hash").unwrap(); + let (new_wasm, new_code_hash) = compile_module::("new_set_code_hash_contract").unwrap(); + + let contract_addr = Contracts::contract_address(&ALICE, &code_hash, &[]); + + ExtBuilder::default().existential_deposit(100).build().execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + + // Instantiate the 'caller' + assert_ok!(Contracts::instantiate_with_code( + Origin::signed(ALICE), + 300_000, + GAS_LIMIT, + None, + wasm, + vec![], + vec![], + )); + // upload new code + assert_ok!(Contracts::upload_code(Origin::signed(ALICE), new_wasm.clone(), None)); + + // First call sets new code_hash and returns 1 + let result = Contracts::bare_call( + ALICE, + contract_addr.clone(), + 0, + GAS_LIMIT, + None, + new_code_hash.as_ref().to_vec(), + true, + ) + .result + .unwrap(); + assert_return_code!(result, 1); + + // Second calls new contract code that returns 2 + let result = + Contracts::bare_call(ALICE, contract_addr.clone(), 0, GAS_LIMIT, None, vec![], true) + .result + .unwrap(); + assert_return_code!(result, 2); + + // Checking for the last event only + assert_eq!( + System::events().pop().unwrap(), + EventRecord { + phase: Phase::Initialization, + event: Event::Contracts(crate::Event::ContractCodeUpdated { + contract: contract_addr.clone(), + new_code_hash: new_code_hash.clone(), + old_code_hash: code_hash.clone(), + }), + topics: vec![], + }, + ); + }); +} diff --git a/frame/contracts/src/wasm/code_cache.rs b/frame/contracts/src/wasm/code_cache.rs index a48f9838837c..9a447066667b 100644 --- a/frame/contracts/src/wasm/code_cache.rs +++ b/frame/contracts/src/wasm/code_cache.rs @@ -117,6 +117,22 @@ pub fn decrement_refcount(code_hash: CodeHash) -> Result<(), Dispa Ok(()) } +/// Increment the refcount of a code in-storage by one. +/// +/// # Errors +/// +/// [`Error::CodeNotFound`] is returned if the specified `code_hash` does not exist. +pub fn increment_refcount(code_hash: CodeHash) -> Result<(), DispatchError> { + >::mutate(code_hash, |existing| -> Result<(), DispatchError> { + if let Some(info) = existing { + info.refcount = info.refcount.saturating_add(1); + Ok(()) + } else { + Err(Error::::CodeNotFound.into()) + } + }) +} + /// Try to remove code together with all associated information. pub fn try_remove(origin: &T::AccountId, code_hash: CodeHash) -> DispatchResult { >::try_mutate_exists(&code_hash, |existing| { diff --git a/frame/contracts/src/wasm/mod.rs b/frame/contracts/src/wasm/mod.rs index 491daa58523e..3053f33ff033 100644 --- a/frame/contracts/src/wasm/mod.rs +++ b/frame/contracts/src/wasm/mod.rs @@ -26,7 +26,10 @@ mod runtime; #[cfg(feature = "runtime-benchmarks")] pub use self::code_cache::reinstrument; -pub use self::runtime::{ReturnCode, Runtime, RuntimeCosts}; +pub use self::{ + code_cache::{decrement_refcount, increment_refcount}, + runtime::{ReturnCode, Runtime, RuntimeCosts}, +}; use crate::{ exec::{ExecResult, Executable, ExportedFunction, Ext}, gas::GasMeter, @@ -322,6 +325,7 @@ mod tests { gas_meter: GasMeter, debug_buffer: Vec, ecdsa_recover: RefCell>, + code_hashes: Vec>, } /// The call is mocked and just returns this hardcoded value. @@ -332,6 +336,7 @@ mod tests { impl Default for MockExt { fn default() -> Self { Self { + code_hashes: Default::default(), storage: Default::default(), instantiates: Default::default(), terminations: Default::default(), @@ -390,6 +395,10 @@ mod tests { ExecReturnValue { flags: ReturnFlags::empty(), data: Bytes(Vec::new()) }, )) } + fn set_code_hash(&mut self, hash: CodeHash) -> Result<(), DispatchError> { + self.code_hashes.push(hash); + Ok(()) + } fn transfer(&mut self, to: &AccountIdOf, value: u64) -> Result<(), DispatchError> { self.transfers.push(TransferEntry { to: to.clone(), value }); Ok(()) @@ -798,6 +807,67 @@ mod tests { ); } + #[test] + #[cfg(feature = "unstable-interface")] + fn contains_storage_works() { + const CODE: &str = r#" +(module + (import "seal0" "seal_return" (func $seal_return (param i32 i32 i32))) + (import "seal0" "seal_input" (func $seal_input (param i32 i32))) + (import "__unstable__" "seal_contains_storage" (func $seal_contains_storage (param i32) (result i32))) + (import "env" "memory" (memory 1 1)) + + ;; [0, 4) size of input buffer (32 byte as we copy the key here) + (data (i32.const 0) "\20") + + ;; [4, 36) input buffer + + ;; [36, inf) output buffer + + (func (export "call") + ;; Receive key + (call $seal_input + (i32.const 4) ;; Pointer to the input buffer + (i32.const 0) ;; Size of the length buffer + ) + + ;; Load the return value into the output buffer + (i32.store (i32.const 36) + (call $seal_contains_storage + (i32.const 4) ;; The pointer to the storage key to fetch + ) + ) + + ;; Return the contents of the buffer + (call $seal_return + (i32.const 0) ;; flags + (i32.const 36) ;; output buffer ptr + (i32.const 4) ;; result is integer (4 bytes) + ) + ) + + (func (export "deploy")) +) +"#; + + let mut ext = MockExt::default(); + + ext.storage.insert([1u8; 32], vec![42u8]); + ext.storage.insert([2u8; 32], vec![]); + + // value does not exist -> sentinel value returned + let result = execute(CODE, [3u8; 32].encode(), &mut ext).unwrap(); + assert_eq!(u32::from_le_bytes(result.data.0.try_into().unwrap()), crate::SENTINEL); + + // value did exist -> success + let result = execute(CODE, [1u8; 32].encode(), &mut ext).unwrap(); + assert_eq!(u32::from_le_bytes(result.data.0.try_into().unwrap()), 1,); + + // value did exist -> success (zero sized type) + let result = execute(CODE, [2u8; 32].encode(), &mut ext).unwrap(); + assert_eq!(u32::from_le_bytes(result.data.0.try_into().unwrap()), 0,); + } + const CODE_INSTANTIATE: &str = r#" (module ;; seal_instantiate( @@ -2249,67 +2319,6 @@ mod tests { assert_eq!(&result.data.0[4..], &[0u8; 0]); } - #[test] - #[cfg(feature = "unstable-interface")] - fn contains_storage_works() { - const CODE: &str = r#" -(module - (import "seal0" "seal_return" (func $seal_return (param i32 i32 i32))) - (import "seal0" "seal_input" (func $seal_input (param i32 i32))) - (import "__unstable__" "seal_contains_storage" (func $seal_contains_storage (param i32) (result i32))) - (import "env" "memory" (memory 1 1)) - - ;; [0, 4) size of input buffer (32 byte as we copy the key here) - (data (i32.const 0) "\20") - - ;; [4, 36) input buffer - - ;; [36, inf) output buffer - - (func (export "call") - ;; Receive key - (call $seal_input - (i32.const 4) ;; Pointer to the input buffer - (i32.const 0) ;; Size of the length buffer - ) - - ;; Load the return value into the output buffer - (i32.store (i32.const 36) - (call $seal_contains_storage - (i32.const 4) ;; The pointer to the storage key to fetch - ) - ) - - ;; Return the contents of the buffer - (call $seal_return - (i32.const 0) ;; flags - (i32.const 36) ;; output buffer ptr - (i32.const 4) ;; result is integer (4 bytes) - ) - ) - - (func (export "deploy")) -) -"#; - - let mut ext = MockExt::default(); - - ext.storage.insert([1u8; 32], vec![42u8]); - ext.storage.insert([2u8; 32], vec![]); - - // value does not exist -> sentinel value returned - let result = execute(CODE, [3u8; 32].encode(), &mut ext).unwrap(); - assert_eq!(u32::from_le_bytes(result.data.0.try_into().unwrap()), crate::SENTINEL); - - // value did exist -> success - let result = execute(CODE, [1u8; 32].encode(), &mut ext).unwrap(); - assert_eq!(u32::from_le_bytes(result.data.0.try_into().unwrap()), 1,); - - // value did exist -> success (zero sized type) - let result = execute(CODE, [2u8; 32].encode(), &mut ext).unwrap(); - assert_eq!(u32::from_le_bytes(result.data.0.try_into().unwrap()), 0,); - } - #[test] #[cfg(feature = "unstable-interface")] fn is_contract_works() { @@ -2385,4 +2394,45 @@ mod tests { ExecReturnValue { flags: ReturnFlags::empty(), data: Bytes(0u32.encode()) }, ); } + + #[test] + #[cfg(feature = "unstable-interface")] + fn set_code_hash() { + const CODE: &str = r#" +(module + (import "__unstable__" "seal_set_code_hash" (func $seal_set_code_hash (param i32) (result i32))) + (import "env" "memory" (memory 1 1)) + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + (func (export "call") + (local $exit_code i32) + (set_local $exit_code + (call $seal_set_code_hash (i32.const 0)) + ) + (call $assert + (i32.eq (get_local $exit_code) (i32.const 0)) ;; ReturnCode::Success + ) + ) + + (func (export "deploy")) + + ;; Hash of code. + (data (i32.const 0) + "\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11" + "\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11" + ) +) +"#; + + let mut mock_ext = MockExt::default(); + execute(CODE, [0u8; 32].encode(), &mut mock_ext).unwrap(); + + assert_eq!(mock_ext.code_hashes.pop().unwrap(), H256::from_slice(&[17u8; 32])); + } } diff --git a/frame/contracts/src/wasm/runtime.rs b/frame/contracts/src/wasm/runtime.rs index 55ab0dfa0ade..384fbff9809b 100644 --- a/frame/contracts/src/wasm/runtime.rs +++ b/frame/contracts/src/wasm/runtime.rs @@ -222,6 +222,9 @@ pub enum RuntimeCosts { /// Weight charged for calling into the runtime. #[cfg(feature = "unstable-interface")] CallRuntime(Weight), + /// Weight of calling `seal_set_code_hash` + #[cfg(feature = "unstable-interface")] + SetCodeHash, } impl RuntimeCosts { @@ -305,6 +308,8 @@ impl RuntimeCosts { CopyIn(len) => s.return_per_byte.saturating_mul(len.into()), #[cfg(feature = "unstable-interface")] CallRuntime(weight) => weight, + #[cfg(feature = "unstable-interface")] + SetCodeHash => s.set_code_hash, }; RuntimeToken { #[cfg(test)] @@ -1960,4 +1965,41 @@ define_env!(Env, , Err(_) => Ok(ReturnCode::EcdsaRecoverFailed), } }, + + // Replace the contract code at the specified address with new code. + // + // # Note + // + // There are a couple of important considerations which must be taken into account when + // using this API: + // + // 1. The storage at the code address will remain untouched. This means that contract developers + // must ensure that the storage layout of the new code is compatible with that of the old code. + // + // 2. Contracts using this API can't be assumed as having deterministic addresses. Said another way, + // when using this API you lose the guarantee that an address always identifies a specific code hash. + // + // 3. If a contract calls into itself after changing its code the new call would use + // the new code. However, if the original caller panics after returning from the sub call it + // would revert the changes made by `seal_set_code_hash` and the next caller would use + // the old code. + // + // # Parameters + // + // - code_hash_ptr: A pointer to the buffer that contains the new code hash. + // + // # Errors + // + // `ReturnCode::CodeNotFound` + [__unstable__] seal_set_code_hash(ctx, code_hash_ptr: u32) -> ReturnCode => { + ctx.charge_gas(RuntimeCosts::SetCodeHash)?; + let code_hash: CodeHash<::T> = ctx.read_sandbox_memory_as(code_hash_ptr)?; + match ctx.ext.set_code_hash(code_hash) { + Err(err) => { + let code = Runtime::::err_into_return_code(err)?; + Ok(code) + }, + Ok(()) => Ok(ReturnCode::Success) + } + }, ); diff --git a/frame/contracts/src/weights.rs b/frame/contracts/src/weights.rs index ec6dcd2eee89..bf35ce511ab2 100644 --- a/frame/contracts/src/weights.rs +++ b/frame/contracts/src/weights.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_contracts //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-02-04, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-02-10, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -101,6 +101,7 @@ pub trait WeightInfo { fn seal_hash_blake2_128(r: u32, ) -> Weight; fn seal_hash_blake2_128_per_kb(n: u32, ) -> Weight; fn seal_ecdsa_recover(r: u32, ) -> Weight; + fn seal_set_code_hash(r: u32, ) -> Weight; fn instr_i64const(r: u32, ) -> Weight; fn instr_i64load(r: u32, ) -> Weight; fn instr_i64store(r: u32, ) -> Weight; @@ -159,32 +160,32 @@ pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize() -> Weight { - (1_640_000 as Weight) + (1_590_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn on_initialize_per_trie_key(k: u32, ) -> Weight { - (6_385_000 as Weight) + (9_975_000 as Weight) // Standard Error: 0 - .saturating_add((748_000 as Weight).saturating_mul(k as Weight)) + .saturating_add((724_000 as Weight).saturating_mul(k as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) } // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize_per_queue_item(q: u32, ) -> Weight { - (0 as Weight) - // Standard Error: 5_000 - .saturating_add((2_304_000 as Weight).saturating_mul(q as Weight)) + (7_415_000 as Weight) + // Standard Error: 4_000 + .saturating_add((2_303_000 as Weight).saturating_mul(q as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Contracts PristineCode (r:1 w:0) // Storage: Contracts CodeStorage (r:0 w:1) fn reinstrument(c: u32, ) -> Weight { - (22_923_000 as Weight) - // Standard Error: 33_000 - .saturating_add((65_851_000 as Weight).saturating_mul(c as Weight)) + (18_519_000 as Weight) + // Standard Error: 36_000 + .saturating_add((66_661_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -193,9 +194,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call_with_code_kb(c: u32, ) -> Weight { - (209_577_000 as Weight) - // Standard Error: 53_000 - .saturating_add((61_341_000 as Weight).saturating_mul(c as Weight)) + (210_319_000 as Weight) + // Standard Error: 41_000 + .saturating_add((54_802_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -207,11 +208,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn instantiate_with_code(c: u32, s: u32, ) -> Weight { - (240_302_000 as Weight) - // Standard Error: 119_000 - .saturating_add((151_894_000 as Weight).saturating_mul(c as Weight)) - // Standard Error: 7_000 - .saturating_add((1_740_000 as Weight).saturating_mul(s as Weight)) + (220_394_000 as Weight) + // Standard Error: 129_000 + .saturating_add((145_155_000 as Weight).saturating_mul(c as Weight)) + // Standard Error: 8_000 + .saturating_add((1_741_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } @@ -222,9 +223,9 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn instantiate(s: u32, ) -> Weight { - (172_047_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_729_000 as Weight).saturating_mul(s as Weight)) + (171_438_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_721_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } @@ -233,7 +234,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call() -> Weight { - (139_349_000 as Weight) + (139_529_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -241,9 +242,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn upload_code(c: u32, ) -> Weight { - (50_449_000 as Weight) - // Standard Error: 45_000 - .saturating_add((68_254_000 as Weight).saturating_mul(c as Weight)) + (51_040_000 as Weight) + // Standard Error: 38_000 + .saturating_add((65_886_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -251,7 +252,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:0 w:1) // Storage: Contracts PristineCode (r:0 w:1) fn remove_code() -> Weight { - (24_576_000 as Weight) + (24_347_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -260,9 +261,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_caller(r: u32, ) -> Weight { - (220_059_000 as Weight) - // Standard Error: 128_000 - .saturating_add((49_607_000 as Weight).saturating_mul(r as Weight)) + (217_164_000 as Weight) + // Standard Error: 89_000 + .saturating_add((48_023_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -271,9 +272,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_is_contract(r: u32, ) -> Weight { - (84_138_000 as Weight) - // Standard Error: 896_000 - .saturating_add((375_553_000 as Weight).saturating_mul(r as Weight)) + (81_537_000 as Weight) + // Standard Error: 847_000 + .saturating_add((367_429_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -283,9 +284,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_caller_is_origin(r: u32, ) -> Weight { - (222_496_000 as Weight) - // Standard Error: 119_000 - .saturating_add((22_340_000 as Weight).saturating_mul(r as Weight)) + (214_798_000 as Weight) + // Standard Error: 56_000 + .saturating_add((21_100_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -294,9 +295,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_address(r: u32, ) -> Weight { - (221_446_000 as Weight) - // Standard Error: 131_000 - .saturating_add((49_401_000 as Weight).saturating_mul(r as Weight)) + (216_615_000 as Weight) + // Standard Error: 75_000 + .saturating_add((48_054_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -305,9 +306,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas_left(r: u32, ) -> Weight { - (220_964_000 as Weight) - // Standard Error: 132_000 - .saturating_add((49_230_000 as Weight).saturating_mul(r as Weight)) + (218_034_000 as Weight) + // Standard Error: 87_000 + .saturating_add((47_594_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -316,9 +317,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_balance(r: u32, ) -> Weight { - (229_399_000 as Weight) - // Standard Error: 166_000 - .saturating_add((137_407_000 as Weight).saturating_mul(r as Weight)) + (221_980_000 as Weight) + // Standard Error: 135_000 + .saturating_add((135_618_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -327,9 +328,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_value_transferred(r: u32, ) -> Weight { - (220_103_000 as Weight) - // Standard Error: 133_000 - .saturating_add((49_410_000 as Weight).saturating_mul(r as Weight)) + (217_623_000 as Weight) + // Standard Error: 86_000 + .saturating_add((47_656_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -338,9 +339,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_minimum_balance(r: u32, ) -> Weight { - (228_143_000 as Weight) - // Standard Error: 151_000 - .saturating_add((48_608_000 as Weight).saturating_mul(r as Weight)) + (216_826_000 as Weight) + // Standard Error: 88_000 + .saturating_add((47_644_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -349,9 +350,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_block_number(r: u32, ) -> Weight { - (223_899_000 as Weight) - // Standard Error: 142_000 - .saturating_add((48_841_000 as Weight).saturating_mul(r as Weight)) + (219_487_000 as Weight) + // Standard Error: 90_000 + .saturating_add((47_167_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -360,9 +361,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_now(r: u32, ) -> Weight { - (224_974_000 as Weight) - // Standard Error: 148_000 - .saturating_add((48_902_000 as Weight).saturating_mul(r as Weight)) + (218_953_000 as Weight) + // Standard Error: 95_000 + .saturating_add((47_458_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -372,9 +373,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0) fn seal_weight_to_fee(r: u32, ) -> Weight { - (227_556_000 as Weight) - // Standard Error: 151_000 - .saturating_add((121_252_000 as Weight).saturating_mul(r as Weight)) + (220_132_000 as Weight) + // Standard Error: 144_000 + .saturating_add((120_373_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -383,9 +384,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas(r: u32, ) -> Weight { - (127_975_000 as Weight) - // Standard Error: 57_000 - .saturating_add((24_843_000 as Weight).saturating_mul(r as Weight)) + (127_458_000 as Weight) + // Standard Error: 56_000 + .saturating_add((24_015_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -394,9 +395,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input(r: u32, ) -> Weight { - (224_592_000 as Weight) - // Standard Error: 141_000 - .saturating_add((48_296_000 as Weight).saturating_mul(r as Weight)) + (220_304_000 as Weight) + // Standard Error: 112_000 + .saturating_add((46_804_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -405,9 +406,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input_per_kb(n: u32, ) -> Weight { - (296_995_000 as Weight) - // Standard Error: 3_000 - .saturating_add((11_884_000 as Weight).saturating_mul(n as Weight)) + (300_916_000 as Weight) + // Standard Error: 8_000 + .saturating_add((10_552_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -415,8 +416,10 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) - fn seal_return(_r: u32, ) -> Weight { - (224_322_000 as Weight) + fn seal_return(r: u32, ) -> Weight { + (211_812_000 as Weight) + // Standard Error: 138_000 + .saturating_add((1_698_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -425,9 +428,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return_per_kb(n: u32, ) -> Weight { - (216_240_000 as Weight) - // Standard Error: 1_000 - .saturating_add((206_000 as Weight).saturating_mul(n as Weight)) + (213_994_000 as Weight) + // Standard Error: 0 + .saturating_add((176_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -438,9 +441,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts DeletionQueue (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_terminate(r: u32, ) -> Weight { - (219_637_000 as Weight) - // Standard Error: 3_916_000 - .saturating_add((51_769_000 as Weight).saturating_mul(r as Weight)) + (215_173_000 as Weight) + // Standard Error: 708_000 + .saturating_add((52_509_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((4 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -452,9 +455,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) fn seal_random(r: u32, ) -> Weight { - (221_470_000 as Weight) - // Standard Error: 154_000 - .saturating_add((158_758_000 as Weight).saturating_mul(r as Weight)) + (219_521_000 as Weight) + // Standard Error: 171_000 + .saturating_add((156_228_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -463,9 +466,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_deposit_event(r: u32, ) -> Weight { - (228_674_000 as Weight) - // Standard Error: 203_000 - .saturating_add((287_195_000 as Weight).saturating_mul(r as Weight)) + (227_624_000 as Weight) + // Standard Error: 193_000 + .saturating_add((285_058_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -475,11 +478,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: System EventTopics (r:100 w:100) fn seal_deposit_event_per_topic_and_kb(t: u32, n: u32, ) -> Weight { - (507_091_000 as Weight) - // Standard Error: 1_863_000 - .saturating_add((291_858_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 367_000 - .saturating_add((83_459_000 as Weight).saturating_mul(n as Weight)) + (503_312_000 as Weight) + // Standard Error: 1_729_000 + .saturating_add((288_009_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 340_000 + .saturating_add((80_936_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(t as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -490,17 +493,17 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_debug_message(r: u32, ) -> Weight { - (133_592_000 as Weight) - // Standard Error: 87_000 - .saturating_add((41_718_000 as Weight).saturating_mul(r as Weight)) + (132_096_000 as Weight) + // Standard Error: 73_000 + .saturating_add((40_337_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage(r: u32, ) -> Weight { - (44_719_000 as Weight) - // Standard Error: 1_036_000 - .saturating_add((407_521_000 as Weight).saturating_mul(r as Weight)) + (52_622_000 as Weight) + // Standard Error: 1_006_000 + .saturating_add((404_716_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -508,25 +511,25 @@ impl WeightInfo for SubstrateWeight { } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage_per_new_kb(n: u32, ) -> Weight { - (606_108_000 as Weight) - // Standard Error: 315_000 - .saturating_add((29_136_000 as Weight).saturating_mul(n as Weight)) + (601_324_000 as Weight) + // Standard Error: 264_000 + .saturating_add((27_943_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage_per_old_kb(n: u32, ) -> Weight { - (634_330_000 as Weight) - // Standard Error: 281_000 - .saturating_add((10_741_000 as Weight).saturating_mul(n as Weight)) + (626_752_000 as Weight) + // Standard Error: 292_000 + .saturating_add((10_616_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage(r: u32, ) -> Weight { - (89_750_000 as Weight) - // Standard Error: 924_000 - .saturating_add((382_525_000 as Weight).saturating_mul(r as Weight)) + (80_138_000 as Weight) + // Standard Error: 933_000 + .saturating_add((382_949_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -534,51 +537,51 @@ impl WeightInfo for SubstrateWeight { } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage_per_kb(n: u32, ) -> Weight { - (616_463_000 as Weight) - // Standard Error: 260_000 - .saturating_add((10_373_000 as Weight).saturating_mul(n as Weight)) + (603_984_000 as Weight) + // Standard Error: 242_000 + .saturating_add((10_712_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage(r: u32, ) -> Weight { - (116_340_000 as Weight) - // Standard Error: 633_000 - .saturating_add((322_054_000 as Weight).saturating_mul(r as Weight)) + (113_136_000 as Weight) + // Standard Error: 635_000 + .saturating_add((324_706_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage_per_kb(n: u32, ) -> Weight { - (563_077_000 as Weight) - // Standard Error: 340_000 - .saturating_add((63_889_000 as Weight).saturating_mul(n as Weight)) + (562_781_000 as Weight) + // Standard Error: 354_000 + .saturating_add((63_275_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(104 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_contains_storage(r: u32, ) -> Weight { - (118_832_000 as Weight) - // Standard Error: 595_000 - .saturating_add((291_817_000 as Weight).saturating_mul(r as Weight)) + (112_237_000 as Weight) + // Standard Error: 655_000 + .saturating_add((296_653_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_contains_storage_per_kb(n: u32, ) -> Weight { - (520_386_000 as Weight) - // Standard Error: 297_000 - .saturating_add((10_076_000 as Weight).saturating_mul(n as Weight)) + (520_002_000 as Weight) + // Standard Error: 232_000 + .saturating_add((9_726_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(104 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage(r: u32, ) -> Weight { - (85_377_000 as Weight) - // Standard Error: 847_000 - .saturating_add((419_438_000 as Weight).saturating_mul(r as Weight)) + (87_232_000 as Weight) + // Standard Error: 920_000 + .saturating_add((415_305_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -586,9 +589,9 @@ impl WeightInfo for SubstrateWeight { } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage_per_kb(n: u32, ) -> Weight { - (666_218_000 as Weight) - // Standard Error: 294_000 - .saturating_add((64_627_000 as Weight).saturating_mul(n as Weight)) + (648_862_000 as Weight) + // Standard Error: 319_000 + .saturating_add((63_991_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().writes(103 as Weight)) } @@ -597,9 +600,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_transfer(r: u32, ) -> Weight { - (108_224_000 as Weight) - // Standard Error: 1_042_000 - .saturating_add((1_723_539_000 as Weight).saturating_mul(r as Weight)) + (99_621_000 as Weight) + // Standard Error: 1_154_000 + .saturating_add((1_732_052_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -611,8 +614,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) fn seal_call(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 7_843_000 - .saturating_add((19_825_093_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 6_293_000 + .saturating_add((19_410_115_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -624,8 +627,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) fn seal_delegate_call(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 11_788_000 - .saturating_add((19_855_594_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 7_155_000 + .saturating_add((19_793_614_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads((99 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -634,13 +637,13 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:2 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_call_per_transfer_input_output_kb(t: u32, i: u32, o: u32, ) -> Weight { - (20_190_331_000 as Weight) - // Standard Error: 75_647_000 - .saturating_add((2_369_225_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 27_000 - .saturating_add((19_831_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 28_000 - .saturating_add((31_191_000 as Weight).saturating_mul(o as Weight)) + (19_711_861_000 as Weight) + // Standard Error: 55_158_000 + .saturating_add((2_509_755_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 19_000 + .saturating_add((17_808_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 21_000 + .saturating_add((28_104_000 as Weight).saturating_mul(o as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().reads((101 as Weight).saturating_mul(t as Weight))) .saturating_add(T::DbWeight::get().writes(101 as Weight)) @@ -654,8 +657,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts OwnerInfoOf (r:100 w:100) fn seal_instantiate(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 50_368_000 - .saturating_add((27_757_564_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 47_294_000 + .saturating_add((26_664_406_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().reads((400 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -668,13 +671,13 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts AccountCounter (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_instantiate_per_input_output_salt_kb(i: u32, o: u32, s: u32, ) -> Weight { - (25_199_228_000 as Weight) + (24_447_236_000 as Weight) // Standard Error: 36_000 - .saturating_add((19_598_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((18_822_000 as Weight).saturating_mul(i as Weight)) // Standard Error: 36_000 - .saturating_add((30_986_000 as Weight).saturating_mul(o as Weight)) + .saturating_add((28_618_000 as Weight).saturating_mul(o as Weight)) // Standard Error: 36_000 - .saturating_add((158_016_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((156_535_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(208 as Weight)) .saturating_add(T::DbWeight::get().writes(206 as Weight)) } @@ -683,9 +686,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256(r: u32, ) -> Weight { - (222_984_000 as Weight) - // Standard Error: 155_000 - .saturating_add((80_649_000 as Weight).saturating_mul(r as Weight)) + (216_091_000 as Weight) + // Standard Error: 123_000 + .saturating_add((79_416_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -694,9 +697,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256_per_kb(n: u32, ) -> Weight { - (393_726_000 as Weight) - // Standard Error: 36_000 - .saturating_add((463_983_000 as Weight).saturating_mul(n as Weight)) + (223_253_000 as Weight) + // Standard Error: 43_000 + .saturating_add((462_629_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -705,9 +708,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256(r: u32, ) -> Weight { - (217_461_000 as Weight) - // Standard Error: 146_000 - .saturating_add((92_540_000 as Weight).saturating_mul(r as Weight)) + (217_285_000 as Weight) + // Standard Error: 147_000 + .saturating_add((91_020_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -716,9 +719,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256_per_kb(n: u32, ) -> Weight { - (271_742_000 as Weight) - // Standard Error: 19_000 - .saturating_add((307_055_000 as Weight).saturating_mul(n as Weight)) + (364_402_000 as Weight) + // Standard Error: 27_000 + .saturating_add((305_342_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -727,9 +730,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256(r: u32, ) -> Weight { - (220_664_000 as Weight) - // Standard Error: 145_000 - .saturating_add((64_516_000 as Weight).saturating_mul(r as Weight)) + (214_309_000 as Weight) + // Standard Error: 107_000 + .saturating_add((63_668_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -738,9 +741,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256_per_kb(n: u32, ) -> Weight { - (287_500_000 as Weight) - // Standard Error: 12_000 - .saturating_add((119_931_000 as Weight).saturating_mul(n as Weight)) + (306_968_000 as Weight) + // Standard Error: 13_000 + .saturating_add((118_373_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -749,9 +752,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128(r: u32, ) -> Weight { - (214_922_000 as Weight) - // Standard Error: 122_000 - .saturating_add((64_236_000 as Weight).saturating_mul(r as Weight)) + (215_434_000 as Weight) + // Standard Error: 115_000 + .saturating_add((62_560_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -760,9 +763,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128_per_kb(n: u32, ) -> Weight { - (251_648_000 as Weight) - // Standard Error: 13_000 - .saturating_add((120_105_000 as Weight).saturating_mul(n as Weight)) + (226_690_000 as Weight) + // Standard Error: 17_000 + .saturating_add((118_871_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -771,266 +774,278 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_ecdsa_recover(r: u32, ) -> Weight { - (124_760_000 as Weight) - // Standard Error: 1_397_000 - .saturating_add((15_387_180_000 as Weight).saturating_mul(r as Weight)) + (187_068_000 as Weight) + // Standard Error: 1_354_000 + .saturating_add((15_409_805_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } + // Storage: System Account (r:1 w:0) + // Storage: Contracts ContractInfoOf (r:1 w:1) + // Storage: Contracts CodeStorage (r:1 w:0) + // Storage: Timestamp Now (r:1 w:0) + // Storage: Contracts OwnerInfoOf (r:36 w:36) + fn seal_set_code_hash(r: u32, ) -> Weight { + (0 as Weight) + // Standard Error: 2_158_000 + .saturating_add((932_937_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(T::DbWeight::get().reads((99 as Weight).saturating_mul(r as Weight))) + .saturating_add(T::DbWeight::get().writes((99 as Weight).saturating_mul(r as Weight))) + } fn instr_i64const(r: u32, ) -> Weight { - (75_287_000 as Weight) - // Standard Error: 11_000 - .saturating_add((569_000 as Weight).saturating_mul(r as Weight)) + (74_317_000 as Weight) + // Standard Error: 1_000 + .saturating_add((597_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64load(r: u32, ) -> Weight { - (74_251_000 as Weight) + (74_303_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_306_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_311_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64store(r: u32, ) -> Weight { - (75_072_000 as Weight) - // Standard Error: 4_000 - .saturating_add((1_386_000 as Weight).saturating_mul(r as Weight)) + (74_024_000 as Weight) + // Standard Error: 0 + .saturating_add((1_431_000 as Weight).saturating_mul(r as Weight)) } fn instr_select(r: u32, ) -> Weight { - (73_811_000 as Weight) - // Standard Error: 0 - .saturating_add((1_783_000 as Weight).saturating_mul(r as Weight)) + (74_108_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_778_000 as Weight).saturating_mul(r as Weight)) } fn instr_if(r: u32, ) -> Weight { - (73_901_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_886_000 as Weight).saturating_mul(r as Weight)) + (73_966_000 as Weight) + // Standard Error: 0 + .saturating_add((1_888_000 as Weight).saturating_mul(r as Weight)) } fn instr_br(r: u32, ) -> Weight { - (73_720_000 as Weight) - // Standard Error: 1_000 - .saturating_add((903_000 as Weight).saturating_mul(r as Weight)) + (73_839_000 as Weight) + // Standard Error: 2_000 + .saturating_add((907_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_if(r: u32, ) -> Weight { - (73_534_000 as Weight) - // Standard Error: 3_000 - .saturating_add((1_459_000 as Weight).saturating_mul(r as Weight)) + (73_624_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_446_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table(r: u32, ) -> Weight { - (73_281_000 as Weight) - // Standard Error: 8_000 - .saturating_add((1_584_000 as Weight).saturating_mul(r as Weight)) + (73_169_000 as Weight) + // Standard Error: 5_000 + .saturating_add((1_602_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table_per_entry(e: u32, ) -> Weight { - (76_135_000 as Weight) - // Standard Error: 1_000 - .saturating_add((6_000 as Weight).saturating_mul(e as Weight)) + (76_328_000 as Weight) + // Standard Error: 0 + .saturating_add((5_000 as Weight).saturating_mul(e as Weight)) } fn instr_call(r: u32, ) -> Weight { - (75_938_000 as Weight) - // Standard Error: 23_000 - .saturating_add((17_156_000 as Weight).saturating_mul(r as Weight)) + (74_771_000 as Weight) + // Standard Error: 22_000 + .saturating_add((17_044_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect(r: u32, ) -> Weight { - (85_864_000 as Weight) - // Standard Error: 28_000 - .saturating_add((28_343_000 as Weight).saturating_mul(r as Weight)) + (90_179_000 as Weight) + // Standard Error: 31_000 + .saturating_add((27_305_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect_per_param(p: u32, ) -> Weight { - (119_795_000 as Weight) - // Standard Error: 1_000 - .saturating_add((911_000 as Weight).saturating_mul(p as Weight)) + (117_977_000 as Weight) + // Standard Error: 2_000 + .saturating_add((928_000 as Weight).saturating_mul(p as Weight)) } fn instr_local_get(r: u32, ) -> Weight { - (74_750_000 as Weight) + (75_093_000 as Weight) // Standard Error: 1_000 - .saturating_add((613_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((610_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_set(r: u32, ) -> Weight { - (74_831_000 as Weight) - // Standard Error: 2_000 - .saturating_add((672_000 as Weight).saturating_mul(r as Weight)) + (74_793_000 as Weight) + // Standard Error: 1_000 + .saturating_add((676_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_tee(r: u32, ) -> Weight { - (74_314_000 as Weight) - // Standard Error: 1_000 - .saturating_add((902_000 as Weight).saturating_mul(r as Weight)) + (74_183_000 as Weight) + // Standard Error: 2_000 + .saturating_add((913_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_get(r: u32, ) -> Weight { - (77_040_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_161_000 as Weight).saturating_mul(r as Weight)) + (77_079_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_156_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_set(r: u32, ) -> Weight { - (76_770_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_372_000 as Weight).saturating_mul(r as Weight)) + (77_063_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_363_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_current(r: u32, ) -> Weight { - (74_010_000 as Weight) - // Standard Error: 1_000 - .saturating_add((665_000 as Weight).saturating_mul(r as Weight)) + (74_314_000 as Weight) + // Standard Error: 2_000 + .saturating_add((662_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_grow(r: u32, ) -> Weight { - (73_597_000 as Weight) - // Standard Error: 929_000 - .saturating_add((183_940_000 as Weight).saturating_mul(r as Weight)) + (73_585_000 as Weight) + // Standard Error: 2_291_000 + .saturating_add((174_749_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64clz(r: u32, ) -> Weight { - (74_488_000 as Weight) - // Standard Error: 4_000 - .saturating_add((893_000 as Weight).saturating_mul(r as Weight)) + (74_062_000 as Weight) + // Standard Error: 2_000 + .saturating_add((905_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ctz(r: u32, ) -> Weight { - (74_024_000 as Weight) - // Standard Error: 5_000 - .saturating_add((908_000 as Weight).saturating_mul(r as Weight)) + (74_121_000 as Weight) + // Standard Error: 1_000 + .saturating_add((903_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64popcnt(r: u32, ) -> Weight { - (74_084_000 as Weight) - // Standard Error: 1_000 - .saturating_add((895_000 as Weight).saturating_mul(r as Weight)) + (74_519_000 as Weight) + // Standard Error: 2_000 + .saturating_add((885_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eqz(r: u32, ) -> Weight { - (74_250_000 as Weight) - // Standard Error: 2_000 - .saturating_add((916_000 as Weight).saturating_mul(r as Weight)) + (74_357_000 as Weight) + // Standard Error: 1_000 + .saturating_add((914_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendsi32(r: u32, ) -> Weight { - (74_027_000 as Weight) + (74_101_000 as Weight) // Standard Error: 1_000 - .saturating_add((883_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((885_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendui32(r: u32, ) -> Weight { - (74_201_000 as Weight) + (74_442_000 as Weight) // Standard Error: 1_000 - .saturating_add((879_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((875_000 as Weight).saturating_mul(r as Weight)) } fn instr_i32wrapi64(r: u32, ) -> Weight { - (74_116_000 as Weight) + (74_247_000 as Weight) // Standard Error: 1_000 - .saturating_add((892_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((891_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eq(r: u32, ) -> Weight { - (74_109_000 as Weight) + (74_091_000 as Weight) // Standard Error: 2_000 - .saturating_add((1_358_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_363_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ne(r: u32, ) -> Weight { - (73_962_000 as Weight) + (74_178_000 as Weight) // Standard Error: 2_000 - .saturating_add((1_363_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_358_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64lts(r: u32, ) -> Weight { - (73_977_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_360_000 as Weight).saturating_mul(r as Weight)) + (74_370_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_353_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ltu(r: u32, ) -> Weight { - (74_046_000 as Weight) + (74_180_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_360_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_356_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gts(r: u32, ) -> Weight { - (73_912_000 as Weight) - // Standard Error: 0 - .saturating_add((1_362_000 as Weight).saturating_mul(r as Weight)) + (74_035_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_365_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gtu(r: u32, ) -> Weight { - (73_918_000 as Weight) + (74_538_000 as Weight) // Standard Error: 2_000 - .saturating_add((1_367_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_357_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64les(r: u32, ) -> Weight { - (73_953_000 as Weight) + (74_035_000 as Weight) // Standard Error: 2_000 - .saturating_add((1_363_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_368_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64leu(r: u32, ) -> Weight { - (74_855_000 as Weight) - // Standard Error: 4_000 - .saturating_add((1_347_000 as Weight).saturating_mul(r as Weight)) + (74_399_000 as Weight) + // Standard Error: 8_000 + .saturating_add((1_362_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ges(r: u32, ) -> Weight { - (73_917_000 as Weight) - // Standard Error: 2_000 + (73_987_000 as Weight) + // Standard Error: 1_000 .saturating_add((1_364_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64geu(r: u32, ) -> Weight { - (73_949_000 as Weight) - // Standard Error: 3_000 - .saturating_add((1_361_000 as Weight).saturating_mul(r as Weight)) + (74_017_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_366_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64add(r: u32, ) -> Weight { - (73_726_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_347_000 as Weight).saturating_mul(r as Weight)) + (74_271_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_330_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64sub(r: u32, ) -> Weight { - (73_921_000 as Weight) - // Standard Error: 1_000 + (74_016_000 as Weight) + // Standard Error: 0 .saturating_add((1_345_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64mul(r: u32, ) -> Weight { - (73_924_000 as Weight) + (74_063_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_341_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_338_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divs(r: u32, ) -> Weight { - (73_842_000 as Weight) - // Standard Error: 2_000 - .saturating_add((2_011_000 as Weight).saturating_mul(r as Weight)) + (74_094_000 as Weight) + // Standard Error: 1_000 + .saturating_add((2_002_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divu(r: u32, ) -> Weight { - (73_932_000 as Weight) - // Standard Error: 1_000 - .saturating_add((2_057_000 as Weight).saturating_mul(r as Weight)) + (73_957_000 as Weight) + // Standard Error: 2_000 + .saturating_add((2_045_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rems(r: u32, ) -> Weight { - (74_028_000 as Weight) + (74_067_000 as Weight) // Standard Error: 2_000 - .saturating_add((2_001_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_975_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64remu(r: u32, ) -> Weight { - (73_784_000 as Weight) - // Standard Error: 2_000 - .saturating_add((2_059_000 as Weight).saturating_mul(r as Weight)) + (74_092_000 as Weight) + // Standard Error: 1_000 + .saturating_add((2_035_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64and(r: u32, ) -> Weight { - (74_169_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_334_000 as Weight).saturating_mul(r as Weight)) + (74_059_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_338_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64or(r: u32, ) -> Weight { - (73_982_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_340_000 as Weight).saturating_mul(r as Weight)) + (74_122_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_335_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64xor(r: u32, ) -> Weight { - (74_310_000 as Weight) + (74_296_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_329_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_333_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shl(r: u32, ) -> Weight { - (73_861_000 as Weight) + (73_810_000 as Weight) // Standard Error: 2_000 - .saturating_add((1_362_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_368_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shrs(r: u32, ) -> Weight { - (73_787_000 as Weight) - // Standard Error: 3_000 - .saturating_add((1_364_000 as Weight).saturating_mul(r as Weight)) + (74_101_000 as Weight) + // Standard Error: 9_000 + .saturating_add((1_407_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shru(r: u32, ) -> Weight { - (73_886_000 as Weight) - // Standard Error: 7_000 - .saturating_add((1_372_000 as Weight).saturating_mul(r as Weight)) + (74_076_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_353_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotl(r: u32, ) -> Weight { - (73_860_000 as Weight) - // Standard Error: 3_000 - .saturating_add((1_362_000 as Weight).saturating_mul(r as Weight)) + (74_082_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_354_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotr(r: u32, ) -> Weight { - (73_917_000 as Weight) + (74_054_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_356_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_355_000 as Weight).saturating_mul(r as Weight)) } } @@ -1038,32 +1053,32 @@ impl WeightInfo for SubstrateWeight { impl WeightInfo for () { // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize() -> Weight { - (1_640_000 as Weight) + (1_590_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn on_initialize_per_trie_key(k: u32, ) -> Weight { - (6_385_000 as Weight) + (9_975_000 as Weight) // Standard Error: 0 - .saturating_add((748_000 as Weight).saturating_mul(k as Weight)) + .saturating_add((724_000 as Weight).saturating_mul(k as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) } // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize_per_queue_item(q: u32, ) -> Weight { - (0 as Weight) - // Standard Error: 5_000 - .saturating_add((2_304_000 as Weight).saturating_mul(q as Weight)) + (7_415_000 as Weight) + // Standard Error: 4_000 + .saturating_add((2_303_000 as Weight).saturating_mul(q as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Contracts PristineCode (r:1 w:0) // Storage: Contracts CodeStorage (r:0 w:1) fn reinstrument(c: u32, ) -> Weight { - (22_923_000 as Weight) - // Standard Error: 33_000 - .saturating_add((65_851_000 as Weight).saturating_mul(c as Weight)) + (18_519_000 as Weight) + // Standard Error: 36_000 + .saturating_add((66_661_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1072,9 +1087,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call_with_code_kb(c: u32, ) -> Weight { - (209_577_000 as Weight) - // Standard Error: 53_000 - .saturating_add((61_341_000 as Weight).saturating_mul(c as Weight)) + (210_319_000 as Weight) + // Standard Error: 41_000 + .saturating_add((54_802_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -1086,11 +1101,11 @@ impl WeightInfo for () { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn instantiate_with_code(c: u32, s: u32, ) -> Weight { - (240_302_000 as Weight) - // Standard Error: 119_000 - .saturating_add((151_894_000 as Weight).saturating_mul(c as Weight)) - // Standard Error: 7_000 - .saturating_add((1_740_000 as Weight).saturating_mul(s as Weight)) + (220_394_000 as Weight) + // Standard Error: 129_000 + .saturating_add((145_155_000 as Weight).saturating_mul(c as Weight)) + // Standard Error: 8_000 + .saturating_add((1_741_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } @@ -1101,9 +1116,9 @@ impl WeightInfo for () { // Storage: System Account (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn instantiate(s: u32, ) -> Weight { - (172_047_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_729_000 as Weight).saturating_mul(s as Weight)) + (171_438_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_721_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } @@ -1112,7 +1127,7 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call() -> Weight { - (139_349_000 as Weight) + (139_529_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -1120,9 +1135,9 @@ impl WeightInfo for () { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn upload_code(c: u32, ) -> Weight { - (50_449_000 as Weight) - // Standard Error: 45_000 - .saturating_add((68_254_000 as Weight).saturating_mul(c as Weight)) + (51_040_000 as Weight) + // Standard Error: 38_000 + .saturating_add((65_886_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -1130,7 +1145,7 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:0 w:1) // Storage: Contracts PristineCode (r:0 w:1) fn remove_code() -> Weight { - (24_576_000 as Weight) + (24_347_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -1139,9 +1154,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_caller(r: u32, ) -> Weight { - (220_059_000 as Weight) - // Standard Error: 128_000 - .saturating_add((49_607_000 as Weight).saturating_mul(r as Weight)) + (217_164_000 as Weight) + // Standard Error: 89_000 + .saturating_add((48_023_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1150,9 +1165,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_is_contract(r: u32, ) -> Weight { - (84_138_000 as Weight) - // Standard Error: 896_000 - .saturating_add((375_553_000 as Weight).saturating_mul(r as Weight)) + (81_537_000 as Weight) + // Standard Error: 847_000 + .saturating_add((367_429_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1162,9 +1177,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_caller_is_origin(r: u32, ) -> Weight { - (222_496_000 as Weight) - // Standard Error: 119_000 - .saturating_add((22_340_000 as Weight).saturating_mul(r as Weight)) + (214_798_000 as Weight) + // Standard Error: 56_000 + .saturating_add((21_100_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1173,9 +1188,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_address(r: u32, ) -> Weight { - (221_446_000 as Weight) - // Standard Error: 131_000 - .saturating_add((49_401_000 as Weight).saturating_mul(r as Weight)) + (216_615_000 as Weight) + // Standard Error: 75_000 + .saturating_add((48_054_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1184,9 +1199,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas_left(r: u32, ) -> Weight { - (220_964_000 as Weight) - // Standard Error: 132_000 - .saturating_add((49_230_000 as Weight).saturating_mul(r as Weight)) + (218_034_000 as Weight) + // Standard Error: 87_000 + .saturating_add((47_594_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1195,9 +1210,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_balance(r: u32, ) -> Weight { - (229_399_000 as Weight) - // Standard Error: 166_000 - .saturating_add((137_407_000 as Weight).saturating_mul(r as Weight)) + (221_980_000 as Weight) + // Standard Error: 135_000 + .saturating_add((135_618_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1206,9 +1221,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_value_transferred(r: u32, ) -> Weight { - (220_103_000 as Weight) - // Standard Error: 133_000 - .saturating_add((49_410_000 as Weight).saturating_mul(r as Weight)) + (217_623_000 as Weight) + // Standard Error: 86_000 + .saturating_add((47_656_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1217,9 +1232,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_minimum_balance(r: u32, ) -> Weight { - (228_143_000 as Weight) - // Standard Error: 151_000 - .saturating_add((48_608_000 as Weight).saturating_mul(r as Weight)) + (216_826_000 as Weight) + // Standard Error: 88_000 + .saturating_add((47_644_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1228,9 +1243,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_block_number(r: u32, ) -> Weight { - (223_899_000 as Weight) - // Standard Error: 142_000 - .saturating_add((48_841_000 as Weight).saturating_mul(r as Weight)) + (219_487_000 as Weight) + // Standard Error: 90_000 + .saturating_add((47_167_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1239,9 +1254,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_now(r: u32, ) -> Weight { - (224_974_000 as Weight) - // Standard Error: 148_000 - .saturating_add((48_902_000 as Weight).saturating_mul(r as Weight)) + (218_953_000 as Weight) + // Standard Error: 95_000 + .saturating_add((47_458_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1251,9 +1266,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0) fn seal_weight_to_fee(r: u32, ) -> Weight { - (227_556_000 as Weight) - // Standard Error: 151_000 - .saturating_add((121_252_000 as Weight).saturating_mul(r as Weight)) + (220_132_000 as Weight) + // Standard Error: 144_000 + .saturating_add((120_373_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1262,9 +1277,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas(r: u32, ) -> Weight { - (127_975_000 as Weight) - // Standard Error: 57_000 - .saturating_add((24_843_000 as Weight).saturating_mul(r as Weight)) + (127_458_000 as Weight) + // Standard Error: 56_000 + .saturating_add((24_015_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1273,9 +1288,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input(r: u32, ) -> Weight { - (224_592_000 as Weight) - // Standard Error: 141_000 - .saturating_add((48_296_000 as Weight).saturating_mul(r as Weight)) + (220_304_000 as Weight) + // Standard Error: 112_000 + .saturating_add((46_804_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1284,9 +1299,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input_per_kb(n: u32, ) -> Weight { - (296_995_000 as Weight) - // Standard Error: 3_000 - .saturating_add((11_884_000 as Weight).saturating_mul(n as Weight)) + (300_916_000 as Weight) + // Standard Error: 8_000 + .saturating_add((10_552_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1294,8 +1309,10 @@ impl WeightInfo for () { // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) - fn seal_return(_r: u32, ) -> Weight { - (224_322_000 as Weight) + fn seal_return(r: u32, ) -> Weight { + (211_812_000 as Weight) + // Standard Error: 138_000 + .saturating_add((1_698_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1304,9 +1321,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return_per_kb(n: u32, ) -> Weight { - (216_240_000 as Weight) - // Standard Error: 1_000 - .saturating_add((206_000 as Weight).saturating_mul(n as Weight)) + (213_994_000 as Weight) + // Standard Error: 0 + .saturating_add((176_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1317,9 +1334,9 @@ impl WeightInfo for () { // Storage: Contracts DeletionQueue (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_terminate(r: u32, ) -> Weight { - (219_637_000 as Weight) - // Standard Error: 3_916_000 - .saturating_add((51_769_000 as Weight).saturating_mul(r as Weight)) + (215_173_000 as Weight) + // Standard Error: 708_000 + .saturating_add((52_509_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((4 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1331,9 +1348,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) fn seal_random(r: u32, ) -> Weight { - (221_470_000 as Weight) - // Standard Error: 154_000 - .saturating_add((158_758_000 as Weight).saturating_mul(r as Weight)) + (219_521_000 as Weight) + // Standard Error: 171_000 + .saturating_add((156_228_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1342,9 +1359,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_deposit_event(r: u32, ) -> Weight { - (228_674_000 as Weight) - // Standard Error: 203_000 - .saturating_add((287_195_000 as Weight).saturating_mul(r as Weight)) + (227_624_000 as Weight) + // Standard Error: 193_000 + .saturating_add((285_058_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1354,11 +1371,11 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: System EventTopics (r:100 w:100) fn seal_deposit_event_per_topic_and_kb(t: u32, n: u32, ) -> Weight { - (507_091_000 as Weight) - // Standard Error: 1_863_000 - .saturating_add((291_858_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 367_000 - .saturating_add((83_459_000 as Weight).saturating_mul(n as Weight)) + (503_312_000 as Weight) + // Standard Error: 1_729_000 + .saturating_add((288_009_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 340_000 + .saturating_add((80_936_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(t as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1369,17 +1386,17 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_debug_message(r: u32, ) -> Weight { - (133_592_000 as Weight) - // Standard Error: 87_000 - .saturating_add((41_718_000 as Weight).saturating_mul(r as Weight)) + (132_096_000 as Weight) + // Standard Error: 73_000 + .saturating_add((40_337_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage(r: u32, ) -> Weight { - (44_719_000 as Weight) - // Standard Error: 1_036_000 - .saturating_add((407_521_000 as Weight).saturating_mul(r as Weight)) + (52_622_000 as Weight) + // Standard Error: 1_006_000 + .saturating_add((404_716_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1387,25 +1404,25 @@ impl WeightInfo for () { } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage_per_new_kb(n: u32, ) -> Weight { - (606_108_000 as Weight) - // Standard Error: 315_000 - .saturating_add((29_136_000 as Weight).saturating_mul(n as Weight)) + (601_324_000 as Weight) + // Standard Error: 264_000 + .saturating_add((27_943_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage_per_old_kb(n: u32, ) -> Weight { - (634_330_000 as Weight) - // Standard Error: 281_000 - .saturating_add((10_741_000 as Weight).saturating_mul(n as Weight)) + (626_752_000 as Weight) + // Standard Error: 292_000 + .saturating_add((10_616_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage(r: u32, ) -> Weight { - (89_750_000 as Weight) - // Standard Error: 924_000 - .saturating_add((382_525_000 as Weight).saturating_mul(r as Weight)) + (80_138_000 as Weight) + // Standard Error: 933_000 + .saturating_add((382_949_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -1413,51 +1430,51 @@ impl WeightInfo for () { } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage_per_kb(n: u32, ) -> Weight { - (616_463_000 as Weight) - // Standard Error: 260_000 - .saturating_add((10_373_000 as Weight).saturating_mul(n as Weight)) + (603_984_000 as Weight) + // Standard Error: 242_000 + .saturating_add((10_712_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage(r: u32, ) -> Weight { - (116_340_000 as Weight) - // Standard Error: 633_000 - .saturating_add((322_054_000 as Weight).saturating_mul(r as Weight)) + (113_136_000 as Weight) + // Standard Error: 635_000 + .saturating_add((324_706_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage_per_kb(n: u32, ) -> Weight { - (563_077_000 as Weight) - // Standard Error: 340_000 - .saturating_add((63_889_000 as Weight).saturating_mul(n as Weight)) + (562_781_000 as Weight) + // Standard Error: 354_000 + .saturating_add((63_275_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(104 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_contains_storage(r: u32, ) -> Weight { - (118_832_000 as Weight) - // Standard Error: 595_000 - .saturating_add((291_817_000 as Weight).saturating_mul(r as Weight)) + (112_237_000 as Weight) + // Standard Error: 655_000 + .saturating_add((296_653_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_contains_storage_per_kb(n: u32, ) -> Weight { - (520_386_000 as Weight) - // Standard Error: 297_000 - .saturating_add((10_076_000 as Weight).saturating_mul(n as Weight)) + (520_002_000 as Weight) + // Standard Error: 232_000 + .saturating_add((9_726_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(104 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage(r: u32, ) -> Weight { - (85_377_000 as Weight) - // Standard Error: 847_000 - .saturating_add((419_438_000 as Weight).saturating_mul(r as Weight)) + (87_232_000 as Weight) + // Standard Error: 920_000 + .saturating_add((415_305_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -1465,9 +1482,9 @@ impl WeightInfo for () { } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage_per_kb(n: u32, ) -> Weight { - (666_218_000 as Weight) - // Standard Error: 294_000 - .saturating_add((64_627_000 as Weight).saturating_mul(n as Weight)) + (648_862_000 as Weight) + // Standard Error: 319_000 + .saturating_add((63_991_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().writes(103 as Weight)) } @@ -1476,9 +1493,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_transfer(r: u32, ) -> Weight { - (108_224_000 as Weight) - // Standard Error: 1_042_000 - .saturating_add((1_723_539_000 as Weight).saturating_mul(r as Weight)) + (99_621_000 as Weight) + // Standard Error: 1_154_000 + .saturating_add((1_732_052_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) @@ -1490,8 +1507,8 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) fn seal_call(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 7_843_000 - .saturating_add((19_825_093_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 6_293_000 + .saturating_add((19_410_115_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1503,8 +1520,8 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) fn seal_delegate_call(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 11_788_000 - .saturating_add((19_855_594_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 7_155_000 + .saturating_add((19_793_614_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads((99 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1513,13 +1530,13 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:2 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_call_per_transfer_input_output_kb(t: u32, i: u32, o: u32, ) -> Weight { - (20_190_331_000 as Weight) - // Standard Error: 75_647_000 - .saturating_add((2_369_225_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 27_000 - .saturating_add((19_831_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 28_000 - .saturating_add((31_191_000 as Weight).saturating_mul(o as Weight)) + (19_711_861_000 as Weight) + // Standard Error: 55_158_000 + .saturating_add((2_509_755_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 19_000 + .saturating_add((17_808_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 21_000 + .saturating_add((28_104_000 as Weight).saturating_mul(o as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().reads((101 as Weight).saturating_mul(t as Weight))) .saturating_add(RocksDbWeight::get().writes(101 as Weight)) @@ -1533,8 +1550,8 @@ impl WeightInfo for () { // Storage: Contracts OwnerInfoOf (r:100 w:100) fn seal_instantiate(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 50_368_000 - .saturating_add((27_757_564_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 47_294_000 + .saturating_add((26_664_406_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().reads((400 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -1547,13 +1564,13 @@ impl WeightInfo for () { // Storage: Contracts AccountCounter (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_instantiate_per_input_output_salt_kb(i: u32, o: u32, s: u32, ) -> Weight { - (25_199_228_000 as Weight) + (24_447_236_000 as Weight) // Standard Error: 36_000 - .saturating_add((19_598_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((18_822_000 as Weight).saturating_mul(i as Weight)) // Standard Error: 36_000 - .saturating_add((30_986_000 as Weight).saturating_mul(o as Weight)) + .saturating_add((28_618_000 as Weight).saturating_mul(o as Weight)) // Standard Error: 36_000 - .saturating_add((158_016_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((156_535_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(208 as Weight)) .saturating_add(RocksDbWeight::get().writes(206 as Weight)) } @@ -1562,9 +1579,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256(r: u32, ) -> Weight { - (222_984_000 as Weight) - // Standard Error: 155_000 - .saturating_add((80_649_000 as Weight).saturating_mul(r as Weight)) + (216_091_000 as Weight) + // Standard Error: 123_000 + .saturating_add((79_416_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1573,9 +1590,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256_per_kb(n: u32, ) -> Weight { - (393_726_000 as Weight) - // Standard Error: 36_000 - .saturating_add((463_983_000 as Weight).saturating_mul(n as Weight)) + (223_253_000 as Weight) + // Standard Error: 43_000 + .saturating_add((462_629_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1584,9 +1601,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256(r: u32, ) -> Weight { - (217_461_000 as Weight) - // Standard Error: 146_000 - .saturating_add((92_540_000 as Weight).saturating_mul(r as Weight)) + (217_285_000 as Weight) + // Standard Error: 147_000 + .saturating_add((91_020_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1595,9 +1612,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256_per_kb(n: u32, ) -> Weight { - (271_742_000 as Weight) - // Standard Error: 19_000 - .saturating_add((307_055_000 as Weight).saturating_mul(n as Weight)) + (364_402_000 as Weight) + // Standard Error: 27_000 + .saturating_add((305_342_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1606,9 +1623,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256(r: u32, ) -> Weight { - (220_664_000 as Weight) - // Standard Error: 145_000 - .saturating_add((64_516_000 as Weight).saturating_mul(r as Weight)) + (214_309_000 as Weight) + // Standard Error: 107_000 + .saturating_add((63_668_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1617,9 +1634,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256_per_kb(n: u32, ) -> Weight { - (287_500_000 as Weight) - // Standard Error: 12_000 - .saturating_add((119_931_000 as Weight).saturating_mul(n as Weight)) + (306_968_000 as Weight) + // Standard Error: 13_000 + .saturating_add((118_373_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1628,9 +1645,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128(r: u32, ) -> Weight { - (214_922_000 as Weight) - // Standard Error: 122_000 - .saturating_add((64_236_000 as Weight).saturating_mul(r as Weight)) + (215_434_000 as Weight) + // Standard Error: 115_000 + .saturating_add((62_560_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1639,9 +1656,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128_per_kb(n: u32, ) -> Weight { - (251_648_000 as Weight) - // Standard Error: 13_000 - .saturating_add((120_105_000 as Weight).saturating_mul(n as Weight)) + (226_690_000 as Weight) + // Standard Error: 17_000 + .saturating_add((118_871_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1650,265 +1667,277 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_ecdsa_recover(r: u32, ) -> Weight { - (124_760_000 as Weight) - // Standard Error: 1_397_000 - .saturating_add((15_387_180_000 as Weight).saturating_mul(r as Weight)) + (187_068_000 as Weight) + // Standard Error: 1_354_000 + .saturating_add((15_409_805_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } + // Storage: System Account (r:1 w:0) + // Storage: Contracts ContractInfoOf (r:1 w:1) + // Storage: Contracts CodeStorage (r:1 w:0) + // Storage: Timestamp Now (r:1 w:0) + // Storage: Contracts OwnerInfoOf (r:36 w:36) + fn seal_set_code_hash(r: u32, ) -> Weight { + (0 as Weight) + // Standard Error: 2_158_000 + .saturating_add((932_937_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(RocksDbWeight::get().reads((99 as Weight).saturating_mul(r as Weight))) + .saturating_add(RocksDbWeight::get().writes((99 as Weight).saturating_mul(r as Weight))) + } fn instr_i64const(r: u32, ) -> Weight { - (75_287_000 as Weight) - // Standard Error: 11_000 - .saturating_add((569_000 as Weight).saturating_mul(r as Weight)) + (74_317_000 as Weight) + // Standard Error: 1_000 + .saturating_add((597_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64load(r: u32, ) -> Weight { - (74_251_000 as Weight) + (74_303_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_306_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_311_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64store(r: u32, ) -> Weight { - (75_072_000 as Weight) - // Standard Error: 4_000 - .saturating_add((1_386_000 as Weight).saturating_mul(r as Weight)) + (74_024_000 as Weight) + // Standard Error: 0 + .saturating_add((1_431_000 as Weight).saturating_mul(r as Weight)) } fn instr_select(r: u32, ) -> Weight { - (73_811_000 as Weight) - // Standard Error: 0 - .saturating_add((1_783_000 as Weight).saturating_mul(r as Weight)) + (74_108_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_778_000 as Weight).saturating_mul(r as Weight)) } fn instr_if(r: u32, ) -> Weight { - (73_901_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_886_000 as Weight).saturating_mul(r as Weight)) + (73_966_000 as Weight) + // Standard Error: 0 + .saturating_add((1_888_000 as Weight).saturating_mul(r as Weight)) } fn instr_br(r: u32, ) -> Weight { - (73_720_000 as Weight) - // Standard Error: 1_000 - .saturating_add((903_000 as Weight).saturating_mul(r as Weight)) + (73_839_000 as Weight) + // Standard Error: 2_000 + .saturating_add((907_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_if(r: u32, ) -> Weight { - (73_534_000 as Weight) - // Standard Error: 3_000 - .saturating_add((1_459_000 as Weight).saturating_mul(r as Weight)) + (73_624_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_446_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table(r: u32, ) -> Weight { - (73_281_000 as Weight) - // Standard Error: 8_000 - .saturating_add((1_584_000 as Weight).saturating_mul(r as Weight)) + (73_169_000 as Weight) + // Standard Error: 5_000 + .saturating_add((1_602_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table_per_entry(e: u32, ) -> Weight { - (76_135_000 as Weight) - // Standard Error: 1_000 - .saturating_add((6_000 as Weight).saturating_mul(e as Weight)) + (76_328_000 as Weight) + // Standard Error: 0 + .saturating_add((5_000 as Weight).saturating_mul(e as Weight)) } fn instr_call(r: u32, ) -> Weight { - (75_938_000 as Weight) - // Standard Error: 23_000 - .saturating_add((17_156_000 as Weight).saturating_mul(r as Weight)) + (74_771_000 as Weight) + // Standard Error: 22_000 + .saturating_add((17_044_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect(r: u32, ) -> Weight { - (85_864_000 as Weight) - // Standard Error: 28_000 - .saturating_add((28_343_000 as Weight).saturating_mul(r as Weight)) + (90_179_000 as Weight) + // Standard Error: 31_000 + .saturating_add((27_305_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect_per_param(p: u32, ) -> Weight { - (119_795_000 as Weight) - // Standard Error: 1_000 - .saturating_add((911_000 as Weight).saturating_mul(p as Weight)) + (117_977_000 as Weight) + // Standard Error: 2_000 + .saturating_add((928_000 as Weight).saturating_mul(p as Weight)) } fn instr_local_get(r: u32, ) -> Weight { - (74_750_000 as Weight) + (75_093_000 as Weight) // Standard Error: 1_000 - .saturating_add((613_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((610_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_set(r: u32, ) -> Weight { - (74_831_000 as Weight) - // Standard Error: 2_000 - .saturating_add((672_000 as Weight).saturating_mul(r as Weight)) + (74_793_000 as Weight) + // Standard Error: 1_000 + .saturating_add((676_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_tee(r: u32, ) -> Weight { - (74_314_000 as Weight) - // Standard Error: 1_000 - .saturating_add((902_000 as Weight).saturating_mul(r as Weight)) + (74_183_000 as Weight) + // Standard Error: 2_000 + .saturating_add((913_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_get(r: u32, ) -> Weight { - (77_040_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_161_000 as Weight).saturating_mul(r as Weight)) + (77_079_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_156_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_set(r: u32, ) -> Weight { - (76_770_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_372_000 as Weight).saturating_mul(r as Weight)) + (77_063_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_363_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_current(r: u32, ) -> Weight { - (74_010_000 as Weight) - // Standard Error: 1_000 - .saturating_add((665_000 as Weight).saturating_mul(r as Weight)) + (74_314_000 as Weight) + // Standard Error: 2_000 + .saturating_add((662_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_grow(r: u32, ) -> Weight { - (73_597_000 as Weight) - // Standard Error: 929_000 - .saturating_add((183_940_000 as Weight).saturating_mul(r as Weight)) + (73_585_000 as Weight) + // Standard Error: 2_291_000 + .saturating_add((174_749_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64clz(r: u32, ) -> Weight { - (74_488_000 as Weight) - // Standard Error: 4_000 - .saturating_add((893_000 as Weight).saturating_mul(r as Weight)) + (74_062_000 as Weight) + // Standard Error: 2_000 + .saturating_add((905_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ctz(r: u32, ) -> Weight { - (74_024_000 as Weight) - // Standard Error: 5_000 - .saturating_add((908_000 as Weight).saturating_mul(r as Weight)) + (74_121_000 as Weight) + // Standard Error: 1_000 + .saturating_add((903_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64popcnt(r: u32, ) -> Weight { - (74_084_000 as Weight) - // Standard Error: 1_000 - .saturating_add((895_000 as Weight).saturating_mul(r as Weight)) + (74_519_000 as Weight) + // Standard Error: 2_000 + .saturating_add((885_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eqz(r: u32, ) -> Weight { - (74_250_000 as Weight) - // Standard Error: 2_000 - .saturating_add((916_000 as Weight).saturating_mul(r as Weight)) + (74_357_000 as Weight) + // Standard Error: 1_000 + .saturating_add((914_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendsi32(r: u32, ) -> Weight { - (74_027_000 as Weight) + (74_101_000 as Weight) // Standard Error: 1_000 - .saturating_add((883_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((885_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendui32(r: u32, ) -> Weight { - (74_201_000 as Weight) + (74_442_000 as Weight) // Standard Error: 1_000 - .saturating_add((879_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((875_000 as Weight).saturating_mul(r as Weight)) } fn instr_i32wrapi64(r: u32, ) -> Weight { - (74_116_000 as Weight) + (74_247_000 as Weight) // Standard Error: 1_000 - .saturating_add((892_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((891_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eq(r: u32, ) -> Weight { - (74_109_000 as Weight) + (74_091_000 as Weight) // Standard Error: 2_000 - .saturating_add((1_358_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_363_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ne(r: u32, ) -> Weight { - (73_962_000 as Weight) + (74_178_000 as Weight) // Standard Error: 2_000 - .saturating_add((1_363_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_358_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64lts(r: u32, ) -> Weight { - (73_977_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_360_000 as Weight).saturating_mul(r as Weight)) + (74_370_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_353_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ltu(r: u32, ) -> Weight { - (74_046_000 as Weight) + (74_180_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_360_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_356_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gts(r: u32, ) -> Weight { - (73_912_000 as Weight) - // Standard Error: 0 - .saturating_add((1_362_000 as Weight).saturating_mul(r as Weight)) + (74_035_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_365_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gtu(r: u32, ) -> Weight { - (73_918_000 as Weight) + (74_538_000 as Weight) // Standard Error: 2_000 - .saturating_add((1_367_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_357_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64les(r: u32, ) -> Weight { - (73_953_000 as Weight) + (74_035_000 as Weight) // Standard Error: 2_000 - .saturating_add((1_363_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_368_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64leu(r: u32, ) -> Weight { - (74_855_000 as Weight) - // Standard Error: 4_000 - .saturating_add((1_347_000 as Weight).saturating_mul(r as Weight)) + (74_399_000 as Weight) + // Standard Error: 8_000 + .saturating_add((1_362_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ges(r: u32, ) -> Weight { - (73_917_000 as Weight) - // Standard Error: 2_000 + (73_987_000 as Weight) + // Standard Error: 1_000 .saturating_add((1_364_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64geu(r: u32, ) -> Weight { - (73_949_000 as Weight) - // Standard Error: 3_000 - .saturating_add((1_361_000 as Weight).saturating_mul(r as Weight)) + (74_017_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_366_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64add(r: u32, ) -> Weight { - (73_726_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_347_000 as Weight).saturating_mul(r as Weight)) + (74_271_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_330_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64sub(r: u32, ) -> Weight { - (73_921_000 as Weight) - // Standard Error: 1_000 + (74_016_000 as Weight) + // Standard Error: 0 .saturating_add((1_345_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64mul(r: u32, ) -> Weight { - (73_924_000 as Weight) + (74_063_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_341_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_338_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divs(r: u32, ) -> Weight { - (73_842_000 as Weight) - // Standard Error: 2_000 - .saturating_add((2_011_000 as Weight).saturating_mul(r as Weight)) + (74_094_000 as Weight) + // Standard Error: 1_000 + .saturating_add((2_002_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divu(r: u32, ) -> Weight { - (73_932_000 as Weight) - // Standard Error: 1_000 - .saturating_add((2_057_000 as Weight).saturating_mul(r as Weight)) + (73_957_000 as Weight) + // Standard Error: 2_000 + .saturating_add((2_045_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rems(r: u32, ) -> Weight { - (74_028_000 as Weight) + (74_067_000 as Weight) // Standard Error: 2_000 - .saturating_add((2_001_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_975_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64remu(r: u32, ) -> Weight { - (73_784_000 as Weight) - // Standard Error: 2_000 - .saturating_add((2_059_000 as Weight).saturating_mul(r as Weight)) + (74_092_000 as Weight) + // Standard Error: 1_000 + .saturating_add((2_035_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64and(r: u32, ) -> Weight { - (74_169_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_334_000 as Weight).saturating_mul(r as Weight)) + (74_059_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_338_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64or(r: u32, ) -> Weight { - (73_982_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_340_000 as Weight).saturating_mul(r as Weight)) + (74_122_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_335_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64xor(r: u32, ) -> Weight { - (74_310_000 as Weight) + (74_296_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_329_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_333_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shl(r: u32, ) -> Weight { - (73_861_000 as Weight) + (73_810_000 as Weight) // Standard Error: 2_000 - .saturating_add((1_362_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_368_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shrs(r: u32, ) -> Weight { - (73_787_000 as Weight) - // Standard Error: 3_000 - .saturating_add((1_364_000 as Weight).saturating_mul(r as Weight)) + (74_101_000 as Weight) + // Standard Error: 9_000 + .saturating_add((1_407_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shru(r: u32, ) -> Weight { - (73_886_000 as Weight) - // Standard Error: 7_000 - .saturating_add((1_372_000 as Weight).saturating_mul(r as Weight)) + (74_076_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_353_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotl(r: u32, ) -> Weight { - (73_860_000 as Weight) - // Standard Error: 3_000 - .saturating_add((1_362_000 as Weight).saturating_mul(r as Weight)) + (74_082_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_354_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotr(r: u32, ) -> Weight { - (73_917_000 as Weight) + (74_054_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_356_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_355_000 as Weight).saturating_mul(r as Weight)) } } From bc8968f4c84ed4cd80acd4d452874c59b5f2fb3b Mon Sep 17 00:00:00 2001 From: Dmitry Kashitsyn Date: Fri, 11 Feb 2022 15:32:06 +0700 Subject: [PATCH 479/695] Separate wasmi and wasmer sandbox implementations into their own modules (#10563) * Moves wasmi specific `ImportResolver` and `MemoryTransfer` impls to submodule * Splits context store environmental, moves impl `Externals` to wasmi backend * Adds wasmer sandbox backend stub module * Move sandbox impl code to backend specific modules * Moves wasmi stuff * Fixes value conversion * Makes it all compile * Remove `with_context_store` * Moves `WasmerBackend` to the impl * Reformat the source * Moves wasmer MemoryWrapper * Reformats the source * Fixes mutability * Moves backend impls to a submodule * Fix visibility * Reformat the source * Feature gate wasmer backend module * Moves wasmi memory allocation to backend module * Rename WasmerBackend to Backend * Refactor dispatch result decoding, get rid of Wasmi types in common sandbox code * Reformat the source * Remove redundant prefixes in backend functions * Remove wasmer-sandbox from default features * Post-review changes * Add conversion soundness proof * Remove redundant prefix * Removes now redundant clone_inner * Add `Error::SandboxBackend`, refactor invoke result * Fix comments * Rename `Error::SandboxBackend` to `Sandbox` * Simplifies logic in `wasmer_backend::invoke` * Fixes memory management --- client/executor/common/src/error.rs | 3 + client/executor/common/src/sandbox.rs | 543 +----------------- .../common/src/sandbox/wasmer_backend.rs | 434 ++++++++++++++ .../common/src/sandbox/wasmi_backend.rs | 323 +++++++++++ client/executor/common/src/util.rs | 191 +----- client/executor/wasmi/src/lib.rs | 6 +- client/executor/wasmtime/src/host.rs | 1 - 7 files changed, 788 insertions(+), 713 deletions(-) create mode 100644 client/executor/common/src/sandbox/wasmer_backend.rs create mode 100644 client/executor/common/src/sandbox/wasmi_backend.rs diff --git a/client/executor/common/src/error.rs b/client/executor/common/src/error.rs index c5de737376c1..5ffcafd7e92c 100644 --- a/client/executor/common/src/error.rs +++ b/client/executor/common/src/error.rs @@ -34,6 +34,9 @@ pub enum Error { #[error(transparent)] Wasmi(#[from] wasmi::Error), + #[error("Sandbox error: {0}")] + Sandbox(String), + #[error("Error calling api function: {0}")] ApiError(Box), diff --git a/client/executor/common/src/sandbox.rs b/client/executor/common/src/sandbox.rs index 34162b7dc497..3f46ec53bdfe 100644 --- a/client/executor/common/src/sandbox.rs +++ b/client/executor/common/src/sandbox.rs @@ -20,24 +20,30 @@ //! //! Sandboxing is backed by wasmi and wasmer, depending on the configuration. +#[cfg(feature = "wasmer-sandbox")] +mod wasmer_backend; + +mod wasmi_backend; + use crate::{ - error::{Error, Result}, + error::{self, Result}, util, }; -use codec::{Decode, Encode}; +use codec::Decode; use sp_core::sandbox as sandbox_primitives; use sp_wasm_interface::{FunctionContext, Pointer, WordSize}; use std::{collections::HashMap, rc::Rc}; -use wasmi::{ - memory_units::Pages, Externals, ImportResolver, MemoryInstance, Module, ModuleInstance, - RuntimeArgs, RuntimeValue, Trap, TrapKind, -}; #[cfg(feature = "wasmer-sandbox")] -use crate::util::wasmer::MemoryWrapper as WasmerMemoryWrapper; -use crate::util::wasmi::MemoryWrapper as WasmiMemoryWrapper; +use wasmer_backend::{ + instantiate as wasmer_instantiate, invoke as wasmer_invoke, new_memory as wasmer_new_memory, + Backend as WasmerBackend, MemoryWrapper as WasmerMemoryWrapper, +}; -environmental::environmental!(SandboxContextStore: trait SandboxContext); +use wasmi_backend::{ + instantiate as wasmi_instantiate, invoke as wasmi_invoke, new_memory as wasmi_new_memory, + MemoryWrapper as WasmiMemoryWrapper, +}; /// Index of a function inside the supervisor. /// @@ -109,63 +115,6 @@ impl Imports { } } -impl ImportResolver for Imports { - fn resolve_func( - &self, - module_name: &str, - field_name: &str, - signature: &::wasmi::Signature, - ) -> std::result::Result { - let idx = self.func_by_name(module_name, field_name).ok_or_else(|| { - wasmi::Error::Instantiation(format!("Export {}:{} not found", module_name, field_name)) - })?; - - Ok(wasmi::FuncInstance::alloc_host(signature.clone(), idx.0)) - } - - fn resolve_memory( - &self, - module_name: &str, - field_name: &str, - _memory_type: &::wasmi::MemoryDescriptor, - ) -> std::result::Result { - let mem = self.memory_by_name(module_name, field_name).ok_or_else(|| { - wasmi::Error::Instantiation(format!("Export {}:{} not found", module_name, field_name)) - })?; - - let wrapper = mem.as_wasmi().ok_or_else(|| { - wasmi::Error::Instantiation(format!( - "Unsupported non-wasmi export {}:{}", - module_name, field_name - )) - })?; - - // Here we use inner memory reference only to resolve - // the imports without accessing the memory contents. - let mem = unsafe { wrapper.clone_inner() }; - - Ok(mem) - } - - fn resolve_global( - &self, - module_name: &str, - field_name: &str, - _global_type: &::wasmi::GlobalDescriptor, - ) -> std::result::Result { - Err(wasmi::Error::Instantiation(format!("Export {}:{} not found", module_name, field_name))) - } - - fn resolve_table( - &self, - module_name: &str, - field_name: &str, - _table_type: &::wasmi::TableDescriptor, - ) -> std::result::Result { - Err(wasmi::Error::Instantiation(format!("Export {}:{} not found", module_name, field_name))) - } -} - /// The sandbox context used to execute sandboxed functions. pub trait SandboxContext { /// Invoke a function in the supervisor environment. @@ -205,132 +154,6 @@ pub struct GuestExternals<'a> { state: u32, } -/// Construct trap error from specified message -fn trap(msg: &'static str) -> Trap { - TrapKind::Host(Box::new(Error::Other(msg.into()))).into() -} - -fn deserialize_result( - mut serialized_result: &[u8], -) -> std::result::Result, Trap> { - use self::sandbox_primitives::HostError; - use sp_wasm_interface::ReturnValue; - let result_val = std::result::Result::::decode(&mut serialized_result) - .map_err(|_| trap("Decoding Result failed!"))?; - - match result_val { - Ok(return_value) => Ok(match return_value { - ReturnValue::Unit => None, - ReturnValue::Value(typed_value) => Some(RuntimeValue::from(typed_value)), - }), - Err(HostError) => Err(trap("Supervisor function returned sandbox::HostError")), - } -} - -impl<'a> Externals for GuestExternals<'a> { - fn invoke_index( - &mut self, - index: usize, - args: RuntimeArgs, - ) -> std::result::Result, Trap> { - SandboxContextStore::with(|sandbox_context| { - // Make `index` typesafe again. - let index = GuestFuncIndex(index); - - // Convert function index from guest to supervisor space - let func_idx = self.sandbox_instance - .guest_to_supervisor_mapping - .func_by_guest_index(index) - .expect( - "`invoke_index` is called with indexes registered via `FuncInstance::alloc_host`; - `FuncInstance::alloc_host` is called with indexes that were obtained from `guest_to_supervisor_mapping`; - `func_by_guest_index` called with `index` can't return `None`; - qed" - ); - - // Serialize arguments into a byte vector. - let invoke_args_data: Vec = args - .as_ref() - .iter() - .cloned() - .map(sp_wasm_interface::Value::from) - .collect::>() - .encode(); - - let state = self.state; - - // Move serialized arguments inside the memory, invoke dispatch thunk and - // then free allocated memory. - let invoke_args_len = invoke_args_data.len() as WordSize; - let invoke_args_ptr = sandbox_context - .supervisor_context() - .allocate_memory(invoke_args_len) - .map_err(|_| trap("Can't allocate memory in supervisor for the arguments"))?; - - let deallocate = |supervisor_context: &mut dyn FunctionContext, ptr, fail_msg| { - supervisor_context.deallocate_memory(ptr).map_err(|_| trap(fail_msg)) - }; - - if sandbox_context - .supervisor_context() - .write_memory(invoke_args_ptr, &invoke_args_data) - .is_err() - { - deallocate( - sandbox_context.supervisor_context(), - invoke_args_ptr, - "Failed dealloction after failed write of invoke arguments", - )?; - return Err(trap("Can't write invoke args into memory")) - } - - let result = sandbox_context.invoke( - invoke_args_ptr, - invoke_args_len, - state, - func_idx, - ); - - deallocate( - sandbox_context.supervisor_context(), - invoke_args_ptr, - "Can't deallocate memory for dispatch thunk's invoke arguments", - )?; - let result = result?; - - // dispatch_thunk returns pointer to serialized arguments. - // Unpack pointer and len of the serialized result data. - let (serialized_result_val_ptr, serialized_result_val_len) = { - // Cast to u64 to use zero-extension. - let v = result as u64; - let ptr = (v as u64 >> 32) as u32; - let len = (v & 0xFFFFFFFF) as u32; - (Pointer::new(ptr), len) - }; - - let serialized_result_val = sandbox_context - .supervisor_context() - .read_memory(serialized_result_val_ptr, serialized_result_val_len) - .map_err(|_| trap("Can't read the serialized result from dispatch thunk")); - - deallocate( - sandbox_context.supervisor_context(), - serialized_result_val_ptr, - "Can't deallocate memory for dispatch thunk's result", - ) - .and_then(|_| serialized_result_val) - .and_then(|serialized_result_val| deserialize_result(&serialized_result_val)) - }).expect("SandboxContextStore is set when invoking sandboxed functions; qed") - } -} - -fn with_guest_externals(sandbox_instance: &SandboxInstance, state: u32, f: F) -> R -where - F: FnOnce(&mut GuestExternals) -> R, -{ - f(&mut GuestExternals { sandbox_instance, state }) -} - /// Module instance in terms of selected backend enum BackendInstance { /// Wasmi module instance @@ -370,74 +193,18 @@ impl SandboxInstance { /// these syscall implementations. pub fn invoke( &self, - - // function to call that is exported from the module export_name: &str, - - // arguments passed to the function - args: &[RuntimeValue], - - // arbitraty context data of the call + args: &[sp_wasm_interface::Value], state: u32, - sandbox_context: &mut dyn SandboxContext, - ) -> std::result::Result, wasmi::Error> { + ) -> std::result::Result, error::Error> { match &self.backend_instance { BackendInstance::Wasmi(wasmi_instance) => - with_guest_externals(self, state, |guest_externals| { - let wasmi_result = SandboxContextStore::using(sandbox_context, || { - wasmi_instance.invoke_export(export_name, args, guest_externals) - })?; - - Ok(wasmi_result) - }), + wasmi_invoke(self, wasmi_instance, export_name, args, state, sandbox_context), #[cfg(feature = "wasmer-sandbox")] - BackendInstance::Wasmer(wasmer_instance) => { - let function = wasmer_instance - .exports - .get_function(export_name) - .map_err(|error| wasmi::Error::Function(error.to_string()))?; - - let args: Vec = args - .iter() - .map(|v| match *v { - RuntimeValue::I32(val) => wasmer::Val::I32(val), - RuntimeValue::I64(val) => wasmer::Val::I64(val), - RuntimeValue::F32(val) => wasmer::Val::F32(val.into()), - RuntimeValue::F64(val) => wasmer::Val::F64(val.into()), - }) - .collect(); - - let wasmer_result = SandboxContextStore::using(sandbox_context, || { - function.call(&args).map_err(|error| wasmi::Error::Function(error.to_string())) - })?; - - if wasmer_result.len() > 1 { - return Err(wasmi::Error::Function( - "multiple return types are not supported yet".into(), - )) - } - - wasmer_result - .first() - .map(|wasm_value| { - let wasmer_value = match *wasm_value { - wasmer::Val::I32(val) => RuntimeValue::I32(val), - wasmer::Val::I64(val) => RuntimeValue::I64(val), - wasmer::Val::F32(val) => RuntimeValue::F32(val.into()), - wasmer::Val::F64(val) => RuntimeValue::F64(val.into()), - _ => - return Err(wasmi::Error::Function(format!( - "Unsupported return value: {:?}", - wasm_value, - ))), - }; - - Ok(wasmer_value) - }) - .transpose() - }, + BackendInstance::Wasmer(wasmer_instance) => + wasmer_invoke(wasmer_instance, export_name, args, state, sandbox_context), } } @@ -634,12 +401,6 @@ impl util::MemoryTransfer for Memory { } } -/// Wasmer specific context -#[cfg(feature = "wasmer-sandbox")] -struct WasmerBackend { - store: wasmer::Store, -} - /// Information specific to a particular execution backend enum BackendContext { /// Wasmi specific context @@ -659,13 +420,8 @@ impl BackendContext { SandboxBackend::TryWasmer => BackendContext::Wasmi, #[cfg(feature = "wasmer-sandbox")] - SandboxBackend::Wasmer | SandboxBackend::TryWasmer => { - let compiler = wasmer_compiler_singlepass::Singlepass::default(); - - BackendContext::Wasmer(WasmerBackend { - store: wasmer::Store::new(&wasmer::JIT::new(compiler).engine()), - }) - }, + SandboxBackend::Wasmer | SandboxBackend::TryWasmer => + BackendContext::Wasmer(WasmerBackend::new()), } } } @@ -709,19 +465,10 @@ impl Store

{ }; let memory = match &backend_context { - BackendContext::Wasmi => Memory::Wasmi(WasmiMemoryWrapper::new(MemoryInstance::alloc( - Pages(initial as usize), - maximum.map(|m| Pages(m as usize)), - )?)), + BackendContext::Wasmi => wasmi_new_memory(initial, maximum)?, #[cfg(feature = "wasmer-sandbox")] - BackendContext::Wasmer(context) => { - let ty = wasmer::MemoryType::new(initial, maximum, false); - Memory::Wasmer(WasmerMemoryWrapper::new( - wasmer::Memory::new(&context.store, ty) - .map_err(|_| Error::InvalidMemoryReference)?, - )) - }, + BackendContext::Wasmer(context) => wasmer_new_memory(context, initial, maximum)?, }; let mem_idx = memories.len(); @@ -827,12 +574,11 @@ impl Store
{ sandbox_context: &mut dyn SandboxContext, ) -> std::result::Result { let sandbox_instance = match self.backend_context { - BackendContext::Wasmi => - Self::instantiate_wasmi(wasm, guest_env, state, sandbox_context)?, + BackendContext::Wasmi => wasmi_instantiate(wasm, guest_env, state, sandbox_context)?, #[cfg(feature = "wasmer-sandbox")] BackendContext::Wasmer(ref context) => - Self::instantiate_wasmer(&context, wasm, guest_env, state, sandbox_context)?, + wasmer_instantiate(&context, wasm, guest_env, state, sandbox_context)?, }; Ok(UnregisteredInstance { sandbox_instance }) @@ -850,241 +596,4 @@ impl
Store
{ self.instances.push(Some((sandbox_instance, dispatch_thunk))); instance_idx as u32 } - - fn instantiate_wasmi( - wasm: &[u8], - guest_env: GuestEnvironment, - state: u32, - sandbox_context: &mut dyn SandboxContext, - ) -> std::result::Result, InstantiationError> { - let wasmi_module = - Module::from_buffer(wasm).map_err(|_| InstantiationError::ModuleDecoding)?; - let wasmi_instance = ModuleInstance::new(&wasmi_module, &guest_env.imports) - .map_err(|_| InstantiationError::Instantiation)?; - - let sandbox_instance = Rc::new(SandboxInstance { - // In general, it's not a very good idea to use `.not_started_instance()` for - // anything but for extracting memory and tables. But in this particular case, we - // are extracting for the purpose of running `start` function which should be ok. - backend_instance: BackendInstance::Wasmi(wasmi_instance.not_started_instance().clone()), - guest_to_supervisor_mapping: guest_env.guest_to_supervisor_mapping, - }); - - with_guest_externals(&sandbox_instance, state, |guest_externals| { - SandboxContextStore::using(sandbox_context, || { - wasmi_instance - .run_start(guest_externals) - .map_err(|_| InstantiationError::StartTrapped) - }) - - // Note: no need to run start on wasmtime instance, since it's done - // automatically - })?; - - Ok(sandbox_instance) - } - - #[cfg(feature = "wasmer-sandbox")] - fn instantiate_wasmer( - context: &WasmerBackend, - wasm: &[u8], - guest_env: GuestEnvironment, - state: u32, - sandbox_context: &mut dyn SandboxContext, - ) -> std::result::Result, InstantiationError> { - let module = wasmer::Module::new(&context.store, wasm) - .map_err(|_| InstantiationError::ModuleDecoding)?; - - type Exports = HashMap; - let mut exports_map = Exports::new(); - - for import in module.imports().into_iter() { - match import.ty() { - // Nothing to do here - wasmer::ExternType::Global(_) | wasmer::ExternType::Table(_) => (), - - wasmer::ExternType::Memory(_) => { - let exports = exports_map - .entry(import.module().to_string()) - .or_insert(wasmer::Exports::new()); - - let memory = guest_env - .imports - .memory_by_name(import.module(), import.name()) - .ok_or(InstantiationError::ModuleDecoding)?; - - let mut wasmer_memory_ref = memory.as_wasmer().expect( - "memory is created by wasmer; \ - exported by the same module and backend; \ - thus the operation can't fail; \ - qed", - ); - - // This is safe since we're only instantiating the module and populating - // the export table, so no memory access can happen at this time. - // All subsequent memory accesses should happen through the wrapper, - // that enforces the memory access protocol. - let wasmer_memory = unsafe { wasmer_memory_ref.clone_inner() }; - - exports.insert(import.name(), wasmer::Extern::Memory(wasmer_memory)); - }, - - wasmer::ExternType::Function(func_ty) => { - let guest_func_index = - guest_env.imports.func_by_name(import.module(), import.name()); - - let guest_func_index = if let Some(index) = guest_func_index { - index - } else { - // Missing import (should we abort here?) - continue - }; - - let supervisor_func_index = guest_env - .guest_to_supervisor_mapping - .func_by_guest_index(guest_func_index) - .ok_or(InstantiationError::ModuleDecoding)?; - - let function = Self::wasmer_dispatch_function( - supervisor_func_index, - &context.store, - func_ty, - state, - ); - - let exports = exports_map - .entry(import.module().to_string()) - .or_insert(wasmer::Exports::new()); - - exports.insert(import.name(), wasmer::Extern::Function(function)); - }, - } - } - - let mut import_object = wasmer::ImportObject::new(); - for (module_name, exports) in exports_map.into_iter() { - import_object.register(module_name, exports); - } - - let instance = SandboxContextStore::using(sandbox_context, || { - wasmer::Instance::new(&module, &import_object).map_err(|error| match error { - wasmer::InstantiationError::Link(_) => InstantiationError::Instantiation, - wasmer::InstantiationError::Start(_) => InstantiationError::StartTrapped, - wasmer::InstantiationError::HostEnvInitialization(_) => - InstantiationError::EnvironmentDefinitionCorrupted, - }) - })?; - - Ok(Rc::new(SandboxInstance { - backend_instance: BackendInstance::Wasmer(instance), - guest_to_supervisor_mapping: guest_env.guest_to_supervisor_mapping, - })) - } - - #[cfg(feature = "wasmer-sandbox")] - fn wasmer_dispatch_function( - supervisor_func_index: SupervisorFuncIndex, - store: &wasmer::Store, - func_ty: &wasmer::FunctionType, - state: u32, - ) -> wasmer::Function { - wasmer::Function::new(store, func_ty, move |params| { - SandboxContextStore::with(|sandbox_context| { - use sp_wasm_interface::Value; - - // Serialize arguments into a byte vector. - let invoke_args_data = params - .iter() - .map(|val| match val { - wasmer::Val::I32(val) => Ok(Value::I32(*val)), - wasmer::Val::I64(val) => Ok(Value::I64(*val)), - wasmer::Val::F32(val) => Ok(Value::F32(f32::to_bits(*val))), - wasmer::Val::F64(val) => Ok(Value::F64(f64::to_bits(*val))), - _ => Err(wasmer::RuntimeError::new(format!( - "Unsupported function argument: {:?}", - val - ))), - }) - .collect::, _>>()? - .encode(); - - // Move serialized arguments inside the memory, invoke dispatch thunk and - // then free allocated memory. - let invoke_args_len = invoke_args_data.len() as WordSize; - let invoke_args_ptr = sandbox_context - .supervisor_context() - .allocate_memory(invoke_args_len) - .map_err(|_| { - wasmer::RuntimeError::new( - "Can't allocate memory in supervisor for the arguments", - ) - })?; - - let deallocate = |fe: &mut dyn FunctionContext, ptr, fail_msg| { - fe.deallocate_memory(ptr).map_err(|_| wasmer::RuntimeError::new(fail_msg)) - }; - - if sandbox_context - .supervisor_context() - .write_memory(invoke_args_ptr, &invoke_args_data) - .is_err() - { - deallocate( - sandbox_context.supervisor_context(), - invoke_args_ptr, - "Failed dealloction after failed write of invoke arguments", - )?; - - return Err(wasmer::RuntimeError::new("Can't write invoke args into memory")) - } - - // Perform the actuall call - let serialized_result = sandbox_context - .invoke(invoke_args_ptr, invoke_args_len, state, supervisor_func_index) - .map_err(|e| wasmer::RuntimeError::new(e.to_string()))?; - - // dispatch_thunk returns pointer to serialized arguments. - // Unpack pointer and len of the serialized result data. - let (serialized_result_val_ptr, serialized_result_val_len) = { - // Cast to u64 to use zero-extension. - let v = serialized_result as u64; - let ptr = (v as u64 >> 32) as u32; - let len = (v & 0xFFFFFFFF) as u32; - (Pointer::new(ptr), len) - }; - - let serialized_result_val = sandbox_context - .supervisor_context() - .read_memory(serialized_result_val_ptr, serialized_result_val_len) - .map_err(|_| { - wasmer::RuntimeError::new( - "Can't read the serialized result from dispatch thunk", - ) - }); - - let deserialized_result = deallocate( - sandbox_context.supervisor_context(), - serialized_result_val_ptr, - "Can't deallocate memory for dispatch thunk's result", - ) - .and_then(|_| serialized_result_val) - .and_then(|serialized_result_val| { - deserialize_result(&serialized_result_val) - .map_err(|e| wasmer::RuntimeError::new(e.to_string())) - })?; - - if let Some(value) = deserialized_result { - Ok(vec![match value { - RuntimeValue::I32(val) => wasmer::Val::I32(val), - RuntimeValue::I64(val) => wasmer::Val::I64(val), - RuntimeValue::F32(val) => wasmer::Val::F32(val.into()), - RuntimeValue::F64(val) => wasmer::Val::F64(val.into()), - }]) - } else { - Ok(vec![]) - } - }) - .expect("SandboxContextStore is set when invoking sandboxed functions; qed") - }) - } } diff --git a/client/executor/common/src/sandbox/wasmer_backend.rs b/client/executor/common/src/sandbox/wasmer_backend.rs new file mode 100644 index 000000000000..dfb26c4a8ded --- /dev/null +++ b/client/executor/common/src/sandbox/wasmer_backend.rs @@ -0,0 +1,434 @@ +// This file is part of Substrate. + +// Copyright (C) 2019-2021 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 . + +//! Wasmer specific impls for sandbox + +use crate::{ + error::{Error, Result}, + sandbox::Memory, + util::{checked_range, MemoryTransfer}, +}; +use codec::{Decode, Encode}; +use sp_core::sandbox::HostError; +use sp_wasm_interface::{FunctionContext, Pointer, ReturnValue, Value, WordSize}; +use std::{cell::RefCell, collections::HashMap, convert::TryInto, rc::Rc}; +use wasmer::RuntimeError; + +use crate::sandbox::{ + BackendInstance, GuestEnvironment, InstantiationError, SandboxContext, SandboxInstance, + SupervisorFuncIndex, +}; + +environmental::environmental!(SandboxContextStore: trait SandboxContext); + +/// Wasmer specific context +pub struct Backend { + store: wasmer::Store, +} + +impl Backend { + pub fn new() -> Self { + let compiler = wasmer_compiler_singlepass::Singlepass::default(); + + Backend { store: wasmer::Store::new(&wasmer::JIT::new(compiler).engine()) } + } +} + +/// Invoke a function within a sandboxed module +pub fn invoke( + instance: &wasmer::Instance, + export_name: &str, + args: &[Value], + _state: u32, + sandbox_context: &mut dyn SandboxContext, +) -> std::result::Result, Error> { + let function = instance + .exports + .get_function(export_name) + .map_err(|error| Error::Sandbox(error.to_string()))?; + + let args: Vec = args + .iter() + .map(|v| match *v { + Value::I32(val) => wasmer::Val::I32(val), + Value::I64(val) => wasmer::Val::I64(val), + Value::F32(val) => wasmer::Val::F32(f32::from_bits(val)), + Value::F64(val) => wasmer::Val::F64(f64::from_bits(val)), + }) + .collect(); + + let wasmer_result = SandboxContextStore::using(sandbox_context, || { + function.call(&args).map_err(|error| Error::Sandbox(error.to_string())) + })?; + + match wasmer_result.as_ref() { + [] => Ok(None), + + [wasm_value] => { + let wasmer_value = match *wasm_value { + wasmer::Val::I32(val) => Value::I32(val), + wasmer::Val::I64(val) => Value::I64(val), + wasmer::Val::F32(val) => Value::F32(f32::to_bits(val)), + wasmer::Val::F64(val) => Value::F64(f64::to_bits(val)), + _ => + return Err(Error::Sandbox(format!( + "Unsupported return value: {:?}", + wasm_value, + ))), + }; + + Ok(Some(wasmer_value)) + }, + + _ => Err(Error::Sandbox("multiple return types are not supported yet".into())), + } +} + +/// Instantiate a module within a sandbox context +pub fn instantiate( + context: &Backend, + wasm: &[u8], + guest_env: GuestEnvironment, + state: u32, + sandbox_context: &mut dyn SandboxContext, +) -> std::result::Result, InstantiationError> { + let module = wasmer::Module::new(&context.store, wasm) + .map_err(|_| InstantiationError::ModuleDecoding)?; + + type Exports = HashMap; + let mut exports_map = Exports::new(); + + for import in module.imports().into_iter() { + match import.ty() { + // Nothing to do here + wasmer::ExternType::Global(_) | wasmer::ExternType::Table(_) => (), + + wasmer::ExternType::Memory(_) => { + let exports = exports_map + .entry(import.module().to_string()) + .or_insert(wasmer::Exports::new()); + + let memory = guest_env + .imports + .memory_by_name(import.module(), import.name()) + .ok_or(InstantiationError::ModuleDecoding)?; + + let wasmer_memory_ref = memory.as_wasmer().expect( + "memory is created by wasmer; \ + exported by the same module and backend; \ + thus the operation can't fail; \ + qed", + ); + + // This is safe since we're only instantiating the module and populating + // the export table, so no memory access can happen at this time. + // All subsequent memory accesses should happen through the wrapper, + // that enforces the memory access protocol. + // + // We take exclusive lock to ensure that we're the only one here, + // since during instantiation phase the memory should only be created + // and not yet accessed. + let wasmer_memory = wasmer_memory_ref + .buffer + .try_borrow_mut() + .map_err(|_| InstantiationError::EnvironmentDefinitionCorrupted)? + .clone(); + + exports.insert(import.name(), wasmer::Extern::Memory(wasmer_memory)); + }, + + wasmer::ExternType::Function(func_ty) => { + let guest_func_index = + guest_env.imports.func_by_name(import.module(), import.name()); + + let guest_func_index = if let Some(index) = guest_func_index { + index + } else { + // Missing import (should we abort here?) + continue + }; + + let supervisor_func_index = guest_env + .guest_to_supervisor_mapping + .func_by_guest_index(guest_func_index) + .ok_or(InstantiationError::ModuleDecoding)?; + + let function = + dispatch_function(supervisor_func_index, &context.store, func_ty, state); + + let exports = exports_map + .entry(import.module().to_string()) + .or_insert(wasmer::Exports::new()); + + exports.insert(import.name(), wasmer::Extern::Function(function)); + }, + } + } + + let mut import_object = wasmer::ImportObject::new(); + for (module_name, exports) in exports_map.into_iter() { + import_object.register(module_name, exports); + } + + let instance = SandboxContextStore::using(sandbox_context, || { + wasmer::Instance::new(&module, &import_object).map_err(|error| match error { + wasmer::InstantiationError::Link(_) => InstantiationError::Instantiation, + wasmer::InstantiationError::Start(_) => InstantiationError::StartTrapped, + wasmer::InstantiationError::HostEnvInitialization(_) => + InstantiationError::EnvironmentDefinitionCorrupted, + }) + })?; + + Ok(Rc::new(SandboxInstance { + backend_instance: BackendInstance::Wasmer(instance), + guest_to_supervisor_mapping: guest_env.guest_to_supervisor_mapping, + })) +} + +fn dispatch_function( + supervisor_func_index: SupervisorFuncIndex, + store: &wasmer::Store, + func_ty: &wasmer::FunctionType, + state: u32, +) -> wasmer::Function { + wasmer::Function::new(store, func_ty, move |params| { + SandboxContextStore::with(|sandbox_context| { + // Serialize arguments into a byte vector. + let invoke_args_data = params + .iter() + .map(|val| match val { + wasmer::Val::I32(val) => Ok(Value::I32(*val)), + wasmer::Val::I64(val) => Ok(Value::I64(*val)), + wasmer::Val::F32(val) => Ok(Value::F32(f32::to_bits(*val))), + wasmer::Val::F64(val) => Ok(Value::F64(f64::to_bits(*val))), + _ => + Err(RuntimeError::new(format!("Unsupported function argument: {:?}", val))), + }) + .collect::, _>>()? + .encode(); + + // Move serialized arguments inside the memory, invoke dispatch thunk and + // then free allocated memory. + let invoke_args_len = invoke_args_data.len() as WordSize; + let invoke_args_ptr = + sandbox_context.supervisor_context().allocate_memory(invoke_args_len).map_err( + |_| RuntimeError::new("Can't allocate memory in supervisor for the arguments"), + )?; + + let deallocate = |fe: &mut dyn FunctionContext, ptr, fail_msg| { + fe.deallocate_memory(ptr).map_err(|_| RuntimeError::new(fail_msg)) + }; + + if sandbox_context + .supervisor_context() + .write_memory(invoke_args_ptr, &invoke_args_data) + .is_err() + { + deallocate( + sandbox_context.supervisor_context(), + invoke_args_ptr, + "Failed dealloction after failed write of invoke arguments", + )?; + + return Err(RuntimeError::new("Can't write invoke args into memory")) + } + + // Perform the actuall call + let serialized_result = sandbox_context + .invoke(invoke_args_ptr, invoke_args_len, state, supervisor_func_index) + .map_err(|e| RuntimeError::new(e.to_string())); + + deallocate( + sandbox_context.supervisor_context(), + invoke_args_ptr, + "Failed dealloction after invoke", + )?; + + let serialized_result = serialized_result?; + + // dispatch_thunk returns pointer to serialized arguments. + // Unpack pointer and len of the serialized result data. + let (serialized_result_val_ptr, serialized_result_val_len) = { + // Cast to u64 to use zero-extension. + let v = serialized_result as u64; + let ptr = (v as u64 >> 32) as u32; + let len = (v & 0xFFFFFFFF) as u32; + (Pointer::new(ptr), len) + }; + + let serialized_result_val = sandbox_context + .supervisor_context() + .read_memory(serialized_result_val_ptr, serialized_result_val_len) + .map_err(|_| { + RuntimeError::new("Can't read the serialized result from dispatch thunk") + }); + + deallocate( + sandbox_context.supervisor_context(), + serialized_result_val_ptr, + "Can't deallocate memory for dispatch thunk's result", + )?; + + let serialized_result_val = serialized_result_val?; + + let deserialized_result = std::result::Result::::decode( + &mut serialized_result_val.as_slice(), + ) + .map_err(|_| RuntimeError::new("Decoding Result failed!"))? + .map_err(|_| RuntimeError::new("Supervisor function returned sandbox::HostError"))?; + + let result = match deserialized_result { + ReturnValue::Value(Value::I32(val)) => vec![wasmer::Val::I32(val)], + ReturnValue::Value(Value::I64(val)) => vec![wasmer::Val::I64(val)], + ReturnValue::Value(Value::F32(val)) => vec![wasmer::Val::F32(f32::from_bits(val))], + ReturnValue::Value(Value::F64(val)) => vec![wasmer::Val::F64(f64::from_bits(val))], + + ReturnValue::Unit => vec![], + }; + + Ok(result) + }) + .expect("SandboxContextStore is set when invoking sandboxed functions; qed") + }) +} + +/// Allocate new memory region +pub fn new_memory( + context: &Backend, + initial: u32, + maximum: Option, +) -> crate::error::Result { + let ty = wasmer::MemoryType::new(initial, maximum, false); + let memory = Memory::Wasmer(MemoryWrapper::new( + wasmer::Memory::new(&context.store, ty).map_err(|_| Error::InvalidMemoryReference)?, + )); + + Ok(memory) +} + +/// In order to enforce memory access protocol to the backend memory +/// we wrap it with `RefCell` and encapsulate all memory operations. +#[derive(Debug, Clone)] +pub struct MemoryWrapper { + buffer: Rc>, +} + +impl MemoryWrapper { + /// Take ownership of the memory region and return a wrapper object + pub fn new(memory: wasmer::Memory) -> Self { + Self { buffer: Rc::new(RefCell::new(memory)) } + } + + /// Returns linear memory of the wasm instance as a slice. + /// + /// # Safety + /// + /// Wasmer doesn't provide comprehensive documentation about the exact behavior of the data + /// pointer. If a dynamic style heap is used the base pointer of the heap can change. Since + /// growing, we cannot guarantee the lifetime of the returned slice reference. + unsafe fn memory_as_slice(memory: &wasmer::Memory) -> &[u8] { + let ptr = memory.data_ptr() as *const _; + + let len: usize = memory.data_size().try_into().expect( + "maximum memory object size never exceeds pointer size on any architecture; \ + usize by design and definition is enough to store any memory object size \ + possible on current achitecture; thus the conversion can not fail; qed", + ); + + if len == 0 { + &[] + } else { + core::slice::from_raw_parts(ptr, len) + } + } + + /// Returns linear memory of the wasm instance as a slice. + /// + /// # Safety + /// + /// See `[memory_as_slice]`. In addition to those requirements, since a mutable reference is + /// returned it must be ensured that only one mutable and no shared references to memory + /// exists at the same time. + unsafe fn memory_as_slice_mut(memory: &mut wasmer::Memory) -> &mut [u8] { + let ptr = memory.data_ptr(); + + let len: usize = memory.data_size().try_into().expect( + "maximum memory object size never exceeds pointer size on any architecture; \ + usize by design and definition is enough to store any memory object size \ + possible on current achitecture; thus the conversion can not fail; qed", + ); + + if len == 0 { + &mut [] + } else { + core::slice::from_raw_parts_mut(ptr, len) + } + } +} + +impl MemoryTransfer for MemoryWrapper { + fn read(&self, source_addr: Pointer, size: usize) -> Result> { + let memory = self.buffer.borrow(); + + let data_size: usize = memory.data_size().try_into().expect( + "maximum memory object size never exceeds pointer size on any architecture; \ + usize by design and definition is enough to store any memory object size \ + possible on current achitecture; thus the conversion can not fail; qed", + ); + + let range = checked_range(source_addr.into(), size, data_size) + .ok_or_else(|| Error::Other("memory read is out of bounds".into()))?; + + let mut buffer = vec![0; range.len()]; + self.read_into(source_addr, &mut buffer)?; + + Ok(buffer) + } + + fn read_into(&self, source_addr: Pointer, destination: &mut [u8]) -> Result<()> { + unsafe { + let memory = self.buffer.borrow(); + + // This should be safe since we don't grow up memory while caching this reference + // and we give up the reference before returning from this function. + let source = Self::memory_as_slice(&memory); + + let range = checked_range(source_addr.into(), destination.len(), source.len()) + .ok_or_else(|| Error::Other("memory read is out of bounds".into()))?; + + destination.copy_from_slice(&source[range]); + Ok(()) + } + } + + fn write_from(&self, dest_addr: Pointer, source: &[u8]) -> Result<()> { + unsafe { + let memory = &mut self.buffer.borrow_mut(); + + // This should be safe since we don't grow up memory while caching this reference + // and we give up the reference before returning from this function. + let destination = Self::memory_as_slice_mut(memory); + + let range = checked_range(dest_addr.into(), source.len(), destination.len()) + .ok_or_else(|| Error::Other("memory write is out of bounds".into()))?; + + destination[range].copy_from_slice(source); + Ok(()) + } + } +} diff --git a/client/executor/common/src/sandbox/wasmi_backend.rs b/client/executor/common/src/sandbox/wasmi_backend.rs new file mode 100644 index 000000000000..92bb0e1e398e --- /dev/null +++ b/client/executor/common/src/sandbox/wasmi_backend.rs @@ -0,0 +1,323 @@ +// This file is part of Substrate. + +// Copyright (C) 2019-2021 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 . + +//! Wasmi specific impls for sandbox + +use codec::{Decode, Encode}; +use sp_core::sandbox::HostError; +use sp_wasm_interface::{FunctionContext, Pointer, ReturnValue, Value, WordSize}; +use std::rc::Rc; + +use wasmi::{ + memory_units::Pages, ImportResolver, MemoryInstance, Module, ModuleInstance, RuntimeArgs, + RuntimeValue, Trap, TrapKind, +}; + +use crate::{ + error::{self, Error}, + sandbox::{ + BackendInstance, GuestEnvironment, GuestExternals, GuestFuncIndex, Imports, + InstantiationError, Memory, SandboxContext, SandboxInstance, + }, + util::{checked_range, MemoryTransfer}, +}; + +environmental::environmental!(SandboxContextStore: trait SandboxContext); + +/// Construct trap error from specified message +fn trap(msg: &'static str) -> Trap { + TrapKind::Host(Box::new(Error::Other(msg.into()))).into() +} + +impl ImportResolver for Imports { + fn resolve_func( + &self, + module_name: &str, + field_name: &str, + signature: &wasmi::Signature, + ) -> std::result::Result { + let idx = self.func_by_name(module_name, field_name).ok_or_else(|| { + wasmi::Error::Instantiation(format!("Export {}:{} not found", module_name, field_name)) + })?; + + Ok(wasmi::FuncInstance::alloc_host(signature.clone(), idx.0)) + } + + fn resolve_memory( + &self, + module_name: &str, + field_name: &str, + _memory_type: &wasmi::MemoryDescriptor, + ) -> std::result::Result { + let mem = self.memory_by_name(module_name, field_name).ok_or_else(|| { + wasmi::Error::Instantiation(format!("Export {}:{} not found", module_name, field_name)) + })?; + + let wrapper = mem.as_wasmi().ok_or_else(|| { + wasmi::Error::Instantiation(format!( + "Unsupported non-wasmi export {}:{}", + module_name, field_name + )) + })?; + + // Here we use inner memory reference only to resolve the imports + // without accessing the memory contents. All subsequent memory accesses + // should happen through the wrapper, that enforces the memory access protocol. + let mem = wrapper.0.clone(); + + Ok(mem) + } + + fn resolve_global( + &self, + module_name: &str, + field_name: &str, + _global_type: &wasmi::GlobalDescriptor, + ) -> std::result::Result { + Err(wasmi::Error::Instantiation(format!("Export {}:{} not found", module_name, field_name))) + } + + fn resolve_table( + &self, + module_name: &str, + field_name: &str, + _table_type: &wasmi::TableDescriptor, + ) -> std::result::Result { + Err(wasmi::Error::Instantiation(format!("Export {}:{} not found", module_name, field_name))) + } +} + +/// Allocate new memory region +pub fn new_memory(initial: u32, maximum: Option) -> crate::error::Result { + let memory = Memory::Wasmi(MemoryWrapper::new( + MemoryInstance::alloc(Pages(initial as usize), maximum.map(|m| Pages(m as usize))) + .map_err(|error| Error::Sandbox(error.to_string()))?, + )); + + Ok(memory) +} + +/// Wasmi provides direct access to its memory using slices. +/// +/// This wrapper limits the scope where the slice can be taken to +#[derive(Debug, Clone)] +pub struct MemoryWrapper(wasmi::MemoryRef); + +impl MemoryWrapper { + /// Take ownership of the memory region and return a wrapper object + fn new(memory: wasmi::MemoryRef) -> Self { + Self(memory) + } +} + +impl MemoryTransfer for MemoryWrapper { + fn read(&self, source_addr: Pointer, size: usize) -> error::Result> { + self.0.with_direct_access(|source| { + let range = checked_range(source_addr.into(), size, source.len()) + .ok_or_else(|| error::Error::Other("memory read is out of bounds".into()))?; + + Ok(Vec::from(&source[range])) + }) + } + + fn read_into(&self, source_addr: Pointer, destination: &mut [u8]) -> error::Result<()> { + self.0.with_direct_access(|source| { + let range = checked_range(source_addr.into(), destination.len(), source.len()) + .ok_or_else(|| error::Error::Other("memory read is out of bounds".into()))?; + + destination.copy_from_slice(&source[range]); + Ok(()) + }) + } + + fn write_from(&self, dest_addr: Pointer, source: &[u8]) -> error::Result<()> { + self.0.with_direct_access_mut(|destination| { + let range = checked_range(dest_addr.into(), source.len(), destination.len()) + .ok_or_else(|| error::Error::Other("memory write is out of bounds".into()))?; + + destination[range].copy_from_slice(source); + Ok(()) + }) + } +} + +impl<'a> wasmi::Externals for GuestExternals<'a> { + fn invoke_index( + &mut self, + index: usize, + args: RuntimeArgs, + ) -> std::result::Result, Trap> { + SandboxContextStore::with(|sandbox_context| { + // Make `index` typesafe again. + let index = GuestFuncIndex(index); + + // Convert function index from guest to supervisor space + let func_idx = self.sandbox_instance + .guest_to_supervisor_mapping + .func_by_guest_index(index) + .expect( + "`invoke_index` is called with indexes registered via `FuncInstance::alloc_host`; + `FuncInstance::alloc_host` is called with indexes that were obtained from `guest_to_supervisor_mapping`; + `func_by_guest_index` called with `index` can't return `None`; + qed" + ); + + // Serialize arguments into a byte vector. + let invoke_args_data: Vec = args + .as_ref() + .iter() + .cloned() + .map(sp_wasm_interface::Value::from) + .collect::>() + .encode(); + + let state = self.state; + + // Move serialized arguments inside the memory, invoke dispatch thunk and + // then free allocated memory. + let invoke_args_len = invoke_args_data.len() as WordSize; + let invoke_args_ptr = sandbox_context + .supervisor_context() + .allocate_memory(invoke_args_len) + .map_err(|_| trap("Can't allocate memory in supervisor for the arguments"))?; + + let deallocate = |supervisor_context: &mut dyn FunctionContext, ptr, fail_msg| { + supervisor_context.deallocate_memory(ptr).map_err(|_| trap(fail_msg)) + }; + + if sandbox_context + .supervisor_context() + .write_memory(invoke_args_ptr, &invoke_args_data) + .is_err() + { + deallocate( + sandbox_context.supervisor_context(), + invoke_args_ptr, + "Failed dealloction after failed write of invoke arguments", + )?; + return Err(trap("Can't write invoke args into memory")) + } + + let result = sandbox_context.invoke( + invoke_args_ptr, + invoke_args_len, + state, + func_idx, + ); + + deallocate( + sandbox_context.supervisor_context(), + invoke_args_ptr, + "Can't deallocate memory for dispatch thunk's invoke arguments", + )?; + let result = result?; + + // dispatch_thunk returns pointer to serialized arguments. + // Unpack pointer and len of the serialized result data. + let (serialized_result_val_ptr, serialized_result_val_len) = { + // Cast to u64 to use zero-extension. + let v = result as u64; + let ptr = (v as u64 >> 32) as u32; + let len = (v & 0xFFFFFFFF) as u32; + (Pointer::new(ptr), len) + }; + + let serialized_result_val = sandbox_context + .supervisor_context() + .read_memory(serialized_result_val_ptr, serialized_result_val_len) + .map_err(|_| trap("Can't read the serialized result from dispatch thunk")); + + deallocate( + sandbox_context.supervisor_context(), + serialized_result_val_ptr, + "Can't deallocate memory for dispatch thunk's result", + ) + .and_then(|_| serialized_result_val) + .and_then(|serialized_result_val| { + let result_val = std::result::Result::::decode(&mut serialized_result_val.as_slice()) + .map_err(|_| trap("Decoding Result failed!"))?; + + match result_val { + Ok(return_value) => Ok(match return_value { + ReturnValue::Unit => None, + ReturnValue::Value(typed_value) => Some(RuntimeValue::from(typed_value)), + }), + Err(HostError) => Err(trap("Supervisor function returned sandbox::HostError")), + } + }) + }).expect("SandboxContextStore is set when invoking sandboxed functions; qed") + } +} + +fn with_guest_externals(sandbox_instance: &SandboxInstance, state: u32, f: F) -> R +where + F: FnOnce(&mut GuestExternals) -> R, +{ + f(&mut GuestExternals { sandbox_instance, state }) +} + +/// Instantiate a module within a sandbox context +pub fn instantiate( + wasm: &[u8], + guest_env: GuestEnvironment, + state: u32, + sandbox_context: &mut dyn SandboxContext, +) -> std::result::Result, InstantiationError> { + let wasmi_module = Module::from_buffer(wasm).map_err(|_| InstantiationError::ModuleDecoding)?; + let wasmi_instance = ModuleInstance::new(&wasmi_module, &guest_env.imports) + .map_err(|_| InstantiationError::Instantiation)?; + + let sandbox_instance = Rc::new(SandboxInstance { + // In general, it's not a very good idea to use `.not_started_instance()` for + // anything but for extracting memory and tables. But in this particular case, we + // are extracting for the purpose of running `start` function which should be ok. + backend_instance: BackendInstance::Wasmi(wasmi_instance.not_started_instance().clone()), + guest_to_supervisor_mapping: guest_env.guest_to_supervisor_mapping, + }); + + with_guest_externals(&sandbox_instance, state, |guest_externals| { + SandboxContextStore::using(sandbox_context, || { + wasmi_instance + .run_start(guest_externals) + .map_err(|_| InstantiationError::StartTrapped) + }) + })?; + + Ok(sandbox_instance) +} + +/// Invoke a function within a sandboxed module +pub fn invoke( + instance: &SandboxInstance, + module: &wasmi::ModuleRef, + export_name: &str, + args: &[Value], + state: u32, + sandbox_context: &mut dyn SandboxContext, +) -> std::result::Result, error::Error> { + with_guest_externals(instance, state, |guest_externals| { + SandboxContextStore::using(sandbox_context, || { + let args = args.iter().cloned().map(Into::into).collect::>(); + + module + .invoke_export(export_name, &args, guest_externals) + .map(|result| result.map(Into::into)) + .map_err(|error| error::Error::Sandbox(error.to_string())) + }) + }) +} diff --git a/client/executor/common/src/util.rs b/client/executor/common/src/util.rs index eddf4230504c..fbae01b556fb 100644 --- a/client/executor/common/src/util.rs +++ b/client/executor/common/src/util.rs @@ -18,7 +18,7 @@ //! Utilities used by all backends -use crate::error::{Error, Result}; +use crate::error::Result; use sp_wasm_interface::Pointer; use std::ops::Range; @@ -50,192 +50,3 @@ pub trait MemoryTransfer { /// Returns an error if the write would go out of the memory bounds. fn write_from(&self, dest_addr: Pointer, source: &[u8]) -> Result<()>; } - -/// Safe wrapper over wasmi memory reference -pub mod wasmi { - use super::*; - - /// Wasmi provides direct access to its memory using slices. - /// - /// This wrapper limits the scope where the slice can be taken to - #[derive(Debug, Clone)] - pub struct MemoryWrapper(::wasmi::MemoryRef); - - impl MemoryWrapper { - /// Take ownership of the memory region and return a wrapper object - pub fn new(memory: ::wasmi::MemoryRef) -> Self { - Self(memory) - } - - /// Clone the underlying memory object - /// - /// # Safety - /// - /// The sole purpose of `MemoryRef` is to protect the memory from uncontrolled - /// access. By returning the memory object "as is" we bypass all of the checks. - /// - /// Intended to use only during module initialization. - pub unsafe fn clone_inner(&self) -> ::wasmi::MemoryRef { - self.0.clone() - } - } - - impl super::MemoryTransfer for MemoryWrapper { - fn read(&self, source_addr: Pointer, size: usize) -> Result> { - self.0.with_direct_access(|source| { - let range = checked_range(source_addr.into(), size, source.len()) - .ok_or_else(|| Error::Other("memory read is out of bounds".into()))?; - - Ok(Vec::from(&source[range])) - }) - } - - fn read_into(&self, source_addr: Pointer, destination: &mut [u8]) -> Result<()> { - self.0.with_direct_access(|source| { - let range = checked_range(source_addr.into(), destination.len(), source.len()) - .ok_or_else(|| Error::Other("memory read is out of bounds".into()))?; - - destination.copy_from_slice(&source[range]); - Ok(()) - }) - } - - fn write_from(&self, dest_addr: Pointer, source: &[u8]) -> Result<()> { - self.0.with_direct_access_mut(|destination| { - let range = checked_range(dest_addr.into(), source.len(), destination.len()) - .ok_or_else(|| Error::Other("memory write is out of bounds".into()))?; - - destination[range].copy_from_slice(source); - Ok(()) - }) - } - } -} - -// Routines specific to Wasmer runtime. Since sandbox can be invoked from both -/// wasmi and wasmtime runtime executors, we need to have a way to deal with sanbox -/// backends right from the start. -#[cfg(feature = "wasmer-sandbox")] -pub mod wasmer { - use super::checked_range; - use crate::error::{Error, Result}; - use sp_wasm_interface::Pointer; - use std::{cell::RefCell, convert::TryInto, rc::Rc}; - - /// In order to enforce memory access protocol to the backend memory - /// we wrap it with `RefCell` and encapsulate all memory operations. - #[derive(Debug, Clone)] - pub struct MemoryWrapper { - buffer: Rc>, - } - - impl MemoryWrapper { - /// Take ownership of the memory region and return a wrapper object - pub fn new(memory: wasmer::Memory) -> Self { - Self { buffer: Rc::new(RefCell::new(memory)) } - } - - /// Returns linear memory of the wasm instance as a slice. - /// - /// # Safety - /// - /// Wasmer doesn't provide comprehensive documentation about the exact behavior of the data - /// pointer. If a dynamic style heap is used the base pointer of the heap can change. Since - /// growing, we cannot guarantee the lifetime of the returned slice reference. - unsafe fn memory_as_slice(memory: &wasmer::Memory) -> &[u8] { - let ptr = memory.data_ptr() as *const _; - let len: usize = - memory.data_size().try_into().expect("data size should fit into usize"); - - if len == 0 { - &[] - } else { - core::slice::from_raw_parts(ptr, len) - } - } - - /// Returns linear memory of the wasm instance as a slice. - /// - /// # Safety - /// - /// See `[memory_as_slice]`. In addition to those requirements, since a mutable reference is - /// returned it must be ensured that only one mutable and no shared references to memory - /// exists at the same time. - unsafe fn memory_as_slice_mut(memory: &wasmer::Memory) -> &mut [u8] { - let ptr = memory.data_ptr(); - let len: usize = - memory.data_size().try_into().expect("data size should fit into usize"); - - if len == 0 { - &mut [] - } else { - core::slice::from_raw_parts_mut(ptr, len) - } - } - - /// Clone the underlying memory object - /// - /// # Safety - /// - /// The sole purpose of `MemoryRef` is to protect the memory from uncontrolled - /// access. By returning the memory object "as is" we bypass all of the checks. - /// - /// Intended to use only during module initialization. - /// - /// # Panics - /// - /// Will panic if `MemoryRef` is currently in use. - pub unsafe fn clone_inner(&mut self) -> wasmer::Memory { - // We take exclusive lock to ensure that we're the only one here - self.buffer.borrow_mut().clone() - } - } - - impl super::MemoryTransfer for MemoryWrapper { - fn read(&self, source_addr: Pointer, size: usize) -> Result> { - let memory = self.buffer.borrow(); - - let data_size = memory.data_size().try_into().expect("data size does not fit"); - - let range = checked_range(source_addr.into(), size, data_size) - .ok_or_else(|| Error::Other("memory read is out of bounds".into()))?; - - let mut buffer = vec![0; range.len()]; - self.read_into(source_addr, &mut buffer)?; - - Ok(buffer) - } - - fn read_into(&self, source_addr: Pointer, destination: &mut [u8]) -> Result<()> { - unsafe { - let memory = self.buffer.borrow(); - - // This should be safe since we don't grow up memory while caching this reference - // and we give up the reference before returning from this function. - let source = Self::memory_as_slice(&memory); - - let range = checked_range(source_addr.into(), destination.len(), source.len()) - .ok_or_else(|| Error::Other("memory read is out of bounds".into()))?; - - destination.copy_from_slice(&source[range]); - Ok(()) - } - } - - fn write_from(&self, dest_addr: Pointer, source: &[u8]) -> Result<()> { - unsafe { - let memory = self.buffer.borrow_mut(); - - // This should be safe since we don't grow up memory while caching this reference - // and we give up the reference before returning from this function. - let destination = Self::memory_as_slice_mut(&memory); - - let range = checked_range(dest_addr.into(), source.len(), destination.len()) - .ok_or_else(|| Error::Other("memory write is out of bounds".into()))?; - - destination[range].copy_from_slice(source); - Ok(()) - } - } - } -} diff --git a/client/executor/wasmi/src/lib.rs b/client/executor/wasmi/src/lib.rs index f0488972daca..97c73c3454a4 100644 --- a/client/executor/wasmi/src/lib.rs +++ b/client/executor/wasmi/src/lib.rs @@ -102,10 +102,7 @@ impl<'a> sandbox::SandboxContext for SandboxContext<'a> { match result { Ok(Some(RuntimeValue::I64(val))) => Ok(val), Ok(_) => return Err("Supervisor function returned unexpected result!".into()), - Err(err) => Err(Error::AbortedDueToTrap(MessageWithBacktrace { - message: err.to_string(), - backtrace: None, - })), + Err(err) => Err(Error::Sandbox(err.to_string())), } } @@ -222,7 +219,6 @@ impl Sandbox for FunctionExecutor { let args = Vec::::decode(&mut args) .map_err(|_| "Can't decode serialized arguments for the invocation")? .into_iter() - .map(Into::into) .collect::>(); let instance = diff --git a/client/executor/wasmtime/src/host.rs b/client/executor/wasmtime/src/host.rs index b310ada24b62..23deacbf9362 100644 --- a/client/executor/wasmtime/src/host.rs +++ b/client/executor/wasmtime/src/host.rs @@ -221,7 +221,6 @@ impl<'a> Sandbox for HostContext<'a> { let args = Vec::::decode(&mut args) .map_err(|_| "Can't decode serialized arguments for the invocation")? .into_iter() - .map(Into::into) .collect::>(); let instance = self.sandbox_store().instance(instance_id).map_err(|e| e.to_string())?; From 1986d9a10a2cbf697ea24ed966305f88e156edd5 Mon Sep 17 00:00:00 2001 From: Antonio Yang Date: Fri, 11 Feb 2022 17:14:13 +0800 Subject: [PATCH 480/695] Show Network ID when creating and inspecting (#10838) Signed-off-by: Antonio Yang --- client/cli/src/commands/utils.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/client/cli/src/commands/utils.rs b/client/cli/src/commands/utils.rs index 7f0413f59601..d20df01e5a90 100644 --- a/client/cli/src/commands/utils.rs +++ b/client/cli/src/commands/utils.rs @@ -73,6 +73,7 @@ pub fn print_from_uri( Pair::Public: Into, { let password = password.as_ref().map(|s| s.expose_secret().as_str()); + let network_id = String::from(unwrap_or_default_ss58_version(network_override)); if let Ok((pair, seed)) = Pair::from_phrase(uri, password.clone()) { let public_key = pair.public(); let network_override = unwrap_or_default_ss58_version(network_override); @@ -81,6 +82,7 @@ pub fn print_from_uri( OutputType::Json => { let json = json!({ "secretPhrase": uri, + "networkId": network_id, "secretSeed": format_seed::(seed), "publicKey": format_public_key::(public_key.clone()), "ss58PublicKey": public_key.to_ss58check_with_version(network_override), @@ -95,12 +97,14 @@ pub fn print_from_uri( OutputType::Text => { println!( "Secret phrase: {}\n \ + Network ID: {}\n \ Secret seed: {}\n \ Public key (hex): {}\n \ Account ID: {}\n \ Public key (SS58): {}\n \ SS58 Address: {}", uri, + network_id, format_seed::(seed), format_public_key::(public_key.clone()), format_account_id::(public_key.clone()), @@ -117,6 +121,7 @@ pub fn print_from_uri( OutputType::Json => { let json = json!({ "secretKeyUri": uri, + "networkId": network_id, "secretSeed": if let Some(seed) = seed { format_seed::(seed) } else { "n/a".into() }, "publicKey": format_public_key::(public_key.clone()), "ss58PublicKey": public_key.to_ss58check_with_version(network_override), @@ -131,12 +136,14 @@ pub fn print_from_uri( OutputType::Text => { println!( "Secret Key URI `{}` is account:\n \ + Network ID: {} \n \ Secret seed: {}\n \ Public key (hex): {}\n \ Account ID: {}\n \ Public key (SS58): {}\n \ SS58 Address: {}", uri, + network_id, if let Some(seed) = seed { format_seed::(seed) } else { "n/a".into() }, format_public_key::(public_key.clone()), format_account_id::(public_key.clone()), @@ -167,7 +174,7 @@ pub fn print_from_uri( OutputType::Text => { println!( "Public Key URI `{}` is account:\n \ - Network ID/version: {}\n \ + Network ID/Version: {}\n \ Public key (hex): {}\n \ Account ID: {}\n \ Public key (SS58): {}\n \ @@ -217,7 +224,7 @@ where }, OutputType::Text => { println!( - "Network ID/version: {}\n \ + "Network ID/Version: {}\n \ Public key (hex): {}\n \ Account ID: {}\n \ Public key (SS58): {}\n \ From c3ebcf1cf05349e748d2c6d45479e12cf803e71a Mon Sep 17 00:00:00 2001 From: Koute Date: Fri, 11 Feb 2022 20:35:35 +0900 Subject: [PATCH 481/695] Reduce overhead of generating network event metrics (#10839) --- client/network/src/service/out_events.rs | 62 +++++++++++++++++------- 1 file changed, 44 insertions(+), 18 deletions(-) diff --git a/client/network/src/service/out_events.rs b/client/network/src/service/out_events.rs index 5f088b85b1cf..1fe13bc30faf 100644 --- a/client/network/src/service/out_events.rs +++ b/client/network/src/service/out_events.rs @@ -37,6 +37,7 @@ use futures::{channel::mpsc, prelude::*, ready, stream::FusedStream}; use parking_lot::Mutex; use prometheus_endpoint::{register, CounterVec, GaugeVec, Opts, PrometheusError, Registry, U64}; use std::{ + cell::RefCell, convert::TryFrom as _, fmt, pin::Pin, @@ -187,6 +188,23 @@ struct Metrics { num_channels: GaugeVec, } +thread_local! { + static LABEL_BUFFER: RefCell = RefCell::new(String::new()); +} + +fn format_label(prefix: &str, protocol: &str, callback: impl FnOnce(&str)) { + LABEL_BUFFER.with(|label_buffer| { + let mut label_buffer = label_buffer.borrow_mut(); + label_buffer.clear(); + label_buffer.reserve(prefix.len() + protocol.len() + 2); + label_buffer.push_str(prefix); + label_buffer.push_str("\""); + label_buffer.push_str(protocol); + label_buffer.push_str("\""); + callback(&label_buffer); + }); +} + impl Metrics { fn register(registry: &Registry) -> Result { Ok(Self { @@ -232,20 +250,26 @@ impl Metrics { .inc_by(num); }, Event::NotificationStreamOpened { protocol, .. } => { - self.events_total - .with_label_values(&[&format!("notif-open-{:?}", protocol), "sent", name]) - .inc_by(num); + format_label("notif-open-", &protocol, |protocol_label| { + self.events_total + .with_label_values(&[protocol_label, "sent", name]) + .inc_by(num); + }); }, Event::NotificationStreamClosed { protocol, .. } => { - self.events_total - .with_label_values(&[&format!("notif-closed-{:?}", protocol), "sent", name]) - .inc_by(num); + format_label("notif-closed-", &protocol, |protocol_label| { + self.events_total + .with_label_values(&[protocol_label, "sent", name]) + .inc_by(num); + }); }, Event::NotificationsReceived { messages, .. } => for (protocol, message) in messages { - self.events_total - .with_label_values(&[&format!("notif-{:?}", protocol), "sent", name]) - .inc_by(num); + format_label("notif-", &protocol, |protocol_label| { + self.events_total + .with_label_values(&[protocol_label, "sent", name]) + .inc_by(num); + }); self.notifications_sizes.with_label_values(&[protocol, "sent", name]).inc_by( num.saturating_mul(u64::try_from(message.len()).unwrap_or(u64::MAX)), ); @@ -267,20 +291,22 @@ impl Metrics { .inc(); }, Event::NotificationStreamOpened { protocol, .. } => { - self.events_total - .with_label_values(&[&format!("notif-open-{:?}", protocol), "received", name]) - .inc(); + format_label("notif-open-", &protocol, |protocol_label| { + self.events_total.with_label_values(&[protocol_label, "received", name]).inc(); + }); }, Event::NotificationStreamClosed { protocol, .. } => { - self.events_total - .with_label_values(&[&format!("notif-closed-{:?}", protocol), "received", name]) - .inc(); + format_label("notif-closed-", &protocol, |protocol_label| { + self.events_total.with_label_values(&[protocol_label, "received", name]).inc(); + }); }, Event::NotificationsReceived { messages, .. } => for (protocol, message) in messages { - self.events_total - .with_label_values(&[&format!("notif-{:?}", protocol), "received", name]) - .inc(); + format_label("notif-", &protocol, |protocol_label| { + self.events_total + .with_label_values(&[protocol_label, "received", name]) + .inc(); + }); self.notifications_sizes .with_label_values(&[&protocol, "received", name]) .inc_by(u64::try_from(message.len()).unwrap_or(u64::MAX)); From a9020646e784170050a4e6324dd067ab0e5af448 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Fri, 11 Feb 2022 14:17:38 +0100 Subject: [PATCH 482/695] Fix reentrancy of FrozenBalance::died hook (#10473) * assets: execute `died` hook outside of mutate Signed-off-by: Oliver Tale-Yazdi * assets: extend tests for `died` hook Signed-off-by: Oliver Tale-Yazdi * assets: update doc of FrozenBalance::died Signed-off-by: Oliver Tale-Yazdi * assets: review fixes - fix cases where `died` should not have been called - use `Option` instead of `DeadConsequence` Signed-off-by: Oliver Tale-Yazdi * assets: update comment in mock.rs Signed-off-by: Oliver Tale-Yazdi * assets: return `Remove` in dead_account The return value is ignored in the only case that it is produced by a call, but having it this way makes it more understandable. Signed-off-by: Oliver Tale-Yazdi --- frame/assets/src/functions.rs | 136 ++++++++++++++++++++++------------ frame/assets/src/mock.rs | 10 +++ frame/assets/src/tests.rs | 47 ++++++++++++ frame/assets/src/types.rs | 8 +- 4 files changed, 148 insertions(+), 53 deletions(-) diff --git a/frame/assets/src/functions.rs b/frame/assets/src/functions.rs index 73804fc832c9..48a86ca3cfa0 100644 --- a/frame/assets/src/functions.rs +++ b/frame/assets/src/functions.rs @@ -84,13 +84,11 @@ impl, I: 'static> Pallet { } pub(super) fn dead_account( - what: T::AssetId, who: &T::AccountId, d: &mut AssetDetails>, reason: &ExistenceReason>, force: bool, ) -> DeadConsequence { - let mut result = Remove; match *reason { ExistenceReason::Consumer => frame_system::Pallet::::dec_consumers(who), ExistenceReason::Sufficient => { @@ -99,11 +97,10 @@ impl, I: 'static> Pallet { }, ExistenceReason::DepositRefunded => {}, ExistenceReason::DepositHeld(_) if !force => return Keep, - ExistenceReason::DepositHeld(_) => result = Keep, + ExistenceReason::DepositHeld(_) => {}, } d.accounts = d.accounts.saturating_sub(1); - T::Freezer::died(what, who); - result + Remove } pub(super) fn can_increase( @@ -323,12 +320,14 @@ impl, I: 'static> Pallet { T::Currency::unreserve(&who, deposit); - if let Remove = Self::dead_account(id, &who, &mut details, &account.reason, false) { + if let Remove = Self::dead_account(&who, &mut details, &account.reason, false) { Account::::remove(id, &who); } else { debug_assert!(false, "refund did not result in dead account?!"); } Asset::::insert(&id, details); + // Executing a hook here is safe, since it is not in a `mutate`. + T::Freezer::died(id, &who); Ok(()) } @@ -461,6 +460,7 @@ impl, I: 'static> Pallet { } let actual = Self::prep_debit(id, target, amount, f)?; + let mut target_died: Option = None; Asset::::try_mutate(id, |maybe_details| -> DispatchResult { let mut details = maybe_details.as_mut().ok_or(Error::::Unknown)?; @@ -475,9 +475,9 @@ impl, I: 'static> Pallet { account.balance = account.balance.saturating_sub(actual); if account.balance < details.min_balance { debug_assert!(account.balance.is_zero(), "checked in prep; qed"); - if let Remove = - Self::dead_account(id, target, &mut details, &account.reason, false) - { + target_died = + Some(Self::dead_account(target, &mut details, &account.reason, false)); + if let Some(Remove) = target_died { return Ok(()) } }; @@ -488,6 +488,10 @@ impl, I: 'static> Pallet { Ok(()) })?; + // Execute hook outside of `mutate`. + if let Some(Remove) = target_died { + T::Freezer::died(id, target); + } Ok(actual) } @@ -507,6 +511,24 @@ impl, I: 'static> Pallet { maybe_need_admin: Option, f: TransferFlags, ) -> Result { + let (balance, died) = + Self::transfer_and_die(id, source, dest, amount, maybe_need_admin, f)?; + if let Some(Remove) = died { + T::Freezer::died(id, source); + } + Ok(balance) + } + + /// Same as `do_transfer` but it does not execute the `FrozenBalance::died` hook and + /// instead returns whether and how the `source` account died in this operation. + fn transfer_and_die( + id: T::AssetId, + source: &T::AccountId, + dest: &T::AccountId, + amount: T::Balance, + maybe_need_admin: Option, + f: TransferFlags, + ) -> Result<(T::Balance, Option), DispatchError> { // Early exist if no-op. if amount.is_zero() { Self::deposit_event(Event::Transferred { @@ -515,7 +537,7 @@ impl, I: 'static> Pallet { to: dest.clone(), amount, }); - return Ok(amount) + return Ok((amount, None)) } // Figure out the debit and credit, together with side-effects. @@ -524,6 +546,7 @@ impl, I: 'static> Pallet { let mut source_account = Account::::get(id, &source).ok_or(Error::::NoAccount)?; + let mut source_died: Option = None; Asset::::try_mutate(id, |maybe_details| -> DispatchResult { let details = maybe_details.as_mut().ok_or(Error::::Unknown)?; @@ -576,9 +599,9 @@ impl, I: 'static> Pallet { // Remove source account if it's now dead. if source_account.balance < details.min_balance { debug_assert!(source_account.balance.is_zero(), "checked in prep; qed"); - if let Remove = - Self::dead_account(id, &source, details, &source_account.reason, false) - { + source_died = + Some(Self::dead_account(&source, details, &source_account.reason, false)); + if let Some(Remove) = source_died { Account::::remove(id, &source); return Ok(()) } @@ -593,7 +616,7 @@ impl, I: 'static> Pallet { to: dest.clone(), amount: credit, }); - Ok(credit) + Ok((credit, source_died)) } /// Create a new asset without taking a deposit. @@ -646,41 +669,53 @@ impl, I: 'static> Pallet { witness: DestroyWitness, maybe_check_owner: Option, ) -> Result { - Asset::::try_mutate_exists(id, |maybe_details| { - let mut details = maybe_details.take().ok_or(Error::::Unknown)?; - if let Some(check_owner) = maybe_check_owner { - ensure!(details.owner == check_owner, Error::::NoPermission); - } - ensure!(details.accounts <= witness.accounts, Error::::BadWitness); - ensure!(details.sufficients <= witness.sufficients, Error::::BadWitness); - ensure!(details.approvals <= witness.approvals, Error::::BadWitness); - - for (who, v) in Account::::drain_prefix(id) { - // We have to force this as it's destroying the entire asset class. - // This could mean that some accounts now have irreversibly reserved - // funds. - let _ = Self::dead_account(id, &who, &mut details, &v.reason, true); - } - debug_assert_eq!(details.accounts, 0); - debug_assert_eq!(details.sufficients, 0); + let mut dead_accounts: Vec = vec![]; - let metadata = Metadata::::take(&id); - T::Currency::unreserve( - &details.owner, - details.deposit.saturating_add(metadata.deposit), - ); + let result_witness: DestroyWitness = Asset::::try_mutate_exists( + id, + |maybe_details| -> Result { + let mut details = maybe_details.take().ok_or(Error::::Unknown)?; + if let Some(check_owner) = maybe_check_owner { + ensure!(details.owner == check_owner, Error::::NoPermission); + } + ensure!(details.accounts <= witness.accounts, Error::::BadWitness); + ensure!(details.sufficients <= witness.sufficients, Error::::BadWitness); + ensure!(details.approvals <= witness.approvals, Error::::BadWitness); + + for (who, v) in Account::::drain_prefix(id) { + // We have to force this as it's destroying the entire asset class. + // This could mean that some accounts now have irreversibly reserved + // funds. + let _ = Self::dead_account(&who, &mut details, &v.reason, true); + dead_accounts.push(who); + } + debug_assert_eq!(details.accounts, 0); + debug_assert_eq!(details.sufficients, 0); - for ((owner, _), approval) in Approvals::::drain_prefix((&id,)) { - T::Currency::unreserve(&owner, approval.deposit); - } - Self::deposit_event(Event::Destroyed { asset_id: id }); + let metadata = Metadata::::take(&id); + T::Currency::unreserve( + &details.owner, + details.deposit.saturating_add(metadata.deposit), + ); - Ok(DestroyWitness { - accounts: details.accounts, - sufficients: details.sufficients, - approvals: details.approvals, - }) - }) + for ((owner, _), approval) in Approvals::::drain_prefix((&id,)) { + T::Currency::unreserve(&owner, approval.deposit); + } + Self::deposit_event(Event::Destroyed { asset_id: id }); + + Ok(DestroyWitness { + accounts: details.accounts, + sufficients: details.sufficients, + approvals: details.approvals, + }) + }, + )?; + + // Execute hooks outside of `mutate`. + for who in dead_accounts { + T::Freezer::died(id, &who); + } + Ok(result_witness) } /// Creates an approval from `owner` to spend `amount` of asset `id` tokens by 'delegate' @@ -742,6 +777,8 @@ impl, I: 'static> Pallet { destination: &T::AccountId, amount: T::Balance, ) -> DispatchResult { + let mut owner_died: Option = None; + Approvals::::try_mutate_exists( (id, &owner, delegate), |maybe_approved| -> DispatchResult { @@ -750,7 +787,7 @@ impl, I: 'static> Pallet { approved.amount.checked_sub(&amount).ok_or(Error::::Unapproved)?; let f = TransferFlags { keep_alive: false, best_effort: false, burn_dust: false }; - Self::do_transfer(id, &owner, &destination, amount, None, f)?; + owner_died = Self::transfer_and_die(id, &owner, &destination, amount, None, f)?.1; if remaining.is_zero() { T::Currency::unreserve(&owner, approved.deposit); @@ -766,6 +803,11 @@ impl, I: 'static> Pallet { Ok(()) }, )?; + + // Execute hook outside of `mutate`. + if let Some(Remove) = owner_died { + T::Freezer::died(id, owner); + } Ok(()) } diff --git a/frame/assets/src/mock.rs b/frame/assets/src/mock.rs index 34a4cf9ef38f..67690e2b28ec 100644 --- a/frame/assets/src/mock.rs +++ b/frame/assets/src/mock.rs @@ -120,19 +120,27 @@ impl FrozenBalance for TestFreezer { fn died(asset: u32, who: &u64) { HOOKS.with(|h| h.borrow_mut().push(Hook::Died(asset, who.clone()))); + // Sanity check: dead accounts have no balance. + assert!(Assets::balance(asset, *who).is_zero()); } } pub(crate) fn set_frozen_balance(asset: u32, who: u64, amount: u64) { FROZEN.with(|f| f.borrow_mut().insert((asset, who), amount)); } + pub(crate) fn clear_frozen_balance(asset: u32, who: u64) { FROZEN.with(|f| f.borrow_mut().remove(&(asset, who))); } + pub(crate) fn hooks() -> Vec { HOOKS.with(|h| h.borrow().clone()) } +pub(crate) fn take_hooks() -> Vec { + HOOKS.with(|h| h.take()) +} + pub(crate) fn new_test_ext() -> sp_io::TestExternalities { let mut storage = frame_system::GenesisConfig::default().build_storage::().unwrap(); @@ -154,6 +162,8 @@ pub(crate) fn new_test_ext() -> sp_io::TestExternalities { config.assimilate_storage(&mut storage).unwrap(); let mut ext: sp_io::TestExternalities = storage.into(); + // Clear thread local vars for https://github.com/paritytech/substrate/issues/10479. + ext.execute_with(|| take_hooks()); ext.execute_with(|| System::set_block_number(1)); ext } diff --git a/frame/assets/src/tests.rs b/frame/assets/src/tests.rs index a9f4dafc910c..7430b742e7d2 100644 --- a/frame/assets/src/tests.rs +++ b/frame/assets/src/tests.rs @@ -125,6 +125,21 @@ fn refunding_asset_deposit_without_burn_should_work() { }); } +/// Refunding reaps an account and calls the `FrozenBalance::died` hook. +#[test] +fn refunding_calls_died_hook() { + new_test_ext().execute_with(|| { + assert_ok!(Assets::force_create(Origin::root(), 0, 1, false, 1)); + Balances::make_free_balance_be(&1, 100); + assert_ok!(Assets::touch(Origin::signed(1), 0)); + assert_ok!(Assets::mint(Origin::signed(1), 0, 1, 100)); + assert_ok!(Assets::refund(Origin::signed(1), 0, true)); + + assert_eq!(Asset::::get(0).unwrap().accounts, 0); + assert_eq!(hooks(), vec![Hook::Died(0, 1)]); + }); +} + #[test] fn approval_lifecycle_works() { new_test_ext().execute_with(|| { @@ -389,19 +404,32 @@ fn min_balance_should_work() { ); // When deducting from an account to below minimum, it should be reaped. + // Death by `transfer`. assert_ok!(Assets::transfer(Origin::signed(1), 0, 2, 91)); assert!(Assets::maybe_balance(0, 1).is_none()); assert_eq!(Assets::balance(0, 2), 100); assert_eq!(Asset::::get(0).unwrap().accounts, 1); + assert_eq!(take_hooks(), vec![Hook::Died(0, 1)]); + // Death by `force_transfer`. assert_ok!(Assets::force_transfer(Origin::signed(1), 0, 2, 1, 91)); assert!(Assets::maybe_balance(0, 2).is_none()); assert_eq!(Assets::balance(0, 1), 100); assert_eq!(Asset::::get(0).unwrap().accounts, 1); + assert_eq!(take_hooks(), vec![Hook::Died(0, 2)]); + // Death by `burn`. assert_ok!(Assets::burn(Origin::signed(1), 0, 1, 91)); assert!(Assets::maybe_balance(0, 1).is_none()); assert_eq!(Asset::::get(0).unwrap().accounts, 0); + assert_eq!(take_hooks(), vec![Hook::Died(0, 1)]); + + // Death by `transfer_approved`. + assert_ok!(Assets::mint(Origin::signed(1), 0, 1, 100)); + Balances::make_free_balance_be(&1, 1); + assert_ok!(Assets::approve_transfer(Origin::signed(1), 0, 2, 100)); + assert_ok!(Assets::transfer_approved(Origin::signed(2), 0, 1, 3, 91)); + assert_eq!(take_hooks(), vec![Hook::Died(0, 1)]); }); } @@ -448,6 +476,7 @@ fn transferring_enough_to_kill_source_when_keep_alive_should_fail() { assert_ok!(Assets::transfer_keep_alive(Origin::signed(1), 0, 2, 90)); assert_eq!(Assets::balance(0, 1), 10); assert_eq!(Assets::balance(0, 2), 90); + assert!(hooks().is_empty()); }); } @@ -684,6 +713,24 @@ fn set_metadata_should_work() { }); } +/// Destroying an asset calls the `FrozenBalance::died` hooks of all accounts. +#[test] +fn destroy_calls_died_hooks() { + new_test_ext().execute_with(|| { + assert_ok!(Assets::force_create(Origin::root(), 0, 1, true, 50)); + // Create account 1 and 2. + assert_ok!(Assets::mint(Origin::signed(1), 0, 1, 100)); + assert_ok!(Assets::mint(Origin::signed(1), 0, 2, 100)); + // Destroy the asset. + let w = Asset::::get(0).unwrap().destroy_witness(); + assert_ok!(Assets::destroy(Origin::signed(1), 0, w)); + + // Asset is gone and accounts 1 and 2 died. + assert!(Asset::::get(0).is_none()); + assert_eq!(hooks(), vec![Hook::Died(0, 1), Hook::Died(0, 2)]); + }) +} + #[test] fn freezer_should_work() { new_test_ext().execute_with(|| { diff --git a/frame/assets/src/types.rs b/frame/assets/src/types.rs index f8172e0a4a51..56034e59086b 100644 --- a/frame/assets/src/types.rs +++ b/frame/assets/src/types.rs @@ -172,13 +172,9 @@ pub trait FrozenBalance { /// If `None` is returned, then nothing special is enforced. fn frozen_balance(asset: AssetId, who: &AccountId) -> Option; - /// Called when an account has been removed. + /// Called after an account has been removed. /// - /// # Warning - /// - /// This function must never access storage of pallet asset. This function is called while some - /// change are pending. Calling into the pallet asset in this function can result in unexpected - /// state. + /// NOTE: It is possible that the asset does no longer exist when this hook is called. fn died(asset: AssetId, who: &AccountId); } From 22ed351d86b3b04ca1df82fb0036c6376bf1fea0 Mon Sep 17 00:00:00 2001 From: Tarekk Mohamed Abdalla Date: Fri, 11 Feb 2022 16:38:58 +0200 Subject: [PATCH 483/695] allow trailing comma (#10841) --- primitives/std/src/lib.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/primitives/std/src/lib.rs b/primitives/std/src/lib.rs index 6a59dcbe4929..03a079e3965f 100644 --- a/primitives/std/src/lib.rs +++ b/primitives/std/src/lib.rs @@ -28,9 +28,13 @@ doc = "Substrate's runtime standard library as compiled without Rust's standard library." )] +/// Initialize a key-value collection from array. +/// +/// Creates a vector of given pairs and calls `collect` on the iterator from it. +/// Can be used to create a `HashMap`. #[macro_export] macro_rules! map { - ($( $name:expr => $value:expr ),*) => ( + ($( $name:expr => $value:expr ),* $(,)? ) => ( vec![ $( ( $name, $value ) ),* ].into_iter().collect() ) } From 66b9c363c617d04ef3fba32d06419eb2bbe3c874 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Silva?= <123550+andresilva@users.noreply.github.com> Date: Fri, 11 Feb 2022 19:38:39 +0000 Subject: [PATCH 484/695] build-script-utils: allow reading the git commit hash from env var (#10845) * build-script-utils: allow reading the git commit hash from env var * build-script-utils: make the env var name substrate specific --- utils/build-script-utils/src/version.rs | 32 +++++++++++++------------ 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/utils/build-script-utils/src/version.rs b/utils/build-script-utils/src/version.rs index e4f1be93cbcc..773949e30d8d 100644 --- a/utils/build-script-utils/src/version.rs +++ b/utils/build-script-utils/src/version.rs @@ -20,21 +20,23 @@ use std::{borrow::Cow, process::Command}; /// Generate the `cargo:` key output pub fn generate_cargo_keys() { - let output = Command::new("git").args(&["rev-parse", "--short", "HEAD"]).output(); - - let commit = match output { - Ok(o) if o.status.success() => { - let sha = String::from_utf8_lossy(&o.stdout).trim().to_owned(); - Cow::from(sha) - }, - Ok(o) => { - println!("cargo:warning=Git command failed with status: {}", o.status); - Cow::from("unknown") - }, - Err(err) => { - println!("cargo:warning=Failed to execute git command: {}", err); - Cow::from("unknown") - }, + let commit = if let Ok(hash) = std::env::var("SUBSTRATE_CLI_GIT_COMMIT_HASH") { + Cow::from(hash.trim().to_owned()) + } else { + match Command::new("git").args(&["rev-parse", "--short", "HEAD"]).output() { + Ok(o) if o.status.success() => { + let sha = String::from_utf8_lossy(&o.stdout).trim().to_owned(); + Cow::from(sha) + }, + Ok(o) => { + println!("cargo:warning=Git command failed with status: {}", o.status); + Cow::from("unknown") + }, + Err(err) => { + println!("cargo:warning=Failed to execute git command: {}", err); + Cow::from("unknown") + }, + } }; println!("cargo:rustc-env=SUBSTRATE_CLI_IMPL_VERSION={}", get_version(&commit)) From 0a92e3eeb6568cee34bcccdf34529f77db767c46 Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Fri, 11 Feb 2022 22:28:10 +0100 Subject: [PATCH 485/695] Don't create DB leaves when syncing historic blocks (#10844) * Don't create DB leaves when syncing historic blocks * Changed leaves check and added test * fmt --- client/db/src/lib.rs | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/client/db/src/lib.rs b/client/db/src/lib.rs index d7550ff9aea1..a2d0cad72845 100644 --- a/client/db/src/lib.rs +++ b/client/db/src/lib.rs @@ -1472,7 +1472,8 @@ impl Backend { } if !existing_header { - { + // Add a new leaf if the block has the potential to be finalized. + if number > last_finalized_num || last_finalized_num.is_zero() { let mut leaves = self.blockchain.leaves.write(); leaves.import(hash, number, parent_hash); leaves.prepare_transaction( @@ -2330,6 +2331,29 @@ pub(crate) mod tests { Ok(header_hash) } + pub fn insert_header_no_head( + backend: &Backend, + number: u64, + parent_hash: H256, + extrinsics_root: H256, + ) -> H256 { + use sp_runtime::testing::Digest; + + let digest = Digest::default(); + let header = Header { + number, + parent_hash, + state_root: BlakeTwo256::trie_root(Vec::new(), StateVersion::V1), + digest, + extrinsics_root, + }; + let header_hash = header.hash(); + let mut op = backend.begin_operation().unwrap(); + op.set_block_data(header, None, None, None, NewBlockState::Normal).unwrap(); + backend.commit_operation(op).unwrap(); + header_hash + } + #[test] fn block_hash_inserted_correctly() { let backing = { @@ -3309,4 +3333,19 @@ pub(crate) mod tests { e @ _ => panic!("Unexpected error {:?}", e), } } + + #[test] + fn test_leaves_not_created_for_ancient_blocks() { + let backend: Backend = Backend::new_test(10, 10); + let block0 = insert_header(&backend, 0, Default::default(), None, Default::default()); + + let block1_a = insert_header(&backend, 1, block0, None, Default::default()); + let block2_a = insert_header(&backend, 2, block1_a, None, Default::default()); + backend.finalize_block(BlockId::hash(block1_a), None).unwrap(); + assert_eq!(backend.blockchain().leaves().unwrap(), vec![block2_a]); + + // Insert a fork prior to finalization point. Leave should not be created. + insert_header_no_head(&backend, 1, block0, [1; 32].into()); + assert_eq!(backend.blockchain().leaves().unwrap(), vec![block2_a]); + } } From aff6731845c8b44f1d00ef1cf8e8589b332e08ed Mon Sep 17 00:00:00 2001 From: driemworks Date: Fri, 11 Feb 2022 19:43:42 -0500 Subject: [PATCH 486/695] cleanup, use unsigned tx when appropriate --- .../pallets/iris-assets/src/lib.rs | 21 +--- .../pallets/iris-session/src/lib.rs | 106 +++++++++++------- bin/node-template/runtime/src/lib.rs | 4 +- 3 files changed, 67 insertions(+), 64 deletions(-) diff --git a/bin/node-template/pallets/iris-assets/src/lib.rs b/bin/node-template/pallets/iris-assets/src/lib.rs index 26ea1e847373..7553149c6cec 100644 --- a/bin/node-template/pallets/iris-assets/src/lib.rs +++ b/bin/node-template/pallets/iris-assets/src/lib.rs @@ -25,33 +25,17 @@ use frame_support::{ }; use frame_system::{ self as system, ensure_signed, - offchain::{ - SendSignedTransaction, - Signer, - }, }; -use sp_core::{ - offchain::{ - Duration, IpfsRequest, IpfsResponse, OpaqueMultiaddr, Timestamp, StorageKind, - }, - crypto::KeyTypeId, - Bytes, -}; +use sp_core::offchain::OpaqueMultiaddr; -use sp_io::offchain::timestamp; use sp_runtime::{ - offchain::{ - ipfs, - }, RuntimeDebug, traits::StaticLookup, }; use sp_std::{ - str, vec::Vec, prelude::*, - convert::TryInto, }; #[derive(Encode, Decode, RuntimeDebug, PartialEq, TypeInfo)] @@ -336,6 +320,7 @@ pub mod pallet { #[pallet::weight(0)] pub fn insert_pin_request( origin: OriginFor, + acct: T::AccountId, asset_owner: T::AccountId, asset_id: T::AssetId, ) -> DispatchResult { @@ -347,7 +332,7 @@ pub mod pallet { ); >::mutate( |queue| queue.push(DataCommand::PinCID( - who.clone(), + acct.clone(), asset_id.clone(), cid.clone(), ))); diff --git a/bin/node-template/pallets/iris-session/src/lib.rs b/bin/node-template/pallets/iris-session/src/lib.rs index 333ed118fb1e..f44109329d7c 100644 --- a/bin/node-template/pallets/iris-session/src/lib.rs +++ b/bin/node-template/pallets/iris-session/src/lib.rs @@ -46,7 +46,6 @@ use sp_runtime::traits::{Convert, Zero}; use sp_staking::offence::{Offence, OffenceError, ReportOffence}; use sp_std::{ collections::{ btree_set::BTreeSet, btree_map::BTreeMap }, - convert::TryInto, str, vec::Vec, prelude::* @@ -64,6 +63,7 @@ use frame_system::{ offchain::{ SendSignedTransaction, Signer, + SubmitTransaction, } }; use sp_io::offchain::timestamp; @@ -286,6 +286,24 @@ pub mod pallet { RequestJoinStoragePoolSuccess(T::AccountId, T::AssetId), } + + #[pallet::validate_unsigned] + impl ValidateUnsigned for Pallet { + type Call = Call; + + /// Validate unsigned call to this module. + /// + fn validate_unsigned(_source: TransactionSource, call: &Self::Call) -> TransactionValidity { + if let Call::submit_rpc_ready { asset_id } = call { + Self::validate_transaction_parameters() + } else if let Call::submit_ipfs_identity{ public_key, multiaddresses } = call { + Self::validate_transaction_parameters() + } else { + InvalidTransaction::Call.into() + } + } + } + // Errors inform users that something went wrong. #[pallet::error] pub enum Error { @@ -425,7 +443,7 @@ pub mod pallet { sp.push(who.clone()); }); let owner = T::Lookup::lookup(pool_owner)?; - >::insert_pin_request(new_origin, owner, pool_id)?; + >::insert_pin_request(new_origin, who.clone(), owner, pool_id)?; Self::deposit_event(Event::RequestJoinStoragePoolSuccess(who.clone(), pool_id.clone())); Ok(()) } @@ -449,8 +467,8 @@ pub mod pallet { id: T::AssetId, balance: T::Balance, ) -> DispatchResult { + // TODO: explore consequences of changing to ensure_root let who = ensure_signed(origin)?; - // TODO: Need some type of verification to prove the caller pinned the content let new_origin = system::RawOrigin::Signed(who.clone()).into(); // creates the asset class >::submit_ipfs_add_results( @@ -460,15 +478,17 @@ pub mod pallet { id, balance, )?; - // award point to self + // award point to all validators if let Some(active_era) = ActiveEra::::get() { >::mutate(active_era.clone(), id, |era_rewards| { - // increment total session rewards (used to find non-contributing validators) - SessionParticipation::::mutate(active_era.clone(), |participants| { - participants.push(who.clone()); - }); - *era_rewards.individual.entry(who.clone()).or_default() += 1; - era_rewards.total += 1; + // reward all validators + for v in >::get() { + SessionParticipation::::mutate(active_era.clone(), |participants| { + participants.push(v.clone()); + }); + *era_rewards.individual.entry(v.clone()).or_default() += 1; + era_rewards.total += 1; + } }); } else { // error @@ -496,29 +516,35 @@ pub mod pallet { Ok(()) } + /// should only be callable by validator nodes (TODO) + /// + /// * `asset_id`: The asset id corresponding to the data that was pinned + /// * `pinner': The node claiming to have pinned the data + /// #[pallet::weight(0)] pub fn submit_ipfs_pin_result( origin: OriginFor, asset_id: T::AssetId, + pinner: T::AccountId, ) -> DispatchResult { let who = ensure_signed(origin)?; // verify they are a candidate storage provider let candidate_storage_providers = >::get(asset_id.clone()); - ensure!(candidate_storage_providers.contains(&who), Error::::NotACandidate); + ensure!(candidate_storage_providers.contains(&pinner), Error::::NotACandidate); // verify not already pinning the content let current_pinners = >::get(asset_id.clone()); - ensure!(!current_pinners.contains(&who), Error::::AlreadyPinned); + ensure!(!current_pinners.contains(&pinner), Error::::AlreadyPinned); // TODO: we need a better scheme for *generating* pool ids -> should always be unique (cid + owner maybe?) >::mutate(asset_id.clone(), |p| { - p.push(who.clone()); + p.push(pinner.clone()); }); - // award point to self + // award point to pinner if let Some(active_era) = ActiveEra::::get() { SessionParticipation::::mutate(active_era.clone(), |p| { - p.push(who.clone()); + p.push(pinner.clone()); }); >::mutate(active_era, asset_id, |era_rewards| { - *era_rewards.individual.entry(who.clone()).or_default() += 1; + *era_rewards.individual.entry(pinner.clone()).or_default() += 1; era_rewards.total += 1; }); } @@ -536,7 +562,7 @@ pub mod pallet { origin: OriginFor, asset_id: T::AssetId, ) -> DispatchResult { - ensure_signed(origin)?; + // ensure_signed(origin)?; if let Some(active_era) = ActiveEra::::get() { >::mutate(active_era.clone(), asset_id.clone(), |era_rewards| { // reward all active storage providers @@ -558,6 +584,7 @@ pub mod pallet { } impl Pallet { + fn initialize_validators(validators: &[T::AccountId]) { assert!(validators.len() > 1, "At least 2 validators should be initialized"); assert!(>::get().is_empty(), "Validators are already initialized!"); @@ -653,7 +680,8 @@ impl Pallet { let pinners = >::get(assetid.clone()); let pinner_candidate_intersection = candidates.into_iter().filter(|c| pinners.contains(c)).collect::>(); - // need to only move candidates that have actually proved they pinned the content + log::info!("Adding {:?} more storage providers", pinner_candidate_intersection.len()); + // need to only move candidates that have actually proved they pinned the content >::insert(assetid.clone(), pinner_candidate_intersection); } } @@ -675,6 +703,13 @@ impl Pallet { } } + fn validate_transaction_parameters() -> TransactionValidity { + ValidTransaction::with_tag_prefix("rpc_ready") + .longevity(5) + .propagate(true) + .build() + } + /// implementation for RPC runtime API to retrieve bytes from the node's local storage /// /// * public_key: The account's public key as bytes @@ -748,6 +783,7 @@ impl Pallet { } } } + let signer = Signer::::all_accounts(); if !signer.can_sign() { log::error!( @@ -768,10 +804,8 @@ impl Pallet { Err(e) => log::error!("Failed to submit transaction: {:?}", e), } } - } Ok(()) - } /// process any requests in the DataQueue @@ -840,10 +874,10 @@ impl Pallet { }, DataCommand::CatBytes(requestor, owner, asset_id) => { // fetch ipfs id - let (public_key, addrs) = + let public_key = if let IpfsResponse::Identity(public_key, addrs) = Self::ipfs_request(IpfsRequest::Identity, deadline)? { - (public_key, addrs) + public_key } else { unreachable!("only `Identity` is a valid response type."); }; @@ -867,26 +901,11 @@ impl Pallet { &cid, &data, ); - - let signer = Signer::::all_accounts(); - if !signer.can_sign() { - log::error!( - "No local accounts available. Consider adding one via `author_insertKey` RPC.", - ); - } - let results = signer.send_signed_transaction(|_account| { - Call::submit_rpc_ready { - // beneficiary: requestor.clone(), - asset_id: asset_id.clone(), - } - }); - - for (_, res) in &results { - match res { - Ok(()) => log::info!("Submitted ipfs results"), - Err(e) => log::error!("Failed to submit transaction: {:?}", e), - } - } + let call = Call::submit_rpc_ready { + asset_id: asset_id.clone(), + }; + SubmitTransaction::>::submit_unsigned_transaction(call.into()) + .map_err(|()| Error::::CantCreateRequest)?; }, Ok(_) => unreachable!("only CatBytes can be a response for that request type."), Err(e) => log::error!("IPFS: cat error: {:?}", e), @@ -904,7 +923,7 @@ impl Pallet { } else { unreachable!("only `Identity` is a valid response type."); }; - let expected_pub_key = >::get(acct); + let expected_pub_key = >::get(acct.clone()); // todo: create new error enum if this is the route i choose ensure!(public_key == expected_pub_key, Error::::BadOrigin); match Self::ipfs_request(IpfsRequest::InsertPin(cid.clone(), false), deadline) { @@ -919,6 +938,7 @@ impl Pallet { let results = signer.send_signed_transaction(|_account| { Call::submit_ipfs_pin_result{ asset_id: asset_id, + pinner: acct.clone(), } }); diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index 55f2c93c7c67..4f8fb817367d 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -452,12 +452,10 @@ construct_runtime!( TransactionPayment: pallet_transaction_payment::{Pallet, Storage}, Sudo: pallet_sudo::{Pallet, Call, Config, Storage, Event}, Iris: pallet_iris_assets::{Pallet, Call, Storage, Event}, - IrisSession: pallet_iris_session::{Pallet, Call, Storage, Event, Config}, + IrisSession: pallet_iris_session::{Pallet, Call, Storage, Event, Config, ValidateUnsigned}, Session: pallet_session::{Pallet, Call, Storage, Event, Config}, Assets: pallet_assets::{Pallet, Storage, Event}, ImOnline: pallet_im_online::{Pallet, Call, Storage, Event, ValidateUnsigned, Config}, - // Offences: pallet_offences::{Pallet, Storage, Event}, - // Historical: pallet_session_historical::{Pallet}, Aura: pallet_aura::{Pallet, Config}, Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event}, } From 8ad1f3bf663d63cd0393ce10c7295399d785574d Mon Sep 17 00:00:00 2001 From: driemworks Date: Sat, 12 Feb 2022 12:13:40 -0500 Subject: [PATCH 487/695] add weights --- bin/node-template/pallets/iris-assets/src/lib.rs | 10 +++++----- .../pallets/iris-session/src/lib.rs | 16 ++++++++-------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/bin/node-template/pallets/iris-assets/src/lib.rs b/bin/node-template/pallets/iris-assets/src/lib.rs index 7553149c6cec..3401e094a1a6 100644 --- a/bin/node-template/pallets/iris-assets/src/lib.rs +++ b/bin/node-template/pallets/iris-assets/src/lib.rs @@ -206,7 +206,7 @@ pub mod pallet { /// * `id`: (temp) the unique id of the asset class -> should be generated instead /// * `balance`: the balance the owner is willing to use to back the asset class which will be created /// - #[pallet::weight(0)] + #[pallet::weight(100)] pub fn create( origin: OriginFor, admin: ::Source, @@ -239,7 +239,7 @@ pub mod pallet { /// * cid: a cid owned by the origin, for which an asset class exists /// * amount: the number of tickets to mint /// - #[pallet::weight(0)] + #[pallet::weight(100)] pub fn mint( origin: OriginFor, beneficiary: ::Source, @@ -264,7 +264,7 @@ pub mod pallet { /// * `owner`: The owner of the content to be fetched /// * `asset_id`: The asset id identifying the content /// - #[pallet::weight(0)] + #[pallet::weight(100)] pub fn request_bytes( origin: OriginFor, owner: ::Source, @@ -289,7 +289,7 @@ pub mod pallet { /// * `id`: The AssetId (passed through from the create_storage_asset call) /// * `balance`: The balance (passed through from the create_storage_asset call) /// - #[pallet::weight(0)] + #[pallet::weight(100)] pub fn submit_ipfs_add_results( origin: OriginFor, admin: ::Source, @@ -317,7 +317,7 @@ pub mod pallet { /// * asset_owner: The owner of the asset class /// * asset_id: The asset id of some asset class /// - #[pallet::weight(0)] + #[pallet::weight(100)] pub fn insert_pin_request( origin: OriginFor, acct: T::AccountId, diff --git a/bin/node-template/pallets/iris-session/src/lib.rs b/bin/node-template/pallets/iris-session/src/lib.rs index f44109329d7c..88de4f5f396f 100644 --- a/bin/node-template/pallets/iris-session/src/lib.rs +++ b/bin/node-template/pallets/iris-session/src/lib.rs @@ -385,7 +385,7 @@ pub mod pallet { /// The origin can be configured using the `AddRemoveOrigin` type in the /// host runtime. Can also be set to sudo/root. /// - #[pallet::weight(0)] + #[pallet::weight(100)] pub fn add_validator(origin: OriginFor, validator_id: T::AccountId) -> DispatchResult { T::AddRemoveOrigin::ensure_origin(origin)?; Self::do_add_validator(validator_id.clone())?; @@ -397,7 +397,7 @@ pub mod pallet { /// /// The origin can be configured using the `AddRemoveOrigin` type in the /// host runtime. Can also be set to sudo/root. - #[pallet::weight(0)] + #[pallet::weight(100)] pub fn remove_validator( origin: OriginFor, validator_id: T::AccountId, @@ -411,7 +411,7 @@ pub mod pallet { /// Add an approved validator again when it comes back online. /// /// For this call, the dispatch origin must be the validator itself. - #[pallet::weight(0)] + #[pallet::weight(100)] pub fn add_validator_again( origin: OriginFor, validator_id: T::AccountId, @@ -427,7 +427,7 @@ pub mod pallet { Ok(()) } - #[pallet::weight(0)] + #[pallet::weight(100)] pub fn join_storage_pool( origin: OriginFor, pool_owner: ::Source, @@ -459,7 +459,7 @@ pub mod pallet { /// * `id`: The AssetId (passed through from the create_storage_asset call) /// * `balance`: The balance (passed through from the create_storage_asset call) /// - #[pallet::weight(0)] + #[pallet::weight(100)] pub fn submit_ipfs_add_results( origin: OriginFor, admin: ::Source, @@ -503,7 +503,7 @@ pub mod pallet { /// * public_key: The IPFS node's public key /// * multiaddresses: A vector of multiaddresses associate with the public key /// - #[pallet::weight(0)] + #[pallet::weight(100)] pub fn submit_ipfs_identity( origin: OriginFor, public_key: Vec, @@ -521,7 +521,7 @@ pub mod pallet { /// * `asset_id`: The asset id corresponding to the data that was pinned /// * `pinner': The node claiming to have pinned the data /// - #[pallet::weight(0)] + #[pallet::weight(100)] pub fn submit_ipfs_pin_result( origin: OriginFor, asset_id: T::AssetId, @@ -557,7 +557,7 @@ pub mod pallet { /// * `beneficiary`: The account that requested the data /// * `host`: The node's host where the data has been made available (RPC endpoint) /// - #[pallet::weight(0)] + #[pallet::weight(100)] pub fn submit_rpc_ready( origin: OriginFor, asset_id: T::AssetId, From 2d8b02af1852d51b7d6a15d6d98b41b76bac614a Mon Sep 17 00:00:00 2001 From: S E R A Y A Date: Sun, 13 Feb 2022 23:14:32 +0100 Subject: [PATCH 488/695] fix broken link (#10846) --- frame/uniques/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frame/uniques/README.md b/frame/uniques/README.md index b924e338452f..8d6859d55e23 100644 --- a/frame/uniques/README.md +++ b/frame/uniques/README.md @@ -73,6 +73,6 @@ and its associated variants for documentation on each function. * [`System`](https://docs.rs/frame-system/latest/frame_system/) * [`Support`](https://docs.rs/frame-support/latest/frame_support/) -* [`Assets`](https://docs.rs/pallet-assets/latest/pallet_assetss/) +* [`Assets`](https://docs.rs/pallet-assets/latest/pallet_assets/) License: Apache-2.0 From 700218cacb44521885ab59ea17f5e7d0d2b8d5af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Mon, 14 Feb 2022 20:31:52 +0100 Subject: [PATCH 489/695] subkey: Support `--version` cli command (#10853) * subkey: Support `--version` cli command * FMT :facepalm: --- bin/utils/subkey/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bin/utils/subkey/src/lib.rs b/bin/utils/subkey/src/lib.rs index 73698db0b7ea..3731d9f3ec75 100644 --- a/bin/utils/subkey/src/lib.rs +++ b/bin/utils/subkey/src/lib.rs @@ -26,7 +26,8 @@ use sc_cli::{ #[clap( name = "subkey", author = "Parity Team ", - about = "Utility for generating and restoring with Substrate keys" + about = "Utility for generating and restoring with Substrate keys", + version )] pub enum Subkey { /// Generate a random node libp2p key, save it to file or print it to stdout From 0ac1a00c54a65416ed44e4c779f1483e32355130 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Mon, 14 Feb 2022 21:12:25 +0100 Subject: [PATCH 490/695] Remove `u32_trait` (#10850) * Remove `u32_trait` This trait only existed because there wasn't any const generic support at time of creation. However, we now have support for it :) * FMT --- bin/node/runtime/src/lib.rs | 30 +- frame/collective/src/lib.rs | 35 +- frame/collective/src/tests.rs | 7 +- .../traits/tokens/imbalance/split_two_ways.rs | 15 +- primitives/core/src/lib.rs | 2 - primitives/core/src/u32_trait.rs | 570 ------------------ 6 files changed, 39 insertions(+), 620 deletions(-) delete mode 100644 primitives/core/src/u32_trait.rs diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 0a13b795919c..0aff3d8046ee 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -53,11 +53,7 @@ pub use pallet_transaction_payment::{CurrencyAdapter, Multiplier, TargetedFeeAdj use pallet_transaction_payment::{FeeDetails, RuntimeDispatchInfo}; use sp_api::impl_runtime_apis; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; -use sp_core::{ - crypto::KeyTypeId, - u32_trait::{_1, _2, _3, _4, _5}, - OpaqueMetadata, -}; +use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; use sp_inherents::{CheckInherentsResult, InherentData}; use sp_runtime::{ create_runtime_str, @@ -550,7 +546,7 @@ impl pallet_staking::Config for Runtime { /// A super-majority of the council can cancel the slash. type SlashCancelOrigin = EnsureOneOf< EnsureRoot, - pallet_collective::EnsureProportionAtLeast<_3, _4, AccountId, CouncilCollective>, + pallet_collective::EnsureProportionAtLeast, >; type SessionInterface = Self; type EraPayout = pallet_staking::ConvertCurve; @@ -796,30 +792,30 @@ impl pallet_democracy::Config for Runtime { type MinimumDeposit = MinimumDeposit; /// A straight majority of the council can decide what their next motion is. type ExternalOrigin = - pallet_collective::EnsureProportionAtLeast<_1, _2, AccountId, CouncilCollective>; + pallet_collective::EnsureProportionAtLeast; /// A super-majority can have the next scheduled referendum be a straight majority-carries vote. type ExternalMajorityOrigin = - pallet_collective::EnsureProportionAtLeast<_3, _4, AccountId, CouncilCollective>; + pallet_collective::EnsureProportionAtLeast; /// A unanimous council can have the next scheduled referendum be a straight default-carries /// (NTB) vote. type ExternalDefaultOrigin = - pallet_collective::EnsureProportionAtLeast<_1, _1, AccountId, CouncilCollective>; + pallet_collective::EnsureProportionAtLeast; /// Two thirds of the technical committee can have an ExternalMajority/ExternalDefault vote /// be tabled immediately and with a shorter voting/enactment period. type FastTrackOrigin = - pallet_collective::EnsureProportionAtLeast<_2, _3, AccountId, TechnicalCollective>; + pallet_collective::EnsureProportionAtLeast; type InstantOrigin = - pallet_collective::EnsureProportionAtLeast<_1, _1, AccountId, TechnicalCollective>; + pallet_collective::EnsureProportionAtLeast; type InstantAllowed = frame_support::traits::ConstBool; type FastTrackVotingPeriod = FastTrackVotingPeriod; // To cancel a proposal which has been passed, 2/3 of the council must agree to it. type CancellationOrigin = - pallet_collective::EnsureProportionAtLeast<_2, _3, AccountId, CouncilCollective>; + pallet_collective::EnsureProportionAtLeast; // To cancel a proposal before it has been passed, the technical committee must be unanimous or // Root must agree. type CancelProposalOrigin = EnsureOneOf< EnsureRoot, - pallet_collective::EnsureProportionAtLeast<_1, _1, AccountId, TechnicalCollective>, + pallet_collective::EnsureProportionAtLeast, >; type BlacklistOrigin = EnsureRoot; // Any single technical committee member may veto a coming council proposal, however they can @@ -909,7 +905,7 @@ impl pallet_collective::Config for Runtime { type EnsureRootOrHalfCouncil = EnsureOneOf< EnsureRoot, - pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>, + pallet_collective::EnsureProportionMoreThan, >; impl pallet_membership::Config for Runtime { type Event = Event; @@ -951,11 +947,11 @@ impl pallet_treasury::Config for Runtime { type Currency = Balances; type ApproveOrigin = EnsureOneOf< EnsureRoot, - pallet_collective::EnsureProportionAtLeast<_3, _5, AccountId, CouncilCollective>, + pallet_collective::EnsureProportionAtLeast, >; type RejectOrigin = EnsureOneOf< EnsureRoot, - pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>, + pallet_collective::EnsureProportionMoreThan, >; type Event = Event; type OnSlash = (); @@ -1226,7 +1222,7 @@ impl pallet_society::Config for Runtime { type RotationPeriod = RotationPeriod; type MaxLockDuration = MaxLockDuration; type FounderSetOrigin = - pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>; + pallet_collective::EnsureProportionMoreThan; type SuspensionJudgementOrigin = pallet_society::EnsureFounder; type MaxCandidateIntake = MaxCandidateIntake; type ChallengePeriod = ChallengePeriod; diff --git a/frame/collective/src/lib.rs b/frame/collective/src/lib.rs index 49328aa0bdc6..e876343ec33d 100644 --- a/frame/collective/src/lib.rs +++ b/frame/collective/src/lib.rs @@ -43,7 +43,6 @@ #![recursion_limit = "128"] use scale_info::TypeInfo; -use sp_core::u32_trait::Value as U32; use sp_io::storage; use sp_runtime::{traits::Hash, RuntimeDebug}; use sp_std::{marker::PhantomData, prelude::*, result}; @@ -1011,43 +1010,43 @@ impl< } } -pub struct EnsureMembers(PhantomData<(N, AccountId, I)>); +pub struct EnsureMembers(PhantomData<(AccountId, I)>); impl< O: Into, O>> + From>, - N: U32, AccountId, I, - > EnsureOrigin for EnsureMembers + const N: u32, + > EnsureOrigin for EnsureMembers { type Success = (MemberCount, MemberCount); fn try_origin(o: O) -> Result { o.into().and_then(|o| match o { - RawOrigin::Members(n, m) if n >= N::VALUE => Ok((n, m)), + RawOrigin::Members(n, m) if n >= N => Ok((n, m)), r => Err(O::from(r)), }) } #[cfg(feature = "runtime-benchmarks")] fn successful_origin() -> O { - O::from(RawOrigin::Members(N::VALUE, N::VALUE)) + O::from(RawOrigin::Members(N, N)) } } -pub struct EnsureProportionMoreThan( - PhantomData<(N, D, AccountId, I)>, +pub struct EnsureProportionMoreThan( + PhantomData<(AccountId, I)>, ); impl< O: Into, O>> + From>, - N: U32, - D: U32, AccountId, I, - > EnsureOrigin for EnsureProportionMoreThan + const N: u32, + const D: u32, + > EnsureOrigin for EnsureProportionMoreThan { type Success = (); fn try_origin(o: O) -> Result { o.into().and_then(|o| match o { - RawOrigin::Members(n, m) if n * D::VALUE > N::VALUE * m => Ok(()), + RawOrigin::Members(n, m) if n * D > N * m => Ok(()), r => Err(O::from(r)), }) } @@ -1058,21 +1057,21 @@ impl< } } -pub struct EnsureProportionAtLeast( - PhantomData<(N, D, AccountId, I)>, +pub struct EnsureProportionAtLeast( + PhantomData<(AccountId, I)>, ); impl< O: Into, O>> + From>, - N: U32, - D: U32, AccountId, I, - > EnsureOrigin for EnsureProportionAtLeast + const N: u32, + const D: u32, + > EnsureOrigin for EnsureProportionAtLeast { type Success = (); fn try_origin(o: O) -> Result { o.into().and_then(|o| match o { - RawOrigin::Members(n, m) if n * D::VALUE >= N::VALUE * m => Ok(()), + RawOrigin::Members(n, m) if n * D >= N * m => Ok(()), r => Err(O::from(r)), }) } diff --git a/frame/collective/src/tests.rs b/frame/collective/src/tests.rs index f77e52a9b6fe..a8abfb0c5235 100644 --- a/frame/collective/src/tests.rs +++ b/frame/collective/src/tests.rs @@ -24,10 +24,7 @@ use frame_support::{ Hashable, }; use frame_system::{EventRecord, Phase}; -use sp_core::{ - u32_trait::{_3, _4}, - H256, -}; +use sp_core::H256; use sp_runtime::{ testing::Header, traits::{BlakeTwo256, IdentityLookup}, @@ -142,7 +139,7 @@ impl Config for Test { } impl mock_democracy::Config for Test { type Event = Event; - type ExternalMajorityOrigin = EnsureProportionAtLeast<_3, _4, u64, Instance1>; + type ExternalMajorityOrigin = EnsureProportionAtLeast; } impl Config for Test { type Origin = Origin; diff --git a/frame/support/src/traits/tokens/imbalance/split_two_ways.rs b/frame/support/src/traits/tokens/imbalance/split_two_ways.rs index a5e42451d82e..b963895af0de 100644 --- a/frame/support/src/traits/tokens/imbalance/split_two_ways.rs +++ b/frame/support/src/traits/tokens/imbalance/split_two_ways.rs @@ -18,27 +18,26 @@ //! Means for splitting an imbalance into two and hanlding them differently. use super::super::imbalance::{Imbalance, OnUnbalanced}; -use sp_core::u32_trait::Value as U32; use sp_runtime::traits::Saturating; use sp_std::{marker::PhantomData, ops::Div}; /// Split an unbalanced amount two ways between a common divisor. -pub struct SplitTwoWays( - PhantomData<(Balance, Imbalance, Part1, Target1, Part2, Target2)>, +pub struct SplitTwoWays( + PhantomData<(Balance, Imbalance, Target1, Target2)>, ); impl< Balance: From + Saturating + Div, I: Imbalance, - Part1: U32, Target1: OnUnbalanced, - Part2: U32, Target2: OnUnbalanced, - > OnUnbalanced for SplitTwoWays + const PART1: u32, + const PART2: u32, + > OnUnbalanced for SplitTwoWays { fn on_nonzero_unbalanced(amount: I) { - let total: u32 = Part1::VALUE + Part2::VALUE; - let amount1 = amount.peek().saturating_mul(Part1::VALUE.into()) / total.into(); + let total: u32 = PART1 + PART2; + let amount1 = amount.peek().saturating_mul(PART1.into()) / total.into(); let (imb1, imb2) = amount.split(amount1); Target1::on_unbalanced(imb1); Target2::on_unbalanced(imb2); diff --git a/primitives/core/src/lib.rs b/primitives/core/src/lib.rs index c794752e9d3d..d21364d3f8fb 100644 --- a/primitives/core/src/lib.rs +++ b/primitives/core/src/lib.rs @@ -56,8 +56,6 @@ pub use hashing::{blake2_128, blake2_256, keccak_256, twox_128, twox_256, twox_6 pub mod crypto; pub mod hexdisplay; -pub mod u32_trait; - pub mod ecdsa; pub mod ed25519; pub mod hash; diff --git a/primitives/core/src/u32_trait.rs b/primitives/core/src/u32_trait.rs deleted file mode 100644 index ff1508040034..000000000000 --- a/primitives/core/src/u32_trait.rs +++ /dev/null @@ -1,570 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2017-2022 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. - -//! An u32 trait with "values" as impl'd types. - -/// A u32 value, wrapped in a trait because we don't yet have const generics. -pub trait Value { - /// The actual value represented by the impl'ing type. - const VALUE: u32; -} - -/// Type representing the value 0 for the `Value` trait. -pub struct _0; -impl Value for _0 { - const VALUE: u32 = 0; -} -/// Type representing the value 1 for the `Value` trait. -pub struct _1; -impl Value for _1 { - const VALUE: u32 = 1; -} -/// Type representing the value 2 for the `Value` trait. -pub struct _2; -impl Value for _2 { - const VALUE: u32 = 2; -} -/// Type representing the value 3 for the `Value` trait. -pub struct _3; -impl Value for _3 { - const VALUE: u32 = 3; -} -/// Type representing the value 4 for the `Value` trait. -pub struct _4; -impl Value for _4 { - const VALUE: u32 = 4; -} -/// Type representing the value 5 for the `Value` trait. -pub struct _5; -impl Value for _5 { - const VALUE: u32 = 5; -} -/// Type representing the value 6 for the `Value` trait. -pub struct _6; -impl Value for _6 { - const VALUE: u32 = 6; -} -/// Type representing the value 7 for the `Value` trait. -pub struct _7; -impl Value for _7 { - const VALUE: u32 = 7; -} -/// Type representing the value 8 for the `Value` trait. -pub struct _8; -impl Value for _8 { - const VALUE: u32 = 8; -} -/// Type representing the value 9 for the `Value` trait. -pub struct _9; -impl Value for _9 { - const VALUE: u32 = 9; -} -/// Type representing the value 10 for the `Value` trait. -pub struct _10; -impl Value for _10 { - const VALUE: u32 = 10; -} -/// Type representing the value 11 for the `Value` trait. -pub struct _11; -impl Value for _11 { - const VALUE: u32 = 11; -} -/// Type representing the value 12 for the `Value` trait. -pub struct _12; -impl Value for _12 { - const VALUE: u32 = 12; -} -/// Type representing the value 13 for the `Value` trait. -pub struct _13; -impl Value for _13 { - const VALUE: u32 = 13; -} -/// Type representing the value 14 for the `Value` trait. -pub struct _14; -impl Value for _14 { - const VALUE: u32 = 14; -} -/// Type representing the value 15 for the `Value` trait. -pub struct _15; -impl Value for _15 { - const VALUE: u32 = 15; -} -/// Type representing the value 16 for the `Value` trait. -pub struct _16; -impl Value for _16 { - const VALUE: u32 = 16; -} -/// Type representing the value 17 for the `Value` trait. -pub struct _17; -impl Value for _17 { - const VALUE: u32 = 17; -} -/// Type representing the value 18 for the `Value` trait. -pub struct _18; -impl Value for _18 { - const VALUE: u32 = 18; -} -/// Type representing the value 19 for the `Value` trait. -pub struct _19; -impl Value for _19 { - const VALUE: u32 = 19; -} -/// Type representing the value 20 for the `Value` trait. -pub struct _20; -impl Value for _20 { - const VALUE: u32 = 20; -} -/// Type representing the value 21 for the `Value` trait. -pub struct _21; -impl Value for _21 { - const VALUE: u32 = 21; -} -/// Type representing the value 22 for the `Value` trait. -pub struct _22; -impl Value for _22 { - const VALUE: u32 = 22; -} -/// Type representing the value 23 for the `Value` trait. -pub struct _23; -impl Value for _23 { - const VALUE: u32 = 23; -} -/// Type representing the value 24 for the `Value` trait. -pub struct _24; -impl Value for _24 { - const VALUE: u32 = 24; -} -/// Type representing the value 25 for the `Value` trait. -pub struct _25; -impl Value for _25 { - const VALUE: u32 = 25; -} -/// Type representing the value 26 for the `Value` trait. -pub struct _26; -impl Value for _26 { - const VALUE: u32 = 26; -} -/// Type representing the value 27 for the `Value` trait. -pub struct _27; -impl Value for _27 { - const VALUE: u32 = 27; -} -/// Type representing the value 28 for the `Value` trait. -pub struct _28; -impl Value for _28 { - const VALUE: u32 = 28; -} -/// Type representing the value 29 for the `Value` trait. -pub struct _29; -impl Value for _29 { - const VALUE: u32 = 29; -} -/// Type representing the value 30 for the `Value` trait. -pub struct _30; -impl Value for _30 { - const VALUE: u32 = 30; -} -/// Type representing the value 31 for the `Value` trait. -pub struct _31; -impl Value for _31 { - const VALUE: u32 = 31; -} -/// Type representing the value 32 for the `Value` trait. -pub struct _32; -impl Value for _32 { - const VALUE: u32 = 32; -} -/// Type representing the value 33 for the `Value` trait. -pub struct _33; -impl Value for _33 { - const VALUE: u32 = 33; -} -/// Type representing the value 34 for the `Value` trait. -pub struct _34; -impl Value for _34 { - const VALUE: u32 = 34; -} -/// Type representing the value 35 for the `Value` trait. -pub struct _35; -impl Value for _35 { - const VALUE: u32 = 35; -} -/// Type representing the value 36 for the `Value` trait. -pub struct _36; -impl Value for _36 { - const VALUE: u32 = 36; -} -/// Type representing the value 37 for the `Value` trait. -pub struct _37; -impl Value for _37 { - const VALUE: u32 = 37; -} -/// Type representing the value 38 for the `Value` trait. -pub struct _38; -impl Value for _38 { - const VALUE: u32 = 38; -} -/// Type representing the value 39 for the `Value` trait. -pub struct _39; -impl Value for _39 { - const VALUE: u32 = 39; -} -/// Type representing the value 40 for the `Value` trait. -pub struct _40; -impl Value for _40 { - const VALUE: u32 = 40; -} -/// Type representing the value 41 for the `Value` trait. -pub struct _41; -impl Value for _41 { - const VALUE: u32 = 41; -} -/// Type representing the value 42 for the `Value` trait. -pub struct _42; -impl Value for _42 { - const VALUE: u32 = 42; -} -/// Type representing the value 43 for the `Value` trait. -pub struct _43; -impl Value for _43 { - const VALUE: u32 = 43; -} -/// Type representing the value 44 for the `Value` trait. -pub struct _44; -impl Value for _44 { - const VALUE: u32 = 44; -} -/// Type representing the value 45 for the `Value` trait. -pub struct _45; -impl Value for _45 { - const VALUE: u32 = 45; -} -/// Type representing the value 46 for the `Value` trait. -pub struct _46; -impl Value for _46 { - const VALUE: u32 = 46; -} -/// Type representing the value 47 for the `Value` trait. -pub struct _47; -impl Value for _47 { - const VALUE: u32 = 47; -} -/// Type representing the value 48 for the `Value` trait. -pub struct _48; -impl Value for _48 { - const VALUE: u32 = 48; -} -/// Type representing the value 49 for the `Value` trait. -pub struct _49; -impl Value for _49 { - const VALUE: u32 = 49; -} -/// Type representing the value 50 for the `Value` trait. -pub struct _50; -impl Value for _50 { - const VALUE: u32 = 50; -} -/// Type representing the value 51 for the `Value` trait. -pub struct _51; -impl Value for _51 { - const VALUE: u32 = 51; -} -/// Type representing the value 52 for the `Value` trait. -pub struct _52; -impl Value for _52 { - const VALUE: u32 = 52; -} -/// Type representing the value 53 for the `Value` trait. -pub struct _53; -impl Value for _53 { - const VALUE: u32 = 53; -} -/// Type representing the value 54 for the `Value` trait. -pub struct _54; -impl Value for _54 { - const VALUE: u32 = 54; -} -/// Type representing the value 55 for the `Value` trait. -pub struct _55; -impl Value for _55 { - const VALUE: u32 = 55; -} -/// Type representing the value 56 for the `Value` trait. -pub struct _56; -impl Value for _56 { - const VALUE: u32 = 56; -} -/// Type representing the value 57 for the `Value` trait. -pub struct _57; -impl Value for _57 { - const VALUE: u32 = 57; -} -/// Type representing the value 58 for the `Value` trait. -pub struct _58; -impl Value for _58 { - const VALUE: u32 = 58; -} -/// Type representing the value 59 for the `Value` trait. -pub struct _59; -impl Value for _59 { - const VALUE: u32 = 59; -} -/// Type representing the value 60 for the `Value` trait. -pub struct _60; -impl Value for _60 { - const VALUE: u32 = 60; -} -/// Type representing the value 61 for the `Value` trait. -pub struct _61; -impl Value for _61 { - const VALUE: u32 = 61; -} -/// Type representing the value 62 for the `Value` trait. -pub struct _62; -impl Value for _62 { - const VALUE: u32 = 62; -} -/// Type representing the value 63 for the `Value` trait. -pub struct _63; -impl Value for _63 { - const VALUE: u32 = 63; -} -/// Type representing the value 64 for the `Value` trait. -pub struct _64; -impl Value for _64 { - const VALUE: u32 = 64; -} -/// Type representing the value 65 for the `Value` trait. -pub struct _65; -impl Value for _65 { - const VALUE: u32 = 65; -} -/// Type representing the value 66 for the `Value` trait. -pub struct _66; -impl Value for _66 { - const VALUE: u32 = 66; -} -/// Type representing the value 67 for the `Value` trait. -pub struct _67; -impl Value for _67 { - const VALUE: u32 = 67; -} -/// Type representing the value 68 for the `Value` trait. -pub struct _68; -impl Value for _68 { - const VALUE: u32 = 68; -} -/// Type representing the value 69 for the `Value` trait. -pub struct _69; -impl Value for _69 { - const VALUE: u32 = 69; -} -/// Type representing the value 70 for the `Value` trait. -pub struct _70; -impl Value for _70 { - const VALUE: u32 = 70; -} -/// Type representing the value 71 for the `Value` trait. -pub struct _71; -impl Value for _71 { - const VALUE: u32 = 71; -} -/// Type representing the value 72 for the `Value` trait. -pub struct _72; -impl Value for _72 { - const VALUE: u32 = 72; -} -/// Type representing the value 73 for the `Value` trait. -pub struct _73; -impl Value for _73 { - const VALUE: u32 = 73; -} -/// Type representing the value 74 for the `Value` trait. -pub struct _74; -impl Value for _74 { - const VALUE: u32 = 74; -} -/// Type representing the value 75 for the `Value` trait. -pub struct _75; -impl Value for _75 { - const VALUE: u32 = 75; -} -/// Type representing the value 76 for the `Value` trait. -pub struct _76; -impl Value for _76 { - const VALUE: u32 = 76; -} -/// Type representing the value 77 for the `Value` trait. -pub struct _77; -impl Value for _77 { - const VALUE: u32 = 77; -} -/// Type representing the value 78 for the `Value` trait. -pub struct _78; -impl Value for _78 { - const VALUE: u32 = 78; -} -/// Type representing the value 79 for the `Value` trait. -pub struct _79; -impl Value for _79 { - const VALUE: u32 = 79; -} -/// Type representing the value 80 for the `Value` trait. -pub struct _80; -impl Value for _80 { - const VALUE: u32 = 80; -} -/// Type representing the value 81 for the `Value` trait. -pub struct _81; -impl Value for _81 { - const VALUE: u32 = 81; -} -/// Type representing the value 82 for the `Value` trait. -pub struct _82; -impl Value for _82 { - const VALUE: u32 = 82; -} -/// Type representing the value 83 for the `Value` trait. -pub struct _83; -impl Value for _83 { - const VALUE: u32 = 83; -} -/// Type representing the value 84 for the `Value` trait. -pub struct _84; -impl Value for _84 { - const VALUE: u32 = 84; -} -/// Type representing the value 85 for the `Value` trait. -pub struct _85; -impl Value for _85 { - const VALUE: u32 = 85; -} -/// Type representing the value 86 for the `Value` trait. -pub struct _86; -impl Value for _86 { - const VALUE: u32 = 86; -} -/// Type representing the value 87 for the `Value` trait. -pub struct _87; -impl Value for _87 { - const VALUE: u32 = 87; -} -/// Type representing the value 88 for the `Value` trait. -pub struct _88; -impl Value for _88 { - const VALUE: u32 = 88; -} -/// Type representing the value 89 for the `Value` trait. -pub struct _89; -impl Value for _89 { - const VALUE: u32 = 89; -} -/// Type representing the value 90 for the `Value` trait. -pub struct _90; -impl Value for _90 { - const VALUE: u32 = 90; -} -/// Type representing the value 91 for the `Value` trait. -pub struct _91; -impl Value for _91 { - const VALUE: u32 = 91; -} -/// Type representing the value 92 for the `Value` trait. -pub struct _92; -impl Value for _92 { - const VALUE: u32 = 92; -} -/// Type representing the value 93 for the `Value` trait. -pub struct _93; -impl Value for _93 { - const VALUE: u32 = 93; -} -/// Type representing the value 94 for the `Value` trait. -pub struct _94; -impl Value for _94 { - const VALUE: u32 = 94; -} -/// Type representing the value 95 for the `Value` trait. -pub struct _95; -impl Value for _95 { - const VALUE: u32 = 95; -} -/// Type representing the value 96 for the `Value` trait. -pub struct _96; -impl Value for _96 { - const VALUE: u32 = 96; -} -/// Type representing the value 97 for the `Value` trait. -pub struct _97; -impl Value for _97 { - const VALUE: u32 = 97; -} -/// Type representing the value 98 for the `Value` trait. -pub struct _98; -impl Value for _98 { - const VALUE: u32 = 98; -} -/// Type representing the value 99 for the `Value` trait. -pub struct _99; -impl Value for _99 { - const VALUE: u32 = 99; -} -/// Type representing the value 100 for the `Value` trait. -pub struct _100; -impl Value for _100 { - const VALUE: u32 = 100; -} -/// Type representing the value 112 for the `Value` trait. -pub struct _112; -impl Value for _112 { - const VALUE: u32 = 112; -} -/// Type representing the value 128 for the `Value` trait. -pub struct _128; -impl Value for _128 { - const VALUE: u32 = 128; -} -/// Type representing the value 160 for the `Value` trait. -pub struct _160; -impl Value for _160 { - const VALUE: u32 = 160; -} -/// Type representing the value 192 for the `Value` trait. -pub struct _192; -impl Value for _192 { - const VALUE: u32 = 192; -} -/// Type representing the value 224 for the `Value` trait. -pub struct _224; -impl Value for _224 { - const VALUE: u32 = 224; -} -/// Type representing the value 256 for the `Value` trait. -pub struct _256; -impl Value for _256 { - const VALUE: u32 = 256; -} -/// Type representing the value 384 for the `Value` trait. -pub struct _384; -impl Value for _384 { - const VALUE: u32 = 384; -} -/// Type representing the value 512 for the `Value` trait. -pub struct _512; -impl Value for _512 { - const VALUE: u32 = 512; -} From 4bc2af13cd81007a2a340d0333062179420d5daf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Mon, 14 Feb 2022 21:12:48 +0100 Subject: [PATCH 491/695] wasm-builder: Support latest nightly (#10837) * wasm-builder: Support latest nightly With latest nightly, aka rust version 1.60+ namespaced features are added. This changes the handling of optional dependencies. We currently have features that enable optional dependencies when `std` is enabled. This was before no problem, but now the wasm-builder detects them as enabled. To support the transition period until 1.60 is released as stable, this pr adds an heuristic to not enable these optional crates in the wasm build when they are enabled in the `std` feature. This heuristic fails when someones enables these optional dependencies from the outside as well as via the `std` feature, however we hope that no one is doing this at the moment. When namespaced features are enabled, these dependencies needs to be enabled using `dep:dependency-name` to solve this properly. https://doc.rust-lang.org/cargo/reference/unstable.html#namespaced-features * Remove accidentally added features --- Cargo.lock | 1 - bin/node/runtime/Cargo.toml | 4 +--- primitives/keyring/Cargo.toml | 1 - utils/wasm-builder/src/wasm_project.rs | 23 ++++++++++++++++++++--- 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index feb721e6092c..e97c90e49236 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4916,7 +4916,6 @@ dependencies = [ "sp-core", "sp-inherents", "sp-io", - "sp-keyring", "sp-npos-elections", "sp-offchain", "sp-runtime", diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 2aad40b4f121..4f235a51171d 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -35,7 +35,6 @@ sp-std = { version = "4.0.0", default-features = false, path = "../../../primiti sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/api" } sp-runtime = { version = "5.0.0", default-features = false, path = "../../../primitives/runtime" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/staking" } -sp-keyring = { version = "5.0.0", optional = true, path = "../../../primitives/keyring" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/session" } sp-transaction-pool = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/transaction-pool" } sp-version = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/version" } @@ -153,7 +152,6 @@ std = [ "sp-runtime/std", "sp-staking/std", "pallet-staking/std", - "sp-keyring", "sp-session/std", "pallet-sudo/std", "frame-support/std", @@ -178,7 +176,7 @@ std = [ "log/std", "frame-try-runtime/std", "sp-npos-elections/std", - "sp-io/std", + "sp-io/std", "pallet-child-bounties/std", ] runtime-benchmarks = [ diff --git a/primitives/keyring/Cargo.toml b/primitives/keyring/Cargo.toml index 5cf8a574505a..1e5a234d3909 100644 --- a/primitives/keyring/Cargo.toml +++ b/primitives/keyring/Cargo.toml @@ -13,7 +13,6 @@ readme = "README.md" [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] - [dependencies] sp-core = { version = "5.0.0", path = "../core" } sp-runtime = { version = "5.0.0", path = "../runtime" } diff --git a/utils/wasm-builder/src/wasm_project.rs b/utils/wasm-builder/src/wasm_project.rs index 20e176444c62..e94703b610a4 100644 --- a/utils/wasm-builder/src/wasm_project.rs +++ b/utils/wasm-builder/src/wasm_project.rs @@ -341,13 +341,30 @@ fn project_enabled_features( ) -> Vec { let package = find_package_by_manifest_path(cargo_manifest, crate_metadata); + let std_enabled = package.features.get("std"); + let mut enabled_features = package .features - .keys() - .filter(|f| { + .iter() + .filter(|(f, v)| { let mut feature_env = f.replace("-", "_"); feature_env.make_ascii_uppercase(); + // If this is a feature that corresponds only to an optional dependency + // and this feature is enabled by the `std` feature, we assume that this + // is only done through the `std` feature. This is a bad heuristic and should + // be removed after namespaced features are landed: + // https://doc.rust-lang.org/cargo/reference/unstable.html#namespaced-features + // Then we can just express this directly in the `Cargo.toml` and do not require + // this heuristic anymore. However, for the transition phase between now and namespaced + // features already being present in nightly, we need this code to make + // runtimes compile with all the possible rustc versions. + if v.len() == 1 && v.get(0).map_or(false, |v| *v == format!("dep:{}", f)) { + if std_enabled.as_ref().map(|e| e.iter().any(|ef| ef == *f)).unwrap_or(false) { + return false + } + } + // We don't want to enable the `std`/`default` feature for the wasm build and // we need to check if the feature is enabled by checking the env variable. *f != "std" && @@ -355,7 +372,7 @@ fn project_enabled_features( .map(|v| v == "1") .unwrap_or_default() }) - .cloned() + .map(|d| d.0.clone()) .collect::>(); enabled_features.sort(); From c269b8a527410b1624470d802e82a7ef13cf86e1 Mon Sep 17 00:00:00 2001 From: driemworks Date: Mon, 14 Feb 2022 20:28:19 -0500 Subject: [PATCH 492/695] update tests, remove unneeded params --- bin/node-template/pallets/iris-assets/src/lib.rs | 5 ++--- .../pallets/iris-session/src/lib.rs | 9 ++------- .../pallets/iris-session/src/tests.rs | 16 +++++++++++++++- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/bin/node-template/pallets/iris-assets/src/lib.rs b/bin/node-template/pallets/iris-assets/src/lib.rs index 3401e094a1a6..b02d85755339 100644 --- a/bin/node-template/pallets/iris-assets/src/lib.rs +++ b/bin/node-template/pallets/iris-assets/src/lib.rs @@ -320,7 +320,6 @@ pub mod pallet { #[pallet::weight(100)] pub fn insert_pin_request( origin: OriginFor, - acct: T::AccountId, asset_owner: T::AccountId, asset_id: T::AssetId, ) -> DispatchResult { @@ -331,8 +330,8 @@ pub mod pallet { asset_id.clone(), ); >::mutate( - |queue| queue.push(DataCommand::PinCID( - acct.clone(), + |queue| queue.push(DataCommand::PinCID( + who.clone(), asset_id.clone(), cid.clone(), ))); diff --git a/bin/node-template/pallets/iris-session/src/lib.rs b/bin/node-template/pallets/iris-session/src/lib.rs index 88de4f5f396f..3f314867b42f 100644 --- a/bin/node-template/pallets/iris-session/src/lib.rs +++ b/bin/node-template/pallets/iris-session/src/lib.rs @@ -10,9 +10,6 @@ //! node has sufficient storage capacity to successfully pin the underlying CID of the asset class, //! then that node is considered a storage provider as long as it is online. //! -//! Temporaraily, this pallet is in a weird limbo between proof of authority and proof of stake -//! without actually verifying any quantitative measure of storage capacity -//! //! The Iris Session Pallet allows addition and removal of //! storage providers via extrinsics (transaction calls), in //! Substrate-based PoA networks. It also integrates with the im-online pallet @@ -438,12 +435,11 @@ pub mod pallet { let new_origin = system::RawOrigin::Signed(who.clone()).into(); let candidate_storage_providers = >::get(pool_id.clone()); ensure!(!candidate_storage_providers.contains(&who), Error::::AlreadyACandidate); - // TODO: we need a better scheme for *generating* pool ids -> should always be unique (cid + owner maybe?) >::mutate(pool_id.clone(), |sp| { sp.push(who.clone()); }); let owner = T::Lookup::lookup(pool_owner)?; - >::insert_pin_request(new_origin, who.clone(), owner, pool_id)?; + >::insert_pin_request(new_origin, owner, pool_id).map_err(|_| Error::::CantCreateRequest); Self::deposit_event(Event::RequestJoinStoragePoolSuccess(who.clone(), pool_id.clone())); Ok(()) } @@ -571,8 +567,8 @@ pub mod pallet { p.push(k.clone()); }); *era_rewards.individual.entry(k.clone()).or_default() += 1; + era_rewards.total += 1; } - era_rewards.total += 1; }); } else { // error -> no active era found @@ -924,7 +920,6 @@ impl Pallet { unreachable!("only `Identity` is a valid response type."); }; let expected_pub_key = >::get(acct.clone()); - // todo: create new error enum if this is the route i choose ensure!(public_key == expected_pub_key, Error::::BadOrigin); match Self::ipfs_request(IpfsRequest::InsertPin(cid.clone(), false), deadline) { Ok(IpfsResponse::Success) => { diff --git a/bin/node-template/pallets/iris-session/src/tests.rs b/bin/node-template/pallets/iris-session/src/tests.rs index 2f98c1ac0b8f..d64ea9b11e2d 100644 --- a/bin/node-template/pallets/iris-session/src/tests.rs +++ b/bin/node-template/pallets/iris-session/src/tests.rs @@ -164,6 +164,8 @@ fn iris_session_join_storage_pool() { p.clone().public(), id.clone(), )); + // AND: I receive a reward point + assert_eq!(crate::ErasRewardPoints::::get(0).p.clone.public(), 1); }); } @@ -340,13 +342,25 @@ fn iris_can_fetch_bytes_and_add_to_offchain_storage() { id.clone(), balance.clone(), )); + // AND: A validator stores the data + assert_ok!(IrisSession::join_storage_pool( + Origin::signed(p.clone().public()), + p.clone().public(), + id.clone(), + )); // AND: I request the owned content from iris assert_ok!(IrisAssets::request_bytes( Origin::signed(p.clone().public()), p.clone().public(), id.clone(), )); - // THEN: the offchain worker adds data to IPFS + // THEN: the offchain worker proxies IPFS requests assert_ok!(IrisSession::handle_data_requests()); + // AND: Each storage provider receives a reward point + let eras_reward_points = crate::ErasRewardPoints::::get(0, id.clone()); + assert_eq!(3, eras_reward_points.total); + for validator in crate::Validators::::get() { + assert_eq!(1, eras_reward_points.individual.entry(validator)); + } }); } From bedaaf32ba41b235277cf828c9dc3f5d54f121c8 Mon Sep 17 00:00:00 2001 From: driemworks Date: Mon, 14 Feb 2022 21:58:16 -0500 Subject: [PATCH 493/695] min authorities check before removal --- bin/node-template/pallets/iris-session/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bin/node-template/pallets/iris-session/src/lib.rs b/bin/node-template/pallets/iris-session/src/lib.rs index 3f314867b42f..15aa00c8009d 100644 --- a/bin/node-template/pallets/iris-session/src/lib.rs +++ b/bin/node-template/pallets/iris-session/src/lib.rs @@ -693,7 +693,8 @@ impl Pallet { *v += 1; }); } else { - Self::mark_for_removal(acct); + // TODO + Self::do_remove_validator(acct); } } } From dd8a868ad819666ff81bd94479657be560daf767 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Tue, 15 Feb 2022 09:56:22 +0100 Subject: [PATCH 494/695] contracts: Fix `seal_call` weights (#10796) * Fix call weights * Fix instantiate benchmark * cargo run --quiet --profile=production --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_contracts --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/contracts/src/weights.rs --template=./.maintain/frame-weight-template.hbs * Remove stale and superflous comments * `decrement_refcount` should be infallible * Don't hardcode increment_refcount, decrement_refcount * Rename CopyIn/CopyOut * Fix warning in tests Co-authored-by: Parity Bot --- frame/contracts/src/benchmarking/mod.rs | 113 +- frame/contracts/src/exec.rs | 61 +- frame/contracts/src/schedule.rs | 48 +- frame/contracts/src/wasm/code_cache.rs | 3 +- frame/contracts/src/wasm/mod.rs | 13 +- frame/contracts/src/wasm/runtime.rs | 89 +- frame/contracts/src/weights.rs | 1270 +++++++++++------------ 7 files changed, 759 insertions(+), 838 deletions(-) diff --git a/frame/contracts/src/benchmarking/mod.rs b/frame/contracts/src/benchmarking/mod.rs index b18b40d0b334..3a749095b955 100644 --- a/frame/contracts/src/benchmarking/mod.rs +++ b/frame/contracts/src/benchmarking/mod.rs @@ -33,6 +33,7 @@ use crate::{ exec::{AccountIdOf, StorageKey}, schedule::{API_BENCHMARK_BATCH_SIZE, INSTR_BENCHMARK_BATCH_SIZE}, storage::Storage, + wasm::CallFlags, Pallet as Contracts, *, }; use codec::{Encode, MaxEncodedLen}; @@ -1526,44 +1527,21 @@ benchmarks! { let origin = RawOrigin::Signed(instance.caller.clone()); }: call(origin, callee, 0u32.into(), Weight::MAX, None, vec![]) - seal_call_per_transfer_input_output_kb { + seal_call_per_transfer_clone_kb { let t in 0 .. 1; - let i in 0 .. code::max_pages::() * 64; - let o in 0 .. (code::max_pages::() - 1) * 64; - let callee_code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal0", - name: "seal_return", - params: vec![ - ValueType::I32, - ValueType::I32, - ValueType::I32, - ], - return_type: None, - }], - call_body: Some(body::plain(vec![ - Instruction::I32Const(0), // flags - Instruction::I32Const(0), // data_ptr - Instruction::I32Const((o * 1024) as i32), // data_len - Instruction::Call(0), - Instruction::End, - ])), - .. Default::default() - }); + let c in 0 .. code::max_pages::() * 64; let callees = (0..API_BENCHMARK_BATCH_SIZE) - .map(|i| Contract::with_index(i + 1, callee_code.clone(), vec![])) + .map(|i| Contract::with_index(i + 1, >::dummy(), vec![])) .collect::, _>>()?; let callee_len = callees.get(0).map(|i| i.account_id.encode().len()).unwrap_or(0); let callee_bytes = callees.iter().flat_map(|x| x.account_id.encode()).collect::>(); - let callees_len = callee_bytes.len(); let value: BalanceOf = t.into(); let value_bytes = value.encode(); let value_len = value_bytes.len(); let code = WasmModule::::from(ModuleDefinition { memory: Some(ImportedMemory::max::()), imported_functions: vec![ImportedFunction { - module: "seal0", + module: "seal1", name: "seal_call", params: vec![ ValueType::I32, @@ -1574,7 +1552,6 @@ benchmarks! { ValueType::I32, ValueType::I32, ValueType::I32, - ValueType::I32, ], return_type: Some(ValueType::I32), }], @@ -1587,21 +1564,16 @@ benchmarks! { offset: value_len as u32, value: callee_bytes, }, - DataSegment { - offset: (value_len + callees_len) as u32, - value: (o * 1024).to_le_bytes().into(), - }, ], call_body: Some(body::repeated_dyn(API_BENCHMARK_BATCH_SIZE, vec![ + Regular(Instruction::I32Const(CallFlags::CLONE_INPUT.bits() as i32)), // flags Counter(value_len as u32, callee_len as u32), // callee_ptr - Regular(Instruction::I32Const(callee_len as i32)), // callee_len Regular(Instruction::I64Const(0)), // gas Regular(Instruction::I32Const(0)), // value_ptr - Regular(Instruction::I32Const(value_len as i32)), // value_len Regular(Instruction::I32Const(0)), // input_data_ptr - Regular(Instruction::I32Const((i * 1024) as i32)), // input_data_len - Regular(Instruction::I32Const((value_len + callees_len + 4) as i32)), // output_ptr - Regular(Instruction::I32Const((value_len + callees_len) as i32)), // output_len_ptr + Regular(Instruction::I32Const(0)), // input_data_len + Regular(Instruction::I32Const(SENTINEL as i32)), // output_ptr + Regular(Instruction::I32Const(0)), // output_len_ptr Regular(Instruction::Call(0)), Regular(Instruction::Drop), ])), @@ -1609,7 +1581,8 @@ benchmarks! { }); let instance = Contract::::new(code, vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + let bytes = vec![42; (c * 1024) as usize]; + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, bytes) // We assume that every instantiate sends at least the minimum balance. seal_instantiate { @@ -1725,52 +1698,28 @@ benchmarks! { } } - seal_instantiate_per_input_output_salt_kb { - let i in 0 .. (code::max_pages::() - 1) * 64; - let o in 0 .. (code::max_pages::() - 1) * 64; + seal_instantiate_per_transfer_salt_kb { + let t in 0 .. 1; let s in 0 .. (code::max_pages::() - 1) * 64; - let callee_code = WasmModule::::from(ModuleDefinition { - memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal0", - name: "seal_return", - params: vec![ - ValueType::I32, - ValueType::I32, - ValueType::I32, - ], - return_type: None, - }], - deploy_body: Some(body::plain(vec![ - Instruction::I32Const(0), // flags - Instruction::I32Const(0), // data_ptr - Instruction::I32Const((o * 1024) as i32), // data_len - Instruction::Call(0), - Instruction::End, - ])), - .. Default::default() - }); + let callee_code = WasmModule::::dummy(); let hash = callee_code.hash.clone(); let hash_bytes = callee_code.hash.encode(); let hash_len = hash_bytes.len(); Contracts::::store_code_raw(callee_code.code, whitelisted_caller())?; - let inputs = (0..API_BENCHMARK_BATCH_SIZE).map(|x| x.encode()).collect::>(); - let input_len = inputs.get(0).map(|x| x.len()).unwrap_or(0); - let input_bytes = inputs.iter().cloned().flatten().collect::>(); - let inputs_len = input_bytes.len(); - let value = T::Currency::minimum_balance(); - assert!(value > 0u32.into()); + let salts = (0..API_BENCHMARK_BATCH_SIZE).map(|x| x.encode()).collect::>(); + let salt_len = salts.get(0).map(|x| x.len()).unwrap_or(0); + let salt_bytes = salts.iter().cloned().flatten().collect::>(); + let salts_len = salt_bytes.len(); + let value: BalanceOf = t.into(); let value_bytes = value.encode(); let value_len = value_bytes.len(); let addr_len = T::AccountId::max_encoded_len(); // offsets where to place static data in contract memory - let input_offset = 0; - let value_offset = inputs_len; + let salt_offset = 0; + let value_offset = salts_len; let hash_offset = value_offset + value_len; let addr_len_offset = hash_offset + hash_len; - let output_len_offset = addr_len_offset + 4; - let output_offset = output_len_offset + 4; let code = WasmModule::::from(ModuleDefinition { memory: Some(ImportedMemory::max::()), @@ -1796,8 +1745,8 @@ benchmarks! { }], data_segments: vec![ DataSegment { - offset: input_offset as u32, - value: input_bytes, + offset: salt_offset as u32, + value: salt_bytes, }, DataSegment { offset: value_offset as u32, @@ -1811,10 +1760,6 @@ benchmarks! { offset: addr_len_offset as u32, value: (addr_len as u32).to_le_bytes().into(), }, - DataSegment { - offset: output_len_offset as u32, - value: (o * 1024).to_le_bytes().into(), - }, ], call_body: Some(body::repeated_dyn(API_BENCHMARK_BATCH_SIZE, vec![ Regular(Instruction::I32Const(hash_offset as i32)), // code_hash_ptr @@ -1822,14 +1767,14 @@ benchmarks! { Regular(Instruction::I64Const(0)), // gas Regular(Instruction::I32Const(value_offset as i32)), // value_ptr Regular(Instruction::I32Const(value_len as i32)), // value_len - Counter(input_offset as u32, input_len as u32), // input_data_ptr - Regular(Instruction::I32Const((i * 1024).max(input_len as u32) as i32)), // input_data_len + Regular(Instruction::I32Const(0)), // input_data_ptr + Regular(Instruction::I32Const(0)), // input_data_len Regular(Instruction::I32Const((addr_len_offset + addr_len) as i32)), // address_ptr Regular(Instruction::I32Const(addr_len_offset as i32)), // address_len_ptr - Regular(Instruction::I32Const(output_offset as i32)), // output_ptr - Regular(Instruction::I32Const(output_len_offset as i32)), // output_len_ptr - Counter(input_offset as u32, input_len as u32), // salt_ptr - Regular(Instruction::I32Const((s * 1024).max(input_len as u32) as i32)), // salt_len + Regular(Instruction::I32Const(SENTINEL as i32)), // output_ptr + Regular(Instruction::I32Const(0)), // output_len_ptr + Counter(salt_offset as u32, salt_len as u32), // salt_ptr + Regular(Instruction::I32Const((s * 1024).max(salt_len as u32) as i32)), // salt_len Regular(Instruction::Call(0)), Regular(Instruction::I32Eqz), Regular(Instruction::If(BlockType::NoResult)), diff --git a/frame/contracts/src/exec.rs b/frame/contracts/src/exec.rs index bca74cd66ced..eb7a68d81ad5 100644 --- a/frame/contracts/src/exec.rs +++ b/frame/contracts/src/exec.rs @@ -18,7 +18,6 @@ use crate::{ gas::GasMeter, storage::{self, Storage, WriteOutcome}, - wasm::{decrement_refcount, increment_refcount}, AccountCounter, BalanceOf, CodeHash, Config, ContractInfo, ContractInfoOf, Error, Event, Pallet as Contracts, Schedule, }; @@ -92,10 +91,6 @@ pub trait Ext: sealing::Sealed { /// Call (possibly transferring some amount of funds) into the specified account. /// /// Returns the original code size of the called contract. - /// - /// # Return Value - /// - /// Result<(ExecReturnValue, CodeSize), (ExecError, CodeSize)> fn call( &mut self, gas_limit: Weight, @@ -108,10 +103,6 @@ pub trait Ext: sealing::Sealed { /// Execute code in the current frame. /// /// Returns the original code size of the called contract. - /// - /// # Return Value - /// - /// Result fn delegate_call( &mut self, code: CodeHash, @@ -123,10 +114,6 @@ pub trait Ext: sealing::Sealed { /// Returns the original code size of the called contract. /// The newly created account will be associated with `code`. `value` specifies the amount of /// value transferred from this to the newly created account. - /// - /// # Return Value - /// - /// Result<(AccountId, ExecReturnValue, CodeSize), (ExecError, CodeSize)> fn instantiate( &mut self, gas_limit: Weight, @@ -269,12 +256,17 @@ pub trait Executable: Sized { gas_meter: &mut GasMeter, ) -> Result; - /// Decrement the refcount by one if the code exists. + /// Increment the refcount of a code in-storage by one. /// - /// # Note + /// This is needed when the code is not set via instantiate but `seal_set_code_hash`. /// - /// Charges weight proportional to the code size from the gas meter. - fn remove_user(code_hash: CodeHash) -> Result<(), DispatchError>; + /// # Errors + /// + /// [`Error::CodeNotFound`] is returned if the specified `code_hash` does not exist. + fn add_user(code_hash: CodeHash) -> Result<(), DispatchError>; + + /// Decrement the refcount by one if the code exists. + fn remove_user(code_hash: CodeHash); /// Execute the specified exported function and return the result. /// @@ -1058,7 +1050,7 @@ where T::Currency::free_balance(&frame.account_id), )?; ContractInfoOf::::remove(&frame.account_id); - E::remove_user(info.code_hash)?; + E::remove_user(info.code_hash); Contracts::::deposit_event(Event::Terminated { contract: frame.account_id.clone(), beneficiary: beneficiary.clone(), @@ -1188,10 +1180,10 @@ where } fn set_code_hash(&mut self, hash: CodeHash) -> Result<(), DispatchError> { - increment_refcount::(hash)?; + E::add_user(hash)?; let top_frame = self.top_frame_mut(); let prev_hash = top_frame.contract_info().code_hash.clone(); - decrement_refcount::(prev_hash.clone())?; + E::remove_user(prev_hash.clone()); top_frame.contract_info().code_hash = hash; Contracts::::deposit_event(Event::ContractCodeUpdated { contract: top_frame.account_id.clone(), @@ -1249,7 +1241,11 @@ mod tests { use pretty_assertions::assert_eq; use sp_core::Bytes; use sp_runtime::{traits::Hash, DispatchError}; - use std::{cell::RefCell, collections::HashMap, rc::Rc}; + use std::{ + cell::RefCell, + collections::hash_map::{Entry, HashMap}, + rc::Rc, + }; type System = frame_system::Pallet; @@ -1311,15 +1307,15 @@ mod tests { }) } - fn increment_refcount(code_hash: CodeHash) { + fn increment_refcount(code_hash: CodeHash) -> Result<(), DispatchError> { LOADER.with(|loader| { let mut loader = loader.borrow_mut(); - loader - .map - .entry(code_hash) - .and_modify(|executable| executable.refcount += 1) - .or_insert_with(|| panic!("code_hash does not exist")); - }); + match loader.map.entry(code_hash) { + Entry::Vacant(_) => Err(>::CodeNotFound)?, + Entry::Occupied(mut entry) => entry.get_mut().refcount += 1, + } + Ok(()) + }) } fn decrement_refcount(code_hash: CodeHash) { @@ -1355,9 +1351,12 @@ mod tests { }) } - fn remove_user(code_hash: CodeHash) -> Result<(), DispatchError> { + fn add_user(code_hash: CodeHash) -> Result<(), DispatchError> { + MockLoader::increment_refcount(code_hash) + } + + fn remove_user(code_hash: CodeHash) { MockLoader::decrement_refcount(code_hash); - Ok(()) } fn execute>( @@ -1367,7 +1366,7 @@ mod tests { input_data: Vec, ) -> ExecResult { if let &Constructor = function { - MockLoader::increment_refcount(self.code_hash); + Self::add_user(self.code_hash).unwrap(); } if function == &self.func_type { (self.func)(MockCtx { ext, input_data }, &self) diff --git a/frame/contracts/src/schedule.rs b/frame/contracts/src/schedule.rs index c92d2dd61610..d6bdf85a4d68 100644 --- a/frame/contracts/src/schedule.rs +++ b/frame/contracts/src/schedule.rs @@ -367,20 +367,14 @@ pub struct HostFnWeights { /// Weight surcharge that is claimed if `seal_call` does a balance transfer. pub call_transfer_surcharge: Weight, - /// Weight per input byte supplied to `seal_call`. - pub call_per_input_byte: Weight, - - /// Weight per output byte received through `seal_call`. - pub call_per_output_byte: Weight, + /// Weight per byte that is cloned by supplying the `CLONE_INPUT` flag. + pub call_per_cloned_byte: Weight, /// Weight of calling `seal_instantiate`. pub instantiate: Weight, - /// Weight per input byte supplied to `seal_instantiate`. - pub instantiate_per_input_byte: Weight, - - /// Weight per output byte received through `seal_instantiate`. - pub instantiate_per_output_byte: Weight, + /// Weight surcharge that is claimed if `seal_instantiate` does a balance transfer. + pub instantiate_transfer_surcharge: Weight, /// Weight per salt byte supplied to `seal_instantiate`. pub instantiate_per_salt_byte: Weight, @@ -623,40 +617,16 @@ impl Default for HostFnWeights { transfer: cost_batched!(seal_transfer), call: cost_batched!(seal_call), delegate_call: cost_batched!(seal_delegate_call), - call_transfer_surcharge: cost_batched_args!( - seal_call_per_transfer_input_output_kb, - 1, - 0, - 0 - ), - call_per_input_byte: cost_byte_batched_args!( - seal_call_per_transfer_input_output_kb, - 0, - 1, - 0 - ), - call_per_output_byte: cost_byte_batched_args!( - seal_call_per_transfer_input_output_kb, - 0, - 0, - 1 - ), + call_transfer_surcharge: cost_batched_args!(seal_call_per_transfer_clone_kb, 1, 0), + call_per_cloned_byte: cost_batched_args!(seal_call_per_transfer_clone_kb, 0, 1), instantiate: cost_batched!(seal_instantiate), - instantiate_per_input_byte: cost_byte_batched_args!( - seal_instantiate_per_input_output_salt_kb, - 1, - 0, - 0 - ), - instantiate_per_output_byte: cost_byte_batched_args!( - seal_instantiate_per_input_output_salt_kb, - 0, + instantiate_transfer_surcharge: cost_byte_batched_args!( + seal_instantiate_per_transfer_salt_kb, 1, 0 ), instantiate_per_salt_byte: cost_byte_batched_args!( - seal_instantiate_per_input_output_salt_kb, - 0, + seal_instantiate_per_transfer_salt_kb, 0, 1 ), diff --git a/frame/contracts/src/wasm/code_cache.rs b/frame/contracts/src/wasm/code_cache.rs index 9a447066667b..9fc49ac9a502 100644 --- a/frame/contracts/src/wasm/code_cache.rs +++ b/frame/contracts/src/wasm/code_cache.rs @@ -108,13 +108,12 @@ where /// /// A contract whose refcount dropped to zero isn't automatically removed. A `remove_code` /// transaction must be submitted by the original uploader to do so. -pub fn decrement_refcount(code_hash: CodeHash) -> Result<(), DispatchError> { +pub fn decrement_refcount(code_hash: CodeHash) { >::mutate(code_hash, |existing| { if let Some(info) = existing { info.refcount = info.refcount.saturating_sub(1); } }); - Ok(()) } /// Increment the refcount of a code in-storage by one. diff --git a/frame/contracts/src/wasm/mod.rs b/frame/contracts/src/wasm/mod.rs index 3053f33ff033..2dbaad0d7932 100644 --- a/frame/contracts/src/wasm/mod.rs +++ b/frame/contracts/src/wasm/mod.rs @@ -25,11 +25,8 @@ mod prepare; mod runtime; #[cfg(feature = "runtime-benchmarks")] -pub use self::code_cache::reinstrument; -pub use self::{ - code_cache::{decrement_refcount, increment_refcount}, - runtime::{ReturnCode, Runtime, RuntimeCosts}, -}; +pub use crate::wasm::code_cache::reinstrument; +pub use crate::wasm::runtime::{CallFlags, ReturnCode, Runtime, RuntimeCosts}; use crate::{ exec::{ExecResult, Executable, ExportedFunction, Ext}, gas::GasMeter, @@ -201,7 +198,11 @@ where code_cache::load(code_hash, schedule, gas_meter) } - fn remove_user(code_hash: CodeHash) -> Result<(), DispatchError> { + fn add_user(code_hash: CodeHash) -> Result<(), DispatchError> { + code_cache::increment_refcount::(code_hash) + } + + fn remove_user(code_hash: CodeHash) { code_cache::decrement_refcount::(code_hash) } diff --git a/frame/contracts/src/wasm/runtime.rs b/frame/contracts/src/wasm/runtime.rs index 384fbff9809b..bb188e10e8fa 100644 --- a/frame/contracts/src/wasm/runtime.rs +++ b/frame/contracts/src/wasm/runtime.rs @@ -136,6 +136,10 @@ pub enum RuntimeCosts { /// Charge the gas meter with the cost of a metering block. The charged costs are /// the supplied cost of the block plus the overhead of the metering itself. MeteringBlock(u32), + /// Weight charged for copying data from the sandbox. + CopyFromContract(u32), + /// Weight charged for copying data to the sandbox. + CopyToContract(u32), /// Weight of calling `seal_caller`. Caller, /// Weight of calling `seal_is_contract`. @@ -162,8 +166,6 @@ pub enum RuntimeCosts { WeightToFee, /// Weight of calling `seal_input` without the weight of copying the input. InputBase, - /// Weight of copying the input data for the given size. - InputCopyOut(u32), /// Weight of calling `seal_return` for the given output size. Return(u32), /// Weight of calling `seal_terminate`. @@ -188,21 +190,19 @@ pub enum RuntimeCosts { TakeStorage(u32), /// Weight of calling `seal_transfer`. Transfer, - /// Weight of calling `seal_call` for the given input size. - CallBase(u32), + /// Base weight of calling `seal_call`. + CallBase, /// Weight of calling `seal_delegate_call` for the given input size. #[cfg(feature = "unstable-interface")] - DelegateCallBase(u32), + DelegateCallBase, /// Weight of the transfer performed during a call. CallSurchargeTransfer, - /// Weight of output received through `seal_call` for the given size. - CallCopyOut(u32), - /// Weight of calling `seal_instantiate` for the given input and salt without output weight. - /// This includes the transfer as an instantiate without a value will always be below - /// the existential deposit and is disregarded as corner case. + /// Weight per byte that is cloned by supplying the `CLONE_INPUT` flag. + CallInputCloned(u32), + /// Weight of calling `seal_instantiate` for the given input length and salt. InstantiateBase { input_data_len: u32, salt_len: u32 }, - /// Weight of output received through `seal_instantiate` for the given size. - InstantiateCopyOut(u32), + /// Weight of the transfer performed during an instantiate. + InstantiateSurchargeTransfer, /// Weight of calling `seal_hash_sha_256` for the given input size. HashSha256(u32), /// Weight of calling `seal_hash_keccak_256` for the given input size. @@ -216,9 +216,6 @@ pub enum RuntimeCosts { EcdsaRecovery, /// Weight charged by a chain extension through `seal_call_chain_extension`. ChainExtension(u64), - /// Weight charged for copying data from the sandbox. - #[cfg(feature = "unstable-interface")] - CopyIn(u32), /// Weight charged for calling into the runtime. #[cfg(feature = "unstable-interface")] CallRuntime(Weight), @@ -236,6 +233,8 @@ impl RuntimeCosts { use self::RuntimeCosts::*; let weight = match *self { MeteringBlock(amount) => s.gas.saturating_add(amount.into()), + CopyFromContract(len) => s.return_per_byte.saturating_mul(len.into()), + CopyToContract(len) => s.input_per_byte.saturating_mul(len.into()), Caller => s.caller, #[cfg(feature = "unstable-interface")] IsContract => s.is_contract, @@ -250,7 +249,6 @@ impl RuntimeCosts { Now => s.now, WeightToFee => s.weight_to_fee, InputBase => s.input, - InputCopyOut(len) => s.input_per_byte.saturating_mul(len.into()), Return(len) => s.r#return.saturating_add(s.return_per_byte.saturating_mul(len.into())), Terminate => s.terminate, Random => s.random, @@ -277,18 +275,16 @@ impl RuntimeCosts { .take_storage .saturating_add(s.take_storage_per_byte.saturating_mul(len.into())), Transfer => s.transfer, - CallBase(len) => - s.call.saturating_add(s.call_per_input_byte.saturating_mul(len.into())), - CallSurchargeTransfer => s.call_transfer_surcharge, - CallCopyOut(len) => s.call_per_output_byte.saturating_mul(len.into()), + CallBase => s.call, #[cfg(feature = "unstable-interface")] - DelegateCallBase(len) => - s.delegate_call.saturating_add(s.call_per_input_byte.saturating_mul(len.into())), + DelegateCallBase => s.delegate_call, + CallSurchargeTransfer => s.call_transfer_surcharge, + CallInputCloned(len) => s.call_per_cloned_byte.saturating_mul(len.into()), InstantiateBase { input_data_len, salt_len } => s .instantiate - .saturating_add(s.instantiate_per_input_byte.saturating_mul(input_data_len.into())) + .saturating_add(s.return_per_byte.saturating_mul(input_data_len.into())) .saturating_add(s.instantiate_per_salt_byte.saturating_mul(salt_len.into())), - InstantiateCopyOut(len) => s.instantiate_per_output_byte.saturating_mul(len.into()), + InstantiateSurchargeTransfer => s.instantiate_transfer_surcharge, HashSha256(len) => s .hash_sha2_256 .saturating_add(s.hash_sha2_256_per_byte.saturating_mul(len.into())), @@ -304,8 +300,7 @@ impl RuntimeCosts { #[cfg(feature = "unstable-interface")] EcdsaRecovery => s.ecdsa_recover, ChainExtension(amount) => amount, - #[cfg(feature = "unstable-interface")] - CopyIn(len) => s.return_per_byte.saturating_mul(len.into()), + #[cfg(feature = "unstable-interface")] CallRuntime(weight) => weight, #[cfg(feature = "unstable-interface")] @@ -319,6 +314,17 @@ impl RuntimeCosts { } } +/// Same as [`Runtime::charge_gas`]. +/// +/// We need this access as a macro because sometimes hiding the lifetimes behind +/// a function won't work out. +macro_rules! charge_gas { + ($runtime:expr, $costs:expr) => {{ + let token = $costs.token(&$runtime.ext.schedule().host_fn_weights); + $runtime.ext.gas_meter().charge(token) + }}; +} + #[cfg_attr(test, derive(Debug, PartialEq, Eq))] #[derive(Copy, Clone)] struct RuntimeToken { @@ -339,7 +345,7 @@ where bitflags! { /// Flags used to change the behaviour of `seal_call` and `seal_delegate_call`. - struct CallFlags: u32 { + pub struct CallFlags: u32 { /// Forward the input of current function to the callee. /// /// Supplied input pointers are ignored when set. @@ -393,11 +399,11 @@ enum CallType { } impl CallType { - fn cost(&self, input_data_len: u32) -> RuntimeCosts { + fn cost(&self) -> RuntimeCosts { match self { - CallType::Call { .. } => RuntimeCosts::CallBase(input_data_len), + CallType::Call { .. } => RuntimeCosts::CallBase, #[cfg(feature = "unstable-interface")] - CallType::DelegateCall { .. } => RuntimeCosts::DelegateCallBase(input_data_len), + CallType::DelegateCall { .. } => RuntimeCosts::DelegateCallBase, } } } @@ -493,8 +499,7 @@ where /// /// Returns `Err(HostError)` if there is not enough gas. pub fn charge_gas(&mut self, costs: RuntimeCosts) -> Result { - let token = costs.token(&self.ext.schedule().host_fn_weights); - self.ext.gas_meter().charge(token) + charge_gas!(self, costs) } /// Adjust a previously charged amount down to its actual amount. @@ -734,12 +739,15 @@ where output_ptr: u32, output_len_ptr: u32, ) -> Result { - self.charge_gas(call_type.cost(input_data_len))?; + self.charge_gas(call_type.cost())?; let input_data = if flags.contains(CallFlags::CLONE_INPUT) { - self.input_data.as_ref().ok_or_else(|| Error::::InputForwarded)?.clone() + let input = self.input_data.as_ref().ok_or_else(|| Error::::InputForwarded)?; + charge_gas!(self, RuntimeCosts::CallInputCloned(input.len() as u32))?; + input.clone() } else if flags.contains(CallFlags::FORWARD_INPUT) { self.input_data.take().ok_or_else(|| Error::::InputForwarded)? } else { + self.charge_gas(RuntimeCosts::CopyFromContract(input_data_len))?; self.read_sandbox_memory(input_data_ptr, input_data_len)? }; @@ -782,7 +790,7 @@ where if let Ok(output) = &call_outcome { self.write_sandbox_output(output_ptr, output_len_ptr, &output.data, true, |len| { - Some(RuntimeCosts::CallCopyOut(len)) + Some(RuntimeCosts::CopyToContract(len)) })?; } Ok(Runtime::::exec_into_return_code(call_outcome)?) @@ -803,8 +811,11 @@ where salt_len: u32, ) -> Result { self.charge_gas(RuntimeCosts::InstantiateBase { input_data_len, salt_len })?; - let code_hash: CodeHash<::T> = self.read_sandbox_memory_as(code_hash_ptr)?; let value: BalanceOf<::T> = self.read_sandbox_memory_as(value_ptr)?; + if value > 0u32.into() { + self.charge_gas(RuntimeCosts::InstantiateSurchargeTransfer)?; + } + let code_hash: CodeHash<::T> = self.read_sandbox_memory_as(code_hash_ptr)?; let input_data = self.read_sandbox_memory(input_data_ptr, input_data_len)?; let salt = self.read_sandbox_memory(salt_ptr, salt_len)?; let instantiate_outcome = self.ext.instantiate(gas, code_hash, value, input_data, &salt); @@ -819,7 +830,7 @@ where )?; } self.write_sandbox_output(output_ptr, output_len_ptr, &output.data, true, |len| { - Some(RuntimeCosts::InstantiateCopyOut(len)) + Some(RuntimeCosts::CopyToContract(len)) })?; } Ok(Runtime::::exec_into_return_code(instantiate_outcome.map(|(_, retval)| retval))?) @@ -1302,7 +1313,7 @@ define_env!(Env, , ctx.charge_gas(RuntimeCosts::InputBase)?; if let Some(input) = ctx.input_data.take() { ctx.write_sandbox_output(out_ptr, out_len_ptr, &input, false, |len| { - Some(RuntimeCosts::InputCopyOut(len)) + Some(RuntimeCosts::CopyToContract(len)) })?; ctx.input_data = Some(input); Ok(()) @@ -1911,7 +1922,7 @@ define_env!(Env, , // deploy a contract using it to a production chain. [__unstable__] seal_call_runtime(ctx, call_ptr: u32, call_len: u32) -> ReturnCode => { use frame_support::{dispatch::GetDispatchInfo, weights::extract_actual_weight}; - ctx.charge_gas(RuntimeCosts::CopyIn(call_len))?; + ctx.charge_gas(RuntimeCosts::CopyFromContract(call_len))?; let call: ::Call = ctx.read_sandbox_memory_as_unbounded( call_ptr, call_len )?; diff --git a/frame/contracts/src/weights.rs b/frame/contracts/src/weights.rs index bf35ce511ab2..c43e98bb8ac4 100644 --- a/frame/contracts/src/weights.rs +++ b/frame/contracts/src/weights.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_contracts //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-02-10, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-02-08, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -89,9 +89,9 @@ pub trait WeightInfo { fn seal_transfer(r: u32, ) -> Weight; fn seal_call(r: u32, ) -> Weight; fn seal_delegate_call(r: u32, ) -> Weight; - fn seal_call_per_transfer_input_output_kb(t: u32, i: u32, o: u32, ) -> Weight; + fn seal_call_per_transfer_clone_kb(t: u32, c: u32, ) -> Weight; fn seal_instantiate(r: u32, ) -> Weight; - fn seal_instantiate_per_input_output_salt_kb(i: u32, o: u32, s: u32, ) -> Weight; + fn seal_instantiate_per_transfer_salt_kb(t: u32, s: u32, ) -> Weight; fn seal_hash_sha2_256(r: u32, ) -> Weight; fn seal_hash_sha2_256_per_kb(n: u32, ) -> Weight; fn seal_hash_keccak_256(r: u32, ) -> Weight; @@ -160,32 +160,32 @@ pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize() -> Weight { - (1_590_000 as Weight) + (1_560_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn on_initialize_per_trie_key(k: u32, ) -> Weight { - (9_975_000 as Weight) + (7_843_000 as Weight) // Standard Error: 0 - .saturating_add((724_000 as Weight).saturating_mul(k as Weight)) + .saturating_add((749_000 as Weight).saturating_mul(k as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) } // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize_per_queue_item(q: u32, ) -> Weight { - (7_415_000 as Weight) - // Standard Error: 4_000 - .saturating_add((2_303_000 as Weight).saturating_mul(q as Weight)) + (3_228_000 as Weight) + // Standard Error: 5_000 + .saturating_add((2_257_000 as Weight).saturating_mul(q as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Contracts PristineCode (r:1 w:0) // Storage: Contracts CodeStorage (r:0 w:1) fn reinstrument(c: u32, ) -> Weight { - (18_519_000 as Weight) - // Standard Error: 36_000 - .saturating_add((66_661_000 as Weight).saturating_mul(c as Weight)) + (20_531_000 as Weight) + // Standard Error: 34_000 + .saturating_add((66_014_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -194,9 +194,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call_with_code_kb(c: u32, ) -> Weight { - (210_319_000 as Weight) - // Standard Error: 41_000 - .saturating_add((54_802_000 as Weight).saturating_mul(c as Weight)) + (295_703_000 as Weight) + // Standard Error: 53_000 + .saturating_add((57_661_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -208,11 +208,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn instantiate_with_code(c: u32, s: u32, ) -> Weight { - (220_394_000 as Weight) - // Standard Error: 129_000 - .saturating_add((145_155_000 as Weight).saturating_mul(c as Weight)) - // Standard Error: 8_000 - .saturating_add((1_741_000 as Weight).saturating_mul(s as Weight)) + (332_572_000 as Weight) + // Standard Error: 125_000 + .saturating_add((149_095_000 as Weight).saturating_mul(c as Weight)) + // Standard Error: 7_000 + .saturating_add((1_779_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } @@ -223,9 +223,9 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn instantiate(s: u32, ) -> Weight { - (171_438_000 as Weight) + (222_992_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_721_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((1_759_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } @@ -234,7 +234,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call() -> Weight { - (139_529_000 as Weight) + (189_003_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -242,9 +242,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn upload_code(c: u32, ) -> Weight { - (51_040_000 as Weight) - // Standard Error: 38_000 - .saturating_add((65_886_000 as Weight).saturating_mul(c as Weight)) + (52_521_000 as Weight) + // Standard Error: 36_000 + .saturating_add((66_486_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -252,7 +252,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:0 w:1) // Storage: Contracts PristineCode (r:0 w:1) fn remove_code() -> Weight { - (24_347_000 as Weight) + (24_705_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -261,9 +261,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_caller(r: u32, ) -> Weight { - (217_164_000 as Weight) - // Standard Error: 89_000 - .saturating_add((48_023_000 as Weight).saturating_mul(r as Weight)) + (300_165_000 as Weight) + // Standard Error: 125_000 + .saturating_add((49_828_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -272,9 +272,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_is_contract(r: u32, ) -> Weight { - (81_537_000 as Weight) - // Standard Error: 847_000 - .saturating_add((367_429_000 as Weight).saturating_mul(r as Weight)) + (179_488_000 as Weight) + // Standard Error: 718_000 + .saturating_add((375_855_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -284,9 +284,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_caller_is_origin(r: u32, ) -> Weight { - (214_798_000 as Weight) - // Standard Error: 56_000 - .saturating_add((21_100_000 as Weight).saturating_mul(r as Weight)) + (295_198_000 as Weight) + // Standard Error: 79_000 + .saturating_add((21_948_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -295,9 +295,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_address(r: u32, ) -> Weight { - (216_615_000 as Weight) - // Standard Error: 75_000 - .saturating_add((48_054_000 as Weight).saturating_mul(r as Weight)) + (300_366_000 as Weight) + // Standard Error: 111_000 + .saturating_add((49_435_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -306,9 +306,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas_left(r: u32, ) -> Weight { - (218_034_000 as Weight) + (299_800_000 as Weight) // Standard Error: 87_000 - .saturating_add((47_594_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((49_002_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -317,9 +317,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_balance(r: u32, ) -> Weight { - (221_980_000 as Weight) - // Standard Error: 135_000 - .saturating_add((135_618_000 as Weight).saturating_mul(r as Weight)) + (303_057_000 as Weight) + // Standard Error: 175_000 + .saturating_add((139_293_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -328,9 +328,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_value_transferred(r: u32, ) -> Weight { - (217_623_000 as Weight) - // Standard Error: 86_000 - .saturating_add((47_656_000 as Weight).saturating_mul(r as Weight)) + (299_754_000 as Weight) + // Standard Error: 93_000 + .saturating_add((48_945_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -339,9 +339,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_minimum_balance(r: u32, ) -> Weight { - (216_826_000 as Weight) - // Standard Error: 88_000 - .saturating_add((47_644_000 as Weight).saturating_mul(r as Weight)) + (302_229_000 as Weight) + // Standard Error: 128_000 + .saturating_add((49_007_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -350,9 +350,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_block_number(r: u32, ) -> Weight { - (219_487_000 as Weight) - // Standard Error: 90_000 - .saturating_add((47_167_000 as Weight).saturating_mul(r as Weight)) + (300_772_000 as Weight) + // Standard Error: 114_000 + .saturating_add((48_794_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -361,9 +361,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_now(r: u32, ) -> Weight { - (218_953_000 as Weight) - // Standard Error: 95_000 - .saturating_add((47_458_000 as Weight).saturating_mul(r as Weight)) + (301_936_000 as Weight) + // Standard Error: 119_000 + .saturating_add((48_839_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -373,9 +373,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0) fn seal_weight_to_fee(r: u32, ) -> Weight { - (220_132_000 as Weight) - // Standard Error: 144_000 - .saturating_add((120_373_000 as Weight).saturating_mul(r as Weight)) + (304_935_000 as Weight) + // Standard Error: 146_000 + .saturating_add((121_871_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -384,9 +384,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas(r: u32, ) -> Weight { - (127_458_000 as Weight) - // Standard Error: 56_000 - .saturating_add((24_015_000 as Weight).saturating_mul(r as Weight)) + (178_176_000 as Weight) + // Standard Error: 52_000 + .saturating_add((24_960_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -395,9 +395,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input(r: u32, ) -> Weight { - (220_304_000 as Weight) - // Standard Error: 112_000 - .saturating_add((46_804_000 as Weight).saturating_mul(r as Weight)) + (297_394_000 as Weight) + // Standard Error: 140_000 + .saturating_add((49_199_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -406,9 +406,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input_per_kb(n: u32, ) -> Weight { - (300_916_000 as Weight) - // Standard Error: 8_000 - .saturating_add((10_552_000 as Weight).saturating_mul(n as Weight)) + (374_409_000 as Weight) + // Standard Error: 3_000 + .saturating_add((11_924_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -417,9 +417,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return(r: u32, ) -> Weight { - (211_812_000 as Weight) - // Standard Error: 138_000 - .saturating_add((1_698_000 as Weight).saturating_mul(r as Weight)) + (292_278_000 as Weight) + // Standard Error: 114_000 + .saturating_add((1_474_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -428,9 +428,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return_per_kb(n: u32, ) -> Weight { - (213_994_000 as Weight) + (294_714_000 as Weight) // Standard Error: 0 - .saturating_add((176_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((230_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -441,9 +441,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts DeletionQueue (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_terminate(r: u32, ) -> Weight { - (215_173_000 as Weight) - // Standard Error: 708_000 - .saturating_add((52_509_000 as Weight).saturating_mul(r as Weight)) + (297_589_000 as Weight) + // Standard Error: 2_835_000 + .saturating_add((53_498_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((4 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -455,9 +455,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) fn seal_random(r: u32, ) -> Weight { - (219_521_000 as Weight) - // Standard Error: 171_000 - .saturating_add((156_228_000 as Weight).saturating_mul(r as Weight)) + (296_371_000 as Weight) + // Standard Error: 220_000 + .saturating_add((160_881_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -466,9 +466,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_deposit_event(r: u32, ) -> Weight { - (227_624_000 as Weight) - // Standard Error: 193_000 - .saturating_add((285_058_000 as Weight).saturating_mul(r as Weight)) + (308_401_000 as Weight) + // Standard Error: 202_000 + .saturating_add((277_771_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -478,11 +478,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: System EventTopics (r:100 w:100) fn seal_deposit_event_per_topic_and_kb(t: u32, n: u32, ) -> Weight { - (503_312_000 as Weight) - // Standard Error: 1_729_000 - .saturating_add((288_009_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 340_000 - .saturating_add((80_936_000 as Weight).saturating_mul(n as Weight)) + (625_100_000 as Weight) + // Standard Error: 2_053_000 + .saturating_add((284_765_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 404_000 + .saturating_add((85_893_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(t as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -493,17 +493,17 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_debug_message(r: u32, ) -> Weight { - (132_096_000 as Weight) - // Standard Error: 73_000 - .saturating_add((40_337_000 as Weight).saturating_mul(r as Weight)) + (182_141_000 as Weight) + // Standard Error: 134_000 + .saturating_add((41_928_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage(r: u32, ) -> Weight { - (52_622_000 as Weight) - // Standard Error: 1_006_000 - .saturating_add((404_716_000 as Weight).saturating_mul(r as Weight)) + (139_030_000 as Weight) + // Standard Error: 1_038_000 + .saturating_add((405_168_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -511,25 +511,25 @@ impl WeightInfo for SubstrateWeight { } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage_per_new_kb(n: u32, ) -> Weight { - (601_324_000 as Weight) - // Standard Error: 264_000 - .saturating_add((27_943_000 as Weight).saturating_mul(n as Weight)) + (689_591_000 as Weight) + // Standard Error: 275_000 + .saturating_add((31_438_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage_per_old_kb(n: u32, ) -> Weight { - (626_752_000 as Weight) - // Standard Error: 292_000 - .saturating_add((10_616_000 as Weight).saturating_mul(n as Weight)) + (709_965_000 as Weight) + // Standard Error: 340_000 + .saturating_add((11_182_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage(r: u32, ) -> Weight { - (80_138_000 as Weight) - // Standard Error: 933_000 - .saturating_add((382_949_000 as Weight).saturating_mul(r as Weight)) + (169_937_000 as Weight) + // Standard Error: 883_000 + .saturating_add((389_090_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -537,51 +537,51 @@ impl WeightInfo for SubstrateWeight { } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage_per_kb(n: u32, ) -> Weight { - (603_984_000 as Weight) - // Standard Error: 242_000 - .saturating_add((10_712_000 as Weight).saturating_mul(n as Weight)) + (695_589_000 as Weight) + // Standard Error: 268_000 + .saturating_add((10_530_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage(r: u32, ) -> Weight { - (113_136_000 as Weight) - // Standard Error: 635_000 - .saturating_add((324_706_000 as Weight).saturating_mul(r as Weight)) + (195_080_000 as Weight) + // Standard Error: 607_000 + .saturating_add((328_903_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage_per_kb(n: u32, ) -> Weight { - (562_781_000 as Weight) - // Standard Error: 354_000 - .saturating_add((63_275_000 as Weight).saturating_mul(n as Weight)) + (647_422_000 as Weight) + // Standard Error: 361_000 + .saturating_add((68_849_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(104 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_contains_storage(r: u32, ) -> Weight { - (112_237_000 as Weight) - // Standard Error: 655_000 - .saturating_add((296_653_000 as Weight).saturating_mul(r as Weight)) + (198_907_000 as Weight) + // Standard Error: 658_000 + .saturating_add((295_368_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_contains_storage_per_kb(n: u32, ) -> Weight { - (520_002_000 as Weight) - // Standard Error: 232_000 - .saturating_add((9_726_000 as Weight).saturating_mul(n as Weight)) + (599_284_000 as Weight) + // Standard Error: 243_000 + .saturating_add((9_923_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(104 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage(r: u32, ) -> Weight { - (87_232_000 as Weight) - // Standard Error: 920_000 - .saturating_add((415_305_000 as Weight).saturating_mul(r as Weight)) + (170_700_000 as Weight) + // Standard Error: 887_000 + .saturating_add((422_448_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -589,9 +589,9 @@ impl WeightInfo for SubstrateWeight { } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage_per_kb(n: u32, ) -> Weight { - (648_862_000 as Weight) - // Standard Error: 319_000 - .saturating_add((63_991_000 as Weight).saturating_mul(n as Weight)) + (743_584_000 as Weight) + // Standard Error: 403_000 + .saturating_add((69_763_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().writes(103 as Weight)) } @@ -600,9 +600,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_transfer(r: u32, ) -> Weight { - (99_621_000 as Weight) - // Standard Error: 1_154_000 - .saturating_add((1_732_052_000 as Weight).saturating_mul(r as Weight)) + (208_815_000 as Weight) + // Standard Error: 1_078_000 + .saturating_add((1_719_660_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -614,8 +614,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) fn seal_call(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 6_293_000 - .saturating_add((19_410_115_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 3_471_000 + .saturating_add((27_917_429_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -627,8 +627,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) fn seal_delegate_call(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 7_155_000 - .saturating_add((19_793_614_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 13_012_000 + .saturating_add((28_044_371_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads((99 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -636,14 +636,12 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts ContractInfoOf (r:101 w:101) // Storage: Contracts CodeStorage (r:2 w:0) // Storage: Timestamp Now (r:1 w:0) - fn seal_call_per_transfer_input_output_kb(t: u32, i: u32, o: u32, ) -> Weight { - (19_711_861_000 as Weight) - // Standard Error: 55_158_000 - .saturating_add((2_509_755_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 19_000 - .saturating_add((17_808_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 21_000 - .saturating_add((28_104_000 as Weight).saturating_mul(o as Weight)) + fn seal_call_per_transfer_clone_kb(t: u32, c: u32, ) -> Weight { + (15_964_304_000 as Weight) + // Standard Error: 19_327_000 + .saturating_add((1_629_626_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 8_000 + .saturating_add((11_992_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().reads((101 as Weight).saturating_mul(t as Weight))) .saturating_add(T::DbWeight::get().writes(101 as Weight)) @@ -657,38 +655,38 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts OwnerInfoOf (r:100 w:100) fn seal_instantiate(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 47_294_000 - .saturating_add((26_664_406_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 50_849_000 + .saturating_add((35_608_311_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().reads((400 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) .saturating_add(T::DbWeight::get().writes((400 as Weight).saturating_mul(r as Weight))) } - // Storage: System Account (r:102 w:102) + // Storage: System Account (r:101 w:101) // Storage: Contracts ContractInfoOf (r:101 w:101) // Storage: Contracts CodeStorage (r:2 w:1) // Storage: Timestamp Now (r:1 w:0) // Storage: Contracts AccountCounter (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) - fn seal_instantiate_per_input_output_salt_kb(i: u32, o: u32, s: u32, ) -> Weight { - (24_447_236_000 as Weight) - // Standard Error: 36_000 - .saturating_add((18_822_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 36_000 - .saturating_add((28_618_000 as Weight).saturating_mul(o as Weight)) - // Standard Error: 36_000 - .saturating_add((156_535_000 as Weight).saturating_mul(s as Weight)) - .saturating_add(T::DbWeight::get().reads(208 as Weight)) - .saturating_add(T::DbWeight::get().writes(206 as Weight)) + fn seal_instantiate_per_transfer_salt_kb(t: u32, s: u32, ) -> Weight { + (19_455_191_000 as Weight) + // Standard Error: 57_478_000 + .saturating_add((786_148_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 27_000 + .saturating_add((160_385_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(207 as Weight)) + .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(t as Weight))) + .saturating_add(T::DbWeight::get().writes(205 as Weight)) + .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(t as Weight))) } // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256(r: u32, ) -> Weight { - (216_091_000 as Weight) + (294_686_000 as Weight) // Standard Error: 123_000 - .saturating_add((79_416_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((81_172_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -697,9 +695,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256_per_kb(n: u32, ) -> Weight { - (223_253_000 as Weight) - // Standard Error: 43_000 - .saturating_add((462_629_000 as Weight).saturating_mul(n as Weight)) + (276_895_000 as Weight) + // Standard Error: 35_000 + .saturating_add((469_007_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -708,9 +706,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256(r: u32, ) -> Weight { - (217_285_000 as Weight) - // Standard Error: 147_000 - .saturating_add((91_020_000 as Weight).saturating_mul(r as Weight)) + (295_476_000 as Weight) + // Standard Error: 127_000 + .saturating_add((91_822_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -719,9 +717,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256_per_kb(n: u32, ) -> Weight { - (364_402_000 as Weight) - // Standard Error: 27_000 - .saturating_add((305_342_000 as Weight).saturating_mul(n as Weight)) + (402_456_000 as Weight) + // Standard Error: 19_000 + .saturating_add((311_103_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -730,9 +728,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256(r: u32, ) -> Weight { - (214_309_000 as Weight) - // Standard Error: 107_000 - .saturating_add((63_668_000 as Weight).saturating_mul(r as Weight)) + (296_702_000 as Weight) + // Standard Error: 142_000 + .saturating_add((64_431_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -741,9 +739,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256_per_kb(n: u32, ) -> Weight { - (306_968_000 as Weight) - // Standard Error: 13_000 - .saturating_add((118_373_000 as Weight).saturating_mul(n as Weight)) + (375_322_000 as Weight) + // Standard Error: 14_000 + .saturating_add((124_338_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -752,9 +750,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128(r: u32, ) -> Weight { - (215_434_000 as Weight) - // Standard Error: 115_000 - .saturating_add((62_560_000 as Weight).saturating_mul(r as Weight)) + (294_158_000 as Weight) + // Standard Error: 148_000 + .saturating_add((64_474_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -763,9 +761,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128_per_kb(n: u32, ) -> Weight { - (226_690_000 as Weight) - // Standard Error: 17_000 - .saturating_add((118_871_000 as Weight).saturating_mul(n as Weight)) + (390_049_000 as Weight) + // Standard Error: 16_000 + .saturating_add((124_330_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -774,9 +772,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_ecdsa_recover(r: u32, ) -> Weight { - (187_068_000 as Weight) - // Standard Error: 1_354_000 - .saturating_add((15_409_805_000 as Weight).saturating_mul(r as Weight)) + (233_346_000 as Weight) + // Standard Error: 1_355_000 + .saturating_add((15_405_070_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -793,259 +791,259 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().writes((99 as Weight).saturating_mul(r as Weight))) } fn instr_i64const(r: u32, ) -> Weight { - (74_317_000 as Weight) - // Standard Error: 1_000 - .saturating_add((597_000 as Weight).saturating_mul(r as Weight)) + (119_148_000 as Weight) + // Standard Error: 2_000 + .saturating_add((585_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64load(r: u32, ) -> Weight { - (74_303_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_311_000 as Weight).saturating_mul(r as Weight)) + (118_413_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_324_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64store(r: u32, ) -> Weight { - (74_024_000 as Weight) - // Standard Error: 0 - .saturating_add((1_431_000 as Weight).saturating_mul(r as Weight)) + (118_700_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_415_000 as Weight).saturating_mul(r as Weight)) } fn instr_select(r: u32, ) -> Weight { - (74_108_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_778_000 as Weight).saturating_mul(r as Weight)) + (118_736_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_777_000 as Weight).saturating_mul(r as Weight)) } fn instr_if(r: u32, ) -> Weight { - (73_966_000 as Weight) - // Standard Error: 0 - .saturating_add((1_888_000 as Weight).saturating_mul(r as Weight)) + (118_277_000 as Weight) + // Standard Error: 4_000 + .saturating_add((1_909_000 as Weight).saturating_mul(r as Weight)) } fn instr_br(r: u32, ) -> Weight { - (73_839_000 as Weight) - // Standard Error: 2_000 - .saturating_add((907_000 as Weight).saturating_mul(r as Weight)) + (118_360_000 as Weight) + // Standard Error: 0 + .saturating_add((895_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_if(r: u32, ) -> Weight { - (73_624_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_446_000 as Weight).saturating_mul(r as Weight)) + (118_142_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_439_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table(r: u32, ) -> Weight { - (73_169_000 as Weight) + (118_239_000 as Weight) // Standard Error: 5_000 - .saturating_add((1_602_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_553_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table_per_entry(e: u32, ) -> Weight { - (76_328_000 as Weight) + (120_801_000 as Weight) // Standard Error: 0 - .saturating_add((5_000 as Weight).saturating_mul(e as Weight)) + .saturating_add((4_000 as Weight).saturating_mul(e as Weight)) } fn instr_call(r: u32, ) -> Weight { - (74_771_000 as Weight) - // Standard Error: 22_000 - .saturating_add((17_044_000 as Weight).saturating_mul(r as Weight)) + (118_536_000 as Weight) + // Standard Error: 16_000 + .saturating_add((17_082_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect(r: u32, ) -> Weight { - (90_179_000 as Weight) - // Standard Error: 31_000 - .saturating_add((27_305_000 as Weight).saturating_mul(r as Weight)) + (130_467_000 as Weight) + // Standard Error: 30_000 + .saturating_add((28_199_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect_per_param(p: u32, ) -> Weight { - (117_977_000 as Weight) - // Standard Error: 2_000 - .saturating_add((928_000 as Weight).saturating_mul(p as Weight)) + (164_624_000 as Weight) + // Standard Error: 3_000 + .saturating_add((901_000 as Weight).saturating_mul(p as Weight)) } fn instr_local_get(r: u32, ) -> Weight { - (75_093_000 as Weight) - // Standard Error: 1_000 - .saturating_add((610_000 as Weight).saturating_mul(r as Weight)) + (119_422_000 as Weight) + // Standard Error: 2_000 + .saturating_add((617_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_set(r: u32, ) -> Weight { - (74_793_000 as Weight) - // Standard Error: 1_000 - .saturating_add((676_000 as Weight).saturating_mul(r as Weight)) + (119_747_000 as Weight) + // Standard Error: 2_000 + .saturating_add((668_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_tee(r: u32, ) -> Weight { - (74_183_000 as Weight) - // Standard Error: 2_000 - .saturating_add((913_000 as Weight).saturating_mul(r as Weight)) + (119_410_000 as Weight) + // Standard Error: 3_000 + .saturating_add((898_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_get(r: u32, ) -> Weight { - (77_079_000 as Weight) + (121_657_000 as Weight) // Standard Error: 2_000 - .saturating_add((1_156_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_160_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_set(r: u32, ) -> Weight { - (77_063_000 as Weight) + (121_531_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_363_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_367_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_current(r: u32, ) -> Weight { - (74_314_000 as Weight) + (118_340_000 as Weight) // Standard Error: 2_000 - .saturating_add((662_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((674_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_grow(r: u32, ) -> Weight { - (73_585_000 as Weight) - // Standard Error: 2_291_000 - .saturating_add((174_749_000 as Weight).saturating_mul(r as Weight)) + (118_114_000 as Weight) + // Standard Error: 194_000 + .saturating_add((229_474_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64clz(r: u32, ) -> Weight { - (74_062_000 as Weight) + (119_160_000 as Weight) // Standard Error: 2_000 - .saturating_add((905_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((890_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ctz(r: u32, ) -> Weight { - (74_121_000 as Weight) - // Standard Error: 1_000 - .saturating_add((903_000 as Weight).saturating_mul(r as Weight)) + (119_199_000 as Weight) + // Standard Error: 3_000 + .saturating_add((893_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64popcnt(r: u32, ) -> Weight { - (74_519_000 as Weight) - // Standard Error: 2_000 + (119_103_000 as Weight) + // Standard Error: 4_000 .saturating_add((885_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eqz(r: u32, ) -> Weight { - (74_357_000 as Weight) - // Standard Error: 1_000 - .saturating_add((914_000 as Weight).saturating_mul(r as Weight)) + (119_033_000 as Weight) + // Standard Error: 3_000 + .saturating_add((917_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendsi32(r: u32, ) -> Weight { - (74_101_000 as Weight) - // Standard Error: 1_000 - .saturating_add((885_000 as Weight).saturating_mul(r as Weight)) + (118_950_000 as Weight) + // Standard Error: 4_000 + .saturating_add((879_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendui32(r: u32, ) -> Weight { - (74_442_000 as Weight) - // Standard Error: 1_000 - .saturating_add((875_000 as Weight).saturating_mul(r as Weight)) + (118_534_000 as Weight) + // Standard Error: 2_000 + .saturating_add((888_000 as Weight).saturating_mul(r as Weight)) } fn instr_i32wrapi64(r: u32, ) -> Weight { - (74_247_000 as Weight) - // Standard Error: 1_000 - .saturating_add((891_000 as Weight).saturating_mul(r as Weight)) + (119_108_000 as Weight) + // Standard Error: 2_000 + .saturating_add((881_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eq(r: u32, ) -> Weight { - (74_091_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_363_000 as Weight).saturating_mul(r as Weight)) + (118_677_000 as Weight) + // Standard Error: 5_000 + .saturating_add((1_360_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ne(r: u32, ) -> Weight { - (74_178_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_358_000 as Weight).saturating_mul(r as Weight)) + (118_769_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_355_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64lts(r: u32, ) -> Weight { - (74_370_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_353_000 as Weight).saturating_mul(r as Weight)) - } - fn instr_i64ltu(r: u32, ) -> Weight { - (74_180_000 as Weight) + (118_690_000 as Weight) // Standard Error: 1_000 .saturating_add((1_356_000 as Weight).saturating_mul(r as Weight)) } + fn instr_i64ltu(r: u32, ) -> Weight { + (118_899_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_350_000 as Weight).saturating_mul(r as Weight)) + } fn instr_i64gts(r: u32, ) -> Weight { - (74_035_000 as Weight) - // Standard Error: 3_000 - .saturating_add((1_365_000 as Weight).saturating_mul(r as Weight)) + (118_519_000 as Weight) + // Standard Error: 6_000 + .saturating_add((1_376_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gtu(r: u32, ) -> Weight { - (74_538_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_357_000 as Weight).saturating_mul(r as Weight)) + (119_315_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_347_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64les(r: u32, ) -> Weight { - (74_035_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_368_000 as Weight).saturating_mul(r as Weight)) + (118_171_000 as Weight) + // Standard Error: 5_000 + .saturating_add((1_377_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64leu(r: u32, ) -> Weight { - (74_399_000 as Weight) - // Standard Error: 8_000 - .saturating_add((1_362_000 as Weight).saturating_mul(r as Weight)) + (118_581_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_367_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ges(r: u32, ) -> Weight { - (73_987_000 as Weight) + (118_673_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_364_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_355_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64geu(r: u32, ) -> Weight { - (74_017_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_366_000 as Weight).saturating_mul(r as Weight)) + (118_618_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_357_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64add(r: u32, ) -> Weight { - (74_271_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_330_000 as Weight).saturating_mul(r as Weight)) + (118_569_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_335_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64sub(r: u32, ) -> Weight { - (74_016_000 as Weight) - // Standard Error: 0 - .saturating_add((1_345_000 as Weight).saturating_mul(r as Weight)) + (118_261_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_363_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64mul(r: u32, ) -> Weight { - (74_063_000 as Weight) - // Standard Error: 1_000 + (118_542_000 as Weight) + // Standard Error: 2_000 .saturating_add((1_338_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divs(r: u32, ) -> Weight { - (74_094_000 as Weight) - // Standard Error: 1_000 - .saturating_add((2_002_000 as Weight).saturating_mul(r as Weight)) + (118_648_000 as Weight) + // Standard Error: 4_000 + .saturating_add((1_993_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divu(r: u32, ) -> Weight { - (73_957_000 as Weight) - // Standard Error: 2_000 - .saturating_add((2_045_000 as Weight).saturating_mul(r as Weight)) + (118_378_000 as Weight) + // Standard Error: 0 + .saturating_add((2_057_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rems(r: u32, ) -> Weight { - (74_067_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_975_000 as Weight).saturating_mul(r as Weight)) + (118_813_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_995_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64remu(r: u32, ) -> Weight { - (74_092_000 as Weight) - // Standard Error: 1_000 - .saturating_add((2_035_000 as Weight).saturating_mul(r as Weight)) + (118_697_000 as Weight) + // Standard Error: 2_000 + .saturating_add((2_025_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64and(r: u32, ) -> Weight { - (74_059_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_338_000 as Weight).saturating_mul(r as Weight)) + (118_838_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_332_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64or(r: u32, ) -> Weight { - (74_122_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_335_000 as Weight).saturating_mul(r as Weight)) + (118_641_000 as Weight) + // Standard Error: 4_000 + .saturating_add((1_347_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64xor(r: u32, ) -> Weight { - (74_296_000 as Weight) + (118_551_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_333_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_338_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shl(r: u32, ) -> Weight { - (73_810_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_368_000 as Weight).saturating_mul(r as Weight)) + (118_603_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_352_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shrs(r: u32, ) -> Weight { - (74_101_000 as Weight) - // Standard Error: 9_000 - .saturating_add((1_407_000 as Weight).saturating_mul(r as Weight)) + (118_885_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_345_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shru(r: u32, ) -> Weight { - (74_076_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_353_000 as Weight).saturating_mul(r as Weight)) + (118_602_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_354_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotl(r: u32, ) -> Weight { - (74_082_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_354_000 as Weight).saturating_mul(r as Weight)) + (118_733_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_349_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotr(r: u32, ) -> Weight { - (74_054_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_355_000 as Weight).saturating_mul(r as Weight)) + (118_920_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_348_000 as Weight).saturating_mul(r as Weight)) } } @@ -1053,32 +1051,32 @@ impl WeightInfo for SubstrateWeight { impl WeightInfo for () { // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize() -> Weight { - (1_590_000 as Weight) + (1_560_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn on_initialize_per_trie_key(k: u32, ) -> Weight { - (9_975_000 as Weight) + (7_843_000 as Weight) // Standard Error: 0 - .saturating_add((724_000 as Weight).saturating_mul(k as Weight)) + .saturating_add((749_000 as Weight).saturating_mul(k as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) } // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize_per_queue_item(q: u32, ) -> Weight { - (7_415_000 as Weight) - // Standard Error: 4_000 - .saturating_add((2_303_000 as Weight).saturating_mul(q as Weight)) + (3_228_000 as Weight) + // Standard Error: 5_000 + .saturating_add((2_257_000 as Weight).saturating_mul(q as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Contracts PristineCode (r:1 w:0) // Storage: Contracts CodeStorage (r:0 w:1) fn reinstrument(c: u32, ) -> Weight { - (18_519_000 as Weight) - // Standard Error: 36_000 - .saturating_add((66_661_000 as Weight).saturating_mul(c as Weight)) + (20_531_000 as Weight) + // Standard Error: 34_000 + .saturating_add((66_014_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1087,9 +1085,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call_with_code_kb(c: u32, ) -> Weight { - (210_319_000 as Weight) - // Standard Error: 41_000 - .saturating_add((54_802_000 as Weight).saturating_mul(c as Weight)) + (295_703_000 as Weight) + // Standard Error: 53_000 + .saturating_add((57_661_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -1101,11 +1099,11 @@ impl WeightInfo for () { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn instantiate_with_code(c: u32, s: u32, ) -> Weight { - (220_394_000 as Weight) - // Standard Error: 129_000 - .saturating_add((145_155_000 as Weight).saturating_mul(c as Weight)) - // Standard Error: 8_000 - .saturating_add((1_741_000 as Weight).saturating_mul(s as Weight)) + (332_572_000 as Weight) + // Standard Error: 125_000 + .saturating_add((149_095_000 as Weight).saturating_mul(c as Weight)) + // Standard Error: 7_000 + .saturating_add((1_779_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } @@ -1116,9 +1114,9 @@ impl WeightInfo for () { // Storage: System Account (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn instantiate(s: u32, ) -> Weight { - (171_438_000 as Weight) + (222_992_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_721_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((1_759_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } @@ -1127,7 +1125,7 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call() -> Weight { - (139_529_000 as Weight) + (189_003_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -1135,9 +1133,9 @@ impl WeightInfo for () { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn upload_code(c: u32, ) -> Weight { - (51_040_000 as Weight) - // Standard Error: 38_000 - .saturating_add((65_886_000 as Weight).saturating_mul(c as Weight)) + (52_521_000 as Weight) + // Standard Error: 36_000 + .saturating_add((66_486_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -1145,7 +1143,7 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:0 w:1) // Storage: Contracts PristineCode (r:0 w:1) fn remove_code() -> Weight { - (24_347_000 as Weight) + (24_705_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -1154,9 +1152,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_caller(r: u32, ) -> Weight { - (217_164_000 as Weight) - // Standard Error: 89_000 - .saturating_add((48_023_000 as Weight).saturating_mul(r as Weight)) + (300_165_000 as Weight) + // Standard Error: 125_000 + .saturating_add((49_828_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1165,9 +1163,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_is_contract(r: u32, ) -> Weight { - (81_537_000 as Weight) - // Standard Error: 847_000 - .saturating_add((367_429_000 as Weight).saturating_mul(r as Weight)) + (179_488_000 as Weight) + // Standard Error: 718_000 + .saturating_add((375_855_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1177,9 +1175,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_caller_is_origin(r: u32, ) -> Weight { - (214_798_000 as Weight) - // Standard Error: 56_000 - .saturating_add((21_100_000 as Weight).saturating_mul(r as Weight)) + (295_198_000 as Weight) + // Standard Error: 79_000 + .saturating_add((21_948_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1188,9 +1186,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_address(r: u32, ) -> Weight { - (216_615_000 as Weight) - // Standard Error: 75_000 - .saturating_add((48_054_000 as Weight).saturating_mul(r as Weight)) + (300_366_000 as Weight) + // Standard Error: 111_000 + .saturating_add((49_435_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1199,9 +1197,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas_left(r: u32, ) -> Weight { - (218_034_000 as Weight) + (299_800_000 as Weight) // Standard Error: 87_000 - .saturating_add((47_594_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((49_002_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1210,9 +1208,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_balance(r: u32, ) -> Weight { - (221_980_000 as Weight) - // Standard Error: 135_000 - .saturating_add((135_618_000 as Weight).saturating_mul(r as Weight)) + (303_057_000 as Weight) + // Standard Error: 175_000 + .saturating_add((139_293_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1221,9 +1219,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_value_transferred(r: u32, ) -> Weight { - (217_623_000 as Weight) - // Standard Error: 86_000 - .saturating_add((47_656_000 as Weight).saturating_mul(r as Weight)) + (299_754_000 as Weight) + // Standard Error: 93_000 + .saturating_add((48_945_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1232,9 +1230,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_minimum_balance(r: u32, ) -> Weight { - (216_826_000 as Weight) - // Standard Error: 88_000 - .saturating_add((47_644_000 as Weight).saturating_mul(r as Weight)) + (302_229_000 as Weight) + // Standard Error: 128_000 + .saturating_add((49_007_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1243,9 +1241,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_block_number(r: u32, ) -> Weight { - (219_487_000 as Weight) - // Standard Error: 90_000 - .saturating_add((47_167_000 as Weight).saturating_mul(r as Weight)) + (300_772_000 as Weight) + // Standard Error: 114_000 + .saturating_add((48_794_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1254,9 +1252,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_now(r: u32, ) -> Weight { - (218_953_000 as Weight) - // Standard Error: 95_000 - .saturating_add((47_458_000 as Weight).saturating_mul(r as Weight)) + (301_936_000 as Weight) + // Standard Error: 119_000 + .saturating_add((48_839_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1266,9 +1264,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0) fn seal_weight_to_fee(r: u32, ) -> Weight { - (220_132_000 as Weight) - // Standard Error: 144_000 - .saturating_add((120_373_000 as Weight).saturating_mul(r as Weight)) + (304_935_000 as Weight) + // Standard Error: 146_000 + .saturating_add((121_871_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1277,9 +1275,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas(r: u32, ) -> Weight { - (127_458_000 as Weight) - // Standard Error: 56_000 - .saturating_add((24_015_000 as Weight).saturating_mul(r as Weight)) + (178_176_000 as Weight) + // Standard Error: 52_000 + .saturating_add((24_960_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1288,9 +1286,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input(r: u32, ) -> Weight { - (220_304_000 as Weight) - // Standard Error: 112_000 - .saturating_add((46_804_000 as Weight).saturating_mul(r as Weight)) + (297_394_000 as Weight) + // Standard Error: 140_000 + .saturating_add((49_199_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1299,9 +1297,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input_per_kb(n: u32, ) -> Weight { - (300_916_000 as Weight) - // Standard Error: 8_000 - .saturating_add((10_552_000 as Weight).saturating_mul(n as Weight)) + (374_409_000 as Weight) + // Standard Error: 3_000 + .saturating_add((11_924_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1310,9 +1308,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return(r: u32, ) -> Weight { - (211_812_000 as Weight) - // Standard Error: 138_000 - .saturating_add((1_698_000 as Weight).saturating_mul(r as Weight)) + (292_278_000 as Weight) + // Standard Error: 114_000 + .saturating_add((1_474_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1321,9 +1319,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return_per_kb(n: u32, ) -> Weight { - (213_994_000 as Weight) + (294_714_000 as Weight) // Standard Error: 0 - .saturating_add((176_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((230_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1334,9 +1332,9 @@ impl WeightInfo for () { // Storage: Contracts DeletionQueue (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_terminate(r: u32, ) -> Weight { - (215_173_000 as Weight) - // Standard Error: 708_000 - .saturating_add((52_509_000 as Weight).saturating_mul(r as Weight)) + (297_589_000 as Weight) + // Standard Error: 2_835_000 + .saturating_add((53_498_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((4 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1348,9 +1346,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) fn seal_random(r: u32, ) -> Weight { - (219_521_000 as Weight) - // Standard Error: 171_000 - .saturating_add((156_228_000 as Weight).saturating_mul(r as Weight)) + (296_371_000 as Weight) + // Standard Error: 220_000 + .saturating_add((160_881_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1359,9 +1357,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_deposit_event(r: u32, ) -> Weight { - (227_624_000 as Weight) - // Standard Error: 193_000 - .saturating_add((285_058_000 as Weight).saturating_mul(r as Weight)) + (308_401_000 as Weight) + // Standard Error: 202_000 + .saturating_add((277_771_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1371,11 +1369,11 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: System EventTopics (r:100 w:100) fn seal_deposit_event_per_topic_and_kb(t: u32, n: u32, ) -> Weight { - (503_312_000 as Weight) - // Standard Error: 1_729_000 - .saturating_add((288_009_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 340_000 - .saturating_add((80_936_000 as Weight).saturating_mul(n as Weight)) + (625_100_000 as Weight) + // Standard Error: 2_053_000 + .saturating_add((284_765_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 404_000 + .saturating_add((85_893_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(t as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1386,17 +1384,17 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_debug_message(r: u32, ) -> Weight { - (132_096_000 as Weight) - // Standard Error: 73_000 - .saturating_add((40_337_000 as Weight).saturating_mul(r as Weight)) + (182_141_000 as Weight) + // Standard Error: 134_000 + .saturating_add((41_928_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage(r: u32, ) -> Weight { - (52_622_000 as Weight) - // Standard Error: 1_006_000 - .saturating_add((404_716_000 as Weight).saturating_mul(r as Weight)) + (139_030_000 as Weight) + // Standard Error: 1_038_000 + .saturating_add((405_168_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1404,25 +1402,25 @@ impl WeightInfo for () { } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage_per_new_kb(n: u32, ) -> Weight { - (601_324_000 as Weight) - // Standard Error: 264_000 - .saturating_add((27_943_000 as Weight).saturating_mul(n as Weight)) + (689_591_000 as Weight) + // Standard Error: 275_000 + .saturating_add((31_438_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage_per_old_kb(n: u32, ) -> Weight { - (626_752_000 as Weight) - // Standard Error: 292_000 - .saturating_add((10_616_000 as Weight).saturating_mul(n as Weight)) + (709_965_000 as Weight) + // Standard Error: 340_000 + .saturating_add((11_182_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage(r: u32, ) -> Weight { - (80_138_000 as Weight) - // Standard Error: 933_000 - .saturating_add((382_949_000 as Weight).saturating_mul(r as Weight)) + (169_937_000 as Weight) + // Standard Error: 883_000 + .saturating_add((389_090_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -1430,51 +1428,51 @@ impl WeightInfo for () { } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage_per_kb(n: u32, ) -> Weight { - (603_984_000 as Weight) - // Standard Error: 242_000 - .saturating_add((10_712_000 as Weight).saturating_mul(n as Weight)) + (695_589_000 as Weight) + // Standard Error: 268_000 + .saturating_add((10_530_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage(r: u32, ) -> Weight { - (113_136_000 as Weight) - // Standard Error: 635_000 - .saturating_add((324_706_000 as Weight).saturating_mul(r as Weight)) + (195_080_000 as Weight) + // Standard Error: 607_000 + .saturating_add((328_903_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage_per_kb(n: u32, ) -> Weight { - (562_781_000 as Weight) - // Standard Error: 354_000 - .saturating_add((63_275_000 as Weight).saturating_mul(n as Weight)) + (647_422_000 as Weight) + // Standard Error: 361_000 + .saturating_add((68_849_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(104 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_contains_storage(r: u32, ) -> Weight { - (112_237_000 as Weight) - // Standard Error: 655_000 - .saturating_add((296_653_000 as Weight).saturating_mul(r as Weight)) + (198_907_000 as Weight) + // Standard Error: 658_000 + .saturating_add((295_368_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_contains_storage_per_kb(n: u32, ) -> Weight { - (520_002_000 as Weight) - // Standard Error: 232_000 - .saturating_add((9_726_000 as Weight).saturating_mul(n as Weight)) + (599_284_000 as Weight) + // Standard Error: 243_000 + .saturating_add((9_923_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(104 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage(r: u32, ) -> Weight { - (87_232_000 as Weight) - // Standard Error: 920_000 - .saturating_add((415_305_000 as Weight).saturating_mul(r as Weight)) + (170_700_000 as Weight) + // Standard Error: 887_000 + .saturating_add((422_448_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -1482,9 +1480,9 @@ impl WeightInfo for () { } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage_per_kb(n: u32, ) -> Weight { - (648_862_000 as Weight) - // Standard Error: 319_000 - .saturating_add((63_991_000 as Weight).saturating_mul(n as Weight)) + (743_584_000 as Weight) + // Standard Error: 403_000 + .saturating_add((69_763_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().writes(103 as Weight)) } @@ -1493,9 +1491,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_transfer(r: u32, ) -> Weight { - (99_621_000 as Weight) - // Standard Error: 1_154_000 - .saturating_add((1_732_052_000 as Weight).saturating_mul(r as Weight)) + (208_815_000 as Weight) + // Standard Error: 1_078_000 + .saturating_add((1_719_660_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) @@ -1507,8 +1505,8 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) fn seal_call(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 6_293_000 - .saturating_add((19_410_115_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 3_471_000 + .saturating_add((27_917_429_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1520,8 +1518,8 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) fn seal_delegate_call(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 7_155_000 - .saturating_add((19_793_614_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 13_012_000 + .saturating_add((28_044_371_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads((99 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1529,14 +1527,12 @@ impl WeightInfo for () { // Storage: Contracts ContractInfoOf (r:101 w:101) // Storage: Contracts CodeStorage (r:2 w:0) // Storage: Timestamp Now (r:1 w:0) - fn seal_call_per_transfer_input_output_kb(t: u32, i: u32, o: u32, ) -> Weight { - (19_711_861_000 as Weight) - // Standard Error: 55_158_000 - .saturating_add((2_509_755_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 19_000 - .saturating_add((17_808_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 21_000 - .saturating_add((28_104_000 as Weight).saturating_mul(o as Weight)) + fn seal_call_per_transfer_clone_kb(t: u32, c: u32, ) -> Weight { + (15_964_304_000 as Weight) + // Standard Error: 19_327_000 + .saturating_add((1_629_626_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 8_000 + .saturating_add((11_992_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().reads((101 as Weight).saturating_mul(t as Weight))) .saturating_add(RocksDbWeight::get().writes(101 as Weight)) @@ -1550,38 +1546,38 @@ impl WeightInfo for () { // Storage: Contracts OwnerInfoOf (r:100 w:100) fn seal_instantiate(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 47_294_000 - .saturating_add((26_664_406_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 50_849_000 + .saturating_add((35_608_311_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().reads((400 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) .saturating_add(RocksDbWeight::get().writes((400 as Weight).saturating_mul(r as Weight))) } - // Storage: System Account (r:102 w:102) + // Storage: System Account (r:101 w:101) // Storage: Contracts ContractInfoOf (r:101 w:101) // Storage: Contracts CodeStorage (r:2 w:1) // Storage: Timestamp Now (r:1 w:0) // Storage: Contracts AccountCounter (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) - fn seal_instantiate_per_input_output_salt_kb(i: u32, o: u32, s: u32, ) -> Weight { - (24_447_236_000 as Weight) - // Standard Error: 36_000 - .saturating_add((18_822_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 36_000 - .saturating_add((28_618_000 as Weight).saturating_mul(o as Weight)) - // Standard Error: 36_000 - .saturating_add((156_535_000 as Weight).saturating_mul(s as Weight)) - .saturating_add(RocksDbWeight::get().reads(208 as Weight)) - .saturating_add(RocksDbWeight::get().writes(206 as Weight)) + fn seal_instantiate_per_transfer_salt_kb(t: u32, s: u32, ) -> Weight { + (19_455_191_000 as Weight) + // Standard Error: 57_478_000 + .saturating_add((786_148_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 27_000 + .saturating_add((160_385_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(RocksDbWeight::get().reads(207 as Weight)) + .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(t as Weight))) + .saturating_add(RocksDbWeight::get().writes(205 as Weight)) + .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(t as Weight))) } // Storage: System Account (r:1 w:0) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256(r: u32, ) -> Weight { - (216_091_000 as Weight) + (294_686_000 as Weight) // Standard Error: 123_000 - .saturating_add((79_416_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((81_172_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1590,9 +1586,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256_per_kb(n: u32, ) -> Weight { - (223_253_000 as Weight) - // Standard Error: 43_000 - .saturating_add((462_629_000 as Weight).saturating_mul(n as Weight)) + (276_895_000 as Weight) + // Standard Error: 35_000 + .saturating_add((469_007_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1601,9 +1597,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256(r: u32, ) -> Weight { - (217_285_000 as Weight) - // Standard Error: 147_000 - .saturating_add((91_020_000 as Weight).saturating_mul(r as Weight)) + (295_476_000 as Weight) + // Standard Error: 127_000 + .saturating_add((91_822_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1612,9 +1608,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256_per_kb(n: u32, ) -> Weight { - (364_402_000 as Weight) - // Standard Error: 27_000 - .saturating_add((305_342_000 as Weight).saturating_mul(n as Weight)) + (402_456_000 as Weight) + // Standard Error: 19_000 + .saturating_add((311_103_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1623,9 +1619,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256(r: u32, ) -> Weight { - (214_309_000 as Weight) - // Standard Error: 107_000 - .saturating_add((63_668_000 as Weight).saturating_mul(r as Weight)) + (296_702_000 as Weight) + // Standard Error: 142_000 + .saturating_add((64_431_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1634,9 +1630,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256_per_kb(n: u32, ) -> Weight { - (306_968_000 as Weight) - // Standard Error: 13_000 - .saturating_add((118_373_000 as Weight).saturating_mul(n as Weight)) + (375_322_000 as Weight) + // Standard Error: 14_000 + .saturating_add((124_338_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1645,9 +1641,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128(r: u32, ) -> Weight { - (215_434_000 as Weight) - // Standard Error: 115_000 - .saturating_add((62_560_000 as Weight).saturating_mul(r as Weight)) + (294_158_000 as Weight) + // Standard Error: 148_000 + .saturating_add((64_474_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1656,9 +1652,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128_per_kb(n: u32, ) -> Weight { - (226_690_000 as Weight) - // Standard Error: 17_000 - .saturating_add((118_871_000 as Weight).saturating_mul(n as Weight)) + (390_049_000 as Weight) + // Standard Error: 16_000 + .saturating_add((124_330_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1667,9 +1663,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_ecdsa_recover(r: u32, ) -> Weight { - (187_068_000 as Weight) - // Standard Error: 1_354_000 - .saturating_add((15_409_805_000 as Weight).saturating_mul(r as Weight)) + (233_346_000 as Weight) + // Standard Error: 1_355_000 + .saturating_add((15_405_070_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1686,258 +1682,258 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().writes((99 as Weight).saturating_mul(r as Weight))) } fn instr_i64const(r: u32, ) -> Weight { - (74_317_000 as Weight) - // Standard Error: 1_000 - .saturating_add((597_000 as Weight).saturating_mul(r as Weight)) + (119_148_000 as Weight) + // Standard Error: 2_000 + .saturating_add((585_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64load(r: u32, ) -> Weight { - (74_303_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_311_000 as Weight).saturating_mul(r as Weight)) + (118_413_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_324_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64store(r: u32, ) -> Weight { - (74_024_000 as Weight) - // Standard Error: 0 - .saturating_add((1_431_000 as Weight).saturating_mul(r as Weight)) + (118_700_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_415_000 as Weight).saturating_mul(r as Weight)) } fn instr_select(r: u32, ) -> Weight { - (74_108_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_778_000 as Weight).saturating_mul(r as Weight)) + (118_736_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_777_000 as Weight).saturating_mul(r as Weight)) } fn instr_if(r: u32, ) -> Weight { - (73_966_000 as Weight) - // Standard Error: 0 - .saturating_add((1_888_000 as Weight).saturating_mul(r as Weight)) + (118_277_000 as Weight) + // Standard Error: 4_000 + .saturating_add((1_909_000 as Weight).saturating_mul(r as Weight)) } fn instr_br(r: u32, ) -> Weight { - (73_839_000 as Weight) - // Standard Error: 2_000 - .saturating_add((907_000 as Weight).saturating_mul(r as Weight)) + (118_360_000 as Weight) + // Standard Error: 0 + .saturating_add((895_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_if(r: u32, ) -> Weight { - (73_624_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_446_000 as Weight).saturating_mul(r as Weight)) + (118_142_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_439_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table(r: u32, ) -> Weight { - (73_169_000 as Weight) + (118_239_000 as Weight) // Standard Error: 5_000 - .saturating_add((1_602_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_553_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table_per_entry(e: u32, ) -> Weight { - (76_328_000 as Weight) + (120_801_000 as Weight) // Standard Error: 0 - .saturating_add((5_000 as Weight).saturating_mul(e as Weight)) + .saturating_add((4_000 as Weight).saturating_mul(e as Weight)) } fn instr_call(r: u32, ) -> Weight { - (74_771_000 as Weight) - // Standard Error: 22_000 - .saturating_add((17_044_000 as Weight).saturating_mul(r as Weight)) + (118_536_000 as Weight) + // Standard Error: 16_000 + .saturating_add((17_082_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect(r: u32, ) -> Weight { - (90_179_000 as Weight) - // Standard Error: 31_000 - .saturating_add((27_305_000 as Weight).saturating_mul(r as Weight)) + (130_467_000 as Weight) + // Standard Error: 30_000 + .saturating_add((28_199_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect_per_param(p: u32, ) -> Weight { - (117_977_000 as Weight) - // Standard Error: 2_000 - .saturating_add((928_000 as Weight).saturating_mul(p as Weight)) + (164_624_000 as Weight) + // Standard Error: 3_000 + .saturating_add((901_000 as Weight).saturating_mul(p as Weight)) } fn instr_local_get(r: u32, ) -> Weight { - (75_093_000 as Weight) - // Standard Error: 1_000 - .saturating_add((610_000 as Weight).saturating_mul(r as Weight)) + (119_422_000 as Weight) + // Standard Error: 2_000 + .saturating_add((617_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_set(r: u32, ) -> Weight { - (74_793_000 as Weight) - // Standard Error: 1_000 - .saturating_add((676_000 as Weight).saturating_mul(r as Weight)) + (119_747_000 as Weight) + // Standard Error: 2_000 + .saturating_add((668_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_tee(r: u32, ) -> Weight { - (74_183_000 as Weight) - // Standard Error: 2_000 - .saturating_add((913_000 as Weight).saturating_mul(r as Weight)) + (119_410_000 as Weight) + // Standard Error: 3_000 + .saturating_add((898_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_get(r: u32, ) -> Weight { - (77_079_000 as Weight) + (121_657_000 as Weight) // Standard Error: 2_000 - .saturating_add((1_156_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_160_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_set(r: u32, ) -> Weight { - (77_063_000 as Weight) + (121_531_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_363_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_367_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_current(r: u32, ) -> Weight { - (74_314_000 as Weight) + (118_340_000 as Weight) // Standard Error: 2_000 - .saturating_add((662_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((674_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_grow(r: u32, ) -> Weight { - (73_585_000 as Weight) - // Standard Error: 2_291_000 - .saturating_add((174_749_000 as Weight).saturating_mul(r as Weight)) + (118_114_000 as Weight) + // Standard Error: 194_000 + .saturating_add((229_474_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64clz(r: u32, ) -> Weight { - (74_062_000 as Weight) + (119_160_000 as Weight) // Standard Error: 2_000 - .saturating_add((905_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((890_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ctz(r: u32, ) -> Weight { - (74_121_000 as Weight) - // Standard Error: 1_000 - .saturating_add((903_000 as Weight).saturating_mul(r as Weight)) + (119_199_000 as Weight) + // Standard Error: 3_000 + .saturating_add((893_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64popcnt(r: u32, ) -> Weight { - (74_519_000 as Weight) - // Standard Error: 2_000 + (119_103_000 as Weight) + // Standard Error: 4_000 .saturating_add((885_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eqz(r: u32, ) -> Weight { - (74_357_000 as Weight) - // Standard Error: 1_000 - .saturating_add((914_000 as Weight).saturating_mul(r as Weight)) + (119_033_000 as Weight) + // Standard Error: 3_000 + .saturating_add((917_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendsi32(r: u32, ) -> Weight { - (74_101_000 as Weight) - // Standard Error: 1_000 - .saturating_add((885_000 as Weight).saturating_mul(r as Weight)) + (118_950_000 as Weight) + // Standard Error: 4_000 + .saturating_add((879_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendui32(r: u32, ) -> Weight { - (74_442_000 as Weight) - // Standard Error: 1_000 - .saturating_add((875_000 as Weight).saturating_mul(r as Weight)) + (118_534_000 as Weight) + // Standard Error: 2_000 + .saturating_add((888_000 as Weight).saturating_mul(r as Weight)) } fn instr_i32wrapi64(r: u32, ) -> Weight { - (74_247_000 as Weight) - // Standard Error: 1_000 - .saturating_add((891_000 as Weight).saturating_mul(r as Weight)) + (119_108_000 as Weight) + // Standard Error: 2_000 + .saturating_add((881_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eq(r: u32, ) -> Weight { - (74_091_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_363_000 as Weight).saturating_mul(r as Weight)) + (118_677_000 as Weight) + // Standard Error: 5_000 + .saturating_add((1_360_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ne(r: u32, ) -> Weight { - (74_178_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_358_000 as Weight).saturating_mul(r as Weight)) + (118_769_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_355_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64lts(r: u32, ) -> Weight { - (74_370_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_353_000 as Weight).saturating_mul(r as Weight)) - } - fn instr_i64ltu(r: u32, ) -> Weight { - (74_180_000 as Weight) + (118_690_000 as Weight) // Standard Error: 1_000 .saturating_add((1_356_000 as Weight).saturating_mul(r as Weight)) } + fn instr_i64ltu(r: u32, ) -> Weight { + (118_899_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_350_000 as Weight).saturating_mul(r as Weight)) + } fn instr_i64gts(r: u32, ) -> Weight { - (74_035_000 as Weight) - // Standard Error: 3_000 - .saturating_add((1_365_000 as Weight).saturating_mul(r as Weight)) + (118_519_000 as Weight) + // Standard Error: 6_000 + .saturating_add((1_376_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gtu(r: u32, ) -> Weight { - (74_538_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_357_000 as Weight).saturating_mul(r as Weight)) + (119_315_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_347_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64les(r: u32, ) -> Weight { - (74_035_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_368_000 as Weight).saturating_mul(r as Weight)) + (118_171_000 as Weight) + // Standard Error: 5_000 + .saturating_add((1_377_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64leu(r: u32, ) -> Weight { - (74_399_000 as Weight) - // Standard Error: 8_000 - .saturating_add((1_362_000 as Weight).saturating_mul(r as Weight)) + (118_581_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_367_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ges(r: u32, ) -> Weight { - (73_987_000 as Weight) + (118_673_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_364_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_355_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64geu(r: u32, ) -> Weight { - (74_017_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_366_000 as Weight).saturating_mul(r as Weight)) + (118_618_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_357_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64add(r: u32, ) -> Weight { - (74_271_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_330_000 as Weight).saturating_mul(r as Weight)) + (118_569_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_335_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64sub(r: u32, ) -> Weight { - (74_016_000 as Weight) - // Standard Error: 0 - .saturating_add((1_345_000 as Weight).saturating_mul(r as Weight)) + (118_261_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_363_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64mul(r: u32, ) -> Weight { - (74_063_000 as Weight) - // Standard Error: 1_000 + (118_542_000 as Weight) + // Standard Error: 2_000 .saturating_add((1_338_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divs(r: u32, ) -> Weight { - (74_094_000 as Weight) - // Standard Error: 1_000 - .saturating_add((2_002_000 as Weight).saturating_mul(r as Weight)) + (118_648_000 as Weight) + // Standard Error: 4_000 + .saturating_add((1_993_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divu(r: u32, ) -> Weight { - (73_957_000 as Weight) - // Standard Error: 2_000 - .saturating_add((2_045_000 as Weight).saturating_mul(r as Weight)) + (118_378_000 as Weight) + // Standard Error: 0 + .saturating_add((2_057_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rems(r: u32, ) -> Weight { - (74_067_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_975_000 as Weight).saturating_mul(r as Weight)) + (118_813_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_995_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64remu(r: u32, ) -> Weight { - (74_092_000 as Weight) - // Standard Error: 1_000 - .saturating_add((2_035_000 as Weight).saturating_mul(r as Weight)) + (118_697_000 as Weight) + // Standard Error: 2_000 + .saturating_add((2_025_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64and(r: u32, ) -> Weight { - (74_059_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_338_000 as Weight).saturating_mul(r as Weight)) + (118_838_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_332_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64or(r: u32, ) -> Weight { - (74_122_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_335_000 as Weight).saturating_mul(r as Weight)) + (118_641_000 as Weight) + // Standard Error: 4_000 + .saturating_add((1_347_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64xor(r: u32, ) -> Weight { - (74_296_000 as Weight) + (118_551_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_333_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_338_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shl(r: u32, ) -> Weight { - (73_810_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_368_000 as Weight).saturating_mul(r as Weight)) + (118_603_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_352_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shrs(r: u32, ) -> Weight { - (74_101_000 as Weight) - // Standard Error: 9_000 - .saturating_add((1_407_000 as Weight).saturating_mul(r as Weight)) + (118_885_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_345_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shru(r: u32, ) -> Weight { - (74_076_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_353_000 as Weight).saturating_mul(r as Weight)) + (118_602_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_354_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotl(r: u32, ) -> Weight { - (74_082_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_354_000 as Weight).saturating_mul(r as Weight)) + (118_733_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_349_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotr(r: u32, ) -> Weight { - (74_054_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_355_000 as Weight).saturating_mul(r as Weight)) + (118_920_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_348_000 as Weight).saturating_mul(r as Weight)) } } From fd2c39705b5781100d6b3628a7e8cf5fed6d340d Mon Sep 17 00:00:00 2001 From: Koute Date: Tue, 15 Feb 2022 20:53:45 +0900 Subject: [PATCH 495/695] Enable the `parking_lot` feature for `tokio` (#10855) --- bin/node/cli/Cargo.toml | 2 +- client/cli/Cargo.toml | 2 +- client/rpc-servers/Cargo.toml | 2 +- client/service/Cargo.toml | 2 +- utils/prometheus/Cargo.toml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index 4b14fe31e5a5..74d62ba78c2a 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -126,7 +126,7 @@ platforms = "2.0" async-std = { version = "1.10.0", features = ["attributes"] } soketto = "0.4.2" criterion = { version = "0.3.5", features = ["async_tokio"] } -tokio = { version = "1.15", features = ["macros", "time"] } +tokio = { version = "1.15", features = ["macros", "time", "parking_lot"] } jsonrpsee-ws-client = "0.4.1" wait-timeout = "0.2" remote-externalities = { path = "../../../utils/frame/remote-externalities" } diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index 5375400056fa..3fd65d23eb88 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -28,7 +28,7 @@ serde = "1.0.136" serde_json = "1.0.74" thiserror = "1.0.30" tiny-bip39 = "0.8.2" -tokio = { version = "1.15", features = ["signal", "rt-multi-thread"] } +tokio = { version = "1.15", features = ["signal", "rt-multi-thread", "parking_lot"] } parity-scale-codec = "2.3.1" sc-client-api = { version = "4.0.0-dev", path = "../api" } diff --git a/client/rpc-servers/Cargo.toml b/client/rpc-servers/Cargo.toml index 4246168c3e66..954bf602f85d 100644 --- a/client/rpc-servers/Cargo.toml +++ b/client/rpc-servers/Cargo.toml @@ -19,7 +19,7 @@ pubsub = { package = "jsonrpc-pubsub", version = "18.0.0" } log = "0.4.8" prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.10.0-dev"} serde_json = "1.0.74" -tokio = "1.15" +tokio = { version = "1.15", features = ["parking_lot"] } http = { package = "jsonrpc-http-server", version = "18.0.0" } ipc = { package = "jsonrpc-ipc-server", version = "18.0.0" } ws = { package = "jsonrpc-ws-server", version = "18.0.0" } diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index 8424fe31a810..55ca01a2284a 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -78,7 +78,7 @@ parity-util-mem = { version = "0.10.2", default-features = false, features = [ "primitive-types", ] } async-trait = "0.1.50" -tokio = { version = "1.15", features = ["time", "rt-multi-thread"] } +tokio = { version = "1.15", features = ["time", "rt-multi-thread", "parking_lot"] } tempfile = "3.1.0" directories = "4.0.1" diff --git a/utils/prometheus/Cargo.toml b/utils/prometheus/Cargo.toml index 27b5f94305fd..264cc44d1602 100644 --- a/utils/prometheus/Cargo.toml +++ b/utils/prometheus/Cargo.toml @@ -18,7 +18,7 @@ prometheus = { version = "0.13.0", default-features = false } futures-util = { version = "0.3.19", default-features = false, features = ["io"] } thiserror = "1.0" async-std = { version = "1.10.0", features = ["unstable"] } -tokio = "1.15" +tokio = { version = "1.15", features = ["parking_lot"] } hyper = { version = "0.14.16", default-features = false, features = ["http1", "server", "tcp"] } [dev-dependencies] From b359b495e0f6aaf7b31e8809d08ebc7348d4f04b Mon Sep 17 00:00:00 2001 From: Alexander Samusev <41779041+alvicsam@users.noreply.github.com> Date: Tue, 15 Feb 2022 13:29:26 +0100 Subject: [PATCH 496/695] [ci] fix publish-rustdocs (#10858) --- .gitlab-ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f6f714ea52b1..8dabbc288cd6 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -756,7 +756,8 @@ publish-rustdoc: # Save README and docs - cp -r ./crate-docs/ /tmp/doc/ - cp README.md /tmp/doc/ - - git checkout gh-pages + # we don't need to commit changes because we copy docs to /tmp + - git checkout gh-pages --force # Install `index-tpl-crud` and generate index.html based on RUSTDOCS_DEPLOY_REFS - which index-tpl-crud &> /dev/null || yarn global add @substrate/index-tpl-crud - index-tpl-crud upsert ./index.html ${CI_COMMIT_REF_NAME} From 9d962620db0dc21837ff5c346789adf35a64a678 Mon Sep 17 00:00:00 2001 From: Davide Galassi Date: Tue, 15 Feb 2022 14:19:39 +0100 Subject: [PATCH 497/695] Fix beefy mock ecdsa keys (#10854) Compressed ECDSA keys requires to have 0x02 or 0x03 as their first byte in order to allow public key recovery. Nevertheless the test was working because of the `unwrap_or_default()` at the end of the conversion routine (i.e. the invalid keys were converted to an empty vector). --- frame/beefy-mmr/src/mock.rs | 7 +++++-- frame/beefy-mmr/src/tests.rs | 8 ++++---- frame/beefy/src/mock.rs | 7 +++++-- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/frame/beefy-mmr/src/mock.rs b/frame/beefy-mmr/src/mock.rs index 88c182aa57ba..dcee901ec14c 100644 --- a/frame/beefy-mmr/src/mock.rs +++ b/frame/beefy-mmr/src/mock.rs @@ -158,9 +158,12 @@ impl pallet_session::SessionManager for MockSessionManager { // Note, that we can't use `UintAuthorityId` here. Reason is that the implementation // of `to_public_key()` assumes, that a public key is 32 bytes long. This is true for -// ed25519 and sr25519 but *not* for ecdsa. An ecdsa public key is 33 bytes. +// ed25519 and sr25519 but *not* for ecdsa. A compressed ecdsa public key is 33 bytes, +// with the first one containing information to reconstruct the uncompressed key. pub fn mock_beefy_id(id: u8) -> BeefyId { - let buf: [u8; 33] = [id; 33]; + let mut buf: [u8; 33] = [id; 33]; + // Set to something valid. + buf[0] = 0x02; let pk = Public::from_raw(buf); BeefyId::from(pk) } diff --git a/frame/beefy-mmr/src/tests.rs b/frame/beefy-mmr/src/tests.rs index 6a81c5f25252..452b8736a791 100644 --- a/frame/beefy-mmr/src/tests.rs +++ b/frame/beefy-mmr/src/tests.rs @@ -71,7 +71,7 @@ fn should_contain_mmr_digest() { assert_eq!( System::digest().logs, vec![beefy_log(ConsensusLog::MmrRoot( - hex!("f3e3afbfa69e89cd1e99f8d3570155962f3346d1d8758dc079be49ef70387758").into() + hex!("969d516e5279540ef38e4a710fb0645cab4c3b01e528be7285b85ec9c5fb55c8").into() ))] ); @@ -82,13 +82,13 @@ fn should_contain_mmr_digest() { System::digest().logs, vec![ beefy_log(ConsensusLog::MmrRoot( - hex!("f3e3afbfa69e89cd1e99f8d3570155962f3346d1d8758dc079be49ef70387758").into() + hex!("969d516e5279540ef38e4a710fb0645cab4c3b01e528be7285b85ec9c5fb55c8").into() )), beefy_log(ConsensusLog::AuthoritiesChange( ValidatorSet::new(vec![mock_beefy_id(3), mock_beefy_id(4),], 1,).unwrap() )), beefy_log(ConsensusLog::MmrRoot( - hex!("7d4ae4524bae75d52b63f08eab173b0c263eb95ae2c55c3a1d871241bd0cc559").into() + hex!("8c42b7b040d262f7f2e26abeb61ab0c3c448f60c7f2f19e6ca0035d9bb3ae7e2").into() )), ] ); @@ -111,7 +111,7 @@ fn should_contain_valid_leaf_data() { beefy_next_authority_set: BeefyNextAuthoritySet { id: 1, len: 2, - root: hex!("01b1a742589773fc054c8f5021a456316ffcec0370b25678b0696e116d1ef9ae") + root: hex!("176e73f1bf656478b728e28dd1a7733c98621b8acf830bff585949763dca7a96") .into(), }, parachain_heads: hex!( diff --git a/frame/beefy/src/mock.rs b/frame/beefy/src/mock.rs index 0d820116d07b..5fc04f7cbd1d 100644 --- a/frame/beefy/src/mock.rs +++ b/frame/beefy/src/mock.rs @@ -122,9 +122,12 @@ impl pallet_session::SessionManager for MockSessionManager { // Note, that we can't use `UintAuthorityId` here. Reason is that the implementation // of `to_public_key()` assumes, that a public key is 32 bytes long. This is true for -// ed25519 and sr25519 but *not* for ecdsa. An ecdsa public key is 33 bytes. +// ed25519 and sr25519 but *not* for ecdsa. A compressed ecdsa public key is 33 bytes, +// with the first one containing information to reconstruct the uncompressed key. pub fn mock_beefy_id(id: u8) -> BeefyId { - let buf: [u8; 33] = [id; 33]; + let mut buf: [u8; 33] = [id; 33]; + // Set to something valid. + buf[0] = 0x02; let pk = Public::from_raw(buf); BeefyId::from(pk) } From b9927cdca03830d07bc1cdd8b8d80a3d32f64bd1 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Tue, 15 Feb 2022 22:21:34 +0100 Subject: [PATCH 498/695] Mark sync_state_genSyncSpec JSON-RPC as safe (#10832) * Mark sync_state_genSyncSpec JSON-RPC as safe * Note that parameter is unused * Ideally I'd wait for compilation to be finished before pushing, but it's really taking a long time * Remove deny_unsafe parameter * Remove unused dependency --- Cargo.lock | 1 - bin/node/rpc/src/lib.rs | 1 - client/sync-state-rpc/Cargo.toml | 1 - client/sync-state-rpc/src/lib.rs | 8 +------- 4 files changed, 1 insertion(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e97c90e49236..635ca97cd1e5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8808,7 +8808,6 @@ dependencies = [ "sc-consensus-babe", "sc-consensus-epochs", "sc-finality-grandpa", - "sc-rpc-api", "serde", "serde_json", "sp-blockchain", diff --git a/bin/node/rpc/src/lib.rs b/bin/node/rpc/src/lib.rs index 30f7a0fdf023..31f2f4108688 100644 --- a/bin/node/rpc/src/lib.rs +++ b/bin/node/rpc/src/lib.rs @@ -165,7 +165,6 @@ where client, shared_authority_set, shared_epoch_changes, - deny_unsafe, )?, )); diff --git a/client/sync-state-rpc/Cargo.toml b/client/sync-state-rpc/Cargo.toml index b413446c321f..3e064685488d 100644 --- a/client/sync-state-rpc/Cargo.toml +++ b/client/sync-state-rpc/Cargo.toml @@ -22,7 +22,6 @@ sc-client-api = { version = "4.0.0-dev", path = "../api" } sc-consensus-babe = { version = "0.10.0-dev", path = "../consensus/babe" } sc-consensus-epochs = { version = "0.10.0-dev", path = "../consensus/epochs" } sc-finality-grandpa = { version = "0.10.0-dev", path = "../finality-grandpa" } -sc-rpc-api = { version = "0.10.0-dev", path = "../rpc-api" } serde_json = "1.0.74" serde = { version = "1.0.136", features = ["derive"] } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } diff --git a/client/sync-state-rpc/src/lib.rs b/client/sync-state-rpc/src/lib.rs index f416b3a0e8f7..6fc0d17800fe 100644 --- a/client/sync-state-rpc/src/lib.rs +++ b/client/sync-state-rpc/src/lib.rs @@ -134,7 +134,6 @@ pub struct SyncStateRpcHandler { client: Arc, shared_authority_set: SharedAuthoritySet, shared_epoch_changes: SharedEpochChanges, - deny_unsafe: sc_rpc_api::DenyUnsafe, } impl SyncStateRpcHandler @@ -148,12 +147,11 @@ where client: Arc, shared_authority_set: SharedAuthoritySet, shared_epoch_changes: SharedEpochChanges, - deny_unsafe: sc_rpc_api::DenyUnsafe, ) -> Result> { if sc_chain_spec::get_extension::(chain_spec.extensions()) .is_some() { - Ok(Self { chain_spec, client, shared_authority_set, shared_epoch_changes, deny_unsafe }) + Ok(Self { chain_spec, client, shared_authority_set, shared_epoch_changes }) } else { Err(Error::::LightSyncStateExtensionNotFound) } @@ -185,10 +183,6 @@ where Backend: HeaderBackend + sc_client_api::AuxStore + 'static, { fn system_gen_sync_spec(&self, raw: bool) -> jsonrpc_core::Result { - if let Err(err) = self.deny_unsafe.check_if_safe() { - return Err(err.into()) - } - let mut chain_spec = self.chain_spec.cloned_box(); let sync_state = self.build_sync_state().map_err(map_error::>)?; From ba88ea2b6546596baa248097acb8f755550d987e Mon Sep 17 00:00:00 2001 From: Koute Date: Wed, 16 Feb 2022 13:14:00 +0900 Subject: [PATCH 499/695] Reduce CPU overhead of gossip (#10859) --- Cargo.lock | 6 ++-- client/finality-grandpa/Cargo.toml | 1 + .../src/communication/gossip.rs | 34 +++++++++---------- client/network-gossip/Cargo.toml | 1 + client/network-gossip/src/state_machine.rs | 15 +++----- 5 files changed, 28 insertions(+), 29 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 635ca97cd1e5..9dc7cd909ff9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -64,9 +64,9 @@ dependencies = [ [[package]] name = "ahash" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43bb833f0bf979d8475d38fbf09ed3b8a55e1885fe93ad3f93239fc6a4f17b98" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" dependencies = [ "getrandom 0.2.3", "once_cell", @@ -8333,6 +8333,7 @@ dependencies = [ name = "sc-finality-grandpa" version = "0.10.0-dev" dependencies = [ + "ahash", "assert_matches", "async-trait", "dyn-clone", @@ -8491,6 +8492,7 @@ dependencies = [ name = "sc-network-gossip" version = "0.10.0-dev" dependencies = [ + "ahash", "async-std", "futures 0.3.16", "futures-timer", diff --git a/client/finality-grandpa/Cargo.toml b/client/finality-grandpa/Cargo.toml index 6d4c3b13662d..6fecebc3fdf6 100644 --- a/client/finality-grandpa/Cargo.toml +++ b/client/finality-grandpa/Cargo.toml @@ -22,6 +22,7 @@ futures-timer = "3.0.1" log = "0.4.8" parking_lot = "0.11.2" rand = "0.8.4" +ahash = "0.7.6" parity-scale-codec = { version = "2.3.1", features = ["derive"] } sp-application-crypto = { version = "5.0.0", path = "../../primitives/application-crypto" } sp-arithmetic = { version = "4.0.0", path = "../../primitives/arithmetic" } diff --git a/client/finality-grandpa/src/communication/gossip.rs b/client/finality-grandpa/src/communication/gossip.rs index ded918c34aa8..7ac4066780d0 100644 --- a/client/finality-grandpa/src/communication/gossip.rs +++ b/client/finality-grandpa/src/communication/gossip.rs @@ -84,23 +84,23 @@ //! //! We only send polite messages to peers, -use parity_scale_codec::{Decode, Encode}; -use sc_network::{ObservedRole, PeerId, ReputationChange}; -use sc_network_gossip::{MessageIntent, ValidatorContext}; -use sp_finality_grandpa::AuthorityId; -use sp_runtime::traits::{Block as BlockT, NumberFor, Zero}; - +use ahash::{AHashMap, AHashSet}; use log::{debug, trace}; +use parity_scale_codec::{Decode, Encode}; use prometheus_endpoint::{register, CounterVec, Opts, PrometheusError, Registry, U64}; use rand::seq::SliceRandom; +use sc_network::{ObservedRole, PeerId, ReputationChange}; +use sc_network_gossip::{MessageIntent, ValidatorContext}; use sc_telemetry::{telemetry, TelemetryHandle, CONSENSUS_DEBUG}; use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender}; +use sp_finality_grandpa::AuthorityId; +use sp_runtime::traits::{Block as BlockT, NumberFor, Zero}; use super::{benefit, cost, Round, SetId}; use crate::{environment, CatchUp, CompactCommit, SignedMessage}; use std::{ - collections::{HashMap, HashSet, VecDeque}, + collections::{HashSet, VecDeque}, time::{Duration, Instant}, }; @@ -260,7 +260,7 @@ const KEEP_RECENT_ROUNDS: usize = 3; struct KeepTopics { current_set: SetId, rounds: VecDeque<(Round, SetId)>, - reverse_map: HashMap, SetId)>, + reverse_map: AHashMap, SetId)>, } impl KeepTopics { @@ -268,7 +268,7 @@ impl KeepTopics { KeepTopics { current_set: SetId(0), rounds: VecDeque::with_capacity(KEEP_RECENT_ROUNDS + 2), - reverse_map: HashMap::new(), + reverse_map: Default::default(), } } @@ -290,7 +290,7 @@ impl KeepTopics { let _ = self.rounds.pop_front(); } - let mut map = HashMap::with_capacity(KEEP_RECENT_ROUNDS + 3); + let mut map = AHashMap::with_capacity(KEEP_RECENT_ROUNDS + 3); map.insert(super::global_topic::(self.current_set.0), (None, self.current_set)); for &(round, set) in &self.rounds { @@ -477,10 +477,10 @@ impl PeerInfo { /// The peers we're connected to in gossip. struct Peers { - inner: HashMap>, + inner: AHashMap>, /// The randomly picked set of `LUCKY_PEERS` we'll gossip to in the first stage of round /// gossiping. - first_stage_peers: HashSet, + first_stage_peers: AHashSet, /// The randomly picked set of peers we'll gossip to in the second stage of gossiping if the /// first stage didn't allow us to spread the voting data enough to conclude the round. This /// set should have size `sqrt(connected_peers)`. @@ -492,10 +492,10 @@ struct Peers { impl Default for Peers { fn default() -> Self { Peers { - inner: HashMap::new(), - first_stage_peers: HashSet::new(), - second_stage_peers: HashSet::new(), - lucky_light_peers: HashSet::new(), + inner: Default::default(), + first_stage_peers: Default::default(), + second_stage_peers: Default::default(), + lucky_light_peers: Default::default(), } } } @@ -608,7 +608,7 @@ impl Peers { } }); - let mut first_stage_peers = HashSet::new(); + let mut first_stage_peers = AHashSet::new(); let mut second_stage_peers = HashSet::new(); // we start by allocating authorities to the first stage set and when the minimum of diff --git a/client/network-gossip/Cargo.toml b/client/network-gossip/Cargo.toml index 7952d97193ea..161129c4ce68 100644 --- a/client/network-gossip/Cargo.toml +++ b/client/network-gossip/Cargo.toml @@ -20,6 +20,7 @@ futures-timer = "3.0.1" libp2p = { version = "0.40.0", default-features = false } log = "0.4.8" lru = "0.7.0" +ahash = "0.7.6" prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.10.0-dev", path = "../../utils/prometheus" } sc-network = { version = "0.10.0-dev", path = "../network" } sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } diff --git a/client/network-gossip/src/state_machine.rs b/client/network-gossip/src/state_machine.rs index 7ad9853b3615..4f06819df64d 100644 --- a/client/network-gossip/src/state_machine.rs +++ b/client/network-gossip/src/state_machine.rs @@ -18,19 +18,13 @@ use crate::{MessageIntent, Network, ValidationResult, Validator, ValidatorContext}; +use ahash::AHashSet; use libp2p::PeerId; use lru::LruCache; use prometheus_endpoint::{register, Counter, PrometheusError, Registry, U64}; use sc_network::ObservedRole; use sp_runtime::traits::{Block as BlockT, Hash, HashFor}; -use std::{ - borrow::Cow, - collections::{HashMap, HashSet}, - iter, - sync::Arc, - time, - time::Instant, -}; +use std::{borrow::Cow, collections::HashMap, iter, sync::Arc, time, time::Instant}; // FIXME: Add additional spam/DoS attack protection: https://github.com/paritytech/substrate/issues/1115 // NOTE: The current value is adjusted based on largest production network deployment (Kusama) and @@ -56,7 +50,7 @@ mod rep { } struct PeerConsensus { - known_messages: HashSet, + known_messages: AHashSet, } /// Topic stream message with sender. @@ -204,7 +198,8 @@ impl ConsensusGossip { ?role, "Registering peer", ); - self.peers.insert(who.clone(), PeerConsensus { known_messages: HashSet::new() }); + self.peers + .insert(who.clone(), PeerConsensus { known_messages: Default::default() }); let validator = self.validator.clone(); let mut context = NetworkContext { gossip: self, network }; From 42eec5bbf2345551e641ffe6bea43403475d0129 Mon Sep 17 00:00:00 2001 From: Qinxuan Chen Date: Wed, 16 Feb 2022 16:26:53 +0800 Subject: [PATCH 500/695] sp-core-hashing: use the `digest::Digest` trait to handle the hashing function uniformly (#10835) * sp-core-hashing: use sha3 instead of tiny-keccak Signed-off-by: koushiro * use blake2 instead of blake2-rfc Signed-off-by: koushiro * improve som hashing of sp-core and sp-api-proc-macro Signed-off-by: koushiro * Some nits Signed-off-by: koushiro * cargo fmt Signed-off-by: koushiro --- Cargo.lock | 54 ++++++++++----- primitives/api/proc-macro/Cargo.toml | 2 +- .../api/proc-macro/src/decl_runtime_apis.rs | 6 +- primitives/core/Cargo.toml | 9 --- primitives/core/hashing/Cargo.toml | 14 ++-- primitives/core/hashing/src/lib.rs | 66 +++++++------------ primitives/core/src/ecdsa.rs | 6 +- primitives/core/src/ed25519.rs | 6 +- 8 files changed, 74 insertions(+), 89 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9dc7cd909ff9..e04aec94d76b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -641,6 +641,15 @@ dependencies = [ "opaque-debug 0.3.0", ] +[[package]] +name = "blake2" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b94ba84325db59637ffc528bbe8c7f86c02c57cff5c0e2b9b00f9a851f42f309" +dependencies = [ + "digest 0.10.2", +] + [[package]] name = "blake2-rfc" version = "0.2.18" @@ -1383,9 +1392,9 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-common" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683d6b536309245c849479fba3da410962a43ed8e51c26b729208ec0ac2798d0" +checksum = "a4600d695eb3f6ce1cd44e6e291adceb2cc3ab12f20a33777ecd0bf6eba34e06" dependencies = [ "generic-array 0.14.4", ] @@ -1603,13 +1612,13 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b697d66081d42af4fba142d56918a3cb21dc8eb63372c6b85d14f44fb9c5979b" +checksum = "8cb780dce4f9a8f5c087362b3a4595936b2019e7c8b30f2c3e9a7e94e6ae9837" dependencies = [ "block-buffer 0.10.0", "crypto-common", - "generic-array 0.14.4", + "subtle", ] [[package]] @@ -3852,7 +3861,7 @@ dependencies = [ "pin-project 1.0.10", "rand 0.7.3", "salsa20", - "sha3", + "sha3 0.9.1", ] [[package]] @@ -4491,7 +4500,7 @@ dependencies = [ "generic-array 0.14.4", "multihash-derive", "sha2 0.9.8", - "sha3", + "sha3 0.9.1", "unsigned-varint 0.5.1", ] @@ -9210,13 +9219,13 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900d964dd36bb15bcf2f2b35694c072feab74969a54f2bbeec7a2d725d2bdcb6" +checksum = "99c3bd8169c58782adad9290a9af5939994036b76187f7b4f0e6de91dbbfc0ec" dependencies = [ "cfg-if 1.0.0", "cpufeatures 0.2.1", - "digest 0.10.1", + "digest 0.10.2", ] [[package]] @@ -9231,6 +9240,16 @@ dependencies = [ "opaque-debug 0.3.0", ] +[[package]] +name = "sha3" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f935e31cf406e8c0e96c2815a5516181b7004ae8c5f296293221e9b1e356bd" +dependencies = [ + "digest 0.10.2", + "keccak", +] + [[package]] name = "sharded-slab" version = "0.1.1" @@ -9317,7 +9336,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6142f7c25e94f6fd25a32c3348ec230df9109b463f59c8c7acc4bd34936babb7" dependencies = [ "aes-gcm", - "blake2", + "blake2 0.9.1", "chacha20poly1305", "rand 0.8.4", "rand_core 0.6.2", @@ -9401,7 +9420,7 @@ dependencies = [ name = "sp-api-proc-macro" version = "4.0.0-dev" dependencies = [ - "blake2-rfc", + "blake2 0.10.2", "proc-macro-crate 1.1.0", "proc-macro2", "quote", @@ -9655,7 +9674,6 @@ dependencies = [ "secrecy", "serde", "serde_json", - "sha2 0.10.0", "sp-core-hashing", "sp-core-hashing-proc-macro", "sp-debug-derive", @@ -9668,8 +9686,6 @@ dependencies = [ "substrate-bip39", "thiserror", "tiny-bip39", - "tiny-keccak", - "twox-hash", "wasmi", "zeroize", ] @@ -9678,11 +9694,12 @@ dependencies = [ name = "sp-core-hashing" version = "4.0.0" dependencies = [ - "blake2-rfc", + "blake2 0.10.2", "byteorder", - "sha2 0.10.0", + "digest 0.10.2", + "sha2 0.10.1", + "sha3 0.10.0", "sp-std", - "tiny-keccak", "twox-hash", ] @@ -11153,6 +11170,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ee73e6e4924fe940354b8d4d98cad5231175d615cd855b758adc658c0aac6a0" dependencies = [ "cfg-if 1.0.0", + "digest 0.10.2", "rand 0.8.4", "static_assertions", ] diff --git a/primitives/api/proc-macro/Cargo.toml b/primitives/api/proc-macro/Cargo.toml index 30ab3ef9562b..356e15a6fd11 100644 --- a/primitives/api/proc-macro/Cargo.toml +++ b/primitives/api/proc-macro/Cargo.toml @@ -19,7 +19,7 @@ proc-macro = true quote = "1.0.10" syn = { version = "1.0.82", features = ["full", "fold", "extra-traits", "visit"] } proc-macro2 = "1.0.36" -blake2-rfc = { version = "0.2.18", default-features = false } +blake2 = { version = "0.10.2", default-features = false } proc-macro-crate = "1.1.0" # Required for the doc tests diff --git a/primitives/api/proc-macro/src/decl_runtime_apis.rs b/primitives/api/proc-macro/src/decl_runtime_apis.rs index 85b66eca7061..6de20df8a41d 100644 --- a/primitives/api/proc-macro/src/decl_runtime_apis.rs +++ b/primitives/api/proc-macro/src/decl_runtime_apis.rs @@ -39,8 +39,6 @@ use syn::{ use std::collections::HashMap; -use blake2_rfc; - /// The ident used for the block generic parameter. const BLOCK_GENERIC_IDENT: &str = "Block"; @@ -750,8 +748,10 @@ fn parse_runtime_api_version(version: &Attribute) -> Result { /// Generates the identifier as const variable for the given `trait_name` /// by hashing the `trait_name`. fn generate_runtime_api_id(trait_name: &str) -> TokenStream { + use blake2::digest::{consts::U8, Digest}; + let mut res = [0; 8]; - res.copy_from_slice(blake2_rfc::blake2b::blake2b(8, &[], trait_name.as_bytes()).as_bytes()); + res.copy_from_slice(blake2::Blake2b::::digest(trait_name).as_slice()); quote!( const ID: [u8; 8] = [ #( #res ),* ]; ) } diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index bd41635a1d7a..08d5cdb87e60 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -49,14 +49,11 @@ bitflags = "1.3" # full crypto ed25519-dalek = { version = "1.0.1", default-features = false, features = ["u64_backend", "alloc"], optional = true } blake2-rfc = { version = "0.2.18", default-features = false, optional = true } -tiny-keccak = { version = "2.0.1", features = ["keccak"], optional = true } schnorrkel = { version = "0.9.1", features = [ "preaudit_deprecated", "u64_backend", ], default-features = false, optional = true } -sha2 = { version = "0.10.0", default-features = false, optional = true } hex = { version = "0.4", default-features = false, optional = true } -twox-hash = { version = "1.6.2", default-features = false, optional = true } libsecp256k1 = { version = "0.7", default-features = false, features = ["hmac", "static-context"], optional = true } merlin = { version = "2.0", default-features = false, optional = true } ss58-registry = { version = "1.11.0", default-features = false } @@ -98,7 +95,6 @@ std = [ "hash-db/std", "sp-std/std", "serde", - "twox-hash/std", "blake2-rfc/std", "ed25519-dalek/std", "hex/std", @@ -107,11 +103,9 @@ std = [ "tiny-bip39", "byteorder/std", "rand", - "sha2/std", "schnorrkel/std", "regex", "num-traits/std", - "tiny-keccak", "sp-core-hashing/std", "sp-debug-derive/std", "sp-externalities", @@ -132,11 +126,8 @@ std = [ full_crypto = [ "ed25519-dalek", "blake2-rfc", - "tiny-keccak", "schnorrkel", "hex", - "sha2", - "twox-hash", "libsecp256k1", "sp-core-hashing", "sp-runtime-interface/disable_target_static_assertions", diff --git a/primitives/core/hashing/Cargo.toml b/primitives/core/hashing/Cargo.toml index 8a84e585dad2..dc5704d2989a 100644 --- a/primitives/core/hashing/Cargo.toml +++ b/primitives/core/hashing/Cargo.toml @@ -16,16 +16,18 @@ targets = ["x86_64-unknown-linux-gnu"] sp-std = { version = "4.0.0", default-features = false, path = "../../std" } byteorder = { version = "1.3.2", default-features = false } -blake2-rfc = { version = "0.2.18", default-features = false } -tiny-keccak = { version = "2.0.1", features = ["keccak"] } -sha2 = { version = "0.10.0", default-features = false } -twox-hash = { version = "1.6.2", default-features = false } +digest = { version = "0.10.2", default-features = false } +blake2 = { version = "0.10.2", default-features = false } +sha2 = { version = "0.10.1", default-features = false } +sha3 = { version = "0.10.0", default-features = false } +twox-hash = { version = "1.6.2", default-features = false, features = ["digest_0_10"] } [features] default = ["std"] std = [ - "blake2-rfc/std", - "sha2/std", "sp-std/std", + "blake2/std", + "sha2/std", + "sha3/std", "twox-hash/std", ] diff --git a/primitives/core/hashing/src/lib.rs b/primitives/core/hashing/src/lib.rs index 9fa433a32320..e6ccd5aaa8fb 100644 --- a/primitives/core/hashing/src/lib.rs +++ b/primitives/core/hashing/src/lib.rs @@ -20,12 +20,17 @@ #![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] -use sha2::{Digest, Sha256}; -use tiny_keccak::{Hasher, Keccak}; +use core::hash::Hasher; + +use byteorder::{ByteOrder, LittleEndian}; +use digest::{ + consts::{U16, U32, U8}, + Digest, +}; /// Do a Blake2 512-bit hash and place result in `dest`. pub fn blake2_512_into(data: &[u8], dest: &mut [u8; 64]) { - dest.copy_from_slice(blake2_rfc::blake2b::blake2b(64, &[], data).as_bytes()); + dest.copy_from_slice(blake2::Blake2b512::digest(data).as_slice()); } /// Do a Blake2 512-bit hash and return result. @@ -37,7 +42,8 @@ pub fn blake2_512(data: &[u8]) -> [u8; 64] { /// Do a Blake2 256-bit hash and place result in `dest`. pub fn blake2_256_into(data: &[u8], dest: &mut [u8; 32]) { - dest.copy_from_slice(blake2_rfc::blake2b::blake2b(32, &[], data).as_bytes()); + type Blake2b256 = blake2::Blake2b; + dest.copy_from_slice(Blake2b256::digest(data).as_slice()); } /// Do a Blake2 256-bit hash and return result. @@ -49,7 +55,8 @@ pub fn blake2_256(data: &[u8]) -> [u8; 32] { /// Do a Blake2 128-bit hash and place result in `dest`. pub fn blake2_128_into(data: &[u8], dest: &mut [u8; 16]) { - dest.copy_from_slice(blake2_rfc::blake2b::blake2b(16, &[], data).as_bytes()); + type Blake2b128 = blake2::Blake2b; + dest.copy_from_slice(Blake2b128::digest(data).as_slice()); } /// Do a Blake2 128-bit hash and return result. @@ -61,7 +68,8 @@ pub fn blake2_128(data: &[u8]) -> [u8; 16] { /// Do a Blake2 64-bit hash and place result in `dest`. pub fn blake2_64_into(data: &[u8], dest: &mut [u8; 8]) { - dest.copy_from_slice(blake2_rfc::blake2b::blake2b(8, &[], data).as_bytes()); + type Blake2b64 = blake2::Blake2b; + dest.copy_from_slice(Blake2b64::digest(data).as_slice()); } /// Do a Blake2 64-bit hash and return result. @@ -73,11 +81,7 @@ pub fn blake2_64(data: &[u8]) -> [u8; 8] { /// Do a XX 64-bit hash and place result in `dest`. pub fn twox_64_into(data: &[u8], dest: &mut [u8; 8]) { - use core::hash::Hasher; - let mut h0 = twox_hash::XxHash::with_seed(0); - h0.write(data); - let r0 = h0.finish(); - use byteorder::{ByteOrder, LittleEndian}; + let r0 = twox_hash::XxHash::with_seed(0).chain_update(data).finish(); LittleEndian::write_u64(&mut dest[0..8], r0); } @@ -90,14 +94,8 @@ pub fn twox_64(data: &[u8]) -> [u8; 8] { /// Do a XX 128-bit hash and place result in `dest`. pub fn twox_128_into(data: &[u8], dest: &mut [u8; 16]) { - use core::hash::Hasher; - let mut h0 = twox_hash::XxHash::with_seed(0); - let mut h1 = twox_hash::XxHash::with_seed(1); - h0.write(data); - h1.write(data); - let r0 = h0.finish(); - let r1 = h1.finish(); - use byteorder::{ByteOrder, LittleEndian}; + let r0 = twox_hash::XxHash::with_seed(0).chain_update(data).finish(); + let r1 = twox_hash::XxHash::with_seed(1).chain_update(data).finish(); LittleEndian::write_u64(&mut dest[0..8], r0); LittleEndian::write_u64(&mut dest[8..16], r1); } @@ -111,20 +109,10 @@ pub fn twox_128(data: &[u8]) -> [u8; 16] { /// Do a XX 256-bit hash and place result in `dest`. pub fn twox_256_into(data: &[u8], dest: &mut [u8; 32]) { - use ::core::hash::Hasher; - use byteorder::{ByteOrder, LittleEndian}; - let mut h0 = twox_hash::XxHash::with_seed(0); - let mut h1 = twox_hash::XxHash::with_seed(1); - let mut h2 = twox_hash::XxHash::with_seed(2); - let mut h3 = twox_hash::XxHash::with_seed(3); - h0.write(data); - h1.write(data); - h2.write(data); - h3.write(data); - let r0 = h0.finish(); - let r1 = h1.finish(); - let r2 = h2.finish(); - let r3 = h3.finish(); + let r0 = twox_hash::XxHash::with_seed(0).chain_update(data).finish(); + let r1 = twox_hash::XxHash::with_seed(1).chain_update(data).finish(); + let r2 = twox_hash::XxHash::with_seed(2).chain_update(data).finish(); + let r3 = twox_hash::XxHash::with_seed(3).chain_update(data).finish(); LittleEndian::write_u64(&mut dest[0..8], r0); LittleEndian::write_u64(&mut dest[8..16], r1); LittleEndian::write_u64(&mut dest[16..24], r2); @@ -140,27 +128,21 @@ pub fn twox_256(data: &[u8]) -> [u8; 32] { /// Do a keccak 256-bit hash and return result. pub fn keccak_256(data: &[u8]) -> [u8; 32] { - let mut keccak = Keccak::v256(); - keccak.update(data); let mut output = [0u8; 32]; - keccak.finalize(&mut output); + output.copy_from_slice(sha3::Keccak256::digest(data).as_slice()); output } /// Do a keccak 512-bit hash and return result. pub fn keccak_512(data: &[u8]) -> [u8; 64] { - let mut keccak = Keccak::v512(); - keccak.update(data); let mut output = [0u8; 64]; - keccak.finalize(&mut output); + output.copy_from_slice(sha3::Keccak512::digest(data).as_slice()); output } /// Do a sha2 256-bit hash and return result. pub fn sha2_256(data: &[u8]) -> [u8; 32] { - let mut hasher = Sha256::new(); - hasher.update(data); let mut output = [0u8; 32]; - output.copy_from_slice(&hasher.finalize()); + output.copy_from_slice(sha2::Sha256::digest(data).as_slice()); output } diff --git a/primitives/core/src/ecdsa.rs b/primitives/core/src/ecdsa.rs index 4d2cae97ef14..0735c3f40cec 100644 --- a/primitives/core/src/ecdsa.rs +++ b/primitives/core/src/ecdsa.rs @@ -348,11 +348,7 @@ impl<'a> TryFrom<&'a Signature> for (libsecp256k1::Signature, libsecp256k1::Reco /// Derive a single hard junction. #[cfg(feature = "full_crypto")] fn derive_hard_junction(secret_seed: &Seed, cc: &[u8; 32]) -> Seed { - ("Secp256k1HDKD", secret_seed, cc).using_encoded(|data| { - let mut res = [0u8; 32]; - res.copy_from_slice(blake2_rfc::blake2b::blake2b(32, &[], data).as_bytes()); - res - }) + ("Secp256k1HDKD", secret_seed, cc).using_encoded(|data| sp_core_hashing::blake2_256(data)) } /// An error when deriving a key. diff --git a/primitives/core/src/ed25519.rs b/primitives/core/src/ed25519.rs index be7547201e84..54f9ed7fc0e3 100644 --- a/primitives/core/src/ed25519.rs +++ b/primitives/core/src/ed25519.rs @@ -396,11 +396,7 @@ impl From<&Public> for CryptoTypePublicPair { /// Derive a single hard junction. #[cfg(feature = "full_crypto")] fn derive_hard_junction(secret_seed: &Seed, cc: &[u8; 32]) -> Seed { - ("Ed25519HDKD", secret_seed, cc).using_encoded(|data| { - let mut res = [0u8; 32]; - res.copy_from_slice(blake2_rfc::blake2b::blake2b(32, &[], data).as_bytes()); - res - }) + ("Ed25519HDKD", secret_seed, cc).using_encoded(|data| sp_core_hashing::blake2_256(data)) } /// An error when deriving a key. From 7fa05d45e570845146e4001f2d30f052f59a87bb Mon Sep 17 00:00:00 2001 From: Dmitry Kashitsyn Date: Wed, 16 Feb 2022 16:53:10 +0700 Subject: [PATCH 501/695] Use fully qualified sytnax for `retain_mut` (#10865) --- client/consensus/babe/src/lib.rs | 2 +- client/transaction-pool/src/graph/validated_pool.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/consensus/babe/src/lib.rs b/client/consensus/babe/src/lib.rs index 9ad50eb9c0e5..19d9e37cf20a 100644 --- a/client/consensus/babe/src/lib.rs +++ b/client/consensus/babe/src/lib.rs @@ -753,7 +753,7 @@ where slot: Slot, epoch_descriptor: &ViableEpochDescriptor, Epoch>, ) { - self.slot_notification_sinks.lock().retain_mut(|sink| { + RetainMut::retain_mut(&mut *self.slot_notification_sinks.lock(), |sink| { match sink.try_send((slot, epoch_descriptor.clone())) { Ok(()) => true, Err(e) => diff --git a/client/transaction-pool/src/graph/validated_pool.rs b/client/transaction-pool/src/graph/validated_pool.rs index 7e19941b2568..4ddaf8de5c2b 100644 --- a/client/transaction-pool/src/graph/validated_pool.rs +++ b/client/transaction-pool/src/graph/validated_pool.rs @@ -203,7 +203,7 @@ impl ValidatedPool { let imported = self.pool.write().import(tx)?; if let base::Imported::Ready { ref hash, .. } = imported { - self.import_notification_sinks.lock().retain_mut(|sink| { + RetainMut::retain_mut(&mut *self.import_notification_sinks.lock(), |sink| { match sink.try_send(*hash) { Ok(()) => true, Err(e) => From b2f76e26a9e8cd0d5457058b20bb250d092a16ac Mon Sep 17 00:00:00 2001 From: zjb0807 Date: Wed, 16 Feb 2022 18:02:35 +0800 Subject: [PATCH 502/695] add llvm (#10864) --- docs/README.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README.adoc b/docs/README.adoc index 05f81442d4ca..0b82f0ed82a1 100644 --- a/docs/README.adoc +++ b/docs/README.adoc @@ -190,7 +190,7 @@ You will also need to install the following packages: - Linux: [source, shell] -sudo apt install cmake pkg-config libssl-dev git clang libclang-dev +sudo apt install cmake pkg-config libssl-dev git clang libclang-dev llvm - Linux on ARM: `rust-lld` is required for linking wasm, but is missing on non Tier 1 platforms. From 5cdbaa3e1caac94fa3ede30f9fb08fd1f031b3d4 Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Wed, 16 Feb 2022 10:40:16 +0000 Subject: [PATCH 503/695] refactor election score (#10834) * refactor election score * Test for ord * remove reference * vec -> slice * change iter to iter_by_significance * improve doc * fix typo * add explanation about [u128; 3] * consolidate threshold and epsilon * random fixes * rename * remove Into * make iter_by_sig private * remove vec * Fix tests --- .../src/benchmarking.rs | 9 +- .../election-provider-multi-phase/src/lib.rs | 41 ++++-- .../src/signed.rs | 87 ++++++++---- .../src/unsigned.rs | 63 +++++---- primitives/arithmetic/src/lib.rs | 2 +- .../fuzzer/src/phragmen_balancing.rs | 15 +- .../fuzzer/src/phragmms_balancing.rs | 14 +- primitives/npos-elections/src/lib.rs | 133 ++++++++++++------ primitives/npos-elections/src/tests.rs | 41 +++++- 9 files changed, 281 insertions(+), 124 deletions(-) diff --git a/frame/election-provider-multi-phase/src/benchmarking.rs b/frame/election-provider-multi-phase/src/benchmarking.rs index d37b9451b770..cc322cbb4d57 100644 --- a/frame/election-provider-multi-phase/src/benchmarking.rs +++ b/frame/election-provider-multi-phase/src/benchmarking.rs @@ -148,7 +148,10 @@ fn solution_with_size( let score = solution.clone().score(stake_of, voter_at, target_at).unwrap(); let round = >::round(); - assert!(score[0] > 0, "score is zero, this probably means that the stakes are not set."); + assert!( + score.minimal_stake > 0, + "score is zero, this probably means that the stakes are not set." + ); Ok(RawSolution { solution, score, round }) } @@ -312,7 +315,7 @@ frame_benchmarking::benchmarks! { // the solution will be worse than all of them meaning the score need to be checked against // ~ log2(c) let solution = RawSolution { - score: [(10_000_000u128 - 1).into(), 0, 0], + score: ElectionScore { minimal_stake: 10_000_000u128 - 1, ..Default::default() }, ..Default::default() }; @@ -323,7 +326,7 @@ frame_benchmarking::benchmarks! { let mut signed_submissions = SignedSubmissions::::get(); for i in 0..c { let raw_solution = RawSolution { - score: [(10_000_000 + i).into(), 0, 0], + score: ElectionScore { minimal_stake: 10_000_000u128 + (i as u128), ..Default::default() }, ..Default::default() }; let signed_submission = SignedSubmission { diff --git a/frame/election-provider-multi-phase/src/lib.rs b/frame/election-provider-multi-phase/src/lib.rs index cad3d12605e4..58df7d5a9d75 100644 --- a/frame/election-provider-multi-phase/src/lib.rs +++ b/frame/election-provider-multi-phase/src/lib.rs @@ -944,8 +944,11 @@ pub mod pallet { // Note: we don't `rotate_round` at this point; the next call to // `ElectionProvider::elect` will succeed and take care of that. - let solution = - ReadySolution { supports, score: [0, 0, 0], compute: ElectionCompute::Emergency }; + let solution = ReadySolution { + supports, + score: Default::default(), + compute: ElectionCompute::Emergency, + }; >::put(solution); Ok(()) @@ -1059,8 +1062,11 @@ pub mod pallet { }, )?; - let solution = - ReadySolution { supports, score: [0, 0, 0], compute: ElectionCompute::Fallback }; + let solution = ReadySolution { + supports, + score: Default::default(), + compute: ElectionCompute::Fallback, + }; >::put(solution); Ok(()) @@ -1138,10 +1144,10 @@ pub mod pallet { .map_err(dispatch_error_to_invalid)?; ValidTransaction::with_tag_prefix("OffchainElection") - // The higher the score[0], the better a solution is. + // The higher the score.minimal_stake, the better a solution is. .priority( T::MinerTxPriority::get() - .saturating_add(raw_solution.score[0].saturated_into()), + .saturating_add(raw_solution.score.minimal_stake.saturated_into()), ) // Used to deduplicate unsigned solutions: each validator should produce one // solution per round at most, and solutions are not propagate. @@ -1430,7 +1436,7 @@ impl Pallet { let submitted_score = raw_solution.score.clone(); ensure!( Self::minimum_untrusted_score().map_or(true, |min_score| { - sp_npos_elections::is_score_better(submitted_score, min_score, Perbill::zero()) + submitted_score.strict_threshold_better(min_score, Perbill::zero()) }), FeasibilityError::UntrustedScoreTooLow ); @@ -1750,7 +1756,7 @@ mod feasibility_check { assert_eq!(MultiPhase::snapshot().unwrap().voters.len(), 8); // Simply faff with the score. - solution.score[0] += 1; + solution.score.minimal_stake += 1; assert_noop!( MultiPhase::feasibility_check(solution, COMPUTE), @@ -1960,7 +1966,10 @@ mod tests { // fill the queue with signed submissions for s in 0..SignedMaxSubmissions::get() { - let solution = RawSolution { score: [(5 + s).into(), 0, 0], ..Default::default() }; + let solution = RawSolution { + score: ElectionScore { minimal_stake: (5 + s).into(), ..Default::default() }, + ..Default::default() + }; assert_ok!(MultiPhase::submit( crate::mock::Origin::signed(99), Box::new(solution), @@ -2087,13 +2096,19 @@ mod tests { crate::mock::Balancing::set(Some((2, 0))); let (solution, _) = MultiPhase::mine_solution::<::Solver>().unwrap(); - // Default solution has a score of [50, 100, 5000]. - assert_eq!(solution.score, [50, 100, 5000]); + // Default solution's score. + assert!(matches!(solution.score, ElectionScore { minimal_stake: 50, .. })); - >::put([49, 0, 0]); + >::put(ElectionScore { + minimal_stake: 49, + ..Default::default() + }); assert_ok!(MultiPhase::feasibility_check(solution.clone(), ElectionCompute::Signed)); - >::put([51, 0, 0]); + >::put(ElectionScore { + minimal_stake: 51, + ..Default::default() + }); assert_noop!( MultiPhase::feasibility_check(solution, ElectionCompute::Signed), FeasibilityError::UntrustedScoreTooLow, diff --git a/frame/election-provider-multi-phase/src/signed.rs b/frame/election-provider-multi-phase/src/signed.rs index 3b314bce80ff..4362fb5127e7 100644 --- a/frame/election-provider-multi-phase/src/signed.rs +++ b/frame/election-provider-multi-phase/src/signed.rs @@ -28,7 +28,7 @@ use frame_support::{ traits::{defensive_prelude::*, Currency, Get, OnUnbalanced, ReservableCurrency}, }; use sp_arithmetic::traits::SaturatedConversion; -use sp_npos_elections::{is_score_better, ElectionScore, NposSolution}; +use sp_npos_elections::{ElectionScore, NposSolution}; use sp_runtime::{ traits::{Saturating, Zero}, RuntimeDebug, @@ -293,7 +293,7 @@ impl SignedSubmissions { let threshold = T::SolutionImprovementThreshold::get(); // if we haven't improved on the weakest score, don't change anything. - if !is_score_better(insert_score, weakest_score, threshold) { + if !insert_score.strict_threshold_better(weakest_score, threshold) { return InsertResult::NotInserted } @@ -592,7 +592,7 @@ mod tests { assert_eq!(balances(&99), (100, 0)); // make the solution invalid. - solution.score[0] += 1; + solution.score.minimal_stake += 1; assert_ok!(submit_with_witness(Origin::signed(99), solution)); assert_eq!(balances(&99), (95, 5)); @@ -618,7 +618,7 @@ mod tests { assert_ok!(submit_with_witness(Origin::signed(99), solution.clone())); // make the solution invalid and weaker. - solution.score[0] -= 1; + solution.score.minimal_stake -= 1; assert_ok!(submit_with_witness(Origin::signed(999), solution)); assert_eq!(balances(&99), (95, 5)); assert_eq!(balances(&999), (95, 5)); @@ -641,12 +641,18 @@ mod tests { for s in 0..SignedMaxSubmissions::get() { // score is always getting better - let solution = RawSolution { score: [(5 + s).into(), 0, 0], ..Default::default() }; + let solution = RawSolution { + score: ElectionScore { minimal_stake: (5 + s).into(), ..Default::default() }, + ..Default::default() + }; assert_ok!(submit_with_witness(Origin::signed(99), solution)); } // weaker. - let solution = RawSolution { score: [4, 0, 0], ..Default::default() }; + let solution = RawSolution { + score: ElectionScore { minimal_stake: 4, ..Default::default() }, + ..Default::default() + }; assert_noop!( submit_with_witness(Origin::signed(99), solution), @@ -663,27 +669,33 @@ mod tests { for s in 0..SignedMaxSubmissions::get() { // score is always getting better - let solution = RawSolution { score: [(5 + s).into(), 0, 0], ..Default::default() }; + let solution = RawSolution { + score: ElectionScore { minimal_stake: (5 + s).into(), ..Default::default() }, + ..Default::default() + }; assert_ok!(submit_with_witness(Origin::signed(99), solution)); } assert_eq!( MultiPhase::signed_submissions() .iter() - .map(|s| s.raw_solution.score[0]) + .map(|s| s.raw_solution.score.minimal_stake) .collect::>(), vec![5, 6, 7, 8, 9] ); // better. - let solution = RawSolution { score: [20, 0, 0], ..Default::default() }; + let solution = RawSolution { + score: ElectionScore { minimal_stake: 20, ..Default::default() }, + ..Default::default() + }; assert_ok!(submit_with_witness(Origin::signed(99), solution)); // the one with score 5 was rejected, the new one inserted. assert_eq!( MultiPhase::signed_submissions() .iter() - .map(|s| s.raw_solution.score[0]) + .map(|s| s.raw_solution.score.minimal_stake) .collect::>(), vec![6, 7, 8, 9, 20] ); @@ -698,30 +710,39 @@ mod tests { for s in 1..SignedMaxSubmissions::get() { // score is always getting better - let solution = RawSolution { score: [(5 + s).into(), 0, 0], ..Default::default() }; + let solution = RawSolution { + score: ElectionScore { minimal_stake: (5 + s).into(), ..Default::default() }, + ..Default::default() + }; assert_ok!(submit_with_witness(Origin::signed(99), solution)); } - let solution = RawSolution { score: [4, 0, 0], ..Default::default() }; + let solution = RawSolution { + score: ElectionScore { minimal_stake: 4, ..Default::default() }, + ..Default::default() + }; assert_ok!(submit_with_witness(Origin::signed(99), solution)); assert_eq!( MultiPhase::signed_submissions() .iter() - .map(|s| s.raw_solution.score[0]) + .map(|s| s.raw_solution.score.minimal_stake) .collect::>(), vec![4, 6, 7, 8, 9], ); // better. - let solution = RawSolution { score: [5, 0, 0], ..Default::default() }; + let solution = RawSolution { + score: ElectionScore { minimal_stake: 5, ..Default::default() }, + ..Default::default() + }; assert_ok!(submit_with_witness(Origin::signed(99), solution)); // the one with score 5 was rejected, the new one inserted. assert_eq!( MultiPhase::signed_submissions() .iter() - .map(|s| s.raw_solution.score[0]) + .map(|s| s.raw_solution.score.minimal_stake) .collect::>(), vec![5, 6, 7, 8, 9], ); @@ -736,7 +757,10 @@ mod tests { for s in 0..SignedMaxSubmissions::get() { // score is always getting better - let solution = RawSolution { score: [(5 + s).into(), 0, 0], ..Default::default() }; + let solution = RawSolution { + score: ElectionScore { minimal_stake: (5 + s).into(), ..Default::default() }, + ..Default::default() + }; assert_ok!(submit_with_witness(Origin::signed(99), solution)); } @@ -744,7 +768,10 @@ mod tests { assert_eq!(balances(&999).1, 0); // better. - let solution = RawSolution { score: [20, 0, 0], ..Default::default() }; + let solution = RawSolution { + score: ElectionScore { minimal_stake: 20, ..Default::default() }, + ..Default::default() + }; assert_ok!(submit_with_witness(Origin::signed(999), solution)); // got one bond back. @@ -760,19 +787,25 @@ mod tests { assert!(MultiPhase::current_phase().is_signed()); for i in 0..SignedMaxSubmissions::get() { - let solution = RawSolution { score: [(5 + i).into(), 0, 0], ..Default::default() }; + let solution = RawSolution { + score: ElectionScore { minimal_stake: (5 + i).into(), ..Default::default() }, + ..Default::default() + }; assert_ok!(submit_with_witness(Origin::signed(99), solution)); } assert_eq!( MultiPhase::signed_submissions() .iter() - .map(|s| s.raw_solution.score[0]) + .map(|s| s.raw_solution.score.minimal_stake) .collect::>(), vec![5, 6, 7] ); // 5 is not accepted. This will only cause processing with no benefit. - let solution = RawSolution { score: [5, 0, 0], ..Default::default() }; + let solution = RawSolution { + score: ElectionScore { minimal_stake: 5, ..Default::default() }, + ..Default::default() + }; assert_noop!( submit_with_witness(Origin::signed(99), solution), Error::::SignedQueueFull, @@ -800,13 +833,13 @@ mod tests { // make the solution invalidly better and submit. This ought to be slashed. let mut solution_999 = solution.clone(); - solution_999.score[0] += 1; + solution_999.score.minimal_stake += 1; assert_ok!(submit_with_witness(Origin::signed(999), solution_999)); // make the solution invalidly worse and submit. This ought to be suppressed and // returned. let mut solution_9999 = solution.clone(); - solution_9999.score[0] -= 1; + solution_9999.score.minimal_stake -= 1; assert_ok!(submit_with_witness(Origin::signed(9999), solution_9999)); assert_eq!( @@ -889,13 +922,19 @@ mod tests { for s in 0..SignedMaxSubmissions::get() { // score is always getting better - let solution = RawSolution { score: [(5 + s).into(), 0, 0], ..Default::default() }; + let solution = RawSolution { + score: ElectionScore { minimal_stake: (5 + s).into(), ..Default::default() }, + ..Default::default() + }; assert_ok!(submit_with_witness(Origin::signed(99), solution)); } // this solution has a higher score than any in the queue let solution = RawSolution { - score: [(5 + SignedMaxSubmissions::get()).into(), 0, 0], + score: ElectionScore { + minimal_stake: (5 + SignedMaxSubmissions::get()).into(), + ..Default::default() + }, ..Default::default() }; diff --git a/frame/election-provider-multi-phase/src/unsigned.rs b/frame/election-provider-multi-phase/src/unsigned.rs index 196147f8a470..510fc9fcdcca 100644 --- a/frame/election-provider-multi-phase/src/unsigned.rs +++ b/frame/election-provider-multi-phase/src/unsigned.rs @@ -26,10 +26,9 @@ use codec::Encode; use frame_election_provider_support::{NposSolver, PerThing128}; use frame_support::{dispatch::DispatchResult, ensure, traits::Get}; use frame_system::offchain::SubmitTransaction; -use sp_arithmetic::Perbill; use sp_npos_elections::{ - assignment_ratio_to_staked_normalized, assignment_staked_to_ratio_normalized, is_score_better, - ElectionResult, NposSolution, + assignment_ratio_to_staked_normalized, assignment_staked_to_ratio_normalized, ElectionResult, + NposSolution, }; use sp_runtime::{ offchain::storage::{MutateStorageError, StorageValueRef}, @@ -624,11 +623,9 @@ impl Pallet { // ensure score is being improved. Panic henceforth. ensure!( - Self::queued_solution().map_or(true, |q: ReadySolution<_>| is_score_better::( - raw_solution.score, - q.score, - T::SolutionImprovementThreshold::get() - )), + Self::queued_solution().map_or(true, |q: ReadySolution<_>| raw_solution + .score + .strict_threshold_better(q.score, T::SolutionImprovementThreshold::get())), Error::::PreDispatchWeakSubmission, ); @@ -748,11 +745,11 @@ mod tests { use frame_support::{ assert_noop, assert_ok, bounded_vec, dispatch::Dispatchable, traits::OffchainWorker, }; - use sp_npos_elections::IndexAssignment; + use sp_npos_elections::{ElectionScore, IndexAssignment}; use sp_runtime::{ offchain::storage_lock::{BlockAndTime, StorageLock}, traits::ValidateUnsigned, - ModuleError, PerU16, + ModuleError, PerU16, Perbill, }; type Assignment = crate::unsigned::Assignment; @@ -760,8 +757,10 @@ mod tests { #[test] fn validate_unsigned_retracts_wrong_phase() { ExtBuilder::default().desired_targets(0).build_and_execute(|| { - let solution = - RawSolution:: { score: [5, 0, 0], ..Default::default() }; + let solution = RawSolution:: { + score: ElectionScore { minimal_stake: 5, ..Default::default() }, + ..Default::default() + }; let call = Call::submit_unsigned { raw_solution: Box::new(solution.clone()), witness: witness(), @@ -833,8 +832,10 @@ mod tests { roll_to(25); assert!(MultiPhase::current_phase().is_unsigned()); - let solution = - RawSolution:: { score: [5, 0, 0], ..Default::default() }; + let solution = RawSolution:: { + score: ElectionScore { minimal_stake: 5, ..Default::default() }, + ..Default::default() + }; let call = Call::submit_unsigned { raw_solution: Box::new(solution.clone()), witness: witness(), @@ -849,7 +850,10 @@ mod tests { assert!(::pre_dispatch(&call).is_ok()); // set a better score - let ready = ReadySolution { score: [10, 0, 0], ..Default::default() }; + let ready = ReadySolution { + score: ElectionScore { minimal_stake: 10, ..Default::default() }, + ..Default::default() + }; >::put(ready); // won't work anymore. @@ -874,7 +878,10 @@ mod tests { roll_to(25); assert!(MultiPhase::current_phase().is_unsigned()); - let raw = RawSolution:: { score: [5, 0, 0], ..Default::default() }; + let raw = RawSolution:: { + score: ElectionScore { minimal_stake: 5, ..Default::default() }, + ..Default::default() + }; let call = Call::submit_unsigned { raw_solution: Box::new(raw.clone()), witness: witness() }; assert_eq!(raw.solution.unique_targets().len(), 0); @@ -900,8 +907,10 @@ mod tests { roll_to(25); assert!(MultiPhase::current_phase().is_unsigned()); - let solution = - RawSolution:: { score: [5, 0, 0], ..Default::default() }; + let solution = RawSolution:: { + score: ElectionScore { minimal_stake: 5, ..Default::default() }, + ..Default::default() + }; let call = Call::submit_unsigned { raw_solution: Box::new(solution.clone()), witness: witness(), @@ -930,8 +939,10 @@ mod tests { assert!(MultiPhase::current_phase().is_unsigned()); // This is in itself an invalid BS solution. - let solution = - RawSolution:: { score: [5, 0, 0], ..Default::default() }; + let solution = RawSolution:: { + score: ElectionScore { minimal_stake: 5, ..Default::default() }, + ..Default::default() + }; let call = Call::submit_unsigned { raw_solution: Box::new(solution.clone()), witness: witness(), @@ -950,8 +961,10 @@ mod tests { assert!(MultiPhase::current_phase().is_unsigned()); // This solution is unfeasible as well, but we won't even get there. - let solution = - RawSolution:: { score: [5, 0, 0], ..Default::default() }; + let solution = RawSolution:: { + score: ElectionScore { minimal_stake: 5, ..Default::default() }, + ..Default::default() + }; let mut correct_witness = witness(); correct_witness.voters += 1; @@ -1070,7 +1083,7 @@ mod tests { Box::new(solution), witness )); - assert_eq!(MultiPhase::queued_solution().unwrap().score[0], 10); + assert_eq!(MultiPhase::queued_solution().unwrap().score.minimal_stake, 10); // trial 1: a solution who's score is only 2, i.e. 20% better in the first element. let result = ElectionResult { @@ -1086,7 +1099,7 @@ mod tests { }; let (solution, _) = MultiPhase::prepare_election_result(result).unwrap(); // 12 is not 50% more than 10 - assert_eq!(solution.score[0], 12); + assert_eq!(solution.score.minimal_stake, 12); assert_noop!( MultiPhase::unsigned_pre_dispatch_checks(&solution), Error::::PreDispatchWeakSubmission, @@ -1107,7 +1120,7 @@ mod tests { ], }; let (solution, witness) = MultiPhase::prepare_election_result(result).unwrap(); - assert_eq!(solution.score[0], 17); + assert_eq!(solution.score.minimal_stake, 17); // and it is fine assert_ok!(MultiPhase::unsigned_pre_dispatch_checks(&solution)); diff --git a/primitives/arithmetic/src/lib.rs b/primitives/arithmetic/src/lib.rs index 92f8a708316d..273608a3d171 100644 --- a/primitives/arithmetic/src/lib.rs +++ b/primitives/arithmetic/src/lib.rs @@ -55,7 +55,7 @@ use traits::{BaseArithmetic, One, SaturatedConversion, Unsigned, Zero}; /// - `Ordering::Equal` otherwise. pub trait ThresholdOrd { /// Compare if `self` is `threshold` greater or less than `other`. - fn tcmp(&self, other: &T, epsilon: T) -> Ordering; + fn tcmp(&self, other: &T, threshold: T) -> Ordering; } impl ThresholdOrd for T diff --git a/primitives/npos-elections/fuzzer/src/phragmen_balancing.rs b/primitives/npos-elections/fuzzer/src/phragmen_balancing.rs index 8f782405df52..76641fc2c79f 100644 --- a/primitives/npos-elections/fuzzer/src/phragmen_balancing.rs +++ b/primitives/npos-elections/fuzzer/src/phragmen_balancing.rs @@ -23,8 +23,8 @@ use common::*; use honggfuzz::fuzz; use rand::{self, SeedableRng}; use sp_npos_elections::{ - assignment_ratio_to_staked_normalized, is_score_better, seq_phragmen, to_supports, - ElectionResult, EvaluateSupport, VoteWeight, + assignment_ratio_to_staked_normalized, seq_phragmen, to_supports, ElectionResult, + EvaluateSupport, VoteWeight, }; use sp_runtime::Perbill; @@ -60,7 +60,7 @@ fn main() { .unwrap(); let score = to_supports(staked.as_ref()).evaluate(); - if score[0] == 0 { + if score.minimal_stake == 0 { // such cases cannot be improved by balancing. return } @@ -80,7 +80,8 @@ fn main() { to_supports(staked.as_ref()).evaluate() }; - let enhance = is_score_better(balanced_score, unbalanced_score, Perbill::zero()); + let enhance = + balanced_score.strict_threshold_better(unbalanced_score, Perbill::zero()); println!( "iter = {} // {:?} -> {:?} [{}]", @@ -90,9 +91,9 @@ fn main() { // The only guarantee of balancing is such that the first and third element of the // score cannot decrease. assert!( - balanced_score[0] >= unbalanced_score[0] && - balanced_score[1] == unbalanced_score[1] && - balanced_score[2] <= unbalanced_score[2] + balanced_score.minimal_stake >= unbalanced_score.minimal_stake && + balanced_score.sum_stake == unbalanced_score.sum_stake && + balanced_score.sum_stake_squared <= unbalanced_score.sum_stake_squared ); } }); diff --git a/primitives/npos-elections/fuzzer/src/phragmms_balancing.rs b/primitives/npos-elections/fuzzer/src/phragmms_balancing.rs index f2b12b137883..09daf3f34d32 100644 --- a/primitives/npos-elections/fuzzer/src/phragmms_balancing.rs +++ b/primitives/npos-elections/fuzzer/src/phragmms_balancing.rs @@ -23,8 +23,8 @@ use common::*; use honggfuzz::fuzz; use rand::{self, SeedableRng}; use sp_npos_elections::{ - assignment_ratio_to_staked_normalized, is_score_better, phragmms, to_supports, ElectionResult, - EvaluateSupport, VoteWeight, + assignment_ratio_to_staked_normalized, phragmms, to_supports, ElectionResult, EvaluateSupport, + VoteWeight, }; use sp_runtime::Perbill; @@ -60,7 +60,7 @@ fn main() { .unwrap(); let score = to_supports(&staked).evaluate(); - if score[0] == 0 { + if score.minimal_stake == 0 { // such cases cannot be improved by balancing. return } @@ -77,7 +77,7 @@ fn main() { to_supports(staked.as_ref()).evaluate() }; - let enhance = is_score_better(balanced_score, unbalanced_score, Perbill::zero()); + let enhance = balanced_score.strict_threshold_better(unbalanced_score, Perbill::zero()); println!( "iter = {} // {:?} -> {:?} [{}]", @@ -87,9 +87,9 @@ fn main() { // The only guarantee of balancing is such that the first and third element of the score // cannot decrease. assert!( - balanced_score[0] >= unbalanced_score[0] && - balanced_score[1] == unbalanced_score[1] && - balanced_score[2] <= unbalanced_score[2] + balanced_score.minimal_stake >= unbalanced_score.minimal_stake && + balanced_score.sum_stake == unbalanced_score.sum_stake && + balanced_score.sum_stake_squared <= unbalanced_score.sum_stake_squared ); }); } diff --git a/primitives/npos-elections/src/lib.rs b/primitives/npos-elections/src/lib.rs index 7b3b09a4c734..7bd1a4b7f69b 100644 --- a/primitives/npos-elections/src/lib.rs +++ b/primitives/npos-elections/src/lib.rs @@ -74,11 +74,12 @@ #![cfg_attr(not(feature = "std"), no_std)] +use scale_info::TypeInfo; use sp_arithmetic::{traits::Zero, Normalizable, PerThing, Rational128, ThresholdOrd}; use sp_core::RuntimeDebug; use sp_std::{cell::RefCell, cmp::Ordering, collections::btree_map::BTreeMap, prelude::*, rc::Rc}; -use codec::{Decode, Encode}; +use codec::{Decode, Encode, MaxEncodedLen}; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; @@ -144,9 +145,86 @@ pub type VoteWeight = u64; /// A type in which performing operations on vote weights are safe. pub type ExtendedBalance = u128; -/// The score of an assignment. This can be computed from the support map via -/// [`EvaluateSupport::evaluate`]. -pub type ElectionScore = [ExtendedBalance; 3]; +/// The score of an election. This is the main measure of an election's quality. +/// +/// By definition, the order of significance in [`ElectionScore`] is: +/// +/// 1. `minimal_stake`. +/// 2. `sum_stake`. +/// 3. `sum_stake_squared`. +#[derive(Clone, Copy, PartialEq, Eq, Encode, Decode, MaxEncodedLen, TypeInfo, Debug, Default)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct ElectionScore { + /// The minimal winner, in terms of total backing stake. + /// + /// This parameter should be maximized. + pub minimal_stake: ExtendedBalance, + /// The sum of the total backing of all winners. + /// + /// This parameter should maximized + pub sum_stake: ExtendedBalance, + /// The sum squared of the total backing of all winners, aka. the variance. + /// + /// Ths parameter should be minimized. + pub sum_stake_squared: ExtendedBalance, +} + +impl ElectionScore { + /// Iterate over the inner items, first visiting the most significant one. + fn iter_by_significance(self) -> impl Iterator { + [self.minimal_stake, self.sum_stake, self.sum_stake_squared].into_iter() + } + + /// Compares two sets of election scores based on desirability, returning true if `self` is + /// strictly `threshold` better than `other`. In other words, each element of `self` must be + /// `self * threshold` better than `other`. + /// + /// Evaluation is done based on the order of significance of the fields of [`ElectionScore`]. + pub fn strict_threshold_better(self, other: Self, threshold: impl PerThing) -> bool { + match self + .iter_by_significance() + .zip(other.iter_by_significance()) + .map(|(this, that)| (this.ge(&that), this.tcmp(&that, threshold.mul_ceil(that)))) + .collect::>() + .as_slice() + { + // threshold better in the `score.minimal_stake`, accept. + [(x, Ordering::Greater), _, _] => { + debug_assert!(x); + true + }, + + // less than threshold better in `score.minimal_stake`, but more than threshold better + // in `score.sum_stake`. + [(true, Ordering::Equal), (_, Ordering::Greater), _] => true, + + // less than threshold better in `score.minimal_stake` and `score.sum_stake`, but more + // than threshold better in `score.sum_stake_squared`. + [(true, Ordering::Equal), (true, Ordering::Equal), (_, Ordering::Less)] => true, + + // anything else is not a good score. + _ => false, + } + } +} + +impl sp_std::cmp::Ord for ElectionScore { + fn cmp(&self, other: &Self) -> Ordering { + // we delegate this to the lexicographic cmp of slices`, and to incorporate that we want the + // third element to be minimized, we swap them. + [self.minimal_stake, self.sum_stake, other.sum_stake_squared].cmp(&[ + other.minimal_stake, + other.sum_stake, + self.sum_stake_squared, + ]) + } +} + +impl sp_std::cmp::PartialOrd for ElectionScore { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} /// A pointer to a candidate struct with interior mutability. pub type CandidatePtr = Rc>>; @@ -353,7 +431,7 @@ pub struct ElectionResult { /// /// This, at the current version, resembles the `Exposure` defined in the Staking pallet, yet they /// do not necessarily have to be the same. -#[derive(RuntimeDebug, Encode, Decode, Clone, Eq, PartialEq, scale_info::TypeInfo)] +#[derive(RuntimeDebug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct Support { /// Total support. @@ -418,49 +496,22 @@ pub trait EvaluateSupport { impl EvaluateSupport for Supports { fn evaluate(&self) -> ElectionScore { - let mut min_support = ExtendedBalance::max_value(); - let mut sum: ExtendedBalance = Zero::zero(); + let mut minimal_stake = ExtendedBalance::max_value(); + let mut sum_stake: ExtendedBalance = Zero::zero(); // NOTE: The third element might saturate but fine for now since this will run on-chain and // need to be fast. - let mut sum_squared: ExtendedBalance = Zero::zero(); + let mut sum_stake_squared: ExtendedBalance = Zero::zero(); + for (_, support) in self { - sum = sum.saturating_add(support.total); + sum_stake = sum_stake.saturating_add(support.total); let squared = support.total.saturating_mul(support.total); - sum_squared = sum_squared.saturating_add(squared); - if support.total < min_support { - min_support = support.total; + sum_stake_squared = sum_stake_squared.saturating_add(squared); + if support.total < minimal_stake { + minimal_stake = support.total; } } - [min_support, sum, sum_squared] - } -} -/// Compares two sets of election scores based on desirability and returns true if `this` is better -/// than `that`. -/// -/// Evaluation is done in a lexicographic manner, and if each element of `this` is `that * epsilon` -/// greater or less than `that`. -/// -/// Note that the third component should be minimized. -pub fn is_score_better(this: ElectionScore, that: ElectionScore, epsilon: P) -> bool { - match this - .iter() - .zip(that.iter()) - .map(|(thi, tha)| (thi.ge(&tha), thi.tcmp(&tha, epsilon.mul_ceil(*tha)))) - .collect::>() - .as_slice() - { - // epsilon better in the score[0], accept. - [(_, Ordering::Greater), _, _] => true, - - // less than epsilon better in score[0], but more than epsilon better in the second. - [(true, Ordering::Equal), (_, Ordering::Greater), _] => true, - - // less than epsilon better in score[0, 1], but more than epsilon better in the third - [(true, Ordering::Equal), (true, Ordering::Equal), (_, Ordering::Less)] => true, - - // anything else is not a good score. - _ => false, + ElectionScore { minimal_stake, sum_stake, sum_stake_squared } } } diff --git a/primitives/npos-elections/src/tests.rs b/primitives/npos-elections/src/tests.rs index c6748b29e985..b199fdd1af77 100644 --- a/primitives/npos-elections/src/tests.rs +++ b/primitives/npos-elections/src/tests.rs @@ -18,9 +18,9 @@ //! Tests for npos-elections. use crate::{ - balancing, helpers::*, is_score_better, mock::*, seq_phragmen, seq_phragmen_core, setup_inputs, - to_support_map, Assignment, ElectionResult, ExtendedBalance, IndexAssignment, NposSolution, - StakedAssignment, Support, Voter, + balancing, helpers::*, mock::*, seq_phragmen, seq_phragmen_core, setup_inputs, to_support_map, + Assignment, ElectionResult, ExtendedBalance, IndexAssignment, NposSolution, StakedAssignment, + Support, Voter, }; use rand::{self, SeedableRng}; use sp_arithmetic::{PerU16, Perbill, Percent, Permill}; @@ -792,6 +792,21 @@ mod assignment_convert_normalize { mod score { use super::*; + use crate::ElectionScore; + use sp_arithmetic::PerThing; + + /// NOTE: in tests, we still use the legacy [u128; 3] since it is more compact. Each `u128` + /// corresponds to element at the respective field index of `ElectionScore`. + impl From<[ExtendedBalance; 3]> for ElectionScore { + fn from(t: [ExtendedBalance; 3]) -> Self { + Self { minimal_stake: t[0], sum_stake: t[1], sum_stake_squared: t[2] } + } + } + + fn is_score_better(this: [u128; 3], that: [u128; 3], p: impl PerThing) -> bool { + ElectionScore::from(this).strict_threshold_better(ElectionScore::from(that), p) + } + #[test] fn score_comparison_is_lexicographical_no_epsilon() { let epsilon = Perbill::zero(); @@ -883,6 +898,26 @@ mod score { false, ); } + + #[test] + fn ord_works() { + // equal only when all elements are equal + assert!(ElectionScore::from([10, 5, 15]) == ElectionScore::from([10, 5, 15])); + assert!(ElectionScore::from([10, 5, 15]) != ElectionScore::from([9, 5, 15])); + assert!(ElectionScore::from([10, 5, 15]) != ElectionScore::from([10, 5, 14])); + + // first element greater, rest don't matter + assert!(ElectionScore::from([10, 5, 15]) > ElectionScore::from([8, 5, 25])); + assert!(ElectionScore::from([10, 5, 15]) > ElectionScore::from([9, 20, 5])); + + // second element greater, rest don't matter + assert!(ElectionScore::from([10, 5, 15]) > ElectionScore::from([10, 4, 25])); + assert!(ElectionScore::from([10, 5, 15]) > ElectionScore::from([10, 4, 5])); + + // second element is less, rest don't matter. Note that this is swapped. + assert!(ElectionScore::from([10, 5, 15]) > ElectionScore::from([10, 5, 16])); + assert!(ElectionScore::from([10, 5, 15]) > ElectionScore::from([10, 5, 25])); + } } mod solution_type { From e6def65920d30029e42d498cb07cec5dd433b927 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Wed, 16 Feb 2022 11:49:31 +0100 Subject: [PATCH 504/695] Measure per byte and not kb for certain benchmarks (#10863) --- frame/contracts/src/benchmarking/mod.rs | 28 +- frame/contracts/src/lib.rs | 13 +- frame/contracts/src/tests.rs | 2 +- frame/contracts/src/wasm/code_cache.rs | 6 +- frame/contracts/src/weights.rs | 1244 +++++++++++------------ 5 files changed, 645 insertions(+), 648 deletions(-) diff --git a/frame/contracts/src/benchmarking/mod.rs b/frame/contracts/src/benchmarking/mod.rs index 3a749095b955..827c729e1615 100644 --- a/frame/contracts/src/benchmarking/mod.rs +++ b/frame/contracts/src/benchmarking/mod.rs @@ -231,8 +231,8 @@ benchmarks! { // first time after a new schedule was deployed: For every new schedule a contract needs // to re-run the instrumentation once. reinstrument { - let c in 0 .. T::Schedule::get().limits.code_len / 1024; - let WasmModule { code, hash, .. } = WasmModule::::sized(c * 1024, Location::Call); + let c in 0 .. T::Schedule::get().limits.code_len; + let WasmModule { code, hash, .. } = WasmModule::::sized(c, Location::Call); Contracts::::store_code_raw(code, whitelisted_caller())?; let schedule = T::Schedule::get(); let mut gas_meter = GasMeter::new(Weight::MAX); @@ -241,15 +241,15 @@ benchmarks! { Contracts::::reinstrument_module(&mut module, &schedule)?; } - // This benchmarks the overhead of loading a code of size `c` kb from storage and into + // This benchmarks the overhead of loading a code of size `c` byte from storage and into // the sandbox. This does **not** include the actual execution for which the gas meter // is responsible. This is achieved by generating all code to the `deploy` function // which is in the wasm module but not executed on `call`. // The results are supposed to be used as `call_with_code_kb(c) - call_with_code_kb(0)`. - call_with_code_kb { - let c in 0 .. T::Schedule::get().limits.code_len / 1024; + call_with_code_per_byte { + let c in 0 .. T::Schedule::get().limits.code_len; let instance = Contract::::with_caller( - whitelisted_caller(), WasmModule::sized(c * 1024, Location::Deploy), vec![], + whitelisted_caller(), WasmModule::sized(c, Location::Deploy), vec![], )?; let value = T::Currency::minimum_balance(); let origin = RawOrigin::Signed(instance.caller.clone()); @@ -271,13 +271,13 @@ benchmarks! { // We cannot let `c` grow to the maximum code size because the code is not allowed // to be larger than the maximum size **after instrumentation**. instantiate_with_code { - let c in 0 .. Perbill::from_percent(49).mul_ceil(T::Schedule::get().limits.code_len) / 1024; - let s in 0 .. code::max_pages::() * 64; - let salt = vec![42u8; (s * 1024) as usize]; + let c in 0 .. Perbill::from_percent(49).mul_ceil(T::Schedule::get().limits.code_len); + let s in 0 .. code::max_pages::() * 64 * 1024; + let salt = vec![42u8; s as usize]; let value = T::Currency::minimum_balance(); let caller = whitelisted_caller(); T::Currency::make_free_balance_be(&caller, caller_funding::()); - let WasmModule { code, hash, .. } = WasmModule::::sized(c * 1024, Location::Call); + let WasmModule { code, hash, .. } = WasmModule::::sized(c, Location::Call); let origin = RawOrigin::Signed(caller.clone()); let addr = Contracts::::contract_address(&caller, &hash, &salt); }: _(origin, value, Weight::MAX, None, code, vec![], salt) @@ -299,8 +299,8 @@ benchmarks! { // Instantiate uses a dummy contract constructor to measure the overhead of the instantiate. // `s`: Size of the salt in kilobytes. instantiate { - let s in 0 .. code::max_pages::() * 64; - let salt = vec![42u8; (s * 1024) as usize]; + let s in 0 .. code::max_pages::() * 64 * 1024; + let salt = vec![42u8; s as usize]; let value = T::Currency::minimum_balance(); let caller = whitelisted_caller(); T::Currency::make_free_balance_be(&caller, caller_funding::()); @@ -360,10 +360,10 @@ benchmarks! { // We cannot let `c` grow to the maximum code size because the code is not allowed // to be larger than the maximum size **after instrumentation**. upload_code { - let c in 0 .. Perbill::from_percent(50).mul_ceil(T::Schedule::get().limits.code_len / 1024); + let c in 0 .. Perbill::from_percent(50).mul_ceil(T::Schedule::get().limits.code_len); let caller = whitelisted_caller(); T::Currency::make_free_balance_be(&caller, caller_funding::()); - let WasmModule { code, hash, .. } = WasmModule::::sized(c * 1024, Location::Call); + let WasmModule { code, hash, .. } = WasmModule::::sized(c, Location::Call); let origin = RawOrigin::Signed(caller.clone()); }: _(origin, code, None) verify { diff --git a/frame/contracts/src/lib.rs b/frame/contracts/src/lib.rs index 9e7b61301e7d..037e3f1d33ae 100644 --- a/frame/contracts/src/lib.rs +++ b/frame/contracts/src/lib.rs @@ -410,10 +410,7 @@ pub mod pallet { /// - The `value` is transferred to the new account. /// - The `deploy` function is executed in the context of the newly-created account. #[pallet::weight( - T::WeightInfo::instantiate_with_code( - code.len() as u32 / 1024, - salt.len() as u32 / 1024, - ) + T::WeightInfo::instantiate_with_code(code.len() as u32, salt.len() as u32) .saturating_add(*gas_limit) )] pub fn instantiate_with_code( @@ -445,7 +442,7 @@ pub mod pallet { } output.gas_meter.into_dispatch_result( output.result.map(|(_address, result)| result), - T::WeightInfo::instantiate_with_code(code_len / 1024, salt_len / 1024), + T::WeightInfo::instantiate_with_code(code_len, salt_len), ) } @@ -455,7 +452,7 @@ pub mod pallet { /// code deployment step. Instead, the `code_hash` of an on-chain deployed wasm binary /// must be supplied. #[pallet::weight( - T::WeightInfo::instantiate(salt.len() as u32 / 1024).saturating_add(*gas_limit) + T::WeightInfo::instantiate(salt.len() as u32).saturating_add(*gas_limit) )] pub fn instantiate( origin: OriginFor, @@ -485,7 +482,7 @@ pub mod pallet { } output.gas_meter.into_dispatch_result( output.result.map(|(_address, output)| output), - T::WeightInfo::instantiate(salt_len / 1024), + T::WeightInfo::instantiate(salt_len), ) } @@ -505,7 +502,7 @@ pub mod pallet { /// To avoid this situation a constructor could employ access control so that it can /// only be instantiated by permissioned entities. The same is true when uploading /// through [`Self::instantiate_with_code`]. - #[pallet::weight(T::WeightInfo::upload_code(code.len() as u32 / 1024))] + #[pallet::weight(T::WeightInfo::upload_code(code.len() as u32))] pub fn upload_code( origin: OriginFor, code: Vec, diff --git a/frame/contracts/src/tests.rs b/frame/contracts/src/tests.rs index 486e84da7547..9ea23e974b21 100644 --- a/frame/contracts/src/tests.rs +++ b/frame/contracts/src/tests.rs @@ -1998,7 +1998,7 @@ fn reinstrument_does_charge() { assert!(result2.gas_consumed > result1.gas_consumed); assert_eq!( result2.gas_consumed, - result1.gas_consumed + ::WeightInfo::reinstrument(code_len / 1024), + result1.gas_consumed + ::WeightInfo::reinstrument(code_len), ); }); } diff --git a/frame/contracts/src/wasm/code_cache.rs b/frame/contracts/src/wasm/code_cache.rs index 9fc49ac9a502..ee5cdd530721 100644 --- a/frame/contracts/src/wasm/code_cache.rs +++ b/frame/contracts/src/wasm/code_cache.rs @@ -216,9 +216,9 @@ impl Token for CodeToken { // point because when charging the general weight for calling the contract we not know the // size of the contract. match *self { - Reinstrument(len) => T::WeightInfo::reinstrument(len / 1024), - Load(len) => T::WeightInfo::call_with_code_kb(len / 1024) - .saturating_sub(T::WeightInfo::call_with_code_kb(0)), + Reinstrument(len) => T::WeightInfo::reinstrument(len), + Load(len) => T::WeightInfo::call_with_code_per_byte(len) + .saturating_sub(T::WeightInfo::call_with_code_per_byte(0)), } } } diff --git a/frame/contracts/src/weights.rs b/frame/contracts/src/weights.rs index c43e98bb8ac4..fd32c247ba72 100644 --- a/frame/contracts/src/weights.rs +++ b/frame/contracts/src/weights.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_contracts //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-02-08, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-02-16, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -48,7 +48,7 @@ pub trait WeightInfo { fn on_initialize_per_trie_key(k: u32, ) -> Weight; fn on_initialize_per_queue_item(q: u32, ) -> Weight; fn reinstrument(c: u32, ) -> Weight; - fn call_with_code_kb(c: u32, ) -> Weight; + fn call_with_code_per_byte(c: u32, ) -> Weight; fn instantiate_with_code(c: u32, s: u32, ) -> Weight; fn instantiate(s: u32, ) -> Weight; fn call() -> Weight; @@ -160,32 +160,32 @@ pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize() -> Weight { - (1_560_000 as Weight) + (1_588_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn on_initialize_per_trie_key(k: u32, ) -> Weight { - (7_843_000 as Weight) + (6_994_000 as Weight) // Standard Error: 0 - .saturating_add((749_000 as Weight).saturating_mul(k as Weight)) + .saturating_add((743_000 as Weight).saturating_mul(k as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) } // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize_per_queue_item(q: u32, ) -> Weight { - (3_228_000 as Weight) - // Standard Error: 5_000 - .saturating_add((2_257_000 as Weight).saturating_mul(q as Weight)) + (2_831_000 as Weight) + // Standard Error: 3_000 + .saturating_add((2_232_000 as Weight).saturating_mul(q as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Contracts PristineCode (r:1 w:0) // Storage: Contracts CodeStorage (r:0 w:1) fn reinstrument(c: u32, ) -> Weight { - (20_531_000 as Weight) - // Standard Error: 34_000 - .saturating_add((66_014_000 as Weight).saturating_mul(c as Weight)) + (17_839_000 as Weight) + // Standard Error: 0 + .saturating_add((64_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -193,10 +193,10 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) - fn call_with_code_kb(c: u32, ) -> Weight { - (295_703_000 as Weight) - // Standard Error: 53_000 - .saturating_add((57_661_000 as Weight).saturating_mul(c as Weight)) + fn call_with_code_per_byte(c: u32, ) -> Weight { + (222_400_000 as Weight) + // Standard Error: 0 + .saturating_add((56_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -208,11 +208,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn instantiate_with_code(c: u32, s: u32, ) -> Weight { - (332_572_000 as Weight) - // Standard Error: 125_000 - .saturating_add((149_095_000 as Weight).saturating_mul(c as Weight)) - // Standard Error: 7_000 - .saturating_add((1_779_000 as Weight).saturating_mul(s as Weight)) + (283_144_000 as Weight) + // Standard Error: 0 + .saturating_add((140_000 as Weight).saturating_mul(c as Weight)) + // Standard Error: 0 + .saturating_add((2_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } @@ -223,9 +223,9 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn instantiate(s: u32, ) -> Weight { - (222_992_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_759_000 as Weight).saturating_mul(s as Weight)) + (171_794_000 as Weight) + // Standard Error: 0 + .saturating_add((2_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } @@ -234,7 +234,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call() -> Weight { - (189_003_000 as Weight) + (140_234_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -242,9 +242,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn upload_code(c: u32, ) -> Weight { - (52_521_000 as Weight) - // Standard Error: 36_000 - .saturating_add((66_486_000 as Weight).saturating_mul(c as Weight)) + (49_467_000 as Weight) + // Standard Error: 0 + .saturating_add((66_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -252,7 +252,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:0 w:1) // Storage: Contracts PristineCode (r:0 w:1) fn remove_code() -> Weight { - (24_705_000 as Weight) + (24_915_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -261,9 +261,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_caller(r: u32, ) -> Weight { - (300_165_000 as Weight) - // Standard Error: 125_000 - .saturating_add((49_828_000 as Weight).saturating_mul(r as Weight)) + (218_957_000 as Weight) + // Standard Error: 114_000 + .saturating_add((49_881_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -272,9 +272,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_is_contract(r: u32, ) -> Weight { - (179_488_000 as Weight) - // Standard Error: 718_000 - .saturating_add((375_855_000 as Weight).saturating_mul(r as Weight)) + (76_490_000 as Weight) + // Standard Error: 856_000 + .saturating_add((375_305_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -284,9 +284,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_caller_is_origin(r: u32, ) -> Weight { - (295_198_000 as Weight) - // Standard Error: 79_000 - .saturating_add((21_948_000 as Weight).saturating_mul(r as Weight)) + (213_485_000 as Weight) + // Standard Error: 76_000 + .saturating_add((22_020_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -295,9 +295,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_address(r: u32, ) -> Weight { - (300_366_000 as Weight) - // Standard Error: 111_000 - .saturating_add((49_435_000 as Weight).saturating_mul(r as Weight)) + (218_468_000 as Weight) + // Standard Error: 108_000 + .saturating_add((49_457_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -306,9 +306,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas_left(r: u32, ) -> Weight { - (299_800_000 as Weight) - // Standard Error: 87_000 - .saturating_add((49_002_000 as Weight).saturating_mul(r as Weight)) + (218_950_000 as Weight) + // Standard Error: 99_000 + .saturating_add((48_859_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -317,9 +317,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_balance(r: u32, ) -> Weight { - (303_057_000 as Weight) - // Standard Error: 175_000 - .saturating_add((139_293_000 as Weight).saturating_mul(r as Weight)) + (226_714_000 as Weight) + // Standard Error: 111_000 + .saturating_add((141_924_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -328,9 +328,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_value_transferred(r: u32, ) -> Weight { - (299_754_000 as Weight) - // Standard Error: 93_000 - .saturating_add((48_945_000 as Weight).saturating_mul(r as Weight)) + (216_673_000 as Weight) + // Standard Error: 90_000 + .saturating_add((49_367_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -339,9 +339,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_minimum_balance(r: u32, ) -> Weight { - (302_229_000 as Weight) - // Standard Error: 128_000 - .saturating_add((49_007_000 as Weight).saturating_mul(r as Weight)) + (215_859_000 as Weight) + // Standard Error: 104_000 + .saturating_add((49_334_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -350,9 +350,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_block_number(r: u32, ) -> Weight { - (300_772_000 as Weight) - // Standard Error: 114_000 - .saturating_add((48_794_000 as Weight).saturating_mul(r as Weight)) + (216_419_000 as Weight) + // Standard Error: 109_000 + .saturating_add((49_417_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -361,9 +361,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_now(r: u32, ) -> Weight { - (301_936_000 as Weight) - // Standard Error: 119_000 - .saturating_add((48_839_000 as Weight).saturating_mul(r as Weight)) + (218_799_000 as Weight) + // Standard Error: 108_000 + .saturating_add((48_631_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -373,9 +373,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0) fn seal_weight_to_fee(r: u32, ) -> Weight { - (304_935_000 as Weight) - // Standard Error: 146_000 - .saturating_add((121_871_000 as Weight).saturating_mul(r as Weight)) + (215_968_000 as Weight) + // Standard Error: 147_000 + .saturating_add((122_978_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -384,9 +384,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas(r: u32, ) -> Weight { - (178_176_000 as Weight) - // Standard Error: 52_000 - .saturating_add((24_960_000 as Weight).saturating_mul(r as Weight)) + (127_183_000 as Weight) + // Standard Error: 35_000 + .saturating_add((24_523_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -395,9 +395,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input(r: u32, ) -> Weight { - (297_394_000 as Weight) - // Standard Error: 140_000 - .saturating_add((49_199_000 as Weight).saturating_mul(r as Weight)) + (217_535_000 as Weight) + // Standard Error: 91_000 + .saturating_add((48_400_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -406,9 +406,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input_per_kb(n: u32, ) -> Weight { - (374_409_000 as Weight) - // Standard Error: 3_000 - .saturating_add((11_924_000 as Weight).saturating_mul(n as Weight)) + (297_539_000 as Weight) + // Standard Error: 5_000 + .saturating_add((11_870_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -417,9 +417,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return(r: u32, ) -> Weight { - (292_278_000 as Weight) - // Standard Error: 114_000 - .saturating_add((1_474_000 as Weight).saturating_mul(r as Weight)) + (211_807_000 as Weight) + // Standard Error: 160_000 + .saturating_add((1_717_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -428,9 +428,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return_per_kb(n: u32, ) -> Weight { - (294_714_000 as Weight) + (213_139_000 as Weight) // Standard Error: 0 - .saturating_add((230_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((197_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -441,9 +441,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts DeletionQueue (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_terminate(r: u32, ) -> Weight { - (297_589_000 as Weight) - // Standard Error: 2_835_000 - .saturating_add((53_498_000 as Weight).saturating_mul(r as Weight)) + (215_292_000 as Weight) + // Standard Error: 390_000 + .saturating_add((52_831_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((4 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -455,9 +455,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) fn seal_random(r: u32, ) -> Weight { - (296_371_000 as Weight) - // Standard Error: 220_000 - .saturating_add((160_881_000 as Weight).saturating_mul(r as Weight)) + (215_802_000 as Weight) + // Standard Error: 132_000 + .saturating_add((159_065_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -466,9 +466,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_deposit_event(r: u32, ) -> Weight { - (308_401_000 as Weight) - // Standard Error: 202_000 - .saturating_add((277_771_000 as Weight).saturating_mul(r as Weight)) + (225_069_000 as Weight) + // Standard Error: 201_000 + .saturating_add((292_145_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -478,11 +478,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: System EventTopics (r:100 w:100) fn seal_deposit_event_per_topic_and_kb(t: u32, n: u32, ) -> Weight { - (625_100_000 as Weight) - // Standard Error: 2_053_000 - .saturating_add((284_765_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 404_000 - .saturating_add((85_893_000 as Weight).saturating_mul(n as Weight)) + (519_617_000 as Weight) + // Standard Error: 1_751_000 + .saturating_add((290_832_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 345_000 + .saturating_add((82_584_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(t as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -493,17 +493,17 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_debug_message(r: u32, ) -> Weight { - (182_141_000 as Weight) - // Standard Error: 134_000 - .saturating_add((41_928_000 as Weight).saturating_mul(r as Weight)) + (132_245_000 as Weight) + // Standard Error: 75_000 + .saturating_add((41_274_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage(r: u32, ) -> Weight { - (139_030_000 as Weight) - // Standard Error: 1_038_000 - .saturating_add((405_168_000 as Weight).saturating_mul(r as Weight)) + (48_288_000 as Weight) + // Standard Error: 1_024_000 + .saturating_add((408_264_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -511,25 +511,25 @@ impl WeightInfo for SubstrateWeight { } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage_per_new_kb(n: u32, ) -> Weight { - (689_591_000 as Weight) - // Standard Error: 275_000 - .saturating_add((31_438_000 as Weight).saturating_mul(n as Weight)) + (607_246_000 as Weight) + // Standard Error: 252_000 + .saturating_add((28_722_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage_per_old_kb(n: u32, ) -> Weight { - (709_965_000 as Weight) - // Standard Error: 340_000 - .saturating_add((11_182_000 as Weight).saturating_mul(n as Weight)) + (623_983_000 as Weight) + // Standard Error: 305_000 + .saturating_add((11_374_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage(r: u32, ) -> Weight { - (169_937_000 as Weight) - // Standard Error: 883_000 - .saturating_add((389_090_000 as Weight).saturating_mul(r as Weight)) + (91_727_000 as Weight) + // Standard Error: 837_000 + .saturating_add((383_577_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -537,51 +537,51 @@ impl WeightInfo for SubstrateWeight { } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage_per_kb(n: u32, ) -> Weight { - (695_589_000 as Weight) - // Standard Error: 268_000 - .saturating_add((10_530_000 as Weight).saturating_mul(n as Weight)) + (604_749_000 as Weight) + // Standard Error: 251_000 + .saturating_add((11_086_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage(r: u32, ) -> Weight { - (195_080_000 as Weight) - // Standard Error: 607_000 - .saturating_add((328_903_000 as Weight).saturating_mul(r as Weight)) + (107_805_000 as Weight) + // Standard Error: 722_000 + .saturating_add((326_494_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage_per_kb(n: u32, ) -> Weight { - (647_422_000 as Weight) - // Standard Error: 361_000 - .saturating_add((68_849_000 as Weight).saturating_mul(n as Weight)) + (564_604_000 as Weight) + // Standard Error: 360_000 + .saturating_add((65_184_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(104 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_contains_storage(r: u32, ) -> Weight { - (198_907_000 as Weight) - // Standard Error: 658_000 - .saturating_add((295_368_000 as Weight).saturating_mul(r as Weight)) + (122_105_000 as Weight) + // Standard Error: 560_000 + .saturating_add((291_458_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_contains_storage_per_kb(n: u32, ) -> Weight { - (599_284_000 as Weight) - // Standard Error: 243_000 - .saturating_add((9_923_000 as Weight).saturating_mul(n as Weight)) + (512_580_000 as Weight) + // Standard Error: 245_000 + .saturating_add((10_171_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(104 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage(r: u32, ) -> Weight { - (170_700_000 as Weight) - // Standard Error: 887_000 - .saturating_add((422_448_000 as Weight).saturating_mul(r as Weight)) + (81_220_000 as Weight) + // Standard Error: 933_000 + .saturating_add((418_532_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -589,9 +589,9 @@ impl WeightInfo for SubstrateWeight { } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage_per_kb(n: u32, ) -> Weight { - (743_584_000 as Weight) - // Standard Error: 403_000 - .saturating_add((69_763_000 as Weight).saturating_mul(n as Weight)) + (652_330_000 as Weight) + // Standard Error: 357_000 + .saturating_add((65_711_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().writes(103 as Weight)) } @@ -600,9 +600,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_transfer(r: u32, ) -> Weight { - (208_815_000 as Weight) - // Standard Error: 1_078_000 - .saturating_add((1_719_660_000 as Weight).saturating_mul(r as Weight)) + (126_544_000 as Weight) + // Standard Error: 1_198_000 + .saturating_add((1_796_593_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -614,8 +614,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) fn seal_call(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 3_471_000 - .saturating_add((27_917_429_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 3_033_000 + .saturating_add((19_788_005_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -627,8 +627,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) fn seal_delegate_call(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 13_012_000 - .saturating_add((28_044_371_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 6_663_000 + .saturating_add((19_835_985_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads((99 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -637,11 +637,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:2 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_call_per_transfer_clone_kb(t: u32, c: u32, ) -> Weight { - (15_964_304_000 as Weight) - // Standard Error: 19_327_000 - .saturating_add((1_629_626_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 8_000 - .saturating_add((11_992_000 as Weight).saturating_mul(c as Weight)) + (10_957_494_000 as Weight) + // Standard Error: 13_908_000 + .saturating_add((1_622_630_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 6_000 + .saturating_add((11_960_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().reads((101 as Weight).saturating_mul(t as Weight))) .saturating_add(T::DbWeight::get().writes(101 as Weight)) @@ -655,8 +655,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts OwnerInfoOf (r:100 w:100) fn seal_instantiate(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 50_849_000 - .saturating_add((35_608_311_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 48_191_000 + .saturating_add((27_587_375_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().reads((400 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -669,11 +669,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts AccountCounter (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_instantiate_per_transfer_salt_kb(t: u32, s: u32, ) -> Weight { - (19_455_191_000 as Weight) - // Standard Error: 57_478_000 - .saturating_add((786_148_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 27_000 - .saturating_add((160_385_000 as Weight).saturating_mul(s as Weight)) + (14_504_226_000 as Weight) + // Standard Error: 66_350_000 + .saturating_add((912_874_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 31_000 + .saturating_add((157_415_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(207 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(t as Weight))) .saturating_add(T::DbWeight::get().writes(205 as Weight)) @@ -684,9 +684,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256(r: u32, ) -> Weight { - (294_686_000 as Weight) - // Standard Error: 123_000 - .saturating_add((81_172_000 as Weight).saturating_mul(r as Weight)) + (216_771_000 as Weight) + // Standard Error: 127_000 + .saturating_add((79_994_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -695,9 +695,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256_per_kb(n: u32, ) -> Weight { - (276_895_000 as Weight) - // Standard Error: 35_000 - .saturating_add((469_007_000 as Weight).saturating_mul(n as Weight)) + (376_960_000 as Weight) + // Standard Error: 24_000 + .saturating_add((465_507_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -706,9 +706,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256(r: u32, ) -> Weight { - (295_476_000 as Weight) - // Standard Error: 127_000 - .saturating_add((91_822_000 as Weight).saturating_mul(r as Weight)) + (212_554_000 as Weight) + // Standard Error: 129_000 + .saturating_add((92_073_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -717,9 +717,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256_per_kb(n: u32, ) -> Weight { - (402_456_000 as Weight) - // Standard Error: 19_000 - .saturating_add((311_103_000 as Weight).saturating_mul(n as Weight)) + (298_638_000 as Weight) + // Standard Error: 23_000 + .saturating_add((307_231_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -728,9 +728,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256(r: u32, ) -> Weight { - (296_702_000 as Weight) - // Standard Error: 142_000 - .saturating_add((64_431_000 as Weight).saturating_mul(r as Weight)) + (216_274_000 as Weight) + // Standard Error: 100_000 + .saturating_add((64_205_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -739,9 +739,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256_per_kb(n: u32, ) -> Weight { - (375_322_000 as Weight) - // Standard Error: 14_000 - .saturating_add((124_338_000 as Weight).saturating_mul(n as Weight)) + (294_478_000 as Weight) + // Standard Error: 18_000 + .saturating_add((120_405_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -750,9 +750,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128(r: u32, ) -> Weight { - (294_158_000 as Weight) - // Standard Error: 148_000 - .saturating_add((64_474_000 as Weight).saturating_mul(r as Weight)) + (215_874_000 as Weight) + // Standard Error: 115_000 + .saturating_add((63_402_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -761,9 +761,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128_per_kb(n: u32, ) -> Weight { - (390_049_000 as Weight) - // Standard Error: 16_000 - .saturating_add((124_330_000 as Weight).saturating_mul(n as Weight)) + (288_361_000 as Weight) + // Standard Error: 15_000 + .saturating_add((120_795_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -772,9 +772,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_ecdsa_recover(r: u32, ) -> Weight { - (233_346_000 as Weight) - // Standard Error: 1_355_000 - .saturating_add((15_405_070_000 as Weight).saturating_mul(r as Weight)) + (142_940_000 as Weight) + // Standard Error: 1_317_000 + .saturating_add((15_385_437_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -785,265 +785,265 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts OwnerInfoOf (r:36 w:36) fn seal_set_code_hash(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 2_158_000 - .saturating_add((932_937_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 1_981_000 + .saturating_add((943_500_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads((99 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes((99 as Weight).saturating_mul(r as Weight))) } fn instr_i64const(r: u32, ) -> Weight { - (119_148_000 as Weight) - // Standard Error: 2_000 - .saturating_add((585_000 as Weight).saturating_mul(r as Weight)) + (74_672_000 as Weight) + // Standard Error: 1_000 + .saturating_add((595_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64load(r: u32, ) -> Weight { - (118_413_000 as Weight) - // Standard Error: 3_000 + (74_346_000 as Weight) + // Standard Error: 1_000 .saturating_add((1_324_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64store(r: u32, ) -> Weight { - (118_700_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_415_000 as Weight).saturating_mul(r as Weight)) + (74_149_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_438_000 as Weight).saturating_mul(r as Weight)) } fn instr_select(r: u32, ) -> Weight { - (118_736_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_777_000 as Weight).saturating_mul(r as Weight)) + (74_186_000 as Weight) + // Standard Error: 4_000 + .saturating_add((1_789_000 as Weight).saturating_mul(r as Weight)) } fn instr_if(r: u32, ) -> Weight { - (118_277_000 as Weight) - // Standard Error: 4_000 - .saturating_add((1_909_000 as Weight).saturating_mul(r as Weight)) + (74_040_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_898_000 as Weight).saturating_mul(r as Weight)) } fn instr_br(r: u32, ) -> Weight { - (118_360_000 as Weight) - // Standard Error: 0 - .saturating_add((895_000 as Weight).saturating_mul(r as Weight)) + (73_909_000 as Weight) + // Standard Error: 1_000 + .saturating_add((910_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_if(r: u32, ) -> Weight { - (118_142_000 as Weight) + (73_873_000 as Weight) // Standard Error: 3_000 - .saturating_add((1_439_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_446_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table(r: u32, ) -> Weight { - (118_239_000 as Weight) - // Standard Error: 5_000 - .saturating_add((1_553_000 as Weight).saturating_mul(r as Weight)) + (73_438_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_582_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table_per_entry(e: u32, ) -> Weight { - (120_801_000 as Weight) + (75_993_000 as Weight) // Standard Error: 0 - .saturating_add((4_000 as Weight).saturating_mul(e as Weight)) + .saturating_add((8_000 as Weight).saturating_mul(e as Weight)) } fn instr_call(r: u32, ) -> Weight { - (118_536_000 as Weight) - // Standard Error: 16_000 - .saturating_add((17_082_000 as Weight).saturating_mul(r as Weight)) + (73_218_000 as Weight) + // Standard Error: 17_000 + .saturating_add((17_167_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect(r: u32, ) -> Weight { - (130_467_000 as Weight) + (85_517_000 as Weight) // Standard Error: 30_000 - .saturating_add((28_199_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((28_885_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect_per_param(p: u32, ) -> Weight { - (164_624_000 as Weight) + (119_915_000 as Weight) // Standard Error: 3_000 - .saturating_add((901_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((918_000 as Weight).saturating_mul(p as Weight)) } fn instr_local_get(r: u32, ) -> Weight { - (119_422_000 as Weight) - // Standard Error: 2_000 - .saturating_add((617_000 as Weight).saturating_mul(r as Weight)) + (74_718_000 as Weight) + // Standard Error: 1_000 + .saturating_add((618_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_set(r: u32, ) -> Weight { - (119_747_000 as Weight) - // Standard Error: 2_000 - .saturating_add((668_000 as Weight).saturating_mul(r as Weight)) + (74_800_000 as Weight) + // Standard Error: 1_000 + .saturating_add((684_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_tee(r: u32, ) -> Weight { - (119_410_000 as Weight) - // Standard Error: 3_000 - .saturating_add((898_000 as Weight).saturating_mul(r as Weight)) + (74_590_000 as Weight) + // Standard Error: 2_000 + .saturating_add((911_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_get(r: u32, ) -> Weight { - (121_657_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_160_000 as Weight).saturating_mul(r as Weight)) + (76_776_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_159_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_set(r: u32, ) -> Weight { - (121_531_000 as Weight) - // Standard Error: 1_000 + (77_283_000 as Weight) + // Standard Error: 2_000 .saturating_add((1_367_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_current(r: u32, ) -> Weight { - (118_340_000 as Weight) - // Standard Error: 2_000 - .saturating_add((674_000 as Weight).saturating_mul(r as Weight)) + (74_555_000 as Weight) + // Standard Error: 1_000 + .saturating_add((655_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_grow(r: u32, ) -> Weight { - (118_114_000 as Weight) - // Standard Error: 194_000 - .saturating_add((229_474_000 as Weight).saturating_mul(r as Weight)) + (73_693_000 as Weight) + // Standard Error: 131_000 + .saturating_add((181_095_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64clz(r: u32, ) -> Weight { - (119_160_000 as Weight) - // Standard Error: 2_000 - .saturating_add((890_000 as Weight).saturating_mul(r as Weight)) + (74_457_000 as Weight) + // Standard Error: 1_000 + .saturating_add((903_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ctz(r: u32, ) -> Weight { - (119_199_000 as Weight) - // Standard Error: 3_000 - .saturating_add((893_000 as Weight).saturating_mul(r as Weight)) + (74_287_000 as Weight) + // Standard Error: 1_000 + .saturating_add((907_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64popcnt(r: u32, ) -> Weight { - (119_103_000 as Weight) - // Standard Error: 4_000 - .saturating_add((885_000 as Weight).saturating_mul(r as Weight)) + (74_603_000 as Weight) + // Standard Error: 3_000 + .saturating_add((892_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eqz(r: u32, ) -> Weight { - (119_033_000 as Weight) - // Standard Error: 3_000 - .saturating_add((917_000 as Weight).saturating_mul(r as Weight)) + (74_383_000 as Weight) + // Standard Error: 1_000 + .saturating_add((920_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendsi32(r: u32, ) -> Weight { - (118_950_000 as Weight) - // Standard Error: 4_000 - .saturating_add((879_000 as Weight).saturating_mul(r as Weight)) + (74_020_000 as Weight) + // Standard Error: 2_000 + .saturating_add((896_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendui32(r: u32, ) -> Weight { - (118_534_000 as Weight) - // Standard Error: 2_000 - .saturating_add((888_000 as Weight).saturating_mul(r as Weight)) + (74_108_000 as Weight) + // Standard Error: 4_000 + .saturating_add((889_000 as Weight).saturating_mul(r as Weight)) } fn instr_i32wrapi64(r: u32, ) -> Weight { - (119_108_000 as Weight) + (74_197_000 as Weight) // Standard Error: 2_000 - .saturating_add((881_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((901_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eq(r: u32, ) -> Weight { - (118_677_000 as Weight) - // Standard Error: 5_000 - .saturating_add((1_360_000 as Weight).saturating_mul(r as Weight)) + (73_941_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_377_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ne(r: u32, ) -> Weight { - (118_769_000 as Weight) - // Standard Error: 3_000 - .saturating_add((1_355_000 as Weight).saturating_mul(r as Weight)) + (73_891_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_383_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64lts(r: u32, ) -> Weight { - (118_690_000 as Weight) + (74_253_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_356_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_369_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ltu(r: u32, ) -> Weight { - (118_899_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_350_000 as Weight).saturating_mul(r as Weight)) + (74_125_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_371_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gts(r: u32, ) -> Weight { - (118_519_000 as Weight) - // Standard Error: 6_000 - .saturating_add((1_376_000 as Weight).saturating_mul(r as Weight)) + (74_144_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_369_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gtu(r: u32, ) -> Weight { - (119_315_000 as Weight) - // Standard Error: 3_000 - .saturating_add((1_347_000 as Weight).saturating_mul(r as Weight)) + (74_170_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_375_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64les(r: u32, ) -> Weight { - (118_171_000 as Weight) - // Standard Error: 5_000 - .saturating_add((1_377_000 as Weight).saturating_mul(r as Weight)) + (74_164_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_370_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64leu(r: u32, ) -> Weight { - (118_581_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_367_000 as Weight).saturating_mul(r as Weight)) + (74_166_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_376_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ges(r: u32, ) -> Weight { - (118_673_000 as Weight) + (73_920_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_355_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_381_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64geu(r: u32, ) -> Weight { - (118_618_000 as Weight) + (74_691_000 as Weight) // Standard Error: 2_000 - .saturating_add((1_357_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_356_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64add(r: u32, ) -> Weight { - (118_569_000 as Weight) + (74_198_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_335_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_347_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64sub(r: u32, ) -> Weight { - (118_261_000 as Weight) - // Standard Error: 3_000 - .saturating_add((1_363_000 as Weight).saturating_mul(r as Weight)) + (74_064_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_358_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64mul(r: u32, ) -> Weight { - (118_542_000 as Weight) - // Standard Error: 2_000 + (75_744_000 as Weight) + // Standard Error: 8_000 .saturating_add((1_338_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divs(r: u32, ) -> Weight { - (118_648_000 as Weight) - // Standard Error: 4_000 - .saturating_add((1_993_000 as Weight).saturating_mul(r as Weight)) + (74_300_000 as Weight) + // Standard Error: 1_000 + .saturating_add((2_003_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divu(r: u32, ) -> Weight { - (118_378_000 as Weight) - // Standard Error: 0 - .saturating_add((2_057_000 as Weight).saturating_mul(r as Weight)) + (74_001_000 as Weight) + // Standard Error: 1_000 + .saturating_add((2_051_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rems(r: u32, ) -> Weight { - (118_813_000 as Weight) - // Standard Error: 3_000 - .saturating_add((1_995_000 as Weight).saturating_mul(r as Weight)) + (74_132_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_994_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64remu(r: u32, ) -> Weight { - (118_697_000 as Weight) - // Standard Error: 2_000 - .saturating_add((2_025_000 as Weight).saturating_mul(r as Weight)) + (74_241_000 as Weight) + // Standard Error: 3_000 + .saturating_add((2_070_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64and(r: u32, ) -> Weight { - (118_838_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_332_000 as Weight).saturating_mul(r as Weight)) + (74_069_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_351_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64or(r: u32, ) -> Weight { - (118_641_000 as Weight) - // Standard Error: 4_000 - .saturating_add((1_347_000 as Weight).saturating_mul(r as Weight)) + (73_978_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_355_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64xor(r: u32, ) -> Weight { - (118_551_000 as Weight) + (74_053_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_338_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_351_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shl(r: u32, ) -> Weight { - (118_603_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_352_000 as Weight).saturating_mul(r as Weight)) + (73_891_000 as Weight) + // Standard Error: 0 + .saturating_add((1_371_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shrs(r: u32, ) -> Weight { - (118_885_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_345_000 as Weight).saturating_mul(r as Weight)) + (74_062_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_366_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shru(r: u32, ) -> Weight { - (118_602_000 as Weight) - // Standard Error: 3_000 - .saturating_add((1_354_000 as Weight).saturating_mul(r as Weight)) + (74_347_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_360_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotl(r: u32, ) -> Weight { - (118_733_000 as Weight) - // Standard Error: 3_000 - .saturating_add((1_349_000 as Weight).saturating_mul(r as Weight)) + (74_116_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_366_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotr(r: u32, ) -> Weight { - (118_920_000 as Weight) + (73_837_000 as Weight) // Standard Error: 3_000 - .saturating_add((1_348_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_377_000 as Weight).saturating_mul(r as Weight)) } } @@ -1051,32 +1051,32 @@ impl WeightInfo for SubstrateWeight { impl WeightInfo for () { // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize() -> Weight { - (1_560_000 as Weight) + (1_588_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn on_initialize_per_trie_key(k: u32, ) -> Weight { - (7_843_000 as Weight) + (6_994_000 as Weight) // Standard Error: 0 - .saturating_add((749_000 as Weight).saturating_mul(k as Weight)) + .saturating_add((743_000 as Weight).saturating_mul(k as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) } // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize_per_queue_item(q: u32, ) -> Weight { - (3_228_000 as Weight) - // Standard Error: 5_000 - .saturating_add((2_257_000 as Weight).saturating_mul(q as Weight)) + (2_831_000 as Weight) + // Standard Error: 3_000 + .saturating_add((2_232_000 as Weight).saturating_mul(q as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Contracts PristineCode (r:1 w:0) // Storage: Contracts CodeStorage (r:0 w:1) fn reinstrument(c: u32, ) -> Weight { - (20_531_000 as Weight) - // Standard Error: 34_000 - .saturating_add((66_014_000 as Weight).saturating_mul(c as Weight)) + (17_839_000 as Weight) + // Standard Error: 0 + .saturating_add((64_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1084,10 +1084,10 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) - fn call_with_code_kb(c: u32, ) -> Weight { - (295_703_000 as Weight) - // Standard Error: 53_000 - .saturating_add((57_661_000 as Weight).saturating_mul(c as Weight)) + fn call_with_code_per_byte(c: u32, ) -> Weight { + (222_400_000 as Weight) + // Standard Error: 0 + .saturating_add((56_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -1099,11 +1099,11 @@ impl WeightInfo for () { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn instantiate_with_code(c: u32, s: u32, ) -> Weight { - (332_572_000 as Weight) - // Standard Error: 125_000 - .saturating_add((149_095_000 as Weight).saturating_mul(c as Weight)) - // Standard Error: 7_000 - .saturating_add((1_779_000 as Weight).saturating_mul(s as Weight)) + (283_144_000 as Weight) + // Standard Error: 0 + .saturating_add((140_000 as Weight).saturating_mul(c as Weight)) + // Standard Error: 0 + .saturating_add((2_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } @@ -1114,9 +1114,9 @@ impl WeightInfo for () { // Storage: System Account (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn instantiate(s: u32, ) -> Weight { - (222_992_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_759_000 as Weight).saturating_mul(s as Weight)) + (171_794_000 as Weight) + // Standard Error: 0 + .saturating_add((2_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } @@ -1125,7 +1125,7 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call() -> Weight { - (189_003_000 as Weight) + (140_234_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -1133,9 +1133,9 @@ impl WeightInfo for () { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn upload_code(c: u32, ) -> Weight { - (52_521_000 as Weight) - // Standard Error: 36_000 - .saturating_add((66_486_000 as Weight).saturating_mul(c as Weight)) + (49_467_000 as Weight) + // Standard Error: 0 + .saturating_add((66_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -1143,7 +1143,7 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:0 w:1) // Storage: Contracts PristineCode (r:0 w:1) fn remove_code() -> Weight { - (24_705_000 as Weight) + (24_915_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -1152,9 +1152,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_caller(r: u32, ) -> Weight { - (300_165_000 as Weight) - // Standard Error: 125_000 - .saturating_add((49_828_000 as Weight).saturating_mul(r as Weight)) + (218_957_000 as Weight) + // Standard Error: 114_000 + .saturating_add((49_881_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1163,9 +1163,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_is_contract(r: u32, ) -> Weight { - (179_488_000 as Weight) - // Standard Error: 718_000 - .saturating_add((375_855_000 as Weight).saturating_mul(r as Weight)) + (76_490_000 as Weight) + // Standard Error: 856_000 + .saturating_add((375_305_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1175,9 +1175,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_caller_is_origin(r: u32, ) -> Weight { - (295_198_000 as Weight) - // Standard Error: 79_000 - .saturating_add((21_948_000 as Weight).saturating_mul(r as Weight)) + (213_485_000 as Weight) + // Standard Error: 76_000 + .saturating_add((22_020_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1186,9 +1186,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_address(r: u32, ) -> Weight { - (300_366_000 as Weight) - // Standard Error: 111_000 - .saturating_add((49_435_000 as Weight).saturating_mul(r as Weight)) + (218_468_000 as Weight) + // Standard Error: 108_000 + .saturating_add((49_457_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1197,9 +1197,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas_left(r: u32, ) -> Weight { - (299_800_000 as Weight) - // Standard Error: 87_000 - .saturating_add((49_002_000 as Weight).saturating_mul(r as Weight)) + (218_950_000 as Weight) + // Standard Error: 99_000 + .saturating_add((48_859_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1208,9 +1208,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_balance(r: u32, ) -> Weight { - (303_057_000 as Weight) - // Standard Error: 175_000 - .saturating_add((139_293_000 as Weight).saturating_mul(r as Weight)) + (226_714_000 as Weight) + // Standard Error: 111_000 + .saturating_add((141_924_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1219,9 +1219,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_value_transferred(r: u32, ) -> Weight { - (299_754_000 as Weight) - // Standard Error: 93_000 - .saturating_add((48_945_000 as Weight).saturating_mul(r as Weight)) + (216_673_000 as Weight) + // Standard Error: 90_000 + .saturating_add((49_367_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1230,9 +1230,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_minimum_balance(r: u32, ) -> Weight { - (302_229_000 as Weight) - // Standard Error: 128_000 - .saturating_add((49_007_000 as Weight).saturating_mul(r as Weight)) + (215_859_000 as Weight) + // Standard Error: 104_000 + .saturating_add((49_334_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1241,9 +1241,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_block_number(r: u32, ) -> Weight { - (300_772_000 as Weight) - // Standard Error: 114_000 - .saturating_add((48_794_000 as Weight).saturating_mul(r as Weight)) + (216_419_000 as Weight) + // Standard Error: 109_000 + .saturating_add((49_417_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1252,9 +1252,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_now(r: u32, ) -> Weight { - (301_936_000 as Weight) - // Standard Error: 119_000 - .saturating_add((48_839_000 as Weight).saturating_mul(r as Weight)) + (218_799_000 as Weight) + // Standard Error: 108_000 + .saturating_add((48_631_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1264,9 +1264,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0) fn seal_weight_to_fee(r: u32, ) -> Weight { - (304_935_000 as Weight) - // Standard Error: 146_000 - .saturating_add((121_871_000 as Weight).saturating_mul(r as Weight)) + (215_968_000 as Weight) + // Standard Error: 147_000 + .saturating_add((122_978_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1275,9 +1275,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas(r: u32, ) -> Weight { - (178_176_000 as Weight) - // Standard Error: 52_000 - .saturating_add((24_960_000 as Weight).saturating_mul(r as Weight)) + (127_183_000 as Weight) + // Standard Error: 35_000 + .saturating_add((24_523_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1286,9 +1286,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input(r: u32, ) -> Weight { - (297_394_000 as Weight) - // Standard Error: 140_000 - .saturating_add((49_199_000 as Weight).saturating_mul(r as Weight)) + (217_535_000 as Weight) + // Standard Error: 91_000 + .saturating_add((48_400_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1297,9 +1297,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input_per_kb(n: u32, ) -> Weight { - (374_409_000 as Weight) - // Standard Error: 3_000 - .saturating_add((11_924_000 as Weight).saturating_mul(n as Weight)) + (297_539_000 as Weight) + // Standard Error: 5_000 + .saturating_add((11_870_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1308,9 +1308,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return(r: u32, ) -> Weight { - (292_278_000 as Weight) - // Standard Error: 114_000 - .saturating_add((1_474_000 as Weight).saturating_mul(r as Weight)) + (211_807_000 as Weight) + // Standard Error: 160_000 + .saturating_add((1_717_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1319,9 +1319,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return_per_kb(n: u32, ) -> Weight { - (294_714_000 as Weight) + (213_139_000 as Weight) // Standard Error: 0 - .saturating_add((230_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((197_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1332,9 +1332,9 @@ impl WeightInfo for () { // Storage: Contracts DeletionQueue (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_terminate(r: u32, ) -> Weight { - (297_589_000 as Weight) - // Standard Error: 2_835_000 - .saturating_add((53_498_000 as Weight).saturating_mul(r as Weight)) + (215_292_000 as Weight) + // Standard Error: 390_000 + .saturating_add((52_831_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((4 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1346,9 +1346,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) fn seal_random(r: u32, ) -> Weight { - (296_371_000 as Weight) - // Standard Error: 220_000 - .saturating_add((160_881_000 as Weight).saturating_mul(r as Weight)) + (215_802_000 as Weight) + // Standard Error: 132_000 + .saturating_add((159_065_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1357,9 +1357,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_deposit_event(r: u32, ) -> Weight { - (308_401_000 as Weight) - // Standard Error: 202_000 - .saturating_add((277_771_000 as Weight).saturating_mul(r as Weight)) + (225_069_000 as Weight) + // Standard Error: 201_000 + .saturating_add((292_145_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1369,11 +1369,11 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: System EventTopics (r:100 w:100) fn seal_deposit_event_per_topic_and_kb(t: u32, n: u32, ) -> Weight { - (625_100_000 as Weight) - // Standard Error: 2_053_000 - .saturating_add((284_765_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 404_000 - .saturating_add((85_893_000 as Weight).saturating_mul(n as Weight)) + (519_617_000 as Weight) + // Standard Error: 1_751_000 + .saturating_add((290_832_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 345_000 + .saturating_add((82_584_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(t as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1384,17 +1384,17 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_debug_message(r: u32, ) -> Weight { - (182_141_000 as Weight) - // Standard Error: 134_000 - .saturating_add((41_928_000 as Weight).saturating_mul(r as Weight)) + (132_245_000 as Weight) + // Standard Error: 75_000 + .saturating_add((41_274_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage(r: u32, ) -> Weight { - (139_030_000 as Weight) - // Standard Error: 1_038_000 - .saturating_add((405_168_000 as Weight).saturating_mul(r as Weight)) + (48_288_000 as Weight) + // Standard Error: 1_024_000 + .saturating_add((408_264_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1402,25 +1402,25 @@ impl WeightInfo for () { } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage_per_new_kb(n: u32, ) -> Weight { - (689_591_000 as Weight) - // Standard Error: 275_000 - .saturating_add((31_438_000 as Weight).saturating_mul(n as Weight)) + (607_246_000 as Weight) + // Standard Error: 252_000 + .saturating_add((28_722_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage_per_old_kb(n: u32, ) -> Weight { - (709_965_000 as Weight) - // Standard Error: 340_000 - .saturating_add((11_182_000 as Weight).saturating_mul(n as Weight)) + (623_983_000 as Weight) + // Standard Error: 305_000 + .saturating_add((11_374_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage(r: u32, ) -> Weight { - (169_937_000 as Weight) - // Standard Error: 883_000 - .saturating_add((389_090_000 as Weight).saturating_mul(r as Weight)) + (91_727_000 as Weight) + // Standard Error: 837_000 + .saturating_add((383_577_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -1428,51 +1428,51 @@ impl WeightInfo for () { } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage_per_kb(n: u32, ) -> Weight { - (695_589_000 as Weight) - // Standard Error: 268_000 - .saturating_add((10_530_000 as Weight).saturating_mul(n as Weight)) + (604_749_000 as Weight) + // Standard Error: 251_000 + .saturating_add((11_086_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage(r: u32, ) -> Weight { - (195_080_000 as Weight) - // Standard Error: 607_000 - .saturating_add((328_903_000 as Weight).saturating_mul(r as Weight)) + (107_805_000 as Weight) + // Standard Error: 722_000 + .saturating_add((326_494_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage_per_kb(n: u32, ) -> Weight { - (647_422_000 as Weight) - // Standard Error: 361_000 - .saturating_add((68_849_000 as Weight).saturating_mul(n as Weight)) + (564_604_000 as Weight) + // Standard Error: 360_000 + .saturating_add((65_184_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(104 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_contains_storage(r: u32, ) -> Weight { - (198_907_000 as Weight) - // Standard Error: 658_000 - .saturating_add((295_368_000 as Weight).saturating_mul(r as Weight)) + (122_105_000 as Weight) + // Standard Error: 560_000 + .saturating_add((291_458_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_contains_storage_per_kb(n: u32, ) -> Weight { - (599_284_000 as Weight) - // Standard Error: 243_000 - .saturating_add((9_923_000 as Weight).saturating_mul(n as Weight)) + (512_580_000 as Weight) + // Standard Error: 245_000 + .saturating_add((10_171_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(104 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage(r: u32, ) -> Weight { - (170_700_000 as Weight) - // Standard Error: 887_000 - .saturating_add((422_448_000 as Weight).saturating_mul(r as Weight)) + (81_220_000 as Weight) + // Standard Error: 933_000 + .saturating_add((418_532_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -1480,9 +1480,9 @@ impl WeightInfo for () { } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage_per_kb(n: u32, ) -> Weight { - (743_584_000 as Weight) - // Standard Error: 403_000 - .saturating_add((69_763_000 as Weight).saturating_mul(n as Weight)) + (652_330_000 as Weight) + // Standard Error: 357_000 + .saturating_add((65_711_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().writes(103 as Weight)) } @@ -1491,9 +1491,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_transfer(r: u32, ) -> Weight { - (208_815_000 as Weight) - // Standard Error: 1_078_000 - .saturating_add((1_719_660_000 as Weight).saturating_mul(r as Weight)) + (126_544_000 as Weight) + // Standard Error: 1_198_000 + .saturating_add((1_796_593_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) @@ -1505,8 +1505,8 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) fn seal_call(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 3_471_000 - .saturating_add((27_917_429_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 3_033_000 + .saturating_add((19_788_005_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1518,8 +1518,8 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) fn seal_delegate_call(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 13_012_000 - .saturating_add((28_044_371_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 6_663_000 + .saturating_add((19_835_985_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads((99 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1528,11 +1528,11 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:2 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_call_per_transfer_clone_kb(t: u32, c: u32, ) -> Weight { - (15_964_304_000 as Weight) - // Standard Error: 19_327_000 - .saturating_add((1_629_626_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 8_000 - .saturating_add((11_992_000 as Weight).saturating_mul(c as Weight)) + (10_957_494_000 as Weight) + // Standard Error: 13_908_000 + .saturating_add((1_622_630_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 6_000 + .saturating_add((11_960_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().reads((101 as Weight).saturating_mul(t as Weight))) .saturating_add(RocksDbWeight::get().writes(101 as Weight)) @@ -1546,8 +1546,8 @@ impl WeightInfo for () { // Storage: Contracts OwnerInfoOf (r:100 w:100) fn seal_instantiate(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 50_849_000 - .saturating_add((35_608_311_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 48_191_000 + .saturating_add((27_587_375_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().reads((400 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -1560,11 +1560,11 @@ impl WeightInfo for () { // Storage: Contracts AccountCounter (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_instantiate_per_transfer_salt_kb(t: u32, s: u32, ) -> Weight { - (19_455_191_000 as Weight) - // Standard Error: 57_478_000 - .saturating_add((786_148_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 27_000 - .saturating_add((160_385_000 as Weight).saturating_mul(s as Weight)) + (14_504_226_000 as Weight) + // Standard Error: 66_350_000 + .saturating_add((912_874_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 31_000 + .saturating_add((157_415_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(207 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(t as Weight))) .saturating_add(RocksDbWeight::get().writes(205 as Weight)) @@ -1575,9 +1575,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256(r: u32, ) -> Weight { - (294_686_000 as Weight) - // Standard Error: 123_000 - .saturating_add((81_172_000 as Weight).saturating_mul(r as Weight)) + (216_771_000 as Weight) + // Standard Error: 127_000 + .saturating_add((79_994_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1586,9 +1586,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256_per_kb(n: u32, ) -> Weight { - (276_895_000 as Weight) - // Standard Error: 35_000 - .saturating_add((469_007_000 as Weight).saturating_mul(n as Weight)) + (376_960_000 as Weight) + // Standard Error: 24_000 + .saturating_add((465_507_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1597,9 +1597,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256(r: u32, ) -> Weight { - (295_476_000 as Weight) - // Standard Error: 127_000 - .saturating_add((91_822_000 as Weight).saturating_mul(r as Weight)) + (212_554_000 as Weight) + // Standard Error: 129_000 + .saturating_add((92_073_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1608,9 +1608,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256_per_kb(n: u32, ) -> Weight { - (402_456_000 as Weight) - // Standard Error: 19_000 - .saturating_add((311_103_000 as Weight).saturating_mul(n as Weight)) + (298_638_000 as Weight) + // Standard Error: 23_000 + .saturating_add((307_231_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1619,9 +1619,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256(r: u32, ) -> Weight { - (296_702_000 as Weight) - // Standard Error: 142_000 - .saturating_add((64_431_000 as Weight).saturating_mul(r as Weight)) + (216_274_000 as Weight) + // Standard Error: 100_000 + .saturating_add((64_205_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1630,9 +1630,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256_per_kb(n: u32, ) -> Weight { - (375_322_000 as Weight) - // Standard Error: 14_000 - .saturating_add((124_338_000 as Weight).saturating_mul(n as Weight)) + (294_478_000 as Weight) + // Standard Error: 18_000 + .saturating_add((120_405_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1641,9 +1641,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128(r: u32, ) -> Weight { - (294_158_000 as Weight) - // Standard Error: 148_000 - .saturating_add((64_474_000 as Weight).saturating_mul(r as Weight)) + (215_874_000 as Weight) + // Standard Error: 115_000 + .saturating_add((63_402_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1652,9 +1652,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128_per_kb(n: u32, ) -> Weight { - (390_049_000 as Weight) - // Standard Error: 16_000 - .saturating_add((124_330_000 as Weight).saturating_mul(n as Weight)) + (288_361_000 as Weight) + // Standard Error: 15_000 + .saturating_add((120_795_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1663,9 +1663,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_ecdsa_recover(r: u32, ) -> Weight { - (233_346_000 as Weight) - // Standard Error: 1_355_000 - .saturating_add((15_405_070_000 as Weight).saturating_mul(r as Weight)) + (142_940_000 as Weight) + // Standard Error: 1_317_000 + .saturating_add((15_385_437_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1676,264 +1676,264 @@ impl WeightInfo for () { // Storage: Contracts OwnerInfoOf (r:36 w:36) fn seal_set_code_hash(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 2_158_000 - .saturating_add((932_937_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 1_981_000 + .saturating_add((943_500_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads((99 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes((99 as Weight).saturating_mul(r as Weight))) } fn instr_i64const(r: u32, ) -> Weight { - (119_148_000 as Weight) - // Standard Error: 2_000 - .saturating_add((585_000 as Weight).saturating_mul(r as Weight)) + (74_672_000 as Weight) + // Standard Error: 1_000 + .saturating_add((595_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64load(r: u32, ) -> Weight { - (118_413_000 as Weight) - // Standard Error: 3_000 + (74_346_000 as Weight) + // Standard Error: 1_000 .saturating_add((1_324_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64store(r: u32, ) -> Weight { - (118_700_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_415_000 as Weight).saturating_mul(r as Weight)) + (74_149_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_438_000 as Weight).saturating_mul(r as Weight)) } fn instr_select(r: u32, ) -> Weight { - (118_736_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_777_000 as Weight).saturating_mul(r as Weight)) + (74_186_000 as Weight) + // Standard Error: 4_000 + .saturating_add((1_789_000 as Weight).saturating_mul(r as Weight)) } fn instr_if(r: u32, ) -> Weight { - (118_277_000 as Weight) - // Standard Error: 4_000 - .saturating_add((1_909_000 as Weight).saturating_mul(r as Weight)) + (74_040_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_898_000 as Weight).saturating_mul(r as Weight)) } fn instr_br(r: u32, ) -> Weight { - (118_360_000 as Weight) - // Standard Error: 0 - .saturating_add((895_000 as Weight).saturating_mul(r as Weight)) + (73_909_000 as Weight) + // Standard Error: 1_000 + .saturating_add((910_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_if(r: u32, ) -> Weight { - (118_142_000 as Weight) + (73_873_000 as Weight) // Standard Error: 3_000 - .saturating_add((1_439_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_446_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table(r: u32, ) -> Weight { - (118_239_000 as Weight) - // Standard Error: 5_000 - .saturating_add((1_553_000 as Weight).saturating_mul(r as Weight)) + (73_438_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_582_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table_per_entry(e: u32, ) -> Weight { - (120_801_000 as Weight) + (75_993_000 as Weight) // Standard Error: 0 - .saturating_add((4_000 as Weight).saturating_mul(e as Weight)) + .saturating_add((8_000 as Weight).saturating_mul(e as Weight)) } fn instr_call(r: u32, ) -> Weight { - (118_536_000 as Weight) - // Standard Error: 16_000 - .saturating_add((17_082_000 as Weight).saturating_mul(r as Weight)) + (73_218_000 as Weight) + // Standard Error: 17_000 + .saturating_add((17_167_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect(r: u32, ) -> Weight { - (130_467_000 as Weight) + (85_517_000 as Weight) // Standard Error: 30_000 - .saturating_add((28_199_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((28_885_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect_per_param(p: u32, ) -> Weight { - (164_624_000 as Weight) + (119_915_000 as Weight) // Standard Error: 3_000 - .saturating_add((901_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((918_000 as Weight).saturating_mul(p as Weight)) } fn instr_local_get(r: u32, ) -> Weight { - (119_422_000 as Weight) - // Standard Error: 2_000 - .saturating_add((617_000 as Weight).saturating_mul(r as Weight)) + (74_718_000 as Weight) + // Standard Error: 1_000 + .saturating_add((618_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_set(r: u32, ) -> Weight { - (119_747_000 as Weight) - // Standard Error: 2_000 - .saturating_add((668_000 as Weight).saturating_mul(r as Weight)) + (74_800_000 as Weight) + // Standard Error: 1_000 + .saturating_add((684_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_tee(r: u32, ) -> Weight { - (119_410_000 as Weight) - // Standard Error: 3_000 - .saturating_add((898_000 as Weight).saturating_mul(r as Weight)) + (74_590_000 as Weight) + // Standard Error: 2_000 + .saturating_add((911_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_get(r: u32, ) -> Weight { - (121_657_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_160_000 as Weight).saturating_mul(r as Weight)) + (76_776_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_159_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_set(r: u32, ) -> Weight { - (121_531_000 as Weight) - // Standard Error: 1_000 + (77_283_000 as Weight) + // Standard Error: 2_000 .saturating_add((1_367_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_current(r: u32, ) -> Weight { - (118_340_000 as Weight) - // Standard Error: 2_000 - .saturating_add((674_000 as Weight).saturating_mul(r as Weight)) + (74_555_000 as Weight) + // Standard Error: 1_000 + .saturating_add((655_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_grow(r: u32, ) -> Weight { - (118_114_000 as Weight) - // Standard Error: 194_000 - .saturating_add((229_474_000 as Weight).saturating_mul(r as Weight)) + (73_693_000 as Weight) + // Standard Error: 131_000 + .saturating_add((181_095_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64clz(r: u32, ) -> Weight { - (119_160_000 as Weight) - // Standard Error: 2_000 - .saturating_add((890_000 as Weight).saturating_mul(r as Weight)) + (74_457_000 as Weight) + // Standard Error: 1_000 + .saturating_add((903_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ctz(r: u32, ) -> Weight { - (119_199_000 as Weight) - // Standard Error: 3_000 - .saturating_add((893_000 as Weight).saturating_mul(r as Weight)) + (74_287_000 as Weight) + // Standard Error: 1_000 + .saturating_add((907_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64popcnt(r: u32, ) -> Weight { - (119_103_000 as Weight) - // Standard Error: 4_000 - .saturating_add((885_000 as Weight).saturating_mul(r as Weight)) + (74_603_000 as Weight) + // Standard Error: 3_000 + .saturating_add((892_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eqz(r: u32, ) -> Weight { - (119_033_000 as Weight) - // Standard Error: 3_000 - .saturating_add((917_000 as Weight).saturating_mul(r as Weight)) + (74_383_000 as Weight) + // Standard Error: 1_000 + .saturating_add((920_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendsi32(r: u32, ) -> Weight { - (118_950_000 as Weight) - // Standard Error: 4_000 - .saturating_add((879_000 as Weight).saturating_mul(r as Weight)) + (74_020_000 as Weight) + // Standard Error: 2_000 + .saturating_add((896_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendui32(r: u32, ) -> Weight { - (118_534_000 as Weight) - // Standard Error: 2_000 - .saturating_add((888_000 as Weight).saturating_mul(r as Weight)) + (74_108_000 as Weight) + // Standard Error: 4_000 + .saturating_add((889_000 as Weight).saturating_mul(r as Weight)) } fn instr_i32wrapi64(r: u32, ) -> Weight { - (119_108_000 as Weight) + (74_197_000 as Weight) // Standard Error: 2_000 - .saturating_add((881_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((901_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eq(r: u32, ) -> Weight { - (118_677_000 as Weight) - // Standard Error: 5_000 - .saturating_add((1_360_000 as Weight).saturating_mul(r as Weight)) + (73_941_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_377_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ne(r: u32, ) -> Weight { - (118_769_000 as Weight) - // Standard Error: 3_000 - .saturating_add((1_355_000 as Weight).saturating_mul(r as Weight)) + (73_891_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_383_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64lts(r: u32, ) -> Weight { - (118_690_000 as Weight) + (74_253_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_356_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_369_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ltu(r: u32, ) -> Weight { - (118_899_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_350_000 as Weight).saturating_mul(r as Weight)) + (74_125_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_371_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gts(r: u32, ) -> Weight { - (118_519_000 as Weight) - // Standard Error: 6_000 - .saturating_add((1_376_000 as Weight).saturating_mul(r as Weight)) + (74_144_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_369_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gtu(r: u32, ) -> Weight { - (119_315_000 as Weight) - // Standard Error: 3_000 - .saturating_add((1_347_000 as Weight).saturating_mul(r as Weight)) + (74_170_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_375_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64les(r: u32, ) -> Weight { - (118_171_000 as Weight) - // Standard Error: 5_000 - .saturating_add((1_377_000 as Weight).saturating_mul(r as Weight)) + (74_164_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_370_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64leu(r: u32, ) -> Weight { - (118_581_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_367_000 as Weight).saturating_mul(r as Weight)) + (74_166_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_376_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ges(r: u32, ) -> Weight { - (118_673_000 as Weight) + (73_920_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_355_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_381_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64geu(r: u32, ) -> Weight { - (118_618_000 as Weight) + (74_691_000 as Weight) // Standard Error: 2_000 - .saturating_add((1_357_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_356_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64add(r: u32, ) -> Weight { - (118_569_000 as Weight) + (74_198_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_335_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_347_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64sub(r: u32, ) -> Weight { - (118_261_000 as Weight) - // Standard Error: 3_000 - .saturating_add((1_363_000 as Weight).saturating_mul(r as Weight)) + (74_064_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_358_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64mul(r: u32, ) -> Weight { - (118_542_000 as Weight) - // Standard Error: 2_000 + (75_744_000 as Weight) + // Standard Error: 8_000 .saturating_add((1_338_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divs(r: u32, ) -> Weight { - (118_648_000 as Weight) - // Standard Error: 4_000 - .saturating_add((1_993_000 as Weight).saturating_mul(r as Weight)) + (74_300_000 as Weight) + // Standard Error: 1_000 + .saturating_add((2_003_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divu(r: u32, ) -> Weight { - (118_378_000 as Weight) - // Standard Error: 0 - .saturating_add((2_057_000 as Weight).saturating_mul(r as Weight)) + (74_001_000 as Weight) + // Standard Error: 1_000 + .saturating_add((2_051_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rems(r: u32, ) -> Weight { - (118_813_000 as Weight) - // Standard Error: 3_000 - .saturating_add((1_995_000 as Weight).saturating_mul(r as Weight)) + (74_132_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_994_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64remu(r: u32, ) -> Weight { - (118_697_000 as Weight) - // Standard Error: 2_000 - .saturating_add((2_025_000 as Weight).saturating_mul(r as Weight)) + (74_241_000 as Weight) + // Standard Error: 3_000 + .saturating_add((2_070_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64and(r: u32, ) -> Weight { - (118_838_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_332_000 as Weight).saturating_mul(r as Weight)) + (74_069_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_351_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64or(r: u32, ) -> Weight { - (118_641_000 as Weight) - // Standard Error: 4_000 - .saturating_add((1_347_000 as Weight).saturating_mul(r as Weight)) + (73_978_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_355_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64xor(r: u32, ) -> Weight { - (118_551_000 as Weight) + (74_053_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_338_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_351_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shl(r: u32, ) -> Weight { - (118_603_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_352_000 as Weight).saturating_mul(r as Weight)) + (73_891_000 as Weight) + // Standard Error: 0 + .saturating_add((1_371_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shrs(r: u32, ) -> Weight { - (118_885_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_345_000 as Weight).saturating_mul(r as Weight)) + (74_062_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_366_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shru(r: u32, ) -> Weight { - (118_602_000 as Weight) - // Standard Error: 3_000 - .saturating_add((1_354_000 as Weight).saturating_mul(r as Weight)) + (74_347_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_360_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotl(r: u32, ) -> Weight { - (118_733_000 as Weight) - // Standard Error: 3_000 - .saturating_add((1_349_000 as Weight).saturating_mul(r as Weight)) + (74_116_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_366_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotr(r: u32, ) -> Weight { - (118_920_000 as Weight) + (73_837_000 as Weight) // Standard Error: 3_000 - .saturating_add((1_348_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_377_000 as Weight).saturating_mul(r as Weight)) } } From 6ab64863c6e653da5cc468257650a970dbc8e9a1 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Wed, 16 Feb 2022 08:57:54 -0700 Subject: [PATCH 505/695] Tidy Democracy (#10867) * add test * Assorted refactorings * complete test * saturating math * final check * use `default` Co-authored-by: Gav Wood --- frame/democracy/src/lib.rs | 42 ++++++++++++++++++------- frame/democracy/src/tests/delegation.rs | 41 +++++++++++++++++++++++- frame/democracy/src/vote.rs | 9 +++++- 3 files changed, 79 insertions(+), 13 deletions(-) diff --git a/frame/democracy/src/lib.rs b/frame/democracy/src/lib.rs index b578df590930..8588f1876d7e 100644 --- a/frame/democracy/src/lib.rs +++ b/frame/democracy/src/lib.rs @@ -842,7 +842,12 @@ pub mod pallet { >::kill(); let now = >::block_number(); - Self::inject_referendum(now + voting_period, proposal_hash, threshold, delay); + Self::inject_referendum( + now.saturating_add(voting_period), + proposal_hash, + threshold, + delay, + ); Ok(()) } @@ -871,7 +876,8 @@ pub mod pallet { existing_vetoers.binary_search(&who).err().ok_or(Error::::AlreadyVetoed)?; existing_vetoers.insert(insert_position, who.clone()); - let until = >::block_number() + T::CooloffPeriod::get(); + let until = + >::block_number().saturating_add(T::CooloffPeriod::get()); >::insert(&proposal_hash, (until, existing_vetoers)); Self::deposit_event(Event::::Vetoed { who, proposal_hash, until }); @@ -1089,7 +1095,10 @@ pub mod pallet { let now = >::block_number(); let (voting, enactment) = (T::VotingPeriod::get(), T::EnactmentPeriod::get()); let additional = if who == provider { Zero::zero() } else { enactment }; - ensure!(now >= since + voting + additional, Error::::TooEarly); + ensure!( + now >= since.saturating_add(voting).saturating_add(additional), + Error::::TooEarly + ); ensure!(expiry.map_or(true, |e| now > e), Error::::Imminent); let res = @@ -1282,7 +1291,7 @@ impl Pallet { /// Get the amount locked in support of `proposal`; `None` if proposal isn't a valid proposal /// index. pub fn backing_for(proposal: PropIndex) -> Option> { - Self::deposit_of(proposal).map(|(l, d)| d * (l.len() as u32).into()) + Self::deposit_of(proposal).map(|(l, d)| d.saturating_mul((l.len() as u32).into())) } /// Get all referenda ready for tally at block `n`. @@ -1318,7 +1327,7 @@ impl Pallet { delay: T::BlockNumber, ) -> ReferendumIndex { >::inject_referendum( - >::block_number() + T::VotingPeriod::get(), + >::block_number().saturating_add(T::VotingPeriod::get()), proposal_hash, threshold, delay, @@ -1424,7 +1433,9 @@ impl Pallet { }, Some(ReferendumInfo::Finished { end, approved }) => { if let Some((lock_periods, balance)) = votes[i].1.locked_if(approved) { - let unlock_at = end + T::VoteLockingPeriod::get() * lock_periods.into(); + let unlock_at = end.saturating_add( + T::VoteLockingPeriod::get().saturating_mul(lock_periods.into()), + ); let now = frame_system::Pallet::::block_number(); if now < unlock_at { ensure!( @@ -1513,9 +1524,16 @@ impl Pallet { }; sp_std::mem::swap(&mut old, voting); match old { - Voting::Delegating { balance, target, conviction, delegations, prior, .. } => { + Voting::Delegating { + balance, target, conviction, delegations, mut prior, .. + } => { // remove any delegation votes to our current target. Self::reduce_upstream_delegation(&target, conviction.votes(balance)); + let now = frame_system::Pallet::::block_number(); + let lock_periods = conviction.lock_periods().into(); + let unlock_block = now + .saturating_add(T::VoteLockingPeriod::get().saturating_mul(lock_periods)); + prior.accumulate(unlock_block, balance); voting.set_common(delegations, prior); }, Voting::Direct { votes, delegations, prior } => { @@ -1548,7 +1566,9 @@ impl Pallet { Self::reduce_upstream_delegation(&target, conviction.votes(balance)); let now = frame_system::Pallet::::block_number(); let lock_periods = conviction.lock_periods().into(); - prior.accumulate(now + T::VoteLockingPeriod::get() * lock_periods, balance); + let unlock_block = now + .saturating_add(T::VoteLockingPeriod::get().saturating_mul(lock_periods)); + prior.accumulate(unlock_block, balance); voting.set_common(delegations, prior); Ok(votes) @@ -1607,7 +1627,7 @@ impl Pallet { LastTabledWasExternal::::put(true); Self::deposit_event(Event::::ExternalTabled); Self::inject_referendum( - now + T::VotingPeriod::get(), + now.saturating_add(T::VotingPeriod::get()), proposal, threshold, T::EnactmentPeriod::get(), @@ -1639,7 +1659,7 @@ impl Pallet { depositors, }); Self::inject_referendum( - now + T::VotingPeriod::get(), + now.saturating_add(T::VotingPeriod::get()), proposal, VoteThreshold::SuperMajorityApprove, T::EnactmentPeriod::get(), @@ -1693,7 +1713,7 @@ impl Pallet { if status.delay.is_zero() { let _ = Self::do_enact_proposal(status.proposal_hash, index); } else { - let when = now + status.delay; + let when = now.saturating_add(status.delay); // Note that we need the preimage now. Preimages::::mutate_exists( &status.proposal_hash, diff --git a/frame/democracy/src/tests/delegation.rs b/frame/democracy/src/tests/delegation.rs index f644f2295174..3551ca8f9112 100644 --- a/frame/democracy/src/tests/delegation.rs +++ b/frame/democracy/src/tests/delegation.rs @@ -158,7 +158,7 @@ fn conviction_should_be_honored_in_delegation() { // If transactor voted, delegated vote is overwritten. new_test_ext().execute_with(|| { let r = begin_referendum(); - // Delegate, undelegate and vote. + // Delegate and vote. assert_ok!(Democracy::delegate(Origin::signed(2), 1, Conviction::Locked6x, 20)); assert_ok!(Democracy::vote(Origin::signed(1), r, aye(1))); // Delegated vote is huge. @@ -177,3 +177,42 @@ fn split_vote_delegation_should_be_ignored() { assert_eq!(tally(r), Tally { ayes: 1, nays: 0, turnout: 10 }); }); } + +#[test] +fn redelegation_keeps_lock() { + // If transactor voted, delegated vote is overwritten. + new_test_ext().execute_with(|| { + let r = begin_referendum(); + // Delegate and vote. + assert_ok!(Democracy::delegate(Origin::signed(2), 1, Conviction::Locked6x, 20)); + assert_ok!(Democracy::vote(Origin::signed(1), r, aye(1))); + // Delegated vote is huge. + assert_eq!(tally(r), Tally { ayes: 121, nays: 0, turnout: 30 }); + + let mut prior_lock = vote::PriorLock::default(); + + // Locked balance of delegator exists + assert_eq!(VotingOf::::get(2).locked_balance(), 20); + assert_eq!(VotingOf::::get(2).prior(), &prior_lock); + + // Delegate someone else at a lower conviction and amount + assert_ok!(Democracy::delegate(Origin::signed(2), 3, Conviction::None, 10)); + + // 6x prior should appear w/ locked balance. + prior_lock.accumulate(98, 20); + assert_eq!(VotingOf::::get(2).prior(), &prior_lock); + assert_eq!(VotingOf::::get(2).locked_balance(), 20); + // Unlock shouldn't work + assert_ok!(Democracy::unlock(Origin::signed(2), 2)); + assert_eq!(VotingOf::::get(2).prior(), &prior_lock); + assert_eq!(VotingOf::::get(2).locked_balance(), 20); + + fast_forward_to(100); + + // Now unlock can remove the prior lock and reduce the locked amount. + assert_eq!(VotingOf::::get(2).prior(), &prior_lock); + assert_ok!(Democracy::unlock(Origin::signed(2), 2)); + assert_eq!(VotingOf::::get(2).prior(), &vote::PriorLock::default()); + assert_eq!(VotingOf::::get(2).locked_balance(), 10); + }); +} diff --git a/frame/democracy/src/vote.rs b/frame/democracy/src/vote.rs index e6a252dcf015..c74623d4dfeb 100644 --- a/frame/democracy/src/vote.rs +++ b/frame/democracy/src/vote.rs @@ -183,7 +183,7 @@ impl votes.iter().map(|i| i.1.balance()).fold(prior.locked(), |a, i| a.max(i)), - Voting::Delegating { balance, .. } => *balance, + Voting::Delegating { balance, prior, .. } => *balance.max(&prior.locked()), } } @@ -199,4 +199,11 @@ impl &PriorLock { + match self { + Voting::Direct { prior, .. } => prior, + Voting::Delegating { prior, .. } => prior, + } + } } From 2c9adf95437a8d3056bcacb0852a91a0940399b4 Mon Sep 17 00:00:00 2001 From: driemworks Date: Wed, 16 Feb 2022 14:34:56 -0500 Subject: [PATCH 506/695] cleanup storage maps, cleanup unused imports --- bin/node-template/node/src/service.rs | 1 - .../pallets/iris-assets/src/lib.rs | 8 +- .../pallets/iris-session/src/lib.rs | 121 ++++++++++-------- .../pallets/iris-session/src/tests.rs | 13 +- bin/node-template/runtime/src/lib.rs | 16 +-- 5 files changed, 87 insertions(+), 72 deletions(-) diff --git a/bin/node-template/node/src/service.rs b/bin/node-template/node/src/service.rs index 31b228040441..17fd9a646f78 100644 --- a/bin/node-template/node/src/service.rs +++ b/bin/node-template/node/src/service.rs @@ -192,7 +192,6 @@ pub fn new_full(mut config: Configuration) -> Result block_announce_validator_builder: None, warp_sync: Some(warp_sync), })?; - let keystore = keystore_container.sync_keystore(); if config.offchain_worker.enabled { sc_service::build_offchain_workers( &config, diff --git a/bin/node-template/pallets/iris-assets/src/lib.rs b/bin/node-template/pallets/iris-assets/src/lib.rs index b02d85755339..d1f5772f048c 100644 --- a/bin/node-template/pallets/iris-assets/src/lib.rs +++ b/bin/node-template/pallets/iris-assets/src/lib.rs @@ -65,10 +65,6 @@ pub mod pallet { use frame_support::{dispatch::DispatchResult, pallet_prelude::*}; use frame_system::{ pallet_prelude::*, - offchain::{ - AppCrypto, - CreateSignedTransaction, - }, }; use sp_core::offchain::OpaqueMultiaddr; use sp_std::{str, vec::Vec}; @@ -156,6 +152,7 @@ pub mod pallet { AssetCreated(T::AssetId), /// A node has published ipfs identity results on chain PublishedIdentity(T::AccountId), + QueuedDataToPin, } #[pallet::error] @@ -335,6 +332,9 @@ pub mod pallet { asset_id.clone(), cid.clone(), ))); + + Self::deposit_event(Event::QueuedDataToPin); + Ok(()) } diff --git a/bin/node-template/pallets/iris-session/src/lib.rs b/bin/node-template/pallets/iris-session/src/lib.rs index 15aa00c8009d..0ba6e168da08 100644 --- a/bin/node-template/pallets/iris-session/src/lib.rs +++ b/bin/node-template/pallets/iris-session/src/lib.rs @@ -291,9 +291,9 @@ pub mod pallet { /// Validate unsigned call to this module. /// fn validate_unsigned(_source: TransactionSource, call: &Self::Call) -> TransactionValidity { - if let Call::submit_rpc_ready { asset_id } = call { + if let Call::submit_rpc_ready { .. } = call { Self::validate_transaction_parameters() - } else if let Call::submit_ipfs_identity{ public_key, multiaddresses } = call { + } else if let Call::submit_ipfs_identity{ .. } = call { Self::validate_transaction_parameters() } else { InvalidTransaction::Call.into() @@ -433,13 +433,23 @@ pub mod pallet { // submit a request to join a storage pool in the next session let who = ensure_signed(origin)?; let new_origin = system::RawOrigin::Signed(who.clone()).into(); - let candidate_storage_providers = >::get(pool_id.clone()); - ensure!(!candidate_storage_providers.contains(&who), Error::::AlreadyACandidate); + // if the node is already a candidate, do not proceed; + ensure!( + !>::get(pool_id.clone()).contains(&who), + Error::::AlreadyACandidate, + ); + // if the node is already a storage provider, do not proceed + ensure!( + !>::get(pool_id.clone()).contains(&who), + Error::::AlreadyPinned, + ); + + let owner = T::Lookup::lookup(pool_owner)?; + >::insert_pin_request(new_origin, owner, pool_id).map_err(|_| Error::::CantCreateRequest)?; + >::mutate(pool_id.clone(), |sp| { sp.push(who.clone()); }); - let owner = T::Lookup::lookup(pool_owner)?; - >::insert_pin_request(new_origin, owner, pool_id).map_err(|_| Error::::CantCreateRequest); Self::deposit_event(Event::RequestJoinStoragePoolSuccess(who.clone(), pool_id.clone())); Ok(()) } @@ -463,7 +473,6 @@ pub mod pallet { id: T::AssetId, balance: T::Balance, ) -> DispatchResult { - // TODO: explore consequences of changing to ensure_root let who = ensure_signed(origin)?; let new_origin = system::RawOrigin::Signed(who.clone()).into(); // creates the asset class @@ -523,7 +532,7 @@ pub mod pallet { asset_id: T::AssetId, pinner: T::AccountId, ) -> DispatchResult { - let who = ensure_signed(origin)?; + let _who = ensure_signed(origin)?; // verify they are a candidate storage provider let candidate_storage_providers = >::get(asset_id.clone()); ensure!(candidate_storage_providers.contains(&pinner), Error::::NotACandidate); @@ -555,7 +564,7 @@ pub mod pallet { /// #[pallet::weight(100)] pub fn submit_rpc_ready( - origin: OriginFor, + _origin: OriginFor, asset_id: T::AssetId, ) -> DispatchResult { // ensure_signed(origin)?; @@ -570,10 +579,7 @@ pub mod pallet { era_rewards.total += 1; } }); - } else { - // error -> no active era found } - // Self::deposit_event(Event::DataReady(beneficiary)); Ok(()) } } @@ -669,17 +675,21 @@ impl Pallet { /// TODO: this undoubtedly will not scale very well fn select_candidate_storage_providers() { // if there are candidate storage providers => for each candidate that pinned the file, move them to storage providers - for assetid in >::asset_ids().into_iter() { + for asset_id in >::asset_ids().into_iter() { // if there are candidates for the asset id - if >::contains_key(assetid.clone()) { - let candidates = >::get(assetid.clone()); - let pinners = >::get(assetid.clone()); - let pinner_candidate_intersection = + if >::contains_key(asset_id.clone()) { + let candidates = >::get(asset_id.clone()); + let pinners = >::get(asset_id.clone()); + let mut pinner_candidate_intersection = candidates.into_iter().filter(|c| pinners.contains(c)).collect::>(); - log::info!("Adding {:?} more storage providers", pinner_candidate_intersection.len()); - // need to only move candidates that have actually proved they pinned the content - >::insert(assetid.clone(), pinner_candidate_intersection); - } + // >::insert(asset_id.clone(), pinner_candidate_intersection); + >::mutate(asset_id.clone(), |sps| { + sps.append(&mut pinner_candidate_intersection); + }); + >::mutate(asset_id.clone(), |qsps| { + *qsps = Vec::new(); + }); + } } } @@ -693,15 +703,21 @@ impl Pallet { *v += 1; }); } else { - // TODO - Self::do_remove_validator(acct); + let mut validators = >::get(); + // Ensuring that the post removal, target validator count doesn't go + // below the minimum. + if validators.len().saturating_sub(1) as u32 >= T::MinAuthorities::get() { + validators.retain(|v| *v != acct.clone()); + >::put(validators); + log::debug!(target: LOG_TARGET, "Validator removal initiated."); + } } } } } fn validate_transaction_parameters() -> TransactionValidity { - ValidTransaction::with_tag_prefix("rpc_ready") + ValidTransaction::with_tag_prefix("iris") .longevity(5) .propagate(true) .build() @@ -872,7 +888,7 @@ impl Pallet { DataCommand::CatBytes(requestor, owner, asset_id) => { // fetch ipfs id let public_key = - if let IpfsResponse::Identity(public_key, addrs) = + if let IpfsResponse::Identity(public_key, _addrs) = Self::ipfs_request(IpfsRequest::Identity, deadline)? { public_key } else { @@ -882,41 +898,38 @@ impl Pallet { let expected_pub_key = >::get(requestor.clone()); ensure!(public_key == expected_pub_key, Error::::BadOrigin); - if let cid = >::asset_class_ownership( + let cid = >::asset_class_ownership( owner.clone(), asset_id.clone() - ) { - ensure!( - owner.clone() == >::asset_access(requestor.clone(), asset_id.clone()), - Error::::InsufficientBalance - ); - match Self::ipfs_request(IpfsRequest::CatBytes(cid.clone()), deadline) { - Ok(IpfsResponse::CatBytes(data)) => { - log::info!("IPFS: Fetched data from IPFS."); - // add to offchain index - sp_io::offchain::local_storage_set( - StorageKind::PERSISTENT, - &cid, - &data, - ); - let call = Call::submit_rpc_ready { - asset_id: asset_id.clone(), - }; - SubmitTransaction::>::submit_unsigned_transaction(call.into()) - .map_err(|()| Error::::CantCreateRequest)?; - }, - Ok(_) => unreachable!("only CatBytes can be a response for that request type."), - Err(e) => log::error!("IPFS: cat error: {:?}", e), - } - } else { - log::error!("the provided owner/cid does not map to a valid asset id: {:?}, {:?}", owner, asset_id) + ); + ensure!( + owner.clone() == >::asset_access(requestor.clone(), asset_id.clone()), + Error::::InsufficientBalance + ); + match Self::ipfs_request(IpfsRequest::CatBytes(cid.clone()), deadline) { + Ok(IpfsResponse::CatBytes(data)) => { + log::info!("IPFS: Fetched data from IPFS."); + // add to offchain index + sp_io::offchain::local_storage_set( + StorageKind::PERSISTENT, + &cid, + &data, + ); + let call = Call::submit_rpc_ready { + asset_id: asset_id.clone(), + }; + SubmitTransaction::>::submit_unsigned_transaction(call.into()) + .map_err(|()| Error::::CantCreateRequest)?; + }, + Ok(_) => unreachable!("only CatBytes can be a response for that request type."), + Err(e) => log::error!("IPFS: cat error: {:?}", e), } }, DataCommand::PinCID(acct, asset_id, cid) => { if sp_io::offchain::is_validator() { - let (public_key, addrs) = - if let IpfsResponse::Identity(public_key, addrs) = + let public_key = + if let IpfsResponse::Identity(public_key, _) = Self::ipfs_request(IpfsRequest::Identity, deadline)? { - (public_key, addrs) + public_key } else { unreachable!("only `Identity` is a valid response type."); }; diff --git a/bin/node-template/pallets/iris-session/src/tests.rs b/bin/node-template/pallets/iris-session/src/tests.rs index d64ea9b11e2d..c57b20a41109 100644 --- a/bin/node-template/pallets/iris-session/src/tests.rs +++ b/bin/node-template/pallets/iris-session/src/tests.rs @@ -165,7 +165,9 @@ fn iris_session_join_storage_pool() { id.clone(), )); // AND: I receive a reward point - assert_eq!(crate::ErasRewardPoints::::get(0).p.clone.public(), 1); + let era_reward_points = crate::ErasRewardPoints::::get(0, id.clone()); + assert_eq!(era_reward_points.total, 1); + assert_eq!(era_reward_points.individual.entry(p.clone.public()), 1); }); } @@ -185,8 +187,8 @@ fn iris_session_submit_rpc_ready_works_for_valid_values() { // test OCW functionality // can add bytes to network #[test] -fn iris_can_add_bytes_to_ipfs() { - let v0 = sp_core::sr25519::Pair::generate_with_phrase(Some("0")).0.public(); +fn iris_session_validators_receive_reward_when_add_bytes_to_ipfs() { + // new keypair let (p, _) = sp_core::sr25519::Pair::generate(); let (offchain, state) = testing::TestOffchainExt::new(); let (pool, _) = testing::TestTransactionPoolExt::new(); @@ -252,7 +254,10 @@ fn iris_can_add_bytes_to_ipfs() { assert_ok!(IrisSession::handle_data_requests()); // AND: each validator is given a reward point let eras_reward_points = crate::ErasRewardPoints::::get(0, id.clone()); - assert_eq!(1, eras_reward_points.total); + assert_eq!(3, eras_reward_points.total); + for validator in crate::Validators::::get() { + assert_eq!(1, eras_reward_points.individual.entry(validator)); + } }); } diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index 4f8fb817367d..734166716021 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -15,15 +15,14 @@ use sp_core::{crypto::KeyTypeId, OpaqueMetadata, Encode, Bytes}; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{ - AccountIdLookup, - BlakeTwo256, + AccountIdLookup, + BlakeTwo256, Block as BlockT, - IdentifyAccount, - NumberFor, - Verify, - SaturatedConversion, - OpaqueKeys, - ConvertInto, + IdentifyAccount, + NumberFor, + Verify, + SaturatedConversion, + OpaqueKeys, }, transaction_validity::{TransactionSource, TransactionValidity, TransactionPriority}, ApplyExtrinsicResult, MultiSignature, @@ -33,7 +32,6 @@ use sp_std::prelude::*; use sp_version::NativeVersion; use sp_version::RuntimeVersion; use frame_system::EnsureRoot; -use pallet_session::historical as pallet_session_historical; use pallet_im_online::sr25519::AuthorityId as ImOnlineId; // A few exports that help ease life for downstream crates. From 36b8970ef68b2f8d031f0aeadbe47d06a2679332 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Wed, 16 Feb 2022 20:39:22 +0100 Subject: [PATCH 507/695] sc-executor: Improve logging (#10869) Improves the logging by switching to `tracing` for a better log output. Besides that, it also adds a trace for the function being executed. --- Cargo.lock | 1 - client/executor/Cargo.toml | 3 +- client/executor/src/native_executor.rs | 58 +++++++++++++++----------- client/executor/src/wasm_runtime.rs | 20 ++++----- 4 files changed, 45 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e04aec94d76b..992a49306f18 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8253,7 +8253,6 @@ dependencies = [ "hex-literal", "lazy_static", "libsecp256k1", - "log 0.4.14", "lru 0.6.6", "parity-scale-codec", "parking_lot 0.11.2", diff --git a/client/executor/Cargo.toml b/client/executor/Cargo.toml index 0d0f2a8bd92e..47ef05005086 100644 --- a/client/executor/Cargo.toml +++ b/client/executor/Cargo.toml @@ -31,10 +31,10 @@ sc-executor-common = { version = "0.10.0-dev", path = "common" } sc-executor-wasmi = { version = "0.10.0-dev", path = "wasmi" } sc-executor-wasmtime = { version = "0.10.0-dev", path = "wasmtime", optional = true } parking_lot = "0.11.2" -log = "0.4.8" libsecp256k1 = "0.7" sp-core-hashing-proc-macro = { version = "4.0.0-dev", path = "../../primitives/core/hashing/proc-macro" } lru = "0.6.6" +tracing = "0.1.29" [dev-dependencies] wat = "1.0" @@ -45,7 +45,6 @@ sp-state-machine = { version = "0.11.0", path = "../../primitives/state-machine" sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } sp-maybe-compressed-blob = { version = "4.1.0-dev", path = "../../primitives/maybe-compressed-blob" } sc-tracing = { version = "4.0.0-dev", path = "../tracing" } -tracing = "0.1.29" tracing-subscriber = "0.2.19" paste = "1.0" regex = "1" diff --git a/client/executor/src/native_executor.rs b/client/executor/src/native_executor.rs index 1bc87840ba35..363ea474a7e4 100644 --- a/client/executor/src/native_executor.rs +++ b/client/executor/src/native_executor.rs @@ -35,7 +35,6 @@ use std::{ }; use codec::{Decode, Encode}; -use log::trace; use sc_executor_common::{ runtime_blob::RuntimeBlob, wasm_runtime::{InvokeMethod, WasmInstance, WasmModule}, @@ -301,6 +300,12 @@ where _use_native: bool, _native_call: Option, ) -> (Result>, bool) { + tracing::trace!( + target: "executor", + %method, + "Executing function", + ); + let result = self.with_instance( runtime_code, ext, @@ -422,10 +427,10 @@ impl RuntimeSpawn for RuntimeInstanceSpawn { let async_ext = match new_async_externalities(scheduler.clone()) { Ok(val) => val, Err(e) => { - log::error!( + tracing::error!( target: "executor", - "Failed to setup externalities for async context: {}", - e, + error = %e, + "Failed to setup externalities for async context.", ); // This will drop sender and receiver end will panic @@ -438,10 +443,10 @@ impl RuntimeSpawn for RuntimeInstanceSpawn { )) { Ok(val) => val, Err(e) => { - log::error!( + tracing::error!( target: "executor", - "Failed to setup runtime extension for async externalities: {}", - e, + error = %e, + "Failed to setup runtime extension for async externalities", ); // This will drop sender and receiver end will panic @@ -476,7 +481,7 @@ impl RuntimeSpawn for RuntimeInstanceSpawn { Err(error) => { // If execution is panicked, the `join` in the original runtime code will // panic as well, since the sender is dropped without sending anything. - log::error!("Call error in spawned task: {}", error); + tracing::error!(error = %error, "Call error in spawned task"); }, } }), @@ -518,10 +523,10 @@ fn preregister_builtin_ext(module: Arc) { RuntimeInstanceSpawn::with_externalities_and_module(module, ext) { if let Err(e) = ext.register_extension(RuntimeSpawnExt(Box::new(runtime_spawn))) { - trace!( + tracing::trace!( target: "executor", - "Failed to register `RuntimeSpawnExt` instance on externalities: {:?}", - e, + error = ?e, + "Failed to register `RuntimeSpawnExt` instance on externalities", ) } } @@ -543,6 +548,12 @@ impl CodeExecutor for NativeElseWasmExecut use_native: bool, native_call: Option, ) -> (Result>, bool) { + tracing::trace!( + target: "executor", + function = %method, + "Executing function", + ); + let mut used_native = false; let result = self.wasm.with_instance( runtime_code, @@ -558,11 +569,11 @@ impl CodeExecutor for NativeElseWasmExecut match (use_native, can_call_with, native_call) { (_, false, _) | (false, _, _) => { if !can_call_with { - trace!( + tracing::trace!( target: "executor", - "Request for native execution failed (native: {}, chain: {})", - self.native_version.runtime_version, - onchain_version, + native = %self.native_version.runtime_version, + chain = %onchain_version, + "Request for native execution failed", ); } @@ -572,12 +583,11 @@ impl CodeExecutor for NativeElseWasmExecut }) }, (true, true, Some(call)) => { - trace!( + tracing::trace!( target: "executor", - "Request for native execution with native call succeeded \ - (native: {}, chain: {}).", - self.native_version.runtime_version, - onchain_version, + native = %self.native_version.runtime_version, + chain = %onchain_version, + "Request for native execution with native call succeeded" ); used_native = true; @@ -587,11 +597,11 @@ impl CodeExecutor for NativeElseWasmExecut Ok(res) }, _ => { - trace!( + tracing::trace!( target: "executor", - "Request for native execution succeeded (native: {}, chain: {})", - self.native_version.runtime_version, - onchain_version + native = %self.native_version.runtime_version, + chain = %onchain_version, + "Request for native execution succeeded", ); used_native = true; diff --git a/client/executor/src/wasm_runtime.rs b/client/executor/src/wasm_runtime.rs index 2cccb6f9c38b..d996d7b490e8 100644 --- a/client/executor/src/wasm_runtime.rs +++ b/client/executor/src/wasm_runtime.rs @@ -103,23 +103,23 @@ impl VersionedRuntime { let result = f(&self.module, &mut *instance, self.version.as_ref(), ext); if let Err(e) = &result { if new_inst { - log::warn!( + tracing::warn!( target: "wasm-runtime", - "Fresh runtime instance failed with {}", - e, + error = %e, + "Fresh runtime instance failed", ) } else { - log::warn!( + tracing::warn!( target: "wasm-runtime", - "Evicting failed runtime instance: {}", - e, + error = %e, + "Evicting failed runtime instance", ); } } else { *locked = Some(instance); if new_inst { - log::debug!( + tracing::debug!( target: "wasm-runtime", "Allocated WASM instance {}/{}", index + 1, @@ -131,7 +131,7 @@ impl VersionedRuntime { result }, None => { - log::warn!(target: "wasm-runtime", "Ran out of free WASM instances"); + tracing::warn!(target: "wasm-runtime", "Ran out of free WASM instances"); // Allocate a new instance let mut instance = self.module.new_instance()?; @@ -259,7 +259,7 @@ impl RuntimeCache { match result { Ok(ref result) => { - log::debug!( + tracing::debug!( target: "wasm-runtime", "Prepared new runtime version {:?} in {} ms.", result.version, @@ -267,7 +267,7 @@ impl RuntimeCache { ); }, Err(ref err) => { - log::warn!(target: "wasm-runtime", "Cannot create a runtime: {:?}", err); + tracing::warn!(target: "wasm-runtime", error = ?err, "Cannot create a runtime"); }, } From e742e251932910c2036f59320d39ef6684974ccd Mon Sep 17 00:00:00 2001 From: driemworks Date: Wed, 16 Feb 2022 15:47:13 -0500 Subject: [PATCH 508/695] fix test issues --- .../pallets/iris-session/src/tests.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/bin/node-template/pallets/iris-session/src/tests.rs b/bin/node-template/pallets/iris-session/src/tests.rs index c57b20a41109..40042378dd44 100644 --- a/bin/node-template/pallets/iris-session/src/tests.rs +++ b/bin/node-template/pallets/iris-session/src/tests.rs @@ -165,9 +165,9 @@ fn iris_session_join_storage_pool() { id.clone(), )); // AND: I receive a reward point - let era_reward_points = crate::ErasRewardPoints::::get(0, id.clone()); - assert_eq!(era_reward_points.total, 1); - assert_eq!(era_reward_points.individual.entry(p.clone.public()), 1); + let mut era_reward_points = crate::ErasRewardPoints::::get(0, id.clone()); + assert_eq!(1, era_reward_points.total); + assert_eq!(1u32, *era_reward_points.individual.entry(p.clone().public()).or_default()); }); } @@ -253,10 +253,10 @@ fn iris_session_validators_receive_reward_when_add_bytes_to_ipfs() { // THEN: the offchain worker adds data to IPFS assert_ok!(IrisSession::handle_data_requests()); // AND: each validator is given a reward point - let eras_reward_points = crate::ErasRewardPoints::::get(0, id.clone()); + let mut eras_reward_points = crate::ErasRewardPoints::::get(0, id.clone()); assert_eq!(3, eras_reward_points.total); for validator in crate::Validators::::get() { - assert_eq!(1, eras_reward_points.individual.entry(validator)); + assert_eq!(1u32, *eras_reward_points.individual.entry(validator).or_default()); } }); } @@ -362,10 +362,10 @@ fn iris_can_fetch_bytes_and_add_to_offchain_storage() { // THEN: the offchain worker proxies IPFS requests assert_ok!(IrisSession::handle_data_requests()); // AND: Each storage provider receives a reward point - let eras_reward_points = crate::ErasRewardPoints::::get(0, id.clone()); + let mut eras_reward_points = crate::ErasRewardPoints::::get(0, id.clone()); assert_eq!(3, eras_reward_points.total); for validator in crate::Validators::::get() { - assert_eq!(1, eras_reward_points.individual.entry(validator)); + assert_eq!(1u32, *eras_reward_points.individual.entry(validator).or_default() ); } }); } From e7be15e245dc28848264861ff5b859116a937b3f Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Thu, 17 Feb 2022 12:37:54 +0100 Subject: [PATCH 509/695] Track allowed requests for state/warp sync (#10843) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Track allowed requests for state/warp sync * Added missing allowed_requests resets * Apply suggestions from code review Co-authored-by: Bastian Köcher * fmt Co-authored-by: Bastian Köcher --- client/network/src/protocol/sync.rs | 72 +++++++++++++++++------------ 1 file changed, 43 insertions(+), 29 deletions(-) diff --git a/client/network/src/protocol/sync.rs b/client/network/src/protocol/sync.rs index d98c0d2c04ab..f31afc828bd8 100644 --- a/client/network/src/protocol/sync.rs +++ b/client/network/src/protocol/sync.rs @@ -141,12 +141,12 @@ mod rep { pub const BAD_RESPONSE: Rep = Rep::new(-(1 << 12), "Incomplete response"); } -enum PendingRequests { +enum AllowedRequests { Some(HashSet), All, } -impl PendingRequests { +impl AllowedRequests { fn add(&mut self, id: &PeerId) { if let Self::Some(ref mut set) = self { set.insert(*id); @@ -174,9 +174,13 @@ impl PendingRequests { Self::All => false, } } + + fn clear(&mut self) { + std::mem::take(self); + } } -impl Default for PendingRequests { +impl Default for AllowedRequests { fn default() -> Self { Self::Some(HashSet::default()) } @@ -211,7 +215,7 @@ pub struct ChainSync { /// Fork sync targets. fork_targets: HashMap>, /// A set of peers for which there might be potential block requests - pending_requests: PendingRequests, + allowed_requests: AllowedRequests, /// A type to check incoming block announcements. block_announce_validator: Box + Send>, /// Maximum number of peers to ask the same blocks in parallel. @@ -549,7 +553,7 @@ impl ChainSync { mode, queue_blocks: Default::default(), fork_targets: Default::default(), - pending_requests: Default::default(), + allowed_requests: Default::default(), block_announce_validator, max_parallel_downloads, downloaded_blocks: 0, @@ -730,7 +734,7 @@ impl ChainSync { ) }; - self.pending_requests.add(&who); + self.allowed_requests.add(&who); self.peers.insert( who, PeerSync { @@ -774,7 +778,7 @@ impl ChainSync { state: PeerSyncState::Available, }, ); - self.pending_requests.add(&who); + self.allowed_requests.add(&who); Ok(None) }, } @@ -841,7 +845,7 @@ impl ChainSync { peer.best_number = number; peer.best_hash = *hash; } - self.pending_requests.add(peer_id); + self.allowed_requests.add(peer_id); } } @@ -883,7 +887,7 @@ impl ChainSync { /// Get an iterator over all block requests of all peers. pub fn block_requests(&mut self) -> impl Iterator)> + '_ { - if self.pending_requests.is_empty() || + if self.allowed_requests.is_empty() || self.state_sync.is_some() || self.mode == SyncMode::Warp { @@ -903,11 +907,11 @@ impl ChainSync { let best_queued = self.best_queued_number; let client = &self.client; let queue = &self.queue_blocks; - let pending_requests = self.pending_requests.take(); + let allowed_requests = self.allowed_requests.take(); let max_parallel = if major_sync { 1 } else { self.max_parallel_downloads }; let gap_sync = &mut self.gap_sync; let iter = self.peers.iter_mut().filter_map(move |(id, peer)| { - if !peer.state.is_available() || !pending_requests.contains(id) { + if !peer.state.is_available() || !allowed_requests.contains(id) { return None } @@ -994,7 +998,12 @@ impl ChainSync { /// Get a state request, if any. pub fn state_request(&mut self) -> Option<(PeerId, StateRequest)> { - if self.peers.iter().any(|(_, peer)| peer.state == PeerSyncState::DownloadingState) { + if self.allowed_requests.is_empty() { + return None + } + if (self.state_sync.is_some() || self.warp_sync.is_some()) && + self.peers.iter().any(|(_, peer)| peer.state == PeerSyncState::DownloadingState) + { // Only one pending state request is allowed. return None } @@ -1002,11 +1011,13 @@ impl ChainSync { if sync.is_complete() { return None } + for (id, peer) in self.peers.iter_mut() { if peer.state.is_available() && peer.common_number >= sync.target_block_num() { peer.state = PeerSyncState::DownloadingState; let request = sync.next_request(); trace!(target: "sync", "New StateRequest for {}: {:?}", id, request); + self.allowed_requests.clear(); return Some((*id, request)) } } @@ -1022,6 +1033,7 @@ impl ChainSync { if peer.state.is_available() && peer.best_number >= target { trace!(target: "sync", "New StateRequest for {}: {:?}", id, request); peer.state = PeerSyncState::DownloadingState; + self.allowed_requests.clear(); return Some((*id, request)) } } @@ -1032,16 +1044,14 @@ impl ChainSync { /// Get a warp sync request, if any. pub fn warp_sync_request(&mut self) -> Option<(PeerId, WarpProofRequest)> { - if self - .peers - .iter() - .any(|(_, peer)| peer.state == PeerSyncState::DownloadingWarpProof) - { - // Only one pending state request is allowed. - return None - } if let Some(sync) = &self.warp_sync { - if sync.is_complete() { + if self.allowed_requests.is_empty() || + sync.is_complete() || + self.peers + .iter() + .any(|(_, peer)| peer.state == PeerSyncState::DownloadingWarpProof) + { + // Only one pending state request is allowed. return None } if let Some(request) = sync.next_warp_poof_request() { @@ -1054,6 +1064,7 @@ impl ChainSync { if peer.state.is_available() && peer.best_number >= median { trace!(target: "sync", "New WarpProofRequest for {}", id); peer.state = PeerSyncState::DownloadingWarpProof; + self.allowed_requests.clear(); return Some((*id, request)) } } @@ -1087,7 +1098,7 @@ impl ChainSync { trace!(target: "sync", "Reversing incoming block list"); blocks.reverse() } - self.pending_requests.add(who); + self.allowed_requests.add(who); if let Some(request) = request { match &mut peer.state { PeerSyncState::DownloadingNew(_) => { @@ -1306,6 +1317,7 @@ impl ChainSync { if let Some(peer) = self.peers.get_mut(&who) { if let PeerSyncState::DownloadingState = peer.state { peer.state = PeerSyncState::Available; + self.allowed_requests.set_all(); } } let import_result = if let Some(sync) = &mut self.state_sync { @@ -1368,6 +1380,7 @@ impl ChainSync { if let Some(peer) = self.peers.get_mut(&who) { if let PeerSyncState::DownloadingWarpProof = peer.state { peer.state = PeerSyncState::Available; + self.allowed_requests.set_all(); } } let import_result = if let Some(sync) = &mut self.warp_sync { @@ -1448,7 +1461,7 @@ impl ChainSync { return Ok(OnBlockJustification::Nothing) }; - self.pending_requests.add(&who); + self.allowed_requests.add(&who); if let PeerSyncState::DownloadingJustification(hash) = peer.state { peer.state = PeerSyncState::Available; @@ -1638,7 +1651,7 @@ impl ChainSync { }; } - self.pending_requests.set_all(); + self.allowed_requests.set_all(); output.into_iter() } @@ -1648,7 +1661,7 @@ impl ChainSync { let finalization_result = if success { Ok((hash, number)) } else { Err(()) }; self.extra_justifications .try_finalize_root((hash, number), finalization_result, true); - self.pending_requests.set_all(); + self.allowed_requests.set_all(); } /// Notify about finalization of the given block. @@ -1675,6 +1688,7 @@ impl ChainSync { ); self.state_sync = Some(StateSync::new(self.client.clone(), header, *skip_proofs)); + self.allowed_requests.set_all(); } } } @@ -1725,7 +1739,7 @@ impl ChainSync { peer.common_number = new_common_number; } } - self.pending_requests.set_all(); + self.allowed_requests.set_all(); } /// Checks if there is a slot for a block announce validation. @@ -1994,7 +2008,7 @@ impl ChainSync { peer.update_common_number(number - One::one()); } } - self.pending_requests.add(&who); + self.allowed_requests.add(&who); // known block case if known || self.is_already_downloading(&hash) { @@ -2060,7 +2074,7 @@ impl ChainSync { } self.peers.remove(who); self.extra_justifications.peer_disconnected(who); - self.pending_requests.set_all(); + self.allowed_requests.set_all(); self.fork_targets.retain(|_, target| { target.peers.remove(who); !target.peers.is_empty() @@ -2083,7 +2097,7 @@ impl ChainSync { if let Err(e) = self.reset_sync_start_point() { warn!(target: "sync", "💔 Unable to restart sync: {}", e); } - self.pending_requests.set_all(); + self.allowed_requests.set_all(); debug!(target:"sync", "Restarted with {} ({})", self.best_queued_number, self.best_queued_hash); let old_peers = std::mem::take(&mut self.peers); From d435ffb0ffee9e0743d4b679699e3ecacffd0d3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Thu, 17 Feb 2022 17:05:18 +0100 Subject: [PATCH 510/695] Slots: Ensure that a race betwen finalized and best number is taken care off (#10876) --- client/consensus/slots/src/lib.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/client/consensus/slots/src/lib.rs b/client/consensus/slots/src/lib.rs index 9fc93788a33e..fc635e918405 100644 --- a/client/consensus/slots/src/lib.rs +++ b/client/consensus/slots/src/lib.rs @@ -789,7 +789,9 @@ where return false } - let unfinalized_block_length = chain_head_number - finalized_number; + // There can be race between getting the finalized number and getting the best number. + // So, better be safe than sorry. + let unfinalized_block_length = chain_head_number.saturating_sub(finalized_number); let interval = unfinalized_block_length.saturating_sub(self.unfinalized_slack) / self.authoring_bias; let interval = interval.min(self.max_interval); From 13495bee57188ff20c47e12b470a3ca2e671e0d9 Mon Sep 17 00:00:00 2001 From: Nazar Mokrynskyi Date: Fri, 18 Feb 2022 11:03:18 +0200 Subject: [PATCH 511/695] Remove old lock file (#10879) --- primitives/npos-elections/fuzzer/Cargo.lock | 1602 ------------------- 1 file changed, 1602 deletions(-) delete mode 100644 primitives/npos-elections/fuzzer/Cargo.lock diff --git a/primitives/npos-elections/fuzzer/Cargo.lock b/primitives/npos-elections/fuzzer/Cargo.lock deleted file mode 100644 index cd172421aeb2..000000000000 --- a/primitives/npos-elections/fuzzer/Cargo.lock +++ /dev/null @@ -1,1602 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -[[package]] -name = "Inflector" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" -dependencies = [ - "lazy_static", - "regex", -] - -[[package]] -name = "ahash" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f33b5018f120946c1dcf279194f238a9f146725593ead1c08fa47ff22b0b5d3" -dependencies = [ - "const-random", -] - -[[package]] -name = "aho-corasick" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada" -dependencies = [ - "memchr", -] - -[[package]] -name = "arbitrary" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64cf76cb6e2222ed0ea86b2b0ee2f71c96ec6edd5af42e84d59160e91b836ec4" - -[[package]] -name = "arrayref" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" - -[[package]] -name = "arrayvec" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" -dependencies = [ - "nodrop", -] - -[[package]] -name = "arrayvec" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" - -[[package]] -name = "autocfg" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" - -[[package]] -name = "autocfg" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" - -[[package]] -name = "backtrace" -version = "0.3.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad235dabf00f36301792cfe82499880ba54c6486be094d1047b02bacb67c14e8" -dependencies = [ - "backtrace-sys", - "cfg-if", - "libc", - "rustc-demangle", -] - -[[package]] -name = "backtrace-sys" -version = "0.1.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca797db0057bae1a7aa2eef3283a874695455cecf08a43bfb8507ee0ebc1ed69" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "base58" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5024ee8015f02155eee35c711107ddd9a9bf3cb689cf2a9089c97e79b6e1ae83" - -[[package]] -name = "bitflags" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" - -[[package]] -name = "bitvec" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a993f74b4c99c1908d156b8d2e0fb6277736b0ecbd833982fd1241d39b2766a6" - -[[package]] -name = "blake2-rfc" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" -dependencies = [ - "arrayvec 0.4.12", - "constant_time_eq", -] - -[[package]] -name = "block-buffer" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" -dependencies = [ - "block-padding", - "byte-tools", - "byteorder", - "generic-array", -] - -[[package]] -name = "block-padding" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" -dependencies = [ - "byte-tools", -] - -[[package]] -name = "byte-slice-cast" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0a5e3906bcbf133e33c1d4d95afc664ad37fbdb9f6568d8043e7ea8c27d93d3" - -[[package]] -name = "byte-tools" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" - -[[package]] -name = "byteorder" -version = "1.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" - -[[package]] -name = "cc" -version = "1.0.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd" - -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - -[[package]] -name = "clear_on_drop" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97276801e127ffb46b66ce23f35cc96bd454fa311294bced4bbace7baa8b1d17" -dependencies = [ - "cc", -] - -[[package]] -name = "cloudabi" -version = "0.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -dependencies = [ - "bitflags", -] - -[[package]] -name = "const-random" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f1af9ac737b2dd2d577701e59fd09ba34822f6f2ebdb30a7647405d9e55e16a" -dependencies = [ - "const-random-macro", - "proc-macro-hack", -] - -[[package]] -name = "const-random-macro" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25e4c606eb459dd29f7c57b2e0879f2b6f14ee130918c2b78ccb58a9624e6c7a" -dependencies = [ - "getrandom", - "proc-macro-hack", -] - -[[package]] -name = "constant_time_eq" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" - -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - -[[package]] -name = "crypto-mac" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" -dependencies = [ - "generic-array", - "subtle 1.0.0", -] - -[[package]] -name = "curve25519-dalek" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b7dcd30ba50cdf88b55b033456138b7c0ac4afdc436d82e1b79f370f24cc66d" -dependencies = [ - "byteorder", - "clear_on_drop", - "digest", - "rand_core 0.3.1", - "subtle 2.2.2", -] - -[[package]] -name = "curve25519-dalek" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26778518a7f6cffa1d25a44b602b62b979bd88adb9e99ffec546998cf3404839" -dependencies = [ - "byteorder", - "digest", - "rand_core 0.5.1", - "subtle 2.2.2", - "zeroize 1.1.0", -] - -[[package]] -name = "derive_more" -version = "0.99.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a806e96c59a76a5ba6e18735b6cf833344671e61e7863f2edb5c518ea2cac95c" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "digest" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" -dependencies = [ - "generic-array", -] - -[[package]] -name = "ed25519-dalek" -version = "1.0.0-pre.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978710b352437433c97b2bff193f2fb1dfd58a093f863dd95e225a19baa599a2" -dependencies = [ - "clear_on_drop", - "curve25519-dalek 2.0.0", - "rand 0.7.3", - "sha2", -] - -[[package]] -name = "environmental" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "516aa8d7a71cb00a1c4146f0798549b93d083d4f189b3ced8f3de6b8f11ee6c4" - -[[package]] -name = "failure" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8529c2421efa3066a5cbd8063d2244603824daccb6936b079010bb2aa89464b" -dependencies = [ - "backtrace", - "failure_derive", -] - -[[package]] -name = "failure_derive" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "030a733c8287d6213886dd487564ff5c8f6aae10278b3588ed177f9d18f8d231" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - -[[package]] -name = "fake-simd" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" - -[[package]] -name = "fixed-hash" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3367952ceb191f4ab95dd5685dc163ac539e36202f9fcfd0cb22f9f9c542fefc" -dependencies = [ - "byteorder", - "libc", - "rand 0.7.3", - "rustc-hex", - "static_assertions", -] - -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" - -[[package]] -name = "generic-array" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" -dependencies = [ - "typenum", -] - -[[package]] -name = "getrandom" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "hash-db" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d23bd4e7b5eda0d0f3a307e8b381fdc8ba9000f26fbe912250c0a4cc3956364a" - -[[package]] -name = "hash256-std-hasher" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92c171d55b98633f4ed3860808f004099b36c1cc29c42cfc53aa8591b21efcf2" -dependencies = [ - "crunchy", -] - -[[package]] -name = "hashbrown" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e6073d0ca812575946eb5f35ff68dbe519907b25c42530389ff946dc84c6ead" -dependencies = [ - "ahash", - "autocfg 0.1.7", -] - -[[package]] -name = "hex" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35" - -[[package]] -name = "hmac" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695" -dependencies = [ - "crypto-mac", - "digest", -] - -[[package]] -name = "hmac-drbg" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6e570451493f10f6581b48cdd530413b63ea9e780f544bfd3bdcaa0d89d1a7b" -dependencies = [ - "digest", - "generic-array", - "hmac", -] - -[[package]] -name = "honggfuzz" -version = "0.5.45" -dependencies = [ - "arbitrary", - "lazy_static", - "memmap", -] - -[[package]] -name = "impl-codec" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1be51a921b067b0eaca2fad532d9400041561aa922221cc65f95a85641c6bf53" -dependencies = [ - "parity-scale-codec", -] - -[[package]] -name = "impl-serde" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58e3cae7e99c7ff5a995da2cf78dd0a5383740eda71d98cf7b1910c301ac69b8" -dependencies = [ - "serde", -] - -[[package]] -name = "impl-serde" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bbe9ea9b182f0fb1cabbd61f4ff9b7b7b9197955e95a7e4c27de5055eb29ff8" -dependencies = [ - "serde", -] - -[[package]] -name = "impl-trait-for-tuples" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef5550a42e3740a0e71f909d4c861056a284060af885ae7aa6242820f920d9d" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "integer-sqrt" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f65877bf7d44897a473350b1046277941cee20b263397e90869c50b6e766088b" - -[[package]] -name = "keccak" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.67" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb147597cdf94ed43ab7a9038716637d2d1bf2bc571da995d0028dec06bd3018" - -[[package]] -name = "libsecp256k1" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc1e2c808481a63dc6da2074752fdd4336a3c8fcc68b83db6f1fd5224ae7962" -dependencies = [ - "arrayref", - "crunchy", - "digest", - "hmac-drbg", - "rand 0.7.3", - "sha2", - "subtle 2.2.2", - "typenum", -] - -[[package]] -name = "lock_api" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79b2de95ecb4691949fea4716ca53cdbcfccb2c612e19644a8bad05edcf9f47b" -dependencies = [ - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "maybe-uninit" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" - -[[package]] -name = "memchr" -version = "2.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" - -[[package]] -name = "memmap" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "memory-db" -version = "0.19.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "198831fe8722331a395bc199a5d08efbc197497ef354cb4c77b969c02ffc0fc4" -dependencies = [ - "ahash", - "hash-db", - "hashbrown", - "parity-util-mem", -] - -[[package]] -name = "memory_units" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882" - -[[package]] -name = "merlin" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b0942b357c1b4d0dc43ba724674ec89c3218e6ca2b3e8269e7cb53bcecd2f6e" -dependencies = [ - "byteorder", - "keccak", - "rand_core 0.4.2", - "zeroize 1.1.0", -] - -[[package]] -name = "nodrop" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" - -[[package]] -name = "num-bigint" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" -dependencies = [ - "autocfg 1.0.0", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-integer" -version = "0.1.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" -dependencies = [ - "autocfg 1.0.0", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da4dc79f9e6c81bef96148c8f6b8e72ad4541caa4a24373e900a36da07de03a3" -dependencies = [ - "autocfg 1.0.0", - "num-bigint", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" -dependencies = [ - "autocfg 1.0.0", -] - -[[package]] -name = "once_cell" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c601810575c99596d4afc46f78a678c80105117c379eb3650cf99b8a21ce5b" -dependencies = [ - "parking_lot 0.9.0", -] - -[[package]] -name = "opaque-debug" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" - -[[package]] -name = "parity-scale-codec" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f509c5e67ca0605ee17dcd3f91ef41cadd685c75a298fb6261b781a5acb3f910" -dependencies = [ - "arrayvec 0.5.1", - "bitvec", - "byte-slice-cast", - "parity-scale-codec-derive", - "serde", -] - -[[package]] -name = "parity-scale-codec-derive" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a0ec292e92e8ec7c58e576adacc1e3f399c597c8f263c42f18420abe58e7245" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "parity-util-mem" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef1476e40bf8f5c6776e9600983435821ca86eb9819d74a6207cca69d091406a" -dependencies = [ - "cfg-if", - "impl-trait-for-tuples", - "parity-util-mem-derive", - "parking_lot 0.10.0", - "primitive-types", - "winapi", -] - -[[package]] -name = "parity-util-mem-derive" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f557c32c6d268a07c921471619c0295f5efad3a0e76d4f97a05c091a51d110b2" -dependencies = [ - "proc-macro2", - "syn", - "synstructure", -] - -[[package]] -name = "parity-wasm" -version = "0.41.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfc878dac00da22f8f61e7af3157988424567ab01d9920b962ef7dcbd7cd865" - -[[package]] -name = "parking_lot" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" -dependencies = [ - "lock_api", - "parking_lot_core 0.6.2", - "rustc_version", -] - -[[package]] -name = "parking_lot" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92e98c49ab0b7ce5b222f2cc9193fc4efe11c6d0bd4f648e374684a6857b1cfc" -dependencies = [ - "lock_api", - "parking_lot_core 0.7.0", -] - -[[package]] -name = "parking_lot_core" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" -dependencies = [ - "cfg-if", - "cloudabi", - "libc", - "redox_syscall", - "rustc_version", - "smallvec 0.6.13", - "winapi", -] - -[[package]] -name = "parking_lot_core" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7582838484df45743c8434fbff785e8edf260c28748353d44bc0da32e0ceabf1" -dependencies = [ - "cfg-if", - "cloudabi", - "libc", - "redox_syscall", - "smallvec 1.3.0", - "winapi", -] - -[[package]] -name = "paste" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63e1afe738d71b1ebab5f1207c055054015427dbfc7bbe9ee1266894156ec046" -dependencies = [ - "paste-impl", - "proc-macro-hack", -] - -[[package]] -name = "paste-impl" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d4dc4a7f6f743211c5aab239640a65091535d97d43d92a52bca435a640892bb" -dependencies = [ - "proc-macro-hack", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "pbkdf2" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9" -dependencies = [ - "byteorder", - "crypto-mac", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" - -[[package]] -name = "primitive-types" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4336f4f5d5524fa60bcbd6fe626f9223d8142a50e7053e979acdf0da41ab975" -dependencies = [ - "fixed-hash", - "impl-codec", - "impl-serde 0.3.0", - "uint", -] - -[[package]] -name = "proc-macro-crate" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e10d4b51f154c8a7fb96fd6dad097cb74b863943ec010ac94b9fd1be8861fe1e" -dependencies = [ - "toml", -] - -[[package]] -name = "proc-macro-hack" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "proc-macro2" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "quote" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" -dependencies = [ - "autocfg 0.1.7", - "libc", - "rand_chacha 0.1.1", - "rand_core 0.4.2", - "rand_hc 0.1.0", - "rand_isaac", - "rand_jitter", - "rand_os", - "rand_pcg", - "rand_xorshift", - "winapi", -] - -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc 0.2.0", -] - -[[package]] -name = "rand_chacha" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" -dependencies = [ - "autocfg 0.1.7", - "rand_core 0.3.1", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", -] - -[[package]] -name = "rand_core" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -dependencies = [ - "rand_core 0.4.2", -] - -[[package]] -name = "rand_core" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rand_hc" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" -dependencies = [ - "rand_core 0.3.1", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", -] - -[[package]] -name = "rand_isaac" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -dependencies = [ - "rand_core 0.3.1", -] - -[[package]] -name = "rand_jitter" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" -dependencies = [ - "libc", - "rand_core 0.4.2", - "winapi", -] - -[[package]] -name = "rand_os" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" -dependencies = [ - "cloudabi", - "fuchsia-cprng", - "libc", - "rand_core 0.4.2", - "rdrand", - "winapi", -] - -[[package]] -name = "rand_pcg" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" -dependencies = [ - "autocfg 0.1.7", - "rand_core 0.4.2", -] - -[[package]] -name = "rand_xorshift" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" -dependencies = [ - "rand_core 0.3.1", -] - -[[package]] -name = "rdrand" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -dependencies = [ - "rand_core 0.3.1", -] - -[[package]] -name = "redox_syscall" -version = "0.1.56" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" - -[[package]] -name = "regex" -version = "1.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322cf97724bea3ee221b78fe25ac9c46114ebb51747ad5babd51a2fc6a8235a8" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", - "thread_local", -] - -[[package]] -name = "regex-syntax" -version = "0.6.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1132f845907680735a84409c3bebc64d1364a5683ffbce899550cd09d5eaefc1" - -[[package]] -name = "rustc-demangle" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustc-hex" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" - -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -dependencies = [ - "semver", -] - -[[package]] -name = "schnorrkel" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eacd8381b3c37840c9c9f40472af529e49975bdcbc24f83c31059fd6539023d3" -dependencies = [ - "curve25519-dalek 1.2.3", - "failure", - "merlin", - "rand 0.6.5", - "rand_core 0.4.2", - "rand_os", - "sha2", - "subtle 2.2.2", - "zeroize 0.9.3", -] - -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" - -[[package]] -name = "serde" -version = "1.0.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "sha2" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27044adfd2e1f077f649f59deb9490d3941d674002f7d062870a60ebe9bd47a0" -dependencies = [ - "block-buffer", - "digest", - "fake-simd", - "opaque-debug", -] - -[[package]] -name = "smallvec" -version = "0.6.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" -dependencies = [ - "maybe-uninit", -] - -[[package]] -name = "smallvec" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c2fb2ec9bcd216a5b0d0ccf31ab17b5ed1d627960edff65bbe95d3ce221cefc" - -[[package]] -name = "sp-application-crypto" -version = "2.0.0-alpha.3" -dependencies = [ - "parity-scale-codec", - "serde", - "sp-core", - "sp-io", - "sp-std", -] - -[[package]] -name = "sp-arithmetic" -version = "2.0.0-alpha.3" -dependencies = [ - "integer-sqrt", - "num-traits", - "parity-scale-codec", - "serde", - "sp-debug-derive", - "sp-std", -] - -[[package]] -name = "sp-core" -version = "2.0.0-alpha.3" -dependencies = [ - "base58", - "blake2-rfc", - "byteorder", - "ed25519-dalek", - "hash-db", - "hash256-std-hasher", - "hex", - "impl-serde 0.3.0", - "lazy_static", - "libsecp256k1", - "log", - "num-traits", - "parity-scale-codec", - "parity-util-mem", - "parking_lot 0.10.0", - "primitive-types", - "rand 0.7.3", - "regex", - "rustc-hex", - "schnorrkel", - "serde", - "sha2", - "sp-debug-derive", - "sp-externalities", - "sp-runtime-interface", - "sp-std", - "sp-storage", - "substrate-bip39", - "tiny-bip39", - "tiny-keccak", - "twox-hash", - "wasmi", - "zeroize 1.1.0", -] - -[[package]] -name = "sp-debug-derive" -version = "2.0.0-alpha.3" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "sp-externalities" -version = "0.8.0-alpha.3" -dependencies = [ - "environmental", - "sp-std", - "sp-storage", -] - -[[package]] -name = "sp-inherents" -version = "2.0.0-alpha.3" -dependencies = [ - "derive_more", - "parity-scale-codec", - "parking_lot 0.10.0", - "sp-core", - "sp-std", -] - -[[package]] -name = "sp-io" -version = "2.0.0-alpha.3" -dependencies = [ - "hash-db", - "libsecp256k1", - "log", - "parity-scale-codec", - "sp-core", - "sp-externalities", - "sp-runtime-interface", - "sp-state-machine", - "sp-std", - "sp-trie", - "sp-wasm-interface", -] - -[[package]] -name = "sp-panic-handler" -version = "2.0.0-alpha.3" -dependencies = [ - "backtrace", - "log", -] - -[[package]] -name = "sp-npos-elections" -version = "2.0.0-alpha.3" -dependencies = [ - "parity-scale-codec", - "serde", - "sp-core", - "sp-npos-elections-compact", - "sp-runtime", - "sp-std", -] - -[[package]] -name = "sp-npos-elections-compact" -version = "2.0.0-rc3" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "sp-npos-elections-fuzzer" -version = "2.0.0" -dependencies = [ - "honggfuzz", - "rand 0.7.3", - "sp-npos-elections", -] - -[[package]] -name = "sp-runtime" -version = "2.0.0-alpha.3" -dependencies = [ - "hash256-std-hasher", - "impl-trait-for-tuples", - "log", - "parity-scale-codec", - "parity-util-mem", - "paste", - "rand 0.7.3", - "serde", - "sp-application-crypto", - "sp-arithmetic", - "sp-core", - "sp-inherents", - "sp-io", - "sp-std", -] - -[[package]] -name = "sp-runtime-interface" -version = "2.0.0-alpha.3" -dependencies = [ - "parity-scale-codec", - "primitive-types", - "sp-externalities", - "sp-runtime-interface-proc-macro", - "sp-std", - "sp-wasm-interface", - "static_assertions", -] - -[[package]] -name = "sp-runtime-interface-proc-macro" -version = "2.0.0-alpha.3" -dependencies = [ - "Inflector", - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "sp-state-machine" -version = "0.8.0-alpha.3" -dependencies = [ - "hash-db", - "log", - "num-traits", - "parity-scale-codec", - "parking_lot 0.10.0", - "rand 0.7.3", - "sp-core", - "sp-externalities", - "sp-panic-handler", - "sp-trie", - "trie-db", - "trie-root", -] - -[[package]] -name = "sp-std" -version = "2.0.0-alpha.3" - -[[package]] -name = "sp-storage" -version = "2.0.0-alpha.3" -dependencies = [ - "impl-serde 0.2.3", - "serde", - "sp-debug-derive", - "sp-std", -] - -[[package]] -name = "sp-trie" -version = "2.0.0-alpha.3" -dependencies = [ - "hash-db", - "memory-db", - "parity-scale-codec", - "sp-core", - "sp-std", - "trie-db", - "trie-root", -] - -[[package]] -name = "sp-wasm-interface" -version = "2.0.0-alpha.3" -dependencies = [ - "impl-trait-for-tuples", - "parity-scale-codec", - "sp-std", - "wasmi", -] - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "substrate-bip39" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be511be555a3633e71739a79e4ddff6a6aaa6579fa6114182a51d72c3eb93c5" -dependencies = [ - "hmac", - "pbkdf2", - "schnorrkel", - "sha2", -] - -[[package]] -name = "subtle" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" - -[[package]] -name = "subtle" -version = "2.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c65d530b10ccaeac294f349038a597e435b18fb456aadd0840a623f83b9e941" - -[[package]] -name = "syn" -version = "1.0.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "123bd9499cfb380418d509322d7a6d52e5315f064fe4b3ad18a53d6b92c07859" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "synstructure" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "unicode-xid", -] - -[[package]] -name = "thread_local" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "tiny-bip39" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6848cd8f566953ce1e8faeba12ee23cbdbb0437754792cd857d44628b5685e3" -dependencies = [ - "failure", - "hmac", - "once_cell", - "pbkdf2", - "rand 0.7.3", - "rustc-hash", - "sha2", - "unicode-normalization", -] - -[[package]] -name = "tiny-keccak" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2953ca5148619bc99695c1274cb54c5275bbb913c6adad87e72eaf8db9787f69" -dependencies = [ - "crunchy", -] - -[[package]] -name = "toml" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a" -dependencies = [ - "serde", -] - -[[package]] -name = "trie-db" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de9222c50cc325855621271157c973da27a0dcd26fa06f8edf81020bd2333df0" -dependencies = [ - "hash-db", - "hashbrown", - "log", - "rustc-hex", - "smallvec 1.3.0", -] - -[[package]] -name = "trie-root" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "652931506d2c1244d7217a70b99f56718a7b4161b37f04e7cd868072a99f68cd" -dependencies = [ - "hash-db", -] - -[[package]] -name = "twox-hash" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bfd5b7557925ce778ff9b9ef90e3ade34c524b5ff10e239c69a42d546d2af56" -dependencies = [ - "rand 0.7.3", -] - -[[package]] -name = "typenum" -version = "1.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" - -[[package]] -name = "uint" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e75a4cdd7b87b28840dba13c483b9a88ee6bbf16ba5c951ee1ecfcf723078e0d" -dependencies = [ - "byteorder", - "crunchy", - "rustc-hex", - "static_assertions", -] - -[[package]] -name = "unicode-normalization" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4" -dependencies = [ - "smallvec 1.3.0", -] - -[[package]] -name = "unicode-xid" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" - -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - -[[package]] -name = "wasmi" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf617d864d25af3587aa745529f7aaa541066c876d57e050c0d0c85c61c92aff" -dependencies = [ - "libc", - "memory_units", - "num-rational", - "num-traits", - "parity-wasm", - "wasmi-validation", -] - -[[package]] -name = "wasmi-validation" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea78c597064ba73596099281e2f4cfc019075122a65cdda3205af94f0b264d93" -dependencies = [ - "parity-wasm", -] - -[[package]] -name = "winapi" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "zeroize" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45af6a010d13e4cf5b54c94ba5a2b2eba5596b9e46bf5875612d332a1f2b3f86" - -[[package]] -name = "zeroize" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cbac2ed2ba24cc90f5e06485ac8c7c1e5449fe8911aef4d8877218af021a5b8" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de251eec69fc7c1bc3923403d18ececb929380e016afe103da75f396704f8ca2" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] From adc95f06936dbdec9479958b13255fcad033264f Mon Sep 17 00:00:00 2001 From: Koute Date: Fri, 18 Feb 2022 21:35:43 +0900 Subject: [PATCH 512/695] Further reduce the CPU overhead of networking metrics (#10875) * Simplify `num_connected_peers` * Track requested peer counts * Revert "Track requested peer counts" This reverts commit 9f1c8704353df6afc17ed7e9f4ab8d8e29466ae4. * Remove `substrate_sub_libp2p_peerset_num_requested` metric * Remove two unused functions that I forgot to get rid of in previous commit --- client/network/src/protocol.rs | 8 +------ .../src/protocol/notifications/behaviour.rs | 21 ------------------- client/network/src/service.rs | 4 ---- client/network/src/service/metrics.rs | 5 ----- 4 files changed, 1 insertion(+), 37 deletions(-) diff --git a/client/network/src/protocol.rs b/client/network/src/protocol.rs index b39d0d1b8428..eb634ca5be76 100644 --- a/client/network/src/protocol.rs +++ b/client/network/src/protocol.rs @@ -465,12 +465,6 @@ impl Protocol { self.behaviour.open_peers() } - /// Returns the list of all the peers that the peerset currently requests us to be connected - /// to on the default set. - pub fn requested_peers(&self) -> impl Iterator { - self.behaviour.requested_peers(HARDCODED_PEERSETS_SYNC) - } - /// Returns the number of discovered nodes that we keep in memory. pub fn num_discovered_peers(&self) -> usize { self.behaviour.num_discovered_peers() @@ -496,7 +490,7 @@ impl Protocol { /// Returns the number of peers we're connected to. pub fn num_connected_peers(&self) -> usize { - self.peers.values().count() + self.peers.len() } /// Returns the number of peers we're connected to and that are being queried. diff --git a/client/network/src/protocol/notifications/behaviour.rs b/client/network/src/protocol/notifications/behaviour.rs index 97047201c308..b47216473970 100644 --- a/client/network/src/protocol/notifications/behaviour.rs +++ b/client/network/src/protocol/notifications/behaviour.rs @@ -251,16 +251,6 @@ impl PeerState { _ => None, } } - - /// True if that node has been requested by the PSM. - fn is_requested(&self) -> bool { - matches!( - self, - Self::PendingRequest { .. } | - Self::Requested | Self::DisabledPendingEnable { .. } | - Self::Enabled { .. } - ) - } } /// State of the handler of a single connection visible from this state machine. @@ -560,17 +550,6 @@ impl Notifications { } } - /// Returns the list of all the peers that the peerset currently requests us to be connected to. - pub fn requested_peers<'a>( - &'a self, - set_id: sc_peerset::SetId, - ) -> impl Iterator + 'a { - self.peers - .iter() - .filter(move |((_, set), state)| *set == set_id && state.is_requested()) - .map(|((id, _), _)| id) - } - /// Returns the list of reserved peers. pub fn reserved_peers<'a>( &'a self, diff --git a/client/network/src/service.rs b/client/network/src/service.rs index b6a1d3c88e7f..a02aa982318a 100644 --- a/client/network/src/service.rs +++ b/client/network/src/service.rs @@ -2108,10 +2108,6 @@ impl Future for NetworkWorker { .peerset_num_discovered .set(this.network_service.behaviour_mut().user_protocol().num_discovered_peers() as u64); - metrics.peerset_num_requested.set( - this.network_service.behaviour_mut().user_protocol().requested_peers().count() - as u64, - ); metrics.pending_connections.set( Swarm::network_info(&this.network_service).connection_counters().num_pending() as u64, diff --git a/client/network/src/service/metrics.rs b/client/network/src/service/metrics.rs index bf94287d1291..ad30b1b093ff 100644 --- a/client/network/src/service/metrics.rs +++ b/client/network/src/service/metrics.rs @@ -69,7 +69,6 @@ pub struct Metrics { pub notifications_streams_closed_total: CounterVec, pub notifications_streams_opened_total: CounterVec, pub peerset_num_discovered: Gauge, - pub peerset_num_requested: Gauge, pub pending_connections: Gauge, pub pending_connections_errors_total: CounterVec, pub requests_in_failure_total: CounterVec, @@ -204,10 +203,6 @@ impl Metrics { "substrate_sub_libp2p_peerset_num_discovered", "Number of nodes stored in the peerset manager", )?, registry)?, - peerset_num_requested: prometheus::register(Gauge::new( - "substrate_sub_libp2p_peerset_num_requested", - "Number of nodes that the peerset manager wants us to be connected to", - )?, registry)?, pending_connections: prometheus::register(Gauge::new( "substrate_sub_libp2p_pending_connections", "Number of connections in the process of being established", From f72fe056844a375f16449555d6e20e57dcd16aa6 Mon Sep 17 00:00:00 2001 From: Gavin Wood Date: Sat, 19 Feb 2022 12:02:47 +0100 Subject: [PATCH 513/695] Introduce `BoundedVec::iter_mut` (#10884) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Introduce iters into BoundedVec * Fix * Remove unneeded funcs * Update frame/support/src/storage/bounded_vec.rs * Update frame/support/src/storage/bounded_vec.rs Co-authored-by: Bastian Köcher --- frame/support/src/storage/bounded_vec.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/frame/support/src/storage/bounded_vec.rs b/frame/support/src/storage/bounded_vec.rs index 9298a5d98b00..86aa4d405cab 100644 --- a/frame/support/src/storage/bounded_vec.rs +++ b/frame/support/src/storage/bounded_vec.rs @@ -159,6 +159,11 @@ impl BoundedVec { pub fn pop(&mut self) -> Option { self.0.pop() } + + /// Exactly the same semantics as [`slice::iter_mut`]. + pub fn iter_mut(&mut self) -> core::slice::IterMut<'_, T> { + self.0.iter_mut() + } } impl> From> for Vec { From e01c36244a91aea715bd45c05e3361fe24fd071d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Sun, 20 Feb 2022 02:49:49 +0100 Subject: [PATCH 514/695] Slots: Log total proposing duration as milliseconds (#10886) Parachains have currently a total proposing time of 500ms, so it this currently always prints `0`. While actually the value is not `0` ;) --- client/consensus/slots/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/consensus/slots/src/lib.rs b/client/consensus/slots/src/lib.rs index fc635e918405..094d065a1c07 100644 --- a/client/consensus/slots/src/lib.rs +++ b/client/consensus/slots/src/lib.rs @@ -654,10 +654,10 @@ pub fn proposing_remaining_duration( debug!( target: log_target, - "No block for {} slots. Applying {} lenience, total proposing duration: {}", + "No block for {} slots. Applying {} lenience, total proposing duration: {}ms", slot_info.slot.saturating_sub(parent_slot + 1), slot_lenience_type.as_str(), - lenient_proposing_duration.as_secs(), + lenient_proposing_duration.as_millis(), ); lenient_proposing_duration From 917fe4919c70cb022a9c90eb6415cf85cbc67f7b Mon Sep 17 00:00:00 2001 From: Zeke Mostov Date: Sun, 20 Feb 2022 16:50:25 -0800 Subject: [PATCH 515/695] staking: Clarify reward calc docs (#10890) --- frame/staking/src/lib.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 17af4829c0ea..3738c87dd5b3 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -221,16 +221,16 @@ //! //! The validator and its nominator split their reward as following: //! -//! The validator can declare an amount, named -//! [`commission`](ValidatorPrefs::commission), that does not get shared -//! with the nominators at each reward payout through its -//! [`ValidatorPrefs`]. This value gets deducted from the total reward -//! that is paid to the validator and its nominators. The remaining portion is split among the -//! validator and all of the nominators that nominated the validator, proportional to the value -//! staked behind this validator (_i.e._ dividing the -//! [`own`](Exposure::own) or -//! [`others`](Exposure::others) by -//! [`total`](Exposure::total) in [`Exposure`]). +//! The validator can declare an amount, named [`commission`](ValidatorPrefs::commission), that does +//! not get shared with the nominators at each reward payout through its [`ValidatorPrefs`]. This +//! value gets deducted from the total reward that is paid to the validator and its nominators. The +//! remaining portion is split pro rata among the validator and the top +//! [`Config::MaxNominatorRewardedPerValidator`] nominators that nominated the validator, +//! proportional to the value staked behind the validator (_i.e._ dividing the +//! [`own`](Exposure::own) or [`others`](Exposure::others) by [`total`](Exposure::total) in +//! [`Exposure`]). Note that the pro rata division of rewards uses the total exposure behind the +//! validator, *not* just the exposure of the validator and the top +//! [`Config::MaxNominatorRewardedPerValidator`] nominators. //! //! All entities who receive a reward have the option to choose their reward destination through the //! [`Payee`] storage item (see From 1db34ffb34a3d5d0fdf823661542b2c4c0aa8501 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Mon, 21 Feb 2022 13:08:24 +0100 Subject: [PATCH 516/695] tracing: Adds `init_for_tests` (#10893) This function is useful for tests. It will enable `TRACE` logging and also uses the libtest aware writer. --- primitives/tracing/src/lib.rs | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/primitives/tracing/src/lib.rs b/primitives/tracing/src/lib.rs index 4cabbbaba6ec..1efae226a546 100644 --- a/primitives/tracing/src/lib.rs +++ b/primitives/tracing/src/lib.rs @@ -108,6 +108,7 @@ pub use crate::types::{WASM_NAME_KEY, WASM_TARGET_KEY, WASM_TRACE_IDENTIFIER}; mod types; /// Try to init a simple tracing subscriber with log compatibility layer. +/// /// Ignores any error. Useful for testing. #[cfg(feature = "std")] pub fn try_init_simple() { @@ -117,6 +118,22 @@ pub fn try_init_simple() { .try_init(); } +/// Init a tracing subscriber for logging in tests. +/// +/// Be aware that this enables `TRACE` by default. It also ignores any error +/// while setting up the logger. +/// +/// The logs are not shown by default, logs are only shown when the test fails +/// or if [`nocapture`](https://doc.rust-lang.org/cargo/commands/cargo-test.html#display-options) +/// is being used. +#[cfg(feature = "std")] +pub fn init_for_tests() { + let _ = tracing_subscriber::fmt() + .with_max_level(tracing::Level::TRACE) + .with_test_writer() + .try_init(); +} + /// Runs given code within a tracing span, measuring it's execution time. /// /// If tracing is not enabled, the code is still executed. Pass in level and name or @@ -126,20 +143,20 @@ pub fn try_init_simple() { /// /// ``` /// sp_tracing::within_span! { -/// sp_tracing::Level::TRACE, +/// sp_tracing::Level::TRACE, /// "test-span"; /// 1 + 1; /// // some other complex code /// } /// /// sp_tracing::within_span! { -/// sp_tracing::span!(sp_tracing::Level::WARN, "warn-span", you_can_pass="any params"); +/// sp_tracing::span!(sp_tracing::Level::WARN, "warn-span", you_can_pass="any params"); /// 1 + 1; /// // some other complex code /// } /// /// sp_tracing::within_span! { -/// sp_tracing::debug_span!("debug-span", you_can_pass="any params"); +/// sp_tracing::debug_span!("debug-span", you_can_pass="any params"); /// 1 + 1; /// // some other complex code /// } From b16a721f271df9350e0dd5aca7e4cb1b4f1574d8 Mon Sep 17 00:00:00 2001 From: Niklas Adolfsson Date: Tue, 22 Feb 2022 09:20:29 +0100 Subject: [PATCH 517/695] make submissions pub (#10899) --- frame/election-provider-multi-phase/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frame/election-provider-multi-phase/src/lib.rs b/frame/election-provider-multi-phase/src/lib.rs index 58df7d5a9d75..9413984f80db 100644 --- a/frame/election-provider-multi-phase/src/lib.rs +++ b/frame/election-provider-multi-phase/src/lib.rs @@ -1233,7 +1233,7 @@ pub mod pallet { /// capacity, it will simply saturate. We can't just iterate over `SignedSubmissionsMap`, /// because iteration is slow. Instead, we store the value here. #[pallet::storage] - pub(crate) type SignedSubmissionNextIndex = StorageValue<_, u32, ValueQuery>; + pub type SignedSubmissionNextIndex = StorageValue<_, u32, ValueQuery>; /// A sorted, bounded set of `(score, index)`, where each `index` points to a value in /// `SignedSubmissions`. @@ -1242,7 +1242,7 @@ pub mod pallet { /// can be quite large, so we're willing to pay the cost of multiple database accesses to access /// them one at a time instead of reading and decoding all of them at once. #[pallet::storage] - pub(crate) type SignedSubmissionIndices = + pub type SignedSubmissionIndices = StorageValue<_, SubmissionIndicesOf, ValueQuery>; /// Unchecked, signed solutions. @@ -1253,7 +1253,7 @@ pub mod pallet { /// Twox note: the key of the map is an auto-incrementing index which users cannot inspect or /// affect; we shouldn't need a cryptographically secure hasher. #[pallet::storage] - pub(crate) type SignedSubmissionsMap = + pub type SignedSubmissionsMap = StorageMap<_, Twox64Concat, u32, SignedSubmissionOf, OptionQuery>; // `SignedSubmissions` items end here. From b46702edbb8c65eb2e3269f8e5cbea4671d1844d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Tue, 22 Feb 2022 10:10:38 +0100 Subject: [PATCH 518/695] contracts: Allow stack height metering to be disabled (#10877) * Allow stack height metering to be disabled * cargo run --quiet --profile=production --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_contracts --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/contracts/src/weights.rs --template=./.maintain/frame-weight-template.hbs * cargo run --quiet --profile=production --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_contracts --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/contracts/src/weights.rs --template=./.maintain/frame-weight-template.hbs Co-authored-by: Parity Bot --- frame/contracts/src/benchmarking/code.rs | 7 +- frame/contracts/src/benchmarking/mod.rs | 6 +- frame/contracts/src/schedule.rs | 12 +- frame/contracts/src/tests.rs | 8 +- frame/contracts/src/wasm/prepare.rs | 9 +- frame/contracts/src/weights.rs | 1158 +++++++++++----------- 6 files changed, 609 insertions(+), 591 deletions(-) diff --git a/frame/contracts/src/benchmarking/code.rs b/frame/contracts/src/benchmarking/code.rs index 4d42349f82a1..f9d71fde6588 100644 --- a/frame/contracts/src/benchmarking/code.rs +++ b/frame/contracts/src/benchmarking/code.rs @@ -566,6 +566,9 @@ fn inject_gas_metering(module: Module) -> Module { } fn inject_stack_metering(module: Module) -> Module { - let height = T::Schedule::get().limits.stack_height; - wasm_instrument::inject_stack_limiter(module, height).unwrap() + if let Some(height) = T::Schedule::get().limits.stack_height { + wasm_instrument::inject_stack_limiter(module, height).unwrap() + } else { + module + } } diff --git a/frame/contracts/src/benchmarking/mod.rs b/frame/contracts/src/benchmarking/mod.rs index 827c729e1615..f5200eef567b 100644 --- a/frame/contracts/src/benchmarking/mod.rs +++ b/frame/contracts/src/benchmarking/mod.rs @@ -2250,7 +2250,7 @@ benchmarks! { // w_local_get = w_bench - 1 * w_param instr_local_get { let r in 0 .. INSTR_BENCHMARK_BATCHES; - let max_locals = T::Schedule::get().limits.stack_height; + let max_locals = T::Schedule::get().limits.stack_height.unwrap_or(512); let mut call_body = body::repeated_dyn(r * INSTR_BENCHMARK_BATCH_SIZE, vec![ RandomGetLocal(0, max_locals), Regular(Instruction::Drop), @@ -2267,7 +2267,7 @@ benchmarks! { // w_local_set = w_bench - 1 * w_param instr_local_set { let r in 0 .. INSTR_BENCHMARK_BATCHES; - let max_locals = T::Schedule::get().limits.stack_height; + let max_locals = T::Schedule::get().limits.stack_height.unwrap_or(512); let mut call_body = body::repeated_dyn(r * INSTR_BENCHMARK_BATCH_SIZE, vec![ RandomI64Repeated(1), RandomSetLocal(0, max_locals), @@ -2284,7 +2284,7 @@ benchmarks! { // w_local_tee = w_bench - 2 * w_param instr_local_tee { let r in 0 .. INSTR_BENCHMARK_BATCHES; - let max_locals = T::Schedule::get().limits.stack_height; + let max_locals = T::Schedule::get().limits.stack_height.unwrap_or(512); let mut call_body = body::repeated_dyn(r * INSTR_BENCHMARK_BATCH_SIZE, vec![ RandomI64Repeated(1), RandomTeeLocal(0, max_locals), diff --git a/frame/contracts/src/schedule.rs b/frame/contracts/src/schedule.rs index d6bdf85a4d68..8535166a6ac5 100644 --- a/frame/contracts/src/schedule.rs +++ b/frame/contracts/src/schedule.rs @@ -104,7 +104,13 @@ pub struct Limits { /// See to find out /// how the stack frame cost is calculated. Each element can be of one of the /// wasm value types. This means the maximum size per element is 64bit. - pub stack_height: u32, + /// + /// # Note + /// + /// It is safe to disable (pass `None`) the `stack_height` when the execution engine + /// is part of the runtime and hence there can be no indeterminism between different + /// client resident execution engines. + pub stack_height: Option, /// Maximum number of globals a module is allowed to declare. /// @@ -496,8 +502,8 @@ impl Default for Limits { fn default() -> Self { Self { event_topics: 4, - // 512 * sizeof(i64) will give us a 4k stack. - stack_height: 512, + // No stack limit required because we use a runtime resident execution engine. + stack_height: None, globals: 256, parameters: 128, memory_pages: 16, diff --git a/frame/contracts/src/tests.rs b/frame/contracts/src/tests.rs index 9ea23e974b21..cdcf41704347 100644 --- a/frame/contracts/src/tests.rs +++ b/frame/contracts/src/tests.rs @@ -239,7 +239,13 @@ parameter_types! { pub const MaxValueSize: u32 = 16_384; pub const DeletionWeightLimit: Weight = 500_000_000_000; pub const MaxCodeSize: u32 = 2 * 1024; - pub MySchedule: Schedule = >::default(); + pub MySchedule: Schedule = { + let mut schedule = >::default(); + // We want stack height to be always enabled for tests so that this + // instrumentation path is always tested implicitly. + schedule.limits.stack_height = Some(512); + schedule + }; pub const TransactionByteFee: u64 = 0; pub static DepositPerByte: BalanceOf = 1; pub const DepositPerItem: BalanceOf = 2; diff --git a/frame/contracts/src/wasm/prepare.rs b/frame/contracts/src/wasm/prepare.rs index 70c15cb8c4e6..4571d752a80c 100644 --- a/frame/contracts/src/wasm/prepare.rs +++ b/frame/contracts/src/wasm/prepare.rs @@ -191,10 +191,13 @@ impl<'a, T: Config> ContractModule<'a, T> { } fn inject_stack_height_metering(self) -> Result { - let contract_module = - wasm_instrument::inject_stack_limiter(self.module, self.schedule.limits.stack_height) + if let Some(limit) = self.schedule.limits.stack_height { + let contract_module = wasm_instrument::inject_stack_limiter(self.module, limit) .map_err(|_| "stack height instrumentation failed")?; - Ok(ContractModule { module: contract_module, schedule: self.schedule }) + Ok(ContractModule { module: contract_module, schedule: self.schedule }) + } else { + Ok(ContractModule { module: self.module, schedule: self.schedule }) + } } /// Check that the module has required exported functions. For now diff --git a/frame/contracts/src/weights.rs b/frame/contracts/src/weights.rs index fd32c247ba72..7d73a3a1cecc 100644 --- a/frame/contracts/src/weights.rs +++ b/frame/contracts/src/weights.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_contracts //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-02-16, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-02-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -160,32 +160,32 @@ pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize() -> Weight { - (1_588_000 as Weight) + (1_512_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn on_initialize_per_trie_key(k: u32, ) -> Weight { - (6_994_000 as Weight) + (8_089_000 as Weight) // Standard Error: 0 - .saturating_add((743_000 as Weight).saturating_mul(k as Weight)) + .saturating_add((741_000 as Weight).saturating_mul(k as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) } // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize_per_queue_item(q: u32, ) -> Weight { - (2_831_000 as Weight) - // Standard Error: 3_000 - .saturating_add((2_232_000 as Weight).saturating_mul(q as Weight)) + (0 as Weight) + // Standard Error: 5_000 + .saturating_add((2_287_000 as Weight).saturating_mul(q as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Contracts PristineCode (r:1 w:0) // Storage: Contracts CodeStorage (r:0 w:1) fn reinstrument(c: u32, ) -> Weight { - (17_839_000 as Weight) + (15_212_000 as Weight) // Standard Error: 0 - .saturating_add((64_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((51_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -194,9 +194,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call_with_code_per_byte(c: u32, ) -> Weight { - (222_400_000 as Weight) + (218_406_000 as Weight) // Standard Error: 0 - .saturating_add((56_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((55_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -208,9 +208,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn instantiate_with_code(c: u32, s: u32, ) -> Weight { - (283_144_000 as Weight) + (265_773_000 as Weight) // Standard Error: 0 - .saturating_add((140_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((127_000 as Weight).saturating_mul(c as Weight)) // Standard Error: 0 .saturating_add((2_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) @@ -223,7 +223,7 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn instantiate(s: u32, ) -> Weight { - (171_794_000 as Weight) + (173_852_000 as Weight) // Standard Error: 0 .saturating_add((2_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) @@ -234,7 +234,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call() -> Weight { - (140_234_000 as Weight) + (140_088_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -242,9 +242,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn upload_code(c: u32, ) -> Weight { - (49_467_000 as Weight) + (44_290_000 as Weight) // Standard Error: 0 - .saturating_add((66_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((51_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -252,7 +252,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:0 w:1) // Storage: Contracts PristineCode (r:0 w:1) fn remove_code() -> Weight { - (24_915_000 as Weight) + (24_364_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -261,9 +261,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_caller(r: u32, ) -> Weight { - (218_957_000 as Weight) - // Standard Error: 114_000 - .saturating_add((49_881_000 as Weight).saturating_mul(r as Weight)) + (219_617_000 as Weight) + // Standard Error: 119_000 + .saturating_add((50_409_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -272,9 +272,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_is_contract(r: u32, ) -> Weight { - (76_490_000 as Weight) - // Standard Error: 856_000 - .saturating_add((375_305_000 as Weight).saturating_mul(r as Weight)) + (102_073_000 as Weight) + // Standard Error: 843_000 + .saturating_add((369_025_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -284,9 +284,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_caller_is_origin(r: u32, ) -> Weight { - (213_485_000 as Weight) - // Standard Error: 76_000 - .saturating_add((22_020_000 as Weight).saturating_mul(r as Weight)) + (213_550_000 as Weight) + // Standard Error: 63_000 + .saturating_add((21_519_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -295,9 +295,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_address(r: u32, ) -> Weight { - (218_468_000 as Weight) - // Standard Error: 108_000 - .saturating_add((49_457_000 as Weight).saturating_mul(r as Weight)) + (220_649_000 as Weight) + // Standard Error: 95_000 + .saturating_add((50_197_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -306,9 +306,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas_left(r: u32, ) -> Weight { - (218_950_000 as Weight) + (218_190_000 as Weight) // Standard Error: 99_000 - .saturating_add((48_859_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((49_817_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -317,9 +317,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_balance(r: u32, ) -> Weight { - (226_714_000 as Weight) - // Standard Error: 111_000 - .saturating_add((141_924_000 as Weight).saturating_mul(r as Weight)) + (223_133_000 as Weight) + // Standard Error: 188_000 + .saturating_add((142_288_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -328,9 +328,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_value_transferred(r: u32, ) -> Weight { - (216_673_000 as Weight) - // Standard Error: 90_000 - .saturating_add((49_367_000 as Weight).saturating_mul(r as Weight)) + (216_612_000 as Weight) + // Standard Error: 103_000 + .saturating_add((49_956_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -339,9 +339,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_minimum_balance(r: u32, ) -> Weight { - (215_859_000 as Weight) - // Standard Error: 104_000 - .saturating_add((49_334_000 as Weight).saturating_mul(r as Weight)) + (218_349_000 as Weight) + // Standard Error: 93_000 + .saturating_add((49_656_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -350,9 +350,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_block_number(r: u32, ) -> Weight { - (216_419_000 as Weight) - // Standard Error: 109_000 - .saturating_add((49_417_000 as Weight).saturating_mul(r as Weight)) + (213_151_000 as Weight) + // Standard Error: 110_000 + .saturating_add((50_099_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -361,9 +361,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_now(r: u32, ) -> Weight { - (218_799_000 as Weight) - // Standard Error: 108_000 - .saturating_add((48_631_000 as Weight).saturating_mul(r as Weight)) + (216_816_000 as Weight) + // Standard Error: 95_000 + .saturating_add((49_724_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -373,9 +373,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0) fn seal_weight_to_fee(r: u32, ) -> Weight { - (215_968_000 as Weight) - // Standard Error: 147_000 - .saturating_add((122_978_000 as Weight).saturating_mul(r as Weight)) + (223_053_000 as Weight) + // Standard Error: 148_000 + .saturating_add((124_240_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -384,9 +384,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas(r: u32, ) -> Weight { - (127_183_000 as Weight) - // Standard Error: 35_000 - .saturating_add((24_523_000 as Weight).saturating_mul(r as Weight)) + (127_253_000 as Weight) + // Standard Error: 27_000 + .saturating_add((25_608_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -395,9 +395,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input(r: u32, ) -> Weight { - (217_535_000 as Weight) - // Standard Error: 91_000 - .saturating_add((48_400_000 as Weight).saturating_mul(r as Weight)) + (218_057_000 as Weight) + // Standard Error: 98_000 + .saturating_add((49_061_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -406,9 +406,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input_per_kb(n: u32, ) -> Weight { - (297_539_000 as Weight) - // Standard Error: 5_000 - .saturating_add((11_870_000 as Weight).saturating_mul(n as Weight)) + (293_563_000 as Weight) + // Standard Error: 3_000 + .saturating_add((11_877_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -417,9 +417,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return(r: u32, ) -> Weight { - (211_807_000 as Weight) - // Standard Error: 160_000 - .saturating_add((1_717_000 as Weight).saturating_mul(r as Weight)) + (211_511_000 as Weight) + // Standard Error: 70_000 + .saturating_add((2_085_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -428,9 +428,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return_per_kb(n: u32, ) -> Weight { - (213_139_000 as Weight) + (213_876_000 as Weight) // Standard Error: 0 - .saturating_add((197_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((193_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -441,9 +441,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts DeletionQueue (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_terminate(r: u32, ) -> Weight { - (215_292_000 as Weight) - // Standard Error: 390_000 - .saturating_add((52_831_000 as Weight).saturating_mul(r as Weight)) + (214_736_000 as Weight) + // Standard Error: 206_000 + .saturating_add((53_637_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((4 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -455,9 +455,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) fn seal_random(r: u32, ) -> Weight { - (215_802_000 as Weight) - // Standard Error: 132_000 - .saturating_add((159_065_000 as Weight).saturating_mul(r as Weight)) + (222_037_000 as Weight) + // Standard Error: 191_000 + .saturating_add((160_114_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -466,9 +466,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_deposit_event(r: u32, ) -> Weight { - (225_069_000 as Weight) - // Standard Error: 201_000 - .saturating_add((292_145_000 as Weight).saturating_mul(r as Weight)) + (219_211_000 as Weight) + // Standard Error: 239_000 + .saturating_add((296_722_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -478,11 +478,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: System EventTopics (r:100 w:100) fn seal_deposit_event_per_topic_and_kb(t: u32, n: u32, ) -> Weight { - (519_617_000 as Weight) - // Standard Error: 1_751_000 - .saturating_add((290_832_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 345_000 - .saturating_add((82_584_000 as Weight).saturating_mul(n as Weight)) + (519_643_000 as Weight) + // Standard Error: 1_842_000 + .saturating_add((300_853_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 363_000 + .saturating_add((82_577_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(t as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -493,17 +493,17 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_debug_message(r: u32, ) -> Weight { - (132_245_000 as Weight) - // Standard Error: 75_000 - .saturating_add((41_274_000 as Weight).saturating_mul(r as Weight)) + (132_710_000 as Weight) + // Standard Error: 77_000 + .saturating_add((41_623_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage(r: u32, ) -> Weight { - (48_288_000 as Weight) - // Standard Error: 1_024_000 - .saturating_add((408_264_000 as Weight).saturating_mul(r as Weight)) + (40_644_000 as Weight) + // Standard Error: 1_072_000 + .saturating_add((412_308_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -511,25 +511,25 @@ impl WeightInfo for SubstrateWeight { } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage_per_new_kb(n: u32, ) -> Weight { - (607_246_000 as Weight) - // Standard Error: 252_000 - .saturating_add((28_722_000 as Weight).saturating_mul(n as Weight)) + (609_052_000 as Weight) + // Standard Error: 258_000 + .saturating_add((28_633_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage_per_old_kb(n: u32, ) -> Weight { - (623_983_000 as Weight) - // Standard Error: 305_000 - .saturating_add((11_374_000 as Weight).saturating_mul(n as Weight)) + (629_665_000 as Weight) + // Standard Error: 300_000 + .saturating_add((10_947_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage(r: u32, ) -> Weight { - (91_727_000 as Weight) - // Standard Error: 837_000 - .saturating_add((383_577_000 as Weight).saturating_mul(r as Weight)) + (91_519_000 as Weight) + // Standard Error: 889_000 + .saturating_add((386_498_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -537,51 +537,51 @@ impl WeightInfo for SubstrateWeight { } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage_per_kb(n: u32, ) -> Weight { - (604_749_000 as Weight) - // Standard Error: 251_000 - .saturating_add((11_086_000 as Weight).saturating_mul(n as Weight)) + (612_224_000 as Weight) + // Standard Error: 269_000 + .saturating_add((10_709_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage(r: u32, ) -> Weight { - (107_805_000 as Weight) - // Standard Error: 722_000 - .saturating_add((326_494_000 as Weight).saturating_mul(r as Weight)) + (112_236_000 as Weight) + // Standard Error: 624_000 + .saturating_add((327_655_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage_per_kb(n: u32, ) -> Weight { - (564_604_000 as Weight) - // Standard Error: 360_000 - .saturating_add((65_184_000 as Weight).saturating_mul(n as Weight)) + (567_711_000 as Weight) + // Standard Error: 387_000 + .saturating_add((63_984_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(104 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_contains_storage(r: u32, ) -> Weight { - (122_105_000 as Weight) - // Standard Error: 560_000 - .saturating_add((291_458_000 as Weight).saturating_mul(r as Weight)) + (109_996_000 as Weight) + // Standard Error: 681_000 + .saturating_add((298_317_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_contains_storage_per_kb(n: u32, ) -> Weight { - (512_580_000 as Weight) - // Standard Error: 245_000 - .saturating_add((10_171_000 as Weight).saturating_mul(n as Weight)) + (518_342_000 as Weight) + // Standard Error: 251_000 + .saturating_add((9_666_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(104 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage(r: u32, ) -> Weight { - (81_220_000 as Weight) - // Standard Error: 933_000 - .saturating_add((418_532_000 as Weight).saturating_mul(r as Weight)) + (75_974_000 as Weight) + // Standard Error: 1_000_000 + .saturating_add((417_954_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -589,9 +589,9 @@ impl WeightInfo for SubstrateWeight { } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage_per_kb(n: u32, ) -> Weight { - (652_330_000 as Weight) - // Standard Error: 357_000 - .saturating_add((65_711_000 as Weight).saturating_mul(n as Weight)) + (653_188_000 as Weight) + // Standard Error: 333_000 + .saturating_add((64_810_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().writes(103 as Weight)) } @@ -600,9 +600,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_transfer(r: u32, ) -> Weight { - (126_544_000 as Weight) - // Standard Error: 1_198_000 - .saturating_add((1_796_593_000 as Weight).saturating_mul(r as Weight)) + (127_056_000 as Weight) + // Standard Error: 1_106_000 + .saturating_add((1_784_183_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -614,8 +614,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) fn seal_call(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 3_033_000 - .saturating_add((19_788_005_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 2_621_000 + .saturating_add((19_757_765_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -627,8 +627,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) fn seal_delegate_call(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 6_663_000 - .saturating_add((19_835_985_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 6_286_000 + .saturating_add((19_798_229_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads((99 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -637,11 +637,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:2 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_call_per_transfer_clone_kb(t: u32, c: u32, ) -> Weight { - (10_957_494_000 as Weight) - // Standard Error: 13_908_000 - .saturating_add((1_622_630_000 as Weight).saturating_mul(t as Weight)) + (10_922_130_000 as Weight) + // Standard Error: 15_556_000 + .saturating_add((1_672_276_000 as Weight).saturating_mul(t as Weight)) // Standard Error: 6_000 - .saturating_add((11_960_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((11_984_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().reads((101 as Weight).saturating_mul(t as Weight))) .saturating_add(T::DbWeight::get().writes(101 as Weight)) @@ -655,8 +655,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts OwnerInfoOf (r:100 w:100) fn seal_instantiate(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 48_191_000 - .saturating_add((27_587_375_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 46_147_000 + .saturating_add((27_589_519_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().reads((400 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -669,11 +669,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts AccountCounter (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_instantiate_per_transfer_salt_kb(t: u32, s: u32, ) -> Weight { - (14_504_226_000 as Weight) - // Standard Error: 66_350_000 - .saturating_add((912_874_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 31_000 - .saturating_add((157_415_000 as Weight).saturating_mul(s as Weight)) + (14_790_752_000 as Weight) + // Standard Error: 37_838_000 + .saturating_add((714_016_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 17_000 + .saturating_add((155_605_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(207 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(t as Weight))) .saturating_add(T::DbWeight::get().writes(205 as Weight)) @@ -684,9 +684,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256(r: u32, ) -> Weight { - (216_771_000 as Weight) - // Standard Error: 127_000 - .saturating_add((79_994_000 as Weight).saturating_mul(r as Weight)) + (216_547_000 as Weight) + // Standard Error: 126_000 + .saturating_add((81_132_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -695,9 +695,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256_per_kb(n: u32, ) -> Weight { - (376_960_000 as Weight) - // Standard Error: 24_000 - .saturating_add((465_507_000 as Weight).saturating_mul(n as Weight)) + (459_912_000 as Weight) + // Standard Error: 27_000 + .saturating_add((464_750_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -706,9 +706,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256(r: u32, ) -> Weight { - (212_554_000 as Weight) - // Standard Error: 129_000 - .saturating_add((92_073_000 as Weight).saturating_mul(r as Weight)) + (212_653_000 as Weight) + // Standard Error: 147_000 + .saturating_add((93_380_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -717,9 +717,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256_per_kb(n: u32, ) -> Weight { - (298_638_000 as Weight) - // Standard Error: 23_000 - .saturating_add((307_231_000 as Weight).saturating_mul(n as Weight)) + (324_536_000 as Weight) + // Standard Error: 20_000 + .saturating_add((306_160_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -728,9 +728,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256(r: u32, ) -> Weight { - (216_274_000 as Weight) - // Standard Error: 100_000 - .saturating_add((64_205_000 as Weight).saturating_mul(r as Weight)) + (218_574_000 as Weight) + // Standard Error: 123_000 + .saturating_add((65_035_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -739,9 +739,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256_per_kb(n: u32, ) -> Weight { - (294_478_000 as Weight) - // Standard Error: 18_000 - .saturating_add((120_405_000 as Weight).saturating_mul(n as Weight)) + (345_804_000 as Weight) + // Standard Error: 14_000 + .saturating_add((118_896_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -750,9 +750,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128(r: u32, ) -> Weight { - (215_874_000 as Weight) - // Standard Error: 115_000 - .saturating_add((63_402_000 as Weight).saturating_mul(r as Weight)) + (215_898_000 as Weight) + // Standard Error: 108_000 + .saturating_add((64_332_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -761,9 +761,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128_per_kb(n: u32, ) -> Weight { - (288_361_000 as Weight) - // Standard Error: 15_000 - .saturating_add((120_795_000 as Weight).saturating_mul(n as Weight)) + (351_569_000 as Weight) + // Standard Error: 18_000 + .saturating_add((118_896_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -772,9 +772,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_ecdsa_recover(r: u32, ) -> Weight { - (142_940_000 as Weight) - // Standard Error: 1_317_000 - .saturating_add((15_385_437_000 as Weight).saturating_mul(r as Weight)) + (272_893_000 as Weight) + // Standard Error: 1_438_000 + .saturating_add((15_412_877_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -785,265 +785,265 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts OwnerInfoOf (r:36 w:36) fn seal_set_code_hash(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 1_981_000 - .saturating_add((943_500_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 2_132_000 + .saturating_add((937_623_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads((99 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes((99 as Weight).saturating_mul(r as Weight))) } fn instr_i64const(r: u32, ) -> Weight { - (74_672_000 as Weight) + (74_268_000 as Weight) // Standard Error: 1_000 .saturating_add((595_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64load(r: u32, ) -> Weight { - (74_346_000 as Weight) + (74_515_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_324_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_300_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64store(r: u32, ) -> Weight { - (74_149_000 as Weight) + (74_217_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_438_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_411_000 as Weight).saturating_mul(r as Weight)) } fn instr_select(r: u32, ) -> Weight { - (74_186_000 as Weight) + (73_689_000 as Weight) // Standard Error: 4_000 - .saturating_add((1_789_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_792_000 as Weight).saturating_mul(r as Weight)) } fn instr_if(r: u32, ) -> Weight { - (74_040_000 as Weight) + (73_755_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_898_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_899_000 as Weight).saturating_mul(r as Weight)) } fn instr_br(r: u32, ) -> Weight { - (73_909_000 as Weight) - // Standard Error: 1_000 - .saturating_add((910_000 as Weight).saturating_mul(r as Weight)) + (73_735_000 as Weight) + // Standard Error: 0 + .saturating_add((903_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_if(r: u32, ) -> Weight { - (73_873_000 as Weight) - // Standard Error: 3_000 - .saturating_add((1_446_000 as Weight).saturating_mul(r as Weight)) + (73_595_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_448_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table(r: u32, ) -> Weight { - (73_438_000 as Weight) + (73_524_000 as Weight) // Standard Error: 3_000 - .saturating_add((1_582_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_572_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table_per_entry(e: u32, ) -> Weight { - (75_993_000 as Weight) + (76_361_000 as Weight) // Standard Error: 0 - .saturating_add((8_000 as Weight).saturating_mul(e as Weight)) + .saturating_add((4_000 as Weight).saturating_mul(e as Weight)) } fn instr_call(r: u32, ) -> Weight { - (73_218_000 as Weight) - // Standard Error: 17_000 - .saturating_add((17_167_000 as Weight).saturating_mul(r as Weight)) + (76_131_000 as Weight) + // Standard Error: 7_000 + .saturating_add((7_271_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect(r: u32, ) -> Weight { - (85_517_000 as Weight) - // Standard Error: 30_000 - .saturating_add((28_885_000 as Weight).saturating_mul(r as Weight)) + (87_948_000 as Weight) + // Standard Error: 14_000 + .saturating_add((9_429_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect_per_param(p: u32, ) -> Weight { - (119_915_000 as Weight) - // Standard Error: 3_000 - .saturating_add((918_000 as Weight).saturating_mul(p as Weight)) + (98_091_000 as Weight) + // Standard Error: 1_000 + .saturating_add((481_000 as Weight).saturating_mul(p as Weight)) } fn instr_local_get(r: u32, ) -> Weight { - (74_718_000 as Weight) + (74_311_000 as Weight) // Standard Error: 1_000 - .saturating_add((618_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((627_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_set(r: u32, ) -> Weight { - (74_800_000 as Weight) + (74_701_000 as Weight) // Standard Error: 1_000 - .saturating_add((684_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((677_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_tee(r: u32, ) -> Weight { - (74_590_000 as Weight) - // Standard Error: 2_000 - .saturating_add((911_000 as Weight).saturating_mul(r as Weight)) + (74_645_000 as Weight) + // Standard Error: 1_000 + .saturating_add((890_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_get(r: u32, ) -> Weight { - (76_776_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_159_000 as Weight).saturating_mul(r as Weight)) + (77_130_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_156_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_set(r: u32, ) -> Weight { - (77_283_000 as Weight) + (77_199_000 as Weight) // Standard Error: 2_000 - .saturating_add((1_367_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_366_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_current(r: u32, ) -> Weight { - (74_555_000 as Weight) - // Standard Error: 1_000 - .saturating_add((655_000 as Weight).saturating_mul(r as Weight)) + (74_024_000 as Weight) + // Standard Error: 2_000 + .saturating_add((675_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_grow(r: u32, ) -> Weight { - (73_693_000 as Weight) - // Standard Error: 131_000 - .saturating_add((181_095_000 as Weight).saturating_mul(r as Weight)) + (75_226_000 as Weight) + // Standard Error: 170_000 + .saturating_add((186_225_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64clz(r: u32, ) -> Weight { - (74_457_000 as Weight) - // Standard Error: 1_000 - .saturating_add((903_000 as Weight).saturating_mul(r as Weight)) + (74_307_000 as Weight) + // Standard Error: 2_000 + .saturating_add((896_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ctz(r: u32, ) -> Weight { - (74_287_000 as Weight) - // Standard Error: 1_000 - .saturating_add((907_000 as Weight).saturating_mul(r as Weight)) + (74_408_000 as Weight) + // Standard Error: 3_000 + .saturating_add((895_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64popcnt(r: u32, ) -> Weight { - (74_603_000 as Weight) - // Standard Error: 3_000 - .saturating_add((892_000 as Weight).saturating_mul(r as Weight)) + (74_418_000 as Weight) + // Standard Error: 1_000 + .saturating_add((885_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eqz(r: u32, ) -> Weight { - (74_383_000 as Weight) - // Standard Error: 1_000 + (74_130_000 as Weight) + // Standard Error: 2_000 .saturating_add((920_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendsi32(r: u32, ) -> Weight { - (74_020_000 as Weight) + (74_318_000 as Weight) // Standard Error: 2_000 - .saturating_add((896_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((876_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendui32(r: u32, ) -> Weight { - (74_108_000 as Weight) - // Standard Error: 4_000 - .saturating_add((889_000 as Weight).saturating_mul(r as Weight)) + (74_496_000 as Weight) + // Standard Error: 1_000 + .saturating_add((871_000 as Weight).saturating_mul(r as Weight)) } fn instr_i32wrapi64(r: u32, ) -> Weight { - (74_197_000 as Weight) - // Standard Error: 2_000 - .saturating_add((901_000 as Weight).saturating_mul(r as Weight)) + (73_938_000 as Weight) + // Standard Error: 0 + .saturating_add((897_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eq(r: u32, ) -> Weight { - (73_941_000 as Weight) + (73_943_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_377_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_367_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ne(r: u32, ) -> Weight { - (73_891_000 as Weight) + (74_305_000 as Weight) // Standard Error: 2_000 - .saturating_add((1_383_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_353_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64lts(r: u32, ) -> Weight { - (74_253_000 as Weight) + (73_948_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_369_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_361_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ltu(r: u32, ) -> Weight { - (74_125_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_371_000 as Weight).saturating_mul(r as Weight)) + (74_188_000 as Weight) + // Standard Error: 4_000 + .saturating_add((1_354_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gts(r: u32, ) -> Weight { - (74_144_000 as Weight) + (74_156_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_369_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_353_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gtu(r: u32, ) -> Weight { - (74_170_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_375_000 as Weight).saturating_mul(r as Weight)) + (73_972_000 as Weight) + // Standard Error: 0 + .saturating_add((1_365_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64les(r: u32, ) -> Weight { - (74_164_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_370_000 as Weight).saturating_mul(r as Weight)) + (74_082_000 as Weight) + // Standard Error: 5_000 + .saturating_add((1_360_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64leu(r: u32, ) -> Weight { - (74_166_000 as Weight) + (74_190_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_376_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_359_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ges(r: u32, ) -> Weight { - (73_920_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_381_000 as Weight).saturating_mul(r as Weight)) + (73_803_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_370_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64geu(r: u32, ) -> Weight { - (74_691_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_356_000 as Weight).saturating_mul(r as Weight)) + (74_063_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_357_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64add(r: u32, ) -> Weight { - (74_198_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_347_000 as Weight).saturating_mul(r as Weight)) + (73_750_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_345_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64sub(r: u32, ) -> Weight { - (74_064_000 as Weight) + (73_979_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_358_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_341_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64mul(r: u32, ) -> Weight { - (75_744_000 as Weight) - // Standard Error: 8_000 - .saturating_add((1_338_000 as Weight).saturating_mul(r as Weight)) + (74_197_000 as Weight) + // Standard Error: 4_000 + .saturating_add((1_332_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divs(r: u32, ) -> Weight { - (74_300_000 as Weight) - // Standard Error: 1_000 - .saturating_add((2_003_000 as Weight).saturating_mul(r as Weight)) + (73_624_000 as Weight) + // Standard Error: 5_000 + .saturating_add((2_020_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divu(r: u32, ) -> Weight { - (74_001_000 as Weight) - // Standard Error: 1_000 - .saturating_add((2_051_000 as Weight).saturating_mul(r as Weight)) + (74_074_000 as Weight) + // Standard Error: 2_000 + .saturating_add((2_050_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rems(r: u32, ) -> Weight { - (74_132_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_994_000 as Weight).saturating_mul(r as Weight)) + (73_766_000 as Weight) + // Standard Error: 5_000 + .saturating_add((2_016_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64remu(r: u32, ) -> Weight { - (74_241_000 as Weight) + (73_978_000 as Weight) // Standard Error: 3_000 - .saturating_add((2_070_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_064_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64and(r: u32, ) -> Weight { - (74_069_000 as Weight) + (73_996_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_351_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_336_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64or(r: u32, ) -> Weight { - (73_978_000 as Weight) - // Standard Error: 3_000 - .saturating_add((1_355_000 as Weight).saturating_mul(r as Weight)) + (74_058_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_335_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64xor(r: u32, ) -> Weight { - (74_053_000 as Weight) + (73_983_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_351_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_337_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shl(r: u32, ) -> Weight { - (73_891_000 as Weight) - // Standard Error: 0 - .saturating_add((1_371_000 as Weight).saturating_mul(r as Weight)) + (74_061_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_351_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shrs(r: u32, ) -> Weight { - (74_062_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_366_000 as Weight).saturating_mul(r as Weight)) + (73_940_000 as Weight) + // Standard Error: 5_000 + .saturating_add((1_360_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shru(r: u32, ) -> Weight { - (74_347_000 as Weight) + (73_954_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_360_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_359_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotl(r: u32, ) -> Weight { - (74_116_000 as Weight) + (74_026_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_366_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_354_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotr(r: u32, ) -> Weight { - (73_837_000 as Weight) - // Standard Error: 3_000 - .saturating_add((1_377_000 as Weight).saturating_mul(r as Weight)) + (74_149_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_352_000 as Weight).saturating_mul(r as Weight)) } } @@ -1051,32 +1051,32 @@ impl WeightInfo for SubstrateWeight { impl WeightInfo for () { // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize() -> Weight { - (1_588_000 as Weight) + (1_512_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn on_initialize_per_trie_key(k: u32, ) -> Weight { - (6_994_000 as Weight) + (8_089_000 as Weight) // Standard Error: 0 - .saturating_add((743_000 as Weight).saturating_mul(k as Weight)) + .saturating_add((741_000 as Weight).saturating_mul(k as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) } // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize_per_queue_item(q: u32, ) -> Weight { - (2_831_000 as Weight) - // Standard Error: 3_000 - .saturating_add((2_232_000 as Weight).saturating_mul(q as Weight)) + (0 as Weight) + // Standard Error: 5_000 + .saturating_add((2_287_000 as Weight).saturating_mul(q as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Contracts PristineCode (r:1 w:0) // Storage: Contracts CodeStorage (r:0 w:1) fn reinstrument(c: u32, ) -> Weight { - (17_839_000 as Weight) + (15_212_000 as Weight) // Standard Error: 0 - .saturating_add((64_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((51_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1085,9 +1085,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call_with_code_per_byte(c: u32, ) -> Weight { - (222_400_000 as Weight) + (218_406_000 as Weight) // Standard Error: 0 - .saturating_add((56_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((55_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -1099,9 +1099,9 @@ impl WeightInfo for () { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn instantiate_with_code(c: u32, s: u32, ) -> Weight { - (283_144_000 as Weight) + (265_773_000 as Weight) // Standard Error: 0 - .saturating_add((140_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((127_000 as Weight).saturating_mul(c as Weight)) // Standard Error: 0 .saturating_add((2_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) @@ -1114,7 +1114,7 @@ impl WeightInfo for () { // Storage: System Account (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn instantiate(s: u32, ) -> Weight { - (171_794_000 as Weight) + (173_852_000 as Weight) // Standard Error: 0 .saturating_add((2_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) @@ -1125,7 +1125,7 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call() -> Weight { - (140_234_000 as Weight) + (140_088_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -1133,9 +1133,9 @@ impl WeightInfo for () { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn upload_code(c: u32, ) -> Weight { - (49_467_000 as Weight) + (44_290_000 as Weight) // Standard Error: 0 - .saturating_add((66_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((51_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -1143,7 +1143,7 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:0 w:1) // Storage: Contracts PristineCode (r:0 w:1) fn remove_code() -> Weight { - (24_915_000 as Weight) + (24_364_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -1152,9 +1152,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_caller(r: u32, ) -> Weight { - (218_957_000 as Weight) - // Standard Error: 114_000 - .saturating_add((49_881_000 as Weight).saturating_mul(r as Weight)) + (219_617_000 as Weight) + // Standard Error: 119_000 + .saturating_add((50_409_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1163,9 +1163,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_is_contract(r: u32, ) -> Weight { - (76_490_000 as Weight) - // Standard Error: 856_000 - .saturating_add((375_305_000 as Weight).saturating_mul(r as Weight)) + (102_073_000 as Weight) + // Standard Error: 843_000 + .saturating_add((369_025_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1175,9 +1175,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_caller_is_origin(r: u32, ) -> Weight { - (213_485_000 as Weight) - // Standard Error: 76_000 - .saturating_add((22_020_000 as Weight).saturating_mul(r as Weight)) + (213_550_000 as Weight) + // Standard Error: 63_000 + .saturating_add((21_519_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1186,9 +1186,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_address(r: u32, ) -> Weight { - (218_468_000 as Weight) - // Standard Error: 108_000 - .saturating_add((49_457_000 as Weight).saturating_mul(r as Weight)) + (220_649_000 as Weight) + // Standard Error: 95_000 + .saturating_add((50_197_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1197,9 +1197,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas_left(r: u32, ) -> Weight { - (218_950_000 as Weight) + (218_190_000 as Weight) // Standard Error: 99_000 - .saturating_add((48_859_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((49_817_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1208,9 +1208,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_balance(r: u32, ) -> Weight { - (226_714_000 as Weight) - // Standard Error: 111_000 - .saturating_add((141_924_000 as Weight).saturating_mul(r as Weight)) + (223_133_000 as Weight) + // Standard Error: 188_000 + .saturating_add((142_288_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1219,9 +1219,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_value_transferred(r: u32, ) -> Weight { - (216_673_000 as Weight) - // Standard Error: 90_000 - .saturating_add((49_367_000 as Weight).saturating_mul(r as Weight)) + (216_612_000 as Weight) + // Standard Error: 103_000 + .saturating_add((49_956_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1230,9 +1230,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_minimum_balance(r: u32, ) -> Weight { - (215_859_000 as Weight) - // Standard Error: 104_000 - .saturating_add((49_334_000 as Weight).saturating_mul(r as Weight)) + (218_349_000 as Weight) + // Standard Error: 93_000 + .saturating_add((49_656_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1241,9 +1241,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_block_number(r: u32, ) -> Weight { - (216_419_000 as Weight) - // Standard Error: 109_000 - .saturating_add((49_417_000 as Weight).saturating_mul(r as Weight)) + (213_151_000 as Weight) + // Standard Error: 110_000 + .saturating_add((50_099_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1252,9 +1252,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_now(r: u32, ) -> Weight { - (218_799_000 as Weight) - // Standard Error: 108_000 - .saturating_add((48_631_000 as Weight).saturating_mul(r as Weight)) + (216_816_000 as Weight) + // Standard Error: 95_000 + .saturating_add((49_724_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1264,9 +1264,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0) fn seal_weight_to_fee(r: u32, ) -> Weight { - (215_968_000 as Weight) - // Standard Error: 147_000 - .saturating_add((122_978_000 as Weight).saturating_mul(r as Weight)) + (223_053_000 as Weight) + // Standard Error: 148_000 + .saturating_add((124_240_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1275,9 +1275,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas(r: u32, ) -> Weight { - (127_183_000 as Weight) - // Standard Error: 35_000 - .saturating_add((24_523_000 as Weight).saturating_mul(r as Weight)) + (127_253_000 as Weight) + // Standard Error: 27_000 + .saturating_add((25_608_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1286,9 +1286,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input(r: u32, ) -> Weight { - (217_535_000 as Weight) - // Standard Error: 91_000 - .saturating_add((48_400_000 as Weight).saturating_mul(r as Weight)) + (218_057_000 as Weight) + // Standard Error: 98_000 + .saturating_add((49_061_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1297,9 +1297,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input_per_kb(n: u32, ) -> Weight { - (297_539_000 as Weight) - // Standard Error: 5_000 - .saturating_add((11_870_000 as Weight).saturating_mul(n as Weight)) + (293_563_000 as Weight) + // Standard Error: 3_000 + .saturating_add((11_877_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1308,9 +1308,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return(r: u32, ) -> Weight { - (211_807_000 as Weight) - // Standard Error: 160_000 - .saturating_add((1_717_000 as Weight).saturating_mul(r as Weight)) + (211_511_000 as Weight) + // Standard Error: 70_000 + .saturating_add((2_085_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1319,9 +1319,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return_per_kb(n: u32, ) -> Weight { - (213_139_000 as Weight) + (213_876_000 as Weight) // Standard Error: 0 - .saturating_add((197_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((193_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1332,9 +1332,9 @@ impl WeightInfo for () { // Storage: Contracts DeletionQueue (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_terminate(r: u32, ) -> Weight { - (215_292_000 as Weight) - // Standard Error: 390_000 - .saturating_add((52_831_000 as Weight).saturating_mul(r as Weight)) + (214_736_000 as Weight) + // Standard Error: 206_000 + .saturating_add((53_637_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((4 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1346,9 +1346,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) fn seal_random(r: u32, ) -> Weight { - (215_802_000 as Weight) - // Standard Error: 132_000 - .saturating_add((159_065_000 as Weight).saturating_mul(r as Weight)) + (222_037_000 as Weight) + // Standard Error: 191_000 + .saturating_add((160_114_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1357,9 +1357,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_deposit_event(r: u32, ) -> Weight { - (225_069_000 as Weight) - // Standard Error: 201_000 - .saturating_add((292_145_000 as Weight).saturating_mul(r as Weight)) + (219_211_000 as Weight) + // Standard Error: 239_000 + .saturating_add((296_722_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1369,11 +1369,11 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: System EventTopics (r:100 w:100) fn seal_deposit_event_per_topic_and_kb(t: u32, n: u32, ) -> Weight { - (519_617_000 as Weight) - // Standard Error: 1_751_000 - .saturating_add((290_832_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 345_000 - .saturating_add((82_584_000 as Weight).saturating_mul(n as Weight)) + (519_643_000 as Weight) + // Standard Error: 1_842_000 + .saturating_add((300_853_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 363_000 + .saturating_add((82_577_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(t as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1384,17 +1384,17 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_debug_message(r: u32, ) -> Weight { - (132_245_000 as Weight) - // Standard Error: 75_000 - .saturating_add((41_274_000 as Weight).saturating_mul(r as Weight)) + (132_710_000 as Weight) + // Standard Error: 77_000 + .saturating_add((41_623_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage(r: u32, ) -> Weight { - (48_288_000 as Weight) - // Standard Error: 1_024_000 - .saturating_add((408_264_000 as Weight).saturating_mul(r as Weight)) + (40_644_000 as Weight) + // Standard Error: 1_072_000 + .saturating_add((412_308_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1402,25 +1402,25 @@ impl WeightInfo for () { } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage_per_new_kb(n: u32, ) -> Weight { - (607_246_000 as Weight) - // Standard Error: 252_000 - .saturating_add((28_722_000 as Weight).saturating_mul(n as Weight)) + (609_052_000 as Weight) + // Standard Error: 258_000 + .saturating_add((28_633_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage_per_old_kb(n: u32, ) -> Weight { - (623_983_000 as Weight) - // Standard Error: 305_000 - .saturating_add((11_374_000 as Weight).saturating_mul(n as Weight)) + (629_665_000 as Weight) + // Standard Error: 300_000 + .saturating_add((10_947_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage(r: u32, ) -> Weight { - (91_727_000 as Weight) - // Standard Error: 837_000 - .saturating_add((383_577_000 as Weight).saturating_mul(r as Weight)) + (91_519_000 as Weight) + // Standard Error: 889_000 + .saturating_add((386_498_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -1428,51 +1428,51 @@ impl WeightInfo for () { } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage_per_kb(n: u32, ) -> Weight { - (604_749_000 as Weight) - // Standard Error: 251_000 - .saturating_add((11_086_000 as Weight).saturating_mul(n as Weight)) + (612_224_000 as Weight) + // Standard Error: 269_000 + .saturating_add((10_709_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage(r: u32, ) -> Weight { - (107_805_000 as Weight) - // Standard Error: 722_000 - .saturating_add((326_494_000 as Weight).saturating_mul(r as Weight)) + (112_236_000 as Weight) + // Standard Error: 624_000 + .saturating_add((327_655_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage_per_kb(n: u32, ) -> Weight { - (564_604_000 as Weight) - // Standard Error: 360_000 - .saturating_add((65_184_000 as Weight).saturating_mul(n as Weight)) + (567_711_000 as Weight) + // Standard Error: 387_000 + .saturating_add((63_984_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(104 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_contains_storage(r: u32, ) -> Weight { - (122_105_000 as Weight) - // Standard Error: 560_000 - .saturating_add((291_458_000 as Weight).saturating_mul(r as Weight)) + (109_996_000 as Weight) + // Standard Error: 681_000 + .saturating_add((298_317_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_contains_storage_per_kb(n: u32, ) -> Weight { - (512_580_000 as Weight) - // Standard Error: 245_000 - .saturating_add((10_171_000 as Weight).saturating_mul(n as Weight)) + (518_342_000 as Weight) + // Standard Error: 251_000 + .saturating_add((9_666_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(104 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage(r: u32, ) -> Weight { - (81_220_000 as Weight) - // Standard Error: 933_000 - .saturating_add((418_532_000 as Weight).saturating_mul(r as Weight)) + (75_974_000 as Weight) + // Standard Error: 1_000_000 + .saturating_add((417_954_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -1480,9 +1480,9 @@ impl WeightInfo for () { } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage_per_kb(n: u32, ) -> Weight { - (652_330_000 as Weight) - // Standard Error: 357_000 - .saturating_add((65_711_000 as Weight).saturating_mul(n as Weight)) + (653_188_000 as Weight) + // Standard Error: 333_000 + .saturating_add((64_810_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().writes(103 as Weight)) } @@ -1491,9 +1491,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_transfer(r: u32, ) -> Weight { - (126_544_000 as Weight) - // Standard Error: 1_198_000 - .saturating_add((1_796_593_000 as Weight).saturating_mul(r as Weight)) + (127_056_000 as Weight) + // Standard Error: 1_106_000 + .saturating_add((1_784_183_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) @@ -1505,8 +1505,8 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) fn seal_call(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 3_033_000 - .saturating_add((19_788_005_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 2_621_000 + .saturating_add((19_757_765_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1518,8 +1518,8 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) fn seal_delegate_call(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 6_663_000 - .saturating_add((19_835_985_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 6_286_000 + .saturating_add((19_798_229_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads((99 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1528,11 +1528,11 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:2 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_call_per_transfer_clone_kb(t: u32, c: u32, ) -> Weight { - (10_957_494_000 as Weight) - // Standard Error: 13_908_000 - .saturating_add((1_622_630_000 as Weight).saturating_mul(t as Weight)) + (10_922_130_000 as Weight) + // Standard Error: 15_556_000 + .saturating_add((1_672_276_000 as Weight).saturating_mul(t as Weight)) // Standard Error: 6_000 - .saturating_add((11_960_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((11_984_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().reads((101 as Weight).saturating_mul(t as Weight))) .saturating_add(RocksDbWeight::get().writes(101 as Weight)) @@ -1546,8 +1546,8 @@ impl WeightInfo for () { // Storage: Contracts OwnerInfoOf (r:100 w:100) fn seal_instantiate(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 48_191_000 - .saturating_add((27_587_375_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 46_147_000 + .saturating_add((27_589_519_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().reads((400 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -1560,11 +1560,11 @@ impl WeightInfo for () { // Storage: Contracts AccountCounter (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_instantiate_per_transfer_salt_kb(t: u32, s: u32, ) -> Weight { - (14_504_226_000 as Weight) - // Standard Error: 66_350_000 - .saturating_add((912_874_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 31_000 - .saturating_add((157_415_000 as Weight).saturating_mul(s as Weight)) + (14_790_752_000 as Weight) + // Standard Error: 37_838_000 + .saturating_add((714_016_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 17_000 + .saturating_add((155_605_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(207 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(t as Weight))) .saturating_add(RocksDbWeight::get().writes(205 as Weight)) @@ -1575,9 +1575,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256(r: u32, ) -> Weight { - (216_771_000 as Weight) - // Standard Error: 127_000 - .saturating_add((79_994_000 as Weight).saturating_mul(r as Weight)) + (216_547_000 as Weight) + // Standard Error: 126_000 + .saturating_add((81_132_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1586,9 +1586,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256_per_kb(n: u32, ) -> Weight { - (376_960_000 as Weight) - // Standard Error: 24_000 - .saturating_add((465_507_000 as Weight).saturating_mul(n as Weight)) + (459_912_000 as Weight) + // Standard Error: 27_000 + .saturating_add((464_750_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1597,9 +1597,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256(r: u32, ) -> Weight { - (212_554_000 as Weight) - // Standard Error: 129_000 - .saturating_add((92_073_000 as Weight).saturating_mul(r as Weight)) + (212_653_000 as Weight) + // Standard Error: 147_000 + .saturating_add((93_380_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1608,9 +1608,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256_per_kb(n: u32, ) -> Weight { - (298_638_000 as Weight) - // Standard Error: 23_000 - .saturating_add((307_231_000 as Weight).saturating_mul(n as Weight)) + (324_536_000 as Weight) + // Standard Error: 20_000 + .saturating_add((306_160_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1619,9 +1619,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256(r: u32, ) -> Weight { - (216_274_000 as Weight) - // Standard Error: 100_000 - .saturating_add((64_205_000 as Weight).saturating_mul(r as Weight)) + (218_574_000 as Weight) + // Standard Error: 123_000 + .saturating_add((65_035_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1630,9 +1630,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256_per_kb(n: u32, ) -> Weight { - (294_478_000 as Weight) - // Standard Error: 18_000 - .saturating_add((120_405_000 as Weight).saturating_mul(n as Weight)) + (345_804_000 as Weight) + // Standard Error: 14_000 + .saturating_add((118_896_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1641,9 +1641,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128(r: u32, ) -> Weight { - (215_874_000 as Weight) - // Standard Error: 115_000 - .saturating_add((63_402_000 as Weight).saturating_mul(r as Weight)) + (215_898_000 as Weight) + // Standard Error: 108_000 + .saturating_add((64_332_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1652,9 +1652,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128_per_kb(n: u32, ) -> Weight { - (288_361_000 as Weight) - // Standard Error: 15_000 - .saturating_add((120_795_000 as Weight).saturating_mul(n as Weight)) + (351_569_000 as Weight) + // Standard Error: 18_000 + .saturating_add((118_896_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1663,9 +1663,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_ecdsa_recover(r: u32, ) -> Weight { - (142_940_000 as Weight) - // Standard Error: 1_317_000 - .saturating_add((15_385_437_000 as Weight).saturating_mul(r as Weight)) + (272_893_000 as Weight) + // Standard Error: 1_438_000 + .saturating_add((15_412_877_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1676,264 +1676,264 @@ impl WeightInfo for () { // Storage: Contracts OwnerInfoOf (r:36 w:36) fn seal_set_code_hash(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 1_981_000 - .saturating_add((943_500_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 2_132_000 + .saturating_add((937_623_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads((99 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes((99 as Weight).saturating_mul(r as Weight))) } fn instr_i64const(r: u32, ) -> Weight { - (74_672_000 as Weight) + (74_268_000 as Weight) // Standard Error: 1_000 .saturating_add((595_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64load(r: u32, ) -> Weight { - (74_346_000 as Weight) + (74_515_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_324_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_300_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64store(r: u32, ) -> Weight { - (74_149_000 as Weight) + (74_217_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_438_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_411_000 as Weight).saturating_mul(r as Weight)) } fn instr_select(r: u32, ) -> Weight { - (74_186_000 as Weight) + (73_689_000 as Weight) // Standard Error: 4_000 - .saturating_add((1_789_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_792_000 as Weight).saturating_mul(r as Weight)) } fn instr_if(r: u32, ) -> Weight { - (74_040_000 as Weight) + (73_755_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_898_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_899_000 as Weight).saturating_mul(r as Weight)) } fn instr_br(r: u32, ) -> Weight { - (73_909_000 as Weight) - // Standard Error: 1_000 - .saturating_add((910_000 as Weight).saturating_mul(r as Weight)) + (73_735_000 as Weight) + // Standard Error: 0 + .saturating_add((903_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_if(r: u32, ) -> Weight { - (73_873_000 as Weight) - // Standard Error: 3_000 - .saturating_add((1_446_000 as Weight).saturating_mul(r as Weight)) + (73_595_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_448_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table(r: u32, ) -> Weight { - (73_438_000 as Weight) + (73_524_000 as Weight) // Standard Error: 3_000 - .saturating_add((1_582_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_572_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table_per_entry(e: u32, ) -> Weight { - (75_993_000 as Weight) + (76_361_000 as Weight) // Standard Error: 0 - .saturating_add((8_000 as Weight).saturating_mul(e as Weight)) + .saturating_add((4_000 as Weight).saturating_mul(e as Weight)) } fn instr_call(r: u32, ) -> Weight { - (73_218_000 as Weight) - // Standard Error: 17_000 - .saturating_add((17_167_000 as Weight).saturating_mul(r as Weight)) + (76_131_000 as Weight) + // Standard Error: 7_000 + .saturating_add((7_271_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect(r: u32, ) -> Weight { - (85_517_000 as Weight) - // Standard Error: 30_000 - .saturating_add((28_885_000 as Weight).saturating_mul(r as Weight)) + (87_948_000 as Weight) + // Standard Error: 14_000 + .saturating_add((9_429_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect_per_param(p: u32, ) -> Weight { - (119_915_000 as Weight) - // Standard Error: 3_000 - .saturating_add((918_000 as Weight).saturating_mul(p as Weight)) + (98_091_000 as Weight) + // Standard Error: 1_000 + .saturating_add((481_000 as Weight).saturating_mul(p as Weight)) } fn instr_local_get(r: u32, ) -> Weight { - (74_718_000 as Weight) + (74_311_000 as Weight) // Standard Error: 1_000 - .saturating_add((618_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((627_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_set(r: u32, ) -> Weight { - (74_800_000 as Weight) + (74_701_000 as Weight) // Standard Error: 1_000 - .saturating_add((684_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((677_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_tee(r: u32, ) -> Weight { - (74_590_000 as Weight) - // Standard Error: 2_000 - .saturating_add((911_000 as Weight).saturating_mul(r as Weight)) + (74_645_000 as Weight) + // Standard Error: 1_000 + .saturating_add((890_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_get(r: u32, ) -> Weight { - (76_776_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_159_000 as Weight).saturating_mul(r as Weight)) + (77_130_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_156_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_set(r: u32, ) -> Weight { - (77_283_000 as Weight) + (77_199_000 as Weight) // Standard Error: 2_000 - .saturating_add((1_367_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_366_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_current(r: u32, ) -> Weight { - (74_555_000 as Weight) - // Standard Error: 1_000 - .saturating_add((655_000 as Weight).saturating_mul(r as Weight)) + (74_024_000 as Weight) + // Standard Error: 2_000 + .saturating_add((675_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_grow(r: u32, ) -> Weight { - (73_693_000 as Weight) - // Standard Error: 131_000 - .saturating_add((181_095_000 as Weight).saturating_mul(r as Weight)) + (75_226_000 as Weight) + // Standard Error: 170_000 + .saturating_add((186_225_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64clz(r: u32, ) -> Weight { - (74_457_000 as Weight) - // Standard Error: 1_000 - .saturating_add((903_000 as Weight).saturating_mul(r as Weight)) + (74_307_000 as Weight) + // Standard Error: 2_000 + .saturating_add((896_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ctz(r: u32, ) -> Weight { - (74_287_000 as Weight) - // Standard Error: 1_000 - .saturating_add((907_000 as Weight).saturating_mul(r as Weight)) + (74_408_000 as Weight) + // Standard Error: 3_000 + .saturating_add((895_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64popcnt(r: u32, ) -> Weight { - (74_603_000 as Weight) - // Standard Error: 3_000 - .saturating_add((892_000 as Weight).saturating_mul(r as Weight)) + (74_418_000 as Weight) + // Standard Error: 1_000 + .saturating_add((885_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eqz(r: u32, ) -> Weight { - (74_383_000 as Weight) - // Standard Error: 1_000 + (74_130_000 as Weight) + // Standard Error: 2_000 .saturating_add((920_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendsi32(r: u32, ) -> Weight { - (74_020_000 as Weight) + (74_318_000 as Weight) // Standard Error: 2_000 - .saturating_add((896_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((876_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendui32(r: u32, ) -> Weight { - (74_108_000 as Weight) - // Standard Error: 4_000 - .saturating_add((889_000 as Weight).saturating_mul(r as Weight)) + (74_496_000 as Weight) + // Standard Error: 1_000 + .saturating_add((871_000 as Weight).saturating_mul(r as Weight)) } fn instr_i32wrapi64(r: u32, ) -> Weight { - (74_197_000 as Weight) - // Standard Error: 2_000 - .saturating_add((901_000 as Weight).saturating_mul(r as Weight)) + (73_938_000 as Weight) + // Standard Error: 0 + .saturating_add((897_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eq(r: u32, ) -> Weight { - (73_941_000 as Weight) + (73_943_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_377_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_367_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ne(r: u32, ) -> Weight { - (73_891_000 as Weight) + (74_305_000 as Weight) // Standard Error: 2_000 - .saturating_add((1_383_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_353_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64lts(r: u32, ) -> Weight { - (74_253_000 as Weight) + (73_948_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_369_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_361_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ltu(r: u32, ) -> Weight { - (74_125_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_371_000 as Weight).saturating_mul(r as Weight)) + (74_188_000 as Weight) + // Standard Error: 4_000 + .saturating_add((1_354_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gts(r: u32, ) -> Weight { - (74_144_000 as Weight) + (74_156_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_369_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_353_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gtu(r: u32, ) -> Weight { - (74_170_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_375_000 as Weight).saturating_mul(r as Weight)) + (73_972_000 as Weight) + // Standard Error: 0 + .saturating_add((1_365_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64les(r: u32, ) -> Weight { - (74_164_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_370_000 as Weight).saturating_mul(r as Weight)) + (74_082_000 as Weight) + // Standard Error: 5_000 + .saturating_add((1_360_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64leu(r: u32, ) -> Weight { - (74_166_000 as Weight) + (74_190_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_376_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_359_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ges(r: u32, ) -> Weight { - (73_920_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_381_000 as Weight).saturating_mul(r as Weight)) + (73_803_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_370_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64geu(r: u32, ) -> Weight { - (74_691_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_356_000 as Weight).saturating_mul(r as Weight)) + (74_063_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_357_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64add(r: u32, ) -> Weight { - (74_198_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_347_000 as Weight).saturating_mul(r as Weight)) + (73_750_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_345_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64sub(r: u32, ) -> Weight { - (74_064_000 as Weight) + (73_979_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_358_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_341_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64mul(r: u32, ) -> Weight { - (75_744_000 as Weight) - // Standard Error: 8_000 - .saturating_add((1_338_000 as Weight).saturating_mul(r as Weight)) + (74_197_000 as Weight) + // Standard Error: 4_000 + .saturating_add((1_332_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divs(r: u32, ) -> Weight { - (74_300_000 as Weight) - // Standard Error: 1_000 - .saturating_add((2_003_000 as Weight).saturating_mul(r as Weight)) + (73_624_000 as Weight) + // Standard Error: 5_000 + .saturating_add((2_020_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divu(r: u32, ) -> Weight { - (74_001_000 as Weight) - // Standard Error: 1_000 - .saturating_add((2_051_000 as Weight).saturating_mul(r as Weight)) + (74_074_000 as Weight) + // Standard Error: 2_000 + .saturating_add((2_050_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rems(r: u32, ) -> Weight { - (74_132_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_994_000 as Weight).saturating_mul(r as Weight)) + (73_766_000 as Weight) + // Standard Error: 5_000 + .saturating_add((2_016_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64remu(r: u32, ) -> Weight { - (74_241_000 as Weight) + (73_978_000 as Weight) // Standard Error: 3_000 - .saturating_add((2_070_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_064_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64and(r: u32, ) -> Weight { - (74_069_000 as Weight) + (73_996_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_351_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_336_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64or(r: u32, ) -> Weight { - (73_978_000 as Weight) - // Standard Error: 3_000 - .saturating_add((1_355_000 as Weight).saturating_mul(r as Weight)) + (74_058_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_335_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64xor(r: u32, ) -> Weight { - (74_053_000 as Weight) + (73_983_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_351_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_337_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shl(r: u32, ) -> Weight { - (73_891_000 as Weight) - // Standard Error: 0 - .saturating_add((1_371_000 as Weight).saturating_mul(r as Weight)) + (74_061_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_351_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shrs(r: u32, ) -> Weight { - (74_062_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_366_000 as Weight).saturating_mul(r as Weight)) + (73_940_000 as Weight) + // Standard Error: 5_000 + .saturating_add((1_360_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shru(r: u32, ) -> Weight { - (74_347_000 as Weight) + (73_954_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_360_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_359_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotl(r: u32, ) -> Weight { - (74_116_000 as Weight) + (74_026_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_366_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_354_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotr(r: u32, ) -> Weight { - (73_837_000 as Weight) - // Standard Error: 3_000 - .saturating_add((1_377_000 as Weight).saturating_mul(r as Weight)) + (74_149_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_352_000 as Weight).saturating_mul(r as Weight)) } } From 8bb8eff0376ff0706f99dd43bae035da8b7827c5 Mon Sep 17 00:00:00 2001 From: Gavin Wood Date: Tue, 22 Feb 2022 11:42:46 +0100 Subject: [PATCH 519/695] Rename Uniques Error::Unknown to something more sensible (#10895) * Rename Uniques Error::Unknown to something more sensible * Typos * Typos * fmt Signed-off-by: Oliver Tale-Yazdi * Fix tests Signed-off-by: Oliver Tale-Yazdi * fmt Signed-off-by: Oliver Tale-Yazdi Co-authored-by: Oliver Tale-Yazdi --- frame/uniques/src/functions.rs | 14 ++++++---- frame/uniques/src/lib.rs | 51 +++++++++++++++++++--------------- frame/uniques/src/tests.rs | 32 ++++++++++++++------- 3 files changed, 58 insertions(+), 39 deletions(-) diff --git a/frame/uniques/src/functions.rs b/frame/uniques/src/functions.rs index 5d573e42097e..40c436bd56b4 100644 --- a/frame/uniques/src/functions.rs +++ b/frame/uniques/src/functions.rs @@ -31,10 +31,11 @@ impl, I: 'static> Pallet { &mut InstanceDetailsFor, ) -> DispatchResult, ) -> DispatchResult { - let class_details = Class::::get(&class).ok_or(Error::::Unknown)?; + let class_details = Class::::get(&class).ok_or(Error::::UnknownClass)?; ensure!(!class_details.is_frozen, Error::::Frozen); - let mut details = Asset::::get(&class, &instance).ok_or(Error::::Unknown)?; + let mut details = + Asset::::get(&class, &instance).ok_or(Error::::UnknownClass)?; ensure!(!details.is_frozen, Error::::Frozen); with_details(&class_details, &mut details)?; @@ -92,7 +93,7 @@ impl, I: 'static> Pallet { maybe_check_owner: Option, ) -> Result { Class::::try_mutate_exists(class, |maybe_details| { - let class_details = maybe_details.take().ok_or(Error::::Unknown)?; + let class_details = maybe_details.take().ok_or(Error::::UnknownClass)?; if let Some(check_owner) = maybe_check_owner { ensure!(class_details.owner == check_owner, Error::::NoPermission); } @@ -131,7 +132,7 @@ impl, I: 'static> Pallet { ensure!(!Asset::::contains_key(class, instance), Error::::AlreadyExists); Class::::try_mutate(&class, |maybe_class_details| -> DispatchResult { - let class_details = maybe_class_details.as_mut().ok_or(Error::::Unknown)?; + let class_details = maybe_class_details.as_mut().ok_or(Error::::UnknownClass)?; with_details(&class_details)?; @@ -165,9 +166,10 @@ impl, I: 'static> Pallet { let owner = Class::::try_mutate( &class, |maybe_class_details| -> Result { - let class_details = maybe_class_details.as_mut().ok_or(Error::::Unknown)?; + let class_details = + maybe_class_details.as_mut().ok_or(Error::::UnknownClass)?; let details = - Asset::::get(&class, &instance).ok_or(Error::::Unknown)?; + Asset::::get(&class, &instance).ok_or(Error::::UnknownClass)?; with_details(&class_details, &details)?; // Return the deposit. diff --git a/frame/uniques/src/lib.rs b/frame/uniques/src/lib.rs index 2956735e5ec3..f35bb3fd61a0 100644 --- a/frame/uniques/src/lib.rs +++ b/frame/uniques/src/lib.rs @@ -303,7 +303,7 @@ pub mod pallet { /// The signing account has no permission to do the operation. NoPermission, /// The given asset ID is unknown. - Unknown, + UnknownClass, /// The asset instance ID has already been used for an asset. AlreadyExists, /// The owner turned out to be different to what was expected. @@ -561,7 +561,8 @@ pub mod pallet { ) -> DispatchResult { let origin = ensure_signed(origin)?; - let mut class_details = Class::::get(&class).ok_or(Error::::Unknown)?; + let mut class_details = + Class::::get(&class).ok_or(Error::::UnknownClass)?; ensure!(class_details.owner == origin, Error::::NoPermission); let deposit = match class_details.free_holding { true => Zero::zero(), @@ -621,8 +622,8 @@ pub mod pallet { let origin = ensure_signed(origin)?; let mut details = - Asset::::get(&class, &instance).ok_or(Error::::Unknown)?; - let class_details = Class::::get(&class).ok_or(Error::::Unknown)?; + Asset::::get(&class, &instance).ok_or(Error::::UnknownClass)?; + let class_details = Class::::get(&class).ok_or(Error::::UnknownClass)?; ensure!(class_details.freezer == origin, Error::::NoPermission); details.is_frozen = true; @@ -651,8 +652,8 @@ pub mod pallet { let origin = ensure_signed(origin)?; let mut details = - Asset::::get(&class, &instance).ok_or(Error::::Unknown)?; - let class_details = Class::::get(&class).ok_or(Error::::Unknown)?; + Asset::::get(&class, &instance).ok_or(Error::::UnknownClass)?; + let class_details = Class::::get(&class).ok_or(Error::::UnknownClass)?; ensure!(class_details.admin == origin, Error::::NoPermission); details.is_frozen = false; @@ -679,7 +680,7 @@ pub mod pallet { let origin = ensure_signed(origin)?; Class::::try_mutate(class, |maybe_details| { - let details = maybe_details.as_mut().ok_or(Error::::Unknown)?; + let details = maybe_details.as_mut().ok_or(Error::::UnknownClass)?; ensure!(&origin == &details.freezer, Error::::NoPermission); details.is_frozen = true; @@ -706,7 +707,7 @@ pub mod pallet { let origin = ensure_signed(origin)?; Class::::try_mutate(class, |maybe_details| { - let details = maybe_details.as_mut().ok_or(Error::::Unknown)?; + let details = maybe_details.as_mut().ok_or(Error::::UnknownClass)?; ensure!(&origin == &details.admin, Error::::NoPermission); details.is_frozen = false; @@ -736,7 +737,7 @@ pub mod pallet { let owner = T::Lookup::lookup(owner)?; Class::::try_mutate(class, |maybe_details| { - let details = maybe_details.as_mut().ok_or(Error::::Unknown)?; + let details = maybe_details.as_mut().ok_or(Error::::UnknownClass)?; ensure!(&origin == &details.owner, Error::::NoPermission); if details.owner == owner { return Ok(()) @@ -784,7 +785,7 @@ pub mod pallet { let freezer = T::Lookup::lookup(freezer)?; Class::::try_mutate(class, |maybe_details| { - let details = maybe_details.as_mut().ok_or(Error::::Unknown)?; + let details = maybe_details.as_mut().ok_or(Error::::UnknownClass)?; ensure!(&origin == &details.owner, Error::::NoPermission); details.issuer = issuer.clone(); @@ -820,9 +821,9 @@ pub mod pallet { let delegate = T::Lookup::lookup(delegate)?; - let class_details = Class::::get(&class).ok_or(Error::::Unknown)?; + let class_details = Class::::get(&class).ok_or(Error::::UnknownClass)?; let mut details = - Asset::::get(&class, &instance).ok_or(Error::::Unknown)?; + Asset::::get(&class, &instance).ok_or(Error::::UnknownClass)?; if let Some(check) = maybe_check { let permitted = &check == &class_details.admin || &check == &details.owner; @@ -870,9 +871,9 @@ pub mod pallet { .map(|_| None) .or_else(|origin| ensure_signed(origin).map(Some).map_err(DispatchError::from))?; - let class_details = Class::::get(&class).ok_or(Error::::Unknown)?; + let class_details = Class::::get(&class).ok_or(Error::::UnknownClass)?; let mut details = - Asset::::get(&class, &instance).ok_or(Error::::Unknown)?; + Asset::::get(&class, &instance).ok_or(Error::::UnknownClass)?; if let Some(check) = maybe_check { let permitted = &check == &class_details.admin || &check == &details.owner; ensure!(permitted, Error::::NoPermission); @@ -925,7 +926,7 @@ pub mod pallet { T::ForceOrigin::ensure_origin(origin)?; Class::::try_mutate(class, |maybe_asset| { - let mut asset = maybe_asset.take().ok_or(Error::::Unknown)?; + let mut asset = maybe_asset.take().ok_or(Error::::UnknownClass)?; let old_owner = asset.owner; let new_owner = T::Lookup::lookup(owner)?; asset.owner = new_owner.clone(); @@ -972,7 +973,8 @@ pub mod pallet { .map(|_| None) .or_else(|origin| ensure_signed(origin).map(Some))?; - let mut class_details = Class::::get(&class).ok_or(Error::::Unknown)?; + let mut class_details = + Class::::get(&class).ok_or(Error::::UnknownClass)?; if let Some(check_owner) = &maybe_check_owner { ensure!(check_owner == &class_details.owner, Error::::NoPermission); } @@ -1033,7 +1035,8 @@ pub mod pallet { .map(|_| None) .or_else(|origin| ensure_signed(origin).map(Some))?; - let mut class_details = Class::::get(&class).ok_or(Error::::Unknown)?; + let mut class_details = + Class::::get(&class).ok_or(Error::::UnknownClass)?; if let Some(check_owner) = &maybe_check_owner { ensure!(check_owner == &class_details.owner, Error::::NoPermission); } @@ -1083,7 +1086,8 @@ pub mod pallet { .map(|_| None) .or_else(|origin| ensure_signed(origin).map(Some))?; - let mut class_details = Class::::get(&class).ok_or(Error::::Unknown)?; + let mut class_details = + Class::::get(&class).ok_or(Error::::UnknownClass)?; if let Some(check_owner) = &maybe_check_owner { ensure!(check_owner == &class_details.owner, Error::::NoPermission); @@ -1142,7 +1146,8 @@ pub mod pallet { .map(|_| None) .or_else(|origin| ensure_signed(origin).map(Some))?; - let mut class_details = Class::::get(&class).ok_or(Error::::Unknown)?; + let mut class_details = + Class::::get(&class).ok_or(Error::::UnknownClass)?; if let Some(check_owner) = &maybe_check_owner { ensure!(check_owner == &class_details.owner, Error::::NoPermission); } @@ -1154,7 +1159,7 @@ pub mod pallet { if metadata.is_some() { class_details.instance_metadatas.saturating_dec(); } - let deposit = metadata.take().ok_or(Error::::Unknown)?.deposit; + let deposit = metadata.take().ok_or(Error::::UnknownClass)?.deposit; T::Currency::unreserve(&class_details.owner, deposit); class_details.total_deposit.saturating_reduce(deposit); @@ -1191,7 +1196,7 @@ pub mod pallet { .map(|_| None) .or_else(|origin| ensure_signed(origin).map(Some))?; - let mut details = Class::::get(&class).ok_or(Error::::Unknown)?; + let mut details = Class::::get(&class).ok_or(Error::::UnknownClass)?; if let Some(check_owner) = &maybe_check_owner { ensure!(check_owner == &details.owner, Error::::NoPermission); } @@ -1245,7 +1250,7 @@ pub mod pallet { .map(|_| None) .or_else(|origin| ensure_signed(origin).map(Some))?; - let details = Class::::get(&class).ok_or(Error::::Unknown)?; + let details = Class::::get(&class).ok_or(Error::::UnknownClass)?; if let Some(check_owner) = &maybe_check_owner { ensure!(check_owner == &details.owner, Error::::NoPermission); } @@ -1254,7 +1259,7 @@ pub mod pallet { let was_frozen = metadata.as_ref().map_or(false, |m| m.is_frozen); ensure!(maybe_check_owner.is_none() || !was_frozen, Error::::Frozen); - let deposit = metadata.take().ok_or(Error::::Unknown)?.deposit; + let deposit = metadata.take().ok_or(Error::::UnknownClass)?.deposit; T::Currency::unreserve(&details.owner, deposit); Self::deposit_event(Event::ClassMetadataCleared { class }); Ok(()) diff --git a/frame/uniques/src/tests.rs b/frame/uniques/src/tests.rs index 293140d5eda1..12f39c78bfe3 100644 --- a/frame/uniques/src/tests.rs +++ b/frame/uniques/src/tests.rs @@ -263,7 +263,7 @@ fn set_class_metadata_should_work() { // Cannot add metadata to unknown asset assert_noop!( Uniques::set_class_metadata(Origin::signed(1), 0, bvec![0u8; 20], false), - Error::::Unknown, + Error::::UnknownClass, ); assert_ok!(Uniques::force_create(Origin::root(), 0, 1, false)); // Cannot add metadata to unowned asset @@ -307,7 +307,10 @@ fn set_class_metadata_should_work() { Uniques::clear_class_metadata(Origin::signed(2), 0), Error::::NoPermission ); - assert_noop!(Uniques::clear_class_metadata(Origin::signed(1), 1), Error::::Unknown); + assert_noop!( + Uniques::clear_class_metadata(Origin::signed(1), 1), + Error::::UnknownClass + ); assert_ok!(Uniques::clear_class_metadata(Origin::signed(1), 0)); assert!(!ClassMetadataOf::::contains_key(0)); }); @@ -361,7 +364,10 @@ fn set_instance_metadata_should_work() { Uniques::clear_metadata(Origin::signed(2), 0, 42), Error::::NoPermission ); - assert_noop!(Uniques::clear_metadata(Origin::signed(1), 1, 42), Error::::Unknown); + assert_noop!( + Uniques::clear_metadata(Origin::signed(1), 1, 42), + Error::::UnknownClass + ); assert_ok!(Uniques::clear_metadata(Origin::signed(1), 0, 42)); assert!(!InstanceMetadataOf::::contains_key(0, 42)); }); @@ -486,7 +492,7 @@ fn burn_works() { assert_ok!(Uniques::force_create(Origin::root(), 0, 1, false)); assert_ok!(Uniques::set_team(Origin::signed(1), 0, 2, 3, 4)); - assert_noop!(Uniques::burn(Origin::signed(5), 0, 42, Some(5)), Error::::Unknown); + assert_noop!(Uniques::burn(Origin::signed(5), 0, 42, Some(5)), Error::::UnknownClass); assert_ok!(Uniques::mint(Origin::signed(2), 0, 42, 5)); assert_ok!(Uniques::mint(Origin::signed(2), 0, 69, 5)); @@ -525,11 +531,11 @@ fn cancel_approval_works() { assert_ok!(Uniques::approve_transfer(Origin::signed(2), 0, 42, 3)); assert_noop!( Uniques::cancel_approval(Origin::signed(2), 1, 42, None), - Error::::Unknown + Error::::UnknownClass ); assert_noop!( Uniques::cancel_approval(Origin::signed(2), 0, 43, None), - Error::::Unknown + Error::::UnknownClass ); assert_noop!( Uniques::cancel_approval(Origin::signed(3), 0, 42, None), @@ -557,11 +563,11 @@ fn cancel_approval_works_with_admin() { assert_ok!(Uniques::approve_transfer(Origin::signed(2), 0, 42, 3)); assert_noop!( Uniques::cancel_approval(Origin::signed(1), 1, 42, None), - Error::::Unknown + Error::::UnknownClass ); assert_noop!( Uniques::cancel_approval(Origin::signed(1), 0, 43, None), - Error::::Unknown + Error::::UnknownClass ); assert_noop!( Uniques::cancel_approval(Origin::signed(1), 0, 42, Some(4)), @@ -583,8 +589,14 @@ fn cancel_approval_works_with_force() { assert_ok!(Uniques::mint(Origin::signed(1), 0, 42, 2)); assert_ok!(Uniques::approve_transfer(Origin::signed(2), 0, 42, 3)); - assert_noop!(Uniques::cancel_approval(Origin::root(), 1, 42, None), Error::::Unknown); - assert_noop!(Uniques::cancel_approval(Origin::root(), 0, 43, None), Error::::Unknown); + assert_noop!( + Uniques::cancel_approval(Origin::root(), 1, 42, None), + Error::::UnknownClass + ); + assert_noop!( + Uniques::cancel_approval(Origin::root(), 0, 43, None), + Error::::UnknownClass + ); assert_noop!( Uniques::cancel_approval(Origin::root(), 0, 42, Some(4)), Error::::WrongDelegate From 542d587c3db7e46b6fff423e8efc4f327f7b79a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Tue, 22 Feb 2022 15:15:57 +0100 Subject: [PATCH 520/695] state-machine: Move all functionality from trie backend to the essence (#10904) * state-machine: Move all functionality from trie backend to the essence This is required for some future changes of me and it also makes more sense to have all the functionality inside the essence. Besides that it changes the child root cache to directly cache the hash. * Update primitives/state-machine/src/trie_backend_essence.rs Co-authored-by: cheme * FMT Co-authored-by: cheme --- primitives/state-machine/src/trie_backend.rs | 112 +--------- .../state-machine/src/trie_backend_essence.rs | 210 ++++++++++++++---- primitives/trie/src/lib.rs | 8 +- 3 files changed, 174 insertions(+), 156 deletions(-) diff --git a/primitives/state-machine/src/trie_backend.rs b/primitives/state-machine/src/trie_backend.rs index 37db59416f10..3b985ec2b99f 100644 --- a/primitives/state-machine/src/trie_backend.rs +++ b/primitives/state-machine/src/trie_backend.rs @@ -18,19 +18,13 @@ //! Trie-based state machine backend. use crate::{ - debug, - trie_backend_essence::{Ephemeral, TrieBackendEssence, TrieBackendStorage}, - warn, Backend, StorageKey, StorageValue, + trie_backend_essence::{TrieBackendEssence, TrieBackendStorage}, + Backend, StorageKey, StorageValue, }; -use codec::{Codec, Decode}; +use codec::Codec; use hash_db::Hasher; -use sp_core::storage::{ChildInfo, ChildType, StateVersion}; -use sp_std::{boxed::Box, vec::Vec}; -use sp_trie::{ - child_delta_trie_root, delta_trie_root, empty_child_trie_root, - trie_types::{TrieDB, TrieError}, - LayoutV0, LayoutV1, Trie, -}; +use sp_core::storage::{ChildInfo, StateVersion}; +use sp_std::vec::Vec; /// Patricia trie-based backend. Transaction type is an overlay of changes to commit. pub struct TrieBackend, H: Hasher> { @@ -144,43 +138,11 @@ where } fn pairs(&self) -> Vec<(StorageKey, StorageValue)> { - let collect_all = || -> Result<_, Box>> { - let trie = TrieDB::::new(self.essence(), self.essence.root())?; - let mut v = Vec::new(); - for x in trie.iter()? { - let (key, value) = x?; - v.push((key.to_vec(), value.to_vec())); - } - - Ok(v) - }; - - match collect_all() { - Ok(v) => v, - Err(e) => { - debug!(target: "trie", "Error extracting trie values: {}", e); - Vec::new() - }, - } + self.essence.pairs() } fn keys(&self, prefix: &[u8]) -> Vec { - let collect_all = || -> Result<_, Box>> { - let trie = TrieDB::::new(self.essence(), self.essence.root())?; - let mut v = Vec::new(); - for x in trie.iter()? { - let (key, _) = x?; - if key.starts_with(prefix) { - v.push(key.to_vec()); - } - } - - Ok(v) - }; - - collect_all() - .map_err(|e| debug!(target: "trie", "Error extracting trie keys: {}", e)) - .unwrap_or_default() + self.essence.keys(prefix) } fn storage_root<'a>( @@ -191,25 +153,7 @@ where where H::Out: Ord, { - let mut write_overlay = S::Overlay::default(); - let mut root = *self.essence.root(); - - { - let mut eph = Ephemeral::new(self.essence.backend_storage(), &mut write_overlay); - let res = match state_version { - StateVersion::V0 => - delta_trie_root::, _, _, _, _, _>(&mut eph, root, delta), - StateVersion::V1 => - delta_trie_root::, _, _, _, _, _>(&mut eph, root, delta), - }; - - match res { - Ok(ret) => root = ret, - Err(e) => warn!(target: "trie", "Failed to write to trie: {}", e), - } - } - - (root, write_overlay) + self.essence.storage_root(delta, state_version) } fn child_storage_root<'a>( @@ -221,45 +165,7 @@ where where H::Out: Ord, { - let default_root = match child_info.child_type() { - ChildType::ParentKeyId => empty_child_trie_root::>(), - }; - let mut write_overlay = S::Overlay::default(); - let prefixed_storage_key = child_info.prefixed_storage_key(); - let mut root = match self.storage(prefixed_storage_key.as_slice()) { - Ok(value) => value - .and_then(|r| Decode::decode(&mut &r[..]).ok()) - .unwrap_or_else(|| default_root.clone()), - Err(e) => { - warn!(target: "trie", "Failed to read child storage root: {}", e); - default_root.clone() - }, - }; - - { - let mut eph = Ephemeral::new(self.essence.backend_storage(), &mut write_overlay); - match match state_version { - StateVersion::V0 => child_delta_trie_root::, _, _, _, _, _, _>( - child_info.keyspace(), - &mut eph, - root, - delta, - ), - StateVersion::V1 => child_delta_trie_root::, _, _, _, _, _, _>( - child_info.keyspace(), - &mut eph, - root, - delta, - ), - } { - Ok(ret) => root = ret, - Err(e) => warn!(target: "trie", "Failed to write to trie: {}", e), - } - } - - let is_default = root == default_root; - - (root, is_default, write_overlay) + self.essence.child_storage_root(child_info, delta, state_version) } fn as_trie_backend(&self) -> Option<&TrieBackend> { diff --git a/primitives/state-machine/src/trie_backend_essence.rs b/primitives/state-machine/src/trie_backend_essence.rs index 8f3c27f03c74..e33e50641bbd 100644 --- a/primitives/state-machine/src/trie_backend_essence.rs +++ b/primitives/state-machine/src/trie_backend_essence.rs @@ -23,10 +23,11 @@ use codec::Encode; use hash_db::{self, AsHashDB, HashDB, HashDBRef, Hasher, Prefix}; #[cfg(feature = "std")] use parking_lot::RwLock; -use sp_core::storage::ChildInfo; +use sp_core::storage::{ChildInfo, ChildType, StateVersion}; use sp_std::{boxed::Box, vec::Vec}; use sp_trie::{ - empty_child_trie_root, read_child_trie_value, read_trie_value, + child_delta_trie_root, delta_trie_root, empty_child_trie_root, read_child_trie_value, + read_trie_value, trie_types::{TrieDB, TrieError}, DBValue, KeySpacedDB, PrefixedMemoryDB, Trie, TrieDBIterator, TrieDBKeyIterator, }; @@ -58,12 +59,12 @@ pub trait Storage: Send + Sync { /// Local cache for child root. #[cfg(feature = "std")] -pub(crate) struct Cache { - pub child_root: HashMap, Option>>, +pub(crate) struct Cache { + pub child_root: HashMap, Option>, } #[cfg(feature = "std")] -impl Cache { +impl Cache { fn new() -> Self { Cache { child_root: HashMap::new() } } @@ -75,7 +76,7 @@ pub struct TrieBackendEssence, H: Hasher> { root: H::Out, empty: H::Out, #[cfg(feature = "std")] - pub(crate) cache: Arc>, + pub(crate) cache: Arc>>, } impl, H: Hasher> TrieBackendEssence @@ -130,22 +131,26 @@ where } /// Access the root of the child storage in its parent trie - fn child_root(&self, child_info: &ChildInfo) -> Result> { + fn child_root(&self, child_info: &ChildInfo) -> Result> { #[cfg(feature = "std")] { if let Some(result) = self.cache.read().child_root.get(child_info.storage_key()) { - return Ok(result.clone()) + return Ok(*result) } } - let result = self.storage(child_info.prefixed_storage_key().as_slice())?; + let result = self.storage(child_info.prefixed_storage_key().as_slice())?.map(|r| { + let mut hash = H::Out::default(); + + // root is fetched from DB, not writable by runtime, so it's always valid. + hash.as_mut().copy_from_slice(&r[..]); + + hash + }); #[cfg(feature = "std")] { - self.cache - .write() - .child_root - .insert(child_info.storage_key().to_vec(), result.clone()); + self.cache.write().child_root.insert(child_info.storage_key().to_vec(), result); } Ok(result) @@ -163,15 +168,7 @@ where None => return Ok(None), }; - let mut hash = H::Out::default(); - - if child_root.len() != hash.as_ref().len() { - return Err(format!("Invalid child storage hash at {:?}", child_info.storage_key())) - } - // note: child_root and hash must be same size, panics otherwise. - hash.as_mut().copy_from_slice(&child_root[..]); - - self.next_storage_key_from_root(&hash, Some(child_info), key) + self.next_storage_key_from_root(&child_root, Some(child_info), key) } /// Return next key from main trie or child trie by providing corresponding root. @@ -231,9 +228,10 @@ where child_info: &ChildInfo, key: &[u8], ) -> Result> { - let root = self - .child_root(child_info)? - .unwrap_or_else(|| empty_child_trie_root::>().encode()); + let root = match self.child_root(child_info)? { + Some(root) => root, + None => return Ok(None), + }; let map_e = |e| format!("Trie lookup error: {}", e); @@ -253,19 +251,13 @@ where f: impl FnMut(Vec, Vec) -> bool, allow_missing_nodes: bool, ) -> Result { - let mut child_root; let root = if let Some(child_info) = child_info.as_ref() { - if let Some(fetched_child_root) = self.child_root(child_info)? { - child_root = H::Out::default(); - // root is fetched from DB, not writable by runtime, so it's always valid. - child_root.as_mut().copy_from_slice(fetched_child_root.as_slice()); - - &child_root - } else { - return Ok(true) + match self.child_root(child_info)? { + Some(child_root) => child_root, + None => return Ok(true), } } else { - &self.root + self.root }; self.trie_iter_inner(&root, prefix, f, child_info, start_at, allow_missing_nodes) @@ -279,22 +271,21 @@ where prefix: Option<&[u8]>, mut f: F, ) { - let mut child_root = H::Out::default(); let root = if let Some(child_info) = child_info.as_ref() { - let root_vec = match self.child_root(child_info) { - Ok(v) => v.unwrap_or_else(|| empty_child_trie_root::>().encode()), + match self.child_root(child_info) { + Ok(Some(v)) => v, + // If the child trie doesn't exist, there is no need to continue. + Ok(None) => return, Err(e) => { debug!(target: "trie", "Error while iterating child storage: {}", e); return }, - }; - child_root.as_mut().copy_from_slice(&root_vec); - &child_root + } } else { - &self.root + self.root }; - self.trie_iter_key_inner(root, prefix, |k| f(k), child_info) + self.trie_iter_key_inner(&root, prefix, |k| f(k), child_info) } /// Execute given closure for all keys starting with prefix. @@ -304,15 +295,16 @@ where prefix: &[u8], mut f: impl FnMut(&[u8]), ) { - let root_vec = match self.child_root(child_info) { - Ok(v) => v.unwrap_or_else(|| empty_child_trie_root::>().encode()), + let root = match self.child_root(child_info) { + Ok(Some(v)) => v, + // If the child trie doesn't exist, there is no need to continue. + Ok(None) => return, Err(e) => { debug!(target: "trie", "Error while iterating child storage: {}", e); return }, }; - let mut root = H::Out::default(); - root.as_mut().copy_from_slice(&root_vec); + self.trie_iter_key_inner( &root, Some(prefix), @@ -438,6 +430,130 @@ where false, ); } + + /// Returns all `(key, value)` pairs in the trie. + pub fn pairs(&self) -> Vec<(StorageKey, StorageValue)> { + let collect_all = || -> sp_std::result::Result<_, Box>> { + let trie = TrieDB::::new(self, &self.root)?; + let mut v = Vec::new(); + for x in trie.iter()? { + let (key, value) = x?; + v.push((key.to_vec(), value.to_vec())); + } + + Ok(v) + }; + + match collect_all() { + Ok(v) => v, + Err(e) => { + debug!(target: "trie", "Error extracting trie values: {}", e); + Vec::new() + }, + } + } + + /// Returns all keys that start with the given `prefix`. + pub fn keys(&self, prefix: &[u8]) -> Vec { + let collect_all = || -> sp_std::result::Result<_, Box>> { + let trie = TrieDB::::new(self, &self.root)?; + let mut v = Vec::new(); + for x in trie.iter()? { + let (key, _) = x?; + if key.starts_with(prefix) { + v.push(key.to_vec()); + } + } + + Ok(v) + }; + + collect_all() + .map_err(|e| debug!(target: "trie", "Error extracting trie keys: {}", e)) + .unwrap_or_default() + } + + /// Return the storage root after applying the given `delta`. + pub fn storage_root<'a>( + &self, + delta: impl Iterator)>, + state_version: StateVersion, + ) -> (H::Out, S::Overlay) + where + H::Out: Ord, + { + let mut write_overlay = S::Overlay::default(); + let mut root = self.root; + + { + let mut eph = Ephemeral::new(self.backend_storage(), &mut write_overlay); + let res = match state_version { + StateVersion::V0 => + delta_trie_root::, _, _, _, _, _>(&mut eph, root, delta), + StateVersion::V1 => + delta_trie_root::, _, _, _, _, _>(&mut eph, root, delta), + }; + + match res { + Ok(ret) => root = ret, + Err(e) => warn!(target: "trie", "Failed to write to trie: {}", e), + } + } + + (root, write_overlay) + } + + /// Returns the child storage root for the child trie `child_info` after applying the given + /// `delta`. + pub fn child_storage_root<'a>( + &self, + child_info: &ChildInfo, + delta: impl Iterator)>, + state_version: StateVersion, + ) -> (H::Out, bool, S::Overlay) + where + H::Out: Ord, + { + let default_root = match child_info.child_type() { + ChildType::ParentKeyId => empty_child_trie_root::>(), + }; + let mut write_overlay = S::Overlay::default(); + let mut root = match self.child_root(child_info) { + Ok(Some(hash)) => hash, + Ok(None) => default_root, + Err(e) => { + warn!(target: "trie", "Failed to read child storage root: {}", e); + default_root.clone() + }, + }; + + { + let mut eph = Ephemeral::new(self.backend_storage(), &mut write_overlay); + match match state_version { + StateVersion::V0 => + child_delta_trie_root::, _, _, _, _, _, _>( + child_info.keyspace(), + &mut eph, + root, + delta, + ), + StateVersion::V1 => + child_delta_trie_root::, _, _, _, _, _, _>( + child_info.keyspace(), + &mut eph, + root, + delta, + ), + } { + Ok(ret) => root = ret, + Err(e) => warn!(target: "trie", "Failed to write to trie: {}", e), + } + } + + let is_default = root == default_root; + + (root, is_default, write_overlay) + } } pub(crate) struct Ephemeral<'a, S: 'a + TrieBackendStorage, H: 'a + Hasher> { diff --git a/primitives/trie/src/lib.rs b/primitives/trie/src/lib.rs index f598615be909..c4d4c7210bd4 100644 --- a/primitives/trie/src/lib.rs +++ b/primitives/trie/src/lib.rs @@ -374,18 +374,14 @@ where pub fn read_child_trie_value( keyspace: &[u8], db: &DB, - root_slice: &[u8], + root: &TrieHash, key: &[u8], ) -> Result>, Box>> where DB: hash_db::HashDBRef, { - let mut root = TrieHash::::default(); - // root is fetched from DB, not writable by runtime, so it's always valid. - root.as_mut().copy_from_slice(root_slice); - let db = KeySpacedDB::new(&*db, keyspace); - TrieDB::::new(&db, &root)?.get(key).map(|x| x.map(|val| val.to_vec())) + TrieDB::::new(&db, root)?.get(key).map(|x| x.map(|val| val.to_vec())) } /// Read a value from the child trie with given query. From 46c67a84587a4f02740e956b9736ad0be970c5f9 Mon Sep 17 00:00:00 2001 From: Zeke Mostov Date: Tue, 22 Feb 2022 06:38:34 -0800 Subject: [PATCH 521/695] staking: Remove `SessionInterface` supertrait (#10901) --- frame/staking/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 3738c87dd5b3..22143ff1ee03 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -653,7 +653,7 @@ impl UnappliedSlash { /// Means for interacting with a specialized version of the `session` trait. /// /// This is needed because `Staking` sets the `ValidatorIdOf` of the `pallet_session::Config` -pub trait SessionInterface: frame_system::Config { +pub trait SessionInterface { /// Disable the validator at the given index, returns `false` if the validator was already /// disabled or the index is out of bounds. fn disable_validator(validator_index: u32) -> bool; From 42b2d623d058197aebc3c737fb44fbbf278a85b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Silva?= <123550+andresilva@users.noreply.github.com> Date: Tue, 22 Feb 2022 19:39:16 +0000 Subject: [PATCH 522/695] consensus-slots: cleanup SlotDuration config (#10878) * consensus-slots: cleanup the SlotDuration config * fix tests * address review comments --- Cargo.lock | 2 + bin/node-template/node/src/service.rs | 10 ++- bin/node/cli/src/service.rs | 9 ++- client/consensus/aura/src/lib.rs | 21 +++--- client/consensus/babe/rpc/src/lib.rs | 2 +- client/consensus/babe/src/lib.rs | 72 ++++++++++--------- client/consensus/babe/src/tests.rs | 14 ++-- .../manual-seal/src/consensus/aura.rs | 19 ++--- .../manual-seal/src/consensus/babe.rs | 12 ++-- .../manual-seal/src/consensus/timestamp.rs | 30 +++++--- client/consensus/slots/src/lib.rs | 56 ++------------- primitives/consensus/aura/src/inherents.rs | 7 +- primitives/consensus/aura/src/lib.rs | 27 +------ primitives/consensus/babe/src/inherents.rs | 8 +-- primitives/consensus/babe/src/lib.rs | 9 +-- primitives/consensus/common/src/lib.rs | 6 -- primitives/consensus/slots/Cargo.toml | 8 ++- primitives/consensus/slots/src/lib.rs | 32 +++++++++ primitives/timestamp/src/lib.rs | 8 ++- 19 files changed, 161 insertions(+), 191 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 992a49306f18..517b92c522d4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9627,6 +9627,8 @@ dependencies = [ "serde", "sp-arithmetic", "sp-runtime", + "sp-std", + "sp-timestamp", ] [[package]] diff --git a/bin/node-template/node/src/service.rs b/bin/node-template/node/src/service.rs index 4395718a6d68..fc7dc9b978df 100644 --- a/bin/node-template/node/src/service.rs +++ b/bin/node-template/node/src/service.rs @@ -8,7 +8,6 @@ use sc_finality_grandpa::SharedVoterState; use sc_keystore::LocalKeystore; use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; use sc_telemetry::{Telemetry, TelemetryWorker}; -use sp_consensus::SlotData; use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; use std::{sync::Arc, time::Duration}; @@ -111,7 +110,7 @@ pub fn new_partial( telemetry.as_ref().map(|x| x.handle()), )?; - let slot_duration = sc_consensus_aura::slot_duration(&*client)?.slot_duration(); + let slot_duration = sc_consensus_aura::slot_duration(&*client)?; let import_queue = sc_consensus_aura::import_queue::(ImportQueueParams { @@ -122,7 +121,7 @@ pub fn new_partial( let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); let slot = - sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( + sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( *timestamp, slot_duration, ); @@ -260,7 +259,6 @@ pub fn new_full(mut config: Configuration) -> Result sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()); let slot_duration = sc_consensus_aura::slot_duration(&*client)?; - let raw_slot_duration = slot_duration.slot_duration(); let aura = sc_consensus_aura::start_aura::( StartAuraParams { @@ -273,9 +271,9 @@ pub fn new_full(mut config: Configuration) -> Result let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); let slot = - sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( + sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( *timestamp, - raw_slot_duration, + slot_duration, ); Ok((timestamp, slot)) diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index 81c68bf5d3aa..10d39f278f5f 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -212,7 +212,7 @@ pub fn new_partial( let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); let slot = - sp_consensus_babe::inherents::InherentDataProvider::from_timestamp_and_duration( + sp_consensus_babe::inherents::InherentDataProvider::from_timestamp_and_slot_duration( *timestamp, slot_duration, ); @@ -419,7 +419,7 @@ pub fn new_full_base( let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); let slot = - sp_consensus_babe::inherents::InherentDataProvider::from_timestamp_and_duration( + sp_consensus_babe::inherents::InherentDataProvider::from_timestamp_and_slot_duration( *timestamp, slot_duration, ); @@ -650,7 +650,10 @@ mod tests { .epoch_changes() .shared_data() .epoch_data(&epoch_descriptor, |slot| { - sc_consensus_babe::Epoch::genesis(&babe_link.config(), slot) + sc_consensus_babe::Epoch::genesis( + babe_link.config().genesis_config(), + slot, + ) }) .unwrap(); diff --git a/client/consensus/aura/src/lib.rs b/client/consensus/aura/src/lib.rs index 61c561088314..d3a6b1058940 100644 --- a/client/consensus/aura/src/lib.rs +++ b/client/consensus/aura/src/lib.rs @@ -77,14 +77,11 @@ pub use sp_consensus::SyncOracle; pub use sp_consensus_aura::{ digests::CompatibleDigestItem, inherents::{InherentDataProvider, InherentType as AuraInherent, INHERENT_IDENTIFIER}, - AuraApi, ConsensusLog, AURA_ENGINE_ID, + AuraApi, ConsensusLog, SlotDuration, AURA_ENGINE_ID, }; type AuthorityId

=

::Public; -/// Slot duration type for Aura. -pub type SlotDuration = sc_consensus_slots::SlotDuration; - /// Get the slot duration for Aura. pub fn slot_duration(client: &C) -> CResult where @@ -94,9 +91,7 @@ where C::Api: AuraApi, { let best_block_id = BlockId::Hash(client.usage_info().chain.best_hash); - let slot_duration = client.runtime_api().slot_duration(&best_block_id)?; - - Ok(SlotDuration::new(slot_duration)) + client.runtime_api().slot_duration(&best_block_id).map_err(|err| err.into()) } /// Get slot author for given block along with authorities. @@ -574,7 +569,7 @@ mod tests { use sc_network_test::{Block as TestBlock, *}; use sp_application_crypto::key_types::AURA; use sp_consensus::{ - AlwaysCanAuthor, DisableProofRecording, NoNetwork as DummyOracle, Proposal, SlotData, + AlwaysCanAuthor, DisableProofRecording, NoNetwork as DummyOracle, Proposal, }; use sp_consensus_aura::sr25519::AuthorityPair; use sp_inherents::InherentData; @@ -672,14 +667,14 @@ mod tests { let client = client.as_client(); let slot_duration = slot_duration(&*client).expect("slot duration available"); - assert_eq!(slot_duration.slot_duration().as_millis() as u64, SLOT_DURATION); + assert_eq!(slot_duration.as_millis() as u64, SLOT_DURATION); import_queue::AuraVerifier::new( client, Box::new(|_, _| async { let timestamp = TimestampInherentDataProvider::from_system_time(); - let slot = InherentDataProvider::from_timestamp_and_duration( + let slot = InherentDataProvider::from_timestamp_and_slot_duration( *timestamp, - Duration::from_secs(6), + SlotDuration::from_millis(6000), ); Ok((timestamp, slot)) @@ -762,9 +757,9 @@ mod tests { justification_sync_link: (), create_inherent_data_providers: |_, _| async { let timestamp = TimestampInherentDataProvider::from_system_time(); - let slot = InherentDataProvider::from_timestamp_and_duration( + let slot = InherentDataProvider::from_timestamp_and_slot_duration( *timestamp, - Duration::from_secs(6), + SlotDuration::from_millis(6000), ); Ok((timestamp, slot)) diff --git a/client/consensus/babe/rpc/src/lib.rs b/client/consensus/babe/rpc/src/lib.rs index 88a176e2de10..9dd6424a43a9 100644 --- a/client/consensus/babe/rpc/src/lib.rs +++ b/client/consensus/babe/rpc/src/lib.rs @@ -207,7 +207,7 @@ where &parent.hash(), parent.number().clone(), slot.into(), - |slot| Epoch::genesis(&babe_config, slot), + |slot| Epoch::genesis(babe_config.genesis_config(), slot), ) .map_err(|e| Error::Consensus(ConsensusError::ChainLookup(e.to_string())))? .ok_or(Error::Consensus(ConsensusError::InvalidAuthoritiesSet)) diff --git a/client/consensus/babe/src/lib.rs b/client/consensus/babe/src/lib.rs index 19d9e37cf20a..78fe506dbf34 100644 --- a/client/consensus/babe/src/lib.rs +++ b/client/consensus/babe/src/lib.rs @@ -66,9 +66,7 @@ #![forbid(unsafe_code)] #![warn(missing_docs)] -use std::{ - borrow::Cow, collections::HashMap, convert::TryInto, pin::Pin, sync::Arc, time::Duration, u64, -}; +use std::{borrow::Cow, collections::HashMap, convert::TryInto, pin::Pin, sync::Arc, u64}; use codec::{Decode, Encode}; use futures::{ @@ -106,10 +104,10 @@ use sp_block_builder::BlockBuilder as BlockBuilderApi; use sp_blockchain::{Error as ClientError, HeaderBackend, HeaderMetadata, Result as ClientResult}; use sp_consensus::{ BlockOrigin, CacheKeyId, CanAuthorWith, Environment, Error as ConsensusError, Proposer, - SelectChain, SlotData, + SelectChain, }; use sp_consensus_babe::inherents::BabeInherentData; -use sp_consensus_slots::Slot; +use sp_consensus_slots::{Slot, SlotDuration}; use sp_core::{crypto::ByteArray, ExecutionContext}; use sp_inherents::{CreateInherentDataProviders, InherentData, InherentDataProvider}; use sp_keystore::{SyncCryptoStore, SyncCryptoStorePtr}; @@ -328,17 +326,15 @@ pub struct BabeIntermediate { /// Intermediate key for Babe engine. pub static INTERMEDIATE_KEY: &[u8] = b"babe1"; -/// A slot duration. -/// -/// Create with [`Self::get`]. -// FIXME: Once Rust has higher-kinded types, the duplication between this -// and `super::babe::Config` can be eliminated. -// https://github.com/paritytech/substrate/issues/2434 +/// Configuration for BABE used for defining block verification parameters as +/// well as authoring (e.g. the slot duration). #[derive(Clone)] -pub struct Config(sc_consensus_slots::SlotDuration); +pub struct Config { + genesis_config: BabeGenesisConfiguration, +} impl Config { - /// Fetch the config from the runtime. + /// Create a new config by reading the genesis configuration from the runtime. pub fn get(client: &C) -> ClientResult where C: AuxStore + ProvideRuntimeApi + UsageProvider, @@ -355,7 +351,7 @@ impl Config { let version = runtime_api.api_version::>(&best_block_id)?; - let slot_duration = if version == Some(1) { + let genesis_config = if version == Some(1) { #[allow(deprecated)] { runtime_api.configuration_before_version_2(&best_block_id)?.into() @@ -368,20 +364,17 @@ impl Config { )) }; - Ok(Self(sc_consensus_slots::SlotDuration::new(slot_duration))) + Ok(Config { genesis_config }) } - /// Get the inner slot duration - pub fn slot_duration(&self) -> Duration { - self.0.slot_duration() + /// Get the genesis configuration. + pub fn genesis_config(&self) -> &BabeGenesisConfiguration { + &self.genesis_config } -} -impl std::ops::Deref for Config { - type Target = BabeGenesisConfiguration; - - fn deref(&self) -> &BabeGenesisConfiguration { - &*self.0 + /// Get the slot duration defined in the genesis configuration. + pub fn slot_duration(&self) -> SlotDuration { + SlotDuration::from_millis(self.genesis_config.slot_duration) } } @@ -488,7 +481,6 @@ where { const HANDLE_BUFFER_SIZE: usize = 1024; - let config = babe_link.config; let slot_notification_sinks = Arc::new(Mutex::new(Vec::new())); let worker = BabeSlotWorker { @@ -502,7 +494,7 @@ where keystore, epoch_changes: babe_link.epoch_changes.clone(), slot_notification_sinks: slot_notification_sinks.clone(), - config: config.clone(), + config: babe_link.config.clone(), block_proposal_slot_portion, max_block_proposal_slot_portion, telemetry, @@ -510,7 +502,7 @@ where info!(target: "babe", "👶 Starting BABE Authorship worker"); let inner = sc_consensus_slots::start_slot_worker( - config.0.clone(), + babe_link.config.slot_duration(), select_chain, worker, sync_oracle, @@ -521,7 +513,8 @@ where let (worker_tx, worker_rx) = channel(HANDLE_BUFFER_SIZE); let answer_requests = - answer_requests(worker_rx, config.0, client, babe_link.epoch_changes.clone()); + answer_requests(worker_rx, babe_link.config, client, babe_link.epoch_changes.clone()); + Ok(BabeWorker { inner: Box::pin(future::join(inner, answer_requests).map(|_| ())), slot_notification_sinks, @@ -531,7 +524,7 @@ where async fn answer_requests( mut request_rx: Receiver>, - genesis_config: sc_consensus_slots::SlotDuration, + config: Config, client: Arc, epoch_changes: SharedEpochChanges, ) where @@ -561,7 +554,7 @@ async fn answer_requests( let viable_epoch = epoch_changes .viable_epoch(&epoch_descriptor, |slot| { - Epoch::genesis(&genesis_config, slot) + Epoch::genesis(&config.genesis_config, slot) }) .ok_or_else(|| Error::::FetchEpoch(parent_hash))?; @@ -720,7 +713,9 @@ where fn authorities_len(&self, epoch_descriptor: &Self::EpochData) -> Option { self.epoch_changes .shared_data() - .viable_epoch(&epoch_descriptor, |slot| Epoch::genesis(&self.config, slot)) + .viable_epoch(&epoch_descriptor, |slot| { + Epoch::genesis(&self.config.genesis_config, slot) + }) .map(|epoch| epoch.as_ref().authorities.len()) } @@ -735,7 +730,9 @@ where slot, self.epoch_changes .shared_data() - .viable_epoch(&epoch_descriptor, |slot| Epoch::genesis(&self.config, slot))? + .viable_epoch(&epoch_descriptor, |slot| { + Epoch::genesis(&self.config.genesis_config, slot) + })? .as_ref(), &self.keystore, ); @@ -1165,7 +1162,9 @@ where .map_err(|e| Error::::ForkTree(Box::new(e)))? .ok_or_else(|| Error::::FetchEpoch(parent_hash))?; let viable_epoch = epoch_changes - .viable_epoch(&epoch_descriptor, |slot| Epoch::genesis(&self.config, slot)) + .viable_epoch(&epoch_descriptor, |slot| { + Epoch::genesis(&self.config.genesis_config, slot) + }) .ok_or_else(|| Error::::FetchEpoch(parent_hash))?; // We add one to the current slot to allow for some small drift. @@ -1498,7 +1497,9 @@ where old_epoch_changes = Some((*epoch_changes).clone()); let viable_epoch = epoch_changes - .viable_epoch(&epoch_descriptor, |slot| Epoch::genesis(&self.config, slot)) + .viable_epoch(&epoch_descriptor, |slot| { + Epoch::genesis(&self.config.genesis_config, slot) + }) .ok_or_else(|| { ConsensusError::ClientImport(Error::::FetchEpoch(parent_hash).into()) })?; @@ -1684,7 +1685,8 @@ pub fn block_import( where Client: AuxStore + HeaderBackend + HeaderMetadata, { - let epoch_changes = aux_schema::load_epoch_changes::(&*client, &config)?; + let epoch_changes = + aux_schema::load_epoch_changes::(&*client, &config.genesis_config)?; let link = BabeLink { epoch_changes: epoch_changes.clone(), config: config.clone() }; // NOTE: this isn't entirely necessary, but since we didn't use to prune the diff --git a/client/consensus/babe/src/tests.rs b/client/consensus/babe/src/tests.rs index 7c04dc03c2f2..d38d57b84f5e 100644 --- a/client/consensus/babe/src/tests.rs +++ b/client/consensus/babe/src/tests.rs @@ -143,7 +143,7 @@ impl DummyProposer { &self.parent_hash, self.parent_number, this_slot, - |slot| Epoch::genesis(&self.factory.config, slot), + |slot| Epoch::genesis(self.factory.config.genesis_config(), slot), ) .expect("client has data to find epoch") .expect("can compute epoch for baked block"); @@ -336,9 +336,9 @@ impl TestNetFactory for BabeTestNet { select_chain: longest_chain, create_inherent_data_providers: Box::new(|_, _| async { let timestamp = TimestampInherentDataProvider::from_system_time(); - let slot = InherentDataProvider::from_timestamp_and_duration( + let slot = InherentDataProvider::from_timestamp_and_slot_duration( *timestamp, - Duration::from_secs(6), + SlotDuration::from_millis(6000), ); Ok((timestamp, slot)) @@ -449,9 +449,9 @@ fn run_one_test(mutator: impl Fn(&mut TestHeader, Stage) + Send + Sync + 'static sync_oracle: DummyOracle, create_inherent_data_providers: Box::new(|_, _| async { let timestamp = TimestampInherentDataProvider::from_system_time(); - let slot = InherentDataProvider::from_timestamp_and_duration( + let slot = InherentDataProvider::from_timestamp_and_slot_duration( *timestamp, - Duration::from_secs(6), + SlotDuration::from_millis(6000), ); Ok((timestamp, slot)) @@ -699,12 +699,12 @@ fn importing_block_one_sets_genesis_epoch() { &mut block_import, ); - let genesis_epoch = Epoch::genesis(&data.link.config, 999.into()); + let genesis_epoch = Epoch::genesis(data.link.config.genesis_config(), 999.into()); let epoch_changes = data.link.epoch_changes.shared_data(); let epoch_for_second_block = epoch_changes .epoch_data_for_child_of(descendent_query(&*client), &block_hash, 1, 1000.into(), |slot| { - Epoch::genesis(&data.link.config, slot) + Epoch::genesis(data.link.config.genesis_config(), slot) }) .unwrap() .unwrap(); diff --git a/client/consensus/manual-seal/src/consensus/aura.rs b/client/consensus/manual-seal/src/consensus/aura.rs index 4497a94bdd42..7b5d6720562b 100644 --- a/client/consensus/manual-seal/src/consensus/aura.rs +++ b/client/consensus/manual-seal/src/consensus/aura.rs @@ -22,13 +22,12 @@ use crate::{ConsensusDataProvider, Error}; use sc_client_api::{AuxStore, UsageProvider}; use sc_consensus::BlockImportParams; -use sc_consensus_aura::slot_duration; use sp_api::{ProvideRuntimeApi, TransactionFor}; use sp_blockchain::{HeaderBackend, HeaderMetadata}; use sp_consensus_aura::{ digests::CompatibleDigestItem, sr25519::{AuthorityId, AuthoritySignature}, - AuraApi, + AuraApi, Slot, SlotDuration, }; use sp_inherents::InherentData; use sp_runtime::{traits::Block as BlockT, Digest, DigestItem}; @@ -37,8 +36,8 @@ use std::{marker::PhantomData, sync::Arc}; /// Consensus data provider for Aura. pub struct AuraConsensusDataProvider { - // slot duration in milliseconds - slot_duration: u64, + // slot duration + slot_duration: SlotDuration, // phantom data for required generics _phantom: PhantomData<(B, C)>, } @@ -52,8 +51,8 @@ where /// Creates a new instance of the [`AuraConsensusDataProvider`], requires that `client` /// implements [`sp_consensus_aura::AuraApi`] pub fn new(client: Arc) -> Self { - let slot_duration = - (*slot_duration(&*client).expect("slot_duration is always present; qed.")).get(); + let slot_duration = sc_consensus_aura::slot_duration(&*client) + .expect("slot_duration is always present; qed."); Self { slot_duration, _phantom: PhantomData } } @@ -76,13 +75,15 @@ where _parent: &B::Header, inherents: &InherentData, ) -> Result { - let time_stamp = - *inherents.timestamp_inherent_data()?.expect("Timestamp is always present; qed"); + let timestamp = + inherents.timestamp_inherent_data()?.expect("Timestamp is always present; qed"); + // we always calculate the new slot number based on the current time-stamp and the slot // duration. let digest_item = >::aura_pre_digest( - (time_stamp / self.slot_duration).into(), + Slot::from_timestamp(timestamp, self.slot_duration), ); + Ok(Digest { logs: vec![digest_item] }) } diff --git a/client/consensus/manual-seal/src/consensus/babe.rs b/client/consensus/manual-seal/src/consensus/babe.rs index dd3f9a253478..53cc58df30a3 100644 --- a/client/consensus/manual-seal/src/consensus/babe.rs +++ b/client/consensus/manual-seal/src/consensus/babe.rs @@ -169,7 +169,9 @@ where .ok_or_else(|| sp_consensus::Error::InvalidAuthoritiesSet)?; let epoch = epoch_changes - .viable_epoch(&epoch_descriptor, |slot| Epoch::genesis(&self.config, slot)) + .viable_epoch(&epoch_descriptor, |slot| { + Epoch::genesis(self.config.genesis_config(), slot) + }) .ok_or_else(|| { log::info!(target: "babe", "create_digest: no viable_epoch :("); sp_consensus::Error::InvalidAuthoritiesSet @@ -283,15 +285,17 @@ where let timestamp = inherents .timestamp_inherent_data()? .ok_or_else(|| Error::StringError("No timestamp inherent data".into()))?; - let slot = *timestamp / self.config.slot_duration; + + let slot = Slot::from_timestamp(timestamp, self.config.slot_duration()); + // manually hard code epoch descriptor epoch_descriptor = match epoch_descriptor { ViableEpochDescriptor::Signaled(identifier, _header) => ViableEpochDescriptor::Signaled( identifier, EpochHeader { - start_slot: slot.into(), - end_slot: (slot * self.config.epoch_length).into(), + start_slot: slot, + end_slot: (*slot * self.config.genesis_config().epoch_length).into(), }, ), _ => unreachable!( diff --git a/client/consensus/manual-seal/src/consensus/timestamp.rs b/client/consensus/manual-seal/src/consensus/timestamp.rs index 908d218da05a..e7f4e709ab99 100644 --- a/client/consensus/manual-seal/src/consensus/timestamp.rs +++ b/client/consensus/manual-seal/src/consensus/timestamp.rs @@ -21,8 +21,6 @@ use crate::Error; use sc_client_api::{AuxStore, UsageProvider}; -use sc_consensus_aura::slot_duration; -use sc_consensus_babe::Config; use sp_api::ProvideRuntimeApi; use sp_blockchain::HeaderBackend; use sp_consensus_aura::{ @@ -30,6 +28,7 @@ use sp_consensus_aura::{ AuraApi, }; use sp_consensus_babe::BabeApi; +use sp_consensus_slots::{Slot, SlotDuration}; use sp_inherents::{InherentData, InherentDataProvider, InherentIdentifier}; use sp_runtime::{ generic::BlockId, @@ -53,7 +52,7 @@ pub struct SlotTimestampProvider { // holds the unix millisecnd timestamp for the most recent block unix_millis: atomic::AtomicU64, // configured slot_duration in the runtime - slot_duration: u64, + slot_duration: SlotDuration, } impl SlotTimestampProvider { @@ -64,7 +63,7 @@ impl SlotTimestampProvider { C: AuxStore + HeaderBackend + ProvideRuntimeApi + UsageProvider, C::Api: BabeApi, { - let slot_duration = Config::get(&*client)?.slot_duration; + let slot_duration = sc_consensus_babe::Config::get(&*client)?.slot_duration(); let time = Self::with_header(&client, slot_duration, |header| { let slot_number = *sc_consensus_babe::find_pre_digest::(&header) @@ -83,7 +82,7 @@ impl SlotTimestampProvider { C: AuxStore + HeaderBackend + ProvideRuntimeApi + UsageProvider, C::Api: AuraApi, { - let slot_duration = (*slot_duration(&*client)?).get(); + let slot_duration = sc_consensus_aura::slot_duration(&*client)?; let time = Self::with_header(&client, slot_duration, |header| { let slot_number = *sc_consensus_aura::find_pre_digest::(&header) @@ -94,7 +93,11 @@ impl SlotTimestampProvider { Ok(Self { unix_millis: atomic::AtomicU64::new(time), slot_duration }) } - fn with_header(client: &Arc, slot_duration: u64, func: F) -> Result + fn with_header( + client: &Arc, + slot_duration: SlotDuration, + func: F, + ) -> Result where B: BlockT, C: AuxStore + HeaderBackend + UsageProvider, @@ -110,7 +113,7 @@ impl SlotTimestampProvider { .ok_or_else(|| "best header not found in the db!".to_string())?; let slot = func(header)?; // add the slot duration so there's no collision of slots - (slot * slot_duration) + slot_duration + (slot * slot_duration.as_millis() as u64) + slot_duration.as_millis() as u64 } else { // this is the first block, use the correct time. let now = SystemTime::now(); @@ -123,8 +126,11 @@ impl SlotTimestampProvider { } /// Get the current slot number - pub fn slot(&self) -> u64 { - self.unix_millis.load(atomic::Ordering::SeqCst) / self.slot_duration + pub fn slot(&self) -> Slot { + Slot::from_timestamp( + self.unix_millis.load(atomic::Ordering::SeqCst).into(), + self.slot_duration, + ) } /// Gets the current time stamp. @@ -140,8 +146,10 @@ impl InherentDataProvider for SlotTimestampProvider { inherent_data: &mut InherentData, ) -> Result<(), sp_inherents::Error> { // we update the time here. - let new_time: InherentType = - self.unix_millis.fetch_add(self.slot_duration, atomic::Ordering::SeqCst).into(); + let new_time: InherentType = self + .unix_millis + .fetch_add(self.slot_duration.as_millis() as u64, atomic::Ordering::SeqCst) + .into(); inherent_data.put_data(INHERENT_IDENTIFIER, &new_time)?; Ok(()) } diff --git a/client/consensus/slots/src/lib.rs b/client/consensus/slots/src/lib.rs index 094d065a1c07..f6129943b241 100644 --- a/client/consensus/slots/src/lib.rs +++ b/client/consensus/slots/src/lib.rs @@ -32,15 +32,14 @@ pub use aux_schema::{check_equivocation, MAX_SLOT_CAPACITY, PRUNING_BOUND}; pub use slots::SlotInfo; use slots::Slots; -use codec::{Decode, Encode}; use futures::{future::Either, Future, TryFutureExt}; use futures_timer::Delay; -use log::{debug, error, info, warn}; +use log::{debug, info, warn}; use sc_consensus::{BlockImport, JustificationSyncLink}; use sc_telemetry::{telemetry, TelemetryHandle, CONSENSUS_DEBUG, CONSENSUS_INFO, CONSENSUS_WARN}; use sp_arithmetic::traits::BaseArithmetic; -use sp_consensus::{CanAuthorWith, Proposer, SelectChain, SlotData, SyncOracle}; -use sp_consensus_slots::Slot; +use sp_consensus::{CanAuthorWith, Proposer, SelectChain, SyncOracle}; +use sp_consensus_slots::{Slot, SlotDuration}; use sp_inherents::CreateInherentDataProviders; use sp_runtime::{ generic::BlockId, @@ -459,8 +458,8 @@ impl_inherent_data_provider_ext_tuple!(T, S, A, B, C, D, E, F, G, H, I, J); /// /// Every time a new slot is triggered, `worker.on_slot` is called and the future it returns is /// polled until completion, unless we are major syncing. -pub async fn start_slot_worker( - slot_duration: SlotDuration, +pub async fn start_slot_worker( + slot_duration: SlotDuration, client: C, mut worker: W, mut sync_oracle: SO, @@ -471,15 +470,11 @@ pub async fn start_slot_worker( C: SelectChain, W: SlotWorker, SO: SyncOracle + Send, - T: SlotData + Clone, CIDP: CreateInherentDataProviders + Send, CIDP::InherentDataProviders: InherentDataProviderExt + Send, CAW: CanAuthorWith + Send, { - let SlotDuration(slot_duration) = slot_duration; - - let mut slots = - Slots::new(slot_duration.slot_duration(), create_inherent_data_providers, client); + let mut slots = Slots::new(slot_duration.as_duration(), create_inherent_data_providers, client); loop { let slot_info = match slots.next_slot().await { @@ -523,45 +518,6 @@ pub enum CheckedHeader { Checked(H, S), } -#[derive(Debug, thiserror::Error)] -#[allow(missing_docs)] -pub enum Error -where - T: Debug, -{ - #[error("Slot duration is invalid: {0:?}")] - SlotDurationInvalid(SlotDuration), -} - -/// A slot duration. Create with [`Self::new`]. -#[derive(Clone, Copy, Debug, Encode, Decode, Hash, PartialOrd, Ord, PartialEq, Eq)] -pub struct SlotDuration(T); - -impl Deref for SlotDuration { - type Target = T; - fn deref(&self) -> &T { - &self.0 - } -} - -impl SlotData for SlotDuration { - fn slot_duration(&self) -> std::time::Duration { - self.0.slot_duration() - } -} - -impl SlotDuration { - /// Create a new instance of `Self`. - pub fn new(val: T) -> Self { - Self(val) - } - - /// Returns slot data value. - pub fn get(&self) -> T { - self.0.clone() - } -} - /// A unit type wrapper to express the proportion of a slot. pub struct SlotProportion(f32); diff --git a/primitives/consensus/aura/src/inherents.rs b/primitives/consensus/aura/src/inherents.rs index c3fa43bec02b..ce3d832c78ee 100644 --- a/primitives/consensus/aura/src/inherents.rs +++ b/primitives/consensus/aura/src/inherents.rs @@ -58,12 +58,11 @@ impl InherentDataProvider { /// Creates the inherent data provider by calculating the slot from the given /// `timestamp` and `duration`. - pub fn from_timestamp_and_duration( + pub fn from_timestamp_and_slot_duration( timestamp: sp_timestamp::Timestamp, - duration: std::time::Duration, + slot_duration: sp_consensus_slots::SlotDuration, ) -> Self { - let slot = - InherentType::from((timestamp.as_duration().as_millis() / duration.as_millis()) as u64); + let slot = InherentType::from_timestamp(timestamp, slot_duration); Self { slot } } diff --git a/primitives/consensus/aura/src/lib.rs b/primitives/consensus/aura/src/lib.rs index cec89d0449d8..3e47adf0bf92 100644 --- a/primitives/consensus/aura/src/lib.rs +++ b/primitives/consensus/aura/src/lib.rs @@ -62,7 +62,7 @@ pub mod ed25519 { pub type AuthorityId = app_ed25519::Public; } -pub use sp_consensus_slots::Slot; +pub use sp_consensus_slots::{Slot, SlotDuration}; /// The `ConsensusEngineId` of AuRa. pub const AURA_ENGINE_ID: ConsensusEngineId = [b'a', b'u', b'r', b'a']; @@ -93,28 +93,3 @@ sp_api::decl_runtime_apis! { fn authorities() -> Vec; } } - -/// Aura slot duration. -/// -/// Internally stored as milliseconds. -#[derive(sp_runtime::RuntimeDebug, Encode, Decode, PartialEq, Clone, Copy)] -pub struct SlotDuration(u64); - -impl SlotDuration { - /// Initialize from the given milliseconds. - pub fn from_millis(val: u64) -> Self { - Self(val) - } - - /// Returns the slot duration in milli seconds. - pub fn get(&self) -> u64 { - self.0 - } -} - -#[cfg(feature = "std")] -impl sp_consensus::SlotData for SlotDuration { - fn slot_duration(&self) -> std::time::Duration { - std::time::Duration::from_millis(self.0) - } -} diff --git a/primitives/consensus/babe/src/inherents.rs b/primitives/consensus/babe/src/inherents.rs index 1eadfd85d114..c26dc514ae15 100644 --- a/primitives/consensus/babe/src/inherents.rs +++ b/primitives/consensus/babe/src/inherents.rs @@ -18,7 +18,6 @@ //! Inherents for BABE use sp_inherents::{Error, InherentData, InherentIdentifier}; - use sp_std::result::Result; /// The BABE inherent identifier. @@ -60,12 +59,11 @@ impl InherentDataProvider { /// Creates the inherent data provider by calculating the slot from the given /// `timestamp` and `duration`. - pub fn from_timestamp_and_duration( + pub fn from_timestamp_and_slot_duration( timestamp: sp_timestamp::Timestamp, - duration: std::time::Duration, + slot_duration: sp_consensus_slots::SlotDuration, ) -> Self { - let slot = - InherentType::from((timestamp.as_duration().as_millis() / duration.as_millis()) as u64); + let slot = InherentType::from_timestamp(timestamp, slot_duration); Self { slot } } diff --git a/primitives/consensus/babe/src/lib.rs b/primitives/consensus/babe/src/lib.rs index e7dfc100825d..492d1a9a7238 100644 --- a/primitives/consensus/babe/src/lib.rs +++ b/primitives/consensus/babe/src/lib.rs @@ -79,7 +79,7 @@ pub const MEDIAN_ALGORITHM_CARDINALITY: usize = 1200; // arbitrary suggestion by /// The index of an authority. pub type AuthorityIndex = u32; -pub use sp_consensus_slots::Slot; +pub use sp_consensus_slots::{Slot, SlotDuration}; /// An equivocation proof for multiple block authorships on the same slot (i.e. double vote). pub type EquivocationProof = sp_consensus_slots::EquivocationProof; @@ -237,13 +237,6 @@ impl AllowedSlots { } } -#[cfg(feature = "std")] -impl sp_consensus::SlotData for BabeGenesisConfiguration { - fn slot_duration(&self) -> std::time::Duration { - std::time::Duration::from_millis(self.slot_duration) - } -} - /// Configuration data used by the BABE consensus engine. #[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, MaxEncodedLen, TypeInfo)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] diff --git a/primitives/consensus/common/src/lib.rs b/primitives/consensus/common/src/lib.rs index edf393fa229a..59bbf7618dfc 100644 --- a/primitives/consensus/common/src/lib.rs +++ b/primitives/consensus/common/src/lib.rs @@ -327,9 +327,3 @@ impl CanAuthorWith for NeverCanAuthor { Err("Authoring is always disabled.".to_string()) } } - -/// A type from which a slot duration can be obtained. -pub trait SlotData { - /// Gets the slot duration. - fn slot_duration(&self) -> sp_std::time::Duration; -} diff --git a/primitives/consensus/slots/Cargo.toml b/primitives/consensus/slots/Cargo.toml index 18506980ae85..aed2265bddca 100644 --- a/primitives/consensus/slots/Cargo.toml +++ b/primitives/consensus/slots/Cargo.toml @@ -16,8 +16,10 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } serde = { version = "1.0", features = ["derive"], optional = true } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../runtime" } sp-arithmetic = { version = "4.0.0", default-features = false, path = "../../arithmetic" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../runtime" } +sp-std = { version = "4.0.0", default-features = false, path = "../../std" } +sp-timestamp = { version = "4.0.0-dev", default-features = false, path = "../../timestamp" } [features] default = ["std"] @@ -25,6 +27,8 @@ std = [ "codec/std", "scale-info/std", "serde", - "sp-runtime/std", "sp-arithmetic/std", + "sp-runtime/std", + "sp-std/std", + "sp-timestamp/std", ] diff --git a/primitives/consensus/slots/src/lib.rs b/primitives/consensus/slots/src/lib.rs index e8ab98399414..21b3cad1e716 100644 --- a/primitives/consensus/slots/src/lib.rs +++ b/primitives/consensus/slots/src/lib.rs @@ -21,6 +21,7 @@ use codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; +use sp_timestamp::Timestamp; /// Unit type wrapper that represents a slot. #[derive(Debug, Encode, MaxEncodedLen, Decode, Eq, Clone, Copy, Default, Ord, TypeInfo)] @@ -64,6 +65,11 @@ impl + Copy> core::cmp::PartialOrd for Slot { } impl Slot { + /// Create a new slot by calculating it from the given timestamp and slot duration. + pub const fn from_timestamp(timestamp: Timestamp, slot_duration: SlotDuration) -> Self { + Slot(timestamp.as_millis() / slot_duration.as_millis()) + } + /// Saturating addition. pub fn saturating_add>(self, rhs: T) -> Self { Self(self.0.saturating_add(rhs.into())) @@ -94,6 +100,32 @@ impl From for u64 { } } +/// A slot duration defined in milliseconds. +#[derive(Clone, Copy, Debug, Encode, Decode, Hash, PartialOrd, Ord, PartialEq, Eq, TypeInfo)] +pub struct SlotDuration(u64); + +impl SlotDuration { + /// Initialize from the given milliseconds. + pub const fn from_millis(millis: u64) -> Self { + Self(millis) + } +} + +impl SlotDuration { + /// Returns `self` as a `u64` representing the duration in milliseconds. + pub const fn as_millis(&self) -> u64 { + self.0 + } +} + +#[cfg(feature = "std")] +impl SlotDuration { + /// Returns `self` as [`sp_std::time::Duration`]. + pub const fn as_duration(&self) -> sp_std::time::Duration { + sp_std::time::Duration::from_millis(self.0) + } +} + /// Represents an equivocation proof. An equivocation happens when a validator /// produces more than one block on the same slot. The proof of equivocation /// are the given distinct headers that were signed by the validator and which diff --git a/primitives/timestamp/src/lib.rs b/primitives/timestamp/src/lib.rs index 76725e28ac82..b98a87c37f69 100644 --- a/primitives/timestamp/src/lib.rs +++ b/primitives/timestamp/src/lib.rs @@ -42,10 +42,16 @@ impl Timestamp { } /// Returns `self` as [`Duration`]. - pub fn as_duration(self) -> Duration { + pub const fn as_duration(self) -> Duration { Duration::from_millis(self.0) } + /// Returns `self` as a `u64` representing the elapsed time since the UNIX_EPOCH in + /// milliseconds. + pub const fn as_millis(&self) -> u64 { + self.0 + } + /// Checked subtraction that returns `None` on an underflow. pub fn checked_sub(self, other: Self) -> Option { self.0.checked_sub(other.0).map(Self) From 7869b6d1be96dff7612a9bc65b69bfc996fd4c04 Mon Sep 17 00:00:00 2001 From: driemworks Date: Tue, 22 Feb 2022 20:42:37 -0500 Subject: [PATCH 523/695] add contracts pallet + rpc to runtime --- Cargo.lock | 6 ++ bin/node-template/node/Cargo.toml | 2 + bin/node-template/node/src/rpc.rs | 11 ++- bin/node-template/runtime/Cargo.toml | 16 +++ bin/node-template/runtime/src/lib.rs | 140 ++++++++++++++++++++++++--- 5 files changed, 157 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7ca8d3e85aec..de27efedaa70 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4992,7 +4992,9 @@ dependencies = [ "frame-benchmarking", "frame-benchmarking-cli", "jsonrpc-core", + "node-primitives", "node-template-runtime", + "pallet-contracts-rpc", "pallet-im-online", "pallet-iris-rpc", "pallet-transaction-payment-rpc", @@ -5037,9 +5039,13 @@ dependencies = [ "frame-system-rpc-runtime-api", "hex-literal", "log 0.4.14", + "node-primitives", "pallet-assets", "pallet-aura", "pallet-balances", + "pallet-contracts", + "pallet-contracts-primitives", + "pallet-contracts-rpc-runtime-api", "pallet-grandpa", "pallet-im-online", "pallet-iris-assets", diff --git a/bin/node-template/node/Cargo.toml b/bin/node-template/node/Cargo.toml index 4cf7fef0e47d..f276c2fdb8b0 100644 --- a/bin/node-template/node/Cargo.toml +++ b/bin/node-template/node/Cargo.toml @@ -41,6 +41,7 @@ pallet-im-online = { version = "4.0.0-dev", default-features = false, path = ".. # These dependencies are used for the node template's RPCs jsonrpc-core = "18.0.0" +node-primitives = { version = "2.0.0", path = "../../node/primitives" } sc-rpc = { version = "4.0.0-dev", path = "../../../client/rpc" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sc-rpc-api = { version = "0.10.0-dev", path = "../../../client/rpc-api" } @@ -50,6 +51,7 @@ sc-basic-authorship = { version = "0.10.0-dev", path = "../../../client/basic-au substrate-frame-rpc-system = { version = "4.0.0-dev", path = "../../../utils/frame/rpc/system" } pallet-transaction-payment-rpc = { version = "4.0.0-dev", path = "../../../frame/transaction-payment/rpc/" } pallet-iris-rpc = { version = "4.0.0-dev", path = "../pallets/iris-session/rpc/" } +pallet-contracts-rpc = { version = "4.0.0-dev", path = "../../../frame/contracts/rpc/" } # These dependencies are used for runtime benchmarking frame-benchmarking = { version = "4.0.0-dev", path = "../../../frame/benchmarking" } diff --git a/bin/node-template/node/src/rpc.rs b/bin/node-template/node/src/rpc.rs index 2b61b3f55c9a..6d650bd934f4 100644 --- a/bin/node-template/node/src/rpc.rs +++ b/bin/node-template/node/src/rpc.rs @@ -7,12 +7,14 @@ use std::sync::Arc; -use node_template_runtime::{opaque::Block, AccountId, Balance, Index}; +use node_primitives::{AccountId, Balance, Block, BlockNumber, Hash, Index}; +// use node_template_runtime::{opaque::Block, AccountId, Balance, Index}; pub use sc_rpc_api::DenyUnsafe; use sc_transaction_pool_api::TransactionPool; use sp_api::ProvideRuntimeApi; use sp_block_builder::BlockBuilder; use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata}; +use pallet_contracts_rpc::{Contracts, ContractsApi}; /// Full client dependencies. pub struct FullDeps { @@ -33,6 +35,7 @@ where C::Api: substrate_frame_rpc_system::AccountNonceApi, C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi, C::Api: pallet_iris_rpc::IrisRuntimeApi, + C::Api: pallet_contracts_rpc::ContractsRuntimeApi, C::Api: BlockBuilder, P: TransactionPool + 'static, { @@ -47,11 +50,9 @@ where io.extend_with(TransactionPaymentApi::to_delegate(TransactionPayment::new(client.clone()))); - // Extend this RPC with a custom API by using the following syntax. - // `YourRpcStruct` should have a reference to a client, which is needed - // to call into the runtime. - // `io.extend_with(YourRpcTrait::to_delegate(YourRpcStruct::new(ReferenceToClient, ...)));` io.extend_with(IrisApi::to_delegate(Iris::new(client.clone()))); + + io.extend_with(ContractsApi::to_delegate(Contracts::new(client.clone()))); io } diff --git a/bin/node-template/runtime/Cargo.toml b/bin/node-template/runtime/Cargo.toml index 76f7e95bc6b6..35247ef94a07 100644 --- a/bin/node-template/runtime/Cargo.toml +++ b/bin/node-template/runtime/Cargo.toml @@ -29,7 +29,11 @@ pallet-iris-assets = { version = "1.0.0", default-features = false, path = "../p pallet-iris-session = { version = "1.0.0", default-features = false, path = "../pallets/iris-session" } pallet-timestamp = { version = "4.0.0-dev", default-features = false, path = "../../../frame/timestamp" } pallet-transaction-payment = { version = "4.0.0-dev", default-features = false, path = "../../../frame/transaction-payment" } +pallet-contracts = { version = "4.0.0-dev", default-features = false, path = "../../../frame/contracts" } +pallet-contracts-primitives = { version = "4.0.0-dev", default-features = false, path = "../../../frame/contracts/common/" } +# primitives +node-primitives = { version = "2.0.0", default-features = false, path = "../../node/primitives" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../../frame/system" } frame-executive = { version = "4.0.0-dev", default-features = false, path = "../../../frame/executive" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/api" } @@ -48,9 +52,11 @@ sp-version = { version = "4.0.0-dev", default-features = false, path = "../../.. frame-system-rpc-runtime-api = { version = "4.0.0-dev", default-features = false, path = "../../../frame/system/rpc/runtime-api/" } pallet-transaction-payment-rpc-runtime-api = { version = "4.0.0-dev", default-features = false, path = "../../../frame/transaction-payment/rpc/runtime-api/" } pallet-iris-rpc-runtime-api = { version = "4.0.0-dev", default-features = false, path = "../pallets/iris-session/rpc/runtime-api/" } +pallet-contracts-rpc-runtime-api = { version = "4.0.0-dev", default-features = false, path = "../../../frame/contracts/rpc/runtime-api/" } # Used for runtime benchmarking frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../../../frame/benchmarking", optional = true } frame-system-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../../../frame/system/benchmarking", optional = true } + hex-literal = { version = "0.3.1", optional = true } log = { version = "0.4.14", default-features = false } @@ -92,6 +98,9 @@ std = [ "sp-std/std", "sp-transaction-pool/std", "sp-version/std", + "pallet-contracts/std", + "pallet-contracts-primitives/std", + "pallet-contracts-rpc-runtime-api/std", ] runtime-benchmarks = [ "frame-benchmarking", @@ -105,4 +114,11 @@ runtime-benchmarks = [ "pallet-timestamp/runtime-benchmarks", "pallet-assets/runtime-benchmarks", "sp-runtime/runtime-benchmarks", + "pallet-contracts/runtime-benchmarks", +] +try-runtime = [ + "pallet-contracts/try-runtime", ] +# Make contract callable functions marked as __unstable__ available. Do not enable +# on live chains as those are subject to change. +contracts-unstable-interface = ["pallet-contracts/unstable-interface"] \ No newline at end of file diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index 734166716021..edca788f2f5d 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -31,16 +31,20 @@ use sp_std::prelude::*; #[cfg(feature = "std")] use sp_version::NativeVersion; use sp_version::RuntimeVersion; -use frame_system::EnsureRoot; +use frame_system::{ + limits::{BlockLength, BlockWeights}, + EnsureRoot, +}; use pallet_im_online::sr25519::AuthorityId as ImOnlineId; +use pallet_contracts::weights::WeightInfo; // A few exports that help ease life for downstream crates. pub use frame_support::{ debug, construct_runtime, parameter_types, - traits::{KeyOwnerProofSystem, Randomness, StorageInfo}, + traits::{KeyOwnerProofSystem, Randomness, StorageInfo, Nothing}, weights::{ constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND}, - IdentityFee, Weight, + IdentityFee, Weight, DispatchClass, }, StorageValue, }; @@ -69,7 +73,7 @@ pub type Signature = MultiSignature; pub type AccountId = <::Signer as IdentifyAccount>::AccountId; /// Balance of an account. -pub type Balance = u128; +// pub type Balance = u128; /// Index of a transaction in the chain. pub type Index = u32; @@ -106,6 +110,12 @@ pub mod opaque { } } +use node_primitives::Balance; + +pub const fn deposit(items: u32, bytes: u32) -> Balance { + items as Balance * 15 * CENTS + (bytes as Balance) * 6 * CENTS +} + // To learn more about runtime versioning and what each of the following value means: // https://substrate.dev/docs/en/knowledgebase/runtime/upgrades#runtime-versioning #[sp_version::runtime_version] @@ -147,17 +157,40 @@ pub fn native_version() -> NativeVersion { NativeVersion { runtime_version: VERSION, can_author_with: Default::default() } } + +/// We assume that ~10% of the block weight is consumed by `on_initialize` handlers. +/// This is used to limit the maximal weight of a single extrinsic. +const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10); +/// We allow `Normal` extrinsics to fill up the block up to 75%, the rest can be used +/// by Operational extrinsics. const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); +/// We allow for 2 seconds of compute with a 6 second average block time. +const MAXIMUM_BLOCK_WEIGHT: Weight = 2 * WEIGHT_PER_SECOND; parameter_types! { - pub const Version: RuntimeVersion = VERSION; pub const BlockHashCount: BlockNumber = 2400; - /// We allow for 2 seconds of compute with a 6 second average block time. - pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights - ::with_sensible_defaults(2 * WEIGHT_PER_SECOND, NORMAL_DISPATCH_RATIO); - pub BlockLength: frame_system::limits::BlockLength = frame_system::limits::BlockLength - ::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); - pub const SS58Prefix: u8 = 42; + pub const Version: RuntimeVersion = VERSION; + pub RuntimeBlockLength: BlockLength = + BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); + pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder() + .base_block(BlockExecutionWeight::get()) + .for_class(DispatchClass::all(), |weights| { + weights.base_extrinsic = ExtrinsicBaseWeight::get(); + }) + .for_class(DispatchClass::Normal, |weights| { + weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT); + }) + .for_class(DispatchClass::Operational, |weights| { + weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT); + // Operational transactions have some extra reserved space, so that they + // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`. + weights.reserved = Some( + MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT + ); + }) + .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) + .build_or_panic(); + pub const SS58Prefix: u16 = 42; } // Configure FRAME pallets to include in runtime. @@ -166,9 +199,9 @@ impl frame_system::Config for Runtime { /// The basic call filter to use in dispatchable. type BaseCallFilter = frame_support::traits::Everything; /// Block & extrinsics weights: base values and limits. - type BlockWeights = BlockWeights; + type BlockWeights = RuntimeBlockWeights; /// The maximum length of a block (in bytes). - type BlockLength = BlockLength; + type BlockLength = RuntimeBlockLength; /// The identifier used to distinguish between accounts. type AccountId = AccountId; /// The aggregated dispatch type that is available for extrinsics. @@ -215,6 +248,47 @@ impl frame_system::Config for Runtime { impl pallet_randomness_collective_flip::Config for Runtime {} +parameter_types! { + pub ContractDeposit: Balance = deposit( + 1, + >::contract_info_size(), + ); + pub const MaxValueSize: u32 = 16 * 1024; + // The lazy deletion runs inside on_initialize. + pub DeletionWeightLimit: Weight = AVERAGE_ON_INITIALIZE_RATIO * + RuntimeBlockWeights::get().max_block; + // The weight needed for decoding the queue should be less or equal than a fifth + // of the overall weight dedicated to the lazy deletion. + pub DeletionQueueDepth: u32 = ((DeletionWeightLimit::get() / ( + ::WeightInfo::on_initialize_per_queue_item(1) - + ::WeightInfo::on_initialize_per_queue_item(0) + )) / 5) as u32; + pub Schedule: pallet_contracts::Schedule = Default::default(); +} + +impl pallet_contracts::Config for Runtime { + type Time = Timestamp; + type Randomness = RandomnessCollectiveFlip; + type Currency = Balances; + type Event = Event; + type Call = Call; + /// The safest default is to allow no calls at all. + /// + /// Runtimes should whitelist dispatchables that are allowed to be called from contracts + /// and make sure they are stable. Dispatchables exposed to contracts are not allowed to + /// change because that would break already deployed contracts. The `Call` structure itself + /// is not allowed to change the indices of existing pallets, too. + type CallFilter = Nothing; + type ContractDeposit = ContractDeposit; + type CallStack = [pallet_contracts::Frame; 31]; + type WeightPrice = pallet_transaction_payment::Pallet; + type WeightInfo = pallet_contracts::weights::SubstrateWeight; + type ChainExtension = (); + type DeletionQueueDepth = DeletionQueueDepth; + type DeletionWeightLimit = DeletionWeightLimit; + type Schedule = Schedule; +} + parameter_types! { // TODO: Increase this when done testing pub const MinAuthorities: u32 = 1; @@ -454,6 +528,8 @@ construct_runtime!( Session: pallet_session::{Pallet, Call, Storage, Event, Config}, Assets: pallet_assets::{Pallet, Storage, Event}, ImOnline: pallet_im_online::{Pallet, Call, Storage, Event, ValidateUnsigned, Config}, + RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage}, + Contracts: pallet_contracts::{Pallet, Call, Storage, Event}, Aura: pallet_aura::{Pallet, Config}, Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event}, } @@ -602,6 +678,42 @@ impl_runtime_apis! { } } + + impl pallet_contracts_rpc_runtime_api::ContractsApi< + Block, AccountId, Balance, BlockNumber, Hash, + > + for Runtime + { + fn call( + origin: AccountId, + dest: AccountId, + value: Balance, + gas_limit: u64, + input_data: Vec, + ) -> pallet_contracts_primitives::ContractExecResult { + Contracts::bare_call(origin, dest, value, gas_limit, input_data, true) + } + + fn instantiate( + origin: AccountId, + endowment: Balance, + gas_limit: u64, + code: pallet_contracts_primitives::Code, + data: Vec, + salt: Vec, + ) -> pallet_contracts_primitives::ContractInstantiateResult + { + Contracts::bare_instantiate(origin, endowment, gas_limit, code, data, salt, true) + } + + fn get_storage( + address: AccountId, + key: [u8; 32], + ) -> pallet_contracts_primitives::GetStorageResult { + Contracts::get_storage(address, key) + } + } + impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi for Runtime { fn query_info( uxt: ::Extrinsic, @@ -642,6 +754,7 @@ impl_runtime_apis! { list_benchmark!(list, extra, pallet_assets, Assets); list_benchmark!(list, extra, frame_system, SystemBench::); + list_benchmark!(list, extra, pallet_contracts, Contracts); list_benchmark!(list, extra, pallet_balances, Balances); list_benchmark!(list, extra, pallet_timestamp, Timestamp); list_benchmark!(list, extra, pallet_iris, Iris); @@ -677,6 +790,7 @@ impl_runtime_apis! { add_benchmark!(params, batches, pallet_assets, Assets); add_benchmark!(params, batches, frame_system, SystemBench::); + add_benchmark!(params, batches, pallet_contracts, Contracts); add_benchmark!(params, batches, pallet_balances, Balances); add_benchmark!(params, batches, pallet_timestamp, Timestamp); add_benchmark!(params, batches, pallet_iris_assets, Iris); From f54e1a2f294c9baa1d8d335c18a7c3e49c47cf6b Mon Sep 17 00:00:00 2001 From: Davide Galassi Date: Wed, 23 Feb 2022 10:17:47 +0100 Subject: [PATCH 524/695] Replace libsecp256k1 with k256 in FRAME related code (#10883) * Replace libsecp256k1 with k256 in beefy-mmr * Port of FRAME `contracts` benchmarking from `libsecp256k1` to `k256` * Newtype to allow `Pcg32` rng usage with `k256` in contracts benchmarks * Use `sp-io::crypto` to generate dummy keys in `contracts` bechmarks * More compact code * Cargo fmt * Build `sp-keystore` only for dev profile * Move public key generation back to the `map` --- Cargo.lock | 146 +++++++++++++++++++++++- Cargo.toml | 1 + frame/beefy-mmr/Cargo.toml | 4 +- frame/beefy-mmr/src/lib.rs | 27 +++-- frame/contracts/Cargo.toml | 4 +- frame/contracts/src/benchmarking/mod.rs | 14 +-- frame/contracts/src/tests.rs | 4 +- 7 files changed, 166 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 517b92c522d4..73b56aa6a377 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -437,6 +437,12 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4521f3e3d031370679b3b140beb36dfe4801b09ac77e30c61941f97df3ef28b" +[[package]] +name = "base16ct" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" + [[package]] name = "base58" version = "0.2.0" @@ -474,6 +480,12 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +[[package]] +name = "base64ct" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "874f8444adcb4952a8bc51305c8be95c8ec8237bb0d2e78d2e039f771f8828a0" + [[package]] name = "beef" version = "0.5.1" @@ -1066,6 +1078,12 @@ dependencies = [ "cache-padded", ] +[[package]] +name = "const-oid" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3" + [[package]] name = "constant_time_eq" version = "0.1.5" @@ -1390,6 +1408,18 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +[[package]] +name = "crypto-bigint" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c6a1d5fa1de37e071642dfa44ec552ca5b299adb128fab16138e24b548fd21" +dependencies = [ + "generic-array 0.14.4", + "rand_core 0.6.2", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.2" @@ -1567,6 +1597,15 @@ dependencies = [ "syn", ] +[[package]] +name = "der" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6919815d73839e7ad218de758883aae3a257ba6759ce7a9992501efbb53d705c" +dependencies = [ + "const-oid", +] + [[package]] name = "derive_more" version = "0.99.16" @@ -1749,6 +1788,17 @@ dependencies = [ "memmap2 0.2.1", ] +[[package]] +name = "ecdsa" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0d69ae62e0ce582d56380743515fefaf1a8c70cec685d9677636d7e30ae9dc9" +dependencies = [ + "der", + "elliptic-curve", + "signature", +] + [[package]] name = "ed25519" version = "1.0.3" @@ -1778,6 +1828,24 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +[[package]] +name = "elliptic-curve" +version = "0.11.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25b477563c2bfed38a3b7a60964c49e058b2510ad3f12ba3483fd8f62c2306d6" +dependencies = [ + "base16ct", + "crypto-bigint", + "der", + "ff", + "generic-array 0.14.4", + "group", + "rand_core 0.6.2", + "sec1", + "subtle", + "zeroize", +] + [[package]] name = "enum-as-inner" version = "0.3.3" @@ -1939,6 +2007,16 @@ dependencies = [ "libc", ] +[[package]] +name = "ff" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2958d04124b9f27f175eaeb9a9f383d026098aa837eadd8ba22c11f13a05b9e" +dependencies = [ + "rand_core 0.6.2", + "subtle", +] + [[package]] name = "file-per-thread-logger" version = "0.1.4" @@ -2619,6 +2697,17 @@ dependencies = [ "web-sys", ] +[[package]] +name = "group" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5ac374b108929de78460075f3dc439fa66df9d8fc77e8f12caa5165fcf0c89" +dependencies = [ + "ff", + "rand_core 0.6.2", + "subtle", +] + [[package]] name = "h2" version = "0.3.9" @@ -3403,6 +3492,18 @@ dependencies = [ "jsonrpsee-types 0.8.0", ] +[[package]] +name = "k256" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cc5937366afd3b38071f400d1ce5bd8b1d40b5083cc14e6f8dbcc4032a7f5bb" +dependencies = [ + "cfg-if 1.0.0", + "ecdsa", + "elliptic-curve", + "sec1", +] + [[package]] name = "keccak" version = "0.1.0" @@ -5523,7 +5624,7 @@ dependencies = [ "frame-system", "hex", "hex-literal", - "libsecp256k1", + "k256", "log 0.4.14", "pallet-beefy", "pallet-mmr", @@ -5603,7 +5704,6 @@ dependencies = [ "frame-support", "frame-system", "hex-literal", - "libsecp256k1", "log 0.4.14", "pallet-balances", "pallet-contracts-primitives", @@ -5620,6 +5720,7 @@ dependencies = [ "smallvec 1.7.0", "sp-core", "sp-io", + "sp-keystore", "sp-runtime", "sp-sandbox", "sp-std", @@ -6865,6 +6966,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs8" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cabda3fb821068a9a4fab19a683eac3af12edf0f34b94a8be53c4972b8149d0" +dependencies = [ + "der", + "spki", + "zeroize", +] + [[package]] name = "pkg-config" version = "0.3.19" @@ -9027,6 +9139,19 @@ dependencies = [ "untrusted", ] +[[package]] +name = "sec1" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08da66b8b0965a5555b6bd6639e68ccba85e1e2506f5fbb089e93f8a04e1a2d1" +dependencies = [ + "der", + "generic-array 0.14.4", + "pkcs8", + "subtle", + "zeroize", +] + [[package]] name = "secrecy" version = "0.8.0" @@ -9285,9 +9410,12 @@ dependencies = [ [[package]] name = "signature" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f0242b8e50dd9accdd56170e94ca1ebd223b098eb9c83539a6e367d0f36ae68" +checksum = "02658e48d89f2bec991f9a78e69cfa4c316f8d6a6c4ec12fae1aeb263d486788" +dependencies = [ + "rand_core 0.6.2", +] [[package]] name = "simba" @@ -10226,6 +10354,16 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "spki" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d01ac02a6ccf3e07db148d2be087da624fea0221a16152ed01f0496a6b0a27" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "ss58-registry" version = "1.11.0" diff --git a/Cargo.toml b/Cargo.toml index a31d8011a9f4..d919fc480563 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -250,6 +250,7 @@ hash-db = { opt-level = 3 } hmac = { opt-level = 3 } httparse = { opt-level = 3 } integer-sqrt = { opt-level = 3 } +k256 = { opt-level = 3 } keccak = { opt-level = 3 } libm = { opt-level = 3 } librocksdb-sys = { opt-level = 3 } diff --git a/frame/beefy-mmr/Cargo.toml b/frame/beefy-mmr/Cargo.toml index f381d4c97577..bb30c540ca1c 100644 --- a/frame/beefy-mmr/Cargo.toml +++ b/frame/beefy-mmr/Cargo.toml @@ -10,7 +10,7 @@ repository = "https://github.com/paritytech/substrate" [dependencies] hex = { version = "0.4", optional = true } codec = { version = "2.2.0", package = "parity-scale-codec", default-features = false, features = ["derive"] } -libsecp256k1 = { version = "0.7.0", default-features = false } +k256 = { version = "0.10.2", default-features = false, features = ["arithmetic"] } log = { version = "0.4.13", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } serde = { version = "1.0.136", optional = true } @@ -43,7 +43,7 @@ std = [ "frame-support/std", "frame-system/std", "hex", - "libsecp256k1/std", + "k256/std", "log/std", "pallet-beefy/std", "pallet-mmr-primitives/std", diff --git a/frame/beefy-mmr/src/lib.rs b/frame/beefy-mmr/src/lib.rs index 38d0a6ac9a7f..476589717e06 100644 --- a/frame/beefy-mmr/src/lib.rs +++ b/frame/beefy-mmr/src/lib.rs @@ -72,21 +72,20 @@ where pub struct BeefyEcdsaToEthereum; impl Convert> for BeefyEcdsaToEthereum { fn convert(a: beefy_primitives::crypto::AuthorityId) -> Vec { + use k256::{elliptic_curve::sec1::ToEncodedPoint, PublicKey}; use sp_core::crypto::ByteArray; - let compressed_key = a.as_slice(); - - libsecp256k1::PublicKey::parse_slice( - compressed_key, - Some(libsecp256k1::PublicKeyFormat::Compressed), - ) - // uncompress the key - .map(|pub_key| pub_key.serialize().to_vec()) - // now convert to ETH address - .map(|uncompressed| sp_io::hashing::keccak_256(&uncompressed[1..])[12..].to_vec()) - .map_err(|_| { - log::error!(target: "runtime::beefy", "Invalid BEEFY PublicKey format!"); - }) - .unwrap_or_default() + + PublicKey::from_sec1_bytes(a.as_slice()) + .map(|pub_key| { + // uncompress the key + let uncompressed = pub_key.to_encoded_point(false); + // convert to ETH address + sp_io::hashing::keccak_256(&uncompressed.as_bytes()[1..])[12..].to_vec() + }) + .map_err(|_| { + log::error!(target: "runtime::beefy", "Invalid BEEFY PublicKey format!"); + }) + .unwrap_or_default() } } diff --git a/frame/contracts/Cargo.toml b/frame/contracts/Cargo.toml index f24e393daa2e..5ab1389f65c1 100644 --- a/frame/contracts/Cargo.toml +++ b/frame/contracts/Cargo.toml @@ -28,7 +28,6 @@ smallvec = { version = "1", default-features = false, features = [ wasmi-validation = { version = "0.4", default-features = false } # Only used in benchmarking to generate random contract code -libsecp256k1 = { version = "0.7", optional = true, default-features = false, features = ["hmac", "static-context"] } rand = { version = "0.8", optional = true, default-features = false } rand_pcg = { version = "0.3", optional = true } @@ -56,6 +55,7 @@ pallet-balances = { version = "4.0.0-dev", path = "../balances" } pallet-timestamp = { version = "4.0.0-dev", path = "../timestamp" } pallet-randomness-collective-flip = { version = "4.0.0-dev", path = "../randomness-collective-flip" } pallet-utility = { version = "4.0.0-dev", path = "../utility" } +sp-keystore = { version = "0.11.0", path = "../../primitives/keystore" } [features] default = ["std"] @@ -77,11 +77,9 @@ std = [ "pallet-contracts-proc-macro/full", "log/std", "rand/std", - "libsecp256k1/std", ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", - "libsecp256k1", "rand", "rand_pcg", "unstable-interface", diff --git a/frame/contracts/src/benchmarking/mod.rs b/frame/contracts/src/benchmarking/mod.rs index f5200eef567b..129b4a62581c 100644 --- a/frame/contracts/src/benchmarking/mod.rs +++ b/frame/contracts/src/benchmarking/mod.rs @@ -1866,20 +1866,14 @@ benchmarks! { // It generates different private keys and signatures for the message "Hello world". seal_ecdsa_recover { let r in 0 .. API_BENCHMARK_BATCHES; - use rand::SeedableRng; - let mut rng = rand_pcg::Pcg32::seed_from_u64(123456); let message_hash = sp_io::hashing::blake2_256("Hello world".as_bytes()); + let key_type = sp_core::crypto::KeyTypeId(*b"code"); let signatures = (0..r * API_BENCHMARK_BATCH_SIZE) .map(|i| { - use libsecp256k1::{SecretKey, Message, sign}; - - let private_key = SecretKey::random(&mut rng); - let (signature, recovery_id) = sign(&Message::parse(&message_hash), &private_key); - let mut full_signature = [0; 65]; - full_signature[..64].copy_from_slice(&signature.serialize()); - full_signature[64] = recovery_id.serialize(); - full_signature + let pub_key = sp_io::crypto::ecdsa_generate(key_type, None); + let sig = sp_io::crypto::ecdsa_sign_prehashed(key_type, &pub_key, &message_hash).expect("Generates signature"); + AsRef::<[u8; 65]>::as_ref(&sig).to_vec() }) .collect::>(); let signatures = signatures.iter().flatten().cloned().collect::>(); diff --git a/frame/contracts/src/tests.rs b/frame/contracts/src/tests.rs index cdcf41704347..8add424db089 100644 --- a/frame/contracts/src/tests.rs +++ b/frame/contracts/src/tests.rs @@ -43,12 +43,13 @@ use frame_system::{self as system, EventRecord, Phase}; use pretty_assertions::assert_eq; use sp_core::Bytes; use sp_io::hashing::blake2_256; +use sp_keystore::{testing::KeyStore, KeystoreExt}; use sp_runtime::{ testing::{Header, H256}, traits::{BlakeTwo256, Convert, Hash, IdentityLookup}, AccountId32, }; -use std::cell::RefCell; +use std::{cell::RefCell, sync::Arc}; use crate as pallet_contracts; @@ -328,6 +329,7 @@ impl ExtBuilder { .assimilate_storage(&mut t) .unwrap(); let mut ext = sp_io::TestExternalities::new(t); + ext.register_extension(KeystoreExt(Arc::new(KeyStore::new()))); ext.execute_with(|| System::set_block_number(1)); ext } From b4ba44d21d9e0a5c15013f60e34daf97e70c5865 Mon Sep 17 00:00:00 2001 From: Davide Galassi Date: Wed, 23 Feb 2022 19:58:33 +0100 Subject: [PATCH 525/695] Clean obsolete BABE's weight data (#10748) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Clean obsolete BABE weight data * Take out test assertion from check closure * Optimize metadata access using `HeaderMetadata` trait * Apply suggestions from code review * Introduce finalize and import pre-commit synchronous actions * Do not hold locks between internal methods calls * Remove unused generic bound * Apply suggestions from code review * Register BABE's pre-commit actions on `block_import` instead of `start_babe` * PreCommit actions should be `Fn` instead of `FnMut` * More robust safenet in case of malformed finality notifications Co-authored-by: Bastian Köcher Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> --- client/api/src/backend.rs | 2 + client/api/src/client.rs | 55 +++++++- client/consensus/babe/src/lib.rs | 105 +++++++++++++-- client/consensus/babe/src/tests.rs | 132 ++++++++++++++----- client/service/src/client/client.rs | 129 +++++++++++------- primitives/blockchain/src/header_metadata.rs | 2 +- 6 files changed, 330 insertions(+), 95 deletions(-) diff --git a/client/api/src/backend.rs b/client/api/src/backend.rs index bb2579e4a420..e96616d5416e 100644 --- a/client/api/src/backend.rs +++ b/client/api/src/backend.rs @@ -75,6 +75,8 @@ pub struct ImportSummary { /// Contains information about the block that just got finalized, /// including tree heads that became stale at the moment of finalization. pub struct FinalizeSummary { + /// Last finalized block header. + pub header: Block::Header, /// Blocks that were finalized. /// The last entry is the one that has been explicitly finalized. pub finalized: Vec, diff --git a/client/api/src/client.rs b/client/api/src/client.rs index 9bb212099565..949cc42c1c04 100644 --- a/client/api/src/client.rs +++ b/client/api/src/client.rs @@ -27,7 +27,8 @@ use sp_runtime::{ }; use std::{collections::HashSet, convert::TryFrom, fmt, sync::Arc}; -use crate::{blockchain::Info, notifications::StorageEventStream}; +use crate::{blockchain::Info, notifications::StorageEventStream, FinalizeSummary, ImportSummary}; + use sc_transaction_pool_api::ChainEvent; use sc_utils::mpsc::TracingUnboundedReceiver; use sp_blockchain; @@ -76,6 +77,34 @@ pub trait BlockchainEvents { ) -> sp_blockchain::Result>; } +/// List of operations to be performed on storage aux data. +/// First tuple element is the encoded data key. +/// Second tuple element is the encoded optional data to write. +/// If `None`, the key and the associated data are deleted from storage. +pub type AuxDataOperations = Vec<(Vec, Option>)>; + +/// Callback invoked before committing the operations created during block import. +/// This gives the opportunity to perform auxiliary pre-commit actions and optionally +/// enqueue further storage write operations to be atomically performed on commit. +pub type OnImportAction = + Box) -> AuxDataOperations) + Send>; + +/// Callback invoked before committing the operations created during block finalization. +/// This gives the opportunity to perform auxiliary pre-commit actions and optionally +/// enqueue further storage write operations to be atomically performed on commit. +pub type OnFinalityAction = + Box) -> AuxDataOperations) + Send>; + +/// Interface to perform auxiliary actions before committing a block import or +/// finality operation. +pub trait PreCommitActions { + /// Actions to be performed on block import. + fn register_import_action(&self, op: OnImportAction); + + /// Actions to be performed on block finalization. + fn register_finality_action(&self, op: OnFinalityAction); +} + /// Interface for fetching block data. pub trait BlockBackend { /// Get block body by ID. Returns `None` if the body is not stored. @@ -300,3 +329,27 @@ impl From> for ChainEvent { Self::Finalized { hash: n.hash, tree_route: n.tree_route } } } + +impl From> for FinalityNotification { + fn from(mut summary: FinalizeSummary) -> Self { + let hash = summary.finalized.pop().unwrap_or_default(); + FinalityNotification { + hash, + header: summary.header, + tree_route: Arc::new(summary.finalized), + stale_heads: Arc::new(summary.stale_heads), + } + } +} + +impl From> for BlockImportNotification { + fn from(summary: ImportSummary) -> Self { + BlockImportNotification { + hash: summary.hash, + origin: summary.origin, + header: summary.header, + is_new_best: summary.is_new_best, + tree_route: summary.tree_route.map(Arc::new), + } + } +} diff --git a/client/consensus/babe/src/lib.rs b/client/consensus/babe/src/lib.rs index 78fe506dbf34..0e9f943eca30 100644 --- a/client/consensus/babe/src/lib.rs +++ b/client/consensus/babe/src/lib.rs @@ -66,7 +66,16 @@ #![forbid(unsafe_code)] #![warn(missing_docs)] -use std::{borrow::Cow, collections::HashMap, convert::TryInto, pin::Pin, sync::Arc, u64}; +use std::{ + borrow::Cow, + collections::{HashMap, HashSet}, + convert::TryInto, + future::Future, + pin::Pin, + sync::Arc, + task::{Context, Poll}, + time::Duration, +}; use codec::{Decode, Encode}; use futures::{ @@ -82,7 +91,10 @@ use prometheus_endpoint::Registry; use retain_mut::RetainMut; use schnorrkel::SignatureError; -use sc_client_api::{backend::AuxStore, BlockchainEvents, ProvideUncles, UsageProvider}; +use sc_client_api::{ + backend::AuxStore, AuxDataOperations, BlockchainEvents, FinalityNotification, PreCommitActions, + ProvideUncles, UsageProvider, +}; use sc_consensus::{ block_import::{ BlockCheckParams, BlockImport, BlockImportParams, ForkChoiceStrategy, ImportResult, @@ -98,7 +110,7 @@ use sc_consensus_slots::{ SlotInfo, StorageChanges, }; use sc_telemetry::{telemetry, TelemetryHandle, CONSENSUS_DEBUG, CONSENSUS_TRACE}; -use sp_api::{ApiExt, NumberFor, ProvideRuntimeApi}; +use sp_api::{ApiExt, ProvideRuntimeApi}; use sp_application_crypto::AppKey; use sp_block_builder::BlockBuilder as BlockBuilderApi; use sp_blockchain::{Error as ClientError, HeaderBackend, HeaderMetadata, Result as ClientResult}; @@ -113,7 +125,7 @@ use sp_inherents::{CreateInherentDataProviders, InherentData, InherentDataProvid use sp_keystore::{SyncCryptoStore, SyncCryptoStorePtr}; use sp_runtime::{ generic::{BlockId, OpaqueDigestItemId}, - traits::{Block as BlockT, Header, Zero}, + traits::{Block as BlockT, Header, NumberFor, One, SaturatedConversion, Saturating, Zero}, DigestItem, }; @@ -458,6 +470,7 @@ where C: ProvideRuntimeApi + ProvideUncles + BlockchainEvents + + PreCommitActions + HeaderBackend + HeaderMetadata + Send @@ -501,7 +514,8 @@ where }; info!(target: "babe", "👶 Starting BABE Authorship worker"); - let inner = sc_consensus_slots::start_slot_worker( + + let slot_worker = sc_consensus_slots::start_slot_worker( babe_link.config.slot_duration(), select_chain, worker, @@ -515,13 +529,69 @@ where let answer_requests = answer_requests(worker_rx, babe_link.config, client, babe_link.epoch_changes.clone()); + let inner = future::select(Box::pin(slot_worker), Box::pin(answer_requests)); Ok(BabeWorker { - inner: Box::pin(future::join(inner, answer_requests).map(|_| ())), + inner: Box::pin(inner.map(|_| ())), slot_notification_sinks, handle: BabeWorkerHandle(worker_tx), }) } +// Remove obsolete block's weight data by leveraging finality notifications. +// This includes data for all finalized blocks (excluding the most recent one) +// and all stale branches. +fn aux_storage_cleanup, Block: BlockT>( + client: &C, + notification: &FinalityNotification, +) -> AuxDataOperations { + let mut aux_keys = HashSet::new(); + + // Cleans data for finalized block's ancestors down to, and including, the previously + // finalized one. + + let first_new_finalized = notification.tree_route.get(0).unwrap_or(¬ification.hash); + match client.header_metadata(*first_new_finalized) { + Ok(meta) => { + aux_keys.insert(aux_schema::block_weight_key(meta.parent)); + }, + Err(err) => { + warn!(target: "babe", "header lookup fail while cleaning data for block {}: {}", first_new_finalized.to_string(), err.to_string()); + }, + } + + aux_keys.extend(notification.tree_route.iter().map(aux_schema::block_weight_key)); + + // Cleans data for stale branches. + + // A safenet in case of malformed notification. + let height_limit = notification.header.number().saturating_sub( + notification.tree_route.len().saturated_into::>() + One::one(), + ); + for head in notification.stale_heads.iter() { + let mut hash = *head; + // Insert stale blocks hashes until canonical chain is not reached. + // Soon or late we should hit an element already present within the `aux_keys` set. + while aux_keys.insert(aux_schema::block_weight_key(hash)) { + match client.header_metadata(hash) { + Ok(meta) => { + // This should never happen and must be considered a bug. + if meta.number <= height_limit { + warn!(target: "babe", "unexpected canonical chain state or malformed finality notification"); + break + } + hash = meta.parent; + }, + Err(err) => { + warn!(target: "babe", "header lookup fail while cleaning data for block {}: {}", head.to_string(), err.to_string()); + break + }, + } + } + } + + aux_keys.into_iter().map(|val| (val, None)).collect() +} + async fn answer_requests( mut request_rx: Receiver>, config: Config, @@ -604,7 +674,7 @@ impl BabeWorkerHandle { /// Worker for Babe which implements `Future`. This must be polled. #[must_use] pub struct BabeWorker { - inner: Pin + Send + 'static>>, + inner: Pin + Send + 'static>>, slot_notification_sinks: SlotNotificationSinks, handle: BabeWorkerHandle, } @@ -628,13 +698,10 @@ impl BabeWorker { } } -impl futures::Future for BabeWorker { +impl Future for BabeWorker { type Output = (); - fn poll( - mut self: Pin<&mut Self>, - cx: &mut futures::task::Context, - ) -> futures::task::Poll { + fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll { self.inner.as_mut().poll(cx) } } @@ -857,7 +924,7 @@ where self.telemetry.clone() } - fn proposing_remaining_duration(&self, slot_info: &SlotInfo) -> std::time::Duration { + fn proposing_remaining_duration(&self, slot_info: &SlotInfo) -> Duration { let parent_slot = find_pre_digest::(&slot_info.chain_head).ok().map(|d| d.slot()); sc_consensus_slots::proposing_remaining_duration( @@ -1683,7 +1750,11 @@ pub fn block_import( client: Arc, ) -> ClientResult<(BabeBlockImport, BabeLink)> where - Client: AuxStore + HeaderBackend + HeaderMetadata, + Client: AuxStore + + HeaderBackend + + HeaderMetadata + + PreCommitActions + + 'static, { let epoch_changes = aux_schema::load_epoch_changes::(&*client, &config.genesis_config)?; @@ -1694,6 +1765,12 @@ where // startup rather than waiting until importing the next epoch change block. prune_finalized(client.clone(), &mut epoch_changes.shared_data())?; + let client_clone = client.clone(); + let on_finality = move |summary: &FinalityNotification| { + aux_storage_cleanup(client_clone.as_ref(), summary) + }; + client.register_finality_action(Box::new(on_finality)); + let import = BabeBlockImport::new(client, epoch_changes, wrapped_block_import, config); Ok((import, link)) diff --git a/client/consensus/babe/src/tests.rs b/client/consensus/babe/src/tests.rs index d38d57b84f5e..d2de05bc9195 100644 --- a/client/consensus/babe/src/tests.rs +++ b/client/consensus/babe/src/tests.rs @@ -28,7 +28,7 @@ use log::debug; use rand::RngCore; use rand_chacha::{rand_core::SeedableRng, ChaChaRng}; use sc_block_builder::{BlockBuilder, BlockBuilderProvider}; -use sc_client_api::{backend::TransactionFor, BlockchainEvents}; +use sc_client_api::{backend::TransactionFor, BlockchainEvents, Finalizer}; use sc_consensus::{BoxBlockImport, BoxJustificationImport}; use sc_consensus_slots::BackoffAuthoringOnFinalizedHeadLagging; use sc_keystore::LocalKeystore; @@ -608,8 +608,8 @@ fn propose_and_import_block( slot: Option, proposer_factory: &mut DummyFactory, block_import: &mut BoxBlockImport, -) -> sp_core::H256 { - let mut proposer = futures::executor::block_on(proposer_factory.init(parent)).unwrap(); +) -> Hash { + let mut proposer = block_on(proposer_factory.init(parent)).unwrap(); let slot = slot.unwrap_or_else(|| { let parent_pre_digest = find_pre_digest::(parent).unwrap(); @@ -625,7 +625,7 @@ fn propose_and_import_block( let parent_hash = parent.hash(); - let mut block = futures::executor::block_on(proposer.propose_with(pre_digest)).unwrap().block; + let mut block = block_on(proposer.propose_with(pre_digest)).unwrap().block; let epoch_descriptor = proposer_factory .epoch_changes @@ -673,6 +673,29 @@ fn propose_and_import_block( post_hash } +// Propose and import n valid BABE blocks that are built on top of the given parent. +// The proposer takes care of producing epoch change digests according to the epoch +// duration (which is set to 6 slots in the test runtime). +fn propose_and_import_blocks( + client: &PeersFullClient, + proposer_factory: &mut DummyFactory, + block_import: &mut BoxBlockImport, + parent_id: BlockId, + n: usize, +) -> Vec { + let mut hashes = Vec::with_capacity(n); + let mut parent_header = client.header(&parent_id).unwrap().unwrap(); + + for _ in 0..n { + let block_hash = + propose_and_import_block(&parent_header, None, proposer_factory, block_import); + hashes.push(block_hash); + parent_header = client.header(&BlockId::Hash(block_hash)).unwrap().unwrap(); + } + + hashes +} + #[test] fn importing_block_one_sets_genesis_epoch() { let mut net = BabeTestNet::new(1); @@ -714,8 +737,6 @@ fn importing_block_one_sets_genesis_epoch() { #[test] fn importing_epoch_change_block_prunes_tree() { - use sc_client_api::Finalizer; - let mut net = BabeTestNet::new(1); let peer = net.peer(0); @@ -732,26 +753,8 @@ fn importing_epoch_change_block_prunes_tree() { mutator: Arc::new(|_, _| ()), }; - // This is just boilerplate code for proposing and importing n valid BABE - // blocks that are built on top of the given parent. The proposer takes care - // of producing epoch change digests according to the epoch duration (which - // is set to 6 slots in the test runtime). - let mut propose_and_import_blocks = |parent_id, n| { - let mut hashes = Vec::new(); - let mut parent_header = client.header(&parent_id).unwrap().unwrap(); - - for _ in 0..n { - let block_hash = propose_and_import_block( - &parent_header, - None, - &mut proposer_factory, - &mut block_import, - ); - hashes.push(block_hash); - parent_header = client.header(&BlockId::Hash(block_hash)).unwrap().unwrap(); - } - - hashes + let mut propose_and_import_blocks_wrap = |parent_id, n| { + propose_and_import_blocks(&client, &mut proposer_factory, &mut block_import, parent_id, n) }; // This is the block tree that we're going to use in this test. Each node @@ -766,12 +769,12 @@ fn importing_epoch_change_block_prunes_tree() { // Create and import the canon chain and keep track of fork blocks (A, C, D) // from the diagram above. - let canon_hashes = propose_and_import_blocks(BlockId::Number(0), 30); + let canon_hashes = propose_and_import_blocks_wrap(BlockId::Number(0), 30); // Create the forks - let fork_1 = propose_and_import_blocks(BlockId::Hash(canon_hashes[0]), 10); - let fork_2 = propose_and_import_blocks(BlockId::Hash(canon_hashes[12]), 15); - let fork_3 = propose_and_import_blocks(BlockId::Hash(canon_hashes[18]), 10); + let fork_1 = propose_and_import_blocks_wrap(BlockId::Hash(canon_hashes[0]), 10); + let fork_2 = propose_and_import_blocks_wrap(BlockId::Hash(canon_hashes[12]), 15); + let fork_3 = propose_and_import_blocks_wrap(BlockId::Hash(canon_hashes[18]), 10); // We should be tracking a total of 9 epochs in the fork tree assert_eq!(epoch_changes.shared_data().tree().iter().count(), 9); @@ -782,7 +785,7 @@ fn importing_epoch_change_block_prunes_tree() { // We finalize block #13 from the canon chain, so on the next epoch // change the tree should be pruned, to not contain F (#7). client.finalize_block(BlockId::Hash(canon_hashes[12]), None, false).unwrap(); - propose_and_import_blocks(BlockId::Hash(client.chain_info().best_hash), 7); + propose_and_import_blocks_wrap(BlockId::Hash(client.chain_info().best_hash), 7); // at this point no hashes from the first fork must exist on the tree assert!(!epoch_changes @@ -809,7 +812,7 @@ fn importing_epoch_change_block_prunes_tree() { // finalizing block #25 from the canon chain should prune out the second fork client.finalize_block(BlockId::Hash(canon_hashes[24]), None, false).unwrap(); - propose_and_import_blocks(BlockId::Hash(client.chain_info().best_hash), 8); + propose_and_import_blocks_wrap(BlockId::Hash(client.chain_info().best_hash), 8); // at this point no hashes from the second fork must exist on the tree assert!(!epoch_changes @@ -894,3 +897,68 @@ fn babe_transcript_generation_match() { }; debug_assert!(test(orig_transcript) == test(transcript_from_data(new_transcript))); } + +#[test] +fn obsolete_blocks_aux_data_cleanup() { + let mut net = BabeTestNet::new(1); + + let peer = net.peer(0); + let data = peer.data.as_ref().expect("babe link set up during initialization"); + let client = peer.client().as_client(); + + // Register the handler (as done by `babe_start`) + let client_clone = client.clone(); + let on_finality = move |summary: &FinalityNotification| { + aux_storage_cleanup(client_clone.as_ref(), summary) + }; + client.register_finality_action(Box::new(on_finality)); + + let mut proposer_factory = DummyFactory { + client: client.clone(), + config: data.link.config.clone(), + epoch_changes: data.link.epoch_changes.clone(), + mutator: Arc::new(|_, _| ()), + }; + + let mut block_import = data.block_import.lock().take().expect("import set up during init"); + + let mut propose_and_import_blocks_wrap = |parent_id, n| { + propose_and_import_blocks(&client, &mut proposer_factory, &mut block_import, parent_id, n) + }; + + let aux_data_check = |hashes: &[Hash], expected: bool| { + hashes.iter().all(|hash| { + aux_schema::load_block_weight(&*peer.client().as_backend(), hash) + .unwrap() + .is_some() == expected + }) + }; + + // Create the following test scenario: + // + // /-----B3 --- B4 ( < fork2 ) + // G --- A1 --- A2 --- A3 --- A4 ( < fork1 ) + // \-----C4 --- C5 ( < fork3 ) + + let fork1_hashes = propose_and_import_blocks_wrap(BlockId::Number(0), 4); + let fork2_hashes = propose_and_import_blocks_wrap(BlockId::Number(2), 2); + let fork3_hashes = propose_and_import_blocks_wrap(BlockId::Number(3), 2); + + // Check that aux data is present for all but the genesis block. + assert!(aux_data_check(&[client.chain_info().genesis_hash], false)); + assert!(aux_data_check(&fork1_hashes, true)); + assert!(aux_data_check(&fork2_hashes, true)); + assert!(aux_data_check(&fork3_hashes, true)); + + // Finalize A3 + client.finalize_block(BlockId::Number(3), None, true).unwrap(); + + // Wiped: A1, A2 + assert!(aux_data_check(&fork1_hashes[..2], false)); + // Present: A3, A4 + assert!(aux_data_check(&fork1_hashes[2..], true)); + // Wiped: B3, B4 + assert!(aux_data_check(&fork2_hashes, false)); + // Present C4, C5 + assert!(aux_data_check(&fork3_hashes, true)); +} diff --git a/client/service/src/client/client.rs b/client/service/src/client/client.rs index 071af36a23f9..8497c34f5abb 100644 --- a/client/service/src/client/client.rs +++ b/client/service/src/client/client.rs @@ -36,11 +36,12 @@ use sc_client_api::{ client::{ BadBlocks, BlockBackend, BlockImportNotification, BlockOf, BlockchainEvents, ClientInfo, FinalityNotification, FinalityNotifications, ForkBlocks, ImportNotifications, - ProvideUncles, + PreCommitActions, ProvideUncles, }, execution_extensions::ExecutionExtensions, notifications::{StorageEventStream, StorageNotifications}, - CallExecutor, ExecutorProvider, KeyIterator, ProofProvider, UsageProvider, + CallExecutor, ExecutorProvider, KeyIterator, OnFinalityAction, OnImportAction, ProofProvider, + UsageProvider, }; use sc_consensus::{ BlockCheckParams, BlockImportParams, ForkChoiceStrategy, ImportResult, StateAction, @@ -76,8 +77,9 @@ use sp_runtime::{ }; use sp_state_machine::{ prove_child_read, prove_range_read_with_child_with_size, prove_read, - read_range_proof_check_with_child_on_proving_backend, Backend as StateBackend, KeyValueStates, - KeyValueStorageLevel, MAX_NESTED_TRIE_DEPTH, + read_range_proof_check_with_child_on_proving_backend, Backend as StateBackend, + ChildStorageCollection, KeyValueStates, KeyValueStorageLevel, StorageCollection, + MAX_NESTED_TRIE_DEPTH, }; use sp_trie::{CompactProof, StorageProof}; use std::{ @@ -108,7 +110,13 @@ where storage_notifications: Mutex>, import_notification_sinks: NotificationSinks>, finality_notification_sinks: NotificationSinks>, - // holds the block hash currently being imported. TODO: replace this with block queue + // Collects auxiliary operations to be performed atomically together with + // block import operations. + import_actions: Mutex>>, + // Collects auxiliary operations to be performed atomically together with + // block finalization operations. + finality_actions: Mutex>>, + // Holds the block hash currently being imported. TODO: replace this with block queue. importing_block: RwLock>, block_rules: BlockRules, execution_extensions: ExecutionExtensions, @@ -279,11 +287,32 @@ where let r = f(&mut op)?; - let ClientImportOperation { op, notify_imported, notify_finalized } = op; + let ClientImportOperation { mut op, notify_imported, notify_finalized } = op; + + let finality_notification = notify_finalized.map(|summary| summary.into()); + let (import_notification, storage_changes) = match notify_imported { + Some(mut summary) => { + let storage_changes = summary.storage_changes.take(); + (Some(summary.into()), storage_changes) + }, + None => (None, None), + }; + + if let Some(ref notification) = finality_notification { + for action in self.finality_actions.lock().iter_mut() { + op.insert_aux(action(notification))?; + } + } + if let Some(ref notification) = import_notification { + for action in self.import_actions.lock().iter_mut() { + op.insert_aux(action(notification))?; + } + } + self.backend.commit_operation(op)?; - self.notify_finalized(notify_finalized)?; - self.notify_imported(notify_imported)?; + self.notify_finalized(finality_notification)?; + self.notify_imported(import_notification, storage_changes)?; Ok(r) }; @@ -367,6 +396,8 @@ where storage_notifications: Mutex::new(StorageNotifications::new(prometheus_registry)), import_notification_sinks: Default::default(), finality_notification_sinks: Default::default(), + import_actions: Default::default(), + finality_actions: Default::default(), importing_block: Default::default(), block_rules: BlockRules::new(fork_blocks, bad_blocks), execution_extensions, @@ -686,12 +717,21 @@ where // We only notify when we are already synced to the tip of the chain // or if this import triggers a re-org if make_notifications || tree_route.is_some() { + let header = import_headers.into_post(); if finalized { let mut summary = match operation.notify_finalized.take() { - Some(summary) => summary, - None => FinalizeSummary { finalized: Vec::new(), stale_heads: Vec::new() }, + Some(mut summary) => { + summary.header = header.clone(); + summary.finalized.push(hash); + summary + }, + None => FinalizeSummary { + header: header.clone(), + finalized: vec![hash], + stale_heads: Vec::new(), + }, }; - summary.finalized.push(hash); + if parent_exists { // Add to the stale list all heads that are branching from parent besides our // current `head`. @@ -718,7 +758,7 @@ where operation.notify_imported = Some(ImportSummary { hash, origin, - header: import_headers.into_post(), + header, is_new_best, storage_changes, tree_route, @@ -863,7 +903,7 @@ where .backend .blockchain() .number(last_finalized)? - .expect("Finalized block expected to be onchain; qed"); + .expect("Previous finalized block expected to be onchain; qed"); let mut stale_heads = Vec::new(); for head in self.backend.blockchain().leaves()? { let route_from_finalized = @@ -884,7 +924,12 @@ where stale_heads.push(head); } } - operation.notify_finalized = Some(FinalizeSummary { finalized, stale_heads }); + let header = self + .backend + .blockchain() + .header(BlockId::Hash(block))? + .expect("Finalized block expected to be onchain; qed"); + operation.notify_finalized = Some(FinalizeSummary { header, finalized, stale_heads }); } Ok(()) @@ -892,11 +937,11 @@ where fn notify_finalized( &self, - notify_finalized: Option>, + notification: Option>, ) -> sp_blockchain::Result<()> { let mut sinks = self.finality_notification_sinks.lock(); - let mut notify_finalized = match notify_finalized { + let notification = match notification { Some(notify_finalized) => notify_finalized, None => { // Cleanup any closed finality notification sinks @@ -907,30 +952,14 @@ where }, }; - let last = notify_finalized.finalized.pop().expect( - "At least one finalized block shall exist within a valid finalization summary; qed", - ); - - let header = self.header(&BlockId::Hash(last))?.expect( - "Header already known to exist in DB because it is indicated in the tree route; \ - qed", - ); - telemetry!( self.telemetry; SUBSTRATE_INFO; "notify.finalized"; - "height" => format!("{}", header.number()), - "best" => ?last, + "height" => format!("{}", notification.header.number()), + "best" => ?notification.hash, ); - let notification = FinalityNotification { - hash: last, - header, - tree_route: Arc::new(notify_finalized.finalized), - stale_heads: Arc::new(notify_finalized.stale_heads), - }; - sinks.retain(|sink| sink.unbounded_send(notification.clone()).is_ok()); Ok(()) @@ -938,12 +967,13 @@ where fn notify_imported( &self, - notify_import: Option>, + notification: Option>, + storage_changes: Option<(StorageCollection, ChildStorageCollection)>, ) -> sp_blockchain::Result<()> { - let notify_import = match notify_import { + let notification = match notification { Some(notify_import) => notify_import, None => { - // cleanup any closed import notification sinks since we won't + // Cleanup any closed import notification sinks since we won't // be sending any notifications below which would remove any // closed sinks. this is necessary since during initial sync we // won't send any import notifications which could lead to a @@ -954,23 +984,15 @@ where }, }; - if let Some(storage_changes) = notify_import.storage_changes { + if let Some(storage_changes) = storage_changes { // TODO [ToDr] How to handle re-orgs? Should we re-emit all storage changes? self.storage_notifications.lock().trigger( - ¬ify_import.hash, + ¬ification.hash, storage_changes.0.into_iter(), storage_changes.1.into_iter().map(|(sk, v)| (sk, v.into_iter())), ); } - let notification = BlockImportNotification:: { - hash: notify_import.hash, - origin: notify_import.origin, - header: notify_import.header, - is_new_best: notify_import.is_new_best, - tree_route: notify_import.tree_route.map(Arc::new), - }; - self.import_notification_sinks .lock() .retain(|sink| sink.unbounded_send(notification.clone()).is_ok()); @@ -1892,6 +1914,19 @@ where } } +impl PreCommitActions for Client +where + Block: BlockT, +{ + fn register_import_action(&self, action: OnImportAction) { + self.import_actions.lock().push(action); + } + + fn register_finality_action(&self, action: OnFinalityAction) { + self.finality_actions.lock().push(action); + } +} + impl BlockchainEvents for Client where E: CallExecutor, diff --git a/primitives/blockchain/src/header_metadata.rs b/primitives/blockchain/src/header_metadata.rs index 6e8dc562473d..c21c82b9fbc2 100644 --- a/primitives/blockchain/src/header_metadata.rs +++ b/primitives/blockchain/src/header_metadata.rs @@ -206,7 +206,7 @@ impl TreeRoute { /// Handles header metadata: hash, number, parent hash, etc. pub trait HeaderMetadata { /// Error used in case the header metadata is not found. - type Error; + type Error: std::error::Error; fn header_metadata( &self, From c48f33d16edc44e12be0b54d66459da430a6d8ff Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Wed, 23 Feb 2022 20:58:53 +0100 Subject: [PATCH 526/695] Factor DB weights out into their own files (#10908) * Factor DB weights out into their own files Signed-off-by: Oliver Tale-Yazdi * Review fixes Signed-off-by: Oliver Tale-Yazdi * Fix CI Signed-off-by: Oliver Tale-Yazdi * Weights in own mod Signed-off-by: Oliver Tale-Yazdi --- frame/support/src/weights.rs | 22 +++---- frame/support/src/weights/paritydb_weights.rs | 63 +++++++++++++++++++ frame/support/src/weights/rocksdb_weights.rs | 63 +++++++++++++++++++ 3 files changed, 135 insertions(+), 13 deletions(-) create mode 100644 frame/support/src/weights/paritydb_weights.rs create mode 100644 frame/support/src/weights/rocksdb_weights.rs diff --git a/frame/support/src/weights.rs b/frame/support/src/weights.rs index 65087c85d326..6c2e693eb476 100644 --- a/frame/support/src/weights.rs +++ b/frame/support/src/weights.rs @@ -127,6 +127,9 @@ //! - Ubuntu 19.10 (GNU/Linux 5.3.0-18-generic x86_64) //! - rustc 1.42.0 (b8cedc004 2020-03-09) +mod paritydb_weights; +mod rocksdb_weights; + use crate::dispatch::{DispatchError, DispatchErrorWithPostInfo, DispatchResultWithPostInfo}; use codec::{Decode, Encode}; use scale_info::TypeInfo; @@ -152,7 +155,7 @@ pub type Weight = u64; /// These constants are specific to FRAME, and the current implementation of its various components. /// For example: FRAME System, FRAME Executive, our FRAME support libraries, etc... pub mod constants { - use super::{RuntimeDbWeight, Weight}; + use super::Weight; use crate::parameter_types; pub const WEIGHT_PER_SECOND: Weight = 1_000_000_000_000; @@ -165,19 +168,12 @@ pub mod constants { pub const BlockExecutionWeight: Weight = 5 * WEIGHT_PER_MILLIS; /// Executing 10,000 System remarks (no-op) txs takes ~1.26 seconds -> ~125 µs per tx pub const ExtrinsicBaseWeight: Weight = 125 * WEIGHT_PER_MICROS; - /// By default, Substrate uses RocksDB, so this will be the weight used throughout - /// the runtime. - pub const RocksDbWeight: RuntimeDbWeight = RuntimeDbWeight { - read: 25 * WEIGHT_PER_MICROS, // ~25 µs @ 200,000 items - write: 100 * WEIGHT_PER_MICROS, // ~100 µs @ 200,000 items - }; - /// ParityDB can be enabled with a feature flag, but is still experimental. These weights - /// are available for brave runtime engineers who may want to try this out as default. - pub const ParityDbWeight: RuntimeDbWeight = RuntimeDbWeight { - read: 8 * WEIGHT_PER_MICROS, // ~8 µs @ 200,000 items - write: 50 * WEIGHT_PER_MICROS, // ~50 µs @ 200,000 items - }; } + + // Expose the DB weights. + pub use super::{ + paritydb_weights::constants::ParityDbWeight, rocksdb_weights::constants::RocksDbWeight, + }; } /// Means of weighing some particular kind of data (`T`). diff --git a/frame/support/src/weights/paritydb_weights.rs b/frame/support/src/weights/paritydb_weights.rs new file mode 100644 index 000000000000..572187ba78a9 --- /dev/null +++ b/frame/support/src/weights/paritydb_weights.rs @@ -0,0 +1,63 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +pub mod constants { + use frame_support::{ + parameter_types, + weights::{constants, RuntimeDbWeight}, + }; + + parameter_types! { + /// ParityDB can be enabled with a feature flag, but is still experimental. These weights + /// are available for brave runtime engineers who may want to try this out as default. + pub const ParityDbWeight: RuntimeDbWeight = RuntimeDbWeight { + read: 8_000 * constants::WEIGHT_PER_NANOS, + write: 50_000 * constants::WEIGHT_PER_NANOS, + }; + } + + #[cfg(test)] + mod test_db_weights { + use super::constants::ParityDbWeight as W; + use frame_support::weights::constants; + + /// Checks that all weights exist and have sane values. + // NOTE: If this test fails but you are sure that the generated values are fine, + // you can delete it. + #[test] + fn sane() { + // At least 1 µs. + assert!( + W::get().reads(1) >= constants::WEIGHT_PER_MICROS, + "Read weight should be at least 1 µs." + ); + assert!( + W::get().writes(1) >= constants::WEIGHT_PER_MICROS, + "Write weight should be at least 1 µs." + ); + // At most 1 ms. + assert!( + W::get().reads(1) <= constants::WEIGHT_PER_MILLIS, + "Read weight should be at most 1 ms." + ); + assert!( + W::get().writes(1) <= constants::WEIGHT_PER_MILLIS, + "Write weight should be at most 1 ms." + ); + } + } +} diff --git a/frame/support/src/weights/rocksdb_weights.rs b/frame/support/src/weights/rocksdb_weights.rs new file mode 100644 index 000000000000..f37964dcbd82 --- /dev/null +++ b/frame/support/src/weights/rocksdb_weights.rs @@ -0,0 +1,63 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +pub mod constants { + use frame_support::{ + parameter_types, + weights::{constants, RuntimeDbWeight}, + }; + + parameter_types! { + /// By default, Substrate uses RocksDB, so this will be the weight used throughout + /// the runtime. + pub const RocksDbWeight: RuntimeDbWeight = RuntimeDbWeight { + read: 25_000 * constants::WEIGHT_PER_NANOS, + write: 100_000 * constants::WEIGHT_PER_NANOS, + }; + } + + #[cfg(test)] + mod test_db_weights { + use super::constants::RocksDbWeight as W; + use frame_support::weights::constants; + + /// Checks that all weights exist and have sane values. + // NOTE: If this test fails but you are sure that the generated values are fine, + // you can delete it. + #[test] + fn sane() { + // At least 1 µs. + assert!( + W::get().reads(1) >= constants::WEIGHT_PER_MICROS, + "Read weight should be at least 1 µs." + ); + assert!( + W::get().writes(1) >= constants::WEIGHT_PER_MICROS, + "Write weight should be at least 1 µs." + ); + // At most 1 ms. + assert!( + W::get().reads(1) <= constants::WEIGHT_PER_MILLIS, + "Read weight should be at most 1 ms." + ); + assert!( + W::get().writes(1) <= constants::WEIGHT_PER_MILLIS, + "Write weight should be at most 1 ms." + ); + } + } +} From 19460bc5263994321a595f6e35501882cdba6f05 Mon Sep 17 00:00:00 2001 From: Koute Date: Thu, 24 Feb 2022 20:30:25 +0900 Subject: [PATCH 527/695] Get rid of unnecessary use of `async-std` in non-test code (#10891) --- Cargo.lock | 29 ------------ client/network/Cargo.toml | 2 +- utils/prometheus/Cargo.toml | 1 - utils/prometheus/src/lib.rs | 28 +++--------- utils/prometheus/src/networking.rs | 71 ------------------------------ 5 files changed, 7 insertions(+), 124 deletions(-) delete mode 100644 utils/prometheus/src/networking.rs diff --git a/Cargo.lock b/Cargo.lock index 73b56aa6a377..b7e4210efdd4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -254,23 +254,6 @@ dependencies = [ "event-listener", ] -[[package]] -name = "async-process" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b21b63ab5a0db0369deb913540af2892750e42d949faacc7a61495ac418a1692" -dependencies = [ - "async-io", - "blocking", - "cfg-if 1.0.0", - "event-listener", - "futures-lite", - "libc", - "once_cell", - "signal-hook", - "winapi 0.3.9", -] - [[package]] name = "async-std" version = "1.10.0" @@ -282,7 +265,6 @@ dependencies = [ "async-global-executor", "async-io", "async-lock", - "async-process", "crossbeam-utils 0.8.5", "futures-channel", "futures-core", @@ -9389,16 +9371,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42a568c8f2cd051a4d283bd6eb0343ac214c1b0f1ac19f93e1175b2dee38c73d" -[[package]] -name = "signal-hook" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef33d6d0cd06e0840fba9985aab098c147e67e05cee14d412d3345ed14ff30ac" -dependencies = [ - "libc", - "signal-hook-registry", -] - [[package]] name = "signal-hook-registry" version = "1.3.0" @@ -10515,7 +10487,6 @@ dependencies = [ name = "substrate-prometheus-endpoint" version = "0.10.0-dev" dependencies = [ - "async-std", "futures-util", "hyper 0.14.16", "log 0.4.14", diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index 86a038028047..7a978d0740f6 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -18,7 +18,6 @@ prost-build = "0.9" [dependencies] async-trait = "0.1" -async-std = "1.10.0" bitflags = "1.3.2" cid = "0.6.0" bytes = "1" @@ -75,6 +74,7 @@ sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } substrate-test-runtime = { version = "2.0.0", path = "../../test-utils/runtime" } substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } tempfile = "3.1.0" +async-std = "1.10.0" [features] default = [] diff --git a/utils/prometheus/Cargo.toml b/utils/prometheus/Cargo.toml index 264cc44d1602..fb998d2809fa 100644 --- a/utils/prometheus/Cargo.toml +++ b/utils/prometheus/Cargo.toml @@ -17,7 +17,6 @@ log = "0.4.8" prometheus = { version = "0.13.0", default-features = false } futures-util = { version = "0.3.19", default-features = false, features = ["io"] } thiserror = "1.0" -async-std = { version = "1.10.0", features = ["unstable"] } tokio = { version = "1.15", features = ["parking_lot"] } hyper = { version = "0.14.16", default-features = false, features = ["http1", "server", "tcp"] } diff --git a/utils/prometheus/src/lib.rs b/utils/prometheus/src/lib.rs index 3d28d9cd6f1c..1892741eff5d 100644 --- a/utils/prometheus/src/lib.rs +++ b/utils/prometheus/src/lib.rs @@ -15,7 +15,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -use futures_util::future::Future; use hyper::{ http::StatusCode, server::Server, @@ -34,7 +33,6 @@ pub use prometheus::{ use prometheus::{core::Collector, Encoder, TextEncoder}; use std::net::SocketAddr; -mod networking; mod sourced; pub use sourced::{MetricSource, SourcedCounter, SourcedGauge, SourcedMetric}; @@ -85,23 +83,10 @@ async fn request_metrics(req: Request, registry: Registry) -> Result hyper::rt::Executor for Executor -where - T: Future + Send + 'static, - T::Output: Send + 'static, -{ - fn execute(&self, future: T) { - async_std::task::spawn(future); - } -} - /// Initializes the metrics context, and starts an HTTP server /// to serve metrics. pub async fn init_prometheus(prometheus_addr: SocketAddr, registry: Registry) -> Result<(), Error> { - let listener = async_std::net::TcpListener::bind(&prometheus_addr) + let listener = tokio::net::TcpListener::bind(&prometheus_addr) .await .map_err(|_| Error::PortInUse(prometheus_addr))?; @@ -110,12 +95,11 @@ pub async fn init_prometheus(prometheus_addr: SocketAddr, registry: Registry) -> /// Init prometheus using the given listener. async fn init_prometheus_with_listener( - listener: async_std::net::TcpListener, + listener: tokio::net::TcpListener, registry: Registry, ) -> Result<(), Error> { - use networking::Incoming; - - log::info!("〽️ Prometheus exporter started at {}", listener.local_addr()?); + let listener = hyper::server::conn::AddrIncoming::from_listener(listener)?; + log::info!("〽️ Prometheus exporter started at {}", listener.local_addr()); let service = make_service_fn(move |_| { let registry = registry.clone(); @@ -127,7 +111,7 @@ async fn init_prometheus_with_listener( } }); - let server = Server::builder(Incoming(listener.incoming())).executor(Executor).serve(service); + let server = Server::builder(listener).serve(service); let result = server.await.map_err(Into::into); @@ -147,7 +131,7 @@ mod tests { let runtime = tokio::runtime::Runtime::new().expect("Creates the runtime"); let listener = runtime - .block_on(async_std::net::TcpListener::bind("127.0.0.1:0")) + .block_on(tokio::net::TcpListener::bind("127.0.0.1:0")) .expect("Creates listener"); let local_addr = listener.local_addr().expect("Returns the local addr"); diff --git a/utils/prometheus/src/networking.rs b/utils/prometheus/src/networking.rs deleted file mode 100644 index fda20b75740b..000000000000 --- a/utils/prometheus/src/networking.rs +++ /dev/null @@ -1,71 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2019-2022 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. - -use async_std::pin::Pin; -use futures_util::{ - io::{AsyncRead, AsyncWrite}, - stream::Stream, -}; -use std::task::{Context, Poll}; - -pub struct Incoming<'a>(pub async_std::net::Incoming<'a>); - -impl hyper::server::accept::Accept for Incoming<'_> { - type Conn = TcpStream; - type Error = async_std::io::Error; - - fn poll_accept( - self: Pin<&mut Self>, - cx: &mut Context, - ) -> Poll>> { - Pin::new(&mut Pin::into_inner(self).0) - .poll_next(cx) - .map(|opt| opt.map(|res| res.map(TcpStream))) - } -} - -pub struct TcpStream(pub async_std::net::TcpStream); - -impl tokio::io::AsyncRead for TcpStream { - fn poll_read( - self: Pin<&mut Self>, - cx: &mut Context, - buf: &mut tokio::io::ReadBuf<'_>, - ) -> Poll> { - Pin::new(&mut Pin::into_inner(self).0) - .poll_read(cx, buf.initialize_unfilled()) - .map_ok(|s| buf.set_filled(s)) - } -} - -impl tokio::io::AsyncWrite for TcpStream { - fn poll_write( - self: Pin<&mut Self>, - cx: &mut Context, - buf: &[u8], - ) -> Poll> { - Pin::new(&mut Pin::into_inner(self).0).poll_write(cx, buf) - } - - fn poll_flush(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { - Pin::new(&mut Pin::into_inner(self).0).poll_flush(cx) - } - - fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { - Pin::new(&mut Pin::into_inner(self).0).poll_close(cx) - } -} From 4544e6d2ce398cadc03b56863f57c1ed6f53d046 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Thu, 24 Feb 2022 13:05:08 +0100 Subject: [PATCH 528/695] No longer generate specs with consensus_engine field (#10346) * No longer generate specs with consensus_engine field * #[allow(unused)] --- client/chain-spec/src/chain_spec.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/client/chain-spec/src/chain_spec.rs b/client/chain-spec/src/chain_spec.rs index 2412a7cdf83f..efb40d46f216 100644 --- a/client/chain-spec/src/chain_spec.rs +++ b/client/chain-spec/src/chain_spec.rs @@ -173,9 +173,8 @@ struct ClientSpec { #[serde(flatten)] extensions: E, // Never used, left only for backward compatibility. - // In a future version, a `skip_serializing` attribute should be added in order to no longer - // generate chain specs with this field. - #[serde(default)] + #[serde(default, skip_serializing)] + #[allow(unused)] consensus_engine: (), #[serde(skip_serializing)] #[allow(unused)] From c22fce5a311beede13479c9a00cca85d823b6b00 Mon Sep 17 00:00:00 2001 From: wigy <1888808+wigy-opensource-developer@users.noreply.github.com> Date: Thu, 24 Feb 2022 15:34:34 +0100 Subject: [PATCH 529/695] Upgrading parity-scale-codec to v3 (#10825) * Upgraded dependencies * Adapting code to scale v3 * Empty commit to trigger CI * Triggering CI * Fixing UI test * Remove superfluous dev-dep added by #9228 * Cryout for CI --- Cargo.lock | 333 +++++++++++------- bin/node-template/pallets/template/Cargo.toml | 4 +- bin/node-template/runtime/Cargo.toml | 4 +- bin/node/bench/Cargo.toml | 6 +- bin/node/cli/Cargo.toml | 2 +- bin/node/executor/Cargo.toml | 4 +- bin/node/inspect/Cargo.toml | 2 +- bin/node/primitives/Cargo.toml | 4 +- bin/node/runtime/Cargo.toml | 4 +- bin/node/testing/Cargo.toml | 2 +- client/api/Cargo.toml | 4 +- client/authority-discovery/Cargo.toml | 2 +- client/basic-authorship/Cargo.toml | 4 +- client/beefy/Cargo.toml | 4 +- client/beefy/rpc/Cargo.toml | 4 +- client/block-builder/Cargo.toml | 2 +- client/chain-spec/Cargo.toml | 2 +- client/cli/Cargo.toml | 2 +- client/consensus/aura/Cargo.toml | 4 +- client/consensus/babe/Cargo.toml | 4 +- client/consensus/common/Cargo.toml | 2 +- client/consensus/epochs/Cargo.toml | 2 +- client/consensus/manual-seal/Cargo.toml | 2 +- client/consensus/pow/Cargo.toml | 4 +- client/consensus/slots/Cargo.toml | 2 +- client/db/Cargo.toml | 12 +- client/executor/Cargo.toml | 4 +- client/executor/common/Cargo.toml | 2 +- client/executor/wasmi/Cargo.toml | 2 +- client/executor/wasmtime/Cargo.toml | 2 +- client/finality-grandpa/Cargo.toml | 8 +- client/finality-grandpa/rpc/Cargo.toml | 4 +- client/informant/Cargo.toml | 2 +- client/keystore/Cargo.toml | 2 +- client/network/Cargo.toml | 4 +- client/network/src/protocol.rs | 2 +- client/network/test/Cargo.toml | 2 +- client/offchain/Cargo.toml | 4 +- client/rpc-api/Cargo.toml | 4 +- client/rpc/Cargo.toml | 4 +- client/service/Cargo.toml | 6 +- client/service/test/Cargo.toml | 4 +- client/state-db/Cargo.toml | 6 +- client/sync-state-rpc/Cargo.toml | 2 +- client/telemetry/Cargo.toml | 2 +- client/tracing/Cargo.toml | 2 +- client/transaction-pool/Cargo.toml | 7 +- client/utils/Cargo.toml | 2 +- frame/assets/Cargo.toml | 4 +- frame/atomic-swap/Cargo.toml | 4 +- frame/aura/Cargo.toml | 4 +- frame/authority-discovery/Cargo.toml | 4 +- frame/authorship/Cargo.toml | 4 +- frame/babe/Cargo.toml | 4 +- frame/bags-list/Cargo.toml | 4 +- frame/balances/Cargo.toml | 4 +- frame/beefy-mmr/Cargo.toml | 4 +- frame/beefy/Cargo.toml | 4 +- frame/benchmarking/Cargo.toml | 4 +- frame/bounties/Cargo.toml | 4 +- frame/child-bounties/Cargo.toml | 4 +- frame/collective/Cargo.toml | 4 +- frame/contracts/Cargo.toml | 4 +- frame/contracts/common/Cargo.toml | 4 +- frame/contracts/rpc/Cargo.toml | 2 +- frame/contracts/rpc/runtime-api/Cargo.toml | 4 +- frame/conviction-voting/Cargo.toml | 4 +- frame/democracy/Cargo.toml | 4 +- .../election-provider-multi-phase/Cargo.toml | 6 +- frame/election-provider-support/Cargo.toml | 4 +- frame/elections-phragmen/Cargo.toml | 4 +- frame/examples/basic/Cargo.toml | 4 +- frame/examples/offchain-worker/Cargo.toml | 4 +- frame/examples/parallel/Cargo.toml | 4 +- frame/executive/Cargo.toml | 4 +- frame/gilt/Cargo.toml | 4 +- frame/grandpa/Cargo.toml | 6 +- frame/identity/Cargo.toml | 4 +- frame/im-online/Cargo.toml | 4 +- frame/indices/Cargo.toml | 4 +- frame/lottery/Cargo.toml | 4 +- frame/membership/Cargo.toml | 4 +- frame/merkle-mountain-range/Cargo.toml | 4 +- .../primitives/Cargo.toml | 2 +- frame/merkle-mountain-range/rpc/Cargo.toml | 2 +- frame/multisig/Cargo.toml | 4 +- frame/nicks/Cargo.toml | 4 +- frame/node-authorization/Cargo.toml | 4 +- frame/offences/Cargo.toml | 4 +- frame/offences/benchmarking/Cargo.toml | 4 +- frame/preimage/Cargo.toml | 4 +- frame/proxy/Cargo.toml | 4 +- frame/randomness-collective-flip/Cargo.toml | 4 +- frame/recovery/Cargo.toml | 4 +- frame/referenda/Cargo.toml | 4 +- frame/scheduler/Cargo.toml | 4 +- frame/scored-pool/Cargo.toml | 4 +- frame/session/Cargo.toml | 4 +- frame/session/benchmarking/Cargo.toml | 4 +- frame/society/Cargo.toml | 4 +- frame/staking/Cargo.toml | 4 +- frame/sudo/Cargo.toml | 4 +- frame/support/Cargo.toml | 8 +- frame/support/test/Cargo.toml | 4 +- frame/support/test/compile_pass/Cargo.toml | 4 +- frame/support/test/pallet/Cargo.toml | 4 +- .../call_argument_invalid_bound_2.stderr | 4 +- frame/system/Cargo.toml | 4 +- frame/system/benchmarking/Cargo.toml | 4 +- frame/system/rpc/runtime-api/Cargo.toml | 2 +- frame/timestamp/Cargo.toml | 4 +- frame/tips/Cargo.toml | 4 +- frame/transaction-payment/Cargo.toml | 4 +- .../asset-tx-payment/Cargo.toml | 4 +- frame/transaction-payment/rpc/Cargo.toml | 2 +- .../rpc/runtime-api/Cargo.toml | 2 +- frame/transaction-storage/Cargo.toml | 4 +- frame/treasury/Cargo.toml | 4 +- frame/uniques/Cargo.toml | 4 +- frame/utility/Cargo.toml | 4 +- frame/vesting/Cargo.toml | 4 +- primitives/api/Cargo.toml | 2 +- .../api/proc-macro/src/decl_runtime_apis.rs | 2 +- .../api/proc-macro/src/impl_runtime_apis.rs | 2 +- primitives/api/test/Cargo.toml | 2 +- primitives/application-crypto/Cargo.toml | 4 +- primitives/arithmetic/Cargo.toml | 6 +- primitives/arithmetic/fuzzer/Cargo.toml | 2 +- primitives/authority-discovery/Cargo.toml | 4 +- primitives/authorship/Cargo.toml | 2 +- primitives/beefy/Cargo.toml | 4 +- primitives/block-builder/Cargo.toml | 2 +- primitives/blockchain/Cargo.toml | 4 +- primitives/consensus/aura/Cargo.toml | 4 +- primitives/consensus/babe/Cargo.toml | 4 +- primitives/consensus/common/Cargo.toml | 2 +- primitives/consensus/pow/Cargo.toml | 2 +- primitives/consensus/slots/Cargo.toml | 4 +- primitives/consensus/vrf/Cargo.toml | 2 +- primitives/core/Cargo.toml | 10 +- primitives/database/Cargo.toml | 4 +- primitives/externalities/Cargo.toml | 2 +- primitives/finality-grandpa/Cargo.toml | 6 +- primitives/inherents/Cargo.toml | 2 +- primitives/io/Cargo.toml | 4 +- primitives/keystore/Cargo.toml | 4 +- primitives/npos-elections/Cargo.toml | 4 +- primitives/npos-elections/fuzzer/Cargo.toml | 4 +- .../npos-elections/solution-type/Cargo.toml | 4 +- primitives/runtime-interface/Cargo.toml | 4 +- primitives/runtime/Cargo.toml | 6 +- primitives/sandbox/Cargo.toml | 2 +- primitives/session/Cargo.toml | 4 +- primitives/staking/Cargo.toml | 4 +- primitives/state-machine/Cargo.toml | 6 +- primitives/storage/Cargo.toml | 2 +- primitives/tasks/Cargo.toml | 2 +- primitives/test-primitives/Cargo.toml | 4 +- primitives/timestamp/Cargo.toml | 2 +- primitives/tracing/Cargo.toml | 2 +- .../transaction-storage-proof/Cargo.toml | 4 +- primitives/trie/Cargo.toml | 10 +- primitives/version/Cargo.toml | 4 +- primitives/version/proc-macro/Cargo.toml | 2 +- primitives/wasm-interface/Cargo.toml | 2 +- test-utils/client/Cargo.toml | 2 +- test-utils/runtime/Cargo.toml | 10 +- test-utils/runtime/client/Cargo.toml | 2 +- .../runtime/transaction-pool/Cargo.toml | 4 +- utils/fork-tree/Cargo.toml | 2 +- utils/frame/benchmarking-cli/Cargo.toml | 2 +- utils/frame/remote-externalities/Cargo.toml | 2 +- utils/frame/rpc/support/Cargo.toml | 4 +- utils/frame/rpc/support/src/lib.rs | 2 +- utils/frame/rpc/system/Cargo.toml | 2 +- utils/frame/try-runtime/cli/Cargo.toml | 2 +- 176 files changed, 528 insertions(+), 450 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b7e4210efdd4..58297393c834 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -486,7 +486,7 @@ dependencies = [ "futures 0.3.16", "log 0.4.14", "parity-scale-codec", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "sc-chain-spec", "sc-client-api", "sc-keystore", @@ -521,7 +521,7 @@ dependencies = [ "jsonrpc-pubsub", "log 0.4.14", "parity-scale-codec", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "sc-rpc", "sc-utils", "serde", @@ -577,9 +577,9 @@ dependencies = [ [[package]] name = "bindgen" -version = "0.59.1" +version = "0.59.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453c49e5950bb0eb63bb3df640e31618846c89d5b7faa54040d76e98e0134375" +checksum = "2bd2a9a458e8f4304c52c43ebb0cfbd520289f8379a52e329a38afda99bf8eb8" dependencies = [ "bitflags", "cexpr", @@ -602,24 +602,12 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitvec" -version = "0.19.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8942c8d352ae1838c9dda0b0ca2ab657696ef2232a20147cf1b30ae1a9cb4321" -dependencies = [ - "funty", - "radium 0.5.3", - "tap", - "wyz", -] - -[[package]] -name = "bitvec" -version = "0.20.2" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f682656975d3a682daff957be4ddeb65d6ad656737cd821f2d00685ae466af1" +checksum = "1489fcb93a5bb47da0462ca93ad252ad6af2145cce58d10d46a83931ba9f016b" dependencies = [ "funty", - "radium 0.6.2", + "radium", "tap", "wyz", ] @@ -824,6 +812,17 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" +[[package]] +name = "bzip2-sys" +version = "0.1.11+1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + [[package]] name = "cache-padded" version = "1.1.1" @@ -881,9 +880,9 @@ dependencies = [ [[package]] name = "cexpr" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db507a7679252d2276ed0dd8113c6875ec56d3089f9225b2b42c30cc1f8e5c89" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" dependencies = [ "nom", ] @@ -2011,9 +2010,9 @@ dependencies = [ [[package]] name = "finality-grandpa" -version = "0.14.4" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8ac3ff5224ef91f3c97e03eb1de2db82743427e91aaa5ac635f454f0b164f5a" +checksum = "d9def033d8505edf199f6a5d07aa7e6d2d6185b164293b77f0efd108f4f3e11d" dependencies = [ "either", "futures 0.3.16", @@ -2182,9 +2181,9 @@ dependencies = [ [[package]] name = "frame-metadata" -version = "14.2.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ed5e5c346de62ca5c184b4325a6600d1eaca210666e4606fe4e449574978d0" +checksum = "df6bb8542ef006ef0de09a5c4420787d79823c0ed7924225822362fd2bf2ff2d" dependencies = [ "cfg-if 1.0.0", "parity-scale-codec", @@ -2404,9 +2403,9 @@ checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" [[package]] name = "funty" -version = "1.1.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" @@ -2759,6 +2758,15 @@ dependencies = [ "ahash", ] +[[package]] +name = "hashbrown" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c21d40587b92fa6a6c6e3c1bdbf87d75511db5672f9c93175574b3a00df1758" +dependencies = [ + "ahash", +] + [[package]] name = "heck" version = "0.3.2" @@ -3043,9 +3051,9 @@ dependencies = [ [[package]] name = "impl-codec" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "161ebdfec3c8e3b52bf61c4f3550a1eea4f9579d10dc1b936f3171ebdcd6c443" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" dependencies = [ "parity-scale-codec", ] @@ -3524,9 +3532,9 @@ dependencies = [ [[package]] name = "kvdb" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a3f58dc069ec0e205a27f5b45920722a46faed802a0541538241af6228f512" +checksum = "a301d8ecb7989d4a6e2c57a49baca77d353bdbf879909debe3f375fe25d61f86" dependencies = [ "parity-util-mem", "smallvec 1.7.0", @@ -3534,20 +3542,20 @@ dependencies = [ [[package]] name = "kvdb-memorydb" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3b6b85fc643f5acd0bffb2cc8a6d150209379267af0d41db72170021841f9f5" +checksum = "ece7e668abd21387aeb6628130a6f4c802787f014fa46bc83221448322250357" dependencies = [ "kvdb", "parity-util-mem", - "parking_lot 0.11.2", + "parking_lot 0.12.0", ] [[package]] name = "kvdb-rocksdb" -version = "0.14.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b1b6ea8f2536f504b645ad78419c8246550e19d2c3419a167080ce08edee35a" +checksum = "a1e72a631a32527fafe22d0751c002e67d28173c49dcaecf79d1aaa323c520e9" dependencies = [ "fs-swap", "kvdb", @@ -3555,7 +3563,7 @@ dependencies = [ "num_cpus", "owning_ref", "parity-util-mem", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "regex", "rocksdb", "smallvec 1.7.0", @@ -4113,14 +4121,17 @@ dependencies = [ [[package]] name = "librocksdb-sys" -version = "6.20.3" +version = "0.6.1+6.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c309a9d2470844aceb9a4a098cf5286154d20596868b75a6b36357d2bb9ca25d" +checksum = "81bc587013734dadb7cf23468e531aa120788b87243648be42e2d3a072186291" dependencies = [ "bindgen", + "bzip2-sys", "cc", "glob", "libc", + "libz-sys", + "tikv-jemalloc-sys", ] [[package]] @@ -4243,9 +4254,9 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" +checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" dependencies = [ "scopeguard", ] @@ -4412,23 +4423,12 @@ dependencies = [ [[package]] name = "memory-db" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de006e09d04fc301a5f7e817b75aa49801c4479a8af753764416b085337ddcc5" -dependencies = [ - "hash-db", - "hashbrown 0.11.2", - "parity-util-mem", -] - -[[package]] -name = "memory-db" -version = "0.28.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d505169b746dacf02f7d14d8c80b34edfd8212159c63d23c977739a0d960c626" +checksum = "6566c70c1016f525ced45d7b7f97730a2bafb037c788211d0c186ef5b2189f0a" dependencies = [ "hash-db", - "hashbrown 0.11.2", + "hashbrown 0.12.0", "parity-util-mem", ] @@ -4459,6 +4459,12 @@ dependencies = [ "log 0.3.9", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.4.4" @@ -5151,13 +5157,12 @@ checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" [[package]] name = "nom" -version = "6.1.2" +version = "7.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7413f999671bd4745a7b624bd370a569fb6bc574b23c83a3c5ed2e453f3d5e2" +checksum = "1b1d11e1ef389c76fe5b81bcaf2ea32cf88b62bc494e19f493d0b30e7a930109" dependencies = [ - "bitvec 0.19.5", - "funty", "memchr", + "minimal-lexical", "version_check 0.9.2", ] @@ -5813,7 +5818,7 @@ dependencies = [ "log 0.4.14", "pallet-balances", "parity-scale-codec", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "rand 0.7.3", "scale-info", "sp-arithmetic", @@ -6615,12 +6620,12 @@ dependencies = [ [[package]] name = "parity-scale-codec" -version = "2.3.1" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "373b1a4c1338d9cd3d1fa53b3a11bdab5ab6bd80a20f7f7becd76953ae2be909" +checksum = "2a7f3fcf5e45fc28b84dcdab6b983e77f197ec01f325a33f404ba6855afd1070" dependencies = [ "arrayvec 0.7.1", - "bitvec 0.20.2", + "bitvec", "byte-slice-cast", "impl-trait-for-tuples", "parity-scale-codec-derive", @@ -6629,9 +6634,9 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "2.3.1" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1557010476e0595c9b568d16dcfb81b93cdeb157612726f5170d31aa707bed27" +checksum = "2c6e626dc84025ff56bf1476ed0e30d10c84d7f89a475ef46ebabee1095a8fba" dependencies = [ "proc-macro-crate 1.1.0", "proc-macro2", @@ -6661,15 +6666,15 @@ dependencies = [ [[package]] name = "parity-util-mem" -version = "0.10.2" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f4cb4e169446179cbc6b8b6320cc9fca49bd2e94e8db25f25f200a8ea774770" +checksum = "c32561d248d352148124f036cac253a644685a21dc9fea383eb4907d7bd35a8f" dependencies = [ "cfg-if 1.0.0", - "hashbrown 0.11.2", + "hashbrown 0.12.0", "impl-trait-for-tuples", "parity-util-mem-derive", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "primitive-types", "smallvec 1.7.0", "winapi 0.3.9", @@ -6743,10 +6748,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", - "lock_api 0.4.5", + "lock_api 0.4.6", "parking_lot_core 0.8.5", ] +[[package]] +name = "parking_lot" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" +dependencies = [ + "lock_api 0.4.6", + "parking_lot_core 0.9.1", +] + [[package]] name = "parking_lot_core" version = "0.6.2" @@ -6776,6 +6791,19 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "parking_lot_core" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28141e0cc4143da2443301914478dc976a61ffdb3f043058310c70df2fed8954" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "redox_syscall 0.2.10", + "smallvec 1.7.0", + "windows-sys", +] + [[package]] name = "paste" version = "0.1.18" @@ -7082,9 +7110,9 @@ dependencies = [ [[package]] name = "primitive-types" -version = "0.10.1" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05e4722c697a58a99d5d06a08c30821d7c082a4632198de1eaa5a6c22ef42373" +checksum = "e28720988bff275df1f51b171e1b2a18c30d194c4d2b61defdacecd625a5d94a" dependencies = [ "fixed-hash", "impl-codec", @@ -7272,15 +7300,9 @@ dependencies = [ [[package]] name = "radium" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8" - -[[package]] -name = "radium" -version = "0.6.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "643f8f41a8ebc4c5dc4515c82bb8abd397b527fc20fd681b7c011c2aee5d44fb" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" [[package]] name = "rand" @@ -7705,9 +7727,9 @@ dependencies = [ [[package]] name = "rocksdb" -version = "0.17.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a62eca5cacf2c8261128631bed9f045598d40bfbe4b29f5163f0f802f8f44a7" +checksum = "620f4129485ff1a7128d184bc687470c21c7951b64779ebc9cfdad3dcd920290" dependencies = [ "libc", "librocksdb-sys", @@ -7934,7 +7956,7 @@ dependencies = [ "futures-timer", "log 0.4.14", "parity-scale-codec", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "sc-block-builder", "sc-client-api", "sc-proposer-metrics", @@ -8040,7 +8062,7 @@ dependencies = [ "hash-db", "log 0.4.14", "parity-scale-codec", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "sc-executor", "sc-transaction-pool-api", "sc-utils", @@ -8073,7 +8095,7 @@ dependencies = [ "log 0.4.14", "parity-db", "parity-scale-codec", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "quickcheck", "sc-client-api", "sc-state-db", @@ -8098,7 +8120,7 @@ dependencies = [ "futures-timer", "libp2p", "log 0.4.14", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "sc-client-api", "sc-utils", "serde", @@ -8122,7 +8144,7 @@ dependencies = [ "getrandom 0.2.3", "log 0.4.14", "parity-scale-codec", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "sc-block-builder", "sc-client-api", "sc-consensus", @@ -8164,7 +8186,7 @@ dependencies = [ "num-rational 0.2.4", "num-traits", "parity-scale-codec", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "rand 0.7.3", "rand_chacha 0.2.2", "retain_mut", @@ -8290,7 +8312,7 @@ dependencies = [ "futures-timer", "log 0.4.14", "parity-scale-codec", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "sc-client-api", "sc-consensus", "sp-api", @@ -8349,7 +8371,7 @@ dependencies = [ "libsecp256k1", "lru 0.6.6", "parity-scale-codec", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "paste 1.0.6", "regex", "sc-executor-common", @@ -8445,7 +8467,7 @@ dependencies = [ "futures-timer", "log 0.4.14", "parity-scale-codec", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "rand 0.8.4", "sc-block-builder", "sc-chain-spec", @@ -8525,7 +8547,7 @@ version = "4.0.0-dev" dependencies = [ "async-trait", "hex", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "serde_json", "sp-application-crypto", "sp-core", @@ -8558,7 +8580,7 @@ dependencies = [ "log 0.4.14", "lru 0.7.0", "parity-scale-codec", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "pin-project 1.0.10", "prost", "prost-build", @@ -8619,7 +8641,7 @@ dependencies = [ "futures-timer", "libp2p", "log 0.4.14", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "rand 0.7.3", "sc-block-builder", "sc-client-api", @@ -8651,7 +8673,7 @@ dependencies = [ "num_cpus", "once_cell", "parity-scale-codec", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "rand 0.7.3", "sc-block-builder", "sc-client-api", @@ -8705,7 +8727,7 @@ dependencies = [ "lazy_static", "log 0.4.14", "parity-scale-codec", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "sc-block-builder", "sc-chain-spec", "sc-client-api", @@ -8741,7 +8763,7 @@ dependencies = [ "jsonrpc-pubsub", "log 0.4.14", "parity-scale-codec", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "sc-chain-spec", "sc-transaction-pool-api", "serde", @@ -8800,7 +8822,7 @@ dependencies = [ "log 0.4.14", "parity-scale-codec", "parity-util-mem", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "pin-project 1.0.10", "rand 0.7.3", "sc-block-builder", @@ -8860,7 +8882,7 @@ dependencies = [ "hex-literal", "log 0.4.14", "parity-scale-codec", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "sc-block-builder", "sc-client-api", "sc-client-db", @@ -8894,7 +8916,7 @@ dependencies = [ "parity-scale-codec", "parity-util-mem", "parity-util-mem-derive", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "sc-client-api", "sp-core", ] @@ -8927,7 +8949,7 @@ dependencies = [ "futures 0.3.16", "libp2p", "log 0.4.14", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "pin-project 1.0.10", "rand 0.7.3", "serde", @@ -8948,7 +8970,7 @@ dependencies = [ "libc", "log 0.4.14", "once_cell", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "regex", "rustc-hash", "sc-client-api", @@ -8990,7 +9012,7 @@ dependencies = [ "log 0.4.14", "parity-scale-codec", "parity-util-mem", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "retain_mut", "sc-block-builder", "sc-client-api", @@ -9030,18 +9052,18 @@ dependencies = [ "futures 0.3.16", "futures-timer", "lazy_static", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "prometheus", "tokio-test", ] [[package]] name = "scale-info" -version = "1.0.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c55b744399c25532d63a0d2789b109df8d46fc93752d46b0782991a931a782f" +checksum = "7d3b4d0b178e3af536f7988303bc73a0766c816de2138c08262015f8ec7be568" dependencies = [ - "bitvec 0.20.2", + "bitvec", "cfg-if 1.0.0", "derive_more", "parity-scale-codec", @@ -9051,9 +9073,9 @@ dependencies = [ [[package]] name = "scale-info-derive" -version = "1.0.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baeb2780690380592f86205aa4ee49815feb2acad8c2f59e6dd207148c3f1fcd" +checksum = "b7805950c36512db9e3251c970bb7ac425f326716941862205d612ab3b5e46e2" dependencies = [ "proc-macro-crate 1.1.0", "proc-macro2", @@ -9640,7 +9662,7 @@ dependencies = [ "log 0.4.14", "lru 0.7.0", "parity-scale-codec", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "sp-api", "sp-consensus", "sp-database", @@ -9766,7 +9788,7 @@ dependencies = [ "num-traits", "parity-scale-codec", "parity-util-mem", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "primitive-types", "rand 0.7.3", "regex", @@ -9819,7 +9841,7 @@ name = "sp-database" version = "4.0.0-dev" dependencies = [ "kvdb", - "parking_lot 0.11.2", + "parking_lot 0.12.0", ] [[package]] @@ -9881,7 +9903,7 @@ dependencies = [ "libsecp256k1", "log 0.4.14", "parity-scale-codec", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "sp-core", "sp-externalities", "sp-keystore", @@ -9913,7 +9935,7 @@ dependencies = [ "futures 0.3.16", "merlin", "parity-scale-codec", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "rand 0.7.3", "rand_chacha 0.2.2", "schnorrkel", @@ -10156,7 +10178,7 @@ dependencies = [ "log 0.4.14", "num-traits", "parity-scale-codec", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "pretty_assertions", "rand 0.7.3", "smallvec 1.7.0", @@ -10269,7 +10291,7 @@ dependencies = [ "criterion", "hash-db", "hex-literal", - "memory-db 0.28.0", + "memory-db", "parity-scale-codec", "scale-info", "sp-core", @@ -10530,7 +10552,7 @@ dependencies = [ "frame-system-rpc-runtime-api", "futures 0.3.16", "log 0.4.14", - "memory-db 0.27.0", + "memory-db", "pallet-babe", "pallet-timestamp", "parity-scale-codec", @@ -10590,7 +10612,7 @@ version = "2.0.0" dependencies = [ "futures 0.3.16", "parity-scale-codec", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "sc-transaction-pool", "sc-transaction-pool-api", "sp-blockchain", @@ -10767,6 +10789,17 @@ dependencies = [ "num_cpus", ] +[[package]] +name = "tikv-jemalloc-sys" +version = "0.4.2+5.2.1-patched.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5844e429d797c62945a566f8da4e24c7fe3fbd5d6617fd8bf7a0b7dc1ee0f22e" +dependencies = [ + "cc", + "fs_extra", + "libc", +] + [[package]] name = "time" version = "0.1.44" @@ -11133,14 +11166,14 @@ checksum = "a7f741b240f1a48843f9b8e0444fb55fb2a4ff67293b50a9179dfd5ea67f8d41" [[package]] name = "trie-bench" -version = "0.29.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36ac46f6503d0fa976193db46f9dbb1d454e5dbde76495f1316f576c7f3f0e6b" +checksum = "57ecec5d10427b35e9ae374b059dccc0801d02d832617c04c78afc7a8c5c4a34" dependencies = [ "criterion", "hash-db", "keccak-hasher", - "memory-db 0.28.0", + "memory-db", "parity-scale-codec", "trie-db", "trie-root", @@ -11149,12 +11182,12 @@ dependencies = [ [[package]] name = "trie-db" -version = "0.23.0" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3ddae50680c12ef75bfbf58416ca6622fa43d879553f6cb2ed1a817346e1ffe" +checksum = "d32d034c0d3db64b43c31de38e945f15b40cd4ca6d2dcfc26d4798ce8de4ab83" dependencies = [ "hash-db", - "hashbrown 0.11.2", + "hashbrown 0.12.0", "log 0.4.14", "rustc-hex", "smallvec 1.7.0", @@ -11279,7 +11312,7 @@ version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ee73e6e4924fe940354b8d4d98cad5231175d615cd855b758adc658c0aac6a0" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 0.1.10", "digest 0.10.2", "rand 0.8.4", "static_assertions", @@ -12185,6 +12218,49 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3df6e476185f92a12c072be4a189a0210dcdcf512a1891d6dff9edb874deadc6" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5" + +[[package]] +name = "windows_i686_gnu" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615" + +[[package]] +name = "windows_i686_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316" + [[package]] name = "winreg" version = "0.6.2" @@ -12206,9 +12282,12 @@ dependencies = [ [[package]] name = "wyz" -version = "0.2.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" +checksum = "30b31594f29d27036c383b53b59ed3476874d518f0efb151b27a4c275141390e" +dependencies = [ + "tap", +] [[package]] name = "x25519-dalek" diff --git a/bin/node-template/pallets/template/Cargo.toml b/bin/node-template/pallets/template/Cargo.toml index 0a9d0eb27a2c..62c1c4310884 100644 --- a/bin/node-template/pallets/template/Cargo.toml +++ b/bin/node-template/pallets/template/Cargo.toml @@ -13,10 +13,10 @@ repository = "https://github.com/substrate-developer-hub/substrate-node-template targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", ] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } frame-support = { default-features = false, version = "4.0.0-dev", path = "../../../../frame/support" } frame-system = { default-features = false, version = "4.0.0-dev", path = "../../../../frame/system" } frame-benchmarking = { default-features = false, version = "4.0.0-dev", path = "../../../../frame/benchmarking", optional = true } diff --git a/bin/node-template/runtime/Cargo.toml b/bin/node-template/runtime/Cargo.toml index 98da28c4476d..ca3b4d93e6b6 100644 --- a/bin/node-template/runtime/Cargo.toml +++ b/bin/node-template/runtime/Cargo.toml @@ -13,8 +13,8 @@ repository = "https://github.com/substrate-developer-hub/substrate-node-template targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } pallet-aura = { version = "4.0.0-dev", default-features = false, path = "../../../frame/aura" } pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../../../frame/balances" } diff --git a/bin/node/bench/Cargo.toml b/bin/node/bench/Cargo.toml index 18951179235c..b14e44371d2b 100644 --- a/bin/node/bench/Cargo.toml +++ b/bin/node/bench/Cargo.toml @@ -20,8 +20,8 @@ sp-state-machine = { version = "0.11.0", path = "../../../primitives/state-machi serde = "1.0.136" serde_json = "1.0.74" derive_more = "0.99.16" -kvdb = "0.10.0" -kvdb-rocksdb = "0.14.0" +kvdb = "0.11.0" +kvdb-rocksdb = "0.15.1" sp-trie = { version = "5.0.0", path = "../../../primitives/trie" } sp-core = { version = "5.0.0", path = "../../../primitives/core" } sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" } @@ -35,7 +35,7 @@ fs_extra = "1" hex = "0.4.0" rand = { version = "0.7.2", features = ["small_rng"] } lazy_static = "1.4.0" -parity-util-mem = { version = "0.10.2", default-features = false, features = ["primitive-types"] } +parity-util-mem = { version = "0.11.0", default-features = false, features = ["primitive-types"] } parity-db = { version = "0.3" } sc-transaction-pool = { version = "4.0.0-dev", path = "../../../client/transaction-pool" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../../../client/transaction-pool/api" } diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index 74d62ba78c2a..4225d09d594a 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -35,7 +35,7 @@ crate-type = ["cdylib", "rlib"] [dependencies] # third-party dependencies clap = { version = "3.0", features = ["derive"], optional = true } -codec = { package = "parity-scale-codec", version = "2.0.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } serde = { version = "1.0.136", features = ["derive"] } futures = "0.3.16" hex-literal = "0.3.4" diff --git a/bin/node/executor/Cargo.toml b/bin/node/executor/Cargo.toml index 531fffe35529..16f232d73d3f 100644 --- a/bin/node/executor/Cargo.toml +++ b/bin/node/executor/Cargo.toml @@ -12,8 +12,8 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0" } -scale-info = { version = "1.0", features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0" } +scale-info = { version = "2.0.0", features = ["derive"] } node-primitives = { version = "2.0.0", path = "../primitives" } node-runtime = { version = "3.0.0-dev", path = "../runtime" } sc-executor = { version = "0.10.0-dev", path = "../../../client/executor" } diff --git a/bin/node/inspect/Cargo.toml b/bin/node/inspect/Cargo.toml index e5b4c41c91b7..162d56fc763f 100644 --- a/bin/node/inspect/Cargo.toml +++ b/bin/node/inspect/Cargo.toml @@ -12,7 +12,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] clap = { version = "3.0", features = ["derive"] } -codec = { package = "parity-scale-codec", version = "2.0.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } thiserror = "1.0" sc-cli = { version = "0.10.0-dev", path = "../../../client/cli" } sc-client-api = { version = "4.0.0-dev", path = "../../../client/api" } diff --git a/bin/node/primitives/Cargo.toml b/bin/node/primitives/Cargo.toml index 5664318513a0..f95f767b4a83 100644 --- a/bin/node/primitives/Cargo.toml +++ b/bin/node/primitives/Cargo.toml @@ -11,10 +11,10 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", ] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../../frame/system" } sp-application-crypto = { version = "5.0.0", default-features = false, path = "../../../primitives/application-crypto" } sp-core = { version = "5.0.0", default-features = false, path = "../../../primitives/core" } diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 4f235a51171d..0055230295a1 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -14,11 +14,11 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] # third-party dependencies -codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", "max-encoded-len", ] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } static_assertions = "1.1.0" hex-literal = { version = "0.3.4", optional = true } log = { version = "0.4.14", default-features = false } diff --git a/bin/node/testing/Cargo.toml b/bin/node/testing/Cargo.toml index 3275aac0ef1d..fc9209ce2b63 100644 --- a/bin/node/testing/Cargo.toml +++ b/bin/node/testing/Cargo.toml @@ -23,7 +23,7 @@ sc-client-db = { version = "0.10.0-dev", path = "../../../client/db/", features ] } sc-client-api = { version = "4.0.0-dev", path = "../../../client/api/" } sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/common" } -codec = { package = "parity-scale-codec", version = "2.0.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } sp-keyring = { version = "5.0.0", path = "../../../primitives/keyring" } node-executor = { version = "3.0.0-dev", path = "../executor" } node-primitives = { version = "2.0.0", path = "../primitives" } diff --git a/client/api/Cargo.toml b/client/api/Cargo.toml index ab6ad96e286f..68ab9aed31fe 100644 --- a/client/api/Cargo.toml +++ b/client/api/Cargo.toml @@ -14,7 +14,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", ] } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } @@ -25,7 +25,7 @@ futures = "0.3.1" hash-db = { version = "0.15.2", default-features = false } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } log = "0.4.8" -parking_lot = "0.11.2" +parking_lot = "0.12.0" sp-database = { version = "4.0.0-dev", path = "../../primitives/database" } sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } sp-keystore = { version = "0.11.0", default-features = false, path = "../../primitives/keystore" } diff --git a/client/authority-discovery/Cargo.toml b/client/authority-discovery/Cargo.toml index e3a3ef2a3591..04dde95837d2 100644 --- a/client/authority-discovery/Cargo.toml +++ b/client/authority-discovery/Cargo.toml @@ -18,7 +18,7 @@ prost-build = "0.9" [dependencies] async-trait = "0.1" -codec = { package = "parity-scale-codec", default-features = false, version = "2.0.0" } +codec = { package = "parity-scale-codec", default-features = false, version = "3.0.0" } thiserror = "1.0" futures = "0.3.9" futures-timer = "3.0.1" diff --git a/client/basic-authorship/Cargo.toml b/client/basic-authorship/Cargo.toml index 85592c7c549c..bbc66cf09f8b 100644 --- a/client/basic-authorship/Cargo.toml +++ b/client/basic-authorship/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } futures = "0.3.9" futures-timer = "3.0.1" log = "0.4.8" @@ -33,4 +33,4 @@ sc-proposer-metrics = { version = "0.10.0-dev", path = "../proposer-metrics" } [dev-dependencies] sc-transaction-pool = { version = "4.0.0-dev", path = "../transaction-pool" } substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } -parking_lot = "0.11.2" +parking_lot = "0.12.0" diff --git a/client/beefy/Cargo.toml b/client/beefy/Cargo.toml index 3ce556e85239..d126d60b8409 100644 --- a/client/beefy/Cargo.toml +++ b/client/beefy/Cargo.toml @@ -11,11 +11,11 @@ description = "BEEFY Client gadget for substrate" fnv = "1.0.6" futures = "0.3" log = "0.4" -parking_lot = "0.11" +parking_lot = "0.12.0" thiserror = "1.0" wasm-timer = "0.2.5" -codec = { version = "2.2.0", package = "parity-scale-codec", features = ["derive"] } +codec = { version = "3.0.0", package = "parity-scale-codec", features = ["derive"] } prometheus = { version = "0.10.0-dev", package = "substrate-prometheus-endpoint", path = "../../utils/prometheus" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } diff --git a/client/beefy/rpc/Cargo.toml b/client/beefy/rpc/Cargo.toml index 44837fb0e41f..053aef500b46 100644 --- a/client/beefy/rpc/Cargo.toml +++ b/client/beefy/rpc/Cargo.toml @@ -10,7 +10,7 @@ description = "RPC for the BEEFY Client gadget for substrate" [dependencies] futures = "0.3.16" log = "0.4" -parking_lot = "0.11" +parking_lot = "0.12.0" thiserror = "1.0" serde = { version = "1.0.136", features = ["derive"] } @@ -19,7 +19,7 @@ jsonrpc-core-client = "18.0.0" jsonrpc-derive = "18.0.0" jsonrpc-pubsub = "18.0.0" -codec = { version = "2.2.0", package = "parity-scale-codec", features = ["derive"] } +codec = { version = "3.0.0", package = "parity-scale-codec", features = ["derive"] } sc-rpc = { version = "4.0.0-dev", path = "../../rpc" } sc-utils = { version = "4.0.0-dev", path = "../../utils" } diff --git a/client/block-builder/Cargo.toml b/client/block-builder/Cargo.toml index e41ab0a5caf1..10c3fbdb9f7f 100644 --- a/client/block-builder/Cargo.toml +++ b/client/block-builder/Cargo.toml @@ -22,7 +22,7 @@ sp-core = { version = "5.0.0", path = "../../primitives/core" } sp-block-builder = { version = "4.0.0-dev", path = "../../primitives/block-builder" } sp-inherents = { version = "4.0.0-dev", path = "../../primitives/inherents" } sc-client-api = { version = "4.0.0-dev", path = "../api" } -codec = { package = "parity-scale-codec", version = "2.0.0", features = [ +codec = { package = "parity-scale-codec", version = "3.0.0", features = [ "derive", ] } diff --git a/client/chain-spec/Cargo.toml b/client/chain-spec/Cargo.toml index 9b299f00a214..9e8e3276e760 100644 --- a/client/chain-spec/Cargo.toml +++ b/client/chain-spec/Cargo.toml @@ -21,5 +21,5 @@ serde = { version = "1.0.136", features = ["derive"] } serde_json = "1.0.74" sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } sc-telemetry = { version = "4.0.0-dev", path = "../telemetry" } -codec = { package = "parity-scale-codec", version = "2.0.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } memmap2 = "0.5.0" diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index 3fd65d23eb88..708e6317d10c 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -30,7 +30,7 @@ thiserror = "1.0.30" tiny-bip39 = "0.8.2" tokio = { version = "1.15", features = ["signal", "rt-multi-thread", "parking_lot"] } -parity-scale-codec = "2.3.1" +parity-scale-codec = "3.0.0" sc-client-api = { version = "4.0.0-dev", path = "../api" } sc-keystore = { version = "4.0.0-dev", path = "../keystore" } sc-network = { version = "0.10.0-dev", path = "../network" } diff --git a/client/consensus/aura/Cargo.toml b/client/consensus/aura/Cargo.toml index 156842c35842..9cb241b6c974 100644 --- a/client/consensus/aura/Cargo.toml +++ b/client/consensus/aura/Cargo.toml @@ -18,7 +18,7 @@ sp-consensus-aura = { version = "0.10.0-dev", path = "../../../primitives/consen sp-block-builder = { version = "4.0.0-dev", path = "../../../primitives/block-builder" } sc-block-builder = { version = "0.10.0-dev", path = "../../block-builder" } sc-client-api = { version = "4.0.0-dev", path = "../../api" } -codec = { package = "parity-scale-codec", version = "2.0.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" } sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/common" } sp-consensus-slots = { version = "0.10.0-dev", path = "../../../primitives/consensus/slots" } @@ -48,4 +48,4 @@ sc-network = { version = "0.10.0-dev", path = "../../network" } sc-network-test = { version = "0.8.0", path = "../../network/test" } substrate-test-runtime-client = { version = "2.0.0", path = "../../../test-utils/runtime/client" } tempfile = "3.1.0" -parking_lot = "0.11.2" +parking_lot = "0.12.0" diff --git a/client/consensus/babe/Cargo.toml b/client/consensus/babe/Cargo.toml index 76ec6a25879f..4a9f1f00b75a 100644 --- a/client/consensus/babe/Cargo.toml +++ b/client/consensus/babe/Cargo.toml @@ -14,7 +14,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", features = [ +codec = { package = "parity-scale-codec", version = "3.0.0", features = [ "derive", ] } sp-consensus-babe = { version = "0.10.0-dev", path = "../../../primitives/consensus/babe" } @@ -44,7 +44,7 @@ sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } fork-tree = { version = "3.0.0", path = "../../../utils/fork-tree" } prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.10.0-dev" } futures = "0.3.9" -parking_lot = "0.11.2" +parking_lot = "0.12.0" log = "0.4.8" schnorrkel = { version = "0.9.1", features = ["preaudit_deprecated"] } rand = "0.7.2" diff --git a/client/consensus/common/Cargo.toml b/client/consensus/common/Cargo.toml index a14a36769033..7add4bb87330 100644 --- a/client/consensus/common/Cargo.toml +++ b/client/consensus/common/Cargo.toml @@ -26,7 +26,7 @@ sp-state-machine = { version = "0.11.0", path = "../../../primitives/state-machi sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } sc-utils = { version = "4.0.0-dev", path = "../../utils" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } -parking_lot = "0.11.2" +parking_lot = "0.12.0" serde = { version = "1.0", features = ["derive"] } prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.10.0-dev" } async-trait = "0.1.42" diff --git a/client/consensus/epochs/Cargo.toml b/client/consensus/epochs/Cargo.toml index b377dccfd368..2c5a6dfbffe0 100644 --- a/client/consensus/epochs/Cargo.toml +++ b/client/consensus/epochs/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"] } fork-tree = { version = "3.0.0", path = "../../../utils/fork-tree" } sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } diff --git a/client/consensus/manual-seal/Cargo.toml b/client/consensus/manual-seal/Cargo.toml index c2c36b1fc586..83828962f670 100644 --- a/client/consensus/manual-seal/Cargo.toml +++ b/client/consensus/manual-seal/Cargo.toml @@ -19,7 +19,7 @@ jsonrpc-core = "18.0.0" jsonrpc-core-client = "18.0.0" jsonrpc-derive = "18.0.0" log = "0.4.8" -codec = { package = "parity-scale-codec", version = "2.0.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } serde = { version = "1.0", features = ["derive"] } assert_matches = "1.3.0" async-trait = "0.1.50" diff --git a/client/consensus/pow/Cargo.toml b/client/consensus/pow/Cargo.toml index eb609489290a..7e3d30e8deba 100644 --- a/client/consensus/pow/Cargo.toml +++ b/client/consensus/pow/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"] } sp-core = { version = "5.0.0", path = "../../../primitives/core" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } @@ -27,7 +27,7 @@ sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/commo log = "0.4.8" futures = "0.3.16" futures-timer = "3.0.1" -parking_lot = "0.11.2" +parking_lot = "0.12.0" thiserror = "1.0" prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.10.0-dev"} async-trait = "0.1.50" diff --git a/client/consensus/slots/Cargo.toml b/client/consensus/slots/Cargo.toml index b13c1bb6b5b3..0127010a1714 100644 --- a/client/consensus/slots/Cargo.toml +++ b/client/consensus/slots/Cargo.toml @@ -14,7 +14,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } sc-client-api = { version = "4.0.0-dev", path = "../../api" } sp-core = { version = "5.0.0", path = "../../../primitives/core" } sp-arithmetic = { version = "4.0.0", path = "../../../primitives/arithmetic" } diff --git a/client/db/Cargo.toml b/client/db/Cargo.toml index f2c21abf6c1d..82607f56f7d1 100644 --- a/client/db/Cargo.toml +++ b/client/db/Cargo.toml @@ -13,14 +13,14 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -parking_lot = "0.11.2" +parking_lot = "0.12.0" log = "0.4.8" -kvdb = "0.10.0" -kvdb-rocksdb = { version = "0.14.0", optional = true } -kvdb-memorydb = "0.10.0" +kvdb = "0.11.0" +kvdb-rocksdb = { version = "0.15.1", optional = true } +kvdb-memorydb = "0.11.0" linked-hash-map = "0.5.4" hash-db = "0.15.2" -codec = { package = "parity-scale-codec", version = "2.0.0", features = [ +codec = { package = "parity-scale-codec", version = "3.0.0", features = [ "derive", ] } @@ -39,7 +39,7 @@ parity-db = { version = "0.3.5", optional = true } sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } quickcheck = "1.0.3" -kvdb-rocksdb = "0.14.0" +kvdb-rocksdb = "0.15.1" tempfile = "3" [features] diff --git a/client/executor/Cargo.toml b/client/executor/Cargo.toml index 47ef05005086..6cd1938822d0 100644 --- a/client/executor/Cargo.toml +++ b/client/executor/Cargo.toml @@ -14,7 +14,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } sp-io = { version = "5.0.0", path = "../../primitives/io" } sp-core = { version = "5.0.0", path = "../../primitives/core" } sp-tasks = { version = "4.0.0-dev", path = "../../primitives/tasks" } @@ -30,7 +30,7 @@ sp-externalities = { version = "0.11.0", path = "../../primitives/externalities" sc-executor-common = { version = "0.10.0-dev", path = "common" } sc-executor-wasmi = { version = "0.10.0-dev", path = "wasmi" } sc-executor-wasmtime = { version = "0.10.0-dev", path = "wasmtime", optional = true } -parking_lot = "0.11.2" +parking_lot = "0.12.0" libsecp256k1 = "0.7" sp-core-hashing-proc-macro = { version = "4.0.0-dev", path = "../../primitives/core/hashing/proc-macro" } lru = "0.6.6" diff --git a/client/executor/common/Cargo.toml b/client/executor/common/Cargo.toml index e23db203b3a4..3edaaf12e5b0 100644 --- a/client/executor/common/Cargo.toml +++ b/client/executor/common/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] wasm-instrument = "0.1" -codec = { package = "parity-scale-codec", version = "2.0.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } wasmi = "0.9.1" sp-core = { version = "5.0.0", path = "../../../primitives/core" } sc-allocator = { version = "4.1.0-dev", path = "../../allocator" } diff --git a/client/executor/wasmi/Cargo.toml b/client/executor/wasmi/Cargo.toml index d333e98bf6cf..9b25ebcb1174 100644 --- a/client/executor/wasmi/Cargo.toml +++ b/client/executor/wasmi/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] log = "0.4.8" wasmi = "0.9.1" -codec = { package = "parity-scale-codec", version = "2.0.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } sc-executor-common = { version = "0.10.0-dev", path = "../common" } sc-allocator = { version = "4.1.0-dev", path = "../../allocator" } sp-wasm-interface = { version = "5.0.0", path = "../../../primitives/wasm-interface" } diff --git a/client/executor/wasmtime/Cargo.toml b/client/executor/wasmtime/Cargo.toml index 0423b384943e..79d5d41087a1 100644 --- a/client/executor/wasmtime/Cargo.toml +++ b/client/executor/wasmtime/Cargo.toml @@ -17,7 +17,7 @@ libc = "0.2.112" cfg-if = "1.0" log = "0.4.8" parity-wasm = "0.42.0" -codec = { package = "parity-scale-codec", version = "2.0.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } sc-executor-common = { version = "0.10.0-dev", path = "../common" } sp-wasm-interface = { version = "5.0.0", path = "../../../primitives/wasm-interface", features = ["wasmtime"] } sp-runtime-interface = { version = "5.0.0", path = "../../../primitives/runtime-interface" } diff --git a/client/finality-grandpa/Cargo.toml b/client/finality-grandpa/Cargo.toml index 6fecebc3fdf6..2e2ad8738f35 100644 --- a/client/finality-grandpa/Cargo.toml +++ b/client/finality-grandpa/Cargo.toml @@ -20,10 +20,10 @@ fork-tree = { version = "3.0.0", path = "../../utils/fork-tree" } futures = "0.3.9" futures-timer = "3.0.1" log = "0.4.8" -parking_lot = "0.11.2" +parking_lot = "0.12.0" rand = "0.8.4" ahash = "0.7.6" -parity-scale-codec = { version = "2.3.1", features = ["derive"] } +parity-scale-codec = { version = "3.0.0", features = ["derive"] } sp-application-crypto = { version = "5.0.0", path = "../../primitives/application-crypto" } sp-arithmetic = { version = "4.0.0", path = "../../primitives/arithmetic" } sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } @@ -44,12 +44,12 @@ sc-network-gossip = { version = "0.10.0-dev", path = "../network-gossip" } sp-finality-grandpa = { version = "4.0.0-dev", path = "../../primitives/finality-grandpa" } prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.10.0-dev" } sc-block-builder = { version = "0.10.0-dev", path = "../block-builder" } -finality-grandpa = { version = "0.14.4", features = ["derive-codec"] } +finality-grandpa = { version = "0.15.0", features = ["derive-codec"] } async-trait = "0.1.50" [dev-dependencies] assert_matches = "1.3.0" -finality-grandpa = { version = "0.14.1", features = [ +finality-grandpa = { version = "0.15.0", features = [ "derive-codec", "test-helpers", ] } diff --git a/client/finality-grandpa/rpc/Cargo.toml b/client/finality-grandpa/rpc/Cargo.toml index b544287a6002..8650ee049853 100644 --- a/client/finality-grandpa/rpc/Cargo.toml +++ b/client/finality-grandpa/rpc/Cargo.toml @@ -14,7 +14,7 @@ sc-rpc = { version = "4.0.0-dev", path = "../../rpc" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sp-core = { version = "5.0.0", path = "../../../primitives/core" } sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } -finality-grandpa = { version = "0.14.4", features = ["derive-codec"] } +finality-grandpa = { version = "0.15.0", features = ["derive-codec"] } jsonrpc-core = "18.0.0" jsonrpc-core-client = "18.0.0" jsonrpc-derive = "18.0.0" @@ -24,7 +24,7 @@ serde = { version = "1.0.105", features = ["derive"] } serde_json = "1.0.50" log = "0.4.8" thiserror = "1.0" -parity-scale-codec = { version = "2.0.0", features = ["derive"] } +parity-scale-codec = { version = "3.0.0", features = ["derive"] } sc-client-api = { version = "4.0.0-dev", path = "../../api" } [dev-dependencies] diff --git a/client/informant/Cargo.toml b/client/informant/Cargo.toml index 78ee90823f22..82917c46d3d2 100644 --- a/client/informant/Cargo.toml +++ b/client/informant/Cargo.toml @@ -17,7 +17,7 @@ ansi_term = "0.12.1" futures = "0.3.9" futures-timer = "3.0.1" log = "0.4.8" -parity-util-mem = { version = "0.10.2", default-features = false, features = ["primitive-types"] } +parity-util-mem = { version = "0.11.0", default-features = false, features = ["primitive-types"] } sc-client-api = { version = "4.0.0-dev", path = "../api" } sc-network = { version = "0.10.0-dev", path = "../network" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } diff --git a/client/keystore/Cargo.toml b/client/keystore/Cargo.toml index 4d67be4167dd..f2a06244cde0 100644 --- a/client/keystore/Cargo.toml +++ b/client/keystore/Cargo.toml @@ -21,7 +21,7 @@ sp-application-crypto = { version = "5.0.0", path = "../../primitives/applicatio sp-core = { version = "5.0.0", path = "../../primitives/core" } sp-keystore = { version = "0.11.0", path = "../../primitives/keystore" } hex = "0.4.0" -parking_lot = "0.11.2" +parking_lot = "0.12.0" serde_json = "1.0.74" [dev-dependencies] diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index 7a978d0740f6..0334c5e819df 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -21,7 +21,7 @@ async-trait = "0.1" bitflags = "1.3.2" cid = "0.6.0" bytes = "1" -codec = { package = "parity-scale-codec", version = "2.0.0", features = [ +codec = { package = "parity-scale-codec", version = "3.0.0", features = [ "derive", ] } either = "1.5.3" @@ -36,7 +36,7 @@ linked-hash-map = "0.5.4" linked_hash_set = "0.1.3" lru = "0.7.0" log = "0.4.8" -parking_lot = "0.11.2" +parking_lot = "0.12.0" pin-project = "1.0.10" prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.10.0-dev", path = "../../utils/prometheus" } prost = "0.9" diff --git a/client/network/src/protocol.rs b/client/network/src/protocol.rs index eb634ca5be76..c00d4302f827 100644 --- a/client/network/src/protocol.rs +++ b/client/network/src/protocol.rs @@ -1666,7 +1666,7 @@ impl NetworkBehaviour for Protocol { } } else { match ( - message::Roles::decode_all(&received_handshake[..]), + message::Roles::decode_all(&mut &received_handshake[..]), self.peers.get(&peer_id), ) { (Ok(roles), _) => CustomMessageOutcome::NotificationStreamOpened { diff --git a/client/network/test/Cargo.toml b/client/network/test/Cargo.toml index 2750c613d42a..7d0b1921b69e 100644 --- a/client/network/test/Cargo.toml +++ b/client/network/test/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] async-std = "1.10.0" sc-network = { version = "0.10.0-dev", path = "../" } log = "0.4.8" -parking_lot = "0.11.2" +parking_lot = "0.12.0" futures = "0.3.9" futures-timer = "3.0.1" rand = "0.7.2" diff --git a/client/offchain/Cargo.toml b/client/offchain/Cargo.toml index 5cd823958eed..054a8c3edf02 100644 --- a/client/offchain/Cargo.toml +++ b/client/offchain/Cargo.toml @@ -14,13 +14,13 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] bytes = "1.1" -codec = { package = "parity-scale-codec", version = "2.0.0", features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"] } hex = "0.4" fnv = "1.0.6" futures = "0.3.16" futures-timer = "3.0.2" num_cpus = "1.13" -parking_lot = "0.11.2" +parking_lot = "0.12.0" rand = "0.7.2" sc-client-api = { version = "4.0.0-dev", path = "../api" } sc-network = { version = "0.10.0-dev", path = "../network" } diff --git a/client/rpc-api/Cargo.toml b/client/rpc-api/Cargo.toml index 00b2fa787ca6..bbbc9a998337 100644 --- a/client/rpc-api/Cargo.toml +++ b/client/rpc-api/Cargo.toml @@ -13,14 +13,14 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } futures = "0.3.16" jsonrpc-core = "18.0.0" jsonrpc-core-client = "18.0.0" jsonrpc-derive = "18.0.0" jsonrpc-pubsub = "18.0.0" log = "0.4.8" -parking_lot = "0.11.2" +parking_lot = "0.12.0" thiserror = "1.0" sp-core = { version = "5.0.0", path = "../../primitives/core" } diff --git a/client/rpc/Cargo.toml b/client/rpc/Cargo.toml index 308d99bc4f37..cbce14cee20d 100644 --- a/client/rpc/Cargo.toml +++ b/client/rpc/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] sc-rpc-api = { version = "0.10.0-dev", path = "../rpc-api" } sc-client-api = { version = "4.0.0-dev", path = "../api" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } -codec = { package = "parity-scale-codec", version = "2.0.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } futures = "0.3.16" jsonrpc-pubsub = "18.0.0" log = "0.4.8" @@ -35,7 +35,7 @@ sc-block-builder = { version = "0.10.0-dev", path = "../block-builder" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sc-tracing = { version = "4.0.0-dev", path = "../tracing" } hash-db = { version = "0.15.2", default-features = false } -parking_lot = "0.11.2" +parking_lot = "0.12.0" lazy_static = { version = "1.4.0", optional = true } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../transaction-pool/api" } diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index 55ca01a2284a..e007486d9ef1 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -27,7 +27,7 @@ futures = "0.3.16" jsonrpc-pubsub = "18.0" jsonrpc-core = "18.0" rand = "0.7.3" -parking_lot = "0.11.2" +parking_lot = "0.12.0" log = "0.4.11" futures-timer = "3.0.1" exit-future = "0.2.0" @@ -56,7 +56,7 @@ sc-chain-spec = { version = "4.0.0-dev", path = "../chain-spec" } sc-client-api = { version = "4.0.0-dev", path = "../api" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } sc-client-db = { version = "0.10.0-dev", default-features = false, path = "../db" } -codec = { package = "parity-scale-codec", version = "2.0.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } sc-executor = { version = "0.10.0-dev", path = "../executor" } sc-transaction-pool = { version = "4.0.0-dev", path = "../transaction-pool" } sp-transaction-pool = { version = "4.0.0-dev", path = "../../primitives/transaction-pool" } @@ -74,7 +74,7 @@ sc-tracing = { version = "4.0.0-dev", path = "../tracing" } sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } tracing = "0.1.29" tracing-futures = { version = "0.2.4" } -parity-util-mem = { version = "0.10.2", default-features = false, features = [ +parity-util-mem = { version = "0.11.0", default-features = false, features = [ "primitive-types", ] } async-trait = "0.1.50" diff --git a/client/service/test/Cargo.toml b/client/service/test/Cargo.toml index 6395f9d9877d..a815d1f5571f 100644 --- a/client/service/test/Cargo.toml +++ b/client/service/test/Cargo.toml @@ -18,7 +18,7 @@ tempfile = "3.1.0" tokio = { version = "1.15.0", features = ["time"] } log = "0.4.8" fdlimit = "0.2.1" -parking_lot = "0.11.2" +parking_lot = "0.12.0" sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-state-machine = { version = "0.11.0", path = "../../../primitives/state-machine" } @@ -40,5 +40,5 @@ sc-client-api = { version = "4.0.0-dev", path = "../../api" } sc-block-builder = { version = "0.10.0-dev", path = "../../block-builder" } sc-executor = { version = "0.10.0-dev", path = "../../executor" } sp-panic-handler = { version = "4.0.0", path = "../../../primitives/panic-handler" } -parity-scale-codec = "2.3.1" +parity-scale-codec = "3.0.0" sp-tracing = { version = "4.0.0", path = "../../../primitives/tracing" } diff --git a/client/state-db/Cargo.toml b/client/state-db/Cargo.toml index fa0c5ed9810c..bf45ad49043c 100644 --- a/client/state-db/Cargo.toml +++ b/client/state-db/Cargo.toml @@ -13,10 +13,10 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -parking_lot = "0.11.2" +parking_lot = "0.12.0" log = "0.4.11" sc-client-api = { version = "4.0.0-dev", path = "../api" } sp-core = { version = "5.0.0", path = "../../primitives/core" } -codec = { package = "parity-scale-codec", version = "2.0.0", features = ["derive"] } -parity-util-mem = { version = "0.10.2", default-features = false, features = ["primitive-types"] } +codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"] } +parity-util-mem = { version = "0.11.0", default-features = false, features = ["primitive-types"] } parity-util-mem-derive = "0.1.0" diff --git a/client/sync-state-rpc/Cargo.toml b/client/sync-state-rpc/Cargo.toml index 3e064685488d..524e9259288a 100644 --- a/client/sync-state-rpc/Cargo.toml +++ b/client/sync-state-rpc/Cargo.toml @@ -26,4 +26,4 @@ serde_json = "1.0.74" serde = { version = "1.0.136", features = ["derive"] } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } -codec = { package = "parity-scale-codec", version = "2.0.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } diff --git a/client/telemetry/Cargo.toml b/client/telemetry/Cargo.toml index 595a57402159..2339fa277cca 100644 --- a/client/telemetry/Cargo.toml +++ b/client/telemetry/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] -parking_lot = "0.11.2" +parking_lot = "0.12.0" futures = "0.3.9" wasm-timer = "0.2.5" libp2p = { version = "0.40.0", default-features = false, features = ["dns-async-std", "tcp-async-io", "wasm-ext", "websocket"] } diff --git a/client/tracing/Cargo.toml b/client/tracing/Cargo.toml index 5f7e0831a536..2d892c926eb6 100644 --- a/client/tracing/Cargo.toml +++ b/client/tracing/Cargo.toml @@ -20,7 +20,7 @@ lazy_static = "1.4.0" libc = "0.2.112" log = { version = "0.4.8" } once_cell = "1.8.0" -parking_lot = "0.11.2" +parking_lot = "0.12.0" regex = "1.5.4" rustc-hash = "1.1.0" serde = "1.0.136" diff --git a/client/transaction-pool/Cargo.toml b/client/transaction-pool/Cargo.toml index 42172ce723e1..a5d6d4e1bf74 100644 --- a/client/transaction-pool/Cargo.toml +++ b/client/transaction-pool/Cargo.toml @@ -13,13 +13,13 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } thiserror = "1.0.30" futures = "0.3.16" futures-timer = "3.0.2" log = "0.4.8" -parity-util-mem = { version = "0.10.2", default-features = false, features = ["primitive-types"] } -parking_lot = "0.11.2" +parity-util-mem = { version = "0.11.0", default-features = false, features = ["primitive-types"] } +parking_lot = "0.12.0" prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.10.0-dev"} sc-client-api = { version = "4.0.0-dev", path = "../api" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } @@ -41,7 +41,6 @@ sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/comm substrate-test-runtime-transaction-pool = { version = "2.0.0", path = "../../test-utils/runtime/transaction-pool" } substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } sc-block-builder = { version = "0.10.0-dev", path = "../block-builder" } -codec = { package = "parity-scale-codec", version = "2.0.0" } substrate-test-runtime = { version = "2.0.0", path = "../../test-utils/runtime" } criterion = "0.3" diff --git a/client/utils/Cargo.toml b/client/utils/Cargo.toml index 24075f932b50..c5acff24548a 100644 --- a/client/utils/Cargo.toml +++ b/client/utils/Cargo.toml @@ -12,7 +12,7 @@ readme = "README.md" [dependencies] futures = "0.3.9" lazy_static = "1.4.0" -parking_lot = "0.11" +parking_lot = "0.12.0" prometheus = { version = "0.13.0", default-features = false } futures-timer = "3.0.2" diff --git a/frame/assets/Cargo.toml b/frame/assets/Cargo.toml index c5d60291fc43..02faa20d03f9 100644 --- a/frame/assets/Cargo.toml +++ b/frame/assets/Cargo.toml @@ -13,8 +13,8 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } # Needed for various traits. In our case, `OnFinalize`. sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } diff --git a/frame/atomic-swap/Cargo.toml b/frame/atomic-swap/Cargo.toml index 1dcd6154d0be..7b737d15d2f5 100644 --- a/frame/atomic-swap/Cargo.toml +++ b/frame/atomic-swap/Cargo.toml @@ -13,8 +13,8 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } diff --git a/frame/aura/Cargo.toml b/frame/aura/Cargo.toml index f869ddb41702..3b1a96f66c46 100644 --- a/frame/aura/Cargo.toml +++ b/frame/aura/Cargo.toml @@ -14,8 +14,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-application-crypto = { version = "5.0.0", default-features = false, path = "../../primitives/application-crypto" } -codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/frame/authority-discovery/Cargo.toml b/frame/authority-discovery/Cargo.toml index b6e8a400f865..509cea33f6a9 100644 --- a/frame/authority-discovery/Cargo.toml +++ b/frame/authority-discovery/Cargo.toml @@ -15,10 +15,10 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-authority-discovery = { version = "4.0.0-dev", default-features = false, path = "../../primitives/authority-discovery" } sp-application-crypto = { version = "5.0.0", default-features = false, path = "../../primitives/application-crypto" } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", ] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } pallet-session = { version = "4.0.0-dev", features = [ "historical", diff --git a/frame/authorship/Cargo.toml b/frame/authorship/Cargo.toml index 31daa74553c2..379a1ab97b8b 100644 --- a/frame/authorship/Cargo.toml +++ b/frame/authorship/Cargo.toml @@ -13,10 +13,10 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", ] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-authorship = { version = "4.0.0-dev", default-features = false, path = "../../primitives/authorship" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } diff --git a/frame/babe/Cargo.toml b/frame/babe/Cargo.toml index f48877746b88..88be992250c7 100644 --- a/frame/babe/Cargo.toml +++ b/frame/babe/Cargo.toml @@ -13,8 +13,8 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/bags-list/Cargo.toml b/frame/bags-list/Cargo.toml index c35ff6fc6c39..18e2c048186c 100644 --- a/frame/bags-list/Cargo.toml +++ b/frame/bags-list/Cargo.toml @@ -14,8 +14,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] # parity -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } # primitives sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } diff --git a/frame/balances/Cargo.toml b/frame/balances/Cargo.toml index f594e67ab861..f7e7c662b020 100644 --- a/frame/balances/Cargo.toml +++ b/frame/balances/Cargo.toml @@ -13,8 +13,8 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } diff --git a/frame/beefy-mmr/Cargo.toml b/frame/beefy-mmr/Cargo.toml index bb30c540ca1c..c5aafa94295e 100644 --- a/frame/beefy-mmr/Cargo.toml +++ b/frame/beefy-mmr/Cargo.toml @@ -9,10 +9,10 @@ repository = "https://github.com/paritytech/substrate" [dependencies] hex = { version = "0.4", optional = true } -codec = { version = "2.2.0", package = "parity-scale-codec", default-features = false, features = ["derive"] } +codec = { version = "3.0.0", package = "parity-scale-codec", default-features = false, features = ["derive"] } k256 = { version = "0.10.2", default-features = false, features = ["arithmetic"] } log = { version = "0.4.13", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } serde = { version = "1.0.136", optional = true } frame-support = { version = "4.0.0-dev", path = "../support", default-features = false } diff --git a/frame/beefy/Cargo.toml b/frame/beefy/Cargo.toml index 5844657dd50c..ed5682fdb474 100644 --- a/frame/beefy/Cargo.toml +++ b/frame/beefy/Cargo.toml @@ -8,8 +8,8 @@ repository = "https://github.com/paritytech/substrate" description = "BEEFY FRAME pallet" [dependencies] -codec = { version = "2.2.0", package = "parity-scale-codec", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { version = "3.0.0", package = "parity-scale-codec", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } serde = { version = "1.0.136", optional = true } frame-support = { version = "4.0.0-dev", path = "../support", default-features = false } diff --git a/frame/benchmarking/Cargo.toml b/frame/benchmarking/Cargo.toml index ad6f99c64517..87089247cc95 100644 --- a/frame/benchmarking/Cargo.toml +++ b/frame/benchmarking/Cargo.toml @@ -15,8 +15,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] linregress = { version = "0.4.4", optional = true } paste = "1.0" -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-api = { version = "4.0.0-dev", path = "../../primitives/api", default-features = false } sp-runtime-interface = { version = "5.0.0", path = "../../primitives/runtime-interface", default-features = false } sp-runtime = { version = "5.0.0", path = "../../primitives/runtime", default-features = false } diff --git a/frame/bounties/Cargo.toml b/frame/bounties/Cargo.toml index 477815a306f3..cc35d54f25e1 100644 --- a/frame/bounties/Cargo.toml +++ b/frame/bounties/Cargo.toml @@ -13,10 +13,10 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", ] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/frame/child-bounties/Cargo.toml b/frame/child-bounties/Cargo.toml index 0eeefd4de459..d912bce112b8 100644 --- a/frame/child-bounties/Cargo.toml +++ b/frame/child-bounties/Cargo.toml @@ -13,10 +13,10 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", ] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/frame/collective/Cargo.toml b/frame/collective/Cargo.toml index 334b4945afa2..c679bb21e820 100644 --- a/frame/collective/Cargo.toml +++ b/frame/collective/Cargo.toml @@ -13,9 +13,9 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } log = { version = "0.4.14", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } diff --git a/frame/contracts/Cargo.toml b/frame/contracts/Cargo.toml index 5ab1389f65c1..cf726b76a5f7 100644 --- a/frame/contracts/Cargo.toml +++ b/frame/contracts/Cargo.toml @@ -14,11 +14,11 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] bitflags = "1.3" -codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", "max-encoded-len", ] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } log = { version = "0.4", default-features = false } wasm-instrument = { version = "0.1", default-features = false } serde = { version = "1", optional = true, features = ["derive"] } diff --git a/frame/contracts/common/Cargo.toml b/frame/contracts/common/Cargo.toml index ad934c41a71f..d19a160fc45c 100644 --- a/frame/contracts/common/Cargo.toml +++ b/frame/contracts/common/Cargo.toml @@ -14,8 +14,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] bitflags = "1.0" -codec = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } serde = { version = "1", features = ["derive"], optional = true } # Substrate Dependencies (This crate should not rely on frame) diff --git a/frame/contracts/rpc/Cargo.toml b/frame/contracts/rpc/Cargo.toml index 52ca0e6d8345..57429fed6722 100644 --- a/frame/contracts/rpc/Cargo.toml +++ b/frame/contracts/rpc/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2" } +codec = { package = "parity-scale-codec", version = "3.0.0" } jsonrpc-core = "18.0.0" jsonrpc-core-client = "18.0.0" jsonrpc-derive = "18.0.0" diff --git a/frame/contracts/rpc/runtime-api/Cargo.toml b/frame/contracts/rpc/runtime-api/Cargo.toml index 8ecdff517537..071b4bafeef4 100644 --- a/frame/contracts/rpc/runtime-api/Cargo.toml +++ b/frame/contracts/rpc/runtime-api/Cargo.toml @@ -13,8 +13,8 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } # Substrate Dependencies pallet-contracts-primitives = { version = "5.0.0", default-features = false, path = "../../common" } diff --git a/frame/conviction-voting/Cargo.toml b/frame/conviction-voting/Cargo.toml index 7b51e3f8c91a..039fdb07caab 100644 --- a/frame/conviction-voting/Cargo.toml +++ b/frame/conviction-voting/Cargo.toml @@ -14,10 +14,10 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.136", optional = true, features = ["derive"] } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", ] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } diff --git a/frame/democracy/Cargo.toml b/frame/democracy/Cargo.toml index 743cea074ee2..e6fe550f8845 100644 --- a/frame/democracy/Cargo.toml +++ b/frame/democracy/Cargo.toml @@ -14,10 +14,10 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.136", optional = true, features = ["derive"] } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", ] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } diff --git a/frame/election-provider-multi-phase/Cargo.toml b/frame/election-provider-multi-phase/Cargo.toml index c0d85737ec22..e96e9c446442 100644 --- a/frame/election-provider-multi-phase/Cargo.toml +++ b/frame/election-provider-multi-phase/Cargo.toml @@ -14,10 +14,10 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] static_assertions = "1.1.0" -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", ] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } log = { version = "0.4.14", default-features = false } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } @@ -40,7 +40,7 @@ rand = { version = "0.7.3", default-features = false, optional = true, features strum = { optional = true, default-features = false, version = "0.23.0", features = ["derive"] } [dev-dependencies] -parking_lot = "0.11.2" +parking_lot = "0.12.0" rand = { version = "0.7.3" } sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } sp-io = { version = "5.0.0", path = "../../primitives/io" } diff --git a/frame/election-provider-support/Cargo.toml b/frame/election-provider-support/Cargo.toml index 662762ef6306..0d11a4ac503e 100644 --- a/frame/election-provider-support/Cargo.toml +++ b/frame/election-provider-support/Cargo.toml @@ -13,8 +13,8 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-arithmetic = { version = "4.0.0", default-features = false, path = "../../primitives/arithmetic" } sp-npos-elections = { version = "4.0.0-dev", default-features = false, path = "../../primitives/npos-elections" } diff --git a/frame/elections-phragmen/Cargo.toml b/frame/elections-phragmen/Cargo.toml index f70eb568349b..3312e4863a64 100644 --- a/frame/elections-phragmen/Cargo.toml +++ b/frame/elections-phragmen/Cargo.toml @@ -13,10 +13,10 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", ] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } sp-npos-elections = { version = "4.0.0-dev", default-features = false, path = "../../primitives/npos-elections" } sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } diff --git a/frame/examples/basic/Cargo.toml b/frame/examples/basic/Cargo.toml index 73c11475fdf6..c368af4267c3 100644 --- a/frame/examples/basic/Cargo.toml +++ b/frame/examples/basic/Cargo.toml @@ -13,9 +13,9 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } log = { version = "0.4.14", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" } diff --git a/frame/examples/offchain-worker/Cargo.toml b/frame/examples/offchain-worker/Cargo.toml index e7ae323050ee..bf6acd652b61 100644 --- a/frame/examples/offchain-worker/Cargo.toml +++ b/frame/examples/offchain-worker/Cargo.toml @@ -13,10 +13,10 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } lite-json = { version = "0.1", default-features = false } log = { version = "0.4.14", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" } diff --git a/frame/examples/parallel/Cargo.toml b/frame/examples/parallel/Cargo.toml index 8d291df19136..ba3c6de5d17a 100644 --- a/frame/examples/parallel/Cargo.toml +++ b/frame/examples/parallel/Cargo.toml @@ -12,8 +12,8 @@ description = "FRAME example pallet using runtime worker threads" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" } diff --git a/frame/executive/Cargo.toml b/frame/executive/Cargo.toml index b261aecdf926..dd37b27d4eb9 100644 --- a/frame/executive/Cargo.toml +++ b/frame/executive/Cargo.toml @@ -13,10 +13,10 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", ] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } diff --git a/frame/gilt/Cargo.toml b/frame/gilt/Cargo.toml index 7ed17d152a01..52b5be3a857b 100644 --- a/frame/gilt/Cargo.toml +++ b/frame/gilt/Cargo.toml @@ -13,8 +13,8 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } sp-arithmetic = { version = "4.0.0", default-features = false, path = "../../primitives/arithmetic" } diff --git a/frame/grandpa/Cargo.toml b/frame/grandpa/Cargo.toml index eda9d630d4f9..52f7b02a387b 100644 --- a/frame/grandpa/Cargo.toml +++ b/frame/grandpa/Cargo.toml @@ -13,8 +13,8 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-application-crypto = { version = "5.0.0", default-features = false, path = "../../primitives/application-crypto" } sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } sp-finality-grandpa = { version = "4.0.0-dev", default-features = false, path = "../../primitives/finality-grandpa" } @@ -32,7 +32,7 @@ log = { version = "0.4.14", default-features = false } [dev-dependencies] frame-benchmarking = { version = "4.0.0-dev", path = "../benchmarking" } -grandpa = { package = "finality-grandpa", version = "0.14.1", features = ["derive-codec"] } +grandpa = { package = "finality-grandpa", version = "0.15.0", features = ["derive-codec"] } sp-keyring = { version = "5.0.0", path = "../../primitives/keyring" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } pallet-offences = { version = "4.0.0-dev", path = "../offences" } diff --git a/frame/identity/Cargo.toml b/frame/identity/Cargo.toml index 209896ec0e55..61ac2907a9cd 100644 --- a/frame/identity/Cargo.toml +++ b/frame/identity/Cargo.toml @@ -13,8 +13,8 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } enumflags2 = { version = "0.6.2" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } diff --git a/frame/im-online/Cargo.toml b/frame/im-online/Cargo.toml index d223e5e8502d..119010ef6b04 100644 --- a/frame/im-online/Cargo.toml +++ b/frame/im-online/Cargo.toml @@ -15,8 +15,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-application-crypto = { version = "5.0.0", default-features = false, path = "../../primitives/application-crypto" } pallet-authorship = { version = "4.0.0-dev", default-features = false, path = "../authorship" } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } diff --git a/frame/indices/Cargo.toml b/frame/indices/Cargo.toml index 28a6427f520b..74d84849c37d 100644 --- a/frame/indices/Cargo.toml +++ b/frame/indices/Cargo.toml @@ -13,8 +13,8 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-keyring = { version = "5.0.0", optional = true, path = "../../primitives/keyring" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } diff --git a/frame/lottery/Cargo.toml b/frame/lottery/Cargo.toml index 2e2c2287a2ab..e43339c1eafa 100644 --- a/frame/lottery/Cargo.toml +++ b/frame/lottery/Cargo.toml @@ -13,10 +13,10 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", ] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/frame/membership/Cargo.toml b/frame/membership/Cargo.toml index f2f7607ce9a5..abf27710cf60 100644 --- a/frame/membership/Cargo.toml +++ b/frame/membership/Cargo.toml @@ -13,8 +13,8 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } log = { version = "0.4.0", default-features = false } sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } diff --git a/frame/merkle-mountain-range/Cargo.toml b/frame/merkle-mountain-range/Cargo.toml index a614ffa97715..82c08a3c262f 100644 --- a/frame/merkle-mountain-range/Cargo.toml +++ b/frame/merkle-mountain-range/Cargo.toml @@ -12,8 +12,8 @@ description = "FRAME Merkle Mountain Range pallet." targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } mmr-lib = { package = "ckb-merkle-mountain-range", default-features = false, version = "0.3.2" } sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } diff --git a/frame/merkle-mountain-range/primitives/Cargo.toml b/frame/merkle-mountain-range/primitives/Cargo.toml index d281f159beba..fe50ca722200 100644 --- a/frame/merkle-mountain-range/primitives/Cargo.toml +++ b/frame/merkle-mountain-range/primitives/Cargo.toml @@ -12,7 +12,7 @@ description = "FRAME Merkle Mountain Range primitives." targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } log = { version = "0.4.14", default-features = false } serde = { version = "1.0.136", optional = true, features = ["derive"] } diff --git a/frame/merkle-mountain-range/rpc/Cargo.toml b/frame/merkle-mountain-range/rpc/Cargo.toml index 7dc891267ceb..6ae0e7a3f076 100644 --- a/frame/merkle-mountain-range/rpc/Cargo.toml +++ b/frame/merkle-mountain-range/rpc/Cargo.toml @@ -13,7 +13,7 @@ publish = false targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } jsonrpc-core = "18.0.0" jsonrpc-core-client = "18.0.0" jsonrpc-derive = "18.0.0" diff --git a/frame/multisig/Cargo.toml b/frame/multisig/Cargo.toml index dfc05888b1aa..8251c7bc9c71 100644 --- a/frame/multisig/Cargo.toml +++ b/frame/multisig/Cargo.toml @@ -13,8 +13,8 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } diff --git a/frame/nicks/Cargo.toml b/frame/nicks/Cargo.toml index bf5afd26ebb5..0acdd4b5bb55 100644 --- a/frame/nicks/Cargo.toml +++ b/frame/nicks/Cargo.toml @@ -13,8 +13,8 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } diff --git a/frame/node-authorization/Cargo.toml b/frame/node-authorization/Cargo.toml index 0d6425188538..63106ec0aa9b 100644 --- a/frame/node-authorization/Cargo.toml +++ b/frame/node-authorization/Cargo.toml @@ -12,8 +12,8 @@ description = "FRAME pallet for node authorization" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } diff --git a/frame/offences/Cargo.toml b/frame/offences/Cargo.toml index 053708c8b247..f6a1fe7c190f 100644 --- a/frame/offences/Cargo.toml +++ b/frame/offences/Cargo.toml @@ -14,8 +14,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../balances" } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } serde = { version = "1.0.136", optional = true } sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } diff --git a/frame/offences/benchmarking/Cargo.toml b/frame/offences/benchmarking/Cargo.toml index 974254538322..ebab8114c1bb 100644 --- a/frame/offences/benchmarking/Cargo.toml +++ b/frame/offences/benchmarking/Cargo.toml @@ -13,8 +13,8 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../../benchmarking" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" } diff --git a/frame/preimage/Cargo.toml b/frame/preimage/Cargo.toml index 66ef8467be28..9cffedf6c215 100644 --- a/frame/preimage/Cargo.toml +++ b/frame/preimage/Cargo.toml @@ -10,8 +10,8 @@ description = "FRAME pallet for storing preimages of hashes" readme = "README.md" [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } diff --git a/frame/proxy/Cargo.toml b/frame/proxy/Cargo.toml index f0bd9391789b..8bf0a1469c37 100644 --- a/frame/proxy/Cargo.toml +++ b/frame/proxy/Cargo.toml @@ -13,8 +13,8 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["max-encoded-len"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["max-encoded-len"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } diff --git a/frame/randomness-collective-flip/Cargo.toml b/frame/randomness-collective-flip/Cargo.toml index a93585700f2b..d6fb14c02d8d 100644 --- a/frame/randomness-collective-flip/Cargo.toml +++ b/frame/randomness-collective-flip/Cargo.toml @@ -14,8 +14,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] safe-mix = { version = "1.0", default-features = false } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } diff --git a/frame/recovery/Cargo.toml b/frame/recovery/Cargo.toml index 88da65327e2f..a629b0bbf0e3 100644 --- a/frame/recovery/Cargo.toml +++ b/frame/recovery/Cargo.toml @@ -13,8 +13,8 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } diff --git a/frame/referenda/Cargo.toml b/frame/referenda/Cargo.toml index 46ede8c1eed0..a3067956db2b 100644 --- a/frame/referenda/Cargo.toml +++ b/frame/referenda/Cargo.toml @@ -14,10 +14,10 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.136", optional = true, features = ["derive"] } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", ] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } diff --git a/frame/scheduler/Cargo.toml b/frame/scheduler/Cargo.toml index d88063d69c5b..c45d961bd694 100644 --- a/frame/scheduler/Cargo.toml +++ b/frame/scheduler/Cargo.toml @@ -10,8 +10,8 @@ description = "FRAME Scheduler pallet" readme = "README.md" [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } log = { version = "0.4.14", default-features = false } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } diff --git a/frame/scored-pool/Cargo.toml b/frame/scored-pool/Cargo.toml index af8b0f6aa264..934400230f7a 100644 --- a/frame/scored-pool/Cargo.toml +++ b/frame/scored-pool/Cargo.toml @@ -13,8 +13,8 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } diff --git a/frame/session/Cargo.toml b/frame/session/Cargo.toml index a342865615d9..9bd4d1fc5095 100644 --- a/frame/session/Cargo.toml +++ b/frame/session/Cargo.toml @@ -16,8 +16,8 @@ targets = ["x86_64-unknown-linux-gnu"] log = { version = "0.4.0", default-features = false } impl-trait-for-tuples = "0.2.1" -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } diff --git a/frame/session/benchmarking/Cargo.toml b/frame/session/benchmarking/Cargo.toml index cd33c5b18649..598c3a73e2e3 100644 --- a/frame/session/benchmarking/Cargo.toml +++ b/frame/session/benchmarking/Cargo.toml @@ -26,8 +26,8 @@ pallet-session = { version = "4.0.0-dev", default-features = false, path = "../. pallet-staking = { version = "4.0.0-dev", default-features = false, features = ["runtime-benchmarks"], path = "../../staking" } [dev-dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", features = ["derive"] } -scale-info = "1.0" +codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"] } +scale-info = "2.0.0" sp-core = { version = "5.0.0", path = "../../../primitives/core" } sp-io = { version = "5.0.0", path = "../../../primitives/io" } pallet-balances = { version = "4.0.0-dev", path = "../../balances" } diff --git a/frame/society/Cargo.toml b/frame/society/Cargo.toml index 2787453d49d3..12fb4202888c 100644 --- a/frame/society/Cargo.toml +++ b/frame/society/Cargo.toml @@ -13,8 +13,8 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/frame/staking/Cargo.toml b/frame/staking/Cargo.toml index 363ffe4428fb..6e85382ddaa2 100644 --- a/frame/staking/Cargo.toml +++ b/frame/staking/Cargo.toml @@ -14,10 +14,10 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.136", optional = true } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", ] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } diff --git a/frame/sudo/Cargo.toml b/frame/sudo/Cargo.toml index 063ea52d5b8b..a4b1d21e9efc 100644 --- a/frame/sudo/Cargo.toml +++ b/frame/sudo/Cargo.toml @@ -13,8 +13,8 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } diff --git a/frame/support/Cargo.toml b/frame/support/Cargo.toml index a5ba2fad18b3..9bb7ae5d8af8 100644 --- a/frame/support/Cargo.toml +++ b/frame/support/Cargo.toml @@ -14,9 +14,9 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.136", optional = true, features = ["derive"] } -codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } -frame-metadata = { version = "14.2.0", default-features = false, features = ["v14"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +frame-metadata = { version = "15.0.0", default-features = false, features = ["v14"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } @@ -40,7 +40,7 @@ sp-core-hashing-proc-macro = { version = "4.0.0-dev", path = "../../primitives/c assert_matches = "1.3.0" pretty_assertions = "1.0.0" frame-system = { version = "4.0.0-dev", path = "../system" } -parity-util-mem = { version = "0.10.2", default-features = false, features = ["primitive-types"] } +parity-util-mem = { version = "0.11.0", default-features = false, features = ["primitive-types"] } [features] default = ["std"] diff --git a/frame/support/test/Cargo.toml b/frame/support/test/Cargo.toml index 9f26df4869af..56e269b43265 100644 --- a/frame/support/test/Cargo.toml +++ b/frame/support/test/Cargo.toml @@ -13,8 +13,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.136", default-features = false, features = ["derive"] } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-arithmetic = { version = "4.0.0", default-features = false, path = "../../../primitives/arithmetic" } sp-io = { version = "5.0.0", path = "../../../primitives/io", default-features = false } sp-state-machine = { version = "0.11.0", optional = true, path = "../../../primitives/state-machine" } diff --git a/frame/support/test/compile_pass/Cargo.toml b/frame/support/test/compile_pass/Cargo.toml index aaa080f84f1a..241ec1b352f4 100644 --- a/frame/support/test/compile_pass/Cargo.toml +++ b/frame/support/test/compile_pass/Cargo.toml @@ -12,8 +12,8 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-core = { version = "5.0.0", default-features = false, path = "../../../../primitives/core" } sp-runtime = { version = "5.0.0", default-features = false, path = "../../../../primitives/runtime" } sp-version = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/version" } diff --git a/frame/support/test/pallet/Cargo.toml b/frame/support/test/pallet/Cargo.toml index c26fdda4e962..51b74d5ec55f 100644 --- a/frame/support/test/pallet/Cargo.toml +++ b/frame/support/test/pallet/Cargo.toml @@ -12,8 +12,8 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../../" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../../system" } diff --git a/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr b/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr index b4a10a6af01f..e9d267274a6e 100644 --- a/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr +++ b/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr @@ -49,7 +49,7 @@ error[E0277]: the trait bound `::Bar: WrapperTypeEncode` is | = note: required because of the requirements on the impl of `Encode` for `::Bar` note: required by a bound in `encode_to` - --> $CARGO/parity-scale-codec-2.3.1/src/codec.rs + --> $CARGO/parity-scale-codec-3.0.0/src/codec.rs | | fn encode_to(&self, dest: &mut T) { | ^^^^^^ required by this bound in `encode_to` @@ -63,7 +63,7 @@ error[E0277]: the trait bound `::Bar: WrapperTypeDecode` is | = note: required because of the requirements on the impl of `Decode` for `::Bar` note: required by a bound in `parity_scale_codec::Decode::decode` - --> $CARGO/parity-scale-codec-2.3.1/src/codec.rs + --> $CARGO/parity-scale-codec-3.0.0/src/codec.rs | | fn decode(input: &mut I) -> Result; | ^^^^^ required by this bound in `parity_scale_codec::Decode::decode` diff --git a/frame/system/Cargo.toml b/frame/system/Cargo.toml index 5d45544fe7bb..a941f6e95ede 100644 --- a/frame/system/Cargo.toml +++ b/frame/system/Cargo.toml @@ -14,8 +14,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.136", optional = true, features = ["derive"] } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "5.0.0", path = "../../primitives/io", default-features = false } diff --git a/frame/system/benchmarking/Cargo.toml b/frame/system/benchmarking/Cargo.toml index fa86250c199e..858d6954405f 100644 --- a/frame/system/benchmarking/Cargo.toml +++ b/frame/system/benchmarking/Cargo.toml @@ -13,8 +13,8 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } sp-runtime = { version = "5.0.0", default-features = false, path = "../../../primitives/runtime" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../../benchmarking" } diff --git a/frame/system/rpc/runtime-api/Cargo.toml b/frame/system/rpc/runtime-api/Cargo.toml index 67e627f7dcf9..e2f85000f5d0 100644 --- a/frame/system/rpc/runtime-api/Cargo.toml +++ b/frame/system/rpc/runtime-api/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/api" } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } [features] default = ["std"] diff --git a/frame/timestamp/Cargo.toml b/frame/timestamp/Cargo.toml index f42a95010587..8cb78c216432 100644 --- a/frame/timestamp/Cargo.toml +++ b/frame/timestamp/Cargo.toml @@ -15,8 +15,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io", optional = true } sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } diff --git a/frame/tips/Cargo.toml b/frame/tips/Cargo.toml index f898a255b87c..78e260e2368c 100644 --- a/frame/tips/Cargo.toml +++ b/frame/tips/Cargo.toml @@ -13,9 +13,9 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } log = { version = "0.4.0", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } serde = { version = "1.0.136", features = ["derive"], optional = true } sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } diff --git a/frame/transaction-payment/Cargo.toml b/frame/transaction-payment/Cargo.toml index 1f27e355b1d9..fe6b4e0e2c7c 100644 --- a/frame/transaction-payment/Cargo.toml +++ b/frame/transaction-payment/Cargo.toml @@ -13,10 +13,10 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", ] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } serde = { version = "1.0.136", optional = true } smallvec = "1.7.0" diff --git a/frame/transaction-payment/asset-tx-payment/Cargo.toml b/frame/transaction-payment/asset-tx-payment/Cargo.toml index 6f42595d200c..7768ae76847a 100644 --- a/frame/transaction-payment/asset-tx-payment/Cargo.toml +++ b/frame/transaction-payment/asset-tx-payment/Cargo.toml @@ -24,8 +24,8 @@ frame-system = { version = "4.0.0-dev", default-features = false, path = "../../ pallet-transaction-payment = { version = "4.0.0-dev", default-features = false, path = ".." } # Other dependencies -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } serde = { version = "1.0.136", optional = true } [dev-dependencies] diff --git a/frame/transaction-payment/rpc/Cargo.toml b/frame/transaction-payment/rpc/Cargo.toml index 844e898ed867..f5d5036978b4 100644 --- a/frame/transaction-payment/rpc/Cargo.toml +++ b/frame/transaction-payment/rpc/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } jsonrpc-core = "18.0.0" jsonrpc-core-client = "18.0.0" jsonrpc-derive = "18.0.0" diff --git a/frame/transaction-payment/rpc/runtime-api/Cargo.toml b/frame/transaction-payment/rpc/runtime-api/Cargo.toml index fed57eb5bf73..82bab82a305f 100644 --- a/frame/transaction-payment/rpc/runtime-api/Cargo.toml +++ b/frame/transaction-payment/rpc/runtime-api/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/api" } sp-runtime = { version = "5.0.0", default-features = false, path = "../../../../primitives/runtime" } pallet-transaction-payment = { version = "4.0.0-dev", default-features = false, path = "../../../transaction-payment" } diff --git a/frame/transaction-storage/Cargo.toml b/frame/transaction-storage/Cargo.toml index f33607058f37..e1275e2476f9 100644 --- a/frame/transaction-storage/Cargo.toml +++ b/frame/transaction-storage/Cargo.toml @@ -15,8 +15,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.136", optional = true } hex-literal = { version = "0.3.4", optional = true } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../balances" } diff --git a/frame/treasury/Cargo.toml b/frame/treasury/Cargo.toml index a7a210457f02..bbcffa68f083 100644 --- a/frame/treasury/Cargo.toml +++ b/frame/treasury/Cargo.toml @@ -13,11 +13,11 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", "max-encoded-len", ] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } serde = { version = "1.0.136", features = ["derive"], optional = true } impl-trait-for-tuples = "0.2.1" diff --git a/frame/uniques/Cargo.toml b/frame/uniques/Cargo.toml index 4e0194b17acb..e0761711501d 100644 --- a/frame/uniques/Cargo.toml +++ b/frame/uniques/Cargo.toml @@ -13,8 +13,8 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/frame/utility/Cargo.toml b/frame/utility/Cargo.toml index ea3977c1b8b2..6397bf028eed 100644 --- a/frame/utility/Cargo.toml +++ b/frame/utility/Cargo.toml @@ -13,8 +13,8 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } diff --git a/frame/vesting/Cargo.toml b/frame/vesting/Cargo.toml index f7dcfd9fa442..52942c8670a3 100644 --- a/frame/vesting/Cargo.toml +++ b/frame/vesting/Cargo.toml @@ -13,10 +13,10 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", ] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/primitives/api/Cargo.toml b/primitives/api/Cargo.toml index ab81ed85f188..c210201a3115 100644 --- a/primitives/api/Cargo.toml +++ b/primitives/api/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } sp-api-proc-macro = { version = "4.0.0-dev", path = "proc-macro" } sp-core = { version = "5.0.0", default-features = false, path = "../core" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } diff --git a/primitives/api/proc-macro/src/decl_runtime_apis.rs b/primitives/api/proc-macro/src/decl_runtime_apis.rs index 6de20df8a41d..bc72aaa81681 100644 --- a/primitives/api/proc-macro/src/decl_runtime_apis.rs +++ b/primitives/api/proc-macro/src/decl_runtime_apis.rs @@ -181,7 +181,7 @@ fn generate_native_call_generators(decl: &ItemTrait) -> Result { { ::decode_with_depth_limit( #crate_::MAX_EXTRINSIC_DEPTH, - &#crate_::Encode::encode(input)[..], + &mut &#crate_::Encode::encode(input)[..], ).map_err(map_error) } )); diff --git a/primitives/api/proc-macro/src/impl_runtime_apis.rs b/primitives/api/proc-macro/src/impl_runtime_apis.rs index f6de60e1c99b..ae18849d83cc 100644 --- a/primitives/api/proc-macro/src/impl_runtime_apis.rs +++ b/primitives/api/proc-macro/src/impl_runtime_apis.rs @@ -86,7 +86,7 @@ fn generate_impl_call( let (#( #pnames ),*) : ( #( #ptypes ),* ) = match #c::DecodeLimit::decode_all_with_depth_limit( #c::MAX_EXTRINSIC_DEPTH, - &#input, + &mut #input, ) { Ok(res) => res, Err(e) => panic!("Bad input data provided to {}: {}", #fn_name_str, e), diff --git a/primitives/api/test/Cargo.toml b/primitives/api/test/Cargo.toml index 064e6a6c9818..8edb2a31fb55 100644 --- a/primitives/api/test/Cargo.toml +++ b/primitives/api/test/Cargo.toml @@ -19,7 +19,7 @@ sp-tracing = { version = "4.0.0", path = "../../tracing" } sp-runtime = { version = "5.0.0", path = "../../runtime" } sp-consensus = { version = "0.10.0-dev", path = "../../consensus/common" } sc-block-builder = { version = "0.10.0-dev", path = "../../../client/block-builder" } -codec = { package = "parity-scale-codec", version = "2.0.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } sp-state-machine = { version = "0.11.0", path = "../../state-machine" } trybuild = "1.0.53" rustversion = "1.0.6" diff --git a/primitives/application-crypto/Cargo.toml b/primitives/application-crypto/Cargo.toml index 818ddbdcc182..45622d6a5393 100644 --- a/primitives/application-crypto/Cargo.toml +++ b/primitives/application-crypto/Cargo.toml @@ -16,8 +16,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-core = { version = "5.0.0", default-features = false, path = "../core" } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } serde = { version = "1.0.136", optional = true, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-io = { version = "5.0.0", default-features = false, path = "../io" } diff --git a/primitives/arithmetic/Cargo.toml b/primitives/arithmetic/Cargo.toml index e3294ff74985..26b0fbcf98d0 100644 --- a/primitives/arithmetic/Cargo.toml +++ b/primitives/arithmetic/Cargo.toml @@ -15,10 +15,10 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", ] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } integer-sqrt = "0.1.2" static_assertions = "1.1.0" num-traits = { version = "0.2.8", default-features = false } @@ -29,7 +29,7 @@ sp-debug-derive = { version = "4.0.0", default-features = false, path = "../debu [dev-dependencies] rand = "0.7.2" criterion = "0.3" -primitive-types = "0.10.1" +primitive-types = "0.11.1" [features] default = ["std"] diff --git a/primitives/arithmetic/fuzzer/Cargo.toml b/primitives/arithmetic/fuzzer/Cargo.toml index 33951687c313..d715515056bb 100644 --- a/primitives/arithmetic/fuzzer/Cargo.toml +++ b/primitives/arithmetic/fuzzer/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-arithmetic = { version = "4.0.0", path = ".." } honggfuzz = "0.5.49" -primitive-types = "0.10.1" +primitive-types = "0.11.1" num-bigint = "0.2" [[bin]] diff --git a/primitives/authority-discovery/Cargo.toml b/primitives/authority-discovery/Cargo.toml index 7c6aa7a6ea00..adbeeb473f2a 100644 --- a/primitives/authority-discovery/Cargo.toml +++ b/primitives/authority-discovery/Cargo.toml @@ -14,8 +14,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-application-crypto = { version = "5.0.0", default-features = false, path = "../application-crypto" } -codec = { package = "parity-scale-codec", default-features = false, version = "2.0.0" } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", default-features = false, version = "3.0.0" } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } sp-runtime = { version = "5.0.0", default-features = false, path = "../runtime" } diff --git a/primitives/authorship/Cargo.toml b/primitives/authorship/Cargo.toml index 4cf8e6e9522d..93b3a43eda17 100644 --- a/primitives/authorship/Cargo.toml +++ b/primitives/authorship/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../inherents" } sp-runtime = { version = "5.0.0", default-features = false, path = "../runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } async-trait = { version = "0.1.50", optional = true } [features] diff --git a/primitives/beefy/Cargo.toml b/primitives/beefy/Cargo.toml index 9d8ec2a653ea..b51c5b4948e1 100644 --- a/primitives/beefy/Cargo.toml +++ b/primitives/beefy/Cargo.toml @@ -8,8 +8,8 @@ repository = "https://github.com/paritytech/substrate" description = "Primitives for BEEFY protocol." [dependencies] -codec = { version = "2.2.0", package = "parity-scale-codec", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { version = "3.0.0", package = "parity-scale-codec", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-api = { version = "4.0.0-dev", path = "../api", default-features = false } sp-application-crypto = { version = "5.0.0", path = "../application-crypto", default-features = false } diff --git a/primitives/block-builder/Cargo.toml b/primitives/block-builder/Cargo.toml index 28f76343c7e9..6f0fe32db2fa 100644 --- a/primitives/block-builder/Cargo.toml +++ b/primitives/block-builder/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] sp-runtime = { version = "5.0.0", default-features = false, path = "../runtime" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../inherents" } [features] diff --git a/primitives/blockchain/Cargo.toml b/primitives/blockchain/Cargo.toml index 89737dbac0c6..69aa7c049f88 100644 --- a/primitives/blockchain/Cargo.toml +++ b/primitives/blockchain/Cargo.toml @@ -16,10 +16,10 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] log = "0.4.11" lru = "0.7.0" -parking_lot = "0.11.2" +parking_lot = "0.12.0" thiserror = "1.0.30" futures = "0.3.9" -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } sp-consensus = { version = "0.10.0-dev", path = "../consensus/common" } sp-runtime = { version = "5.0.0", path = "../runtime" } sp-state-machine = { version = "0.11.0", path = "../state-machine" } diff --git a/primitives/consensus/aura/Cargo.toml b/primitives/consensus/aura/Cargo.toml index e78de2db17b3..a51d4aaeabec 100644 --- a/primitives/consensus/aura/Cargo.toml +++ b/primitives/consensus/aura/Cargo.toml @@ -14,8 +14,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-application-crypto = { version = "5.0.0", default-features = false, path = "../../application-crypto" } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../std" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../api" } sp-runtime = { version = "5.0.0", default-features = false, path = "../../runtime" } diff --git a/primitives/consensus/babe/Cargo.toml b/primitives/consensus/babe/Cargo.toml index b677f4470284..cf276c998f11 100644 --- a/primitives/consensus/babe/Cargo.toml +++ b/primitives/consensus/babe/Cargo.toml @@ -14,8 +14,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-application-crypto = { version = "5.0.0", default-features = false, path = "../../application-crypto" } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } merlin = { version = "2.0", default-features = false } sp-std = { version = "4.0.0", default-features = false, path = "../../std" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../api" } diff --git a/primitives/consensus/common/Cargo.toml b/primitives/consensus/common/Cargo.toml index 2717de72d1e3..d6c31876fa8d 100644 --- a/primitives/consensus/common/Cargo.toml +++ b/primitives/consensus/common/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] async-trait = "0.1.42" -codec = { package = "parity-scale-codec", version = "2.0.0", features = [ +codec = { package = "parity-scale-codec", version = "3.0.0", features = [ "derive", ] } futures = { version = "0.3.1", features = ["thread-pool"] } diff --git a/primitives/consensus/pow/Cargo.toml b/primitives/consensus/pow/Cargo.toml index f70af90afd6d..d5c8aa9613b3 100644 --- a/primitives/consensus/pow/Cargo.toml +++ b/primitives/consensus/pow/Cargo.toml @@ -17,7 +17,7 @@ sp-api = { version = "4.0.0-dev", default-features = false, path = "../../api" } sp-std = { version = "4.0.0", default-features = false, path = "../../std" } sp-runtime = { version = "5.0.0", default-features = false, path = "../../runtime" } sp-core = { version = "5.0.0", default-features = false, path = "../../core" } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } [features] default = ["std"] diff --git a/primitives/consensus/slots/Cargo.toml b/primitives/consensus/slots/Cargo.toml index aed2265bddca..5c8161ddcbe2 100644 --- a/primitives/consensus/slots/Cargo.toml +++ b/primitives/consensus/slots/Cargo.toml @@ -13,8 +13,8 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } serde = { version = "1.0", features = ["derive"], optional = true } sp-arithmetic = { version = "4.0.0", default-features = false, path = "../../arithmetic" } sp-runtime = { version = "5.0.0", default-features = false, path = "../../runtime" } diff --git a/primitives/consensus/vrf/Cargo.toml b/primitives/consensus/vrf/Cargo.toml index 3277a3ff9691..db453f62e801 100644 --- a/primitives/consensus/vrf/Cargo.toml +++ b/primitives/consensus/vrf/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { version = "2.0.0", package = "parity-scale-codec", default-features = false } +codec = { version = "3.0.0", package = "parity-scale-codec", default-features = false } schnorrkel = { version = "0.9.1", features = ["preaudit_deprecated", "u64_backend"], default-features = false } sp-std = { version = "4.0.0", path = "../../std", default-features = false } sp-core = { version = "5.0.0", path = "../../core", default-features = false } diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index 08d5cdb87e60..ab0f38ec109c 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -13,15 +13,15 @@ documentation = "https://docs.rs/sp-core" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = [ +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", "max-encoded-len", ] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } log = { version = "0.4.11", default-features = false } serde = { version = "1.0.136", optional = true, features = ["derive"] } byteorder = { version = "1.3.2", default-features = false } -primitive-types = { version = "0.10.1", default-features = false, features = ["codec", "scale-info"] } +primitive-types = { version = "0.11.1", default-features = false, features = ["codec", "scale-info"] } impl-serde = { version = "0.3.0", optional = true } wasmi = { version = "0.9.1", optional = true } hash-db = { version = "0.15.2", default-features = false } @@ -35,12 +35,12 @@ num-traits = { version = "0.2.8", default-features = false } zeroize = { version = "1.4.3", default-features = false } secrecy = { version = "0.8.0", default-features = false } lazy_static = { version = "1.4.0", default-features = false, optional = true } -parking_lot = { version = "0.11.2", optional = true } +parking_lot = { version = "0.12.0", optional = true } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-debug-derive = { version = "4.0.0", default-features = false, path = "../debug-derive" } sp-storage = { version = "5.0.0", default-features = false, path = "../storage" } sp-externalities = { version = "0.11.0", optional = true, path = "../externalities" } -parity-util-mem = { version = "0.10.2", default-features = false, features = ["primitive-types"] } +parity-util-mem = { version = "0.11.0", default-features = false, features = ["primitive-types"] } futures = { version = "0.3.1", optional = true } dyn-clonable = { version = "0.9.0", optional = true } thiserror = { version = "1.0.30", optional = true } diff --git a/primitives/database/Cargo.toml b/primitives/database/Cargo.toml index 6c3eea9aa1f9..198f44510209 100644 --- a/primitives/database/Cargo.toml +++ b/primitives/database/Cargo.toml @@ -11,6 +11,6 @@ documentation = "https://docs.rs/sp-database" readme = "README.md" [dependencies] -parking_lot = "0.11.2" -kvdb = "0.10.0" +parking_lot = "0.12.0" +kvdb = "0.11.0" diff --git a/primitives/externalities/Cargo.toml b/primitives/externalities/Cargo.toml index 7b7beb51e780..f47f0ba494a7 100644 --- a/primitives/externalities/Cargo.toml +++ b/primitives/externalities/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] sp-storage = { version = "5.0.0", path = "../storage", default-features = false } sp-std = { version = "4.0.0", path = "../std", default-features = false } environmental = { version = "1.1.3", default-features = false } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } [features] default = ["std"] diff --git a/primitives/finality-grandpa/Cargo.toml b/primitives/finality-grandpa/Cargo.toml index a05636d44a56..a40873ef4c2f 100644 --- a/primitives/finality-grandpa/Cargo.toml +++ b/primitives/finality-grandpa/Cargo.toml @@ -15,9 +15,9 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } -grandpa = { package = "finality-grandpa", version = "0.14.1", default-features = false, features = ["derive-codec"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +grandpa = { package = "finality-grandpa", version = "0.15.0", default-features = false, features = ["derive-codec"] } log = { version = "0.4.8", optional = true } serde = { version = "1.0.136", optional = true, features = ["derive"] } sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } diff --git a/primitives/inherents/Cargo.toml b/primitives/inherents/Cargo.toml index f78f4aea14e4..4fe1c75b52ae 100644 --- a/primitives/inherents/Cargo.toml +++ b/primitives/inherents/Cargo.toml @@ -18,7 +18,7 @@ targets = ["x86_64-unknown-linux-gnu"] sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-core = { version = "5.0.0", default-features = false, path = "../core" } sp-runtime = { version = "5.0.0", path = "../runtime", optional = true } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } thiserror = { version = "1.0.30", optional = true } impl-trait-for-tuples = "0.2.0" async-trait = { version = "0.1.50", optional = true } diff --git a/primitives/io/Cargo.toml b/primitives/io/Cargo.toml index b9cbdbaa70e7..b28db8c1ff3d 100644 --- a/primitives/io/Cargo.toml +++ b/primitives/io/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } hash-db = { version = "0.15.2", default-features = false } sp-core = { version = "5.0.0", default-features = false, path = "../core" } sp-keystore = { version = "0.11.0", default-features = false, optional = true, path = "../keystore" } @@ -29,7 +29,7 @@ sp-externalities = { version = "0.11.0", optional = true, path = "../externaliti sp-tracing = { version = "4.0.0", default-features = false, path = "../tracing" } log = { version = "0.4.8", optional = true } futures = { version = "0.3.1", features = ["thread-pool"], optional = true } -parking_lot = { version = "0.11.2", optional = true } +parking_lot = { version = "0.12.0", optional = true } tracing = { version = "0.1.29", default-features = false } tracing-core = { version = "0.1.17", default-features = false} diff --git a/primitives/keystore/Cargo.toml b/primitives/keystore/Cargo.toml index 26748d3227d6..182a5f494fbc 100644 --- a/primitives/keystore/Cargo.toml +++ b/primitives/keystore/Cargo.toml @@ -15,11 +15,11 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] async-trait = "0.1.50" futures = "0.3.1" -parking_lot = { version = "0.11.2", default-features = false } +parking_lot = { version = "0.12.0", default-features = false } serde = { version = "1.0", optional = true } thiserror = "1.0" -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } schnorrkel = { version = "0.9.1", features = ["preaudit_deprecated", "u64_backend"], default-features = false } merlin = { version = "2.0", default-features = false } sp-core = { version = "5.0.0", path = "../core" } diff --git a/primitives/npos-elections/Cargo.toml b/primitives/npos-elections/Cargo.toml index 88475e10f732..6d70658c2701 100644 --- a/primitives/npos-elections/Cargo.toml +++ b/primitives/npos-elections/Cargo.toml @@ -13,8 +13,8 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } serde = { version = "1.0.136", optional = true, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-npos-elections-solution-type = { version = "4.0.0-dev", path = "./solution-type" } diff --git a/primitives/npos-elections/fuzzer/Cargo.toml b/primitives/npos-elections/fuzzer/Cargo.toml index 335195e9bf5b..0c6c44ced7f4 100644 --- a/primitives/npos-elections/fuzzer/Cargo.toml +++ b/primitives/npos-elections/fuzzer/Cargo.toml @@ -18,8 +18,8 @@ clap = { version = "3.0", features = ["derive"] } honggfuzz = "0.5" rand = { version = "0.8", features = ["std", "small_rng"] } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-npos-elections = { version = "4.0.0-dev", path = ".." } sp-runtime = { version = "5.0.0", path = "../../runtime" } diff --git a/primitives/npos-elections/solution-type/Cargo.toml b/primitives/npos-elections/solution-type/Cargo.toml index cfb3af4552e2..5b45bb246f39 100644 --- a/primitives/npos-elections/solution-type/Cargo.toml +++ b/primitives/npos-elections/solution-type/Cargo.toml @@ -21,8 +21,8 @@ proc-macro2 = "1.0.36" proc-macro-crate = "1.1.0" [dev-dependencies] -parity-scale-codec = "2.3.1" -scale-info = "1.0" +parity-scale-codec = "3.0.0" +scale-info = "2.0.0" sp-arithmetic = { path = "../../arithmetic", version = "4.0.0" } # used by generate_solution_type: sp-npos-elections = { path = "..", version = "4.0.0-dev" } diff --git a/primitives/runtime-interface/Cargo.toml b/primitives/runtime-interface/Cargo.toml index 89805a9db36d..e227a7b63cde 100644 --- a/primitives/runtime-interface/Cargo.toml +++ b/primitives/runtime-interface/Cargo.toml @@ -19,9 +19,9 @@ sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-tracing = { version = "4.0.0", default-features = false, path = "../tracing" } sp-runtime-interface-proc-macro = { version = "4.0.0", path = "proc-macro" } sp-externalities = { version = "0.11.0", optional = true, path = "../externalities" } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } static_assertions = "1.0.0" -primitive-types = { version = "0.10.1", default-features = false } +primitive-types = { version = "0.11.1", default-features = false } sp-storage = { version = "5.0.0", default-features = false, path = "../storage" } impl-trait-for-tuples = "0.2.1" diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 7b58482b2c36..7c7e74b60053 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -16,8 +16,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.136", optional = true, features = ["derive"] } -codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-core = { version = "5.0.0", default-features = false, path = "../core" } sp-application-crypto = { version = "5.0.0", default-features = false, path = "../application-crypto" } sp-arithmetic = { version = "4.0.0", default-features = false, path = "../arithmetic" } @@ -27,7 +27,7 @@ log = { version = "0.4.14", default-features = false } paste = "1.0" rand = { version = "0.7.2", optional = true } impl-trait-for-tuples = "0.2.1" -parity-util-mem = { version = "0.10.2", default-features = false, features = ["primitive-types"] } +parity-util-mem = { version = "0.11.0", default-features = false, features = ["primitive-types"] } hash256-std-hasher = { version = "0.15.2", default-features = false } either = { version = "1.5", default-features = false } diff --git a/primitives/sandbox/Cargo.toml b/primitives/sandbox/Cargo.toml index a72786807330..e04df06f2828 100644 --- a/primitives/sandbox/Cargo.toml +++ b/primitives/sandbox/Cargo.toml @@ -24,7 +24,7 @@ sp-core = { version = "5.0.0", default-features = false, path = "../core" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-io = { version = "5.0.0", default-features = false, path = "../io" } sp-wasm-interface = { version = "5.0.0", default-features = false, path = "../wasm-interface" } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } log = { version = "0.4", default-features = false } [dev-dependencies] diff --git a/primitives/session/Cargo.toml b/primitives/session/Cargo.toml index 4138ecb519df..abc4b60cfc32 100644 --- a/primitives/session/Cargo.toml +++ b/primitives/session/Cargo.toml @@ -13,8 +13,8 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } sp-core = { version = "5.0.0", default-features = false, path = "../core" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } diff --git a/primitives/staking/Cargo.toml b/primitives/staking/Cargo.toml index 54e556dfae12..408dcb860596 100644 --- a/primitives/staking/Cargo.toml +++ b/primitives/staking/Cargo.toml @@ -13,8 +13,8 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-runtime = { version = "5.0.0", default-features = false, path = "../runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } diff --git a/primitives/state-machine/Cargo.toml b/primitives/state-machine/Cargo.toml index 15720688c058..300af627f71b 100644 --- a/primitives/state-machine/Cargo.toml +++ b/primitives/state-machine/Cargo.toml @@ -16,14 +16,14 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] log = { version = "0.4.11", optional = true } thiserror = { version = "1.0.30", optional = true } -parking_lot = { version = "0.11.2", optional = true } +parking_lot = { version = "0.12.0", optional = true } hash-db = { version = "0.15.2", default-features = false } -trie-db = { version = "0.23.0", default-features = false } +trie-db = { version = "0.23.1", default-features = false } trie-root = { version = "0.17.0", default-features = false } sp-trie = { version = "5.0.0", path = "../trie", default-features = false } sp-core = { version = "5.0.0", path = "../core", default-features = false } sp-panic-handler = { version = "4.0.0", path = "../panic-handler", optional = true } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } num-traits = { version = "0.2.8", default-features = false } rand = { version = "0.7.2", optional = true } sp-externalities = { version = "0.11.0", path = "../externalities", default-features = false } diff --git a/primitives/storage/Cargo.toml b/primitives/storage/Cargo.toml index 7d1a8c03c0a0..f6fe678c370b 100644 --- a/primitives/storage/Cargo.toml +++ b/primitives/storage/Cargo.toml @@ -19,7 +19,7 @@ serde = { version = "1.0.136", optional = true, features = ["derive"] } impl-serde = { version = "0.3.1", optional = true } ref-cast = "1.0.0" sp-debug-derive = { version = "4.0.0", default-features = false, path = "../debug-derive" } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } [features] default = [ "std" ] diff --git a/primitives/tasks/Cargo.toml b/primitives/tasks/Cargo.toml index 00943e865720..3cf4a583d60e 100644 --- a/primitives/tasks/Cargo.toml +++ b/primitives/tasks/Cargo.toml @@ -22,7 +22,7 @@ sp-runtime-interface = { version = "5.0.0", default-features = false, path = ".. sp-std = { version = "4.0.0", default-features = false, path = "../std" } [dev-dependencies] -codec = { package = "parity-scale-codec", default-features = false, version = "2.0.0" } +codec = { package = "parity-scale-codec", default-features = false, version = "3.0.0" } [features] default = ["std"] diff --git a/primitives/test-primitives/Cargo.toml b/primitives/test-primitives/Cargo.toml index 101a9249bf70..2c13f0f8d64f 100644 --- a/primitives/test-primitives/Cargo.toml +++ b/primitives/test-primitives/Cargo.toml @@ -13,11 +13,11 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-application-crypto = { version = "5.0.0", default-features = false, path = "../application-crypto" } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } sp-core = { version = "5.0.0", default-features = false, path = "../core" } serde = { version = "1.0.136", optional = true, features = ["derive"] } sp-runtime = { version = "5.0.0", default-features = false, path = "../runtime" } -parity-util-mem = { version = "0.10.2", default-features = false, features = ["primitive-types"] } +parity-util-mem = { version = "0.11.0", default-features = false, features = ["primitive-types"] } [features] default = [ diff --git a/primitives/timestamp/Cargo.toml b/primitives/timestamp/Cargo.toml index f7ac2e663e39..ec112ac5916f 100644 --- a/primitives/timestamp/Cargo.toml +++ b/primitives/timestamp/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-runtime = { version = "5.0.0", default-features = false, path = "../runtime" } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../inherents" } thiserror = { version = "1.0.30", optional = true } log = { version = "0.4.8", optional = true } diff --git a/primitives/tracing/Cargo.toml b/primitives/tracing/Cargo.toml index 0b5a273e11d3..3c3149a8b471 100644 --- a/primitives/tracing/Cargo.toml +++ b/primitives/tracing/Cargo.toml @@ -19,7 +19,7 @@ targets = ["x86_64-unknown-linux-gnu", "wasm32-unknown-unknown"] [dependencies] sp-std = { version = "4.0.0", path = "../std", default-features = false } -codec = { version = "2.0.0", package = "parity-scale-codec", default-features = false, features = [ +codec = { version = "3.0.0", package = "parity-scale-codec", default-features = false, features = [ "derive", ] } tracing = { version = "0.1.29", default-features = false } diff --git a/primitives/transaction-storage-proof/Cargo.toml b/primitives/transaction-storage-proof/Cargo.toml index 9e2898fe267e..ca285323f292 100644 --- a/primitives/transaction-storage-proof/Cargo.toml +++ b/primitives/transaction-storage-proof/Cargo.toml @@ -18,8 +18,8 @@ sp-runtime = { version = "5.0.0", default-features = false, path = "../runtime" sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-trie = { version = "5.0.0", optional = true, path = "../trie" } sp-core = { version = "5.0.0", path = "../core", optional = true } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } log = { version = "0.4.8", optional = true } async-trait = { version = "0.1.50", optional = true } diff --git a/primitives/trie/Cargo.toml b/primitives/trie/Cargo.toml index e79f2ffb7f84..022dd606ba11 100644 --- a/primitives/trie/Cargo.toml +++ b/primitives/trie/Cargo.toml @@ -18,17 +18,17 @@ name = "bench" harness = false [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../std" } hash-db = { version = "0.15.2", default-features = false } -trie-db = { version = "0.23.0", default-features = false } +trie-db = { version = "0.23.1", default-features = false } trie-root = { version = "0.17.0", default-features = false } -memory-db = { version = "0.28.0", default-features = false } +memory-db = { version = "0.29.0", default-features = false } sp-core = { version = "5.0.0", default-features = false, path = "../core" } [dev-dependencies] -trie-bench = "0.29.0" +trie-bench = "0.30.0" trie-standardmap = "0.15.2" criterion = "0.3.3" hex-literal = "0.3.4" diff --git a/primitives/version/Cargo.toml b/primitives/version/Cargo.toml index 053ba49fd82f..590bf081eb06 100644 --- a/primitives/version/Cargo.toml +++ b/primitives/version/Cargo.toml @@ -16,8 +16,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] impl-serde = { version = "0.3.1", optional = true } serde = { version = "1.0.136", optional = true, features = ["derive"] } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-runtime = { version = "5.0.0", default-features = false, path = "../runtime" } sp-version-proc-macro = { version = "4.0.0-dev", default-features = false, path = "proc-macro" } diff --git a/primitives/version/proc-macro/Cargo.toml b/primitives/version/proc-macro/Cargo.toml index a706f74f4522..c8f59f4fca25 100644 --- a/primitives/version/proc-macro/Cargo.toml +++ b/primitives/version/proc-macro/Cargo.toml @@ -19,7 +19,7 @@ proc-macro = true quote = "1.0.10" syn = { version = "1.0.82", features = ["full", "fold", "extra-traits", "visit"] } proc-macro2 = "1.0.36" -codec = { package = "parity-scale-codec", version = "2.0.0", features = [ "derive" ] } +codec = { package = "parity-scale-codec", version = "3.0.0", features = [ "derive" ] } [dev-dependencies] sp-version = { version = "4.0.0-dev", path = ".." } diff --git a/primitives/wasm-interface/Cargo.toml b/primitives/wasm-interface/Cargo.toml index bb82629ba01e..acf22f189b87 100644 --- a/primitives/wasm-interface/Cargo.toml +++ b/primitives/wasm-interface/Cargo.toml @@ -19,7 +19,7 @@ wasmtime = { version = "0.33.0", optional = true, default-features = false } log = { version = "0.4.14", optional = true } impl-trait-for-tuples = "0.2.1" sp-std = { version = "4.0.0", path = "../std", default-features = false } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } [features] default = [ "std" ] diff --git a/test-utils/client/Cargo.toml b/test-utils/client/Cargo.toml index a74d7b583527..ffddda3ac1f5 100644 --- a/test-utils/client/Cargo.toml +++ b/test-utils/client/Cargo.toml @@ -12,7 +12,7 @@ publish = false targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } futures = "0.3.16" hex = "0.4" serde = "1.0.136" diff --git a/test-utils/runtime/Cargo.toml b/test-utils/runtime/Cargo.toml index 6529fa71106e..b955aa07afa7 100644 --- a/test-utils/runtime/Cargo.toml +++ b/test-utils/runtime/Cargo.toml @@ -17,11 +17,11 @@ sp-application-crypto = { version = "5.0.0", default-features = false, path = ". sp-consensus-aura = { version = "0.10.0-dev", default-features = false, path = "../../primitives/consensus/aura" } sp-consensus-babe = { version = "0.10.0-dev", default-features = false, path = "../../primitives/consensus/babe" } sp-block-builder = { version = "4.0.0-dev", default-features = false, path = "../../primitives/block-builder" } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../primitives/inherents" } sp-keyring = { version = "5.0.0", optional = true, path = "../../primitives/keyring" } -memory-db = { version = "0.27.0", default-features = false } +memory-db = { version = "0.29.0", default-features = false } sp-offchain = { version = "4.0.0-dev", default-features = false, path = "../../primitives/offchain" } sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } @@ -39,8 +39,8 @@ pallet-timestamp = { version = "4.0.0-dev", default-features = false, path = ".. sp-finality-grandpa = { version = "4.0.0-dev", default-features = false, path = "../../primitives/finality-grandpa" } sp-trie = { version = "5.0.0", default-features = false, path = "../../primitives/trie" } sp-transaction-pool = { version = "4.0.0-dev", default-features = false, path = "../../primitives/transaction-pool" } -trie-db = { version = "0.23.0", default-features = false } -parity-util-mem = { version = "0.10.2", default-features = false, features = ["primitive-types"] } +trie-db = { version = "0.23.1", default-features = false } +parity-util-mem = { version = "0.11.0", default-features = false, features = ["primitive-types"] } sc-service = { version = "0.10.0-dev", default-features = false, optional = true, features = ["test-helpers"], path = "../../client/service" } sp-state-machine = { version = "0.11.0", default-features = false, path = "../../primitives/state-machine" } sp-externalities = { version = "0.11.0", default-features = false, path = "../../primitives/externalities" } diff --git a/test-utils/runtime/client/Cargo.toml b/test-utils/runtime/client/Cargo.toml index fd260453ca18..3491a7a09f9c 100644 --- a/test-utils/runtime/client/Cargo.toml +++ b/test-utils/runtime/client/Cargo.toml @@ -21,6 +21,6 @@ substrate-test-runtime = { version = "2.0.0", path = "../../runtime" } sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -codec = { package = "parity-scale-codec", version = "2.0.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } sc-client-api = { version = "4.0.0-dev", path = "../../../client/api" } futures = "0.3.9" diff --git a/test-utils/runtime/transaction-pool/Cargo.toml b/test-utils/runtime/transaction-pool/Cargo.toml index ef2ebd64fb22..edb2efdb273f 100644 --- a/test-utils/runtime/transaction-pool/Cargo.toml +++ b/test-utils/runtime/transaction-pool/Cargo.toml @@ -13,8 +13,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] substrate-test-runtime-client = { version = "2.0.0", path = "../client" } -parking_lot = "0.11.2" -codec = { package = "parity-scale-codec", version = "2.0.0" } +parking_lot = "0.12.0" +codec = { package = "parity-scale-codec", version = "3.0.0" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } sc-transaction-pool = { version = "4.0.0-dev", path = "../../../client/transaction-pool" } diff --git a/utils/fork-tree/Cargo.toml b/utils/fork-tree/Cargo.toml index cdfce5592f2f..4ac176f645bd 100644 --- a/utils/fork-tree/Cargo.toml +++ b/utils/fork-tree/Cargo.toml @@ -14,4 +14,4 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"] } diff --git a/utils/frame/benchmarking-cli/Cargo.toml b/utils/frame/benchmarking-cli/Cargo.toml index 9e2de0e8c358..bbfcbb7e8b81 100644 --- a/utils/frame/benchmarking-cli/Cargo.toml +++ b/utils/frame/benchmarking-cli/Cargo.toml @@ -24,7 +24,7 @@ sp-externalities = { version = "0.11.0", path = "../../../primitives/externaliti sp-keystore = { version = "0.11.0", path = "../../../primitives/keystore" } sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } sp-state-machine = { version = "0.11.0", path = "../../../primitives/state-machine" } -codec = { version = "2.0.0", package = "parity-scale-codec" } +codec = { version = "3.0.0", package = "parity-scale-codec" } clap = { version = "3.0", features = ["derive"] } chrono = "0.4" serde = "1.0.136" diff --git a/utils/frame/remote-externalities/Cargo.toml b/utils/frame/remote-externalities/Cargo.toml index cf8a0f606987..ec05b7133412 100644 --- a/utils/frame/remote-externalities/Cargo.toml +++ b/utils/frame/remote-externalities/Cargo.toml @@ -18,7 +18,7 @@ jsonrpsee = { version = "0.8", features = ["ws-client", "macros"] } env_logger = "0.9" frame-support = { path = "../../../frame/support", optional = true, version = "4.0.0-dev" } log = "0.4.11" -codec = { package = "parity-scale-codec", version = "2.0.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } serde_json = "1.0" serde = "1.0.136" diff --git a/utils/frame/rpc/support/Cargo.toml b/utils/frame/rpc/support/Cargo.toml index fcb5a4367386..b255f5ab2a79 100644 --- a/utils/frame/rpc/support/Cargo.toml +++ b/utils/frame/rpc/support/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] futures = "0.3.16" jsonrpc-client-transports = { version = "18.0.0", features = ["http"] } -codec = { package = "parity-scale-codec", version = "2.0.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } serde = "1" frame-support = { version = "4.0.0-dev", path = "../../../../frame/support" } sp-storage = { version = "5.0.0", path = "../../../../primitives/storage" } @@ -25,5 +25,5 @@ sc-rpc-api = { version = "0.10.0-dev", path = "../../../../client/rpc-api" } [dev-dependencies] frame-system = { version = "4.0.0-dev", path = "../../../../frame/system" } -scale-info = "1.0" +scale-info = "2.0.0" tokio = "1.15" diff --git a/utils/frame/rpc/support/src/lib.rs b/utils/frame/rpc/support/src/lib.rs index 9cf99ddf97b0..5d7cba19f643 100644 --- a/utils/frame/rpc/support/src/lib.rs +++ b/utils/frame/rpc/support/src/lib.rs @@ -126,7 +126,7 @@ impl StorageQuery { block_index: Option, ) -> Result, RpcError> { let opt: Option = state_client.storage(self.key, block_index).await?; - opt.map(|encoded| V::decode_all(&encoded.0)) + opt.map(|encoded| V::decode_all(&mut &encoded.0[..])) .transpose() .map_err(|decode_err| RpcError::Other(Box::new(decode_err))) } diff --git a/utils/frame/rpc/system/Cargo.toml b/utils/frame/rpc/system/Cargo.toml index 8ce72416dac2..950cbd09b278 100644 --- a/utils/frame/rpc/system/Cargo.toml +++ b/utils/frame/rpc/system/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sc-client-api = { version = "4.0.0-dev", path = "../../../../client/api" } -codec = { package = "parity-scale-codec", version = "2.0.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } futures = "0.3.16" jsonrpc-core = "18.0.0" jsonrpc-core-client = "18.0.0" diff --git a/utils/frame/try-runtime/cli/Cargo.toml b/utils/frame/try-runtime/cli/Cargo.toml index 12380e2d3272..27129f38acc7 100644 --- a/utils/frame/try-runtime/cli/Cargo.toml +++ b/utils/frame/try-runtime/cli/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] clap = { version = "3.0", features = ["derive"] } log = "0.4.8" -parity-scale-codec = { version = "2.3.1" } +parity-scale-codec = "3.0.0" serde = "1.0.136" zstd = "0.9.0" From b8c5b846617f837116e63ab1794a5310fb960246 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Fri, 25 Feb 2022 16:01:33 +0100 Subject: [PATCH 530/695] sc-cli: Fix bugs after switching to clap3 (#10920) * sc-cli: Fix bugs after switching to clap3 Before switching to clap3 we support cli options like `--reserved-nodes A B` and after you needed to pass `--reserved-nodes` cli option multiple times `--reserved-nodes A --reserved-nodes B`. This is fixed by setting `multiple_occurrences(true)` option. This also done for all the other `Vec` cli options in `sc-cli`. Besides that `--sync` wasn't supporting case insensitive parsing of the value. This is now also supported. For both regressions a test is added. Besides that the pr removes all the `rename_all = PascalCase` attributes, because they are not needed. All other `ArgEnum`s were checked and all are already using `ignore_case(true)`. * Bring back `PascalCase`, because otherwise it falls back to `kebab-case`... --- client/cli/src/arg_enums.rs | 44 +++++++++++------- client/cli/src/params/network_params.rs | 62 +++++++++++++++++++++++-- client/cli/src/params/shared_params.rs | 2 +- client/network/src/config.rs | 2 +- 4 files changed, 87 insertions(+), 23 deletions(-) diff --git a/client/cli/src/arg_enums.rs b/client/cli/src/arg_enums.rs index 249e3c639e4e..a5403e3497c9 100644 --- a/client/cli/src/arg_enums.rs +++ b/client/cli/src/arg_enums.rs @@ -15,8 +15,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -// NOTE: we allow missing docs here because arg_enum! creates the function variants without doc -#![allow(missing_docs)] + +//! Definitions of [`ArgEnum`] types. use clap::ArgEnum; @@ -90,6 +90,7 @@ impl Into for WasmExecutionMethod { #[derive(Debug, Copy, Clone, PartialEq, Eq, ArgEnum)] #[clap(rename_all = "PascalCase")] pub enum TracingReceiver { + /// Output the tracing records using the log. Log, } @@ -101,25 +102,33 @@ impl Into for TracingReceiver { } } -#[allow(missing_docs)] +/// The type of the node key. #[derive(Debug, Copy, Clone, PartialEq, Eq, ArgEnum)] #[clap(rename_all = "PascalCase")] pub enum NodeKeyType { + /// Use ed25519. Ed25519, } +/// The crypto scheme to use. #[derive(Debug, Copy, Clone, PartialEq, Eq, ArgEnum)] #[clap(rename_all = "PascalCase")] pub enum CryptoScheme { + /// Use ed25519. Ed25519, + /// Use sr25519. Sr25519, + /// Use Ecdsa, } +/// The type of the output format. #[derive(Debug, Copy, Clone, PartialEq, Eq, ArgEnum)] #[clap(rename_all = "PascalCase")] pub enum OutputType { + /// Output as json. Json, + /// Output as text. Text, } @@ -127,13 +136,13 @@ pub enum OutputType { #[derive(Debug, Copy, Clone, PartialEq, Eq, ArgEnum)] #[clap(rename_all = "PascalCase")] pub enum ExecutionStrategy { - // Execute with native build (if available, WebAssembly otherwise). + /// Execute with native build (if available, WebAssembly otherwise). Native, - // Only execute with the WebAssembly build. + /// Only execute with the WebAssembly build. Wasm, - // Execute with both native (where available) and WebAssembly builds. + /// Execute with both native (where available) and WebAssembly builds. Both, - // Execute with the native build if possible; if it fails, then execute with WebAssembly. + /// Execute with the native build if possible; if it fails, then execute with WebAssembly. NativeElseWasm, } @@ -165,12 +174,12 @@ impl ExecutionStrategy { #[derive(Debug, Copy, Clone, PartialEq, ArgEnum)] #[clap(rename_all = "PascalCase")] pub enum RpcMethods { - // Expose every RPC method only when RPC is listening on `localhost`, - // otherwise serve only safe RPC methods. + /// Expose every RPC method only when RPC is listening on `localhost`, + /// otherwise serve only safe RPC methods. Auto, - // Allow only a safe subset of RPC methods. + /// Allow only a safe subset of RPC methods. Safe, - // Expose every RPC method (even potentially unsafe ones). + /// Expose every RPC method (even potentially unsafe ones). Unsafe, } @@ -224,22 +233,25 @@ impl Database { #[derive(Debug, Clone, ArgEnum)] #[clap(rename_all = "PascalCase")] pub enum OffchainWorkerEnabled { + /// Always have offchain worker enabled. Always, + /// Never enable the offchain worker. Never, + /// Only enable the offchain worker when running as validator. WhenValidating, } /// Syncing mode. -#[derive(Debug, Clone, Copy, ArgEnum)] +#[derive(Debug, Clone, Copy, ArgEnum, PartialEq)] #[clap(rename_all = "PascalCase")] pub enum SyncMode { - // Full sync. Donwnload end verify all blocks. + /// Full sync. Download end verify all blocks. Full, - // Download blocks without executing them. Download latest state with proofs. + /// Download blocks without executing them. Download latest state with proofs. Fast, - // Download blocks without executing them. Download latest state without proofs. + /// Download blocks without executing them. Download latest state without proofs. FastUnsafe, - // Prove finality and download the latest state. + /// Prove finality and download the latest state. Warp, } diff --git a/client/cli/src/params/network_params.rs b/client/cli/src/params/network_params.rs index 1de2896cba73..7a265c5e2760 100644 --- a/client/cli/src/params/network_params.rs +++ b/client/cli/src/params/network_params.rs @@ -34,11 +34,11 @@ use std::{borrow::Cow, path::PathBuf}; #[derive(Debug, Clone, Args)] pub struct NetworkParams { /// Specify a list of bootnodes. - #[clap(long, value_name = "ADDR")] + #[clap(long, value_name = "ADDR", multiple_values(true))] pub bootnodes: Vec, /// Specify a list of reserved node addresses. - #[clap(long, value_name = "ADDR")] + #[clap(long, value_name = "ADDR", multiple_values(true))] pub reserved_nodes: Vec, /// Whether to only synchronize the chain with reserved nodes. @@ -54,7 +54,7 @@ pub struct NetworkParams { /// The public address that other nodes will use to connect to it. /// This can be used if there's a proxy in front of this node. - #[clap(long, value_name = "PUBLIC_ADDR")] + #[clap(long, value_name = "PUBLIC_ADDR", multiple_values(true))] pub public_addr: Vec, /// Listen on this multiaddress. @@ -62,7 +62,7 @@ pub struct NetworkParams { /// By default: /// If `--validator` is passed: `/ip4/0.0.0.0/tcp/` and `/ip6/[::]/tcp/`. /// Otherwise: `/ip4/0.0.0.0/tcp//ws` and `/ip6/[::]/tcp//ws`. - #[clap(long, value_name = "LISTEN_ADDR")] + #[clap(long, value_name = "LISTEN_ADDR", multiple_values(true))] pub listen_addr: Vec, /// Specify p2p protocol TCP port. @@ -137,7 +137,7 @@ pub struct NetworkParams { /// - `Fast`: Download blocks and the latest state only. /// /// - `FastUnsafe`: Same as `Fast`, but skip downloading state proofs. - #[clap(long, arg_enum, value_name = "SYNC_MODE", default_value = "Full")] + #[clap(long, arg_enum, value_name = "SYNC_MODE", default_value = "Full", ignore_case(true))] pub sync: SyncMode, } @@ -237,3 +237,55 @@ impl NetworkParams { } } } + +#[cfg(test)] +mod tests { + use super::*; + use clap::Parser; + + #[derive(Parser)] + struct Cli { + #[clap(flatten)] + network_params: NetworkParams, + } + + #[test] + fn reserved_nodes_multiple_values_and_occurrences() { + let params = Cli::try_parse_from([ + "", + "--reserved-nodes", + "/ip4/0.0.0.0/tcp/501/p2p/12D3KooWEBo1HUPQJwiBmM5kSeg4XgiVxEArArQdDarYEsGxMfbS", + "/ip4/0.0.0.0/tcp/502/p2p/12D3KooWEBo1HUPQJwiBmM5kSeg4XgiVxEArArQdDarYEsGxMfbS", + "--reserved-nodes", + "/ip4/0.0.0.0/tcp/503/p2p/12D3KooWEBo1HUPQJwiBmM5kSeg4XgiVxEArArQdDarYEsGxMfbS", + ]) + .expect("Parses network params"); + + let expected = vec![ + MultiaddrWithPeerId::try_from( + "/ip4/0.0.0.0/tcp/501/p2p/12D3KooWEBo1HUPQJwiBmM5kSeg4XgiVxEArArQdDarYEsGxMfbS" + .to_string(), + ) + .unwrap(), + MultiaddrWithPeerId::try_from( + "/ip4/0.0.0.0/tcp/502/p2p/12D3KooWEBo1HUPQJwiBmM5kSeg4XgiVxEArArQdDarYEsGxMfbS" + .to_string(), + ) + .unwrap(), + MultiaddrWithPeerId::try_from( + "/ip4/0.0.0.0/tcp/503/p2p/12D3KooWEBo1HUPQJwiBmM5kSeg4XgiVxEArArQdDarYEsGxMfbS" + .to_string(), + ) + .unwrap(), + ]; + + assert_eq!(expected, params.network_params.reserved_nodes); + } + + #[test] + fn sync_ingores_case() { + let params = Cli::try_parse_from(["", "--sync", "wArP"]).expect("Parses network params"); + + assert_eq!(SyncMode::Warp, params.network_params.sync); + } +} diff --git a/client/cli/src/params/shared_params.rs b/client/cli/src/params/shared_params.rs index a4f2271e12c4..4066a75a9353 100644 --- a/client/cli/src/params/shared_params.rs +++ b/client/cli/src/params/shared_params.rs @@ -46,7 +46,7 @@ pub struct SharedParams { /// /// Log levels (least to most verbose) are error, warn, info, debug, and trace. /// By default, all targets log `info`. The global log level can be set with -l. - #[clap(short = 'l', long, value_name = "LOG_PATTERN")] + #[clap(short = 'l', long, value_name = "LOG_PATTERN", multiple_values(true))] pub log: Vec, /// Enable detailed log output. diff --git a/client/network/src/config.rs b/client/network/src/config.rs index 3b9c864c3792..a7e4e5cc8766 100644 --- a/client/network/src/config.rs +++ b/client/network/src/config.rs @@ -295,7 +295,7 @@ pub fn parse_addr(mut addr: Multiaddr) -> Result<(PeerId, Multiaddr), ParseErr> /// assert_eq!(addr.peer_id.to_base58(), "QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV"); /// assert_eq!(addr.multiaddr.to_string(), "/ip4/198.51.100.19/tcp/30333"); /// ``` -#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] +#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq)] #[serde(try_from = "String", into = "String")] pub struct MultiaddrWithPeerId { /// Address of the node. From dfe52f7de12a7e308c0bc3a25e211b9cc4d61871 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Fri, 25 Feb 2022 20:30:57 +0100 Subject: [PATCH 531/695] Storage benchmarking (#10897) * WIP Signed-off-by: Oliver Tale-Yazdi * WIP: DB benchmarking Signed-off-by: Oliver Tale-Yazdi * WIP Signed-off-by: Oliver Tale-Yazdi * WIP Signed-off-by: Oliver Tale-Yazdi * Simplify code Signed-off-by: Oliver Tale-Yazdi * Remove old files Signed-off-by: Oliver Tale-Yazdi * Remove old files Signed-off-by: Oliver Tale-Yazdi * Minimize changes Signed-off-by: Oliver Tale-Yazdi * Add license Signed-off-by: Oliver Tale-Yazdi * Remove dependencies Signed-off-by: Oliver Tale-Yazdi * Extend template Signed-off-by: Oliver Tale-Yazdi * Linter Signed-off-by: Oliver Tale-Yazdi * Linter Signed-off-by: Oliver Tale-Yazdi * Beauty fixes Signed-off-by: Oliver Tale-Yazdi * Remove default Signed-off-by: Oliver Tale-Yazdi * Add feature Signed-off-by: Oliver Tale-Yazdi * Remove seed Signed-off-by: Oliver Tale-Yazdi * CI wakeup Signed-off-by: Oliver Tale-Yazdi * Fmt Signed-off-by: Oliver Tale-Yazdi * Review fixes Signed-off-by: Oliver Tale-Yazdi * Adding doc Signed-off-by: Oliver Tale-Yazdi * Adding doc Signed-off-by: Oliver Tale-Yazdi * Improve template Signed-off-by: Oliver Tale-Yazdi * Do not expose columns Signed-off-by: Oliver Tale-Yazdi * Fix ColumnId Signed-off-by: Oliver Tale-Yazdi * Nicer template prints Signed-off-by: Oliver Tale-Yazdi * Cleanup Signed-off-by: Oliver Tale-Yazdi * Fix json path Signed-off-by: Oliver Tale-Yazdi * Simplify `bench_write` logic Signed-off-by: Oliver Tale-Yazdi * Invert tx before the second commit Signed-off-by: Oliver Tale-Yazdi --- Cargo.lock | 31 ++- bin/node/cli/src/cli.rs | 4 + bin/node/cli/src/command.rs | 16 ++ client/cli/src/arg_enums.rs | 2 +- client/cli/src/params/database_params.rs | 2 +- client/cli/src/params/pruning_params.rs | 2 +- client/cli/src/params/shared_params.rs | 2 +- client/db/Cargo.toml | 1 + client/db/src/lib.rs | 20 +- utils/frame/benchmarking-cli/Cargo.toml | 17 +- utils/frame/benchmarking-cli/src/lib.rs | 3 + .../frame/benchmarking-cli/src/storage/cmd.rs | 171 ++++++++++++++++ .../frame/benchmarking-cli/src/storage/mod.rs | 24 +++ .../benchmarking-cli/src/storage/read.rs | 76 +++++++ .../benchmarking-cli/src/storage/record.rs | 191 ++++++++++++++++++ .../benchmarking-cli/src/storage/template.rs | 126 ++++++++++++ .../benchmarking-cli/src/storage/weights.hbs | 107 ++++++++++ .../benchmarking-cli/src/storage/write.rs | 131 ++++++++++++ utils/frame/benchmarking-cli/src/writer.rs | 2 +- 19 files changed, 917 insertions(+), 11 deletions(-) create mode 100644 utils/frame/benchmarking-cli/src/storage/cmd.rs create mode 100644 utils/frame/benchmarking-cli/src/storage/mod.rs create mode 100644 utils/frame/benchmarking-cli/src/storage/read.rs create mode 100644 utils/frame/benchmarking-cli/src/storage/record.rs create mode 100644 utils/frame/benchmarking-cli/src/storage/template.rs create mode 100644 utils/frame/benchmarking-cli/src/storage/weights.hbs create mode 100644 utils/frame/benchmarking-cli/src/storage/write.rs diff --git a/Cargo.lock b/Cargo.lock index 58297393c834..826ed90d4553 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2127,20 +2127,34 @@ dependencies = [ "frame-benchmarking", "frame-support", "handlebars", + "hash-db", + "hex", + "itertools", + "kvdb", "linked-hash-map", "log 0.4.14", + "memory-db", "parity-scale-codec", + "rand 0.8.4", "sc-cli", + "sc-client-api", "sc-client-db", "sc-executor", "sc-service", "serde", "serde_json", + "serde_nanos", + "sp-api", + "sp-blockchain", "sp-core", + "sp-database", "sp-externalities", "sp-keystore", "sp-runtime", "sp-state-machine", + "sp-std", + "sp-storage", + "sp-trie", ] [[package]] @@ -3151,9 +3165,9 @@ checksum = "47be2f14c678be2fdcab04ab1171db51b2762ce6f0a8ee87c8dd4a04ed216135" [[package]] name = "itertools" -version = "0.10.0" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d572918e350e82412fe766d24b15e6682fb2ed2bbe018280caa810397cb319" +checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" dependencies = [ "either", ] @@ -7414,9 +7428,9 @@ dependencies = [ [[package]] name = "rand_distr" -version = "0.4.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "051b398806e42b9cd04ad9ec8f81e355d0a382c543ac6672c62f5a5b452ef142" +checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" dependencies = [ "num-traits", "rand 0.8.4", @@ -9289,6 +9303,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_nanos" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e44969a61f5d316be20a42ff97816efb3b407a924d06824c3d8a49fa8450de0e" +dependencies = [ + "serde", +] + [[package]] name = "sha-1" version = "0.8.2" diff --git a/bin/node/cli/src/cli.rs b/bin/node/cli/src/cli.rs index 00393c52f8b6..386215854b96 100644 --- a/bin/node/cli/src/cli.rs +++ b/bin/node/cli/src/cli.rs @@ -42,6 +42,10 @@ pub enum Subcommand { #[clap(name = "benchmark", about = "Benchmark runtime pallets.")] Benchmark(frame_benchmarking_cli::BenchmarkCmd), + /// Sub command for benchmarking the storage speed. + #[clap(name = "benchmark-storage", about = "Benchmark storage speed.")] + BenchmarkStorage(frame_benchmarking_cli::StorageCmd), + /// Try some command against runtime state. #[cfg(feature = "try-runtime")] TryRuntime(try_runtime_cli::TryRuntimeCmd), diff --git a/bin/node/cli/src/command.rs b/bin/node/cli/src/command.rs index d9ba53785ba0..cc6480bb90d5 100644 --- a/bin/node/cli/src/command.rs +++ b/bin/node/cli/src/command.rs @@ -95,6 +95,22 @@ pub fn run() -> Result<()> { You can enable it with `--features runtime-benchmarks`." .into()) }, + Some(Subcommand::BenchmarkStorage(cmd)) => { + if !cfg!(feature = "runtime-benchmarks") { + return Err("Benchmarking wasn't enabled when building the node. \ + You can enable it with `--features runtime-benchmarks`." + .into()) + } + + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { + let PartialComponents { client, task_manager, backend, .. } = new_partial(&config)?; + let db = backend.expose_db(); + let storage = backend.expose_storage(); + + Ok((cmd.run(config, client, db, storage), task_manager)) + }) + }, Some(Subcommand::Key(cmd)) => cmd.run(&cli), Some(Subcommand::Sign(cmd)) => cmd.run(), Some(Subcommand::Verify(cmd)) => cmd.run(), diff --git a/client/cli/src/arg_enums.rs b/client/cli/src/arg_enums.rs index a5403e3497c9..7c9974fff38a 100644 --- a/client/cli/src/arg_enums.rs +++ b/client/cli/src/arg_enums.rs @@ -194,7 +194,7 @@ impl Into for RpcMethods { } /// Database backend -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, PartialEq, Copy)] pub enum Database { /// Facebooks RocksDB RocksDb, diff --git a/client/cli/src/params/database_params.rs b/client/cli/src/params/database_params.rs index dd11c21f432b..70c929ecf202 100644 --- a/client/cli/src/params/database_params.rs +++ b/client/cli/src/params/database_params.rs @@ -21,7 +21,7 @@ use clap::Args; use sc_service::TransactionStorageMode; /// Parameters for block import. -#[derive(Debug, Clone, Args)] +#[derive(Debug, Clone, PartialEq, Args)] pub struct DatabaseParams { /// Select database backend to use. #[clap( diff --git a/client/cli/src/params/pruning_params.rs b/client/cli/src/params/pruning_params.rs index a8516ee1453a..de9628ecf7ad 100644 --- a/client/cli/src/params/pruning_params.rs +++ b/client/cli/src/params/pruning_params.rs @@ -21,7 +21,7 @@ use clap::Args; use sc_service::{KeepBlocks, PruningMode, Role}; /// Parameters to define the pruning mode -#[derive(Debug, Clone, Args)] +#[derive(Debug, Clone, PartialEq, Args)] pub struct PruningParams { /// Specify the state pruning mode, a number of blocks to keep or 'archive'. /// diff --git a/client/cli/src/params/shared_params.rs b/client/cli/src/params/shared_params.rs index 4066a75a9353..99eddf4e7c4b 100644 --- a/client/cli/src/params/shared_params.rs +++ b/client/cli/src/params/shared_params.rs @@ -22,7 +22,7 @@ use sc_service::config::BasePath; use std::path::PathBuf; /// Shared parameters used by all `CoreParams`. -#[derive(Debug, Clone, Args)] +#[derive(Debug, Clone, PartialEq, Args)] pub struct SharedParams { /// Specify the chain specification. /// diff --git a/client/db/Cargo.toml b/client/db/Cargo.toml index 82607f56f7d1..a9fa370a8ead 100644 --- a/client/db/Cargo.toml +++ b/client/db/Cargo.toml @@ -45,5 +45,6 @@ tempfile = "3" [features] default = [] test-helpers = [] +runtime-benchmarks = [] with-kvdb-rocksdb = ["kvdb-rocksdb"] with-parity-db = ["parity-db"] diff --git a/client/db/src/lib.rs b/client/db/src/lib.rs index a2d0cad72845..3fd3bf8d0904 100644 --- a/client/db/src/lib.rs +++ b/client/db/src/lib.rs @@ -106,7 +106,8 @@ const DEFAULT_CHILD_RATIO: (usize, usize) = (1, 10); pub type DbState = sp_state_machine::TrieBackend>>, HashFor>; -const DB_HASH_LEN: usize = 32; +/// Length of a [`DbHash`]. +pub const DB_HASH_LEN: usize = 32; /// Hash type that this backend uses for the database. pub type DbHash = sp_core::H256; @@ -1050,6 +1051,23 @@ impl Backend { Self::new(db_setting, canonicalization_delay).expect("failed to create test-db") } + /// Expose the Database that is used by this backend. + /// The second argument is the Column that stores the State. + /// + /// Should only be needed for benchmarking. + #[cfg(any(feature = "runtime-benchmarks"))] + pub fn expose_db(&self) -> (Arc>, sp_database::ColumnId) { + (self.storage.db.clone(), columns::STATE) + } + + /// Expose the Storage that is used by this backend. + /// + /// Should only be needed for benchmarking. + #[cfg(any(feature = "runtime-benchmarks"))] + pub fn expose_storage(&self) -> Arc>> { + self.storage.clone() + } + fn from_database( db: Arc>, canonicalization_delay: u64, diff --git a/utils/frame/benchmarking-cli/Cargo.toml b/utils/frame/benchmarking-cli/Cargo.toml index bbfcbb7e8b81..dc6c5eb22165 100644 --- a/utils/frame/benchmarking-cli/Cargo.toml +++ b/utils/frame/benchmarking-cli/Cargo.toml @@ -17,13 +17,21 @@ frame-benchmarking = { version = "4.0.0-dev", path = "../../../frame/benchmarkin frame-support = { version = "4.0.0-dev", path = "../../../frame/support" } sp-core = { version = "5.0.0", path = "../../../primitives/core" } sc-service = { version = "0.10.0-dev", default-features = false, path = "../../../client/service" } +sc-client-api = { version = "4.0.0-dev", path = "../../../client/api" } sc-cli = { version = "0.10.0-dev", path = "../../../client/cli" } sc-client-db = { version = "0.10.0-dev", path = "../../../client/db" } sc-executor = { version = "0.10.0-dev", path = "../../../client/executor" } + +sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-externalities = { version = "0.11.0", path = "../../../primitives/externalities" } +sp-database = { version = "4.0.0-dev", path = "../../../primitives/database" } +sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sp-keystore = { version = "0.11.0", path = "../../../primitives/keystore" } +sp-storage = { version = "5.0.0", path = "../../../primitives/storage" } sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } +sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } sp-state-machine = { version = "0.11.0", path = "../../../primitives/state-machine" } +sp-trie = { version = "5.0.0", path = "../../../primitives/trie" } codec = { version = "3.0.0", package = "parity-scale-codec" } clap = { version = "3.0", features = ["derive"] } chrono = "0.4" @@ -33,7 +41,14 @@ handlebars = "4.1.6" Inflector = "0.11.4" linked-hash-map = "0.5.4" log = "0.4.8" +itertools = "0.10.3" +serde_nanos = "0.1.2" +kvdb = "0.11.0" +hash-db = "0.15.2" +hex = "0.4.3" +memory-db = "0.29.0" +rand = { version = "0.8.4", features = ["small_rng"] } [features] -default = ["db"] +default = ["db", "sc-client-db/runtime-benchmarks"] db = ["sc-client-db/with-kvdb-rocksdb", "sc-client-db/with-parity-db"] diff --git a/utils/frame/benchmarking-cli/src/lib.rs b/utils/frame/benchmarking-cli/src/lib.rs index 3b0f4843d206..56aab0321ccd 100644 --- a/utils/frame/benchmarking-cli/src/lib.rs +++ b/utils/frame/benchmarking-cli/src/lib.rs @@ -16,11 +16,14 @@ // limitations under the License. mod command; +mod storage; mod writer; use sc_cli::{ExecutionStrategy, WasmExecutionMethod}; use std::{fmt::Debug, path::PathBuf}; +pub use storage::StorageCmd; + // Add a more relaxed parsing for pallet names by allowing pallet directory names with `-` to be // used like crate names with `_` fn parse_pallet_name(pallet: &str) -> String { diff --git a/utils/frame/benchmarking-cli/src/storage/cmd.rs b/utils/frame/benchmarking-cli/src/storage/cmd.rs new file mode 100644 index 000000000000..4376b616286a --- /dev/null +++ b/utils/frame/benchmarking-cli/src/storage/cmd.rs @@ -0,0 +1,171 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +use sc_cli::{CliConfiguration, DatabaseParams, PruningParams, Result, SharedParams}; +use sc_client_api::{Backend as ClientBackend, StorageProvider, UsageProvider}; +use sc_client_db::DbHash; +use sc_service::Configuration; +use sp_blockchain::HeaderBackend; +use sp_database::{ColumnId, Database}; +use sp_runtime::traits::{Block as BlockT, HashFor}; +use sp_state_machine::Storage; +use sp_storage::StateVersion; + +use clap::{Args, Parser}; +use log::info; +use rand::prelude::*; +use serde::Serialize; +use std::{fmt::Debug, sync::Arc}; + +use super::{record::StatSelect, template::TemplateData}; + +/// Benchmark the storage of a Substrate node with a live chain snapshot. +#[derive(Debug, Parser)] +pub struct StorageCmd { + #[allow(missing_docs)] + #[clap(flatten)] + pub shared_params: SharedParams, + + #[allow(missing_docs)] + #[clap(flatten)] + pub database_params: DatabaseParams, + + #[allow(missing_docs)] + #[clap(flatten)] + pub pruning_params: PruningParams, + + #[allow(missing_docs)] + #[clap(flatten)] + pub params: StorageParams, +} + +/// Parameters for modifying the benchmark behaviour and the post processing of the results. +#[derive(Debug, Default, Serialize, Clone, PartialEq, Args)] +pub struct StorageParams { + /// Path to write the *weight* file to. Can be a file or directory. + /// For substrate this should be `frame/support/src/weights`. + #[clap(long, default_value = ".")] + pub weight_path: String, + + /// Select a specific metric to calculate the final weight output. + #[clap(long = "metric", default_value = "average")] + pub weight_metric: StatSelect, + + /// Multiply the resulting weight with the given factor. Must be positive. + /// Is calculated before `weight_add`. + #[clap(long = "mul", default_value = "1")] + pub weight_mul: f64, + + /// Add the given offset to the resulting weight. + /// Is calculated after `weight_mul`. + #[clap(long = "add", default_value = "0")] + pub weight_add: u64, + + /// Skip the `read` benchmark. + #[clap(long)] + pub skip_read: bool, + + /// Skip the `write` benchmark. + #[clap(long)] + pub skip_write: bool, + + /// Rounds of warmups before measuring. + /// Only supported for `read` benchmarks. + #[clap(long, default_value = "1")] + pub warmups: u32, + + /// The `StateVersion` to use. Substrate `--dev` should use `V1` and Polkadot `V0`. + /// Selecting the wrong version can corrupt the DB. + #[clap(long, possible_values = ["0", "1"])] + pub state_version: u8, + + /// State cache size. + #[clap(long, default_value = "0")] + pub state_cache_size: usize, +} + +impl StorageCmd { + /// Calls into the Read and Write benchmarking functions. + /// Processes the output and writes it into files and stdout. + pub async fn run( + &self, + cfg: Configuration, + client: Arc, + db: (Arc>, ColumnId), + storage: Arc>>, + ) -> Result<()> + where + BA: ClientBackend, + Block: BlockT, + C: UsageProvider + StorageProvider + HeaderBackend, + { + let mut template = TemplateData::new(&cfg, &self.params); + + if !self.params.skip_read { + let record = self.bench_read(client.clone())?; + record.save_json(&cfg, "read")?; + let stats = record.calculate_stats()?; + info!("Time summary [ns]:\n{:?}\nValue size summary:\n{:?}", stats.0, stats.1); + template.set_stats(Some(stats), None)?; + } + + if !self.params.skip_write { + let record = self.bench_write(client, db, storage)?; + record.save_json(&cfg, "write")?; + let stats = record.calculate_stats()?; + info!("Time summary [ns]:\n{:?}\nValue size summary:\n{:?}", stats.0, stats.1); + template.set_stats(None, Some(stats))?; + } + + template.write(&self.params.weight_path) + } + + /// Returns the specified state version. + pub(crate) fn state_version(&self) -> StateVersion { + match self.params.state_version { + 0 => StateVersion::V0, + 1 => StateVersion::V1, + _ => unreachable!("Clap set to only allow 0 and 1"), + } + } + + /// Creates an rng from a random seed. + pub(crate) fn setup_rng() -> impl rand::Rng { + let seed = rand::thread_rng().gen::(); + info!("Using seed {}", seed); + StdRng::seed_from_u64(seed) + } +} + +// Boilerplate +impl CliConfiguration for StorageCmd { + fn shared_params(&self) -> &SharedParams { + &self.shared_params + } + + fn database_params(&self) -> Option<&DatabaseParams> { + Some(&self.database_params) + } + + fn pruning_params(&self) -> Option<&PruningParams> { + Some(&self.pruning_params) + } + + fn state_cache_size(&self) -> Result { + Ok(self.params.state_cache_size) + } +} diff --git a/utils/frame/benchmarking-cli/src/storage/mod.rs b/utils/frame/benchmarking-cli/src/storage/mod.rs new file mode 100644 index 000000000000..9849cbcb6097 --- /dev/null +++ b/utils/frame/benchmarking-cli/src/storage/mod.rs @@ -0,0 +1,24 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +pub mod cmd; +pub mod read; +pub mod record; +pub mod template; +pub mod write; + +pub use cmd::StorageCmd; diff --git a/utils/frame/benchmarking-cli/src/storage/read.rs b/utils/frame/benchmarking-cli/src/storage/read.rs new file mode 100644 index 000000000000..3974c4010f63 --- /dev/null +++ b/utils/frame/benchmarking-cli/src/storage/read.rs @@ -0,0 +1,76 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +use sc_cli::Result; +use sc_client_api::{Backend as ClientBackend, StorageProvider, UsageProvider}; +use sp_core::storage::StorageKey; +use sp_runtime::{ + generic::BlockId, + traits::{Block as BlockT, Header as HeaderT}, +}; + +use log::info; +use rand::prelude::*; +use std::{fmt::Debug, sync::Arc, time::Instant}; + +use super::{cmd::StorageCmd, record::BenchRecord}; + +impl StorageCmd { + /// Benchmarks the time it takes to read a single Storage item. + /// Uses the latest state that is available for the given client. + pub(crate) fn bench_read(&self, client: Arc) -> Result + where + C: UsageProvider + StorageProvider, + B: BlockT + Debug, + BA: ClientBackend, + <::Header as HeaderT>::Number: From, + { + let mut record = BenchRecord::default(); + let block = BlockId::Number(client.usage_info().chain.best_number); + + info!("Preparing keys from block {}", block); + // Load all keys and randomly shuffle them. + let empty_prefix = StorageKey(Vec::new()); + let mut keys = client.storage_keys(&block, &empty_prefix)?; + let mut rng = Self::setup_rng(); + keys.shuffle(&mut rng); + + // Run some rounds of the benchmark as warmup. + for i in 0..self.params.warmups { + info!("Warmup round {}/{}", i + 1, self.params.warmups); + for key in keys.clone() { + let _ = client + .storage(&block, &key) + .expect("Checked above to exist") + .ok_or("Value unexpectedly empty")?; + } + } + + // Interesting part here: + // Read all the keys in the database and measure the time it takes to access each. + info!("Reading {} keys", keys.len()); + for key in keys.clone() { + let start = Instant::now(); + let v = client + .storage(&block, &key) + .expect("Checked above to exist") + .ok_or("Value unexpectedly empty")?; + record.append(v.0.len(), start.elapsed())?; + } + Ok(record) + } +} diff --git a/utils/frame/benchmarking-cli/src/storage/record.rs b/utils/frame/benchmarking-cli/src/storage/record.rs new file mode 100644 index 000000000000..00a613c71300 --- /dev/null +++ b/utils/frame/benchmarking-cli/src/storage/record.rs @@ -0,0 +1,191 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +//! Calculates statistics and fills out the `weight.hbs` template. + +use sc_cli::Result; +use sc_service::Configuration; + +use log::info; +use serde::Serialize; +use std::{fmt, fs, result, str::FromStr, time::Duration}; + +/// Raw output of a Storage benchmark. +#[derive(Debug, Default, Clone, Serialize)] +pub(crate) struct BenchRecord { + /// Multi-Map of value sizes and the time that it took to access them. + ns_per_size: Vec<(u64, u64)>, +} + +/// Various statistics that help to gauge the quality of the produced weights. +/// Will be written to the weight file and printed to console. +#[derive(Serialize, Default, Clone)] +pub(crate) struct Stats { + /// Sum of all values. + sum: u64, + /// Minimal observed value. + min: u64, + /// Maximal observed value. + max: u64, + + /// Average of all values. + avg: u64, + /// Median of all values. + median: u64, + /// Standard derivation of all values. + stddev: f64, + + /// 99th percentile. At least 99% of all values are below this threshold. + p99: u64, + /// 95th percentile. At least 95% of all values are below this threshold. + p95: u64, + /// 75th percentile. At least 75% of all values are below this threshold. + p75: u64, +} + +/// Selects a specific field from a [`Stats`] object. +/// Not all fields are available. +#[derive(Debug, Clone, Copy, Serialize, PartialEq)] +pub enum StatSelect { + /// Select the maximum. + Maximum, + /// Select the average. + Average, + /// Select the median. + Median, + /// Select the 99th percentile. + P99Percentile, + /// Select the 95th percentile. + P95Percentile, + /// Select the 75th percentile. + P75Percentile, +} + +impl BenchRecord { + /// Appends a new record. Uses safe casts. + pub fn append(&mut self, size: usize, d: Duration) -> Result<()> { + let size: u64 = size.try_into().map_err(|e| format!("Size overflow u64: {}", e))?; + let ns: u64 = d + .as_nanos() + .try_into() + .map_err(|e| format!("Nanoseconds overflow u64: {}", e))?; + self.ns_per_size.push((size, ns)); + Ok(()) + } + + /// Returns the statistics for *time* and *value size*. + pub(crate) fn calculate_stats(self) -> Result<(Stats, Stats)> { + let (size, time): (Vec<_>, Vec<_>) = self.ns_per_size.into_iter().unzip(); + let size = Stats::new(&size)?; + let time = Stats::new(&time)?; + Ok((time, size)) // The swap of time/size here is intentional. + } + + /// Saves the raw results in a json file in the current directory. + /// Prefixes it with the DB name and suffixed with `path_suffix`. + pub fn save_json(&self, cfg: &Configuration, path_suffix: &str) -> Result<()> { + let path = format!("{}_{}.json", cfg.database, path_suffix).to_lowercase(); + let json = serde_json::to_string_pretty(&self) + .map_err(|e| format!("Serializing as JSON: {:?}", e))?; + fs::write(&path, json)?; + info!("Raw data written to {:?}", fs::canonicalize(&path)?); + Ok(()) + } +} + +impl Stats { + /// Calculates statistics and returns them. + pub fn new(xs: &Vec) -> Result { + if xs.is_empty() { + return Err("Empty input is invalid".into()) + } + let (avg, stddev) = Self::avg_and_stddev(&xs); + + Ok(Self { + sum: xs.iter().sum(), + min: *xs.iter().min().expect("Checked for non-empty above"), + max: *xs.iter().max().expect("Checked for non-empty above"), + + avg: avg as u64, + median: Self::percentile(xs.clone(), 0.50), + stddev: (stddev * 100.0).round() / 100.0, // round to 1/100 + + p99: Self::percentile(xs.clone(), 0.99), + p95: Self::percentile(xs.clone(), 0.95), + p75: Self::percentile(xs.clone(), 0.75), + }) + } + + /// Returns the selected stat. + pub(crate) fn select(&self, s: StatSelect) -> u64 { + match s { + StatSelect::Maximum => self.max, + StatSelect::Average => self.avg, + StatSelect::Median => self.median, + StatSelect::P99Percentile => self.p99, + StatSelect::P95Percentile => self.p95, + StatSelect::P75Percentile => self.p75, + } + } + + /// Returns the *average* and the *standard derivation*. + fn avg_and_stddev(xs: &Vec) -> (f64, f64) { + let avg = xs.iter().map(|x| *x as f64).sum::() / xs.len() as f64; + let variance = xs.iter().map(|x| (*x as f64 - avg).powi(2)).sum::() / xs.len() as f64; + (avg, variance.sqrt()) + } + + /// Returns the specified percentile for the given data. + /// This is best effort since it ignores the interpolation case. + fn percentile(mut xs: Vec, p: f64) -> u64 { + xs.sort(); + let index = (xs.len() as f64 * p).ceil() as usize; + xs[index] + } +} + +impl fmt::Debug for Stats { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Total: {}\n", self.sum)?; + write!(f, "Min: {}, Max: {}\n", self.min, self.max)?; + write!(f, "Average: {}, Median: {}, Stddev: {}\n", self.avg, self.median, self.stddev)?; + write!(f, "Percentiles 99th, 95th, 75th: {}, {}, {}", self.p99, self.p95, self.p75) + } +} + +impl Default for StatSelect { + /// Returns the `Average` selector. + fn default() -> Self { + Self::Average + } +} + +impl FromStr for StatSelect { + type Err = &'static str; + + fn from_str(day: &str) -> result::Result { + match day.to_lowercase().as_str() { + "max" => Ok(Self::Maximum), + "average" => Ok(Self::Average), + "median" => Ok(Self::Median), + "p99" => Ok(Self::P99Percentile), + "p95" => Ok(Self::P95Percentile), + "p75" => Ok(Self::P75Percentile), + _ => Err("String was not a StatSelect"), + } + } +} diff --git a/utils/frame/benchmarking-cli/src/storage/template.rs b/utils/frame/benchmarking-cli/src/storage/template.rs new file mode 100644 index 000000000000..56e0869a914a --- /dev/null +++ b/utils/frame/benchmarking-cli/src/storage/template.rs @@ -0,0 +1,126 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +use sc_cli::Result; +use sc_service::Configuration; + +use log::info; +use serde::Serialize; +use std::{env, fs, path::PathBuf}; + +use super::{cmd::StorageParams, record::Stats}; + +static VERSION: &'static str = env!("CARGO_PKG_VERSION"); +static TEMPLATE: &str = include_str!("./weights.hbs"); + +/// Data consumed by Handlebar to fill out the `weights.hbs` template. +#[derive(Serialize, Default, Debug, Clone)] +pub(crate) struct TemplateData { + /// Name of the database used. + db_name: String, + /// Name of the runtime. Taken from the chain spec. + runtime_name: String, + /// Version of the benchmarking CLI used. + version: String, + /// Date that the template was filled out. + date: String, + /// Command line arguments that were passed to the CLI. + args: Vec, + /// Storage params of the executed command. + params: StorageParams, + /// The weight for one `read`. + read_weight: u64, + /// The weight for one `write`. + write_weight: u64, + /// Stats about a `read` benchmark. Contains *time* and *value size* stats. + /// The *value size* stats are currently not used in the template. + read: Option<(Stats, Stats)>, + /// Stats about a `write` benchmark. Contains *time* and *value size* stats. + /// The *value size* stats are currently not used in the template. + write: Option<(Stats, Stats)>, +} + +impl TemplateData { + /// Returns a new [`Self`] from the given configuration. + pub fn new(cfg: &Configuration, params: &StorageParams) -> Self { + TemplateData { + db_name: format!("{}", cfg.database), + runtime_name: cfg.chain_spec.name().into(), + version: VERSION.into(), + date: chrono::Utc::now().format("%Y-%m-%d (Y/M/D)").to_string(), + args: env::args().collect::>(), + params: params.clone(), + ..Default::default() + } + } + + /// Sets the stats and calculates the final weights. + pub fn set_stats( + &mut self, + read: Option<(Stats, Stats)>, + write: Option<(Stats, Stats)>, + ) -> Result<()> { + if let Some(read) = read { + self.read_weight = calc_weight(&read.0, &self.params)?; + self.read = Some(read); + } + if let Some(write) = write { + self.write_weight = calc_weight(&write.0, &self.params)?; + self.write = Some(write); + } + Ok(()) + } + + /// Filles out the `weights.hbs` HBS template with its own data. + /// Writes the result to `path` which can be a directory or file. + pub fn write(&self, path: &str) -> Result<()> { + let mut handlebars = handlebars::Handlebars::new(); + // Format large integers with underscore. + handlebars.register_helper("underscore", Box::new(crate::writer::UnderscoreHelper)); + // Don't HTML escape any characters. + handlebars.register_escape_fn(|s| -> String { s.to_string() }); + + let out_path = self.build_path(path); + let mut fd = fs::File::create(&out_path)?; + info!("Writing weights to {:?}", fs::canonicalize(&out_path)?); + handlebars + .render_template_to_write(&TEMPLATE, &self, &mut fd) + .map_err(|e| format!("HBS template write: {:?}", e).into()) + } + + /// Builds a path for the weight file. + fn build_path(&self, weight_out: &str) -> PathBuf { + let mut path = PathBuf::from(weight_out); + if path.is_dir() { + path.push(format!("{}_weights.rs", self.db_name.to_lowercase())); + path.set_extension("rs"); + } + path + } +} + +/// Calculates the final weight by multiplying the selected metric with +/// `mul` and adding `add`. +/// Does not use safe casts and can overflow. +fn calc_weight(stat: &Stats, params: &StorageParams) -> Result { + if params.weight_mul.is_sign_negative() || !params.weight_mul.is_normal() { + return Err("invalid floating number for `weight_mul`".into()) + } + let s = stat.select(params.weight_metric) as f64; + let w = s.mul_add(params.weight_mul, params.weight_add as f64).ceil(); + Ok(w as u64) // No safe cast here since there is no `From` for `u64`. +} diff --git a/utils/frame/benchmarking-cli/src/storage/weights.hbs b/utils/frame/benchmarking-cli/src/storage/weights.hbs new file mode 100644 index 000000000000..ffeb1fe04d81 --- /dev/null +++ b/utils/frame/benchmarking-cli/src/storage/weights.hbs @@ -0,0 +1,107 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION {{version}} +//! DATE: {{date}} +//! +//! DATABASE: `{{db_name}}`, RUNTIME: `{{runtime_name}}` +//! SKIP-WRITE: `{{params.skip_write}}`, SKIP-READ: `{{params.skip_read}}`, WARMUPS: `{{params.warmups}}` +//! STATE-VERSION: `V{{params.state_version}}`, STATE-CACHE-SIZE: `{{params.state_cache_size}}` +//! WEIGHT-PATH: `{{params.weight_path}}` +//! METRIC: `{{params.weight_metric}}`, WEIGHT-MUL: `{{params.weight_mul}}`, WEIGHT-ADD: `{{params.weight_add}}` + +// Executed Command: +{{#each args as |arg|}} +// {{arg}} +{{/each}} + +/// Storage DB weights for the {{runtime_name}} runtime and {{db_name}}. +pub mod constants { + use frame_support::{parameter_types, weights::{RuntimeDbWeight, constants}}; + + parameter_types! { + {{#if (eq db_name "ParityDb")}} + /// ParityDB can be enabled with a feature flag, but is still experimental. These weights + /// are available for brave runtime engineers who may want to try this out as default. + {{else}} + /// By default, Substrate uses RocksDB, so this will be the weight used throughout + /// the runtime. + {{/if}} + pub const {{db_name}}Weight: RuntimeDbWeight = RuntimeDbWeight { + /// Time to read one storage item. + /// Calculated by multiplying the *{{params.weight_metric}}* of all values with `{{params.weight_mul}}` and adding `{{params.weight_add}}`. + /// + /// Stats [ns]: + /// Min, Max: {{underscore read.0.min}}, {{underscore read.0.max}} + /// Average: {{underscore read.0.avg}} + /// Median: {{underscore read.0.median}} + /// StdDev: {{read.0.stddev}} + /// + /// Percentiles [ns]: + /// 99th: {{underscore read.0.p99}} + /// 95th: {{underscore read.0.p95}} + /// 75th: {{underscore read.0.p75}} + read: {{underscore read_weight}} * constants::WEIGHT_PER_NANOS, + + /// Time to write one storage item. + /// Calculated by multiplying the *{{params.weight_metric}}* of all values with `{{params.weight_mul}}` and adding `{{params.weight_add}}`. + /// + /// Stats [ns]: + /// Min, Max: {{underscore write.0.min}}, {{underscore write.0.max}} + /// Average: {{underscore write.0.avg}} + /// Median: {{underscore write.0.median}} + /// StdDev: {{write.0.stddev}} + /// + /// Percentiles [ns]: + /// 99th: {{underscore write.0.p99}} + /// 95th: {{underscore write.0.p95}} + /// 75th: {{underscore write.0.p75}} + write: {{underscore write_weight}} * constants::WEIGHT_PER_NANOS, + }; + } + + #[cfg(test)] + mod test_db_weights { + use super::constants::{{db_name}}Weight as W; + use frame_support::weights::constants; + + /// Checks that all weights exist and have sane values. + // NOTE: If this test fails but you are sure that the generated values are fine, + // you can delete it. + #[test] + fn bound() { + // At least 1 µs. + assert!( + W::get().reads(1) >= constants::WEIGHT_PER_MICROS, + "Read weight should be at least 1 µs." + ); + assert!( + W::get().writes(1) >= constants::WEIGHT_PER_MICROS, + "Write weight should be at least 1 µs." + ); + // At most 1 ms. + assert!( + W::get().reads(1) <= constants::WEIGHT_PER_MILLIS, + "Read weight should be at most 1 ms." + ); + assert!( + W::get().writes(1) <= constants::WEIGHT_PER_MILLIS, + "Write weight should be at most 1 ms." + ); + } + } +} diff --git a/utils/frame/benchmarking-cli/src/storage/write.rs b/utils/frame/benchmarking-cli/src/storage/write.rs new file mode 100644 index 000000000000..eb9ba11f3069 --- /dev/null +++ b/utils/frame/benchmarking-cli/src/storage/write.rs @@ -0,0 +1,131 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +use sc_cli::Result; +use sc_client_api::UsageProvider; +use sc_client_db::{DbHash, DbState, DB_HASH_LEN}; +use sp_api::StateBackend; +use sp_blockchain::HeaderBackend; +use sp_database::{ColumnId, Transaction}; +use sp_runtime::{ + generic::BlockId, + traits::{Block as BlockT, HashFor, Header as HeaderT}, +}; +use sp_trie::PrefixedMemoryDB; + +use log::info; +use rand::prelude::*; +use std::{fmt::Debug, sync::Arc, time::Instant}; + +use super::{cmd::StorageCmd, record::BenchRecord}; + +impl StorageCmd { + /// Benchmarks the time it takes to write a single Storage item. + /// Uses the latest state that is available for the given client. + pub(crate) fn bench_write( + &self, + client: Arc, + (db, state_col): (Arc>, ColumnId), + storage: Arc>>, + ) -> Result + where + Block: BlockT

+ Debug, + H: HeaderT, + C: UsageProvider + HeaderBackend, + { + // Store the time that it took to write each value. + let mut record = BenchRecord::default(); + + let supports_rc = db.supports_ref_counting(); + let block = BlockId::Number(client.usage_info().chain.best_number); + let header = client.header(block)?.ok_or("Header not found")?; + let original_root = *header.state_root(); + let trie = DbState::::new(storage.clone(), original_root); + + info!("Preparing keys from block {}", block); + // Load all KV pairs and randomly shuffle them. + let mut kvs = trie.pairs(); + let mut rng = Self::setup_rng(); + kvs.shuffle(&mut rng); + + info!("Writing {} keys", kvs.len()); + // Write each value in one commit. + for (k, original_v) in kvs.iter() { + // Create a random value to overwrite with. + // NOTE: We use a possibly higher entropy than the original value, + // could be improved but acts as an over-estimation which is fine for now. + let mut new_v = vec![0; original_v.len()]; + rng.fill_bytes(&mut new_v[..]); + + // Interesting part here: + let start = Instant::now(); + // Create a TX that will modify the Trie in the DB and + // calculate the root hash of the Trie after the modification. + let replace = vec![(k.as_ref(), Some(new_v.as_ref()))]; + let (_, stx) = trie.storage_root(replace.iter().cloned(), self.state_version()); + // Only the keep the insertions, since we do not want to benchmark pruning. + let tx = convert_tx::(stx.clone(), true, state_col, supports_rc); + db.commit(tx).map_err(|e| format!("Writing to the Database: {}", e))?; + record.append(new_v.len(), start.elapsed())?; + + // Now undo the changes by removing what was added. + let tx = convert_tx::(stx.clone(), false, state_col, supports_rc); + db.commit(tx).map_err(|e| format!("Writing to the Database: {}", e))?; + } + Ok(record) + } +} + +/// Converts a Trie transaction into a DB transaction. +/// Removals are ignored and will not be included in the final tx. +/// `invert_inserts` replaces all inserts with removals. +/// +/// The keys of Trie transactions are prefixed, this is treated differently by each DB. +/// ParityDB can use an optimization where only the last `DB_HASH_LEN` byte are needed. +/// The last `DB_HASH_LEN` byte are the hash of the actual stored data, everything +/// before that is the route in the Patricia Trie. +/// RocksDB cannot do this and needs the whole route, hence no key truncating for RocksDB. +/// +/// TODO: +/// This copies logic from [`sp_client_db::Backend::try_commit_operation`] and should be +/// refactored to use a canonical `sanitize_key` function from `sp_client_db` which +/// does not yet exist. +fn convert_tx( + mut tx: PrefixedMemoryDB>, + invert_inserts: bool, + col: ColumnId, + supports_rc: bool, +) -> Transaction { + let mut ret = Transaction::::default(); + + for (mut k, (v, rc)) in tx.drain().into_iter() { + if supports_rc { + let _prefix = k.drain(0..k.len() - DB_HASH_LEN); + } + + if rc > 0 { + if invert_inserts { + ret.set(col, k.as_ref(), &v); + } else { + ret.remove(col, &k); + } + } + // < 0 means removal - ignored. + // 0 means no modification. + } + ret +} diff --git a/utils/frame/benchmarking-cli/src/writer.rs b/utils/frame/benchmarking-cli/src/writer.rs index 1e31c4e98e56..17f1221e46d8 100644 --- a/utils/frame/benchmarking-cli/src/writer.rs +++ b/utils/frame/benchmarking-cli/src/writer.rs @@ -436,7 +436,7 @@ where // A Handlebars helper to add an underscore after every 3rd character, // i.e. a separator for large numbers. #[derive(Clone, Copy)] -struct UnderscoreHelper; +pub(crate) struct UnderscoreHelper; impl handlebars::HelperDef for UnderscoreHelper { fn call<'reg: 'rc, 'rc>( &self, From c0d51ec8879224bf6003fc67d91f6c8ecb236276 Mon Sep 17 00:00:00 2001 From: driemworks Date: Fri, 25 Feb 2022 17:49:58 -0500 Subject: [PATCH 532/695] add transfer assets extrinsic --- .../pallets/iris-assets/src/lib.rs | 33 ++++++++++++ .../pallets/iris-assets/src/mock.rs | 8 ++- .../pallets/iris-assets/src/tests.rs | 52 +++++++++++++++++-- 3 files changed, 84 insertions(+), 9 deletions(-) diff --git a/bin/node-template/pallets/iris-assets/src/lib.rs b/bin/node-template/pallets/iris-assets/src/lib.rs index d1f5772f048c..3a3ef3061eb1 100644 --- a/bin/node-template/pallets/iris-assets/src/lib.rs +++ b/bin/node-template/pallets/iris-assets/src/lib.rs @@ -177,6 +177,8 @@ pub mod pallet { NoSuchAssetClass, /// the account does not have a sufficient balance InsufficientBalance, + /// the asset id is unknown or you do not have access to it + InvalidAssetId, } #[pallet::hooks] @@ -255,6 +257,37 @@ pub mod pallet { Self::deposit_event(Event::AssetCreated(asset_id.clone())); Ok(()) } + + /// transfer an amount of owned assets to another address + /// + /// * `target`: The target node to receive the assets + /// * `asset_id`: The asset id of the asset to be transferred + /// * `amount`: The amount of the asset to transfer + /// + #[pallet::weight(100)] + pub fn transfer_asset( + origin: OriginFor, + target: ::Source, + asset_id: T::AssetId, + #[pallet::compact] amount: T::Balance, + ) -> DispatchResult { + let current_owner = ensure_signed(origin)?; + + ensure!( + AssetAccess::::contains_key(current_owner.clone(), asset_id.clone()), + Error::::InvalidAssetId, + ); + + let new_origin = system::RawOrigin::Signed(current_owner.clone()).into(); + >::transfer( + new_origin, + asset_id.clone(), + target.clone(), + amount.clone(), + )?; + + Ok(()) + } /// request to fetch bytes from ipfs and add to offchain storage /// diff --git a/bin/node-template/pallets/iris-assets/src/mock.rs b/bin/node-template/pallets/iris-assets/src/mock.rs index 5198c428690f..5743e7b19dd9 100644 --- a/bin/node-template/pallets/iris-assets/src/mock.rs +++ b/bin/node-template/pallets/iris-assets/src/mock.rs @@ -123,13 +123,11 @@ pub fn new_test_ext() -> sp_io::TestExternalities { // Build genesis storage according to the mock runtime. -pub fn new_test_ext_funded(pair1_funded: sp_core::sr25519::Pair) -> sp_io::TestExternalities { +pub fn new_test_ext_funded(pairs: Vec<(sp_core::sr25519::Public, u64)>) -> sp_io::TestExternalities { let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - // let (pair1, _) = sp_core::sr25519::Pair::generate(); - let (pair2, _) = sp_core::sr25519::Pair::generate(); - let (pair3, _) = sp_core::sr25519::Pair::generate(); + pallet_balances::GenesisConfig:: { - balances: vec![(pair1_funded.clone().public(), 10), (pair2.public(), 20), (pair3.public(), 30)], + balances: pairs, } .assimilate_storage(&mut t) .unwrap(); diff --git a/bin/node-template/pallets/iris-assets/src/tests.rs b/bin/node-template/pallets/iris-assets/src/tests.rs index ddd9228bd466..6ed376173f34 100644 --- a/bin/node-template/pallets/iris-assets/src/tests.rs +++ b/bin/node-template/pallets/iris-assets/src/tests.rs @@ -24,6 +24,7 @@ fn iris_assets_initial_state() { fn iris_assets_ipfs_add_bytes_works_for_valid_value() { // Given: I am a valid node with a positive balance let (p, _) = sp_core::sr25519::Pair::generate(); + let pairs = vec![(p.clone().public(), 10)]; let multiaddr_vec = "/ip4/127.0.0.1/tcp/4001/p2p/12D3KooWMvyvKxYcy9mjbFbXcogFSCvENzQ62ogRxHKZaksFCkAp".as_bytes().to_vec(); let cid_vec = "QmPZv7P8nQUSh2CpqTvUeYemFyjvMjgWEs8H1Tm8b3zAm9".as_bytes().to_vec(); let name: Vec = "test.txt".as_bytes().to_vec(); @@ -41,7 +42,7 @@ fn iris_assets_ipfs_add_bytes_works_for_valid_value() { balance.clone(), ); - new_test_ext_funded(p.clone()).execute_with(|| { + new_test_ext_funded(pairs).execute_with(|| { // WHEN: I invoke the create_storage_assets extrinsic assert_ok!(Iris::create( Origin::signed(p.clone().public()), @@ -66,6 +67,7 @@ fn iris_assets_ipfs_add_bytes_works_for_valid_value() { fn iris_assets_request_data_works_for_valid_values() { // GIVEN: I am a valid Iris node with a positive balance let (p, _) = sp_core::sr25519::Pair::generate(); + let pairs = vec![(p.clone().public(), 10)]; // let cid_vec = "QmPZv7P8nQUSh2CpqTvUeYemFyjvMjgWEs8H1Tm8b3zAm9".as_bytes().to_vec(); let asset_id = 1; let expected_data_command = crate::DataCommand::CatBytes( @@ -73,7 +75,7 @@ fn iris_assets_request_data_works_for_valid_values() { p.clone().public(), asset_id.clone(), ); - new_test_ext_funded(p.clone()).execute_with(|| { + new_test_ext_funded(pairs).execute_with(|| { // WHEN: I invoke the request_data extrinsic assert_ok!(Iris::request_bytes( Origin::signed(p.clone().public()), @@ -94,11 +96,12 @@ fn iris_assets_request_data_works_for_valid_values() { fn iris_assets_submit_ipfs_add_results_works_for_valid_values() { // GIVEN: I am a valid Iris node with a positive valance let (p, _) = sp_core::sr25519::Pair::generate(); + let pairs = vec![(p.clone().public(), 10)]; let cid_vec = "QmPZv7P8nQUSh2CpqTvUeYemFyjvMjgWEs8H1Tm8b3zAm9".as_bytes().to_vec(); let id = 1; let balance = 1; - new_test_ext_funded(p.clone()).execute_with(|| { + new_test_ext_funded(pairs).execute_with(|| { // WHEN: I invoke the submit_ipfs_add_results extrinsic assert_ok!(Iris::submit_ipfs_add_results( Origin::signed(p.clone().public()), @@ -119,11 +122,12 @@ fn iris_assets_submit_ipfs_add_results_works_for_valid_values() { fn iris_assets_mint_tickets_works_for_valid_values() { // GIVEN: I am a valid Iris node with a positive valance let (p, _) = sp_core::sr25519::Pair::generate(); + let pairs = vec![(p.clone().public(), 10)]; let cid_vec = "QmPZv7P8nQUSh2CpqTvUeYemFyjvMjgWEs8H1Tm8b3zAm9".as_bytes().to_vec(); let balance = 1; let id = 1; - new_test_ext_funded(p.clone()).execute_with(|| { + new_test_ext_funded(pairs).execute_with(|| { // AND: I create an owned asset class assert_ok!(Iris::submit_ipfs_add_results( Origin::signed(p.clone().public()), @@ -145,3 +149,43 @@ fn iris_assets_mint_tickets_works_for_valid_values() { assert_eq!(asset_class_owner, p.clone().public()) }); } + +#[test] +fn iris_assets_can_transer_assets() { + // GIVEN: I am valid Iris node with a positive balance // GIVEN: I am a valid Iris node with a positive valance + let (p, _) = sp_core::sr25519::Pair::generate(); + let (p2, _) = sp_core::sr25519::Pair::generate(); + let pairs = vec![(p.clone().public(), 10), (p2.clone().public(), 10)]; + let cid_vec = "QmPZv7P8nQUSh2CpqTvUeYemFyjvMjgWEs8H1Tm8b3zAm9".as_bytes().to_vec(); + let balance = 1; + let id = 1; + + new_test_ext_funded(pairs).execute_with(|| { + // AND: I create an owned asset class + assert_ok!(Iris::submit_ipfs_add_results( + Origin::signed(p.clone().public()), + p.clone().public(), + cid_vec.clone(), + id.clone(), + balance.clone(), + )); + // WHEN: I invoke the mint_tickets extrinsic + assert_ok!(Iris::mint( + Origin::signed(p.clone().public()), + p.clone().public(), + id.clone(), + balance.clone(), + )); + // THEN: new assets are created and awarded to the benficiary + // AND: A new entry is added to the AssetAccess StorageDoubleMap + let asset_class_owner = crate::AssetAccess::::get(p.clone().public(), id.clone()); + assert_eq!(asset_class_owner, p.clone().public()); + // THEN: I can transfer my owned asset to another address + assert_ok!(Iris::transfer_asset( + Origin::signed(p.clone().public()), + p2.clone().public(), + id.clone(), + balance.clone(), + )); + }); +} From 039f2b6c05255c6ba840ddea92a107a88881f9a7 Mon Sep 17 00:00:00 2001 From: driemworks Date: Fri, 25 Feb 2022 19:08:47 -0500 Subject: [PATCH 533/695] add chain ext --- .../runtime/src/chain-extension.rs | 55 ++++++++++++++++++ bin/node-template/runtime/src/lib.rs | 58 ++++++++++++++++++- 2 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 bin/node-template/runtime/src/chain-extension.rs diff --git a/bin/node-template/runtime/src/chain-extension.rs b/bin/node-template/runtime/src/chain-extension.rs new file mode 100644 index 000000000000..ed33b78d912f --- /dev/null +++ b/bin/node-template/runtime/src/chain-extension.rs @@ -0,0 +1,55 @@ +// use codec::Encode; +// use frame_support::log::{ +// error, +// trace, +// }; +// use pallet_contracts::chain_extension::{ +// ChainExtension, +// Environment, +// Ext, +// InitState, +// RetVal, +// SysConfig, +// UncheckedFrom, +// }; +// use sp_runtime::DispatchError; + +// pub struct IrisExtension; + +// impl ChainExtension for IrisExtension { +// fn call( +// func_id: u32, +// env: Environment, +// ) -> Result +// where +// ::AccountId: +// UncheckedFrom<::Hash> + AsRef<[u8]>, +// { +// match func_id { +// 1 => { +// let mut env = env.buf_in_buf_out(); +// let arg: [u8; 32] = env.read_as()?; +// // call to transfer assets should go here +// // crate::IrisAssets::trandsfer(&arg); +// // let random_slice = random_seed.encode(); +// trace!( +// target: "runtime", +// "[ChainExtension]|call|func_id:{:}", +// func_id +// ); +// // env.write(&random_slice, false, None).map_err(|_| { +// // DispatchError::Other("ChainExtension failed to call transfer_assets") +// // })?; +// } +// _ => { +// error!("Called an unregistered `func_id`: {:}", func_id); +// return Err(DispatchError::Other("Unimplemented func_id")) +// } +// } +// Ok(RetVal::Converging(0)) +// } + +// fn enabled() -> bool { +// true +// } +// } diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index edca788f2f5d..fdaa660600d4 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -283,7 +283,7 @@ impl pallet_contracts::Config for Runtime { type CallStack = [pallet_contracts::Frame; 31]; type WeightPrice = pallet_transaction_payment::Pallet; type WeightInfo = pallet_contracts::weights::SubstrateWeight; - type ChainExtension = (); + type ChainExtension = IrisExtension; type DeletionQueueDepth = DeletionQueueDepth; type DeletionWeightLimit = DeletionWeightLimit; type Schedule = Schedule; @@ -800,3 +800,59 @@ impl_runtime_apis! { } } } + +// use codec::Encode; +use frame_support::log::{ + error, + trace, +}; +use pallet_contracts::chain_extension::{ + ChainExtension, + Environment, + Ext, + InitState, + RetVal, + SysConfig, + UncheckedFrom, +}; +use sp_runtime::DispatchError; + +pub struct IrisExtension; + +impl ChainExtension for IrisExtension { + fn call( + func_id: u32, + env: Environment, + ) -> Result + where + ::AccountId: + UncheckedFrom<::Hash> + AsRef<[u8]>, + { + match func_id { + 1 => { + let mut env = env.buf_in_buf_out(); + let arg: [u8; 32] = env.read_as()?; + // call to transfer assets should go here + // crate::IrisAssets::trandsfer(&arg); + // let random_slice = random_seed.encode(); + trace!( + target: "runtime", + "[ChainExtension]|call|func_id:{:}", + func_id + ); + // env.write(&random_slice, false, None).map_err(|_| { + // DispatchError::Other("ChainExtension failed to call transfer_assets") + // })?; + } + _ => { + error!("Called an unregistered `func_id`: {:}", func_id); + return Err(DispatchError::Other("Unimplemented func_id")) + } + } + Ok(RetVal::Converging(0)) + } + + fn enabled() -> bool { + true + } +} From 970ee8034874ceb10f52491958383ec56e6a793c Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Sat, 26 Feb 2022 08:39:56 +0000 Subject: [PATCH 534/695] Minor improvements to `bounded_vec` and `defensive`. (#10873) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix a few things in bounded_vec * add test for try_extend * Update frame/support/src/storage/bounded_vec.rs Co-authored-by: Bastian Köcher * some review comments * use swap * remove clone * use pop instead of truncate * remove warn * review comments * Update frame/support/src/storage/bounded_vec.rs Co-authored-by: Bastian Köcher * fix rustdoc * fix links * undo link Co-authored-by: Bastian Köcher --- frame/referenda/src/lib.rs | 2 +- frame/referenda/src/types.rs | 2 +- frame/support/src/storage/bounded_vec.rs | 211 +++++++++++++++-------- frame/support/src/traits.rs | 2 + frame/support/src/traits/misc.rs | 143 +++++---------- 5 files changed, 189 insertions(+), 171 deletions(-) diff --git a/frame/referenda/src/lib.rs b/frame/referenda/src/lib.rs index fb8e9aa6a6db..2d4d29b0bc13 100644 --- a/frame/referenda/src/lib.rs +++ b/frame/referenda/src/lib.rs @@ -866,7 +866,7 @@ impl Pallet { let new_pos = queue.binary_search_by_key(&ayes, |x| x.1).unwrap_or_else(|x| x); branch = if maybe_old_pos.is_none() && new_pos > 0 { // Just insert. - queue.force_insert_keep_right(new_pos, (index, ayes)); + let _ = queue.force_insert_keep_right(new_pos, (index, ayes)); ServiceBranch::RequeuedInsertion } else if let Some(old_pos) = maybe_old_pos { // We were in the queue - slide into the correct position. diff --git a/frame/referenda/src/types.rs b/frame/referenda/src/types.rs index 1b028fdfe9f7..367fa2a4ba45 100644 --- a/frame/referenda/src/types.rs +++ b/frame/referenda/src/types.rs @@ -86,7 +86,7 @@ impl> InsertSorted for BoundedVec { mut f: F, ) -> bool { let index = self.binary_search_by_key::(&f(&t), f).unwrap_or_else(|x| x); - self.force_insert_keep_right(index, t) + self.force_insert_keep_right(index, t).is_ok() } } diff --git a/frame/support/src/storage/bounded_vec.rs b/frame/support/src/storage/bounded_vec.rs index 86aa4d405cab..206a7e5d4ede 100644 --- a/frame/support/src/storage/bounded_vec.rs +++ b/frame/support/src/storage/bounded_vec.rs @@ -119,7 +119,17 @@ impl BoundedVec { self.0 } - /// Exactly the same semantics as [`Vec::remove`]. + /// Exactly the same semantics as [`slice::sort_by`]. + /// + /// This is safe since sorting cannot change the number of elements in the vector. + pub fn sort_by(&mut self, compare: F) + where + F: FnMut(&T, &T) -> sp_std::cmp::Ordering, + { + self.0.sort_by(compare) + } + + /// Exactly the same semantics as `Vec::remove`. /// /// # Panics /// @@ -128,7 +138,7 @@ impl BoundedVec { self.0.remove(index) } - /// Exactly the same semantics as [`Vec::swap_remove`]. + /// Exactly the same semantics as `slice::swap_remove`. /// /// # Panics /// @@ -137,12 +147,12 @@ impl BoundedVec { self.0.swap_remove(index) } - /// Exactly the same semantics as [`Vec::retain`]. + /// Exactly the same semantics as `Vec::retain`. pub fn retain bool>(&mut self, f: F) { self.0.retain(f) } - /// Exactly the same semantics as [`slice::get_mut`]. + /// Exactly the same semantics as `slice::get_mut`. pub fn get_mut>( &mut self, index: I, @@ -150,12 +160,16 @@ impl BoundedVec { self.0.get_mut(index) } - /// Exactly the same semantics as [`Vec::truncate`]. + /// Exactly the same semantics as `Vec::truncate`. + /// + /// This is safe because `truncate` can never increase the length of the internal vector. pub fn truncate(&mut self, s: usize) { self.0.truncate(s); } - /// Exactly the same semantics as [`Vec::pop`]. + /// Exactly the same semantics as `Vec::pop`. + /// + /// This is safe since popping can only shrink the inner vector. pub fn pop(&mut self) -> Option { self.0.pop() } @@ -191,54 +205,76 @@ impl> BoundedVec { S::get() as usize } - /// Forces the insertion of `s` into `self` retaining all items with index at least `index`. + /// Returns true of this collection is full. + pub fn is_full(&self) -> bool { + self.len() >= Self::bound() + } + + /// Forces the insertion of `element` into `self` retaining all items with index at least + /// `index`. /// /// If `index == 0` and `self.len() == Self::bound()`, then this is a no-op. /// /// If `Self::bound() < index` or `self.len() < index`, then this is also a no-op. /// - /// Returns `true` if the item was inserted. - pub fn force_insert_keep_right(&mut self, index: usize, element: T) -> bool { + /// Returns `Ok(maybe_removed)` if the item was inserted, where `maybe_removed` is + /// `Some(removed)` if an item was removed to make room for the new one. Returns `Err(())` if + /// `element` cannot be inserted. + pub fn force_insert_keep_right( + &mut self, + index: usize, + mut element: T, + ) -> Result, ()> { // Check against panics. if Self::bound() < index || self.len() < index { - return false - } - if self.len() < Self::bound() { + Err(()) + } else if self.len() < Self::bound() { // Cannot panic since self.len() >= index; self.0.insert(index, element); + Ok(None) } else { if index == 0 { - return false + return Err(()) } - self[0] = element; + sp_std::mem::swap(&mut self[0], &mut element); // `[0..index] cannot panic since self.len() >= index. // `rotate_left(1)` cannot panic because there is at least 1 element. self[0..index].rotate_left(1); + Ok(Some(element)) } - true } - /// Forces the insertion of `s` into `self` retaining all items with index at most `index`. + /// Forces the insertion of `element` into `self` retaining all items with index at most + /// `index`. /// /// If `index == Self::bound()` and `self.len() == Self::bound()`, then this is a no-op. /// /// If `Self::bound() < index` or `self.len() < index`, then this is also a no-op. /// - /// Returns `true` if the item was inserted. - pub fn force_insert_keep_left(&mut self, index: usize, element: T) -> bool { + /// Returns `Ok(maybe_removed)` if the item was inserted, where `maybe_removed` is + /// `Some(removed)` if an item was removed to make room for the new one. Returns `Err(())` if + /// `element` cannot be inserted. + pub fn force_insert_keep_left(&mut self, index: usize, element: T) -> Result, ()> { // Check against panics. if Self::bound() < index || self.len() < index || Self::bound() == 0 { - return false + return Err(()) } // Noop condition. if Self::bound() == index && self.len() <= Self::bound() { - return false + return Err(()) } - // Cannot panic since `Self.bound() > 0` - self.0.truncate(Self::bound() - 1); + let maybe_removed = if self.is_full() { + // defensive-only: since we are at capacity, this is a noop. + self.0.truncate(Self::bound()); + // if we truncate anything, it will be the last one. + self.0.pop() + } else { + None + }; + // Cannot panic since `self.len() >= index`; self.0.insert(index, element); - true + Ok(maybe_removed) } /// Move the position of an item from one location to another in the slice. @@ -311,6 +347,20 @@ impl> BoundedVec { self.0.resize(size, value); } + /// Exactly the same semantics as [`Vec::extend`], but returns an error and does nothing if the + /// length of the outcome is larger than the bound. + pub fn try_extend( + &mut self, + with: impl IntoIterator + ExactSizeIterator, + ) -> Result<(), ()> { + if with.len().saturating_add(self.len()) <= Self::bound() { + self.0.extend(with); + Ok(()) + } else { + Err(()) + } + } + /// Consumes self and mutates self via the given `mutate` function. /// /// If the outcome of mutation is within bounds, `Some(Self)` is returned. Else, `None` is @@ -522,7 +572,7 @@ where #[cfg(test)] pub mod test { use super::*; - use crate::{traits::ConstU32, Twox128}; + use crate::{bounded_vec, traits::ConstU32, Twox128}; use sp_io::TestExternalities; crate::generate_storage_alias! { Prefix, Foo => Value>> } @@ -534,7 +584,7 @@ pub mod test { #[test] fn slide_works() { - let mut b: BoundedVec> = vec![0, 1, 2, 3, 4, 5].try_into().unwrap(); + let mut b: BoundedVec> = bounded_vec![0, 1, 2, 3, 4, 5]; assert!(b.slide(1, 5)); assert_eq!(*b, vec![0, 2, 3, 4, 1, 5]); assert!(b.slide(4, 0)); @@ -551,7 +601,7 @@ pub mod test { assert!(!b.slide(7, 0)); assert_eq!(*b, vec![0, 2, 3, 4, 5, 1]); - let mut c: BoundedVec> = vec![0, 1, 2].try_into().unwrap(); + let mut c: BoundedVec> = bounded_vec![0, 1, 2]; assert!(!c.slide(1, 5)); assert_eq!(*c, vec![0, 1, 2]); assert!(!c.slide(4, 0)); @@ -564,7 +614,7 @@ pub mod test { #[test] fn slide_noops_work() { - let mut b: BoundedVec> = vec![0, 1, 2, 3, 4, 5].try_into().unwrap(); + let mut b: BoundedVec> = bounded_vec![0, 1, 2, 3, 4, 5]; assert!(!b.slide(3, 3)); assert_eq!(*b, vec![0, 1, 2, 3, 4, 5]); assert!(!b.slide(3, 4)); @@ -573,58 +623,59 @@ pub mod test { #[test] fn force_insert_keep_left_works() { - let mut b: BoundedVec> = vec![].try_into().unwrap(); - assert!(!b.force_insert_keep_left(1, 10)); + let mut b: BoundedVec> = bounded_vec![]; + assert_eq!(b.force_insert_keep_left(1, 10), Err(())); assert!(b.is_empty()); - assert!(b.force_insert_keep_left(0, 30)); - assert!(b.force_insert_keep_left(0, 10)); - assert!(b.force_insert_keep_left(1, 20)); - assert!(b.force_insert_keep_left(3, 40)); + assert_eq!(b.force_insert_keep_left(0, 30), Ok(None)); + assert_eq!(b.force_insert_keep_left(0, 10), Ok(None)); + assert_eq!(b.force_insert_keep_left(1, 20), Ok(None)); + assert_eq!(b.force_insert_keep_left(3, 40), Ok(None)); assert_eq!(*b, vec![10, 20, 30, 40]); // at capacity. - assert!(!b.force_insert_keep_left(4, 41)); + assert_eq!(b.force_insert_keep_left(4, 41), Err(())); assert_eq!(*b, vec![10, 20, 30, 40]); - assert!(b.force_insert_keep_left(3, 31)); + assert_eq!(b.force_insert_keep_left(3, 31), Ok(Some(40))); assert_eq!(*b, vec![10, 20, 30, 31]); - assert!(b.force_insert_keep_left(1, 11)); + assert_eq!(b.force_insert_keep_left(1, 11), Ok(Some(31))); assert_eq!(*b, vec![10, 11, 20, 30]); - assert!(b.force_insert_keep_left(0, 1)); + assert_eq!(b.force_insert_keep_left(0, 1), Ok(Some(30))); assert_eq!(*b, vec![1, 10, 11, 20]); - let mut z: BoundedVec> = vec![].try_into().unwrap(); + let mut z: BoundedVec> = bounded_vec![]; assert!(z.is_empty()); - assert!(!z.force_insert_keep_left(0, 10)); + assert_eq!(z.force_insert_keep_left(0, 10), Err(())); assert!(z.is_empty()); } #[test] fn force_insert_keep_right_works() { - let mut b: BoundedVec> = vec![].try_into().unwrap(); - assert!(!b.force_insert_keep_right(1, 10)); + let mut b: BoundedVec> = bounded_vec![]; + assert_eq!(b.force_insert_keep_right(1, 10), Err(())); assert!(b.is_empty()); - assert!(b.force_insert_keep_right(0, 30)); - assert!(b.force_insert_keep_right(0, 10)); - assert!(b.force_insert_keep_right(1, 20)); - assert!(b.force_insert_keep_right(3, 40)); + assert_eq!(b.force_insert_keep_right(0, 30), Ok(None)); + assert_eq!(b.force_insert_keep_right(0, 10), Ok(None)); + assert_eq!(b.force_insert_keep_right(1, 20), Ok(None)); + assert_eq!(b.force_insert_keep_right(3, 40), Ok(None)); assert_eq!(*b, vec![10, 20, 30, 40]); + // at capacity. - assert!(!b.force_insert_keep_right(0, 0)); + assert_eq!(b.force_insert_keep_right(0, 0), Err(())); assert_eq!(*b, vec![10, 20, 30, 40]); - assert!(b.force_insert_keep_right(1, 11)); + assert_eq!(b.force_insert_keep_right(1, 11), Ok(Some(10))); assert_eq!(*b, vec![11, 20, 30, 40]); - assert!(b.force_insert_keep_right(3, 31)); + assert_eq!(b.force_insert_keep_right(3, 31), Ok(Some(11))); assert_eq!(*b, vec![20, 30, 31, 40]); - assert!(b.force_insert_keep_right(4, 41)); + assert_eq!(b.force_insert_keep_right(4, 41), Ok(Some(20))); assert_eq!(*b, vec![30, 31, 40, 41]); - assert!(!b.force_insert_keep_right(5, 69)); + assert_eq!(b.force_insert_keep_right(5, 69), Err(())); assert_eq!(*b, vec![30, 31, 40, 41]); - let mut z: BoundedVec> = vec![].try_into().unwrap(); + let mut z: BoundedVec> = bounded_vec![]; assert!(z.is_empty()); - assert!(!z.force_insert_keep_right(0, 10)); + assert_eq!(z.force_insert_keep_right(0, 10), Err(())); assert!(z.is_empty()); } @@ -636,13 +687,13 @@ pub mod test { #[test] fn decode_len_works() { TestExternalities::default().execute_with(|| { - let bounded: BoundedVec> = vec![1, 2, 3].try_into().unwrap(); + let bounded: BoundedVec> = bounded_vec![1, 2, 3]; Foo::put(bounded); assert_eq!(Foo::decode_len().unwrap(), 3); }); TestExternalities::default().execute_with(|| { - let bounded: BoundedVec> = vec![1, 2, 3].try_into().unwrap(); + let bounded: BoundedVec> = bounded_vec![1, 2, 3]; FooMap::insert(1, bounded); assert_eq!(FooMap::decode_len(1).unwrap(), 3); assert!(FooMap::decode_len(0).is_none()); @@ -650,7 +701,7 @@ pub mod test { }); TestExternalities::default().execute_with(|| { - let bounded: BoundedVec> = vec![1, 2, 3].try_into().unwrap(); + let bounded: BoundedVec> = bounded_vec![1, 2, 3]; FooDoubleMap::insert(1, 1, bounded); assert_eq!(FooDoubleMap::decode_len(1, 1).unwrap(), 3); assert!(FooDoubleMap::decode_len(2, 1).is_none()); @@ -661,7 +712,7 @@ pub mod test { #[test] fn try_insert_works() { - let mut bounded: BoundedVec> = vec![1, 2, 3].try_into().unwrap(); + let mut bounded: BoundedVec> = bounded_vec![1, 2, 3]; bounded.try_insert(1, 0).unwrap(); assert_eq!(*bounded, vec![1, 0, 2, 3]); @@ -685,13 +736,13 @@ pub mod test { #[test] #[should_panic(expected = "insertion index (is 9) should be <= len (is 3)")] fn try_inert_panics_if_oob() { - let mut bounded: BoundedVec> = vec![1, 2, 3].try_into().unwrap(); + let mut bounded: BoundedVec> = bounded_vec![1, 2, 3]; bounded.try_insert(9, 0).unwrap(); } #[test] fn try_push_works() { - let mut bounded: BoundedVec> = vec![1, 2, 3].try_into().unwrap(); + let mut bounded: BoundedVec> = bounded_vec![1, 2, 3]; bounded.try_push(0).unwrap(); assert_eq!(*bounded, vec![1, 2, 3, 0]); @@ -700,7 +751,7 @@ pub mod test { #[test] fn deref_coercion_works() { - let bounded: BoundedVec> = vec![1, 2, 3].try_into().unwrap(); + let bounded: BoundedVec> = bounded_vec![1, 2, 3]; // these methods come from deref-ed vec. assert_eq!(bounded.len(), 3); assert!(bounded.iter().next().is_some()); @@ -709,7 +760,7 @@ pub mod test { #[test] fn try_mutate_works() { - let bounded: BoundedVec> = vec![1, 2, 3, 4, 5, 6].try_into().unwrap(); + let bounded: BoundedVec> = bounded_vec![1, 2, 3, 4, 5, 6]; let bounded = bounded.try_mutate(|v| v.push(7)).unwrap(); assert_eq!(bounded.len(), 7); assert!(bounded.try_mutate(|v| v.push(8)).is_none()); @@ -717,13 +768,13 @@ pub mod test { #[test] fn slice_indexing_works() { - let bounded: BoundedVec> = vec![1, 2, 3, 4, 5, 6].try_into().unwrap(); + let bounded: BoundedVec> = bounded_vec![1, 2, 3, 4, 5, 6]; assert_eq!(&bounded[0..=2], &[1, 2, 3]); } #[test] fn vec_eq_works() { - let bounded: BoundedVec> = vec![1, 2, 3, 4, 5, 6].try_into().unwrap(); + let bounded: BoundedVec> = bounded_vec![1, 2, 3, 4, 5, 6]; assert_eq!(bounded, vec![1, 2, 3, 4, 5, 6]); } @@ -738,7 +789,7 @@ pub mod test { #[test] fn can_be_collected() { - let b1: BoundedVec> = vec![1, 2, 3, 4].try_into().unwrap(); + let b1: BoundedVec> = bounded_vec![1, 2, 3, 4]; let b2: BoundedVec> = b1.iter().map(|x| x + 1).try_collect().unwrap(); assert_eq!(b2, vec![2, 3, 4, 5]); @@ -777,8 +828,8 @@ pub mod test { #[test] fn eq_works() { // of same type - let b1: BoundedVec> = vec![1, 2, 3].try_into().unwrap(); - let b2: BoundedVec> = vec![1, 2, 3].try_into().unwrap(); + let b1: BoundedVec> = bounded_vec![1, 2, 3]; + let b2: BoundedVec> = bounded_vec![1, 2, 3]; assert_eq!(b1, b2); // of different type, but same value and bound. @@ -786,19 +837,41 @@ pub mod test { B1: u32 = 7; B2: u32 = 7; } - let b1: BoundedVec = vec![1, 2, 3].try_into().unwrap(); - let b2: BoundedVec = vec![1, 2, 3].try_into().unwrap(); + let b1: BoundedVec = bounded_vec![1, 2, 3]; + let b2: BoundedVec = bounded_vec![1, 2, 3]; assert_eq!(b1, b2); } #[test] fn ord_works() { use std::cmp::Ordering; - let b1: BoundedVec> = vec![1, 2, 3].try_into().unwrap(); - let b2: BoundedVec> = vec![1, 3, 2].try_into().unwrap(); + let b1: BoundedVec> = bounded_vec![1, 2, 3]; + let b2: BoundedVec> = bounded_vec![1, 3, 2]; // ordering for vec is lexicographic. assert_eq!(b1.cmp(&b2), Ordering::Less); assert_eq!(b1.cmp(&b2), b1.into_inner().cmp(&b2.into_inner())); } + + #[test] + fn try_extend_works() { + let mut b: BoundedVec> = bounded_vec![1, 2, 3]; + + assert!(b.try_extend(vec![4].into_iter()).is_ok()); + assert_eq!(*b, vec![1, 2, 3, 4]); + + assert!(b.try_extend(vec![5].into_iter()).is_ok()); + assert_eq!(*b, vec![1, 2, 3, 4, 5]); + + assert!(b.try_extend(vec![6].into_iter()).is_err()); + assert_eq!(*b, vec![1, 2, 3, 4, 5]); + + let mut b: BoundedVec> = bounded_vec![1, 2, 3]; + assert!(b.try_extend(vec![4, 5].into_iter()).is_ok()); + assert_eq!(*b, vec![1, 2, 3, 4, 5]); + + let mut b: BoundedVec> = bounded_vec![1, 2, 3]; + assert!(b.try_extend(vec![4, 5, 6].into_iter()).is_err()); + assert_eq!(*b, vec![1, 2, 3]); + } } diff --git a/frame/support/src/traits.rs b/frame/support/src/traits.rs index 5ee2952e445b..88891c83276b 100644 --- a/frame/support/src/traits.rs +++ b/frame/support/src/traits.rs @@ -58,6 +58,8 @@ pub use misc::{ PreimageRecipient, PrivilegeCmp, SameOrOther, Time, TryCollect, TryDrop, UnixTime, WrapperKeepOpaque, WrapperOpaque, }; +#[doc(hidden)] +pub use misc::{DEFENSIVE_OP_INTERNAL_ERROR, DEFENSIVE_OP_PUBLIC_ERROR}; mod stored_map; pub use stored_map::{StorageMapShim, StoredMap}; diff --git a/frame/support/src/traits/misc.rs b/frame/support/src/traits/misc.rs index eaada3ea2c36..d2fd438d3a80 100644 --- a/frame/support/src/traits/misc.rs +++ b/frame/support/src/traits/misc.rs @@ -24,8 +24,34 @@ use sp_arithmetic::traits::{CheckedAdd, CheckedMul, CheckedSub, Saturating}; use sp_runtime::{traits::Block as BlockT, DispatchError}; use sp_std::{cmp::Ordering, prelude::*}; -const DEFENSIVE_OP_PUBLIC_ERROR: &'static str = "a defensive failure has been triggered; please report the block number at https://github.com/paritytech/substrate/issues"; -const DEFENSIVE_OP_INTERNAL_ERROR: &'static str = "Defensive failure has been triggered!"; +#[doc(hidden)] +pub const DEFENSIVE_OP_PUBLIC_ERROR: &'static str = "a defensive failure has been triggered; please report the block number at https://github.com/paritytech/substrate/issues"; +#[doc(hidden)] +pub const DEFENSIVE_OP_INTERNAL_ERROR: &'static str = "Defensive failure has been triggered!"; + +/// Generic function to mark an execution path as ONLY defensive. +/// +/// Similar to mark a match arm or `if/else` branch as `unreachable!`. +#[macro_export] +macro_rules! defensive { + () => { + frame_support::log::error!( + target: "runtime", + "{}", + $crate::traits::misc::DEFENSIVE_OP_PUBLIC_ERROR + ); + debug_assert!(false, "{}", $crate::traits::misc::DEFENSIVE_OP_INTERNAL_ERROR); + }; + ($error:tt) => { + frame_support::log::error!( + target: "runtime", + "{}: {:?}", + $crate::traits::misc::DEFENSIVE_OP_PUBLIC_ERROR, + $error + ); + debug_assert!(false, "{}: {:?}", $crate::traits::misc::DEFENSIVE_OP_INTERNAL_ERROR, $error); + } +} /// Prelude module for all defensive traits to be imported at once. pub mod defensive_prelude { @@ -116,12 +142,7 @@ impl Defensive for Option { match self { Some(inner) => inner, None => { - debug_assert!(false, "{}", DEFENSIVE_OP_INTERNAL_ERROR); - frame_support::log::error!( - target: "runtime", - "{}", - DEFENSIVE_OP_PUBLIC_ERROR - ); + defensive!(); or }, } @@ -131,12 +152,7 @@ impl Defensive for Option { match self { Some(inner) => inner, None => { - debug_assert!(false, "{}", DEFENSIVE_OP_INTERNAL_ERROR); - frame_support::log::error!( - target: "runtime", - "{}", - DEFENSIVE_OP_PUBLIC_ERROR - ); + defensive!(); f() }, } @@ -149,12 +165,7 @@ impl Defensive for Option { match self { Some(inner) => inner, None => { - debug_assert!(false, "{}", DEFENSIVE_OP_INTERNAL_ERROR); - frame_support::log::error!( - target: "runtime", - "{}", - DEFENSIVE_OP_PUBLIC_ERROR - ); + defensive!(); Default::default() }, } @@ -164,12 +175,7 @@ impl Defensive for Option { match self { Some(inner) => Some(inner), None => { - debug_assert!(false, "{}", DEFENSIVE_OP_INTERNAL_ERROR); - frame_support::log::error!( - target: "runtime", - "{}", - DEFENSIVE_OP_PUBLIC_ERROR - ); + defensive!(); None }, } @@ -181,13 +187,7 @@ impl Defensive for Result { match self { Ok(inner) => inner, Err(e) => { - debug_assert!(false, "{}: {:?}", DEFENSIVE_OP_INTERNAL_ERROR, e); - frame_support::log::error!( - target: "runtime", - "{}: {:?}", - DEFENSIVE_OP_PUBLIC_ERROR, - e - ); + defensive!(e); or }, } @@ -197,13 +197,7 @@ impl Defensive for Result { match self { Ok(inner) => inner, Err(e) => { - debug_assert!(false, "{}: {:?}", DEFENSIVE_OP_INTERNAL_ERROR, e); - frame_support::log::error!( - target: "runtime", - "{}: {:?}", - DEFENSIVE_OP_PUBLIC_ERROR, - e - ); + defensive!(e); f() }, } @@ -216,13 +210,7 @@ impl Defensive for Result { match self { Ok(inner) => inner, Err(e) => { - debug_assert!(false, "{}: {:?}", DEFENSIVE_OP_INTERNAL_ERROR, e); - frame_support::log::error!( - target: "runtime", - "{}: {:?}", - DEFENSIVE_OP_PUBLIC_ERROR, - e - ); + defensive!(e); Default::default() }, } @@ -232,13 +220,7 @@ impl Defensive for Result { match self { Ok(inner) => Ok(inner), Err(e) => { - debug_assert!(false, "{}: {:?}", DEFENSIVE_OP_INTERNAL_ERROR, e); - frame_support::log::error!( - target: "runtime", - "{}: {:?}", - DEFENSIVE_OP_PUBLIC_ERROR, - e - ); + defensive!(e); Err(e) }, } @@ -248,13 +230,7 @@ impl Defensive for Result { impl DefensiveResult for Result { fn defensive_map_err F>(self, o: O) -> Result { self.map_err(|e| { - debug_assert!(false, "{}: {:?}", DEFENSIVE_OP_INTERNAL_ERROR, e); - frame_support::log::error!( - target: "runtime", - "{}: {:?}", - DEFENSIVE_OP_PUBLIC_ERROR, - e - ); + defensive!(e); o(e) }) } @@ -262,13 +238,7 @@ impl DefensiveResult for Result { fn defensive_map_or_else U, F: FnOnce(T) -> U>(self, default: D, f: F) -> U { self.map_or_else( |e| { - debug_assert!(false, "{}: {:?}", DEFENSIVE_OP_INTERNAL_ERROR, e); - frame_support::log::error!( - target: "runtime", - "{}: {:?}", - DEFENSIVE_OP_PUBLIC_ERROR, - e - ); + defensive!(e); default(e) }, f, @@ -279,13 +249,7 @@ impl DefensiveResult for Result { match self { Ok(inner) => Some(inner), Err(e) => { - debug_assert!(false, "{}: {:?}", DEFENSIVE_OP_INTERNAL_ERROR, e); - frame_support::log::error!( - target: "runtime", - "{}: {:?}", - DEFENSIVE_OP_PUBLIC_ERROR, - e - ); + defensive!(e); None }, } @@ -295,13 +259,7 @@ impl DefensiveResult for Result { match self { Ok(inner) => Ok(f(inner)), Err(e) => { - debug_assert!(false, "{}: {:?}", DEFENSIVE_OP_INTERNAL_ERROR, e); - frame_support::log::error!( - target: "runtime", - "{}: {:?}", - DEFENSIVE_OP_PUBLIC_ERROR, - e - ); + defensive!(e); Err(e) }, } @@ -312,12 +270,7 @@ impl DefensiveOption for Option { fn defensive_map_or_else U, F: FnOnce(T) -> U>(self, default: D, f: F) -> U { self.map_or_else( || { - debug_assert!(false, "{}", DEFENSIVE_OP_INTERNAL_ERROR); - frame_support::log::error!( - target: "runtime", - "{}", - DEFENSIVE_OP_PUBLIC_ERROR, - ); + defensive!(); default() }, f, @@ -326,12 +279,7 @@ impl DefensiveOption for Option { fn defensive_ok_or_else E>(self, err: F) -> Result { self.ok_or_else(|| { - debug_assert!(false, "{}", DEFENSIVE_OP_INTERNAL_ERROR); - frame_support::log::error!( - target: "runtime", - "{}", - DEFENSIVE_OP_PUBLIC_ERROR, - ); + defensive!(); err() }) } @@ -340,12 +288,7 @@ impl DefensiveOption for Option { match self { Some(inner) => Some(f(inner)), None => { - debug_assert!(false, "{}", DEFENSIVE_OP_INTERNAL_ERROR); - frame_support::log::error!( - target: "runtime", - "{}", - DEFENSIVE_OP_PUBLIC_ERROR, - ); + defensive!(); None }, } From bfc6fb4a95adccf96dadbe5e5e6bb8605d5a2c01 Mon Sep 17 00:00:00 2001 From: Davide Galassi Date: Sat, 26 Feb 2022 22:00:00 +0100 Subject: [PATCH 535/695] Replace libsecp256k1 with secp256k1 (#10798) * Replace libsecp256k1 with secp256k1 * Wipe ecdsa secret key from memory on drop * Some comments for a known issue * Safer core crypto primitives `from_slice` constructor Previous version panics if slice lenght is not the expected one. * Unit test fix * Enable use of global secp256k1 context * Better comments for ecdsa `Pair` drop * Replace `libsecp256k1` with `seco256k1` in `beefy-mmr` Used to convert ecdsa public key to ETH address * Replace `libsecp256k1` with `secp256k1` in FRAME `contracts`benchmarks * Temporary rollback of `beefy-mmr` to libsecp256k1 Check for detected build issues * Cargo fmt * Rollback of FRAME `contracts` benchmarks to `libsecp256k1` * Rollback for unrelated changes * Typo fix * Add comments for deprecated `ecdsa_verify` and `secp256k1_ecdsa_recover` --- Cargo.lock | 22 ++- Cargo.toml | 1 + client/authority-discovery/src/tests.rs | 2 +- client/executor/Cargo.toml | 1 - primitives/core/Cargo.toml | 5 +- primitives/core/src/ecdsa.rs | 220 +++++++++++------------- primitives/core/src/ed25519.rs | 7 +- primitives/core/src/sr25519.rs | 7 +- primitives/io/Cargo.toml | 2 + primitives/io/src/lib.rs | 69 ++++---- 10 files changed, 184 insertions(+), 152 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 826ed90d4553..66910db9d31b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8382,7 +8382,6 @@ version = "0.10.0-dev" dependencies = [ "hex-literal", "lazy_static", - "libsecp256k1", "lru 0.6.6", "parity-scale-codec", "parking_lot 0.12.0", @@ -9170,6 +9169,25 @@ dependencies = [ "zeroize", ] +[[package]] +name = "secp256k1" +version = "0.21.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab7883017d5b21f011ef8040ea9c6c7ac90834c0df26a69e4c0b06276151f125" +dependencies = [ + "rand 0.6.5", + "secp256k1-sys", +] + +[[package]] +name = "secp256k1-sys" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "957da2573cde917463ece3570eab4a0b3f19de6f1646cde62e6fd3868f566036" +dependencies = [ + "cc", +] + [[package]] name = "secrecy" version = "0.8.0" @@ -9817,6 +9835,7 @@ dependencies = [ "regex", "scale-info", "schnorrkel", + "secp256k1", "secrecy", "serde", "serde_json", @@ -9927,6 +9946,7 @@ dependencies = [ "log 0.4.14", "parity-scale-codec", "parking_lot 0.12.0", + "secp256k1", "sp-core", "sp-externalities", "sp-keystore", diff --git a/Cargo.toml b/Cargo.toml index d919fc480563..a12910c52c01 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -265,6 +265,7 @@ percent-encoding = { opt-level = 3 } primitive-types = { opt-level = 3 } ring = { opt-level = 3 } rustls = { opt-level = 3 } +secp256k1 = { opt-level = 3 } sha2 = { opt-level = 3 } sha3 = { opt-level = 3 } smallvec = { opt-level = 3 } diff --git a/client/authority-discovery/src/tests.rs b/client/authority-discovery/src/tests.rs index 3b632d217400..e9f94b6a186d 100644 --- a/client/authority-discovery/src/tests.rs +++ b/client/authority-discovery/src/tests.rs @@ -105,7 +105,7 @@ fn cryptos_are_compatible() { let sp_core_signature = sp_core_secret.sign(message); // no error expected... assert!(sp_core::ed25519::Pair::verify( - &sp_core::ed25519::Signature::from_slice(&libp2p_signature), + &sp_core::ed25519::Signature::from_slice(&libp2p_signature).unwrap(), message, &sp_core_public )); diff --git a/client/executor/Cargo.toml b/client/executor/Cargo.toml index 6cd1938822d0..5c62de767100 100644 --- a/client/executor/Cargo.toml +++ b/client/executor/Cargo.toml @@ -31,7 +31,6 @@ sc-executor-common = { version = "0.10.0-dev", path = "common" } sc-executor-wasmi = { version = "0.10.0-dev", path = "wasmi" } sc-executor-wasmtime = { version = "0.10.0-dev", path = "wasmtime", optional = true } parking_lot = "0.12.0" -libsecp256k1 = "0.7" sp-core-hashing-proc-macro = { version = "4.0.0-dev", path = "../../primitives/core/hashing/proc-macro" } lru = "0.6.6" tracing = "0.1.29" diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index ab0f38ec109c..bd1930bf51b6 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -54,8 +54,9 @@ schnorrkel = { version = "0.9.1", features = [ "u64_backend", ], default-features = false, optional = true } hex = { version = "0.4", default-features = false, optional = true } -libsecp256k1 = { version = "0.7", default-features = false, features = ["hmac", "static-context"], optional = true } +libsecp256k1 = { version = "0.7", default-features = false, features = ["static-context"], optional = true } merlin = { version = "2.0", default-features = false, optional = true } +secp256k1 = { version = "0.21.2", default-features = false, features = ["recovery", "global-context"], optional = true } ss58-registry = { version = "1.11.0", default-features = false } sp-core-hashing = { version = "4.0.0", path = "./hashing", default-features = false, optional = true } sp-runtime-interface = { version = "5.0.0", default-features = false, path = "../runtime-interface" } @@ -106,6 +107,7 @@ std = [ "schnorrkel/std", "regex", "num-traits/std", + "secp256k1/std", "sp-core-hashing/std", "sp-debug-derive/std", "sp-externalities", @@ -129,6 +131,7 @@ full_crypto = [ "schnorrkel", "hex", "libsecp256k1", + "secp256k1", "sp-core-hashing", "sp-runtime-interface/disable_target_static_assertions", "merlin", diff --git a/primitives/core/src/ecdsa.rs b/primitives/core/src/ecdsa.rs index 0735c3f40cec..9389a277736d 100644 --- a/primitives/core/src/ecdsa.rs +++ b/primitives/core/src/ecdsa.rs @@ -15,9 +15,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// tag::description[] -//! Simple ECDSA API. -// end::description[] +//! Simple ECDSA secp256k1 API. use codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; @@ -37,9 +35,12 @@ use crate::{ #[cfg(feature = "std")] use bip39::{Language, Mnemonic, MnemonicType}; #[cfg(feature = "full_crypto")] -use core::convert::{TryFrom, TryInto}; +use core::convert::TryFrom; #[cfg(feature = "full_crypto")] -use libsecp256k1::{PublicKey, SecretKey}; +use secp256k1::{ + ecdsa::{RecoverableSignature, RecoveryId}, + Message, PublicKey, SecretKey, SECP256K1, +}; #[cfg(feature = "std")] use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; #[cfg(feature = "full_crypto")] @@ -57,7 +58,17 @@ type Seed = [u8; 32]; /// The ECDSA compressed public key. #[cfg_attr(feature = "full_crypto", derive(Hash))] #[derive( - Clone, Encode, Decode, PassByInner, MaxEncodedLen, TypeInfo, Eq, PartialEq, PartialOrd, Ord, + Clone, + Copy, + Encode, + Decode, + PassByInner, + MaxEncodedLen, + TypeInfo, + Eq, + PartialEq, + PartialOrd, + Ord, )] pub struct Public(pub [u8; 33]); @@ -75,10 +86,16 @@ impl Public { /// This will convert the full public key into the compressed format. #[cfg(feature = "std")] pub fn from_full(full: &[u8]) -> Result { - libsecp256k1::PublicKey::parse_slice(full, None) - .map(|k| k.serialize_compressed()) - .map(Self) - .map_err(|_| ()) + let pubkey = if full.len() == 64 { + // Tag it as uncompressed public key. + let mut tagged_full = [0u8; 65]; + tagged_full[0] = 0x04; + tagged_full[1..].copy_from_slice(full); + secp256k1::PublicKey::from_slice(&tagged_full) + } else { + secp256k1::PublicKey::from_slice(full) + }; + pubkey.map(|k| Self(k.serialize())).map_err(|_| ()) } } @@ -296,55 +313,46 @@ impl Signature { /// /// NOTE: No checking goes on to ensure this is a real signature. Only use it if /// you are certain that the array actually is a signature. GIGO! - pub fn from_slice(data: &[u8]) -> Self { + pub fn from_slice(data: &[u8]) -> Option { + if data.len() != 65 { + return None + } let mut r = [0u8; 65]; r.copy_from_slice(data); - Signature(r) + Some(Signature(r)) } /// Recover the public key from this signature and a message. #[cfg(feature = "full_crypto")] pub fn recover>(&self, message: M) -> Option { - let message = libsecp256k1::Message::parse(&blake2_256(message.as_ref())); - let sig: (_, _) = self.try_into().ok()?; - libsecp256k1::recover(&message, &sig.0, &sig.1) - .ok() - .map(|recovered| Public(recovered.serialize_compressed())) + self.recover_prehashed(&blake2_256(message.as_ref())) } /// Recover the public key from this signature and a pre-hashed message. #[cfg(feature = "full_crypto")] pub fn recover_prehashed(&self, message: &[u8; 32]) -> Option { - let message = libsecp256k1::Message::parse(message); - - let sig: (_, _) = self.try_into().ok()?; - - libsecp256k1::recover(&message, &sig.0, &sig.1) + let rid = RecoveryId::from_i32(self.0[64] as i32).ok()?; + let sig = RecoverableSignature::from_compact(&self.0[..64], rid).ok()?; + let message = Message::from_slice(message).expect("Message is 32 bytes; qed"); + SECP256K1 + .recover_ecdsa(&message, &sig) .ok() - .map(|key| Public(key.serialize_compressed())) + .map(|pubkey| Public(pubkey.serialize())) } } #[cfg(feature = "full_crypto")] -impl From<(libsecp256k1::Signature, libsecp256k1::RecoveryId)> for Signature { - fn from(x: (libsecp256k1::Signature, libsecp256k1::RecoveryId)) -> Signature { +impl From for Signature { + fn from(recsig: RecoverableSignature) -> Signature { let mut r = Self::default(); - r.0[0..64].copy_from_slice(&x.0.serialize()[..]); - r.0[64] = x.1.serialize(); + let (recid, sig) = recsig.serialize_compact(); + r.0[..64].copy_from_slice(&sig); + // This is safe due to the limited range of possible valid ids. + r.0[64] = recid.to_i32() as u8; r } } -#[cfg(feature = "full_crypto")] -impl<'a> TryFrom<&'a Signature> for (libsecp256k1::Signature, libsecp256k1::RecoveryId) { - type Error = (); - fn try_from( - x: &'a Signature, - ) -> Result<(libsecp256k1::Signature, libsecp256k1::RecoveryId), Self::Error> { - parse_signature_standard(&x.0).map_err(|_| ()) - } -} - /// Derive a single hard junction. #[cfg(feature = "full_crypto")] fn derive_hard_junction(secret_seed: &Seed, cc: &[u8; 32]) -> Seed { @@ -362,7 +370,7 @@ pub enum DeriveError { #[cfg(feature = "full_crypto")] #[derive(Clone)] pub struct Pair { - public: PublicKey, + public: Public, secret: SecretKey, } @@ -416,8 +424,9 @@ impl TraitPair for Pair { /// You should never need to use this; generate(), generate_with_phrase fn from_seed_slice(seed_slice: &[u8]) -> Result { let secret = - SecretKey::parse_slice(seed_slice).map_err(|_| SecretStringError::InvalidSeedLength)?; - let public = PublicKey::from_secret_key(&secret); + SecretKey::from_slice(seed_slice).map_err(|_| SecretStringError::InvalidSeedLength)?; + let public = PublicKey::from_secret_key(SECP256K1, &secret); + let public = Public(public.serialize()); Ok(Pair { public, secret }) } @@ -427,7 +436,7 @@ impl TraitPair for Pair { path: Iter, _seed: Option, ) -> Result<(Pair, Option), DeriveError> { - let mut acc = self.secret.serialize(); + let mut acc = self.seed(); for j in path { match j { DeriveJunction::Soft(_cc) => return Err(DeriveError::SoftKeyInPath), @@ -439,25 +448,19 @@ impl TraitPair for Pair { /// Get the public key. fn public(&self) -> Public { - Public(self.public.serialize_compressed()) + self.public } /// Sign a message. fn sign(&self, message: &[u8]) -> Signature { - let message = libsecp256k1::Message::parse(&blake2_256(message)); - libsecp256k1::sign(&message, &self.secret).into() + self.sign_prehashed(&blake2_256(message)) } /// Verify a signature on a message. Returns true if the signature is good. fn verify>(sig: &Self::Signature, message: M, pubkey: &Self::Public) -> bool { - let message = libsecp256k1::Message::parse(&blake2_256(message.as_ref())); - let sig: (_, _) = match sig.try_into() { - Ok(x) => x, - _ => return false, - }; - match libsecp256k1::recover(&message, &sig.0, &sig.1) { - Ok(actual) => pubkey.0[..] == actual.serialize_compressed()[..], - _ => false, + match sig.recover(message) { + Some(actual) => actual == *pubkey, + None => false, } } @@ -466,17 +469,9 @@ impl TraitPair for Pair { /// This doesn't use the type system to ensure that `sig` and `pubkey` are the correct /// size. Use it only if you're coming from byte buffers and need the speed. fn verify_weak, M: AsRef<[u8]>>(sig: &[u8], message: M, pubkey: P) -> bool { - let message = libsecp256k1::Message::parse(&blake2_256(message.as_ref())); - if sig.len() != 65 { - return false - } - let (sig, ri) = match parse_signature_standard(&sig) { - Ok(sigri) => sigri, - _ => return false, - }; - match libsecp256k1::recover(&message, &sig, &ri) { - Ok(actual) => pubkey.as_ref() == &actual.serialize()[1..], - _ => false, + match Signature::from_slice(sig).and_then(|sig| sig.recover(message)) { + Some(actual) => actual.as_ref() == pubkey.as_ref(), + None => false, } } @@ -490,7 +485,7 @@ impl TraitPair for Pair { impl Pair { /// Get the seed for this key. pub fn seed(&self) -> Seed { - self.secret.serialize() + self.secret.serialize_secret() } /// Exactly as `from_string` except that if no matches are found then, the the first 32 @@ -507,57 +502,57 @@ impl Pair { /// Sign a pre-hashed message pub fn sign_prehashed(&self, message: &[u8; 32]) -> Signature { - let message = libsecp256k1::Message::parse(message); - libsecp256k1::sign(&message, &self.secret).into() + let message = Message::from_slice(message).expect("Message is 32 bytes; qed"); + SECP256K1.sign_ecdsa_recoverable(&message, &self.secret).into() } /// Verify a signature on a pre-hashed message. Return `true` if the signature is valid /// and thus matches the given `public` key. pub fn verify_prehashed(sig: &Signature, message: &[u8; 32], public: &Public) -> bool { - let message = libsecp256k1::Message::parse(message); - - let sig: (_, _) = match sig.try_into() { - Ok(x) => x, - _ => return false, - }; - - match libsecp256k1::recover(&message, &sig.0, &sig.1) { - Ok(actual) => public.0[..] == actual.serialize_compressed()[..], - _ => false, + match sig.recover_prehashed(message) { + Some(actual) => actual == *public, + None => false, } } /// Verify a signature on a message. Returns true if the signature is good. - /// Parses Signature using parse_overflowing_slice + /// Parses Signature using parse_overflowing_slice. + #[deprecated(note = "please use `verify` instead")] pub fn verify_deprecated>(sig: &Signature, message: M, pubkey: &Public) -> bool { let message = libsecp256k1::Message::parse(&blake2_256(message.as_ref())); - let (sig, ri) = match parse_signature_overflowing(&sig.0) { - Ok(sigri) => sigri, + + let parse_signature_overflowing = |x: [u8; 65]| { + let sig = libsecp256k1::Signature::parse_overflowing_slice(&x[..64]).ok()?; + let rid = libsecp256k1::RecoveryId::parse(x[64]).ok()?; + Some((sig, rid)) + }; + + let (sig, rid) = match parse_signature_overflowing(sig.0) { + Some(sigri) => sigri, _ => return false, }; - match libsecp256k1::recover(&message, &sig, &ri) { - Ok(actual) => pubkey.0[..] == actual.serialize_compressed()[..], + match libsecp256k1::recover(&message, &sig, &rid) { + Ok(actual) => pubkey.0 == actual.serialize_compressed(), _ => false, } } } +// The `secp256k1` backend doesn't implement cleanup for their private keys. +// Currently we should take care of wiping the secret from memory. +// NOTE: this solution is not effective when `Pair` is moved around memory. +// The very same problem affects other cryptographic backends that are just using +// `zeroize`for their secrets. #[cfg(feature = "full_crypto")] -fn parse_signature_standard( - x: &[u8], -) -> Result<(libsecp256k1::Signature, libsecp256k1::RecoveryId), libsecp256k1::Error> { - let sig = libsecp256k1::Signature::parse_standard_slice(&x[..64])?; - let ri = libsecp256k1::RecoveryId::parse(x[64])?; - Ok((sig, ri)) -} - -#[cfg(feature = "full_crypto")] -fn parse_signature_overflowing( - x: &[u8], -) -> Result<(libsecp256k1::Signature, libsecp256k1::RecoveryId), libsecp256k1::Error> { - let sig = libsecp256k1::Signature::parse_overflowing_slice(&x[..64])?; - let ri = libsecp256k1::RecoveryId::parse(x[64])?; - Ok((sig, ri)) +impl Drop for Pair { + fn drop(&mut self) { + let ptr = self.secret.as_mut_ptr(); + for off in 0..self.secret.len() { + unsafe { + core::ptr::write_volatile(ptr.add(off), 0); + } + } + } } impl CryptoType for Public { @@ -578,12 +573,9 @@ impl CryptoType for Pair { #[cfg(test)] mod test { use super::*; - use crate::{ - crypto::{ - set_default_ss58_version, PublicError, Ss58AddressFormat, Ss58AddressFormatRegistry, - DEV_PHRASE, - }, - keccak_256, + use crate::crypto::{ + set_default_ss58_version, PublicError, Ss58AddressFormat, Ss58AddressFormatRegistry, + DEV_PHRASE, }; use hex_literal::hex; use serde_json; @@ -802,22 +794,20 @@ mod test { // `msg` shouldn't be mangled let msg = [0u8; 32]; let sig1 = pair.sign_prehashed(&msg); - let sig2: Signature = - libsecp256k1::sign(&libsecp256k1::Message::parse(&msg), &pair.secret).into(); - + let sig2: Signature = { + let message = Message::from_slice(&msg).unwrap(); + SECP256K1.sign_ecdsa_recoverable(&message, &pair.secret).into() + }; assert_eq!(sig1, sig2); // signature is actually different let sig2 = pair.sign(&msg); - assert_ne!(sig1, sig2); // using pre-hashed `msg` works - let msg = keccak_256(b"this should be hashed"); - let sig1 = pair.sign_prehashed(&msg); - let sig2: Signature = - libsecp256k1::sign(&libsecp256k1::Message::parse(&msg), &pair.secret).into(); - + let msg = b"this should be hashed"; + let sig1 = pair.sign_prehashed(&blake2_256(msg)); + let sig2 = pair.sign(msg); assert_eq!(sig1, sig2); } @@ -826,12 +816,12 @@ mod test { let (pair, _, _) = Pair::generate_with_phrase(Some("password")); // `msg` and `sig` match - let msg = keccak_256(b"this should be hashed"); + let msg = blake2_256(b"this should be hashed"); let sig = pair.sign_prehashed(&msg); assert!(Pair::verify_prehashed(&sig, &msg, &pair.public())); // `msg` and `sig` don't match - let msg = keccak_256(b"this is a different message"); + let msg = blake2_256(b"this is a different message"); assert!(!Pair::verify_prehashed(&sig, &msg, &pair.public())); } @@ -840,7 +830,7 @@ mod test { let (pair, _, _) = Pair::generate_with_phrase(Some("password")); // recovered key matches signing key - let msg = keccak_256(b"this should be hashed"); + let msg = blake2_256(b"this should be hashed"); let sig = pair.sign_prehashed(&msg); let key = sig.recover_prehashed(&msg).unwrap(); assert_eq!(pair.public(), key); @@ -849,7 +839,7 @@ mod test { assert!(Pair::verify_prehashed(&sig, &msg, &key)); // recovered key and signing key don't match - let msg = keccak_256(b"this is a different message"); + let msg = blake2_256(b"this is a different message"); let key = sig.recover_prehashed(&msg).unwrap(); assert_ne!(pair.public(), key); } diff --git a/primitives/core/src/ed25519.rs b/primitives/core/src/ed25519.rs index 54f9ed7fc0e3..555c23c6b60c 100644 --- a/primitives/core/src/ed25519.rs +++ b/primitives/core/src/ed25519.rs @@ -321,10 +321,13 @@ impl Signature { /// /// NOTE: No checking goes on to ensure this is a real signature. Only use it if /// you are certain that the array actually is a signature. GIGO! - pub fn from_slice(data: &[u8]) -> Self { + pub fn from_slice(data: &[u8]) -> Option { + if data.len() != 64 { + return None + } let mut r = [0u8; 64]; r.copy_from_slice(data); - Signature(r) + Some(Signature(r)) } /// A new instance from an H512. diff --git a/primitives/core/src/sr25519.rs b/primitives/core/src/sr25519.rs index 5e18e02c0ffd..2f298fa2a266 100644 --- a/primitives/core/src/sr25519.rs +++ b/primitives/core/src/sr25519.rs @@ -341,10 +341,13 @@ impl Signature { /// /// NOTE: No checking goes on to ensure this is a real signature. Only use it if /// you are certain that the array actually is a signature. GIGO! - pub fn from_slice(data: &[u8]) -> Self { + pub fn from_slice(data: &[u8]) -> Option { + if data.len() != 64 { + return None + } let mut r = [0u8; 64]; r.copy_from_slice(data); - Signature(r) + Some(Signature(r)) } /// A new instance from an H512. diff --git a/primitives/io/Cargo.toml b/primitives/io/Cargo.toml index b28db8c1ff3d..6cc6c47ddc96 100644 --- a/primitives/io/Cargo.toml +++ b/primitives/io/Cargo.toml @@ -30,6 +30,7 @@ sp-tracing = { version = "4.0.0", default-features = false, path = "../tracing" log = { version = "0.4.8", optional = true } futures = { version = "0.3.1", features = ["thread-pool"], optional = true } parking_lot = { version = "0.12.0", optional = true } +secp256k1 = { version = "0.21.2", features = ["recovery", "global-context"], optional = true } tracing = { version = "0.1.29", default-features = false } tracing-core = { version = "0.1.17", default-features = false} @@ -44,6 +45,7 @@ std = [ "sp-trie", "sp-state-machine", "libsecp256k1", + "secp256k1", "sp-runtime-interface/std", "sp-externalities", "sp-wasm-interface/std", diff --git a/primitives/io/src/lib.rs b/primitives/io/src/lib.rs index db86fe096415..9f49a098b6ad 100644 --- a/primitives/io/src/lib.rs +++ b/primitives/io/src/lib.rs @@ -66,6 +66,12 @@ use sp_runtime_interface::{ use codec::{Decode, Encode}; +#[cfg(feature = "std")] +use secp256k1::{ + ecdsa::{RecoverableSignature, RecoveryId}, + Message, SECP256K1, +}; + #[cfg(feature = "std")] use sp_externalities::{Externalities, ExternalitiesExt}; @@ -647,7 +653,7 @@ pub trait Crypto { SyncCryptoStore::sign_with(keystore, id, &pub_key.into(), msg) .ok() .flatten() - .map(|sig| ed25519::Signature::from_slice(sig.as_slice())) + .and_then(|sig| ed25519::Signature::from_slice(&sig)) } /// Verify `ed25519` signature. @@ -771,7 +777,7 @@ pub trait Crypto { SyncCryptoStore::sign_with(keystore, id, &pub_key.into(), msg) .ok() .flatten() - .map(|sig| sr25519::Signature::from_slice(sig.as_slice())) + .and_then(|sig| sr25519::Signature::from_slice(&sig)) } /// Verify an `sr25519` signature. @@ -820,7 +826,7 @@ pub trait Crypto { SyncCryptoStore::sign_with(keystore, id, &pub_key.into(), msg) .ok() .flatten() - .map(|sig| ecdsa::Signature::from_slice(sig.as_slice())) + .and_then(|sig| ecdsa::Signature::from_slice(&sig)) } /// Sign the given a pre-hashed `msg` with the `ecdsa` key that corresponds to the given public @@ -842,7 +848,9 @@ pub trait Crypto { /// Verify `ecdsa` signature. /// /// Returns `true` when the verification was successful. + /// This version is able to handle, non-standard, overflowing signatures. fn ecdsa_verify(sig: &ecdsa::Signature, msg: &[u8], pub_key: &ecdsa::Public) -> bool { + #[allow(deprecated)] ecdsa::Pair::verify_deprecated(sig, msg, pub_key) } @@ -891,18 +899,20 @@ pub trait Crypto { /// /// Returns `Err` if the signature is bad, otherwise the 64-byte pubkey /// (doesn't include the 0x04 prefix). + /// This version is able to handle, non-standard, overflowing signatures. fn secp256k1_ecdsa_recover( sig: &[u8; 65], msg: &[u8; 32], ) -> Result<[u8; 64], EcdsaVerifyError> { - let rs = libsecp256k1::Signature::parse_overflowing_slice(&sig[0..64]) - .map_err(|_| EcdsaVerifyError::BadRS)?; - let v = libsecp256k1::RecoveryId::parse( - if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8 + let rid = libsecp256k1::RecoveryId::parse( + if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8, ) .map_err(|_| EcdsaVerifyError::BadV)?; - let pubkey = libsecp256k1::recover(&libsecp256k1::Message::parse(msg), &rs, &v) - .map_err(|_| EcdsaVerifyError::BadSignature)?; + let sig = libsecp256k1::Signature::parse_overflowing_slice(&sig[..64]) + .map_err(|_| EcdsaVerifyError::BadRS)?; + let msg = libsecp256k1::Message::parse(msg); + let pubkey = + libsecp256k1::recover(&msg, &sig, &rid).map_err(|_| EcdsaVerifyError::BadSignature)?; let mut res = [0u8; 64]; res.copy_from_slice(&pubkey.serialize()[1..65]); Ok(res) @@ -920,16 +930,16 @@ pub trait Crypto { sig: &[u8; 65], msg: &[u8; 32], ) -> Result<[u8; 64], EcdsaVerifyError> { - let rs = libsecp256k1::Signature::parse_standard_slice(&sig[0..64]) + let rid = RecoveryId::from_i32(if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as i32) + .map_err(|_| EcdsaVerifyError::BadV)?; + let sig = RecoverableSignature::from_compact(&sig[..64], rid) .map_err(|_| EcdsaVerifyError::BadRS)?; - let v = libsecp256k1::RecoveryId::parse( - if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8 - ) - .map_err(|_| EcdsaVerifyError::BadV)?; - let pubkey = libsecp256k1::recover(&libsecp256k1::Message::parse(msg), &rs, &v) + let msg = Message::from_slice(msg).expect("Message is 32 bytes; qed"); + let pubkey = SECP256K1 + .recover_ecdsa(&msg, &sig) .map_err(|_| EcdsaVerifyError::BadSignature)?; let mut res = [0u8; 64]; - res.copy_from_slice(&pubkey.serialize()[1..65]); + res.copy_from_slice(&pubkey.serialize_uncompressed()[1..]); Ok(res) } @@ -943,14 +953,15 @@ pub trait Crypto { sig: &[u8; 65], msg: &[u8; 32], ) -> Result<[u8; 33], EcdsaVerifyError> { - let rs = libsecp256k1::Signature::parse_overflowing_slice(&sig[0..64]) - .map_err(|_| EcdsaVerifyError::BadRS)?; - let v = libsecp256k1::RecoveryId::parse( - if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8 + let rid = libsecp256k1::RecoveryId::parse( + if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8, ) .map_err(|_| EcdsaVerifyError::BadV)?; - let pubkey = libsecp256k1::recover(&libsecp256k1::Message::parse(msg), &rs, &v) - .map_err(|_| EcdsaVerifyError::BadSignature)?; + let sig = libsecp256k1::Signature::parse_overflowing_slice(&sig[0..64]) + .map_err(|_| EcdsaVerifyError::BadRS)?; + let msg = libsecp256k1::Message::parse(msg); + let pubkey = + libsecp256k1::recover(&msg, &sig, &rid).map_err(|_| EcdsaVerifyError::BadSignature)?; Ok(pubkey.serialize_compressed()) } @@ -965,15 +976,15 @@ pub trait Crypto { sig: &[u8; 65], msg: &[u8; 32], ) -> Result<[u8; 33], EcdsaVerifyError> { - let rs = libsecp256k1::Signature::parse_standard_slice(&sig[0..64]) + let rid = RecoveryId::from_i32(if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as i32) + .map_err(|_| EcdsaVerifyError::BadV)?; + let sig = RecoverableSignature::from_compact(&sig[..64], rid) .map_err(|_| EcdsaVerifyError::BadRS)?; - let v = libsecp256k1::RecoveryId::parse( - if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8 - ) - .map_err(|_| EcdsaVerifyError::BadV)?; - let pubkey = libsecp256k1::recover(&libsecp256k1::Message::parse(msg), &rs, &v) + let msg = Message::from_slice(msg).expect("Message is 32 bytes; qed"); + let pubkey = SECP256K1 + .recover_ecdsa(&msg, &sig) .map_err(|_| EcdsaVerifyError::BadSignature)?; - Ok(pubkey.serialize_compressed()) + Ok(pubkey.serialize()) } } From 8da9ad8bc619f2c782ff4a343cd5cdfb346c58b1 Mon Sep 17 00:00:00 2001 From: omadoyeabraham Date: Mon, 28 Feb 2022 10:47:04 +0100 Subject: [PATCH 536/695] Integrate try-runtime into substrate node template (#10909) * [10892-integrate-try-runtime-into-node-template] - Integrated try-runtime into node template * [10892-integrate-try-runtime-into-node-template] Added match arms for try-runtime in command.rs * [10892-integrate-try-runtime-into-node-template] Added match arms for try-runtime in command.rs * Added feature flag for try-runtime in node-template/node and enabled try-runtime for node-template/runtime * Added missing type annotations for try-runtime SubCommand in node-template * Added missing type annotations for try-runtime SubCommand in node-template * Implemented frame_try_runtime::TryRuntime for the node-template Runtime --- Cargo.lock | 2 ++ bin/node-template/node/Cargo.toml | 6 ++++++ bin/node-template/node/src/cli.rs | 8 ++++++++ bin/node-template/node/src/command.rs | 17 +++++++++++++++++ bin/node-template/runtime/Cargo.toml | 12 ++++++++++++ bin/node-template/runtime/src/lib.rs | 15 +++++++++++++++ 6 files changed, 60 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 66910db9d31b..1e44edc89994 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5085,6 +5085,7 @@ dependencies = [ "sp-timestamp", "substrate-build-script-utils", "substrate-frame-rpc-system", + "try-runtime-cli", ] [[package]] @@ -5097,6 +5098,7 @@ dependencies = [ "frame-system", "frame-system-benchmarking", "frame-system-rpc-runtime-api", + "frame-try-runtime", "hex-literal", "pallet-aura", "pallet-balances", diff --git a/bin/node-template/node/Cargo.toml b/bin/node-template/node/Cargo.toml index 1f8ff0ae1e0d..ea14942afee0 100644 --- a/bin/node-template/node/Cargo.toml +++ b/bin/node-template/node/Cargo.toml @@ -55,9 +55,15 @@ frame-benchmarking-cli = { version = "4.0.0-dev", path = "../../../utils/frame/b # Local Dependencies node-template-runtime = { version = "4.0.0-dev", path = "../runtime" } +# CLI-specific dependencies +try-runtime-cli = { version = "0.10.0-dev", optional = true, path = "../../../utils/frame/try-runtime/cli" } + [build-dependencies] substrate-build-script-utils = { version = "3.0.0", path = "../../../utils/build-script-utils" } [features] default = [] runtime-benchmarks = ["node-template-runtime/runtime-benchmarks"] +# Enable features that allow the runtime to be tried and debugged. Name might be subject to change +# in the near future. +try-runtime = ["node-template-runtime/try-runtime", "try-runtime-cli"] diff --git a/bin/node-template/node/src/cli.rs b/bin/node-template/node/src/cli.rs index d787f57f071a..c4d27b71e499 100644 --- a/bin/node-template/node/src/cli.rs +++ b/bin/node-template/node/src/cli.rs @@ -39,4 +39,12 @@ pub enum Subcommand { /// The custom benchmark subcommand benchmarking runtime pallets. #[clap(name = "benchmark", about = "Benchmark runtime pallets.")] Benchmark(frame_benchmarking_cli::BenchmarkCmd), + + /// Try some command against runtime state. + #[cfg(feature = "try-runtime")] + TryRuntime(try_runtime_cli::TryRuntimeCmd), + + /// Try some command against runtime state. Note: `try-runtime` feature must be enabled. + #[cfg(not(feature = "try-runtime"))] + TryRuntime, } diff --git a/bin/node-template/node/src/command.rs b/bin/node-template/node/src/command.rs index e1cfeaeb801e..72c7a75b387b 100644 --- a/bin/node-template/node/src/command.rs +++ b/bin/node-template/node/src/command.rs @@ -108,6 +108,23 @@ pub fn run() -> sc_cli::Result<()> { `--features runtime-benchmarks`." .into()) }, + #[cfg(feature = "try-runtime")] + Some(Subcommand::TryRuntime(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { + // we don't need any of the components of new_partial, just a runtime, or a task + // manager to do `async_run`. + let registry = config.prometheus_config.as_ref().map(|cfg| &cfg.registry); + let task_manager = + sc_service::TaskManager::new(config.tokio_handle.clone(), registry) + .map_err(|e| sc_cli::Error::Service(sc_service::Error::Prometheus(e)))?; + Ok((cmd.run::(config), task_manager)) + }) + }, + #[cfg(not(feature = "try-runtime"))] + Some(Subcommand::TryRuntime) => Err("TryRuntime wasn't enabled when building the node. \ + You can enable it with `--features try-runtime`." + .into()), None => { let runner = cli.create_runner(&cli.run)?; runner.run_node_until_exit(|config| async move { diff --git a/bin/node-template/runtime/Cargo.toml b/bin/node-template/runtime/Cargo.toml index ca3b4d93e6b6..95021227cf4f 100644 --- a/bin/node-template/runtime/Cargo.toml +++ b/bin/node-template/runtime/Cargo.toml @@ -23,6 +23,7 @@ pallet-grandpa = { version = "4.0.0-dev", default-features = false, path = "../. pallet-randomness-collective-flip = { version = "4.0.0-dev", default-features = false, path = "../../../frame/randomness-collective-flip" } pallet-sudo = { version = "4.0.0-dev", default-features = false, path = "../../../frame/sudo" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../../frame/system" } +frame-try-runtime = { version = "0.10.0-dev", default-features = false, path = "../../../frame/try-runtime", optional = true } pallet-timestamp = { version = "4.0.0-dev", default-features = false, path = "../../../frame/timestamp" } pallet-transaction-payment = { version = "4.0.0-dev", default-features = false, path = "../../../frame/transaction-payment" } frame-executive = { version = "4.0.0-dev", default-features = false, path = "../../../frame/executive" } @@ -94,3 +95,14 @@ runtime-benchmarks = [ "pallet-timestamp/runtime-benchmarks", "sp-runtime/runtime-benchmarks", ] +try-runtime = [ + "frame-executive/try-runtime", + "frame-try-runtime", + "frame-system/try-runtime", + "pallet-balances/try-runtime", + "pallet-grandpa/try-runtime", + "pallet-randomness-collective-flip/try-runtime", + "pallet-sudo/try-runtime", + "pallet-timestamp/try-runtime", + "pallet-transaction-payment/try-runtime", +] diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index 0b39d76fe495..93cf234fa52b 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -515,4 +515,19 @@ impl_runtime_apis! { Ok(batches) } } + + #[cfg(feature = "try-runtime")] + impl frame_try_runtime::TryRuntime for Runtime { + fn on_runtime_upgrade() -> (Weight, Weight) { + // NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to + // have a backtrace here. If any of the pre/post migration checks fail, we shall stop + // right here and right now. + let weight = Executive::try_runtime_upgrade().unwrap(); + (weight, BlockWeights::get().max_block) + } + + fn execute_block_no_check(block: Block) -> Weight { + Executive::execute_block_no_check(block) + } + } } From e073c241c3c9e48e0678581029bac84ba32dbb09 Mon Sep 17 00:00:00 2001 From: Ross Bulat Date: Mon, 28 Feb 2022 13:58:30 +0000 Subject: [PATCH 537/695] doc corrections (#10936) --- frame/election-provider-multi-phase/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frame/election-provider-multi-phase/src/lib.rs b/frame/election-provider-multi-phase/src/lib.rs index 9413984f80db..8b4ae60facb5 100644 --- a/frame/election-provider-multi-phase/src/lib.rs +++ b/frame/election-provider-multi-phase/src/lib.rs @@ -103,7 +103,7 @@ //! //! Validators will only submit solutions if the one that they have computed is sufficiently better //! than the best queued one (see [`pallet::Config::SolutionImprovementThreshold`]) and will limit -//! the weigh of the solution to [`pallet::Config::MinerMaxWeight`]. +//! the weight of the solution to [`pallet::Config::MinerMaxWeight`]. //! //! The unsigned phase can be made passive depending on how the previous signed phase went, by //! setting the first inner value of [`Phase`] to `false`. For now, the signed phase is always @@ -147,13 +147,13 @@ //! which is capable of connecting to a live network, and generating appropriate `supports` using a //! standard algorithm, and outputting the `supports` in hex format, ready for submission. Note that //! while this binary lives in the Polkadot repository, this particular subcommand of it can work -//! against any substrate based-chain. +//! against any substrate-based chain. //! //! See the `staking-miner` documentation in the Polkadot repository for more information. //! //! ## Feasible Solution (correct solution) //! -//! All submissions must undergo a feasibility check. Signed solutions are checked on by one at the +//! All submissions must undergo a feasibility check. Signed solutions are checked one by one at the //! end of the signed phase, and the unsigned solutions are checked on the spot. A feasible solution //! is as follows: //! From 79d04758ec7feed94842ae9f9955c05c42646070 Mon Sep 17 00:00:00 2001 From: Roman Gafiyatullin Date: Mon, 28 Feb 2022 23:51:35 +0200 Subject: [PATCH 538/695] #10576: generic utility to unsubscribe from broadcast upon drop of the rx-side. (#10708) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * #10576: refactor `sc-utils::notification` and `sc-client-api::notifications`, so that they use common subscribe/unsubscribe routines * Add some docs. Reorganise `sc-utils::notification` * `sc-clent-api::notifications` and `sc-utils::notification` — ensure the SubscriptionGuard is dropped before the Rx-channel * `sc-utils::pubsub::SubscriptionGuard` make it a bit more ergonomic. Let the `Rx` to be put inside of the `SubscriptionGuard`, so that the latter shall guarantee the order: - first unsubscribe; - then drop the `Rx`. * Being less zealous with splitting the modules into little pieces * rework pubsub: the concrete usage should only define a good registry type * sc-client-api::notifications: make it comply with the reworked pubsub * cargo fmt * make sc-client-api tests work * Address the review notes * cargo fmt * Describe the behaviour of pubsub registry * Doc-comments for module `sc-utils::pubsub` * Fix: it used to send notifications regardless of the filter setup during subscription * `sc-client-api::StorageNotifications` the API does not have to require mut-self-reference. As a result `sc-service::Client` does not have to wrap its `storage_notifications` into a Mutex. * cargo fmt * Several changes addressing the notes by @bckhr. - Remove the `impl Default for StorageNotifications`; - no need for groupping the `remove_from` and `listen_from` into a separate `helpers` module; - remove unnecessary import `use registry::SubscribeOp`. * Add a doc-comment to the `sc-client::notifications::SubscribeOp` * As per @bkchr note on the unproven assertion: behave gracefully upon receiving a duplicate subscription-ID. * sc-utils::pubsub: log when a registry yields an ID that does point to an existing sink * `sc-utils::notifications`: payload materialized lazily * Update Cargo.lock (after adding `log` as a dependency to the `sc-utils`) * `sc-client-api::notifications`: introduce a struct (instead of a type def) for the notification message * Get rid of `sc-utils::pubsub::Channel` trait (instead just use the `sc-utils::mpsc`) * The SubsID is no more generic: the fact it is a `Copy` is known — no need to pass it by ref * sc-utils::pubsub internals do not have to be generic over the channel type * Rename Hub::dispatch into Hub::send * That method was unnecessary (`SubscriberSink::render_notification`) * cargo fmt * No need for a separate UnsubscribeGuard type * Ditch the type-def of SubsID in the sc-utils::pubsub, instead — just use the crate::id_sequence::SeqID * Return the ::Ret when sending an item * Make the `Hub::lock_registry(...)` method more ergonomic * cargo doc links * cargo doc links * Use a simpler name for the type * cargo doc links * Derive `Default` rather than implement it * Derive `Default` rather than implement it * Remove an unnecessary usage of type_name * Define a more cautious order between sinks.remove->registry.unsubscribe and registry.subscribe->sinks.insert * Hub: lock_registry_for_tests->map_registry_for_tests — a safer choice for a public API * Replace Mutex over the shared Registry with a ReentrableMutex+RefCell * sc-utils::pubsub: add tests for a panicking registry * Add the missing copyright headers * Arc> -> Arc<[_]> --- Cargo.lock | 1 + client/api/src/client.rs | 8 +- client/api/src/notifications.rs | 616 ++---------------- client/api/src/notifications/registry.rs | 365 +++++++++++ client/api/src/notifications/tests.rs | 221 +++++++ client/rpc/src/state/state_full.rs | 4 +- client/service/src/client/client.rs | 8 +- client/transaction-pool/api/src/lib.rs | 2 +- client/transaction-pool/tests/pool.rs | 14 +- client/utils/Cargo.toml | 1 + client/utils/src/id_sequence.rs | 54 ++ client/utils/src/lib.rs | 2 + client/utils/src/notification.rs | 143 ++-- client/utils/src/notification/registry.rs | 63 ++ client/utils/src/notification/tests.rs | 52 ++ client/utils/src/pubsub.rs | 263 ++++++++ client/utils/src/pubsub/tests.rs | 123 ++++ .../src/pubsub/tests/normal_operation.rs | 88 +++ .../src/pubsub/tests/panicking_registry.rs | 248 +++++++ 19 files changed, 1604 insertions(+), 672 deletions(-) create mode 100644 client/api/src/notifications/registry.rs create mode 100644 client/api/src/notifications/tests.rs create mode 100644 client/utils/src/id_sequence.rs create mode 100644 client/utils/src/notification/registry.rs create mode 100644 client/utils/src/notification/tests.rs create mode 100644 client/utils/src/pubsub.rs create mode 100644 client/utils/src/pubsub/tests.rs create mode 100644 client/utils/src/pubsub/tests/normal_operation.rs create mode 100644 client/utils/src/pubsub/tests/panicking_registry.rs diff --git a/Cargo.lock b/Cargo.lock index 1e44edc89994..da474bdcfb21 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9067,6 +9067,7 @@ dependencies = [ "futures 0.3.16", "futures-timer", "lazy_static", + "log 0.4.14", "parking_lot 0.12.0", "prometheus", "tokio-test", diff --git a/client/api/src/client.rs b/client/api/src/client.rs index 949cc42c1c04..11195e1def28 100644 --- a/client/api/src/client.rs +++ b/client/api/src/client.rs @@ -307,9 +307,9 @@ pub struct FinalityNotification { /// Finalized block header. pub header: Block::Header, /// Path from the old finalized to new finalized parent (implicitly finalized blocks). - pub tree_route: Arc>, + pub tree_route: Arc<[Block::Hash]>, /// Stale branches heads. - pub stale_heads: Arc>, + pub stale_heads: Arc<[Block::Hash]>, } impl TryFrom> for ChainEvent { @@ -336,8 +336,8 @@ impl From> for FinalityNotification { FinalityNotification { hash, header: summary.header, - tree_route: Arc::new(summary.finalized), - stale_heads: Arc::new(summary.stale_heads), + tree_route: Arc::from(summary.finalized), + stale_heads: Arc::from(summary.stale_heads), } } } diff --git a/client/api/src/notifications.rs b/client/api/src/notifications.rs index 8199bc6b9710..36798abc5bde 100644 --- a/client/api/src/notifications.rs +++ b/client/api/src/notifications.rs @@ -21,30 +21,54 @@ use std::{ collections::{HashMap, HashSet}, pin::Pin, - sync::{Arc, Weak}, + sync::Arc, task::Poll, }; -use fnv::{FnvHashMap, FnvHashSet}; use futures::Stream; -use parking_lot::Mutex; -use prometheus_endpoint::{register, CounterVec, Opts, Registry, U64}; -use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender}; -use sp_core::{ - hexdisplay::HexDisplay, - storage::{StorageData, StorageKey}, -}; + +use prometheus_endpoint::Registry as PrometheusRegistry; + +use sc_utils::pubsub::{Hub, Receiver}; +use sp_core::storage::{StorageData, StorageKey}; use sp_runtime::traits::Block as BlockT; +mod registry; + +use registry::Registry; + +#[cfg(test)] +mod tests; + +/// A type of a message delivered to the subscribers +#[derive(Debug)] +pub struct StorageNotification { + /// The hash of the block + pub block: Hash, + + /// The set of changes + pub changes: StorageChangeSet, +} + /// Storage change set #[derive(Debug)] pub struct StorageChangeSet { - changes: Arc)>>, - child_changes: Arc)>)>>, + changes: Arc<[(StorageKey, Option)]>, + child_changes: Arc<[(StorageKey, Vec<(StorageKey, Option)>)]>, filter: Keys, child_filters: ChildKeys, } +/// Manages storage listeners. +#[derive(Debug)] +pub struct StorageNotifications(Hub, Registry>); + +/// Type that implements `futures::Stream` of storage change events. +pub struct StorageEventStream(Receiver, Registry>); + +type Keys = Option>; +type ChildKeys = Option>>>; + impl StorageChangeSet { /// Convert the change set into iterator over storage items. pub fn iter<'a>( @@ -80,125 +104,24 @@ impl StorageChangeSet { } } -/// Type that implements `futures::Stream` of storage change events. -pub struct StorageEventStream { - rx: TracingUnboundedReceiver<(H, StorageChangeSet)>, - storage_notifications: Weak>>, - was_triggered: bool, - id: u64, -} - impl Stream for StorageEventStream { - type Item = as Stream>::Item; + type Item = StorageNotification; fn poll_next( - mut self: Pin<&mut Self>, + self: Pin<&mut Self>, cx: &mut std::task::Context<'_>, ) -> Poll> { - let result = Stream::poll_next(Pin::new(&mut self.rx), cx); - if result.is_ready() { - self.was_triggered = true; - } - result - } -} - -impl Drop for StorageEventStream { - fn drop(&mut self) { - if let Some(storage_notifications) = self.storage_notifications.upgrade() { - if let Some((keys, child_keys)) = - storage_notifications.lock().remove_subscriber(self.id) - { - if !self.was_triggered { - log::trace!( - target: "storage_notifications", - "Listener was never triggered: id={}, keys={:?}, child_keys={:?}", - self.id, - PrintKeys(&keys), - PrintChildKeys(&child_keys), - ); - } - } - } - } -} - -type SubscriberId = u64; - -type SubscribersGauge = CounterVec; - -/// Manages storage listeners. -#[derive(Debug)] -pub struct StorageNotifications(Arc>>); - -type Keys = Option>; -type ChildKeys = Option>>>; - -#[derive(Debug)] -struct StorageNotificationsImpl { - metrics: Option, - next_id: SubscriberId, - wildcard_listeners: FnvHashSet, - listeners: HashMap>, - child_listeners: HashMap< - StorageKey, - (HashMap>, FnvHashSet), - >, - sinks: FnvHashMap< - SubscriberId, - (TracingUnboundedSender<(Hash, StorageChangeSet)>, Keys, ChildKeys), - >, -} - -impl Default for StorageNotifications { - fn default() -> Self { - Self(Default::default()) - } -} - -impl Default for StorageNotificationsImpl { - fn default() -> Self { - Self { - metrics: Default::default(), - next_id: Default::default(), - wildcard_listeners: Default::default(), - listeners: Default::default(), - child_listeners: Default::default(), - sinks: Default::default(), - } - } -} - -struct PrintKeys<'a>(&'a Keys); -impl<'a> std::fmt::Debug for PrintKeys<'a> { - fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { - if let Some(keys) = self.0 { - fmt.debug_list().entries(keys.iter().map(HexDisplay::from)).finish() - } else { - write!(fmt, "None") - } - } -} - -struct PrintChildKeys<'a>(&'a ChildKeys); -impl<'a> std::fmt::Debug for PrintChildKeys<'a> { - fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { - if let Some(map) = self.0 { - fmt.debug_map() - .entries(map.iter().map(|(key, values)| (HexDisplay::from(key), PrintKeys(values)))) - .finish() - } else { - write!(fmt, "None") - } + Stream::poll_next(Pin::new(&mut self.get_mut().0), cx) } } impl StorageNotifications { /// Initialize a new StorageNotifications /// optionally pass a prometheus registry to send subscriber metrics to - pub fn new(prometheus_registry: Option) -> Self { - StorageNotifications(Arc::new(Mutex::new(StorageNotificationsImpl::new( - prometheus_registry, - )))) + pub fn new(prometheus_registry: Option) -> Self { + let registry = Registry::new(prometheus_registry); + let hub = Hub::new_with_registry("mpsc_storage_notification_items", registry); + + StorageNotifications(hub) } /// Trigger notification to all listeners. @@ -206,467 +129,24 @@ impl StorageNotifications { /// Note the changes are going to be filtered by listener's filter key. /// In fact no event might be sent if clients are not interested in the changes. pub fn trigger( - &mut self, + &self, hash: &Block::Hash, changeset: impl Iterator, Option>)>, child_changeset: impl Iterator< Item = (Vec, impl Iterator, Option>)>), >, ) { - self.0.lock().trigger(hash, changeset, child_changeset); + self.0.send((hash, changeset, child_changeset)) } /// Start listening for particular storage keys. pub fn listen( - &mut self, + &self, filter_keys: Option<&[StorageKey]>, filter_child_keys: Option<&[(StorageKey, Option>)]>, ) -> StorageEventStream { - let (id, rx) = self.0.lock().listen(filter_keys, filter_child_keys); - let storage_notifications = Arc::downgrade(&self.0); - StorageEventStream { rx, storage_notifications, was_triggered: false, id } - } -} - -impl StorageNotificationsImpl { - fn new(prometheus_registry: Option) -> Self { - let metrics = prometheus_registry.and_then(|r| { - CounterVec::new( - Opts::new( - "substrate_storage_notification_subscribers", - "Number of subscribers in storage notification sytem", - ), - &["action"], // added | removed - ) - .and_then(|g| register(g, &r)) - .ok() - }); - - StorageNotificationsImpl { - metrics, - next_id: Default::default(), - wildcard_listeners: Default::default(), - listeners: Default::default(), - child_listeners: Default::default(), - sinks: Default::default(), - } - } - fn trigger( - &mut self, - hash: &Hash, - changeset: impl Iterator, Option>)>, - child_changeset: impl Iterator< - Item = (Vec, impl Iterator, Option>)>), - >, - ) where - Hash: Clone, - { - let has_wildcard = !self.wildcard_listeners.is_empty(); - - // early exit if no listeners - if !has_wildcard && self.listeners.is_empty() && self.child_listeners.is_empty() { - return - } - - let mut subscribers = self.wildcard_listeners.clone(); - let mut changes = Vec::new(); - let mut child_changes = Vec::new(); - - // Collect subscribers and changes - for (k, v) in changeset { - let k = StorageKey(k); - let listeners = self.listeners.get(&k); - - if let Some(ref listeners) = listeners { - subscribers.extend(listeners.iter()); - } - - if has_wildcard || listeners.is_some() { - changes.push((k, v.map(StorageData))); - } - } - for (sk, changeset) in child_changeset { - let sk = StorageKey(sk); - if let Some((cl, cw)) = self.child_listeners.get(&sk) { - let mut changes = Vec::new(); - for (k, v) in changeset { - let k = StorageKey(k); - let listeners = cl.get(&k); - - if let Some(ref listeners) = listeners { - subscribers.extend(listeners.iter()); - } - - subscribers.extend(cw.iter()); - - if !cw.is_empty() || listeners.is_some() { - changes.push((k, v.map(StorageData))); - } - } - if !changes.is_empty() { - child_changes.push((sk, changes)); - } - } - } - - // Don't send empty notifications - if changes.is_empty() && child_changes.is_empty() { - return - } - - let changes = Arc::new(changes); - let child_changes = Arc::new(child_changes); - // Trigger the events - - let to_remove = self - .sinks - .iter() - .filter_map(|(subscriber, &(ref sink, ref filter, ref child_filters))| { - let should_remove = { - if subscribers.contains(subscriber) { - sink.unbounded_send(( - hash.clone(), - StorageChangeSet { - changes: changes.clone(), - child_changes: child_changes.clone(), - filter: filter.clone(), - child_filters: child_filters.clone(), - }, - )) - .is_err() - } else { - sink.is_closed() - } - }; - - if should_remove { - Some(subscriber.clone()) - } else { - None - } - }) - .collect::>(); - - for sub_id in to_remove { - self.remove_subscriber(sub_id); - } - } - - fn remove_subscriber_from( - subscriber: &SubscriberId, - filters: &Keys, - listeners: &mut HashMap>, - wildcards: &mut FnvHashSet, - ) { - match filters { - None => { - wildcards.remove(subscriber); - }, - Some(filters) => - for key in filters.iter() { - let remove_key = match listeners.get_mut(key) { - Some(ref mut set) => { - set.remove(subscriber); - set.is_empty() - }, - None => false, - }; - - if remove_key { - listeners.remove(key); - } - }, - } - } - - fn remove_subscriber(&mut self, subscriber: SubscriberId) -> Option<(Keys, ChildKeys)> { - let (_, filters, child_filters) = self.sinks.remove(&subscriber)?; - Self::remove_subscriber_from( - &subscriber, - &filters, - &mut self.listeners, - &mut self.wildcard_listeners, - ); - if let Some(child_filters) = child_filters.as_ref() { - for (c_key, filters) in child_filters { - if let Some((listeners, wildcards)) = self.child_listeners.get_mut(&c_key) { - Self::remove_subscriber_from( - &subscriber, - &filters, - &mut *listeners, - &mut *wildcards, - ); - - if listeners.is_empty() && wildcards.is_empty() { - self.child_listeners.remove(&c_key); - } - } - } - } - if let Some(m) = self.metrics.as_ref() { - m.with_label_values(&[&"removed"]).inc(); - } - - Some((filters, child_filters)) - } - - fn listen_from( - current_id: SubscriberId, - filter_keys: &Option>, - listeners: &mut HashMap>, - wildcards: &mut FnvHashSet, - ) -> Keys { - match filter_keys { - None => { - wildcards.insert(current_id); - None - }, - Some(keys) => Some( - keys.as_ref() - .iter() - .map(|key| { - listeners - .entry(key.clone()) - .or_insert_with(Default::default) - .insert(current_id); - key.clone() - }) - .collect(), - ), - } - } - - fn listen( - &mut self, - filter_keys: Option<&[StorageKey]>, - filter_child_keys: Option<&[(StorageKey, Option>)]>, - ) -> (u64, TracingUnboundedReceiver<(Hash, StorageChangeSet)>) { - self.next_id += 1; - let current_id = self.next_id; - - // add subscriber for every key - let keys = Self::listen_from( - current_id, - &filter_keys, - &mut self.listeners, - &mut self.wildcard_listeners, - ); - let child_keys = filter_child_keys.map(|filter_child_keys| { - filter_child_keys - .iter() - .map(|(c_key, o_keys)| { - let (c_listeners, c_wildcards) = - self.child_listeners.entry(c_key.clone()).or_insert_with(Default::default); - - ( - c_key.clone(), - Self::listen_from(current_id, o_keys, &mut *c_listeners, &mut *c_wildcards), - ) - }) - .collect() - }); - - // insert sink - let (tx, rx) = tracing_unbounded("mpsc_storage_notification_items"); - self.sinks.insert(current_id, (tx, keys, child_keys)); - - if let Some(m) = self.metrics.as_ref() { - m.with_label_values(&[&"added"]).inc(); - } - - (current_id, rx) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use sp_runtime::testing::{Block as RawBlock, ExtrinsicWrapper, H256 as Hash}; - use std::iter::{empty, Empty}; - - type TestChangeSet = ( - Vec<(StorageKey, Option)>, - Vec<(StorageKey, Vec<(StorageKey, Option)>)>, - ); - - #[cfg(test)] - impl From for StorageChangeSet { - fn from(changes: TestChangeSet) -> Self { - // warning hardcoded child trie wildcard to test upon - let child_filters = Some( - [(StorageKey(vec![4]), None), (StorageKey(vec![5]), None)] - .iter() - .cloned() - .collect(), - ); - StorageChangeSet { - changes: Arc::new(changes.0), - child_changes: Arc::new(changes.1), - filter: None, - child_filters, - } - } - } - - #[cfg(test)] - impl PartialEq for StorageChangeSet { - fn eq(&self, other: &Self) -> bool { - self.iter().eq(other.iter()) - } - } - - type Block = RawBlock>; - - #[test] - fn triggering_change_should_notify_wildcard_listeners() { - // given - let mut notifications = StorageNotifications::::default(); - let child_filter = [(StorageKey(vec![4]), None)]; - let mut recv = - futures::executor::block_on_stream(notifications.listen(None, Some(&child_filter[..]))); - - // when - let changeset = vec![(vec![2], Some(vec![3])), (vec![3], None)]; - let c_changeset_1 = vec![(vec![5], Some(vec![4])), (vec![6], None)]; - let c_changeset = vec![(vec![4], c_changeset_1)]; - notifications.trigger( - &Hash::from_low_u64_be(1), - changeset.into_iter(), - c_changeset.into_iter().map(|(a, b)| (a, b.into_iter())), - ); - - // then - assert_eq!( - recv.next().unwrap(), - ( - Hash::from_low_u64_be(1), - ( - vec![ - (StorageKey(vec![2]), Some(StorageData(vec![3]))), - (StorageKey(vec![3]), None), - ], - vec![( - StorageKey(vec![4]), - vec![ - (StorageKey(vec![5]), Some(StorageData(vec![4]))), - (StorageKey(vec![6]), None), - ] - )] - ) - .into() - ) - ); - } - - #[test] - fn should_only_notify_interested_listeners() { - // given - let mut notifications = StorageNotifications::::default(); - let child_filter = [(StorageKey(vec![4]), Some(vec![StorageKey(vec![5])]))]; - let mut recv1 = futures::executor::block_on_stream( - notifications.listen(Some(&[StorageKey(vec![1])]), None), - ); - let mut recv2 = futures::executor::block_on_stream( - notifications.listen(Some(&[StorageKey(vec![2])]), None), - ); - let mut recv3 = futures::executor::block_on_stream( - notifications.listen(Some(&[]), Some(&child_filter)), - ); - - // when - let changeset = vec![(vec![2], Some(vec![3])), (vec![1], None)]; - let c_changeset_1 = vec![(vec![5], Some(vec![4])), (vec![6], None)]; - - let c_changeset = vec![(vec![4], c_changeset_1)]; - notifications.trigger( - &Hash::from_low_u64_be(1), - changeset.into_iter(), - c_changeset.into_iter().map(|(a, b)| (a, b.into_iter())), - ); - - // then - assert_eq!( - recv1.next().unwrap(), - (Hash::from_low_u64_be(1), (vec![(StorageKey(vec![1]), None),], vec![]).into()) - ); - assert_eq!( - recv2.next().unwrap(), - ( - Hash::from_low_u64_be(1), - (vec![(StorageKey(vec![2]), Some(StorageData(vec![3]))),], vec![]).into() - ) - ); - assert_eq!( - recv3.next().unwrap(), - ( - Hash::from_low_u64_be(1), - ( - vec![], - vec![( - StorageKey(vec![4]), - vec![(StorageKey(vec![5]), Some(StorageData(vec![4])))] - ),] - ) - .into() - ) - ); - } - - #[test] - fn should_cleanup_subscribers_if_dropped() { - // given - let mut notifications = StorageNotifications::::default(); - { - let child_filter = [(StorageKey(vec![4]), Some(vec![StorageKey(vec![5])]))]; - let _recv1 = futures::executor::block_on_stream( - notifications.listen(Some(&[StorageKey(vec![1])]), None), - ); - let _recv2 = futures::executor::block_on_stream( - notifications.listen(Some(&[StorageKey(vec![2])]), None), - ); - let _recv3 = futures::executor::block_on_stream(notifications.listen(None, None)); - let _recv4 = - futures::executor::block_on_stream(notifications.listen(None, Some(&child_filter))); - assert_eq!(notifications.0.lock().listeners.len(), 2); - assert_eq!(notifications.0.lock().wildcard_listeners.len(), 2); - assert_eq!(notifications.0.lock().child_listeners.len(), 1); - } - - // when - let changeset = vec![(vec![2], Some(vec![3])), (vec![1], None)]; - let c_changeset = empty::<(_, Empty<_>)>(); - notifications.trigger(&Hash::from_low_u64_be(1), changeset.into_iter(), c_changeset); - - // then - assert_eq!(notifications.0.lock().listeners.len(), 0); - assert_eq!(notifications.0.lock().wildcard_listeners.len(), 0); - assert_eq!(notifications.0.lock().child_listeners.len(), 0); - } - - #[test] - fn should_cleanup_subscriber_if_stream_is_dropped() { - let mut notifications = StorageNotifications::::default(); - let stream = notifications.listen(None, None); - assert_eq!(notifications.0.lock().sinks.len(), 1); - std::mem::drop(stream); - assert_eq!(notifications.0.lock().sinks.len(), 0); - } - - #[test] - fn should_not_send_empty_notifications() { - // given - let mut recv = { - let mut notifications = StorageNotifications::::default(); - let recv = futures::executor::block_on_stream(notifications.listen(None, None)); - - // when - let changeset = vec![]; - let c_changeset = empty::<(_, Empty<_>)>(); - notifications.trigger(&Hash::from_low_u64_be(1), changeset.into_iter(), c_changeset); - recv - }; + let receiver = self.0.subscribe(registry::SubscribeOp { filter_keys, filter_child_keys }); - // then - assert_eq!(recv.next(), None); + StorageEventStream(receiver) } } diff --git a/client/api/src/notifications/registry.rs b/client/api/src/notifications/registry.rs new file mode 100644 index 000000000000..b34d5a6b6711 --- /dev/null +++ b/client/api/src/notifications/registry.rs @@ -0,0 +1,365 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2022 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 . + +use super::*; + +use sp_core::hexdisplay::HexDisplay; + +use fnv::{FnvHashMap, FnvHashSet}; +use prometheus_endpoint::{register, CounterVec, Opts, U64}; + +use sc_utils::{ + id_sequence::SeqID as SubscriberId, + pubsub::{Dispatch, Subscribe, Unsubscribe}, +}; + +type SubscribersGauge = CounterVec; + +/// A command to subscribe with the specified filters. +/// +/// Used by the implementation of [`Subscribe`] trait for [`Registry]. +pub(super) struct SubscribeOp<'a> { + pub filter_keys: Option<&'a [StorageKey]>, + pub filter_child_keys: Option<&'a [(StorageKey, Option>)]>, +} + +#[derive(Debug, Default)] +pub(super) struct Registry { + pub(super) metrics: Option, + pub(super) wildcard_listeners: FnvHashSet, + pub(super) listeners: HashMap>, + pub(super) child_listeners: HashMap< + StorageKey, + (HashMap>, FnvHashSet), + >, + pub(super) sinks: FnvHashMap, +} + +#[derive(Debug)] +pub(super) struct SubscriberSink { + subs_id: SubscriberId, + keys: Keys, + child_keys: ChildKeys, + was_triggered: bool, +} + +impl Drop for SubscriberSink { + fn drop(&mut self) { + if !self.was_triggered { + log::trace!( + target: "storage_notifications", + "Listener was never triggered: id={}, keys={:?}, child_keys={:?}", + self.subs_id, + PrintKeys(&self.keys), + PrintChildKeys(&self.child_keys), + ); + } + } +} + +impl SubscriberSink { + fn new(subs_id: SubscriberId, keys: Keys, child_keys: ChildKeys) -> Self { + Self { subs_id, keys, child_keys, was_triggered: false } + } +} + +impl Registry { + pub(super) fn new(prometheus_registry: Option) -> Self { + let metrics = prometheus_registry.and_then(|r| { + CounterVec::new( + Opts::new( + "substrate_storage_notification_subscribers", + "Number of subscribers in storage notification sytem", + ), + &["action"], // added | removed + ) + .and_then(|g| register(g, &r)) + .ok() + }); + + Registry { metrics, ..Default::default() } + } +} + +impl Unsubscribe for Registry { + fn unsubscribe(&mut self, subs_id: SubscriberId) { + self.remove_subscriber(subs_id); + } +} + +impl<'a> Subscribe> for Registry { + fn subscribe(&mut self, subs_op: SubscribeOp<'a>, subs_id: SubscriberId) { + let SubscribeOp { filter_keys, filter_child_keys } = subs_op; + + let keys = Self::listen_from( + subs_id, + filter_keys.as_ref(), + &mut self.listeners, + &mut self.wildcard_listeners, + ); + + let child_keys = filter_child_keys.map(|filter_child_keys| { + filter_child_keys + .iter() + .map(|(c_key, o_keys)| { + let (c_listeners, c_wildcards) = + self.child_listeners.entry(c_key.clone()).or_default(); + + ( + c_key.clone(), + Self::listen_from( + subs_id, + o_keys.as_ref(), + &mut *c_listeners, + &mut *c_wildcards, + ), + ) + }) + .collect() + }); + + if let Some(m) = self.metrics.as_ref() { + m.with_label_values(&[&"added"]).inc(); + } + + if self + .sinks + .insert(subs_id, SubscriberSink::new(subs_id, keys, child_keys)) + .is_some() + { + log::warn!("The `subscribe`-method has been passed a non-unique subs_id (in `sc-client-api::notifications`)"); + } + } +} + +impl<'a, Hash, CS, CCS, CCSI> Dispatch<(&'a Hash, CS, CCS)> for Registry +where + Hash: Clone, + CS: Iterator, Option>)>, + CCS: Iterator, CCSI)>, + CCSI: Iterator, Option>)>, +{ + type Item = StorageNotification; + type Ret = (); + + fn dispatch(&mut self, message: (&'a Hash, CS, CCS), dispatch: F) -> Self::Ret + where + F: FnMut(&SubscriberId, Self::Item), + { + let (hash, changeset, child_changeset) = message; + self.trigger(hash, changeset, child_changeset, dispatch); + } +} + +impl Registry { + pub(super) fn trigger( + &mut self, + hash: &Hash, + changeset: impl Iterator, Option>)>, + child_changeset: impl Iterator< + Item = (Vec, impl Iterator, Option>)>), + >, + mut dispatch: F, + ) where + Hash: Clone, + F: FnMut(&SubscriberId, StorageNotification), + { + let has_wildcard = !self.wildcard_listeners.is_empty(); + + // early exit if no listeners + if !has_wildcard && self.listeners.is_empty() && self.child_listeners.is_empty() { + return + } + + let mut subscribers = self.wildcard_listeners.clone(); + let mut changes = Vec::new(); + let mut child_changes = Vec::new(); + + // Collect subscribers and changes + for (k, v) in changeset { + let k = StorageKey(k); + let listeners = self.listeners.get(&k); + + if let Some(ref listeners) = listeners { + subscribers.extend(listeners.iter()); + } + + if has_wildcard || listeners.is_some() { + changes.push((k, v.map(StorageData))); + } + } + for (sk, changeset) in child_changeset { + let sk = StorageKey(sk); + if let Some((cl, cw)) = self.child_listeners.get(&sk) { + let mut changes = Vec::new(); + for (k, v) in changeset { + let k = StorageKey(k); + let listeners = cl.get(&k); + + if let Some(ref listeners) = listeners { + subscribers.extend(listeners.iter()); + } + + subscribers.extend(cw.iter()); + + if !cw.is_empty() || listeners.is_some() { + changes.push((k, v.map(StorageData))); + } + } + if !changes.is_empty() { + child_changes.push((sk, changes)); + } + } + } + + // Don't send empty notifications + if changes.is_empty() && child_changes.is_empty() { + return + } + + let changes = Arc::<[_]>::from(changes); + let child_changes = Arc::<[_]>::from(child_changes); + + // Trigger the events + self.sinks.iter_mut().for_each(|(subs_id, sink)| { + if subscribers.contains(subs_id) { + sink.was_triggered = true; + + let storage_change_set = StorageChangeSet { + changes: changes.clone(), + child_changes: child_changes.clone(), + filter: sink.keys.clone(), + child_filters: sink.child_keys.clone(), + }; + + let notification = + StorageNotification { block: hash.clone(), changes: storage_change_set }; + + dispatch(subs_id, notification); + } + }); + } +} + +impl Registry { + fn remove_subscriber(&mut self, subscriber: SubscriberId) -> Option<(Keys, ChildKeys)> { + let sink = self.sinks.remove(&subscriber)?; + + Self::remove_subscriber_from( + subscriber, + &sink.keys, + &mut self.listeners, + &mut self.wildcard_listeners, + ); + if let Some(child_filters) = &sink.child_keys { + for (c_key, filters) in child_filters { + if let Some((listeners, wildcards)) = self.child_listeners.get_mut(&c_key) { + Self::remove_subscriber_from( + subscriber, + &filters, + &mut *listeners, + &mut *wildcards, + ); + + if listeners.is_empty() && wildcards.is_empty() { + self.child_listeners.remove(&c_key); + } + } + } + } + if let Some(m) = self.metrics.as_ref() { + m.with_label_values(&[&"removed"]).inc(); + } + + Some((sink.keys.clone(), sink.child_keys.clone())) + } + + fn remove_subscriber_from( + subscriber: SubscriberId, + filters: &Keys, + listeners: &mut HashMap>, + wildcards: &mut FnvHashSet, + ) { + match filters { + None => { + wildcards.remove(&subscriber); + }, + Some(filters) => + for key in filters.iter() { + let remove_key = match listeners.get_mut(key) { + Some(ref mut set) => { + set.remove(&subscriber); + set.is_empty() + }, + None => false, + }; + + if remove_key { + listeners.remove(key); + } + }, + } + } + + fn listen_from( + current_id: SubscriberId, + filter_keys: Option>, + listeners: &mut HashMap>, + wildcards: &mut FnvHashSet, + ) -> Keys { + match filter_keys { + None => { + wildcards.insert(current_id); + None + }, + Some(keys) => Some( + keys.as_ref() + .iter() + .map(|key| { + listeners.entry(key.clone()).or_default().insert(current_id); + key.clone() + }) + .collect(), + ), + } + } +} + +pub(super) struct PrintKeys<'a>(pub &'a Keys); +impl<'a> std::fmt::Debug for PrintKeys<'a> { + fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { + if let Some(keys) = self.0 { + fmt.debug_list().entries(keys.iter().map(HexDisplay::from)).finish() + } else { + write!(fmt, "None") + } + } +} + +pub(super) struct PrintChildKeys<'a>(pub &'a ChildKeys); +impl<'a> std::fmt::Debug for PrintChildKeys<'a> { + fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { + if let Some(map) = self.0 { + fmt.debug_map() + .entries(map.iter().map(|(key, values)| (HexDisplay::from(key), PrintKeys(values)))) + .finish() + } else { + write!(fmt, "None") + } + } +} diff --git a/client/api/src/notifications/tests.rs b/client/api/src/notifications/tests.rs new file mode 100644 index 000000000000..2c728de7428d --- /dev/null +++ b/client/api/src/notifications/tests.rs @@ -0,0 +1,221 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2022 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 . + +use super::*; + +use sp_runtime::testing::{Block as RawBlock, ExtrinsicWrapper, H256 as Hash}; +use std::iter::{empty, Empty}; + +type TestChangeSet = ( + Vec<(StorageKey, Option)>, + Vec<(StorageKey, Vec<(StorageKey, Option)>)>, +); + +impl From for StorageChangeSet { + fn from(changes: TestChangeSet) -> Self { + // warning hardcoded child trie wildcard to test upon + let child_filters = Some( + [(StorageKey(vec![4]), None), (StorageKey(vec![5]), None)] + .iter() + .cloned() + .collect(), + ); + StorageChangeSet { + changes: From::from(changes.0), + child_changes: From::from(changes.1), + filter: None, + child_filters, + } + } +} + +impl PartialEq for StorageChangeSet { + fn eq(&self, other: &Self) -> bool { + self.iter().eq(other.iter()) + } +} + +type Block = RawBlock>; + +#[test] +fn triggering_change_should_notify_wildcard_listeners() { + // given + let notifications = StorageNotifications::::new(None); + let child_filter = [(StorageKey(vec![4]), None)]; + let mut recv = + futures::executor::block_on_stream(notifications.listen(None, Some(&child_filter[..]))); + + // when + let changeset = vec![(vec![2], Some(vec![3])), (vec![3], None)]; + let c_changeset_1 = vec![(vec![5], Some(vec![4])), (vec![6], None)]; + let c_changeset = vec![(vec![4], c_changeset_1)]; + notifications.trigger( + &Hash::from_low_u64_be(1), + changeset.into_iter(), + c_changeset.into_iter().map(|(a, b)| (a, b.into_iter())), + ); + + // then + assert_eq!( + recv.next().map(StorageNotification::into_fields).unwrap(), + ( + Hash::from_low_u64_be(1), + ( + vec![ + (StorageKey(vec![2]), Some(StorageData(vec![3]))), + (StorageKey(vec![3]), None), + ], + vec![( + StorageKey(vec![4]), + vec![ + (StorageKey(vec![5]), Some(StorageData(vec![4]))), + (StorageKey(vec![6]), None), + ] + )] + ) + .into() + ) + ); +} + +#[test] +fn should_only_notify_interested_listeners() { + // given + let notifications = StorageNotifications::::new(None); + let child_filter = [(StorageKey(vec![4]), Some(vec![StorageKey(vec![5])]))]; + let mut recv1 = futures::executor::block_on_stream( + notifications.listen(Some(&[StorageKey(vec![1])]), None), + ); + let mut recv2 = futures::executor::block_on_stream( + notifications.listen(Some(&[StorageKey(vec![2])]), None), + ); + let mut recv3 = + futures::executor::block_on_stream(notifications.listen(Some(&[]), Some(&child_filter))); + + // when + let changeset = vec![(vec![2], Some(vec![3])), (vec![1], None)]; + let c_changeset_1 = vec![(vec![5], Some(vec![4])), (vec![6], None)]; + + let c_changeset = vec![(vec![4], c_changeset_1)]; + notifications.trigger( + &Hash::from_low_u64_be(1), + changeset.into_iter(), + c_changeset.into_iter().map(|(a, b)| (a, b.into_iter())), + ); + + // then + assert_eq!( + recv1.next().map(StorageNotification::into_fields).unwrap(), + (Hash::from_low_u64_be(1), (vec![(StorageKey(vec![1]), None),], vec![]).into()) + ); + assert_eq!( + recv2.next().map(StorageNotification::into_fields).unwrap(), + ( + Hash::from_low_u64_be(1), + (vec![(StorageKey(vec![2]), Some(StorageData(vec![3]))),], vec![]).into() + ) + ); + assert_eq!( + recv3.next().map(StorageNotification::into_fields).unwrap(), + ( + Hash::from_low_u64_be(1), + ( + vec![], + vec![( + StorageKey(vec![4]), + vec![(StorageKey(vec![5]), Some(StorageData(vec![4])))] + ),] + ) + .into() + ) + ); +} + +#[test] +fn should_cleanup_subscribers_if_dropped() { + // given + let notifications = StorageNotifications::::new(None); + { + let child_filter = [(StorageKey(vec![4]), Some(vec![StorageKey(vec![5])]))]; + let _recv1 = futures::executor::block_on_stream( + notifications.listen(Some(&[StorageKey(vec![1])]), None), + ); + let _recv2 = futures::executor::block_on_stream( + notifications.listen(Some(&[StorageKey(vec![2])]), None), + ); + let _recv3 = futures::executor::block_on_stream(notifications.listen(None, None)); + let _recv4 = + futures::executor::block_on_stream(notifications.listen(None, Some(&child_filter))); + assert_eq!(notifications.map_registry(|r| r.listeners.len()), 2); + assert_eq!(notifications.map_registry(|r| r.wildcard_listeners.len()), 2); + assert_eq!(notifications.map_registry(|r| r.child_listeners.len()), 1); + } + + // when + let changeset = vec![(vec![2], Some(vec![3])), (vec![1], None)]; + let c_changeset = empty::<(_, Empty<_>)>(); + notifications.trigger(&Hash::from_low_u64_be(1), changeset.into_iter(), c_changeset); + + // then + assert_eq!(notifications.map_registry(|r| r.listeners.len()), 0); + assert_eq!(notifications.map_registry(|r| r.wildcard_listeners.len()), 0); + assert_eq!(notifications.map_registry(|r| r.child_listeners.len()), 0); +} + +#[test] +fn should_cleanup_subscriber_if_stream_is_dropped() { + let notifications = StorageNotifications::::new(None); + let stream = notifications.listen(None, None); + assert_eq!(notifications.map_registry(|r| r.sinks.len()), 1); + std::mem::drop(stream); + assert_eq!(notifications.map_registry(|r| r.sinks.len()), 0); +} + +#[test] +fn should_not_send_empty_notifications() { + // given + let mut recv = { + let notifications = StorageNotifications::::new(None); + let recv = futures::executor::block_on_stream(notifications.listen(None, None)); + + // when + let changeset = vec![]; + let c_changeset = empty::<(_, Empty<_>)>(); + notifications.trigger(&Hash::from_low_u64_be(1), changeset.into_iter(), c_changeset); + recv + }; + + // then + assert_eq!(recv.next().map(StorageNotification::into_fields), None); +} + +impl StorageNotifications { + fn map_registry(&self, map: MapF) -> Ret + where + MapF: FnOnce(&Registry) -> Ret, + { + self.0.map_registry_for_tests(map) + } +} + +impl StorageNotification { + fn into_fields(self) -> (H, StorageChangeSet) { + let Self { block, changes } = self; + (block, changes) + } +} diff --git a/client/rpc/src/state/state_full.rs b/client/rpc/src/state/state_full.rs index b8132094fe8d..1a35760bd67d 100644 --- a/client/rpc/src/state/state_full.rs +++ b/client/rpc/src/state/state_full.rs @@ -51,7 +51,7 @@ use super::{ }; use sc_client_api::{ Backend, BlockBackend, BlockchainEvents, CallExecutor, ExecutorProvider, ProofProvider, - StorageProvider, + StorageNotification, StorageProvider, }; use std::marker::PhantomData; @@ -466,7 +466,7 @@ where ); self.subscriptions.add(subscriber, |sink| { - let stream = stream.map(|(block, changes)| { + let stream = stream.map(|StorageNotification { block, changes }| { Ok(Ok::<_, rpc::Error>(StorageChangeSet { block, changes: changes diff --git a/client/service/src/client/client.rs b/client/service/src/client/client.rs index 8497c34f5abb..004d4b711e09 100644 --- a/client/service/src/client/client.rs +++ b/client/service/src/client/client.rs @@ -107,7 +107,7 @@ where { backend: Arc, executor: E, - storage_notifications: Mutex>, + storage_notifications: StorageNotifications, import_notification_sinks: NotificationSinks>, finality_notification_sinks: NotificationSinks>, // Collects auxiliary operations to be performed atomically together with @@ -393,7 +393,7 @@ where Ok(Client { backend, executor, - storage_notifications: Mutex::new(StorageNotifications::new(prometheus_registry)), + storage_notifications: StorageNotifications::new(prometheus_registry), import_notification_sinks: Default::default(), finality_notification_sinks: Default::default(), import_actions: Default::default(), @@ -986,7 +986,7 @@ where if let Some(storage_changes) = storage_changes { // TODO [ToDr] How to handle re-orgs? Should we re-emit all storage changes? - self.storage_notifications.lock().trigger( + self.storage_notifications.trigger( ¬ification.hash, storage_changes.0.into_iter(), storage_changes.1.into_iter().map(|(sk, v)| (sk, v.into_iter())), @@ -1951,7 +1951,7 @@ where filter_keys: Option<&[StorageKey]>, child_filter_keys: Option<&[(StorageKey, Option>)]>, ) -> sp_blockchain::Result> { - Ok(self.storage_notifications.lock().listen(filter_keys, child_filter_keys)) + Ok(self.storage_notifications.listen(filter_keys, child_filter_keys)) } } diff --git a/client/transaction-pool/api/src/lib.rs b/client/transaction-pool/api/src/lib.rs index 7c90cd79ccae..d7b3ddc99636 100644 --- a/client/transaction-pool/api/src/lib.rs +++ b/client/transaction-pool/api/src/lib.rs @@ -292,7 +292,7 @@ pub enum ChainEvent { /// Hash of just finalized block. hash: B::Hash, /// Path from old finalized to new finalized parent. - tree_route: Arc>, + tree_route: Arc<[B::Hash]>, }, } diff --git a/client/transaction-pool/tests/pool.rs b/client/transaction-pool/tests/pool.rs index 21a87f6e006e..08ecdbc86cca 100644 --- a/client/transaction-pool/tests/pool.rs +++ b/client/transaction-pool/tests/pool.rs @@ -387,7 +387,7 @@ fn should_push_watchers_during_maintenance() { let header_hash = header.hash(); block_on(pool.maintain(block_event(header))); - let event = ChainEvent::Finalized { hash: header_hash.clone(), tree_route: Arc::new(vec![]) }; + let event = ChainEvent::Finalized { hash: header_hash.clone(), tree_route: Arc::from(vec![]) }; block_on(pool.maintain(event)); // then @@ -445,7 +445,7 @@ fn finalization() { let event = ChainEvent::NewBestBlock { hash: header.hash(), tree_route: None }; block_on(pool.maintain(event)); - let event = ChainEvent::Finalized { hash: header.hash(), tree_route: Arc::new(vec![]) }; + let event = ChainEvent::Finalized { hash: header.hash(), tree_route: Arc::from(vec![]) }; block_on(pool.maintain(event)); let mut stream = futures::executor::block_on_stream(watcher); @@ -493,7 +493,7 @@ fn fork_aware_finalization() { b1 = header.hash(); block_on(pool.maintain(event)); assert_eq!(pool.status().ready, 0); - let event = ChainEvent::Finalized { hash: b1, tree_route: Arc::new(vec![]) }; + let event = ChainEvent::Finalized { hash: b1, tree_route: Arc::from(vec![]) }; block_on(pool.maintain(event)); } @@ -537,7 +537,7 @@ fn fork_aware_finalization() { block_on(pool.maintain(event)); assert_eq!(pool.status().ready, 2); - let event = ChainEvent::Finalized { hash: header.hash(), tree_route: Arc::new(vec![]) }; + let event = ChainEvent::Finalized { hash: header.hash(), tree_route: Arc::from(vec![]) }; block_on(pool.maintain(event)); } @@ -554,7 +554,7 @@ fn fork_aware_finalization() { d1 = header.hash(); block_on(pool.maintain(event)); assert_eq!(pool.status().ready, 2); - let event = ChainEvent::Finalized { hash: d1, tree_route: Arc::new(vec![]) }; + let event = ChainEvent::Finalized { hash: d1, tree_route: Arc::from(vec![]) }; block_on(pool.maintain(event)); } @@ -567,7 +567,7 @@ fn fork_aware_finalization() { let event = ChainEvent::NewBestBlock { hash: header.hash(), tree_route: None }; block_on(pool.maintain(event)); assert_eq!(pool.status().ready, 0); - block_on(pool.maintain(ChainEvent::Finalized { hash: e1, tree_route: Arc::new(vec![]) })); + block_on(pool.maintain(ChainEvent::Finalized { hash: e1, tree_route: Arc::from(vec![]) })); } for (canon_watcher, h) in canon_watchers { @@ -637,7 +637,7 @@ fn prune_and_retract_tx_at_same_time() { block_on(pool.maintain(event)); assert_eq!(pool.status().ready, 0); - let event = ChainEvent::Finalized { hash: header.hash(), tree_route: Arc::new(vec![]) }; + let event = ChainEvent::Finalized { hash: header.hash(), tree_route: Arc::from(vec![]) }; block_on(pool.maintain(event)); header.hash() diff --git a/client/utils/Cargo.toml b/client/utils/Cargo.toml index c5acff24548a..70d6bcd8b049 100644 --- a/client/utils/Cargo.toml +++ b/client/utils/Cargo.toml @@ -15,6 +15,7 @@ lazy_static = "1.4.0" parking_lot = "0.12.0" prometheus = { version = "0.13.0", default-features = false } futures-timer = "3.0.2" +log = "0.4" [features] default = ["metered"] diff --git a/client/utils/src/id_sequence.rs b/client/utils/src/id_sequence.rs new file mode 100644 index 000000000000..2ccb4fc3f32e --- /dev/null +++ b/client/utils/src/id_sequence.rs @@ -0,0 +1,54 @@ +// This file is part of Substrate. + +// Copyright (C) 2020-2022 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 . + +//! Produce opaque sequential IDs. + +/// A Sequence of IDs. +#[derive(Debug, Default)] +// The `Clone` trait is intentionally not defined on this type. +pub struct IDSequence { + next_id: u64, +} + +/// A Sequential ID. +/// +/// Its integer value is intentionally not public: it is supposed to be instantiated from within +/// this module only. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct SeqID(u64); + +impl std::fmt::Display for SeqID { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + +impl IDSequence { + /// Create a new ID-sequence. + pub fn new() -> Self { + Default::default() + } + + /// Obtain another ID from this sequence. + pub fn next_id(&mut self) -> SeqID { + let id = SeqID(self.next_id); + self.next_id += 1; + + id + } +} diff --git a/client/utils/src/lib.rs b/client/utils/src/lib.rs index b3fb8400b12f..0e47330335c2 100644 --- a/client/utils/src/lib.rs +++ b/client/utils/src/lib.rs @@ -36,7 +36,9 @@ //! | entity | Name of channel passed to `tracing_unbounded` | //! | action | One of `send`/`received`/`dropped` | +pub mod id_sequence; pub mod metrics; pub mod mpsc; pub mod notification; +pub mod pubsub; pub mod status_sinks; diff --git a/client/utils/src/notification.rs b/client/utils/src/notification.rs index 21d01c5f99fe..ff527c343f9f 100644 --- a/client/utils/src/notification.rs +++ b/client/utils/src/notification.rs @@ -26,15 +26,19 @@ //! //! See [`sc-service::builder::RpcExtensionBuilder`] for more details. -use std::{marker::PhantomData, sync::Arc}; +use futures::stream::{FusedStream, Stream}; +use std::{ + pin::Pin, + task::{Context, Poll}, +}; -use crate::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender}; +use crate::pubsub::{Hub, Receiver}; -use parking_lot::Mutex; +mod registry; +use registry::Registry; -/// Collection of channel sending endpoints shared with the receiver side -/// so they can register themselves. -type SharedSenders = Arc>>>; +#[cfg(test)] +mod tests; /// Trait used to define the "tracing key" string used to tag /// and identify the mpsc channels. @@ -44,108 +48,75 @@ pub trait TracingKeyStr { const TRACING_KEY: &'static str; } -/// The sending half of the notifications channel(s). +/// The receiving half of the notifications channel. /// -/// Used to send notifications from the BEEFY gadget side. +/// The [`NotificationStream`] entity stores the [`Hub`] so it can be +/// used to add more subscriptions. #[derive(Clone)] -pub struct NotificationSender { - subscribers: SharedSenders, +pub struct NotificationStream { + hub: Hub, + _pd: std::marker::PhantomData, } -impl NotificationSender { - /// The `subscribers` should be shared with a corresponding `NotificationStream`. - fn new(subscribers: SharedSenders) -> Self { - Self { subscribers } - } - - /// Send out a notification to all subscribers that a new payload is available for a - /// block. - pub fn notify( - &self, - payload: impl FnOnce() -> Result, - ) -> Result<(), Error> { - let mut subscribers = self.subscribers.lock(); - - // do an initial prune on closed subscriptions - subscribers.retain(|n| !n.is_closed()); - - if !subscribers.is_empty() { - let payload = payload()?; - subscribers.retain(|n| n.unbounded_send(payload.clone()).is_ok()); - } - - Ok(()) - } +/// The receiving half of the notifications channel(s). +#[derive(Debug)] +pub struct NotificationReceiver { + receiver: Receiver, } -/// The receiving half of the notifications channel. -/// -/// The `NotificationStream` entity stores the `SharedSenders` so it can be -/// used to add more subscriptions. -#[derive(Clone)] -pub struct NotificationStream { - subscribers: SharedSenders, - _trace_key: PhantomData, +/// The sending half of the notifications channel(s). +pub struct NotificationSender { + hub: Hub, } -impl NotificationStream { +impl NotificationStream { /// Creates a new pair of receiver and sender of `Payload` notifications. pub fn channel() -> (NotificationSender, Self) { - let subscribers = Arc::new(Mutex::new(vec![])); - let receiver = NotificationStream::new(subscribers.clone()); - let sender = NotificationSender::new(subscribers); + let hub = Hub::new(TK::TRACING_KEY); + let sender = NotificationSender { hub: hub.clone() }; + let receiver = NotificationStream { hub, _pd: Default::default() }; (sender, receiver) } - /// Create a new receiver of `Payload` notifications. - /// - /// The `subscribers` should be shared with a corresponding `NotificationSender`. - fn new(subscribers: SharedSenders) -> Self { - Self { subscribers, _trace_key: PhantomData } - } - /// Subscribe to a channel through which the generic payload can be received. - pub fn subscribe(&self) -> TracingUnboundedReceiver { - let (sender, receiver) = tracing_unbounded(TK::TRACING_KEY); - self.subscribers.lock().push(sender); - receiver + pub fn subscribe(&self) -> NotificationReceiver { + let receiver = self.hub.subscribe(()); + NotificationReceiver { receiver } } } -#[cfg(test)] -mod tests { - use super::*; - use futures::StreamExt; - - #[derive(Clone)] - pub struct DummyTracingKey; - impl TracingKeyStr for DummyTracingKey { - const TRACING_KEY: &'static str = "test_notification_stream"; +impl NotificationSender { + /// Send out a notification to all subscribers that a new payload is available for a + /// block. + pub fn notify( + &self, + payload: impl FnOnce() -> Result, + ) -> Result<(), Error> + where + Payload: Clone, + { + self.hub.send(payload) } +} - type StringStream = NotificationStream; - - #[test] - fn notification_channel_simple() { - let (sender, stream) = StringStream::channel(); +impl Clone for NotificationSender { + fn clone(&self) -> Self { + Self { hub: self.hub.clone() } + } +} - let test_payload = String::from("test payload"); - let closure_payload = test_payload.clone(); +impl Unpin for NotificationReceiver {} - // Create a future to receive a single notification - // from the stream and verify its payload. - let future = stream.subscribe().take(1).for_each(move |payload| { - let test_payload = closure_payload.clone(); - async move { - assert_eq!(payload, test_payload); - } - }); +impl Stream for NotificationReceiver { + type Item = Payload; - // Send notification. - let r: std::result::Result<(), ()> = sender.notify(|| Ok(test_payload)); - r.unwrap(); + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + Pin::new(&mut self.get_mut().receiver).poll_next(cx) + } +} - // Run receiver future. - tokio_test::block_on(future); +impl FusedStream for NotificationReceiver { + fn is_terminated(&self) -> bool { + self.receiver.is_terminated() } } diff --git a/client/utils/src/notification/registry.rs b/client/utils/src/notification/registry.rs new file mode 100644 index 000000000000..ebe41452a567 --- /dev/null +++ b/client/utils/src/notification/registry.rs @@ -0,0 +1,63 @@ +// This file is part of Substrate. + +// Copyright (C) 2021-2022 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 . + +use std::collections::HashSet; + +use crate::{ + id_sequence::SeqID, + pubsub::{Dispatch, Subscribe, Unsubscribe}, +}; + +/// The shared structure to keep track on subscribers. +#[derive(Debug, Default)] +pub(super) struct Registry { + pub(super) subscribers: HashSet, +} + +impl Subscribe<()> for Registry { + fn subscribe(&mut self, _subs_key: (), subs_id: SeqID) { + self.subscribers.insert(subs_id); + } +} +impl Unsubscribe for Registry { + fn unsubscribe(&mut self, subs_id: SeqID) { + self.subscribers.remove(&subs_id); + } +} + +impl Dispatch for Registry +where + MakePayload: FnOnce() -> Result, + Payload: Clone, +{ + type Item = Payload; + type Ret = Result<(), Error>; + + fn dispatch(&mut self, make_payload: MakePayload, mut dispatch: F) -> Self::Ret + where + F: FnMut(&SeqID, Self::Item), + { + if !self.subscribers.is_empty() { + let payload = make_payload()?; + for subs_id in &self.subscribers { + dispatch(subs_id, payload.clone()); + } + } + Ok(()) + } +} diff --git a/client/utils/src/notification/tests.rs b/client/utils/src/notification/tests.rs new file mode 100644 index 000000000000..a001fa7e89e9 --- /dev/null +++ b/client/utils/src/notification/tests.rs @@ -0,0 +1,52 @@ +// This file is part of Substrate. + +// Copyright (C) 2021-2022 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 . + +use super::*; +use futures::StreamExt; + +#[derive(Clone)] +pub struct DummyTracingKey; +impl TracingKeyStr for DummyTracingKey { + const TRACING_KEY: &'static str = "test_notification_stream"; +} + +type StringStream = NotificationStream; + +#[test] +fn notification_channel_simple() { + let (sender, stream) = StringStream::channel(); + + let test_payload = String::from("test payload"); + let closure_payload = test_payload.clone(); + + // Create a future to receive a single notification + // from the stream and verify its payload. + let future = stream.subscribe().take(1).for_each(move |payload| { + let test_payload = closure_payload.clone(); + async move { + assert_eq!(payload, test_payload); + } + }); + + // Send notification. + let r: std::result::Result<(), ()> = sender.notify(|| Ok(test_payload)); + r.unwrap(); + + // Run receiver future. + tokio_test::block_on(future); +} diff --git a/client/utils/src/pubsub.rs b/client/utils/src/pubsub.rs new file mode 100644 index 000000000000..c8e51e3494b9 --- /dev/null +++ b/client/utils/src/pubsub.rs @@ -0,0 +1,263 @@ +// This file is part of Substrate. + +// Copyright (C) 2021-2022 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 . + +//! Provides means to implement a typical Pub/Sub mechanism. +//! +//! This module provides a type [`Hub`] which can be used both to subscribe, +//! and to send the broadcast messages. +//! +//! The [`Hub`] type is parametrized by two other types: +//! - `Message` — the type of a message that shall be delivered to the subscribers; +//! - `Registry` — implementation of the subscription/dispatch logic. +//! +//! A Registry is implemented by defining the following traits: +//! - [`Subscribe`]; +//! - [`Dispatch`]; +//! - [`Unsubscribe`]. +//! +//! As a result of subscription `Hub::subscribe` method returns an instance of +//! [`Receiver`]. That can be used as a [`Stream`] to receive the messages. +//! Upon drop the [`Receiver`] shall unregister itself from the `Hub`. + +use std::{ + collections::HashMap, + pin::Pin, + sync::{Arc, Weak}, + task::{Context, Poll}, +}; + +use futures::stream::{FusedStream, Stream}; +// use parking_lot::Mutex; +use parking_lot::ReentrantMutex; +use std::cell::RefCell; + +use crate::{ + id_sequence::SeqID, + mpsc::{TracingUnboundedReceiver, TracingUnboundedSender}, +}; + +#[cfg(test)] +mod tests; + +/// Unsubscribe: unregisters a previously created subscription. +pub trait Unsubscribe { + /// Remove all registrations of the subscriber with ID `subs_id`. + fn unsubscribe(&mut self, subs_id: SeqID); +} + +/// Subscribe using a key of type `K` +pub trait Subscribe { + /// Register subscriber with the ID `subs_id` as having interest to the key `K`. + fn subscribe(&mut self, subs_key: K, subs_id: SeqID); +} + +/// Dispatch a message of type `M`. +pub trait Dispatch { + /// The type of the that shall be sent through the channel as a result of such dispatch. + type Item; + /// The type returned by the `dispatch`-method. + type Ret; + + /// Dispatch the message of type `M`. + /// + /// The implementation is given an instance of `M` and is supposed to invoke `dispatch` for + /// each matching subscriber, with an argument of type `Self::Item` matching that subscriber. + /// + /// Note that this does not have to be of the same type with the item that will be sent through + /// to the subscribers. The subscribers will receive a message of type `Self::Item`. + fn dispatch(&mut self, message: M, dispatch: F) -> Self::Ret + where + F: FnMut(&SeqID, Self::Item); +} + +/// A subscription hub. +/// +/// Does the subscription and dispatch. +/// The exact subscription and routing behaviour is to be implemented by the Registry (of type `R`). +/// The Hub under the hood uses the channel defined in `crate::mpsc` module. +#[derive(Debug)] +pub struct Hub { + tracing_key: &'static str, + shared: Arc>>>, +} + +/// The receiving side of the subscription. +/// +/// The messages are delivered as items of a [`Stream`]. +/// Upon drop this receiver unsubscribes itself from the [`Hub`]. +#[derive(Debug)] +pub struct Receiver +where + R: Unsubscribe, +{ + rx: TracingUnboundedReceiver, + + shared: Weak>>>, + subs_id: SeqID, +} + +#[derive(Debug)] +struct Shared { + id_sequence: crate::id_sequence::IDSequence, + registry: R, + sinks: HashMap>, +} + +impl Hub +where + R: Unsubscribe, +{ + /// Provide access to the registry (for test purposes). + pub fn map_registry_for_tests(&self, map: MapF) -> Ret + where + MapF: FnOnce(&R) -> Ret, + { + let shared_locked = self.shared.lock(); + let shared_borrowed = shared_locked.borrow(); + map(&shared_borrowed.registry) + } +} + +impl Drop for Receiver +where + R: Unsubscribe, +{ + fn drop(&mut self) { + if let Some(shared) = self.shared.upgrade() { + shared.lock().borrow_mut().unsubscribe(self.subs_id); + } + } +} + +impl Hub { + /// Create a new instance of Hub (with default value for the Registry). + pub fn new(tracing_key: &'static str) -> Self + where + R: Default, + { + Self::new_with_registry(tracing_key, Default::default()) + } + + /// Create a new instance of Hub over the initialized Registry. + pub fn new_with_registry(tracing_key: &'static str, registry: R) -> Self { + let shared = + Shared { registry, sinks: Default::default(), id_sequence: Default::default() }; + let shared = Arc::new(ReentrantMutex::new(RefCell::new(shared))); + Self { tracing_key, shared } + } + + /// Subscribe to this Hub using the `subs_key: K`. + /// + /// A subscription with a key `K` is possible if the Registry implements `Subscribe`. + pub fn subscribe(&self, subs_key: K) -> Receiver + where + R: Subscribe + Unsubscribe, + { + let shared_locked = self.shared.lock(); + let mut shared_borrowed = shared_locked.borrow_mut(); + + let subs_id = shared_borrowed.id_sequence.next_id(); + + // The order (registry.subscribe then sinks.insert) is important here: + // assuming that `Subscribe::subscribe` can panic, it is better to at least + // have the sink disposed. + shared_borrowed.registry.subscribe(subs_key, subs_id); + + let (tx, rx) = crate::mpsc::tracing_unbounded(self.tracing_key); + assert!(shared_borrowed.sinks.insert(subs_id, tx).is_none(), "Used IDSequence to create another ID. Should be unique until u64 is overflowed. Should be unique."); + + Receiver { shared: Arc::downgrade(&self.shared), subs_id, rx } + } + + /// Send the message produced with `Trigger`. + /// + /// This is possible if the registry implements `Dispatch`. + pub fn send(&self, trigger: Trigger) -> >::Ret + where + R: Dispatch, + { + let shared_locked = self.shared.lock(); + let mut shared_borrowed = shared_locked.borrow_mut(); + let (registry, sinks) = shared_borrowed.get_mut(); + + let dispatch_result = registry.dispatch(trigger, |subs_id, item| { + if let Some(tx) = sinks.get_mut(&subs_id) { + if let Err(send_err) = tx.unbounded_send(item) { + log::warn!("Sink with SubsID = {} failed to perform unbounded_send: {} ({} as Dispatch<{}, Item = {}>::dispatch(...))", subs_id, send_err, std::any::type_name::(), + std::any::type_name::(), + std::any::type_name::()); + } + } else { + log::warn!( + "No Sink for SubsID = {} ({} as Dispatch<{}, Item = {}>::dispatch(...))", + subs_id, + std::any::type_name::(), + std::any::type_name::(), + std::any::type_name::(), + ); + } + }); + + dispatch_result + } +} + +impl Shared { + fn get_mut(&mut self) -> (&mut R, &mut HashMap>) { + (&mut self.registry, &mut self.sinks) + } + + fn unsubscribe(&mut self, subs_id: SeqID) + where + R: Unsubscribe, + { + // The order (sinks.remove then registry.unsubscribe) is important here: + // assuming that `Unsubscribe::unsubscribe` can panic, it is better to at least + // have the sink disposed. + self.sinks.remove(&subs_id); + self.registry.unsubscribe(subs_id); + } +} + +impl Clone for Hub { + fn clone(&self) -> Self { + Self { tracing_key: self.tracing_key, shared: self.shared.clone() } + } +} + +impl Unpin for Receiver where R: Unsubscribe {} + +impl Stream for Receiver +where + R: Unsubscribe, +{ + type Item = M; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + Pin::new(&mut self.get_mut().rx).poll_next(cx) + } +} + +impl FusedStream for Receiver +where + R: Unsubscribe, +{ + fn is_terminated(&self) -> bool { + self.rx.is_terminated() + } +} diff --git a/client/utils/src/pubsub/tests.rs b/client/utils/src/pubsub/tests.rs new file mode 100644 index 000000000000..12945c0d886b --- /dev/null +++ b/client/utils/src/pubsub/tests.rs @@ -0,0 +1,123 @@ +// This file is part of Substrate. + +// Copyright (C) 2020-2022 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 . + +use futures::StreamExt; +use tokio_test::block_on; + +use super::*; + +mod normal_operation; +mod panicking_registry; + +const TK: &str = "a_tracing_key"; + +type Message = u64; +type TestHub = Hub; +type TestReceiver = Receiver; + +#[derive(Default)] +struct Registry { + subscribers: HashMap, +} + +struct SubsKey { + _receiver: Option, + panic: SubsKeyPanic, +} + +impl SubsKey { + fn new() -> Self { + Self { _receiver: None, panic: SubsKeyPanic::None } + } + fn with_receiver(self, receiver: TestReceiver) -> Self { + Self { _receiver: Some(receiver), ..self } + } + fn with_panic(self, panic: SubsKeyPanic) -> Self { + Self { panic, ..self } + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum SubsKeyPanic { + None, + + OnSubscribePanicBefore, + OnSubscribePanicAfter, + + OnUnsubscribePanicBefore, + OnUnsubscribePanicAfter, + + OnDispatchPanicBefore, + OnDispatchPanicAfter, +} + +impl Hub { + fn subs_count(&self) -> usize { + self.map_registry_for_tests(|r| r.subscribers.len()) + } + fn sink_count(&self) -> usize { + self.shared.lock().borrow().sinks.len() + } +} + +impl Subscribe for Registry { + fn subscribe(&mut self, subs_key: SubsKey, subs_id: SeqID) { + let sk_panic = subs_key.panic; + + if sk_panic == SubsKeyPanic::OnSubscribePanicBefore { + panic!("on-subscribe-panic-before") + } + self.subscribers.insert(subs_id, subs_key); + if sk_panic == SubsKeyPanic::OnSubscribePanicAfter { + panic!("on-subscribe-panic-after") + } + } +} +impl Unsubscribe for Registry { + fn unsubscribe(&mut self, subs_id: SeqID) { + let sk_panic = + self.subscribers.get(&subs_id).map(|sk| sk.panic).unwrap_or(SubsKeyPanic::None); + + if sk_panic == SubsKeyPanic::OnUnsubscribePanicBefore { + panic!("on-unsubscribe-panic-before") + } + self.subscribers.remove(&subs_id); + if sk_panic == SubsKeyPanic::OnUnsubscribePanicAfter { + panic!("on-unsubscribe-panic-after") + } + } +} +impl Dispatch for Registry { + type Item = Message; + type Ret = (); + + fn dispatch(&mut self, message: Message, mut dispatch: F) -> Self::Ret + where + F: FnMut(&SeqID, Self::Item), + { + self.subscribers.iter().for_each(|(id, subs_key)| { + if subs_key.panic == SubsKeyPanic::OnDispatchPanicBefore { + panic!("on-dispatch-panic-before") + } + dispatch(id, message); + if subs_key.panic == SubsKeyPanic::OnDispatchPanicAfter { + panic!("on-dispatch-panic-after") + } + }); + } +} diff --git a/client/utils/src/pubsub/tests/normal_operation.rs b/client/utils/src/pubsub/tests/normal_operation.rs new file mode 100644 index 000000000000..a13c718d74a8 --- /dev/null +++ b/client/utils/src/pubsub/tests/normal_operation.rs @@ -0,0 +1,88 @@ +// This file is part of Substrate. + +// Copyright (C) 2020-2022 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 . + +use super::*; + +#[test] +fn positive_rx_receives_relevant_messages_and_terminates_upon_hub_drop() { + block_on(async { + let hub = TestHub::new(TK); + assert_eq!(hub.subs_count(), 0); + + // No subscribers yet. That message is not supposed to get to anyone. + hub.send(0); + + let mut rx_01 = hub.subscribe(SubsKey::new()); + assert_eq!(hub.subs_count(), 1); + + // That message is sent after subscription. Should be delivered into rx_01. + hub.send(1); + assert_eq!(Some(1), rx_01.next().await); + + // Hub is disposed. The rx_01 should be over after that. + std::mem::drop(hub); + + assert!(!rx_01.is_terminated()); + assert_eq!(None, rx_01.next().await); + assert!(rx_01.is_terminated()); + }); +} + +#[test] +fn positive_subs_count_is_correct_upon_drop_of_rxs() { + block_on(async { + let hub = TestHub::new(TK); + assert_eq!(hub.subs_count(), 0); + + let rx_01 = hub.subscribe(SubsKey::new()); + assert_eq!(hub.subs_count(), 1); + let rx_02 = hub.subscribe(SubsKey::new()); + assert_eq!(hub.subs_count(), 2); + + std::mem::drop(rx_01); + assert_eq!(hub.subs_count(), 1); + std::mem::drop(rx_02); + assert_eq!(hub.subs_count(), 0); + }); +} + +#[test] +fn positive_subs_count_is_correct_upon_drop_of_rxs_on_cloned_hubs() { + block_on(async { + let hub_01 = TestHub::new(TK); + let hub_02 = hub_01.clone(); + assert_eq!(hub_01.subs_count(), 0); + assert_eq!(hub_02.subs_count(), 0); + + let rx_01 = hub_02.subscribe(SubsKey::new()); + assert_eq!(hub_01.subs_count(), 1); + assert_eq!(hub_02.subs_count(), 1); + + let rx_02 = hub_02.subscribe(SubsKey::new()); + assert_eq!(hub_01.subs_count(), 2); + assert_eq!(hub_02.subs_count(), 2); + + std::mem::drop(rx_01); + assert_eq!(hub_01.subs_count(), 1); + assert_eq!(hub_02.subs_count(), 1); + + std::mem::drop(rx_02); + assert_eq!(hub_01.subs_count(), 0); + assert_eq!(hub_02.subs_count(), 0); + }); +} diff --git a/client/utils/src/pubsub/tests/panicking_registry.rs b/client/utils/src/pubsub/tests/panicking_registry.rs new file mode 100644 index 000000000000..26ce63bd51b0 --- /dev/null +++ b/client/utils/src/pubsub/tests/panicking_registry.rs @@ -0,0 +1,248 @@ +// This file is part of Substrate. + +// Copyright (C) 2020-2022 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 . + +use super::*; + +use std::panic::{catch_unwind, AssertUnwindSafe}; + +fn assert_hub_props(hub: &TestHub, sinks_count: usize, subs_count: usize) { + assert_eq!(hub.sink_count(), sinks_count); + assert_eq!(hub.subs_count(), subs_count); +} + +#[test] +fn t01() { + let hub = TestHub::new(TK); + assert_hub_props(&hub, 0, 0); + + let rx_01 = hub.subscribe(SubsKey::new()); + assert_hub_props(&hub, 1, 1); + + std::mem::drop(rx_01); + assert_hub_props(&hub, 0, 0); +} + +#[test] +fn t02() { + block_on(async { + // Create a Hub + let hub = TestHub::new(TK); + assert_hub_props(&hub, 0, 0); + + // Subscribe rx-01 + let rx_01 = hub.subscribe(SubsKey::new()); + assert_hub_props(&hub, 1, 1); + + // Subscribe rx-02 so that its unsubscription will lead to an attempt to drop rx-01 in the + // middle of unsubscription of rx-02 + let rx_02 = hub.subscribe(SubsKey::new().with_receiver(rx_01)); + assert_hub_props(&hub, 2, 2); + + // Subscribe rx-03 in order to see that it will receive messages after the unclean + // unsubscription + let mut rx_03 = hub.subscribe(SubsKey::new()); + assert_hub_props(&hub, 3, 3); + + // drop rx-02 leads to an attempt to unsubscribe rx-01 + assert!(catch_unwind(AssertUnwindSafe(move || { + std::mem::drop(rx_02); + })) + .is_err()); + + // One of the rxes could not unsubscribe + assert_hub_props(&hub, 2, 2); + + // Subscribe rx-04 in order to see that it will receive messages after the unclean + // unsubscription + let mut rx_04 = hub.subscribe(SubsKey::new()); + assert_hub_props(&hub, 3, 3); + + hub.send(2); + + // The messages are still received + assert_eq!(rx_03.next().await, Some(2)); + assert_eq!(rx_04.next().await, Some(2)); + + // Perform a clean unsubscription + std::mem::drop(rx_04); + + hub.send(3); + + // The messages are still received + assert_eq!(rx_03.next().await, Some(3)); + + std::mem::drop(rx_03); + + hub.send(4); + + // The stuck subscription is still there + assert_hub_props(&hub, 1, 1); + }); +} + +async fn add_some_subscribers_see_that_messages_are_delivered_and_unsubscribe(hub: &TestHub) { + let rx_01 = hub.subscribe(SubsKey::new()); + let rx_02 = hub.subscribe(SubsKey::new()); + + hub.send(1); + hub.send(2); + hub.send(3); + + assert_eq!(rx_01.take(3).collect::>().await, vec![1, 2, 3]); + + hub.send(4); + hub.send(5); + hub.send(6); + + assert_eq!(rx_02.take(6).collect::>().await, vec![1, 2, 3, 4, 5, 6]); +} + +#[test] +fn t03() { + block_on(async { + // Create a Hub + let hub = TestHub::new(TK); + assert_hub_props(&hub, 0, 0); + add_some_subscribers_see_that_messages_are_delivered_and_unsubscribe(&hub).await; + assert_hub_props(&hub, 0, 0); + + assert!(catch_unwind(AssertUnwindSafe( + || hub.subscribe(SubsKey::new().with_panic(SubsKeyPanic::OnSubscribePanicBefore)) + )) + .is_err()); + + assert_hub_props(&hub, 0, 0); + add_some_subscribers_see_that_messages_are_delivered_and_unsubscribe(&hub).await; + assert_hub_props(&hub, 0, 0); + }); +} + +#[test] +fn t04() { + block_on(async { + let hub = TestHub::new(TK); + + assert_hub_props(&hub, 0, 0); + add_some_subscribers_see_that_messages_are_delivered_and_unsubscribe(&hub).await; + assert_hub_props(&hub, 0, 0); + + assert!(catch_unwind(AssertUnwindSafe( + || hub.subscribe(SubsKey::new().with_panic(SubsKeyPanic::OnSubscribePanicAfter)) + )) + .is_err()); + + // the registry has panicked after it has added a subs-id into its internal storage — the + // sinks do not leak, although the subscriptions storage contains some garbage + assert_hub_props(&hub, 0, 1); + add_some_subscribers_see_that_messages_are_delivered_and_unsubscribe(&hub).await; + assert_hub_props(&hub, 0, 1); + }) +} + +#[test] +fn t05() { + block_on(async { + let hub = TestHub::new(TK); + + assert_hub_props(&hub, 0, 0); + add_some_subscribers_see_that_messages_are_delivered_and_unsubscribe(&hub).await; + assert_hub_props(&hub, 0, 0); + + let rx_01 = + hub.subscribe(SubsKey::new().with_panic(SubsKeyPanic::OnUnsubscribePanicBefore)); + + assert_hub_props(&hub, 1, 1); + add_some_subscribers_see_that_messages_are_delivered_and_unsubscribe(&hub).await; + assert_hub_props(&hub, 1, 1); + + assert!(catch_unwind(AssertUnwindSafe(move || std::mem::drop(rx_01))).is_err()); + + // the registry has panicked on-unsubscribe before it removed the subs-id from its internal + // storage — the sinks do not leak, although the subscriptions storage contains some garbage + assert_hub_props(&hub, 0, 1); + add_some_subscribers_see_that_messages_are_delivered_and_unsubscribe(&hub).await; + assert_hub_props(&hub, 0, 1); + }) +} + +#[test] +fn t06() { + block_on(async { + let hub = TestHub::new(TK); + + assert_hub_props(&hub, 0, 0); + add_some_subscribers_see_that_messages_are_delivered_and_unsubscribe(&hub).await; + assert_hub_props(&hub, 0, 0); + + let rx_01 = hub.subscribe(SubsKey::new().with_panic(SubsKeyPanic::OnUnsubscribePanicAfter)); + + assert_hub_props(&hub, 1, 1); + add_some_subscribers_see_that_messages_are_delivered_and_unsubscribe(&hub).await; + assert_hub_props(&hub, 1, 1); + + assert!(catch_unwind(AssertUnwindSafe(move || std::mem::drop(rx_01))).is_err()); + + // the registry has panicked on-unsubscribe after it removed the subs-id from its internal + // storage — the sinks do not leak, the subscriptions storage does not contain any garbage + assert_hub_props(&hub, 0, 0); + add_some_subscribers_see_that_messages_are_delivered_and_unsubscribe(&hub).await; + assert_hub_props(&hub, 0, 0); + }) +} + +#[test] +fn t07() { + block_on(async { + let hub = TestHub::new(TK); + + assert_hub_props(&hub, 0, 0); + add_some_subscribers_see_that_messages_are_delivered_and_unsubscribe(&hub).await; + assert_hub_props(&hub, 0, 0); + + let rx_01 = hub.subscribe(SubsKey::new().with_panic(SubsKeyPanic::OnDispatchPanicBefore)); + assert_hub_props(&hub, 1, 1); + assert!(catch_unwind(AssertUnwindSafe(|| hub.send(1))).is_err()); + assert_hub_props(&hub, 1, 1); + + std::mem::drop(rx_01); + assert_hub_props(&hub, 0, 0); + add_some_subscribers_see_that_messages_are_delivered_and_unsubscribe(&hub).await; + assert_hub_props(&hub, 0, 0); + }) +} + +#[test] +fn t08() { + block_on(async { + let hub = TestHub::new(TK); + + assert_hub_props(&hub, 0, 0); + add_some_subscribers_see_that_messages_are_delivered_and_unsubscribe(&hub).await; + assert_hub_props(&hub, 0, 0); + + let rx_01 = hub.subscribe(SubsKey::new().with_panic(SubsKeyPanic::OnDispatchPanicAfter)); + assert_hub_props(&hub, 1, 1); + assert!(catch_unwind(AssertUnwindSafe(|| hub.send(1))).is_err()); + assert_hub_props(&hub, 1, 1); + + std::mem::drop(rx_01); + assert_hub_props(&hub, 0, 0); + add_some_subscribers_see_that_messages_are_delivered_and_unsubscribe(&hub).await; + assert_hub_props(&hub, 0, 0); + }) +} From 66ff3a566e6ee7d85f30fc11d45047bd41854b9e Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Mon, 28 Feb 2022 21:54:48 +0000 Subject: [PATCH 539/695] Bring back MaxNominations as a metadata constant (#10947) --- frame/staking/src/pallet/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 2be75752f101..f53e6b50d7a3 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -96,6 +96,7 @@ pub mod pallet { >; /// Maximum number of nominations per nominator. + #[pallet::constant] type MaxNominations: Get; /// Tokens have been minted and are unused for validator-reward. From 1fabe26f239166e210f723756812d7eca069e41e Mon Sep 17 00:00:00 2001 From: driemworks Date: Mon, 28 Feb 2022 19:19:35 -0500 Subject: [PATCH 540/695] chain ext: parse params and call transfer func --- bin/node-template/runtime/src/lib.rs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index fdaa660600d4..9b5952569cf3 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -204,6 +204,7 @@ impl frame_system::Config for Runtime { type BlockLength = RuntimeBlockLength; /// The identifier used to distinguish between accounts. type AccountId = AccountId; + // type AccountId = From<[u8; 32]>; /// The aggregated dispatch type that is available for extrinsics. type Call = Call; /// The lookup mechanism to get account ID from whatever is passed in dispatchers. @@ -816,10 +817,14 @@ use pallet_contracts::chain_extension::{ UncheckedFrom, }; use sp_runtime::DispatchError; +use frame_system::{ + self as system, +}; pub struct IrisExtension; impl ChainExtension for IrisExtension { + fn call( func_id: u32, env: Environment, @@ -831,10 +836,14 @@ impl ChainExtension for IrisExtension { match func_id { 1 => { let mut env = env.buf_in_buf_out(); - let arg: [u8; 32] = env.read_as()?; - // call to transfer assets should go here - // crate::IrisAssets::trandsfer(&arg); - // let random_slice = random_seed.encode(); + let caller_account: AccountId = env.read_as()?; + let target: AccountId = env.read_as()?; + let asset_id: u32 = env.read_as()?; + let amount: u64 = env.read_as()?; + let origin: Origin = system::RawOrigin::Signed(caller_account).into(); + crate::Iris::transfer_asset( + origin, sp_runtime::MultiAddress::Id(target), asset_id, amount, + )?; trace!( target: "runtime", "[ChainExtension]|call|func_id:{:}", @@ -849,7 +858,7 @@ impl ChainExtension for IrisExtension { return Err(DispatchError::Other("Unimplemented func_id")) } } - Ok(RetVal::Converging(0)) + Ok(RetVal::Converging(func_id)) } fn enabled() -> bool { From f90dfc63a41f27ed36ba482582d3a913a61217ff Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Mar 2022 10:22:10 +0100 Subject: [PATCH 541/695] Bump futures from 0.3.16 to 0.3.19 (#10930) Bumps [futures](https://github.com/rust-lang/futures-rs) from 0.3.16 to 0.3.19. - [Release notes](https://github.com/rust-lang/futures-rs/releases) - [Changelog](https://github.com/rust-lang/futures-rs/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/futures-rs/compare/0.3.16...0.3.19) --- updated-dependencies: - dependency-name: futures dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 194 +++++++++--------- bin/node/bench/Cargo.toml | 2 +- bin/node/cli/Cargo.toml | 4 +- bin/node/executor/Cargo.toml | 2 +- bin/node/testing/Cargo.toml | 2 +- client/api/Cargo.toml | 2 +- client/authority-discovery/Cargo.toml | 2 +- client/basic-authorship/Cargo.toml | 2 +- client/beefy/rpc/Cargo.toml | 2 +- client/cli/Cargo.toml | 2 +- client/consensus/aura/Cargo.toml | 2 +- client/consensus/babe/Cargo.toml | 2 +- client/consensus/babe/rpc/Cargo.toml | 2 +- client/consensus/common/Cargo.toml | 2 +- client/consensus/manual-seal/Cargo.toml | 2 +- client/consensus/pow/Cargo.toml | 2 +- client/consensus/slots/Cargo.toml | 2 +- client/finality-grandpa/Cargo.toml | 2 +- client/informant/Cargo.toml | 2 +- client/network-gossip/Cargo.toml | 2 +- client/network/Cargo.toml | 2 +- client/network/test/Cargo.toml | 2 +- client/offchain/Cargo.toml | 2 +- client/peerset/Cargo.toml | 2 +- client/rpc-api/Cargo.toml | 2 +- client/rpc-servers/Cargo.toml | 2 +- client/rpc/Cargo.toml | 2 +- client/service/Cargo.toml | 2 +- client/service/test/Cargo.toml | 2 +- client/telemetry/Cargo.toml | 2 +- client/transaction-pool/Cargo.toml | 2 +- client/transaction-pool/api/Cargo.toml | 2 +- client/utils/Cargo.toml | 2 +- primitives/api/test/Cargo.toml | 2 +- primitives/blockchain/Cargo.toml | 2 +- primitives/consensus/common/Cargo.toml | 4 +- primitives/core/Cargo.toml | 2 +- primitives/inherents/Cargo.toml | 2 +- primitives/io/Cargo.toml | 2 +- primitives/keystore/Cargo.toml | 2 +- test-utils/client/Cargo.toml | 2 +- test-utils/runtime/Cargo.toml | 2 +- test-utils/runtime/client/Cargo.toml | 2 +- .../runtime/transaction-pool/Cargo.toml | 2 +- utils/frame/rpc/support/Cargo.toml | 2 +- utils/frame/rpc/system/Cargo.toml | 2 +- 46 files changed, 144 insertions(+), 144 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index da474bdcfb21..e6ae5a1fea5f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -483,7 +483,7 @@ version = "4.0.0-dev" dependencies = [ "beefy-primitives", "fnv", - "futures 0.3.16", + "futures 0.3.19", "log 0.4.14", "parity-scale-codec", "parking_lot 0.12.0", @@ -514,7 +514,7 @@ version = "4.0.0-dev" dependencies = [ "beefy-gadget", "beefy-primitives", - "futures 0.3.16", + "futures 0.3.19", "jsonrpc-core", "jsonrpc-core-client", "jsonrpc-derive", @@ -1301,7 +1301,7 @@ dependencies = [ "clap 2.34.0", "criterion-plot", "csv", - "futures 0.3.16", + "futures 0.3.19", "itertools", "lazy_static", "num-traits", @@ -1955,7 +1955,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e43f2f1833d64e33f15592464d6fdd70f349dda7b1a53088eb83cd94014008c5" dependencies = [ - "futures 0.3.16", + "futures 0.3.19", ] [[package]] @@ -2015,7 +2015,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9def033d8505edf199f6a5d07aa7e6d2d6185b164293b77f0efd108f4f3e11d" dependencies = [ "either", - "futures 0.3.16", + "futures 0.3.19", "futures-timer", "log 0.4.14", "num-traits", @@ -2429,9 +2429,9 @@ checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" [[package]] name = "futures" -version = "0.3.16" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adc00f486adfc9ce99f77d717836f0c5aa84965eb0b4f051f4e83f7cab53f8b" +checksum = "28560757fe2bb34e79f907794bb6b22ae8b0e5c669b638a1132f2592b19035b4" dependencies = [ "futures-channel", "futures-core", @@ -2460,9 +2460,9 @@ checksum = "d0c8ff0461b82559810cdccfde3215c3f373807f5e5232b71479bff7bb2583d7" [[package]] name = "futures-executor" -version = "0.3.16" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d0d535a57b87e1ae31437b892713aee90cd2d7b0ee48727cd11fc72ef54761c" +checksum = "29d6d2ff5bb10fb95c85b8ce46538a2e5f5e7fdc755623a7d4529ab8a4ed9d2a" dependencies = [ "futures-core", "futures-task", @@ -3054,7 +3054,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a6d52908d4ea4ab2bc22474ba149bf1011c8e2c3ebc1ff593ae28ac44f494b6" dependencies = [ "async-io", - "futures 0.3.16", + "futures 0.3.19", "futures-lite", "if-addrs", "ipnet", @@ -3209,7 +3209,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2b99d4207e2a04fb4581746903c2bb7eb376f88de9c699d0f3e10feeac0cd3a" dependencies = [ "derive_more", - "futures 0.3.16", + "futures 0.3.19", "hyper 0.14.16", "hyper-tls", "jsonrpc-core", @@ -3228,7 +3228,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14f7f76aef2d054868398427f6c54943cf3d1caa9a7ec7d0c38d69df97a965eb" dependencies = [ - "futures 0.3.16", + "futures 0.3.19", "futures-executor", "futures-util", "log 0.4.14", @@ -3243,7 +3243,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b51da17abecbdab3e3d4f26b01c5ec075e88d3abe3ab3b05dc9aa69392764ec0" dependencies = [ - "futures 0.3.16", + "futures 0.3.19", "jsonrpc-client-transports", ] @@ -3265,7 +3265,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1dea6e07251d9ce6a552abfb5d7ad6bc290a4596c8dcc3d795fae2bbdc1f3ff" dependencies = [ - "futures 0.3.16", + "futures 0.3.19", "hyper 0.14.16", "jsonrpc-core", "jsonrpc-server-utils", @@ -3281,7 +3281,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "382bb0206323ca7cda3dcd7e245cea86d37d02457a02a975e3378fb149a48845" dependencies = [ - "futures 0.3.16", + "futures 0.3.19", "jsonrpc-core", "jsonrpc-server-utils", "log 0.4.14", @@ -3296,7 +3296,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240f87695e6c6f62fb37f05c02c04953cf68d6408b8c1c89de85c7a0125b1011" dependencies = [ - "futures 0.3.16", + "futures 0.3.19", "jsonrpc-core", "lazy_static", "log 0.4.14", @@ -3312,7 +3312,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa4fdea130485b572c39a460d50888beb00afb3e35de23ccd7fad8ff19f0e0d4" dependencies = [ "bytes 1.1.0", - "futures 0.3.16", + "futures 0.3.19", "globset", "jsonrpc-core", "lazy_static", @@ -3329,7 +3329,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f892c7d766369475ab7b0669f417906302d7c0fb521285c0a0c92e52e7c8e946" dependencies = [ - "futures 0.3.16", + "futures 0.3.19", "jsonrpc-core", "jsonrpc-server-utils", "log 0.4.14", @@ -3367,7 +3367,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3303cdf246e6ab76e2866fb3d9acb6c76a068b1b28bd923a1b7a8122257ad7b5" dependencies = [ - "futures 0.3.16", + "futures 0.3.19", "http", "jsonrpsee-core", "jsonrpsee-types 0.8.0", @@ -3470,7 +3470,7 @@ dependencies = [ "arrayvec 0.7.1", "async-trait", "fnv", - "futures 0.3.16", + "futures 0.3.19", "http", "jsonrpsee-types 0.4.1", "log 0.4.14", @@ -3669,7 +3669,7 @@ checksum = "3bec54343492ba5940a6c555e512c6721139835d28c59bc22febece72dfd0d9d" dependencies = [ "atomic", "bytes 1.1.0", - "futures 0.3.16", + "futures 0.3.19", "lazy_static", "libp2p-core", "libp2p-deflate", @@ -3713,7 +3713,7 @@ dependencies = [ "ed25519-dalek", "either", "fnv", - "futures 0.3.16", + "futures 0.3.19", "futures-timer", "lazy_static", "libsecp256k1", @@ -3743,7 +3743,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51a800adb195f33de63f4b17b63fe64cfc23bf2c6a0d3d0d5321328664e65197" dependencies = [ "flate2", - "futures 0.3.16", + "futures 0.3.19", "libp2p-core", ] @@ -3754,7 +3754,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb8f89d15cb6e3c5bc22afff7513b11bab7856f2872d3cfba86f7f63a06bc498" dependencies = [ "async-std-resolver", - "futures 0.3.16", + "futures 0.3.19", "libp2p-core", "log 0.4.14", "smallvec 1.7.0", @@ -3769,7 +3769,7 @@ checksum = "aab3d7210901ea51b7bae2b581aa34521797af8c4ec738c980bda4a06434067f" dependencies = [ "cuckoofilter", "fnv", - "futures 0.3.16", + "futures 0.3.19", "libp2p-core", "libp2p-swarm", "log 0.4.14", @@ -3790,7 +3790,7 @@ dependencies = [ "byteorder", "bytes 1.1.0", "fnv", - "futures 0.3.16", + "futures 0.3.19", "hex_fmt", "libp2p-core", "libp2p-swarm", @@ -3811,7 +3811,7 @@ version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cca1275574183f288ff8b72d535d5ffa5ea9292ef7829af8b47dcb197c7b0dcd" dependencies = [ - "futures 0.3.16", + "futures 0.3.19", "libp2p-core", "libp2p-swarm", "log 0.4.14", @@ -3833,7 +3833,7 @@ dependencies = [ "bytes 1.1.0", "either", "fnv", - "futures 0.3.16", + "futures 0.3.19", "libp2p-core", "libp2p-swarm", "log 0.4.14", @@ -3857,7 +3857,7 @@ dependencies = [ "async-io", "data-encoding", "dns-parser", - "futures 0.3.16", + "futures 0.3.19", "if-watch", "lazy_static", "libp2p-core", @@ -3891,7 +3891,7 @@ checksum = "7f2cd64ef597f40e14bfce0497f50ecb63dd6d201c61796daeb4227078834fbf" dependencies = [ "asynchronous-codec 0.6.0", "bytes 1.1.0", - "futures 0.3.16", + "futures 0.3.19", "libp2p-core", "log 0.4.14", "nohash-hasher", @@ -3909,7 +3909,7 @@ checksum = "a8772c7a99088221bb7ca9c5c0574bf55046a7ab4c319f3619b275f28c8fb87a" dependencies = [ "bytes 1.1.0", "curve25519-dalek 3.0.2", - "futures 0.3.16", + "futures 0.3.19", "lazy_static", "libp2p-core", "log 0.4.14", @@ -3929,7 +3929,7 @@ version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80ef7b0ec5cf06530d9eb6cf59ae49d46a2c45663bde31c25a12f682664adbcf" dependencies = [ - "futures 0.3.16", + "futures 0.3.19", "libp2p-core", "libp2p-swarm", "log 0.4.14", @@ -3946,7 +3946,7 @@ checksum = "5fba1a6ff33e4a274c89a3b1d78b9f34f32af13265cc5c46c16938262d4e945a" dependencies = [ "asynchronous-codec 0.6.0", "bytes 1.1.0", - "futures 0.3.16", + "futures 0.3.19", "libp2p-core", "log 0.4.14", "prost", @@ -3961,7 +3961,7 @@ version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f1a458bbda880107b5b36fcb9b5a1ef0c329685da0e203ed692a8ebe64cc92c" dependencies = [ - "futures 0.3.16", + "futures 0.3.19", "log 0.4.14", "pin-project 1.0.10", "rand 0.7.3", @@ -3977,7 +3977,7 @@ checksum = "2852b61c90fa8ce3c8fcc2aba76e6cefc20d648f9df29157d6b3a916278ef3e3" dependencies = [ "asynchronous-codec 0.6.0", "bytes 1.1.0", - "futures 0.3.16", + "futures 0.3.19", "futures-timer", "libp2p-core", "libp2p-swarm", @@ -4000,7 +4000,7 @@ checksum = "14a6d2b9e7677eff61dc3d2854876aaf3976d84a01ef6664b610c77a0c9407c5" dependencies = [ "asynchronous-codec 0.6.0", "bimap", - "futures 0.3.16", + "futures 0.3.19", "libp2p-core", "libp2p-swarm", "log 0.4.14", @@ -4022,7 +4022,7 @@ checksum = "a877a4ced6d46bf84677e1974e8cf61fb434af73b2e96fb48d6cb6223a4634d8" dependencies = [ "async-trait", "bytes 1.1.0", - "futures 0.3.16", + "futures 0.3.19", "libp2p-core", "libp2p-swarm", "log 0.4.14", @@ -4040,7 +4040,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f5184a508f223bc100a12665517773fb8730e9f36fc09eefb670bf01b107ae9" dependencies = [ "either", - "futures 0.3.16", + "futures 0.3.19", "libp2p-core", "log 0.4.14", "rand 0.7.3", @@ -4066,7 +4066,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7399c5b6361ef525d41c11fcf51635724f832baf5819b30d3d873eabb4fbae4b" dependencies = [ "async-io", - "futures 0.3.16", + "futures 0.3.19", "futures-timer", "if-watch", "ipnet", @@ -4083,7 +4083,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8b7563e46218165dfd60f64b96f7ce84590d75f53ecbdc74a7dd01450dc5973" dependencies = [ "async-std", - "futures 0.3.16", + "futures 0.3.19", "libp2p-core", "log 0.4.14", ] @@ -4094,7 +4094,7 @@ version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1008a302b73c5020251f9708c653f5ed08368e530e247cc9cd2f109ff30042cf" dependencies = [ - "futures 0.3.16", + "futures 0.3.19", "js-sys", "libp2p-core", "parity-send-wrapper", @@ -4109,7 +4109,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22e12df82d1ed64969371a9e65ea92b91064658604cc2576c2757f18ead9a1cf" dependencies = [ "either", - "futures 0.3.16", + "futures 0.3.19", "futures-rustls", "libp2p-core", "log 0.4.14", @@ -4126,7 +4126,7 @@ version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e7362abb8867d7187e7e93df17f460d554c997fc5c8ac57dc1259057f6889af" dependencies = [ - "futures 0.3.16", + "futures 0.3.19", "libp2p-core", "parking_lot 0.11.2", "thiserror", @@ -4647,7 +4647,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d91ec0a2440aaff5f78ec35631a7027d50386c6163aa975f7caa0d5da4b6ff8" dependencies = [ "bytes 1.1.0", - "futures 0.3.16", + "futures 0.3.19", "log 0.4.14", "pin-project 1.0.10", "smallvec 1.7.0", @@ -4751,7 +4751,7 @@ dependencies = [ "clap 3.0.7", "derive_more", "fs_extra", - "futures 0.3.16", + "futures 0.3.19", "hash-db", "hex", "kvdb", @@ -4793,7 +4793,7 @@ dependencies = [ "frame-benchmarking-cli", "frame-system", "frame-system-rpc-runtime-api", - "futures 0.3.16", + "futures 0.3.19", "hex-literal", "jsonrpsee-ws-client 0.4.1", "log 0.4.14", @@ -4872,7 +4872,7 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", - "futures 0.3.16", + "futures 0.3.19", "node-primitives", "node-runtime", "node-testing", @@ -5131,7 +5131,7 @@ version = "3.0.0-dev" dependencies = [ "frame-system", "fs_extra", - "futures 0.3.16", + "futures 0.3.19", "log 0.4.14", "node-executor", "node-primitives", @@ -6672,7 +6672,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9981e32fb75e004cc148f5fb70342f393830e0a4aa62e3cc93b50976218d42b6" dependencies = [ - "futures 0.3.16", + "futures 0.3.19", "libc", "log 0.4.14", "rand 0.7.3", @@ -7881,7 +7881,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4da5fcb054c46f5a5dff833b129285a93d3f0179531735e6c866e8cc307d2020" dependencies = [ - "futures 0.3.16", + "futures 0.3.19", "pin-project 0.4.27", "static_assertions", ] @@ -7940,7 +7940,7 @@ name = "sc-authority-discovery" version = "0.10.0-dev" dependencies = [ "async-trait", - "futures 0.3.16", + "futures 0.3.19", "futures-timer", "ip_network", "libp2p", @@ -7968,7 +7968,7 @@ dependencies = [ name = "sc-basic-authorship" version = "0.10.0-dev" dependencies = [ - "futures 0.3.16", + "futures 0.3.19", "futures-timer", "log 0.4.14", "parity-scale-codec", @@ -8038,7 +8038,7 @@ dependencies = [ "chrono", "clap 3.0.7", "fdlimit", - "futures 0.3.16", + "futures 0.3.19", "hex", "libp2p", "log 0.4.14", @@ -8074,7 +8074,7 @@ name = "sc-client-api" version = "4.0.0-dev" dependencies = [ "fnv", - "futures 0.3.16", + "futures 0.3.19", "hash-db", "log 0.4.14", "parity-scale-codec", @@ -8132,7 +8132,7 @@ name = "sc-consensus" version = "0.10.0-dev" dependencies = [ "async-trait", - "futures 0.3.16", + "futures 0.3.19", "futures-timer", "libp2p", "log 0.4.14", @@ -8156,7 +8156,7 @@ name = "sc-consensus-aura" version = "0.10.0-dev" dependencies = [ "async-trait", - "futures 0.3.16", + "futures 0.3.19", "getrandom 0.2.3", "log 0.4.14", "parity-scale-codec", @@ -8195,7 +8195,7 @@ version = "0.10.0-dev" dependencies = [ "async-trait", "fork-tree", - "futures 0.3.16", + "futures 0.3.19", "log 0.4.14", "merlin", "num-bigint", @@ -8243,7 +8243,7 @@ dependencies = [ name = "sc-consensus-babe-rpc" version = "0.10.0-dev" dependencies = [ - "futures 0.3.16", + "futures 0.3.19", "jsonrpc-core", "jsonrpc-core-client", "jsonrpc-derive", @@ -8286,7 +8286,7 @@ version = "0.10.0-dev" dependencies = [ "assert_matches", "async-trait", - "futures 0.3.16", + "futures 0.3.19", "jsonrpc-core", "jsonrpc-core-client", "jsonrpc-derive", @@ -8324,7 +8324,7 @@ name = "sc-consensus-pow" version = "0.10.0-dev" dependencies = [ "async-trait", - "futures 0.3.16", + "futures 0.3.19", "futures-timer", "log 0.4.14", "parity-scale-codec", @@ -8348,7 +8348,7 @@ name = "sc-consensus-slots" version = "0.10.0-dev" dependencies = [ "async-trait", - "futures 0.3.16", + "futures 0.3.19", "futures-timer", "log 0.4.14", "parity-scale-codec", @@ -8478,7 +8478,7 @@ dependencies = [ "dyn-clone", "finality-grandpa", "fork-tree", - "futures 0.3.16", + "futures 0.3.19", "futures-timer", "log 0.4.14", "parity-scale-codec", @@ -8518,7 +8518,7 @@ name = "sc-finality-grandpa-rpc" version = "0.10.0-dev" dependencies = [ "finality-grandpa", - "futures 0.3.16", + "futures 0.3.19", "jsonrpc-core", "jsonrpc-core-client", "jsonrpc-derive", @@ -8545,7 +8545,7 @@ name = "sc-informant" version = "0.10.0-dev" dependencies = [ "ansi_term", - "futures 0.3.16", + "futures 0.3.19", "futures-timer", "log 0.4.14", "parity-util-mem", @@ -8585,7 +8585,7 @@ dependencies = [ "either", "fnv", "fork-tree", - "futures 0.3.16", + "futures 0.3.19", "futures-timer", "hex", "ip_network", @@ -8633,7 +8633,7 @@ version = "0.10.0-dev" dependencies = [ "ahash", "async-std", - "futures 0.3.16", + "futures 0.3.19", "futures-timer", "libp2p", "log 0.4.14", @@ -8652,7 +8652,7 @@ version = "0.8.0" dependencies = [ "async-std", "async-trait", - "futures 0.3.16", + "futures 0.3.19", "futures-timer", "libp2p", "log 0.4.14", @@ -8679,7 +8679,7 @@ version = "4.0.0-dev" dependencies = [ "bytes 1.1.0", "fnv", - "futures 0.3.16", + "futures 0.3.19", "futures-timer", "hex", "hyper 0.14.16", @@ -8713,7 +8713,7 @@ dependencies = [ name = "sc-peerset" version = "4.0.0-dev" dependencies = [ - "futures 0.3.16", + "futures 0.3.19", "libp2p", "log 0.4.14", "rand 0.7.3", @@ -8735,7 +8735,7 @@ name = "sc-rpc" version = "4.0.0-dev" dependencies = [ "assert_matches", - "futures 0.3.16", + "futures 0.3.19", "hash-db", "jsonrpc-core", "jsonrpc-pubsub", @@ -8771,7 +8771,7 @@ dependencies = [ name = "sc-rpc-api" version = "0.10.0-dev" dependencies = [ - "futures 0.3.16", + "futures 0.3.19", "jsonrpc-core", "jsonrpc-core-client", "jsonrpc-derive", @@ -8795,7 +8795,7 @@ dependencies = [ name = "sc-rpc-server" version = "4.0.0-dev" dependencies = [ - "futures 0.3.16", + "futures 0.3.19", "jsonrpc-core", "jsonrpc-http-server", "jsonrpc-ipc-server", @@ -8829,7 +8829,7 @@ dependencies = [ "async-trait", "directories", "exit-future", - "futures 0.3.16", + "futures 0.3.19", "futures-timer", "hash-db", "jsonrpc-core", @@ -8892,7 +8892,7 @@ name = "sc-service-test" version = "2.0.0" dependencies = [ "fdlimit", - "futures 0.3.16", + "futures 0.3.19", "hex", "hex-literal", "log 0.4.14", @@ -8961,7 +8961,7 @@ name = "sc-telemetry" version = "4.0.0-dev" dependencies = [ "chrono", - "futures 0.3.16", + "futures 0.3.19", "libp2p", "log 0.4.14", "parking_lot 0.12.0", @@ -9020,7 +9020,7 @@ version = "4.0.0-dev" dependencies = [ "assert_matches", "criterion", - "futures 0.3.16", + "futures 0.3.19", "futures-timer", "hex", "linked-hash-map", @@ -9052,7 +9052,7 @@ dependencies = [ name = "sc-transaction-pool-api" version = "4.0.0-dev" dependencies = [ - "futures 0.3.16", + "futures 0.3.19", "log 0.4.14", "serde", "sp-blockchain", @@ -9064,7 +9064,7 @@ dependencies = [ name = "sc-utils" version = "4.0.0-dev" dependencies = [ - "futures 0.3.16", + "futures 0.3.19", "futures-timer", "lazy_static", "log 0.4.14", @@ -9541,7 +9541,7 @@ checksum = "b5c71ed3d54db0a699f4948e1bb3e45b450fa31fe602621dee6680361d569c88" dependencies = [ "base64 0.12.3", "bytes 0.5.6", - "futures 0.3.16", + "futures 0.3.19", "httparse", "log 0.4.14", "rand 0.7.3", @@ -9557,7 +9557,7 @@ dependencies = [ "base64 0.13.0", "bytes 1.1.0", "flate2", - "futures 0.3.16", + "futures 0.3.19", "httparse", "log 0.4.14", "rand 0.8.4", @@ -9597,7 +9597,7 @@ name = "sp-api-test" version = "2.0.1" dependencies = [ "criterion", - "futures 0.3.16", + "futures 0.3.19", "log 0.4.14", "parity-scale-codec", "rustversion", @@ -9702,7 +9702,7 @@ dependencies = [ name = "sp-blockchain" version = "4.0.0-dev" dependencies = [ - "futures 0.3.16", + "futures 0.3.19", "log 0.4.14", "lru 0.7.0", "parity-scale-codec", @@ -9720,7 +9720,7 @@ name = "sp-consensus" version = "0.10.0-dev" dependencies = [ "async-trait", - "futures 0.3.16", + "futures 0.3.19", "futures-timer", "log 0.4.14", "parity-scale-codec", @@ -9819,7 +9819,7 @@ dependencies = [ "criterion", "dyn-clonable", "ed25519-dalek", - "futures 0.3.16", + "futures 0.3.19", "hash-db", "hash256-std-hasher", "hex", @@ -9930,7 +9930,7 @@ name = "sp-inherents" version = "4.0.0-dev" dependencies = [ "async-trait", - "futures 0.3.16", + "futures 0.3.19", "impl-trait-for-tuples", "parity-scale-codec", "sp-core", @@ -9943,7 +9943,7 @@ dependencies = [ name = "sp-io" version = "5.0.0" dependencies = [ - "futures 0.3.16", + "futures 0.3.19", "hash-db", "libsecp256k1", "log 0.4.14", @@ -9978,7 +9978,7 @@ name = "sp-keystore" version = "0.11.0" dependencies = [ "async-trait", - "futures 0.3.16", + "futures 0.3.19", "merlin", "parity-scale-codec", "parking_lot 0.12.0", @@ -10517,7 +10517,7 @@ version = "3.0.0" dependencies = [ "frame-support", "frame-system", - "futures 0.3.16", + "futures 0.3.19", "jsonrpc-client-transports", "parity-scale-codec", "sc-rpc-api", @@ -10532,7 +10532,7 @@ name = "substrate-frame-rpc-system" version = "4.0.0-dev" dependencies = [ "frame-system-rpc-runtime-api", - "futures 0.3.16", + "futures 0.3.19", "jsonrpc-core", "jsonrpc-core-client", "jsonrpc-derive", @@ -10568,7 +10568,7 @@ name = "substrate-test-client" version = "2.0.1" dependencies = [ "async-trait", - "futures 0.3.16", + "futures 0.3.19", "hex", "parity-scale-codec", "sc-client-api", @@ -10596,7 +10596,7 @@ dependencies = [ "frame-support", "frame-system", "frame-system-rpc-runtime-api", - "futures 0.3.16", + "futures 0.3.19", "log 0.4.14", "memory-db", "pallet-babe", @@ -10638,7 +10638,7 @@ dependencies = [ name = "substrate-test-runtime-client" version = "2.0.0" dependencies = [ - "futures 0.3.16", + "futures 0.3.19", "parity-scale-codec", "sc-block-builder", "sc-client-api", @@ -10656,7 +10656,7 @@ dependencies = [ name = "substrate-test-runtime-transaction-pool" version = "2.0.0" dependencies = [ - "futures 0.3.16", + "futures 0.3.19", "parity-scale-codec", "parking_lot 0.12.0", "sc-transaction-pool", @@ -10671,7 +10671,7 @@ dependencies = [ name = "substrate-test-utils" version = "4.0.0-dev" dependencies = [ - "futures 0.3.16", + "futures 0.3.19", "sc-service", "substrate-test-utils-derive", "tokio", @@ -11358,7 +11358,7 @@ version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ee73e6e4924fe940354b8d4d98cad5231175d615cd855b758adc658c0aac6a0" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "digest 0.10.2", "rand 0.8.4", "static_assertions", @@ -11696,7 +11696,7 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f" dependencies = [ - "futures 0.3.16", + "futures 0.3.19", "js-sys", "parking_lot 0.11.2", "pin-utils", @@ -12352,7 +12352,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7d9028f208dd5e63c614be69f115c1b53cacc1111437d4c765185856666c107" dependencies = [ - "futures 0.3.16", + "futures 0.3.19", "log 0.4.14", "nohash-hasher", "parking_lot 0.11.2", diff --git a/bin/node/bench/Cargo.toml b/bin/node/bench/Cargo.toml index b14e44371d2b..c770ca01ecf0 100644 --- a/bin/node/bench/Cargo.toml +++ b/bin/node/bench/Cargo.toml @@ -39,4 +39,4 @@ parity-util-mem = { version = "0.11.0", default-features = false, features = ["p parity-db = { version = "0.3" } sc-transaction-pool = { version = "4.0.0-dev", path = "../../../client/transaction-pool" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../../../client/transaction-pool/api" } -futures = { version = "0.3.4", features = ["thread-pool"] } +futures = { version = "0.3.19", features = ["thread-pool"] } diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index 4225d09d594a..57bbbdddcb2e 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -37,7 +37,7 @@ crate-type = ["cdylib", "rlib"] clap = { version = "3.0", features = ["derive"], optional = true } codec = { package = "parity-scale-codec", version = "3.0.0" } serde = { version = "1.0.136", features = ["derive"] } -futures = "0.3.16" +futures = "0.3.19" hex-literal = "0.3.4" log = "0.4.8" rand = "0.8" @@ -116,7 +116,7 @@ sc-service-test = { version = "2.0.0", path = "../../../client/service/test" } sc-block-builder = { version = "0.10.0-dev", path = "../../../client/block-builder" } sp-tracing = { version = "4.0.0", path = "../../../primitives/tracing" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -futures = "0.3.16" +futures = "0.3.19" tempfile = "3.1.0" assert_cmd = "2.0.2" nix = "0.23" diff --git a/bin/node/executor/Cargo.toml b/bin/node/executor/Cargo.toml index 16f232d73d3f..6bb762319b27 100644 --- a/bin/node/executor/Cargo.toml +++ b/bin/node/executor/Cargo.toml @@ -40,7 +40,7 @@ sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } sp-externalities = { version = "0.11.0", path = "../../../primitives/externalities" } sp-keyring = { version = "5.0.0", path = "../../../primitives/keyring" } wat = "1.0" -futures = "0.3.9" +futures = "0.3.19" [features] wasmtime = ["sc-executor/wasmtime"] diff --git a/bin/node/testing/Cargo.toml b/bin/node/testing/Cargo.toml index fc9209ce2b63..3c0be4e19c9e 100644 --- a/bin/node/testing/Cargo.toml +++ b/bin/node/testing/Cargo.toml @@ -48,4 +48,4 @@ sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" log = "0.4.8" tempfile = "3.1.0" fs_extra = "1" -futures = "0.3.1" +futures = "0.3.19" diff --git a/client/api/Cargo.toml b/client/api/Cargo.toml index 68ab9aed31fe..b82309ef6faf 100644 --- a/client/api/Cargo.toml +++ b/client/api/Cargo.toml @@ -21,7 +21,7 @@ sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/comm sc-executor = { version = "0.10.0-dev", path = "../executor" } sp-externalities = { version = "0.11.0", path = "../../primitives/externalities" } fnv = "1.0.6" -futures = "0.3.1" +futures = "0.3.19" hash-db = { version = "0.15.2", default-features = false } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } log = "0.4.8" diff --git a/client/authority-discovery/Cargo.toml b/client/authority-discovery/Cargo.toml index 04dde95837d2..197b8cfd1fbb 100644 --- a/client/authority-discovery/Cargo.toml +++ b/client/authority-discovery/Cargo.toml @@ -20,7 +20,7 @@ prost-build = "0.9" async-trait = "0.1" codec = { package = "parity-scale-codec", default-features = false, version = "3.0.0" } thiserror = "1.0" -futures = "0.3.9" +futures = "0.3.19" futures-timer = "3.0.1" ip_network = "0.4.1" libp2p = { version = "0.40.0", default-features = false, features = ["kad"] } diff --git a/client/basic-authorship/Cargo.toml b/client/basic-authorship/Cargo.toml index bbc66cf09f8b..5791b2b4010f 100644 --- a/client/basic-authorship/Cargo.toml +++ b/client/basic-authorship/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0" } -futures = "0.3.9" +futures = "0.3.19" futures-timer = "3.0.1" log = "0.4.8" prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.10.0-dev"} diff --git a/client/beefy/rpc/Cargo.toml b/client/beefy/rpc/Cargo.toml index 053aef500b46..19e1e20c7735 100644 --- a/client/beefy/rpc/Cargo.toml +++ b/client/beefy/rpc/Cargo.toml @@ -8,7 +8,7 @@ repository = "https://github.com/paritytech/substrate" description = "RPC for the BEEFY Client gadget for substrate" [dependencies] -futures = "0.3.16" +futures = "0.3.19" log = "0.4" parking_lot = "0.12.0" thiserror = "1.0" diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index 708e6317d10c..47ef9619661c 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] chrono = "0.4.10" clap = { version = "3.0", features = ["derive"] } fdlimit = "0.2.1" -futures = "0.3.9" +futures = "0.3.19" hex = "0.4.2" libp2p = "0.40.0" log = "0.4.11" diff --git a/client/consensus/aura/Cargo.toml b/client/consensus/aura/Cargo.toml index 9cb241b6c974..b82a71587048 100644 --- a/client/consensus/aura/Cargo.toml +++ b/client/consensus/aura/Cargo.toml @@ -23,7 +23,7 @@ sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/c sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/common" } sp-consensus-slots = { version = "0.10.0-dev", path = "../../../primitives/consensus/slots" } thiserror = "1.0" -futures = "0.3.9" +futures = "0.3.19" sp-inherents = { version = "4.0.0-dev", path = "../../../primitives/inherents" } log = "0.4.8" sp-core = { version = "5.0.0", path = "../../../primitives/core" } diff --git a/client/consensus/babe/Cargo.toml b/client/consensus/babe/Cargo.toml index 4a9f1f00b75a..edcf8759f6a7 100644 --- a/client/consensus/babe/Cargo.toml +++ b/client/consensus/babe/Cargo.toml @@ -43,7 +43,7 @@ sc-consensus-slots = { version = "0.10.0-dev", path = "../slots" } sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } fork-tree = { version = "3.0.0", path = "../../../utils/fork-tree" } prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.10.0-dev" } -futures = "0.3.9" +futures = "0.3.19" parking_lot = "0.12.0" log = "0.4.8" schnorrkel = { version = "0.9.1", features = ["preaudit_deprecated"] } diff --git a/client/consensus/babe/rpc/Cargo.toml b/client/consensus/babe/rpc/Cargo.toml index 8ceada5fe1f1..5e9f98d628c7 100644 --- a/client/consensus/babe/rpc/Cargo.toml +++ b/client/consensus/babe/rpc/Cargo.toml @@ -23,7 +23,7 @@ serde = { version = "1.0.136", features = ["derive"] } sp-blockchain = { version = "4.0.0-dev", path = "../../../../primitives/blockchain" } sp-runtime = { version = "5.0.0", path = "../../../../primitives/runtime" } sc-consensus-epochs = { version = "0.10.0-dev", path = "../../epochs" } -futures = "0.3.16" +futures = "0.3.19" thiserror = "1.0" sp-api = { version = "4.0.0-dev", path = "../../../../primitives/api" } sp-consensus = { version = "0.10.0-dev", path = "../../../../primitives/consensus/common" } diff --git a/client/consensus/common/Cargo.toml b/client/consensus/common/Cargo.toml index 7add4bb87330..7677e0569e56 100644 --- a/client/consensus/common/Cargo.toml +++ b/client/consensus/common/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] thiserror = "1.0.30" libp2p = { version = "0.40.0", default-features = false } log = "0.4.8" -futures = { version = "0.3.1", features = ["thread-pool"] } +futures = { version = "0.3.19", features = ["thread-pool"] } futures-timer = "3.0.1" sc-client-api = { version = "4.0.0-dev", path = "../../api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } diff --git a/client/consensus/manual-seal/Cargo.toml b/client/consensus/manual-seal/Cargo.toml index 83828962f670..6b9404ce34c9 100644 --- a/client/consensus/manual-seal/Cargo.toml +++ b/client/consensus/manual-seal/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] thiserror = "1.0" -futures = "0.3.9" +futures = "0.3.19" jsonrpc-core = "18.0.0" jsonrpc-core-client = "18.0.0" jsonrpc-derive = "18.0.0" diff --git a/client/consensus/pow/Cargo.toml b/client/consensus/pow/Cargo.toml index 7e3d30e8deba..cb21a45ebdb0 100644 --- a/client/consensus/pow/Cargo.toml +++ b/client/consensus/pow/Cargo.toml @@ -25,7 +25,7 @@ sp-consensus-pow = { version = "0.10.0-dev", path = "../../../primitives/consens sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" } sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/common" } log = "0.4.8" -futures = "0.3.16" +futures = "0.3.19" futures-timer = "3.0.1" parking_lot = "0.12.0" thiserror = "1.0" diff --git a/client/consensus/slots/Cargo.toml b/client/consensus/slots/Cargo.toml index 0127010a1714..4f4cf4d58bc3 100644 --- a/client/consensus/slots/Cargo.toml +++ b/client/consensus/slots/Cargo.toml @@ -27,7 +27,7 @@ sc-telemetry = { version = "4.0.0-dev", path = "../../telemetry" } sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" } sp-inherents = { version = "4.0.0-dev", path = "../../../primitives/inherents" } sp-timestamp = { version = "4.0.0-dev", path = "../../../primitives/timestamp" } -futures = "0.3.9" +futures = "0.3.19" futures-timer = "3.0.1" log = "0.4.11" thiserror = "1.0.30" diff --git a/client/finality-grandpa/Cargo.toml b/client/finality-grandpa/Cargo.toml index 2e2ad8738f35..5927a9bef4e6 100644 --- a/client/finality-grandpa/Cargo.toml +++ b/client/finality-grandpa/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] thiserror = "1.0" dyn-clone = "1.0" fork-tree = { version = "3.0.0", path = "../../utils/fork-tree" } -futures = "0.3.9" +futures = "0.3.19" futures-timer = "3.0.1" log = "0.4.8" parking_lot = "0.12.0" diff --git a/client/informant/Cargo.toml b/client/informant/Cargo.toml index 82917c46d3d2..7ab057b5f0dc 100644 --- a/client/informant/Cargo.toml +++ b/client/informant/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] ansi_term = "0.12.1" -futures = "0.3.9" +futures = "0.3.19" futures-timer = "3.0.1" log = "0.4.8" parity-util-mem = { version = "0.11.0", default-features = false, features = ["primitive-types"] } diff --git a/client/network-gossip/Cargo.toml b/client/network-gossip/Cargo.toml index 161129c4ce68..d9b52c31f273 100644 --- a/client/network-gossip/Cargo.toml +++ b/client/network-gossip/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] -futures = "0.3.9" +futures = "0.3.19" futures-timer = "3.0.1" libp2p = { version = "0.40.0", default-features = false } log = "0.4.8" diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index 0334c5e819df..c26d90b8952e 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -27,7 +27,7 @@ codec = { package = "parity-scale-codec", version = "3.0.0", features = [ either = "1.5.3" fnv = "1.0.6" fork-tree = { version = "3.0.0", path = "../../utils/fork-tree" } -futures = "0.3.9" +futures = "0.3.19" futures-timer = "3.0.2" asynchronous-codec = "0.5" hex = "0.4.0" diff --git a/client/network/test/Cargo.toml b/client/network/test/Cargo.toml index 7d0b1921b69e..4a47365e0641 100644 --- a/client/network/test/Cargo.toml +++ b/client/network/test/Cargo.toml @@ -17,7 +17,7 @@ async-std = "1.10.0" sc-network = { version = "0.10.0-dev", path = "../" } log = "0.4.8" parking_lot = "0.12.0" -futures = "0.3.9" +futures = "0.3.19" futures-timer = "3.0.1" rand = "0.7.2" libp2p = { version = "0.40.0", default-features = false } diff --git a/client/offchain/Cargo.toml b/client/offchain/Cargo.toml index 054a8c3edf02..654633d6ed7f 100644 --- a/client/offchain/Cargo.toml +++ b/client/offchain/Cargo.toml @@ -17,7 +17,7 @@ bytes = "1.1" codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"] } hex = "0.4" fnv = "1.0.6" -futures = "0.3.16" +futures = "0.3.19" futures-timer = "3.0.2" num_cpus = "1.13" parking_lot = "0.12.0" diff --git a/client/peerset/Cargo.toml b/client/peerset/Cargo.toml index ac3590630a1e..1bbf8bd6e9cb 100644 --- a/client/peerset/Cargo.toml +++ b/client/peerset/Cargo.toml @@ -14,7 +14,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -futures = "0.3.9" +futures = "0.3.19" libp2p = { version = "0.40.0", default-features = false } sc-utils = { version = "4.0.0-dev", path = "../utils"} log = "0.4.8" diff --git a/client/rpc-api/Cargo.toml b/client/rpc-api/Cargo.toml index bbbc9a998337..cfcadad1361a 100644 --- a/client/rpc-api/Cargo.toml +++ b/client/rpc-api/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0" } -futures = "0.3.16" +futures = "0.3.19" jsonrpc-core = "18.0.0" jsonrpc-core-client = "18.0.0" jsonrpc-derive = "18.0.0" diff --git a/client/rpc-servers/Cargo.toml b/client/rpc-servers/Cargo.toml index 954bf602f85d..496152ecb750 100644 --- a/client/rpc-servers/Cargo.toml +++ b/client/rpc-servers/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -futures = "0.3.16" +futures = "0.3.19" jsonrpc-core = "18.0.0" pubsub = { package = "jsonrpc-pubsub", version = "18.0.0" } log = "0.4.8" diff --git a/client/rpc/Cargo.toml b/client/rpc/Cargo.toml index cbce14cee20d..96dfa2c1caa4 100644 --- a/client/rpc/Cargo.toml +++ b/client/rpc/Cargo.toml @@ -17,7 +17,7 @@ sc-rpc-api = { version = "0.10.0-dev", path = "../rpc-api" } sc-client-api = { version = "4.0.0-dev", path = "../api" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } codec = { package = "parity-scale-codec", version = "3.0.0" } -futures = "0.3.16" +futures = "0.3.19" jsonrpc-pubsub = "18.0.0" log = "0.4.8" sp-core = { version = "5.0.0", path = "../../primitives/core" } diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index e007486d9ef1..1747d8e61ea7 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -23,7 +23,7 @@ test-helpers = [] [dependencies] thiserror = "1.0.30" -futures = "0.3.16" +futures = "0.3.19" jsonrpc-pubsub = "18.0" jsonrpc-core = "18.0" rand = "0.7.3" diff --git a/client/service/test/Cargo.toml b/client/service/test/Cargo.toml index a815d1f5571f..ac1fb7ad0159 100644 --- a/client/service/test/Cargo.toml +++ b/client/service/test/Cargo.toml @@ -26,7 +26,7 @@ sp-externalities = { version = "0.11.0", path = "../../../primitives/externaliti sp-trie = { version = "5.0.0", path = "../../../primitives/trie" } sp-storage = { version = "5.0.0", path = "../../../primitives/storage" } sc-client-db = { version = "0.10.0-dev", default-features = false, path = "../../db" } -futures = "0.3.16" +futures = "0.3.19" sc-service = { version = "0.10.0-dev", features = ["test-helpers"], path = "../../service" } sc-network = { version = "0.10.0-dev", path = "../../network" } sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" } diff --git a/client/telemetry/Cargo.toml b/client/telemetry/Cargo.toml index 2339fa277cca..7bdd60a037e1 100644 --- a/client/telemetry/Cargo.toml +++ b/client/telemetry/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] parking_lot = "0.12.0" -futures = "0.3.9" +futures = "0.3.19" wasm-timer = "0.2.5" libp2p = { version = "0.40.0", default-features = false, features = ["dns-async-std", "tcp-async-io", "wasm-ext", "websocket"] } log = "0.4.8" diff --git a/client/transaction-pool/Cargo.toml b/client/transaction-pool/Cargo.toml index a5d6d4e1bf74..ac5beeac605f 100644 --- a/client/transaction-pool/Cargo.toml +++ b/client/transaction-pool/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0" } thiserror = "1.0.30" -futures = "0.3.16" +futures = "0.3.19" futures-timer = "3.0.2" log = "0.4.8" parity-util-mem = { version = "0.11.0", default-features = false, features = ["primitive-types"] } diff --git a/client/transaction-pool/api/Cargo.toml b/client/transaction-pool/api/Cargo.toml index 70f18c345e05..eb5f0ed6b0b7 100644 --- a/client/transaction-pool/api/Cargo.toml +++ b/client/transaction-pool/api/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/paritytech/substrate/" description = "Transaction pool client facing API." [dependencies] -futures = "0.3.1" +futures = "0.3.19" log = "0.4.8" serde = { version = "1.0.136", features = ["derive"] } thiserror = "1.0.30" diff --git a/client/utils/Cargo.toml b/client/utils/Cargo.toml index 70d6bcd8b049..a107aab1dbd6 100644 --- a/client/utils/Cargo.toml +++ b/client/utils/Cargo.toml @@ -10,7 +10,7 @@ description = "I/O for Substrate runtimes" readme = "README.md" [dependencies] -futures = "0.3.9" +futures = "0.3.19" lazy_static = "1.4.0" parking_lot = "0.12.0" prometheus = { version = "0.13.0", default-features = false } diff --git a/primitives/api/test/Cargo.toml b/primitives/api/test/Cargo.toml index 8edb2a31fb55..9078c69f994e 100644 --- a/primitives/api/test/Cargo.toml +++ b/primitives/api/test/Cargo.toml @@ -26,7 +26,7 @@ rustversion = "1.0.6" [dev-dependencies] criterion = "0.3.0" -futures = "0.3.9" +futures = "0.3.19" log = "0.4.14" sp-core = { version = "5.0.0", path = "../../core" } diff --git a/primitives/blockchain/Cargo.toml b/primitives/blockchain/Cargo.toml index 69aa7c049f88..59d0121647c5 100644 --- a/primitives/blockchain/Cargo.toml +++ b/primitives/blockchain/Cargo.toml @@ -18,7 +18,7 @@ log = "0.4.11" lru = "0.7.0" parking_lot = "0.12.0" thiserror = "1.0.30" -futures = "0.3.9" +futures = "0.3.19" codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } sp-consensus = { version = "0.10.0-dev", path = "../consensus/common" } sp-runtime = { version = "5.0.0", path = "../runtime" } diff --git a/primitives/consensus/common/Cargo.toml b/primitives/consensus/common/Cargo.toml index d6c31876fa8d..4d0d17e1288e 100644 --- a/primitives/consensus/common/Cargo.toml +++ b/primitives/consensus/common/Cargo.toml @@ -18,7 +18,7 @@ async-trait = "0.1.42" codec = { package = "parity-scale-codec", version = "3.0.0", features = [ "derive", ] } -futures = { version = "0.3.1", features = ["thread-pool"] } +futures = { version = "0.3.19", features = ["thread-pool"] } log = "0.4.8" sp-core = { path = "../../core", version = "5.0.0"} sp-inherents = { version = "4.0.0-dev", path = "../../inherents" } @@ -30,7 +30,7 @@ sp-runtime = { version = "5.0.0", path = "../../runtime" } thiserror = "1.0.30" [dev-dependencies] -futures = "0.3.9" +futures = "0.3.19" sp-test-primitives = { version = "2.0.0", path = "../../test-primitives" } [features] diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index bd1930bf51b6..d1a813057958 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -41,7 +41,7 @@ sp-debug-derive = { version = "4.0.0", default-features = false, path = "../debu sp-storage = { version = "5.0.0", default-features = false, path = "../storage" } sp-externalities = { version = "0.11.0", optional = true, path = "../externalities" } parity-util-mem = { version = "0.11.0", default-features = false, features = ["primitive-types"] } -futures = { version = "0.3.1", optional = true } +futures = { version = "0.3.19", optional = true } dyn-clonable = { version = "0.9.0", optional = true } thiserror = { version = "1.0.30", optional = true } bitflags = "1.3" diff --git a/primitives/inherents/Cargo.toml b/primitives/inherents/Cargo.toml index 4fe1c75b52ae..3bbe3caf5615 100644 --- a/primitives/inherents/Cargo.toml +++ b/primitives/inherents/Cargo.toml @@ -24,7 +24,7 @@ impl-trait-for-tuples = "0.2.0" async-trait = { version = "0.1.50", optional = true } [dev-dependencies] -futures = "0.3.9" +futures = "0.3.19" [features] default = [ "std" ] diff --git a/primitives/io/Cargo.toml b/primitives/io/Cargo.toml index 6cc6c47ddc96..b955d4c784da 100644 --- a/primitives/io/Cargo.toml +++ b/primitives/io/Cargo.toml @@ -28,7 +28,7 @@ sp-trie = { version = "5.0.0", optional = true, path = "../trie" } sp-externalities = { version = "0.11.0", optional = true, path = "../externalities" } sp-tracing = { version = "4.0.0", default-features = false, path = "../tracing" } log = { version = "0.4.8", optional = true } -futures = { version = "0.3.1", features = ["thread-pool"], optional = true } +futures = { version = "0.3.19", features = ["thread-pool"], optional = true } parking_lot = { version = "0.12.0", optional = true } secp256k1 = { version = "0.21.2", features = ["recovery", "global-context"], optional = true } tracing = { version = "0.1.29", default-features = false } diff --git a/primitives/keystore/Cargo.toml b/primitives/keystore/Cargo.toml index 182a5f494fbc..341d2460765b 100644 --- a/primitives/keystore/Cargo.toml +++ b/primitives/keystore/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] async-trait = "0.1.50" -futures = "0.3.1" +futures = "0.3.19" parking_lot = { version = "0.12.0", default-features = false } serde = { version = "1.0", optional = true } thiserror = "1.0" diff --git a/test-utils/client/Cargo.toml b/test-utils/client/Cargo.toml index ffddda3ac1f5..6deaddd9068f 100644 --- a/test-utils/client/Cargo.toml +++ b/test-utils/client/Cargo.toml @@ -13,7 +13,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0" } -futures = "0.3.16" +futures = "0.3.19" hex = "0.4" serde = "1.0.136" serde_json = "1.0.74" diff --git a/test-utils/runtime/Cargo.toml b/test-utils/runtime/Cargo.toml index b955aa07afa7..79d43bea8520 100644 --- a/test-utils/runtime/Cargo.toml +++ b/test-utils/runtime/Cargo.toml @@ -55,7 +55,7 @@ sc-block-builder = { version = "0.10.0-dev", path = "../../client/block-builder" sc-executor = { version = "0.10.0-dev", path = "../../client/executor" } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } substrate-test-runtime-client = { version = "2.0.0", path = "./client" } -futures = "0.3.9" +futures = "0.3.19" [build-dependencies] substrate-wasm-builder = { version = "5.0.0-dev", path = "../../utils/wasm-builder" } diff --git a/test-utils/runtime/client/Cargo.toml b/test-utils/runtime/client/Cargo.toml index 3491a7a09f9c..552a0581d79e 100644 --- a/test-utils/runtime/client/Cargo.toml +++ b/test-utils/runtime/client/Cargo.toml @@ -23,4 +23,4 @@ sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } codec = { package = "parity-scale-codec", version = "3.0.0" } sc-client-api = { version = "4.0.0-dev", path = "../../../client/api" } -futures = "0.3.9" +futures = "0.3.19" diff --git a/test-utils/runtime/transaction-pool/Cargo.toml b/test-utils/runtime/transaction-pool/Cargo.toml index edb2efdb273f..b936e6d9cb35 100644 --- a/test-utils/runtime/transaction-pool/Cargo.toml +++ b/test-utils/runtime/transaction-pool/Cargo.toml @@ -19,5 +19,5 @@ sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } sc-transaction-pool = { version = "4.0.0-dev", path = "../../../client/transaction-pool" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../../../client/transaction-pool/api" } -futures = "0.3.16" +futures = "0.3.19" thiserror = "1.0" diff --git a/utils/frame/rpc/support/Cargo.toml b/utils/frame/rpc/support/Cargo.toml index b255f5ab2a79..645e33f4b21a 100644 --- a/utils/frame/rpc/support/Cargo.toml +++ b/utils/frame/rpc/support/Cargo.toml @@ -15,7 +15,7 @@ description = "Substrate RPC for FRAME's support" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -futures = "0.3.16" +futures = "0.3.19" jsonrpc-client-transports = { version = "18.0.0", features = ["http"] } codec = { package = "parity-scale-codec", version = "3.0.0" } serde = "1" diff --git a/utils/frame/rpc/system/Cargo.toml b/utils/frame/rpc/system/Cargo.toml index 950cbd09b278..79794d779252 100644 --- a/utils/frame/rpc/system/Cargo.toml +++ b/utils/frame/rpc/system/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sc-client-api = { version = "4.0.0-dev", path = "../../../../client/api" } codec = { package = "parity-scale-codec", version = "3.0.0" } -futures = "0.3.16" +futures = "0.3.19" jsonrpc-core = "18.0.0" jsonrpc-core-client = "18.0.0" jsonrpc-derive = "18.0.0" From 8934e6de3f8a5d48af8971c7a0fcc4c668d4f9ce Mon Sep 17 00:00:00 2001 From: Xiankun Cheng Date: Tue, 1 Mar 2022 22:32:22 +1300 Subject: [PATCH 542/695] Clean up extra_constant renaming. (#10935) Co-authored-by: Xiankun Cheng --- frame/transaction-payment/src/lib.rs | 5 ++--- frame/vesting/src/lib.rs | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/frame/transaction-payment/src/lib.rs b/frame/transaction-payment/src/lib.rs index e4d77a05f284..37fecf20cc52 100644 --- a/frame/transaction-payment/src/lib.rs +++ b/frame/transaction-payment/src/lib.rs @@ -297,10 +297,9 @@ pub mod pallet { #[pallet::extra_constants] impl Pallet { - // TODO: rename to snake case after https://github.com/paritytech/substrate/issues/8826 fixed. - #[allow(non_snake_case)] + #[pallet::constant_name(WeightToFee)] /// The polynomial that is applied in order to derive fee from weight. - fn WeightToFee() -> Vec>> { + fn weight_to_fee_polynomial() -> Vec>> { T::WeightToFee::polynomial().to_vec() } } diff --git a/frame/vesting/src/lib.rs b/frame/vesting/src/lib.rs index 747521f4fa53..775902f223ba 100644 --- a/frame/vesting/src/lib.rs +++ b/frame/vesting/src/lib.rs @@ -171,9 +171,8 @@ pub mod pallet { #[pallet::extra_constants] impl Pallet { - // TODO: rename to snake case after https://github.com/paritytech/substrate/issues/8826 fixed. - #[allow(non_snake_case)] - fn MaxVestingSchedules() -> u32 { + #[pallet::constant_name(MaxVestingSchedules)] + fn max_vesting_schedules() -> u32 { T::MAX_VESTING_SCHEDULES } } From 919e304dd6f3c11a55ee125498e8e531ce343805 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Mar 2022 10:03:31 +0000 Subject: [PATCH 543/695] Bump smallvec from 1.7.0 to 1.8.0 (#10949) Bumps [smallvec](https://github.com/servo/rust-smallvec) from 1.7.0 to 1.8.0. - [Release notes](https://github.com/servo/rust-smallvec/releases) - [Commits](https://github.com/servo/rust-smallvec/compare/v1.7.0...v1.8.0) --- updated-dependencies: - dependency-name: smallvec dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 80 +++++++++---------- client/network/Cargo.toml | 2 +- frame/support/Cargo.toml | 2 +- frame/transaction-payment/Cargo.toml | 2 +- .../asset-tx-payment/Cargo.toml | 2 +- primitives/state-machine/Cargo.toml | 2 +- 6 files changed, 45 insertions(+), 45 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e6ae5a1fea5f..08d44487776d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1159,7 +1159,7 @@ dependencies = [ "gimli 0.22.0", "log 0.4.14", "regalloc 0.0.31", - "smallvec 1.7.0", + "smallvec 1.8.0", "target-lexicon 0.11.2", "thiserror", ] @@ -1177,7 +1177,7 @@ dependencies = [ "gimli 0.26.1", "log 0.4.14", "regalloc 0.0.33", - "smallvec 1.7.0", + "smallvec 1.8.0", "target-lexicon 0.12.0", ] @@ -1238,7 +1238,7 @@ checksum = "b608bb7656c554d0a4cf8f50c7a10b857e80306f6ff829ad6d468a7e2323c8d8" dependencies = [ "cranelift-codegen 0.68.0", "log 0.4.14", - "smallvec 1.7.0", + "smallvec 1.8.0", "target-lexicon 0.11.2", ] @@ -1250,7 +1250,7 @@ checksum = "b7cb156de1097f567d46bf57a0cd720a72c3e15e1a2bd8b1041ba2fc894471b7" dependencies = [ "cranelift-codegen 0.80.0", "log 0.4.14", - "smallvec 1.7.0", + "smallvec 1.8.0", "target-lexicon 0.12.0", ] @@ -1276,7 +1276,7 @@ dependencies = [ "cranelift-frontend 0.80.0", "itertools", "log 0.4.14", - "smallvec 1.7.0", + "smallvec 1.8.0", "wasmparser 0.81.0", "wasmtime-types", ] @@ -2223,7 +2223,7 @@ dependencies = [ "pretty_assertions", "scale-info", "serde", - "smallvec 1.7.0", + "smallvec 1.8.0", "sp-arithmetic", "sp-core", "sp-core-hashing-proc-macro", @@ -3551,7 +3551,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a301d8ecb7989d4a6e2c57a49baca77d353bdbf879909debe3f375fe25d61f86" dependencies = [ "parity-util-mem", - "smallvec 1.7.0", + "smallvec 1.8.0", ] [[package]] @@ -3580,7 +3580,7 @@ dependencies = [ "parking_lot 0.12.0", "regex", "rocksdb", - "smallvec 1.7.0", + "smallvec 1.8.0", ] [[package]] @@ -3698,7 +3698,7 @@ dependencies = [ "multiaddr", "parking_lot 0.11.2", "pin-project 1.0.10", - "smallvec 1.7.0", + "smallvec 1.8.0", "wasm-timer", ] @@ -3729,7 +3729,7 @@ dependencies = [ "ring", "rw-stream-sink", "sha2 0.9.8", - "smallvec 1.7.0", + "smallvec 1.8.0", "thiserror", "unsigned-varint 0.7.0", "void", @@ -3757,7 +3757,7 @@ dependencies = [ "futures 0.3.19", "libp2p-core", "log 0.4.14", - "smallvec 1.7.0", + "smallvec 1.8.0", "trust-dns-resolver", ] @@ -3776,7 +3776,7 @@ dependencies = [ "prost", "prost-build", "rand 0.7.3", - "smallvec 1.7.0", + "smallvec 1.8.0", ] [[package]] @@ -3800,7 +3800,7 @@ dependencies = [ "rand 0.7.3", "regex", "sha2 0.9.8", - "smallvec 1.7.0", + "smallvec 1.8.0", "unsigned-varint 0.7.0", "wasm-timer", ] @@ -3818,7 +3818,7 @@ dependencies = [ "lru 0.6.6", "prost", "prost-build", - "smallvec 1.7.0", + "smallvec 1.8.0", "wasm-timer", ] @@ -3841,7 +3841,7 @@ dependencies = [ "prost-build", "rand 0.7.3", "sha2 0.9.8", - "smallvec 1.7.0", + "smallvec 1.8.0", "uint", "unsigned-varint 0.7.0", "void", @@ -3864,7 +3864,7 @@ dependencies = [ "libp2p-swarm", "log 0.4.14", "rand 0.8.4", - "smallvec 1.7.0", + "smallvec 1.8.0", "socket2 0.4.0", "void", ] @@ -3897,7 +3897,7 @@ dependencies = [ "nohash-hasher", "parking_lot 0.11.2", "rand 0.7.3", - "smallvec 1.7.0", + "smallvec 1.8.0", "unsigned-varint 0.7.0", ] @@ -3986,7 +3986,7 @@ dependencies = [ "prost", "prost-build", "rand 0.7.3", - "smallvec 1.7.0", + "smallvec 1.8.0", "unsigned-varint 0.7.0", "void", "wasm-timer", @@ -4028,7 +4028,7 @@ dependencies = [ "log 0.4.14", "lru 0.7.0", "rand 0.7.3", - "smallvec 1.7.0", + "smallvec 1.8.0", "unsigned-varint 0.7.0", "wasm-timer", ] @@ -4044,7 +4044,7 @@ dependencies = [ "libp2p-core", "log 0.4.14", "rand 0.7.3", - "smallvec 1.7.0", + "smallvec 1.8.0", "void", "wasm-timer", ] @@ -4650,7 +4650,7 @@ dependencies = [ "futures 0.3.19", "log 0.4.14", "pin-project 1.0.10", - "smallvec 1.7.0", + "smallvec 1.8.0", "unsigned-varint 0.7.0", ] @@ -5416,7 +5416,7 @@ dependencies = [ "scale-info", "serde", "serde_json", - "smallvec 1.7.0", + "smallvec 1.8.0", "sp-core", "sp-io", "sp-runtime", @@ -5720,7 +5720,7 @@ dependencies = [ "rand_pcg 0.3.1", "scale-info", "serde", - "smallvec 1.7.0", + "smallvec 1.8.0", "sp-core", "sp-io", "sp-keystore", @@ -6494,7 +6494,7 @@ dependencies = [ "scale-info", "serde", "serde_json", - "smallvec 1.7.0", + "smallvec 1.8.0", "sp-core", "sp-io", "sp-runtime", @@ -6692,7 +6692,7 @@ dependencies = [ "parity-util-mem-derive", "parking_lot 0.12.0", "primitive-types", - "smallvec 1.7.0", + "smallvec 1.8.0", "winapi 0.3.9", ] @@ -6803,7 +6803,7 @@ dependencies = [ "instant", "libc", "redox_syscall 0.2.10", - "smallvec 1.7.0", + "smallvec 1.8.0", "winapi 0.3.9", ] @@ -6816,7 +6816,7 @@ dependencies = [ "cfg-if 1.0.0", "libc", "redox_syscall 0.2.10", - "smallvec 1.7.0", + "smallvec 1.8.0", "windows-sys", ] @@ -7629,7 +7629,7 @@ checksum = "571f7f397d61c4755285cd37853fe8e03271c243424a907415909379659381c5" dependencies = [ "log 0.4.14", "rustc-hash", - "smallvec 1.7.0", + "smallvec 1.8.0", ] [[package]] @@ -7640,7 +7640,7 @@ checksum = "7d808cff91dfca7b239d40b972ba628add94892b1d9e19a842aedc5cfae8ab1a" dependencies = [ "log 0.4.14", "rustc-hash", - "smallvec 1.7.0", + "smallvec 1.8.0", ] [[package]] @@ -8608,7 +8608,7 @@ dependencies = [ "sc-utils", "serde", "serde_json", - "smallvec 1.7.0", + "smallvec 1.8.0", "sp-arithmetic", "sp-blockchain", "sp-consensus", @@ -9484,9 +9484,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" [[package]] name = "snap" @@ -10227,7 +10227,7 @@ dependencies = [ "parking_lot 0.12.0", "pretty_assertions", "rand 0.7.3", - "smallvec 1.7.0", + "smallvec 1.8.0", "sp-core", "sp-externalities", "sp-panic-handler", @@ -11190,7 +11190,7 @@ dependencies = [ "serde", "serde_json", "sharded-slab", - "smallvec 1.7.0", + "smallvec 1.8.0", "thread_local", "tracing", "tracing-core", @@ -11236,7 +11236,7 @@ dependencies = [ "hashbrown 0.12.0", "log 0.4.14", "rustc-hex", - "smallvec 1.7.0", + "smallvec 1.8.0", ] [[package]] @@ -11276,7 +11276,7 @@ dependencies = [ "lazy_static", "log 0.4.14", "rand 0.8.4", - "smallvec 1.7.0", + "smallvec 1.8.0", "thiserror", "tinyvec", "url 2.2.1", @@ -11296,7 +11296,7 @@ dependencies = [ "lru-cache", "parking_lot 0.11.2", "resolv-conf", - "smallvec 1.7.0", + "smallvec 1.8.0", "thiserror", "trust-dns-proto", ] @@ -11737,7 +11737,7 @@ dependencies = [ "enumset", "serde", "serde_bytes", - "smallvec 1.7.0", + "smallvec 1.8.0", "target-lexicon 0.11.2", "thiserror", "wasmer-types", @@ -11757,7 +11757,7 @@ dependencies = [ "more-asserts", "rayon", "serde", - "smallvec 1.7.0", + "smallvec 1.8.0", "tracing", "wasmer-compiler", "wasmer-types", @@ -11777,7 +11777,7 @@ dependencies = [ "more-asserts", "rayon", "serde", - "smallvec 1.7.0", + "smallvec 1.8.0", "wasmer-compiler", "wasmer-types", "wasmer-vm", diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index c26d90b8952e..2e5bb3ea0ee5 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -46,7 +46,7 @@ sc-client-api = { version = "4.0.0-dev", path = "../api" } sc-peerset = { version = "4.0.0-dev", path = "../peerset" } serde = { version = "1.0.136", features = ["derive"] } serde_json = "1.0.74" -smallvec = "1.7.0" +smallvec = "1.8.0" sp-arithmetic = { version = "4.0.0", path = "../../primitives/arithmetic" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } diff --git a/frame/support/Cargo.toml b/frame/support/Cargo.toml index 9bb7ae5d8af8..cd6a082e57cf 100644 --- a/frame/support/Cargo.toml +++ b/frame/support/Cargo.toml @@ -32,7 +32,7 @@ once_cell = { version = "1", default-features = false, optional = true } sp-state-machine = { version = "0.11.0", optional = true, path = "../../primitives/state-machine" } bitflags = "1.3" impl-trait-for-tuples = "0.2.1" -smallvec = "1.7.0" +smallvec = "1.8.0" log = { version = "0.4.14", default-features = false } sp-core-hashing-proc-macro = { version = "4.0.0-dev", path = "../../primitives/core/hashing/proc-macro" } diff --git a/frame/transaction-payment/Cargo.toml b/frame/transaction-payment/Cargo.toml index fe6b4e0e2c7c..0d2388e05bd2 100644 --- a/frame/transaction-payment/Cargo.toml +++ b/frame/transaction-payment/Cargo.toml @@ -18,7 +18,7 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = ] } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } serde = { version = "1.0.136", optional = true } -smallvec = "1.7.0" +smallvec = "1.8.0" sp-core = { version = "5.0.0", path = "../../primitives/core", default-features = false } sp-io = { version = "5.0.0", path = "../../primitives/io", default-features = false } diff --git a/frame/transaction-payment/asset-tx-payment/Cargo.toml b/frame/transaction-payment/asset-tx-payment/Cargo.toml index 7768ae76847a..b3471b38045f 100644 --- a/frame/transaction-payment/asset-tx-payment/Cargo.toml +++ b/frame/transaction-payment/asset-tx-payment/Cargo.toml @@ -29,7 +29,7 @@ scale-info = { version = "2.0.0", default-features = false, features = ["derive" serde = { version = "1.0.136", optional = true } [dev-dependencies] -smallvec = "1.7.0" +smallvec = "1.8.0" serde_json = "1.0.74" sp-storage = { version = "5.0.0", default-features = false, path = "../../../primitives/storage" } diff --git a/primitives/state-machine/Cargo.toml b/primitives/state-machine/Cargo.toml index 300af627f71b..9e0c0c026a23 100644 --- a/primitives/state-machine/Cargo.toml +++ b/primitives/state-machine/Cargo.toml @@ -27,7 +27,7 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = num-traits = { version = "0.2.8", default-features = false } rand = { version = "0.7.2", optional = true } sp-externalities = { version = "0.11.0", path = "../externalities", default-features = false } -smallvec = "1.7.0" +smallvec = "1.8.0" sp-std = { version = "4.0.0", default-features = false, path = "../std" } tracing = { version = "0.1.29", optional = true } From b4c188b3904209aba4b331ab19c46c8d0ff64d3c Mon Sep 17 00:00:00 2001 From: Guillaume Thiolliere Date: Tue, 1 Mar 2022 14:31:51 +0100 Subject: [PATCH 544/695] new pallet: whitelist pallet (#10159) * pallet whitelist * refactor a bit * fmt * address audit * improve tests * return Ok + refund * add test for dispatching failing * add dispatch_whitelisted_call_with_preimage * fmt * better name * Consume all data on decode Signed-off-by: Oliver Tale-Yazdi * Add error docs Signed-off-by: Oliver Tale-Yazdi * Remove phantom data Signed-off-by: Oliver Tale-Yazdi * Use rust 2021 Signed-off-by: Oliver Tale-Yazdi * Update crate features Signed-off-by: Oliver Tale-Yazdi * Fmt Signed-off-by: Oliver Tale-Yazdi * Make compile Signed-off-by: Oliver Tale-Yazdi * cargo run --quiet --profile=production --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_whitelist --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/whitelist/src/weights.rs --template=./.maintain/frame-weight-template.hbs * Bump Preimage max size Signed-off-by: Oliver Tale-Yazdi * cargo run --quiet --profile=production --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_whitelist --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/whitelist/src/weights.rs --template=./.maintain/frame-weight-template.hbs * Fmt Signed-off-by: Oliver Tale-Yazdi Co-authored-by: Oliver Tale-Yazdi Co-authored-by: Parity Bot --- Cargo.lock | 19 +++ Cargo.toml | 1 + bin/node/runtime/Cargo.toml | 3 + bin/node/runtime/src/lib.rs | 11 ++ frame/conviction-voting/Cargo.toml | 2 +- frame/referenda/Cargo.toml | 2 +- frame/whitelist/Cargo.toml | 47 ++++++ frame/whitelist/src/benchmarking.rs | 120 ++++++++++++++ frame/whitelist/src/lib.rs | 244 ++++++++++++++++++++++++++++ frame/whitelist/src/mock.rs | 124 ++++++++++++++ frame/whitelist/src/tests.rs | 175 ++++++++++++++++++++ frame/whitelist/src/weights.rs | 126 ++++++++++++++ primitives/runtime/src/lib.rs | 2 +- 13 files changed, 873 insertions(+), 3 deletions(-) create mode 100644 frame/whitelist/Cargo.toml create mode 100644 frame/whitelist/src/benchmarking.rs create mode 100644 frame/whitelist/src/lib.rs create mode 100644 frame/whitelist/src/mock.rs create mode 100644 frame/whitelist/src/tests.rs create mode 100644 frame/whitelist/src/weights.rs diff --git a/Cargo.lock b/Cargo.lock index 08d44487776d..2bd91ca7b6b8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5019,6 +5019,7 @@ dependencies = [ "pallet-uniques", "pallet-utility", "pallet-vesting", + "pallet-whitelist", "parity-scale-codec", "scale-info", "sp-api", @@ -6615,6 +6616,24 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-whitelist" +version = "4.0.0-dev" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "pallet-balances", + "pallet-preimage", + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + [[package]] name = "parity-db" version = "0.3.5" diff --git a/Cargo.toml b/Cargo.toml index a12910c52c01..f24ff6d04980 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -138,6 +138,7 @@ members = [ "frame/uniques", "frame/utility", "frame/vesting", + "frame/whitelist", "primitives/api", "primitives/api/proc-macro", "primitives/api/test", diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 0055230295a1..39c4609c4425 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -100,6 +100,7 @@ pallet-asset-tx-payment = { version = "4.0.0-dev", default-features = false, pat pallet-transaction-storage = { version = "4.0.0-dev", default-features = false, path = "../../../frame/transaction-storage" } pallet-uniques = { version = "4.0.0-dev", default-features = false, path = "../../../frame/uniques" } pallet-vesting = { version = "4.0.0-dev", default-features = false, path = "../../../frame/vesting" } +pallet-whitelist = { version = "4.0.0-dev", default-features = false, path = "../../../frame/whitelist" } [build-dependencies] substrate-wasm-builder = { version = "5.0.0-dev", path = "../../../utils/wasm-builder" } @@ -220,6 +221,7 @@ runtime-benchmarks = [ "pallet-utility/runtime-benchmarks", "pallet-uniques/runtime-benchmarks", "pallet-vesting/runtime-benchmarks", + "pallet-whitelist/runtime-benchmarks", "frame-system-benchmarking", "hex-literal", ] @@ -267,6 +269,7 @@ try-runtime = [ "pallet-uniques/try-runtime", "pallet-utility/try-runtime", "pallet-vesting/try-runtime", + "pallet-whitelist/try-runtime", ] # Make contract callable functions marked as __unstable__ available. Do not enable # on live chains as those are subject to change. diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 0aff3d8046ee..9ff19760c775 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -1357,6 +1357,15 @@ impl pallet_transaction_storage::Config for Runtime { type WeightInfo = pallet_transaction_storage::weights::SubstrateWeight; } +impl pallet_whitelist::Config for Runtime { + type Event = Event; + type Call = Call; + type WhitelistOrigin = EnsureRoot; + type DispatchWhitelistedOrigin = EnsureRoot; + type PreimageProvider = Preimage; + type WeightInfo = pallet_whitelist::weights::SubstrateWeight; +} + construct_runtime!( pub enum Runtime where Block = Block, @@ -1411,6 +1420,7 @@ construct_runtime!( ChildBounties: pallet_child_bounties, Referenda: pallet_referenda, ConvictionVoting: pallet_conviction_voting, + Whitelist: pallet_whitelist, } ); @@ -1509,6 +1519,7 @@ mod benches { [pallet_uniques, Uniques] [pallet_utility, Utility] [pallet_vesting, Vesting] + [pallet_whitelist, Whitelist] ); } diff --git a/frame/conviction-voting/Cargo.toml b/frame/conviction-voting/Cargo.toml index 039fdb07caab..7e9930257435 100644 --- a/frame/conviction-voting/Cargo.toml +++ b/frame/conviction-voting/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-conviction-voting" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/referenda/Cargo.toml b/frame/referenda/Cargo.toml index a3067956db2b..56598af91393 100644 --- a/frame/referenda/Cargo.toml +++ b/frame/referenda/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-referenda" version = "4.0.0-dev" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "Apache-2.0" homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate/" diff --git a/frame/whitelist/Cargo.toml b/frame/whitelist/Cargo.toml new file mode 100644 index 000000000000..057e7fd71f30 --- /dev/null +++ b/frame/whitelist/Cargo.toml @@ -0,0 +1,47 @@ +[package] +name = "pallet-whitelist" +version = "4.0.0-dev" +authors = ["Parity Technologies "] +edition = "2021" +license = "Apache-2.0" +homepage = "https://substrate.io" +repository = "https://github.com/paritytech/substrate/" +description = "FRAME pallet for whitelisting call, and dispatch from specific origin" +readme = "README.md" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } +scale-info = { version = "2.0", default-features = false, features = ["derive"] } +sp-api = { version = "4.0.0-dev", default-features = false, path = "../../primitives/api" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } +sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } +frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } +frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } + +[dev-dependencies] +sp-core = { version = "5.0.0", path = "../../primitives/core" } +pallet-preimage = { version = "4.0.0-dev", path = "../preimage/" } +pallet-balances = { version = "4.0.0-dev", path = "../balances/" } + +[features] +default = ["std"] +std = [ + "codec/std", + "scale-info/std", + "sp-std/std", + "sp-io/std", + "sp-runtime/std", + "frame-support/std", + "frame-system/std", +] +runtime-benchmarks = [ + "frame-benchmarking", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", +] +try-runtime = ["frame-support/try-runtime"] diff --git a/frame/whitelist/src/benchmarking.rs b/frame/whitelist/src/benchmarking.rs new file mode 100644 index 000000000000..c51ea0a0a324 --- /dev/null +++ b/frame/whitelist/src/benchmarking.rs @@ -0,0 +1,120 @@ +// This file is part of Substrate. + +// Copyright (C) 2021 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. + +//! Whitelist pallet benchmarking. + +#![cfg(feature = "runtime-benchmarks")] + +use super::*; +use core::convert::TryInto; +use frame_benchmarking::benchmarks; +use frame_support::{ensure, traits::PreimageRecipient}; +use sp_runtime::traits::Hash; + +#[cfg(test)] +use crate::Pallet as Whitelist; + +benchmarks! { + whitelist_call { + let origin = T::WhitelistOrigin::successful_origin(); + let call_hash = Default::default(); + }: _(origin, call_hash) + verify { + ensure!( + WhitelistedCall::::contains_key(call_hash), + "call not whitelisted" + ); + ensure!( + T::PreimageProvider::preimage_requested(&call_hash), + "preimage not requested" + ); + } + + remove_whitelisted_call { + let origin = T::WhitelistOrigin::successful_origin(); + let call_hash = Default::default(); + Pallet::::whitelist_call(origin.clone(), call_hash) + .expect("whitelisting call must be successful"); + }: _(origin, call_hash) + verify { + ensure!( + !WhitelistedCall::::contains_key(call_hash), + "whitelist not removed" + ); + ensure!( + !T::PreimageProvider::preimage_requested(&call_hash), + "preimage still requested" + ); + } + + // We benchmark with the maximum possible size for a call. + // If the resulting weight is too big, maybe it worth having a weight which depends + // on the size of the call, with a new witness in parameter. + dispatch_whitelisted_call { + let origin = T::DispatchWhitelistedOrigin::successful_origin(); + // NOTE: we remove `10` because we need some bytes to encode the variants and vec length + let remark_len = >::MaxSize::get() - 10; + let remark = sp_std::vec![1_8; remark_len as usize]; + + let call: ::Call = frame_system::Call::remark { remark }.into(); + let call_weight = call.get_dispatch_info().weight; + let encoded_call = call.encode(); + let call_hash = T::Hashing::hash(&encoded_call[..]); + + Pallet::::whitelist_call(origin.clone(), call_hash) + .expect("whitelisting call must be successful"); + + let encoded_call = encoded_call.try_into().expect("encoded_call must be small enough"); + T::PreimageProvider::note_preimage(encoded_call); + + }: _(origin, call_hash, call_weight) + verify { + ensure!( + !WhitelistedCall::::contains_key(call_hash), + "whitelist not removed" + ); + ensure!( + !T::PreimageProvider::preimage_requested(&call_hash), + "preimage still requested" + ); + } + + dispatch_whitelisted_call_with_preimage { + let n in 1 .. 10_000; + + let origin = T::DispatchWhitelistedOrigin::successful_origin(); + let remark = sp_std::vec![1u8; n as usize]; + + let call: ::Call = frame_system::Call::remark { remark }.into(); + let call_hash = T::Hashing::hash_of(&call); + + Pallet::::whitelist_call(origin.clone(), call_hash) + .expect("whitelisting call must be successful"); + }: _(origin, Box::new(call)) + verify { + ensure!( + !WhitelistedCall::::contains_key(call_hash), + "whitelist not removed" + ); + ensure!( + !T::PreimageProvider::preimage_requested(&call_hash), + "preimage still requested" + ); + } + + impl_benchmark_test_suite!(Whitelist, crate::mock::new_test_ext(), crate::mock::Test); +} diff --git a/frame/whitelist/src/lib.rs b/frame/whitelist/src/lib.rs new file mode 100644 index 000000000000..9f20386da85f --- /dev/null +++ b/frame/whitelist/src/lib.rs @@ -0,0 +1,244 @@ +// This file is part of Substrate. + +// Copyright (C) 2021 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. + +//! # Whitelist Pallet +//! +//! - [`Config`] +//! - [`Call`] +//! +//! ## Overview +//! +//! Allow some configurable origin: [`Config::WhitelistOrigin`] to whitelist some hash of a call, +//! and allow another configurable origin: [`Config::DispatchWhitelistedOrigin`] to dispatch them +//! with the root origin. +//! +//! In the meantime the call corresponding to the hash must have been submitted to the to the +//! pre-image handler [`PreimageProvider`]. + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; +#[cfg(test)] +mod mock; +#[cfg(test)] +mod tests; +pub mod weights; + +use sp_runtime::traits::Dispatchable; +use sp_std::prelude::*; + +use codec::{Decode, DecodeLimit, Encode, FullCodec, MaxEncodedLen}; +use frame_support::{ + ensure, + traits::{PreimageProvider, PreimageRecipient}, + weights::{GetDispatchInfo, PostDispatchInfo}, +}; +use scale_info::TypeInfo; +use sp_api::HashT; +use weights::WeightInfo; + +use frame_support::pallet_prelude::*; +use frame_system::pallet_prelude::*; + +pub use pallet::*; + +#[derive(Clone, Encode, Decode, TypeInfo, MaxEncodedLen)] +pub struct Preimage { + preimage: BoundedVec, + deposit: Option<(AccountId, Balance)>, +} + +#[frame_support::pallet] +pub mod pallet { + use super::*; + + #[pallet::config] + pub trait Config: frame_system::Config { + /// The overarching event type. + type Event: From> + IsType<::Event>; + + /// The overarching call type. + type Call: IsType<::Call> + + Dispatchable + + GetDispatchInfo + + FullCodec + + TypeInfo + + From> + + Parameter; + + /// Required origin for whitelisting a call. + type WhitelistOrigin: EnsureOrigin; + + /// Required origin for dispatching whitelisted call with root origin. + type DispatchWhitelistedOrigin: EnsureOrigin; + + /// The handler of pre-images. + // NOTE: recipient is only needed for benchmarks. + type PreimageProvider: PreimageProvider + PreimageRecipient; + + /// The weight information for this pallet. + type WeightInfo: weights::WeightInfo; + } + + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet(_); + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + CallWhitelisted { call_hash: T::Hash }, + WhitelistedCallRemoved { call_hash: T::Hash }, + WhitelistedCallDispatched { call_hash: T::Hash, result: DispatchResultWithPostInfo }, + } + + #[pallet::error] + pub enum Error { + /// The preimage of the call hash could not be loaded. + UnavailablePreImage, + /// The call could not be decoded. + UndecodableCall, + /// The weight of the decoded call was higher than the witness. + InvalidCallWeightWitness, + /// The call was not whitelisted. + CallIsNotWhitelisted, + /// The call was already whitelisted; No-Op. + CallAlreadyWhitelisted, + } + + #[pallet::storage] + pub type WhitelistedCall = StorageMap<_, Twox64Concat, T::Hash, (), OptionQuery>; + + #[pallet::call] + impl Pallet { + #[pallet::weight(T::WeightInfo::whitelist_call())] + pub fn whitelist_call(origin: OriginFor, call_hash: T::Hash) -> DispatchResult { + T::WhitelistOrigin::ensure_origin(origin)?; + + ensure!( + !WhitelistedCall::::contains_key(call_hash), + Error::::CallAlreadyWhitelisted, + ); + + WhitelistedCall::::insert(call_hash, ()); + T::PreimageProvider::request_preimage(&call_hash); + + Self::deposit_event(Event::::CallWhitelisted { call_hash }); + + Ok(()) + } + + #[pallet::weight(T::WeightInfo::remove_whitelisted_call())] + pub fn remove_whitelisted_call(origin: OriginFor, call_hash: T::Hash) -> DispatchResult { + T::WhitelistOrigin::ensure_origin(origin)?; + + WhitelistedCall::::take(call_hash).ok_or(Error::::CallIsNotWhitelisted)?; + + T::PreimageProvider::unrequest_preimage(&call_hash); + + Self::deposit_event(Event::::WhitelistedCallRemoved { call_hash }); + + Ok(()) + } + + #[pallet::weight( + T::WeightInfo::dispatch_whitelisted_call().saturating_add(*call_weight_witness) + )] + pub fn dispatch_whitelisted_call( + origin: OriginFor, + call_hash: T::Hash, + call_weight_witness: Weight, + ) -> DispatchResultWithPostInfo { + T::DispatchWhitelistedOrigin::ensure_origin(origin)?; + + ensure!( + WhitelistedCall::::contains_key(call_hash), + Error::::CallIsNotWhitelisted, + ); + + let call = T::PreimageProvider::get_preimage(&call_hash) + .ok_or(Error::::UnavailablePreImage)?; + + let call = ::Call::decode_all_with_depth_limit( + sp_api::MAX_EXTRINSIC_DEPTH, + &mut &call[..], + ) + .map_err(|_| Error::::UndecodableCall)?; + + ensure!( + call.get_dispatch_info().weight <= call_weight_witness, + Error::::InvalidCallWeightWitness + ); + + let actual_weight = Self::clean_and_dispatch(call_hash, call) + .map(|w| w.saturating_add(T::WeightInfo::dispatch_whitelisted_call())); + + Ok(actual_weight.into()) + } + + #[pallet::weight({ + let call_weight = call.get_dispatch_info().weight; + let call_len = call.encoded_size() as u32; + + T::WeightInfo::dispatch_whitelisted_call_with_preimage(call_len) + .saturating_add(call_weight) + })] + pub fn dispatch_whitelisted_call_with_preimage( + origin: OriginFor, + call: Box<::Call>, + ) -> DispatchResultWithPostInfo { + T::DispatchWhitelistedOrigin::ensure_origin(origin)?; + + let call_hash = ::Hashing::hash_of(&call); + + ensure!( + WhitelistedCall::::contains_key(call_hash), + Error::::CallIsNotWhitelisted, + ); + + let call_len = call.encoded_size() as u32; + let actual_weight = Self::clean_and_dispatch(call_hash, *call).map(|w| { + w.saturating_add(T::WeightInfo::dispatch_whitelisted_call_with_preimage(call_len)) + }); + + Ok(actual_weight.into()) + } + } +} + +impl Pallet { + /// Clean whitelisting/preimage and dispatch call. + /// + /// Return the call actual weight of the dispatched call if there is some. + fn clean_and_dispatch(call_hash: T::Hash, call: ::Call) -> Option { + WhitelistedCall::::remove(call_hash); + + T::PreimageProvider::unrequest_preimage(&call_hash); + + let result = call.dispatch(frame_system::Origin::::Root.into()); + + let call_actual_weight = match result { + Ok(call_post_info) => call_post_info.actual_weight, + Err(call_err) => call_err.post_info.actual_weight, + }; + + Self::deposit_event(Event::::WhitelistedCallDispatched { call_hash, result }); + + call_actual_weight + } +} diff --git a/frame/whitelist/src/mock.rs b/frame/whitelist/src/mock.rs new file mode 100644 index 000000000000..3009a6f6b5d5 --- /dev/null +++ b/frame/whitelist/src/mock.rs @@ -0,0 +1,124 @@ +// This file is part of Substrate. + +// Copyright (C) 2021 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. + +// Mock for Whitelist Pallet + +#![cfg(test)] + +use crate as pallet_whitelist; + +use frame_support::{ + parameter_types, + traits::{ConstU32, ConstU64, Nothing}, +}; +use frame_system::EnsureRoot; +use sp_core::H256; +use sp_runtime::{ + testing::Header, + traits::{BlakeTwo256, IdentityLookup}, + BuildStorage, +}; + +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlock; + +frame_support::construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system, + Balances: pallet_balances, + Whitelist: pallet_whitelist, + Preimage: pallet_preimage, + } +); + +frame_support::parameter_types! { + pub BlockWeights: frame_system::limits::BlockWeights = + frame_system::limits::BlockWeights::simple_max(1024); +} +impl frame_system::Config for Test { + type BaseCallFilter = Nothing; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Call = Call; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = Event; + type BlockHashCount = ConstU64<250>; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = ConstU32<16>; +} + +impl pallet_balances::Config for Test { + type MaxLocks = (); + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; + type Balance = u64; + type Event = Event; + type DustRemoval = (); + type ExistentialDeposit = ConstU64<1>; + type AccountStore = System; + type WeightInfo = (); +} + +parameter_types! { + // Taken from Polkadot as reference. + pub const PreimageMaxSize: u32 = 4096 * 1024; +} + +impl pallet_preimage::Config for Test { + type Event = Event; + type Currency = Balances; + type ManagerOrigin = EnsureRoot; + type MaxSize = PreimageMaxSize; + type BaseDeposit = ConstU64<1>; + type ByteDeposit = ConstU64<1>; + type WeightInfo = (); +} + +impl pallet_whitelist::Config for Test { + type Event = Event; + type Call = Call; + type WhitelistOrigin = EnsureRoot; + type DispatchWhitelistedOrigin = EnsureRoot; + type PreimageProvider = Preimage; + type WeightInfo = (); +} + +pub fn new_test_ext() -> sp_io::TestExternalities { + let t = GenesisConfig::default().build_storage().unwrap(); + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| System::set_block_number(1)); + ext +} diff --git a/frame/whitelist/src/tests.rs b/frame/whitelist/src/tests.rs new file mode 100644 index 000000000000..67bccaeaeebe --- /dev/null +++ b/frame/whitelist/src/tests.rs @@ -0,0 +1,175 @@ +// This file is part of Substrate. + +// Copyright (C) 2021 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. + +// Tests for Whitelist Pallet + +use crate::mock::*; +use codec::Encode; +use frame_support::{assert_noop, assert_ok, dispatch::GetDispatchInfo, traits::PreimageProvider}; +use sp_runtime::{traits::Hash, DispatchError}; + +#[test] +fn test_whitelist_call_and_remove() { + new_test_ext().execute_with(|| { + let call = Call::System(frame_system::Call::remark { remark: vec![] }); + let encoded_call = call.encode(); + let call_hash = ::Hashing::hash(&encoded_call[..]); + + assert_noop!( + Whitelist::remove_whitelisted_call(Origin::root(), call_hash), + crate::Error::::CallIsNotWhitelisted, + ); + + assert_noop!( + Whitelist::whitelist_call(Origin::signed(1), call_hash), + DispatchError::BadOrigin, + ); + + assert_ok!(Whitelist::whitelist_call(Origin::root(), call_hash)); + + assert!(Preimage::preimage_requested(&call_hash)); + + assert_noop!( + Whitelist::whitelist_call(Origin::root(), call_hash), + crate::Error::::CallAlreadyWhitelisted, + ); + + assert_noop!( + Whitelist::remove_whitelisted_call(Origin::signed(1), call_hash), + DispatchError::BadOrigin, + ); + + assert_ok!(Whitelist::remove_whitelisted_call(Origin::root(), call_hash)); + + assert!(!Preimage::preimage_requested(&call_hash)); + + assert_noop!( + Whitelist::remove_whitelisted_call(Origin::root(), call_hash), + crate::Error::::CallIsNotWhitelisted, + ); + }); +} + +#[test] +fn test_whitelist_call_and_execute() { + new_test_ext().execute_with(|| { + let call = Call::System(frame_system::Call::remark_with_event { remark: vec![1] }); + let call_weight = call.get_dispatch_info().weight; + let encoded_call = call.encode(); + let call_hash = ::Hashing::hash(&encoded_call[..]); + + assert_noop!( + Whitelist::dispatch_whitelisted_call(Origin::root(), call_hash, call_weight), + crate::Error::::CallIsNotWhitelisted, + ); + + assert_ok!(Whitelist::whitelist_call(Origin::root(), call_hash)); + + assert_noop!( + Whitelist::dispatch_whitelisted_call(Origin::signed(1), call_hash, call_weight), + DispatchError::BadOrigin, + ); + + assert_noop!( + Whitelist::dispatch_whitelisted_call(Origin::root(), call_hash, call_weight), + crate::Error::::UnavailablePreImage, + ); + + assert_ok!(Preimage::note_preimage(Origin::root(), encoded_call)); + + assert!(Preimage::preimage_requested(&call_hash)); + + assert_noop!( + Whitelist::dispatch_whitelisted_call(Origin::root(), call_hash, call_weight - 1), + crate::Error::::InvalidCallWeightWitness, + ); + + assert_ok!(Whitelist::dispatch_whitelisted_call(Origin::root(), call_hash, call_weight)); + + assert!(!Preimage::preimage_requested(&call_hash)); + + assert_noop!( + Whitelist::dispatch_whitelisted_call(Origin::root(), call_hash, call_weight), + crate::Error::::CallIsNotWhitelisted, + ); + }); +} + +#[test] +fn test_whitelist_call_and_execute_failing_call() { + new_test_ext().execute_with(|| { + let call = Call::Whitelist(crate::Call::dispatch_whitelisted_call { + call_hash: Default::default(), + call_weight_witness: 0, + }); + let call_weight = call.get_dispatch_info().weight; + let encoded_call = call.encode(); + let call_hash = ::Hashing::hash(&encoded_call[..]); + + assert_ok!(Whitelist::whitelist_call(Origin::root(), call_hash)); + assert_ok!(Preimage::note_preimage(Origin::root(), encoded_call)); + assert!(Preimage::preimage_requested(&call_hash)); + assert_ok!(Whitelist::dispatch_whitelisted_call(Origin::root(), call_hash, call_weight)); + assert!(!Preimage::preimage_requested(&call_hash)); + }); +} + +#[test] +fn test_whitelist_call_and_execute_without_note_preimage() { + new_test_ext().execute_with(|| { + let call = + Box::new(Call::System(frame_system::Call::remark_with_event { remark: vec![1] })); + let call_hash = ::Hashing::hash_of(&call); + + assert_ok!(Whitelist::whitelist_call(Origin::root(), call_hash)); + assert!(Preimage::preimage_requested(&call_hash)); + + assert_ok!(Whitelist::dispatch_whitelisted_call_with_preimage( + Origin::root(), + call.clone() + )); + + assert!(!Preimage::preimage_requested(&call_hash)); + + assert_noop!( + Whitelist::dispatch_whitelisted_call_with_preimage(Origin::root(), call), + crate::Error::::CallIsNotWhitelisted, + ); + }); +} + +#[test] +fn test_whitelist_call_and_execute_decode_consumes_all() { + new_test_ext().execute_with(|| { + let call = Call::System(frame_system::Call::remark_with_event { remark: vec![1] }); + let call_weight = call.get_dispatch_info().weight; + let mut call = call.encode(); + // Appending something does not make the encoded call invalid. + // This tests that the decode function consumes all data. + call.extend(call.clone()); + + let call_hash = ::Hashing::hash(&call[..]); + + assert_ok!(Preimage::note_preimage(Origin::root(), call)); + assert_ok!(Whitelist::whitelist_call(Origin::root(), call_hash)); + + assert_noop!( + Whitelist::dispatch_whitelisted_call(Origin::root(), call_hash, call_weight), + crate::Error::::UndecodableCall, + ); + }); +} diff --git a/frame/whitelist/src/weights.rs b/frame/whitelist/src/weights.rs new file mode 100644 index 000000000000..fdba734db64b --- /dev/null +++ b/frame/whitelist/src/weights.rs @@ -0,0 +1,126 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +//! Autogenerated weights for pallet_whitelist +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2022-02-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 + +// Executed Command: +// target/production/substrate +// benchmark +// --chain=dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_whitelist +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 +// --output=./frame/whitelist/src/weights.rs +// --template=./.maintain/frame-weight-template.hbs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +/// Weight functions needed for pallet_whitelist. +pub trait WeightInfo { + fn whitelist_call() -> Weight; + fn remove_whitelisted_call() -> Weight; + fn dispatch_whitelisted_call() -> Weight; + fn dispatch_whitelisted_call_with_preimage(n: u32, ) -> Weight; +} + +/// Weights for pallet_whitelist using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + // Storage: Whitelist WhitelistedCall (r:1 w:1) + // Storage: Preimage StatusFor (r:1 w:1) + fn whitelist_call() -> Weight { + (16_254_000 as Weight) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + } + // Storage: Whitelist WhitelistedCall (r:1 w:1) + // Storage: Preimage StatusFor (r:1 w:1) + // Storage: Preimage PreimageFor (r:0 w:1) + fn remove_whitelisted_call() -> Weight { + (18_348_000 as Weight) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } + // Storage: Whitelist WhitelistedCall (r:1 w:1) + // Storage: Preimage PreimageFor (r:1 w:1) + // Storage: Preimage StatusFor (r:1 w:1) + fn dispatch_whitelisted_call() -> Weight { + (6_618_241_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } + // Storage: Whitelist WhitelistedCall (r:1 w:1) + // Storage: Preimage StatusFor (r:1 w:1) + // Storage: Preimage PreimageFor (r:0 w:1) + fn dispatch_whitelisted_call_with_preimage(n: u32, ) -> Weight { + (20_619_000 as Weight) + // Standard Error: 0 + .saturating_add((2_000 as Weight).saturating_mul(n as Weight)) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } +} + +// For backwards compatibility and tests +impl WeightInfo for () { + // Storage: Whitelist WhitelistedCall (r:1 w:1) + // Storage: Preimage StatusFor (r:1 w:1) + fn whitelist_call() -> Weight { + (16_254_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + } + // Storage: Whitelist WhitelistedCall (r:1 w:1) + // Storage: Preimage StatusFor (r:1 w:1) + // Storage: Preimage PreimageFor (r:0 w:1) + fn remove_whitelisted_call() -> Weight { + (18_348_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + } + // Storage: Whitelist WhitelistedCall (r:1 w:1) + // Storage: Preimage PreimageFor (r:1 w:1) + // Storage: Preimage StatusFor (r:1 w:1) + fn dispatch_whitelisted_call() -> Weight { + (6_618_241_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + } + // Storage: Whitelist WhitelistedCall (r:1 w:1) + // Storage: Preimage StatusFor (r:1 w:1) + // Storage: Preimage PreimageFor (r:0 w:1) + fn dispatch_whitelisted_call_with_preimage(n: u32, ) -> Weight { + (20_619_000 as Weight) + // Standard Error: 0 + .saturating_add((2_000 as Weight).saturating_mul(n as Weight)) + .saturating_add(RocksDbWeight::get().reads(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + } +} diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 6d32d2322c76..a428da59f6a0 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -511,7 +511,7 @@ pub enum DispatchError { /// Result of a `Dispatchable` which contains the `DispatchResult` and additional information about /// the `Dispatchable` that is only known post dispatch. -#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, RuntimeDebug)] +#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, RuntimeDebug, TypeInfo)] pub struct DispatchErrorWithPostInfo where Info: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable, From d14784fee8eddead26efc8617c512cc8775bfde5 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 1 Mar 2022 13:35:23 +0000 Subject: [PATCH 545/695] Release primitive crates (#10937) * cargo set-version --bump major -p pallet-contracts-primitives * cargo set-version --bump major -p sp-core * cargo set-version --bump major -p sp-runtime-interface * cargo set-version --bump major -p sp-wasm-interface * cargo set-version --bump major -p sp-runtime * cargo set-version --bump major -p sp-storage * cargo set-version --bump major -p sp-rpc * cargo set-version --bump major -p sp-io * cargo set-version --bump major -p sp-trie * cargo set-version -p sp-state-machine -- 0.12.0 * cargo set-version -p sp-externalities -- 0.12.0 * cargo set-version -p sp-keystore -- 0.12.0 * cargo set-version --bump major -p sp-keyring * cargo set-version --bump major -p sp-version * cargo set-version --bump major -p sp-tracing * cargo set-version --bump major -p sp-application-crypto * cargo set-version --bump major -p sp-arithmetic * cargo unleash version bump-major -p sp-runtime-interface-proc-macro * Add codec max-encoded-len feature to sp-arithmetic * cargo unleash version bump-major -p sp-core-hashing-proc-macro --- Cargo.lock | 38 +++++++++---------- bin/node-template/node/Cargo.toml | 4 +- bin/node-template/pallets/template/Cargo.toml | 6 +-- bin/node-template/runtime/Cargo.toml | 6 +-- bin/node/bench/Cargo.toml | 10 ++--- bin/node/cli/Cargo.toml | 12 +++--- bin/node/executor/Cargo.toml | 18 ++++----- bin/node/inspect/Cargo.toml | 4 +- bin/node/primitives/Cargo.toml | 6 +-- bin/node/rpc/Cargo.toml | 4 +- bin/node/runtime/Cargo.toml | 10 ++--- bin/node/testing/Cargo.toml | 8 ++-- bin/utils/chain-spec-builder/Cargo.toml | 4 +- client/allocator/Cargo.toml | 4 +- client/api/Cargo.toml | 14 +++---- client/authority-discovery/Cargo.toml | 8 ++-- client/basic-authorship/Cargo.toml | 4 +- client/beefy/Cargo.toml | 12 +++--- client/beefy/rpc/Cargo.toml | 4 +- client/block-builder/Cargo.toml | 6 +-- client/chain-spec/Cargo.toml | 4 +- client/cli/Cargo.toml | 10 ++--- client/consensus/aura/Cargo.toml | 12 +++--- client/consensus/babe/Cargo.toml | 14 +++---- client/consensus/babe/rpc/Cargo.toml | 10 ++--- client/consensus/common/Cargo.toml | 6 +-- client/consensus/epochs/Cargo.toml | 2 +- client/consensus/manual-seal/Cargo.toml | 6 +-- client/consensus/pow/Cargo.toml | 4 +- client/consensus/slots/Cargo.toml | 8 ++-- client/consensus/uncles/Cargo.toml | 2 +- client/db/Cargo.toml | 12 +++--- client/executor/Cargo.toml | 20 +++++----- client/executor/common/Cargo.toml | 4 +- client/executor/runtime-test/Cargo.toml | 6 +-- client/executor/wasmi/Cargo.toml | 6 +-- client/executor/wasmtime/Cargo.toml | 8 ++-- client/finality-grandpa/Cargo.toml | 14 +++---- client/finality-grandpa/rpc/Cargo.toml | 8 ++-- client/informant/Cargo.toml | 2 +- client/keystore/Cargo.toml | 6 +-- client/network-gossip/Cargo.toml | 2 +- client/network/Cargo.toml | 8 ++-- client/network/test/Cargo.toml | 6 +-- client/offchain/Cargo.toml | 6 +-- client/rpc-api/Cargo.toml | 10 ++--- client/rpc/Cargo.toml | 12 +++--- client/service/Cargo.toml | 20 +++++----- client/service/test/Cargo.toml | 14 +++---- client/state-db/Cargo.toml | 2 +- client/sync-state-rpc/Cargo.toml | 2 +- client/tracing/Cargo.toml | 8 ++-- client/transaction-pool/Cargo.toml | 6 +-- client/transaction-pool/api/Cargo.toml | 2 +- frame/assets/Cargo.toml | 6 +-- frame/atomic-swap/Cargo.toml | 6 +-- frame/aura/Cargo.toml | 8 ++-- frame/authority-discovery/Cargo.toml | 8 ++-- frame/authorship/Cargo.toml | 6 +-- frame/babe/Cargo.toml | 8 ++-- frame/bags-list/Cargo.toml | 14 +++---- frame/bags-list/remote-tests/Cargo.toml | 8 ++-- frame/balances/Cargo.toml | 6 +-- frame/beefy-mmr/Cargo.toml | 6 +-- frame/beefy/Cargo.toml | 6 +-- frame/benchmarking/Cargo.toml | 12 +++--- frame/bounties/Cargo.toml | 6 +-- frame/child-bounties/Cargo.toml | 6 +-- frame/collective/Cargo.toml | 6 +-- frame/contracts/Cargo.toml | 10 ++--- frame/contracts/common/Cargo.toml | 8 ++-- frame/contracts/rpc/Cargo.toml | 8 ++-- frame/contracts/rpc/runtime-api/Cargo.toml | 4 +- frame/conviction-voting/Cargo.toml | 6 +-- frame/democracy/Cargo.toml | 6 +-- .../election-provider-multi-phase/Cargo.toml | 14 +++---- frame/election-provider-support/Cargo.toml | 8 ++-- frame/elections-phragmen/Cargo.toml | 8 ++-- frame/examples/basic/Cargo.toml | 6 +-- frame/examples/offchain-worker/Cargo.toml | 8 ++-- frame/examples/parallel/Cargo.toml | 6 +-- frame/executive/Cargo.toml | 14 +++---- frame/gilt/Cargo.toml | 8 ++-- frame/grandpa/Cargo.toml | 10 ++--- frame/identity/Cargo.toml | 6 +-- frame/im-online/Cargo.toml | 8 ++-- frame/indices/Cargo.toml | 8 ++-- frame/lottery/Cargo.toml | 6 +-- frame/membership/Cargo.toml | 6 +-- frame/merkle-mountain-range/Cargo.toml | 6 +-- .../primitives/Cargo.toml | 4 +- frame/merkle-mountain-range/rpc/Cargo.toml | 4 +- frame/multisig/Cargo.toml | 6 +-- frame/nicks/Cargo.toml | 6 +-- frame/node-authorization/Cargo.toml | 6 +-- frame/offences/Cargo.toml | 6 +-- frame/offences/benchmarking/Cargo.toml | 6 +-- frame/preimage/Cargo.toml | 8 ++-- frame/proxy/Cargo.toml | 6 +-- frame/randomness-collective-flip/Cargo.toml | 6 +-- frame/recovery/Cargo.toml | 6 +-- frame/referenda/Cargo.toml | 6 +-- frame/scheduler/Cargo.toml | 6 +-- frame/scored-pool/Cargo.toml | 6 +-- frame/session/Cargo.toml | 8 ++-- frame/session/benchmarking/Cargo.toml | 6 +-- frame/society/Cargo.toml | 6 +-- frame/staking/Cargo.toml | 10 ++--- frame/staking/reward-curve/Cargo.toml | 2 +- frame/staking/reward-fn/Cargo.toml | 2 +- frame/sudo/Cargo.toml | 6 +-- frame/support/Cargo.toml | 14 +++---- frame/support/test/Cargo.toml | 12 +++--- frame/support/test/compile_pass/Cargo.toml | 6 +-- frame/system/Cargo.toml | 10 ++--- frame/system/benchmarking/Cargo.toml | 6 +-- frame/timestamp/Cargo.toml | 8 ++-- frame/tips/Cargo.toml | 8 ++-- frame/transaction-payment/Cargo.toml | 6 +-- .../asset-tx-payment/Cargo.toml | 8 ++-- frame/transaction-payment/rpc/Cargo.toml | 6 +-- .../rpc/runtime-api/Cargo.toml | 2 +- frame/transaction-storage/Cargo.toml | 6 +-- frame/treasury/Cargo.toml | 6 +-- frame/try-runtime/Cargo.toml | 2 +- frame/uniques/Cargo.toml | 6 +-- frame/utility/Cargo.toml | 8 ++-- frame/vesting/Cargo.toml | 6 +-- primitives/api/Cargo.toml | 8 ++-- primitives/api/test/Cargo.toml | 10 ++--- primitives/application-crypto/Cargo.toml | 6 +-- primitives/application-crypto/test/Cargo.toml | 8 ++-- primitives/arithmetic/Cargo.toml | 3 +- primitives/arithmetic/fuzzer/Cargo.toml | 2 +- primitives/authority-discovery/Cargo.toml | 4 +- primitives/authorship/Cargo.toml | 2 +- primitives/beefy/Cargo.toml | 8 ++-- primitives/block-builder/Cargo.toml | 2 +- primitives/blockchain/Cargo.toml | 4 +- primitives/consensus/aura/Cargo.toml | 4 +- primitives/consensus/babe/Cargo.toml | 8 ++-- primitives/consensus/common/Cargo.toml | 8 ++-- primitives/consensus/pow/Cargo.toml | 4 +- primitives/consensus/slots/Cargo.toml | 4 +- primitives/consensus/vrf/Cargo.toml | 4 +- primitives/core/Cargo.toml | 10 ++--- primitives/core/hashing/proc-macro/Cargo.toml | 2 +- primitives/externalities/Cargo.toml | 4 +- primitives/finality-grandpa/Cargo.toml | 8 ++-- primitives/inherents/Cargo.toml | 4 +- primitives/io/Cargo.toml | 18 ++++----- primitives/keyring/Cargo.toml | 6 +-- primitives/keystore/Cargo.toml | 6 +-- primitives/npos-elections/Cargo.toml | 6 +-- primitives/npos-elections/fuzzer/Cargo.toml | 2 +- .../npos-elections/solution-type/Cargo.toml | 2 +- primitives/offchain/Cargo.toml | 4 +- primitives/rpc/Cargo.toml | 4 +- primitives/runtime-interface/Cargo.toml | 18 ++++----- .../runtime-interface/proc-macro/Cargo.toml | 2 +- .../test-wasm-deprecated/Cargo.toml | 6 +-- .../runtime-interface/test-wasm/Cargo.toml | 6 +-- primitives/runtime-interface/test/Cargo.toml | 8 ++-- primitives/runtime/Cargo.toml | 14 +++---- primitives/sandbox/Cargo.toml | 6 +-- primitives/session/Cargo.toml | 4 +- primitives/staking/Cargo.toml | 2 +- primitives/state-machine/Cargo.toml | 10 ++--- primitives/storage/Cargo.toml | 2 +- primitives/tasks/Cargo.toml | 8 ++-- primitives/test-primitives/Cargo.toml | 6 +-- primitives/timestamp/Cargo.toml | 2 +- primitives/tracing/Cargo.toml | 2 +- primitives/transaction-pool/Cargo.toml | 2 +- .../transaction-storage-proof/Cargo.toml | 6 +-- primitives/trie/Cargo.toml | 6 +-- primitives/version/Cargo.toml | 6 +-- primitives/version/proc-macro/Cargo.toml | 2 +- primitives/wasm-interface/Cargo.toml | 2 +- test-utils/client/Cargo.toml | 10 ++--- test-utils/runtime/Cargo.toml | 20 +++++----- test-utils/runtime/client/Cargo.toml | 4 +- .../runtime/transaction-pool/Cargo.toml | 2 +- utils/frame/benchmarking-cli/Cargo.toml | 14 +++---- utils/frame/frame-utilities-cli/Cargo.toml | 4 +- utils/frame/generate-bags/Cargo.toml | 2 +- utils/frame/remote-externalities/Cargo.toml | 8 ++-- utils/frame/rpc/support/Cargo.toml | 2 +- utils/frame/rpc/system/Cargo.toml | 6 +-- utils/frame/try-runtime/cli/Cargo.toml | 14 +++---- 190 files changed, 667 insertions(+), 666 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2bd91ca7b6b8..59ff43598fae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5735,7 +5735,7 @@ dependencies = [ [[package]] name = "pallet-contracts-primitives" -version = "5.0.0" +version = "6.0.0" dependencies = [ "bitflags", "parity-scale-codec", @@ -9634,7 +9634,7 @@ dependencies = [ [[package]] name = "sp-application-crypto" -version = "5.0.0" +version = "6.0.0" dependencies = [ "parity-scale-codec", "scale-info", @@ -9658,7 +9658,7 @@ dependencies = [ [[package]] name = "sp-arithmetic" -version = "4.0.0" +version = "5.0.0" dependencies = [ "criterion", "integer-sqrt", @@ -9829,7 +9829,7 @@ dependencies = [ [[package]] name = "sp-core" -version = "5.0.0" +version = "6.0.0" dependencies = [ "base58", "bitflags", @@ -9892,7 +9892,7 @@ dependencies = [ [[package]] name = "sp-core-hashing-proc-macro" -version = "4.0.0-dev" +version = "5.0.0" dependencies = [ "proc-macro2", "quote", @@ -9919,7 +9919,7 @@ dependencies = [ [[package]] name = "sp-externalities" -version = "0.11.0" +version = "0.12.0" dependencies = [ "environmental", "parity-scale-codec", @@ -9960,7 +9960,7 @@ dependencies = [ [[package]] name = "sp-io" -version = "5.0.0" +version = "6.0.0" dependencies = [ "futures 0.3.19", "hash-db", @@ -9984,7 +9984,7 @@ dependencies = [ [[package]] name = "sp-keyring" -version = "5.0.0" +version = "6.0.0" dependencies = [ "lazy_static", "sp-core", @@ -9994,7 +9994,7 @@ dependencies = [ [[package]] name = "sp-keystore" -version = "0.11.0" +version = "0.12.0" dependencies = [ "async-trait", "futures 0.3.19", @@ -10082,7 +10082,7 @@ dependencies = [ [[package]] name = "sp-rpc" -version = "5.0.0" +version = "6.0.0" dependencies = [ "rustc-hash", "serde", @@ -10092,7 +10092,7 @@ dependencies = [ [[package]] name = "sp-runtime" -version = "5.0.0" +version = "6.0.0" dependencies = [ "either", "hash256-std-hasher", @@ -10119,7 +10119,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface" -version = "5.0.0" +version = "6.0.0" dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", @@ -10141,7 +10141,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface-proc-macro" -version = "4.0.0" +version = "5.0.0" dependencies = [ "Inflector", "proc-macro-crate 1.1.0", @@ -10236,7 +10236,7 @@ dependencies = [ [[package]] name = "sp-state-machine" -version = "0.11.0" +version = "0.12.0" dependencies = [ "hash-db", "hex-literal", @@ -10265,7 +10265,7 @@ version = "4.0.0" [[package]] name = "sp-storage" -version = "5.0.0" +version = "6.0.0" dependencies = [ "impl-serde", "parity-scale-codec", @@ -10317,7 +10317,7 @@ dependencies = [ [[package]] name = "sp-tracing" -version = "4.0.0" +version = "5.0.0" dependencies = [ "parity-scale-codec", "sp-std", @@ -10351,7 +10351,7 @@ dependencies = [ [[package]] name = "sp-trie" -version = "5.0.0" +version = "6.0.0" dependencies = [ "criterion", "hash-db", @@ -10370,7 +10370,7 @@ dependencies = [ [[package]] name = "sp-version" -version = "4.0.0-dev" +version = "5.0.0" dependencies = [ "impl-serde", "parity-scale-codec", @@ -10397,7 +10397,7 @@ dependencies = [ [[package]] name = "sp-wasm-interface" -version = "5.0.0" +version = "6.0.0" dependencies = [ "impl-trait-for-tuples", "log 0.4.14", diff --git a/bin/node-template/node/Cargo.toml b/bin/node-template/node/Cargo.toml index ea14942afee0..98e8af96d3f8 100644 --- a/bin/node-template/node/Cargo.toml +++ b/bin/node-template/node/Cargo.toml @@ -20,7 +20,7 @@ name = "node-template" clap = { version = "3.0", features = ["derive"] } sc-cli = { version = "0.10.0-dev", path = "../../../client/cli", features = ["wasmtime"] } -sp-core = { version = "5.0.0", path = "../../../primitives/core" } +sp-core = { version = "6.0.0", path = "../../../primitives/core" } sc-executor = { version = "0.10.0-dev", path = "../../../client/executor", features = ["wasmtime"] } sc-service = { version = "0.10.0-dev", path = "../../../client/service", features = ["wasmtime"] } sc-telemetry = { version = "4.0.0-dev", path = "../../../client/telemetry" } @@ -34,7 +34,7 @@ sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/commo sc-finality-grandpa = { version = "0.10.0-dev", path = "../../../client/finality-grandpa" } sp-finality-grandpa = { version = "4.0.0-dev", path = "../../../primitives/finality-grandpa" } sc-client-api = { version = "4.0.0-dev", path = "../../../client/api" } -sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } +sp-runtime = { version = "6.0.0", path = "../../../primitives/runtime" } sp-timestamp = { version = "4.0.0-dev", path = "../../../primitives/timestamp" } # These dependencies are used for the node template's RPCs diff --git a/bin/node-template/pallets/template/Cargo.toml b/bin/node-template/pallets/template/Cargo.toml index 62c1c4310884..ffc02dbd96f6 100644 --- a/bin/node-template/pallets/template/Cargo.toml +++ b/bin/node-template/pallets/template/Cargo.toml @@ -22,9 +22,9 @@ frame-system = { default-features = false, version = "4.0.0-dev", path = "../../ frame-benchmarking = { default-features = false, version = "4.0.0-dev", path = "../../../../frame/benchmarking", optional = true } [dev-dependencies] -sp-core = { default-features = false, version = "5.0.0", path = "../../../../primitives/core" } -sp-io = { default-features = false, version = "5.0.0", path = "../../../../primitives/io" } -sp-runtime = { default-features = false, version = "5.0.0", path = "../../../../primitives/runtime" } +sp-core = { default-features = false, version = "6.0.0", path = "../../../../primitives/core" } +sp-io = { default-features = false, version = "6.0.0", path = "../../../../primitives/io" } +sp-runtime = { default-features = false, version = "6.0.0", path = "../../../../primitives/runtime" } [features] default = ["std"] diff --git a/bin/node-template/runtime/Cargo.toml b/bin/node-template/runtime/Cargo.toml index 95021227cf4f..d20a6c39aa5d 100644 --- a/bin/node-template/runtime/Cargo.toml +++ b/bin/node-template/runtime/Cargo.toml @@ -30,14 +30,14 @@ frame-executive = { version = "4.0.0-dev", default-features = false, path = "../ sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/api" } sp-block-builder = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/block-builder"} sp-consensus-aura = { version = "0.10.0-dev", default-features = false, path = "../../../primitives/consensus/aura" } -sp-core = { version = "5.0.0", default-features = false, path = "../../../primitives/core" } +sp-core = { version = "6.0.0", default-features = false, path = "../../../primitives/core" } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/inherents"} sp-offchain = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/offchain" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../../primitives/runtime" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/session" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } sp-transaction-pool = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/transaction-pool" } -sp-version = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/version" } +sp-version = { version = "5.0.0", default-features = false, path = "../../../primitives/version" } # Used for the node template's RPCs frame-system-rpc-runtime-api = { version = "4.0.0-dev", default-features = false, path = "../../../frame/system/rpc/runtime-api/" } diff --git a/bin/node/bench/Cargo.toml b/bin/node/bench/Cargo.toml index c770ca01ecf0..2c5dea2cc28a 100644 --- a/bin/node/bench/Cargo.toml +++ b/bin/node/bench/Cargo.toml @@ -15,20 +15,20 @@ node-primitives = { version = "2.0.0", path = "../primitives" } node-testing = { version = "3.0.0-dev", path = "../testing" } node-runtime = { version = "3.0.0-dev", path = "../runtime" } sc-client-api = { version = "4.0.0-dev", path = "../../../client/api/" } -sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } -sp-state-machine = { version = "0.11.0", path = "../../../primitives/state-machine" } +sp-runtime = { version = "6.0.0", path = "../../../primitives/runtime" } +sp-state-machine = { version = "0.12.0", path = "../../../primitives/state-machine" } serde = "1.0.136" serde_json = "1.0.74" derive_more = "0.99.16" kvdb = "0.11.0" kvdb-rocksdb = "0.15.1" -sp-trie = { version = "5.0.0", path = "../../../primitives/trie" } -sp-core = { version = "5.0.0", path = "../../../primitives/core" } +sp-trie = { version = "6.0.0", path = "../../../primitives/trie" } +sp-core = { version = "6.0.0", path = "../../../primitives/core" } sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" } sc-basic-authorship = { version = "0.10.0-dev", path = "../../../client/basic-authorship" } sp-inherents = { version = "4.0.0-dev", path = "../../../primitives/inherents" } sp-timestamp = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/timestamp" } -sp-tracing = { version = "4.0.0", path = "../../../primitives/tracing" } +sp-tracing = { version = "5.0.0", path = "../../../primitives/tracing" } hash-db = "0.15.2" tempfile = "3.1.0" fs_extra = "1" diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index 57bbbdddcb2e..b4a91712fd16 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -47,13 +47,13 @@ sp-authority-discovery = { version = "4.0.0-dev", path = "../../../primitives/au sp-consensus-babe = { version = "0.10.0-dev", path = "../../../primitives/consensus/babe" } grandpa-primitives = { version = "4.0.0-dev", package = "sp-finality-grandpa", path = "../../../primitives/finality-grandpa" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } -sp-core = { version = "5.0.0", path = "../../../primitives/core" } -sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } +sp-core = { version = "6.0.0", path = "../../../primitives/core" } +sp-runtime = { version = "6.0.0", path = "../../../primitives/runtime" } sp-timestamp = { version = "4.0.0-dev", path = "../../../primitives/timestamp" } sp-authorship = { version = "4.0.0-dev", path = "../../../primitives/authorship" } sp-inherents = { version = "4.0.0-dev", path = "../../../primitives/inherents" } -sp-keyring = { version = "5.0.0", path = "../../../primitives/keyring" } -sp-keystore = { version = "0.11.0", path = "../../../primitives/keystore" } +sp-keyring = { version = "6.0.0", path = "../../../primitives/keyring" } +sp-keystore = { version = "0.12.0", path = "../../../primitives/keystore" } sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" } sp-transaction-pool = { version = "4.0.0-dev", path = "../../../primitives/transaction-pool" } sp-transaction-storage-proof = { version = "4.0.0-dev", path = "../../../primitives/transaction-storage-proof" } @@ -102,7 +102,7 @@ sc-cli = { version = "0.10.0-dev", optional = true, path = "../../../client/cli" sc-service = { version = "0.10.0-dev", default-features = false, path = "../../../client/service", features = [ "wasmtime", ] } -sp-trie = { version = "5.0.0", default-features = false, path = "../../../primitives/trie", features = [ +sp-trie = { version = "6.0.0", default-features = false, path = "../../../primitives/trie", features = [ "memory-tracker", ] } @@ -114,7 +114,7 @@ sc-consensus-babe = { version = "0.10.0-dev", path = "../../../client/consensus/ sc-consensus-epochs = { version = "0.10.0-dev", path = "../../../client/consensus/epochs" } sc-service-test = { version = "2.0.0", path = "../../../client/service/test" } sc-block-builder = { version = "0.10.0-dev", path = "../../../client/block-builder" } -sp-tracing = { version = "4.0.0", path = "../../../primitives/tracing" } +sp-tracing = { version = "5.0.0", path = "../../../primitives/tracing" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } futures = "0.3.19" tempfile = "3.1.0" diff --git a/bin/node/executor/Cargo.toml b/bin/node/executor/Cargo.toml index 6bb762319b27..e29ffd9b671f 100644 --- a/bin/node/executor/Cargo.toml +++ b/bin/node/executor/Cargo.toml @@ -17,11 +17,11 @@ scale-info = { version = "2.0.0", features = ["derive"] } node-primitives = { version = "2.0.0", path = "../primitives" } node-runtime = { version = "3.0.0-dev", path = "../runtime" } sc-executor = { version = "0.10.0-dev", path = "../../../client/executor" } -sp-core = { version = "5.0.0", path = "../../../primitives/core" } -sp-keystore = { version = "0.11.0", path = "../../../primitives/keystore" } -sp-state-machine = { version = "0.11.0", path = "../../../primitives/state-machine" } -sp-tracing = { version = "4.0.0", path = "../../../primitives/tracing" } -sp-trie = { version = "5.0.0", path = "../../../primitives/trie" } +sp-core = { version = "6.0.0", path = "../../../primitives/core" } +sp-keystore = { version = "0.12.0", path = "../../../primitives/keystore" } +sp-state-machine = { version = "0.12.0", path = "../../../primitives/state-machine" } +sp-tracing = { version = "5.0.0", path = "../../../primitives/tracing" } +sp-trie = { version = "6.0.0", path = "../../../primitives/trie" } frame-benchmarking = { version = "4.0.0-dev", path = "../../../frame/benchmarking" } [dev-dependencies] @@ -34,11 +34,11 @@ pallet-contracts = { version = "4.0.0-dev", path = "../../../frame/contracts" } pallet-im-online = { version = "4.0.0-dev", path = "../../../frame/im-online" } pallet-timestamp = { version = "4.0.0-dev", path = "../../../frame/timestamp" } pallet-treasury = { version = "4.0.0-dev", path = "../../../frame/treasury" } -sp-application-crypto = { version = "5.0.0", path = "../../../primitives/application-crypto" } +sp-application-crypto = { version = "6.0.0", path = "../../../primitives/application-crypto" } sp-consensus-babe = { version = "0.10.0-dev", path = "../../../primitives/consensus/babe" } -sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } -sp-externalities = { version = "0.11.0", path = "../../../primitives/externalities" } -sp-keyring = { version = "5.0.0", path = "../../../primitives/keyring" } +sp-runtime = { version = "6.0.0", path = "../../../primitives/runtime" } +sp-externalities = { version = "0.12.0", path = "../../../primitives/externalities" } +sp-keyring = { version = "6.0.0", path = "../../../primitives/keyring" } wat = "1.0" futures = "0.3.19" diff --git a/bin/node/inspect/Cargo.toml b/bin/node/inspect/Cargo.toml index 162d56fc763f..5e7ed16efdcf 100644 --- a/bin/node/inspect/Cargo.toml +++ b/bin/node/inspect/Cargo.toml @@ -19,5 +19,5 @@ sc-client-api = { version = "4.0.0-dev", path = "../../../client/api" } sc-executor = { version = "0.10.0-dev", path = "../../../client/executor" } sc-service = { version = "0.10.0-dev", default-features = false, path = "../../../client/service" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-core = { version = "5.0.0", path = "../../../primitives/core" } -sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } +sp-core = { version = "6.0.0", path = "../../../primitives/core" } +sp-runtime = { version = "6.0.0", path = "../../../primitives/runtime" } diff --git a/bin/node/primitives/Cargo.toml b/bin/node/primitives/Cargo.toml index f95f767b4a83..0d49d4a247c0 100644 --- a/bin/node/primitives/Cargo.toml +++ b/bin/node/primitives/Cargo.toml @@ -16,9 +16,9 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = ] } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../../frame/system" } -sp-application-crypto = { version = "5.0.0", default-features = false, path = "../../../primitives/application-crypto" } -sp-core = { version = "5.0.0", default-features = false, path = "../../../primitives/core" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../../primitives/runtime" } +sp-application-crypto = { version = "6.0.0", default-features = false, path = "../../../primitives/application-crypto" } +sp-core = { version = "6.0.0", default-features = false, path = "../../../primitives/core" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../../primitives/runtime" } [features] default = ["std"] diff --git a/bin/node/rpc/Cargo.toml b/bin/node/rpc/Cargo.toml index c6ba0c9f992d..95ea3f8174fa 100644 --- a/bin/node/rpc/Cargo.toml +++ b/bin/node/rpc/Cargo.toml @@ -29,9 +29,9 @@ sc-sync-state-rpc = { version = "0.10.0-dev", path = "../../../client/sync-state sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-block-builder = { version = "4.0.0-dev", path = "../../../primitives/block-builder" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-keystore = { version = "0.11.0", path = "../../../primitives/keystore" } +sp-keystore = { version = "0.12.0", path = "../../../primitives/keystore" } sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" } sp-consensus-babe = { version = "0.10.0-dev", path = "../../../primitives/consensus/babe" } -sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } +sp-runtime = { version = "6.0.0", path = "../../../primitives/runtime" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../../../client/transaction-pool/api" } substrate-frame-rpc-system = { version = "4.0.0-dev", path = "../../../utils/frame/rpc/system" } diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 39c4609c4425..2d2c903f70ca 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -30,16 +30,16 @@ sp-block-builder = { path = "../../../primitives/block-builder", default-feature sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/inherents" } node-primitives = { version = "2.0.0", default-features = false, path = "../primitives" } sp-offchain = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/offchain" } -sp-core = { version = "5.0.0", default-features = false, path = "../../../primitives/core" } +sp-core = { version = "6.0.0", default-features = false, path = "../../../primitives/core" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/api" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../../primitives/runtime" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/staking" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/session" } sp-transaction-pool = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/transaction-pool" } -sp-version = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/version" } +sp-version = { version = "5.0.0", default-features = false, path = "../../../primitives/version" } sp-npos-elections = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/npos-elections" } -sp-io = { version = "5.0.0", default-features = false, path = "../../../primitives/io" } +sp-io = { version = "6.0.0", default-features = false, path = "../../../primitives/io" } sp-sandbox = { version = "0.10.0-dev", default-features = false, path = "../../../primitives/sandbox" } # frame dependencies @@ -61,7 +61,7 @@ pallet-bounties = { version = "4.0.0-dev", default-features = false, path = "../ pallet-child-bounties = { version = "4.0.0-dev", default-features = false, path = "../../../frame/child-bounties" } pallet-collective = { version = "4.0.0-dev", default-features = false, path = "../../../frame/collective" } pallet-contracts = { version = "4.0.0-dev", default-features = false, path = "../../../frame/contracts" } -pallet-contracts-primitives = { version = "5.0.0", default-features = false, path = "../../../frame/contracts/common/" } +pallet-contracts-primitives = { version = "6.0.0", default-features = false, path = "../../../frame/contracts/common/" } pallet-contracts-rpc-runtime-api = { version = "4.0.0-dev", default-features = false, path = "../../../frame/contracts/rpc/runtime-api/" } pallet-conviction-voting = { version = "4.0.0-dev", default-features = false, path = "../../../frame/conviction-voting" } pallet-democracy = { version = "4.0.0-dev", default-features = false, path = "../../../frame/democracy" } diff --git a/bin/node/testing/Cargo.toml b/bin/node/testing/Cargo.toml index 3c0be4e19c9e..36a25ab7d4a7 100644 --- a/bin/node/testing/Cargo.toml +++ b/bin/node/testing/Cargo.toml @@ -24,13 +24,13 @@ sc-client-db = { version = "0.10.0-dev", path = "../../../client/db/", features sc-client-api = { version = "4.0.0-dev", path = "../../../client/api/" } sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/common" } codec = { package = "parity-scale-codec", version = "3.0.0" } -sp-keyring = { version = "5.0.0", path = "../../../primitives/keyring" } +sp-keyring = { version = "6.0.0", path = "../../../primitives/keyring" } node-executor = { version = "3.0.0-dev", path = "../executor" } node-primitives = { version = "2.0.0", path = "../primitives" } node-runtime = { version = "3.0.0-dev", path = "../runtime" } -sp-core = { version = "5.0.0", path = "../../../primitives/core" } -sp-io = { version = "5.0.0", path = "../../../primitives/io" } -sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } +sp-core = { version = "6.0.0", path = "../../../primitives/core" } +sp-io = { version = "6.0.0", path = "../../../primitives/io" } +sp-runtime = { version = "6.0.0", path = "../../../primitives/runtime" } sc-executor = { version = "0.10.0-dev", path = "../../../client/executor", features = [ "wasmtime", ] } diff --git a/bin/utils/chain-spec-builder/Cargo.toml b/bin/utils/chain-spec-builder/Cargo.toml index f6af82ba42eb..953731719848 100644 --- a/bin/utils/chain-spec-builder/Cargo.toml +++ b/bin/utils/chain-spec-builder/Cargo.toml @@ -21,5 +21,5 @@ rand = "0.8" sc-keystore = { version = "4.0.0-dev", path = "../../../client/keystore" } sc-chain-spec = { version = "4.0.0-dev", path = "../../../client/chain-spec" } node-cli = { version = "3.0.0-dev", path = "../../node/cli" } -sp-core = { version = "5.0.0", path = "../../../primitives/core" } -sp-keystore = { version = "0.11.0", path = "../../../primitives/keystore" } +sp-core = { version = "6.0.0", path = "../../../primitives/core" } +sp-keystore = { version = "0.12.0", path = "../../../primitives/keystore" } diff --git a/client/allocator/Cargo.toml b/client/allocator/Cargo.toml index 6f20449b38bc..8375c39ba4a1 100644 --- a/client/allocator/Cargo.toml +++ b/client/allocator/Cargo.toml @@ -14,7 +14,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-core = { version = "5.0.0", path = "../../primitives/core" } -sp-wasm-interface = { version = "5.0.0", path = "../../primitives/wasm-interface" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } +sp-wasm-interface = { version = "6.0.0", path = "../../primitives/wasm-interface" } log = "0.4.11" thiserror = "1.0.30" diff --git a/client/api/Cargo.toml b/client/api/Cargo.toml index b82309ef6faf..3d1802c379f0 100644 --- a/client/api/Cargo.toml +++ b/client/api/Cargo.toml @@ -19,7 +19,7 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = ] } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } sc-executor = { version = "0.10.0-dev", path = "../executor" } -sp-externalities = { version = "0.11.0", path = "../../primitives/externalities" } +sp-externalities = { version = "0.12.0", path = "../../primitives/externalities" } fnv = "1.0.6" futures = "0.3.19" hash-db = { version = "0.15.2", default-features = false } @@ -27,14 +27,14 @@ sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } log = "0.4.8" parking_lot = "0.12.0" sp-database = { version = "4.0.0-dev", path = "../../primitives/database" } -sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } -sp-keystore = { version = "0.11.0", default-features = false, path = "../../primitives/keystore" } +sp-core = { version = "6.0.0", default-features = false, path = "../../primitives/core" } +sp-keystore = { version = "0.12.0", default-features = false, path = "../../primitives/keystore" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } sc-utils = { version = "4.0.0-dev", path = "../utils" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } -sp-state-machine = { version = "0.11.0", path = "../../primitives/state-machine" } -sp-trie = { version = "5.0.0", path = "../../primitives/trie" } -sp-storage = { version = "5.0.0", path = "../../primitives/storage" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } +sp-state-machine = { version = "0.12.0", path = "../../primitives/state-machine" } +sp-trie = { version = "6.0.0", path = "../../primitives/trie" } +sp-storage = { version = "6.0.0", path = "../../primitives/storage" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../transaction-pool/api" } prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.10.0-dev", path = "../../utils/prometheus" } diff --git a/client/authority-discovery/Cargo.toml b/client/authority-discovery/Cargo.toml index 197b8cfd1fbb..d866bafb29dc 100644 --- a/client/authority-discovery/Cargo.toml +++ b/client/authority-discovery/Cargo.toml @@ -32,12 +32,12 @@ sc-client-api = { version = "4.0.0-dev", path = "../api" } sc-network = { version = "0.10.0-dev", path = "../network" } sp-authority-discovery = { version = "4.0.0-dev", path = "../../primitives/authority-discovery" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } -sp-core = { version = "5.0.0", path = "../../primitives/core" } -sp-keystore = { version = "0.11.0", path = "../../primitives/keystore" } -sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } +sp-keystore = { version = "0.12.0", path = "../../primitives/keystore" } +sp-runtime = { version = "6.0.0", path = "../../primitives/runtime" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } [dev-dependencies] quickcheck = "1.0.3" -sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } +sp-tracing = { version = "5.0.0", path = "../../primitives/tracing" } substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } diff --git a/client/basic-authorship/Cargo.toml b/client/basic-authorship/Cargo.toml index 5791b2b4010f..4fd140835525 100644 --- a/client/basic-authorship/Cargo.toml +++ b/client/basic-authorship/Cargo.toml @@ -19,8 +19,8 @@ futures-timer = "3.0.1" log = "0.4.8" prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.10.0-dev"} sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } -sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } -sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-runtime = { version = "6.0.0", path = "../../primitives/runtime" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sc-client-api = { version = "4.0.0-dev", path = "../api" } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } diff --git a/client/beefy/Cargo.toml b/client/beefy/Cargo.toml index d126d60b8409..f23b3f5dc4a6 100644 --- a/client/beefy/Cargo.toml +++ b/client/beefy/Cargo.toml @@ -19,12 +19,12 @@ codec = { version = "3.0.0", package = "parity-scale-codec", features = ["derive prometheus = { version = "0.10.0-dev", package = "substrate-prometheus-endpoint", path = "../../utils/prometheus" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } -sp-application-crypto = { version = "5.0.0", path = "../../primitives/application-crypto" } -sp-arithmetic = { version = "4.0.0", path = "../../primitives/arithmetic" } +sp-application-crypto = { version = "6.0.0", path = "../../primitives/application-crypto" } +sp-arithmetic = { version = "5.0.0", path = "../../primitives/arithmetic" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } -sp-core = { version = "5.0.0", path = "../../primitives/core" } -sp-keystore = { version = "0.11.0", path = "../../primitives/keystore" } -sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } +sp-keystore = { version = "0.12.0", path = "../../primitives/keystore" } +sp-runtime = { version = "6.0.0", path = "../../primitives/runtime" } sc-chain-spec = { version = "4.0.0-dev", path = "../../client/chain-spec" } sc-utils = { version = "4.0.0-dev", path = "../utils" } @@ -36,7 +36,7 @@ sc-network-gossip = { version = "0.10.0-dev", path = "../network-gossip" } beefy-primitives = { version = "4.0.0-dev", path = "../../primitives/beefy" } [dev-dependencies] -sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } +sp-tracing = { version = "5.0.0", path = "../../primitives/tracing" } sc-network-test = { version = "0.8.0", path = "../network/test" } strum = { version = "0.23", features = ["derive"] } diff --git a/client/beefy/rpc/Cargo.toml b/client/beefy/rpc/Cargo.toml index 19e1e20c7735..071b07b6b229 100644 --- a/client/beefy/rpc/Cargo.toml +++ b/client/beefy/rpc/Cargo.toml @@ -24,8 +24,8 @@ codec = { version = "3.0.0", package = "parity-scale-codec", features = ["derive sc-rpc = { version = "4.0.0-dev", path = "../../rpc" } sc-utils = { version = "4.0.0-dev", path = "../../utils" } -sp-core = { version = "5.0.0", path = "../../../primitives/core" } -sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } +sp-core = { version = "6.0.0", path = "../../../primitives/core" } +sp-runtime = { version = "6.0.0", path = "../../../primitives/runtime" } beefy-gadget = { version = "4.0.0-dev", path = "../." } beefy-primitives = { version = "4.0.0-dev", path = "../../../primitives/beefy" } diff --git a/client/block-builder/Cargo.toml b/client/block-builder/Cargo.toml index 10c3fbdb9f7f..fff7740ff8d0 100644 --- a/client/block-builder/Cargo.toml +++ b/client/block-builder/Cargo.toml @@ -14,11 +14,11 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-state-machine = { version = "0.11.0", path = "../../primitives/state-machine" } -sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } +sp-state-machine = { version = "0.12.0", path = "../../primitives/state-machine" } +sp-runtime = { version = "6.0.0", path = "../../primitives/runtime" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } -sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } sp-block-builder = { version = "4.0.0-dev", path = "../../primitives/block-builder" } sp-inherents = { version = "4.0.0-dev", path = "../../primitives/inherents" } sc-client-api = { version = "4.0.0-dev", path = "../api" } diff --git a/client/chain-spec/Cargo.toml b/client/chain-spec/Cargo.toml index 9e8e3276e760..68d591254d21 100644 --- a/client/chain-spec/Cargo.toml +++ b/client/chain-spec/Cargo.toml @@ -16,10 +16,10 @@ targets = ["x86_64-unknown-linux-gnu"] sc-chain-spec-derive = { version = "4.0.0-dev", path = "./derive" } impl-trait-for-tuples = "0.2.1" sc-network = { version = "0.10.0-dev", path = "../network" } -sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } serde = { version = "1.0.136", features = ["derive"] } serde_json = "1.0.74" -sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } +sp-runtime = { version = "6.0.0", path = "../../primitives/runtime" } sc-telemetry = { version = "4.0.0-dev", path = "../telemetry" } codec = { package = "parity-scale-codec", version = "3.0.0" } memmap2 = "0.5.0" diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index 47ef9619661c..813215321dfc 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -39,12 +39,12 @@ sc-telemetry = { version = "4.0.0-dev", path = "../telemetry" } sc-tracing = { version = "4.0.0-dev", path = "../tracing" } sc-utils = { version = "4.0.0-dev", path = "../utils" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } -sp-core = { version = "5.0.0", path = "../../primitives/core" } -sp-keyring = { version = "5.0.0", path = "../../primitives/keyring" } -sp-keystore = { version = "0.11.0", path = "../../primitives/keystore" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } +sp-keyring = { version = "6.0.0", path = "../../primitives/keyring" } +sp-keystore = { version = "0.12.0", path = "../../primitives/keystore" } sp-panic-handler = { version = "4.0.0", path = "../../primitives/panic-handler" } -sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } -sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } +sp-runtime = { version = "6.0.0", path = "../../primitives/runtime" } +sp-version = { version = "5.0.0", path = "../../primitives/version" } [dev-dependencies] tempfile = "3.1.0" diff --git a/client/consensus/aura/Cargo.toml b/client/consensus/aura/Cargo.toml index b82a71587048..6f5ff3c221fa 100644 --- a/client/consensus/aura/Cargo.toml +++ b/client/consensus/aura/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-application-crypto = { version = "5.0.0", path = "../../../primitives/application-crypto" } +sp-application-crypto = { version = "6.0.0", path = "../../../primitives/application-crypto" } sp-consensus-aura = { version = "0.10.0-dev", path = "../../../primitives/consensus/aura" } sp-block-builder = { version = "4.0.0-dev", path = "../../../primitives/block-builder" } sc-block-builder = { version = "0.10.0-dev", path = "../../block-builder" } @@ -26,12 +26,12 @@ thiserror = "1.0" futures = "0.3.19" sp-inherents = { version = "4.0.0-dev", path = "../../../primitives/inherents" } log = "0.4.8" -sp-core = { version = "5.0.0", path = "../../../primitives/core" } +sp-core = { version = "6.0.0", path = "../../../primitives/core" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sc-consensus-slots = { version = "0.10.0-dev", path = "../slots" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } -sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } -sp-keystore = { version = "0.11.0", path = "../../../primitives/keystore" } +sp-runtime = { version = "6.0.0", path = "../../../primitives/runtime" } +sp-keystore = { version = "0.12.0", path = "../../../primitives/keystore" } sc-telemetry = { version = "4.0.0-dev", path = "../../telemetry" } prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.10.0-dev" } async-trait = "0.1.50" @@ -41,8 +41,8 @@ getrandom = { version = "0.2", features = ["js"], optional = true } [dev-dependencies] sp-timestamp = { version = "4.0.0-dev", path = "../../../primitives/timestamp" } -sp-keyring = { version = "5.0.0", path = "../../../primitives/keyring" } -sp-tracing = { version = "4.0.0", path = "../../../primitives/tracing" } +sp-keyring = { version = "6.0.0", path = "../../../primitives/keyring" } +sp-tracing = { version = "5.0.0", path = "../../../primitives/tracing" } sc-keystore = { version = "4.0.0-dev", path = "../../keystore" } sc-network = { version = "0.10.0-dev", path = "../../network" } sc-network-test = { version = "0.8.0", path = "../../network/test" } diff --git a/client/consensus/babe/Cargo.toml b/client/consensus/babe/Cargo.toml index edcf8759f6a7..a135807d707e 100644 --- a/client/consensus/babe/Cargo.toml +++ b/client/consensus/babe/Cargo.toml @@ -19,15 +19,15 @@ codec = { package = "parity-scale-codec", version = "3.0.0", features = [ ] } sp-consensus-babe = { version = "0.10.0-dev", path = "../../../primitives/consensus/babe" } sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/common" } -sp-core = { version = "5.0.0", path = "../../../primitives/core" } -sp-application-crypto = { version = "5.0.0", path = "../../../primitives/application-crypto" } -sp-keystore = { version = "0.11.0", path = "../../../primitives/keystore" } +sp-core = { version = "6.0.0", path = "../../../primitives/core" } +sp-application-crypto = { version = "6.0.0", path = "../../../primitives/application-crypto" } +sp-keystore = { version = "0.12.0", path = "../../../primitives/keystore" } num-bigint = "0.2.3" num-rational = "0.2.2" num-traits = "0.2.8" serde = { version = "1.0.136", features = ["derive"] } -sp-version = { version = "4.0.0-dev", path = "../../../primitives/version" } -sp-io = { version = "5.0.0", path = "../../../primitives/io" } +sp-version = { version = "5.0.0", path = "../../../primitives/version" } +sp-io = { version = "6.0.0", path = "../../../primitives/io" } sp-inherents = { version = "4.0.0-dev", path = "../../../primitives/inherents" } sc-telemetry = { version = "4.0.0-dev", path = "../../telemetry" } sc-keystore = { version = "4.0.0-dev", path = "../../keystore" } @@ -40,7 +40,7 @@ sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/c sp-consensus-slots = { version = "0.10.0-dev", path = "../../../primitives/consensus/slots" } sp-consensus-vrf = { version = "0.10.0-dev", path = "../../../primitives/consensus/vrf" } sc-consensus-slots = { version = "0.10.0-dev", path = "../slots" } -sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } +sp-runtime = { version = "6.0.0", path = "../../../primitives/runtime" } fork-tree = { version = "3.0.0", path = "../../../utils/fork-tree" } prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.10.0-dev" } futures = "0.3.19" @@ -55,7 +55,7 @@ async-trait = "0.1.50" [dev-dependencies] sp-timestamp = { version = "4.0.0-dev", path = "../../../primitives/timestamp" } -sp-tracing = { version = "4.0.0", path = "../../../primitives/tracing" } +sp-tracing = { version = "5.0.0", path = "../../../primitives/tracing" } sc-network = { version = "0.10.0-dev", path = "../../network" } sc-network-test = { version = "0.8.0", path = "../../network/test" } substrate-test-runtime-client = { version = "2.0.0", path = "../../../test-utils/runtime/client" } diff --git a/client/consensus/babe/rpc/Cargo.toml b/client/consensus/babe/rpc/Cargo.toml index 5e9f98d628c7..7db7edd2de13 100644 --- a/client/consensus/babe/rpc/Cargo.toml +++ b/client/consensus/babe/rpc/Cargo.toml @@ -21,20 +21,20 @@ jsonrpc-derive = "18.0.0" sp-consensus-babe = { version = "0.10.0-dev", path = "../../../../primitives/consensus/babe" } serde = { version = "1.0.136", features = ["derive"] } sp-blockchain = { version = "4.0.0-dev", path = "../../../../primitives/blockchain" } -sp-runtime = { version = "5.0.0", path = "../../../../primitives/runtime" } +sp-runtime = { version = "6.0.0", path = "../../../../primitives/runtime" } sc-consensus-epochs = { version = "0.10.0-dev", path = "../../epochs" } futures = "0.3.19" thiserror = "1.0" sp-api = { version = "4.0.0-dev", path = "../../../../primitives/api" } sp-consensus = { version = "0.10.0-dev", path = "../../../../primitives/consensus/common" } -sp-core = { version = "5.0.0", path = "../../../../primitives/core" } -sp-application-crypto = { version = "5.0.0", path = "../../../../primitives/application-crypto" } -sp-keystore = { version = "0.11.0", path = "../../../../primitives/keystore" } +sp-core = { version = "6.0.0", path = "../../../../primitives/core" } +sp-application-crypto = { version = "6.0.0", path = "../../../../primitives/application-crypto" } +sp-keystore = { version = "0.12.0", path = "../../../../primitives/keystore" } [dev-dependencies] sc-consensus = { version = "0.10.0-dev", path = "../../../consensus/common" } serde_json = "1.0.74" -sp-keyring = { version = "5.0.0", path = "../../../../primitives/keyring" } +sp-keyring = { version = "6.0.0", path = "../../../../primitives/keyring" } sc-keystore = { version = "4.0.0-dev", path = "../../../keystore" } substrate-test-runtime-client = { version = "2.0.0", path = "../../../../test-utils/runtime/client" } tempfile = "3.1.0" diff --git a/client/consensus/common/Cargo.toml b/client/consensus/common/Cargo.toml index 7677e0569e56..3c640a2363b6 100644 --- a/client/consensus/common/Cargo.toml +++ b/client/consensus/common/Cargo.toml @@ -20,10 +20,10 @@ futures = { version = "0.3.19", features = ["thread-pool"] } futures-timer = "3.0.1" sc-client-api = { version = "4.0.0-dev", path = "../../api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-core = { path = "../../../primitives/core", version = "5.0.0"} +sp-core = { path = "../../../primitives/core", version = "6.0.0"} sp-consensus = { path = "../../../primitives/consensus/common", version = "0.10.0-dev" } -sp-state-machine = { version = "0.11.0", path = "../../../primitives/state-machine" } -sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } +sp-state-machine = { version = "0.12.0", path = "../../../primitives/state-machine" } +sp-runtime = { version = "6.0.0", path = "../../../primitives/runtime" } sc-utils = { version = "4.0.0-dev", path = "../../utils" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } parking_lot = "0.12.0" diff --git a/client/consensus/epochs/Cargo.toml b/client/consensus/epochs/Cargo.toml index 2c5a6dfbffe0..2caf60547cce 100644 --- a/client/consensus/epochs/Cargo.toml +++ b/client/consensus/epochs/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"] } fork-tree = { version = "3.0.0", path = "../../../utils/fork-tree" } -sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } +sp-runtime = { version = "6.0.0", path = "../../../primitives/runtime" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sc-client-api = { path = "../../api" , version = "4.0.0-dev"} sc-consensus = { path = "../common" , version = "0.10.0-dev"} diff --git a/client/consensus/manual-seal/Cargo.toml b/client/consensus/manual-seal/Cargo.toml index 6b9404ce34c9..7aaad863af55 100644 --- a/client/consensus/manual-seal/Cargo.toml +++ b/client/consensus/manual-seal/Cargo.toml @@ -37,9 +37,9 @@ sp-blockchain = { path = "../../../primitives/blockchain", version = "4.0.0-dev" sp-consensus = { path = "../../../primitives/consensus/common", version = "0.10.0-dev" } sp-consensus-slots = { path = "../../../primitives/consensus/slots", version = "0.10.0-dev" } sp-inherents = { path = "../../../primitives/inherents", version = "4.0.0-dev" } -sp-runtime = { path = "../../../primitives/runtime", version = "5.0.0"} -sp-core = { path = "../../../primitives/core", version = "5.0.0"} -sp-keystore = { path = "../../../primitives/keystore", version = "0.11.0"} +sp-runtime = { path = "../../../primitives/runtime", version = "6.0.0"} +sp-core = { path = "../../../primitives/core", version = "6.0.0"} +sp-keystore = { path = "../../../primitives/keystore", version = "0.12.0"} sp-api = { path = "../../../primitives/api", version = "4.0.0-dev" } sc-transaction-pool-api = { path = "../../../client/transaction-pool/api", version = "4.0.0-dev" } sp-timestamp = { path = "../../../primitives/timestamp", version = "4.0.0-dev" } diff --git a/client/consensus/pow/Cargo.toml b/client/consensus/pow/Cargo.toml index cb21a45ebdb0..553ef60e8145 100644 --- a/client/consensus/pow/Cargo.toml +++ b/client/consensus/pow/Cargo.toml @@ -14,9 +14,9 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"] } -sp-core = { version = "5.0.0", path = "../../../primitives/core" } +sp-core = { version = "6.0.0", path = "../../../primitives/core" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } +sp-runtime = { version = "6.0.0", path = "../../../primitives/runtime" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sc-client-api = { version = "4.0.0-dev", path = "../../api" } sp-block-builder = { version = "4.0.0-dev", path = "../../../primitives/block-builder" } diff --git a/client/consensus/slots/Cargo.toml b/client/consensus/slots/Cargo.toml index 4f4cf4d58bc3..07e0c291f4a3 100644 --- a/client/consensus/slots/Cargo.toml +++ b/client/consensus/slots/Cargo.toml @@ -16,13 +16,13 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0" } sc-client-api = { version = "4.0.0-dev", path = "../../api" } -sp-core = { version = "5.0.0", path = "../../../primitives/core" } -sp-arithmetic = { version = "4.0.0", path = "../../../primitives/arithmetic" } +sp-core = { version = "6.0.0", path = "../../../primitives/core" } +sp-arithmetic = { version = "5.0.0", path = "../../../primitives/arithmetic" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/common" } sp-consensus-slots = { version = "0.10.0-dev", path = "../../../primitives/consensus/slots" } -sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } -sp-state-machine = { version = "0.11.0", path = "../../../primitives/state-machine" } +sp-runtime = { version = "6.0.0", path = "../../../primitives/runtime" } +sp-state-machine = { version = "0.12.0", path = "../../../primitives/state-machine" } sc-telemetry = { version = "4.0.0-dev", path = "../../telemetry" } sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" } sp-inherents = { version = "4.0.0-dev", path = "../../../primitives/inherents" } diff --git a/client/consensus/uncles/Cargo.toml b/client/consensus/uncles/Cargo.toml index 7482fdc12d08..c512eb7e9f83 100644 --- a/client/consensus/uncles/Cargo.toml +++ b/client/consensus/uncles/Cargo.toml @@ -14,6 +14,6 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sc-client-api = { version = "4.0.0-dev", path = "../../api" } -sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } +sp-runtime = { version = "6.0.0", path = "../../../primitives/runtime" } sp-authorship = { version = "4.0.0-dev", path = "../../../primitives/authorship" } thiserror = "1.0.30" diff --git a/client/db/Cargo.toml b/client/db/Cargo.toml index a9fa370a8ead..32fa9d463413 100644 --- a/client/db/Cargo.toml +++ b/client/db/Cargo.toml @@ -25,18 +25,18 @@ codec = { package = "parity-scale-codec", version = "3.0.0", features = [ ] } sc-client-api = { version = "4.0.0-dev", path = "../api" } -sp-arithmetic = { version = "4.0.0", path = "../../primitives/arithmetic" } -sp-core = { version = "5.0.0", path = "../../primitives/core" } -sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } -sp-state-machine = { version = "0.11.0", path = "../../primitives/state-machine" } +sp-arithmetic = { version = "5.0.0", path = "../../primitives/arithmetic" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } +sp-runtime = { version = "6.0.0", path = "../../primitives/runtime" } +sp-state-machine = { version = "0.12.0", path = "../../primitives/state-machine" } sc-state-db = { version = "0.10.0-dev", path = "../state-db" } -sp-trie = { version = "5.0.0", path = "../../primitives/trie" } +sp-trie = { version = "6.0.0", path = "../../primitives/trie" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-database = { version = "4.0.0-dev", path = "../../primitives/database" } parity-db = { version = "0.3.5", optional = true } [dev-dependencies] -sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } +sp-tracing = { version = "5.0.0", path = "../../primitives/tracing" } substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } quickcheck = "1.0.3" kvdb-rocksdb = "0.15.1" diff --git a/client/executor/Cargo.toml b/client/executor/Cargo.toml index 5c62de767100..96a9c0ba6e39 100644 --- a/client/executor/Cargo.toml +++ b/client/executor/Cargo.toml @@ -15,23 +15,23 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0" } -sp-io = { version = "5.0.0", path = "../../primitives/io" } -sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-io = { version = "6.0.0", path = "../../primitives/io" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } sp-tasks = { version = "4.0.0-dev", path = "../../primitives/tasks" } -sp-trie = { version = "5.0.0", path = "../../primitives/trie" } -sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } +sp-trie = { version = "6.0.0", path = "../../primitives/trie" } +sp-version = { version = "5.0.0", path = "../../primitives/version" } sp-panic-handler = { version = "4.0.0", path = "../../primitives/panic-handler" } wasmi = "0.9.1" lazy_static = "1.4.0" sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } -sp-wasm-interface = { version = "5.0.0", path = "../../primitives/wasm-interface" } -sp-runtime-interface = { version = "5.0.0", path = "../../primitives/runtime-interface" } -sp-externalities = { version = "0.11.0", path = "../../primitives/externalities" } +sp-wasm-interface = { version = "6.0.0", path = "../../primitives/wasm-interface" } +sp-runtime-interface = { version = "6.0.0", path = "../../primitives/runtime-interface" } +sp-externalities = { version = "0.12.0", path = "../../primitives/externalities" } sc-executor-common = { version = "0.10.0-dev", path = "common" } sc-executor-wasmi = { version = "0.10.0-dev", path = "wasmi" } sc-executor-wasmtime = { version = "0.10.0-dev", path = "wasmtime", optional = true } parking_lot = "0.12.0" -sp-core-hashing-proc-macro = { version = "4.0.0-dev", path = "../../primitives/core/hashing/proc-macro" } +sp-core-hashing-proc-macro = { version = "5.0.0", path = "../../primitives/core/hashing/proc-macro" } lru = "0.6.6" tracing = "0.1.29" @@ -40,8 +40,8 @@ wat = "1.0" hex-literal = "0.3.4" sc-runtime-test = { version = "2.0.0", path = "runtime-test" } substrate-test-runtime = { version = "2.0.0", path = "../../test-utils/runtime" } -sp-state-machine = { version = "0.11.0", path = "../../primitives/state-machine" } -sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } +sp-state-machine = { version = "0.12.0", path = "../../primitives/state-machine" } +sp-runtime = { version = "6.0.0", path = "../../primitives/runtime" } sp-maybe-compressed-blob = { version = "4.1.0-dev", path = "../../primitives/maybe-compressed-blob" } sc-tracing = { version = "4.0.0-dev", path = "../tracing" } tracing-subscriber = "0.2.19" diff --git a/client/executor/common/Cargo.toml b/client/executor/common/Cargo.toml index 3edaaf12e5b0..9282fe3b03dd 100644 --- a/client/executor/common/Cargo.toml +++ b/client/executor/common/Cargo.toml @@ -17,9 +17,9 @@ targets = ["x86_64-unknown-linux-gnu"] wasm-instrument = "0.1" codec = { package = "parity-scale-codec", version = "3.0.0" } wasmi = "0.9.1" -sp-core = { version = "5.0.0", path = "../../../primitives/core" } +sp-core = { version = "6.0.0", path = "../../../primitives/core" } sc-allocator = { version = "4.1.0-dev", path = "../../allocator" } -sp-wasm-interface = { version = "5.0.0", path = "../../../primitives/wasm-interface" } +sp-wasm-interface = { version = "6.0.0", path = "../../../primitives/wasm-interface" } sp-maybe-compressed-blob = { version = "4.1.0-dev", path = "../../../primitives/maybe-compressed-blob" } sp-serializer = { version = "4.0.0-dev", path = "../../../primitives/serializer" } thiserror = "1.0.30" diff --git a/client/executor/runtime-test/Cargo.toml b/client/executor/runtime-test/Cargo.toml index ca1746c842e1..352ffdf7a65c 100644 --- a/client/executor/runtime-test/Cargo.toml +++ b/client/executor/runtime-test/Cargo.toml @@ -13,9 +13,9 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-core = { version = "5.0.0", default-features = false, path = "../../../primitives/core" } -sp-io = { version = "5.0.0", default-features = false, path = "../../../primitives/io", features = ["improved_panic_error_reporting"] } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../../primitives/runtime" } +sp-core = { version = "6.0.0", default-features = false, path = "../../../primitives/core" } +sp-io = { version = "6.0.0", default-features = false, path = "../../../primitives/io", features = ["improved_panic_error_reporting"] } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../../primitives/runtime" } sp-sandbox = { version = "0.10.0-dev", default-features = false, path = "../../../primitives/sandbox" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } sp-tasks = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/tasks" } diff --git a/client/executor/wasmi/Cargo.toml b/client/executor/wasmi/Cargo.toml index 9b25ebcb1174..cab254f1c71f 100644 --- a/client/executor/wasmi/Cargo.toml +++ b/client/executor/wasmi/Cargo.toml @@ -19,7 +19,7 @@ wasmi = "0.9.1" codec = { package = "parity-scale-codec", version = "3.0.0" } sc-executor-common = { version = "0.10.0-dev", path = "../common" } sc-allocator = { version = "4.1.0-dev", path = "../../allocator" } -sp-wasm-interface = { version = "5.0.0", path = "../../../primitives/wasm-interface" } -sp-runtime-interface = { version = "5.0.0", path = "../../../primitives/runtime-interface" } -sp-core = { version = "5.0.0", path = "../../../primitives/core" } +sp-wasm-interface = { version = "6.0.0", path = "../../../primitives/wasm-interface" } +sp-runtime-interface = { version = "6.0.0", path = "../../../primitives/runtime-interface" } +sp-core = { version = "6.0.0", path = "../../../primitives/core" } scoped-tls = "1.0" diff --git a/client/executor/wasmtime/Cargo.toml b/client/executor/wasmtime/Cargo.toml index 79d5d41087a1..04163c2c4226 100644 --- a/client/executor/wasmtime/Cargo.toml +++ b/client/executor/wasmtime/Cargo.toml @@ -19,9 +19,9 @@ log = "0.4.8" parity-wasm = "0.42.0" codec = { package = "parity-scale-codec", version = "3.0.0" } sc-executor-common = { version = "0.10.0-dev", path = "../common" } -sp-wasm-interface = { version = "5.0.0", path = "../../../primitives/wasm-interface", features = ["wasmtime"] } -sp-runtime-interface = { version = "5.0.0", path = "../../../primitives/runtime-interface" } -sp-core = { version = "5.0.0", path = "../../../primitives/core" } +sp-wasm-interface = { version = "6.0.0", path = "../../../primitives/wasm-interface", features = ["wasmtime"] } +sp-runtime-interface = { version = "6.0.0", path = "../../../primitives/runtime-interface" } +sp-core = { version = "6.0.0", path = "../../../primitives/core" } sc-allocator = { version = "4.1.0-dev", path = "../../allocator" } wasmtime = { version = "0.33.0", default-features = false, features = [ "cache", @@ -32,5 +32,5 @@ wasmtime = { version = "0.33.0", default-features = false, features = [ [dev-dependencies] sc-runtime-test = { version = "2.0.0", path = "../runtime-test" } -sp-io = { version = "5.0.0", path = "../../../primitives/io" } +sp-io = { version = "6.0.0", path = "../../../primitives/io" } wat = "1.0" diff --git a/client/finality-grandpa/Cargo.toml b/client/finality-grandpa/Cargo.toml index 5927a9bef4e6..34feadac5e41 100644 --- a/client/finality-grandpa/Cargo.toml +++ b/client/finality-grandpa/Cargo.toml @@ -24,15 +24,15 @@ parking_lot = "0.12.0" rand = "0.8.4" ahash = "0.7.6" parity-scale-codec = { version = "3.0.0", features = ["derive"] } -sp-application-crypto = { version = "5.0.0", path = "../../primitives/application-crypto" } -sp-arithmetic = { version = "4.0.0", path = "../../primitives/arithmetic" } -sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } +sp-application-crypto = { version = "6.0.0", path = "../../primitives/application-crypto" } +sp-arithmetic = { version = "5.0.0", path = "../../primitives/arithmetic" } +sp-runtime = { version = "6.0.0", path = "../../primitives/runtime" } sc-chain-spec = { version = "4.0.0-dev", path = "../../client/chain-spec" } sc-utils = { version = "4.0.0-dev", path = "../utils" } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } sc-consensus = { version = "0.10.0-dev", path = "../consensus/common" } -sp-core = { version = "5.0.0", path = "../../primitives/core" } -sp-keystore = { version = "0.11.0", path = "../../primitives/keystore" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } +sp-keystore = { version = "0.12.0", path = "../../primitives/keystore" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } sc-telemetry = { version = "4.0.0-dev", path = "../telemetry" } sc-keystore = { version = "4.0.0-dev", path = "../keystore" } @@ -55,8 +55,8 @@ finality-grandpa = { version = "0.15.0", features = [ ] } sc-network = { version = "0.10.0-dev", path = "../network" } sc-network-test = { version = "0.8.0", path = "../network/test" } -sp-keyring = { version = "5.0.0", path = "../../primitives/keyring" } +sp-keyring = { version = "6.0.0", path = "../../primitives/keyring" } substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } -sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } +sp-tracing = { version = "5.0.0", path = "../../primitives/tracing" } tokio = "1.15" tempfile = "3.1.0" diff --git a/client/finality-grandpa/rpc/Cargo.toml b/client/finality-grandpa/rpc/Cargo.toml index 8650ee049853..5e173e1a15fe 100644 --- a/client/finality-grandpa/rpc/Cargo.toml +++ b/client/finality-grandpa/rpc/Cargo.toml @@ -12,8 +12,8 @@ readme = "README.md" sc-finality-grandpa = { version = "0.10.0-dev", path = "../" } sc-rpc = { version = "4.0.0-dev", path = "../../rpc" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-core = { version = "5.0.0", path = "../../../primitives/core" } -sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } +sp-core = { version = "6.0.0", path = "../../../primitives/core" } +sp-runtime = { version = "6.0.0", path = "../../../primitives/runtime" } finality-grandpa = { version = "0.15.0", features = ["derive-codec"] } jsonrpc-core = "18.0.0" jsonrpc-core-client = "18.0.0" @@ -32,7 +32,7 @@ sc-block-builder = { version = "0.10.0-dev", path = "../../block-builder" } sc-rpc = { version = "4.0.0-dev", path = "../../rpc", features = [ "test-helpers", ] } -sp-core = { version = "5.0.0", path = "../../../primitives/core" } +sp-core = { version = "6.0.0", path = "../../../primitives/core" } sp-finality-grandpa = { version = "4.0.0-dev", path = "../../../primitives/finality-grandpa" } -sp-keyring = { version = "5.0.0", path = "../../../primitives/keyring" } +sp-keyring = { version = "6.0.0", path = "../../../primitives/keyring" } substrate-test-runtime-client = { version = "2.0.0", path = "../../../test-utils/runtime/client" } diff --git a/client/informant/Cargo.toml b/client/informant/Cargo.toml index 7ab057b5f0dc..dba0555c6896 100644 --- a/client/informant/Cargo.toml +++ b/client/informant/Cargo.toml @@ -21,5 +21,5 @@ parity-util-mem = { version = "0.11.0", default-features = false, features = ["p sc-client-api = { version = "4.0.0-dev", path = "../api" } sc-network = { version = "0.10.0-dev", path = "../network" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } -sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } +sp-runtime = { version = "6.0.0", path = "../../primitives/runtime" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../transaction-pool/api" } diff --git a/client/keystore/Cargo.toml b/client/keystore/Cargo.toml index f2a06244cde0..09fca2a843a1 100644 --- a/client/keystore/Cargo.toml +++ b/client/keystore/Cargo.toml @@ -17,9 +17,9 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] async-trait = "0.1.50" thiserror = "1.0" -sp-application-crypto = { version = "5.0.0", path = "../../primitives/application-crypto" } -sp-core = { version = "5.0.0", path = "../../primitives/core" } -sp-keystore = { version = "0.11.0", path = "../../primitives/keystore" } +sp-application-crypto = { version = "6.0.0", path = "../../primitives/application-crypto" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } +sp-keystore = { version = "0.12.0", path = "../../primitives/keystore" } hex = "0.4.0" parking_lot = "0.12.0" serde_json = "1.0.74" diff --git a/client/network-gossip/Cargo.toml b/client/network-gossip/Cargo.toml index d9b52c31f273..ade44dc94aa8 100644 --- a/client/network-gossip/Cargo.toml +++ b/client/network-gossip/Cargo.toml @@ -23,7 +23,7 @@ lru = "0.7.0" ahash = "0.7.6" prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.10.0-dev", path = "../../utils/prometheus" } sc-network = { version = "0.10.0-dev", path = "../network" } -sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } +sp-runtime = { version = "6.0.0", path = "../../primitives/runtime" } tracing = "0.1.29" [dev-dependencies] diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index 2e5bb3ea0ee5..0dbdd3ec50e9 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -47,12 +47,12 @@ sc-peerset = { version = "4.0.0-dev", path = "../peerset" } serde = { version = "1.0.136", features = ["derive"] } serde_json = "1.0.74" smallvec = "1.8.0" -sp-arithmetic = { version = "4.0.0", path = "../../primitives/arithmetic" } +sp-arithmetic = { version = "5.0.0", path = "../../primitives/arithmetic" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } sc-consensus = { version = "0.10.0-dev", path = "../consensus/common" } -sp-core = { version = "5.0.0", path = "../../primitives/core" } -sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } +sp-runtime = { version = "6.0.0", path = "../../primitives/runtime" } sc-utils = { version = "4.0.0-dev", path = "../utils" } sp-finality-grandpa = { version = "4.0.0-dev", path = "../../primitives/finality-grandpa" } thiserror = "1.0" @@ -70,7 +70,7 @@ libp2p = { version = "0.40.0", default-features = false } quickcheck = "1.0.3" rand = "0.7.2" sp-test-primitives = { version = "2.0.0", path = "../../primitives/test-primitives" } -sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } +sp-tracing = { version = "5.0.0", path = "../../primitives/tracing" } substrate-test-runtime = { version = "2.0.0", path = "../../test-utils/runtime" } substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } tempfile = "3.1.0" diff --git a/client/network/test/Cargo.toml b/client/network/test/Cargo.toml index 4a47365e0641..be15cbc807e2 100644 --- a/client/network/test/Cargo.toml +++ b/client/network/test/Cargo.toml @@ -25,12 +25,12 @@ sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/c sc-consensus = { version = "0.10.0-dev", path = "../../consensus/common" } sc-client-api = { version = "4.0.0-dev", path = "../../api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } -sp-core = { version = "5.0.0", path = "../../../primitives/core" } +sp-runtime = { version = "6.0.0", path = "../../../primitives/runtime" } +sp-core = { version = "6.0.0", path = "../../../primitives/core" } sc-block-builder = { version = "0.10.0-dev", path = "../../block-builder" } sp-consensus-babe = { version = "0.10.0-dev", path = "../../../primitives/consensus/babe" } substrate-test-runtime-client = { version = "2.0.0", path = "../../../test-utils/runtime/client" } substrate-test-runtime = { version = "2.0.0", path = "../../../test-utils/runtime" } -sp-tracing = { version = "4.0.0", path = "../../../primitives/tracing" } +sp-tracing = { version = "5.0.0", path = "../../../primitives/tracing" } sc-service = { version = "0.10.0-dev", default-features = false, features = ["test-helpers"], path = "../../service" } async-trait = "0.1.50" diff --git a/client/offchain/Cargo.toml b/client/offchain/Cargo.toml index 654633d6ed7f..e542759b4809 100644 --- a/client/offchain/Cargo.toml +++ b/client/offchain/Cargo.toml @@ -25,9 +25,9 @@ rand = "0.7.2" sc-client-api = { version = "4.0.0-dev", path = "../api" } sc-network = { version = "0.10.0-dev", path = "../network" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } -sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } sp-offchain = { version = "4.0.0-dev", path = "../../primitives/offchain" } -sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } +sp-runtime = { version = "6.0.0", path = "../../primitives/runtime" } sc-utils = { version = "4.0.0-dev", path = "../utils" } threadpool = "1.7" hyper = { version = "0.14.16", features = ["stream", "http2"] } @@ -40,7 +40,7 @@ sc-client-db = { version = "0.10.0-dev", default-features = true, path = "../db" sc-block-builder = { version = "0.10.0-dev", path = "../block-builder" } sc-transaction-pool = { version = "4.0.0-dev", path = "../transaction-pool" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../transaction-pool/api" } -sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } +sp-tracing = { version = "5.0.0", path = "../../primitives/tracing" } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } tokio = "1.15" diff --git a/client/rpc-api/Cargo.toml b/client/rpc-api/Cargo.toml index cfcadad1361a..510c59e5b8aa 100644 --- a/client/rpc-api/Cargo.toml +++ b/client/rpc-api/Cargo.toml @@ -23,12 +23,12 @@ log = "0.4.8" parking_lot = "0.12.0" thiserror = "1.0" -sp-core = { version = "5.0.0", path = "../../primitives/core" } -sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } -sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } +sp-version = { version = "5.0.0", path = "../../primitives/version" } +sp-runtime = { version = "6.0.0", path = "../../primitives/runtime" } sc-chain-spec = { path = "../chain-spec", version = "4.0.0-dev" } serde = { version = "1.0.136", features = ["derive"] } serde_json = "1.0.74" sc-transaction-pool-api = { version = "4.0.0-dev", path = "../transaction-pool/api" } -sp-rpc = { version = "5.0.0", path = "../../primitives/rpc" } -sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } +sp-rpc = { version = "6.0.0", path = "../../primitives/rpc" } +sp-tracing = { version = "5.0.0", path = "../../primitives/tracing" } diff --git a/client/rpc/Cargo.toml b/client/rpc/Cargo.toml index 96dfa2c1caa4..314c49d2f862 100644 --- a/client/rpc/Cargo.toml +++ b/client/rpc/Cargo.toml @@ -20,16 +20,16 @@ codec = { package = "parity-scale-codec", version = "3.0.0" } futures = "0.3.19" jsonrpc-pubsub = "18.0.0" log = "0.4.8" -sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } rpc = { package = "jsonrpc-core", version = "18.0.0" } -sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } +sp-version = { version = "5.0.0", path = "../../primitives/version" } serde_json = "1.0.74" sp-session = { version = "4.0.0-dev", path = "../../primitives/session" } sp-offchain = { version = "4.0.0-dev", path = "../../primitives/offchain" } -sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } +sp-runtime = { version = "6.0.0", path = "../../primitives/runtime" } sc-utils = { version = "4.0.0-dev", path = "../utils" } -sp-rpc = { version = "5.0.0", path = "../../primitives/rpc" } -sp-keystore = { version = "0.11.0", path = "../../primitives/keystore" } +sp-rpc = { version = "6.0.0", path = "../../primitives/rpc" } +sp-keystore = { version = "0.12.0", path = "../../primitives/keystore" } sc-chain-spec = { version = "4.0.0-dev", path = "../chain-spec" } sc-block-builder = { version = "0.10.0-dev", path = "../block-builder" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } @@ -43,7 +43,7 @@ sc-transaction-pool-api = { version = "4.0.0-dev", path = "../transaction-pool/a assert_matches = "1.3.0" lazy_static = "1.4.0" sc-network = { version = "0.10.0-dev", path = "../network" } -sp-io = { version = "5.0.0", path = "../../primitives/io" } +sp-io = { version = "6.0.0", path = "../../primitives/io" } substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } sc-transaction-pool = { version = "4.0.0-dev", path = "../transaction-pool" } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index 1747d8e61ea7..84ac9e3de642 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -36,21 +36,21 @@ hash-db = "0.15.2" serde = "1.0.136" serde_json = "1.0.74" sc-keystore = { version = "4.0.0-dev", path = "../keystore" } -sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } -sp-trie = { version = "5.0.0", path = "../../primitives/trie" } -sp-externalities = { version = "0.11.0", path = "../../primitives/externalities" } +sp-runtime = { version = "6.0.0", path = "../../primitives/runtime" } +sp-trie = { version = "6.0.0", path = "../../primitives/trie" } +sp-externalities = { version = "0.12.0", path = "../../primitives/externalities" } sc-utils = { version = "4.0.0-dev", path = "../utils" } -sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } +sp-version = { version = "5.0.0", path = "../../primitives/version" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } -sp-core = { version = "5.0.0", path = "../../primitives/core" } -sp-keystore = { version = "0.11.0", path = "../../primitives/keystore" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } +sp-keystore = { version = "0.12.0", path = "../../primitives/keystore" } sp-session = { version = "4.0.0-dev", path = "../../primitives/session" } -sp-state-machine = { version = "0.11.0", path = "../../primitives/state-machine" } -sp-application-crypto = { version = "5.0.0", path = "../../primitives/application-crypto" } +sp-state-machine = { version = "0.12.0", path = "../../primitives/state-machine" } +sp-application-crypto = { version = "6.0.0", path = "../../primitives/application-crypto" } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } sc-consensus = { version = "0.10.0-dev", path = "../../client/consensus/common" } sp-inherents = { version = "4.0.0-dev", path = "../../primitives/inherents" } -sp-storage = { version = "5.0.0", path = "../../primitives/storage" } +sp-storage = { version = "6.0.0", path = "../../primitives/storage" } sc-network = { version = "0.10.0-dev", path = "../network" } sc-chain-spec = { version = "4.0.0-dev", path = "../chain-spec" } sc-client-api = { version = "4.0.0-dev", path = "../api" } @@ -71,7 +71,7 @@ sc-telemetry = { version = "4.0.0-dev", path = "../telemetry" } sc-offchain = { version = "4.0.0-dev", path = "../offchain" } prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.10.0-dev" } sc-tracing = { version = "4.0.0-dev", path = "../tracing" } -sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } +sp-tracing = { version = "5.0.0", path = "../../primitives/tracing" } tracing = "0.1.29" tracing-futures = { version = "0.2.4" } parity-util-mem = { version = "0.11.0", default-features = false, features = [ diff --git a/client/service/test/Cargo.toml b/client/service/test/Cargo.toml index ac1fb7ad0159..0b99b9c5aeb9 100644 --- a/client/service/test/Cargo.toml +++ b/client/service/test/Cargo.toml @@ -21,18 +21,18 @@ fdlimit = "0.2.1" parking_lot = "0.12.0" sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } -sp-state-machine = { version = "0.11.0", path = "../../../primitives/state-machine" } -sp-externalities = { version = "0.11.0", path = "../../../primitives/externalities" } -sp-trie = { version = "5.0.0", path = "../../../primitives/trie" } -sp-storage = { version = "5.0.0", path = "../../../primitives/storage" } +sp-state-machine = { version = "0.12.0", path = "../../../primitives/state-machine" } +sp-externalities = { version = "0.12.0", path = "../../../primitives/externalities" } +sp-trie = { version = "6.0.0", path = "../../../primitives/trie" } +sp-storage = { version = "6.0.0", path = "../../../primitives/storage" } sc-client-db = { version = "0.10.0-dev", default-features = false, path = "../../db" } futures = "0.3.19" sc-service = { version = "0.10.0-dev", features = ["test-helpers"], path = "../../service" } sc-network = { version = "0.10.0-dev", path = "../../network" } sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" } sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/common" } -sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } -sp-core = { version = "5.0.0", path = "../../../primitives/core" } +sp-runtime = { version = "6.0.0", path = "../../../primitives/runtime" } +sp-core = { version = "6.0.0", path = "../../../primitives/core" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../../../client/transaction-pool/api" } substrate-test-runtime = { version = "2.0.0", path = "../../../test-utils/runtime" } substrate-test-runtime-client = { version = "2.0.0", path = "../../../test-utils/runtime/client" } @@ -41,4 +41,4 @@ sc-block-builder = { version = "0.10.0-dev", path = "../../block-builder" } sc-executor = { version = "0.10.0-dev", path = "../../executor" } sp-panic-handler = { version = "4.0.0", path = "../../../primitives/panic-handler" } parity-scale-codec = "3.0.0" -sp-tracing = { version = "4.0.0", path = "../../../primitives/tracing" } +sp-tracing = { version = "5.0.0", path = "../../../primitives/tracing" } diff --git a/client/state-db/Cargo.toml b/client/state-db/Cargo.toml index bf45ad49043c..42ef4338b406 100644 --- a/client/state-db/Cargo.toml +++ b/client/state-db/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] parking_lot = "0.12.0" log = "0.4.11" sc-client-api = { version = "4.0.0-dev", path = "../api" } -sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"] } parity-util-mem = { version = "0.11.0", default-features = false, features = ["primitive-types"] } parity-util-mem-derive = "0.1.0" diff --git a/client/sync-state-rpc/Cargo.toml b/client/sync-state-rpc/Cargo.toml index 524e9259288a..e6072267f963 100644 --- a/client/sync-state-rpc/Cargo.toml +++ b/client/sync-state-rpc/Cargo.toml @@ -25,5 +25,5 @@ sc-finality-grandpa = { version = "0.10.0-dev", path = "../finality-grandpa" } serde_json = "1.0.74" serde = { version = "1.0.136", features = ["derive"] } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } -sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } +sp-runtime = { version = "6.0.0", path = "../../primitives/runtime" } codec = { package = "parity-scale-codec", version = "3.0.0" } diff --git a/client/tracing/Cargo.toml b/client/tracing/Cargo.toml index 2d892c926eb6..ab7d231e2c17 100644 --- a/client/tracing/Cargo.toml +++ b/client/tracing/Cargo.toml @@ -28,12 +28,12 @@ thiserror = "1.0.30" tracing = "0.1.29" tracing-log = "0.1.2" tracing-subscriber = { version = "0.2.25", features = ["parking_lot"] } -sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } -sp-rpc = { version = "5.0.0", path = "../../primitives/rpc" } -sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } +sp-tracing = { version = "5.0.0", path = "../../primitives/tracing" } +sp-rpc = { version = "6.0.0", path = "../../primitives/rpc" } +sp-runtime = { version = "6.0.0", path = "../../primitives/runtime" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } -sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } sc-client-api = { version = "4.0.0-dev", path = "../api" } sc-tracing-proc-macro = { version = "4.0.0-dev", path = "./proc-macro" } sc-rpc-server = { version = "4.0.0-dev", path = "../rpc-servers" } diff --git a/client/transaction-pool/Cargo.toml b/client/transaction-pool/Cargo.toml index ac5beeac605f..4c9a341db6a2 100644 --- a/client/transaction-pool/Cargo.toml +++ b/client/transaction-pool/Cargo.toml @@ -23,9 +23,9 @@ parking_lot = "0.12.0" prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.10.0-dev"} sc-client-api = { version = "4.0.0-dev", path = "../api" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } -sp-core = { version = "5.0.0", path = "../../primitives/core" } -sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } -sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } +sp-runtime = { version = "6.0.0", path = "../../primitives/runtime" } +sp-tracing = { version = "5.0.0", path = "../../primitives/tracing" } sp-transaction-pool = { version = "4.0.0-dev", path = "../../primitives/transaction-pool" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "./api" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } diff --git a/client/transaction-pool/api/Cargo.toml b/client/transaction-pool/api/Cargo.toml index eb5f0ed6b0b7..b444be6c6e78 100644 --- a/client/transaction-pool/api/Cargo.toml +++ b/client/transaction-pool/api/Cargo.toml @@ -14,5 +14,5 @@ log = "0.4.8" serde = { version = "1.0.136", features = ["derive"] } thiserror = "1.0.30" -sp-runtime = { version = "5.0.0", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../../primitives/runtime" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } diff --git a/frame/assets/Cargo.toml b/frame/assets/Cargo.toml index 02faa20d03f9..b69b53a095eb 100644 --- a/frame/assets/Cargo.toml +++ b/frame/assets/Cargo.toml @@ -17,7 +17,7 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } # Needed for various traits. In our case, `OnFinalize`. -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } # Needed for type-safe access to storage DB. frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } # `system` module provides us with all sorts of useful stuff and macros depend on it being around. @@ -25,9 +25,9 @@ frame-system = { version = "4.0.0-dev", default-features = false, path = "../sys frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } sp-std = { version = "4.0.0", path = "../../primitives/std" } -sp-io = { version = "5.0.0", path = "../../primitives/io" } +sp-io = { version = "6.0.0", path = "../../primitives/io" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/frame/atomic-swap/Cargo.toml b/frame/atomic-swap/Cargo.toml index 7b737d15d2f5..9be0868760dd 100644 --- a/frame/atomic-swap/Cargo.toml +++ b/frame/atomic-swap/Cargo.toml @@ -17,10 +17,10 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } -sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } +sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } +sp-core = { version = "6.0.0", default-features = false, path = "../../primitives/core" } [dev-dependencies] pallet-balances = { version = "4.0.0-dev", path = "../balances" } diff --git a/frame/aura/Cargo.toml b/frame/aura/Cargo.toml index 3b1a96f66c46..d6d792886c2f 100644 --- a/frame/aura/Cargo.toml +++ b/frame/aura/Cargo.toml @@ -13,19 +13,19 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-application-crypto = { version = "5.0.0", default-features = false, path = "../../primitives/application-crypto" } +sp-application-crypto = { version = "6.0.0", default-features = false, path = "../../primitives/application-crypto" } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } sp-consensus-aura = { version = "0.10.0-dev", path = "../../primitives/consensus/aura", default-features = false } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } pallet-timestamp = { version = "4.0.0-dev", default-features = false, path = "../timestamp" } [dev-dependencies] -sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } -sp-io = { version = "5.0.0", path = "../../primitives/io" } +sp-core = { version = "6.0.0", default-features = false, path = "../../primitives/core" } +sp-io = { version = "6.0.0", path = "../../primitives/io" } [features] default = ["std"] diff --git a/frame/authority-discovery/Cargo.toml b/frame/authority-discovery/Cargo.toml index 509cea33f6a9..c44134190e8a 100644 --- a/frame/authority-discovery/Cargo.toml +++ b/frame/authority-discovery/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-authority-discovery = { version = "4.0.0-dev", default-features = false, path = "../../primitives/authority-discovery" } -sp-application-crypto = { version = "5.0.0", default-features = false, path = "../../primitives/application-crypto" } +sp-application-crypto = { version = "6.0.0", default-features = false, path = "../../primitives/application-crypto" } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", ] } @@ -23,13 +23,13 @@ sp-std = { version = "4.0.0", default-features = false, path = "../../primitives pallet-session = { version = "4.0.0-dev", features = [ "historical", ], path = "../session", default-features = false } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "5.0.0", path = "../../primitives/core" } -sp-io = { version = "5.0.0", path = "../../primitives/io" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } +sp-io = { version = "6.0.0", path = "../../primitives/io" } [features] default = ["std"] diff --git a/frame/authorship/Cargo.toml b/frame/authorship/Cargo.toml index 379a1ab97b8b..adeebf0e4b37 100644 --- a/frame/authorship/Cargo.toml +++ b/frame/authorship/Cargo.toml @@ -19,14 +19,14 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-authorship = { version = "4.0.0-dev", default-features = false, path = "../../primitives/authorship" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } impl-trait-for-tuples = "0.2.1" [dev-dependencies] -sp-core = { version = "5.0.0", path = "../../primitives/core" } -sp-io = { version = "5.0.0", path = "../../primitives/io" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } +sp-io = { version = "6.0.0", path = "../../primitives/io" } [features] default = ["std"] diff --git a/frame/babe/Cargo.toml b/frame/babe/Cargo.toml index 88be992250c7..d4447ba33855 100644 --- a/frame/babe/Cargo.toml +++ b/frame/babe/Cargo.toml @@ -21,11 +21,11 @@ frame-system = { version = "4.0.0-dev", default-features = false, path = "../sys pallet-authorship = { version = "4.0.0-dev", default-features = false, path = "../authorship" } pallet-session = { version = "4.0.0-dev", default-features = false, path = "../session" } pallet-timestamp = { version = "4.0.0-dev", default-features = false, path = "../timestamp" } -sp-application-crypto = { version = "5.0.0", default-features = false, path = "../../primitives/application-crypto" } +sp-application-crypto = { version = "6.0.0", default-features = false, path = "../../primitives/application-crypto" } sp-consensus-babe = { version = "0.10.0-dev", default-features = false, path = "../../primitives/consensus/babe" } sp-consensus-vrf = { version = "0.10.0-dev", default-features = false, path = "../../primitives/consensus/vrf" } -sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../primitives/session" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } @@ -36,7 +36,7 @@ pallet-balances = { version = "4.0.0-dev", path = "../balances" } pallet-offences = { version = "4.0.0-dev", path = "../offences" } pallet-staking = { version = "4.0.0-dev", path = "../staking" } pallet-staking-reward-curve = { version = "4.0.0-dev", path = "../staking/reward-curve" } -sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } frame-election-provider-support = { version = "4.0.0-dev", path = "../election-provider-support" } [features] diff --git a/frame/bags-list/Cargo.toml b/frame/bags-list/Cargo.toml index 18e2c048186c..f96048d7fcb8 100644 --- a/frame/bags-list/Cargo.toml +++ b/frame/bags-list/Cargo.toml @@ -18,7 +18,7 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } # primitives -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } # FRAME @@ -32,14 +32,14 @@ log = { version = "0.4.14", default-features = false } # Optional imports for benchmarking frame-benchmarking = { version = "4.0.0-dev", path = "../benchmarking", optional = true, default-features = false } pallet-balances = { version = "4.0.0-dev", path = "../balances", optional = true, default-features = false } -sp-core = { version = "5.0.0", path = "../../primitives/core", optional = true, default-features = false } -sp-io = { version = "5.0.0", path = "../../primitives/io", optional = true, default-features = false } -sp-tracing = { version = "4.0.0", path = "../../primitives/tracing", optional = true, default-features = false } +sp-core = { version = "6.0.0", path = "../../primitives/core", optional = true, default-features = false } +sp-io = { version = "6.0.0", path = "../../primitives/io", optional = true, default-features = false } +sp-tracing = { version = "5.0.0", path = "../../primitives/tracing", optional = true, default-features = false } [dev-dependencies] -sp-core = { version = "5.0.0", path = "../../primitives/core"} -sp-io = { version = "5.0.0", path = "../../primitives/io"} -sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } +sp-core = { version = "6.0.0", path = "../../primitives/core"} +sp-io = { version = "6.0.0", path = "../../primitives/io"} +sp-tracing = { version = "5.0.0", path = "../../primitives/tracing" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } frame-election-provider-support = { version = "4.0.0-dev", path = "../election-provider-support", features = ["runtime-benchmarks"] } frame-benchmarking = { version = "4.0.0-dev", path = "../benchmarking" } diff --git a/frame/bags-list/remote-tests/Cargo.toml b/frame/bags-list/remote-tests/Cargo.toml index 8f3ce53f8ebb..e81c4f1a8d4e 100644 --- a/frame/bags-list/remote-tests/Cargo.toml +++ b/frame/bags-list/remote-tests/Cargo.toml @@ -21,10 +21,10 @@ frame-system = { path = "../../system", version = "4.0.0-dev" } frame-support = { path = "../../support", version = "4.0.0-dev" } # core -sp-storage = { path = "../../../primitives/storage", version = "5.0.0"} -sp-core = { path = "../../../primitives/core", version = "5.0.0"} -sp-tracing = { path = "../../../primitives/tracing", version = "4.0.0" } -sp-runtime = { path = "../../../primitives/runtime", version = "5.0.0"} +sp-storage = { path = "../../../primitives/storage", version = "6.0.0"} +sp-core = { path = "../../../primitives/core", version = "6.0.0"} +sp-tracing = { path = "../../../primitives/tracing", version = "5.0.0"} +sp-runtime = { path = "../../../primitives/runtime", version = "6.0.0"} sp-std = { path = "../../../primitives/std", version = "4.0.0" } # utils diff --git a/frame/balances/Cargo.toml b/frame/balances/Cargo.toml index f7e7c662b020..d0a6f2699ab3 100644 --- a/frame/balances/Cargo.toml +++ b/frame/balances/Cargo.toml @@ -16,15 +16,15 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } log = { version = "0.4.14", default-features = false } [dev-dependencies] -sp-io = { version = "5.0.0", path = "../../primitives/io" } -sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-io = { version = "6.0.0", path = "../../primitives/io" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } pallet-transaction-payment = { version = "4.0.0-dev", path = "../transaction-payment" } [features] diff --git a/frame/beefy-mmr/Cargo.toml b/frame/beefy-mmr/Cargo.toml index c5aafa94295e..c6d3b1b165fa 100644 --- a/frame/beefy-mmr/Cargo.toml +++ b/frame/beefy-mmr/Cargo.toml @@ -21,9 +21,9 @@ pallet-mmr = { version = "4.0.0-dev", path = "../merkle-mountain-range", default pallet-mmr-primitives = { version = "4.0.0-dev", path = "../merkle-mountain-range/primitives", default-features = false } pallet-session = { version = "4.0.0-dev", path = "../session", default-features = false } -sp-core = { version = "5.0.0", path = "../../primitives/core", default-features = false } -sp-io = { version = "5.0.0", path = "../../primitives/io", default-features = false } -sp-runtime = { version = "5.0.0", path = "../../primitives/runtime", default-features = false } +sp-core = { version = "6.0.0", path = "../../primitives/core", default-features = false } +sp-io = { version = "6.0.0", path = "../../primitives/io", default-features = false } +sp-runtime = { version = "6.0.0", path = "../../primitives/runtime", default-features = false } sp-std = { version = "4.0.0", path = "../../primitives/std", default-features = false } beefy-merkle-tree = { version = "4.0.0-dev", path = "./primitives", default-features = false } diff --git a/frame/beefy/Cargo.toml b/frame/beefy/Cargo.toml index ed5682fdb474..dc7ef8eda86b 100644 --- a/frame/beefy/Cargo.toml +++ b/frame/beefy/Cargo.toml @@ -15,7 +15,7 @@ serde = { version = "1.0.136", optional = true } frame-support = { version = "4.0.0-dev", path = "../support", default-features = false } frame-system = { version = "4.0.0-dev", path = "../system", default-features = false } -sp-runtime = { version = "5.0.0", path = "../../primitives/runtime", default-features = false } +sp-runtime = { version = "6.0.0", path = "../../primitives/runtime", default-features = false } sp-std = { version = "4.0.0", path = "../../primitives/std", default-features = false } pallet-session = { version = "4.0.0-dev", path = "../session", default-features = false } @@ -23,8 +23,8 @@ pallet-session = { version = "4.0.0-dev", path = "../session", default-features beefy-primitives = { version = "4.0.0-dev", path = "../../primitives/beefy", default-features = false } [dev-dependencies] -sp-core = { version = "5.0.0", path = "../../primitives/core" } -sp-io = { version = "5.0.0", path = "../../primitives/io" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } +sp-io = { version = "6.0.0", path = "../../primitives/io" } sp-staking = { version = "4.0.0-dev", path = "../../primitives/staking" } [features] diff --git a/frame/benchmarking/Cargo.toml b/frame/benchmarking/Cargo.toml index 87089247cc95..37259f351e9f 100644 --- a/frame/benchmarking/Cargo.toml +++ b/frame/benchmarking/Cargo.toml @@ -18,12 +18,12 @@ paste = "1.0" codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-api = { version = "4.0.0-dev", path = "../../primitives/api", default-features = false } -sp-runtime-interface = { version = "5.0.0", path = "../../primitives/runtime-interface", default-features = false } -sp-runtime = { version = "5.0.0", path = "../../primitives/runtime", default-features = false } +sp-runtime-interface = { version = "6.0.0", path = "../../primitives/runtime-interface", default-features = false } +sp-runtime = { version = "6.0.0", path = "../../primitives/runtime", default-features = false } sp-std = { version = "4.0.0", path = "../../primitives/std", default-features = false } -sp-io = { version = "5.0.0", path = "../../primitives/io", default-features = false } -sp-application-crypto = { version = "5.0.0", path = "../../primitives/application-crypto", default-features = false } -sp-storage = { version = "5.0.0", path = "../../primitives/storage", default-features = false } +sp-io = { version = "6.0.0", path = "../../primitives/io", default-features = false } +sp-application-crypto = { version = "6.0.0", path = "../../primitives/application-crypto", default-features = false } +sp-storage = { version = "6.0.0", path = "../../primitives/storage", default-features = false } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } log = { version = "0.4.14", default-features = false } @@ -31,7 +31,7 @@ serde = { version = "1.0.136", optional = true } [dev-dependencies] hex-literal = "0.3.4" -sp-keystore = { version = "0.11.0", path = "../../primitives/keystore" } +sp-keystore = { version = "0.12.0", path = "../../primitives/keystore" } [features] default = ["std"] diff --git a/frame/bounties/Cargo.toml b/frame/bounties/Cargo.toml index cc35d54f25e1..7907df2209a4 100644 --- a/frame/bounties/Cargo.toml +++ b/frame/bounties/Cargo.toml @@ -18,12 +18,12 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = ] } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } pallet-treasury = { version = "4.0.0-dev", default-features = false, path = "../treasury" } -sp-io = { version = "5.0.0", path = "../../primitives/io", default-features = false } -sp-core = { version = "5.0.0", path = "../../primitives/core", default-features = false } +sp-io = { version = "6.0.0", path = "../../primitives/io", default-features = false } +sp-core = { version = "6.0.0", path = "../../primitives/core", default-features = false } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } log = { version = "0.4.14", default-features = false } diff --git a/frame/child-bounties/Cargo.toml b/frame/child-bounties/Cargo.toml index d912bce112b8..91df3e051f1b 100644 --- a/frame/child-bounties/Cargo.toml +++ b/frame/child-bounties/Cargo.toml @@ -18,13 +18,13 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = ] } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } pallet-treasury = { version = "4.0.0-dev", default-features = false, path = "../treasury" } pallet-bounties = { version = "4.0.0-dev", default-features = false, path = "../bounties" } -sp-io = { version = "5.0.0", path = "../../primitives/io", default-features = false } -sp-core = { version = "5.0.0", path = "../../primitives/core", default-features = false } +sp-io = { version = "6.0.0", path = "../../primitives/io", default-features = false } +sp-core = { version = "6.0.0", path = "../../primitives/core", default-features = false } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } log = { version = "0.4.14", default-features = false } diff --git a/frame/collective/Cargo.toml b/frame/collective/Cargo.toml index c679bb21e820..190f477dd893 100644 --- a/frame/collective/Cargo.toml +++ b/frame/collective/Cargo.toml @@ -17,9 +17,9 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = log = { version = "0.4.14", default-features = false } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } -sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } -sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-core = { version = "6.0.0", default-features = false, path = "../../primitives/core" } +sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } diff --git a/frame/contracts/Cargo.toml b/frame/contracts/Cargo.toml index cf726b76a5f7..ca7b8ec1aa9f 100644 --- a/frame/contracts/Cargo.toml +++ b/frame/contracts/Cargo.toml @@ -35,11 +35,11 @@ rand_pcg = { version = "0.3", optional = true } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } -pallet-contracts-primitives = { version = "5.0.0", default-features = false, path = "common" } +pallet-contracts-primitives = { version = "6.0.0", default-features = false, path = "common" } pallet-contracts-proc-macro = { version = "4.0.0-dev", path = "proc-macro" } -sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } -sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-core = { version = "6.0.0", default-features = false, path = "../../primitives/core" } +sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } sp-sandbox = { version = "0.10.0-dev", default-features = false, path = "../../primitives/sandbox" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } @@ -55,7 +55,7 @@ pallet-balances = { version = "4.0.0-dev", path = "../balances" } pallet-timestamp = { version = "4.0.0-dev", path = "../timestamp" } pallet-randomness-collective-flip = { version = "4.0.0-dev", path = "../randomness-collective-flip" } pallet-utility = { version = "4.0.0-dev", path = "../utility" } -sp-keystore = { version = "0.11.0", path = "../../primitives/keystore" } +sp-keystore = { version = "0.12.0", path = "../../primitives/keystore" } [features] default = ["std"] diff --git a/frame/contracts/common/Cargo.toml b/frame/contracts/common/Cargo.toml index d19a160fc45c..49d7973ab155 100644 --- a/frame/contracts/common/Cargo.toml +++ b/frame/contracts/common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pallet-contracts-primitives" -version = "5.0.0" +version = "6.0.0" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" @@ -19,10 +19,10 @@ scale-info = { version = "2.0.0", default-features = false, features = ["derive" serde = { version = "1", features = ["derive"], optional = true } # Substrate Dependencies (This crate should not rely on frame) -sp-core = { version = "5.0.0", path = "../../../primitives/core", default-features = false } +sp-core = { version = "6.0.0", path = "../../../primitives/core", default-features = false } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } -sp-rpc = { version = "5.0.0", path = "../../../primitives/rpc", optional = true } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../../primitives/runtime" } +sp-rpc = { version = "6.0.0", path = "../../../primitives/rpc", optional = true } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../../primitives/runtime" } [features] default = ["std"] diff --git a/frame/contracts/rpc/Cargo.toml b/frame/contracts/rpc/Cargo.toml index 57429fed6722..e506e78a2fbd 100644 --- a/frame/contracts/rpc/Cargo.toml +++ b/frame/contracts/rpc/Cargo.toml @@ -20,13 +20,13 @@ jsonrpc-derive = "18.0.0" serde = { version = "1", features = ["derive"] } # Substrate Dependencies -pallet-contracts-primitives = { version = "5.0.0", path = "../common" } +pallet-contracts-primitives = { version = "6.0.0", path = "../common" } pallet-contracts-rpc-runtime-api = { version = "4.0.0-dev", path = "./runtime-api" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-core = { version = "5.0.0", path = "../../../primitives/core" } -sp-rpc = { version = "5.0.0", path = "../../../primitives/rpc" } -sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } +sp-core = { version = "6.0.0", path = "../../../primitives/core" } +sp-rpc = { version = "6.0.0", path = "../../../primitives/rpc" } +sp-runtime = { version = "6.0.0", path = "../../../primitives/runtime" } [dev-dependencies] serde_json = "1" diff --git a/frame/contracts/rpc/runtime-api/Cargo.toml b/frame/contracts/rpc/runtime-api/Cargo.toml index 071b4bafeef4..5c95cfacf76b 100644 --- a/frame/contracts/rpc/runtime-api/Cargo.toml +++ b/frame/contracts/rpc/runtime-api/Cargo.toml @@ -17,9 +17,9 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } # Substrate Dependencies -pallet-contracts-primitives = { version = "5.0.0", default-features = false, path = "../../common" } +pallet-contracts-primitives = { version = "6.0.0", default-features = false, path = "../../common" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/api" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../../../primitives/runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../../../primitives/std" } [features] diff --git a/frame/conviction-voting/Cargo.toml b/frame/conviction-voting/Cargo.toml index 7e9930257435..a2d3bde497c4 100644 --- a/frame/conviction-voting/Cargo.toml +++ b/frame/conviction-voting/Cargo.toml @@ -19,15 +19,15 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = ] } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } -sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } assert_matches = "1.3.0" [dev-dependencies] -sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } pallet-scheduler = { version = "4.0.0-dev", path = "../scheduler" } diff --git a/frame/democracy/Cargo.toml b/frame/democracy/Cargo.toml index e6fe550f8845..dddfcd9e1a31 100644 --- a/frame/democracy/Cargo.toml +++ b/frame/democracy/Cargo.toml @@ -19,14 +19,14 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = ] } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } pallet-scheduler = { version = "4.0.0-dev", path = "../scheduler" } diff --git a/frame/election-provider-multi-phase/Cargo.toml b/frame/election-provider-multi-phase/Cargo.toml index e96e9c446442..ffaad4f46669 100644 --- a/frame/election-provider-multi-phase/Cargo.toml +++ b/frame/election-provider-multi-phase/Cargo.toml @@ -23,12 +23,12 @@ log = { version = "0.4.14", default-features = false } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } -sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } +sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-core = { version = "6.0.0", default-features = false, path = "../../primitives/core" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } sp-npos-elections = { version = "4.0.0-dev", default-features = false, path = "../../primitives/npos-elections" } -sp-arithmetic = { version = "4.0.0", default-features = false, path = "../../primitives/arithmetic" } +sp-arithmetic = { version = "5.0.0", default-features = false, path = "../../primitives/arithmetic" } frame-election-provider-support = { version = "4.0.0-dev", default-features = false, path = "../election-provider-support" } # Optional imports for benchmarking @@ -42,10 +42,10 @@ strum = { optional = true, default-features = false, version = "0.23.0", feature [dev-dependencies] parking_lot = "0.12.0" rand = { version = "0.7.3" } -sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } -sp-io = { version = "5.0.0", path = "../../primitives/io" } +sp-core = { version = "6.0.0", default-features = false, path = "../../primitives/core" } +sp-io = { version = "6.0.0", path = "../../primitives/io" } sp-npos-elections = { version = "4.0.0-dev", default-features = false, path = "../../primitives/npos-elections" } -sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } +sp-tracing = { version = "5.0.0", path = "../../primitives/tracing" } frame-election-provider-support = { version = "4.0.0-dev", features = [ ], path = "../election-provider-support" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } diff --git a/frame/election-provider-support/Cargo.toml b/frame/election-provider-support/Cargo.toml index 0d11a4ac503e..9364dd5553ef 100644 --- a/frame/election-provider-support/Cargo.toml +++ b/frame/election-provider-support/Cargo.toml @@ -16,16 +16,16 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-arithmetic = { version = "4.0.0", default-features = false, path = "../../primitives/arithmetic" } +sp-arithmetic = { version = "5.0.0", default-features = false, path = "../../primitives/arithmetic" } sp-npos-elections = { version = "4.0.0-dev", default-features = false, path = "../../primitives/npos-elections" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } [dev-dependencies] sp-npos-elections = { version = "4.0.0-dev", path = "../../primitives/npos-elections" } -sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } -sp-core = { version = "5.0.0", path = "../../primitives/core" } -sp-io = { version = "5.0.0", path = "../../primitives/io" } +sp-runtime = { version = "6.0.0", path = "../../primitives/runtime" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } +sp-io = { version = "6.0.0", path = "../../primitives/io" } [features] default = ["std"] diff --git a/frame/elections-phragmen/Cargo.toml b/frame/elections-phragmen/Cargo.toml index 3312e4863a64..f772a82d73d8 100644 --- a/frame/elections-phragmen/Cargo.toml +++ b/frame/elections-phragmen/Cargo.toml @@ -17,19 +17,19 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = "derive", ] } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } sp-npos-elections = { version = "4.0.0-dev", default-features = false, path = "../../primitives/npos-elections" } -sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } +sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } +sp-core = { version = "6.0.0", default-features = false, path = "../../primitives/core" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } log = { version = "0.4.14", default-features = false } [dev-dependencies] pallet-balances = { version = "4.0.0-dev", path = "../balances" } -sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } substrate-test-utils = { version = "4.0.0-dev", path = "../../test-utils" } [features] diff --git a/frame/examples/basic/Cargo.toml b/frame/examples/basic/Cargo.toml index c368af4267c3..837244811e4f 100644 --- a/frame/examples/basic/Cargo.toml +++ b/frame/examples/basic/Cargo.toml @@ -21,12 +21,12 @@ frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = " frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" } pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../../balances" } -sp-io = { version = "5.0.0", default-features = false, path = "../../../primitives/io" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../../primitives/runtime" } +sp-io = { version = "6.0.0", default-features = false, path = "../../../primitives/io" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } [dev-dependencies] -sp-core = { version = "5.0.0", path = "../../../primitives/core", default-features = false } +sp-core = { version = "6.0.0", path = "../../../primitives/core", default-features = false } [features] default = ["std"] diff --git a/frame/examples/offchain-worker/Cargo.toml b/frame/examples/offchain-worker/Cargo.toml index bf6acd652b61..32ca98f505b0 100644 --- a/frame/examples/offchain-worker/Cargo.toml +++ b/frame/examples/offchain-worker/Cargo.toml @@ -20,10 +20,10 @@ scale-info = { version = "2.0.0", default-features = false, features = ["derive" frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" } -sp-core = { version = "5.0.0", default-features = false, path = "../../../primitives/core" } -sp-io = { version = "5.0.0", default-features = false, path = "../../../primitives/io" } -sp-keystore = { version = "0.11.0", path = "../../../primitives/keystore", optional = true } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../../primitives/runtime" } +sp-core = { version = "6.0.0", default-features = false, path = "../../../primitives/core" } +sp-io = { version = "6.0.0", default-features = false, path = "../../../primitives/io" } +sp-keystore = { version = "0.12.0", path = "../../../primitives/keystore", optional = true } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } [features] diff --git a/frame/examples/parallel/Cargo.toml b/frame/examples/parallel/Cargo.toml index ba3c6de5d17a..2d5a2432e661 100644 --- a/frame/examples/parallel/Cargo.toml +++ b/frame/examples/parallel/Cargo.toml @@ -17,9 +17,9 @@ scale-info = { version = "2.0.0", default-features = false, features = ["derive" frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" } -sp-core = { version = "5.0.0", default-features = false, path = "../../../primitives/core" } -sp-io = { version = "5.0.0", default-features = false, path = "../../../primitives/io" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../../primitives/runtime" } +sp-core = { version = "6.0.0", default-features = false, path = "../../../primitives/core" } +sp-io = { version = "6.0.0", default-features = false, path = "../../../primitives/io" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } sp-tasks = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/tasks" } diff --git a/frame/executive/Cargo.toml b/frame/executive/Cargo.toml index dd37b27d4eb9..5613b4256236 100644 --- a/frame/executive/Cargo.toml +++ b/frame/executive/Cargo.toml @@ -19,19 +19,19 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } -sp-tracing = { version = "4.0.0", default-features = false, path = "../../primitives/tracing" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } +sp-tracing = { version = "5.0.0", default-features = false, path = "../../primitives/tracing" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } -sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } +sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } +sp-core = { version = "6.0.0", default-features = false, path = "../../primitives/core" } [dev-dependencies] hex-literal = "0.3.4" -sp-core = { version = "5.0.0", path = "../../primitives/core" } -sp-io = { version = "5.0.0", path = "../../primitives/io" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } +sp-io = { version = "6.0.0", path = "../../primitives/io" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } pallet-transaction-payment = { version = "4.0.0-dev", path = "../transaction-payment" } -sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } +sp-version = { version = "5.0.0", path = "../../primitives/version" } sp-inherents = { version = "4.0.0-dev", path = "../../primitives/inherents" } [features] diff --git a/frame/gilt/Cargo.toml b/frame/gilt/Cargo.toml index 52b5be3a857b..f47166fb3d08 100644 --- a/frame/gilt/Cargo.toml +++ b/frame/gilt/Cargo.toml @@ -16,15 +16,15 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } -sp-arithmetic = { version = "4.0.0", default-features = false, path = "../../primitives/arithmetic" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } +sp-arithmetic = { version = "5.0.0", default-features = false, path = "../../primitives/arithmetic" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } [dev-dependencies] -sp-io = { version = "5.0.0", path = "../../primitives/io" } -sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-io = { version = "6.0.0", path = "../../primitives/io" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/frame/grandpa/Cargo.toml b/frame/grandpa/Cargo.toml index 52f7b02a387b..ee5fa5e52b8e 100644 --- a/frame/grandpa/Cargo.toml +++ b/frame/grandpa/Cargo.toml @@ -15,13 +15,13 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } -sp-application-crypto = { version = "5.0.0", default-features = false, path = "../../primitives/application-crypto" } -sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } +sp-application-crypto = { version = "6.0.0", default-features = false, path = "../../primitives/application-crypto" } +sp-core = { version = "6.0.0", default-features = false, path = "../../primitives/core" } sp-finality-grandpa = { version = "4.0.0-dev", default-features = false, path = "../../primitives/finality-grandpa" } -sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } +sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../primitives/session" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } @@ -33,7 +33,7 @@ log = { version = "0.4.14", default-features = false } [dev-dependencies] frame-benchmarking = { version = "4.0.0-dev", path = "../benchmarking" } grandpa = { package = "finality-grandpa", version = "0.15.0", features = ["derive-codec"] } -sp-keyring = { version = "5.0.0", path = "../../primitives/keyring" } +sp-keyring = { version = "6.0.0", path = "../../primitives/keyring" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } pallet-offences = { version = "4.0.0-dev", path = "../offences" } pallet-staking = { version = "4.0.0-dev", path = "../staking" } diff --git a/frame/identity/Cargo.toml b/frame/identity/Cargo.toml index 61ac2907a9cd..7159c71644fb 100644 --- a/frame/identity/Cargo.toml +++ b/frame/identity/Cargo.toml @@ -17,14 +17,14 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } enumflags2 = { version = "0.6.2" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/frame/im-online/Cargo.toml b/frame/im-online/Cargo.toml index 119010ef6b04..86d7d9a05341 100644 --- a/frame/im-online/Cargo.toml +++ b/frame/im-online/Cargo.toml @@ -13,14 +13,14 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-application-crypto = { version = "5.0.0", default-features = false, path = "../../primitives/application-crypto" } +sp-application-crypto = { version = "6.0.0", default-features = false, path = "../../primitives/application-crypto" } pallet-authorship = { version = "4.0.0-dev", default-features = false, path = "../authorship" } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } -sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } +sp-core = { version = "6.0.0", default-features = false, path = "../../primitives/core" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/indices/Cargo.toml b/frame/indices/Cargo.toml index 74d84849c37d..d651bcc15c06 100644 --- a/frame/indices/Cargo.toml +++ b/frame/indices/Cargo.toml @@ -15,11 +15,11 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } -sp-keyring = { version = "5.0.0", optional = true, path = "../../primitives/keyring" } +sp-keyring = { version = "6.0.0", optional = true, path = "../../primitives/keyring" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } -sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } +sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } +sp-core = { version = "6.0.0", default-features = false, path = "../../primitives/core" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/lottery/Cargo.toml b/frame/lottery/Cargo.toml index e43339c1eafa..ad94b0935ffd 100644 --- a/frame/lottery/Cargo.toml +++ b/frame/lottery/Cargo.toml @@ -18,7 +18,7 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = ] } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } @@ -27,8 +27,8 @@ frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = " [dev-dependencies] frame-support-test = { version = "3.0.0", path = "../support/test" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } -sp-core = { version = "5.0.0", path = "../../primitives/core" } -sp-io = { version = "5.0.0", path = "../../primitives/io" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } +sp-io = { version = "6.0.0", path = "../../primitives/io" } [features] default = ["std"] diff --git a/frame/membership/Cargo.toml b/frame/membership/Cargo.toml index abf27710cf60..6f654bfbe858 100644 --- a/frame/membership/Cargo.toml +++ b/frame/membership/Cargo.toml @@ -17,9 +17,9 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } log = { version = "0.4.0", default-features = false } -sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } -sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-core = { version = "6.0.0", default-features = false, path = "../../primitives/core" } +sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } diff --git a/frame/merkle-mountain-range/Cargo.toml b/frame/merkle-mountain-range/Cargo.toml index 82c08a3c262f..c0e1f6702c73 100644 --- a/frame/merkle-mountain-range/Cargo.toml +++ b/frame/merkle-mountain-range/Cargo.toml @@ -16,9 +16,9 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } mmr-lib = { package = "ckb-merkle-mountain-range", default-features = false, version = "0.3.2" } -sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } -sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-core = { version = "6.0.0", default-features = false, path = "../../primitives/core" } +sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } diff --git a/frame/merkle-mountain-range/primitives/Cargo.toml b/frame/merkle-mountain-range/primitives/Cargo.toml index fe50ca722200..3ce2caa7762c 100644 --- a/frame/merkle-mountain-range/primitives/Cargo.toml +++ b/frame/merkle-mountain-range/primitives/Cargo.toml @@ -17,8 +17,8 @@ log = { version = "0.4.14", default-features = false } serde = { version = "1.0.136", optional = true, features = ["derive"] } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/api" } -sp-core = { version = "5.0.0", default-features = false, path = "../../../primitives/core" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../../primitives/runtime" } +sp-core = { version = "6.0.0", default-features = false, path = "../../../primitives/core" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" } diff --git a/frame/merkle-mountain-range/rpc/Cargo.toml b/frame/merkle-mountain-range/rpc/Cargo.toml index 6ae0e7a3f076..7124682c5689 100644 --- a/frame/merkle-mountain-range/rpc/Cargo.toml +++ b/frame/merkle-mountain-range/rpc/Cargo.toml @@ -21,8 +21,8 @@ serde = { version = "1.0.136", features = ["derive"] } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-core = { version = "5.0.0", path = "../../../primitives/core" } -sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } +sp-core = { version = "6.0.0", path = "../../../primitives/core" } +sp-runtime = { version = "6.0.0", path = "../../../primitives/runtime" } pallet-mmr-primitives = { version = "4.0.0-dev", path = "../primitives" } diff --git a/frame/multisig/Cargo.toml b/frame/multisig/Cargo.toml index 8251c7bc9c71..67da75a137f9 100644 --- a/frame/multisig/Cargo.toml +++ b/frame/multisig/Cargo.toml @@ -17,14 +17,14 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } +sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/frame/nicks/Cargo.toml b/frame/nicks/Cargo.toml index 0acdd4b5bb55..fa6dd3395a09 100644 --- a/frame/nicks/Cargo.toml +++ b/frame/nicks/Cargo.toml @@ -16,13 +16,13 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/frame/node-authorization/Cargo.toml b/frame/node-authorization/Cargo.toml index 63106ec0aa9b..67c39ca4e350 100644 --- a/frame/node-authorization/Cargo.toml +++ b/frame/node-authorization/Cargo.toml @@ -16,9 +16,9 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } -sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } -sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-core = { version = "6.0.0", default-features = false, path = "../../primitives/core" } +sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } log = { version = "0.4.14", default-features = false } diff --git a/frame/offences/Cargo.toml b/frame/offences/Cargo.toml index f6a1fe7c190f..93ece2ae7fd2 100644 --- a/frame/offences/Cargo.toml +++ b/frame/offences/Cargo.toml @@ -18,15 +18,15 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } serde = { version = "1.0.136", optional = true } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } log = { version = "0.4.14", default-features = false } [dev-dependencies] -sp-io = { version = "5.0.0", path = "../../primitives/io" } -sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-io = { version = "6.0.0", path = "../../primitives/io" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } [features] default = ["std"] diff --git a/frame/offences/benchmarking/Cargo.toml b/frame/offences/benchmarking/Cargo.toml index ebab8114c1bb..605e0c60a03c 100644 --- a/frame/offences/benchmarking/Cargo.toml +++ b/frame/offences/benchmarking/Cargo.toml @@ -29,7 +29,7 @@ pallet-session = { version = "4.0.0-dev", default-features = false, path = "../. pallet-staking = { version = "4.0.0-dev", default-features = false, features = [ "runtime-benchmarks", ], path = "../../staking" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../../primitives/runtime" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/staking" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } frame-election-provider-support = { version = "4.0.0-dev", default-features = false, path = "../../election-provider-support" } @@ -37,8 +37,8 @@ frame-election-provider-support = { version = "4.0.0-dev", default-features = fa [dev-dependencies] pallet-staking-reward-curve = { version = "4.0.0-dev", path = "../../staking/reward-curve" } pallet-timestamp = { version = "4.0.0-dev", path = "../../timestamp" } -sp-core = { version = "5.0.0", path = "../../../primitives/core" } -sp-io = { version = "5.0.0", path = "../../../primitives/io" } +sp-core = { version = "6.0.0", path = "../../../primitives/core" } +sp-io = { version = "6.0.0", path = "../../../primitives/io" } [features] default = ["std"] diff --git a/frame/preimage/Cargo.toml b/frame/preimage/Cargo.toml index 9cffedf6c215..70c5292f7f8c 100644 --- a/frame/preimage/Cargo.toml +++ b/frame/preimage/Cargo.toml @@ -14,15 +14,15 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } -sp-core = { version = "5.0.0", default-features = false, optional = true, path = "../../primitives/core" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } +sp-core = { version = "6.0.0", default-features = false, optional = true, path = "../../primitives/core" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -sp-core = { version = "5.0.0", path = "../../primitives/core", default-features = false } +sp-core = { version = "6.0.0", path = "../../primitives/core", default-features = false } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/frame/proxy/Cargo.toml b/frame/proxy/Cargo.toml index 8bf0a1469c37..6f1dd15ed6b3 100644 --- a/frame/proxy/Cargo.toml +++ b/frame/proxy/Cargo.toml @@ -17,14 +17,14 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } -sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } pallet-utility = { version = "4.0.0-dev", path = "../utility" } diff --git a/frame/randomness-collective-flip/Cargo.toml b/frame/randomness-collective-flip/Cargo.toml index d6fb14c02d8d..d05bcd534ec4 100644 --- a/frame/randomness-collective-flip/Cargo.toml +++ b/frame/randomness-collective-flip/Cargo.toml @@ -16,15 +16,15 @@ targets = ["x86_64-unknown-linux-gnu"] safe-mix = { version = "1.0", default-features = false } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "5.0.0", path = "../../primitives/core" } -sp-io = { version = "5.0.0", path = "../../primitives/io" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } +sp-io = { version = "6.0.0", path = "../../primitives/io" } [features] default = ["std"] diff --git a/frame/recovery/Cargo.toml b/frame/recovery/Cargo.toml index a629b0bbf0e3..6bba8102af2e 100644 --- a/frame/recovery/Cargo.toml +++ b/frame/recovery/Cargo.toml @@ -16,13 +16,13 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/frame/referenda/Cargo.toml b/frame/referenda/Cargo.toml index 56598af91393..080e4d7ab778 100644 --- a/frame/referenda/Cargo.toml +++ b/frame/referenda/Cargo.toml @@ -19,15 +19,15 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = ] } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } -sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } assert_matches = { version = "1.5", optional = true } [dev-dependencies] -sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } pallet-scheduler = { version = "4.0.0-dev", path = "../scheduler" } pallet-preimage = { version = "4.0.0-dev", path = "../preimage" } diff --git a/frame/scheduler/Cargo.toml b/frame/scheduler/Cargo.toml index c45d961bd694..f08a0318a702 100644 --- a/frame/scheduler/Cargo.toml +++ b/frame/scheduler/Cargo.toml @@ -14,15 +14,15 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } log = { version = "0.4.14", default-features = false } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } +sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -sp-core = { version = "5.0.0", path = "../../primitives/core", default-features = false } +sp-core = { version = "6.0.0", path = "../../primitives/core", default-features = false } substrate-test-utils = { version = "4.0.0-dev", path = "../../test-utils" } pallet-preimage = { version = "4.0.0-dev", path = "../preimage" } diff --git a/frame/scored-pool/Cargo.toml b/frame/scored-pool/Cargo.toml index 934400230f7a..203c06065c35 100644 --- a/frame/scored-pool/Cargo.toml +++ b/frame/scored-pool/Cargo.toml @@ -15,15 +15,15 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } -sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } [dev-dependencies] pallet-balances = { version = "4.0.0-dev", path = "../balances" } -sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } [features] default = ["std"] diff --git a/frame/session/Cargo.toml b/frame/session/Cargo.toml index 9bd4d1fc5095..4302c6a44cb0 100644 --- a/frame/session/Cargo.toml +++ b/frame/session/Cargo.toml @@ -20,12 +20,12 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } -sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-core = { version = "6.0.0", default-features = false, path = "../../primitives/core" } +sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../primitives/session" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" } -sp-trie = { version = "5.0.0", default-features = false, path = "../../primitives/trie", optional = true } +sp-trie = { version = "6.0.0", default-features = false, path = "../../primitives/trie", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/session/benchmarking/Cargo.toml b/frame/session/benchmarking/Cargo.toml index 598c3a73e2e3..23336e647b02 100644 --- a/frame/session/benchmarking/Cargo.toml +++ b/frame/session/benchmarking/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] rand = { version = "0.7.2", default-features = false } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../../primitives/runtime" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/session" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../../benchmarking" } @@ -28,8 +28,8 @@ pallet-staking = { version = "4.0.0-dev", default-features = false, features = [ [dev-dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"] } scale-info = "2.0.0" -sp-core = { version = "5.0.0", path = "../../../primitives/core" } -sp-io = { version = "5.0.0", path = "../../../primitives/io" } +sp-core = { version = "6.0.0", path = "../../../primitives/core" } +sp-io = { version = "6.0.0", path = "../../../primitives/io" } pallet-balances = { version = "4.0.0-dev", path = "../../balances" } pallet-timestamp = { version = "4.0.0-dev", path = "../../timestamp" } pallet-staking-reward-curve = { version = "4.0.0-dev", path = "../../staking/reward-curve" } diff --git a/frame/society/Cargo.toml b/frame/society/Cargo.toml index 12fb4202888c..cd3afdb9beeb 100644 --- a/frame/society/Cargo.toml +++ b/frame/society/Cargo.toml @@ -15,15 +15,15 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } rand_chacha = { version = "0.2", default-features = false } [dev-dependencies] -sp-core = { version = "5.0.0", path = "../../primitives/core" } -sp-io ={ version = "5.0.0", path = "../../primitives/io" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } +sp-io ={ version = "6.0.0", path = "../../primitives/io" } frame-support-test = { version = "3.0.0", path = "../support/test" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } diff --git a/frame/staking/Cargo.toml b/frame/staking/Cargo.toml index 6e85382ddaa2..abe977a70eaa 100644 --- a/frame/staking/Cargo.toml +++ b/frame/staking/Cargo.toml @@ -19,8 +19,8 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = ] } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } @@ -28,7 +28,7 @@ pallet-session = { version = "4.0.0-dev", default-features = false, features = [ "historical", ], path = "../session" } pallet-authorship = { version = "4.0.0-dev", default-features = false, path = "../authorship" } -sp-application-crypto = { version = "5.0.0", default-features = false, path = "../../primitives/application-crypto" } +sp-application-crypto = { version = "6.0.0", default-features = false, path = "../../primitives/application-crypto" } frame-election-provider-support = { version = "4.0.0-dev", default-features = false, path = "../election-provider-support" } log = { version = "0.4.14", default-features = false } @@ -37,8 +37,8 @@ frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = " rand_chacha = { version = "0.2", default-features = false, optional = true } [dev-dependencies] -sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } -sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-tracing = { version = "5.0.0", path = "../../primitives/tracing" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } sp-npos-elections = { version = "4.0.0-dev", path = "../../primitives/npos-elections" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } pallet-timestamp = { version = "4.0.0-dev", path = "../timestamp" } diff --git a/frame/staking/reward-curve/Cargo.toml b/frame/staking/reward-curve/Cargo.toml index 86fdd09076e5..82167bd8c8ec 100644 --- a/frame/staking/reward-curve/Cargo.toml +++ b/frame/staking/reward-curve/Cargo.toml @@ -21,4 +21,4 @@ proc-macro2 = "1.0.36" proc-macro-crate = "1.1.0" [dev-dependencies] -sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } +sp-runtime = { version = "6.0.0", path = "../../../primitives/runtime" } diff --git a/frame/staking/reward-fn/Cargo.toml b/frame/staking/reward-fn/Cargo.toml index 07dc404c8e35..9a768becae83 100644 --- a/frame/staking/reward-fn/Cargo.toml +++ b/frame/staking/reward-fn/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [lib] [dependencies] -sp-arithmetic = { version = "4.0.0", default-features = false, path = "../../../primitives/arithmetic" } +sp-arithmetic = { version = "5.0.0", default-features = false, path = "../../../primitives/arithmetic" } log = { version = "0.4.14", default-features = false } [features] diff --git a/frame/sudo/Cargo.toml b/frame/sudo/Cargo.toml index a4b1d21e9efc..17d6ef4da489 100644 --- a/frame/sudo/Cargo.toml +++ b/frame/sudo/Cargo.toml @@ -16,13 +16,13 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } [features] default = ["std"] diff --git a/frame/support/Cargo.toml b/frame/support/Cargo.toml index cd6a082e57cf..796df7697d74 100644 --- a/frame/support/Cargo.toml +++ b/frame/support/Cargo.toml @@ -18,23 +18,23 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } frame-metadata = { version = "15.0.0", default-features = false, features = ["v14"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } -sp-tracing = { version = "4.0.0", default-features = false, path = "../../primitives/tracing" } -sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } -sp-arithmetic = { version = "4.0.0", default-features = false, path = "../../primitives/arithmetic" } +sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } +sp-tracing = { version = "5.0.0", default-features = false, path = "../../primitives/tracing" } +sp-core = { version = "6.0.0", default-features = false, path = "../../primitives/core" } +sp-arithmetic = { version = "5.0.0", default-features = false, path = "../../primitives/arithmetic" } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../primitives/inherents" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" } tt-call = "1.0.8" frame-support-procedural = { version = "4.0.0-dev", default-features = false, path = "./procedural" } paste = "1.0" once_cell = { version = "1", default-features = false, optional = true } -sp-state-machine = { version = "0.11.0", optional = true, path = "../../primitives/state-machine" } +sp-state-machine = { version = "0.12.0", optional = true, path = "../../primitives/state-machine" } bitflags = "1.3" impl-trait-for-tuples = "0.2.1" smallvec = "1.8.0" log = { version = "0.4.14", default-features = false } -sp-core-hashing-proc-macro = { version = "4.0.0-dev", path = "../../primitives/core/hashing/proc-macro" } +sp-core-hashing-proc-macro = { version = "5.0.0", path = "../../primitives/core/hashing/proc-macro" } [dev-dependencies] assert_matches = "1.3.0" diff --git a/frame/support/test/Cargo.toml b/frame/support/test/Cargo.toml index 56e269b43265..ef20915899fd 100644 --- a/frame/support/test/Cargo.toml +++ b/frame/support/test/Cargo.toml @@ -15,14 +15,14 @@ targets = ["x86_64-unknown-linux-gnu"] serde = { version = "1.0.136", default-features = false, features = ["derive"] } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } -sp-arithmetic = { version = "4.0.0", default-features = false, path = "../../../primitives/arithmetic" } -sp-io = { version = "5.0.0", path = "../../../primitives/io", default-features = false } -sp-state-machine = { version = "0.11.0", optional = true, path = "../../../primitives/state-machine" } +sp-arithmetic = { version = "5.0.0", default-features = false, path = "../../../primitives/arithmetic" } +sp-io = { version = "6.0.0", path = "../../../primitives/io", default-features = false } +sp-state-machine = { version = "0.12.0", optional = true, path = "../../../primitives/state-machine" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../../primitives/runtime" } -sp-core = { version = "5.0.0", default-features = false, path = "../../../primitives/core" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../../primitives/runtime" } +sp-core = { version = "6.0.0", default-features = false, path = "../../../primitives/core" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } -sp-version = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/version" } +sp-version = { version = "5.0.0", default-features = false, path = "../../../primitives/version" } trybuild = "1.0.53" pretty_assertions = "1.0.0" rustversion = "1.0.6" diff --git a/frame/support/test/compile_pass/Cargo.toml b/frame/support/test/compile_pass/Cargo.toml index 241ec1b352f4..33ee3e8c2d07 100644 --- a/frame/support/test/compile_pass/Cargo.toml +++ b/frame/support/test/compile_pass/Cargo.toml @@ -14,9 +14,9 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } -sp-core = { version = "5.0.0", default-features = false, path = "../../../../primitives/core" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../../../primitives/runtime" } -sp-version = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/version" } +sp-core = { version = "6.0.0", default-features = false, path = "../../../../primitives/core" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../../../primitives/runtime" } +sp-version = { version = "5.0.0", default-features = false, path = "../../../../primitives/version" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../../" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../../system" } diff --git a/frame/system/Cargo.toml b/frame/system/Cargo.toml index a941f6e95ede..a5a65e403454 100644 --- a/frame/system/Cargo.toml +++ b/frame/system/Cargo.toml @@ -16,17 +16,17 @@ targets = ["x86_64-unknown-linux-gnu"] serde = { version = "1.0.136", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } -sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } +sp-core = { version = "6.0.0", default-features = false, path = "../../primitives/core" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "5.0.0", path = "../../primitives/io", default-features = false } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } -sp-version = { version = "4.0.0-dev", default-features = false, path = "../../primitives/version" } +sp-io = { version = "6.0.0", path = "../../primitives/io", default-features = false } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } +sp-version = { version = "5.0.0", default-features = false, path = "../../primitives/version" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } log = { version = "0.4.14", default-features = false } [dev-dependencies] criterion = "0.3.3" -sp-externalities = { version = "0.11.0", path = "../../primitives/externalities" } +sp-externalities = { version = "0.12.0", path = "../../primitives/externalities" } substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } [features] diff --git a/frame/system/benchmarking/Cargo.toml b/frame/system/benchmarking/Cargo.toml index 858d6954405f..7ca76c260c43 100644 --- a/frame/system/benchmarking/Cargo.toml +++ b/frame/system/benchmarking/Cargo.toml @@ -16,14 +16,14 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../../primitives/runtime" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../../benchmarking" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" } -sp-core = { version = "5.0.0", default-features = false, path = "../../../primitives/core" } +sp-core = { version = "6.0.0", default-features = false, path = "../../../primitives/core" } [dev-dependencies] -sp-io = { version = "5.0.0", path = "../../../primitives/io" } +sp-io = { version = "6.0.0", path = "../../../primitives/io" } [features] default = ["std"] diff --git a/frame/timestamp/Cargo.toml b/frame/timestamp/Cargo.toml index 8cb78c216432..1652be977674 100644 --- a/frame/timestamp/Cargo.toml +++ b/frame/timestamp/Cargo.toml @@ -18,8 +18,8 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io", optional = true } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io", optional = true } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../primitives/inherents" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } @@ -28,8 +28,8 @@ sp-timestamp = { version = "4.0.0-dev", default-features = false, path = "../../ log = { version = "0.4.14", default-features = false } [dev-dependencies] -sp-io ={ version = "5.0.0", path = "../../primitives/io" } -sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-io ={ version = "6.0.0", path = "../../primitives/io" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } [features] default = ["std"] diff --git a/frame/tips/Cargo.toml b/frame/tips/Cargo.toml index 78e260e2368c..017d86ea72b3 100644 --- a/frame/tips/Cargo.toml +++ b/frame/tips/Cargo.toml @@ -18,9 +18,9 @@ log = { version = "0.4.0", default-features = false } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } serde = { version = "1.0.136", features = ["derive"], optional = true } -sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } -sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-core = { version = "6.0.0", default-features = false, path = "../../primitives/core" } +sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } @@ -30,7 +30,7 @@ pallet-treasury = { version = "4.0.0-dev", default-features = false, path = "../ frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -sp-storage = { version = "5.0.0", path = "../../primitives/storage" } +sp-storage = { version = "6.0.0", path = "../../primitives/storage" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/frame/transaction-payment/Cargo.toml b/frame/transaction-payment/Cargo.toml index 0d2388e05bd2..5ac9ea1e713c 100644 --- a/frame/transaction-payment/Cargo.toml +++ b/frame/transaction-payment/Cargo.toml @@ -20,9 +20,9 @@ scale-info = { version = "2.0.0", default-features = false, features = ["derive" serde = { version = "1.0.136", optional = true } smallvec = "1.8.0" -sp-core = { version = "5.0.0", path = "../../primitives/core", default-features = false } -sp-io = { version = "5.0.0", path = "../../primitives/io", default-features = false } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-core = { version = "6.0.0", path = "../../primitives/core", default-features = false } +sp-io = { version = "6.0.0", path = "../../primitives/io", default-features = false } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/frame/transaction-payment/asset-tx-payment/Cargo.toml b/frame/transaction-payment/asset-tx-payment/Cargo.toml index b3471b38045f..da30136c067a 100644 --- a/frame/transaction-payment/asset-tx-payment/Cargo.toml +++ b/frame/transaction-payment/asset-tx-payment/Cargo.toml @@ -14,9 +14,9 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] # Substrate dependencies -sp-core = { version = "5.0.0", default-features = false, path = "../../../primitives/core" } -sp-io = { version = "5.0.0", default-features = false, path = "../../../primitives/io" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../../primitives/runtime" } +sp-core = { version = "6.0.0", default-features = false, path = "../../../primitives/core" } +sp-io = { version = "6.0.0", default-features = false, path = "../../../primitives/io" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" } @@ -32,7 +32,7 @@ serde = { version = "1.0.136", optional = true } smallvec = "1.8.0" serde_json = "1.0.74" -sp-storage = { version = "5.0.0", default-features = false, path = "../../../primitives/storage" } +sp-storage = { version = "6.0.0", default-features = false, path = "../../../primitives/storage" } pallet-assets = { version = "4.0.0-dev", path = "../../assets" } pallet-authorship = { version = "4.0.0-dev", path = "../../authorship" } diff --git a/frame/transaction-payment/rpc/Cargo.toml b/frame/transaction-payment/rpc/Cargo.toml index f5d5036978b4..64d7007dfe6c 100644 --- a/frame/transaction-payment/rpc/Cargo.toml +++ b/frame/transaction-payment/rpc/Cargo.toml @@ -20,7 +20,7 @@ jsonrpc-derive = "18.0.0" sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-core = { version = "5.0.0", path = "../../../primitives/core" } -sp-rpc = { version = "5.0.0", path = "../../../primitives/rpc" } -sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } +sp-core = { version = "6.0.0", path = "../../../primitives/core" } +sp-rpc = { version = "6.0.0", path = "../../../primitives/rpc" } +sp-runtime = { version = "6.0.0", path = "../../../primitives/runtime" } pallet-transaction-payment-rpc-runtime-api = { version = "4.0.0-dev", path = "./runtime-api" } diff --git a/frame/transaction-payment/rpc/runtime-api/Cargo.toml b/frame/transaction-payment/rpc/runtime-api/Cargo.toml index 82bab82a305f..d057361e1f5f 100644 --- a/frame/transaction-payment/rpc/runtime-api/Cargo.toml +++ b/frame/transaction-payment/rpc/runtime-api/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/api" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../../../primitives/runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../../../primitives/runtime" } pallet-transaction-payment = { version = "4.0.0-dev", default-features = false, path = "../../../transaction-payment" } [features] diff --git a/frame/transaction-storage/Cargo.toml b/frame/transaction-storage/Cargo.toml index e1275e2476f9..b4ec343dc621 100644 --- a/frame/transaction-storage/Cargo.toml +++ b/frame/transaction-storage/Cargo.toml @@ -20,16 +20,16 @@ scale-info = { version = "2.0.0", default-features = false, features = ["derive" frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../balances" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } +sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../primitives/inherents" } sp-transaction-storage-proof = { version = "4.0.0-dev", default-features = false, path = "../../primitives/transaction-storage-proof" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] sp-transaction-storage-proof = { version = "4.0.0-dev", default-features = true, path = "../../primitives/transaction-storage-proof" } -sp-core = { version = "5.0.0", path = "../../primitives/core", default-features = false } +sp-core = { version = "6.0.0", path = "../../primitives/core", default-features = false } [features] default = ["std"] diff --git a/frame/treasury/Cargo.toml b/frame/treasury/Cargo.toml index bbcffa68f083..ca32f4713ee2 100644 --- a/frame/treasury/Cargo.toml +++ b/frame/treasury/Cargo.toml @@ -22,7 +22,7 @@ serde = { version = "1.0.136", features = ["derive"], optional = true } impl-trait-for-tuples = "0.2.1" sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } @@ -31,8 +31,8 @@ pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../ [dev-dependencies] -sp-io = { version = "5.0.0", path = "../../primitives/io" } -sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-io = { version = "6.0.0", path = "../../primitives/io" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } [features] default = ["std"] diff --git a/frame/try-runtime/Cargo.toml b/frame/try-runtime/Cargo.toml index 0546c0a898fb..e40b92b8e98d 100644 --- a/frame/try-runtime/Cargo.toml +++ b/frame/try-runtime/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-api = { version = "4.0.0-dev", path = "../../primitives/api", default-features = false } sp-std = { version = "4.0.0", path = "../../primitives/std" , default-features = false } -sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" , default-features = false } +sp-runtime = { version = "6.0.0", path = "../../primitives/runtime" , default-features = false } frame-support = { version = "4.0.0-dev", path = "../support", default-features = false } diff --git a/frame/uniques/Cargo.toml b/frame/uniques/Cargo.toml index e0761711501d..6f4e8f91b26f 100644 --- a/frame/uniques/Cargo.toml +++ b/frame/uniques/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } @@ -24,8 +24,8 @@ log = { version = "0.4.14", default-features = false } [dev-dependencies] sp-std = { version = "4.0.0", path = "../../primitives/std" } -sp-core = { version = "5.0.0", path = "../../primitives/core" } -sp-io = { version = "5.0.0", path = "../../primitives/io" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } +sp-io = { version = "6.0.0", path = "../../primitives/io" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/frame/utility/Cargo.toml b/frame/utility/Cargo.toml index 6397bf028eed..f059937ad2d9 100644 --- a/frame/utility/Cargo.toml +++ b/frame/utility/Cargo.toml @@ -17,15 +17,15 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } -sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-core = { version = "6.0.0", default-features = false, path = "../../primitives/core" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } +sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/frame/vesting/Cargo.toml b/frame/vesting/Cargo.toml index 52942c8670a3..36a877478a4e 100644 --- a/frame/vesting/Cargo.toml +++ b/frame/vesting/Cargo.toml @@ -18,15 +18,15 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = ] } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } log = { version = "0.4.0", default-features = false } [dev-dependencies] -sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } -sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/primitives/api/Cargo.toml b/primitives/api/Cargo.toml index c210201a3115..a0dd8eeb31e7 100644 --- a/primitives/api/Cargo.toml +++ b/primitives/api/Cargo.toml @@ -15,11 +15,11 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } sp-api-proc-macro = { version = "4.0.0-dev", path = "proc-macro" } -sp-core = { version = "5.0.0", default-features = false, path = "../core" } +sp-core = { version = "6.0.0", default-features = false, path = "../core" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../runtime" } -sp-version = { version = "4.0.0-dev", default-features = false, path = "../version" } -sp-state-machine = { version = "0.11.0", optional = true, path = "../state-machine" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../runtime" } +sp-version = { version = "5.0.0", default-features = false, path = "../version" } +sp-state-machine = { version = "0.12.0", optional = true, path = "../state-machine" } hash-db = { version = "0.15.2", optional = true } thiserror = { version = "1.0.30", optional = true } diff --git a/primitives/api/test/Cargo.toml b/primitives/api/test/Cargo.toml index 9078c69f994e..786639f393e9 100644 --- a/primitives/api/test/Cargo.toml +++ b/primitives/api/test/Cargo.toml @@ -14,13 +14,13 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-api = { version = "4.0.0-dev", path = "../" } substrate-test-runtime-client = { version = "2.0.0", path = "../../../test-utils/runtime/client" } -sp-version = { version = "4.0.0-dev", path = "../../version" } -sp-tracing = { version = "4.0.0", path = "../../tracing" } -sp-runtime = { version = "5.0.0", path = "../../runtime" } +sp-version = { version = "5.0.0", path = "../../version" } +sp-tracing = { version = "5.0.0", path = "../../tracing" } +sp-runtime = { version = "6.0.0", path = "../../runtime" } sp-consensus = { version = "0.10.0-dev", path = "../../consensus/common" } sc-block-builder = { version = "0.10.0-dev", path = "../../../client/block-builder" } codec = { package = "parity-scale-codec", version = "3.0.0" } -sp-state-machine = { version = "0.11.0", path = "../../state-machine" } +sp-state-machine = { version = "0.12.0", path = "../../state-machine" } trybuild = "1.0.53" rustversion = "1.0.6" @@ -28,7 +28,7 @@ rustversion = "1.0.6" criterion = "0.3.0" futures = "0.3.19" log = "0.4.14" -sp-core = { version = "5.0.0", path = "../../core" } +sp-core = { version = "6.0.0", path = "../../core" } [[bench]] name = "bench" diff --git a/primitives/application-crypto/Cargo.toml b/primitives/application-crypto/Cargo.toml index 45622d6a5393..7ac487fe35d2 100644 --- a/primitives/application-crypto/Cargo.toml +++ b/primitives/application-crypto/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-application-crypto" -version = "5.0.0" +version = "6.0.0" authors = ["Parity Technologies "] edition = "2021" description = "Provides facilities for generating application specific crypto wrapper types." @@ -15,12 +15,12 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-core = { version = "5.0.0", default-features = false, path = "../core" } +sp-core = { version = "6.0.0", default-features = false, path = "../core" } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } serde = { version = "1.0.136", optional = true, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../std" } -sp-io = { version = "5.0.0", default-features = false, path = "../io" } +sp-io = { version = "6.0.0", default-features = false, path = "../io" } [features] default = [ "std" ] diff --git a/primitives/application-crypto/test/Cargo.toml b/primitives/application-crypto/test/Cargo.toml index 515be41be3d2..9e93e78f69ff 100644 --- a/primitives/application-crypto/test/Cargo.toml +++ b/primitives/application-crypto/test/Cargo.toml @@ -13,9 +13,9 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-core = { version = "5.0.0", default-features = false, path = "../../core" } -sp-keystore = { version = "0.11.0", path = "../../keystore", default-features = false } +sp-core = { version = "6.0.0", default-features = false, path = "../../core" } +sp-keystore = { version = "0.12.0", path = "../../keystore", default-features = false } substrate-test-runtime-client = { version = "2.0.0", path = "../../../test-utils/runtime/client" } -sp-runtime = { version = "5.0.0", path = "../../runtime" } +sp-runtime = { version = "6.0.0", path = "../../runtime" } sp-api = { version = "4.0.0-dev", path = "../../api" } -sp-application-crypto = { version = "5.0.0", path = "../" } +sp-application-crypto = { version = "6.0.0", path = "../" } diff --git a/primitives/arithmetic/Cargo.toml b/primitives/arithmetic/Cargo.toml index 26b0fbcf98d0..654127671466 100644 --- a/primitives/arithmetic/Cargo.toml +++ b/primitives/arithmetic/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-arithmetic" -version = "4.0.0" +version = "5.0.0" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" @@ -17,6 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", + "max-encoded-len", ] } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } integer-sqrt = "0.1.2" diff --git a/primitives/arithmetic/fuzzer/Cargo.toml b/primitives/arithmetic/fuzzer/Cargo.toml index d715515056bb..e51dd4e415a6 100644 --- a/primitives/arithmetic/fuzzer/Cargo.toml +++ b/primitives/arithmetic/fuzzer/Cargo.toml @@ -14,7 +14,7 @@ publish = false targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-arithmetic = { version = "4.0.0", path = ".." } +sp-arithmetic = { version = "5.0.0", path = ".." } honggfuzz = "0.5.49" primitive-types = "0.11.1" num-bigint = "0.2" diff --git a/primitives/authority-discovery/Cargo.toml b/primitives/authority-discovery/Cargo.toml index adbeeb473f2a..687987ab2ec9 100644 --- a/primitives/authority-discovery/Cargo.toml +++ b/primitives/authority-discovery/Cargo.toml @@ -13,12 +13,12 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-application-crypto = { version = "5.0.0", default-features = false, path = "../application-crypto" } +sp-application-crypto = { version = "6.0.0", default-features = false, path = "../application-crypto" } codec = { package = "parity-scale-codec", default-features = false, version = "3.0.0" } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../runtime" } [features] default = ["std"] diff --git a/primitives/authorship/Cargo.toml b/primitives/authorship/Cargo.toml index 93b3a43eda17..75e94b895f12 100644 --- a/primitives/authorship/Cargo.toml +++ b/primitives/authorship/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../inherents" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } async-trait = { version = "0.1.50", optional = true } diff --git a/primitives/beefy/Cargo.toml b/primitives/beefy/Cargo.toml index b51c5b4948e1..9012803a902d 100644 --- a/primitives/beefy/Cargo.toml +++ b/primitives/beefy/Cargo.toml @@ -12,15 +12,15 @@ codec = { version = "3.0.0", package = "parity-scale-codec", default-features = scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-api = { version = "4.0.0-dev", path = "../api", default-features = false } -sp-application-crypto = { version = "5.0.0", path = "../application-crypto", default-features = false } -sp-core = { version = "5.0.0", path = "../core", default-features = false } -sp-runtime = { version = "5.0.0", path = "../runtime", default-features = false } +sp-application-crypto = { version = "6.0.0", path = "../application-crypto", default-features = false } +sp-core = { version = "6.0.0", path = "../core", default-features = false } +sp-runtime = { version = "6.0.0", path = "../runtime", default-features = false } sp-std = { version = "4.0.0", path = "../std", default-features = false } [dev-dependencies] hex = "0.4.3" hex-literal = "0.3" -sp-keystore = { version = "0.11.0", path = "../keystore" } +sp-keystore = { version = "0.12.0", path = "../keystore" } [features] default = ["std"] diff --git a/primitives/block-builder/Cargo.toml b/primitives/block-builder/Cargo.toml index 6f0fe32db2fa..6d7a0a2789c2 100644 --- a/primitives/block-builder/Cargo.toml +++ b/primitives/block-builder/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-runtime = { version = "5.0.0", default-features = false, path = "../runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../runtime" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } diff --git a/primitives/blockchain/Cargo.toml b/primitives/blockchain/Cargo.toml index 59d0121647c5..bdb326bdb2e9 100644 --- a/primitives/blockchain/Cargo.toml +++ b/primitives/blockchain/Cargo.toml @@ -21,7 +21,7 @@ thiserror = "1.0.30" futures = "0.3.19" codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } sp-consensus = { version = "0.10.0-dev", path = "../consensus/common" } -sp-runtime = { version = "5.0.0", path = "../runtime" } -sp-state-machine = { version = "0.11.0", path = "../state-machine" } +sp-runtime = { version = "6.0.0", path = "../runtime" } +sp-state-machine = { version = "0.12.0", path = "../state-machine" } sp-database = { version = "4.0.0-dev", path = "../database" } sp-api = { version = "4.0.0-dev", path = "../api" } diff --git a/primitives/consensus/aura/Cargo.toml b/primitives/consensus/aura/Cargo.toml index a51d4aaeabec..28f68f15cd9e 100644 --- a/primitives/consensus/aura/Cargo.toml +++ b/primitives/consensus/aura/Cargo.toml @@ -13,12 +13,12 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-application-crypto = { version = "5.0.0", default-features = false, path = "../../application-crypto" } +sp-application-crypto = { version = "6.0.0", default-features = false, path = "../../application-crypto" } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../std" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../api" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../runtime" } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../inherents" } sp-timestamp = { version = "4.0.0-dev", default-features = false, path = "../../timestamp" } sp-consensus-slots = { version = "0.10.0-dev", default-features = false, path = "../slots" } diff --git a/primitives/consensus/babe/Cargo.toml b/primitives/consensus/babe/Cargo.toml index cf276c998f11..46bb51a061e6 100644 --- a/primitives/consensus/babe/Cargo.toml +++ b/primitives/consensus/babe/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-application-crypto = { version = "5.0.0", default-features = false, path = "../../application-crypto" } +sp-application-crypto = { version = "6.0.0", default-features = false, path = "../../application-crypto" } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } merlin = { version = "2.0", default-features = false } @@ -22,10 +22,10 @@ sp-api = { version = "4.0.0-dev", default-features = false, path = "../../api" } sp-consensus = { version = "0.10.0-dev", optional = true, path = "../common" } sp-consensus-slots = { version = "0.10.0-dev", default-features = false, path = "../slots" } sp-consensus-vrf = { version = "0.10.0-dev", path = "../vrf", default-features = false } -sp-core = { version = "5.0.0", default-features = false, path = "../../core" } +sp-core = { version = "6.0.0", default-features = false, path = "../../core" } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../inherents" } -sp-keystore = { version = "0.11.0", default-features = false, path = "../../keystore", optional = true } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../runtime" } +sp-keystore = { version = "0.12.0", default-features = false, path = "../../keystore", optional = true } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../runtime" } sp-timestamp = { version = "4.0.0-dev", path = "../../timestamp", optional = true } serde = { version = "1.0.136", features = ["derive"], optional = true } async-trait = { version = "0.1.50", optional = true } diff --git a/primitives/consensus/common/Cargo.toml b/primitives/consensus/common/Cargo.toml index 4d0d17e1288e..c712eff28500 100644 --- a/primitives/consensus/common/Cargo.toml +++ b/primitives/consensus/common/Cargo.toml @@ -20,13 +20,13 @@ codec = { package = "parity-scale-codec", version = "3.0.0", features = [ ] } futures = { version = "0.3.19", features = ["thread-pool"] } log = "0.4.8" -sp-core = { path = "../../core", version = "5.0.0"} +sp-core = { path = "../../core", version = "6.0.0"} sp-inherents = { version = "4.0.0-dev", path = "../../inherents" } -sp-state-machine = { version = "0.11.0", path = "../../state-machine" } +sp-state-machine = { version = "0.12.0", path = "../../state-machine" } futures-timer = "3.0.1" sp-std = { version = "4.0.0", path = "../../std" } -sp-version = { version = "4.0.0-dev", path = "../../version" } -sp-runtime = { version = "5.0.0", path = "../../runtime" } +sp-version = { version = "5.0.0", path = "../../version" } +sp-runtime = { version = "6.0.0", path = "../../runtime" } thiserror = "1.0.30" [dev-dependencies] diff --git a/primitives/consensus/pow/Cargo.toml b/primitives/consensus/pow/Cargo.toml index d5c8aa9613b3..eb2db085c482 100644 --- a/primitives/consensus/pow/Cargo.toml +++ b/primitives/consensus/pow/Cargo.toml @@ -15,8 +15,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-api = { version = "4.0.0-dev", default-features = false, path = "../../api" } sp-std = { version = "4.0.0", default-features = false, path = "../../std" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../runtime" } -sp-core = { version = "5.0.0", default-features = false, path = "../../core" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../runtime" } +sp-core = { version = "6.0.0", default-features = false, path = "../../core" } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } [features] diff --git a/primitives/consensus/slots/Cargo.toml b/primitives/consensus/slots/Cargo.toml index 5c8161ddcbe2..a334b10d6586 100644 --- a/primitives/consensus/slots/Cargo.toml +++ b/primitives/consensus/slots/Cargo.toml @@ -16,8 +16,8 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } serde = { version = "1.0", features = ["derive"], optional = true } -sp-arithmetic = { version = "4.0.0", default-features = false, path = "../../arithmetic" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../runtime" } +sp-arithmetic = { version = "5.0.0", default-features = false, path = "../../arithmetic" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../std" } sp-timestamp = { version = "4.0.0-dev", default-features = false, path = "../../timestamp" } diff --git a/primitives/consensus/vrf/Cargo.toml b/primitives/consensus/vrf/Cargo.toml index db453f62e801..80d2d1ddb09d 100644 --- a/primitives/consensus/vrf/Cargo.toml +++ b/primitives/consensus/vrf/Cargo.toml @@ -16,8 +16,8 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { version = "3.0.0", package = "parity-scale-codec", default-features = false } schnorrkel = { version = "0.9.1", features = ["preaudit_deprecated", "u64_backend"], default-features = false } sp-std = { version = "4.0.0", path = "../../std", default-features = false } -sp-core = { version = "5.0.0", path = "../../core", default-features = false } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../runtime" } +sp-core = { version = "6.0.0", path = "../../core", default-features = false } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../runtime" } [features] default = ["std"] diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index d1a813057958..70ae11cf543b 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-core" -version = "5.0.0" +version = "6.0.0" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" @@ -38,8 +38,8 @@ lazy_static = { version = "1.4.0", default-features = false, optional = true } parking_lot = { version = "0.12.0", optional = true } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-debug-derive = { version = "4.0.0", default-features = false, path = "../debug-derive" } -sp-storage = { version = "5.0.0", default-features = false, path = "../storage" } -sp-externalities = { version = "0.11.0", optional = true, path = "../externalities" } +sp-storage = { version = "6.0.0", default-features = false, path = "../storage" } +sp-externalities = { version = "0.12.0", optional = true, path = "../externalities" } parity-util-mem = { version = "0.11.0", default-features = false, features = ["primitive-types"] } futures = { version = "0.3.19", optional = true } dyn-clonable = { version = "0.9.0", optional = true } @@ -59,7 +59,7 @@ merlin = { version = "2.0", default-features = false, optional = true } secp256k1 = { version = "0.21.2", default-features = false, features = ["recovery", "global-context"], optional = true } ss58-registry = { version = "1.11.0", default-features = false } sp-core-hashing = { version = "4.0.0", path = "./hashing", default-features = false, optional = true } -sp-runtime-interface = { version = "5.0.0", default-features = false, path = "../runtime-interface" } +sp-runtime-interface = { version = "6.0.0", default-features = false, path = "../runtime-interface" } [dev-dependencies] sp-serializer = { version = "4.0.0-dev", path = "../serializer" } @@ -67,7 +67,7 @@ hex-literal = "0.3.4" rand = "0.7.2" criterion = "0.3.3" serde_json = "1.0" -sp-core-hashing-proc-macro = { version = "4.0.0-dev", path = "./hashing/proc-macro" } +sp-core-hashing-proc-macro = { version = "5.0.0", path = "./hashing/proc-macro" } [[bench]] name = "bench" diff --git a/primitives/core/hashing/proc-macro/Cargo.toml b/primitives/core/hashing/proc-macro/Cargo.toml index fea865ab9e10..b3dc155cd8bf 100644 --- a/primitives/core/hashing/proc-macro/Cargo.toml +++ b/primitives/core/hashing/proc-macro/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-core-hashing-proc-macro" -version = "4.0.0-dev" +version = "5.0.0" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" diff --git a/primitives/externalities/Cargo.toml b/primitives/externalities/Cargo.toml index f47f0ba494a7..4fc8619a9ba5 100644 --- a/primitives/externalities/Cargo.toml +++ b/primitives/externalities/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-externalities" -version = "0.11.0" +version = "0.12.0" license = "Apache-2.0" authors = ["Parity Technologies "] edition = "2021" @@ -14,7 +14,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-storage = { version = "5.0.0", path = "../storage", default-features = false } +sp-storage = { version = "6.0.0", path = "../storage", default-features = false } sp-std = { version = "4.0.0", path = "../std", default-features = false } environmental = { version = "1.1.3", default-features = false } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } diff --git a/primitives/finality-grandpa/Cargo.toml b/primitives/finality-grandpa/Cargo.toml index a40873ef4c2f..671168ef90b8 100644 --- a/primitives/finality-grandpa/Cargo.toml +++ b/primitives/finality-grandpa/Cargo.toml @@ -21,10 +21,10 @@ grandpa = { package = "finality-grandpa", version = "0.15.0", default-features = log = { version = "0.4.8", optional = true } serde = { version = "1.0.136", optional = true, features = ["derive"] } sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } -sp-application-crypto = { version = "5.0.0", default-features = false, path = "../application-crypto" } -sp-core = { version = "5.0.0", default-features = false, path = "../core" } -sp-keystore = { version = "0.11.0", default-features = false, path = "../keystore", optional = true } -sp-runtime = { version = "5.0.0", default-features = false, path = "../runtime" } +sp-application-crypto = { version = "6.0.0", default-features = false, path = "../application-crypto" } +sp-core = { version = "6.0.0", default-features = false, path = "../core" } +sp-keystore = { version = "0.12.0", default-features = false, path = "../keystore", optional = true } +sp-runtime = { version = "6.0.0", default-features = false, path = "../runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } [features] diff --git a/primitives/inherents/Cargo.toml b/primitives/inherents/Cargo.toml index 3bbe3caf5615..a90fb67e2385 100644 --- a/primitives/inherents/Cargo.toml +++ b/primitives/inherents/Cargo.toml @@ -16,8 +16,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-std = { version = "4.0.0", default-features = false, path = "../std" } -sp-core = { version = "5.0.0", default-features = false, path = "../core" } -sp-runtime = { version = "5.0.0", path = "../runtime", optional = true } +sp-core = { version = "6.0.0", default-features = false, path = "../core" } +sp-runtime = { version = "6.0.0", path = "../runtime", optional = true } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } thiserror = { version = "1.0.30", optional = true } impl-trait-for-tuples = "0.2.0" diff --git a/primitives/io/Cargo.toml b/primitives/io/Cargo.toml index b955d4c784da..c51e34b861b9 100644 --- a/primitives/io/Cargo.toml +++ b/primitives/io/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-io" -version = "5.0.0" +version = "6.0.0" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" @@ -17,16 +17,16 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } hash-db = { version = "0.15.2", default-features = false } -sp-core = { version = "5.0.0", default-features = false, path = "../core" } -sp-keystore = { version = "0.11.0", default-features = false, optional = true, path = "../keystore" } +sp-core = { version = "6.0.0", default-features = false, path = "../core" } +sp-keystore = { version = "0.12.0", default-features = false, optional = true, path = "../keystore" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } libsecp256k1 = { version = "0.7", optional = true } -sp-state-machine = { version = "0.11.0", optional = true, path = "../state-machine" } -sp-wasm-interface = { version = "5.0.0", path = "../wasm-interface", default-features = false } -sp-runtime-interface = { version = "5.0.0", default-features = false, path = "../runtime-interface" } -sp-trie = { version = "5.0.0", optional = true, path = "../trie" } -sp-externalities = { version = "0.11.0", optional = true, path = "../externalities" } -sp-tracing = { version = "4.0.0", default-features = false, path = "../tracing" } +sp-state-machine = { version = "0.12.0", optional = true, path = "../state-machine" } +sp-wasm-interface = { version = "6.0.0", path = "../wasm-interface", default-features = false } +sp-runtime-interface = { version = "6.0.0", default-features = false, path = "../runtime-interface" } +sp-trie = { version = "6.0.0", optional = true, path = "../trie" } +sp-externalities = { version = "0.12.0", optional = true, path = "../externalities" } +sp-tracing = { version = "5.0.0", default-features = false, path = "../tracing" } log = { version = "0.4.8", optional = true } futures = { version = "0.3.19", features = ["thread-pool"], optional = true } parking_lot = { version = "0.12.0", optional = true } diff --git a/primitives/keyring/Cargo.toml b/primitives/keyring/Cargo.toml index 1e5a234d3909..6186a51fef85 100644 --- a/primitives/keyring/Cargo.toml +++ b/primitives/keyring/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-keyring" -version = "5.0.0" +version = "6.0.0" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" @@ -14,7 +14,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-core = { version = "5.0.0", path = "../core" } -sp-runtime = { version = "5.0.0", path = "../runtime" } +sp-core = { version = "6.0.0", path = "../core" } +sp-runtime = { version = "6.0.0", path = "../runtime" } lazy_static = "1.4.0" strum = { version = "0.23.0", features = ["derive"] } diff --git a/primitives/keystore/Cargo.toml b/primitives/keystore/Cargo.toml index 341d2460765b..7b1d1dd4ebc4 100644 --- a/primitives/keystore/Cargo.toml +++ b/primitives/keystore/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-keystore" -version = "0.11.0" +version = "0.12.0" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" @@ -22,8 +22,8 @@ thiserror = "1.0" codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } schnorrkel = { version = "0.9.1", features = ["preaudit_deprecated", "u64_backend"], default-features = false } merlin = { version = "2.0", default-features = false } -sp-core = { version = "5.0.0", path = "../core" } -sp-externalities = { version = "0.11.0", path = "../externalities", default-features = false } +sp-core = { version = "6.0.0", path = "../core" } +sp-externalities = { version = "0.12.0", path = "../externalities", default-features = false } [dev-dependencies] rand = "0.7.2" diff --git a/primitives/npos-elections/Cargo.toml b/primitives/npos-elections/Cargo.toml index 6d70658c2701..b96b38695859 100644 --- a/primitives/npos-elections/Cargo.toml +++ b/primitives/npos-elections/Cargo.toml @@ -18,9 +18,9 @@ scale-info = { version = "2.0.0", default-features = false, features = ["derive" serde = { version = "1.0.136", optional = true, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-npos-elections-solution-type = { version = "4.0.0-dev", path = "./solution-type" } -sp-arithmetic = { version = "4.0.0", default-features = false, path = "../arithmetic" } -sp-core = { version = "5.0.0", default-features = false, path = "../core" } -sp-runtime = { version = "5.0.0", path = "../runtime", default-features = false } +sp-arithmetic = { version = "5.0.0", default-features = false, path = "../arithmetic" } +sp-core = { version = "6.0.0", default-features = false, path = "../core" } +sp-runtime = { version = "6.0.0", path = "../runtime", default-features = false } [dev-dependencies] substrate-test-utils = { version = "4.0.0-dev", path = "../../test-utils" } diff --git a/primitives/npos-elections/fuzzer/Cargo.toml b/primitives/npos-elections/fuzzer/Cargo.toml index 0c6c44ced7f4..6ad59d807fa5 100644 --- a/primitives/npos-elections/fuzzer/Cargo.toml +++ b/primitives/npos-elections/fuzzer/Cargo.toml @@ -21,7 +21,7 @@ rand = { version = "0.8", features = ["std", "small_rng"] } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-npos-elections = { version = "4.0.0-dev", path = ".." } -sp-runtime = { version = "5.0.0", path = "../../runtime" } +sp-runtime = { version = "6.0.0", path = "../../runtime" } [[bin]] name = "reduce" diff --git a/primitives/npos-elections/solution-type/Cargo.toml b/primitives/npos-elections/solution-type/Cargo.toml index 5b45bb246f39..fcd39437945f 100644 --- a/primitives/npos-elections/solution-type/Cargo.toml +++ b/primitives/npos-elections/solution-type/Cargo.toml @@ -23,7 +23,7 @@ proc-macro-crate = "1.1.0" [dev-dependencies] parity-scale-codec = "3.0.0" scale-info = "2.0.0" -sp-arithmetic = { path = "../../arithmetic", version = "4.0.0" } +sp-arithmetic = { path = "../../arithmetic", version = "5.0.0"} # used by generate_solution_type: sp-npos-elections = { path = "..", version = "4.0.0-dev" } trybuild = "1.0.53" diff --git a/primitives/offchain/Cargo.toml b/primitives/offchain/Cargo.toml index a96cd852bf24..ff647f0e7420 100644 --- a/primitives/offchain/Cargo.toml +++ b/primitives/offchain/Cargo.toml @@ -13,9 +13,9 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-core = { version = "5.0.0", default-features = false, path = "../core" } +sp-core = { version = "6.0.0", default-features = false, path = "../core" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../runtime" } [features] default = ["std"] diff --git a/primitives/rpc/Cargo.toml b/primitives/rpc/Cargo.toml index 240b74baf474..f2d048ef713e 100644 --- a/primitives/rpc/Cargo.toml +++ b/primitives/rpc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-rpc" -version = "5.0.0" +version = "6.0.0" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.136", features = ["derive"] } -sp-core = { version = "5.0.0", path = "../core" } +sp-core = { version = "6.0.0", path = "../core" } rustc-hash = "1.1.0" [dev-dependencies] diff --git a/primitives/runtime-interface/Cargo.toml b/primitives/runtime-interface/Cargo.toml index e227a7b63cde..883ea28e5e88 100644 --- a/primitives/runtime-interface/Cargo.toml +++ b/primitives/runtime-interface/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-runtime-interface" -version = "5.0.0" +version = "6.0.0" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" @@ -14,22 +14,22 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-wasm-interface = { version = "5.0.0", path = "../wasm-interface", default-features = false } +sp-wasm-interface = { version = "6.0.0", path = "../wasm-interface", default-features = false } sp-std = { version = "4.0.0", default-features = false, path = "../std" } -sp-tracing = { version = "4.0.0", default-features = false, path = "../tracing" } -sp-runtime-interface-proc-macro = { version = "4.0.0", path = "proc-macro" } -sp-externalities = { version = "0.11.0", optional = true, path = "../externalities" } +sp-tracing = { version = "5.0.0", default-features = false, path = "../tracing" } +sp-runtime-interface-proc-macro = { version = "5.0.0", path = "proc-macro" } +sp-externalities = { version = "0.12.0", optional = true, path = "../externalities" } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } static_assertions = "1.0.0" primitive-types = { version = "0.11.1", default-features = false } -sp-storage = { version = "5.0.0", default-features = false, path = "../storage" } +sp-storage = { version = "6.0.0", default-features = false, path = "../storage" } impl-trait-for-tuples = "0.2.1" [dev-dependencies] sp-runtime-interface-test-wasm = { version = "2.0.0", path = "test-wasm" } -sp-state-machine = { version = "0.11.0", path = "../state-machine" } -sp-core = { version = "5.0.0", path = "../core" } -sp-io = { version = "5.0.0", path = "../io" } +sp-state-machine = { version = "0.12.0", path = "../state-machine" } +sp-core = { version = "6.0.0", path = "../core" } +sp-io = { version = "6.0.0", path = "../io" } rustversion = "1.0.6" trybuild = "1.0.53" diff --git a/primitives/runtime-interface/proc-macro/Cargo.toml b/primitives/runtime-interface/proc-macro/Cargo.toml index f69c49843c1d..57e5448348d6 100644 --- a/primitives/runtime-interface/proc-macro/Cargo.toml +++ b/primitives/runtime-interface/proc-macro/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-runtime-interface-proc-macro" -version = "4.0.0" +version = "5.0.0" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" diff --git a/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml b/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml index 18046626f650..1b0c9f57e5c4 100644 --- a/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml +++ b/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml @@ -13,10 +13,10 @@ publish = false targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-runtime-interface = { version = "5.0.0", default-features = false, path = "../" } +sp-runtime-interface = { version = "6.0.0", default-features = false, path = "../" } sp-std = { version = "4.0.0", default-features = false, path = "../../std" } -sp-io = { version = "5.0.0", default-features = false, path = "../../io" } -sp-core = { version = "5.0.0", default-features = false, path = "../../core" } +sp-io = { version = "6.0.0", default-features = false, path = "../../io" } +sp-core = { version = "6.0.0", default-features = false, path = "../../core" } [build-dependencies] substrate-wasm-builder = { version = "5.0.0-dev", path = "../../../utils/wasm-builder" } diff --git a/primitives/runtime-interface/test-wasm/Cargo.toml b/primitives/runtime-interface/test-wasm/Cargo.toml index 9b6bdf39eb4c..4dfa0fd015d8 100644 --- a/primitives/runtime-interface/test-wasm/Cargo.toml +++ b/primitives/runtime-interface/test-wasm/Cargo.toml @@ -13,10 +13,10 @@ publish = false targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-runtime-interface = { version = "5.0.0", default-features = false, path = "../" } +sp-runtime-interface = { version = "6.0.0", default-features = false, path = "../" } sp-std = { version = "4.0.0", default-features = false, path = "../../std" } -sp-io = { version = "5.0.0", default-features = false, path = "../../io" } -sp-core = { version = "5.0.0", default-features = false, path = "../../core" } +sp-io = { version = "6.0.0", default-features = false, path = "../../io" } +sp-core = { version = "6.0.0", default-features = false, path = "../../core" } [build-dependencies] substrate-wasm-builder = { version = "5.0.0-dev", path = "../../../utils/wasm-builder" } diff --git a/primitives/runtime-interface/test/Cargo.toml b/primitives/runtime-interface/test/Cargo.toml index 107a8fcc7f2a..3b51088ea377 100644 --- a/primitives/runtime-interface/test/Cargo.toml +++ b/primitives/runtime-interface/test/Cargo.toml @@ -12,13 +12,13 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-runtime-interface = { version = "5.0.0", path = "../" } +sp-runtime-interface = { version = "6.0.0", path = "../" } sc-executor = { version = "0.10.0-dev", path = "../../../client/executor" } sc-executor-common = { version = "0.10.0-dev", path = "../../../client/executor/common" } sp-runtime-interface-test-wasm = { version = "2.0.0", path = "../test-wasm" } sp-runtime-interface-test-wasm-deprecated = { version = "2.0.0", path = "../test-wasm-deprecated" } -sp-state-machine = { version = "0.11.0", path = "../../state-machine" } -sp-runtime = { version = "5.0.0", path = "../../runtime" } -sp-io = { version = "5.0.0", path = "../../io" } +sp-state-machine = { version = "0.12.0", path = "../../state-machine" } +sp-runtime = { version = "6.0.0", path = "../../runtime" } +sp-io = { version = "6.0.0", path = "../../io" } tracing = "0.1.29" tracing-core = "0.1.17" diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 7c7e74b60053..91bf6d36b0a7 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-runtime" -version = "5.0.0" +version = "6.0.0" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" @@ -18,11 +18,11 @@ targets = ["x86_64-unknown-linux-gnu"] serde = { version = "1.0.136", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } -sp-core = { version = "5.0.0", default-features = false, path = "../core" } -sp-application-crypto = { version = "5.0.0", default-features = false, path = "../application-crypto" } -sp-arithmetic = { version = "4.0.0", default-features = false, path = "../arithmetic" } +sp-core = { version = "6.0.0", default-features = false, path = "../core" } +sp-application-crypto = { version = "6.0.0", default-features = false, path = "../application-crypto" } +sp-arithmetic = { version = "5.0.0", default-features = false, path = "../arithmetic" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } -sp-io = { version = "5.0.0", default-features = false, path = "../io" } +sp-io = { version = "6.0.0", default-features = false, path = "../io" } log = { version = "0.4.14", default-features = false } paste = "1.0" rand = { version = "0.7.2", optional = true } @@ -34,10 +34,10 @@ either = { version = "1.5", default-features = false } [dev-dependencies] serde_json = "1.0.74" rand = "0.7.2" -sp-state-machine = { version = "0.11.0", path = "../state-machine" } +sp-state-machine = { version = "0.12.0", path = "../state-machine" } sp-api = { version = "4.0.0-dev", path = "../api" } substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } -sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } +sp-tracing = { version = "5.0.0", path = "../../primitives/tracing" } zstd = "0.9" [features] diff --git a/primitives/sandbox/Cargo.toml b/primitives/sandbox/Cargo.toml index e04df06f2828..22d295f31370 100644 --- a/primitives/sandbox/Cargo.toml +++ b/primitives/sandbox/Cargo.toml @@ -20,10 +20,10 @@ wasmi = "0.9.0" [dependencies] wasmi = { version = "0.9.0", optional = true } -sp-core = { version = "5.0.0", default-features = false, path = "../core" } +sp-core = { version = "6.0.0", default-features = false, path = "../core" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } -sp-io = { version = "5.0.0", default-features = false, path = "../io" } -sp-wasm-interface = { version = "5.0.0", default-features = false, path = "../wasm-interface" } +sp-io = { version = "6.0.0", default-features = false, path = "../io" } +sp-wasm-interface = { version = "6.0.0", default-features = false, path = "../wasm-interface" } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } log = { version = "0.4", default-features = false } diff --git a/primitives/session/Cargo.toml b/primitives/session/Cargo.toml index abc4b60cfc32..9ffaa2cf3bdd 100644 --- a/primitives/session/Cargo.toml +++ b/primitives/session/Cargo.toml @@ -16,10 +16,10 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } -sp-core = { version = "5.0.0", default-features = false, path = "../core" } +sp-core = { version = "6.0.0", default-features = false, path = "../core" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../staking" } -sp-runtime = { version = "5.0.0", optional = true, path = "../runtime" } +sp-runtime = { version = "6.0.0", optional = true, path = "../runtime" } [features] default = [ "std" ] diff --git a/primitives/staking/Cargo.toml b/primitives/staking/Cargo.toml index 408dcb860596..2cb1ae0938a8 100644 --- a/primitives/staking/Cargo.toml +++ b/primitives/staking/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } -sp-runtime = { version = "5.0.0", default-features = false, path = "../runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } [features] diff --git a/primitives/state-machine/Cargo.toml b/primitives/state-machine/Cargo.toml index 9e0c0c026a23..2a6ab80133ee 100644 --- a/primitives/state-machine/Cargo.toml +++ b/primitives/state-machine/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-state-machine" -version = "0.11.0" +version = "0.12.0" authors = ["Parity Technologies "] description = "Substrate State Machine" edition = "2021" @@ -20,20 +20,20 @@ parking_lot = { version = "0.12.0", optional = true } hash-db = { version = "0.15.2", default-features = false } trie-db = { version = "0.23.1", default-features = false } trie-root = { version = "0.17.0", default-features = false } -sp-trie = { version = "5.0.0", path = "../trie", default-features = false } -sp-core = { version = "5.0.0", path = "../core", default-features = false } +sp-trie = { version = "6.0.0", path = "../trie", default-features = false } +sp-core = { version = "6.0.0", path = "../core", default-features = false } sp-panic-handler = { version = "4.0.0", path = "../panic-handler", optional = true } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } num-traits = { version = "0.2.8", default-features = false } rand = { version = "0.7.2", optional = true } -sp-externalities = { version = "0.11.0", path = "../externalities", default-features = false } +sp-externalities = { version = "0.12.0", path = "../externalities", default-features = false } smallvec = "1.8.0" sp-std = { version = "4.0.0", default-features = false, path = "../std" } tracing = { version = "0.1.29", optional = true } [dev-dependencies] hex-literal = "0.3.4" -sp-runtime = { version = "5.0.0", path = "../runtime" } +sp-runtime = { version = "6.0.0", path = "../runtime" } pretty_assertions = "1.0.0" rand = "0.7.2" diff --git a/primitives/storage/Cargo.toml b/primitives/storage/Cargo.toml index f6fe678c370b..a304bd660cc1 100644 --- a/primitives/storage/Cargo.toml +++ b/primitives/storage/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-storage" -version = "5.0.0" +version = "6.0.0" authors = ["Parity Technologies "] edition = "2021" description = "Storage related primitives" diff --git a/primitives/tasks/Cargo.toml b/primitives/tasks/Cargo.toml index 3cf4a583d60e..7f05afeaf0ce 100644 --- a/primitives/tasks/Cargo.toml +++ b/primitives/tasks/Cargo.toml @@ -15,10 +15,10 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] log = { version = "0.4.8", optional = true } -sp-core = { version = "5.0.0", default-features = false, path = "../core" } -sp-externalities = { version = "0.11.0", optional = true, path = "../externalities" } -sp-io = { version = "5.0.0", default-features = false, path = "../io" } -sp-runtime-interface = { version = "5.0.0", default-features = false, path = "../runtime-interface" } +sp-core = { version = "6.0.0", default-features = false, path = "../core" } +sp-externalities = { version = "0.12.0", optional = true, path = "../externalities" } +sp-io = { version = "6.0.0", default-features = false, path = "../io" } +sp-runtime-interface = { version = "6.0.0", default-features = false, path = "../runtime-interface" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } [dev-dependencies] diff --git a/primitives/test-primitives/Cargo.toml b/primitives/test-primitives/Cargo.toml index 2c13f0f8d64f..0d491ea217c6 100644 --- a/primitives/test-primitives/Cargo.toml +++ b/primitives/test-primitives/Cargo.toml @@ -12,11 +12,11 @@ publish = false targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-application-crypto = { version = "5.0.0", default-features = false, path = "../application-crypto" } +sp-application-crypto = { version = "6.0.0", default-features = false, path = "../application-crypto" } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -sp-core = { version = "5.0.0", default-features = false, path = "../core" } +sp-core = { version = "6.0.0", default-features = false, path = "../core" } serde = { version = "1.0.136", optional = true, features = ["derive"] } -sp-runtime = { version = "5.0.0", default-features = false, path = "../runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../runtime" } parity-util-mem = { version = "0.11.0", default-features = false, features = ["primitive-types"] } [features] diff --git a/primitives/timestamp/Cargo.toml b/primitives/timestamp/Cargo.toml index ec112ac5916f..176a4db5cb45 100644 --- a/primitives/timestamp/Cargo.toml +++ b/primitives/timestamp/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../runtime" } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../inherents" } thiserror = { version = "1.0.30", optional = true } diff --git a/primitives/tracing/Cargo.toml b/primitives/tracing/Cargo.toml index 3c3149a8b471..3f53cc2e6c5c 100644 --- a/primitives/tracing/Cargo.toml +++ b/primitives/tracing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-tracing" -version = "4.0.0" +version = "5.0.0" license = "Apache-2.0" authors = ["Parity Technologies "] edition = "2021" diff --git a/primitives/transaction-pool/Cargo.toml b/primitives/transaction-pool/Cargo.toml index c8f70bdce9de..544b149ce3a4 100644 --- a/primitives/transaction-pool/Cargo.toml +++ b/primitives/transaction-pool/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../runtime" } [features] default = [ "std" ] diff --git a/primitives/transaction-storage-proof/Cargo.toml b/primitives/transaction-storage-proof/Cargo.toml index ca285323f292..803ec67f571c 100644 --- a/primitives/transaction-storage-proof/Cargo.toml +++ b/primitives/transaction-storage-proof/Cargo.toml @@ -14,10 +14,10 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../inherents" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } -sp-trie = { version = "5.0.0", optional = true, path = "../trie" } -sp-core = { version = "5.0.0", path = "../core", optional = true } +sp-trie = { version = "6.0.0", optional = true, path = "../trie" } +sp-core = { version = "6.0.0", path = "../core", optional = true } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } log = { version = "0.4.8", optional = true } diff --git a/primitives/trie/Cargo.toml b/primitives/trie/Cargo.toml index 022dd606ba11..240c93233bfd 100644 --- a/primitives/trie/Cargo.toml +++ b/primitives/trie/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-trie" -version = "5.0.0" +version = "6.0.0" authors = ["Parity Technologies "] description = "Patricia trie stuff using a parity-scale-codec node format" repository = "https://github.com/paritytech/substrate/" @@ -25,14 +25,14 @@ hash-db = { version = "0.15.2", default-features = false } trie-db = { version = "0.23.1", default-features = false } trie-root = { version = "0.17.0", default-features = false } memory-db = { version = "0.29.0", default-features = false } -sp-core = { version = "5.0.0", default-features = false, path = "../core" } +sp-core = { version = "6.0.0", default-features = false, path = "../core" } [dev-dependencies] trie-bench = "0.30.0" trie-standardmap = "0.15.2" criterion = "0.3.3" hex-literal = "0.3.4" -sp-runtime = { version = "5.0.0", path = "../runtime" } +sp-runtime = { version = "6.0.0", path = "../runtime" } [features] default = ["std"] diff --git a/primitives/version/Cargo.toml b/primitives/version/Cargo.toml index 590bf081eb06..8518dfffa5db 100644 --- a/primitives/version/Cargo.toml +++ b/primitives/version/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-version" -version = "4.0.0-dev" +version = "5.0.0" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" @@ -19,10 +19,10 @@ serde = { version = "1.0.136", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../std" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../runtime" } sp-version-proc-macro = { version = "4.0.0-dev", default-features = false, path = "proc-macro" } parity-wasm = { version = "0.42.2", optional = true } -sp-core-hashing-proc-macro = { version = "4.0.0-dev", path = "../core/hashing/proc-macro" } +sp-core-hashing-proc-macro = { version = "5.0.0", path = "../core/hashing/proc-macro" } thiserror = { version = "1.0.30", optional = true } [features] diff --git a/primitives/version/proc-macro/Cargo.toml b/primitives/version/proc-macro/Cargo.toml index c8f59f4fca25..e54012a516f2 100644 --- a/primitives/version/proc-macro/Cargo.toml +++ b/primitives/version/proc-macro/Cargo.toml @@ -22,4 +22,4 @@ proc-macro2 = "1.0.36" codec = { package = "parity-scale-codec", version = "3.0.0", features = [ "derive" ] } [dev-dependencies] -sp-version = { version = "4.0.0-dev", path = ".." } +sp-version = { version = "5.0.0", path = ".." } diff --git a/primitives/wasm-interface/Cargo.toml b/primitives/wasm-interface/Cargo.toml index acf22f189b87..fa6c5ede1854 100644 --- a/primitives/wasm-interface/Cargo.toml +++ b/primitives/wasm-interface/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-wasm-interface" -version = "5.0.0" +version = "6.0.0" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" diff --git a/test-utils/client/Cargo.toml b/test-utils/client/Cargo.toml index 6deaddd9068f..f3299d800a6f 100644 --- a/test-utils/client/Cargo.toml +++ b/test-utils/client/Cargo.toml @@ -29,9 +29,9 @@ sc-service = { version = "0.10.0-dev", default-features = false, features = [ ], path = "../../client/service" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } -sp-core = { version = "5.0.0", path = "../../primitives/core" } -sp-keystore = { version = "0.11.0", path = "../../primitives/keystore" } -sp-keyring = { version = "5.0.0", path = "../../primitives/keyring" } -sp-runtime = { version = "5.0.0", path = "../../primitives/runtime" } -sp-state-machine = { version = "0.11.0", path = "../../primitives/state-machine" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } +sp-keystore = { version = "0.12.0", path = "../../primitives/keystore" } +sp-keyring = { version = "6.0.0", path = "../../primitives/keyring" } +sp-runtime = { version = "6.0.0", path = "../../primitives/runtime" } +sp-state-machine = { version = "0.12.0", path = "../../primitives/state-machine" } async-trait = "0.1.50" diff --git a/test-utils/runtime/Cargo.toml b/test-utils/runtime/Cargo.toml index 79d43bea8520..9bf66a64db42 100644 --- a/test-utils/runtime/Cargo.toml +++ b/test-utils/runtime/Cargo.toml @@ -13,37 +13,37 @@ publish = false targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-application-crypto = { version = "5.0.0", default-features = false, path = "../../primitives/application-crypto" } +sp-application-crypto = { version = "6.0.0", default-features = false, path = "../../primitives/application-crypto" } sp-consensus-aura = { version = "0.10.0-dev", default-features = false, path = "../../primitives/consensus/aura" } sp-consensus-babe = { version = "0.10.0-dev", default-features = false, path = "../../primitives/consensus/babe" } sp-block-builder = { version = "4.0.0-dev", default-features = false, path = "../../primitives/block-builder" } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../primitives/inherents" } -sp-keyring = { version = "5.0.0", optional = true, path = "../../primitives/keyring" } +sp-keyring = { version = "6.0.0", optional = true, path = "../../primitives/keyring" } memory-db = { version = "0.29.0", default-features = false } sp-offchain = { version = "4.0.0-dev", default-features = false, path = "../../primitives/offchain" } -sp-core = { version = "5.0.0", default-features = false, path = "../../primitives/core" } +sp-core = { version = "6.0.0", default-features = false, path = "../../primitives/core" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime-interface = { version = "5.0.0", default-features = false, path = "../../primitives/runtime-interface" } -sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime-interface = { version = "6.0.0", default-features = false, path = "../../primitives/runtime-interface" } +sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../../frame/support" } -sp-version = { version = "4.0.0-dev", default-features = false, path = "../../primitives/version" } +sp-version = { version = "5.0.0", default-features = false, path = "../../primitives/version" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../primitives/session" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../primitives/api" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } pallet-babe = { version = "4.0.0-dev", default-features = false, path = "../../frame/babe" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../frame/system" } frame-system-rpc-runtime-api = { version = "4.0.0-dev", default-features = false, path = "../../frame/system/rpc/runtime-api" } pallet-timestamp = { version = "4.0.0-dev", default-features = false, path = "../../frame/timestamp" } sp-finality-grandpa = { version = "4.0.0-dev", default-features = false, path = "../../primitives/finality-grandpa" } -sp-trie = { version = "5.0.0", default-features = false, path = "../../primitives/trie" } +sp-trie = { version = "6.0.0", default-features = false, path = "../../primitives/trie" } sp-transaction-pool = { version = "4.0.0-dev", default-features = false, path = "../../primitives/transaction-pool" } trie-db = { version = "0.23.1", default-features = false } parity-util-mem = { version = "0.11.0", default-features = false, features = ["primitive-types"] } sc-service = { version = "0.10.0-dev", default-features = false, optional = true, features = ["test-helpers"], path = "../../client/service" } -sp-state-machine = { version = "0.11.0", default-features = false, path = "../../primitives/state-machine" } -sp-externalities = { version = "0.11.0", default-features = false, path = "../../primitives/externalities" } +sp-state-machine = { version = "0.12.0", default-features = false, path = "../../primitives/state-machine" } +sp-externalities = { version = "0.12.0", default-features = false, path = "../../primitives/externalities" } # 3rd party cfg-if = "1.0" diff --git a/test-utils/runtime/client/Cargo.toml b/test-utils/runtime/client/Cargo.toml index 552a0581d79e..642d754868f7 100644 --- a/test-utils/runtime/client/Cargo.toml +++ b/test-utils/runtime/client/Cargo.toml @@ -16,9 +16,9 @@ sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/c sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/common" } sc-block-builder = { version = "0.10.0-dev", path = "../../../client/block-builder" } substrate-test-client = { version = "2.0.0", path = "../../client" } -sp-core = { version = "5.0.0", path = "../../../primitives/core" } +sp-core = { version = "6.0.0", path = "../../../primitives/core" } substrate-test-runtime = { version = "2.0.0", path = "../../runtime" } -sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } +sp-runtime = { version = "6.0.0", path = "../../../primitives/runtime" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } codec = { package = "parity-scale-codec", version = "3.0.0" } diff --git a/test-utils/runtime/transaction-pool/Cargo.toml b/test-utils/runtime/transaction-pool/Cargo.toml index b936e6d9cb35..8bc75c9d4c05 100644 --- a/test-utils/runtime/transaction-pool/Cargo.toml +++ b/test-utils/runtime/transaction-pool/Cargo.toml @@ -16,7 +16,7 @@ substrate-test-runtime-client = { version = "2.0.0", path = "../client" } parking_lot = "0.12.0" codec = { package = "parity-scale-codec", version = "3.0.0" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } +sp-runtime = { version = "6.0.0", path = "../../../primitives/runtime" } sc-transaction-pool = { version = "4.0.0-dev", path = "../../../client/transaction-pool" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../../../client/transaction-pool/api" } futures = "0.3.19" diff --git a/utils/frame/benchmarking-cli/Cargo.toml b/utils/frame/benchmarking-cli/Cargo.toml index dc6c5eb22165..20122c427936 100644 --- a/utils/frame/benchmarking-cli/Cargo.toml +++ b/utils/frame/benchmarking-cli/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] frame-benchmarking = { version = "4.0.0-dev", path = "../../../frame/benchmarking" } frame-support = { version = "4.0.0-dev", path = "../../../frame/support" } -sp-core = { version = "5.0.0", path = "../../../primitives/core" } +sp-core = { version = "6.0.0", path = "../../../primitives/core" } sc-service = { version = "0.10.0-dev", default-features = false, path = "../../../client/service" } sc-client-api = { version = "4.0.0-dev", path = "../../../client/api" } sc-cli = { version = "0.10.0-dev", path = "../../../client/cli" } @@ -23,15 +23,15 @@ sc-client-db = { version = "0.10.0-dev", path = "../../../client/db" } sc-executor = { version = "0.10.0-dev", path = "../../../client/executor" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } -sp-externalities = { version = "0.11.0", path = "../../../primitives/externalities" } +sp-externalities = { version = "0.12.0", path = "../../../primitives/externalities" } sp-database = { version = "4.0.0-dev", path = "../../../primitives/database" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-keystore = { version = "0.11.0", path = "../../../primitives/keystore" } -sp-storage = { version = "5.0.0", path = "../../../primitives/storage" } -sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } +sp-keystore = { version = "0.12.0", path = "../../../primitives/keystore" } +sp-storage = { version = "6.0.0", path = "../../../primitives/storage" } +sp-runtime = { version = "6.0.0", path = "../../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } -sp-state-machine = { version = "0.11.0", path = "../../../primitives/state-machine" } -sp-trie = { version = "5.0.0", path = "../../../primitives/trie" } +sp-state-machine = { version = "0.12.0", path = "../../../primitives/state-machine" } +sp-trie = { version = "6.0.0", path = "../../../primitives/trie" } codec = { version = "3.0.0", package = "parity-scale-codec" } clap = { version = "3.0", features = ["derive"] } chrono = "0.4" diff --git a/utils/frame/frame-utilities-cli/Cargo.toml b/utils/frame/frame-utilities-cli/Cargo.toml index 50a00db1d4d3..bc673105b78b 100644 --- a/utils/frame/frame-utilities-cli/Cargo.toml +++ b/utils/frame/frame-utilities-cli/Cargo.toml @@ -13,9 +13,9 @@ readme = "README.md" [dependencies] clap = { version = "3.0", features = ["derive"] } -sp-core = { version = "5.0.0", path = "../../../primitives/core" } +sp-core = { version = "6.0.0", path = "../../../primitives/core" } sc-cli = { version = "0.10.0-dev", path = "../../../client/cli" } -sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } +sp-runtime = { version = "6.0.0", path = "../../../primitives/runtime" } frame-system = { version = "4.0.0-dev", path = "../../../frame/system" } frame-support = { version = "4.0.0-dev", path = "../../../frame/support" } diff --git a/utils/frame/generate-bags/Cargo.toml b/utils/frame/generate-bags/Cargo.toml index 5bda705a581a..7c7fdea056b2 100644 --- a/utils/frame/generate-bags/Cargo.toml +++ b/utils/frame/generate-bags/Cargo.toml @@ -17,7 +17,7 @@ frame-system = { version = "4.0.0-dev", path = "../../../frame/system" } pallet-staking = { version = "4.0.0-dev", path = "../../../frame/staking" } # primitives -sp-io = { version = "5.0.0", path = "../../../primitives/io" } +sp-io = { version = "6.0.0", path = "../../../primitives/io" } # third party chrono = { version = "0.4.19" } diff --git a/utils/frame/remote-externalities/Cargo.toml b/utils/frame/remote-externalities/Cargo.toml index ec05b7133412..d5042444119d 100644 --- a/utils/frame/remote-externalities/Cargo.toml +++ b/utils/frame/remote-externalities/Cargo.toml @@ -22,10 +22,10 @@ codec = { package = "parity-scale-codec", version = "3.0.0" } serde_json = "1.0" serde = "1.0.136" -sp-io = { version = "5.0.0", path = "../../../primitives/io" } -sp-core = { version = "5.0.0", path = "../../../primitives/core" } -sp-runtime = { version = "5.0.0", path = "../../../primitives/runtime" } -sp-version = { version = "4.0.0-dev", path = "../../../primitives/version" } +sp-io = { version = "6.0.0", path = "../../../primitives/io" } +sp-core = { version = "6.0.0", path = "../../../primitives/core" } +sp-runtime = { version = "6.0.0", path = "../../../primitives/runtime" } +sp-version = { version = "5.0.0", path = "../../../primitives/version" } [dev-dependencies] tokio = { version = "1.15", features = ["macros", "rt-multi-thread"] } diff --git a/utils/frame/rpc/support/Cargo.toml b/utils/frame/rpc/support/Cargo.toml index 645e33f4b21a..f1cf00153f3b 100644 --- a/utils/frame/rpc/support/Cargo.toml +++ b/utils/frame/rpc/support/Cargo.toml @@ -20,7 +20,7 @@ jsonrpc-client-transports = { version = "18.0.0", features = ["http"] } codec = { package = "parity-scale-codec", version = "3.0.0" } serde = "1" frame-support = { version = "4.0.0-dev", path = "../../../../frame/support" } -sp-storage = { version = "5.0.0", path = "../../../../primitives/storage" } +sp-storage = { version = "6.0.0", path = "../../../../primitives/storage" } sc-rpc-api = { version = "0.10.0-dev", path = "../../../../client/rpc-api" } [dev-dependencies] diff --git a/utils/frame/rpc/system/Cargo.toml b/utils/frame/rpc/system/Cargo.toml index 79794d779252..1015760efee6 100644 --- a/utils/frame/rpc/system/Cargo.toml +++ b/utils/frame/rpc/system/Cargo.toml @@ -20,10 +20,10 @@ jsonrpc-core = "18.0.0" jsonrpc-core-client = "18.0.0" jsonrpc-derive = "18.0.0" log = "0.4.8" -sp-runtime = { version = "5.0.0", path = "../../../../primitives/runtime" } +sp-runtime = { version = "6.0.0", path = "../../../../primitives/runtime" } sp-api = { version = "4.0.0-dev", path = "../../../../primitives/api" } frame-system-rpc-runtime-api = { version = "4.0.0-dev", path = "../../../../frame/system/rpc/runtime-api" } -sp-core = { version = "5.0.0", path = "../../../../primitives/core" } +sp-core = { version = "6.0.0", path = "../../../../primitives/core" } sp-blockchain = { version = "4.0.0-dev", path = "../../../../primitives/blockchain" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../../../../client/transaction-pool/api" } sp-block-builder = { version = "4.0.0-dev", path = "../../../../primitives/block-builder" } @@ -31,5 +31,5 @@ sc-rpc-api = { version = "0.10.0-dev", path = "../../../../client/rpc-api" } [dev-dependencies] substrate-test-runtime-client = { version = "2.0.0", path = "../../../../test-utils/runtime/client" } -sp-tracing = { version = "4.0.0", path = "../../../../primitives/tracing" } +sp-tracing = { version = "5.0.0", path = "../../../../primitives/tracing" } sc-transaction-pool = { version = "4.0.0-dev", path = "../../../../client/transaction-pool" } diff --git a/utils/frame/try-runtime/cli/Cargo.toml b/utils/frame/try-runtime/cli/Cargo.toml index 27129f38acc7..04b6d336f740 100644 --- a/utils/frame/try-runtime/cli/Cargo.toml +++ b/utils/frame/try-runtime/cli/Cargo.toml @@ -23,13 +23,13 @@ sc-service = { version = "0.10.0-dev", default-features = false, path = "../../. sc-cli = { version = "0.10.0-dev", path = "../../../../client/cli" } sc-executor = { version = "0.10.0-dev", path = "../../../../client/executor" } sc-chain-spec = { version = "4.0.0-dev", path = "../../../../client/chain-spec" } -sp-state-machine = { version = "0.11.0", path = "../../../../primitives/state-machine" } -sp-runtime = { version = "5.0.0", path = "../../../../primitives/runtime" } -sp-core = { version = "5.0.0", path = "../../../../primitives/core" } -sp-io = { version = "5.0.0", path = "../../../../primitives/io" } -sp-keystore = { version = "0.11.0", path = "../../../../primitives/keystore" } -sp-externalities = { version = "0.11.0", path = "../../../../primitives/externalities" } -sp-version = { version = "4.0.0-dev", path = "../../../../primitives/version" } +sp-state-machine = { version = "0.12.0", path = "../../../../primitives/state-machine" } +sp-runtime = { version = "6.0.0", path = "../../../../primitives/runtime" } +sp-core = { version = "6.0.0", path = "../../../../primitives/core" } +sp-io = { version = "6.0.0", path = "../../../../primitives/io" } +sp-keystore = { version = "0.12.0", path = "../../../../primitives/keystore" } +sp-externalities = { version = "0.12.0", path = "../../../../primitives/externalities" } +sp-version = { version = "5.0.0", path = "../../../../primitives/version" } remote-externalities = { version = "0.10.0-dev", path = "../../remote-externalities" } jsonrpsee = { version = "0.4.1", default-features = false, features = ["ws-client"] } From e75de5f0ed73e87f626d69d1479f3abee1aa6892 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 1 Mar 2022 14:41:07 +0000 Subject: [PATCH 546/695] Update new whitelist pallet to new primitive versions (#10953) --- frame/whitelist/Cargo.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frame/whitelist/Cargo.toml b/frame/whitelist/Cargo.toml index 057e7fd71f30..6bc43ff96178 100644 --- a/frame/whitelist/Cargo.toml +++ b/frame/whitelist/Cargo.toml @@ -17,14 +17,14 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = scale-info = { version = "2.0", default-features = false, features = ["derive"] } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../primitives/api" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "5.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -sp-core = { version = "5.0.0", path = "../../primitives/core" } +sp-core = { version = "6.0.0", path = "../../primitives/core" } pallet-preimage = { version = "4.0.0-dev", path = "../preimage/" } pallet-balances = { version = "4.0.0-dev", path = "../balances/" } From 0063f74287d29ff347121fcd23a00f1d8b1e4a57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Tue, 1 Mar 2022 23:33:47 +0100 Subject: [PATCH 547/695] sp-trie: Switch to thiserror and some other small cleanups (#10954) * sp-trie: Switch to thiserror and some other small cleanups * Add some extra method for converting a compact proof to a memory db --- Cargo.lock | 1 + primitives/trie/Cargo.toml | 2 + primitives/trie/src/error.rs | 34 ++--------- primitives/trie/src/node_codec.rs | 10 ++-- primitives/trie/src/storage_proof.rs | 68 +++++++++++++--------- primitives/trie/src/trie_codec.rs | 85 +++++++--------------------- 6 files changed, 74 insertions(+), 126 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 59ff43598fae..5c1b6ed88fb4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10362,6 +10362,7 @@ dependencies = [ "sp-core", "sp-runtime", "sp-std", + "thiserror", "trie-bench", "trie-db", "trie-root", diff --git a/primitives/trie/Cargo.toml b/primitives/trie/Cargo.toml index 240c93233bfd..dfe3150194a3 100644 --- a/primitives/trie/Cargo.toml +++ b/primitives/trie/Cargo.toml @@ -26,6 +26,7 @@ trie-db = { version = "0.23.1", default-features = false } trie-root = { version = "0.17.0", default-features = false } memory-db = { version = "0.29.0", default-features = false } sp-core = { version = "6.0.0", default-features = false, path = "../core" } +thiserror = { version = "1.0.30", optional = true } [dev-dependencies] trie-bench = "0.30.0" @@ -45,5 +46,6 @@ std = [ "trie-db/std", "trie-root/std", "sp-core/std", + "thiserror", ] memory-tracker = [] diff --git a/primitives/trie/src/error.rs b/primitives/trie/src/error.rs index b43412ebc7dc..e0b3642b6db7 100644 --- a/primitives/trie/src/error.rs +++ b/primitives/trie/src/error.rs @@ -15,18 +15,14 @@ // See the License for the specific language governing permissions and // limitations under the License. -#[cfg(feature = "std")] -use std::error::Error as StdError; -#[cfg(feature = "std")] -use std::fmt; - -#[derive(Debug, PartialEq, Eq, Clone)] /// Error for trie node decoding. +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "std", derive(thiserror::Error))] pub enum Error { - /// Bad format. + #[cfg_attr(feature = "std", error("Bad format"))] BadFormat, - /// Decoding error. - Decode(codec::Error), + #[cfg_attr(feature = "std", error("Decoding failed: {0}"))] + Decode(#[cfg_attr(feature = "std", source)] codec::Error), } impl From for Error { @@ -34,23 +30,3 @@ impl From for Error { Error::Decode(x) } } - -#[cfg(feature = "std")] -impl StdError for Error { - fn description(&self) -> &str { - match self { - Error::BadFormat => "Bad format error", - Error::Decode(_) => "Decoding error", - } - } -} - -#[cfg(feature = "std")] -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - Error::Decode(e) => write!(f, "Decode error: {}", e), - Error::BadFormat => write!(f, "Bad format"), - } - } -} diff --git a/primitives/trie/src/node_codec.rs b/primitives/trie/src/node_codec.rs index 4aaed2ec7e4e..bd0ba27483e6 100644 --- a/primitives/trie/src/node_codec.rs +++ b/primitives/trie/src/node_codec.rs @@ -23,7 +23,7 @@ use codec::{Compact, Decode, Encode, Input}; use hash_db::Hasher; use sp_std::{borrow::Borrow, marker::PhantomData, ops::Range, vec::Vec}; use trie_db::{ - self, nibble_ops, + nibble_ops, node::{NibbleSlicePlan, NodeHandlePlan, NodePlan, Value, ValuePlan}, ChildReference, NodeCodec as NodeCodecT, Partial, }; @@ -54,9 +54,7 @@ impl<'a> ByteSliceInput<'a> { impl<'a> Input for ByteSliceInput<'a> { fn remaining_len(&mut self) -> Result, codec::Error> { - let remaining = - if self.offset <= self.data.len() { Some(self.data.len() - self.offset) } else { None }; - Ok(remaining) + Ok(Some(self.data.len().saturating_sub(self.offset))) } fn read(&mut self, into: &mut [u8]) -> Result<(), codec::Error> { @@ -76,7 +74,9 @@ impl<'a> Input for ByteSliceInput<'a> { } } -/// Concrete implementation of a `NodeCodec` with Parity Codec encoding, generic over the `Hasher` +/// Concrete implementation of a [`NodeCodecT`] with SCALE encoding. +/// +/// It is generic over `H` the [`Hasher`]. #[derive(Default, Clone)] pub struct NodeCodec(PhantomData); diff --git a/primitives/trie/src/storage_proof.rs b/primitives/trie/src/storage_proof.rs index 8caae06d390c..79da009ae151 100644 --- a/primitives/trie/src/storage_proof.rs +++ b/primitives/trie/src/storage_proof.rs @@ -35,12 +35,6 @@ pub struct StorageProof { trie_nodes: Vec>, } -/// Storage proof in compact form. -#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode, TypeInfo)] -pub struct CompactProof { - pub encoded_nodes: Vec>, -} - impl StorageProof { /// Constructs a storage proof from a subset of encoded trie nodes in a storage backend. pub fn new(trie_nodes: Vec>) -> Self { @@ -71,7 +65,7 @@ impl StorageProof { self.trie_nodes } - /// Creates a `MemoryDB` from `Self`. + /// Creates a [`MemoryDB`](crate::MemoryDB) from `Self`. pub fn into_memory_db(self) -> crate::MemoryDB { self.into() } @@ -79,10 +73,7 @@ impl StorageProof { /// Merges multiple storage proofs covering potentially different sets of keys into one proof /// covering all keys. The merged proof output may be smaller than the aggregate size of the /// input proofs due to deduplication of trie nodes. - pub fn merge(proofs: I) -> Self - where - I: IntoIterator, - { + pub fn merge(proofs: impl IntoIterator) -> Self { let trie_nodes = proofs .into_iter() .flat_map(|proof| proof.iter_nodes()) @@ -93,12 +84,11 @@ impl StorageProof { Self { trie_nodes } } - /// Encode as a compact proof with default - /// trie layout. + /// Encode as a compact proof with default trie layout. pub fn into_compact_proof( self, root: H::Out, - ) -> Result>> { + ) -> Result> { crate::encode_compact::>(self, root) } @@ -114,6 +104,22 @@ impl StorageProof { } } +impl From for crate::MemoryDB { + fn from(proof: StorageProof) -> Self { + let mut db = crate::MemoryDB::default(); + proof.iter_nodes().for_each(|n| { + db.insert(crate::EMPTY_PREFIX, &n); + }); + db + } +} + +/// Storage proof in compact form. +#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode, TypeInfo)] +pub struct CompactProof { + pub encoded_nodes: Vec>, +} + impl CompactProof { /// Return an iterator on the compact encoded nodes. pub fn iter_compact_encoded_nodes(&self) -> impl Iterator { @@ -121,13 +127,10 @@ impl CompactProof { } /// Decode to a full storage_proof. - /// - /// Method use a temporary `HashDB`, and `sp_trie::decode_compact` - /// is often better. pub fn to_storage_proof( &self, expected_root: Option<&H::Out>, - ) -> Result<(StorageProof, H::Out), crate::CompactProofError>> { + ) -> Result<(StorageProof, H::Out), crate::CompactProofError> { let mut db = crate::MemoryDB::::new(&[]); let root = crate::decode_compact::, _, _>( &mut db, @@ -144,6 +147,25 @@ impl CompactProof { root, )) } + + /// Convert self into a [`MemoryDB`](crate::MemoryDB). + /// + /// `expected_root` is the expected root of this compact proof. + /// + /// Returns the memory db and the root of the trie. + pub fn to_memory_db( + &self, + expected_root: Option<&H::Out>, + ) -> Result<(crate::MemoryDB, H::Out), crate::CompactProofError> { + let mut db = crate::MemoryDB::::new(&[]); + let root = crate::decode_compact::, _, _>( + &mut db, + self.iter_compact_encoded_nodes(), + expected_root, + )?; + + Ok((db, root)) + } } /// An iterator over trie nodes constructed from a storage proof. The nodes are not guaranteed to @@ -165,13 +187,3 @@ impl Iterator for StorageProofNodeIterator { self.inner.next() } } - -impl From for crate::MemoryDB { - fn from(proof: StorageProof) -> Self { - let mut db = crate::MemoryDB::default(); - for item in proof.iter_nodes() { - db.insert(crate::EMPTY_PREFIX, &item); - } - db - } -} diff --git a/primitives/trie/src/trie_codec.rs b/primitives/trie/src/trie_codec.rs index 62edc82e4c54..a7f292271565 100644 --- a/primitives/trie/src/trie_codec.rs +++ b/primitives/trie/src/trie_codec.rs @@ -20,80 +20,34 @@ //! This uses compact proof from trie crate and extends //! it to substrate specific layout and child trie system. -use crate::{ - CompactProof, HashDBT, StorageProof, TrieConfiguration, TrieError, TrieHash, EMPTY_PREFIX, -}; +use crate::{CompactProof, HashDBT, StorageProof, TrieConfiguration, TrieHash, EMPTY_PREFIX}; use sp_std::{boxed::Box, vec::Vec}; -#[cfg(feature = "std")] -use std::error::Error as StdError; -#[cfg(feature = "std")] -use std::fmt; -use trie_db::Trie; +use trie_db::{CError, Trie}; /// Error for trie node decoding. -pub enum Error { - /// Verification failed due to root mismatch. - RootMismatch(TrieHash, TrieHash), - /// Missing nodes in proof. +#[derive(Debug)] +#[cfg_attr(feature = "std", derive(thiserror::Error))] +pub enum Error { + #[cfg_attr(feature = "std", error("Invalid root {0:x?}, expected {1:x?}"))] + RootMismatch(H, H), + #[cfg_attr(feature = "std", error("Missing nodes in the proof"))] IncompleteProof, - /// Compact node is not needed. + #[cfg_attr(feature = "std", error("Child node content with no root in proof"))] ExtraneousChildNode, - /// Child content with root not in proof. - ExtraneousChildProof(TrieHash), - /// Bad child trie root. + #[cfg_attr(feature = "std", error("Proof of child trie {0:x?} not in parent proof"))] + ExtraneousChildProof(H), + #[cfg_attr(feature = "std", error("Invalid root {0:x?}, expected {1:x?}"))] InvalidChildRoot(Vec, Vec), - /// Errors from trie crate. - TrieError(Box>), + #[cfg_attr(feature = "std", error("Trie error: {0:?}"))] + TrieError(Box>), } -impl From>> for Error { - fn from(error: Box>) -> Self { +impl From>> for Error { + fn from(error: Box>) -> Self { Error::TrieError(error) } } -#[cfg(feature = "std")] -impl StdError for Error { - fn description(&self) -> &str { - match self { - Error::InvalidChildRoot(..) => "Invalid child root error", - Error::TrieError(..) => "Trie db error", - Error::RootMismatch(..) => "Trie db error", - Error::IncompleteProof => "Incomplete proof", - Error::ExtraneousChildNode => "Extraneous child node", - Error::ExtraneousChildProof(..) => "Extraneous child proof", - } - } -} - -#[cfg(feature = "std")] -impl fmt::Debug for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - ::fmt(&self, f) - } -} - -#[cfg(feature = "std")] -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - Error::InvalidChildRoot(k, v) => write!(f, "InvalidChildRoot at {:x?}: {:x?}", k, v), - Error::TrieError(e) => write!(f, "Trie error: {}", e), - Error::IncompleteProof => write!(f, "Incomplete proof"), - Error::ExtraneousChildNode => write!(f, "Child node content with no root in proof"), - Error::ExtraneousChildProof(root) => { - write!(f, "Proof of child trie {:x?} not in parent proof", root.as_ref()) - }, - Error::RootMismatch(root, expected) => write!( - f, - "Verification error, root is {:x?}, expected: {:x?}", - root.as_ref(), - expected.as_ref(), - ), - } - } -} - /// Decode a compact proof. /// /// Takes as input a destination `db` for decoded node and `encoded` @@ -105,7 +59,7 @@ pub fn decode_compact<'a, L, DB, I>( db: &mut DB, encoded: I, expected_root: Option<&TrieHash>, -) -> Result, Error> +) -> Result, Error, CError>> where L: TrieConfiguration, DB: HashDBT + hash_db::HashDBRef, @@ -195,7 +149,10 @@ where /// Then parse all child trie root and compress main trie content first /// then all child trie contents. /// Child trie are ordered by the order of their roots in the top trie. -pub fn encode_compact(proof: StorageProof, root: TrieHash) -> Result> +pub fn encode_compact( + proof: StorageProof, + root: TrieHash, +) -> Result, CError>> where L: TrieConfiguration, { From c6aa3209d6277b853f5eb15d74fb9812024ef23c Mon Sep 17 00:00:00 2001 From: Zeke Mostov Date: Tue, 1 Mar 2022 15:31:13 -0800 Subject: [PATCH 548/695] Only maintain at most 1 `UnlockChunk` per era (#10670) * Only maintain at most 1 `UnlockChunk` per era * Bound `unlocking` * Run cargo +nightly-2021-10-29 fmt * Make benchmarks stuff compile * Update frame/staking/src/lib.rs Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> * Remove DerefMut; Implement neccesary methods directly * Doc comments for new BoundedVec methods * Fix benchmarks * wip bonded_vec macro * Correct rust doc * Apply suggestions from code review Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> * Update staking::Config impls * Add MaxUnlockingChunks to more places * Use defensive saturating add * FMT Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> --- bin/node/runtime/src/lib.rs | 1 + frame/babe/src/mock.rs | 1 + frame/grandpa/src/mock.rs | 1 + frame/offences/benchmarking/src/mock.rs | 1 + frame/session/benchmarking/src/mock.rs | 1 + frame/staking/src/benchmarking.rs | 10 +- frame/staking/src/lib.rs | 22 +++- frame/staking/src/mock.rs | 1 + frame/staking/src/pallet/impls.rs | 8 +- frame/staking/src/pallet/mod.rs | 40 +++++-- frame/staking/src/tests.rs | 141 ++++++++++++----------- frame/support/src/storage/bounded_vec.rs | 15 ++- 12 files changed, 147 insertions(+), 95 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 9ff19760c775..0b0c033ae851 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -558,6 +558,7 @@ impl pallet_staking::Config for Runtime { // Alternatively, use pallet_staking::UseNominatorsMap to just use the nominators map. // Note that the aforementioned does not scale to a very large number of nominators. type SortedListProvider = BagsList; + type MaxUnlockingChunks = ConstU32<32>; type WeightInfo = pallet_staking::weights::SubstrateWeight; type BenchmarkingConfig = StakingBenchmarkingConfig; } diff --git a/frame/babe/src/mock.rs b/frame/babe/src/mock.rs index 2e4b6023f1e5..152ec5ab206e 100644 --- a/frame/babe/src/mock.rs +++ b/frame/babe/src/mock.rs @@ -198,6 +198,7 @@ impl pallet_staking::Config for Test { type ElectionProvider = onchain::OnChainSequentialPhragmen; type GenesisElectionProvider = Self::ElectionProvider; type SortedListProvider = pallet_staking::UseNominatorsMap; + type MaxUnlockingChunks = ConstU32<32>; type BenchmarkingConfig = pallet_staking::TestBenchmarkingConfig; type WeightInfo = (); } diff --git a/frame/grandpa/src/mock.rs b/frame/grandpa/src/mock.rs index d07f3136d9a0..9dac33f97984 100644 --- a/frame/grandpa/src/mock.rs +++ b/frame/grandpa/src/mock.rs @@ -206,6 +206,7 @@ impl pallet_staking::Config for Test { type ElectionProvider = onchain::OnChainSequentialPhragmen; type GenesisElectionProvider = Self::ElectionProvider; type SortedListProvider = pallet_staking::UseNominatorsMap; + type MaxUnlockingChunks = ConstU32<32>; type BenchmarkingConfig = pallet_staking::TestBenchmarkingConfig; type WeightInfo = (); } diff --git a/frame/offences/benchmarking/src/mock.rs b/frame/offences/benchmarking/src/mock.rs index 3b5e640867c5..22c9af0f4c3c 100644 --- a/frame/offences/benchmarking/src/mock.rs +++ b/frame/offences/benchmarking/src/mock.rs @@ -176,6 +176,7 @@ impl pallet_staking::Config for Test { type ElectionProvider = onchain::OnChainSequentialPhragmen; type GenesisElectionProvider = Self::ElectionProvider; type SortedListProvider = pallet_staking::UseNominatorsMap; + type MaxUnlockingChunks = ConstU32<32>; type BenchmarkingConfig = pallet_staking::TestBenchmarkingConfig; type WeightInfo = (); } diff --git a/frame/session/benchmarking/src/mock.rs b/frame/session/benchmarking/src/mock.rs index 37305437ca09..a9328b6546c9 100644 --- a/frame/session/benchmarking/src/mock.rs +++ b/frame/session/benchmarking/src/mock.rs @@ -181,6 +181,7 @@ impl pallet_staking::Config for Test { type OffendingValidatorsThreshold = (); type ElectionProvider = onchain::OnChainSequentialPhragmen; type GenesisElectionProvider = Self::ElectionProvider; + type MaxUnlockingChunks = ConstU32<32>; type SortedListProvider = pallet_staking::UseNominatorsMap; type BenchmarkingConfig = pallet_staking::TestBenchmarkingConfig; type WeightInfo = (); diff --git a/frame/staking/src/benchmarking.rs b/frame/staking/src/benchmarking.rs index 65a1ee92e2ea..7593522055fb 100644 --- a/frame/staking/src/benchmarking.rs +++ b/frame/staking/src/benchmarking.rs @@ -618,7 +618,7 @@ benchmarks! { } rebond { - let l in 1 .. MAX_UNLOCKING_CHUNKS as u32; + let l in 1 .. MaxUnlockingChunks::get() as u32; // clean up any existing state. clear_validators_and_nominators::(); @@ -652,7 +652,7 @@ benchmarks! { let mut staking_ledger = Ledger::::get(controller.clone()).unwrap(); for _ in 0 .. l { - staking_ledger.unlocking.push(unlock_chunk.clone()) + staking_ledger.unlocking.try_push(unlock_chunk.clone()).unwrap() } Ledger::::insert(controller.clone(), staking_ledger.clone()); let original_bonded: BalanceOf = staking_ledger.active; @@ -702,7 +702,7 @@ benchmarks! { stash: stash.clone(), active: T::Currency::minimum_balance() - One::one(), total: T::Currency::minimum_balance() - One::one(), - unlocking: vec![], + unlocking: Default::default(), claimed_rewards: vec![], }; Ledger::::insert(&controller, l); @@ -788,7 +788,7 @@ benchmarks! { #[extra] do_slash { - let l in 1 .. MAX_UNLOCKING_CHUNKS as u32; + let l in 1 .. MaxUnlockingChunks::get() as u32; let (stash, controller) = create_stash_controller::(0, 100, Default::default())?; let mut staking_ledger = Ledger::::get(controller.clone()).unwrap(); let unlock_chunk = UnlockChunk::> { @@ -796,7 +796,7 @@ benchmarks! { era: EraIndex::zero(), }; for _ in 0 .. l { - staking_ledger.unlocking.push(unlock_chunk.clone()) + staking_ledger.unlocking.try_push(unlock_chunk.clone()).unwrap(); } Ledger::::insert(controller, staking_ledger); let slash_amount = T::Currency::minimum_balance() * 10u32.into(); diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 22143ff1ee03..d833ac86fe0b 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -301,6 +301,7 @@ mod pallet; use codec::{Decode, Encode, HasCompact}; use frame_support::{ + parameter_types, traits::{ConstU32, Currency, Get}, weights::Weight, BoundedVec, EqNoBound, PartialEqNoBound, RuntimeDebugNoBound, @@ -347,6 +348,10 @@ type NegativeImbalanceOf = <::Currency as Currency< ::AccountId, >>::NegativeImbalance; +parameter_types! { + pub MaxUnlockingChunks: u32 = 32; +} + /// Information regarding the active era (era in used in session). #[derive(Encode, Decode, RuntimeDebug, TypeInfo)] pub struct ActiveEraInfo { @@ -446,9 +451,10 @@ pub struct StakingLedger { /// rounds. #[codec(compact)] pub active: Balance, - /// Any balance that is becoming free, which may eventually be transferred out - /// of the stash (assuming it doesn't get slashed first). - pub unlocking: Vec>, + /// Any balance that is becoming free, which may eventually be transferred out of the stash + /// (assuming it doesn't get slashed first). It is assumed that this will be treated as a first + /// in, first out queue where the new (higher value) eras get pushed on the back. + pub unlocking: BoundedVec, MaxUnlockingChunks>, /// List of eras for which the stakers behind a validator have claimed rewards. Only updated /// for validators. pub claimed_rewards: Vec, @@ -463,7 +469,7 @@ impl Self { let mut total = self.total; - let unlocking = self + let unlocking: BoundedVec<_, _> = self .unlocking .into_iter() .filter(|chunk| { @@ -483,7 +489,11 @@ impl>() + .try_into() + .expect( + "filtering items from a bounded vec always leaves length less than bounds. qed", + ); Self { stash: self.stash, diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index 95f305dfdd22..12d3804b4e30 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -271,6 +271,7 @@ impl crate::pallet::pallet::Config for Test { type GenesisElectionProvider = Self::ElectionProvider; // NOTE: consider a macro and use `UseNominatorsMap` as well. type SortedListProvider = BagsList; + type MaxUnlockingChunks = ConstU32<32>; type BenchmarkingConfig = TestBenchmarkingConfig; type WeightInfo = (); } diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index ae20550cd40b..5cd0d0107f01 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -928,7 +928,7 @@ impl ElectionDataProvider for Pallet { stash: voter.clone(), active: stake, total: stake, - unlocking: vec![], + unlocking: Default::default(), claimed_rewards: vec![], }, ); @@ -946,7 +946,7 @@ impl ElectionDataProvider for Pallet { stash: target.clone(), active: stake, total: stake, - unlocking: vec![], + unlocking: Default::default(), claimed_rewards: vec![], }, ); @@ -983,7 +983,7 @@ impl ElectionDataProvider for Pallet { stash: v.clone(), active: stake, total: stake, - unlocking: vec![], + unlocking: Default::default(), claimed_rewards: vec![], }, ); @@ -1004,7 +1004,7 @@ impl ElectionDataProvider for Pallet { stash: v.clone(), active: stake, total: stake, - unlocking: vec![], + unlocking: Default::default(), claimed_rewards: vec![], }, ); diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index f53e6b50d7a3..9d3b438daebb 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -21,8 +21,8 @@ use frame_election_provider_support::SortedListProvider; use frame_support::{ pallet_prelude::*, traits::{ - Currency, CurrencyToVote, EnsureOrigin, EstimateNextNewSession, Get, LockIdentifier, - LockableCurrency, OnUnbalanced, UnixTime, + Currency, CurrencyToVote, DefensiveSaturating, EnsureOrigin, EstimateNextNewSession, Get, + LockIdentifier, LockableCurrency, OnUnbalanced, UnixTime, }, weights::Weight, }; @@ -40,12 +40,11 @@ pub use impls::*; use crate::{ log, slashing, weights::WeightInfo, ActiveEraInfo, BalanceOf, EraPayout, EraRewardPoints, - Exposure, Forcing, NegativeImbalanceOf, Nominations, PositiveImbalanceOf, Releases, - RewardDestination, SessionInterface, StakingLedger, UnappliedSlash, UnlockChunk, + Exposure, Forcing, MaxUnlockingChunks, NegativeImbalanceOf, Nominations, PositiveImbalanceOf, + Releases, RewardDestination, SessionInterface, StakingLedger, UnappliedSlash, UnlockChunk, ValidatorPrefs, }; -pub const MAX_UNLOCKING_CHUNKS: usize = 32; const STAKING_ID: LockIdentifier = *b"staking "; #[frame_support::pallet] @@ -157,6 +156,10 @@ pub mod pallet { /// the bags-list is not desired, [`impls::UseNominatorsMap`] is likely the desired option. type SortedListProvider: SortedListProvider; + /// The maximum number of `unlocking` chunks a [`StakingLedger`] can have. Effectively + /// determines how many unique eras a staker may be unbonding in. + type MaxUnlockingChunks: Get; + /// Some parameters of the benchmarking. type BenchmarkingConfig: BenchmarkingConfig; @@ -772,7 +775,7 @@ pub mod pallet { stash, total: value, active: value, - unlocking: vec![], + unlocking: Default::default(), claimed_rewards: (last_reward_era..current_era).collect(), }; Self::update_ledger(&controller, &item); @@ -837,7 +840,7 @@ pub mod pallet { /// Once the unlock period is done, you can call `withdraw_unbonded` to actually move /// the funds out of management ready for transfer. /// - /// No more than a limited number of unlocking chunks (see `MAX_UNLOCKING_CHUNKS`) + /// No more than a limited number of unlocking chunks (see `MaxUnlockingChunks`) /// can co-exists at the same time. In that case, [`Call::withdraw_unbonded`] need /// to be called first to remove some of the chunks (if possible). /// @@ -854,7 +857,10 @@ pub mod pallet { ) -> DispatchResult { let controller = ensure_signed(origin)?; let mut ledger = Self::ledger(&controller).ok_or(Error::::NotController)?; - ensure!(ledger.unlocking.len() < MAX_UNLOCKING_CHUNKS, Error::::NoMoreChunks,); + ensure!( + ledger.unlocking.len() < MaxUnlockingChunks::get() as usize, + Error::::NoMoreChunks, + ); let mut value = value.min(ledger.active); @@ -881,7 +887,19 @@ pub mod pallet { // Note: in case there is no current era it is fine to bond one era more. let era = Self::current_era().unwrap_or(0) + T::BondingDuration::get(); - ledger.unlocking.push(UnlockChunk { value, era }); + if let Some(mut chunk) = + ledger.unlocking.last_mut().filter(|chunk| chunk.era == era) + { + // To keep the chunk count down, we only keep one chunk per era. Since + // `unlocking` is a FiFo queue, if a chunk exists for `era` we know that it will + // be the last one. + chunk.value = chunk.value.defensive_saturating_add(value) + } else { + ledger + .unlocking + .try_push(UnlockChunk { value, era }) + .map_err(|_| Error::::NoMoreChunks)?; + }; // NOTE: ledger must be updated prior to calling `Self::weight_of`. Self::update_ledger(&controller, &ledger); @@ -1348,10 +1366,10 @@ pub mod pallet { /// /// # /// - Time complexity: O(L), where L is unlocking chunks - /// - Bounded by `MAX_UNLOCKING_CHUNKS`. + /// - Bounded by `MaxUnlockingChunks`. /// - Storage changes: Can't increase storage, only decrease it. /// # - #[pallet::weight(T::WeightInfo::rebond(MAX_UNLOCKING_CHUNKS as u32))] + #[pallet::weight(T::WeightInfo::rebond(MaxUnlockingChunks::get() as u32))] pub fn rebond( origin: OriginFor, #[pallet::compact] value: BalanceOf, diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 4073c069fb6b..0fc6cd27a266 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -17,10 +17,10 @@ //! Tests for the module. -use super::{Event, *}; +use super::{Event, MaxUnlockingChunks, *}; use frame_election_provider_support::{ElectionProvider, SortedListProvider, Support}; use frame_support::{ - assert_noop, assert_ok, + assert_noop, assert_ok, bounded_vec, dispatch::WithPostDispatchInfo, pallet_prelude::*, traits::{Currency, Get, ReservableCurrency}, @@ -104,7 +104,7 @@ fn basic_setup_works() { stash: 11, total: 1000, active: 1000, - unlocking: vec![], + unlocking: Default::default(), claimed_rewards: vec![] }) ); @@ -115,7 +115,7 @@ fn basic_setup_works() { stash: 21, total: 1000, active: 1000, - unlocking: vec![], + unlocking: Default::default(), claimed_rewards: vec![] }) ); @@ -138,7 +138,7 @@ fn basic_setup_works() { stash: 101, total: 500, active: 500, - unlocking: vec![], + unlocking: Default::default(), claimed_rewards: vec![] }) ); @@ -382,7 +382,7 @@ fn staking_should_work() { stash: 3, total: 1500, active: 1500, - unlocking: vec![], + unlocking: Default::default(), claimed_rewards: vec![0], }) ); @@ -936,7 +936,7 @@ fn reward_destination_works() { stash: 11, total: 1000, active: 1000, - unlocking: vec![], + unlocking: Default::default(), claimed_rewards: vec![], }) ); @@ -959,7 +959,7 @@ fn reward_destination_works() { stash: 11, total: 1000 + total_payout_0, active: 1000 + total_payout_0, - unlocking: vec![], + unlocking: Default::default(), claimed_rewards: vec![0], }) ); @@ -987,7 +987,7 @@ fn reward_destination_works() { stash: 11, total: 1000 + total_payout_0, active: 1000 + total_payout_0, - unlocking: vec![], + unlocking: Default::default(), claimed_rewards: vec![0, 1], }) ); @@ -1016,7 +1016,7 @@ fn reward_destination_works() { stash: 11, total: 1000 + total_payout_0, active: 1000 + total_payout_0, - unlocking: vec![], + unlocking: Default::default(), claimed_rewards: vec![0, 1, 2], }) ); @@ -1081,7 +1081,7 @@ fn bond_extra_works() { stash: 11, total: 1000, active: 1000, - unlocking: vec![], + unlocking: Default::default(), claimed_rewards: vec![], }) ); @@ -1098,7 +1098,7 @@ fn bond_extra_works() { stash: 11, total: 1000 + 100, active: 1000 + 100, - unlocking: vec![], + unlocking: Default::default(), claimed_rewards: vec![], }) ); @@ -1112,7 +1112,7 @@ fn bond_extra_works() { stash: 11, total: 1000000, active: 1000000, - unlocking: vec![], + unlocking: Default::default(), claimed_rewards: vec![], }) ); @@ -1150,7 +1150,7 @@ fn bond_extra_and_withdraw_unbonded_works() { stash: 11, total: 1000, active: 1000, - unlocking: vec![], + unlocking: Default::default(), claimed_rewards: vec![], }) ); @@ -1168,7 +1168,7 @@ fn bond_extra_and_withdraw_unbonded_works() { stash: 11, total: 1000 + 100, active: 1000 + 100, - unlocking: vec![], + unlocking: Default::default(), claimed_rewards: vec![], }) ); @@ -1189,7 +1189,7 @@ fn bond_extra_and_withdraw_unbonded_works() { stash: 11, total: 1000 + 100, active: 1000 + 100, - unlocking: vec![], + unlocking: Default::default(), claimed_rewards: vec![], }) ); @@ -1207,7 +1207,7 @@ fn bond_extra_and_withdraw_unbonded_works() { stash: 11, total: 1000 + 100, active: 100, - unlocking: vec![UnlockChunk { value: 1000, era: 2 + 3 }], + unlocking: bounded_vec![UnlockChunk { value: 1000, era: 2 + 3 }], claimed_rewards: vec![] }), ); @@ -1220,7 +1220,7 @@ fn bond_extra_and_withdraw_unbonded_works() { stash: 11, total: 1000 + 100, active: 100, - unlocking: vec![UnlockChunk { value: 1000, era: 2 + 3 }], + unlocking: bounded_vec![UnlockChunk { value: 1000, era: 2 + 3 }], claimed_rewards: vec![] }), ); @@ -1236,7 +1236,7 @@ fn bond_extra_and_withdraw_unbonded_works() { stash: 11, total: 1000 + 100, active: 100, - unlocking: vec![UnlockChunk { value: 1000, era: 2 + 3 }], + unlocking: bounded_vec![UnlockChunk { value: 1000, era: 2 + 3 }], claimed_rewards: vec![] }), ); @@ -1252,7 +1252,7 @@ fn bond_extra_and_withdraw_unbonded_works() { stash: 11, total: 100, active: 100, - unlocking: vec![], + unlocking: Default::default(), claimed_rewards: vec![] }), ); @@ -1262,23 +1262,35 @@ fn bond_extra_and_withdraw_unbonded_works() { #[test] fn too_many_unbond_calls_should_not_work() { ExtBuilder::default().build_and_execute(|| { - // locked at era 0 until 3 - for _ in 0..MAX_UNLOCKING_CHUNKS - 1 { + let mut current_era = 0; + // locked at era MaxUnlockingChunks - 1 until 3 + for i in 0..MaxUnlockingChunks::get() - 1 { + // There is only 1 chunk per era, so we need to be in a new era to create a chunk. + current_era = i as u32; + mock::start_active_era(current_era); assert_ok!(Staking::unbond(Origin::signed(10), 1)); } - mock::start_active_era(1); + current_era += 1; + mock::start_active_era(current_era); - // locked at era 1 until 4 + // This chunk is locked at `current_era` through `current_era + 2` (because BondingDuration + // == 3). assert_ok!(Staking::unbond(Origin::signed(10), 1)); + assert_eq!( + Staking::ledger(&10).unwrap().unlocking.len(), + MaxUnlockingChunks::get() as usize + ); // can't do more. assert_noop!(Staking::unbond(Origin::signed(10), 1), Error::::NoMoreChunks); - mock::start_active_era(3); + current_era += 2; + mock::start_active_era(current_era); assert_noop!(Staking::unbond(Origin::signed(10), 1), Error::::NoMoreChunks); - // free up. + // free up everything except the most recently added chunk. assert_ok!(Staking::withdraw_unbonded(Origin::signed(10), 0)); + assert_eq!(Staking::ledger(&10).unwrap().unlocking.len(), 1); // Can add again. assert_ok!(Staking::unbond(Origin::signed(10), 1)); @@ -1310,7 +1322,7 @@ fn rebond_works() { stash: 11, total: 1000, active: 1000, - unlocking: vec![], + unlocking: Default::default(), claimed_rewards: vec![], }) ); @@ -1329,7 +1341,7 @@ fn rebond_works() { stash: 11, total: 1000, active: 100, - unlocking: vec![UnlockChunk { value: 900, era: 2 + 3 }], + unlocking: bounded_vec![UnlockChunk { value: 900, era: 2 + 3 }], claimed_rewards: vec![], }) ); @@ -1342,7 +1354,7 @@ fn rebond_works() { stash: 11, total: 1000, active: 1000, - unlocking: vec![], + unlocking: Default::default(), claimed_rewards: vec![], }) ); @@ -1355,7 +1367,7 @@ fn rebond_works() { stash: 11, total: 1000, active: 100, - unlocking: vec![UnlockChunk { value: 900, era: 5 }], + unlocking: bounded_vec![UnlockChunk { value: 900, era: 5 }], claimed_rewards: vec![], }) ); @@ -1368,7 +1380,7 @@ fn rebond_works() { stash: 11, total: 1000, active: 600, - unlocking: vec![UnlockChunk { value: 400, era: 5 }], + unlocking: bounded_vec![UnlockChunk { value: 400, era: 5 }], claimed_rewards: vec![], }) ); @@ -1381,7 +1393,7 @@ fn rebond_works() { stash: 11, total: 1000, active: 1000, - unlocking: vec![], + unlocking: Default::default(), claimed_rewards: vec![], }) ); @@ -1396,11 +1408,7 @@ fn rebond_works() { stash: 11, total: 1000, active: 100, - unlocking: vec![ - UnlockChunk { value: 300, era: 5 }, - UnlockChunk { value: 300, era: 5 }, - UnlockChunk { value: 300, era: 5 }, - ], + unlocking: bounded_vec![UnlockChunk { value: 900, era: 5 }], claimed_rewards: vec![], }) ); @@ -1413,10 +1421,7 @@ fn rebond_works() { stash: 11, total: 1000, active: 600, - unlocking: vec![ - UnlockChunk { value: 300, era: 5 }, - UnlockChunk { value: 100, era: 5 }, - ], + unlocking: bounded_vec![UnlockChunk { value: 400, era: 5 }], claimed_rewards: vec![], }) ); @@ -1443,7 +1448,7 @@ fn rebond_is_fifo() { stash: 11, total: 1000, active: 1000, - unlocking: vec![], + unlocking: Default::default(), claimed_rewards: vec![], }) ); @@ -1458,7 +1463,7 @@ fn rebond_is_fifo() { stash: 11, total: 1000, active: 600, - unlocking: vec![UnlockChunk { value: 400, era: 2 + 3 },], + unlocking: bounded_vec![UnlockChunk { value: 400, era: 2 + 3 }], claimed_rewards: vec![], }) ); @@ -1473,9 +1478,9 @@ fn rebond_is_fifo() { stash: 11, total: 1000, active: 300, - unlocking: vec![ + unlocking: bounded_vec![ UnlockChunk { value: 400, era: 2 + 3 }, - UnlockChunk { value: 300, era: 3 + 3 }, + UnlockChunk { value: 300, era: 3 + 3 } ], claimed_rewards: vec![], }) @@ -1491,10 +1496,10 @@ fn rebond_is_fifo() { stash: 11, total: 1000, active: 100, - unlocking: vec![ + unlocking: bounded_vec![ UnlockChunk { value: 400, era: 2 + 3 }, UnlockChunk { value: 300, era: 3 + 3 }, - UnlockChunk { value: 200, era: 4 + 3 }, + UnlockChunk { value: 200, era: 4 + 3 } ], claimed_rewards: vec![], }) @@ -1508,9 +1513,9 @@ fn rebond_is_fifo() { stash: 11, total: 1000, active: 500, - unlocking: vec![ + unlocking: bounded_vec![ UnlockChunk { value: 400, era: 2 + 3 }, - UnlockChunk { value: 100, era: 3 + 3 }, + UnlockChunk { value: 100, era: 3 + 3 } ], claimed_rewards: vec![], }) @@ -1540,7 +1545,7 @@ fn rebond_emits_right_value_in_event() { stash: 11, total: 1000, active: 100, - unlocking: vec![UnlockChunk { value: 900, era: 1 + 3 }], + unlocking: bounded_vec![UnlockChunk { value: 900, era: 1 + 3 }], claimed_rewards: vec![], }) ); @@ -1553,7 +1558,7 @@ fn rebond_emits_right_value_in_event() { stash: 11, total: 1000, active: 200, - unlocking: vec![UnlockChunk { value: 800, era: 1 + 3 }], + unlocking: bounded_vec![UnlockChunk { value: 800, era: 1 + 3 }], claimed_rewards: vec![], }) ); @@ -1568,7 +1573,7 @@ fn rebond_emits_right_value_in_event() { stash: 11, total: 1000, active: 1000, - unlocking: vec![], + unlocking: Default::default(), claimed_rewards: vec![], }) ); @@ -1604,7 +1609,7 @@ fn reward_to_stake_works() { stash: 21, total: 69, active: 69, - unlocking: vec![], + unlocking: Default::default(), claimed_rewards: vec![], }, ); @@ -1665,7 +1670,7 @@ fn reap_stash_works() { stash: 11, total: 5, active: 5, - unlocking: vec![], + unlocking: Default::default(), claimed_rewards: vec![], }, ); @@ -1784,7 +1789,7 @@ fn bond_with_no_staked_value() { stash: 1, active: 0, total: 5, - unlocking: vec![UnlockChunk { value: 5, era: 3 }], + unlocking: bounded_vec![UnlockChunk { value: 5, era: 3 }], claimed_rewards: vec![], }) ); @@ -3354,7 +3359,7 @@ fn test_payout_stakers() { stash: 11, total: 1000, active: 1000, - unlocking: vec![], + unlocking: Default::default(), claimed_rewards: vec![1] }) ); @@ -3376,7 +3381,7 @@ fn test_payout_stakers() { stash: 11, total: 1000, active: 1000, - unlocking: vec![], + unlocking: Default::default(), claimed_rewards: (1..=14).collect() }) ); @@ -3397,7 +3402,7 @@ fn test_payout_stakers() { stash: 11, total: 1000, active: 1000, - unlocking: vec![], + unlocking: Default::default(), claimed_rewards: vec![15, 98] }) ); @@ -3412,7 +3417,7 @@ fn test_payout_stakers() { stash: 11, total: 1000, active: 1000, - unlocking: vec![], + unlocking: Default::default(), claimed_rewards: vec![15, 23, 42, 69, 98] }) ); @@ -3607,7 +3612,7 @@ fn bond_during_era_correctly_populates_claimed_rewards() { stash: 9, total: 1000, active: 1000, - unlocking: vec![], + unlocking: Default::default(), claimed_rewards: vec![], }) ); @@ -3619,7 +3624,7 @@ fn bond_during_era_correctly_populates_claimed_rewards() { stash: 11, total: 1000, active: 1000, - unlocking: vec![], + unlocking: Default::default(), claimed_rewards: (0..5).collect(), }) ); @@ -3631,7 +3636,7 @@ fn bond_during_era_correctly_populates_claimed_rewards() { stash: 13, total: 1000, active: 1000, - unlocking: vec![], + unlocking: Default::default(), claimed_rewards: (15..99).collect(), }) ); @@ -3850,7 +3855,7 @@ fn cannot_rebond_to_lower_than_ed() { stash: 21, total: 10 * 1000, active: 10 * 1000, - unlocking: vec![], + unlocking: Default::default(), claimed_rewards: vec![] } ); @@ -3864,7 +3869,7 @@ fn cannot_rebond_to_lower_than_ed() { stash: 21, total: 10 * 1000, active: 0, - unlocking: vec![UnlockChunk { value: 10 * 1000, era: 3 }], + unlocking: bounded_vec![UnlockChunk { value: 10 * 1000, era: 3 }], claimed_rewards: vec![] } ); @@ -3887,7 +3892,7 @@ fn cannot_bond_extra_to_lower_than_ed() { stash: 21, total: 10 * 1000, active: 10 * 1000, - unlocking: vec![], + unlocking: Default::default(), claimed_rewards: vec![] } ); @@ -3901,7 +3906,7 @@ fn cannot_bond_extra_to_lower_than_ed() { stash: 21, total: 10 * 1000, active: 0, - unlocking: vec![UnlockChunk { value: 10 * 1000, era: 3 }], + unlocking: bounded_vec![UnlockChunk { value: 10 * 1000, era: 3 }], claimed_rewards: vec![] } ); @@ -3928,7 +3933,7 @@ fn do_not_die_when_active_is_ed() { stash: 21, total: 1000 * ed, active: 1000 * ed, - unlocking: vec![], + unlocking: Default::default(), claimed_rewards: vec![] } ); @@ -3945,7 +3950,7 @@ fn do_not_die_when_active_is_ed() { stash: 21, total: ed, active: ed, - unlocking: vec![], + unlocking: Default::default(), claimed_rewards: vec![] } ); diff --git a/frame/support/src/storage/bounded_vec.rs b/frame/support/src/storage/bounded_vec.rs index 206a7e5d4ede..4e513258f968 100644 --- a/frame/support/src/storage/bounded_vec.rs +++ b/frame/support/src/storage/bounded_vec.rs @@ -25,7 +25,7 @@ use crate::{ }; use codec::{Decode, Encode, EncodeLike, MaxEncodedLen}; use core::{ - ops::{Deref, Index, IndexMut}, + ops::{Deref, Index, IndexMut, RangeBounds}, slice::SliceIndex, }; use sp_std::{marker::PhantomData, prelude::*}; @@ -178,6 +178,19 @@ impl BoundedVec { pub fn iter_mut(&mut self) -> core::slice::IterMut<'_, T> { self.0.iter_mut() } + + /// Exactly the same semantics as [`slice::last_mut`]. + pub fn last_mut(&mut self) -> Option<&mut T> { + self.0.last_mut() + } + + /// Exact same semantics as [`Vec::drain`]. + pub fn drain(&mut self, range: R) -> sp_std::vec::Drain<'_, T> + where + R: RangeBounds, + { + self.0.drain(range) + } } impl> From> for Vec { From a9345510cf5b76d12c8365d618aa562ffe507f25 Mon Sep 17 00:00:00 2001 From: Zeke Mostov Date: Tue, 1 Mar 2022 21:49:23 -0800 Subject: [PATCH 549/695] staking: Expose `MaxUnlockingChunks` in metadata as a const (#10958) --- frame/staking/src/pallet/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 9d3b438daebb..eb8dab7ce6bb 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -158,6 +158,7 @@ pub mod pallet { /// The maximum number of `unlocking` chunks a [`StakingLedger`] can have. Effectively /// determines how many unique eras a staker may be unbonding in. + #[pallet::constant] type MaxUnlockingChunks: Get; /// Some parameters of the benchmarking. From a7a4c68b092fa64e20d286cf1697ec3378e2ed57 Mon Sep 17 00:00:00 2001 From: Zeke Mostov Date: Wed, 2 Mar 2022 00:40:08 -0800 Subject: [PATCH 550/695] Allow trailing commas for `bounded_vec!` (#10959) --- frame/staking/src/tests.rs | 6 +++--- frame/support/src/lib.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 0fc6cd27a266..0f979f1d5922 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -1480,7 +1480,7 @@ fn rebond_is_fifo() { active: 300, unlocking: bounded_vec![ UnlockChunk { value: 400, era: 2 + 3 }, - UnlockChunk { value: 300, era: 3 + 3 } + UnlockChunk { value: 300, era: 3 + 3 }, ], claimed_rewards: vec![], }) @@ -1499,7 +1499,7 @@ fn rebond_is_fifo() { unlocking: bounded_vec![ UnlockChunk { value: 400, era: 2 + 3 }, UnlockChunk { value: 300, era: 3 + 3 }, - UnlockChunk { value: 200, era: 4 + 3 } + UnlockChunk { value: 200, era: 4 + 3 }, ], claimed_rewards: vec![], }) @@ -1515,7 +1515,7 @@ fn rebond_is_fifo() { active: 500, unlocking: bounded_vec![ UnlockChunk { value: 400, era: 2 + 3 }, - UnlockChunk { value: 100, era: 3 + 3 } + UnlockChunk { value: 100, era: 3 + 3 }, ], claimed_rewards: vec![], }) diff --git a/frame/support/src/lib.rs b/frame/support/src/lib.rs index ef60729f6d86..3988b5e9af21 100644 --- a/frame/support/src/lib.rs +++ b/frame/support/src/lib.rs @@ -123,7 +123,7 @@ impl TypeId for PalletId { #[macro_export] #[cfg(feature = "std")] macro_rules! bounded_vec { - ($ ($values:expr),* ) => { + ($ ($values:expr),* $(,)?) => { { use $crate::sp_std::convert::TryInto as _; $crate::sp_std::vec![$($values),*].try_into().unwrap() From f4fb93fdccc2edc38a394fc42a93ab73974fc4f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Wed, 2 Mar 2022 10:03:10 +0100 Subject: [PATCH 551/695] SimpleSlotWorker: Do not implement `SlotWorker` for all types implementing `SimpleSlotWorker` (#10934) Because Rust currently doesn't support specialization, it prevents users from implementing `SlotWorker` for their own types. This pr solves this by removing the generic implementation of `SlotWorker` for `SimpleSlotWorker` and providing some wrapper type for that. --- client/consensus/aura/src/lib.rs | 4 ++-- client/consensus/babe/src/lib.rs | 2 +- client/consensus/slots/src/lib.rs | 13 ++++++++++--- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/client/consensus/aura/src/lib.rs b/client/consensus/aura/src/lib.rs index d3a6b1058940..4d91eaaae92a 100644 --- a/client/consensus/aura/src/lib.rs +++ b/client/consensus/aura/src/lib.rs @@ -279,7 +279,7 @@ where L: sc_consensus::JustificationSyncLink, BS: BackoffAuthoringBlocksStrategy> + Send + Sync + 'static, { - AuraWorker { + sc_consensus_slots::SimpleSlotWorkerToSlotWorker(AuraWorker { client, block_import, env: proposer_factory, @@ -292,7 +292,7 @@ where block_proposal_slot_portion, max_block_proposal_slot_portion, _key_type: PhantomData::

, - } + }) } struct AuraWorker { diff --git a/client/consensus/babe/src/lib.rs b/client/consensus/babe/src/lib.rs index 0e9f943eca30..442dbab77e12 100644 --- a/client/consensus/babe/src/lib.rs +++ b/client/consensus/babe/src/lib.rs @@ -518,7 +518,7 @@ where let slot_worker = sc_consensus_slots::start_slot_worker( babe_link.config.slot_duration(), select_chain, - worker, + sc_consensus_slots::SimpleSlotWorkerToSlotWorker(worker), sync_oracle, create_inherent_data_providers, can_author_with, diff --git a/client/consensus/slots/src/lib.rs b/client/consensus/slots/src/lib.rs index f6129943b241..a97469fbcc30 100644 --- a/client/consensus/slots/src/lib.rs +++ b/client/consensus/slots/src/lib.rs @@ -401,15 +401,22 @@ pub trait SimpleSlotWorker { } } +/// A type that implements [`SlotWorker`] for a type that implements [`SimpleSlotWorker`]. +/// +/// This is basically a workaround for Rust not supporting specialization. Otherwise we could +/// implement [`SlotWorker`] for any `T` that implements [`SimpleSlotWorker`], but currently +/// that would prevent downstream users to implement [`SlotWorker`] for their own types. +pub struct SimpleSlotWorkerToSlotWorker(pub T); + #[async_trait::async_trait] -impl + Send + Sync> - SlotWorker>::Proof> for T +impl + Send + Sync, B: BlockT> + SlotWorker>::Proof> for SimpleSlotWorkerToSlotWorker { async fn on_slot( &mut self, slot_info: SlotInfo, ) -> Option>::Proof>> { - SimpleSlotWorker::on_slot(self, slot_info).await + self.0.on_slot(slot_info).await } } From 90b89f8f607f9a921a810651e1dd2ae764f089a9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 2 Mar 2022 16:39:39 +0100 Subject: [PATCH 552/695] Bump digest from 0.10.2 to 0.10.3 (#10960) Bumps [digest](https://github.com/RustCrypto/traits) from 0.10.2 to 0.10.3. - [Release notes](https://github.com/RustCrypto/traits/releases) - [Commits](https://github.com/RustCrypto/traits/compare/digest-v0.10.2...digest-v0.10.3) --- updated-dependencies: - dependency-name: digest dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 23 ++++++++++++----------- primitives/core/hashing/Cargo.toml | 2 +- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5c1b6ed88fb4..3d95343cb0b2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -629,7 +629,7 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b94ba84325db59637ffc528bbe8c7f86c02c57cff5c0e2b9b00f9a851f42f309" dependencies = [ - "digest 0.10.2", + "digest 0.10.3", ] [[package]] @@ -1403,11 +1403,12 @@ dependencies = [ [[package]] name = "crypto-common" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4600d695eb3f6ce1cd44e6e291adceb2cc3ab12f20a33777ecd0bf6eba34e06" +checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" dependencies = [ "generic-array 0.14.4", + "typenum", ] [[package]] @@ -1632,9 +1633,9 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cb780dce4f9a8f5c087362b3a4595936b2019e7c8b30f2c3e9a7e94e6ae9837" +checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" dependencies = [ "block-buffer 0.10.0", "crypto-common", @@ -9416,7 +9417,7 @@ checksum = "99c3bd8169c58782adad9290a9af5939994036b76187f7b4f0e6de91dbbfc0ec" dependencies = [ "cfg-if 1.0.0", "cpufeatures 0.2.1", - "digest 0.10.2", + "digest 0.10.3", ] [[package]] @@ -9437,7 +9438,7 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "31f935e31cf406e8c0e96c2815a5516181b7004ae8c5f296293221e9b1e356bd" dependencies = [ - "digest 0.10.2", + "digest 0.10.3", "keccak", ] @@ -9883,7 +9884,7 @@ version = "4.0.0" dependencies = [ "blake2 0.10.2", "byteorder", - "digest 0.10.2", + "digest 0.10.3", "sha2 0.10.1", "sha3 0.10.0", "sp-std", @@ -11379,7 +11380,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ee73e6e4924fe940354b8d4d98cad5231175d615cd855b758adc658c0aac6a0" dependencies = [ "cfg-if 1.0.0", - "digest 0.10.2", + "digest 0.10.3", "rand 0.8.4", "static_assertions", ] @@ -11392,9 +11393,9 @@ checksum = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" [[package]] name = "typenum" -version = "1.12.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" [[package]] name = "ucd-trie" diff --git a/primitives/core/hashing/Cargo.toml b/primitives/core/hashing/Cargo.toml index dc5704d2989a..978cb8906d5d 100644 --- a/primitives/core/hashing/Cargo.toml +++ b/primitives/core/hashing/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] sp-std = { version = "4.0.0", default-features = false, path = "../../std" } byteorder = { version = "1.3.2", default-features = false } -digest = { version = "0.10.2", default-features = false } +digest = { version = "0.10.3", default-features = false } blake2 = { version = "0.10.2", default-features = false } sha2 = { version = "0.10.1", default-features = false } sha3 = { version = "0.10.0", default-features = false } From 7a742c6f7746f12e1340e9f401fadc529575a096 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 2 Mar 2022 21:13:24 +0100 Subject: [PATCH 553/695] Bump scale-info from 2.0.0 to 2.0.1 (#10965) Bumps [scale-info](https://github.com/paritytech/scale-info) from 2.0.0 to 2.0.1. - [Release notes](https://github.com/paritytech/scale-info/releases) - [Changelog](https://github.com/paritytech/scale-info/blob/master/CHANGELOG.md) - [Commits](https://github.com/paritytech/scale-info/commits) --- updated-dependencies: - dependency-name: scale-info dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- bin/node-template/pallets/template/Cargo.toml | 2 +- bin/node-template/runtime/Cargo.toml | 2 +- bin/node/executor/Cargo.toml | 2 +- bin/node/primitives/Cargo.toml | 2 +- bin/node/runtime/Cargo.toml | 2 +- frame/assets/Cargo.toml | 2 +- frame/atomic-swap/Cargo.toml | 2 +- frame/aura/Cargo.toml | 2 +- frame/authority-discovery/Cargo.toml | 2 +- frame/authorship/Cargo.toml | 2 +- frame/babe/Cargo.toml | 2 +- frame/bags-list/Cargo.toml | 2 +- frame/balances/Cargo.toml | 2 +- frame/beefy-mmr/Cargo.toml | 2 +- frame/beefy/Cargo.toml | 2 +- frame/benchmarking/Cargo.toml | 2 +- frame/bounties/Cargo.toml | 2 +- frame/child-bounties/Cargo.toml | 2 +- frame/collective/Cargo.toml | 2 +- frame/contracts/Cargo.toml | 2 +- frame/contracts/rpc/runtime-api/Cargo.toml | 2 +- frame/conviction-voting/Cargo.toml | 2 +- frame/democracy/Cargo.toml | 2 +- frame/election-provider-multi-phase/Cargo.toml | 2 +- frame/election-provider-support/Cargo.toml | 2 +- frame/examples/basic/Cargo.toml | 2 +- frame/examples/offchain-worker/Cargo.toml | 2 +- frame/examples/parallel/Cargo.toml | 2 +- frame/executive/Cargo.toml | 2 +- frame/gilt/Cargo.toml | 2 +- frame/grandpa/Cargo.toml | 2 +- frame/identity/Cargo.toml | 2 +- frame/im-online/Cargo.toml | 2 +- frame/indices/Cargo.toml | 2 +- frame/lottery/Cargo.toml | 2 +- frame/membership/Cargo.toml | 2 +- frame/merkle-mountain-range/Cargo.toml | 2 +- frame/multisig/Cargo.toml | 2 +- frame/nicks/Cargo.toml | 2 +- frame/node-authorization/Cargo.toml | 2 +- frame/offences/Cargo.toml | 2 +- frame/preimage/Cargo.toml | 2 +- frame/proxy/Cargo.toml | 2 +- frame/randomness-collective-flip/Cargo.toml | 2 +- frame/recovery/Cargo.toml | 2 +- frame/referenda/Cargo.toml | 2 +- frame/scheduler/Cargo.toml | 2 +- frame/scored-pool/Cargo.toml | 2 +- frame/session/Cargo.toml | 2 +- frame/session/benchmarking/Cargo.toml | 2 +- frame/society/Cargo.toml | 2 +- frame/staking/Cargo.toml | 2 +- frame/sudo/Cargo.toml | 2 +- frame/support/Cargo.toml | 2 +- frame/support/test/Cargo.toml | 2 +- frame/support/test/compile_pass/Cargo.toml | 2 +- frame/system/Cargo.toml | 2 +- frame/system/benchmarking/Cargo.toml | 2 +- frame/timestamp/Cargo.toml | 2 +- frame/tips/Cargo.toml | 2 +- frame/transaction-payment/Cargo.toml | 2 +- frame/transaction-payment/asset-tx-payment/Cargo.toml | 2 +- frame/transaction-storage/Cargo.toml | 2 +- frame/treasury/Cargo.toml | 2 +- frame/uniques/Cargo.toml | 2 +- frame/utility/Cargo.toml | 2 +- frame/vesting/Cargo.toml | 2 +- primitives/application-crypto/Cargo.toml | 2 +- primitives/arithmetic/Cargo.toml | 2 +- primitives/authority-discovery/Cargo.toml | 2 +- primitives/beefy/Cargo.toml | 2 +- primitives/consensus/aura/Cargo.toml | 2 +- primitives/consensus/babe/Cargo.toml | 2 +- primitives/core/Cargo.toml | 2 +- primitives/finality-grandpa/Cargo.toml | 2 +- primitives/npos-elections/Cargo.toml | 2 +- primitives/npos-elections/fuzzer/Cargo.toml | 2 +- primitives/npos-elections/solution-type/Cargo.toml | 2 +- primitives/runtime/Cargo.toml | 2 +- primitives/session/Cargo.toml | 2 +- primitives/staking/Cargo.toml | 2 +- primitives/transaction-storage-proof/Cargo.toml | 2 +- primitives/trie/Cargo.toml | 2 +- primitives/version/Cargo.toml | 2 +- test-utils/runtime/Cargo.toml | 2 +- utils/frame/rpc/support/Cargo.toml | 2 +- 87 files changed, 88 insertions(+), 88 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3d95343cb0b2..b5c78491628d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9095,9 +9095,9 @@ dependencies = [ [[package]] name = "scale-info" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d3b4d0b178e3af536f7988303bc73a0766c816de2138c08262015f8ec7be568" +checksum = "0563970d79bcbf3c537ce3ad36d859b30d36fc5b190efd227f1f7a84d7cf0d42" dependencies = [ "bitvec", "cfg-if 1.0.0", diff --git a/bin/node-template/pallets/template/Cargo.toml b/bin/node-template/pallets/template/Cargo.toml index ffc02dbd96f6..686dd38b577b 100644 --- a/bin/node-template/pallets/template/Cargo.toml +++ b/bin/node-template/pallets/template/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", ] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } frame-support = { default-features = false, version = "4.0.0-dev", path = "../../../../frame/support" } frame-system = { default-features = false, version = "4.0.0-dev", path = "../../../../frame/system" } frame-benchmarking = { default-features = false, version = "4.0.0-dev", path = "../../../../frame/benchmarking", optional = true } diff --git a/bin/node-template/runtime/Cargo.toml b/bin/node-template/runtime/Cargo.toml index d20a6c39aa5d..f4ff87729082 100644 --- a/bin/node-template/runtime/Cargo.toml +++ b/bin/node-template/runtime/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } pallet-aura = { version = "4.0.0-dev", default-features = false, path = "../../../frame/aura" } pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../../../frame/balances" } diff --git a/bin/node/executor/Cargo.toml b/bin/node/executor/Cargo.toml index e29ffd9b671f..21862ecf81b5 100644 --- a/bin/node/executor/Cargo.toml +++ b/bin/node/executor/Cargo.toml @@ -13,7 +13,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0" } -scale-info = { version = "2.0.0", features = ["derive"] } +scale-info = { version = "2.0.1", features = ["derive"] } node-primitives = { version = "2.0.0", path = "../primitives" } node-runtime = { version = "3.0.0-dev", path = "../runtime" } sc-executor = { version = "0.10.0-dev", path = "../../../client/executor" } diff --git a/bin/node/primitives/Cargo.toml b/bin/node/primitives/Cargo.toml index 0d49d4a247c0..711b30d33933 100644 --- a/bin/node/primitives/Cargo.toml +++ b/bin/node/primitives/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", ] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../../frame/system" } sp-application-crypto = { version = "6.0.0", default-features = false, path = "../../../primitives/application-crypto" } sp-core = { version = "6.0.0", default-features = false, path = "../../../primitives/core" } diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 2d2c903f70ca..e7bd50c3d189 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -18,7 +18,7 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = "derive", "max-encoded-len", ] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } static_assertions = "1.1.0" hex-literal = { version = "0.3.4", optional = true } log = { version = "0.4.14", default-features = false } diff --git a/frame/assets/Cargo.toml b/frame/assets/Cargo.toml index b69b53a095eb..d3685e658232 100644 --- a/frame/assets/Cargo.toml +++ b/frame/assets/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } # Needed for various traits. In our case, `OnFinalize`. sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } diff --git a/frame/atomic-swap/Cargo.toml b/frame/atomic-swap/Cargo.toml index 9be0868760dd..361b7d5833e6 100644 --- a/frame/atomic-swap/Cargo.toml +++ b/frame/atomic-swap/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } diff --git a/frame/aura/Cargo.toml b/frame/aura/Cargo.toml index d6d792886c2f..96cfade56cc0 100644 --- a/frame/aura/Cargo.toml +++ b/frame/aura/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-application-crypto = { version = "6.0.0", default-features = false, path = "../../primitives/application-crypto" } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/frame/authority-discovery/Cargo.toml b/frame/authority-discovery/Cargo.toml index c44134190e8a..d379bdda6cf8 100644 --- a/frame/authority-discovery/Cargo.toml +++ b/frame/authority-discovery/Cargo.toml @@ -18,7 +18,7 @@ sp-application-crypto = { version = "6.0.0", default-features = false, path = ". codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", ] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } pallet-session = { version = "4.0.0-dev", features = [ "historical", diff --git a/frame/authorship/Cargo.toml b/frame/authorship/Cargo.toml index adeebf0e4b37..77a44f5b5dd7 100644 --- a/frame/authorship/Cargo.toml +++ b/frame/authorship/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", ] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-authorship = { version = "4.0.0-dev", default-features = false, path = "../../primitives/authorship" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } diff --git a/frame/babe/Cargo.toml b/frame/babe/Cargo.toml index d4447ba33855..a13a2d71f25d 100644 --- a/frame/babe/Cargo.toml +++ b/frame/babe/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/bags-list/Cargo.toml b/frame/bags-list/Cargo.toml index f96048d7fcb8..87b8d7939e12 100644 --- a/frame/bags-list/Cargo.toml +++ b/frame/bags-list/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] # parity codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } # primitives sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } diff --git a/frame/balances/Cargo.toml b/frame/balances/Cargo.toml index d0a6f2699ab3..a0de11638e66 100644 --- a/frame/balances/Cargo.toml +++ b/frame/balances/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } diff --git a/frame/beefy-mmr/Cargo.toml b/frame/beefy-mmr/Cargo.toml index c6d3b1b165fa..19703fa79863 100644 --- a/frame/beefy-mmr/Cargo.toml +++ b/frame/beefy-mmr/Cargo.toml @@ -12,7 +12,7 @@ hex = { version = "0.4", optional = true } codec = { version = "3.0.0", package = "parity-scale-codec", default-features = false, features = ["derive"] } k256 = { version = "0.10.2", default-features = false, features = ["arithmetic"] } log = { version = "0.4.13", default-features = false } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } serde = { version = "1.0.136", optional = true } frame-support = { version = "4.0.0-dev", path = "../support", default-features = false } diff --git a/frame/beefy/Cargo.toml b/frame/beefy/Cargo.toml index dc7ef8eda86b..6ed9e7375bfe 100644 --- a/frame/beefy/Cargo.toml +++ b/frame/beefy/Cargo.toml @@ -9,7 +9,7 @@ description = "BEEFY FRAME pallet" [dependencies] codec = { version = "3.0.0", package = "parity-scale-codec", default-features = false, features = ["derive"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } serde = { version = "1.0.136", optional = true } frame-support = { version = "4.0.0-dev", path = "../support", default-features = false } diff --git a/frame/benchmarking/Cargo.toml b/frame/benchmarking/Cargo.toml index 37259f351e9f..ce301ff9034a 100644 --- a/frame/benchmarking/Cargo.toml +++ b/frame/benchmarking/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] linregress = { version = "0.4.4", optional = true } paste = "1.0" codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-api = { version = "4.0.0-dev", path = "../../primitives/api", default-features = false } sp-runtime-interface = { version = "6.0.0", path = "../../primitives/runtime-interface", default-features = false } sp-runtime = { version = "6.0.0", path = "../../primitives/runtime", default-features = false } diff --git a/frame/bounties/Cargo.toml b/frame/bounties/Cargo.toml index 7907df2209a4..a158895a252b 100644 --- a/frame/bounties/Cargo.toml +++ b/frame/bounties/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", ] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/frame/child-bounties/Cargo.toml b/frame/child-bounties/Cargo.toml index 91df3e051f1b..9d2e1031604e 100644 --- a/frame/child-bounties/Cargo.toml +++ b/frame/child-bounties/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", ] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/frame/collective/Cargo.toml b/frame/collective/Cargo.toml index 190f477dd893..c9793e155c2a 100644 --- a/frame/collective/Cargo.toml +++ b/frame/collective/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } log = { version = "0.4.14", default-features = false } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-core = { version = "6.0.0", default-features = false, path = "../../primitives/core" } sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } diff --git a/frame/contracts/Cargo.toml b/frame/contracts/Cargo.toml index ca7b8ec1aa9f..2e906b69f32f 100644 --- a/frame/contracts/Cargo.toml +++ b/frame/contracts/Cargo.toml @@ -18,7 +18,7 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = "derive", "max-encoded-len", ] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } log = { version = "0.4", default-features = false } wasm-instrument = { version = "0.1", default-features = false } serde = { version = "1", optional = true, features = ["derive"] } diff --git a/frame/contracts/rpc/runtime-api/Cargo.toml b/frame/contracts/rpc/runtime-api/Cargo.toml index 5c95cfacf76b..e50a41624e7e 100644 --- a/frame/contracts/rpc/runtime-api/Cargo.toml +++ b/frame/contracts/rpc/runtime-api/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } # Substrate Dependencies pallet-contracts-primitives = { version = "6.0.0", default-features = false, path = "../../common" } diff --git a/frame/conviction-voting/Cargo.toml b/frame/conviction-voting/Cargo.toml index a2d3bde497c4..5877bf0c5da2 100644 --- a/frame/conviction-voting/Cargo.toml +++ b/frame/conviction-voting/Cargo.toml @@ -17,7 +17,7 @@ serde = { version = "1.0.136", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", ] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } diff --git a/frame/democracy/Cargo.toml b/frame/democracy/Cargo.toml index dddfcd9e1a31..49b21d0eecdc 100644 --- a/frame/democracy/Cargo.toml +++ b/frame/democracy/Cargo.toml @@ -17,7 +17,7 @@ serde = { version = "1.0.136", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", ] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } diff --git a/frame/election-provider-multi-phase/Cargo.toml b/frame/election-provider-multi-phase/Cargo.toml index ffaad4f46669..38039f6926b1 100644 --- a/frame/election-provider-multi-phase/Cargo.toml +++ b/frame/election-provider-multi-phase/Cargo.toml @@ -17,7 +17,7 @@ static_assertions = "1.1.0" codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", ] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } log = { version = "0.4.14", default-features = false } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/frame/election-provider-support/Cargo.toml b/frame/election-provider-support/Cargo.toml index 9364dd5553ef..e66774c6b5e7 100644 --- a/frame/election-provider-support/Cargo.toml +++ b/frame/election-provider-support/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-arithmetic = { version = "5.0.0", default-features = false, path = "../../primitives/arithmetic" } sp-npos-elections = { version = "4.0.0-dev", default-features = false, path = "../../primitives/npos-elections" } diff --git a/frame/examples/basic/Cargo.toml b/frame/examples/basic/Cargo.toml index 837244811e4f..a54301944a01 100644 --- a/frame/examples/basic/Cargo.toml +++ b/frame/examples/basic/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } log = { version = "0.4.14", default-features = false } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" } diff --git a/frame/examples/offchain-worker/Cargo.toml b/frame/examples/offchain-worker/Cargo.toml index 32ca98f505b0..8daf0686d816 100644 --- a/frame/examples/offchain-worker/Cargo.toml +++ b/frame/examples/offchain-worker/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } lite-json = { version = "0.1", default-features = false } log = { version = "0.4.14", default-features = false } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" } diff --git a/frame/examples/parallel/Cargo.toml b/frame/examples/parallel/Cargo.toml index 2d5a2432e661..367b2e98aaa6 100644 --- a/frame/examples/parallel/Cargo.toml +++ b/frame/examples/parallel/Cargo.toml @@ -13,7 +13,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" } diff --git a/frame/executive/Cargo.toml b/frame/executive/Cargo.toml index 5613b4256236..f920affaab20 100644 --- a/frame/executive/Cargo.toml +++ b/frame/executive/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", ] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } diff --git a/frame/gilt/Cargo.toml b/frame/gilt/Cargo.toml index f47166fb3d08..837504e516ce 100644 --- a/frame/gilt/Cargo.toml +++ b/frame/gilt/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } sp-arithmetic = { version = "5.0.0", default-features = false, path = "../../primitives/arithmetic" } diff --git a/frame/grandpa/Cargo.toml b/frame/grandpa/Cargo.toml index ee5fa5e52b8e..cad238a4e365 100644 --- a/frame/grandpa/Cargo.toml +++ b/frame/grandpa/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-application-crypto = { version = "6.0.0", default-features = false, path = "../../primitives/application-crypto" } sp-core = { version = "6.0.0", default-features = false, path = "../../primitives/core" } sp-finality-grandpa = { version = "4.0.0-dev", default-features = false, path = "../../primitives/finality-grandpa" } diff --git a/frame/identity/Cargo.toml b/frame/identity/Cargo.toml index 7159c71644fb..7ebfda7cf176 100644 --- a/frame/identity/Cargo.toml +++ b/frame/identity/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } enumflags2 = { version = "0.6.2" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } diff --git a/frame/im-online/Cargo.toml b/frame/im-online/Cargo.toml index 86d7d9a05341..277d4d2fb2de 100644 --- a/frame/im-online/Cargo.toml +++ b/frame/im-online/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] sp-application-crypto = { version = "6.0.0", default-features = false, path = "../../primitives/application-crypto" } pallet-authorship = { version = "4.0.0-dev", default-features = false, path = "../authorship" } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-core = { version = "6.0.0", default-features = false, path = "../../primitives/core" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } diff --git a/frame/indices/Cargo.toml b/frame/indices/Cargo.toml index d651bcc15c06..690fc9db14f9 100644 --- a/frame/indices/Cargo.toml +++ b/frame/indices/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-keyring = { version = "6.0.0", optional = true, path = "../../primitives/keyring" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } diff --git a/frame/lottery/Cargo.toml b/frame/lottery/Cargo.toml index ad94b0935ffd..7932abdc21a0 100644 --- a/frame/lottery/Cargo.toml +++ b/frame/lottery/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", ] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/frame/membership/Cargo.toml b/frame/membership/Cargo.toml index 6f654bfbe858..40ad619e904c 100644 --- a/frame/membership/Cargo.toml +++ b/frame/membership/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } log = { version = "0.4.0", default-features = false } sp-core = { version = "6.0.0", default-features = false, path = "../../primitives/core" } diff --git a/frame/merkle-mountain-range/Cargo.toml b/frame/merkle-mountain-range/Cargo.toml index c0e1f6702c73..796ab98dc2c3 100644 --- a/frame/merkle-mountain-range/Cargo.toml +++ b/frame/merkle-mountain-range/Cargo.toml @@ -13,7 +13,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } mmr-lib = { package = "ckb-merkle-mountain-range", default-features = false, version = "0.3.2" } sp-core = { version = "6.0.0", default-features = false, path = "../../primitives/core" } diff --git a/frame/multisig/Cargo.toml b/frame/multisig/Cargo.toml index 67da75a137f9..a2188ca18b3b 100644 --- a/frame/multisig/Cargo.toml +++ b/frame/multisig/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } diff --git a/frame/nicks/Cargo.toml b/frame/nicks/Cargo.toml index fa6dd3395a09..9e98864d24f9 100644 --- a/frame/nicks/Cargo.toml +++ b/frame/nicks/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } diff --git a/frame/node-authorization/Cargo.toml b/frame/node-authorization/Cargo.toml index 67c39ca4e350..6ae1f21336b6 100644 --- a/frame/node-authorization/Cargo.toml +++ b/frame/node-authorization/Cargo.toml @@ -13,7 +13,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } sp-core = { version = "6.0.0", default-features = false, path = "../../primitives/core" } diff --git a/frame/offences/Cargo.toml b/frame/offences/Cargo.toml index 93ece2ae7fd2..01409d78053c 100644 --- a/frame/offences/Cargo.toml +++ b/frame/offences/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../balances" } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } serde = { version = "1.0.136", optional = true } sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } diff --git a/frame/preimage/Cargo.toml b/frame/preimage/Cargo.toml index 70c5292f7f8c..58809f9e9896 100644 --- a/frame/preimage/Cargo.toml +++ b/frame/preimage/Cargo.toml @@ -11,7 +11,7 @@ readme = "README.md" [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } diff --git a/frame/proxy/Cargo.toml b/frame/proxy/Cargo.toml index 6f1dd15ed6b3..bdc39a81e34a 100644 --- a/frame/proxy/Cargo.toml +++ b/frame/proxy/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["max-encoded-len"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } diff --git a/frame/randomness-collective-flip/Cargo.toml b/frame/randomness-collective-flip/Cargo.toml index d05bcd534ec4..17d4ff461aa0 100644 --- a/frame/randomness-collective-flip/Cargo.toml +++ b/frame/randomness-collective-flip/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] safe-mix = { version = "1.0", default-features = false } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } diff --git a/frame/recovery/Cargo.toml b/frame/recovery/Cargo.toml index 6bba8102af2e..0a173fe2c9da 100644 --- a/frame/recovery/Cargo.toml +++ b/frame/recovery/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } diff --git a/frame/referenda/Cargo.toml b/frame/referenda/Cargo.toml index 080e4d7ab778..d85503a741f4 100644 --- a/frame/referenda/Cargo.toml +++ b/frame/referenda/Cargo.toml @@ -17,7 +17,7 @@ serde = { version = "1.0.136", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", ] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" } sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } diff --git a/frame/scheduler/Cargo.toml b/frame/scheduler/Cargo.toml index f08a0318a702..9000d1f693cc 100644 --- a/frame/scheduler/Cargo.toml +++ b/frame/scheduler/Cargo.toml @@ -11,7 +11,7 @@ readme = "README.md" [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } log = { version = "0.4.14", default-features = false } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } diff --git a/frame/scored-pool/Cargo.toml b/frame/scored-pool/Cargo.toml index 203c06065c35..73fd25158ca8 100644 --- a/frame/scored-pool/Cargo.toml +++ b/frame/scored-pool/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } diff --git a/frame/session/Cargo.toml b/frame/session/Cargo.toml index 4302c6a44cb0..647b3482b202 100644 --- a/frame/session/Cargo.toml +++ b/frame/session/Cargo.toml @@ -17,7 +17,7 @@ log = { version = "0.4.0", default-features = false } impl-trait-for-tuples = "0.2.1" codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-core = { version = "6.0.0", default-features = false, path = "../../primitives/core" } diff --git a/frame/session/benchmarking/Cargo.toml b/frame/session/benchmarking/Cargo.toml index 23336e647b02..b00d1335d22a 100644 --- a/frame/session/benchmarking/Cargo.toml +++ b/frame/session/benchmarking/Cargo.toml @@ -27,7 +27,7 @@ pallet-staking = { version = "4.0.0-dev", default-features = false, features = [ [dev-dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"] } -scale-info = "2.0.0" +scale-info = "2.0.1" sp-core = { version = "6.0.0", path = "../../../primitives/core" } sp-io = { version = "6.0.0", path = "../../../primitives/io" } pallet-balances = { version = "4.0.0-dev", path = "../../balances" } diff --git a/frame/society/Cargo.toml b/frame/society/Cargo.toml index cd3afdb9beeb..1fd9693d0d00 100644 --- a/frame/society/Cargo.toml +++ b/frame/society/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/frame/staking/Cargo.toml b/frame/staking/Cargo.toml index abe977a70eaa..073d959e2d1d 100644 --- a/frame/staking/Cargo.toml +++ b/frame/staking/Cargo.toml @@ -17,7 +17,7 @@ serde = { version = "1.0.136", optional = true } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", ] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } diff --git a/frame/sudo/Cargo.toml b/frame/sudo/Cargo.toml index 17d6ef4da489..b209351ddaf0 100644 --- a/frame/sudo/Cargo.toml +++ b/frame/sudo/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } diff --git a/frame/support/Cargo.toml b/frame/support/Cargo.toml index 796df7697d74..3161e4f4db69 100644 --- a/frame/support/Cargo.toml +++ b/frame/support/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.136", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } frame-metadata = { version = "15.0.0", default-features = false, features = ["v14"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } diff --git a/frame/support/test/Cargo.toml b/frame/support/test/Cargo.toml index ef20915899fd..d99889cf99bc 100644 --- a/frame/support/test/Cargo.toml +++ b/frame/support/test/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.136", default-features = false, features = ["derive"] } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-arithmetic = { version = "5.0.0", default-features = false, path = "../../../primitives/arithmetic" } sp-io = { version = "6.0.0", path = "../../../primitives/io", default-features = false } sp-state-machine = { version = "0.12.0", optional = true, path = "../../../primitives/state-machine" } diff --git a/frame/support/test/compile_pass/Cargo.toml b/frame/support/test/compile_pass/Cargo.toml index 33ee3e8c2d07..5850d2e5db14 100644 --- a/frame/support/test/compile_pass/Cargo.toml +++ b/frame/support/test/compile_pass/Cargo.toml @@ -13,7 +13,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-core = { version = "6.0.0", default-features = false, path = "../../../../primitives/core" } sp-runtime = { version = "6.0.0", default-features = false, path = "../../../../primitives/runtime" } sp-version = { version = "5.0.0", default-features = false, path = "../../../../primitives/version" } diff --git a/frame/system/Cargo.toml b/frame/system/Cargo.toml index a5a65e403454..e9196c4eb94f 100644 --- a/frame/system/Cargo.toml +++ b/frame/system/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.136", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-core = { version = "6.0.0", default-features = false, path = "../../primitives/core" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "6.0.0", path = "../../primitives/io", default-features = false } diff --git a/frame/system/benchmarking/Cargo.toml b/frame/system/benchmarking/Cargo.toml index 7ca76c260c43..c543d5af0412 100644 --- a/frame/system/benchmarking/Cargo.toml +++ b/frame/system/benchmarking/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } sp-runtime = { version = "6.0.0", default-features = false, path = "../../../primitives/runtime" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../../benchmarking" } diff --git a/frame/timestamp/Cargo.toml b/frame/timestamp/Cargo.toml index 1652be977674..72d632faf858 100644 --- a/frame/timestamp/Cargo.toml +++ b/frame/timestamp/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io", optional = true } sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } diff --git a/frame/tips/Cargo.toml b/frame/tips/Cargo.toml index 017d86ea72b3..dc65d5c28d1c 100644 --- a/frame/tips/Cargo.toml +++ b/frame/tips/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } log = { version = "0.4.0", default-features = false } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } serde = { version = "1.0.136", features = ["derive"], optional = true } sp-core = { version = "6.0.0", default-features = false, path = "../../primitives/core" } diff --git a/frame/transaction-payment/Cargo.toml b/frame/transaction-payment/Cargo.toml index 5ac9ea1e713c..ea894e7cada6 100644 --- a/frame/transaction-payment/Cargo.toml +++ b/frame/transaction-payment/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", ] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } serde = { version = "1.0.136", optional = true } smallvec = "1.8.0" diff --git a/frame/transaction-payment/asset-tx-payment/Cargo.toml b/frame/transaction-payment/asset-tx-payment/Cargo.toml index da30136c067a..ec07fc967c92 100644 --- a/frame/transaction-payment/asset-tx-payment/Cargo.toml +++ b/frame/transaction-payment/asset-tx-payment/Cargo.toml @@ -25,7 +25,7 @@ pallet-transaction-payment = { version = "4.0.0-dev", default-features = false, # Other dependencies codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } serde = { version = "1.0.136", optional = true } [dev-dependencies] diff --git a/frame/transaction-storage/Cargo.toml b/frame/transaction-storage/Cargo.toml index b4ec343dc621..eec505708ed7 100644 --- a/frame/transaction-storage/Cargo.toml +++ b/frame/transaction-storage/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] serde = { version = "1.0.136", optional = true } hex-literal = { version = "0.3.4", optional = true } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../balances" } diff --git a/frame/treasury/Cargo.toml b/frame/treasury/Cargo.toml index ca32f4713ee2..f848f48acd25 100644 --- a/frame/treasury/Cargo.toml +++ b/frame/treasury/Cargo.toml @@ -17,7 +17,7 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = "derive", "max-encoded-len", ] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } serde = { version = "1.0.136", features = ["derive"], optional = true } impl-trait-for-tuples = "0.2.1" diff --git a/frame/uniques/Cargo.toml b/frame/uniques/Cargo.toml index 6f4e8f91b26f..b0abb814eb5a 100644 --- a/frame/uniques/Cargo.toml +++ b/frame/uniques/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/frame/utility/Cargo.toml b/frame/utility/Cargo.toml index f059937ad2d9..6235d1ee1555 100644 --- a/frame/utility/Cargo.toml +++ b/frame/utility/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } sp-core = { version = "6.0.0", default-features = false, path = "../../primitives/core" } diff --git a/frame/vesting/Cargo.toml b/frame/vesting/Cargo.toml index 36a877478a4e..83f897847f79 100644 --- a/frame/vesting/Cargo.toml +++ b/frame/vesting/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive", ] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/primitives/application-crypto/Cargo.toml b/primitives/application-crypto/Cargo.toml index 7ac487fe35d2..a8181ca5380c 100644 --- a/primitives/application-crypto/Cargo.toml +++ b/primitives/application-crypto/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-core = { version = "6.0.0", default-features = false, path = "../core" } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } serde = { version = "1.0.136", optional = true, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-io = { version = "6.0.0", default-features = false, path = "../io" } diff --git a/primitives/arithmetic/Cargo.toml b/primitives/arithmetic/Cargo.toml index 654127671466..26ee7677363c 100644 --- a/primitives/arithmetic/Cargo.toml +++ b/primitives/arithmetic/Cargo.toml @@ -19,7 +19,7 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = "derive", "max-encoded-len", ] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } integer-sqrt = "0.1.2" static_assertions = "1.1.0" num-traits = { version = "0.2.8", default-features = false } diff --git a/primitives/authority-discovery/Cargo.toml b/primitives/authority-discovery/Cargo.toml index 687987ab2ec9..c452aaa89202 100644 --- a/primitives/authority-discovery/Cargo.toml +++ b/primitives/authority-discovery/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-application-crypto = { version = "6.0.0", default-features = false, path = "../application-crypto" } codec = { package = "parity-scale-codec", default-features = false, version = "3.0.0" } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } sp-runtime = { version = "6.0.0", default-features = false, path = "../runtime" } diff --git a/primitives/beefy/Cargo.toml b/primitives/beefy/Cargo.toml index 9012803a902d..4aa53aff2c3c 100644 --- a/primitives/beefy/Cargo.toml +++ b/primitives/beefy/Cargo.toml @@ -9,7 +9,7 @@ description = "Primitives for BEEFY protocol." [dependencies] codec = { version = "3.0.0", package = "parity-scale-codec", default-features = false, features = ["derive"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-api = { version = "4.0.0-dev", path = "../api", default-features = false } sp-application-crypto = { version = "6.0.0", path = "../application-crypto", default-features = false } diff --git a/primitives/consensus/aura/Cargo.toml b/primitives/consensus/aura/Cargo.toml index 28f68f15cd9e..2c4a2f0a0de9 100644 --- a/primitives/consensus/aura/Cargo.toml +++ b/primitives/consensus/aura/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-application-crypto = { version = "6.0.0", default-features = false, path = "../../application-crypto" } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../std" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../api" } sp-runtime = { version = "6.0.0", default-features = false, path = "../../runtime" } diff --git a/primitives/consensus/babe/Cargo.toml b/primitives/consensus/babe/Cargo.toml index 46bb51a061e6..189dc5b2e80f 100644 --- a/primitives/consensus/babe/Cargo.toml +++ b/primitives/consensus/babe/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-application-crypto = { version = "6.0.0", default-features = false, path = "../../application-crypto" } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } merlin = { version = "2.0", default-features = false } sp-std = { version = "4.0.0", default-features = false, path = "../../std" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../api" } diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index 70ae11cf543b..1effb8efbf5a 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -17,7 +17,7 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = "derive", "max-encoded-len", ] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } log = { version = "0.4.11", default-features = false } serde = { version = "1.0.136", optional = true, features = ["derive"] } byteorder = { version = "1.3.2", default-features = false } diff --git a/primitives/finality-grandpa/Cargo.toml b/primitives/finality-grandpa/Cargo.toml index 671168ef90b8..ebc067e630c1 100644 --- a/primitives/finality-grandpa/Cargo.toml +++ b/primitives/finality-grandpa/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } grandpa = { package = "finality-grandpa", version = "0.15.0", default-features = false, features = ["derive-codec"] } log = { version = "0.4.8", optional = true } serde = { version = "1.0.136", optional = true, features = ["derive"] } diff --git a/primitives/npos-elections/Cargo.toml b/primitives/npos-elections/Cargo.toml index b96b38695859..3facf32196c7 100644 --- a/primitives/npos-elections/Cargo.toml +++ b/primitives/npos-elections/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } serde = { version = "1.0.136", optional = true, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-npos-elections-solution-type = { version = "4.0.0-dev", path = "./solution-type" } diff --git a/primitives/npos-elections/fuzzer/Cargo.toml b/primitives/npos-elections/fuzzer/Cargo.toml index 6ad59d807fa5..afa331b0676e 100644 --- a/primitives/npos-elections/fuzzer/Cargo.toml +++ b/primitives/npos-elections/fuzzer/Cargo.toml @@ -19,7 +19,7 @@ honggfuzz = "0.5" rand = { version = "0.8", features = ["std", "small_rng"] } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-npos-elections = { version = "4.0.0-dev", path = ".." } sp-runtime = { version = "6.0.0", path = "../../runtime" } diff --git a/primitives/npos-elections/solution-type/Cargo.toml b/primitives/npos-elections/solution-type/Cargo.toml index fcd39437945f..813637e89c33 100644 --- a/primitives/npos-elections/solution-type/Cargo.toml +++ b/primitives/npos-elections/solution-type/Cargo.toml @@ -22,7 +22,7 @@ proc-macro-crate = "1.1.0" [dev-dependencies] parity-scale-codec = "3.0.0" -scale-info = "2.0.0" +scale-info = "2.0.1" sp-arithmetic = { path = "../../arithmetic", version = "5.0.0"} # used by generate_solution_type: sp-npos-elections = { path = "..", version = "4.0.0-dev" } diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 91bf6d36b0a7..5f7b45ba15a8 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.136", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-core = { version = "6.0.0", default-features = false, path = "../core" } sp-application-crypto = { version = "6.0.0", default-features = false, path = "../application-crypto" } sp-arithmetic = { version = "5.0.0", default-features = false, path = "../arithmetic" } diff --git a/primitives/session/Cargo.toml b/primitives/session/Cargo.toml index 9ffaa2cf3bdd..476bacc88ae3 100644 --- a/primitives/session/Cargo.toml +++ b/primitives/session/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } sp-core = { version = "6.0.0", default-features = false, path = "../core" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } diff --git a/primitives/staking/Cargo.toml b/primitives/staking/Cargo.toml index 2cb1ae0938a8..7761519dabef 100644 --- a/primitives/staking/Cargo.toml +++ b/primitives/staking/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-runtime = { version = "6.0.0", default-features = false, path = "../runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } diff --git a/primitives/transaction-storage-proof/Cargo.toml b/primitives/transaction-storage-proof/Cargo.toml index 803ec67f571c..966142a7e14f 100644 --- a/primitives/transaction-storage-proof/Cargo.toml +++ b/primitives/transaction-storage-proof/Cargo.toml @@ -19,7 +19,7 @@ sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-trie = { version = "6.0.0", optional = true, path = "../trie" } sp-core = { version = "6.0.0", path = "../core", optional = true } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } log = { version = "0.4.8", optional = true } async-trait = { version = "0.1.50", optional = true } diff --git a/primitives/trie/Cargo.toml b/primitives/trie/Cargo.toml index dfe3150194a3..f434a15b8964 100644 --- a/primitives/trie/Cargo.toml +++ b/primitives/trie/Cargo.toml @@ -19,7 +19,7 @@ harness = false [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../std" } hash-db = { version = "0.15.2", default-features = false } trie-db = { version = "0.23.1", default-features = false } diff --git a/primitives/version/Cargo.toml b/primitives/version/Cargo.toml index 8518dfffa5db..7488d924070c 100644 --- a/primitives/version/Cargo.toml +++ b/primitives/version/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] impl-serde = { version = "0.3.1", optional = true } serde = { version = "1.0.136", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-runtime = { version = "6.0.0", default-features = false, path = "../runtime" } sp-version-proc-macro = { version = "4.0.0-dev", default-features = false, path = "proc-macro" } diff --git a/test-utils/runtime/Cargo.toml b/test-utils/runtime/Cargo.toml index 9bf66a64db42..8c61cbbf8adb 100644 --- a/test-utils/runtime/Cargo.toml +++ b/test-utils/runtime/Cargo.toml @@ -18,7 +18,7 @@ sp-consensus-aura = { version = "0.10.0-dev", default-features = false, path = " sp-consensus-babe = { version = "0.10.0-dev", default-features = false, path = "../../primitives/consensus/babe" } sp-block-builder = { version = "4.0.0-dev", default-features = false, path = "../../primitives/block-builder" } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../primitives/inherents" } sp-keyring = { version = "6.0.0", optional = true, path = "../../primitives/keyring" } memory-db = { version = "0.29.0", default-features = false } diff --git a/utils/frame/rpc/support/Cargo.toml b/utils/frame/rpc/support/Cargo.toml index f1cf00153f3b..0055ef47f8f4 100644 --- a/utils/frame/rpc/support/Cargo.toml +++ b/utils/frame/rpc/support/Cargo.toml @@ -25,5 +25,5 @@ sc-rpc-api = { version = "0.10.0-dev", path = "../../../../client/rpc-api" } [dev-dependencies] frame-system = { version = "4.0.0-dev", path = "../../../../frame/system" } -scale-info = "2.0.0" +scale-info = "2.0.1" tokio = "1.15" From e41027bb59f985b32a1100b6790b2c99458b2afc Mon Sep 17 00:00:00 2001 From: Sergejs Kostjucenko <85877331+sergejparity@users.noreply.github.com> Date: Thu, 3 Mar 2022 10:59:42 +0200 Subject: [PATCH 554/695] Add pr-custom-review config (#10968) --- .github/pr-custom-review.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .github/pr-custom-review.yml diff --git a/.github/pr-custom-review.yml b/.github/pr-custom-review.yml new file mode 100644 index 000000000000..615203c11c15 --- /dev/null +++ b/.github/pr-custom-review.yml @@ -0,0 +1,18 @@ +rules: + - name: Changed runtime files + condition: .*/runtime/.*lib.rs + check_type: changed_files + min_approvals: 2 + teams: + - substrateteamleads + + - name: Substrate developers + check_type: changed_files + condition: .* + any: + - min_approvals: 2 + teams: + - core-devs + - min_approvals: 1 + teams: + - substrateteamleads \ No newline at end of file From 21cadf1af453716aea1e5362c83aa314811da657 Mon Sep 17 00:00:00 2001 From: Falco Hirschenberger Date: Thu, 3 Mar 2022 10:17:24 +0100 Subject: [PATCH 555/695] Revise how staking configurations are set (#10955) * Revise how staking configurations are set fixes #10938 * Fix and add additional tests * Format * Formatting * Add doc Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> * Update frame/staking/src/tests.rs Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> * Format * Fix build * Update weights.rs * cargo run --quiet --profile=production --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_staking --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/staking/src/weights.rs --template=./.maintain/frame-weight-template.hbs Co-authored-by: Shawn Tabrizi Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Co-authored-by: Parity Bot --- frame/staking/src/benchmarking.rs | 49 ++++-- frame/staking/src/pallet/mod.rs | 56 +++++-- frame/staking/src/tests.rs | 138 ++++++++++------ frame/staking/src/weights.rs | 253 ++++++++++++++++-------------- 4 files changed, 308 insertions(+), 188 deletions(-) diff --git a/frame/staking/src/benchmarking.rs b/frame/staking/src/benchmarking.rs index 7593522055fb..ec7d36c820f3 100644 --- a/frame/staking/src/benchmarking.rs +++ b/frame/staking/src/benchmarking.rs @@ -18,7 +18,7 @@ //! Staking pallet benchmarking. use super::*; -use crate::Pallet as Staking; +use crate::{ConfigOp, Pallet as Staking}; use testing_utils::*; use codec::Decode; @@ -852,16 +852,15 @@ benchmarks! { assert_eq!(targets.len() as u32, v); } - set_staking_configs { - // This function always does the same thing... just write to 4 storage items. - }: _( + set_staking_configs_all_set { + }: set_staking_configs( RawOrigin::Root, - BalanceOf::::max_value(), - BalanceOf::::max_value(), - Some(u32::MAX), - Some(u32::MAX), - Some(Percent::max_value()), - Perbill::max_value() + ConfigOp::Set(BalanceOf::::max_value()), + ConfigOp::Set(BalanceOf::::max_value()), + ConfigOp::Set(u32::MAX), + ConfigOp::Set(u32::MAX), + ConfigOp::Set(Percent::max_value()), + ConfigOp::Set(Perbill::max_value()) ) verify { assert_eq!(MinNominatorBond::::get(), BalanceOf::::max_value()); assert_eq!(MinValidatorBond::::get(), BalanceOf::::max_value()); @@ -871,6 +870,24 @@ benchmarks! { assert_eq!(MinCommission::::get(), Perbill::from_percent(100)); } + set_staking_configs_all_remove { + }: set_staking_configs( + RawOrigin::Root, + ConfigOp::Remove, + ConfigOp::Remove, + ConfigOp::Remove, + ConfigOp::Remove, + ConfigOp::Remove, + ConfigOp::Remove + ) verify { + assert!(!MinNominatorBond::::exists()); + assert!(!MinValidatorBond::::exists()); + assert!(!MaxNominatorsCount::::exists()); + assert!(!MaxValidatorsCount::::exists()); + assert!(!ChillThreshold::::exists()); + assert!(!MinCommission::::exists()); + } + chill_other { // clean up any existing state. clear_validators_and_nominators::(); @@ -886,12 +903,12 @@ benchmarks! { Staking::::set_staking_configs( RawOrigin::Root.into(), - BalanceOf::::max_value(), - BalanceOf::::max_value(), - Some(0), - Some(0), - Some(Percent::from_percent(0)), - Zero::zero(), + ConfigOp::Set(BalanceOf::::max_value()), + ConfigOp::Set(BalanceOf::::max_value()), + ConfigOp::Set(0), + ConfigOp::Set(0), + ConfigOp::Set(Percent::from_percent(0)), + ConfigOp::Set(Zero::zero()), )?; let caller = whitelisted_caller(); diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index eb8dab7ce6bb..58f9fd237263 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -19,6 +19,7 @@ use frame_election_provider_support::SortedListProvider; use frame_support::{ + dispatch::Codec, pallet_prelude::*, traits::{ Currency, CurrencyToVote, DefensiveSaturating, EnsureOrigin, EstimateNextNewSession, Get, @@ -32,7 +33,7 @@ use sp_runtime::{ DispatchError, Perbill, Percent, }; use sp_staking::{EraIndex, SessionIndex}; -use sp_std::{convert::From, prelude::*}; +use sp_std::{cmp::max, convert::From, prelude::*}; mod impls; @@ -60,6 +61,17 @@ pub mod pallet { #[pallet::without_storage_info] pub struct Pallet(_); + /// Possible operations on the configuration values of this pallet. + #[derive(TypeInfo, Debug, Clone, Encode, Decode, PartialEq)] + pub enum ConfigOp { + /// Don't change. + Noop, + /// Set the given value. + Set(T), + /// Remove from storage. + Remove, + } + #[pallet::config] pub trait Config: frame_system::Config + SendTransactionTypes> { /// The staking balance. @@ -1532,23 +1544,39 @@ pub mod pallet { /// /// NOTE: Existing nominators and validators will not be affected by this update. /// to kick people under the new limits, `chill_other` should be called. - #[pallet::weight(T::WeightInfo::set_staking_configs())] + // We assume the worst case for this call is either: all items are set or all items are + // removed. + #[pallet::weight(max( + T::WeightInfo::set_staking_configs_all_set(), + T::WeightInfo::set_staking_configs_all_remove() + ))] pub fn set_staking_configs( origin: OriginFor, - min_nominator_bond: BalanceOf, - min_validator_bond: BalanceOf, - max_nominator_count: Option, - max_validator_count: Option, - chill_threshold: Option, - min_commission: Perbill, + min_nominator_bond: ConfigOp>, + min_validator_bond: ConfigOp>, + max_nominator_count: ConfigOp, + max_validator_count: ConfigOp, + chill_threshold: ConfigOp, + min_commission: ConfigOp, ) -> DispatchResult { ensure_root(origin)?; - MinNominatorBond::::set(min_nominator_bond); - MinValidatorBond::::set(min_validator_bond); - MaxNominatorsCount::::set(max_nominator_count); - MaxValidatorsCount::::set(max_validator_count); - ChillThreshold::::set(chill_threshold); - MinCommission::::set(min_commission); + + macro_rules! config_op_exp { + ($storage:ty, $op:ident) => { + match $op { + ConfigOp::Noop => (), + ConfigOp::Set(v) => <$storage>::put(v), + ConfigOp::Remove => <$storage>::kill(), + } + }; + } + + config_op_exp!(MinNominatorBond, min_nominator_bond); + config_op_exp!(MinValidatorBond, min_validator_bond); + config_op_exp!(MaxNominatorsCount, max_nominator_count); + config_op_exp!(MaxValidatorsCount, max_validator_count); + config_op_exp!(ChillThreshold, chill_threshold); + config_op_exp!(MinCommission, min_commission); Ok(()) } diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 0f979f1d5922..2b2a32e0edab 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -17,10 +17,10 @@ //! Tests for the module. -use super::{Event, MaxUnlockingChunks, *}; +use super::{ConfigOp, Event, MaxUnlockingChunks, *}; use frame_election_provider_support::{ElectionProvider, SortedListProvider, Support}; use frame_support::{ - assert_noop, assert_ok, bounded_vec, + assert_noop, assert_ok, assert_storage_noop, bounded_vec, dispatch::WithPostDispatchInfo, pallet_prelude::*, traits::{Currency, Get, ReservableCurrency}, @@ -40,6 +40,56 @@ use sp_staking::{ use sp_std::prelude::*; use substrate_test_utils::assert_eq_uvec; +#[test] +fn set_staking_configs_works() { + ExtBuilder::default().build_and_execute(|| { + // setting works + assert_ok!(Staking::set_staking_configs( + Origin::root(), + ConfigOp::Set(1_500), + ConfigOp::Set(2_000), + ConfigOp::Set(10), + ConfigOp::Set(20), + ConfigOp::Set(Percent::from_percent(75)), + ConfigOp::Set(Zero::zero()) + )); + assert_eq!(MinNominatorBond::::get(), 1_500); + assert_eq!(MinValidatorBond::::get(), 2_000); + assert_eq!(MaxNominatorsCount::::get(), Some(10)); + assert_eq!(MaxValidatorsCount::::get(), Some(20)); + assert_eq!(ChillThreshold::::get(), Some(Percent::from_percent(75))); + assert_eq!(MinCommission::::get(), Perbill::from_percent(0)); + + // noop does nothing + assert_storage_noop!(assert_ok!(Staking::set_staking_configs( + Origin::root(), + ConfigOp::Noop, + ConfigOp::Noop, + ConfigOp::Noop, + ConfigOp::Noop, + ConfigOp::Noop, + ConfigOp::Noop + ))); + + // removing works + assert_ok!(Staking::set_staking_configs( + Origin::root(), + ConfigOp::Remove, + ConfigOp::Remove, + ConfigOp::Remove, + ConfigOp::Remove, + ConfigOp::Remove, + ConfigOp::Remove + )); + assert_eq!(MinNominatorBond::::get(), 0); + assert_eq!(MinValidatorBond::::get(), 0); + assert_eq!(MaxNominatorsCount::::get(), None); + assert_eq!(MaxValidatorsCount::::get(), None); + assert_eq!(ChillThreshold::::get(), None); + assert_eq!(MinCommission::::get(), Perbill::from_percent(0)); + }); +} + #[test] fn force_unstake_works() { ExtBuilder::default().build_and_execute(|| { @@ -4368,12 +4418,12 @@ fn chill_other_works() { // Change the minimum bond... but no limits. assert_ok!(Staking::set_staking_configs( Origin::root(), - 1_500, - 2_000, - None, - None, - None, - Zero::zero() + ConfigOp::Set(1_500), + ConfigOp::Set(2_000), + ConfigOp::Remove, + ConfigOp::Remove, + ConfigOp::Remove, + ConfigOp::Remove )); // Still can't chill these users @@ -4389,12 +4439,12 @@ fn chill_other_works() { // Add limits, but no threshold assert_ok!(Staking::set_staking_configs( Origin::root(), - 1_500, - 2_000, - Some(10), - Some(10), - None, - Zero::zero() + ConfigOp::Noop, + ConfigOp::Noop, + ConfigOp::Set(10), + ConfigOp::Set(10), + ConfigOp::Noop, + ConfigOp::Noop )); // Still can't chill these users @@ -4410,12 +4460,12 @@ fn chill_other_works() { // Add threshold, but no limits assert_ok!(Staking::set_staking_configs( Origin::root(), - 1_500, - 2_000, - None, - None, - Some(Percent::from_percent(0)), - Zero::zero() + ConfigOp::Noop, + ConfigOp::Noop, + ConfigOp::Remove, + ConfigOp::Remove, + ConfigOp::Noop, + ConfigOp::Noop )); // Still can't chill these users @@ -4431,12 +4481,12 @@ fn chill_other_works() { // Add threshold and limits assert_ok!(Staking::set_staking_configs( Origin::root(), - 1_500, - 2_000, - Some(10), - Some(10), - Some(Percent::from_percent(75)), - Zero::zero() + ConfigOp::Noop, + ConfigOp::Noop, + ConfigOp::Set(10), + ConfigOp::Set(10), + ConfigOp::Set(Percent::from_percent(75)), + ConfigOp::Noop )); // 16 people total because tests start with 2 active one @@ -4476,12 +4526,12 @@ fn capped_stakers_works() { let max = 10; assert_ok!(Staking::set_staking_configs( Origin::root(), - 10, - 10, - Some(max), - Some(max), - Some(Percent::from_percent(0)), - Zero::zero(), + ConfigOp::Set(10), + ConfigOp::Set(10), + ConfigOp::Set(max), + ConfigOp::Set(max), + ConfigOp::Remove, + ConfigOp::Remove, )); // can create `max - validator_count` validators @@ -4546,12 +4596,12 @@ fn capped_stakers_works() { // No problem when we set to `None` again assert_ok!(Staking::set_staking_configs( Origin::root(), - 10, - 10, - None, - None, - None, - Zero::zero(), + ConfigOp::Noop, + ConfigOp::Noop, + ConfigOp::Remove, + ConfigOp::Remove, + ConfigOp::Noop, + ConfigOp::Noop, )); assert_ok!(Staking::nominate(Origin::signed(last_nominator), vec![1])); assert_ok!(Staking::validate(Origin::signed(last_validator), ValidatorPrefs::default())); @@ -4568,12 +4618,12 @@ fn min_commission_works() { assert_ok!(Staking::set_staking_configs( Origin::root(), - 0, - 0, - None, - None, - None, - Perbill::from_percent(10), + ConfigOp::Remove, + ConfigOp::Remove, + ConfigOp::Remove, + ConfigOp::Remove, + ConfigOp::Remove, + ConfigOp::Set(Perbill::from_percent(10)), )); // can't make it less than 10 now diff --git a/frame/staking/src/weights.rs b/frame/staking/src/weights.rs index dcb544283c22..9d43cd882260 100644 --- a/frame/staking/src/weights.rs +++ b/frame/staking/src/weights.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_staking //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-02-09, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-03-02, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -70,7 +70,8 @@ pub trait WeightInfo { fn new_era(v: u32, n: u32, ) -> Weight; fn get_npos_voters(v: u32, n: u32, s: u32, ) -> Weight; fn get_npos_targets(v: u32, ) -> Weight; - fn set_staking_configs() -> Weight; + fn set_staking_configs_all_set() -> Weight; + fn set_staking_configs_all_remove() -> Weight; fn chill_other() -> Weight; fn force_apply_min_commission() -> Weight; } @@ -85,7 +86,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Balances Locks (r:1 w:1) // Storage: Staking Payee (r:0 w:1) fn bond() -> Weight { - (37_772_000 as Weight) + (37_238_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } @@ -95,7 +96,7 @@ impl WeightInfo for SubstrateWeight { // Storage: BagsList ListNodes (r:3 w:3) // Storage: BagsList ListBags (r:2 w:2) fn bond_extra() -> Weight { - (64_816_000 as Weight) + (64_061_000 as Weight) .saturating_add(T::DbWeight::get().reads(8 as Weight)) .saturating_add(T::DbWeight::get().writes(7 as Weight)) } @@ -109,7 +110,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking Bonded (r:1 w:0) // Storage: BagsList ListBags (r:2 w:2) fn unbond() -> Weight { - (71_635_000 as Weight) + (70_069_000 as Weight) .saturating_add(T::DbWeight::get().reads(12 as Weight)) .saturating_add(T::DbWeight::get().writes(8 as Weight)) } @@ -118,9 +119,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn withdraw_unbonded_update(s: u32, ) -> Weight { - (30_612_000 as Weight) + (29_855_000 as Weight) // Standard Error: 0 - .saturating_add((59_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((53_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -137,8 +138,10 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:1 w:1) // Storage: Balances Locks (r:1 w:1) // Storage: Staking Payee (r:0 w:1) - fn withdraw_unbonded_kill(_s: u32, ) -> Weight { - (59_116_000 as Weight) + fn withdraw_unbonded_kill(s: u32, ) -> Weight { + (57_313_000 as Weight) + // Standard Error: 0 + .saturating_add((1_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(13 as Weight)) .saturating_add(T::DbWeight::get().writes(11 as Weight)) } @@ -154,16 +157,16 @@ impl WeightInfo for SubstrateWeight { // Storage: BagsList CounterForListNodes (r:1 w:1) // Storage: Staking CounterForValidators (r:1 w:1) fn validate() -> Weight { - (45_505_000 as Weight) + (44_448_000 as Weight) .saturating_add(T::DbWeight::get().reads(12 as Weight)) .saturating_add(T::DbWeight::get().writes(8 as Weight)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking Nominators (r:1 w:1) fn kick(k: u32, ) -> Weight { - (12_764_000 as Weight) - // Standard Error: 15_000 - .saturating_add((8_301_000 as Weight).saturating_mul(k as Weight)) + (13_902_000 as Weight) + // Standard Error: 12_000 + .saturating_add((7_421_000 as Weight).saturating_mul(k as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(k as Weight))) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) @@ -180,9 +183,9 @@ impl WeightInfo for SubstrateWeight { // Storage: BagsList CounterForListNodes (r:1 w:1) // Storage: Staking CounterForNominators (r:1 w:1) fn nominate(n: u32, ) -> Weight { - (51_439_000 as Weight) - // Standard Error: 10_000 - .saturating_add((3_323_000 as Weight).saturating_mul(n as Weight)) + (49_580_000 as Weight) + // Standard Error: 9_000 + .saturating_add((3_362_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(12 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(n as Weight))) .saturating_add(T::DbWeight::get().writes(6 as Weight)) @@ -195,49 +198,49 @@ impl WeightInfo for SubstrateWeight { // Storage: BagsList ListBags (r:1 w:1) // Storage: BagsList CounterForListNodes (r:1 w:1) fn chill() -> Weight { - (44_847_000 as Weight) + (44_180_000 as Weight) .saturating_add(T::DbWeight::get().reads(8 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking Payee (r:0 w:1) fn set_payee() -> Weight { - (7_795_000 as Weight) + (7_922_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Staking Bonded (r:1 w:1) // Storage: Staking Ledger (r:2 w:2) fn set_controller() -> Weight { - (16_051_000 as Weight) + (15_436_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Staking ValidatorCount (r:0 w:1) fn set_validator_count() -> Weight { - (1_107_000 as Weight) + (1_091_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Staking ForceEra (r:0 w:1) fn force_no_eras() -> Weight { - (1_126_000 as Weight) + (1_204_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Staking ForceEra (r:0 w:1) fn force_new_era() -> Weight { - (1_183_000 as Weight) + (1_208_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Staking ForceEra (r:0 w:1) fn force_new_era_always() -> Weight { - (1_181_000 as Weight) + (1_220_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Staking Invulnerables (r:0 w:1) fn set_invulnerables(v: u32, ) -> Weight { - (1_705_000 as Weight) + (1_473_000 as Weight) // Standard Error: 0 - .saturating_add((50_000 as Weight).saturating_mul(v as Weight)) + .saturating_add((9_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Staking Bonded (r:1 w:1) @@ -254,18 +257,18 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking Payee (r:0 w:1) // Storage: Staking SpanSlash (r:0 w:2) fn force_unstake(s: u32, ) -> Weight { - (57_431_000 as Weight) + (55_815_000 as Weight) // Standard Error: 1_000 - .saturating_add((801_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((808_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(11 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) } // Storage: Staking UnappliedSlashes (r:1 w:1) fn cancel_deferred_slash(s: u32, ) -> Weight { - (950_258_000 as Weight) - // Standard Error: 56_000 - .saturating_add((5_001_000 as Weight).saturating_mul(s as Weight)) + (903_077_000 as Weight) + // Standard Error: 53_000 + .saturating_add((4_434_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -280,9 +283,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking Payee (r:2 w:0) // Storage: System Account (r:2 w:2) fn payout_stakers_dead_controller(n: u32, ) -> Weight { - (94_238_000 as Weight) - // Standard Error: 15_000 - .saturating_add((23_978_000 as Weight).saturating_mul(n as Weight)) + (79_440_000 as Weight) + // Standard Error: 14_000 + .saturating_add((24_005_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(10 as Weight)) .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(n as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -300,9 +303,9 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:2 w:2) // Storage: Balances Locks (r:2 w:2) fn payout_stakers_alive_staked(n: u32, ) -> Weight { - (109_323_000 as Weight) - // Standard Error: 22_000 - .saturating_add((33_887_000 as Weight).saturating_mul(n as Weight)) + (99_118_000 as Weight) + // Standard Error: 20_000 + .saturating_add((33_274_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(11 as Weight)) .saturating_add(T::DbWeight::get().reads((5 as Weight).saturating_mul(n as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -315,9 +318,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking Bonded (r:1 w:0) // Storage: BagsList ListBags (r:2 w:2) fn rebond(l: u32, ) -> Weight { - (64_807_000 as Weight) + (63_335_000 as Weight) // Standard Error: 2_000 - .saturating_add((50_000 as Weight).saturating_mul(l as Weight)) + .saturating_add((53_000 as Weight).saturating_mul(l as Weight)) .saturating_add(T::DbWeight::get().reads(9 as Weight)) .saturating_add(T::DbWeight::get().writes(8 as Weight)) } @@ -332,8 +335,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking ErasStartSessionIndex (r:0 w:1) fn set_history_depth(e: u32, ) -> Weight { (0 as Weight) - // Standard Error: 61_000 - .saturating_add((20_457_000 as Weight).saturating_mul(e as Weight)) + // Standard Error: 58_000 + .saturating_add((20_386_000 as Weight).saturating_mul(e as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) .saturating_add(T::DbWeight::get().writes((7 as Weight).saturating_mul(e as Weight))) @@ -352,9 +355,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking Payee (r:0 w:1) // Storage: Staking SpanSlash (r:0 w:1) fn reap_stash(s: u32, ) -> Weight { - (62_856_000 as Weight) + (61_486_000 as Weight) // Standard Error: 0 - .saturating_add((802_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((809_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(12 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) @@ -379,10 +382,10 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking ErasStartSessionIndex (r:0 w:1) fn new_era(v: u32, n: u32, ) -> Weight { (0 as Weight) - // Standard Error: 804_000 - .saturating_add((226_855_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 40_000 - .saturating_add((31_928_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 878_000 + .saturating_add((212_233_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 44_000 + .saturating_add((30_364_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(208 as Weight)) .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(v as Weight))) .saturating_add(T::DbWeight::get().reads((4 as Weight).saturating_mul(n as Weight))) @@ -400,12 +403,12 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking Nominators (r:1000 w:0) fn get_npos_voters(v: u32, n: u32, s: u32, ) -> Weight { (0 as Weight) - // Standard Error: 87_000 - .saturating_add((18_771_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 87_000 - .saturating_add((21_895_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 2_984_000 - .saturating_add((8_282_000 as Weight).saturating_mul(s as Weight)) + // Standard Error: 95_000 + .saturating_add((18_439_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 95_000 + .saturating_add((20_382_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 3_232_000 + .saturating_add((4_870_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(204 as Weight)) .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(v as Weight))) .saturating_add(T::DbWeight::get().reads((4 as Weight).saturating_mul(n as Weight))) @@ -414,8 +417,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking Validators (r:501 w:0) fn get_npos_targets(v: u32, ) -> Weight { (0 as Weight) - // Standard Error: 28_000 - .saturating_add((7_801_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 29_000 + .saturating_add((7_552_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(v as Weight))) } @@ -425,8 +428,18 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking ChillThreshold (r:0 w:1) // Storage: Staking MaxNominatorsCount (r:0 w:1) // Storage: Staking MinNominatorBond (r:0 w:1) - fn set_staking_configs() -> Weight { - (3_680_000 as Weight) + fn set_staking_configs_all_set() -> Weight { + (3_597_000 as Weight) + .saturating_add(T::DbWeight::get().writes(6 as Weight)) + } + // Storage: Staking MinCommission (r:0 w:1) + // Storage: Staking MinValidatorBond (r:0 w:1) + // Storage: Staking MaxValidatorsCount (r:0 w:1) + // Storage: Staking ChillThreshold (r:0 w:1) + // Storage: Staking MaxNominatorsCount (r:0 w:1) + // Storage: Staking MinNominatorBond (r:0 w:1) + fn set_staking_configs_all_remove() -> Weight { + (3_198_000 as Weight) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } // Storage: Staking Ledger (r:1 w:0) @@ -440,14 +453,14 @@ impl WeightInfo for SubstrateWeight { // Storage: BagsList ListBags (r:1 w:1) // Storage: BagsList CounterForListNodes (r:1 w:1) fn chill_other() -> Weight { - (55_459_000 as Weight) + (55_725_000 as Weight) .saturating_add(T::DbWeight::get().reads(11 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } // Storage: Staking MinCommission (r:1 w:0) // Storage: Staking Validators (r:1 w:1) fn force_apply_min_commission() -> Weight { - (8_939_000 as Weight) + (8_946_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -462,7 +475,7 @@ impl WeightInfo for () { // Storage: Balances Locks (r:1 w:1) // Storage: Staking Payee (r:0 w:1) fn bond() -> Weight { - (37_772_000 as Weight) + (37_238_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } @@ -472,7 +485,7 @@ impl WeightInfo for () { // Storage: BagsList ListNodes (r:3 w:3) // Storage: BagsList ListBags (r:2 w:2) fn bond_extra() -> Weight { - (64_816_000 as Weight) + (64_061_000 as Weight) .saturating_add(RocksDbWeight::get().reads(8 as Weight)) .saturating_add(RocksDbWeight::get().writes(7 as Weight)) } @@ -486,7 +499,7 @@ impl WeightInfo for () { // Storage: Staking Bonded (r:1 w:0) // Storage: BagsList ListBags (r:2 w:2) fn unbond() -> Weight { - (71_635_000 as Weight) + (70_069_000 as Weight) .saturating_add(RocksDbWeight::get().reads(12 as Weight)) .saturating_add(RocksDbWeight::get().writes(8 as Weight)) } @@ -495,9 +508,9 @@ impl WeightInfo for () { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn withdraw_unbonded_update(s: u32, ) -> Weight { - (30_612_000 as Weight) + (29_855_000 as Weight) // Standard Error: 0 - .saturating_add((59_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((53_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -514,8 +527,10 @@ impl WeightInfo for () { // Storage: System Account (r:1 w:1) // Storage: Balances Locks (r:1 w:1) // Storage: Staking Payee (r:0 w:1) - fn withdraw_unbonded_kill(_s: u32, ) -> Weight { - (59_116_000 as Weight) + fn withdraw_unbonded_kill(s: u32, ) -> Weight { + (57_313_000 as Weight) + // Standard Error: 0 + .saturating_add((1_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(13 as Weight)) .saturating_add(RocksDbWeight::get().writes(11 as Weight)) } @@ -531,16 +546,16 @@ impl WeightInfo for () { // Storage: BagsList CounterForListNodes (r:1 w:1) // Storage: Staking CounterForValidators (r:1 w:1) fn validate() -> Weight { - (45_505_000 as Weight) + (44_448_000 as Weight) .saturating_add(RocksDbWeight::get().reads(12 as Weight)) .saturating_add(RocksDbWeight::get().writes(8 as Weight)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking Nominators (r:1 w:1) fn kick(k: u32, ) -> Weight { - (12_764_000 as Weight) - // Standard Error: 15_000 - .saturating_add((8_301_000 as Weight).saturating_mul(k as Weight)) + (13_902_000 as Weight) + // Standard Error: 12_000 + .saturating_add((7_421_000 as Weight).saturating_mul(k as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(k as Weight))) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) @@ -557,9 +572,9 @@ impl WeightInfo for () { // Storage: BagsList CounterForListNodes (r:1 w:1) // Storage: Staking CounterForNominators (r:1 w:1) fn nominate(n: u32, ) -> Weight { - (51_439_000 as Weight) - // Standard Error: 10_000 - .saturating_add((3_323_000 as Weight).saturating_mul(n as Weight)) + (49_580_000 as Weight) + // Standard Error: 9_000 + .saturating_add((3_362_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(12 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(n as Weight))) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) @@ -572,49 +587,49 @@ impl WeightInfo for () { // Storage: BagsList ListBags (r:1 w:1) // Storage: BagsList CounterForListNodes (r:1 w:1) fn chill() -> Weight { - (44_847_000 as Weight) + (44_180_000 as Weight) .saturating_add(RocksDbWeight::get().reads(8 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking Payee (r:0 w:1) fn set_payee() -> Weight { - (7_795_000 as Weight) + (7_922_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Staking Bonded (r:1 w:1) // Storage: Staking Ledger (r:2 w:2) fn set_controller() -> Weight { - (16_051_000 as Weight) + (15_436_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } // Storage: Staking ValidatorCount (r:0 w:1) fn set_validator_count() -> Weight { - (1_107_000 as Weight) + (1_091_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Staking ForceEra (r:0 w:1) fn force_no_eras() -> Weight { - (1_126_000 as Weight) + (1_204_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Staking ForceEra (r:0 w:1) fn force_new_era() -> Weight { - (1_183_000 as Weight) + (1_208_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Staking ForceEra (r:0 w:1) fn force_new_era_always() -> Weight { - (1_181_000 as Weight) + (1_220_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Staking Invulnerables (r:0 w:1) fn set_invulnerables(v: u32, ) -> Weight { - (1_705_000 as Weight) + (1_473_000 as Weight) // Standard Error: 0 - .saturating_add((50_000 as Weight).saturating_mul(v as Weight)) + .saturating_add((9_000 as Weight).saturating_mul(v as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Staking Bonded (r:1 w:1) @@ -631,18 +646,18 @@ impl WeightInfo for () { // Storage: Staking Payee (r:0 w:1) // Storage: Staking SpanSlash (r:0 w:2) fn force_unstake(s: u32, ) -> Weight { - (57_431_000 as Weight) + (55_815_000 as Weight) // Standard Error: 1_000 - .saturating_add((801_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((808_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(11 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) } // Storage: Staking UnappliedSlashes (r:1 w:1) fn cancel_deferred_slash(s: u32, ) -> Weight { - (950_258_000 as Weight) - // Standard Error: 56_000 - .saturating_add((5_001_000 as Weight).saturating_mul(s as Weight)) + (903_077_000 as Weight) + // Standard Error: 53_000 + .saturating_add((4_434_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -657,9 +672,9 @@ impl WeightInfo for () { // Storage: Staking Payee (r:2 w:0) // Storage: System Account (r:2 w:2) fn payout_stakers_dead_controller(n: u32, ) -> Weight { - (94_238_000 as Weight) - // Standard Error: 15_000 - .saturating_add((23_978_000 as Weight).saturating_mul(n as Weight)) + (79_440_000 as Weight) + // Standard Error: 14_000 + .saturating_add((24_005_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(10 as Weight)) .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(n as Weight))) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) @@ -677,9 +692,9 @@ impl WeightInfo for () { // Storage: System Account (r:2 w:2) // Storage: Balances Locks (r:2 w:2) fn payout_stakers_alive_staked(n: u32, ) -> Weight { - (109_323_000 as Weight) - // Standard Error: 22_000 - .saturating_add((33_887_000 as Weight).saturating_mul(n as Weight)) + (99_118_000 as Weight) + // Standard Error: 20_000 + .saturating_add((33_274_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(11 as Weight)) .saturating_add(RocksDbWeight::get().reads((5 as Weight).saturating_mul(n as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -692,9 +707,9 @@ impl WeightInfo for () { // Storage: Staking Bonded (r:1 w:0) // Storage: BagsList ListBags (r:2 w:2) fn rebond(l: u32, ) -> Weight { - (64_807_000 as Weight) + (63_335_000 as Weight) // Standard Error: 2_000 - .saturating_add((50_000 as Weight).saturating_mul(l as Weight)) + .saturating_add((53_000 as Weight).saturating_mul(l as Weight)) .saturating_add(RocksDbWeight::get().reads(9 as Weight)) .saturating_add(RocksDbWeight::get().writes(8 as Weight)) } @@ -709,8 +724,8 @@ impl WeightInfo for () { // Storage: Staking ErasStartSessionIndex (r:0 w:1) fn set_history_depth(e: u32, ) -> Weight { (0 as Weight) - // Standard Error: 61_000 - .saturating_add((20_457_000 as Weight).saturating_mul(e as Weight)) + // Standard Error: 58_000 + .saturating_add((20_386_000 as Weight).saturating_mul(e as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) .saturating_add(RocksDbWeight::get().writes((7 as Weight).saturating_mul(e as Weight))) @@ -729,9 +744,9 @@ impl WeightInfo for () { // Storage: Staking Payee (r:0 w:1) // Storage: Staking SpanSlash (r:0 w:1) fn reap_stash(s: u32, ) -> Weight { - (62_856_000 as Weight) + (61_486_000 as Weight) // Standard Error: 0 - .saturating_add((802_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((809_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(12 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) @@ -756,10 +771,10 @@ impl WeightInfo for () { // Storage: Staking ErasStartSessionIndex (r:0 w:1) fn new_era(v: u32, n: u32, ) -> Weight { (0 as Weight) - // Standard Error: 804_000 - .saturating_add((226_855_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 40_000 - .saturating_add((31_928_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 878_000 + .saturating_add((212_233_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 44_000 + .saturating_add((30_364_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(208 as Weight)) .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(v as Weight))) .saturating_add(RocksDbWeight::get().reads((4 as Weight).saturating_mul(n as Weight))) @@ -777,12 +792,12 @@ impl WeightInfo for () { // Storage: Staking Nominators (r:1000 w:0) fn get_npos_voters(v: u32, n: u32, s: u32, ) -> Weight { (0 as Weight) - // Standard Error: 87_000 - .saturating_add((18_771_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 87_000 - .saturating_add((21_895_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 2_984_000 - .saturating_add((8_282_000 as Weight).saturating_mul(s as Weight)) + // Standard Error: 95_000 + .saturating_add((18_439_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 95_000 + .saturating_add((20_382_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 3_232_000 + .saturating_add((4_870_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(204 as Weight)) .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(v as Weight))) .saturating_add(RocksDbWeight::get().reads((4 as Weight).saturating_mul(n as Weight))) @@ -791,8 +806,8 @@ impl WeightInfo for () { // Storage: Staking Validators (r:501 w:0) fn get_npos_targets(v: u32, ) -> Weight { (0 as Weight) - // Standard Error: 28_000 - .saturating_add((7_801_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 29_000 + .saturating_add((7_552_000 as Weight).saturating_mul(v as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(v as Weight))) } @@ -802,8 +817,18 @@ impl WeightInfo for () { // Storage: Staking ChillThreshold (r:0 w:1) // Storage: Staking MaxNominatorsCount (r:0 w:1) // Storage: Staking MinNominatorBond (r:0 w:1) - fn set_staking_configs() -> Weight { - (3_680_000 as Weight) + fn set_staking_configs_all_set() -> Weight { + (3_597_000 as Weight) + .saturating_add(RocksDbWeight::get().writes(6 as Weight)) + } + // Storage: Staking MinCommission (r:0 w:1) + // Storage: Staking MinValidatorBond (r:0 w:1) + // Storage: Staking MaxValidatorsCount (r:0 w:1) + // Storage: Staking ChillThreshold (r:0 w:1) + // Storage: Staking MaxNominatorsCount (r:0 w:1) + // Storage: Staking MinNominatorBond (r:0 w:1) + fn set_staking_configs_all_remove() -> Weight { + (3_198_000 as Weight) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } // Storage: Staking Ledger (r:1 w:0) @@ -817,14 +842,14 @@ impl WeightInfo for () { // Storage: BagsList ListBags (r:1 w:1) // Storage: BagsList CounterForListNodes (r:1 w:1) fn chill_other() -> Weight { - (55_459_000 as Weight) + (55_725_000 as Weight) .saturating_add(RocksDbWeight::get().reads(11 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } // Storage: Staking MinCommission (r:1 w:0) // Storage: Staking Validators (r:1 w:1) fn force_apply_min_commission() -> Weight { - (8_939_000 as Weight) + (8_946_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } From efc28453c4efbb950d097d7314ac789fa6d801df Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Mar 2022 10:45:29 +0100 Subject: [PATCH 556/695] Bump libc from 0.2.112 to 0.2.119 (#10967) Bumps [libc](https://github.com/rust-lang/libc) from 0.2.112 to 0.2.119. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.112...0.2.119) --- updated-dependencies: - dependency-name: libc dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- client/executor/wasmtime/Cargo.toml | 2 +- client/tracing/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b5c78491628d..fb22dd6530a2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3610,9 +3610,9 @@ checksum = "3576a87f2ba00f6f106fdfcd16db1d698d648a26ad8e0573cad8537c3c362d2a" [[package]] name = "libc" -version = "0.2.112" +version = "0.2.119" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" +checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4" [[package]] name = "libgit2-sys" diff --git a/client/executor/wasmtime/Cargo.toml b/client/executor/wasmtime/Cargo.toml index 04163c2c4226..13bf196c4d44 100644 --- a/client/executor/wasmtime/Cargo.toml +++ b/client/executor/wasmtime/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -libc = "0.2.112" +libc = "0.2.119" cfg-if = "1.0" log = "0.4.8" parity-wasm = "0.42.0" diff --git a/client/tracing/Cargo.toml b/client/tracing/Cargo.toml index ab7d231e2c17..3c4401e2d342 100644 --- a/client/tracing/Cargo.toml +++ b/client/tracing/Cargo.toml @@ -17,7 +17,7 @@ ansi_term = "0.12.1" atty = "0.2.13" chrono = "0.4.19" lazy_static = "1.4.0" -libc = "0.2.112" +libc = "0.2.119" log = { version = "0.4.8" } once_cell = "1.8.0" parking_lot = "0.12.0" From 574237b7b603823fb9cb675e0e303a76865180e3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Mar 2022 10:50:49 +0000 Subject: [PATCH 557/695] Bump parity-db from 0.3.5 to 0.3.8 (#10970) Bumps [parity-db](https://github.com/paritytech/parity-db) from 0.3.5 to 0.3.8. - [Release notes](https://github.com/paritytech/parity-db/releases) - [Commits](https://github.com/paritytech/parity-db/commits/v0.3.8) --- updated-dependencies: - dependency-name: parity-db dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- client/db/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fb22dd6530a2..9cb1eae0a91f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6637,9 +6637,9 @@ dependencies = [ [[package]] name = "parity-db" -version = "0.3.5" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78a95abf24f1097c6e3181abbbbfc3630b3b5e681470940f719b69acb4911c7f" +checksum = "865edee5b792f537356d9e55cbc138e7f4718dc881a7ea45a18b37bf61c21e3d" dependencies = [ "blake2-rfc", "crc32fast", diff --git a/client/db/Cargo.toml b/client/db/Cargo.toml index 32fa9d463413..7b1e4da20861 100644 --- a/client/db/Cargo.toml +++ b/client/db/Cargo.toml @@ -33,7 +33,7 @@ sc-state-db = { version = "0.10.0-dev", path = "../state-db" } sp-trie = { version = "6.0.0", path = "../../primitives/trie" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-database = { version = "4.0.0-dev", path = "../../primitives/database" } -parity-db = { version = "0.3.5", optional = true } +parity-db = { version = "0.3.8", optional = true } [dev-dependencies] sp-tracing = { version = "5.0.0", path = "../../primitives/tracing" } From 15b8fd5af658810035ec2757b1a977db17f7aab4 Mon Sep 17 00:00:00 2001 From: Niklas Adolfsson Date: Thu, 3 Mar 2022 23:47:10 +0100 Subject: [PATCH 558/695] [EPM pallet]: remove `number of signed submissions` (#10945) * [EPM pallet]: remove `number of signed submissions` Closing #9229 * fix tests * remove needless assert * Update frame/election-provider-multi-phase/src/lib.rs * cargo fmt Signed-off-by: Niklas * fix grumbles * cargo run --quiet --profile=production --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_election_provider_multi_phase --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/election-provider-multi-phase/src/weights.rs --template=./.maintain/frame-weight-template.hbs * drop `num_signed_submissions` in WeightInfo too * fix build Co-authored-by: Parity Bot --- .../src/benchmarking.rs | 10 +- .../election-provider-multi-phase/src/lib.rs | 23 +-- .../election-provider-multi-phase/src/mock.rs | 4 +- .../src/signed.rs | 84 ++++------- .../src/unsigned.rs | 2 +- .../src/weights.rs | 134 ++++++++---------- 6 files changed, 101 insertions(+), 156 deletions(-) diff --git a/frame/election-provider-multi-phase/src/benchmarking.rs b/frame/election-provider-multi-phase/src/benchmarking.rs index cc322cbb4d57..479afd984338 100644 --- a/frame/election-provider-multi-phase/src/benchmarking.rs +++ b/frame/election-provider-multi-phase/src/benchmarking.rs @@ -310,7 +310,6 @@ frame_benchmarking::benchmarks! { } submit { - let c in 1 .. (T::SignedMaxSubmissions::get() - 1); // the solution will be worse than all of them meaning the score need to be checked against // ~ log2(c) @@ -324,7 +323,10 @@ frame_benchmarking::benchmarks! { >::put(1); let mut signed_submissions = SignedSubmissions::::get(); - for i in 0..c { + + // Insert `max - 1` submissions because the call to `submit` will insert another + // submission and the score is worse then the previous scores. + for i in 0..(T::SignedMaxSubmissions::get() - 1) { let raw_solution = RawSolution { score: ElectionScore { minimal_stake: 10_000_000u128 + (i as u128), ..Default::default() }, ..Default::default() @@ -342,9 +344,9 @@ frame_benchmarking::benchmarks! { let caller = frame_benchmarking::whitelisted_caller(); T::Currency::make_free_balance_be(&caller, T::Currency::minimum_balance() * 10u32.into()); - }: _(RawOrigin::Signed(caller), Box::new(solution), c) + }: _(RawOrigin::Signed(caller), Box::new(solution)) verify { - assert!(>::signed_submissions().len() as u32 == c + 1); + assert!(>::signed_submissions().len() as u32 == T::SignedMaxSubmissions::get()); } submit_unsigned { diff --git a/frame/election-provider-multi-phase/src/lib.rs b/frame/election-provider-multi-phase/src/lib.rs index 8b4ae60facb5..7e211c5ee921 100644 --- a/frame/election-provider-multi-phase/src/lib.rs +++ b/frame/election-provider-multi-phase/src/lib.rs @@ -963,25 +963,13 @@ pub mod pallet { /// /// A deposit is reserved and recorded for the solution. Based on the outcome, the solution /// might be rewarded, slashed, or get all or a part of the deposit back. - /// - /// # - /// Queue size must be provided as witness data. - /// # - #[pallet::weight(T::WeightInfo::submit(*num_signed_submissions))] + #[pallet::weight(T::WeightInfo::submit())] pub fn submit( origin: OriginFor, raw_solution: Box>>, - num_signed_submissions: u32, ) -> DispatchResult { let who = ensure_signed(origin)?; - // ensure witness data is correct. - ensure!( - num_signed_submissions >= - >::decode_len().unwrap_or_default() as u32, - Error::::SignedInvalidWitness, - ); - // ensure solution is timely. ensure!(Self::current_phase().is_signed(), Error::::PreDispatchEarlySubmission); @@ -1000,8 +988,7 @@ pub mod pallet { // create the submission let deposit = Self::deposit_for(&raw_solution, size); let reward = { - let call = - Call::submit { raw_solution: raw_solution.clone(), num_signed_submissions }; + let call = Call::submit { raw_solution: raw_solution.clone() }; let call_fee = T::EstimateCallFee::estimate_call_fee(&call, None.into()); T::SignedRewardBase::get().saturating_add(call_fee) }; @@ -1970,11 +1957,7 @@ mod tests { score: ElectionScore { minimal_stake: (5 + s).into(), ..Default::default() }, ..Default::default() }; - assert_ok!(MultiPhase::submit( - crate::mock::Origin::signed(99), - Box::new(solution), - MultiPhase::signed_submissions().len() as u32 - )); + assert_ok!(MultiPhase::submit(crate::mock::Origin::signed(99), Box::new(solution))); } // an unexpected call to elect. diff --git a/frame/election-provider-multi-phase/src/mock.rs b/frame/election-provider-multi-phase/src/mock.rs index 9ac0ecfef5dc..7c7034ac91a8 100644 --- a/frame/election-provider-multi-phase/src/mock.rs +++ b/frame/election-provider-multi-phase/src/mock.rs @@ -343,11 +343,11 @@ impl multi_phase::weights::WeightInfo for DualMockWeightInfo { <() as multi_phase::weights::WeightInfo>::finalize_signed_phase_reject_solution() } } - fn submit(c: u32) -> Weight { + fn submit() -> Weight { if MockWeightInfo::get() { Zero::zero() } else { - <() as multi_phase::weights::WeightInfo>::submit(c) + <() as multi_phase::weights::WeightInfo>::submit() } } fn submit_unsigned(v: u32, t: u32, a: u32, d: u32) -> Weight { diff --git a/frame/election-provider-multi-phase/src/signed.rs b/frame/election-provider-multi-phase/src/signed.rs index 4362fb5127e7..a233346b4fd7 100644 --- a/frame/election-provider-multi-phase/src/signed.rs +++ b/frame/election-provider-multi-phase/src/signed.rs @@ -500,18 +500,7 @@ mod tests { }, Error, Phase, }; - use frame_support::{assert_noop, assert_ok, assert_storage_noop, dispatch::DispatchResult}; - - fn submit_with_witness( - origin: Origin, - solution: RawSolution>, - ) -> DispatchResult { - MultiPhase::submit( - origin, - Box::new(solution), - MultiPhase::signed_submissions().len() as u32, - ) - } + use frame_support::{assert_noop, assert_ok, assert_storage_noop}; #[test] fn cannot_submit_too_early() { @@ -524,31 +513,12 @@ mod tests { let solution = raw_solution(); assert_noop!( - submit_with_witness(Origin::signed(10), solution), + MultiPhase::submit(Origin::signed(10), Box::new(solution)), Error::::PreDispatchEarlySubmission, ); }) } - #[test] - fn wrong_witness_fails() { - ExtBuilder::default().build_and_execute(|| { - roll_to(15); - assert!(MultiPhase::current_phase().is_signed()); - - let solution = raw_solution(); - // submit this once correctly - assert_ok!(submit_with_witness(Origin::signed(99), solution.clone())); - assert_eq!(MultiPhase::signed_submissions().len(), 1); - - // now try and cheat by passing a lower queue length - assert_noop!( - MultiPhase::submit(Origin::signed(99), Box::new(solution), 0), - Error::::SignedInvalidWitness, - ); - }) - } - #[test] fn should_pay_deposit() { ExtBuilder::default().build_and_execute(|| { @@ -558,7 +528,7 @@ mod tests { let solution = raw_solution(); assert_eq!(balances(&99), (100, 0)); - assert_ok!(submit_with_witness(Origin::signed(99), solution)); + assert_ok!(MultiPhase::submit(Origin::signed(99), Box::new(solution))); assert_eq!(balances(&99), (95, 5)); assert_eq!(MultiPhase::signed_submissions().iter().next().unwrap().deposit, 5); @@ -574,7 +544,7 @@ mod tests { let solution = raw_solution(); assert_eq!(balances(&99), (100, 0)); - assert_ok!(submit_with_witness(Origin::signed(99), solution)); + assert_ok!(MultiPhase::submit(Origin::signed(99), Box::new(solution))); assert_eq!(balances(&99), (95, 5)); assert!(MultiPhase::finalize_signed_phase()); @@ -594,7 +564,7 @@ mod tests { // make the solution invalid. solution.score.minimal_stake += 1; - assert_ok!(submit_with_witness(Origin::signed(99), solution)); + assert_ok!(MultiPhase::submit(Origin::signed(99), Box::new(solution))); assert_eq!(balances(&99), (95, 5)); // no good solution was stored. @@ -615,11 +585,11 @@ mod tests { assert_eq!(balances(&999), (100, 0)); // submit as correct. - assert_ok!(submit_with_witness(Origin::signed(99), solution.clone())); + assert_ok!(MultiPhase::submit(Origin::signed(99), Box::new(solution.clone()))); // make the solution invalid and weaker. solution.score.minimal_stake -= 1; - assert_ok!(submit_with_witness(Origin::signed(999), solution)); + assert_ok!(MultiPhase::submit(Origin::signed(999), Box::new(solution))); assert_eq!(balances(&99), (95, 5)); assert_eq!(balances(&999), (95, 5)); @@ -645,7 +615,7 @@ mod tests { score: ElectionScore { minimal_stake: (5 + s).into(), ..Default::default() }, ..Default::default() }; - assert_ok!(submit_with_witness(Origin::signed(99), solution)); + assert_ok!(MultiPhase::submit(Origin::signed(99), Box::new(solution))); } // weaker. @@ -655,7 +625,7 @@ mod tests { }; assert_noop!( - submit_with_witness(Origin::signed(99), solution), + MultiPhase::submit(Origin::signed(99), Box::new(solution)), Error::::SignedQueueFull, ); }) @@ -673,7 +643,7 @@ mod tests { score: ElectionScore { minimal_stake: (5 + s).into(), ..Default::default() }, ..Default::default() }; - assert_ok!(submit_with_witness(Origin::signed(99), solution)); + assert_ok!(MultiPhase::submit(Origin::signed(99), Box::new(solution))); } assert_eq!( @@ -689,7 +659,7 @@ mod tests { score: ElectionScore { minimal_stake: 20, ..Default::default() }, ..Default::default() }; - assert_ok!(submit_with_witness(Origin::signed(99), solution)); + assert_ok!(MultiPhase::submit(Origin::signed(99), Box::new(solution))); // the one with score 5 was rejected, the new one inserted. assert_eq!( @@ -714,14 +684,14 @@ mod tests { score: ElectionScore { minimal_stake: (5 + s).into(), ..Default::default() }, ..Default::default() }; - assert_ok!(submit_with_witness(Origin::signed(99), solution)); + assert_ok!(MultiPhase::submit(Origin::signed(99), Box::new(solution))); } let solution = RawSolution { score: ElectionScore { minimal_stake: 4, ..Default::default() }, ..Default::default() }; - assert_ok!(submit_with_witness(Origin::signed(99), solution)); + assert_ok!(MultiPhase::submit(Origin::signed(99), Box::new(solution))); assert_eq!( MultiPhase::signed_submissions() @@ -736,7 +706,7 @@ mod tests { score: ElectionScore { minimal_stake: 5, ..Default::default() }, ..Default::default() }; - assert_ok!(submit_with_witness(Origin::signed(99), solution)); + assert_ok!(MultiPhase::submit(Origin::signed(99), Box::new(solution))); // the one with score 5 was rejected, the new one inserted. assert_eq!( @@ -761,7 +731,7 @@ mod tests { score: ElectionScore { minimal_stake: (5 + s).into(), ..Default::default() }, ..Default::default() }; - assert_ok!(submit_with_witness(Origin::signed(99), solution)); + assert_ok!(MultiPhase::submit(Origin::signed(99), Box::new(solution))); } assert_eq!(balances(&99).1, 2 * 5); @@ -772,7 +742,7 @@ mod tests { score: ElectionScore { minimal_stake: 20, ..Default::default() }, ..Default::default() }; - assert_ok!(submit_with_witness(Origin::signed(999), solution)); + assert_ok!(MultiPhase::submit(Origin::signed(999), Box::new(solution))); // got one bond back. assert_eq!(balances(&99).1, 2 * 4); @@ -791,7 +761,7 @@ mod tests { score: ElectionScore { minimal_stake: (5 + i).into(), ..Default::default() }, ..Default::default() }; - assert_ok!(submit_with_witness(Origin::signed(99), solution)); + assert_ok!(MultiPhase::submit(Origin::signed(99), Box::new(solution))); } assert_eq!( MultiPhase::signed_submissions() @@ -807,7 +777,7 @@ mod tests { ..Default::default() }; assert_noop!( - submit_with_witness(Origin::signed(99), solution), + MultiPhase::submit(Origin::signed(99), Box::new(solution)), Error::::SignedQueueFull, ); }) @@ -829,18 +799,18 @@ mod tests { let solution = raw_solution(); // submit a correct one. - assert_ok!(submit_with_witness(Origin::signed(99), solution.clone())); + assert_ok!(MultiPhase::submit(Origin::signed(99), Box::new(solution.clone()))); // make the solution invalidly better and submit. This ought to be slashed. let mut solution_999 = solution.clone(); solution_999.score.minimal_stake += 1; - assert_ok!(submit_with_witness(Origin::signed(999), solution_999)); + assert_ok!(MultiPhase::submit(Origin::signed(999), Box::new(solution_999))); // make the solution invalidly worse and submit. This ought to be suppressed and // returned. let mut solution_9999 = solution.clone(); solution_9999.score.minimal_stake -= 1; - assert_ok!(submit_with_witness(Origin::signed(9999), solution_9999)); + assert_ok!(MultiPhase::submit(Origin::signed(9999), Box::new(solution_9999))); assert_eq!( MultiPhase::signed_submissions().iter().map(|x| x.who).collect::>(), @@ -881,14 +851,14 @@ mod tests { assert_eq!(raw.solution.voter_count(), 5); assert_eq!(::SignedMaxWeight::get(), 40); - assert_ok!(submit_with_witness(Origin::signed(99), raw.clone())); + assert_ok!(MultiPhase::submit(Origin::signed(99), Box::new(raw.clone()))); ::set(30); // note: resubmitting the same solution is technically okay as long as the queue has // space. assert_noop!( - submit_with_witness(Origin::signed(99), raw), + MultiPhase::submit(Origin::signed(99), Box::new(raw)), Error::::SignedTooMuchWeight, ); }) @@ -904,7 +874,7 @@ mod tests { assert_eq!(balances(&123), (0, 0)); assert_noop!( - submit_with_witness(Origin::signed(123), solution), + MultiPhase::submit(Origin::signed(123), Box::new(solution)), Error::::SignedCannotPayDeposit, ); @@ -926,7 +896,7 @@ mod tests { score: ElectionScore { minimal_stake: (5 + s).into(), ..Default::default() }, ..Default::default() }; - assert_ok!(submit_with_witness(Origin::signed(99), solution)); + assert_ok!(MultiPhase::submit(Origin::signed(99), Box::new(solution))); } // this solution has a higher score than any in the queue @@ -940,7 +910,7 @@ mod tests { assert_eq!(balances(&123), (0, 0)); assert_noop!( - submit_with_witness(Origin::signed(123), solution), + MultiPhase::submit(Origin::signed(123), Box::new(solution)), Error::::SignedCannotPayDeposit, ); @@ -969,7 +939,7 @@ mod tests { let solution = raw_solution(); // submit a correct one. - assert_ok!(submit_with_witness(Origin::signed(99), solution.clone())); + assert_ok!(MultiPhase::submit(Origin::signed(99), Box::new(solution))); // _some_ good solution was stored. assert!(MultiPhase::finalize_signed_phase()); diff --git a/frame/election-provider-multi-phase/src/unsigned.rs b/frame/election-provider-multi-phase/src/unsigned.rs index 510fc9fcdcca..81ea4453d096 100644 --- a/frame/election-provider-multi-phase/src/unsigned.rs +++ b/frame/election-provider-multi-phase/src/unsigned.rs @@ -662,7 +662,7 @@ mod max_weight { fn finalize_signed_phase_reject_solution() -> Weight { unreachable!() } - fn submit(c: u32) -> Weight { + fn submit() -> Weight { unreachable!() } fn submit_unsigned(v: u32, t: u32, a: u32, d: u32) -> Weight { diff --git a/frame/election-provider-multi-phase/src/weights.rs b/frame/election-provider-multi-phase/src/weights.rs index 99e149eff241..54c519681922 100644 --- a/frame/election-provider-multi-phase/src/weights.rs +++ b/frame/election-provider-multi-phase/src/weights.rs @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_election_provider_multi_phase //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-30, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-03-03, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate +// target/production/substrate // benchmark // --chain=dev // --steps=50 @@ -33,9 +33,7 @@ // --wasm-execution=compiled // --heap-pages=4096 // --output=./frame/election-provider-multi-phase/src/weights.rs -// --template=.maintain/frame-weight-template.hbs -// --header=HEADER-APACHE2 -// --raw +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -53,7 +51,7 @@ pub trait WeightInfo { fn finalize_signed_phase_reject_solution() -> Weight; fn create_snapshot_internal(v: u32, t: u32, ) -> Weight; fn elect_queued(a: u32, d: u32, ) -> Weight; - fn submit(c: u32, ) -> Weight; + fn submit() -> Weight; fn submit_unsigned(v: u32, t: u32, a: u32, d: u32, ) -> Weight; fn feasibility_check(v: u32, t: u32, a: u32, d: u32, ) -> Weight; } @@ -70,33 +68,33 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking ForceEra (r:1 w:0) // Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) fn on_initialize_nothing() -> Weight { - (12_763_000 as Weight) + (13_342_000 as Weight) .saturating_add(T::DbWeight::get().reads(8 as Weight)) } // Storage: ElectionProviderMultiPhase Round (r:1 w:0) // Storage: ElectionProviderMultiPhase CurrentPhase (r:0 w:1) fn on_initialize_open_signed() -> Weight { - (13_195_000 as Weight) + (13_503_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: ElectionProviderMultiPhase Round (r:1 w:0) // Storage: ElectionProviderMultiPhase CurrentPhase (r:0 w:1) fn on_initialize_open_unsigned() -> Weight { - (12_782_000 as Weight) + (13_688_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: System Account (r:1 w:1) // Storage: ElectionProviderMultiPhase QueuedSolution (r:0 w:1) fn finalize_signed_phase_accept_solution() -> Weight { - (27_421_000 as Weight) + (29_124_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: System Account (r:1 w:1) fn finalize_signed_phase_reject_solution() -> Weight { - (21_325_000 as Weight) + (21_950_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -104,11 +102,11 @@ impl WeightInfo for SubstrateWeight { // Storage: ElectionProviderMultiPhase DesiredTargets (r:0 w:1) // Storage: ElectionProviderMultiPhase Snapshot (r:0 w:1) fn create_snapshot_internal(v: u32, t: u32, ) -> Weight { - (0 as Weight) + (17_274_000 as Weight) // Standard Error: 1_000 - .saturating_add((216_000 as Weight).saturating_mul(v as Weight)) + .saturating_add((191_000 as Weight).saturating_mul(v as Weight)) // Standard Error: 3_000 - .saturating_add((51_000 as Weight).saturating_mul(t as Weight)) + .saturating_add((53_000 as Weight).saturating_mul(t as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: ElectionProviderMultiPhase SignedSubmissionIndices (r:1 w:1) @@ -121,24 +119,22 @@ impl WeightInfo for SubstrateWeight { // Storage: ElectionProviderMultiPhase Snapshot (r:0 w:1) // Storage: ElectionProviderMultiPhase CurrentPhase (r:0 w:1) fn elect_queued(a: u32, d: u32, ) -> Weight { - (38_368_000 as Weight) + (145_826_000 as Weight) // Standard Error: 4_000 - .saturating_add((1_414_000 as Weight).saturating_mul(a as Weight)) - // Standard Error: 7_000 - .saturating_add((175_000 as Weight).saturating_mul(d as Weight)) + .saturating_add((604_000 as Weight).saturating_mul(a as Weight)) + // Standard Error: 6_000 + .saturating_add((72_000 as Weight).saturating_mul(d as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(8 as Weight)) } - // Storage: ElectionProviderMultiPhase SignedSubmissionIndices (r:1 w:1) // Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) // Storage: ElectionProviderMultiPhase SnapshotMetadata (r:1 w:0) // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0) + // Storage: ElectionProviderMultiPhase SignedSubmissionIndices (r:1 w:1) // Storage: ElectionProviderMultiPhase SignedSubmissionNextIndex (r:1 w:1) // Storage: ElectionProviderMultiPhase SignedSubmissionsMap (r:0 w:1) - fn submit(c: u32, ) -> Weight { - (39_488_000 as Weight) - // Standard Error: 22_000 - .saturating_add((230_000 as Weight).saturating_mul(c as Weight)) + fn submit() -> Weight { + (41_579_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -151,14 +147,14 @@ impl WeightInfo for SubstrateWeight { // Storage: ElectionProviderMultiPhase Snapshot (r:1 w:0) fn submit_unsigned(v: u32, t: u32, a: u32, d: u32, ) -> Weight { (0 as Weight) - // Standard Error: 2_000 - .saturating_add((1_544_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 5_000 - .saturating_add((60_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 9_000 - .saturating_add((6_555_000 as Weight).saturating_mul(a as Weight)) - // Standard Error: 14_000 - .saturating_add((1_318_000 as Weight).saturating_mul(d as Weight)) + // Standard Error: 3_000 + .saturating_add((882_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 7_000 + .saturating_add((144_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 12_000 + .saturating_add((6_534_000 as Weight).saturating_mul(a as Weight)) + // Standard Error: 18_000 + .saturating_add((1_312_000 as Weight).saturating_mul(d as Weight)) .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -166,16 +162,14 @@ impl WeightInfo for SubstrateWeight { // Storage: ElectionProviderMultiPhase DesiredTargets (r:1 w:0) // Storage: ElectionProviderMultiPhase MinimumUntrustedScore (r:1 w:0) // Storage: ElectionProviderMultiPhase Snapshot (r:1 w:0) - fn feasibility_check(v: u32, t: u32, a: u32, d: u32, ) -> Weight { + fn feasibility_check(v: u32, _t: u32, a: u32, d: u32, ) -> Weight { (0 as Weight) // Standard Error: 3_000 - .saturating_add((1_527_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 6_000 - .saturating_add((151_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 10_000 - .saturating_add((5_433_000 as Weight).saturating_mul(a as Weight)) - // Standard Error: 15_000 - .saturating_add((1_420_000 as Weight).saturating_mul(d as Weight)) + .saturating_add((835_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 12_000 + .saturating_add((5_395_000 as Weight).saturating_mul(a as Weight)) + // Standard Error: 19_000 + .saturating_add((1_243_000 as Weight).saturating_mul(d as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) } } @@ -191,33 +185,33 @@ impl WeightInfo for () { // Storage: Staking ForceEra (r:1 w:0) // Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) fn on_initialize_nothing() -> Weight { - (12_763_000 as Weight) + (13_342_000 as Weight) .saturating_add(RocksDbWeight::get().reads(8 as Weight)) } // Storage: ElectionProviderMultiPhase Round (r:1 w:0) // Storage: ElectionProviderMultiPhase CurrentPhase (r:0 w:1) fn on_initialize_open_signed() -> Weight { - (13_195_000 as Weight) + (13_503_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: ElectionProviderMultiPhase Round (r:1 w:0) // Storage: ElectionProviderMultiPhase CurrentPhase (r:0 w:1) fn on_initialize_open_unsigned() -> Weight { - (12_782_000 as Weight) + (13_688_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: System Account (r:1 w:1) // Storage: ElectionProviderMultiPhase QueuedSolution (r:0 w:1) fn finalize_signed_phase_accept_solution() -> Weight { - (27_421_000 as Weight) + (29_124_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: System Account (r:1 w:1) fn finalize_signed_phase_reject_solution() -> Weight { - (21_325_000 as Weight) + (21_950_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -225,11 +219,11 @@ impl WeightInfo for () { // Storage: ElectionProviderMultiPhase DesiredTargets (r:0 w:1) // Storage: ElectionProviderMultiPhase Snapshot (r:0 w:1) fn create_snapshot_internal(v: u32, t: u32, ) -> Weight { - (0 as Weight) + (17_274_000 as Weight) // Standard Error: 1_000 - .saturating_add((216_000 as Weight).saturating_mul(v as Weight)) + .saturating_add((191_000 as Weight).saturating_mul(v as Weight)) // Standard Error: 3_000 - .saturating_add((51_000 as Weight).saturating_mul(t as Weight)) + .saturating_add((53_000 as Weight).saturating_mul(t as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } // Storage: ElectionProviderMultiPhase SignedSubmissionIndices (r:1 w:1) @@ -242,24 +236,22 @@ impl WeightInfo for () { // Storage: ElectionProviderMultiPhase Snapshot (r:0 w:1) // Storage: ElectionProviderMultiPhase CurrentPhase (r:0 w:1) fn elect_queued(a: u32, d: u32, ) -> Weight { - (38_368_000 as Weight) + (145_826_000 as Weight) // Standard Error: 4_000 - .saturating_add((1_414_000 as Weight).saturating_mul(a as Weight)) - // Standard Error: 7_000 - .saturating_add((175_000 as Weight).saturating_mul(d as Weight)) + .saturating_add((604_000 as Weight).saturating_mul(a as Weight)) + // Standard Error: 6_000 + .saturating_add((72_000 as Weight).saturating_mul(d as Weight)) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(8 as Weight)) } - // Storage: ElectionProviderMultiPhase SignedSubmissionIndices (r:1 w:1) // Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) // Storage: ElectionProviderMultiPhase SnapshotMetadata (r:1 w:0) // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0) + // Storage: ElectionProviderMultiPhase SignedSubmissionIndices (r:1 w:1) // Storage: ElectionProviderMultiPhase SignedSubmissionNextIndex (r:1 w:1) // Storage: ElectionProviderMultiPhase SignedSubmissionsMap (r:0 w:1) - fn submit(c: u32, ) -> Weight { - (39_488_000 as Weight) - // Standard Error: 22_000 - .saturating_add((230_000 as Weight).saturating_mul(c as Weight)) + fn submit() -> Weight { + (41_579_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -272,14 +264,14 @@ impl WeightInfo for () { // Storage: ElectionProviderMultiPhase Snapshot (r:1 w:0) fn submit_unsigned(v: u32, t: u32, a: u32, d: u32, ) -> Weight { (0 as Weight) - // Standard Error: 2_000 - .saturating_add((1_544_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 5_000 - .saturating_add((60_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 9_000 - .saturating_add((6_555_000 as Weight).saturating_mul(a as Weight)) - // Standard Error: 14_000 - .saturating_add((1_318_000 as Weight).saturating_mul(d as Weight)) + // Standard Error: 3_000 + .saturating_add((882_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 7_000 + .saturating_add((144_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 12_000 + .saturating_add((6_534_000 as Weight).saturating_mul(a as Weight)) + // Standard Error: 18_000 + .saturating_add((1_312_000 as Weight).saturating_mul(d as Weight)) .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -287,16 +279,14 @@ impl WeightInfo for () { // Storage: ElectionProviderMultiPhase DesiredTargets (r:1 w:0) // Storage: ElectionProviderMultiPhase MinimumUntrustedScore (r:1 w:0) // Storage: ElectionProviderMultiPhase Snapshot (r:1 w:0) - fn feasibility_check(v: u32, t: u32, a: u32, d: u32, ) -> Weight { + fn feasibility_check(v: u32, _t: u32, a: u32, d: u32, ) -> Weight { (0 as Weight) // Standard Error: 3_000 - .saturating_add((1_527_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 6_000 - .saturating_add((151_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 10_000 - .saturating_add((5_433_000 as Weight).saturating_mul(a as Weight)) - // Standard Error: 15_000 - .saturating_add((1_420_000 as Weight).saturating_mul(d as Weight)) + .saturating_add((835_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 12_000 + .saturating_add((5_395_000 as Weight).saturating_mul(a as Weight)) + // Standard Error: 19_000 + .saturating_add((1_243_000 as Weight).saturating_mul(d as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) } } From 9b5e654074655737ac041d059d88bfd68593b069 Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Fri, 4 Mar 2022 11:30:29 +0100 Subject: [PATCH 559/695] Refactored block body database scheme (#10779) * Refactored tx storage database scheme * Bump parity-db * fmt * Fix handling invalid index size + test * Removed superflous result * Minor changes * fmt --- bin/node/cli/benches/block_production.rs | 3 +- bin/node/cli/benches/transaction_pool.rs | 3 +- bin/node/testing/src/bench.rs | 1 - client/cli/src/config.rs | 11 +- client/cli/src/params/database_params.rs | 19 - client/db/src/lib.rs | 473 ++++++++++++----------- client/db/src/parity_db.rs | 18 +- client/db/src/upgrade.rs | 42 +- client/db/src/utils.rs | 17 +- client/service/src/builder.rs | 14 +- client/service/src/config.rs | 4 +- client/service/src/lib.rs | 1 - client/service/test/src/client/mod.rs | 6 +- client/service/test/src/lib.rs | 3 +- test-utils/client/src/lib.rs | 6 +- 15 files changed, 329 insertions(+), 292 deletions(-) diff --git a/bin/node/cli/benches/block_production.rs b/bin/node/cli/benches/block_production.rs index 69e9e0076a16..77b51fa28dd1 100644 --- a/bin/node/cli/benches/block_production.rs +++ b/bin/node/cli/benches/block_production.rs @@ -29,7 +29,7 @@ use sc_consensus::{ use sc_service::{ config::{ DatabaseSource, KeepBlocks, KeystoreConfig, NetworkConfiguration, OffchainWorkerConfig, - PruningMode, TransactionStorageMode, WasmExecutionMethod, + PruningMode, WasmExecutionMethod, }, BasePath, Configuration, Role, }; @@ -76,7 +76,6 @@ fn new_node(tokio_handle: Handle) -> node_cli::service::NewFullBase { state_cache_child_ratio: None, state_pruning: PruningMode::ArchiveAll, keep_blocks: KeepBlocks::All, - transaction_storage: TransactionStorageMode::BlockBody, chain_spec: spec, wasm_method: WasmExecutionMethod::Compiled, execution_strategies: ExecutionStrategies { diff --git a/bin/node/cli/benches/transaction_pool.rs b/bin/node/cli/benches/transaction_pool.rs index 9baa3e7fc117..e89527f2333a 100644 --- a/bin/node/cli/benches/transaction_pool.rs +++ b/bin/node/cli/benches/transaction_pool.rs @@ -25,7 +25,7 @@ use sc_client_api::execution_extensions::ExecutionStrategies; use sc_service::{ config::{ DatabaseSource, KeepBlocks, KeystoreConfig, NetworkConfiguration, OffchainWorkerConfig, - PruningMode, TransactionPoolOptions, TransactionStorageMode, WasmExecutionMethod, + PruningMode, TransactionPoolOptions, WasmExecutionMethod, }, BasePath, Configuration, Role, }; @@ -67,7 +67,6 @@ fn new_node(tokio_handle: Handle) -> node_cli::service::NewFullBase { state_cache_child_ratio: None, state_pruning: PruningMode::ArchiveAll, keep_blocks: KeepBlocks::All, - transaction_storage: TransactionStorageMode::BlockBody, chain_spec: spec, wasm_method: WasmExecutionMethod::Interpreted, // NOTE: we enforce the use of the native runtime to make the errors more debuggable diff --git a/bin/node/testing/src/bench.rs b/bin/node/testing/src/bench.rs index 18333280bb8a..8227582d88a4 100644 --- a/bin/node/testing/src/bench.rs +++ b/bin/node/testing/src/bench.rs @@ -393,7 +393,6 @@ impl BenchDb { state_pruning: PruningMode::ArchiveAll, source: database_type.into_settings(dir.into()), keep_blocks: sc_client_db::KeepBlocks::All, - transaction_storage: sc_client_db::TransactionStorageMode::BlockBody, }; let task_executor = TaskExecutor::new(); diff --git a/client/cli/src/config.rs b/client/cli/src/config.rs index b5470db91db3..a40be77f65aa 100644 --- a/client/cli/src/config.rs +++ b/client/cli/src/config.rs @@ -31,7 +31,7 @@ use sc_service::{ NodeKeyConfig, OffchainWorkerConfig, PrometheusConfig, PruningMode, Role, RpcMethods, TelemetryEndpoints, TransactionPoolOptions, WasmExecutionMethod, }, - ChainSpec, KeepBlocks, TracingReceiver, TransactionStorageMode, + ChainSpec, KeepBlocks, TracingReceiver, }; use sc_tracing::logging::LoggerBuilder; use std::{net::SocketAddr, path::PathBuf}; @@ -198,14 +198,6 @@ pub trait CliConfiguration: Sized { Ok(self.database_params().map(|x| x.database_cache_size()).unwrap_or_default()) } - /// Get the database transaction storage scheme. - fn database_transaction_storage(&self) -> Result { - Ok(self - .database_params() - .map(|x| x.transaction_storage()) - .unwrap_or(TransactionStorageMode::BlockBody)) - } - /// Get the database backend variant. /// /// By default this is retrieved from `DatabaseParams` if it is available. Otherwise its `None`. @@ -519,7 +511,6 @@ pub trait CliConfiguration: Sized { state_cache_child_ratio: self.state_cache_child_ratio()?, state_pruning: self.state_pruning(unsafe_pruning, &role)?, keep_blocks: self.keep_blocks()?, - transaction_storage: self.database_transaction_storage()?, wasm_method: self.wasm_method()?, wasm_runtime_overrides: self.wasm_runtime_overrides(), execution_strategies: self.execution_strategies(is_dev, is_validator)?, diff --git a/client/cli/src/params/database_params.rs b/client/cli/src/params/database_params.rs index 70c929ecf202..e954b8cc3bc2 100644 --- a/client/cli/src/params/database_params.rs +++ b/client/cli/src/params/database_params.rs @@ -18,7 +18,6 @@ use crate::arg_enums::Database; use clap::Args; -use sc_service::TransactionStorageMode; /// Parameters for block import. #[derive(Debug, Clone, PartialEq, Args)] @@ -36,15 +35,6 @@ pub struct DatabaseParams { /// Limit the memory the database cache can use. #[clap(long = "db-cache", value_name = "MiB")] pub database_cache_size: Option, - - /// Enable storage chain mode - /// - /// This changes the storage format for blocks bodies. - /// If this is enabled, each transaction is stored separately in the - /// transaction database column and is only referenced by hash - /// in the block body column. - #[clap(long)] - pub storage_chain: bool, } impl DatabaseParams { @@ -57,13 +47,4 @@ impl DatabaseParams { pub fn database_cache_size(&self) -> Option { self.database_cache_size } - - /// Transaction storage scheme. - pub fn transaction_storage(&self) -> TransactionStorageMode { - if self.storage_chain { - TransactionStorageMode::StorageChain - } else { - TransactionStorageMode::BlockBody - } - } } diff --git a/client/db/src/lib.rs b/client/db/src/lib.rs index 3fd3bf8d0904..f451062de33a 100644 --- a/client/db/src/lib.rs +++ b/client/db/src/lib.rs @@ -111,13 +111,18 @@ pub const DB_HASH_LEN: usize = 32; /// Hash type that this backend uses for the database. pub type DbHash = sp_core::H256; -/// This is used as block body when storage-chain mode is enabled. +/// An extrinsic entry in the database. #[derive(Debug, Encode, Decode)] -struct ExtrinsicHeader { - /// Hash of the indexed part - indexed_hash: DbHash, // Zero hash if there's no indexed data - /// The rest of the data. - data: Vec, +enum DbExtrinsic { + /// Extrinsic that contains indexed data. + Indexed { + /// Hash of the indexed part. + hash: DbHash, + /// Extrinsic header. + header: Vec, + }, + /// Complete extrinsic data. + Full(B::Extrinsic), } /// A reference tracking state. @@ -295,8 +300,6 @@ pub struct DatabaseSettings { pub source: DatabaseSource, /// Block pruning mode. pub keep_blocks: KeepBlocks, - /// Block body/Transaction storage scheme. - pub transaction_storage: TransactionStorageMode, } /// Block pruning settings. @@ -308,16 +311,6 @@ pub enum KeepBlocks { Some(u32), } -/// Block body storage scheme. -#[derive(Debug, Clone, Copy)] -pub enum TransactionStorageMode { - /// Store block body as an encoded list of full transactions in the BODY column - BlockBody, - /// Store a list of hashes in the BODY column and each transaction individually - /// in the TRANSACTION column. - StorageChain, -} - /// Where to find the database.. #[derive(Debug, Clone)] pub enum DatabaseSource { @@ -406,6 +399,7 @@ pub(crate) mod columns { pub const OFFCHAIN: u32 = 9; /// Transactions pub const TRANSACTION: u32 = 11; + pub const BODY_INDEX: u32 = 12; } struct PendingBlock { @@ -453,14 +447,10 @@ pub struct BlockchainDb { leaves: RwLock>>, header_metadata_cache: Arc>, header_cache: Mutex>>, - transaction_storage: TransactionStorageMode, } impl BlockchainDb { - fn new( - db: Arc>, - transaction_storage: TransactionStorageMode, - ) -> ClientResult { + fn new(db: Arc>) -> ClientResult { let meta = read_meta::(&*db, columns::HEADER)?; let leaves = LeafSet::read_from_db(&*db, columns::META, meta_keys::LEAF_PREFIX)?; Ok(BlockchainDb { @@ -469,7 +459,6 @@ impl BlockchainDb { meta: Arc::new(RwLock::new(meta)), header_metadata_cache: Arc::new(HeaderMetadataCache::default()), header_cache: Default::default(), - transaction_storage, }) } @@ -558,59 +547,61 @@ impl sc_client_api::blockchain::HeaderBackend for Blockcha impl sc_client_api::blockchain::Backend for BlockchainDb { fn body(&self, id: BlockId) -> ClientResult>> { - let body = match read_db(&*self.db, columns::KEY_LOOKUP, columns::BODY, id)? { - Some(body) => body, - None => return Ok(None), - }; - match self.transaction_storage { - TransactionStorageMode::BlockBody => match Decode::decode(&mut &body[..]) { - Ok(body) => Ok(Some(body)), + if let Some(body) = read_db(&*self.db, columns::KEY_LOOKUP, columns::BODY, id)? { + // Plain body + match Decode::decode(&mut &body[..]) { + Ok(body) => return Ok(Some(body)), Err(err) => return Err(sp_blockchain::Error::Backend(format!( "Error decoding body: {}", err ))), - }, - TransactionStorageMode::StorageChain => { - match Vec::::decode(&mut &body[..]) { - Ok(index) => { - let extrinsics: ClientResult> = index - .into_iter() - .map(|ExtrinsicHeader { indexed_hash, data }| { - let decode_result = if indexed_hash != Default::default() { - match self.db.get(columns::TRANSACTION, indexed_hash.as_ref()) { - Some(t) => { - let mut input = - utils::join_input(data.as_ref(), t.as_ref()); - Block::Extrinsic::decode(&mut input) - }, - None => - return Err(sp_blockchain::Error::Backend(format!( - "Missing indexed transaction {:?}", - indexed_hash - ))), - } - } else { - Block::Extrinsic::decode(&mut data.as_ref()) + } + } + + if let Some(index) = read_db(&*self.db, columns::KEY_LOOKUP, columns::BODY_INDEX, id)? { + match Vec::>::decode(&mut &index[..]) { + Ok(index) => { + let mut body = Vec::new(); + for ex in index { + match ex { + DbExtrinsic::Indexed { hash, header } => { + match self.db.get(columns::TRANSACTION, hash.as_ref()) { + Some(t) => { + let mut input = + utils::join_input(header.as_ref(), t.as_ref()); + let ex = Block::Extrinsic::decode(&mut input).map_err( + |err| { + sp_blockchain::Error::Backend(format!( + "Error decoding indexed extrinsic: {}", + err + )) + }, + )?; + body.push(ex); + }, + None => + return Err(sp_blockchain::Error::Backend(format!( + "Missing indexed transaction {:?}", + hash + ))), }; - decode_result.map_err(|err| { - sp_blockchain::Error::Backend(format!( - "Error decoding extrinsic: {}", - err - )) - }) - }) - .collect(); - Ok(Some(extrinsics?)) - }, - Err(err) => - return Err(sp_blockchain::Error::Backend(format!( - "Error decoding body list: {}", - err - ))), - } - }, + }, + DbExtrinsic::Full(ex) => { + body.push(ex); + }, + } + } + return Ok(Some(body)) + }, + Err(err) => + return Err(sp_blockchain::Error::Backend(format!( + "Error decoding body list: {}", + err + ))), + } } + Ok(None) } fn justifications(&self, id: BlockId) -> ClientResult> { @@ -648,37 +639,29 @@ impl sc_client_api::blockchain::Backend for BlockchainDb) -> ClientResult>>> { - match self.transaction_storage { - TransactionStorageMode::BlockBody => Ok(None), - TransactionStorageMode::StorageChain => { - let body = match read_db(&*self.db, columns::KEY_LOOKUP, columns::BODY, id)? { - Some(body) => body, - None => return Ok(None), - }; - match Vec::::decode(&mut &body[..]) { - Ok(index) => { - let mut transactions = Vec::new(); - for ExtrinsicHeader { indexed_hash, .. } in index.into_iter() { - if indexed_hash != Default::default() { - match self.db.get(columns::TRANSACTION, indexed_hash.as_ref()) { - Some(t) => transactions.push(t), - None => - return Err(sp_blockchain::Error::Backend(format!( - "Missing indexed transaction {:?}", - indexed_hash - ))), - } - } + let body = match read_db(&*self.db, columns::KEY_LOOKUP, columns::BODY_INDEX, id)? { + Some(body) => body, + None => return Ok(None), + }; + match Vec::>::decode(&mut &body[..]) { + Ok(index) => { + let mut transactions = Vec::new(); + for ex in index.into_iter() { + if let DbExtrinsic::Indexed { hash, .. } = ex { + match self.db.get(columns::TRANSACTION, hash.as_ref()) { + Some(t) => transactions.push(t), + None => + return Err(sp_blockchain::Error::Backend(format!( + "Missing indexed transaction {:?}", + hash + ))), } - Ok(Some(transactions)) - }, - Err(err) => - return Err(sp_blockchain::Error::Backend(format!( - "Error decoding body list: {}", - err - ))), + } } + Ok(Some(transactions)) }, + Err(err) => + Err(sp_blockchain::Error::Backend(format!("Error decoding body list: {}", err))), } } } @@ -1005,7 +988,6 @@ pub struct Backend { import_lock: Arc>, is_archive: bool, keep_blocks: KeepBlocks, - transaction_storage: TransactionStorageMode, io_stats: FrozenForDuration<(kvdb::IoStats, StateUsageInfo)>, state_usage: Arc, genesis_state: RwLock>>>, @@ -1023,20 +1005,12 @@ impl Backend { /// Create new memory-backed client backend for tests. #[cfg(any(test, feature = "test-helpers"))] pub fn new_test(keep_blocks: u32, canonicalization_delay: u64) -> Self { - Self::new_test_with_tx_storage( - keep_blocks, - canonicalization_delay, - TransactionStorageMode::BlockBody, - ) + Self::new_test_with_tx_storage(keep_blocks, canonicalization_delay) } /// Create new memory-backed client backend for tests. #[cfg(any(test, feature = "test-helpers"))] - pub fn new_test_with_tx_storage( - keep_blocks: u32, - canonicalization_delay: u64, - transaction_storage: TransactionStorageMode, - ) -> Self { + pub fn new_test_with_tx_storage(keep_blocks: u32, canonicalization_delay: u64) -> Self { let db = kvdb_memorydb::create(crate::utils::NUM_COLUMNS); let db = sp_database::as_database(db); let db_setting = DatabaseSettings { @@ -1045,7 +1019,6 @@ impl Backend { state_pruning: PruningMode::keep_blocks(keep_blocks), source: DatabaseSource::Custom(db), keep_blocks: KeepBlocks::Some(keep_blocks), - transaction_storage, }; Self::new(db_setting, canonicalization_delay).expect("failed to create test-db") @@ -1074,7 +1047,7 @@ impl Backend { config: &DatabaseSettings, ) -> ClientResult { let is_archive_pruning = config.state_pruning.is_archive(); - let blockchain = BlockchainDb::new(db.clone(), config.transaction_storage.clone())?; + let blockchain = BlockchainDb::new(db.clone())?; let map_e = |e: sc_state_db::Error| sp_blockchain::Error::from_state_db(e); let state_db: StateDb<_, _> = StateDb::new( config.state_pruning.clone(), @@ -1100,7 +1073,6 @@ impl Backend { io_stats: FrozenForDuration::new(std::time::Duration::from_secs(1)), state_usage: Arc::new(StateUsageStats::new()), keep_blocks: config.keep_blocks.clone(), - transaction_storage: config.transaction_storage.clone(), genesis_state: RwLock::new(None), }; @@ -1334,26 +1306,18 @@ impl Backend { transaction.set_from_vec(columns::HEADER, &lookup_key, pending_block.header.encode()); if let Some(body) = pending_block.body { - match self.transaction_storage { - TransactionStorageMode::BlockBody => { - transaction.set_from_vec(columns::BODY, &lookup_key, body.encode()); - }, - TransactionStorageMode::StorageChain => { - let body = - apply_index_ops::(&mut transaction, body, operation.index_ops); - transaction.set_from_vec(columns::BODY, &lookup_key, body); - }, + // If we have any index operations we save block in the new format with indexed + // extrinsic headers Otherwise we save the body as a single blob. + if operation.index_ops.is_empty() { + transaction.set_from_vec(columns::BODY, &lookup_key, body.encode()); + } else { + let body = + apply_index_ops::(&mut transaction, body, operation.index_ops); + transaction.set_from_vec(columns::BODY_INDEX, &lookup_key, body); } } if let Some(body) = pending_block.indexed_body { - match self.transaction_storage { - TransactionStorageMode::BlockBody => { - debug!(target: "db", "Commit: ignored indexed block body"); - }, - TransactionStorageMode::StorageChain => { - apply_indexed_body::(&mut transaction, body); - }, - } + apply_indexed_body::(&mut transaction, body); } if let Some(justifications) = pending_block.justifications { transaction.set_from_vec( @@ -1691,7 +1655,7 @@ impl Backend { let mut hash = h.clone(); // Follow displaced chains back until we reach a finalized block. // Since leaves are discarded due to finality, they can't have parents - // that are canonical, but not yet finalized. So we stop deletig as soon as + // that are canonical, but not yet finalized. So we stop deleting as soon as // we reach canonical chain. while self.blockchain.hash(number)? != Some(hash.clone()) { let id = BlockId::::hash(hash.clone()); @@ -1714,36 +1678,37 @@ impl Backend { transaction: &mut Transaction, id: BlockId, ) -> ClientResult<()> { - match read_db(&*self.storage.db, columns::KEY_LOOKUP, columns::BODY, id)? { - Some(body) => { - debug!(target: "db", "Removing block #{}", id); - utils::remove_from_db( - transaction, - &*self.storage.db, - columns::KEY_LOOKUP, - columns::BODY, - id, - )?; - match self.transaction_storage { - TransactionStorageMode::BlockBody => {}, - TransactionStorageMode::StorageChain => { - match Vec::::decode(&mut &body[..]) { - Ok(body) => - for ExtrinsicHeader { indexed_hash, .. } in body { - if indexed_hash != Default::default() { - transaction.release(columns::TRANSACTION, indexed_hash); - } - }, - Err(err) => - return Err(sp_blockchain::Error::Backend(format!( - "Error decoding body list: {}", - err - ))), + debug!(target: "db", "Removing block #{}", id); + utils::remove_from_db( + transaction, + &*self.storage.db, + columns::KEY_LOOKUP, + columns::BODY, + id, + )?; + if let Some(index) = + read_db(&*self.storage.db, columns::KEY_LOOKUP, columns::BODY_INDEX, id)? + { + utils::remove_from_db( + transaction, + &*self.storage.db, + columns::KEY_LOOKUP, + columns::BODY_INDEX, + id, + )?; + match Vec::>::decode(&mut &index[..]) { + Ok(index) => + for ex in index { + if let DbExtrinsic::Indexed { hash, .. } = ex { + transaction.release(columns::TRANSACTION, hash); } }, - } - }, - None => return Ok(()), + Err(err) => + return Err(sp_blockchain::Error::Backend(format!( + "Error decoding body list: {}", + err + ))), + } } Ok(()) } @@ -1785,7 +1750,7 @@ fn apply_index_ops( body: Vec, ops: Vec, ) -> Vec { - let mut extrinsic_headers: Vec = Vec::with_capacity(body.len()); + let mut extrinsic_index: Vec> = Vec::with_capacity(body.len()); let mut index_map = HashMap::new(); let mut renewed_map = HashMap::new(); for op in ops { @@ -1799,37 +1764,44 @@ fn apply_index_ops( } } for (index, extrinsic) in body.into_iter().enumerate() { - let extrinsic = extrinsic.encode(); - let extrinsic_header = if let Some(hash) = renewed_map.get(&(index as u32)) { + let db_extrinsic = if let Some(hash) = renewed_map.get(&(index as u32)) { // Bump ref counter + let extrinsic = extrinsic.encode(); transaction.reference(columns::TRANSACTION, DbHash::from_slice(hash.as_ref())); - ExtrinsicHeader { indexed_hash: hash.clone(), data: extrinsic } + DbExtrinsic::Indexed { hash: hash.clone(), header: extrinsic } } else { match index_map.get(&(index as u32)) { - Some((hash, size)) if *size as usize <= extrinsic.len() => { - let offset = extrinsic.len() - *size as usize; - transaction.store( - columns::TRANSACTION, - DbHash::from_slice(hash.as_ref()), - extrinsic[offset..].to_vec(), - ); - ExtrinsicHeader { - indexed_hash: DbHash::from_slice(hash.as_ref()), - data: extrinsic[..offset].to_vec(), + Some((hash, size)) => { + let encoded = extrinsic.encode(); + if *size as usize <= encoded.len() { + let offset = encoded.len() - *size as usize; + transaction.store( + columns::TRANSACTION, + DbHash::from_slice(hash.as_ref()), + encoded[offset..].to_vec(), + ); + DbExtrinsic::Indexed { + hash: DbHash::from_slice(hash.as_ref()), + header: encoded[..offset].to_vec(), + } + } else { + // Invalid indexed slice. Just store full data and don't index anything. + DbExtrinsic::Full(extrinsic) } }, - _ => ExtrinsicHeader { indexed_hash: Default::default(), data: extrinsic }, + _ => DbExtrinsic::Full(extrinsic), } }; - extrinsic_headers.push(extrinsic_header); + extrinsic_index.push(db_extrinsic); } debug!( target: "db", - "DB transaction index: {} inserted, {} renewed", + "DB transaction index: {} inserted, {} renewed, {} full", index_map.len(), - renewed_map.len() + renewed_map.len(), + extrinsic_index.len() - index_map.len() - renewed_map.len(), ); - extrinsic_headers.encode() + extrinsic_index.encode() } fn apply_indexed_body(transaction: &mut Transaction, body: Vec>) { @@ -2417,7 +2389,6 @@ pub(crate) mod tests { state_pruning: PruningMode::keep_blocks(1), source: DatabaseSource::Custom(backing), keep_blocks: KeepBlocks::All, - transaction_storage: TransactionStorageMode::BlockBody, }, 0, ) @@ -3087,46 +3058,43 @@ pub(crate) mod tests { #[test] fn prune_blocks_on_finalize() { - for storage in &[TransactionStorageMode::BlockBody, TransactionStorageMode::StorageChain] { - let backend = Backend::::new_test_with_tx_storage(2, 0, *storage); - let mut blocks = Vec::new(); - let mut prev_hash = Default::default(); - for i in 0..5 { - let hash = insert_block( - &backend, - i, - prev_hash, - None, - Default::default(), - vec![i.into()], - None, - ) - .unwrap(); - blocks.push(hash); - prev_hash = hash; - } + let backend = Backend::::new_test_with_tx_storage(2, 0); + let mut blocks = Vec::new(); + let mut prev_hash = Default::default(); + for i in 0..5 { + let hash = insert_block( + &backend, + i, + prev_hash, + None, + Default::default(), + vec![i.into()], + None, + ) + .unwrap(); + blocks.push(hash); + prev_hash = hash; + } - { - let mut op = backend.begin_operation().unwrap(); - backend.begin_state_operation(&mut op, BlockId::Hash(blocks[4])).unwrap(); - for i in 1..5 { - op.mark_finalized(BlockId::Hash(blocks[i]), None).unwrap(); - } - backend.commit_operation(op).unwrap(); + { + let mut op = backend.begin_operation().unwrap(); + backend.begin_state_operation(&mut op, BlockId::Hash(blocks[4])).unwrap(); + for i in 1..5 { + op.mark_finalized(BlockId::Hash(blocks[i]), None).unwrap(); } - let bc = backend.blockchain(); - assert_eq!(None, bc.body(BlockId::hash(blocks[0])).unwrap()); - assert_eq!(None, bc.body(BlockId::hash(blocks[1])).unwrap()); - assert_eq!(None, bc.body(BlockId::hash(blocks[2])).unwrap()); - assert_eq!(Some(vec![3.into()]), bc.body(BlockId::hash(blocks[3])).unwrap()); - assert_eq!(Some(vec![4.into()]), bc.body(BlockId::hash(blocks[4])).unwrap()); + backend.commit_operation(op).unwrap(); } + let bc = backend.blockchain(); + assert_eq!(None, bc.body(BlockId::hash(blocks[0])).unwrap()); + assert_eq!(None, bc.body(BlockId::hash(blocks[1])).unwrap()); + assert_eq!(None, bc.body(BlockId::hash(blocks[2])).unwrap()); + assert_eq!(Some(vec![3.into()]), bc.body(BlockId::hash(blocks[3])).unwrap()); + assert_eq!(Some(vec![4.into()]), bc.body(BlockId::hash(blocks[4])).unwrap()); } #[test] fn prune_blocks_on_finalize_with_fork() { - let backend = - Backend::::new_test_with_tx_storage(2, 10, TransactionStorageMode::StorageChain); + let backend = Backend::::new_test_with_tx_storage(2, 10); let mut blocks = Vec::new(); let mut prev_hash = Default::default(); for i in 0..5 { @@ -3185,10 +3153,86 @@ pub(crate) mod tests { assert_eq!(Some(vec![4.into()]), bc.body(BlockId::hash(blocks[4])).unwrap()); } + #[test] + fn indexed_data_block_body() { + let backend = Backend::::new_test_with_tx_storage(1, 10); + + let x0 = ExtrinsicWrapper::from(0u64).encode(); + let x1 = ExtrinsicWrapper::from(1u64).encode(); + let x0_hash = as sp_core::Hasher>::hash(&x0[1..]); + let x1_hash = as sp_core::Hasher>::hash(&x1[1..]); + let index = vec![ + IndexOperation::Insert { + extrinsic: 0, + hash: x0_hash.as_ref().to_vec(), + size: (x0.len() - 1) as u32, + }, + IndexOperation::Insert { + extrinsic: 1, + hash: x1_hash.as_ref().to_vec(), + size: (x1.len() - 1) as u32, + }, + ]; + let hash = insert_block( + &backend, + 0, + Default::default(), + None, + Default::default(), + vec![0u64.into(), 1u64.into()], + Some(index), + ) + .unwrap(); + let bc = backend.blockchain(); + assert_eq!(bc.indexed_transaction(&x0_hash).unwrap().unwrap(), &x0[1..]); + assert_eq!(bc.indexed_transaction(&x1_hash).unwrap().unwrap(), &x1[1..]); + + // Push one more blocks and make sure block is pruned and transaction index is cleared. + insert_block(&backend, 1, hash, None, Default::default(), vec![], None).unwrap(); + backend.finalize_block(BlockId::Number(1), None).unwrap(); + assert_eq!(bc.body(BlockId::Number(0)).unwrap(), None); + assert_eq!(bc.indexed_transaction(&x0_hash).unwrap(), None); + assert_eq!(bc.indexed_transaction(&x1_hash).unwrap(), None); + } + + #[test] + fn index_invalid_size() { + let backend = Backend::::new_test_with_tx_storage(1, 10); + + let x0 = ExtrinsicWrapper::from(0u64).encode(); + let x1 = ExtrinsicWrapper::from(1u64).encode(); + let x0_hash = as sp_core::Hasher>::hash(&x0[..]); + let x1_hash = as sp_core::Hasher>::hash(&x1[..]); + let index = vec![ + IndexOperation::Insert { + extrinsic: 0, + hash: x0_hash.as_ref().to_vec(), + size: (x0.len()) as u32, + }, + IndexOperation::Insert { + extrinsic: 1, + hash: x1_hash.as_ref().to_vec(), + size: (x1.len() + 1) as u32, + }, + ]; + insert_block( + &backend, + 0, + Default::default(), + None, + Default::default(), + vec![0u64.into(), 1u64.into()], + Some(index), + ) + .unwrap(); + let bc = backend.blockchain(); + assert_eq!(bc.indexed_transaction(&x0_hash).unwrap().unwrap(), &x0[..]); + assert_eq!(bc.indexed_transaction(&x1_hash).unwrap(), None); + } + #[test] fn renew_transaction_storage() { - let backend = - Backend::::new_test_with_tx_storage(2, 10, TransactionStorageMode::StorageChain); + let backend = Backend::::new_test_with_tx_storage(2, 10); let mut blocks = Vec::new(); let mut prev_hash = Default::default(); let x1 = ExtrinsicWrapper::from(0u64).encode(); @@ -3235,8 +3279,7 @@ pub(crate) mod tests { #[test] fn remove_leaf_block_works() { - let backend = - Backend::::new_test_with_tx_storage(2, 10, TransactionStorageMode::StorageChain); + let backend = Backend::::new_test_with_tx_storage(2, 10); let mut blocks = Vec::new(); let mut prev_hash = Default::default(); for i in 0..2 { diff --git a/client/db/src/parity_db.rs b/client/db/src/parity_db.rs index ebe2988e27f0..c27d7b0d4b4d 100644 --- a/client/db/src/parity_db.rs +++ b/client/db/src/parity_db.rs @@ -38,20 +38,22 @@ pub fn open>( path: &std::path::Path, db_type: DatabaseType, create: bool, + upgrade: bool, ) -> parity_db::Result>> { let mut config = parity_db::Options::with_columns(path, NUM_COLUMNS as u8); match db_type { DatabaseType::Full => { - let indexes = [ + let compressed = [ columns::STATE, columns::HEADER, columns::BODY, + columns::BODY_INDEX, columns::TRANSACTION, columns::JUSTIFICATIONS, ]; - for i in indexes { + for i in compressed { let mut column = &mut config.columns[i as usize]; column.compression = parity_db::CompressionType::Lz4; } @@ -60,9 +62,21 @@ pub fn open>( state_col.ref_counted = true; state_col.preimage = true; state_col.uniform = true; + + let mut tx_col = &mut config.columns[columns::TRANSACTION as usize]; + tx_col.ref_counted = true; + tx_col.preimage = true; + tx_col.uniform = true; }, } + if upgrade { + log::info!("Upgrading database metadata."); + if let Some(meta) = parity_db::Options::load_metadata(path)? { + config.write_metadata(path, &meta.salt)?; + } + } + let db = if create { parity_db::Db::open_or_create(&config)? } else { diff --git a/client/db/src/upgrade.rs b/client/db/src/upgrade.rs index a42a1960a57c..ec91a753ed87 100644 --- a/client/db/src/upgrade.rs +++ b/client/db/src/upgrade.rs @@ -33,11 +33,12 @@ use sp_runtime::traits::Block as BlockT; const VERSION_FILE_NAME: &'static str = "db_version"; /// Current db version. -const CURRENT_VERSION: u32 = 3; +const CURRENT_VERSION: u32 = 4; /// Number of columns in v1. const V1_NUM_COLUMNS: u32 = 11; const V2_NUM_COLUMNS: u32 = 12; +const V3_NUM_COLUMNS: u32 = 12; /// Database upgrade errors. #[derive(Debug)] @@ -68,7 +69,7 @@ impl fmt::Display for UpgradeError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { UpgradeError::UnknownDatabaseVersion => { - write!(f, "Database version cannot be read from exisiting db_version file") + write!(f, "Database version cannot be read from existing db_version file") }, UpgradeError::MissingDatabaseVersionFile => write!(f, "Missing database version file"), UpgradeError::UnsupportedVersion(version) => { @@ -92,9 +93,16 @@ pub fn upgrade_db(db_path: &Path, db_type: DatabaseType) -> Upgra 0 => return Err(UpgradeError::UnsupportedVersion(db_version)), 1 => { migrate_1_to_2::(db_path, db_type)?; - migrate_2_to_3::(db_path, db_type)? + migrate_2_to_3::(db_path, db_type)?; + migrate_3_to_4::(db_path, db_type)?; + }, + 2 => { + migrate_2_to_3::(db_path, db_type)?; + migrate_3_to_4::(db_path, db_type)?; + }, + 3 => { + migrate_3_to_4::(db_path, db_type)?; }, - 2 => migrate_2_to_3::(db_path, db_type)?, CURRENT_VERSION => (), _ => return Err(UpgradeError::FutureDatabaseVersion(db_version)), } @@ -139,6 +147,15 @@ fn migrate_2_to_3(db_path: &Path, _db_type: DatabaseType) -> Upgr Ok(()) } +/// Migration from version3 to version4: +/// 1) the number of columns has changed from 12 to 13; +/// 2) BODY_INDEX column is added; +fn migrate_3_to_4(db_path: &Path, _db_type: DatabaseType) -> UpgradeResult<()> { + let db_cfg = DatabaseConfig::with_columns(V3_NUM_COLUMNS); + let db = Database::open(&db_cfg, db_path)?; + db.add_column().map_err(Into::into) +} + /// Reads current database version from the file at given path. /// If the file does not exist returns 0. fn current_version(path: &Path) -> UpgradeResult { @@ -173,9 +190,7 @@ fn version_file_path(path: &Path) -> PathBuf { #[cfg(test)] mod tests { use super::*; - use crate::{ - tests::Block, DatabaseSettings, DatabaseSource, KeepBlocks, TransactionStorageMode, - }; + use crate::{tests::Block, DatabaseSettings, DatabaseSource, KeepBlocks}; use sc_state_db::PruningMode; fn create_db(db_path: &Path, version: Option) { @@ -194,7 +209,6 @@ mod tests { state_pruning: PruningMode::ArchiveAll, source: DatabaseSource::RocksDb { path: db_path.to_owned(), cache_size: 128 }, keep_blocks: KeepBlocks::All, - transaction_storage: TransactionStorageMode::BlockBody, }, db_type, ) @@ -229,4 +243,16 @@ mod tests { assert_eq!(current_version(&db_path).unwrap(), CURRENT_VERSION); } } + + #[test] + fn upgrade_to_4_works() { + let db_type = DatabaseType::Full; + for version_from_file in &[None, Some(1), Some(2), Some(3)] { + let db_dir = tempfile::TempDir::new().unwrap(); + let db_path = db_dir.path().join(db_type.as_str()); + create_db(&db_path, *version_from_file); + open_database(&db_path, db_type).unwrap(); + assert_eq!(current_version(&db_path).unwrap(), CURRENT_VERSION); + } + } } diff --git a/client/db/src/utils.rs b/client/db/src/utils.rs index c3a60962a67d..7dcb6676a175 100644 --- a/client/db/src/utils.rs +++ b/client/db/src/utils.rs @@ -40,7 +40,7 @@ use sp_trie::DBValue; feature = "test-helpers", test ))] -pub const NUM_COLUMNS: u32 = 12; +pub const NUM_COLUMNS: u32 = 13; /// Meta column. The set of keys in the column is shared by full && light storages. pub const COLUMN_META: u32 = 0; @@ -252,7 +252,7 @@ impl From for sp_blockchain::Error { #[cfg(feature = "with-parity-db")] impl From for OpenDbError { fn from(err: parity_db::Error) -> Self { - if err.to_string().contains("use open_or_create") { + if matches!(err, parity_db::Error::DatabaseNotFound) { OpenDbError::DoesNotExist } else { OpenDbError::Internal(err.to_string()) @@ -272,8 +272,14 @@ impl From for OpenDbError { #[cfg(feature = "with-parity-db")] fn open_parity_db(path: &Path, db_type: DatabaseType, create: bool) -> OpenDbResult { - let db = crate::parity_db::open(path, db_type, create)?; - Ok(db) + match crate::parity_db::open(path, db_type, create, false) { + Ok(db) => Ok(db), + Err(parity_db::Error::InvalidConfiguration(_)) => { + // Try to update the database with the new config + Ok(crate::parity_db::open(path, db_type, create, true)?) + }, + Err(e) => Err(e.into()), + } } #[cfg(not(feature = "with-parity-db"))] @@ -573,7 +579,7 @@ impl<'a, 'b> codec::Input for JoinInput<'a, 'b> { #[cfg(test)] mod tests { use super::*; - use crate::{KeepBlocks, TransactionStorageMode}; + use crate::KeepBlocks; use codec::Input; use sc_state_db::PruningMode; use sp_runtime::testing::{Block as RawBlock, ExtrinsicWrapper}; @@ -689,7 +695,6 @@ mod tests { state_pruning: PruningMode::ArchiveAll, source, keep_blocks: KeepBlocks::All, - transaction_storage: TransactionStorageMode::BlockBody, } } diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index bf681aec94c7..e9c1691107c7 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -19,7 +19,7 @@ use crate::{ build_network_future, client::{Client, ClientConfig}, - config::{Configuration, KeystoreConfig, PrometheusConfig, TransactionStorageMode}, + config::{Configuration, KeystoreConfig, PrometheusConfig}, error::Error, metrics::MetricsService, start_rpc_servers, RpcHandlers, SpawnTaskHandle, TaskManager, TransactionPoolAdapter, @@ -39,7 +39,7 @@ use sc_executor::RuntimeVersionOf; use sc_keystore::LocalKeystore; use sc_network::{ block_request_handler::{self, BlockRequestHandler}, - config::{Role, SyncMode}, + config::Role, light_client_requests::{self, handler::LightClientRequestHandler}, state_request_handler::{self, StateRequestHandler}, warp_request_handler::{self, RequestHandler as WarpSyncRequestHandler, WarpSyncProvider}, @@ -264,7 +264,6 @@ where state_pruning: config.state_pruning.clone(), source: config.database.clone(), keep_blocks: config.keep_blocks.clone(), - transaction_storage: config.transaction_storage.clone(), }; let backend = new_db_backend(db_config)?; @@ -842,7 +841,7 @@ where } }; - let mut network_params = sc_network::config::Params { + let network_params = sc_network::config::Params { role: config.role.clone(), executor: { let spawn_handle = Clone::clone(&spawn_handle); @@ -869,13 +868,6 @@ where light_client_request_protocol_config, }; - // Storage chains don't keep full block history and can't be synced in full mode. - // Force fast sync when storage chain mode is enabled. - if matches!(config.transaction_storage, TransactionStorageMode::StorageChain) { - network_params.network_config.sync_mode = - SyncMode::Fast { storage_chain_mode: true, skip_proofs: false }; - } - let has_bootnodes = !network_params.network_config.boot_nodes.is_empty(); let network_mut = sc_network::NetworkWorker::new(network_params)?; let network = network_mut.service().clone(); diff --git a/client/service/src/config.rs b/client/service/src/config.rs index 45a6f832f8ee..fd32aebdebdd 100644 --- a/client/service/src/config.rs +++ b/client/service/src/config.rs @@ -19,7 +19,7 @@ //! Service configuration. pub use sc_client_api::execution_extensions::{ExecutionStrategies, ExecutionStrategy}; -pub use sc_client_db::{Database, DatabaseSource, KeepBlocks, PruningMode, TransactionStorageMode}; +pub use sc_client_db::{Database, DatabaseSource, KeepBlocks, PruningMode}; pub use sc_executor::WasmExecutionMethod; pub use sc_network::{ config::{ @@ -71,8 +71,6 @@ pub struct Configuration { pub state_pruning: PruningMode, /// Number of blocks to keep in the db. pub keep_blocks: KeepBlocks, - /// Transaction storage scheme. - pub transaction_storage: TransactionStorageMode, /// Chain configuration. pub chain_spec: Box, /// Wasm execution method. diff --git a/client/service/src/lib.rs b/client/service/src/lib.rs index d158bbc42e94..6d9d99994288 100644 --- a/client/service/src/lib.rs +++ b/client/service/src/lib.rs @@ -58,7 +58,6 @@ pub use self::{ }; pub use config::{ BasePath, Configuration, DatabaseSource, KeepBlocks, PruningMode, Role, RpcMethods, TaskType, - TransactionStorageMode, }; pub use sc_chain_spec::{ ChainSpec, ChainType, Extension as ChainSpecExtension, GenericChainSpec, NoExtension, diff --git a/client/service/test/src/client/mod.rs b/client/service/test/src/client/mod.rs index 2b0ea460c4dd..c86b23347d41 100644 --- a/client/service/test/src/client/mod.rs +++ b/client/service/test/src/client/mod.rs @@ -23,9 +23,7 @@ use sc_block_builder::BlockBuilderProvider; use sc_client_api::{ in_mem, BlockBackend, BlockchainEvents, FinalityNotifications, StorageProvider, }; -use sc_client_db::{ - Backend, DatabaseSettings, DatabaseSource, KeepBlocks, PruningMode, TransactionStorageMode, -}; +use sc_client_db::{Backend, DatabaseSettings, DatabaseSource, KeepBlocks, PruningMode}; use sc_consensus::{ BlockCheckParams, BlockImport, BlockImportParams, ForkChoiceStrategy, ImportResult, }; @@ -1203,7 +1201,6 @@ fn doesnt_import_blocks_that_revert_finality() { state_cache_child_ratio: None, state_pruning: PruningMode::ArchiveAll, keep_blocks: KeepBlocks::All, - transaction_storage: TransactionStorageMode::BlockBody, source: DatabaseSource::RocksDb { path: tmp.path().into(), cache_size: 1024 }, }, u64::MAX, @@ -1419,7 +1416,6 @@ fn returns_status_for_pruned_blocks() { state_cache_child_ratio: None, state_pruning: PruningMode::keep_blocks(1), keep_blocks: KeepBlocks::All, - transaction_storage: TransactionStorageMode::BlockBody, source: DatabaseSource::RocksDb { path: tmp.path().into(), cache_size: 1024 }, }, u64::MAX, diff --git a/client/service/test/src/lib.rs b/client/service/test/src/lib.rs index 67b33dfd55d1..c492ed30f7d9 100644 --- a/client/service/test/src/lib.rs +++ b/client/service/test/src/lib.rs @@ -30,7 +30,7 @@ use sc_service::{ client::Client, config::{BasePath, DatabaseSource, KeystoreConfig}, ChainSpecExtension, Configuration, Error, GenericChainSpec, KeepBlocks, Role, RuntimeGenesis, - SpawnTaskHandle, TaskManager, TransactionStorageMode, + SpawnTaskHandle, TaskManager, }; use sc_transaction_pool_api::TransactionPool; use sp_api::BlockId; @@ -235,7 +235,6 @@ fn node_config< state_cache_child_ratio: None, state_pruning: Default::default(), keep_blocks: KeepBlocks::All, - transaction_storage: TransactionStorageMode::BlockBody, chain_spec: Box::new((*spec).clone()), wasm_method: sc_service::config::WasmExecutionMethod::Interpreted, wasm_runtime_overrides: Default::default(), diff --git a/test-utils/client/src/lib.rs b/test-utils/client/src/lib.rs index 277965655882..94a350b5f5df 100644 --- a/test-utils/client/src/lib.rs +++ b/test-utils/client/src/lib.rs @@ -105,11 +105,7 @@ impl /// Create new `TestClientBuilder` with default backend and storage chain mode pub fn with_tx_storage(keep_blocks: u32) -> Self { - let backend = Arc::new(Backend::new_test_with_tx_storage( - keep_blocks, - 0, - sc_client_db::TransactionStorageMode::StorageChain, - )); + let backend = Arc::new(Backend::new_test_with_tx_storage(keep_blocks, 0)); Self::with_backend(backend) } } From e4633560680f8ce077c896815cf23a9d7f04967e Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Fri, 4 Mar 2022 13:22:10 +0100 Subject: [PATCH 560/695] Deprecate "paritydb-experimental" CLI in favour or "paritydb" (#10975) * Deprecate paritydb-experimental * Updated comment --- client/cli/src/arg_enums.rs | 8 ++++++-- client/cli/src/config.rs | 7 +++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/client/cli/src/arg_enums.rs b/client/cli/src/arg_enums.rs index 7c9974fff38a..6b0a029dd4fe 100644 --- a/client/cli/src/arg_enums.rs +++ b/client/cli/src/arg_enums.rs @@ -201,8 +201,10 @@ pub enum Database { /// ParityDb. ParityDb, /// Detect whether there is an existing database. Use it, if there is, if not, create new - /// instance of paritydb + /// instance of ParityDb Auto, + /// ParityDb. + ParityDbDeprecated, } impl std::str::FromStr for Database { @@ -212,6 +214,8 @@ impl std::str::FromStr for Database { if s.eq_ignore_ascii_case("rocksdb") { Ok(Self::RocksDb) } else if s.eq_ignore_ascii_case("paritydb-experimental") { + Ok(Self::ParityDbDeprecated) + } else if s.eq_ignore_ascii_case("paritydb") { Ok(Self::ParityDb) } else if s.eq_ignore_ascii_case("auto") { Ok(Self::Auto) @@ -224,7 +228,7 @@ impl std::str::FromStr for Database { impl Database { /// Returns all the variants of this enum to be shown in the cli. pub fn variants() -> &'static [&'static str] { - &["rocksdb", "paritydb-experimental", "auto"] + &["rocksdb", "paritydb", "paritydb-experimental", "auto"] } } diff --git a/client/cli/src/config.rs b/client/cli/src/config.rs index a40be77f65aa..d0f10dc9f6f3 100644 --- a/client/cli/src/config.rs +++ b/client/cli/src/config.rs @@ -222,6 +222,13 @@ pub trait CliConfiguration: Sized { Ok(match database { Database::RocksDb => DatabaseSource::RocksDb { path: rocksdb_path, cache_size }, Database::ParityDb => DatabaseSource::ParityDb { path: paritydb_path }, + Database::ParityDbDeprecated => { + eprintln!( + "WARNING: \"paritydb-experimental\" database setting is deprecated and will be removed in future releases. \ + Please update your setup to use the new value: \"paritydb\"." + ); + DatabaseSource::ParityDb { path: paritydb_path } + }, Database::Auto => DatabaseSource::Auto { paritydb_path, rocksdb_path, cache_size }, }) } From 47bb6089bb87c66a7600e06419534e9959fdaa6f Mon Sep 17 00:00:00 2001 From: Alexander Gryaznov Date: Fri, 4 Mar 2022 18:28:00 +0300 Subject: [PATCH 561/695] [contracts] Stabilize "seal0" `is_contract` and `caller_is_origin` (#10971) * stabilize `seal_is_contract` * stabilize `seal_caller_is_origin` --- frame/contracts/src/benchmarking/mod.rs | 4 ++-- frame/contracts/src/wasm/mod.rs | 6 ++---- frame/contracts/src/wasm/runtime.rs | 8 ++------ 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/frame/contracts/src/benchmarking/mod.rs b/frame/contracts/src/benchmarking/mod.rs index 129b4a62581c..5fdc5c2ab784 100644 --- a/frame/contracts/src/benchmarking/mod.rs +++ b/frame/contracts/src/benchmarking/mod.rs @@ -409,7 +409,7 @@ benchmarks! { let code = WasmModule::::from(ModuleDefinition { memory: Some(ImportedMemory::max::()), imported_functions: vec![ImportedFunction { - module: "__unstable__", + module: "seal0", name: "seal_is_contract", params: vec![ValueType::I32], return_type: Some(ValueType::I32), @@ -441,7 +441,7 @@ benchmarks! { let code = WasmModule::::from(ModuleDefinition { memory: Some(ImportedMemory::max::()), imported_functions: vec![ImportedFunction { - module: "__unstable__", + module: "seal0", name: "seal_caller_is_origin", params: vec![], return_type: Some(ValueType::I32), diff --git a/frame/contracts/src/wasm/mod.rs b/frame/contracts/src/wasm/mod.rs index 2dbaad0d7932..d89e7c1c8037 100644 --- a/frame/contracts/src/wasm/mod.rs +++ b/frame/contracts/src/wasm/mod.rs @@ -2321,12 +2321,11 @@ mod tests { } #[test] - #[cfg(feature = "unstable-interface")] fn is_contract_works() { const CODE_IS_CONTRACT: &str = r#" ;; This runs `is_contract` check on zero account address (module - (import "__unstable__" "seal_is_contract" (func $seal_is_contract (param i32) (result i32))) + (import "seal0" "seal_is_contract" (func $seal_is_contract (param i32) (result i32))) (import "seal0" "seal_return" (func $seal_return (param i32 i32 i32))) (import "env" "memory" (memory 1 1)) @@ -2362,12 +2361,11 @@ mod tests { } #[test] - #[cfg(feature = "unstable-interface")] fn caller_is_origin_works() { const CODE_CALLER_IS_ORIGIN: &str = r#" ;; This runs `caller_is_origin` check on zero account address (module - (import "__unstable__" "seal_caller_is_origin" (func $seal_caller_is_origin (result i32))) + (import "seal0" "seal_caller_is_origin" (func $seal_caller_is_origin (result i32))) (import "seal0" "seal_return" (func $seal_return (param i32 i32 i32))) (import "env" "memory" (memory 1 1)) diff --git a/frame/contracts/src/wasm/runtime.rs b/frame/contracts/src/wasm/runtime.rs index bb188e10e8fa..d008fa3f1dac 100644 --- a/frame/contracts/src/wasm/runtime.rs +++ b/frame/contracts/src/wasm/runtime.rs @@ -143,10 +143,8 @@ pub enum RuntimeCosts { /// Weight of calling `seal_caller`. Caller, /// Weight of calling `seal_is_contract`. - #[cfg(feature = "unstable-interface")] IsContract, /// Weight of calling `seal_caller_is_origin`. - #[cfg(feature = "unstable-interface")] CallerIsOrigin, /// Weight of calling `seal_address`. Address, @@ -236,9 +234,7 @@ impl RuntimeCosts { CopyFromContract(len) => s.return_per_byte.saturating_mul(len.into()), CopyToContract(len) => s.input_per_byte.saturating_mul(len.into()), Caller => s.caller, - #[cfg(feature = "unstable-interface")] IsContract => s.is_contract, - #[cfg(feature = "unstable-interface")] CallerIsOrigin => s.caller_is_origin, Address => s.address, GasLeft => s.gas_left, @@ -1372,7 +1368,7 @@ define_env!(Env, , // Should be decodable as an `T::AccountId`. Traps otherwise. // // Returned value is a u32-encoded boolean: (0 = false, 1 = true). - [__unstable__] seal_is_contract(ctx, account_ptr: u32) -> u32 => { + [seal0] seal_is_contract(ctx, account_ptr: u32) -> u32 => { ctx.charge_gas(RuntimeCosts::IsContract)?; let address: <::T as frame_system::Config>::AccountId = ctx.read_sandbox_memory_as(account_ptr)?; @@ -1390,7 +1386,7 @@ define_env!(Env, , // and `false` indicates that the caller is another contract. // // Returned value is a u32-encoded boolean: (0 = false, 1 = true). - [__unstable__] seal_caller_is_origin(ctx) -> u32 => { + [seal0] seal_caller_is_origin(ctx) -> u32 => { ctx.charge_gas(RuntimeCosts::CallerIsOrigin)?; Ok(ctx.ext.caller_is_origin() as u32) }, From d5090c66cf013b065bc00c987dfdbf64c85f04b3 Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Fri, 4 Mar 2022 15:54:23 +0000 Subject: [PATCH 562/695] Trie version migration pallet (#10073) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * starting * Updated from other branch. * setting flag * flag in storage struct * fix flagging to access and insert. * added todo to fix * also missing serialize meta to storage proof * extract meta. * Isolate old trie layout. * failing test that requires storing in meta when old hash scheme is used. * old hash compatibility * Db migrate. * runing tests with both states when interesting. * fix chain spec test with serde default. * export state (missing trie function). * Pending using new branch, lacking genericity on layout resolution. * extract and set global meta * Update to branch 4 * fix iterator with root flag (no longer insert node). * fix trie root hashing of root * complete basic backend. * Remove old_hash meta from proof that do not use inner_hashing. * fix trie test for empty (force layout on empty deltas). * Root update fix. * debug on meta * Use trie key iteration that do not include value in proofs. * switch default test ext to use inner hash. * small integration test, and fix tx cache mgmt in ext. test failing * Proof scenario at state-machine level. * trace for db upgrade * try different param * act more like iter_from. * Bigger batches. * Update trie dependency. * drafting codec changes and refact * before removing unused branch no value alt hashing. more work todo rename all flag var to alt_hash, and remove extrinsic replace by storage query at every storage_root call. * alt hashing only for branch with value. * fix trie tests * Hash of value include the encoded size. * removing fields(broken) * fix trie_stream to also include value length in inner hash. * triedbmut only using alt type if inner hashing. * trie_stream to also only use alt hashing type when actually alt hashing. * Refactor meta state, logic should work with change of trie treshold. * Remove NoMeta variant. * Remove state_hashed trigger specific functions. * pending switching to using threshold, new storage root api does not make much sense. * refactoring to use state from backend (not possible payload changes). * Applying from previous state * Remove default from storage, genesis need a special build. * rem empty space * Catch problem: when using triedb with default: we should not revert nodes: otherwhise thing as trie codec cannot decode-encode without changing state. * fix compilation * Right logic to avoid switch on reencode when default layout. * Clean up some todos * remove trie meta from root upstream * update upstream and fix benches. * split some long lines. * UPdate trie crate to work with new design. * Finish update to refactored upstream. * update to latest triedb changes. * Clean up. * fix executor test. * rust fmt from master. * rust format. * rustfmt * fix * start host function driven versioning * update state-machine part * still need access to state version from runtime * state hash in mem: wrong * direction likely correct, but passing call to code exec for genesis init seem awkward. * state version serialize in runtime, wrong approach, just initialize it with no threshold for core api < 4 seems more proper. * stateversion from runtime version (core api >= 4). * update trie, fix tests * unused import * clean some TODOs * Require RuntimeVersionOf for executor * use RuntimeVersionOf to resolve genesis state version. * update runtime version test * fix state-machine tests * TODO * Use runtime version from storage wasm with fast sync. * rustfmt * fmt * fix test * revert useless changes. * clean some unused changes * fmt * removing useless trait function. * remove remaining reference to state_hash * fix some imports * Follow chain state version management. * trie update, fix and constant threshold for trie layouts. * update deps * Update to latest trie pr changes. * fix benches * Verify proof requires right layout. * update trie_root * Update trie deps to latest * Update to latest trie versioning * Removing patch * update lock * extrinsic for sc-service-test using layout v0. * Adding RuntimeVersionOf to CallExecutor works. * fmt * error when resolving version and no wasm in storage. * use existing utils to instantiate runtime code. * migration pallet * Patch to delay runtime switch. * Revert "Patch to delay runtime switch." This reverts commit d35f273b7d67b1b85a9e72973cab13c5c156c1d3. * fix test * fix child migration calls. * useless closure * remove remaining state_hash variables. * Fix and add more tests * Remove outdated comment * useless inner hash * fmt * remote tests * finally ksm works * batches are broken * clean the benchmarks * Apply suggestions from code review Co-authored-by: Guillaume Thiolliere * Apply suggestions from code review Co-authored-by: Guillaume Thiolliere * Update frame/state-trie-migration/src/lib.rs Co-authored-by: Joshy Orndorff * Update frame/state-trie-migration/src/lib.rs * brand new version * fix build * Update frame/state-trie-migration/src/lib.rs Co-authored-by: Guillaume Thiolliere * Update frame/state-trie-migration/src/lib.rs Co-authored-by: Guillaume Thiolliere * Update primitives/storage/src/lib.rs Co-authored-by: cheme * Update frame/state-trie-migration/src/lib.rs Co-authored-by: cheme * Update frame/state-trie-migration/src/lib.rs Co-authored-by: cheme * fmt and opt-in feature to apply state change. * feature gate core version, use new test feature for node and test node * Use a 'State' api version instead of Core one. * fix merge of test function * use blake macro. * Fix state api (require declaring the api in runtime). * Opt out feature, fix macro for io to select a given version instead of latest. * run test nodes on new state. * fix * new test structure * new testing stuff from emeric * Add commit_all, still not working * Fix all tests * add comment * we have PoV tracking baby * document stuff, but proof size is still wrong * FUCK YEAH * a big batch of review comments * add more tests * tweak test * update config * some remote-ext stuff * delete some of the old stuff * sync more files with master to minimize the diff * Fix all tests * make signed migration a bit more relaxed * add witness check to signed submissions * allow custom migration to also go above limit * Fix these pesky tests * ==== removal of the unsigned stuff ==== * Make all tests work again * separate the tests from the logic so it can be reused easier * fix overall build * Update frame/state-trie-migration/src/lib.rs Co-authored-by: cheme * Update frame/state-trie-migration/src/lib.rs Co-authored-by: cheme * Slightly better termination * some final tweaks * Fix tests * Restrict access to signed migrations * address most of the review comments * fix defensive * New simplified code * Fix weights * fmt * Update frame/state-trie-migration/src/lib.rs Co-authored-by: Bastian Köcher * make the tests correctly fail * Fix build * Fix build * try and fix the benchmarks * fix build * Fix cargo file * Fix runtime deposit * make rustdoc happy * cargo run --quiet --profile=production --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_state_trie_migration --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/state-trie-migration/src/weights.rs --template=./.maintain/frame-weight-template.hbs Co-authored-by: cheme Co-authored-by: Guillaume Thiolliere Co-authored-by: Joshy Orndorff Co-authored-by: Bastian Köcher Co-authored-by: Parity Bot --- Cargo.lock | 31 + bin/node/runtime/Cargo.toml | 4 + bin/node/runtime/src/lib.rs | 26 +- frame/bags-list/remote-tests/src/migration.rs | 3 +- .../remote-tests/src/sanity_check.rs | 3 +- frame/bags-list/remote-tests/src/snapshot.rs | 2 +- frame/state-trie-migration/Cargo.toml | 57 + frame/state-trie-migration/src/lib.rs | 1557 +++++++++++++++++ frame/state-trie-migration/src/weights.rs | 137 ++ frame/support/src/traits/misc.rs | 8 +- primitives/core/src/lib.rs | 2 +- primitives/state-machine/src/testing.rs | 7 +- .../state-machine/src/trie_backend_essence.rs | 78 +- primitives/storage/src/lib.rs | 13 +- utils/frame/remote-externalities/src/lib.rs | 66 +- utils/frame/try-runtime/cli/src/lib.rs | 1 + 16 files changed, 1954 insertions(+), 41 deletions(-) create mode 100644 frame/state-trie-migration/Cargo.toml create mode 100644 frame/state-trie-migration/src/lib.rs create mode 100644 frame/state-trie-migration/src/weights.rs diff --git a/Cargo.lock b/Cargo.lock index 9cb1eae0a91f..bfe180174026 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5010,6 +5010,7 @@ dependencies = [ "pallet-society", "pallet-staking", "pallet-staking-reward-curve", + "pallet-state-trie-migration", "pallet-sudo", "pallet-timestamp", "pallet-tips", @@ -6419,6 +6420,30 @@ dependencies = [ "sp-arithmetic", ] +[[package]] +name = "pallet-state-trie-migration" +version = "4.0.0-dev" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log 0.4.14", + "pallet-balances", + "parity-scale-codec", + "parking_lot 0.12.0", + "remote-externalities", + "scale-info", + "serde", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "sp-tracing", + "thousands", + "tokio", + "zstd", +] + [[package]] name = "pallet-sudo" version = "4.0.0-dev" @@ -10838,6 +10863,12 @@ dependencies = [ "syn", ] +[[package]] +name = "thousands" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bf63baf9f5039dadc247375c29eb13706706cfde997d0330d05aa63a77d8820" + [[package]] name = "thread_local" version = "1.1.3" diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index e7bd50c3d189..0572345fa0c8 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -87,6 +87,7 @@ pallet-session = { version = "4.0.0-dev", features = [ "historical" ], path = ". pallet-session-benchmarking = { version = "4.0.0-dev", path = "../../../frame/session/benchmarking", default-features = false, optional = true } pallet-staking = { version = "4.0.0-dev", default-features = false, path = "../../../frame/staking" } pallet-staking-reward-curve = { version = "4.0.0-dev", default-features = false, path = "../../../frame/staking/reward-curve" } +pallet-state-trie-migration = { version = "4.0.0-dev", default-features = false, path = "../../../frame/state-trie-migration" } pallet-scheduler = { version = "4.0.0-dev", default-features = false, path = "../../../frame/scheduler" } pallet-society = { version = "4.0.0-dev", default-features = false, path = "../../../frame/society" } pallet-sudo = { version = "4.0.0-dev", default-features = false, path = "../../../frame/sudo" } @@ -153,6 +154,7 @@ std = [ "sp-runtime/std", "sp-staking/std", "pallet-staking/std", + "pallet-state-trie-migration/std", "sp-session/std", "pallet-sudo/std", "frame-support/std", @@ -214,6 +216,7 @@ runtime-benchmarks = [ "pallet-session-benchmarking", "pallet-society/runtime-benchmarks", "pallet-staking/runtime-benchmarks", + "pallet-state-trie-migration/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", "pallet-tips/runtime-benchmarks", "pallet-transaction-storage/runtime-benchmarks", @@ -261,6 +264,7 @@ try-runtime = [ "pallet-session/try-runtime", "pallet-society/try-runtime", "pallet-staking/try-runtime", + "pallet-state-trie-migration/try-runtime", "pallet-sudo/try-runtime", "pallet-timestamp/try-runtime", "pallet-tips/try-runtime", diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 0b0c033ae851..f12bf8a88365 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -39,7 +39,7 @@ use frame_support::{ }; use frame_system::{ limits::{BlockLength, BlockWeights}, - EnsureRoot, + EnsureRoot, EnsureSigned, }; pub use node_primitives::{AccountId, Signature}; use node_primitives::{AccountIndex, Balance, BlockNumber, Hash, Index, Moment}; @@ -1367,6 +1367,28 @@ impl pallet_whitelist::Config for Runtime { type WeightInfo = pallet_whitelist::weights::SubstrateWeight; } +parameter_types! { + pub const SignedMigrationMaxLimits: pallet_state_trie_migration::MigrationLimits = + pallet_state_trie_migration::MigrationLimits { size: 1024 * 1024 / 2, item: 512 }; + pub const MigrationSignedDepositPerItem: Balance = 1 * CENTS; + pub const MigrationSignedDepositBase: Balance = 20 * DOLLARS; +} + +impl pallet_state_trie_migration::Config for Runtime { + type Event = Event; + type ControlOrigin = EnsureRoot; + type Currency = Balances; + type SignedDepositPerItem = MigrationSignedDepositPerItem; + type SignedDepositBase = MigrationSignedDepositBase; + type SignedMigrationMaxLimits = SignedMigrationMaxLimits; + // Warning: this is not advised, as it might allow the chain to be temporarily DOS-ed. + // Preferably, if the chain's governance/maintenance team is planning on using a specific + // account for the migration, put it here to make sure only that account can trigger the signed + // migrations. + type SignedFilter = EnsureSigned; + type WeightInfo = (); +} + construct_runtime!( pub enum Runtime where Block = Block, @@ -1418,6 +1440,7 @@ construct_runtime!( Uniques: pallet_uniques, TransactionStorage: pallet_transaction_storage, BagsList: pallet_bags_list, + StateTrieMigration: pallet_state_trie_migration, ChildBounties: pallet_child_bounties, Referenda: pallet_referenda, ConvictionVoting: pallet_conviction_voting, @@ -1512,6 +1535,7 @@ mod benches { [pallet_scheduler, Scheduler] [pallet_session, SessionBench::] [pallet_staking, Staking] + [pallet_state_trie_migration, StateTrieMigration] [frame_system, SystemBench::] [pallet_timestamp, Timestamp] [pallet_tips, Tips] diff --git a/frame/bags-list/remote-tests/src/migration.rs b/frame/bags-list/remote-tests/src/migration.rs index aadbbdae3d61..4d5169fcc6df 100644 --- a/frame/bags-list/remote-tests/src/migration.rs +++ b/frame/bags-list/remote-tests/src/migration.rs @@ -34,8 +34,7 @@ pub async fn execute( .mode(Mode::Online(OnlineConfig { transport: ws_url.to_string().into(), pallets: vec![pallet_staking::Pallet::::name().to_string()], - at: None, - state_snapshot: None, + ..Default::default() })) .build() .await diff --git a/frame/bags-list/remote-tests/src/sanity_check.rs b/frame/bags-list/remote-tests/src/sanity_check.rs index adab1ae5477e..f2b6881edea7 100644 --- a/frame/bags-list/remote-tests/src/sanity_check.rs +++ b/frame/bags-list/remote-tests/src/sanity_check.rs @@ -35,8 +35,7 @@ pub async fn execute .mode(Mode::Online(OnlineConfig { transport: ws_url.to_string().into(), pallets: vec![pallet_bags_list::Pallet::::name().to_string()], - at: None, - state_snapshot: None, + ..Default::default() })) .inject_hashed_prefix(&>::prefix_hash()) .inject_hashed_prefix(&>::prefix_hash()) diff --git a/frame/bags-list/remote-tests/src/snapshot.rs b/frame/bags-list/remote-tests/src/snapshot.rs index 78f462e55b8f..241b64b36611 100644 --- a/frame/bags-list/remote-tests/src/snapshot.rs +++ b/frame/bags-list/remote-tests/src/snapshot.rs @@ -35,7 +35,7 @@ pub async fn execute // is bags-list. pallets: vec![pallet_bags_list::Pallet::::name().to_string()], at: None, - state_snapshot: None, + ..Default::default() })) .inject_hashed_prefix(&>::prefix_hash()) .inject_hashed_prefix(&>::prefix_hash()) diff --git a/frame/state-trie-migration/Cargo.toml b/frame/state-trie-migration/Cargo.toml new file mode 100644 index 000000000000..fb8bccb52d1f --- /dev/null +++ b/frame/state-trie-migration/Cargo.toml @@ -0,0 +1,57 @@ +[package] +name = "pallet-state-trie-migration" +version = "4.0.0-dev" +authors = ["Parity Technologies "] +edition = "2021" +license = "Apache-2.0" +homepage = "https://substrate.dev" +repository = "https://github.com/paritytech/substrate/" +description = "FRAME pallet migration of trie" +readme = "README.md" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +log = { version = "0.4.14", default-features = false } + +sp-std = { default-features = false, path = "../../primitives/std" } +sp-io = { default-features = false, path = "../../primitives/io" } +sp-core = { default-features = false, path = "../../primitives/core" } +sp-runtime = { default-features = false, path = "../../primitives/runtime" } + +frame-support = { default-features = false, path = "../support" } +frame-system = { default-features = false, path = "../system" } +frame-benchmarking = { default-features = false, path = "../benchmarking", optional = true } + +serde = { version = "1.0.133", optional = true } +thousands = { version = "0.2.0", optional = true } +remote-externalities = { path = "../../utils/frame/remote-externalities", optional = true } +zstd = { version = "0.9.0", optional = true } + +[dev-dependencies] +pallet-balances = { path = "../balances" } +parking_lot = "0.12.0" +sp-tracing = { path = "../../primitives/tracing" } +tokio = { version = "1.10", features = ["macros"] } + +[features] +default = ["std"] +std = [ + "log/std", + "scale-info/std", + "codec/std", + "frame-benchmarking/std", + "frame-support/std", + "frame-system/std", + "sp-core/std", + "sp-io/std", + "sp-runtime/std", + "sp-std/std" +] +runtime-benchmarks = ["frame-benchmarking"] +try-runtime = ["frame-support/try-runtime"] + +remote-test = [ "std", "zstd", "serde", "thousands", "remote-externalities" ] diff --git a/frame/state-trie-migration/src/lib.rs b/frame/state-trie-migration/src/lib.rs new file mode 100644 index 000000000000..4de130e9ac06 --- /dev/null +++ b/frame/state-trie-migration/src/lib.rs @@ -0,0 +1,1557 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +//! # Pallet State Trie Migration +//! +//! Reads and writes all keys and values in the entire state in a systematic way. This is useful for +//! upgrading a chain to [`sp-core::StateVersion::V1`], where all keys need to be touched. +//! +//! ## Migration Types +//! +//! This pallet provides 2 ways to do this, each of which is suited for a particular use-case, and +//! can be enabled independently. +//! +//! ### Auto migration +//! +//! This system will try and migrate all keys by continuously using `on_initialize`. It is only +//! sensible for a relay chain or a solo chain, where going slightly over weight is not a problem. +//! It can be configured so that the migration takes at most `n` items and tries to not go over `x` +//! bytes, but the latter is not guaranteed. +//! +//! For example, if a chain contains keys of 1 byte size, the `on_initialize` could read up to `x - +//! 1` bytes from `n` different keys, while the next key is suddenly `:code:`, and there is no way +//! to bail out of this. +//! +//! ### Signed migration +//! +//! As a backup, the migration process can be set in motion via signed transactions that basically +//! say in advance how many items and how many bytes they will consume, and pay for it as well. This +//! can be a good safe alternative, if the former system is not desirable. +//! +//! The (minor) caveat of this approach is that we cannot know in advance how many bytes reading a +//! certain number of keys will incur. To overcome this, the runtime needs to configure this pallet +//! with a `SignedDepositPerItem`. This is the per-item deposit that the origin of the signed +//! migration transactions need to have in their account (on top of the normal fee) and if the size +//! witness data that they claim is incorrect, this deposit is slashed. +//! +//! --- +//! +//! Initially, this pallet does not contain any auto migration. They must be manually enabled by the +//! `ControlOrigin`. + +#![cfg_attr(not(feature = "std"), no_std)] + +pub use pallet::*; + +const LOG_TARGET: &'static str = "runtime::state-trie-migration"; + +#[macro_export] +macro_rules! log { + ($level:tt, $patter:expr $(, $values:expr)* $(,)?) => { + log::$level!( + target: crate::LOG_TARGET, + concat!("[{:?}] 🤖 ", $patter), frame_system::Pallet::::block_number() $(, $values)* + ) + }; +} + +#[frame_support::pallet] +pub mod pallet { + use frame_support::{ + dispatch::{DispatchErrorWithPostInfo, PostDispatchInfo}, + ensure, + pallet_prelude::*, + traits::{Currency, Get}, + }; + use frame_system::{self, pallet_prelude::*}; + use sp_core::storage::well_known_keys::DEFAULT_CHILD_STORAGE_KEY_PREFIX; + use sp_runtime::{ + self, + traits::{Saturating, Zero}, + }; + use sp_std::prelude::*; + + pub(crate) type BalanceOf = + <::Currency as Currency<::AccountId>>::Balance; + + /// The weight information of this pallet. + pub trait WeightInfo { + fn process_top_key(x: u32) -> Weight; + fn continue_migrate() -> Weight; + fn continue_migrate_wrong_witness() -> Weight; + fn migrate_custom_top_fail() -> Weight; + fn migrate_custom_top_success() -> Weight; + fn migrate_custom_child_fail() -> Weight; + fn migrate_custom_child_success() -> Weight; + } + + impl WeightInfo for () { + fn process_top_key(_: u32) -> Weight { + 1000000 + } + fn continue_migrate() -> Weight { + 1000000 + } + fn continue_migrate_wrong_witness() -> Weight { + 1000000 + } + fn migrate_custom_top_fail() -> Weight { + 1000000 + } + fn migrate_custom_top_success() -> Weight { + 1000000 + } + fn migrate_custom_child_fail() -> Weight { + 1000000 + } + fn migrate_custom_child_success() -> Weight { + 1000000 + } + } + + /// A migration task stored in state. + /// + /// It tracks the last top and child keys read. + #[derive(Clone, Encode, Decode, scale_info::TypeInfo, PartialEq, Eq)] + #[codec(mel_bound(T: Config))] + #[scale_info(skip_type_params(T))] + pub struct MigrationTask { + /// The last top key that we migrated. + /// + /// If it does not exist, it means that the migration is done and no further keys exist. + pub(crate) last_top: Option>, + /// The last child key that we have processed. + /// + /// This is a child key under the current `self.last_top`. + /// + /// If this is set, no further top keys are processed until the child key migration is + /// complete. + pub(crate) last_child: Option>, + + /// A marker to indicate if the previous tick was a child tree migration or not. + pub(crate) prev_tick_child: bool, + + /// Dynamic counter for the number of items that we have processed in this execution from + /// the top trie. + /// + /// It is not written to storage. + #[codec(skip)] + pub(crate) dyn_top_items: u32, + /// Dynamic counter for the number of items that we have processed in this execution from + /// any child trie. + /// + /// It is not written to storage. + #[codec(skip)] + pub(crate) dyn_child_items: u32, + + /// Dynamic counter for for the byte size of items that we have processed in this + /// execution. + /// + /// It is not written to storage. + #[codec(skip)] + pub(crate) dyn_size: u32, + + /// The total size of the migration, over all executions. + /// + /// This only kept around for bookkeeping and debugging. + pub(crate) size: u32, + /// The total count of top keys in the migration, over all executions. + /// + /// This only kept around for bookkeeping and debugging. + pub(crate) top_items: u32, + /// The total count of child keys in the migration, over all executions. + /// + /// This only kept around for bookkeeping and debugging. + pub(crate) child_items: u32, + + #[codec(skip)] + pub(crate) _ph: sp_std::marker::PhantomData, + } + + impl sp_std::fmt::Debug for MigrationTask { + fn fmt(&self, f: &mut sp_std::fmt::Formatter<'_>) -> sp_std::fmt::Result { + f.debug_struct("MigrationTask") + .field( + "top", + &self.last_top.as_ref().map(|d| sp_core::hexdisplay::HexDisplay::from(d)), + ) + .field( + "child", + &self.last_child.as_ref().map(|d| sp_core::hexdisplay::HexDisplay::from(d)), + ) + .field("prev_tick_child", &self.prev_tick_child) + .field("dyn_top_items", &self.dyn_top_items) + .field("dyn_child_items", &self.dyn_child_items) + .field("dyn_size", &self.dyn_size) + .field("size", &self.size) + .field("top_items", &self.top_items) + .field("child_items", &self.child_items) + .finish() + } + } + + impl Default for MigrationTask { + fn default() -> Self { + Self { + last_top: Some(Default::default()), + last_child: Default::default(), + dyn_child_items: Default::default(), + dyn_top_items: Default::default(), + dyn_size: Default::default(), + prev_tick_child: Default::default(), + _ph: Default::default(), + size: Default::default(), + top_items: Default::default(), + child_items: Default::default(), + } + } + } + + impl MigrationTask { + /// Return true if the task is finished. + pub(crate) fn finished(&self) -> bool { + self.last_top.is_none() && self.last_child.is_none() + } + + /// Check if there's any work left, or if we have exhausted the limits already. + fn exhausted(&self, limits: MigrationLimits) -> bool { + self.dyn_total_items() >= limits.item || self.dyn_size >= limits.size + } + + /// get the total number of keys affected by the current task. + pub(crate) fn dyn_total_items(&self) -> u32 { + self.dyn_child_items.saturating_add(self.dyn_top_items) + } + + /// Migrate keys until either of the given limits are exhausted, or if no more top keys + /// exist. + /// + /// Note that this can return after the **first** migration tick that causes exhaustion, + /// specifically in the case of the `size` constrain. The reason for this is that before + /// reading a key, we simply cannot know how many bytes it is. In other words, this should + /// not be used in any environment where resources are strictly bounded (e.g. a parachain), + /// but it is acceptable otherwise (relay chain, offchain workers). + pub fn migrate_until_exhaustion(&mut self, limits: MigrationLimits) { + log!(debug, "running migrations on top of {:?} until {:?}", self, limits); + + if limits.item.is_zero() || limits.size.is_zero() { + // handle this minor edge case, else we would call `migrate_tick` at least once. + log!(warn, "limits are zero. stopping"); + return + } + + while !self.exhausted(limits) && !self.finished() { + self.migrate_tick(); + } + + // accumulate dynamic data into the storage items. + self.size = self.size.saturating_add(self.dyn_size); + self.child_items = self.child_items.saturating_add(self.dyn_child_items); + self.top_items = self.top_items.saturating_add(self.dyn_top_items); + log!(debug, "finished with {:?}", self); + } + + /// Migrate AT MOST ONE KEY. This can be either a top or a child key. + /// + /// This function is *the* core of this entire pallet. + fn migrate_tick(&mut self) { + match (self.last_top.as_ref(), self.last_child.as_ref()) { + (Some(_), Some(_)) => { + // we're in the middle of doing work on a child tree. + self.migrate_child(); + }, + (Some(ref top_key), None) => { + // we have a top key and no child key. 3 possibilities exist: + // 1. we continue the top key migrations. + // 2. this is the root of a child key, and we start processing child keys (and + // should call `migrate_child`). + // 3. this is the root of a child key, and we are finishing all child-keys (and + // should call `migrate_top`). + + // NOTE: this block is written intentionally to verbosely for easy of + // verification. + match ( + top_key.starts_with(DEFAULT_CHILD_STORAGE_KEY_PREFIX), + self.prev_tick_child, + ) { + (false, false) => { + // continue the top key migration + self.migrate_top(); + }, + (true, false) => { + self.last_child = Some(Default::default()); + self.migrate_child(); + self.prev_tick_child = true; + }, + (true, true) => { + // we're done with migrating a child-root. + self.prev_tick_child = false; + self.migrate_top(); + }, + (false, true) => { + // should never happen. + log!(error, "LOGIC ERROR: unreachable code [0]."); + Pallet::::halt(); + }, + }; + }, + (None, Some(_)) => { + log!(error, "LOGIC ERROR: unreachable code [1]."); + Pallet::::halt() + }, + (None, None) => { + // nada + }, + } + } + + /// Migrate the current child key, setting it to its new value, if one exists. + /// + /// It updates the dynamic counters. + fn migrate_child(&mut self) { + use sp_io::default_child_storage as child_io; + let (last_child, last_top) = match (&self.last_child, &self.last_top) { + (Some(last_child), Some(last_top)) => (last_child, last_top), + _ => { + // defensive: this function is only called when both of these values exist. + // much that we can do otherwise.. + frame_support::defensive!("cannot migrate child key."); + return + }, + }; + + let child_root = Pallet::::transform_child_key_or_halt(&last_top); + let maybe_current_child = child_io::next_key(child_root, &last_child); + if let Some(ref current_child) = maybe_current_child { + let added_size = if let Some(data) = child_io::get(child_root, ¤t_child) { + child_io::set(child_root, current_child, &data); + data.len() as u32 + } else { + Zero::zero() + }; + self.dyn_size = self.dyn_size.saturating_add(added_size); + self.dyn_child_items.saturating_inc(); + } + + log!(trace, "migrated a child key, next_child_key: {:?}", maybe_current_child); + self.last_child = maybe_current_child; + } + + /// Migrate the current top key, setting it to its new value, if one exists. + /// + /// It updates the dynamic counters. + fn migrate_top(&mut self) { + let last_top = match &self.last_top { + Some(last_top) => last_top, + None => { + // defensive: this function is only called when this value exist. + // much that we can do otherwise.. + frame_support::defensive!("cannot migrate top key."); + return + }, + }; + + let maybe_current_top = sp_io::storage::next_key(last_top); + if let Some(ref current_top) = maybe_current_top { + let added_size = if let Some(data) = sp_io::storage::get(¤t_top) { + sp_io::storage::set(¤t_top, &data); + data.len() as u32 + } else { + Zero::zero() + }; + self.dyn_size = self.dyn_size.saturating_add(added_size); + self.dyn_top_items.saturating_inc(); + } + + log!(trace, "migrated a top key, next_top_key = {:?}", maybe_current_top); + self.last_top = maybe_current_top; + } + } + + /// The limits of a migration. + #[derive(Clone, Copy, Encode, Decode, scale_info::TypeInfo, Default, Debug, PartialEq, Eq)] + pub struct MigrationLimits { + /// The byte size limit. + pub size: u32, + /// The number of keys limit. + pub item: u32, + } + + /// How a migration was computed. + #[derive(Clone, Copy, Encode, Decode, scale_info::TypeInfo, Debug, PartialEq, Eq)] + pub enum MigrationCompute { + /// A signed origin triggered the migration. + Signed, + /// An automatic task triggered the migration. + Auto, + } + + /// Inner events of this pallet. + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + /// Given number of `(top, child)` keys were migrated respectively, with the given + /// `compute`. + Migrated { top: u32, child: u32, compute: MigrationCompute }, + /// Some account got slashed by the given amount. + Slashed { who: T::AccountId, amount: BalanceOf }, + /// The auto migration task finished. + AutoMigrationFinished, + /// Migration got halted. + Halted, + } + + /// The outer Pallet struct. + #[pallet::pallet] + #[pallet::generate_store(pub(crate) trait Store)] + #[pallet::without_storage_info] + pub struct Pallet(_); + + /// Configurations of this pallet. + #[pallet::config] + pub trait Config: frame_system::Config { + /// Origin that can control the configurations of this pallet. + type ControlOrigin: frame_support::traits::EnsureOrigin; + + /// Filter on which origin that trigger the manual migrations. + type SignedFilter: EnsureOrigin; + + /// The overarching event type. + type Event: From> + IsType<::Event>; + + /// The currency provider type. + type Currency: Currency; + + /// The amount of deposit collected per item in advance, for signed migrations. + /// + /// This should reflect the average storage value size in the worse case. + type SignedDepositPerItem: Get>; + + /// The base value of [`Config::SignedDepositPerItem`]. + /// + /// Final deposit is `items * SignedDepositPerItem + SignedDepositBase`. + type SignedDepositBase: Get>; + + /// The maximum limits that the signed migration could use. + #[pallet::constant] + type SignedMigrationMaxLimits: Get; + + /// The weight information of this pallet. + type WeightInfo: WeightInfo; + } + + /// Migration progress. + /// + /// This stores the snapshot of the last migrated keys. It can be set into motion and move + /// forward by any of the means provided by this pallet. + #[pallet::storage] + #[pallet::getter(fn migration_process)] + pub type MigrationProcess = StorageValue<_, MigrationTask, ValueQuery>; + + /// The limits that are imposed on automatic migrations. + /// + /// If set to None, then no automatic migration happens. + #[pallet::storage] + #[pallet::getter(fn auto_limits)] + pub type AutoLimits = StorageValue<_, Option, ValueQuery>; + + #[pallet::error] + pub enum Error { + /// max signed limits not respected. + MaxSignedLimits, + /// submitter does not have enough funds. + NotEnoughFunds, + /// bad witness data provided. + BadWitness, + /// upper bound of size is exceeded, + SizeUpperBoundExceeded, + } + + #[pallet::call] + impl Pallet { + /// Control the automatic migration. + /// + /// The dispatch origin of this call must be [`Config::ControlOrigin`]. + #[pallet::weight(T::DbWeight::get().reads_writes(1, 1))] + pub fn control_auto_migration( + origin: OriginFor, + maybe_config: Option, + ) -> DispatchResultWithPostInfo { + T::ControlOrigin::ensure_origin(origin)?; + AutoLimits::::put(maybe_config); + Ok(().into()) + } + + /// Continue the migration for the given `limits`. + /// + /// The dispatch origin of this call can be any signed account. + /// + /// This transaction has NO MONETARY INCENTIVES. calling it will not reward anyone. Albeit, + /// Upon successful execution, the transaction fee is returned. + /// + /// The (potentially over-estimated) of the byte length of all the data read must be + /// provided for up-front fee-payment and weighing. In essence, the caller is guaranteeing + /// that executing the current `MigrationTask` with the given `limits` will not exceed + /// `real_size_upper` bytes of read data. + /// + /// The `witness_task` is merely a helper to prevent the caller from being slashed or + /// generally trigger a migration that they do not intend. This parameter is just a message + /// from caller, saying that they believed `witness_task` was the last state of the + /// migration, and they only wish for their transaction to do anything, if this assumption + /// holds. In case `witness_task` does not match, the transaction fails. + /// + /// Based on the documentation of [`MigrationTask::migrate_until_exhaustion`], the + /// recommended way of doing this is to pass a `limit` that only bounds `count`, as the + /// `size` limit can always be overwritten. + #[pallet::weight( + // the migration process + Pallet::::dynamic_weight(limits.item, * real_size_upper) + // rest of the operations, like deposit etc. + + T::WeightInfo::continue_migrate() + )] + pub fn continue_migrate( + origin: OriginFor, + limits: MigrationLimits, + real_size_upper: u32, + witness_task: MigrationTask, + ) -> DispatchResultWithPostInfo { + let who = T::SignedFilter::ensure_origin(origin)?; + + let max_limits = T::SignedMigrationMaxLimits::get(); + ensure!( + limits.size <= max_limits.size && limits.item <= max_limits.item, + Error::::MaxSignedLimits, + ); + + // ensure they can pay more than the fee. + let deposit = T::SignedDepositPerItem::get().saturating_mul(limits.item.into()); + ensure!(T::Currency::can_slash(&who, deposit), Error::::NotEnoughFunds); + + let mut task = Self::migration_process(); + ensure!( + task == witness_task, + DispatchErrorWithPostInfo { + error: Error::::BadWitness.into(), + post_info: PostDispatchInfo { + actual_weight: Some(T::WeightInfo::continue_migrate_wrong_witness()), + pays_fee: Pays::Yes + } + } + ); + task.migrate_until_exhaustion(limits); + + // ensure that the migration witness data was correct. + if real_size_upper < task.dyn_size { + // let the imbalance burn. + let (_imbalance, _remainder) = T::Currency::slash(&who, deposit); + Self::deposit_event(Event::::Slashed { who, amount: deposit }); + debug_assert!(_remainder.is_zero()); + return Err(Error::::SizeUpperBoundExceeded.into()) + } + + Self::deposit_event(Event::::Migrated { + top: task.dyn_top_items, + child: task.dyn_child_items, + compute: MigrationCompute::Signed, + }); + + // refund and correct the weight. + let actual_weight = Some( + Pallet::::dynamic_weight(limits.item, task.dyn_size) + .saturating_add(T::WeightInfo::continue_migrate()), + ); + + MigrationProcess::::put(task); + Ok((actual_weight, Pays::No).into()) + } + + /// Migrate the list of top keys by iterating each of them one by one. + /// + /// This does not affect the global migration process tracker ([`MigrationProcess`]), and + /// should only be used in case any keys are leftover due to a bug. + #[pallet::weight( + T::WeightInfo::migrate_custom_top_success() + .max(T::WeightInfo::migrate_custom_top_fail()) + .saturating_add( + Pallet::::dynamic_weight(keys.len() as u32, *witness_size) + ) + )] + pub fn migrate_custom_top( + origin: OriginFor, + keys: Vec>, + witness_size: u32, + ) -> DispatchResultWithPostInfo { + let who = T::SignedFilter::ensure_origin(origin)?; + + // ensure they can pay more than the fee. + let deposit = T::SignedDepositBase::get().saturating_add( + T::SignedDepositPerItem::get().saturating_mul((keys.len() as u32).into()), + ); + ensure!(T::Currency::can_slash(&who, deposit), "not enough funds"); + + let mut dyn_size = 0u32; + for key in &keys { + if let Some(data) = sp_io::storage::get(&key) { + dyn_size = dyn_size.saturating_add(data.len() as u32); + sp_io::storage::set(key, &data); + } + } + + if dyn_size > witness_size { + let (_imbalance, _remainder) = T::Currency::slash(&who, deposit); + Self::deposit_event(Event::::Slashed { who, amount: deposit }); + debug_assert!(_remainder.is_zero()); + Err("wrong witness data".into()) + } else { + Self::deposit_event(Event::::Migrated { + top: keys.len() as u32, + child: 0, + compute: MigrationCompute::Signed, + }); + Ok(PostDispatchInfo { + actual_weight: Some( + T::WeightInfo::migrate_custom_top_success().saturating_add( + Pallet::::dynamic_weight(keys.len() as u32, dyn_size), + ), + ), + pays_fee: Pays::Yes, + }) + } + } + + /// Migrate the list of child keys by iterating each of them one by one. + /// + /// All of the given child keys must be present under one `child_root`. + /// + /// This does not affect the global migration process tracker ([`MigrationProcess`]), and + /// should only be used in case any keys are leftover due to a bug. + #[pallet::weight( + T::WeightInfo::migrate_custom_child_success() + .max(T::WeightInfo::migrate_custom_child_fail()) + .saturating_add( + Pallet::::dynamic_weight(child_keys.len() as u32, *total_size) + ) + )] + pub fn migrate_custom_child( + origin: OriginFor, + root: Vec, + child_keys: Vec>, + total_size: u32, + ) -> DispatchResultWithPostInfo { + use sp_io::default_child_storage as child_io; + let who = T::SignedFilter::ensure_origin(origin)?; + + // ensure they can pay more than the fee. + let deposit = T::SignedDepositBase::get().saturating_add( + T::SignedDepositPerItem::get().saturating_mul((child_keys.len() as u32).into()), + ); + sp_std::if_std! { + println!("+ {:?} / {:?} / {:?}", who, deposit, T::Currency::free_balance(&who)); + } + ensure!(T::Currency::can_slash(&who, deposit), "not enough funds"); + + let mut dyn_size = 0u32; + let transformed_child_key = Self::transform_child_key(&root).ok_or("bad child key")?; + for child_key in &child_keys { + if let Some(data) = child_io::get(transformed_child_key, &child_key) { + dyn_size = dyn_size.saturating_add(data.len() as u32); + child_io::set(transformed_child_key, &child_key, &data); + } + } + + if dyn_size != total_size { + let (_imbalance, _remainder) = T::Currency::slash(&who, deposit); + debug_assert!(_remainder.is_zero()); + Self::deposit_event(Event::::Slashed { who, amount: deposit }); + Err(DispatchErrorWithPostInfo { + error: "bad witness".into(), + post_info: PostDispatchInfo { + actual_weight: Some(T::WeightInfo::migrate_custom_child_fail()), + pays_fee: Pays::Yes, + }, + }) + } else { + Self::deposit_event(Event::::Migrated { + top: 0, + child: child_keys.len() as u32, + compute: MigrationCompute::Signed, + }); + Ok(PostDispatchInfo { + actual_weight: Some( + T::WeightInfo::migrate_custom_child_success().saturating_add( + Pallet::::dynamic_weight(child_keys.len() as u32, total_size), + ), + ), + pays_fee: Pays::Yes, + }) + } + } + } + + #[pallet::hooks] + impl Hooks> for Pallet { + fn on_initialize(_: BlockNumberFor) -> Weight { + if let Some(limits) = Self::auto_limits() { + let mut task = Self::migration_process(); + task.migrate_until_exhaustion(limits); + let weight = Self::dynamic_weight(task.dyn_total_items(), task.dyn_size); + + log!( + info, + "migrated {} top keys, {} child keys, and a total of {} bytes.", + task.dyn_top_items, + task.dyn_child_items, + task.dyn_size, + ); + + if task.finished() { + Self::deposit_event(Event::::AutoMigrationFinished); + AutoLimits::::kill(); + } else { + Self::deposit_event(Event::::Migrated { + top: task.dyn_top_items, + child: task.dyn_child_items, + compute: MigrationCompute::Auto, + }); + } + + MigrationProcess::::put(task); + + weight + } else { + T::DbWeight::get().reads(1) + } + } + } + + impl Pallet { + /// The real weight of a migration of the given number of `items` with total `size`. + fn dynamic_weight(items: u32, size: u32) -> frame_support::pallet_prelude::Weight { + let items = items as Weight; + items + .saturating_mul(::DbWeight::get().reads_writes(1, 1)) + // we assume that the read/write per-byte weight is the same for child and top tree. + .saturating_add(T::WeightInfo::process_top_key(size)) + } + + /// Put a stop to all ongoing migrations. + fn halt() { + AutoLimits::::kill(); + Self::deposit_event(Event::::Halted); + } + + /// Convert a child root key, aka. "Child-bearing top key" into the proper format. + fn transform_child_key(root: &Vec) -> Option<&[u8]> { + use sp_core::storage::{ChildType, PrefixedStorageKey}; + match ChildType::from_prefixed_key(PrefixedStorageKey::new_ref(root)) { + Some((ChildType::ParentKeyId, root)) => Some(root), + _ => None, + } + } + + /// Same as [`child_io_key`], and it halts the auto/unsigned migrations if a bad child root + /// is used. + /// + /// This should be used when we are sure that `root` is a correct default child root. + fn transform_child_key_or_halt(root: &Vec) -> &[u8] { + let key = Self::transform_child_key(root); + if key.is_none() { + Self::halt(); + } + key.unwrap_or_default() + } + + /// Convert a child root to be in the default child-tree. + #[cfg(any(test, feature = "runtime-benchmarks"))] + pub(crate) fn childify(root: &'static str) -> Vec { + let mut string = DEFAULT_CHILD_STORAGE_KEY_PREFIX.to_vec(); + string.extend_from_slice(root.as_ref()); + string + } + } +} + +#[cfg(feature = "runtime-benchmarks")] +mod benchmarks { + use super::{pallet::Pallet as StateTrieMigration, *}; + use frame_support::traits::{Currency, Get}; + use sp_runtime::traits::Saturating; + use sp_std::prelude::*; + + // The size of the key seemingly makes no difference in the read/write time, so we make it + // constant. + const KEY: &'static [u8] = b"key"; + + frame_benchmarking::benchmarks! { + continue_migrate { + // note that this benchmark should migrate nothing, as we only want the overhead weight + // of the bookkeeping, and the migration cost itself is noted via the `dynamic_weight` + // function. + let null = MigrationLimits::default(); + let caller = frame_benchmarking::whitelisted_caller(); + }: _(frame_system::RawOrigin::Signed(caller), null, 0, StateTrieMigration::::migration_process()) + verify { + assert_eq!(StateTrieMigration::::migration_process(), Default::default()) + } + + continue_migrate_wrong_witness { + let null = MigrationLimits::default(); + let caller = frame_benchmarking::whitelisted_caller(); + let bad_witness = MigrationTask { last_top: Some(vec![1u8]), ..Default::default() }; + }: { + assert!( + StateTrieMigration::::continue_migrate( + frame_system::RawOrigin::Signed(caller).into(), + null, + 0, + bad_witness, + ) + .is_err() + ) + } + verify { + assert_eq!(StateTrieMigration::::migration_process(), Default::default()) + } + + migrate_custom_top_success { + let null = MigrationLimits::default(); + let caller = frame_benchmarking::whitelisted_caller(); + let deposit = T::SignedDepositBase::get().saturating_add( + T::SignedDepositPerItem::get().saturating_mul(1u32.into()), + ); + let stash = T::Currency::minimum_balance() * BalanceOf::::from(1000u32) + deposit; + T::Currency::make_free_balance_be(&caller, stash); + }: migrate_custom_top(frame_system::RawOrigin::Signed(caller.clone()), Default::default(), 0) + verify { + assert_eq!(StateTrieMigration::::migration_process(), Default::default()); + assert_eq!(T::Currency::free_balance(&caller), stash) + } + + migrate_custom_top_fail { + let null = MigrationLimits::default(); + let caller = frame_benchmarking::whitelisted_caller(); + let deposit = T::SignedDepositBase::get().saturating_add( + T::SignedDepositPerItem::get().saturating_mul(1u32.into()), + ); + let stash = T::Currency::minimum_balance() * BalanceOf::::from(1000u32) + deposit; + T::Currency::make_free_balance_be(&caller, stash); + // for tests, we need to make sure there is _something_ in storage that is being + // migrated. + sp_io::storage::set(b"foo", vec![1u8;33].as_ref()); + }: { + assert!( + StateTrieMigration::::migrate_custom_top( + frame_system::RawOrigin::Signed(caller.clone()).into(), + vec![b"foo".to_vec()], + 1, + ).is_err() + ) + } + verify { + assert_eq!(StateTrieMigration::::migration_process(), Default::default()); + // must have gotten slashed + assert!(T::Currency::free_balance(&caller) < stash) + } + + migrate_custom_child_success { + let caller = frame_benchmarking::whitelisted_caller(); + let deposit = T::SignedDepositBase::get().saturating_add( + T::SignedDepositPerItem::get().saturating_mul(1u32.into()), + ); + let stash = T::Currency::minimum_balance() * BalanceOf::::from(1000u32) + deposit; + T::Currency::make_free_balance_be(&caller, stash); + }: migrate_custom_child( + frame_system::RawOrigin::Signed(caller.clone()), + StateTrieMigration::::childify(Default::default()), + Default::default(), + 0 + ) + verify { + assert_eq!(StateTrieMigration::::migration_process(), Default::default()); + assert_eq!(T::Currency::free_balance(&caller), stash); + } + + migrate_custom_child_fail { + let caller = frame_benchmarking::whitelisted_caller(); + let deposit = T::SignedDepositBase::get().saturating_add( + T::SignedDepositPerItem::get().saturating_mul(1u32.into()), + ); + let stash = T::Currency::minimum_balance() * BalanceOf::::from(1000u32) + deposit; + T::Currency::make_free_balance_be(&caller, stash); + // for tests, we need to make sure there is _something_ in storage that is being + // migrated. + sp_io::default_child_storage::set(b"top", b"foo", vec![1u8;33].as_ref()); + }: { + assert!( + StateTrieMigration::::migrate_custom_child( + frame_system::RawOrigin::Signed(caller.clone()).into(), + StateTrieMigration::::childify("top"), + vec![b"foo".to_vec()], + 1, + ).is_err() + ) + } + verify { + assert_eq!(StateTrieMigration::::migration_process(), Default::default()); + // must have gotten slashed + assert!(T::Currency::free_balance(&caller) < stash) + } + + process_top_key { + let v in 1 .. (4 * 1024 * 1024); + + let value = sp_std::vec![1u8; v as usize]; + sp_io::storage::set(KEY, &value); + }: { + let data = sp_io::storage::get(KEY).unwrap(); + sp_io::storage::set(KEY, &data); + let _next = sp_io::storage::next_key(KEY); + assert_eq!(data, value); + } + + impl_benchmark_test_suite!( + StateTrieMigration, + crate::mock::new_test_ext(sp_runtime::StateVersion::V0, true, None, None), + crate::mock::Test + ); + } +} + +#[cfg(test)] +mod mock { + use super::*; + use crate as pallet_state_trie_migration; + use frame_support::{parameter_types, traits::Hooks}; + use frame_system::{EnsureRoot, EnsureSigned}; + use sp_core::{ + storage::{ChildInfo, StateVersion}, + H256, + }; + use sp_runtime::{ + traits::{BlakeTwo256, Header as _, IdentityLookup}, + StorageChild, + }; + + type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; + type Block = frame_system::mocking::MockBlock; + + // Configure a mock runtime to test the pallet. + frame_support::construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Balances: pallet_balances::{Pallet, Call, Config, Storage, Event}, + StateTrieMigration: pallet_state_trie_migration::{Pallet, Call, Storage, Event}, + } + ); + + parameter_types! { + pub const BlockHashCount: u32 = 250; + pub const SS58Prefix: u8 = 42; + } + + impl frame_system::Config for Test { + type BaseCallFilter = frame_support::traits::Everything; + type BlockWeights = (); + type BlockLength = (); + type Origin = Origin; + type Call = Call; + type Index = u64; + type BlockNumber = u32; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = sp_runtime::generic::Header; + type Event = Event; + type BlockHashCount = BlockHashCount; + type DbWeight = (); + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = SS58Prefix; + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; + } + + parameter_types! { + pub const ExistentialDeposit: u64 = 1; + pub const OffchainRepeat: u32 = 1; + pub const SignedDepositPerItem: u64 = 1; + pub const SignedDepositBase: u64 = 5; + pub const SignedMigrationMaxLimits: MigrationLimits = MigrationLimits { size: 1024, item: 5 }; + } + + impl pallet_balances::Config for Test { + type Balance = u64; + type Event = Event; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type MaxLocks = (); + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; + type WeightInfo = (); + } + + impl pallet_state_trie_migration::Config for Test { + type Event = Event; + type ControlOrigin = EnsureRoot; + type Currency = Balances; + type SignedDepositPerItem = SignedDepositPerItem; + type SignedDepositBase = SignedDepositBase; + type SignedMigrationMaxLimits = SignedMigrationMaxLimits; + type SignedFilter = EnsureSigned; + type WeightInfo = (); + } + + pub fn new_test_ext( + version: StateVersion, + with_pallets: bool, + custom_keys: Option, Vec)>>, + custom_child: Option, Vec, Vec)>>, + ) -> sp_io::TestExternalities { + let minimum_size = sp_core::storage::TRIE_VALUE_NODE_THRESHOLD as usize + 1; + let mut custom_storage = sp_core::storage::Storage { + top: vec![ + (b"key1".to_vec(), vec![1u8; minimum_size + 1]), // 6b657931 + (b"key2".to_vec(), vec![1u8; minimum_size + 2]), // 6b657931 + (b"key3".to_vec(), vec![1u8; minimum_size + 3]), // 6b657931 + (b"key4".to_vec(), vec![1u8; minimum_size + 4]), // 6b657931 + (b"key5".to_vec(), vec![1u8; minimum_size + 5]), // 6b657932 + (b"key6".to_vec(), vec![1u8; minimum_size + 6]), // 6b657934 + (b"key7".to_vec(), vec![1u8; minimum_size + 7]), // 6b657934 + (b"key8".to_vec(), vec![1u8; minimum_size + 8]), // 6b657934 + (b"key9".to_vec(), vec![1u8; minimum_size + 9]), // 6b657934 + (b"CODE".to_vec(), vec![1u8; minimum_size + 100]), // 434f4445 + ] + .into_iter() + .chain(custom_keys.unwrap_or_default()) + .collect(), + children_default: vec![ + ( + b"chk1".to_vec(), // 63686b31 + StorageChild { + data: vec![ + (b"key1".to_vec(), vec![1u8; 55]), + (b"key2".to_vec(), vec![2u8; 66]), + ] + .into_iter() + .collect(), + child_info: ChildInfo::new_default(b"chk1"), + }, + ), + ( + b"chk2".to_vec(), + StorageChild { + data: vec![ + (b"key1".to_vec(), vec![1u8; 54]), + (b"key2".to_vec(), vec![2u8; 64]), + ] + .into_iter() + .collect(), + child_info: ChildInfo::new_default(b"chk2"), + }, + ), + ] + .into_iter() + .chain( + custom_child + .unwrap_or_default() + .into_iter() + .map(|(r, k, v)| { + ( + r.clone(), + StorageChild { + data: vec![(k, v)].into_iter().collect(), + child_info: ChildInfo::new_default(&r), + }, + ) + }) + .collect::>(), + ) + .collect(), + }; + + if with_pallets { + frame_system::GenesisConfig::default() + .assimilate_storage::(&mut custom_storage) + .unwrap(); + pallet_balances::GenesisConfig:: { balances: vec![(1, 1000)] } + .assimilate_storage(&mut custom_storage) + .unwrap(); + } + + sp_tracing::try_init_simple(); + (custom_storage, version).into() + } + + pub(crate) fn run_to_block(n: u32) -> (H256, u64) { + let mut root = Default::default(); + let mut weight_sum = 0; + log::trace!(target: LOG_TARGET, "running from {:?} to {:?}", System::block_number(), n); + while System::block_number() < n { + System::set_block_number(System::block_number() + 1); + System::on_initialize(System::block_number()); + + weight_sum += StateTrieMigration::on_initialize(System::block_number()); + + root = System::finalize().state_root().clone(); + System::on_finalize(System::block_number()); + } + (root, weight_sum) + } +} + +#[cfg(test)] +mod test { + use super::{mock::*, *}; + use sp_runtime::{traits::Bounded, StateVersion}; + + #[test] + fn fails_if_no_migration() { + let mut ext = new_test_ext(StateVersion::V0, false, None, None); + let root1 = ext.execute_with(|| run_to_block(30).0); + + let mut ext2 = new_test_ext(StateVersion::V1, false, None, None); + let root2 = ext2.execute_with(|| run_to_block(30).0); + + // these two roots should not be the same. + assert_ne!(root1, root2); + } + + #[test] + #[ignore] + fn detects_value_in_empty_top_key() { + let limit = MigrationLimits { item: 1, size: 1000 }; + let initial_keys = Some(vec![(vec![], vec![66u8; 77])]); + let mut ext = new_test_ext(StateVersion::V0, false, initial_keys.clone(), None); + + let root_upgraded = ext.execute_with(|| { + sp_io::storage::set(&[], &vec![66u8; 77]); + + AutoLimits::::put(Some(limit)); + let root = run_to_block(30).0; + + // eventually everything is over. + assert!(StateTrieMigration::migration_process().finished()); + root + }); + + let mut ext2 = new_test_ext(StateVersion::V1, false, initial_keys, None); + let root = ext2.execute_with(|| { + AutoLimits::::put(Some(limit)); + run_to_block(30).0 + }); + + assert_eq!(root, root_upgraded); + } + + #[test] + #[ignore] + fn detects_value_in_first_child_key() { + use frame_support::storage::child; + let limit = MigrationLimits { item: 1, size: 1000 }; + let initial_child = Some(vec![(b"chk1".to_vec(), vec![], vec![66u8; 77])]); + let mut ext = new_test_ext(StateVersion::V0, false, None, initial_child.clone()); + + let root_upgraded = ext.execute_with(|| { + AutoLimits::::put(Some(limit)); + let root = run_to_block(30).0; + + // eventually everything is over. + assert!(StateTrieMigration::migration_process().finished()); + root + }); + + let mut ext2 = new_test_ext(StateVersion::V1, false, None, initial_child); + let root = ext2.execute_with(|| { + child::put(&child::ChildInfo::new_default(b"chk1"), &[], &vec![66u8; 77]); + AutoLimits::::put(Some(limit)); + run_to_block(30).0 + }); + + assert_eq!(root, root_upgraded); + } + + #[test] + fn auto_migrate_works() { + let run_with_limits = |limit, from, until| { + let mut ext = new_test_ext(StateVersion::V0, false, None, None); + let root_upgraded = ext.execute_with(|| { + assert_eq!(AutoLimits::::get(), None); + assert_eq!(MigrationProcess::::get(), Default::default()); + + // nothing happens if we don't set the limits. + let _ = run_to_block(from); + assert_eq!(MigrationProcess::::get(), Default::default()); + + // this should allow 1 item per block to be migrated. + AutoLimits::::put(Some(limit)); + + let root = run_to_block(until).0; + + // eventually everything is over. + assert!(matches!( + StateTrieMigration::migration_process(), + MigrationTask { last_child: None, last_top: None, .. } + )); + root + }); + + let mut ext2 = new_test_ext(StateVersion::V1, false, None, None); + let root = ext2.execute_with(|| { + // update ex2 to contain the new items + let _ = run_to_block(from); + AutoLimits::::put(Some(limit)); + run_to_block(until).0 + }); + assert_eq!(root, root_upgraded); + }; + + // single item + run_with_limits(MigrationLimits { item: 1, size: 1000 }, 10, 100); + // multi-item + run_with_limits(MigrationLimits { item: 5, size: 1000 }, 10, 100); + // multi-item, based on size. Note that largest value is 100 bytes. + run_with_limits(MigrationLimits { item: 1000, size: 128 }, 10, 100); + // unbounded + run_with_limits( + MigrationLimits { item: Bounded::max_value(), size: Bounded::max_value() }, + 10, + 100, + ); + } + + #[test] + fn signed_migrate_works() { + new_test_ext(StateVersion::V0, true, None, None).execute_with(|| { + assert_eq!(MigrationProcess::::get(), Default::default()); + + // can't submit if limit is too high. + frame_support::assert_err!( + StateTrieMigration::continue_migrate( + Origin::signed(1), + MigrationLimits { item: 5, size: sp_runtime::traits::Bounded::max_value() }, + Bounded::max_value(), + MigrationProcess::::get() + ), + Error::::MaxSignedLimits, + ); + + // can't submit if poor. + frame_support::assert_err!( + StateTrieMigration::continue_migrate( + Origin::signed(2), + MigrationLimits { item: 5, size: 100 }, + 100, + MigrationProcess::::get() + ), + Error::::NotEnoughFunds, + ); + + // can't submit with bad witness. + frame_support::assert_err_ignore_postinfo!( + StateTrieMigration::continue_migrate( + Origin::signed(1), + MigrationLimits { item: 5, size: 100 }, + 100, + MigrationTask { last_top: Some(vec![1u8]), ..Default::default() } + ), + Error::::BadWitness + ); + + // migrate all keys in a series of submissions + while !MigrationProcess::::get().finished() { + // first we compute the task to get the accurate consumption. + let mut task = StateTrieMigration::migration_process(); + task.migrate_until_exhaustion(SignedMigrationMaxLimits::get()); + + frame_support::assert_ok!(StateTrieMigration::continue_migrate( + Origin::signed(1), + SignedMigrationMaxLimits::get(), + task.dyn_size, + MigrationProcess::::get() + )); + + // no funds should remain reserved. + assert_eq!(Balances::reserved_balance(&1), 0); + + // and the task should be updated + assert!(matches!( + StateTrieMigration::migration_process(), + MigrationTask { size: x, .. } if x > 0, + )); + } + }); + } + + #[test] + fn custom_migrate_top_works() { + let correct_witness = 3 + sp_core::storage::TRIE_VALUE_NODE_THRESHOLD * 3 + 1 + 2 + 3; + new_test_ext(StateVersion::V0, true, None, None).execute_with(|| { + frame_support::assert_ok!(StateTrieMigration::migrate_custom_top( + Origin::signed(1), + vec![b"key1".to_vec(), b"key2".to_vec(), b"key3".to_vec()], + correct_witness, + )); + + // no funds should remain reserved. + assert_eq!(Balances::reserved_balance(&1), 0); + assert_eq!(Balances::free_balance(&1), 1000); + }); + + new_test_ext(StateVersion::V0, true, None, None).execute_with(|| { + // works if the witness is an overestimate + frame_support::assert_ok!(StateTrieMigration::migrate_custom_top( + Origin::signed(1), + vec![b"key1".to_vec(), b"key2".to_vec(), b"key3".to_vec()], + correct_witness + 99, + )); + + // no funds should remain reserved. + assert_eq!(Balances::reserved_balance(&1), 0); + assert_eq!(Balances::free_balance(&1), 1000); + }); + + new_test_ext(StateVersion::V0, true, None, None).execute_with(|| { + assert_eq!(Balances::free_balance(&1), 1000); + + // note that we don't expect this to be a noop -- we do slash. + frame_support::assert_err!( + StateTrieMigration::migrate_custom_top( + Origin::signed(1), + vec![b"key1".to_vec(), b"key2".to_vec(), b"key3".to_vec()], + correct_witness - 1, + ), + "wrong witness data" + ); + + // no funds should remain reserved. + assert_eq!(Balances::reserved_balance(&1), 0); + assert_eq!( + Balances::free_balance(&1), + 1000 - (3 * SignedDepositPerItem::get() + SignedDepositBase::get()) + ); + }); + } + + #[test] + fn custom_migrate_child_works() { + new_test_ext(StateVersion::V0, true, None, None).execute_with(|| { + frame_support::assert_ok!(StateTrieMigration::migrate_custom_child( + Origin::signed(1), + StateTrieMigration::childify("chk1"), + vec![b"key1".to_vec(), b"key2".to_vec()], + 55 + 66, + )); + + // no funds should remain reserved. + assert_eq!(Balances::reserved_balance(&1), 0); + assert_eq!(Balances::free_balance(&1), 1000); + }); + + new_test_ext(StateVersion::V0, true, None, None).execute_with(|| { + assert_eq!(Balances::free_balance(&1), 1000); + + // note that we don't expect this to be a noop -- we do slash. + assert!(StateTrieMigration::migrate_custom_child( + Origin::signed(1), + StateTrieMigration::childify("chk1"), + vec![b"key1".to_vec(), b"key2".to_vec()], + 999999, // wrong witness + ) + .is_err()); + + // no funds should remain reserved. + assert_eq!(Balances::reserved_balance(&1), 0); + assert_eq!( + Balances::free_balance(&1), + 1000 - (2 * SignedDepositPerItem::get() + SignedDepositBase::get()) + ); + }); + } +} + +/// Exported set of tests to be called against different runtimes. +#[cfg(feature = "remote-test")] +pub(crate) mod remote_tests { + use crate::{AutoLimits, MigrationLimits, Pallet as StateTrieMigration, LOG_TARGET}; + use codec::Encode; + use frame_benchmarking::Zero; + use frame_support::traits::{Get, Hooks}; + use frame_system::Pallet as System; + use remote_externalities::Mode; + use sp_core::H256; + use sp_runtime::traits::{Block as BlockT, HashFor, Header as _, One}; + use thousands::Separable; + + fn run_to_block>( + n: ::BlockNumber, + ) -> (H256, u64) { + let mut root = Default::default(); + let mut weight_sum = 0; + while System::::block_number() < n { + System::::set_block_number(System::::block_number() + One::one()); + System::::on_initialize(System::::block_number()); + + weight_sum += + StateTrieMigration::::on_initialize(System::::block_number()); + + root = System::::finalize().state_root().clone(); + System::::on_finalize(System::::block_number()); + } + (root, weight_sum) + } + + /// Run the entire migration, against the given `Runtime`, until completion. + /// + /// This will print some very useful statistics, make sure [`crate::LOG_TARGET`] is enabled. + pub(crate) async fn run_with_limits< + Runtime: crate::Config, + Block: BlockT + serde::de::DeserializeOwned, + >( + limits: MigrationLimits, + mode: Mode, + ) { + let mut ext = remote_externalities::Builder::::new() + .mode(mode) + .state_version(sp_core::storage::StateVersion::V0) + .build() + .await + .unwrap(); + + let mut now = ext.execute_with(|| { + AutoLimits::::put(Some(limits)); + // requires the block number type in our tests to be same as with mainnet, u32. + frame_system::Pallet::::block_number() + }); + + let mut duration: ::BlockNumber = Zero::zero(); + // set the version to 1, as if the upgrade happened. + ext.state_version = sp_core::storage::StateVersion::V1; + + let (top_left, child_left) = ext.as_backend().essence().check_migration_state().unwrap(); + assert!( + top_left > 0, + "no node needs migrating, this probably means that state was initialized with `StateVersion::V1`", + ); + + log::info!( + target: LOG_TARGET, + "initial check: top_left: {}, child_left: {}", + top_left.separate_with_commas(), + child_left.separate_with_commas(), + ); + + loop { + let last_state_root = ext.backend.root().clone(); + let ((finished, weight), proof) = ext.execute_and_prove(|| { + let weight = run_to_block::(now + One::one()).1; + if StateTrieMigration::::migration_process().finished() { + return (true, weight) + } + duration += One::one(); + now += One::one(); + (false, weight) + }); + + let compact_proof = + proof.clone().into_compact_proof::>(last_state_root).unwrap(); + log::info!( + target: LOG_TARGET, + "proceeded to #{}, weight: [{} / {}], proof: [{} / {} / {}]", + now, + weight.separate_with_commas(), + ::BlockWeights::get() + .max_block + .separate_with_commas(), + proof.encoded_size().separate_with_commas(), + compact_proof.encoded_size().separate_with_commas(), + zstd::stream::encode_all(&compact_proof.encode()[..], 0) + .unwrap() + .len() + .separate_with_commas(), + ); + ext.commit_all().unwrap(); + + if finished { + break + } + } + + ext.execute_with(|| { + log::info!( + target: LOG_TARGET, + "finished on_initialize migration in {} block, final state of the task: {:?}", + duration, + StateTrieMigration::::migration_process(), + ) + }); + + let (top_left, child_left) = ext.as_backend().essence().check_migration_state().unwrap(); + assert_eq!(top_left, 0); + assert_eq!(child_left, 0); + } +} + +#[cfg(all(test, feature = "remote-test"))] +mod remote_tests_local { + use super::{ + mock::{Call as MockCall, *}, + remote_tests::run_with_limits, + *, + }; + use remote_externalities::{Mode, OfflineConfig, OnlineConfig}; + use sp_runtime::traits::Bounded; + + // we only use the hash type from this, so using the mock should be fine. + type Extrinsic = sp_runtime::testing::TestXt; + type Block = sp_runtime::testing::Block; + + #[tokio::test] + async fn on_initialize_migration() { + sp_tracing::try_init_simple(); + let mode = Mode::OfflineOrElseOnline( + OfflineConfig { state_snapshot: env!("SNAP").to_owned().into() }, + OnlineConfig { + transport: std::env!("WS_API").to_owned().into(), + state_snapshot: Some(env!("SNAP").to_owned().into()), + ..Default::default() + }, + ); + + // item being the bottleneck + run_with_limits::( + MigrationLimits { item: 8 * 1024, size: 128 * 1024 * 1024 }, + mode.clone(), + ) + .await; + // size being the bottleneck + run_with_limits::( + MigrationLimits { item: Bounded::max_value(), size: 64 * 1024 }, + mode, + ) + .await; + } +} diff --git a/frame/state-trie-migration/src/weights.rs b/frame/state-trie-migration/src/weights.rs new file mode 100644 index 000000000000..f08b115378f2 --- /dev/null +++ b/frame/state-trie-migration/src/weights.rs @@ -0,0 +1,137 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +//! Autogenerated weights for pallet_state_trie_migration +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2022-03-04, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 + +// Executed Command: +// target/production/substrate +// benchmark +// --chain=dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_state_trie_migration +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 +// --output=./frame/state-trie-migration/src/weights.rs +// --template=./.maintain/frame-weight-template.hbs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +/// Weight functions needed for pallet_state_trie_migration. +pub trait WeightInfo { + fn continue_migrate() -> Weight; + fn continue_migrate_wrong_witness() -> Weight; + fn migrate_custom_top_success() -> Weight; + fn migrate_custom_top_fail() -> Weight; + fn migrate_custom_child_success() -> Weight; + fn migrate_custom_child_fail() -> Weight; + fn process_top_key(v: u32, ) -> Weight; +} + +/// Weights for pallet_state_trie_migration using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + // Storage: StateTrieMigration MigrationProcess (r:1 w:1) + fn continue_migrate() -> Weight { + (13_385_000 as Weight) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + // Storage: StateTrieMigration MigrationProcess (r:1 w:0) + fn continue_migrate_wrong_witness() -> Weight { + (1_757_000 as Weight) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + } + fn migrate_custom_top_success() -> Weight { + (12_813_000 as Weight) + } + // Storage: unknown [0x666f6f] (r:1 w:1) + fn migrate_custom_top_fail() -> Weight { + (24_961_000 as Weight) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + fn migrate_custom_child_success() -> Weight { + (13_132_000 as Weight) + } + // Storage: unknown [0x666f6f] (r:1 w:1) + fn migrate_custom_child_fail() -> Weight { + (29_215_000 as Weight) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + // Storage: unknown [0x6b6579] (r:1 w:1) + fn process_top_key(v: u32, ) -> Weight { + (0 as Weight) + // Standard Error: 0 + .saturating_add((2_000 as Weight).saturating_mul(v as Weight)) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } +} + +// For backwards compatibility and tests +impl WeightInfo for () { + // Storage: StateTrieMigration MigrationProcess (r:1 w:1) + fn continue_migrate() -> Weight { + (13_385_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + // Storage: StateTrieMigration MigrationProcess (r:1 w:0) + fn continue_migrate_wrong_witness() -> Weight { + (1_757_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + } + fn migrate_custom_top_success() -> Weight { + (12_813_000 as Weight) + } + // Storage: unknown [0x666f6f] (r:1 w:1) + fn migrate_custom_top_fail() -> Weight { + (24_961_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + fn migrate_custom_child_success() -> Weight { + (13_132_000 as Weight) + } + // Storage: unknown [0x666f6f] (r:1 w:1) + fn migrate_custom_child_fail() -> Weight { + (29_215_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + // Storage: unknown [0x6b6579] (r:1 w:1) + fn process_top_key(v: u32, ) -> Weight { + (0 as Weight) + // Standard Error: 0 + .saturating_add((2_000 as Weight).saturating_mul(v as Weight)) + .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } +} diff --git a/frame/support/src/traits/misc.rs b/frame/support/src/traits/misc.rs index d2fd438d3a80..8c61874003bc 100644 --- a/frame/support/src/traits/misc.rs +++ b/frame/support/src/traits/misc.rs @@ -38,18 +38,18 @@ macro_rules! defensive { frame_support::log::error!( target: "runtime", "{}", - $crate::traits::misc::DEFENSIVE_OP_PUBLIC_ERROR + $crate::traits::DEFENSIVE_OP_PUBLIC_ERROR ); - debug_assert!(false, "{}", $crate::traits::misc::DEFENSIVE_OP_INTERNAL_ERROR); + debug_assert!(false, "{}", $crate::traits::DEFENSIVE_OP_INTERNAL_ERROR); }; ($error:tt) => { frame_support::log::error!( target: "runtime", "{}: {:?}", - $crate::traits::misc::DEFENSIVE_OP_PUBLIC_ERROR, + $crate::traits::DEFENSIVE_OP_PUBLIC_ERROR, $error ); - debug_assert!(false, "{}: {:?}", $crate::traits::misc::DEFENSIVE_OP_INTERNAL_ERROR, $error); + debug_assert!(false, "{}: {:?}", $crate::traits::DEFENSIVE_OP_INTERNAL_ERROR, $error); } } diff --git a/primitives/core/src/lib.rs b/primitives/core/src/lib.rs index d21364d3f8fb..b7c8b69e8a0a 100644 --- a/primitives/core/src/lib.rs +++ b/primitives/core/src/lib.rs @@ -96,7 +96,7 @@ pub enum ExecutionContext { /// We distinguish between major sync and import so that validators who are running /// their initial sync (or catching up after some time offline) can use the faster /// native runtime (since we can reasonably assume the network as a whole has already - /// come to a broad conensus on the block and it probably hasn't been crafted + /// come to a broad consensus on the block and it probably hasn't been crafted /// specifically to attack this node), but when importing blocks at the head of the /// chain in normal operation they can use the safer Wasm version. Syncing, diff --git a/primitives/state-machine/src/testing.rs b/primitives/state-machine/src/testing.rs index 6be601aa72b3..7f71d24b761a 100644 --- a/primitives/state-machine/src/testing.rs +++ b/primitives/state-machine/src/testing.rs @@ -23,8 +23,8 @@ use std::{ }; use crate::{ - backend::Backend, ext::Ext, InMemoryBackend, InMemoryProvingBackend, OverlayedChanges, - StorageKey, StorageTransactionCache, StorageValue, + backend::Backend, ext::Ext, InMemoryBackend, OverlayedChanges, StorageKey, + StorageTransactionCache, StorageValue, }; use hash_db::Hasher; @@ -100,7 +100,6 @@ where state_version: StateVersion, ) -> Self { assert!(storage.top.keys().all(|key| !is_child_storage_key(key))); - assert!(storage.children_default.keys().all(|key| is_child_storage_key(key))); storage.top.insert(CODE.to_vec(), code.to_vec()); @@ -204,7 +203,7 @@ where /// This implementation will wipe the proof recorded in between calls. Consecutive calls will /// get their own proof from scratch. pub fn execute_and_prove(&mut self, execute: impl FnOnce() -> R) -> (R, StorageProof) { - let proving_backend = InMemoryProvingBackend::new(&self.backend); + let proving_backend = crate::InMemoryProvingBackend::new(&self.backend); let mut proving_ext = Ext::new( &mut self.overlay, &mut self.storage_transaction_cache, diff --git a/primitives/state-machine/src/trie_backend_essence.rs b/primitives/state-machine/src/trie_backend_essence.rs index e33e50641bbd..b0eb54382437 100644 --- a/primitives/state-machine/src/trie_backend_essence.rs +++ b/primitives/state-machine/src/trie_backend_essence.rs @@ -23,21 +23,23 @@ use codec::Encode; use hash_db::{self, AsHashDB, HashDB, HashDBRef, Hasher, Prefix}; #[cfg(feature = "std")] use parking_lot::RwLock; -use sp_core::storage::{ChildInfo, ChildType, StateVersion}; +use sp_core::storage::{ChildInfo, ChildType, PrefixedStorageKey, StateVersion}; use sp_std::{boxed::Box, vec::Vec}; use sp_trie::{ child_delta_trie_root, delta_trie_root, empty_child_trie_root, read_child_trie_value, read_trie_value, trie_types::{TrieDB, TrieError}, - DBValue, KeySpacedDB, PrefixedMemoryDB, Trie, TrieDBIterator, TrieDBKeyIterator, + DBValue, KeySpacedDB, LayoutV1 as Layout, PrefixedMemoryDB, Trie, TrieDBIterator, + TrieDBKeyIterator, }; #[cfg(feature = "std")] use std::collections::HashMap; #[cfg(feature = "std")] use std::sync::Arc; -// In this module, we only use layout for read operation and empty root, -// where V1 and V0 are equivalent. -use sp_trie::LayoutV1 as Layout; +use trie_db::{ + node::{NodePlan, ValuePlan}, + TrieDBNodeIterator, +}; #[cfg(not(feature = "std"))] macro_rules! format { @@ -431,6 +433,72 @@ where ); } + /// Check remaining state item to migrate. Note this function should be remove when all state + /// migration did finished as it is only an utility. + // original author: @cheme + pub fn check_migration_state(&self) -> Result<(u64, u64)> { + let threshold: u32 = sp_core::storage::TRIE_VALUE_NODE_THRESHOLD; + let mut nb_to_migrate = 0; + let mut nb_to_migrate_child = 0; + + let trie = sp_trie::trie_types::TrieDB::new(self, &self.root) + .map_err(|e| format!("TrieDB creation error: {}", e))?; + let iter_node = TrieDBNodeIterator::new(&trie) + .map_err(|e| format!("TrieDB node iterator error: {}", e))?; + for node in iter_node { + let node = node.map_err(|e| format!("TrieDB node iterator error: {}", e))?; + match node.2.node_plan() { + NodePlan::Leaf { value, .. } | + NodePlan::NibbledBranch { value: Some(value), .. } => + if let ValuePlan::Inline(range) = value { + if (range.end - range.start) as u32 >= threshold { + nb_to_migrate += 1; + } + }, + _ => (), + } + } + + let mut child_roots: Vec<(ChildInfo, Vec)> = Vec::new(); + // get all child trie roots + for key_value in trie.iter().map_err(|e| format!("TrieDB node iterator error: {}", e))? { + let (key, value) = + key_value.map_err(|e| format!("TrieDB node iterator error: {}", e))?; + if key[..] + .starts_with(sp_core::storage::well_known_keys::DEFAULT_CHILD_STORAGE_KEY_PREFIX) + { + let prefixed_key = PrefixedStorageKey::new(key); + let (_type, unprefixed) = ChildType::from_prefixed_key(&prefixed_key).unwrap(); + child_roots.push((ChildInfo::new_default(unprefixed), value)); + } + } + for (child_info, root) in child_roots { + let mut child_root = H::Out::default(); + let storage = KeySpacedDB::new(self, child_info.keyspace()); + + child_root.as_mut()[..].copy_from_slice(&root[..]); + let trie = sp_trie::trie_types::TrieDB::new(&storage, &child_root) + .map_err(|e| format!("New child TrieDB error: {}", e))?; + let iter_node = TrieDBNodeIterator::new(&trie) + .map_err(|e| format!("TrieDB node iterator error: {}", e))?; + for node in iter_node { + let node = node.map_err(|e| format!("Child TrieDB node iterator error: {}", e))?; + match node.2.node_plan() { + NodePlan::Leaf { value, .. } | + NodePlan::NibbledBranch { value: Some(value), .. } => + if let ValuePlan::Inline(range) = value { + if (range.end - range.start) as u32 >= threshold { + nb_to_migrate_child += 1; + } + }, + _ => (), + } + } + } + + Ok((nb_to_migrate, nb_to_migrate_child)) + } + /// Returns all `(key, value)` pairs in the trie. pub fn pairs(&self) -> Vec<(StorageKey, StorageValue)> { let collect_all = || -> sp_std::result::Result<_, Box>> { diff --git a/primitives/storage/src/lib.rs b/primitives/storage/src/lib.rs index 1e97454b2605..d377ea931df2 100644 --- a/primitives/storage/src/lib.rs +++ b/primitives/storage/src/lib.rs @@ -119,8 +119,7 @@ impl DerefMut for PrefixedStorageKey { } impl PrefixedStorageKey { - /// Create a prefixed storage key from its byte array - /// representation. + /// Create a prefixed storage key from its byte array representation. pub fn new(inner: Vec) -> Self { PrefixedStorageKey(inner) } @@ -130,9 +129,7 @@ impl PrefixedStorageKey { PrefixedStorageKey::ref_cast(inner) } - /// Get inner key, this should - /// only be needed when writing - /// into parent trie to avoid an + /// Get inner key, this should only be needed when writing into parent trie to avoid an /// allocation. pub fn into_inner(self) -> Vec { self.0 @@ -171,10 +168,8 @@ pub struct StorageChild { pub struct Storage { /// Top trie storage data. pub top: StorageMap, - /// Children trie storage data. - /// The key does not including prefix, for the `default` - /// trie kind, so this is exclusively for the `ChildType::ParentKeyId` - /// tries. + /// Children trie storage data. Key does not include prefix, only for the `default` trie kind, + /// of `ChildType::ParentKeyId` type. pub children_default: std::collections::HashMap, StorageChild>, } diff --git a/utils/frame/remote-externalities/src/lib.rs b/utils/frame/remote-externalities/src/lib.rs index d6dfd1c59d4e..533d65c49c2e 100644 --- a/utils/frame/remote-externalities/src/lib.rs +++ b/utils/frame/remote-externalities/src/lib.rs @@ -40,7 +40,7 @@ use sp_core::{ }, }; pub use sp_io::TestExternalities; -use sp_runtime::traits::Block as BlockT; +use sp_runtime::{traits::Block as BlockT, StateVersion}; use std::{ fs, path::{Path, PathBuf}, @@ -56,6 +56,7 @@ type ChildKeyValues = Vec<(ChildInfo, Vec)>; const LOG_TARGET: &str = "remote-ext"; const DEFAULT_TARGET: &str = "wss://rpc.polkadot.io:443"; const BATCH_SIZE: usize = 1000; +const PAGE: u32 = 512; #[rpc(client)] pub trait RpcApi { @@ -117,12 +118,6 @@ pub struct OfflineConfig { pub state_snapshot: SnapshotConfig, } -impl> From

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 z zrVm@R2GGKYK@G60ok0(2kyVf|_rg*m%AH_j-uZ0+p6C#F| zUIyA5SZF@`33|sa!{TM5VjEvU?Ct8|cYT4vVjJYJh}pU?QzvS9_Su4@*&%$i&ckL;@>YqAh(2kf_xS zPF0O`^Mcl{VwWzlS@%>f0O)6f`z=qn>LARHJ*g6o(PlEK%LEA*m7pR+3qHpdO1Y2oHmgU$?#Hhun|ia_1R z(oNexV1%vesf@HlqMD~gH8$%gky^E1Rf$A^fZ*7UC9mc3DTA;I-5IW{Hm2{*s>q4b zDA9@1Hmy5R%KTm0y&U2q6fgT5Z~Dx>?C3JB?K{=mFG_Uf`pfsH@`J^GSLCkSy&S?Q z%CM!YO)xDVz%JI+>LGn4(bBdh>r;OYDc-;fl%aW7kNV?FxrAD`K$}jZUD0TF8^z$J z6KJ&CpwXTv5O{^N=1M#Hk9E-3lN?!uXb-^{^EOeLxhF&FggqJTiB~rI&K;23%&^ni zg~CCcqG+`PyEvIB+p)>9bPw5RWhC9xHEE^k9#Y|RQ4HjuXo4xD7&0>r{@CVZVW)bl z`H>lwQruWp3w0ft(!G{ z3fg2KQb?TN(&9RHN5@+Lf|JN^QyqvPkljElb*v{!DPoyA7Rz<%mO50WKMnITdUWUz zXC@aVo`)ToS%Diwp0nZQ4UC+~Q~z=UBTrr%WUm#Msk(=AVfeypC8F5P9`*lYVv%H|yuhA&8g4XGq>YyhI?|GTdrhz=Lu`Of5vdjfvmN z*oOaBLQiQ6MX$>5paAYUfq;l|}4!#(1h^ufnMO0~a z{b-SpVZ935m0V|gr~$;H46@$8K0$lEkaAgoBmo4w%gfUZNVy{2(5LkrtXp2{c^lT3 z+x860a?5Z%-P{xyAuGxJEzoQMG(7qtfabpmV3bwoe+NnH%Po6!MH=XVa7gI80xT4| zyh&Ru+9lyaJNZF*xso5m`Vv2vn8X+EOYR66-D0>`V7F282Q=}E?sR8VKKQ-}9Kc@^ zlMq6iQ7PM8m!+*2Aw-?5Wb>d;se>jbTPmAdR*vU;4Xo8UOY} z%(!XGP87p9r=qwuxgdEb34oA=>qKnQW&YY3bd}1p>PzqXHR_E!-=SfV;EHOXdV>r7 zo~FYo?}hoNw`)GmdT*XE09sy-mS^^;>3q`Pp!0l<%{X*uISr&9@2A9es!J&-G zH)4uiG6F3ACE#Iy&dyK+Nr5=yxJSmIliu`G7RrbO7Qukz8mHzICf86agIr_ZFK?l# za402_NqmotD-e80Ir)Y3A$kwqpHXKIz(LNrltZ6!zk_ly_1;m`JM`q7$-Q^hFXA0d zd6e6LiPLcd&DjE-5EN+8wuvgJGTv*Z#7m$zPpn{+93cR;Oi;9yisbBzq_5;s!FMSX zMK7QQJuNLrY@bi?UoMBlIG5CQj@Jj{czuywR9kJX{Hq!wJNJyTz#dY{s$Vt5Ykg3> zq{&S*X-2EPnwmuCkS_#iQ10x>)z0044DR1NvkqO}bE*_~X{TLs{Lp;Sz(-zf#N8#T zfF?#QmuQ~QN_GzR)7?K|&l{!_L?S~On@P;^)Ndo5Mi!NqVUJ))W~B8;am}j3Bv&HG z6RS+DtT9FPhJEftSaY=4mo6%U)(Hd7&@9_mt3(0qrjkgQZo~D-o`k|TQ<9?zwxk~R zJQcgBccEm9U(Qs(g4uw2z$$;7sENaEsaq{g*8ekevcERR&)xqUDUq=02vzJ4=k#NB zTb=Z;Wig^OVsEtQEtP1x(VtZLK$Vk&()!plHAZ7ATk;~3xsS+B-R&98Rpec4l@f!D zligSugP9Z5>G#V}CgJ8@S%d8Sc8?#PxLq z$?AHGscfiNB*LVRqpcK58`TDx(Kfw-9>wMfD?(ASqAe6{@**@PE80ZS1{G~CFV)XR z|7PCb+sd8`tAQ3$clb1Qhnhooq=#EC=+nGw+4dzJwl6QGG*rfTtVl109>(Erp~!l; z)w{FVzX`n>cvlA^IN{(##wI+pgN3SKr$U&3kT3Vpl2kj09dbMi`xQ(vfB!^iHHpl26=5V@?HaZ4b?z!iPDh<$Qu9*7?%P}8>*}j zhtDMx*-&MRcxzku)`q&#hZ?}M5I|x>g}%%wL0&@y7B_R%jM4?idrFMvM0%|~5LhI) zd5DN2v0U#JbA`P}C_VJ2&%;|Ik!R0_x-pV?b@%_o3pTh75CcJxMpkksXw;ht1Lwz$ zCGoVD&eBae zuY-kn5n2pO5P>bl=y>WA(OH^+XcuN0EZTRp2<@I(A{vF<4`B2Kuu4|DMOVT%awoDt zp~1H;7O*-u2OG~S+?sBvZJXbavQ!DX=OrZOp(Je>MGUqW#_UhAT}~!KjTRFa)oCNu zNSHhiC4qPgRs_xCM9-L0`lvDAml!t1SFlD+<~ zylgZp5rvZgS1@#PnO8u)@<7aTM>56HLiKvvU=6x(F^vX4>CfVKoY}KY-{~0$C>MAC zB%*EB7gZLj*Xmn(W5qaJ6`@VO*trg)lFQ06dFRH7$#aFegP+=UAZ5{|CrUA>=3#nu zw$Z3g<)d9*(2GnM+k!|AgPbk539T(rJ=f~}6h#8ndiDA8k{?XIMT%QidaK{!)?#Q=@Q-eKfcIYA%(a54+zn(o9)cq6uKschWx#67V z3bkSFM7@q#_xf!nxJ0>P1V}Nlml%Qjn)l#I?h|9Wg+&+1WrQfKw%$>dw<+*0rMv2aP*lwX+r0Vr-b=KJJu`my8qvV;f z60%O?&~MHj&_O7POe%o^@KvGepW9R2d|TX$QkIvOTg~mrRzrCouPCoj=b^qm5E!x0 zgZIm;uvNk!xn!f&NK?j>+6zS^8TZm2bi_vf%Hc+-2qpuS#xij-+jGWcx=4=Tg9L75 zIuPruPB-3Yk6&idT{8TPc=kS0%`Fci@K_&qJnT+6i9Zs$eilsQZ-BkmoYR zpbv;U)NN$km?eyin^TB@+?Zc9PXNJ&Tu0-B(}3i0L->~h2}tfsj7Tn@OXkluWqz0d zNVO?qOX7Y`#9_{$qE^wz4T9V?a=Nm@Adq1+;Q=t)C>SCE>bWnD0{^_s22Yt=SJsQy z+xuU~%#U-mHfiwy$F*7$J(hz%nr!dW-Mk+c6139X4&!UP-GEsdoV_FLMhsdND{zWC z&E(7w+i;>~T;$udG6h)V%}{oLOxIREqaWi2=0nF7HfhJ~0@)eJLKDKum#xcE=51RL zhPYdJ>|D42Gb@C&=P7gv6AK~i1qzelg+Xi(FR6}@JQk-k3u_Mu!YCiy!%7vmtZHI! z^FuaxNpELA{N_7ar6jPW&tl(#X;N}qdW4-l0oax%fSb1JL?q&>WH?yi*afUty-cvN ztC!p8r`cRp>|(yE9h9C%NotTn1OLHBY&kh>!~(W^jdsPr`tqX6j*7B#m4asoLeWHk6gkuXr4u6=rS@(>p2<*+lgBxcJ6 zt|#K+E2pp2P#%j-1oTE%W5J0O8eOdtohZ7p^ar-ZtBq)F5S8Ud(K2KowUS2?P8UH` z)X7|c-nAy^G!s2gDDs~}ELVmJF3OXs>ZgrT_-N^T4dbf;=^c-Tc zKnZ^z%pw@dke03${Ad$R;VO$e*pMT6s7kFMUXlW$R=7`1sTJ;%0)kwUoC;0Ftdnmn z>c|KQ!XgO50@)1J{gpw1C;^4K7IrD?OqupjnOBe67Csk_(mg*(I@u&O5NMhPIC8o zPc27oa!M98bM%h3h}9xF49C)Z=h1z*Qz{&bQCC^}7vP4ylX}dVeS?D4Oq8>>jM%5sF$A&Go8Tirx~6+7$JB)dEG&eB1lhp@?kd zJ&L{)il!)<^$))uinKx`e-PcrD#gY(2MH6 zP}HNS)2n7EI{KU52^`=E^=chOZwqhDQPg6eE=7O+Eq`mCBHXl#6n!%kEl`BJS08>k z6b(G*BaV3RF7$J>ueR3eOxt_P7w0-cmQ-{^G#cgf{&M}4azo)q#(~(4DY_1i=ZDgS zYsr(AJv=r<;uBZ{RmTKTXK@xY30}|g7(cH{k@(MesJdd*$)y36A-P#i@JkB`eL9zf z=1d?$wIMIQ{t2nHQ6iHhN9m(zTM?b)a#9i}-!fA18#7kTa6PT| z)N+i4551*dtMpc52)U>fp&xQlDQKV6BN~}zhQofz`uL8PM%G(pNa6zd|OGHasrcs;K z+$>}4t7LqFn6lw|0I?u=lM6)KMZoQ7{j0D^*Mr%kTJp7U^Ru?dK^_jpNO;ph4tLaI zY&wQ`>cFIYI>O22 z5;4c}(foM2CkX+UDaUCmPO`FANLl1V@&{CX+?d=MrCl8hcgJ(d8CLG$?g=Pe|G1AB| z5kkCR^*BaP`Q=CnXap^q78OprGl>}_PAz7TIdLk{Td;7bU3bt=sE&#dJR_A4Y;Me23+XuT z0{MDR#>6KMq`1L>&RwtAjv&E;3J@i-FvwtRP9@mS7WAu&Ae?bJBrt$ck%awDR5ML; zIGwn-Q@h0^72+leOabu{ilF1}aLVZPyLpk{-HH0%(__ZUnTB3xh7YF6&2F&V64bh2 zK&V-?24GL{K!NK)SHvD@M*y?Cj^OBmV!nT^G`eIkDAQtV8P^CBmkl}iXCMc>KYJ0I z`W@jM@&XC#8%8-ZI8+YK*p0#;W^wJ=nMRAf8~*nFJB7ARy2aJ|x9wKfj-LoY!{we) z#~-OXA;YN!SLTDm?_kQRNZM41GxOUN@F`m)H`fcNGcgDq($tr>$md-CzwEthuwBxfMQY9f&=!)q|ar2?;mOtb}N_KOTRN_ii z`#J|AQcA~tQ5tt+NV-vigB6H7A~;}(X-;C@jsm_Ng&5-QHXw)r0j6V$>)B;FO;;gK+9Plt2sIbIm1M**! zW#hTJ#8>U>DuqsR^Oec2182?Hs0RYuA_EyHcU4Bda)}26;w5xb5EW{&L|r03OpWF$ zB~2{&z|J+ZzUoXW9{awv%JOHhq`xd9Hb|TdZlG?@9LxyHljtWxCWO1coXs7~L_=6h zNxnG3fA3oT#O~^`ElVT&liKw6((`61YPlrhX+t8Yq3!yWINZ1vjfMD#Ai3r=Gdt8<_@1U1s!Tut)QA6<)u)KTV%Kx zYAzN!h0)l6 zAnW_QFd*~-v7CN{Jv7#j)*hPespsAu`a*}GCheffSye+LEItabrb^t_?b_&EGpbPA za1`JJi7_@s)!Hr=v_I7cqN3+ zH-uFq&M^HgWF9Mu@~m|eA%aN$vSlE+_FlC3 zkeeBOMKYj*!b2GaQSez{#a*-_;w4@!r|6kM+N|HA9kU<+ zHl38AU3ELO{`%fPvuLZVy*E%ekVyuK|5VUJcI0P&J#{N<5qjXOks9l%w-Dg(yTr)K zhiHdUHM!rXfy~Aw)4{WE zleI%4GFxdG1A9taZb&a>NksY)pL2)0m*OyD3$;imlmuf-{_6d1W42B`uu2R_Z14b4hulEpI+sg=+*1in}zEPb6agR>MM281n{z*`6�E@^ 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

nkyoJ7^W9c3~jN;vc3sOtk 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ψ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

7%jb0-+Ae% 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

B@n*FM}mz*gwh z`EvIiu9=>dDMNw5xp|!_Q^SKoEbJty3tPGlO3~p-9|Xnd@T4CEhZ+t~`a*Ds;_#$D z1cx>bFZ;xlqQSK+Jpi|I1W(Ed3e%UxlX`>Fba;YiP@E1=+7*-IL^FyX{p_>lSq)N9~w2JjgQCj(K zpjF_8kKhSDK>>R?3EhGcc6id>pokrw&`pZc@Ylq?#NU*(;Ujp`UZppD1W)i0+~_HI zf{)-vf58)c1h@VYyu?QWs`EXjrTNzJnp8~}Gpk4+saC^Nv!Mh}!3|Hr6FdbsJOxki z6x{F>Ji$|N!&C4oo;q!l>hHqNi?~T&8*Z}A65N6w_w)&Ff*Wpb^Hs_*+}!S~zzsLI z{R+5fxIM$xot%JPUB5a1ZqBmwTkeybeM`ULHje5&FrJSU_ucXXH)h-f)ZX6+PxYvb zNvXmSZ@%j*Rbenk$8=kSIqIedBh0!$dA*sI*GU4*Nn$X@oPpb3_DCJCxIFIg2lYUUWZ_@ zj$y||u!xJ^@t~Q4MVyDdZGy$Nac~MhX!dRk=Oyti=AWKY3MZzt_mS`lnU-kpC^;gR?<{k1n1dDYHITZwpxC}WJ1dCLV%MK_b zSZo`oz3_QvO&@g>q%$H4qmI5{5rt7lL9mFzsG}fQL}AoX5GL>^nQQ+hnM>Xta zoQ9(ybr4Z#I0}MA6dI0#U=f9eqaavBq2VY97Ex$83W7xxI2?=5G((~0C`e006wKG2 zTaXcjnxo)aCMbn)wZ}C~gc&;u7E#cldOAX|hysV8@Tq3+5?$?gPh^9b#JbrSji#`b z?zUmXr?5dNSLq{J9Bx`e@JJem8*YL}+#GKB2_Es|Rte{=!SCdJ{tg|V)5$Fk4A%QU zJ*CE+nm3adJyY-hoI$n{$S)Y=bOQM$gPchqpEStX1ajISe*z>JjQKk_-K;Yc;DV8q z{lrxN%+LR)wXA;~wd%0QV?U?Rv46|o&X!*!B1Wgq?7}gs+Lr4!7gnz#c8z;U<3HQ8 zi$=L$6yZ4FnHE=uxGI!$f|CFbOz(CyV>g()+1V3LYs~UrYh-k6yge~FHQSkm}Joh#OwqPnGiX{6?FM$u&c2lj+gQ5nwt#~Z4RER_CWYCltI~9 zI=)Y=OG^+P*XGY%(eZnpAj>Ix=dzjz6MPApV>D}&r88#?9N?EF6DSZuVbBPTFHZCa zzohDy_Gm#W>&HN^=$9UTb_w zsC>KIb1D6xd zl!XF}#hFu<)N^%e+C?+RV2GCT1z}n4xWhaFQT@Rz>kr>%p`teV2&&X({w@lO_8%*Y zaZ~twQ6FRbkdsF|jh2g+(iZLHL{=OiT`<4*Q}L4>`e+v*Ypc z@$+?@Y&_pqO}Jnfoln$n#%Yjy&9U}3`saV`H-2FFhK!8zmY?VKm1E@E$`04BQtxn= zl_i-RmqKJb<_=Ak>$$t=S;j>Vo^>oU@i_kB!4ws9h&)HM&U9$C^DFZCMnkwlc!VVy zbD&xG)xS??riC1-~h&C6c(>poL>imyrp@10Ub zPs6Le51qgB-!qt+eOVbgFBXXnRX7X`U47Z>eua94-C$OOCUo-D%QbZDz0h5S7t{p+ z*Jvmy2ye8t$zqX2ma;9l1tB8H`to17{c}mlmwnRurSQ5R&;TbEawASj`=jIdq1vT- z-7m`=Xs1y@6OCYul?1_8f0-*Jo2e!<3otFvkt`DNtbnbAKKH%u4>Yu36S*`u6Sd?d zwa}nq!OLFv(Quc&?z6^w+3UV7)&=RfWUu=^zr>o^>2*IUKBUcbw>#1e0@al=Yr?*k)jhXqDY^r*Zopovl0@!uA-Ymk(casf43sR`m)#kXh>=MLeD56 zdCALwe)a&HRV(Ux0-zzszu}mJ83?}qOp3bElk)U=+3Wr@;C276^QIgzFFeq=Kdgjr z?yoG&N+gPZ^iNo5e`IC7d4I3DlCM9E<%dtFA@e}*3G*QwJdSjSHFFvYE9t}L;<_$> z^YSP)Y>&?3RdK!f&*a^og?8KM$nZYc=+A4XrO~gwFRca-><{;Nx%O*0_AwGl9hKc# zXT`bx;1VYxIr`g&bw2x>9G2`+#l}+J>RJn+x+Ny^i0 zr^)V=eyoDIywjak;UG9`%jDE(sb)bQXNq%H%UrBw&T5&9wdkyC7;^E~HmhU)lX$HJ zO+xSLP4(;Qg_dE<@zDi}pW#AY?R`C(f!|Cj_&jeywC=$n}p$A zD%Yb6{dq^IH!aw|`AMd>v>fMSN|+=oGp>5lhm>?LDb*g&xHmWVkV!u4Ts7@DE+yyl zMLclTS9>!M(%f#&(sQSOODAamvyR9@U0NC-j|B+r<#h|V$uM7_1a&!WEt@cxFW^jW zh8_{dL|Xf-Eqim^dsUkPZSz?Qob65^2n443qw`fDmwjR+e8)}T#KWiOSbjJi;=8({3 zV2OAyBj}-(>{|_W{*sM2+PsXY%Wv#*eRD~kwTICx4ThK@y+Ge2m+J9>*_lu9i@Z`c{EHwmfbi5T5m)7vKKIQ@*}c$A+)PKJWg91d!2N{!-Q zP^&?e-rAelN4;Jq{%D6uF|!X=5%Ui5*&BKj-8W^0D0&iy#$rx*b*MY95p0yS1yZy< zBK37b3XN;BO32{*9xFw6`C zfSl3|OGo2xnW*=?tB^_Kf1q@q3B$%xZ#bv_X7fF{o}5uPElLuGaypvVS91Dr7Sgf} zO0IX&tNr(^7D`r3i*%c)&`K&^0CLX6^wFR-r_~P?$fEl3(Nx#M8Ua!Ww{mS*nxY() ze8M27z2xH2l+LM86H<;3+ruC)lNwDW@6(bcwWm1m#w#~Y6Rb!(OA=P_bWQ{}%#t5D zXoefZu`?gF=7H93@6H%o+2A>YJp%9H>bjtP)V{-IKdP@N(ua&;QWhN{k&7Y9Y0z7) zA?CY7Qa7;S&?=o{St|ufxSgl6A^Jti!x`a%6kW$+&Fe!dEN+`y3rJ1z={N@1E@{&>$eF!t(q!j2eF?!0y%pMFXPPs`NJ zOGNC^%LH2*ykxV4YZ<-7v6Zco>1^C?ud_bM)ErIF>T{Gd+%GaHMNI+aY*hgz#L*iI zEki(iV;Gmw%k_tvy(Li%9IR${9FBEBa&sho9BI_>yvA=JxiCj%79^7sX}jXuolx(% zj>4urYZdmcP}7kb5yae7Z%JS(4cUMl@!&iOIBki*2%w2c*_6J(w7Wyd#% z*oo{OM27;Mp`y7-$Fee7RuQ1VWa=&C`;?2p7?;BKr6Tv{?!|xzRon`mNU1d6ADp{# zf%E(nih`m+qv#}92a+A2W|d{P4i`g@*tJCW3!xasWB0D80QWcDiHK^rf*LSY>9pob zO@zGS4xFrWZRrXf^w8rzG8TtAAJ^)+CIXB-ohM{mD`4F^KAmT8}xH30Jgzuh>k-zA#W^ z8cv5X7ckj3mH>@*%scxEUIFa1nIblq%#M_)5;9n{UDK*Gw6;szCTIa3%NO)xSc4s+ zQ((UvmiZO=zWd12%=h2d+n+a&KH~4>3?iw)Y*+Lspm|?+-wN;RNaX}JcQ;U5Jg!pZ z^b=ethodG@FXdIbzMwGHG|=+mUEw=r4u2|1d*}t)GwV;G*zu#v9Kgxjkt*R(zbjai zw_0ag93pT>Rvy1tLkJ~PGvks(OKR|{p}m-F2Aa{5$kls+29_y!)&bO0@-0}N;7<7o zbNC?LWkn^0$a%dN6ZnpcdnynGRnhjnNBQzE&z!iWg4GFhKdl2B+6jL@r$n*jOH)(bJEFf>13&4>A zz%<=yD6Y^be#%Dr-wPwM6uqNvXX-9GI)ib4bN}j9WLwL|e{^KH#)3nW1&781!^NV* zRy{5{z=n;L-{1P%sg-PH?eG89W6hPU^TY?qYW#x3|K1Q2ewwA_Td`sh;*s3maDT0S zQ%!NaNQ9cR*XFfA&^W`9Db7}uYuRkX>tmT=Li%|V0IJ!RIOJ#me-E0WOwD`P`QW1bIr5X8_UP; zyN|!MqxVX~;pd^os#u#TDDNon$npDnP1Y#Jczb~vlugsQ8>Ckxa?k}nsvd!=)_$@C zsNpAv+-UG2l^O1sBYczKpTpG7Sq$bp&U&mPE zX*1ogkB_fBK$kwyW!)AI0i_WTUHkA~ex?ChKOH*k5L!(Q9z-|yR#E3!Xp^)<;;$Z# zZ4kCg|AaWKiU9;*k8pCk8^!WzByFgWY+&M*AxFaGvT zZ{A19;NQEl_M0F7tJ<4aAGr@o&mQHcL0L6cS~`%sV_l>!rk^IQZxBejid&dR@9j1B z-A6$WH+3#d@%fBd`oU&V)=?dYU+hj_}Nx- z=z;qEQVd}g^5l3_2(nV!W~^m5W_C+NPgwwL`ui{XWVsLFzytja^=-Ws#iZpk{A#)J ztbQ@~_9K;DAz)3- zAJod)wYAS5sANW6k`+XlD*1u{>31fCN`rYX4Fumb`?@UM?HgpiG!Art*@;efE~ zM@s_j$vo`Z+7kz`yqh$DzoHvCA(Hn<6S|#ku$;z5aGV;Tb-*+MC{>fym|Fkz@@j8X z*p4wbH?x#eO~CBE4ZYNON~TT86HN^xdjd1@QDJ^On1r~Ps#i6yruc(DD49uNo+rapJaz*D zI*De|FL8q2;E;wmw(BqoR#2TbB5&5IHQaf0$<5+!lMe7>q2dz4qE`ueJ8thg$6UMNm}17DwBCera!<0AK#C8iuMMP7e2y{rOpa+ zK$H#u+OxqjQey`<63+;|v{aK13Zw{14RNHl4c{9X4&_rJ7C{;vCS z&c5(>-51?h(<=G9?#r5e;qSUH$5@rPs+H4B1{<2&&Y|9&DCX=G#=7n(eSCNHWqfz^ zWqfz^Wqfz^Wqfz^rO_P&dg4wLj^lw=`goxAWjxUOG9GAs84t9+G=MhHx_6=p91oh( z$AhLX<3ZDx@u2BT12hAmbEodKhcp@L27M}hJOKJK9sqr50AS6u?}T}cZ$|0ko6(m> zGgetHwaoa+l-{V!ilE79HH(NZh;4L?@6&&C0vsxzzhwo&;LG>+AMr`+{G({SM9Ibj zjKyGD-aF8Shdbi)3FJg)398gqAY(}^AFWc1jEA#*Z`GMd(Uu=!Te^C&RjoN%t;F1o z{dTnGh~qE?`A8np&)=-2syy*LmZc)!t5rApOjDX=0OqG9!nYlTSGk!5uv1?E)n1e; zFSGz6N7WWUT?UvIz;mCkG3+)oKD8CRJB(eyF~%_)448s6=;==Svq7JgdGfUE1VI zMN$*cExVRg)@lhh2D41Drw(b_86RQnr*QoT+U&<)?U2qy`UoDvJCT#s6@CyyR z4ZarmD6eVON`z9q%m!)ORYQ$dQ5PYsb;HCF`$gQCrDFD8EXYxAy8xlm#w=oz^#bl` zqM?&0vQs2c-CNxr^ePesl-e#Mk|>rM-(@sOwA&z2F3*HSrPba9iAw)9Fv+_>!csX2 zdmVxs)@Tyf7lvEXoKs~_R5_*L5LHV41A&1m0iJyY<|pNLp=~NsrG49oB15?vRicZi zhxnlz;*NNZw_;b+}Zeip>uz|S!DePyCE)7X;t(w00D3>rX_1~phis0H0z zIb&DCIzh4E>HCCzXX`Fi`b5FYUBk&2PzH=l(yq0p3w%1g9C;-#V89#fFn#dc5f zYy8$@7-(@?chYLx#_g_>!;5LJNrtA^4QGPsw@qO#qNOtQYF1f~zr$X%*v(RzCa}W! zY0}OWw#8J`Z%xiD1k_+IGv|i0)&!0j)rM8Z<4H?a;xB1I+e4ePR_mm9LlyT)wCI$R zwrQPI+B{kx3s~4LX3$f3o2hPKs+z$gM_dNh;{&kX z8PAGYa+kDi14W@K6h8e$NoW76Rvuo<{IBSksZz***qe9MK9ewC^6UvmCUb zbk}y2Vk-CEeb<0-8ML4|KtU9@!Fd7ehxP!r5sld7QzPBo%T%Owxbev)27St#pSYA& zjuEl~(+_io64!?5F*;?xRx-Fy_=eb)Y!z}H`cr!+ZS=?_j z%%l6urTy1RhFRLb(I$RWhLN@DQe~JB(!peyx9yh#s^gA^?B%seLX7A`7Wa#}LY%fa z_bt0*m?Qhedy(?;+e=4D$Jk(qI6<;z24v5oLxnCXy>0&{|T~v-?(bm}3$uY?>_D$b6`cG@;7&)dUV7Bss|=MYln6lR@H=h#($fG6^Kd!r-Fw z1|(;S${u4yg>YO1nTwHJLoU%ha)O5iNK7u$*d@p%k;=x&C6`ELNiH!eGpUfCLBCMd zup`gi<1`+T;8_-!h#Fm z*9k6f+wX#lJzMIS$t_b&(PXMAnoL>V9)F|c!HDPb7>N>w$rpyI>1qlV(NMn~E5FjzE7YL59AW0xt+#fqHS>XjR>00`z zKrr%YR3I4nWCDQ}n~Mqr;uqP7Krm9#1_A+Cp4>u#;E{f38Xarv{>fG9vtV0z1%CGNye2{IVY$5s+0^P=OuubWUXanf|}8c zZ?#m~elbFHUhY>3a#Y`tF3z{Z5e3tWFi6r&DgKWYsInIMAtIzK_7zIVhOQvP3NzYT zG=DI|v+D`;0YzfY*SNJ(y$r9sFWM{8mS|WRH{H~uVP!yj#q1+c4k-JT&cKudaUeC6 z#SDt~`k2o9n06>i(-^V^wusL(2zX~uvvAn~gz{8Er;RC;8AqC(P9y=$^z)AlY#&WS zC{>C{L;N-_2-#JL0EO_Xs`_yM%}?8KbDhWy!}&u~KWrXh>Z7?C$*_KN``is?J=fUH zl_w%Z( zEEn~%q)r~jjy|sRa~Ypa_Y_F!Q0yy1YvXy*zLIavU?{YqbYf8goovShReb)rp!~Vz zOu!7tn0-X15?_k@<|wf3Ew5yRW_7kF=uTL?6&HzF#Wor;*v^3N81#h^pJB4)7BdI) z<92!AHhd&!8IeA&CGJUc6;e=viMkIMbws=#RC= z?lrnWlM#DUDv8=!qrjaIaCBfu{zLF)+(PExPxCtKuTqwRh>bu;ehg~<;%YxdMC7@Fx zJ{^~7+*aGkfCavYgJ6UgA5?G8?&8Usdqz*#{Ms&YSL1SUd^fNf_cy%N>f%PN1@eK}!PQvR;{f>$22z~6OWR?JGu z-})D@EoJwU_Km;(?GCe$E;Hz@lE0qlDEPT_eab%Xr7?L$7 z2*%JxHo01~F>jPjsGvpbmp9Kk$jwMZy^N-{UbPmBjy-zV!)Gx2II} zBd??woD+w_PXDKs`PTNUNqCmyS(47|13VD^!mqO#ulK|f2lF@D>zYzu&*uYT!nkhs ze+@i3(&E_)QYfNYX+7> zRj;Zuy2z&V;Wl++A%7{cGfPfYV1U!vuhtx@S=O9upjcm*m8W0Sm});~waehjDF&PdWiviip-V9DR)0_3}8TSDKxoE{vT{8%zdeyN90ARvx5jr;mfCT_< z$)hSkbPO779gNQ!E54EvYYiPsi8YXxQ(_JHrIc9fJ9AS*ax9F2 zBpW0BIxx)BkXQre$&^?F=5$J|0dp!P)__?}i8WxD$^vE$?|Ko0o>&8B zIVIMBSxSjDU=~wi4Vd!=3^=b70P|eH91p-q{wS3$XYR#@#Laj~MiP|)ckU8cSZ4^0B2f_-6!XzuT z#Pp(TUR#n@%T>-OeFi3QAr+XJGO9EYw(K;AZS}1x+wIGzrY51xqIyE|kyPd)N=Xls z&=8JwM-kz-JNfkeo#18Makp|L=~np__+i@x7u}eI4HtuqER^PZAozP)9YM2Hmxz|WR=JT^Yu_9`NOZ2RH8Y_n#Ixwq=aTXjH=^IB9sBVCj<)|spT0}j|~z!)|K z*dZ2!#C$qp4vKO+Wk9r4jv7AA>9ClY`SL_t-lCIHgk0?0HEcTtR)eZHb{4evyh>xA zLsw|K%gmgUc$(Xa`Pv{xcjV0@-PxcA-6eNQOfJ%Q_4;43Q>x}(M!+J738CD1Bg0~+ zRIqtiN4P(!apaoe3@K}U#@ zzgYiC0b(7*Ct}u*!SFUYm}Sma9mXD{4&${DI?PiY#yKP6WKw%w+d?fqPje2?95+1u zY>9s3;zKU`%@H)&pV~Uj$Zk;XkV2XSEe_y-yh(E(oa3oTPj4or{>^j8B^kS6E zb*)=YE4qnJ8{_(Py$zdwj2kwE0MM{?eb~A>-IEn_MDf5j@2s#@P(=+{FaZr|--cFZ z6E-Dw-bskMuD~|J_ibhlXA4z7XiIpTOePK6`A+h1g`@3znfj5vmPbD&KcoZYV|qp} zu<}ixRBBN^J~s7PeT{j+GZWG$&&)5+wEA&Ut&E>kHl>#KS5ry`K}ZCXxlN}45`>A89Anvqx#1{IzON9O@w`( zW(F;tg-jwt(ulyal7;eI8{RW*Q9?)sriCm!n0>un=A^6)j1k+Lv>%CDzi7b@PRxGl?pLr-g6Rsm<-zAhEhwqj{A7t;aLvn)P> zcluy{4iCR#_F(=rf0-cDk+0atXYjrlOk2+H&(1P9wy;i%TcOPsQ^(0pgT?EV{2PSA z%C!K7EDJHmXW-JUK$%nK_&Y*^ICw=OYmgIV;Z#^D<-64XN}W^Lxi$t!N{dNxszgU{ zsy1UTJUT7$lmo#G-dq6zED<^6g2;ix+f>NL)BFsq*pdBkDPR=|>M5^Lw;71{hbGWKl|_x=p0oCteVw%ET0@5(L0V6+(nir#B>27U23nx^TIK+8Ilz3P3?m z8iZ;FInM0X2$g$A6ETZWE$9RH#nuRw3vp|NdZFUM^{BdTN`#65C=%*~`fTg9G<1pOE@6Npn~j2%$nz6E)quTG#Z zO(WK*FiqqPEaK|n<*N@f6-PJIm5I_=Q4w_7@&Ryei-xTsEME#YKiSTE)v4-LT(~=4 zEo>P21GFS?ICVB^tTkH%+__ zpWuvX!m)f!6G(zNEJ3~Ju?%3ILR4Zal5r$x3B+la-Axb#p(Y4UGs`6inscu_bp;Z| z>u&h~E(vi>I#RI`gf0a#Vmf!wZu1A;ihTBX61ZC8ni@pz1SedEoK`q-T7B=7kK%F# z#~@GnAzr0zCOchzj8GHm`UyP+G{RtiMNDmv5xvr)>lq`lWdOW3yJn%L?n6H|m z_l~l4kK8&>=ogtEvQz?~=-DoxXd@w>0@ktJoZF0dKuqYhMf%O{G7VnTIsQ{ zDk+eiRk?yx5EByv@zez>7q|GNjfW~+>DvjPmF+4+NulD2L zyVjz#g9jmJ36*9+W(e~sIhFvn<^S-y(!xQKe`jLjl!1+_Ic1}$#KH}mk&lIUnE+*I z7J$6qybzIb3w&jFlooPU(w90rxRGji5m1V7IIP18IopjPXB7|@5lnsERopn3PLw%K z(K!9pKcxQQZl#&mEM4Bs2#G?gY);ZD7_tT<+ioi!&%%ft>*Z`T!JJ}aQ0<;#7w1xj zyFdn814WJ8-UvBMPa7d;>90l8aR6?l26dahRN(~MEO zgmc}kawe*QqG^jUn|qAeT_MIS#HnO3WHDx~U*lrT&NHsBhjZ!qGVYk?%-f53Yzt2K z+%r!{#SaAv_-z2-W-2B#{52OJ+AT8784_@Cqo{~?k0&dbhkL<{;I>$NsAeVd->47I zu@BjBk2H>5(W$6zPoO$&6gxv>gNi3BUI00|f`Ht6?jmgBPK89>DdRVaB+roI$r1+_ zArZ)SdLUUiihK$Qx!(Dr6&j}MAslCB2#gS!zXlmEq zA&gCqdA{>D; zVaF;{`xGtAB(AN8m99Sz}X@!OD=bD8h=Y)FF9eL zb!riTLhHH0^zX!ZxGT(R)wWH#`tRkzi{m_C9@b;L7=8An&_vkINeMKfFQ^_Zj#SHX z@)v_Z02323A(08s4lk_xyHtP;2g+q;8MROwa+_+C_yTH8JhWl;N~hvpX9XElqPr?{ z$pAT0yBK<_p7Fi6IFmH~{%XEi?xl6*D^*-Q&@Qd1P{BP!>WSeSd zudG|FfOeSN5e`(wA^l{m|3Q06bkueLxCyta&xmJ%P-laYMDo)EF5eYOQ2l3naZAAFi{0fc^3-xYEb zcu*yCT)kU%Z8^n~HLsn4gge;TUH#v(UBd*EY!0>+hfCY18fpPd8d8q1!%o?QAh$KP zdF(1j^J~+O|H4Ap?wLWvVwGu0;(`TcyiExkHXpPwd0BXU>^wBqj)9a4m2qaz9c)Or zfq=>IJl0EB%!wxZTf`IKAbbV>wJ=j%a0*tv1$a`6y$_uJY_Cmr^sB@OJ z!BkrTK*HXKG7^KNN_}3lEK`QMXqQ^8UCP2_7|b2E3~hi`8<{EBLfdji{(xnjf(OeS z1`-R}8#dDoEW2uDJeIq(AM`_lNs<(G10rlSc9)Lsp`&3yY`*SN@ITQvBr0@hL3Yhn ztWBJPm06w3)j9BXLuuZ9BXv=JeL*e5>U6EH%_Y&|E(HVJMT>Qq#oCt?XQjNce5f98 zB`M-ZtUVeZktMv;)mgbNwHMWos3{;;IKDgv=qCy)r(41mNXSEFxu%&aDP+QRng|7@ zv}48(rA!Ku;$V$_COfH;h@a~t+Abf``swS7CLMMOm2`INsBuA4@V8aLw${5i=nYa>Lj4wOu7+q8J1ydk?;={o zZXqDl%NVPrp=_ICyizmp(T^y*;nOiBB?zEI>`A2*P!|<(=cPl+qayCCet|*LERj>1 zC7?1z+_QQEKK@E+`2}@N!)Qavnt>`YtgtmiOM&)mTpv?;i2}7$!L(v}C6+1ELMlUK zlGrbuks#qx?|mGe)nX7~XEq4M+aPDOq258~Ji3mEmpV3kEia zUlxq`1vOTFrgv-p3}-x&a!}YgE$oOHn{x1cdqg?N55lgt?=En^(EQ-kuc-%l4;*xt zj8)XBG2d0G2WvQ!E^tY7PVpZ-m>IiwnVGyar0b?j(nVyALT?54CYE)au^h$&zkpm){axsl= z0Mqt5odoJ@QV;74)T5S0$i`$a#3X86r{31zV?KrjeYiYa|f}4_#0rxyW8X8p*|=kzBkijijt$+XVsp zbd1C3BhRXXu+7cuBZaN5mt&tmOer8^cLeXfpgwYY$>qkogTk}8s5)|kR(!EG#&%(K zBt0EmOdBbE%vgnFWi_`Bau#8?Ea^>!WR=a?@3bh%v(^-nu^>C;Fy&%78%$8A^Om4; zYZQ`n96>oYp++lxq`nErs3Fxv6t7LWB?z(CETZ}m`O9v=iof|>Q%4HN7uQA_K!uc% z*1S`WR_Y3Aar^Dq4!>w?tS(YGj=IQ5y)|8A>PxY)E;8jwx=0c6KkFj3ySijuh z8)+R?_-bn%9U!!h5g=Y_T1TIlN$IGc>vWEE^6of0S?-P_lmAmtH=<#*HCe|SqmB`e zm84_DD0eA3Mn|1gjCz}hEKcemiRF+=I=CebWA$qz4WoEmD4ka5nuf8e;1V>9sZdSB zC@QRL7?ax;K3Q17r4V@Aem#+2_tTpP5vyiF6W#P(AJ-y91>*y}Rtm;tiJ%Py<4(ti zT$#AN$%R6_>!K1ZLqQZp{{b(aG7S?nCy$_5SK8GOzAh*kj|C;;gD4q6nV}cpbng;7 z5|%<#i$W#)4!+S!64iq^M|xeBwE`0Kw7JF@ETFY#iNyxtus9w}$cmBy9}Egfi(H1Q zo@SW<(8jr#77%-q;7nuqi&wSnK@nh^V>T3QH>HBDH>UfHZ2O|sa>X=@5sp151o=v` zZ4kg;rJKAZJAZ@d=a%ej4>U!r`I8FGC*I<5+mSdnJ75@jc)JQMd2z224d2=21rh)Y#^~NZ0F5WBfbkyC-?tvB# z!rLLWyz6Ln{z9foQy@sG0Y|!^j#e?HB#T{0M_YZD!bGSDet1boE3Z}?CezV=(RNbO z(e^gdcWESGA~qgrzA*&?-4c_Op5)TAq6uVB_v?m_oQYUoVz{CvH)`-SKCeXp|sMoa?U9TJb0;^_CYc}P2-Q>!OUY8phrC(jz?|NO>r|ETJ zpTLkn1LLcr$pP8FpH?>O{1yk~N z8)a+l!enTdvZfX_MWn`P4Blwa(QTSt&`mAc7TbEDA3`K*daVM{OKJp>6Eq>!Eu`ei z5=4s-C=4x@_lRNK11tgO#?Cl)lT^3rF{{&rLlSFaddYGmY(&-V-l)2*)dl6RF9>@x zDy`MExg=Vgmg*MwZK-ZkI|`K@y`@K$w5XhYuZ1Z}NSZE>IJwo964YTy9lM0FRvZGe zvh=}jcH_iSTLf?dTa4*(q>hsw$yW=TT|pONYRK({xk=;wE8QfgLkw9|hNrWB1TRrj z%gRMeD^GcbH3=JEF@^J=80%B~HjvRK@=8TYeY{FNRi&=-I_()A<<-am2SZ+iR`>+3 z0IM3fZ!Ttdg4Ze2YP9_DKB=`((i8N#oq#K1AN0b!(+&~sJ`?;(fQxT0 zb-M*aUN4ap$#@sTC!|PrJ}!4p6vv~h-$I!B5$))4RA$s>7s)@QcZPq3XJkZ7kyBaPb(AM@*~hz|*hjGXJmJ@}N4f}0 zM4%3N%~~HGA|R8_1^SS!^w-e|^1{~AiJ{%vX(dS4Q37;(EhxcZ@$)u%SN|&#;Jz>; z0rT#AfSB^e2rKzIgA#&p3-4+-Fc0mczQ8EI{b)0c3?qw1ga0|UH1L`YVNgmRl{ zP=UB!uJZ5&C_&dE1|w8F`xL$Bl`&X^p%Akl!x#`?6n4XF?SIzin9pEmX^g#doR!^& z_gTo6nN!=^+=7HRb_nOPvM#=;Smlr%3-~GWLpXLnsf&gJS+&qS>$}B!l9T)Btw{>v zpSNJ9Iy1=GS8-a!3l;%Tj1&rbG5OcZ1Ws@|vrg&2Eq?Ve^uDY|C}v^#&RCdt@vf)E zu~#OkfN`wYtRm+@TMVCUlya;hjs-n&SQLg|lCVtSnvH%(M8O45l(6HEl)!4H@f}!j z5-LD&^Z>~mn6Ps^covDl*h0h-Pj{@BB55tlCY0Jm50fMj`Z!(HrC7D{eL!}59!h~uJS1fb^kNVZ&?23&AP*-DF!{o`jjg?;b;XjL8FCPurAHqEl z)5fK+qLN2zM*mNZ+BgA^J=G2gB6AV^4cQCreS1wZnD`oEPhfdNIMS1C56{R@q;$Ch zfE*}gU!=OMMshlLyUqF%B!H%d`qB8vJjM{WP)>g5HXD$w7hH=GG^L* zfL0GYL9%l#)`0wW)1-lshR+4g9j53=ax$G%xmQB)gj-x|yZXgERhW~S2dL!m$@{2| zNI^YmZ5!dpQ3?Q3TZV-?_VoLFCI9HnE$$r!s4M%Yc#PTn{#ITT?ap^S=cc`TZrr_V z=Z@_+Tz_4E+x*<@%=A>D|4sJnF;NuVEJy?OhQXq(zN~BWQ?0z+=`Kw4CfOtEx~%?3 zewKdnijWy!*~vWd7E&$d+-R0xSMD+Cn<%6NU`)y}4siA7%|7r8_ebqBwr&Hun^^g7Bn~eI&C({p_t@GzlcH!cK0l@jIx`U5L0XJxs;lv zx#t$_8-sOn@U9qVM3BMyH;m^BL zH&o=74RGc=S(dd}WNdd~8+K8ols8gg(voVZ52$?67_)YXmZKfyc|~h$(XgEV6L67! z)O@=R__iC`LEF$UKvpHVzKU_8nJBjZBWgkd$#cnTS@6RsuT&GPIs zItXAKpk5GQbDz!)T27_vq6d;9CaKlZLJe9Q0Bszs{a4nT_uX=;I<$UMy>%PWI7Rj+ zR9_|f4`d^Z>|$KR19yp(_gBMj^Q~gS^X=A+I@WIs`FoaYOLO?K9?$qU35P~R#yr;H z@W6N!t{R!-j?yvQ)@+Jrx+gsdcwrVFJ-I(Lo5Rm2Y=a2m~OE*rI22kycVwZOMU0rw80l`Uf9lPT9iH#BuDdR?YQ(vm zs1xWauRhganqLQ#*BOS^Cn9*8%Uav*e!bKk2JiRG7=7xT0G;)^%>8kj8E4x5|^`TdW8MikR#vzepA9%1e}vX zDdBxm*&uTVN*2l4%6i9~UX4g=6C;s9KYqMpPOmlOCqW_9xEWdpVWO)rPI|44(`8mT zUsb5rkqY^pdNRik>!!T)*7YRKj?UrlYnfo?4BFU}&7&do$Q1M;XCLePM^?^Bnxr8L2>i?HXube;2%BQt%M-DQ=G~gejB0u5 zL#Oy~kcA^r*(e#MUXEJ8rFke?VYZ|ez=W0d!K2$0_Wsh%)u1t8yoPoAfy)8Lx}xbN z-MxUJy|gu`fKd*Kvj&M?!}TVWV5jl341wl$Wj+4a>h*Fxd+lDYqi2`nu^PZY^9uC; zd|wgtYQ!@_jPUk9X!3R`GWP*0jxh|_NcK>zjDle*>2-v5tD9wsvscEo4?^CyW1`R7u%?vY9srY$f#+S934 z^u>d$Y>}GryRD_247X$!!c`_qVS6Z5Y1z5kb>ISWclo<-Uj;CVH36fLIrcgH?=tvB zXST7tWcZK#<;L&}@pbrH5To?~?4=&?UhhHZ>jirt+o2V*5jgX^8UeM{=z%l-O=Xmx zrhnM=*A8@Ys$rW+HDB4aw8sH*_5fyeZ zyTdueuBzQB5!)=mJl_@aoUuF#-?<(h)Xi4UZ&;o^WAmVUwmhG(JPPT$zMj1y z&j&4!;)kx!1I<}IzhrsF_x(ob(sM0at{v-Zy3kt0EUGO>ANn}R*R*$sPSUU(azajp_^~I04idhZwkUvJIVFvLd$08`d!O21`#X?J3^k5 zmS^YKdQc4nl>V~i8Z&@fgHp69BPb=Zl~78crL;csUPtM+O`&w#Y(I4K7pwz{mbxBY z*M~emV|lcfKbF0=kI|k-Euyy_@-_x@n=7tefw&4hWr%aiW{L zEJ~u@(gjc<#|*V^880C0QI&dv;6}wdG;_&?bUx;i3vE^wt%FB9X(cXNGk=n|+HuFR zSlwb*t-V4LR-Ur&(S8a9{UZDCWWVZvUOR_DCPz-~P1q~o%-Fsi>S-S?zs+5C2g)zA z{+HYC9(GEO%NL!)a#m@hfxt70^q1qVgedi+1EeO5ihM!8ILyj7wG`^CRleg7eS>2a z@~NcoUHvbHW@VAspxIlmUaO|%UTl@;wa4lIwqP-n#k!PH`{g0{vh3xEN~h?!iIRf`33zn zUuiNa#&+S(*uh~5@61_6xhI59aIuyo+PXPw-I_7*)aG9L+Oo&D1)Pjr(%y$Nq`%!L ziT=iTab8wlr{C9Azo+zjD*R?H3J0XP2At~?*rGW2w$FzC0AJgD6D@I219blDQmA>8 zjobqzg;wCB)TIaQ-R}9MQ$P+Q-pb*PZG{~*Fu7iR!2zy4tBX_(Dp#-6p>i}ERB08s zAXKQr8c@}c3fcl7ivHoiap!OV3FrfQ0}^q%JD6!=jUcgX1G1DUA{%aZ2AL$ljHK=W zb16QEls1M*-^!I;vf;ihPZCjzb&5)SELc_A>u+fsy*P+*iRjiML_M(+G!(icvK3w@ zXe{~E#qq|WF^9_aKfw{k7)E7)CJN|()BS5v6yO;MyPRZ4Q;jtAAXny80SDA z9klY>4ZT*44GwfS>^w45P`~ni>csKS>ck1#4(+J*>YuF_^OL=at{q8b+3p;gypwC1 z5?%Md{cqvI>}gqoEuGsMX-IcAHow4<`NH3IUv$};-=5ekqnpqCp2OxBT|?&g4>rH( zYB0YCu=(W}YK2zGUxxrxB4l(9aptwRL64L^zDN2pzDN2pzDN2pzDN2pzDN4f=n-(k zYdVJ}?nEpdKN3nG54XOIhg)C9!>upl;ntT1+&~B8>m2IdX`21O|3=2VOR4eD>C1TN z^kqDB`qF?77~ra%L!CRN&yPHK1O}y#he2P)!=Nt>7-$I*taGT%x#T$C}}+a5vEx=$6>*L|u6c-^Op%GQ0VCPDoZ%c4fBn!onZ_+-V4 zEG<~Q{;~TK0B-cg*khv;*An0WRRjIT{2GvMIaHzP22mJiYk+fkO^5m$^k`hG(dGr} z50z9*!O3ity#z7~c}ED%SWTm}nHxuPac{embC6XdACZ*y&AWPGCuq4G5$R9X{4r8OZ`S_48t?b^;OEtL+91d}E- zN^3%+v?er4YeJ*61~gm_H?qa+d&?3>nk_4>*|O4_Ei0|jGT|d6%QUe)D!zEjqk>D7 z)@X%57^XIAU~E)O@zP^B2$p{LM;)clQK7_2<4fWGs?IM&{q`nHcEvA3{2Dt8-s~l& zaJG~P7TP81k)svR<|gi5;*QAD+nd=DG4W`nE^=(NBjOO$#dk!g7Hmf(ub+sJH_PG} zc0@|Ah@ttVB8ldgYRH;jD)MN4smQbWrJ6F$FV)nxFUX3v$74rS-{aLwDSdp8^ksaH zMwwExw(&hunejc+mqw3(+jes7h{PhsjfB$2!>upl;ntV&BcU(j;ntT1+(2jhHFiW| zBjcb``grK{Wju8HG9Eg8X+Q@Iwku;tBqlQs2BnXOL0`thpf3#=Xvy|o?1;pW#nE)Tb+V{)w9PdvB{2Upq3rvwRI=9kXO|n@5LrN5=$*Rd>XF`Av-esUv z1O>aZ@O7Lj(t@R{j6i$ks=`Xf32zXEY`oqxsIAp4G_JPH9jwKYW#@DKW^1b$QB$rS zRdk%>6v79}xgVYfvRLP1B;S@0Gdy|FP@UY2CZwk)jDtl^Xa_$dKn`)Uy<{_j!i61- z44-l^vY0zUsn+myNVTw4VXb$cB59~=E=4vsS~EB#+4UlJXq)M$u2eC_qBoKbbXTc# z$prkX=Z&QH5-tz522%YCnVjaXypdwhGe$4h=shOi9?b&j)8&S*A@`vp%@1t1WRYFF zBA2DNOav88P!#i!0L6)BHgs(tk^0{vpPvdU-^om7*pe`cJw{C?8mQWo&Gr_m@xtWO z`N39Zx@7Sg6SJ7N_EfkZ*_udqtAYeVdyBxBm^WG|hBwqb%)yJ4r`d#fnqiq*%tMr? zrw6k^|EG?CUAD2g7?Z9#5J>A}QLUBM7s~rHMpU$-c8{%k!t5r8J;jyGqC-qP$+Qt#F{r2&Ud6KGk}CAobebMti*w))0Tj zUbEg*y$-9=9qP61!F?RVc)oa`wQT0;ZEZPqCKun;_6Ba9GJk?i-^UN&fr=Nj{vTP4 ztmmhqk+>(X1_)w6^cFGxa;dGDafp8QYTx>QWM(uokdQC8e5W}m8lrbnq@Is+8D`8t zxJe}u#3FRP34sV+n}>LMZ%6|C_dVufB5iuH9_c|fPeR68Ol zwR5R8wI8?I8Hvk+bbaksBkj>fY7eoS_9m=79jfk{zq5wn!Z_VbZ`QY`L*uHLRucql zOMswf5ZopJ#M`eO068a_fCwlOL~QVYXi^aQ-GVLur1^tT%p$Wyu$GKp5}^5cS~n;2 zlasFwI&KF{aZjXr>kg+WQ`&);mM+cEF~E>7U6_#(rz@n@jNzEqy*}fs-UcVLNrdj5 z*?J=9;zDAr^jb=+HFGv4*5J`dd7U-D&!@y%4^O~KjUMXVhIm6_t@uhxtTl8jCDuS% zPKh<(mr`P_@61h&!Lcv~9JQleCT1NNeul&vFi)n$8Zf6*Vhxy6DX|93YD%mD!&DY9 zYb_sw6}X4Zf;uo_DV|sZW;rF+fLTh3HDDG~Vhxz{1`If_69DsEz#I?2JZS|P);cia zl{PEu@jxtLZ1<7`Z;LBTW^6t_7Pr>yn^)x2D_gj)NLT0*Vy6P8eG`M4$2nq9GkTAR`r z(Pm%=tdZ`PApyxQv_i_VV|Q^wZ4NChGdr5!6H>}p$05lQ^10Dwma0r#*VUTQlZfQt z*`kc*)Sj30a34Nk67pj3r|1#?c;0G7m#-7Ok(FMu*(r2|a!bl&G3AZ(H#`tXac{Bv zwoV>oEXT{TMh?EOZ=B`xZ&VuFQ9kk-7Rc5Q3NWa ziIrDohOCck4zR}2wnK1yQOr2lZO@OCw)}vtNIqUr+)-gzeI9)-3({jN!BP;r{@c2BIQ|c^^zlY?)`3toQmV zt1$`*gy~jr#-lGSK!rH^4@+IKNBX4n5yf;QwMcpeS&e`#(#Xu;x?MbCEj~TE)pR@= zG3gPh=-^Wp{z-cg!>xDNl;8189dM@oi#Cg4-!c%G=efN%M|;rf|DK1DQV22ovP5iT zq++{BFYL&4eh^?)$m*#!oz_IysCW~$FR+S^bz&2L9GW;rs2eqY_Q&FIhAo;Jn4kfQ z=!MY;;Z1@KGi<`X^E)A3ly#!}UvMWnu@f-Yts4nr)W!+?xT+BoJM2VE*JP}Lf}`&? zcdk`?MQCqxbLFd>nJcY0LamVzvd#@!*3g+0fdS*kNCXBJudKYqHm%P6W@dhAzQ(U3 z=TS9eouA2^`Akku_T*(tD?T5MD+H!uJ9ZABIln$DUebn*lA8%3j>5p>29TG)#NwLN z>ie@5Cmq-muwq>ZjL z;MJ5_a~+$guB8j;GxgJV>O`$`6)iwEO>F^6!9xBCvL1TPa%6Ykjx0z2R0y8_vHV&8 zZ1gq|6)P_L+0AfS83K&Rc|7&;l z{`P(C`zP;9o5e-c!Y$ub5`~+4Kc5e9Ky^lu$rTs>Kz%*+m6M=#ZXcBJ!$}l^H*2vh zIxM#=Zyjhtf)XZ(mtuY;K(m%UOog1JQ8?(qByTpEiL8ui(Y{XGVmo2`5=BBT;w`r` zI0VfUlf*Sv@aV~cd&>A`ag7z2S+R|a={F2!X&;`lkUyVwlP;j8>-PU#77-;Lz%7-> zZBhy9629%PBQ|_7`GTxfaQx_C-uK5W5AGYGG2JAFsnxcTJlMKUhVaM4Ri+z5_U^ag z3&SdaslIGaQRu?&c(tl4Nheeb-r&m5j+Vv?7#gulzUI3LtW=aNrqWQ67 z1AL8%I=}PkTid4?biFR36?&4lvN)K(NJ%A?9RvfWkM^Hs(f=j2Zg{2dkG6)wE*f~- zRW9U@wZNvzqWALQIGDeJ1kmwPQWpe;^zgsweIP>Nz-(tiikB9}(b7kAFdB7J26vdQ@&?&>I29$|t`42@QP-jQx+RZVs?7sHKJcwf%pukWWI_ zLjD?qmM=kW^K(3AoSaCa99c19BXX8lI{Cr9GM~+mp@Q8fh>LSV= zhTkqEyFyr;&xTHTJi2Fec98GsD~P| zCXI>iHl#5h<48_{##CaI#vX;RB9TFFMq_~RS_{zM275-`P*ML#9C1hK5UcbTe?C`G zaNRDEGZYjO_H|dc73=?{sVa?d%m_n)1okVXi~KDA6jPr3b(H%N$I7-ytdfR%eemVW1r@ z-&dutwJp**4kNK>ue2+a@IZ;&L=FMOXnhJMbTEGcpbmld#kGlB^CMc1NIWmf`f1gA zFn?U{XeA+riSq160T`msUp(w7PzQZyj6d`aau&V4M31_T`Lvi(|M!6k&cPYa>EOBC z<{)qR^{<^2<11}=`tR0gH`2Z(M3z7P9x=$7k$j_RmJa|#xSJpBP@tmpK>i|+Dsdwg z+j>E3QOFSC6g*Wb?;Fi}YX7I-3iQ&ho^B21VXjQ-`5HCYj<4K2HL&PJYLHH8E2shH z2-M>#;`Hy2QpDo)1t3R>8p8ds+%RVQ||P+-I(etCr*z{^_3eM z1N+3kvkV(e^-dhvUYP2g#=vegY(MdC&Ewr0v)tiCT8K2OcH=t+0(?3SyYbuD3F*>| zao{VW_S(gTTc%131?yNrtIi76QL(zm#Z{g1 z6JLHDob((gh-Qz8pd>_dJCZtjiX-o0vEV|JKA@#9*eo5>btnBG;bdtrSDRYN9yNLwsRj`my%K-YN94~?t(cC9V}r>Zw?U%7MA7hnu_DV2WQ%=$6hrYvj%3Nb)!1ESlCoZPoPq9r~0eoX+Vyff{UnOy;RNp_oCcV8Xy}c;B^%gQNHY|8>b&MX9>^FMs4L~$k3ioc#W(V6z z;36fZ?BMnJ_O_F^efG9Xxn9U+!#wtLB{7ei23*%Um^E=-Lh})^m&qUy26_20XE`SO zic`^b=Fve7f~4iANYK?vHphdwe9E&K$1(wL74{p&Wk$CqE{ocUjn=9Q%tvf*Px4}j z!YHS@SxL4g_@@z^b?X!2!|U%Z3t_Xvri>eGCdyZG^A^3LbG_PXfTUo8hIx_bn@IAE zNky}Ibq31KrEzuK8}rjwD|s+KY^ugKe39;E{DHR1ExqzP4 z?;8&0r}YGj!dUr$*JhZs_fUcO@wpZh<5JRIt%-Xh>zoa&bMGkYR4f1+O?HvOu}vx) zx&B$7Qf9QJaqTDQunCs(K~5+czoxJQmgs21y8PJ5(eCdK-T(WK@F574a~pO4dmG(9 z=CxV(?cFO_>v;F;BM=2fU0*%yMpVRAq+3IU{FSaNc4z^-zSyZpzu0BVVL&%&&K%5->N$<)uAVpCiZ~_~;Mnc|l|)QUr4Gyfw!vHt ztBidlw2Nc)=>}HUc74ZTHT5yLL&FkZ0~X$;-4UDZ+LSBXE}YiH8#2N>N9C8=R>ctH zTa_`w>0d9g>2|_6H(iro&Q$3q>heq2oSqBVj@y;>GR&n3r)YbG zoA+FO+!of-%HxK>C zl)iRFbhFakV%)F{3pXFU`ndViBcF_PV~bTrv)cau<=a#GxiPqL;c%1FY9%fWTQ#k& zcl3PZ>Z9k0U#v)^t{r*nWFY};boz;a#$ZjOG`ma5z9OI6USXT zkfkel;=SzNeLY#O6aK2U{XsaZ5AG%D3QjcDg6r4WDCL=2a8tU1al`iK4={bp`LHjR z+jiX7@}jY>6m*xQiVU@W(gZ)mZI~hi_xxp-A8hKtZh)e|i0-0$!D4Tm&uh_zK z-HsFsn=oIP0_Y#fd;tovHfVDlcVdTD&wXoVFvkY1qXUlF29s)>0`49E9s^6wjOB}p zDIcz6Y^s4+bJc12q|_l%SFX6-uBiGUF!m4YsG(TCX395yF0sLp zneup*o)qXRT?F+zcFeJgwZ~MhrbAz8YD~|5^vV=#0-`xtyj#Ow`M@8aWK4pQBdLA3 z$ynj(k|wD$s!0k8A6aIlSuoX*Y_O(yQ`H;kk)qORy&g$*g_?R4PZ}p@$Bck$kr)Q{ z@)#OrN_|jc`Ej?49MkTOt;tcIF|TimSp*g_s3dKZZ;a2o_2`!DX#%x#whn_VI;lzR zaUgA|WxZm;)0d;d;%HP@0K^4R{1<=posMG7zB-B>z4!81b?m;;k^8zDZeK$ZsAWRg zZ87Ln22&M|7jp70z1X z*9YV4>qhN(P1@J`{&zpCg<^YCsjT(FS<%qw+9v%P_Id42RZcW6GSvr7k12+28IEWs2R~;fy5Sqb>|6&cY>s-`SxU>dG)=J@g(+x^nvZQ&&hT9qzW-w+~ zR@_CDw;IbOmczs4#P?@5ve@l|{sg?p9RlrOwAR`hQw?&`r$n8C(01+C6tvs{o&62g zl$%QH((dofHRZ^$#+owIkgTt0O(AgRWHBYH0atUsjC&X)65Mxa@yPrCFuQj!=NffJ zfBk$c=5B4jo|yxqhCgUVQAJIy?(LPK@1>QK`rD=Vxlh(5UF_1Z%jIo8UCC)rY0mb;CG`_lQ3k zM|B09@M?J#lA!3_1(FSmZ@kV_bD7Y5OLoFmJ|p9Y@TgIV6?aH6)q9+b=%QH}rhy@RI^akc+K`6idnN=3BKEK8FN0*n&;*&Ki z>Y5zVs99{C1#k9Z>kl-5@$rI-(1FAKzjukt*4J?mo_!FsMM+d_AvD`9E(SnY_~bk~ zoa}!yYy!Xw*2()1_y55gHj^S(QY>h~hHTDn9ygJ0YE)_%2jZuGP9V+%so~N=?Ax>j zvm32uEB{svL`T1?(7>AYAo?_2g$Dj??d0X6h|NS;bhWnj->q@%f4icZ{-7?)a4D5(GB0AEq;-#?`NFSQ^0J(krpvweb?;w_P_IoOonGU+l7qj$=DGkr$Y z=aYOdPvHa#m&UkFH{@{3s>NwLE*8LKXUFi8o2Yky=AJ(uh&=N&Bd1pFhV`3hmHN*)IpBwM6dBGjJU#q08mZ$#U&GYvT=Zkq?AGa0Tv|_SgQt7GIy~B`zFWs9| z58IKl1Z4B97S(p=q2i>m-aS_o%zS$XwX_r5sy*CJf zf3jDja7Nq}`||B?XMDqrIezC@H*UEK%hL8sC0~xJ$cvWw8xB&sLumzY3g_Y~AOT!J zP6Wo5A=0j6Y#e@rvE^cHH9+|#r=Pt4hdzre(vyXK8fJHijc4>mXg*>bPw}7zI)p93 zq*E{l0WhA{Cfi{kY^M{*EEB>4SW~-c8>_;=8ta;%n$j;(ple7-f{qt7(1Qv;*LH`51vyGHw9wB}?9VZlKs)Zg}9MJ9yka)K)66nyo^_w;NnX*PZRcT3T&G6b<@7;151}8-cjvdK zZLax%iwl?kCuc_?9)isyuyBXwVZ6+sz5#dS403UbHvjp*0(cM0)-X}-zNg&%zq1CL zR6!U-={vbl5u(Mrks*R1Kr!vxt%y+(Qjm#AZzvbv^yVXP)Xhn`D2$wpmtV8>Lv!s= zWPg^aZc#z5siB)YVF5Gc5xIX4Cd>K3R0JykH&K4}=;~r7088$eZ)dHX%X_?Z!5vEQ z55QN&AHV+<#PC&Iiz0Yo~m+3ASks=sctLFGF^|- zE4Oj&lRQ6PJ~vxTJHpEQ|AqZf`YN|l=CeRJt*}Lw^#BGOfmO>r%@5`NDX4?cwmAnE zv@`!9U2|Pbgx>rMe&vjujvo4#*iXJF_UClDMjb0~dJD^1tG^fOUjdqybLd|ATnA@X z^Qc$ecX#46 zP}CgW+w#Yzhg4Spf~tM$xSer$Rnay9ZbdF!YMCCtkw-WJ@d{qqBfpec>#lv$z6@J? zNv1}S>jxlOHGejtb2(nbHS-(Ywjy$-qjps^c(TzJ3`I&Urp-crJKTZ9v=+6+Ygs?U ziYH+IT8dEPnD}4|?Lz({KZ>N)tP@rQw+^+NvA zs+w-9rdzLOQm5t&pia?Em5`;X$)!ya}p-r)va#N)zy97ut-8y zS|k|(@GEAmVH9JNTw$?q-smjImpjdL^JPuWzPh1H-}J>fLrnv0LPhX449>o|>6cG1 zp@YM(&e<^=eI9jX*eV}+cr|K)gTqwUc#7G8x+N@0zP&0KTzX%~>l&#|uU=(2s>;Ok zy2dJ&@v*yyWRhOX10e>HC9sEh8m6nDbV+SI!W~$`B|sRq`jjVQSLhE;ziF}S-jdzs z8;7nPWG%mFj^pALT^-EqmY=I76iWC+m7s$R|NX7)-L%tX6v6?{F8qMgxI8*Ir+3T6 z2mbUa293@OsN3{mRtFMLtYTds=JPqXJ8Bb= ze}A?QVZChWJ`4cXWq4V}2lk*{{_y{>TbKUNlhSV9qG4Gs--fDSp&EHWX@#~(-UKX7 z+tqz8?0&Y_o*>#~x?WO(T<+f(pjnZkQ6v%%jq1EIJ%kh_HO}hK_R8>?hCzH;8?h{B zvmu5o)|9_!IB6#vro@scseM-6{5feS8RFs5h!DGyNMj(eRLm<%rgm~cGiXvr`@{sP zZ>l=DK-<8rUu!m%*TQjp z<($%bI%NubpeE}9$mw4p68UmFwU;Cf(L_|&!-A{fde{sqHgs@&A09+L%19}qQN@lHEeV3PBqvx)qB%=) zf+dL)>(E3TU*a}LDkWNM(;B|%U~j30FCK)Lj>9)%=Qx^+OHUzBQ_L&>5-eZK5 zDX4JcFn>m2fk-wnD`JyateUCC~IuU$|G~R&XV1A4=-k0>g?C&gNc;K`vR-WtC zS-GXUkSk!0cMkg=HY*>ed%ynvPd234tXw7inTNriFRQ`*pNmN-YHq&fSH%GQ?qxV;P6)r9NuM*x>(5N*3}+F`NsxuO$UN4}Vp4O`B=c0$jh| z4UfFt16xr!!XZQ5W`<+Zm>DjU6f>A^-%i4T5pV_40gpfV{2`SafNPmUI3ozxvIru3z(?E?ky|fif|&Hf zrqN_MtLwRG3a|v`ionBL2gglhafa$ghI0q=2L-7Xab+}^0Fna2p>1mvgzs!yyBSbc zo}vewah`{+kgDQrRVsV*ZKS$WDH|Qniw09#*4iX)Td7mbE1@H_^t3YxOrop?1Pl`2 zySaVVCPPk3o;mD1s9X#yq`4$#X-1J$s^;7T7HJU)vprY%&U z>&t<|!yCev1EXJVJB$~LmodeHHkbS({tOdr2~CpFXdI16G2BsXPoRp`Qt$TShLI$I zxS_ayBneQjuVG0A4NDa+m1MZQZloZ?eqAvalLVERwV157zl|9R0fOQME&E2O$2z`C z1Rb7LpZ5m|gx6!3>1T?0uCpuV%LCZNiAUw)f?xA@-i)9c9pewG60; zDXB3|N@|Rgk{aWrBpauSh>v^HR52GZXF~^|j|QO6v(Y@>V#N5p0Q11^0D6zf{jGog zD2uL=k8z+}&z07IffBI{b{ZKCb{TxLew}0mXBzcwDghN(}gI82N*{YW&G1CpdfdB(H0c}C=nYlh4FLVt=lI4 zhw#fYB)j*&2*D!No3P@<~CTj1_CNYDiR?&Btpw z46Qf}_!$Ql&%^*!Sd2)hMjUWbjkCx71=81#BaPS9MqR}lRM80M3rP%Gkj4sAJ~y+Q zkkpFd$c;V_r6LvCAj_UhA>7Zp<&0U~I4`i!6&)DHIBBCr!Q96D!VdW+!4O1i3$Y9C8;Ak815(cDQQ*bg^ zk^~sM3?4@?;MZC01j0@X;m0CDWaY0Q6`8j|hL+Q~UUWC`ji7JZY$K>e*CU~rU=$;v zXkciKx!88E1A`b{IgRR5fR&z@k~RkSE0FO8mhVU&mWT>lwmqPNYYwIkWrJPxKfhgR zA$FXU%DZd_Z`TE~P1ZJ@9RUFN2LahcyJT2Nc&yicx`hO>B z;2>xLs^d)kEuH?8_;VBdPja@!*Au1H$?RCwCYFgq1~`)^bFiXYxzM}-y>V;vQScp-@j z7kdpVT(98ZI)^H}VY^9%cAg;EAK*oD05a?Z51^}xowfI$jMxcLF&sPZ|946C6QW{V zE_QCYO4wQR*alY>JMaC>C&psu_`A0VJEy0%7(3`ajdsqwk8!=qGwYGliNCLU=!Y<~ zs)#Bf+RO;;NP~b4Y;%)q?R&QvK|~EP1byuqkk2=MBC(jYI_o)ArC%BAInmi-?66HT z?EK9&z|OHRCDt=SKEM7OY0`}&ABhK>qn%}g)g|d#?t9WbmqC=MO%YSj@=edipn0`jt(t(_77$oo#yTy|$lF#p43k3b@c=CDsuch=W+>!p*Ta2B^o1eM{*m?X5Y0ou6K4+^v z*A>G6iu>cWSS$J2e+{*ILPUs^OCJ51&j+$p{mD`co-=WEKQ3 zgz+1rrc2K9^%ouBPS9A*$|Wa{8Y}Lku?so!hH$G<7&maE(S+i_UE#152lJ<;sJ7}3 z=4Ul{OI+LR)hD+cQ=8}R2#9|0XdVt3MngOLTeOl=`QCzSc?;L_48=LtU^DE?AYk$Y zMT0Rw`tWEBAgYW2IIHn>v$Ja`UrM3~sj>x_^Hw-|C zh)I#B6NrK%ml~CqQ}M{5<`FK5N{&f%$RoITNWPu?!plxx@-|nl*(jlWl3$vnZgtyy zPw?#vCu``$QhNvzW$ze5J-Q!RzmB%$qi9|xMIpNuEx4REv_aI=?p{)PQx|zAiENStRU;e(B zq;vO}K5$^bzRrP*L)o2shdVum{5ZKQ<=)}0Vpp+~Q}{d0Xp(*pcH$tr9tv}1wdus1 z(Nq$dGV<-}bb@+*s+!4<=L+;eO(dVrvCZ4%2~)ZPpfAr}EZ*TV0F4F%gS&=MueUuo zHD!I=IC#jnBVWjhfo8q=%>^?ceaBVLs5aRCjxrm8%qH%VznksvtVjpAf2CuTKF;t5 zXF8ah;SXl9DZ`)l?C3hvpRAKYAlCb8x|{vau+dI;An0N`Y`JaSfgl4P1@pXGZPT$R z-TI(!qD4OzHKkWyp6nQhFHiHn7RX=5-wx&<@(#Oe>(Pfx&*DzF<4Xo>p!l!1$Bqn>@G+lP!nSd`X98z_Q{OB`%vp% ze38PeB{)KonmFE3jhqeQI-@Mr3kV~>a8*MxTb&~ww~bQss)n(n^u3Ky3RgAQC^fHY zV3g{F61{s(l$ebp7QK6CYa^zWmlIvZuEEaB?Pa(+A@x#MCwzzXGWAhMQR0R7U@Yq1 z&s>9T#HYWQwh<$`_jjzjDBv=+%cqIjZFmpUeT>)lr5Q!x$R>}i{^7~1u6zHfkI+WY z@6-)jzxcMK09*BN_?L;D<*nYJ$1Ujb_kQB4W9OTnPqZ_#1^wa{Zb8p+2gjC@Pejo2 znX6AeUwM2yf)GV`o&R+8vGe!3Zp9~8xWC1fr{Ad3Ph8RD z+H%_26R`7V*MKqq#-m?|*jb#fsg~bWrLT5%6pIDp(M~dIY@T+OKh4hesu0iHS4|AO zsty_7{6Ip_2=P2srC%BGTs4P`pS%Xx`JG>_)~EWq^>Zgu`Z$aFB^hqc5r}?E$tM~{ zf97f+$khRL)8C0-PwZ#4Zo7H<50Z7_#1&1j6HTYYEA=|S&szJ>@)sRJOZB~68Jy+V z(fIdrE}eg4*YO>4n9;WNZ(*Z^FlhQP?z`1?j7|Z#>%zp(%paVs5%0Ebu6v!1-{5Gc z(a@Zp`iDg9Cwesw`jH<`tMUp1pE#&#PB(j)@!a=Zl=|a#XLE-c*;d-hd*W(Pf5Yni zHwr=QEAI&D|5lZLWu(8h)mCpv->~!R*8n@;IGM0BLN_bA+}p9Xc14Wg+>VRV&ZTXM zP-+-)Y7`m72*0h^agw%leJY3GS+fSva}k+5^FzNoA` zmKK{Uqn#5Mx7b`7?ZoZ$BY$%BCH~dQ=SVby-@Hrwzx<_ywUsNHS*sW4%9nPC`utIFH2md>& z6@9r*Ki~ZOw9+qL8U1i{b4xMw&1;OIl`p25G=ibUCsX>BVd(T$J0wMo!+(yL$}0oK zR@2YQKcqEEl3(IKZ~1njpXDo}pVM2tvTqA3`(IrH>@3#g;yVBN!cxVTu899EUM;Ec zt)IC13WtAlGSSFdop#QADy5&kBHCGe?iTZ&Xh!(yYk-}<{z#H>T+<;ydS{k;HdSRJ5~pMQ)#iIeO2H9*kE9!V@_L~MTKVQf6UA-yuOdCQkAuw$C44>)$lYO17_vhV4x z4AbD?v2y`0KNYIH{O~ogxLRgghaN&)Efhx=cj8;8iW(nR>w>DNjhy&ehlre_&5e$o ze(kT)=xKpSlmGD#CXsBVZsxco2flL`*D;Pb@THhq(SdI?pmb(V8PYM18y(l7mM8yT z$5?4T5kr}c2Zs!DxA@w>LHo!1TIcXSxjSV#M9qIY56Q(SISHk+(lh^eySo13 zKow^-Cv-{U%0IbTm0$XKK^N}$HFqEWkTn5DSh}0Dg7LxQg;4tH@j{VHGhE>QgEJ=4 z^26P{a;IS*lUe+Ei#$g~IH*)tI21#wARN$;fzIT)roav!Rb+vZeA<`dWeW^NHK>&q z0F+jI5@H}JAO=+^@BvY#`A`fxy4TI%Z#0Wvikf9Qn8RFKF+93*o49ahg4^O}Wtj=t z;`dkV)71|YBXntZ)Wt3Zi^y>#^3j_4iP}XE3`fh8<#E;=4#mDLKl%=W52P!rEdGsU zO~cWWBb7-6Hm2in+eZ z#TR)%h!NxHEn(pJaQV5fo&+KBdLSW|U_}4HV9Dhc$gti94-}#GziGEyDQc|wLPDuH z8WnBhA&eO4E&3n*Ih#)^cYruOc=;&-G?MUq^`JJ0t63by&;HL-9fQ1eU+4bzefj;n zh@kl0HXqBy8|(2C&rcjK-=#yK5N@3D%X5dzpEoWLFFVW1Mbd(Qq>9KZ8_zmpgJRR? zC%6oh@IxgZ`AhEp1GXm0XO({L18ko`b_i=o=c97&nuzVl>cR~1x6~c%6!A`&at7;17d|X74~!*Er}HeO8bCpY^-A z-AH}*n;hyQMMi-v7K`~CGJ+VtA@pcSJsJw(RhmVxhfNmjAub>_lra=tY*ov^hEsKB z!ee;xu&?YYA*X$ISEHR!>{E8TR*7~2*Ho7yM2U7ni5?3kqULZFAJ@eWqHNi$reC?& zkYlcKy50qF^c)27m~V59-FUYurrY=1$-4QNY9(+@z_axs8!gvKp2f~PS$c*RKVw(Q zMX+2^ivmv=_S3>T4OjnIL%sqSI%_1E>5Z`tdgJr6cl(MEZHa*=xrUi_kZ2v9`V+0A zWTrb|wbX4n%-(8Ocg?<`+sL`$!TkFI;RY#1k(H&NTYDS$Vgh`gB@oeY*1`>Nq6?MN0X%Wj7pqH8TzaXWNqR#lDuqeoRnQl~%peMSg3v+|c*-U{ zL9AI%3bjUSiGC7RC&82qvo8aCq2EVNO5%u@CPs7%ABZHzIX6V4PmyxO^hm8lA0w?? z9Hf=~cZZn?)H2-jC6u2&C=Xgb%ojQNYmfDiqMyD+XLDS&wtuNpo|54UzI#WJQs?ch z#hZ2J+ala4iy#{-R`#r|?1@MQd_1a(8{7=QodFG62Ic9JkT|TvzASxd?xG(YRcX}-^4uh1ni!(W>E0WS5a#lTT)OLuMZJDz zolKGTb-zr)>6eh%ywmD~XF&E8wr$DC--zJGIMQEs`6U|?h^+%c1qS2gfPWTB{<%uV zkqDVjwctC9LILaY(=8UCE)$B62*&Zzf@*7w%{#5}OI|iGM@j zl@?Ss)J+=ug~0>`;~tH?{^ksYZzx<{(zA>HC_`@J)uyf_T7#4WwYA*pcOZT7L+mxJ z&_txQId7p1kK9&4Qj(GKvi1WylMwN5J@gpl{SjpY6e|+4X4}cA(ZfiQE{m>p%MiTM z^sUYiHGe1%AzG!-#yHx2@UTRzP=W@%utR~ua`?VummU9bwuG*^RQLN1iwAld)3)=) zit!Pu8A#RV>rDu~7?cT0LOz;{?bFPp2Yux_>|jt;znCC$WM- zeBP${3~5KcskG5-G(A#DeUGJ%vsR$*GXq&4vMiJ;qhwinG<@b5tY*%I3D#r^4^DjG zKhOlUS5wPndg^5Hm7$PIRlhnnX(5jz^mDxv?>LF`qxV^^HmJT6>9|#WC(LoD`c91F zk?K3*z(jc0&pE=j8Y%qB+c6>L(qGleQY}4Z101;t6>}_`(9cxX(GSqQsrFZsUBYnR zRQuXwcawhqayuqp<4v^-lih3e`(G!!&(E0j7bhC&O|?fS=d*i{>gmrW=V$%tE0ewJ z=6BzF)Ci=)y&l=ySYZ^fwQJ{xDD(XJl)ulLpXP7RzHi#MllE18q55H;VQ1H6UHfp# zKFsXHYwW|T?ZebQYz%yOQ7tyJN&E0B`*4SSIAb4fw-2}JLk>&sqqk!NpD(E06ceX9 zywyJ6Y@ef1k+R7?-)NtY+UMetM&p_{x@p>C>{BW{FRJ!zaI9O#a)ZeDdEq z<&*z(nEZbVlmERi`R|?b$$!t3PyV~7eDd#`^2vYKlu!OUr+o6C3X}icF!|pJlmG27 z`TrOu{~c34`EQ@{$-j5XC;!NlPyW#g|FF*7FA9`D z$lRa$LFfL2KK#Mw{`7O3`;&a0pCgho>fP2j_cfzoP!GcVD^s!9rS$f~wu5LFw5Anu zG5cW^iFXVr6T)QFginbV+iMJD8jn=1khc+XB%q$()JqRZ%bWldyf1I+P1-xRzJ($y zn|e)4vJWmndFC4DHuXkHL)h$Oolx%Lrrwy9Q{B)l)7GI^*t#|eWo>NqDpRkrvBUEh zB^y2c^eYZwfbd7C075Xi&1!CQ{zn(Q16Bp24ssPA@xjJy@)=6+8!SAPrO!}!_h8{o z+34ZOy7CZ8Y@ZS#ReJ zNltGx^f{wtW#xcVlfXt+_3lJxCaVi3qAo5E=~6a=1mKQ56|nv z>MHjSk&6uQe0XNMH$W1m{KIqlaH`rOmv}JESa7F%Q`Je>=pUTb2Pw~5o*T;#>BJIQ zd^goa*x?ct^Uhs-^8a2$#}mD`}vAhFNkj zQIrld=3pWV7-^w?Z_kM>P_9(Ny3aN%)B3prKq{Fc9GjGB^!MU)Z?k7+T-hR!@V26% zZ&VpeJ3rmqNa`X-#I5HdN~v;f_?M=8TSE2c6}vy%QeAFU8*cmvz5)>%^4e2J2-H9K{m$~IPKxhz>sa-}o_I-}wG;$RBH(2X|6 zrJ-EbSjb|r$uObmX8H6Q1EsXIFkTO&sV=Tk&=>4I#^rc%voYUUGE{w5(CJ(`tgN|^ zQ&_FJX^I?{&I>|L#W1QI*2d0|W0r73K}X!Zjf(Z@s)zMd3mIh7V%=hkgoGEe0!>tsTvE$+ zgVDy}e1YA-Qq=kk?2HTBdC9IXI6pB#e^Fg_5!k57fy>m#4J2N}dynE~uy$g~(l{8}!U9flFHgq65<^&q3cH1w7*~ z$Wq`j(gP{v;tcWKAUnXlN%NY>4`tac6QFPKpQ!HYO(a-u7n&wDs*i0cQc?O(p;Cli zR!R0Fz`#*f3Gg~elVt)LyTs5k0V!qRa;yb*d!#x@*5EIdsI|&~oUMAgl&rX5y?Sb#Md{2i<@W`a5l1>?~4$e z9}whxGPJ%2(|zJ3$o2293Vs@=$Q5HN#_6*mbojQ<#x6D`2qKk!N3U$??aX#EL}wId zHXg$;v*Drnr|U5;J;`FLdib1XSzAB5R|vL<^+gqOD9z zThS9DhShRzQ_(PUGhrC$Ip@oq8n@hts(8k7HN$lz&seEuxRT`=7poa@-S`5%g1O@! z&p-wXvI2?eZ7vB^K|=y)#|{(62~wt6ZiQJ+k7T3AdUgqws3r=&=pS|k5lNX9kc-C3 z1}34s*85|Km^}#yqDEWFHV+-k(j&)uW5z;6mIdi-8$`JxK9u!sJlr#BPG4osV^s=S zVfNWHJYcjcE~S?W#cHRGV>BWzEe77j?Z_#WRxgt?QKhVUlyF zqoxyR{SHzy)^)j}`{U(`hNWw^&yM!e5=QCaUIhXJXt6Yk_>Wc|(4s!L_)Wy7x^t_m ztHRCzT`U_DQ5>?0Q71vQW8@c_+)wYCzo$!S#p7pQ8ft#D;kGY4CQjB#5OOs zVaQ?yWZL{CMWWBiidFgSq#OoVkX-nVXAN5z<_}nB-zPq?eGt;HIftj{H>fLyV;Uy& zklQJqxF;c`4Hr)%62jy+B?c;ep7|aYbBVhtN`o~L7;P{O?l>%l68*E>E9G1;zIbJE zhb7tXdt??Fi>$yD*b^AoTQ4?7iU*n6PsU9PBUE(Fr2v0h?X8fXE=!*&AD7BUP+9hY zP>FsdyjWnX@M~s{^AtmusHOi_0qoQdCadf^xwAm7SQJ5SL8v6zrm(VNoL`oluvkgJ zl})^&5^q70%cUT>_?MuAr`+jWQ&$}q8+s=5$d_QLf=C+VQbfAdIgCO(Dh25Kjj(YQ zA2eD@@K^N|skx$Q8FJ!E;6>7VwTU1X08iiGBK`64(hY*nO9auE@AhOkV6nj{lJ63i zy0js<-_~lfCZQar8aE zuTTNz-Em%U#dl7Utc{KsYY0?4->=XCCdR5G$MsG62P*9wtdwBs;KQQr+eA)i_;2aE zrIz6I!OG$|V=2E>Nx>t5GVdr;G`6>*h_D}-m^*|VW+>u2mu_dRsdo0>LNXr%DNAIF zE+o1PsKgAflHjOFt$SqNZBnBKlrvM;I->#YW zX9?Fn|JlJ^H6t-T!OlBCfQqmx@PhYV-bYnM2u~jrRHL7r!Dn!Dk#T%jyNVmbc0Rk} z1x2FYfMVT#8@_Hk=x(;7U;0Fn$_LlIS(Cf34qmPGdy>05_jK-V^B(+K7q=Ad%IVYc ztet1~T^srO$Dquoic13_wW~YY2Q>#hL+bhY30oX;TGJ=26N~)`K-KjJnmyhHsyt_XmjM=-nIi zD)AZm*a@NGSoA9S;m+)-*neQWY(B@#{A}_dVKw!8sy(wOSss()q~FQce9gEVM)HOG zAY=J=xRUSPqGw+X^sGoeUQHJ61o8;ZXsBZ%i5*qz0X>KG=wTtDgYlL$U0N$Vj#q}% z^ZPa&%-3E82AoJg`MF2pd86gJ9Ypu9vk-l%p}S3l{!dN_n?ZhmUC?)Xk_#ZZMak^{ zF_EW^Z=eXN3;JF35|3#q;MK?S7_Ek#CRU`igcps6ovy};lw-6O$9gmSH}BWX#z;6< zhIqgw{rtU<3G*$zTnmG^b7d`@T#FjB$^C6E?*=hWw#{R91zG(Q>cumR^7wxRzJ+tf zmGyy1a@eMS<;aOYRHxSvida-)uCKukUdJ0sE33iEdZ0U55P@NN`sA&2FO3{#t&@3W%k^+=ftZD&#-$5J|{E1lr3`=4#M(svi>l-$9YU3a$#>H1dCP!dXFnVl5^J2R`E*C~wO_52cI>c<^5W?3>l@>${&=~p$8a$DE?W86HB8XlY>N#i!?P(vdC;;*Q{7X@U26J2(EKG6w=kPWr{jceAK zm+|!Pl%pl1_e&GHkDGGL9&m6~#@`Bk$nu6_o{C%=2ido08;MX|>t18t^Py0-JxJlP zj%;Wk!6r}ZuADrL<2;xrWS>o*nxJBS`x|iP;rHlYj3c&pC_@yw;xZ1W!{Kd?AU^tW=}M5W4k)7!wj zEf3*+E6>j+`)_SlSg&o@5W@&zflshvGooIvjAfJYy6<`xZWH%Ob}C3DbsyWlgS~Ds zy~^8tu-6NDJU)-S-mp6F{hU46yEf$V_DEb6v>gQ5NNt%N6p#UT)aiSQfcIh3ZSUZ_GlU^-f23XQ7vR zr)xK5pl87aKR0whvf*ik*d5Sk`J;O1jVFZqe8%<=i zjHa74AUAZfk!>QLxmlx}-WYp?h(;_?D&0VGlhz-xL#gzq!5^hM^f8z74CJ93x-Ef8 ztFfn~&yCYH^~s2(F+XJ0Gp^z?&dM)_nI8scWyq1UiibmEjgeSua<& zQEcp@40X3Vfz>DAZOKKwj$%8}B@wXQSKV4JDq+O9s9_6S)VL{J^qTd#=nzK-Y2I!X zXDvf&5IAZk=r{t=oj?a95{0xv#FFq7(u%%}W!nO)ygHi>Pn!#V`Xg{TCo<0ugD4p0 z^Fl(wDZ3$|!Xl?4iyYD!)W9Np4&!V6=Q{tH^`95`&-MOe{?f|=_>6$g|D&?@;j({_ zW3;LuAFSNZoyEZ)ClwB8|UTB+` z8o`g+2B@B1WSfV2vPxwKIyFLfG84PTbpF{I&oVaEzhQ^f!L0sR_bML(yh$7aON+P$ z#vySM4$F$WbmxrYba(m=+%Drx-5Z>hb@#xuGMFAGFm`095?fNh9{un zHKgy4bG|Z!1`f^=jN+E@x>3z03U=KO&Nj<~vrQuDKlCXd(bIt8j+H5 z!xg6`VM6NR{822~OMG#^s4Yjv&32^OedIo@x#@qG(Tcj@1L`h@FQZ==zJ5&sMW9`7 zt8}>&^5nr0n!|u?1bxL;D?~c|LlI2G7Kq|(veMG# zCD!v+&&0h4N1)Nyz5(H)k&V7)=Arp(@8*OTHqr4;)=|h1=r?4Tc3aSI;_XQ2Yz6w= z{_*h<(QjEsq2DWL#L}3S_1jXd5b+D5m>7&yOvgw^2}pnl>x6_u;jIP)HE-UkZt-vk zrefoukEhhPCJ79vIa||7v4~9?*NQWOU7(6~zO*MR&Wb9roz{^pSzIu5Per4cA=Q+` zGS&32Xi8OCq-K5PoJVlFFyvB=cw8g>VB|e;0tY8?Z4lLg3wNm2qK~esIp?<5}A*HVy9(5NxS@?&x#@W~~-A2>sH`a@g0_?83%e5MU)40`rO> zkp4dbjnCpuB6=>3RN#JuckrfoXRcU*{!w))qRBEIi&>*jmxR3lP8zUDmBV(&Un$?p zB#BEFy?b=LyRk}X&X4;5w)r@*&(oUL8*a^Jf7dfdM57h^5t3)JZCz_L_lr}d)(HQv(T1_Ej-KGb-s;f}&)*rA~&8-E>BfWk!gx z#TAt*Ed_>7OLye#qZ`smM%zJgC45O_)C@F)se>A7{n(xx0TduVdbi>2NuCsw09pB~ zb@5F@*$~jj(>y?{t#1NH! zD=d_5i z6kq~pdW}2yhJ@G1lL}OWnu^v^@gr=7{rEW4J>SjRHq~LNP1W1UeZ4GS^kKD=H=Jw_y>*NLGRMv@Sz(CWF^-E33QbMEH?CGDvcI; zDj07#XsHlIPi1u&A}UqNorvUihRf}TQaKsgXJHTeJyYqatXJrsM=Y9$l~H6m9v+5; zu+1ke+Gz~++D2P!L`%-sg5`jhp{seFv%+FcYWuSz9R0{POApUBcXjJzwvlE2JGIC}O(VGz1N|U6H9nv&Mt-y&BB0zqc zU_R(kqaxh2%OMzV7h8WUd^OIHR z(vHe(VUmK%iYS{5VJ{HmNPkDQG9&FB6#_@PJ8FbA5aCgA2sb{lj7D?DmMulG+leHByKo?eOz@Z^LO*X`gA5~WPl0cC^%Xad3tEN4OiEN7a0 zEN7bb?oONH?k=;IVmX5&2*)J!x-m?Gt{cN79=kED#hPP}5KLYNs1*N_RxVsoGw_W*~vrynk6 z+UC7v;abR{ubyKQ8n<|aFO1A{Dif-7#_8$hbPAB#6GN{Q<3g`+<5b&}oAr%T^sV!N zoJXYHFa(oeY-zB1O{vrDH9RgSpf(aOnGQCMfXQMwH34HzMd*#p8zUf@I$C$+7HG$~ z9Z-xxRl`R>MPNe4M2~B_hD;$aLOsC@_F1uOiK$|2VwN+I zkZw3D133z~Yt3(kb^{7g2gZl=+gg_n9Tx!k@O%s#r*v6c>0#Xb26EIK3y_T?8QGG- zq~l4yLPalR1h4tQk-(o%jRY=kHJ=$-Q}e^I0D{{N|M(Gjx<2>Ht^K7~D(H7ljSqD1 z(sYd?y#5-b%)Ed6@y8l(pe=iNV_ti; zR*?xu5%=bTYx_h^0^&gO!HmYtu z-FQ82FH6SgALx(9h;q(%Qe z8+DVdBwE;D`jsdos{AZp_qf*iF616bH!y7d%{y=E(mW6M9LzfyqV;9|mN(sD;uGT$ zmD0kCPtdB6hOQr;SPkJx;;DZDf`=#KIE5#ZxwKw-?I7bxDirC6B@o*LU8F#u!D1Q9 zMs+1)6j^lGOMz}W~~*V{^YIDbGbJGo~w>G+TFaq%%`J^#$-(oDENn zMQ20HMpsuO5a88r5~s#`&=QF7*cxX;Xd&N77AV~$^j5k_xSUYgtv`u%zl#H}dD!l7 zWz`Fn+wE2(5G?Is-bA5K8HJK!CqZw(Kf>H1@sGGFEQklkv=pMnG;3?e9=<0@M`5u? z#iCU7YNr%JExac%-fs7WXRmM@luH+JYS~tYw|5%hUW;O@i@QoI#NDkhW*DRLzgJK33^Y3?*uBtMskeQZb(`t&>`_yGwO>_h8OGX-dAv zOI=Wdm!oamQbzOWZNx7m8azcHsB&BB3THHf_P3UEW=V8*ve2HLvM{ol%G|3iz%W*E zHFf#}WD0~(huk3p3LNC^sUIJ2;|NKPXb=Hgf^rSw%EcG^@k z8pUuzRT8@xPpCj|3@Cgy7rYR@KSEXT4I%gd#gf@EP%LxiqYqa=v6wR^_DX1$QGy>L z&62Ljwn+D?0h(1{WTaWmVo?N|75QaM*Ej}97m$J#LbCJ=>DoF#x(XSjEumKkgFdz; zm~X(BNR_77p-R)5RHx4cHJN@Us)YYe>}DiK)uk!QVRUHqHU!8yJ@6qbKT?sklxJhW z^0kzQ=qZN(&rEr)DVC%Y5Gc=Nv6wxH_E*y<0Jp8OeuZm^RExBN8BUf&MOZdKhVfIYi$M zm_zV3!VIES)sZO#-4`+_vB(HdAdCLa0+GB|*oO??6GZ zjb#hgWZ>~mMX^@WB>R^k3IZ# z`iC#l{5SvOAARTp-}umP|E2ZUj3&!?F0f?gw+?KlHS(>pBBp;5E@WY}ZUw0*PzJ7` z3iQLyk|xr?Yrv($>2udzf}+M`sj+fbSRgpd;gaI?;ZI^=@dY|~3yX_5ANb@SqtLXA z12^J?Ln3$ni7S+07tcAK9Hlx?O)qyG{!pA^bq?YXF5h^sl@ zKw3ei;rY741GoV8(cfJHpz$=BFM?0lapA^#i@@cw%0X}kn`sOIaHWb_N7!%NM zFn$*NY-KgXQ`sk#hU0u|-sii;LCpD;PM@>cD;&)9v)Kg<1Do8EemS^|DT;xBG@ha^H65|*)XySnaU5a~6h$9Jb&GM91uy4Ag*3ha{CnAG}l z16pxkfypUfH=wOOiOa@(#4!P3U4Sf90OI}j$+62RE3UhO@aOF^mgp*p^(fT-{j}4s zv{NA1(N;Jg*V3MZjqmMCLW+1Dmam$R{<>CPyf=bVUvX46dhx875QphIp5|!VSd`V> z@t;AYM~(}-b&wC~!t3{0*emESPjvU`_dMG_p+`S#h_C1_I-`tPz!YYGrHM6;b}u%& zFCmvQ0XJ@rHXzfY!ur`W-|sJe=6AmG(8ckekz7o5R63H)9qP?--5>w|G$edyHkXYY zc<9h=Gc#F-6Z`Z1dmsPew{(o(9}Xz`Kv7Wz(a)-fz@XXNN!812#c;^%rQs{eeN>(l ziaM8#%@AjBmp|;`=Oz5lIp$8bj|V#Y+Fo;}N3?+9Y&h%Op55%(!`WUQnlp#9jykAd z0>iiSJp5WL`IIM2mvwi=;Cmuif(T7J4^@v@d%M^V>iu>)x#zrY#47p!@c^i>S9y-+9J71@F_1kB9 zd+C%h>{Eb)?(6>pGud9zg`$cI)VQiq{X7L3%}*Q5_(G)vyvRGz#6bb4wZ{A>zVWud zhl70lfqV8Q5`4@HuXN8Ga2x`6(~rCRrO>8$zDUFngjUC;!QCinSQqgnk3-j9Tx0&T z|KSgyOiO=t!@6xg0Ul|OVnz6*qw%rL;(7k7AO4H?9r@J9{&;v52z;9Mu4*sa`|^aH zJ|9~HsLB%*o-iMsP>(|J)M8(z9ZrT6EsC<+$ksnDVphF^1@bMBNIwxEv|`pi&sER= zRAhQ}&xQwj=02*`o~;l6)wOg6YLRcMjW7Rj=U_2LSc-;tLPY2USnZ*pIFzSzc2lH8A~#io$&UA=l7I<1{6 zQ%#2On8k&)I|i@uUAllPSPZq-DF&`{h46TGt5Alp=ZvvO;8kpQM>0`uas2bxcm``> zC&zY7@9!K`7;;IRGVjP;O3upKvC&aSjFF)#c&BRWYokQdPox4IAJ};4xMStXPA?4u z$a0Mu1>i|yrl;BF3^7~7HC z&KS+Pw?RO>N{0|RwR0D^2Lebooj&Rs2Lq;e?%&H?1ZyUOP&t=4JtRnYi*}C)h2bqG zVm&s&A-RfsHd>|>Lu!e(GxGxnYp_){!=MN3xN%Cg9XV2&R39*If0|qkxT1dAfC0M} zk4@?xxhLZ9MWNsoXfv>^8PHJUura6=i;I~la>Y#JqQlq|%Fm>K7UUvd#O47dTTlfq z;B9f3v}|e0mnz4pToOPKo{Y=F2y2k%WH<|r#ZUMkQV*Y(ENhHX&)*lH~H)tHG# ztJyJr11_JOo0Go}HVnF}Zp5`&S#j(KAj`5ew3cAnY@3bAB~mK@(N<1w;|(M7xXO{= zWDJPWau;X%rF)`-8Z*B-oB0Km7W!Z-^oG-iMaL|XS@Kh`AK8T5kl53XUa|1CyJ0&h z)hVIlj-S{q*1^O}<1+0FzFy<%`i!o6PrO#u_Z3a2aH)!PdW)3AhNH2sgLD&GWgwlc zGEov+Wowac)he?NhLKFJHxl#0W+L5xpq%Hzfk5-{3-XQ(L(SHp(j^wej{HFn@#n6I z+NM_df=Ii{QB<-TUK&*enV5FYjP?H(^$<1jOjS+HFTO(}>`U@5eXgQBR*3)t&nhBd zXAK|%&py^_C(JpZKxuMt9%w|u$)#EHw`Jz+^qbjN*q-+pl%rA84fByWfvs|}7u7bh z(X<(aY`{sZo|1CVQKK9nj)Tuooc5O|XrFz{vAkdZNp5&WoSVPO{WR4RRtSZlqbwGk zWR>)^#8MfhAYw+h14)NJ$?k9l0Sj5_Ah((zAvW{n+MCjknJ6lIV%9k%DsiSMX%f*7 zVeO$qh>qIqqE>By!vx%vM~jb5R0yl}pr8<}WOY^^CKX{30Tl@`>)gf$Y&E_5e1HQn zEERQKb`T3XWfUm?ePkXMuX$)0d6Sox%D4rExd&2aHZfz0TTqZll1Ag*z+&(IWj`8N+?E1$_D>cbe`LUxvN*QNlu|c5 zh?kyoE!(SlL(zN^FFhZsm`^|~&F+AQ1MdUQM6ziPPDRyL7i|`UCGM+O^QiB`t138A z&CXAm(POZJ`(p`p&%FjpB2sZ1$QLC0o3#6pe}DgxUpvN;>%tyziAa%P+=5V+ae`OO&~3SzKSk-6Q~_1?D?dTr>OKeH=L_D-32%jx zp_QAZq!xX-l(1m{S*aR)R!GxS>9`H~S2n>biFPDyg3nUV&MZO&^*bu>w}+|j(Q?s~ zGv4ai#GuNzp}&>ys!*}I2lK*g<>$$JNp`cwRn!hNygox+W)92|*+h`R`|Z7MRJff* zjV9Zmr)Pid*B<|sOYPeM0TU3q0^zC_=5zLyVV>r9vke0n0uJ&L;V@i7sY(dyeG>-?0$+U~^>wKzt4E`X( zj4TX4Oax2mo?{>z$6~2V&wKRD0UgjZ{Yy8m8z9%)H#lLp{pI4un_ zGmC-5HWM#oN(hRZs>sscP*-_L?{ca3~IzZesXGiVOHtl06FLiG`YRouS zcH|u;lt+xx@oQ~4qmfH{re2-awvRb#OtV_xX2jP10EdSg$gS8;O^sAfizC5oiiRV> z!fN*55o!4;rd6pp07<^~jaifZToW;GmvSSp>PT0%^gfB2S$!A2h~AQ1Vag!bj!?{D z8Ou&H57jH(8k9iK3*P`O$%s})qr8&k7+D+Y0-V@v3Qho+43N9)>7PeJwm9B3KM&kU z@up_u76|^lsDOw@Q4OHgSvDPD2i|Qt6Pvp+%~N%kD}gyYSPw$w@o=(MlVKaL@z6O4 zB$FdjCHSP-3(+>iR{IIx_mpQbnP|Ah9w&WqO*Mal@gwU3MPzT8Nx-=;{jp?YQ-f?? zF_bD@6Z7cPzb}Z3q@};7>TM%PW;u~?_fXZdlV%JdO4&oF8b|2%p1o4VKF5DM(Ijo4A`+ z6kukNIQo&4n8c(Bpp8<@?! z@g_TUwaqM2)YZg8J>!i961I?P&|Xm$ofgqLuy+trXGMy4@KOE?;a$f|8A>5w(;U#iCr=zKK^7b^*~N?55R;4)!7E5@L! z$C^2Ua*?9jtvGpENg)P5DQ7DwOO~=!Nm;fOwiAnbxaEnjh?8EVa48fiY%&%p+?quS zVc3h5K2Vd_KKi!SBnto*Z%0U3L?U;6p|~j8YG$Ezdl{E$iB$RoA)(x;laL^X0DV`L z9>hP^^_gZZQCyVs!ZG6%*)>jQFV~yF>&wf{$#x+X7_(ZpF?vN~qI%)_azk;PY`jU& zFy<*zM6_PBs1MvIt}k#gkGuQp!D}$a?G^QqIRdlC0|~SK1YpLi&`|gGftKx}88>i>OYFLF3oh z*0`Otm0B821R$KS{~6s*KKpxvZYN7`dv>>zc5pi}yUDYCr%OxmS-JYeW9 zB+(^3L2@uB5*MYihK}tQ;J% z7&-AMPvb7J#dvUt{U{`0mR&zRGG9}y<>3d?KYbgJlDIi!+ZFj+pxeRa(FtAM2wia$ z$06_)^Ft{$1rhdle6;GP;RF?8FS_qA_&&A9XGTqE^ndZaUco~8p(HC4)Llx3ST-OP zU@cN9hwbDH+kmFHK|M!)$IZa)>Oihhy_@3MM^&&hK|z%#V79$kFUg2qQm z!HSgliBemxq{|CtNYjIOBQ{a~6N0SN-3igqO9@ZZ3&wQ5U`)n@s*LF|^nH~+zlt$M zGAG7_s`YivY`!O)IYfCHP0x$7NY$EX){{n}P&HB7YW!qz7s?eZu5ywBWUkc1cQud% zvO(GELRd}9mDL1Z49ZisYYmPdoc`% zQ_Z*y)e2s`&B`{Ewq;Q<32cCRqod$6c^d&k%p8=)|KUGJJH>f!bf}jzEX)FO>2eSz z_<&BHobd2wGGs-`gNN$wu%B>ol25VNgzLy)9pMuu&ETaYPgJ?6I|xjbzPx-fxQ?8f zTJz6EzBsoI?)bPEPOmMC1A6|y=`|mkKUa(9v!pPeu`@#KvpVWFzmL}az&D{YvV5pJ zE#@i(Dw@=$IRh|?LqiK~li_N2^MtGm&Z^nA492x{HH>y{UXz8u?GTuhn8RinyBCuZ zz_XLdLox}qvPsE~1WwCFXS!Rk1+?y>U(@jzMMKNf0|jxK(Rq>7-bu4WIN0rUPqacb zBA>(>$9dVRH7<};oun)UyWo~8X;rK^(}`RP7UxM#Ru#3BON{pA2hWq@;H2}UI3bHT zDhx_|ipNQH($&%c-i~am9mh(AV-PYw52)`9B_xf}Ge4kcVOCuAHc!`BKmAiVY%bv- zBhf!Pvb)mBj$(^ohwX592jJ?_LP1;=4`hdJ^#Tobz(?DS0-E>)<{O0!il_3FgoQ^I z#dsi(J}(a`<~@?UnOFS7;_#DMSUhca?4sh=g$8EJw5&WUYjz|%+9UI+Z{$d_^`kuv zKmTKK>2x*`+|-?iicG0T0$=I0q#k8+;i#k@6{(MyZ>Trw6Ow5+LGL-&>lcjvY z%o7CtKz?@!qm5A+X38Q3-$GKLsxd_>!DCqCjdMR`u|5LFn~2{09%m#5j$^1Icizct zW9%0kme|7Hv+iisWd*bw404BL9$anhv`@gwnt*64tBP-yYAdUXnU;#mAZlLXFsY6Q z13{KiHv?Di?U3E75zJb4%E?0Z^PQG$5#vQG+joXkBi=t8ii4N1rxs2PC5Gv8iz`Cl zh(X}HRR){EGdwgaQ#NsCK)yXzpIp2|xTp{FqabF7DjL<@xm5=!D5FUL=$d%P9p@TQ zMp5AHj#}CFR}=eeyBUDBZDCjInSg?Rtq-Ctn9T@iEJ5@9?3ltxGEMm@mS3Q=V6|=5 zM3e9R7Dp@F?qpW9Uk2$SOr3=ZqIZh1BT7K*4p-6L{M#hS+Ohy}Gqf6QzS#%oLtCnn-&S2>++<1IBu5am`!5-_D-XFZZrYyaU9D{0sPgr`{ zWvC=Tgc>=<+@b^&$OuJ|AWLr}KT{Zk6Qd*fY zFk4D#h{gtODcIbKuVm?MXq&7^k)>D4uvvN`Zz#pgWH`GgORr)`>6AOWEJQO5MmOkr z6#RWbrjPr5OOD(@@Rr5L)o?spF)+VNR)D?1;KD@slcTlxz^pLa(DLX8dz2uCbCXiV zG#C9*T>7{_nt!+vxD)t5oh`yxI-{+Ss?#G*s!*3^s-y~v8pFxB0jNr<=%SB~p1H{y zG&GX61MD2wk{||P6a=gcq-u(k0$E**7$8&7bE6l;oxf@gnX(&0;vz_k*oj7bi&9OjLqY)Fy7N> z1ThJ>G!-pz91mp$4n4=?rfRX=`3y%+OJgeS+IBSC-1lakqx7`ho${3jhFrle4&B!W zj@TyDUC{**ChJNLj5i;y6E|G)cySFPN5l!xP1LTNYb!bx!qHg^AhFF(A$a(kp{h2b z&3umr&KW}@7l|wSHmPssTbzQZdFUppQI3)a&4cwQZg^S^ahhB)h*|IED}a^IPDDht zLmuE#JBpp`Q(PIMNjN>`{IHcxi65$OOz%~U!8TgObVcj%J(WkfOmmR+uFn4JS>#x% zpPnJ{9B1(7C7wC4+DzNn1rksj)pFIJZKgjuE+{L`?y`d2DyRt0nLby|S^9uH6e+UZME5NN zDL@z}@@g62Ptclb3bR8jxoXN1DH~&oHn?f4F7%YGoXHW>&=f#%9yLmc-CyT+0m_{ z_3jo;#8eR5xA-#AO6YE-jVYeoT&!^d4>Pjs8E6>;*K?m|>AZRd(p|yH%JVG7t!Kc+ z4I?hg;w7_%MR64X+}cec_%kK|M_5MDu&PN$@vum%h=@uHjxZ>a+ch21CIkE2F8N=Y zWbtmFqCC2vK?r{CFC2vt_Jl0ORwV%`tw^xC5afykYpfImg&BY#WLu=$sw8RACXnVT zC9DF(weX32fq-Xx^Bycz608S{l?1EcM3Equ2qq^~VAg=Dh-s#PsuXJBRtE%CDp)Ei zFkK25R1$p1l>`S$ksv~<#UboAl&B&x5mw;LU_dGjI5qbS=QQhWn6LImQ+3SAb74(J zo{RV#AWlGi&Z}uX!xa`f!l!lObF_>29L8d0VKP!b1UfhD{15a>o7w+^<8$15M1hW}i$H`SZPqY0$MHl{78yXrPZAZO1B-)1LtyroL@^rh@?we#Ja4NSxNdd0pz!`x89wGYa4!Y-_EaEvj#EEExII9 ztBi)}heD1U@+`!2MW0YA0;`-;-OEpmJQ$=2!apDes4TWR#jnncw-sg4*cDL7`FW9g zqu)t#W8{P8NG8@{s(Lh{;#?-_z!dsw8XV5l{%RVMW|Owj=VTO)0*B}lW`7lwTcl=C z;t$gE2D_PI>uink7XfQFt;gCodE8Yyvq3VL%DJ9hp{%0PH!4`ZOC(MYX3J3eoGavt!HR17?wG#2oJWl0a@@dAVza@){Ex2AYOhkHOwlOJ7cFCr@TS(KqURQ1d z?)D3v)mt93h$iMP4~o8k4k?evO>wiu@<8hALmrP419|9p-H^xQhJid5&htVZkMXk1 z=&#>gmsfq-se6E$ z7x#erhr18<=Cj$dC$lWPJ+(iSr!$N0A|~*&_Uz}-we6@&;8b}dyD5HVNpzuE+&Ar| z=xDpRkJ^(M&QNigsx2?>@NJkOqdrT!dum^oje)k$BCjkZjNU2MSDtOFf&z4F}%r8LhLg~CV3NcYsf3lY?4mkA%O>9k}4dSCNQhJTy z2?tG^JVGq@c}ky@mu1)Jj{R$%;J>V3xUlo=%T$`8-kYF%k|||X4m8|;#@-* z<2AOyXJfH)x_ZP0Yj3)Gq){}byCQbP@3PG|*IuuF;m0_-r}n?ml?&uEwcq6xb`aw> zSO^vFGq(^bqPj0z!$ViIS(W-)4Hq@>)ycfxy)IlYzTFu!S1$d3jM*w?1r*;Y@3ty? zov!lLtPB%#%f4o_$Pr(VMgDhv7P(zFi@fc5#kJ4RFRp$5 zSHAuc?Ot94DSkx}ZgqcoKhSD^Lv(NnWhI*_xl74ZN?ua3kX4-Hap>6*r)?k}9#i&Q zaE_a@$nkb(kuTnuMeg|{S;1q~zsLhcI*w4U#6bb9uV{H~gt6=N_5@K~AS#N%lwFtp zpY9%DP`$=CRE&CF2U%r9gA|d`(HyF0e8XO#dXcY;<`Bmh2f{Y0`yh1DwFv5{2&%5T z_7_O4F1@xFbrxm;QMQ<>CiIFiV)WZhnQq6g!X7cE$00|GpBwM)r1Ua`5pt>8U&g6t zuR2gmF=1su?=(*Mu)WIdV$KVSB#-!`=rI>ns=SD?jk2CyCxPrbpf##c4(S=Wxz(f> zT_=TcdROiBz0ur+xM|7?LKXz%#IPUEdvN3+mh@?DqMCB^4#E;eZy=&h%ewvPVN?nc zW6b>d0^bEc9+)GhdE7c6$6Pk*m*z-OLa;*v;r#z&m3>JTB{r_}MT$i|Kv7NmnP1|T4AKy~7=F|ADRX%5xt5bG|#%1HQd%R}8CnM!^DW&LY=*lqqi|jh{X@doSm; zyZ#}EFy`j#3x}x10?zHr_V7yDEABmdsJDj-IN8pL@@((n?hTyeZQPC?ti$gh&+u(5 z2F^h&knr+*kFq2PzPUgTk)SwpC#xHsB$Ok_xhvZlhd$y%$EIsT-}#H#E+6{Nb%##5 z>d+T_=pziB@(g`ML%*Ri^j#YIP7R$uVd#o$P!8QcWauMEcl5S+;h$10)fCQ&My;OIMoqNYcQAV?aSA9MBMWlye*|pN5rrm*wr>Ci z`-G4P%Gr-)H#2w~i!C^XVd-q|h66xF*$%eeF1_!1EqIK9_Xgq#FeFZN^D3Jns%30C z22Eh$#)>V8=>zA6I3`}F%1|rQ*<+tE+tdBAY!37vCYIz*Fr~v17*PbrxyCeDuLi;w z8qH5*E@F#dT-W0=@;Q)Y4|sD!Rt{C38|o2hF|>z>Rp=6?Ll49;*LVwo7ii_@dV3Dg z44;K|=6K_S*v|vmT(;9jp8#NhK~P8=J)B1#EJb5+_-uC+ja9~f3#Z}<(NR`>w6}|? z&29hyBLHBI^|7-%VgML+0KAR`WNpNrX$c4bpd*kN!%ykQvX>GRGJA>rc`f@u?9$fd zR(C;C3istK>lYiE9ri&~E^pF4KCF#(MdpA4vhVmigJvikY+FXbCVHdkXDzRhiRc$- zXu@T$!SPh%7ff?QNC`Kg3wVVQAPARS>aVGJTeV7Flt9JV;QKZ}!?BvwDIT{CI4r!{ zU*^~CqzYF?sWVvKA=!2&_>>=i*PC13W1xHWLq}%$Ba;k$N@|I$%6z^dc#1t0Zt+s5 zs5%_$7ozI^HZj6@7TTeyjqdpi|M8RG{nVEpJN^Q22jyFDt}STojksN3 z)BT{{HILp0Ifbb|wfq(QW!m`*BTN6}m+5C-*R06zLheV+{5@ac@OA#e;ADiS_wxG) zd_(}Qi!1!bIL+&)dhMbDv4_S)WA}N{hLw+vm%5MIgSyb6(7B=X<3ccX%+VwwFnbc~ zBd{<_Xa;<>d66}4uGtMyY%d$8OL`cJmQ{1Wgbd2I>ImtZRO?{d?*>G-(tUusKCY2m zoIrQ1aXVxsc6vLzTIh$5y-7-(AmbU?ZdZ-ylR0t3w2-kiOZ3_%jN3*@+a{VWw}~Wt ztTxXR&kDEl%j|kcoN|e!a@UZHGzRoAUtu%DyKblgs&b~wG-hKdnw&-ipkt6NKcfj8 z$q%M!(=QXQMc6+2b1-P%*l|U3}ZHL*2lqttsWBYO+t7>n(6?a;V8{K zVl`c1`{QEmjpMcSt#Z5Qc1GDW_!a2@P*;}6mV?*o{9cV9B#Ff^xko%uu}UDm2WE=U zPl|vxoFxZlHjJj9aw+-gB9CtTK_M*f9g(N0hd zzw8-EpH2Uar+A_#$&xuF4Q4?q-ZE~9_HSpCpJ(AEv&qjPaPsp;M9w5%92VtSNn-Fl;7o9B zOHYsLLkH68zge=YwuC`j>pGFdz~2uy^p~LM`N>dS@vxl?jqvF|SYr0muzyG=ezsdz zUtW(6gfS0ODt*$1`6K#;LoV?f`UnA;Nsq;`EDrbV%M;+Gx?Eg?No~i6MMUa_`;ea; zDO}T&e1#QFPYGQAOSat_2QA4b_Ie+yc?+C#lAMLMDI>zkzCUV2ms;9Z5O6SvD&RYvPFLemqEKb|;8hO> zEifs3P@NMwrmc&2+7qP%0)?=>{~VW95nyuJkOzXLc}sHm2_$ zOy3>T_YJ1+Q~J5#GSNpt;)UV3xny+Z1TNGX5Yv=A#`9T-TYlck*Z~p2`-xPzU*I~@ zjgDdXJX%BQd8Gpymvv0(l@2T22BP%J038lg=nyCXqVxj0Dl0?j23VD^09@&YrAh}I z17L;k!a&1DWMjGK2^k-QOvUM)by3nla#ojvslXaUG!$gyLP7FrFa3vi8X}fpiXvKAydCu6k{6>sL_Rq{B>9kYVi?~@P~U7M~U|nF|fDcs96`rkQIEG zw!HapESorlg%G)gj`78YLz(xl(l;wsC-!kZDbO6fZH5DnX9V`VpE!sYhs8AnLx)3` zwwd!`;Drx~VjV}&hxu4L0R$zf{?i03D!|jk40aOzS8w=l(|`20W!Dqdp%ZHQL|Y3> zlPUi4VS7`L2>t$!Fxma@J>7XzKJ?}gX{Z}NJzjiTR^)Z0?_Be#^f}uRCsyv*Pzg~g zN#CW?!Vh|HFcBm9tgmKaEb~bp#TfI4{ZZ`VL4Ta$5mZrujjBVK#7nPkoG%}fd-%p~ zy#b);LQ{E`!*3~4j~!%6nmDl+F&en{kIVk}T)!Jj25Lkl^=c=tuv$5h;{{-q4rSp? zn*n22?U&%X)V;G?XV(SM zB=6hN7Cfu!Hc2^?AlrgBv8#RQlln1l(+C{HUO{%E{7N`Ij=M04gMm5yt|xL)`QHH(`A+r@=}ktG9xysn%2lKkIE zzfd3Qnuw3`W+Sz?U**llrZ<6+u|WlRp1K**KzYn%(8hT42*gbm+`c>?_arbz+0Ib& z`6(LrF020pq(gf z6l4qRHrwFBKbRofGxf-pI_Ya~*+zJ7Qi9ye6PwQbti9nGHi@)R{>y?Bq|qykCX>b? zaYD3M=NrH@WTj>{l1;pBygAQ?PBwA4w<+61sNR|GCYlxg4l2~XidLHzAcf#LQ{)TT;>;9XG}QGAijdIZ&6Hc3VhsZg zvYVI-7Ckjkg3V>df>`;9DQzJ(u+>g98Uz9Xx}=_;MEqTtO!muFtcd@fOWl;WlK_Bi(KFrd!m9})%-sDTRj?v`x``B+kq5{YD%!&lW z9BKF*+yF-&;=i|MNC&{IY`;FQRSCQyD4%U~k>mO)D`fOGE%EdZrCbt|Lmvu=ffeWx zjwav(YP?7{ISy^P-Ap%|RoMa)iaTK6&%>P+6-MSmL1sX8p*AO2Y^oVf0Nkj(h=eKMD9fSV zhHSzW7}=yJFemDdD=_-DRAATxnL*tt6`0F^$yV(>naX!J7)cQl2n{tz10VA}W<}`v zSuSpny0Ss)ikdtZlr3p3qv{ZULWd610W_}LGigW&?c63dru|>tCN{3y#9Z~FdhFmc z>7wK+S_*ADHL?Wjc{)_O=6nT;RL z8a$B40YcV4@iSHC0Hh?Z-$lB1ml`!mOQvcHd(iH=kc|KNdpng4*&iR^ux@Ot5p|^q z-kwOirx5>pclk==MV=Zgrae5MxzAegkxB!_0E=!qe?c|cKH~i6AOG0bzV#;;zk}&> zu5pY0>}GF{`o|C4>1r$EVhr<-edL|L_15C$9#U`M7F`f+_pvaK-nGflnl0%eh znW%>Znhq)`T^&au)$?K0U*?*jIKnYS0-=N0G-lkBWhb=nsSt*@I1GC8nN;72qqdzI zCNoeJV{qVA`l(>oG9D{L8_GKAKS(X1`^cs=C2Mkk%dJ9CG128#z?X?sAi8)Af4=2!AFyZ^Qsd`Qm=uu z>6eTa((}3xf-_?hCGy8GiH%`==kXMT%Vobr{a4N=x4tXKX-knqBn)v4<+!*|1-y= zWWtV(G^~1_zIly;WqMc`rs8isHUz1NqC(zOv{tihuVG)1qF&=NhGUs+Wl$HII49F! zG4^{mUA3T(c{~M_{BpfF=W`3Bo{njoDId0VFMTcGW^GeSVP+IV|xRQVNdNtgzTA1xWf@miJJksW*z#V z7}+c~_&qg2Qe6js!5)D>reJr562v!f*Y=>iG>RW$e9S{QU^h6v;ggr-A8JHTG2_9c zgt;zMQ{$ydtVkN?io{ZHkmWgiUNMZD#^zlQ{uSCsTfOlkgwVyoFgBisEQBV!Gi(p} z=LDcI#|F@+kv;ybrYOV5&uEq~x zcFaIg%eB`fAxB}tYjO|=`X3ku`r@eProv`hx$XJkcD;2^*z`<`tu_&2mL9ukMaUxh zH@}j|>CyJHYARqpHqxFLksMMeW5YKy_mCvlMt;;fR!z_9S(3ih&SBQ&ewn1d9$vJ) zm!zM3H!DwuMm*bi{U`Zf2&ZUIu*JZ(RO8?^dOVu}dB3ky*f{}v?4{pt-a2EO2i`$$ z#DX#q{(vqLt&Vtx5Si#1$vpV@(1qzNvNfv*Le>Iw%rSy}04^JN444L9@fs?^!grUL z6*VfK&V>L-`iixn@AV^rJ=4v;f{ca#kmBVQWOa%adxIBzr$&1eDm%)pcr-%D8G4vA8iVc+ltXZ>+kv zMQy=c6i`R50S-FhC@{$ycjVq3VN4jJT>{7;1T^L=tE(Sm(+}aeF)EZRuxl3jf?{I8 zrBAWa`W=oL4IS2F2+ZqIxe#S7l~g6F8K}Wm-QwKC!O5Wh|U2g$BKnA4-yK|%75;6*7Q}Os(`3mGz*)KGMUf&;q4-xUaSoGGC$l>=e^Mhff{ZA^%@Z9$l4P_p#V6H zEP-}Z4V>21^wU~^+PE;+Il6%b6O-2)ZAX&rO7(Gs%uNMD%|FR9Q~7PtlgS8kHli^w znMr<BC zBS#RFI?4H*;1cjhqX)6k+E~uoqqVkFJj#H3CKzr>rRt+&@tg;$pm)>S6WpTwMy=k7 z3gqZ<@)SbU8A$exwQuux7e{IG^e#--q8@bfiBU~waZMXM!AI>4xjbzBQ@Ytsy#o;_ zR(`XZR{G{*(gdtCG<`zc;yhWa?F0he>izjkqycgNpcJz5MdQ!4+6IEVq9u6Nu7izo> zMQZ+g(8Ud0RW0`g$iCU)AKBrxEW@8I+4f!xEAx$$+xr zPK)*zadlU+)m&2aU0QMB)O7cH-sezd{{Qe7b zm^tGU7Z>o?i$oWrtmI0OSmIFr39s!$sO>XW=EPuaUnmkQwc%+4d{wei+eH)H1l_RK z3mjICQA^J$v0hl*2eB@ivIpTo!(;~lAqfQ$g~=WuCk0Jj`yl_GFVme)P*aed^!Cy^ z7?*#X$Ed$Rm-OZt3p@sCwa+8l{wlu6qli$Dcu(+JP$w>5DFftSUuR{2WAhJx5&na{ z?i4Xff{4Oi0aS1vP4GTAAUrZzkckd*%wLA*a+0Soo|tOFlrZ#EE26c&$FkGz)dMfK z?-^0#$CfL$$pej07xbEusK~*d%$!!kgVh>;pt@8O3*Kcg8=$<%O-I*7ERK3W+Ld!e z_#z2Y_XuMJV?q*Ly|0ZX>V22R#Ae2GA(|LD?#Qo^AmpR%(C$%_5yBU7wA}K7ktVFB zA<-ps;A8wl&S-p{N&A7l#YIPT$P&OMcwk&+ROgHS7Nc6OB!yA2s-9s~Amab1Q8_{c zJB`7u*U9^dL)9c2GafB84yL~&83H*{SfoYAgmlu6in{WyqP`R}O-ETg5UBf1AfthW z7;roTJ2a(4ZFE+_M?44+w#Jlhd`{^VJx}Ro=u&z`)myfcBdXA$X_Y9^Dq+PIH7n6- zVBHppgp=f3)^1GE0$*UgFF=3E>4%(U`iz3d1?wbQ)u-r3Aqu*5Yv0;!EHx>|Mm1{Y z!-TJ%?QYcEHOmJRnyiI!*}#i5hk*g9NZY5r`hbhHC23lgSOBXg+hs^BAXT%-oL;g} zifh4@j$OB6D2SAjC$(`=%lku>P4iOLG-?&3OSa(G-93+52OWVzd*K0bwLenUE!;Xe z7KQaQ^@bcr>rtIu8t~zzv#W)f>|p-XUq8~X&; z#O1`jape@>Zc|Rtui>ATkBW-ADLqq}LC*|X$(`^9uEuVu3&EFKQVe5mNp7pC$FdW3 z&0K`4!rW!>V$&Bf3`Z_41CO>rfU+Df7Z7(Yjt zZ{6Wh3P}g(PU=-NN>a6+9$vbr4-~myhljRjQXfepa&Zv=%5jwG#n z+EFb$-MFI{rY>*W?k6^cL7cN-VZxLz+qDmAj2|S|UFUoaeni;ZQYn*K4KvVL8PEOW zARhzbcCtUe$DoBA%$RWUM~6Ach=A;^df|lCUHSCCkwIYL@4npUOl4wb2Q?A`Gc}}{ zt?6Z-w88B_3!O%4*){7kl(CVkbeXO$pM;2cpXX|Qp3l>N74tEK?PmYbNDYkJ-;5fe zZW3!?p@F@b-#%NU{vCe-&Y9@Q0Z2wr1V-aNbzd>VbxEMMr%&pIy&rp7s>hWCNX$3B zR_A;j^_^GPKAD{xx@6UNTY&q`B)-`PmI zi5H9wx--5(yQ^y&DYZn~v-52+r#KnfsQ{pUE3Of2Jy9wHPw}(H5j+ zF4|-!eVQ)2JfZlPS)fo*;UGe4y!CZpiFS{5@Nkt7gUKztN5M{s;i~|3Q}mhAgBZOHuwytrbdoSypvUsZRoD7edp-M zn@wlv%}8PwlRJ7HFNJ|X)LuLWC5>@C#76J?9^6!H2zMl<1S;3jW-^CpUJuH$ymay> zJ!|Y-Idl!QfCf=w9}KEvySTq2udIA3kZ7xoc0i5aH`+ZpkO9Qm7>&EXK8tLi&DCz% z+jt!r+TyVOoUomCdscI^^Tl=NS!XuMkgP{u82%DxYEe(D9 zItw^He@~Zf;jSN~)~Iml)(?b6N@o{KASZhWJvsm$j><;b#x_vp^iU^1X*R~LS@ZcO zyirXRysGr|+U~ZU;S#nLz~VcenN(}{Pne_|WL{u{vd*%UL~Bl9_`QWqpqgC7Si;&( z0-g4htgTO8QaieruC z@{9!)bB*B~wc97@-`{6)p-mp5+!DeX9U_wes7mQlqTw4-+jU-~Zr9(PcWFgh1d89oX(zgD1?g zO}2Q8re3I5G8daZ=swfeW2LnWeW(^v=bu@5T<#lTR6Naz zWe^`3#GRw>-q2`6l^RhsU96XMiB4xmNoH4vpm$<0c#$yM+sqPkfSC|$fu05qn9lkk zOY8_%GDMgMnPxdyT#GT~+cQ$o2LB;BU^>1Yp3}yoXr4>9wVP&}y?DgseaO*Z7-DOG z@Y-H=N(BpTfK376PLOM$Z|DPH+kTO{xf-3ljW5h-psi=jY7QBDoy$Z;;hAD=>)IL8pi*Z5nu+n#KrO z)S-DfsUxY_cDsWp^}6iL3DUU^q_ZIjxT4wnm9i^?D7|)J_EuxXKs zS9e6OLa}yX1m^?l4+F~F(7{DMxovAZo~~EtekgIQy3Wc)5*yA4xHO!tsT?iBpmnV* ztr>B21}X=f6=26&v8OP@z|O5PAgRG!dcZBHTS&*;d0}JeJajZ0P60eCK=qSotEE8y zy5C$A(RcnH$yiDLr05O^!sBx7;CwK=5{QaNrK%jYXx(%Bh$*TiM^YC(Nf%_P_r4yj%K;wKaJ{mBK^d^70+*xQ z{N$ya9{(+Y8f=5NUuQBY?G8!$$aJLzLBf=rut(rER`v+`xQ>)Hst)=wtmRu1NGLB_ zEbU7>0YXmb%`ksL5e0tb9Szh!5%TixRKcnskQXbdp8mBh3Wf-*W|N;qzys?wXlx+} zpN{v^w6t7l+PMJv#u^IKt+s1)-1KL?h*XzQq%h=)2sduC!~JuO{av6fm4%t@Ya%*% z$2dM3%;&p=78n13*c?hGLa<1n0f8mI;YiVb-;Q={m(%pQCWZi23{-)fE?HASJs zOX-Nck-WoiLXgzTTZouZu`bdX+ix?&GI3IBBp{Tw^;G@b-im-5$cXiWK}mResGdev zyi{Su;t}a_T_v6DkN>p$KHY2NcjNO_f0InGw?Z0{SHDRzEFpnSZfC^#H-2xaU(2@# zwa|I@kzf4+X{{nHU;gQ)|pxeRl&>j?2{I@Vj}bmD?sQ-t1v=bu4Us%8c3z(F<%=)CdZHm>g_(5 z{`FBH39tavOtE+*Ez-%ONM`)^mOK5&!Y&9SqWDISUM009|Bb}${m6zmTxzbH2lEI1 z`yY$O1ZMU8q6AlSg%Y2SC17AwGEo$L8D!)ht|pU{4#_x7*bE$K?FmRjl`+V@yV+OeE&z*hW*JkU{v#Cb_xM9P)&OYsMP zQ1w!>CuK7x<*KLHokYn9FoOmRQ3i)mK#2u7Ai!ZX6X($hN+NEVu&P7nvWCB9{c4Mvd5b}BC;26st_k15z{+&MB~vm%-RQ=+{yp_=??J|M-tPjLf^q z6cqxn@FK)&mx#q-OcD3~O~k$NqNNx>NWfTAu~IUiFK1b+@=~1bTc`?Jr!gTZWP#cM zboYZU0O=2NLkJ|yhm8t=R&HX7NWGJ3jQW88HBuY^I-aIo+%K+W`R+;PEoOCWRbq77gwaU)r55=!e)-y(I?7HA)!Sun5sVUC=jEn^8b}(rftuL^Cc{nXhyJ zXgc6=$h1u0v+e}NYspEU!1ywo8e6zBXRA^MQ?Xd#3Rz>Yv zMbAz)A={-9VsG>u=WW#{ctz1GAnI9)3s;J3&3pt4KZZA<%E;s>8* z;0HJ60)b~)+`FSKPOSrB$dX>9q!LoDk$vw}DeIOA`?P?dFS14rEBW)sti|dOKv6*)9XL>3|?22Z)_=**jnrFNCFIG^ho~Seb zqH$UvW=>;}yA7AjQRZH@eMZ1H6HrhYy4ejB|_?9~k!pJDxVM z(P{4&R{qDI#0jr8;&+-nE zOY9(B89sP0@9bmSG3fTj5BECC{b!ga;E5!BblzJpqs7#8Y{AZZ^0KPc;*iV*p96_L z#G%D_89e|1@ZYvE`#qJK3)_%EI02$8@Wae4BUywnck%3|Q$ZCWW#Tv!6(j{CgUBcGVB@+`b^<%g@ zA))PPX5e(VCM*{bf>yks@)|%@ZU9wz4WcSHh^o8>Qk5G>RbFae>@jA42(k`>A7%3~ z?VRVibwpo8WidB>z@J%X^bBOz$tpQGEx_tK>yVzInr_sy$Sn1&Mqunz=hzq2${4fhy|SVO zBOfAV&TUl|bu0-%#1-!VIt|vV6r3XLWqQPNn^r#?9$gN7zO35LMagXe&88OUMKFn3 zEtSlQRB&ujjGXEsQY|*3x0pm*l`C0Ttd5FcR>E8SHDSU>j=)U}P(7xFSgE8ExMdCz z(vQ}JQ7m*xWU;Re!A4@p3=_LsLk6iGO^;eQJ?7+y$X15j2-|9ND>cayzmZ3Z7Soa-T%GbUb2(tKT3pi*;myFNV`^|xr zvWv>Qs5eVqqK&xDX>9uLA?}F_%_PgzWTp4X;4kypeOQe-xFXP+oP638q?EdZeEv4+ z@9=}sAqdn|EBQL>o3RzkjM*&yswz=qe@0{XNT@k_gzkrAu5zc&!d#lgvsdb4;Yw z7ExR>P{K9+tLXY-$*&`DFJyP)UA>ub(Kh7*%eAYFxy&-!8JxYK>FcanVp+P%xioFjnJSK=E+ny6nhRZ@SPUbs6v zKtT>Ht>plOtzxo~JDU1ozd|h90&)j9$4CU;mwWmMLlAoMw+1YouE1anEP}B#(~G<* zL2V35y>?FX7w-|Sbr=wD*MM6~B0dNRy?M-l(qm4TG8T6r*^t%1alP2_$;7@afpbo5|iI?h%xea#)|gX#}c zbMW;?sQK4X>PJjW?EFeIg(O)8fwPJIbv=m9A}k^|AScd^tvj(qL92a6uuP}U@Yq|6 zT-&>H@PAM7YsQUu`9d>=t&I}4CZA(Og~Vm>_u@;6rRg+Tfrf~~OoH4#_1VvU`|McZaU~f@I`Z}o-J3^JrFkPU>E9HqVV+l-~Y9ryfpkKs$_}KYE){& zeE7ftQUVT#jc>}c8M2}1nv2P|GvZBQk`yvk1JaoGBFy$S-!zkevl>a-fMJs(Nd&_t zhq1RTce{Zc?Q4_%)$4bFudZ`5bx!rwIYlKG9m<z9b(Q^SSS<+^hSea6seq>au~vIn%hs-?+^5cs z4kN4rI(fh-eA69BB>K&PPIye|?;TaAF_NyQ(|uSwTtRZ9%n&%s0s6V|fVxYY)>wxI z+G?P* zUo&x^ERAolfrpgbvtXBGZ3KU0vF5AwiE9`^C7M1heL^aqgwoyz5A4nEFlrKrT+AlH zxt2=vt2V~ga{*$A!V$&k3#O&ZHKuMXKqUzOzyarbFN`cBtS+!*R7xq~)bk7t><3|! z><7~}HTEiOjlLXh=5S^^)r~N!_IEVsp@&crj-^itn}=A{-*;ld?|tx%GWi&fOCC`h z=b`Ph1b3?E7+<@ArHNpFTMXK=rh2g{ZG)q#Fd>#lOg%m$xy{tDc(@wYys0)8`iTRx z6+yR`M#|+ydrn9{zbGG6X>BkZ4MbK*L}#@?ZzI{rS;Fy1?%a$-bl!-lLP1f%M;?(% zo3=2+2d5>$-ypqT2oVf zi}R0`<;z2s91I^$7Bixn@G7>r!|`CIAs&{!Eo@j(g}bw7=+<6FyL@>4%d=zh2~v1O zzvq7btX_Cp{l-AOKzjU`)^xfcIoLE2M&gixOz!W+s~M(iX-&cCM|;zbwof&4oqr_X zg%_M}=G$*3D^1o?Qkrcz>U=JnT>n35>bA4*!KQBeLZjJRSKtZI7QJa9>~yhUy8|l2 zUH%dQ8wi@a#NeHx6EqtY)lY z@D!^6!Z5iD+5H}?;A6Z`{nV34TSX>M%2t(5By!6D<2niKlR%MEuQe+txP;_&`52ee zb}9eB+94h7RL^IDkg514>h7Ug`d??=cIT&EES#OEU>vt`8S;b_mwske)!cvVW zgoK9vO5#H9c>ey>pG0IN6Vfhdh)jp38Ig^HN)r~({!J&c5v`GoL?RO^MJ6Ov;=Es4;+4Of$&=LhBI3iMVy4j?M|DXEmg{El+X z-C=!pLRTxin&c<&yFU2|Sdax4?3c1IFnF{;bU%kgghvMuusk%}(Dn^m59x?Zv(UhY zqOC8h3yl?$_E8v}7)niW*keTP+K=&12Q({0u*N84`DS64aL^RC?hpTK7#gh`afp!} zZ8}2(@oP&UgUcP7IOFrHs9EAK4NDb&vxlWN8_#)I$bz+pC6OnnonBdi)|1I@T1D~4 z?-l(It{cP;`bmBD3VB7#3HlJJ=yvrQlTT9VRZw@nV%&3MrV zSL;sq-wiG*nmXFww67sD)6$x4Z%z*{G2T=9?PiWF9{>=WmTrc;$ckBZqIB58bz^2q zp7l4EDYjX{+vElcVaB#>C?=-sdsoP``{`VvKhJ+?h)wa30uEeQ{5lWv+7 z-v=0CXgI9Jz@(Nmskbb<}83VCTz_@VG1> z7|M3md4agF1>V1s(#o_IJY(Sf9l#K7#~u^PSk2j;9pGYD6v>$sc?Io9iY4{TZT%mXnXd9CT6>&L&Uw zB7Y_;=ambqrDQB@9$|{b4>gYzZ6;hu8Juim>+WnPHz*y!%0l!=33dEG+uSFH!j4&d zj{NK_hTfJpX=?bjGqB;I``8sI3kh@{(KKlqn$cK7No>K`d$Km@!V-~hZNJBV9Knu3qtt^P=JR;ay8OcbQ! zPC_d*BSN#63Pp^t_}gfNPExsC7uZC=G6tehxZs((mV|9uOi*wMup~u`2xy%4eSeVM zFb%e6%5FdtIVJQO^CV9yleNT-OdXD8CJ!K@VRpNdAQq<{;YqK-&Ywto!PR17{K!S^ zU;&h+f9W>v%H1!TRe2g0Y%XszGHex33$o&vEz#lk@J^(|JMA@XfO!jr6&V`*6CE;o z+7QVlI^^aRMru4sJ&Op|D$|*#^lJe}lVT2W2hjy0;q_&?8NO8`(v@b#^{Xv08Pg)D z0X(^aP@fecM?h=?tZUwv3zhi?CbkNBN7{BZbRU=OmHN(m*}7*ky8tKUDIB^F@Ao^! z#Hkq!Y`CvV7{LuwQFfe%ZSWR(N+{5ymc2n)ee{3vQ zTdCScBkDrzMb|yNhQJo~*dXF*FM(2gqAx=xBoVi*kmQ@VMarQ%xJe3Y$GJlE@Ut$d z6jGq1gqH=tM)w?2!NEHI8{Hwrn(E(38EabQToPRTKj=2IT|w|M{Q?Zz?}M3n1P=n3 zqkme<%j}OWHbTDABv`MWU>${hFRb+|`r(aXcpsZZSPZgQ2rhWy1p+$cP0yrb_Kh zAj*(%wAy3F+1Sf8J z0@Vgksw{&;>%Mv~O@MxNVAC7*$s6xg&3m}`eqHSI3uEsFBP0jKx9QLAgk&%?cYHs% zQSQJ;i)C8E_;(=L_<<#UN5=AdnD`F32tQT;H`#j-6>&sTv_e8Akq$cd-mFgRPG{;M&E-F2VS2^ZYj;*TlOsw*>syv;l4K_QfK#9-R@EQd?2+*rJ$`388K zV(6QPh$j2a_Z)l^+z<|RC?`CH?tQoIEvw* z%(H*2yUQx;uFyMnVR&;+vsW5ee95sSR%NPb0t&cUvVy~G*c-$vW}(A7YaIN}(fwQPiav>&kpW10>sq zbybrQb+Xx>#Bc^#*&OZS2B)kHSwJZ3-`DhQtkl4|zAn@41d0WvyNcPjnhiDdT27#w zeIOr3Xgo?&!&=qHnzD}qiy}DUJ>OxZgi-jQTU41Sb`Q;y2}gU`N2n8b21Qb`v7_t+ zK=0C5e*)B0!z4q}0xMVhlt*bHd!2cbw6)m!UVD*6B1Wn=Ce#d_&es)fCE}WJ-C7mJ zpbhwf*GZlSSk3`#3IT?X7W5If3t`;?s_HtbYO4Gdk~DU(VzYY@S#G_%O^de+*&f+h z+PxzepSi-@d=ys|nWnftw3$<)g$)+T6Bmj|p%)h-nT;_$wO;IrmKU&*-j8Z<*YqpqiI%WqAC1}x8P$rs8 z_ISY07ZXw?qe>gRut0|7=TncZ%dbes(7T_n>WJHhSxxN+DUxkSA_Q)_%)^ph$u@i? zCCc;T_Ka-9*HIE}!`tn(C0@Ie!c)AKvLk>h$u`vBZN5s|kP@>E^&|}gvId~h1StKI z8R9Fc`k#MyHar5EPV;YLb+*yr@tUtgsrieaH4k+e|5F?yN{OhaPxOVpVc$~B^mD;C zu+?^H>=SEesqvM3jfeWnyP^AW(;1azyj2{xNz*nG7BI-sZKTWfBkg>&uBo6=VWQiQ)s@jix&luHY(BN@;25MWZ;^=zhpkeY*ps@7+81E+78#%4gt- zWDFiJo+51l+LFbftf!Vy{;g7cyl0HvHa}YDyhj=-z$pEQ{vx#G7Cpg=2dCS$4i+o%?oRc_@a6rdkj_Kh_x-pS47DC> zq5ScCw8d%H{65m^O<8NL-WL5n+)~&Hy=nEP_4`n(w@tq!0NnYw#Cj z?f$qsFW?{a3)QlXB+6$hnZdU3qS>33w3>-B19RMD#vE19wH3M%NMQ7YerI=QCt1T~ zr|I{~vjD6+!pxLyj5eO=^hlgd8lFyXR=+Eq-rRVY4RibRd1g`s)o6ry$`RY}e$8mH}qaWzaym~XgKg{tw zp@?3F@Kqx<(d)~`pt(qTUc?cvE1%_CV*>s*w9cMLInMRqLu%CCx49E$JzQmem%70y zYp7Tpv66(2f~piyqlKtc0~ITQX37#w65fIRq!Q7|Q52&~P4Cqcw!|}ANs!n_12Lb9 zm-Tgw(}k$w61uedK+XJ>)>`WJMzs2pjh3$MTPNddb*@l;Td@QUnKv1J`c_!=h}>`& zhF3Fdk-{LS7P1*W=mUBMK3G>(Zuq2+s&b**1zblWBwe3He>}~#u=+^|4k6YO;YHrg z$K5AwP1?~qXtMQufwyDmDc9%BWo?g=%yKZT5;siz;0Q`t6XBXhpz@L;24#?DL}aZo zNFE&#iLa7Jlrd$f480xdGO{StWKl24B7vxqMY@|#BBwZ?m6s05D4FzgHba8sG@_pO z%OW>hYVTfXCSh~~!f2<2(TiAod9ei2OJFw(RMq3(jad@OmspT55}E;sfu?d{wqR%T9R-p`69p2>8c86%h|4IDUd&|_NH5_s3MBmH zCXj9rm=Q>*FFfph^#p!>CZH=7FBdzpSl zd$3Pqw-RYU?EEtW1HBgxaGiLT-}mz(|a7?)Fid6Y|w_H7l9 zaB0zzEK_i4fuzVlE-gn{E08Adu+)SV^=$~YJs-_-*$4BuM+RjZNvGdwg3COFD?tqWVvAMOF-p4;=4CBi%2)GYS=bg|Hvb7il;i!7*>ITGeWI zz8JZ;Hw&uIz?0`OCJJ)ds;Bqg+iR-0g)9{x#8Ha=P9H{0%qz79H^cD;+hxW=i}f1R zFk?oNZm?ixidKA$8D|jj25!p<_3;L;j*OxixMMy8tj6V-k>9=EKF5~Q7rsG)&&u$b zH8Y|Gm>2iwa|W(C4;ohqgVy+$8UKFyi`rq%#$(urHu0H%3!G2_W>i%(%)NnQ;Lro! zfM-rCGBnZ-i!=o6@>vQ51m1R7Sba_2!OMvKuP7>ky0=8Xb9X#0g&n4YgdNti9la%c ziT=!mB}0Y%y+!&otI1@XxRC?_YG!!qK$FHL_UYq%kgsh#Kx(#JH)H2)fWq13jA@dP zsuoBtWpcqgJ+PMeEmR5vs43DqNlr&7VlO0&F!Orm z;$?J6E0nh8@-3iLIhJoVWQzm)Hg0M?cOwb*aEm7933lX5)0f_L3l7?MB@#gkj3=Au zw1FB&0{+sspeqel><6f74oVEhHEi`X?BuM->dz^8Wl5QwtfNc`w1Y;=)gU za=Fnx6WwjXMhc&-7do{ArzPN|iT3RgLJ8eH^_QejAuN$g-}Hd~oHjk6;}*wYz%dY6 zeB#JR+{l2$;K}2EzmoPq938d;(h)V3|9Dk?xNUnN9HT1X9C2p8i0t#y*QsfD_Auh# z=KI9>%d=C`1t>hJ-(^+lrhzs;Fgr7G^8-}&s(cp3Tuhvq^vw^mwapKal;r+a3oXCnZQYrUfy$?-T~F@sOiA{Qi$qJFOzW5wPqik=2khia`6MBO4%rx zw)rWIKYBNVhU9FmJ$Gs}}nPo;yn#YY7z_gY`^I2aoZUU zs4t4r)C$ZP;S!fTZ?*GcTkqNjSqpl%A5s;b`$R-MtPB~YtwNVUKmMDC;ORCg z4EfSn4!ST}&TSogR&05~(i_y&6Y&3e!4{=D=MWQ@`s~W9Ojt0h#0+GLVTM_+lnXQ3 zHOx@Zi%nsP2Q!9jR9@oB43ea6emcjAnY;W@POojIZUTc7GYKb{e7G$R7PnnzHSEMl zL6liZbMdtDIs87cU_&Ho26qgRWV?%R7vGEZ>oU=FvH;hdDMMzhdzzNg#cjy+o!5>_ zFTiZ|qZBBAbLHlISweb@Lz2}Sq5-C;5ul<|D0g{TAkEXT#~o%#gN`mMDsU%OU%44q zDzBLerq`-LmG_$pmoOEN;L`)Q@xn#j7@sc+!7&xXu}%oX(Cqmu_gvlKB-5FVbRbo6 zluL6(o3c-V2jrD~dy?nL>M0A)mxVPC+=a5RHiV01VXgnTxt~B|k>mTMe#!OvxPEbZ zpU^KZ@5l6u!~2+i@nFjg*8=4c{jxy$uzp#{Jgi?9G9S_}u(%VaWW1C$eU|Iu5`DPA z4e@0(bu)VUz;TcXTyStKbNLd#yv(~V_RC9LzQ`}1;c};6UgQ$hPEdTB%iJ$HVm1W7 ze2UASU!LdkM!)7Ec%j9m9h3qs-AbL80cPS&qU4DV$0_jC?J~Wl z-uEX)u|@`tb5Fg`am_~IM}Ee-R*tT&U4pKR>PAn6Y?fc)x9-ddJBAUUjBTPh*s>M?m9_ zkoD$UOk$WfcK4LplFHU9p5mnJ<3DD-z!DnC&C7atr2BI!Q^p-df2rArwATh)aaDq{ zb}@op>q_qGzoET;q(NfOtmWq|y0BMkPdbK5&`Z%$-OHUEA^KQ{J7m&veg$f5hGX(m>K)XX+&e{7jI5Aob=<3r}mzPW)hvOXJUXD?<`dxE9o zm#NOU`ZmGFbUu2D(~|VNJlMPU|cPVndoWZ@N*_?Aqqr&<9PQmFUXnw2VC~ zi#E(*ElseNI4fHl^$|<>E*Z+9EmJpOs=a|askQs*Xtk)%&;zD(a>mBDgg>fN>l7h&O4tTpx73$!yQHHj458Y>j4MN+T#@ zU)JgVTE-~_*Ez=TUs1};c0a8I^McgP4e=8Z446@={o=du%*C)nKeLHn8gs?N(V(0k zwmg~}elxdtm*&!IVTWB^5PM{Xd^IA?1!dOW*07kwq^4Ecunv8bFeNijdSnt7N4^Y3 zz1IDbMkQ3JnAN8=n1mc=n;4*ASc_{9bg>$!B!UgJ8l#FB9Encjc&5VO$ZR2ukzF1$ z$W{E-M#cl^q#f26;cPj=srm@b2TKf5nC3qp=O1XC+Y|SZ50Prm4?C`ZNk>KT;*&7o zcK3G@_dHLl_QjLKE_&RhCKf1f;Q3*3p6jNxH82oA&mSg?mdv5KXsHg1f6z4!OBwe* z;yZ<#m3A zi5(B&(-=3Y01q`K9j^?5;La(-9!4CJ;9LH!K3X8)Nk*P7-5yd!upPBTNNyMuDt>ZROeHJE?>vKstZQ&gI)=5V@y z8u$(YMFe6>!P>AbcVeP@-nbZ?&~@*c`5IZimzTEgmarCIT!Y!y*}RXU`^!nDCA3Yw4BO@Y-&SEt zUA>x@gKj=7rInG&{nkjyMK#5YPR!RdOOt|Y*;GIDQ@?>e-mRA6%-5B(D4VR3$s{5R zyrVghCD(3}XjYx4d?m47tSa+I`$2VE!puy*WC0OoOYOxHAgP>Ot3`{|G4*{3pA-yb z30;&ou{Okp;W%2F=;2Dj&5@fy1NXW0QTKp7IjkitX?xn70m=D_4-RBs;$iIwt`p{g zAR)2vov^6gmvaGcEPPir69&?>{p=1$8f1OPy!5TG1dEV`&@sQ~hIjGd5>D42uYgr#1-(Rt=r5)5?e3 z4~CMrUIqPL5Fbi~mw#+@UNNM8X?I1Uc%gcQpF3(6PLSs;7@>@1GfwuDWdYbQzyVAC zmxxl_ujGBH@QRdLalZfLEZ+Gs+;2%LgDusHOQ6FYl&+Q>G`V4)d6!HEvS9A~)=qPE z4KpEV^gdlCGwqex%?kqAa&*Agd}hD_#Srcd*^0x@M2@Ujf;L015CR5Y4i;Wtv8*#g z@;d~gf}`Q^)Q~TnQ{{!B+;-jJpdR+O-fC8Z;nP}k`sa3zVA|m98sj&(f+Keas+i3N ze?j@~uMJG?WSZJXI*eN)w47EvxJOjD*``*&(h8IuyQa27wW#tg#db)Fkq%b@2eUK1 zDZsZwa&Quhbr;9-0%S8jVTnl@=KLtFp-DfPmQ3_ZmS5)3q*(^47Sma01;+5(GPMLN zdnA?6S^-w9B;{^>wnQnZI&|W*FkZ>X~9i?TmYT7T4!9ZzQHtu5g%V|j+XB@sn zx#DC)ErmsmLEb=%8Bk|1DuKnkemctj*y!DW@ygF`p^Ad*wWt(!Yfp?q7x3QO6~;Hd zSCuid0FcJ1UB=fk9I(Mf)mr_msr<{rR3;Jmj|m$EylzbNIwv-h=M~m(Mp{Mz|gwXrh0R` z^oGT?Fl%T#O#(`BQ1#}eC0gic*)tKzjrgYoP77X0xMqt!EslAXFxWQf3ggO%S_vp$`U`!x0C@uX6ct~2V1uELS0atxQ)%d32-Be znU1R(IqzccW6iuZ-=W!Cq!sS&$t|Ozg2piI7h?b$cEIARSua>rXxKJY#lIzxZkn*E zNd-e#TCD&}WRs6YE=A|l-pDG?&rrp+sIIN<9RDb6U0P3&;w`{O<6 zt^470Pb{16htfS(>+WX#t#0|nDqlXNPbk*Nij1t>DK}g&$}`2|tzw@FNC2_TdNe((r>e>iDsv4?j#CCH$BQTeOma z_xJ9AY-BD#4o4F3qC%2w;?=-8{~rNEb`b9oz0R8AZP z2N->H8XKy0jUgr7buCu=nGeV}vH1nk%&(xkwr6^`f+X89TIH9B?6y_7ewwtN%VTbU zp=NkWs(w#WRO^$PZ$8Dbs0D9$m#u{x7l$6vpF{-0J?>DKCgIWCTGSUYODJ%971FVY zNDB{zf$TIrm@m!_3BTiB7l01ObkO%LzoHXraj~}i8ntY9jwSCb3{i`({HWFf@5+6} zOYfC%G2K+Fhb`-B11+;!K_qSwX67r1s6_XvZ~3D7HLGCGA#_+X^Ca zl&-D;fhG7HOhHKmfLRKi!*%ro&y9F6gsh~CC~S==^m<# zxwtS4&v}qdHjE8GPC^*cLJgp(fHoD}>=cj^JX2iW+VDj4el~cfZ7f%WC$#7gm1=Jg z-2rdfA>}cyP|h=Oytvh>Y`!R{+V*1Ne_y5W2i{&T7{kmF3t-(}kk_suV zktJxM2@wN(JO&b}^rHiAAeFIvI#Yb)tEXsw-X#tK!c%sD4w%2FORO^~vRznRE<}0! zxs^fy1|_@Eghn8EAbO)wR)~S7WxFFF{Gzy^0Ln*3GPbB|H;JCoLsUxxJr5m#?8QAQ z)~ECW6gB@vL#DidrwRbCPQ|NajJ(y7(>uZ8~S75@qL ze@=M+EFk^VHGve^pXv-Cy`T@{?^HMp?fYNs{e}F*nh@}WXiR-Orqhu2S zyMcdQ{%z#nCX}@+;~gG4t2rUNBmkfq48#+cQBxO(T>&N(52ASV&P(Y78;7-D5EBEMU;vnOaeo^=W{s$KgGq4{xl#I>yR+l+9Z`F$UEyqQ zNZ{L62Kk{)T}+z|>DTU*%d)l|#)12{resv>N&@aX?3k%Ri*{|I)oS~7X@?<(x*F(X zxU0PJb`KqYurATH8^$aT4`r7BUNNh@?0Tblfh@cT!qOUrIg~66r)zn1l4`(m56N^O zT3ggGzq&1NJx$1PPiU9sGAbQ0a!E=w4=r-Z6l()oj9fYcsGutRSQToeK%?$ikJP-Pn)KEP^s=Jl!KB526NVN;7uG4A@CFD{)v^*%3)bv~J zx*T{1`mWvqD395_ElClRXE({mG;udLqRMm-K)9yXU6j$^*+a(Mv> zT+`FSS$yHgWIPF?E>erkt(rZ<7H$aLq)@KU{lC|Z%?es5$7EHEE z0+-J%M?iU)fh{Y_{4Jkbc7fUI-URR#TApdZ zz75SHPBK_H!MK^^oyCK%<9cT_^2sYl8Yg*dp>y-bmON674jnI75E)UetlIQm#1AV? zA#CYwbzb9tfzno63)_mK(qz)-v~Hv266;bPHfx3%B@gJsRLJ*J9ryXX`Z~wDF>5Iy zOtFklFShazk1w?@g;}NKx42GA0HALcU(;*g4y9Y{;Xq-=>SkTY-qEWM{wwkrIYrO0 zu^lY(io<5Fl3+}}=Yj=FGf#938{%UoFO&Vbqf1K9BTOp?wt*@x- z>Kwqwr~4|lg3K5Hz$CEdG8tZ^0cw4YRixfxi)B0-WZ;XuL~P>@?u4d06pY34pURf> z1_g1e5&X-y+mW1ts(1&~STxrzQNr>VYGVj&XRbK?TWs3u{+=n*awl(zC1yPUFFJ0C z7Pp3mdY)@96IIQ#z}2M4J*U(eJ4Ju!luR9M(Vp#XMIGg)S&Y5Dc25Z{$uW`u(ja#M zqn={4^6Y{ZTRB9?-eW}#K>Y9uf^a&Elm*{3yKaI zF)aSE>OBYxG@ms1CTMO2;$9LVZuo+&BaxuB1rk^|#H{S_NIt91xqxYRza}GIFSF1) zYiy5|JoYEcOG}I(QX9okqTcs8`kP{0$f?8FW41CJw-z}`irNJ!{0)G@Dp5WS4-0MG zryb98(6S&5(dZ#y|Ku5E>)5qS4C`8-ThK!=cKWHf;)G%%C1SqvYo z^DH8Ip%Acc2?#k}&<||R*afOByYPRi3q7S(pi6Z8|0wSnFI}>ybjt>6@~1d^Bd?2-dYJKazP2U|ay6U^G|S4+#>uB;)-|CdZ!jxnSeWu-e&B6k5^Drs zhHuVo2j)-iEv9A`tVQGHE5d{CEAH7}Z4nbPI?^&EKrjV3FBm1AiJWQ&C71e2HZuu_ z&eXXXGagG4{pqVC_D-rtH6OQ<(_S+GG-@=N*fic(>h?QD7elU1(lM$x;>mRZS6>9! zTde1H%St}(d?f5^dktW(F$rZN;Yl3vzND>lRlt{nDY_L2D&R^HX z5FL&JJzmJDm#sHc0M1CAgEYjt(7q&6Oa;-KnmBt=s5LJ}H$%rx8vOoqgeYhxcsnj2UL%4=M19ui*rR6K7*1i=f zA9FpJ#wNu-Z!7A2Z}T8emCgw=lOBsGF?1d zyel`j;jY;djmn z70Cw6WWfjXM^N0sZPNuix5Az!lpQ;{;cc5US_B9(QT3I+B9>--rC6{2a;vYH9JF5C?ki>;&5Hq5Y7n)iIP@8K zK(Vbjrr&h3RB`c?N*9VFpRAXj`;;8~yt2z( zTjRu2nL%Na7`M28g;1stO!byPs^Y0eB$Orj zw*@YTAXQQmGs?J~{l|W6E?VkBUrhr0z-O?}wq~NN=jsKfxgnWl%hl^At=v04A;bv9 znct`*hI-cA@03Z#v{_M-Lm`e);@Zq4p^3uHYK(;YljTxVXD>%=D46C3E;x9-gRhi* zJ%omt8{hrAys#xq;9cT{=^$G+$q&ZQGO1W1Ygx&6Cz-APXjfXMNSQ)sK z0uAQ7xpX(exS@XWR(Cuhs->m)a;@Cg=IzmrU`mNvsHa|Fi3Gub!8CzbkaM~wMshn{K38mkmW#;Vk3 zGa4(04A7-A^%*E#jYXz>*abpd6*^u~-t=TbP;s>}xjio;^=F%Z`)o%p)R- z!&J%)2o+w?TxG&b5;2RF*+x>Vc%by#PLi$dYtZ;>sCwLnUqpo0I;*tDe!@bqn5?o}Nj-7q_qiC`_sO+ifS1 za&3B6NXc;gP9Vy7apLn5X*U&*_vuBc^x|*V1)Uso=-(3hafwmFT+9kC7!`mht#zvaHzfniMnppwD5D@5RlgVUo0Lkmiy}kz`)X+(9#Tm1av`7 zmWp05^QPXQ>0#(W>WQoZIr!Fs9}O{Hhh0+r;DNSvkl=fxdDylE*4f6G7>6(7B&xWN zI4#*c`+9biq5}F{gry~Ixus9wZ&urs^n~v;W3$?*DhE5p8yJTp-fRF2{<&xzi7Bv1 z(nJ5#e-+A^LLi%lS*hnlHHBacQ<@Y4DnN3`rz@yo*_GM>n^H!Mw^)n=x&d}VB~Lx_ z0o`Dd(o(Q`DZ0UCN^26-Vp`myg2Y=c>`0m#38&^ za$b`MXtNiz+Rdg4Lj!gvudN%%Mwa#LvRcF<8@1GPChNMv=CyPKRv#?V@@X=3263gKbq5YL7|rBQ0t&3G zt={v2QouciS5$Lwh&mLhqH7{SEitQ-=bcd*N%&6dm*ja0fl+e375$P_Pth;(wkrC? zaKl#Zt5rZkbxe+fCBhy?ttBwU$@sFCc4APj5y~PbU);a;Km^aJBfN!x(?bRV|>%(mtcvGTq*?5cfv|Cq*uK+Pv<|U-fKx2ZYu6tje@)5tlR$c znFL|A^v4Tn+4&?30@!Mr^&tZ?LYF=drF+&tqMu zpU1k+JYRJw^&B$@8LyFE*dA1_Np3xSCv8@79H>WS@XDcdXq29=j?552*Q#6{mLXcH zzYqg4Oz)%m$3#do?4OIQN_YfQtNB2reZ>mEvNeJ+2%Yh0YCTSyhaRgpN~Gn0SLI0Z zsxT@G_*Z^heCAb8hqf<>PoW6BuOs3Gyh<9Al?QxKm=swg`C z3elq|qq1u~h*2}HP|{b;Xw?(BC+oo5efP()c&f98tmzNiF0iyE0F5s>WvoAFR%L{u z`XFmGO1VbN)UC6zWAEd31jn3LSmV;`*}83bcpLULD^$U@E+M$tv5cP`GM!n_<6SL|FrTwJG0A*q zu-*bUVI_Q@KukN)O5U5;#t+vF4LR5x3mQ@9b(BH7wj?)Jit=lj>FmaI$cR;z{FKrb zx+SAR{goP_Fg_Uo_`oO}a;^&vKY?F?J`m>~gC@fGY^Q`$hwXmpF}PU`)y5AhTl2a?B^9S4)@*z-@GDY|a@MrxlqE|;QKm3_3r!O4&A8i5>zu|R zo|O$Mc*o&0)BRnK_LdO72Kacto?a2hZ$)OgSp4kyQ`~PWnWsmry^#D9@6PS(h|hB? zyN`dux%>HNiaLjXa$K`?>tyeU%Nqy37XF#mm=n{oTw~>tbLP2CN6sN^${l7#REs5r z)wpLYV;96A@6=gy;Nf-gP6B-TcxU^{yfd=Rc#PbdEYsGs$(PAGjxD?i+nyXIyd+|s zma`x-g8SKXE%$|~ZCbvGnJGviu%soDh-W*xe~{v)uN}`=gyfYC4M^`XG_FF|U#Vn8X#@j!s4n zL(&wkjf2+02=Zz3`k;7P&>$&U;a$_|Bq94miZ-rJ+f5wTHf4)jmS;<{OrjR|!kR<0 zEf*+Ro)MkCN4u8qc$$iyZ8veuKql^U$+l{=l%2;si&hjCOLgz+;H|Ra)quGrtPMWR zL`?YQzP)Rk!s~B?Ny5+KTX0<;|3@8u!h%N9{C7xkl-uJe`trW;BVNwSfH%^x~R<{oLDlw%~2T=FrBm#RwiW$$Gq{!|8gv zp}E%4R`2Bz_W#W&IBjQg`unJ5e49x!CfPMr&Px%e`P=F_-&~1R@fGcil771%ONX+e znt}!?;g?*|CQ%Y^%W;=UM(csLjs@;9UkF4K!Ec74-nv(pd6^T_SR{U2#bRwXD`bu^ zA3{1=_hoB+OuW|gRG3Ru@`x}4E>NHBQ#@u$gPpcl$^qrypeB^dR%)xHBKE5z9QMhY2$l-3h+YDi zbDqx#y&S5S$ISWQVSEguOlZqvTPjn2dSIzJGj7z@xeb$Uzha9CWgG-i{4j{_haG)w zil~!4UWO8&#(eh|Q`3hNHTKOKd3lkQ}t)H)0NGt36@}obm>~oc&%9<^C1*Pu-(|6t z{^ir`2{R2&c?6_?#O!j3BEd%@n*C03Y$*;zaXxfKHN||Gt9JH^UOhr$xnr84MT}s_ zrBm)mHJMJiqicJ0B9i9joNvo5PoX>fU*WV@-{s5a$MyMj?(&_9OE{=lM7m(RY?k>* zJ@5hK z*2@rHlMvBk5yKmJX|4PU+LUd%&f#trcp?FYJgByc`n-z%>jGo1S+D!Pn&P7jnV!>P!$1ABjfik3(EsOSmkFGBk% zlR=<(hcG!Rd$Qw4x}WRFD=GSOQG6!KtkW@W`Be1LX|@Kbkb5Ii_hKvJ!6FNyC)*GX z6(N!AS}tr01fGx1>*N}vT8sB)n;bEG!4=?VuNg0@oay(($Ome0p4qS{fm&2DVNJx2 z>Q5OuK>S@R`M>`cD=|TReXOLo_=B=Q{7#C|tjl;BdoM5@yMtU}G=2)h%BsmO{in*O~$>finVn;3y=-*M?d zi;Y0Q@r{l9VdaWE*7wo8TeF3%_#N9`U#2%NQx#liHShh%=NQm%vJcj-2Awc<$x|Gm zT2Ax`f!E>J!#rEL0thac<(Ez|Lv6M22*|-eI`G|g&oB2@p{d#1LQgWo3XSQo)JPh|T zH8H}*B7=iw<&kC&ExX(?&Ibp?;L|!N-L?eBEfnOy$-z=XSxjXxzLA`eakBWZA;-oA zGID&R1}P>{-qB8LDRK|+%O7`tTD=4m6UEVgDXzm&ldqit?rgvmzEJ~hJ-EO74`xjG zNZ?JZ3^!BvS-?a!<8-sA%Vy()ERu>iXS4h79a#GMp558^F+E(pCFcy8?~P40i}Sp9 zA%?^l`Km8Yz=!EeKQ$h*k~%FeTge)fc)!`*Wyr9dxB&niMl8yS^@zCeFMBwzKM{+L zPY8XhKM@tiCuZEqMhW1nBayBbTOA;?gVDBjy{G$;fN zvCx~f!Y9i@Z_x@_&K*(5>_+pNm3PWK*G_k8y!-M-m&)O%k?Ey}MTkYU))rz>tykdE z*xp7Mow2C5z%hSZ%O?T;IL56sOAD&__@`GutzEPwJX|@bh2V=S>#n%u{G+VdOcL{a z?^e#S6EI@hKam;HJyR%nVqobHKx7pPK zSFhypm#Brtsa<(nUPsBHGlCe^jSr3I(!wY%UY^<@W#>tG-2bY*raXwY5Df7G^p`2gO!L zIVVfJbXe_;aT1ly8kAVpppWd!(Y%A1EzX^Z=f%ZttC@t9sv2U%TpQ!rG2fkLFES=| zag@p@_UAfu4K}MvQA#rCAg40z7z`sHKG;2>`2+~Q!~{8K($J`qpCkwAV?Ihrsi83X z_$*qcPG6mpvOwOk@&*DLO*e^9!Dq|%mzcfq+vXV{(aoW2GD(J&;)Jl5ak053lPQpx znVRBiN;Z^11&#$9#*+^F>P*V3rmTC+pwP6WRER7@AM>0)_JqdGjfOFKt_6l%xWN_E2HgM>P#|cBP_qh{K)5p~Jq77e3;ZB8 z31eXo{6Y8vJ{z9tpgTKIUX>(7RQ-GpmOJgBlqkHeq3}9Av%XW6+)Cc9q3h_DI@PQ? z6}z+(MBAlSMfaw~FmP;0TCmD(xLFJvZ35a9wURoE>STk4+wRxMg~s%ENa7(8f!#A# zi3IH4#^VIQy}@=!^(SzN*Mj8WF6Tk+>5XJ@%r+H(Z-Wv+2z=c*2kLKv9himMDIyzw zc|(+I3&3w>SA}POxzAYQVX+tOC4hb(N$QIU=|UjM3XqV z=7KLLml_1mK}?HO31=;9b99OQ^EozfDxX3P`))Jrqslc2EX0z4_kCGn(0o2Drgd<$!B|*+Di8pNfIjk zN`8Lk&-r{e&_skt4z}eh+{MpB{$Rl$1b*0Hp}_mEtHIq_*B@Y-Z~@-vD=sBq**Yo- zZg+t@X#o=8k9pTn0R&2keGJTnY`TX!hV`aT#ITNQ`-^11J|bwV+5Hj!kcvc-RxEC= z=`wJ$6%D*(taN4RZV;q6{Po{b9n%#2+~0gY_4m^Umvsqe+WWDOy!*F*@^cse=C>mo z+qqvo5MXBa?|l^Zv=VPOlZ(izml_swqR+eFwzsHw_5kcK%vh#0w4uvktm-lnzsJEw zhHVt@&pG)rc6BUv^^=#%u0Bz9^>o$MU-^YokN$@*zw7_~yS2LdTm4-n@SW<*uA=ej z;CU6PtMnty#g7_D5m(J%5@5lYQpf}YGAFQyb^7i&r)c@isgwlGDR+T)*-BiS(*{DC z`!ewn1|RoQTdA%gP069#(EP^J$01;=NAFZ>h0sw;9P zao2wiX!V;FzxtCO{qXXkzxn*1|ImZ3A@;G>|9Q~rhdQf;_X@Uh(|H}_izn-Zq--&^ zT6*8&(t9aN@9BQw4Nn(a`k~XG6LpKMf2<*fB%P%yyxeC#o#XlnuagE0^W^u z#=|CVcZ=UCPl-7YmTJ;DxOCp>(s?0CXFjP(XMHJ8TqWuxtW7#oyry(s5-OW?j{O!_ z`U4l#&pL#5(T76#qUzGw{TJd)OOno^PdYCp>3oYz=cNJZe49&WS1kGj^b%s+dwcE~ zQy|paKdXBCnF`@AeC^;vzy8s$zwga!;JfCfrb@Vbuk5T;iAp}Jv!>cto#iNyr2WX# zi47dNKG`SGCX(W_#I1MsgYP#QlNMeG;=?L*JnTe0~#xitmo`2g{!Ds}BY zR3N_AUjJZ!ui5k`9VQ{fbAmC5d<6i1Sqh0u)X!aiSKrm&Rh000SGjfo*THKuZV$TG zsI-aHQPbp1M`;tOb0>$TDQzXGN2Sfkc0j_0Yt!3SlC$b+ira^VR`bF^L&nIg*i?K~ zA=w8q0&4~bGqQ%N_0ZJ~4)H|c^>el~PPoo4f~#2?zg2OEcb|RlM?d|! zAN$C!uO$u#2=0ZoG(KB(wPtCYsk(aM9l!WjpI-Uc)30BHkv-gxxz}fCz}Q-Nq}EjG zzcKs6r}%lYKgK_wHHVVVwL9Q*mA^qASA|0<1FpGADVwkz2l!p_uoX>YC-#(hGdA!j z<8JGaBWw(PJd{4hQG&Zh&Ii=^z9+n1K9T1H)I>N1KaGTCkM_-tB?)GcG~enDxo*|7 z*rT%6cLkom>R$Ck4qWs2X(fnWLc}&rF|NI%^41m4`~@mWcZKQ3 z;#%v4r{DX@XMf>x{e@p2Ypzcqh2*oS{bVu-Cuo;G`XTCqSFmF8BgrW_EeIQw0TGG@ zAoc8`EDnlqTA!tW_^FEcQ%2>2)(S&Q(fIOR@|MpA;OYw04ON0yPPr+y$mlVc@+g}w zQ&u&d<7dXButrr7DI8<1F5wdQsaO3?)o=V=9kWvcgf}>4NSNcYTQ(f4ft@tSiF{Q4 zW6K|02H@3(W(+(60j7H-^UqHY;^^Mek zHQZ|n`T`IA*W}OxsfN5aLA|2@IyOD3rY8)P=_P+9tI{Lc0UKSS29POYnax6iJEOiXXs=l(l{g9L$I{!1PK4rB&v7r>x{T<>sZPTM$BjUk zgXk#}Za5+&iWC{q0sy{tq)<1RnbBTT5rO^uX(2JNV}H3e1LK9`fAtAC+?5zu`9dE9 zdjl&Y^bXnFH9Y_`BU-FuEJ!W&Zc) zT=?RO=^aC1h&>0*d{k>UT1@cw9&d``d>-{m_E=MP)-+Nke#Qs4Gpjb!Lvl2x<|WD) zM(n_2u>*7rV$@91cm1&FvXC8X_9mR&_y5(iqu8wCcnpejrpw-&yV2PU9n*l}4y<2j z1V=MUm{49eLK+GbE-;T;R^Quvqt&*+`UrT5>So{ZYfI+c538r+LE=ffy2iXmmL_om z^qcTdlXw|y30H4oDaW#GkC;(D?2JUqq&aVa@1laJK(tgVEj-iMe{-Wjf9$dGEwpwb zV_+VZCve!-S%q&^c?{TKO%KMQx3y%T)dWLJnj%a^>}v$}#ep)m`scmT7ZZ0OH?kk- zt)~MVI)qdfUNeLr&?pF`bVl0WA>L(~@(Nv|e1LmeR%P~LDwkH;0k5mxT_v+04c+MN*!W%R#=?*^g=3(Svbh{>BFqp(oA@DN`XoP05a|*L zDBVDC>H6N*e)M51q~+u}89H?afCpR^`>cX1UxkqgKsEmA*Spn$8}IY z?TzWa7zSQ~ac`%CBB$-n%|tS}{OfG$gizwcmJY&g@BtXuvgiji@@-PvKoSN_zS-wx zcA(VeK-zzXJ&^X_utQ6R9FrhC(KF)hVYkvfm3i{w#)$&8do0gS})j9383IEZS; zQ>CK-GCvBSZTAjv1OHv{ZJQ$UEO8-p7t4SWUZa$^f;_AD-CqY!O$0#Q{2p)irby>a3SMojq8df8SYjtW@)y)R zu}#Ne84?}6EyBh0Uzo|Kgf0!M1D-nL6#)vZg{j)G1x_1N=~K7z)o0S=c$U5+mA>sp z(lh$NsFcl#Em6 z%2b$DD*Y|K5lR{B$?+eQ&Pkze+LbGiXxC&O#EUYK$Pi=^G)I_5JZk6D+~l0tsTq*S z5@2|hppUUIjdwasYoa)R%{UqJXi+(2?9cWa|D5*x`AB3%9Bm5ZW>P3nCTSy`Pvlba zFhappE<_V)mF4TCJcMT8-F<-v`(Bfe`4;&GeW83tIL0ez;lwm5x&5$E2W2R1^IZGe zgwT%e8+nzJJ{3Jg{~4S3JpELzeZ@i9&OJt_T>E|xQ0Vt|-O+c^wfbImj}QhG(e1K` zU?Mt$VNGXggh%`Gky@{#{N)9X$1!-*SM^(VguoBe0DHi9`pPJV>q+@Z3a(Tja?@)+ zV9?JF_8y?TFzLh&+*ixF&ncclZbn6AEs&@`-To{k{pt1tlhdDWAI#`axBpK?mJIac z!impGUH^IhCWk~o99!I?N9egxD0o>aKl#!{X@~_WLPoD*nSPQ-I$J=f?Iq>e9?p48 z#?KM~ z3g;Vl=TH<;VhhP^}o4AftNWOtHncDOAp^059+UlB?H5=;Dx4H0Ak* zQ~6OKK|Gi|38n|eC)}Ir$9waZ)RLXBQ8Y!`^OtMj^u zNu(qVhZLwwl%bnUJ5!w6kQ#!odGTyjOrJQ>$cr~u#b+s=j>QvYu?(X7uz!kOQD-Hf zT0T77%Jfwh74fN(;{-@dD}YeN#byY*yy1+fZRO3*7!=HFLzah;5Q<~iGV*~Og|7jZ zjE*zxqRF89r!@ACt+8kYy`E-JbC@tFiPdMtAU*&k?-9m04#BwyzvK_tLll+kl0lGb z<25&PQx(fxB`i~?bYMhf7E<7)gn!99Ud9Z1DW<2Aw3lInieuAPx0jgPQ%8BdRw@` zf!*6#F39v=6mICfINRe$m(;EP-|*tFQ+E7|5vRZ*k&62sRntToqi zLA&S4Z6jsj?%OmTUJ|;+&b#x?nC0|J&N3ACL!uD85zG3;lEk=V2d>nBR_IEf87h|X z95k>j-NVb!4rTh9EgxBLM5@+H!kGG|J^RROXUFX1`yPyfV&_}I24zVWRlLNuflyg? z7yO$$acQVBh+7HuqQNGE!qlvtXe6fQqBsn{p@-tbcOzn4nuFr94t?SKN2FoJx(+^& zDpM^yJYFk6Ey#*9wF2-vD=yXw@a|^C!w*(~$vQ~f}FJo-6$1M>8hL&}|#Yl`P zv#DL$JflEkk?Tdn2xG=_OUMCmcpVeqXVc*r#@5wxKBqcm3QO-Xn36~sH}we{cHlq>|8U-da#*P<0`hs@R&H;} z=)KDif9*@!!PN1qJMx8@bR8CE-k#sM4{>p02p`U0`p(`>T)lL;w~MAk?~Qvy5Pk&q z*RIA7>FOnZ5L>@VoF~#ajCe?f>QTp$w&BRJj2AXB(+tIN1T+ny`^yPOj%WCaoRM*w z&~Vs9yBd)Ot^o~$Y?{~+jyvf!sc5*E7CDX-myJ7dR5Lw*Dg_B`H!;BmR7L2~9gYl( z#mt@Ii9claw9ryMWOhMFQ}Q!U=IA?gTB?bug=XSI%_DNh2@#xw1}y-7ToyOpFEI{n zs)q?RVM15z9t%j0xBzjJkXlD<8&b>aUd4_8FzdPkv~m88d}Ho9K27dA<_~vWmui^5 zo8_+ShMOZnbL!GYch|j+n()@$9yVgQ;HBGGe6P-&+*sU6z83&WW@b9JNjWppe=WNT zb5JU}pz`TAdpf~#4wNuj-iY1H+|hjiicv-T+rq~E#arCvdk2#?CcAlr98ud~S^8FU zCy^wsZfP9f++Tx-jNi*p@OeS+i1|vNAzPAlUSfP>~c;_ z9qOVLduv#Jt6^%FkJ)Q)tM<0n?)<{W!k!r+*;v@5b0@jGOWsADJGqfMg`w*DcCZk@ z(;=NZ*-lQZEu6r}0NeJ)T(8OSq;us`BB4{_UX-syCJ>sJshPmbqSK}K^p@}f;R|oz zv0_u9+zNQ?^#X6lDx{X#m(+ur$5;MFYGjF0`-l^e^aP07k7ilAZrBfCw;}(h9jSV=n82*4W3m}-|YL0J#0vo7pNOR(@=C)Fy4Q0EJlGbAHtk3p7ac17T?cTel z^-d%s|MhUhC}3+RU8Z{;+jPkH;Zv{;z-n_7=s4#`T#kh~O_VJj$G5yUYM1Y@ypnfFl7mSuF{~1*2>9RA{x|YjsE3YQkB7;XvF^K508%{1e#v_-V-vb7E3YJ=L-5DoYM&DTR zSC4enxg#GTA2XNEkm#q_MS0&9gA$AGyxC}#w%tiLVz)T!KmzDSFPW3>p7P{O;V-r@ z(`Zhc+fl8UMlyex-%csR>{Le_v^qDFQv&r+TuF1k%7>RCB=#ZRXiwhTem|a$TI%=X z%`(b$yJ?K*-uvLDFVNV)VtK5Coyi2;e5_cs_~ z$qpO!eeY@WKK_`E<2cpu9!to|I>&CfACZsJ&eAUpF4@-o`-}#n?ylu($SOv&(ue!? zC7uTHf(dzTr<}m~XdSc8N~)AWYewKCG7_&8s)?=hqQl@yi%Y&RPrsZNUz>30>@Hl} z-~!nY8I;!ZaE&o79w-xK>Z>3&3KjaoDv$R6YD*o6zMZ?L%DZjcJzd^a!7HWGVOyVJV zb+-%hTwq749%qPKmv^R)?(#AeQ4`Ikw%+7rOM+jMp#%A9b$H4FZS9(QfT!txdJ8JO zzzf4PG9H}(azsodw;rJe!WW|}EZN+z7~&0nh5b9E8~^~7f{E_n z>YE3)J-%jKhsAbq5`{3s~J7hch7q`@GI8JRha6XT!{3t&<-P_a67vYaLm6O@W{qq)Q; z91g+EUHbBRL@b3zCDJuwlruK1hg}B{E1f&w493GnYE(2DmSkwOAfgcNvDhb(vE1w9 z;ikQfH_~@+0ZYh?s5#+*73G98So=q_oFfKD(Zqv&Ot0wRo7WAoaGbubR31%^GzhEC z4#!b16&#m$_BLZLn;;94#ux&9eDk^tof~*Ivy83W# z+WX*v{HA?C5qyJ=;``^Vmhycj_jq5uhgDzkoyFO{dWB&p>qi%7dq6%L57~MXyy>`D zwzOj6B*U(^%lU98(+KYP9rth2$(y^v=-b0h2YNTjnlJ-I8kLDs$=}v%@k4|qUTryK z<>K&sa{%JJbu9uS+(e#Rp-tHz-NZhzJnC35DqyH_z;9S!ZN|yetVnDObRbRBFv!nL zSZ4&(-c9D)=O*|1|v8c<(s~X zfEtUTDUI?uk&h0z$6Q8k z*09OF;;`k}ZSpJCF1q!h%G48B$HK-zn|zLj8Deh-U00aL8a8-7voY7`I_aIsaIXz|2h|uq?H|1N zhi-C=DsLzSx85=kCHF&VD#uQ5D?1H$jh(LSc}GR&CED{PYT8t4LEWdXX3rBJA+a~6 zu!m^R$G0qoL2K~VE7|V31w>TlJ76D0tCN*)6YKD$wrI<5Nw)k#7R(ld#TfIrRzn`| zNi^hXJ;)mga~Lq>;cTTLAO1h~-akst>%8xK=bf3I*`1x;SzrO|VzI!T!IIpiND-ze zkd+u0FAgPvF=NR+I6A7LbILz-de8;aQYxdWr=SR1kb}5Pia4}QJ4}tpw8*q#4w_Ig z<;cz2f^F8OZJMT2*_I_pq9od;EjXo9Cgy4S`99CR@B7YT!C#^zJIA81?>qOs?|tum z?(_RT_qkgd@(j_Cd6OX@z72*v>I>pZ0_!i5ArHuU-*Q7CCX$gTCO}g9~TuhIQrZy zPBJpa;!zeo9O3wV%$alo%GSJkCf)K}IDuI+jKKZdaps#g^J723ty8~ zf_f&GI6SBpNYK$@Bfejo^QH$9U?m%tcpyO;L#p&7D^Y;5 zN`Re)jZDB45k#Rq3UTBTYA_i(O#h@2(hghL1g)rdnNLi_PsFQ#LTy{iukIxv-D^{BEfXtH2nN@)4LQ(tcUcDykBI>! z>_f|1TC~9LiAeTs65_d(!6!8vIUz(;DdYC7OBO;hul|5$a>}bmzKbmN$a`?gT}=Ln z9-Sp3k z8iYcmcz?f`0cDz7@%Wf;Zp9+(B$AUWuBk5zv5rP32QQ7((1?a~-5+aG-q&yQ*RsRp zn-2{%jIMT(Z0#y+7w7Wz6`UKEJZMvXXIRSIxc}iR^ZDF8?X=(O3=YnwzZ{yl?{aA{ zXiCXh3{$av8=7+V?!r_uJ=Xe<^eNZac%_Y1-12y|cH}O&^^E`Hvyw9|kTsGIz$~9*Y zYvq?yDG@% z>YqzGByUpQ+4Rz+#*u1Edn?b{X6c6;uHeStT&5` zw*L*Zi4~aO7CzV!tRyavf&z$VB@}`!Yp4duRq>44ZwpfiV^x@+n)PaL30)aN{YB?n->ml$J&9=~)BybNphI1MVsg}*VdXvx15u5-5Y|n%GTSUm%IXYUGc>#@poC!*E(1Zt0Qxc-PPDEvn+J+bK#eb6C6dZaZhkAm~J z=!B?Ck60H2Y9b0yk>hY!ow^_^PVkF3+$=srE_JSpp7db ziItoq<=hR}d0^pe#GFZB5_;tikZ-2^0owJ;A0S*>>YW4-uno|d?oEo*!G+Qus}v*;7kU~o8?8#N2!oBpwx-oIVyhBFay7Jp!e0+s6%r>} zWdsNws1@q8sb)0ocSyfZ+xmp7U}VD8OKBqE>ZLT1aP?A}NT^yHT%?JFsh85kG&IZC z>*&k$XtxVru9rdz@NYmhRtgn#DCLXwx)8twrK>N6`)7qOGxplK9F7FQ?j>+t*mD|Q z-y6JeugP_bI-XQ0*%*5}n_G|>LPlFJge{3ugr~!KqYRva!f&?039<3t3!@1vLavFJ zga%kxZuqGY${!)ELIKr)LlvCh` zPYO5QX(WrD$5fT}*wTTeA#v4Em=rX_!N0M#+uXn3 zbW=>+GO4l=yDT*tCflqG&Bm=uN&&4epjFz3hFuw}$^?NxH^pHJ#SN22|CvZ@YrK=F zc2mQCVj=*euV$sh^0bjQm!o|uJ=zQ2xiN7B{d%;CmxaQL3#EdS=f!s21e z2qU$R1OVqwDI?6&^<{DD>0x*M@I8m`VRzH);N#N4tcX(KB%UBSiPYqbOzc_ZOx2P_ zm=gvz0%}&E07RUjpoap8autt&P_`1{waM8b=Z^;C02y_SI4s!Lv!o2S8yvPPoW;aG zySmt&G#@Cj-AN@_>Od*(0c32GcTMnl-+Yf>WgI?(Q?{0S8Gt-f2Z%vR0%gGQsK&=k zy4YE%Km!mB20w0C)6iE2qZz@Ce*h`Sbi|MQ_R;jxX!Zm`eGq1jvW8|0JUca0R#S6f z%rj7L?nKz}i0aN9RrT*%;^iZ z;9S`tp+IVIw>QYqykUni%0MFHo1BmU+tSB?)Z)iZ>D<#hB>`cK64a z!MTqKAN1>}e%YVzTjJ;vhQj!l!lK?oz0`{sekp;$^xN=8PKSl>&dE0u7KpI=Zh()N z`fm6M7b}2v4xfTeC{5t|=_UIcZwINEjKMz_-fV7d$y-}0TU+$j7B6Y-E^qBlS|j|* zTQhWpP?>1^hHkaYCHBoC`dagL<@RV58?begB>wKdP)`^t_EzlR zLEG?VY*7lc|UB|TM*i^|-Vsb?ee*ppx`3EDEWSB+HxQaV`pDh5*15TxaM{7T2^*NPKk&Wf#P{~X=Cp)9 z;Ju|lu?n&fJD@N4m(`DX>w+ZEyd;pB{AgHWoI9dCk{}Tin>Oy~qG*rvMTrv94+;9P z3FD=^hP|*$u?)%px1|7mzAi7y6xS*Dnn_v@Kzr~T8z;-H&gEw4%T)*+47w;5_ktW) zyE~(D(7|Za(V~=E9v=+WsB##ctB^oCdEg^iWb%z_8gwA7b@9G5PD_77?iVFC{Di$|yQ6b-ACBnvmH{3JbS8 zBJ>N407nCpnyBzeR7RaaQ5Sky7il$s4a}oqlq&)~CB{h9O%hYxmVFFf%qOJ8V+Q2_gHBBe?)KF9TW4lhcP1*K6s4S%F*)?@Tw#_+>leYpvQ20wuvyTl9RpKDulv zGW1bGl_ zy2DvBP5!m*%o&}V)A-1?YB^xcMvL3)QsyeW|Iy`WG4EPIr+{!pdA7JC?MdRqQ*f*v z|4d3c!+W)Vl^5kELEk5WUkC74^zj(+-EKtt*&5?yKV35Qaw>>UrQ?g45KG@vcMy#j zc)RgqN2lDZbW>Is4Ud!K>kjxn8~2X!^5?R*_jks|psC?DzTF>o(^zUfkw~nuaNdn( z6#<;;3w@tq7eB!_xXrC|eZ>l|=64YPCq288gfF0;-1o?Nl->t^l)q)xkCq*_wr%i~ zW%T9MV?**S&JthBN=F=n!kKY#Y7au+KFH_v5mXy{VO~(s8@G;j^es)8y*?tSkte(O zw;+zN(=3<5whNDDi{=N0i|H{Z)iZv^H_hUDfxTdxL^~fiKJ3@4G!Mx(Hv5>Zc0!I> zXIv-H6K0*4oggf5*U`}|5`i+x7mn%=O3myN=@OKqQZLHy1Rp+ujMyD`vdjHb+M)Y0 z@4J8DwZCr}`d-`jhYPX0SdNy&RJaHyHdG9YGL+bT2+#y56x`PUqVZ3_67&gXA2sux zNatDj?~Hj6wi#lwYZa?j;m8D1buBzVcpRi9cZW-w_HHB#4izRYV4fsU!$qXq3`_(O ze>-%+g8O^8Ff|_bz_xA$;(Fqhl$fY_Jj!=gmn67#1p zoGz%u@STOb7^~B>v<`EL;1WNC1=|H}d_Rfw+-}${Wg)IiMF<<(g33aAEhXJ<$UWpd z@nM$_?NQFyCgUPPpl|3UkO{@4kn=g0tXRSHR}T)1MAl%g_^R?9LsW1E!8z`1*)0w1 z5Ia?qwabCZ9sfd?Y(~rK<6d=@OsIG*2~{|li@)rJztE#r;H05D6FV{eqbne>d`Y)r zCr7jD=H?!H|EN~69fnkP3r{88!VMzo*R(tL*jY5H`8hV+t86B!G29n+D$$_gm`6kj zx)w@p>CbyzjopixL{Inybb=NEshwgu;G`J?0<5l+%2WDo;AAQkblQz~%kPGWm*qFm z3|ND+(o1G-)^-*L6tc571l0If)f}pTniKL%chfS;_~%V49+jWB`slfrt#7!nsXqGp zW$U|7v25Rlw_$vLryHk2`q7YRe4_;rSD?kv72z!zB<#UZfF0EUTh=NV)^UiDcK{9K zV52mj^t+*r%R?Fg=a3e)jPQ)Ta~KE~p8@4XDkBH_QW&l)Uk;TS=L{FXBjE>B!>jll zAQJRLuqmkbYx5Muin36~2e29Tv7%PM#w%_Hx<=|i9~#h+KhP|%fr0AOXzp(5!eMuX z8_NlFcY~O7GPJ?Zh@_+L(n#jC?fqE}yY6OPksZ$OW^v7-Jr@@4rny~uZ6VCP8%92d z`06i7qU{O;gd4Ae{YWit76MO#%_3c;FvOvp7&Zp=;XxQheS@uP@HrS1W}MZC?Yr zi#QlKVEhcO0Cgf?x|&@1662fx`koi-OSEzpVnQP zR?XCm*{VBjB6SaHnSOGZ1QlwiK?scobj4q+I(1(BFTuNa$T1#SWwuqB!JyHUPtmVNk;|%j74sT zjyg;QQ9vH0(kP)k(&#E$<6}egkl`x-`eyd+41F=h9cUx$CXD*uma4wQV|*}E>w+{B zfFl8I2C!5IEu7P#q&(0e(uZc!D60;QCzEa2S<0SF_J#lOWTk>{!qab2jR>3(+E+iU zRn~^jCnJpcHoBM%4Ad>ZE%m3ZfutPy07(K9=LB-(6#_}Jg3Tz(Jd35S%(MJDPV!J< ztS6-N*o=;tO=Og?n@LdS*?vme5yF*HDLwjXWKs-;FB31Zaf}xEB~xrsYLQF}6y}|( zL4nblO8a5aE<%6QG1vk0FY?QgTA`i-q49}M6J&97-`(z82 z0K^h_jMOJ$^2H?N`wb&geYM+1#o(%-i2Kb`t z)m!^YVZ9@)#;M3mjfm4>;KPD(^r%xS)o5(czraCMySRmt>`NO2Tap~Iz=4H)r$=TPh1VHnkSnOD!U zP&15qL}Cp+JvLe+qO}P^(SnkQbi=CpKNJUi15?)uZ%_`unw7yb+ZLf08QvTGZDvM} z9JLkJK+l*!1eFS3-l(qxB0Q6NuJ=eFa<$&mGuUmIwFDwVParZAv;V?dJo_(0-KKp< z)_@r|@(yllN0EdyWeG%v%3^f2gWzgLGU{sk?=W1g1R`t{wk}_zk6#f-N&;V>y9&l-XnbcA|WC=Zc*QnuPF{EpZSQI(>Rb4QqGrn!8|0#^AHJ3XL~E3Lty zu*9FE;9W^+OX)U=&(UH^6WrHJvZTZSK~|JWZ3dbVPR%g-9iAq52R{f!kfE_c)tNXT z41sb$+OUL0V0r;k=(ehCM zTMn-rX&l~Y=TbF5NdQ=<)&Q4{&%8J6guRM;;^bhcqEP+p2JQ7jK&dkDtY;R!hDO4* zVT3xCg=@lfy1X&G5y2sZ8qZ1s0BEEOqK;=GxtfykOeEJa;p3S|z_#(tOs@yOcwO44 zmPn+cKmW<|SO8~D)8AmtJ^(UrMs zk}9fI;8GcVFHM%{R*JAvZh`0~w|He+Sc==XhUPF@#8YH)8nyRQ2@1~XyLD+fNh77a zJPL-C-!0Y8M8$x?=yX0GhFS~Z&a2C3cjK1q|Hu$G8h>1?yC`Q-wtbC9k zI-Fso5*=|wfB5xZ&=hr}Eo>>hZaRT|z5D0~F@YiXg}X;@3U9*N=DlTXU!LufnZ2;d z%Ud|0@YgagM06p*HVC)+cp9%8ORK`{%X4VQy{t7-f$XO;$*V$2>}4|zzE1V zt7_Ii2;}aWv84ztQ19ejx@1QG9#P>QunFA>2m7=nhWOW5mXFtkZ;v}pUJrBA*OkuI zd4I8?U&RkKiYI=Ao6;pT{&9ct^Hw7YjZH)J8qbZ@*h=ucSg!%U+-{u7cYMt!sloP7 zUsR^T%e%k`zh|`}${6yA@N0a<3vwTluWQRs5iCcLLhs!;-KOo2(}fj^F4*t_JGy|1 zX<2^*S^M6@D^2@@mri-4Abv6$y9QEUaQ&ma(MkvZ)z4C7MOzwp<%7}sDaUBkRI1FE zR2fRCWi=EF`Yw&`UGGG#B~})x0Du~W9W25Ito5O%{+IUL3|;{C>c+OfjGgdcP%9fJ zgnGPj+xgQT@)aRE`*R7!rTJE6W##aJ;-${q`PNln@JbuTT;QILtJ`1ePqbLgp5R}z zI#6tbsN>vgSon{4S3}WWYee?otg}86A`beGm%-v2wVfaek7ZLKZqS&M9{|U50ko|O zF3Bb*MF_Doj=IjPZ)_gm#{{Qt1@@V-LUzZ9y|(0{88*_~+ersVZ)F?Qw%P@4Wb#{9 zN3ejHzcxu&+1}$S2(f4l+BYwycH!Zs*H;Nn<-Qt&0yyfURNK;KC@#0lsGm1DAkNYu z6leOrMrZR<+6-Rgv~rXj*{Zoh2_*Wa_@Kj11pqI_uXzn1oHnbFJ=t@WoWzB;-NyJd?iIy&_Y-qDsedK1ag>#t?tU<|@H6y(4IzWKYfQ#Y*%K_k<06M=`7PxfcdH znX{)^QlOZXX@-!d@kg2+YUe5B;byRu;K-Y}u&R615SZm$9qz}uUg9&ial!k1#GFfp z$pVBWLN7>C>|>4i%Pv1dW$<@O59QkhSTzLB_;D!$3pXnS7CLW%z_S#;1_WmNRSkhl z^fZhHJmVM*hzwq04>bgy)X|i$34ItnC_~Q;sPguc%?%7@^|hSsgdw)FEo}rbC0cpyt}*+;@m(>A`Ka zy%L5Oq~lGrYd~Qx0GODxAF#^s?7$txrDup!?a@cE)fg?T%?^Rgba+PY?AV{^KmjN* zlAeW)nz->Pb`Fsludq-nVCcKg%Pf$2v5|tes^i5UYiy-d0BjTUwq1lc19od`l0xHq z$OT&HSgk9@eCviX}n#|K2#4n5n2Rm@U!R+en8lfAM#1de4$$XrXJj;^br6e zc6_txD?TffsS$wqp5aO`)AP6~{hRA~EA^a6mP>oy`eu6Gdbytes1C&zNDM5RbAXYs z2q$8W1V`agVM}{(CA9eg#gV4Kwy(92$#re!PeiN(Ux3+c^eYKU(plc<_q-#Qnks5GVNdqke4k2Vp0AcA) z*fq`=+gkTz+j1Nj2c1ZGA|0hgtpm$#f98dzz- zFSr+_-DK*drU5%gWMwDGNc=-vlGftH{)R4S*P0)-gz`&*O;~k_#w7*V*JvPqgFSY9 zSF8icP9r^#Li?;N+=$KZAO&Gb=o%~mjb=UTsP$-8b2l3B9&;;GB{UUcOE0GA!lY&C zWSK}=I#JM+d>IIEAVwJQ=Ocm5P#HHTM(i#TXk!1lFjx(PjD~Cxp;^v7gdGe0bW~(> z-FgBbdgB8a#LHNkbcR+A$oj*w8 z8um)Y9g)ri#695R`gbdVbAIm(n!9l`nI9@6?EJ*@Fe!DX<2iBjq{r@& z%0Vg$AU`F7w>fMwZrgOOtwRC>J9W#h0MOW#iLwjoR_Z}3^#Jn9exII5|T_@=t`6-u+PqRZrm&sQM^Wp_G|oie(ypeLgfhluNUXw+oi zK=%>_mYgV8gordqP%>tP&{}lqqPgtnY%J=x*{;T{P*(>3L@}HWKM+hK)LMQf26{k> zMU2fBrU@z}h|SS{0Io%LikI4!8_|q5=PFjbO=<}xA{KJU18s><$@p#w6-ISGhj1~W zN4cpI0u4QNp@}(T$jmIl5Y-lR++hgPOuM!#8#V>wmeY^W8S_@NKF9`VmK5$*d|K$g zn+o`@EloZpOD58w67q~u4?FM=zDQ6BHp z!c(X;FU>=v{s|)DVVFlD6zo%de)2?U;sPbdIw3M)lE#~{aeR|O_hK;^PO_*ZKL8lK zSo&J_0i+NL`jm55al9IoVRXy`3WZNsdc|}FI#-E%+$Iv6avkyhf%O$5?b$6+8dZSd{Z+ z(NfT78NcWBd#?IDso#^;@1cGV*NdM|`&W3U!4^LfIP<_%uSTR~sluj{56K8@NtdH7 z>L;Qb4F@&H{zj(Es1EE9&D&0j=H9kD z&@#(>(5o_=?CAk`i0ljd!B~Z!RxQH9XdufD8f>7Y$arGcGTXRnWu;Rg6SjN3(pbzi zL@zTotIshjJCIVS0zi+;4x}jq$=<=A{OwBusYdd;PE|uE3W%he(sLVp=^6VS(}B8} zH+N4uegUiY6GwXgOc@EZk8K*=Tk>`+PyA(JL`5jzR-}p@*dtmk3Z_a-o-CSlfT-f{K@zlRJ>ZDUKJ(14Jav+01I@y~IZgsbuDe4w=4{PZTeUCpt%9kI z=X+QWge}$yZiIKai3z?WXFKq~(~=iI{$~tN8PakMfoS03*G?gSCBO2+zxeEze(%$d z{OmvaYmOi*aR55=?(k`t_lA#0oqCs+s(fsGl<^P#SseL=EHe7uznN%sl0G*MZ%nJ3 zdF}W9nT^=81KTOc%ODh( zj0)`qI-VcJLtZS5e+$~4=UZR$?g%J9slhlX8{T;~_Fg*uI)-V%r+w9UWJCaLyMzGL5Xu<>MDJRfel)n3KmfVg%)zR$ zmS~M7&eSWxp}_szzp@!|_TcE71Hg0_Ksr%+qeOwSTeMSltHMip;!KBo59X3#;9;av zPzT14@UrmEHJQ}42|g+|?e+zdg021v;dScE6DXi49dTp+Pd+0}$=*H04}*Y&H60M^ z1Q7Bq*2e#3M}hJ2%f}cS5-_CpM-UvkvH7lG_eT6bv6%!aPZ}MXUoSuvY9A&yj%MoV zFBvUTQhZcK&%yi_K~~fx($uXoeI4TZjH(WPNwu=x(|>vC>TE?S_$m(+7{wu1wl&by`ODj7l#--JRfBfnDfBjRR{_GQfC9R5YnY6kr zy#I=>E~Tqq=rrc;!6eC}XYV4KH`dp|d{rWxGa=(52I_}tZ&F<+uv;*cMsA_3IjpY)=~LqK{Nbl5OO{pU6cG% z1hxF_eMFU%#h9slc-~*Yi0*owD_OWN>#SIvf!Dc88lrXcTJjy0b>3igroGM^Q7OI7 z4J?C{bufAPR@dvinKd@A^H%bymUaF!tJCs2q>aqI4oaim&AnXMj;r1BWk6+Q_2Yd! zmZB)O)}i!@qO@c#jdY@DM-yI@#9U%ut;*>O+~wNpoz9z$kF@Z(9nNi)&j{C-6V-T2 zjcX0q;1*ifyJnXBC4QW6y8@YF(>gIH|Hpity` zgLhgpdEUr+MH4qDt$4N;-fVEMH$P&%(0g`rc|pJ(>VM3m39>$`sdhON z)SlC7s$k6pj%+~W4#JBrM;TXc0W^y=1?{mZV2U=+!U@6>E}aCx$KbK+Gzm5(5eF;i z8vw>8z_7Ruc@}gv{|0#wyD{R{z@J6%KbhwW{!8MlN;Qgi9s^JL58#tOwXtzBEBb?v zn@vdWKf>33;r`E3HeHrINf~_2>buufC@BO6I8O={?WwAT!Oy3}NACk+Sp|4NXDY-R zt@Xh#_~U}gwnjjdD3u0-&wBY<{wLok!vY=Iz>1ifg2Me03v;&zmGEL z1^m+zCXQK=sK=%F-8EEXLQ8j`m?1BezwvWPa`Hf?eaw&&0xK>xIw7!i)97=VRdu^}-ip;YnLni*25=A8k@&dzbFD zYeQ;}PFu)YBJ$NtC$DjtR%GL9Heh9*%RG7vmj#yFxa=WNi%VeR7nc>bP;psRuC}%8 z8bxodW;YDC>2ed9fjrKRui(*K%Wl@mYw;Lgw&qfD8(T`K`aX72aJgNX3s<_cxr2asE_af0gv(vSy}EpOxKEc8!=TH_#&D?Xsm5@m>*>aDKU4Al5URYw2mc<6 zG*_UJwhePoB<^j@z!PBdD?$&^-8W*@f1s*r;_o$vR~8LL<*`jZqoS=PUjcI+UPV)@ z*3=coUaTcUGKuL@VJW{u$*&8!kQUc*E_t7%xNVd6?*n7C3@n7C3H zCa%;laiuU!Tq%N2$@g$MVBt4;4(eDT9?7_4Z6$^uhC^;cx||9jfs4t zE-S<9jNUzIHCwVu)@_-sGo`v-fQYYCq%o?4a=gOe50X_L)}g>o!bs%a&Cts7LtKdV zyoC$#Y)80o+`?^K*uE>z8PTstxe!VE9xf!4dLI|k+1<`%!B$+f1^XDkb}O3=JAT<- z%7wGP@8Uv=xes$8#SL*OVISu;G`NO?`6*oy8>e+09nA05bw7Esb-nUnem~dZ0a)d# z^RTnruKDeQVxWHeFt;my`$=xE@Y{3TUhTJ!a{C6qeT>^{{Fa>j;aa~XrY^iu;*A4D zxoD}TDQ7Cmc!7j^;zyryZ#-%5-2-@yG-KIDQjq0nzJV)|s_r^$9&T{*3?-+Z_zk^y zlT}-#+7SwG;5dQ*`12>lA8%S8{A)GHiP|iv>rWVb>IaNj>IWNdsKt}GSc`xJv*A2q zoxxO^bXX3J;c9j^+5OG9zs=;U;aG_eOnVI&wMoB~o z5P=`^8^4DuHff0y^sI&yd;Z+&6szS5zB%4mOVfiIK3piFx&&e${)0dJ(@%Wn zD=(kqCS21M7w&ZC50;E(Sb|XDHoo*C!2!j_h!?#njICBWg#FS= zR7`*e+rp%65I_Sn1bU2xZfXUj?6_fmU%Lt|bov+?D2$ zoy{=fykx>f#C}!8uK-y{bmuF+Qi1|LS#^0eUmZ?rsf2!0YzN=Ou1;Rs)z5y@UA2hj zs;h_#$%fQb`XS=eT>LMlGozU|ME#nzjDxYT9jvk-~ZX#7MR$c|*6^|f*L>#)A<~J_F9-@}7bZxPYTwM6yVcP|V@_v$Q+Qs(VE5P@k z`nU{$LGh1&R`|Z_RpR>(-utTwS-x1|`yYJy-~PydICJh#{^nm)bbso}C)91B`{RBq ziv7ip!X(6VTZez~`G4`)<7dDBAOEOP>?U-F+t<;3>RXEL_x}v@;$3~V>gwfyy{V`0 zzIsp5Y3hXepBT3PP^*==doLxDSIjX*yb32ap`mQF2~Oeqcze_w{HmTo82o;rHPTiE z1#ApHA-zD(hy2ML^Hu?N{GoxO^}*u7JVoO*iu>EP6oVpHobg+fx#C{GMWHKB`>i^3 z%5PDVij#gjr7yhL8uq*g=PjdldAw0=2v1yg2-AaKtA_AoJ~A&Ofz;&??DROJs8db1 zAxu~lFXp~UmUFEd#S6B7L=KkXdB4@Z#fyHc-HFfnEzXwWS--{MQat0gI9+r~9yD)` zm(Tkxju(TNF$4KuR`aLxp^nwyZhWXxy(u^Fn=%$B3$Twt`vImDvz`G6@Sd5gQQXI^ zZEm$WkcqDf%t4s*TjoF(zeSJ-13TST}qt(=t zhxM~~%m!z5r7%7Za>ys~I8c;R;=HcV-G;8H5RZcy(ml`X3Sw?(w@Vt`h7i*5lwkhB zuWKF^46O|vf&viX@DCg##q=Gr0*6`ikf4NC38?i1nU?mYP|R_WU@s}IY%`W{%KWa= zyspa4Xl+rxO}~{hnPzp?$jh}%?6z9IvufG14*2=aDZv2^TMRd+7gcBGsqdz1gd z3Z>GNbv-?|tquQb9SLzSzWG*w1)@Ua-?2oS+Xp$#whae zXRF1^n$@c91xDSpB9EH3T1Xx%Vp+zTFH!LQlvfydJHH|V-eveCN7S8mcR@jlCwPw6 z5u}Ha$v253EFoa9Y8O@Q0HrTx6#`=7SKdj!v6>&Nqu=`l3<_^g%qY8zBkE+ig7nOP z-Q3UW(Nt1B&Q2d6O+?jWqPW;IpNs_mwCS%%4lgAsf^>lS@lp;`k~*-bD&6oF&dSkNi%t%}w3DH2M+a3+dpo9pCV zVzkxs;sRwX`xH;t%05S#POo~RRtCob;mJwGV$!B!`p6oQ9g3TvqT2M4HKPJ=ec5#t z(?`~j3S9fCSbcnuKAuw_(X%vY)|ZMGt14DZgRD0d&u=QG!9ekIRk0d;h6XQcAEFdh z8XQvPfvDzbI#o=ABZ}|aR7`{WDZaNVrosFas?U>ZkY(lvO9n zS;{3nn6VN2&5EotEr_kyZ+vT0_22l`Db1{aJ>5hY$G-iyACS86?he|4GHSF`r;s*qh!_0XP=+)eFF`poI6;=sj!6_uhn ztF9>XGkz-`;JW$nN^T$Z(yO>V=eIa-i%OkmeFSwH4_vc<|V*Yhowj@kcUJ&%XRPx6|$_$NLucWozX zC*IV3UzNr(70Z?(9RKu^Z-^3uRwux2<085T>6;tIQ3zGD0S&(VF|IIfq{C)-V5HQe=&e59i;9l%6S?AL38v1EZeul6AP_Pxn^N3LH)q+F;6a?mOXX zr3F|EGmjkZeDrYmK~|tAA7TC3q?x(p2EQ2@m`xjo{}jxWQJ?IMhJ&Z{%&bv^gYOWY zC?4;v44g_}d^ZjDO+$8ZpXgc#E_G%-r9L!YMs_a(Xpm$dvW<&FT{!yJbn~Yyd zIe`Y}0WE`>6ACeSjQ%LbK>bpBRQjdP3l}rya1W^g^S6W5+;i5>(%}DAKLtd9XAKQL zSM^-Ly4XV%;rc>v)EoScKNAU$*q#}enL=kt8N~d*Fz;A;m=Q0H)(o|#zNha&H6g!h1QPri6t=)j^`_gd)x3buzj|}@h*=H*QDQ1h56$n5ZpF+hbbk7 z(!PIhqDd3W0A{R-WzH-Uy6ctMkA`_+wFpLy5*aiJds>E|@KxM}2EpH$4`xzm;Y0BD zctp64a<6%cF13)nC7R!aHNGDmguN5&R>BBt$9iltSY|7lG6L(0pft49MfzrL4E06) zCw@&d549LRY2ugt>*=dgbO!~j1Dz{Hg&ajv0K=N0=~9TaGWcE1;+7+u{H8~iTrD&Y z(mYSDHDX;-2Qe7{645Koge?(gwo{Eaw&P1ut`!En%)h>peRbq<>J`)ft+6Lq&2WmE zJ)*5hIj)Lf*Km?lAz_zHj-fUU^DfNl1;E|pjJ3%o*dW?dOMX2TukVZ3cg5>1@%q?3 z@#d3$v%DVv$JaUq79-SV>2@bAzW^DUl}tyDG+lQ^TBc8(;z1>V(e!IR>DScp_^$Pf zBl?&{j=Q9$a#V!QI|&Y(vMTu7CS%UxIQ${GWsMK<_Y5wX-y5e?_!%I7yf^r~&#zAb zlu9qdgw}?iM=pv{l$5JQ{fjD`684#NksJ}`n1u)CJTI(7KJXs0hBHPqNy8~|VdistJ z12)tXDskYNdC%2fJ_yWc7_5y9M6aQO;0ES3VNwI+P}Rsx$Y}>N0RWLx;#)ON8A-+X zAPh%+XE;4e$`NtNnYwF1KWC%1L6+o4Pt_SQN?jjo4jzuJ^6OD^Ow~eG zBeetB_!)Koa=Zo15dJ|I%q)~X=7;S?Vso&a-$a1M<{f)}e;j)NaGbEw)Zh!%Gq}x2 zLk2Ic<3pPwR5+!YalzLiyEqF%C^MYQ1UkE*1+B;h%LxDm;z`iOfFf}g((hMNUWNbLQp)8h;!AVDg>ps)?jf|#O{Q_g+wk1*U;E> zu85J$gPTbP*QG(=Ow-N;)2oWu?t^7jYuiN$2Sf9cUR1^sUBdKm zihq+*)R;G+&J?G?h}%ykJ*tNcg)_hsLQkh+g2vPV6O6i!(*XEK9i?0B+$woDEm2GA zPf>Pp7V$nA&%tCK&-VQ22vgHWV*9+#i^uug;HQm3DX7b z^}&}b0@k<0%%#E&zT)LFBMuv%mUvhi$*5t%l1_yNp*)o6RESbfqbH$@8illqoD`1L z67ufmi;0^~MTG;sgj91d*2z-R1irG@+O#v`g(I8)Gk&d;koMY%s%o2m_7f4lK=)WE zT97PnjW`Wd+kT*QIFs8VVp1skqwuVvFE7jJPx1l0^jxiFFe z1}6L0uGa;kQNlR%$muWxYaI-`veUxSb&cyscE*Y^hTFUdW88i0yK5YT!7g|L0FF2W|j#K_w7Km^*_=fq;9vENbJpjwt;pD5s+sW zJu+x;5eu1$V+Wwh_16=i(0kt5-)`0<+R^so;(Q!9!64aVm@G`QcHv)rG!q8GORz9k zG6W{IL)(ZV5C|}7{ATLXf`Hu>U)7;t_O1g1{<~b`gv#)0K=P0WGN=J|wW~vAU~>&X zv)yJzA23Rx0`7G2V?M4PVOPX9@bZkcoyt)`q~8eDXj{qeXcd&0VsU#L`wW&e(ULj+ zL0G=7aR5PV*fOcv$!oLI^VvaL(KPb)a&~%}9p%`o&5r-H*?A_bXnW^NPtUT3zpUxe zDP5+#?mQlr-_h4OW|x^BI~s^>ivs253DQg$GIIjETJ1}k9Y=NIbUTj!1}3ciPbnaB ziSy8O)%3?!7`u5n0I?y3<1*yT@*Sk~z`_;$kbt*A6%8AgFfi@4#IkAaJ+ z!x}U~)cjG?=C2dyu^)P4^JnLokweWMk9NgX|4BMww8G?T2?6|K-9gH7$IeJ%0I}W8 z?WJ;y7{F@-q=m9UFLR^nBOP_m5z`~n?k2;ob!Bu@#yDewV6O%qBXkVw)u^$Gp0<|t zY~=HW9Zj`dG{rnV!rAn)g}qnB21d>@4KBOUBxL3QD>aM0A$Trxn4HjG4?Z&f;6(Z0 zp0Nk9`dA~dbdJ)X4XN;q2_DC!M8e{>D3KBid>){&;o=6W8|&brt{7WAK$=iXXfg=f z-$9B}Bktt_*F!f9H1>f(T$3x@jZg+jEObND<#+-)s)L}CVT~Q|U>zFiAzJfw#|X8G%y5h_LjtZY8mTY>{^d|Njcyzxri2kw2KN3YjF^;KnFPdU zi~z(DBch_1FhUO;BgzMk5qjVlksb&mC{^E5k%TdiXfozjt4fC-lEWke`=xFJ0yW?g7kse(sB9yvfMg~$!QafAuZ_EMrA2a)4d918y zRrJ?%EO&yrN+F1fm}<(Xl&YUkWTbY~54FhlzT;$D~dd)yV5vp8TF~_1n4=~*Ev&pQ(&)Afn;Uw3Qop!v=xU1Y!TcHSi?71Mlq=X& zWBy`844!ebPQ3x{oqo2}bAJlTl&?yA{%TU*(Geq9rK>9p3{4t}q_&o0T9>!!-6^Y; z2iY_C|DPKeuM=Yi?T>xxH^$0jyI^Yz0o(){U7MWUQuwvvI*8w;S~oqroQX?Sw}vj* z63uG3QaUc`CVM5qm2U&<01SzMbzw*FmDGP4D84bi$11{g+-gCe+XLKcd6(PoDpmU7 z^^|@LjR%ag8Ca%m6GEb4$Xbdz{7CviRMa(neC{BjdfXB}XUo55nlf8xfAF<&v*k<^ z@k0NI>iK$nBCxM23c!cQ?RIOBaoCiwppFCDht7(=77J}zMehN@8DH-$i*T3D#_HVa zkSSH?n8Wf#K>&DjoRTgJ3G4UbqGn-xRi$a8wa+s;K2H z0S90K7$v%2)RirffOVgQ#UelPN1W`10Hcz9yJvm4&tx_FD)2#JNCTYprFonBbTEs3 zpOtRRZ;gv2IQCM(|hVaI4VDPNr>2(0hLB*t9$FLnp_5(?7K@9p4 zhs&*X-MBn(a*Q1Ofwi?gyeZDij&MVS<{-Q|-t7zr<6S>o8}DFG^2R8s<$?!5aJSos z$lYEawtbX}X@yrAGM>?L0ozY6=!!A?`DPe}T@m7tIS`*xVh*F$*vmgml$opFqT)aD z5*!XW<~z83F~?Z(=o^qCYHbt5SvAkdodNx`$)PnkW!t5wPpK)gWIwr5asHj4bL^xk zO(ECaed#_|cuPWC4Vq{Ks4OsB)PnsDen-MFKcr4PZ!wECTCrHQk~XY<_^#4(Vob^W zw{+e7x8^%B{IM>Ygm<^PnA!EnhFq3NxZYN5bTBAg%I|9qPZ<#P7~PGIG6%Rh_}vQT zOZ2E^D{;TxG#v%_p0pATgoC}Tjye!@Iy9h!8`WJW%xA4_)75aFpcTt~(h(6dXY?$k zx)gd_SD;JD@fUJ~>GL_ZJLMI6l<=2=gzEwo3FZC>RwdQ$Z(;*-#c`$+S-r#aZ^Htu zR3`KbQ<+e!jhMiJQe~3lcC2ufX*O7Ms7%)URw`2rERIv;+;+Bdu-gP_3SNy;Ii;yI zeH#dGi!L{@=`{Bho6gX8;nUOBbK#&2QKp$0H+=+PJR_taP@MUYW+Y}P8q}Pj$UK)Q z@pC!mwJB>X?#racMHg30tF;mi7#7l|wGu+BXXJ#Cc;^!@2z_x+8X7Y{c=*6%y1=#o zY%3fK`aul-ocSV@#e85Eu-t}fre16=EgI2Kv_cBHpfhyjL@AX8XVt2}k+>M^fQzn( zkSnBIs{DCi5xSEh{1W~g*=!&s=A4icUzo8E<|_I0bRxhARr3W4gO*DN^B14FNK<-} z%g*JxNgx#G+Yk>lMR(}z@sWE)OB+LjO6cI@GaH0q)LUZu#ukU?YIrax5lkaC`V$)a zjF!9=v<01wF?}NOP4N(19R9xXA3;m;FGgfiE!{;d-0+qJr4i1L4~i`xk@*1xdyy`C zGMXcyF-$SlWSf9%Mrc5{B($Yyo8Y_=HuPN?WaQ=(qhY}-Exy90pAb8M4M#} z;x{idkCUQjEyRWTB-R2*Op+KmUaH=jb#Z@lG}^4-0s>QFQO$IEh>+JNPl}n$05C$g zb5Z2`Gjyq>7;|f(k)~%!`9<}D-PwEGCdJ3!Ln!Zv&$zV^N_#Krz8v-o-Hdi6T{h{y z3zXB=;#fH!-c31|J!9qj6oEQZaM`z-+3r14uu7eH#%h;3aS*1U6BAMsbz&S}5fF2w z5|8&L0$|>wE$Q}@$4qhuzM2M^vApb&mE0|QY$JDjJPwk(ePM6CPf|dI)Jn={8qp9l ziN&#k$eG>}XXZr(DNu}4h!ODHYi)tQbMy2tbHROKM*H5Jrk7+)v zp&1E2+#8`ZT8cL8V31$Q1Jwi^wmBT+hjhp4Vz(qDsg3yOD?&QkbAI@+E%o&SoNpjy zieqcW+WXuqY|q=_v)0G0T6>MXvc!0?R{-+iC~X-Xj@HN~G&*T1rHWV^9qKo@p?y_0 zI_W{05Qo--j6Ui7tb@=+X3XV>x7n!LWQ4S3BcwgwH$P#nJ}E5^%M5rm@1su(+Hw_I zZ^SIJ}w<*vw)&u^2n+Oj13Cxm7)7RMt^%!RG`uOq&4K zZp=8hH(V|49}E_OTIVfN+P|~m-+4t}0M4isWncA;N&m*Ae*;X1FoGS!40pST#eCQi%k`~AQ06yA|gJn>nsgHJ0sF6$Nd>Q`}~_{>=8#q%m% zE$;utT3s0Ubn%###5357t?Mlpz2f1qdXMW@@#f;>FV)(+%-g-qZ=+;R4}RJE%jl=W zf#44b^kUEERcZHq$zjI(7Ld3SwFNQ{ z!C0dj9JQx`v5&JcJrD=riUQ2U@FXr=S~b`P=iburG}!>9ciK*y zX;KPlr_bhZSxy=COK!fleRbGM-4l9PXIhb^l3uc8r`C^F><31qW&N}Y)&oK+&En7y z{Une&IILB*@Y;r`d% z#7HMplAnm}~>JzB-8qnoF!V0`YCVp!K)U} zvoJToj|mp_13Uo&DVn-_gSBDfzf3b-8=vrat0rjB9t}P&Uvxx8F)I}(vq)*NoM3zZ zSF@g(Qac$N{sf?La7}S;V*>`=i|%xtO;kMn6Q8AMXITV`Lq+lGWjt6z+nA2ofh0xn zJRRD?@9C5ds5-BOTGA}0>VUR8W4a2JGQ5+>!K3Y2<8^n>a802{x7A zK}p;wd(7S-YqE05*?B;5qpSfTZB(Q;e1+pI%8iQrxJ`4RCvh&w>Swc4H$=(pVQFun z0l-lv7|H||60UhJFc1bih|TZihQ^aOrmf2NCH`oei;b1?X) zX4&T2McNpA+Vm!lhTAI9nm|dvL|@>bqISGdrt`HWT6^Fvoh~WA7A);oUZsjVmv7ov zt9;W;h*DPL^liW}epV$O+#iqlU_l2yfYMtJFW!YBznrZE`(S<6bJoUcI+c z1FC;&WNTNHHk12Rx%aSHIjX#9=->A&;g&ZkFe=EVx}K#k#S)36Uj;oMXNv2aJk zeJRE$!}+E7qJvMO#b2U}jvy-c@s!vyM`_8Ek+AkwLKgByyi=O%>x3+I3=!hcaB$3l zi{RyBvTq)4H?o@*&zmiFuw4lt%o2e6$l;ZbjCyhi@}&0=VK;W*?tE0S31ElNSOU_% zLkKQ1MP(glG}FcV)=3775kj2ZF0S`+T@X~m>~JwZgle`p9PoRQe)aj{K!F$v&9mN2 zW2SS?52Y)2fV-qBp&hu{Lki9{t)E9^ckQsogS)M34P^>JpkdHoXAoF;3V5$mw!7(F z?76PGrWoVwd*!#XYB=o(ybE|?yYj*g@C9>O;3JcFD1ZeAueD7_!4}64s~O`6C-srZ z+D9h!5rVI*uRSbh8y0!}#M=e|)3(8-tI(DFR<=#V0mq_MZDbaeEFk~d^3m~Iaeu+Z&g)4Pg z4lBAW!bZ642}A2@xa!8{u|Rf0=t921Ym2z^2r_pw4P6KyIipj<^R}<+y-Q9M`0vqTw*O0Dnv4y2{68!&~&>?NO#$ zu{xOLv4Cud<614pbwxR@{pGlZ<+vt|WQ00!G|+VkzhTbWJxE7bq(Z6&#pAy!+x&Ok z&K5ewl4$EI-p)28`g}9I4lAHDc5;@Dc5XACZ1a)t)xb#zGvTy8-;Ia?QL=`}TEGOTZj+^a!fmrz_3ypB&ZTRW1iaQ7%LR^ZeclMid zw$&!rICJqiBd$bBi;$a_L~;W{=sv4RJ^Bf!MP)=i|D#h<kB^|_MMMHuivlbA2YD8%dwZx?+11uqK>0_0TC#@0a zY|qkLcf;oOo}MYRb!wdxn<+I&ZInJ;a=Sh*9~&E-~> z$w(pcb}l>OS{pm_=#z4;t0Ra#eWvz#-)%E#JE0pA+uNYV>Oa7;O|aM_g5qA|$SG>F z0|N-D|H=!W!|bt;!X7<DX^SsY*2J9|N&5y}C*;w}cNcEgMUtM?wK zsl9SZ?cj@gKALog1uGD|gRl>Kiv|ip=(9br3)|H%rjcJbt#;6l^a8MzsHgf7j+dtG z+qiIu^*SpMT@%xE2$9IYL_N0LxI`G6(_${-sga|d>RO{!vkz;8ECrJKC6%MZuG@(& zaz)?s-xvEnWRx=%067?hCd&Y{Vrw57x}aodz8J~F-u+mbJ64jNXhDhCWp81INinKXbN_gJ&Oo2dPe{; z6m|T5>t-5?2KTU)Jnn-_CkvzUvE5UgY&$cnYurPv2ipESTWXQQx>>%&_)y}%$8_vT z=2l;K8Zho+dE}JbNGz6sxX5ff2}32k@KrNcXhH7*Dy(@GpxE&{AIX#`mRp5#ldGe&^5o&rVzTrw3trc@J{587QZTRdi{ z`CAcL^;~iRh(^dK;ij*Lq?hT_r3$0(mb#-pnj~GcU7!w$w|(gcEO@s*I z(0jqzZ1UK2pPP|1bbcI9~rq!t=6B{H*>FqZ;|Qa+$*Ri3@nN7)KgV$rV%%TBV^f zqKI9Ep1=^$<88o(Kdg9DaJBJi$| z_j|yoDdJoE$47J8CDSO{e!&c$hDVTWMl{7W$t1b?2>;XWKf;6Ye06oVnjXtQft}Ib z-U4BF+#;tD6tuT5wzrqoM!{t!{-hb6(xlXD8e+HGUS0d~`CbI(90lrg>4O71W)Yo> zmJ6q=RCovjPsZfJ1|-=*$7Jdc#~y$qBOcr=12VqAPdayn{XB-4p7U1u4T_k;#N7&a zpc{8rVq%(_#p_uXhVTzA`>{88=`k4>~WtfG7 zuu2EhqzMPuBgoURC+ad%hwp3hAsE{Ms)M!}4cu?Jcqnd+6+e)Qi7v0zKAVc0W5o}q z;?`L4!>Je)OpSwyRXS_1~)|D;)oIAd=_ zi)A^msr3(WYB=NZQ;$m%2z!bV&dqZ%;eO!HmAs1l^p^=(IcBAT7A0jYoZ5!HiB|2GNkvuTb$%UHvA->E!*(pVP z&|h=$yy}a*!Gf}8i!YA7$&l@f*pd1o@6iWZ>S)Gk)?m!WUzu+RbMYwK=zJNVPQC`9 zYELGN3a^Ll*_t$Z^4|D{J&evcMmj;PCwhbpm~E+AX<`C2c!Aw#g2vQFWFi_(9!G;Y ztAThMnz+p`K;;q;>Q8Lqm6R||TGX*vYipc1_btPU@Na-0Ea0u?clwgRhuwp57s1y6 zJcW(GF>DV#rVY3-@El&y*J(p82U*C{#SYpztxM+Ne3DKE@A~R&?pLz9fH(uj%UkUZ#My^(cBMP*O4-FQesK z7=Z1*vlC@3n#azil@d5L*5tNOxhkqq zL^6;e1i~qUi!hqLnK#IOfj7)LhrV9VS%&SqhC~^&AsJa?GtD1}^cNVjw2#z>k`Z~`>Z2^2D<#r&*SpX+2 z$Z|W_5BphW4`?ZS07pSFHxn!pG0V)W{bcA2+ZY_4cTo9R|qglodk_kSE{^437ITKPg0UjVorc8lT&}o@wAfSD^I=SI%x*SVjH^?sU ztIDA*FE90Z3kZ=p>*evNHO3}O^Y$A-ec&SBj}Cl-Y1wI8{g7#Tdh!ISNN_#0Hto$%^uG#I&bacTY) z7i~T~H*gNqu?;*%R-Pl8!qONs0dZ2(Qlzp__ zF^Pw0{mN7AIAuFoM|N_hy@@iWw9|UX?SjbJ!Zul^_JKQg9U3j(*bG!O<;`lywk1M8 zHpOR`f`2nm75oToHD>2OB>dJvrH1OZH9ui7X=m9_Djom^&!VABu#t6U7(#nE5wfBD zz%3CVn+6Yvvl!|*{U@H&hv(>%V2|9M-H4yvDq~4kJO`#e?89?1=Q;kfJ$tOa;!egnHh=zPPyBGa;o3njofKH|lBZ3bP0NjRRT# z^<2}B0CB4Yg~51)Qm5DrsZ(GXa1NY%yMho;HRj7b7jy2k6YEwl4+;Im-ug?}1mZwU zHo!ygRoDAsZz|Gkpy(gW^bvEwWl~h8$@e1es$!<6+^~@`J(g=pFDU6TxFJdxBslD( zVs$Wnh0wqBC(N}|`--`L(r-Q_^3g!~mY9*@Ax#?NtToNINY<};PCReR0lmtv3EV<0 z`;e}jU7fz5tWJy=a%1R@Ou^Wn<`Gb{;WMp@bj9ou(&jKrO{&NB)?k~WlJuC3z}$xX zoqd!C5R2gn!b&^?y?HJ1UHceFBrOEgiFPn&7;4r8FGgS!Ga;>i!f>Z6C$)|kS4T-c zLtaeho@x+F+qgUuU<gZTv8l;saJJ`8-$n`Wzn={R`m$|I%!d*w%=MR6oQNT2h2c+HbAS8ElIGX zGn&;o{YLc*`H*9AO=}=n5ajBWv-9YfCpFF4#b2w<8B}1Fe_LN|njN*88pP&9=E4;!day z_F1$ehPK6brhyCQY#ZtwJbRzetu5X-K#p=@L(bsB$0+sw#$Jnex+kJtoJOWR^tJOR zQMTj0jCK*$iy!(&pQUI}7O`akONh^?zPnUlqiwVN?S-l=wAZrJIG*35o~&`8XY-g8 z6j{yfLaeP_(AwZjKT>u}Jv}5xQE1Ce_oybfLp5}jctr9!6~S)7R&b%cmfwQUvMsOd zIbj?}y4Xvq(P1X06b@{O_w-62*EIiHq7s`mB6W#e4HJq@Y8tx};w@36X+CWVaq)dZ z+Y@X`zMUUtnBdXi%fcYx&Mmc2u!*>gNu3bM;&)TMRo5E=C;@UE%x?$Z98ral1vC-& zT+!xx2*2WT`-q@!+pETp_sM|P%n5(uR$8!)eC41`wR}p=72}AhD=Zu+$boY03%u+c zo%!+4zMeGqlEenDdTCRFc zmm@gzDodKp;^9jX8%hrIQ71ND949syhlovEp_mWoRg@+5Z4`;k*_?dwRH%sUbi)Up zs0~iJnRyD6IE?SIlgTUNyb=Zpt27K8BdFK6ZAZI`X6|L3g#UT`4 zTanC{jCuP2-1Kf2e~`-Dm6{2j>@wo-O-Wg87bjte=2UNMAtgdpn}b|NG{cSAf5{t_ zaQN&G8)+L;G3mx5pi0Ml#(a8Eb`x8aUMzv6sXD}}HB!N*bv&t`Lz&t6xgV3#m~#Dj zv57ZF1vc%tYuhB)Iq?V=oi_XJYmslGiJ3OKSF;7SArm5=Sce-QWGA%*)`TJSmJb`I zcU|VqJc>ESpnCURpNL>NY!{Z z%KeuA`la?;D((U9DIW5iZJ|v^EaU>spMT{%h`S@|Ww|z8VkoT-{#aXCQIfws`!4@o zJD)%+jXLQCoSCK7Bsak~x!bbZYl%e!RW{2#ltzBCq0qEjQukBAG}4;#Yw%yTJ~V0s z!gNWiP7am3*d(az3(T{*O&T$f0N)rPbs5@yQ@SN#%j1;*l_QQ+>&8ZJ0{GEKO}(#x&VfHe+?4EdSQR*mS$Fvf@30ntjXq$pJtZ;jq^#{$e;d6rNJ{L44jvSB3sC^V(w1L)c!{7w9d zTdHr+$Y{&XapmqN?r!1Au|c)<_uD9m>+eVGg#%Q34~2wZl_w7~6}9Dez5!^<4b}X( zS%fS2BofWcxdXlHL2X6-LbkqQK7rnYIaYbZ`pQ*c@Q3h72f&;uO&8iFI45EhR|3<~HjW8Q7fl*+-x_!ou8K=Dcf9PO-QT#BuYJMz+IRZU z?l0%n+02)4wQ0Z&u`zdm3^;AtLp~Tam=VVzSwzgkyjX%&Pf~fs+XxgorwHqVKl{5T zhkSyM2=|zs7)|U!2&$V}Fl))>NN&ma*-#NxTVzVVryA< za6Z2-*#>?lZ{&&kpWH0-M9UUIVj}Aj?C4&K9n*3HY1Tm}C{oPB9rGtXP_!&e1eY*s zXpR%W0(P8r?m=qtvD(xx@GDL|I3c5kiK1+Q35B03Ft5ft#d;&}tkB~Kg~aTn$fcX= zoRj8P^H7B?S)?3A3nkxl4R`aDEfF!?k@X(<~tJ(?h9N6fY)S(UT~PnHs1VO%_a37TcylNmdh zAK@zb_m`A*&*hDFqJVMvXMj?`iDPn(7+l{h1_?5AvnMGXW0EmKs0->|Ml>=NO4Fg~ zzzxTx>xo*lbS09of+R5I3)VD+b}1`y&evrnW{uQ0@o04#a?^Ii zE2#`6iNn5(c1;+M*JNS*FMy%Js*-w9H#C}C7#e?x?SLO>H@daR+8~q1R?kp58rq7* zFXx5uCAeEsp&fb833cXj@%p(~s;+s-dOdHn17Aw)^QsOfNQii6jB&OZlyk-n_ z0w@A8ns2dE$u>z@vSk;?RubXVv&3<{@Ib9wpQ5X zji%NL<-G@lO-%y!y(VF7>qa*%73$HJ|EGRaON8h(W+uAjLdL+>2uJglExm>H+9S`?yEb9J1XBV26~Mol=1B@ z>#rTTsg#;98?YXw7mpL4l-+rMtN`bug`tsl1Q zUdzxXmL))zgk`X*;~(;1Cdyl$S$=Er*2`Kif3Vsnv5AN0l@Qzs!U%9CA~9gVGl*cY zNaRFG446R)0vj+yfD8&a!5Bdl5JXJ;GA0;e;C;S(pHo%0)siJ66K4X#eXCBLpZn~y zf1Q2yS)EMu(gj(XnBcn4j9N#qr&u_$BJCoeuTC~=4_Tr*0!pL!n<}&z+>wL_YYDj$ zK2;^aACh82!&D1m9!U0k94!R{u+)~y0PM-A+m>7!fIXRMx8%|QjM8&nV{${|CY+qO z&_3bk`WqY$Fy)u^+7M1ODmJIu`q9x%hUTq$^H`F53$&5oU#tavu_k)s)felMzF41n z9sfetDH5{rLayoyg9}yjZ z5bUIzHUReQ6ofG;UZ}3-aWf|=J|0Y*vbrZ!Uwp7!{Qgx`RoN_V z;w>nyH){NTSlK3beRhX1i)w1B>!qXw)m1QR$opV@wv~rF*!YObD^RW3{b+;JZ)x3V z@hVB}q}~+7D~>|LGgvFE%V2(sf>%RZD!#q}Hk|dRi=F7craqey^MmQwHaf+Kn z(NM5fjD)f`!`8$*`Hllz(5>V?7{Lpts-&t zdU}X8STw8nse%dAcBTwgYQCgE}<9q}#4eDN`3URR}rF`pk&YMnV-_^WnmAh2EpPz-zQ1RtJlZ$v0a z=P99Jhv6d>;>e+Bs<=V|>g?CZD?F$)@-GcEnm5;Ch3fEDzzXJyX-L_0jHduH87}iA z+<8X*FLN33msoX7tj_#pav`~1(4XpRwxLPPcx^RY5BBo)CbfSC`x91WbC zs?oeNbj@|RDWGf;g!m5nQ5Xy97x&nX^-b=9 z6K`_E+R*Kdn~PR$r9p(htN5YwTd35yrW9k_Xrx+ga^oyzo80Oj&23b3VEo2XdyrFx z_t!VM$#jixa%bnsM~;et5)rF?acZM0?sAj5#VP1k$z0MvbOBTvce(AHbG6HD9oVXM z3z)a|ci2E-E@vidP%Xc<$&Q{ZDJhCtQQlF3Epu#e99Cv<(FVsOGb03-+!kfPV0>$6 zYuhw%pN*^L+1#cFl5#z0cvh2iw*apo>0Tr#!&e-S_&YJv`B=PhVn+&U zAgSLjF;-*!s=RsV32C>vgF+aZr@b^t_SeJ#*D7`AX!ez8L|#Bha#pkZN9%c%^~ukW z@dX~dg-GjYf&B}iG^^M)->VLXx~>Sv=vW8?hLAQ|@K!>&PtxpiHVdXWe zhJhY|ovIB(b=^`>v+f}$G(;b8#>R!uCVz4RSV_|3hOZ2|<9?$NV*UvjPKn>Da3Da@ zepJV#o16$8z>?7KG-}|ak~vPJo@@|M8M7=I<_lX6uvm5=UdDeyoNKVCl`f-=!V8ss zvi^lPIglPq#kgIYKQ?QTB8bQWq5*k!G<)8U%{nKWj2(t_p|G4wX{!;~F}FPnqWCI$ zWx=_$RxzI#Y=o%LW*>vKQakvRhjRTsrW(Gxm|{|h(?Cb$uM{RF4%VlLHye-MxX@Z% zF8Mez!+d<&E1G}q@B-|=$~(@U=tCqcD50WUnm@>jBbk;G*lcHLgu~jG;70H5e{2(Eq zbs|B-4$4R(JkHsI&O6Z8MLR_H(77PBe?{e|P_EQUnRSMiop{fYY6q>}*K? zXc;*`{7^|VL3%0#D(dA}sxe82EWRF+q$D%Oir9`1ri><)lopRBeW3+l=7xYKH9-r4 z(SvmUKfO~vc%1QPxR|mt5rXsi`S>;{zWHFvmbsGAhm1%ZCSZ5SbhM=d7~Xl%X~eB2 zXwsU|(FT&3#>HQ5NPAS$M@AC9RW0)z->M$%pW7qTQDLZ^&s06y+3-{5m^f=adZ2-A zou1s^Ad(BedmEVC`Q_SBg6K_gBboP@&%V6Ry!r;&Jp3j9iT=XtP< z$*DxE?8$1z^HnvY9>ki5YPvz}0u9>b6{G4}yq`EHpc&Ts2>mqosN&>p*SrCu3l#XW zV_;^L)&Wt81gV_{VPVloakRWGE+X?uyoj|f&}`a@zczv2U<)D^jAX}2Hs>y5WXSVR-7ZK zLQ$%;^Tpo=MD~?~tDc7TG^7+|piAbnroPbb0b5l(JW!$1(8maPZ zqkbk612<NC^YgPHroJ zw|WjDuh?}oI~JhBlAA)C`9b&YFpt&`ra8O3m#!cglARUzy!F9ZB*7I>$c4asmJJ9y z1Evj1{1|QPGM!3>V4LBbD%VMUQ|DAwH6$VPJ$cQbc2O=0OK;r{A1pvFwozl;QFY%x7l3*Bt z(CHb@dLFR~hU{$XuryFvDOh5IG3F~0)6iWaD3O=}LgsL{d?Fm&Mi(W&R1}AOK;i3< z@F&xNsByS5WKoWu%mzBobE_{tG4}oqsuCi$^aC4pNow_S%x!=fI z&RbR-h?q5Ahiyt3VhRX8PpG%Yz}d#|K!Y(nUW2&-+Ud)11#_lxnmENfv{nx~ux{nq zNx(k>^}YHs7wq>ak@mSG)Qa!aJCNV5Ur5EQego{cmCrTc?~>8Yp-=3a%X=dReXyHy z2K_q-jvBx}0{9Il2jdiAHPo)pZXro0#w)k$YycQTR&faa*sp!Gid}?rI&ueHEk=Uq&Dk|$r4SDl zDAh(!M<(_{Rk|eRLqi)H4{;Vz&$|fkdW0v{&0p1)cfRr3Kt6PuZx=BiWQ}QIm8OGk zZV>H{Pb3e;7o|->A7XBPKiW1q-1rQ3l~(bgT7s1&?N6&T_3C}}YD$&N2L<)9U;T=M z>?tOI!-1>NT>Oa-v@mcPzxF46t-!C?>?VPdE=B6)wQrxxc!=fnr5ZF@SY(7#Kre_Kx;I zd5I}4JJXTJS+KWis?d7lTwyxupR6sEeVoJuLvZK4PCPi1nZ*(+I4j=7T6_W#Vp?o@ zcG-sPF}-jb zk}MyCOa=ahr(jU=FZY&Tc@2_VRDL<6R7?=~s^IP;!O>1@ zKFkml2>3PtA@>(9uNkh6@gIo0jb?=FJn6U;2E z+@9Tq0AKbG6X64TyTTBn-!-RFc1NTJ=IGoI5u zKY(C0zZfc@BXZbTQbxs^Dr5OgJ z%ve}rl9NEz%9m+ME@0sZD-UQQIRn&N)A_FDJYQdl;wo`xwX{I0mYCjM>&7vkOFRvU z!hf9%AxOIe%qqNF9)nOvkB4avNT!w|b4sEOI2bxKj7(N1wEw z!jc)qH|RNj0zs zz5$iG1O;oU^UpSz@w>W1^GRVL>oP65-t&N)nI6pWV`jDT+>I?va__(&%i5xB_X7PMZFML0d!*G}uiwM1?gsrH!ak>8>~=P*4`H`swv@xhHB`-@EK!2xww zfi8q|H7cNeYgVCs;Wz4YwR79=kOS;dQ^w2Hqv`710#nA=ZI*cxJP$NL>mwC zv!a-~G&rS&hXj};+$;ey8b9L27M>(#BY)ID-7Kxn_k8IDqv3+f?$iwUvS0P^85vuk6dzCp6gab)-FeUaIRdZEejvV!akD9 z8Z#Dsq}(^5m)y>P&dr4-myK~tmBVFpVI_TF`dr%1*P%oXMS%-5@+-R+iHfRk#Jx9D z%R1plTBQ=0%3>B6DzLK1ZKzT+C=S*z2Ku3e3yCyjK`JWIO*0nhNlt%s{|Tm--X@9{ zjaLdBBP3ya>2*lTU+`kyM@6D9b~wOr?$PPyTqW=$q0FGpTtGhQB~Sbry0SOAqPrgU zHY~1lBqJZqD(~ou8J5gCu%!FKTrG58q%03--Al-RAx!0kqBxk=L31$~2D?GA7a>Ku z1t14M(;K+LNR5Ht9_&jF$i;DjjBD%-@5>2!qn3A1)TcmU9e)N_k0773gj28 z=v@G&PUfSpEG%wLJHIf0k*=G0QTIYUtBVT!cp*{y1dKrKIB-#Cun`;fw6%bZ1PdF` z>yTH7L-_*6bTgMAw(~W4+u){W$b)*SxRKfzf%p$P@x{chJIj;?5s7Mxt~U$o#M7YO zn_YVSNg=F zy0$QHRqGP%MUPe5=! z^HErcDwlzfMJN!RKaXj@+t$Lb%@tC~Gh?ne*}|00J6H7a-{)K@PT&xW#^54HI#A$Q zj`!|63IbdLa_6lJ`81v1qK7?=ZDf&*WJdL1&k+DGgT4UCJz-C1bhKPhqSm!9ZEF1} z%E~1oM>B{fqGZr7J7Bo7^SE)t75*!>CBA*c)fc3?z-)~w6`FJzsg-%JIJDSOVSe%e3?pI? zBvS?8EFPPaOnbV;nMi6ecm6zkk|Lw-{xaQN%qaI!2bm|y%mJC0*^;UH0+Mf=lT7zE zkbG;EtopWLnct@hg(DkhdKZ%A;VO$IuSG^D`QV)7shQp-B=4V-3^80o^8ID<65jTf zZ&SSC@)LSI!Q1Zg%|>`9Ju>lbrw{S@WO<^>QYe`rt|$4iImrz1a*~f$$r|EeD%`0d z&U%GckmU~F3$nRWG8Jwi`L;R9RCp!Hw^qr*lWkbmXBX$^@&$uH=X18)FcG-em*lI& zInD^ynpM>8ToWm36?5i}P`qGYAkb$+=8khz;<=&3IV$n<AOH1CjsAyd^tV_OBwyW&z@`Z|qTrF!N=(Fbl`!T^wP&j%#+vOVpUKyh*`{XlOUjqEGhn{=_iPX|zc9R< zr3#*3zEJi0@`Xk(k1y)XPV4@eDse?fKU1CAQoc~)%J`xZvsU6*kydvSBPL?2xU$z? z(FG?Rt}@8%DStcCi-zFqm(sgxcr3 zPz%Y_H6qeJPF|W_c06gehZQEv>DA@Bzbs!bW-@{NJgi07Gs$s^*M;`_A4Ei#@Vd-i zU#!v{HSXC9x&>vQe(DrLTq*B999ON<^fJxSX8kG7`QODMmRl_;T- zIrSX&#&lb8{{|*l-TnrWSi{eCG56*S@mb}*qGj- zV^_rH^bP^r;tjsYn<%`&%e?tk&S2mZ_6u3Q(ES`4`ty7#@N|jeo59YIji)8PD0!Ol zwaU|kFJYccie_m;`cPR$ug%-2QuzzGJ+IjDTOUP9KD*eX-_BPsVQ&e^!?>l z}sPjL!Nm;bdX3Cd?3zz+3C`T0^ z%-d3y=oa+NRA)8<<(eQxmnyJQR^x%Du{e5@va8eLMK$F&+91q)xVF2D%Ldk7KGw$7 zl0B7=$`HUJSx0#kOS{b8`iwY&fo75S7SQD{?0i4=_Rym4v_2nM)O}%_MT8l7eLkJP z5NXBwedR@of(Co{3mGJg1}3ysaABs=KzlhO&_H`RGtfYLIXBQids!W5puJoeXrR4t zR@Z1CFCdG0Bq+Sl#Hh>jO?KBKy4DYD9z_g-Ko|wUR-ZI?LQPfHQ{(*emyxJYVi&!M z3NAY!BMf`i@HFn<3bAbq(Kpu$sm2Ls<-Xd=IlV0CSq(DwkYdw4#YaiiNx?psoqF}& z^c%BJI0DQ9vVUV*s;lSid67lHd@#KsX!lQWrg@m1{W*ZQGOiES3&@rmmSR>3HnUEm_D${0*1 z1dB%NWhA@_7zPThajjjtrO>gAd=TLtR2>#7vqSp}*l|WE)V5)dBCP7Df5%#a9rjgZ zw>YVMAafRceGqD1zC$_&k@m}XI6nl~I4c5JuJl(y_bGazCHTD^~;GrkYlI6FZvr$1Z1sqtm@e(S1<iEx-tU;)y)!|t!Y2VHU$1`Sl&%?8JZj{bUc3%*l z)e_q`mQG9036G3UyMf9Lt4AyYJ(&Z=;?yQ0+f5lyEU>Hx4(5YCGXrv70R`9{9FUuu z9)-fdP><*E_<%p2&m;b4N?pq1UVq%cBR*(K<(`4!9)DcL;~szP^0?a{CwXK(lo#Jj zNtxY+`o%K3xLmK#60dp|os)8{C3KP2SF^XqmS(j6v#9`Q(%>{Gw-ihGqqcHWVL&*c zbtvOwuoDL-S$Cd|Mq;XPCsS=I45CA5{hqjHHWgI!^;ONQjF2T32di7{A8b&smg-M! zr{NsEpI>G24HUTeb^5S4e8_v3VT)ZDh&K2?ATze0cOj35{c#KEDL z2_&byw?2D7?-#Dm?$_@^?zh$Ny7k#!{X(7Y)i182_vjbO{t#~U`*|+6fx{*+2?)ZB zyqllt;4)d>Qc;zAq+I zH}9z~vwS?q9`Px#PJ>p^6W8Vk^YdzDqHSe})LQ+@OJ9abwaNFFT>fO)*+=* z*}0_FDs#1l+cQ_!d$!st!-$B2)Gg+@{qnU=45{)tPbaYP==$4Mb>9kcR;ah8&Qx#Hak!lZB2HNFj}GP0AciTLPUtBmFKI;%R=$zt25`8 zFLZNxd{GJ0S+(MK4MBP_ESogCb4W^?I2vLvZX)7=1Hr%yhvKOCC}#Nq*Hw`xqudge zWUS_`{CUvO1^oUTG*rLH#!qmSsD2;UFEsTrE}u95Lg@W&$yF;a!u`_MQ|H}s$`tl4 z7UhTjhs{tYoUF`eV;rolOp!=d<_k%!txTn|GTHg8R^~aplnbH9ONswoUTO;xL!?v3 z^Buu3A}lRU5vv>>qhSFw1-aE>g#pV{0GDpD%_^9DBa>{HA$>so~y22lQ*wzlUD$p|yie1h(GaSY$!x*Efp)puI;9;S}>`;V-gOUk$5r@$+ zbx#R8*Dw7#UwG(c)ZLA}u!4bEL(&2uY;HwxA!?!bQkAs$V>mj)Vn$SicBWhxCiy`!K)a#{AvS ziIw11#Ap^X+w^+pV)a^T^8+v_9bGW4E`Zp+OXpwA#DZgma_bwXixyXbRX7~CSjb`@ zEBTezJ1xED1Vq|Hc1({sK`q){JX^cppsif%E-B6=bmmoQbmVZY4)m0juuh;P~g zD6Caw%7*C|V1k*5ylA+PKswVX>)5Rt(nP7Y^Mrv@&Y61qVYEZ;ZzE^YfrFv>PzNaw zwYyy!=IQVdavHx!U=Sg`l6Mttr@~zP=|V2MW+%9OfwEoSyOnArA5#q+Maydkr=PsW zL!4*x_Ej^(3w2K7tKv3}5-p5A^iTb6&Wgy~;z7_$P(GPjb*#chuXnfov?c&H{V1w! z>fJr<=!&qn%wnL_PDbWBl)zjET8U(xKPWIL9lJUfO zj3k3icSN^GKbF1Ru-ZDLQs!AaY>Mtk(9zwCYD887T9U(7aIZTB9ebo;Eowc5k^8J! zofT|Gg4G~qvPl~WMuVp`cO$|0P}9R{b5AWy??^COc$*`^nqkvZ@0goDlspn_AN8+p zBZ=J(Dmx8592=sPtS!uwSvW*TMuL&W??5g+I7dX%ALUv&k?tcnm18i&qu59Yr7Td# z#hNAcG9N&fUt|;Mji`>YWjZHKA7iY3WG$q> zLo#?qAIXi%zmaP>(jn95HFjVtz!)wH9LVe*RZ#WdpV+Go1?y}R%$*kF|!J5BvKR%*ybImc>r)&ruADL5j3Ah z?ZZf**5YL6CZMB%s(l(kMeTRiY8SxjB!Xq~@#jkE$&HCGAf&vSt;@OrZ@^|AMRb z5e^OYp8}C)R_wJ~C*vUysbu^=WJi;5U)xlE;V)A>*tEzMMwSG!DeOWj#m|c6)u~Y( zfm|D|61MPXysyK;t74o=4;w?5@=n;~%_Pz}{_Z2h(>FZClTxR$m-*>nVnki%cRi%j zcqe##t+a?1Xo8thIKiT5tH7l@vTJ+IFp->R)md)F{y@sHdm$QHfn6qJsE8qwIf~Bm*b#JvAYyRk5n6Px z!FxKYb#NY)wae3({oq>aX*l9gF_*{)7XV*Vjyj|ehpbGw-%_}wt4vX=lp$a6YO<0_ zr5vfjsi{n*EUCe#NvTq^cPYxN-^IAy0=}M?T*{fI@c7GiRLwh0L5j;`Cw5Xz(Fmz> z*r}(|AyRLxQWfz9e;pl)YZPozI3WDU>b}l45?7Uuc<>bO+pPhHWTvWc_p;e$njDf& zxj~EH9cjFNS#N&LU_=fID$uss_*ysTo*>GXU zo=iK-q^U{mvNnuur#GOdSapyXl8O6-4#oq4px}~18qsqSZZs6GA*@vG+@#J74V}RD z=%ohOMPBAr$x7SiWXL;V`Zd{2brFmZZ22_%bd2@C0`c&iAMV-QR z8zrUzGm9ExmejHROFBL%_`_f833*_sXf^f3`Hn* z^UQ+DWU21FZ4C?#4Ue=(#}nTY?hVQxG1f(b#*(jfH zeG9R2JVePI{y0TyD6xw1Wkt@ipR^~P6v#=DG4y@lbLSHxI!PG?uQ>2#YAaS2kE^QE zs_ewz;>{kRMpS89R?3mQVBX_H)1$Ht zDa;|S+)b3jsN92$NhWUWqAW-;5Ska#dgci+z!Bl%p|<+p___Q`#aG$dDQJFl7DIhuh~cNnkB(&I>Boe_s+s~ zwIoVGXq5>%PUR%>`0d#|3F)Og6?gm=Wg@YA&rmvev(1fNpr%#I1kgo@umz2XBt()@ zT$_IcyTZoAnD;+ z5{(a%gvjbrcD9)wfpbG;-$09`*9hkc#a7~3LVd76v*BR_ zqdyv1R*ozyM`lompF`5>BSS@idWSA+k=QJk?39GRlTp(J6rxf-iFRMNW?G4d!%nn+Y!Lh&O7Y{byE0V05cRcqqOs8GZ`kqT+bI* zj3^VnuoaRSZd4O^Tm&)HoQoaKd3EOxsKI89*JhaT6p^f~>w&DxVziZ`DVwjlxholu z@Y+hQu5`I8?AF1|z8eXlmvR#95-{IcRy(`SM5&i1H%er8Xy5wEuZ*KxTObh^(3C_szL^NYpWv zd}U5M!X5ab$&xa@%8@6eL3L6yzlJp3p>VMq=l#Y@VfjWU_Zk(~0+FR5PZP&EvwILY zksD?jQ%D)Ihg{dQ-T9Ww111wFzAj>e<^U&lW)IV$KjO6uvax#bFhv-FqzROxibIi# z-dS6zC?QW{*Z@;AAbWpBdh4T9-SE@}B$vl-)z5G;cV`M(k6}DQ>XjHfrQFopnY|U1 z>5ZfGHE!q;TuacIwSML!Ho}+y49#E8;HMk_dO^&gYImZv%%=Hxm-ri_`6y$NBDlcB zg?s@OkBYx9$QRVUczP6UJ7}ZYhr-a+vwcVQbxelRZBnR~+W2R>M|pd>?P38d_Ll^A z;41*SI%;4ndqAYHgu!=W4?2EokiO}Qr^gU z(uS1C$N9odX-<4#kk~vLl_o6jsB(LWv%^akW70`!8F!6^tzNE60cL_VV)j;EFbZ77 z4`TBc$6SqAfUr$qmi(ZPb*G_+qEZ`1gT};<@{M_bRl{Sb!8~{@6s^{xuzDUm?vVTx z@L1jw;IY|v<4jao8YW;4Vgo4yn~~QFkK2;+D?C00ECL8}uM4ovb=Jrb8M&aG^oS_c zq(?*%p_m6zK(2^Fh;{*mgb;=(aVj;D1OerC5&4$sIwb8UbPhQiB^G*jTyq%ET-(wL zfzo5Ao!kMrg z%C7DK0U3J!brvr@xJse6eL`#nlN9$F)xnK8E%9@)*|sch4|&~?h8JK0%f&4K=x|(8 zFF?Tj6cRSH0I`v0|H2t2N#B|s%PBJp+4;XG3G_}h^3b84^=CAaAFR4@>#`EezR<|B zn;Y@I+yj_QN_AKBn@t1d>GVJ6jp^k7$QxT%^ja$J8Ei|NUpaU`@9XfoTI*+b0?x^oH4;@P-Gy z$!xR!sm@7)F3-+3uP)RL_C&0Tt$s~2FZ4hNlw3_mQv36Z8j0Q*hju;U7?=o#RaO<@ ztEy5$H#-GrjbWv|6N7(2P=NV$YafOpyF1uG zid|t#Wm3UdWsI3C9>P-$gqm4`Q|??$3Y`2JqELcz?PW-11!v*%;T~~1m%^Gxk8+boD*)J33;6*N&XNwvkRpYUPFs?Ci`lcD#88@aCMHS2 zWLJUrcc8x95L%@q=J=KIHjAm-Y(0Tx?xMQ=nVI6GOY-fpGR z9h|$H+gpv`-F=~YIm~1^S&I=?>O1i3>+lYyTpgC#M4i8vXTt;oKprl3v2#wfxTN>W zHb!;)^&qyahR&Z6I~T~|0Ts^1;}Q224L;f(+*Px54QsMz;pI7_r@&pE*GOPB&%qJM z*pDxH%~nWz^f4+j{9_c!O|eer`@W(wTglvo+3KHv$eg<63Q|JCkE#TPMm;aN36Wo6=7sII&5DPuH!nYtSA*>2Y|UX?*R~C;#6WahKoi7 zq1{;*m)8O;+(JW&KPR;xUtXO@+w4#&QoQD{*$E~QO;q;YaBCTE)OMt{M{(IRxs>n* zyAi!ecvGXf`4{li?6r#qOOp$awQ(Z^0&(@o?D2?DEoNwL&i5jm?%+uR@OCg!`xUcV zd_u8G-KQhqGf0Ln2Y8Lb6@V7TvOQP~w&@PzqTzA7v?wY&q*Z|zf>j~A8x9F{a&A5P zK0Dy~wzv=SW`q|~FGWsu=(FAx39cMO!0J)dqL4+EcV27w)f9w@&u<=bB{rsFUW#lW zw1h(I1(nKTiFtv&#@OR^F$H2V|KYKW!>WX%%enOd4CNgwIYo!Yh7|3|I@q~IEvr@5 z2AYi_zU|g?g3^aDYU-$Z8_v7R!QQD2Bl8$2ppDL%FwT7}K+TLTL``Df%qVq=Jerpp zJgwL$N2_h#qbssmMlm@%Ejm>fp0XmK;eWk^7aYk3DI#Z`;c5m5u zIq#woee=GLtxiB=$V?T-V9&lZg1on=hCj#Dvp3a=YE?s5ZOE$EYBc+kGu>+!e>n@Px=q!c*ZK0a=mVLBA&WhiSQ@=ENn5D*C=K#%a2Aw76$3J9 z>MW2}PC-11jsh{5HK60goc>{(y+I-LMuHSlfqugcIevB>7m)(HGDqK5Cx7H2=WO+| z=5>xsNCmreTZ6A_lvo`j#M`7V8O1~g&G*kq=CqYgi_5-WuVl)jUu!3zp1fKIRa?c^ zNQMz5MrPI|@5?r&cd`ulqW-|ERmKQSh4dC47Npl9{6Mspm*Jc}iJmX2;yPO{dcD|V zhM0t)g7ml+YteGi+cP|dQkjdMF6oPsN`FKQnHg})mw%j5dIZlCJLQlJW3o4t0(9{B zhFl^GN%)3nWHt%U3Bf{C)wdsDD{Zb$Y?r-NyhfX@xG`JQ)>iRGUhOoWz*hV|Zx-0x z-rm8R1+=!eck>qGq_m1Z;>}`b**8U#Us3};fZvqf1njX2+{h1d#r6EajgVi9AJd^p zBf`bM@VLzBG1}7Assiv5v=C&d708rMd#hZ|kts>NX(k`&?9S6ABs@cO8J42RFrd z0g#Rh9ubrG^x1gD&jVFa{HTgW-gDui#hYi0p7MYR2-!W73=kD(_k9J8@URFvgMCQ9 z2fil}0v^vZ5JrX=IOc93>SeXhb2$*cDw1Zt^e*{3=DDDr`?sM^kF<0p#(JqbnnB?vL! zC^2+iU$IRZ7))lcU$oehWt+Xp8jJCXiCd*~h$CI03fmflSuxRC zRwZju7v%fQAFB^B&iFhcMCXl>J!oVaV!5X;7cE?l7!TGHhDYq(Nbhk3bQ6VbE47M8 z2KzWY&97sS+@RRnUn%YszmX6N^$@yIRI zTpZ*lV!E=np3%{GGoyeT744He$35MQi)MJxGVc7oy9BW3=^M!IUL@CeBmCOmFym7B z4vDOVOgHfY;C|hTwhB5ag;Mi)ZK@_D(aNR9(sgD|Ini2BC0& z;AUeDiH=31o`PfSePB5&&od=qAV_}96_>zKb!ZxDDZ?snS2OK|7L$mJVS@gs*V{~u zq@}C7Bx5iGi}<-lmPhbO``KvJL*j?FYi-7)a%0yvQZ1>rmkQ6Yq#Ar$;%v|uV1W~f z`T9`bwRuwtqjd(TMP#n`LfgB!mONj>1xscon(6uQWI1avF3Mb;C)etCb1$uG6(W~I zyhi(esvVI7j)7Sx)ae!2>7w$AK1$AX6aR9)Rs;o0_ZPNPnX5ylF_YeO*s<*ux}yA1 z0B3xMqWJ*$Q}2q(uy!`n32LQRML1o--X|r z=%;O4H(TOu69vACFfgZ~I}#|{?`}0xEF;6wGJ;P`>feRVo!x4&m)WIf?llBL-OP$$ zk1)^f!sMWh&>=^C|C=|FHx^_`it>`u8hzyrXS5jo6=H-86Q&D4qS04-*JQE2t2d&B#$3|M2n}!rsBBjw zVUcmD5$>n$v{Z|1l7@&Nz-|Gj+D7pjnxL4xp3p~*(`zbK7dl;r8%}dez=pso?3L0g zcq=k}B)A;IRh-DS1ZLu16ayS;3in(&wL*ND zjYyfID8QHo!&CvuuzjVxyohAo_5;~JFED@=2kqs4{q5`%+Rz$y1Lrkt4GHBL2EEi1 z0xRIx6Kev7l+aec=byHN9247z8`wP4Xvp5lPF^eEu*sF9Hs`uy6q4Dr)zV?F&ny}?TSOzGNiA0@uyhW3N ztZ|L>GKj9(T3f}N{78gJiTf<~>uV_+Rs6SV32T+`eY2{%WI3gT|F4$73ThSKswKeY zP5`vIL+RkcIqC^%0;(XWwIX0x-^}73KF^Ym!b9?~W zccqOCJSe?D@ry_+VwG*CuR}8zW{HTZB$1v7^B)@;G_d>oL1ZQtN5s2&Oda#e#Mbc` zsb(HL2C_0J_!_llO2S$Slv<+!DVyzgPT>+G?D@(5<##pMgAYCE)bje+Cx70g5jewgUuHoFLHhWXW{C@EReq z)@J!QG1EDyRNSiPX8G&mq{muLQ1p0N?)v?zsU8@RbpF!B8+){qe0}{m{>$+O(GL%D znMNUK44s>vYX>R}7oiCN37qTJ-<{cc&2o{mS@73qt|&WzvjL193R&O;gy3q*^d>~0oLUrR8FJkidB0)eW) ztecz73W}dOy-I3801?X`+5$Av5W!)vdCK6JjNmvkfP-Pdcmqd1vu{B$;Gr27rI4p( zODQZPrJ-(Ws&Q*bM{{2~Avur9XZIxoch7y6IFY6`0YQMP9t}yoO06>eBek4hWZ0Dss^ibaN`XK1T@s^a_*Z@8V{JylyxF82z?X?xv8qje zl-%6|Xu;LG;#9J;As_f*9~|xlbmn0XGNMgHfPzYfCO+TU7lKJTwO3~*(bHEZ2wG*X%KmEQ*VG~vHib^!WPkVQ0bsZja+ zIQ@p4oi{qav<{ZI+DMipOSIgrip$2%;L$o9%Q||OC{8=Z0MljJvSp2B%K`%gnI%Jl zV?42TwMGK5S;C7}tc2%UvKmry4ZSD&&^tCvzN)v7PHWM6i*JKP#!w4$`fM$!uVwIz zfd65Z_|6@`yJ`?IG(16eQ#UUgo1moOR)i1leVtiMLSJWiZweOhx>sWrx^irhaL+bn z_=NNuyTRL3`4UHOvt{L-bu2;bkgP`LQBAs&4WoM1&^Y%VhDNqI<2=byA=@GGDa-f3chlCHuC!8e{TSzuBu^IxQl>?GE zGXZBy;5CwkDW0NrDDz?ijq^TELf>#}!DYK%}tg?Ec1w3`sopi(}`6L7hVpTv8 z&$Tw@GLK`=Wn`-_*VQo>fgZ}rP-f@0c~i{i;+R)Qbceb5?vVA%dPKm6vO?6oxf%DB z86T)+Bw)qdjEBpN+znIK$cc<9V@(D$1V-e<2V|}cjmu$izd*XECO=yKl9UPMjCbks zzks9>+juY0pc6lGDH4xHT4KJibi>*>8C(Zo!mBV(daTWpG*>+H`>=+ z2_#?Yzd0it=K|3oBAP_DD85-E8a$ThYbacPYb!QF~XhMv_8d$5PT5sU| zYVC&g8fVLDjW6?8iD`2VM^;}>vPyFLEZtxtb<5hLcXDP3tRfCPEIa$CMOOo-FUhAv z(`Gj}+ZB6nQo9w@DKi@ygvL|P{gQ{qi?M+J}iRYa5GbVW|Jy0K8ac?zt4VaRg zUFC1LQKWWmEGu@LEjaM80)&r#$Jsto8e#isoSh=nYX9`mc&`y5)9?}VQ$j|SMbO~U zvXsmQl`2mwe0MNBewId;6_1}40ARc3`^SL-n-`D>rV1Im^NHv?@BqPaaAwp-y$zs* z$Z`Qedxt>cz&Ms64Y;9*(bdMF4*|&MSdwb~Bw`eTpvTwKPODA4D-s6=F;V5%5Y0Gb zgQFqUZuX~}N<*Ns3&N24{w?`u&G;Tm`!6Tb0S+BI{Wdv`*dske%fXksYk{?BeRp$a zE@P%Om4T)8f7--L7QnH>PJq7Ay3u{>2a57{1vFVcw2>BMg_biK=R%s(R&k`EJuvx| zW6Nw9s~eE_bgOv0Q5Ad4p6lg|3%L!8i=CAdLsx?;+@zOv-Yg3T(?q5AWd~QcN2956 zW=Xv`6sw3HDqAUmjlzH|pRL2tbC;B(iMK)N?M;9+K+6oIYx@cei_j%%jZQI=tl0Ug zna4LjMkCn{uYMNrus2T+-nD1yp`!DlY0+@^U9sDe?m0+r>fK!v@k zhT&5cs@mYggaWEre3C6=1@DNphFyl6w#r%IS?7~ZYHZmFpZ8QN+!wCEDtc@y9gpHt zyMtu)FGFjvCW=QCe&$X^DXRBlZQNIqwaf-(`KqbN`=-L?$*G|YzFJ#x*#be)7b6rMQRC+9 z)oJv7oULg;XzL1EC#78n42@RvGDL(ben#zr3`w%;5n>Bk0l}I$KyQz^F4`cr;PRQ` zVFW21%vX+G2sa}hoZU%7>>;mt6~7x$j?HqEc>MTZeJ`Jor;chRgo_4>YfuSoG7-%%=pjurjza}{yRHAvzrr2RDJb= zRIt+R;D!U7TIrfdJCz;nR&1KO_nm8vtxg^|*CNtH3HZRdA^-k!Lw@xdwRO2p_EC`A zZs?SCZq>1)k5CCvcsN3VVLY^C2CvrJ%amcf{qR4<<&R@fZ2b?T#PE(wV0=f%CuV8& z&P2AE&G?-FE|!xH_E0F)DW4J{U%sL^P&VZNUycG10Is|TmTVofMHC_DFnp}r%S({; zm|539dfZ$o{UdMqvdc~X=&}+4dET#o*lQpL`7!!Ox2AvOb^RkRi@d6)u~-Lam-eN9 z^xVS)EP2#AntBI~d{vVisg`AnBx|$}F&>YI@mNF*<_N%fCMNt0p)5ymNM^wS&l>a$ z!b|E9CK9=!KVikk=@?vG3!|5FFWR}h^|%*Jzq~(czYGV~g2m9)j>=BM#34HWWxppnP5fE2Ox z&JqUlaPL`Nu$tv@mMuNu?BZf)L>o>a_2eI315|zKWwr?a{UQ)Z(-qS2-x)tcoIb>9 zf;eXIDp%Og5GN}s4~Wx?h{JE!kS8)$qdp6dp+22{>I3tI>KGLgec@@xc&{6%&$)s6 z@NU$noA*wJ`t$-H*m0Kl@r6!>B>G4Isi@(Cc__^SNgZ=24H2ellx9z$G*BEdc~P3N zVppUz`Pp(8@7=wvdp3t7d-8w!8PQ=rs;|L+gwamR6k$JMqs|2KSAOBW~q>4c_qm#<-oH`G6UUS*>gHF%hiD{G?&t!x<`Nw>tuy4;ygh}^%&(QFL&M~ zX3BPd-irav3k&RMM|bQJJGo=#XX`|THU(kN_QXluY)yL0_$GU^xKDJY5<$tllicTc zx!ZYM<&P*6-odJCr7fL9*OFcG0ki!xFI@@6gy~?0OoA0ftp1e)S}=&n%~_j-NnL)~ z*r2lb`bP3v(I?Z~PJn>KsX$b|nB60bwvM3$txg_Y6h&QL!KFpiriaHCd2XT288TFd zTD_eki%he%e3fXp=ou{cH1e<9g54Dx6-$Oyql7fCc6LYrv^FiP5Uz+kqo0S4(B zaj_K(-p&?_1Lsaeya4k%pts)Q45av(CN1x@j;0YLsfKsQc$oKK_9SWNxIiKWZ>SHm zc16s(Gn8rPOFVz;9%;YNw?iD`e)wxp&6WWIF5_)GB|h5x10vyQUI_;zs%Co zQonAE{X*1)2bD_7&%h4(IGtc`MzA;gz#h!}%*4+iZtlQ90tAl>9kuQmywH6?HR3{V z^vx_{6r;!@9ot#bvE9}1AZgFw;q9`H_S3OQlWJQ3u9A)o_R+CDk&f*y=~$;u$8N9a z77CK;Sd4!8Q;|xUZQ*mFJ6=mm)a$6K(k#OCj%T4m!poX}_IT^OouLagG z@7(tWguK!eS|py3V|C_4vU0dNREUqYSpjhHLGxoa^ZP}F$k^~Bf+*!DI(PEG(`dIim zop?}84kEVE$f7r6UD~h~NtUw!z?ZQO*|qL0V6VaQmL6lQL(VRp1=6~)PBwS}^q50E z80os;h#Bj`l|aEyQJs|^xXEN3P$65UKW=ih{oLPiM#D@No98`T71ETU6Fv-!!%f2vf#Plv5_p zUiK;N-1fh@C3ceI!!g6gXW2{V4&kHWs!<{l@(fKR4Vp+K;%v8}iNy2QrRTLSY%pTZ znT&qdYXkRXW24k=o*mBJ!x4fA=Q%*H#$l_({FMJpZke%*B6w*;NeCx2uwN?+Ly26~ z&Yanp#S_aTGpf&q;Dz-?8?@!*R{*kptkfx;*bnzldh&ks`6t;)uUbE*;`VRf5kB=p z{z=s&*}V83aNrB4FiGxWK~IT0l&&oh@Gmc&DsBL_Q4MLhmBVF~c$&Qalv!_}Os0$fi4XUcIB z&B$?vqYWjI{NHe#I*(xltkpM8pc=V>A#3znAsv^5URsia;1Ys(M+J@<=3h}B?Fg%^ zatIkPN>tJtZ4nyzF&R-OKI#r3CB$uFj2gv$`3keu>q3Q1d_~ddvU&3Aj0ml-PRw&v zZ_)ci&vP3i>GU9w*0KRM>jP|U>HnlCD#Bzfq{nN)nEf-HxEMgnWhWiM$O}ZVTy{c` zIP2r>_Vy9Gt?C%Z@!Oko9LH~$FEnv5^0e0|FuYf;E<#E}OdVFJIgaDuN<;5gU?}?4 z2&iB>UI@j8f2^Fu(e|h}>wLgsNVx)~FH)U?rpIQ1R1{`eUfmSY13uW%HB4UJ$8X~C zvWYJT7hI^EHNHJIVa3ZvFy%uC&E39ggzMxqp!?p;fLLfhod#in)}XcKY&1a7#VmtU zGeYodVR)J!gY9or5OgsM2x4+%0vQ}<9ZE6FJdB@q2%cyZCoxI%uN;LmZJVM-eH5~W zJnf^Pfu~_wFkJbx;2K^{iw9*p-r6|{m>E2t9I>B<0i|(3oMx#81jAAc&Kg!bi#UcZ zoW$6u>B&ZR92ZE#e=b+LG1~2Ji=Ix!Jt0eZVhn7Nt2(kQ15(*KrIF0+Cir>m#k!9G96BX?F}Eg` z067(Vag&bVgzV0pVJ7BSMi}6n!(|~~w2YkOv@tc(RD6EJ;j%Et0aSLr$_>#Ck89Oa zY=CDbsOB@?0IE5M%Ooo>ofW9+hszqc@|37*gO4g#qwjE8oR@&L#`Fv~A=LqE`?pD& zW?_q1>l_vg6fjN8G0`tZ*$unS%sQ1;xM>Cy~LpN%1W3k1 zcn$EwC6%T-nUtqko0f$8r(HjR|7n9HMPKKMGgvCf@r?8NReW(}?)+t4t+Ei~6d^*s z{^SaE&?r{D+>{|)1w-U?LgRQ`R*T50aI_MsY(+{!53y+CvL}*`i@+}pp#-F3d4P1? zu0}g6d#R~KA!LO@@09QQKIv7VDR~IgBHqklcb{RmQe5&x_a4}pkr33}5&%yYgPL0c zz{z4za}vsk9P0oN;o;Zvbsv{sSUCf)&Xfp@mTaZt)u0Ytyiq4N$jT;|7U?UxX^{i3 z)J<;z&{R1G(x%gBaO?aY+_gHdmUdoaamq+u>zCv3bd_>#siq=3P18U{}h--seA%R6Us;(J6vf0x0GC?ACH*of56 zp~dEWF+R96wa`7hdAv9V+l)efkN|F3tPe1tVFq=@o|nrDGe5i`kxgGQ`N<|MOmwpi z6CfsChVvYVqe74Il|oD-Ur+5nXrx1No$VYi*O^y=DU>+w@(t0&Bmj-aAugfiXS7GC zUsO{=OPXi$wJOoi^vK6g01C4`_4whBw^4n(-cS74(_9n1&Z-^lD1 zT9y{`27e<d*(~ zMqAY^eC}QLcsa^$%OXxyR_q*)b95hg$T`}PI8Qrj^pL5Tdxkd7Q|%NjK;V`}pR1P9 zBr+)^OK+%90~lDq*2HU#?|JuO21y*pc8prOlIM z9IXPz(Gs3ijDt(FbnmPqBpk}{CI}q5WF#DyKHtDQRF02}q?j;W3vVOsjh92@OCO{e z*;SiTIHg9mmP;?P%_Y~dyKp!ry(T?hrztwRk!z5j;q^&_9|~|EMmz6lYBK`S3D^rm zA3DWi?$cAVD(U>n+U_livm9eYv6~R@+9T*MfuMfQPFL6!Fouc-m?1lYA&}=fg<-R< z0rwUgQtN||ddLYQC$@(IQtK?}Apec3Ee#(F9|T^p#}#(} zU)(*&aMk|OJ`@jc0mXG?yVn;`d~vKQU$REaBcS*o$q}(h6S@cd9<>pl!D;h}?ouE1 zgi!2^Ks(~#YWO}f7vE)io)^<~!rePocI#M7A9V>3*@mrQd2T`}1G1YoYsj7&vWv(# zvWIx{M&;@bH=;VK391OP8&NzSc8f*h!Koivjv?d=^O1mE3-XB3x=k`N-+6Eu=A&xF zy|NtgR>>Vnw*%_tZF)h>q`XGvjB%SZA*qb6Zjc@-zt?^GaaMum0MD5Bws9HPRTNQkMzw^kO{?0C)WwUI3 zmgm_tS0&Ew<2XMm0drJve{OYWT8g%e!acwd1V&NJU z@O7|O0kV}UkU*jcabR6Cl^p!|{me%qOloiu-Bj|Wn4roB(P1R6bFZMp^^KykYmu)d zI;+Li$wmYxE=y8_rV%{Il|hk$nPmT|S^{X46(6kZm6;qIXrKC!wK?gMkCvf)xJ zQ(3#$n=TjSR1ykLQ`wl_R!(K3e=4z@a9f&o6Q}GJ>_9sxsHvp1rjoC#$~z`i0bk>- ze5wHQr3&l{BNPU|vpIfHUYoau=Zy`Fjk@Pe^JW@Gqp0T1RE$PZ&6{wH zY}LGBiL2&KT{R*b*n!PksGHi$d1BtwRQb-lsipGW+Bo%jYs@!qJ6aX>;r6>geblr1 zzZ@wXUymdWK>}F+r!%-M1Jj@qkrck zB0oq(3a0@oY8Ig2#e*ON8M#BDY(NHrQ9fH({IV$pS)_jMQ&atWV*Se8A@fw8=5tz7 zI0cOZyirTSx~I_6(bt8MoS-Gn-&fr~Dfm1PYdxmdP@q$+Yu9n>LO(dgy0#y;E~v#R z)^+HX5+Z0m168zSt3SZF6dr9$I zT+=Dj?pwbK7b`#kRmi7;!q;{l49$v?T4#@KcEi)ws-RdJ4|2b}Y&I<(f89Qq{TI|T z#vzMcf7091w7gKRTL08FF;ftkR!cE6)%Y5vf z-_)@Ll>(xmf#{lh7`pV0d@u;8V&D3HFZK#u7M$4ObzzSLL1Oa58=5@RVA7L$L{*`l z6Qr|N1Ns!w1$8tq%9*)CB;q?VF&Ue`Jq2B|;xWJeFnOoFu1WW%x-XnBtCPRv%>1vD z=D|mI*GB z$0x8a(>Fq=uH(yXX4J4?kpEcAgq4C`-zM;JpE@1FQD$}W>!HVM(wjD=;v|?+`L;A) zP>p6yx^+{kU|}o?zAeZ*^>0&~(h0tyF7vIEFRFjLep4zCj@mbrpZd2gn^G+yL}JP< z&d;cS%QvOWp~QB+oslo8f5Wt)dE~VY)!gyQz|qp z-o+|dT4oqppZ-C}FuBPPv)Dz33Iv!E-WM`VY)ap&8vcX~eQ@Y(O72#kf%WMgW%vLY z`hbC|e2+4KXI5^EtY7Bi-qdeafiA30K5Q{0@cRRUB)g+WMtNCDT zK`3-`G7Pm}}8)+8SSDw=dHg}>k~b1gM3o%I>GxjNa4xj}s@CSQ3`@^zO$OA03t(z_f(6 zlL2=wJnGP}^#}wgVOP()k)xs6W}yNHVGHmK7C%^-ttX%%RMCgLwmKcK(}Ib^2gpb8 zu&P4|Bj~1U32{KKhMy9>RRjdSmS|>B8 z4=^cKOSg=ToNLWbdGq_|e6y_hVr$akog{KC43+_*wz2Fi+LCWg=aa;N7UF*D7aJ6* zZ1(~Hr*p;X0DC$Djdbv4 z+RL)dvMVwC%m-hA zey$rUu*kf`Jhh(COIaBzhCIJi)r-e4X2p7b^A|!ry%gR64KNd7(Yf&zWv#Qb%`5S& z<`X^BX^RG!<`qdG2pxJ=tO!=k_>h{cnBs8JX0hX)s6(CoE`k*|Q^%~O{H>=*YFBJx}){ApzuT0dHoKZ3E$8Ye9p%K!FWAtdfrDg=<)Bepx%*>R#A? zSFYgji`_b~oK|Ft_x1p#L@KpbG*zWoCTRr=pG=+iz8(IsoYkVuEnwyFO+7#!OdTmm z_={xLMS`O>#@f2lx-y_mFCg6VcKNP`TV=zo(C~mEZ;K{@V8`q?z{}Jl zt1&$2ty&b>g@MyTIZ&!E8r48$eK^iY8^0EUhucW;Agv8ki_MUT{#xr;R5d!g)4l4C z7A`o5u3{UJ^d{cI-2OtVIf(F_65%x%*zyulY{l9#HuIX=Kwf6Th0}&L+8MPOiO5v_ z`sNgayg}<(vo#o(@&H}!4J{aJHX4l<|LK1N+S4Qb?(Q&)m@y1$U(Hq_lC?M4V&&1A zYQ{)=V?NNgpk;mz3tE*7gi3(2{M+dJtIBF*MW7n?qgZzCBN|q7tnwx16X)HLg}iva zNP@J1u9o4erT?irY-}K1TX!WBc1Na>$N8__5M6=-S<|8WYE+=7fJZsD#0*lOmYuU0++-^knBx?nW6>3nz_qQ2A$bPH_Cxt1xPrf;6UnHxRnT;s-T zt*%{G7it0JugS$d%m~yQ)ywEFu3%FIT8Bw1LgqJ0$QYjItqYU1H*9x-H?QsvYCKv* znA0G^2Fw4qEHUh`Jg+RFWtYZMx;mriXpLzGezh#M&`WXYI*hW{wx(i1Ne3x2*l43# zsck^4Z6HBem^{3pF$5n2j%^7HAlBW!9g{~E`Hho6Y62UGpjGJqdM=#chycUffoC4Y%?AfO>+*sAg(0qIff)_<-=cbrSe3Dl!MZ-ByW3LipY6 z$M0C>9Qu5pU%$u<|! z{U{qt;zc#g)$i%6EU(%0M?ZV?osZmc%OC#P&FmcW=_~#TCN_QNcRqCcXW##!`}Uit zo=&rAF`I9Y8CJI?V|j%J<1F{!>qX4;XhJD}SYU!2-z5uEt$*%(A>=HV?*D^u%i_)? zW+uh`$qX9|6inDh$qs)S0ZGP_&Ae}{e=*Mw?W^eOv`|9GI7NbXGt{>G;b?2*o>K$O z=iSyU&^+?cq3{36KYjI<4+hYD!9NK!I}U&2Pv80NHywVyXwlOF8Jp}cy?gtQzy85D zy>@?698}w#Z`x$rx3_-qzDM5tC)@uDMED0yS@?E}qy6h@w0C{-hws{T*Bf8ACye&5 zq<@=GGyQ?rziscQ-|+X}y6EW|?OO)Y;rff++R+3(WM8`UxJ z4ID8{=rQ3hb)39L$?LPL{cS66QoC>q!l!L_D28aZGGL81e;sFOMz(~hfVff#VHjHs ziz{S=(&diTxLFMO(`H)`!oo{QAjf9#fwx*8qzETP+W8&t!Bn;tDVyrAfwix_PF@S| z`=A+8C((B3K3*Ed7bC6>PJd?m_6PU;&R^g89|ZluVpZt;poXD^ywBDQ^<9limyH;& zsJF$o=uU74WN^J<{7=*%Vrq_072TcS2TSGWU5JQ;;T zYq20ypxP*j!v}$O9j(LUUdxNa4N6sm8;Dnf+viHS^+PL&&C~(3! z`u2dKhvG(R`|)4MhLP8Utgd~JG_DNc*i{rPDJ7lR!n>>}<@7s#qndiUJE8|E#}FKe zK?B3;DNI1TjcW?bkh2&+s7b}q4?~O9b6xf26j#1n@hNu=$;Y+DmWEk@SyFaD+lm@D z7?S6gApw0C`juU-ua7P2v6ji8Awg@pxuKD(cVb!ggHfsYQd}af=|6tocmL*l2mkbo zzo8}4lKIOKSW<`0_f_2?=6^s-z?R;Pawp;N7Sy3tA;3-Yk4a%RA_gdg0nO>k^}HCM zeC0%VxvpP=>4858E2j=7*2|!SE-n^>#Pu5*8&4M`9;zVm_8v ziyahfan~TR*&zXZjseBS5)`%=jsuGQrvQqLrx7XsrUJ$9?EdS%fBj@3@zimmc>+irJOxOcPMr911&K#@ zJ@Ust_~v~_KW8HC$t;hjPAOU^0L4S60E*Lz6c1ORc+(?~{NodE|LP}OPd`!&oB$FJ zp8_OKCsKT+g2b-J-};t2KD*hfe_#rxPjAPhIC}O@H8b-}B&?|MGRWB6>XCI5B(zNE|r@NSscb z_-cg{w;VqF#GgF;2eK;q~rK;m@b#GwijJAUU|e|pPDzWLVQJL%=| z)VW7{K2Vs;3D@YJ0w_)=Qhcof#Si}bXOHfD^XDG;zn^}j;K<3bgd#xVyQct&(}@&c zuOM;g%degNAAhj_%m4IK5Glq^0E!=+0w_)=Qv6*7ihDnH?-LImyyJ`Oo_?fY^ZmF; z@#9l~#OXwe!xbbBeE5T3e*HI&-11jH1*8~10VuY;`(H;R{rd_OJKy6d-Xrk>W@NiFl;{Rvw-J|U)s(k;o*52oR za*3m*Mb^(c?E9ztMjOrFhMF|2L6yf*z&RMnA+9&6PBm|P~p^>xK zs;X5rYu0?#tXWlilPIp%ik^##kB(n+&9=)QedfZKK~x;D6I5KW8>rZuRPks<6=!_) z{?osG!AHOQ-*=Ti_FR7)xD!mQ*$qtWO``Zkg^4RK{J>=&x$pxIf#{cdPRb_O8SSg< zb^{Z8lO}#yVPgI7E`kKB zR$=1%w@-Zgr%yd~@0MNWk3F|EU$GNZ+_@X5*qcQ0M1_j4UvciYeth58Kl1u@onnHzzR(L=~XHX}{H9R0G&3UUrO{%~a zYMvqH#QJqSdw)ePnd2yP9NCYeBTF1*Q*e}(II>XJ7<5vG=d_y%_Bm6XG_G>bpUijL4_2THKPP~k+{ZZITtu~+lsAxuZn=^mV85$J{_+dkpwS2$KT z6TKi-JQ8Qmv7%_IdMJ*CVi_tbCaPg#S=%rX;!nCzaZHJd!=^)pg>q-bPa@^)0xG(h zXdj|tY3bg1CO8BxWfyMcC^Bo;$bq;nMQPHfk})c3c=dEB2#oQYnNSca zn!+0p#Apba`=h?(Aeqyz)bD|1@adKqtL%|=b|4Cqa*JtuCqGaT5uhOo&bn6y{*6j7 zDf*01JulLVk$>am@jts6$NRL)ZbdDB;@p4v*|k?Z@)<(yUiNtI-3&uN%U$Dwddsty ze)cTI9sHR zfI3h{F_!h{$s?Q=L`S&v7WrGw8|q6{w$6_cx-IQP;hbt$tP3P1CA({%D890aj}$zx z0jE+aoYAzZ&XzJT(3#R+&EhlbOcg93f##*&%P6SkSa%c@A)rB7G!;^O4!sT`#WYj1 zHF7Cfb{@qf-s=6iQ2h}rvo~<^T3RpW6dSMOw`E%j*w{fxum|ZML6E-U{9zNKVi&xJ zU}B*Qo&jCbY3e&~d7cz(udSiW4$ll*4d}hPZTo;xXf5A4FwG`{r9hR~9zLpyM@bBQ zargEGgy4VCYAyI*q{@Xw?zPRv9zOk^NB;GXPoDKwA?l^r7O_QOdSi*I2&L*#JR=u!f)uxW2fMdi{@Pe^wtD99}0yaf)*p$cn z=CF1pQ*;*AfMTD;@hHU(ij%q!Y`nTeSzAH+^-m)W9oZMh)y?ME%^&#P!?)bD=02cMYu<45j(-9Au)_xA0`qZ3J853)(-EBD<3llB*1zfSsaq+-&eT@Nm4H;hS_ zbTcUvkRu@8hi)~x8RaohI5WRGg^LY#lcATu&~Jq5VQAv%3#O4r`x~20U`zgR-d@Sj zI`~aI;JS7+>RLXjF|@v-W?cv34lABgg#DT=ttwqUUO{4r$2l1AMe+8KJu6ox*=8QMjW@pPPfFDZGt2JCk$>9c3RqT7S? zF<@IIwgzf5asl115vYLX(28nj)G=+2d@w0QawUb9u;1CyyT-v3dM~daemZ(_nq!~& z=;IfD;led*n91xQg|3}R3K_&~56vqnR41QZltLmyWH4kX8%AWv+mbxkFeMoVDKr|l zNk#)E-!%hfBJK`)Au)8%Oa@M5&h9;-!N3_s4Al%Ad=15KD=T8-#UH%=oX_0!h*s!# zZu>y+<4gAHX3_svorF?tafMhA7z_CMokI!Tja_}kL*IJji@!NTi|1?}H-c*YRC_0R zEH|Ity|?hQy~58AZoA~?5B>hPxBTV)gPz&@8a>Zc=sDy5Pj7how-;{w5Bm>#X6xuup|Db2y9-?Qj37cSmp!-Qj&r{I+f7q+Fhv?aB?Dc$wo)3Ru>#x3d{|CPDvHggAm{{$R_}OdZGk%si zzchJ$?!HUUeCU~LzA(1`kk6bwM9*F$pVKS!eCm-;J#*o?tIzn_endVTIJrmUvzzz{ zlYLDsYO52PTHNjKBazSK1E0L+sXL$gNw1Sn>BZae9Gbm9wb;%6%sf>JlMwZ%J_&ib zt(CpjpED}@ec-9@-+1@G+;R79`;m2V;2zTNy}LK{JHx3|^!waHkNwMv3x0HSpWHE7 zp$jL>eVdIv@Q25@ob~F|^%wo&)=%BK@w)5wBY}l~W{(8cUek9g zD*Sxq{ENSK`PY7N(f`R`QWbHx8!q9g`VF{-2a^m9=_)Kv-czEGk0I(XJv(-^H=`* zo`I_hVBlcqPWsm6RuH93|Gn-%MR`|K+>py$ozQ?}$j{S$b4%kEN>^0$hUWJ|e zfA_r$xBT{j&p)vrQ4eb-dqh2Z4L={K@bk?z*M8}&E6=`1`?p_i<9()ej`{ll3Y7Ws8&a^+`(ZfDZBJ`c3d;5Py>`53h!@kX zL|TD+6eDA?)Io`iBLK>c_io^qIHI9oGh_yLQx@YLfOI4xXf#V-^JCko9xAg`P| z62ILwcNFEsfIQtwGbVRO2*^`x&+)p!+t)N{mDS+Z=QPwjPsWwup`9Z9Lx%9)fA0vt z>ZcZLQbV|%lWPI9QIBVZO$SQwt;kI5K^OS ztv*D?V9b#CJD00@-bF^$8LKmxyc(@Xz$m;`(b*i;`1^20VUsr;}eoTnHps)_;e;2$vriqA&~UDYSlYo%p~~ro|eE(=p@v> zxX%*u>XU~pVYEtMj{=`8sS>y;jf7)Df(2wl$GS3NQ?>D+uhDZ_A6JANW;(jqwu3lQ z{E~zTf!;Y0?@hZkz(|w;Z`~P!X)|m&9o?QWUz_hZ5}M6tJ${V~>@1U}$Ir=^Wn?VQ z@%g09vFql_G_D};;U03nm+`_C@@5pB3oYfCGb_`~M5O=aT<*5RrrmTZ zd~r{+SkF#dK1OE+XT>8mdBV;P@J`}`me|2ttWGM~gwc0AnJpSIIald#d$I-4dTC@y z7KEEe-+MAN7e!phuEp?VgjE!Donfn6^5>dV_maPbEKWNIssIcxz!E^<1qedJywI)% z``b6P78)UkHoR)p20QnPWYrB_cg|KG{d2s5t~5=MbdK`o`*fx-QcT2S7vAz4?!2Xl z?v_hhx1Y@j6lq)chgok(Ug!6PG*{$lOIHw(&#?MEKV0i)wMq9dCS{FWvp`DB)u?yn z8c;D;G|-icu#G8#6Y4oXjd!&t?U5lm7;d1R{~lCgQ@4nE$CU%Ajx>`bNdcijC+wzs zp14eA=KjMbx@4xefLXY8Xh?173IjUimzIc+1Wdf$83?yUp3O&wzCX9wIIW2h(TF=( zCb<{05$){JB(a-p2nJ=HgqW@SD$x~+xkS%(#uAHNK~@1Km^CD zRBy>Keh_5Y2_4vBoBH}xqH(ZpZ=xdV57p|8YC~;$qZ^?HKHh|Mq6grtWn#(YrmpRj z)D(39SL=pV){%U$7=BMD)ff{23$18oa>IF`vQ7UNXV=+dZ$8vc8_W2VnG=n%fJ^@b zkFKd^ZsL_%z9u;d!)R30x9>i|T%YD~lqCMSAmnx*DhYyGJI+x5X}0 z{gg35Pw18e0kCrgR=C`-#F_XCtT-E6%|PM?Qa96+?1ogCY|_TyjubBHT@v_xQ?|S~ z|Hg@K*#>j}_|p<>15*T>aKi_cSQFYLBuF=jPzq5xyNN^I4AVTqEAR9|`U|S>5UQ=e z#!6$^-?+TXVqIpnP*`H)(GPZw%ce}m)@ZglYyBeRz+fUJN9ub!+}X#cFg2SC4H0m2 ze1wg|qkcA}h26sy?t*CRbx>5=(50&olw=oM{*h$fNAIllI^xs%ZX_UV)X*QKr1e-x zbL&A8SDuYc;zYGD%fY@cGe$2-+%IB|T;oGORShvUEiU@$?F`l6jzb0NYC|RZiyDX= zb%$~Iu@m-UC~*v&8PN|f?DUT1E7#aQ{@$_YpMU;8pLskOMK+IScYO@sPCmS_B-xzn zz9jPb8nTL7NSMINvcYu~l;}OG55pfIL@JJ2$`R-phRC3#jLy0!SsF`&tS?3*(HM?9 zBUR3lnB$eru5ylvImShumU8SOC9BsiS2FEp{z?NoQ9D+5BGc09k{dC%Z%r|A$w{Hf z3xU?E4I9{ZStL2Dv2OxJSmreum=9{i2NAvcjdoX*ho$nAffP!bY&5k<+MdWpnlagk z=8c5bC??A*ST|%%IcQ{Gg*lPDy>42$bh3L;CG|T^(Fkxi*PzUjx2OlA=3Xm@P%iqp zFA^H>3HzfEb=aaN{repi!VwqSa{bLebaZY5ed3vm(a>`}+6TvtW#SqXRWHcbQ$J6+ zJ#k|o8(~3`ta7-N8;mhlDxsK)-fS?_()dr^xW}{L7q`H)X8OxH+m<>xUOJVVigfZv zpXPUcrd%L2KYSu?s9-qv^S8qZnQZaA9IZl zA`*g90$3&C=q}-6b8;Wnp(`6%qg)eU7k_0-o2i;&fZosUOOp-^sdOjWNUrKbd4{4n zh(x$n!K-8*XUk}kGI^(Icc*41PqhLoeLXj5 zHHwvY-K!7YVZ~t7rP;ek#nDjQ_dNUlcm}A}&8n8WT6LZcf0nhrq|x#2y-^rdPGBS` zy^dqU0^5#oUIKMfV-}<*aHu!(v?yKP_QWPynE$Gw6a>ip(#`#$#&kE{su61l*6U|p z(*ZBy#KtUU_3b8xPoz_>SN(=MBcCZZPU=F)Oy&hHd5wa}1yMby!*;xM9xWt)0 zmz2YrjkNrUx%-rgp7%#WGLa5BfD?RR(3FYvNJ}${^hVM1PaU}m^&Nmi`n!8kw|`P(|Q;z+Zf%aVYEGxz4pY6(-LxtYYnE&VUW{3K~BR<{W}Whk2lla z=;YJQVx?fF?l>8Q948S&N$V-!JU5!XO9x$yX78j8%)+JFNo=>nkbN(2@Fjc^DU?Da zj%FuyxUU;{W#|E>nG;5y@ja4fe2?Vm@6e!;C++a-tpqBi^5fgW1P${S(IleHTIZDV zQj$h+z}JF=E5s2o86yd#e!h85;^Q!!zwl|`CLj#JKwT9r`Q@zLH%i}C198oGds*U^1hB#zaM8gbA$nA6Dt z>Cl4Y%)h!oUf)GLqfv6YIZ83aYo+@rJQ{SL`HFczLh{zif0D;Mb#Ov^S2 zl&a0gqI6%?z|-w_Y~vNAxm;(j;Q!yoM`}xH_<*&7#pfDrNVm*c!kSjdF?+kp8D)QS z$T5qq%E4PUOwJ~1o03DHX4RIP)HJ>Ct9fAoOq0x2>di$Bp;ZdZAR9FsQLa@@!T@=8 zUM*!Q30Md0j$Q{vNdP&R50yPq68#@yg)DYbNsxK92Brk4WL8%Ry405s$0VU|m2eJ? zh!jC0A05L4B9^cO6hQ@`Nus6B;LLHFgQS-ULOR~p@tH2L8V#wDp8-2 z$x0^Lb`Po(9@@}>jg%<`Io$enNh;W8`qmF{(^{tnh_36v0NE4KO>e{^aBIV>#Q}y_ z#G;%UoXTO8MJ(RM5(Ua(I7BSUu}OfBopKnvSs}-UzRF>sXNR066}jpgs6z2hs_mFE zCl1#!Vpm2E9AQeznM6r?$iTHqn3TZ4)kcy82Ckw9m0;jXYOp#OxY|fk0uqX2&5=W8 z^_vW9d0)h+0D6nlyB;~ZYg6jpe=xp^$rYDxOU$}lY(#;V$pF1C#pct}L1l$Pky$jH zFXEXuSw|uX9%)=wbXHsmfMz>qvYjtdUND};c)Wo?7M%1Xth)JZ$cpAOl%uxr*raYi z>-j!&eOXonw99_ZAtC1+X;RQ0@gLA*lWo$Ulu!7!q#2vkd%2Q#{61wH zpOPL;gL}D>dK0-E1RCrEnI|@RaefPuU5Q`E~K)_!iw3_Y=Qu!q6deU5L94%cLjZv8UMBnCiCWrYsXA#Wq`# znirf3o{U)56|eeA%1I^~O1noZ%o~ZU*`}!)eo_8XN$ZCn(R76Mh=)_`a(*}Kj`^Nq zJq>jGioMEiU$GieNf;(HQ><)A^VAw$k3LkR5rA0+Jj5mxMFmGKO%4g@jW_XQ^O+0nwFNKztJjTzb<}#ig zrCdK~8d%t#vlArz@-iXez^Q~gw?so{UhK2cI%a~daSlWsqpXakrl+q+;LLYy-BomO z7Zjo2jVaxlnZ&zco0~^S=9l49Gqx+T0dMJFFI<{!6rGDt^8k3$h0RV{{-cq`tbmo> zYPrTy?&gnUt^Ps@3p)qch$AHrlsM%dDx`f7V;+r!&H@OdJ-eit_Q86ztLWQ@0QDyN z!aC+c9&sYW^X)@a-Y`HEu)$sN&*BHp*-X7%zwE(#O20Vtx9OK79v;&#^R`L*Mf`VI znBJ-vtvhD6fZ9PPZ6Qf3Oe>Ld`W+9y7l&Vrryhl+0hQS=*rH9hLpyEP31dm?azRTu zjPtyeSLs)Tbk?XO9#_(q%1G!U*n8K(%Sr2+Q0QVlZZ2-*oi;6uszj%=Lkk-y)XuB) z*uq+I&Em!ewLqEBLallt{qokSvBvTCVX=}k+KZx8HOWdXYguF}PE&msr}`*#XnYM_ zlhAnn=Iif1_U#K}N6#1=zw=AKPT!8oT6fA>001x!00OJ8NZw593aw00;YsaRQviH; zf%a>7!?4OG6VX7R7KbE%J`Jd&Z96omP^3LL-_11-*KSPHu zmQPjn$RfW>Hrs+A6oUVHivTjVg24P4`L;CMAi)8^EBKWa{*(X?R=6ut@!!(S6zK-k zyj$VMiqQ%Oc*!5MV54+n^LCfbN-Z-8YxOq&bBV9c!wq_eXKx7a>+!UZ!w9#o{5TwCW2skJjjlpU zn}1$8-)AIbc@XBo)Cx7Um%?xO}AboG90OyQxuR3JNj|VpH4pO?z43bv_0Qg^m$5F`w&w$``>6VWW9z>LTZS?g*;oZk@O;N4*MWQaG> z(nv2zChUms81%VLcJ{imA-Cl7jT1GOA$vubr;8?WZY@nj)3iB00bv=zAfUwKrdDyA z2WKsxR;F$T|HtC|HTkQNu7|Bb0;`EAO&3Kmy6$9Dz^hN-r=x8*i}SYJ)COXEah@{1 zefcO@DrZ28#r=`Vy`wHJ$|b7(jxjq&_~_A%&f*$#c8-kfN&XA7<|;|kz?$QFHrAY! zy45)3BT|;F=bb&HK6qzIqJQ5pQMVnA6+=0PF~Z=`7!@rv3g2{6F)B*u-R;*pdSTL0 zDB`ij1B}FfqRzko?E2(z0lIge2;dfIeLISX++(#X|d!;Xo z1gc7$c!3L^Q6|2H-F&Gf{bIh|d|$f6KO`PA-VGsCmf$zNTwJJE=I$$YRfMa4R=q%oLtxOKWq zR`Zq7iAtKazNBT?F%gVKVFRKX>+f{jcs!yKaF`}g zLXv!=W@KO?)0yMji}drB_G_FHyB!iLkHPawA{YafWVW?UY+yg3=krBW{+czNbfEx1 zum_LIVI>zoW!0uxc+*v>Q_DdQTXRZ4eo?$W$B@`|@QJd>HVUK$cJ>pE#j%&fI~ zhtRJK?-*)mNSWPrGmBR`?mco0nDa@+7~UPNt<}ux%-ULQ(JhkaUPX}RM}`C=IoV!2 z%5#`)im7GRaggVmqCDrz8D)7=%D84Uwra9m;V6t-m(kVdMps{5mQQbRbsJhime&of zQkK7>bmr8CN``*}SAc}b1omMi!~5zo{6(8n3?Rscq$_i3 zH8U_ZyS6cnIpx!f(#jy#YfohO;moYthtvJxO2xc_m(mWL&r4+}vPvT#B|`sDNKH(; zn7K&1;|#hsn15GVj07}^C?f(oh-7snQ*<;BtL1?lwt(v19QMoMKC0S=(-W&)>q9WB zo}m7@B5HeqMP5<9AYJE&7gUF7@3k5B*{IL}CLv*U2`CR!)ti74>ruAG;Mn;27hIN| z>`|;e1;$G#Y4T<~Yq$7*Rhjx~eZMMezlL8ln~AFRDX#p9%RV-wK znVG!mQ_5;pg9-3(@y@rJ>1ckn1jp41Q~ls`OD6e0N~yLn(AG?+pSKYC=-<`}X2}n* zI>dk`&|HG2mSKdRAZ~jxN{cT>gZ`p<9sR;G5%A_M8KBFM!MpQelMDiexy^6|ObrM^ zwA%O+p|3^xVJAbFi`Sv!SU6&3n@_IvIV9AQ4}&~4;`nr4xAvkQYK={NeCze;sqH1` z&qb=sDa(4D_qN94h8V8_%K<;08)sX3Y2LeUtc?d~oO6P?%-n%*6w(sbdr*v3K?7;pzJml6TUdP$NvXoBg?RsG+6M{urJ$<-7oebv1o&Zag4B zDAiEG2~D0UkPw|N*Hq%8D#|%B!3%9C12i&GX)`!+`ShR5Pr0K~Uy<1_4{wh)sH@6` z9T%Xd9y>08tom^QX=}A9J|eeP;u8~Hl)KLresMWsgAYvU?}eiR($=SUYz~0|No2(> zw#QZ?MsYe=2yr8=ClMK=Xqx(I0l1MAMpHj8z;?)XM%2pyG%0B5o^t6+aRL0FNU_1P zjAlC|4c4Mrd;)|IvJ679IT40NpZ1A( z{E4V*r2lV)sBM0*KNB?q+$l_wgm8;R=q)_@7Y#HerTeN4*%S2`>mt_~2^K92S0g$w zBl6lR8=9=;LR_}6t<8`$A7P6Kz(_)bd$=tTRJo<)Qz8|USwXm4tdb&^*=$mb{)6j9 z#X^k|3Kh01^%p%n? zTW(C>r{!tNYArUyfc6kxh3=jt`A;`w=g<+r8Q`askxE67A|o}kiqci7NX{WrOTTD_ z7*+l|tY=I=P)VxSgD+>*q6tZ%N~VEPpsEZ_54vPRu$Wxss6Yic4inDdxCLW5c1#^wR|`D-n7+T*dLs}+9@$@a z1~3GT@Y3RjkF&pw7#mn;4r4T)fHmn$>>xbHVytGl8K|_2HN0`(^{7SD3(?U)&(O1m zIuK&}J`H;@WE9lWxG2VAWgVrkNpU`XWfn{Cv{Ws?!%Fo@_Jw**z=9~M3>Mv9?X>~` zhKOw!aji3#`O!S+-34pS%4Bf81vQnF}OshFSxhEf+J;H}H z{DZ?hw$0XCpa0L2e=G5)p3>>_RRk7#&+N(_Z*=-k=?skh$CW1&SRk4jn4u(-?}1Y~ zgI;p2N)FCY6932GDV-rNxmqQMY9+t(M+44a+nRNTPU#GLNum-^Z9I?7J2fA!z5p;* zJ6SV$ePgqJ*$2Hzzig)6s9(0sPUv@NETt%+DOoXzqbw^Fcv9hH{KHSL{Kzw3!J6IL zizvAL?B{=c$sOGGIH|V>p5OlbgC97X%*}ee^@`7~dG_}o#WAu;uXld%(x3kDTi40m z$7>j@RrT77O*ViVd(|$3*?QJTLIbc317LAuym?BA_><8UK0*wKGPhch?Tva7VS@gw zg}=Z`SMf%u4Aseyj{&nv#e2gL)qn!dm1G4h zti;7;W8hdAlVcG+>Xj|vQzd^}(DjzbHx)6oGa5B~J8r>q>yM6Gu}E9f!}ZPOF7;OT z$_MSrPKkK5Y&6L2lv6q@j-K}%Y!P=Ci;eXSzBJF#oHEvC0|@=CS0^`H_bAIVBo>D{ zkcH=hf--&FNW;rlqydr(go;cpRy?U2whl?=j)b`_2NnK%!C`rdC&z1;`u-@vJ<2vLSpj zG4+!g1c;LQClle5jZ;6Fxs{Fjggd{jCJCpSI5SuPel2AJ`6C#3X4FeGI_Wx+MZnLB zfU{-!EK^*8a40k_mg};9WnW~HV!V3X-WyZJI@>A{rM66I0nawrkGa7t^cPP4Hk!!K z^nqlIqFk4~p#FLle!zT|7d8)}!d-_6Eix_-DyrL@^D8e{dSs74-X;$3N zyvzuVf-G?PdIq*cBJ*EW`|(hiCrP1*TZi6zZi%bPM2E~0SC)wmmL)P-FqEWjAe!hw z^3b}@JMoswheK#@G6@7}yODg(ktn#>rGFwzEIwjt$4881n~arqr-FcEY>q*)-Vy*U z8mnN^riVZ#qQ)?Vu7w05r{(j~HYZ_gRbRBjuRNq?hvOG$EP@%wDOe;&B^xeg(sFFd zHXcmc*)zs`8KHrN`OvN&*K zW9pdd0O=c&J7s;-)JFZzCG7Bl5L=iWnQTlu&Ek$!TQyJ$D5$(C7xCT6KiVnMxfPKm ziIuxC&6Z`$+#@3FD@Y504qyY(xT<^DF=IrtnfmJ?8ZyX6jK(7vd=bnindyZ8n)n% z(|O>NTC2oNCv?CT+DUB`Khon?Mcddje=*5cUP`U4f0gBB+o{du!HSBu7w1X2?WLoI zhhKm|gYD(MxxHn_bVY&B%hOmo6GmbW!UWHBnUT|IUfr_W<% zt0{ShcW7?6l5d(_T^pmL1Dj!%gbP~{4+NoTUerBvsiCf?L|u=7>1HWnAmuer`7;%D zJ(|!k4^Rg*l`+(5HuGXo*Hex4j;L!&G#%vQ%t$jLcc#T$<06}gxiDZxsl(+0jFS<)#HH#yHic&zUvP@q!(LI&EYAW$i7$)ee1w00Q zbur7WLla&4YAQ+g&w!N-t!qp;l_Yo9J5Z8` zNO=dE7}%BOcW+=YBFZ)^k~IIo4$Tkl+vbP%ZSy zne;Y0ebC$XO{KSq4S!L3ySEa|JL>Ho>FvIm^|nJUy1@_d|I|y2}#r2J2ao|+vXcHG+z?V?)AJPkGkG&Mxzle zT%TR`5R>Z)+IDe9ZLKqbD{bAQ652Buv~@p^L0hw3snXUt=`8s4pz5WqwX3I(r%_Xk zeaavNd5X4{J<;A324k)@J(-qx3Wo7sWUz+j6da16IYrY?3cwO6Wsh_ARCeC_Cm|#8 z_$ML5+@z9m|9*uGNBsCQUH)%b$RJ(X($xwk#5Kl3>5dv{T1m5g&%GC=hGNUjo=BR{ zXK8tpL2c6wK9C=rbL+S+hB@Pc@o_EmS}-aLwcCD!tEHINS`pHJX64wcWYMu~UkvGw zS-Q58O|qmN({&&xtJ1;@`XN5`$0tuH8>3L(IxAGjx;yC2+6e)Ii6fcSXqJi%&jpQy zC&I_VQ?q>PDW3=o2)TXb6FMcN4U|uVcEUG`vpWX<6DjszwybCusX1DR{On{4!){N- zMViTj_lWUOovfPsN$OfSH?pwH{^Us|_%kgdKY1rUG_8U|8ww#!%lOfvtrL5|hbSu? zCKtkCtApx)G1BNIK)*cYda^p@IvRA@GTSSKI>7DjgwYeuD3!Na+R*`;jRK3?u3wXTJ_onk$^@NZBT&(8GYXZ80W?cQE4ksuG)i z6`gja`)7<)+;QA2cV=`YG8n$+3%a8SEya!KP0?++ON}5wqv5S7Y-fk#Vz&+Q%ph(H zS4h}yLwH)Yscq77_&lV?(ikvpdl(I8V=GLC9{Tyhb~FI-`S^#XVLIXAPfQo&19b8y zru!4qjl*X0tjM2hKHxoPI@6vOv}T8bi%Buq+;*_7YGoLqF{>R`Wr|PwpRo5hWs6&C zzTDf;4O+u->q-3(Z&$MY9pZ53&wPJY(e#t76ssEV&aypebQZ^TKV8>$9^QzE?kVQ~ zgZ4^cU+CF(LfL*a4s&4EN?n7MilL$W zZo2|X1Vd7|j**@cj6KH)8`pLjBUyzJ&?+^f!5PuuG%-IqDi=19WS@1)CQmDtv%VVzskXM~Xtit>f`e0I_LCx1a1&OX+X zVF(6L1%}xM?N4Z2&Nx#VhI44K9(ONeo=OX$riS{IbDUWh3AGzQ0HJ zr}gn)IrG4gntFL^$Gvpj$8H~Izf^JSQ<`hcZGFJPJ=4Y9EXHmub}+Wt8<;ICmQ*II zbUPB_2!1~H6~2eKUj@|tDk3aSN7rywFLto#}QW1Lv=kxR18}9W;)MoKP z50_vKcI?i_uiF0LZJ)W|tkYzy>H;Dy9vz`4)tjoNMgEraX5xd5RM$C}x^T$1PuBuNZ5W^_EA0g z=KbG{T?pM(7i!%VY8EXQ0D3xf`IvSMPK4L_G-Li&BsU@TX0n(c^hC0W;S!}uYt_bO`d|(9WJ$L@$f$O)NapRLV zGnfMEif&NtaDcP~RR;%oixE^{se?+;azw5`6;lKx+lgKkUWWp-fgS|y<_g*wNn;AM zXLm#Ej8j4jvueP7&#&Wr_Yv%aB~pk8u7SMuMT5*CZzA|e3&_|!kcU7u>{%~b7aFZI z;Z2?CM^RIpz+mU*Dj0~9#NHElhR7j!MrS06XL!pg%SkxGM&KE)*4BGzH=D`>2oCU( z{^QsNC*MT;V~5%=g)Vt>!Bsg_qm(HouhkymImO27_-*|_wRI_v*lCzaCY&e z{SHnidw?{uvCbc<$pr{~&*Xvxi_p8r0^urw>uh$JKkArq?weDp*zA^j9{cnUKY8|N zuQ!=Cg>cXBCR{T+Dk|8^65;C=s9&f+y|5C$zrFN|Colc{Id}bhI*Bj^)WN9)JH15c z*opEczPe<>BJ>v$!$pI(#`8I%pfe;P`#=Tg9TlLvic@YZu1ne301C}EQ03Fo=3ZkX z;ODZU|0%qfC2K;?7|J+#*STrvo~E73Q>y80U8g;aV=knvjXEa4jFjxiWE}I&55i#@ zoE4W;P6O%4toTqZ!6xwMRte0$lhfrl0!fTW(!rb3WDx979-cYg2d@GeRf{P)&47q0 zTMkl3ak&^Yt94DZL&Jf~?DmkEXdBh3fayH8(8?6$%|?2g$C(vixvm3?y_h{j%oy3qaa)`Z2Mw&^Iq&iN< z&2fxMQHR`%!Ri#!Gz8TieC#|-y8_b#`qgRIx-o=l2qy_};<}f!O)(CPRVlDEccSZV z+YNm+%X%>T4udhq6C8Tw)^HoK`k>oc`#$KS<)EKj4tkR(jq4Io;8XI=#4%su1MX^; z@fI(Xw>9Bmu?x|2(q(6>MN|s#P=_Rx`}dM{T00p z-QC+0XPcXP>L&9f7I`w|MnUF&lNgU;$F$gvou3xZG@}!b3n4A#iCPMCT*FH7XqAW| zkUYX2%9AX`i5vY4MoPYs`$_ z+H?bX68|&bjMEGIvYQvDsccpXEn8G%=2YJE0#t5iG8&aLBAL&vj8b+=<>5#?QMqR5 zHb6|C+crw6&eja@Ru)d6rWO~9+sG9)3wZAjX<*gJ)>k1KkrPk zw7$F(vC>qFHj@crg&_mZ6}VwUqV0%d$PJXbF=c6P>M#msI9|)ymBAGR9YnlL1YTDe(`aHhCfh$?}Qo znZsE{neW#`_@WC<@8v1SCGwoTA!!Y*YqIaOIJlh^m#@ENoZ&0N$t=%WQD8J{ zVh1G$;w@|T^!D`+3=R#?8kyaiGk4zn1CpU)4lR5ww1D6nK47R=NYdFMDI;nAP_cld zUw_`=Xpl5-sF+RCk3v$Dq`6+#Jt3)wq&Y(zPL&m3yagkk4)l`L8YYp6Jor1L}4AW6gi;pQ*gYSj;sG&EEUw~1VTmP3bV zahQ9A2feP-!-umdH851PsOyQ(d51eq)^@zanro1{MP;{ze7MN;ojF_%)ehom_q z^>|%p{oH|=OH$M8+7L?3BdOuYSrd{t9SkLEb$v7>9Y7Mhk%ftsA?ZL}8=e$remFfg zl?0M)DIzqhHz;R>wa%^?`tMcz9xmH7h>;Zid8w_`nLIG{)ZhAn<|OSTu!bp&XcI|% zMiDf0T_ej*YevIneV3WMT2ig`jPA2RXlOMJ{l7Zxm@&FGZC$TZSjpk|u2GqJl;9x< zVoNp?Rmpi*vKfU+F4cvVHbYy*YQE#7eqd8!nqHVGe?m845{k#oXgCID(`!LqDt~{9uG~X=NY* zzLE?~TA%+210t&_mjz4bW!7mCaBZ|^bb%yfvY>U1QY1RsiO__{uTCQXkO6R?Ot7Rl zl?6}}WE?(poWz&3VW6OF=)$zxJTJ|aMB0*?S$oR_%?yMSuZaOzUR?T#+enJH#Ysni zEm|?9gkffySa*6aG2P;s6w1Smcvx`#ZF(q!S3pigOOp|!>kEgjts$w4pn-c;+;H#K zM~!nJBSX!qv`sCteAlMXh-IoPxf^%p{p-e^`7X^ef!rK%0J=EIg+eeC{4zFNoGxxa@)BK6Lmz3RBaxbP z<$PL`D9-ilRDtX10T;RJhjpRA^)kuerVdKaj!5M(o{VEzoUViJv@9N@DP&o}T%=~| z=tLvRvam4+!&f}U3y3WXD^C=yuXv2N7puRzZ+L-*Xf*jhnu2PuSgG%fj3&v_WS(MO zPGU^s8Srpgxr{zg+LYCCgtN+G7aiD@-ppyh$rCvT*5l`?VR=5V zvlB^({v6ZS{Jh=(GhzFVQk*&|-tdHMnG%kcge^}3uTPOL8t&;q38&bz10_RdwR1>h z6Ub>~(HokoLWf!Hd{URubQ+IRA%-xeg6mRdubD%}Tfoe+h`G zrr+ArxjA^k8k(O$I+S^$^mTb6YNb&;IwcXH8pR`3BGFXIgNV;n-ED0&5$f$UebX=c z4Gi-&5b=8L;4d(+xUm^P)&mGv%xMEx zORfNm@mZO&p+QqyM+ye~ds%!oOd)Yqtfx5n#3C1@J;mSAo~IqH1YM5-L$og%8aBOPO60T}*O7+HI>&*-azf3-&CUn%Vl=sAPSXmy> zcd82j%8~>mk_h5T%5a~GrPV%`!m+g4w@4?_fH(|5Qhd--41+OEY`tJK~lwIP^61joe2A|z6eK<8kHHR*l7V4cNtEF zHIWrhAq5H-F&onITv*a>@L7p6qaUsj%zH$&pAH+ZZ>Lcl@6)i@Nj@tDP9p zxHWp#wEK+$d+Y}0W8Pzj@LGz@xv|qu?r_iRJM8A!fiV~ivdxz9*+`aT#O(CRT0mE_ zpvom|1bBq8CBw}F<3Pv){;6Hw)DRWd?!jzGltRQgeNa>{z0H^l*d58bz>FK?@H$s&NBH5}o_Y?i=90)UPOG1z#;(S2O?#)G@mNWFM^4NxYlGXE`KXf|q_;yS z2T31MCtECF(A|N&^>#hjAHT?rU@Bs2ga;r~@ADx=fU^iL?`MB;jJfN>MVSm001q%+ z>Focv1|N zNg%+Af?I3_oA_yF@ADVs*hv5I15h>-(k9SiMdfzs8LCn4HW4+fkn3DDvVrY-TYu3A zOx*p?uyzv%p`0!VHJW2(>AfcJ^u#&o1m2kcMT=G#ZBVRtVd&?*toM{|5lxN)zh%oH zzHex~!&m5*z<6M0MLYf0H?bN|`WX-^R_#G@G!G$|j6Gyom+Y#Ei9zoVu!&7NT0huBKEgX<`zEflWHL#E0c0 z>7j^wX)$?C7Bk&J0sxQ_L5mKgR-)0RC4xKL43=nmPb@5iRxf-OijzadUZLhYsVZMW zZ~19y-D{tI9pCBAtt4n(0hfy64er2GjOy$qC+VOL{U` z3-U}ZGdW>2gAJSmDqsjsiA9X2-^i`-n0WvJFWr{cN(SO%#%o9s9KX!hOx`JPx)o= zqK0JGh4?aGi|6ZXk!2aAa@&^r?Y4efJ>x5kb@Lu8fI@*QG%HfGmA;;L7q61`(7IMs zV9JnH0CxhE*i#7ilW>ea6JDr+@h^3m*wg4i^lSMDGmAR$cb{-@E!COy4w%faYWKP} z>&upzuF4IhEGV>8^#z3{fCZI2(}E?_{x7`h?9`T5J@g2f0vH_|WOIq3DXoc?#j;!f z)kHpB6WsaMRX^HS^<$h`f9h51zL6eaj&(I0gK*xA;4%q|P-=OWfe5p*QL|AE%DjY9 zFfuZx*EKQ`4fT60!52sY|rZzI9 z8trM&JPkmuQmku$qu%|uF5R8Fl+M#qKZy7`pcmon{%|!qRlZB-1^NEOf__B`X`(yC zq*u%PhnZ3@#%I@O7ZZbKm!!pa8fG0MD)FY0I9oz;vnSGPe80uF8*y?mG05v2?H1v8 zo{THobHOwM!|^XHb=LC#Xuq?Uzb;9}T4%2q%g9ypK=R}0q&(jh1 zq*>RfJ*k;R_9RNk?MW*ahuV{7p2P|#2~NNiC88&vSki#*A3}&X+H>?f*=Wy=j9UFl zb0?j7Yi!xyf*E?^$@B{TZgj zoE0*`5^_AjG`R}Ig^sx*hGea=33nRB^C+ zaY*h|Db4KJTxRIizuD+&sg&zCS=O;N2>NPe|ed2`H^3Q5?pH zQla^MxIMs%5RchKoSS&Jy$oCf)}W5j``&ENtP9X}nDr0_7P9I;8)9y_cr(`Z zZW-&k%&0dm#v4~WwIWTs8E@@~Ay#ZEgss=BF~1q8p7_hb8lHNIqw2_6_m&+@;wDes#|PN;%HbbeIFn zyf;l~b|np(YTlRH6?C?{25Ha9zPKd1zu0=?%wI^Wb~s3pzDb?YuxTrJoFw*|Ox0ta zV0ugiA`5dHuNKKrZDlq2TvZYaM9|D_Ddnw5rOktU!!Le#4D6appX)nan}q7|fr>mh zC~7@2p&++-lSc1(1VH3^FI9j0=jnq; zAU;ZpJ`8M_kb;1CJA` zZd09ze(Hu^B$GDu{^5apB)vv?C3EK(4WWiCMX+BgR9J`}WL04u$MP$eyQdN z%uA0iL=u;dvYH1nEAZ(#O0%&C{_yygv%Y`*S(kyp79@L#XNmXMU3>lA7eDg!-DxuR$JHp{(^CMgH5P#7vmStFPpnDW!OQEBU=pvh=SW0zxVhbh>PRO9YJnXmj(F%+zH*LuI`+Cb z_K9=<N^kJ zbk6w}Y}~{(Ab%~Ug0{0y*=T7l9vi16+RmQm_3i9SkdAm6aM+o5PE&`j?d-?+c6MLC z=-Sb~q}*^Fa4hB>UsnP<6S}7Wdk%e?2(YvF-a<$!V71e>+R!dw%^O<*i^7lSm6y*p zv_qjJSEmFl;nmT)O*G_U=1#}3MCC^+QS;SHfB%bb-T35f7VxrjNFlI5{)SeOzpba# z&I+g#&o1r{7ZKv7g$NZ*BO>HYQ8>0gyd=V~KimZC6sZIEN(8;o7ICI#?jWnw*7W;u zoqwPC$nRF2zWuvzD$bBMJ@Bt(UGwP=to{AgPha@%;u9jzkhM@;f8&?Vy8C1IZhQLf zq__hoPRzSuuL-j9e21+2e24TUkYm=P$xH6r_Qb{8u6`~l{-~v`(A%$NU5i?&V>Vl+ z-DbWz)GeETr*9P@l#M+;@!iuOI`=DI|1HMYJM*mgt!Hr)^w^`>p>?>dc+zu5$+`2) z`@i<3e|>(cQX(syZgg1;Tlo4gO$ zl0^4j=LeCXyCfe?+DM1FF7s7TEddxuQ$q6aE&dXhzZ4RYQ#IO-B~pwUJuNdtsJ=Im zK#66p2x>6UdR+yKX2-LNMD_0=KvXiRuXy&^Ad@)sQ;MpuxG2h_zOf&D|Gx8Xx&F$Z z+-q)+zEaNjsUO;S@1m0mPcXMJT`rQ=B_0&wD4>&Wdi5a_ty81GNmXiHK;w9okm)B4 znZ|9d#RI~&iYkK2(Pe=nOd73*KITzAS?`lh^Ft>bArPJE!rel_2md$~1s|7N&U0eQ zO9N9*Mol#Ia9?i^b0)bjd=K$)25RXeahQgEO>vh;QuX7`!BQ7v8>&v6^dkxt;X+SS6+_u zii?X0h}87on>{jF)x)6m$j^<>s>c>$@H4P6r$@fyVuQW_s@4sPUx^=W=qVa}0^kNQ z3v11e!sT);v2_MmA|j|!fpa*LuzVD*BC`uTS`CB8duUysX2u-)mF9eswiU)_6PD3geR-Trt*Mna>&pSY+3Ep&*+pggZmLGlcH+n;@IEv*MH7kJHcN;>>-)g>snI^{dK| zmJhKacWn9%IU@Tlae_y!;_;V(DQ>MDZ86DKNIbCA@^CHnVNU2IV;};MXGc-rvFXFO zISW7Ff)A@tL?qM!a>k`TMVUt?6Zn9NBb`KE7h6f+SKJ$RjB$r;-cbKQ=229AY?5NT z8I(UP`;J*J&a+MCO|p?P20_&}iK~cUHjgq})Oj41fJh2OKN}BvaI^)k5e)kJ#(Sv_ z_x8Ieb1`Mi<)7$)5~_aP@(Mn!&-lP`H9XO-I^I-UgMGMl+C>=O8ow~;{)xFqdgDUu zM~BimaUaSy6n*Aa5+jth9@Ie)kwus?*|H*t05!G%udK{4Y7RFA7c|WCXyV|m3gM%E z!h>itSpa*4oU4QiOrT)mxT{1NJBw`o@Bv; zp2YS`D`laBo+KicAPIfas+X2zn7sH2Eh3iv6?PGa(SeVL1Y;Z-e2U^LjD^u0d4}*+ zTmm*JvX)aAmBs=$ETlOy!WW^2lOM-3ai*?%4Gk=(_u~Ba@IjH7@?@qoFyf@SGT9jj zhm@zkC}o0p=7?j{MUW8ad+i&N*XT)OJ){-+W7C|srOQWChw?9NU0gDZ$q|5=l>QeU z4ZN)QE{_z&>@CvGj9K9Yh!=N3}JCy6Hh%2s4)MqoBZMQXuj zez@mTm*>CMzZb~;){0i}epI!>FsN;o6pEi!ss8O>cwHdK-{0tUfhFF5$#x3iJQH=m z07oXTDFxdimunK=N2R$|vXX-JCH7F7aL27xGZK%L$|Wvs4tKvz5X;;V%pMJ`?8fzb0Q9T zn&OGXfEILbEY$}`U&t3LF_u0YAR!A>a2>-o(;rN=O`To4;|63zD!S|};Z3}st&C~3+E_`2Cw3sv!6{SD1@WU(Sk1GefiUb6z*B5vQrl? zZoc-GapK~O_4Zry$WA$pbc#n7YgQiF^ETeA$>mN@Bx159N)Y*3Fr}1V@biNM}5{oAaA@+2c;JJq1)aq7G^` zg)>muby4%k*2iKOJ)9a->cn1)tNb~Jx$gy zL9(rXEm1E4%-%~8{sK0?VPV$V&z4aE;g^*0J8C`Ppq-*hhTqf98p|jV;-NL?Hyrvg zY9!l9)fpR)!)3cdQfTf~%BHzj z2X*)rT?|EsExcB&)MKm^*a*u>vsVpuYdKpva%Y{8EJ0++uj)z$@1Fch8sT|ZR=KK4 zc(G0iZ(+b9>Jk=&LNSfc(Q54#UDaw>thGbCk`Il^3u9|Sc%UdV!8)R-ZOMC<``yvG zjvuht7B3~QQd>oIQ5VrXt;C7Fy-%N_{{TQA}-(+Hse%AKNLY zkRek7r}p%*nvY08frBO1wEL8Lnt5csz)PIuX1)6 zW~)%>Wq^r8I@D1$^H>}z^rv3xXhGs5wnUE+SQ+si)e{hLaE(O`KuZ@>5pAyxI|kTs z_GtL8U?j6PA~NS`$OdIoVxwYJhg~vQvgZG@#p`n4HX|rY&33AZ*YKL!IIPD!ZV0JH zizQmUh>bvnRxjh66DY`FHb|bzOekUSK4=0iEuPBM1gE8)5~PqdVOX`D+CafahB}O{ zfHy0%D2}ecSVFxZz<6I|mb&EA_=m$-w`%-V^yK;gXbsicKfd04-d%NQ{m^>rHlmS5 zjwn(664AdnTYW(k9YhyI^#_TRkBGxh-`Pg^4cC`plme|bk^_?i#ST`*akCEK(EyI$ zMsBSJS0vt_9-JL~aO2>Eg93z@<(h-WcruqvD+-$fNfyV-MJx&pGDr<6SswpD-Ynyl z)F1h33bcq$Ytf)3aQpfHjBidYOo7>2qOw>dA;IWBj1sR4mbY%KVZ_LAC&fpF;^St` z=S!olh#%g&fSE@^7cjirT^;B;4jJQsRyI7)XFK}Uwx&feC^%Y!DIz|8@2cZK%nmzX zDfGw1hA~~$wMAt$d_1L}hJ_dYDioVb1+~ge=+rB8AY&mqXdA5vNEUcuq=gYvD@GS( zvZ}V^AO*_|jn&M8vs7YpC?+LVBcRp}1VkA_zL3{Q=A?53S%qa@tfO(8%wZ*5g#a7BxkzoxLJBM{5sTDt|Wt2%sg(E9&5-K1&~sf z+!b196-;y$#z~L0aoWQQN2&_-*i|9#C494Zv2GqWOOI1}Qc|%U@MAn?0^0g$d}MbV z`I4r^<5?iD#-rbu#F1wWMk#3DT02pHT1D*?GhkC14TLka#=?MY@>?g1_4pkLYB9sk zI9ke3yU+MU4{EVCQfR{+WdDn9Za6kK+|^u(B)29{G5c^ta_BJ`P*H+(2@T{&HwhXJ z#AAbotU!-?38SOOuF>J$B_9UwfPF-bQO+r02RUbHs#$ZCWN>gW9dwO7CT?4sc(d+W&NK~0rWhDF&8{2W&={aISloN! z1u%jWduiv2ya2RU8s8N#Dj}oW@S?{Mtlq5ytw5l;gOWb}m-h8#`t57<^)>a|Lr{nY zFwi_3#a&!+!xoQ5JaJ5TH`)Hfsj^+$TNeQ;t8ENeSMg9S7>%^6$1d89?~z7@;HgYt zSWyA?5_-p{Rxv$fX@CszR)?&#i4k(O^r1D4YCrNSPV8y=vWc^TMw;%J35J#2)G8&* z3gumm3dki1Z#DagY!#VRc}rp`tiecWMOsOmi>9ZXergGRoi@~_>sDCVmO|V~|7*_K z$Dn(O8bQ3rMlhzdT9NrtEY_gI)ogw5Ln@WD0r^Pc2-F#!%f^zHfn}%5XyK_@OcGPn z3~TPzX$2WIS$U6L)@+spUvD=YaA;9mr=fBUsb#6=a2`xZYZQ6hoMh-G=ph6VBtw^{ zoETgU3u9<5%8@K(Q#k`A$Cnaq63h_mjs+B4pDVaV>k%Vi?#k`c{q*e1J1HtSIZE^; zGgmFB@riL)>ABFTs7&i7&2FS#?CoZ~!AT`G4Q<>3MAzW#qq1_kR;~4YXQi&%sbku_ z(iXAax*^v4eoejgfo%01=G{vGUV41Ww0pu_3t6!&b~?xrG1#j-8l!}0_R!D*1hD$` zRrRsn#ozZ62^&YD`gJxL#8$DRl`Q^s}G&Z(sUaFWshJq zPaX=vWb7KWoRzGMnR#NL`}iRr)pI`5gHYsh$+gD}0{h}-Y~rV(iHmhN42^I7=L%P) zh}MyBd}5-qCZqptbwa}1I?*F61ust*t<`;z`{_tXb6Y1&b?>cCK#L_YNgW$8nLaMv zm@mUv0|o0R#yc;|u+Sb0bJm{q?ge?}kzL`HG>%Z(MP}AHb1o;vmU4!f6q8*uOvR3P zWL@e~XlUrFk(vgWDtm_5sw&~r-{0TY?;P*?z@$PDDmst6SlPs_E)B3%vc$dTf>aU( z!DBLH^~rem)JK>0yprSM<&$;E3brijkRXcV?ZcDIs_NAey@cGfvUp_>F#P5XbDkU0 zOS+Q~1IXPFVo}Sbt^32kNXtoxRa!1sW3nQN)p9M@*EKLT!u}J|;@r1O@|$UZkvzT7 z{1ei4K$h6j135`FF@g^cr=^yIP`e&mzgZita>>axzWkte9`)00}28tnbm(?FS)YYH)0W=4(rYnQm zW+AmH?ae|Fy$jkba8T`Z)WqR9uu&j6ur92h$Wr}LpF;B;gA;M>H&;h0W=WL zK+@qfnkE8Mna18#PqVEBnpbC364Gjit1$PDw~Az%o5%B$?HC+CGMP`cG2y+oQ%+CE zTRc5=ZHik2e9?_Ct7Yy`)RUIbajpBDbm+ynoE&)&sxgCEP?gr31pleqEn=TaS$9XzhDz5oM;s90R7TBkO1Ncur+09^1fnkRUGtje9Nn z7Hm;=xw|arlP#o|$HZ!weNfo#I_3WL3z})~bfZ)p61HyIf^{}_hz`93BB2?}ACz?B zDa-QY;GuALPBk<(7-E=K9iv3Z8$vl2S)J+h39sh<;Y-77bPU;h&39z)HTRNQBIuX% znhmcs$C=9+F&RRjodzfb#sea0%p%?c0=YL9n3q}|6sqc|Mq;LFAfzw=03Je^t);3G z1zDFPYDTP3S4IgNEY)CoH8EhBo!j1@qtf{%2Pr)xO%UT-(u7r$IytC?j$&47G@*LT z;11J%jZ8%rUzR{jhQ2wQYhSWcOOlY!FLTnUQ1S%gka z*OQC^^PDPh*PY`qVLaVW2KOTKYV;QkI|iHSP1+d@TgAM&d@%YMZBqiD98yYF+rpQ! zIY9hof)9C3iNP{~m&{+@g8yzn((A=mlTr-=#ja?h`i`bHHi+i@+a2&YkB|KoH4s&6 zF467Y#j;|k-_vSh9}e-fn%IXQJ*^V^lHzXxH+b6efj1;6dN%BOl6GOEpNvb?O1QL> zZ3A{3l^otKTjdguS6qxLh95zYfK*j%6594OWD*1Mov?n>`Bk-#fu6VJynWA=Hi>YO4qAmZvUn`1>D89 zGfhK$FH2D_168?9EHz1)<|nsgG~K_otV5q3PbLb7Z!qBm=Ml)ilK;79(b}t#lQKUf z@Q~+_DnAVlM^Od2E)oZ#rG2-isql=MHoMy#r|dd~PzmjFdQT^o_=ZC9c>;})N4ruo zZ_MY#ff<`!Pd%wuS|#;L^S8YQAH}@>{lD{b?|S#wKl8d*9gyLoYs|_(Dh!Ypw zRl|M<<2=xgzv0H0tE$;PC(2`EhXgNKbWy76Gc#5$#iiZEPj1FHN&h z2?+pkD%He{oCk_;lKj)3vs@g!pR*7tw7*c4R|sC@1KZ0taGXD)s@>mnzxmr(s@`>b zDOE=w|DAuo=YwDT+%wmu>byzSa_C-{s-;r(jfteWqOJOw_nNq_WUE3IBzi4v)$T#N zh!VL3W%dpSXP&Qrjru@)pw;%@_x}68{JZe{jGog z%D*^u^z)Be94o`Nd(g0PBx3Ch8wO?t!zRr~4Rl?wCj$m*8N*^Z0k7|KQJpN?Xv4DX zc!y+w6W&t1rAd|Vpx;X@X=z9VuPg|DiVP^olDl%JlVynoDNc;bntHf9WKFRp9MoJJ zYZ@2=uwsS~OiQe(W$!U-dWnu$$#r5olBc!8#O@wxOvQ8q#x$TJ7*kBEQ1Q-XP_c|L z#ou`fjOn}B30jE#$tqO}_jlICjW$baGg(X+au$dYV!BmMvJH2y(tT7MXWm3-qtZ6> z1~&Q2#4_mQEq3o(vM(j#AVYwrI`m5M8o8Z$jgV5r!I^#3RuxzeupA{er>Qg%%JT3m zg`8p_`^_XnIay=*C3y6`Rgoo^pa>=|s*z8jw(F|I6IARjvr|xMPn>Sz`^sDs`SUC{ zM?#G&7v_^N19*vL^AJe+$KuBG-wk;w1ms89A74}0V&Ogz^ayCcj7^4(7^vn2EJMe4 z!ax&a0me)AuHHCaGC9t!);3XC048cV6Omk$9855g-xg%_r-Zv><6KCd++iLbW8WVl zO1Lbhz-NG&T70XLw1gZfVx=laijruI$lUTgr+8))GFLjq$#fEOxQODO!$pEzOo{Q8 z94?oMmdpf`mqod^JOzvL?=MZkBE7gI1xuN)q~PRM!JjBwadx}-&D*dM{auxK(iNtJ z?9N!JU52$Y@bYCOI^lGwmF>7HQLoPZ%H3fyquN`qN;DWcXvW2}na}-)5CyRo?akzzV?vy+ zET@~C6`2<*|H*(>{^KA*`*`vKtD}5LoOucyAg~_}g7pHv@3lJ0p7i;FI!sfWDDLIS zuaH%-8{L(>L@SLV*_>mDYPR;ci!qKOVZ;} zow~tdj)T%mI;nbalGKFMEcLvS()v~p6oUCqxhYE zifl*rf#fhe%dJ(G`M_);swhK6)eeNDUYfu#-Rc(MPXm!W z`PE;BX9_7`Cvl<}7_KRuf)|S^1CA_xSJ6pf)$^}L02VIHH=;6AX0*Y{y5e1aeIWp1 zDqp9H3`lojz8;>L>d*frJd*^#s{&H?36}Kv(=>cY1~d2ZQk@N( z+K}gL*wlt3XJ%@RjDh2VsWq7@i_Fwo`nj^mOsz>&SyW{h!_)?&OD3`^J6XtBX6Dy) zN%`tp` zTL`U`u@_6vN%uq{=NurunzLVpIY9EC=i1hdfWo1G-9Rgii6g?Q3XzG-YE8C z?Hg5Sw&sv3mOGn9SEWxk#f`3&mQr-L=8)>@+p^KMf>c-3mW{5JKE2?4G^!wS%^}r= zsb|yZs#r>QVU~@q6`|(hM%Ri^nz<+;U8_c)aXuP-=J{y!!t>Fn=84uEr@d7*$^nhw zpVsA{l9ev2d+@`zBm_j2E7^}5wS9?|e`<>c7lj#%d7Da;L-U`?xWuP1>@EoA`RT5l zMPqjB5}&)g;>y~yZF=)64^`&v2SJHV#_XiM@3ZL?xt}Zo74t(6^3`|3Yu1PfJ55;5 z*Y;QdQ!QYyrciVntzg9SS!Gy4;&~WTRP(p4dPizjtBFOSh zpM%gGK{N?)sz_bVktfbSTv_`+^Y?x7Q;W6ySpY*O`~1}HAK}-x{#Cn^j{EK;DxxY^ zSMe!qan)U~S6q?S-wx8;T~a!ev{y2*DL7m#S@6b9``aRI|a%ZQ9jXS|)3ftW)=5VF#1|NoFlRjFB;E z7MTF14#Pt5Kc&^_J?<%Jcrh?^IkM6HxMh>6V?KSgh1s=P)?fJOY8sd1L%1-$vz>!i zw{V5j#3Aj_uJg&C=7Ij?+?hxq>aeyw}IF3y!#<+tf@Xk6Lx@v+!L zXBbp>sdj3pne^JZy#AxtPSx1QVTT5--+R@DhR01Icw3|jr*ird+w;R7jhh!}f`S8c z{hGcB1iNaU5ofh)=YUYxgs4d$N7)`(FUa(#97F-{pPWf%iycb3vNz1X;|JP#fWGk3 zV<d#D**Att}sirw@eNlyBp^9+-i*9Lbbhz^4g17JNAwDc!^v+ z5H9z?S=2n}FX z)@L(Mm6M~TPK4uT_dQ%LTH6jqX={OMI)b1JSlE=eDy8^s+Og>*)32T2^kLpE$&d zfdx@0w!q-ZjQ;SC%K2^i zZP_$~zB#|`WqfH~JqJc_d)c8r2O_mEaME@XWX(f2@!KfT<65EKG^0vrdYTidq*Kg2#(>HN>PQGZ$Ow2#U%16JWMmA<0z(EWWzVO1Ptd&h4L>O*@iy?Q` z&1Sr6QL$|m(RmxZnl@E#%r=?2=@=t5br^FhYYlLSR0UTYO7P$nKO5!WYvDnYhQU5L zxf?VMw&b;Xo5hurSp(ugrdHNC2ucI3 zxE5*B$kjR|O7~_v=&-U?8i-qk581hiu3}ukFe@zs5VJG}lRlo9E~68Q4i+8gVZU>8 zkNlvni5M7+0X&_XvzGBg-c)_sf@iV=*q0gf+GchuOu26Jdot0}EJxlh2f`GAcI6y- zP5BFB$YX4pbVNh<=du~}HN@8)YbePY3WKF-&C!*Sp~u3eban>8OTeA6(rcbsvFhWC0xw7&;)`-_b9p8K`J^4atB=+Up381X@g$NYPYBjAganLU5%w|zL}hFy+sXSb0qZL@WV7jQ$KjA#Z&Z0 zGn;Z10JKI@=2>8l%>~&uiyqDx*(9tnOg)ohOVaCSiqP#^wzjJzp@8<`27~^Zlxvt7 z1DPo_2E4IbY(L4QR1*Bj6v-HNEfEtXGN0IUIc|;K1cL=+d&OR#W8b^9O=7ig?l%F< zIFY0eGJ6vO8l%Hs{iFqEg3P{-^BRvQ4&A~Pkl;WT)@rl=lpU!P0EI+j1KWuEIR2LE zX6-r5o^>!ub1hJszDNu&AV4E*?5+Fno5bVjA5kEY%9J`QRA&2=_3Aci{K)I$^SsGJ>W`OuD-tq%)LF2ozG>tFh@bUzjt2e2NxL1Y*k)O{G9muBGl1hEzb`2lR(hmciY`)wGbzWr0~49ZNTt4qzwipa)$47lYR} zfK!}uw1^9M$dcpg>k{#4ygJi?YpG~@ z1WEi*W@gkpE-WQdd1&Gn>w8d*UFAq+1XtD?cxdQDn$9^Ic0Ev#+2}exgmj(uG7=-% z4ijI33c?H6Rp*G(4LK5o>Xm9trM;Xd24LSEV82}USYW@DtFEcYR093jXl_vP4~5a# ze(f%hwGPa6zu;T2#Lk9b>RpG+rB-@v`5E1eG(ONvqiD(6TWS%F0Gy!rug6m1w@)Zg z!@8pr=F><1K;hI3KXLJ=l-0YqN|^@5nkdfRM%4z)K&6d3-JJ4_KP7nt$Gp6JJ})^t z(lDP|32RBqkp>rPkT&9e|A%==%YY0D!6#M~;Oo-Uw3{e-y^ zdgCF77yAbI#p{I7l};}$KYhe~gz2+8AnMczb=Jxb)LzeHhC)RB66P@C31M261izbO6Ux{XBz{f zlUF;p-e1^~#siLSifbS2Lr zS2yI}DwBs`-jt5RLY3Wo%nW;}%D-a@*Yl+qD_9067(u=(_lZvXH@sN$y>$_hUtWqY zDChJEJG1BjlmQ0!%GyimN=78)_p%=4OV96-T~&@k_q*D^RA;KX5^ zG&MId{XuB0%ixq(0ydSmNsXErX-lbijcmW1Q7nV`DoVpe&EWe~PyUA`=n^w#V~QUq z5SdGBa%S8Cfx|*BGIx~d8ZCiW1&?+AMbmSE>IgqlykY+pre zlB%RicwtAe4!?zn>%RSpm`+aLu7FT3Ret(s397vK)Y$D_TktF})61*%e7n%6^C$cP z0siZw@BfIVc9`X{+ynPd?Md-6WdNDO$!|Xfj{Meb=BLHXHh~Pwr&ssu+LHu<8u|M) zDFg>%Nj6{=7NHN1khz?6CF&sG)xBM*eZ-0BKGQvYat;Abs24m&!xbLx(ZriJK)WAh zrirR3@qR;U+)4>$K5dIQhREXJjU{_lU?WmkqcAORcFad()Wfd@h_oceEu`%0uhW59 z=nI*v2Ua^0Qa5RN)_<)eTgDWA1@~;yWWGjP9>>-%?QWo}@>Oc?hkUD<>A8Vwu6< zfowtefdv;?RjIq~Ys5}P^2xg_HEkJ6TYGpsb=p#9KNB4I0Y6TQiE$CKZFj*$wXi^S zq$aLKz*3jHAJroM(tJr-q;q$yh?NDIr>VujqQR4w-6v&X`?G2}*Q~?M0K!@dZj#}P zdO}w-bE&|Gl5~V{Ln_qFBM8G~196TpExsgvhozc1Rpzz*N^88%oI#5;nf2Qm#oWQE zv|I&DO%AKS(%p8+RfD7g%D~8PW?J%x(%|2amNU@FaKSAoKYzr8Qji$N2GL`99YmsG zKgtTpi$vHab~eZN?b8fAWh<7$mmZ~SmFfN$KGjDxYy=|X71a+`_}&0{_ODG zTx2zNx2I_y)ffhA)27A z`K#$ZIdPFM$_**lw?SW2Le0*aL1$D~Y61@F>iiX$&9epr>#iD(r!KYzW~)~?oVCK? z{Gp6$xIDRiH1RiQRl>3!=2;-Qw~62v-ljR8?rp-+?rPR@_TlDBeNBtyMmU=eOK>(* zcQ!4=vmrQ|@BIyPHg{$y~!P(T^>X2nCEbq?dn4HaIj$$(*?rbKp zvspO^-Oq%LJyle9fySP^C@b%5>)s=>weRe35mulY>ker_H0g>n{}YC5(`}hcyD)3A zCB6~pV7Vi!Kc8;R-}IXdIOmRX)=j7nQ8pM?5yEIAF%}EMuYg7e5kP|$TMV8$Qa-!hU+SVS@gomwL&Nk2@bGJPPMrn=Tb=`zXW0%&p>4|PxmABBZ5v1kJt1xw= zngZ(K*B%EbehdS}OC7H9HONnYK#*U!6mp!FqRvUHBb_odI_fa9y#yO~TK$Wb)?WoS zj_ciJu%TN@=-6}pb>Q#*5^(%~Ga%dEj zJ_=l)auj@zM}cF!icvJR6JZH0K5e65CF}`|;t{>O3@u2mHb4tjzeEcnvT_u*>{M|k z>2g*viZLZ?HqJa|kZT5a2>);$^s+i{w>qP_mq5(wJSO?ddn4On0ov-EvN|N78`0M& ztbWky>)PZY*jB+CBji2ZS4w=1He(*I@ysxbuT)}|?=gP_?XaTETRg3oY`l*=OdyYH zSOUL=8UlbVIN+J7D(mU2UV?yU|B^DCoi%uhs?PQ$UcpOqBakKSuRgEdB!nt0#3FM{ zN%7R|_*>)xiTv%FDib;;_P_V1-}upA{P5#nH6M9`i3&DGFn|e-nTgKDt6CL_JWj9=Fw7@(I3x^K(92A!7q3c$5K(Ncx$HRCEE`%J|IFkk)kPZVH& z>mTeZAw>SO6__9W((6C=`M>$~-?!^#hQMSqT@0qpawokcE#ZZ}dc!>hc=f(Q8!3BNz7vlCr_WN$RPi zOUkyKvYVZ{^x-H7|cPTU{T)({g`R$M;%;%`zUwTAi&8$5q@Epdzj$w{aqp}&?%!wz)-~?^U;o*= ze(Dn+_{7T;*bk{PYQ?H7s8?*q${P0x5clIUqiz^Z-%}cfcT^hpLtlOP{y%*GmtOyw z+6XugkAQP6MVG~=rPK{d`Pa{ay8lr{_vHIa>fT;a_or?zneZR}^$oxEjW53Po&V1W z;u6ZoOlb4wF>%jTblF|GEO8$=3*tT@(QQ3dMi--L7HZI0a`lHJH|Q$4k5pJUAzxWe z(UkJ-3a2R|^0B*15q@Gs#zmoZd8wvpZeRySFo40gGZ)~ccJRWD9MjDMzMVOL*Y`YJ zypBB_d zxqB%q&bk%(YbL=Jac_jUYt4(1)%$1#uL6i*^*-~jUwh;=55M;{@4RgUm50n8X8e3HpVf!&=!)72}YPSV=_$`xqv&$>! zhz0iL%L(j_rNDCUR)iuXRdWZd;7MR_ziV`aNvKleF%t)dEMu)3&n&Q-;0^OVtCZBE zm416-l4@A1SpR&Ojflu=typd-5w>QYOa$%Puw-mI&ULnfBX|)nhJctQXz}9Pmf^)^ zTp3WOSwP(;Gji(c>;mGiRVMeR{_1xN#ax0lx z^N9F86`Y@Ym4#0-az`sTAOG8T9KY{lfAiVbje_&eK{(A(UCW?}V|h!-i(@D9K6?5A zp;c;SaGJ7IHI>nQLP66?GnJ9&_jI1`h`@Z`xlYTV;k8#-8$ecXY+ZRnqG+CeA3tsS zId6|5FTRJ!``UMpwj`CYt;kCtQq9Ci!DThK7D7w6{Wc1XCIpraOlJTXRDjG{p-M&p zQ(QUd#zIR2w5XuVG(~yS-eR#+uG-!4^?D;=y=S62YRBQyq+IY}Qr%WC@^=2#W5{H_ z$=7=bRMVY0qd1>tI*T{3YI2F|t$7t|Z@g)-j9<*$C(P4#U++sPELHVbM)A}qd~9VO zk14+B70v2bajqu$ahN!sr&$Cg752?o0z>zG7ipqg-!kXuai4r4BLVRrWXQw-hyT&e~{|@hcwBn|ui@t8>ow)c+Qm zHsmMdvUmSNE;>6T*#2ZETXk-g1Ef$V({8P;KeC|f$@rnCT+ZR>;#Zd0CXxtUb{na1 z2nHCv0I@x2Oc}7BL_aup;EPAKa`o#98+PZv zAoO(awmV3_HMZQnZbb1mXPGw#m;OZMV#$oz;Qz)j__$uh%Up;S$j>-NEbQ52LA0*N zR$Zujjp4lJ6)=b|afcP8dp_p#5KBypJQv}l^7V&Sz)(cdjL7oiHyOU3a~$sV z|4|`46D~Xx`A>_5edhclpZM~-{_@VB_@(!bGQibLks)9l^xJJ|wuZD)L>?(-qcVwb z7?x{7j!I-2sPMtq2^94KsycwtZs1+k)fv2%rJ^wnC5DcPD{0Tsyqqvp0Tk) z8z#jbsbPI+vwrzh{yr1*El;gJG;IK@1--a}R{TaWh0w@9;53$I)I^mLx3T}>FTMG5 zCm%lk&HpY4PKxWN~q8_JU5E4-39Q;gj~#R%cq)58%%H-Bsa1gM z?uM!FV4k#_W|Z>A6t1AW74=Y~RM&;)q>a9%?DC~g7BP~$iHBUsH8nqGdSgrt%wl0p zVQ`2=3S%t4ztE*)rJFv+Jb>HGG0Bh{N-_3z%m~29HtQZOfR7i@V3IV|?$>PSgeL}e zUN1NRzV602d8b#J;akE*DskIiLl_>ll`O8p2I-k!U!2} zJ0lRQL_skvVzXaM@L&sx!yrH%fnYm{^u{Q9lz7NAdgHCpI{UuHnLOA(y7!}tH8l2L z+UH0QHig*b4kq@yO9Qe?b(W9vHdu2fFW&HlIV_~cuD;;V1}=C?-qyd24j_2rOiKZDP!6B7vpf}r#G znNP&Ibu6u&b6bTrqh0ZP_olj_?;?f`Q!L%yX4WU495(MIrL>=HSs(W_LTd6*ggDS} zgpYg5G}#g-cX;Po<>cN_I=R)(wc**JLNl$jK`n^qb%lR52VsSmu?jC^gLuKxm6nUpwZe-5!rngL zAQ@BMb-m7nX)9a4S|8`kn)YcZ2-?qJ`n0eKOTyULBCH#&wKG~_H{D2C z{k^l0)peuw1mcl(S$z^6%%`E+8>#eSNBAiUwa(H0hdq%ab;?K2LZ__T|8A+!Rn zDk6OP*#D=YPFZ)QY;kh6?(!PO|6%j(NVWICS*X1y?nmI+0M|bLUt<87{4TZyucIg?Uafsf0fu?m z-Tcr>4e8Oeq;0oGkzGO)`Q(Q2iT^Y|Ug%{@9BO$JEUl1c!qt${3l-DVEb-%!F0&!1 z+$Y&?vC*RYka8=nXU3?OK(UJD_KeDxTWR6(J1sNDDo;U(+ZtK0)Q(TqkF|Wco*6^C;h%cq zuF=}`AaU0-W2~CE>zOeM85q4VEO+KL$p@xkr8A$!&e8&K9WV~jpX7kdb+%F+@YJpA^~jPWl&|1)2BburktqGk*;~(lgL3`&y0a;bld-wXU4FlpTD-HpPx(9 zvFgki2f|Z7Q>#;hTFh$n$^5|iH>Uh*;YJv;Q*Z-?meV-f!=*KL1XV`|&7IMUygD|` z^+DVqljaB}g&^>NP3#nHN^>%S>)kId)%^D2= zvC~_2RmudZA^b8z1CI5z5=;OX&l|exhYTBd*z3?gDV58pVep5{lk(H z9E1!VD+zz2`4H^#*gSr-7n?q%sz?uGecdWkh^MQ6n4%F3U&Erwh{_KTtMOG)u3=wfx=BC3O7BO zDAZ}=3WeQ46waO(6ms}(WfX$AfI{P@GjXBr4KXg6^m-H*E%?W%9Rd#WX2 z$RvqD!XJ@(PWMUR9^>w7T|b-VE=4X{y4DL|O^T2_mm^m!tZPQyQL$ zYyPHWVZK(o!U_Oqf|-{Nu!YfaA&|Wm>l(qbm_(Z9b}othmXrmW<}qF1=b8riDm8v4 zO=C93u3_UFNe^UNII4+yzAY$fZGCek!Z3j64+^vaOLPC^e<}H*7-xRG?w1H|_p!zo z@(FkG^;nH15}{LO5kSWZQ~u0vCt7YfXAxD%|e(4$)>Lo-#Q|F3-3gG*=_O^KQ ze#zfgLoB=+M@k{eZmspWU;r~Au1Kw_CMm?X5c))KSmQ={xl(yxs z8i8=o)~-#Jn0&f;Zxl5z@Bao1DHYAI;`8`@&0_s(P#Q?eJ&bf-8vnhzbZb6+0jbdB7sZcu`=iV4 zzSsGINAv#ZlAe&woR+kXm`P+b%g#O5ga7(UsDPf~y!<(*0Ypyt}u-%@Ikzo$N zl%)HFwq5lb?-t&6)n9Jrgv}a71r^?KH+e0J<~nL(SN(^{>BS|sK3uGBP?&*RblF%y zHG5IOhah5>E|iffCVaC?QO!du9W(dOt<3y$`(|MQLOkHF;o!TaB;`i9M48c@oGB8! z{nw;STh%SSaB2W#pq~$)E2ZW3BUzBT(>-AVY6F%I5yrYjlSh*3y1-KtaXO*XScO{m z3vPm~-Q?2R={lSAreuh@{+C{JYURmI`PT~CQV{MOt$FSc_a?kDs->*R^{siWr+A^b ziIUb%O$4~ITKmX)*nxU04ZG2@;j|Q4*TatG!nQ~pgs3H9hl#@)qwqgi*l|8kxE^){ z6S5w5ls=tY)%CCg?_@pfs62Gsm&*Tp(!vhKMXkZeBdH>f8nm>tV=~6NdcVdKjX)gtH1m&J;5|`jo{C4_wgDN{*8J zh75osmMdz?%*XtXLL{F|Cp5BL#$n>EUQWCzeO0ugqbTT1|FZGrS1dm4vl(i_{m*C~ zajjM?KBPX>`jXJ$1I3eX+tA^>su4N0G5PiBVTa+kYOZ7guY;kr-_r--0=>!oa z(pOl!0Ou>OU4Zmx?c&Q~c`@0y_1c9kyt!YXRSa_njG;+x9k~O=y$oR?BYMl1H2gi5 z!kBi}doQh)>0$nh&@*o`&dz871vR^`6qnh$Kq3i?{Q zD~mkwuptYwbhWZbY+kM8)454&u_22}XR{%z(ih3V)+_^`{aM;krt6ko5!6P5#X;ka zmG)-q%`Ry%-027YFfq3Yi(7? zmyNz?M&axhj4ataE36WK<tbf`+7%)CweD-3Z+>8EjKY%>Khmq! z_YsmO-M=@PU<2vI0-fRyk7FSCMQ&0 zN)Y`yYq|t2GkVQyu7)&?H51i@vKFeceX?MARD>a~tg?6*^MjDk-;9ErUo{ zG`_Rdqe3g49Selpwj&mxzrX@w22-b|ry>bkH4_(*+j)UO$X#M;yXr?8y(Y>e0{dV- zQ7G!>Qbk=bZ&PQbT+U%%ERZYcUG<~hptQ5yT9~2vmozwJN!TDyYl5(B$WDF$m}WDx zB`SV|G#QT$NRwHiWn@UU-~cE>ABgS6Z2b(>s}eBCC;EMNH~>oz&# ze8##>UX4{+x5-+&wAjEbgxMW8BXU5ODEh)stlQ-OcsBVTLddbyCja3xEl$43FJ_L8 zuZgEPq9}&yH3mcIbYGpI+5%}V&uww+Z1}l;59Wy2)S23(P}`gkv1-VMubrGju906- ziW5`Z3=as!hEMnAl`TVuAJt6511*|neoz;PE1GE#YEh}{zS)>XGh;kcG{Xi{`LpwB z*RpPC7n9nF0=A8jU#wOmc5O~G6dux)Ce{fI2kH{Yr_J8r(!c^=V*RgP%m6Bv<& z?oaxNx~m+~28&&onixN8=CgQuU|@ku6V*_t%1{n}HdZ%pPc{ek$*6bnD$i7dDjg=ElW95XCMA)u<LSVMV}H}wk9gL9At%>&o9)L=pjzzn!nB= zWeZphHmcdy50S#AzBmzb)%lX>VI{ID!)$6YJ;3a2815--SH`*wP7eY0SUw!FS7ym$ z?0_TRKqyuP0cMimj1RqvS+q{)>^Wl)`^sM>K~(El+V7X+GM1+|+ilxsNj()fk}zyU zIr?tQJC5lrC&$7zNzUxk=ve;v<2ALITALgfzbffqSan}Zo_6oHA)q}~@A1c(ah@z{ zrZ-)YmNgrpX6x(+YdZ={R_iP8!l=Qj(A@@?RMhT}$H19>8!USht7)K+^y>)@R(Yp{ z>U^yRYZ)7=!Ja3|j<1@sFi1&RrC?cpu$DUkFK|$8o=Mbf$F7@q&V} zcLv5ccDA^Vv{QlW#;V6x)?CH-&=D(8u(Nc0$`7)_8zX2=?u@g1W1UMBd7W7zM{r5W z+h??4WzAJ^$;whNf=fj4GHc6BO%lOme)mrmaJL(^yw?7BQl*DE)i~I%dlt*AuCNw! z+x_D0)XkHg5-v4aAG@iSn)1Nrkw95VUF!M$mR;#+TI5Tr=O?uhU*+9LWT|B#A8Pax zm%mS2EKJeKMv<__>ptwuES9m7eZq-tH0C^X%Drvwz%ZU7HzHB8r$wsgry2_mcKd7f zv=J?=qb5@&vn21#ExlALoXWeI`VM4G6aZv$GikVzo6Kt=UmPKLmb^r+j6S$kjxX|S z>NiXG@wE}Y9+*>vVYTX75?5s*gNnW$65g^^oR>^dhjHNja>By~L`&JYQgw~>>Sk_e zDnIgDA6cw*A7s9xhJ&vOj(Y}5QbLAuP&SdEbZ-ta-Fpuul>M>L)0p)HO6$dt(_+Zn zlm|w#h7Xw!R%eEXjH0p8+mO?JJhtkLvv6Ym! zi`g7urU*H?%_yc_SB>ZYFBkL%amlQ9J?k(oAGwVy6Bz1oLZ=`nfS2Jk!Bk&k)k~@L zLD8u4l=sM3QOgXJY-+zEo(o@13v!ZqD7S`zAEaZ`cHpg<33(Dg4UjQU>WiogA{9^q zqsT?AZq~lL-=%6^@6AX&oe-uS4XREBa5mGQz8avX)$L5y!MHfkT^fT5(;5u9&L$n< zS$hyxdF9k1>s%criWLZ|t-QXCrTtZx)}Dp3vbjyuhRx z>Y!lf%u+pLSpP|ewbPV~2t0>CaE;P$+WfXOQV*{UlXOdeGG|S?l}%!OdZKhE^z|Ht zyzSnUxQT}lzI+I=0$=r+&EN-oK2wwk|5>-U0kPPa%`o7pUY9lixx?2D6p>=H!)wMv z!qHULJHV|c&63mByC&M{K_Wh zvKdjb1sIb8v-1PJN$5z=oxCk^7LL6P#^_Qmv*&&otR}qVH!k!h^$-qiAs;O%fUPt+ zDV^F0x~G$El?rMVWz^`Hu2AWuKb*9tsKfYMSv%{>Rp^=wTgNHNRUF<`x28#H1xZE9 zy7_G{Td-nvZ#`L?us;~&S#Jv7oYcU^vdPd+(tS*lG9~#jl%#5ZO1eDJaRl{c=r_w? z{+5hDkCcj2*@RpyQ}A0+F3qB1=sk?cl&$Nt{SR(rkPu_!-vq+@ zn>6UG)7#V`Py?X+vEPjSH1oT*0-cm?gg{#You)dH4_6ZBQbR#J;wk{ey}D}20v{9dg!8W%&-k+m?{V_ za68#HeW)X2TlKNEQr$o*iUP%?X<%pjp6EPD^2dBL^dYaM#Eevw=CA&7@L-|Kpi<8^ z(HsBaO3DbBsg#q@LQT)QbCAtS#%Hrlt_x@7PT9D+;KZsr-sq4@2e9+ASw|R~=1t)- z$rq)rF?;-1y-^vdoi5taj2OOx*qDy08f{) zDM$t5sSZPSi#(pc;!tmcSMbNka3||(niR$842m3!AUB0VXc?EMWx1`_z+_&(UY6UU zqRNd|n3R{o>1rpJi?@xk>em?~>fT;60htl4W@OeG1&Hz?k7>vte4*d&)r1@TOdobD zl*=bcOo1u!gAYB)Z-D=(8!!;+_S!%KdNo)np#b~=8W+ZGP%00D4dspml?UX6az_H? zhOq++z|r-7H_#dwXql{cxqd;yX5{XQ?GV`l3Nufp5#vTwCmX;Aas+dMx2c1$5$t>I zT)!*+na-vzt>JK?HaDOZP@5YNrW$4N-fb_l2Q#iqKr86?l{^%%0&bKmgu=h*ZO--U z)GGx4>H4sUxoqjXJ2_#eK-+L3y8(ZYrUL ztMO@ZW{LZ*w}RRl)VgMZsao__)pObp8DhMa1AyAHPBO#yq-=BW5I}|0^R$noR*h6_ z=p*GBZkas8Y}#SMI=N?OLk<)f949^_qE0Sj4Y$p3jpuxvs%b`FB=-S_HZ&G9DupkB z^HGkE+8T4HI^>i1n4s+NXk{?A1+&x_?w}&Bezt`b;9Igy3;o2SGsPB#M-! zdBmIl`soK2Yxza_k-z7&`+;Dr#F#*K?HowPFx`Td6Ty1)!^_6hs0TNJxKpHC{%7;- zo37*Nmhh=4oFocv^+0qN&cjmZ1H(7_l0#ZccblnAVu}CBoHNo2b$YZT}NRQro=C> zw%*)&cfb9EQwg02DW$6e*(Ctxm$&G1(gZ~>P`e0Z&1OO`66sz| z3N5A!9)q=CJ(tWDSq086HZ%KPL}veLk=cZ-R1}$g>l`98q1`=qIb^9#ko7$%kVz~` zmPBSA8HiqpY808Fd5bnYGE+dXd}J0Xmyy|Y@%kAevuTUWm`|AU$ZR9Z-6ONm;*6q_ zDUZyi7Er_8Y|0|DsWLK~F)op_6hRRpvrw}7$ZVrWX4AkyuZqlOEHW!GXptGgp&~Or zs>qDEaWFCqeLE2b0a;~aR<^L_kr^$^ix`N^kP^5+kr{r+G{1EA2@|9b^F=zUL4nQY zsB|)$whwEHI_87PgIO*zqg#uX5au{CQ?WcCHHJmu;|!76zgc8v^1~c-CY6^;m3EN2> zrUwmOHb(iX!_kseUnyGR5I~!^!8C)BXjm6^`!{ zIV)7mnmgO+&C2L64aYDx3ZDqaBsEMR!ltj#>l3{#AspKxkBCX0Yat%mV;~%}s%1Dv zC52;KJRFWTS!+#gfEp{#aJ_4B?n>Oe?~!DjXXO)2eXHH|7-Kn9a5jR*JSE9MdSP zen*F6M)VD$)dm?+h76*7$QFTGI5yq0MKy~;HS8iBOJs#D9IGPHDfzTr%w@np5snc! zBPkY+X<8uwPk3ccuZ3eOufi^sI}%hLkQ3@V5-5k&nYEQS(Di;b2LlF*a15;AMHsoe z;!uTS0g4cg4K<=V%r{2(z}NL~tUVNt&17x4qhdtchrXGp9xX(fg=75 zaO?sL$4Wp92!&(nW&i>e-uAM1paxY>!2!As&Be^AUduKM06`o-W8CA4#^5+&FRG!$ zXAmxwrbS~aVFtF0#wa!CQ!xsYm>{)7WKl$8V#SuEQ!5P6Z@NI5wo&0SX$ldIT@7FZ zFv$qkLNpepiKZ1OiBIrhBGi{g)%Z(o+K}9`Qnl!}Mf8ksyFW{x%Fj({-calc*t(!M@sOuhSXr!5-m z6yp>|%%PA08{nxGoeOG@>@JMfd<@Ln&}e1*WR@7~1j@E~5LKPch9FEfY?#f;%1Ghl zvOyRYl7EwN5M~B#+So*qHt4Z=$Z4!;i+Jl_%(Vx};y(poR*7IBa3c_Zy zEoTnGuwg?%7_TiCgrRCQojt>UHsfw0176I2A!_0zn@2Ps**tY~%K9551)WU%OZ92l zGEFxs!bkHUHG0uRg_zDOwNy!*Lu>|XE8s#FtcPh?|KK4?C$ehRdI<`3lG+^{3sx%S zu_%;xe+vl%n@HxAcxsBN0ZnR+2*N&BPsUl~^?xF)SX(O(=eViDN63iTcwvLJ9R}z( zru+vsRq)g{Rj~4{MQi=^OPsylgal(ev%9gz)^0n6#7Vn90(=I6dLqL&ADGW_I|VVN z?;v6ESWDFLc8YPv6M&{czEYl=`JwPw)!`qe-Lm=B#G!IrE%7_678s zE|GGbK^+rN$R&?#Die%~&w6MA(-dayYz|0f!nahg6ec~P7d6v^_$OHtpV78dPk9uE!lbm@G){-BK6}{6n0aVf_~!M34bbihv&EVcMF*NWHAhm7+SC)u4l*#WP3vu< z8@v{sIbcYNG7Kg#(m+uPF?|#$W>&h8O%Vm`tOyBqDl}Peuqs^Dco2Nm17HpsA$iuO zpBOqC?a3{WCvUn{D%v)Cjr%ODuPn$u6(EK^61vm_ln?EZfFy&Hh0X(t92)>91{AEe z?#TF@Kd=%ESd(-jHY=v0zlJP>Znl;95->Z1dn814?d1>~wEt{Von1b+Hp-c}i^{9y z3bSzLPmHtfe)C;|?z^UT??I>Cnru#tk2UI0Dal_)oSk@FVcB6aHY{z>!(Epue$ z!2EEg*G|qP`5h_|9h3a^d^K%huOH)eUZw9nwGZe!wGPi29KW%Nmyhs0C%X%Ok8N7$ z{%*+DjE}z9$ai=o#*bs0`f2`5&7$*hDBq!P{>Hy4Crdkriue4{rxwY;vtQ;1HFJ1Q z8DwYl^^Q4dt@-pVb6MjcQ2*cEx4fRWRP=ftsg?~!UyAFSXWCQ@7woa5K4o+OP?g^G zv%D>&?Wgm_?w<56jfg=X9T-jiXsEiKm)OyjnCVOM`@xV6x)`o0B1U=toR5r_=V=q} z^Z6pfM!)U|;G;wU@N^vk5>WPrwmoYuBG5KBNJRXseH|Kk{^?Lbx+4r8D_LwUg?aAM z3N5=YlKiMBnkU`gv-CG~b97FLj^F@|gVB^Y*)B9lIf9FOKsFE9%4V{A1`aK`^25$B z#;{_ZGjJ$LZN!-$-sGHlFN`|KnfIu~IrA>Q2F`Rsa?g+-q~X-uq6

for SnapshotConfig { - fn from(p: P) -> Self { - Self { path: p.into() } - } -} - /// Description of the transport protocol (for online execution). #[derive(Debug, Clone)] pub enum Transport { @@ -187,6 +182,8 @@ pub struct OnlineConfig { pub pallets: Vec, /// Transport config. pub transport: Transport, + /// Lookout for child-keys, and scrape them as well if set to true. + pub scrape_children: bool, } impl OnlineConfig { @@ -205,10 +202,17 @@ impl Default for OnlineConfig { at: None, state_snapshot: None, pallets: vec![], + scrape_children: true, } } } +impl From for OnlineConfig { + fn from(s: String) -> Self { + Self { transport: s.into(), ..Default::default() } + } +} + /// Configuration of the state snapshot. #[derive(Clone)] pub struct SnapshotConfig { @@ -222,6 +226,12 @@ impl SnapshotConfig { } } +impl From for SnapshotConfig { + fn from(s: String) -> Self { + Self::new(s) + } +} + impl Default for SnapshotConfig { fn default() -> Self { Self { path: Path::new("SNAPSHOT").into() } @@ -242,6 +252,8 @@ pub struct Builder { hashed_blacklist: Vec>, /// connectivity mode, online or offline. mode: Mode, + /// The state version being used. + state_version: StateVersion, } // NOTE: ideally we would use `DefaultNoBound` here, but not worth bringing in frame-support for @@ -254,6 +266,7 @@ impl Default for Builder { hashed_prefixes: Default::default(), hashed_keys: Default::default(), hashed_blacklist: Default::default(), + state_version: StateVersion::V1, } } } @@ -306,7 +319,6 @@ impl Builder { prefix: StorageKey, at: B::Hash, ) -> Result, &'static str> { - const PAGE: u32 = 512; let mut last_key: Option = None; let mut all_keys: Vec = vec![]; let keys = loop { @@ -320,6 +332,7 @@ impl Builder { "rpc get_keys failed" })?; let page_len = page.len(); + all_keys.extend(page); if page_len < PAGE as usize { @@ -362,11 +375,12 @@ impl Builder { .cloned() .map(|key| ("state_getStorage", rpc_params![key, at])) .collect::>(); + let values = client.batch_request::>(batch).await.map_err(|e| { log::error!( target: LOG_TARGET, "failed to execute batch: {:?}. Error: {:?}", - chunk_keys, + chunk_keys.iter().map(|k| HexDisplay::from(k)).collect::>(), e ); "batch failed." @@ -693,7 +707,7 @@ impl Builder { // inject manual key values. if !self.hashed_key_values.is_empty() { - log::debug!( + log::info!( target: LOG_TARGET, "extending externalities with {} manually injected key-values", self.hashed_key_values.len() @@ -703,7 +717,7 @@ impl Builder { // exclude manual key values. if !self.hashed_blacklist.is_empty() { - log::debug!( + log::info!( target: LOG_TARGET, "excluding externalities from {} keys", self.hashed_blacklist.len() @@ -795,6 +809,12 @@ impl Builder { self } + /// The state version to use. + pub fn state_version(mut self, version: StateVersion) -> Self { + self.state_version = version; + self + } + /// overwrite the `at` value, if `mode` is set to [`Mode::Online`]. /// /// noop if `mode` is [`Mode::Offline`] @@ -808,8 +828,13 @@ impl Builder { /// Build the test externalities. pub async fn build(self) -> Result { + let state_version = self.state_version; let (top_kv, child_kv) = self.pre_build().await?; - let mut ext = TestExternalities::new_with_code(Default::default(), Default::default()); + let mut ext = TestExternalities::new_with_code_and_state( + Default::default(), + Default::default(), + state_version, + ); info!(target: LOG_TARGET, "injecting a total of {} top keys", top_kv.len()); for (k, v) in top_kv { @@ -1165,4 +1190,21 @@ mod remote_tests { std::fs::remove_file(d.path()).unwrap(); } } + + #[tokio::test] + async fn can_build_child_tree() { + init_logger(); + Builder::::new() + .mode(Mode::Online(OnlineConfig { + // transport: "wss://kusama-rpc.polkadot.io".to_owned().into(), + transport: "ws://kianenigma-archive:9924".to_owned().into(), + // transport: "ws://localhost:9999".to_owned().into(), + pallets: vec!["Crowdloan".to_owned()], + ..Default::default() + })) + .build() + .await + .expect(REMOTE_INACCESSIBLE) + .execute_with(|| {}); + } } diff --git a/utils/frame/try-runtime/cli/src/lib.rs b/utils/frame/try-runtime/cli/src/lib.rs index ae7a1c3ae87c..92721228c929 100644 --- a/utils/frame/try-runtime/cli/src/lib.rs +++ b/utils/frame/try-runtime/cli/src/lib.rs @@ -493,6 +493,7 @@ impl State { transport: uri.to_owned().into(), state_snapshot: snapshot_path.as_ref().map(SnapshotConfig::new), pallets: pallets.clone().unwrap_or_default(), + scrape_children: true, at, })) .inject_hashed_key( From a8b6a5d6a378425b6ec24369579155422fe04dc8 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Fri, 4 Mar 2022 18:22:52 +0200 Subject: [PATCH 563/695] BEEFY and GRANDPA protocol names should use full genesis hash (#10974) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit std::fmt::Display shows formats as reduced hash (e.g. 0xb0a8…dafe) Use hex::encode to format full hash. Signed-off-by: acatangiu --- Cargo.lock | 4 ++ client/beefy/Cargo.toml | 2 + client/beefy/src/lib.rs | 51 +++++++++++++++++-- client/finality-grandpa/Cargo.toml | 3 ++ .../finality-grandpa/src/communication/mod.rs | 6 +-- .../src/communication/tests.rs | 43 ++++++++++++++++ 6 files changed, 103 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bfe180174026..db6edfa81d53 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -484,6 +484,7 @@ dependencies = [ "beefy-primitives", "fnv", "futures 0.3.19", + "hex", "log 0.4.14", "parity-scale-codec", "parking_lot 0.12.0", @@ -494,6 +495,7 @@ dependencies = [ "sc-network-gossip", "sc-network-test", "sc-utils", + "serde", "sp-api", "sp-application-crypto", "sp-arithmetic", @@ -8525,6 +8527,7 @@ dependencies = [ "fork-tree", "futures 0.3.19", "futures-timer", + "hex", "log 0.4.14", "parity-scale-codec", "parking_lot 0.12.0", @@ -8539,6 +8542,7 @@ dependencies = [ "sc-network-test", "sc-telemetry", "sc-utils", + "serde", "serde_json", "sp-api", "sp-application-crypto", diff --git a/client/beefy/Cargo.toml b/client/beefy/Cargo.toml index f23b3f5dc4a6..1cd0f1fd50d8 100644 --- a/client/beefy/Cargo.toml +++ b/client/beefy/Cargo.toml @@ -10,6 +10,7 @@ description = "BEEFY Client gadget for substrate" [dependencies] fnv = "1.0.6" futures = "0.3" +hex = "0.4.2" log = "0.4" parking_lot = "0.12.0" thiserror = "1.0" @@ -39,4 +40,5 @@ beefy-primitives = { version = "4.0.0-dev", path = "../../primitives/beefy" } sp-tracing = { version = "5.0.0", path = "../../primitives/tracing" } sc-network-test = { version = "0.8.0", path = "../network/test" } +serde = "1.0.136" strum = { version = "0.23", features = ["derive"] } diff --git a/client/beefy/src/lib.rs b/client/beefy/src/lib.rs index 9b2bf383df8e..29d74c15dd59 100644 --- a/client/beefy/src/lib.rs +++ b/client/beefy/src/lib.rs @@ -53,13 +53,13 @@ pub(crate) mod beefy_protocol_name { /// Name of the notifications protocol used by BEEFY. /// /// Must be registered towards the networking in order for BEEFY to properly function. - pub fn standard_name( + pub fn standard_name>( genesis_hash: &Hash, chain_spec: &Box, ) -> std::borrow::Cow<'static, str> { let chain_prefix = match chain_spec.fork_id() { - Some(fork_id) => format!("/{}/{}", genesis_hash, fork_id), - None => format!("/{}", genesis_hash), + Some(fork_id) => format!("/{}/{}", hex::encode(genesis_hash), fork_id), + None => format!("/{}", hex::encode(genesis_hash)), }; format!("{}{}", chain_prefix, NAME).into() } @@ -190,3 +190,48 @@ where worker.run().await } + +#[cfg(test)] +mod tests { + use super::*; + use sc_chain_spec::{ChainSpec, GenericChainSpec}; + use serde::{Deserialize, Serialize}; + use sp_core::H256; + use sp_runtime::{BuildStorage, Storage}; + + #[derive(Debug, Serialize, Deserialize)] + struct Genesis(std::collections::BTreeMap); + impl BuildStorage for Genesis { + fn assimilate_storage(&self, storage: &mut Storage) -> Result<(), String> { + storage.top.extend( + self.0.iter().map(|(a, b)| (a.clone().into_bytes(), b.clone().into_bytes())), + ); + Ok(()) + } + } + + #[test] + fn beefy_protocol_name() { + let chain_spec = GenericChainSpec::::from_json_file(std::path::PathBuf::from( + "../chain-spec/res/chain_spec.json", + )) + .unwrap() + .cloned_box(); + + // Create protocol name using random genesis hash. + let genesis_hash = H256::random(); + let expected = format!("/{}/beefy/1", hex::encode(genesis_hash)); + let proto_name = beefy_protocol_name::standard_name(&genesis_hash, &chain_spec); + assert_eq!(proto_name.to_string(), expected); + + // Create protocol name using hardcoded genesis hash. Verify exact representation. + let genesis_hash = [ + 50, 4, 60, 123, 58, 106, 216, 246, 194, 188, 139, 193, 33, 212, 202, 171, 9, 55, 123, + 94, 8, 43, 12, 251, 187, 57, 173, 19, 188, 74, 205, 147, + ]; + let expected = + "/32043c7b3a6ad8f6c2bc8bc121d4caab09377b5e082b0cfbbb39ad13bc4acd93/beefy/1".to_string(); + let proto_name = beefy_protocol_name::standard_name(&genesis_hash, &chain_spec); + assert_eq!(proto_name.to_string(), expected); + } +} diff --git a/client/finality-grandpa/Cargo.toml b/client/finality-grandpa/Cargo.toml index 34feadac5e41..9733f35bd0e9 100644 --- a/client/finality-grandpa/Cargo.toml +++ b/client/finality-grandpa/Cargo.toml @@ -19,6 +19,7 @@ dyn-clone = "1.0" fork-tree = { version = "3.0.0", path = "../../utils/fork-tree" } futures = "0.3.19" futures-timer = "3.0.1" +hex = "0.4.2" log = "0.4.8" parking_lot = "0.12.0" rand = "0.8.4" @@ -58,5 +59,7 @@ sc-network-test = { version = "0.8.0", path = "../network/test" } sp-keyring = { version = "6.0.0", path = "../../primitives/keyring" } substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } sp-tracing = { version = "5.0.0", path = "../../primitives/tracing" } + +serde = "1.0.136" tokio = "1.15" tempfile = "3.1.0" diff --git a/client/finality-grandpa/src/communication/mod.rs b/client/finality-grandpa/src/communication/mod.rs index 809e721448bd..9c05774fffdf 100644 --- a/client/finality-grandpa/src/communication/mod.rs +++ b/client/finality-grandpa/src/communication/mod.rs @@ -77,13 +77,13 @@ pub mod grandpa_protocol_name { /// Name of the notifications protocol used by GRANDPA. /// /// Must be registered towards the networking in order for GRANDPA to properly function. - pub fn standard_name( + pub fn standard_name>( genesis_hash: &Hash, chain_spec: &Box, ) -> std::borrow::Cow<'static, str> { let chain_prefix = match chain_spec.fork_id() { - Some(fork_id) => format!("/{}/{}", genesis_hash, fork_id), - None => format!("/{}", genesis_hash), + Some(fork_id) => format!("/{}/{}", hex::encode(genesis_hash), fork_id), + None => format!("/{}", hex::encode(genesis_hash)), }; format!("{}{}", chain_prefix, NAME).into() } diff --git a/client/finality-grandpa/src/communication/tests.rs b/client/finality-grandpa/src/communication/tests.rs index c135f58a2eec..e41d21fc0684 100644 --- a/client/finality-grandpa/src/communication/tests.rs +++ b/client/finality-grandpa/src/communication/tests.rs @@ -535,3 +535,46 @@ fn peer_with_higher_view_leads_to_catch_up_request() { futures::executor::block_on(test); } + +fn local_chain_spec() -> Box { + use sc_chain_spec::{ChainSpec, GenericChainSpec}; + use serde::{Deserialize, Serialize}; + use sp_runtime::{BuildStorage, Storage}; + + #[derive(Debug, Serialize, Deserialize)] + struct Genesis(std::collections::BTreeMap); + impl BuildStorage for Genesis { + fn assimilate_storage(&self, storage: &mut Storage) -> Result<(), String> { + storage.top.extend( + self.0.iter().map(|(a, b)| (a.clone().into_bytes(), b.clone().into_bytes())), + ); + Ok(()) + } + } + let chain_spec = GenericChainSpec::::from_json_file(std::path::PathBuf::from( + "../chain-spec/res/chain_spec.json", + )) + .unwrap(); + chain_spec.cloned_box() +} + +#[test] +fn grandpa_protocol_name() { + let chain_spec = local_chain_spec(); + + // Create protocol name using random genesis hash. + let genesis_hash = sp_core::H256::random(); + let expected = format!("/{}/grandpa/1", hex::encode(genesis_hash)); + let proto_name = grandpa_protocol_name::standard_name(&genesis_hash, &chain_spec); + assert_eq!(proto_name.to_string(), expected); + + // Create protocol name using hardcoded genesis hash. Verify exact representation. + let genesis_hash = [ + 53, 79, 112, 97, 119, 217, 39, 202, 147, 138, 225, 38, 88, 182, 215, 185, 110, 88, 8, 53, + 125, 210, 158, 151, 50, 113, 102, 59, 245, 199, 221, 240, + ]; + let expected = + "/354f706177d927ca938ae12658b6d7b96e5808357dd29e973271663bf5c7ddf0/grandpa/1".to_string(); + let proto_name = grandpa_protocol_name::standard_name(&genesis_hash, &chain_spec); + assert_eq!(proto_name.to_string(), expected); +} From 7a6d95937d62e1b16ea990fb42ac8d5bf7bda16d Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Fri, 4 Mar 2022 21:00:45 +0100 Subject: [PATCH 564/695] Move weight constants to own mod (#10980) * Move block+ext weights to own mod Signed-off-by: Oliver Tale-Yazdi * Unused import Signed-off-by: Oliver Tale-Yazdi --- frame/support/src/weights.rs | 14 +++--- frame/support/src/weights/block_weights.rs | 46 +++++++++++++++++++ .../support/src/weights/extrinsic_weights.rs | 46 +++++++++++++++++++ 3 files changed, 99 insertions(+), 7 deletions(-) create mode 100644 frame/support/src/weights/block_weights.rs create mode 100644 frame/support/src/weights/extrinsic_weights.rs diff --git a/frame/support/src/weights.rs b/frame/support/src/weights.rs index 6c2e693eb476..b3ed42bb45fc 100644 --- a/frame/support/src/weights.rs +++ b/frame/support/src/weights.rs @@ -127,6 +127,8 @@ //! - Ubuntu 19.10 (GNU/Linux 5.3.0-18-generic x86_64) //! - rustc 1.42.0 (b8cedc004 2020-03-09) +mod block_weights; +mod extrinsic_weights; mod paritydb_weights; mod rocksdb_weights; @@ -156,19 +158,17 @@ pub type Weight = u64; /// For example: FRAME System, FRAME Executive, our FRAME support libraries, etc... pub mod constants { use super::Weight; - use crate::parameter_types; pub const WEIGHT_PER_SECOND: Weight = 1_000_000_000_000; pub const WEIGHT_PER_MILLIS: Weight = WEIGHT_PER_SECOND / 1000; // 1_000_000_000 pub const WEIGHT_PER_MICROS: Weight = WEIGHT_PER_MILLIS / 1000; // 1_000_000 pub const WEIGHT_PER_NANOS: Weight = WEIGHT_PER_MICROS / 1000; // 1_000 - parameter_types! { - /// Importing a block with 0 txs takes ~5 ms - pub const BlockExecutionWeight: Weight = 5 * WEIGHT_PER_MILLIS; - /// Executing 10,000 System remarks (no-op) txs takes ~1.26 seconds -> ~125 µs per tx - pub const ExtrinsicBaseWeight: Weight = 125 * WEIGHT_PER_MICROS; - } + // Expose the Block and Extrinsic base weights. + pub use super::{ + block_weights::constants::BlockExecutionWeight, + extrinsic_weights::constants::ExtrinsicBaseWeight, + }; // Expose the DB weights. pub use super::{ diff --git a/frame/support/src/weights/block_weights.rs b/frame/support/src/weights/block_weights.rs new file mode 100644 index 000000000000..4db90f0c0207 --- /dev/null +++ b/frame/support/src/weights/block_weights.rs @@ -0,0 +1,46 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +pub mod constants { + use frame_support::{ + parameter_types, + weights::{constants, Weight}, + }; + + parameter_types! { + /// Importing a block with 0 Extrinsics. + pub const BlockExecutionWeight: Weight = 5_000_000 * constants::WEIGHT_PER_NANOS; + } + + #[cfg(test)] + mod test_weights { + use frame_support::weights::constants; + + /// Checks that the weight exists and is sane. + // NOTE: If this test fails but you are sure that the generated values are fine, + // you can delete it. + #[test] + fn sane() { + let w = super::constants::BlockExecutionWeight::get(); + + // At least 100 µs. + assert!(w >= 100 * constants::WEIGHT_PER_MICROS, "Weight should be at least 100 µs."); + // At most 50 ms. + assert!(w <= 50 * constants::WEIGHT_PER_MILLIS, "Weight should be at most 50 ms."); + } + } +} diff --git a/frame/support/src/weights/extrinsic_weights.rs b/frame/support/src/weights/extrinsic_weights.rs new file mode 100644 index 000000000000..158ba99c6a4c --- /dev/null +++ b/frame/support/src/weights/extrinsic_weights.rs @@ -0,0 +1,46 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +pub mod constants { + use frame_support::{ + parameter_types, + weights::{constants, Weight}, + }; + + parameter_types! { + /// Executing a NO-OP `System::remarks` Extrinsic. + pub const ExtrinsicBaseWeight: Weight = 125_000 * constants::WEIGHT_PER_NANOS; + } + + #[cfg(test)] + mod test_weights { + use frame_support::weights::constants; + + /// Checks that the weight exists and is sane. + // NOTE: If this test fails but you are sure that the generated values are fine, + // you can delete it. + #[test] + fn sane() { + let w = super::constants::ExtrinsicBaseWeight::get(); + + // At least 10 µs. + assert!(w >= 10 * constants::WEIGHT_PER_MICROS, "Weight should be at least 10 µs."); + // At most 1 ms. + assert!(w <= constants::WEIGHT_PER_MILLIS, "Weight should be at most 1 ms."); + } + } +} From 1ac8f633a19bbe9836cfc0d4d68fc8a700e145f9 Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Fri, 4 Mar 2022 20:20:19 +0000 Subject: [PATCH 565/695] add block usage logs to system pallet (#10940) * add block usage logs to system pallet * add Debug * use % instead of default Debug impl * change formatting * revert --- frame/system/src/lib.rs | 34 +++++++++++++++++++++++++ primitives/arithmetic/src/per_things.rs | 7 +++-- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/frame/system/src/lib.rs b/frame/system/src/lib.rs index 3b4de0c472c4..9b30e7b45227 100644 --- a/frame/system/src/lib.rs +++ b/frame/system/src/lib.rs @@ -1272,6 +1272,40 @@ impl Pallet { /// Remove temporary "environment" entries in storage, compute the storage root and return the /// resulting header for this block. pub fn finalize() -> T::Header { + log::debug!( + target: "runtime::system", + "[{:?}] length: {} (normal {}%, op: {}%, mandatory {}%) / normal weight: {} ({}%) \ + / op weight {} ({}%) / mandatory weight {} ({}%)", + Self::block_number(), + Self::all_extrinsics_len(), + sp_runtime::Percent::from_rational( + Self::all_extrinsics_len(), + *T::BlockLength::get().max.get(DispatchClass::Normal) + ).deconstruct(), + sp_runtime::Percent::from_rational( + Self::all_extrinsics_len(), + *T::BlockLength::get().max.get(DispatchClass::Operational) + ).deconstruct(), + sp_runtime::Percent::from_rational( + Self::all_extrinsics_len(), + *T::BlockLength::get().max.get(DispatchClass::Mandatory) + ).deconstruct(), + Self::block_weight().get(DispatchClass::Normal), + sp_runtime::Percent::from_rational( + *Self::block_weight().get(DispatchClass::Normal), + T::BlockWeights::get().get(DispatchClass::Normal).max_total.unwrap_or(Bounded::max_value()) + ).deconstruct(), + Self::block_weight().get(DispatchClass::Operational), + sp_runtime::Percent::from_rational( + *Self::block_weight().get(DispatchClass::Operational), + T::BlockWeights::get().get(DispatchClass::Operational).max_total.unwrap_or(Bounded::max_value()) + ).deconstruct(), + Self::block_weight().get(DispatchClass::Mandatory), + sp_runtime::Percent::from_rational( + *Self::block_weight().get(DispatchClass::Mandatory), + T::BlockWeights::get().get(DispatchClass::Mandatory).max_total.unwrap_or(Bounded::max_value()) + ).deconstruct(), + ); ExecutionPhase::::kill(); AllExtrinsicsLen::::kill(); diff --git a/primitives/arithmetic/src/per_things.rs b/primitives/arithmetic/src/per_things.rs index fbd45bb69324..c3ccca56ca33 100644 --- a/primitives/arithmetic/src/per_things.rs +++ b/primitives/arithmetic/src/per_things.rs @@ -24,7 +24,6 @@ use crate::traits::{ }; use codec::{CompactAs, Encode}; use num_traits::{Pow, SaturatingAdd, SaturatingSub}; -use sp_debug_derive::RuntimeDebug; use sp_std::{ convert::{TryFrom, TryInto}, fmt, ops, @@ -425,7 +424,7 @@ macro_rules! implement_per_thing { /// #[doc = $title] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] - #[derive(Encode, Copy, Clone, PartialEq, Eq, codec::MaxEncodedLen, PartialOrd, Ord, RuntimeDebug, scale_info::TypeInfo)] + #[derive(Encode, Copy, Clone, PartialEq, Eq, codec::MaxEncodedLen, PartialOrd, Ord, sp_std::fmt::Debug, scale_info::TypeInfo)] pub struct $name($type); /// Implementation makes any compact encoding of `PerThing::Inner` valid, @@ -847,7 +846,7 @@ macro_rules! implement_per_thing { #[cfg(test)] mod $test_mod { use codec::{Encode, Decode}; - use super::{$name, Saturating, RuntimeDebug, PerThing}; + use super::{$name, Saturating, PerThing}; use crate::traits::Zero; #[test] @@ -871,7 +870,7 @@ macro_rules! implement_per_thing { assert!(<$upper_type>::from($max) * <$upper_type>::from($max) < <$upper_type>::max_value()); } - #[derive(Encode, Decode, PartialEq, Eq, RuntimeDebug)] + #[derive(Encode, Decode, PartialEq, Eq, Debug)] struct WithCompact { data: T, } From 3f8dea20381042fcd66386fb30f404df665e2915 Mon Sep 17 00:00:00 2001 From: driemworks Date: Fri, 4 Mar 2022 20:56:14 -0500 Subject: [PATCH 566/695] update runtime storage, update chain extension --- .../pallets/iris-assets/src/lib.rs | 51 +++++++++++------ .../pallets/iris-session/src/lib.rs | 4 +- .../runtime/src/chain-extension.rs | 55 ------------------- bin/node-template/runtime/src/lib.rs | 43 ++++++++++++--- 4 files changed, 72 insertions(+), 81 deletions(-) delete mode 100644 bin/node-template/runtime/src/chain-extension.rs diff --git a/bin/node-template/pallets/iris-assets/src/lib.rs b/bin/node-template/pallets/iris-assets/src/lib.rs index 3a3ef3061eb1..a46e70b0a5fc 100644 --- a/bin/node-template/pallets/iris-assets/src/lib.rs +++ b/bin/node-template/pallets/iris-assets/src/lib.rs @@ -95,7 +95,7 @@ pub mod pallet { T::Balance, T::AccountId> >, - ValueQuery + ValueQuery, >; /// A collection of asset ids @@ -109,15 +109,23 @@ pub mod pallet { ValueQuery, >; - /// Store the map associating owned CID to a specific asset ID - /// - /// asset_admin_accountid -> CID -> asset id + // TODO: Combine the following maps into one using a custom struct + /// map asset id to admin account #[pallet::storage] #[pallet::getter(fn asset_class_ownership)] - pub(super) type AssetClassOwnership = StorageDoubleMap< + pub(super) type AssetClassOwnership = StorageMap< _, Blake2_128Concat, + T::AssetId, T::AccountId, + ValueQuery, + >; + + // map asset id to cid + #[pallet::storage] + #[pallet::getter(fn metadata)] + pub(super) type Metadata = StorageMap< + _, Blake2_128Concat, T::AssetId, Vec, @@ -246,7 +254,7 @@ pub mod pallet { #[pallet::compact] amount: T::Balance, ) -> DispatchResult { let who = ensure_signed(origin)?; - ensure!(AssetClassOwnership::::contains_key(who.clone(), asset_id.clone()), Error::::NoSuchOwnedContent); + // ensure!(AssetClassOwnership::::contains_key(asset_id.clone()), Error::::NoSuchOwnedContent); let new_origin = system::RawOrigin::Signed(who.clone()).into(); let beneficiary_accountid = T::Lookup::lookup(beneficiary.clone())?; @@ -272,11 +280,6 @@ pub mod pallet { #[pallet::compact] amount: T::Balance, ) -> DispatchResult { let current_owner = ensure_signed(origin)?; - - ensure!( - AssetAccess::::contains_key(current_owner.clone(), asset_id.clone()), - Error::::InvalidAssetId, - ); let new_origin = system::RawOrigin::Signed(current_owner.clone()).into(); >::transfer( @@ -285,6 +288,11 @@ pub mod pallet { target.clone(), amount.clone(), )?; + + let target_account = T::Lookup::lookup(target)?; + // get asset owner (could be different than origin) + let asset_id_owner = >::get(asset_id.clone()); + >::insert(target_account.clone(), asset_id.clone(), asset_id_owner.clone()); Ok(()) } @@ -332,9 +340,15 @@ pub mod pallet { >::create(new_origin, id.clone(), admin.clone(), balance) .map_err(|_| Error::::CantCreateAssetClass)?; - + + >::insert(id.clone(), cid.clone()); + // let new_new_origin = system::RawOrigin::Signed(who).into(); + // >::set_metadata( + // new_new_origin, id.clone(), "cid".as_bytes().to_vec(), cid.clone(), 0, + // )?; + let which_admin = T::Lookup::lookup(admin.clone())?; - >::insert(which_admin, id.clone(), cid.clone()); + >::insert(id.clone(), which_admin); >::mutate(|ids| ids.push(id.clone())); Self::deposit_event(Event::AssetClassCreated(id.clone())); @@ -354,11 +368,14 @@ pub mod pallet { asset_id: T::AssetId, ) -> DispatchResult { let who = ensure_signed(origin)?; - ensure!(>::contains_key(asset_owner.clone(), asset_id.clone()), Error::::NoSuchOwnedContent); - let cid = >::get( - asset_owner.clone(), - asset_id.clone(), + + let asset_id_owner = >::get(asset_id.clone()); + ensure!( + asset_id_owner == asset_owner.clone(), + Error::::NoSuchOwnedContent ); + + let cid: Vec = >::get(asset_id.clone()); >::mutate( |queue| queue.push(DataCommand::PinCID( who.clone(), diff --git a/bin/node-template/pallets/iris-session/src/lib.rs b/bin/node-template/pallets/iris-session/src/lib.rs index 0ba6e168da08..16f1b7438cba 100644 --- a/bin/node-template/pallets/iris-session/src/lib.rs +++ b/bin/node-template/pallets/iris-session/src/lib.rs @@ -898,8 +898,8 @@ impl Pallet { let expected_pub_key = >::get(requestor.clone()); ensure!(public_key == expected_pub_key, Error::::BadOrigin); - let cid = >::asset_class_ownership( - owner.clone(), asset_id.clone() + let cid = >::metadata( + asset_id.clone() ); ensure!( owner.clone() == >::asset_access(requestor.clone(), asset_id.clone()), diff --git a/bin/node-template/runtime/src/chain-extension.rs b/bin/node-template/runtime/src/chain-extension.rs deleted file mode 100644 index ed33b78d912f..000000000000 --- a/bin/node-template/runtime/src/chain-extension.rs +++ /dev/null @@ -1,55 +0,0 @@ -// use codec::Encode; -// use frame_support::log::{ -// error, -// trace, -// }; -// use pallet_contracts::chain_extension::{ -// ChainExtension, -// Environment, -// Ext, -// InitState, -// RetVal, -// SysConfig, -// UncheckedFrom, -// }; -// use sp_runtime::DispatchError; - -// pub struct IrisExtension; - -// impl ChainExtension for IrisExtension { -// fn call( -// func_id: u32, -// env: Environment, -// ) -> Result -// where -// ::AccountId: -// UncheckedFrom<::Hash> + AsRef<[u8]>, -// { -// match func_id { -// 1 => { -// let mut env = env.buf_in_buf_out(); -// let arg: [u8; 32] = env.read_as()?; -// // call to transfer assets should go here -// // crate::IrisAssets::trandsfer(&arg); -// // let random_slice = random_seed.encode(); -// trace!( -// target: "runtime", -// "[ChainExtension]|call|func_id:{:}", -// func_id -// ); -// // env.write(&random_slice, false, None).map_err(|_| { -// // DispatchError::Other("ChainExtension failed to call transfer_assets") -// // })?; -// } -// _ => { -// error!("Called an unregistered `func_id`: {:}", func_id); -// return Err(DispatchError::Other("Unimplemented func_id")) -// } -// } -// Ok(RetVal::Converging(0)) -// } - -// fn enabled() -> bool { -// true -// } -// } diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index 9b5952569cf3..3383d0aad869 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -834,13 +834,22 @@ impl ChainExtension for IrisExtension { UncheckedFrom<::Hash> + AsRef<[u8]>, { match func_id { + // transfer_asset 1 => { let mut env = env.buf_in_buf_out(); - let caller_account: AccountId = env.read_as()?; - let target: AccountId = env.read_as()?; - let asset_id: u32 = env.read_as()?; - let amount: u64 = env.read_as()?; + + // let caller_account: AccountId = env.read_as()?; + // let target: AccountId = env.read_as()?; + // let asset_id: u32 = env.read_as()?; + // let amount: u64 = env.read_as()?; + + let (caller_account, target, asset_id, amount): (AccountId, AccountId, u32, u64) = env.read_as()?; + // let target: AccountId = env.read_as()?; + // let asset_id: u32 = env.read_as()?; + // let amount: u64 = env.read_as()?; + let origin: Origin = system::RawOrigin::Signed(caller_account).into(); + crate::Iris::transfer_asset( origin, sp_runtime::MultiAddress::Id(target), asset_id, amount, )?; @@ -849,11 +858,31 @@ impl ChainExtension for IrisExtension { "[ChainExtension]|call|func_id:{:}", func_id ); - // env.write(&random_slice, false, None).map_err(|_| { + }, + // mint assets + 2 => { + let mut env = env.buf_in_buf_out(); + + let caller_account: AccountId = env.read_as()?; + let beneficiary: AccountId = env.read_as()?; + let asset_id: u32 = env.read_as()?; + let amount: u64 = env.read_as()?; + + let origin: Origin = system::RawOrigin::Signed(caller_account).into(); + + crate::Iris::mint( + origin, sp_runtime::MultiAddress::Id(beneficiary), asset_id, amount, + )?; + trace!( + target: "runtime", + "[ChainExtension]|call|func_id:{:}", + func_id + ); + }, + _ => { + // env.write(&random_slice, false, None).map_err(|_| { // DispatchError::Other("ChainExtension failed to call transfer_assets") // })?; - } - _ => { error!("Called an unregistered `func_id`: {:}", func_id); return Err(DispatchError::Other("Unimplemented func_id")) } From 8e69505c1962ca99a2deda59c7876b9659667e7f Mon Sep 17 00:00:00 2001 From: driemworks Date: Fri, 4 Mar 2022 21:06:14 -0500 Subject: [PATCH 567/695] cleanup chain ext --- bin/node-template/runtime/src/lib.rs | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index 3383d0aad869..01a15e3972f6 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -837,17 +837,7 @@ impl ChainExtension for IrisExtension { // transfer_asset 1 => { let mut env = env.buf_in_buf_out(); - - // let caller_account: AccountId = env.read_as()?; - // let target: AccountId = env.read_as()?; - // let asset_id: u32 = env.read_as()?; - // let amount: u64 = env.read_as()?; - let (caller_account, target, asset_id, amount): (AccountId, AccountId, u32, u64) = env.read_as()?; - // let target: AccountId = env.read_as()?; - // let asset_id: u32 = env.read_as()?; - // let amount: u64 = env.read_as()?; - let origin: Origin = system::RawOrigin::Signed(caller_account).into(); crate::Iris::transfer_asset( @@ -862,12 +852,7 @@ impl ChainExtension for IrisExtension { // mint assets 2 => { let mut env = env.buf_in_buf_out(); - - let caller_account: AccountId = env.read_as()?; - let beneficiary: AccountId = env.read_as()?; - let asset_id: u32 = env.read_as()?; - let amount: u64 = env.read_as()?; - + let (caller_account, target, asset_id, amount): (AccountId, AccountId, u32, u64) = env.read_as()?; let origin: Origin = system::RawOrigin::Signed(caller_account).into(); crate::Iris::mint( From 32a4fe01f110a755bf22eb8f803cdfd7052d4f8b Mon Sep 17 00:00:00 2001 From: Liu-Cheng Xu Date: Sat, 5 Mar 2022 15:51:19 +0800 Subject: [PATCH 568/695] Fix the undeterministic storage proof recorded for the same execution (#10915) * Add a test case for the determinism of recorded proof * Replace HashMap with BTreeMap for the actual proof records * cargo +nightly fmt --all * Store the trie nodes in BTreeSet for StorageProof * Nit * Revert the BTreeMap changes and sort when converting to storage proof * Remove PartialEq from StorageProof * Remove unnecessary change * Add `compare` method to StorageProof * FMT * Dummy change to trigger CI * Use `BTreeSet` for StorageProof and keep using `Vec` for CompactProof * Update comment on `iter_nodes` * Revert `PartialEq` removal --- client/executor/src/native_executor.rs | 5 +- client/offchain/src/api/http.rs | 10 ++-- .../state-machine/src/proving_backend.rs | 49 +++++++++++++++---- primitives/trie/src/storage_proof.rs | 31 ++++++------ primitives/trie/src/trie_stream.rs | 2 +- 5 files changed, 65 insertions(+), 32 deletions(-) diff --git a/client/executor/src/native_executor.rs b/client/executor/src/native_executor.rs index 363ea474a7e4..669780f2a4b6 100644 --- a/client/executor/src/native_executor.rs +++ b/client/executor/src/native_executor.rs @@ -462,8 +462,9 @@ impl RuntimeSpawn for RuntimeInstanceSpawn { // https://github.com/paritytech/substrate/issues/7354 let mut instance = match module.new_instance() { Ok(instance) => instance, - Err(error) => - panic!("failed to create new instance from module: {}", error), + Err(error) => { + panic!("failed to create new instance from module: {}", error) + }, }; match instance diff --git a/client/offchain/src/api/http.rs b/client/offchain/src/api/http.rs index bc8f81f25a64..2a7514116cb5 100644 --- a/client/offchain/src/api/http.rs +++ b/client/offchain/src/api/http.rs @@ -432,8 +432,9 @@ impl HttpApi { ); }, None => {}, // can happen if we detected an IO error when sending the body - _ => - tracing::error!(target: "offchain-worker::http", "State mismatch between the API and worker"), + _ => { + tracing::error!(target: "offchain-worker::http", "State mismatch between the API and worker") + }, } }, @@ -443,8 +444,9 @@ impl HttpApi { self.requests.insert(id, HttpApiRequest::Fail(error)); }, None => {}, // can happen if we detected an IO error when sending the body - _ => - tracing::error!(target: "offchain-worker::http", "State mismatch between the API and worker"), + _ => { + tracing::error!(target: "offchain-worker::http", "State mismatch between the API and worker") + }, }, None => { diff --git a/primitives/state-machine/src/proving_backend.rs b/primitives/state-machine/src/proving_backend.rs index 934f08492dee..eeffcc8e4705 100644 --- a/primitives/state-machine/src/proving_backend.rs +++ b/primitives/state-machine/src/proving_backend.rs @@ -158,15 +158,13 @@ impl ProofRecorder { /// Convert into a [`StorageProof`]. pub fn to_storage_proof(&self) -> StorageProof { - let trie_nodes = self - .inner - .read() - .records - .iter() - .filter_map(|(_k, v)| v.as_ref().map(|v| v.to_vec())) - .collect(); - - StorageProof::new(trie_nodes) + StorageProof::new( + self.inner + .read() + .records + .iter() + .filter_map(|(_k, v)| v.as_ref().map(|v| v.to_vec())), + ) } /// Reset the internal state. @@ -393,6 +391,7 @@ mod tests { proving_backend::create_proof_check_backend, trie_backend::tests::test_trie, InMemoryBackend, }; + use sp_core::H256; use sp_runtime::traits::BlakeTwo256; use sp_trie::PrefixedMemoryDB; @@ -426,7 +425,6 @@ mod tests { #[test] fn proof_is_invalid_when_does_not_contains_root() { - use sp_core::H256; let result = create_proof_check_backend::( H256::from_low_u64_be(1), StorageProof::empty(), @@ -582,4 +580,35 @@ mod tests { assert!(backend.storage(b"doesnotexist2").unwrap().is_none()); check_estimation(&backend); } + + #[test] + fn proof_recorded_for_same_execution_should_be_deterministic() { + let storage_changes = vec![ + (H256::random(), Some(b"value1".to_vec())), + (H256::random(), Some(b"value2".to_vec())), + (H256::random(), Some(b"value3".to_vec())), + (H256::random(), Some(b"value4".to_vec())), + (H256::random(), Some(b"value5".to_vec())), + (H256::random(), Some(b"value6".to_vec())), + (H256::random(), Some(b"value7".to_vec())), + (H256::random(), Some(b"value8".to_vec())), + ]; + + let proof_recorder = + ProofRecorder:: { inner: Arc::new(RwLock::new(ProofRecorderInner::default())) }; + storage_changes + .clone() + .into_iter() + .for_each(|(key, val)| proof_recorder.record(key, val)); + let proof1 = proof_recorder.to_storage_proof(); + + let proof_recorder = + ProofRecorder:: { inner: Arc::new(RwLock::new(ProofRecorderInner::default())) }; + storage_changes + .into_iter() + .for_each(|(key, val)| proof_recorder.record(key, val)); + let proof2 = proof_recorder.to_storage_proof(); + + assert_eq!(proof1, proof2); + } } diff --git a/primitives/trie/src/storage_proof.rs b/primitives/trie/src/storage_proof.rs index 79da009ae151..f6139584dbba 100644 --- a/primitives/trie/src/storage_proof.rs +++ b/primitives/trie/src/storage_proof.rs @@ -18,7 +18,7 @@ use codec::{Decode, Encode}; use hash_db::{HashDB, Hasher}; use scale_info::TypeInfo; -use sp_std::vec::Vec; +use sp_std::{collections::btree_set::BTreeSet, iter::IntoIterator, vec::Vec}; // Note that `LayoutV1` usage here (proof compaction) is compatible // with `LayoutV0`. use crate::LayoutV1 as Layout; @@ -32,13 +32,13 @@ use crate::LayoutV1 as Layout; /// the serialized nodes and performing the key lookups. #[derive(Debug, PartialEq, Eq, Clone, Encode, Decode, TypeInfo)] pub struct StorageProof { - trie_nodes: Vec>, + trie_nodes: BTreeSet>, } impl StorageProof { /// Constructs a storage proof from a subset of encoded trie nodes in a storage backend. - pub fn new(trie_nodes: Vec>) -> Self { - StorageProof { trie_nodes } + pub fn new(trie_nodes: impl IntoIterator>) -> Self { + StorageProof { trie_nodes: BTreeSet::from_iter(trie_nodes) } } /// Returns a new empty proof. @@ -46,7 +46,7 @@ impl StorageProof { /// An empty proof is capable of only proving trivial statements (ie. that an empty set of /// key-value pairs exist in storage). pub fn empty() -> Self { - StorageProof { trie_nodes: Vec::new() } + StorageProof { trie_nodes: BTreeSet::new() } } /// Returns whether this is an empty proof. @@ -54,14 +54,14 @@ impl StorageProof { self.trie_nodes.is_empty() } - /// Create an iterator over trie nodes constructed from the proof. The nodes are not guaranteed - /// to be traversed in any particular order. + /// Create an iterator over encoded trie nodes in lexicographical order constructed + /// from the proof. pub fn iter_nodes(self) -> StorageProofNodeIterator { StorageProofNodeIterator::new(self) } /// Convert into plain node vector. - pub fn into_nodes(self) -> Vec> { + pub fn into_nodes(self) -> BTreeSet> { self.trie_nodes } @@ -138,12 +138,13 @@ impl CompactProof { expected_root, )?; Ok(( - StorageProof::new( - db.drain() - .into_iter() - .filter_map(|kv| if (kv.1).1 > 0 { Some((kv.1).0) } else { None }) - .collect(), - ), + StorageProof::new(db.drain().into_iter().filter_map(|kv| { + if (kv.1).1 > 0 { + Some((kv.1).0) + } else { + None + } + })), root, )) } @@ -171,7 +172,7 @@ impl CompactProof { /// An iterator over trie nodes constructed from a storage proof. The nodes are not guaranteed to /// be traversed in any particular order. pub struct StorageProofNodeIterator { - inner: > as IntoIterator>::IntoIter, + inner: > as IntoIterator>::IntoIter, } impl StorageProofNodeIterator { diff --git a/primitives/trie/src/trie_stream.rs b/primitives/trie/src/trie_stream.rs index 7a5c7d003e03..a17d7c25e1b8 100644 --- a/primitives/trie/src/trie_stream.rs +++ b/primitives/trie/src/trie_stream.rs @@ -26,8 +26,8 @@ use hash_db::Hasher; use sp_std::vec::Vec; use trie_root; -#[derive(Default, Clone)] /// Codec-flavored TrieStream. +#[derive(Default, Clone)] pub struct TrieStream { /// Current node buffer. buffer: Vec, From 41acb92d947b713b1deeb256283eef0fd719bca9 Mon Sep 17 00:00:00 2001 From: driemworks Date: Sat, 5 Mar 2022 15:15:57 -0500 Subject: [PATCH 569/695] create iris ledger pallet --- .../pallets/iris-ledger/Cargo.toml | 54 +++++ .../pallets/iris-ledger/README.md | 1 + .../pallets/iris-ledger/src/benchmarking.rs | 20 ++ .../pallets/iris-ledger/src/lib.rs | 163 +++++++++++++++ .../pallets/iris-ledger/src/mock.rs | 135 +++++++++++++ .../pallets/iris-ledger/src/tests.rs | 191 ++++++++++++++++++ bin/node-template/runtime/src/lib.rs | 43 +++- 7 files changed, 605 insertions(+), 2 deletions(-) create mode 100644 bin/node-template/pallets/iris-ledger/Cargo.toml create mode 100644 bin/node-template/pallets/iris-ledger/README.md create mode 100644 bin/node-template/pallets/iris-ledger/src/benchmarking.rs create mode 100644 bin/node-template/pallets/iris-ledger/src/lib.rs create mode 100644 bin/node-template/pallets/iris-ledger/src/mock.rs create mode 100644 bin/node-template/pallets/iris-ledger/src/tests.rs diff --git a/bin/node-template/pallets/iris-ledger/Cargo.toml b/bin/node-template/pallets/iris-ledger/Cargo.toml new file mode 100644 index 000000000000..ae017ba59de4 --- /dev/null +++ b/bin/node-template/pallets/iris-ledger/Cargo.toml @@ -0,0 +1,54 @@ +[package] +authors = ['Substrate DevHub '] +edition = '2018' +name = 'pallet-iris-assets' +version = "1.0.0" +license = "Unlicense" +homepage = "https://substrate.dev" +repository = "https://github.com/substrate-developer-hub/substrate-node-template/" +description = "FRAME pallet template for Iris Asset management." +readme = "README.md" +publish = false + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ + "derive", +] } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } + +sp-io = { default-features = false, version = "4.0.0-dev", path = "../../../../primitives/io" } +sp-std = { default-features = false, version = "4.0.0-dev", path = "../../../../primitives/std" } +sp-core = { default-features = false, version = "4.0.0-dev", path = "../../../../primitives/core" } +sp-runtime = { default-features = false, version = "4.0.0-dev", path = "../../../../primitives/runtime" } +sp-keystore = { version = "0.10.0-dev", path = "../../../../primitives/keystore", optional = true } + +frame-support = { default-features = false, version = "4.0.0-dev", path = "../../../../frame/support" } +frame-system = { default-features = false, version = "4.0.0-dev", path = "../../../../frame/system" } +frame-benchmarking = { default-features = false, version = "4.0.0-dev", path = "../../../../frame/benchmarking", optional = true } +log = { version = "0.4.14", default-features = false } + +pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../../../../frame/balances" } +pallet-assets = { version = "4.0.0-dev", default-features = false, path = "../../../../frame/assets" } + +[features] +default = ['std'] +std = [ + 'codec/std', + 'scale-info/std', + 'frame-support/std', + 'frame-system/std', + 'frame-benchmarking/std', + 'sp-io/std', + 'sp-std/std', + 'sp-keystore/std', + 'sp-runtime/std', + 'log/std', + 'pallet-assets/std', + 'pallet-balances/std', +] + +runtime-benchmarks = ["frame-benchmarking"] +try-runtime = ["frame-support/try-runtime"] diff --git a/bin/node-template/pallets/iris-ledger/README.md b/bin/node-template/pallets/iris-ledger/README.md new file mode 100644 index 000000000000..8d751a42207d --- /dev/null +++ b/bin/node-template/pallets/iris-ledger/README.md @@ -0,0 +1 @@ +License: Unlicense \ No newline at end of file diff --git a/bin/node-template/pallets/iris-ledger/src/benchmarking.rs b/bin/node-template/pallets/iris-ledger/src/benchmarking.rs new file mode 100644 index 000000000000..2117c048cfbd --- /dev/null +++ b/bin/node-template/pallets/iris-ledger/src/benchmarking.rs @@ -0,0 +1,20 @@ +//! Benchmarking setup for pallet-template + +use super::*; + +#[allow(unused)] +use crate::Pallet as Template; +use frame_benchmarking::{benchmarks, impl_benchmark_test_suite, whitelisted_caller}; +use frame_system::RawOrigin; + +benchmarks! { + do_something { + let s in 0 .. 100; + let caller: T::AccountId = whitelisted_caller(); + }: _(RawOrigin::Signed(caller), s) + verify { + assert_eq!(Something::::get(), Some(s)); + } +} + +impl_benchmark_test_suite!(Template, crate::mock::new_test_ext(), crate::mock::Test); diff --git a/bin/node-template/pallets/iris-ledger/src/lib.rs b/bin/node-template/pallets/iris-ledger/src/lib.rs new file mode 100644 index 000000000000..7f2d38eeea2c --- /dev/null +++ b/bin/node-template/pallets/iris-ledger/src/lib.rs @@ -0,0 +1,163 @@ +#![cfg_attr(not(feature = "std"), no_std)] + +//! # Iris Storage Pallet +//! +//! +//! ## Overview +//! +//! ### Goals +//! The Iris module provides functionality for creation and management of storage assets and access management +//! +//! ### Dispatchable Functions +//! +//! #### Permissionless functions +//! * create_storage_asset +//! +//! #### Permissioned Functions +//! * mint_tickets +//! + +use scale_info::TypeInfo; +use codec::{Encode, Decode}; +use frame_support::{ + ensure, + traits::{Currency, LockIdentifier, LockableCurrency, WithdrawReasons}, +}; +use frame_system::{ + self as system, ensure_signed, +}; + +use sp_core::offchain::OpaqueMultiaddr; + +use sp_runtime::{ + RuntimeDebug, + traits::StaticLookup, +}; +use sp_std::{ + vec::Vec, + prelude::*, +}; + +type IRIS_LOCK_ID: LockIdentifier: *b"irislock"; + +type BalanceOf = + <::IrisCurrency as Currency<::AccountId>>::Balance; + +pub use pallet::*; + +#[cfg(test)] +mod mock; + +#[cfg(test)] +mod tests; + +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; + +#[frame_support::pallet] +pub mod pallet { + use super::*; + use frame_support::{ + dispatch::DispatchResult, + pallet_prelude::*, + traits::ExistenceRequirement::KeepAlive, + }; + use frame_system::{ + pallet_prelude::*, + }; + use sp_core::offchain::OpaqueMultiaddr; + use sp_std::{str, vec::Vec}; + + #[pallet::config] + /// the module configuration trait + pub trait Config: frame_system::Config { + /// The overarching event type + type Event: From> + IsType<::Event>; + /// the overarching call type + type Call: From>; + /// the currency used + type IrisCurrency: LockableCurrency; + } + + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet(_); + + // TODO: Move this to it's own pallet? + #[pallet::storage] + #[pallet::getter(fn iris_ledger)] + pub(super) type IrisLedger = StorageDoubleMap< + _, + Blake2_128Concat, + T::AccountId, + Blake2_128Concat, + LockIdentifier, + T::Balance, + ValueQuery, + >; + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + /// some amount of currency was locked + Locked(T::AccountId, BalanceOf), + /// currency was unlocked by an account + Unlocked(T::AccountId), + } + + #[pallet::error] + pub enum Error { + + } + + #[pallet::call] + impl Pallet { + + #[pallet::weight(100)] + pub fn lock_currency( + origin: OriginFor, + amount: T::IrisCurrency, + cid : Vec, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + // let lock_id: LockIdentifier = cid; + T::IrisCurrency::set_lock( + IRIS_LOCK_ID, + &who, + amount.clone(), + WithdrawReasons::all(), + ); + >::insert(who.clone(), IRIS_LOCK_ID, amount.clone()); + Self::deposit_event(Event::Locked(who, amount)); + Ok(()) + } + + #[pallet::weight(100)] + pub fn unlock_currency_and_transfer( + origin: OriginFor, + target: T::AccountId, + cid: Vec, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + // we assume locked amount equals amount in IrisLedger... for now + // let lock_id: LockIdentifier = cid; + let amount = >::get(who.clone(), IRIS_LOCK_ID); + T::IrisCurrency::remove_lock(IRIS_LOCK_ID, &who); + + let new_origin = system::RawOrigin::Signed(who).into(); + T::IrisCurrency::transfer( + new_origin, + target, + amount, + KeepAlive, + )?; + Self::deposit_event(Event::Unlocked(who)); + Ok(()) + } + + } +} + +impl Pallet { + +} \ No newline at end of file diff --git a/bin/node-template/pallets/iris-ledger/src/mock.rs b/bin/node-template/pallets/iris-ledger/src/mock.rs new file mode 100644 index 000000000000..194c86cbc067 --- /dev/null +++ b/bin/node-template/pallets/iris-ledger/src/mock.rs @@ -0,0 +1,135 @@ +// #![cfg(test)] +// use crate::{self as pallet_iris_assets, Config}; +// use frame_support::{construct_runtime, parameter_types}; +// use sp_core::{ +// Pair, +// H256, +// sr25519::{ +// Signature, +// }, +// }; +// use sp_runtime::{ +// testing::{Header, TestXt}, +// traits::{BlakeTwo256, Extrinsic as ExtrinsicT, IdentityLookup, IdentifyAccount, Verify}, +// }; + +// type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +// type Block = frame_system::mocking::MockBlock; + +// // Configure a mock runtime to test the pallet. +// construct_runtime!( +// pub enum Test where +// Block = Block, +// NodeBlock = Block, +// UncheckedExtrinsic = UncheckedExtrinsic, +// { +// System: frame_system::{Pallet, Call, Config, Storage, Event}, +// Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, +// Assets: pallet_assets::{Pallet, Storage, Event}, +// Iris: pallet_iris_assets::{Pallet, Call, Storage, Event}, +// } +// ); + +// parameter_types! { +// pub const BlockHashCount: u64 = 250; +// pub const SS58Prefix: u8 = 42; +// } + +// impl frame_system::Config for Test { +// type BaseCallFilter = frame_support::traits::Everything; +// type BlockWeights = (); +// type BlockLength = (); +// type DbWeight = (); +// type Origin = Origin; +// type Call = Call; +// type Index = u64; +// type BlockNumber = u64; +// type Hash = H256; +// type Hashing = BlakeTwo256; +// type AccountId = sp_core::sr25519::Public; +// type Lookup = IdentityLookup; +// type Header = Header; +// type Event = Event; +// type BlockHashCount = BlockHashCount; +// type Version = (); +// type PalletInfo = PalletInfo; +// type AccountData = pallet_balances::AccountData; +// type OnNewAccount = (); +// type OnKilledAccount = (); +// type SystemWeightInfo = (); +// type SS58Prefix = (); +// type OnSetCode = (); +// } + +// // SS58Prefix +// parameter_types! { +// pub const ExistentialDeposit: u64 = 1; +// } + +// impl pallet_balances::Config for Test { +// type MaxLocks = (); +// type MaxReserves = (); +// type ReserveIdentifier = [u8; 8]; +// type Balance = u64; +// type DustRemoval = (); +// type Event = Event; +// type ExistentialDeposit = ExistentialDeposit; +// type AccountStore = System; +// type WeightInfo = (); +// } + +// parameter_types! { +// pub const AssetDeposit: u64 = 1; +// pub const ApprovalDeposit: u64 = 1; +// pub const StringLimit: u32 = 50; +// pub const MetadataDepositBase: u64 = 1; +// pub const MetadataDepositPerByte: u64 = 1; +// } + +// impl pallet_assets::Config for Test { +// type Event = Event; +// type Balance = u64; +// type AssetId = u32; +// type Currency = Balances; +// type ForceOrigin = frame_system::EnsureRoot; +// type AssetDeposit = AssetDeposit; +// type MetadataDepositBase = MetadataDepositBase; +// type MetadataDepositPerByte = MetadataDepositPerByte; +// type ApprovalDeposit = ApprovalDeposit; +// type StringLimit = StringLimit; +// type Freezer = (); +// type WeightInfo = (); +// type Extra = (); +// } + +// impl Config for Test { +// type Currency = Balances; +// type Call = Call; +// type Event = Event; +// } + +// pub fn new_test_ext() -> sp_io::TestExternalities { +// let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); +// let (pair1, _) = sp_core::sr25519::Pair::generate(); +// let (pair2, _) = sp_core::sr25519::Pair::generate(); +// let (pair3, _) = sp_core::sr25519::Pair::generate(); +// pallet_balances::GenesisConfig:: { +// balances: vec![(pair1.public(), 10), (pair2.public(), 20), (pair3.public(), 30)], +// } +// .assimilate_storage(&mut t) +// .unwrap(); +// t.into() +// } + + +// // Build genesis storage according to the mock runtime. +// pub fn new_test_ext_funded(pairs: Vec<(sp_core::sr25519::Public, u64)>) -> sp_io::TestExternalities { +// let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + +// pallet_balances::GenesisConfig:: { +// balances: pairs, +// } +// .assimilate_storage(&mut t) +// .unwrap(); +// t.into() +// } diff --git a/bin/node-template/pallets/iris-ledger/src/tests.rs b/bin/node-template/pallets/iris-ledger/src/tests.rs new file mode 100644 index 000000000000..f46d2a532e34 --- /dev/null +++ b/bin/node-template/pallets/iris-ledger/src/tests.rs @@ -0,0 +1,191 @@ +// use super::*; +// use frame_support::{assert_ok}; +// use mock::*; +// use sp_core::Pair; +// use sp_core::{ +// offchain::{testing, OffchainWorkerExt, TransactionPoolExt, OffchainDbExt} +// }; +// use sp_keystore::{testing::KeyStore, KeystoreExt, SyncCryptoStore}; +// use std::sync::Arc; + +// #[test] +// fn iris_assets_initial_state() { +// new_test_ext().execute_with(|| { +// // Given: The node is initialized at block 0 +// // When: I query runtime storagey +// let data_queue = crate::DataQueue::::get(); +// let len = data_queue.len(); +// // Then: Runtime storage is empty +// assert_eq!(len, 0); +// }); +// } + +// #[test] +// fn iris_assets_ipfs_add_bytes_works_for_valid_value() { +// // Given: I am a valid node with a positive balance +// let (p, _) = sp_core::sr25519::Pair::generate(); +// let pairs = vec![(p.clone().public(), 10)]; +// let multiaddr_vec = "/ip4/127.0.0.1/tcp/4001/p2p/12D3KooWMvyvKxYcy9mjbFbXcogFSCvENzQ62ogRxHKZaksFCkAp".as_bytes().to_vec(); +// let cid_vec = "QmPZv7P8nQUSh2CpqTvUeYemFyjvMjgWEs8H1Tm8b3zAm9".as_bytes().to_vec(); +// let name: Vec = "test.txt".as_bytes().to_vec(); +// let cost = 1; +// let id = 1; +// let balance = 1; + +// // +// let expected_data_command = crate::DataCommand::AddBytes( +// OpaqueMultiaddr(multiaddr_vec.clone()), +// cid_vec.clone(), +// p.clone().public(), +// name.clone(), +// id.clone(), +// balance.clone(), +// ); + +// new_test_ext_funded(pairs).execute_with(|| { +// // WHEN: I invoke the create_storage_assets extrinsic +// assert_ok!(Iris::create( +// Origin::signed(p.clone().public()), +// p.clone().public(), +// multiaddr_vec.clone(), +// cid_vec.clone(), +// name.clone(), +// id.clone(), +// balance.clone(), +// )); + +// // THEN: There is a single DataCommand::AddBytes in the DataQueue +// let mut data_queue = crate::DataQueue::::get(); +// let len = data_queue.len(); +// assert_eq!(len, 1); +// let actual_data_command = data_queue.pop(); +// assert_eq!(actual_data_command, Some(expected_data_command)); +// }); +// } + +// #[test] +// fn iris_assets_request_data_works_for_valid_values() { +// // GIVEN: I am a valid Iris node with a positive balance +// let (p, _) = sp_core::sr25519::Pair::generate(); +// let pairs = vec![(p.clone().public(), 10)]; +// // let cid_vec = "QmPZv7P8nQUSh2CpqTvUeYemFyjvMjgWEs8H1Tm8b3zAm9".as_bytes().to_vec(); +// let asset_id = 1; +// let expected_data_command = crate::DataCommand::CatBytes( +// p.clone().public(), +// p.clone().public(), +// asset_id.clone(), +// ); +// new_test_ext_funded(pairs).execute_with(|| { +// // WHEN: I invoke the request_data extrinsic +// assert_ok!(Iris::request_bytes( +// Origin::signed(p.clone().public()), +// p.clone().public(), +// asset_id.clone(), +// )); + +// // THEN: There should be a single DataCommand::CatBytes in the DataQueue +// let mut data_queue = crate::DataQueue::::get(); +// let len = data_queue.len(); +// assert_eq!(len, 1); +// let actual_data_command = data_queue.pop(); +// assert_eq!(actual_data_command, Some(expected_data_command)); +// }); +// } + +// #[test] +// fn iris_assets_submit_ipfs_add_results_works_for_valid_values() { +// // GIVEN: I am a valid Iris node with a positive valance +// let (p, _) = sp_core::sr25519::Pair::generate(); +// let pairs = vec![(p.clone().public(), 10)]; +// let cid_vec = "QmPZv7P8nQUSh2CpqTvUeYemFyjvMjgWEs8H1Tm8b3zAm9".as_bytes().to_vec(); +// let id = 1; +// let balance = 1; + +// new_test_ext_funded(pairs).execute_with(|| { +// // WHEN: I invoke the submit_ipfs_add_results extrinsic +// assert_ok!(Iris::submit_ipfs_add_results( +// Origin::signed(p.clone().public()), +// p.clone().public(), +// cid_vec.clone(), +// id.clone(), +// balance.clone(), +// )); + +// // THEN: a new asset class is created +// // AND: A new entry is added to the AssetClassOwnership StorageDoubleMap +// let admin_asset_class_cid = crate::AssetClassOwnership::::get(p.clone().public(), id.clone()); +// assert_eq!(admin_asset_class_cid, cid_vec.clone()); +// }); +// } + +// #[test] +// fn iris_assets_mint_tickets_works_for_valid_values() { +// // GIVEN: I am a valid Iris node with a positive valance +// let (p, _) = sp_core::sr25519::Pair::generate(); +// let pairs = vec![(p.clone().public(), 10)]; +// let cid_vec = "QmPZv7P8nQUSh2CpqTvUeYemFyjvMjgWEs8H1Tm8b3zAm9".as_bytes().to_vec(); +// let balance = 1; +// let id = 1; + +// new_test_ext_funded(pairs).execute_with(|| { +// // AND: I create an owned asset class +// assert_ok!(Iris::submit_ipfs_add_results( +// Origin::signed(p.clone().public()), +// p.clone().public(), +// cid_vec.clone(), +// id.clone(), +// balance.clone(), +// )); +// // WHEN: I invoke the mint_tickets extrinsic +// assert_ok!(Iris::mint( +// Origin::signed(p.clone().public()), +// p.clone().public(), +// id.clone(), +// balance.clone(), +// )); +// // THEN: new assets are created and awarded to the benficiary +// // AND: A new entry is added to the AssetAccess StorageDoubleMap +// let asset_class_owner = crate::AssetAccess::::get(p.clone().public(), id.clone()); +// assert_eq!(asset_class_owner, p.clone().public()) +// }); +// } + +// #[test] +// fn iris_assets_can_transer_assets() { +// // GIVEN: I am valid Iris node with a positive balance // GIVEN: I am a valid Iris node with a positive valance +// let (p, _) = sp_core::sr25519::Pair::generate(); +// let (p2, _) = sp_core::sr25519::Pair::generate(); +// let pairs = vec![(p.clone().public(), 10), (p2.clone().public(), 10)]; +// let cid_vec = "QmPZv7P8nQUSh2CpqTvUeYemFyjvMjgWEs8H1Tm8b3zAm9".as_bytes().to_vec(); +// let balance = 1; +// let id = 1; + +// new_test_ext_funded(pairs).execute_with(|| { +// // AND: I create an owned asset class +// assert_ok!(Iris::submit_ipfs_add_results( +// Origin::signed(p.clone().public()), +// p.clone().public(), +// cid_vec.clone(), +// id.clone(), +// balance.clone(), +// )); +// // WHEN: I invoke the mint_tickets extrinsic +// assert_ok!(Iris::mint( +// Origin::signed(p.clone().public()), +// p.clone().public(), +// id.clone(), +// balance.clone(), +// )); +// // THEN: new assets are created and awarded to the benficiary +// // AND: A new entry is added to the AssetAccess StorageDoubleMap +// let asset_class_owner = crate::AssetAccess::::get(p.clone().public(), id.clone()); +// assert_eq!(asset_class_owner, p.clone().public()); +// // THEN: I can transfer my owned asset to another address +// assert_ok!(Iris::transfer_asset( +// Origin::signed(p.clone().public()), +// p2.clone().public(), +// id.clone(), +// balance.clone(), +// )); +// }); +// } diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index 01a15e3972f6..84046e7e5ec5 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -61,6 +61,7 @@ pub use sp_runtime::{Perbill, Permill}; /// Import the template pallet. pub use pallet_iris_assets; pub use pallet_iris_session; +pub use pallet_iris_ledger; /// An index to a block. pub type BlockNumber = u32; @@ -454,7 +455,13 @@ pub type SignedPayload = generic::SignedPayload; impl pallet_iris_assets::Config for Runtime { type Event = Event; type Call = Call; - type Currency = Balances; + type IrisCurrency = Balances; +} + +impl pallet_iris_ledger::Config for Runtime { + type Event = Event; + type Call = Call; + type IrisCurrency = Balances; } impl frame_system::offchain::CreateSignedTransaction for Runtime @@ -526,6 +533,7 @@ construct_runtime!( Sudo: pallet_sudo::{Pallet, Call, Config, Storage, Event}, Iris: pallet_iris_assets::{Pallet, Call, Storage, Event}, IrisSession: pallet_iris_session::{Pallet, Call, Storage, Event, Config, ValidateUnsigned}, + IrisLedger: pallet_iris_ledger::{Pallet, Call, Storage, Event}, Session: pallet_session::{Pallet, Call, Storage, Event, Config}, Assets: pallet_assets::{Pallet, Storage, Event}, ImOnline: pallet_im_online::{Pallet, Call, Storage, Event, ValidateUnsigned, Config}, @@ -802,7 +810,19 @@ impl_runtime_apis! { } } -// use codec::Encode; +/** + * + * CHAIN EXTENSION + * + * Here we expose functionality that can be used by smart contracts to hook into the iris runtime + * + * in general, this exposes iris functionality that doesn't rely on the underlying IPFS network + * + * We expose functionality to: + * - transfer owned assets + * - mint assets from an owned asset class + * + */ use frame_support::log::{ error, trace, @@ -864,6 +884,25 @@ impl ChainExtension for IrisExtension { func_id ); }, + // lock currrency + 3 => { + let mut env = env.buf_in_buf_out(); + let (caller_account, amount, cid): (AccountId, u64, Vec) = env.read_as()?; + let origin: Origin = system::RawOrigin::Signed(caller_account).into(); + + crate::Iris::lock_currency( + origin, amount, cid + )?; + trace!( + target: "runtime", + "[ChainExtension]|call|func_id:{:}", + func_id + ); + }, + // unlock and transfer currency + 4 => { + + }, _ => { // env.write(&random_slice, false, None).map_err(|_| { // DispatchError::Other("ChainExtension failed to call transfer_assets") From 8000e77adeb716a5291b6e1c08cff0acd7291bc1 Mon Sep 17 00:00:00 2001 From: driemworks Date: Sat, 5 Mar 2022 15:20:05 -0500 Subject: [PATCH 570/695] ledger funcs in chain ext --- .../pallets/iris-ledger/src/lib.rs | 4 +--- bin/node-template/runtime/src/lib.rs | 23 ++++++++++++++----- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/bin/node-template/pallets/iris-ledger/src/lib.rs b/bin/node-template/pallets/iris-ledger/src/lib.rs index 7f2d38eeea2c..51bebfbb48ec 100644 --- a/bin/node-template/pallets/iris-ledger/src/lib.rs +++ b/bin/node-template/pallets/iris-ledger/src/lib.rs @@ -136,11 +136,9 @@ pub mod pallet { pub fn unlock_currency_and_transfer( origin: OriginFor, target: T::AccountId, - cid: Vec, ) -> DispatchResult { let who = ensure_signed(origin)?; - // we assume locked amount equals amount in IrisLedger... for now - // let lock_id: LockIdentifier = cid; + // assume ammount in ledger matches locked amount for now...... let amount = >::get(who.clone(), IRIS_LOCK_ID); T::IrisCurrency::remove_lock(IRIS_LOCK_ID, &who); diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index 84046e7e5ec5..10dbc0eecd5c 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -854,7 +854,7 @@ impl ChainExtension for IrisExtension { UncheckedFrom<::Hash> + AsRef<[u8]>, { match func_id { - // transfer_asset + // IrisAssets::transfer_asset 1 => { let mut env = env.buf_in_buf_out(); let (caller_account, target, asset_id, amount): (AccountId, AccountId, u32, u64) = env.read_as()?; @@ -869,7 +869,7 @@ impl ChainExtension for IrisExtension { func_id ); }, - // mint assets + // IrisAssets::mint 2 => { let mut env = env.buf_in_buf_out(); let (caller_account, target, asset_id, amount): (AccountId, AccountId, u32, u64) = env.read_as()?; @@ -884,14 +884,14 @@ impl ChainExtension for IrisExtension { func_id ); }, - // lock currrency + // IrisLedger::lock_currrency 3 => { let mut env = env.buf_in_buf_out(); let (caller_account, amount, cid): (AccountId, u64, Vec) = env.read_as()?; let origin: Origin = system::RawOrigin::Signed(caller_account).into(); - crate::Iris::lock_currency( - origin, amount, cid + crate::IrisLedger::lock_currency( + origin, amount, cid, )?; trace!( target: "runtime", @@ -899,9 +899,20 @@ impl ChainExtension for IrisExtension { func_id ); }, - // unlock and transfer currency + // IrisLedger::unlock_currency_and_transfer 4 => { + let mut env = env.buf_in_buf_out(); + let (caller_account, target): (AccountId, AccountId) = env.read_as()?; + let origin: Origin = system::RawOrigin::Signed(caller_account).into(); + crate::IrisLedger::unlock_currency_and_transfer( + origin, target, + )?; + trace!( + target: "runtime", + "[ChainExtension]|call|func_id:{:}", + func_id + ); }, _ => { // env.write(&random_slice, false, None).map_err(|_| { From 86f08c1bf6921c0af63bfcc3c761f8aadf76451c Mon Sep 17 00:00:00 2001 From: driemworks Date: Sat, 5 Mar 2022 15:30:12 -0500 Subject: [PATCH 571/695] rename Iris -> IrisAssets, update readmes --- bin/node-template/pallets/iris-assets/README.md | 8 ++++++++ bin/node-template/pallets/iris-ledger/README.md | 6 +++++- bin/node-template/runtime/src/lib.rs | 6 +++--- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/bin/node-template/pallets/iris-assets/README.md b/bin/node-template/pallets/iris-assets/README.md index 8d751a42207d..0f069f5534be 100644 --- a/bin/node-template/pallets/iris-assets/README.md +++ b/bin/node-template/pallets/iris-assets/README.md @@ -1 +1,9 @@ +# Iris-Assets + +This pallet contains functions that allow users to create and manage asset classes and derived assets. +Additionally, it provides the functionality to add DataCommands to a queue which are processed by validator nodes. This allows us to accomplish: + +- Adding data to iris +- Requesting data from iris + License: Unlicense \ No newline at end of file diff --git a/bin/node-template/pallets/iris-ledger/README.md b/bin/node-template/pallets/iris-ledger/README.md index 8d751a42207d..f16f1c50c923 100644 --- a/bin/node-template/pallets/iris-ledger/README.md +++ b/bin/node-template/pallets/iris-ledger/README.md @@ -1 +1,5 @@ -License: Unlicense \ No newline at end of file +# Iris-Ledger + +The Iris Ledger facilitates the management of funds for iris nodes. In particular, it allows nodes to lock funds, unlock funds, and transfer them to a address. We expose this functionality via our chain extension in order to make this functionality easily callable within smart contracts. + +License: Unlicense diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index 10dbc0eecd5c..8e9db0fcec8d 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -531,7 +531,7 @@ construct_runtime!( Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, TransactionPayment: pallet_transaction_payment::{Pallet, Storage}, Sudo: pallet_sudo::{Pallet, Call, Config, Storage, Event}, - Iris: pallet_iris_assets::{Pallet, Call, Storage, Event}, + IrisAssets: pallet_iris_assets::{Pallet, Call, Storage, Event}, IrisSession: pallet_iris_session::{Pallet, Call, Storage, Event, Config, ValidateUnsigned}, IrisLedger: pallet_iris_ledger::{Pallet, Call, Storage, Event}, Session: pallet_session::{Pallet, Call, Storage, Event, Config}, @@ -860,7 +860,7 @@ impl ChainExtension for IrisExtension { let (caller_account, target, asset_id, amount): (AccountId, AccountId, u32, u64) = env.read_as()?; let origin: Origin = system::RawOrigin::Signed(caller_account).into(); - crate::Iris::transfer_asset( + crate::IrisAssets::transfer_asset( origin, sp_runtime::MultiAddress::Id(target), asset_id, amount, )?; trace!( @@ -875,7 +875,7 @@ impl ChainExtension for IrisExtension { let (caller_account, target, asset_id, amount): (AccountId, AccountId, u32, u64) = env.read_as()?; let origin: Origin = system::RawOrigin::Signed(caller_account).into(); - crate::Iris::mint( + crate::IrisAssets::mint( origin, sp_runtime::MultiAddress::Id(beneficiary), asset_id, amount, )?; trace!( From f6679ddd31f68e9f1578064d58a246130c27026b Mon Sep 17 00:00:00 2001 From: Gavin Wood Date: Mon, 7 Mar 2022 09:12:03 +0100 Subject: [PATCH 572/695] Minor Uniques pallet improvements and XCM v3 preparations (#10896) * Introduce Helper to Uniques for benchmark stuff * Fixes * Formatting * Featuregate the Helper, include ContainsPair * Introduce & use EnsureOriginWithArg * Benchmarking * Docs * More ContainsBoth helpers * Formatting * Formatting * Fixes Co-authored-by: Shawn Tabrizi --- bin/node/runtime/src/lib.rs | 9 +- frame/support/src/traits.rs | 10 +- frame/support/src/traits/dispatch.rs | 48 +++++ frame/support/src/traits/members.rs | 150 ++++++++++++--- .../support/src/traits/tokens/nonfungible.rs | 9 +- .../support/src/traits/tokens/nonfungibles.rs | 6 +- frame/uniques/src/benchmarking.rs | 73 +++++--- frame/uniques/src/impl_nonfungibles.rs | 15 +- frame/uniques/src/lib.rs | 172 ++++++++++++------ frame/uniques/src/mock.rs | 5 +- frame/uniques/src/tests.rs | 18 ++ frame/uniques/src/weights.rs | 15 ++ 12 files changed, 417 insertions(+), 113 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index f12bf8a88365..e2903c0b314d 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -27,9 +27,9 @@ use frame_election_provider_support::onchain; use frame_support::{ construct_runtime, parameter_types, traits::{ - ConstU128, ConstU16, ConstU32, Currency, EnsureOneOf, EqualPrivilegeOnly, Everything, - Imbalance, InstanceFilter, KeyOwnerProofSystem, LockIdentifier, Nothing, OnUnbalanced, - U128CurrencyToVote, + AsEnsureOriginWithArg, ConstU128, ConstU16, ConstU32, Currency, EnsureOneOf, + EqualPrivilegeOnly, Everything, Imbalance, InstanceFilter, KeyOwnerProofSystem, + LockIdentifier, Nothing, OnUnbalanced, U128CurrencyToVote, }, weights::{ constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND}, @@ -1348,6 +1348,9 @@ impl pallet_uniques::Config for Runtime { type KeyLimit = KeyLimit; type ValueLimit = ValueLimit; type WeightInfo = pallet_uniques::weights::SubstrateWeight; + #[cfg(feature = "runtime-benchmarks")] + type Helper = (); + type CreateOrigin = AsEnsureOriginWithArg>; } impl pallet_transaction_storage::Config for Runtime { diff --git a/frame/support/src/traits.rs b/frame/support/src/traits.rs index 88891c83276b..a8ce78ae9dab 100644 --- a/frame/support/src/traits.rs +++ b/frame/support/src/traits.rs @@ -34,8 +34,9 @@ mod members; #[allow(deprecated)] pub use members::{AllowAll, DenyAll, Filter}; pub use members::{ - AsContains, ChangeMembers, Contains, ContainsLengthBound, Everything, InitializeMembers, - IsInVec, Nothing, SortedMembers, + AsContains, ChangeMembers, Contains, ContainsLengthBound, ContainsPair, Everything, + EverythingBut, FromContainsPair, InitializeMembers, InsideBoth, IsInVec, Nothing, + SortedMembers, TheseExcept, }; mod validation; @@ -89,7 +90,10 @@ pub use storage::{ }; mod dispatch; -pub use dispatch::{EnsureOneOf, EnsureOrigin, OriginTrait, UnfilteredDispatchable}; +pub use dispatch::{ + AsEnsureOriginWithArg, EnsureOneOf, EnsureOrigin, EnsureOriginWithArg, OriginTrait, + UnfilteredDispatchable, +}; mod voting; pub use voting::{ diff --git a/frame/support/src/traits/dispatch.rs b/frame/support/src/traits/dispatch.rs index 1a4e9f6f7cc2..250a31ebfb17 100644 --- a/frame/support/src/traits/dispatch.rs +++ b/frame/support/src/traits/dispatch.rs @@ -27,10 +27,12 @@ use sp_runtime::{ pub trait EnsureOrigin { /// A return type. type Success; + /// Perform the origin check. fn ensure_origin(o: OuterOrigin) -> Result { Self::try_origin(o).map_err(|_| BadOrigin) } + /// Perform the origin check. fn try_origin(o: OuterOrigin) -> Result; @@ -41,6 +43,52 @@ pub trait EnsureOrigin { fn successful_origin() -> OuterOrigin; } +/// Some sort of check on the origin is performed by this object. +pub trait EnsureOriginWithArg { + /// A return type. + type Success; + + /// Perform the origin check. + fn ensure_origin(o: OuterOrigin, a: &Argument) -> Result { + Self::try_origin(o, a).map_err(|_| BadOrigin) + } + + /// Perform the origin check, returning the origin value if unsuccessful. This allows chaining. + fn try_origin(o: OuterOrigin, a: &Argument) -> Result; + + /// Returns an outer origin capable of passing `try_origin` check. + /// + /// ** Should be used for benchmarking only!!! ** + #[cfg(feature = "runtime-benchmarks")] + fn successful_origin(a: &Argument) -> OuterOrigin; +} + +pub struct AsEnsureOriginWithArg(sp_std::marker::PhantomData); +impl> + EnsureOriginWithArg for AsEnsureOriginWithArg +{ + /// A return type. + type Success = EO::Success; + + /// Perform the origin check. + fn ensure_origin(o: OuterOrigin, _: &Argument) -> Result { + EO::ensure_origin(o) + } + + /// Perform the origin check, returning the origin value if unsuccessful. This allows chaining. + fn try_origin(o: OuterOrigin, _: &Argument) -> Result { + EO::try_origin(o) + } + + /// Returns an outer origin capable of passing `try_origin` check. + /// + /// ** Should be used for benchmarking only!!! ** + #[cfg(feature = "runtime-benchmarks")] + fn successful_origin(_: &Argument) -> OuterOrigin { + EO::successful_origin() + } +} + /// Type that can be dispatched with an origin but without checking the origin filter. /// /// Implemented for pallet dispatchable type by `decl_module` and for runtime dispatchable by diff --git a/frame/support/src/traits/members.rs b/frame/support/src/traits/members.rs index ba72b4819933..f3c586b64af0 100644 --- a/frame/support/src/traits/members.rs +++ b/frame/support/src/traits/members.rs @@ -25,6 +25,40 @@ pub trait Contains { fn contains(t: &T) -> bool; } +#[impl_trait_for_tuples::impl_for_tuples(1, 30)] +impl Contains for Tuple { + fn contains(t: &T) -> bool { + for_tuples!( #( + if Tuple::contains(t) { return true } + )* ); + false + } +} + +/// A trait for querying whether a type can be said to "contain" a pair-value. +pub trait ContainsPair { + /// Return `true` if this "contains" the pair-value `(a, b)`. + fn contains(a: &A, b: &B) -> bool; +} + +#[impl_trait_for_tuples::impl_for_tuples(0, 30)] +impl ContainsPair for Tuple { + fn contains(a: &A, b: &B) -> bool { + for_tuples!( #( + if Tuple::contains(a, b) { return true } + )* ); + false + } +} + +/// Converter `struct` to use a `ContainsPair` implementation for a `Contains` bound. +pub struct FromContainsPair(PhantomData); +impl> Contains<(A, B)> for FromContainsPair { + fn contains((ref a, ref b): &(A, B)) -> bool { + CP::contains(a, b) + } +} + /// A [`Contains`] implementation that contains every value. pub enum Everything {} impl Contains for Everything { @@ -32,6 +66,11 @@ impl Contains for Everything { true } } +impl ContainsPair for Everything { + fn contains(_: &A, _: &B) -> bool { + true + } +} /// A [`Contains`] implementation that contains no value. pub enum Nothing {} @@ -40,43 +79,112 @@ impl Contains for Nothing { false } } +impl ContainsPair for Nothing { + fn contains(_: &A, _: &B) -> bool { + false + } +} -#[deprecated = "Use `Everything` instead"] -pub type AllowAll = Everything; -#[deprecated = "Use `Nothing` instead"] -pub type DenyAll = Nothing; -#[deprecated = "Use `Contains` instead"] -pub trait Filter { - fn filter(t: &T) -> bool; +/// A [`Contains`] implementation that contains everything except the values in `Exclude`. +pub struct EverythingBut(PhantomData); +impl> Contains for EverythingBut { + fn contains(t: &T) -> bool { + !Exclude::contains(t) + } } -#[allow(deprecated)] -impl> Filter for C { - fn filter(t: &T) -> bool { - Self::contains(t) +impl> ContainsPair for EverythingBut { + fn contains(a: &A, b: &B) -> bool { + !Exclude::contains(a, b) } } -#[impl_trait_for_tuples::impl_for_tuples(1, 30)] -impl Contains for Tuple { +/// A [`Contains`] implementation that contains all members of `These` excepting any members in +/// `Except`. +pub struct TheseExcept(PhantomData<(These, Except)>); +impl, Except: Contains> Contains for TheseExcept { fn contains(t: &T) -> bool { - for_tuples!( #( - if Tuple::contains(t) { return true } - )* ); - false + These::contains(t) && !Except::contains(t) + } +} +impl, Except: ContainsPair> ContainsPair + for TheseExcept +{ + fn contains(a: &A, b: &B) -> bool { + These::contains(a, b) && !Except::contains(a, b) + } +} + +/// A [`Contains`] implementation which contains all members of `These` which are also members of +/// `Those`. +pub struct InsideBoth(PhantomData<(These, Those)>); +impl, Those: Contains> Contains for InsideBoth { + fn contains(t: &T) -> bool { + These::contains(t) && Those::contains(t) + } +} +impl, Those: ContainsPair> ContainsPair + for InsideBoth +{ + fn contains(a: &A, b: &B) -> bool { + These::contains(a, b) && Those::contains(a, b) } } /// Create a type which implements the `Contains` trait for a particular type with syntax similar /// to `matches!`. #[macro_export] -macro_rules! match_type { - ( pub type $n:ident: impl Contains<$t:ty> = { $phead:pat_param $( | $ptail:pat )* } ; ) => { +macro_rules! match_types { + ( + pub type $n:ident: impl Contains<$t:ty> = { + $phead:pat_param $( | $ptail:pat )* + }; + $( $rest:tt )* + ) => { pub struct $n; impl $crate::traits::Contains<$t> for $n { fn contains(l: &$t) -> bool { matches!(l, $phead $( | $ptail )* ) } } + $crate::match_types!( $( $rest )* ); + }; + ( + pub type $n:ident: impl ContainsPair<$a:ty, $b:ty> = { + $phead:pat_param $( | $ptail:pat )* + }; + $( $rest:tt )* + ) => { + pub struct $n; + impl $crate::traits::ContainsPair<$a, $b> for $n { + fn contains(a: &$a, b: &$b) -> bool { + matches!((a, b), $phead $( | $ptail )* ) + } + } + $crate::match_types!( $( $rest )* ); + }; + () => {} +} + +/// Create a type which implements the `Contains` trait for a particular type with syntax similar +/// to `matches!`. +#[macro_export] +#[deprecated = "Use `match_types!` instead"] +macro_rules! match_type { + ($( $x:tt )*) => { $crate::match_types!( $( $x )* ); } +} + +#[deprecated = "Use `Everything` instead"] +pub type AllowAll = Everything; +#[deprecated = "Use `Nothing` instead"] +pub type DenyAll = Nothing; +#[deprecated = "Use `Contains` instead"] +pub trait Filter { + fn filter(t: &T) -> bool; +} +#[allow(deprecated)] +impl> Filter for C { + fn filter(t: &T) -> bool { + Self::contains(t) } } @@ -84,12 +192,12 @@ macro_rules! match_type { mod tests { use super::*; - match_type! { + match_types! { pub type OneOrTenToTwenty: impl Contains = { 1 | 10..=20 }; } #[test] - fn match_type_works() { + fn match_types_works() { for i in 0..=255 { assert_eq!(OneOrTenToTwenty::contains(&i), i == 1 || i >= 10 && i <= 20); } diff --git a/frame/support/src/traits/tokens/nonfungible.rs b/frame/support/src/traits/tokens/nonfungible.rs index 08e9a3a18a4b..5cf9638131b2 100644 --- a/frame/support/src/traits/tokens/nonfungible.rs +++ b/frame/support/src/traits/tokens/nonfungible.rs @@ -85,7 +85,10 @@ pub trait Mutate: Inspect { /// Burn some asset `instance`. /// /// By default, this is not a supported operation. - fn burn_from(_instance: &Self::InstanceId) -> DispatchResult { + fn burn( + _instance: &Self::InstanceId, + _maybe_check_owner: Option<&AccountId>, + ) -> DispatchResult { Err(TokenError::Unsupported.into()) } @@ -166,8 +169,8 @@ impl< fn mint_into(instance: &Self::InstanceId, who: &AccountId) -> DispatchResult { >::mint_into(&A::get(), instance, who) } - fn burn_from(instance: &Self::InstanceId) -> DispatchResult { - >::burn_from(&A::get(), instance) + fn burn(instance: &Self::InstanceId, maybe_check_owner: Option<&AccountId>) -> DispatchResult { + >::burn(&A::get(), instance, maybe_check_owner) } fn set_attribute(instance: &Self::InstanceId, key: &[u8], value: &[u8]) -> DispatchResult { >::set_attribute(&A::get(), instance, key, value) diff --git a/frame/support/src/traits/tokens/nonfungibles.rs b/frame/support/src/traits/tokens/nonfungibles.rs index 1172fb602283..8bd731b20342 100644 --- a/frame/support/src/traits/tokens/nonfungibles.rs +++ b/frame/support/src/traits/tokens/nonfungibles.rs @@ -165,7 +165,11 @@ pub trait Mutate: Inspect { /// Burn some asset `instance` of `class`. /// /// By default, this is not a supported operation. - fn burn_from(_class: &Self::ClassId, _instance: &Self::InstanceId) -> DispatchResult { + fn burn( + _class: &Self::ClassId, + _instance: &Self::InstanceId, + _maybe_check_owner: Option<&AccountId>, + ) -> DispatchResult { Err(TokenError::Unsupported.into()) } diff --git a/frame/uniques/src/benchmarking.rs b/frame/uniques/src/benchmarking.rs index f3f9b7b28df7..d6223ec88f81 100644 --- a/frame/uniques/src/benchmarking.rs +++ b/frame/uniques/src/benchmarking.rs @@ -40,12 +40,13 @@ fn create_class, I: 'static>( ) -> (T::ClassId, T::AccountId, ::Source) { let caller: T::AccountId = whitelisted_caller(); let caller_lookup = T::Lookup::unlookup(caller.clone()); - let class = Default::default(); + let class = T::Helper::class(0); T::Currency::make_free_balance_be(&caller, DepositBalanceOf::::max_value()); - assert!(Uniques::::create( - SystemOrigin::Signed(caller.clone()).into(), + assert!(Uniques::::force_create( + SystemOrigin::Root.into(), class, caller_lookup.clone(), + false, ) .is_ok()); (class, caller, caller_lookup) @@ -53,14 +54,14 @@ fn create_class, I: 'static>( fn add_class_metadata, I: 'static>( ) -> (T::AccountId, ::Source) { - let caller = Class::::get(T::ClassId::default()).unwrap().owner; + let caller = Class::::get(T::Helper::class(0)).unwrap().owner; if caller != whitelisted_caller() { whitelist_account!(caller); } let caller_lookup = T::Lookup::unlookup(caller.clone()); assert!(Uniques::::set_class_metadata( SystemOrigin::Signed(caller.clone()).into(), - Default::default(), + T::Helper::class(0), vec![0; T::StringLimit::get() as usize].try_into().unwrap(), false, ) @@ -71,15 +72,15 @@ fn add_class_metadata, I: 'static>( fn mint_instance, I: 'static>( index: u16, ) -> (T::InstanceId, T::AccountId, ::Source) { - let caller = Class::::get(T::ClassId::default()).unwrap().admin; + let caller = Class::::get(T::Helper::class(0)).unwrap().admin; if caller != whitelisted_caller() { whitelist_account!(caller); } let caller_lookup = T::Lookup::unlookup(caller.clone()); - let instance = index.into(); + let instance = T::Helper::instance(index); assert!(Uniques::::mint( SystemOrigin::Signed(caller.clone()).into(), - Default::default(), + T::Helper::class(0), instance, caller_lookup.clone(), ) @@ -90,14 +91,14 @@ fn mint_instance, I: 'static>( fn add_instance_metadata, I: 'static>( instance: T::InstanceId, ) -> (T::AccountId, ::Source) { - let caller = Class::::get(T::ClassId::default()).unwrap().owner; + let caller = Class::::get(T::Helper::class(0)).unwrap().owner; if caller != whitelisted_caller() { whitelist_account!(caller); } let caller_lookup = T::Lookup::unlookup(caller.clone()); assert!(Uniques::::set_metadata( SystemOrigin::Signed(caller.clone()).into(), - Default::default(), + T::Helper::class(0), instance, vec![0; T::StringLimit::get() as usize].try_into().unwrap(), false, @@ -109,7 +110,7 @@ fn add_instance_metadata, I: 'static>( fn add_instance_attribute, I: 'static>( instance: T::InstanceId, ) -> (BoundedVec, T::AccountId, ::Source) { - let caller = Class::::get(T::ClassId::default()).unwrap().owner; + let caller = Class::::get(T::Helper::class(0)).unwrap().owner; if caller != whitelisted_caller() { whitelist_account!(caller); } @@ -117,7 +118,7 @@ fn add_instance_attribute, I: 'static>( let key: BoundedVec<_, _> = vec![0; T::KeyLimit::get() as usize].try_into().unwrap(); assert!(Uniques::::set_attribute( SystemOrigin::Signed(caller.clone()).into(), - Default::default(), + T::Helper::class(0), Some(instance), key.clone(), vec![0; T::ValueLimit::get() as usize].try_into().unwrap(), @@ -136,20 +137,24 @@ fn assert_last_event, I: 'static>(generic_event: >:: benchmarks_instance_pallet! { create { - let caller: T::AccountId = whitelisted_caller(); - let caller_lookup = T::Lookup::unlookup(caller.clone()); + let class = T::Helper::class(0); + let origin = T::CreateOrigin::successful_origin(&class); + let caller = T::CreateOrigin::ensure_origin(origin.clone(), &class).unwrap(); + whitelist_account!(caller); + let admin = T::Lookup::unlookup(caller.clone()); T::Currency::make_free_balance_be(&caller, DepositBalanceOf::::max_value()); - }: _(SystemOrigin::Signed(caller.clone()), Default::default(), caller_lookup) + let call = Call::::create { class, admin }; + }: { call.dispatch_bypass_filter(origin)? } verify { - assert_last_event::(Event::Created { class: Default::default(), creator: caller.clone(), owner: caller }.into()); + assert_last_event::(Event::Created { class: T::Helper::class(0), creator: caller.clone(), owner: caller }.into()); } force_create { let caller: T::AccountId = whitelisted_caller(); let caller_lookup = T::Lookup::unlookup(caller.clone()); - }: _(SystemOrigin::Root, Default::default(), caller_lookup, true) + }: _(SystemOrigin::Root, T::Helper::class(0), caller_lookup, true) verify { - assert_last_event::(Event::ForceCreated { class: Default::default(), owner: caller }.into()); + assert_last_event::(Event::ForceCreated { class: T::Helper::class(0), owner: caller }.into()); } destroy { @@ -163,10 +168,10 @@ benchmarks_instance_pallet! { mint_instance::(i as u16); } for i in 0..m { - add_instance_metadata::((i as u16).into()); + add_instance_metadata::(T::Helper::instance(i as u16)); } for i in 0..a { - add_instance_attribute::((i as u16).into()); + add_instance_attribute::(T::Helper::instance(i as u16)); } let witness = Class::::get(class).unwrap().destroy_witness(); }: _(SystemOrigin::Signed(caller), class, witness) @@ -176,7 +181,7 @@ benchmarks_instance_pallet! { mint { let (class, caller, caller_lookup) = create_class::(); - let instance = Default::default(); + let instance = T::Helper::instance(0); }: _(SystemOrigin::Signed(caller.clone()), class, instance, caller_lookup) verify { assert_last_event::(Event::Issued { class, instance, owner: caller }.into()); @@ -192,7 +197,7 @@ benchmarks_instance_pallet! { transfer { let (class, caller, caller_lookup) = create_class::(); - let (instance, ..) = mint_instance::(Default::default()); + let (instance, ..) = mint_instance::(0); let target: T::AccountId = account("target", 0, SEED); let target_lookup = T::Lookup::unlookup(target.clone()); @@ -222,15 +227,15 @@ benchmarks_instance_pallet! { freeze { let (class, caller, caller_lookup) = create_class::(); - let (instance, ..) = mint_instance::(Default::default()); - }: _(SystemOrigin::Signed(caller.clone()), Default::default(), Default::default()) + let (instance, ..) = mint_instance::(0); + }: _(SystemOrigin::Signed(caller.clone()), T::Helper::class(0), T::Helper::instance(0)) verify { - assert_last_event::(Event::Frozen { class: Default::default(), instance: Default::default() }.into()); + assert_last_event::(Event::Frozen { class: T::Helper::class(0), instance: T::Helper::instance(0) }.into()); } thaw { let (class, caller, caller_lookup) = create_class::(); - let (instance, ..) = mint_instance::(Default::default()); + let (instance, ..) = mint_instance::(0); Uniques::::freeze( SystemOrigin::Signed(caller.clone()).into(), class, @@ -262,6 +267,8 @@ benchmarks_instance_pallet! { let target: T::AccountId = account("target", 0, SEED); let target_lookup = T::Lookup::unlookup(target.clone()); T::Currency::make_free_balance_be(&target, T::Currency::minimum_balance()); + let origin = SystemOrigin::Signed(target.clone()).into(); + Uniques::::set_accept_ownership(origin, Some(class.clone()))?; }: _(SystemOrigin::Signed(caller), class, target_lookup) verify { assert_last_event::(Event::OwnerChanged { class, new_owner: target }.into()); @@ -272,7 +279,7 @@ benchmarks_instance_pallet! { let target0 = T::Lookup::unlookup(account("target", 0, SEED)); let target1 = T::Lookup::unlookup(account("target", 1, SEED)); let target2 = T::Lookup::unlookup(account("target", 2, SEED)); - }: _(SystemOrigin::Signed(caller), Default::default(), target0.clone(), target1.clone(), target2.clone()) + }: _(SystemOrigin::Signed(caller), class, target0.clone(), target1.clone(), target2.clone()) verify { assert_last_event::(Event::TeamChanged{ class, @@ -379,5 +386,17 @@ benchmarks_instance_pallet! { assert_last_event::(Event::ApprovalCancelled { class, instance, owner: caller, delegate }.into()); } + set_accept_ownership { + let caller: T::AccountId = whitelisted_caller(); + T::Currency::make_free_balance_be(&caller, DepositBalanceOf::::max_value()); + let class = T::Helper::class(0); + }: _(SystemOrigin::Signed(caller.clone()), Some(class.clone())) + verify { + assert_last_event::(Event::OwnershipAcceptanceChanged { + who: caller, + maybe_class: Some(class), + }.into()); + } + impl_benchmark_test_suite!(Uniques, crate::mock::new_test_ext(), crate::mock::Test); } diff --git a/frame/uniques/src/impl_nonfungibles.rs b/frame/uniques/src/impl_nonfungibles.rs index a9695e8e898a..89b95fb77048 100644 --- a/frame/uniques/src/impl_nonfungibles.rs +++ b/frame/uniques/src/impl_nonfungibles.rs @@ -128,8 +128,19 @@ impl, I: 'static> Mutate<::AccountId> for Pallet Self::do_mint(class.clone(), instance.clone(), who.clone(), |_| Ok(())) } - fn burn_from(class: &Self::ClassId, instance: &Self::InstanceId) -> DispatchResult { - Self::do_burn(class.clone(), instance.clone(), |_, _| Ok(())) + fn burn( + class: &Self::ClassId, + instance: &Self::InstanceId, + maybe_check_owner: Option<&T::AccountId>, + ) -> DispatchResult { + Self::do_burn(class.clone(), instance.clone(), |_, d| { + if let Some(check_owner) = maybe_check_owner { + if &d.owner != check_owner { + Err(Error::::NoPermission)?; + } + } + Ok(()) + }) } } diff --git a/frame/uniques/src/lib.rs b/frame/uniques/src/lib.rs index f35bb3fd61a0..1e1482545419 100644 --- a/frame/uniques/src/lib.rs +++ b/frame/uniques/src/lib.rs @@ -41,8 +41,10 @@ mod types; pub mod migration; pub mod weights; -use codec::{Decode, Encode, HasCompact}; -use frame_support::traits::{BalanceStatus::Reserved, Currency, ReservableCurrency}; +use codec::{Decode, Encode}; +use frame_support::traits::{ + BalanceStatus::Reserved, Currency, EnsureOriginWithArg, ReservableCurrency, +}; use frame_system::Config as SystemConfig; use sp_runtime::{ traits::{Saturating, StaticLookup, Zero}, @@ -64,6 +66,21 @@ pub mod pallet { #[pallet::generate_store(pub(super) trait Store)] pub struct Pallet(_); + #[cfg(feature = "runtime-benchmarks")] + pub trait BenchmarkHelper { + fn class(i: u16) -> ClassId; + fn instance(i: u16) -> InstanceId; + } + #[cfg(feature = "runtime-benchmarks")] + impl, InstanceId: From> BenchmarkHelper for () { + fn class(i: u16) -> ClassId { + i.into() + } + fn instance(i: u16) -> InstanceId { + i.into() + } + } + #[pallet::config] /// The module configuration trait. pub trait Config: frame_system::Config { @@ -71,16 +88,10 @@ pub mod pallet { type Event: From> + IsType<::Event>; /// Identifier for the class of asset. - type ClassId: Member + Parameter + Default + Copy + HasCompact + MaxEncodedLen; + type ClassId: Member + Parameter + MaxEncodedLen + Copy; /// The type used to identify a unique asset within an asset class. - type InstanceId: Member - + Parameter - + Default - + Copy - + HasCompact - + From - + MaxEncodedLen; + type InstanceId: Member + Parameter + MaxEncodedLen + Copy; /// The currency mechanism, used for paying for reserves. type Currency: ReservableCurrency; @@ -89,6 +100,14 @@ pub mod pallet { /// attributes. type ForceOrigin: EnsureOrigin; + /// Standard class creation is only allowed if the origin attempting it and the class are + /// in this set. + type CreateOrigin: EnsureOriginWithArg< + Success = Self::AccountId, + Self::Origin, + Self::ClassId, + >; + /// The basic amount of funds that must be reserved for an asset class. #[pallet::constant] type ClassDeposit: Get>; @@ -122,6 +141,10 @@ pub mod pallet { #[pallet::constant] type ValueLimit: Get; + #[cfg(feature = "runtime-benchmarks")] + /// A set of helper functions for benchmarking. + type Helper: BenchmarkHelper; + /// Weight information for extrinsics in this pallet. type WeightInfo: WeightInfo; } @@ -135,6 +158,11 @@ pub mod pallet { ClassDetails>, >; + #[pallet::storage] + /// The class, if any, of which an account is willing to take ownership. + pub(super) type OwnershipAcceptance, I: 'static = ()> = + StorageMap<_, Blake2_128Concat, T::AccountId, T::ClassId>; + #[pallet::storage] /// The assets held by any given account; set out this way so that assets owned by a single /// account can be enumerated. @@ -296,6 +324,8 @@ pub mod pallet { maybe_instance: Option, key: BoundedVec, }, + /// Ownership acceptance has changed for an account. + OwnershipAcceptanceChanged { who: T::AccountId, maybe_class: Option }, } #[pallet::error] @@ -320,6 +350,8 @@ pub mod pallet { NoDelegate, /// No approval exists that would allow the transfer. Unapproved, + /// The named owner has not signed ownership of the class is acceptable. + Unaccepted, } impl, I: 'static> Pallet { @@ -327,6 +359,11 @@ pub mod pallet { pub fn owner(class: T::ClassId, instance: T::InstanceId) -> Option { Asset::::get(class, instance).map(|i| i.owner) } + + /// Get the owner of the asset instance, if the asset exists. + pub fn class_owner(class: T::ClassId) -> Option { + Class::::get(class).map(|i| i.owner) + } } #[pallet::call] @@ -350,10 +387,10 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::create())] pub fn create( origin: OriginFor, - #[pallet::compact] class: T::ClassId, + class: T::ClassId, admin: ::Source, ) -> DispatchResult { - let owner = ensure_signed(origin)?; + let owner = T::CreateOrigin::ensure_origin(origin, &class)?; let admin = T::Lookup::lookup(admin)?; Self::do_create_class( @@ -385,7 +422,7 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::force_create())] pub fn force_create( origin: OriginFor, - #[pallet::compact] class: T::ClassId, + class: T::ClassId, owner: ::Source, free_holding: bool, ) -> DispatchResult { @@ -424,7 +461,7 @@ pub mod pallet { ))] pub fn destroy( origin: OriginFor, - #[pallet::compact] class: T::ClassId, + class: T::ClassId, witness: DestroyWitness, ) -> DispatchResultWithPostInfo { let maybe_check_owner = match T::ForceOrigin::try_origin(origin) { @@ -455,8 +492,8 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::mint())] pub fn mint( origin: OriginFor, - #[pallet::compact] class: T::ClassId, - #[pallet::compact] instance: T::InstanceId, + class: T::ClassId, + instance: T::InstanceId, owner: ::Source, ) -> DispatchResult { let origin = ensure_signed(origin)?; @@ -484,8 +521,8 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::burn())] pub fn burn( origin: OriginFor, - #[pallet::compact] class: T::ClassId, - #[pallet::compact] instance: T::InstanceId, + class: T::ClassId, + instance: T::InstanceId, check_owner: Option<::Source>, ) -> DispatchResult { let origin = ensure_signed(origin)?; @@ -520,8 +557,8 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::transfer())] pub fn transfer( origin: OriginFor, - #[pallet::compact] class: T::ClassId, - #[pallet::compact] instance: T::InstanceId, + class: T::ClassId, + instance: T::InstanceId, dest: ::Source, ) -> DispatchResult { let origin = ensure_signed(origin)?; @@ -556,7 +593,7 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::redeposit(instances.len() as u32))] pub fn redeposit( origin: OriginFor, - #[pallet::compact] class: T::ClassId, + class: T::ClassId, instances: Vec, ) -> DispatchResult { let origin = ensure_signed(origin)?; @@ -616,8 +653,8 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::freeze())] pub fn freeze( origin: OriginFor, - #[pallet::compact] class: T::ClassId, - #[pallet::compact] instance: T::InstanceId, + class: T::ClassId, + instance: T::InstanceId, ) -> DispatchResult { let origin = ensure_signed(origin)?; @@ -646,8 +683,8 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::thaw())] pub fn thaw( origin: OriginFor, - #[pallet::compact] class: T::ClassId, - #[pallet::compact] instance: T::InstanceId, + class: T::ClassId, + instance: T::InstanceId, ) -> DispatchResult { let origin = ensure_signed(origin)?; @@ -673,10 +710,7 @@ pub mod pallet { /// /// Weight: `O(1)` #[pallet::weight(T::WeightInfo::freeze_class())] - pub fn freeze_class( - origin: OriginFor, - #[pallet::compact] class: T::ClassId, - ) -> DispatchResult { + pub fn freeze_class(origin: OriginFor, class: T::ClassId) -> DispatchResult { let origin = ensure_signed(origin)?; Class::::try_mutate(class, |maybe_details| { @@ -700,10 +734,7 @@ pub mod pallet { /// /// Weight: `O(1)` #[pallet::weight(T::WeightInfo::thaw_class())] - pub fn thaw_class( - origin: OriginFor, - #[pallet::compact] class: T::ClassId, - ) -> DispatchResult { + pub fn thaw_class(origin: OriginFor, class: T::ClassId) -> DispatchResult { let origin = ensure_signed(origin)?; Class::::try_mutate(class, |maybe_details| { @@ -722,7 +753,8 @@ pub mod pallet { /// Origin must be Signed and the sender should be the Owner of the asset `class`. /// /// - `class`: The asset class whose owner should be changed. - /// - `owner`: The new Owner of this asset class. + /// - `owner`: The new Owner of this asset class. They must have called + /// `set_accept_ownership` with `class` in order for this operation to succeed. /// /// Emits `OwnerChanged`. /// @@ -730,12 +762,15 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::transfer_ownership())] pub fn transfer_ownership( origin: OriginFor, - #[pallet::compact] class: T::ClassId, + class: T::ClassId, owner: ::Source, ) -> DispatchResult { let origin = ensure_signed(origin)?; let owner = T::Lookup::lookup(owner)?; + let acceptable_class = OwnershipAcceptance::::get(&owner); + ensure!(acceptable_class.as_ref() == Some(&class), Error::::Unaccepted); + Class::::try_mutate(class, |maybe_details| { let details = maybe_details.as_mut().ok_or(Error::::UnknownClass)?; ensure!(&origin == &details.owner, Error::::NoPermission); @@ -753,6 +788,7 @@ pub mod pallet { ClassAccount::::remove(&details.owner, &class); ClassAccount::::insert(&owner, &class, ()); details.owner = owner.clone(); + OwnershipAcceptance::::remove(&owner); Self::deposit_event(Event::OwnerChanged { class, new_owner: owner }); Ok(()) @@ -774,7 +810,7 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::set_team())] pub fn set_team( origin: OriginFor, - #[pallet::compact] class: T::ClassId, + class: T::ClassId, issuer: ::Source, admin: ::Source, freezer: ::Source, @@ -811,8 +847,8 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::approve_transfer())] pub fn approve_transfer( origin: OriginFor, - #[pallet::compact] class: T::ClassId, - #[pallet::compact] instance: T::InstanceId, + class: T::ClassId, + instance: T::InstanceId, delegate: ::Source, ) -> DispatchResult { let maybe_check: Option = T::ForceOrigin::try_origin(origin) @@ -863,8 +899,8 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::cancel_approval())] pub fn cancel_approval( origin: OriginFor, - #[pallet::compact] class: T::ClassId, - #[pallet::compact] instance: T::InstanceId, + class: T::ClassId, + instance: T::InstanceId, maybe_check_delegate: Option<::Source>, ) -> DispatchResult { let maybe_check: Option = T::ForceOrigin::try_origin(origin) @@ -915,7 +951,7 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::force_asset_status())] pub fn force_asset_status( origin: OriginFor, - #[pallet::compact] class: T::ClassId, + class: T::ClassId, owner: ::Source, issuer: ::Source, admin: ::Source, @@ -964,7 +1000,7 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::set_attribute())] pub fn set_attribute( origin: OriginFor, - #[pallet::compact] class: T::ClassId, + class: T::ClassId, maybe_instance: Option, key: BoundedVec, value: BoundedVec, @@ -1027,7 +1063,7 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::clear_attribute())] pub fn clear_attribute( origin: OriginFor, - #[pallet::compact] class: T::ClassId, + class: T::ClassId, maybe_instance: Option, key: BoundedVec, ) -> DispatchResult { @@ -1077,8 +1113,8 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::set_metadata())] pub fn set_metadata( origin: OriginFor, - #[pallet::compact] class: T::ClassId, - #[pallet::compact] instance: T::InstanceId, + class: T::ClassId, + instance: T::InstanceId, data: BoundedVec, is_frozen: bool, ) -> DispatchResult { @@ -1139,8 +1175,8 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::clear_metadata())] pub fn clear_metadata( origin: OriginFor, - #[pallet::compact] class: T::ClassId, - #[pallet::compact] instance: T::InstanceId, + class: T::ClassId, + instance: T::InstanceId, ) -> DispatchResult { let maybe_check_owner = T::ForceOrigin::try_origin(origin) .map(|_| None) @@ -1188,7 +1224,7 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::set_class_metadata())] pub fn set_class_metadata( origin: OriginFor, - #[pallet::compact] class: T::ClassId, + class: T::ClassId, data: BoundedVec, is_frozen: bool, ) -> DispatchResult { @@ -1242,10 +1278,7 @@ pub mod pallet { /// /// Weight: `O(1)` #[pallet::weight(T::WeightInfo::clear_class_metadata())] - pub fn clear_class_metadata( - origin: OriginFor, - #[pallet::compact] class: T::ClassId, - ) -> DispatchResult { + pub fn clear_class_metadata(origin: OriginFor, class: T::ClassId) -> DispatchResult { let maybe_check_owner = T::ForceOrigin::try_origin(origin) .map(|_| None) .or_else(|origin| ensure_signed(origin).map(Some))?; @@ -1265,5 +1298,40 @@ pub mod pallet { Ok(()) }) } + + /// Set (or reset) the acceptance of ownership for a particular account. + /// + /// Origin must be `Signed` and if `maybe_class` is `Some`, then the signer must have a + /// provider reference. + /// + /// - `maybe_class`: The identifier of the asset class whose ownership the signer is willing + /// to accept, or if `None`, an indication that the signer is willing to accept no + /// ownership transferal. + /// + /// Emits `OwnershipAcceptanceChanged`. + #[pallet::weight(T::WeightInfo::set_accept_ownership())] + pub fn set_accept_ownership( + origin: OriginFor, + maybe_class: Option, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + let old = OwnershipAcceptance::::get(&who); + match (old.is_some(), maybe_class.is_some()) { + (false, true) => { + frame_system::Pallet::::inc_consumers(&who)?; + }, + (true, false) => { + frame_system::Pallet::::dec_consumers(&who); + }, + _ => {}, + } + if let Some(class) = maybe_class.as_ref() { + OwnershipAcceptance::::insert(&who, class); + } else { + OwnershipAcceptance::::remove(&who); + } + Self::deposit_event(Event::OwnershipAcceptanceChanged { who, maybe_class }); + Ok(()) + } } } diff --git a/frame/uniques/src/mock.rs b/frame/uniques/src/mock.rs index 2a94fcbee347..265142443ef4 100644 --- a/frame/uniques/src/mock.rs +++ b/frame/uniques/src/mock.rs @@ -22,7 +22,7 @@ use crate as pallet_uniques; use frame_support::{ construct_runtime, - traits::{ConstU32, ConstU64}, + traits::{AsEnsureOriginWithArg, ConstU32, ConstU64}, }; use sp_core::H256; use sp_runtime::{ @@ -89,6 +89,7 @@ impl Config for Test { type ClassId = u32; type InstanceId = u32; type Currency = Balances; + type CreateOrigin = AsEnsureOriginWithArg>; type ForceOrigin = frame_system::EnsureRoot; type ClassDeposit = ConstU64<2>; type InstanceDeposit = ConstU64<1>; @@ -99,6 +100,8 @@ impl Config for Test { type KeyLimit = ConstU32<50>; type ValueLimit = ConstU32<50>; type WeightInfo = (); + #[cfg(feature = "runtime-benchmarks")] + type Helper = (); } pub(crate) fn new_test_ext() -> sp_io::TestExternalities { diff --git a/frame/uniques/src/tests.rs b/frame/uniques/src/tests.rs index 12f39c78bfe3..364073ad37cd 100644 --- a/frame/uniques/src/tests.rs +++ b/frame/uniques/src/tests.rs @@ -196,6 +196,9 @@ fn origin_guards_should_work() { new_test_ext().execute_with(|| { assert_ok!(Uniques::force_create(Origin::root(), 0, 1, true)); assert_ok!(Uniques::mint(Origin::signed(1), 0, 42, 1)); + + Balances::make_free_balance_be(&2, 100); + assert_ok!(Uniques::set_accept_ownership(Origin::signed(2), Some(0))); assert_noop!( Uniques::transfer_ownership(Origin::signed(2), 0, 2), Error::::NoPermission @@ -218,13 +221,20 @@ fn transfer_owner_should_work() { Balances::make_free_balance_be(&3, 100); assert_ok!(Uniques::create(Origin::signed(1), 0, 1)); assert_eq!(classes(), vec![(1, 0)]); + assert_noop!( + Uniques::transfer_ownership(Origin::signed(1), 0, 2), + Error::::Unaccepted + ); + assert_ok!(Uniques::set_accept_ownership(Origin::signed(2), Some(0))); assert_ok!(Uniques::transfer_ownership(Origin::signed(1), 0, 2)); + assert_eq!(classes(), vec![(2, 0)]); assert_eq!(Balances::total_balance(&1), 98); assert_eq!(Balances::total_balance(&2), 102); assert_eq!(Balances::reserved_balance(&1), 0); assert_eq!(Balances::reserved_balance(&2), 2); + assert_ok!(Uniques::set_accept_ownership(Origin::signed(1), Some(0))); assert_noop!( Uniques::transfer_ownership(Origin::signed(1), 0, 1), Error::::NoPermission @@ -234,12 +244,20 @@ fn transfer_owner_should_work() { assert_ok!(Uniques::set_class_metadata(Origin::signed(2), 0, bvec![0u8; 20], false)); assert_ok!(Uniques::mint(Origin::signed(1), 0, 42, 1)); assert_ok!(Uniques::set_metadata(Origin::signed(2), 0, 42, bvec![0u8; 20], false)); + assert_ok!(Uniques::set_accept_ownership(Origin::signed(3), Some(0))); assert_ok!(Uniques::transfer_ownership(Origin::signed(2), 0, 3)); assert_eq!(classes(), vec![(3, 0)]); assert_eq!(Balances::total_balance(&2), 57); assert_eq!(Balances::total_balance(&3), 145); assert_eq!(Balances::reserved_balance(&2), 0); assert_eq!(Balances::reserved_balance(&3), 45); + + // 2's acceptence from before is reset when it became owner, so it cannot be transfered + // without a fresh acceptance. + assert_noop!( + Uniques::transfer_ownership(Origin::signed(3), 0, 2), + Error::::Unaccepted + ); }); } diff --git a/frame/uniques/src/weights.rs b/frame/uniques/src/weights.rs index 1df8fe0ff665..eb9067b7133a 100644 --- a/frame/uniques/src/weights.rs +++ b/frame/uniques/src/weights.rs @@ -68,6 +68,7 @@ pub trait WeightInfo { fn clear_class_metadata() -> Weight; fn approve_transfer() -> Weight; fn cancel_approval() -> Weight; + fn set_accept_ownership() -> Weight; } /// Weights for pallet_uniques using the Substrate node and recommended hardware. @@ -249,6 +250,13 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } + // Storage: Uniques Class (r:1 w:0) + // Storage: Uniques Asset (r:1 w:1) + fn set_accept_ownership() -> Weight { + (19_417_000 as Weight) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } } // For backwards compatibility and tests @@ -429,4 +437,11 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } + // Storage: Uniques Class (r:1 w:0) + // Storage: Uniques Asset (r:1 w:1) + fn set_accept_ownership() -> Weight { + (19_417_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } } From 55192ea3f13e8a3d84b228b98922881c2cd94cba Mon Sep 17 00:00:00 2001 From: Zeke Mostov Date: Tue, 8 Mar 2022 12:31:20 +0000 Subject: [PATCH 573/695] election provider support: Update some test only types (#10983) --- frame/election-provider-support/src/lib.rs | 35 ++++------------------ 1 file changed, 6 insertions(+), 29 deletions(-) diff --git a/frame/election-provider-support/src/lib.rs b/frame/election-provider-support/src/lib.rs index 26efe5107b67..ca22e3093855 100644 --- a/frame/election-provider-support/src/lib.rs +++ b/frame/election-provider-support/src/lib.rs @@ -262,33 +262,6 @@ pub trait ElectionDataProvider { fn clear() {} } -/// An election data provider that should only be used for testing. -#[cfg(feature = "std")] -pub struct TestDataProvider(sp_std::marker::PhantomData); - -#[cfg(feature = "std")] -impl ElectionDataProvider for TestDataProvider<(AccountId, BlockNumber)> { - type AccountId = AccountId; - type BlockNumber = BlockNumber; - type MaxVotesPerVoter = (); - - fn targets(_maybe_max_len: Option) -> data_provider::Result> { - Ok(Default::default()) - } - - fn voters(_maybe_max_len: Option) -> data_provider::Result>> { - Ok(Default::default()) - } - - fn desired_targets() -> data_provider::Result { - Ok(Default::default()) - } - - fn next_election_prediction(now: BlockNumber) -> BlockNumber { - now - } -} - /// Something that can compute the result of an election and pass it back to the caller. /// /// This trait only provides an interface to _request_ an election, i.e. @@ -340,11 +313,15 @@ pub trait InstantElectionProvider: ElectionProvider { pub struct NoElection(sp_std::marker::PhantomData); #[cfg(feature = "std")] -impl ElectionProvider for NoElection<(AccountId, BlockNumber)> { +impl ElectionProvider + for NoElection<(AccountId, BlockNumber, DataProvider)> +where + DataProvider: ElectionDataProvider, +{ type AccountId = AccountId; type BlockNumber = BlockNumber; type Error = &'static str; - type DataProvider = TestDataProvider<(AccountId, BlockNumber)>; + type DataProvider = DataProvider; fn elect() -> Result, Self::Error> { Err(" cannot do anything.") From 8df8d908c4d77a8dd19751784b6aca62159ddda8 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Tue, 8 Mar 2022 08:48:30 -0400 Subject: [PATCH 574/695] Feedback from @XLC for Referenda Pallet (#10991) * feedback from @xlc * english * fmt Signed-off-by: Oliver Tale-Yazdi Co-authored-by: Oliver Tale-Yazdi --- frame/referenda/src/benchmarking.rs | 4 +-- frame/referenda/src/lib.rs | 22 +++++++--------- frame/referenda/src/mock.rs | 4 +-- frame/referenda/src/tests.rs | 39 ++++++++++++++++------------ frame/referenda/src/types.rs | 22 +--------------- frame/support/src/traits/schedule.rs | 13 ++++++++-- 6 files changed, 47 insertions(+), 57 deletions(-) diff --git a/frame/referenda/src/benchmarking.rs b/frame/referenda/src/benchmarking.rs index 76a8173f16c9..08612e0614ae 100644 --- a/frame/referenda/src/benchmarking.rs +++ b/frame/referenda/src/benchmarking.rs @@ -48,7 +48,7 @@ fn create_referendum() -> (T::AccountId, ReferendumIndex) { RawOrigin::Signed(caller.clone()).into(), RawOrigin::Root.into(), T::Hashing::hash_of(&0), - AtOrAfter::After(0u32.into()) + DispatchTime::After(0u32.into()) )); let index = ReferendumCount::::get() - 1; (caller, index) @@ -182,7 +182,7 @@ benchmarks! { RawOrigin::Signed(caller), RawOrigin::Root.into(), T::Hashing::hash_of(&0), - AtOrAfter::After(0u32.into()) + DispatchTime::After(0u32.into()) ) verify { let index = ReferendumCount::::get().checked_sub(1).unwrap(); assert_matches!(ReferendumInfoFor::::get(index), Some(ReferendumInfo::Ongoing(_))); diff --git a/frame/referenda/src/lib.rs b/frame/referenda/src/lib.rs index 2d4d29b0bc13..fb19d2b9ed24 100644 --- a/frame/referenda/src/lib.rs +++ b/frame/referenda/src/lib.rs @@ -68,8 +68,8 @@ use frame_support::{ v2::{Anon as ScheduleAnon, Named as ScheduleNamed}, DispatchTime, MaybeHashed, }, - Currency, Get, LockIdentifier, LockableCurrency, OnUnbalanced, OriginTrait, PollStatus, - Polling, ReservableCurrency, VoteTally, + Currency, Get, LockIdentifier, OnUnbalanced, OriginTrait, PollStatus, Polling, + ReservableCurrency, VoteTally, }, BoundedVec, }; @@ -86,7 +86,7 @@ pub mod weights; use branch::{BeginDecidingBranch, OneFewerDecidingBranch, ServiceBranch}; pub use pallet::*; pub use types::{ - AtOrAfter, BalanceOf, CallOf, Curve, DecidingStatus, DecidingStatusOf, Deposit, InsertSorted, + BalanceOf, CallOf, Curve, DecidingStatus, DecidingStatusOf, Deposit, InsertSorted, NegativeImbalanceOf, PalletsOriginOf, ReferendumIndex, ReferendumInfo, ReferendumInfoOf, ReferendumStatus, ReferendumStatusOf, ScheduleAddressOf, TallyOf, TrackIdOf, TrackInfo, TrackInfoOf, TracksInfo, VotesOf, @@ -126,9 +126,7 @@ pub mod pallet { type Scheduler: ScheduleAnon, PalletsOriginOf, Hash = Self::Hash> + ScheduleNamed, PalletsOriginOf, Hash = Self::Hash>; /// Currency type for this pallet. - type Currency: ReservableCurrency - + LockableCurrency; - + type Currency: ReservableCurrency; // Origins and unbalances. /// Origin from which any vote may be cancelled. type CancelOrigin: EnsureOrigin; @@ -175,8 +173,6 @@ pub mod pallet { pub type ReferendumCount = StorageValue<_, ReferendumIndex, ValueQuery>; /// Information concerning any given referendum. - /// - /// TWOX-NOTE: SAFE as indexes are not under an attacker’s control. #[pallet::storage] pub type ReferendumInfoFor = StorageMap<_, Blake2_128Concat, ReferendumIndex, ReferendumInfoOf>; @@ -301,7 +297,7 @@ pub mod pallet { /// Referendum is not ongoing. NotOngoing, /// Referendum's decision deposit is already paid. - HaveDeposit, + HasDeposit, /// The track identifier given was invalid. BadTrack, /// There are already a full complement of referendums in progress for this track. @@ -338,7 +334,7 @@ pub mod pallet { origin: OriginFor, proposal_origin: PalletsOriginOf, proposal_hash: T::Hash, - enactment_moment: AtOrAfter, + enactment_moment: DispatchTime, ) -> DispatchResult { let who = ensure_signed(origin)?; @@ -385,7 +381,7 @@ pub mod pallet { ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; let mut status = Self::ensure_ongoing(index)?; - ensure!(status.decision_deposit.is_none(), Error::::HaveDeposit); + ensure!(status.decision_deposit.is_none(), Error::::HasDeposit); let track = Self::track(status.track).ok_or(Error::::NoTrack)?; status.decision_deposit = Some(Self::take_deposit(who.clone(), track.decision_deposit)?); @@ -598,7 +594,7 @@ impl Polling for Pallet { track: class, origin: frame_support::dispatch::RawOrigin::Root.into(), proposal_hash: ::hash_of(&index), - enactment: AtOrAfter::After(Zero::zero()), + enactment: DispatchTime::After(Zero::zero()), submitted: now, submission_deposit: Deposit { who: dummy_account_id, amount: Zero::zero() }, decision_deposit: None, @@ -651,7 +647,7 @@ impl Pallet { fn schedule_enactment( index: ReferendumIndex, track: &TrackInfoOf, - desired: AtOrAfter, + desired: DispatchTime, origin: PalletsOriginOf, call_hash: T::Hash, ) { diff --git a/frame/referenda/src/mock.rs b/frame/referenda/src/mock.rs index 063b124f2b71..fdd14fdadf04 100644 --- a/frame/referenda/src/mock.rs +++ b/frame/referenda/src/mock.rs @@ -306,7 +306,7 @@ pub fn propose_set_balance(who: u64, value: u64, delay: u64) -> DispatchResult { Origin::signed(who), frame_system::RawOrigin::Root.into(), set_balance_proposal_hash(value), - AtOrAfter::After(delay), + DispatchTime::After(delay), ) } @@ -434,7 +434,7 @@ impl RefState { Origin::signed(1), frame_support::dispatch::RawOrigin::Root.into(), set_balance_proposal_hash(1), - AtOrAfter::At(10), + DispatchTime::At(10), )); assert_ok!(Referenda::place_decision_deposit(Origin::signed(2), 0)); if matches!(self, RefState::Confirming { immediate: true }) { diff --git a/frame/referenda/src/tests.rs b/frame/referenda/src/tests.rs index cea071ced12f..96edd4ce879c 100644 --- a/frame/referenda/src/tests.rs +++ b/frame/referenda/src/tests.rs @@ -47,7 +47,7 @@ fn basic_happy_path_works() { Origin::signed(1), RawOrigin::Root.into(), set_balance_proposal_hash(1), - AtOrAfter::At(10), + DispatchTime::At(10), )); assert_eq!(Balances::reserved_balance(&1), 2); assert_eq!(ReferendumCount::::get(), 1); @@ -178,7 +178,7 @@ fn queueing_works() { Origin::signed(5), RawOrigin::Root.into(), set_balance_proposal_hash(0), - AtOrAfter::After(0), + DispatchTime::After(0), )); assert_ok!(Referenda::place_decision_deposit(Origin::signed(5), 0)); @@ -190,7 +190,7 @@ fn queueing_works() { Origin::signed(i), RawOrigin::Root.into(), set_balance_proposal_hash(i), - AtOrAfter::After(0), + DispatchTime::After(0), )); assert_ok!(Referenda::place_decision_deposit(Origin::signed(i), i as u32)); // TODO: decision deposit after some initial votes with a non-highest voted coming @@ -275,7 +275,7 @@ fn auto_timeout_should_happen_with_nothing_but_submit() { Origin::signed(1), RawOrigin::Root.into(), set_balance_proposal_hash(1), - AtOrAfter::At(20), + DispatchTime::At(20), )); run_to(20); assert_matches!(ReferendumInfoFor::::get(0), Some(ReferendumInfo::Ongoing(..))); @@ -295,13 +295,13 @@ fn tracks_are_distinguished() { Origin::signed(1), RawOrigin::Root.into(), set_balance_proposal_hash(1), - AtOrAfter::At(10), + DispatchTime::At(10), )); assert_ok!(Referenda::submit( Origin::signed(2), RawOrigin::None.into(), set_balance_proposal_hash(2), - AtOrAfter::At(20), + DispatchTime::At(20), )); assert_ok!(Referenda::place_decision_deposit(Origin::signed(3), 0)); @@ -318,7 +318,7 @@ fn tracks_are_distinguished() { track: 0, origin: OriginCaller::system(RawOrigin::Root), proposal_hash: set_balance_proposal_hash(1), - enactment: AtOrAfter::At(10), + enactment: DispatchTime::At(10), submitted: 1, submission_deposit: Deposit { who: 1, amount: 2 }, decision_deposit: Some(Deposit { who: 3, amount: 10 }), @@ -334,7 +334,7 @@ fn tracks_are_distinguished() { track: 1, origin: OriginCaller::system(RawOrigin::None), proposal_hash: set_balance_proposal_hash(2), - enactment: AtOrAfter::At(20), + enactment: DispatchTime::At(20), submitted: 1, submission_deposit: Deposit { who: 2, amount: 2 }, decision_deposit: Some(Deposit { who: 4, amount: 1 }), @@ -355,13 +355,18 @@ fn submit_errors_work() { let h = set_balance_proposal_hash(1); // No track for Signed origins. assert_noop!( - Referenda::submit(Origin::signed(1), RawOrigin::Signed(2).into(), h, AtOrAfter::At(10),), + Referenda::submit( + Origin::signed(1), + RawOrigin::Signed(2).into(), + h, + DispatchTime::At(10), + ), Error::::NoTrack ); // No funds for deposit assert_noop!( - Referenda::submit(Origin::signed(10), RawOrigin::Root.into(), h, AtOrAfter::At(10),), + Referenda::submit(Origin::signed(10), RawOrigin::Root.into(), h, DispatchTime::At(10),), BalancesError::::InsufficientBalance ); }); @@ -378,13 +383,13 @@ fn decision_deposit_errors_work() { Origin::signed(1), RawOrigin::Root.into(), h, - AtOrAfter::At(10), + DispatchTime::At(10), )); let e = BalancesError::::InsufficientBalance; assert_noop!(Referenda::place_decision_deposit(Origin::signed(10), 0), e); assert_ok!(Referenda::place_decision_deposit(Origin::signed(2), 0)); - let e = Error::::HaveDeposit; + let e = Error::::HasDeposit; assert_noop!(Referenda::place_decision_deposit(Origin::signed(2), 0), e); }); } @@ -400,7 +405,7 @@ fn refund_deposit_works() { Origin::signed(1), RawOrigin::Root.into(), h, - AtOrAfter::At(10), + DispatchTime::At(10), )); let e = Error::::NoDeposit; assert_noop!(Referenda::refund_decision_deposit(Origin::signed(2), 0), e); @@ -422,7 +427,7 @@ fn cancel_works() { Origin::signed(1), RawOrigin::Root.into(), h, - AtOrAfter::At(10), + DispatchTime::At(10), )); assert_ok!(Referenda::place_decision_deposit(Origin::signed(2), 0)); @@ -441,7 +446,7 @@ fn cancel_errors_works() { Origin::signed(1), RawOrigin::Root.into(), h, - AtOrAfter::At(10), + DispatchTime::At(10), )); assert_ok!(Referenda::place_decision_deposit(Origin::signed(2), 0)); assert_noop!(Referenda::cancel(Origin::signed(1), 0), BadOrigin); @@ -459,7 +464,7 @@ fn kill_works() { Origin::signed(1), RawOrigin::Root.into(), h, - AtOrAfter::At(10), + DispatchTime::At(10), )); assert_ok!(Referenda::place_decision_deposit(Origin::signed(2), 0)); @@ -479,7 +484,7 @@ fn kill_errors_works() { Origin::signed(1), RawOrigin::Root.into(), h, - AtOrAfter::At(10), + DispatchTime::At(10), )); assert_ok!(Referenda::place_decision_deposit(Origin::signed(2), 0)); assert_noop!(Referenda::kill(Origin::signed(4), 0), BadOrigin); diff --git a/frame/referenda/src/types.rs b/frame/referenda/src/types.rs index 367fa2a4ba45..8ea9fc3faf3d 100644 --- a/frame/referenda/src/types.rs +++ b/frame/referenda/src/types.rs @@ -185,26 +185,6 @@ pub trait TracksInfo { } } -/// Indication of either a specific moment or a delay from a implicitly defined moment. -#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] -pub enum AtOrAfter { - /// Indiciates that the event should occur at the moment given. - At(Moment), - /// Indiciates that the event should occur some period of time (defined by the parameter) after - /// a prior event. The prior event is defined by the context, but for the purposes of - /// referendum proposals, the "prior event" is the passing of the referendum. - After(Moment), -} - -impl AtOrAfter { - pub fn evaluate(&self, since: Moment) -> Moment { - match &self { - Self::At(m) => *m, - Self::After(m) => m.saturating_add(since), - } - } -} - /// Info regarding an ongoing referendum. #[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] pub struct ReferendumStatus< @@ -224,7 +204,7 @@ pub struct ReferendumStatus< /// The hash of the proposal up for referendum. pub(crate) proposal_hash: Hash, /// The time the proposal should be scheduled for enactment. - pub(crate) enactment: AtOrAfter, + pub(crate) enactment: DispatchTime, /// The time of submission. Once `UndecidingTimeout` passes, it may be closed by anyone if it /// `deciding` is `None`. pub(crate) submitted: Moment, diff --git a/frame/support/src/traits/schedule.rs b/frame/support/src/traits/schedule.rs index 3b8e6da3e2ef..c2d0d4bc3b81 100644 --- a/frame/support/src/traits/schedule.rs +++ b/frame/support/src/traits/schedule.rs @@ -19,7 +19,7 @@ use codec::{Codec, Decode, Encode, EncodeLike, MaxEncodedLen}; use scale_info::TypeInfo; -use sp_runtime::{DispatchError, RuntimeDebug}; +use sp_runtime::{traits::Saturating, DispatchError, RuntimeDebug}; use sp_std::{fmt::Debug, prelude::*, result::Result}; /// Information relating to the period of a scheduled task. First item is the length of the @@ -32,7 +32,7 @@ pub type Period = (BlockNumber, u32); pub type Priority = u8; /// The dispatch time of a scheduled task. -#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] +#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] pub enum DispatchTime { /// At specified block. At(BlockNumber), @@ -40,6 +40,15 @@ pub enum DispatchTime { After(BlockNumber), } +impl DispatchTime { + pub fn evaluate(&self, since: BlockNumber) -> BlockNumber { + match &self { + Self::At(m) => *m, + Self::After(m) => m.saturating_add(since), + } + } +} + /// The highest priority. We invert the value so that normal sorting will place the highest /// priority at the beginning of the list. pub const HIGHEST_PRIORITY: Priority = 0; From b36030a6e8c21af9f18bb0d6a667188fac0dbc47 Mon Sep 17 00:00:00 2001 From: Zeke Mostov Date: Wed, 9 Mar 2022 16:28:28 +0000 Subject: [PATCH 575/695] Make bags-list generic over node value and instantiable (#10997) * make instantiable * update * cargo fmt * Clean up * bags-list: Make it generic over node value * Respond to some feedback * Apply suggestions from code review Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> * Add back default impl for weight update worst case * Update to Score in more places' * Use VoteWeight, not u64 to reduce test diff * FMT * FullCodec implies Codec * formatting * Fixup bags list remote test Co-authored-by: doordashcon Co-authored-by: Doordashcon <90750465+Doordashcon@users.noreply.github.com> Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> --- bin/node/runtime/src/lib.rs | 3 +- frame/bags-list/remote-tests/src/lib.rs | 23 +- frame/bags-list/src/benchmarks.rs | 47 +++-- frame/bags-list/src/lib.rs | 146 +++++++------ frame/bags-list/src/list/mod.rs | 235 +++++++++++---------- frame/bags-list/src/list/tests.rs | 143 ++++++++++--- frame/bags-list/src/mock.rs | 15 +- frame/bags-list/src/tests.rs | 38 ++-- frame/election-provider-support/Cargo.toml | 2 +- frame/election-provider-support/src/lib.rs | 28 +-- frame/staking/src/benchmarking.rs | 2 +- frame/staking/src/mock.rs | 5 +- frame/staking/src/pallet/impls.rs | 19 +- frame/staking/src/pallet/mod.rs | 5 +- 14 files changed, 428 insertions(+), 283 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index e2903c0b314d..8c7a20af1568 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -690,9 +690,10 @@ parameter_types! { impl pallet_bags_list::Config for Runtime { type Event = Event; - type VoteWeightProvider = Staking; + type ScoreProvider = Staking; type WeightInfo = pallet_bags_list::weights::SubstrateWeight; type BagThresholds = BagThresholds; + type Score = sp_npos_elections::VoteWeight; } parameter_types! { diff --git a/frame/bags-list/remote-tests/src/lib.rs b/frame/bags-list/remote-tests/src/lib.rs index 9a88ff24f2f3..83c322f93134 100644 --- a/frame/bags-list/remote-tests/src/lib.rs +++ b/frame/bags-list/remote-tests/src/lib.rs @@ -17,6 +17,7 @@ //! Utilities for remote-testing pallet-bags-list. +use frame_election_provider_support::ScoreProvider; use sp_std::prelude::*; /// A common log target to use. @@ -55,8 +56,12 @@ pub fn display_and_check_bags(currency_unit: u64, currency_na let mut rebaggable = 0; let mut active_bags = 0; for vote_weight_thresh in ::BagThresholds::get() { + let vote_weight_thresh_u64: u64 = (*vote_weight_thresh) + .try_into() + .map_err(|_| "runtime must configure score to at most u64 to use this test") + .unwrap(); // threshold in terms of UNITS (e.g. KSM, DOT etc) - let vote_weight_thresh_as_unit = *vote_weight_thresh as f64 / currency_unit as f64; + let vote_weight_thresh_as_unit = vote_weight_thresh_u64 as f64 / currency_unit as f64; let pretty_thresh = format!("Threshold: {}. {}", vote_weight_thresh_as_unit, currency_name); let bag = match pallet_bags_list::Pallet::::list_bags_get(*vote_weight_thresh) { @@ -70,9 +75,13 @@ pub fn display_and_check_bags(currency_unit: u64, currency_na active_bags += 1; for id in bag.std_iter().map(|node| node.std_id().clone()) { - let vote_weight = pallet_staking::Pallet::::weight_of(&id); + let vote_weight = ::ScoreProvider::score(&id); + let vote_weight_thresh_u64: u64 = (*vote_weight_thresh) + .try_into() + .map_err(|_| "runtime must configure score to at most u64 to use this test") + .unwrap(); let vote_weight_as_balance: pallet_staking::BalanceOf = - vote_weight.try_into().map_err(|_| "can't convert").unwrap(); + vote_weight_thresh_u64.try_into().map_err(|_| "can't convert").unwrap(); if vote_weight_as_balance < min_nominator_bond { log::trace!( @@ -87,13 +96,17 @@ pub fn display_and_check_bags(currency_unit: u64, currency_na pallet_bags_list::Node::::get(&id).expect("node in bag must exist."); if node.is_misplaced(vote_weight) { rebaggable += 1; + let notional_bag = pallet_bags_list::notional_bag_for::(vote_weight); + let notional_bag_as_u64: u64 = notional_bag + .try_into() + .map_err(|_| "runtime must configure score to at most u64 to use this test") + .unwrap(); log::trace!( target: LOG_TARGET, "Account {:?} can be rebagged from {:?} to {:?}", id, vote_weight_thresh_as_unit, - pallet_bags_list::notional_bag_for::(vote_weight) as f64 / - currency_unit as f64 + notional_bag_as_u64 as f64 / currency_unit as f64 ); } } diff --git a/frame/bags-list/src/benchmarks.rs b/frame/bags-list/src/benchmarks.rs index cc575d7d1eff..b94a97093d00 100644 --- a/frame/bags-list/src/benchmarks.rs +++ b/frame/bags-list/src/benchmarks.rs @@ -20,9 +20,10 @@ use super::*; use crate::list::List; use frame_benchmarking::{account, whitelist_account, whitelisted_caller}; -use frame_election_provider_support::VoteWeightProvider; +use frame_election_provider_support::ScoreProvider; use frame_support::{assert_ok, traits::Get}; use frame_system::RawOrigin as SystemOrigin; +use sp_runtime::traits::One; frame_benchmarking::benchmarks! { rebag_non_terminal { @@ -36,7 +37,7 @@ frame_benchmarking::benchmarks! { // clear any pre-existing storage. // NOTE: safe to call outside block production - List::::unsafe_clear(); + List::::unsafe_clear(); // define our origin and destination thresholds. let origin_bag_thresh = T::BagThresholds::get()[0]; @@ -44,21 +45,21 @@ frame_benchmarking::benchmarks! { // seed items in the origin bag. let origin_head: T::AccountId = account("origin_head", 0, 0); - assert_ok!(List::::insert(origin_head.clone(), origin_bag_thresh)); + assert_ok!(List::::insert(origin_head.clone(), origin_bag_thresh)); let origin_middle: T::AccountId = account("origin_middle", 0, 0); // the node we rebag (_R_) - assert_ok!(List::::insert(origin_middle.clone(), origin_bag_thresh)); + assert_ok!(List::::insert(origin_middle.clone(), origin_bag_thresh)); let origin_tail: T::AccountId = account("origin_tail", 0, 0); - assert_ok!(List::::insert(origin_tail.clone(), origin_bag_thresh)); + assert_ok!(List::::insert(origin_tail.clone(), origin_bag_thresh)); // seed items in the destination bag. let dest_head: T::AccountId = account("dest_head", 0, 0); - assert_ok!(List::::insert(dest_head.clone(), dest_bag_thresh)); + assert_ok!(List::::insert(dest_head.clone(), dest_bag_thresh)); // the bags are in the expected state after initial setup. assert_eq!( - List::::get_bags(), + List::::get_bags(), vec![ (origin_bag_thresh, vec![origin_head.clone(), origin_middle.clone(), origin_tail.clone()]), (dest_bag_thresh, vec![dest_head.clone()]) @@ -67,12 +68,12 @@ frame_benchmarking::benchmarks! { let caller = whitelisted_caller(); // update the weight of `origin_middle` to guarantee it will be rebagged into the destination. - T::VoteWeightProvider::set_vote_weight_of(&origin_middle, dest_bag_thresh); + T::ScoreProvider::set_score_of(&origin_middle, dest_bag_thresh); }: rebag(SystemOrigin::Signed(caller), origin_middle.clone()) verify { // check the bags have updated as expected. assert_eq!( - List::::get_bags(), + List::::get_bags(), vec![ ( origin_bag_thresh, @@ -104,18 +105,18 @@ frame_benchmarking::benchmarks! { // seed items in the origin bag. let origin_head: T::AccountId = account("origin_head", 0, 0); - assert_ok!(List::::insert(origin_head.clone(), origin_bag_thresh)); + assert_ok!(List::::insert(origin_head.clone(), origin_bag_thresh)); let origin_tail: T::AccountId = account("origin_tail", 0, 0); // the node we rebag (_R_) - assert_ok!(List::::insert(origin_tail.clone(), origin_bag_thresh)); + assert_ok!(List::::insert(origin_tail.clone(), origin_bag_thresh)); // seed items in the destination bag. let dest_head: T::AccountId = account("dest_head", 0, 0); - assert_ok!(List::::insert(dest_head.clone(), dest_bag_thresh)); + assert_ok!(List::::insert(dest_head.clone(), dest_bag_thresh)); // the bags are in the expected state after initial setup. assert_eq!( - List::::get_bags(), + List::::get_bags(), vec![ (origin_bag_thresh, vec![origin_head.clone(), origin_tail.clone()]), (dest_bag_thresh, vec![dest_head.clone()]) @@ -124,12 +125,12 @@ frame_benchmarking::benchmarks! { let caller = whitelisted_caller(); // update the weight of `origin_tail` to guarantee it will be rebagged into the destination. - T::VoteWeightProvider::set_vote_weight_of(&origin_tail, dest_bag_thresh); + T::ScoreProvider::set_score_of(&origin_tail, dest_bag_thresh); }: rebag(SystemOrigin::Signed(caller), origin_tail.clone()) verify { // check the bags have updated as expected. assert_eq!( - List::::get_bags(), + List::::get_bags(), vec![ (origin_bag_thresh, vec![origin_head.clone()]), (dest_bag_thresh, vec![dest_head.clone(), origin_tail.clone()]) @@ -147,22 +148,22 @@ frame_benchmarking::benchmarks! { // insert the nodes in order let lighter: T::AccountId = account("lighter", 0, 0); - assert_ok!(List::::insert(lighter.clone(), bag_thresh)); + assert_ok!(List::::insert(lighter.clone(), bag_thresh)); let heavier_prev: T::AccountId = account("heavier_prev", 0, 0); - assert_ok!(List::::insert(heavier_prev.clone(), bag_thresh)); + assert_ok!(List::::insert(heavier_prev.clone(), bag_thresh)); let heavier: T::AccountId = account("heavier", 0, 0); - assert_ok!(List::::insert(heavier.clone(), bag_thresh)); + assert_ok!(List::::insert(heavier.clone(), bag_thresh)); let heavier_next: T::AccountId = account("heavier_next", 0, 0); - assert_ok!(List::::insert(heavier_next.clone(), bag_thresh)); + assert_ok!(List::::insert(heavier_next.clone(), bag_thresh)); - T::VoteWeightProvider::set_vote_weight_of(&lighter, bag_thresh - 1); - T::VoteWeightProvider::set_vote_weight_of(&heavier, bag_thresh); + T::ScoreProvider::set_score_of(&lighter, bag_thresh - One::one()); + T::ScoreProvider::set_score_of(&heavier, bag_thresh); assert_eq!( - List::::iter().map(|n| n.id().clone()).collect::>(), + List::::iter().map(|n| n.id().clone()).collect::>(), vec![lighter.clone(), heavier_prev.clone(), heavier.clone(), heavier_next.clone()] ); @@ -170,7 +171,7 @@ frame_benchmarking::benchmarks! { }: _(SystemOrigin::Signed(heavier.clone()), lighter.clone()) verify { assert_eq!( - List::::iter().map(|n| n.id().clone()).collect::>(), + List::::iter().map(|n| n.id().clone()).collect::>(), vec![heavier, lighter, heavier_prev, heavier_next] ) } diff --git a/frame/bags-list/src/lib.rs b/frame/bags-list/src/lib.rs index 89c54db87023..c502245409fd 100644 --- a/frame/bags-list/src/lib.rs +++ b/frame/bags-list/src/lib.rs @@ -17,13 +17,14 @@ //! # Bags-List Pallet //! -//! A semi-sorted list, where items hold an `AccountId` based on some `VoteWeight`. The `AccountId` -//! (`id` for short) might be synonym to a `voter` or `nominator` in some context, and `VoteWeight` -//! signifies the chance of each id being included in the final [`SortedListProvider::iter`]. +//! A semi-sorted list, where items hold an `AccountId` based on some `Score`. The +//! `AccountId` (`id` for short) might be synonym to a `voter` or `nominator` in some context, and +//! `Score` signifies the chance of each id being included in the final +//! [`SortedListProvider::iter`]. //! //! It implements [`frame_election_provider_support::SortedListProvider`] to provide a semi-sorted //! list of accounts to another pallet. It needs some other pallet to give it some information about -//! the weights of accounts via [`frame_election_provider_support::VoteWeightProvider`]. +//! the weights of accounts via [`frame_election_provider_support::ScoreProvider`]. //! //! This pallet is not configurable at genesis. Whoever uses it should call appropriate functions of //! the `SortedListProvider` (e.g. `on_insert`, or `unsafe_regenerate`) at their genesis. @@ -33,12 +34,12 @@ //! The data structure exposed by this pallet aims to be optimized for: //! //! - insertions and removals. -//! - iteration over the top* N items by weight, where the precise ordering of items doesn't +//! - iteration over the top* N items by score, where the precise ordering of items doesn't //! particularly matter. //! //! # Details //! -//! - items are kept in bags, which are delineated by their range of weight (See +//! - items are kept in bags, which are delineated by their range of score (See //! [`Config::BagThresholds`]). //! - for iteration, bags are chained together from highest to lowest and elements within the bag //! are iterated from head to tail. @@ -46,14 +47,16 @@ //! it will worsen its position in list iteration; this reduces incentives for some types of spam //! that involve consistently removing and inserting for better position. Further, ordering //! granularity is thus dictated by range between each bag threshold. -//! - if an item's weight changes to a value no longer within the range of its current bag the -//! item's position will need to be updated by an external actor with rebag (update), or removal -//! and insertion. +//! - if an item's score changes to a value no longer within the range of its current bag the item's +//! position will need to be updated by an external actor with rebag (update), or removal and +//! insertion. #![cfg_attr(not(feature = "std"), no_std)] -use frame_election_provider_support::{SortedListProvider, VoteWeight, VoteWeightProvider}; +use codec::FullCodec; +use frame_election_provider_support::{ScoreProvider, SortedListProvider}; use frame_system::ensure_signed; +use sp_runtime::traits::{AtLeast32BitUnsigned, Bounded}; use sp_std::prelude::*; #[cfg(any(feature = "runtime-benchmarks", test))] @@ -92,38 +95,38 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(crate) trait Store)] - pub struct Pallet(_); + pub struct Pallet(_); #[pallet::config] - pub trait Config: frame_system::Config { + pub trait Config: frame_system::Config { /// The overarching event type. - type Event: From> + IsType<::Event>; + type Event: From> + IsType<::Event>; /// Weight information for extrinsics in this pallet. type WeightInfo: weights::WeightInfo; - /// Something that provides the weights of ids. - type VoteWeightProvider: VoteWeightProvider; + /// Something that provides the scores of ids. + type ScoreProvider: ScoreProvider; /// The list of thresholds separating the various bags. /// - /// Ids are separated into unsorted bags according to their vote weight. This specifies the - /// thresholds separating the bags. An id's bag is the largest bag for which the id's weight + /// Ids are separated into unsorted bags according to their score. This specifies the + /// thresholds separating the bags. An id's bag is the largest bag for which the id's score /// is less than or equal to its upper threshold. /// /// When ids are iterated, higher bags are iterated completely before lower bags. This means - /// that iteration is _semi-sorted_: ids of higher weight tend to come before ids of lower - /// weight, but peer ids within a particular bag are sorted in insertion order. + /// that iteration is _semi-sorted_: ids of higher score tend to come before ids of lower + /// score, but peer ids within a particular bag are sorted in insertion order. /// /// # Expressing the constant /// /// This constant must be sorted in strictly increasing order. Duplicate items are not /// permitted. /// - /// There is an implied upper limit of `VoteWeight::MAX`; that value does not need to be + /// There is an implied upper limit of `Score::MAX`; that value does not need to be /// specified within the bag. For any two threshold lists, if one ends with - /// `VoteWeight::MAX`, the other one does not, and they are otherwise equal, the two lists - /// will behave identically. + /// `Score::MAX`, the other one does not, and they are otherwise equal, the two + /// lists will behave identically. /// /// # Calculation /// @@ -141,52 +144,68 @@ pub mod pallet { /// the procedure given above, then the constant ratio is equal to 2. /// - If `BagThresholds::get().len() == 200`, and the thresholds are determined according to /// the procedure given above, then the constant ratio is approximately equal to 1.248. - /// - If the threshold list begins `[1, 2, 3, ...]`, then an id with weight 0 or 1 will fall - /// into bag 0, an id with weight 2 will fall into bag 1, etc. + /// - If the threshold list begins `[1, 2, 3, ...]`, then an id with score 0 or 1 will fall + /// into bag 0, an id with score 2 will fall into bag 1, etc. /// /// # Migration /// /// In the event that this list ever changes, a copy of the old bags list must be retained. /// With that `List::migrate` can be called, which will perform the appropriate migration. #[pallet::constant] - type BagThresholds: Get<&'static [VoteWeight]>; + type BagThresholds: Get<&'static [Self::Score]>; + + /// The type used to dictate a node position relative to other nodes. + type Score: Clone + + Default + + PartialEq + + Eq + + Ord + + PartialOrd + + sp_std::fmt::Debug + + Copy + + AtLeast32BitUnsigned + + Bounded + + TypeInfo + + FullCodec + + MaxEncodedLen; } /// A single node, within some bag. /// /// Nodes store links forward and back within their respective bags. #[pallet::storage] - pub(crate) type ListNodes = - CountedStorageMap<_, Twox64Concat, T::AccountId, list::Node>; + pub(crate) type ListNodes, I: 'static = ()> = + CountedStorageMap<_, Twox64Concat, T::AccountId, list::Node>; /// A bag stored in storage. /// /// Stores a `Bag` struct, which stores head and tail pointers to itself. #[pallet::storage] - pub(crate) type ListBags = StorageMap<_, Twox64Concat, VoteWeight, list::Bag>; + pub(crate) type ListBags, I: 'static = ()> = + StorageMap<_, Twox64Concat, T::Score, list::Bag>; #[pallet::event] #[pallet::generate_deposit(pub(crate) fn deposit_event)] - pub enum Event { + pub enum Event, I: 'static = ()> { /// Moved an account from one bag to another. - Rebagged { who: T::AccountId, from: VoteWeight, to: VoteWeight }, + Rebagged { who: T::AccountId, from: T::Score, to: T::Score }, } #[pallet::error] #[cfg_attr(test, derive(PartialEq))] - pub enum Error { + pub enum Error { /// Attempted to place node in front of a node in another bag. NotInSameBag, /// Id not found in list. IdNotFound, - /// An Id does not have a greater vote weight than another Id. + /// An Id does not have a greater score than another Id. NotHeavier, } #[pallet::call] - impl Pallet { + impl, I: 'static> Pallet { /// Declare that some `dislocated` account has, through rewards or penalties, sufficiently - /// changed its weight that it should properly fall into a different bag than its current + /// changed its score that it should properly fall into a different bag than its current /// one. /// /// Anyone can call this function about any potentially dislocated account. @@ -196,8 +215,8 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::rebag_non_terminal().max(T::WeightInfo::rebag_terminal()))] pub fn rebag(origin: OriginFor, dislocated: T::AccountId) -> DispatchResult { ensure_signed(origin)?; - let current_weight = T::VoteWeightProvider::vote_weight(&dislocated); - let _ = Pallet::::do_rebag(&dislocated, current_weight); + let current_score = T::ScoreProvider::score(&dislocated); + let _ = Pallet::::do_rebag(&dislocated, current_score); Ok(()) } @@ -208,16 +227,16 @@ pub mod pallet { /// /// Only works if /// - both nodes are within the same bag, - /// - and `origin` has a greater `VoteWeight` than `lighter`. + /// - and `origin` has a greater `Score` than `lighter`. #[pallet::weight(T::WeightInfo::put_in_front_of())] pub fn put_in_front_of(origin: OriginFor, lighter: T::AccountId) -> DispatchResult { let heavier = ensure_signed(origin)?; - List::::put_in_front_of(&lighter, &heavier).map_err(Into::into) + List::::put_in_front_of(&lighter, &heavier).map_err(Into::into) } } #[pallet::hooks] - impl Hooks> for Pallet { + impl, I: 'static> Hooks> for Pallet { fn integrity_test() { // ensure they are strictly increasing, this also implies that duplicates are detected. assert!( @@ -228,71 +247,70 @@ pub mod pallet { } } -impl Pallet { +impl, I: 'static> Pallet { /// Move an account from one bag to another, depositing an event on success. /// /// If the account changed bags, returns `Some((from, to))`. - pub fn do_rebag( - account: &T::AccountId, - new_weight: VoteWeight, - ) -> Option<(VoteWeight, VoteWeight)> { + pub fn do_rebag(account: &T::AccountId, new_weight: T::Score) -> Option<(T::Score, T::Score)> { // if no voter at that node, don't do anything. // the caller just wasted the fee to call this. - let maybe_movement = list::Node::::get(&account) + let maybe_movement = list::Node::::get(&account) .and_then(|node| List::update_position_for(node, new_weight)); if let Some((from, to)) = maybe_movement { - Self::deposit_event(Event::::Rebagged { who: account.clone(), from, to }); + Self::deposit_event(Event::::Rebagged { who: account.clone(), from, to }); }; maybe_movement } /// Equivalent to `ListBags::get`, but public. Useful for tests in outside of this crate. #[cfg(feature = "std")] - pub fn list_bags_get(weight: VoteWeight) -> Option> { - ListBags::get(weight) + pub fn list_bags_get(score: T::Score) -> Option> { + ListBags::get(score) } } -impl SortedListProvider for Pallet { +impl, I: 'static> SortedListProvider for Pallet { type Error = Error; + type Score = T::Score; + fn iter() -> Box> { - Box::new(List::::iter().map(|n| n.id().clone())) + Box::new(List::::iter().map(|n| n.id().clone())) } fn count() -> u32 { - ListNodes::::count() + ListNodes::::count() } fn contains(id: &T::AccountId) -> bool { - List::::contains(id) + List::::contains(id) } - fn on_insert(id: T::AccountId, weight: VoteWeight) -> Result<(), Error> { - List::::insert(id, weight) + fn on_insert(id: T::AccountId, score: T::Score) -> Result<(), Error> { + List::::insert(id, score) } - fn on_update(id: &T::AccountId, new_weight: VoteWeight) { - Pallet::::do_rebag(id, new_weight); + fn on_update(id: &T::AccountId, new_score: T::Score) { + Pallet::::do_rebag(id, new_score); } fn on_remove(id: &T::AccountId) { - List::::remove(id) + List::::remove(id) } fn unsafe_regenerate( all: impl IntoIterator, - weight_of: Box VoteWeight>, + score_of: Box T::Score>, ) -> u32 { // NOTE: This call is unsafe for the same reason as SortedListProvider::unsafe_regenerate. // I.e. because it can lead to many storage accesses. // So it is ok to call it as caller must ensure the conditions. - List::::unsafe_regenerate(all, weight_of) + List::::unsafe_regenerate(all, score_of) } #[cfg(feature = "std")] fn sanity_check() -> Result<(), &'static str> { - List::::sanity_check() + List::::sanity_check() } #[cfg(not(feature = "std"))] @@ -304,17 +322,17 @@ impl SortedListProvider for Pallet { // NOTE: This call is unsafe for the same reason as SortedListProvider::unsafe_clear. // I.e. because it can lead to many storage accesses. // So it is ok to call it as caller must ensure the conditions. - List::::unsafe_clear() + List::::unsafe_clear() } #[cfg(feature = "runtime-benchmarks")] - fn weight_update_worst_case(who: &T::AccountId, is_increase: bool) -> VoteWeight { + fn score_update_worst_case(who: &T::AccountId, is_increase: bool) -> Self::Score { use frame_support::traits::Get as _; let thresholds = T::BagThresholds::get(); - let node = list::Node::::get(who).unwrap(); + let node = list::Node::::get(who).unwrap(); let current_bag_idx = thresholds .iter() - .chain(sp_std::iter::once(&VoteWeight::MAX)) + .chain(sp_std::iter::once(&T::Score::max_value())) .position(|w| w == &node.bag_upper()) .unwrap(); diff --git a/frame/bags-list/src/list/mod.rs b/frame/bags-list/src/list/mod.rs index 8cd89b8fff1c..4921817c7e14 100644 --- a/frame/bags-list/src/list/mod.rs +++ b/frame/bags-list/src/list/mod.rs @@ -26,9 +26,10 @@ use crate::Config; use codec::{Decode, Encode, MaxEncodedLen}; -use frame_election_provider_support::{VoteWeight, VoteWeightProvider}; +use frame_election_provider_support::ScoreProvider; use frame_support::{traits::Get, DefaultNoBound}; use scale_info::TypeInfo; +use sp_runtime::traits::{Bounded, Zero}; use sp_std::{ boxed::Box, collections::{btree_map::BTreeMap, btree_set::BTreeSet}, @@ -46,36 +47,36 @@ pub enum Error { #[cfg(test)] mod tests; -/// Given a certain vote weight, to which bag does it belong to? +/// Given a certain score, to which bag does it belong to? /// /// Bags are identified by their upper threshold; the value returned by this function is guaranteed /// to be a member of `T::BagThresholds`. /// -/// Note that even if the thresholds list does not have `VoteWeight::MAX` as its final member, this -/// function behaves as if it does. -pub fn notional_bag_for(weight: VoteWeight) -> VoteWeight { +/// Note that even if the thresholds list does not have `T::Score::max_value()` as its final member, +/// this function behaves as if it does. +pub fn notional_bag_for, I: 'static>(score: T::Score) -> T::Score { let thresholds = T::BagThresholds::get(); - let idx = thresholds.partition_point(|&threshold| weight > threshold); - thresholds.get(idx).copied().unwrap_or(VoteWeight::MAX) + let idx = thresholds.partition_point(|&threshold| score > threshold); + thresholds.get(idx).copied().unwrap_or(T::Score::max_value()) } /// The **ONLY** entry point of this module. All operations to the bags-list should happen through /// this interface. It is forbidden to access other module members directly. // -// Data structure providing efficient mostly-accurate selection of the top N id by `VoteWeight`. +// Data structure providing efficient mostly-accurate selection of the top N id by `Score`. // // It's implemented as a set of linked lists. Each linked list comprises a bag of ids of -// arbitrary and unbounded length, all having a vote weight within a particular constant range. +// arbitrary and unbounded length, all having a score within a particular constant range. // This structure means that ids can be added and removed in `O(1)` time. // // Iteration is accomplished by chaining the iteration of each bag, from greatest to least. While -// the users within any particular bag are sorted in an entirely arbitrary order, the overall vote -// weight decreases as successive bags are reached. This means that it is valid to truncate +// the users within any particular bag are sorted in an entirely arbitrary order, the overall score +// decreases as successive bags are reached. This means that it is valid to truncate // iteration at any desired point; only those ids in the lowest bag can be excluded. This // satisfies both the desire for fairness and the requirement for efficiency. -pub struct List(PhantomData); +pub struct List, I: 'static = ()>(PhantomData<(T, I)>); -impl List { +impl, I: 'static> List { /// Remove all data associated with the list from storage. /// /// ## WARNING @@ -83,8 +84,8 @@ impl List { /// this function should generally not be used in production as it could lead to a very large /// number of storage accesses. pub(crate) fn unsafe_clear() { - crate::ListBags::::remove_all(None); - crate::ListNodes::::remove_all(); + crate::ListBags::::remove_all(None); + crate::ListNodes::::remove_all(); } /// Regenerate all of the data from the given ids. @@ -98,13 +99,13 @@ impl List { /// Returns the number of ids migrated. pub fn unsafe_regenerate( all: impl IntoIterator, - weight_of: Box VoteWeight>, + score_of: Box T::Score>, ) -> u32 { // NOTE: This call is unsafe for the same reason as SortedListProvider::unsafe_regenerate. // I.e. because it can lead to many storage accesses. // So it is ok to call it as caller must ensure the conditions. Self::unsafe_clear(); - Self::insert_many(all, weight_of) + Self::insert_many(all, score_of) } /// Migrate the list from one set of thresholds to another. @@ -127,7 +128,7 @@ impl List { /// - ids whose bags change at all are implicitly rebagged into the appropriate bag in the new /// threshold set. #[allow(dead_code)] - pub fn migrate(old_thresholds: &[VoteWeight]) -> u32 { + pub fn migrate(old_thresholds: &[T::Score]) -> u32 { let new_thresholds = T::BagThresholds::get(); if new_thresholds == old_thresholds { return 0 @@ -135,11 +136,13 @@ impl List { // we can't check all preconditions, but we can check one debug_assert!( - crate::ListBags::::iter().all(|(threshold, _)| old_thresholds.contains(&threshold)), + crate::ListBags::::iter() + .all(|(threshold, _)| old_thresholds.contains(&threshold)), "not all `bag_upper` currently in storage are members of `old_thresholds`", ); debug_assert!( - crate::ListNodes::::iter().all(|(_, node)| old_thresholds.contains(&node.bag_upper)), + crate::ListNodes::::iter() + .all(|(_, node)| old_thresholds.contains(&node.bag_upper)), "not all `node.bag_upper` currently in storage are members of `old_thresholds`", ); @@ -158,7 +161,7 @@ impl List { let affected_bag = { // this recreates `notional_bag_for` logic, but with the old thresholds. let idx = old_thresholds.partition_point(|&threshold| inserted_bag > threshold); - old_thresholds.get(idx).copied().unwrap_or(VoteWeight::MAX) + old_thresholds.get(idx).copied().unwrap_or(T::Score::max_value()) }; if !affected_old_bags.insert(affected_bag) { // If the previous threshold list was [10, 20], and we insert [3, 5], then there's @@ -166,7 +169,7 @@ impl List { continue } - if let Some(bag) = Bag::::get(affected_bag) { + if let Some(bag) = Bag::::get(affected_bag) { affected_accounts.extend(bag.iter().map(|node| node.id)); } } @@ -178,17 +181,17 @@ impl List { continue } - if let Some(bag) = Bag::::get(removed_bag) { + if let Some(bag) = Bag::::get(removed_bag) { affected_accounts.extend(bag.iter().map(|node| node.id)); } } // migrate the voters whose bag has changed let num_affected = affected_accounts.len() as u32; - let weight_of = T::VoteWeightProvider::vote_weight; + let score_of = T::ScoreProvider::score; let _removed = Self::remove_many(&affected_accounts); debug_assert_eq!(_removed, num_affected); - let _inserted = Self::insert_many(affected_accounts.into_iter(), weight_of); + let _inserted = Self::insert_many(affected_accounts.into_iter(), score_of); debug_assert_eq!(_inserted, num_affected); // we couldn't previously remove the old bags because both insertion and removal assume that @@ -199,10 +202,10 @@ impl List { // lookups. for removed_bag in removed_bags { debug_assert!( - !crate::ListNodes::::iter().any(|(_, node)| node.bag_upper == removed_bag), + !crate::ListNodes::::iter().any(|(_, node)| node.bag_upper == removed_bag), "no id should be present in a removed bag", ); - crate::ListBags::::remove(removed_bag); + crate::ListBags::::remove(removed_bag); } debug_assert_eq!(Self::sanity_check(), Ok(())); @@ -212,14 +215,14 @@ impl List { /// Returns `true` if the list contains `id`, otherwise returns `false`. pub(crate) fn contains(id: &T::AccountId) -> bool { - crate::ListNodes::::contains_key(id) + crate::ListNodes::::contains_key(id) } /// Iterate over all nodes in all bags in the list. /// /// Full iteration can be expensive; it's recommended to limit the number of items with /// `.take(n)`. - pub(crate) fn iter() -> impl Iterator> { + pub(crate) fn iter() -> impl Iterator> { // We need a touch of special handling here: because we permit `T::BagThresholds` to // omit the final bound, we need to ensure that we explicitly include that threshold in the // list. @@ -228,12 +231,14 @@ impl List { // easier; they can just configure `type BagThresholds = ()`. let thresholds = T::BagThresholds::get(); let iter = thresholds.iter().copied(); - let iter: Box> = if thresholds.last() == Some(&VoteWeight::MAX) { + let iter: Box> = if thresholds.last() == + Some(&T::Score::max_value()) + { // in the event that they included it, we can just pass the iterator through unchanged. Box::new(iter.rev()) } else { // otherwise, insert it here. - Box::new(iter.chain(iter::once(VoteWeight::MAX)).rev()) + Box::new(iter.chain(iter::once(T::Score::max_value())).rev()) }; iter.filter_map(Bag::get).flat_map(|bag| bag.iter()) @@ -245,12 +250,12 @@ impl List { /// Returns the final count of number of ids inserted. fn insert_many( ids: impl IntoIterator, - weight_of: impl Fn(&T::AccountId) -> VoteWeight, + score_of: impl Fn(&T::AccountId) -> T::Score, ) -> u32 { let mut count = 0; ids.into_iter().for_each(|v| { - let weight = weight_of(&v); - if Self::insert(v, weight).is_ok() { + let score = score_of(&v); + if Self::insert(v, score).is_ok() { count += 1; } }); @@ -261,13 +266,13 @@ impl List { /// Insert a new id into the appropriate bag in the list. /// /// Returns an error if the list already contains `id`. - pub(crate) fn insert(id: T::AccountId, weight: VoteWeight) -> Result<(), Error> { + pub(crate) fn insert(id: T::AccountId, score: T::Score) -> Result<(), Error> { if Self::contains(&id) { return Err(Error::Duplicate) } - let bag_weight = notional_bag_for::(weight); - let mut bag = Bag::::get_or_make(bag_weight); + let bag_score = notional_bag_for::(score); + let mut bag = Bag::::get_or_make(bag_score); // unchecked insertion is okay; we just got the correct `notional_bag_for`. bag.insert_unchecked(id.clone()); @@ -276,11 +281,12 @@ impl List { crate::log!( debug, - "inserted {:?} with weight {} into bag {:?}, new count is {}", + "inserted {:?} with score {:? + } into bag {:?}, new count is {}", id, - weight, - bag_weight, - crate::ListNodes::::count(), + score, + bag_score, + crate::ListNodes::::count(), ); Ok(()) @@ -301,7 +307,7 @@ impl List { let mut count = 0; for id in ids.into_iter() { - let node = match Node::::get(id) { + let node = match Node::::get(id) { Some(node) => node, None => continue, }; @@ -314,7 +320,7 @@ impl List { // this node is a head or tail, so the bag needs to be updated let bag = bags .entry(node.bag_upper) - .or_insert_with(|| Bag::::get_or_make(node.bag_upper)); + .or_insert_with(|| Bag::::get_or_make(node.bag_upper)); // node.bag_upper must be correct, therefore this bag will contain this node. bag.remove_node_unchecked(&node); } @@ -341,17 +347,17 @@ impl List { /// [`self.insert`]. However, given large quantities of nodes to move, it may be more efficient /// to call [`self.remove_many`] followed by [`self.insert_many`]. pub(crate) fn update_position_for( - node: Node, - new_weight: VoteWeight, - ) -> Option<(VoteWeight, VoteWeight)> { - node.is_misplaced(new_weight).then(move || { + node: Node, + new_score: T::Score, + ) -> Option<(T::Score, T::Score)> { + node.is_misplaced(new_score).then(move || { let old_bag_upper = node.bag_upper; if !node.is_terminal() { // this node is not a head or a tail, so we can just cut it out of the list. update // and put the prev and next of this node, we do `node.put` inside `insert_note`. node.excise(); - } else if let Some(mut bag) = Bag::::get(node.bag_upper) { + } else if let Some(mut bag) = Bag::::get(node.bag_upper) { // this is a head or tail, so the bag must be updated. bag.remove_node_unchecked(&node); bag.put(); @@ -365,8 +371,8 @@ impl List { } // put the node into the appropriate new bag. - let new_bag_upper = notional_bag_for::(new_weight); - let mut bag = Bag::::get_or_make(new_bag_upper); + let new_bag_upper = notional_bag_for::(new_score); + let mut bag = Bag::::get_or_make(new_bag_upper); // prev, next, and bag_upper of the node are updated inside `insert_node`, also // `node.put` is in there. bag.insert_node_unchecked(node); @@ -377,23 +383,22 @@ impl List { } /// Put `heavier_id` to the position directly in front of `lighter_id`. Both ids must be in the - /// same bag and the `weight_of` `lighter_id` must be less than that of `heavier_id`. + /// same bag and the `score_of` `lighter_id` must be less than that of `heavier_id`. pub(crate) fn put_in_front_of( lighter_id: &T::AccountId, heavier_id: &T::AccountId, - ) -> Result<(), crate::pallet::Error> { + ) -> Result<(), crate::pallet::Error> { use crate::pallet; use frame_support::ensure; - let lighter_node = Node::::get(&lighter_id).ok_or(pallet::Error::IdNotFound)?; - let heavier_node = Node::::get(&heavier_id).ok_or(pallet::Error::IdNotFound)?; + let lighter_node = Node::::get(&lighter_id).ok_or(pallet::Error::IdNotFound)?; + let heavier_node = Node::::get(&heavier_id).ok_or(pallet::Error::IdNotFound)?; ensure!(lighter_node.bag_upper == heavier_node.bag_upper, pallet::Error::NotInSameBag); // this is the most expensive check, so we do it last. ensure!( - T::VoteWeightProvider::vote_weight(&heavier_id) > - T::VoteWeightProvider::vote_weight(&lighter_id), + T::ScoreProvider::score(&heavier_id) > T::ScoreProvider::score(&lighter_id), pallet::Error::NotHeavier ); @@ -403,7 +408,7 @@ impl List { // re-fetch `lighter_node` from storage since it may have been updated when `heavier_node` // was removed. - let lighter_node = Node::::get(&lighter_id).ok_or_else(|| { + let lighter_node = Node::::get(&lighter_id).ok_or_else(|| { debug_assert!(false, "id that should exist cannot be found"); crate::log!(warn, "id that should exist cannot be found"); pallet::Error::IdNotFound @@ -422,7 +427,7 @@ impl List { /// - this is a naive function in that it does not check if `node` belongs to the same bag as /// `at`. It is expected that the call site will check preconditions. /// - this will panic if `at.bag_upper` is not a bag that already exists in storage. - fn insert_at_unchecked(mut at: Node, mut node: Node) { + fn insert_at_unchecked(mut at: Node, mut node: Node) { // connect `node` to its new `prev`. node.prev = at.prev.clone(); if let Some(mut prev) = at.prev() { @@ -439,7 +444,7 @@ impl List { // since `node` is always in front of `at` we know that 1) there is always at least 2 // nodes in the bag, and 2) only `node` could be the head and only `at` could be the // tail. - let mut bag = Bag::::get(at.bag_upper) + let mut bag = Bag::::get(at.bag_upper) .expect("given nodes must always have a valid bag. qed."); if node.prev == None { @@ -473,8 +478,8 @@ impl List { ); let iter_count = Self::iter().count() as u32; - let stored_count = crate::ListNodes::::count(); - let nodes_count = crate::ListNodes::::iter().count() as u32; + let stored_count = crate::ListNodes::::count(); + let nodes_count = crate::ListNodes::::iter().count() as u32; ensure!(iter_count == stored_count, "iter_count != stored_count"); ensure!(stored_count == nodes_count, "stored_count != nodes_count"); @@ -482,14 +487,15 @@ impl List { let active_bags = { let thresholds = T::BagThresholds::get().iter().copied(); - let thresholds: Vec = if thresholds.clone().last() == Some(VoteWeight::MAX) { - // in the event that they included it, we don't need to make any changes - thresholds.collect() - } else { - // otherwise, insert it here. - thresholds.chain(iter::once(VoteWeight::MAX)).collect() - }; - thresholds.into_iter().filter_map(|t| Bag::::get(t)) + let thresholds: Vec = + if thresholds.clone().last() == Some(T::Score::max_value()) { + // in the event that they included it, we don't need to make any changes + thresholds.collect() + } else { + // otherwise, insert it here. + thresholds.chain(iter::once(T::Score::max_value())).collect() + }; + thresholds.into_iter().filter_map(|t| Bag::::get(t)) }; let _ = active_bags.clone().map(|b| b.sanity_check()).collect::>()?; @@ -502,7 +508,7 @@ impl List { // check that all nodes are sane. We check the `ListNodes` storage item directly in case we // have some "stale" nodes that are not in a bag. - for (_id, node) in crate::ListNodes::::iter() { + for (_id, node) in crate::ListNodes::::iter() { node.sanity_check()? } @@ -517,21 +523,24 @@ impl List { /// Returns the nodes of all non-empty bags. For testing and benchmarks. #[cfg(any(feature = "std", feature = "runtime-benchmarks"))] #[allow(dead_code)] - pub(crate) fn get_bags() -> Vec<(VoteWeight, Vec)> { + pub(crate) fn get_bags() -> Vec<(T::Score, Vec)> { use frame_support::traits::Get as _; let thresholds = T::BagThresholds::get(); let iter = thresholds.iter().copied(); - let iter: Box> = if thresholds.last() == Some(&VoteWeight::MAX) { + let iter: Box> = if thresholds.last() == + Some(&T::Score::max_value()) + { // in the event that they included it, we can just pass the iterator through unchanged. Box::new(iter) } else { // otherwise, insert it here. - Box::new(iter.chain(sp_std::iter::once(VoteWeight::MAX))) + Box::new(iter.chain(sp_std::iter::once(T::Score::max_value()))) }; iter.filter_map(|t| { - Bag::::get(t).map(|bag| (t, bag.iter().map(|n| n.id().clone()).collect::>())) + Bag::::get(t) + .map(|bag| (t, bag.iter().map(|n| n.id().clone()).collect::>())) }) .collect::>() } @@ -546,37 +555,39 @@ impl List { /// appearing within the ids set. #[derive(DefaultNoBound, Encode, Decode, MaxEncodedLen, TypeInfo)] #[codec(mel_bound())] -#[scale_info(skip_type_params(T))] +#[scale_info(skip_type_params(T, I))] #[cfg_attr(feature = "std", derive(frame_support::DebugNoBound, Clone, PartialEq))] -pub struct Bag { +pub struct Bag, I: 'static = ()> { head: Option, tail: Option, #[codec(skip)] - bag_upper: VoteWeight, + bag_upper: T::Score, + #[codec(skip)] + _phantom: PhantomData, } -impl Bag { +impl, I: 'static> Bag { #[cfg(test)] pub(crate) fn new( head: Option, tail: Option, - bag_upper: VoteWeight, + bag_upper: T::Score, ) -> Self { - Self { head, tail, bag_upper } + Self { head, tail, bag_upper, _phantom: PhantomData } } - /// Get a bag by its upper vote weight. - pub(crate) fn get(bag_upper: VoteWeight) -> Option> { - crate::ListBags::::try_get(bag_upper).ok().map(|mut bag| { + /// Get a bag by its upper score. + pub(crate) fn get(bag_upper: T::Score) -> Option> { + crate::ListBags::::try_get(bag_upper).ok().map(|mut bag| { bag.bag_upper = bag_upper; bag }) } - /// Get a bag by its upper vote weight or make it, appropriately initialized. Does not check if + /// Get a bag by its upper score or make it, appropriately initialized. Does not check if /// if `bag_upper` is a valid threshold. - fn get_or_make(bag_upper: VoteWeight) -> Bag { + fn get_or_make(bag_upper: T::Score) -> Bag { Self::get(bag_upper).unwrap_or(Bag { bag_upper, ..Default::default() }) } @@ -588,24 +599,24 @@ impl Bag { /// Put the bag back into storage. fn put(self) { if self.is_empty() { - crate::ListBags::::remove(self.bag_upper); + crate::ListBags::::remove(self.bag_upper); } else { - crate::ListBags::::insert(self.bag_upper, self); + crate::ListBags::::insert(self.bag_upper, self); } } /// Get the head node in this bag. - fn head(&self) -> Option> { + fn head(&self) -> Option> { self.head.as_ref().and_then(|id| Node::get(id)) } /// Get the tail node in this bag. - fn tail(&self) -> Option> { + fn tail(&self) -> Option> { self.tail.as_ref().and_then(|id| Node::get(id)) } /// Iterate over the nodes in this bag. - pub(crate) fn iter(&self) -> impl Iterator> { + pub(crate) fn iter(&self) -> impl Iterator> { sp_std::iter::successors(self.head(), |prev| prev.next()) } @@ -620,7 +631,13 @@ impl Bag { // insert_node will overwrite `prev`, `next` and `bag_upper` to the proper values. As long // as this bag is the correct one, we're good. All calls to this must come after getting the // correct [`notional_bag_for`]. - self.insert_node_unchecked(Node:: { id, prev: None, next: None, bag_upper: 0 }); + self.insert_node_unchecked(Node:: { + id, + prev: None, + next: None, + bag_upper: Zero::zero(), + _phantom: PhantomData, + }); } /// Insert a node into this bag. @@ -630,7 +647,7 @@ impl Bag { /// /// Storage note: this modifies storage, but only for the node. You still need to call /// `self.put()` after use. - fn insert_node_unchecked(&mut self, mut node: Node) { + fn insert_node_unchecked(&mut self, mut node: Node) { if let Some(tail) = &self.tail { if *tail == node.id { // this should never happen, but this check prevents one path to a worst case @@ -674,7 +691,7 @@ impl Bag { /// /// Storage note: this modifies storage, but only for adjacent nodes. You still need to call /// `self.put()` and `ListNodes::remove(id)` to update storage for the bag and `node`. - fn remove_node_unchecked(&mut self, node: &Node) { + fn remove_node_unchecked(&mut self, node: &Node) { // reassign neighboring nodes. node.excise(); @@ -735,7 +752,7 @@ impl Bag { /// Iterate over the nodes in this bag (public for tests). #[cfg(feature = "std")] #[allow(dead_code)] - pub fn std_iter(&self) -> impl Iterator> { + pub fn std_iter(&self) -> impl Iterator> { sp_std::iter::successors(self.head(), |prev| prev.next()) } @@ -749,24 +766,26 @@ impl Bag { /// A Node is the fundamental element comprising the doubly-linked list described by `Bag`. #[derive(Encode, Decode, MaxEncodedLen, TypeInfo)] #[codec(mel_bound())] -#[scale_info(skip_type_params(T))] +#[scale_info(skip_type_params(T, I))] #[cfg_attr(feature = "std", derive(frame_support::DebugNoBound, Clone, PartialEq))] -pub struct Node { +pub struct Node, I: 'static = ()> { id: T::AccountId, prev: Option, next: Option, - bag_upper: VoteWeight, + bag_upper: T::Score, + #[codec(skip)] + _phantom: PhantomData, } -impl Node { +impl, I: 'static> Node { /// Get a node by id. - pub fn get(id: &T::AccountId) -> Option> { - crate::ListNodes::::try_get(id).ok() + pub fn get(id: &T::AccountId) -> Option> { + crate::ListNodes::::try_get(id).ok() } /// Put the node back into storage. fn put(self) { - crate::ListNodes::::insert(self.id.clone(), self); + crate::ListNodes::::insert(self.id.clone(), self); } /// Update neighboring nodes to point to reach other. @@ -790,22 +809,22 @@ impl Node { /// /// It is naive because it does not check if the node has first been removed from its bag. fn remove_from_storage_unchecked(&self) { - crate::ListNodes::::remove(&self.id) + crate::ListNodes::::remove(&self.id) } /// Get the previous node in the bag. - fn prev(&self) -> Option> { + fn prev(&self) -> Option> { self.prev.as_ref().and_then(|id| Node::get(id)) } /// Get the next node in the bag. - fn next(&self) -> Option> { + fn next(&self) -> Option> { self.next.as_ref().and_then(|id| Node::get(id)) } /// `true` when this voter is in the wrong bag. - pub fn is_misplaced(&self, current_weight: VoteWeight) -> bool { - notional_bag_for::(current_weight) != self.bag_upper + pub fn is_misplaced(&self, current_score: T::Score) -> bool { + notional_bag_for::(current_score) != self.bag_upper } /// `true` when this voter is a bag head or tail. @@ -828,13 +847,13 @@ impl Node { /// The bag this nodes belongs to (public for benchmarks). #[cfg(feature = "runtime-benchmarks")] #[allow(dead_code)] - pub fn bag_upper(&self) -> VoteWeight { + pub fn bag_upper(&self) -> T::Score { self.bag_upper } #[cfg(feature = "std")] fn sanity_check(&self) -> Result<(), &'static str> { - let expected_bag = Bag::::get(self.bag_upper).ok_or("bag not found for node")?; + let expected_bag = Bag::::get(self.bag_upper).ok_or("bag not found for node")?; let id = self.id(); diff --git a/frame/bags-list/src/list/tests.rs b/frame/bags-list/src/list/tests.rs index aaa215b0af1c..9b7a078b4428 100644 --- a/frame/bags-list/src/list/tests.rs +++ b/frame/bags-list/src/list/tests.rs @@ -20,14 +20,20 @@ use crate::{ mock::{test_utils::*, *}, ListBags, ListNodes, }; -use frame_election_provider_support::SortedListProvider; +use frame_election_provider_support::{SortedListProvider, VoteWeight}; use frame_support::{assert_ok, assert_storage_noop}; #[test] fn basic_setup_works() { ExtBuilder::default().build_and_execute(|| { // syntactic sugar to create a raw node - let node = |id, prev, next, bag_upper| Node:: { id, prev, next, bag_upper }; + let node = |id, prev, next, bag_upper| Node:: { + id, + prev, + next, + bag_upper, + _phantom: PhantomData, + }; assert_eq!(ListNodes::::count(), 4); assert_eq!(ListNodes::::iter().count(), 4); @@ -38,11 +44,11 @@ fn basic_setup_works() { // the state of the bags is as expected assert_eq!( ListBags::::get(10).unwrap(), - Bag:: { head: Some(1), tail: Some(1), bag_upper: 0 } + Bag:: { head: Some(1), tail: Some(1), bag_upper: 0, _phantom: PhantomData } ); assert_eq!( ListBags::::get(1_000).unwrap(), - Bag:: { head: Some(2), tail: Some(4), bag_upper: 0 } + Bag:: { head: Some(2), tail: Some(4), bag_upper: 0, _phantom: PhantomData } ); assert_eq!(ListNodes::::get(2).unwrap(), node(2, None, Some(3), 1_000)); @@ -65,24 +71,24 @@ fn basic_setup_works() { #[test] fn notional_bag_for_works() { // under a threshold gives the next threshold. - assert_eq!(notional_bag_for::(0), 10); - assert_eq!(notional_bag_for::(9), 10); + assert_eq!(notional_bag_for::(0), 10); + assert_eq!(notional_bag_for::(9), 10); // at a threshold gives that threshold. - assert_eq!(notional_bag_for::(10), 10); + assert_eq!(notional_bag_for::(10), 10); // above the threshold, gives the next threshold. - assert_eq!(notional_bag_for::(11), 20); + assert_eq!(notional_bag_for::(11), 20); let max_explicit_threshold = *::BagThresholds::get().last().unwrap(); assert_eq!(max_explicit_threshold, 10_000); - // if the max explicit threshold is less than VoteWeight::MAX, + // if the max explicit threshold is less than T::Value::max_value(), assert!(VoteWeight::MAX > max_explicit_threshold); - // then anything above it will belong to the VoteWeight::MAX bag. - assert_eq!(notional_bag_for::(max_explicit_threshold), max_explicit_threshold); - assert_eq!(notional_bag_for::(max_explicit_threshold + 1), VoteWeight::MAX); + // then anything above it will belong to the T::Value::max_value() bag. + assert_eq!(notional_bag_for::(max_explicit_threshold), max_explicit_threshold); + assert_eq!(notional_bag_for::(max_explicit_threshold + 1), VoteWeight::MAX); } #[test] @@ -388,14 +394,26 @@ mod list { #[should_panic = "given nodes must always have a valid bag. qed."] fn put_in_front_of_panics_if_bag_not_found() { ExtBuilder::default().skip_genesis_ids().build_and_execute_no_post_check(|| { - let node_10_no_bag = Node:: { id: 10, prev: None, next: None, bag_upper: 15 }; - let node_11_no_bag = Node:: { id: 11, prev: None, next: None, bag_upper: 15 }; + let node_10_no_bag = Node:: { + id: 10, + prev: None, + next: None, + bag_upper: 15, + _phantom: PhantomData, + }; + let node_11_no_bag = Node:: { + id: 11, + prev: None, + next: None, + bag_upper: 15, + _phantom: PhantomData, + }; // given ListNodes::::insert(10, node_10_no_bag); ListNodes::::insert(11, node_11_no_bag); - StakingMock::set_vote_weight_of(&10, 14); - StakingMock::set_vote_weight_of(&11, 15); + StakingMock::set_score_of(&10, 14); + StakingMock::set_score_of(&11, 15); assert!(!ListBags::::contains_key(15)); assert_eq!(List::::get_bags(), vec![]); @@ -414,8 +432,13 @@ mod list { assert_eq!(List::::get_bags(), vec![(10, vec![1]), (1_000, vec![2, 3, 4])]); // implicitly also test that `node`'s `prev`/`next` are correctly re-assigned. - let node_42 = - Node:: { id: 42, prev: Some(1), next: Some(2), bag_upper: 1_000 }; + let node_42 = Node:: { + id: 42, + prev: Some(1), + next: Some(2), + bag_upper: 1_000, + _phantom: PhantomData, + }; assert!(!crate::ListNodes::::contains_key(42)); let node_1 = crate::ListNodes::::get(&1).unwrap(); @@ -438,7 +461,13 @@ mod list { assert_eq!(List::::get_bags(), vec![(10, vec![1]), (1_000, vec![2, 3, 4])]); // implicitly also test that `node`'s `prev`/`next` are correctly re-assigned. - let node_42 = Node:: { id: 42, prev: Some(4), next: None, bag_upper: 1_000 }; + let node_42 = Node:: { + id: 42, + prev: Some(4), + next: None, + bag_upper: 1_000, + _phantom: PhantomData, + }; assert!(!crate::ListNodes::::contains_key(42)); let node_2 = crate::ListNodes::::get(&2).unwrap(); @@ -461,7 +490,13 @@ mod list { assert_eq!(List::::get_bags(), vec![(10, vec![1]), (1_000, vec![2, 3, 4])]); // implicitly also test that `node`'s `prev`/`next` are correctly re-assigned. - let node_42 = Node:: { id: 42, prev: None, next: Some(2), bag_upper: 1_000 }; + let node_42 = Node:: { + id: 42, + prev: None, + next: Some(2), + bag_upper: 1_000, + _phantom: PhantomData, + }; assert!(!crate::ListNodes::::contains_key(42)); let node_3 = crate::ListNodes::::get(&3).unwrap(); @@ -484,8 +519,13 @@ mod list { assert_eq!(List::::get_bags(), vec![(10, vec![1]), (1_000, vec![2, 3, 4])]); // implicitly also test that `node`'s `prev`/`next` are correctly re-assigned. - let node_42 = - Node:: { id: 42, prev: Some(42), next: Some(42), bag_upper: 1_000 }; + let node_42 = Node:: { + id: 42, + prev: Some(42), + next: Some(42), + bag_upper: 1_000, + _phantom: PhantomData, + }; assert!(!crate::ListNodes::::contains_key(42)); let node_4 = crate::ListNodes::::get(&4).unwrap(); @@ -512,7 +552,7 @@ mod bags { let bag = Bag::::get(bag_upper).unwrap(); let bag_ids = bag.iter().map(|n| *n.id()).collect::>(); - assert_eq!(bag, Bag:: { head, tail, bag_upper }); + assert_eq!(bag, Bag:: { head, tail, bag_upper, _phantom: PhantomData }); assert_eq!(bag_ids, ids); }; @@ -543,7 +583,13 @@ mod bags { #[test] fn insert_node_sets_proper_bag() { ExtBuilder::default().build_and_execute_no_post_check(|| { - let node = |id, bag_upper| Node:: { id, prev: None, next: None, bag_upper }; + let node = |id, bag_upper| Node:: { + id, + prev: None, + next: None, + bag_upper, + _phantom: PhantomData, + }; assert_eq!(List::::get_bags(), vec![(10, vec![1]), (1_000, vec![2, 3, 4])]); @@ -552,7 +598,7 @@ mod bags { assert_eq!( ListNodes::::get(&42).unwrap(), - Node { bag_upper: 10, prev: Some(1), next: None, id: 42 } + Node { bag_upper: 10, prev: Some(1), next: None, id: 42, _phantom: PhantomData } ); }); } @@ -560,7 +606,13 @@ mod bags { #[test] fn insert_node_happy_paths_works() { ExtBuilder::default().build_and_execute_no_post_check(|| { - let node = |id, bag_upper| Node:: { id, prev: None, next: None, bag_upper }; + let node = |id, bag_upper| Node:: { + id, + prev: None, + next: None, + bag_upper, + _phantom: PhantomData, + }; // when inserting into a bag with 1 node let mut bag_10 = Bag::::get(10).unwrap(); @@ -581,15 +633,26 @@ mod bags { assert_eq!(bag_as_ids(&bag_20), vec![62]); // when inserting a node pointing to the accounts not in the bag - let node_61 = - Node:: { id: 61, prev: Some(21), next: Some(101), bag_upper: 20 }; + let node_61 = Node:: { + id: 61, + prev: Some(21), + next: Some(101), + bag_upper: 20, + _phantom: PhantomData, + }; bag_20.insert_node_unchecked(node_61); // then ids are in order assert_eq!(bag_as_ids(&bag_20), vec![62, 61]); // and when the node is re-fetched all the info is correct assert_eq!( Node::::get(&61).unwrap(), - Node:: { id: 61, prev: Some(62), next: None, bag_upper: 20 } + Node:: { + id: 61, + prev: Some(62), + next: None, + bag_upper: 20, + _phantom: PhantomData, + } ); // state of all bags is as expected @@ -604,7 +667,13 @@ mod bags { // Document improper ways `insert_node` may be getting used. #[test] fn insert_node_bad_paths_documented() { - let node = |id, prev, next, bag_upper| Node:: { id, prev, next, bag_upper }; + let node = |id, prev, next, bag_upper| Node:: { + id, + prev, + next, + bag_upper, + _phantom: PhantomData, + }; ExtBuilder::default().build_and_execute_no_post_check(|| { // when inserting a node with both prev & next pointing at an account in an incorrect // bag. @@ -657,7 +726,10 @@ mod bags { ); // ^^^ despite being the bags head, it has a prev - assert_eq!(bag_1000, Bag { head: Some(2), tail: Some(2), bag_upper: 1_000 }) + assert_eq!( + bag_1000, + Bag { head: Some(2), tail: Some(2), bag_upper: 1_000, _phantom: PhantomData } + ) }); } @@ -669,7 +741,13 @@ mod bags { )] fn insert_node_duplicate_tail_panics_with_debug_assert() { ExtBuilder::default().build_and_execute(|| { - let node = |id, prev, next, bag_upper| Node:: { id, prev, next, bag_upper }; + let node = |id, prev, next, bag_upper| Node:: { + id, + prev, + next, + bag_upper, + _phantom: PhantomData, + }; // given assert_eq!(List::::get_bags(), vec![(10, vec![1]), (1_000, vec![2, 3, 4])],); @@ -801,6 +879,7 @@ mod bags { prev: None, next: Some(3), bag_upper: 10, // should be 1_000 + _phantom: PhantomData, }; let mut bag_1000 = Bag::::get(1_000).unwrap(); diff --git a/frame/bags-list/src/mock.rs b/frame/bags-list/src/mock.rs index aa3f549e12de..fce143105417 100644 --- a/frame/bags-list/src/mock.rs +++ b/frame/bags-list/src/mock.rs @@ -27,19 +27,21 @@ pub type AccountId = u32; pub type Balance = u32; parameter_types! { - // Set the vote weight for any id who's weight has _not_ been set with `set_vote_weight_of`. + // Set the vote weight for any id who's weight has _not_ been set with `set_score_of`. pub static NextVoteWeight: VoteWeight = 0; pub static NextVoteWeightMap: HashMap = Default::default(); } pub struct StakingMock; -impl frame_election_provider_support::VoteWeightProvider for StakingMock { - fn vote_weight(id: &AccountId) -> VoteWeight { +impl frame_election_provider_support::ScoreProvider for StakingMock { + type Score = VoteWeight; + + fn score(id: &AccountId) -> Self::Score { *NextVoteWeightMap::get().get(id).unwrap_or(&NextVoteWeight::get()) } #[cfg(any(feature = "runtime-benchmarks", test))] - fn set_vote_weight_of(id: &AccountId, weight: VoteWeight) { + fn set_score_of(id: &AccountId, weight: Self::Score) { NEXT_VOTE_WEIGHT_MAP.with(|m| m.borrow_mut().insert(id.clone(), weight)); } } @@ -79,7 +81,8 @@ impl bags_list::Config for Runtime { type Event = Event; type WeightInfo = (); type BagThresholds = BagThresholds; - type VoteWeightProvider = StakingMock; + type ScoreProvider = StakingMock; + type Score = VoteWeight; } type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; @@ -134,7 +137,7 @@ impl ExtBuilder { ext.execute_with(|| { for (id, weight) in ids_with_weight { frame_support::assert_ok!(List::::insert(*id, *weight)); - StakingMock::set_vote_weight_of(id, *weight); + StakingMock::set_score_of(id, *weight); } }); diff --git a/frame/bags-list/src/tests.rs b/frame/bags-list/src/tests.rs index 43397b3c120f..99396c9cbb3e 100644 --- a/frame/bags-list/src/tests.rs +++ b/frame/bags-list/src/tests.rs @@ -18,7 +18,7 @@ use frame_support::{assert_noop, assert_ok, assert_storage_noop, traits::IntegrityTest}; use super::*; -use frame_election_provider_support::SortedListProvider; +use frame_election_provider_support::{SortedListProvider, VoteWeight}; use list::Bag; use mock::{test_utils::*, *}; @@ -35,7 +35,7 @@ mod pallet { ); // when increasing vote weight to the level of non-existent bag - StakingMock::set_vote_weight_of(&42, 2_000); + StakingMock::set_score_of(&42, 2_000); assert_ok!(BagsList::rebag(Origin::signed(0), 42)); // then a new bag is created and the id moves into it @@ -45,7 +45,7 @@ mod pallet { ); // when decreasing weight within the range of the current bag - StakingMock::set_vote_weight_of(&42, 1_001); + StakingMock::set_score_of(&42, 1_001); assert_ok!(BagsList::rebag(Origin::signed(0), 42)); // then the id does not move @@ -55,7 +55,7 @@ mod pallet { ); // when reducing weight to the level of a non-existent bag - StakingMock::set_vote_weight_of(&42, 30); + StakingMock::set_score_of(&42, 30); assert_ok!(BagsList::rebag(Origin::signed(0), 42)); // then a new bag is created and the id moves into it @@ -65,7 +65,7 @@ mod pallet { ); // when increasing weight to the level of a pre-existing bag - StakingMock::set_vote_weight_of(&42, 500); + StakingMock::set_score_of(&42, 500); assert_ok!(BagsList::rebag(Origin::signed(0), 42)); // then the id moves into that bag @@ -85,7 +85,7 @@ mod pallet { assert_eq!(List::::get_bags(), vec![(10, vec![1]), (1_000, vec![2, 3, 4])]); // when - StakingMock::set_vote_weight_of(&4, 10); + StakingMock::set_score_of(&4, 10); assert_ok!(BagsList::rebag(Origin::signed(0), 4)); // then @@ -93,7 +93,7 @@ mod pallet { assert_eq!(Bag::::get(1_000).unwrap(), Bag::new(Some(2), Some(3), 1_000)); // when - StakingMock::set_vote_weight_of(&3, 10); + StakingMock::set_score_of(&3, 10); assert_ok!(BagsList::rebag(Origin::signed(0), 3)); // then @@ -104,7 +104,7 @@ mod pallet { assert_eq!(get_list_as_ids(), vec![2u32, 1, 4, 3]); // when - StakingMock::set_vote_weight_of(&2, 10); + StakingMock::set_score_of(&2, 10); assert_ok!(BagsList::rebag(Origin::signed(0), 2)); // then @@ -119,7 +119,7 @@ mod pallet { fn rebag_head_works() { ExtBuilder::default().build_and_execute(|| { // when - StakingMock::set_vote_weight_of(&2, 10); + StakingMock::set_score_of(&2, 10); assert_ok!(BagsList::rebag(Origin::signed(0), 2)); // then @@ -127,7 +127,7 @@ mod pallet { assert_eq!(Bag::::get(1_000).unwrap(), Bag::new(Some(3), Some(4), 1_000)); // when - StakingMock::set_vote_weight_of(&3, 10); + StakingMock::set_score_of(&3, 10); assert_ok!(BagsList::rebag(Origin::signed(0), 3)); // then @@ -135,7 +135,7 @@ mod pallet { assert_eq!(Bag::::get(1_000).unwrap(), Bag::new(Some(4), Some(4), 1_000)); // when - StakingMock::set_vote_weight_of(&4, 10); + StakingMock::set_score_of(&4, 10); assert_ok!(BagsList::rebag(Origin::signed(0), 4)); // then @@ -241,7 +241,7 @@ mod pallet { // given assert_eq!(List::::get_bags(), vec![(10, vec![1]), (1_000, vec![2, 3, 4, 5])]); - StakingMock::set_vote_weight_of(&3, 999); + StakingMock::set_score_of(&3, 999); // when assert_ok!(BagsList::put_in_front_of(Origin::signed(4), 3)); @@ -262,7 +262,7 @@ mod pallet { vec![(10, vec![1]), (1_000, vec![2, 3, 4, 5, 6])] ); - StakingMock::set_vote_weight_of(&5, 999); + StakingMock::set_score_of(&5, 999); // when assert_ok!(BagsList::put_in_front_of(Origin::signed(3), 5)); @@ -281,7 +281,7 @@ mod pallet { // given assert_eq!(List::::get_bags(), vec![(10, vec![1]), (1_000, vec![2, 3, 4])]); - StakingMock::set_vote_weight_of(&2, 999); + StakingMock::set_score_of(&2, 999); // when assert_ok!(BagsList::put_in_front_of(Origin::signed(3), 2)); @@ -297,7 +297,7 @@ mod pallet { // given assert_eq!(List::::get_bags(), vec![(10, vec![1]), (1_000, vec![2, 3, 4])]); - StakingMock::set_vote_weight_of(&3, 999); + StakingMock::set_score_of(&3, 999); // when assert_ok!(BagsList::put_in_front_of(Origin::signed(4), 3)); @@ -313,7 +313,7 @@ mod pallet { // given assert_eq!(List::::get_bags(), vec![(10, vec![1]), (1_000, vec![2, 3, 4, 5])]); - StakingMock::set_vote_weight_of(&2, 999); + StakingMock::set_score_of(&2, 999); // when assert_ok!(BagsList::put_in_front_of(Origin::signed(5), 2)); @@ -329,7 +329,7 @@ mod pallet { // given assert_eq!(List::::get_bags(), vec![(10, vec![1]), (1_000, vec![2, 3, 4, 5])]); - StakingMock::set_vote_weight_of(&4, 999); + StakingMock::set_score_of(&4, 999); // when BagsList::put_in_front_of(Origin::signed(2), 4).unwrap(); @@ -359,7 +359,7 @@ mod pallet { // given assert_eq!(List::::get_bags(), vec![(10, vec![1]), (1_000, vec![2, 3, 4])]); - StakingMock::set_vote_weight_of(&4, 999); + StakingMock::set_score_of(&4, 999); // when BagsList::put_in_front_of(Origin::signed(2), 4).unwrap(); @@ -375,7 +375,7 @@ mod pallet { // given assert_eq!(List::::get_bags(), vec![(10, vec![1]), (1_000, vec![2, 3, 4])]); - StakingMock::set_vote_weight_of(&3, 999); + StakingMock::set_score_of(&3, 999); // then assert_noop!( diff --git a/frame/election-provider-support/Cargo.toml b/frame/election-provider-support/Cargo.toml index e66774c6b5e7..b95bd994fa70 100644 --- a/frame/election-provider-support/Cargo.toml +++ b/frame/election-provider-support/Cargo.toml @@ -18,12 +18,12 @@ scale-info = { version = "2.0.1", default-features = false, features = ["derive" sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-arithmetic = { version = "5.0.0", default-features = false, path = "../../primitives/arithmetic" } sp-npos-elections = { version = "4.0.0-dev", default-features = false, path = "../../primitives/npos-elections" } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } [dev-dependencies] sp-npos-elections = { version = "4.0.0-dev", path = "../../primitives/npos-elections" } -sp-runtime = { version = "6.0.0", path = "../../primitives/runtime" } sp-core = { version = "6.0.0", path = "../../primitives/core" } sp-io = { version = "6.0.0", path = "../../primitives/io" } diff --git a/frame/election-provider-support/src/lib.rs b/frame/election-provider-support/src/lib.rs index ca22e3093855..ff57eacf68fa 100644 --- a/frame/election-provider-support/src/lib.rs +++ b/frame/election-provider-support/src/lib.rs @@ -168,6 +168,7 @@ pub mod onchain; use frame_support::{traits::Get, BoundedVec}; +use sp_runtime::traits::Bounded; use sp_std::{fmt::Debug, prelude::*}; /// Re-export some type as they are used in the interface. @@ -333,9 +334,7 @@ where /// This is generic over `AccountId` and it can represent a validator, a nominator, or any other /// entity. /// -/// To simplify the trait, the `VoteWeight` is hardcoded as the weight of each entity. The weights -/// are ascending, the higher, the better. In the long term, if this trait ends up having use cases -/// outside of the election context, it is easy enough to make it generic over the `VoteWeight`. +/// The scores (see [`Self::Score`]) are ascending, the higher, the better. /// /// Something that implements this trait will do a best-effort sort over ids, and thus can be /// used on the implementing side of [`ElectionDataProvider`]. @@ -343,6 +342,9 @@ pub trait SortedListProvider { /// The list's error type. type Error: sp_std::fmt::Debug; + /// The type used by the list to compare nodes for ordering. + type Score: Bounded; + /// An iterator over the list, which can have `take` called on it. fn iter() -> Box>; @@ -353,10 +355,10 @@ pub trait SortedListProvider { fn contains(id: &AccountId) -> bool; /// Hook for inserting a new id. - fn on_insert(id: AccountId, weight: VoteWeight) -> Result<(), Self::Error>; + fn on_insert(id: AccountId, score: Self::Score) -> Result<(), Self::Error>; /// Hook for updating a single id. - fn on_update(id: &AccountId, weight: VoteWeight); + fn on_update(id: &AccountId, score: Self::Score); /// Hook for removing am id from the list. fn on_remove(id: &AccountId); @@ -371,7 +373,7 @@ pub trait SortedListProvider { /// new list, which can lead to too many storage accesses, exhausting the block weight. fn unsafe_regenerate( all: impl IntoIterator, - weight_of: Box VoteWeight>, + score_of: Box Self::Score>, ) -> u32; /// Remove all items from the list. @@ -388,21 +390,23 @@ pub trait SortedListProvider { /// If `who` changes by the returned amount they are guaranteed to have a worst case change /// in their list position. #[cfg(feature = "runtime-benchmarks")] - fn weight_update_worst_case(_who: &AccountId, _is_increase: bool) -> VoteWeight { - VoteWeight::MAX + fn score_update_worst_case(_who: &AccountId, _is_increase: bool) -> Self::Score { + Self::Score::max_value() } } /// Something that can provide the `VoteWeight` of an account. Similar to [`ElectionProvider`] and /// [`ElectionDataProvider`], this should typically be implementing by whoever is supposed to *use* /// `SortedListProvider`. -pub trait VoteWeightProvider { - /// Get the current `VoteWeight` of `who`. - fn vote_weight(who: &AccountId) -> VoteWeight; +pub trait ScoreProvider { + type Score; + + /// Get the current `Score` of `who`. + fn score(who: &AccountId) -> Self::Score; /// For tests and benchmarks, set the `VoteWeight`. #[cfg(any(feature = "runtime-benchmarks", test))] - fn set_vote_weight_of(_: &AccountId, _: VoteWeight) {} + fn set_score_of(_: &AccountId, _: Self::Score) {} } /// Something that can compute the result to an NPoS solution. diff --git a/frame/staking/src/benchmarking.rs b/frame/staking/src/benchmarking.rs index ec7d36c820f3..3e57b647ac80 100644 --- a/frame/staking/src/benchmarking.rs +++ b/frame/staking/src/benchmarking.rs @@ -189,7 +189,7 @@ impl ListScenario { // find a destination weight that will trigger the worst case scenario let dest_weight_as_vote = - T::SortedListProvider::weight_update_worst_case(&origin_stash1, is_increase); + T::SortedListProvider::score_update_worst_case(&origin_stash1, is_increase); let total_issuance = T::Currency::total_issuance(); diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index 12d3804b4e30..843791a46ade 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -18,7 +18,7 @@ //! Test utilities use crate::{self as pallet_staking, *}; -use frame_election_provider_support::{onchain, SortedListProvider}; +use frame_election_provider_support::{onchain, SortedListProvider, VoteWeight}; use frame_support::{ assert_ok, parameter_types, traits::{ @@ -240,8 +240,9 @@ parameter_types! { impl pallet_bags_list::Config for Test { type Event = Event; type WeightInfo = (); - type VoteWeightProvider = Staking; + type ScoreProvider = Staking; type BagThresholds = BagThresholds; + type Score = VoteWeight; } impl onchain::Config for Test { diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 5cd0d0107f01..a4aadb16ab1b 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -18,8 +18,8 @@ //! Implementations for the Staking FRAME Pallet. use frame_election_provider_support::{ - data_provider, ElectionDataProvider, ElectionProvider, SortedListProvider, Supports, - VoteWeight, VoteWeightProvider, VoterOf, + data_provider, ElectionDataProvider, ElectionProvider, ScoreProvider, SortedListProvider, + Supports, VoteWeight, VoterOf, }; use frame_support::{ pallet_prelude::*, @@ -1244,13 +1244,15 @@ where } } -impl VoteWeightProvider for Pallet { - fn vote_weight(who: &T::AccountId) -> VoteWeight { +impl ScoreProvider for Pallet { + type Score = VoteWeight; + + fn score(who: &T::AccountId) -> Self::Score { Self::weight_of(who) } #[cfg(feature = "runtime-benchmarks")] - fn set_vote_weight_of(who: &T::AccountId, weight: VoteWeight) { + fn set_score_of(who: &T::AccountId, weight: Self::Score) { // this will clearly results in an inconsistent state, but it should not matter for a // benchmark. let active: BalanceOf = weight.try_into().map_err(|_| ()).unwrap(); @@ -1279,6 +1281,7 @@ impl VoteWeightProvider for Pallet { pub struct UseNominatorsMap(sp_std::marker::PhantomData); impl SortedListProvider for UseNominatorsMap { type Error = (); + type Score = VoteWeight; /// Returns iterator over voter list, which can have `take` called on it. fn iter() -> Box> { @@ -1290,11 +1293,11 @@ impl SortedListProvider for UseNominatorsMap { fn contains(id: &T::AccountId) -> bool { Nominators::::contains_key(id) } - fn on_insert(_: T::AccountId, _weight: VoteWeight) -> Result<(), Self::Error> { + fn on_insert(_: T::AccountId, _weight: Self::Score) -> Result<(), Self::Error> { // nothing to do on insert. Ok(()) } - fn on_update(_: &T::AccountId, _weight: VoteWeight) { + fn on_update(_: &T::AccountId, _weight: Self::Score) { // nothing to do on update. } fn on_remove(_: &T::AccountId) { @@ -1302,7 +1305,7 @@ impl SortedListProvider for UseNominatorsMap { } fn unsafe_regenerate( _: impl IntoIterator, - _: Box VoteWeight>, + _: Box Self::Score>, ) -> u32 { // nothing to do upon regenerate. 0 diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 58f9fd237263..b50ce5ed4502 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -166,7 +166,10 @@ pub mod pallet { /// Something that can provide a sorted list of voters in a somewhat sorted way. The /// original use case for this was designed with `pallet_bags_list::Pallet` in mind. If /// the bags-list is not desired, [`impls::UseNominatorsMap`] is likely the desired option. - type SortedListProvider: SortedListProvider; + type SortedListProvider: SortedListProvider< + Self::AccountId, + Score = frame_election_provider_support::VoteWeight, + >; /// The maximum number of `unlocking` chunks a [`StakingLedger`] can have. Effectively /// determines how many unique eras a staker may be unbonding in. From 1321c6f0806def1e1ceee9e99a937d540eb25f21 Mon Sep 17 00:00:00 2001 From: Qinxuan Chen Date: Thu, 10 Mar 2022 17:02:58 +0800 Subject: [PATCH 576/695] sc-finality-grandpa: use the #[from] attriute to remove boilerplate code (#11003) Signed-off-by: koushiro --- client/finality-grandpa/src/lib.rs | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/client/finality-grandpa/src/lib.rs b/client/finality-grandpa/src/lib.rs index 8316e56b5b5e..fef16286381e 100644 --- a/client/finality-grandpa/src/lib.rs +++ b/client/finality-grandpa/src/lib.rs @@ -279,7 +279,7 @@ impl Config { pub enum Error { /// An error within grandpa. #[error("grandpa error: {0}")] - Grandpa(GrandpaError), + Grandpa(#[from] GrandpaError), /// A network error. #[error("network error: {0}")] @@ -291,7 +291,7 @@ pub enum Error { /// Could not complete a round on disk. #[error("could not complete a round on disk: {0}")] - Client(ClientError), + Client(#[from] ClientError), /// Could not sign outgoing message #[error("could not sign outgoing message: {0}")] @@ -310,18 +310,6 @@ pub enum Error { RuntimeApi(sp_api::ApiError), } -impl From for Error { - fn from(e: GrandpaError) -> Self { - Error::Grandpa(e) - } -} - -impl From for Error { - fn from(e: ClientError) -> Self { - Error::Client(e) - } -} - /// Something which can determine if a block is known. pub(crate) trait BlockStatus { /// Return `Ok(Some(number))` or `Ok(None)` depending on whether the block From 5afd5b8a4ee7bfb7d60d114b0968910f12748160 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Thu, 10 Mar 2022 12:28:00 +0100 Subject: [PATCH 577/695] contracts: Add test to verify unique trie ids (#10914) * Add test to verify unique trie ids * Rename trie_seed to nonce * Rename AccountCounter -> Nonce * fmt --- frame/contracts/src/exec.rs | 67 +++++++++++++-------------- frame/contracts/src/lib.rs | 27 +++++++++-- frame/contracts/src/migration.rs | 24 ++++++++++ frame/contracts/src/storage.rs | 7 ++- frame/contracts/src/tests.rs | 77 ++++++++++++++++++++++++++++---- frame/contracts/src/weights.rs | 16 +++---- 6 files changed, 162 insertions(+), 56 deletions(-) diff --git a/frame/contracts/src/exec.rs b/frame/contracts/src/exec.rs index eb7a68d81ad5..455665687d97 100644 --- a/frame/contracts/src/exec.rs +++ b/frame/contracts/src/exec.rs @@ -18,7 +18,7 @@ use crate::{ gas::GasMeter, storage::{self, Storage, WriteOutcome}, - AccountCounter, BalanceOf, CodeHash, Config, ContractInfo, ContractInfoOf, Error, Event, + BalanceOf, CodeHash, Config, ContractInfo, ContractInfoOf, Error, Event, Nonce, Pallet as Contracts, Schedule, }; use frame_support::{ @@ -315,9 +315,10 @@ pub struct Stack<'a, T: Config, E> { timestamp: MomentOf, /// The block number at the time of call stack instantiation. block_number: T::BlockNumber, - /// The account counter is cached here when accessed. It is written back when the call stack - /// finishes executing. - account_counter: Option, + /// The nonce is cached here when accessed. It is written back when the call stack + /// finishes executing. Please refer to [`Nonce`] to a description of + /// the nonce itself. + nonce: Option, /// The actual call stack. One entry per nested contract called/instantiated. /// This does **not** include the [`Self::first_frame`]. frames: SmallVec, @@ -385,8 +386,8 @@ enum FrameArgs<'a, T: Config, E> { Instantiate { /// The contract or signed origin which instantiates the new contract. sender: T::AccountId, - /// The seed that should be used to derive a new trie id for the contract. - trie_seed: u64, + /// The nonce that should be used to derive a new trie id for the contract. + nonce: u64, /// The executable whose `deploy` function is run. executable: E, /// A salt used in the contract address deriviation of the new contract. @@ -571,7 +572,7 @@ where let (mut stack, executable) = Self::new( FrameArgs::Instantiate { sender: origin.clone(), - trie_seed: Self::initial_trie_seed(), + nonce: Self::initial_nonce(), executable, salt, }, @@ -596,7 +597,7 @@ where value: BalanceOf, debug_message: Option<&'a mut Vec>, ) -> Result<(Self, E), ExecError> { - let (first_frame, executable, account_counter) = + let (first_frame, executable, nonce) = Self::new_frame(args, value, gas_meter, storage_meter, 0, &schedule)?; let stack = Self { origin, @@ -605,7 +606,7 @@ where storage_meter, timestamp: T::Time::now(), block_number: >::block_number(), - account_counter, + nonce, first_frame, frames: Default::default(), debug_message, @@ -627,7 +628,7 @@ where gas_limit: Weight, schedule: &Schedule, ) -> Result<(Frame, E, Option), ExecError> { - let (account_id, contract_info, executable, delegate_caller, entry_point, account_counter) = + let (account_id, contract_info, executable, delegate_caller, entry_point, nonce) = match frame_args { FrameArgs::Call { dest, cached_info, delegated_call } => { let contract = if let Some(contract) = cached_info { @@ -645,10 +646,10 @@ where (dest, contract, executable, delegate_caller, ExportedFunction::Call, None) }, - FrameArgs::Instantiate { sender, trie_seed, executable, salt } => { + FrameArgs::Instantiate { sender, nonce, executable, salt } => { let account_id = >::contract_address(&sender, executable.code_hash(), &salt); - let trie_id = Storage::::generate_trie_id(&account_id, trie_seed); + let trie_id = Storage::::generate_trie_id(&account_id, nonce); let contract = Storage::::new_contract( &account_id, trie_id, @@ -660,7 +661,7 @@ where executable, None, ExportedFunction::Constructor, - Some(trie_seed), + Some(nonce), ) }, }; @@ -676,7 +677,7 @@ where allows_reentry: true, }; - Ok((frame, executable, account_counter)) + Ok((frame, executable, nonce)) } /// Create a subsequent nested frame. @@ -782,9 +783,9 @@ where /// This is called after running the current frame. It commits cached values to storage /// and invalidates all stale references to it that might exist further down the call stack. fn pop_frame(&mut self, persist: bool) { - // Revert the account counter in case of a failed instantiation. + // Revert changes to the nonce in case of a failed instantiation. if !persist && self.top_frame().entry_point == ExportedFunction::Constructor { - self.account_counter.as_mut().map(|c| *c = c.wrapping_sub(1)); + self.nonce.as_mut().map(|c| *c = c.wrapping_sub(1)); } // Pop the current frame from the stack and return it in case it needs to interact @@ -861,8 +862,8 @@ where if let Some(contract) = contract { >::insert(&self.first_frame.account_id, contract); } - if let Some(counter) = self.account_counter { - >::set(counter); + if let Some(nonce) = self.nonce { + >::set(nonce); } } } @@ -920,20 +921,20 @@ where !self.frames().any(|f| &f.account_id == id && !f.allows_reentry) } - /// Increments the cached account id and returns the value to be used for the trie_id. - fn next_trie_seed(&mut self) -> u64 { - let next = if let Some(current) = self.account_counter { + /// Increments and returns the next nonce. Pulls it from storage if it isn't in cache. + fn next_nonce(&mut self) -> u64 { + let next = if let Some(current) = self.nonce { current.wrapping_add(1) } else { - Self::initial_trie_seed() + Self::initial_nonce() }; - self.account_counter = Some(next); + self.nonce = Some(next); next } - /// The account seed to be used to instantiate the account counter cache. - fn initial_trie_seed() -> u64 { - >::get().wrapping_add(1) + /// Pull the current nonce from storage. + fn initial_nonce() -> u64 { + >::get().wrapping_add(1) } } @@ -1020,11 +1021,11 @@ where salt: &[u8], ) -> Result<(AccountIdOf, ExecReturnValue), ExecError> { let executable = E::from_storage(code_hash, &self.schedule, self.gas_meter())?; - let trie_seed = self.next_trie_seed(); + let nonce = self.next_nonce(); let executable = self.push_frame( FrameArgs::Instantiate { sender: self.top_frame().account_id.clone(), - trie_seed, + nonce, executable, salt, }, @@ -2445,7 +2446,7 @@ mod tests { } #[test] - fn account_counter() { + fn nonce() { let fail_code = MockLoader::insert(Constructor, |_, _| exec_trapped()); let success_code = MockLoader::insert(Constructor, |_, _| exec_success()); let succ_fail_code = MockLoader::insert(Constructor, move |ctx, _| { @@ -2495,7 +2496,7 @@ mod tests { None, ) .ok(); - assert_eq!(>::get(), 0); + assert_eq!(>::get(), 0); assert_ok!(MockStack::run_instantiate( ALICE, @@ -2508,7 +2509,7 @@ mod tests { &[], None, )); - assert_eq!(>::get(), 1); + assert_eq!(>::get(), 1); assert_ok!(MockStack::run_instantiate( ALICE, @@ -2521,7 +2522,7 @@ mod tests { &[], None, )); - assert_eq!(>::get(), 2); + assert_eq!(>::get(), 2); assert_ok!(MockStack::run_instantiate( ALICE, @@ -2534,7 +2535,7 @@ mod tests { &[], None, )); - assert_eq!(>::get(), 4); + assert_eq!(>::get(), 4); }); } diff --git a/frame/contracts/src/lib.rs b/frame/contracts/src/lib.rs index 037e3f1d33ae..4edf43a67215 100644 --- a/frame/contracts/src/lib.rs +++ b/frame/contracts/src/lib.rs @@ -134,7 +134,7 @@ type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; /// The current storage version. -const STORAGE_VERSION: StorageVersion = StorageVersion::new(6); +const STORAGE_VERSION: StorageVersion = StorageVersion::new(7); /// Used as a sentinel value when reading and writing contract memory. /// @@ -665,9 +665,30 @@ pub mod pallet { #[pallet::storage] pub(crate) type OwnerInfoOf = StorageMap<_, Identity, CodeHash, OwnerInfo>; - /// The subtrie counter. + /// This is a **monotonic** counter incremented on contract instantiation. + /// + /// This is used in order to generate unique trie ids for contracts. + /// The trie id of a new contract is calculated from hash(account_id, nonce). + /// The nonce is required because otherwise the following sequence would lead to + /// a possible collision of storage: + /// + /// 1. Create a new contract. + /// 2. Terminate the contract. + /// 3. Immediately recreate the contract with the same account_id. + /// + /// This is bad because the contents of a trie are deleted lazily and there might be + /// storage of the old instantiation still in it when the new contract is created. Please + /// note that we can't replace the counter by the block number because the sequence above + /// can happen in the same block. We also can't keep the account counter in memory only + /// because storage is the only way to communicate across different extrinsics in the + /// same block. + /// + /// # Note + /// + /// Do not use it to determine the number of contracts. It won't be decremented if + /// a contract is destroyed. #[pallet::storage] - pub(crate) type AccountCounter = StorageValue<_, u64, ValueQuery>; + pub(crate) type Nonce = StorageValue<_, u64, ValueQuery>; /// The code associated with a given account. /// diff --git a/frame/contracts/src/migration.rs b/frame/contracts/src/migration.rs index 59d3721ab13c..035e3b4409cf 100644 --- a/frame/contracts/src/migration.rs +++ b/frame/contracts/src/migration.rs @@ -19,6 +19,7 @@ use crate::{BalanceOf, CodeHash, Config, Pallet, TrieId, Weight}; use codec::{Decode, Encode}; use frame_support::{ codec, generate_storage_alias, + pallet_prelude::*, storage::migration, traits::{Get, PalletInfoAccess}, Identity, Twox64Concat, @@ -47,6 +48,11 @@ pub fn migrate() -> Weight { StorageVersion::new(6).put::>(); } + if version < 7 { + weight = weight.saturating_add(v7::migrate::()); + StorageVersion::new(7).put::>(); + } + weight } @@ -249,3 +255,21 @@ mod v6 { weight } } + +/// Rename `AccountCounter` to `Nonce`. +mod v7 { + use super::*; + + pub fn migrate() -> Weight { + generate_storage_alias!( + Contracts, + AccountCounter => Value + ); + generate_storage_alias!( + Contracts, + Nonce => Value + ); + Nonce::set(AccountCounter::take()); + T::DbWeight::get().reads_writes(1, 2) + } +} diff --git a/frame/contracts/src/storage.rs b/frame/contracts/src/storage.rs index 51a43a178242..17022e942766 100644 --- a/frame/contracts/src/storage.rs +++ b/frame/contracts/src/storage.rs @@ -290,10 +290,9 @@ where weight_limit.saturating_sub(weight_per_key.saturating_mul(remaining_key_budget as Weight)) } - /// This generator uses inner counter for account id and applies the hash over `AccountId + - /// accountid_counter`. - pub fn generate_trie_id(account_id: &AccountIdOf, seed: u64) -> TrieId { - let buf: Vec<_> = account_id.as_ref().iter().chain(&seed.to_le_bytes()).cloned().collect(); + /// Generates a unique trie id by returning `hash(account_id ++ nonce)`. + pub fn generate_trie_id(account_id: &AccountIdOf, nonce: u64) -> TrieId { + let buf: Vec<_> = account_id.as_ref().iter().chain(&nonce.to_le_bytes()).cloned().collect(); T::Hashing::hash(&buf).as_ref().into() } diff --git a/frame/contracts/src/tests.rs b/frame/contracts/src/tests.rs index 8add424db089..4c8c42c77da5 100644 --- a/frame/contracts/src/tests.rs +++ b/frame/contracts/src/tests.rs @@ -74,17 +74,15 @@ frame_support::construct_runtime!( #[macro_use] pub mod test_utils { use super::{Balances, Test}; - use crate::{ - exec::AccountIdOf, storage::Storage, AccountCounter, CodeHash, Config, ContractInfoOf, - }; + use crate::{exec::AccountIdOf, storage::Storage, CodeHash, Config, ContractInfoOf, Nonce}; use frame_support::traits::Currency; pub fn place_contract(address: &AccountIdOf, code_hash: CodeHash) { - let seed = >::mutate(|counter| { + let nonce = >::mutate(|counter| { *counter += 1; *counter }); - let trie_id = Storage::::generate_trie_id(address, seed); + let trie_id = Storage::::generate_trie_id(address, nonce); set_balance(address, ::Currency::minimum_balance() * 10); let contract = Storage::::new_contract(&address, trie_id, code_hash).unwrap(); >::insert(address, contract); @@ -349,6 +347,11 @@ where Ok((wasm_binary, code_hash)) } +fn initialize_block(number: u64) { + System::reset_events(); + System::initialize(&number, &[0u8; 32].into(), &Default::default()); +} + // Perform a call to a plain account. // The actual transfer fails because we can only call contracts. // Then we check that at least the base costs where charged (no runtime gas costs.) @@ -540,9 +543,67 @@ fn run_out_of_gas() { }); } -fn initialize_block(number: u64) { - System::reset_events(); - System::initialize(&number, &[0u8; 32].into(), &Default::default()); +/// Check that contracts with the same account id have different trie ids. +/// Check the `Nonce` storage item for more information. +#[test] +fn instantiate_unique_trie_id() { + let (wasm, code_hash) = compile_module::("self_destruct").unwrap(); + + ExtBuilder::default().existential_deposit(500).build().execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + Contracts::upload_code(Origin::signed(ALICE), wasm, None).unwrap(); + let addr = Contracts::contract_address(&ALICE, &code_hash, &[]); + + // Instantiate the contract and store its trie id for later comparison. + assert_ok!(Contracts::instantiate( + Origin::signed(ALICE), + 0, + GAS_LIMIT, + None, + code_hash, + vec![], + vec![], + )); + let trie_id = ContractInfoOf::::get(&addr).unwrap().trie_id; + + // Try to instantiate it again without termination should yield an error. + assert_err_ignore_postinfo!( + Contracts::instantiate( + Origin::signed(ALICE), + 0, + GAS_LIMIT, + None, + code_hash, + vec![], + vec![], + ), + >::DuplicateContract, + ); + + // Terminate the contract. + assert_ok!(Contracts::call( + Origin::signed(ALICE), + addr.clone(), + 0, + GAS_LIMIT, + None, + vec![] + )); + + // Re-Instantiate after termination. + assert_ok!(Contracts::instantiate( + Origin::signed(ALICE), + 0, + GAS_LIMIT, + None, + code_hash, + vec![], + vec![], + )); + + // Trie ids shouldn't match or we might have a collision + assert_ne!(trie_id, ContractInfoOf::::get(&addr).unwrap().trie_id); + }); } #[test] diff --git a/frame/contracts/src/weights.rs b/frame/contracts/src/weights.rs index 7d73a3a1cecc..b438ad51cbfc 100644 --- a/frame/contracts/src/weights.rs +++ b/frame/contracts/src/weights.rs @@ -201,7 +201,7 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Contracts CodeStorage (r:1 w:1) - // Storage: Contracts AccountCounter (r:1 w:1) + // Storage: Contracts Nonce (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) @@ -217,7 +217,7 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().writes(6 as Weight)) } // Storage: Contracts CodeStorage (r:1 w:1) - // Storage: Contracts AccountCounter (r:1 w:1) + // Storage: Contracts Nonce (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) @@ -651,7 +651,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) - // Storage: Contracts AccountCounter (r:1 w:1) + // Storage: Contracts Nonce (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:100 w:100) fn seal_instantiate(r: u32, ) -> Weight { (0 as Weight) @@ -666,7 +666,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts ContractInfoOf (r:101 w:101) // Storage: Contracts CodeStorage (r:2 w:1) // Storage: Timestamp Now (r:1 w:0) - // Storage: Contracts AccountCounter (r:1 w:1) + // Storage: Contracts Nonce (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_instantiate_per_transfer_salt_kb(t: u32, s: u32, ) -> Weight { (14_790_752_000 as Weight) @@ -1092,7 +1092,7 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Contracts CodeStorage (r:1 w:1) - // Storage: Contracts AccountCounter (r:1 w:1) + // Storage: Contracts Nonce (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) @@ -1108,7 +1108,7 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } // Storage: Contracts CodeStorage (r:1 w:1) - // Storage: Contracts AccountCounter (r:1 w:1) + // Storage: Contracts Nonce (r:1 w:1) // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) @@ -1542,7 +1542,7 @@ impl WeightInfo for () { // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) - // Storage: Contracts AccountCounter (r:1 w:1) + // Storage: Contracts Nonce (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:100 w:100) fn seal_instantiate(r: u32, ) -> Weight { (0 as Weight) @@ -1557,7 +1557,7 @@ impl WeightInfo for () { // Storage: Contracts ContractInfoOf (r:101 w:101) // Storage: Contracts CodeStorage (r:2 w:1) // Storage: Timestamp Now (r:1 w:0) - // Storage: Contracts AccountCounter (r:1 w:1) + // Storage: Contracts Nonce (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_instantiate_per_transfer_salt_kb(t: u32, s: u32, ) -> Weight { (14_790_752_000 as Weight) From 3d9361d080c48368c2c56b2928374428580efceb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Thu, 10 Mar 2022 19:26:42 +0100 Subject: [PATCH 578/695] sp-core: `full_crypto` doesn't imply `std` (#11006) * sp-core: `full_crypto` doesn't imply `std` This pr changes the feature set of `secp256k1` to not use `global-context` when only the `full_crypto` is enabled. It will be slower when the `std` feature is not enabled as the context always needs to be recreated, but that is fine. * Update client/cli/src/arg_enums.rs Co-authored-by: Davide Galassi Co-authored-by: Davide Galassi --- primitives/core/Cargo.toml | 3 ++- primitives/core/src/ecdsa.rs | 32 ++++++++++++++++++++++++++------ 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index 1effb8efbf5a..55d00362033d 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -56,7 +56,7 @@ schnorrkel = { version = "0.9.1", features = [ hex = { version = "0.4", default-features = false, optional = true } libsecp256k1 = { version = "0.7", default-features = false, features = ["static-context"], optional = true } merlin = { version = "2.0", default-features = false, optional = true } -secp256k1 = { version = "0.21.2", default-features = false, features = ["recovery", "global-context"], optional = true } +secp256k1 = { version = "0.21.2", default-features = false, features = ["recovery", "alloc"], optional = true } ss58-registry = { version = "1.11.0", default-features = false } sp-core-hashing = { version = "4.0.0", path = "./hashing", default-features = false, optional = true } sp-runtime-interface = { version = "6.0.0", default-features = false, path = "../runtime-interface" } @@ -108,6 +108,7 @@ std = [ "regex", "num-traits/std", "secp256k1/std", + "secp256k1/global-context", "sp-core-hashing/std", "sp-debug-derive/std", "sp-externalities", diff --git a/primitives/core/src/ecdsa.rs b/primitives/core/src/ecdsa.rs index 9389a277736d..7a4e4399913d 100644 --- a/primitives/core/src/ecdsa.rs +++ b/primitives/core/src/ecdsa.rs @@ -34,12 +34,14 @@ use crate::{ }; #[cfg(feature = "std")] use bip39::{Language, Mnemonic, MnemonicType}; -#[cfg(feature = "full_crypto")] -use core::convert::TryFrom; +#[cfg(all(feature = "full_crypto", not(feature = "std")))] +use secp256k1::Secp256k1; +#[cfg(feature = "std")] +use secp256k1::SECP256K1; #[cfg(feature = "full_crypto")] use secp256k1::{ ecdsa::{RecoverableSignature, RecoveryId}, - Message, PublicKey, SecretKey, SECP256K1, + Message, PublicKey, SecretKey, }; #[cfg(feature = "std")] use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; @@ -334,7 +336,13 @@ impl Signature { let rid = RecoveryId::from_i32(self.0[64] as i32).ok()?; let sig = RecoverableSignature::from_compact(&self.0[..64], rid).ok()?; let message = Message::from_slice(message).expect("Message is 32 bytes; qed"); - SECP256K1 + + #[cfg(feature = "std")] + let context = SECP256K1; + #[cfg(not(feature = "std"))] + let context = Secp256k1::verification_only(); + + context .recover_ecdsa(&message, &sig) .ok() .map(|pubkey| Public(pubkey.serialize())) @@ -425,7 +433,13 @@ impl TraitPair for Pair { fn from_seed_slice(seed_slice: &[u8]) -> Result { let secret = SecretKey::from_slice(seed_slice).map_err(|_| SecretStringError::InvalidSeedLength)?; - let public = PublicKey::from_secret_key(SECP256K1, &secret); + + #[cfg(feature = "std")] + let context = SECP256K1; + #[cfg(not(feature = "std"))] + let context = Secp256k1::signing_only(); + + let public = PublicKey::from_secret_key(&context, &secret); let public = Public(public.serialize()); Ok(Pair { public, secret }) } @@ -503,7 +517,13 @@ impl Pair { /// Sign a pre-hashed message pub fn sign_prehashed(&self, message: &[u8; 32]) -> Signature { let message = Message::from_slice(message).expect("Message is 32 bytes; qed"); - SECP256K1.sign_ecdsa_recoverable(&message, &self.secret).into() + + #[cfg(feature = "std")] + let context = SECP256K1; + #[cfg(not(feature = "std"))] + let context = Secp256k1::signing_only(); + + context.sign_ecdsa_recoverable(&message, &self.secret).into() } /// Verify a signature on a pre-hashed message. Return `true` if the signature is valid From f5f286db0da99761792b69bf4a997535dcc8f260 Mon Sep 17 00:00:00 2001 From: Liu-Cheng Xu Date: Fri, 11 Mar 2022 02:35:11 +0800 Subject: [PATCH 579/695] Remove unused `parent_hash` in `OverlayedChanges::into_storage_changes` (#11011) Ref https://github.com/paritytech/substrate/pull/10922#issuecomment-1064258443 CC @cheme --- primitives/api/proc-macro/src/impl_runtime_apis.rs | 1 - primitives/state-machine/src/ext.rs | 8 +------- primitives/state-machine/src/overlayed_changes/mod.rs | 4 +--- primitives/state-machine/src/testing.rs | 1 - utils/frame/try-runtime/cli/src/commands/follow_chain.rs | 1 - 5 files changed, 2 insertions(+), 13 deletions(-) diff --git a/primitives/api/proc-macro/src/impl_runtime_apis.rs b/primitives/api/proc-macro/src/impl_runtime_apis.rs index ae18849d83cc..dc89c9f592e5 100644 --- a/primitives/api/proc-macro/src/impl_runtime_apis.rs +++ b/primitives/api/proc-macro/src/impl_runtime_apis.rs @@ -301,7 +301,6 @@ fn generate_runtime_api_base_structures() -> Result { self.changes.replace(Default::default()).into_storage_changes( backend, - parent_hash, self.storage_transaction_cache.replace(Default::default()), state_version, ) diff --git a/primitives/state-machine/src/ext.rs b/primitives/state-machine/src/ext.rs index e87b22d4f9b7..7b7e4b47f19b 100644 --- a/primitives/state-machine/src/ext.rs +++ b/primitives/state-machine/src/ext.rs @@ -660,7 +660,6 @@ where self.overlay .drain_storage_changes( self.backend, - Default::default(), self.storage_transaction_cache, Default::default(), // using any state ) @@ -680,12 +679,7 @@ where } let changes = self .overlay - .drain_storage_changes( - self.backend, - Default::default(), - self.storage_transaction_cache, - state_version, - ) + .drain_storage_changes(self.backend, self.storage_transaction_cache, state_version) .expect(EXT_NOT_ALLOWED_TO_FAIL); self.backend .commit( diff --git a/primitives/state-machine/src/overlayed_changes/mod.rs b/primitives/state-machine/src/overlayed_changes/mod.rs index d75feec0ced9..59f3e1cffa5f 100644 --- a/primitives/state-machine/src/overlayed_changes/mod.rs +++ b/primitives/state-machine/src/overlayed_changes/mod.rs @@ -500,21 +500,19 @@ impl OverlayedChanges { pub fn into_storage_changes, H: Hasher>( mut self, backend: &B, - parent_hash: H::Out, mut cache: StorageTransactionCache, state_version: StateVersion, ) -> Result, DefaultError> where H::Out: Ord + Encode + 'static, { - self.drain_storage_changes(backend, parent_hash, &mut cache, state_version) + self.drain_storage_changes(backend, &mut cache, state_version) } /// Drain all changes into a [`StorageChanges`] instance. Leave empty overlay in place. pub fn drain_storage_changes, H: Hasher>( &mut self, backend: &B, - _parent_hash: H::Out, mut cache: &mut StorageTransactionCache, state_version: StateVersion, ) -> Result, DefaultError> diff --git a/primitives/state-machine/src/testing.rs b/primitives/state-machine/src/testing.rs index 7f71d24b761a..bc462ae01ab2 100644 --- a/primitives/state-machine/src/testing.rs +++ b/primitives/state-machine/src/testing.rs @@ -179,7 +179,6 @@ where pub fn commit_all(&mut self) -> Result<(), String> { let changes = self.overlay.drain_storage_changes::<_, _>( &self.backend, - Default::default(), &mut Default::default(), self.state_version, )?; diff --git a/utils/frame/try-runtime/cli/src/commands/follow_chain.rs b/utils/frame/try-runtime/cli/src/commands/follow_chain.rs index 82bc04880106..7400813b9175 100644 --- a/utils/frame/try-runtime/cli/src/commands/follow_chain.rs +++ b/utils/frame/try-runtime/cli/src/commands/follow_chain.rs @@ -150,7 +150,6 @@ where let storage_changes = changes .drain_storage_changes( &state_ext.backend, - Default::default(), &mut Default::default(), // Note that in case a block contains a runtime upgrade, // state version could potentially be incorrect here, From b7eb9a1108eb9f574e1a2b1bb2899d2c528cd685 Mon Sep 17 00:00:00 2001 From: driemworks Date: Thu, 10 Mar 2022 20:45:22 -0500 Subject: [PATCH 580/695] iris ledger pallet -> transfer not yet functioning --- Cargo.lock | 19 ++++++ .../pallets/iris-ledger/Cargo.toml | 4 +- .../pallets/iris-ledger/src/lib.rs | 68 +++++++++++-------- bin/node-template/runtime/Cargo.toml | 2 + bin/node-template/runtime/src/lib.rs | 9 +-- 5 files changed, 66 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 67fd26b49277..fd75e61b7135 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4979,6 +4979,7 @@ dependencies = [ "pallet-grandpa", "pallet-im-online", "pallet-iris-assets", + "pallet-iris-ledger", "pallet-iris-rpc-runtime-api", "pallet-iris-session", "pallet-randomness-collective-flip", @@ -5807,6 +5808,24 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-iris-ledger" +version = "1.0.0" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log 0.4.14", + "pallet-balances", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-keystore", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-iris-rpc" version = "4.0.0-dev" diff --git a/bin/node-template/pallets/iris-ledger/Cargo.toml b/bin/node-template/pallets/iris-ledger/Cargo.toml index ae017ba59de4..1eac5cb2b6e9 100644 --- a/bin/node-template/pallets/iris-ledger/Cargo.toml +++ b/bin/node-template/pallets/iris-ledger/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ['Substrate DevHub '] edition = '2018' -name = 'pallet-iris-assets' +name = 'pallet-iris-ledger' version = "1.0.0" license = "Unlicense" homepage = "https://substrate.dev" @@ -31,7 +31,6 @@ frame-benchmarking = { default-features = false, version = "4.0.0-dev", path = " log = { version = "0.4.14", default-features = false } pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../../../../frame/balances" } -pallet-assets = { version = "4.0.0-dev", default-features = false, path = "../../../../frame/assets" } [features] default = ['std'] @@ -46,7 +45,6 @@ std = [ 'sp-keystore/std', 'sp-runtime/std', 'log/std', - 'pallet-assets/std', 'pallet-balances/std', ] diff --git a/bin/node-template/pallets/iris-ledger/src/lib.rs b/bin/node-template/pallets/iris-ledger/src/lib.rs index 51bebfbb48ec..5901b9831dc3 100644 --- a/bin/node-template/pallets/iris-ledger/src/lib.rs +++ b/bin/node-template/pallets/iris-ledger/src/lib.rs @@ -1,26 +1,24 @@ #![cfg_attr(not(feature = "std"), no_std)] -//! # Iris Storage Pallet -//! +//! # Iris Ledger Pallet //! //! ## Overview -//! -//! ### Goals -//! The Iris module provides functionality for creation and management of storage assets and access management +//! This pallet provides functionality for nodes to lock funds, unlock funds, and transfer them to other nodes. +//! In essence, it enables nodes to promise funds to other nodes from within the context of a smart contract (via a chain extension) +//! or by calling the exgtrinsics directly. //! //! ### Dispatchable Functions +//! +//! * lock_currency +//! +//! * unlock_currency_and_transfer //! -//! #### Permissionless functions -//! * create_storage_asset -//! -//! #### Permissioned Functions -//! * mint_tickets //! use scale_info::TypeInfo; use codec::{Encode, Decode}; use frame_support::{ - ensure, + dispatch::DispatchResult, traits::{Currency, LockIdentifier, LockableCurrency, WithdrawReasons}, }; use frame_system::{ @@ -31,17 +29,14 @@ use sp_core::offchain::OpaqueMultiaddr; use sp_runtime::{ RuntimeDebug, - traits::StaticLookup, + traits::{ + AtLeast32BitUnsigned, Bounded, CheckedAdd, CheckedSub, Saturating, StaticLookup, Zero, + }, }; use sp_std::{ - vec::Vec, prelude::*, }; - -type IRIS_LOCK_ID: LockIdentifier: *b"irislock"; - -type BalanceOf = - <::IrisCurrency as Currency<::AccountId>>::Balance; +use codec::HasCompact; pub use pallet::*; @@ -68,11 +63,17 @@ pub mod pallet { use sp_core::offchain::OpaqueMultiaddr; use sp_std::{str, vec::Vec}; + const IRIS_LOCK_ID: LockIdentifier = *b"irislock"; + + type BalanceOf = + <::IrisCurrency as Currency<::AccountId>>::Balance; + + #[pallet::config] /// the module configuration trait pub trait Config: frame_system::Config { /// The overarching event type - type Event: From> + IsType<::Event>; + type Event: From> + IsType<::Event>; /// the overarching call type type Call: From>; /// the currency used @@ -92,7 +93,7 @@ pub mod pallet { T::AccountId, Blake2_128Concat, LockIdentifier, - T::Balance, + BalanceOf, ValueQuery, >; @@ -113,11 +114,14 @@ pub mod pallet { #[pallet::call] impl Pallet { + /// lock some amount of currency + /// + /// * amount: the amount of currency to lock + /// #[pallet::weight(100)] pub fn lock_currency( origin: OriginFor, - amount: T::IrisCurrency, - cid : Vec, + #[pallet::compact] amount: BalanceOf, ) -> DispatchResult { let who = ensure_signed(origin)?; // let lock_id: LockIdentifier = cid; @@ -132,6 +136,10 @@ pub mod pallet { Ok(()) } + /// Unlock currency and transfer it to a target node + /// + /// * target: the node to which currency will be transferred + /// #[pallet::weight(100)] pub fn unlock_currency_and_transfer( origin: OriginFor, @@ -142,13 +150,15 @@ pub mod pallet { let amount = >::get(who.clone(), IRIS_LOCK_ID); T::IrisCurrency::remove_lock(IRIS_LOCK_ID, &who); - let new_origin = system::RawOrigin::Signed(who).into(); - T::IrisCurrency::transfer( - new_origin, - target, - amount, - KeepAlive, - )?; + // let new_origin = system::RawOrigin::Signed(who.clone()).into(); + // T::IrisCurrency::transfer( + // new_origin, + // &target, + // amount, + // KeepAlive, + // )?; + + >::remove(who.clone(), IRIS_LOCK_ID); Self::deposit_event(Event::Unlocked(who)); Ok(()) } diff --git a/bin/node-template/runtime/Cargo.toml b/bin/node-template/runtime/Cargo.toml index 35247ef94a07..18b6678e1006 100644 --- a/bin/node-template/runtime/Cargo.toml +++ b/bin/node-template/runtime/Cargo.toml @@ -27,6 +27,7 @@ pallet-assets = { version = "4.0.0-dev", default-features = false, path = "../.. pallet-session = { version = "4.0.0-dev", default-features = false, features = ["historical"], path = "../../../frame/session" } pallet-iris-assets = { version = "1.0.0", default-features = false, path = "../pallets/iris-assets" } pallet-iris-session = { version = "1.0.0", default-features = false, path = "../pallets/iris-session" } +pallet-iris-ledger = { version = "1.0.0", default-features = false, path = "../pallets/iris-ledger" } pallet-timestamp = { version = "4.0.0-dev", default-features = false, path = "../../../frame/timestamp" } pallet-transaction-payment = { version = "4.0.0-dev", default-features = false, path = "../../../frame/transaction-payment" } pallet-contracts = { version = "4.0.0-dev", default-features = false, path = "../../../frame/contracts" } @@ -80,6 +81,7 @@ std = [ "pallet-sudo/std", "pallet-im-online/std", "pallet-iris-assets/std", + "pallet-iris-ledger/std", "pallet-timestamp/std", "pallet-transaction-payment-rpc-runtime-api/std", "pallet-iris-rpc-runtime-api/std", diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index 8e9db0fcec8d..a112a2c82256 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -455,12 +455,13 @@ pub type SignedPayload = generic::SignedPayload; impl pallet_iris_assets::Config for Runtime { type Event = Event; type Call = Call; - type IrisCurrency = Balances; + type Currency = Balances; } impl pallet_iris_ledger::Config for Runtime { type Event = Event; type Call = Call; + // type Balance = u64; type IrisCurrency = Balances; } @@ -876,7 +877,7 @@ impl ChainExtension for IrisExtension { let origin: Origin = system::RawOrigin::Signed(caller_account).into(); crate::IrisAssets::mint( - origin, sp_runtime::MultiAddress::Id(beneficiary), asset_id, amount, + origin, sp_runtime::MultiAddress::Id(target), asset_id, amount, )?; trace!( target: "runtime", @@ -887,11 +888,11 @@ impl ChainExtension for IrisExtension { // IrisLedger::lock_currrency 3 => { let mut env = env.buf_in_buf_out(); - let (caller_account, amount, cid): (AccountId, u64, Vec) = env.read_as()?; + let (caller_account, amount): (AccountId, u64) = env.read_as()?; let origin: Origin = system::RawOrigin::Signed(caller_account).into(); crate::IrisLedger::lock_currency( - origin, amount, cid, + origin, amount.into(), )?; trace!( target: "runtime", From 5cc2ef8e4c03b64691db367036fedd8f4d7f0326 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Fri, 11 Mar 2022 23:20:18 +0100 Subject: [PATCH 581/695] sp-api: Don't be dirty (#11015) Ensure that the sp api macros don't use functions without providing the full path to the function. This hygiene ensures that we don't actually try to call a method of an imported trait for example. --- .../api/proc-macro/src/decl_runtime_apis.rs | 26 +++--- .../api/proc-macro/src/impl_runtime_apis.rs | 88 ++++++++++--------- 2 files changed, 59 insertions(+), 55 deletions(-) diff --git a/primitives/api/proc-macro/src/decl_runtime_apis.rs b/primitives/api/proc-macro/src/decl_runtime_apis.rs index bc72aaa81681..2301f531590e 100644 --- a/primitives/api/proc-macro/src/decl_runtime_apis.rs +++ b/primitives/api/proc-macro/src/decl_runtime_apis.rs @@ -378,21 +378,21 @@ fn generate_call_api_at_calls(decl: &ItemTrait) -> Result { #[cfg(any(feature = "std", test))] #[allow(clippy::too_many_arguments)] pub fn #fn_name< - R: #crate_::Encode + #crate_::Decode + PartialEq, + R: #crate_::Encode + #crate_::Decode + std::cmp::PartialEq, NC: FnOnce() -> std::result::Result + std::panic::UnwindSafe, Block: #crate_::BlockT, T: #crate_::CallApiAt, >( call_runtime_at: &T, at: &#crate_::BlockId, - args: Vec, + args: std::vec::Vec, changes: &std::cell::RefCell<#crate_::OverlayedChanges>, storage_transaction_cache: &std::cell::RefCell< #crate_::StorageTransactionCache >, - native_call: Option, + native_call: std::option::Option, context: #crate_::ExecutionContext, - recorder: &Option<#crate_::ProofRecorder>, + recorder: &std::option::Option<#crate_::ProofRecorder>, ) -> std::result::Result<#crate_::NativeOrEncoded, #crate_::ApiError> { let version = call_runtime_at.runtime_version_at(at)?; @@ -412,7 +412,7 @@ fn generate_call_api_at_calls(decl: &ItemTrait) -> Result { recorder, }; - let ret = call_runtime_at.call_api_at(params)?; + let ret = #crate_::CallApiAt::::call_api_at(call_runtime_at, params)?; return Ok(ret) } @@ -429,7 +429,7 @@ fn generate_call_api_at_calls(decl: &ItemTrait) -> Result { recorder, }; - call_runtime_at.call_api_at(params) + #crate_::CallApiAt::::call_api_at(call_runtime_at, params) } )); } @@ -677,13 +677,13 @@ impl<'a> ToClientSideDecl<'a> { #native_handling }, #crate_::NativeOrEncoded::Encoded(r) => { - <#ret_type as #crate_::Decode>::decode(&mut &r[..]) - .map_err(|err| - #crate_::ApiError::FailedToDecodeReturnValue { - function: #function_name, - error: err, - } - ) + std::result::Result::map_err( + <#ret_type as #crate_::Decode>::decode(&mut &r[..]), + |err| #crate_::ApiError::FailedToDecodeReturnValue { + function: #function_name, + error: err, + } + ) } } ) diff --git a/primitives/api/proc-macro/src/impl_runtime_apis.rs b/primitives/api/proc-macro/src/impl_runtime_apis.rs index dc89c9f592e5..f594a743fcf9 100644 --- a/primitives/api/proc-macro/src/impl_runtime_apis.rs +++ b/primitives/api/proc-macro/src/impl_runtime_apis.rs @@ -207,7 +207,7 @@ fn generate_runtime_api_base_structures() -> Result { storage_transaction_cache: std::cell::RefCell< #crate_::StorageTransactionCache >, - recorder: Option<#crate_::ProofRecorder>, + recorder: std::option::Option<#crate_::ProofRecorder>, } // `RuntimeApi` itself is not threadsafe. However, an instance is only available in a @@ -233,12 +233,12 @@ fn generate_runtime_api_base_structures() -> Result { &self, call: F, ) -> R where Self: Sized { - self.changes.borrow_mut().start_transaction(); - *self.commit_on_success.borrow_mut() = false; + #crate_::OverlayedChanges::start_transaction(&mut std::cell::RefCell::borrow_mut(&self.changes)); + *std::cell::RefCell::borrow_mut(&self.commit_on_success) = false; let res = call(self); - *self.commit_on_success.borrow_mut() = true; + *std::cell::RefCell::borrow_mut(&self.commit_on_success) = true; - self.commit_or_rollback(matches!(res, #crate_::TransactionOutcome::Commit(_))); + self.commit_or_rollback(std::matches!(res, #crate_::TransactionOutcome::Commit(_))); res.into_inner() } @@ -247,9 +247,8 @@ fn generate_runtime_api_base_structures() -> Result { &self, at: &#crate_::BlockId, ) -> std::result::Result where Self: Sized { - self.call - .runtime_version_at(at) - .map(|v| v.has_api_with(&A::ID, |v| v == A::VERSION)) + #crate_::CallApiAt::::runtime_version_at(self.call, at) + .map(|v| #crate_::RuntimeVersion::has_api_with(&v, &A::ID, |v| v == A::VERSION)) } fn has_api_with bool>( @@ -257,51 +256,48 @@ fn generate_runtime_api_base_structures() -> Result { at: &#crate_::BlockId, pred: P, ) -> std::result::Result where Self: Sized { - self.call - .runtime_version_at(at) - .map(|v| v.has_api_with(&A::ID, pred)) + #crate_::CallApiAt::::runtime_version_at(self.call, at) + .map(|v| #crate_::RuntimeVersion::has_api_with(&v, &A::ID, pred)) } fn api_version( &self, at: &#crate_::BlockId, ) -> std::result::Result, #crate_::ApiError> where Self: Sized { - self.call - .runtime_version_at(at) - .map(|v| v.api_version(&A::ID)) + #crate_::CallApiAt::::runtime_version_at(self.call, at) + .map(|v| #crate_::RuntimeVersion::api_version(&v, &A::ID)) } fn record_proof(&mut self) { - self.recorder = Some(Default::default()); + self.recorder = std::option::Option::Some(std::default::Default::default()); } - fn proof_recorder(&self) -> Option<#crate_::ProofRecorder> { - self.recorder.clone() + fn proof_recorder(&self) -> std::option::Option<#crate_::ProofRecorder> { + std::clone::Clone::clone(&self.recorder) } - fn extract_proof(&mut self) -> Option<#crate_::StorageProof> { - self.recorder - .take() - .map(|recorder| recorder.to_storage_proof()) + fn extract_proof(&mut self) -> std::option::Option<#crate_::StorageProof> { + std::option::Option::take(&mut self.recorder) + .map(|recorder| #crate_::ProofRecorder::::to_storage_proof(&recorder)) } fn into_storage_changes( &self, backend: &Self::StateBackend, parent_hash: Block::Hash, - ) -> std::result::Result< + ) -> core::result::Result< #crate_::StorageChanges, String > where Self: Sized { - let at = #crate_::BlockId::Hash(parent_hash.clone()); - let state_version = self.call - .runtime_version_at(&at) - .map(|v| v.state_version()) + let at = #crate_::BlockId::Hash(std::clone::Clone::clone(&parent_hash)); + let state_version = #crate_::CallApiAt::::runtime_version_at(self.call, &at) + .map(|v| #crate_::RuntimeVersion::state_version(&v)) .map_err(|e| format!("Failed to get state version: {}", e))?; - self.changes.replace(Default::default()).into_storage_changes( + #crate_::OverlayedChanges::into_storage_changes( + std::cell::RefCell::take(&self.changes), backend, - self.storage_transaction_cache.replace(Default::default()), + core::cell::RefCell::take(&self.storage_transaction_cache), state_version, ) } @@ -321,9 +317,9 @@ fn generate_runtime_api_base_structures() -> Result { RuntimeApiImpl { call: unsafe { std::mem::transmute(call) }, commit_on_success: true.into(), - changes: Default::default(), - recorder: Default::default(), - storage_transaction_cache: Default::default(), + changes: std::default::Default::default(), + recorder: std::default::Default::default(), + storage_transaction_cache: std::default::Default::default(), }.into() } } @@ -331,20 +327,22 @@ fn generate_runtime_api_base_structures() -> Result { #[cfg(any(feature = "std", test))] impl> RuntimeApiImpl { fn call_api_at< - R: #crate_::Encode + #crate_::Decode + PartialEq, + R: #crate_::Encode + #crate_::Decode + std::cmp::PartialEq, F: FnOnce( &C, &std::cell::RefCell<#crate_::OverlayedChanges>, &std::cell::RefCell<#crate_::StorageTransactionCache>, - &Option<#crate_::ProofRecorder>, + &std::option::Option<#crate_::ProofRecorder>, ) -> std::result::Result<#crate_::NativeOrEncoded, E>, E, >( &self, call_api_at: F, ) -> std::result::Result<#crate_::NativeOrEncoded, E> { - if *self.commit_on_success.borrow() { - self.changes.borrow_mut().start_transaction(); + if *std::cell::RefCell::borrow(&self.commit_on_success) { + #crate_::OverlayedChanges::start_transaction( + &mut std::cell::RefCell::borrow_mut(&self.changes) + ); } let res = call_api_at( &self.call, @@ -353,7 +351,7 @@ fn generate_runtime_api_base_structures() -> Result { &self.recorder, ); - self.commit_or_rollback(res.is_ok()); + self.commit_or_rollback(std::result::Result::is_ok(&res)); res } @@ -362,13 +360,19 @@ fn generate_runtime_api_base_structures() -> Result { We only close a transaction when we opened one ourself. Other parts of the runtime that make use of transactions (state-machine) also balance their transactions. The runtime cannot close client initiated - transactions. qed"; - if *self.commit_on_success.borrow() { - if commit { - self.changes.borrow_mut().commit_transaction().expect(proof); + transactions; qed"; + if *std::cell::RefCell::borrow(&self.commit_on_success) { + let res = if commit { + #crate_::OverlayedChanges::commit_transaction( + &mut std::cell::RefCell::borrow_mut(&self.changes) + ) } else { - self.changes.borrow_mut().rollback_transaction().expect(proof); - } + #crate_::OverlayedChanges::rollback_transaction( + &mut std::cell::RefCell::borrow_mut(&self.changes) + ) + }; + + std::result::Result::expect(res, proof); } } } From 6bc85d986b6448d88e6e5f14603e292d83f73f8f Mon Sep 17 00:00:00 2001 From: driemworks Date: Fri, 11 Mar 2022 18:38:24 -0500 Subject: [PATCH 582/695] unlock and transfer works --- Cargo.lock | 1656 +++++++++-------- .../pallets/iris-assets/src/lib.rs | 1 - .../pallets/iris-ledger/src/lib.rs | 17 +- .../pallets/iris-ledger/src/mock.rs | 223 +-- .../pallets/iris-ledger/src/tests.rs | 212 +-- client/consensus/aura/Cargo.toml | 2 +- 6 files changed, 978 insertions(+), 1133 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fd75e61b7135..0585177784ae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -21,6 +21,15 @@ dependencies = [ "gimli 0.25.0", ] +[[package]] +name = "addr2line" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" +dependencies = [ + "gimli 0.26.1", +] + [[package]] name = "adler" version = "1.0.2" @@ -33,7 +42,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" dependencies = [ - "generic-array 0.14.4", + "generic-array 0.14.5", ] [[package]] @@ -64,13 +73,13 @@ dependencies = [ [[package]] name = "ahash" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43bb833f0bf979d8475d38fbf09ed3b8a55e1885fe93ad3f93239fc6a4f17b98" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" dependencies = [ - "getrandom 0.2.3", + "getrandom 0.2.5", "once_cell", - "version_check 0.9.3", + "version_check 0.9.4", ] [[package]] @@ -102,24 +111,24 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.44" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61604a8f862e1d5c3229fdd78f8b02c68dcf73a4c4b05fd636d12240aaa242c1" +checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27" [[package]] name = "approx" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "072df7202e63b127ab55acfe16ce97013d5b97bf160489336d3f1840fd78e99e" +checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" dependencies = [ "num-traits", ] [[package]] name = "arbitrary" -version = "1.0.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "577b08a4acd7b99869f863c50011b01eb73424ccc798ecd996f2e24817adfca7" +checksum = "c38b6b6b79f671c25e1a3e785b7b82d7562ffc9cd3efdc98627e5668a2472490" [[package]] name = "arrayref" @@ -144,15 +153,15 @@ checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" [[package]] name = "arrayvec" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4dc07131ffa69b8072d35f5007352af944213cde02545e2103680baed38fcd" +checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" [[package]] name = "asn1_der" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d6e24d2cce90c53b948c46271bfb053e4bdc2db9b5d3f65e20f8cf28a1b7fc3" +checksum = "e22d1f4b888c298a027c99dc9048015fac177587de20fc30232a057dfbe24a21" [[package]] name = "assert_cmd" @@ -211,9 +220,9 @@ dependencies = [ [[package]] name = "async-global-executor" -version = "2.0.2" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9586ec52317f36de58453159d48351bc244bc24ced3effc1fce22f3d48664af6" +checksum = "c026b7e44f1316b567ee750fea85103f87fcb80792b860e979f221259796ca0a" dependencies = [ "async-channel", "async-executor", @@ -239,16 +248,16 @@ dependencies = [ "parking", "polling", "slab", - "socket2 0.4.2", + "socket2 0.4.4", "waker-fn", "winapi 0.3.9", ] [[package]] name = "async-lock" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6a8ea61bf9947a1007c5cada31e647dbc77b103c679858150003ba697ea798b" +checksum = "e97a171d191782fba31bb902b14ad94e24a68145032b7eedf871ab0bc0d077b6" dependencies = [ "event-listener", ] @@ -264,9 +273,9 @@ dependencies = [ [[package]] name = "async-process" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b21b63ab5a0db0369deb913540af2892750e42d949faacc7a61495ac418a1692" +checksum = "83137067e3a2a6a06d67168e49e68a0957d215410473a740cea95a2425c0b7c6" dependencies = [ "async-io", "blocking", @@ -291,7 +300,7 @@ dependencies = [ "async-io", "async-lock", "async-process", - "crossbeam-utils 0.8.5", + "crossbeam-utils 0.8.7", "futures-channel", "futures-core", "futures-io", @@ -302,7 +311,7 @@ dependencies = [ "memchr", "num_cpus", "once_cell", - "pin-project-lite 0.2.7", + "pin-project-lite 0.2.8", "pin-utils", "slab", "wasm-bindgen-futures", @@ -310,9 +319,9 @@ dependencies = [ [[package]] name = "async-std-resolver" -version = "0.20.3" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed4e2c3da14d8ad45acb1e3191db7a918e9505b6f155b218e70a7c9a1a48c638" +checksum = "dbf3e776afdf3a2477ef4854b85ba0dff3bd85792f685fb3c68948b4d304e4f0" dependencies = [ "async-std", "async-trait", @@ -345,15 +354,15 @@ dependencies = [ [[package]] name = "async-task" -version = "4.0.3" +version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91831deabf0d6d7ec49552e489aed63b7456a7a3c46cff62adad428110b0af0" +checksum = "30696a84d817107fc028e049980e09d5e140e8da8f1caeb17e8e950658a3cea9" [[package]] name = "async-trait" -version = "0.1.51" +version = "0.1.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44318e776df68115a881de9a8fd1b9e53368d7a4a5ce4cc48517da3393233a5e" +checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3" dependencies = [ "proc-macro2", "quote", @@ -370,7 +379,7 @@ dependencies = [ "futures-sink", "futures-util", "memchr", - "pin-project-lite 0.2.7", + "pin-project-lite 0.2.8", ] [[package]] @@ -383,16 +392,16 @@ dependencies = [ "futures-sink", "futures-util", "memchr", - "pin-project-lite 0.2.7", + "pin-project-lite 0.2.8", ] [[package]] name = "atomic" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3410529e8288c463bedb5930f82833bc0c90e5d2fe639a56582a4d09220b281" +checksum = "b88d82667eca772c4aa12f0f1348b3ae643424c8876448f3f7bd5787032e234c" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", ] [[package]] @@ -414,39 +423,42 @@ dependencies = [ [[package]] name = "autocfg" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" +checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78" +dependencies = [ + "autocfg 1.1.0", +] [[package]] name = "autocfg" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.61" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7a905d892734eea339e896738c14b9afce22b5318f64b951e70bf3844419b01" +checksum = "5e121dee8023ce33ab248d9ce1493df03c3b38a659b240096fcbd7048ff9c31f" dependencies = [ - "addr2line", + "addr2line 0.17.0", "cc", "cfg-if 1.0.0", "libc", "miniz_oxide", - "object 0.26.2", + "object 0.27.1", "rustc-demangle", ] [[package]] name = "bae" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec107f431ee3d8a8e45e6dd117adab769556ef463959e77bf6a4888d5fd500cf" +checksum = "33b8de67cc41132507eeece2584804efcb15f85ba516e34c944b7667f480397a" dependencies = [ - "heck", - "proc-macro-error 0.4.12", + "heck 0.3.3", + "proc-macro-error", "proc-macro2", "quote", "syn", @@ -510,7 +522,7 @@ version = "4.0.0-dev" dependencies = [ "beefy-primitives", "fnv", - "futures 0.3.17", + "futures 0.3.21", "log 0.4.14", "parity-scale-codec", "parking_lot 0.11.2", @@ -539,7 +551,7 @@ version = "4.0.0-dev" dependencies = [ "beefy-gadget", "beefy-primitives", - "futures 0.3.17", + "futures 0.3.21", "jsonrpc-core", "jsonrpc-core-client", "jsonrpc-derive", @@ -589,9 +601,9 @@ dependencies = [ [[package]] name = "bindgen" -version = "0.59.1" +version = "0.59.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453c49e5950bb0eb63bb3df640e31618846c89d5b7faa54040d76e98e0134375" +checksum = "2bd2a9a458e8f4304c52c43ebb0cfbd520289f8379a52e329a38afda99bf8eb8" dependencies = [ "bitflags", "cexpr", @@ -612,18 +624,6 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" -[[package]] -name = "bitvec" -version = "0.19.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8942c8d352ae1838c9dda0b0ca2ab657696ef2232a20147cf1b30ae1a9cb4321" -dependencies = [ - "funty", - "radium 0.5.3", - "tap", - "wyz", -] - [[package]] name = "bitvec" version = "0.20.4" @@ -631,7 +631,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7774144344a4faa177370406a7ff5f1da24303817368584c6206c8303eb07848" dependencies = [ "funty", - "radium 0.6.2", + "radium", "tap", "wyz", ] @@ -713,7 +713,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ "block-padding 0.2.1", - "generic-array 0.14.4", + "generic-array 0.14.5", ] [[package]] @@ -733,9 +733,9 @@ checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" [[package]] name = "blocking" -version = "1.0.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e170dbede1f740736619b776d7251cb1b9095c435c34d8ca9f57fcd2f335e9" +checksum = "046e47d4b2d391b1f6f8b407b1deb8dee56c1852ccd868becf2710f601b5f427" dependencies = [ "async-channel", "async-task", @@ -774,15 +774,15 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.7.1" +version = "3.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9df67f7bf9ef8498769f994239c45613ef0c5899415fb58e9add412d2c1a538" +checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" [[package]] name = "byte-slice-cast" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca0796d76a983651b4a0ddda16203032759f2fd9103d9181f7c65c06ee8872e6" +checksum = "87c5fdd0166095e1d463fc6cc01aa8ce547ad77a4e84d42eb6762b084e28067e" [[package]] name = "byte-tools" @@ -820,15 +820,15 @@ checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" [[package]] name = "cache-padded" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba" +checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c" [[package]] name = "camino" -version = "1.0.5" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52d74260d9bf6944e2208aa46841b4b8f0d7ffc0849a06837b2f510337f86b2b" +checksum = "6f3132262930b0522068049f5870a856ab8affc80c70d08b6ecb785771a6fc23" dependencies = [ "serde", ] @@ -867,18 +867,18 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.70" +version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26a6ce4b6a484fa3edb70f7efa6fc430fd2b87285fe8b84304fd0936faa0dc0" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" dependencies = [ "jobserver", ] [[package]] name = "cexpr" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db507a7679252d2276ed0dd8113c6875ec56d3089f9225b2b42c30cc1f8e5c89" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" dependencies = [ "nom", ] @@ -975,7 +975,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" dependencies = [ - "generic-array 0.14.4", + "generic-array 0.14.5", ] [[package]] @@ -989,22 +989,22 @@ dependencies = [ [[package]] name = "clang-sys" -version = "1.2.2" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10612c0ec0e0a1ff0e97980647cb058a6e7aedb913d01d009c406b8b7d0b26ee" +checksum = "4cc00842eed744b858222c4c9faf7243aafc6d33f92f96935263ef4d8a41ce21" dependencies = [ "glob", "libc", - "libloading 0.7.0", + "libloading 0.7.3", ] [[package]] name = "clap" -version = "2.33.3" +version = "2.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ - "ansi_term 0.11.0", + "ansi_term 0.12.1", "atty", "bitflags", "strsim 0.8.0", @@ -1045,9 +1045,9 @@ checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" [[package]] name = "core-foundation" -version = "0.9.1" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a89e2ae426ea83155dccf10c0fa6b1463ef6d5fcb44cee0b224a408fa640a62" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" dependencies = [ "core-foundation-sys", "libc", @@ -1055,15 +1055,15 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" [[package]] name = "cpp_demangle" -version = "0.3.3" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea47428dc9d2237f3c6bc134472edfd63ebba0af932e783506dcfd66f10d18a" +checksum = "eeaa953eaad386a53111e47172c2fedba671e5684c8dd601a5f474f4f118710f" dependencies = [ "cfg-if 1.0.0", ] @@ -1118,7 +1118,7 @@ dependencies = [ "gimli 0.22.0", "log 0.4.14", "regalloc", - "smallvec 1.7.0", + "smallvec 1.8.0", "target-lexicon 0.11.2", "thiserror", ] @@ -1137,8 +1137,8 @@ dependencies = [ "log 0.4.14", "regalloc", "serde", - "smallvec 1.7.0", - "target-lexicon 0.12.2", + "smallvec 1.8.0", + "target-lexicon 0.12.3", ] [[package]] @@ -1202,7 +1202,7 @@ checksum = "b608bb7656c554d0a4cf8f50c7a10b857e80306f6ff829ad6d468a7e2323c8d8" dependencies = [ "cranelift-codegen 0.68.0", "log 0.4.14", - "smallvec 1.7.0", + "smallvec 1.8.0", "target-lexicon 0.11.2", ] @@ -1214,8 +1214,8 @@ checksum = "279afcc0d3e651b773f94837c3d581177b348c8d69e928104b2e9fccb226f921" dependencies = [ "cranelift-codegen 0.76.0", "log 0.4.14", - "smallvec 1.7.0", - "target-lexicon 0.12.2", + "smallvec 1.8.0", + "target-lexicon 0.12.3", ] [[package]] @@ -1226,7 +1226,7 @@ checksum = "4c04d1fe6a5abb5bb0edc78baa8ef238370fb8e389cc88b6d153f7c3e9680425" dependencies = [ "cranelift-codegen 0.76.0", "libc", - "target-lexicon 0.12.2", + "target-lexicon 0.12.3", ] [[package]] @@ -1241,16 +1241,16 @@ dependencies = [ "itertools", "log 0.4.14", "serde", - "smallvec 1.7.0", + "smallvec 1.8.0", "thiserror", "wasmparser 0.79.0", ] [[package]] name = "crc32fast" -version = "1.2.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" dependencies = [ "cfg-if 1.0.0", ] @@ -1293,12 +1293,12 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" +checksum = "e54ea8bc3fb1ee042f5aace6e3c6e025d3874866da222930f70ce62aceba0bfa" dependencies = [ "cfg-if 1.0.0", - "crossbeam-utils 0.8.5", + "crossbeam-utils 0.8.7", ] [[package]] @@ -1309,17 +1309,17 @@ checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" dependencies = [ "cfg-if 1.0.0", "crossbeam-epoch", - "crossbeam-utils 0.8.5", + "crossbeam-utils 0.8.7", ] [[package]] name = "crossbeam-epoch" -version = "0.9.5" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd" +checksum = "c00d6d2ea26e8b151d99093005cb442fb9a37aeaca582a03ec70946f49ab5ed9" dependencies = [ "cfg-if 1.0.0", - "crossbeam-utils 0.8.5", + "crossbeam-utils 0.8.7", "lazy_static", "memoffset", "scopeguard", @@ -1331,16 +1331,16 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", "cfg-if 0.1.10", "lazy_static", ] [[package]] name = "crossbeam-utils" -version = "0.8.5" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" +checksum = "b5e5bed1f1c269533fa816a0a5492b3545209a205ca1a54842be180eb63a16a6" dependencies = [ "cfg-if 1.0.0", "lazy_static", @@ -1368,7 +1368,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" dependencies = [ - "generic-array 0.14.4", + "generic-array 0.14.5", "subtle 2.4.1", ] @@ -1378,7 +1378,7 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" dependencies = [ - "generic-array 0.14.4", + "generic-array 0.14.5", "subtle 2.4.1", ] @@ -1390,7 +1390,7 @@ checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" dependencies = [ "bstr", "csv-core", - "itoa", + "itoa 0.4.8", "ryu", "serde", ] @@ -1471,9 +1471,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "757c0ded2af11d8e739c4daea1ac623dd1624b06c844cf3f5a39f1bdbd99bb12" +checksum = "d0d720b8683f8dd83c65155f0530560cba68cd2bf395f6513a483caee57ff7f4" dependencies = [ "darling_core", "darling_macro", @@ -1481,9 +1481,9 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c34d8efb62d0c2d7f60ece80f75e5c63c1588ba68032740494b0b9a996466e3" +checksum = "7a340f241d2ceed1deb47ae36c4144b2707ec7dd0b649f894cb39bb595986324" dependencies = [ "fnv", "ident_case", @@ -1495,9 +1495,9 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade7bff147130fe5e6d39f089c6bd49ec0250f35d70b2eebf72afdfc919f15cc" +checksum = "72c41b3b7352feb3211a0d743dc5700a4e3b60f51bd2b368892d1e0f9a95f44b" dependencies = [ "darling_core", "quote", @@ -1532,14 +1532,14 @@ dependencies = [ [[package]] name = "derive_more" -version = "0.99.16" +version = "0.99.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40eebddd2156ce1bb37b20bbe5151340a31828b1f2d22ba4141f3531710e38df" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ "convert_case", "proc-macro2", "quote", - "rustc_version 0.3.3", + "rustc_version 0.4.0", "syn", ] @@ -1576,7 +1576,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "generic-array 0.14.4", + "generic-array 0.14.5", ] [[package]] @@ -1677,14 +1677,14 @@ checksum = "ee2626afccd7561a06cf1367e2950c4718ea04565e20fb5029b6c7d8ad09abcf" [[package]] name = "dynasm" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdc2d9a5e44da60059bd38db2d05cbb478619541b8c79890547861ec1e3194f0" +checksum = "47b1801e630bd336d0bbbdbf814de6cc749c9a400c7e3d995e6adfd455d0c83c" dependencies = [ "bitflags", "byteorder", "lazy_static", - "proc-macro-error 1.0.4", + "proc-macro-error", "proc-macro2", "quote", "syn", @@ -1692,20 +1692,20 @@ dependencies = [ [[package]] name = "dynasmrt" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42276e3f205fe63887cca255aa9a65a63fb72764c30b9a6252a7c7e46994f689" +checksum = "1d428afc93ad288f6dffc1fa5f4a78201ad2eec33c5a522e51c181009eb09061" dependencies = [ "byteorder", "dynasm", - "memmap2", + "memmap2 0.5.3", ] [[package]] name = "ed25519" -version = "1.2.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4620d40f6d2601794401d6dd95a5cf69b6c157852539470eeda433a99b3c0efc" +checksum = "eed12bbf7b5312f8da1c2722bc06d8c6b12c2d86a7fb35a194c7f3e6fc2bbe39" dependencies = [ "signature", ] @@ -1720,7 +1720,7 @@ dependencies = [ "ed25519", "rand 0.7.3", "serde", - "sha2 0.9.8", + "sha2 0.9.9", "zeroize", ] @@ -1732,11 +1732,11 @@ checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] name = "enum-as-inner" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c5f0096a91d210159eceb2ff5e1c4da18388a170e1e3ce948aac9c8fdbbf595" +checksum = "570d109b813e904becc80d8d5da38376818a143348413f7149f1340fe04754d4" dependencies = [ - "heck", + "heck 0.4.0", "proc-macro2", "quote", "syn", @@ -1764,9 +1764,9 @@ dependencies = [ [[package]] name = "enumset" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e76129da36102af021b8e5000dab2c1c30dbef85c1e482beeff8da5dde0e0b0" +checksum = "6216d2c19a6fb5f29d1ada1dc7bc4367a8cbf0fa4af5cf12e07b5bbdde6b5b2c" dependencies = [ "enumset_derive", ] @@ -1783,19 +1783,6 @@ dependencies = [ "syn", ] -[[package]] -name = "env_logger" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" -dependencies = [ - "atty", - "humantime 1.3.0", - "log 0.4.14", - "regex", - "termcolor", -] - [[package]] name = "env_logger" version = "0.8.4" @@ -1813,7 +1800,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3" dependencies = [ "atty", - "humantime 2.1.0", + "humantime", "log 0.4.14", "regex", "termcolor", @@ -1827,18 +1814,18 @@ checksum = "68b91989ae21441195d7d9b9993a2f9295c7e1a8c96255d8b729accddc124797" [[package]] name = "erased-serde" -version = "0.3.16" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3de9ad4541d99dc22b59134e7ff8dc3d6c988c89ecd7324bf10a8362b07a2afa" +checksum = "56047058e1ab118075ca22f9ecd737bcc961aa3566a3019cb71388afa280bd8a" dependencies = [ "serde", ] [[package]] name = "errno" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa68f2fb9cae9d37c9b2b3584aba698a2e97f72d7aef7b9f7aa71d8b54ce46fe" +checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" dependencies = [ "errno-dragonfly", "libc", @@ -1857,9 +1844,9 @@ dependencies = [ [[package]] name = "event-listener" -version = "2.5.1" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59" +checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71" [[package]] name = "exit-future" @@ -1867,7 +1854,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e43f2f1833d64e33f15592464d6fdd70f349dda7b1a53088eb83cd94014008c5" dependencies = [ - "futures 0.3.17", + "futures 0.3.21", ] [[package]] @@ -1884,9 +1871,9 @@ checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" [[package]] name = "fastrand" -version = "1.5.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b394ed3d285a429378d3b384b9eb1285267e7df4b166df24b7a6939a04dc392e" +checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" dependencies = [ "instant", ] @@ -1902,11 +1889,11 @@ dependencies = [ [[package]] name = "file-per-thread-logger" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fdbe0d94371f9ce939b555dd342d0686cc4c0cadbcd4b61d70af5ff97eb4126" +checksum = "21e16290574b39ee41c71aeb90ae960c504ebaf1e2a1c87bd52aa56ed6e1a02f" dependencies = [ - "env_logger 0.7.1", + "env_logger 0.9.0", "log 0.4.14", ] @@ -1918,7 +1905,7 @@ checksum = "975ccf83d8d9d0d84682850a38c8169027be83368805971cc4f238c2b245bc98" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall 0.2.10", + "redox_syscall 0.2.11", "winapi 0.3.9", ] @@ -1929,13 +1916,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8ac3ff5224ef91f3c97e03eb1de2db82743427e91aaa5ac635f454f0b164f5a" dependencies = [ "either", - "futures 0.3.17", + "futures 0.3.21", "futures-timer 3.0.2", "log 0.4.14", "num-traits", "parity-scale-codec", "parking_lot 0.11.2", - "rand 0.8.4", + "rand 0.8.5", "scale-info", ] @@ -1946,7 +1933,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcf0ed7fe52a17a03854ec54a9f76d6d84508d1c0e66bc1793301c73fc8493c" dependencies = [ "byteorder", - "rand 0.8.4", + "rand 0.8.5", "rustc-hex", "static_assertions", ] @@ -2018,7 +2005,7 @@ dependencies = [ "linregress", "log 0.4.14", "parity-scale-codec", - "paste 1.0.5", + "paste 1.0.6", "scale-info", "sp-api", "sp-io", @@ -2091,9 +2078,9 @@ dependencies = [ [[package]] name = "frame-metadata" -version = "14.0.0" +version = "14.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96616f82e069102b95a72c87de4c84d2f87ef7f0f20630e78ce3824436483110" +checksum = "37ed5e5c346de62ca5c184b4325a6600d1eaca210666e4606fe4e449574978d0" dependencies = [ "cfg-if 1.0.0", "parity-scale-codec", @@ -2115,11 +2102,11 @@ dependencies = [ "once_cell", "parity-scale-codec", "parity-util-mem", - "paste 1.0.5", + "paste 1.0.6", "pretty_assertions 0.6.1", "scale-info", "serde", - "smallvec 1.7.0", + "smallvec 1.8.0", "sp-arithmetic", "sp-core", "sp-inherents", @@ -2147,7 +2134,7 @@ name = "frame-support-procedural-tools" version = "4.0.0-dev" dependencies = [ "frame-support-procedural-tools-derive", - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn", @@ -2310,9 +2297,9 @@ checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" [[package]] name = "futures" -version = "0.3.17" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12aa0eb539080d55c3f2d45a67c3b58b6b0773c1a3ca2dfec66d58c97fd66ca" +checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" dependencies = [ "futures-channel", "futures-core", @@ -2325,9 +2312,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.17" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5da6ba8c3bb3c165d3c7319fc1cc8304facf1fb8db99c5de877183c08a273888" +checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" dependencies = [ "futures-core", "futures-sink", @@ -2335,15 +2322,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.17" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d1c26957f23603395cd326b0ffe64124b818f4449552f960d815cfba83a53d" +checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" [[package]] name = "futures-executor" -version = "0.3.17" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45025be030969d763025784f7f355043dc6bc74093e4ecc5000ca4dc50d8745c" +checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" dependencies = [ "futures-core", "futures-task", @@ -2353,9 +2340,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.17" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "522de2a0fe3e380f1bc577ba0474108faf3f6b18321dbf60b3b9c39a75073377" +checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" [[package]] name = "futures-lite" @@ -2368,18 +2355,16 @@ dependencies = [ "futures-io", "memchr", "parking", - "pin-project-lite 0.2.7", + "pin-project-lite 0.2.8", "waker-fn", ] [[package]] name = "futures-macro" -version = "0.3.17" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18e4a4b95cea4b4ccbcf1c5675ca7c4ee4e9e75eb79944d07defde18068f79bb" +checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" dependencies = [ - "autocfg 1.0.1", - "proc-macro-hack", "proc-macro2", "quote", "syn", @@ -2398,15 +2383,15 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.17" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36ea153c13024fe480590b3e3d4cad89a0cfacecc24577b68f86c6ced9c2bc11" +checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" [[package]] name = "futures-task" -version = "0.3.17" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d3d00f4eddb73e498a54394f228cd55853bdf059259e8e7bc6e69d408892e99" +checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" [[package]] name = "futures-timer" @@ -2422,11 +2407,10 @@ checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" [[package]] name = "futures-util" -version = "0.3.17" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36568465210a3a6ee45e1f165136d68671471a501e632e9a98d96872222b5481" +checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" dependencies = [ - "autocfg 1.0.1", "futures 0.1.31", "futures-channel", "futures-core", @@ -2435,10 +2419,8 @@ dependencies = [ "futures-sink", "futures-task", "memchr", - "pin-project-lite 0.2.7", + "pin-project-lite 0.2.8", "pin-utils", - "proc-macro-hack", - "proc-macro-nested", "slab", ] @@ -2477,12 +2459,12 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.4" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" +checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" dependencies = [ "typenum", - "version_check 0.9.3", + "version_check 0.9.4", ] [[package]] @@ -2500,15 +2482,13 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.3" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +checksum = "d39cd93900197114fa1fcb7ae84ca742095eed9442088988ae74fa744e930e77" dependencies = [ "cfg-if 1.0.0", - "js-sys", "libc", "wasi 0.10.0+wasi-snapshot-preview1", - "wasm-bindgen", ] [[package]] @@ -2543,11 +2523,17 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "gimli" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" + [[package]] name = "git2" -version = "0.13.22" +version = "0.13.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c1cbbfc9a1996c6af82c2b4caf828d2c653af4fcdbb0e5674cc966eee5a4197" +checksum = "f29229cc1b24c0e6062f6e742aa3e256492a5323365e5ed3413599f8a5eff7d6" dependencies = [ "bitflags", "libc", @@ -2577,22 +2563,21 @@ dependencies = [ [[package]] name = "gloo-timers" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47204a46aaff920a1ea58b11d03dec6f704287d27561724a4631e450654a891f" +checksum = "4d12a7f4e95cfe710f1d624fb1210b7d961a5fb05c4fd942f4feab06e61f590e" dependencies = [ "futures-channel", "futures-core", "js-sys", "wasm-bindgen", - "web-sys", ] [[package]] name = "half" -version = "1.7.1" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62aca2aba2d62b4a7f5b33f3712cb1b0692779a56fb510499d5c0aa594daeaf3" +checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" [[package]] name = "handlebars" @@ -2647,6 +2632,12 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -2664,9 +2655,9 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hex-literal" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21e4590e13640f19f249fe3e4eca5113bc4289f2497710378190e7f4bd96f45b" +checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" [[package]] name = "hex_fmt" @@ -2722,7 +2713,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" dependencies = [ "digest 0.9.0", - "generic-array 0.14.4", + "generic-array 0.14.5", "hmac 0.8.1", ] @@ -2750,46 +2741,37 @@ dependencies = [ [[package]] name = "http" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1323096b05d41827dadeaee54c9981958c0f94e670bc94ed80037d1a7b8b186b" +checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03" dependencies = [ "bytes 1.1.0", "fnv", - "itoa", + "itoa 1.0.1", ] [[package]] name = "http-body" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "399c583b2979440c60be0821a6199eca73bc3c8dcd9d070d75ac726e2c6186e5" +checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6" dependencies = [ "bytes 1.1.0", "http", - "pin-project-lite 0.2.7", + "pin-project-lite 0.2.8", ] [[package]] name = "httparse" -version = "1.5.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503" +checksum = "9100414882e15fb7feccb4897e5f0ff0ff1ca7d1a86a23208ada4d7a18e6c6c4" [[package]] name = "httpdate" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6456b8a6c8f33fee7d958fcd1b60d55b11940a79e63ae87013e6d22e26034440" - -[[package]] -name = "humantime" -version = "1.3.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" -dependencies = [ - "quick-error 1.2.3", -] +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" [[package]] name = "humantime" @@ -2818,9 +2800,9 @@ dependencies = [ [[package]] name = "hyper" -version = "0.14.13" +version = "0.14.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15d1cfb9e4f68655fa04c01f59edb405b6074a0f7118ea881e5026e4a1cd8593" +checksum = "043f0e083e9901b6cc658a77d1eb86f4fc650bbb977a4337dd63192826aa85dd" dependencies = [ "bytes 1.1.0", "futures-channel", @@ -2830,9 +2812,9 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa", - "pin-project-lite 0.2.7", - "socket2 0.4.2", + "itoa 1.0.1", + "pin-project-lite 0.2.8", + "socket2 0.4.4", "tokio", "tower-service", "tracing", @@ -2847,7 +2829,7 @@ checksum = "5f9f7a97316d44c0af9b0301e65010573a853a9fc97046d7331d7f6bc0fd5a64" dependencies = [ "ct-logs", "futures-util", - "hyper 0.14.13", + "hyper 0.14.17", "log 0.4.14", "rustls", "rustls-native-certs", @@ -2863,7 +2845,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ "bytes 1.1.0", - "hyper 0.14.13", + "hyper 0.14.17", "native-tls", "tokio", "tokio-native-tls", @@ -2899,9 +2881,9 @@ dependencies = [ [[package]] name = "if-addrs" -version = "0.6.6" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9a83ec4af652890ac713ffd8dc859e650420a5ef47f7b9be29b6664ab50fbc8" +checksum = "2273e421f7c4f0fc99e1934fe4776f59d8df2972f4199d703fc0da9f2a9f73de" dependencies = [ "if-addrs-sys", "libc", @@ -2925,7 +2907,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae8ab7f67bad3240049cb24fb9cb0b4c2c6af4c245840917fbbdededeee91179" dependencies = [ "async-io", - "futures 0.3.17", + "futures 0.3.21", "futures-lite", "if-addrs", "ipnet", @@ -2945,18 +2927,18 @@ dependencies = [ [[package]] name = "impl-serde" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b47ca4d2b6931707a55fce5cf66aff80e2178c8b63bbb4ecb5695cbc870ddf6f" +checksum = "4551f042f3438e64dbd6226b20527fc84a6e1fe65688b58746a2f53623f25f5c" dependencies = [ "serde", ] [[package]] name = "impl-trait-for-tuples" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5dacb10c5b3bb92d46ba347505a9041e676bb20ad220101326bffb0c93031ee" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" dependencies = [ "proc-macro2", "quote", @@ -2965,20 +2947,20 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" +checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", "hashbrown", "serde", ] [[package]] name = "instant" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "716d3d89f35ac6a34fd0eed635395f4c3b76fa889338a4632e5231a8684216bd" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ "cfg-if 1.0.0", ] @@ -2998,7 +2980,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64fa110ec7b8f493f416eed552740d10e7030ad5f63b2308f82c9608ec2df275" dependencies = [ - "futures 0.3.17", + "futures 0.3.21", "futures-timer 2.0.2", ] @@ -3013,9 +2995,9 @@ dependencies = [ [[package]] name = "ip_network" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09b746553d2f4a1ca26fab939943ddfb217a091f34f53571620a8e3d30691303" +checksum = "aa2f047c0a98b2f299aa5d6d7088443570faae494e9ae1305e48be000c9e0eb1" [[package]] name = "ipconfig" @@ -3032,7 +3014,7 @@ dependencies = [ [[package]] name = "ipfs" version = "0.2.1" -source = "git+https://github.com/rs-ipfs/rust-ipfs#111f116e366e8f3f9b409d1c92be6ac51f7009f4" +source = "git+https://github.com/rs-ipfs/rust-ipfs#3eff4e15342d430870bfa4fad7c2604c865266b2" dependencies = [ "anyhow", "async-stream", @@ -3043,7 +3025,7 @@ dependencies = [ "cid 0.5.1", "either", "fs2", - "futures 0.3.17", + "futures 0.3.21", "hash_hasher", "ipfs-bitswap", "ipfs-unixfs", @@ -3069,11 +3051,11 @@ dependencies = [ [[package]] name = "ipfs-bitswap" version = "0.1.0" -source = "git+https://github.com/rs-ipfs/rust-ipfs#111f116e366e8f3f9b409d1c92be6ac51f7009f4" +source = "git+https://github.com/rs-ipfs/rust-ipfs#3eff4e15342d430870bfa4fad7c2604c865266b2" dependencies = [ "cid 0.5.1", "fnv", - "futures 0.3.17", + "futures 0.3.21", "hash_hasher", "libp2p-core", "libp2p-swarm", @@ -3089,27 +3071,27 @@ dependencies = [ [[package]] name = "ipfs-unixfs" version = "0.2.0" -source = "git+https://github.com/rs-ipfs/rust-ipfs#111f116e366e8f3f9b409d1c92be6ac51f7009f4" +source = "git+https://github.com/rs-ipfs/rust-ipfs#3eff4e15342d430870bfa4fad7c2604c865266b2" dependencies = [ "cid 0.5.1", "either", "filetime", "multihash 0.11.4", "quick-protobuf", - "sha2 0.9.8", + "sha2 0.9.9", ] [[package]] name = "ipnet" -version = "2.3.1" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9" +checksum = "35e70ee094dc02fd9c13fdad4940090f22dbd6ac7c9e7094a46cf0232a50bc7c" [[package]] name = "itertools" -version = "0.10.1" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf" +checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" dependencies = [ "either", ] @@ -3120,6 +3102,12 @@ version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" +[[package]] +name = "itoa" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" + [[package]] name = "jobserver" version = "0.1.24" @@ -3131,9 +3119,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.55" +version = "0.3.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84" +checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04" dependencies = [ "wasm-bindgen", ] @@ -3145,8 +3133,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2b99d4207e2a04fb4581746903c2bb7eb376f88de9c699d0f3e10feeac0cd3a" dependencies = [ "derive_more", - "futures 0.3.17", - "hyper 0.14.13", + "futures 0.3.21", + "hyper 0.14.17", "hyper-tls", "jsonrpc-core", "jsonrpc-pubsub", @@ -3164,7 +3152,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14f7f76aef2d054868398427f6c54943cf3d1caa9a7ec7d0c38d69df97a965eb" dependencies = [ - "futures 0.3.17", + "futures 0.3.21", "futures-executor", "futures-util", "log 0.4.14", @@ -3179,7 +3167,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b51da17abecbdab3e3d4f26b01c5ec075e88d3abe3ab3b05dc9aa69392764ec0" dependencies = [ - "futures 0.3.17", + "futures 0.3.21", "jsonrpc-client-transports", ] @@ -3201,8 +3189,8 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1dea6e07251d9ce6a552abfb5d7ad6bc290a4596c8dcc3d795fae2bbdc1f3ff" dependencies = [ - "futures 0.3.17", - "hyper 0.14.13", + "futures 0.3.21", + "hyper 0.14.17", "jsonrpc-core", "jsonrpc-server-utils", "log 0.4.14", @@ -3217,7 +3205,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "382bb0206323ca7cda3dcd7e245cea86d37d02457a02a975e3378fb149a48845" dependencies = [ - "futures 0.3.17", + "futures 0.3.21", "jsonrpc-core", "jsonrpc-server-utils", "log 0.4.14", @@ -3232,7 +3220,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240f87695e6c6f62fb37f05c02c04953cf68d6408b8c1c89de85c7a0125b1011" dependencies = [ - "futures 0.3.17", + "futures 0.3.21", "jsonrpc-core", "lazy_static", "log 0.4.14", @@ -3248,7 +3236,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa4fdea130485b572c39a460d50888beb00afb3e35de23ccd7fad8ff19f0e0d4" dependencies = [ "bytes 1.1.0", - "futures 0.3.17", + "futures 0.3.21", "globset", "jsonrpc-core", "lazy_static", @@ -3265,7 +3253,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f892c7d766369475ab7b0669f417906302d7c0fb521285c0a0c92e52e7c8e946" dependencies = [ - "futures 0.3.17", + "futures 0.3.21", "jsonrpc-core", "jsonrpc-server-utils", "log 0.4.14", @@ -3282,7 +3270,7 @@ checksum = "8edb341d35279b59c79d7fe9e060a51aec29d45af99cc7c72ea7caa350fa71a4" dependencies = [ "Inflector", "bae", - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn", @@ -3298,7 +3286,7 @@ dependencies = [ "beef", "futures-channel", "futures-util", - "hyper 0.14.13", + "hyper 0.14.17", "log 0.4.14", "serde", "serde_json", @@ -3314,10 +3302,10 @@ checksum = "9841352dbecf4c2ed5dc71698df9f1660262ae4e0b610e968602529bdbcf7b30" dependencies = [ "async-trait", "fnv", - "futures 0.3.17", + "futures 0.3.21", "jsonrpsee-types", "log 0.4.14", - "pin-project 1.0.8", + "pin-project 1.0.10", "rustls", "rustls-native-certs", "serde", @@ -3373,7 +3361,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45a3f58dc069ec0e205a27f5b45920722a46faed802a0541538241af6228f512" dependencies = [ "parity-util-mem", - "smallvec 1.7.0", + "smallvec 1.8.0", ] [[package]] @@ -3402,7 +3390,7 @@ dependencies = [ "parking_lot 0.11.2", "regex", "rocksdb", - "smallvec 1.7.0", + "smallvec 1.8.0", ] [[package]] @@ -3425,21 +3413,21 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "leb128" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3576a87f2ba00f6f106fdfcd16db1d698d648a26ad8e0573cad8537c3c362d2a" +checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "libc" -version = "0.2.103" +version = "0.2.119" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6" +checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4" [[package]] name = "libgit2-sys" -version = "0.12.23+1.2.0" +version = "0.12.26+1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29730a445bae719db3107078b46808cc45a5b7a6bae3f31272923af969453356" +checksum = "19e1c899248e606fbfe68dcb31d8b0176ebab833b103824af31bddf4b7457494" dependencies = [ "cc", "libc", @@ -3469,9 +3457,9 @@ dependencies = [ [[package]] name = "libloading" -version = "0.7.0" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f84d96438c15fcd6c3f244c8fce01d1e2b9c6b5623e9c711dc9286d8fc92d6a" +checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd" dependencies = [ "cfg-if 1.0.0", "winapi 0.3.9", @@ -3479,9 +3467,9 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a" +checksum = "33a33a362ce288760ec6a508b94caaec573ae7d3bbbd91b87aa0bad4456839db" [[package]] name = "libp2p" @@ -3491,7 +3479,7 @@ checksum = "9004c06878ef8f3b4b4067e69a140d87ed20bf777287f82223e49713b36ee433" dependencies = [ "atomic", "bytes 1.1.0", - "futures 0.3.17", + "futures 0.3.21", "lazy_static", "libp2p-core", "libp2p-deflate", @@ -3517,8 +3505,8 @@ dependencies = [ "libp2p-yamux", "multiaddr", "parking_lot 0.11.2", - "pin-project 1.0.8", - "smallvec 1.7.0", + "pin-project 1.0.10", + "smallvec 1.8.0", "wasm-timer", ] @@ -3533,7 +3521,7 @@ dependencies = [ "ed25519-dalek", "either", "fnv", - "futures 0.3.17", + "futures 0.3.21", "futures-timer 3.0.2", "lazy_static", "libsecp256k1 0.5.0", @@ -3542,16 +3530,16 @@ dependencies = [ "multihash 0.14.0", "multistream-select", "parking_lot 0.11.2", - "pin-project 1.0.8", + "pin-project 1.0.10", "prost", "prost-build", "rand 0.7.3", "ring", "rw-stream-sink", - "sha2 0.9.8", - "smallvec 1.7.0", + "sha2 0.9.9", + "smallvec 1.8.0", "thiserror", - "unsigned-varint 0.7.0", + "unsigned-varint 0.7.1", "void", "zeroize", ] @@ -3563,7 +3551,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "66097fccc0b7f8579f90a03ea76ba6196332ea049fd07fd969490a06819dcdc8" dependencies = [ "flate2", - "futures 0.3.17", + "futures 0.3.21", "libp2p-core", ] @@ -3574,10 +3562,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "58ff08b3196b85a17f202d80589e93b1660a574af67275706657fdc762e42c32" dependencies = [ "async-std-resolver", - "futures 0.3.17", + "futures 0.3.21", "libp2p-core", "log 0.4.14", - "smallvec 1.7.0", + "smallvec 1.8.0", "trust-dns-resolver", ] @@ -3589,14 +3577,14 @@ checksum = "404eca8720967179dac7a5b4275eb91f904a53859c69ca8d018560ad6beb214f" dependencies = [ "cuckoofilter", "fnv", - "futures 0.3.17", + "futures 0.3.21", "libp2p-core", "libp2p-swarm", "log 0.4.14", "prost", "prost-build", "rand 0.7.3", - "smallvec 1.7.0", + "smallvec 1.8.0", ] [[package]] @@ -3610,7 +3598,7 @@ dependencies = [ "byteorder", "bytes 1.1.0", "fnv", - "futures 0.3.17", + "futures 0.3.21", "hex_fmt", "libp2p-core", "libp2p-swarm", @@ -3619,9 +3607,9 @@ dependencies = [ "prost-build", "rand 0.7.3", "regex", - "sha2 0.9.8", - "smallvec 1.7.0", - "unsigned-varint 0.7.0", + "sha2 0.9.9", + "smallvec 1.8.0", + "unsigned-varint 0.7.1", "wasm-timer", ] @@ -3631,13 +3619,13 @@ version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7b61f6cf07664fb97016c318c4d4512b3dd4cc07238607f3f0163245f99008e" dependencies = [ - "futures 0.3.17", + "futures 0.3.21", "libp2p-core", "libp2p-swarm", "log 0.4.14", "prost", "prost-build", - "smallvec 1.7.0", + "smallvec 1.8.0", "wasm-timer", ] @@ -3652,17 +3640,17 @@ dependencies = [ "bytes 1.1.0", "either", "fnv", - "futures 0.3.17", + "futures 0.3.21", "libp2p-core", "libp2p-swarm", "log 0.4.14", "prost", "prost-build", "rand 0.7.3", - "sha2 0.9.8", - "smallvec 1.7.0", + "sha2 0.9.9", + "smallvec 1.8.0", "uint", - "unsigned-varint 0.7.0", + "unsigned-varint 0.7.1", "void", "wasm-timer", ] @@ -3676,15 +3664,15 @@ dependencies = [ "async-io", "data-encoding", "dns-parser", - "futures 0.3.17", + "futures 0.3.21", "if-watch", "lazy_static", "libp2p-core", "libp2p-swarm", "log 0.4.14", - "rand 0.8.4", - "smallvec 1.7.0", - "socket2 0.4.2", + "rand 0.8.5", + "smallvec 1.8.0", + "socket2 0.4.4", "void", ] @@ -3696,14 +3684,14 @@ checksum = "313d9ea526c68df4425f580024e67a9d3ffd49f2c33de5154b1f5019816f7a99" dependencies = [ "asynchronous-codec 0.6.0", "bytes 1.1.0", - "futures 0.3.17", + "futures 0.3.21", "libp2p-core", "log 0.4.14", "nohash-hasher", "parking_lot 0.11.2", "rand 0.7.3", - "smallvec 1.7.0", - "unsigned-varint 0.7.0", + "smallvec 1.8.0", + "unsigned-varint 0.7.1", ] [[package]] @@ -3714,14 +3702,14 @@ checksum = "3f1db7212f342b6ba7c981cc40e31f76e9e56cb48e65fa4c142ecaca5839523e" dependencies = [ "bytes 1.1.0", "curve25519-dalek 3.2.0", - "futures 0.3.17", + "futures 0.3.21", "lazy_static", "libp2p-core", "log 0.4.14", "prost", "prost-build", - "rand 0.8.4", - "sha2 0.9.8", + "rand 0.8.5", + "sha2 0.9.9", "snow", "static_assertions", "x25519-dalek", @@ -3734,7 +3722,7 @@ version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2482cfd9eb0b7a0baaf3e7b329dc4f2785181a161b1a47b7192f8d758f54a439" dependencies = [ - "futures 0.3.17", + "futures 0.3.21", "libp2p-core", "libp2p-swarm", "log 0.4.14", @@ -3751,12 +3739,12 @@ checksum = "13b4783e5423870b9a5c199f65a7a3bc66d86ab56b2b9beebf3c338d889cf8e4" dependencies = [ "asynchronous-codec 0.6.0", "bytes 1.1.0", - "futures 0.3.17", + "futures 0.3.21", "libp2p-core", "log 0.4.14", "prost", "prost-build", - "unsigned-varint 0.7.0", + "unsigned-varint 0.7.1", "void", ] @@ -3766,9 +3754,9 @@ version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07cb4dd4b917e5b40ddefe49b96b07adcd8d342e0317011d175b7b2bb1dcc974" dependencies = [ - "futures 0.3.17", + "futures 0.3.21", "log 0.4.14", - "pin-project 1.0.8", + "pin-project 1.0.10", "rand 0.7.3", "salsa20", "sha3", @@ -3782,17 +3770,17 @@ checksum = "0133f6cfd81cdc16e716de2982e012c62e6b9d4f12e41967b3ee361051c622aa" dependencies = [ "asynchronous-codec 0.6.0", "bytes 1.1.0", - "futures 0.3.17", + "futures 0.3.21", "futures-timer 3.0.2", "libp2p-core", "libp2p-swarm", "log 0.4.14", - "pin-project 1.0.8", + "pin-project 1.0.10", "prost", "prost-build", "rand 0.7.3", - "smallvec 1.7.0", - "unsigned-varint 0.7.0", + "smallvec 1.8.0", + "unsigned-varint 0.7.1", "void", "wasm-timer", ] @@ -3805,15 +3793,15 @@ checksum = "06cdae44b6821466123af93cbcdec7c9e6ba9534a8af9cdc296446d39416d241" dependencies = [ "async-trait", "bytes 1.1.0", - "futures 0.3.17", + "futures 0.3.21", "libp2p-core", "libp2p-swarm", "log 0.4.14", "lru", "minicbor", "rand 0.7.3", - "smallvec 1.7.0", - "unsigned-varint 0.7.0", + "smallvec 1.8.0", + "unsigned-varint 0.7.1", "wasm-timer", ] @@ -3824,11 +3812,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7083861341e1555467863b4cd802bea1e8c4787c0f7b5110097d0f1f3248f9a9" dependencies = [ "either", - "futures 0.3.17", + "futures 0.3.21", "libp2p-core", "log 0.4.14", "rand 0.7.3", - "smallvec 1.7.0", + "smallvec 1.8.0", "void", "wasm-timer", ] @@ -3850,7 +3838,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79edd26b6b4bb5feee210dcda562dca186940dfecb0024b979c3f50824b3bf28" dependencies = [ "async-io", - "futures 0.3.17", + "futures 0.3.21", "futures-timer 3.0.2", "if-addrs", "if-watch", @@ -3858,7 +3846,7 @@ dependencies = [ "libc", "libp2p-core", "log 0.4.14", - "socket2 0.4.2", + "socket2 0.4.4", "tokio", ] @@ -3869,7 +3857,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "280e793440dd4e9f273d714f4497325c72cddb0fe85a49f9a03c88f41dd20182" dependencies = [ "async-std", - "futures 0.3.17", + "futures 0.3.21", "libp2p-core", "log 0.4.14", ] @@ -3880,7 +3868,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f553b7140fad3d7a76f50497b0ea591e26737d9607428a75509fc191e4d1b1f6" dependencies = [ - "futures 0.3.17", + "futures 0.3.21", "js-sys", "libp2p-core", "parity-send-wrapper", @@ -3895,7 +3883,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ddf99dcbf5063e9d59087f61b1e85c686ceab2f5abedb472d32288065c0e5e27" dependencies = [ "either", - "futures 0.3.17", + "futures 0.3.21", "futures-rustls", "libp2p-core", "log 0.4.14", @@ -3912,7 +3900,7 @@ version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "214cc0dd9c37cbed27f0bb1eba0c41bbafdb93a8be5e9d6ae1e6b4b42cd044bf" dependencies = [ - "futures 0.3.17", + "futures 0.3.21", "libp2p-core", "parking_lot 0.11.2", "thiserror", @@ -3962,7 +3950,7 @@ dependencies = [ "libsecp256k1-gen-genmult 0.2.1", "rand 0.7.3", "serde", - "sha2 0.9.8", + "sha2 0.9.9", "typenum", ] @@ -3981,7 +3969,7 @@ dependencies = [ "libsecp256k1-gen-genmult 0.2.1", "rand 0.7.3", "serde", - "sha2 0.9.8", + "sha2 0.9.9", "typenum", ] @@ -3997,9 +3985,9 @@ dependencies = [ "libsecp256k1-core 0.3.0", "libsecp256k1-gen-ecmult 0.3.0", "libsecp256k1-gen-genmult 0.3.0", - "rand 0.8.4", + "rand 0.8.5", "serde", - "sha2 0.9.8", + "sha2 0.9.9", ] [[package]] @@ -4062,9 +4050,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.3" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de5435b8549c16d423ed0c03dbaafe57cf6c3344744f1242520d59c9d8ecec66" +checksum = "6f35facd4a5673cb5a48822be2be1d4236c1c99cb4113cab7061ac720d5bf859" dependencies = [ "cc", "libc", @@ -4126,9 +4114,9 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" +checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" dependencies = [ "scopeguard", ] @@ -4172,9 +4160,9 @@ dependencies = [ [[package]] name = "lz4" -version = "1.23.2" +version = "1.23.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aac20ed6991e01bf6a2e68cc73df2b389707403662a8ba89f68511fb340f724c" +checksum = "4edcb94251b1c375c459e5abe9fb0168c1c826c3370172684844f8f3f8d1a885" dependencies = [ "libc", "lz4-sys", @@ -4182,9 +4170,9 @@ dependencies = [ [[package]] name = "lz4-sys" -version = "1.9.2" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dca79aa95d8b3226213ad454d328369853be3a1382d89532a854f4d69640acae" +checksum = "d7be8908e2ed6f31c02db8a9fa962f03e36c53fbfde437363eae3306b85d7e17" dependencies = [ "cc", "libc", @@ -4228,9 +4216,9 @@ checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" [[package]] name = "matrixmultiply" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a8a15b776d9dfaecd44b03c5828c2199cddff5247215858aac14624f8d6b741" +checksum = "add85d4dd35074e6fedc608f8c8f513a3548619a9024b751949ef0e8e45a4d84" dependencies = [ "rawpointer", ] @@ -4266,13 +4254,22 @@ dependencies = [ "libc", ] +[[package]] +name = "memmap2" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "057a3db23999c867821a7a59feb06a578fcb03685e983dff90daf9e7d24ac08f" +dependencies = [ + "libc", +] + [[package]] name = "memoffset" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", ] [[package]] @@ -4333,6 +4330,12 @@ dependencies = [ "syn", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.4.4" @@ -4340,7 +4343,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" dependencies = [ "adler", - "autocfg 1.0.1", + "autocfg 1.1.0", ] [[package]] @@ -4364,14 +4367,15 @@ dependencies = [ [[package]] name = "mio" -version = "0.7.13" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c2bdb6314ec10835cd3293dd268473a835c02b7b352e788be788b3c6ca6bb16" +checksum = "7ba42135c6a5917b9db9cd7b293e5409e1c6b041e6f9825e92e55a894c63b6f8" dependencies = [ "libc", "log 0.4.14", "miow 0.3.7", "ntapi", + "wasi 0.11.0+wasi-snapshot-preview1", "winapi 0.3.9", ] @@ -4410,9 +4414,9 @@ dependencies = [ [[package]] name = "more-asserts" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0debeb9fcf88823ea64d64e4a815ab1643f33127d995978e099942ce38f25238" +checksum = "7843ec2de400bcbc6a6328c958dc38e5359da6e93e72e37bc5246bf1ae776389" [[package]] name = "multiaddr" @@ -4428,7 +4432,7 @@ dependencies = [ "percent-encoding 2.1.0", "serde", "static_assertions", - "unsigned-varint 0.7.0", + "unsigned-varint 0.7.1", "url 2.2.2", ] @@ -4464,7 +4468,7 @@ dependencies = [ "blake2s_simd", "digest 0.9.0", "sha-1 0.9.8", - "sha2 0.9.8", + "sha2 0.9.9", "sha3", "unsigned-varint 0.5.1", ] @@ -4479,9 +4483,9 @@ dependencies = [ "blake2s_simd", "blake3", "digest 0.9.0", - "generic-array 0.14.4", + "generic-array 0.14.5", "multihash-derive", - "sha2 0.9.8", + "sha2 0.9.9", "sha3", "unsigned-varint 0.5.1", ] @@ -4493,10 +4497,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "752a61cd890ff691b4411423d23816d5866dd5621e4d1c5687a53b94b5a979d8" dependencies = [ "digest 0.9.0", - "generic-array 0.14.4", + "generic-array 0.14.5", "multihash-derive", - "sha2 0.9.8", - "unsigned-varint 0.7.0", + "sha2 0.9.9", + "unsigned-varint 0.7.1", ] [[package]] @@ -4505,8 +4509,8 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "424f6e86263cd5294cbd7f1e95746b95aca0e0d66bff31e5a40d6baa87b4aa99" dependencies = [ - "proc-macro-crate 1.1.0", - "proc-macro-error 1.0.4", + "proc-macro-crate 1.1.3", + "proc-macro-error", "proc-macro2", "quote", "syn", @@ -4521,16 +4525,16 @@ checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" [[package]] name = "multistream-select" -version = "0.10.2" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d91ec0a2440aaff5f78ec35631a7027d50386c6163aa975f7caa0d5da4b6ff8" +checksum = "56a336acba8bc87c8876f6425407dbbe6c417bf478b22015f8fb0994ef3bc0ab" dependencies = [ "bytes 1.1.0", - "futures 0.3.17", + "futures 0.3.21", "log 0.4.14", - "pin-project 1.0.8", - "smallvec 1.7.0", - "unsigned-varint 0.7.0", + "pin-project 1.0.10", + "smallvec 1.8.0", + "unsigned-varint 0.7.1", ] [[package]] @@ -4545,7 +4549,7 @@ dependencies = [ "num-complex", "num-rational 0.4.0", "num-traits", - "rand 0.8.4", + "rand 0.8.5", "rand_distr", "simba", "typenum", @@ -4568,7 +4572,7 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10a8690bf09abf659851e58cd666c3d37ac6af07c2bd7a9e332cfba471715775" dependencies = [ - "rand 0.8.4", + "rand 0.8.5", ] [[package]] @@ -4618,7 +4622,7 @@ version = "0.9.0-dev" dependencies = [ "derive_more", "fs_extra", - "futures 0.3.17", + "futures 0.3.21", "hash-db", "hex", "kvdb", @@ -4657,7 +4661,7 @@ dependencies = [ "async-std", "frame-benchmarking-cli", "frame-system", - "futures 0.3.17", + "futures 0.3.21", "hex-literal", "ipfs", "jsonrpsee-ws-client", @@ -4732,7 +4736,7 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", - "futures 0.3.17", + "futures 0.3.21", "node-primitives", "node-runtime", "node-testing", @@ -4818,7 +4822,7 @@ dependencies = [ name = "node-rpc-client" version = "2.0.0" dependencies = [ - "futures 0.3.17", + "futures 0.3.21", "jsonrpc-core-client", "node-primitives", "sc-rpc", @@ -5010,7 +5014,7 @@ version = "3.0.0-dev" dependencies = [ "frame-system", "fs_extra", - "futures 0.3.17", + "futures 0.3.21", "log 0.4.14", "node-executor", "node-primitives", @@ -5051,21 +5055,20 @@ checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" [[package]] name = "nom" -version = "6.1.2" +version = "7.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7413f999671bd4745a7b624bd370a569fb6bc574b23c83a3c5ed2e453f3d5e2" +checksum = "1b1d11e1ef389c76fe5b81bcaf2ea32cf88b62bc494e19f493d0b30e7a930109" dependencies = [ - "bitvec 0.19.5", - "funty", "memchr", - "version_check 0.9.3", + "minimal-lexical", + "version_check 0.9.4", ] [[package]] name = "ntapi" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" +checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" dependencies = [ "winapi 0.3.9", ] @@ -5076,7 +5079,7 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", "num-integer", "num-traits", ] @@ -5097,7 +5100,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bafe4179722c2894288ee77a9f044f02811c86af699344c498b0840c698a2465" dependencies = [ "arrayvec 0.4.12", - "itoa", + "itoa 0.4.8", ] [[package]] @@ -5106,7 +5109,7 @@ version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", "num-traits", ] @@ -5116,7 +5119,7 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", "num-bigint", "num-integer", "num-traits", @@ -5128,7 +5131,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d41702bd167c2df5520b384281bc111a4b5efcf7fbc4c9c222c815b07e0a6a6a" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", "num-integer", "num-traits", ] @@ -5139,15 +5142,15 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", "libm", ] [[package]] name = "num_cpus" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" dependencies = [ "hermit-abi", "libc", @@ -5174,11 +5177,20 @@ dependencies = [ "memchr", ] +[[package]] +name = "object" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" +checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" [[package]] name = "oorandom" @@ -5200,9 +5212,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl" -version = "0.10.36" +version = "0.10.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d9facdb76fec0b73c406f125d44d86fdad818d66fef0531eec9233ca425ff4a" +checksum = "0c7ae222234c30df141154f159066c5093ff73b63204dcda7121eb082fc56a95" dependencies = [ "bitflags", "cfg-if 1.0.0", @@ -5214,17 +5226,17 @@ dependencies = [ [[package]] name = "openssl-probe" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.67" +version = "0.9.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69df2d8dfc6ce3aaf44b40dec6f487d5a886516cf6879c49e98e0710f310a058" +checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", "cc", "libc", "pkg-config", @@ -5233,9 +5245,9 @@ dependencies = [ [[package]] name = "output_vt100" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9" +checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66" dependencies = [ "winapi 0.3.9", ] @@ -5498,7 +5510,7 @@ dependencies = [ "rand_pcg 0.2.1", "scale-info", "serde", - "smallvec 1.7.0", + "smallvec 1.8.0", "sp-core", "sp-io", "sp-runtime", @@ -6224,7 +6236,7 @@ dependencies = [ name = "pallet-staking-reward-curve" version = "4.0.0-dev" dependencies = [ - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "sp-runtime", @@ -6302,7 +6314,7 @@ dependencies = [ "scale-info", "serde", "serde_json", - "smallvec 1.7.0", + "smallvec 1.8.0", "sp-core", "sp-io", "sp-runtime", @@ -6424,9 +6436,9 @@ dependencies = [ [[package]] name = "parity-db" -version = "0.3.2" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91b679c6acc14fac74382942e2b73bea441686a33430b951ea03b5aeb6a7f254" +checksum = "865edee5b792f537356d9e55cbc138e7f4718dc881a7ea45a18b37bf61c21e3d" dependencies = [ "blake2-rfc", "crc32fast", @@ -6435,9 +6447,9 @@ dependencies = [ "libc", "log 0.4.14", "lz4", - "memmap2", + "memmap2 0.2.3", "parking_lot 0.11.2", - "rand 0.8.4", + "rand 0.8.5", "snap", ] @@ -6447,8 +6459,8 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "373b1a4c1338d9cd3d1fa53b3a11bdab5ab6bd80a20f7f7becd76953ae2be909" dependencies = [ - "arrayvec 0.7.1", - "bitvec 0.20.4", + "arrayvec 0.7.2", + "bitvec", "byte-slice-cast", "impl-trait-for-tuples", "parity-scale-codec-derive", @@ -6461,7 +6473,7 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1557010476e0595c9b568d16dcfb81b93cdeb157612726f5170d31aa707bed27" dependencies = [ - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn", @@ -6479,7 +6491,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9981e32fb75e004cc148f5fb70342f393830e0a4aa62e3cc93b50976218d42b6" dependencies = [ - "futures 0.3.17", + "futures 0.3.21", "libc", "log 0.4.14", "rand 0.7.3", @@ -6499,7 +6511,7 @@ dependencies = [ "parity-util-mem-derive", "parking_lot 0.11.2", "primitive-types", - "smallvec 1.7.0", + "smallvec 1.8.0", "winapi 0.3.9", ] @@ -6531,9 +6543,9 @@ checksum = "be5e13c266502aadf83426d87d81a0f5d1ef45b8027f5a471c360abfe4bfae92" [[package]] name = "parity-ws" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0ab8a461779bd022964cae2b4989fa9c99deb270bec162da2125ec03c09fcaa" +checksum = "5983d3929ad50f12c3eb9a6743f19d691866ecd44da74c0a3308c3f8a56df0c6" dependencies = [ "byteorder", "bytes 0.4.12", @@ -6581,10 +6593,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", - "lock_api 0.4.5", + "lock_api 0.4.6", "parking_lot_core 0.8.5", ] +[[package]] +name = "parking_lot" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" +dependencies = [ + "lock_api 0.4.6", + "parking_lot_core 0.9.1", +] + [[package]] name = "parking_lot_core" version = "0.6.2" @@ -6610,7 +6632,7 @@ dependencies = [ "cloudabi", "libc", "redox_syscall 0.1.57", - "smallvec 1.7.0", + "smallvec 1.8.0", "winapi 0.3.9", ] @@ -6623,11 +6645,24 @@ dependencies = [ "cfg-if 1.0.0", "instant", "libc", - "redox_syscall 0.2.10", - "smallvec 1.7.0", + "redox_syscall 0.2.11", + "smallvec 1.8.0", "winapi 0.3.9", ] +[[package]] +name = "parking_lot_core" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28141e0cc4143da2443301914478dc976a61ffdb3f043058310c70df2fed8954" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "redox_syscall 0.2.11", + "smallvec 1.8.0", + "windows-sys", +] + [[package]] name = "paste" version = "0.1.18" @@ -6640,9 +6675,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf547ad0c65e31259204bd90935776d1c693cec2f4ff7abb7a1bbbd40dfe58" +checksum = "0744126afe1a6dd7f394cb50a716dbe086cb06e255e53d8d0185d82828358fb5" [[package]] name = "paste-impl" @@ -6744,27 +6779,27 @@ dependencies = [ [[package]] name = "pin-project" -version = "0.4.28" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "918192b5c59119d51e0cd221f4d49dde9112824ba717369e903c97d076083d0f" +checksum = "9615c18d31137579e9ff063499264ddc1278e7b1982757ebc111028c4d1dc909" dependencies = [ - "pin-project-internal 0.4.28", + "pin-project-internal 0.4.29", ] [[package]] name = "pin-project" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576bc800220cc65dac09e99e97b08b358cfab6e17078de8dc5fee223bd2d0c08" +checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" dependencies = [ - "pin-project-internal 1.0.8", + "pin-project-internal 1.0.10", ] [[package]] name = "pin-project-internal" -version = "0.4.28" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be26700300be6d9d23264c73211d8190e755b6b5ca7a1b28230025511b52a5e" +checksum = "044964427019eed9d49d9d5bbce6047ef18f37100ea400912a9fa4a3523ab12a" dependencies = [ "proc-macro2", "quote", @@ -6773,9 +6808,9 @@ dependencies = [ [[package]] name = "pin-project-internal" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e8fe8163d14ce7f0cdac2e040116f22eac817edabff0be91e8aff7e9accf389" +checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" dependencies = [ "proc-macro2", "quote", @@ -6790,9 +6825,9 @@ checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" [[package]] name = "pin-project-lite" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443" +checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" [[package]] name = "pin-utils" @@ -6802,9 +6837,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.20" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c9b1041b4387893b91ee6746cddfc28516aff326a3519fb2adf820932c5e6cb" +checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" [[package]] name = "platforms" @@ -6842,9 +6877,9 @@ dependencies = [ [[package]] name = "polling" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92341d779fa34ea8437ef4d82d440d5e1ce3f3ff7f824aa64424cd481f9a1f25" +checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259" dependencies = [ "cfg-if 1.0.0", "libc", @@ -6878,15 +6913,15 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.10" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "predicates" -version = "2.0.2" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c143348f141cc87aab5b950021bac6145d0e5ae754b0591de23244cee42c9308" +checksum = "a5aab5be6e4732b473071984b3164dbbfb7a3674d30ea5ff44410b6bcd960c3c" dependencies = [ "difflib", "itertools", @@ -6895,18 +6930,18 @@ dependencies = [ [[package]] name = "predicates-core" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57e35a3326b75e49aa85f5dc6ec15b41108cf5aee58eabb1f274dd18b73c2451" +checksum = "da1c2388b1513e1b605fcec39a95e0a9e8ef088f71443ef37099fa9ae6673fcb" [[package]] name = "predicates-tree" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7dd0fd014130206c9352efbdc92be592751b2b9274dff685348341082c6ea3d" +checksum = "4d86de6de25020a36c6d3643a86d9a6a9f552107c0559c60ea03551b5e16c032" dependencies = [ "predicates-core", - "treeline", + "termtree", ] [[package]] @@ -6957,51 +6992,25 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "1.1.0" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebace6889caf889b4d3f76becee12e90353f2b8c7d875534a71e5742f8f6f83" +checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" dependencies = [ "thiserror", "toml", ] -[[package]] -name = "proc-macro-error" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18f33027081eba0a6d8aba6d1b1c3a3be58cbb12106341c2d5759fcd9b5277e7" -dependencies = [ - "proc-macro-error-attr 0.4.12", - "proc-macro2", - "quote", - "syn", - "version_check 0.9.3", -] - [[package]] name = "proc-macro-error" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ - "proc-macro-error-attr 1.0.4", + "proc-macro-error-attr", "proc-macro2", "quote", "syn", - "version_check 0.9.3", -] - -[[package]] -name = "proc-macro-error-attr" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a5b4b77fdb63c1eca72173d68d24501c54ab1269409f6b672c85deb18af69de" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "syn-mid", - "version_check 0.9.3", + "version_check 0.9.4", ] [[package]] @@ -7012,7 +7021,7 @@ checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ "proc-macro2", "quote", - "version_check 0.9.3", + "version_check 0.9.4", ] [[package]] @@ -7021,17 +7030,11 @@ version = "0.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" -[[package]] -name = "proc-macro-nested" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" - [[package]] name = "proc-macro2" -version = "1.0.29" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f5105d4fdaab20335ca9565e106a5d9b82b6219b5ba735731124ac6711d23d" +checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" dependencies = [ "unicode-xid", ] @@ -7067,7 +7070,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "355f634b43cdd80724ee7848f95770e7e70eefa6dcf14fea676216573b8fd603" dependencies = [ "bytes 1.1.0", - "heck", + "heck 0.3.3", "itertools", "log 0.4.14", "multimap", @@ -7103,9 +7106,9 @@ dependencies = [ [[package]] name = "psm" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd136ff4382c4753fc061cb9e4712ab2af263376b95bbd5bd8cd50c020b78e69" +checksum = "6eca0fa5dd7c4c96e184cec588f0b1db1ee3165e678db21c09793105acb17e6f" dependencies = [ "cc", ] @@ -7150,7 +7153,7 @@ checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6" dependencies = [ "env_logger 0.8.4", "log 0.4.14", - "rand 0.8.4", + "rand 0.8.5", ] [[package]] @@ -7166,19 +7169,13 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.9" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" dependencies = [ "proc-macro2", ] -[[package]] -name = "radium" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8" - [[package]] name = "radium" version = "0.6.2" @@ -7191,7 +7188,7 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" dependencies = [ - "autocfg 0.1.7", + "autocfg 0.1.8", "libc", "rand_chacha 0.1.1", "rand_core 0.4.2", @@ -7220,14 +7217,13 @@ dependencies = [ [[package]] name = "rand" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha 0.3.1", "rand_core 0.6.3", - "rand_hc 0.3.1", ] [[package]] @@ -7236,7 +7232,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" dependencies = [ - "autocfg 0.1.7", + "autocfg 0.1.8", "rand_core 0.3.1", ] @@ -7290,17 +7286,17 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" dependencies = [ - "getrandom 0.2.3", + "getrandom 0.2.5", ] [[package]] name = "rand_distr" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "964d548f8e7d12e102ef183a0de7e98180c9f8729f555897a857b96e48122d2f" +checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" dependencies = [ "num-traits", - "rand 0.8.4", + "rand 0.8.5", ] [[package]] @@ -7321,15 +7317,6 @@ dependencies = [ "rand_core 0.5.1", ] -[[package]] -name = "rand_hc" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" -dependencies = [ - "rand_core 0.6.3", -] - [[package]] name = "rand_isaac" version = "0.1.1" @@ -7370,7 +7357,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" dependencies = [ - "autocfg 0.1.7", + "autocfg 0.1.8", "rand_core 0.4.2", ] @@ -7404,7 +7391,7 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", "crossbeam-deque", "either", "rayon-core", @@ -7418,7 +7405,7 @@ checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e" dependencies = [ "crossbeam-channel", "crossbeam-deque", - "crossbeam-utils 0.8.5", + "crossbeam-utils 0.8.7", "lazy_static", "num_cpus", ] @@ -7440,9 +7427,9 @@ checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" [[package]] name = "redox_syscall" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +checksum = "8380fe0152551244f0747b1bf41737e0f8a74f97a14ccefd1148187271634f3c" dependencies = [ "bitflags", ] @@ -7453,8 +7440,8 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" dependencies = [ - "getrandom 0.2.3", - "redox_syscall 0.2.10", + "getrandom 0.2.5", + "redox_syscall 0.2.11", ] [[package]] @@ -7486,14 +7473,14 @@ dependencies = [ "log 0.4.14", "rustc-hash", "serde", - "smallvec 1.7.0", + "smallvec 1.8.0", ] [[package]] name = "regex" -version = "1.5.4" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" dependencies = [ "aho-corasick", "memchr", @@ -7567,9 +7554,9 @@ dependencies = [ [[package]] name = "retain_mut" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "448296241d034b96c11173591deaa1302f2c17b56092106c1f92c1bc0183a8c9" +checksum = "8c31b5c4033f8fdde8700e4657be2c497e7288f01515be52168c631e2e4d4086" [[package]] name = "ring" @@ -7648,7 +7635,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.4", + "semver 1.0.6", ] [[package]] @@ -7678,9 +7665,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61b3909d758bb75c79f23d4736fac9433868679d3ad2ea7a61e3c25cfda9a088" +checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" [[package]] name = "rw-stream-sink" @@ -7688,16 +7675,16 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4da5fcb054c46f5a5dff833b129285a93d3f0179531735e6c866e8cc307d2020" dependencies = [ - "futures 0.3.17", - "pin-project 0.4.28", + "futures 0.3.21", + "pin-project 0.4.29", "static_assertions", ] [[package]] name = "ryu" -version = "1.0.5" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" +checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" [[package]] name = "safe-mix" @@ -7748,7 +7735,7 @@ version = "0.10.0-dev" dependencies = [ "async-trait", "derive_more", - "futures 0.3.17", + "futures 0.3.21", "futures-timer 3.0.2", "ip_network", "libp2p", @@ -7775,7 +7762,7 @@ dependencies = [ name = "sc-basic-authorship" version = "0.10.0-dev" dependencies = [ - "futures 0.3.17", + "futures 0.3.21", "futures-timer 3.0.2", "log 0.4.14", "parity-scale-codec", @@ -7831,7 +7818,7 @@ dependencies = [ name = "sc-chain-spec-derive" version = "4.0.0-dev" dependencies = [ - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn", @@ -7843,7 +7830,7 @@ version = "0.10.0-dev" dependencies = [ "chrono", "fdlimit", - "futures 0.3.17", + "futures 0.3.21", "hex", "libp2p", "log 0.4.14", @@ -7880,7 +7867,7 @@ name = "sc-client-api" version = "4.0.0-dev" dependencies = [ "fnv", - "futures 0.3.17", + "futures 0.3.21", "hash-db", "log 0.4.14", "parity-scale-codec", @@ -7938,7 +7925,7 @@ name = "sc-consensus" version = "0.10.0-dev" dependencies = [ "async-trait", - "futures 0.3.17", + "futures 0.3.21", "futures-timer 3.0.2", "libp2p", "log 0.4.14", @@ -7963,8 +7950,7 @@ version = "0.10.0-dev" dependencies = [ "async-trait", "derive_more", - "futures 0.3.17", - "getrandom 0.2.3", + "futures 0.3.21", "log 0.4.14", "parity-scale-codec", "parking_lot 0.11.2", @@ -8002,7 +7988,7 @@ dependencies = [ "async-trait", "derive_more", "fork-tree", - "futures 0.3.17", + "futures 0.3.21", "log 0.4.14", "merlin", "num-bigint", @@ -8050,7 +8036,7 @@ name = "sc-consensus-babe-rpc" version = "0.10.0-dev" dependencies = [ "derive_more", - "futures 0.3.17", + "futures 0.3.21", "jsonrpc-core", "jsonrpc-core-client", "jsonrpc-derive", @@ -8093,7 +8079,7 @@ dependencies = [ "assert_matches", "async-trait", "derive_more", - "futures 0.3.17", + "futures 0.3.21", "jsonrpc-core", "jsonrpc-core-client", "jsonrpc-derive", @@ -8129,7 +8115,7 @@ version = "0.10.0-dev" dependencies = [ "async-trait", "derive_more", - "futures 0.3.17", + "futures 0.3.21", "futures-timer 3.0.2", "log 0.4.14", "parity-scale-codec", @@ -8152,7 +8138,7 @@ name = "sc-consensus-slots" version = "0.10.0-dev" dependencies = [ "async-trait", - "futures 0.3.17", + "futures 0.3.21", "futures-timer 3.0.2", "log 0.4.14", "parity-scale-codec", @@ -8193,7 +8179,7 @@ dependencies = [ "log 0.4.14", "parity-scale-codec", "parking_lot 0.11.2", - "paste 1.0.5", + "paste 1.0.6", "regex", "sc-executor-common", "sc-executor-wasmi", @@ -8284,12 +8270,12 @@ dependencies = [ "dyn-clone", "finality-grandpa", "fork-tree", - "futures 0.3.17", + "futures 0.3.21", "futures-timer 3.0.2", "log 0.4.14", "parity-scale-codec", "parking_lot 0.11.2", - "rand 0.8.4", + "rand 0.8.5", "sc-block-builder", "sc-client-api", "sc-consensus", @@ -8323,7 +8309,7 @@ version = "0.10.0-dev" dependencies = [ "derive_more", "finality-grandpa", - "futures 0.3.17", + "futures 0.3.21", "jsonrpc-core", "jsonrpc-core-client", "jsonrpc-derive", @@ -8349,7 +8335,7 @@ name = "sc-informant" version = "0.10.0-dev" dependencies = [ "ansi_term 0.12.1", - "futures 0.3.17", + "futures 0.3.21", "futures-timer 3.0.2", "log 0.4.14", "parity-util-mem", @@ -8407,7 +8393,7 @@ dependencies = [ "either", "fnv", "fork-tree", - "futures 0.3.17", + "futures 0.3.21", "futures-timer 3.0.2", "hex", "ip_network", @@ -8418,7 +8404,7 @@ dependencies = [ "lru", "parity-scale-codec", "parking_lot 0.11.2", - "pin-project 1.0.8", + "pin-project 1.0.10", "prost", "prost-build", "quickcheck", @@ -8430,7 +8416,7 @@ dependencies = [ "sc-utils", "serde", "serde_json", - "smallvec 1.7.0", + "smallvec 1.8.0", "sp-arithmetic", "sp-blockchain", "sp-consensus", @@ -8454,7 +8440,7 @@ name = "sc-network-gossip" version = "0.10.0-dev" dependencies = [ "async-std", - "futures 0.3.17", + "futures 0.3.21", "futures-timer 3.0.2", "libp2p", "log 0.4.14", @@ -8473,7 +8459,7 @@ version = "0.8.0" dependencies = [ "async-std", "async-trait", - "futures 0.3.17", + "futures 0.3.21", "futures-timer 3.0.2", "libp2p", "log 0.4.14", @@ -8501,10 +8487,10 @@ dependencies = [ "bytes 1.1.0", "cid 0.5.1", "fnv", - "futures 0.3.17", + "futures 0.3.21", "futures-timer 3.0.2", "hex", - "hyper 0.14.13", + "hyper 0.14.17", "hyper-rustls", "ipfs", "lazy_static", @@ -8535,7 +8521,7 @@ dependencies = [ name = "sc-peerset" version = "4.0.0-dev" dependencies = [ - "futures 0.3.17", + "futures 0.3.21", "libp2p", "log 0.4.14", "rand 0.7.3", @@ -8557,7 +8543,7 @@ name = "sc-rpc" version = "4.0.0-dev" dependencies = [ "assert_matches", - "futures 0.3.17", + "futures 0.3.21", "hash-db", "jsonrpc-core", "jsonrpc-pubsub", @@ -8593,7 +8579,7 @@ dependencies = [ name = "sc-rpc-api" version = "0.10.0-dev" dependencies = [ - "futures 0.3.17", + "futures 0.3.21", "jsonrpc-core", "jsonrpc-core-client", "jsonrpc-derive", @@ -8617,7 +8603,7 @@ dependencies = [ name = "sc-rpc-server" version = "4.0.0-dev" dependencies = [ - "futures 0.3.17", + "futures 0.3.21", "jsonrpc-core", "jsonrpc-http-server", "jsonrpc-ipc-server", @@ -8650,7 +8636,7 @@ dependencies = [ "async-trait", "directories", "exit-future", - "futures 0.3.17", + "futures 0.3.21", "futures-timer 3.0.2", "hash-db", "jsonrpc-core", @@ -8659,7 +8645,7 @@ dependencies = [ "parity-scale-codec", "parity-util-mem", "parking_lot 0.11.2", - "pin-project 1.0.8", + "pin-project 1.0.10", "rand 0.7.3", "sc-block-builder", "sc-chain-spec", @@ -8714,7 +8700,7 @@ name = "sc-service-test" version = "2.0.0" dependencies = [ "fdlimit", - "futures 0.3.17", + "futures 0.3.21", "hex-literal", "log 0.4.14", "parity-scale-codec", @@ -8784,11 +8770,11 @@ name = "sc-telemetry" version = "4.0.0-dev" dependencies = [ "chrono", - "futures 0.3.17", + "futures 0.3.21", "libp2p", "log 0.4.14", "parking_lot 0.11.2", - "pin-project 1.0.8", + "pin-project 1.0.10", "rand 0.7.3", "serde", "serde_json", @@ -8828,7 +8814,7 @@ dependencies = [ name = "sc-tracing-proc-macro" version = "4.0.0-dev" dependencies = [ - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn", @@ -8840,7 +8826,7 @@ version = "4.0.0-dev" dependencies = [ "assert_matches", "criterion", - "futures 0.3.17", + "futures 0.3.21", "hex", "intervalier", "linked-hash-map", @@ -8873,7 +8859,7 @@ name = "sc-transaction-pool-api" version = "4.0.0-dev" dependencies = [ "derive_more", - "futures 0.3.17", + "futures 0.3.21", "log 0.4.14", "serde", "sp-blockchain", @@ -8885,7 +8871,7 @@ dependencies = [ name = "sc-utils" version = "4.0.0-dev" dependencies = [ - "futures 0.3.17", + "futures 0.3.21", "futures-timer 3.0.2", "lazy_static", "prometheus", @@ -8897,7 +8883,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c55b744399c25532d63a0d2789b109df8d46fc93752d46b0782991a931a782f" dependencies = [ - "bitvec 0.20.4", + "bitvec", "cfg-if 1.0.0", "derive_more", "parity-scale-codec", @@ -8911,7 +8897,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baeb2780690380592f86205aa4ee49815feb2acad8c2f59e6dd207148c3f1fcd" dependencies = [ - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn", @@ -8978,9 +8964,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.4.2" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525bc1abfda2e1998d152c45cf13e696f76d0a4972310b22fac1658b05df7c87" +checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc" dependencies = [ "bitflags", "core-foundation", @@ -8991,9 +8977,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.4.2" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9dd14d83160b528b7bfd66439110573efcfbe281b17fc2ca9f39f550d619c7e" +checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" dependencies = [ "core-foundation-sys", "libc", @@ -9029,9 +9015,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.4" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012" +checksum = "a4a3381e03edd24287172047536f20cabde766e2cd3e65e6b00fb3af51c4f38d" [[package]] name = "semver-parser" @@ -9050,9 +9036,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.130" +version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" +checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" dependencies = [ "serde_derive", ] @@ -9078,9 +9064,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.130" +version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b" +checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" dependencies = [ "proc-macro2", "quote", @@ -9089,11 +9075,11 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.68" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f690853975602e1bfe1ccbf50504d67174e3bcf340f23b5ea9992e0587a52d8" +checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" dependencies = [ - "itoa", + "itoa 1.0.1", "ryu", "serde", ] @@ -9125,9 +9111,18 @@ dependencies = [ [[package]] name = "sha1" -version = "0.6.0" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770" +dependencies = [ + "sha1_smol", +] + +[[package]] +name = "sha1_smol" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" +checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" [[package]] name = "sha2" @@ -9143,9 +9138,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.9.8" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b69f9a4c9740d74c5baa3fd2e547f9525fa8088a8a958e0ca2409a514e33f5fa" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" dependencies = [ "block-buffer 0.9.0", "cfg-if 1.0.0", @@ -9168,9 +9163,9 @@ dependencies = [ [[package]] name = "sharded-slab" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "740223c51853f3145fe7c90360d2d4232f2b62e3449489c207eccde818979982" +checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" dependencies = [ "lazy_static", ] @@ -9183,9 +9178,9 @@ checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" [[package]] name = "signal-hook" -version = "0.3.10" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c98891d737e271a2954825ef19e46bd16bdb98e2746f2eec4f7a4ef7946efd1" +checksum = "647c97df271007dcea485bb74ffdb57f2e683f1306c854f468a0c244badabf2d" dependencies = [ "libc", "signal-hook-registry", @@ -9202,9 +9197,9 @@ dependencies = [ [[package]] name = "signature" -version = "1.3.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c19772be3c4dd2ceaacf03cb41d5885f2a02c4d8804884918e3a258480803335" +checksum = "f054c6c1a6e95179d6f23ed974060dcefb2d9388bb7256900badad682c499de4" [[package]] name = "simba" @@ -9215,14 +9210,14 @@ dependencies = [ "approx", "num-complex", "num-traits", - "paste 1.0.5", + "paste 1.0.6", ] [[package]] name = "slab" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c307a32c1c5c437f38c7fd45d753050587732ba8628319fbdf12a7e289ccc590" +checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" [[package]] name = "sled" @@ -9232,7 +9227,7 @@ checksum = "7f96b4737c2ce5987354855aed3797279def4ebf734436c6aa4552cf8e169935" dependencies = [ "crc32fast", "crossbeam-epoch", - "crossbeam-utils 0.8.5", + "crossbeam-utils 0.8.7", "fs2", "fxhash", "libc", @@ -9260,9 +9255,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" [[package]] name = "snap" @@ -9279,11 +9274,11 @@ dependencies = [ "aes-gcm", "blake2", "chacha20poly1305", - "rand 0.8.4", + "rand 0.8.5", "rand_core 0.6.3", "ring", "rustc_version 0.3.3", - "sha2 0.9.8", + "sha2 0.9.9", "subtle 2.4.1", "x25519-dalek", ] @@ -9301,9 +9296,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.4.2" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516" +checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" dependencies = [ "libc", "winapi 0.3.9", @@ -9318,7 +9313,7 @@ dependencies = [ "base64 0.12.3", "bytes 0.5.6", "flate2", - "futures 0.3.17", + "futures 0.3.21", "httparse", "log 0.4.14", "rand 0.7.3", @@ -9333,10 +9328,10 @@ checksum = "a74e48087dbeed4833785c2f3352b59140095dc192dce966a3bfc155020a439f" dependencies = [ "base64 0.13.0", "bytes 1.1.0", - "futures 0.3.17", + "futures 0.3.21", "httparse", "log 0.4.14", - "rand 0.8.4", + "rand 0.8.5", "sha-1 0.9.8", ] @@ -9362,7 +9357,7 @@ name = "sp-api-proc-macro" version = "4.0.0-dev" dependencies = [ "blake2-rfc", - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn", @@ -9373,7 +9368,7 @@ name = "sp-api-test" version = "2.0.1" dependencies = [ "criterion", - "futures 0.3.17", + "futures 0.3.21", "log 0.4.14", "parity-scale-codec", "rustversion", @@ -9478,7 +9473,7 @@ dependencies = [ name = "sp-blockchain" version = "4.0.0-dev" dependencies = [ - "futures 0.3.17", + "futures 0.3.21", "log 0.4.14", "lru", "parity-scale-codec", @@ -9496,7 +9491,7 @@ name = "sp-consensus" version = "0.10.0-dev" dependencies = [ "async-trait", - "futures 0.3.17", + "futures 0.3.21", "futures-timer 3.0.2", "log 0.4.14", "parity-scale-codec", @@ -9591,7 +9586,7 @@ dependencies = [ "criterion", "dyn-clonable", "ed25519-dalek", - "futures 0.3.17", + "futures 0.3.21", "hash-db", "hash256-std-hasher", "hex", @@ -9613,7 +9608,7 @@ dependencies = [ "secrecy", "serde", "serde_json", - "sha2 0.9.8", + "sha2 0.9.9", "sp-debug-derive", "sp-externalities", "sp-runtime-interface", @@ -9678,7 +9673,7 @@ name = "sp-inherents" version = "4.0.0-dev" dependencies = [ "async-trait", - "futures 0.3.17", + "futures 0.3.21", "impl-trait-for-tuples", "parity-scale-codec", "sp-core", @@ -9691,7 +9686,7 @@ dependencies = [ name = "sp-io" version = "4.0.0-dev" dependencies = [ - "futures 0.3.17", + "futures 0.3.21", "hash-db", "libsecp256k1 0.6.0", "log 0.4.14", @@ -9726,7 +9721,7 @@ version = "0.10.0-dev" dependencies = [ "async-trait", "derive_more", - "futures 0.3.17", + "futures 0.3.21", "merlin", "parity-scale-codec", "parking_lot 0.11.2", @@ -9779,7 +9774,7 @@ name = "sp-npos-elections-solution-type" version = "4.0.0-dev" dependencies = [ "parity-scale-codec", - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "scale-info", @@ -9825,7 +9820,7 @@ dependencies = [ "log 0.4.14", "parity-scale-codec", "parity-util-mem", - "paste 1.0.5", + "paste 1.0.6", "rand 0.7.3", "scale-info", "serde", @@ -9868,7 +9863,7 @@ name = "sp-runtime-interface-proc-macro" version = "4.0.0-dev" dependencies = [ "Inflector", - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn", @@ -9970,7 +9965,7 @@ dependencies = [ "parking_lot 0.11.2", "pretty_assertions 0.6.1", "rand 0.7.3", - "smallvec 1.7.0", + "smallvec 1.8.0", "sp-core", "sp-externalities", "sp-panic-handler", @@ -10162,7 +10157,7 @@ dependencies = [ "lazy_static", "nalgebra", "num-traits", - "rand 0.8.4", + "rand 0.8.5", ] [[package]] @@ -10179,9 +10174,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "structopt" -version = "0.3.23" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf9d950ef167e25e0bdb073cf1d68e9ad2795ac826f2f3f59647817cf23c0bfa" +checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10" dependencies = [ "clap", "lazy_static", @@ -10190,12 +10185,12 @@ dependencies = [ [[package]] name = "structopt-derive" -version = "0.4.16" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134d838a2c9943ac3125cf6df165eda53493451b719f3255b2a26b85f772d0ba" +checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" dependencies = [ - "heck", - "proc-macro-error 1.0.4", + "heck 0.3.3", + "proc-macro-error", "proc-macro2", "quote", "syn", @@ -10225,7 +10220,7 @@ version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee8bc6b87a5112aeeab1f4a9f7ab634fe6cbefc4850006df31267f4cfb9e3149" dependencies = [ - "heck", + "heck 0.3.3", "proc-macro2", "quote", "syn", @@ -10237,7 +10232,7 @@ version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d06aaeeee809dbc59eb4556183dd927df67db1540de5be8d3ec0b6636358a5ec" dependencies = [ - "heck", + "heck 0.3.3", "proc-macro2", "quote", "syn", @@ -10260,7 +10255,7 @@ dependencies = [ "hmac 0.11.0", "pbkdf2 0.8.0", "schnorrkel", - "sha2 0.9.8", + "sha2 0.9.9", "zeroize", ] @@ -10289,7 +10284,7 @@ version = "3.0.0" dependencies = [ "frame-support", "frame-system", - "futures 0.3.17", + "futures 0.3.21", "jsonrpc-client-transports", "parity-scale-codec", "sc-rpc-api", @@ -10304,7 +10299,7 @@ name = "substrate-frame-rpc-system" version = "4.0.0-dev" dependencies = [ "frame-system-rpc-runtime-api", - "futures 0.3.17", + "futures 0.3.21", "jsonrpc-core", "jsonrpc-core-client", "jsonrpc-derive", @@ -10330,7 +10325,7 @@ dependencies = [ "async-std", "derive_more", "futures-util", - "hyper 0.14.13", + "hyper 0.14.17", "log 0.4.14", "prometheus", "tokio", @@ -10341,7 +10336,7 @@ name = "substrate-test-client" version = "2.0.1" dependencies = [ "async-trait", - "futures 0.3.17", + "futures 0.3.21", "hex", "parity-scale-codec", "sc-client-api", @@ -10370,7 +10365,7 @@ dependencies = [ "frame-support", "frame-system", "frame-system-rpc-runtime-api", - "futures 0.3.17", + "futures 0.3.21", "log 0.4.14", "memory-db", "pallet-babe", @@ -10412,7 +10407,7 @@ dependencies = [ name = "substrate-test-runtime-client" version = "2.0.0" dependencies = [ - "futures 0.3.17", + "futures 0.3.21", "parity-scale-codec", "sc-block-builder", "sc-client-api", @@ -10432,7 +10427,7 @@ name = "substrate-test-runtime-transaction-pool" version = "2.0.0" dependencies = [ "derive_more", - "futures 0.3.17", + "futures 0.3.21", "parity-scale-codec", "parking_lot 0.11.2", "sc-transaction-pool", @@ -10446,7 +10441,7 @@ dependencies = [ name = "substrate-test-utils" version = "4.0.0-dev" dependencies = [ - "futures 0.3.17", + "futures 0.3.21", "sc-service", "substrate-test-utils-derive", "tokio", @@ -10457,7 +10452,7 @@ dependencies = [ name = "substrate-test-utils-derive" version = "0.10.0-dev" dependencies = [ - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn", @@ -10500,31 +10495,20 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "syn" -version = "1.0.77" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5239bc68e0fef57495900cfea4e8dc75596d9a319d7e16b1e0a440d24e6fe0a0" +checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" dependencies = [ "proc-macro2", "quote", "unicode-xid", ] -[[package]] -name = "syn-mid" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baa8e7560a164edb1621a55d18a0c59abf49d360f47aa7b821061dd7eea7fac9" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "synstructure" -version = "0.12.5" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "474aaa926faa1603c40b7885a9eaea29b444d1cb2850cb7c0e37bb1a4182f4fa" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ "proc-macro2", "quote", @@ -10546,39 +10530,45 @@ checksum = "422045212ea98508ae3d28025bc5aaa2bd4a9cdaecd442a08da2ee620ee9ea95" [[package]] name = "target-lexicon" -version = "0.12.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9bffcddbc2458fa3e6058414599e3c838a022abae82e5c67b4f7f80298d5bff" +checksum = "d7fa7e55043acb85fca6b3c01485a2eeb6b69c5d21002e273c79e465f43b7ac1" [[package]] name = "tempfile" -version = "3.2.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" dependencies = [ "cfg-if 1.0.0", + "fastrand", "libc", - "rand 0.8.4", - "redox_syscall 0.2.10", + "redox_syscall 0.2.11", "remove_dir_all", "winapi 0.3.9", ] [[package]] name = "termcolor" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" dependencies = [ "winapi-util", ] +[[package]] +name = "termtree" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507e9898683b6c43a9aa55b64259b721b52ba226e0f3779137e50ad114a4c90b" + [[package]] name = "test-runner" version = "0.9.0" dependencies = [ "frame-system", - "futures 0.3.17", + "futures 0.3.21", "jsonrpc-core", "log 0.4.14", "num-traits", @@ -10650,18 +10640,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.29" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "602eca064b2d83369e2b2f34b09c70b605402801927c65c11071ac911d299b88" +checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.29" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bad553cc2c78e8de258400763a647e80e6d1b31ee237275d756f6836d204494c" +checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" dependencies = [ "proc-macro2", "quote", @@ -10670,9 +10660,9 @@ dependencies = [ [[package]] name = "thread_local" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd" +checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" dependencies = [ "once_cell", ] @@ -10709,7 +10699,7 @@ dependencies = [ "pbkdf2 0.4.0", "rand 0.7.3", "rustc-hash", - "sha2 0.9.8", + "sha2 0.9.9", "thiserror", "unicode-normalization", "wasm-bindgen", @@ -10737,9 +10727,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83b2a3d4d9091d0abd7eba4dc2710b1718583bd4d8992e2190720ea38f391f7" +checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" dependencies = [ "tinyvec_macros", ] @@ -10752,20 +10742,20 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.12.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2c2416fdedca8443ae44b4527de1ea633af61d8f7169ffa6e72c5b53d24efcc" +checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee" dependencies = [ - "autocfg 1.0.1", "bytes 1.1.0", "libc", "memchr", - "mio 0.7.13", + "mio 0.8.1", "num_cpus", "once_cell", - "parking_lot 0.11.2", - "pin-project-lite 0.2.7", + "parking_lot 0.12.0", + "pin-project-lite 0.2.8", "signal-hook-registry", + "socket2 0.4.4", "tokio-macros", "winapi 0.3.9", ] @@ -10804,9 +10794,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "1.3.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54473be61f4ebe4efd09cec9bd5d16fa51d70ea0192213d754d2d500457db110" +checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" dependencies = [ "proc-macro2", "quote", @@ -10855,12 +10845,12 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b2f3f698253f03119ac0102beaa64f67a67e08074d03a22d18784104543727f" +checksum = "50145484efff8818b5ccd256697f36863f587da82cf8b409c53adf1e840798e3" dependencies = [ "futures-core", - "pin-project-lite 0.2.7", + "pin-project-lite 0.2.8", "tokio", ] @@ -10901,16 +10891,16 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d3725d3efa29485e87311c5b699de63cde14b00ed4d256b8318aa30ca452cd" +checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0" dependencies = [ "bytes 1.1.0", "futures-core", "futures-io", "futures-sink", "log 0.4.14", - "pin-project-lite 0.2.7", + "pin-project-lite 0.2.8", "tokio", ] @@ -10931,22 +10921,22 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" [[package]] name = "tracing" -version = "0.1.28" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84f96e095c0c82419687c20ddf5cb3eadb61f4e1405923c9dc8e53a1adacbda8" +checksum = "4a1bdf54a7c28a2bbf701e1d2233f6c77f473486b94bee4f9678da5a148dca7f" dependencies = [ "cfg-if 1.0.0", "log 0.4.14", - "pin-project-lite 0.2.7", + "pin-project-lite 0.2.8", "tracing-attributes", "tracing-core", ] [[package]] name = "tracing-attributes" -version = "0.1.16" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98863d0dd09fa59a1b79c6750ad80dbda6b75f4e71c437a6a1a8cb91a8bcbd77" +checksum = "2e65ce065b4b5c53e73bb28912318cb8c9e9ad3921f1d669eb0e68b4c8143a2b" dependencies = [ "proc-macro2", "quote", @@ -10955,11 +10945,12 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.20" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46125608c26121c81b0c6d693eab5a420e416da7e43c426d2e8f7df8da8a3acf" +checksum = "aa31669fa42c09c34d94d8165dd2012e8ff3c66aca50f3bb226b68f216f2706c" dependencies = [ "lazy_static", + "valuable", ] [[package]] @@ -10968,9 +10959,9 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" dependencies = [ - "futures 0.3.17", + "futures 0.3.21", "futures-task", - "pin-project 1.0.8", + "pin-project 1.0.10", "tracing", ] @@ -10987,9 +10978,9 @@ dependencies = [ [[package]] name = "tracing-serde" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb65ea441fbb84f9f6748fd496cf7f63ec9af5bca94dd86456978d055e8eb28b" +checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1" dependencies = [ "serde", "tracing-core", @@ -10997,9 +10988,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.2.24" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdd0568dbfe3baf7048b7908d2b32bca0d81cd56bec6d2a8f894b01d74f86be3" +checksum = "0e0d2eaa99c3c2e41547cfa109e910a68ea03823cccad4a0525dcbc9b01e8c71" dependencies = [ "ansi_term 0.12.1", "chrono", @@ -11009,7 +11000,7 @@ dependencies = [ "serde", "serde_json", "sharded-slab", - "smallvec 1.7.0", + "smallvec 1.8.0", "thread_local", "tracing", "tracing-core", @@ -11023,12 +11014,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" -[[package]] -name = "treeline" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7f741b240f1a48843f9b8e0444fb55fb2a4ff67293b50a9179dfd5ea67f8d41" - [[package]] name = "trie-bench" version = "0.28.0" @@ -11055,7 +11040,7 @@ dependencies = [ "hashbrown", "log 0.4.14", "rustc-hex", - "smallvec 1.7.0", + "smallvec 1.8.0", ] [[package]] @@ -11079,9 +11064,9 @@ dependencies = [ [[package]] name = "trust-dns-proto" -version = "0.20.3" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0d7f5db438199a6e2609debe3f69f808d074e0a2888ee0bccb45fe234d03f4" +checksum = "ca94d4e9feb6a181c690c4040d7a24ef34018d8313ac5044a61d21222ae24e31" dependencies = [ "async-trait", "cfg-if 1.0.0", @@ -11094,8 +11079,8 @@ dependencies = [ "ipnet", "lazy_static", "log 0.4.14", - "rand 0.8.4", - "smallvec 1.7.0", + "rand 0.8.5", + "smallvec 1.8.0", "thiserror", "tinyvec", "tokio", @@ -11104,9 +11089,9 @@ dependencies = [ [[package]] name = "trust-dns-resolver" -version = "0.20.3" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ad17b608a64bd0735e67bde16b0636f8aa8591f831a25d18443ed00a699770" +checksum = "ecae383baad9995efaa34ce8e57d12c3f305e545887472a492b838f4b5cfb77a" dependencies = [ "cfg-if 1.0.0", "futures-util", @@ -11116,7 +11101,7 @@ dependencies = [ "lru-cache", "parking_lot 0.11.2", "resolv-conf", - "smallvec 1.7.0", + "smallvec 1.8.0", "thiserror", "tokio", "trust-dns-proto", @@ -11153,13 +11138,13 @@ dependencies = [ [[package]] name = "trybuild" -version = "1.0.45" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bdaf2a1d317f3d58b44b31c7f6436b9b9acafe7bddfeace50897c2b804d7792" +checksum = "2d60539445867cdd9680b2bfe2d0428f1814b7d5c9652f09d8d3eae9d19308db" dependencies = [ "dissimilar", "glob", - "lazy_static", + "once_cell", "serde", "serde_json", "termcolor", @@ -11168,12 +11153,12 @@ dependencies = [ [[package]] name = "twox-hash" -version = "1.6.1" +version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f559b464de2e2bdabcac6a210d12e9b5a5973c251e102c44c585c71d51bd78e" +checksum = "4ee73e6e4924fe940354b8d4d98cad5231175d615cd855b758adc658c0aac6a0" dependencies = [ "cfg-if 1.0.0", - "rand 0.8.4", + "rand 0.8.5", "static_assertions", ] @@ -11185,9 +11170,9 @@ checksum = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" [[package]] name = "typenum" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" [[package]] name = "ucd-trie" @@ -11197,9 +11182,9 @@ checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" [[package]] name = "uint" -version = "0.9.1" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6470ab50f482bde894a037a57064480a246dbfdd5960bd65a44824693f08da5f" +checksum = "12f03af7ccf01dd611cc450a0d10dbc9b745770d096473e2faf0ca6e2d66d1e0" dependencies = [ "byteorder", "crunchy", @@ -11222,14 +11207,14 @@ version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" dependencies = [ - "version_check 0.9.3", + "version_check 0.9.4", ] [[package]] name = "unicode-bidi" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "246f4c42e67e7a4e3c6106ff716a5d067d4132a642840b242e357e468a2a0085" +checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" [[package]] name = "unicode-normalization" @@ -11242,9 +11227,9 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" +checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" [[package]] name = "unicode-width" @@ -11264,7 +11249,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" dependencies = [ - "generic-array 0.14.4", + "generic-array 0.14.5", "subtle 2.4.1", ] @@ -11294,9 +11279,9 @@ dependencies = [ [[package]] name = "unsigned-varint" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f8d425fafb8cd76bc3f22aace4af471d3156301d7508f2107e98fbeae10bc7f" +checksum = "d86a8dc7f45e4c1b0d30e43038c38f274e77af056aa5f74b93c2cf9eb3c1c836" dependencies = [ "asynchronous-codec 0.6.0", "bytes 1.1.0", @@ -11333,14 +11318,20 @@ dependencies = [ "percent-encoding 2.1.0", ] +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + [[package]] name = "value-bag" -version = "1.0.0-alpha.7" +version = "1.0.0-alpha.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd320e1520f94261153e96f7534476ad869c14022aee1e59af7c778075d840ae" +checksum = "79923f7731dc61ebfba3633098bf3ac533bbd35ccd8c57e7088d9a5eebe0263f" dependencies = [ "ctor", - "version_check 0.9.3", + "version_check 0.9.4", ] [[package]] @@ -11363,9 +11354,9 @@ checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" [[package]] name = "version_check" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "void" @@ -11421,11 +11412,17 @@ version = "0.10.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + [[package]] name = "wasm-bindgen" -version = "0.2.78" +version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce" +checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -11433,9 +11430,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.78" +version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b" +checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca" dependencies = [ "bumpalo", "lazy_static", @@ -11448,9 +11445,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.28" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e8d7523cb1f2a4c96c1317ca690031b714a51cc14e05f712446691f413f5d39" +checksum = "2eb6ec270a31b1d3c7e266b999739109abce8b6c87e4b31fcfcd788b65267395" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -11460,9 +11457,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.78" +version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9" +checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -11470,9 +11467,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.78" +version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab" +checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc" dependencies = [ "proc-macro2", "quote", @@ -11483,9 +11480,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.78" +version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc" +checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2" [[package]] name = "wasm-gc-api" @@ -11504,7 +11501,7 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f" dependencies = [ - "futures 0.3.17", + "futures 0.3.21", "js-sys", "parking_lot 0.11.2", "pin-utils", @@ -11545,7 +11542,7 @@ dependencies = [ "enumset", "serde", "serde_bytes", - "smallvec 1.7.0", + "smallvec 1.8.0", "target-lexicon 0.11.2", "thiserror", "wasmer-types", @@ -11565,7 +11562,7 @@ dependencies = [ "more-asserts", "rayon", "serde", - "smallvec 1.7.0", + "smallvec 1.8.0", "tracing", "wasmer-compiler", "wasmer-types", @@ -11585,7 +11582,7 @@ dependencies = [ "more-asserts", "rayon", "serde", - "smallvec 1.7.0", + "smallvec 1.8.0", "wasmer-compiler", "wasmer-types", "wasmer-vm", @@ -11597,7 +11594,7 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8b86dcd2c3efdb8390728a2b56f762db07789aaa5aa872a9dc776ba3a7912ed" dependencies = [ - "proc-macro-error 1.0.4", + "proc-macro-error", "proc-macro2", "quote", "syn", @@ -11612,7 +11609,7 @@ dependencies = [ "backtrace", "bincode", "lazy_static", - "memmap2", + "memmap2 0.2.3", "more-asserts", "rustc-demangle", "serde", @@ -11759,13 +11756,13 @@ dependencies = [ "lazy_static", "libc", "log 0.4.14", - "paste 1.0.5", + "paste 1.0.6", "psm", "region", "rustc-demangle", "serde", - "smallvec 1.7.0", - "target-lexicon 0.12.2", + "smallvec 1.8.0", + "target-lexicon 0.12.3", "wasmparser 0.79.0", "wasmtime-cache", "wasmtime-environ", @@ -11790,7 +11787,7 @@ dependencies = [ "libc", "log 0.4.14", "serde", - "sha2 0.9.8", + "sha2 0.9.9", "toml", "winapi 0.3.9", "zstd", @@ -11806,7 +11803,7 @@ dependencies = [ "cranelift-entity 0.76.0", "cranelift-frontend 0.76.0", "cranelift-wasm", - "target-lexicon 0.12.2", + "target-lexicon 0.12.3", "wasmparser 0.79.0", "wasmtime-environ", ] @@ -11821,7 +11818,7 @@ dependencies = [ "gimli 0.25.0", "more-asserts", "object 0.26.2", - "target-lexicon 0.12.2", + "target-lexicon 0.12.3", "thiserror", "wasmparser 0.79.0", "wasmtime-environ", @@ -11852,7 +11849,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0bf1dfb213a35d8f21aefae40e597fe72778a907011ffdff7affb029a02af9a" dependencies = [ - "addr2line", + "addr2line 0.16.0", "anyhow", "cfg-if 1.0.0", "cranelift-codegen 0.76.0", @@ -11867,7 +11864,7 @@ dependencies = [ "rayon", "region", "serde", - "target-lexicon 0.12.2", + "target-lexicon 0.12.3", "thiserror", "wasmparser 0.79.0", "wasmtime-cranelift", @@ -11888,7 +11885,7 @@ dependencies = [ "anyhow", "more-asserts", "object 0.26.2", - "target-lexicon 0.12.2", + "target-lexicon 0.12.3", "wasmtime-debug", "wasmtime-environ", ] @@ -11904,7 +11901,7 @@ dependencies = [ "lazy_static", "libc", "serde", - "target-lexicon 0.12.2", + "target-lexicon 0.12.3", "wasmtime-environ", "wasmtime-runtime", ] @@ -11926,7 +11923,7 @@ dependencies = [ "mach", "memoffset", "more-asserts", - "rand 0.8.4", + "rand 0.8.5", "region", "thiserror", "wasmtime-environ", @@ -11935,27 +11932,29 @@ dependencies = [ [[package]] name = "wast" -version = "38.0.0" +version = "39.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ebc29df4629f497e0893aacd40f13a4a56b85ef6eb4ab6d603f07244f1a7bf2" +checksum = "e9bbbd53432b267421186feee3e52436531fa69a7cfee9403f5204352df3dd05" dependencies = [ "leb128", + "memchr", + "unicode-width", ] [[package]] name = "wat" -version = "1.0.40" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adcfaeb27e2578d2c6271a45609f4a055e6d7ba3a12eff35b1fd5ba147bdf046" +checksum = "ab98ed25494f97c69f28758617f27c3e92e5336040b5c3a14634f2dd3fe61830" dependencies = [ "wast", ] [[package]] name = "web-sys" -version = "0.3.55" +version = "0.3.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb" +checksum = "c060b319f29dd25724f09a2ba1418f142f539b2be99fbf4d2d5a8f7330afb8eb" dependencies = [ "js-sys", "wasm-bindgen", @@ -12032,9 +12031,9 @@ dependencies = [ [[package]] name = "which" -version = "4.2.2" +version = "4.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea187a8ef279bc014ec368c27a920da2024d2a711109bfbe3440585d5cf27ad9" +checksum = "2a5a7e487e921cf220206864a94a89b6c6905bfc19f1057fa26a4cb360e5c1d2" dependencies = [ "either", "lazy_static", @@ -12090,6 +12089,49 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3df6e476185f92a12c072be4a189a0210dcdcf512a1891d6dff9edb874deadc6" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5" + +[[package]] +name = "windows_i686_gnu" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615" + +[[package]] +name = "windows_i686_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316" + [[package]] name = "winreg" version = "0.6.2" @@ -12132,28 +12174,28 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7d9028f208dd5e63c614be69f115c1b53cacc1111437d4c765185856666c107" dependencies = [ - "futures 0.3.17", + "futures 0.3.21", "log 0.4.14", "nohash-hasher", "parking_lot 0.11.2", - "rand 0.8.4", + "rand 0.8.5", "static_assertions", ] [[package]] name = "zeroize" -version = "1.4.2" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf68b08513768deaa790264a7fac27a58cbf2705cfcdc9448362229217d7e970" +checksum = "50344758e2f40e3a1fcfc8f6f91aa57b5f8ebd8d27919fe6451f15aaaf9ee608" dependencies = [ "zeroize_derive", ] [[package]] name = "zeroize_derive" -version = "1.2.0" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdff2024a851a322b08f179173ae2ba620445aef1e838f0c196820eade4ae0c7" +checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17" dependencies = [ "proc-macro2", "quote", @@ -12163,18 +12205,18 @@ dependencies = [ [[package]] name = "zstd" -version = "0.9.0+zstd.1.5.0" +version = "0.9.2+zstd.1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07749a5dc2cb6b36661290245e350f15ec3bbb304e493db54a1d354480522ccd" +checksum = "2390ea1bf6c038c39674f22d95f0564725fc06034a47129179810b2fc58caa54" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" -version = "4.1.1+zstd.1.5.0" +version = "4.1.3+zstd.1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c91c90f2c593b003603e5e0493c837088df4469da25aafff8bce42ba48caf079" +checksum = "e99d81b99fb3c2c2c794e3fe56c305c63d5173a16a46b5850b07c935ffc7db79" dependencies = [ "libc", "zstd-sys", @@ -12182,9 +12224,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "1.6.1+zstd.1.5.0" +version = "1.6.2+zstd.1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "615120c7a2431d16cf1cf979e7fc31ba7a5b5e5707b29c8a99e5dbf8a8392a33" +checksum = "2daf2f248d9ea44454bfcb2516534e8b8ad2fc91bf818a1885495fc42bc8ac9f" dependencies = [ "cc", "libc", diff --git a/bin/node-template/pallets/iris-assets/src/lib.rs b/bin/node-template/pallets/iris-assets/src/lib.rs index a46e70b0a5fc..f33d0ce20129 100644 --- a/bin/node-template/pallets/iris-assets/src/lib.rs +++ b/bin/node-template/pallets/iris-assets/src/lib.rs @@ -254,7 +254,6 @@ pub mod pallet { #[pallet::compact] amount: T::Balance, ) -> DispatchResult { let who = ensure_signed(origin)?; - // ensure!(AssetClassOwnership::::contains_key(asset_id.clone()), Error::::NoSuchOwnedContent); let new_origin = system::RawOrigin::Signed(who.clone()).into(); let beneficiary_accountid = T::Lookup::lookup(beneficiary.clone())?; diff --git a/bin/node-template/pallets/iris-ledger/src/lib.rs b/bin/node-template/pallets/iris-ledger/src/lib.rs index 5901b9831dc3..cf44c1b26b6e 100644 --- a/bin/node-template/pallets/iris-ledger/src/lib.rs +++ b/bin/node-template/pallets/iris-ledger/src/lib.rs @@ -124,7 +124,6 @@ pub mod pallet { #[pallet::compact] amount: BalanceOf, ) -> DispatchResult { let who = ensure_signed(origin)?; - // let lock_id: LockIdentifier = cid; T::IrisCurrency::set_lock( IRIS_LOCK_ID, &who, @@ -146,17 +145,17 @@ pub mod pallet { target: T::AccountId, ) -> DispatchResult { let who = ensure_signed(origin)?; + // let new_origin: OriginFor = system::RawOrigin::Signed(who.clone()).into(); // assume ammount in ledger matches locked amount for now...... let amount = >::get(who.clone(), IRIS_LOCK_ID); + T::IrisCurrency::remove_lock(IRIS_LOCK_ID, &who); - - // let new_origin = system::RawOrigin::Signed(who.clone()).into(); - // T::IrisCurrency::transfer( - // new_origin, - // &target, - // amount, - // KeepAlive, - // )?; + T::IrisCurrency::transfer( + &who, + &target, + amount, + KeepAlive, + )?; >::remove(who.clone(), IRIS_LOCK_ID); Self::deposit_event(Event::Unlocked(who)); diff --git a/bin/node-template/pallets/iris-ledger/src/mock.rs b/bin/node-template/pallets/iris-ledger/src/mock.rs index 194c86cbc067..4e0743440e13 100644 --- a/bin/node-template/pallets/iris-ledger/src/mock.rs +++ b/bin/node-template/pallets/iris-ledger/src/mock.rs @@ -1,135 +1,110 @@ -// #![cfg(test)] -// use crate::{self as pallet_iris_assets, Config}; -// use frame_support::{construct_runtime, parameter_types}; -// use sp_core::{ -// Pair, -// H256, -// sr25519::{ -// Signature, -// }, -// }; -// use sp_runtime::{ -// testing::{Header, TestXt}, -// traits::{BlakeTwo256, Extrinsic as ExtrinsicT, IdentityLookup, IdentifyAccount, Verify}, -// }; +#![cfg(test)] +use crate::{self as pallet_iris_assets, Config}; +use frame_support::{construct_runtime, parameter_types}; +use sp_core::{ + Pair, + H256, + sr25519::{ + Signature, + }, +}; +use sp_runtime::{ + testing::{Header, TestXt}, + traits::{BlakeTwo256, Extrinsic as ExtrinsicT, IdentityLookup, IdentifyAccount, Verify}, +}; -// type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; -// type Block = frame_system::mocking::MockBlock; +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlock; -// // Configure a mock runtime to test the pallet. -// construct_runtime!( -// pub enum Test where -// Block = Block, -// NodeBlock = Block, -// UncheckedExtrinsic = UncheckedExtrinsic, -// { -// System: frame_system::{Pallet, Call, Config, Storage, Event}, -// Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, -// Assets: pallet_assets::{Pallet, Storage, Event}, -// Iris: pallet_iris_assets::{Pallet, Call, Storage, Event}, -// } -// ); +// Configure a mock runtime to test the pallet. +construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + IrisLedger: pallet_iris_ledger::{Pallet, Call, Storage, Event}, + } +); -// parameter_types! { -// pub const BlockHashCount: u64 = 250; -// pub const SS58Prefix: u8 = 42; -// } +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const SS58Prefix: u8 = 42; +} -// impl frame_system::Config for Test { -// type BaseCallFilter = frame_support::traits::Everything; -// type BlockWeights = (); -// type BlockLength = (); -// type DbWeight = (); -// type Origin = Origin; -// type Call = Call; -// type Index = u64; -// type BlockNumber = u64; -// type Hash = H256; -// type Hashing = BlakeTwo256; -// type AccountId = sp_core::sr25519::Public; -// type Lookup = IdentityLookup; -// type Header = Header; -// type Event = Event; -// type BlockHashCount = BlockHashCount; -// type Version = (); -// type PalletInfo = PalletInfo; -// type AccountData = pallet_balances::AccountData; -// type OnNewAccount = (); -// type OnKilledAccount = (); -// type SystemWeightInfo = (); -// type SS58Prefix = (); -// type OnSetCode = (); -// } +impl frame_system::Config for Test { + type BaseCallFilter = frame_support::traits::Everything; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type Origin = Origin; + type Call = Call; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = sp_core::sr25519::Public; + type Lookup = IdentityLookup; + type Header = Header; + type Event = Event; + type BlockHashCount = BlockHashCount; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); +} -// // SS58Prefix -// parameter_types! { -// pub const ExistentialDeposit: u64 = 1; -// } +// SS58Prefix +parameter_types! { + pub const ExistentialDeposit: u64 = 1; +} -// impl pallet_balances::Config for Test { -// type MaxLocks = (); -// type MaxReserves = (); -// type ReserveIdentifier = [u8; 8]; -// type Balance = u64; -// type DustRemoval = (); -// type Event = Event; -// type ExistentialDeposit = ExistentialDeposit; -// type AccountStore = System; -// type WeightInfo = (); -// } +impl pallet_balances::Config for Test { + type MaxLocks = (); + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; + type Balance = u64; + type DustRemoval = (); + type Event = Event; + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); +} -// parameter_types! { -// pub const AssetDeposit: u64 = 1; -// pub const ApprovalDeposit: u64 = 1; -// pub const StringLimit: u32 = 50; -// pub const MetadataDepositBase: u64 = 1; -// pub const MetadataDepositPerByte: u64 = 1; -// } +impl Config for Test { + type Currency = Balances; + type Call = Call; + type Event = Event; +} -// impl pallet_assets::Config for Test { -// type Event = Event; -// type Balance = u64; -// type AssetId = u32; -// type Currency = Balances; -// type ForceOrigin = frame_system::EnsureRoot; -// type AssetDeposit = AssetDeposit; -// type MetadataDepositBase = MetadataDepositBase; -// type MetadataDepositPerByte = MetadataDepositPerByte; -// type ApprovalDeposit = ApprovalDeposit; -// type StringLimit = StringLimit; -// type Freezer = (); -// type WeightInfo = (); -// type Extra = (); -// } +pub fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + let (pair1, _) = sp_core::sr25519::Pair::generate(); + let (pair2, _) = sp_core::sr25519::Pair::generate(); + let (pair3, _) = sp_core::sr25519::Pair::generate(); + pallet_balances::GenesisConfig:: { + balances: vec![(pair1.public(), 10), (pair2.public(), 20), (pair3.public(), 30)], + } + .assimilate_storage(&mut t) + .unwrap(); + t.into() +} -// impl Config for Test { -// type Currency = Balances; -// type Call = Call; -// type Event = Event; -// } -// pub fn new_test_ext() -> sp_io::TestExternalities { -// let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); -// let (pair1, _) = sp_core::sr25519::Pair::generate(); -// let (pair2, _) = sp_core::sr25519::Pair::generate(); -// let (pair3, _) = sp_core::sr25519::Pair::generate(); -// pallet_balances::GenesisConfig:: { -// balances: vec![(pair1.public(), 10), (pair2.public(), 20), (pair3.public(), 30)], -// } -// .assimilate_storage(&mut t) -// .unwrap(); -// t.into() -// } +// Build genesis storage according to the mock runtime. +pub fn new_test_ext_funded(pairs: Vec<(sp_core::sr25519::Public, u64)>) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - -// // Build genesis storage according to the mock runtime. -// pub fn new_test_ext_funded(pairs: Vec<(sp_core::sr25519::Public, u64)>) -> sp_io::TestExternalities { -// let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - -// pallet_balances::GenesisConfig:: { -// balances: pairs, -// } -// .assimilate_storage(&mut t) -// .unwrap(); -// t.into() -// } + pallet_balances::GenesisConfig:: { + balances: pairs, + } + .assimilate_storage(&mut t) + .unwrap(); + t.into() +} diff --git a/bin/node-template/pallets/iris-ledger/src/tests.rs b/bin/node-template/pallets/iris-ledger/src/tests.rs index f46d2a532e34..ec80244f4426 100644 --- a/bin/node-template/pallets/iris-ledger/src/tests.rs +++ b/bin/node-template/pallets/iris-ledger/src/tests.rs @@ -1,191 +1,21 @@ -// use super::*; -// use frame_support::{assert_ok}; -// use mock::*; -// use sp_core::Pair; -// use sp_core::{ -// offchain::{testing, OffchainWorkerExt, TransactionPoolExt, OffchainDbExt} -// }; -// use sp_keystore::{testing::KeyStore, KeystoreExt, SyncCryptoStore}; -// use std::sync::Arc; - -// #[test] -// fn iris_assets_initial_state() { -// new_test_ext().execute_with(|| { -// // Given: The node is initialized at block 0 -// // When: I query runtime storagey -// let data_queue = crate::DataQueue::::get(); -// let len = data_queue.len(); -// // Then: Runtime storage is empty -// assert_eq!(len, 0); -// }); -// } - -// #[test] -// fn iris_assets_ipfs_add_bytes_works_for_valid_value() { -// // Given: I am a valid node with a positive balance -// let (p, _) = sp_core::sr25519::Pair::generate(); -// let pairs = vec![(p.clone().public(), 10)]; -// let multiaddr_vec = "/ip4/127.0.0.1/tcp/4001/p2p/12D3KooWMvyvKxYcy9mjbFbXcogFSCvENzQ62ogRxHKZaksFCkAp".as_bytes().to_vec(); -// let cid_vec = "QmPZv7P8nQUSh2CpqTvUeYemFyjvMjgWEs8H1Tm8b3zAm9".as_bytes().to_vec(); -// let name: Vec = "test.txt".as_bytes().to_vec(); -// let cost = 1; -// let id = 1; -// let balance = 1; - -// // -// let expected_data_command = crate::DataCommand::AddBytes( -// OpaqueMultiaddr(multiaddr_vec.clone()), -// cid_vec.clone(), -// p.clone().public(), -// name.clone(), -// id.clone(), -// balance.clone(), -// ); - -// new_test_ext_funded(pairs).execute_with(|| { -// // WHEN: I invoke the create_storage_assets extrinsic -// assert_ok!(Iris::create( -// Origin::signed(p.clone().public()), -// p.clone().public(), -// multiaddr_vec.clone(), -// cid_vec.clone(), -// name.clone(), -// id.clone(), -// balance.clone(), -// )); - -// // THEN: There is a single DataCommand::AddBytes in the DataQueue -// let mut data_queue = crate::DataQueue::::get(); -// let len = data_queue.len(); -// assert_eq!(len, 1); -// let actual_data_command = data_queue.pop(); -// assert_eq!(actual_data_command, Some(expected_data_command)); -// }); -// } - -// #[test] -// fn iris_assets_request_data_works_for_valid_values() { -// // GIVEN: I am a valid Iris node with a positive balance -// let (p, _) = sp_core::sr25519::Pair::generate(); -// let pairs = vec![(p.clone().public(), 10)]; -// // let cid_vec = "QmPZv7P8nQUSh2CpqTvUeYemFyjvMjgWEs8H1Tm8b3zAm9".as_bytes().to_vec(); -// let asset_id = 1; -// let expected_data_command = crate::DataCommand::CatBytes( -// p.clone().public(), -// p.clone().public(), -// asset_id.clone(), -// ); -// new_test_ext_funded(pairs).execute_with(|| { -// // WHEN: I invoke the request_data extrinsic -// assert_ok!(Iris::request_bytes( -// Origin::signed(p.clone().public()), -// p.clone().public(), -// asset_id.clone(), -// )); - -// // THEN: There should be a single DataCommand::CatBytes in the DataQueue -// let mut data_queue = crate::DataQueue::::get(); -// let len = data_queue.len(); -// assert_eq!(len, 1); -// let actual_data_command = data_queue.pop(); -// assert_eq!(actual_data_command, Some(expected_data_command)); -// }); -// } - -// #[test] -// fn iris_assets_submit_ipfs_add_results_works_for_valid_values() { -// // GIVEN: I am a valid Iris node with a positive valance -// let (p, _) = sp_core::sr25519::Pair::generate(); -// let pairs = vec![(p.clone().public(), 10)]; -// let cid_vec = "QmPZv7P8nQUSh2CpqTvUeYemFyjvMjgWEs8H1Tm8b3zAm9".as_bytes().to_vec(); -// let id = 1; -// let balance = 1; - -// new_test_ext_funded(pairs).execute_with(|| { -// // WHEN: I invoke the submit_ipfs_add_results extrinsic -// assert_ok!(Iris::submit_ipfs_add_results( -// Origin::signed(p.clone().public()), -// p.clone().public(), -// cid_vec.clone(), -// id.clone(), -// balance.clone(), -// )); - -// // THEN: a new asset class is created -// // AND: A new entry is added to the AssetClassOwnership StorageDoubleMap -// let admin_asset_class_cid = crate::AssetClassOwnership::::get(p.clone().public(), id.clone()); -// assert_eq!(admin_asset_class_cid, cid_vec.clone()); -// }); -// } - -// #[test] -// fn iris_assets_mint_tickets_works_for_valid_values() { -// // GIVEN: I am a valid Iris node with a positive valance -// let (p, _) = sp_core::sr25519::Pair::generate(); -// let pairs = vec![(p.clone().public(), 10)]; -// let cid_vec = "QmPZv7P8nQUSh2CpqTvUeYemFyjvMjgWEs8H1Tm8b3zAm9".as_bytes().to_vec(); -// let balance = 1; -// let id = 1; - -// new_test_ext_funded(pairs).execute_with(|| { -// // AND: I create an owned asset class -// assert_ok!(Iris::submit_ipfs_add_results( -// Origin::signed(p.clone().public()), -// p.clone().public(), -// cid_vec.clone(), -// id.clone(), -// balance.clone(), -// )); -// // WHEN: I invoke the mint_tickets extrinsic -// assert_ok!(Iris::mint( -// Origin::signed(p.clone().public()), -// p.clone().public(), -// id.clone(), -// balance.clone(), -// )); -// // THEN: new assets are created and awarded to the benficiary -// // AND: A new entry is added to the AssetAccess StorageDoubleMap -// let asset_class_owner = crate::AssetAccess::::get(p.clone().public(), id.clone()); -// assert_eq!(asset_class_owner, p.clone().public()) -// }); -// } - -// #[test] -// fn iris_assets_can_transer_assets() { -// // GIVEN: I am valid Iris node with a positive balance // GIVEN: I am a valid Iris node with a positive valance -// let (p, _) = sp_core::sr25519::Pair::generate(); -// let (p2, _) = sp_core::sr25519::Pair::generate(); -// let pairs = vec![(p.clone().public(), 10), (p2.clone().public(), 10)]; -// let cid_vec = "QmPZv7P8nQUSh2CpqTvUeYemFyjvMjgWEs8H1Tm8b3zAm9".as_bytes().to_vec(); -// let balance = 1; -// let id = 1; - -// new_test_ext_funded(pairs).execute_with(|| { -// // AND: I create an owned asset class -// assert_ok!(Iris::submit_ipfs_add_results( -// Origin::signed(p.clone().public()), -// p.clone().public(), -// cid_vec.clone(), -// id.clone(), -// balance.clone(), -// )); -// // WHEN: I invoke the mint_tickets extrinsic -// assert_ok!(Iris::mint( -// Origin::signed(p.clone().public()), -// p.clone().public(), -// id.clone(), -// balance.clone(), -// )); -// // THEN: new assets are created and awarded to the benficiary -// // AND: A new entry is added to the AssetAccess StorageDoubleMap -// let asset_class_owner = crate::AssetAccess::::get(p.clone().public(), id.clone()); -// assert_eq!(asset_class_owner, p.clone().public()); -// // THEN: I can transfer my owned asset to another address -// assert_ok!(Iris::transfer_asset( -// Origin::signed(p.clone().public()), -// p2.clone().public(), -// id.clone(), -// balance.clone(), -// )); -// }); -// } +use super::*; +use frame_support::{assert_ok}; +use mock::*; +use sp_core::Pair; +use sp_core::{ + offchain::{testing, OffchainWorkerExt, TransactionPoolExt, OffchainDbExt} +}; +use sp_keystore::{testing::KeyStore, KeystoreExt, SyncCryptoStore}; +use std::sync::Arc; + +#[test] +fn iris_ledger_initial_state() { + new_test_ext().execute_with(|| { + // Given: The node is initialized at block 0 + // When: I query runtime storagey + let ledger = crate::Ledger::::get(); + let len = data_queue.len(); + // Then: Runtime storage is empty + assert_eq!(len, 0); + }); +} diff --git a/client/consensus/aura/Cargo.toml b/client/consensus/aura/Cargo.toml index 75595779427b..c7a38b1bbfdf 100644 --- a/client/consensus/aura/Cargo.toml +++ b/client/consensus/aura/Cargo.toml @@ -37,7 +37,7 @@ prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../.. async-trait = "0.1.50" # We enable it only for web-wasm check # See https://docs.rs/getrandom/0.2.1/getrandom/#webassembly-support -getrandom = { version = "0.2", features = ["js"], optional = true } +# getrandom = { version = "0.2", features = ["js"], optional = true } [dev-dependencies] sp-timestamp = { version = "4.0.0-dev", path = "../../../primitives/timestamp" } From 89fcb3e4f62d221d4e161a437768e77d6265889e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Sat, 12 Mar 2022 15:31:37 +0100 Subject: [PATCH 583/695] Update clap to the latest version (#11017) * Update clap to the latest version Besides that it also removes some `structopt` leftovers from some docs. * Fix compile errors * More fixes --- Cargo.lock | 40 ++++++------ bin/node-template/node/Cargo.toml | 2 +- bin/node/bench/Cargo.toml | 2 +- bin/node/cli/Cargo.toml | 4 +- bin/node/cli/build.rs | 4 +- bin/node/inspect/Cargo.toml | 2 +- bin/utils/chain-spec-builder/Cargo.toml | 2 +- bin/utils/subkey/Cargo.toml | 2 +- client/cli/Cargo.toml | 2 +- client/cli/src/arg_enums.rs | 8 +++ client/cli/src/lib.rs | 62 +++++++++---------- client/cli/src/params/import_params.rs | 9 +-- primitives/npos-elections/fuzzer/Cargo.toml | 2 +- utils/frame/benchmarking-cli/Cargo.toml | 2 +- utils/frame/benchmarking-cli/src/lib.rs | 8 +-- utils/frame/frame-utilities-cli/Cargo.toml | 2 +- .../generate-bags/node-runtime/Cargo.toml | 2 +- utils/frame/try-runtime/cli/Cargo.toml | 2 +- utils/frame/try-runtime/cli/src/lib.rs | 16 ++--- 19 files changed, 87 insertions(+), 86 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index db6edfa81d53..1ad59291eca2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -931,7 +931,7 @@ name = "chain-spec-builder" version = "2.0.0" dependencies = [ "ansi_term", - "clap 3.0.7", + "clap 3.1.6", "node-cli", "rand 0.8.4", "sc-chain-spec", @@ -1006,9 +1006,9 @@ dependencies = [ [[package]] name = "clap" -version = "3.0.7" +version = "3.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12e8611f9ae4e068fa3e56931fded356ff745e70987ff76924a6e0ab1c8ef2e3" +checksum = "d8c93436c21e4698bacadf42917db28b23017027a4deccb35dbe47a7e7840123" dependencies = [ "atty", "bitflags", @@ -1018,7 +1018,7 @@ dependencies = [ "os_str_bytes", "strsim", "termcolor", - "textwrap 0.14.2", + "textwrap 0.15.0", ] [[package]] @@ -1027,14 +1027,14 @@ version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a394f7ec0715b42a4e52b294984c27c9a61f77c8d82f7774c5198350be143f19" dependencies = [ - "clap 3.0.7", + "clap 3.1.6", ] [[package]] name = "clap_derive" -version = "3.0.5" +version = "3.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41a0645a430ec9136d2d701e54a95d557de12649a9dd7109ced3187e648ac824" +checksum = "da95d038ede1a964ce99f49cbe27a7fb538d1da595e4b4f70b8c8f338d17bf16" dependencies = [ "heck 0.4.0", "proc-macro-error", @@ -2126,7 +2126,7 @@ version = "4.0.0-dev" dependencies = [ "Inflector", "chrono", - "clap 3.0.7", + "clap 3.1.6", "frame-benchmarking", "frame-support", "handlebars", @@ -4751,7 +4751,7 @@ dependencies = [ name = "node-bench" version = "0.9.0-dev" dependencies = [ - "clap 3.0.7", + "clap 3.1.6", "derive_more", "fs_extra", "futures 0.3.19", @@ -4790,7 +4790,7 @@ version = "3.0.0-dev" dependencies = [ "assert_cmd", "async-std", - "clap 3.0.7", + "clap 3.1.6", "clap_complete", "criterion", "frame-benchmarking-cli", @@ -4904,7 +4904,7 @@ dependencies = [ name = "node-inspect" version = "0.9.0-dev" dependencies = [ - "clap 3.0.7", + "clap 3.1.6", "parity-scale-codec", "sc-cli", "sc-client-api", @@ -5050,7 +5050,7 @@ dependencies = [ name = "node-runtime-generate-bags" version = "3.0.0" dependencies = [ - "clap 3.0.7", + "clap 3.1.6", "generate-bags", "node-runtime", ] @@ -5059,7 +5059,7 @@ dependencies = [ name = "node-template" version = "4.0.0-dev" dependencies = [ - "clap 3.0.7", + "clap 3.1.6", "frame-benchmarking", "frame-benchmarking-cli", "jsonrpc-core", @@ -8083,7 +8083,7 @@ name = "sc-cli" version = "0.10.0-dev" dependencies = [ "chrono", - "clap 3.0.7", + "clap 3.1.6", "fdlimit", "futures 0.3.19", "hex", @@ -10068,7 +10068,7 @@ dependencies = [ name = "sp-npos-elections-fuzzer" version = "2.0.0-alpha.5" dependencies = [ - "clap 3.0.7", + "clap 3.1.6", "honggfuzz", "parity-scale-codec", "rand 0.8.4", @@ -10525,7 +10525,7 @@ dependencies = [ name = "subkey" version = "2.0.1" dependencies = [ - "clap 3.0.7", + "clap 3.1.6", "sc-cli", ] @@ -10553,7 +10553,7 @@ dependencies = [ name = "substrate-frame-cli" version = "4.0.0-dev" dependencies = [ - "clap 3.0.7", + "clap 3.1.6", "frame-support", "frame-system", "sc-cli", @@ -10843,9 +10843,9 @@ dependencies = [ [[package]] name = "textwrap" -version = "0.14.2" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" +checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" [[package]] name = "thiserror" @@ -11367,7 +11367,7 @@ checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" name = "try-runtime-cli" version = "0.10.0-dev" dependencies = [ - "clap 3.0.7", + "clap 3.1.6", "jsonrpsee 0.4.1", "log 0.4.14", "parity-scale-codec", diff --git a/bin/node-template/node/Cargo.toml b/bin/node-template/node/Cargo.toml index 98e8af96d3f8..4549a5b613da 100644 --- a/bin/node-template/node/Cargo.toml +++ b/bin/node-template/node/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] name = "node-template" [dependencies] -clap = { version = "3.0", features = ["derive"] } +clap = { version = "3.1.6", features = ["derive"] } sc-cli = { version = "0.10.0-dev", path = "../../../client/cli", features = ["wasmtime"] } sp-core = { version = "6.0.0", path = "../../../primitives/core" } diff --git a/bin/node/bench/Cargo.toml b/bin/node/bench/Cargo.toml index 2c5dea2cc28a..5b728258dd03 100644 --- a/bin/node/bench/Cargo.toml +++ b/bin/node/bench/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -clap = { version = "3.0", features = ["derive"] } +clap = { version = "3.1.6", features = ["derive"] } log = "0.4.8" node-primitives = { version = "2.0.0", path = "../primitives" } node-testing = { version = "3.0.0-dev", path = "../testing" } diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index b4a91712fd16..24e069d21f69 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -34,7 +34,7 @@ crate-type = ["cdylib", "rlib"] [dependencies] # third-party dependencies -clap = { version = "3.0", features = ["derive"], optional = true } +clap = { version = "3.1.6", features = ["derive"], optional = true } codec = { package = "parity-scale-codec", version = "3.0.0" } serde = { version = "1.0.136", features = ["derive"] } futures = "0.3.19" @@ -133,7 +133,7 @@ remote-externalities = { path = "../../../utils/frame/remote-externalities" } pallet-timestamp = { version = "4.0.0-dev", path = "../../../frame/timestamp" } [build-dependencies] -clap = { version = "3.0", optional = true } +clap = { version = "3.1.6", optional = true } clap_complete = { version = "3.0", optional = true } node-inspect = { version = "0.9.0-dev", optional = true, path = "../inspect" } frame-benchmarking-cli = { version = "4.0.0-dev", optional = true, path = "../../../utils/frame/benchmarking-cli" } diff --git a/bin/node/cli/build.rs b/bin/node/cli/build.rs index 6a010d8858fe..6a3d13dda6a0 100644 --- a/bin/node/cli/build.rs +++ b/bin/node/cli/build.rs @@ -25,7 +25,7 @@ fn main() { mod cli { include!("src/cli.rs"); - use clap::{ArgEnum, IntoApp}; + use clap::{ArgEnum, CommandFactory}; use clap_complete::{generate_to, Shell}; use std::{env, fs, path::Path}; use substrate_build_script_utils::{generate_cargo_keys, rerun_if_git_head_changed}; @@ -61,6 +61,6 @@ mod cli { fs::create_dir(&path).ok(); - let _ = generate_to(*shell, &mut Cli::into_app(), "substrate-node", &path); + let _ = generate_to(*shell, &mut Cli::command(), "substrate-node", &path); } } diff --git a/bin/node/inspect/Cargo.toml b/bin/node/inspect/Cargo.toml index 5e7ed16efdcf..c41681d11be1 100644 --- a/bin/node/inspect/Cargo.toml +++ b/bin/node/inspect/Cargo.toml @@ -11,7 +11,7 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -clap = { version = "3.0", features = ["derive"] } +clap = { version = "3.1.6", features = ["derive"] } codec = { package = "parity-scale-codec", version = "3.0.0" } thiserror = "1.0" sc-cli = { version = "0.10.0-dev", path = "../../../client/cli" } diff --git a/bin/utils/chain-spec-builder/Cargo.toml b/bin/utils/chain-spec-builder/Cargo.toml index 953731719848..1ea1c402151d 100644 --- a/bin/utils/chain-spec-builder/Cargo.toml +++ b/bin/utils/chain-spec-builder/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] ansi_term = "0.12.1" -clap = { version = "3.0", features = ["derive"] } +clap = { version = "3.1.6", features = ["derive"] } rand = "0.8" sc-keystore = { version = "4.0.0-dev", path = "../../../client/keystore" } diff --git a/bin/utils/subkey/Cargo.toml b/bin/utils/subkey/Cargo.toml index 85f864cfbfc1..c8132fe7b5b4 100644 --- a/bin/utils/subkey/Cargo.toml +++ b/bin/utils/subkey/Cargo.toml @@ -17,5 +17,5 @@ path = "src/main.rs" name = "subkey" [dependencies] -clap = { version = "3.0", features = ["derive"] } +clap = { version = "3.1.6", features = ["derive"] } sc-cli = { version = "0.10.0-dev", path = "../../../client/cli" } diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index 813215321dfc..8fdb192b43fb 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] chrono = "0.4.10" -clap = { version = "3.0", features = ["derive"] } +clap = { version = "3.1.6", features = ["derive"] } fdlimit = "0.2.1" futures = "0.3.19" hex = "0.4.2" diff --git a/client/cli/src/arg_enums.rs b/client/cli/src/arg_enums.rs index 6b0a029dd4fe..df4b68ff5c32 100644 --- a/client/cli/src/arg_enums.rs +++ b/client/cli/src/arg_enums.rs @@ -86,6 +86,14 @@ impl Into for WasmExecutionMethod { } } +/// The default [`WasmExecutionMethod`]. +#[cfg(feature = "wasmtime")] +pub const DEFAULT_WASM_EXECUTION_METHOD: &str = "Compiled"; + +/// The default [`WasmExecutionMethod`]. +#[cfg(not(feature = "wasmtime"))] +pub const DEFAULT_WASM_EXECUTION_METHOD: &str = "interpreted-i-know-what-i-do"; + #[allow(missing_docs)] #[derive(Debug, Copy, Clone, PartialEq, Eq, ArgEnum)] #[clap(rename_all = "PascalCase")] diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index c242050dbf32..c920c6cd52cf 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -22,6 +22,9 @@ #![warn(unused_extern_crates)] #![warn(unused_imports)] +use clap::{CommandFactory, FromArgMatches, Parser}; +use sc_service::Configuration; + pub mod arg_enums; mod commands; mod config; @@ -31,33 +34,31 @@ mod runner; pub use arg_enums::*; pub use clap; -use clap::{AppSettings, FromArgMatches, IntoApp, Parser}; pub use commands::*; pub use config::*; pub use error::*; pub use params::*; pub use runner::*; -use sc_service::Configuration; pub use sc_service::{ChainSpec, Role}; pub use sc_tracing::logging::LoggerBuilder; pub use sp_version::RuntimeVersion; /// Substrate client CLI /// -/// This trait needs to be defined on the root structopt of the application. It will provide the -/// implementation name, version, executable name, description, author, support_url, copyright start -/// year and most importantly: how to load the chain spec. -/// -/// StructOpt must not be in scope to use from_args (or the similar methods). This trait provides -/// its own implementation that will fill the necessary field based on the trait's functions. +/// This trait needs to be implemented on the root CLI struct of the application. It will provide +/// the implementation `name`, `version`, `executable name`, `description`, `author`, `support_url`, +/// `copyright start year` and most importantly: how to load the chain spec. pub trait SubstrateCli: Sized { /// Implementation name. fn impl_name() -> String; /// Implementation version. /// - /// By default this will look like this: 2.0.0-b950f731c-x86_64-linux-gnu where the hash is the - /// short commit hash of the commit of in the Git repository. + /// By default this will look like this: + /// + /// `2.0.0-b950f731c-x86_64-linux-gnu` + /// + /// Where the hash is the short commit hash of the commit of in the Git repository. fn impl_version() -> String; /// Executable file name. @@ -88,14 +89,13 @@ pub trait SubstrateCli: Sized { fn load_spec(&self, id: &str) -> std::result::Result, String>; /// Helper function used to parse the command line arguments. This is the equivalent of - /// `structopt`'s `from_iter()` except that it takes a `VersionInfo` argument to provide the - /// name of the application, author, "about" and version. It will also set - /// `AppSettings::GlobalVersion`. + /// [`clap::Parser::parse()`]. /// - /// To allow running the node without subcommand, tt also sets a few more settings: - /// `AppSettings::ArgsNegateSubcommands` and `AppSettings::SubcommandsNegateReqs`. + /// To allow running the node without subcommand, it also sets a few more settings: + /// [`clap::Command::propagate_version`], [`clap::Command::args_conflicts_with_subcommands`], + /// [`clap::Command::subcommand_negates_reqs`]. /// - /// Gets the struct from the command line arguments. Print the + /// Creates `Self` from the command line arguments. Print the /// error message and quit the program in case of failure. fn from_args() -> Self where @@ -105,14 +105,13 @@ pub trait SubstrateCli: Sized { } /// Helper function used to parse the command line arguments. This is the equivalent of - /// `structopt`'s `from_iter()` except that it takes a `VersionInfo` argument to provide the - /// name of the application, author, "about" and version. It will also set - /// `AppSettings::GlobalVersion`. + /// [`clap::Parser::parse_from`]. /// /// To allow running the node without subcommand, it also sets a few more settings: - /// `AppSettings::ArgsNegateSubcommands` and `AppSettings::SubcommandsNegateReqs`. + /// [`clap::Command::propagate_version`], [`clap::Command::args_conflicts_with_subcommands`], + /// [`clap::Command::subcommand_negates_reqs`]. /// - /// Gets the struct from any iterator such as a `Vec` of your making. + /// Creates `Self` from any iterator over arguments. /// Print the error message and quit the program in case of failure. fn from_iter(iter: I) -> Self where @@ -120,7 +119,7 @@ pub trait SubstrateCli: Sized { I: IntoIterator, I::Item: Into + Clone, { - let app = ::into_app(); + let app = ::command(); let mut full_version = Self::impl_version(); full_version.push_str("\n"); @@ -133,11 +132,9 @@ pub trait SubstrateCli: Sized { .author(author.as_str()) .about(about.as_str()) .version(full_version.as_str()) - .setting( - AppSettings::PropagateVersion | - AppSettings::ArgsNegateSubcommands | - AppSettings::SubcommandsNegateReqs, - ); + .propagate_version(true) + .args_conflicts_with_subcommands(true) + .subcommand_negates_reqs(true); let matches = app.try_get_matches_from(iter).unwrap_or_else(|e| e.exit()); @@ -145,14 +142,13 @@ pub trait SubstrateCli: Sized { } /// Helper function used to parse the command line arguments. This is the equivalent of - /// `structopt`'s `from_iter()` except that it takes a `VersionInfo` argument to provide the - /// name of the application, author, "about" and version. It will also set - /// `AppSettings::GlobalVersion`. + /// [`clap::Parser::try_parse_from`] /// /// To allow running the node without subcommand, it also sets a few more settings: - /// `AppSettings::ArgsNegateSubcommands` and `AppSettings::SubcommandsNegateReqs`. + /// [`clap::Command::propagate_version`], [`clap::Command::args_conflicts_with_subcommands`], + /// [`clap::Command::subcommand_negates_reqs`]. /// - /// Gets the struct from any iterator such as a `Vec` of your making. + /// Creates `Self` from any iterator over arguments. /// Print the error message and quit the program in case of failure. /// /// **NOTE:** This method WILL NOT exit when `--help` or `--version` (or short versions) are @@ -165,7 +161,7 @@ pub trait SubstrateCli: Sized { I: IntoIterator, I::Item: Into + Clone, { - let app = ::into_app(); + let app = ::command(); let mut full_version = Self::impl_version(); full_version.push_str("\n"); diff --git a/client/cli/src/params/import_params.rs b/client/cli/src/params/import_params.rs index 1ec79800136d..1df11cff8d79 100644 --- a/client/cli/src/params/import_params.rs +++ b/client/cli/src/params/import_params.rs @@ -21,6 +21,7 @@ use crate::{ ExecutionStrategy, WasmExecutionMethod, DEFAULT_EXECUTION_BLOCK_CONSTRUCTION, DEFAULT_EXECUTION_IMPORT_BLOCK, DEFAULT_EXECUTION_IMPORT_BLOCK_VALIDATOR, DEFAULT_EXECUTION_OFFCHAIN_WORKER, DEFAULT_EXECUTION_OTHER, DEFAULT_EXECUTION_SYNCING, + DEFAULT_WASM_EXECUTION_METHOD, }, params::{DatabaseParams, PruningParams}, }; @@ -28,12 +29,6 @@ use clap::Args; use sc_client_api::execution_extensions::ExecutionStrategies; use std::path::PathBuf; -#[cfg(feature = "wasmtime")] -const WASM_METHOD_DEFAULT: &str = "Compiled"; - -#[cfg(not(feature = "wasmtime"))] -const WASM_METHOD_DEFAULT: &str = "interpreted-i-know-what-i-do"; - /// Parameters for block import. #[derive(Debug, Clone, Args)] pub struct ImportParams { @@ -59,7 +54,7 @@ pub struct ImportParams { value_name = "METHOD", possible_values = WasmExecutionMethod::variants(), ignore_case = true, - default_value = WASM_METHOD_DEFAULT + default_value = DEFAULT_WASM_EXECUTION_METHOD, )] pub wasm_method: WasmExecutionMethod, diff --git a/primitives/npos-elections/fuzzer/Cargo.toml b/primitives/npos-elections/fuzzer/Cargo.toml index afa331b0676e..2f2bae2dd44d 100644 --- a/primitives/npos-elections/fuzzer/Cargo.toml +++ b/primitives/npos-elections/fuzzer/Cargo.toml @@ -14,7 +14,7 @@ publish = false targets = ["x86_64-unknown-linux-gnu"] [dependencies] -clap = { version = "3.0", features = ["derive"] } +clap = { version = "3.1.6", features = ["derive"] } honggfuzz = "0.5" rand = { version = "0.8", features = ["std", "small_rng"] } diff --git a/utils/frame/benchmarking-cli/Cargo.toml b/utils/frame/benchmarking-cli/Cargo.toml index 20122c427936..81e7396db3e6 100644 --- a/utils/frame/benchmarking-cli/Cargo.toml +++ b/utils/frame/benchmarking-cli/Cargo.toml @@ -33,7 +33,7 @@ sp-std = { version = "4.0.0", default-features = false, path = "../../../primiti sp-state-machine = { version = "0.12.0", path = "../../../primitives/state-machine" } sp-trie = { version = "6.0.0", path = "../../../primitives/trie" } codec = { version = "3.0.0", package = "parity-scale-codec" } -clap = { version = "3.0", features = ["derive"] } +clap = { version = "3.1.6", features = ["derive"] } chrono = "0.4" serde = "1.0.136" serde_json = "1.0.74" diff --git a/utils/frame/benchmarking-cli/src/lib.rs b/utils/frame/benchmarking-cli/src/lib.rs index 56aab0321ccd..640b1770f5c3 100644 --- a/utils/frame/benchmarking-cli/src/lib.rs +++ b/utils/frame/benchmarking-cli/src/lib.rs @@ -19,7 +19,7 @@ mod command; mod storage; mod writer; -use sc_cli::{ExecutionStrategy, WasmExecutionMethod}; +use sc_cli::{ExecutionStrategy, WasmExecutionMethod, DEFAULT_WASM_EXECUTION_METHOD}; use std::{fmt::Debug, path::PathBuf}; pub use storage::StorageCmd; @@ -46,11 +46,11 @@ pub struct BenchmarkCmd { pub steps: u32, /// Indicates lowest values for each of the component ranges. - #[clap(long = "low", use_delimiter = true)] + #[clap(long = "low", use_value_delimiter = true)] pub lowest_range_values: Vec, /// Indicates highest values for each of the component ranges. - #[clap(long = "high", use_delimiter = true)] + #[clap(long = "high", use_value_delimiter = true)] pub highest_range_values: Vec, /// Select how many repetitions of this benchmark should run from within the wasm. @@ -130,7 +130,7 @@ pub struct BenchmarkCmd { value_name = "METHOD", possible_values = WasmExecutionMethod::variants(), ignore_case = true, - default_value = "compiled" + default_value = DEFAULT_WASM_EXECUTION_METHOD, )] pub wasm_method: WasmExecutionMethod, diff --git a/utils/frame/frame-utilities-cli/Cargo.toml b/utils/frame/frame-utilities-cli/Cargo.toml index bc673105b78b..43c8b3189895 100644 --- a/utils/frame/frame-utilities-cli/Cargo.toml +++ b/utils/frame/frame-utilities-cli/Cargo.toml @@ -11,7 +11,7 @@ documentation = "https://docs.rs/substrate-frame-cli" readme = "README.md" [dependencies] -clap = { version = "3.0", features = ["derive"] } +clap = { version = "3.1.6", features = ["derive"] } sp-core = { version = "6.0.0", path = "../../../primitives/core" } sc-cli = { version = "0.10.0-dev", path = "../../../client/cli" } diff --git a/utils/frame/generate-bags/node-runtime/Cargo.toml b/utils/frame/generate-bags/node-runtime/Cargo.toml index 11dee7b8b68e..d5c8cab7ba0d 100644 --- a/utils/frame/generate-bags/node-runtime/Cargo.toml +++ b/utils/frame/generate-bags/node-runtime/Cargo.toml @@ -14,4 +14,4 @@ node-runtime = { version = "3.0.0-dev", path = "../../../../bin/node/runtime" } generate-bags = { version = "4.0.0-dev", path = "../" } # third-party -clap = { version = "3.0", features = ["derive"] } +clap = { version = "3.1.6", features = ["derive"] } diff --git a/utils/frame/try-runtime/cli/Cargo.toml b/utils/frame/try-runtime/cli/Cargo.toml index 04b6d336f740..6f72bd3b9d7f 100644 --- a/utils/frame/try-runtime/cli/Cargo.toml +++ b/utils/frame/try-runtime/cli/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -clap = { version = "3.0", features = ["derive"] } +clap = { version = "3.1.6", features = ["derive"] } log = "0.4.8" parity-scale-codec = "3.0.0" serde = "1.0.136" diff --git a/utils/frame/try-runtime/cli/src/lib.rs b/utils/frame/try-runtime/cli/src/lib.rs index 92721228c929..2298fa5c042e 100644 --- a/utils/frame/try-runtime/cli/src/lib.rs +++ b/utils/frame/try-runtime/cli/src/lib.rs @@ -270,7 +270,9 @@ use remote_externalities::{ Builder, Mode, OfflineConfig, OnlineConfig, SnapshotConfig, TestExternalities, }; use sc_chain_spec::ChainSpec; -use sc_cli::{CliConfiguration, ExecutionStrategy, WasmExecutionMethod}; +use sc_cli::{ + CliConfiguration, ExecutionStrategy, WasmExecutionMethod, DEFAULT_WASM_EXECUTION_METHOD, +}; use sc_executor::NativeElseWasmExecutor; use sc_service::{Configuration, NativeExecutionDispatch}; use sp_core::{ @@ -394,7 +396,7 @@ pub struct SharedParams { value_name = "METHOD", possible_values = WasmExecutionMethod::variants(), ignore_case = true, - default_value = "Compiled" + default_value = DEFAULT_WASM_EXECUTION_METHOD, )] pub wasm_method: WasmExecutionMethod, @@ -458,15 +460,15 @@ pub enum State { snapshot_path: Option, /// The pallets to scrape. If empty, entire chain state will be scraped. - #[clap(short, long, require_delimiter = true)] - pallets: Option>, + #[clap(short, long, multiple_values = true)] + pallets: Vec, /// Fetch the child-keys as well. /// - /// Default is `false`, if specific `pallets` are specified, true otherwise. In other + /// Default is `false`, if specific `--pallets` are specified, `true` otherwise. In other /// words, if you scrape the whole state the child tree data is included out of the box. /// Otherwise, it must be enabled explicitly using this flag. - #[clap(long, require_delimiter = true)] + #[clap(long)] child_tree: bool, }, } @@ -492,7 +494,7 @@ impl State { .mode(Mode::Online(OnlineConfig { transport: uri.to_owned().into(), state_snapshot: snapshot_path.as_ref().map(SnapshotConfig::new), - pallets: pallets.clone().unwrap_or_default(), + pallets: pallets.clone(), scrape_children: true, at, })) From b797b89a9633c387ebc2f283af83d9cd450f5f50 Mon Sep 17 00:00:00 2001 From: Sergejs Kostjucenko <85877331+sergejparity@users.noreply.github.com> Date: Mon, 14 Mar 2022 10:42:34 +0200 Subject: [PATCH 584/695] Move scripts used in CI to the new location (#11008) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move scripts used in CI to the new location - **./scripts/ci/** * Move github scripts * Move more files * Move ci scripts and fix dependencies * Update docs/node-template-release.md Co-authored-by: João Paulo Silva de Souza <77391175+joao-paulo-parity@users.noreply.github.com> * Remove Cargo.lock * Apply suggestions from code review Co-authored-by: Denis Pisarev * Make more paths uniform Co-authored-by: João Paulo Silva de Souza <77391175+joao-paulo-parity@users.noreply.github.com> Co-authored-by: Denis Pisarev --- .github/workflows/check-labels.yml | 2 +- .github/workflows/monthly-tag.yml | 2 +- .gitignore | 2 +- .gitlab-ci.yml | 52 +++++++++---------- docs/CODEOWNERS | 2 +- docs/node-template-release.md | 4 +- {.maintain => scripts/ci}/common/lib.sh | 0 {.maintain => scripts/ci}/deny.toml | 0 .../ci}/docker/subkey.Dockerfile | 2 +- .../ci}/docker/substrate.Dockerfile | 2 +- .../ci}/github/check_labels.sh | 0 .../ci/github}/generate_changelog.sh | 0 .../ci}/gitlab/check_runtime.sh | 0 .../ci}/gitlab/check_signed.sh | 0 .../ci/gitlab}/ensure-deps.sh | 0 .../ci}/gitlab/publish_draft_release.sh | 0 .../ci}/gitlab/skip_if_draft.sh | 0 .../alerting-rules/alerting-rule-tests.yaml | 0 .../alerting-rules/alerting-rules.yaml | 0 .../grafana-dashboards/README_dashboard.md | 0 .../substrate-networking.json | 0 .../substrate-service-tasks.json | 0 .../ci}/node-template-release.sh | 2 +- .../ci}/node-template-release/Cargo.toml | 0 .../ci}/node-template-release/src/main.rs | 0 25 files changed, 35 insertions(+), 35 deletions(-) rename {.maintain => scripts/ci}/common/lib.sh (100%) rename {.maintain => scripts/ci}/deny.toml (100%) rename {.maintain => scripts/ci}/docker/subkey.Dockerfile (93%) rename {.maintain => scripts/ci}/docker/substrate.Dockerfile (96%) rename {.maintain => scripts/ci}/github/check_labels.sh (100%) rename {.maintain/gitlab => scripts/ci/github}/generate_changelog.sh (100%) rename {.maintain => scripts/ci}/gitlab/check_runtime.sh (100%) rename {.maintain => scripts/ci}/gitlab/check_signed.sh (100%) rename {.maintain => scripts/ci/gitlab}/ensure-deps.sh (100%) rename {.maintain => scripts/ci}/gitlab/publish_draft_release.sh (100%) rename {.maintain => scripts/ci}/gitlab/skip_if_draft.sh (100%) rename {.maintain => scripts/ci}/monitoring/alerting-rules/alerting-rule-tests.yaml (100%) rename {.maintain => scripts/ci}/monitoring/alerting-rules/alerting-rules.yaml (100%) rename {.maintain => scripts/ci}/monitoring/grafana-dashboards/README_dashboard.md (100%) rename {.maintain => scripts/ci}/monitoring/grafana-dashboards/substrate-networking.json (100%) rename {.maintain => scripts/ci}/monitoring/grafana-dashboards/substrate-service-tasks.json (100%) rename {.maintain => scripts/ci}/node-template-release.sh (84%) rename {.maintain => scripts/ci}/node-template-release/Cargo.toml (100%) rename {.maintain => scripts/ci}/node-template-release/src/main.rs (100%) diff --git a/.github/workflows/check-labels.yml b/.github/workflows/check-labels.yml index 7180e7b50966..74fdd9b2d818 100644 --- a/.github/workflows/check-labels.yml +++ b/.github/workflows/check-labels.yml @@ -14,7 +14,7 @@ jobs: ref: ${{ github.event.pull_request.head.ref }} repository: ${{ github.event.pull_request.head.repo.full_name }} - name: Check labels - run: bash ${{ github.workspace }}/.maintain/github/check_labels.sh + run: bash ${{ github.workspace }}/scripts/ci/github/check_labels.sh env: GITHUB_PR: ${{ github.event.pull_request.number }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/monthly-tag.yml b/.github/workflows/monthly-tag.yml index 8736a341cecf..9fed86539601 100644 --- a/.github/workflows/monthly-tag.yml +++ b/.github/workflows/monthly-tag.yml @@ -29,7 +29,7 @@ jobs: echo "" >> Changelog.md echo "## Changes since last snapshot (${{ steps.tags.outputs.old }})" >> Changelog.md echo "" >> Changelog.md - ./.maintain/gitlab/generate_changelog.sh ${{ steps.tags.outputs.old }} >> Changelog.md + ./scripts/ci/github/generate_changelog.sh ${{ steps.tags.outputs.old }} >> Changelog.md - name: Release snapshot id: release-snapshot uses: actions/create-release@latest diff --git a/.gitignore b/.gitignore index f1103fdab93a..5cd013e054e4 100644 --- a/.gitignore +++ b/.gitignore @@ -24,4 +24,4 @@ rls*.log .cargo-remote.toml *.bin *.iml -.maintain/node-template-release/Cargo.lock +scripts/ci/node-template-release/Cargo.lock diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8dabbc288cd6..b6f9ff948606 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -18,7 +18,7 @@ # script: # - echo "List of shell commands to run in your job" # - echo "You can also just specify a script here, like so:" -# - ./.maintain/gitlab/my_amazing_script.sh +# - ./scripts/ci/gitlab/my_amazing_script.sh stages: - check @@ -165,12 +165,12 @@ default: fi .cargo-check-benches-script: &cargo-check-benches-script - - mkdir -p artifacts/benches/$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA + - mkdir -p ./artifacts/benches/$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA - SKIP_WASM_BUILD=1 time cargo +nightly check --benches --all - 'cargo run --release -p node-bench -- ::node::import::native::sr25519::transfer_keep_alive::paritydb::small --json - | tee artifacts/benches/$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA/::node::import::native::sr25519::transfer_keep_alive::paritydb::small.json' + | tee ./artifacts/benches/$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA/::node::import::native::sr25519::transfer_keep_alive::paritydb::small.json' - 'cargo run --release -p node-bench -- ::trie::read::small --json - | tee artifacts/benches/$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA/::trie::read::small.json' + | tee ./artifacts/benches/$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA/::trie::read::small.json' - sccache -s .build-linux-substrate-script: &build-linux-substrate-script @@ -185,7 +185,7 @@ default: tee ./artifacts/substrate/VERSION; fi - sha256sum ./artifacts/substrate/substrate | tee ./artifacts/substrate/substrate.sha256 - - cp -r .maintain/docker/substrate.Dockerfile ./artifacts/substrate/ + - cp -r ./scripts/ci/docker/substrate.Dockerfile ./artifacts/substrate/ - sccache -s #### Vault secrets @@ -241,7 +241,7 @@ skip-if-draft: - echo "Commit message is ${CI_COMMIT_MESSAGE}" - echo "Ref is ${CI_COMMIT_REF_NAME}" - echo "pipeline source is ${CI_PIPELINE_SOURCE}" - - ./.maintain/gitlab/skip_if_draft.sh + - ./scripts/ci/gitlab/skip_if_draft.sh #### stage: check @@ -256,7 +256,7 @@ check-runtime: GITLAB_API: "https://gitlab.parity.io/api/v4" GITHUB_API_PROJECT: "parity%2Finfrastructure%2Fgithub-api" script: - - ./.maintain/gitlab/check_runtime.sh + - ./scripts/ci/gitlab/check_runtime.sh allow_failure: true check-signed-tag: @@ -267,7 +267,7 @@ check-signed-tag: - if: $CI_COMMIT_REF_NAME =~ /^ci-release-.*$/ - if: $CI_COMMIT_REF_NAME =~ /^v[0-9]+\.[0-9]+.*$/ # i.e. v1.0, v2.1rc1 script: - - ./.maintain/gitlab/check_signed.sh + - ./scripts/ci/gitlab/check_signed.sh test-dependency-rules: stage: check @@ -276,7 +276,7 @@ test-dependency-rules: rules: - if: $CI_COMMIT_REF_NAME =~ /^[0-9]+$/ # PRs script: - - .maintain/ensure-deps.sh + - ./scripts/ci/gitlab/ensure-deps.sh test-prometheus-alerting-rules: stage: check @@ -288,11 +288,11 @@ test-prometheus-alerting-rules: - if: $CI_COMMIT_BRANCH changes: - .gitlab-ci.yml - - .maintain/monitoring/**/* + - ./scripts/ci/monitoring/**/* script: - - promtool check rules .maintain/monitoring/alerting-rules/alerting-rules.yaml - - cat .maintain/monitoring/alerting-rules/alerting-rules.yaml | - promtool test rules .maintain/monitoring/alerting-rules/alerting-rule-tests.yaml + - promtool check rules ./scripts/ci/monitoring/alerting-rules/alerting-rules.yaml + - cat ./scripts/ci/monitoring/alerting-rules/alerting-rules.yaml | + promtool test rules ./scripts/ci/monitoring/alerting-rules/alerting-rule-tests.yaml #### stage: test @@ -301,10 +301,10 @@ cargo-deny: <<: *docker-env <<: *nightly-pipeline script: - - cargo deny check --hide-inclusion-graph -c .maintain/deny.toml + - cargo deny check --hide-inclusion-graph -c ./scripts/ci/deny.toml after_script: - echo "___The complete log is in the artifacts___" - - cargo deny check -c .maintain/deny.toml 2> deny.log + - cargo deny check -c ./scripts/ci/deny.toml 2> deny.log artifacts: name: $CI_COMMIT_SHORT_SHA expire_in: 3 days @@ -404,13 +404,13 @@ test-deterministic-wasm: # build runtime - cargo build --verbose --release -p node-runtime # make checksum - - sha256sum target/release/wbuild/node-runtime/target/wasm32-unknown-unknown/release/node_runtime.wasm > checksum.sha256 + - sha256sum ./target/release/wbuild/node-runtime/target/wasm32-unknown-unknown/release/node_runtime.wasm > checksum.sha256 # clean up – FIXME: can we reuse some of the artifacts? - cargo clean # build again - cargo build --verbose --release -p node-runtime # confirm checksum - - sha256sum -c checksum.sha256 + - sha256sum -c ./checksum.sha256 - sccache -s test-linux-stable: &test-linux @@ -426,8 +426,8 @@ test-linux-stable: &test-linux WASM_BUILD_NO_COLOR: 1 script: # this job runs all tests in former runtime-benchmarks, frame-staking and wasmtime tests - - time cargo test --workspace --locked --release --verbose --features runtime-benchmarks --manifest-path bin/node/cli/Cargo.toml - - time cargo test -p frame-support-test --features=conditional-storage,no-metadata-docs --manifest-path frame/support/test/Cargo.toml --test pallet # does not reuse cache 1 min 44 sec + - time cargo test --workspace --locked --release --verbose --features runtime-benchmarks --manifest-path ./bin/node/cli/Cargo.toml + - time cargo test -p frame-support-test --features=conditional-storage,no-metadata-docs --manifest-path ./frame/support/test/Cargo.toml --test pallet # does not reuse cache 1 min 44 sec - SUBSTRATE_TEST_TIMEOUT=1 time cargo test -p substrate-test-utils --release --verbose --locked -- --ignored timeout - sccache -s @@ -443,7 +443,7 @@ test-frame-examples-compile-to-wasm: RUSTFLAGS: "-Cdebug-assertions=y" RUST_BACKTRACE: 1 script: - - cd frame/examples/offchain-worker/ + - cd ./frame/examples/offchain-worker/ - cargo +nightly build --target=wasm32-unknown-unknown --no-default-features - cd ../basic - cargo +nightly build --target=wasm32-unknown-unknown --no-default-features @@ -475,8 +475,8 @@ check-tracing: <<: *test-refs script: # with-tracing must be explicitly activated, we run a test to ensure this works as expected in both cases - - time cargo +nightly test --manifest-path primitives/tracing/Cargo.toml --no-default-features - - time cargo +nightly test --manifest-path primitives/tracing/Cargo.toml --no-default-features --features=with-tracing + - time cargo +nightly test --manifest-path ./primitives/tracing/Cargo.toml --no-default-features + - time cargo +nightly test --manifest-path ./primitives/tracing/Cargo.toml --no-default-features --features=with-tracing - sccache -s test-full-crypto-feature: @@ -568,7 +568,7 @@ build-linux-substrate: script: - *build-linux-substrate-script - printf '\n# building node-template\n\n' - - ./.maintain/node-template-release.sh ./artifacts/substrate/substrate-node-template.tar.gz + - ./scripts/ci/node-template-release.sh ./artifacts/substrate/substrate-node-template.tar.gz build-linux-subkey: &build-subkey stage: build @@ -590,7 +590,7 @@ build-linux-subkey: &build-subkey sed -n -E 's/^subkey ([0-9.]+.*)/\1/p' | tee ./artifacts/subkey/VERSION; - sha256sum ./artifacts/subkey/subkey | tee ./artifacts/subkey/subkey.sha256 - - cp -r .maintain/docker/subkey.Dockerfile ./artifacts/subkey/ + - cp -r ./scripts/ci/docker/subkey.Dockerfile ./artifacts/subkey/ - sccache -s build-macos-subkey: @@ -784,7 +784,7 @@ publish-draft-release: - if: $CI_COMMIT_REF_NAME =~ /^ci-release-.*$/ - if: $CI_COMMIT_REF_NAME =~ /^v[0-9]+\.[0-9]+.*$/ # i.e. v1.0, v2.1rc1 script: - - ./.maintain/gitlab/publish_draft_release.sh + - ./scripts/ci/gitlab/publish_draft_release.sh allow_failure: true #### stage: deploy @@ -807,4 +807,4 @@ deploy-prometheus-alerting-rules: - if: $CI_COMMIT_REF_NAME == "master" changes: - .gitlab-ci.yml - - .maintain/monitoring/**/* + - ./scripts/ci/monitoring/**/* diff --git a/docs/CODEOWNERS b/docs/CODEOWNERS index 70009d311f1c..0b9e6e778305 100644 --- a/docs/CODEOWNERS +++ b/docs/CODEOWNERS @@ -19,7 +19,7 @@ # - The latest matching rule, if multiple, takes precedence. # CI -/.maintain/ @paritytech/ci +/scripts/ci/ @paritytech/ci /.github/ @paritytech/ci /.gitlab-ci.yml @paritytech/ci diff --git a/docs/node-template-release.md b/docs/node-template-release.md index 25834ae99f43..4f4977a9df03 100644 --- a/docs/node-template-release.md +++ b/docs/node-template-release.md @@ -7,7 +7,7 @@ the existence of your current git commit ID in the remote repository. Assume you are in root directory of Substrate. Run: ```bash - cd .maintain/ + cd scripts/ci/ ./node-template-release.sh ``` @@ -50,7 +50,7 @@ commit in Substrate remote repository, such as: ``` P.S: This step can be automated if we update `node-template-release` package in - `.maintain/node-template-release`. + `scripts/ci/node-template-release`. 4. Once the three `Cargo.toml`s are updated, compile and confirm that the Node Template builds. Then commit the changes to a new branch in [Substrate Node Template](https://github.com/substrate-developer-hub/substrate-node-template), and make a PR. diff --git a/.maintain/common/lib.sh b/scripts/ci/common/lib.sh similarity index 100% rename from .maintain/common/lib.sh rename to scripts/ci/common/lib.sh diff --git a/.maintain/deny.toml b/scripts/ci/deny.toml similarity index 100% rename from .maintain/deny.toml rename to scripts/ci/deny.toml diff --git a/.maintain/docker/subkey.Dockerfile b/scripts/ci/docker/subkey.Dockerfile similarity index 93% rename from .maintain/docker/subkey.Dockerfile rename to scripts/ci/docker/subkey.Dockerfile index 5797295806d0..3483502845cf 100644 --- a/.maintain/docker/subkey.Dockerfile +++ b/scripts/ci/docker/subkey.Dockerfile @@ -8,7 +8,7 @@ LABEL io.parity.image.authors="devops-team@parity.io" \ io.parity.image.vendor="Parity Technologies" \ io.parity.image.title="parity/subkey" \ io.parity.image.description="Subkey: key generating utility for Substrate." \ - io.parity.image.source="https://github.com/paritytech/substrate/blob/${VCS_REF}/.maintain/docker/subkey.Dockerfile" \ + io.parity.image.source="https://github.com/paritytech/substrate/blob/${VCS_REF}/scripts/ci/docker/subkey.Dockerfile" \ io.parity.image.revision="${VCS_REF}" \ io.parity.image.created="${BUILD_DATE}" \ io.parity.image.documentation="https://github.com/paritytech/substrate/tree/${VCS_REF}/subkey" diff --git a/.maintain/docker/substrate.Dockerfile b/scripts/ci/docker/substrate.Dockerfile similarity index 96% rename from .maintain/docker/substrate.Dockerfile rename to scripts/ci/docker/substrate.Dockerfile index e13dfb426adf..b4c103ed5244 100644 --- a/.maintain/docker/substrate.Dockerfile +++ b/scripts/ci/docker/substrate.Dockerfile @@ -8,7 +8,7 @@ LABEL io.parity.image.authors="devops-team@parity.io" \ io.parity.image.vendor="Parity Technologies" \ io.parity.image.title="parity/substrate" \ io.parity.image.description="Substrate: The platform for blockchain innovators." \ - io.parity.image.source="https://github.com/paritytech/substrate/blob/${VCS_REF}/.maintain/docker/Dockerfile" \ + io.parity.image.source="https://github.com/paritytech/substrate/blob/${VCS_REF}/scripts/ci/docker/Dockerfile" \ io.parity.image.revision="${VCS_REF}" \ io.parity.image.created="${BUILD_DATE}" \ io.parity.image.documentation="https://wiki.parity.io/Parity-Substrate" diff --git a/.maintain/github/check_labels.sh b/scripts/ci/github/check_labels.sh similarity index 100% rename from .maintain/github/check_labels.sh rename to scripts/ci/github/check_labels.sh diff --git a/.maintain/gitlab/generate_changelog.sh b/scripts/ci/github/generate_changelog.sh similarity index 100% rename from .maintain/gitlab/generate_changelog.sh rename to scripts/ci/github/generate_changelog.sh diff --git a/.maintain/gitlab/check_runtime.sh b/scripts/ci/gitlab/check_runtime.sh similarity index 100% rename from .maintain/gitlab/check_runtime.sh rename to scripts/ci/gitlab/check_runtime.sh diff --git a/.maintain/gitlab/check_signed.sh b/scripts/ci/gitlab/check_signed.sh similarity index 100% rename from .maintain/gitlab/check_signed.sh rename to scripts/ci/gitlab/check_signed.sh diff --git a/.maintain/ensure-deps.sh b/scripts/ci/gitlab/ensure-deps.sh similarity index 100% rename from .maintain/ensure-deps.sh rename to scripts/ci/gitlab/ensure-deps.sh diff --git a/.maintain/gitlab/publish_draft_release.sh b/scripts/ci/gitlab/publish_draft_release.sh similarity index 100% rename from .maintain/gitlab/publish_draft_release.sh rename to scripts/ci/gitlab/publish_draft_release.sh diff --git a/.maintain/gitlab/skip_if_draft.sh b/scripts/ci/gitlab/skip_if_draft.sh similarity index 100% rename from .maintain/gitlab/skip_if_draft.sh rename to scripts/ci/gitlab/skip_if_draft.sh diff --git a/.maintain/monitoring/alerting-rules/alerting-rule-tests.yaml b/scripts/ci/monitoring/alerting-rules/alerting-rule-tests.yaml similarity index 100% rename from .maintain/monitoring/alerting-rules/alerting-rule-tests.yaml rename to scripts/ci/monitoring/alerting-rules/alerting-rule-tests.yaml diff --git a/.maintain/monitoring/alerting-rules/alerting-rules.yaml b/scripts/ci/monitoring/alerting-rules/alerting-rules.yaml similarity index 100% rename from .maintain/monitoring/alerting-rules/alerting-rules.yaml rename to scripts/ci/monitoring/alerting-rules/alerting-rules.yaml diff --git a/.maintain/monitoring/grafana-dashboards/README_dashboard.md b/scripts/ci/monitoring/grafana-dashboards/README_dashboard.md similarity index 100% rename from .maintain/monitoring/grafana-dashboards/README_dashboard.md rename to scripts/ci/monitoring/grafana-dashboards/README_dashboard.md diff --git a/.maintain/monitoring/grafana-dashboards/substrate-networking.json b/scripts/ci/monitoring/grafana-dashboards/substrate-networking.json similarity index 100% rename from .maintain/monitoring/grafana-dashboards/substrate-networking.json rename to scripts/ci/monitoring/grafana-dashboards/substrate-networking.json diff --git a/.maintain/monitoring/grafana-dashboards/substrate-service-tasks.json b/scripts/ci/monitoring/grafana-dashboards/substrate-service-tasks.json similarity index 100% rename from .maintain/monitoring/grafana-dashboards/substrate-service-tasks.json rename to scripts/ci/monitoring/grafana-dashboards/substrate-service-tasks.json diff --git a/.maintain/node-template-release.sh b/scripts/ci/node-template-release.sh similarity index 84% rename from .maintain/node-template-release.sh rename to scripts/ci/node-template-release.sh index cb5e72e7fa98..09ef98e04627 100755 --- a/.maintain/node-template-release.sh +++ b/scripts/ci/node-template-release.sh @@ -11,6 +11,6 @@ if [ "$#" -ne 1 ]; then fi PATH_TO_ARCHIVE=$1 -cd $PROJECT_ROOT/.maintain/node-template-release +cd $PROJECT_ROOT/scripts/ci/node-template-release cargo run $PROJECT_ROOT/bin/node-template $PROJECT_ROOT/$PATH_TO_ARCHIVE diff --git a/.maintain/node-template-release/Cargo.toml b/scripts/ci/node-template-release/Cargo.toml similarity index 100% rename from .maintain/node-template-release/Cargo.toml rename to scripts/ci/node-template-release/Cargo.toml diff --git a/.maintain/node-template-release/src/main.rs b/scripts/ci/node-template-release/src/main.rs similarity index 100% rename from .maintain/node-template-release/src/main.rs rename to scripts/ci/node-template-release/src/main.rs From 11403bf965dd99d8af11d8f73128f7b4896a65bd Mon Sep 17 00:00:00 2001 From: Georges Date: Mon, 14 Mar 2022 10:00:41 +0000 Subject: [PATCH 585/695] Move `sp-npos-elections-solution-type` to `frame-election-provider-support` (#11016) * Move `sp-npos-elections-solution-type` to `frame-election-provider-support` First stab at it, will need to amend some more stuff * Fixing tests * Fixing tests * Fixing cargo.toml for std configuration * fmt * Committing suggested changes renaming, and re exporting macro. * Removing unneeded imports --- Cargo.lock | 47 ++- Cargo.toml | 3 +- bin/node/runtime/src/lib.rs | 2 +- .../election-provider-multi-phase/Cargo.toml | 3 +- .../election-provider-multi-phase/src/mock.rs | 2 +- frame/election-provider-support/Cargo.toml | 1 + .../solution-type/Cargo.toml | 6 +- .../solution-type/fuzzer/Cargo.toml | 30 ++ .../solution-type}/fuzzer/src/compact.rs | 3 +- .../solution-type/src/codec.rs | 0 .../src/from_assignment_helpers.rs | 0 .../solution-type/src/index_assignment.rs | 0 .../solution-type/src/lib.rs | 4 +- .../solution-type/src/mock.rs | 178 +++++++++ .../solution-type/src/single_page.rs | 0 .../solution-type/src/tests.rs | 350 ++++++++++++++++++ .../tests/ui/fail/missing_accuracy.rs | 2 +- .../tests/ui/fail/missing_accuracy.stderr | 0 .../tests/ui/fail/missing_target.rs | 2 +- .../tests/ui/fail/missing_target.stderr | 0 .../tests/ui/fail/missing_voter.rs | 2 +- .../tests/ui/fail/missing_voter.stderr | 0 .../tests/ui/fail/no_annotations.rs | 2 +- .../tests/ui/fail/no_annotations.stderr | 0 .../tests/ui/fail/swap_voter_target.rs | 2 +- .../tests/ui/fail/swap_voter_target.stderr | 0 .../tests/ui/fail/wrong_attribute.rs | 2 +- .../tests/ui/fail/wrong_attribute.stderr | 0 frame/election-provider-support/src/lib.rs | 1 + frame/staking/src/lib.rs | 6 +- primitives/npos-elections/Cargo.toml | 1 - primitives/npos-elections/fuzzer/Cargo.toml | 4 - primitives/npos-elections/src/lib.rs | 7 +- primitives/npos-elections/src/mock.rs | 161 -------- primitives/npos-elections/src/tests.rs | 331 +---------------- 35 files changed, 616 insertions(+), 536 deletions(-) rename {primitives/npos-elections => frame/election-provider-support}/solution-type/Cargo.toml (73%) create mode 100644 frame/election-provider-support/solution-type/fuzzer/Cargo.toml rename {primitives/npos-elections => frame/election-provider-support/solution-type}/fuzzer/src/compact.rs (94%) rename {primitives/npos-elections => frame/election-provider-support}/solution-type/src/codec.rs (100%) rename {primitives/npos-elections => frame/election-provider-support}/solution-type/src/from_assignment_helpers.rs (100%) rename {primitives/npos-elections => frame/election-provider-support}/solution-type/src/index_assignment.rs (100%) rename {primitives/npos-elections => frame/election-provider-support}/solution-type/src/lib.rs (98%) create mode 100644 frame/election-provider-support/solution-type/src/mock.rs rename {primitives/npos-elections => frame/election-provider-support}/solution-type/src/single_page.rs (100%) create mode 100644 frame/election-provider-support/solution-type/src/tests.rs rename {primitives/npos-elections => frame/election-provider-support}/solution-type/tests/ui/fail/missing_accuracy.rs (64%) rename {primitives/npos-elections => frame/election-provider-support}/solution-type/tests/ui/fail/missing_accuracy.stderr (100%) rename {primitives/npos-elections => frame/election-provider-support}/solution-type/tests/ui/fail/missing_target.rs (63%) rename {primitives/npos-elections => frame/election-provider-support}/solution-type/tests/ui/fail/missing_target.stderr (100%) rename {primitives/npos-elections => frame/election-provider-support}/solution-type/tests/ui/fail/missing_voter.rs (63%) rename {primitives/npos-elections => frame/election-provider-support}/solution-type/tests/ui/fail/missing_voter.stderr (100%) rename {primitives/npos-elections => frame/election-provider-support}/solution-type/tests/ui/fail/no_annotations.rs (58%) rename {primitives/npos-elections => frame/election-provider-support}/solution-type/tests/ui/fail/no_annotations.stderr (100%) rename {primitives/npos-elections => frame/election-provider-support}/solution-type/tests/ui/fail/swap_voter_target.rs (66%) rename {primitives/npos-elections => frame/election-provider-support}/solution-type/tests/ui/fail/swap_voter_target.stderr (100%) rename {primitives/npos-elections => frame/election-provider-support}/solution-type/tests/ui/fail/wrong_attribute.rs (69%) rename {primitives/npos-elections => frame/election-provider-support}/solution-type/tests/ui/fail/wrong_attribute.stderr (100%) diff --git a/Cargo.lock b/Cargo.lock index 1ad59291eca2..9f4d2f21cf9c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2160,10 +2160,26 @@ dependencies = [ "sp-trie", ] +[[package]] +name = "frame-election-provider-solution-type" +version = "4.0.0-dev" +dependencies = [ + "parity-scale-codec", + "proc-macro-crate 1.1.0", + "proc-macro2", + "quote", + "scale-info", + "sp-arithmetic", + "sp-npos-elections", + "syn", + "trybuild", +] + [[package]] name = "frame-election-provider-support" version = "4.0.0-dev" dependencies = [ + "frame-election-provider-solution-type", "frame-support", "frame-system", "parity-scale-codec", @@ -2176,6 +2192,21 @@ dependencies = [ "sp-std", ] +[[package]] +name = "frame-election-solution-type-fuzzer" +version = "2.0.0-alpha.5" +dependencies = [ + "clap 3.0.7", + "frame-election-provider-solution-type", + "honggfuzz", + "parity-scale-codec", + "rand 0.8.4", + "scale-info", + "sp-arithmetic", + "sp-npos-elections", + "sp-runtime", +] + [[package]] name = "frame-executive" version = "4.0.0-dev" @@ -10058,7 +10089,6 @@ dependencies = [ "serde", "sp-arithmetic", "sp-core", - "sp-npos-elections-solution-type", "sp-runtime", "sp-std", "substrate-test-utils", @@ -10077,21 +10107,6 @@ dependencies = [ "sp-runtime", ] -[[package]] -name = "sp-npos-elections-solution-type" -version = "4.0.0-dev" -dependencies = [ - "parity-scale-codec", - "proc-macro-crate 1.1.0", - "proc-macro2", - "quote", - "scale-info", - "sp-arithmetic", - "sp-npos-elections", - "syn", - "trybuild", -] - [[package]] name = "sp-offchain" version = "4.0.0-dev" diff --git a/Cargo.toml b/Cargo.toml index f24ff6d04980..bce23456b27e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -86,6 +86,8 @@ members = [ "frame/try-runtime", "frame/election-provider-multi-phase", "frame/election-provider-support", + "frame/election-provider-support/solution-type", + "frame/election-provider-support/solution-type/fuzzer", "frame/examples/basic", "frame/examples/offchain-worker", "frame/examples/parallel", @@ -169,7 +171,6 @@ members = [ "primitives/keystore", "primitives/maybe-compressed-blob", "primitives/npos-elections", - "primitives/npos-elections/solution-type", "primitives/npos-elections/fuzzer", "primitives/offchain", "primitives/panic-handler", diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 8c7a20af1568..20b718e2fa8f 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -588,7 +588,7 @@ parameter_types! { .get(DispatchClass::Normal); } -sp_npos_elections::generate_solution_type!( +frame_election_provider_support::generate_solution_type!( #[compact] pub struct NposSolution16::< VoterIndex = u32, diff --git a/frame/election-provider-multi-phase/Cargo.toml b/frame/election-provider-multi-phase/Cargo.toml index 38039f6926b1..25f98d965d86 100644 --- a/frame/election-provider-multi-phase/Cargo.toml +++ b/frame/election-provider-multi-phase/Cargo.toml @@ -46,8 +46,7 @@ sp-core = { version = "6.0.0", default-features = false, path = "../../primitive sp-io = { version = "6.0.0", path = "../../primitives/io" } sp-npos-elections = { version = "4.0.0-dev", default-features = false, path = "../../primitives/npos-elections" } sp-tracing = { version = "5.0.0", path = "../../primitives/tracing" } -frame-election-provider-support = { version = "4.0.0-dev", features = [ -], path = "../election-provider-support" } +frame-election-provider-support = { version = "4.0.0-dev", path = "../election-provider-support" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } frame-benchmarking = { version = "4.0.0-dev", path = "../benchmarking" } diff --git a/frame/election-provider-multi-phase/src/mock.rs b/frame/election-provider-multi-phase/src/mock.rs index 7c7034ac91a8..7c4ef5d8055c 100644 --- a/frame/election-provider-multi-phase/src/mock.rs +++ b/frame/election-provider-multi-phase/src/mock.rs @@ -68,7 +68,7 @@ pub(crate) type BlockNumber = u64; pub(crate) type VoterIndex = u32; pub(crate) type TargetIndex = u16; -sp_npos_elections::generate_solution_type!( +frame_election_provider_support::generate_solution_type!( #[compact] pub struct TestNposSolution::(16) ); diff --git a/frame/election-provider-support/Cargo.toml b/frame/election-provider-support/Cargo.toml index b95bd994fa70..16b79dbb098d 100644 --- a/frame/election-provider-support/Cargo.toml +++ b/frame/election-provider-support/Cargo.toml @@ -21,6 +21,7 @@ sp-npos-elections = { version = "4.0.0-dev", default-features = false, path = ". sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } +frame-election-provider-solution-type = { version = "4.0.0-dev", path = "solution-type" } [dev-dependencies] sp-npos-elections = { version = "4.0.0-dev", path = "../../primitives/npos-elections" } diff --git a/primitives/npos-elections/solution-type/Cargo.toml b/frame/election-provider-support/solution-type/Cargo.toml similarity index 73% rename from primitives/npos-elections/solution-type/Cargo.toml rename to frame/election-provider-support/solution-type/Cargo.toml index 813637e89c33..d489c7b4c10d 100644 --- a/primitives/npos-elections/solution-type/Cargo.toml +++ b/frame/election-provider-support/solution-type/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "sp-npos-elections-solution-type" +name = "frame-election-provider-solution-type" version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2021" @@ -23,7 +23,7 @@ proc-macro-crate = "1.1.0" [dev-dependencies] parity-scale-codec = "3.0.0" scale-info = "2.0.1" -sp-arithmetic = { path = "../../arithmetic", version = "5.0.0"} +sp-arithmetic = { version = "5.0.0", path = "../../../primitives/arithmetic" } # used by generate_solution_type: -sp-npos-elections = { path = "..", version = "4.0.0-dev" } +sp-npos-elections = { version = "4.0.0-dev", path = "../../../primitives/npos-elections" } trybuild = "1.0.53" diff --git a/frame/election-provider-support/solution-type/fuzzer/Cargo.toml b/frame/election-provider-support/solution-type/fuzzer/Cargo.toml new file mode 100644 index 000000000000..f52b7f733262 --- /dev/null +++ b/frame/election-provider-support/solution-type/fuzzer/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "frame-election-solution-type-fuzzer" +version = "2.0.0-alpha.5" +authors = ["Parity Technologies "] +edition = "2021" +license = "Apache-2.0" +homepage = "https://substrate.io" +repository = "https://github.com/paritytech/substrate/" +description = "Fuzzer for phragmén solution type implementation." +publish = false + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +clap = { version = "3.0", features = ["derive"] } +honggfuzz = "0.5" +rand = { version = "0.8", features = ["std", "small_rng"] } + +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } +frame-election-provider-solution-type = { version = "4.0.0-dev", path = ".." } +sp-arithmetic = { version = "5.0.0", path = "../../../../primitives/arithmetic" } +sp-runtime = { version = "6.0.0", path = "../../../../primitives/runtime" } +# used by generate_solution_type: +sp-npos-elections = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/npos-elections" } + +[[bin]] +name = "compact" +path = "src/compact.rs" diff --git a/primitives/npos-elections/fuzzer/src/compact.rs b/frame/election-provider-support/solution-type/fuzzer/src/compact.rs similarity index 94% rename from primitives/npos-elections/fuzzer/src/compact.rs rename to frame/election-provider-support/solution-type/fuzzer/src/compact.rs index 595048575d99..501d241b2b80 100644 --- a/primitives/npos-elections/fuzzer/src/compact.rs +++ b/frame/election-provider-support/solution-type/fuzzer/src/compact.rs @@ -1,5 +1,6 @@ +use frame_election_provider_solution_type::generate_solution_type; use honggfuzz::fuzz; -use sp_npos_elections::{generate_solution_type, sp_arithmetic::Percent}; +use sp_arithmetic::Percent; use sp_runtime::codec::{Encode, Error}; fn main() { diff --git a/primitives/npos-elections/solution-type/src/codec.rs b/frame/election-provider-support/solution-type/src/codec.rs similarity index 100% rename from primitives/npos-elections/solution-type/src/codec.rs rename to frame/election-provider-support/solution-type/src/codec.rs diff --git a/primitives/npos-elections/solution-type/src/from_assignment_helpers.rs b/frame/election-provider-support/solution-type/src/from_assignment_helpers.rs similarity index 100% rename from primitives/npos-elections/solution-type/src/from_assignment_helpers.rs rename to frame/election-provider-support/solution-type/src/from_assignment_helpers.rs diff --git a/primitives/npos-elections/solution-type/src/index_assignment.rs b/frame/election-provider-support/solution-type/src/index_assignment.rs similarity index 100% rename from primitives/npos-elections/solution-type/src/index_assignment.rs rename to frame/election-provider-support/solution-type/src/index_assignment.rs diff --git a/primitives/npos-elections/solution-type/src/lib.rs b/frame/election-provider-support/solution-type/src/lib.rs similarity index 98% rename from primitives/npos-elections/solution-type/src/lib.rs rename to frame/election-provider-support/solution-type/src/lib.rs index 6e632d19e171..3de923cdffd0 100644 --- a/primitives/npos-elections/solution-type/src/lib.rs +++ b/frame/election-provider-support/solution-type/src/lib.rs @@ -57,7 +57,7 @@ pub(crate) fn syn_err(message: &'static str) -> syn::Error { /// type, `u8` target type and `Perbill` accuracy with maximum of 4 edges per voter. /// /// ``` -/// # use sp_npos_elections_solution_type::generate_solution_type; +/// # use frame_election_provider_solution_type::generate_solution_type; /// # use sp_arithmetic::per_things::Perbill; /// generate_solution_type!(pub struct TestSolution::< /// VoterIndex = u16, @@ -100,7 +100,7 @@ pub(crate) fn syn_err(message: &'static str) -> syn::Error { /// for numbers will be used, similar to how `parity-scale-codec`'s `Compact` works. /// /// ``` -/// # use sp_npos_elections_solution_type::generate_solution_type; +/// # use frame_election_provider_solution_type::generate_solution_type; /// # use sp_npos_elections::NposSolution; /// # use sp_arithmetic::per_things::Perbill; /// generate_solution_type!( diff --git a/frame/election-provider-support/solution-type/src/mock.rs b/frame/election-provider-support/solution-type/src/mock.rs new file mode 100644 index 000000000000..c3d032f2eb25 --- /dev/null +++ b/frame/election-provider-support/solution-type/src/mock.rs @@ -0,0 +1,178 @@ +// This file is part of Substrate. + +// Copyright (C) 2019-2022 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. + +//! Mock file for solution-type. + +#![cfg(test)] + +use std::{collections::HashMap, convert::TryInto, hash::Hash, HashSet}; + +use rand::{seq::SliceRandom, Rng}; + +/// The candidate mask allows easy disambiguation between voters and candidates: accounts +/// for which this bit is set are candidates, and without it, are voters. +pub const CANDIDATE_MASK: AccountId = 1 << ((std::mem::size_of::() * 8) - 1); + +pub type TestAccuracy = sp_runtime::Perbill; + +pub fn p(p: u8) -> TestAccuracy { + TestAccuracy::from_percent(p.into()) +} + +pub type MockAssignment = crate::Assignment; +pub type Voter = (AccountId, VoteWeight, Vec); + +crate::generate_solution_type! { + pub struct TestSolution::< + VoterIndex = u32, + TargetIndex = u16, + Accuracy = TestAccuracy, + >(16) +} + +/// Generate voter and assignment lists. Makes no attempt to be realistic about winner or assignment +/// fairness. +/// +/// Maintains these invariants: +/// +/// - candidate ids have `CANDIDATE_MASK` bit set +/// - voter ids do not have `CANDIDATE_MASK` bit set +/// - assignments have the same ordering as voters +/// - `assignments.distribution.iter().map(|(_, frac)| frac).sum() == One::one()` +/// - a coherent set of winners is chosen. +/// - the winner set is a subset of the candidate set. +/// - `assignments.distribution.iter().all(|(who, _)| winners.contains(who))` +pub fn generate_random_votes( + candidate_count: usize, + voter_count: usize, + mut rng: impl Rng, +) -> (Vec, Vec, Vec) { + // cache for fast generation of unique candidate and voter ids + let mut used_ids = HashSet::with_capacity(candidate_count + voter_count); + + // candidates are easy: just a completely random set of IDs + let mut candidates: Vec = Vec::with_capacity(candidate_count); + while candidates.len() < candidate_count { + let mut new = || rng.gen::() | CANDIDATE_MASK; + let mut id = new(); + // insert returns `false` when the value was already present + while !used_ids.insert(id) { + id = new(); + } + candidates.push(id); + } + + // voters are random ids, random weights, random selection from the candidates + let mut voters = Vec::with_capacity(voter_count); + while voters.len() < voter_count { + let mut new = || rng.gen::() & !CANDIDATE_MASK; + let mut id = new(); + // insert returns `false` when the value was already present + while !used_ids.insert(id) { + id = new(); + } + + let vote_weight = rng.gen(); + + // it's not interesting if a voter chooses 0 or all candidates, so rule those cases out. + // also, let's not generate any cases which result in a compact overflow. + let n_candidates_chosen = + rng.gen_range(1, candidates.len().min(::LIMIT)); + + let mut chosen_candidates = Vec::with_capacity(n_candidates_chosen); + chosen_candidates.extend(candidates.choose_multiple(&mut rng, n_candidates_chosen)); + voters.push((id, vote_weight, chosen_candidates)); + } + + // always generate a sensible number of winners: elections are uninteresting if nobody wins, + // or everybody wins + let num_winners = rng.gen_range(1, candidate_count); + let mut winners: HashSet = HashSet::with_capacity(num_winners); + winners.extend(candidates.choose_multiple(&mut rng, num_winners)); + assert_eq!(winners.len(), num_winners); + + let mut assignments = Vec::with_capacity(voters.len()); + for (voter_id, _, votes) in voters.iter() { + let chosen_winners = votes.iter().filter(|vote| winners.contains(vote)).cloned(); + let num_chosen_winners = chosen_winners.clone().count(); + + // distribute the available stake randomly + let stake_distribution = if num_chosen_winners == 0 { + continue + } else { + let mut available_stake = 1000; + let mut stake_distribution = Vec::with_capacity(num_chosen_winners); + for _ in 0..num_chosen_winners - 1 { + let stake = rng.gen_range(0, available_stake).min(1); + stake_distribution.push(TestAccuracy::from_perthousand(stake)); + available_stake -= stake; + } + stake_distribution.push(TestAccuracy::from_perthousand(available_stake)); + stake_distribution.shuffle(&mut rng); + stake_distribution + }; + + assignments.push(MockAssignment { + who: *voter_id, + distribution: chosen_winners.zip(stake_distribution).collect(), + }); + } + + (voters, assignments, candidates) +} + +fn generate_cache(voters: Voters) -> HashMap +where + Voters: Iterator, + Item: Hash + Eq + Copy, +{ + let mut cache = HashMap::new(); + for (idx, voter_id) in voters.enumerate() { + cache.insert(voter_id, idx); + } + cache +} + +/// Create a function that returns the index of a voter in the voters list. +pub fn make_voter_fn(voters: &[Voter]) -> impl Fn(&AccountId) -> Option +where + usize: TryInto, +{ + let cache = generate_cache(voters.iter().map(|(id, _, _)| *id)); + move |who| { + if cache.get(who).is_none() { + println!("WARNING: voter {} will raise InvalidIndex", who); + } + cache.get(who).cloned().and_then(|i| i.try_into().ok()) + } +} + +/// Create a function that returns the index of a candidate in the candidates list. +pub fn make_target_fn( + candidates: &[AccountId], +) -> impl Fn(&AccountId) -> Option +where + usize: TryInto, +{ + let cache = generate_cache(candidates.iter().cloned()); + move |who| { + if cache.get(who).is_none() { + println!("WARNING: target {} will raise InvalidIndex", who); + } + cache.get(who).cloned().and_then(|i| i.try_into().ok()) + } +} diff --git a/primitives/npos-elections/solution-type/src/single_page.rs b/frame/election-provider-support/solution-type/src/single_page.rs similarity index 100% rename from primitives/npos-elections/solution-type/src/single_page.rs rename to frame/election-provider-support/solution-type/src/single_page.rs diff --git a/frame/election-provider-support/solution-type/src/tests.rs b/frame/election-provider-support/solution-type/src/tests.rs new file mode 100644 index 000000000000..f173e425b518 --- /dev/null +++ b/frame/election-provider-support/solution-type/src/tests.rs @@ -0,0 +1,350 @@ +// This file is part of Substrate. + +// Copyright (C) 2019-2022 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. + +//! Tests for solution-type. + +#![cfg(test)] + +use crate::{mock::*, IndexAssignment, NposSolution}; +use rand::SeedableRng; +use std::convert::TryInto; + +mod solution_type { + use super::*; + use codec::{Decode, Encode}; + // these need to come from the same dev-dependency `sp-npos-elections`, not from the crate. + use crate::{generate_solution_type, Assignment, Error as NposError, NposSolution}; + use sp_std::{convert::TryInto, fmt::Debug}; + + #[allow(dead_code)] + mod __private { + // This is just to make sure that the solution can be generated in a scope without any + // imports. + use crate::generate_solution_type; + generate_solution_type!( + #[compact] + struct InnerTestSolutionIsolated::(12) + ); + } + + #[test] + fn solution_struct_works_with_and_without_compact() { + // we use u32 size to make sure compact is smaller. + let without_compact = { + generate_solution_type!( + pub struct InnerTestSolution::< + VoterIndex = u32, + TargetIndex = u32, + Accuracy = TestAccuracy, + >(16) + ); + let solution = InnerTestSolution { + votes1: vec![(2, 20), (4, 40)], + votes2: vec![(1, [(10, p(80))], 11), (5, [(50, p(85))], 51)], + ..Default::default() + }; + + solution.encode().len() + }; + + let with_compact = { + generate_solution_type!( + #[compact] + pub struct InnerTestSolutionCompact::< + VoterIndex = u32, + TargetIndex = u32, + Accuracy = TestAccuracy, + >(16) + ); + let compact = InnerTestSolutionCompact { + votes1: vec![(2, 20), (4, 40)], + votes2: vec![(1, [(10, p(80))], 11), (5, [(50, p(85))], 51)], + ..Default::default() + }; + + compact.encode().len() + }; + + assert!(with_compact < without_compact); + } + + #[test] + fn solution_struct_is_codec() { + let solution = TestSolution { + votes1: vec![(2, 20), (4, 40)], + votes2: vec![(1, [(10, p(80))], 11), (5, [(50, p(85))], 51)], + ..Default::default() + }; + + let encoded = solution.encode(); + + assert_eq!(solution, Decode::decode(&mut &encoded[..]).unwrap()); + assert_eq!(solution.voter_count(), 4); + assert_eq!(solution.edge_count(), 2 + 4); + assert_eq!(solution.unique_targets(), vec![10, 11, 20, 40, 50, 51]); + } + + #[test] + fn remove_voter_works() { + let mut solution = TestSolution { + votes1: vec![(0, 2), (1, 6)], + votes2: vec![(2, [(0, p(80))], 1), (3, [(7, p(85))], 8)], + votes3: vec![(4, [(3, p(50)), (4, p(25))], 5)], + ..Default::default() + }; + + assert!(!solution.remove_voter(11)); + assert!(solution.remove_voter(2)); + assert_eq!( + solution, + TestSolution { + votes1: vec![(0, 2), (1, 6)], + votes2: vec![(3, [(7, p(85))], 8)], + votes3: vec![(4, [(3, p(50)), (4, p(25))], 5,)], + ..Default::default() + }, + ); + + assert!(solution.remove_voter(4)); + assert_eq!( + solution, + TestSolution { + votes1: vec![(0, 2), (1, 6)], + votes2: vec![(3, [(7, p(85))], 8)], + ..Default::default() + }, + ); + + assert!(solution.remove_voter(1)); + assert_eq!( + solution, + TestSolution { + votes1: vec![(0, 2)], + votes2: vec![(3, [(7, p(85))], 8),], + ..Default::default() + }, + ); + } + + #[test] + fn from_and_into_assignment_works() { + let voters = vec![2 as AccountId, 4, 1, 5, 3]; + let targets = vec![ + 10 as AccountId, + 11, + 20, // 2 + 30, + 31, // 4 + 32, + 40, // 6 + 50, + 51, // 8 + ]; + + let assignments = vec![ + Assignment { who: 2 as AccountId, distribution: vec![(20u64, p(100))] }, + Assignment { who: 4, distribution: vec![(40, p(100))] }, + Assignment { who: 1, distribution: vec![(10, p(80)), (11, p(20))] }, + Assignment { who: 5, distribution: vec![(50, p(85)), (51, p(15))] }, + Assignment { who: 3, distribution: vec![(30, p(50)), (31, p(25)), (32, p(25))] }, + ]; + + let voter_index = |a: &AccountId| -> Option { + voters.iter().position(|x| x == a).map(TryInto::try_into).unwrap().ok() + }; + let target_index = |a: &AccountId| -> Option { + targets.iter().position(|x| x == a).map(TryInto::try_into).unwrap().ok() + }; + + let solution = + TestSolution::from_assignment(&assignments, voter_index, target_index).unwrap(); + + // basically number of assignments that it is encoding. + assert_eq!(solution.voter_count(), assignments.len()); + assert_eq!( + solution.edge_count(), + assignments.iter().fold(0, |a, b| a + b.distribution.len()), + ); + + assert_eq!( + solution, + TestSolution { + votes1: vec![(0, 2), (1, 6)], + votes2: vec![(2, [(0, p(80))], 1), (3, [(7, p(85))], 8)], + votes3: vec![(4, [(3, p(50)), (4, p(25))], 5)], + ..Default::default() + } + ); + + assert_eq!(solution.unique_targets(), vec![0, 1, 2, 3, 4, 5, 6, 7, 8]); + + let voter_at = |a: u32| -> Option { + voters.get(>::try_into(a).unwrap()).cloned() + }; + let target_at = |a: u16| -> Option { + targets.get(>::try_into(a).unwrap()).cloned() + }; + + assert_eq!(solution.into_assignment(voter_at, target_at).unwrap(), assignments); + } + + #[test] + fn unique_targets_len_edge_count_works() { + // we don't really care about voters here so all duplicates. This is not invalid per se. + let solution = TestSolution { + votes1: vec![(99, 1), (99, 2)], + votes2: vec![(99, [(3, p(10))], 7), (99, [(4, p(10))], 8)], + votes3: vec![(99, [(11, p(10)), (12, p(10))], 13)], + // ensure the last one is also counted. + votes16: vec![( + 99, + [ + (66, p(10)), + (66, p(10)), + (66, p(10)), + (66, p(10)), + (66, p(10)), + (66, p(10)), + (66, p(10)), + (66, p(10)), + (66, p(10)), + (66, p(10)), + (66, p(10)), + (66, p(10)), + (66, p(10)), + (66, p(10)), + (66, p(10)), + ], + 67, + )], + ..Default::default() + }; + + assert_eq!(solution.unique_targets(), vec![1, 2, 3, 4, 7, 8, 11, 12, 13, 66, 67]); + assert_eq!(solution.edge_count(), 2 + (2 * 2) + 3 + 16); + assert_eq!(solution.voter_count(), 6); + + // this one has some duplicates. + let solution = TestSolution { + votes1: vec![(99, 1), (99, 1)], + votes2: vec![(99, [(3, p(10))], 7), (99, [(4, p(10))], 8)], + votes3: vec![(99, [(11, p(10)), (11, p(10))], 13)], + ..Default::default() + }; + + assert_eq!(solution.unique_targets(), vec![1, 3, 4, 7, 8, 11, 13]); + assert_eq!(solution.edge_count(), 2 + (2 * 2) + 3); + assert_eq!(solution.voter_count(), 5); + } + + #[test] + fn solution_into_assignment_must_report_overflow() { + // in votes2 + let solution = TestSolution { + votes1: Default::default(), + votes2: vec![(0, [(1, p(100))], 2)], + ..Default::default() + }; + + let voter_at = |a: u32| -> Option { Some(a as AccountId) }; + let target_at = |a: u16| -> Option { Some(a as AccountId) }; + + assert_eq!( + solution.into_assignment(&voter_at, &target_at).unwrap_err(), + NposError::SolutionWeightOverflow, + ); + + // in votes3 onwards + let solution = TestSolution { + votes1: Default::default(), + votes2: Default::default(), + votes3: vec![(0, [(1, p(70)), (2, p(80))], 3)], + ..Default::default() + }; + + assert_eq!( + solution.into_assignment(&voter_at, &target_at).unwrap_err(), + NposError::SolutionWeightOverflow, + ); + } + + #[test] + fn target_count_overflow_is_detected() { + let voter_index = |a: &AccountId| -> Option { Some(*a as u32) }; + let target_index = |a: &AccountId| -> Option { Some(*a as u16) }; + + let assignments = vec![Assignment { + who: 1 as AccountId, + distribution: (10..27).map(|i| (i as AccountId, p(i as u8))).collect::>(), + }]; + + let solution = TestSolution::from_assignment(&assignments, voter_index, target_index); + assert_eq!(solution.unwrap_err(), NposError::SolutionTargetOverflow); + } + + #[test] + fn zero_target_count_is_ignored() { + let voters = vec![1 as AccountId, 2]; + let targets = vec![10 as AccountId, 11]; + + let assignments = vec![ + Assignment { who: 1 as AccountId, distribution: vec![(10, p(50)), (11, p(50))] }, + Assignment { who: 2, distribution: vec![] }, + ]; + + let voter_index = |a: &AccountId| -> Option { + voters.iter().position(|x| x == a).map(TryInto::try_into).unwrap().ok() + }; + let target_index = |a: &AccountId| -> Option { + targets.iter().position(|x| x == a).map(TryInto::try_into).unwrap().ok() + }; + + let solution = + TestSolution::from_assignment(&assignments, voter_index, target_index).unwrap(); + + assert_eq!( + solution, + TestSolution { + votes1: Default::default(), + votes2: vec![(0, [(0, p(50))], 1)], + ..Default::default() + } + ); + } +} + +#[test] +fn index_assignments_generate_same_solution_as_plain_assignments() { + let rng = rand::rngs::SmallRng::seed_from_u64(0); + + let (voters, assignments, candidates) = generate_random_votes(1000, 2500, rng); + let voter_index = make_voter_fn(&voters); + let target_index = make_target_fn(&candidates); + + let solution = + TestSolution::from_assignment(&assignments, &voter_index, &target_index).unwrap(); + + let index_assignments = assignments + .into_iter() + .map(|assignment| IndexAssignment::new(&assignment, &voter_index, &target_index)) + .collect::, _>>() + .unwrap(); + + let index_compact = index_assignments.as_slice().try_into().unwrap(); + + assert_eq!(solution, index_compact); +} diff --git a/primitives/npos-elections/solution-type/tests/ui/fail/missing_accuracy.rs b/frame/election-provider-support/solution-type/tests/ui/fail/missing_accuracy.rs similarity index 64% rename from primitives/npos-elections/solution-type/tests/ui/fail/missing_accuracy.rs rename to frame/election-provider-support/solution-type/tests/ui/fail/missing_accuracy.rs index b74b857e4581..22693cd875e1 100644 --- a/primitives/npos-elections/solution-type/tests/ui/fail/missing_accuracy.rs +++ b/frame/election-provider-support/solution-type/tests/ui/fail/missing_accuracy.rs @@ -1,4 +1,4 @@ -use sp_npos_elections_solution_type::generate_solution_type; +use frame_election_provider_solution_type::generate_solution_type; generate_solution_type!(pub struct TestSolution::< VoterIndex = u16, diff --git a/primitives/npos-elections/solution-type/tests/ui/fail/missing_accuracy.stderr b/frame/election-provider-support/solution-type/tests/ui/fail/missing_accuracy.stderr similarity index 100% rename from primitives/npos-elections/solution-type/tests/ui/fail/missing_accuracy.stderr rename to frame/election-provider-support/solution-type/tests/ui/fail/missing_accuracy.stderr diff --git a/primitives/npos-elections/solution-type/tests/ui/fail/missing_target.rs b/frame/election-provider-support/solution-type/tests/ui/fail/missing_target.rs similarity index 63% rename from primitives/npos-elections/solution-type/tests/ui/fail/missing_target.rs rename to frame/election-provider-support/solution-type/tests/ui/fail/missing_target.rs index 4c9cd51a3209..8d0ca927c5fb 100644 --- a/primitives/npos-elections/solution-type/tests/ui/fail/missing_target.rs +++ b/frame/election-provider-support/solution-type/tests/ui/fail/missing_target.rs @@ -1,4 +1,4 @@ -use sp_npos_elections_solution_type::generate_solution_type; +use frame_election_provider_solution_type::generate_solution_type; generate_solution_type!(pub struct TestSolution::< VoterIndex = u16, diff --git a/primitives/npos-elections/solution-type/tests/ui/fail/missing_target.stderr b/frame/election-provider-support/solution-type/tests/ui/fail/missing_target.stderr similarity index 100% rename from primitives/npos-elections/solution-type/tests/ui/fail/missing_target.stderr rename to frame/election-provider-support/solution-type/tests/ui/fail/missing_target.stderr diff --git a/primitives/npos-elections/solution-type/tests/ui/fail/missing_voter.rs b/frame/election-provider-support/solution-type/tests/ui/fail/missing_voter.rs similarity index 63% rename from primitives/npos-elections/solution-type/tests/ui/fail/missing_voter.rs rename to frame/election-provider-support/solution-type/tests/ui/fail/missing_voter.rs index b87037f77f1e..ad4b7f521779 100644 --- a/primitives/npos-elections/solution-type/tests/ui/fail/missing_voter.rs +++ b/frame/election-provider-support/solution-type/tests/ui/fail/missing_voter.rs @@ -1,4 +1,4 @@ -use sp_npos_elections_solution_type::generate_solution_type; +use frame_election_provider_solution_type::generate_solution_type; generate_solution_type!(pub struct TestSolution::< u16, diff --git a/primitives/npos-elections/solution-type/tests/ui/fail/missing_voter.stderr b/frame/election-provider-support/solution-type/tests/ui/fail/missing_voter.stderr similarity index 100% rename from primitives/npos-elections/solution-type/tests/ui/fail/missing_voter.stderr rename to frame/election-provider-support/solution-type/tests/ui/fail/missing_voter.stderr diff --git a/primitives/npos-elections/solution-type/tests/ui/fail/no_annotations.rs b/frame/election-provider-support/solution-type/tests/ui/fail/no_annotations.rs similarity index 58% rename from primitives/npos-elections/solution-type/tests/ui/fail/no_annotations.rs rename to frame/election-provider-support/solution-type/tests/ui/fail/no_annotations.rs index cfca2841db63..87673a382351 100644 --- a/primitives/npos-elections/solution-type/tests/ui/fail/no_annotations.rs +++ b/frame/election-provider-support/solution-type/tests/ui/fail/no_annotations.rs @@ -1,4 +1,4 @@ -use sp_npos_elections_solution_type::generate_solution_type; +use frame_election_provider_solution_type::generate_solution_type; generate_solution_type!(pub struct TestSolution::< u16, diff --git a/primitives/npos-elections/solution-type/tests/ui/fail/no_annotations.stderr b/frame/election-provider-support/solution-type/tests/ui/fail/no_annotations.stderr similarity index 100% rename from primitives/npos-elections/solution-type/tests/ui/fail/no_annotations.stderr rename to frame/election-provider-support/solution-type/tests/ui/fail/no_annotations.stderr diff --git a/primitives/npos-elections/solution-type/tests/ui/fail/swap_voter_target.rs b/frame/election-provider-support/solution-type/tests/ui/fail/swap_voter_target.rs similarity index 66% rename from primitives/npos-elections/solution-type/tests/ui/fail/swap_voter_target.rs rename to frame/election-provider-support/solution-type/tests/ui/fail/swap_voter_target.rs index 443202d11b39..f1d5d0e7bf99 100644 --- a/primitives/npos-elections/solution-type/tests/ui/fail/swap_voter_target.rs +++ b/frame/election-provider-support/solution-type/tests/ui/fail/swap_voter_target.rs @@ -1,4 +1,4 @@ -use sp_npos_elections_solution_type::generate_solution_type; +use frame_election_provider_solution_type::generate_solution_type; generate_solution_type!(pub struct TestSolution::< TargetIndex = u16, diff --git a/primitives/npos-elections/solution-type/tests/ui/fail/swap_voter_target.stderr b/frame/election-provider-support/solution-type/tests/ui/fail/swap_voter_target.stderr similarity index 100% rename from primitives/npos-elections/solution-type/tests/ui/fail/swap_voter_target.stderr rename to frame/election-provider-support/solution-type/tests/ui/fail/swap_voter_target.stderr diff --git a/primitives/npos-elections/solution-type/tests/ui/fail/wrong_attribute.rs b/frame/election-provider-support/solution-type/tests/ui/fail/wrong_attribute.rs similarity index 69% rename from primitives/npos-elections/solution-type/tests/ui/fail/wrong_attribute.rs rename to frame/election-provider-support/solution-type/tests/ui/fail/wrong_attribute.rs index 3008277e36b7..d04cc4a7a966 100644 --- a/primitives/npos-elections/solution-type/tests/ui/fail/wrong_attribute.rs +++ b/frame/election-provider-support/solution-type/tests/ui/fail/wrong_attribute.rs @@ -1,4 +1,4 @@ -use sp_npos_elections_solution_type::generate_solution_type; +use frame_election_provider_solution_type::generate_solution_type; generate_solution_type!( #[pages(1)] pub struct TestSolution::< diff --git a/primitives/npos-elections/solution-type/tests/ui/fail/wrong_attribute.stderr b/frame/election-provider-support/solution-type/tests/ui/fail/wrong_attribute.stderr similarity index 100% rename from primitives/npos-elections/solution-type/tests/ui/fail/wrong_attribute.stderr rename to frame/election-provider-support/solution-type/tests/ui/fail/wrong_attribute.stderr diff --git a/frame/election-provider-support/src/lib.rs b/frame/election-provider-support/src/lib.rs index ff57eacf68fa..1bd10ba09346 100644 --- a/frame/election-provider-support/src/lib.rs +++ b/frame/election-provider-support/src/lib.rs @@ -172,6 +172,7 @@ use sp_runtime::traits::Bounded; use sp_std::{fmt::Debug, prelude::*}; /// Re-export some type as they are used in the interface. +pub use frame_election_provider_solution_type::generate_solution_type; pub use sp_arithmetic::PerThing; pub use sp_npos_elections::{ Assignment, ElectionResult, ExtendedBalance, IdentifierT, PerThing128, Support, Supports, diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index d833ac86fe0b..4c1bb438457e 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -302,7 +302,7 @@ mod pallet; use codec::{Decode, Encode, HasCompact}; use frame_support::{ parameter_types, - traits::{ConstU32, Currency, Get}, + traits::{Currency, Get}, weights::Weight, BoundedVec, EqNoBound, PartialEqNoBound, RuntimeDebugNoBound, }; @@ -861,6 +861,6 @@ pub struct TestBenchmarkingConfig; #[cfg(feature = "std")] impl BenchmarkingConfig for TestBenchmarkingConfig { - type MaxValidators = ConstU32<100>; - type MaxNominators = ConstU32<100>; + type MaxValidators = frame_support::traits::ConstU32<100>; + type MaxNominators = frame_support::traits::ConstU32<100>; } diff --git a/primitives/npos-elections/Cargo.toml b/primitives/npos-elections/Cargo.toml index 3facf32196c7..13edbfe90008 100644 --- a/primitives/npos-elections/Cargo.toml +++ b/primitives/npos-elections/Cargo.toml @@ -17,7 +17,6 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } serde = { version = "1.0.136", optional = true, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../std" } -sp-npos-elections-solution-type = { version = "4.0.0-dev", path = "./solution-type" } sp-arithmetic = { version = "5.0.0", default-features = false, path = "../arithmetic" } sp-core = { version = "6.0.0", default-features = false, path = "../core" } sp-runtime = { version = "6.0.0", path = "../runtime", default-features = false } diff --git a/primitives/npos-elections/fuzzer/Cargo.toml b/primitives/npos-elections/fuzzer/Cargo.toml index 2f2bae2dd44d..71c0c07c3032 100644 --- a/primitives/npos-elections/fuzzer/Cargo.toml +++ b/primitives/npos-elections/fuzzer/Cargo.toml @@ -35,10 +35,6 @@ path = "src/phragmen_balancing.rs" name = "phragmms_balancing" path = "src/phragmms_balancing.rs" -[[bin]] -name = "compact" -path = "src/compact.rs" - [[bin]] name = "phragmen_pjr" path = "src/phragmen_pjr.rs" diff --git a/primitives/npos-elections/src/lib.rs b/primitives/npos-elections/src/lib.rs index 7bd1a4b7f69b..673036c2d19d 100644 --- a/primitives/npos-elections/src/lib.rs +++ b/primitives/npos-elections/src/lib.rs @@ -77,7 +77,9 @@ use scale_info::TypeInfo; use sp_arithmetic::{traits::Zero, Normalizable, PerThing, Rational128, ThresholdOrd}; use sp_core::RuntimeDebug; -use sp_std::{cell::RefCell, cmp::Ordering, collections::btree_map::BTreeMap, prelude::*, rc::Rc}; +use sp_std::{ + cell::RefCell, cmp::Ordering, collections::btree_map::BTreeMap, prelude::*, rc::Rc, vec, +}; use codec::{Decode, Encode, MaxEncodedLen}; #[cfg(feature = "std")] @@ -117,9 +119,6 @@ pub use sp_arithmetic; #[doc(hidden)] pub use sp_std; -// re-export the solution type macro. -pub use sp_npos_elections_solution_type::generate_solution_type; - /// The errors that might occur in the this crate and solution-type. #[derive(Eq, PartialEq, RuntimeDebug)] pub enum Error { diff --git a/primitives/npos-elections/src/mock.rs b/primitives/npos-elections/src/mock.rs index 85c970d7b418..dd85ce9b6dfa 100644 --- a/primitives/npos-elections/src/mock.rs +++ b/primitives/npos-elections/src/mock.rs @@ -19,13 +19,6 @@ #![cfg(test)] -use std::{ - collections::{HashMap, HashSet}, - convert::TryInto, - hash::Hash, -}; - -use rand::{self, seq::SliceRandom, Rng}; use sp_arithmetic::{ traits::{One, SaturatedConversion, Zero}, PerThing, @@ -37,27 +30,6 @@ use crate::{seq_phragmen, Assignment, ElectionResult, ExtendedBalance, PerThing1 pub type AccountId = u64; -/// The candidate mask allows easy disambiguation between voters and candidates: accounts -/// for which this bit is set are candidates, and without it, are voters. -pub const CANDIDATE_MASK: AccountId = 1 << ((std::mem::size_of::() * 8) - 1); - -pub type TestAccuracy = sp_runtime::Perbill; - -crate::generate_solution_type! { - pub struct TestSolution::< - VoterIndex = u32, - TargetIndex = u16, - Accuracy = TestAccuracy, - >(16) -} - -pub fn p(p: u8) -> TestAccuracy { - TestAccuracy::from_percent(p.into()) -} - -pub type MockAssignment = crate::Assignment; -pub type Voter = (AccountId, VoteWeight, Vec); - #[derive(Default, Debug)] pub(crate) struct _Candidate { who: A, @@ -412,136 +384,3 @@ pub(crate) fn build_support_map_float( } supports } - -/// Generate voter and assignment lists. Makes no attempt to be realistic about winner or assignment -/// fairness. -/// -/// Maintains these invariants: -/// -/// - candidate ids have `CANDIDATE_MASK` bit set -/// - voter ids do not have `CANDIDATE_MASK` bit set -/// - assignments have the same ordering as voters -/// - `assignments.distribution.iter().map(|(_, frac)| frac).sum() == One::one()` -/// - a coherent set of winners is chosen. -/// - the winner set is a subset of the candidate set. -/// - `assignments.distribution.iter().all(|(who, _)| winners.contains(who))` -pub fn generate_random_votes( - candidate_count: usize, - voter_count: usize, - mut rng: impl Rng, -) -> (Vec, Vec, Vec) { - // cache for fast generation of unique candidate and voter ids - let mut used_ids = HashSet::with_capacity(candidate_count + voter_count); - - // candidates are easy: just a completely random set of IDs - let mut candidates: Vec = Vec::with_capacity(candidate_count); - while candidates.len() < candidate_count { - let mut new = || rng.gen::() | CANDIDATE_MASK; - let mut id = new(); - // insert returns `false` when the value was already present - while !used_ids.insert(id) { - id = new(); - } - candidates.push(id); - } - - // voters are random ids, random weights, random selection from the candidates - let mut voters = Vec::with_capacity(voter_count); - while voters.len() < voter_count { - let mut new = || rng.gen::() & !CANDIDATE_MASK; - let mut id = new(); - // insert returns `false` when the value was already present - while !used_ids.insert(id) { - id = new(); - } - - let vote_weight = rng.gen(); - - // it's not interesting if a voter chooses 0 or all candidates, so rule those cases out. - // also, let's not generate any cases which result in a compact overflow. - let n_candidates_chosen = - rng.gen_range(1, candidates.len().min(::LIMIT)); - - let mut chosen_candidates = Vec::with_capacity(n_candidates_chosen); - chosen_candidates.extend(candidates.choose_multiple(&mut rng, n_candidates_chosen)); - voters.push((id, vote_weight, chosen_candidates)); - } - - // always generate a sensible number of winners: elections are uninteresting if nobody wins, - // or everybody wins - let num_winners = rng.gen_range(1, candidate_count); - let mut winners: HashSet = HashSet::with_capacity(num_winners); - winners.extend(candidates.choose_multiple(&mut rng, num_winners)); - assert_eq!(winners.len(), num_winners); - - let mut assignments = Vec::with_capacity(voters.len()); - for (voter_id, _, votes) in voters.iter() { - let chosen_winners = votes.iter().filter(|vote| winners.contains(vote)).cloned(); - let num_chosen_winners = chosen_winners.clone().count(); - - // distribute the available stake randomly - let stake_distribution = if num_chosen_winners == 0 { - continue - } else { - let mut available_stake = 1000; - let mut stake_distribution = Vec::with_capacity(num_chosen_winners); - for _ in 0..num_chosen_winners - 1 { - let stake = rng.gen_range(0, available_stake).min(1); - stake_distribution.push(TestAccuracy::from_perthousand(stake)); - available_stake -= stake; - } - stake_distribution.push(TestAccuracy::from_perthousand(available_stake)); - stake_distribution.shuffle(&mut rng); - stake_distribution - }; - - assignments.push(MockAssignment { - who: *voter_id, - distribution: chosen_winners.zip(stake_distribution).collect(), - }); - } - - (voters, assignments, candidates) -} - -fn generate_cache(voters: Voters) -> HashMap -where - Voters: Iterator, - Item: Hash + Eq + Copy, -{ - let mut cache = HashMap::new(); - for (idx, voter_id) in voters.enumerate() { - cache.insert(voter_id, idx); - } - cache -} - -/// Create a function that returns the index of a voter in the voters list. -pub fn make_voter_fn(voters: &[Voter]) -> impl Fn(&AccountId) -> Option -where - usize: TryInto, -{ - let cache = generate_cache(voters.iter().map(|(id, _, _)| *id)); - move |who| { - if cache.get(who).is_none() { - println!("WARNING: voter {} will raise InvalidIndex", who); - } - cache.get(who).cloned().and_then(|i| i.try_into().ok()) - } -} - -/// Create a function that returns the index of a candidate in the candidates list. -pub fn make_target_fn( - candidates: &[AccountId], -) -> impl Fn(&AccountId) -> Option -where - usize: TryInto, -{ - let cache = generate_cache(candidates.iter().cloned()); - move |who| { - if cache.get(who).is_none() { - println!("WARNING: target {} will raise InvalidIndex", who); - } - cache.get(who).cloned().and_then(|i| i.try_into().ok()) - } -} diff --git a/primitives/npos-elections/src/tests.rs b/primitives/npos-elections/src/tests.rs index b199fdd1af77..1cf5ea8a2492 100644 --- a/primitives/npos-elections/src/tests.rs +++ b/primitives/npos-elections/src/tests.rs @@ -19,12 +19,9 @@ use crate::{ balancing, helpers::*, mock::*, seq_phragmen, seq_phragmen_core, setup_inputs, to_support_map, - Assignment, ElectionResult, ExtendedBalance, IndexAssignment, NposSolution, StakedAssignment, - Support, Voter, + Assignment, ElectionResult, ExtendedBalance, StakedAssignment, Support, Voter, }; -use rand::{self, SeedableRng}; use sp_arithmetic::{PerU16, Perbill, Percent, Permill}; -use std::convert::TryInto; use substrate_test_utils::assert_eq_uvec; #[test] @@ -919,329 +916,3 @@ mod score { assert!(ElectionScore::from([10, 5, 15]) > ElectionScore::from([10, 5, 25])); } } - -mod solution_type { - use super::*; - use codec::{Decode, Encode}; - // these need to come from the same dev-dependency `sp-npos-elections`, not from the crate. - use crate::{generate_solution_type, Assignment, Error as NposError, NposSolution}; - use sp_std::{convert::TryInto, fmt::Debug}; - - #[allow(dead_code)] - mod __private { - // This is just to make sure that the solution can be generated in a scope without any - // imports. - use crate::generate_solution_type; - generate_solution_type!( - #[compact] - struct InnerTestSolutionIsolated::(12) - ); - } - - #[test] - fn solution_struct_works_with_and_without_compact() { - // we use u32 size to make sure compact is smaller. - let without_compact = { - generate_solution_type!( - pub struct InnerTestSolution::< - VoterIndex = u32, - TargetIndex = u32, - Accuracy = TestAccuracy, - >(16) - ); - let solution = InnerTestSolution { - votes1: vec![(2, 20), (4, 40)], - votes2: vec![(1, [(10, p(80))], 11), (5, [(50, p(85))], 51)], - ..Default::default() - }; - - solution.encode().len() - }; - - let with_compact = { - generate_solution_type!( - #[compact] - pub struct InnerTestSolutionCompact::< - VoterIndex = u32, - TargetIndex = u32, - Accuracy = TestAccuracy, - >(16) - ); - let compact = InnerTestSolutionCompact { - votes1: vec![(2, 20), (4, 40)], - votes2: vec![(1, [(10, p(80))], 11), (5, [(50, p(85))], 51)], - ..Default::default() - }; - - compact.encode().len() - }; - - assert!(with_compact < without_compact); - } - - #[test] - fn solution_struct_is_codec() { - let solution = TestSolution { - votes1: vec![(2, 20), (4, 40)], - votes2: vec![(1, [(10, p(80))], 11), (5, [(50, p(85))], 51)], - ..Default::default() - }; - - let encoded = solution.encode(); - - assert_eq!(solution, Decode::decode(&mut &encoded[..]).unwrap()); - assert_eq!(solution.voter_count(), 4); - assert_eq!(solution.edge_count(), 2 + 4); - assert_eq!(solution.unique_targets(), vec![10, 11, 20, 40, 50, 51]); - } - - #[test] - fn remove_voter_works() { - let mut solution = TestSolution { - votes1: vec![(0, 2), (1, 6)], - votes2: vec![(2, [(0, p(80))], 1), (3, [(7, p(85))], 8)], - votes3: vec![(4, [(3, p(50)), (4, p(25))], 5)], - ..Default::default() - }; - - assert!(!solution.remove_voter(11)); - assert!(solution.remove_voter(2)); - assert_eq!( - solution, - TestSolution { - votes1: vec![(0, 2), (1, 6)], - votes2: vec![(3, [(7, p(85))], 8)], - votes3: vec![(4, [(3, p(50)), (4, p(25))], 5,)], - ..Default::default() - }, - ); - - assert!(solution.remove_voter(4)); - assert_eq!( - solution, - TestSolution { - votes1: vec![(0, 2), (1, 6)], - votes2: vec![(3, [(7, p(85))], 8)], - ..Default::default() - }, - ); - - assert!(solution.remove_voter(1)); - assert_eq!( - solution, - TestSolution { - votes1: vec![(0, 2)], - votes2: vec![(3, [(7, p(85))], 8),], - ..Default::default() - }, - ); - } - - #[test] - fn from_and_into_assignment_works() { - let voters = vec![2 as AccountId, 4, 1, 5, 3]; - let targets = vec![ - 10 as AccountId, - 11, - 20, // 2 - 30, - 31, // 4 - 32, - 40, // 6 - 50, - 51, // 8 - ]; - - let assignments = vec![ - Assignment { who: 2 as AccountId, distribution: vec![(20u64, p(100))] }, - Assignment { who: 4, distribution: vec![(40, p(100))] }, - Assignment { who: 1, distribution: vec![(10, p(80)), (11, p(20))] }, - Assignment { who: 5, distribution: vec![(50, p(85)), (51, p(15))] }, - Assignment { who: 3, distribution: vec![(30, p(50)), (31, p(25)), (32, p(25))] }, - ]; - - let voter_index = |a: &AccountId| -> Option { - voters.iter().position(|x| x == a).map(TryInto::try_into).unwrap().ok() - }; - let target_index = |a: &AccountId| -> Option { - targets.iter().position(|x| x == a).map(TryInto::try_into).unwrap().ok() - }; - - let solution = - TestSolution::from_assignment(&assignments, voter_index, target_index).unwrap(); - - // basically number of assignments that it is encoding. - assert_eq!(solution.voter_count(), assignments.len()); - assert_eq!( - solution.edge_count(), - assignments.iter().fold(0, |a, b| a + b.distribution.len()), - ); - - assert_eq!( - solution, - TestSolution { - votes1: vec![(0, 2), (1, 6)], - votes2: vec![(2, [(0, p(80))], 1), (3, [(7, p(85))], 8)], - votes3: vec![(4, [(3, p(50)), (4, p(25))], 5)], - ..Default::default() - } - ); - - assert_eq!(solution.unique_targets(), vec![0, 1, 2, 3, 4, 5, 6, 7, 8]); - - let voter_at = |a: u32| -> Option { - voters.get(>::try_into(a).unwrap()).cloned() - }; - let target_at = |a: u16| -> Option { - targets.get(>::try_into(a).unwrap()).cloned() - }; - - assert_eq!(solution.into_assignment(voter_at, target_at).unwrap(), assignments); - } - - #[test] - fn unique_targets_len_edge_count_works() { - // we don't really care about voters here so all duplicates. This is not invalid per se. - let solution = TestSolution { - votes1: vec![(99, 1), (99, 2)], - votes2: vec![(99, [(3, p(10))], 7), (99, [(4, p(10))], 8)], - votes3: vec![(99, [(11, p(10)), (12, p(10))], 13)], - // ensure the last one is also counted. - votes16: vec![( - 99, - [ - (66, p(10)), - (66, p(10)), - (66, p(10)), - (66, p(10)), - (66, p(10)), - (66, p(10)), - (66, p(10)), - (66, p(10)), - (66, p(10)), - (66, p(10)), - (66, p(10)), - (66, p(10)), - (66, p(10)), - (66, p(10)), - (66, p(10)), - ], - 67, - )], - ..Default::default() - }; - - assert_eq!(solution.unique_targets(), vec![1, 2, 3, 4, 7, 8, 11, 12, 13, 66, 67]); - assert_eq!(solution.edge_count(), 2 + (2 * 2) + 3 + 16); - assert_eq!(solution.voter_count(), 6); - - // this one has some duplicates. - let solution = TestSolution { - votes1: vec![(99, 1), (99, 1)], - votes2: vec![(99, [(3, p(10))], 7), (99, [(4, p(10))], 8)], - votes3: vec![(99, [(11, p(10)), (11, p(10))], 13)], - ..Default::default() - }; - - assert_eq!(solution.unique_targets(), vec![1, 3, 4, 7, 8, 11, 13]); - assert_eq!(solution.edge_count(), 2 + (2 * 2) + 3); - assert_eq!(solution.voter_count(), 5); - } - - #[test] - fn solution_into_assignment_must_report_overflow() { - // in votes2 - let solution = TestSolution { - votes1: Default::default(), - votes2: vec![(0, [(1, p(100))], 2)], - ..Default::default() - }; - - let voter_at = |a: u32| -> Option { Some(a as AccountId) }; - let target_at = |a: u16| -> Option { Some(a as AccountId) }; - - assert_eq!( - solution.into_assignment(&voter_at, &target_at).unwrap_err(), - NposError::SolutionWeightOverflow, - ); - - // in votes3 onwards - let solution = TestSolution { - votes1: Default::default(), - votes2: Default::default(), - votes3: vec![(0, [(1, p(70)), (2, p(80))], 3)], - ..Default::default() - }; - - assert_eq!( - solution.into_assignment(&voter_at, &target_at).unwrap_err(), - NposError::SolutionWeightOverflow, - ); - } - - #[test] - fn target_count_overflow_is_detected() { - let voter_index = |a: &AccountId| -> Option { Some(*a as u32) }; - let target_index = |a: &AccountId| -> Option { Some(*a as u16) }; - - let assignments = vec![Assignment { - who: 1 as AccountId, - distribution: (10..27).map(|i| (i as AccountId, p(i as u8))).collect::>(), - }]; - - let solution = TestSolution::from_assignment(&assignments, voter_index, target_index); - assert_eq!(solution.unwrap_err(), NposError::SolutionTargetOverflow); - } - - #[test] - fn zero_target_count_is_ignored() { - let voters = vec![1 as AccountId, 2]; - let targets = vec![10 as AccountId, 11]; - - let assignments = vec![ - Assignment { who: 1 as AccountId, distribution: vec![(10, p(50)), (11, p(50))] }, - Assignment { who: 2, distribution: vec![] }, - ]; - - let voter_index = |a: &AccountId| -> Option { - voters.iter().position(|x| x == a).map(TryInto::try_into).unwrap().ok() - }; - let target_index = |a: &AccountId| -> Option { - targets.iter().position(|x| x == a).map(TryInto::try_into).unwrap().ok() - }; - - let solution = - TestSolution::from_assignment(&assignments, voter_index, target_index).unwrap(); - - assert_eq!( - solution, - TestSolution { - votes1: Default::default(), - votes2: vec![(0, [(0, p(50))], 1)], - ..Default::default() - } - ); - } -} - -#[test] -fn index_assignments_generate_same_solution_as_plain_assignments() { - let rng = rand::rngs::SmallRng::seed_from_u64(0); - - let (voters, assignments, candidates) = generate_random_votes(1000, 2500, rng); - let voter_index = make_voter_fn(&voters); - let target_index = make_target_fn(&candidates); - - let solution = - TestSolution::from_assignment(&assignments, &voter_index, &target_index).unwrap(); - - let index_assignments = assignments - .into_iter() - .map(|assignment| IndexAssignment::new(&assignment, &voter_index, &target_index)) - .collect::, _>>() - .unwrap(); - - let index_compact = index_assignments.as_slice().try_into().unwrap(); - - assert_eq!(solution, index_compact); -} From 345e3b1fcbbb0c479a031c45859d7154e7c4b5f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Mon, 14 Mar 2022 12:48:29 +0100 Subject: [PATCH 586/695] shell.nix: Update to a newer nightly (#11028) --- shell.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shell.nix b/shell.nix index a86af005383f..023946ce16de 100644 --- a/shell.nix +++ b/shell.nix @@ -2,10 +2,10 @@ let mozillaOverlay = import (builtins.fetchGit { url = "https://github.com/mozilla/nixpkgs-mozilla.git"; - rev = "4a07484cf0e49047f82d83fd119acffbad3b235f"; + rev = "15b7a05f20aab51c4ffbefddb1b448e862dccb7d"; }); nixpkgs = import { overlays = [ mozillaOverlay ]; }; - rust-nightly = with nixpkgs; ((rustChannelOf { date = "2021-09-10"; channel = "nightly"; }).rust.override { + rust-nightly = with nixpkgs; ((rustChannelOf { date = "2022-02-10"; channel = "nightly"; }).rust.override { extensions = [ "rust-src" ]; targets = [ "wasm32-unknown-unknown" ]; }); From 8d456dcdcbddff022beacedbf9b0de07c3cd09b6 Mon Sep 17 00:00:00 2001 From: driemworks Date: Mon, 14 Mar 2022 21:27:49 -0500 Subject: [PATCH 587/695] update chain ext --- bin/node-template/runtime/src/lib.rs | 30 ++++++++++------------------ 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index a112a2c82256..5331b04a344a 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -855,6 +855,11 @@ impl ChainExtension for IrisExtension { UncheckedFrom<::Hash> + AsRef<[u8]>, { match func_id { + trace!( + target: "runtime", + "[ChainExtension]|call|func_id:{:}", + func_id + ); // IrisAssets::transfer_asset 1 => { let mut env = env.buf_in_buf_out(); @@ -864,27 +869,22 @@ impl ChainExtension for IrisExtension { crate::IrisAssets::transfer_asset( origin, sp_runtime::MultiAddress::Id(target), asset_id, amount, )?; - trace!( - target: "runtime", - "[ChainExtension]|call|func_id:{:}", - func_id - ); - }, + } // IrisAssets::mint 2 => { let mut env = env.buf_in_buf_out(); let (caller_account, target, asset_id, amount): (AccountId, AccountId, u32, u64) = env.read_as()?; let origin: Origin = system::RawOrigin::Signed(caller_account).into(); - crate::IrisAssets::mint( + crate::IrisAssets::mint( origin, sp_runtime::MultiAddress::Id(target), asset_id, amount, )?; - trace!( + trace!( target: "runtime", "[ChainExtension]|call|func_id:{:}", func_id ); - }, + } // IrisLedger::lock_currrency 3 => { let mut env = env.buf_in_buf_out(); @@ -894,11 +894,6 @@ impl ChainExtension for IrisExtension { crate::IrisLedger::lock_currency( origin, amount.into(), )?; - trace!( - target: "runtime", - "[ChainExtension]|call|func_id:{:}", - func_id - ); }, // IrisLedger::unlock_currency_and_transfer 4 => { @@ -909,12 +904,7 @@ impl ChainExtension for IrisExtension { crate::IrisLedger::unlock_currency_and_transfer( origin, target, )?; - trace!( - target: "runtime", - "[ChainExtension]|call|func_id:{:}", - func_id - ); - }, + } _ => { // env.write(&random_slice, false, None).map_err(|_| { // DispatchError::Other("ChainExtension failed to call transfer_assets") From 99661cbc683d42346706b771966a672637bfd4ca Mon Sep 17 00:00:00 2001 From: driemworks Date: Mon, 14 Mar 2022 21:28:22 -0500 Subject: [PATCH 588/695] update naming, formatting, start tests --- .../pallets/iris-assets/src/lib.rs | 9 ++++++-- .../pallets/iris-ledger/src/lib.rs | 15 ++++++------- .../pallets/iris-ledger/src/tests.rs | 21 ++++++++++++++++++- 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/bin/node-template/pallets/iris-assets/src/lib.rs b/bin/node-template/pallets/iris-assets/src/lib.rs index f33d0ce20129..ce899c65ceb7 100644 --- a/bin/node-template/pallets/iris-assets/src/lib.rs +++ b/bin/node-template/pallets/iris-assets/src/lib.rs @@ -257,8 +257,13 @@ pub mod pallet { let new_origin = system::RawOrigin::Signed(who.clone()).into(); let beneficiary_accountid = T::Lookup::lookup(beneficiary.clone())?; - >::mint(new_origin, asset_id.clone(), beneficiary.clone(), amount) - .map_err(|_| Error::::CantMintAssets)?; + >::mint( + new_origin, + asset_id.clone(), + beneficiary.clone(), + amount + )?; + >::insert(beneficiary_accountid.clone(), asset_id.clone(), who.clone()); Self::deposit_event(Event::AssetCreated(asset_id.clone())); diff --git a/bin/node-template/pallets/iris-ledger/src/lib.rs b/bin/node-template/pallets/iris-ledger/src/lib.rs index cf44c1b26b6e..bb1020a8a94c 100644 --- a/bin/node-template/pallets/iris-ledger/src/lib.rs +++ b/bin/node-template/pallets/iris-ledger/src/lib.rs @@ -87,12 +87,10 @@ pub mod pallet { // TODO: Move this to it's own pallet? #[pallet::storage] #[pallet::getter(fn iris_ledger)] - pub(super) type IrisLedger = StorageDoubleMap< + pub(super) type Ledger = StorageMap< _, Blake2_128Concat, T::AccountId, - Blake2_128Concat, - LockIdentifier, BalanceOf, ValueQuery, >; @@ -130,7 +128,7 @@ pub mod pallet { amount.clone(), WithdrawReasons::all(), ); - >::insert(who.clone(), IRIS_LOCK_ID, amount.clone()); + >::insert(who.clone(), amount.clone()); Self::deposit_event(Event::Locked(who, amount)); Ok(()) } @@ -145,9 +143,8 @@ pub mod pallet { target: T::AccountId, ) -> DispatchResult { let who = ensure_signed(origin)?; - // let new_origin: OriginFor = system::RawOrigin::Signed(who.clone()).into(); - // assume ammount in ledger matches locked amount for now...... - let amount = >::get(who.clone(), IRIS_LOCK_ID); + // assume ammount in ledger matches locked amount for now + let amount = >::get(who.clone()); T::IrisCurrency::remove_lock(IRIS_LOCK_ID, &who); T::IrisCurrency::transfer( @@ -155,9 +152,9 @@ pub mod pallet { &target, amount, KeepAlive, - )?; + ); - >::remove(who.clone(), IRIS_LOCK_ID); + >::remove(who.clone()); Self::deposit_event(Event::Unlocked(who)); Ok(()) } diff --git a/bin/node-template/pallets/iris-ledger/src/tests.rs b/bin/node-template/pallets/iris-ledger/src/tests.rs index ec80244f4426..f2d860a7d35d 100644 --- a/bin/node-template/pallets/iris-ledger/src/tests.rs +++ b/bin/node-template/pallets/iris-ledger/src/tests.rs @@ -14,8 +14,27 @@ fn iris_ledger_initial_state() { // Given: The node is initialized at block 0 // When: I query runtime storagey let ledger = crate::Ledger::::get(); - let len = data_queue.len(); + let len = ledger.len(); // Then: Runtime storage is empty assert_eq!(len, 0); }); } + +#[test] +fn iris_ledger_can_lock() { + let (p, _) = sp_core::sr25519::Pair::generate(); + let pairs = vec![(p.clone().public(), 10)]; + new_test_ext_funded(pairs).execute_with(|| { + assert_ok!( + Origin::signed(p.clone().public()), + 1, + ); + let mut locked_amount = crate::Ledger::::get(p.public().clone()); + assert_eq!(1, locked_amount); + }); +} + +#[test] +fn iris_ledger_can_unlock_and_transfer() { + +} From 5463591f60fdc4870165cb2025174153fae0bd7a Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Tue, 15 Mar 2022 13:48:29 +0100 Subject: [PATCH 589/695] Update lockfile (#11035) Signed-off-by: Oliver Tale-Yazdi --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 9f4d2f21cf9c..82dea83813d0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2196,7 +2196,7 @@ dependencies = [ name = "frame-election-solution-type-fuzzer" version = "2.0.0-alpha.5" dependencies = [ - "clap 3.0.7", + "clap 3.1.6", "frame-election-provider-solution-type", "honggfuzz", "parity-scale-codec", From 80a90e70eec6368fc95ae5bdf03ef57fb61ab378 Mon Sep 17 00:00:00 2001 From: Daan Schutte Date: Tue, 15 Mar 2022 17:21:16 +0300 Subject: [PATCH 590/695] Additional `benchmark-storage` flags (#11004) * Fix typos * Enable overwriting handlebars template * Optionally name json output or disable json altogether * Don't write to json by default * Include block id in handlebars output * Include warmups for write benchmarks * PR comments * Drop unnecessary file extension * Use more appropriate types * Use more appropriate error message * More use of more appropriate types * Rework write benchmark warmups * Run same benchmark for both read and write --- utils/frame/benchmarking-cli/src/lib.rs | 2 +- .../frame/benchmarking-cli/src/storage/cmd.rs | 63 ++++++++++++++++--- .../benchmarking-cli/src/storage/read.rs | 11 ---- .../benchmarking-cli/src/storage/record.rs | 14 +++-- .../benchmarking-cli/src/storage/template.rs | 32 +++++++--- .../benchmarking-cli/src/storage/weights.hbs | 1 + 6 files changed, 93 insertions(+), 30 deletions(-) diff --git a/utils/frame/benchmarking-cli/src/lib.rs b/utils/frame/benchmarking-cli/src/lib.rs index 640b1770f5c3..9815fe88a7f0 100644 --- a/utils/frame/benchmarking-cli/src/lib.rs +++ b/utils/frame/benchmarking-cli/src/lib.rs @@ -67,7 +67,7 @@ pub struct BenchmarkCmd { #[clap(long = "json")] pub json_output: bool, - /// Write the raw results in JSON format into the give file. + /// Write the raw results in JSON format into the given file. #[clap(long, conflicts_with = "json-output")] pub json_file: Option, diff --git a/utils/frame/benchmarking-cli/src/storage/cmd.rs b/utils/frame/benchmarking-cli/src/storage/cmd.rs index 4376b616286a..ad7d13a2022e 100644 --- a/utils/frame/benchmarking-cli/src/storage/cmd.rs +++ b/utils/frame/benchmarking-cli/src/storage/cmd.rs @@ -20,6 +20,7 @@ use sc_client_api::{Backend as ClientBackend, StorageProvider, UsageProvider}; use sc_client_db::DbHash; use sc_service::Configuration; use sp_blockchain::HeaderBackend; +use sp_core::storage::StorageKey; use sp_database::{ColumnId, Database}; use sp_runtime::traits::{Block as BlockT, HashFor}; use sp_state_machine::Storage; @@ -29,7 +30,8 @@ use clap::{Args, Parser}; use log::info; use rand::prelude::*; use serde::Serialize; -use std::{fmt::Debug, sync::Arc}; +use sp_runtime::generic::BlockId; +use std::{fmt::Debug, path::PathBuf, sync::Arc}; use super::{record::StatSelect, template::TemplateData}; @@ -58,8 +60,8 @@ pub struct StorageCmd { pub struct StorageParams { /// Path to write the *weight* file to. Can be a file or directory. /// For substrate this should be `frame/support/src/weights`. - #[clap(long, default_value = ".")] - pub weight_path: String, + #[clap(long)] + pub weight_path: Option, /// Select a specific metric to calculate the final weight output. #[clap(long = "metric", default_value = "average")] @@ -83,8 +85,19 @@ pub struct StorageParams { #[clap(long)] pub skip_write: bool, + /// Specify the Handlebars template to use for outputting benchmark results. + #[clap(long)] + pub template_path: Option, + + /// Path to write the raw 'read' results in JSON format to. Can be a file or directory. + #[clap(long)] + pub json_read_path: Option, + + /// Path to write the raw 'write' results in JSON format to. Can be a file or directory. + #[clap(long)] + pub json_write_path: Option, + /// Rounds of warmups before measuring. - /// Only supported for `read` benchmarks. #[clap(long, default_value = "1")] pub warmups: u32, @@ -115,23 +128,32 @@ impl StorageCmd { { let mut template = TemplateData::new(&cfg, &self.params); + let block_id = BlockId::::Number(client.usage_info().chain.best_number); + template.set_block_number(block_id.to_string()); + if !self.params.skip_read { + self.bench_warmup(&client)?; let record = self.bench_read(client.clone())?; - record.save_json(&cfg, "read")?; + if let Some(path) = &self.params.json_read_path { + record.save_json(&cfg, path, "read")?; + } let stats = record.calculate_stats()?; info!("Time summary [ns]:\n{:?}\nValue size summary:\n{:?}", stats.0, stats.1); template.set_stats(Some(stats), None)?; } if !self.params.skip_write { + self.bench_warmup(&client)?; let record = self.bench_write(client, db, storage)?; - record.save_json(&cfg, "write")?; + if let Some(path) = &self.params.json_write_path { + record.save_json(&cfg, path, "write")?; + } let stats = record.calculate_stats()?; info!("Time summary [ns]:\n{:?}\nValue size summary:\n{:?}", stats.0, stats.1); template.set_stats(None, Some(stats))?; } - template.write(&self.params.weight_path) + template.write(&self.params.weight_path, &self.params.template_path) } /// Returns the specified state version. @@ -149,6 +171,33 @@ impl StorageCmd { info!("Using seed {}", seed); StdRng::seed_from_u64(seed) } + + /// Run some rounds of the (read) benchmark as warmup. + /// See `frame_benchmarking_cli::storage::read::bench_read` for detailed comments. + fn bench_warmup(&self, client: &Arc) -> Result<()> + where + C: UsageProvider + StorageProvider, + B: BlockT + Debug, + BA: ClientBackend, + { + let block = BlockId::Number(client.usage_info().chain.best_number); + let empty_prefix = StorageKey(Vec::new()); + let mut keys = client.storage_keys(&block, &empty_prefix)?; + let mut rng = Self::setup_rng(); + keys.shuffle(&mut rng); + + for i in 0..self.params.warmups { + info!("Warmup round {}/{}", i + 1, self.params.warmups); + for key in keys.clone() { + let _ = client + .storage(&block, &key) + .expect("Checked above to exist") + .ok_or("Value unexpectedly empty"); + } + } + + Ok(()) + } } // Boilerplate diff --git a/utils/frame/benchmarking-cli/src/storage/read.rs b/utils/frame/benchmarking-cli/src/storage/read.rs index 3974c4010f63..ca506202e106 100644 --- a/utils/frame/benchmarking-cli/src/storage/read.rs +++ b/utils/frame/benchmarking-cli/src/storage/read.rs @@ -49,17 +49,6 @@ impl StorageCmd { let mut rng = Self::setup_rng(); keys.shuffle(&mut rng); - // Run some rounds of the benchmark as warmup. - for i in 0..self.params.warmups { - info!("Warmup round {}/{}", i + 1, self.params.warmups); - for key in keys.clone() { - let _ = client - .storage(&block, &key) - .expect("Checked above to exist") - .ok_or("Value unexpectedly empty")?; - } - } - // Interesting part here: // Read all the keys in the database and measure the time it takes to access each. info!("Reading {} keys", keys.len()); diff --git a/utils/frame/benchmarking-cli/src/storage/record.rs b/utils/frame/benchmarking-cli/src/storage/record.rs index 00a613c71300..667274bef0dd 100644 --- a/utils/frame/benchmarking-cli/src/storage/record.rs +++ b/utils/frame/benchmarking-cli/src/storage/record.rs @@ -22,7 +22,7 @@ use sc_service::Configuration; use log::info; use serde::Serialize; -use std::{fmt, fs, result, str::FromStr, time::Duration}; +use std::{fmt, fs, path::PathBuf, result, str::FromStr, time::Duration}; /// Raw output of a Storage benchmark. #[derive(Debug, Default, Clone, Serialize)] @@ -95,12 +95,18 @@ impl BenchRecord { Ok((time, size)) // The swap of time/size here is intentional. } - /// Saves the raw results in a json file in the current directory. + /// Unless a path is specified, saves the raw results in a json file in the current directory. /// Prefixes it with the DB name and suffixed with `path_suffix`. - pub fn save_json(&self, cfg: &Configuration, path_suffix: &str) -> Result<()> { - let path = format!("{}_{}.json", cfg.database, path_suffix).to_lowercase(); + pub fn save_json(&self, cfg: &Configuration, out_path: &PathBuf, suffix: &str) -> Result<()> { + let mut path = PathBuf::from(out_path); + if path.is_dir() || path.as_os_str().is_empty() { + path.push(&format!("{}_{}", cfg.database, suffix).to_lowercase()); + path.set_extension("json"); + } + let json = serde_json::to_string_pretty(&self) .map_err(|e| format!("Serializing as JSON: {:?}", e))?; + fs::write(&path, json)?; info!("Raw data written to {:?}", fs::canonicalize(&path)?); Ok(()) diff --git a/utils/frame/benchmarking-cli/src/storage/template.rs b/utils/frame/benchmarking-cli/src/storage/template.rs index 56e0869a914a..13b825d891a5 100644 --- a/utils/frame/benchmarking-cli/src/storage/template.rs +++ b/utils/frame/benchmarking-cli/src/storage/template.rs @@ -32,6 +32,8 @@ static TEMPLATE: &str = include_str!("./weights.hbs"); pub(crate) struct TemplateData { /// Name of the database used. db_name: String, + /// Block number that was used. + block_number: String, /// Name of the runtime. Taken from the chain spec. runtime_name: String, /// Version of the benchmarking CLI used. @@ -85,28 +87,44 @@ impl TemplateData { Ok(()) } - /// Filles out the `weights.hbs` HBS template with its own data. + /// Sets the block id that was used. + pub fn set_block_number(&mut self, block_number: String) { + self.block_number = block_number + } + + /// Fills out the `weights.hbs` or specified HBS template with its own data. /// Writes the result to `path` which can be a directory or file. - pub fn write(&self, path: &str) -> Result<()> { + pub fn write(&self, path: &Option, hbs_template: &Option) -> Result<()> { let mut handlebars = handlebars::Handlebars::new(); // Format large integers with underscore. handlebars.register_helper("underscore", Box::new(crate::writer::UnderscoreHelper)); // Don't HTML escape any characters. handlebars.register_escape_fn(|s| -> String { s.to_string() }); + // Use custom template if provided. + let template = match hbs_template { + Some(template) if template.is_file() => fs::read_to_string(template)?, + Some(_) => return Err("Handlebars template is not a valid file!".into()), + None => TEMPLATE.to_string(), + }; let out_path = self.build_path(path); let mut fd = fs::File::create(&out_path)?; info!("Writing weights to {:?}", fs::canonicalize(&out_path)?); + handlebars - .render_template_to_write(&TEMPLATE, &self, &mut fd) + .render_template_to_write(&template, &self, &mut fd) .map_err(|e| format!("HBS template write: {:?}", e).into()) } /// Builds a path for the weight file. - fn build_path(&self, weight_out: &str) -> PathBuf { - let mut path = PathBuf::from(weight_out); - if path.is_dir() { - path.push(format!("{}_weights.rs", self.db_name.to_lowercase())); + fn build_path(&self, weight_out: &Option) -> PathBuf { + let mut path = match weight_out { + Some(p) => PathBuf::from(p), + None => PathBuf::new(), + }; + + if path.is_dir() || path.as_os_str().is_empty() { + path.push(format!("{}_weights", self.db_name.to_lowercase())); path.set_extension("rs"); } path diff --git a/utils/frame/benchmarking-cli/src/storage/weights.hbs b/utils/frame/benchmarking-cli/src/storage/weights.hbs index ffeb1fe04d81..bfb832cb847f 100644 --- a/utils/frame/benchmarking-cli/src/storage/weights.hbs +++ b/utils/frame/benchmarking-cli/src/storage/weights.hbs @@ -19,6 +19,7 @@ //! DATE: {{date}} //! //! DATABASE: `{{db_name}}`, RUNTIME: `{{runtime_name}}` +//! BLOCK-NUM: `{{block_number}}` //! SKIP-WRITE: `{{params.skip_write}}`, SKIP-READ: `{{params.skip_read}}`, WARMUPS: `{{params.warmups}}` //! STATE-VERSION: `V{{params.state_version}}`, STATE-CACHE-SIZE: `{{params.state_cache_size}}` //! WEIGHT-PATH: `{{params.weight_path}}` From 8b26ac915b3226d2e234b4c03dab32d3793d328a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Tue, 15 Mar 2022 16:14:19 +0100 Subject: [PATCH 591/695] SharedData: Update locks to mention possible deadlocks (#11034) * SharedData: Update locks to mention possible deadlocks * Update `Cargo.lock` --- client/consensus/common/src/shared_data.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/client/consensus/common/src/shared_data.rs b/client/consensus/common/src/shared_data.rs index 17217d997e23..fb04966b5db6 100644 --- a/client/consensus/common/src/shared_data.rs +++ b/client/consensus/common/src/shared_data.rs @@ -167,6 +167,13 @@ struct SharedDataInner { /// // As we don't know the order of the threads, we need to check for both combinations /// assert!(*data == "hello world321" || *data == "hello world312"); /// ``` +/// +/// # Deadlock +/// +/// Be aware that this data structure doesn't give you any guarantees that you can not create a +/// deadlock. If you use [`release_mutex`](SharedDataLocked::release_mutex) followed by a call +/// to [`shared_data`](Self::shared_data) in the same thread will make your program dead lock. +/// The same applies when you are using a single threaded executor. pub struct SharedData { inner: Arc>>, cond_var: Arc, From cc282f84ba53ed2a08374d2a655dc8f08cbc5e86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Tue, 15 Mar 2022 16:26:59 +0100 Subject: [PATCH 592/695] Stabilize `seal_delegate_call` (#11037) --- frame/contracts/fixtures/delegate_call.wat | 2 +- frame/contracts/src/benchmarking/mod.rs | 2 +- frame/contracts/src/tests.rs | 1 - frame/contracts/src/wasm/mod.rs | 2 +- frame/contracts/src/wasm/runtime.rs | 7 +------ 5 files changed, 4 insertions(+), 10 deletions(-) diff --git a/frame/contracts/fixtures/delegate_call.wat b/frame/contracts/fixtures/delegate_call.wat index e1c5fa813e59..7fe422af4551 100644 --- a/frame/contracts/fixtures/delegate_call.wat +++ b/frame/contracts/fixtures/delegate_call.wat @@ -2,7 +2,7 @@ (import "seal0" "seal_input" (func $seal_input (param i32 i32))) (import "seal0" "seal_get_storage" (func $seal_get_storage (param i32 i32 i32) (result i32))) (import "seal0" "seal_set_storage" (func $seal_set_storage (param i32 i32 i32))) - (import "__unstable__" "seal_delegate_call" (func $seal_delegate_call (param i32 i32 i32 i32 i32 i32) (result i32))) + (import "seal0" "seal_delegate_call" (func $seal_delegate_call (param i32 i32 i32 i32 i32 i32) (result i32))) (import "env" "memory" (memory 3 3)) ;; [0, 32) storage key diff --git a/frame/contracts/src/benchmarking/mod.rs b/frame/contracts/src/benchmarking/mod.rs index 5fdc5c2ab784..8539978bd6b3 100644 --- a/frame/contracts/src/benchmarking/mod.rs +++ b/frame/contracts/src/benchmarking/mod.rs @@ -1492,7 +1492,7 @@ benchmarks! { let code = WasmModule::::from(ModuleDefinition { memory: Some(ImportedMemory::max::()), imported_functions: vec![ImportedFunction { - module: "__unstable__", + module: "seal0", name: "seal_delegate_call", params: vec![ ValueType::I32, diff --git a/frame/contracts/src/tests.rs b/frame/contracts/src/tests.rs index 4c8c42c77da5..2b01cbe3c742 100644 --- a/frame/contracts/src/tests.rs +++ b/frame/contracts/src/tests.rs @@ -762,7 +762,6 @@ fn deploy_and_call_other_contract() { } #[test] -#[cfg(feature = "unstable-interface")] fn delegate_call() { let (caller_wasm, caller_code_hash) = compile_module::("delegate_call").unwrap(); let (callee_wasm, callee_code_hash) = compile_module::("delegate_call_lib").unwrap(); diff --git a/frame/contracts/src/wasm/mod.rs b/frame/contracts/src/wasm/mod.rs index d89e7c1c8037..3912a936684c 100644 --- a/frame/contracts/src/wasm/mod.rs +++ b/frame/contracts/src/wasm/mod.rs @@ -618,7 +618,7 @@ mod tests { ;; output_ptr: u32, ;; output_len_ptr: u32 ;;) -> u32 - (import "__unstable__" "seal_delegate_call" (func $seal_delegate_call (param i32 i32 i32 i32 i32 i32) (result i32))) + (import "seal0" "seal_delegate_call" (func $seal_delegate_call (param i32 i32 i32 i32 i32 i32) (result i32))) (import "env" "memory" (memory 1 1)) (func (export "call") (drop diff --git a/frame/contracts/src/wasm/runtime.rs b/frame/contracts/src/wasm/runtime.rs index d008fa3f1dac..043b45e6a76e 100644 --- a/frame/contracts/src/wasm/runtime.rs +++ b/frame/contracts/src/wasm/runtime.rs @@ -191,7 +191,6 @@ pub enum RuntimeCosts { /// Base weight of calling `seal_call`. CallBase, /// Weight of calling `seal_delegate_call` for the given input size. - #[cfg(feature = "unstable-interface")] DelegateCallBase, /// Weight of the transfer performed during a call. CallSurchargeTransfer, @@ -272,7 +271,6 @@ impl RuntimeCosts { .saturating_add(s.take_storage_per_byte.saturating_mul(len.into())), Transfer => s.transfer, CallBase => s.call, - #[cfg(feature = "unstable-interface")] DelegateCallBase => s.delegate_call, CallSurchargeTransfer => s.call_transfer_surcharge, CallInputCloned(len) => s.call_per_cloned_byte.saturating_mul(len.into()), @@ -389,7 +387,6 @@ bitflags! { enum CallType { /// Execute another instantiated contract Call { callee_ptr: u32, value_ptr: u32, gas: u64 }, - #[cfg(feature = "unstable-interface")] /// Execute deployed code in the context (storage, account ID, value) of the caller contract DelegateCall { code_hash_ptr: u32 }, } @@ -398,7 +395,6 @@ impl CallType { fn cost(&self) -> RuntimeCosts { match self { CallType::Call { .. } => RuntimeCosts::CallBase, - #[cfg(feature = "unstable-interface")] CallType::DelegateCall { .. } => RuntimeCosts::DelegateCallBase, } } @@ -763,7 +759,6 @@ where flags.contains(CallFlags::ALLOW_REENTRY), ) }, - #[cfg(feature = "unstable-interface")] CallType::DelegateCall { code_hash_ptr } => { if flags.contains(CallFlags::ALLOW_REENTRY) { return Err(Error::::InvalidCallFlags.into()) @@ -1129,7 +1124,7 @@ define_env!(Env, , // `ReturnCode::CalleeReverted`: Output buffer is returned. // `ReturnCode::CalleeTrapped` // `ReturnCode::CodeNotFound` - [__unstable__] seal_delegate_call( + [seal0] seal_delegate_call( ctx, flags: u32, code_hash_ptr: u32, From 4d001219e3c8ac41c15bd646d25e3b9caccc8e3b Mon Sep 17 00:00:00 2001 From: driemworks Date: Tue, 15 Mar 2022 17:16:52 -0500 Subject: [PATCH 593/695] add tests --- .../pallets/iris-ledger/src/tests.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/bin/node-template/pallets/iris-ledger/src/tests.rs b/bin/node-template/pallets/iris-ledger/src/tests.rs index f2d860a7d35d..0d6edf1beb8b 100644 --- a/bin/node-template/pallets/iris-ledger/src/tests.rs +++ b/bin/node-template/pallets/iris-ledger/src/tests.rs @@ -36,5 +36,21 @@ fn iris_ledger_can_lock() { #[test] fn iris_ledger_can_unlock_and_transfer() { + let (p, _) = sp_core::sr25519::Pair::generate(); + let (p2, _) = sp_core::sr25519::Pair::generate(); + let pairs = vec![(p.clone().public(), 10)]; + new_test_ext_funded(pairs).execute_with(|| { + assert_ok!( + Origin::signed(p.clone().public()), + 1, + ); + + assert_ok!( + Origin::signed(p.clone().public()), + p2.clone().public(), + ); + let mut locked_amount = crate::Ledger::::get(p.public().clone()); + assert_eq!(0, locked_amount); + }); } From d94ad48e533262627434ef954f783e336ff14389 Mon Sep 17 00:00:00 2001 From: driemworks Date: Tue, 15 Mar 2022 20:07:05 -0500 Subject: [PATCH 594/695] re-enumerate chain ext func ids --- bin/node-template/runtime/src/lib.rs | 36 +++++++++++++--------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index 5331b04a344a..0645488c17a9 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -854,14 +854,14 @@ impl ChainExtension for IrisExtension { ::AccountId: UncheckedFrom<::Hash> + AsRef<[u8]>, { - match func_id { - trace!( - target: "runtime", - "[ChainExtension]|call|func_id:{:}", - func_id - ); + trace!( + target: "runtime", + "[ChainExtension]|call|func_id:{:}", + func_id + ); + match func_id { // IrisAssets::transfer_asset - 1 => { + 0 => { let mut env = env.buf_in_buf_out(); let (caller_account, target, asset_id, amount): (AccountId, AccountId, u32, u64) = env.read_as()?; let origin: Origin = system::RawOrigin::Signed(caller_account).into(); @@ -869,9 +869,10 @@ impl ChainExtension for IrisExtension { crate::IrisAssets::transfer_asset( origin, sp_runtime::MultiAddress::Id(target), asset_id, amount, )?; - } + Ok(RetVal::Converging(func_id)) + }, // IrisAssets::mint - 2 => { + 1 => { let mut env = env.buf_in_buf_out(); let (caller_account, target, asset_id, amount): (AccountId, AccountId, u32, u64) = env.read_as()?; let origin: Origin = system::RawOrigin::Signed(caller_account).into(); @@ -879,14 +880,10 @@ impl ChainExtension for IrisExtension { crate::IrisAssets::mint( origin, sp_runtime::MultiAddress::Id(target), asset_id, amount, )?; - trace!( - target: "runtime", - "[ChainExtension]|call|func_id:{:}", - func_id - ); - } + Ok(RetVal::Converging(func_id)) + }, // IrisLedger::lock_currrency - 3 => { + 2 => { let mut env = env.buf_in_buf_out(); let (caller_account, amount): (AccountId, u64) = env.read_as()?; let origin: Origin = system::RawOrigin::Signed(caller_account).into(); @@ -894,9 +891,10 @@ impl ChainExtension for IrisExtension { crate::IrisLedger::lock_currency( origin, amount.into(), )?; + Ok(RetVal::Converging(func_id)) }, // IrisLedger::unlock_currency_and_transfer - 4 => { + 3 => { let mut env = env.buf_in_buf_out(); let (caller_account, target): (AccountId, AccountId) = env.read_as()?; let origin: Origin = system::RawOrigin::Signed(caller_account).into(); @@ -904,7 +902,8 @@ impl ChainExtension for IrisExtension { crate::IrisLedger::unlock_currency_and_transfer( origin, target, )?; - } + Ok(RetVal::Converging(func_id)) + }, _ => { // env.write(&random_slice, false, None).map_err(|_| { // DispatchError::Other("ChainExtension failed to call transfer_assets") @@ -913,7 +912,6 @@ impl ChainExtension for IrisExtension { return Err(DispatchError::Other("Unimplemented func_id")) } } - Ok(RetVal::Converging(func_id)) } fn enabled() -> bool { From 499acc0e31e06dee9110a9cc169cd7c52f500b10 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 16 Mar 2022 09:47:16 +0000 Subject: [PATCH 595/695] Bump names from 0.12.0 to 0.13.0 (#11047) Bumps [names](https://github.com/fnichol/names) from 0.12.0 to 0.13.0. - [Release notes](https://github.com/fnichol/names/releases) - [Changelog](https://github.com/fnichol/names/blob/main/CHANGELOG.md) - [Commits](https://github.com/fnichol/names/compare/v0.12.0...v0.13.0) --- updated-dependencies: - dependency-name: names dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- client/cli/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 82dea83813d0..903b76bff802 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4719,9 +4719,9 @@ dependencies = [ [[package]] name = "names" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a8690bf09abf659851e58cd666c3d37ac6af07c2bd7a9e332cfba471715775" +checksum = "e7d66043b25d4a6cccb23619d10c19c25304b355a7dccd4a8e11423dd2382146" dependencies = [ "rand 0.8.4", ] diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index 8fdb192b43fb..c799fd6dee98 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -20,7 +20,7 @@ futures = "0.3.19" hex = "0.4.2" libp2p = "0.40.0" log = "0.4.11" -names = { version = "0.12.0", default-features = false } +names = { version = "0.13.0", default-features = false } rand = "0.7.3" regex = "1.5.4" rpassword = "5.0.0" From 027fc0666fa2f981a693a394f76dc9f4b87209a4 Mon Sep 17 00:00:00 2001 From: cheme Date: Wed, 16 Mar 2022 12:43:24 +0100 Subject: [PATCH 596/695] State migration rpc (#10981) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * setting flag * flag in storage struct * fix flagging to access and insert. * added todo to fix * also missing serialize meta to storage proof * extract meta. * Isolate old trie layout. * failing test that requires storing in meta when old hash scheme is used. * old hash compatibility * Db migrate. * runing tests with both states when interesting. * fix chain spec test with serde default. * export state (missing trie function). * Pending using new branch, lacking genericity on layout resolution. * extract and set global meta * Update to branch 4 * fix iterator with root flag (no longer insert node). * fix trie root hashing of root * complete basic backend. * Remove old_hash meta from proof that do not use inner_hashing. * fix trie test for empty (force layout on empty deltas). * Root update fix. * debug on meta * Use trie key iteration that do not include value in proofs. * switch default test ext to use inner hash. * small integration test, and fix tx cache mgmt in ext. test failing * Proof scenario at state-machine level. * trace for db upgrade * try different param * act more like iter_from. * Bigger batches. * Update trie dependency. * drafting codec changes and refact * before removing unused branch no value alt hashing. more work todo rename all flag var to alt_hash, and remove extrinsic replace by storage query at every storage_root call. * alt hashing only for branch with value. * fix trie tests * Hash of value include the encoded size. * removing fields(broken) * fix trie_stream to also include value length in inner hash. * triedbmut only using alt type if inner hashing. * trie_stream to also only use alt hashing type when actually alt hashing. * Refactor meta state, logic should work with change of trie treshold. * Remove NoMeta variant. * Remove state_hashed trigger specific functions. * pending switching to using threshold, new storage root api does not make much sense. * refactoring to use state from backend (not possible payload changes). * Applying from previous state * Remove default from storage, genesis need a special build. * rem empty space * Catch problem: when using triedb with default: we should not revert nodes: otherwhise thing as trie codec cannot decode-encode without changing state. * fix compilation * Right logic to avoid switch on reencode when default layout. * Clean up some todos * remove trie meta from root upstream * update upstream and fix benches. * split some long lines. * UPdate trie crate to work with new design. * Finish update to refactored upstream. * update to latest triedb changes. * Clean up. * fix executor test. * rust fmt from master. * rust format. * rustfmt * fix * start host function driven versioning * update state-machine part * still need access to state version from runtime * state hash in mem: wrong * direction likely correct, but passing call to code exec for genesis init seem awkward. * state version serialize in runtime, wrong approach, just initialize it with no threshold for core api < 4 seems more proper. * stateversion from runtime version (core api >= 4). * update trie, fix tests * unused import * clean some TODOs * Require RuntimeVersionOf for executor * use RuntimeVersionOf to resolve genesis state version. * update runtime version test * fix state-machine tests * TODO * Use runtime version from storage wasm with fast sync. * rustfmt * fmt * fix test * revert useless changes. * clean some unused changes * fmt * removing useless trait function. * remove remaining reference to state_hash * fix some imports * Follow chain state version management. * trie update, fix and constant threshold for trie layouts. * update deps * Update to latest trie pr changes. * fix benches * Verify proof requires right layout. * update trie_root * Update trie deps to latest * Update to latest trie versioning * Removing patch * update lock * extrinsic for sc-service-test using layout v0. * Adding RuntimeVersionOf to CallExecutor works. * fmt * error when resolving version and no wasm in storage. * use existing utils to instantiate runtime code. * migration pallet * Patch to delay runtime switch. * Revert "Patch to delay runtime switch." This reverts commit d35f273b7d67b1b85a9e72973cab13c5c156c1d3. * fix test * fix child migration calls. * useless closure * remove remaining state_hash variables. * Fix and add more tests * Remove outdated comment * useless inner hash * fmt * remote tests * finally ksm works * batches are broken * clean the benchmarks * Apply suggestions from code review Co-authored-by: Guillaume Thiolliere * Apply suggestions from code review Co-authored-by: Guillaume Thiolliere * Update frame/state-trie-migration/src/lib.rs Co-authored-by: Joshy Orndorff * Update frame/state-trie-migration/src/lib.rs * brand new version * fix build * Update frame/state-trie-migration/src/lib.rs Co-authored-by: Guillaume Thiolliere * Update frame/state-trie-migration/src/lib.rs Co-authored-by: Guillaume Thiolliere * Update primitives/storage/src/lib.rs Co-authored-by: cheme * Update frame/state-trie-migration/src/lib.rs Co-authored-by: cheme * Update frame/state-trie-migration/src/lib.rs Co-authored-by: cheme * fmt and opt-in feature to apply state change. * feature gate core version, use new test feature for node and test node * Use a 'State' api version instead of Core one. * fix merge of test function * use blake macro. * Fix state api (require declaring the api in runtime). * Opt out feature, fix macro for io to select a given version instead of latest. * run test nodes on new state. * fix * new test structure * new testing stuff from emeric * Add commit_all, still not working * Fix all tests * add comment * we have PoV tracking baby * document stuff, but proof size is still wrong * FUCK YEAH * a big batch of review comments * add more tests * tweak test * update config * some remote-ext stuff * delete some of the old stuff * sync more files with master to minimize the diff * Fix all tests * make signed migration a bit more relaxed * add witness check to signed submissions * allow custom migration to also go above limit * Fix these pesky tests * ==== removal of the unsigned stuff ==== * Make all tests work again * separate the tests from the logic so it can be reused easier * fix overall build * Update frame/state-trie-migration/src/lib.rs Co-authored-by: cheme * Update frame/state-trie-migration/src/lib.rs Co-authored-by: cheme * Slightly better termination * some final tweaks * Fix tests * Restrict access to signed migrations * mig rpc * fix * better rpc name * Make rpc unsafe * address most of the review comments * fix defensive * New simplified code * Fix weights * fmt * Update frame/state-trie-migration/src/lib.rs Co-authored-by: Bastian Köcher * make the tests correctly fail * Fix build * Fix build * try and fix the benchmarks * fix build * Fix cargo file * Fix runtime deposit * make rustdoc happy * cargo run --quiet --profile=production --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_state_trie_migration --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/state-trie-migration/src/weights.rs --template=./.maintain/frame-weight-template.hbs * update rpc deps, try to process empty keys. * move rpc crate * move check backend out of state machine * Add primitive crate. * module code * fix runtime test * StateMigrationStatusProvider * Pass backend to rpc. * fmt * review changes * move rpc crate * try remove primitive crate * Update utils/frame/rpc/state-trie-migration-rpc/Cargo.toml Co-authored-by: Bastian Köcher * review changes. Co-authored-by: kianenigma Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Co-authored-by: Guillaume Thiolliere Co-authored-by: Joshy Orndorff Co-authored-by: Bastian Köcher Co-authored-by: Parity Bot --- Cargo.lock | 26 ++- Cargo.toml | 2 + bin/node/cli/src/service.rs | 3 +- bin/node/rpc/Cargo.toml | 1 + bin/node/rpc/src/lib.rs | 5 + frame/state-trie-migration/Cargo.toml | 5 +- frame/state-trie-migration/src/lib.rs | 176 +++++++++--------- primitives/state-machine/Cargo.toml | 2 - .../state-machine/src/trie_backend_essence.rs | 72 +------ .../rpc/state-trie-migration-rpc/Cargo.toml | 38 ++++ .../rpc/state-trie-migration-rpc/README.md | 3 + .../rpc/state-trie-migration-rpc/src/lib.rs | 164 ++++++++++++++++ 12 files changed, 332 insertions(+), 165 deletions(-) create mode 100644 utils/frame/rpc/state-trie-migration-rpc/Cargo.toml create mode 100644 utils/frame/rpc/state-trie-migration-rpc/README.md create mode 100644 utils/frame/rpc/state-trie-migration-rpc/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 903b76bff802..e2321d7fa99d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4987,6 +4987,7 @@ dependencies = [ "sp-keystore", "sp-runtime", "substrate-frame-rpc-system", + "substrate-state-trie-migration-rpc", ] [[package]] @@ -6472,6 +6473,7 @@ dependencies = [ "sp-runtime", "sp-std", "sp-tracing", + "substrate-state-trie-migration-rpc", "thousands", "tokio", "zstd", @@ -10300,7 +10302,6 @@ dependencies = [ "sp-trie", "thiserror", "tracing", - "trie-db", "trie-root", ] @@ -10628,6 +10629,29 @@ dependencies = [ "tokio", ] +[[package]] +name = "substrate-state-trie-migration-rpc" +version = "4.0.0-dev" +dependencies = [ + "jsonrpc-core", + "jsonrpc-core-client", + "jsonrpc-derive", + "log 0.4.14", + "parity-scale-codec", + "sc-client-api", + "sc-rpc-api", + "scale-info", + "serde", + "serde_json", + "sp-core", + "sp-io", + "sp-runtime", + "sp-state-machine", + "sp-std", + "sp-trie", + "trie-db", +] + [[package]] name = "substrate-test-client" version = "2.0.1" diff --git a/Cargo.toml b/Cargo.toml index bce23456b27e..13657dd1234a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -119,6 +119,7 @@ members = [ "frame/staking", "frame/staking/reward-curve", "frame/staking/reward-fn", + "frame/state-trie-migration", "frame/sudo", "frame/support", "frame/support/procedural", @@ -210,6 +211,7 @@ members = [ "utils/frame/remote-externalities", "utils/frame/frame-utilities-cli", "utils/frame/try-runtime/cli", + "utils/frame/rpc/state-trie-migration-rpc", "utils/frame/rpc/support", "utils/frame/rpc/system", "utils/frame/generate-bags", diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index 10d39f278f5f..038c14029cf3 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -252,6 +252,7 @@ pub fn new_partial( let keystore = keystore_container.sync_keystore(); let chain_spec = config.chain_spec.cloned_box(); + let rpc_backend = backend.clone(); let rpc_extensions_builder = move |deny_unsafe, subscription_executor| { let deps = node_rpc::FullDeps { client: client.clone(), @@ -273,7 +274,7 @@ pub fn new_partial( }, }; - node_rpc::create_full(deps).map_err(Into::into) + node_rpc::create_full(deps, rpc_backend.clone()).map_err(Into::into) }; (rpc_extensions_builder, rpc_setup) diff --git a/bin/node/rpc/Cargo.toml b/bin/node/rpc/Cargo.toml index 95ea3f8174fa..6c18e70f0d63 100644 --- a/bin/node/rpc/Cargo.toml +++ b/bin/node/rpc/Cargo.toml @@ -35,3 +35,4 @@ sp-consensus-babe = { version = "0.10.0-dev", path = "../../../primitives/consen sp-runtime = { version = "6.0.0", path = "../../../primitives/runtime" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../../../client/transaction-pool/api" } substrate-frame-rpc-system = { version = "4.0.0-dev", path = "../../../utils/frame/rpc/system" } +substrate-state-trie-migration-rpc = { version = "4.0.0-dev", path = "../../../utils/frame/rpc/state-trie-migration-rpc/" } diff --git a/bin/node/rpc/src/lib.rs b/bin/node/rpc/src/lib.rs index 31f2f4108688..09f350ed3dcf 100644 --- a/bin/node/rpc/src/lib.rs +++ b/bin/node/rpc/src/lib.rs @@ -99,6 +99,7 @@ pub type IoHandler = jsonrpc_core::IoHandler; /// Instantiate all Full RPC extensions. pub fn create_full( deps: FullDeps, + backend: Arc, ) -> Result, Box> where C: ProvideRuntimeApi @@ -159,6 +160,10 @@ where finality_provider, ))); + io.extend_with(substrate_state_trie_migration_rpc::StateMigrationApi::to_delegate( + substrate_state_trie_migration_rpc::MigrationRpc::new(client.clone(), backend, deny_unsafe), + )); + io.extend_with(sc_sync_state_rpc::SyncStateRpcApi::to_delegate( sc_sync_state_rpc::SyncStateRpcHandler::new( chain_spec, diff --git a/frame/state-trie-migration/Cargo.toml b/frame/state-trie-migration/Cargo.toml index fb8bccb52d1f..762fd85f13b6 100644 --- a/frame/state-trie-migration/Cargo.toml +++ b/frame/state-trie-migration/Cargo.toml @@ -21,6 +21,7 @@ sp-std = { default-features = false, path = "../../primitives/std" } sp-io = { default-features = false, path = "../../primitives/io" } sp-core = { default-features = false, path = "../../primitives/core" } sp-runtime = { default-features = false, path = "../../primitives/runtime" } +substrate-state-trie-migration-rpc = { optional = true, path = "../../utils/frame/rpc/state-trie-migration-rpc" } frame-support = { default-features = false, path = "../support" } frame-system = { default-features = false, path = "../system" } @@ -49,9 +50,9 @@ std = [ "sp-core/std", "sp-io/std", "sp-runtime/std", - "sp-std/std" + "sp-std/std", ] runtime-benchmarks = ["frame-benchmarking"] try-runtime = ["frame-support/try-runtime"] -remote-test = [ "std", "zstd", "serde", "thousands", "remote-externalities" ] +remote-test = [ "std", "zstd", "serde", "thousands", "remote-externalities", "substrate-state-trie-migration-rpc" ] diff --git a/frame/state-trie-migration/src/lib.rs b/frame/state-trie-migration/src/lib.rs index 4de130e9ac06..a5a077c54e57 100644 --- a/frame/state-trie-migration/src/lib.rs +++ b/frame/state-trie-migration/src/lib.rs @@ -123,6 +123,13 @@ pub mod pallet { } } + #[derive(Clone, Encode, Decode, scale_info::TypeInfo, PartialEq, Eq)] + pub(crate) enum Progress { + ToStart, + LastKey(Vec), + Complete, + } + /// A migration task stored in state. /// /// It tracks the last top and child keys read. @@ -130,20 +137,13 @@ pub mod pallet { #[codec(mel_bound(T: Config))] #[scale_info(skip_type_params(T))] pub struct MigrationTask { - /// The last top key that we migrated. + /// The current top trie migration progress. + pub(crate) progress_top: Progress, + /// The current child trie migration progress. /// - /// If it does not exist, it means that the migration is done and no further keys exist. - pub(crate) last_top: Option>, - /// The last child key that we have processed. - /// - /// This is a child key under the current `self.last_top`. - /// - /// If this is set, no further top keys are processed until the child key migration is - /// complete. - pub(crate) last_child: Option>, - - /// A marker to indicate if the previous tick was a child tree migration or not. - pub(crate) prev_tick_child: bool, + /// If `ToStart`, no further top keys are processed until the child key migration is + /// `Complete`. + pub(crate) progress_child: Progress, /// Dynamic counter for the number of items that we have processed in this execution from /// the top trie. @@ -182,18 +182,22 @@ pub mod pallet { pub(crate) _ph: sp_std::marker::PhantomData, } + impl sp_std::fmt::Debug for Progress { + fn fmt(&self, f: &mut sp_std::fmt::Formatter<'_>) -> sp_std::fmt::Result { + match self { + Progress::ToStart => f.write_str("To start"), + Progress::LastKey(key) => + write!(f, "Last: {:?}", sp_core::hexdisplay::HexDisplay::from(key)), + Progress::Complete => f.write_str("Complete"), + } + } + } + impl sp_std::fmt::Debug for MigrationTask { fn fmt(&self, f: &mut sp_std::fmt::Formatter<'_>) -> sp_std::fmt::Result { f.debug_struct("MigrationTask") - .field( - "top", - &self.last_top.as_ref().map(|d| sp_core::hexdisplay::HexDisplay::from(d)), - ) - .field( - "child", - &self.last_child.as_ref().map(|d| sp_core::hexdisplay::HexDisplay::from(d)), - ) - .field("prev_tick_child", &self.prev_tick_child) + .field("top", &self.progress_top) + .field("child", &self.progress_child) .field("dyn_top_items", &self.dyn_top_items) .field("dyn_child_items", &self.dyn_child_items) .field("dyn_size", &self.dyn_size) @@ -207,12 +211,11 @@ pub mod pallet { impl Default for MigrationTask { fn default() -> Self { Self { - last_top: Some(Default::default()), - last_child: Default::default(), + progress_top: Progress::ToStart, + progress_child: Progress::ToStart, dyn_child_items: Default::default(), dyn_top_items: Default::default(), dyn_size: Default::default(), - prev_tick_child: Default::default(), _ph: Default::default(), size: Default::default(), top_items: Default::default(), @@ -224,7 +227,7 @@ pub mod pallet { impl MigrationTask { /// Return true if the task is finished. pub(crate) fn finished(&self) -> bool { - self.last_top.is_none() && self.last_child.is_none() + matches!(self.progress_top, Progress::Complete) } /// Check if there's any work left, or if we have exhausted the limits already. @@ -269,51 +272,36 @@ pub mod pallet { /// /// This function is *the* core of this entire pallet. fn migrate_tick(&mut self) { - match (self.last_top.as_ref(), self.last_child.as_ref()) { - (Some(_), Some(_)) => { + match (&self.progress_top, &self.progress_child) { + (Progress::ToStart, _) => { + self.migrate_top(); + }, + (Progress::LastKey(_), Progress::LastKey(_)) => { // we're in the middle of doing work on a child tree. self.migrate_child(); }, - (Some(ref top_key), None) => { - // we have a top key and no child key. 3 possibilities exist: - // 1. we continue the top key migrations. - // 2. this is the root of a child key, and we start processing child keys (and - // should call `migrate_child`). + (Progress::LastKey(top_key), Progress::ToStart) => { // 3. this is the root of a child key, and we are finishing all child-keys (and // should call `migrate_top`). // NOTE: this block is written intentionally to verbosely for easy of // verification. - match ( - top_key.starts_with(DEFAULT_CHILD_STORAGE_KEY_PREFIX), - self.prev_tick_child, - ) { - (false, false) => { - // continue the top key migration - self.migrate_top(); - }, - (true, false) => { - self.last_child = Some(Default::default()); - self.migrate_child(); - self.prev_tick_child = true; - }, - (true, true) => { - // we're done with migrating a child-root. - self.prev_tick_child = false; - self.migrate_top(); - }, - (false, true) => { - // should never happen. - log!(error, "LOGIC ERROR: unreachable code [0]."); - Pallet::::halt(); - }, - }; + if !top_key.starts_with(DEFAULT_CHILD_STORAGE_KEY_PREFIX) { + // we continue the top key migrations. + // continue the top key migration + self.migrate_top(); + } else { + // this is the root of a child key, and we start processing child keys (and + // should call `migrate_child`). + self.migrate_child(); + } }, - (None, Some(_)) => { - log!(error, "LOGIC ERROR: unreachable code [1]."); - Pallet::::halt() + (Progress::LastKey(_), Progress::Complete) => { + // we're done with migrating a child-root. + self.migrate_top(); + self.progress_child = Progress::ToStart; }, - (None, None) => { + (Progress::Complete, _) => { // nada }, } @@ -324,19 +312,26 @@ pub mod pallet { /// It updates the dynamic counters. fn migrate_child(&mut self) { use sp_io::default_child_storage as child_io; - let (last_child, last_top) = match (&self.last_child, &self.last_top) { - (Some(last_child), Some(last_top)) => (last_child, last_top), + let (maybe_current_child, child_root) = match (&self.progress_child, &self.progress_top) + { + (Progress::LastKey(last_child), Progress::LastKey(last_top)) => { + let child_root = Pallet::::transform_child_key_or_halt(&last_top); + let maybe_current_child = child_io::next_key(child_root, &last_child); + (maybe_current_child, child_root) + }, + (Progress::ToStart, Progress::LastKey(last_top)) => { + let child_root = Pallet::::transform_child_key_or_halt(&last_top); + // Start with the empty key as first key. + (Some(Vec::new()), child_root) + }, _ => { - // defensive: this function is only called when both of these values exist. - // much that we can do otherwise.. + // defensive: there must be an ongoing top migration. frame_support::defensive!("cannot migrate child key."); return }, }; - let child_root = Pallet::::transform_child_key_or_halt(&last_top); - let maybe_current_child = child_io::next_key(child_root, &last_child); - if let Some(ref current_child) = maybe_current_child { + if let Some(current_child) = maybe_current_child.as_ref() { let added_size = if let Some(data) = child_io::get(child_root, ¤t_child) { child_io::set(child_root, current_child, &data); data.len() as u32 @@ -348,25 +343,28 @@ pub mod pallet { } log!(trace, "migrated a child key, next_child_key: {:?}", maybe_current_child); - self.last_child = maybe_current_child; + self.progress_child = match maybe_current_child { + Some(last_child) => Progress::LastKey(last_child), + None => Progress::Complete, + } } /// Migrate the current top key, setting it to its new value, if one exists. /// /// It updates the dynamic counters. fn migrate_top(&mut self) { - let last_top = match &self.last_top { - Some(last_top) => last_top, - None => { - // defensive: this function is only called when this value exist. - // much that we can do otherwise.. + let maybe_current_top = match &self.progress_top { + Progress::LastKey(last_top) => sp_io::storage::next_key(last_top), + // Start with the empty key as first key. + Progress::ToStart => Some(Vec::new()), + Progress::Complete => { + // defensive: there must be an ongoing top migration. frame_support::defensive!("cannot migrate top key."); return }, }; - let maybe_current_top = sp_io::storage::next_key(last_top); - if let Some(ref current_top) = maybe_current_top { + if let Some(current_top) = maybe_current_top.as_ref() { let added_size = if let Some(data) = sp_io::storage::get(¤t_top) { sp_io::storage::set(¤t_top, &data); data.len() as u32 @@ -378,7 +376,10 @@ pub mod pallet { } log!(trace, "migrated a top key, next_top_key = {:?}", maybe_current_top); - self.last_top = maybe_current_top; + self.progress_top = match maybe_current_top { + Some(last_top) => Progress::LastKey(last_top), + None => Progress::Complete, + } } } @@ -811,7 +812,7 @@ mod benchmarks { continue_migrate_wrong_witness { let null = MigrationLimits::default(); let caller = frame_benchmarking::whitelisted_caller(); - let bad_witness = MigrationTask { last_top: Some(vec![1u8]), ..Default::default() }; + let bad_witness = MigrationTask { progress_top: Progress::LastKey(vec![1u8]), ..Default::default() }; }: { assert!( StateTrieMigration::::continue_migrate( @@ -1141,15 +1142,12 @@ mod test { } #[test] - #[ignore] fn detects_value_in_empty_top_key() { let limit = MigrationLimits { item: 1, size: 1000 }; let initial_keys = Some(vec![(vec![], vec![66u8; 77])]); let mut ext = new_test_ext(StateVersion::V0, false, initial_keys.clone(), None); let root_upgraded = ext.execute_with(|| { - sp_io::storage::set(&[], &vec![66u8; 77]); - AutoLimits::::put(Some(limit)); let root = run_to_block(30).0; @@ -1168,9 +1166,7 @@ mod test { } #[test] - #[ignore] fn detects_value_in_first_child_key() { - use frame_support::storage::child; let limit = MigrationLimits { item: 1, size: 1000 }; let initial_child = Some(vec![(b"chk1".to_vec(), vec![], vec![66u8; 77])]); let mut ext = new_test_ext(StateVersion::V0, false, None, initial_child.clone()); @@ -1186,7 +1182,6 @@ mod test { let mut ext2 = new_test_ext(StateVersion::V1, false, None, initial_child); let root = ext2.execute_with(|| { - child::put(&child::ChildInfo::new_default(b"chk1"), &[], &vec![66u8; 77]); AutoLimits::::put(Some(limit)); run_to_block(30).0 }); @@ -1214,7 +1209,7 @@ mod test { // eventually everything is over. assert!(matches!( StateTrieMigration::migration_process(), - MigrationTask { last_child: None, last_top: None, .. } + MigrationTask { progress_top: Progress::Complete, .. } )); root }); @@ -1276,7 +1271,10 @@ mod test { Origin::signed(1), MigrationLimits { item: 5, size: 100 }, 100, - MigrationTask { last_top: Some(vec![1u8]), ..Default::default() } + MigrationTask { + progress_top: Progress::LastKey(vec![1u8]), + ..Default::default() + } ), Error::::BadWitness ); @@ -1451,7 +1449,8 @@ pub(crate) mod remote_tests { // set the version to 1, as if the upgrade happened. ext.state_version = sp_core::storage::StateVersion::V1; - let (top_left, child_left) = ext.as_backend().essence().check_migration_state().unwrap(); + let (top_left, child_left) = + substrate_state_trie_migration_rpc::migration_status(&ext.as_backend()).unwrap(); assert!( top_left > 0, "no node needs migrating, this probably means that state was initialized with `StateVersion::V1`", @@ -1509,7 +1508,8 @@ pub(crate) mod remote_tests { ) }); - let (top_left, child_left) = ext.as_backend().essence().check_migration_state().unwrap(); + let (top_left, child_left) = + substrate_state_trie_migration_rpc::migration_status(&ext.as_backend()).unwrap(); assert_eq!(top_left, 0); assert_eq!(child_left, 0); } diff --git a/primitives/state-machine/Cargo.toml b/primitives/state-machine/Cargo.toml index 2a6ab80133ee..80651130575e 100644 --- a/primitives/state-machine/Cargo.toml +++ b/primitives/state-machine/Cargo.toml @@ -18,7 +18,6 @@ log = { version = "0.4.11", optional = true } thiserror = { version = "1.0.30", optional = true } parking_lot = { version = "0.12.0", optional = true } hash-db = { version = "0.15.2", default-features = false } -trie-db = { version = "0.23.1", default-features = false } trie-root = { version = "0.17.0", default-features = false } sp-trie = { version = "6.0.0", path = "../trie", default-features = false } sp-core = { version = "6.0.0", path = "../core", default-features = false } @@ -47,7 +46,6 @@ std = [ "sp-externalities/std", "sp-std/std", "sp-trie/std", - "trie-db/std", "trie-root/std", "log", "thiserror", diff --git a/primitives/state-machine/src/trie_backend_essence.rs b/primitives/state-machine/src/trie_backend_essence.rs index b0eb54382437..8531e4907d6a 100644 --- a/primitives/state-machine/src/trie_backend_essence.rs +++ b/primitives/state-machine/src/trie_backend_essence.rs @@ -23,7 +23,7 @@ use codec::Encode; use hash_db::{self, AsHashDB, HashDB, HashDBRef, Hasher, Prefix}; #[cfg(feature = "std")] use parking_lot::RwLock; -use sp_core::storage::{ChildInfo, ChildType, PrefixedStorageKey, StateVersion}; +use sp_core::storage::{ChildInfo, ChildType, StateVersion}; use sp_std::{boxed::Box, vec::Vec}; use sp_trie::{ child_delta_trie_root, delta_trie_root, empty_child_trie_root, read_child_trie_value, @@ -36,10 +36,6 @@ use sp_trie::{ use std::collections::HashMap; #[cfg(feature = "std")] use std::sync::Arc; -use trie_db::{ - node::{NodePlan, ValuePlan}, - TrieDBNodeIterator, -}; #[cfg(not(feature = "std"))] macro_rules! format { @@ -433,72 +429,6 @@ where ); } - /// Check remaining state item to migrate. Note this function should be remove when all state - /// migration did finished as it is only an utility. - // original author: @cheme - pub fn check_migration_state(&self) -> Result<(u64, u64)> { - let threshold: u32 = sp_core::storage::TRIE_VALUE_NODE_THRESHOLD; - let mut nb_to_migrate = 0; - let mut nb_to_migrate_child = 0; - - let trie = sp_trie::trie_types::TrieDB::new(self, &self.root) - .map_err(|e| format!("TrieDB creation error: {}", e))?; - let iter_node = TrieDBNodeIterator::new(&trie) - .map_err(|e| format!("TrieDB node iterator error: {}", e))?; - for node in iter_node { - let node = node.map_err(|e| format!("TrieDB node iterator error: {}", e))?; - match node.2.node_plan() { - NodePlan::Leaf { value, .. } | - NodePlan::NibbledBranch { value: Some(value), .. } => - if let ValuePlan::Inline(range) = value { - if (range.end - range.start) as u32 >= threshold { - nb_to_migrate += 1; - } - }, - _ => (), - } - } - - let mut child_roots: Vec<(ChildInfo, Vec)> = Vec::new(); - // get all child trie roots - for key_value in trie.iter().map_err(|e| format!("TrieDB node iterator error: {}", e))? { - let (key, value) = - key_value.map_err(|e| format!("TrieDB node iterator error: {}", e))?; - if key[..] - .starts_with(sp_core::storage::well_known_keys::DEFAULT_CHILD_STORAGE_KEY_PREFIX) - { - let prefixed_key = PrefixedStorageKey::new(key); - let (_type, unprefixed) = ChildType::from_prefixed_key(&prefixed_key).unwrap(); - child_roots.push((ChildInfo::new_default(unprefixed), value)); - } - } - for (child_info, root) in child_roots { - let mut child_root = H::Out::default(); - let storage = KeySpacedDB::new(self, child_info.keyspace()); - - child_root.as_mut()[..].copy_from_slice(&root[..]); - let trie = sp_trie::trie_types::TrieDB::new(&storage, &child_root) - .map_err(|e| format!("New child TrieDB error: {}", e))?; - let iter_node = TrieDBNodeIterator::new(&trie) - .map_err(|e| format!("TrieDB node iterator error: {}", e))?; - for node in iter_node { - let node = node.map_err(|e| format!("Child TrieDB node iterator error: {}", e))?; - match node.2.node_plan() { - NodePlan::Leaf { value, .. } | - NodePlan::NibbledBranch { value: Some(value), .. } => - if let ValuePlan::Inline(range) = value { - if (range.end - range.start) as u32 >= threshold { - nb_to_migrate_child += 1; - } - }, - _ => (), - } - } - } - - Ok((nb_to_migrate, nb_to_migrate_child)) - } - /// Returns all `(key, value)` pairs in the trie. pub fn pairs(&self) -> Vec<(StorageKey, StorageValue)> { let collect_all = || -> sp_std::result::Result<_, Box>> { diff --git a/utils/frame/rpc/state-trie-migration-rpc/Cargo.toml b/utils/frame/rpc/state-trie-migration-rpc/Cargo.toml new file mode 100644 index 000000000000..deb641a89a46 --- /dev/null +++ b/utils/frame/rpc/state-trie-migration-rpc/Cargo.toml @@ -0,0 +1,38 @@ +[package] +name = "substrate-state-trie-migration-rpc" +version = "4.0.0-dev" +authors = ["Parity Technologies "] +edition = "2021" +license = "Apache-2.0" +homepage = "https://substrate.io" +repository = "https://github.com/paritytech/substrate/" +description = "Node-specific RPC methods for interaction with state trie migration." +readme = "README.md" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +serde = { version = "1", features = ["derive"] } +log = { version = "0.4.14", default-features = false } + +sp-std = { path = "../../../../primitives/std" } +sp-io = { path = "../../../../primitives/io" } +sp-core = { path = "../../../../primitives/core" } +sp-state-machine = { path = "../../../../primitives/state-machine" } +sp-trie = { path = "../../../../primitives/trie" } +trie-db = { version = "0.23.1" } + +jsonrpc-core = "18.0.0" +jsonrpc-core-client = "18.0.0" +jsonrpc-derive = "18.0.0" + +# Substrate Dependencies +sc-client-api = { version = "4.0.0-dev", path = "../../../../client/api" } +sc-rpc-api = { version = "0.10.0-dev", path = "../../../../client/rpc-api" } +sp-runtime = { version = "6.0.0", path = "../../../../primitives/runtime" } + +[dev-dependencies] +serde_json = "1" diff --git a/utils/frame/rpc/state-trie-migration-rpc/README.md b/utils/frame/rpc/state-trie-migration-rpc/README.md new file mode 100644 index 000000000000..03bbfdf1b593 --- /dev/null +++ b/utils/frame/rpc/state-trie-migration-rpc/README.md @@ -0,0 +1,3 @@ +Node-specific RPC methods for interaction with trie migration. + +License: Apache-2.0 diff --git a/utils/frame/rpc/state-trie-migration-rpc/src/lib.rs b/utils/frame/rpc/state-trie-migration-rpc/src/lib.rs new file mode 100644 index 000000000000..98a3cf964843 --- /dev/null +++ b/utils/frame/rpc/state-trie-migration-rpc/src/lib.rs @@ -0,0 +1,164 @@ +// This file is part of Substrate. + +// Copyright (C) 2019-2022 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. + +//! Rpc for state migration. + +use jsonrpc_core::{Error, ErrorCode, Result}; +use jsonrpc_derive::rpc; +use sc_rpc_api::DenyUnsafe; +use serde::{Deserialize, Serialize}; +use sp_runtime::{generic::BlockId, traits::Block as BlockT}; +use std::sync::Arc; + +use sp_core::{ + storage::{ChildInfo, ChildType, PrefixedStorageKey}, + Hasher, +}; +use sp_state_machine::Backend; +use sp_trie::{trie_types::TrieDB, KeySpacedDB, Trie}; +use trie_db::{ + node::{NodePlan, ValuePlan}, + TrieDBNodeIterator, +}; + +fn count_migrate<'a, H: Hasher>( + storage: &'a dyn trie_db::HashDBRef>, + root: &'a H::Out, +) -> std::result::Result<(u64, TrieDB<'a, H>), String> { + let mut nb = 0u64; + let trie = TrieDB::new(storage, root).map_err(|e| format!("TrieDB creation error: {}", e))?; + let iter_node = + TrieDBNodeIterator::new(&trie).map_err(|e| format!("TrieDB node iterator error: {}", e))?; + for node in iter_node { + let node = node.map_err(|e| format!("TrieDB node iterator error: {}", e))?; + match node.2.node_plan() { + NodePlan::Leaf { value, .. } | NodePlan::NibbledBranch { value: Some(value), .. } => + if let ValuePlan::Inline(range) = value { + if (range.end - range.start) as u32 >= + sp_core::storage::TRIE_VALUE_NODE_THRESHOLD + { + nb += 1; + } + }, + _ => (), + } + } + Ok((nb, trie)) +} + +/// Check trie migration status. +pub fn migration_status(backend: &B) -> std::result::Result<(u64, u64), String> +where + H: Hasher, + H::Out: codec::Codec, + B: Backend, +{ + let trie_backend = if let Some(backend) = backend.as_trie_backend() { + backend + } else { + return Err("No access to trie from backend.".to_string()) + }; + let essence = trie_backend.essence(); + let (nb_to_migrate, trie) = count_migrate(essence, &essence.root())?; + + let mut nb_to_migrate_child = 0; + let mut child_roots: Vec<(ChildInfo, Vec)> = Vec::new(); + // get all child trie roots + for key_value in trie.iter().map_err(|e| format!("TrieDB node iterator error: {}", e))? { + let (key, value) = key_value.map_err(|e| format!("TrieDB node iterator error: {}", e))?; + if key[..].starts_with(sp_core::storage::well_known_keys::DEFAULT_CHILD_STORAGE_KEY_PREFIX) + { + let prefixed_key = PrefixedStorageKey::new(key); + let (_type, unprefixed) = ChildType::from_prefixed_key(&prefixed_key).unwrap(); + child_roots.push((ChildInfo::new_default(unprefixed), value)); + } + } + for (child_info, root) in child_roots { + let mut child_root = H::Out::default(); + let storage = KeySpacedDB::new(essence, child_info.keyspace()); + + child_root.as_mut()[..].copy_from_slice(&root[..]); + nb_to_migrate_child += count_migrate(&storage, &child_root)?.0; + } + + Ok((nb_to_migrate, nb_to_migrate_child)) +} + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +#[serde(deny_unknown_fields)] +pub struct MigrationStatusResult { + top_remaining_to_migrate: u64, + child_remaining_to_migrate: u64, +} + +/// Migration RPC methods. +#[rpc] +pub trait StateMigrationApi { + /// Check current migration state. + /// + /// This call is performed locally without submitting any transactions. Thus executing this + /// won't change any state. Nonetheless it is a VERY costy call that should be + /// only exposed to trusted peers. + #[rpc(name = "state_trieMigrationStatus")] + fn call(&self, at: Option) -> Result; +} + +/// An implementation of state migration specific RPC methods. +pub struct MigrationRpc { + client: Arc, + backend: Arc, + deny_unsafe: DenyUnsafe, + _marker: std::marker::PhantomData<(B, BA)>, +} + +impl MigrationRpc { + /// Create new state migration rpc for the given reference to the client. + pub fn new(client: Arc, backend: Arc, deny_unsafe: DenyUnsafe) -> Self { + MigrationRpc { client, backend, deny_unsafe, _marker: Default::default() } + } +} + +impl StateMigrationApi<::Hash> for MigrationRpc +where + B: BlockT, + C: Send + Sync + 'static + sc_client_api::HeaderBackend, + BA: 'static + sc_client_api::backend::Backend, +{ + fn call(&self, at: Option<::Hash>) -> Result { + if let Err(err) = self.deny_unsafe.check_if_safe() { + return Err(err.into()) + } + + let block_id = BlockId::hash(at.unwrap_or_else(|| self.client.info().best_hash)); + let state = self.backend.state_at(block_id).map_err(error_into_rpc_err)?; + let (top, child) = migration_status(&state).map_err(error_into_rpc_err)?; + + Ok(MigrationStatusResult { + top_remaining_to_migrate: top, + child_remaining_to_migrate: child, + }) + } +} + +fn error_into_rpc_err(err: impl std::fmt::Display) -> Error { + Error { + code: ErrorCode::InternalError, + message: "Error while checking migration state".into(), + data: Some(err.to_string().into()), + } +} From 805475c248b8d5b1d85655ce9f6d0b55c9fd3925 Mon Sep 17 00:00:00 2001 From: Falco Hirschenberger Date: Wed, 16 Mar 2022 17:05:34 +0100 Subject: [PATCH 597/695] Prevent possible rocksdb-corruption by running benchmark-storage (#11040) * Prevent possible rocksdb-corruption by running benchmark-storage Also adds a `sanitize_key` function to strip path-prefixes from the db-keys (for databases that use prefixed keys such as rocksdb) fixes #10998 * Fix @cheme 's annotations. * Update utils/frame/benchmarking-cli/src/storage/write.rs Co-authored-by: Oliver Tale-Yazdi * Make logic match the name of bool flag `invert_inserts` * Remove unused lifetime Co-authored-by: Oliver Tale-Yazdi --- client/db/src/lib.rs | 8 +-- client/db/src/parity_db.rs | 4 ++ primitives/database/src/lib.rs | 5 ++ .../benchmarking-cli/src/storage/write.rs | 64 ++++++++++--------- 4 files changed, 46 insertions(+), 35 deletions(-) diff --git a/client/db/src/lib.rs b/client/db/src/lib.rs index f451062de33a..6a8a025f1f45 100644 --- a/client/db/src/lib.rs +++ b/client/db/src/lib.rs @@ -107,7 +107,8 @@ pub type DbState = sp_state_machine::TrieBackend>>, HashFor>; /// Length of a [`DbHash`]. -pub const DB_HASH_LEN: usize = 32; +const DB_HASH_LEN: usize = 32; + /// Hash type that this backend uses for the database. pub type DbHash = sp_core::H256; @@ -1351,10 +1352,7 @@ impl Backend { let mut removal: u64 = 0; let mut bytes_removal: u64 = 0; for (mut key, (val, rc)) in operation.db_updates.drain() { - if !self.storage.prefix_keys { - // Strip prefix - key.drain(0..key.len() - DB_HASH_LEN); - }; + self.storage.db.sanitize_key(&mut key); if rc > 0 { ops += 1; bytes += key.len() as u64 + val.len() as u64; diff --git a/client/db/src/parity_db.rs b/client/db/src/parity_db.rs index c27d7b0d4b4d..c81a346bb023 100644 --- a/client/db/src/parity_db.rs +++ b/client/db/src/parity_db.rs @@ -112,4 +112,8 @@ impl> Database for DbAdapter { fn supports_ref_counting(&self) -> bool { true } + + fn sanitize_key(&self, key: &mut Vec) { + let _prefix = key.drain(0..key.len() - crate::DB_HASH_LEN); + } } diff --git a/primitives/database/src/lib.rs b/primitives/database/src/lib.rs index 2d7c5fd6653e..3ec62a2b7814 100644 --- a/primitives/database/src/lib.rs +++ b/primitives/database/src/lib.rs @@ -110,6 +110,11 @@ pub trait Database>: Send + Sync { fn supports_ref_counting(&self) -> bool { false } + + /// Remove a possible path-prefix from the key. + /// + /// Not all database implementations use a prefix for keys, so this function may be a noop. + fn sanitize_key(&self, _key: &mut Vec) {} } impl std::fmt::Debug for dyn Database { diff --git a/utils/frame/benchmarking-cli/src/storage/write.rs b/utils/frame/benchmarking-cli/src/storage/write.rs index eb9ba11f3069..94a0eea9728f 100644 --- a/utils/frame/benchmarking-cli/src/storage/write.rs +++ b/utils/frame/benchmarking-cli/src/storage/write.rs @@ -17,7 +17,7 @@ use sc_cli::Result; use sc_client_api::UsageProvider; -use sc_client_db::{DbHash, DbState, DB_HASH_LEN}; +use sc_client_db::{DbHash, DbState}; use sp_api::StateBackend; use sp_blockchain::HeaderBackend; use sp_database::{ColumnId, Transaction}; @@ -27,7 +27,7 @@ use sp_runtime::{ }; use sp_trie::PrefixedMemoryDB; -use log::info; +use log::{info, trace}; use rand::prelude::*; use std::{fmt::Debug, sync::Arc, time::Instant}; @@ -50,7 +50,6 @@ impl StorageCmd { // Store the time that it took to write each value. let mut record = BenchRecord::default(); - let supports_rc = db.supports_ref_counting(); let block = BlockId::Number(client.usage_info().chain.best_number); let header = client.header(block)?.ok_or("Header not found")?; let original_root = *header.state_root(); @@ -62,15 +61,34 @@ impl StorageCmd { let mut rng = Self::setup_rng(); kvs.shuffle(&mut rng); + // Generate all random values first; Make sure there are no collisions with existing + // db entries, so we can rollback all additions without corrupting existing entries. + for (k, original_v) in kvs.iter_mut() { + 'retry: loop { + let mut new_v = vec![0; original_v.len()]; + // Create a random value to overwrite with. + // NOTE: We use a possibly higher entropy than the original value, + // could be improved but acts as an over-estimation which is fine for now. + rng.fill_bytes(&mut new_v[..]); + let new_kv = vec![(k.as_ref(), Some(new_v.as_ref()))]; + let (_, mut stx) = trie.storage_root(new_kv.iter().cloned(), self.state_version()); + for (mut k, (_, rc)) in stx.drain().into_iter() { + if rc > 0 { + db.sanitize_key(&mut k); + if db.get(state_col, &k).is_some() { + trace!("Benchmark-store key creation: Key collision detected, retry"); + continue 'retry + } + } + } + *original_v = new_v; + break + } + } + info!("Writing {} keys", kvs.len()); // Write each value in one commit. - for (k, original_v) in kvs.iter() { - // Create a random value to overwrite with. - // NOTE: We use a possibly higher entropy than the original value, - // could be improved but acts as an over-estimation which is fine for now. - let mut new_v = vec![0; original_v.len()]; - rng.fill_bytes(&mut new_v[..]); - + for (k, new_v) in kvs.iter() { // Interesting part here: let start = Instant::now(); // Create a TX that will modify the Trie in the DB and @@ -78,12 +96,12 @@ impl StorageCmd { let replace = vec![(k.as_ref(), Some(new_v.as_ref()))]; let (_, stx) = trie.storage_root(replace.iter().cloned(), self.state_version()); // Only the keep the insertions, since we do not want to benchmark pruning. - let tx = convert_tx::(stx.clone(), true, state_col, supports_rc); + let tx = convert_tx::(db.clone(), stx.clone(), false, state_col); db.commit(tx).map_err(|e| format!("Writing to the Database: {}", e))?; record.append(new_v.len(), start.elapsed())?; // Now undo the changes by removing what was added. - let tx = convert_tx::(stx.clone(), false, state_col, supports_rc); + let tx = convert_tx::(db.clone(), stx.clone(), true, state_col); db.commit(tx).map_err(|e| format!("Writing to the Database: {}", e))?; } Ok(record) @@ -93,35 +111,21 @@ impl StorageCmd { /// Converts a Trie transaction into a DB transaction. /// Removals are ignored and will not be included in the final tx. /// `invert_inserts` replaces all inserts with removals. -/// -/// The keys of Trie transactions are prefixed, this is treated differently by each DB. -/// ParityDB can use an optimization where only the last `DB_HASH_LEN` byte are needed. -/// The last `DB_HASH_LEN` byte are the hash of the actual stored data, everything -/// before that is the route in the Patricia Trie. -/// RocksDB cannot do this and needs the whole route, hence no key truncating for RocksDB. -/// -/// TODO: -/// This copies logic from [`sp_client_db::Backend::try_commit_operation`] and should be -/// refactored to use a canonical `sanitize_key` function from `sp_client_db` which -/// does not yet exist. fn convert_tx( + db: Arc>, mut tx: PrefixedMemoryDB>, invert_inserts: bool, col: ColumnId, - supports_rc: bool, ) -> Transaction { let mut ret = Transaction::::default(); for (mut k, (v, rc)) in tx.drain().into_iter() { - if supports_rc { - let _prefix = k.drain(0..k.len() - DB_HASH_LEN); - } - if rc > 0 { + db.sanitize_key(&mut k); if invert_inserts { - ret.set(col, k.as_ref(), &v); - } else { ret.remove(col, &k); + } else { + ret.set(col, &k, &v); } } // < 0 means removal - ignored. From cf69667d603943badcf7a17e67cbb0a727a65ac0 Mon Sep 17 00:00:00 2001 From: Georges Date: Wed, 16 Mar 2022 21:27:19 +0000 Subject: [PATCH 598/695] Moving `NposSolution` to frame (#11031) * Move `sp-npos-elections-solution-type` to `frame-election-provider-support` First stab at it, will need to amend some more stuff * Fixing tests * Fixing tests * Fixing cargo.toml for std configuration * fmt * Committing suggested changes renaming, and re exporting macro. * Removing unneeded imports * Move `NposSolution` to frame * Removing `npos_election` dependencies Implementing _fpes better * some feedback for moving NPoSSolution to frame * fmt * more formatting * Fixed some imports and fmt * Fixing docs Co-authored-by: kianenigma --- Cargo.lock | 4 +- bin/node/runtime/Cargo.toml | 2 - bin/node/runtime/src/lib.rs | 16 +-- .../src/benchmarking.rs | 2 +- .../election-provider-multi-phase/src/lib.rs | 5 +- .../election-provider-multi-phase/src/mock.rs | 4 +- .../src/signed.rs | 3 +- .../src/unsigned.rs | 12 +- .../solution-type/Cargo.toml | 2 +- .../solution-type/fuzzer/Cargo.toml | 1 + .../solution-type/src/codec.rs | 72 +++++----- .../solution-type/src/lib.rs | 14 +- .../solution-type/src/single_page.rs | 62 ++++---- frame/election-provider-support/src/lib.rs | 77 +++++++++- frame/election-provider-support/src/traits.rs | 129 +++++++++++++++++ frame/staking/src/pallet/mod.rs | 8 +- primitives/npos-elections/src/assignments.rs | 43 +----- primitives/npos-elections/src/lib.rs | 18 +-- primitives/npos-elections/src/traits.rs | 132 +----------------- 19 files changed, 313 insertions(+), 293 deletions(-) create mode 100644 frame/election-provider-support/src/traits.rs diff --git a/Cargo.lock b/Cargo.lock index e2321d7fa99d..d3cc9ab0d432 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2164,13 +2164,13 @@ dependencies = [ name = "frame-election-provider-solution-type" version = "4.0.0-dev" dependencies = [ + "frame-election-provider-support", "parity-scale-codec", "proc-macro-crate 1.1.0", "proc-macro2", "quote", "scale-info", "sp-arithmetic", - "sp-npos-elections", "syn", "trybuild", ] @@ -2198,6 +2198,7 @@ version = "2.0.0-alpha.5" dependencies = [ "clap 3.1.6", "frame-election-provider-solution-type", + "frame-election-provider-support", "honggfuzz", "parity-scale-codec", "rand 0.8.4", @@ -5065,7 +5066,6 @@ dependencies = [ "sp-core", "sp-inherents", "sp-io", - "sp-npos-elections", "sp-offchain", "sp-runtime", "sp-sandbox", diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 0572345fa0c8..686508b47dba 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -38,7 +38,6 @@ sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../.. sp-session = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/session" } sp-transaction-pool = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/transaction-pool" } sp-version = { version = "5.0.0", default-features = false, path = "../../../primitives/version" } -sp-npos-elections = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/npos-elections" } sp-io = { version = "6.0.0", default-features = false, path = "../../../primitives/io" } sp-sandbox = { version = "0.10.0-dev", default-features = false, path = "../../../primitives/sandbox" } @@ -178,7 +177,6 @@ std = [ "pallet-vesting/std", "log/std", "frame-try-runtime/std", - "sp-npos-elections/std", "sp-io/std", "pallet-child-bounties/std", ] diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 20b718e2fa8f..797e0c079028 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -23,9 +23,11 @@ #![recursion_limit = "256"] use codec::{Decode, Encode, MaxEncodedLen}; -use frame_election_provider_support::onchain; +use frame_election_provider_support::{onchain, ExtendedBalance, VoteWeight}; use frame_support::{ - construct_runtime, parameter_types, + construct_runtime, + pallet_prelude::Get, + parameter_types, traits::{ AsEnsureOriginWithArg, ConstU128, ConstU16, ConstU32, Currency, EnsureOneOf, EqualPrivilegeOnly, Everything, Imbalance, InstanceFilter, KeyOwnerProofSystem, @@ -598,7 +600,7 @@ frame_election_provider_support::generate_solution_type!( ); parameter_types! { - pub MaxNominations: u32 = ::LIMIT as u32; + pub MaxNominations: u32 = ::LIMIT as u32; } /// The numbers configured here could always be more than the the maximum limits of staking pallet @@ -621,10 +623,8 @@ pub const MINER_MAX_ITERATIONS: u32 = 10; /// A source of random balance for NposSolver, which is meant to be run by the OCW election miner. pub struct OffchainRandomBalancing; -impl frame_support::pallet_prelude::Get> - for OffchainRandomBalancing -{ - fn get() -> Option<(usize, sp_npos_elections::ExtendedBalance)> { +impl Get> for OffchainRandomBalancing { + fn get() -> Option<(usize, ExtendedBalance)> { use sp_runtime::traits::TrailingZeroInput; let iters = match MINER_MAX_ITERATIONS { 0 => 0, @@ -693,7 +693,7 @@ impl pallet_bags_list::Config for Runtime { type ScoreProvider = Staking; type WeightInfo = pallet_bags_list::weights::SubstrateWeight; type BagThresholds = BagThresholds; - type Score = sp_npos_elections::VoteWeight; + type Score = VoteWeight; } parameter_types! { diff --git a/frame/election-provider-multi-phase/src/benchmarking.rs b/frame/election-provider-multi-phase/src/benchmarking.rs index 479afd984338..b331516a4e79 100644 --- a/frame/election-provider-multi-phase/src/benchmarking.rs +++ b/frame/election-provider-multi-phase/src/benchmarking.rs @@ -28,7 +28,6 @@ use frame_support::{ use frame_system::RawOrigin; use rand::{prelude::SliceRandom, rngs::SmallRng, SeedableRng}; use sp_arithmetic::{per_things::Percent, traits::One}; -use sp_npos_elections::IndexAssignment; use sp_runtime::InnerOf; const SEED: u32 = 999; @@ -461,6 +460,7 @@ frame_benchmarking::benchmarks! { T::BenchmarkingConfig::DESIRED_TARGETS[1]; // Subtract this percentage from the actual encoded size let f in 0 .. 95; + use frame_election_provider_support::IndexAssignment; // Compute a random solution, then work backwards to get the lists of voters, targets, and // assignments diff --git a/frame/election-provider-multi-phase/src/lib.rs b/frame/election-provider-multi-phase/src/lib.rs index 7e211c5ee921..b366ceb4dafe 100644 --- a/frame/election-provider-multi-phase/src/lib.rs +++ b/frame/election-provider-multi-phase/src/lib.rs @@ -231,7 +231,7 @@ use codec::{Decode, Encode}; use frame_election_provider_support::{ - ElectionDataProvider, ElectionProvider, InstantElectionProvider, + ElectionDataProvider, ElectionProvider, InstantElectionProvider, NposSolution, }; use frame_support::{ dispatch::DispatchResultWithPostInfo, @@ -246,8 +246,7 @@ use sp_arithmetic::{ UpperOf, }; use sp_npos_elections::{ - assignment_ratio_to_staked_normalized, ElectionScore, EvaluateSupport, NposSolution, Supports, - VoteWeight, + assignment_ratio_to_staked_normalized, ElectionScore, EvaluateSupport, Supports, VoteWeight, }; use sp_runtime::{ traits::Bounded, diff --git a/frame/election-provider-multi-phase/src/mock.rs b/frame/election-provider-multi-phase/src/mock.rs index 7c4ef5d8055c..d09d45784cba 100644 --- a/frame/election-provider-multi-phase/src/mock.rs +++ b/frame/election-provider-multi-phase/src/mock.rs @@ -18,7 +18,7 @@ use super::*; use crate as multi_phase; use frame_election_provider_support::{ - data_provider, onchain, ElectionDataProvider, SequentialPhragmen, + data_provider, onchain, ElectionDataProvider, NposSolution, SequentialPhragmen, }; pub use frame_support::{assert_noop, assert_ok}; use frame_support::{ @@ -38,7 +38,7 @@ use sp_core::{ }; use sp_npos_elections::{ assignment_ratio_to_staked_normalized, seq_phragmen, to_supports, ElectionResult, - EvaluateSupport, ExtendedBalance, NposSolution, + EvaluateSupport, ExtendedBalance, }; use sp_runtime::{ testing::Header, diff --git a/frame/election-provider-multi-phase/src/signed.rs b/frame/election-provider-multi-phase/src/signed.rs index a233346b4fd7..82b40e327603 100644 --- a/frame/election-provider-multi-phase/src/signed.rs +++ b/frame/election-provider-multi-phase/src/signed.rs @@ -23,12 +23,13 @@ use crate::{ SolutionOrSnapshotSize, Weight, WeightInfo, }; use codec::{Decode, Encode, HasCompact}; +use frame_election_provider_support::NposSolution; use frame_support::{ storage::bounded_btree_map::BoundedBTreeMap, traits::{defensive_prelude::*, Currency, Get, OnUnbalanced, ReservableCurrency}, }; use sp_arithmetic::traits::SaturatedConversion; -use sp_npos_elections::{ElectionScore, NposSolution}; +use sp_npos_elections::ElectionScore; use sp_runtime::{ traits::{Saturating, Zero}, RuntimeDebug, diff --git a/frame/election-provider-multi-phase/src/unsigned.rs b/frame/election-provider-multi-phase/src/unsigned.rs index 81ea4453d096..3380a61d4310 100644 --- a/frame/election-provider-multi-phase/src/unsigned.rs +++ b/frame/election-provider-multi-phase/src/unsigned.rs @@ -23,12 +23,11 @@ use crate::{ WeightInfo, }; use codec::Encode; -use frame_election_provider_support::{NposSolver, PerThing128}; +use frame_election_provider_support::{NposSolution, NposSolver, PerThing128}; use frame_support::{dispatch::DispatchResult, ensure, traits::Get}; use frame_system::offchain::SubmitTransaction; use sp_npos_elections::{ assignment_ratio_to_staked_normalized, assignment_staked_to_ratio_normalized, ElectionResult, - NposSolution, }; use sp_runtime::{ offchain::storage::{MutateStorageError, StorageValueRef}, @@ -52,9 +51,9 @@ pub type VoterOf = frame_election_provider_support::VoterOf<::Da pub type Assignment = sp_npos_elections::Assignment<::AccountId, SolutionAccuracyOf>; -/// The [`IndexAssignment`][sp_npos_elections::IndexAssignment] type specialized for a particular -/// runtime `T`. -pub type IndexAssignmentOf = sp_npos_elections::IndexAssignmentOf>; +/// The [`IndexAssignment`][frame_election_provider_support::IndexAssignment] type specialized for a +/// particular runtime `T`. +pub type IndexAssignmentOf = frame_election_provider_support::IndexAssignmentOf>; /// Error type of the pallet's [`crate::Config::Solver`]. pub type SolverErrorOf = <::Solver as NposSolver>::Error; @@ -742,10 +741,11 @@ mod tests { }; use codec::Decode; use frame_benchmarking::Zero; + use frame_election_provider_support::IndexAssignment; use frame_support::{ assert_noop, assert_ok, bounded_vec, dispatch::Dispatchable, traits::OffchainWorker, }; - use sp_npos_elections::{ElectionScore, IndexAssignment}; + use sp_npos_elections::ElectionScore; use sp_runtime::{ offchain::storage_lock::{BlockAndTime, StorageLock}, traits::ValidateUnsigned, diff --git a/frame/election-provider-support/solution-type/Cargo.toml b/frame/election-provider-support/solution-type/Cargo.toml index d489c7b4c10d..09747eebe2df 100644 --- a/frame/election-provider-support/solution-type/Cargo.toml +++ b/frame/election-provider-support/solution-type/Cargo.toml @@ -25,5 +25,5 @@ parity-scale-codec = "3.0.0" scale-info = "2.0.1" sp-arithmetic = { version = "5.0.0", path = "../../../primitives/arithmetic" } # used by generate_solution_type: -sp-npos-elections = { version = "4.0.0-dev", path = "../../../primitives/npos-elections" } +frame-election-provider-support = { version = "4.0.0-dev", path = ".." } trybuild = "1.0.53" diff --git a/frame/election-provider-support/solution-type/fuzzer/Cargo.toml b/frame/election-provider-support/solution-type/fuzzer/Cargo.toml index f52b7f733262..f6c2f2fe491e 100644 --- a/frame/election-provider-support/solution-type/fuzzer/Cargo.toml +++ b/frame/election-provider-support/solution-type/fuzzer/Cargo.toml @@ -20,6 +20,7 @@ rand = { version = "0.8", features = ["std", "small_rng"] } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } frame-election-provider-solution-type = { version = "4.0.0-dev", path = ".." } +frame-election-provider-support = { version = "4.0.0-dev", path = "../.." } sp-arithmetic = { version = "5.0.0", path = "../../../../primitives/arithmetic" } sp-runtime = { version = "6.0.0", path = "../../../../primitives/runtime" } # used by generate_solution_type: diff --git a/frame/election-provider-support/solution-type/src/codec.rs b/frame/election-provider-support/solution-type/src/codec.rs index 71faa141f0b6..05d753d3d845 100644 --- a/frame/election-provider-support/solution-type/src/codec.rs +++ b/frame/election-provider-support/solution-type/src/codec.rs @@ -51,14 +51,14 @@ fn decode_impl( quote! { let #name = < - _npos::sp_std::prelude::Vec<(_npos::codec::Compact<#voter_type>, _npos::codec::Compact<#target_type>)> + _feps::sp_std::prelude::Vec<(_feps::codec::Compact<#voter_type>, _feps::codec::Compact<#target_type>)> as - _npos::codec::Decode + _feps::codec::Decode >::decode(value)?; let #name = #name .into_iter() .map(|(v, t)| (v.0, t.0)) - .collect::<_npos::sp_std::prelude::Vec<_>>(); + .collect::<_feps::sp_std::prelude::Vec<_>>(); } }; @@ -73,12 +73,12 @@ fn decode_impl( quote! { let #name = < - _npos::sp_std::prelude::Vec<( - _npos::codec::Compact<#voter_type>, - [(_npos::codec::Compact<#target_type>, _npos::codec::Compact<#weight_type>); #c-1], - _npos::codec::Compact<#target_type>, + _feps::sp_std::prelude::Vec<( + _feps::codec::Compact<#voter_type>, + [(_feps::codec::Compact<#target_type>, _feps::codec::Compact<#weight_type>); #c-1], + _feps::codec::Compact<#target_type>, )> - as _npos::codec::Decode + as _feps::codec::Decode >::decode(value)?; let #name = #name .into_iter() @@ -87,7 +87,7 @@ fn decode_impl( [ #inner_impl ], t_last.0, )) - .collect::<_npos::sp_std::prelude::Vec<_>>(); + .collect::<_feps::sp_std::prelude::Vec<_>>(); } }) .collect::(); @@ -100,8 +100,8 @@ fn decode_impl( .collect::(); quote!( - impl _npos::codec::Decode for #ident { - fn decode(value: &mut I) -> Result { + impl _feps::codec::Decode for #ident { + fn decode(value: &mut I) -> Result { #decode_impl_single #decode_impl_rest @@ -123,10 +123,10 @@ fn encode_impl(ident: &syn::Ident, count: usize) -> TokenStream2 { let #name = self.#name .iter() .map(|(v, t)| ( - _npos::codec::Compact(v.clone()), - _npos::codec::Compact(t.clone()), + _feps::codec::Compact(v.clone()), + _feps::codec::Compact(t.clone()), )) - .collect::<_npos::sp_std::prelude::Vec<_>>(); + .collect::<_feps::sp_std::prelude::Vec<_>>(); #name.encode_to(&mut r); } }; @@ -139,8 +139,8 @@ fn encode_impl(ident: &syn::Ident, count: usize) -> TokenStream2 { let inners_solution_array = (0..c - 1) .map(|i| { quote! {( - _npos::codec::Compact(inner[#i].0.clone()), - _npos::codec::Compact(inner[#i].1.clone()), + _feps::codec::Compact(inner[#i].0.clone()), + _feps::codec::Compact(inner[#i].1.clone()), ),} }) .collect::(); @@ -149,19 +149,19 @@ fn encode_impl(ident: &syn::Ident, count: usize) -> TokenStream2 { let #name = self.#name .iter() .map(|(v, inner, t_last)| ( - _npos::codec::Compact(v.clone()), + _feps::codec::Compact(v.clone()), [ #inners_solution_array ], - _npos::codec::Compact(t_last.clone()), + _feps::codec::Compact(t_last.clone()), )) - .collect::<_npos::sp_std::prelude::Vec<_>>(); + .collect::<_feps::sp_std::prelude::Vec<_>>(); #name.encode_to(&mut r); } }) .collect::(); quote!( - impl _npos::codec::Encode for #ident { - fn encode(&self) -> _npos::sp_std::prelude::Vec { + impl _feps::codec::Encode for #ident { + fn encode(&self) -> _feps::sp_std::prelude::Vec { let mut r = vec![]; #encode_impl_single #encode_impl_rest @@ -182,8 +182,8 @@ fn scale_info_impl( let name = format!("{}", vote_field(1)); quote! { .field(|f| - f.ty::<_npos::sp_std::prelude::Vec< - (_npos::codec::Compact<#voter_type>, _npos::codec::Compact<#target_type>) + f.ty::<_feps::sp_std::prelude::Vec< + (_feps::codec::Compact<#voter_type>, _feps::codec::Compact<#target_type>) >>() .name(#name) ) @@ -194,10 +194,10 @@ fn scale_info_impl( let name = format!("{}", vote_field(2)); quote! { .field(|f| - f.ty::<_npos::sp_std::prelude::Vec<( - _npos::codec::Compact<#voter_type>, - (_npos::codec::Compact<#target_type>, _npos::codec::Compact<#weight_type>), - _npos::codec::Compact<#target_type> + f.ty::<_feps::sp_std::prelude::Vec<( + _feps::codec::Compact<#voter_type>, + (_feps::codec::Compact<#target_type>, _feps::codec::Compact<#weight_type>), + _feps::codec::Compact<#target_type> )>>() .name(#name) ) @@ -209,13 +209,13 @@ fn scale_info_impl( let name = format!("{}", vote_field(c)); quote! { .field(|f| - f.ty::<_npos::sp_std::prelude::Vec<( - _npos::codec::Compact<#voter_type>, + f.ty::<_feps::sp_std::prelude::Vec<( + _feps::codec::Compact<#voter_type>, [ - (_npos::codec::Compact<#target_type>, _npos::codec::Compact<#weight_type>); + (_feps::codec::Compact<#target_type>, _feps::codec::Compact<#weight_type>); #c - 1 ], - _npos::codec::Compact<#target_type> + _feps::codec::Compact<#target_type> )>>() .name(#name) ) @@ -224,14 +224,14 @@ fn scale_info_impl( .collect::(); quote!( - impl _npos::scale_info::TypeInfo for #ident { + impl _feps::scale_info::TypeInfo for #ident { type Identity = Self; - fn type_info() -> _npos::scale_info::Type<_npos::scale_info::form::MetaForm> { - _npos::scale_info::Type::builder() - .path(_npos::scale_info::Path::new(stringify!(#ident), module_path!())) + fn type_info() -> _feps::scale_info::Type<_feps::scale_info::form::MetaForm> { + _feps::scale_info::Type::builder() + .path(_feps::scale_info::Path::new(stringify!(#ident), module_path!())) .composite( - _npos::scale_info::build::Fields::named() + _feps::scale_info::build::Fields::named() #scale_info_impl_single #scale_info_impl_double #scale_info_impl_rest diff --git a/frame/election-provider-support/solution-type/src/lib.rs b/frame/election-provider-support/solution-type/src/lib.rs index 3de923cdffd0..6e2788f06007 100644 --- a/frame/election-provider-support/solution-type/src/lib.rs +++ b/frame/election-provider-support/solution-type/src/lib.rs @@ -88,7 +88,7 @@ pub(crate) fn syn_err(message: &'static str) -> syn::Error { /// ``` /// /// The given struct provides function to convert from/to `Assignment` as part of -/// `sp_npos_elections::Solution` trait: +/// `frame_election_provider_support::NposSolution` trait: /// /// - `fn from_assignment<..>(..)` /// - `fn into_assignment<..>(..)` @@ -101,7 +101,7 @@ pub(crate) fn syn_err(message: &'static str) -> syn::Error { /// /// ``` /// # use frame_election_provider_solution_type::generate_solution_type; -/// # use sp_npos_elections::NposSolution; +/// # use frame_election_provider_support::NposSolution; /// # use sp_arithmetic::per_things::Perbill; /// generate_solution_type!( /// #[compact] @@ -226,11 +226,11 @@ where } fn imports() -> Result { - match crate_name("sp-npos-elections") { - Ok(FoundCrate::Itself) => Ok(quote! { use crate as _npos; }), - Ok(FoundCrate::Name(sp_npos_elections)) => { - let ident = syn::Ident::new(&sp_npos_elections, Span::call_site()); - Ok(quote!( extern crate #ident as _npos; )) + match crate_name("frame-election-provider-support") { + Ok(FoundCrate::Itself) => Ok(quote! { use crate as _feps; }), + Ok(FoundCrate::Name(frame_election_provider_support)) => { + let ident = syn::Ident::new(&frame_election_provider_support, Span::call_site()); + Ok(quote!( extern crate #ident as _feps; )) }, Err(e) => Err(syn::Error::new(Span::call_site(), e)), } diff --git a/frame/election-provider-support/solution-type/src/single_page.rs b/frame/election-provider-support/solution-type/src/single_page.rs index 01a8a8eba5dc..c1d897444da3 100644 --- a/frame/election-provider-support/solution-type/src/single_page.rs +++ b/frame/election-provider-support/solution-type/src/single_page.rs @@ -39,7 +39,7 @@ pub(crate) fn generate(def: crate::SolutionDef) -> Result { let name = vote_field(1); // NOTE: we use the visibility of the struct for the fields as well.. could be made better. quote!( - #vis #name: _npos::sp_std::prelude::Vec<(#voter_type, #target_type)>, + #vis #name: _feps::sp_std::prelude::Vec<(#voter_type, #target_type)>, ) }; @@ -48,7 +48,7 @@ pub(crate) fn generate(def: crate::SolutionDef) -> Result { let field_name = vote_field(c); let array_len = c - 1; quote!( - #vis #field_name: _npos::sp_std::prelude::Vec<( + #vis #field_name: _feps::sp_std::prelude::Vec<( #voter_type, [(#target_type, #weight_type); #array_len], #target_type @@ -83,9 +83,9 @@ pub(crate) fn generate(def: crate::SolutionDef) -> Result { Eq, Clone, Debug, - _npos::codec::Encode, - _npos::codec::Decode, - _npos::scale_info::TypeInfo, + _feps::codec::Encode, + _feps::codec::Decode, + _feps::scale_info::TypeInfo, )]) }; @@ -101,8 +101,8 @@ pub(crate) fn generate(def: crate::SolutionDef) -> Result { #derives_and_maybe_compact_encoding #vis struct #ident { #single #rest } - use _npos::__OrInvalidIndex; - impl _npos::NposSolution for #ident { + use _feps::__OrInvalidIndex; + impl _feps::NposSolution for #ident { const LIMIT: usize = #count; type VoterIndex = #voter_type; type TargetIndex = #target_type; @@ -114,34 +114,34 @@ pub(crate) fn generate(def: crate::SolutionDef) -> Result { } fn from_assignment( - assignments: &[_npos::Assignment], + assignments: &[_feps::Assignment], voter_index: FV, target_index: FT, - ) -> Result + ) -> Result where - A: _npos::IdentifierT, + A: _feps::IdentifierT, for<'r> FV: Fn(&'r A) -> Option, for<'r> FT: Fn(&'r A) -> Option, { let mut #struct_name: #ident = Default::default(); - for _npos::Assignment { who, distribution } in assignments { + for _feps::Assignment { who, distribution } in assignments { match distribution.len() { 0 => continue, #from_impl _ => { - return Err(_npos::Error::SolutionTargetOverflow); + return Err(_feps::Error::SolutionTargetOverflow); } } }; Ok(#struct_name) } - fn into_assignment( + fn into_assignment( self, voter_at: impl Fn(Self::VoterIndex) -> Option, target_at: impl Fn(Self::TargetIndex) -> Option, - ) -> Result<_npos::sp_std::prelude::Vec<_npos::Assignment>, _npos::Error> { - let mut #assignment_name: _npos::sp_std::prelude::Vec<_npos::Assignment> = Default::default(); + ) -> Result<_feps::sp_std::prelude::Vec<_feps::Assignment>, _feps::Error> { + let mut #assignment_name: _feps::sp_std::prelude::Vec<_feps::Assignment> = Default::default(); #into_impl Ok(#assignment_name) } @@ -158,10 +158,10 @@ pub(crate) fn generate(def: crate::SolutionDef) -> Result { all_edges } - fn unique_targets(&self) -> _npos::sp_std::prelude::Vec { + fn unique_targets(&self) -> _feps::sp_std::prelude::Vec { // NOTE: this implementation returns the targets sorted, but we don't use it yet per // se, nor is the API enforcing it. - use _npos::sp_std::collections::btree_set::BTreeSet; + use _feps::sp_std::collections::btree_set::BTreeSet; let mut all_targets: BTreeSet = BTreeSet::new(); let mut maybe_insert_target = |t: Self::TargetIndex| { all_targets.insert(t); @@ -173,22 +173,22 @@ pub(crate) fn generate(def: crate::SolutionDef) -> Result { } } - type __IndexAssignment = _npos::IndexAssignment< - <#ident as _npos::NposSolution>::VoterIndex, - <#ident as _npos::NposSolution>::TargetIndex, - <#ident as _npos::NposSolution>::Accuracy, + type __IndexAssignment = _feps::IndexAssignment< + <#ident as _feps::NposSolution>::VoterIndex, + <#ident as _feps::NposSolution>::TargetIndex, + <#ident as _feps::NposSolution>::Accuracy, >; - impl<'a> _npos::sp_std::convert::TryFrom<&'a [__IndexAssignment]> for #ident { - type Error = _npos::Error; + impl<'a> _feps::sp_std::convert::TryFrom<&'a [__IndexAssignment]> for #ident { + type Error = _feps::Error; fn try_from(index_assignments: &'a [__IndexAssignment]) -> Result { let mut #struct_name = #ident::default(); - for _npos::IndexAssignment { who, distribution } in index_assignments { + for _feps::IndexAssignment { who, distribution } in index_assignments { match distribution.len() { 0 => {} #from_index_impl _ => { - return Err(_npos::Error::SolutionTargetOverflow); + return Err(_feps::Error::SolutionTargetOverflow); } } }; @@ -310,7 +310,7 @@ pub(crate) fn into_impl( let name = vote_field(1); quote!( for (voter_index, target_index) in self.#name { - #assignments.push(_npos::Assignment { + #assignments.push(_feps::Assignment { who: voter_at(voter_index).or_invalid_index()?, distribution: vec![ (target_at(target_index).or_invalid_index()?, #per_thing::one()) @@ -329,25 +329,25 @@ pub(crate) fn into_impl( let mut inners_parsed = inners .iter() .map(|(ref t_idx, p)| { - sum = _npos::sp_arithmetic::traits::Saturating::saturating_add(sum, *p); + sum = _feps::sp_arithmetic::traits::Saturating::saturating_add(sum, *p); let target = target_at(*t_idx).or_invalid_index()?; Ok((target, *p)) }) - .collect::, _npos::Error>>()?; + .collect::, _feps::Error>>()?; if sum >= #per_thing::one() { - return Err(_npos::Error::SolutionWeightOverflow); + return Err(_feps::Error::SolutionWeightOverflow); } // defensive only. Since Percent doesn't have `Sub`. - let p_last = _npos::sp_arithmetic::traits::Saturating::saturating_sub( + let p_last = _feps::sp_arithmetic::traits::Saturating::saturating_sub( #per_thing::one(), sum, ); inners_parsed.push((target_at(t_last_idx).or_invalid_index()?, p_last)); - #assignments.push(_npos::Assignment { + #assignments.push(_feps::Assignment { who: voter_at(voter_index).or_invalid_index()?, distribution: inners_parsed, }); diff --git a/frame/election-provider-support/src/lib.rs b/frame/election-provider-support/src/lib.rs index 1bd10ba09346..ca95eda6b509 100644 --- a/frame/election-provider-support/src/lib.rs +++ b/frame/election-provider-support/src/lib.rs @@ -167,17 +167,86 @@ #![cfg_attr(not(feature = "std"), no_std)] pub mod onchain; -use frame_support::{traits::Get, BoundedVec}; +pub mod traits; +use codec::{Decode, Encode}; +use frame_support::{traits::Get, BoundedVec, RuntimeDebug}; use sp_runtime::traits::Bounded; use sp_std::{fmt::Debug, prelude::*}; -/// Re-export some type as they are used in the interface. +/// Re-export the solution generation macro. pub use frame_election_provider_solution_type::generate_solution_type; +/// Re-export some type as they are used in the interface. pub use sp_arithmetic::PerThing; pub use sp_npos_elections::{ - Assignment, ElectionResult, ExtendedBalance, IdentifierT, PerThing128, Support, Supports, - VoteWeight, + Assignment, ElectionResult, Error, ExtendedBalance, IdentifierT, PerThing128, Support, + Supports, VoteWeight, }; +pub use traits::NposSolution; + +// re-export for the solution macro, with the dependencies of the macro. +#[doc(hidden)] +pub use codec; +#[doc(hidden)] +pub use scale_info; +#[doc(hidden)] +pub use sp_arithmetic; +#[doc(hidden)] +pub use sp_std; +// Simple Extension trait to easily convert `None` from index closures to `Err`. +// +// This is only generated and re-exported for the solution code to use. +#[doc(hidden)] +pub trait __OrInvalidIndex { + fn or_invalid_index(self) -> Result; +} + +impl __OrInvalidIndex for Option { + fn or_invalid_index(self) -> Result { + self.ok_or(Error::SolutionInvalidIndex) + } +} + +/// The [`IndexAssignment`] type is an intermediate between the assignments list +/// ([`&[Assignment]`][Assignment]) and `SolutionOf`. +/// +/// The voter and target identifiers have already been replaced with appropriate indices, +/// making it fast to repeatedly encode into a `SolutionOf`. This property turns out +/// to be important when trimming for solution length. +#[derive(RuntimeDebug, Clone, Default)] +#[cfg_attr(feature = "std", derive(PartialEq, Eq, Encode, Decode))] +pub struct IndexAssignment { + /// Index of the voter among the voters list. + pub who: VoterIndex, + /// The distribution of the voter's stake among winning targets. + /// + /// Targets are identified by their index in the canonical list. + pub distribution: Vec<(TargetIndex, P)>, +} + +impl IndexAssignment { + pub fn new( + assignment: &Assignment, + voter_index: impl Fn(&AccountId) -> Option, + target_index: impl Fn(&AccountId) -> Option, + ) -> Result { + Ok(Self { + who: voter_index(&assignment.who).or_invalid_index()?, + distribution: assignment + .distribution + .iter() + .map(|(target, proportion)| Some((target_index(target)?, proportion.clone()))) + .collect::>>() + .or_invalid_index()?, + }) + } +} + +/// A type alias for [`IndexAssignment`] made from [`NposSolution`]. +pub type IndexAssignmentOf = IndexAssignment< + ::VoterIndex, + ::TargetIndex, + ::Accuracy, +>; /// Types that are used by the data provider trait. pub mod data_provider { diff --git a/frame/election-provider-support/src/traits.rs b/frame/election-provider-support/src/traits.rs new file mode 100644 index 000000000000..e1fc0663e7d1 --- /dev/null +++ b/frame/election-provider-support/src/traits.rs @@ -0,0 +1,129 @@ +// This file is part of Substrate. + +// Copyright (C) 2019-2022 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 +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Traits for the election operations. + +use crate::{Assignment, IdentifierT, IndexAssignmentOf, PerThing128, VoteWeight}; +use codec::Encode; +use scale_info::TypeInfo; +use sp_arithmetic::traits::{Bounded, UniqueSaturatedInto}; +use sp_npos_elections::{ElectionScore, Error, EvaluateSupport}; +use sp_std::{ + convert::{TryFrom, TryInto}, + fmt::Debug, + prelude::*, +}; + +/// An opaque index-based, NPoS solution type. +pub trait NposSolution +where + Self: Sized + for<'a> sp_std::convert::TryFrom<&'a [IndexAssignmentOf], Error = Error>, +{ + /// The maximum number of votes that are allowed. + const LIMIT: usize; + + /// The voter type. Needs to be an index (convert to usize). + type VoterIndex: UniqueSaturatedInto + + TryInto + + TryFrom + + Debug + + Copy + + Clone + + Bounded + + Encode + + TypeInfo; + + /// The target type. Needs to be an index (convert to usize). + type TargetIndex: UniqueSaturatedInto + + TryInto + + TryFrom + + Debug + + Copy + + Clone + + Bounded + + Encode + + TypeInfo; + + /// The weight/accuracy type of each vote. + type Accuracy: PerThing128; + + /// Get the length of all the voters that this type is encoding. + /// + /// This is basically the same as the number of assignments, or number of active voters. + fn voter_count(&self) -> usize; + + /// Get the total count of edges. + /// + /// This is effectively in the range of {[`Self::voter_count`], [`Self::voter_count`] * + /// [`Self::LIMIT`]}. + fn edge_count(&self) -> usize; + + /// Get the number of unique targets in the whole struct. + /// + /// Once presented with a list of winners, this set and the set of winners must be + /// equal. + fn unique_targets(&self) -> Vec; + + /// Get the average edge count. + fn average_edge_count(&self) -> usize { + self.edge_count().checked_div(self.voter_count()).unwrap_or(0) + } + + /// Compute the score of this solution type. + fn score( + self, + stake_of: FS, + voter_at: impl Fn(Self::VoterIndex) -> Option, + target_at: impl Fn(Self::TargetIndex) -> Option, + ) -> Result + where + for<'r> FS: Fn(&'r A) -> VoteWeight, + A: IdentifierT, + { + let ratio = self.into_assignment(voter_at, target_at)?; + let staked = + sp_npos_elections::helpers::assignment_ratio_to_staked_normalized(ratio, stake_of)?; + let supports = sp_npos_elections::to_supports(&staked); + Ok(supports.evaluate()) + } + + /// Remove a certain voter. + /// + /// This will only search until the first instance of `to_remove`, and return true. If + /// no instance is found (no-op), then it returns false. + /// + /// In other words, if this return true, exactly **one** element must have been removed self. + fn remove_voter(&mut self, to_remove: Self::VoterIndex) -> bool; + + /// Build self from a list of assignments. + fn from_assignment( + assignments: &[Assignment], + voter_index: FV, + target_index: FT, + ) -> Result + where + A: IdentifierT, + for<'r> FV: Fn(&'r A) -> Option, + for<'r> FT: Fn(&'r A) -> Option; + + /// Convert self into a `Vec>` + fn into_assignment( + self, + voter_at: impl Fn(Self::VoterIndex) -> Option, + target_at: impl Fn(Self::TargetIndex) -> Option, + ) -> Result>, Error>; +} diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index b50ce5ed4502..39173bf61c83 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -40,9 +40,9 @@ mod impls; pub use impls::*; use crate::{ - log, slashing, weights::WeightInfo, ActiveEraInfo, BalanceOf, EraPayout, EraRewardPoints, - Exposure, Forcing, MaxUnlockingChunks, NegativeImbalanceOf, Nominations, PositiveImbalanceOf, - Releases, RewardDestination, SessionInterface, StakingLedger, UnappliedSlash, UnlockChunk, + slashing, weights::WeightInfo, ActiveEraInfo, BalanceOf, EraPayout, EraRewardPoints, Exposure, + Forcing, MaxUnlockingChunks, NegativeImbalanceOf, Nominations, PositiveImbalanceOf, Releases, + RewardDestination, SessionInterface, StakingLedger, UnappliedSlash, UnlockChunk, ValidatorPrefs, }; @@ -554,7 +554,7 @@ pub mod pallet { } for &(ref stash, ref controller, balance, ref status) in &self.stakers { - log!( + crate::log!( trace, "inserting genesis staker: {:?} => {:?} => {:?}", stash, diff --git a/primitives/npos-elections/src/assignments.rs b/primitives/npos-elections/src/assignments.rs index 5641a33447ba..9422ccdf6588 100644 --- a/primitives/npos-elections/src/assignments.rs +++ b/primitives/npos-elections/src/assignments.rs @@ -17,7 +17,7 @@ //! Structs and helpers for distributing a voter's stake among various winners. -use crate::{Error, ExtendedBalance, IdentifierT, PerThing128, __OrInvalidIndex}; +use crate::{ExtendedBalance, IdentifierT, PerThing128}; #[cfg(feature = "std")] use codec::{Decode, Encode}; use sp_arithmetic::{ @@ -166,44 +166,3 @@ impl StakedAssignment { self.distribution.iter().fold(Zero::zero(), |a, b| a.saturating_add(b.1)) } } -/// The [`IndexAssignment`] type is an intermediate between the assignments list -/// ([`&[Assignment]`][Assignment]) and `SolutionOf`. -/// -/// The voter and target identifiers have already been replaced with appropriate indices, -/// making it fast to repeatedly encode into a `SolutionOf`. This property turns out -/// to be important when trimming for solution length. -#[derive(RuntimeDebug, Clone, Default)] -#[cfg_attr(feature = "std", derive(PartialEq, Eq, Encode, Decode))] -pub struct IndexAssignment { - /// Index of the voter among the voters list. - pub who: VoterIndex, - /// The distribution of the voter's stake among winning targets. - /// - /// Targets are identified by their index in the canonical list. - pub distribution: Vec<(TargetIndex, P)>, -} - -impl IndexAssignment { - pub fn new( - assignment: &Assignment, - voter_index: impl Fn(&AccountId) -> Option, - target_index: impl Fn(&AccountId) -> Option, - ) -> Result { - Ok(Self { - who: voter_index(&assignment.who).or_invalid_index()?, - distribution: assignment - .distribution - .iter() - .map(|(target, proportion)| Some((target_index(target)?, proportion.clone()))) - .collect::>>() - .or_invalid_index()?, - }) - } -} - -/// A type alias for [`IndexAssignment`] made from [`crate::NposSolution`]. -pub type IndexAssignmentOf = IndexAssignment< - ::VoterIndex, - ::TargetIndex, - ::Accuracy, ->; diff --git a/primitives/npos-elections/src/lib.rs b/primitives/npos-elections/src/lib.rs index 673036c2d19d..11d531fa56d8 100644 --- a/primitives/npos-elections/src/lib.rs +++ b/primitives/npos-elections/src/lib.rs @@ -100,26 +100,16 @@ pub mod pjr; pub mod reduce; pub mod traits; -pub use assignments::{Assignment, IndexAssignment, IndexAssignmentOf, StakedAssignment}; +pub use assignments::{Assignment, StakedAssignment}; pub use balancing::*; pub use helpers::*; pub use phragmen::*; pub use phragmms::*; pub use pjr::*; pub use reduce::reduce; -pub use traits::{IdentifierT, NposSolution, PerThing128, __OrInvalidIndex}; - -// re-export for the solution macro, with the dependencies of the macro. -#[doc(hidden)] -pub use codec; -#[doc(hidden)] -pub use scale_info; -#[doc(hidden)] -pub use sp_arithmetic; -#[doc(hidden)] -pub use sp_std; - -/// The errors that might occur in the this crate and solution-type. +pub use traits::{IdentifierT, PerThing128}; + +/// The errors that might occur in this crate and `frame-election-provider-solution-type`. #[derive(Eq, PartialEq, RuntimeDebug)] pub enum Error { /// While going from solution indices to ratio, the weight of all the edges has gone above the diff --git a/primitives/npos-elections/src/traits.rs b/primitives/npos-elections/src/traits.rs index 0723948b6226..91026f9de4b6 100644 --- a/primitives/npos-elections/src/traits.rs +++ b/primitives/npos-elections/src/traits.rs @@ -17,22 +17,9 @@ //! Traits for the npos-election operations. -use crate::{ - Assignment, ElectionScore, Error, EvaluateSupport, ExtendedBalance, IndexAssignmentOf, - VoteWeight, -}; -use codec::Encode; -use scale_info::TypeInfo; -use sp_arithmetic::{ - traits::{Bounded, UniqueSaturatedInto}, - PerThing, -}; -use sp_std::{ - convert::{TryFrom, TryInto}, - fmt::Debug, - ops::Mul, - prelude::*, -}; +use crate::ExtendedBalance; +use sp_arithmetic::PerThing; +use sp_std::{fmt::Debug, ops::Mul, prelude::*}; /// an aggregator trait for a generic type of a voter/target identifier. This usually maps to /// substrate's account id. @@ -42,116 +29,3 @@ impl IdentifierT for T {} /// Aggregator trait for a PerThing that can be multiplied by u128 (ExtendedBalance). pub trait PerThing128: PerThing + Mul {} impl> PerThing128 for T {} - -/// Simple Extension trait to easily convert `None` from index closures to `Err`. -/// -/// This is only generated and re-exported for the solution code to use. -#[doc(hidden)] -pub trait __OrInvalidIndex { - fn or_invalid_index(self) -> Result; -} - -impl __OrInvalidIndex for Option { - fn or_invalid_index(self) -> Result { - self.ok_or(Error::SolutionInvalidIndex) - } -} - -/// An opaque index-based, NPoS solution type. -pub trait NposSolution -where - Self: Sized + for<'a> sp_std::convert::TryFrom<&'a [IndexAssignmentOf], Error = Error>, -{ - /// The maximum number of votes that are allowed. - const LIMIT: usize; - - /// The voter type. Needs to be an index (convert to usize). - type VoterIndex: UniqueSaturatedInto - + TryInto - + TryFrom - + Debug - + Copy - + Clone - + Bounded - + Encode - + TypeInfo; - - /// The target type. Needs to be an index (convert to usize). - type TargetIndex: UniqueSaturatedInto - + TryInto - + TryFrom - + Debug - + Copy - + Clone - + Bounded - + Encode - + TypeInfo; - - /// The weight/accuracy type of each vote. - type Accuracy: PerThing128; - - /// Get the length of all the voters that this type is encoding. - /// - /// This is basically the same as the number of assignments, or number of active voters. - fn voter_count(&self) -> usize; - - /// Get the total count of edges. - /// - /// This is effectively in the range of {[`Self::voter_count`], [`Self::voter_count`] * - /// [`Self::LIMIT`]}. - fn edge_count(&self) -> usize; - - /// Get the number of unique targets in the whole struct. - /// - /// Once presented with a list of winners, this set and the set of winners must be - /// equal. - fn unique_targets(&self) -> Vec; - - /// Get the average edge count. - fn average_edge_count(&self) -> usize { - self.edge_count().checked_div(self.voter_count()).unwrap_or(0) - } - - /// Compute the score of this solution type. - fn score( - self, - stake_of: FS, - voter_at: impl Fn(Self::VoterIndex) -> Option, - target_at: impl Fn(Self::TargetIndex) -> Option, - ) -> Result - where - for<'r> FS: Fn(&'r A) -> VoteWeight, - A: IdentifierT, - { - let ratio = self.into_assignment(voter_at, target_at)?; - let staked = crate::helpers::assignment_ratio_to_staked_normalized(ratio, stake_of)?; - let supports = crate::to_supports(&staked); - Ok(supports.evaluate()) - } - - /// Remove a certain voter. - /// - /// This will only search until the first instance of `to_remove`, and return true. If - /// no instance is found (no-op), then it returns false. - /// - /// In other words, if this return true, exactly **one** element must have been removed self. - fn remove_voter(&mut self, to_remove: Self::VoterIndex) -> bool; - - /// Build self from a list of assignments. - fn from_assignment( - assignments: &[Assignment], - voter_index: FV, - target_index: FT, - ) -> Result - where - A: IdentifierT, - for<'r> FV: Fn(&'r A) -> Option, - for<'r> FT: Fn(&'r A) -> Option; - - /// Convert self into a `Vec>` - fn into_assignment( - self, - voter_at: impl Fn(Self::VoterIndex) -> Option, - target_at: impl Fn(Self::TargetIndex) -> Option, - ) -> Result>, Error>; -} From 89682c1fd676816dc261959fee0c1d6cece98384 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Thu, 17 Mar 2022 11:40:31 +0100 Subject: [PATCH 599/695] Add execution overhead benchmarking (#10977) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add benchmark-block Signed-off-by: Oliver Tale-Yazdi * Remove first approach This reverts commit 9ce7f32cae12ce637bd3b85d255dd55ba7198f9d. * Add block and extrinsic benchmarks * Doc Signed-off-by: Oliver Tale-Yazdi * Fix template Signed-off-by: Oliver Tale-Yazdi * Beauty fixes Signed-off-by: Oliver Tale-Yazdi * Check for non-empty chain Signed-off-by: Oliver Tale-Yazdi * Add tests for Stats Signed-off-by: Oliver Tale-Yazdi * Review fixes Signed-off-by: Oliver Tale-Yazdi * Review fixes Signed-off-by: Oliver Tale-Yazdi * Apply suggestions from code review Co-authored-by: Shawn Tabrizi * Review fixes Signed-off-by: Oliver Tale-Yazdi * Review fixes Signed-off-by: Oliver Tale-Yazdi * Push first version again Signed-off-by: Oliver Tale-Yazdi * Push first version again Signed-off-by: Oliver Tale-Yazdi * Cleanup Signed-off-by: Oliver Tale-Yazdi * Cleanup Signed-off-by: Oliver Tale-Yazdi * Cleanup Signed-off-by: Oliver Tale-Yazdi * Beauty fixes Signed-off-by: Oliver Tale-Yazdi * Apply suggestions from code review Co-authored-by: Bastian Köcher * Update utils/frame/benchmarking-cli/src/overhead/template.rs Co-authored-by: Bastian Köcher * Review fixes Signed-off-by: Oliver Tale-Yazdi * Doc + Template fixes Signed-off-by: Oliver Tale-Yazdi * Review fixes Signed-off-by: Oliver Tale-Yazdi * Comment fix Signed-off-by: Oliver Tale-Yazdi * Add test Signed-off-by: Oliver Tale-Yazdi * Pust merge fixup Signed-off-by: Oliver Tale-Yazdi * Fixup Signed-off-by: Oliver Tale-Yazdi * Move code to better place Signed-off-by: Oliver Tale-Yazdi Co-authored-by: Shawn Tabrizi Co-authored-by: Bastian Köcher --- Cargo.lock | 2 + bin/node/cli/src/cli.rs | 7 + bin/node/cli/src/command.rs | 25 ++- bin/node/cli/src/command_helper.rs | 69 ++++++ bin/node/cli/src/lib.rs | 2 + .../cli/tests/benchmark_overhead_works.rs | 46 ++++ utils/frame/benchmarking-cli/Cargo.toml | 2 + utils/frame/benchmarking-cli/src/lib.rs | 3 + .../benchmarking-cli/src/overhead/bench.rs | 210 ++++++++++++++++++ .../benchmarking-cli/src/overhead/cmd.rs | 118 ++++++++++ .../benchmarking-cli/src/overhead/mod.rs | 22 ++ .../benchmarking-cli/src/overhead/template.rs | 110 +++++++++ .../benchmarking-cli/src/overhead/weights.hbs | 92 ++++++++ .../src/post_processing/mod.rs | 95 ++++++++ .../frame/benchmarking-cli/src/storage/cmd.rs | 27 +-- .../benchmarking-cli/src/storage/record.rs | 59 ++++- .../benchmarking-cli/src/storage/template.rs | 16 +- 17 files changed, 852 insertions(+), 53 deletions(-) create mode 100644 bin/node/cli/src/command_helper.rs create mode 100644 bin/node/cli/tests/benchmark_overhead_works.rs create mode 100644 utils/frame/benchmarking-cli/src/overhead/bench.rs create mode 100644 utils/frame/benchmarking-cli/src/overhead/cmd.rs create mode 100644 utils/frame/benchmarking-cli/src/overhead/mod.rs create mode 100644 utils/frame/benchmarking-cli/src/overhead/template.rs create mode 100644 utils/frame/benchmarking-cli/src/overhead/weights.hbs create mode 100644 utils/frame/benchmarking-cli/src/post_processing/mod.rs diff --git a/Cargo.lock b/Cargo.lock index d3cc9ab0d432..fb9561dfabdc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2139,6 +2139,7 @@ dependencies = [ "memory-db", "parity-scale-codec", "rand 0.8.4", + "sc-block-builder", "sc-cli", "sc-client-api", "sc-client-db", @@ -2152,6 +2153,7 @@ dependencies = [ "sp-core", "sp-database", "sp-externalities", + "sp-inherents", "sp-keystore", "sp-runtime", "sp-state-machine", diff --git a/bin/node/cli/src/cli.rs b/bin/node/cli/src/cli.rs index 386215854b96..a911cc26ef87 100644 --- a/bin/node/cli/src/cli.rs +++ b/bin/node/cli/src/cli.rs @@ -42,6 +42,13 @@ pub enum Subcommand { #[clap(name = "benchmark", about = "Benchmark runtime pallets.")] Benchmark(frame_benchmarking_cli::BenchmarkCmd), + /// Sub command for benchmarking the per-block and per-extrinsic execution overhead. + #[clap( + name = "benchmark-overhead", + about = "Benchmark the per-block and per-extrinsic execution overhead." + )] + BenchmarkOverhead(frame_benchmarking_cli::OverheadCmd), + /// Sub command for benchmarking the storage speed. #[clap(name = "benchmark-storage", about = "Benchmark storage speed.")] BenchmarkStorage(frame_benchmarking_cli::StorageCmd), diff --git a/bin/node/cli/src/command.rs b/bin/node/cli/src/command.rs index cc6480bb90d5..e208e324ee2a 100644 --- a/bin/node/cli/src/command.rs +++ b/bin/node/cli/src/command.rs @@ -18,10 +18,13 @@ use crate::{chain_spec, service, service::new_partial, Cli, Subcommand}; use node_executor::ExecutorDispatch; -use node_runtime::{Block, RuntimeApi}; +use node_primitives::Block; +use node_runtime::RuntimeApi; use sc_cli::{ChainSpec, Result, RuntimeVersion, SubstrateCli}; use sc_service::PartialComponents; +use std::sync::Arc; + impl SubstrateCli for Cli { fn impl_name() -> String { "Substrate Node".into() @@ -95,13 +98,21 @@ pub fn run() -> Result<()> { You can enable it with `--features runtime-benchmarks`." .into()) }, - Some(Subcommand::BenchmarkStorage(cmd)) => { - if !cfg!(feature = "runtime-benchmarks") { - return Err("Benchmarking wasn't enabled when building the node. \ - You can enable it with `--features runtime-benchmarks`." - .into()) - } + Some(Subcommand::BenchmarkOverhead(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.async_run(|mut config| { + use super::command_helper::{inherent_data, ExtrinsicBuilder}; + // We don't use the authority role since that would start producing blocks + // in the background which would mess with our benchmark. + config.role = sc_service::Role::Full; + let PartialComponents { client, task_manager, .. } = new_partial(&config)?; + let ext_builder = ExtrinsicBuilder::new(client.clone()); + + Ok((cmd.run(config, client, inherent_data()?, Arc::new(ext_builder)), task_manager)) + }) + }, + Some(Subcommand::BenchmarkStorage(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { let PartialComponents { client, task_manager, backend, .. } = new_partial(&config)?; diff --git a/bin/node/cli/src/command_helper.rs b/bin/node/cli/src/command_helper.rs new file mode 100644 index 000000000000..51fe7a5c5a7b --- /dev/null +++ b/bin/node/cli/src/command_helper.rs @@ -0,0 +1,69 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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 . + +//! Contains code to setup the command invocations in [`super::command`] which would +//! otherwise bloat that module. + +use crate::service::{create_extrinsic, FullClient}; + +use node_runtime::SystemCall; +use sc_cli::Result; +use sp_inherents::{InherentData, InherentDataProvider}; +use sp_keyring::Sr25519Keyring; +use sp_runtime::OpaqueExtrinsic; + +use std::{sync::Arc, time::Duration}; + +/// Generates extrinsics for the `benchmark-overhead` command. +pub struct ExtrinsicBuilder { + client: Arc, +} + +impl ExtrinsicBuilder { + /// Creates a new [`Self`] from the given client. + pub fn new(client: Arc) -> Self { + Self { client } + } +} + +impl frame_benchmarking_cli::ExtrinsicBuilder for ExtrinsicBuilder { + fn remark(&self, nonce: u32) -> std::result::Result { + let acc = Sr25519Keyring::Bob.pair(); + let extrinsic: OpaqueExtrinsic = create_extrinsic( + self.client.as_ref(), + acc, + SystemCall::remark { remark: vec![] }, + Some(nonce), + ) + .into(); + + Ok(extrinsic) + } +} + +/// Generates inherent data for the `benchmark-overhead` command. +pub fn inherent_data() -> Result { + let mut inherent_data = InherentData::new(); + let d = Duration::from_millis(0); + let timestamp = sp_timestamp::InherentDataProvider::new(d.into()); + + timestamp + .provide_inherent_data(&mut inherent_data) + .map_err(|e| format!("creating inherent data: {:?}", e))?; + Ok(inherent_data) +} diff --git a/bin/node/cli/src/lib.rs b/bin/node/cli/src/lib.rs index 791140a25484..06c0bcccbc29 100644 --- a/bin/node/cli/src/lib.rs +++ b/bin/node/cli/src/lib.rs @@ -38,6 +38,8 @@ pub mod service; mod cli; #[cfg(feature = "cli")] mod command; +#[cfg(feature = "cli")] +mod command_helper; #[cfg(feature = "cli")] pub use cli::*; diff --git a/bin/node/cli/tests/benchmark_overhead_works.rs b/bin/node/cli/tests/benchmark_overhead_works.rs new file mode 100644 index 000000000000..550221ee2f70 --- /dev/null +++ b/bin/node/cli/tests/benchmark_overhead_works.rs @@ -0,0 +1,46 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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 . + +use assert_cmd::cargo::cargo_bin; +use std::process::Command; +use tempfile::tempdir; + +/// Tests that the `benchmark-overhead` command works for the substrate dev runtime. +#[test] +fn benchmark_overhead_works() { + let tmp_dir = tempdir().expect("could not create a temp dir"); + let base_path = tmp_dir.path(); + + // Only put 10 extrinsics into the block otherwise it takes forever to build it + // especially for a non-release build. + let status = Command::new(cargo_bin("substrate")) + .args(&["benchmark-overhead", "--dev", "-d"]) + .arg(base_path) + .arg("--weight-path") + .arg(base_path) + .args(["--warmup", "10", "--repeat", "10"]) + .args(["--add", "100", "--mul", "1.2", "--metric", "p75"]) + .args(["--max-ext-per-block", "10"]) + .status() + .unwrap(); + assert!(status.success()); + + // Weight files have been created. + assert!(base_path.join("block_weights.rs").exists()); + assert!(base_path.join("extrinsic_weights.rs").exists()); +} diff --git a/utils/frame/benchmarking-cli/Cargo.toml b/utils/frame/benchmarking-cli/Cargo.toml index 81e7396db3e6..5575bb833ca7 100644 --- a/utils/frame/benchmarking-cli/Cargo.toml +++ b/utils/frame/benchmarking-cli/Cargo.toml @@ -16,6 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] frame-benchmarking = { version = "4.0.0-dev", path = "../../../frame/benchmarking" } frame-support = { version = "4.0.0-dev", path = "../../../frame/support" } sp-core = { version = "6.0.0", path = "../../../primitives/core" } +sc-block-builder = { version = "0.10.0-dev", path = "../../../client/block-builder" } sc-service = { version = "0.10.0-dev", default-features = false, path = "../../../client/service" } sc-client-api = { version = "4.0.0-dev", path = "../../../client/api" } sc-cli = { version = "0.10.0-dev", path = "../../../client/cli" } @@ -26,6 +27,7 @@ sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-externalities = { version = "0.12.0", path = "../../../primitives/externalities" } sp-database = { version = "4.0.0-dev", path = "../../../primitives/database" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } +sp-inherents = { version = "4.0.0-dev", path = "../../../primitives/inherents" } sp-keystore = { version = "0.12.0", path = "../../../primitives/keystore" } sp-storage = { version = "6.0.0", path = "../../../primitives/storage" } sp-runtime = { version = "6.0.0", path = "../../../primitives/runtime" } diff --git a/utils/frame/benchmarking-cli/src/lib.rs b/utils/frame/benchmarking-cli/src/lib.rs index 9815fe88a7f0..e06d57963dad 100644 --- a/utils/frame/benchmarking-cli/src/lib.rs +++ b/utils/frame/benchmarking-cli/src/lib.rs @@ -16,12 +16,15 @@ // limitations under the License. mod command; +pub mod overhead; +mod post_processing; mod storage; mod writer; use sc_cli::{ExecutionStrategy, WasmExecutionMethod, DEFAULT_WASM_EXECUTION_METHOD}; use std::{fmt::Debug, path::PathBuf}; +pub use overhead::{ExtrinsicBuilder, OverheadCmd}; pub use storage::StorageCmd; // Add a more relaxed parsing for pallet names by allowing pallet directory names with `-` to be diff --git a/utils/frame/benchmarking-cli/src/overhead/bench.rs b/utils/frame/benchmarking-cli/src/overhead/bench.rs new file mode 100644 index 000000000000..3e18c6a86db2 --- /dev/null +++ b/utils/frame/benchmarking-cli/src/overhead/bench.rs @@ -0,0 +1,210 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +//! Contains the core benchmarking logic. + +use sc_block_builder::{BlockBuilderApi, BlockBuilderProvider}; +use sc_cli::{Error, Result}; +use sc_client_api::Backend as ClientBackend; +use sp_api::{ApiExt, BlockId, Core, ProvideRuntimeApi}; +use sp_blockchain::{ + ApplyExtrinsicFailed::Validity, + Error::{ApplyExtrinsicFailed, RuntimeApiError}, +}; +use sp_runtime::{ + traits::{Block as BlockT, Zero}, + transaction_validity::{InvalidTransaction, TransactionValidityError}, + OpaqueExtrinsic, +}; + +use clap::Args; +use log::info; +use serde::Serialize; +use std::{marker::PhantomData, sync::Arc, time::Instant}; + +use crate::{overhead::cmd::ExtrinsicBuilder, storage::record::Stats}; + +/// Parameters to configure an *overhead* benchmark. +#[derive(Debug, Default, Serialize, Clone, PartialEq, Args)] +pub struct BenchmarkParams { + /// Rounds of warmups before measuring. + #[clap(long, default_value = "100")] + pub warmup: u32, + + /// How many times the benchmark should be repeated. + #[clap(long, default_value = "1000")] + pub repeat: u32, + + /// Maximal number of extrinsics that should be put into a block. + /// + /// Only useful for debugging. + #[clap(long)] + pub max_ext_per_block: Option, +} + +/// The results of multiple runs in nano seconds. +pub(crate) type BenchRecord = Vec; + +/// Type of a benchmark. +#[derive(Serialize, Clone, PartialEq, Copy)] +pub(crate) enum BenchmarkType { + /// Measure the per-extrinsic execution overhead. + Extrinsic, + /// Measure the per-block execution overhead. + Block, +} + +/// Holds all objects needed to run the *overhead* benchmarks. +pub(crate) struct Benchmark { + client: Arc, + params: BenchmarkParams, + inherent_data: sp_inherents::InherentData, + ext_builder: Arc, + _p: PhantomData<(Block, BA)>, +} + +impl Benchmark +where + Block: BlockT, + BA: ClientBackend, + C: BlockBuilderProvider + ProvideRuntimeApi, + C::Api: ApiExt + BlockBuilderApi, +{ + /// Create a new [`Self`] from the arguments. + pub fn new( + client: Arc, + params: BenchmarkParams, + inherent_data: sp_inherents::InherentData, + ext_builder: Arc, + ) -> Self { + Self { client, params, inherent_data, ext_builder, _p: PhantomData } + } + + /// Run the specified benchmark. + pub fn bench(&self, bench_type: BenchmarkType) -> Result { + let (block, num_ext) = self.build_block(bench_type)?; + let record = self.measure_block(&block, num_ext, bench_type)?; + Stats::new(&record) + } + + /// Builds a block for the given benchmark type. + /// + /// Returns the block and the number of extrinsics in the block + /// that are not inherents. + fn build_block(&self, bench_type: BenchmarkType) -> Result<(Block, u64)> { + let mut builder = self.client.new_block(Default::default())?; + // Create and insert the inherents. + let inherents = builder.create_inherents(self.inherent_data.clone())?; + for inherent in inherents { + builder.push(inherent)?; + } + + // Return early if we just want a block with inherents and no additional extrinsics. + if bench_type == BenchmarkType::Block { + return Ok((builder.build()?.block, 0)) + } + + // Put as many extrinsics into the block as possible and count them. + info!("Building block, this takes some time..."); + let mut num_ext = 0; + for nonce in 0..self.max_ext_per_block() { + let ext = self.ext_builder.remark(nonce)?; + match builder.push(ext.clone()) { + Ok(()) => {}, + Err(ApplyExtrinsicFailed(Validity(TransactionValidityError::Invalid( + InvalidTransaction::ExhaustsResources, + )))) => break, // Block is full + Err(e) => return Err(Error::Client(e)), + } + num_ext += 1; + } + if num_ext == 0 { + return Err("A Block must hold at least one extrinsic".into()) + } + info!("Extrinsics per block: {}", num_ext); + let block = builder.build()?.block; + + Ok((block, num_ext)) + } + + /// Measures the time that it take to execute a block or an extrinsic. + fn measure_block( + &self, + block: &Block, + num_ext: u64, + bench_type: BenchmarkType, + ) -> Result { + let mut record = BenchRecord::new(); + if bench_type == BenchmarkType::Extrinsic && num_ext == 0 { + return Err("Cannot measure the extrinsic time of an empty block".into()) + } + let genesis = BlockId::Number(Zero::zero()); + + info!("Running {} warmups...", self.params.warmup); + for _ in 0..self.params.warmup { + self.client + .runtime_api() + .execute_block(&genesis, block.clone()) + .map_err(|e| Error::Client(RuntimeApiError(e)))?; + } + + info!("Executing block {} times", self.params.repeat); + // Interesting part here: + // Execute a block multiple times and record each execution time. + for _ in 0..self.params.repeat { + let block = block.clone(); + let runtime_api = self.client.runtime_api(); + let start = Instant::now(); + + runtime_api + .execute_block(&genesis, block) + .map_err(|e| Error::Client(RuntimeApiError(e)))?; + + let elapsed = start.elapsed().as_nanos(); + if bench_type == BenchmarkType::Extrinsic { + // Checked for non-zero div above. + record.push((elapsed as f64 / num_ext as f64).ceil() as u64); + } else { + record.push(elapsed as u64); + } + } + + Ok(record) + } + + fn max_ext_per_block(&self) -> u32 { + self.params.max_ext_per_block.unwrap_or(u32::MAX) + } +} + +impl BenchmarkType { + /// Short name of the benchmark type. + pub(crate) fn short_name(&self) -> &'static str { + match self { + Self::Extrinsic => "extrinsic", + Self::Block => "block", + } + } + + /// Long name of the benchmark type. + pub(crate) fn long_name(&self) -> &'static str { + match self { + Self::Extrinsic => "ExtrinsicBase", + Self::Block => "BlockExecution", + } + } +} diff --git a/utils/frame/benchmarking-cli/src/overhead/cmd.rs b/utils/frame/benchmarking-cli/src/overhead/cmd.rs new file mode 100644 index 000000000000..8c75627fe246 --- /dev/null +++ b/utils/frame/benchmarking-cli/src/overhead/cmd.rs @@ -0,0 +1,118 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +//! Contains the [`OverheadCmd`] as entry point for the CLI to execute +//! the *overhead* benchmarks. + +use sc_block_builder::{BlockBuilderApi, BlockBuilderProvider}; +use sc_cli::{CliConfiguration, Result, SharedParams}; +use sc_client_api::Backend as ClientBackend; +use sc_service::Configuration; +use sp_api::{ApiExt, ProvideRuntimeApi}; +use sp_runtime::{traits::Block as BlockT, OpaqueExtrinsic}; + +use clap::{Args, Parser}; +use log::info; +use serde::Serialize; +use std::{fmt::Debug, sync::Arc}; + +use crate::{ + overhead::{ + bench::{Benchmark, BenchmarkParams, BenchmarkType}, + template::TemplateData, + }, + post_processing::WeightParams, +}; + +/// Benchmarks the per-block and per-extrinsic execution overhead. +#[derive(Debug, Parser)] +pub struct OverheadCmd { + #[allow(missing_docs)] + #[clap(flatten)] + pub shared_params: SharedParams, + + #[allow(missing_docs)] + #[clap(flatten)] + pub params: OverheadParams, +} + +/// Configures the benchmark, the post-processing and weight generation. +#[derive(Debug, Default, Serialize, Clone, PartialEq, Args)] +pub struct OverheadParams { + #[allow(missing_docs)] + #[clap(flatten)] + pub weight: WeightParams, + + #[allow(missing_docs)] + #[clap(flatten)] + pub bench: BenchmarkParams, +} + +/// Used by the benchmark to build signed extrinsics. +/// +/// The built extrinsics only need to be valid in the first block +/// who's parent block is the genesis block. +pub trait ExtrinsicBuilder { + /// Build a `System::remark` extrinsic. + fn remark(&self, nonce: u32) -> std::result::Result; +} + +impl OverheadCmd { + /// Measures the per-block and per-extrinsic execution overhead. + /// + /// Writes the results to console and into two instances of the + /// `weights.hbs` template, one for each benchmark. + pub async fn run( + &self, + cfg: Configuration, + client: Arc, + inherent_data: sp_inherents::InherentData, + ext_builder: Arc, + ) -> Result<()> + where + Block: BlockT, + BA: ClientBackend, + C: BlockBuilderProvider + ProvideRuntimeApi, + C::Api: ApiExt + BlockBuilderApi, + { + let bench = Benchmark::new(client, self.params.bench.clone(), inherent_data, ext_builder); + + // per-block execution overhead + { + let stats = bench.bench(BenchmarkType::Block)?; + info!("Per-block execution overhead [ns]:\n{:?}", stats); + let template = TemplateData::new(BenchmarkType::Block, &cfg, &self.params, &stats)?; + template.write(&self.params.weight.weight_path)?; + } + // per-extrinsic execution overhead + { + let stats = bench.bench(BenchmarkType::Extrinsic)?; + info!("Per-extrinsic execution overhead [ns]:\n{:?}", stats); + let template = TemplateData::new(BenchmarkType::Extrinsic, &cfg, &self.params, &stats)?; + template.write(&self.params.weight.weight_path)?; + } + + Ok(()) + } +} + +// Boilerplate +impl CliConfiguration for OverheadCmd { + fn shared_params(&self) -> &SharedParams { + &self.shared_params + } +} diff --git a/utils/frame/benchmarking-cli/src/overhead/mod.rs b/utils/frame/benchmarking-cli/src/overhead/mod.rs new file mode 100644 index 000000000000..abdeac22b789 --- /dev/null +++ b/utils/frame/benchmarking-cli/src/overhead/mod.rs @@ -0,0 +1,22 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +mod bench; +pub mod cmd; +mod template; + +pub use cmd::{ExtrinsicBuilder, OverheadCmd}; diff --git a/utils/frame/benchmarking-cli/src/overhead/template.rs b/utils/frame/benchmarking-cli/src/overhead/template.rs new file mode 100644 index 000000000000..f6fb8ed9d929 --- /dev/null +++ b/utils/frame/benchmarking-cli/src/overhead/template.rs @@ -0,0 +1,110 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +//! Converts a benchmark result into [`TemplateData`] and writes +//! it into the `weights.hbs` template. + +use sc_cli::Result; +use sc_service::Configuration; + +use handlebars::Handlebars; +use log::info; +use serde::Serialize; +use std::{env, fs, path::PathBuf}; + +use crate::{ + overhead::{bench::BenchmarkType, cmd::OverheadParams}, + storage::record::Stats, +}; + +static VERSION: &'static str = env!("CARGO_PKG_VERSION"); +static TEMPLATE: &str = include_str!("./weights.hbs"); + +/// Data consumed by Handlebar to fill out the `weights.hbs` template. +#[derive(Serialize, Debug, Clone)] +pub(crate) struct TemplateData { + /// Short name of the benchmark. Can be "block" or "extrinsic". + long_name: String, + /// Long name of the benchmark. Can be "BlockExecution" or "ExtrinsicBase". + short_name: String, + /// Name of the runtime. Taken from the chain spec. + runtime_name: String, + /// Version of the benchmarking CLI used. + version: String, + /// Date that the template was filled out. + date: String, + /// Command line arguments that were passed to the CLI. + args: Vec, + /// Params of the executed command. + params: OverheadParams, + /// Stats about the benchmark result. + stats: Stats, + /// The resulting weight in ns. + weight: u64, +} + +impl TemplateData { + /// Returns a new [`Self`] from the given params. + pub(crate) fn new( + t: BenchmarkType, + cfg: &Configuration, + params: &OverheadParams, + stats: &Stats, + ) -> Result { + let weight = params.weight.calc_weight(stats)?; + + Ok(TemplateData { + short_name: t.short_name().into(), + long_name: t.long_name().into(), + runtime_name: cfg.chain_spec.name().into(), + version: VERSION.into(), + date: chrono::Utc::now().format("%Y-%m-%d (Y/M/D)").to_string(), + args: env::args().collect::>(), + params: params.clone(), + stats: stats.clone(), + weight, + }) + } + + /// Fill out the `weights.hbs` HBS template with its own data. + /// Writes the result to `path` which can be a directory or a file. + pub fn write(&self, path: &Option) -> Result<()> { + let mut handlebars = Handlebars::new(); + // Format large integers with underscores. + handlebars.register_helper("underscore", Box::new(crate::writer::UnderscoreHelper)); + // Don't HTML escape any characters. + handlebars.register_escape_fn(|s| -> String { s.to_string() }); + + let out_path = self.build_path(path)?; + let mut fd = fs::File::create(&out_path)?; + info!("Writing weights to {:?}", fs::canonicalize(&out_path)?); + handlebars + .render_template_to_write(&TEMPLATE, &self, &mut fd) + .map_err(|e| format!("HBS template write: {:?}", e).into()) + } + + /// Build a path for the weight file. + fn build_path(&self, weight_out: &Option) -> Result { + let mut path = weight_out.clone().unwrap_or(PathBuf::from(".")); + + if !path.is_dir() { + return Err("Need directory as --weight-path".into()) + } + path.push(format!("{}_weights.rs", self.short_name)); + Ok(path) + } +} diff --git a/utils/frame/benchmarking-cli/src/overhead/weights.hbs b/utils/frame/benchmarking-cli/src/overhead/weights.hbs new file mode 100644 index 000000000000..0f6b7f3e9119 --- /dev/null +++ b/utils/frame/benchmarking-cli/src/overhead/weights.hbs @@ -0,0 +1,92 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION {{version}} +//! DATE: {{date}} +//! +//! SHORT-NAME: `{{short_name}}`, LONG-NAME: `{{long_name}}`, RUNTIME: `{{runtime_name}}` +//! WARMUPS: `{{params.bench.warmup}}`, REPEAT: `{{params.bench.repeat}}` +//! WEIGHT-PATH: `{{params.weight.weight_path}}` +//! WEIGHT-METRIC: `{{params.weight.weight_metric}}`, WEIGHT-MUL: `{{params.weight.weight_mul}}`, WEIGHT-ADD: `{{params.weight.weight_add}}` + +// Executed Command: +{{#each args as |arg|}} +// {{arg}} +{{/each}} + +use frame_support::{ + parameter_types, + weights::{constants::WEIGHT_PER_NANOS, Weight}, +}; + +parameter_types! { + {{#if (eq short_name "block")}} + /// Time to execute an empty block. + {{else}} + /// Time to execute a NO-OP extrinsic eg. `System::remark`. + {{/if}} + /// Calculated by multiplying the *{{params.weight.weight_metric}}* with `{{params.weight.weight_mul}}` and adding `{{params.weight.weight_add}}`. + /// + /// Stats [ns]: + /// Min, Max: {{underscore stats.min}}, {{underscore stats.max}} + /// Average: {{underscore stats.avg}} + /// Median: {{underscore stats.median}} + /// StdDev: {{stats.stddev}} + /// + /// Percentiles [ns]: + /// 99th: {{underscore stats.p99}} + /// 95th: {{underscore stats.p95}} + /// 75th: {{underscore stats.p75}} + pub const {{long_name}}Weight: Weight = {{underscore weight}} * WEIGHT_PER_NANOS; +} + +#[cfg(test)] +mod test_weights { + use frame_support::weights::constants; + + /// Checks that the weight exists and is sane. + // NOTE: If this test fails but you are sure that the generated values are fine, + // you can delete it. + #[test] + fn sane() { + let w = super::{{long_name}}Weight::get(); + + {{#if (eq short_name "block")}} + // At least 100 µs. + assert!( + w >= 100 * constants::WEIGHT_PER_MICROS, + "Weight should be at least 100 µs." + ); + // At most 50 ms. + assert!( + w <= 50 * constants::WEIGHT_PER_MILLIS, + "Weight should be at most 50 ms." + ); + {{else}} + // At least 10 µs. + assert!( + w >= 10 * constants::WEIGHT_PER_MICROS, + "Weight should be at least 10 µs." + ); + // At most 1 ms. + assert!( + w <= constants::WEIGHT_PER_MILLIS, + "Weight should be at most 1 ms." + ); + {{/if}} + } +} diff --git a/utils/frame/benchmarking-cli/src/post_processing/mod.rs b/utils/frame/benchmarking-cli/src/post_processing/mod.rs new file mode 100644 index 000000000000..fb20d9bd0c48 --- /dev/null +++ b/utils/frame/benchmarking-cli/src/post_processing/mod.rs @@ -0,0 +1,95 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +//! Calculates a weight from the statistics of a benchmark result. + +use sc_cli::Result; + +use clap::Args; +use serde::Serialize; +use std::path::PathBuf; + +use crate::storage::record::{StatSelect, Stats}; + +/// Configures the weight generation. +#[derive(Debug, Default, Serialize, Clone, PartialEq, Args)] +pub struct WeightParams { + /// File or directory to write the *weight* files to. + /// + /// For Substrate this should be `frame/support/src/weights`. + #[clap(long)] + pub weight_path: Option, + + /// Select a specific metric to calculate the final weight output. + #[clap(long = "metric", default_value = "average")] + pub weight_metric: StatSelect, + + /// Multiply the resulting weight with the given factor. Must be positive. + /// + /// Is applied before `weight_add`. + #[clap(long = "mul", default_value = "1")] + pub weight_mul: f64, + + /// Add the given offset to the resulting weight. + /// + /// Is applied after `weight_mul`. + #[clap(long = "add", default_value = "0")] + pub weight_add: u64, +} + +/// Calculates the final weight by multiplying the selected metric with +/// `weight_mul` and adding `weight_add`. +/// Does not use safe casts and can overflow. +impl WeightParams { + pub(crate) fn calc_weight(&self, stat: &Stats) -> Result { + if self.weight_mul.is_sign_negative() || !self.weight_mul.is_normal() { + return Err("invalid floating number for `weight_mul`".into()) + } + let s = stat.select(self.weight_metric) as f64; + let w = s.mul_add(self.weight_mul, self.weight_add as f64).ceil(); + Ok(w as u64) // No safe cast here since there is no `From` for `u64`. + } +} + +#[cfg(test)] +mod test_weight_params { + use super::WeightParams; + use crate::storage::record::{StatSelect, Stats}; + + #[test] + fn calc_weight_works() { + let stats = Stats { avg: 113, ..Default::default() }; + let params = WeightParams { + weight_metric: StatSelect::Average, + weight_mul: 0.75, + weight_add: 3, + ..Default::default() + }; + + let want = (113.0f64 * 0.75 + 3.0).ceil() as u64; // Ceil for overestimation. + let got = params.calc_weight(&stats).unwrap(); + assert_eq!(want, got); + } + + #[test] + fn calc_weight_detects_negative_mul() { + let stats = Stats::default(); + let params = WeightParams { weight_mul: -0.75, ..Default::default() }; + + assert!(params.calc_weight(&stats).is_err()); + } +} diff --git a/utils/frame/benchmarking-cli/src/storage/cmd.rs b/utils/frame/benchmarking-cli/src/storage/cmd.rs index ad7d13a2022e..c38e6636e5a3 100644 --- a/utils/frame/benchmarking-cli/src/storage/cmd.rs +++ b/utils/frame/benchmarking-cli/src/storage/cmd.rs @@ -33,8 +33,8 @@ use serde::Serialize; use sp_runtime::generic::BlockId; use std::{fmt::Debug, path::PathBuf, sync::Arc}; -use super::{record::StatSelect, template::TemplateData}; - +use super::template::TemplateData; +use crate::post_processing::WeightParams; /// Benchmark the storage of a Substrate node with a live chain snapshot. #[derive(Debug, Parser)] pub struct StorageCmd { @@ -58,24 +58,9 @@ pub struct StorageCmd { /// Parameters for modifying the benchmark behaviour and the post processing of the results. #[derive(Debug, Default, Serialize, Clone, PartialEq, Args)] pub struct StorageParams { - /// Path to write the *weight* file to. Can be a file or directory. - /// For substrate this should be `frame/support/src/weights`. - #[clap(long)] - pub weight_path: Option, - - /// Select a specific metric to calculate the final weight output. - #[clap(long = "metric", default_value = "average")] - pub weight_metric: StatSelect, - - /// Multiply the resulting weight with the given factor. Must be positive. - /// Is calculated before `weight_add`. - #[clap(long = "mul", default_value = "1")] - pub weight_mul: f64, - - /// Add the given offset to the resulting weight. - /// Is calculated after `weight_mul`. - #[clap(long = "add", default_value = "0")] - pub weight_add: u64, + #[allow(missing_docs)] + #[clap(flatten)] + pub weight_params: WeightParams, /// Skip the `read` benchmark. #[clap(long)] @@ -153,7 +138,7 @@ impl StorageCmd { template.set_stats(None, Some(stats))?; } - template.write(&self.params.weight_path, &self.params.template_path) + template.write(&self.params.weight_params.weight_path, &self.params.template_path) } /// Returns the specified state version. diff --git a/utils/frame/benchmarking-cli/src/storage/record.rs b/utils/frame/benchmarking-cli/src/storage/record.rs index 667274bef0dd..530fa4cdfe96 100644 --- a/utils/frame/benchmarking-cli/src/storage/record.rs +++ b/utils/frame/benchmarking-cli/src/storage/record.rs @@ -36,25 +36,25 @@ pub(crate) struct BenchRecord { #[derive(Serialize, Default, Clone)] pub(crate) struct Stats { /// Sum of all values. - sum: u64, + pub(crate) sum: u64, /// Minimal observed value. - min: u64, + pub(crate) min: u64, /// Maximal observed value. - max: u64, + pub(crate) max: u64, /// Average of all values. - avg: u64, + pub(crate) avg: u64, /// Median of all values. - median: u64, + pub(crate) median: u64, /// Standard derivation of all values. - stddev: f64, + pub(crate) stddev: f64, /// 99th percentile. At least 99% of all values are below this threshold. - p99: u64, + pub(crate) p99: u64, /// 95th percentile. At least 95% of all values are below this threshold. - p95: u64, + pub(crate) p95: u64, /// 75th percentile. At least 75% of all values are below this threshold. - p75: u64, + pub(crate) p75: u64, } /// Selects a specific field from a [`Stats`] object. @@ -159,8 +159,8 @@ impl Stats { /// This is best effort since it ignores the interpolation case. fn percentile(mut xs: Vec, p: f64) -> u64 { xs.sort(); - let index = (xs.len() as f64 * p).ceil() as usize; - xs[index] + let index = (xs.len() as f64 * p).ceil() as usize - 1; + xs[index.clamp(0, xs.len() - 1)] } } @@ -195,3 +195,40 @@ impl FromStr for StatSelect { } } } + +#[cfg(test)] +mod test_stats { + use super::Stats; + use rand::{seq::SliceRandom, thread_rng}; + + #[test] + fn stats_correct() { + let mut data: Vec = (1..=100).collect(); + data.shuffle(&mut thread_rng()); + let stats = Stats::new(&data).unwrap(); + + assert_eq!(stats.sum, 5050); + assert_eq!(stats.min, 1); + assert_eq!(stats.max, 100); + + assert_eq!(stats.avg, 50); + assert_eq!(stats.median, 50); // 50.5 to be exact. + assert_eq!(stats.stddev, 28.87); // Rounded with 1/100 precision. + + assert_eq!(stats.p99, 99); + assert_eq!(stats.p95, 95); + assert_eq!(stats.p75, 75); + } + + #[test] + fn no_panic_short_lengths() { + // Empty input does error. + assert!(Stats::new(&vec![]).is_err()); + + // Different small input lengths are fine. + for l in 1..10 { + let data = (0..=l).collect(); + assert!(Stats::new(&data).is_ok()); + } + } +} diff --git a/utils/frame/benchmarking-cli/src/storage/template.rs b/utils/frame/benchmarking-cli/src/storage/template.rs index 13b825d891a5..10e6902b934b 100644 --- a/utils/frame/benchmarking-cli/src/storage/template.rs +++ b/utils/frame/benchmarking-cli/src/storage/template.rs @@ -77,11 +77,11 @@ impl TemplateData { write: Option<(Stats, Stats)>, ) -> Result<()> { if let Some(read) = read { - self.read_weight = calc_weight(&read.0, &self.params)?; + self.read_weight = self.params.weight_params.calc_weight(&read.0)?; self.read = Some(read); } if let Some(write) = write { - self.write_weight = calc_weight(&write.0, &self.params)?; + self.write_weight = self.params.weight_params.calc_weight(&write.0)?; self.write = Some(write); } Ok(()) @@ -130,15 +130,3 @@ impl TemplateData { path } } - -/// Calculates the final weight by multiplying the selected metric with -/// `mul` and adding `add`. -/// Does not use safe casts and can overflow. -fn calc_weight(stat: &Stats, params: &StorageParams) -> Result { - if params.weight_mul.is_sign_negative() || !params.weight_mul.is_normal() { - return Err("invalid floating number for `weight_mul`".into()) - } - let s = stat.select(params.weight_metric) as f64; - let w = s.mul_add(params.weight_mul, params.weight_add as f64).ceil(); - Ok(w as u64) // No safe cast here since there is no `From` for `u64`. -} From 150fea0726b528484d600a56a2dd92a783755518 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Thu, 17 Mar 2022 12:16:56 +0100 Subject: [PATCH 600/695] sc-rpc-api: Remove unused error variants (#11012) --- client/rpc-api/src/author/error.rs | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/client/rpc-api/src/author/error.rs b/client/rpc-api/src/author/error.rs index eee77edd5e20..fe12bd581f12 100644 --- a/client/rpc-api/src/author/error.rs +++ b/client/rpc-api/src/author/error.rs @@ -43,15 +43,9 @@ pub enum Error { /// Incorrect extrinsic format. #[error("Invalid extrinsic format: {}", .0)] BadFormat(#[from] codec::Error), - /// Incorrect seed phrase. - #[error("Invalid seed phrase/SURI")] - BadSeedPhrase, /// Key type ID has an unknown format. #[error("Invalid key type ID format (should be of length four)")] BadKeyType, - /// Key type ID has some unsupported crypto. - #[error("The crypto of key type ID is unknown")] - UnsupportedKeyType, /// Some random issue with the key store. Shouldn't happen. #[error("The key store is unavailable")] KeyStoreUnavailable, @@ -84,8 +78,6 @@ const POOL_TOO_LOW_PRIORITY: i64 = POOL_INVALID_TX + 4; const POOL_CYCLE_DETECTED: i64 = POOL_INVALID_TX + 5; /// The transaction was not included to the pool because of the limits. const POOL_IMMEDIATELY_DROPPED: i64 = POOL_INVALID_TX + 6; -/// The key type crypto is not known. -const UNSUPPORTED_KEY_TYPE: i64 = POOL_INVALID_TX + 7; /// The transaction was not included to the pool since it is unactionable, /// it is not propagable and the local node does not author blocks. const POOL_UNACTIONABLE: i64 = POOL_INVALID_TX + 8; @@ -156,14 +148,6 @@ impl From for rpc::Error { the local node does not author blocks".into(), ), }, - Error::UnsupportedKeyType => rpc::Error { - code: rpc::ErrorCode::ServerError(UNSUPPORTED_KEY_TYPE), - message: "Unknown key type crypto" .into(), - data: Some( - "The crypto for the given key type is unknown, please add the public key to the \ - request to insert the key successfully.".into() - ), - }, Error::UnsafeRpcCalled(e) => e.into(), e => errors::internal(e), } From 96738a1f3dbe4a1fb6abb385920fb403ee961488 Mon Sep 17 00:00:00 2001 From: Georges Date: Thu, 17 Mar 2022 12:52:26 +0000 Subject: [PATCH 601/695] Allow `pallet-election-provider` to accept smaller solutions as well (#10905) * Allow `pallet-election-provider` to accept smaller solutions, issue #9478 * Fixing a typo * Adding some more tests Removing a seemingly outdated comment * making it a URL * Updating test name as per suggestion Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> * Updating documentation to be more explicit And to follow the general guidelines Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> * Fixing formatting Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> --- .../election-provider-multi-phase/src/lib.rs | 49 ++++++++++++++++--- .../src/unsigned.rs | 7 ++- frame/election-provider-support/src/lib.rs | 6 +++ 3 files changed, 54 insertions(+), 8 deletions(-) diff --git a/frame/election-provider-multi-phase/src/lib.rs b/frame/election-provider-multi-phase/src/lib.rs index b366ceb4dafe..90c540b85d67 100644 --- a/frame/election-provider-multi-phase/src/lib.rs +++ b/frame/election-provider-multi-phase/src/lib.rs @@ -1346,7 +1346,7 @@ impl Pallet { T::DataProvider::targets(Some(target_limit)).map_err(ElectionError::DataProvider)?; let voters = T::DataProvider::voters(Some(voter_limit)).map_err(ElectionError::DataProvider)?; - let desired_targets = + let mut desired_targets = T::DataProvider::desired_targets().map_err(ElectionError::DataProvider)?; // Defensive-only. @@ -1355,6 +1355,22 @@ impl Pallet { return Err(ElectionError::DataProvider("Snapshot too big for submission.")) } + // If `desired_targets` > `targets.len()`, cap `desired_targets` to that level and emit a + // warning + let max_len = targets + .len() + .try_into() + .map_err(|_| ElectionError::DataProvider("Failed to convert usize"))?; + if desired_targets > max_len { + log!( + warn, + "desired_targets: {} > targets.len(): {}, capping desired_targets", + desired_targets, + max_len + ); + desired_targets = max_len; + } + Ok((targets, voters, desired_targets)) } @@ -1413,9 +1429,6 @@ impl Pallet { let desired_targets = Self::desired_targets().ok_or(FeasibilityError::SnapshotUnavailable)?; - // NOTE: this is a bit of duplicate, but we keep it around for veracity. The unsigned path - // already checked this in `unsigned_per_dispatch_checks`. The signed path *could* check it - // upon arrival, thus we would then remove it here. Given overlay it is cheap anyhow ensure!(winners.len() as u32 == desired_targets, FeasibilityError::WrongWinnerCount); // Ensure that the solution's score can pass absolute min-score. @@ -1588,7 +1601,7 @@ mod feasibility_check { raw_solution, roll_to, EpochLength, ExtBuilder, MultiPhase, Runtime, SignedPhase, TargetIndex, UnsignedPhase, VoterIndex, }; - use frame_support::assert_noop; + use frame_support::{assert_noop, assert_ok}; const COMPUTE: ElectionCompute = ElectionCompute::OnChain; @@ -1625,7 +1638,7 @@ mod feasibility_check { } #[test] - fn desired_targets() { + fn desired_targets_gets_capped() { ExtBuilder::default().desired_targets(8).build_and_execute(|| { roll_to(::get() - ::get() - ::get()); assert!(MultiPhase::current_phase().is_signed()); @@ -1633,8 +1646,30 @@ mod feasibility_check { let raw = raw_solution(); assert_eq!(raw.solution.unique_targets().len(), 4); - assert_eq!(MultiPhase::desired_targets().unwrap(), 8); + // desired_targets is capped to the number of targets which is 4 + assert_eq!(MultiPhase::desired_targets().unwrap(), 4); + + // It should succeed + assert_ok!(MultiPhase::feasibility_check(raw, COMPUTE)); + }) + } + + #[test] + fn less_than_desired_targets_fails() { + ExtBuilder::default().desired_targets(8).build_and_execute(|| { + roll_to(::get() - ::get() - ::get()); + assert!(MultiPhase::current_phase().is_signed()); + + let mut raw = raw_solution(); + + assert_eq!(raw.solution.unique_targets().len(), 4); + // desired_targets is capped to the number of targets which is 4 + assert_eq!(MultiPhase::desired_targets().unwrap(), 4); + + // Force the number of winners to be bigger to fail + raw.solution.votes1[0].1 = 4; + // It should succeed assert_noop!( MultiPhase::feasibility_check(raw, COMPUTE), FeasibilityError::WrongWinnerCount, diff --git a/frame/election-provider-multi-phase/src/unsigned.rs b/frame/election-provider-multi-phase/src/unsigned.rs index 3380a61d4310..c52a4da22cb8 100644 --- a/frame/election-provider-multi-phase/src/unsigned.rs +++ b/frame/election-provider-multi-phase/src/unsigned.rs @@ -1044,8 +1044,13 @@ mod tests { roll_to(25); assert!(MultiPhase::current_phase().is_unsigned()); + // Force the number of winners to be bigger to fail + let (mut solution, _) = + MultiPhase::mine_solution::<::Solver>().unwrap(); + solution.solution.votes1[0].1 = 4; + assert_eq!( - MultiPhase::mine_check_save_submit().unwrap_err(), + MultiPhase::basic_checks(&solution, "mined").unwrap_err(), MinerError::PreDispatchChecksFailed(DispatchError::Module(ModuleError { index: 2, error: 1, diff --git a/frame/election-provider-support/src/lib.rs b/frame/election-provider-support/src/lib.rs index ca95eda6b509..e1975a2681e6 100644 --- a/frame/election-provider-support/src/lib.rs +++ b/frame/election-provider-support/src/lib.rs @@ -289,6 +289,12 @@ pub trait ElectionDataProvider { /// /// This should be implemented as a self-weighing function. The implementor should register its /// appropriate weight at the end of execution with the system pallet directly. + /// + /// A sensible implementation should use the minimum between this value and + /// [`Self::targets().len()`], since desiring a winner set larger than candidates is not + /// feasible. + /// + /// This is documented further in issue: fn desired_targets() -> data_provider::Result; /// Provide a best effort prediction about when the next election is about to happen. From 8e0dbe7a3ff961634df9db7d384012d5150423c1 Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Thu, 17 Mar 2022 15:47:42 +0000 Subject: [PATCH 602/695] fix sibmit benchmark in election-multi-phase pallet (#11057) --- frame/election-provider-multi-phase/src/benchmarking.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/frame/election-provider-multi-phase/src/benchmarking.rs b/frame/election-provider-multi-phase/src/benchmarking.rs index b331516a4e79..2a9286369f39 100644 --- a/frame/election-provider-multi-phase/src/benchmarking.rs +++ b/frame/election-provider-multi-phase/src/benchmarking.rs @@ -309,7 +309,6 @@ frame_benchmarking::benchmarks! { } submit { - // the solution will be worse than all of them meaning the score need to be checked against // ~ log2(c) let solution = RawSolution { @@ -341,7 +340,11 @@ frame_benchmarking::benchmarks! { signed_submissions.put(); let caller = frame_benchmarking::whitelisted_caller(); - T::Currency::make_free_balance_be(&caller, T::Currency::minimum_balance() * 10u32.into()); + let deposit = MultiPhase::::deposit_for( + &solution, + MultiPhase::::snapshot_metadata().unwrap_or_default(), + ); + T::Currency::make_free_balance_be(&caller, T::Currency::minimum_balance() * 1000u32.into() + deposit); }: _(RawOrigin::Signed(caller), Box::new(solution)) verify { From c15504c646f2b7eea92341bfac29b19d1c9d53b3 Mon Sep 17 00:00:00 2001 From: driemworks Date: Thu, 17 Mar 2022 14:13:10 -0500 Subject: [PATCH 603/695] add burn extrinsic --- .../pallets/iris-assets/src/lib.rs | 49 ++++++++++++++----- .../pallets/iris-assets/src/tests.rs | 48 ++++++++++++++++++ 2 files changed, 85 insertions(+), 12 deletions(-) diff --git a/bin/node-template/pallets/iris-assets/src/lib.rs b/bin/node-template/pallets/iris-assets/src/lib.rs index ce899c65ceb7..d92ecdb1f817 100644 --- a/bin/node-template/pallets/iris-assets/src/lib.rs +++ b/bin/node-template/pallets/iris-assets/src/lib.rs @@ -158,6 +158,8 @@ pub mod pallet { AssetClassCreated(T::AssetId), /// A new asset was created (tickets minted) AssetCreated(T::AssetId), + /// An asset was burned succesfully + AssetBurned(T::AssetId), /// A node has published ipfs identity results on chain PublishedIdentity(T::AccountId), QueuedDataToPin, @@ -220,8 +222,8 @@ pub mod pallet { addr: Vec, cid: Vec, name: Vec, - id: T::AssetId, - balance: T::Balance, + #[pallet::compact] id: T::AssetId, + #[pallet::compact] balance: T::Balance, ) -> DispatchResult { let who = ensure_signed(origin)?; let multiaddr = OpaqueMultiaddr(addr); @@ -250,7 +252,7 @@ pub mod pallet { pub fn mint( origin: OriginFor, beneficiary: ::Source, - asset_id: T::AssetId, + #[pallet::compact] asset_id: T::AssetId, #[pallet::compact] amount: T::Balance, ) -> DispatchResult { let who = ensure_signed(origin)?; @@ -280,7 +282,7 @@ pub mod pallet { pub fn transfer_asset( origin: OriginFor, target: ::Source, - asset_id: T::AssetId, + #[pallet::compact] asset_id: T::AssetId, #[pallet::compact] amount: T::Balance, ) -> DispatchResult { let current_owner = ensure_signed(origin)?; @@ -300,6 +302,33 @@ pub mod pallet { Ok(()) } + + /// Burns the amount of assets + /// + /// * `target`: the target account to burn assets from + /// * `asset_id`: The asset id to burn + /// * `amount`: The amount of assets to burn + /// + #[pallet::weight(100)] + pub fn burn( + origin: OriginFor, + target: ::Source, + #[pallet::compact] asset_id: T::AssetId, + #[pallet::compact] amount: T::Balance, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + let new_origin = system::RawOrigin::Signed(current_owner.clone()).into(); + >::burn( + new_origin, + asset_id.clone(), + target, + amount.clone(), + )?; + + Self::deposit_event(Event::AssetBurned(asset_id.clone())); + + Ok(()) + } /// request to fetch bytes from ipfs and add to offchain storage /// @@ -310,7 +339,7 @@ pub mod pallet { pub fn request_bytes( origin: OriginFor, owner: ::Source, - asset_id: T::AssetId, + #[pallet::compact] asset_id: T::AssetId, ) -> DispatchResult { let who = ensure_signed(origin)?; let owner_account = T::Lookup::lookup(owner)?; @@ -336,8 +365,8 @@ pub mod pallet { origin: OriginFor, admin: ::Source, cid: Vec, - id: T::AssetId, - balance: T::Balance, + #[pallet::compact] id: T::AssetId, + #[pallet::compact] balance: T::Balance, ) -> DispatchResult { let who = ensure_signed(origin)?; let new_origin = system::RawOrigin::Signed(who).into(); @@ -346,10 +375,6 @@ pub mod pallet { .map_err(|_| Error::::CantCreateAssetClass)?; >::insert(id.clone(), cid.clone()); - // let new_new_origin = system::RawOrigin::Signed(who).into(); - // >::set_metadata( - // new_new_origin, id.clone(), "cid".as_bytes().to_vec(), cid.clone(), 0, - // )?; let which_admin = T::Lookup::lookup(admin.clone())?; >::insert(id.clone(), which_admin); @@ -369,7 +394,7 @@ pub mod pallet { pub fn insert_pin_request( origin: OriginFor, asset_owner: T::AccountId, - asset_id: T::AssetId, + #[pallet::compact] asset_id: T::AssetId, ) -> DispatchResult { let who = ensure_signed(origin)?; diff --git a/bin/node-template/pallets/iris-assets/src/tests.rs b/bin/node-template/pallets/iris-assets/src/tests.rs index 6ed376173f34..7fb1da723ffd 100644 --- a/bin/node-template/pallets/iris-assets/src/tests.rs +++ b/bin/node-template/pallets/iris-assets/src/tests.rs @@ -189,3 +189,51 @@ fn iris_assets_can_transer_assets() { )); }); } + +#[test] +fn iris_assets_can_burn_asset() { + // Given: I am a valid node with a positive balance + let (p, _) = sp_core::sr25519::Pair::generate(); + let pairs = vec![(p.clone().public(), 10)]; + let multiaddr_vec = "/ip4/127.0.0.1/tcp/4001/p2p/12D3KooWMvyvKxYcy9mjbFbXcogFSCvENzQ62ogRxHKZaksFCkAp".as_bytes().to_vec(); + let cid_vec = "QmPZv7P8nQUSh2CpqTvUeYemFyjvMjgWEs8H1Tm8b3zAm9".as_bytes().to_vec(); + let name: Vec = "test.txt".as_bytes().to_vec(); + let cost = 1; + let id = 1; + let balance = 2; + + // + let expected_data_command = crate::DataCommand::AddBytes( + OpaqueMultiaddr(multiaddr_vec.clone()), + cid_vec.clone(), + p.clone().public(), + name.clone(), + id.clone(), + balance.clone(), + ); + + new_test_ext_funded(pairs).execute_with(|| { + // GIVEN: I create an asset class + assert_ok!(Iris::submit_ipfs_add_results( + Origin::signed(p.clone().public()), + p.clone().public(), + cid_vec.clone(), + id.clone(), + balance.clone(), + )); + // AND: I mint some assets + assert_ok!(Iris::mint( + Origin::signed(p.clone().public()), + p.clone().public(), + id.clone(), + balance.clone(), + )); + // WHEN: I burn 1 asset + asset_ok!(Iris::burn( + Origin::signed(p.clone().public()), + id.clone(), + p.clone().public(), + 1, + )); + }); +} From 4ee156c7b6c88b551b7a3fcedff514d3ea8be358 Mon Sep 17 00:00:00 2001 From: driemworks Date: Thu, 17 Mar 2022 14:35:02 -0500 Subject: [PATCH 604/695] fix tests --- .../pallets/iris-assets/src/lib.rs | 5 ++- .../pallets/iris-assets/src/mock.rs | 7 ++-- .../pallets/iris-assets/src/tests.rs | 32 ++++++------------- 3 files changed, 13 insertions(+), 31 deletions(-) diff --git a/bin/node-template/pallets/iris-assets/src/lib.rs b/bin/node-template/pallets/iris-assets/src/lib.rs index d92ecdb1f817..b62665d1782e 100644 --- a/bin/node-template/pallets/iris-assets/src/lib.rs +++ b/bin/node-template/pallets/iris-assets/src/lib.rs @@ -1,7 +1,6 @@ #![cfg_attr(not(feature = "std"), no_std)] -//! # Iris Storage Pallet -//! +//! # Iris Assets Pallet //! //! ## Overview //! @@ -317,7 +316,7 @@ pub mod pallet { #[pallet::compact] amount: T::Balance, ) -> DispatchResult { let who = ensure_signed(origin)?; - let new_origin = system::RawOrigin::Signed(current_owner.clone()).into(); + let new_origin = system::RawOrigin::Signed(who.clone()).into(); >::burn( new_origin, asset_id.clone(), diff --git a/bin/node-template/pallets/iris-assets/src/mock.rs b/bin/node-template/pallets/iris-assets/src/mock.rs index 5743e7b19dd9..e58aa2ab7480 100644 --- a/bin/node-template/pallets/iris-assets/src/mock.rs +++ b/bin/node-template/pallets/iris-assets/src/mock.rs @@ -4,13 +4,10 @@ use frame_support::{construct_runtime, parameter_types}; use sp_core::{ Pair, H256, - sr25519::{ - Signature, - }, }; use sp_runtime::{ - testing::{Header, TestXt}, - traits::{BlakeTwo256, Extrinsic as ExtrinsicT, IdentityLookup, IdentifyAccount, Verify}, + testing::Header, + traits::{BlakeTwo256, Extrinsic as ExtrinsicT, IdentityLookup}, }; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; diff --git a/bin/node-template/pallets/iris-assets/src/tests.rs b/bin/node-template/pallets/iris-assets/src/tests.rs index 7fb1da723ffd..f231636a7f34 100644 --- a/bin/node-template/pallets/iris-assets/src/tests.rs +++ b/bin/node-template/pallets/iris-assets/src/tests.rs @@ -2,11 +2,11 @@ use super::*; use frame_support::{assert_ok}; use mock::*; use sp_core::Pair; -use sp_core::{ - offchain::{testing, OffchainWorkerExt, TransactionPoolExt, OffchainDbExt} -}; -use sp_keystore::{testing::KeyStore, KeystoreExt, SyncCryptoStore}; -use std::sync::Arc; +// use sp_core::{ +// offchain::{testing, OffchainWorkerExt, TransactionPoolExt, OffchainDbExt} +// }; +// use sp_keystore::{testing::KeyStore, KeystoreExt, SyncCryptoStore}; +// use std::sync::Arc; #[test] fn iris_assets_initial_state() { @@ -28,7 +28,6 @@ fn iris_assets_ipfs_add_bytes_works_for_valid_value() { let multiaddr_vec = "/ip4/127.0.0.1/tcp/4001/p2p/12D3KooWMvyvKxYcy9mjbFbXcogFSCvENzQ62ogRxHKZaksFCkAp".as_bytes().to_vec(); let cid_vec = "QmPZv7P8nQUSh2CpqTvUeYemFyjvMjgWEs8H1Tm8b3zAm9".as_bytes().to_vec(); let name: Vec = "test.txt".as_bytes().to_vec(); - let cost = 1; let id = 1; let balance = 1; @@ -113,8 +112,8 @@ fn iris_assets_submit_ipfs_add_results_works_for_valid_values() { // THEN: a new asset class is created // AND: A new entry is added to the AssetClassOwnership StorageDoubleMap - let admin_asset_class_cid = crate::AssetClassOwnership::::get(p.clone().public(), id.clone()); - assert_eq!(admin_asset_class_cid, cid_vec.clone()); + let asset_class_owner = crate::AssetClassOwnership::::get(id.clone()); + assert_eq!(asset_class_owner, p.clone().public()); }); } @@ -195,23 +194,10 @@ fn iris_assets_can_burn_asset() { // Given: I am a valid node with a positive balance let (p, _) = sp_core::sr25519::Pair::generate(); let pairs = vec![(p.clone().public(), 10)]; - let multiaddr_vec = "/ip4/127.0.0.1/tcp/4001/p2p/12D3KooWMvyvKxYcy9mjbFbXcogFSCvENzQ62ogRxHKZaksFCkAp".as_bytes().to_vec(); let cid_vec = "QmPZv7P8nQUSh2CpqTvUeYemFyjvMjgWEs8H1Tm8b3zAm9".as_bytes().to_vec(); - let name: Vec = "test.txt".as_bytes().to_vec(); - let cost = 1; let id = 1; let balance = 2; - // - let expected_data_command = crate::DataCommand::AddBytes( - OpaqueMultiaddr(multiaddr_vec.clone()), - cid_vec.clone(), - p.clone().public(), - name.clone(), - id.clone(), - balance.clone(), - ); - new_test_ext_funded(pairs).execute_with(|| { // GIVEN: I create an asset class assert_ok!(Iris::submit_ipfs_add_results( @@ -229,10 +215,10 @@ fn iris_assets_can_burn_asset() { balance.clone(), )); // WHEN: I burn 1 asset - asset_ok!(Iris::burn( + assert_ok!(Iris::burn( Origin::signed(p.clone().public()), - id.clone(), p.clone().public(), + id.clone(), 1, )); }); From 584d98758d2d0ba523642f70a70ec554eeabe061 Mon Sep 17 00:00:00 2001 From: driemworks Date: Thu, 17 Mar 2022 17:01:57 -0500 Subject: [PATCH 605/695] create Metadata struct --- .../pallets/iris-assets/src/lib.rs | 21 ++++++++++++++----- .../pallets/iris-ledger/src/lib.rs | 4 ---- .../pallets/iris-session/src/lib.rs | 4 +--- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/bin/node-template/pallets/iris-assets/src/lib.rs b/bin/node-template/pallets/iris-assets/src/lib.rs index b62665d1782e..ef894997ebd1 100644 --- a/bin/node-template/pallets/iris-assets/src/lib.rs +++ b/bin/node-template/pallets/iris-assets/src/lib.rs @@ -47,6 +47,12 @@ pub enum DataCommand { PinCID(AccountId, AssetId, Vec), } +#[derive(Encode, Decode, RuntimeDebug, PartialEq, TypeInfo, Default)] +pub struct Metadata { + pub cid: Vec, + addresses: Vec, +} + pub use pallet::*; #[cfg(test)] @@ -122,12 +128,13 @@ pub mod pallet { // map asset id to cid #[pallet::storage] - #[pallet::getter(fn metadata)] - pub(super) type Metadata = StorageMap< + #[pallet::getter(fn metadata_map)] + pub(super) type MetadataMap = StorageMap< _, Blake2_128Concat, T::AssetId, - Vec, + Metadata, + // Vec, ValueQuery, >; @@ -373,7 +380,11 @@ pub mod pallet { >::create(new_origin, id.clone(), admin.clone(), balance) .map_err(|_| Error::::CantCreateAssetClass)?; - >::insert(id.clone(), cid.clone()); + let metadata: Metadata = Metadata { + cid: cid.clone(), + addresses: Vec::new(), + }; + >::insert(id.clone(), metadata); let which_admin = T::Lookup::lookup(admin.clone())?; >::insert(id.clone(), which_admin); @@ -403,7 +414,7 @@ pub mod pallet { Error::::NoSuchOwnedContent ); - let cid: Vec = >::get(asset_id.clone()); + let cid: Vec = >::get(asset_id.clone()).cid; >::mutate( |queue| queue.push(DataCommand::PinCID( who.clone(), diff --git a/bin/node-template/pallets/iris-ledger/src/lib.rs b/bin/node-template/pallets/iris-ledger/src/lib.rs index bb1020a8a94c..749ac9cc6b19 100644 --- a/bin/node-template/pallets/iris-ledger/src/lib.rs +++ b/bin/node-template/pallets/iris-ledger/src/lib.rs @@ -161,7 +161,3 @@ pub mod pallet { } } - -impl Pallet { - -} \ No newline at end of file diff --git a/bin/node-template/pallets/iris-session/src/lib.rs b/bin/node-template/pallets/iris-session/src/lib.rs index 16f1b7438cba..356779209287 100644 --- a/bin/node-template/pallets/iris-session/src/lib.rs +++ b/bin/node-template/pallets/iris-session/src/lib.rs @@ -898,9 +898,7 @@ impl Pallet { let expected_pub_key = >::get(requestor.clone()); ensure!(public_key == expected_pub_key, Error::::BadOrigin); - let cid = >::metadata( - asset_id.clone() - ); + let cid = >::metadata_map(asset_id.clone()).cid; ensure!( owner.clone() == >::asset_access(requestor.clone(), asset_id.clone()), Error::::InsufficientBalance From d810c15dc18bfdeffccbc03a01200aae41472d9a Mon Sep 17 00:00:00 2001 From: driemworks Date: Thu, 17 Mar 2022 20:07:54 -0500 Subject: [PATCH 606/695] Revert "create Metadata struct" This reverts commit 584d98758d2d0ba523642f70a70ec554eeabe061. --- .../pallets/iris-assets/src/lib.rs | 21 +++++-------------- .../pallets/iris-ledger/src/lib.rs | 4 ++++ .../pallets/iris-session/src/lib.rs | 4 +++- 3 files changed, 12 insertions(+), 17 deletions(-) diff --git a/bin/node-template/pallets/iris-assets/src/lib.rs b/bin/node-template/pallets/iris-assets/src/lib.rs index ef894997ebd1..b62665d1782e 100644 --- a/bin/node-template/pallets/iris-assets/src/lib.rs +++ b/bin/node-template/pallets/iris-assets/src/lib.rs @@ -47,12 +47,6 @@ pub enum DataCommand { PinCID(AccountId, AssetId, Vec), } -#[derive(Encode, Decode, RuntimeDebug, PartialEq, TypeInfo, Default)] -pub struct Metadata { - pub cid: Vec, - addresses: Vec, -} - pub use pallet::*; #[cfg(test)] @@ -128,13 +122,12 @@ pub mod pallet { // map asset id to cid #[pallet::storage] - #[pallet::getter(fn metadata_map)] - pub(super) type MetadataMap = StorageMap< + #[pallet::getter(fn metadata)] + pub(super) type Metadata = StorageMap< _, Blake2_128Concat, T::AssetId, - Metadata, - // Vec, + Vec, ValueQuery, >; @@ -380,11 +373,7 @@ pub mod pallet { >::create(new_origin, id.clone(), admin.clone(), balance) .map_err(|_| Error::::CantCreateAssetClass)?; - let metadata: Metadata = Metadata { - cid: cid.clone(), - addresses: Vec::new(), - }; - >::insert(id.clone(), metadata); + >::insert(id.clone(), cid.clone()); let which_admin = T::Lookup::lookup(admin.clone())?; >::insert(id.clone(), which_admin); @@ -414,7 +403,7 @@ pub mod pallet { Error::::NoSuchOwnedContent ); - let cid: Vec = >::get(asset_id.clone()).cid; + let cid: Vec = >::get(asset_id.clone()); >::mutate( |queue| queue.push(DataCommand::PinCID( who.clone(), diff --git a/bin/node-template/pallets/iris-ledger/src/lib.rs b/bin/node-template/pallets/iris-ledger/src/lib.rs index 749ac9cc6b19..bb1020a8a94c 100644 --- a/bin/node-template/pallets/iris-ledger/src/lib.rs +++ b/bin/node-template/pallets/iris-ledger/src/lib.rs @@ -161,3 +161,7 @@ pub mod pallet { } } + +impl Pallet { + +} \ No newline at end of file diff --git a/bin/node-template/pallets/iris-session/src/lib.rs b/bin/node-template/pallets/iris-session/src/lib.rs index 356779209287..16f1b7438cba 100644 --- a/bin/node-template/pallets/iris-session/src/lib.rs +++ b/bin/node-template/pallets/iris-session/src/lib.rs @@ -898,7 +898,9 @@ impl Pallet { let expected_pub_key = >::get(requestor.clone()); ensure!(public_key == expected_pub_key, Error::::BadOrigin); - let cid = >::metadata_map(asset_id.clone()).cid; + let cid = >::metadata( + asset_id.clone() + ); ensure!( owner.clone() == >::asset_access(requestor.clone(), asset_id.clone()), Error::::InsufficientBalance From 627ba73fafc526b85f9ed141c33dc26ada292247 Mon Sep 17 00:00:00 2001 From: AurevoirXavier Date: Fri, 18 Mar 2022 20:35:38 +0800 Subject: [PATCH 607/695] Use Lowercase (#11059) --- utils/frame/try-runtime/cli/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/frame/try-runtime/cli/src/lib.rs b/utils/frame/try-runtime/cli/src/lib.rs index 2298fa5c042e..ef8db7a1e5a0 100644 --- a/utils/frame/try-runtime/cli/src/lib.rs +++ b/utils/frame/try-runtime/cli/src/lib.rs @@ -619,7 +619,7 @@ pub(crate) async fn ensure_matching_spec { // first, deal with spec name - if expected_spec_name == name { + if expected_spec_name.to_lowercase() == name { log::info!(target: LOG_TARGET, "found matching spec name: {:?}", name); } else { let msg = format!( From cdf591a4ec194bf8232915ef109874c3baec39a0 Mon Sep 17 00:00:00 2001 From: AurevoirXavier Date: Fri, 18 Mar 2022 23:03:21 +0800 Subject: [PATCH 608/695] Expose `ToOwned` (#11060) --- primitives/std/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/primitives/std/src/lib.rs b/primitives/std/src/lib.rs index 03a079e3965f..05dff0f3077b 100644 --- a/primitives/std/src/lib.rs +++ b/primitives/std/src/lib.rs @@ -99,6 +99,7 @@ impl Writer { /// This should include only things which are in the normal std prelude. pub mod prelude { pub use crate::{ + borrow::ToOwned, boxed::Box, clone::Clone, cmp::{Eq, PartialEq, Reverse}, From 2892d23e3f0d254dcd8068852c365e7dcbd48386 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 18 Mar 2022 15:25:16 +0000 Subject: [PATCH 609/695] Bump serde_json from 1.0.74 to 1.0.79 (#11020) Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.74 to 1.0.79. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.74...v1.0.79) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- bin/node/bench/Cargo.toml | 2 +- client/beefy/rpc/Cargo.toml | 2 +- client/chain-spec/Cargo.toml | 2 +- client/cli/Cargo.toml | 2 +- client/consensus/babe/rpc/Cargo.toml | 2 +- client/finality-grandpa/Cargo.toml | 2 +- client/keystore/Cargo.toml | 2 +- client/network/Cargo.toml | 2 +- client/peerset/Cargo.toml | 2 +- client/rpc-api/Cargo.toml | 2 +- client/rpc-servers/Cargo.toml | 2 +- client/rpc/Cargo.toml | 2 +- client/service/Cargo.toml | 2 +- client/sync-state-rpc/Cargo.toml | 2 +- client/telemetry/Cargo.toml | 2 +- frame/merkle-mountain-range/rpc/Cargo.toml | 2 +- frame/transaction-payment/Cargo.toml | 2 +- frame/transaction-payment/asset-tx-payment/Cargo.toml | 2 +- primitives/rpc/Cargo.toml | 2 +- primitives/runtime/Cargo.toml | 2 +- primitives/serializer/Cargo.toml | 2 +- test-utils/client/Cargo.toml | 2 +- utils/frame/benchmarking-cli/Cargo.toml | 2 +- 24 files changed, 25 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fb9561dfabdc..d3b0771c451c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9399,9 +9399,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.74" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee2bb9cd061c5865d345bb02ca49fcef1391741b672b54a0bf7b679badec3142" +checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" dependencies = [ "itoa 1.0.1", "ryu", diff --git a/bin/node/bench/Cargo.toml b/bin/node/bench/Cargo.toml index 5b728258dd03..7bdf46e2b660 100644 --- a/bin/node/bench/Cargo.toml +++ b/bin/node/bench/Cargo.toml @@ -18,7 +18,7 @@ sc-client-api = { version = "4.0.0-dev", path = "../../../client/api/" } sp-runtime = { version = "6.0.0", path = "../../../primitives/runtime" } sp-state-machine = { version = "0.12.0", path = "../../../primitives/state-machine" } serde = "1.0.136" -serde_json = "1.0.74" +serde_json = "1.0.79" derive_more = "0.99.16" kvdb = "0.11.0" kvdb-rocksdb = "0.15.1" diff --git a/client/beefy/rpc/Cargo.toml b/client/beefy/rpc/Cargo.toml index 071b07b6b229..ebbb9527f936 100644 --- a/client/beefy/rpc/Cargo.toml +++ b/client/beefy/rpc/Cargo.toml @@ -31,7 +31,7 @@ beefy-gadget = { version = "4.0.0-dev", path = "../." } beefy-primitives = { version = "4.0.0-dev", path = "../../../primitives/beefy" } [dev-dependencies] -serde_json = "1.0.74" +serde_json = "1.0.79" sc-rpc = { version = "4.0.0-dev", path = "../../rpc", features = [ "test-helpers", diff --git a/client/chain-spec/Cargo.toml b/client/chain-spec/Cargo.toml index 68d591254d21..e18f9b72c75e 100644 --- a/client/chain-spec/Cargo.toml +++ b/client/chain-spec/Cargo.toml @@ -18,7 +18,7 @@ impl-trait-for-tuples = "0.2.1" sc-network = { version = "0.10.0-dev", path = "../network" } sp-core = { version = "6.0.0", path = "../../primitives/core" } serde = { version = "1.0.136", features = ["derive"] } -serde_json = "1.0.74" +serde_json = "1.0.79" sp-runtime = { version = "6.0.0", path = "../../primitives/runtime" } sc-telemetry = { version = "4.0.0-dev", path = "../telemetry" } codec = { package = "parity-scale-codec", version = "3.0.0" } diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index c799fd6dee98..665bd6acfaf3 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -25,7 +25,7 @@ rand = "0.7.3" regex = "1.5.4" rpassword = "5.0.0" serde = "1.0.136" -serde_json = "1.0.74" +serde_json = "1.0.79" thiserror = "1.0.30" tiny-bip39 = "0.8.2" tokio = { version = "1.15", features = ["signal", "rt-multi-thread", "parking_lot"] } diff --git a/client/consensus/babe/rpc/Cargo.toml b/client/consensus/babe/rpc/Cargo.toml index 7db7edd2de13..ee6549480a6d 100644 --- a/client/consensus/babe/rpc/Cargo.toml +++ b/client/consensus/babe/rpc/Cargo.toml @@ -33,7 +33,7 @@ sp-keystore = { version = "0.12.0", path = "../../../../primitives/keystore" } [dev-dependencies] sc-consensus = { version = "0.10.0-dev", path = "../../../consensus/common" } -serde_json = "1.0.74" +serde_json = "1.0.79" sp-keyring = { version = "6.0.0", path = "../../../../primitives/keyring" } sc-keystore = { version = "4.0.0-dev", path = "../../../keystore" } substrate-test-runtime-client = { version = "2.0.0", path = "../../../../test-utils/runtime/client" } diff --git a/client/finality-grandpa/Cargo.toml b/client/finality-grandpa/Cargo.toml index 9733f35bd0e9..86cd57fc7c09 100644 --- a/client/finality-grandpa/Cargo.toml +++ b/client/finality-grandpa/Cargo.toml @@ -37,7 +37,7 @@ sp-keystore = { version = "0.12.0", path = "../../primitives/keystore" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } sc-telemetry = { version = "4.0.0-dev", path = "../telemetry" } sc-keystore = { version = "4.0.0-dev", path = "../keystore" } -serde_json = "1.0.74" +serde_json = "1.0.79" sc-client-api = { version = "4.0.0-dev", path = "../api" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sc-network = { version = "0.10.0-dev", path = "../network" } diff --git a/client/keystore/Cargo.toml b/client/keystore/Cargo.toml index 09fca2a843a1..844110f66886 100644 --- a/client/keystore/Cargo.toml +++ b/client/keystore/Cargo.toml @@ -22,7 +22,7 @@ sp-core = { version = "6.0.0", path = "../../primitives/core" } sp-keystore = { version = "0.12.0", path = "../../primitives/keystore" } hex = "0.4.0" parking_lot = "0.12.0" -serde_json = "1.0.74" +serde_json = "1.0.79" [dev-dependencies] tempfile = "3.1.0" diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index 0dbdd3ec50e9..671271fcb3b7 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -45,7 +45,7 @@ sc-block-builder = { version = "0.10.0-dev", path = "../block-builder" } sc-client-api = { version = "4.0.0-dev", path = "../api" } sc-peerset = { version = "4.0.0-dev", path = "../peerset" } serde = { version = "1.0.136", features = ["derive"] } -serde_json = "1.0.74" +serde_json = "1.0.79" smallvec = "1.8.0" sp-arithmetic = { version = "5.0.0", path = "../../primitives/arithmetic" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } diff --git a/client/peerset/Cargo.toml b/client/peerset/Cargo.toml index 1bbf8bd6e9cb..12991eac81bd 100644 --- a/client/peerset/Cargo.toml +++ b/client/peerset/Cargo.toml @@ -18,7 +18,7 @@ futures = "0.3.19" libp2p = { version = "0.40.0", default-features = false } sc-utils = { version = "4.0.0-dev", path = "../utils"} log = "0.4.8" -serde_json = "1.0.74" +serde_json = "1.0.79" wasm-timer = "0.2" [dev-dependencies] diff --git a/client/rpc-api/Cargo.toml b/client/rpc-api/Cargo.toml index 510c59e5b8aa..38ac1fc44335 100644 --- a/client/rpc-api/Cargo.toml +++ b/client/rpc-api/Cargo.toml @@ -28,7 +28,7 @@ sp-version = { version = "5.0.0", path = "../../primitives/version" } sp-runtime = { version = "6.0.0", path = "../../primitives/runtime" } sc-chain-spec = { path = "../chain-spec", version = "4.0.0-dev" } serde = { version = "1.0.136", features = ["derive"] } -serde_json = "1.0.74" +serde_json = "1.0.79" sc-transaction-pool-api = { version = "4.0.0-dev", path = "../transaction-pool/api" } sp-rpc = { version = "6.0.0", path = "../../primitives/rpc" } sp-tracing = { version = "5.0.0", path = "../../primitives/tracing" } diff --git a/client/rpc-servers/Cargo.toml b/client/rpc-servers/Cargo.toml index 496152ecb750..f0c3fd496aa7 100644 --- a/client/rpc-servers/Cargo.toml +++ b/client/rpc-servers/Cargo.toml @@ -18,7 +18,7 @@ jsonrpc-core = "18.0.0" pubsub = { package = "jsonrpc-pubsub", version = "18.0.0" } log = "0.4.8" prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.10.0-dev"} -serde_json = "1.0.74" +serde_json = "1.0.79" tokio = { version = "1.15", features = ["parking_lot"] } http = { package = "jsonrpc-http-server", version = "18.0.0" } ipc = { package = "jsonrpc-ipc-server", version = "18.0.0" } diff --git a/client/rpc/Cargo.toml b/client/rpc/Cargo.toml index 314c49d2f862..eeeb67f36261 100644 --- a/client/rpc/Cargo.toml +++ b/client/rpc/Cargo.toml @@ -23,7 +23,7 @@ log = "0.4.8" sp-core = { version = "6.0.0", path = "../../primitives/core" } rpc = { package = "jsonrpc-core", version = "18.0.0" } sp-version = { version = "5.0.0", path = "../../primitives/version" } -serde_json = "1.0.74" +serde_json = "1.0.79" sp-session = { version = "4.0.0-dev", path = "../../primitives/session" } sp-offchain = { version = "4.0.0-dev", path = "../../primitives/offchain" } sp-runtime = { version = "6.0.0", path = "../../primitives/runtime" } diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index 84ac9e3de642..737a29f1db0c 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -34,7 +34,7 @@ exit-future = "0.2.0" pin-project = "1.0.10" hash-db = "0.15.2" serde = "1.0.136" -serde_json = "1.0.74" +serde_json = "1.0.79" sc-keystore = { version = "4.0.0-dev", path = "../keystore" } sp-runtime = { version = "6.0.0", path = "../../primitives/runtime" } sp-trie = { version = "6.0.0", path = "../../primitives/trie" } diff --git a/client/sync-state-rpc/Cargo.toml b/client/sync-state-rpc/Cargo.toml index e6072267f963..e13631f210bc 100644 --- a/client/sync-state-rpc/Cargo.toml +++ b/client/sync-state-rpc/Cargo.toml @@ -22,7 +22,7 @@ sc-client-api = { version = "4.0.0-dev", path = "../api" } sc-consensus-babe = { version = "0.10.0-dev", path = "../consensus/babe" } sc-consensus-epochs = { version = "0.10.0-dev", path = "../consensus/epochs" } sc-finality-grandpa = { version = "0.10.0-dev", path = "../finality-grandpa" } -serde_json = "1.0.74" +serde_json = "1.0.79" serde = { version = "1.0.136", features = ["derive"] } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-runtime = { version = "6.0.0", path = "../../primitives/runtime" } diff --git a/client/telemetry/Cargo.toml b/client/telemetry/Cargo.toml index 7bdd60a037e1..6daa75f45362 100644 --- a/client/telemetry/Cargo.toml +++ b/client/telemetry/Cargo.toml @@ -23,6 +23,6 @@ log = "0.4.8" pin-project = "1.0.10" rand = "0.7.2" serde = { version = "1.0.136", features = ["derive"] } -serde_json = "1.0.74" +serde_json = "1.0.79" chrono = "0.4.19" thiserror = "1.0.30" diff --git a/frame/merkle-mountain-range/rpc/Cargo.toml b/frame/merkle-mountain-range/rpc/Cargo.toml index 7124682c5689..9ac26c2ed54b 100644 --- a/frame/merkle-mountain-range/rpc/Cargo.toml +++ b/frame/merkle-mountain-range/rpc/Cargo.toml @@ -27,4 +27,4 @@ sp-runtime = { version = "6.0.0", path = "../../../primitives/runtime" } pallet-mmr-primitives = { version = "4.0.0-dev", path = "../primitives" } [dev-dependencies] -serde_json = "1.0.74" +serde_json = "1.0.79" diff --git a/frame/transaction-payment/Cargo.toml b/frame/transaction-payment/Cargo.toml index ea894e7cada6..d37a98deecb2 100644 --- a/frame/transaction-payment/Cargo.toml +++ b/frame/transaction-payment/Cargo.toml @@ -29,7 +29,7 @@ frame-support = { version = "4.0.0-dev", default-features = false, path = "../su frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } [dev-dependencies] -serde_json = "1.0.74" +serde_json = "1.0.79" pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] diff --git a/frame/transaction-payment/asset-tx-payment/Cargo.toml b/frame/transaction-payment/asset-tx-payment/Cargo.toml index ec07fc967c92..0c2bcb730aa7 100644 --- a/frame/transaction-payment/asset-tx-payment/Cargo.toml +++ b/frame/transaction-payment/asset-tx-payment/Cargo.toml @@ -30,7 +30,7 @@ serde = { version = "1.0.136", optional = true } [dev-dependencies] smallvec = "1.8.0" -serde_json = "1.0.74" +serde_json = "1.0.79" sp-storage = { version = "6.0.0", default-features = false, path = "../../../primitives/storage" } diff --git a/primitives/rpc/Cargo.toml b/primitives/rpc/Cargo.toml index f2d048ef713e..dcfd48558de2 100644 --- a/primitives/rpc/Cargo.toml +++ b/primitives/rpc/Cargo.toml @@ -18,4 +18,4 @@ sp-core = { version = "6.0.0", path = "../core" } rustc-hash = "1.1.0" [dev-dependencies] -serde_json = "1.0.74" +serde_json = "1.0.79" diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 5f7b45ba15a8..a0acdaf27dc5 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -32,7 +32,7 @@ hash256-std-hasher = { version = "0.15.2", default-features = false } either = { version = "1.5", default-features = false } [dev-dependencies] -serde_json = "1.0.74" +serde_json = "1.0.79" rand = "0.7.2" sp-state-machine = { version = "0.12.0", path = "../state-machine" } sp-api = { version = "4.0.0-dev", path = "../api" } diff --git a/primitives/serializer/Cargo.toml b/primitives/serializer/Cargo.toml index 6a9fb5d90ddb..c81f1cd10a82 100644 --- a/primitives/serializer/Cargo.toml +++ b/primitives/serializer/Cargo.toml @@ -15,4 +15,4 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = "1.0.136" -serde_json = "1.0.74" +serde_json = "1.0.79" diff --git a/test-utils/client/Cargo.toml b/test-utils/client/Cargo.toml index f3299d800a6f..1f7115cf16cf 100644 --- a/test-utils/client/Cargo.toml +++ b/test-utils/client/Cargo.toml @@ -16,7 +16,7 @@ codec = { package = "parity-scale-codec", version = "3.0.0" } futures = "0.3.19" hex = "0.4" serde = "1.0.136" -serde_json = "1.0.74" +serde_json = "1.0.79" sc-client-api = { version = "4.0.0-dev", path = "../../client/api" } sc-client-db = { version = "0.10.0-dev", features = [ "test-helpers", diff --git a/utils/frame/benchmarking-cli/Cargo.toml b/utils/frame/benchmarking-cli/Cargo.toml index 5575bb833ca7..b28fe195a2f3 100644 --- a/utils/frame/benchmarking-cli/Cargo.toml +++ b/utils/frame/benchmarking-cli/Cargo.toml @@ -38,7 +38,7 @@ codec = { version = "3.0.0", package = "parity-scale-codec" } clap = { version = "3.1.6", features = ["derive"] } chrono = "0.4" serde = "1.0.136" -serde_json = "1.0.74" +serde_json = "1.0.79" handlebars = "4.1.6" Inflector = "0.11.4" linked-hash-map = "0.5.4" From c364008a6c7da8456e17967f55edf51e45146998 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 18 Mar 2022 17:16:09 +0000 Subject: [PATCH 610/695] Bump proc-macro-crate from 1.1.0 to 1.1.3 (#11063) Bumps [proc-macro-crate](https://github.com/bkchr/proc-macro-crate) from 1.1.0 to 1.1.3. - [Release notes](https://github.com/bkchr/proc-macro-crate/releases) - [Commits](https://github.com/bkchr/proc-macro-crate/commits) --- updated-dependencies: - dependency-name: proc-macro-crate dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 28 +++++++++---------- client/chain-spec/derive/Cargo.toml | 2 +- client/tracing/proc-macro/Cargo.toml | 2 +- .../solution-type/Cargo.toml | 2 +- frame/staking/reward-curve/Cargo.toml | 2 +- frame/support/procedural/tools/Cargo.toml | 2 +- primitives/api/proc-macro/Cargo.toml | 2 +- .../runtime-interface/proc-macro/Cargo.toml | 2 +- test-utils/derive/Cargo.toml | 2 +- 9 files changed, 22 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d3b0771c451c..70a50a6f3e23 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2168,7 +2168,7 @@ version = "4.0.0-dev" dependencies = [ "frame-election-provider-support", "parity-scale-codec", - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "scale-info", @@ -2290,7 +2290,7 @@ name = "frame-support-procedural-tools" version = "4.0.0-dev" dependencies = [ "frame-support-procedural-tools-derive", - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn", @@ -3448,7 +3448,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4299ebf790ea9de1cb72e73ff2ae44c723ef264299e5e2d5ef46a371eb3ac3d8" dependencies = [ - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn", @@ -4663,7 +4663,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "424f6e86263cd5294cbd7f1e95746b95aca0e0d66bff31e5a40d6baa87b4aa99" dependencies = [ - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro-error", "proc-macro2", "quote", @@ -6441,7 +6441,7 @@ dependencies = [ name = "pallet-staking-reward-curve" version = "4.0.0-dev" dependencies = [ - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "sp-runtime", @@ -6736,7 +6736,7 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c6e626dc84025ff56bf1476ed0e30d10c84d7f89a475ef46ebabee1095a8fba" dependencies = [ - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn", @@ -7230,9 +7230,9 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "1.1.0" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebace6889caf889b4d3f76becee12e90353f2b8c7d875534a71e5742f8f6f83" +checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" dependencies = [ "thiserror", "toml", @@ -8107,7 +8107,7 @@ dependencies = [ name = "sc-chain-spec-derive" version = "4.0.0-dev" dependencies = [ - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn", @@ -9092,7 +9092,7 @@ dependencies = [ name = "sc-tracing-proc-macro" version = "4.0.0-dev" dependencies = [ - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn", @@ -9177,7 +9177,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7805950c36512db9e3251c970bb7ac425f326716941862205d612ab3b5e46e2" dependencies = [ - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn", @@ -9670,7 +9670,7 @@ name = "sp-api-proc-macro" version = "4.0.0-dev" dependencies = [ "blake2 0.10.2", - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn", @@ -10193,7 +10193,7 @@ name = "sp-runtime-interface-proc-macro" version = "5.0.0" dependencies = [ "Inflector", - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn", @@ -10773,7 +10773,7 @@ dependencies = [ name = "substrate-test-utils-derive" version = "0.10.0-dev" dependencies = [ - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn", diff --git a/client/chain-spec/derive/Cargo.toml b/client/chain-spec/derive/Cargo.toml index 1ea9440572d4..9aa1d6c09405 100644 --- a/client/chain-spec/derive/Cargo.toml +++ b/client/chain-spec/derive/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] proc-macro = true [dependencies] -proc-macro-crate = "1.1.0" +proc-macro-crate = "1.1.3" proc-macro2 = "1.0.36" quote = "1.0.10" syn = "1.0.82" diff --git a/client/tracing/proc-macro/Cargo.toml b/client/tracing/proc-macro/Cargo.toml index e939d0837b21..645a6ed93a16 100644 --- a/client/tracing/proc-macro/Cargo.toml +++ b/client/tracing/proc-macro/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] proc-macro = true [dependencies] -proc-macro-crate = "1.1.0" +proc-macro-crate = "1.1.3" proc-macro2 = "1.0.36" quote = { version = "1.0.10", features = ["proc-macro"] } syn = { version = "1.0.82", features = ["proc-macro", "full", "extra-traits", "parsing"] } diff --git a/frame/election-provider-support/solution-type/Cargo.toml b/frame/election-provider-support/solution-type/Cargo.toml index 09747eebe2df..e59bbcc8e7b3 100644 --- a/frame/election-provider-support/solution-type/Cargo.toml +++ b/frame/election-provider-support/solution-type/Cargo.toml @@ -18,7 +18,7 @@ proc-macro = true syn = { version = "1.0.82", features = ["full", "visit"] } quote = "1.0" proc-macro2 = "1.0.36" -proc-macro-crate = "1.1.0" +proc-macro-crate = "1.1.3" [dev-dependencies] parity-scale-codec = "3.0.0" diff --git a/frame/staking/reward-curve/Cargo.toml b/frame/staking/reward-curve/Cargo.toml index 82167bd8c8ec..d53fb72b0e08 100644 --- a/frame/staking/reward-curve/Cargo.toml +++ b/frame/staking/reward-curve/Cargo.toml @@ -18,7 +18,7 @@ proc-macro = true syn = { version = "1.0.82", features = ["full", "visit"] } quote = "1.0.10" proc-macro2 = "1.0.36" -proc-macro-crate = "1.1.0" +proc-macro-crate = "1.1.3" [dev-dependencies] sp-runtime = { version = "6.0.0", path = "../../../primitives/runtime" } diff --git a/frame/support/procedural/tools/Cargo.toml b/frame/support/procedural/tools/Cargo.toml index ae2de2effd4a..b38071dd3158 100644 --- a/frame/support/procedural/tools/Cargo.toml +++ b/frame/support/procedural/tools/Cargo.toml @@ -16,4 +16,4 @@ frame-support-procedural-tools-derive = { version = "3.0.0", path = "./derive" } proc-macro2 = "1.0.36" quote = "1.0.10" syn = { version = "1.0.82", features = ["full", "visit", "extra-traits"] } -proc-macro-crate = "1.1.0" +proc-macro-crate = "1.1.3" diff --git a/primitives/api/proc-macro/Cargo.toml b/primitives/api/proc-macro/Cargo.toml index 356e15a6fd11..dc5deb2efa66 100644 --- a/primitives/api/proc-macro/Cargo.toml +++ b/primitives/api/proc-macro/Cargo.toml @@ -20,7 +20,7 @@ quote = "1.0.10" syn = { version = "1.0.82", features = ["full", "fold", "extra-traits", "visit"] } proc-macro2 = "1.0.36" blake2 = { version = "0.10.2", default-features = false } -proc-macro-crate = "1.1.0" +proc-macro-crate = "1.1.3" # Required for the doc tests [features] diff --git a/primitives/runtime-interface/proc-macro/Cargo.toml b/primitives/runtime-interface/proc-macro/Cargo.toml index 57e5448348d6..ef59e0119f9f 100644 --- a/primitives/runtime-interface/proc-macro/Cargo.toml +++ b/primitives/runtime-interface/proc-macro/Cargo.toml @@ -20,4 +20,4 @@ syn = { version = "1.0.82", features = ["full", "visit", "fold", "extra-traits"] quote = "1.0.10" proc-macro2 = "1.0.36" Inflector = "0.11.4" -proc-macro-crate = "1.1.0" +proc-macro-crate = "1.1.3" diff --git a/test-utils/derive/Cargo.toml b/test-utils/derive/Cargo.toml index 166d9cc1eff1..16e0b9822f7b 100644 --- a/test-utils/derive/Cargo.toml +++ b/test-utils/derive/Cargo.toml @@ -11,7 +11,7 @@ description = "Substrate test utilities macros" [dependencies] quote = "1.0.10" syn = { version = "1.0.82", features = ["full"] } -proc-macro-crate = "1.1.0" +proc-macro-crate = "1.1.3" proc-macro2 = "1.0.36" [lib] From b1ea7c1a85f86e94c10be40abe2920d2deef473c Mon Sep 17 00:00:00 2001 From: driemworks Date: Fri, 18 Mar 2022 13:11:14 -0500 Subject: [PATCH 611/695] use assets pallet runtime storage to get assset id owner --- .../pallets/iris-assets/README.md | 2 +- .../pallets/iris-assets/src/lib.rs | 19 +++++++++++-------- .../pallets/iris-session/src/lib.rs | 1 + frame/assets/src/lib.rs | 1 + frame/assets/src/types.rs | 2 +- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/bin/node-template/pallets/iris-assets/README.md b/bin/node-template/pallets/iris-assets/README.md index 0f069f5534be..0c2d74605ea5 100644 --- a/bin/node-template/pallets/iris-assets/README.md +++ b/bin/node-template/pallets/iris-assets/README.md @@ -6,4 +6,4 @@ Additionally, it provides the functionality to add DataCommands to a queue which - Adding data to iris - Requesting data from iris -License: Unlicense \ No newline at end of file +License: Unlicense diff --git a/bin/node-template/pallets/iris-assets/src/lib.rs b/bin/node-template/pallets/iris-assets/src/lib.rs index b62665d1782e..4b34967347c1 100644 --- a/bin/node-template/pallets/iris-assets/src/lib.rs +++ b/bin/node-template/pallets/iris-assets/src/lib.rs @@ -115,8 +115,8 @@ pub mod pallet { pub(super) type AssetClassOwnership = StorageMap< _, Blake2_128Concat, - T::AssetId, T::AccountId, + Vec, ValueQuery, >; @@ -295,8 +295,8 @@ pub mod pallet { )?; let target_account = T::Lookup::lookup(target)?; - // get asset owner (could be different than origin) - let asset_id_owner = >::get(asset_id.clone()); + + let asset_id_owner = >::asset(asset_id.clone()).unwrap().owner; >::insert(target_account.clone(), asset_id.clone(), asset_id_owner.clone()); Ok(()) @@ -376,7 +376,10 @@ pub mod pallet { >::insert(id.clone(), cid.clone()); let which_admin = T::Lookup::lookup(admin.clone())?; - >::insert(id.clone(), which_admin); + let mut asset_ids = >::get(which_admin); + asset_ids.mutate(|ids| { + ids.push(, id.clone())); + }); >::mutate(|ids| ids.push(id.clone())); Self::deposit_event(Event::AssetClassCreated(id.clone())); @@ -386,8 +389,8 @@ pub mod pallet { /// Add a request to pin a cid to the DataQueue for your embedded IPFS node /// - /// * asset_owner: The owner of the asset class - /// * asset_id: The asset id of some asset class + /// * `asset_owner`: The owner of the asset class + /// * `asset_id`: The asset id of some asset class /// #[pallet::weight(100)] pub fn insert_pin_request( @@ -396,8 +399,8 @@ pub mod pallet { #[pallet::compact] asset_id: T::AssetId, ) -> DispatchResult { let who = ensure_signed(origin)?; - - let asset_id_owner = >::get(asset_id.clone()); + + let asset_id_owner = >::asset(asset_id.clone()).unwrap().owner; ensure!( asset_id_owner == asset_owner.clone(), Error::::NoSuchOwnedContent diff --git a/bin/node-template/pallets/iris-session/src/lib.rs b/bin/node-template/pallets/iris-session/src/lib.rs index 16f1b7438cba..beb2b3ced134 100644 --- a/bin/node-template/pallets/iris-session/src/lib.rs +++ b/bin/node-template/pallets/iris-session/src/lib.rs @@ -1005,6 +1005,7 @@ impl pallet_session::SessionManager for Pallet { fn end_session(end_index: u32) { log::info!("Ending session with index: {:?}", end_index); + // TODO: calculate which validators should fetch which data? not ideal really.. idk Self::mark_dead_validators(end_index); } diff --git a/frame/assets/src/lib.rs b/frame/assets/src/lib.rs index 2c9f994b3fef..5cdb48b9672b 100644 --- a/frame/assets/src/lib.rs +++ b/frame/assets/src/lib.rs @@ -225,6 +225,7 @@ pub mod pallet { } #[pallet::storage] + #[pallet::getter(fn asset)] /// Details of an asset. pub(super) type Asset, I: 'static = ()> = StorageMap< _, diff --git a/frame/assets/src/types.rs b/frame/assets/src/types.rs index bc2edce848a6..8e0de6f1173d 100644 --- a/frame/assets/src/types.rs +++ b/frame/assets/src/types.rs @@ -30,7 +30,7 @@ pub(super) type DepositBalanceOf = #[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, MaxEncodedLen, TypeInfo)] pub struct AssetDetails { /// Can change `owner`, `issuer`, `freezer` and `admin` accounts. - pub(super) owner: AccountId, + pub owner: AccountId, /// Can mint tokens. pub(super) issuer: AccountId, /// Can thaw tokens, force transfers and burn tokens from any account. From 318ec575bcca3b447aebad680e5f37d4cbfd5792 Mon Sep 17 00:00:00 2001 From: driemworks Date: Fri, 18 Mar 2022 18:36:50 -0500 Subject: [PATCH 612/695] use assets pallet to get owner of asset class --- bin/node-template/pallets/iris-assets/src/lib.rs | 4 +--- bin/node-template/pallets/iris-ledger/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/bin/node-template/pallets/iris-assets/src/lib.rs b/bin/node-template/pallets/iris-assets/src/lib.rs index 4b34967347c1..dcb9b8914213 100644 --- a/bin/node-template/pallets/iris-assets/src/lib.rs +++ b/bin/node-template/pallets/iris-assets/src/lib.rs @@ -377,9 +377,7 @@ pub mod pallet { let which_admin = T::Lookup::lookup(admin.clone())?; let mut asset_ids = >::get(which_admin); - asset_ids.mutate(|ids| { - ids.push(, id.clone())); - }); + asset_ids.push(id.clone()); >::mutate(|ids| ids.push(id.clone())); Self::deposit_event(Event::AssetClassCreated(id.clone())); diff --git a/bin/node-template/pallets/iris-ledger/src/lib.rs b/bin/node-template/pallets/iris-ledger/src/lib.rs index bb1020a8a94c..66ddead93ecc 100644 --- a/bin/node-template/pallets/iris-ledger/src/lib.rs +++ b/bin/node-template/pallets/iris-ledger/src/lib.rs @@ -152,7 +152,7 @@ pub mod pallet { &target, amount, KeepAlive, - ); + )?; >::remove(who.clone()); Self::deposit_event(Event::Unlocked(who)); From 4c9bf004f07c698451de5bc7749d0e23f08b7eea Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Sat, 19 Mar 2022 11:35:39 +0000 Subject: [PATCH 613/695] some additional utils for state-trie-migration (#11064) * some additional utils for state-trie-migration' * Update frame/state-trie-migration/src/lib.rs Co-authored-by: cheme Co-authored-by: cheme --- bin/node/runtime/src/lib.rs | 3 -- frame/state-trie-migration/src/lib.rs | 75 ++++++++++++++++++++++----- 2 files changed, 63 insertions(+), 15 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 797e0c079028..d679af6f51c4 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -1372,8 +1372,6 @@ impl pallet_whitelist::Config for Runtime { } parameter_types! { - pub const SignedMigrationMaxLimits: pallet_state_trie_migration::MigrationLimits = - pallet_state_trie_migration::MigrationLimits { size: 1024 * 1024 / 2, item: 512 }; pub const MigrationSignedDepositPerItem: Balance = 1 * CENTS; pub const MigrationSignedDepositBase: Balance = 20 * DOLLARS; } @@ -1384,7 +1382,6 @@ impl pallet_state_trie_migration::Config for Runtime { type Currency = Balances; type SignedDepositPerItem = MigrationSignedDepositPerItem; type SignedDepositBase = MigrationSignedDepositBase; - type SignedMigrationMaxLimits = SignedMigrationMaxLimits; // Warning: this is not advised, as it might allow the chain to be temporarily DOS-ed. // Preferably, if the chain's governance/maintenance team is planning on using a specific // account for the migration, put it here to make sure only that account can trigger the signed diff --git a/frame/state-trie-migration/src/lib.rs b/frame/state-trie-migration/src/lib.rs index a5a077c54e57..87be4099c89c 100644 --- a/frame/state-trie-migration/src/lib.rs +++ b/frame/state-trie-migration/src/lib.rs @@ -123,10 +123,14 @@ pub mod pallet { } } + /// The progress of either the top or child keys. #[derive(Clone, Encode, Decode, scale_info::TypeInfo, PartialEq, Eq)] - pub(crate) enum Progress { + pub enum Progress { + /// Yet to begin. ToStart, + /// Ongoing, with the last key given. LastKey(Vec), + /// All done. Complete, } @@ -447,10 +451,6 @@ pub mod pallet { /// Final deposit is `items * SignedDepositPerItem + SignedDepositBase`. type SignedDepositBase: Get>; - /// The maximum limits that the signed migration could use. - #[pallet::constant] - type SignedMigrationMaxLimits: Get; - /// The weight information of this pallet. type WeightInfo: WeightInfo; } @@ -470,6 +470,13 @@ pub mod pallet { #[pallet::getter(fn auto_limits)] pub type AutoLimits = StorageValue<_, Option, ValueQuery>; + /// The maximum limits that the signed migration could use. + /// + /// If not set, no signed submission is allowed. + #[pallet::storage] + #[pallet::getter(fn signed_migration_max_limits)] + pub type SignedMigrationMaxLimits = StorageValue<_, MigrationLimits, OptionQuery>; + #[pallet::error] pub enum Error { /// max signed limits not respected. @@ -480,6 +487,8 @@ pub mod pallet { BadWitness, /// upper bound of size is exceeded, SizeUpperBoundExceeded, + /// Signed migration is not allowed because the maximum limit is not set yet. + SignedMigrationNotAllowed, } #[pallet::call] @@ -491,7 +500,7 @@ pub mod pallet { pub fn control_auto_migration( origin: OriginFor, maybe_config: Option, - ) -> DispatchResultWithPostInfo { + ) -> DispatchResult { T::ControlOrigin::ensure_origin(origin)?; AutoLimits::::put(maybe_config); Ok(().into()) @@ -532,7 +541,8 @@ pub mod pallet { ) -> DispatchResultWithPostInfo { let who = T::SignedFilter::ensure_origin(origin)?; - let max_limits = T::SignedMigrationMaxLimits::get(); + let max_limits = + Self::signed_migration_max_limits().ok_or(Error::::SignedMigrationNotAllowed)?; ensure!( limits.size <= max_limits.size && limits.item <= max_limits.item, Error::::MaxSignedLimits, @@ -701,6 +711,40 @@ pub mod pallet { }) } } + + /// Set the maximum limit of the signed migration. + #[pallet::weight(T::DbWeight::get().reads_writes(1, 1))] + pub fn set_signed_max_limits( + origin: OriginFor, + limits: MigrationLimits, + ) -> DispatchResult { + let _ = T::ControlOrigin::ensure_origin(origin)?; + SignedMigrationMaxLimits::::put(limits); + Ok(()) + } + + /// Forcefully set the progress the running migration. + /// + /// This is only useful in one case: the next key to migrate is too big to be migrated with + /// a signed account, in a parachain context, and we simply want to skip it. A reasonable + /// example of this would be `:code:`, which is both very expensive to migrate, and commonly + /// used, so probably it is already migrated. + /// + /// In case you mess things up, you can also, in principle, use this to reset the migration + /// process. + #[pallet::weight(T::DbWeight::get().reads_writes(1, 1))] + pub fn force_set_progress( + origin: OriginFor, + progress_top: Progress, + progress_child: Progress, + ) -> DispatchResult { + let _ = T::ControlOrigin::ensure_origin(origin)?; + MigrationProcess::::mutate(|task| { + task.progress_top = progress_top; + task.progress_child = progress_child; + }); + Ok(()) + } } #[pallet::hooks] @@ -1000,7 +1044,6 @@ mod mock { pub const OffchainRepeat: u32 = 1; pub const SignedDepositPerItem: u64 = 1; pub const SignedDepositBase: u64 = 5; - pub const SignedMigrationMaxLimits: MigrationLimits = MigrationLimits { size: 1024, item: 5 }; } impl pallet_balances::Config for Test { @@ -1021,7 +1064,6 @@ mod mock { type Currency = Balances; type SignedDepositPerItem = SignedDepositPerItem; type SignedDepositBase = SignedDepositBase; - type SignedMigrationMaxLimits = SignedMigrationMaxLimits; type SignedFilter = EnsureSigned; type WeightInfo = (); } @@ -1104,7 +1146,14 @@ mod mock { } sp_tracing::try_init_simple(); - (custom_storage, version).into() + let mut ext: sp_io::TestExternalities = (custom_storage, version).into(); + + // set some genesis values for this pallet as well. + ext.execute_with(|| { + SignedMigrationMaxLimits::::put(MigrationLimits { size: 1024, item: 5 }); + }); + + ext } pub(crate) fn run_to_block(n: u32) -> (H256, u64) { @@ -1283,11 +1332,13 @@ mod test { while !MigrationProcess::::get().finished() { // first we compute the task to get the accurate consumption. let mut task = StateTrieMigration::migration_process(); - task.migrate_until_exhaustion(SignedMigrationMaxLimits::get()); + task.migrate_until_exhaustion( + StateTrieMigration::signed_migration_max_limits().unwrap(), + ); frame_support::assert_ok!(StateTrieMigration::continue_migrate( Origin::signed(1), - SignedMigrationMaxLimits::get(), + StateTrieMigration::signed_migration_max_limits().unwrap(), task.dyn_size, MigrationProcess::::get() )); From 8cbda809d3495f38ce04eec46e90330db213af8a Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Sat, 19 Mar 2022 12:24:41 +0000 Subject: [PATCH 614/695] Incorporate the new electing/electable naming into the code (#10956) * Incorporate the new electing/electable naming into the code * Update frame/election-provider-support/src/lib.rs Co-authored-by: Zeke Mostov * Update frame/election-provider-support/src/lib.rs Co-authored-by: Zeke Mostov * Some additional changes * fmt * update codec * revert lock file to master * fix doc test Co-authored-by: Zeke Mostov --- bin/node/runtime/src/lib.rs | 16 +++---- frame/bags-list/remote-tests/src/snapshot.rs | 3 +- .../src/benchmarking.rs | 4 +- .../election-provider-multi-phase/src/lib.rs | 37 +++++++-------- .../election-provider-multi-phase/src/mock.rs | 13 +++-- frame/election-provider-support/src/lib.rs | 17 ++++--- .../election-provider-support/src/onchain.rs | 11 +++-- frame/staking/src/pallet/impls.rs | 4 +- frame/staking/src/tests.rs | 47 ++++++++++--------- 9 files changed, 82 insertions(+), 70 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index d679af6f51c4..64bdcfc87020 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -46,11 +46,12 @@ use frame_system::{ pub use node_primitives::{AccountId, Signature}; use node_primitives::{AccountIndex, Balance, BlockNumber, Hash, Index, Moment}; use pallet_contracts::weights::WeightInfo; +use pallet_election_provider_multi_phase::SolutionAccuracyOf; use pallet_grandpa::{ fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList, }; use pallet_im_online::sr25519::AuthorityId as ImOnlineId; -use pallet_session::historical as pallet_session_historical; +use pallet_session::historical::{self as pallet_session_historical}; pub use pallet_transaction_payment::{CurrencyAdapter, Multiplier, TargetedFeeAdjustment}; use pallet_transaction_payment::{FeeDetails, RuntimeDispatchInfo}; use sp_api::impl_runtime_apis; @@ -668,20 +669,17 @@ impl pallet_election_provider_multi_phase::Config for Runtime { type DataProvider = Staking; type Solution = NposSolution16; type Fallback = pallet_election_provider_multi_phase::NoFallback; - type GovernanceFallback = - frame_election_provider_support::onchain::OnChainSequentialPhragmen; + type GovernanceFallback = onchain::OnChainSequentialPhragmen; type Solver = frame_election_provider_support::SequentialPhragmen< AccountId, - pallet_election_provider_multi_phase::SolutionAccuracyOf, + SolutionAccuracyOf, OffchainRandomBalancing, >; - type WeightInfo = pallet_election_provider_multi_phase::weights::SubstrateWeight; type ForceOrigin = EnsureRootOrHalfCouncil; + type MaxElectableTargets = ConstU16<{ u16::MAX }>; + type MaxElectingVoters = ConstU32<10_000>; type BenchmarkingConfig = ElectionProviderBenchmarkConfig; - // BagsList allows a practically unbounded count of nominators to participate in NPoS elections. - // To ensure we respect memory limits when using the BagsList this must be set to a number of - // voters we know can fit into a single vec allocation. - type VoterSnapshotPerBlock = ConstU32<10_000>; + type WeightInfo = pallet_election_provider_multi_phase::weights::SubstrateWeight; } parameter_types! { diff --git a/frame/bags-list/remote-tests/src/snapshot.rs b/frame/bags-list/remote-tests/src/snapshot.rs index 241b64b36611..2d996746a29c 100644 --- a/frame/bags-list/remote-tests/src/snapshot.rs +++ b/frame/bags-list/remote-tests/src/snapshot.rs @@ -56,7 +56,8 @@ pub async fn execute ); let voters = - as ElectionDataProvider>::voters(voter_limit).unwrap(); + as ElectionDataProvider>::electing_voters(voter_limit) + .unwrap(); let mut voters_nominator_only = voters .iter() diff --git a/frame/election-provider-multi-phase/src/benchmarking.rs b/frame/election-provider-multi-phase/src/benchmarking.rs index 2a9286369f39..923e9e2d984c 100644 --- a/frame/election-provider-multi-phase/src/benchmarking.rs +++ b/frame/election-provider-multi-phase/src/benchmarking.rs @@ -260,8 +260,8 @@ frame_benchmarking::benchmarks! { // we don't directly need the data-provider to be populated, but it is just easy to use it. set_up_data_provider::(v, t); - let targets = T::DataProvider::targets(None)?; - let voters = T::DataProvider::voters(None)?; + let targets = T::DataProvider::electable_targets(None)?; + let voters = T::DataProvider::electing_voters(None)?; let desired_targets = T::DataProvider::desired_targets()?; assert!(>::snapshot().is_none()); }: { diff --git a/frame/election-provider-multi-phase/src/lib.rs b/frame/election-provider-multi-phase/src/lib.rs index 90c540b85d67..b57d24d2d530 100644 --- a/frame/election-provider-multi-phase/src/lib.rs +++ b/frame/election-provider-multi-phase/src/lib.rs @@ -69,7 +69,7 @@ //! Upon the end of the signed phase, the solutions are examined from best to worse (i.e. `pop()`ed //! until drained). Each solution undergoes an expensive `Pallet::feasibility_check`, which ensures //! the score claimed by this score was correct, and it is valid based on the election data (i.e. -//! votes and candidates). At each step, if the current best solution passes the feasibility check, +//! votes and targets). At each step, if the current best solution passes the feasibility check, //! it is considered to be the best one. The sender of the origin is rewarded, and the rest of the //! queued solutions get their deposit back and are discarded, without being checked. //! @@ -249,7 +249,6 @@ use sp_npos_elections::{ assignment_ratio_to_staked_normalized, ElectionScore, EvaluateSupport, Supports, VoteWeight, }; use sp_runtime::{ - traits::Bounded, transaction_validity::{ InvalidTransaction, TransactionPriority, TransactionSource, TransactionValidity, TransactionValidityError, ValidTransaction, @@ -643,14 +642,15 @@ pub mod pallet { #[pallet::constant] type SignedDepositWeight: Get>; - /// The maximum number of voters to put in the snapshot. At the moment, snapshots are only - /// over a single block, but once multi-block elections are introduced they will take place - /// over multiple blocks. - /// - /// Also, note the data type: If the voters are represented by a `u32` in `type - /// CompactSolution`, the same `u32` is used here to ensure bounds are respected. + /// The maximum number of electing voters to put in the snapshot. At the moment, snapshots + /// are only over a single block, but once multi-block elections are introduced they will + /// take place over multiple blocks. + #[pallet::constant] + type MaxElectingVoters: Get>; + + /// The maximum number of electable targets to put in the snapshot. #[pallet::constant] - type VoterSnapshotPerBlock: Get>; + type MaxElectableTargets: Get>; /// Handler for the slashed deposits. type SlashHandler: OnUnbalanced>; @@ -817,7 +817,7 @@ pub mod pallet { fn integrity_test() { use sp_std::mem::size_of; // The index type of both voters and targets need to be smaller than that of usize (very - // unlikely to be the case, but anyhow). + // unlikely to be the case, but anyhow).. assert!(size_of::>() <= size_of::()); assert!(size_of::>() <= size_of::()); @@ -1338,14 +1338,13 @@ impl Pallet { /// Extracted for easier weight calculation. fn create_snapshot_external( ) -> Result<(Vec, Vec>, u32), ElectionError> { - let target_limit = >::max_value().saturated_into::(); - // for now we have just a single block snapshot. - let voter_limit = T::VoterSnapshotPerBlock::get().saturated_into::(); - - let targets = - T::DataProvider::targets(Some(target_limit)).map_err(ElectionError::DataProvider)?; - let voters = - T::DataProvider::voters(Some(voter_limit)).map_err(ElectionError::DataProvider)?; + let target_limit = T::MaxElectableTargets::get().saturated_into::(); + let voter_limit = T::MaxElectingVoters::get().saturated_into::(); + + let targets = T::DataProvider::electable_targets(Some(target_limit)) + .map_err(ElectionError::DataProvider)?; + let voters = T::DataProvider::electing_voters(Some(voter_limit)) + .map_err(ElectionError::DataProvider)?; let mut desired_targets = T::DataProvider::desired_targets().map_err(ElectionError::DataProvider)?; @@ -2090,7 +2089,7 @@ mod tests { // we have 8 voters in total. assert_eq!(crate::mock::Voters::get().len(), 8); // but we want to take 2. - crate::mock::VoterSnapshotPerBlock::set(2); + crate::mock::MaxElectingVoters::set(2); // Signed phase opens just fine. roll_to(15); diff --git a/frame/election-provider-multi-phase/src/mock.rs b/frame/election-provider-multi-phase/src/mock.rs index d09d45784cba..89b5b72565dc 100644 --- a/frame/election-provider-multi-phase/src/mock.rs +++ b/frame/election-provider-multi-phase/src/mock.rs @@ -263,7 +263,8 @@ parameter_types! { pub static MinerMaxWeight: Weight = BlockWeights::get().max_block; pub static MinerMaxLength: u32 = 256; pub static MockWeightInfo: bool = false; - pub static VoterSnapshotPerBlock: VoterIndex = u32::max_value(); + pub static MaxElectingVoters: VoterIndex = u32::max_value(); + pub static MaxElectableTargets: TargetIndex = TargetIndex::max_value(); pub static EpochLength: u64 = 30; pub static OnChianFallback: bool = true; @@ -413,7 +414,8 @@ impl crate::Config for Runtime { type GovernanceFallback = NoFallback; type ForceOrigin = frame_system::EnsureRoot; type Solution = TestNposSolution; - type VoterSnapshotPerBlock = VoterSnapshotPerBlock; + type MaxElectingVoters = MaxElectingVoters; + type MaxElectableTargets = MaxElectableTargets; type Solver = SequentialPhragmen, Balancing>; } @@ -439,7 +441,8 @@ impl ElectionDataProvider for StakingMock { type AccountId = AccountId; type BlockNumber = u64; type MaxVotesPerVoter = MaxNominations; - fn targets(maybe_max_len: Option) -> data_provider::Result> { + + fn electable_targets(maybe_max_len: Option) -> data_provider::Result> { let targets = Targets::get(); if maybe_max_len.map_or(false, |max_len| targets.len() > max_len) { @@ -449,7 +452,9 @@ impl ElectionDataProvider for StakingMock { Ok(targets) } - fn voters(maybe_max_len: Option) -> data_provider::Result>> { + fn electing_voters( + maybe_max_len: Option, + ) -> data_provider::Result>> { let mut voters = Voters::get(); if let Some(max_len) = maybe_max_len { voters.truncate(max_len) diff --git a/frame/election-provider-support/src/lib.rs b/frame/election-provider-support/src/lib.rs index e1975a2681e6..81fd841a6dc4 100644 --- a/frame/election-provider-support/src/lib.rs +++ b/frame/election-provider-support/src/lib.rs @@ -107,12 +107,12 @@ //! fn desired_targets() -> data_provider::Result { //! Ok(1) //! } -//! fn voters(maybe_max_len: Option) +//! fn electing_voters(maybe_max_len: Option) //! -> data_provider::Result>> //! { //! Ok(Default::default()) //! } -//! fn targets(maybe_max_len: Option) -> data_provider::Result> { +//! fn electable_targets(maybe_max_len: Option) -> data_provider::Result> { //! Ok(vec![10, 20, 30]) //! } //! fn next_election_prediction(now: BlockNumber) -> BlockNumber { @@ -138,7 +138,7 @@ //! type DataProvider = T::DataProvider; //! //! fn elect() -> Result, Self::Error> { -//! Self::DataProvider::targets(None) +//! Self::DataProvider::electable_targets(None) //! .map_err(|_| "failed to elect") //! .map(|t| vec![(t[0], Support::default())]) //! } @@ -265,16 +265,19 @@ pub trait ElectionDataProvider { /// Maximum number of votes per voter that this data provider is providing. type MaxVotesPerVoter: Get; - /// All possible targets for the election, i.e. the candidates. + /// All possible targets for the election, i.e. the targets that could become elected, thus + /// "electable". /// /// If `maybe_max_len` is `Some(v)` then the resulting vector MUST NOT be longer than `v` items /// long. /// /// This should be implemented as a self-weighing function. The implementor should register its /// appropriate weight at the end of execution with the system pallet directly. - fn targets(maybe_max_len: Option) -> data_provider::Result>; + fn electable_targets( + maybe_max_len: Option, + ) -> data_provider::Result>; - /// All possible voters for the election. + /// All the voters that participate in the election, thus "electing". /// /// Note that if a notion of self-vote exists, it should be represented here. /// @@ -283,7 +286,7 @@ pub trait ElectionDataProvider { /// /// This should be implemented as a self-weighing function. The implementor should register its /// appropriate weight at the end of execution with the system pallet directly. - fn voters(maybe_max_len: Option) -> data_provider::Result>>; + fn electing_voters(maybe_max_len: Option) -> data_provider::Result>>; /// The number of targets to elect. /// diff --git a/frame/election-provider-support/src/onchain.rs b/frame/election-provider-support/src/onchain.rs index 41245f67fb02..7d845c2dc5ab 100644 --- a/frame/election-provider-support/src/onchain.rs +++ b/frame/election-provider-support/src/onchain.rs @@ -79,10 +79,11 @@ impl OnChainSequentialPhragmen { maybe_max_voters: Option, maybe_max_targets: Option, ) -> Result, Error> { - let voters = ::DataProvider::voters(maybe_max_voters) - .map_err(Error::DataProvider)?; - let targets = ::DataProvider::targets(maybe_max_targets) + let voters = ::DataProvider::electing_voters(maybe_max_voters) .map_err(Error::DataProvider)?; + let targets = + ::DataProvider::electable_targets(maybe_max_targets) + .map_err(Error::DataProvider)?; let desired_targets = ::DataProvider::desired_targets() .map_err(Error::DataProvider)?; @@ -197,7 +198,7 @@ mod tests { type AccountId = AccountId; type BlockNumber = BlockNumber; type MaxVotesPerVoter = ConstU32<2>; - fn voters(_: Option) -> data_provider::Result>> { + fn electing_voters(_: Option) -> data_provider::Result>> { Ok(vec![ (1, 10, bounded_vec![10, 20]), (2, 20, bounded_vec![30, 20]), @@ -205,7 +206,7 @@ mod tests { ]) } - fn targets(_: Option) -> data_provider::Result> { + fn electable_targets(_: Option) -> data_provider::Result> { Ok(vec![10, 20, 30]) } diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index a4aadb16ab1b..cb024ba2bc52 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -860,7 +860,7 @@ impl ElectionDataProvider for Pallet { Ok(Self::validator_count()) } - fn voters(maybe_max_len: Option) -> data_provider::Result>> { + fn electing_voters(maybe_max_len: Option) -> data_provider::Result>> { // This can never fail -- if `maybe_max_len` is `Some(_)` we handle it. let voters = Self::get_npos_voters(maybe_max_len); debug_assert!(maybe_max_len.map_or(true, |max| voters.len() <= max)); @@ -868,7 +868,7 @@ impl ElectionDataProvider for Pallet { Ok(voters) } - fn targets(maybe_max_len: Option) -> data_provider::Result> { + fn electable_targets(maybe_max_len: Option) -> data_provider::Result> { let target_count = Validators::::count(); // We can't handle this case yet -- return an error. diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 2b2a32e0edab..2d4145242a45 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -4055,10 +4055,12 @@ mod election_data_provider { #[test] fn voters_include_self_vote() { ExtBuilder::default().nominate(false).build_and_execute(|| { - assert!(>::iter().map(|(x, _)| x).all(|v| Staking::voters(None) - .unwrap() - .into_iter() - .any(|(w, _, t)| { v == w && t[0] == w }))) + assert!(>::iter().map(|(x, _)| x).all(|v| Staking::electing_voters( + None + ) + .unwrap() + .into_iter() + .any(|(w, _, t)| { v == w && t[0] == w }))) }) } @@ -4067,7 +4069,7 @@ mod election_data_provider { ExtBuilder::default().build_and_execute(|| { assert_eq!(Staking::nominators(101).unwrap().targets, vec![11, 21]); assert_eq!( - ::voters(None) + ::electing_voters(None) .unwrap() .iter() .find(|x| x.0 == 101) @@ -4082,7 +4084,7 @@ mod election_data_provider { // 11 is gone. start_active_era(2); assert_eq!( - ::voters(None) + ::electing_voters(None) .unwrap() .iter() .find(|x| x.0 == 101) @@ -4094,7 +4096,7 @@ mod election_data_provider { // resubmit and it is back assert_ok!(Staking::nominate(Origin::signed(100), vec![11, 21])); assert_eq!( - ::voters(None) + ::electing_voters(None) .unwrap() .iter() .find(|x| x.0 == 101) @@ -4118,20 +4120,23 @@ mod election_data_provider { ); // if limits is less.. - assert_eq!(Staking::voters(Some(1)).unwrap().len(), 1); + assert_eq!(Staking::electing_voters(Some(1)).unwrap().len(), 1); // if limit is equal.. - assert_eq!(Staking::voters(Some(5)).unwrap().len(), 5); + assert_eq!(Staking::electing_voters(Some(5)).unwrap().len(), 5); // if limit is more. - assert_eq!(Staking::voters(Some(55)).unwrap().len(), 5); + assert_eq!(Staking::electing_voters(Some(55)).unwrap().len(), 5); // if target limit is more.. - assert_eq!(Staking::targets(Some(6)).unwrap().len(), 4); - assert_eq!(Staking::targets(Some(4)).unwrap().len(), 4); + assert_eq!(Staking::electable_targets(Some(6)).unwrap().len(), 4); + assert_eq!(Staking::electable_targets(Some(4)).unwrap().len(), 4); // if target limit is less, then we return an error. - assert_eq!(Staking::targets(Some(1)).unwrap_err(), "Target snapshot too big"); + assert_eq!( + Staking::electable_targets(Some(1)).unwrap_err(), + "Target snapshot too big" + ); }); } @@ -4165,7 +4170,7 @@ mod election_data_provider { // we take 4 voters: 2 validators and 2 nominators (so nominators quota = 2) assert_eq!( - Staking::voters(Some(3)) + Staking::electing_voters(Some(3)) .unwrap() .iter() .map(|(stash, _, _)| stash) @@ -4204,7 +4209,7 @@ mod election_data_provider { // we take 5 voters assert_eq!( - Staking::voters(Some(5)) + Staking::electing_voters(Some(5)) .unwrap() .iter() .map(|(stash, _, _)| stash) @@ -4225,7 +4230,7 @@ mod election_data_provider { // we take 4 voters assert_eq!( - Staking::voters(Some(4)) + Staking::electing_voters(Some(4)) .unwrap() .iter() .map(|(stash, _, _)| stash) @@ -4666,7 +4671,7 @@ fn change_of_max_nominations() { vec![(70, 3), (101, 2), (60, 1)] ); // 3 validators and 3 nominators - assert_eq!(Staking::voters(None).unwrap().len(), 3 + 3); + assert_eq!(Staking::electing_voters(None).unwrap().len(), 3 + 3); // abrupt change from 16 to 4, everyone should be fine. MaxNominations::set(4); @@ -4677,7 +4682,7 @@ fn change_of_max_nominations() { .collect::>(), vec![(70, 3), (101, 2), (60, 1)] ); - assert_eq!(Staking::voters(None).unwrap().len(), 3 + 3); + assert_eq!(Staking::electing_voters(None).unwrap().len(), 3 + 3); // abrupt change from 4 to 3, everyone should be fine. MaxNominations::set(3); @@ -4688,7 +4693,7 @@ fn change_of_max_nominations() { .collect::>(), vec![(70, 3), (101, 2), (60, 1)] ); - assert_eq!(Staking::voters(None).unwrap().len(), 3 + 3); + assert_eq!(Staking::electing_voters(None).unwrap().len(), 3 + 3); // abrupt change from 3 to 2, this should cause some nominators to be non-decodable, and // thus non-existent unless if they update. @@ -4705,7 +4710,7 @@ fn change_of_max_nominations() { // but its value cannot be decoded and default is returned. assert!(Nominators::::get(70).is_none()); - assert_eq!(Staking::voters(None).unwrap().len(), 3 + 2); + assert_eq!(Staking::electing_voters(None).unwrap().len(), 3 + 2); assert!(Nominators::::contains_key(101)); // abrupt change from 2 to 1, this should cause some nominators to be non-decodable, and @@ -4722,7 +4727,7 @@ fn change_of_max_nominations() { assert!(Nominators::::contains_key(60)); assert!(Nominators::::get(70).is_none()); assert!(Nominators::::get(60).is_some()); - assert_eq!(Staking::voters(None).unwrap().len(), 3 + 1); + assert_eq!(Staking::electing_voters(None).unwrap().len(), 3 + 1); // now one of them can revive themselves by re-nominating to a proper value. assert_ok!(Staking::nominate(Origin::signed(71), vec![1])); From b64647c3a27f0461416c768822c670fe6f8564d9 Mon Sep 17 00:00:00 2001 From: Koute Date: Sun, 20 Mar 2022 04:11:02 +0900 Subject: [PATCH 615/695] Refactor WASM module instantiation (#10480) * Refactor WASM module instantiation; enable WASM instance pooling * Disable the `uffd` feature on `wasmtime` * Restore the original behavior regarding the initial WASM memory size * Adjust error message * Remove unnecessary import in the benchmarks * Preinstantiate the WASM runtime for a slight speedup * Delete the asserts in `convert_memory_import_into_export` * `return` -> `break` * Revert WASM instance pooling for now * Have `convert_memory_import_into_export` return an error instead of panic * Update the warning when an import is missing * Rustfmt and clippy fix * Fix executor benchmarks' compilation without `wasmtime` being enabled * rustfmt again * Align to review comments * Extend tests so that both imported and exported memories are tested * Increase the number of heap pages for exported memories too * Fix `decommit_works` test --- Cargo.lock | 2 + client/executor/Cargo.toml | 6 + client/executor/benches/bench.rs | 136 ++++++++++++ client/executor/benches/kusama_runtime.wasm | Bin 0 -> 5554150 bytes .../common/src/runtime_blob/runtime_blob.rs | 84 +++++++- client/executor/wasmtime/src/imports.rs | 162 +++----------- .../executor/wasmtime/src/instance_wrapper.rs | 91 ++++---- client/executor/wasmtime/src/runtime.rs | 106 ++++----- client/executor/wasmtime/src/tests.rs | 204 ++++++++++-------- 9 files changed, 468 insertions(+), 323 deletions(-) create mode 100644 client/executor/benches/bench.rs create mode 100755 client/executor/benches/kusama_runtime.wasm diff --git a/Cargo.lock b/Cargo.lock index 70a50a6f3e23..2760ee0570d4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8464,6 +8464,8 @@ dependencies = [ name = "sc-executor" version = "0.10.0-dev" dependencies = [ + "criterion", + "env_logger 0.9.0", "hex-literal", "lazy_static", "lru 0.6.6", diff --git a/client/executor/Cargo.toml b/client/executor/Cargo.toml index 96a9c0ba6e39..cba5892eace1 100644 --- a/client/executor/Cargo.toml +++ b/client/executor/Cargo.toml @@ -47,6 +47,12 @@ sc-tracing = { version = "4.0.0-dev", path = "../tracing" } tracing-subscriber = "0.2.19" paste = "1.0" regex = "1" +criterion = "0.3" +env_logger = "0.9" + +[[bench]] +name = "bench" +harness = false [features] default = ["std"] diff --git a/client/executor/benches/bench.rs b/client/executor/benches/bench.rs new file mode 100644 index 000000000000..20632536571b --- /dev/null +++ b/client/executor/benches/bench.rs @@ -0,0 +1,136 @@ +// This file is part of Substrate. + +// Copyright (C) 2021 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. + +use criterion::{criterion_group, criterion_main, Criterion}; + +use sc_executor_common::{runtime_blob::RuntimeBlob, wasm_runtime::WasmModule}; +use sc_runtime_test::wasm_binary_unwrap as test_runtime; +use sp_wasm_interface::HostFunctions as _; +use std::sync::Arc; + +enum Method { + Interpreted, + #[cfg(feature = "wasmtime")] + Compiled { + fast_instance_reuse: bool, + }, +} + +// This is just a bog-standard Kusama runtime with the extra `test_empty_return` +// function copy-pasted from the test runtime. +fn kusama_runtime() -> &'static [u8] { + include_bytes!("kusama_runtime.wasm") +} + +fn initialize(runtime: &[u8], method: Method) -> Arc { + let blob = RuntimeBlob::uncompress_if_needed(runtime).unwrap(); + let host_functions = sp_io::SubstrateHostFunctions::host_functions(); + let heap_pages = 2048; + let allow_missing_func_imports = true; + + match method { + Method::Interpreted => sc_executor_wasmi::create_runtime( + blob, + heap_pages, + host_functions, + allow_missing_func_imports, + ) + .map(|runtime| -> Arc { Arc::new(runtime) }), + #[cfg(feature = "wasmtime")] + Method::Compiled { fast_instance_reuse } => + sc_executor_wasmtime::create_runtime::( + blob, + sc_executor_wasmtime::Config { + heap_pages, + max_memory_size: None, + allow_missing_func_imports, + cache_path: None, + semantics: sc_executor_wasmtime::Semantics { + fast_instance_reuse, + deterministic_stack_limit: None, + canonicalize_nans: false, + parallel_compilation: true, + }, + }, + ) + .map(|runtime| -> Arc { Arc::new(runtime) }), + } + .unwrap() +} + +fn bench_call_instance(c: &mut Criterion) { + let _ = env_logger::try_init(); + + #[cfg(feature = "wasmtime")] + { + let runtime = initialize(test_runtime(), Method::Compiled { fast_instance_reuse: true }); + c.bench_function("call_instance_test_runtime_with_fast_instance_reuse", |b| { + let mut instance = runtime.new_instance().unwrap(); + b.iter(|| instance.call_export("test_empty_return", &[0]).unwrap()) + }); + } + + #[cfg(feature = "wasmtime")] + { + let runtime = initialize(test_runtime(), Method::Compiled { fast_instance_reuse: false }); + c.bench_function("call_instance_test_runtime_without_fast_instance_reuse", |b| { + let mut instance = runtime.new_instance().unwrap(); + b.iter(|| instance.call_export("test_empty_return", &[0]).unwrap()); + }); + } + + #[cfg(feature = "wasmtime")] + { + let runtime = initialize(kusama_runtime(), Method::Compiled { fast_instance_reuse: true }); + c.bench_function("call_instance_kusama_runtime_with_fast_instance_reuse", |b| { + let mut instance = runtime.new_instance().unwrap(); + b.iter(|| instance.call_export("test_empty_return", &[0]).unwrap()) + }); + } + + #[cfg(feature = "wasmtime")] + { + let runtime = initialize(kusama_runtime(), Method::Compiled { fast_instance_reuse: false }); + c.bench_function("call_instance_kusama_runtime_without_fast_instance_reuse", |b| { + let mut instance = runtime.new_instance().unwrap(); + b.iter(|| instance.call_export("test_empty_return", &[0]).unwrap()); + }); + } + + { + let runtime = initialize(test_runtime(), Method::Interpreted); + c.bench_function("call_instance_test_runtime_interpreted", |b| { + let mut instance = runtime.new_instance().unwrap(); + b.iter(|| instance.call_export("test_empty_return", &[0]).unwrap()) + }); + } + + { + let runtime = initialize(kusama_runtime(), Method::Interpreted); + c.bench_function("call_instance_kusama_runtime_interpreted", |b| { + let mut instance = runtime.new_instance().unwrap(); + b.iter(|| instance.call_export("test_empty_return", &[0]).unwrap()) + }); + } +} + +criterion_group! { + name = benches; + config = Criterion::default(); + targets = bench_call_instance +} +criterion_main!(benches); diff --git a/client/executor/benches/kusama_runtime.wasm b/client/executor/benches/kusama_runtime.wasm new file mode 100755 index 0000000000000000000000000000000000000000..3470237fb5aeea2fc21c9efc5a214b0754f3afd6 GIT binary patch literal 5554150 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 R@EV##%=Od9YW3M5K^Vb=n#@W3T{1r zPRvX|14gk-zBdr~i0T8%LRFEF`eaIopSe&o?@2zYGTqR5h2^5@o|)YmvlYG%15uHx zIs_{et{3VSNL7JE+qWnPrQX23ig_0b*_3WBU=hg>o&1sj#ZjMlLM% zHd%>dGz>9}$Dw0PMXlj%=@?dF?o2v{6htjWM0osJ(lH$Aqji~djJi)N=op8SJYW?{ z9pi9|aNHOj183A&9iyob2g8Y4!jvdHYOg_QpK_m+bCA^bqtg;h)iz{LmM3_06^W&2 zg=YUfZY{y-VvzWkVWP!!bw`nk$l2^p#l7J^x~MBeNnuan%N(aGFhrR}_AQgnDkNzA z+b;`z1}N9eq?ib)ECUf$a~Bt;lkAF!WElv;hi?T5qt2*WXw{co70}08#r{f*+i0Yw z$B!m8AYjFi9x$nzT4sWb=%=2CR?$y~6VO70pv*ce{t-@6v&6L5QAw96%KKcVugjz>kTmtJb|B@_OlYi-jl7B_sWNt@ph0nNt zFh)19;Qz38U{&_bCq+7f`J~npm2eL7KoFH@;2P}WX!UhAtK5~lUxfV?y;GPEKcr*o z$0aGp_3U^$3{asg6xCcqLYs=>a9!KYQ{=!F((HXZAi7>K&gGPxs8#J1Iu7kpcl01j zH_r1RPWL*Cw`>aWmf^ux97bc}DTZ=3`Q9TozBRPrsY(oXcc|BgIVU2q0PNYo-5(at zt_=Y%LGnyMF{%r^(4=&9z(=i0jtfcJ2JXuZ6uBqU6DHdGG(G_<`)7j~5>Wb_wc9e6 zLMpWn3987drJk-LG0fPnPt4gW2Lr6BL)P^c(S6iUhSy&5wJv$_Y)y|?PitVvy5(m2 zqPzA6%yGF)%$2l9fb=Ymst*@ZNYWDkN_xtKc~GIFep8pLcA4q&VY?Is!5OjY4bJyN z)Bo@pB0V9LF>4MBE1Oh&Oc5Y&-<$36=a2Jh=9fw`;v{;lqRJ`RTKdlrg}Mjl@-oRK zD~EUB@liCJDV)^byF5%~dkS!QgKYT8RE`P(lD%Lsp4{>|c^w`%Y4#P+3Z@q*U` zY-(F-@$?}IzyZe!|LUZ?DfyTzaU|5cH9Q;UXHQf>Xk^aB9u$*c4CAZ~uw`yX_%9u#nsJkjrXuX--<2E~j&G?A zM}_47u%lx5$WI>nVN)RiKj`jAQXU(^LSQqMHMT|TiRV5%sZGmh zY*#Oo`cVi0>W#8d%=7R>%0L0|Aq032@0N*c@*x&StyqtG&-ta!$r*@=Yg#u_*D?!t z=<-;G@U!d?rLKhv$-ESp;SuYM!BkS$GC8J6T~mTuQ<`(T*%U74lRGHokfs&yJ(ZNVPFc<}cW;!0`2;b|O z``4SC7Gr-owL90J+P?bK3R}xN(AAc*ec5(0Qj1qfSC+erpw|oK#&7PD=fZC&fdYMl z8`sT+@CrD!xctSV|Ge;01OzGIlP}ut(X?Cn)a;?<#`4OcZ~b&70ex>Kl~VTft(kJm zU;phleZP5=a>hv`w;hatN<_;x#P0;%mGm6m(VoT~1i$-Rg~-Ldw!5*+E?^GFHwD4O zG`8ehe_aK%etnOI#jooby9#RQpBHc6uAJ5RtkpF9Wshqy(feoroNTYvjkE&_; zkrSVJ_oohh>AjBvBtb!wKGhs-Co!1+ucz^mrochVh3U42 zS@NN@v6v-^Fw*8cYtt&m+v71i&b50xUrFQtkxM{k1sDW?HGGCTugf*;itrm-Y=T%Y zPp;)NXjtz=BNu^Jb{9|dPU{2GKXm6fo2NyzBzs0hrB@quyZv1|hJRaU)x;c~D zYbh%mowFy4j>_?|I$F7)|0Wc7DX+b=q P9{jwFF+}f_6XOoFuw^xPAWY{(;`VMk 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

::on_chain_storage_version(); diff --git a/frame/vesting/src/lib.rs b/frame/vesting/src/lib.rs index c823bccf38b1..dfd7fa094c96 100644 --- a/frame/vesting/src/lib.rs +++ b/frame/vesting/src/lib.rs @@ -45,13 +45,14 @@ #![cfg_attr(not(feature = "std"), no_std)] mod benchmarking; -mod migrations; + #[cfg(test)] mod mock; #[cfg(test)] mod tests; mod vesting_info; +pub mod migrations; pub mod weights; use codec::{Decode, Encode, MaxEncodedLen}; @@ -179,29 +180,6 @@ pub mod pallet { #[pallet::hooks] impl Hooks> for Pallet { - #[cfg(feature = "try-runtime")] - fn pre_upgrade() -> Result<(), &'static str> { - if StorageVersion::::get() == Releases::V0 { - migrations::v1::pre_migrate::() - } else { - Ok(()) - } - } - - fn on_runtime_upgrade() -> Weight { - if StorageVersion::::get() == Releases::V0 { - StorageVersion::::put(Releases::V1); - migrations::v1::migrate::().saturating_add(T::DbWeight::get().reads_writes(1, 1)) - } else { - T::DbWeight::get().reads(1) - } - } - - #[cfg(feature = "try-runtime")] - fn post_upgrade() -> Result<(), &'static str> { - migrations::v1::post_migrate::() - } - fn integrity_test() { assert!(T::MAX_VESTING_SCHEDULES > 0, "`MaxVestingSchedules` must ge greater than 0"); } diff --git a/frame/vesting/src/migrations.rs b/frame/vesting/src/migrations.rs index 688ebf6ad1c9..15668425b4b2 100644 --- a/frame/vesting/src/migrations.rs +++ b/frame/vesting/src/migrations.rs @@ -20,11 +20,11 @@ use super::*; // Migration from single schedule to multiple schedules. -pub(crate) mod v1 { +pub mod v1 { use super::*; #[cfg(feature = "try-runtime")] - pub(crate) fn pre_migrate() -> Result<(), &'static str> { + pub fn pre_migrate() -> Result<(), &'static str> { assert!(StorageVersion::::get() == Releases::V0, "Storage version too high."); log::debug!( @@ -37,7 +37,7 @@ pub(crate) mod v1 { /// Migrate from single schedule to multi schedule storage. /// WARNING: This migration will delete schedules if `MaxVestingSchedules < 1`. - pub(crate) fn migrate() -> Weight { + pub fn migrate() -> Weight { let mut reads_writes = 0; Vesting::::translate::, T::BlockNumber>, _>( @@ -65,7 +65,7 @@ pub(crate) mod v1 { } #[cfg(feature = "try-runtime")] - pub(crate) fn post_migrate() -> Result<(), &'static str> { + pub fn post_migrate() -> Result<(), &'static str> { assert_eq!(StorageVersion::::get(), Releases::V1); for (_key, schedules) in Vesting::::iter() { From 823c2533612e9bab7ac5e4f57a7c5daa762c00a5 Mon Sep 17 00:00:00 2001 From: Nazar Mokrynskyi Date: Thu, 20 Jan 2022 12:02:22 +0200 Subject: [PATCH 403/695] Relax types on `DigestItemRef`, such that byte slices can be used in addition to vector references (#10536) * Relax types on `DigestItemRef`, such that byte slices can be used in addition to vector references * Apply clippy suggestions --- Cargo.lock | 2 +- bin/node-template/node/Cargo.toml | 2 +- bin/node-template/pallets/template/Cargo.toml | 2 +- bin/node-template/runtime/Cargo.toml | 2 +- bin/node/bench/Cargo.toml | 2 +- bin/node/cli/Cargo.toml | 2 +- bin/node/executor/Cargo.toml | 2 +- bin/node/inspect/Cargo.toml | 2 +- bin/node/primitives/Cargo.toml | 2 +- bin/node/rpc/Cargo.toml | 2 +- bin/node/runtime/Cargo.toml | 2 +- bin/node/testing/Cargo.toml | 2 +- client/api/Cargo.toml | 2 +- client/authority-discovery/Cargo.toml | 2 +- client/basic-authorship/Cargo.toml | 2 +- client/beefy/Cargo.toml | 2 +- client/beefy/rpc/Cargo.toml | 2 +- client/block-builder/Cargo.toml | 2 +- client/chain-spec/Cargo.toml | 2 +- client/cli/Cargo.toml | 2 +- client/consensus/aura/Cargo.toml | 2 +- client/consensus/babe/Cargo.toml | 2 +- client/consensus/babe/rpc/Cargo.toml | 2 +- client/consensus/common/Cargo.toml | 2 +- client/consensus/epochs/Cargo.toml | 2 +- client/consensus/manual-seal/Cargo.toml | 2 +- client/consensus/pow/Cargo.toml | 2 +- client/consensus/slots/Cargo.toml | 2 +- client/consensus/uncles/Cargo.toml | 2 +- client/db/Cargo.toml | 2 +- client/executor/Cargo.toml | 2 +- client/executor/runtime-test/Cargo.toml | 2 +- client/finality-grandpa/Cargo.toml | 2 +- client/finality-grandpa/rpc/Cargo.toml | 2 +- client/informant/Cargo.toml | 2 +- client/network-gossip/Cargo.toml | 2 +- client/network/Cargo.toml | 2 +- client/network/test/Cargo.toml | 2 +- client/offchain/Cargo.toml | 2 +- client/rpc-api/Cargo.toml | 2 +- client/rpc/Cargo.toml | 2 +- client/service/Cargo.toml | 2 +- client/service/test/Cargo.toml | 2 +- client/sync-state-rpc/Cargo.toml | 2 +- client/tracing/Cargo.toml | 2 +- client/transaction-pool/Cargo.toml | 2 +- client/transaction-pool/api/Cargo.toml | 2 +- frame/assets/Cargo.toml | 2 +- frame/atomic-swap/Cargo.toml | 2 +- frame/aura/Cargo.toml | 2 +- frame/authority-discovery/Cargo.toml | 2 +- frame/authorship/Cargo.toml | 2 +- frame/babe/Cargo.toml | 2 +- frame/bags-list/Cargo.toml | 2 +- frame/bags-list/remote-tests/Cargo.toml | 2 +- frame/balances/Cargo.toml | 2 +- frame/beefy-mmr/Cargo.toml | 2 +- frame/beefy/Cargo.toml | 2 +- frame/benchmarking/Cargo.toml | 2 +- frame/bounties/Cargo.toml | 2 +- frame/child-bounties/Cargo.toml | 2 +- frame/collective/Cargo.toml | 2 +- frame/contracts/Cargo.toml | 2 +- frame/contracts/common/Cargo.toml | 2 +- frame/contracts/rpc/Cargo.toml | 2 +- frame/contracts/rpc/runtime-api/Cargo.toml | 2 +- frame/democracy/Cargo.toml | 2 +- frame/election-provider-multi-phase/Cargo.toml | 2 +- frame/election-provider-support/Cargo.toml | 2 +- frame/elections-phragmen/Cargo.toml | 2 +- frame/examples/basic/Cargo.toml | 2 +- frame/examples/offchain-worker/Cargo.toml | 2 +- frame/examples/parallel/Cargo.toml | 2 +- frame/executive/Cargo.toml | 2 +- frame/gilt/Cargo.toml | 2 +- frame/grandpa/Cargo.toml | 2 +- frame/identity/Cargo.toml | 2 +- frame/im-online/Cargo.toml | 2 +- frame/indices/Cargo.toml | 2 +- frame/lottery/Cargo.toml | 2 +- frame/membership/Cargo.toml | 2 +- frame/merkle-mountain-range/Cargo.toml | 2 +- frame/merkle-mountain-range/primitives/Cargo.toml | 2 +- frame/merkle-mountain-range/rpc/Cargo.toml | 2 +- frame/multisig/Cargo.toml | 2 +- frame/nicks/Cargo.toml | 2 +- frame/node-authorization/Cargo.toml | 2 +- frame/offences/Cargo.toml | 2 +- frame/offences/benchmarking/Cargo.toml | 2 +- frame/preimage/Cargo.toml | 2 +- frame/proxy/Cargo.toml | 2 +- frame/randomness-collective-flip/Cargo.toml | 2 +- frame/recovery/Cargo.toml | 2 +- frame/scheduler/Cargo.toml | 2 +- frame/scored-pool/Cargo.toml | 2 +- frame/session/Cargo.toml | 2 +- frame/session/benchmarking/Cargo.toml | 2 +- frame/society/Cargo.toml | 2 +- frame/staking/Cargo.toml | 2 +- frame/staking/reward-curve/Cargo.toml | 2 +- frame/sudo/Cargo.toml | 2 +- frame/support/Cargo.toml | 2 +- frame/support/test/Cargo.toml | 2 +- frame/support/test/compile_pass/Cargo.toml | 2 +- frame/system/Cargo.toml | 2 +- frame/system/benchmarking/Cargo.toml | 2 +- frame/timestamp/Cargo.toml | 2 +- frame/tips/Cargo.toml | 2 +- frame/transaction-payment/Cargo.toml | 2 +- .../transaction-payment/asset-tx-payment/Cargo.toml | 2 +- frame/transaction-payment/rpc/Cargo.toml | 2 +- frame/transaction-payment/rpc/runtime-api/Cargo.toml | 2 +- frame/transaction-storage/Cargo.toml | 2 +- frame/treasury/Cargo.toml | 2 +- frame/try-runtime/Cargo.toml | 2 +- frame/uniques/Cargo.toml | 2 +- frame/utility/Cargo.toml | 2 +- frame/vesting/Cargo.toml | 2 +- primitives/api/Cargo.toml | 2 +- primitives/api/test/Cargo.toml | 2 +- primitives/application-crypto/test/Cargo.toml | 2 +- primitives/authority-discovery/Cargo.toml | 2 +- primitives/authorship/Cargo.toml | 2 +- primitives/beefy/Cargo.toml | 2 +- primitives/block-builder/Cargo.toml | 2 +- primitives/blockchain/Cargo.toml | 2 +- primitives/consensus/aura/Cargo.toml | 2 +- primitives/consensus/babe/Cargo.toml | 2 +- primitives/consensus/common/Cargo.toml | 2 +- primitives/consensus/pow/Cargo.toml | 2 +- primitives/consensus/slots/Cargo.toml | 2 +- primitives/consensus/vrf/Cargo.toml | 2 +- primitives/finality-grandpa/Cargo.toml | 2 +- primitives/inherents/Cargo.toml | 2 +- primitives/keyring/Cargo.toml | 2 +- primitives/npos-elections/Cargo.toml | 2 +- primitives/npos-elections/fuzzer/Cargo.toml | 2 +- primitives/offchain/Cargo.toml | 2 +- primitives/runtime-interface/test/Cargo.toml | 2 +- primitives/runtime/Cargo.toml | 2 +- primitives/runtime/src/generic/digest.rs | 12 ++++++------ primitives/session/Cargo.toml | 2 +- primitives/staking/Cargo.toml | 2 +- primitives/state-machine/Cargo.toml | 2 +- primitives/test-primitives/Cargo.toml | 2 +- primitives/timestamp/Cargo.toml | 2 +- primitives/transaction-pool/Cargo.toml | 2 +- primitives/transaction-storage-proof/Cargo.toml | 2 +- primitives/trie/Cargo.toml | 2 +- primitives/version/Cargo.toml | 2 +- test-utils/client/Cargo.toml | 2 +- test-utils/runtime/Cargo.toml | 2 +- test-utils/runtime/client/Cargo.toml | 2 +- test-utils/runtime/transaction-pool/Cargo.toml | 2 +- utils/frame/benchmarking-cli/Cargo.toml | 2 +- utils/frame/frame-utilities-cli/Cargo.toml | 2 +- utils/frame/remote-externalities/Cargo.toml | 2 +- utils/frame/rpc/system/Cargo.toml | 2 +- utils/frame/try-runtime/cli/Cargo.toml | 2 +- 159 files changed, 164 insertions(+), 164 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1a43c9ded813..580da5ad074c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9678,7 +9678,7 @@ dependencies = [ [[package]] name = "sp-runtime" -version = "4.0.0" +version = "4.1.0-dev" dependencies = [ "either", "hash256-std-hasher", diff --git a/bin/node-template/node/Cargo.toml b/bin/node-template/node/Cargo.toml index dbf44a75c139..2b280e1bf00d 100644 --- a/bin/node-template/node/Cargo.toml +++ b/bin/node-template/node/Cargo.toml @@ -34,7 +34,7 @@ sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/commo sc-finality-grandpa = { version = "0.10.0-dev", path = "../../../client/finality-grandpa" } sp-finality-grandpa = { version = "4.0.0-dev", path = "../../../primitives/finality-grandpa" } sc-client-api = { version = "4.0.0-dev", path = "../../../client/api" } -sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } sp-timestamp = { version = "4.0.0-dev", path = "../../../primitives/timestamp" } # These dependencies are used for the node template's RPCs diff --git a/bin/node-template/pallets/template/Cargo.toml b/bin/node-template/pallets/template/Cargo.toml index ab69a3fe73ea..9702501a3e0e 100644 --- a/bin/node-template/pallets/template/Cargo.toml +++ b/bin/node-template/pallets/template/Cargo.toml @@ -24,7 +24,7 @@ frame-benchmarking = { default-features = false, version = "4.0.0-dev", path = " [dev-dependencies] sp-core = { default-features = false, version = "4.1.0-dev", path = "../../../../primitives/core" } sp-io = { default-features = false, version = "4.0.0-dev", path = "../../../../primitives/io" } -sp-runtime = { default-features = false, version = "4.0.0", path = "../../../../primitives/runtime" } +sp-runtime = { default-features = false, version = "4.1.0-dev", path = "../../../../primitives/runtime" } [features] default = ["std"] diff --git a/bin/node-template/runtime/Cargo.toml b/bin/node-template/runtime/Cargo.toml index c56162c8ffed..b757029f2581 100644 --- a/bin/node-template/runtime/Cargo.toml +++ b/bin/node-template/runtime/Cargo.toml @@ -32,7 +32,7 @@ sp-consensus-aura = { version = "0.10.0-dev", default-features = false, path = " sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } sp-inherents = { path = "../../../primitives/inherents", default-features = false, version = "4.0.0-dev"} sp-offchain = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/offchain" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/runtime" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/session" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } sp-transaction-pool = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/transaction-pool" } diff --git a/bin/node/bench/Cargo.toml b/bin/node/bench/Cargo.toml index 90951d75cfd2..670f6c4d3ed8 100644 --- a/bin/node/bench/Cargo.toml +++ b/bin/node/bench/Cargo.toml @@ -14,7 +14,7 @@ node-primitives = { version = "2.0.0", path = "../primitives" } node-testing = { version = "3.0.0-dev", path = "../testing" } node-runtime = { version = "3.0.0-dev", path = "../runtime" } sc-client-api = { version = "4.0.0-dev", path = "../../../client/api/" } -sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } sp-state-machine = { version = "0.10.0", path = "../../../primitives/state-machine" } serde = "1.0.132" serde_json = "1.0.74" diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index 58b4d9806846..248181ac5c8b 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -48,7 +48,7 @@ sp-consensus-babe = { version = "0.10.0-dev", path = "../../../primitives/consen grandpa-primitives = { version = "4.0.0-dev", package = "sp-finality-grandpa", path = "../../../primitives/finality-grandpa" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } -sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } sp-timestamp = { version = "4.0.0-dev", path = "../../../primitives/timestamp" } sp-authorship = { version = "4.0.0-dev", path = "../../../primitives/authorship" } sp-inherents = { version = "4.0.0-dev", path = "../../../primitives/inherents" } diff --git a/bin/node/executor/Cargo.toml b/bin/node/executor/Cargo.toml index 9796ef6c0ad7..e23152e00e5e 100644 --- a/bin/node/executor/Cargo.toml +++ b/bin/node/executor/Cargo.toml @@ -36,7 +36,7 @@ pallet-timestamp = { version = "4.0.0-dev", path = "../../../frame/timestamp" } pallet-treasury = { version = "4.0.0-dev", path = "../../../frame/treasury" } sp-application-crypto = { version = "4.0.0", path = "../../../primitives/application-crypto" } sp-consensus-babe = { version = "0.10.0-dev", path = "../../../primitives/consensus/babe" } -sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } sp-externalities = { version = "0.10.0", path = "../../../primitives/externalities" } sp-keyring = { version = "4.1.0-dev", path = "../../../primitives/keyring" } wat = "1.0" diff --git a/bin/node/inspect/Cargo.toml b/bin/node/inspect/Cargo.toml index cb9557b506a1..d72c6f43d005 100644 --- a/bin/node/inspect/Cargo.toml +++ b/bin/node/inspect/Cargo.toml @@ -19,5 +19,5 @@ sc-executor = { version = "0.10.0-dev", path = "../../../client/executor" } sc-service = { version = "0.10.0-dev", default-features = false, path = "../../../client/service" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } -sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } structopt = "0.3.8" diff --git a/bin/node/primitives/Cargo.toml b/bin/node/primitives/Cargo.toml index 05def58be234..e00f46720c94 100644 --- a/bin/node/primitives/Cargo.toml +++ b/bin/node/primitives/Cargo.toml @@ -18,7 +18,7 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] frame-system = { version = "4.0.0-dev", default-features = false, path = "../../../frame/system" } sp-application-crypto = { version = "4.0.0", default-features = false, path = "../../../primitives/application-crypto" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/runtime" } [features] default = ["std"] diff --git a/bin/node/rpc/Cargo.toml b/bin/node/rpc/Cargo.toml index 3eed3ad4e0cc..36d313ebc30a 100644 --- a/bin/node/rpc/Cargo.toml +++ b/bin/node/rpc/Cargo.toml @@ -32,6 +32,6 @@ sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" sp-keystore = { version = "0.10.0", path = "../../../primitives/keystore" } sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" } sp-consensus-babe = { version = "0.10.0-dev", path = "../../../primitives/consensus/babe" } -sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../../../client/transaction-pool/api" } substrate-frame-rpc-system = { version = "4.0.0-dev", path = "../../../utils/frame/rpc/system" } diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 1cffabe09ae6..ef1b73aed854 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -33,7 +33,7 @@ sp-offchain = { version = "4.0.0-dev", default-features = false, path = "../../. sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/api" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/runtime" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/staking" } sp-keyring = { version = "4.1.0-dev", optional = true, path = "../../../primitives/keyring" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/session" } diff --git a/bin/node/testing/Cargo.toml b/bin/node/testing/Cargo.toml index d0348b3096bb..29efc0028c15 100644 --- a/bin/node/testing/Cargo.toml +++ b/bin/node/testing/Cargo.toml @@ -30,7 +30,7 @@ node-primitives = { version = "2.0.0", path = "../primitives" } node-runtime = { version = "3.0.0-dev", path = "../runtime" } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sp-io = { version = "4.0.0-dev", path = "../../../primitives/io" } -sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } sc-executor = { version = "0.10.0-dev", path = "../../../client/executor", features = [ "wasmtime", ] } diff --git a/client/api/Cargo.toml b/client/api/Cargo.toml index f1d3969ec27a..c18b920cace8 100644 --- a/client/api/Cargo.toml +++ b/client/api/Cargo.toml @@ -31,7 +31,7 @@ sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primi sp-keystore = { version = "0.10.0", default-features = false, path = "../../primitives/keystore" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } sc-utils = { version = "4.0.0-dev", path = "../utils" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } sp-state-machine = { version = "0.10.0", path = "../../primitives/state-machine" } sp-trie = { version = "4.0.0", path = "../../primitives/trie" } sp-storage = { version = "4.0.0", path = "../../primitives/storage" } diff --git a/client/authority-discovery/Cargo.toml b/client/authority-discovery/Cargo.toml index ac9f0cdb1828..c6c523fa5eec 100644 --- a/client/authority-discovery/Cargo.toml +++ b/client/authority-discovery/Cargo.toml @@ -34,7 +34,7 @@ sp-authority-discovery = { version = "4.0.0-dev", path = "../../primitives/autho sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-keystore = { version = "0.10.0", path = "../../primitives/keystore" } -sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } [dev-dependencies] diff --git a/client/basic-authorship/Cargo.toml b/client/basic-authorship/Cargo.toml index 26a2defbbb4d..e1083b15a970 100644 --- a/client/basic-authorship/Cargo.toml +++ b/client/basic-authorship/Cargo.toml @@ -19,7 +19,7 @@ futures-timer = "3.0.1" log = "0.4.8" prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.10.0-dev"} sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } -sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sc-client-api = { version = "4.0.0-dev", path = "../api" } diff --git a/client/beefy/Cargo.toml b/client/beefy/Cargo.toml index d57d053c16f4..9761f18d7845 100644 --- a/client/beefy/Cargo.toml +++ b/client/beefy/Cargo.toml @@ -24,7 +24,7 @@ sp-arithmetic = { version = "4.0.0", path = "../../primitives/arithmetic" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-keystore = { version = "0.10.0", path = "../../primitives/keystore" } -sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } sc-chain-spec = { version = "4.0.0-dev", path = "../../client/chain-spec" } sc-utils = { version = "4.0.0-dev", path = "../utils" } diff --git a/client/beefy/rpc/Cargo.toml b/client/beefy/rpc/Cargo.toml index 0f29804d6780..a72af62fdeea 100644 --- a/client/beefy/rpc/Cargo.toml +++ b/client/beefy/rpc/Cargo.toml @@ -26,7 +26,7 @@ sc-rpc = { version = "4.0.0-dev", path = "../../rpc" } sc-utils = { version = "4.0.0-dev", path = "../../utils" } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } -sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } beefy-gadget = { version = "4.0.0-dev", path = "../." } beefy-primitives = { version = "4.0.0-dev", path = "../../../primitives/beefy" } diff --git a/client/block-builder/Cargo.toml b/client/block-builder/Cargo.toml index ab77bc005f6c..19b8839c1228 100644 --- a/client/block-builder/Cargo.toml +++ b/client/block-builder/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-state-machine = { version = "0.10.0", path = "../../primitives/state-machine" } -sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } diff --git a/client/chain-spec/Cargo.toml b/client/chain-spec/Cargo.toml index 769f502dd5ed..0110e82532a5 100644 --- a/client/chain-spec/Cargo.toml +++ b/client/chain-spec/Cargo.toml @@ -19,7 +19,7 @@ sc-network = { version = "0.10.0-dev", path = "../network" } sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } serde = { version = "1.0.132", features = ["derive"] } serde_json = "1.0.74" -sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } sc-telemetry = { version = "4.0.0-dev", path = "../telemetry" } codec = { package = "parity-scale-codec", version = "2.0.0" } memmap2 = "0.5.0" diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index 5b7825182b38..01f5aab25d5f 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -29,7 +29,7 @@ sp-panic-handler = { version = "4.0.0", path = "../../primitives/panic-handler" sc-client-api = { version = "4.0.0-dev", path = "../api" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sc-network = { version = "0.10.0-dev", path = "../network" } -sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } sc-utils = { version = "4.0.0-dev", path = "../utils" } sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } diff --git a/client/consensus/aura/Cargo.toml b/client/consensus/aura/Cargo.toml index 534aa28920ae..97409c5944db 100644 --- a/client/consensus/aura/Cargo.toml +++ b/client/consensus/aura/Cargo.toml @@ -30,7 +30,7 @@ sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sc-consensus-slots = { version = "0.10.0-dev", path = "../slots" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } -sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } sp-keystore = { version = "0.10.0", path = "../../../primitives/keystore" } sc-telemetry = { version = "4.0.0-dev", path = "../../telemetry" } prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.10.0-dev" } diff --git a/client/consensus/babe/Cargo.toml b/client/consensus/babe/Cargo.toml index 8d0ceb2b615b..e4d66fcad87c 100644 --- a/client/consensus/babe/Cargo.toml +++ b/client/consensus/babe/Cargo.toml @@ -40,7 +40,7 @@ sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/c sp-consensus-slots = { version = "0.10.0-dev", path = "../../../primitives/consensus/slots" } sp-consensus-vrf = { version = "0.10.0-dev", path = "../../../primitives/consensus/vrf" } sc-consensus-slots = { version = "0.10.0-dev", path = "../slots" } -sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } fork-tree = { version = "3.0.0", path = "../../../utils/fork-tree" } prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.10.0-dev" } futures = "0.3.9" diff --git a/client/consensus/babe/rpc/Cargo.toml b/client/consensus/babe/rpc/Cargo.toml index 0806f72e688e..93be56b9d360 100644 --- a/client/consensus/babe/rpc/Cargo.toml +++ b/client/consensus/babe/rpc/Cargo.toml @@ -21,7 +21,7 @@ jsonrpc-derive = "18.0.0" sp-consensus-babe = { version = "0.10.0-dev", path = "../../../../primitives/consensus/babe" } serde = { version = "1.0.132", features=["derive"] } sp-blockchain = { version = "4.0.0-dev", path = "../../../../primitives/blockchain" } -sp-runtime = { version = "4.0.0", path = "../../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../../../primitives/runtime" } sc-consensus-epochs = { version = "0.10.0-dev", path = "../../epochs" } futures = "0.3.16" derive_more = "0.99.16" diff --git a/client/consensus/common/Cargo.toml b/client/consensus/common/Cargo.toml index 0ca0c5675839..72a0544535ad 100644 --- a/client/consensus/common/Cargo.toml +++ b/client/consensus/common/Cargo.toml @@ -23,7 +23,7 @@ sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" sp-core = { path = "../../../primitives/core", version = "4.1.0-dev" } sp-consensus = { path = "../../../primitives/consensus/common", version = "0.10.0-dev" } sp-state-machine = { version = "0.10.0", path = "../../../primitives/state-machine" } -sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } sc-utils = { version = "4.0.0-dev", path = "../../utils" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } parking_lot = "0.11.2" diff --git a/client/consensus/epochs/Cargo.toml b/client/consensus/epochs/Cargo.toml index efd11b8d401d..bb4a77b559e0 100644 --- a/client/consensus/epochs/Cargo.toml +++ b/client/consensus/epochs/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", features = ["derive"] } fork-tree = { version = "3.0.0", path = "../../../utils/fork-tree" } -sp-runtime = { path = "../../../primitives/runtime" , version = "4.0.0"} +sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sc-client-api = { path = "../../api" , version = "4.0.0-dev"} sc-consensus = { path = "../common" , version = "0.10.0-dev"} diff --git a/client/consensus/manual-seal/Cargo.toml b/client/consensus/manual-seal/Cargo.toml index c55228abb527..89f3335899f1 100644 --- a/client/consensus/manual-seal/Cargo.toml +++ b/client/consensus/manual-seal/Cargo.toml @@ -37,7 +37,7 @@ sp-blockchain = { path = "../../../primitives/blockchain", version = "4.0.0-dev" sp-consensus = { path = "../../../primitives/consensus/common", version = "0.10.0-dev" } sp-consensus-slots = { path = "../../../primitives/consensus/slots", version = "0.10.0-dev" } sp-inherents = { path = "../../../primitives/inherents", version = "4.0.0-dev" } -sp-runtime = { path = "../../../primitives/runtime", version = "4.0.0" } +sp-runtime = { path = "../../../primitives/runtime", version = "4.1.0-dev" } sp-core = { path = "../../../primitives/core", version = "4.1.0-dev" } sp-keystore = { path = "../../../primitives/keystore", version = "0.10.0" } sp-api = { path = "../../../primitives/api", version = "4.0.0-dev" } diff --git a/client/consensus/pow/Cargo.toml b/client/consensus/pow/Cargo.toml index 19cc5135de03..db9e4e164e4e 100644 --- a/client/consensus/pow/Cargo.toml +++ b/client/consensus/pow/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0", features = ["derive"] } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sc-client-api = { version = "4.0.0-dev", path = "../../api" } sp-block-builder = { version = "4.0.0-dev", path = "../../../primitives/block-builder" } diff --git a/client/consensus/slots/Cargo.toml b/client/consensus/slots/Cargo.toml index 782e979ed6ef..60f57449a3a3 100644 --- a/client/consensus/slots/Cargo.toml +++ b/client/consensus/slots/Cargo.toml @@ -21,7 +21,7 @@ sp-arithmetic = { version = "4.0.0", path = "../../../primitives/arithmetic" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/common" } sp-consensus-slots = { version = "0.10.0-dev", path = "../../../primitives/consensus/slots" } -sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } sp-state-machine = { version = "0.10.0", path = "../../../primitives/state-machine" } sc-telemetry = { version = "4.0.0-dev", path = "../../telemetry" } sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" } diff --git a/client/consensus/uncles/Cargo.toml b/client/consensus/uncles/Cargo.toml index 346d3e34c01b..b9eaae4773a6 100644 --- a/client/consensus/uncles/Cargo.toml +++ b/client/consensus/uncles/Cargo.toml @@ -14,6 +14,6 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sc-client-api = { version = "4.0.0-dev", path = "../../api" } -sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } sp-authorship = { version = "4.0.0-dev", path = "../../../primitives/authorship" } thiserror = "1.0.30" diff --git a/client/db/Cargo.toml b/client/db/Cargo.toml index 5acc7e9df8b8..0db0f8309e2e 100644 --- a/client/db/Cargo.toml +++ b/client/db/Cargo.toml @@ -27,7 +27,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", features = [ sc-client-api = { version = "4.0.0-dev", path = "../api" } sp-arithmetic = { version = "4.0.0", path = "../../primitives/arithmetic" } sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } -sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } sp-state-machine = { version = "0.10.0", path = "../../primitives/state-machine" } sc-state-db = { version = "0.10.0-dev", path = "../state-db" } sp-trie = { version = "4.0.0", path = "../../primitives/trie" } diff --git a/client/executor/Cargo.toml b/client/executor/Cargo.toml index 09f10a975340..e10cbf347db5 100644 --- a/client/executor/Cargo.toml +++ b/client/executor/Cargo.toml @@ -42,7 +42,7 @@ hex-literal = "0.3.4" sc-runtime-test = { version = "2.0.0", path = "runtime-test" } substrate-test-runtime = { version = "2.0.0", path = "../../test-utils/runtime" } sp-state-machine = { version = "0.10.0", path = "../../primitives/state-machine" } -sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } sp-maybe-compressed-blob = { version = "4.1.0-dev", path = "../../primitives/maybe-compressed-blob" } sc-tracing = { version = "4.0.0-dev", path = "../tracing" } tracing = "0.1.29" diff --git a/client/executor/runtime-test/Cargo.toml b/client/executor/runtime-test/Cargo.toml index 8fbaf2102aeb..1318c7246a84 100644 --- a/client/executor/runtime-test/Cargo.toml +++ b/client/executor/runtime-test/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/io" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/runtime" } sp-sandbox = { version = "0.10.0-dev", default-features = false, path = "../../../primitives/sandbox" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } sp-tasks = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/tasks" } diff --git a/client/finality-grandpa/Cargo.toml b/client/finality-grandpa/Cargo.toml index 83ebe617973b..3f9261c0c17a 100644 --- a/client/finality-grandpa/Cargo.toml +++ b/client/finality-grandpa/Cargo.toml @@ -26,7 +26,7 @@ rand = "0.8.4" parity-scale-codec = { version = "2.3.1", features = ["derive"] } sp-application-crypto = { version = "4.0.0", path = "../../primitives/application-crypto" } sp-arithmetic = { version = "4.0.0", path = "../../primitives/arithmetic" } -sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } sc-chain-spec = { version = "4.0.0-dev", path = "../../client/chain-spec" } sc-utils = { version = "4.0.0-dev", path = "../utils" } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } diff --git a/client/finality-grandpa/rpc/Cargo.toml b/client/finality-grandpa/rpc/Cargo.toml index 2fe7d3683159..be6dfc371e4a 100644 --- a/client/finality-grandpa/rpc/Cargo.toml +++ b/client/finality-grandpa/rpc/Cargo.toml @@ -13,7 +13,7 @@ sc-finality-grandpa = { version = "0.10.0-dev", path = "../" } sc-rpc = { version = "4.0.0-dev", path = "../../rpc" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } -sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } finality-grandpa = { version = "0.14.4", features = ["derive-codec"] } jsonrpc-core = "18.0.0" jsonrpc-core-client = "18.0.0" diff --git a/client/informant/Cargo.toml b/client/informant/Cargo.toml index d6e9c655aad9..ce7fe31648a1 100644 --- a/client/informant/Cargo.toml +++ b/client/informant/Cargo.toml @@ -21,5 +21,5 @@ parity-util-mem = { version = "0.10.2", default-features = false, features = ["p sc-client-api = { version = "4.0.0-dev", path = "../api" } sc-network = { version = "0.10.0-dev", path = "../network" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } -sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../transaction-pool/api" } diff --git a/client/network-gossip/Cargo.toml b/client/network-gossip/Cargo.toml index c90d1db44afc..9523e32f99e0 100644 --- a/client/network-gossip/Cargo.toml +++ b/client/network-gossip/Cargo.toml @@ -22,7 +22,7 @@ log = "0.4.8" lru = "0.7.0" prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.10.0-dev", path = "../../utils/prometheus" } sc-network = { version = "0.10.0-dev", path = "../network" } -sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } tracing = "0.1.29" [dev-dependencies] diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index 2df700fae8a3..f378b75990cb 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -54,7 +54,7 @@ sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } sc-consensus = { version = "0.10.0-dev", path = "../consensus/common" } sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } -sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } sc-utils = { version = "4.0.0-dev", path = "../utils" } sp-finality-grandpa = { version = "4.0.0-dev", path = "../../primitives/finality-grandpa" } thiserror = "1" diff --git a/client/network/test/Cargo.toml b/client/network/test/Cargo.toml index e2e46a27b273..6b6d777e7396 100644 --- a/client/network/test/Cargo.toml +++ b/client/network/test/Cargo.toml @@ -25,7 +25,7 @@ sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/c sc-consensus = { version = "0.10.0-dev", path = "../../consensus/common" } sc-client-api = { version = "4.0.0-dev", path = "../../api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sc-block-builder = { version = "0.10.0-dev", path = "../../block-builder" } sp-consensus-babe = { version = "0.10.0-dev", path = "../../../primitives/consensus/babe" } diff --git a/client/offchain/Cargo.toml b/client/offchain/Cargo.toml index 4ca1b242a48e..dd4bdb71f93b 100644 --- a/client/offchain/Cargo.toml +++ b/client/offchain/Cargo.toml @@ -27,7 +27,7 @@ sc-network = { version = "0.10.0-dev", path = "../network" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-offchain = { version = "4.0.0-dev", path = "../../primitives/offchain" } -sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } sc-utils = { version = "4.0.0-dev", path = "../utils" } threadpool = "1.7" hyper = { version = "0.14.16", features = ["stream", "http2"] } diff --git a/client/rpc-api/Cargo.toml b/client/rpc-api/Cargo.toml index aa560bc2e1c1..4b2882ee827f 100644 --- a/client/rpc-api/Cargo.toml +++ b/client/rpc-api/Cargo.toml @@ -25,7 +25,7 @@ thiserror = "1.0" sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } -sp-runtime = { path = "../../primitives/runtime", version = "4.0.0" } +sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } sc-chain-spec = { path = "../chain-spec", version = "4.0.0-dev" } serde = { version = "1.0.132", features = ["derive"] } serde_json = "1.0.74" diff --git a/client/rpc/Cargo.toml b/client/rpc/Cargo.toml index 3a2af0bb211e..87fc263356a7 100644 --- a/client/rpc/Cargo.toml +++ b/client/rpc/Cargo.toml @@ -26,7 +26,7 @@ sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } serde_json = "1.0.74" sp-session = { version = "4.0.0-dev", path = "../../primitives/session" } sp-offchain = { version = "4.0.0-dev", path = "../../primitives/offchain" } -sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } sc-utils = { version = "4.0.0-dev", path = "../utils" } sp-rpc = { version = "4.0.0-dev", path = "../../primitives/rpc" } sp-keystore = { version = "0.10.0", path = "../../primitives/keystore" } diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index e9b05c0d28aa..f23bf3f55bbf 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -36,7 +36,7 @@ hash-db = "0.15.2" serde = "1.0.132" serde_json = "1.0.74" sc-keystore = { version = "4.0.0-dev", path = "../keystore" } -sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } sp-trie = { version = "4.0.0", path = "../../primitives/trie" } sp-externalities = { version = "0.10.0", path = "../../primitives/externalities" } sc-utils = { version = "4.0.0-dev", path = "../utils" } diff --git a/client/service/test/Cargo.toml b/client/service/test/Cargo.toml index 5073f46eb0ef..84b1d44e7bde 100644 --- a/client/service/test/Cargo.toml +++ b/client/service/test/Cargo.toml @@ -31,7 +31,7 @@ sc-service = { version = "0.10.0-dev", features = ["test-helpers"], path = "../. sc-network = { version = "0.10.0-dev", path = "../../network" } sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" } sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/common" } -sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../../../client/transaction-pool/api" } substrate-test-runtime = { version = "2.0.0", path = "../../../test-utils/runtime" } diff --git a/client/sync-state-rpc/Cargo.toml b/client/sync-state-rpc/Cargo.toml index e5ac6550d213..0aae985319d4 100644 --- a/client/sync-state-rpc/Cargo.toml +++ b/client/sync-state-rpc/Cargo.toml @@ -26,5 +26,5 @@ sc-rpc-api = { version = "0.10.0-dev", path = "../rpc-api" } serde_json = "1.0.74" serde = { version = "1.0.132", features = ["derive"] } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } -sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } codec = { package = "parity-scale-codec", version = "2.0.0" } diff --git a/client/tracing/Cargo.toml b/client/tracing/Cargo.toml index 7ea0d80ba1f2..62c7f7a4becc 100644 --- a/client/tracing/Cargo.toml +++ b/client/tracing/Cargo.toml @@ -30,7 +30,7 @@ tracing-log = "0.1.2" tracing-subscriber = { version = "0.2.25", features = ["parking_lot"] } sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } sp-rpc = { version = "4.0.0-dev", path = "../../primitives/rpc" } -sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } diff --git a/client/transaction-pool/Cargo.toml b/client/transaction-pool/Cargo.toml index a98dfac620c1..73ec7cfff7f3 100644 --- a/client/transaction-pool/Cargo.toml +++ b/client/transaction-pool/Cargo.toml @@ -24,7 +24,7 @@ prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../.. sc-client-api = { version = "4.0.0-dev", path = "../api" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } -sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } sp-tracing = { version = "4.0.0", path = "../../primitives/tracing" } sp-transaction-pool = { version = "4.0.0-dev", path = "../../primitives/transaction-pool" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "./api" } diff --git a/client/transaction-pool/api/Cargo.toml b/client/transaction-pool/api/Cargo.toml index e79aa4c7f804..95b82e26fc5d 100644 --- a/client/transaction-pool/api/Cargo.toml +++ b/client/transaction-pool/api/Cargo.toml @@ -13,7 +13,7 @@ futures = { version = "0.3.1" } log = { version = "0.4.8" } serde = { version = "1.0.132", features = ["derive"] } thiserror = { version = "1.0.30" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/runtime" } derive_more = { version = "0.99.16" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } diff --git a/frame/assets/Cargo.toml b/frame/assets/Cargo.toml index c36200fb1ac4..c250a75d4c2f 100644 --- a/frame/assets/Cargo.toml +++ b/frame/assets/Cargo.toml @@ -17,7 +17,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } # Needed for various traits. In our case, `OnFinalize`. -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } # Needed for type-safe access to storage DB. frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } # `system` module provides us with all sorts of useful stuff and macros depend on it being around. diff --git a/frame/atomic-swap/Cargo.toml b/frame/atomic-swap/Cargo.toml index 7a1415946e76..0f478ab5602f 100644 --- a/frame/atomic-swap/Cargo.toml +++ b/frame/atomic-swap/Cargo.toml @@ -17,7 +17,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } diff --git a/frame/aura/Cargo.toml b/frame/aura/Cargo.toml index 34956b1116e9..f5c71a308858 100644 --- a/frame/aura/Cargo.toml +++ b/frame/aura/Cargo.toml @@ -17,7 +17,7 @@ sp-application-crypto = { version = "4.0.0", default-features = false, path = ". codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } sp-consensus-aura = { version = "0.10.0-dev", path = "../../primitives/consensus/aura", default-features = false } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/authority-discovery/Cargo.toml b/frame/authority-discovery/Cargo.toml index 4cb40a0f2661..c1233028df4e 100644 --- a/frame/authority-discovery/Cargo.toml +++ b/frame/authority-discovery/Cargo.toml @@ -23,7 +23,7 @@ sp-std = { version = "4.0.0", default-features = false, path = "../../primitives pallet-session = { version = "4.0.0-dev", features = [ "historical", ], path = "../session", default-features = false } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/authorship/Cargo.toml b/frame/authorship/Cargo.toml index 77be81c082b1..c17fc49ecdcc 100644 --- a/frame/authorship/Cargo.toml +++ b/frame/authorship/Cargo.toml @@ -19,7 +19,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-authorship = { version = "4.0.0-dev", default-features = false, path = "../../primitives/authorship" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } impl-trait-for-tuples = "0.2.1" diff --git a/frame/babe/Cargo.toml b/frame/babe/Cargo.toml index 5242de638c38..673af5c30ed6 100644 --- a/frame/babe/Cargo.toml +++ b/frame/babe/Cargo.toml @@ -25,7 +25,7 @@ sp-application-crypto = { version = "4.0.0", default-features = false, path = ". sp-consensus-babe = { version = "0.10.0-dev", default-features = false, path = "../../primitives/consensus/babe" } sp-consensus-vrf = { version = "0.10.0-dev", default-features = false, path = "../../primitives/consensus/vrf" } sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../primitives/session" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } diff --git a/frame/bags-list/Cargo.toml b/frame/bags-list/Cargo.toml index e5e746ad1b62..9e802527f18d 100644 --- a/frame/bags-list/Cargo.toml +++ b/frame/bags-list/Cargo.toml @@ -18,7 +18,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } # primitives -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } # FRAME diff --git a/frame/bags-list/remote-tests/Cargo.toml b/frame/bags-list/remote-tests/Cargo.toml index b120b32d5d4b..d8797ad360ba 100644 --- a/frame/bags-list/remote-tests/Cargo.toml +++ b/frame/bags-list/remote-tests/Cargo.toml @@ -24,7 +24,7 @@ frame-support = { path = "../../support", version = "4.0.0-dev" } sp-storage = { path = "../../../primitives/storage", version = "4.0.0" } sp-core = { path = "../../../primitives/core", version = "4.1.0-dev" } sp-tracing = { path = "../../../primitives/tracing", version = "4.0.0" } -sp-runtime = { path = "../../../primitives/runtime", version = "4.0.0" } +sp-runtime = { path = "../../../primitives/runtime", version = "4.1.0-dev" } sp-std = { path = "../../../primitives/std", version = "4.0.0" } # utils diff --git a/frame/balances/Cargo.toml b/frame/balances/Cargo.toml index fdabb4132b1a..02b94fe606c4 100644 --- a/frame/balances/Cargo.toml +++ b/frame/balances/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/beefy-mmr/Cargo.toml b/frame/beefy-mmr/Cargo.toml index b36b3ba873ae..c793173cc22d 100644 --- a/frame/beefy-mmr/Cargo.toml +++ b/frame/beefy-mmr/Cargo.toml @@ -23,7 +23,7 @@ pallet-session = { version = "4.0.0-dev", path = "../session", default-features sp-core = { version = "4.1.0-dev", path = "../../primitives/core", default-features = false } sp-io = { version = "4.0.0-dev", path = "../../primitives/io", default-features = false } -sp-runtime = { version = "4.0.0", path = "../../primitives/runtime", default-features = false } +sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime", default-features = false } sp-std = { version = "4.0.0", path = "../../primitives/std", default-features = false } beefy-merkle-tree = { version = "4.0.0-dev", path = "./primitives", default-features = false } diff --git a/frame/beefy/Cargo.toml b/frame/beefy/Cargo.toml index 753e90faad2e..52471a332dd7 100644 --- a/frame/beefy/Cargo.toml +++ b/frame/beefy/Cargo.toml @@ -15,7 +15,7 @@ serde = { version = "1.0.132", optional = true } frame-support = { version = "4.0.0-dev", path = "../support", default-features = false } frame-system = { version = "4.0.0-dev", path = "../system", default-features = false } -sp-runtime = { version = "4.0.0", path = "../../primitives/runtime", default-features = false } +sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime", default-features = false } sp-std = { version = "4.0.0", path = "../../primitives/std", default-features = false } pallet-session = { version = "4.0.0-dev", path = "../session", default-features = false } diff --git a/frame/benchmarking/Cargo.toml b/frame/benchmarking/Cargo.toml index d3dcf589e446..ce110d8ba511 100644 --- a/frame/benchmarking/Cargo.toml +++ b/frame/benchmarking/Cargo.toml @@ -19,7 +19,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-api = { version = "4.0.0-dev", path = "../../primitives/api", default-features = false } sp-runtime-interface = { version = "4.1.0-dev", path = "../../primitives/runtime-interface", default-features = false } -sp-runtime = { version = "4.0.0", path = "../../primitives/runtime", default-features = false } +sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime", default-features = false } sp-std = { version = "4.0.0", path = "../../primitives/std", default-features = false } sp-io = { version = "4.0.0", path = "../../primitives/io", default-features = false } sp-application-crypto = { version = "4.0.0", path = "../../primitives/application-crypto", default-features = false } diff --git a/frame/bounties/Cargo.toml b/frame/bounties/Cargo.toml index 2e328e19b8ec..73973ab18caa 100644 --- a/frame/bounties/Cargo.toml +++ b/frame/bounties/Cargo.toml @@ -18,7 +18,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } pallet-treasury = { version = "4.0.0-dev", default-features = false, path = "../treasury" } diff --git a/frame/child-bounties/Cargo.toml b/frame/child-bounties/Cargo.toml index fcd8e839fb1e..742110a58bff 100644 --- a/frame/child-bounties/Cargo.toml +++ b/frame/child-bounties/Cargo.toml @@ -18,7 +18,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } pallet-treasury = { version = "4.0.0-dev", default-features = false, path = "../treasury" } diff --git a/frame/collective/Cargo.toml b/frame/collective/Cargo.toml index cc17a6d7ce60..bd0573bace66 100644 --- a/frame/collective/Cargo.toml +++ b/frame/collective/Cargo.toml @@ -19,7 +19,7 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } diff --git a/frame/contracts/Cargo.toml b/frame/contracts/Cargo.toml index 64c1de220155..f0d2833c61fd 100644 --- a/frame/contracts/Cargo.toml +++ b/frame/contracts/Cargo.toml @@ -40,7 +40,7 @@ pallet-contracts-primitives = { version = "4.0.0-dev", default-features = false, pallet-contracts-proc-macro = { version = "4.0.0-dev", path = "proc-macro" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } sp-sandbox = { version = "0.10.0-dev", default-features = false, path = "../../primitives/sandbox" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } diff --git a/frame/contracts/common/Cargo.toml b/frame/contracts/common/Cargo.toml index 2b565b4c9e2c..05bfc212e305 100644 --- a/frame/contracts/common/Cargo.toml +++ b/frame/contracts/common/Cargo.toml @@ -22,7 +22,7 @@ serde = { version = "1", features = ["derive"], optional = true } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core", default-features = false } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } sp-rpc = { version = "4.0.0-dev", path = "../../../primitives/rpc", optional = true } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/runtime" } [features] default = ["std"] diff --git a/frame/contracts/rpc/Cargo.toml b/frame/contracts/rpc/Cargo.toml index 51a512277c56..9a88013c3408 100644 --- a/frame/contracts/rpc/Cargo.toml +++ b/frame/contracts/rpc/Cargo.toml @@ -26,7 +26,7 @@ sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sp-rpc = { version = "4.0.0-dev", path = "../../../primitives/rpc" } -sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } [dev-dependencies] serde_json = "1" diff --git a/frame/contracts/rpc/runtime-api/Cargo.toml b/frame/contracts/rpc/runtime-api/Cargo.toml index c7251306192e..bb70d0835d26 100644 --- a/frame/contracts/rpc/runtime-api/Cargo.toml +++ b/frame/contracts/rpc/runtime-api/Cargo.toml @@ -19,7 +19,7 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] # Substrate Dependencies pallet-contracts-primitives = { version = "4.0.0-dev", default-features = false, path = "../../common" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/api" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../../../primitives/std" } [features] diff --git a/frame/democracy/Cargo.toml b/frame/democracy/Cargo.toml index ef8e1f3a2f17..730bc6fffbdf 100644 --- a/frame/democracy/Cargo.toml +++ b/frame/democracy/Cargo.toml @@ -20,7 +20,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/election-provider-multi-phase/Cargo.toml b/frame/election-provider-multi-phase/Cargo.toml index c8ed0c561b46..7add94dc76c8 100644 --- a/frame/election-provider-multi-phase/Cargo.toml +++ b/frame/election-provider-multi-phase/Cargo.toml @@ -26,7 +26,7 @@ frame-system = { version = "4.0.0-dev", default-features = false, path = "../sys sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } sp-npos-elections = { version = "4.0.0-dev", default-features = false, path = "../../primitives/npos-elections" } sp-arithmetic = { version = "4.0.0", default-features = false, path = "../../primitives/arithmetic" } frame-election-provider-support = { version = "4.0.0-dev", default-features = false, path = "../election-provider-support" } diff --git a/frame/election-provider-support/Cargo.toml b/frame/election-provider-support/Cargo.toml index 8fabefa7a12c..1cb477d6c79c 100644 --- a/frame/election-provider-support/Cargo.toml +++ b/frame/election-provider-support/Cargo.toml @@ -23,7 +23,7 @@ frame-system = { version = "4.0.0-dev", default-features = false, path = "../sys [dev-dependencies] sp-npos-elections = { version = "4.0.0-dev", path = "../../primitives/npos-elections" } -sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } diff --git a/frame/elections-phragmen/Cargo.toml b/frame/elections-phragmen/Cargo.toml index bcf91ac5c73c..867b1627272a 100644 --- a/frame/elections-phragmen/Cargo.toml +++ b/frame/elections-phragmen/Cargo.toml @@ -17,7 +17,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = "derive", ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } sp-npos-elections = { version = "4.0.0-dev", default-features = false, path = "../../primitives/npos-elections" } sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/frame/examples/basic/Cargo.toml b/frame/examples/basic/Cargo.toml index 48f505444884..894b9b4d5010 100644 --- a/frame/examples/basic/Cargo.toml +++ b/frame/examples/basic/Cargo.toml @@ -22,7 +22,7 @@ frame-support = { version = "4.0.0-dev", default-features = false, path = "../.. frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" } pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../../balances" } sp-io = { version = "4.0.0", default-features = false, path = "../../../primitives/io" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } [dev-dependencies] diff --git a/frame/examples/offchain-worker/Cargo.toml b/frame/examples/offchain-worker/Cargo.toml index 6152b2ca95ee..68ad2125eef4 100644 --- a/frame/examples/offchain-worker/Cargo.toml +++ b/frame/examples/offchain-worker/Cargo.toml @@ -23,7 +23,7 @@ frame-system = { version = "4.0.0-dev", default-features = false, path = "../../ sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/io" } sp-keystore = { version = "0.10.0", path = "../../../primitives/keystore", optional = true } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } [features] diff --git a/frame/examples/parallel/Cargo.toml b/frame/examples/parallel/Cargo.toml index 94c18b6c9828..b3ec1a72506b 100644 --- a/frame/examples/parallel/Cargo.toml +++ b/frame/examples/parallel/Cargo.toml @@ -19,7 +19,7 @@ frame-support = { version = "4.0.0-dev", default-features = false, path = "../.. frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/io" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } sp-tasks = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/tasks" } diff --git a/frame/executive/Cargo.toml b/frame/executive/Cargo.toml index 02cb2b22b388..1b6a237f3b93 100644 --- a/frame/executive/Cargo.toml +++ b/frame/executive/Cargo.toml @@ -19,7 +19,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } sp-tracing = { version = "4.0.0", default-features = false, path = "../../primitives/tracing" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } diff --git a/frame/gilt/Cargo.toml b/frame/gilt/Cargo.toml index 39b9fb558293..b958b7ba337f 100644 --- a/frame/gilt/Cargo.toml +++ b/frame/gilt/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } sp-arithmetic = { version = "4.0.0", default-features = false, path = "../../primitives/arithmetic" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/frame/grandpa/Cargo.toml b/frame/grandpa/Cargo.toml index 8604c678bf64..4b2ab7eca871 100644 --- a/frame/grandpa/Cargo.toml +++ b/frame/grandpa/Cargo.toml @@ -21,7 +21,7 @@ sp-finality-grandpa = { version = "4.0.0-dev", default-features = false, path = sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../primitives/session" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/frame/identity/Cargo.toml b/frame/identity/Cargo.toml index 32e62d8aec0b..00be4d767ec2 100644 --- a/frame/identity/Cargo.toml +++ b/frame/identity/Cargo.toml @@ -18,7 +18,7 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] enumflags2 = { version = "0.6.2" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/im-online/Cargo.toml b/frame/im-online/Cargo.toml index dc839d0d1f9e..9d659d304dbb 100644 --- a/frame/im-online/Cargo.toml +++ b/frame/im-online/Cargo.toml @@ -20,7 +20,7 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/indices/Cargo.toml b/frame/indices/Cargo.toml index d2c114e60519..a2998c7cfae9 100644 --- a/frame/indices/Cargo.toml +++ b/frame/indices/Cargo.toml @@ -18,7 +18,7 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] sp-keyring = { version = "4.1.0-dev", optional = true, path = "../../primitives/keyring" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/lottery/Cargo.toml b/frame/lottery/Cargo.toml index 9f31f8017341..cef152a18588 100644 --- a/frame/lottery/Cargo.toml +++ b/frame/lottery/Cargo.toml @@ -18,7 +18,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/membership/Cargo.toml b/frame/membership/Cargo.toml index fc0d44c76656..7ded2fd586e1 100644 --- a/frame/membership/Cargo.toml +++ b/frame/membership/Cargo.toml @@ -19,7 +19,7 @@ log = { version = "0.4.0", default-features = false } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } diff --git a/frame/merkle-mountain-range/Cargo.toml b/frame/merkle-mountain-range/Cargo.toml index 10476e9a73dd..495b0add5b1c 100644 --- a/frame/merkle-mountain-range/Cargo.toml +++ b/frame/merkle-mountain-range/Cargo.toml @@ -18,7 +18,7 @@ mmr-lib = { package = "ckb-merkle-mountain-range", default-features = false, ver sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } diff --git a/frame/merkle-mountain-range/primitives/Cargo.toml b/frame/merkle-mountain-range/primitives/Cargo.toml index 6991ff16939b..2e483360facc 100644 --- a/frame/merkle-mountain-range/primitives/Cargo.toml +++ b/frame/merkle-mountain-range/primitives/Cargo.toml @@ -18,7 +18,7 @@ serde = { version = "1.0.132", optional = true, features = ["derive"] } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/api" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" } diff --git a/frame/merkle-mountain-range/rpc/Cargo.toml b/frame/merkle-mountain-range/rpc/Cargo.toml index cf6aee670b5b..d6bf66cefefb 100644 --- a/frame/merkle-mountain-range/rpc/Cargo.toml +++ b/frame/merkle-mountain-range/rpc/Cargo.toml @@ -22,7 +22,7 @@ serde = { version = "1.0.132", features = ["derive"] } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } -sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } pallet-mmr-primitives = { version = "4.0.0-dev", path = "../primitives" } diff --git a/frame/multisig/Cargo.toml b/frame/multisig/Cargo.toml index d1c8d8c60c21..696f8afe0d85 100644 --- a/frame/multisig/Cargo.toml +++ b/frame/multisig/Cargo.toml @@ -17,7 +17,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } diff --git a/frame/nicks/Cargo.toml b/frame/nicks/Cargo.toml index 08d529070a5e..221a386c752a 100644 --- a/frame/nicks/Cargo.toml +++ b/frame/nicks/Cargo.toml @@ -17,7 +17,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/node-authorization/Cargo.toml b/frame/node-authorization/Cargo.toml index 350914381c1e..610e536a2c81 100644 --- a/frame/node-authorization/Cargo.toml +++ b/frame/node-authorization/Cargo.toml @@ -18,7 +18,7 @@ frame-support = { version = "4.0.0-dev", default-features = false, path = "../su frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } log = { version = "0.4.14", default-features = false } diff --git a/frame/offences/Cargo.toml b/frame/offences/Cargo.toml index 8084a63cc276..49aa1d770e5b 100644 --- a/frame/offences/Cargo.toml +++ b/frame/offences/Cargo.toml @@ -18,7 +18,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } serde = { version = "1.0.132", optional = true } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/offences/benchmarking/Cargo.toml b/frame/offences/benchmarking/Cargo.toml index 28e4fde7c3ce..2764eedc1191 100644 --- a/frame/offences/benchmarking/Cargo.toml +++ b/frame/offences/benchmarking/Cargo.toml @@ -29,7 +29,7 @@ pallet-session = { version = "4.0.0-dev", default-features = false, path = "../. pallet-staking = { version = "4.0.0-dev", default-features = false, features = [ "runtime-benchmarks", ], path = "../../staking" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/runtime" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/staking" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } frame-election-provider-support = { version = "4.0.0-dev", default-features = false, path = "../../election-provider-support" } diff --git a/frame/preimage/Cargo.toml b/frame/preimage/Cargo.toml index 29763d08017f..17fed986f757 100644 --- a/frame/preimage/Cargo.toml +++ b/frame/preimage/Cargo.toml @@ -16,7 +16,7 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } sp-core = { version = "4.1.0-dev", default-features = false, optional = true, path = "../../primitives/core" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } diff --git a/frame/proxy/Cargo.toml b/frame/proxy/Cargo.toml index c5d9dc857b8d..a07ecb499774 100644 --- a/frame/proxy/Cargo.toml +++ b/frame/proxy/Cargo.toml @@ -18,7 +18,7 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } diff --git a/frame/randomness-collective-flip/Cargo.toml b/frame/randomness-collective-flip/Cargo.toml index 037ce134045c..a29e7ac7b326 100644 --- a/frame/randomness-collective-flip/Cargo.toml +++ b/frame/randomness-collective-flip/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] safe-mix = { version = "1.0", default-features = false } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/frame/recovery/Cargo.toml b/frame/recovery/Cargo.toml index 3ed194225d0a..53fe6851564d 100644 --- a/frame/recovery/Cargo.toml +++ b/frame/recovery/Cargo.toml @@ -17,7 +17,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/scheduler/Cargo.toml b/frame/scheduler/Cargo.toml index 9cc34f69db79..424c3852862e 100644 --- a/frame/scheduler/Cargo.toml +++ b/frame/scheduler/Cargo.toml @@ -16,7 +16,7 @@ log = { version = "0.4.14", default-features = false } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } diff --git a/frame/scored-pool/Cargo.toml b/frame/scored-pool/Cargo.toml index f570039abc33..b97a7e366490 100644 --- a/frame/scored-pool/Cargo.toml +++ b/frame/scored-pool/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/session/Cargo.toml b/frame/session/Cargo.toml index 57b7fff99479..db6f10c72888 100644 --- a/frame/session/Cargo.toml +++ b/frame/session/Cargo.toml @@ -22,7 +22,7 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../primitives/session" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" } sp-trie = { version = "4.0.0", default-features = false, path = "../../primitives/trie", optional = true } diff --git a/frame/session/benchmarking/Cargo.toml b/frame/session/benchmarking/Cargo.toml index 5f889e66a870..10a430d52b0a 100644 --- a/frame/session/benchmarking/Cargo.toml +++ b/frame/session/benchmarking/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] rand = { version = "0.7.2", default-features = false } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/runtime" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/session" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../../benchmarking" } diff --git a/frame/society/Cargo.toml b/frame/society/Cargo.toml index ad53026f4ce0..fa3f981f19d4 100644 --- a/frame/society/Cargo.toml +++ b/frame/society/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/staking/Cargo.toml b/frame/staking/Cargo.toml index c72a1c0ec662..e0d5dabaa892 100644 --- a/frame/staking/Cargo.toml +++ b/frame/staking/Cargo.toml @@ -20,7 +20,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/staking/reward-curve/Cargo.toml b/frame/staking/reward-curve/Cargo.toml index bcbdffd6adc3..4c1d2b922f6d 100644 --- a/frame/staking/reward-curve/Cargo.toml +++ b/frame/staking/reward-curve/Cargo.toml @@ -21,4 +21,4 @@ proc-macro2 = "1.0.36" proc-macro-crate = "1.1.0" [dev-dependencies] -sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } diff --git a/frame/sudo/Cargo.toml b/frame/sudo/Cargo.toml index c553c80d19d2..504eb37b8d00 100644 --- a/frame/sudo/Cargo.toml +++ b/frame/sudo/Cargo.toml @@ -17,7 +17,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } diff --git a/frame/support/Cargo.toml b/frame/support/Cargo.toml index a6bbc73f9ddb..d652e5ea4344 100644 --- a/frame/support/Cargo.toml +++ b/frame/support/Cargo.toml @@ -19,7 +19,7 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] frame-metadata = { version = "14.2.0", default-features = false, features = ["v14"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } sp-tracing = { version = "4.0.0", default-features = false, path = "../../primitives/tracing" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-arithmetic = { version = "4.0.0", default-features = false, path = "../../primitives/arithmetic" } diff --git a/frame/support/test/Cargo.toml b/frame/support/test/Cargo.toml index f7275cbe2e85..257cca3218da 100644 --- a/frame/support/test/Cargo.toml +++ b/frame/support/test/Cargo.toml @@ -19,7 +19,7 @@ sp-arithmetic = { version = "4.0.0", default-features = false, path = "../../../ sp-io = { version = "4.0.0", path = "../../../primitives/io", default-features = false } sp-state-machine = { version = "0.10.0", optional = true, path = "../../../primitives/state-machine" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/runtime" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } sp-version = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/version" } diff --git a/frame/support/test/compile_pass/Cargo.toml b/frame/support/test/compile_pass/Cargo.toml index 21d3be667253..93443e33503c 100644 --- a/frame/support/test/compile_pass/Cargo.toml +++ b/frame/support/test/compile_pass/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../../primitives/core" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../../primitives/runtime" } sp-version = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/version" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../../" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../../system" } diff --git a/frame/system/Cargo.toml b/frame/system/Cargo.toml index 7c1526bbd9d4..ae9242087f1a 100644 --- a/frame/system/Cargo.toml +++ b/frame/system/Cargo.toml @@ -19,7 +19,7 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0", path = "../../primitives/io", default-features = false } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } sp-version = { version = "4.0.0-dev", default-features = false, path = "../../primitives/version" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } log = { version = "0.4.14", default-features = false } diff --git a/frame/system/benchmarking/Cargo.toml b/frame/system/benchmarking/Cargo.toml index ff31c6fdbac4..4ca250fa0ec7 100644 --- a/frame/system/benchmarking/Cargo.toml +++ b/frame/system/benchmarking/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/runtime" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../../benchmarking" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" } diff --git a/frame/timestamp/Cargo.toml b/frame/timestamp/Cargo.toml index e10acdc25457..b66a91acebaa 100644 --- a/frame/timestamp/Cargo.toml +++ b/frame/timestamp/Cargo.toml @@ -19,7 +19,7 @@ codec = { package = "parity-scale-codec", version = "2.2.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io", optional = true } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../primitives/inherents" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/frame/tips/Cargo.toml b/frame/tips/Cargo.toml index 42d58ec38844..bbe78fd30a56 100644 --- a/frame/tips/Cargo.toml +++ b/frame/tips/Cargo.toml @@ -20,7 +20,7 @@ serde = { version = "1.0.132", features = ["derive"], optional = true } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/frame/transaction-payment/Cargo.toml b/frame/transaction-payment/Cargo.toml index 9cf6790de46d..8cb544159dd7 100644 --- a/frame/transaction-payment/Cargo.toml +++ b/frame/transaction-payment/Cargo.toml @@ -22,7 +22,7 @@ smallvec = "1.7.0" sp-core = { version = "4.1.0-dev", path = "../../primitives/core", default-features = false } sp-io = { version = "4.0.0-dev", path = "../../primitives/io", default-features = false } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/frame/transaction-payment/asset-tx-payment/Cargo.toml b/frame/transaction-payment/asset-tx-payment/Cargo.toml index 820c8f00bb8f..ab2d3302f95b 100644 --- a/frame/transaction-payment/asset-tx-payment/Cargo.toml +++ b/frame/transaction-payment/asset-tx-payment/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] # Substrate dependencies sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } sp-io = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/io" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" } diff --git a/frame/transaction-payment/rpc/Cargo.toml b/frame/transaction-payment/rpc/Cargo.toml index b8e43848dbf4..2486654404ae 100644 --- a/frame/transaction-payment/rpc/Cargo.toml +++ b/frame/transaction-payment/rpc/Cargo.toml @@ -22,5 +22,5 @@ sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sp-rpc = { version = "4.0.0-dev", path = "../../../primitives/rpc" } -sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } pallet-transaction-payment-rpc-runtime-api = { version = "4.0.0-dev", path = "./runtime-api" } diff --git a/frame/transaction-payment/rpc/runtime-api/Cargo.toml b/frame/transaction-payment/rpc/runtime-api/Cargo.toml index 6cfe02d15c4f..1ad56280ac08 100644 --- a/frame/transaction-payment/rpc/runtime-api/Cargo.toml +++ b/frame/transaction-payment/rpc/runtime-api/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/api" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../../primitives/runtime" } pallet-transaction-payment = { version = "4.0.0-dev", default-features = false, path = "../../../transaction-payment" } [features] diff --git a/frame/transaction-storage/Cargo.toml b/frame/transaction-storage/Cargo.toml index 68b391387f87..e4351438811f 100644 --- a/frame/transaction-storage/Cargo.toml +++ b/frame/transaction-storage/Cargo.toml @@ -20,7 +20,7 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../balances" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../primitives/inherents" } diff --git a/frame/treasury/Cargo.toml b/frame/treasury/Cargo.toml index a4e211283e13..0a2dab417e34 100644 --- a/frame/treasury/Cargo.toml +++ b/frame/treasury/Cargo.toml @@ -22,7 +22,7 @@ serde = { version = "1.0.132", features = ["derive"], optional = true } impl-trait-for-tuples = "0.2.1" sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } diff --git a/frame/try-runtime/Cargo.toml b/frame/try-runtime/Cargo.toml index 860a9e988b11..905c58ab00be 100644 --- a/frame/try-runtime/Cargo.toml +++ b/frame/try-runtime/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-api = { version = "4.0.0-dev", path = "../../primitives/api", default-features = false } sp-std = { version = "4.0.0", path = "../../primitives/std" , default-features = false } -sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" , default-features = false } +sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" , default-features = false } frame-support = { version = "4.0.0-dev", path = "../support", default-features = false } diff --git a/frame/uniques/Cargo.toml b/frame/uniques/Cargo.toml index a168c96778ad..38c519f80167 100644 --- a/frame/uniques/Cargo.toml +++ b/frame/uniques/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } diff --git a/frame/utility/Cargo.toml b/frame/utility/Cargo.toml index 62fa402705ef..85f522975dbb 100644 --- a/frame/utility/Cargo.toml +++ b/frame/utility/Cargo.toml @@ -18,7 +18,7 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "4.0.0", default-features = false, path = "../../primitives/io" } diff --git a/frame/vesting/Cargo.toml b/frame/vesting/Cargo.toml index fa0b564c855d..e488e282cd45 100644 --- a/frame/vesting/Cargo.toml +++ b/frame/vesting/Cargo.toml @@ -18,7 +18,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = ] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } diff --git a/primitives/api/Cargo.toml b/primitives/api/Cargo.toml index b940ae93baa5..f2c3e67800dc 100644 --- a/primitives/api/Cargo.toml +++ b/primitives/api/Cargo.toml @@ -17,7 +17,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = sp-api-proc-macro = { version = "4.0.0-dev", path = "proc-macro" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../runtime" } sp-version = { version = "4.0.0-dev", default-features = false, path = "../version" } sp-state-machine = { version = "0.10.0", optional = true, path = "../state-machine" } hash-db = { version = "0.15.2", optional = true } diff --git a/primitives/api/test/Cargo.toml b/primitives/api/test/Cargo.toml index 38845340027f..79e302c4c065 100644 --- a/primitives/api/test/Cargo.toml +++ b/primitives/api/test/Cargo.toml @@ -16,7 +16,7 @@ sp-api = { version = "4.0.0-dev", path = "../" } substrate-test-runtime-client = { version = "2.0.0", path = "../../../test-utils/runtime/client" } sp-version = { version = "4.0.0-dev", path = "../../version" } sp-tracing = { version = "4.0.0", path = "../../tracing" } -sp-runtime = { version = "4.0.0", path = "../../runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../runtime" } sp-consensus = { version = "0.10.0-dev", path = "../../consensus/common" } sc-block-builder = { version = "0.10.0-dev", path = "../../../client/block-builder" } codec = { package = "parity-scale-codec", version = "2.0.0" } diff --git a/primitives/application-crypto/test/Cargo.toml b/primitives/application-crypto/test/Cargo.toml index 0fdb64c5b292..178932869611 100644 --- a/primitives/application-crypto/test/Cargo.toml +++ b/primitives/application-crypto/test/Cargo.toml @@ -16,6 +16,6 @@ targets = ["x86_64-unknown-linux-gnu"] sp-core = { version = "4.1.0-dev", default-features = false, path = "../../core" } sp-keystore = { version = "0.10.0", path = "../../keystore", default-features = false } substrate-test-runtime-client = { version = "2.0.0", path = "../../../test-utils/runtime/client" } -sp-runtime = { version = "4.0.0", path = "../../runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../runtime" } sp-api = { version = "4.0.0-dev", path = "../../api" } sp-application-crypto = { version = "4.0.0", path = "../" } diff --git a/primitives/authority-discovery/Cargo.toml b/primitives/authority-discovery/Cargo.toml index 2f1d38c31152..2fd2c4847692 100644 --- a/primitives/authority-discovery/Cargo.toml +++ b/primitives/authority-discovery/Cargo.toml @@ -18,7 +18,7 @@ codec = { package = "parity-scale-codec", default-features = false, version = "2 scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../runtime" } [features] default = ["std"] diff --git a/primitives/authorship/Cargo.toml b/primitives/authorship/Cargo.toml index 81fa39e93a1a..8e97942499aa 100644 --- a/primitives/authorship/Cargo.toml +++ b/primitives/authorship/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../inherents" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } async-trait = { version = "0.1.50", optional = true } diff --git a/primitives/beefy/Cargo.toml b/primitives/beefy/Cargo.toml index 6a74c58d2ceb..edcb2244e58f 100644 --- a/primitives/beefy/Cargo.toml +++ b/primitives/beefy/Cargo.toml @@ -14,7 +14,7 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] sp-api = { version = "4.0.0-dev", path = "../api", default-features = false } sp-application-crypto = { version = "4.0.0", path = "../application-crypto", default-features = false } sp-core = { version = "4.1.0-dev", path = "../core", default-features = false } -sp-runtime = { version = "4.0.0", path = "../runtime", default-features = false } +sp-runtime = { version = "4.1.0-dev", path = "../runtime", default-features = false } sp-std = { version = "4.0.0", path = "../std", default-features = false } [dev-dependencies] diff --git a/primitives/block-builder/Cargo.toml b/primitives/block-builder/Cargo.toml index 083865cd2ccc..5009207a3f5c 100644 --- a/primitives/block-builder/Cargo.toml +++ b/primitives/block-builder/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-runtime = { version = "4.0.0", default-features = false, path = "../runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../runtime" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } diff --git a/primitives/blockchain/Cargo.toml b/primitives/blockchain/Cargo.toml index 57732c360bac..366d0f3c373e 100644 --- a/primitives/blockchain/Cargo.toml +++ b/primitives/blockchain/Cargo.toml @@ -21,7 +21,7 @@ thiserror = "1.0.30" futures = "0.3.9" codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } sp-consensus = { version = "0.10.0-dev", path = "../consensus/common" } -sp-runtime = { version = "4.0.0", path = "../runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../runtime" } sp-state-machine = { version = "0.10.0", path = "../state-machine" } sp-database = { version = "4.0.0-dev", path = "../database" } sp-api = { version = "4.0.0-dev", path = "../api" } diff --git a/primitives/consensus/aura/Cargo.toml b/primitives/consensus/aura/Cargo.toml index 747a9f546cb0..f15f0008164d 100644 --- a/primitives/consensus/aura/Cargo.toml +++ b/primitives/consensus/aura/Cargo.toml @@ -18,7 +18,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../../std" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../api" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../runtime" } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../inherents" } sp-timestamp = { version = "4.0.0-dev", default-features = false, path = "../../timestamp" } sp-consensus-slots = { version = "0.10.0-dev", default-features = false, path = "../slots" } diff --git a/primitives/consensus/babe/Cargo.toml b/primitives/consensus/babe/Cargo.toml index 330ce775eb06..1471ca05f591 100644 --- a/primitives/consensus/babe/Cargo.toml +++ b/primitives/consensus/babe/Cargo.toml @@ -25,7 +25,7 @@ sp-consensus-vrf = { version = "0.10.0-dev", path = "../vrf", default-features = sp-core = { version = "4.1.0-dev", default-features = false, path = "../../core" } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../inherents" } sp-keystore = { version = "0.10.0", default-features = false, path = "../../keystore", optional = true } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../runtime" } sp-timestamp = { version = "4.0.0-dev", path = "../../timestamp", optional = true } serde = { version = "1.0.132", features = ["derive"], optional = true } async-trait = { version = "0.1.50", optional = true } diff --git a/primitives/consensus/common/Cargo.toml b/primitives/consensus/common/Cargo.toml index e638c04a08dc..93338d62cfc0 100644 --- a/primitives/consensus/common/Cargo.toml +++ b/primitives/consensus/common/Cargo.toml @@ -26,7 +26,7 @@ sp-state-machine = { version = "0.10.0", path = "../../state-machine" } futures-timer = "3.0.1" sp-std = { version = "4.0.0", path = "../../std" } sp-version = { version = "4.0.0-dev", path = "../../version" } -sp-runtime = { version = "4.0.0", path = "../../runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../runtime" } thiserror = "1.0.30" [dev-dependencies] diff --git a/primitives/consensus/pow/Cargo.toml b/primitives/consensus/pow/Cargo.toml index 6e00453da1bd..810e9c23a659 100644 --- a/primitives/consensus/pow/Cargo.toml +++ b/primitives/consensus/pow/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-api = { version = "4.0.0-dev", default-features = false, path = "../../api" } sp-std = { version = "4.0.0", default-features = false, path = "../../std" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../runtime" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../core" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } diff --git a/primitives/consensus/slots/Cargo.toml b/primitives/consensus/slots/Cargo.toml index 23f73454aad9..ea2a86218982 100644 --- a/primitives/consensus/slots/Cargo.toml +++ b/primitives/consensus/slots/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } serde = { version = "1.0", features = ["derive"], optional = true } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../runtime" } sp-arithmetic = { version = "4.0.0", default-features = false, path = "../../arithmetic" } [features] diff --git a/primitives/consensus/vrf/Cargo.toml b/primitives/consensus/vrf/Cargo.toml index 586b6354f55a..7504a159a3db 100644 --- a/primitives/consensus/vrf/Cargo.toml +++ b/primitives/consensus/vrf/Cargo.toml @@ -17,7 +17,7 @@ codec = { version = "2.0.0", package = "parity-scale-codec", default-features = schnorrkel = { version = "0.9.1", features = ["preaudit_deprecated", "u64_backend"], default-features = false } sp-std = { version = "4.0.0", path = "../../std", default-features = false } sp-core = { version = "4.1.0-dev", path = "../../core", default-features = false } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../runtime" } [features] default = ["std"] diff --git a/primitives/finality-grandpa/Cargo.toml b/primitives/finality-grandpa/Cargo.toml index e12d7a52695d..e36c088c3583 100644 --- a/primitives/finality-grandpa/Cargo.toml +++ b/primitives/finality-grandpa/Cargo.toml @@ -24,7 +24,7 @@ sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } sp-application-crypto = { version = "4.0.0", default-features = false, path = "../application-crypto" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } sp-keystore = { version = "0.10.0", default-features = false, path = "../keystore", optional = true } -sp-runtime = { version = "4.0.0", default-features = false, path = "../runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } [features] diff --git a/primitives/inherents/Cargo.toml b/primitives/inherents/Cargo.toml index 1ef0f2012056..02f084b6e634 100644 --- a/primitives/inherents/Cargo.toml +++ b/primitives/inherents/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } -sp-runtime = { version = "4.0.0", path = "../runtime", optional = true } +sp-runtime = { version = "4.1.0-dev", path = "../runtime", optional = true } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } thiserror = { version = "1.0.30", optional = true } impl-trait-for-tuples = "0.2.0" diff --git a/primitives/keyring/Cargo.toml b/primitives/keyring/Cargo.toml index d9250d0011f1..a457f4983c16 100644 --- a/primitives/keyring/Cargo.toml +++ b/primitives/keyring/Cargo.toml @@ -16,6 +16,6 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-core = { version = "4.1.0-dev", path = "../core" } -sp-runtime = { version = "4.0.0", path = "../runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../runtime" } lazy_static = "1.4.0" strum = { version = "0.22.0", features = ["derive"] } diff --git a/primitives/npos-elections/Cargo.toml b/primitives/npos-elections/Cargo.toml index d255688b56c7..062f786aaef1 100644 --- a/primitives/npos-elections/Cargo.toml +++ b/primitives/npos-elections/Cargo.toml @@ -20,7 +20,7 @@ sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-npos-elections-solution-type = { version = "4.0.0-dev", path = "./solution-type" } sp-arithmetic = { version = "4.0.0", default-features = false, path = "../arithmetic" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } -sp-runtime = { version = "4.0.0", path = "../runtime", default-features = false } +sp-runtime = { version = "4.1.0-dev", path = "../runtime", default-features = false } [dev-dependencies] substrate-test-utils = { version = "4.0.0-dev", path = "../../test-utils" } diff --git a/primitives/npos-elections/fuzzer/Cargo.toml b/primitives/npos-elections/fuzzer/Cargo.toml index 62bb1090d047..17423b624760 100644 --- a/primitives/npos-elections/fuzzer/Cargo.toml +++ b/primitives/npos-elections/fuzzer/Cargo.toml @@ -19,7 +19,7 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] honggfuzz = "0.5" rand = { version = "0.7.3", features = ["std", "small_rng"] } sp-npos-elections = { version = "4.0.0-dev", path = ".." } -sp-runtime = { version = "4.0.0", path = "../../runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../runtime" } structopt = "0.3.25" [[bin]] diff --git a/primitives/offchain/Cargo.toml b/primitives/offchain/Cargo.toml index 50a6d8344f0d..7e0ce31d5d0c 100644 --- a/primitives/offchain/Cargo.toml +++ b/primitives/offchain/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../runtime" } [features] default = ["std"] diff --git a/primitives/runtime-interface/test/Cargo.toml b/primitives/runtime-interface/test/Cargo.toml index 06fcf920a691..82c6a21b995c 100644 --- a/primitives/runtime-interface/test/Cargo.toml +++ b/primitives/runtime-interface/test/Cargo.toml @@ -18,7 +18,7 @@ sc-executor-common = { version = "0.10.0-dev", path = "../../../client/executor/ sp-runtime-interface-test-wasm = { version = "2.0.0", path = "../test-wasm" } sp-runtime-interface-test-wasm-deprecated = { version = "2.0.0", path = "../test-wasm-deprecated" } sp-state-machine = { version = "0.10.0", path = "../../state-machine" } -sp-runtime = { version = "4.0.0", path = "../../runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../runtime" } sp-io = { version = "4.0.0", path = "../../io" } tracing = "0.1.29" tracing-core = "0.1.17" diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index abf246eece9a..e6bb5a1c842e 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-runtime" -version = "4.0.0" +version = "4.1.0-dev" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" diff --git a/primitives/runtime/src/generic/digest.rs b/primitives/runtime/src/generic/digest.rs index f3cb7b99efb6..55e0d69fad33 100644 --- a/primitives/runtime/src/generic/digest.rs +++ b/primitives/runtime/src/generic/digest.rs @@ -177,16 +177,16 @@ pub enum DigestItemRef<'a> { /// the consensus engine can (and should) read them itself to avoid /// code and state duplication. It is erroneous for a runtime to produce /// these, but this is not (yet) checked. - PreRuntime(&'a ConsensusEngineId, &'a Vec), + PreRuntime(&'a ConsensusEngineId, &'a [u8]), /// A message from the runtime to the consensus engine. This should *never* /// be generated by the native code of any consensus engine, but this is not /// checked (yet). - Consensus(&'a ConsensusEngineId, &'a Vec), + Consensus(&'a ConsensusEngineId, &'a [u8]), /// Put a Seal on it. This is only used by native code, and is never seen /// by runtimes. - Seal(&'a ConsensusEngineId, &'a Vec), + Seal(&'a ConsensusEngineId, &'a [u8]), /// Any 'non-system' digest item, opaque to the native code. - Other(&'a Vec), + Other(&'a [u8]), /// Runtime code or heap pages updated. RuntimeEnvironmentUpdated, } @@ -358,8 +358,8 @@ impl<'a> DigestItemRef<'a> { (OpaqueDigestItemId::Seal(w), &Self::Seal(v, s)) | (OpaqueDigestItemId::PreRuntime(w), &Self::PreRuntime(v, s)) if v == w => - Some(&s[..]), - (OpaqueDigestItemId::Other, &Self::Other(s)) => Some(&s[..]), + Some(s), + (OpaqueDigestItemId::Other, &Self::Other(s)) => Some(s), _ => None, } } diff --git a/primitives/session/Cargo.toml b/primitives/session/Cargo.toml index cca35710172b..293f3642b7f3 100644 --- a/primitives/session/Cargo.toml +++ b/primitives/session/Cargo.toml @@ -19,7 +19,7 @@ sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../staking" } -sp-runtime = { version = "4.0.0", optional = true, path = "../runtime" } +sp-runtime = { version = "4.1.0-dev", optional = true, path = "../runtime" } [features] default = [ "std" ] diff --git a/primitives/staking/Cargo.toml b/primitives/staking/Cargo.toml index 533e177391b0..6ae972f1814b 100644 --- a/primitives/staking/Cargo.toml +++ b/primitives/staking/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-runtime = { version = "4.0.0", default-features = false, path = "../runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } [features] diff --git a/primitives/state-machine/Cargo.toml b/primitives/state-machine/Cargo.toml index b9e5c1d4f3f0..c885f99fdb83 100644 --- a/primitives/state-machine/Cargo.toml +++ b/primitives/state-machine/Cargo.toml @@ -33,7 +33,7 @@ tracing = { version = "0.1.29", optional = true } [dev-dependencies] hex-literal = "0.3.4" -sp-runtime = { version = "4.0.0", path = "../runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../runtime" } pretty_assertions = "1.0.0" rand = "0.7.2" diff --git a/primitives/test-primitives/Cargo.toml b/primitives/test-primitives/Cargo.toml index 5a045185e7ce..ab2ef0d54ca4 100644 --- a/primitives/test-primitives/Cargo.toml +++ b/primitives/test-primitives/Cargo.toml @@ -16,7 +16,7 @@ sp-application-crypto = { version = "4.0.0", default-features = false, path = ". codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } sp-core = { version = "4.1.0-dev", default-features = false, path = "../core" } serde = { version = "1.0.132", optional = true, features = ["derive"] } -sp-runtime = { version = "4.0.0", default-features = false, path = "../runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../runtime" } parity-util-mem = { version = "0.10.2", default-features = false, features = ["primitive-types"] } [features] diff --git a/primitives/timestamp/Cargo.toml b/primitives/timestamp/Cargo.toml index 4c5fdefe990a..e42ca738cd55 100644 --- a/primitives/timestamp/Cargo.toml +++ b/primitives/timestamp/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../runtime" } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../inherents" } thiserror = { version = "1.0.30", optional = true } diff --git a/primitives/transaction-pool/Cargo.toml b/primitives/transaction-pool/Cargo.toml index 2590208078db..fab5f90ffffc 100644 --- a/primitives/transaction-pool/Cargo.toml +++ b/primitives/transaction-pool/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../runtime" } [features] default = [ "std" ] diff --git a/primitives/transaction-storage-proof/Cargo.toml b/primitives/transaction-storage-proof/Cargo.toml index d731808c64c2..87f7f81cd586 100644 --- a/primitives/transaction-storage-proof/Cargo.toml +++ b/primitives/transaction-storage-proof/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../inherents" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../runtime" } sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-trie = { version = "4.0.0", optional = true, path = "../trie" } sp-core = { version = "4.1.0-dev", path = "../core", optional = true } diff --git a/primitives/trie/Cargo.toml b/primitives/trie/Cargo.toml index 8e54035b3ae7..4564fa86ced9 100644 --- a/primitives/trie/Cargo.toml +++ b/primitives/trie/Cargo.toml @@ -32,7 +32,7 @@ trie-bench = "0.29.0" trie-standardmap = "0.15.2" criterion = "0.3.3" hex-literal = "0.3.4" -sp-runtime = { version = "4.0.0", path = "../runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../runtime" } [features] default = ["std"] diff --git a/primitives/version/Cargo.toml b/primitives/version/Cargo.toml index 7fb55295088e..1bb39eca1364 100644 --- a/primitives/version/Cargo.toml +++ b/primitives/version/Cargo.toml @@ -19,7 +19,7 @@ serde = { version = "1.0.132", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { version = "4.0.0", default-features = false, path = "../std" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../runtime" } sp-version-proc-macro = { version = "4.0.0-dev", default-features = false, path = "proc-macro" } parity-wasm = { version = "0.42.2", optional = true } sp-core-hashing-proc-macro = { version = "4.0.0-dev", path = "../core/hashing/proc-macro" } diff --git a/test-utils/client/Cargo.toml b/test-utils/client/Cargo.toml index 91504df481df..902a14b1b3bd 100644 --- a/test-utils/client/Cargo.toml +++ b/test-utils/client/Cargo.toml @@ -32,6 +32,6 @@ sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/comm sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-keystore = { version = "0.10.0", path = "../../primitives/keystore" } sp-keyring = { version = "4.1.0-dev", path = "../../primitives/keyring" } -sp-runtime = { version = "4.0.0", path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } sp-state-machine = { version = "0.10.0", path = "../../primitives/state-machine" } async-trait = "0.1.50" diff --git a/test-utils/runtime/Cargo.toml b/test-utils/runtime/Cargo.toml index ee38cfd250dc..e88f57136602 100644 --- a/test-utils/runtime/Cargo.toml +++ b/test-utils/runtime/Cargo.toml @@ -31,7 +31,7 @@ frame-support = { version = "4.0.0-dev", default-features = false, path = "../.. sp-version = { version = "4.0.0-dev", default-features = false, path = "../../primitives/version" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../primitives/session" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../primitives/api" } -sp-runtime = { version = "4.0.0", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../primitives/runtime" } pallet-babe = { version = "4.0.0-dev", default-features = false, path = "../../frame/babe" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../frame/system" } frame-system-rpc-runtime-api = { version = "4.0.0-dev", default-features = false, path = "../../frame/system/rpc/runtime-api" } diff --git a/test-utils/runtime/client/Cargo.toml b/test-utils/runtime/client/Cargo.toml index 7babbfb2ed8e..ba0f01cfced9 100644 --- a/test-utils/runtime/client/Cargo.toml +++ b/test-utils/runtime/client/Cargo.toml @@ -18,7 +18,7 @@ sc-block-builder = { version = "0.10.0-dev", path = "../../../client/block-build substrate-test-client = { version = "2.0.0", path = "../../client" } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } substrate-test-runtime = { version = "2.0.0", path = "../../runtime" } -sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } codec = { package = "parity-scale-codec", version = "2.0.0" } diff --git a/test-utils/runtime/transaction-pool/Cargo.toml b/test-utils/runtime/transaction-pool/Cargo.toml index 8eaaac62c556..39221a2d1579 100644 --- a/test-utils/runtime/transaction-pool/Cargo.toml +++ b/test-utils/runtime/transaction-pool/Cargo.toml @@ -16,7 +16,7 @@ substrate-test-runtime-client = { version = "2.0.0", path = "../client" } parking_lot = "0.11.2" codec = { package = "parity-scale-codec", version = "2.0.0" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } sc-transaction-pool = { version = "4.0.0-dev", path = "../../../client/transaction-pool" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../../../client/transaction-pool/api" } futures = "0.3.16" diff --git a/utils/frame/benchmarking-cli/Cargo.toml b/utils/frame/benchmarking-cli/Cargo.toml index 61988e24e3b0..fa91956ec794 100644 --- a/utils/frame/benchmarking-cli/Cargo.toml +++ b/utils/frame/benchmarking-cli/Cargo.toml @@ -22,7 +22,7 @@ sc-client-db = { version = "0.10.0-dev", path = "../../../client/db" } sc-executor = { version = "0.10.0-dev", path = "../../../client/executor" } sp-externalities = { version = "0.10.0", path = "../../../primitives/externalities" } sp-keystore = { version = "0.10.0", path = "../../../primitives/keystore" } -sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } sp-state-machine = { version = "0.10.0", path = "../../../primitives/state-machine" } codec = { version = "2.0.0", package = "parity-scale-codec" } structopt = "0.3.25" diff --git a/utils/frame/frame-utilities-cli/Cargo.toml b/utils/frame/frame-utilities-cli/Cargo.toml index db9e4a7d9074..d256bba4b5b3 100644 --- a/utils/frame/frame-utilities-cli/Cargo.toml +++ b/utils/frame/frame-utilities-cli/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" [dependencies] sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sc-cli = { version = "0.10.0-dev", path = "../../../client/cli" } -sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } structopt = "0.3.25" frame-system = { version = "4.0.0-dev", path = "../../../frame/system" } frame-support = { version = "4.0.0-dev", path = "../../../frame/support" } diff --git a/utils/frame/remote-externalities/Cargo.toml b/utils/frame/remote-externalities/Cargo.toml index f4e26b4db39b..6d926846b4a3 100644 --- a/utils/frame/remote-externalities/Cargo.toml +++ b/utils/frame/remote-externalities/Cargo.toml @@ -24,7 +24,7 @@ serde = "1.0.132" sp-io = { version = "4.0.0-dev", path = "../../../primitives/io" } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } -sp-runtime = { version = "4.0.0", path = "../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } sp-version = { version = "4.0.0-dev", path = "../../../primitives/version" } [dev-dependencies] diff --git a/utils/frame/rpc/system/Cargo.toml b/utils/frame/rpc/system/Cargo.toml index 53ad36a96930..cb801c6cbf27 100644 --- a/utils/frame/rpc/system/Cargo.toml +++ b/utils/frame/rpc/system/Cargo.toml @@ -20,7 +20,7 @@ jsonrpc-core = "18.0.0" jsonrpc-core-client = "18.0.0" jsonrpc-derive = "18.0.0" log = "0.4.8" -sp-runtime = { version = "4.0.0", path = "../../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../../../primitives/runtime" } sp-api = { version = "4.0.0-dev", path = "../../../../primitives/api" } frame-system-rpc-runtime-api = { version = "4.0.0-dev", path = "../../../../frame/system/rpc/runtime-api" } sp-core = { version = "4.1.0-dev", path = "../../../../primitives/core" } diff --git a/utils/frame/try-runtime/cli/Cargo.toml b/utils/frame/try-runtime/cli/Cargo.toml index 0c96d727cee0..2e214ec2307b 100644 --- a/utils/frame/try-runtime/cli/Cargo.toml +++ b/utils/frame/try-runtime/cli/Cargo.toml @@ -23,7 +23,7 @@ sc-cli = { version = "0.10.0-dev", path = "../../../../client/cli" } sc-executor = { version = "0.10.0-dev", path = "../../../../client/executor" } sc-chain-spec = { version = "4.0.0-dev", path = "../../../../client/chain-spec" } sp-state-machine = { version = "0.10.0", path = "../../../../primitives/state-machine" } -sp-runtime = { version = "4.0.0", path = "../../../../primitives/runtime" } +sp-runtime = { version = "4.1.0-dev", path = "../../../../primitives/runtime" } sp-core = { version = "4.1.0-dev", path = "../../../../primitives/core" } sp-io = { version = "4.0.0-dev", path = "../../../../primitives/io" } sp-keystore = { version = "0.10.0", path = "../../../../primitives/keystore" } From f318350b6410ef47e438aae24c0b4779373d0a7b Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Thu, 20 Jan 2022 12:16:04 +0100 Subject: [PATCH 404/695] Require `MaxEncodedLen` per default (#10662) * Remove generate_storage_info Signed-off-by: Oliver Tale-Yazdi * Add without_storage_info where needed Signed-off-by: Oliver Tale-Yazdi * Update doc tests Signed-off-by: Oliver Tale-Yazdi * Add more without_storage_info Signed-off-by: Oliver Tale-Yazdi * fix TryBuild Signed-off-by: Oliver Tale-Yazdi * fix TryBuild tests Signed-off-by: Oliver Tale-Yazdi --- frame/assets/src/lib.rs | 1 - frame/atomic-swap/src/lib.rs | 1 + frame/aura/src/lib.rs | 1 - frame/authority-discovery/src/lib.rs | 1 - frame/authorship/src/lib.rs | 1 + frame/babe/src/lib.rs | 1 - frame/bags-list/src/lib.rs | 1 - frame/balances/src/lib.rs | 1 - frame/beefy-mmr/src/lib.rs | 1 + frame/beefy/src/lib.rs | 1 + frame/bounties/src/lib.rs | 1 + frame/child-bounties/src/lib.rs | 1 - frame/collective/src/lib.rs | 1 + frame/contracts/src/lib.rs | 1 + frame/democracy/src/lib.rs | 1 + .../election-provider-multi-phase/src/lib.rs | 1 + frame/elections-phragmen/src/lib.rs | 1 + frame/examples/offchain-worker/src/lib.rs | 1 + frame/examples/parallel/src/lib.rs | 1 + frame/gilt/src/lib.rs | 1 + frame/grandpa/src/lib.rs | 1 - frame/identity/src/lib.rs | 1 - frame/im-online/src/lib.rs | 1 - frame/indices/src/lib.rs | 1 + frame/lottery/src/lib.rs | 1 - frame/membership/src/lib.rs | 1 + frame/merkle-mountain-range/src/lib.rs | 1 + frame/multisig/src/lib.rs | 1 + frame/nicks/src/lib.rs | 1 + frame/node-authorization/src/lib.rs | 1 + frame/offences/src/lib.rs | 1 + frame/preimage/src/lib.rs | 1 - frame/proxy/src/lib.rs | 1 - frame/randomness-collective-flip/src/lib.rs | 1 + frame/recovery/src/lib.rs | 1 + frame/scheduler/src/lib.rs | 1 + frame/scored-pool/src/lib.rs | 1 + frame/session/src/lib.rs | 1 + frame/society/src/lib.rs | 1 + frame/staking/src/pallet/mod.rs | 1 + frame/sudo/src/lib.rs | 1 - frame/sudo/src/mock.rs | 1 + .../src/pallet/expand/pallet_struct.rs | 8 +-- .../src/pallet/parse/pallet_struct.rs | 26 ++++---- frame/support/src/lib.rs | 4 +- frame/support/test/tests/pallet.rs | 2 +- .../test/tests/pallet_compatibility.rs | 1 + .../tests/pallet_compatibility_instance.rs | 1 + ...storage_ensure_span_are_ok_on_wrong_gen.rs | 1 + ...age_ensure_span_are_ok_on_wrong_gen.stderr | 62 +++++++++---------- ...ensure_span_are_ok_on_wrong_gen_unnamed.rs | 1 + ...re_span_are_ok_on_wrong_gen_unnamed.stderr | 62 +++++++++---------- .../pallet_ui/storage_info_unsatisfied.rs | 1 - .../pallet_ui/storage_info_unsatisfied.stderr | 10 +-- .../storage_info_unsatisfied_nmap.rs | 1 - .../storage_info_unsatisfied_nmap.stderr | 6 +- frame/system/src/lib.rs | 1 + frame/timestamp/src/lib.rs | 1 - frame/tips/src/lib.rs | 1 + frame/transaction-payment/src/lib.rs | 1 + frame/transaction-storage/src/lib.rs | 1 + frame/treasury/src/lib.rs | 1 - frame/uniques/src/lib.rs | 1 + frame/vesting/src/lib.rs | 1 - 64 files changed, 127 insertions(+), 109 deletions(-) diff --git a/frame/assets/src/lib.rs b/frame/assets/src/lib.rs index be8df104dbf0..71ba7b4d2491 100644 --- a/frame/assets/src/lib.rs +++ b/frame/assets/src/lib.rs @@ -172,7 +172,6 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] - #[pallet::generate_storage_info] pub struct Pallet(_); #[pallet::config] diff --git a/frame/atomic-swap/src/lib.rs b/frame/atomic-swap/src/lib.rs index 8259f53f3950..e83055b4d283 100644 --- a/frame/atomic-swap/src/lib.rs +++ b/frame/atomic-swap/src/lib.rs @@ -182,6 +182,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] pub struct Pallet(PhantomData); #[pallet::storage] diff --git a/frame/aura/src/lib.rs b/frame/aura/src/lib.rs index 4b1d5aeb4a70..657965c60a3f 100644 --- a/frame/aura/src/lib.rs +++ b/frame/aura/src/lib.rs @@ -81,7 +81,6 @@ pub mod pallet { } #[pallet::pallet] - #[pallet::generate_storage_info] pub struct Pallet(sp_std::marker::PhantomData); #[pallet::hooks] diff --git a/frame/authority-discovery/src/lib.rs b/frame/authority-discovery/src/lib.rs index 03f6e753fd47..a56d8e785f6a 100644 --- a/frame/authority-discovery/src/lib.rs +++ b/frame/authority-discovery/src/lib.rs @@ -39,7 +39,6 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] - #[pallet::generate_storage_info] pub struct Pallet(_); #[pallet::config] diff --git a/frame/authorship/src/lib.rs b/frame/authorship/src/lib.rs index 3fa081f5263e..6b72d6ac5d28 100644 --- a/frame/authorship/src/lib.rs +++ b/frame/authorship/src/lib.rs @@ -156,6 +156,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] pub struct Pallet(_); #[pallet::hooks] diff --git a/frame/babe/src/lib.rs b/frame/babe/src/lib.rs index e2cc36ca098f..f673c8b43bee 100644 --- a/frame/babe/src/lib.rs +++ b/frame/babe/src/lib.rs @@ -115,7 +115,6 @@ pub mod pallet { /// The BABE Pallet #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] - #[pallet::generate_storage_info] pub struct Pallet(_); #[pallet::config] diff --git a/frame/bags-list/src/lib.rs b/frame/bags-list/src/lib.rs index 98261b6bbafc..89c54db87023 100644 --- a/frame/bags-list/src/lib.rs +++ b/frame/bags-list/src/lib.rs @@ -92,7 +92,6 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(crate) trait Store)] - #[pallet::generate_storage_info] pub struct Pallet(_); #[pallet::config] diff --git a/frame/balances/src/lib.rs b/frame/balances/src/lib.rs index 5235dc97ccb4..f94afec06942 100644 --- a/frame/balances/src/lib.rs +++ b/frame/balances/src/lib.rs @@ -242,7 +242,6 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] - #[pallet::generate_storage_info] pub struct Pallet(PhantomData<(T, I)>); #[pallet::call] diff --git a/frame/beefy-mmr/src/lib.rs b/frame/beefy-mmr/src/lib.rs index 38d0a6ac9a7f..d66de51d9af2 100644 --- a/frame/beefy-mmr/src/lib.rs +++ b/frame/beefy-mmr/src/lib.rs @@ -119,6 +119,7 @@ pub mod pallet { /// BEEFY-MMR pallet. #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] pub struct Pallet(_); /// The module's configuration trait. diff --git a/frame/beefy/src/lib.rs b/frame/beefy/src/lib.rs index eb822915ee46..4aa1d1337cd0 100644 --- a/frame/beefy/src/lib.rs +++ b/frame/beefy/src/lib.rs @@ -51,6 +51,7 @@ pub mod pallet { } #[pallet::pallet] + #[pallet::without_storage_info] pub struct Pallet(PhantomData); #[pallet::hooks] diff --git a/frame/bounties/src/lib.rs b/frame/bounties/src/lib.rs index d71b58f05882..d46180f6bbe1 100644 --- a/frame/bounties/src/lib.rs +++ b/frame/bounties/src/lib.rs @@ -180,6 +180,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] pub struct Pallet(_); #[pallet::config] diff --git a/frame/child-bounties/src/lib.rs b/frame/child-bounties/src/lib.rs index 6bdc1865b841..36acc7766bf6 100644 --- a/frame/child-bounties/src/lib.rs +++ b/frame/child-bounties/src/lib.rs @@ -130,7 +130,6 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] - #[pallet::generate_storage_info] pub struct Pallet(_); #[pallet::config] diff --git a/frame/collective/src/lib.rs b/frame/collective/src/lib.rs index 3f423f35b7e5..3e3b923d6ee3 100644 --- a/frame/collective/src/lib.rs +++ b/frame/collective/src/lib.rs @@ -172,6 +172,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] #[pallet::storage_version(STORAGE_VERSION)] + #[pallet::without_storage_info] pub struct Pallet(PhantomData<(T, I)>); #[pallet::config] diff --git a/frame/contracts/src/lib.rs b/frame/contracts/src/lib.rs index 36b0e12dcd7f..e57b88c5d038 100644 --- a/frame/contracts/src/lib.rs +++ b/frame/contracts/src/lib.rs @@ -303,6 +303,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::storage_version(STORAGE_VERSION)] + #[pallet::without_storage_info] pub struct Pallet(PhantomData); #[pallet::hooks] diff --git a/frame/democracy/src/lib.rs b/frame/democracy/src/lib.rs index 1e5f3c403006..1c052ad2d417 100644 --- a/frame/democracy/src/lib.rs +++ b/frame/democracy/src/lib.rs @@ -246,6 +246,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] pub struct Pallet(_); #[pallet::config] diff --git a/frame/election-provider-multi-phase/src/lib.rs b/frame/election-provider-multi-phase/src/lib.rs index 8087d22cffe6..4716bcd6c859 100644 --- a/frame/election-provider-multi-phase/src/lib.rs +++ b/frame/election-provider-multi-phase/src/lib.rs @@ -1205,6 +1205,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] pub struct Pallet(PhantomData); } diff --git a/frame/elections-phragmen/src/lib.rs b/frame/elections-phragmen/src/lib.rs index 1e8f61f6b268..7f576144d136 100644 --- a/frame/elections-phragmen/src/lib.rs +++ b/frame/elections-phragmen/src/lib.rs @@ -250,6 +250,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] #[pallet::storage_version(STORAGE_VERSION)] + #[pallet::without_storage_info] pub struct Pallet(PhantomData); #[pallet::hooks] diff --git a/frame/examples/offchain-worker/src/lib.rs b/frame/examples/offchain-worker/src/lib.rs index 764f6cb9e2d7..08f449f8d51d 100644 --- a/frame/examples/offchain-worker/src/lib.rs +++ b/frame/examples/offchain-worker/src/lib.rs @@ -158,6 +158,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] pub struct Pallet(_); #[pallet::hooks] diff --git a/frame/examples/parallel/src/lib.rs b/frame/examples/parallel/src/lib.rs index 4ea52173a09a..7b8948c2ebd0 100644 --- a/frame/examples/parallel/src/lib.rs +++ b/frame/examples/parallel/src/lib.rs @@ -48,6 +48,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] pub struct Pallet(_); /// A public part of the pallet. diff --git a/frame/gilt/src/lib.rs b/frame/gilt/src/lib.rs index 4fd18626d931..6211b15d8c8c 100644 --- a/frame/gilt/src/lib.rs +++ b/frame/gilt/src/lib.rs @@ -178,6 +178,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] pub struct Pallet(_); /// A single bid on a gilt, an item of a *queue* in `Queues`. diff --git a/frame/grandpa/src/lib.rs b/frame/grandpa/src/lib.rs index 1f6139cf81fd..0aaf0f679ce1 100644 --- a/frame/grandpa/src/lib.rs +++ b/frame/grandpa/src/lib.rs @@ -83,7 +83,6 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] #[pallet::storage_version(STORAGE_VERSION)] - #[pallet::generate_storage_info] pub struct Pallet(_); #[pallet::config] diff --git a/frame/identity/src/lib.rs b/frame/identity/src/lib.rs index a2516a1e874e..51e63541a89b 100644 --- a/frame/identity/src/lib.rs +++ b/frame/identity/src/lib.rs @@ -152,7 +152,6 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] - #[pallet::generate_storage_info] pub struct Pallet(_); /// Information that is pertinent to identify the entity behind an account. diff --git a/frame/im-online/src/lib.rs b/frame/im-online/src/lib.rs index c9377cd274ad..5ad27850a2c1 100644 --- a/frame/im-online/src/lib.rs +++ b/frame/im-online/src/lib.rs @@ -315,7 +315,6 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] - #[pallet::generate_storage_info] pub struct Pallet(_); #[pallet::config] diff --git a/frame/indices/src/lib.rs b/frame/indices/src/lib.rs index 0aa931559e0a..7d23fa5e8c7f 100644 --- a/frame/indices/src/lib.rs +++ b/frame/indices/src/lib.rs @@ -74,6 +74,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] pub struct Pallet(PhantomData); #[pallet::call] diff --git a/frame/lottery/src/lib.rs b/frame/lottery/src/lib.rs index b04dbc845568..c9a508372ca8 100644 --- a/frame/lottery/src/lib.rs +++ b/frame/lottery/src/lib.rs @@ -124,7 +124,6 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] - #[pallet::generate_storage_info] pub struct Pallet(_); /// The pallet's config trait. diff --git a/frame/membership/src/lib.rs b/frame/membership/src/lib.rs index 016c4b39851a..e8256fab83af 100644 --- a/frame/membership/src/lib.rs +++ b/frame/membership/src/lib.rs @@ -46,6 +46,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] #[pallet::storage_version(STORAGE_VERSION)] + #[pallet::without_storage_info] pub struct Pallet(PhantomData<(T, I)>); #[pallet::config] diff --git a/frame/merkle-mountain-range/src/lib.rs b/frame/merkle-mountain-range/src/lib.rs index 0f5fe751bbd9..2a93dc7af289 100644 --- a/frame/merkle-mountain-range/src/lib.rs +++ b/frame/merkle-mountain-range/src/lib.rs @@ -84,6 +84,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] pub struct Pallet(PhantomData<(T, I)>); /// This pallet's configuration trait diff --git a/frame/multisig/src/lib.rs b/frame/multisig/src/lib.rs index 16ee1c500096..cd59ea881739 100644 --- a/frame/multisig/src/lib.rs +++ b/frame/multisig/src/lib.rs @@ -153,6 +153,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] pub struct Pallet(_); /// The set of open multisig operations. diff --git a/frame/nicks/src/lib.rs b/frame/nicks/src/lib.rs index 24d80f5a9521..9e4ecf8b2b1a 100644 --- a/frame/nicks/src/lib.rs +++ b/frame/nicks/src/lib.rs @@ -114,6 +114,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] pub struct Pallet(_); #[pallet::call] diff --git a/frame/node-authorization/src/lib.rs b/frame/node-authorization/src/lib.rs index 87ec3973d0a8..07f2e9de37dd 100644 --- a/frame/node-authorization/src/lib.rs +++ b/frame/node-authorization/src/lib.rs @@ -57,6 +57,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] pub struct Pallet(_); /// The module configuration trait diff --git a/frame/offences/src/lib.rs b/frame/offences/src/lib.rs index c12f0d1bcc78..6119fce7769e 100644 --- a/frame/offences/src/lib.rs +++ b/frame/offences/src/lib.rs @@ -50,6 +50,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] pub struct Pallet(_); /// The pallet's config trait. diff --git a/frame/preimage/src/lib.rs b/frame/preimage/src/lib.rs index 7564629bad29..c34057a1034d 100644 --- a/frame/preimage/src/lib.rs +++ b/frame/preimage/src/lib.rs @@ -100,7 +100,6 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] - #[pallet::generate_storage_info] pub struct Pallet(PhantomData); #[pallet::event] diff --git a/frame/proxy/src/lib.rs b/frame/proxy/src/lib.rs index 68aa580bfe7f..425af1836785 100644 --- a/frame/proxy/src/lib.rs +++ b/frame/proxy/src/lib.rs @@ -102,7 +102,6 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] - #[pallet::generate_storage_info] pub struct Pallet(_); /// Configuration trait. diff --git a/frame/randomness-collective-flip/src/lib.rs b/frame/randomness-collective-flip/src/lib.rs index fbc8aaaa7ec5..a74c58405de4 100644 --- a/frame/randomness-collective-flip/src/lib.rs +++ b/frame/randomness-collective-flip/src/lib.rs @@ -91,6 +91,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] pub struct Pallet(_); #[pallet::config] diff --git a/frame/recovery/src/lib.rs b/frame/recovery/src/lib.rs index b0505cbb7daf..f5a57843a983 100644 --- a/frame/recovery/src/lib.rs +++ b/frame/recovery/src/lib.rs @@ -212,6 +212,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] pub struct Pallet(_); /// Configuration trait. diff --git a/frame/scheduler/src/lib.rs b/frame/scheduler/src/lib.rs index 4fd5d50a4de0..7ecd9024e9f9 100644 --- a/frame/scheduler/src/lib.rs +++ b/frame/scheduler/src/lib.rs @@ -203,6 +203,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] pub struct Pallet(_); /// `system::Config` should always be included in our implied traits. diff --git a/frame/scored-pool/src/lib.rs b/frame/scored-pool/src/lib.rs index e95786e0c08f..3f0674d720ef 100644 --- a/frame/scored-pool/src/lib.rs +++ b/frame/scored-pool/src/lib.rs @@ -129,6 +129,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] pub struct Pallet(_); #[pallet::config] diff --git a/frame/session/src/lib.rs b/frame/session/src/lib.rs index 7a0783718705..4cf793a9b473 100644 --- a/frame/session/src/lib.rs +++ b/frame/session/src/lib.rs @@ -373,6 +373,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] #[pallet::storage_version(STORAGE_VERSION)] + #[pallet::without_storage_info] pub struct Pallet(_); #[pallet::config] diff --git a/frame/society/src/lib.rs b/frame/society/src/lib.rs index 3d2814ad5232..a9f83094fd49 100644 --- a/frame/society/src/lib.rs +++ b/frame/society/src/lib.rs @@ -371,6 +371,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] pub struct Pallet(_); #[pallet::config] diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 8444034ad49d..20864e4829e6 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -56,6 +56,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(crate) trait Store)] + #[pallet::without_storage_info] pub struct Pallet(_); #[pallet::config] diff --git a/frame/sudo/src/lib.rs b/frame/sudo/src/lib.rs index d57c75f23f5a..d9e72b37f297 100644 --- a/frame/sudo/src/lib.rs +++ b/frame/sudo/src/lib.rs @@ -121,7 +121,6 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] - #[pallet::generate_storage_info] pub struct Pallet(PhantomData); #[pallet::call] diff --git a/frame/sudo/src/mock.rs b/frame/sudo/src/mock.rs index e6af6978f8c8..410807789069 100644 --- a/frame/sudo/src/mock.rs +++ b/frame/sudo/src/mock.rs @@ -45,6 +45,7 @@ pub mod logger { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] pub struct Pallet(PhantomData); #[pallet::call] diff --git a/frame/support/procedural/src/pallet/expand/pallet_struct.rs b/frame/support/procedural/src/pallet/expand/pallet_struct.rs index 5ec10d733e5e..61c6d001a6f9 100644 --- a/frame/support/procedural/src/pallet/expand/pallet_struct.rs +++ b/frame/support/procedural/src/pallet/expand/pallet_struct.rs @@ -99,19 +99,19 @@ pub fn expand_pallet_struct(def: &mut Def) -> proc_macro2::TokenStream { }; let storage_info_span = - def.pallet_struct.generate_storage_info.unwrap_or(def.pallet_struct.attr_span); + def.pallet_struct.without_storage_info.unwrap_or(def.pallet_struct.attr_span); let storage_names = &def.storages.iter().map(|storage| &storage.ident).collect::>(); let storage_cfg_attrs = &def.storages.iter().map(|storage| &storage.cfg_attrs).collect::>(); - // Depending on the flag `generate_storage_info` and the storage attribute `unbounded`, we use + // Depending on the flag `without_storage_info` and the storage attribute `unbounded`, we use // partial or full storage info from storage. let storage_info_traits = &def .storages .iter() .map(|storage| { - if storage.unbounded || def.pallet_struct.generate_storage_info.is_none() { + if storage.unbounded || def.pallet_struct.without_storage_info.is_some() { quote::quote_spanned!(storage_info_span => PartialStorageInfoTrait) } else { quote::quote_spanned!(storage_info_span => StorageInfoTrait) @@ -123,7 +123,7 @@ pub fn expand_pallet_struct(def: &mut Def) -> proc_macro2::TokenStream { .storages .iter() .map(|storage| { - if storage.unbounded || def.pallet_struct.generate_storage_info.is_none() { + if storage.unbounded || def.pallet_struct.without_storage_info.is_some() { quote::quote_spanned!(storage_info_span => partial_storage_info) } else { quote::quote_spanned!(storage_info_span => storage_info) diff --git a/frame/support/procedural/src/pallet/parse/pallet_struct.rs b/frame/support/procedural/src/pallet/parse/pallet_struct.rs index 19d2811687d2..d98862be8f78 100644 --- a/frame/support/procedural/src/pallet/parse/pallet_struct.rs +++ b/frame/support/procedural/src/pallet/parse/pallet_struct.rs @@ -24,7 +24,7 @@ mod keyword { syn::custom_keyword!(pallet); syn::custom_keyword!(Pallet); syn::custom_keyword!(generate_store); - syn::custom_keyword!(generate_storage_info); + syn::custom_keyword!(without_storage_info); syn::custom_keyword!(storage_version); syn::custom_keyword!(Store); } @@ -43,18 +43,18 @@ pub struct PalletStructDef { pub attr_span: proc_macro2::Span, /// Whether to specify the storages max encoded len when implementing `StorageInfoTrait`. /// Contains the span of the attribute. - pub generate_storage_info: Option, + pub without_storage_info: Option, /// The current storage version of the pallet. pub storage_version: Option, } /// Parse for one variant of: /// * `#[pallet::generate_store($vis trait Store)]` -/// * `#[pallet::generate_storage_info]` +/// * `#[pallet::without_storage_info]` /// * `#[pallet::storage_version(STORAGE_VERSION)]` pub enum PalletStructAttr { GenerateStore { span: proc_macro2::Span, vis: syn::Visibility, keyword: keyword::Store }, - GenerateStorageInfoTrait(proc_macro2::Span), + WithoutStorageInfoTrait(proc_macro2::Span), StorageVersion { storage_version: syn::Path, span: proc_macro2::Span }, } @@ -62,7 +62,7 @@ impl PalletStructAttr { fn span(&self) -> proc_macro2::Span { match self { Self::GenerateStore { span, .. } => *span, - Self::GenerateStorageInfoTrait(span) => *span, + Self::WithoutStorageInfoTrait(span) => *span, Self::StorageVersion { span, .. } => *span, } } @@ -86,9 +86,9 @@ impl syn::parse::Parse for PalletStructAttr { generate_content.parse::()?; let keyword = generate_content.parse::()?; Ok(Self::GenerateStore { vis, keyword, span }) - } else if lookahead.peek(keyword::generate_storage_info) { - let span = content.parse::()?.span(); - Ok(Self::GenerateStorageInfoTrait(span)) + } else if lookahead.peek(keyword::without_storage_info) { + let span = content.parse::()?.span(); + Ok(Self::WithoutStorageInfoTrait(span)) } else if lookahead.peek(keyword::storage_version) { let span = content.parse::()?.span(); @@ -117,7 +117,7 @@ impl PalletStructDef { }; let mut store = None; - let mut generate_storage_info = None; + let mut without_storage_info = None; let mut storage_version_found = None; let struct_attrs: Vec = helper::take_item_pallet_attrs(&mut item.attrs)?; @@ -126,10 +126,10 @@ impl PalletStructDef { PalletStructAttr::GenerateStore { vis, keyword, .. } if store.is_none() => { store = Some((vis, keyword)); }, - PalletStructAttr::GenerateStorageInfoTrait(span) - if generate_storage_info.is_none() => + PalletStructAttr::WithoutStorageInfoTrait(span) + if without_storage_info.is_none() => { - generate_storage_info = Some(span); + without_storage_info = Some(span); }, PalletStructAttr::StorageVersion { storage_version, .. } if storage_version_found.is_none() => @@ -164,7 +164,7 @@ impl PalletStructDef { pallet, store, attr_span, - generate_storage_info, + without_storage_info, storage_version: storage_version_found, }) } diff --git a/frame/support/src/lib.rs b/frame/support/src/lib.rs index 64bca7262829..fc2754c5c555 100644 --- a/frame/support/src/lib.rs +++ b/frame/support/src/lib.rs @@ -1967,7 +1967,7 @@ pub mod pallet_prelude { /// pub trait Config: frame_system::Config { /// #[pallet::constant] // put the constant in metadata /// type MyGetParam: Get; -/// type Balance: Parameter + From; +/// type Balance: Parameter + MaxEncodedLen + From; /// type Event: From> + IsType<::Event>; /// } /// @@ -2156,7 +2156,7 @@ pub mod pallet_prelude { /// pub trait Config: frame_system::Config { /// #[pallet::constant] /// type MyGetParam: Get; -/// type Balance: Parameter + From; +/// type Balance: Parameter + MaxEncodedLen + From; /// type Event: From> + IsType<::Event>; /// } /// diff --git a/frame/support/test/tests/pallet.rs b/frame/support/test/tests/pallet.rs index 5f9e886dbb67..2cb7b283b66f 100644 --- a/frame/support/test/tests/pallet.rs +++ b/frame/support/test/tests/pallet.rs @@ -156,7 +156,6 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(crate) trait Store)] - #[pallet::generate_storage_info] #[pallet::storage_version(STORAGE_VERSION)] pub struct Pallet(_); @@ -450,6 +449,7 @@ pub mod pallet2 { #[pallet::pallet] #[pallet::generate_store(pub(crate) trait Store)] + #[pallet::without_storage_info] pub struct Pallet(_); #[pallet::hooks] diff --git a/frame/support/test/tests/pallet_compatibility.rs b/frame/support/test/tests/pallet_compatibility.rs index 339a8b6b0924..9327f5b6a330 100644 --- a/frame/support/test/tests/pallet_compatibility.rs +++ b/frame/support/test/tests/pallet_compatibility.rs @@ -124,6 +124,7 @@ pub mod pallet { } #[pallet::pallet] + #[pallet::without_storage_info] pub struct Pallet(_); #[pallet::hooks] diff --git a/frame/support/test/tests/pallet_compatibility_instance.rs b/frame/support/test/tests/pallet_compatibility_instance.rs index 4fe577f520fa..3de45df22367 100644 --- a/frame/support/test/tests/pallet_compatibility_instance.rs +++ b/frame/support/test/tests/pallet_compatibility_instance.rs @@ -109,6 +109,7 @@ pub mod pallet { } #[pallet::pallet] + #[pallet::without_storage_info] pub struct Pallet(PhantomData<(T, I)>); #[pallet::hooks] diff --git a/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.rs b/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.rs index 30b6d651f3b8..fe4682c401fa 100644 --- a/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.rs +++ b/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.rs @@ -7,6 +7,7 @@ mod pallet { pub trait Config: frame_system::Config {} #[pallet::pallet] + #[pallet::without_storage_info] pub struct Pallet(core::marker::PhantomData); #[pallet::hooks] diff --git a/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.stderr b/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.stderr index 82fd3ad884f9..35f8bbdbd524 100644 --- a/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.stderr +++ b/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.stderr @@ -1,97 +1,97 @@ error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied - --> $DIR/storage_ensure_span_are_ok_on_wrong_gen.rs:9:12 + --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.rs:10:12 | -9 | #[pallet::pallet] - | ^^^^^^ the trait `WrapperTypeDecode` is not implemented for `Bar` +10 | #[pallet::without_storage_info] + | ^^^^^^^^^^^^^^^^^^^^ the trait `WrapperTypeDecode` is not implemented for `Bar` | = note: required because of the requirements on the impl of `Decode` for `Bar` = note: required because of the requirements on the impl of `FullCodec` for `Bar` = note: required because of the requirements on the impl of `PartialStorageInfoTrait` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` note: required by `partial_storage_info` - --> $DIR/storage.rs:88:2 + --> $WORKSPACE/frame/support/src/traits/storage.rs | -88 | fn partial_storage_info() -> Vec; + | fn partial_storage_info() -> Vec; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `Bar: EncodeLike` is not satisfied - --> $DIR/storage_ensure_span_are_ok_on_wrong_gen.rs:9:12 + --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.rs:10:12 | -9 | #[pallet::pallet] - | ^^^^^^ the trait `EncodeLike` is not implemented for `Bar` +10 | #[pallet::without_storage_info] + | ^^^^^^^^^^^^^^^^^^^^ the trait `EncodeLike` is not implemented for `Bar` | = note: required because of the requirements on the impl of `FullEncode` for `Bar` = note: required because of the requirements on the impl of `FullCodec` for `Bar` = note: required because of the requirements on the impl of `PartialStorageInfoTrait` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` note: required by `partial_storage_info` - --> $DIR/storage.rs:88:2 + --> $WORKSPACE/frame/support/src/traits/storage.rs | -88 | fn partial_storage_info() -> Vec; + | fn partial_storage_info() -> Vec; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied - --> $DIR/storage_ensure_span_are_ok_on_wrong_gen.rs:9:12 + --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.rs:10:12 | -9 | #[pallet::pallet] - | ^^^^^^ the trait `WrapperTypeEncode` is not implemented for `Bar` +10 | #[pallet::without_storage_info] + | ^^^^^^^^^^^^^^^^^^^^ the trait `WrapperTypeEncode` is not implemented for `Bar` | = note: required because of the requirements on the impl of `Encode` for `Bar` = note: required because of the requirements on the impl of `FullEncode` for `Bar` = note: required because of the requirements on the impl of `FullCodec` for `Bar` = note: required because of the requirements on the impl of `PartialStorageInfoTrait` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` note: required by `partial_storage_info` - --> $DIR/storage.rs:88:2 + --> $WORKSPACE/frame/support/src/traits/storage.rs | -88 | fn partial_storage_info() -> Vec; + | fn partial_storage_info() -> Vec; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `Bar: TypeInfo` is not satisfied - --> $DIR/storage_ensure_span_are_ok_on_wrong_gen.rs:20:12 + --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.rs:21:12 | -20 | #[pallet::storage] +21 | #[pallet::storage] | ^^^^^^^ the trait `TypeInfo` is not implemented for `Bar` | = note: required because of the requirements on the impl of `StaticTypeInfo` for `Bar` = note: required because of the requirements on the impl of `StorageEntryMetadataBuilder` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` note: required by `build_metadata` - --> $DIR/mod.rs:113:2 + --> $WORKSPACE/frame/support/src/storage/types/mod.rs | -113 | fn build_metadata(doc: Vec<&'static str>, entries: &mut Vec); + | fn build_metadata(doc: Vec<&'static str>, entries: &mut Vec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied - --> $DIR/storage_ensure_span_are_ok_on_wrong_gen.rs:20:12 + --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.rs:21:12 | -20 | #[pallet::storage] +21 | #[pallet::storage] | ^^^^^^^ the trait `WrapperTypeDecode` is not implemented for `Bar` | = note: required because of the requirements on the impl of `Decode` for `Bar` = note: required because of the requirements on the impl of `FullCodec` for `Bar` = note: required because of the requirements on the impl of `StorageEntryMetadataBuilder` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` note: required by `build_metadata` - --> $DIR/mod.rs:113:2 + --> $WORKSPACE/frame/support/src/storage/types/mod.rs | -113 | fn build_metadata(doc: Vec<&'static str>, entries: &mut Vec); + | fn build_metadata(doc: Vec<&'static str>, entries: &mut Vec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `Bar: EncodeLike` is not satisfied - --> $DIR/storage_ensure_span_are_ok_on_wrong_gen.rs:20:12 + --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.rs:21:12 | -20 | #[pallet::storage] +21 | #[pallet::storage] | ^^^^^^^ the trait `EncodeLike` is not implemented for `Bar` | = note: required because of the requirements on the impl of `FullEncode` for `Bar` = note: required because of the requirements on the impl of `FullCodec` for `Bar` = note: required because of the requirements on the impl of `StorageEntryMetadataBuilder` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` note: required by `build_metadata` - --> $DIR/mod.rs:113:2 + --> $WORKSPACE/frame/support/src/storage/types/mod.rs | -113 | fn build_metadata(doc: Vec<&'static str>, entries: &mut Vec); + | fn build_metadata(doc: Vec<&'static str>, entries: &mut Vec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied - --> $DIR/storage_ensure_span_are_ok_on_wrong_gen.rs:20:12 + --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.rs:21:12 | -20 | #[pallet::storage] +21 | #[pallet::storage] | ^^^^^^^ the trait `WrapperTypeEncode` is not implemented for `Bar` | = note: required because of the requirements on the impl of `Encode` for `Bar` @@ -99,7 +99,7 @@ error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied = note: required because of the requirements on the impl of `FullCodec` for `Bar` = note: required because of the requirements on the impl of `StorageEntryMetadataBuilder` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` note: required by `build_metadata` - --> $DIR/mod.rs:113:2 + --> $WORKSPACE/frame/support/src/storage/types/mod.rs | -113 | fn build_metadata(doc: Vec<&'static str>, entries: &mut Vec); + | fn build_metadata(doc: Vec<&'static str>, entries: &mut Vec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs b/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs index ddb19121660d..82512a89fb15 100644 --- a/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs +++ b/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs @@ -7,6 +7,7 @@ mod pallet { pub trait Config: frame_system::Config {} #[pallet::pallet] + #[pallet::without_storage_info] pub struct Pallet(core::marker::PhantomData); #[pallet::hooks] diff --git a/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.stderr b/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.stderr index eb1404fc62c3..b5f250bb8971 100644 --- a/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.stderr +++ b/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.stderr @@ -1,97 +1,97 @@ error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied - --> $DIR/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs:9:12 + --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs:10:12 | -9 | #[pallet::pallet] - | ^^^^^^ the trait `WrapperTypeDecode` is not implemented for `Bar` +10 | #[pallet::without_storage_info] + | ^^^^^^^^^^^^^^^^^^^^ the trait `WrapperTypeDecode` is not implemented for `Bar` | = note: required because of the requirements on the impl of `Decode` for `Bar` = note: required because of the requirements on the impl of `FullCodec` for `Bar` = note: required because of the requirements on the impl of `PartialStorageInfoTrait` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` note: required by `partial_storage_info` - --> $DIR/storage.rs:88:2 + --> $WORKSPACE/frame/support/src/traits/storage.rs | -88 | fn partial_storage_info() -> Vec; + | fn partial_storage_info() -> Vec; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `Bar: EncodeLike` is not satisfied - --> $DIR/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs:9:12 + --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs:10:12 | -9 | #[pallet::pallet] - | ^^^^^^ the trait `EncodeLike` is not implemented for `Bar` +10 | #[pallet::without_storage_info] + | ^^^^^^^^^^^^^^^^^^^^ the trait `EncodeLike` is not implemented for `Bar` | = note: required because of the requirements on the impl of `FullEncode` for `Bar` = note: required because of the requirements on the impl of `FullCodec` for `Bar` = note: required because of the requirements on the impl of `PartialStorageInfoTrait` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` note: required by `partial_storage_info` - --> $DIR/storage.rs:88:2 + --> $WORKSPACE/frame/support/src/traits/storage.rs | -88 | fn partial_storage_info() -> Vec; + | fn partial_storage_info() -> Vec; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied - --> $DIR/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs:9:12 + --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs:10:12 | -9 | #[pallet::pallet] - | ^^^^^^ the trait `WrapperTypeEncode` is not implemented for `Bar` +10 | #[pallet::without_storage_info] + | ^^^^^^^^^^^^^^^^^^^^ the trait `WrapperTypeEncode` is not implemented for `Bar` | = note: required because of the requirements on the impl of `Encode` for `Bar` = note: required because of the requirements on the impl of `FullEncode` for `Bar` = note: required because of the requirements on the impl of `FullCodec` for `Bar` = note: required because of the requirements on the impl of `PartialStorageInfoTrait` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` note: required by `partial_storage_info` - --> $DIR/storage.rs:88:2 + --> $WORKSPACE/frame/support/src/traits/storage.rs | -88 | fn partial_storage_info() -> Vec; + | fn partial_storage_info() -> Vec; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `Bar: TypeInfo` is not satisfied - --> $DIR/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs:20:12 + --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs:21:12 | -20 | #[pallet::storage] +21 | #[pallet::storage] | ^^^^^^^ the trait `TypeInfo` is not implemented for `Bar` | = note: required because of the requirements on the impl of `StaticTypeInfo` for `Bar` = note: required because of the requirements on the impl of `StorageEntryMetadataBuilder` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` note: required by `build_metadata` - --> $DIR/mod.rs:113:2 + --> $WORKSPACE/frame/support/src/storage/types/mod.rs | -113 | fn build_metadata(doc: Vec<&'static str>, entries: &mut Vec); + | fn build_metadata(doc: Vec<&'static str>, entries: &mut Vec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied - --> $DIR/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs:20:12 + --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs:21:12 | -20 | #[pallet::storage] +21 | #[pallet::storage] | ^^^^^^^ the trait `WrapperTypeDecode` is not implemented for `Bar` | = note: required because of the requirements on the impl of `Decode` for `Bar` = note: required because of the requirements on the impl of `FullCodec` for `Bar` = note: required because of the requirements on the impl of `StorageEntryMetadataBuilder` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` note: required by `build_metadata` - --> $DIR/mod.rs:113:2 + --> $WORKSPACE/frame/support/src/storage/types/mod.rs | -113 | fn build_metadata(doc: Vec<&'static str>, entries: &mut Vec); + | fn build_metadata(doc: Vec<&'static str>, entries: &mut Vec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `Bar: EncodeLike` is not satisfied - --> $DIR/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs:20:12 + --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs:21:12 | -20 | #[pallet::storage] +21 | #[pallet::storage] | ^^^^^^^ the trait `EncodeLike` is not implemented for `Bar` | = note: required because of the requirements on the impl of `FullEncode` for `Bar` = note: required because of the requirements on the impl of `FullCodec` for `Bar` = note: required because of the requirements on the impl of `StorageEntryMetadataBuilder` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` note: required by `build_metadata` - --> $DIR/mod.rs:113:2 + --> $WORKSPACE/frame/support/src/storage/types/mod.rs | -113 | fn build_metadata(doc: Vec<&'static str>, entries: &mut Vec); + | fn build_metadata(doc: Vec<&'static str>, entries: &mut Vec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied - --> $DIR/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs:20:12 + --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs:21:12 | -20 | #[pallet::storage] +21 | #[pallet::storage] | ^^^^^^^ the trait `WrapperTypeEncode` is not implemented for `Bar` | = note: required because of the requirements on the impl of `Encode` for `Bar` @@ -99,7 +99,7 @@ error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied = note: required because of the requirements on the impl of `FullCodec` for `Bar` = note: required because of the requirements on the impl of `StorageEntryMetadataBuilder` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` note: required by `build_metadata` - --> $DIR/mod.rs:113:2 + --> $WORKSPACE/frame/support/src/storage/types/mod.rs | -113 | fn build_metadata(doc: Vec<&'static str>, entries: &mut Vec); + | fn build_metadata(doc: Vec<&'static str>, entries: &mut Vec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/frame/support/test/tests/pallet_ui/storage_info_unsatisfied.rs b/frame/support/test/tests/pallet_ui/storage_info_unsatisfied.rs index 76e356610064..4d43e3a17a9e 100644 --- a/frame/support/test/tests/pallet_ui/storage_info_unsatisfied.rs +++ b/frame/support/test/tests/pallet_ui/storage_info_unsatisfied.rs @@ -7,7 +7,6 @@ mod pallet { pub trait Config: frame_system::Config {} #[pallet::pallet] - #[pallet::generate_storage_info] pub struct Pallet(core::marker::PhantomData); #[pallet::hooks] diff --git a/frame/support/test/tests/pallet_ui/storage_info_unsatisfied.stderr b/frame/support/test/tests/pallet_ui/storage_info_unsatisfied.stderr index 0ffb015e36bc..35537cfbc9e0 100644 --- a/frame/support/test/tests/pallet_ui/storage_info_unsatisfied.stderr +++ b/frame/support/test/tests/pallet_ui/storage_info_unsatisfied.stderr @@ -1,12 +1,12 @@ error[E0277]: the trait bound `Bar: MaxEncodedLen` is not satisfied - --> $DIR/storage_info_unsatisfied.rs:10:12 + --> tests/pallet_ui/storage_info_unsatisfied.rs:9:12 | -10 | #[pallet::generate_storage_info] - | ^^^^^^^^^^^^^^^^^^^^^ the trait `MaxEncodedLen` is not implemented for `Bar` +9 | #[pallet::pallet] + | ^^^^^^ the trait `MaxEncodedLen` is not implemented for `Bar` | = note: required because of the requirements on the impl of `StorageInfoTrait` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` note: required by `storage_info` - --> $DIR/storage.rs:71:2 + --> $WORKSPACE/frame/support/src/traits/storage.rs | -71 | fn storage_info() -> Vec; + | fn storage_info() -> Vec; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.rs b/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.rs index 15456c78e9ba..dd10bc0723fe 100644 --- a/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.rs +++ b/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.rs @@ -10,7 +10,6 @@ mod pallet { pub trait Config: frame_system::Config {} #[pallet::pallet] - #[pallet::generate_storage_info] pub struct Pallet(core::marker::PhantomData); #[pallet::hooks] diff --git a/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr b/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr index cb9a0bd55989..fb6580bb5a3e 100644 --- a/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr +++ b/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `Bar: MaxEncodedLen` is not satisfied - --> tests/pallet_ui/storage_info_unsatisfied_nmap.rs:13:12 + --> tests/pallet_ui/storage_info_unsatisfied_nmap.rs:12:12 | -13 | #[pallet::generate_storage_info] - | ^^^^^^^^^^^^^^^^^^^^^ the trait `MaxEncodedLen` is not implemented for `Bar` +12 | #[pallet::pallet] + | ^^^^^^ the trait `MaxEncodedLen` is not implemented for `Bar` | = note: required because of the requirements on the impl of `KeyGeneratorMaxEncodedLen` for `Key` = note: required because of the requirements on the impl of `StorageInfoTrait` for `frame_support::pallet_prelude::StorageNMap<_GeneratedPrefixForStorageFoo, Key, u32>` diff --git a/frame/system/src/lib.rs b/frame/system/src/lib.rs index 7615424ba57e..800ffbfd20dc 100644 --- a/frame/system/src/lib.rs +++ b/frame/system/src/lib.rs @@ -351,6 +351,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub (super) trait Store)] + #[pallet::without_storage_info] pub struct Pallet(_); #[pallet::hooks] diff --git a/frame/timestamp/src/lib.rs b/frame/timestamp/src/lib.rs index a0b9babcd984..d8bfb405e5c7 100644 --- a/frame/timestamp/src/lib.rs +++ b/frame/timestamp/src/lib.rs @@ -148,7 +148,6 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] - #[pallet::generate_storage_info] pub struct Pallet(PhantomData); /// Current time for the current block. diff --git a/frame/tips/src/lib.rs b/frame/tips/src/lib.rs index 7761800638d3..ae320629dfc3 100644 --- a/frame/tips/src/lib.rs +++ b/frame/tips/src/lib.rs @@ -120,6 +120,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] #[pallet::storage_version(STORAGE_VERSION)] + #[pallet::without_storage_info] pub struct Pallet(_); #[pallet::config] diff --git a/frame/transaction-payment/src/lib.rs b/frame/transaction-payment/src/lib.rs index 8bda316c501a..16d2ff5827c4 100644 --- a/frame/transaction-payment/src/lib.rs +++ b/frame/transaction-payment/src/lib.rs @@ -248,6 +248,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] pub struct Pallet(_); #[pallet::config] diff --git a/frame/transaction-storage/src/lib.rs b/frame/transaction-storage/src/lib.rs index 23cc9ee0a238..d95a60b49512 100644 --- a/frame/transaction-storage/src/lib.rs +++ b/frame/transaction-storage/src/lib.rs @@ -129,6 +129,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] pub struct Pallet(_); #[pallet::hooks] diff --git a/frame/treasury/src/lib.rs b/frame/treasury/src/lib.rs index c2dd59953be3..762c0e592d89 100644 --- a/frame/treasury/src/lib.rs +++ b/frame/treasury/src/lib.rs @@ -139,7 +139,6 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] - #[pallet::generate_storage_info] pub struct Pallet(PhantomData<(T, I)>); #[pallet::config] diff --git a/frame/uniques/src/lib.rs b/frame/uniques/src/lib.rs index dde30920b227..6b05aaeec296 100644 --- a/frame/uniques/src/lib.rs +++ b/frame/uniques/src/lib.rs @@ -62,6 +62,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] pub struct Pallet(_); #[pallet::config] diff --git a/frame/vesting/src/lib.rs b/frame/vesting/src/lib.rs index dfd7fa094c96..747521f4fa53 100644 --- a/frame/vesting/src/lib.rs +++ b/frame/vesting/src/lib.rs @@ -203,7 +203,6 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] - #[pallet::generate_storage_info] pub struct Pallet(_); #[pallet::genesis_config] From 49c2268cf871f34a8d73e943ee2e92afe865da16 Mon Sep 17 00:00:00 2001 From: driemworks Date: Thu, 20 Jan 2022 10:38:28 -0600 Subject: [PATCH 405/695] move OCW functionality to iris-session pallet --- .../pallets/iris-assets/src/lib.rs | 26 +++--------- .../pallets/iris-session/src/lib.rs | 41 +++++++++++++------ 2 files changed, 33 insertions(+), 34 deletions(-) diff --git a/bin/node-template/pallets/iris-assets/src/lib.rs b/bin/node-template/pallets/iris-assets/src/lib.rs index 7153314eb2f6..458a6e2eec00 100644 --- a/bin/node-template/pallets/iris-assets/src/lib.rs +++ b/bin/node-template/pallets/iris-assets/src/lib.rs @@ -64,8 +64,9 @@ use sp_std::{ pub enum DataCommand { /// (ipfs_address, cid, requesting node address, filename, asset id, balance) AddBytes(OpaqueMultiaddr, Vec, LookupSource, Vec, AssetId, Balance), - // /// owner, cid + // /// owner, cid, recipient CatBytes(AccountId, Vec, AccountId), + PinCID(), } #[derive(Encode, Decode, RuntimeDebug, Clone, Default, Eq, PartialEq, TypeInfo)] @@ -247,26 +248,9 @@ pub mod pallet { 0 } - fn offchain_worker(block_number: T::BlockNumber) { - // // every 5 blocks - // if block_number % 5u32.into() == 0u32.into() { - // if let Err(e) = Self::connection_housekeeping() { - // log::error!("IPFS: Encountered an error while processing data requests: {:?}", e); - // } - // } - - // // handle data requests each block - // if let Err(e) = Self::handle_data_requests() { - // log::error!("IPFS: Encountered an error while processing data requests: {:?}", e); - // } - - // // every 5 blocks - // if block_number % 5u32.into() == 0u32.into() { - // if let Err(e) = Self::print_metadata() { - // log::error!("IPFS: Encountered an error while obtaining metadata: {:?}", e); - // } - // } - } + // fn offchain_worker(block_number: T::BlockNumber) { + + // } } #[pallet::call] diff --git a/bin/node-template/pallets/iris-session/src/lib.rs b/bin/node-template/pallets/iris-session/src/lib.rs index a569fb95985e..11bae5787765 100644 --- a/bin/node-template/pallets/iris-session/src/lib.rs +++ b/bin/node-template/pallets/iris-session/src/lib.rs @@ -136,6 +136,17 @@ pub mod pallet { ValueQuery, >; + /// map substrate public key to ipfs public key + #[pallet::storage] + #[pallet::getter(fn substrate_ipfs_bridge)] + pub(super) type SubstrateIpfsBridge = StorageMap< + _, + Blake2_128Concat, + T::AccountId, + Vec, + ValueQuery, + >; + #[pallet::storage] #[pallet::getter(fn validators)] pub type Validators = StorageValue<_, Vec, ValueQuery>; @@ -344,7 +355,17 @@ pub mod pallet { multiaddresses: Vec, ) -> DispatchResult { let who = ensure_signed(origin)?; - >::insert(public_key.clone(), multiaddresses.clone()); + + >::insert( + public_key.clone(), + multiaddresses.clone() + ); + + >::insert( + who.clone(), + public_key.clone() + ); + Self::deposit_event(Event::PublishedIdentity(who.clone())); Ok(()) } @@ -408,12 +429,12 @@ impl Pallet { } /// Ensure the candidate validator is eligible to be a validator - /// 1) Check that it is not a duplicate - /// 2) fn approve_validator(validator_id: T::AccountId) -> DispatchResult { let approved_set: BTreeSet<_> = >::get().into_iter().collect(); ensure!(!approved_set.contains(&validator_id), Error::::Duplicate); >::mutate(|v| v.push(validator_id.clone())); + log::info!("HEY JUST WANTED TO DISPLAY IN THE LOGS WHERE THIS IS GETTING EXECUTED AND HOW FREQUENTLY SO TAHT I CAN BETTER UNDERSTAND THE FLOW"); + log::info!("HEY JUST WANTED TO DISPLAY IN THE LOGS WHERE THIS IS GETTING EXECUTED AND HOW FREQUENTLY SO TAHT I CAN BETTER UNDERSTAND THE FLOW"); // In storage pool -> move from candidate storage provider to storage provider Ok(()) } @@ -591,12 +612,6 @@ impl Pallet { ); } let results = signer.send_signed_transaction(|_account| { - // Ca::submit_ipfs_add_results{ - // admin: admin.clone(), - // cid: new_cid.clone(), - // id: id.clone(), - // balance: balance.clone(), - // } Call::submit_ipfs_add_results{ admin: admin.clone(), cid: new_cid.clone(), @@ -662,7 +677,10 @@ impl Pallet { } else { log::error!("the provided owner/cid does not map to a valid asset id: {:?}, {:?}", owner, cid) } - } + }, + DataCommand::PinCID() => { + + } } } @@ -699,9 +717,6 @@ impl pallet_session::SessionManager for Pallet { // also has the im-online pallet. Self::remove_offline_validators(); log::debug!(target: LOG_TARGET, "New session called; updated validator set provided."); - - // TODO: Need to verify that storage providers have data pinned... - Some(Self::validators()) } From 48e0b415b94d8ce14e0ebbbdb813263afa27f02e Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Thu, 20 Jan 2022 14:17:16 -0400 Subject: [PATCH 406/695] dont increase the allocated size of vec (#10701) --- frame/support/src/storage/bounded_vec.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/frame/support/src/storage/bounded_vec.rs b/frame/support/src/storage/bounded_vec.rs index 6d7206df6db1..6b20ed2bba90 100644 --- a/frame/support/src/storage/bounded_vec.rs +++ b/frame/support/src/storage/bounded_vec.rs @@ -222,16 +222,17 @@ impl> BoundedVec { /// Returns `true` if the item was inserted. pub fn force_insert_keep_left(&mut self, index: usize, element: T) -> bool { // Check against panics. - if Self::bound() < index || self.len() < index { + if Self::bound() < index || self.len() < index || Self::bound() == 0 { return false } // Noop condition. if Self::bound() == index && self.len() <= Self::bound() { return false } - // Cannot panic since self.len() >= index; + // Cannot panic since `Self.bound() > 0` + self.0.truncate(Self::bound() - 1); + // Cannot panic since `self.len() >= index`; self.0.insert(index, element); - self.0.truncate(Self::bound()); true } From 6bbc6885509430aac4b0cba4ac6c1a11fe525307 Mon Sep 17 00:00:00 2001 From: Sacha Lansky Date: Fri, 21 Jan 2022 17:28:43 +0100 Subject: [PATCH 407/695] Fix typo (#10714) --- primitives/state-machine/src/overlayed_changes/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/primitives/state-machine/src/overlayed_changes/mod.rs b/primitives/state-machine/src/overlayed_changes/mod.rs index 89bbb063ef9a..d75feec0ced9 100644 --- a/primitives/state-machine/src/overlayed_changes/mod.rs +++ b/primitives/state-machine/src/overlayed_changes/mod.rs @@ -104,7 +104,7 @@ pub struct OverlayedChanges { stats: StateMachineStats, } -/// Transcation index operation. +/// Transaction index operation. #[derive(Debug, Clone)] pub enum IndexOperation { /// Insert transaction into index. From 9247e150ca0f50841a60a213ad8b15efdbd616fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Fri, 21 Jan 2022 17:43:21 +0100 Subject: [PATCH 408/695] wasm-builder: Improve workspace handling (#10700) When building a wasm binary from a different repo inside a local workspace, we did not used the correct `Cargo.toml` to find the correct patches and features. The solution to this is to just walk up from the target directory until we find the workspace we are currently compiling. If this heuristic isn't working, we print a warning and let the user set an env variable `WASM_BUILD_WORKSPACE_HINT` to tell the `wasm-builder` where the actual workspace is. --- utils/wasm-builder/src/lib.rs | 7 ++++++ utils/wasm-builder/src/wasm_project.rs | 30 +++++++++++++++++++++----- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/utils/wasm-builder/src/lib.rs b/utils/wasm-builder/src/lib.rs index 899903d96d16..f5e04dd7d774 100644 --- a/utils/wasm-builder/src/lib.rs +++ b/utils/wasm-builder/src/lib.rs @@ -83,6 +83,10 @@ //! needs to be absolute. //! - `WASM_BUILD_TOOLCHAIN` - The toolchain that should be used to build the Wasm binaries. The //! format needs to be the same as used by cargo, e.g. `nightly-2020-02-20`. +//! - `WASM_BUILD_WORKSPACE_HINT` - Hint the workspace that is being built. This is normally not +//! required as we walk up from the target directory until we find a `Cargo.toml`. If the target +//! directory is changed for the build, this environment variable can be used to point to the +//! actual workspace. //! //! Each project can be skipped individually by using the environment variable //! `SKIP_PROJECT_NAME_WASM_BUILD`. Where `PROJECT_NAME` needs to be replaced by the name of the @@ -138,6 +142,9 @@ const WASM_BUILD_TOOLCHAIN: &str = "WASM_BUILD_TOOLCHAIN"; /// Environment variable that makes sure the WASM build is triggered. const FORCE_WASM_BUILD_ENV: &str = "FORCE_WASM_BUILD"; +/// Environment variable that hints the workspace we are building. +const WASM_BUILD_WORKSPACE_HINT: &str = "WASM_BUILD_WORKSPACE_HINT"; + /// Write to the given `file` if the `content` is different. fn write_file_if_changed(file: impl AsRef, content: impl AsRef) { if fs::read_to_string(file.as_ref()).ok().as_deref() != Some(content.as_ref()) { diff --git a/utils/wasm-builder/src/wasm_project.rs b/utils/wasm-builder/src/wasm_project.rs index cf437ee7f0e6..809a940c7406 100644 --- a/utils/wasm-builder/src/wasm_project.rs +++ b/utils/wasm-builder/src/wasm_project.rs @@ -77,6 +77,15 @@ fn crate_metadata(cargo_manifest: &Path) -> Metadata { let cargo_lock_existed = cargo_lock.exists(); + // If we can find a `Cargo.lock`, we assume that this is the workspace root and there exists a + // `Cargo.toml` that we can use for getting the metadata. + let cargo_manifest = if let Some(mut cargo_lock) = find_cargo_lock(cargo_manifest) { + cargo_lock.set_file_name("Cargo.toml"); + cargo_lock + } else { + cargo_manifest.to_path_buf() + }; + let crate_metadata = MetadataCommand::new() .manifest_path(cargo_manifest) .exec() @@ -151,18 +160,29 @@ fn find_cargo_lock(cargo_manifest: &Path) -> Option { } } - if let Some(path) = find_impl(build_helper::out_dir()) { - return Some(path) + if let Ok(workspace) = env::var(crate::WASM_BUILD_WORKSPACE_HINT) { + let path = PathBuf::from(workspace); + + if path.join("Cargo.lock").exists() { + return Some(path.join("Cargo.lock")) + } else { + build_helper::warning!( + "`{}` env variable doesn't point to a directory that contains a `Cargo.lock`.", + crate::WASM_BUILD_WORKSPACE_HINT, + ); + } } - if let Some(path) = find_impl(cargo_manifest.to_path_buf()) { + if let Some(path) = find_impl(build_helper::out_dir()) { return Some(path) } build_helper::warning!( - "Could not find `Cargo.lock` for `{}`, while searching from `{}`.", + "Could not find `Cargo.lock` for `{}`, while searching from `{}`. \ + To fix this, point the `{}` env variable to the directory of the workspace being compiled.", cargo_manifest.display(), - build_helper::out_dir().display() + build_helper::out_dir().display(), + crate::WASM_BUILD_WORKSPACE_HINT, ); None From 227a94faa19364a6beef666e736484b3ff558132 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Fri, 21 Jan 2022 18:08:35 +0100 Subject: [PATCH 409/695] Add `MaxEncodeLen` to `implement_per_thing!` (#10715) * fix doc Signed-off-by: Oliver Tale-Yazdi * Add MaxEncodedLen to implement_per_thing! Signed-off-by: Oliver Tale-Yazdi * Test that Percent et.al. can be used in Storage. Signed-off-by: Oliver Tale-Yazdi * Add comment Signed-off-by: Oliver Tale-Yazdi * Revert "Test that Percent et.al. can be used in Storage." This reverts commit 52558afea6f9b53fb07521f1b6393bc320d21dfc. * Test MaxEncodedLen in implement_per_thing! Signed-off-by: Oliver Tale-Yazdi * Revert "Add comment" This reverts commit 27a96f6e527f71a57ace289c041de514edbe9104. --- frame/support/test/tests/pallet.rs | 2 +- primitives/arithmetic/src/per_things.rs | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/frame/support/test/tests/pallet.rs b/frame/support/test/tests/pallet.rs index 2cb7b283b66f..cf882556088e 100644 --- a/frame/support/test/tests/pallet.rs +++ b/frame/support/test/tests/pallet.rs @@ -432,7 +432,7 @@ pub mod pallet { } // Test that a pallet with non generic event and generic genesis_config is correctly handled -// and that a pallet without the attribute generate_storage_info is correctly handled. +// and that a pallet with the attribute without_storage_info is correctly handled. #[frame_support::pallet] pub mod pallet2 { use super::{SomeAssociation1, SomeType1}; diff --git a/primitives/arithmetic/src/per_things.rs b/primitives/arithmetic/src/per_things.rs index 21ad0dd52099..fbd45bb69324 100644 --- a/primitives/arithmetic/src/per_things.rs +++ b/primitives/arithmetic/src/per_things.rs @@ -425,7 +425,7 @@ macro_rules! implement_per_thing { /// #[doc = $title] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] - #[derive(Encode, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug, scale_info::TypeInfo)] + #[derive(Encode, Copy, Clone, PartialEq, Eq, codec::MaxEncodedLen, PartialOrd, Ord, RuntimeDebug, scale_info::TypeInfo)] pub struct $name($type); /// Implementation makes any compact encoding of `PerThing::Inner` valid, @@ -905,6 +905,15 @@ macro_rules! implement_per_thing { } } + #[test] + fn has_max_encoded_len() { + struct AsMaxEncodedLen { + _data: T, + } + + let _ = AsMaxEncodedLen { _data: $name(1) }; + } + #[test] fn fail_on_invalid_encoded_value() { let value = <$upper_type>::from($max) * 2; From af5e675dd73788f1a9629c5213252517d8fad354 Mon Sep 17 00:00:00 2001 From: Jimmy Chu Date: Sat, 22 Jan 2022 01:32:45 +0800 Subject: [PATCH 410/695] Script for publishing rustdocs at gh-pages (#10604) * wip Signed-off-by: Jimmy Chu * Added the rustdocs-release script Signed-off-by: Jimmy Chu * updated gitlab-ci script Signed-off-by: Jimmy Chu * Updated to set NIGHTLY to false by default Signed-off-by: Jimmy Chu * Added documentation Signed-off-by: Jimmy Chu --- .gitlab-ci.yml | 32 +---- .maintain/rustdocs-release.sh | 244 ++++++++++++++++++++++++++++++++++ docs/rustdocs-release.md | 20 +++ 3 files changed, 269 insertions(+), 27 deletions(-) create mode 100755 .maintain/rustdocs-release.sh create mode 100644 docs/rustdocs-release.md diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b68dd303841d..a0b71fcff02e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -747,13 +747,7 @@ publish-rustdoc: image: node:16 variables: GIT_DEPTH: 100 - # --- Following variables are for rustdocs deployment --- - # Space separated values of branches and tags to generate rustdocs - RUSTDOCS_DEPLOY_REFS: "master monthly-2021-09+1 monthly-2021-08 v3.0.0" - # Location of the docs index template - INDEX_TPL: ".maintain/docs-index-tpl.ejs" - # Where the `/latest` symbolic link links to. One of the $RUSTDOCS_DEPLOY_REFS value. - LATEST: "monthly-2021-09+1" + RUSTDOCS_DEPLOY_REFS: "master" rules: - if: $CI_PIPELINE_SOURCE == "pipeline" when: never @@ -783,34 +777,18 @@ publish-rustdoc: - git config remote.origin.url "git@github.com:/paritytech/${CI_PROJECT_NAME}.git" - git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*" - git fetch origin gh-pages - # Install `ejs` and generate index.html based on RUSTDOCS_DEPLOY_REFS - - yarn global add ejs - - 'ejs ${INDEX_TPL} -i "{\"deploy_refs\":\"${RUSTDOCS_DEPLOY_REFS}\",\"repo_name\":\"${CI_PROJECT_NAME}\",\"latest\":\"${LATEST}\"}" > /tmp/index.html' # Save README and docs - cp -r ./crate-docs/ /tmp/doc/ - cp README.md /tmp/doc/ - git checkout gh-pages - # Remove directories no longer necessary, as specified in $RUSTDOCS_DEPLOY_REFS. - # Also ensure $RUSTDOCS_DEPLOY_REFS is not just empty spaces. - # Even though this block spans multiple lines, they are concatenated to run as a single line - # command, so note for the semi-colons in the inner-most code block. - - if [[ ! -z ${RUSTDOCS_DEPLOY_REFS// } ]]; then - for FILE in *; do - if [[ ! " $RUSTDOCS_DEPLOY_REFS " =~ " $FILE " ]]; then - echo "Removing ${FILE}..."; - rm -rf $FILE; - fi - done - fi - # Move the index page & built back - - mv -f /tmp/index.html . + # Install `index-tpl-crud` and generate index.html based on RUSTDOCS_DEPLOY_REFS + - which index-tpl-crud &> /dev/null || yarn global add @jimmychu0807/index-tpl-crud + - index-tpl-crud upsert ./index.html ${CI_COMMIT_REF_NAME} # Ensure the destination dir doesn't exist. - rm -rf ${CI_COMMIT_REF_NAME} - mv -f /tmp/doc ${CI_COMMIT_REF_NAME} - # Add the symlink - - '[[ -e "$LATEST" ]] && ln -sf "${LATEST}" latest' # Upload files - - git add --all --force + - git add --all # `git commit` has an exit code of > 0 if there is nothing to commit. # This causes GitLab to exit immediately and marks this job failed. # We don't want to mark the entire job failed if there's nothing to diff --git a/.maintain/rustdocs-release.sh b/.maintain/rustdocs-release.sh new file mode 100755 index 000000000000..8a250849ee7a --- /dev/null +++ b/.maintain/rustdocs-release.sh @@ -0,0 +1,244 @@ +#!/usr/bin/env bash +# set -x + +# This script manages the deployment of Substrate rustdocs to https://paritytech.github.io/substrate/. +# - With `deploy` sub-command, it will checkout the passed-in branch/tag ref, build the rustdocs +# locally (this takes some time), update the `index.html` index page, and push it to remote +# `gh-pages` branch. So users running this command need to have write access to the remote +# `gh-pages` branch. This sub-command depends on [@jimmychu0807/index-tpl-crud](https://www.npmjs.com/package/@jimmychu0807/index-tpl-crud) +# to update the DOM of index.html page. +# - With `remove` sub-command, it will remove the deployed rustdocs from `gh-pages`, and update the +# index.html page as necessary. It may remove the `latest` symbolic link. +# +# Examples: +# # Showing help text +# rustdocs-release.sh -h +# +# # Deploy rustdocs of `monthly-2021-10` tag +# rustdocs-release.sh deploy monthly-2021-10 +# +# # In addition to the above, the `latest` symlink will point to this version of rustdocs +# rustdocs-release.sh deploy -l monthly-2021-10 +# +# # Remove the rustdocs of `monthly-2021-10` from `gh-pages`. +# rustdocs-release.sh remove monthly-2021-10 +# +# Dependencies: +# - @jimmychu0807/index-tpl-crud - https://www.npmjs.com/package/@jimmychu0807/index-tpl-crud +# + +# Script setting +# The git repo http URL +REMOTE_REPO="https://github.com/paritytech/substrate.git" +TMP_PREFIX="/tmp" # tmp location that the built doc is copied to. +DOC_INDEX_PAGE="sc_service/index.html" + +# Set to `true` if using cargo `nightly` toolchain to build the doc. +# Set to `false` to use the default cargo toolchain. This is preferred if you want to build +# the rustdocs with a pinned nightly version set to your default toolchain. +CARGO_NIGHTLY=false + +# Set the git remote name. Most of the time the default is `origin`. +GIT_REMOTE="origin" +LATEST=false + +# Setting the help text +declare -A HELP_TXT +HELP_TXT["deploy"]=$(cat <<-EOH +Build and deploy the rustdocs of the specified branch/tag to \`gh-pages\` branch. + + usage: $0 deploy [-l] + example: $0 deploy -l monthly-2021-10 + + options: + -l The \`latest\` path will be sym'linked to this rustdocs version +EOH +) + +HELP_TXT["remove"]=$(cat <<-EOH +Remove the rustdocs of the specified version from \`gh-pages\` branch. + + usage: $0 remove + example: $0 remove monthly-2021-10 +EOH +) + +set_and_check_rustdoc_ref() { + [[ -z "$1" ]] && { + echo -e "git branch_ref is not specified.\n" + echo "${HELP_TXT[$2]}" + exit 1 + } + BUILD_RUSTDOC_REF=$1 +} + +check_local_change() { + # Check there is no local changes before proceeding + [[ -n $(git status --porcelain) ]] \ + && echo "Local changes exist, please either discard or commit them as this command will change the current checkout branch." \ + && exit 1 +} + +build_rustdocs() { + # Build the docs + time cargo $($CARGO_NIGHTLY && echo "+nightly") doc --workspace --all-features --verbose \ + || { echo "Generate $1 rustdocs failed" && exit 1; } + rm -f target/doc/.lock + + # Moving the built doc to the tmp location + mv target/doc "${2}" + [[ -n "${DOC_INDEX_PAGE}" ]] \ + && echo "" > "${2}/index.html" +} + +upsert_index_page() { + # Check if `index-tpl-crud` exists + which index-tpl-crud &> /dev/null || yarn global add @jimmychu0807/index-tpl-crud + index-tpl-crud upsert $($1 && echo "-l") ./index.html "$2" +} + +rm_index_page() { + which index-tpl-crud &> /dev/null || yarn global add @jimmychu0807/index-tpl-crud + index-tpl-crud rm ./index.html "$1" +} + +git_add_commit_push() { + git add --all + git commit -m "$1" || echo "Nothing to commit" + git push "${GIT_REMOTE}" gh-pages --force +} + +import_gh_key() { + [[ -n $GITHUB_SSH_PRIV_KEY ]] && { + eval $(ssh-agent) + ssh-add - <<< $GITHUB_SSH_PRIV_KEY + } + + # Adding github.com as known_hosts + ssh-keygen -F github.com &>/dev/null || { + [[ -e ~/.ssh ]] || mkdir ~/.ssh + [[ -e ~/.ssh/known_hosts ]] || touch ~/.ssh/known_hosts + ssh-keyscan -t rsa github.com >> ~/.ssh/known_hosts + } +} + +deploy_main() { + check_local_change + import_gh_key + + CURRENT_GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD) + TMP_PROJECT_PATH="${TMP_PREFIX}/${PROJECT_NAME}" + DOC_PATH="${TMP_PROJECT_PATH}/${BUILD_RUSTDOC_REF}" + + # Build the tmp project path + rm -rf "${TMP_PROJECT_PATH}" && mkdir "${TMP_PROJECT_PATH}" + + # Copy .gitignore file to tmp + [[ -e "${PROJECT_PATH}/.gitignore" ]] && cp "${PROJECT_PATH}/.gitignore" "${TMP_PROJECT_PATH}" + + git fetch --all + git checkout -f ${BUILD_RUSTDOC_REF} || { echo "Checkout \`${BUILD_RUSTDOC_REF}\` error." && exit 1; } + build_rustdocs "${BUILD_RUSTDOC_REF}" "${DOC_PATH}" + + # git checkout `gh-pages` branch + git fetch "${GIT_REMOTE}" gh-pages + git checkout gh-pages + # Move the built back + [[ -e "${TMP_PROJECT_PATH}/.gitignore" ]] && cp -f "${TMP_PROJECT_PATH}/.gitignore" . + # Ensure the destination dir doesn't exist under current path. + rm -rf "${BUILD_RUSTDOC_REF}" + mv -f "${DOC_PATH}" "${BUILD_RUSTDOC_REF}" + + upsert_index_page $LATEST "${BUILD_RUSTDOC_REF}" + # Add the latest symlink + $LATEST && rm -rf latest && ln -sf "${BUILD_RUSTDOC_REF}" latest + + git_add_commit_push "___Deployed rustdocs of ${BUILD_RUSTDOC_REF}___" + # Clean up + # Remove the tmp asset created + rm -rf "${TMP_PROJECT_PATH}" + # Resume back previous checkout branch. + git checkout -f "$CURRENT_GIT_BRANCH" +} + +remove_main() { + check_local_change + import_gh_key + + CURRENT_GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD) + + # git checkout `gh-pages` branch + git fetch "${GIT_REMOTE}" gh-pages + git checkout gh-pages + + rm -rf "${BUILD_RUSTDOC_REF}" + rm_index_page "${BUILD_RUSTDOC_REF}" + # check if the destination of `latest` exists and rmove if not. + [[ -e "latest" ]] || rm latest + + git_add_commit_push "___Removed rustdocs of ${BUILD_RUSTDOC_REF}___" + + # Resume back previous checkout branch. + git checkout -f "$CURRENT_GIT_BRANCH" +} + +# ---- The script execution entry point starts here ---- + +# Arguments handling +SUBCMD=$1 +[[ $SUBCMD == "deploy" || $SUBCMD == "remove" ]] \ + || { echo "Please specify a subcommand of \`deploy\` or \`remove\`" && exit 1 ;} +shift + +# After removing the subcommand, there could only be 1 or 2 parameters afterward +[[ $# -lt 1 || $# -gt 2 ]] && { + echo "${HELP_TXT[${SUBCMD}]}" + exit 1 +} + +# Parsing options and argument for `deploy` subcommand +[[ $SUBCMD == "deploy" ]] && { + while getopts :lh opt; do + case $opt in + l) + LATEST=true + ;; + h) + echo "${HELP_TXT[$SUBCMD]}" + exit 0 + ;; + \?) + echo "Invalid option: -$OPTARG" >&2 + exit 1 + ;; + esac + done +} +# Parsing options and argument for `remove` subcommand +[[ $SUBCMD == "remove" ]] && { + while getopts :h opt; do + case $opt in + h) + echo "${HELP_TXT[$SUBCMD]}" + exit 0 + ;; + \?) + echo "Invalid option: -$OPTARG" >&2 + exit 1 + ;; + esac + done +} + +shift $(($OPTIND - 1)) +set_and_check_rustdoc_ref ${1:-''} $SUBCMD + +SCRIPT=$(realpath $0) +SCRIPT_PATH=$(dirname $SCRIPT) +PROJECT_PATH=$(dirname ${SCRIPT_PATH}) +PROJECT_NAME=$(basename "$PROJECT_PATH") + +pushd "${PROJECT_PATH}" &>/dev/null +[[ $SUBCMD == "deploy" ]] && deploy_main +[[ $SUBCMD == "remove" ]] && remove_main +popd &>/dev/null diff --git a/docs/rustdocs-release.md b/docs/rustdocs-release.md new file mode 100644 index 000000000000..5c7e2db40a2c --- /dev/null +++ b/docs/rustdocs-release.md @@ -0,0 +1,20 @@ +# Rustdocs Release Process + +There is [a script in place](../.maintain/rustdocs-release.sh) to manage the deployment of Substrate rustdocs at +https://paritytech.github.io/substrate, which is pushing the rustdocs file in `gh-pages` branch of +https://github.com/paritytech/substrate. + +The documentation at the top of the `rustdocs-release.sh` explains most of the mechanics of the script. + +Manage the rustdocs deployment with one of the following commands. + +```bash +# Deploy rustdocs of `monthly-2021-10` tag +.maintain/rustdocs-release.sh deploy monthly-2021-10 + +# In addition to the above, the `latest` symlink will point to this version of rustdocs +.maintain/rustdocs-release.sh deploy -l monthly-2021-10 + +# Remove the rustdocs of `monthly-2021-10` from `gh-pages`. +.maintain/rustdocs-release.sh remove monthly-2021-10 +``` From 94dfe152e61e42cd27844a65165cfdedde5232eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Fri, 21 Jan 2022 20:21:36 +0100 Subject: [PATCH 411/695] Remove some last `AccountId32::default()` leftovers (#10655) * Remove some last `AccountId32::default()` leftovers As we removed `Default` of account id, we have overseen some last bits. This pr removes these last bits. * Fix --- frame/collective/src/lib.rs | 7 +++++-- primitives/core/src/crypto.rs | 10 ++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/frame/collective/src/lib.rs b/frame/collective/src/lib.rs index 3e3b923d6ee3..49328aa0bdc6 100644 --- a/frame/collective/src/lib.rs +++ b/frame/collective/src/lib.rs @@ -990,8 +990,8 @@ where pub struct EnsureMember(PhantomData<(AccountId, I)>); impl< O: Into, O>> + From>, - AccountId: Default, I, + AccountId: Decode, > EnsureOrigin for EnsureMember { type Success = AccountId; @@ -1004,7 +1004,10 @@ impl< #[cfg(feature = "runtime-benchmarks")] fn successful_origin() -> O { - O::from(RawOrigin::Member(Default::default())) + let zero_account_id = + AccountId::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()) + .expect("infinite length input; no invalid inputs for type; qed"); + O::from(RawOrigin::Member(zero_account_id)) } } diff --git a/primitives/core/src/crypto.rs b/primitives/core/src/crypto.rs index 41ee9466ad93..12f8397eee4a 100644 --- a/primitives/core/src/crypto.rs +++ b/primitives/core/src/crypto.rs @@ -478,9 +478,7 @@ pub trait Public: ByteArray + Derive + CryptoType + PartialEq + Eq + Clone + Sen } /// An opaque 32-byte cryptographic identifier. -#[derive( - Clone, Eq, PartialEq, Ord, PartialOrd, Default, Encode, Decode, MaxEncodedLen, TypeInfo, -)] +#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, MaxEncodedLen, TypeInfo)] #[cfg_attr(feature = "std", derive(Hash))] pub struct AccountId32([u8; 32]); @@ -541,9 +539,9 @@ impl<'a> sp_std::convert::TryFrom<&'a [u8]> for AccountId32 { type Error = (); fn try_from(x: &'a [u8]) -> Result { if x.len() == 32 { - let mut r = AccountId32::default(); - r.0.copy_from_slice(x); - Ok(r) + let mut data = [0; 32]; + data.copy_from_slice(x); + Ok(AccountId32(data)) } else { Err(()) } From 32b71896df8a832e7c139a842e46710e4d3f70cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Sat, 22 Jan 2022 21:15:28 +0100 Subject: [PATCH 412/695] wasm-builder: Enable all features when running `cargo metadata` (#10716) This is required for projects like Cumulus that have dependencies on `westend-runtime`, but this runtime is only added when the `runtime-benchmarks` feature is enabled. By having all features "enabled" in `cargo metadata` we ensure that all crates can be found. --- utils/wasm-builder/src/wasm_project.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/utils/wasm-builder/src/wasm_project.rs b/utils/wasm-builder/src/wasm_project.rs index 809a940c7406..9b5a33b6a623 100644 --- a/utils/wasm-builder/src/wasm_project.rs +++ b/utils/wasm-builder/src/wasm_project.rs @@ -31,7 +31,7 @@ use toml::value::Table; use build_helper::rerun_if_changed; -use cargo_metadata::{Metadata, MetadataCommand}; +use cargo_metadata::{CargoOpt, Metadata, MetadataCommand}; use walkdir::WalkDir; @@ -88,6 +88,7 @@ fn crate_metadata(cargo_manifest: &Path) -> Metadata { let crate_metadata = MetadataCommand::new() .manifest_path(cargo_manifest) + .features(CargoOpt::AllFeatures) .exec() .expect("`cargo metadata` can not fail on project `Cargo.toml`; qed"); From b57c08be31f0427780b0b1a1e21cea54a996cd7a Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Mon, 24 Jan 2022 10:48:44 +0100 Subject: [PATCH 413/695] Fix #10688 being misimplemented (#10721) --- client/network/src/protocol.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/network/src/protocol.rs b/client/network/src/protocol.rs index 3fb40b7199d6..5541a0145366 100644 --- a/client/network/src/protocol.rs +++ b/client/network/src/protocol.rs @@ -827,7 +827,7 @@ impl Protocol { } if status.roles.is_light() && - (self.peers.len() - self.sync.num_peers()) < self.default_peers_set_num_light + (self.peers.len() - self.sync.num_peers()) >= self.default_peers_set_num_light { // Make sure that not all slots are occupied by light clients. debug!(target: "sync", "Too many light nodes, rejecting {}", who); From 48c05c0ab98d34944d395c638188755f3e4694b1 Mon Sep 17 00:00:00 2001 From: Jimmy Chu Date: Mon, 24 Jan 2022 19:11:26 +0800 Subject: [PATCH 414/695] Changing the node package to be under @substrate namespace (#10722) Signed-off-by: Jimmy Chu --- .gitlab-ci.yml | 2 +- .maintain/rustdocs-release.sh | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a0b71fcff02e..b2716b018d6c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -782,7 +782,7 @@ publish-rustdoc: - cp README.md /tmp/doc/ - git checkout gh-pages # Install `index-tpl-crud` and generate index.html based on RUSTDOCS_DEPLOY_REFS - - which index-tpl-crud &> /dev/null || yarn global add @jimmychu0807/index-tpl-crud + - which index-tpl-crud &> /dev/null || yarn global add @substrate/index-tpl-crud - index-tpl-crud upsert ./index.html ${CI_COMMIT_REF_NAME} # Ensure the destination dir doesn't exist. - rm -rf ${CI_COMMIT_REF_NAME} diff --git a/.maintain/rustdocs-release.sh b/.maintain/rustdocs-release.sh index 8a250849ee7a..2a1e141e63ad 100755 --- a/.maintain/rustdocs-release.sh +++ b/.maintain/rustdocs-release.sh @@ -5,7 +5,7 @@ # - With `deploy` sub-command, it will checkout the passed-in branch/tag ref, build the rustdocs # locally (this takes some time), update the `index.html` index page, and push it to remote # `gh-pages` branch. So users running this command need to have write access to the remote -# `gh-pages` branch. This sub-command depends on [@jimmychu0807/index-tpl-crud](https://www.npmjs.com/package/@jimmychu0807/index-tpl-crud) +# `gh-pages` branch. This sub-command depends on [@substrate/index-tpl-crud](https://www.npmjs.com/package/@substrate/index-tpl-crud) # to update the DOM of index.html page. # - With `remove` sub-command, it will remove the deployed rustdocs from `gh-pages`, and update the # index.html page as necessary. It may remove the `latest` symbolic link. @@ -24,7 +24,7 @@ # rustdocs-release.sh remove monthly-2021-10 # # Dependencies: -# - @jimmychu0807/index-tpl-crud - https://www.npmjs.com/package/@jimmychu0807/index-tpl-crud +# - @substrate/index-tpl-crud - https://www.npmjs.com/package/@substrate/index-tpl-crud # # Script setting @@ -93,12 +93,12 @@ build_rustdocs() { upsert_index_page() { # Check if `index-tpl-crud` exists - which index-tpl-crud &> /dev/null || yarn global add @jimmychu0807/index-tpl-crud + which index-tpl-crud &> /dev/null || yarn global add @substrate/index-tpl-crud index-tpl-crud upsert $($1 && echo "-l") ./index.html "$2" } rm_index_page() { - which index-tpl-crud &> /dev/null || yarn global add @jimmychu0807/index-tpl-crud + which index-tpl-crud &> /dev/null || yarn global add @substrate/index-tpl-crud index-tpl-crud rm ./index.html "$1" } From 542a8585339d2581e641df339d254d7dd22b1456 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Mon, 24 Jan 2022 13:35:25 +0100 Subject: [PATCH 415/695] Optimized weights (#10692) * Add optimization flags to 'release' profile Signed-off-by: Oliver Tale-Yazdi * Optimized weights Signed-off-by: Oliver Tale-Yazdi * Add missing pallets Signed-off-by: Oliver Tale-Yazdi * Add `production` profile Signed-off-by: Oliver Tale-Yazdi * pallet-collective: fix tests the weight of System.remark went to 0, the collective test uses a remark call to trigger an out-of-gas condition so I replaced it with a `remark_with_event` call. Signed-off-by: Oliver Tale-Yazdi --- Cargo.toml | 11 + frame/assets/src/weights.rs | 145 +-- frame/bags-list/src/weights.rs | 24 +- frame/balances/src/weights.rs | 41 +- frame/benchmarking/src/weights.rs | 64 +- frame/bounties/src/weights.rs | 65 +- frame/child-bounties/src/weights.rs | 57 +- frame/collective/src/tests.rs | 2 +- frame/collective/src/weights.rs | 285 ++-- frame/contracts/src/weights.rs | 1152 +++++++++-------- frame/democracy/src/weights.rs | 213 +-- .../src/weights.rs | 143 +- frame/elections-phragmen/src/weights.rs | 165 +-- frame/gilt/src/weights.rs | 69 +- frame/identity/src/weights.rs | 232 ++-- frame/im-online/src/weights.rs | 27 +- frame/indices/src/weights.rs | 33 +- frame/lottery/src/weights.rs | 38 +- frame/membership/src/weights.rs | 189 +-- frame/multisig/src/weights.rs | 125 +- frame/preimage/src/weights.rs | 48 +- frame/proxy/src/weights.rs | 129 +- frame/scheduler/src/weights.rs | 168 +-- frame/session/src/weights.rs | 21 +- frame/staking/src/weights.rs | 224 ++-- frame/system/src/weights.rs | 67 +- frame/timestamp/src/weights.rs | 21 +- frame/tips/src/weights.rs | 117 +- frame/transaction-storage/src/weights.rs | 27 +- frame/treasury/src/weights.rs | 45 +- frame/uniques/src/weights.rs | 125 +- frame/utility/src/weights.rs | 45 +- frame/vesting/src/weights.rs | 153 +-- 33 files changed, 2162 insertions(+), 2108 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b7051bdd44ef..48a36419eb74 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -272,6 +272,17 @@ wasmi = { opt-level = 3 } x25519-dalek = { opt-level = 3 } yamux = { opt-level = 3 } zeroize = { opt-level = 3 } + [profile.release] # Substrate runtime requires unwinding. panic = "unwind" + +[profile.production] +inherits = "release" + +# Sacrifice compile speed for execution speed by using optimization flags: + +# https://doc.rust-lang.org/rustc/linker-plugin-lto.html +lto = "fat" +# https://doc.rust-lang.org/rustc/codegen-options/index.html#codegen-units +codegen-units = 1 diff --git a/frame/assets/src/weights.rs b/frame/assets/src/weights.rs index 423677cf1380..fb6e68dfc772 100644 --- a/frame/assets/src/weights.rs +++ b/frame/assets/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. +// Copyright (C) 2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_assets //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-08-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 +//! DATE: 2022-01-17, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// target/release/substrate +// ./target/lto-fat-cg1/substrate // benchmark // --chain=dev // --steps=50 @@ -33,8 +33,9 @@ // --wasm-execution=compiled // --heap-pages=4096 // --output=./frame/assets/src/weights.rs -// --template=./.maintain/frame-weight-template.hbs - +// --template=.maintain/frame-weight-template.hbs +// --header=LICENSE-APACHE2 +// --raw #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -75,13 +76,13 @@ pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { // Storage: Assets Asset (r:1 w:1) fn create() -> Weight { - (41_651_000 as Weight) + (22_050_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:1) fn force_create() -> Weight { - (21_378_000 as Weight) + (11_673_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -92,12 +93,12 @@ impl WeightInfo for SubstrateWeight { // Storage: Assets Approvals (r:501 w:500) fn destroy(c: u32, s: u32, a: u32, ) -> Weight { (0 as Weight) - // Standard Error: 32_000 - .saturating_add((21_163_000 as Weight).saturating_mul(c as Weight)) - // Standard Error: 32_000 - .saturating_add((26_932_000 as Weight).saturating_mul(s as Weight)) - // Standard Error: 329_000 - .saturating_add((29_714_000 as Weight).saturating_mul(a as Weight)) + // Standard Error: 36_000 + .saturating_add((14_657_000 as Weight).saturating_mul(c as Weight)) + // Standard Error: 36_000 + .saturating_add((17_018_000 as Weight).saturating_mul(s as Weight)) + // Standard Error: 362_000 + .saturating_add((16_620_000 as Weight).saturating_mul(a as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(c as Weight))) .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(s as Weight))) @@ -110,14 +111,14 @@ impl WeightInfo for SubstrateWeight { // Storage: Assets Asset (r:1 w:1) // Storage: Assets Account (r:1 w:1) fn mint() -> Weight { - (47_913_000 as Weight) + (26_254_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Assets Asset (r:1 w:1) // Storage: Assets Account (r:1 w:1) fn burn() -> Weight { - (55_759_000 as Weight) + (30_407_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -125,7 +126,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Assets Account (r:2 w:2) // Storage: System Account (r:1 w:1) fn transfer() -> Weight { - (83_205_000 as Weight) + (44_220_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } @@ -133,7 +134,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Assets Account (r:2 w:2) // Storage: System Account (r:1 w:1) fn transfer_keep_alive() -> Weight { - (70_665_000 as Weight) + (36_910_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } @@ -141,93 +142,93 @@ impl WeightInfo for SubstrateWeight { // Storage: Assets Account (r:2 w:2) // Storage: System Account (r:1 w:1) fn force_transfer() -> Weight { - (81_458_000 as Weight) + (44_330_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } // Storage: Assets Asset (r:1 w:0) // Storage: Assets Account (r:1 w:1) fn freeze() -> Weight { - (32_845_000 as Weight) + (17_937_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:0) // Storage: Assets Account (r:1 w:1) fn thaw() -> Weight { - (33_303_000 as Weight) + (18_224_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:1) fn freeze_asset() -> Weight { - (23_434_000 as Weight) + (14_875_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:1) fn thaw_asset() -> Weight { - (24_173_000 as Weight) + (14_792_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:1) // Storage: Assets Metadata (r:1 w:0) fn transfer_ownership() -> Weight { - (27_466_000 as Weight) + (15_794_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:1) fn set_team() -> Weight { - (24_608_000 as Weight) + (14_702_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:0) // Storage: Assets Metadata (r:1 w:1) fn set_metadata(n: u32, s: u32, ) -> Weight { - (49_515_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 1_000 - .saturating_add((6_000 as Weight).saturating_mul(s as Weight)) + (27_368_000 as Weight) + // Standard Error: 0 + .saturating_add((4_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 0 + .saturating_add((4_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:0) // Storage: Assets Metadata (r:1 w:1) fn clear_metadata() -> Weight { - (48_163_000 as Weight) + (28_222_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:0) // Storage: Assets Metadata (r:1 w:1) fn force_set_metadata(_n: u32, s: u32, ) -> Weight { - (26_722_000 as Weight) + (15_139_000 as Weight) // Standard Error: 0 - .saturating_add((5_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((3_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:0) // Storage: Assets Metadata (r:1 w:1) fn force_clear_metadata() -> Weight { - (47_923_000 as Weight) + (28_065_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:1) fn force_asset_status() -> Weight { - (23_081_000 as Weight) + (13_808_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:1) // Storage: Assets Approvals (r:1 w:1) fn approve_transfer() -> Weight { - (56_998_000 as Weight) + (31_261_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -236,21 +237,21 @@ impl WeightInfo for SubstrateWeight { // Storage: Assets Account (r:2 w:2) // Storage: System Account (r:1 w:1) fn transfer_approved() -> Weight { - (107_171_000 as Weight) + (56_329_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } // Storage: Assets Asset (r:1 w:1) // Storage: Assets Approvals (r:1 w:1) fn cancel_approval() -> Weight { - (57_358_000 as Weight) + (32_086_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Assets Asset (r:1 w:1) // Storage: Assets Approvals (r:1 w:1) fn force_cancel_approval() -> Weight { - (58_330_000 as Weight) + (32_502_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -260,13 +261,13 @@ impl WeightInfo for SubstrateWeight { impl WeightInfo for () { // Storage: Assets Asset (r:1 w:1) fn create() -> Weight { - (41_651_000 as Weight) + (22_050_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:1) fn force_create() -> Weight { - (21_378_000 as Weight) + (11_673_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -277,12 +278,12 @@ impl WeightInfo for () { // Storage: Assets Approvals (r:501 w:500) fn destroy(c: u32, s: u32, a: u32, ) -> Weight { (0 as Weight) - // Standard Error: 32_000 - .saturating_add((21_163_000 as Weight).saturating_mul(c as Weight)) - // Standard Error: 32_000 - .saturating_add((26_932_000 as Weight).saturating_mul(s as Weight)) - // Standard Error: 329_000 - .saturating_add((29_714_000 as Weight).saturating_mul(a as Weight)) + // Standard Error: 36_000 + .saturating_add((14_657_000 as Weight).saturating_mul(c as Weight)) + // Standard Error: 36_000 + .saturating_add((17_018_000 as Weight).saturating_mul(s as Weight)) + // Standard Error: 362_000 + .saturating_add((16_620_000 as Weight).saturating_mul(a as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(c as Weight))) .saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(s as Weight))) @@ -295,14 +296,14 @@ impl WeightInfo for () { // Storage: Assets Asset (r:1 w:1) // Storage: Assets Account (r:1 w:1) fn mint() -> Weight { - (47_913_000 as Weight) + (26_254_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Assets Asset (r:1 w:1) // Storage: Assets Account (r:1 w:1) fn burn() -> Weight { - (55_759_000 as Weight) + (30_407_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -310,7 +311,7 @@ impl WeightInfo for () { // Storage: Assets Account (r:2 w:2) // Storage: System Account (r:1 w:1) fn transfer() -> Weight { - (83_205_000 as Weight) + (44_220_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } @@ -318,7 +319,7 @@ impl WeightInfo for () { // Storage: Assets Account (r:2 w:2) // Storage: System Account (r:1 w:1) fn transfer_keep_alive() -> Weight { - (70_665_000 as Weight) + (36_910_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } @@ -326,93 +327,93 @@ impl WeightInfo for () { // Storage: Assets Account (r:2 w:2) // Storage: System Account (r:1 w:1) fn force_transfer() -> Weight { - (81_458_000 as Weight) + (44_330_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } // Storage: Assets Asset (r:1 w:0) // Storage: Assets Account (r:1 w:1) fn freeze() -> Weight { - (32_845_000 as Weight) + (17_937_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:0) // Storage: Assets Account (r:1 w:1) fn thaw() -> Weight { - (33_303_000 as Weight) + (18_224_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:1) fn freeze_asset() -> Weight { - (23_434_000 as Weight) + (14_875_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:1) fn thaw_asset() -> Weight { - (24_173_000 as Weight) + (14_792_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:1) // Storage: Assets Metadata (r:1 w:0) fn transfer_ownership() -> Weight { - (27_466_000 as Weight) + (15_794_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:1) fn set_team() -> Weight { - (24_608_000 as Weight) + (14_702_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:0) // Storage: Assets Metadata (r:1 w:1) fn set_metadata(n: u32, s: u32, ) -> Weight { - (49_515_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 1_000 - .saturating_add((6_000 as Weight).saturating_mul(s as Weight)) + (27_368_000 as Weight) + // Standard Error: 0 + .saturating_add((4_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 0 + .saturating_add((4_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:0) // Storage: Assets Metadata (r:1 w:1) fn clear_metadata() -> Weight { - (48_163_000 as Weight) + (28_222_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:0) // Storage: Assets Metadata (r:1 w:1) fn force_set_metadata(_n: u32, s: u32, ) -> Weight { - (26_722_000 as Weight) + (15_139_000 as Weight) // Standard Error: 0 - .saturating_add((5_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((3_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:0) // Storage: Assets Metadata (r:1 w:1) fn force_clear_metadata() -> Weight { - (47_923_000 as Weight) + (28_065_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:1) fn force_asset_status() -> Weight { - (23_081_000 as Weight) + (13_808_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Assets Asset (r:1 w:1) // Storage: Assets Approvals (r:1 w:1) fn approve_transfer() -> Weight { - (56_998_000 as Weight) + (31_261_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -421,21 +422,21 @@ impl WeightInfo for () { // Storage: Assets Account (r:2 w:2) // Storage: System Account (r:1 w:1) fn transfer_approved() -> Weight { - (107_171_000 as Weight) + (56_329_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } // Storage: Assets Asset (r:1 w:1) // Storage: Assets Approvals (r:1 w:1) fn cancel_approval() -> Weight { - (57_358_000 as Weight) + (32_086_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Assets Asset (r:1 w:1) // Storage: Assets Approvals (r:1 w:1) fn force_cancel_approval() -> Weight { - (58_330_000 as Weight) + (32_502_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } diff --git a/frame/bags-list/src/weights.rs b/frame/bags-list/src/weights.rs index 5a8f51cc07c7..6cd9449b4286 100644 --- a/frame/bags-list/src/weights.rs +++ b/frame/bags-list/src/weights.rs @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_bags_list //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-05, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 +//! DATE: 2022-01-19, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// target/release/substrate +// ./target/optimized/substrate // benchmark // --chain=dev // --steps=50 @@ -32,8 +32,10 @@ // --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/bags-list/src/weights.rs -// --template=./.maintain/frame-weight-template.hbs +// --output=./weights-optimized/frame/bags-list/src//weights.rs +// --template=.maintain/frame-weight-template.hbs +// --header=HEADER-APACHE2 +// --raw #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -57,7 +59,7 @@ impl WeightInfo for SubstrateWeight { // Storage: BagsList ListNodes (r:4 w:4) // Storage: BagsList ListBags (r:1 w:1) fn rebag_non_terminal() -> Weight { - (62_060_000 as Weight) + (50_222_000 as Weight) .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } @@ -66,7 +68,7 @@ impl WeightInfo for SubstrateWeight { // Storage: BagsList ListNodes (r:3 w:3) // Storage: BagsList ListBags (r:2 w:2) fn rebag_terminal() -> Weight { - (60_585_000 as Weight) + (47_975_000 as Weight) .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } @@ -76,7 +78,7 @@ impl WeightInfo for SubstrateWeight { // Storage: BagsList CounterForListNodes (r:1 w:1) // Storage: BagsList ListBags (r:1 w:1) fn put_in_front_of() -> Weight { - (69_779_000 as Weight) + (55_539_000 as Weight) .saturating_add(T::DbWeight::get().reads(10 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } @@ -89,7 +91,7 @@ impl WeightInfo for () { // Storage: BagsList ListNodes (r:4 w:4) // Storage: BagsList ListBags (r:1 w:1) fn rebag_non_terminal() -> Weight { - (62_060_000 as Weight) + (50_222_000 as Weight) .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } @@ -98,7 +100,7 @@ impl WeightInfo for () { // Storage: BagsList ListNodes (r:3 w:3) // Storage: BagsList ListBags (r:2 w:2) fn rebag_terminal() -> Weight { - (60_585_000 as Weight) + (47_975_000 as Weight) .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } @@ -108,7 +110,7 @@ impl WeightInfo for () { // Storage: BagsList CounterForListNodes (r:1 w:1) // Storage: BagsList ListBags (r:1 w:1) fn put_in_front_of() -> Weight { - (69_779_000 as Weight) + (55_539_000 as Weight) .saturating_add(RocksDbWeight::get().reads(10 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } diff --git a/frame/balances/src/weights.rs b/frame/balances/src/weights.rs index a272753b7346..f34dd65191e4 100644 --- a/frame/balances/src/weights.rs +++ b/frame/balances/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. +// Copyright (C) 2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_balances //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-09-13, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 +//! DATE: 2022-01-17, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// target/release/substrate +// ./target/lto-fat-cg1/substrate // benchmark // --chain=dev // --steps=50 @@ -33,8 +33,9 @@ // --wasm-execution=compiled // --heap-pages=4096 // --output=./frame/balances/src/weights.rs -// --template=./.maintain/frame-weight-template.hbs - +// --template=.maintain/frame-weight-template.hbs +// --header=LICENSE-APACHE2 +// --raw #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -59,43 +60,43 @@ pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { // Storage: System Account (r:1 w:1) fn transfer() -> Weight { - (70_952_000 as Weight) + (34_668_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: System Account (r:1 w:1) fn transfer_keep_alive() -> Weight { - (54_410_000 as Weight) + (26_826_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: System Account (r:1 w:1) fn set_balance_creating() -> Weight { - (29_176_000 as Weight) + (17_292_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: System Account (r:1 w:1) fn set_balance_killing() -> Weight { - (35_214_000 as Weight) + (19_988_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: System Account (r:2 w:2) fn force_transfer() -> Weight { - (71_780_000 as Weight) + (34_646_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: System Account (r:1 w:1) fn transfer_all() -> Weight { - (66_475_000 as Weight) + (32_040_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: System Account (r:1 w:1) fn force_unreserve() -> Weight { - (27_766_000 as Weight) + (15_743_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -105,43 +106,43 @@ impl WeightInfo for SubstrateWeight { impl WeightInfo for () { // Storage: System Account (r:1 w:1) fn transfer() -> Weight { - (70_952_000 as Weight) + (34_668_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: System Account (r:1 w:1) fn transfer_keep_alive() -> Weight { - (54_410_000 as Weight) + (26_826_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: System Account (r:1 w:1) fn set_balance_creating() -> Weight { - (29_176_000 as Weight) + (17_292_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: System Account (r:1 w:1) fn set_balance_killing() -> Weight { - (35_214_000 as Weight) + (19_988_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: System Account (r:2 w:2) fn force_transfer() -> Weight { - (71_780_000 as Weight) + (34_646_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: System Account (r:1 w:1) fn transfer_all() -> Weight { - (66_475_000 as Weight) + (32_040_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: System Account (r:1 w:1) fn force_unreserve() -> Weight { - (27_766_000 as Weight) + (15_743_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } diff --git a/frame/benchmarking/src/weights.rs b/frame/benchmarking/src/weights.rs index a4d46d24b6e3..2945daeaf312 100644 --- a/frame/benchmarking/src/weights.rs +++ b/frame/benchmarking/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. +// Copyright (C) 2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,11 +18,11 @@ //! Autogenerated weights for frame_benchmarking //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-12-02, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 +//! DATE: 2022-01-17, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// target/release/substrate +// ./target/lto-fat-cg1/substrate // benchmark // --chain=dev // --steps=50 @@ -33,7 +33,9 @@ // --wasm-execution=compiled // --heap-pages=4096 // --output=./frame/benchmarking/src/weights.rs -// --template=./.maintain/frame-weight-template.hbs +// --template=.maintain/frame-weight-template.hbs +// --header=LICENSE-APACHE2 +// --raw #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -58,39 +60,37 @@ pub trait WeightInfo { pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { fn addition(_i: u32, ) -> Weight { - (284_000 as Weight) + (141_000 as Weight) } fn subtraction(_i: u32, ) -> Weight { - (279_000 as Weight) + (136_000 as Weight) } fn multiplication(_i: u32, ) -> Weight { - (278_000 as Weight) + (136_000 as Weight) } fn division(_i: u32, ) -> Weight { - (274_000 as Weight) + (134_000 as Weight) } - fn hashing(i: u32, ) -> Weight { - (33_441_957_000 as Weight) - // Standard Error: 535_000 - .saturating_add((363_000 as Weight).saturating_mul(i as Weight)) + fn hashing(_i: u32, ) -> Weight { + (21_681_881_000 as Weight) } fn sr25519_verification(i: u32, ) -> Weight { - (26_000 as Weight) - // Standard Error: 14_000 - .saturating_add((48_151_000 as Weight).saturating_mul(i as Weight)) + (0 as Weight) + // Standard Error: 6_000 + .saturating_add((42_000_000 as Weight).saturating_mul(i as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn storage_read(i: u32, ) -> Weight { (0 as Weight) - // Standard Error: 4_000 - .saturating_add((2_694_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 3_000 + .saturating_add((1_984_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) } // Storage: Skipped Metadata (r:0 w:0) fn storage_write(i: u32, ) -> Weight { (0 as Weight) // Standard Error: 0 - .saturating_add((606_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((363_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(i as Weight))) } } @@ -98,39 +98,37 @@ impl WeightInfo for SubstrateWeight { // For backwards compatibility and tests impl WeightInfo for () { fn addition(_i: u32, ) -> Weight { - (284_000 as Weight) + (141_000 as Weight) } fn subtraction(_i: u32, ) -> Weight { - (279_000 as Weight) + (136_000 as Weight) } fn multiplication(_i: u32, ) -> Weight { - (278_000 as Weight) + (136_000 as Weight) } fn division(_i: u32, ) -> Weight { - (274_000 as Weight) + (134_000 as Weight) } - fn hashing(i: u32, ) -> Weight { - (33_441_957_000 as Weight) - // Standard Error: 535_000 - .saturating_add((363_000 as Weight).saturating_mul(i as Weight)) + fn hashing(_i: u32, ) -> Weight { + (21_681_881_000 as Weight) } fn sr25519_verification(i: u32, ) -> Weight { - (26_000 as Weight) - // Standard Error: 14_000 - .saturating_add((48_151_000 as Weight).saturating_mul(i as Weight)) + (0 as Weight) + // Standard Error: 6_000 + .saturating_add((42_000_000 as Weight).saturating_mul(i as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn storage_read(i: u32, ) -> Weight { (0 as Weight) - // Standard Error: 4_000 - .saturating_add((2_694_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 3_000 + .saturating_add((1_984_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) } // Storage: Skipped Metadata (r:0 w:0) fn storage_write(i: u32, ) -> Weight { (0 as Weight) // Standard Error: 0 - .saturating_add((606_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((363_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(i as Weight))) } } diff --git a/frame/bounties/src/weights.rs b/frame/bounties/src/weights.rs index 4cff3180ca79..9c1ce532dff7 100644 --- a/frame/bounties/src/weights.rs +++ b/frame/bounties/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. +// Copyright (C) 2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,23 +18,24 @@ //! Autogenerated weights for pallet_bounties //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-11-19, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 +//! DATE: 2022-01-17, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/release/substrate +// ./target/lto-fat-cg1/substrate // benchmark // --chain=dev // --steps=50 // --repeat=20 -// --pallet -// pallet_bounties +// --pallet=pallet_bounties // --extrinsic=* // --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/bounties/src/ -// --template=./.maintain/frame-weight-template.hbs +// --output=./frame/bounties/src/weights.rs +// --template=.maintain/frame-weight-template.hbs +// --header=LICENSE-APACHE2 +// --raw #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -66,7 +67,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Bounties BountyDescriptions (r:0 w:1) // Storage: Bounties Bounties (r:0 w:1) fn propose_bounty(d: u32, ) -> Weight { - (58_161_000 as Weight) + (23_165_000 as Weight) // Standard Error: 0 .saturating_add((1_000 as Weight).saturating_mul(d as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) @@ -75,34 +76,34 @@ impl WeightInfo for SubstrateWeight { // Storage: Bounties Bounties (r:1 w:1) // Storage: Bounties BountyApprovals (r:1 w:1) fn approve_bounty() -> Weight { - (20_000_000 as Weight) + (6_876_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Bounties Bounties (r:1 w:1) fn propose_curator() -> Weight { - (14_000_000 as Weight) + (5_718_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Bounties Bounties (r:1 w:1) // Storage: System Account (r:1 w:1) fn unassign_curator() -> Weight { - (62_000_000 as Weight) + (27_021_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Bounties Bounties (r:1 w:1) // Storage: System Account (r:1 w:1) fn accept_curator() -> Weight { - (55_000_000 as Weight) + (20_933_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Bounties Bounties (r:1 w:1) // Storage: ChildBounties ParentChildBounties (r:1 w:0) fn award_bounty() -> Weight { - (46_000_000 as Weight) + (17_285_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -111,7 +112,7 @@ impl WeightInfo for SubstrateWeight { // Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) // Storage: Bounties BountyDescriptions (r:0 w:1) fn claim_bounty() -> Weight { - (185_000_000 as Weight) + (61_264_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } @@ -120,7 +121,7 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:1 w:1) // Storage: Bounties BountyDescriptions (r:0 w:1) fn close_bounty_proposed() -> Weight { - (82_000_000 as Weight) + (28_218_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -129,13 +130,13 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:2 w:2) // Storage: Bounties BountyDescriptions (r:0 w:1) fn close_bounty_active() -> Weight { - (137_000_000 as Weight) + (45_577_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } // Storage: Bounties Bounties (r:1 w:1) fn extend_bounty_expiry() -> Weight { - (33_000_000 as Weight) + (14_983_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -144,8 +145,8 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:2 w:2) fn spend_funds(b: u32, ) -> Weight { (0 as Weight) - // Standard Error: 191_000 - .saturating_add((81_116_000 as Weight).saturating_mul(b as Weight)) + // Standard Error: 14_000 + .saturating_add((28_380_000 as Weight).saturating_mul(b as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(b as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -160,7 +161,7 @@ impl WeightInfo for () { // Storage: Bounties BountyDescriptions (r:0 w:1) // Storage: Bounties Bounties (r:0 w:1) fn propose_bounty(d: u32, ) -> Weight { - (58_161_000 as Weight) + (23_165_000 as Weight) // Standard Error: 0 .saturating_add((1_000 as Weight).saturating_mul(d as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) @@ -169,34 +170,34 @@ impl WeightInfo for () { // Storage: Bounties Bounties (r:1 w:1) // Storage: Bounties BountyApprovals (r:1 w:1) fn approve_bounty() -> Weight { - (20_000_000 as Weight) + (6_876_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Bounties Bounties (r:1 w:1) fn propose_curator() -> Weight { - (14_000_000 as Weight) + (5_718_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Bounties Bounties (r:1 w:1) // Storage: System Account (r:1 w:1) fn unassign_curator() -> Weight { - (62_000_000 as Weight) + (27_021_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Bounties Bounties (r:1 w:1) // Storage: System Account (r:1 w:1) fn accept_curator() -> Weight { - (55_000_000 as Weight) + (20_933_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Bounties Bounties (r:1 w:1) // Storage: ChildBounties ParentChildBounties (r:1 w:0) fn award_bounty() -> Weight { - (46_000_000 as Weight) + (17_285_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -205,7 +206,7 @@ impl WeightInfo for () { // Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) // Storage: Bounties BountyDescriptions (r:0 w:1) fn claim_bounty() -> Weight { - (185_000_000 as Weight) + (61_264_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } @@ -214,7 +215,7 @@ impl WeightInfo for () { // Storage: System Account (r:1 w:1) // Storage: Bounties BountyDescriptions (r:0 w:1) fn close_bounty_proposed() -> Weight { - (82_000_000 as Weight) + (28_218_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -223,13 +224,13 @@ impl WeightInfo for () { // Storage: System Account (r:2 w:2) // Storage: Bounties BountyDescriptions (r:0 w:1) fn close_bounty_active() -> Weight { - (137_000_000 as Weight) + (45_577_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } // Storage: Bounties Bounties (r:1 w:1) fn extend_bounty_expiry() -> Weight { - (33_000_000 as Weight) + (14_983_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -238,8 +239,8 @@ impl WeightInfo for () { // Storage: System Account (r:2 w:2) fn spend_funds(b: u32, ) -> Weight { (0 as Weight) - // Standard Error: 191_000 - .saturating_add((81_116_000 as Weight).saturating_mul(b as Weight)) + // Standard Error: 14_000 + .saturating_add((28_380_000 as Weight).saturating_mul(b as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(b as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) diff --git a/frame/child-bounties/src/weights.rs b/frame/child-bounties/src/weights.rs index 1662984aa7a3..73bc535cb300 100644 --- a/frame/child-bounties/src/weights.rs +++ b/frame/child-bounties/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. +// Copyright (C) 2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,23 +18,24 @@ //! Autogenerated weights for pallet_child_bounties //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-12-03, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 +//! DATE: 2022-01-19, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/release/substrate +// ./target/optimized/substrate // benchmark // --chain=dev // --steps=50 // --repeat=20 -// --pallet -// pallet_child_bounties +// --pallet=pallet_child_bounties // --extrinsic=* // --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/child-bounties/src/ -// --template=./.maintain/frame-weight-template.hbs +// --output=./weights-optimized/frame/child-bounties/src//weights.rs +// --template=.maintain/frame-weight-template.hbs +// --header=HEADER-APACHE2 +// --raw #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -64,10 +65,8 @@ impl WeightInfo for SubstrateWeight { // Storage: ChildBounties ChildBountyCount (r:1 w:1) // Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) // Storage: ChildBounties ChildBounties (r:0 w:1) - fn add_child_bounty(d: u32, ) -> Weight { - (113_579_000 as Weight) - // Standard Error: 1_000 - .saturating_add((4_000 as Weight).saturating_mul(d as Weight)) + fn add_child_bounty(_d: u32, ) -> Weight { + (44_997_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } @@ -75,7 +74,7 @@ impl WeightInfo for SubstrateWeight { // Storage: ChildBounties ChildBounties (r:1 w:1) // Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) fn propose_curator() -> Weight { - (24_000_000 as Weight) + (11_848_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -83,7 +82,7 @@ impl WeightInfo for SubstrateWeight { // Storage: ChildBounties ChildBounties (r:1 w:1) // Storage: System Account (r:1 w:1) fn accept_curator() -> Weight { - (55_000_000 as Weight) + (24_490_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -91,14 +90,14 @@ impl WeightInfo for SubstrateWeight { // Storage: Bounties Bounties (r:1 w:0) // Storage: System Account (r:1 w:1) fn unassign_curator() -> Weight { - (61_000_000 as Weight) + (28_605_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Bounties Bounties (r:1 w:0) // Storage: ChildBounties ChildBounties (r:1 w:1) fn award_child_bounty() -> Weight { - (42_000_000 as Weight) + (19_471_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -107,7 +106,7 @@ impl WeightInfo for SubstrateWeight { // Storage: ChildBounties ParentChildBounties (r:1 w:1) // Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) fn claim_child_bounty() -> Weight { - (153_000_000 as Weight) + (60_737_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } @@ -118,7 +117,7 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:2 w:2) // Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) fn close_child_bounty_added() -> Weight { - (101_000_000 as Weight) + (43_120_000 as Weight) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } @@ -129,7 +128,7 @@ impl WeightInfo for SubstrateWeight { // Storage: ChildBounties ParentChildBounties (r:1 w:1) // Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) fn close_child_bounty_active() -> Weight { - (130_000_000 as Weight) + (53_610_000 as Weight) .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(7 as Weight)) } @@ -143,10 +142,8 @@ impl WeightInfo for () { // Storage: ChildBounties ChildBountyCount (r:1 w:1) // Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) // Storage: ChildBounties ChildBounties (r:0 w:1) - fn add_child_bounty(d: u32, ) -> Weight { - (113_579_000 as Weight) - // Standard Error: 1_000 - .saturating_add((4_000 as Weight).saturating_mul(d as Weight)) + fn add_child_bounty(_d: u32, ) -> Weight { + (44_997_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } @@ -154,7 +151,7 @@ impl WeightInfo for () { // Storage: ChildBounties ChildBounties (r:1 w:1) // Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) fn propose_curator() -> Weight { - (24_000_000 as Weight) + (11_848_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -162,7 +159,7 @@ impl WeightInfo for () { // Storage: ChildBounties ChildBounties (r:1 w:1) // Storage: System Account (r:1 w:1) fn accept_curator() -> Weight { - (55_000_000 as Weight) + (24_490_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -170,14 +167,14 @@ impl WeightInfo for () { // Storage: Bounties Bounties (r:1 w:0) // Storage: System Account (r:1 w:1) fn unassign_curator() -> Weight { - (61_000_000 as Weight) + (28_605_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Bounties Bounties (r:1 w:0) // Storage: ChildBounties ChildBounties (r:1 w:1) fn award_child_bounty() -> Weight { - (42_000_000 as Weight) + (19_471_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -186,7 +183,7 @@ impl WeightInfo for () { // Storage: ChildBounties ParentChildBounties (r:1 w:1) // Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) fn claim_child_bounty() -> Weight { - (153_000_000 as Weight) + (60_737_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } @@ -197,7 +194,7 @@ impl WeightInfo for () { // Storage: System Account (r:2 w:2) // Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) fn close_child_bounty_added() -> Weight { - (101_000_000 as Weight) + (43_120_000 as Weight) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } @@ -208,7 +205,7 @@ impl WeightInfo for () { // Storage: ChildBounties ParentChildBounties (r:1 w:1) // Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) fn close_child_bounty_active() -> Weight { - (130_000_000 as Weight) + (53_610_000 as Weight) .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(7 as Weight)) } diff --git a/frame/collective/src/tests.rs b/frame/collective/src/tests.rs index 4f40e02732b4..f77e52a9b6fe 100644 --- a/frame/collective/src/tests.rs +++ b/frame/collective/src/tests.rs @@ -175,7 +175,7 @@ pub fn new_test_ext() -> sp_io::TestExternalities { } fn make_proposal(value: u64) -> Call { - Call::System(frame_system::Call::remark { remark: value.encode() }) + Call::System(frame_system::Call::remark_with_event { remark: value.to_be_bytes().to_vec() }) } fn record(event: Event) -> EventRecord { diff --git a/frame/collective/src/weights.rs b/frame/collective/src/weights.rs index bdb07834a66c..a559261fdea0 100644 --- a/frame/collective/src/weights.rs +++ b/frame/collective/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. +// Copyright (C) 2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_collective //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-08-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 +//! DATE: 2022-01-17, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// target/release/substrate +// ./target/lto-fat-cg1/substrate // benchmark // --chain=dev // --steps=50 @@ -33,8 +33,9 @@ // --wasm-execution=compiled // --heap-pages=4096 // --output=./frame/collective/src/weights.rs -// --template=./.maintain/frame-weight-template.hbs - +// --template=.maintain/frame-weight-template.hbs +// --header=LICENSE-APACHE2 +// --raw #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -60,132 +61,132 @@ pub trait WeightInfo { /// Weights for pallet_collective using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - // Storage: Instance1Collective Members (r:1 w:1) - // Storage: Instance1Collective Proposals (r:1 w:0) - // Storage: Instance1Collective Voting (r:100 w:100) - // Storage: Instance1Collective Prime (r:0 w:1) + // Storage: Council Members (r:1 w:1) + // Storage: Council Proposals (r:1 w:0) + // Storage: Council Voting (r:100 w:100) + // Storage: Council Prime (r:0 w:1) fn set_members(m: u32, n: u32, p: u32, ) -> Weight { (0 as Weight) - // Standard Error: 4_000 - .saturating_add((14_084_000 as Weight).saturating_mul(m as Weight)) - // Standard Error: 4_000 - .saturating_add((161_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 4_000 - .saturating_add((19_201_000 as Weight).saturating_mul(p as Weight)) + // Standard Error: 7_000 + .saturating_add((12_933_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 7_000 + .saturating_add((81_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 7_000 + .saturating_add((15_645_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(p as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(p as Weight))) } - // Storage: Instance1Collective Members (r:1 w:0) + // Storage: Council Members (r:1 w:0) fn execute(b: u32, m: u32, ) -> Weight { - (22_748_000 as Weight) + (12_975_000 as Weight) // Standard Error: 0 - .saturating_add((3_000 as Weight).saturating_mul(b as Weight)) + .saturating_add((2_000 as Weight).saturating_mul(b as Weight)) // Standard Error: 0 - .saturating_add((92_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((74_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) } - // Storage: Instance1Collective Members (r:1 w:0) - // Storage: Instance1Collective ProposalOf (r:1 w:0) + // Storage: Council Members (r:1 w:0) + // Storage: Council ProposalOf (r:1 w:0) fn propose_execute(b: u32, m: u32, ) -> Weight { - (27_465_000 as Weight) + (15_120_000 as Weight) // Standard Error: 0 - .saturating_add((3_000 as Weight).saturating_mul(b as Weight)) + .saturating_add((2_000 as Weight).saturating_mul(b as Weight)) // Standard Error: 0 - .saturating_add((178_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((139_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) } - // Storage: Instance1Collective Members (r:1 w:0) - // Storage: Instance1Collective ProposalOf (r:1 w:1) - // Storage: Instance1Collective Proposals (r:1 w:1) - // Storage: Instance1Collective ProposalCount (r:1 w:1) - // Storage: Instance1Collective Voting (r:0 w:1) + // Storage: Council Members (r:1 w:0) + // Storage: Council ProposalOf (r:1 w:1) + // Storage: Council Proposals (r:1 w:1) + // Storage: Council ProposalCount (r:1 w:1) + // Storage: Council Voting (r:0 w:1) fn propose_proposed(b: u32, m: u32, p: u32, ) -> Weight { - (39_869_000 as Weight) + (18_343_000 as Weight) // Standard Error: 0 .saturating_add((8_000 as Weight).saturating_mul(b as Weight)) // Standard Error: 1_000 - .saturating_add((107_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((83_000 as Weight).saturating_mul(m as Weight)) // Standard Error: 1_000 - .saturating_add((406_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((211_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } - // Storage: Instance1Collective Members (r:1 w:0) - // Storage: Instance1Collective Voting (r:1 w:1) + // Storage: Council Members (r:1 w:0) + // Storage: Council Voting (r:1 w:1) fn vote(m: u32, ) -> Weight { - (37_387_000 as Weight) + (26_675_000 as Weight) // Standard Error: 2_000 - .saturating_add((223_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((166_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - // Storage: Instance1Collective Voting (r:1 w:1) - // Storage: Instance1Collective Members (r:1 w:0) - // Storage: Instance1Collective Proposals (r:1 w:1) - // Storage: Instance1Collective ProposalOf (r:0 w:1) + // Storage: Council Voting (r:1 w:1) + // Storage: Council Members (r:1 w:0) + // Storage: Council Proposals (r:1 w:1) + // Storage: Council ProposalOf (r:0 w:1) fn close_early_disapproved(m: u32, p: u32, ) -> Weight { - (45_670_000 as Weight) + (28_535_000 as Weight) // Standard Error: 1_000 - .saturating_add((170_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((123_000 as Weight).saturating_mul(m as Weight)) // Standard Error: 1_000 - .saturating_add((358_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((154_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } - // Storage: Instance1Collective Voting (r:1 w:1) - // Storage: Instance1Collective Members (r:1 w:0) - // Storage: Instance1Collective ProposalOf (r:1 w:1) - // Storage: Instance1Collective Proposals (r:1 w:1) + // Storage: Council Voting (r:1 w:1) + // Storage: Council Members (r:1 w:0) + // Storage: Council ProposalOf (r:1 w:1) + // Storage: Council Proposals (r:1 w:1) fn close_early_approved(b: u32, m: u32, p: u32, ) -> Weight { - (52_529_000 as Weight) + (27_235_000 as Weight) // Standard Error: 0 - .saturating_add((7_000 as Weight).saturating_mul(b as Weight)) + .saturating_add((6_000 as Weight).saturating_mul(b as Weight)) // Standard Error: 1_000 - .saturating_add((206_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((158_000 as Weight).saturating_mul(m as Weight)) // Standard Error: 1_000 - .saturating_add((412_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((201_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } - // Storage: Instance1Collective Voting (r:1 w:1) - // Storage: Instance1Collective Members (r:1 w:0) - // Storage: Instance1Collective Prime (r:1 w:0) - // Storage: Instance1Collective Proposals (r:1 w:1) - // Storage: Instance1Collective ProposalOf (r:0 w:1) + // Storage: Council Voting (r:1 w:1) + // Storage: Council Members (r:1 w:0) + // Storage: Council Prime (r:1 w:0) + // Storage: Council Proposals (r:1 w:1) + // Storage: Council ProposalOf (r:0 w:1) fn close_disapproved(m: u32, p: u32, ) -> Weight { - (50_427_000 as Weight) + (29_502_000 as Weight) // Standard Error: 1_000 - .saturating_add((170_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((139_000 as Weight).saturating_mul(m as Weight)) // Standard Error: 1_000 - .saturating_add((354_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((163_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } - // Storage: Instance1Collective Voting (r:1 w:1) - // Storage: Instance1Collective Members (r:1 w:0) - // Storage: Instance1Collective Prime (r:1 w:0) - // Storage: Instance1Collective ProposalOf (r:1 w:1) - // Storage: Instance1Collective Proposals (r:1 w:1) + // Storage: Council Voting (r:1 w:1) + // Storage: Council Members (r:1 w:0) + // Storage: Council Prime (r:1 w:0) + // Storage: Council ProposalOf (r:1 w:1) + // Storage: Council Proposals (r:1 w:1) fn close_approved(b: u32, m: u32, p: u32, ) -> Weight { - (57_031_000 as Weight) + (28_944_000 as Weight) // Standard Error: 0 - .saturating_add((7_000 as Weight).saturating_mul(b as Weight)) + .saturating_add((5_000 as Weight).saturating_mul(b as Weight)) // Standard Error: 1_000 - .saturating_add((208_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((170_000 as Weight).saturating_mul(m as Weight)) // Standard Error: 1_000 - .saturating_add((408_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((208_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } - // Storage: Instance1Collective Proposals (r:1 w:1) - // Storage: Instance1Collective Voting (r:0 w:1) - // Storage: Instance1Collective ProposalOf (r:0 w:1) + // Storage: Council Proposals (r:1 w:1) + // Storage: Council Voting (r:0 w:1) + // Storage: Council ProposalOf (r:0 w:1) fn disapprove_proposal(p: u32, ) -> Weight { - (27_458_000 as Weight) + (16_215_000 as Weight) // Standard Error: 1_000 - .saturating_add((402_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((212_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -193,132 +194,132 @@ impl WeightInfo for SubstrateWeight { // For backwards compatibility and tests impl WeightInfo for () { - // Storage: Instance1Collective Members (r:1 w:1) - // Storage: Instance1Collective Proposals (r:1 w:0) - // Storage: Instance1Collective Voting (r:100 w:100) - // Storage: Instance1Collective Prime (r:0 w:1) + // Storage: Council Members (r:1 w:1) + // Storage: Council Proposals (r:1 w:0) + // Storage: Council Voting (r:100 w:100) + // Storage: Council Prime (r:0 w:1) fn set_members(m: u32, n: u32, p: u32, ) -> Weight { (0 as Weight) - // Standard Error: 4_000 - .saturating_add((14_084_000 as Weight).saturating_mul(m as Weight)) - // Standard Error: 4_000 - .saturating_add((161_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 4_000 - .saturating_add((19_201_000 as Weight).saturating_mul(p as Weight)) + // Standard Error: 7_000 + .saturating_add((12_933_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 7_000 + .saturating_add((81_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 7_000 + .saturating_add((15_645_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(p as Weight))) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(p as Weight))) } - // Storage: Instance1Collective Members (r:1 w:0) + // Storage: Council Members (r:1 w:0) fn execute(b: u32, m: u32, ) -> Weight { - (22_748_000 as Weight) + (12_975_000 as Weight) // Standard Error: 0 - .saturating_add((3_000 as Weight).saturating_mul(b as Weight)) + .saturating_add((2_000 as Weight).saturating_mul(b as Weight)) // Standard Error: 0 - .saturating_add((92_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((74_000 as Weight).saturating_mul(m as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) } - // Storage: Instance1Collective Members (r:1 w:0) - // Storage: Instance1Collective ProposalOf (r:1 w:0) + // Storage: Council Members (r:1 w:0) + // Storage: Council ProposalOf (r:1 w:0) fn propose_execute(b: u32, m: u32, ) -> Weight { - (27_465_000 as Weight) + (15_120_000 as Weight) // Standard Error: 0 - .saturating_add((3_000 as Weight).saturating_mul(b as Weight)) + .saturating_add((2_000 as Weight).saturating_mul(b as Weight)) // Standard Error: 0 - .saturating_add((178_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((139_000 as Weight).saturating_mul(m as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) } - // Storage: Instance1Collective Members (r:1 w:0) - // Storage: Instance1Collective ProposalOf (r:1 w:1) - // Storage: Instance1Collective Proposals (r:1 w:1) - // Storage: Instance1Collective ProposalCount (r:1 w:1) - // Storage: Instance1Collective Voting (r:0 w:1) + // Storage: Council Members (r:1 w:0) + // Storage: Council ProposalOf (r:1 w:1) + // Storage: Council Proposals (r:1 w:1) + // Storage: Council ProposalCount (r:1 w:1) + // Storage: Council Voting (r:0 w:1) fn propose_proposed(b: u32, m: u32, p: u32, ) -> Weight { - (39_869_000 as Weight) + (18_343_000 as Weight) // Standard Error: 0 .saturating_add((8_000 as Weight).saturating_mul(b as Weight)) // Standard Error: 1_000 - .saturating_add((107_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((83_000 as Weight).saturating_mul(m as Weight)) // Standard Error: 1_000 - .saturating_add((406_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((211_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } - // Storage: Instance1Collective Members (r:1 w:0) - // Storage: Instance1Collective Voting (r:1 w:1) + // Storage: Council Members (r:1 w:0) + // Storage: Council Voting (r:1 w:1) fn vote(m: u32, ) -> Weight { - (37_387_000 as Weight) + (26_675_000 as Weight) // Standard Error: 2_000 - .saturating_add((223_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((166_000 as Weight).saturating_mul(m as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } - // Storage: Instance1Collective Voting (r:1 w:1) - // Storage: Instance1Collective Members (r:1 w:0) - // Storage: Instance1Collective Proposals (r:1 w:1) - // Storage: Instance1Collective ProposalOf (r:0 w:1) + // Storage: Council Voting (r:1 w:1) + // Storage: Council Members (r:1 w:0) + // Storage: Council Proposals (r:1 w:1) + // Storage: Council ProposalOf (r:0 w:1) fn close_early_disapproved(m: u32, p: u32, ) -> Weight { - (45_670_000 as Weight) + (28_535_000 as Weight) // Standard Error: 1_000 - .saturating_add((170_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((123_000 as Weight).saturating_mul(m as Weight)) // Standard Error: 1_000 - .saturating_add((358_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((154_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } - // Storage: Instance1Collective Voting (r:1 w:1) - // Storage: Instance1Collective Members (r:1 w:0) - // Storage: Instance1Collective ProposalOf (r:1 w:1) - // Storage: Instance1Collective Proposals (r:1 w:1) + // Storage: Council Voting (r:1 w:1) + // Storage: Council Members (r:1 w:0) + // Storage: Council ProposalOf (r:1 w:1) + // Storage: Council Proposals (r:1 w:1) fn close_early_approved(b: u32, m: u32, p: u32, ) -> Weight { - (52_529_000 as Weight) + (27_235_000 as Weight) // Standard Error: 0 - .saturating_add((7_000 as Weight).saturating_mul(b as Weight)) + .saturating_add((6_000 as Weight).saturating_mul(b as Weight)) // Standard Error: 1_000 - .saturating_add((206_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((158_000 as Weight).saturating_mul(m as Weight)) // Standard Error: 1_000 - .saturating_add((412_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((201_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } - // Storage: Instance1Collective Voting (r:1 w:1) - // Storage: Instance1Collective Members (r:1 w:0) - // Storage: Instance1Collective Prime (r:1 w:0) - // Storage: Instance1Collective Proposals (r:1 w:1) - // Storage: Instance1Collective ProposalOf (r:0 w:1) + // Storage: Council Voting (r:1 w:1) + // Storage: Council Members (r:1 w:0) + // Storage: Council Prime (r:1 w:0) + // Storage: Council Proposals (r:1 w:1) + // Storage: Council ProposalOf (r:0 w:1) fn close_disapproved(m: u32, p: u32, ) -> Weight { - (50_427_000 as Weight) + (29_502_000 as Weight) // Standard Error: 1_000 - .saturating_add((170_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((139_000 as Weight).saturating_mul(m as Weight)) // Standard Error: 1_000 - .saturating_add((354_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((163_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } - // Storage: Instance1Collective Voting (r:1 w:1) - // Storage: Instance1Collective Members (r:1 w:0) - // Storage: Instance1Collective Prime (r:1 w:0) - // Storage: Instance1Collective ProposalOf (r:1 w:1) - // Storage: Instance1Collective Proposals (r:1 w:1) + // Storage: Council Voting (r:1 w:1) + // Storage: Council Members (r:1 w:0) + // Storage: Council Prime (r:1 w:0) + // Storage: Council ProposalOf (r:1 w:1) + // Storage: Council Proposals (r:1 w:1) fn close_approved(b: u32, m: u32, p: u32, ) -> Weight { - (57_031_000 as Weight) + (28_944_000 as Weight) // Standard Error: 0 - .saturating_add((7_000 as Weight).saturating_mul(b as Weight)) + .saturating_add((5_000 as Weight).saturating_mul(b as Weight)) // Standard Error: 1_000 - .saturating_add((208_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((170_000 as Weight).saturating_mul(m as Weight)) // Standard Error: 1_000 - .saturating_add((408_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((208_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } - // Storage: Instance1Collective Proposals (r:1 w:1) - // Storage: Instance1Collective Voting (r:0 w:1) - // Storage: Instance1Collective ProposalOf (r:0 w:1) + // Storage: Council Proposals (r:1 w:1) + // Storage: Council Voting (r:0 w:1) + // Storage: Council ProposalOf (r:0 w:1) fn disapprove_proposal(p: u32, ) -> Weight { - (27_458_000 as Weight) + (16_215_000 as Weight) // Standard Error: 1_000 - .saturating_add((402_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((212_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } diff --git a/frame/contracts/src/weights.rs b/frame/contracts/src/weights.rs index 17ee020f0113..655cba5d3b9a 100644 --- a/frame/contracts/src/weights.rs +++ b/frame/contracts/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. +// Copyright (C) 2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_contracts //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-12-20, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 +//! DATE: 2022-01-17, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// target/release/substrate +// ./target/lto-fat-cg1/substrate // benchmark // --chain=dev // --steps=50 @@ -33,7 +33,9 @@ // --wasm-execution=compiled // --heap-pages=4096 // --output=./frame/contracts/src/weights.rs -// --template=./.maintain/frame-weight-template.hbs +// --template=.maintain/frame-weight-template.hbs +// --header=LICENSE-APACHE2 +// --raw #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -153,32 +155,32 @@ pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize() -> Weight { - (2_286_000 as Weight) + (1_585_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn on_initialize_per_trie_key(k: u32, ) -> Weight { - (0 as Weight) - // Standard Error: 3_000 - .saturating_add((2_219_000 as Weight).saturating_mul(k as Weight)) + (7_902_000 as Weight) + // Standard Error: 0 + .saturating_add((751_000 as Weight).saturating_mul(k as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) } // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize_per_queue_item(q: u32, ) -> Weight { - (95_627_000 as Weight) - // Standard Error: 2_000 - .saturating_add((242_000 as Weight).saturating_mul(q as Weight)) + (31_473_000 as Weight) + // Standard Error: 1_000 + .saturating_add((104_000 as Weight).saturating_mul(q as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Contracts PristineCode (r:1 w:0) // Storage: Contracts CodeStorage (r:0 w:1) fn reinstrument(c: u32, ) -> Weight { - (17_037_000 as Weight) - // Standard Error: 98_000 - .saturating_add((88_875_000 as Weight).saturating_mul(c as Weight)) + (15_462_000 as Weight) + // Standard Error: 35_000 + .saturating_add((81_710_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -187,9 +189,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call_with_code_kb(c: u32, ) -> Weight { - (348_110_000 as Weight) - // Standard Error: 136_000 - .saturating_add((81_086_000 as Weight).saturating_mul(c as Weight)) + (169_561_000 as Weight) + // Standard Error: 56_000 + .saturating_add((60_037_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -201,11 +203,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn instantiate_with_code(c: u32, s: u32, ) -> Weight { - (414_966_000 as Weight) - // Standard Error: 137_000 - .saturating_add((198_330_000 as Weight).saturating_mul(c as Weight)) + (169_885_000 as Weight) + // Standard Error: 127_000 + .saturating_add((170_680_000 as Weight).saturating_mul(c as Weight)) // Standard Error: 8_000 - .saturating_add((2_180_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((1_788_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } @@ -216,9 +218,9 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn instantiate(s: u32, ) -> Weight { - (201_465_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_993_000 as Weight).saturating_mul(s as Weight)) + (150_265_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_722_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } @@ -227,7 +229,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call() -> Weight { - (154_139_000 as Weight) + (114_784_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -235,9 +237,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn upload_code(c: u32, ) -> Weight { - (69_640_000 as Weight) - // Standard Error: 93_000 - .saturating_add((89_969_000 as Weight).saturating_mul(c as Weight)) + (48_072_000 as Weight) + // Standard Error: 36_000 + .saturating_add((83_578_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -245,7 +247,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:0 w:1) // Storage: Contracts PristineCode (r:0 w:1) fn remove_code() -> Weight { - (31_567_000 as Weight) + (24_739_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -254,9 +256,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_caller(r: u32, ) -> Weight { - (405_395_000 as Weight) - // Standard Error: 167_000 - .saturating_add((79_867_000 as Weight).saturating_mul(r as Weight)) + (174_123_000 as Weight) + // Standard Error: 127_000 + .saturating_add((56_078_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -265,9 +267,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_address(r: u32, ) -> Weight { - (405_173_000 as Weight) - // Standard Error: 152_000 - .saturating_add((79_619_000 as Weight).saturating_mul(r as Weight)) + (180_168_000 as Weight) + // Standard Error: 122_000 + .saturating_add((56_154_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -276,9 +278,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas_left(r: u32, ) -> Weight { - (406_537_000 as Weight) - // Standard Error: 148_000 - .saturating_add((78_129_000 as Weight).saturating_mul(r as Weight)) + (179_464_000 as Weight) + // Standard Error: 96_000 + .saturating_add((55_350_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -287,9 +289,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_balance(r: u32, ) -> Weight { - (416_289_000 as Weight) - // Standard Error: 165_000 - .saturating_add((218_401_000 as Weight).saturating_mul(r as Weight)) + (181_031_000 as Weight) + // Standard Error: 154_000 + .saturating_add((149_508_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -298,9 +300,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_value_transferred(r: u32, ) -> Weight { - (408_205_000 as Weight) - // Standard Error: 154_000 - .saturating_add((79_563_000 as Weight).saturating_mul(r as Weight)) + (178_709_000 as Weight) + // Standard Error: 107_000 + .saturating_add((56_326_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -309,9 +311,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_minimum_balance(r: u32, ) -> Weight { - (408_124_000 as Weight) - // Standard Error: 149_000 - .saturating_add((79_032_000 as Weight).saturating_mul(r as Weight)) + (175_715_000 as Weight) + // Standard Error: 116_000 + .saturating_add((56_755_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -320,9 +322,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_block_number(r: u32, ) -> Weight { - (406_141_000 as Weight) - // Standard Error: 150_000 - .saturating_add((78_992_000 as Weight).saturating_mul(r as Weight)) + (178_552_000 as Weight) + // Standard Error: 121_000 + .saturating_add((55_756_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -331,9 +333,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_now(r: u32, ) -> Weight { - (418_112_000 as Weight) - // Standard Error: 155_000 - .saturating_add((77_902_000 as Weight).saturating_mul(r as Weight)) + (186_172_000 as Weight) + // Standard Error: 106_000 + .saturating_add((55_311_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -343,9 +345,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0) fn seal_weight_to_fee(r: u32, ) -> Weight { - (411_683_000 as Weight) - // Standard Error: 173_000 - .saturating_add((205_824_000 as Weight).saturating_mul(r as Weight)) + (183_750_000 as Weight) + // Standard Error: 140_000 + .saturating_add((131_877_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -354,9 +356,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas(r: u32, ) -> Weight { - (132_178_000 as Weight) - // Standard Error: 84_000 - .saturating_add((38_233_000 as Weight).saturating_mul(r as Weight)) + (97_350_000 as Weight) + // Standard Error: 54_000 + .saturating_add((27_606_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -365,9 +367,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input(r: u32, ) -> Weight { - (405_685_000 as Weight) - // Standard Error: 142_000 - .saturating_add((72_826_000 as Weight).saturating_mul(r as Weight)) + (179_058_000 as Weight) + // Standard Error: 106_000 + .saturating_add((53_258_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -376,9 +378,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input_per_kb(n: u32, ) -> Weight { - (490_336_000 as Weight) - // Standard Error: 7_000 - .saturating_add((38_070_000 as Weight).saturating_mul(n as Weight)) + (248_562_000 as Weight) + // Standard Error: 5_000 + .saturating_add((10_515_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -387,9 +389,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return(r: u32, ) -> Weight { - (384_543_000 as Weight) - // Standard Error: 105_000 - .saturating_add((15_793_000 as Weight).saturating_mul(r as Weight)) + (161_228_000 as Weight) + // Standard Error: 90_000 + .saturating_add((14_539_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -398,9 +400,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return_per_kb(n: u32, ) -> Weight { - (399_205_000 as Weight) - // Standard Error: 1_000 - .saturating_add((637_000 as Weight).saturating_mul(n as Weight)) + (177_866_000 as Weight) + // Standard Error: 0 + .saturating_add((188_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -411,9 +413,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts DeletionQueue (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_terminate(r: u32, ) -> Weight { - (396_375_000 as Weight) - // Standard Error: 3_023_000 - .saturating_add((79_797_000 as Weight).saturating_mul(r as Weight)) + (164_572_000 as Weight) + // Standard Error: 1_817_000 + .saturating_add((68_480_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((4 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -425,9 +427,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) fn seal_random(r: u32, ) -> Weight { - (390_550_000 as Weight) - // Standard Error: 290_000 - .saturating_add((245_730_000 as Weight).saturating_mul(r as Weight)) + (168_658_000 as Weight) + // Standard Error: 189_000 + .saturating_add((166_190_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -436,9 +438,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_deposit_event(r: u32, ) -> Weight { - (408_011_000 as Weight) - // Standard Error: 273_000 - .saturating_add((406_522_000 as Weight).saturating_mul(r as Weight)) + (185_391_000 as Weight) + // Standard Error: 191_000 + .saturating_add((292_609_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -448,11 +450,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: System EventTopics (r:100 w:100) fn seal_deposit_event_per_topic_and_kb(t: u32, n: u32, ) -> Weight { - (890_741_000 as Weight) - // Standard Error: 2_072_000 - .saturating_add((382_953_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 408_000 - .saturating_add((162_320_000 as Weight).saturating_mul(n as Weight)) + (507_994_000 as Weight) + // Standard Error: 1_569_000 + .saturating_add((276_852_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 309_000 + .saturating_add((79_461_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(t as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -463,17 +465,17 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_debug_message(r: u32, ) -> Weight { - (153_163_000 as Weight) - // Standard Error: 137_000 - .saturating_add((59_081_000 as Weight).saturating_mul(r as Weight)) + (99_048_000 as Weight) + // Standard Error: 87_000 + .saturating_add((46_088_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage(r: u32, ) -> Weight { - (459_368_000 as Weight) - // Standard Error: 560_000 - .saturating_add((330_190_000 as Weight).saturating_mul(r as Weight)) + (142_559_000 as Weight) + // Standard Error: 603_000 + .saturating_add((269_723_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -485,17 +487,17 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: unknown [0x7afa01283080ef247df84e0ba38ea5a587d25ce6633a6bfbba02068c14023441] (r:1 w:1) fn seal_set_storage_per_kb(n: u32, ) -> Weight { - (727_394_000 as Weight) - // Standard Error: 247_000 - .saturating_add((73_350_000 as Weight).saturating_mul(n as Weight)) + (346_704_000 as Weight) + // Standard Error: 200_000 + .saturating_add((29_907_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage(r: u32, ) -> Weight { - (163_262_000 as Weight) - // Standard Error: 1_492_000 - .saturating_add((799_087_000 as Weight).saturating_mul(r as Weight)) + (0 as Weight) + // Standard Error: 1_963_000 + .saturating_add((746_581_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -503,18 +505,18 @@ impl WeightInfo for SubstrateWeight { } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage(r: u32, ) -> Weight { - (288_728_000 as Weight) - // Standard Error: 752_000 - .saturating_add((434_780_000 as Weight).saturating_mul(r as Weight)) + (69_873_000 as Weight) + // Standard Error: 722_000 + .saturating_add((338_292_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_contains_storage(r: u32, ) -> Weight { - (209_606_000 as Weight) - // Standard Error: 1_137_000 - .saturating_add((680_187_000 as Weight).saturating_mul(r as Weight)) + (0 as Weight) + // Standard Error: 1_169_000 + .saturating_add((480_500_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -525,17 +527,17 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: unknown [0x7afa01283080ef247df84e0ba38ea5a587d25ce6633a6bfbba02068c14023441] (r:1 w:0) fn seal_get_storage_per_kb(n: u32, ) -> Weight { - (619_600_000 as Weight) - // Standard Error: 207_000 - .saturating_add((111_030_000 as Weight).saturating_mul(n as Weight)) + (327_625_000 as Weight) + // Standard Error: 146_000 + .saturating_add((55_028_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage(r: u32, ) -> Weight { - (279_528_000 as Weight) - // Standard Error: 932_000 - .saturating_add((541_965_000 as Weight).saturating_mul(r as Weight)) + (41_931_000 as Weight) + // Standard Error: 933_000 + .saturating_add((433_619_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -543,9 +545,9 @@ impl WeightInfo for SubstrateWeight { } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage_per_kb(n: u32, ) -> Weight { - (985_732_000 as Weight) - // Standard Error: 446_000 - .saturating_add((123_295_000 as Weight).saturating_mul(n as Weight)) + (639_259_000 as Weight) + // Standard Error: 365_000 + .saturating_add((64_588_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().writes(103 as Weight)) } @@ -554,9 +556,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_transfer(r: u32, ) -> Weight { - (284_785_000 as Weight) - // Standard Error: 1_479_000 - .saturating_add((2_527_544_000 as Weight).saturating_mul(r as Weight)) + (71_335_000 as Weight) + // Standard Error: 1_489_000 + .saturating_add((1_765_321_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -568,8 +570,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) fn seal_call(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 5_742_000 - .saturating_add((37_993_391_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 9_243_000 + .saturating_add((16_121_990_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -580,13 +582,13 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:2 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_call_per_transfer_input_output_kb(t: u32, i: u32, o: u32, ) -> Weight { - (37_404_660_000 as Weight) - // Standard Error: 92_661_000 - .saturating_add((2_486_257_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 33_000 - .saturating_add((63_001_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 35_000 - .saturating_add((101_347_000 as Weight).saturating_mul(o as Weight)) + (15_978_164_000 as Weight) + // Standard Error: 57_271_000 + .saturating_add((1_179_479_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 20_000 + .saturating_add((17_389_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 21_000 + .saturating_add((28_660_000 as Weight).saturating_mul(o as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().reads((101 as Weight).saturating_mul(t as Weight))) .saturating_add(T::DbWeight::get().writes(101 as Weight)) @@ -600,8 +602,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts OwnerInfoOf (r:100 w:100) fn seal_instantiate(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 119_281_000 - .saturating_add((47_113_525_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 115_056_000 + .saturating_add((23_312_565_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().reads((400 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -614,13 +616,13 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts AccountCounter (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_instantiate_per_input_output_salt_kb(i: u32, o: u32, s: u32, ) -> Weight { - (41_157_901_000 as Weight) - // Standard Error: 147_000 - .saturating_add((64_877_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 147_000 - .saturating_add((102_420_000 as Weight).saturating_mul(o as Weight)) - // Standard Error: 147_000 - .saturating_add((201_587_000 as Weight).saturating_mul(s as Weight)) + (18_724_034_000 as Weight) + // Standard Error: 66_000 + .saturating_add((18_363_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 66_000 + .saturating_add((29_093_000 as Weight).saturating_mul(o as Weight)) + // Standard Error: 66_000 + .saturating_add((158_645_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(208 as Weight)) .saturating_add(T::DbWeight::get().writes(206 as Weight)) } @@ -629,9 +631,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256(r: u32, ) -> Weight { - (402_224_000 as Weight) - // Standard Error: 166_000 - .saturating_add((103_985_000 as Weight).saturating_mul(r as Weight)) + (179_769_000 as Weight) + // Standard Error: 121_000 + .saturating_add((80_706_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -640,9 +642,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256_per_kb(n: u32, ) -> Weight { - (663_731_000 as Weight) - // Standard Error: 42_000 - .saturating_add((505_157_000 as Weight).saturating_mul(n as Weight)) + (279_632_000 as Weight) + // Standard Error: 17_000 + .saturating_add((372_618_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -651,9 +653,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256(r: u32, ) -> Weight { - (402_638_000 as Weight) - // Standard Error: 165_000 - .saturating_add((117_589_000 as Weight).saturating_mul(r as Weight)) + (182_040_000 as Weight) + // Standard Error: 119_000 + .saturating_add((88_916_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -662,9 +664,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256_per_kb(n: u32, ) -> Weight { - (491_978_000 as Weight) - // Standard Error: 23_000 - .saturating_add((363_687_000 as Weight).saturating_mul(n as Weight)) + (253_225_000 as Weight) + // Standard Error: 16_000 + .saturating_add((247_883_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -673,9 +675,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256(r: u32, ) -> Weight { - (402_254_000 as Weight) - // Standard Error: 154_000 - .saturating_add((86_403_000 as Weight).saturating_mul(r as Weight)) + (179_945_000 as Weight) + // Standard Error: 96_000 + .saturating_add((68_362_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -684,9 +686,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256_per_kb(n: u32, ) -> Weight { - (476_405_000 as Weight) - // Standard Error: 18_000 - .saturating_add((163_921_000 as Weight).saturating_mul(n as Weight)) + (191_286_000 as Weight) + // Standard Error: 38_000 + .saturating_add((121_358_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -695,9 +697,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128(r: u32, ) -> Weight { - (399_949_000 as Weight) - // Standard Error: 142_000 - .saturating_add((85_448_000 as Weight).saturating_mul(r as Weight)) + (179_381_000 as Weight) + // Standard Error: 101_000 + .saturating_add((68_158_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -706,9 +708,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128_per_kb(n: u32, ) -> Weight { - (475_437_000 as Weight) - // Standard Error: 15_000 - .saturating_add((163_921_000 as Weight).saturating_mul(n as Weight)) + (135_478_000 as Weight) + // Standard Error: 41_000 + .saturating_add((121_422_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -717,266 +719,266 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_ecdsa_recover(r: u32, ) -> Weight { - (373_575_000 as Weight) - // Standard Error: 1_639_000 - .saturating_add((15_530_027_000 as Weight).saturating_mul(r as Weight)) + (123_468_000 as Weight) + // Standard Error: 1_017_000 + .saturating_add((15_542_677_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn instr_i64const(r: u32, ) -> Weight { - (52_763_000 as Weight) + (52_702_000 as Weight) // Standard Error: 12_000 - .saturating_add((857_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((844_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64load(r: u32, ) -> Weight { - (47_313_000 as Weight) + (47_295_000 as Weight) // Standard Error: 10_000 - .saturating_add((2_935_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((3_045_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64store(r: u32, ) -> Weight { - (47_147_000 as Weight) - // Standard Error: 10_000 - .saturating_add((2_995_000 as Weight).saturating_mul(r as Weight)) + (46_353_000 as Weight) + // Standard Error: 9_000 + .saturating_add((3_047_000 as Weight).saturating_mul(r as Weight)) } fn instr_select(r: u32, ) -> Weight { - (50_124_000 as Weight) + (49_811_000 as Weight) // Standard Error: 11_000 - .saturating_add((2_421_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_408_000 as Weight).saturating_mul(r as Weight)) } fn instr_if(r: u32, ) -> Weight { - (47_288_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_523_000 as Weight).saturating_mul(r as Weight)) + (47_054_000 as Weight) + // Standard Error: 12_000 + .saturating_add((2_504_000 as Weight).saturating_mul(r as Weight)) } fn instr_br(r: u32, ) -> Weight { - (50_198_000 as Weight) + (49_912_000 as Weight) // Standard Error: 16_000 - .saturating_add((1_473_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_460_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_if(r: u32, ) -> Weight { - (44_008_000 as Weight) + (43_860_000 as Weight) // Standard Error: 17_000 - .saturating_add((2_174_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_150_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table(r: u32, ) -> Weight { - (37_602_000 as Weight) + (37_009_000 as Weight) // Standard Error: 16_000 - .saturating_add((2_820_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_762_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table_per_entry(e: u32, ) -> Weight { - (46_232_000 as Weight) + (45_776_000 as Weight) // Standard Error: 3_000 .saturating_add((17_000 as Weight).saturating_mul(e as Weight)) } fn instr_call(r: u32, ) -> Weight { - (40_148_000 as Weight) - // Standard Error: 22_000 - .saturating_add((20_585_000 as Weight).saturating_mul(r as Weight)) + (39_611_000 as Weight) + // Standard Error: 17_000 + .saturating_add((20_805_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect(r: u32, ) -> Weight { - (43_948_000 as Weight) - // Standard Error: 31_000 - .saturating_add((30_226_000 as Weight).saturating_mul(r as Weight)) + (45_523_000 as Weight) + // Standard Error: 27_000 + .saturating_add((31_622_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect_per_param(p: u32, ) -> Weight { - (78_722_000 as Weight) - // Standard Error: 5_000 - .saturating_add((1_199_000 as Weight).saturating_mul(p as Weight)) + (79_764_000 as Weight) + // Standard Error: 6_000 + .saturating_add((1_198_000 as Weight).saturating_mul(p as Weight)) } fn instr_local_get(r: u32, ) -> Weight { - (48_083_000 as Weight) - // Standard Error: 12_000 - .saturating_add((805_000 as Weight).saturating_mul(r as Weight)) + (46_510_000 as Weight) + // Standard Error: 11_000 + .saturating_add((810_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_set(r: u32, ) -> Weight { - (47_710_000 as Weight) + (46_567_000 as Weight) // Standard Error: 11_000 - .saturating_add((843_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((833_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_tee(r: u32, ) -> Weight { - (44_785_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_466_000 as Weight).saturating_mul(r as Weight)) + (43_439_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_463_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_get(r: u32, ) -> Weight { - (50_106_000 as Weight) - // Standard Error: 20_000 - .saturating_add((1_641_000 as Weight).saturating_mul(r as Weight)) + (46_201_000 as Weight) + // Standard Error: 19_000 + .saturating_add((1_635_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_set(r: u32, ) -> Weight { - (47_058_000 as Weight) + (42_639_000 as Weight) // Standard Error: 18_000 - .saturating_add((1_707_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_652_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_current(r: u32, ) -> Weight { - (51_494_000 as Weight) - // Standard Error: 15_000 - .saturating_add((925_000 as Weight).saturating_mul(r as Weight)) + (51_159_000 as Weight) + // Standard Error: 14_000 + .saturating_add((917_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_grow(r: u32, ) -> Weight { - (36_983_000 as Weight) - // Standard Error: 3_602_000 - .saturating_add((634_259_000 as Weight).saturating_mul(r as Weight)) + (36_462_000 as Weight) + // Standard Error: 867_000 + .saturating_add((187_724_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64clz(r: u32, ) -> Weight { - (60_711_000 as Weight) - // Standard Error: 22_000 - .saturating_add((1_157_000 as Weight).saturating_mul(r as Weight)) + (53_776_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_307_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ctz(r: u32, ) -> Weight { - (53_908_000 as Weight) - // Standard Error: 9_000 - .saturating_add((1_305_000 as Weight).saturating_mul(r as Weight)) + (53_674_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_304_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64popcnt(r: u32, ) -> Weight { - (53_939_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_314_000 as Weight).saturating_mul(r as Weight)) + (53_654_000 as Weight) + // Standard Error: 9_000 + .saturating_add((1_299_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eqz(r: u32, ) -> Weight { - (54_086_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_309_000 as Weight).saturating_mul(r as Weight)) + (53_493_000 as Weight) + // Standard Error: 9_000 + .saturating_add((1_299_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendsi32(r: u32, ) -> Weight { - (43_845_000 as Weight) + (43_373_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_493_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_492_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendui32(r: u32, ) -> Weight { - (43_518_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_501_000 as Weight).saturating_mul(r as Weight)) + (43_222_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_498_000 as Weight).saturating_mul(r as Weight)) } fn instr_i32wrapi64(r: u32, ) -> Weight { - (53_912_000 as Weight) + (53_706_000 as Weight) // Standard Error: 9_000 - .saturating_add((1_302_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_292_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eq(r: u32, ) -> Weight { - (49_594_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_890_000 as Weight).saturating_mul(r as Weight)) + (48_994_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_888_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ne(r: u32, ) -> Weight { - (49_659_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_894_000 as Weight).saturating_mul(r as Weight)) + (49_464_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_876_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64lts(r: u32, ) -> Weight { - (49_401_000 as Weight) + (49_194_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_902_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_884_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ltu(r: u32, ) -> Weight { - (49_880_000 as Weight) + (49_291_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_885_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_883_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gts(r: u32, ) -> Weight { - (49_466_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_894_000 as Weight).saturating_mul(r as Weight)) + (49_227_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_886_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gtu(r: u32, ) -> Weight { - (49_514_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_891_000 as Weight).saturating_mul(r as Weight)) + (49_219_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_885_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64les(r: u32, ) -> Weight { - (49_588_000 as Weight) + (49_263_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_898_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_882_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64leu(r: u32, ) -> Weight { - (49_589_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_891_000 as Weight).saturating_mul(r as Weight)) + (49_251_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_882_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ges(r: u32, ) -> Weight { - (49_685_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_892_000 as Weight).saturating_mul(r as Weight)) + (49_257_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_882_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64geu(r: u32, ) -> Weight { - (49_601_000 as Weight) + (49_219_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_891_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_885_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64add(r: u32, ) -> Weight { - (49_430_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_894_000 as Weight).saturating_mul(r as Weight)) + (49_221_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_888_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64sub(r: u32, ) -> Weight { - (49_533_000 as Weight) + (48_936_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_893_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_900_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64mul(r: u32, ) -> Weight { - (49_766_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_888_000 as Weight).saturating_mul(r as Weight)) + (49_266_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_882_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divs(r: u32, ) -> Weight { - (49_315_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_552_000 as Weight).saturating_mul(r as Weight)) + (49_246_000 as Weight) + // Standard Error: 10_000 + .saturating_add((2_565_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divu(r: u32, ) -> Weight { - (49_786_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_203_000 as Weight).saturating_mul(r as Weight)) + (49_181_000 as Weight) + // Standard Error: 10_000 + .saturating_add((2_211_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rems(r: u32, ) -> Weight { - (49_651_000 as Weight) + (49_337_000 as Weight) // Standard Error: 11_000 - .saturating_add((2_461_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_525_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64remu(r: u32, ) -> Weight { - (49_747_000 as Weight) - // Standard Error: 10_000 - .saturating_add((2_196_000 as Weight).saturating_mul(r as Weight)) + (49_387_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_241_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64and(r: u32, ) -> Weight { - (49_719_000 as Weight) + (49_137_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_892_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_900_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64or(r: u32, ) -> Weight { - (49_463_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_896_000 as Weight).saturating_mul(r as Weight)) + (49_366_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_882_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64xor(r: u32, ) -> Weight { - (49_379_000 as Weight) + (49_143_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_903_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_912_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shl(r: u32, ) -> Weight { - (49_404_000 as Weight) + (49_195_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_902_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_891_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shrs(r: u32, ) -> Weight { - (49_498_000 as Weight) - // Standard Error: 10_000 + (49_228_000 as Weight) + // Standard Error: 11_000 .saturating_add((1_900_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shru(r: u32, ) -> Weight { - (49_541_000 as Weight) + (49_279_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_897_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_888_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotl(r: u32, ) -> Weight { - (49_452_000 as Weight) + (49_091_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_900_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_909_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotr(r: u32, ) -> Weight { - (49_350_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_902_000 as Weight).saturating_mul(r as Weight)) + (49_436_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_883_000 as Weight).saturating_mul(r as Weight)) } } @@ -984,32 +986,32 @@ impl WeightInfo for SubstrateWeight { impl WeightInfo for () { // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize() -> Weight { - (2_286_000 as Weight) + (1_585_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn on_initialize_per_trie_key(k: u32, ) -> Weight { - (0 as Weight) - // Standard Error: 3_000 - .saturating_add((2_219_000 as Weight).saturating_mul(k as Weight)) + (7_902_000 as Weight) + // Standard Error: 0 + .saturating_add((751_000 as Weight).saturating_mul(k as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) } // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize_per_queue_item(q: u32, ) -> Weight { - (95_627_000 as Weight) - // Standard Error: 2_000 - .saturating_add((242_000 as Weight).saturating_mul(q as Weight)) + (31_473_000 as Weight) + // Standard Error: 1_000 + .saturating_add((104_000 as Weight).saturating_mul(q as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Contracts PristineCode (r:1 w:0) // Storage: Contracts CodeStorage (r:0 w:1) fn reinstrument(c: u32, ) -> Weight { - (17_037_000 as Weight) - // Standard Error: 98_000 - .saturating_add((88_875_000 as Weight).saturating_mul(c as Weight)) + (15_462_000 as Weight) + // Standard Error: 35_000 + .saturating_add((81_710_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1018,9 +1020,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call_with_code_kb(c: u32, ) -> Weight { - (348_110_000 as Weight) - // Standard Error: 136_000 - .saturating_add((81_086_000 as Weight).saturating_mul(c as Weight)) + (169_561_000 as Weight) + // Standard Error: 56_000 + .saturating_add((60_037_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -1032,11 +1034,11 @@ impl WeightInfo for () { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn instantiate_with_code(c: u32, s: u32, ) -> Weight { - (414_966_000 as Weight) - // Standard Error: 137_000 - .saturating_add((198_330_000 as Weight).saturating_mul(c as Weight)) + (169_885_000 as Weight) + // Standard Error: 127_000 + .saturating_add((170_680_000 as Weight).saturating_mul(c as Weight)) // Standard Error: 8_000 - .saturating_add((2_180_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((1_788_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } @@ -1047,9 +1049,9 @@ impl WeightInfo for () { // Storage: System Account (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn instantiate(s: u32, ) -> Weight { - (201_465_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_993_000 as Weight).saturating_mul(s as Weight)) + (150_265_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_722_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } @@ -1058,7 +1060,7 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call() -> Weight { - (154_139_000 as Weight) + (114_784_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -1066,9 +1068,9 @@ impl WeightInfo for () { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn upload_code(c: u32, ) -> Weight { - (69_640_000 as Weight) - // Standard Error: 93_000 - .saturating_add((89_969_000 as Weight).saturating_mul(c as Weight)) + (48_072_000 as Weight) + // Standard Error: 36_000 + .saturating_add((83_578_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -1076,7 +1078,7 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:0 w:1) // Storage: Contracts PristineCode (r:0 w:1) fn remove_code() -> Weight { - (31_567_000 as Weight) + (24_739_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -1085,9 +1087,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_caller(r: u32, ) -> Weight { - (405_395_000 as Weight) - // Standard Error: 167_000 - .saturating_add((79_867_000 as Weight).saturating_mul(r as Weight)) + (174_123_000 as Weight) + // Standard Error: 127_000 + .saturating_add((56_078_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1096,9 +1098,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_address(r: u32, ) -> Weight { - (405_173_000 as Weight) - // Standard Error: 152_000 - .saturating_add((79_619_000 as Weight).saturating_mul(r as Weight)) + (180_168_000 as Weight) + // Standard Error: 122_000 + .saturating_add((56_154_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1107,9 +1109,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas_left(r: u32, ) -> Weight { - (406_537_000 as Weight) - // Standard Error: 148_000 - .saturating_add((78_129_000 as Weight).saturating_mul(r as Weight)) + (179_464_000 as Weight) + // Standard Error: 96_000 + .saturating_add((55_350_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1118,9 +1120,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_balance(r: u32, ) -> Weight { - (416_289_000 as Weight) - // Standard Error: 165_000 - .saturating_add((218_401_000 as Weight).saturating_mul(r as Weight)) + (181_031_000 as Weight) + // Standard Error: 154_000 + .saturating_add((149_508_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1129,9 +1131,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_value_transferred(r: u32, ) -> Weight { - (408_205_000 as Weight) - // Standard Error: 154_000 - .saturating_add((79_563_000 as Weight).saturating_mul(r as Weight)) + (178_709_000 as Weight) + // Standard Error: 107_000 + .saturating_add((56_326_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1140,9 +1142,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_minimum_balance(r: u32, ) -> Weight { - (408_124_000 as Weight) - // Standard Error: 149_000 - .saturating_add((79_032_000 as Weight).saturating_mul(r as Weight)) + (175_715_000 as Weight) + // Standard Error: 116_000 + .saturating_add((56_755_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1151,9 +1153,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_block_number(r: u32, ) -> Weight { - (406_141_000 as Weight) - // Standard Error: 150_000 - .saturating_add((78_992_000 as Weight).saturating_mul(r as Weight)) + (178_552_000 as Weight) + // Standard Error: 121_000 + .saturating_add((55_756_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1162,9 +1164,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_now(r: u32, ) -> Weight { - (418_112_000 as Weight) - // Standard Error: 155_000 - .saturating_add((77_902_000 as Weight).saturating_mul(r as Weight)) + (186_172_000 as Weight) + // Standard Error: 106_000 + .saturating_add((55_311_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1174,9 +1176,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0) fn seal_weight_to_fee(r: u32, ) -> Weight { - (411_683_000 as Weight) - // Standard Error: 173_000 - .saturating_add((205_824_000 as Weight).saturating_mul(r as Weight)) + (183_750_000 as Weight) + // Standard Error: 140_000 + .saturating_add((131_877_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1185,9 +1187,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas(r: u32, ) -> Weight { - (132_178_000 as Weight) - // Standard Error: 84_000 - .saturating_add((38_233_000 as Weight).saturating_mul(r as Weight)) + (97_350_000 as Weight) + // Standard Error: 54_000 + .saturating_add((27_606_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1196,9 +1198,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input(r: u32, ) -> Weight { - (405_685_000 as Weight) - // Standard Error: 142_000 - .saturating_add((72_826_000 as Weight).saturating_mul(r as Weight)) + (179_058_000 as Weight) + // Standard Error: 106_000 + .saturating_add((53_258_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1207,9 +1209,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input_per_kb(n: u32, ) -> Weight { - (490_336_000 as Weight) - // Standard Error: 7_000 - .saturating_add((38_070_000 as Weight).saturating_mul(n as Weight)) + (248_562_000 as Weight) + // Standard Error: 5_000 + .saturating_add((10_515_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1218,9 +1220,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return(r: u32, ) -> Weight { - (384_543_000 as Weight) - // Standard Error: 105_000 - .saturating_add((15_793_000 as Weight).saturating_mul(r as Weight)) + (161_228_000 as Weight) + // Standard Error: 90_000 + .saturating_add((14_539_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1229,9 +1231,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return_per_kb(n: u32, ) -> Weight { - (399_205_000 as Weight) - // Standard Error: 1_000 - .saturating_add((637_000 as Weight).saturating_mul(n as Weight)) + (177_866_000 as Weight) + // Standard Error: 0 + .saturating_add((188_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1242,9 +1244,9 @@ impl WeightInfo for () { // Storage: Contracts DeletionQueue (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_terminate(r: u32, ) -> Weight { - (396_375_000 as Weight) - // Standard Error: 3_023_000 - .saturating_add((79_797_000 as Weight).saturating_mul(r as Weight)) + (164_572_000 as Weight) + // Standard Error: 1_817_000 + .saturating_add((68_480_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((4 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1256,9 +1258,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) fn seal_random(r: u32, ) -> Weight { - (390_550_000 as Weight) - // Standard Error: 290_000 - .saturating_add((245_730_000 as Weight).saturating_mul(r as Weight)) + (168_658_000 as Weight) + // Standard Error: 189_000 + .saturating_add((166_190_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1267,9 +1269,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_deposit_event(r: u32, ) -> Weight { - (408_011_000 as Weight) - // Standard Error: 273_000 - .saturating_add((406_522_000 as Weight).saturating_mul(r as Weight)) + (185_391_000 as Weight) + // Standard Error: 191_000 + .saturating_add((292_609_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1279,11 +1281,11 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: System EventTopics (r:100 w:100) fn seal_deposit_event_per_topic_and_kb(t: u32, n: u32, ) -> Weight { - (890_741_000 as Weight) - // Standard Error: 2_072_000 - .saturating_add((382_953_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 408_000 - .saturating_add((162_320_000 as Weight).saturating_mul(n as Weight)) + (507_994_000 as Weight) + // Standard Error: 1_569_000 + .saturating_add((276_852_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 309_000 + .saturating_add((79_461_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(t as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1294,17 +1296,17 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_debug_message(r: u32, ) -> Weight { - (153_163_000 as Weight) - // Standard Error: 137_000 - .saturating_add((59_081_000 as Weight).saturating_mul(r as Weight)) + (99_048_000 as Weight) + // Standard Error: 87_000 + .saturating_add((46_088_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage(r: u32, ) -> Weight { - (459_368_000 as Weight) - // Standard Error: 560_000 - .saturating_add((330_190_000 as Weight).saturating_mul(r as Weight)) + (142_559_000 as Weight) + // Standard Error: 603_000 + .saturating_add((269_723_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -1316,17 +1318,17 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: unknown [0x7afa01283080ef247df84e0ba38ea5a587d25ce6633a6bfbba02068c14023441] (r:1 w:1) fn seal_set_storage_per_kb(n: u32, ) -> Weight { - (727_394_000 as Weight) - // Standard Error: 247_000 - .saturating_add((73_350_000 as Weight).saturating_mul(n as Weight)) + (346_704_000 as Weight) + // Standard Error: 200_000 + .saturating_add((29_907_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage(r: u32, ) -> Weight { - (163_262_000 as Weight) - // Standard Error: 1_492_000 - .saturating_add((799_087_000 as Weight).saturating_mul(r as Weight)) + (0 as Weight) + // Standard Error: 1_963_000 + .saturating_add((746_581_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -1334,18 +1336,18 @@ impl WeightInfo for () { } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage(r: u32, ) -> Weight { - (288_728_000 as Weight) - // Standard Error: 752_000 - .saturating_add((434_780_000 as Weight).saturating_mul(r as Weight)) + (69_873_000 as Weight) + // Standard Error: 722_000 + .saturating_add((338_292_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_contains_storage(r: u32, ) -> Weight { - (209_606_000 as Weight) - // Standard Error: 1_137_000 - .saturating_add((680_187_000 as Weight).saturating_mul(r as Weight)) + (0 as Weight) + // Standard Error: 1_169_000 + .saturating_add((480_500_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1356,17 +1358,17 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: unknown [0x7afa01283080ef247df84e0ba38ea5a587d25ce6633a6bfbba02068c14023441] (r:1 w:0) fn seal_get_storage_per_kb(n: u32, ) -> Weight { - (619_600_000 as Weight) - // Standard Error: 207_000 - .saturating_add((111_030_000 as Weight).saturating_mul(n as Weight)) + (327_625_000 as Weight) + // Standard Error: 146_000 + .saturating_add((55_028_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage(r: u32, ) -> Weight { - (279_528_000 as Weight) - // Standard Error: 932_000 - .saturating_add((541_965_000 as Weight).saturating_mul(r as Weight)) + (41_931_000 as Weight) + // Standard Error: 933_000 + .saturating_add((433_619_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -1374,9 +1376,9 @@ impl WeightInfo for () { } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage_per_kb(n: u32, ) -> Weight { - (985_732_000 as Weight) - // Standard Error: 446_000 - .saturating_add((123_295_000 as Weight).saturating_mul(n as Weight)) + (639_259_000 as Weight) + // Standard Error: 365_000 + .saturating_add((64_588_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().writes(103 as Weight)) } @@ -1385,9 +1387,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_transfer(r: u32, ) -> Weight { - (284_785_000 as Weight) - // Standard Error: 1_479_000 - .saturating_add((2_527_544_000 as Weight).saturating_mul(r as Weight)) + (71_335_000 as Weight) + // Standard Error: 1_489_000 + .saturating_add((1_765_321_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) @@ -1399,8 +1401,8 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) fn seal_call(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 5_742_000 - .saturating_add((37_993_391_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 9_243_000 + .saturating_add((16_121_990_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1411,13 +1413,13 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:2 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_call_per_transfer_input_output_kb(t: u32, i: u32, o: u32, ) -> Weight { - (37_404_660_000 as Weight) - // Standard Error: 92_661_000 - .saturating_add((2_486_257_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 33_000 - .saturating_add((63_001_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 35_000 - .saturating_add((101_347_000 as Weight).saturating_mul(o as Weight)) + (15_978_164_000 as Weight) + // Standard Error: 57_271_000 + .saturating_add((1_179_479_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 20_000 + .saturating_add((17_389_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 21_000 + .saturating_add((28_660_000 as Weight).saturating_mul(o as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().reads((101 as Weight).saturating_mul(t as Weight))) .saturating_add(RocksDbWeight::get().writes(101 as Weight)) @@ -1431,8 +1433,8 @@ impl WeightInfo for () { // Storage: Contracts OwnerInfoOf (r:100 w:100) fn seal_instantiate(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 119_281_000 - .saturating_add((47_113_525_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 115_056_000 + .saturating_add((23_312_565_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().reads((400 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -1445,13 +1447,13 @@ impl WeightInfo for () { // Storage: Contracts AccountCounter (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_instantiate_per_input_output_salt_kb(i: u32, o: u32, s: u32, ) -> Weight { - (41_157_901_000 as Weight) - // Standard Error: 147_000 - .saturating_add((64_877_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 147_000 - .saturating_add((102_420_000 as Weight).saturating_mul(o as Weight)) - // Standard Error: 147_000 - .saturating_add((201_587_000 as Weight).saturating_mul(s as Weight)) + (18_724_034_000 as Weight) + // Standard Error: 66_000 + .saturating_add((18_363_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 66_000 + .saturating_add((29_093_000 as Weight).saturating_mul(o as Weight)) + // Standard Error: 66_000 + .saturating_add((158_645_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(208 as Weight)) .saturating_add(RocksDbWeight::get().writes(206 as Weight)) } @@ -1460,9 +1462,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256(r: u32, ) -> Weight { - (402_224_000 as Weight) - // Standard Error: 166_000 - .saturating_add((103_985_000 as Weight).saturating_mul(r as Weight)) + (179_769_000 as Weight) + // Standard Error: 121_000 + .saturating_add((80_706_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1471,9 +1473,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256_per_kb(n: u32, ) -> Weight { - (663_731_000 as Weight) - // Standard Error: 42_000 - .saturating_add((505_157_000 as Weight).saturating_mul(n as Weight)) + (279_632_000 as Weight) + // Standard Error: 17_000 + .saturating_add((372_618_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1482,9 +1484,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256(r: u32, ) -> Weight { - (402_638_000 as Weight) - // Standard Error: 165_000 - .saturating_add((117_589_000 as Weight).saturating_mul(r as Weight)) + (182_040_000 as Weight) + // Standard Error: 119_000 + .saturating_add((88_916_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1493,9 +1495,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256_per_kb(n: u32, ) -> Weight { - (491_978_000 as Weight) - // Standard Error: 23_000 - .saturating_add((363_687_000 as Weight).saturating_mul(n as Weight)) + (253_225_000 as Weight) + // Standard Error: 16_000 + .saturating_add((247_883_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1504,9 +1506,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256(r: u32, ) -> Weight { - (402_254_000 as Weight) - // Standard Error: 154_000 - .saturating_add((86_403_000 as Weight).saturating_mul(r as Weight)) + (179_945_000 as Weight) + // Standard Error: 96_000 + .saturating_add((68_362_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1515,9 +1517,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256_per_kb(n: u32, ) -> Weight { - (476_405_000 as Weight) - // Standard Error: 18_000 - .saturating_add((163_921_000 as Weight).saturating_mul(n as Weight)) + (191_286_000 as Weight) + // Standard Error: 38_000 + .saturating_add((121_358_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1526,9 +1528,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128(r: u32, ) -> Weight { - (399_949_000 as Weight) - // Standard Error: 142_000 - .saturating_add((85_448_000 as Weight).saturating_mul(r as Weight)) + (179_381_000 as Weight) + // Standard Error: 101_000 + .saturating_add((68_158_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1537,9 +1539,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128_per_kb(n: u32, ) -> Weight { - (475_437_000 as Weight) - // Standard Error: 15_000 - .saturating_add((163_921_000 as Weight).saturating_mul(n as Weight)) + (135_478_000 as Weight) + // Standard Error: 41_000 + .saturating_add((121_422_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1548,265 +1550,265 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_ecdsa_recover(r: u32, ) -> Weight { - (373_575_000 as Weight) - // Standard Error: 1_639_000 - .saturating_add((15_530_027_000 as Weight).saturating_mul(r as Weight)) + (123_468_000 as Weight) + // Standard Error: 1_017_000 + .saturating_add((15_542_677_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn instr_i64const(r: u32, ) -> Weight { - (52_763_000 as Weight) + (52_702_000 as Weight) // Standard Error: 12_000 - .saturating_add((857_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((844_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64load(r: u32, ) -> Weight { - (47_313_000 as Weight) + (47_295_000 as Weight) // Standard Error: 10_000 - .saturating_add((2_935_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((3_045_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64store(r: u32, ) -> Weight { - (47_147_000 as Weight) - // Standard Error: 10_000 - .saturating_add((2_995_000 as Weight).saturating_mul(r as Weight)) + (46_353_000 as Weight) + // Standard Error: 9_000 + .saturating_add((3_047_000 as Weight).saturating_mul(r as Weight)) } fn instr_select(r: u32, ) -> Weight { - (50_124_000 as Weight) + (49_811_000 as Weight) // Standard Error: 11_000 - .saturating_add((2_421_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_408_000 as Weight).saturating_mul(r as Weight)) } fn instr_if(r: u32, ) -> Weight { - (47_288_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_523_000 as Weight).saturating_mul(r as Weight)) + (47_054_000 as Weight) + // Standard Error: 12_000 + .saturating_add((2_504_000 as Weight).saturating_mul(r as Weight)) } fn instr_br(r: u32, ) -> Weight { - (50_198_000 as Weight) + (49_912_000 as Weight) // Standard Error: 16_000 - .saturating_add((1_473_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_460_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_if(r: u32, ) -> Weight { - (44_008_000 as Weight) + (43_860_000 as Weight) // Standard Error: 17_000 - .saturating_add((2_174_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_150_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table(r: u32, ) -> Weight { - (37_602_000 as Weight) + (37_009_000 as Weight) // Standard Error: 16_000 - .saturating_add((2_820_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_762_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table_per_entry(e: u32, ) -> Weight { - (46_232_000 as Weight) + (45_776_000 as Weight) // Standard Error: 3_000 .saturating_add((17_000 as Weight).saturating_mul(e as Weight)) } fn instr_call(r: u32, ) -> Weight { - (40_148_000 as Weight) - // Standard Error: 22_000 - .saturating_add((20_585_000 as Weight).saturating_mul(r as Weight)) + (39_611_000 as Weight) + // Standard Error: 17_000 + .saturating_add((20_805_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect(r: u32, ) -> Weight { - (43_948_000 as Weight) - // Standard Error: 31_000 - .saturating_add((30_226_000 as Weight).saturating_mul(r as Weight)) + (45_523_000 as Weight) + // Standard Error: 27_000 + .saturating_add((31_622_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect_per_param(p: u32, ) -> Weight { - (78_722_000 as Weight) - // Standard Error: 5_000 - .saturating_add((1_199_000 as Weight).saturating_mul(p as Weight)) + (79_764_000 as Weight) + // Standard Error: 6_000 + .saturating_add((1_198_000 as Weight).saturating_mul(p as Weight)) } fn instr_local_get(r: u32, ) -> Weight { - (48_083_000 as Weight) - // Standard Error: 12_000 - .saturating_add((805_000 as Weight).saturating_mul(r as Weight)) + (46_510_000 as Weight) + // Standard Error: 11_000 + .saturating_add((810_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_set(r: u32, ) -> Weight { - (47_710_000 as Weight) + (46_567_000 as Weight) // Standard Error: 11_000 - .saturating_add((843_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((833_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_tee(r: u32, ) -> Weight { - (44_785_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_466_000 as Weight).saturating_mul(r as Weight)) + (43_439_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_463_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_get(r: u32, ) -> Weight { - (50_106_000 as Weight) - // Standard Error: 20_000 - .saturating_add((1_641_000 as Weight).saturating_mul(r as Weight)) + (46_201_000 as Weight) + // Standard Error: 19_000 + .saturating_add((1_635_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_set(r: u32, ) -> Weight { - (47_058_000 as Weight) + (42_639_000 as Weight) // Standard Error: 18_000 - .saturating_add((1_707_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_652_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_current(r: u32, ) -> Weight { - (51_494_000 as Weight) - // Standard Error: 15_000 - .saturating_add((925_000 as Weight).saturating_mul(r as Weight)) + (51_159_000 as Weight) + // Standard Error: 14_000 + .saturating_add((917_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_grow(r: u32, ) -> Weight { - (36_983_000 as Weight) - // Standard Error: 3_602_000 - .saturating_add((634_259_000 as Weight).saturating_mul(r as Weight)) + (36_462_000 as Weight) + // Standard Error: 867_000 + .saturating_add((187_724_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64clz(r: u32, ) -> Weight { - (60_711_000 as Weight) - // Standard Error: 22_000 - .saturating_add((1_157_000 as Weight).saturating_mul(r as Weight)) + (53_776_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_307_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ctz(r: u32, ) -> Weight { - (53_908_000 as Weight) - // Standard Error: 9_000 - .saturating_add((1_305_000 as Weight).saturating_mul(r as Weight)) + (53_674_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_304_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64popcnt(r: u32, ) -> Weight { - (53_939_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_314_000 as Weight).saturating_mul(r as Weight)) + (53_654_000 as Weight) + // Standard Error: 9_000 + .saturating_add((1_299_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eqz(r: u32, ) -> Weight { - (54_086_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_309_000 as Weight).saturating_mul(r as Weight)) + (53_493_000 as Weight) + // Standard Error: 9_000 + .saturating_add((1_299_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendsi32(r: u32, ) -> Weight { - (43_845_000 as Weight) + (43_373_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_493_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_492_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendui32(r: u32, ) -> Weight { - (43_518_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_501_000 as Weight).saturating_mul(r as Weight)) + (43_222_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_498_000 as Weight).saturating_mul(r as Weight)) } fn instr_i32wrapi64(r: u32, ) -> Weight { - (53_912_000 as Weight) + (53_706_000 as Weight) // Standard Error: 9_000 - .saturating_add((1_302_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_292_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eq(r: u32, ) -> Weight { - (49_594_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_890_000 as Weight).saturating_mul(r as Weight)) + (48_994_000 as Weight) + // Standard Error: 10_000 + .saturating_add((1_888_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ne(r: u32, ) -> Weight { - (49_659_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_894_000 as Weight).saturating_mul(r as Weight)) + (49_464_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_876_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64lts(r: u32, ) -> Weight { - (49_401_000 as Weight) + (49_194_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_902_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_884_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ltu(r: u32, ) -> Weight { - (49_880_000 as Weight) + (49_291_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_885_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_883_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gts(r: u32, ) -> Weight { - (49_466_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_894_000 as Weight).saturating_mul(r as Weight)) + (49_227_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_886_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gtu(r: u32, ) -> Weight { - (49_514_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_891_000 as Weight).saturating_mul(r as Weight)) + (49_219_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_885_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64les(r: u32, ) -> Weight { - (49_588_000 as Weight) + (49_263_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_898_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_882_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64leu(r: u32, ) -> Weight { - (49_589_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_891_000 as Weight).saturating_mul(r as Weight)) + (49_251_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_882_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ges(r: u32, ) -> Weight { - (49_685_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_892_000 as Weight).saturating_mul(r as Weight)) + (49_257_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_882_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64geu(r: u32, ) -> Weight { - (49_601_000 as Weight) + (49_219_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_891_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_885_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64add(r: u32, ) -> Weight { - (49_430_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_894_000 as Weight).saturating_mul(r as Weight)) + (49_221_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_888_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64sub(r: u32, ) -> Weight { - (49_533_000 as Weight) + (48_936_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_893_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_900_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64mul(r: u32, ) -> Weight { - (49_766_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_888_000 as Weight).saturating_mul(r as Weight)) + (49_266_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_882_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divs(r: u32, ) -> Weight { - (49_315_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_552_000 as Weight).saturating_mul(r as Weight)) + (49_246_000 as Weight) + // Standard Error: 10_000 + .saturating_add((2_565_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divu(r: u32, ) -> Weight { - (49_786_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_203_000 as Weight).saturating_mul(r as Weight)) + (49_181_000 as Weight) + // Standard Error: 10_000 + .saturating_add((2_211_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rems(r: u32, ) -> Weight { - (49_651_000 as Weight) + (49_337_000 as Weight) // Standard Error: 11_000 - .saturating_add((2_461_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_525_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64remu(r: u32, ) -> Weight { - (49_747_000 as Weight) - // Standard Error: 10_000 - .saturating_add((2_196_000 as Weight).saturating_mul(r as Weight)) + (49_387_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_241_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64and(r: u32, ) -> Weight { - (49_719_000 as Weight) + (49_137_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_892_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_900_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64or(r: u32, ) -> Weight { - (49_463_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_896_000 as Weight).saturating_mul(r as Weight)) + (49_366_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_882_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64xor(r: u32, ) -> Weight { - (49_379_000 as Weight) + (49_143_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_903_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_912_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shl(r: u32, ) -> Weight { - (49_404_000 as Weight) + (49_195_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_902_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_891_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shrs(r: u32, ) -> Weight { - (49_498_000 as Weight) - // Standard Error: 10_000 + (49_228_000 as Weight) + // Standard Error: 11_000 .saturating_add((1_900_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shru(r: u32, ) -> Weight { - (49_541_000 as Weight) + (49_279_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_897_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_888_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotl(r: u32, ) -> Weight { - (49_452_000 as Weight) + (49_091_000 as Weight) // Standard Error: 11_000 - .saturating_add((1_900_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_909_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotr(r: u32, ) -> Weight { - (49_350_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_902_000 as Weight).saturating_mul(r as Weight)) + (49_436_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_883_000 as Weight).saturating_mul(r as Weight)) } } diff --git a/frame/democracy/src/weights.rs b/frame/democracy/src/weights.rs index aa8e68f57053..22743124253b 100644 --- a/frame/democracy/src/weights.rs +++ b/frame/democracy/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. +// Copyright (C) 2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_democracy //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-09-30, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 +//! DATE: 2022-01-17, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// target/release/substrate +// ./target/lto-fat-cg1/substrate // benchmark // --chain=dev // --steps=50 @@ -33,8 +33,9 @@ // --wasm-execution=compiled // --heap-pages=4096 // --output=./frame/democracy/src/weights.rs -// --template=./.maintain/frame-weight-template.hbs - +// --template=.maintain/frame-weight-template.hbs +// --header=LICENSE-APACHE2 +// --raw #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -81,15 +82,15 @@ impl WeightInfo for SubstrateWeight { // Storage: Democracy Blacklist (r:1 w:0) // Storage: Democracy DepositOf (r:0 w:1) fn propose() -> Weight { - (67_388_000 as Weight) + (42_599_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Democracy DepositOf (r:1 w:1) fn second(s: u32, ) -> Weight { - (41_157_000 as Weight) - // Standard Error: 0 - .saturating_add((157_000 as Weight).saturating_mul(s as Weight)) + (25_521_000 as Weight) + // Standard Error: 1_000 + .saturating_add((171_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -97,9 +98,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Democracy VotingOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_new(r: u32, ) -> Weight { - (46_406_000 as Weight) + (34_035_000 as Weight) // Standard Error: 1_000 - .saturating_add((170_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((142_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -107,16 +108,16 @@ impl WeightInfo for SubstrateWeight { // Storage: Democracy VotingOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_existing(r: u32, ) -> Weight { - (46_071_000 as Weight) + (33_910_000 as Weight) // Standard Error: 1_000 - .saturating_add((166_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((147_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy Cancellations (r:1 w:1) fn emergency_cancel() -> Weight { - (27_699_000 as Weight) + (14_874_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -127,16 +128,16 @@ impl WeightInfo for SubstrateWeight { // Storage: Democracy DepositOf (r:1 w:1) // Storage: System Account (r:1 w:1) fn blacklist(p: u32, ) -> Weight { - (82_703_000 as Weight) - // Standard Error: 4_000 - .saturating_add((500_000 as Weight).saturating_mul(p as Weight)) + (49_557_000 as Weight) + // Standard Error: 3_000 + .saturating_add((267_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy Blacklist (r:1 w:0) fn external_propose(v: u32, ) -> Weight { - (13_747_000 as Weight) + (7_540_000 as Weight) // Standard Error: 0 .saturating_add((76_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) @@ -144,28 +145,28 @@ impl WeightInfo for SubstrateWeight { } // Storage: Democracy NextExternal (r:0 w:1) fn external_propose_majority() -> Weight { - (3_070_000 as Weight) + (1_272_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Democracy NextExternal (r:0 w:1) fn external_propose_default() -> Weight { - (3_080_000 as Weight) + (1_274_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy ReferendumCount (r:1 w:1) // Storage: Democracy ReferendumInfoOf (r:0 w:1) fn fast_track() -> Weight { - (29_129_000 as Weight) + (15_216_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy Blacklist (r:1 w:1) fn veto_external(v: u32, ) -> Weight { - (30_105_000 as Weight) + (16_713_000 as Weight) // Standard Error: 0 - .saturating_add((104_000 as Weight).saturating_mul(v as Weight)) + .saturating_add((92_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -173,56 +174,58 @@ impl WeightInfo for SubstrateWeight { // Storage: Democracy DepositOf (r:1 w:1) // Storage: System Account (r:1 w:1) fn cancel_proposal(p: u32, ) -> Weight { - (55_228_000 as Weight) - // Standard Error: 1_000 - .saturating_add((457_000 as Weight).saturating_mul(p as Weight)) + (37_990_000 as Weight) + // Standard Error: 2_000 + .saturating_add((259_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Democracy ReferendumInfoOf (r:0 w:1) fn cancel_referendum() -> Weight { - (17_319_000 as Weight) + (9_756_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Scheduler Lookup (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) fn cancel_queued(r: u32, ) -> Weight { - (29_738_000 as Weight) + (19_408_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_153_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((650_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } - // Storage: Democracy LowestUnbaked (r:1 w:0) + // Storage: Democracy LowestUnbaked (r:1 w:1) // Storage: Democracy ReferendumCount (r:1 w:0) // Storage: Democracy ReferendumInfoOf (r:1 w:0) fn on_initialize_base(r: u32, ) -> Weight { - (2_165_000 as Weight) + (2_134_000 as Weight) // Standard Error: 3_000 - .saturating_add((5_577_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((3_041_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(r as Weight))) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - // Storage: Democracy LowestUnbaked (r:1 w:0) + // Storage: Democracy LowestUnbaked (r:1 w:1) // Storage: Democracy ReferendumCount (r:1 w:0) // Storage: Democracy LastTabledWasExternal (r:1 w:0) // Storage: Democracy NextExternal (r:1 w:0) // Storage: Democracy PublicProps (r:1 w:0) // Storage: Democracy ReferendumInfoOf (r:1 w:0) fn on_initialize_base_with_launch_period(r: u32, ) -> Weight { - (9_396_000 as Weight) - // Standard Error: 4_000 - .saturating_add((5_604_000 as Weight).saturating_mul(r as Weight)) + (6_357_000 as Weight) + // Standard Error: 3_000 + .saturating_add((3_054_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(r as Weight))) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Democracy VotingOf (r:3 w:3) // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn delegate(r: u32, ) -> Weight { - (57_783_000 as Weight) - // Standard Error: 4_000 - .saturating_add((7_623_000 as Weight).saturating_mul(r as Weight)) + (30_822_000 as Weight) + // Standard Error: 3_000 + .saturating_add((3_826_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(4 as Weight)) @@ -231,9 +234,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Democracy VotingOf (r:2 w:2) // Storage: Democracy ReferendumInfoOf (r:1 w:1) fn undelegate(r: u32, ) -> Weight { - (26_027_000 as Weight) - // Standard Error: 4_000 - .saturating_add((7_593_000 as Weight).saturating_mul(r as Weight)) + (15_307_000 as Weight) + // Standard Error: 3_000 + .saturating_add((3_827_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -241,12 +244,12 @@ impl WeightInfo for SubstrateWeight { } // Storage: Democracy PublicProps (r:0 w:1) fn clear_public_proposals() -> Weight { - (2_780_000 as Weight) + (1_624_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Democracy Preimages (r:1 w:1) fn note_preimage(b: u32, ) -> Weight { - (46_416_000 as Weight) + (22_731_000 as Weight) // Standard Error: 0 .saturating_add((2_000 as Weight).saturating_mul(b as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) @@ -254,7 +257,7 @@ impl WeightInfo for SubstrateWeight { } // Storage: Democracy Preimages (r:1 w:1) fn note_imminent_preimage(b: u32, ) -> Weight { - (29_735_000 as Weight) + (15_518_000 as Weight) // Standard Error: 0 .saturating_add((2_000 as Weight).saturating_mul(b as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) @@ -263,7 +266,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Democracy Preimages (r:1 w:1) // Storage: System Account (r:1 w:0) fn reap_preimage(b: u32, ) -> Weight { - (41_276_000 as Weight) + (23_749_000 as Weight) // Standard Error: 0 .saturating_add((1_000 as Weight).saturating_mul(b as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) @@ -273,9 +276,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn unlock_remove(r: u32, ) -> Weight { - (40_348_000 as Weight) + (21_818_000 as Weight) // Standard Error: 1_000 - .saturating_add((60_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((66_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -283,27 +286,27 @@ impl WeightInfo for SubstrateWeight { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn unlock_set(r: u32, ) -> Weight { - (37_475_000 as Weight) + (21_491_000 as Weight) // Standard Error: 1_000 - .saturating_add((151_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((121_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy VotingOf (r:1 w:1) fn remove_vote(r: u32, ) -> Weight { - (19_970_000 as Weight) + (11_767_000 as Weight) // Standard Error: 1_000 - .saturating_add((153_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((115_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy VotingOf (r:1 w:1) fn remove_other_vote(r: u32, ) -> Weight { - (20_094_000 as Weight) + (11_959_000 as Weight) // Standard Error: 1_000 - .saturating_add((157_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((111_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -316,15 +319,15 @@ impl WeightInfo for () { // Storage: Democracy Blacklist (r:1 w:0) // Storage: Democracy DepositOf (r:0 w:1) fn propose() -> Weight { - (67_388_000 as Weight) + (42_599_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } // Storage: Democracy DepositOf (r:1 w:1) fn second(s: u32, ) -> Weight { - (41_157_000 as Weight) - // Standard Error: 0 - .saturating_add((157_000 as Weight).saturating_mul(s as Weight)) + (25_521_000 as Weight) + // Standard Error: 1_000 + .saturating_add((171_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -332,9 +335,9 @@ impl WeightInfo for () { // Storage: Democracy VotingOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_new(r: u32, ) -> Weight { - (46_406_000 as Weight) + (34_035_000 as Weight) // Standard Error: 1_000 - .saturating_add((170_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((142_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -342,16 +345,16 @@ impl WeightInfo for () { // Storage: Democracy VotingOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_existing(r: u32, ) -> Weight { - (46_071_000 as Weight) + (33_910_000 as Weight) // Standard Error: 1_000 - .saturating_add((166_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((147_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy Cancellations (r:1 w:1) fn emergency_cancel() -> Weight { - (27_699_000 as Weight) + (14_874_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -362,16 +365,16 @@ impl WeightInfo for () { // Storage: Democracy DepositOf (r:1 w:1) // Storage: System Account (r:1 w:1) fn blacklist(p: u32, ) -> Weight { - (82_703_000 as Weight) - // Standard Error: 4_000 - .saturating_add((500_000 as Weight).saturating_mul(p as Weight)) + (49_557_000 as Weight) + // Standard Error: 3_000 + .saturating_add((267_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy Blacklist (r:1 w:0) fn external_propose(v: u32, ) -> Weight { - (13_747_000 as Weight) + (7_540_000 as Weight) // Standard Error: 0 .saturating_add((76_000 as Weight).saturating_mul(v as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) @@ -379,28 +382,28 @@ impl WeightInfo for () { } // Storage: Democracy NextExternal (r:0 w:1) fn external_propose_majority() -> Weight { - (3_070_000 as Weight) + (1_272_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Democracy NextExternal (r:0 w:1) fn external_propose_default() -> Weight { - (3_080_000 as Weight) + (1_274_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy ReferendumCount (r:1 w:1) // Storage: Democracy ReferendumInfoOf (r:0 w:1) fn fast_track() -> Weight { - (29_129_000 as Weight) + (15_216_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy Blacklist (r:1 w:1) fn veto_external(v: u32, ) -> Weight { - (30_105_000 as Weight) + (16_713_000 as Weight) // Standard Error: 0 - .saturating_add((104_000 as Weight).saturating_mul(v as Weight)) + .saturating_add((92_000 as Weight).saturating_mul(v as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -408,56 +411,58 @@ impl WeightInfo for () { // Storage: Democracy DepositOf (r:1 w:1) // Storage: System Account (r:1 w:1) fn cancel_proposal(p: u32, ) -> Weight { - (55_228_000 as Weight) - // Standard Error: 1_000 - .saturating_add((457_000 as Weight).saturating_mul(p as Weight)) + (37_990_000 as Weight) + // Standard Error: 2_000 + .saturating_add((259_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } // Storage: Democracy ReferendumInfoOf (r:0 w:1) fn cancel_referendum() -> Weight { - (17_319_000 as Weight) + (9_756_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Scheduler Lookup (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) fn cancel_queued(r: u32, ) -> Weight { - (29_738_000 as Weight) + (19_408_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_153_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((650_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } - // Storage: Democracy LowestUnbaked (r:1 w:0) + // Storage: Democracy LowestUnbaked (r:1 w:1) // Storage: Democracy ReferendumCount (r:1 w:0) // Storage: Democracy ReferendumInfoOf (r:1 w:0) fn on_initialize_base(r: u32, ) -> Weight { - (2_165_000 as Weight) + (2_134_000 as Weight) // Standard Error: 3_000 - .saturating_add((5_577_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((3_041_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(r as Weight))) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } - // Storage: Democracy LowestUnbaked (r:1 w:0) + // Storage: Democracy LowestUnbaked (r:1 w:1) // Storage: Democracy ReferendumCount (r:1 w:0) // Storage: Democracy LastTabledWasExternal (r:1 w:0) // Storage: Democracy NextExternal (r:1 w:0) // Storage: Democracy PublicProps (r:1 w:0) // Storage: Democracy ReferendumInfoOf (r:1 w:0) fn on_initialize_base_with_launch_period(r: u32, ) -> Weight { - (9_396_000 as Weight) - // Standard Error: 4_000 - .saturating_add((5_604_000 as Weight).saturating_mul(r as Weight)) + (6_357_000 as Weight) + // Standard Error: 3_000 + .saturating_add((3_054_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(r as Weight))) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Democracy VotingOf (r:3 w:3) // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn delegate(r: u32, ) -> Weight { - (57_783_000 as Weight) - // Standard Error: 4_000 - .saturating_add((7_623_000 as Weight).saturating_mul(r as Weight)) + (30_822_000 as Weight) + // Standard Error: 3_000 + .saturating_add((3_826_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) @@ -466,9 +471,9 @@ impl WeightInfo for () { // Storage: Democracy VotingOf (r:2 w:2) // Storage: Democracy ReferendumInfoOf (r:1 w:1) fn undelegate(r: u32, ) -> Weight { - (26_027_000 as Weight) - // Standard Error: 4_000 - .saturating_add((7_593_000 as Weight).saturating_mul(r as Weight)) + (15_307_000 as Weight) + // Standard Error: 3_000 + .saturating_add((3_827_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) @@ -476,12 +481,12 @@ impl WeightInfo for () { } // Storage: Democracy PublicProps (r:0 w:1) fn clear_public_proposals() -> Weight { - (2_780_000 as Weight) + (1_624_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Democracy Preimages (r:1 w:1) fn note_preimage(b: u32, ) -> Weight { - (46_416_000 as Weight) + (22_731_000 as Weight) // Standard Error: 0 .saturating_add((2_000 as Weight).saturating_mul(b as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) @@ -489,7 +494,7 @@ impl WeightInfo for () { } // Storage: Democracy Preimages (r:1 w:1) fn note_imminent_preimage(b: u32, ) -> Weight { - (29_735_000 as Weight) + (15_518_000 as Weight) // Standard Error: 0 .saturating_add((2_000 as Weight).saturating_mul(b as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) @@ -498,7 +503,7 @@ impl WeightInfo for () { // Storage: Democracy Preimages (r:1 w:1) // Storage: System Account (r:1 w:0) fn reap_preimage(b: u32, ) -> Weight { - (41_276_000 as Weight) + (23_749_000 as Weight) // Standard Error: 0 .saturating_add((1_000 as Weight).saturating_mul(b as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) @@ -508,9 +513,9 @@ impl WeightInfo for () { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn unlock_remove(r: u32, ) -> Weight { - (40_348_000 as Weight) + (21_818_000 as Weight) // Standard Error: 1_000 - .saturating_add((60_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((66_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -518,27 +523,27 @@ impl WeightInfo for () { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn unlock_set(r: u32, ) -> Weight { - (37_475_000 as Weight) + (21_491_000 as Weight) // Standard Error: 1_000 - .saturating_add((151_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((121_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy VotingOf (r:1 w:1) fn remove_vote(r: u32, ) -> Weight { - (19_970_000 as Weight) + (11_767_000 as Weight) // Standard Error: 1_000 - .saturating_add((153_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((115_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy VotingOf (r:1 w:1) fn remove_other_vote(r: u32, ) -> Weight { - (20_094_000 as Weight) + (11_959_000 as Weight) // Standard Error: 1_000 - .saturating_add((157_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((111_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } diff --git a/frame/election-provider-multi-phase/src/weights.rs b/frame/election-provider-multi-phase/src/weights.rs index 7bb3303cba2e..8e627b246d37 100644 --- a/frame/election-provider-multi-phase/src/weights.rs +++ b/frame/election-provider-multi-phase/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. +// Copyright (C) 2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_election_provider_multi_phase //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-09-22, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 +//! DATE: 2022-01-19, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// target/release/substrate +// ./target/optimized/substrate // benchmark // --chain=dev // --steps=50 @@ -32,9 +32,10 @@ // --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/election-provider-multi-phase/src/weights.rs -// --template=./.maintain/frame-weight-template.hbs - +// --output=./weights-optimized/frame/election-provider-multi-phase/src//weights.rs +// --template=.maintain/frame-weight-template.hbs +// --header=HEADER-APACHE2 +// --raw #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -69,33 +70,33 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking ForceEra (r:1 w:0) // Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) fn on_initialize_nothing() -> Weight { - (22_784_000 as Weight) + (12_360_000 as Weight) .saturating_add(T::DbWeight::get().reads(8 as Weight)) } // Storage: ElectionProviderMultiPhase Round (r:1 w:0) // Storage: ElectionProviderMultiPhase CurrentPhase (r:0 w:1) fn on_initialize_open_signed() -> Weight { - (32_763_000 as Weight) + (12_981_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: ElectionProviderMultiPhase Round (r:1 w:0) // Storage: ElectionProviderMultiPhase CurrentPhase (r:0 w:1) fn on_initialize_open_unsigned() -> Weight { - (29_117_000 as Weight) + (12_684_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: System Account (r:1 w:1) // Storage: ElectionProviderMultiPhase QueuedSolution (r:0 w:1) fn finalize_signed_phase_accept_solution() -> Weight { - (48_996_000 as Weight) + (27_272_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: System Account (r:1 w:1) fn finalize_signed_phase_reject_solution() -> Weight { - (32_508_000 as Weight) + (20_798_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -103,11 +104,11 @@ impl WeightInfo for SubstrateWeight { // Storage: ElectionProviderMultiPhase DesiredTargets (r:0 w:1) // Storage: ElectionProviderMultiPhase Snapshot (r:0 w:1) fn create_snapshot_internal(v: u32, t: u32, ) -> Weight { - (96_001_000 as Weight) + (13_760_000 as Weight) // Standard Error: 1_000 - .saturating_add((307_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 2_000 - .saturating_add((133_000 as Weight).saturating_mul(t as Weight)) + .saturating_add((201_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 3_000 + .saturating_add((49_000 as Weight).saturating_mul(t as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: ElectionProviderMultiPhase SignedSubmissionIndices (r:1 w:1) @@ -120,11 +121,11 @@ impl WeightInfo for SubstrateWeight { // Storage: ElectionProviderMultiPhase Snapshot (r:0 w:1) // Storage: ElectionProviderMultiPhase CurrentPhase (r:0 w:1) fn elect_queued(a: u32, d: u32, ) -> Weight { - (100_505_000 as Weight) - // Standard Error: 6_000 - .saturating_add((1_665_000 as Weight).saturating_mul(a as Weight)) - // Standard Error: 10_000 - .saturating_add((443_000 as Weight).saturating_mul(d as Weight)) + (108_461_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_318_000 as Weight).saturating_mul(a as Weight)) + // Standard Error: 5_000 + .saturating_add((194_000 as Weight).saturating_mul(d as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(8 as Weight)) } @@ -135,9 +136,9 @@ impl WeightInfo for SubstrateWeight { // Storage: ElectionProviderMultiPhase SignedSubmissionNextIndex (r:1 w:1) // Storage: ElectionProviderMultiPhase SignedSubmissionsMap (r:0 w:1) fn submit(c: u32, ) -> Weight { - (74_088_000 as Weight) - // Standard Error: 59_000 - .saturating_add((187_000 as Weight).saturating_mul(c as Weight)) + (39_721_000 as Weight) + // Standard Error: 24_000 + .saturating_add((298_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -150,14 +151,14 @@ impl WeightInfo for SubstrateWeight { // Storage: ElectionProviderMultiPhase Snapshot (r:1 w:0) fn submit_unsigned(v: u32, t: u32, a: u32, d: u32, ) -> Weight { (0 as Weight) - // Standard Error: 5_000 - .saturating_add((1_970_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 10_000 - .saturating_add((173_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 18_000 - .saturating_add((9_783_000 as Weight).saturating_mul(a as Weight)) - // Standard Error: 27_000 - .saturating_add((2_224_000 as Weight).saturating_mul(d as Weight)) + // Standard Error: 4_000 + .saturating_add((1_612_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 8_000 + .saturating_add((105_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 13_000 + .saturating_add((7_024_000 as Weight).saturating_mul(a as Weight)) + // Standard Error: 20_000 + .saturating_add((1_361_000 as Weight).saturating_mul(d as Weight)) .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -167,14 +168,14 @@ impl WeightInfo for SubstrateWeight { // Storage: ElectionProviderMultiPhase Snapshot (r:1 w:0) fn feasibility_check(v: u32, t: u32, a: u32, d: u32, ) -> Weight { (0 as Weight) - // Standard Error: 3_000 - .saturating_add((1_910_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 7_000 - .saturating_add((111_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 2_000 + .saturating_add((1_639_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 5_000 + .saturating_add((138_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 8_000 + .saturating_add((5_665_000 as Weight).saturating_mul(a as Weight)) // Standard Error: 13_000 - .saturating_add((7_741_000 as Weight).saturating_mul(a as Weight)) - // Standard Error: 19_000 - .saturating_add((1_844_000 as Weight).saturating_mul(d as Weight)) + .saturating_add((980_000 as Weight).saturating_mul(d as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) } } @@ -190,33 +191,33 @@ impl WeightInfo for () { // Storage: Staking ForceEra (r:1 w:0) // Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) fn on_initialize_nothing() -> Weight { - (22_784_000 as Weight) + (12_360_000 as Weight) .saturating_add(RocksDbWeight::get().reads(8 as Weight)) } // Storage: ElectionProviderMultiPhase Round (r:1 w:0) // Storage: ElectionProviderMultiPhase CurrentPhase (r:0 w:1) fn on_initialize_open_signed() -> Weight { - (32_763_000 as Weight) + (12_981_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: ElectionProviderMultiPhase Round (r:1 w:0) // Storage: ElectionProviderMultiPhase CurrentPhase (r:0 w:1) fn on_initialize_open_unsigned() -> Weight { - (29_117_000 as Weight) + (12_684_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: System Account (r:1 w:1) // Storage: ElectionProviderMultiPhase QueuedSolution (r:0 w:1) fn finalize_signed_phase_accept_solution() -> Weight { - (48_996_000 as Weight) + (27_272_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: System Account (r:1 w:1) fn finalize_signed_phase_reject_solution() -> Weight { - (32_508_000 as Weight) + (20_798_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -224,11 +225,11 @@ impl WeightInfo for () { // Storage: ElectionProviderMultiPhase DesiredTargets (r:0 w:1) // Storage: ElectionProviderMultiPhase Snapshot (r:0 w:1) fn create_snapshot_internal(v: u32, t: u32, ) -> Weight { - (96_001_000 as Weight) + (13_760_000 as Weight) // Standard Error: 1_000 - .saturating_add((307_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 2_000 - .saturating_add((133_000 as Weight).saturating_mul(t as Weight)) + .saturating_add((201_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 3_000 + .saturating_add((49_000 as Weight).saturating_mul(t as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } // Storage: ElectionProviderMultiPhase SignedSubmissionIndices (r:1 w:1) @@ -241,11 +242,11 @@ impl WeightInfo for () { // Storage: ElectionProviderMultiPhase Snapshot (r:0 w:1) // Storage: ElectionProviderMultiPhase CurrentPhase (r:0 w:1) fn elect_queued(a: u32, d: u32, ) -> Weight { - (100_505_000 as Weight) - // Standard Error: 6_000 - .saturating_add((1_665_000 as Weight).saturating_mul(a as Weight)) - // Standard Error: 10_000 - .saturating_add((443_000 as Weight).saturating_mul(d as Weight)) + (108_461_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_318_000 as Weight).saturating_mul(a as Weight)) + // Standard Error: 5_000 + .saturating_add((194_000 as Weight).saturating_mul(d as Weight)) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(8 as Weight)) } @@ -256,9 +257,9 @@ impl WeightInfo for () { // Storage: ElectionProviderMultiPhase SignedSubmissionNextIndex (r:1 w:1) // Storage: ElectionProviderMultiPhase SignedSubmissionsMap (r:0 w:1) fn submit(c: u32, ) -> Weight { - (74_088_000 as Weight) - // Standard Error: 59_000 - .saturating_add((187_000 as Weight).saturating_mul(c as Weight)) + (39_721_000 as Weight) + // Standard Error: 24_000 + .saturating_add((298_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -271,14 +272,14 @@ impl WeightInfo for () { // Storage: ElectionProviderMultiPhase Snapshot (r:1 w:0) fn submit_unsigned(v: u32, t: u32, a: u32, d: u32, ) -> Weight { (0 as Weight) - // Standard Error: 5_000 - .saturating_add((1_970_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 10_000 - .saturating_add((173_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 18_000 - .saturating_add((9_783_000 as Weight).saturating_mul(a as Weight)) - // Standard Error: 27_000 - .saturating_add((2_224_000 as Weight).saturating_mul(d as Weight)) + // Standard Error: 4_000 + .saturating_add((1_612_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 8_000 + .saturating_add((105_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 13_000 + .saturating_add((7_024_000 as Weight).saturating_mul(a as Weight)) + // Standard Error: 20_000 + .saturating_add((1_361_000 as Weight).saturating_mul(d as Weight)) .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -288,14 +289,14 @@ impl WeightInfo for () { // Storage: ElectionProviderMultiPhase Snapshot (r:1 w:0) fn feasibility_check(v: u32, t: u32, a: u32, d: u32, ) -> Weight { (0 as Weight) - // Standard Error: 3_000 - .saturating_add((1_910_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 7_000 - .saturating_add((111_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 2_000 + .saturating_add((1_639_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 5_000 + .saturating_add((138_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 8_000 + .saturating_add((5_665_000 as Weight).saturating_mul(a as Weight)) // Standard Error: 13_000 - .saturating_add((7_741_000 as Weight).saturating_mul(a as Weight)) - // Standard Error: 19_000 - .saturating_add((1_844_000 as Weight).saturating_mul(d as Weight)) + .saturating_add((980_000 as Weight).saturating_mul(d as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) } } diff --git a/frame/elections-phragmen/src/weights.rs b/frame/elections-phragmen/src/weights.rs index 0bfc3d2ea87a..57cb1b718fb7 100644 --- a/frame/elections-phragmen/src/weights.rs +++ b/frame/elections-phragmen/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. +// Copyright (C) 2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_elections_phragmen //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-08-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 +//! DATE: 2022-01-19, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// target/release/substrate +// ./target/optimized/substrate // benchmark // --chain=dev // --steps=50 @@ -32,9 +32,10 @@ // --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/elections-phragmen/src/weights.rs -// --template=./.maintain/frame-weight-template.hbs - +// --output=./weights-optimized/frame/elections-phragmen/src//weights.rs +// --template=.maintain/frame-weight-template.hbs +// --header=HEADER-APACHE2 +// --raw #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -53,8 +54,8 @@ pub trait WeightInfo { fn renounce_candidacy_candidate(c: u32, ) -> Weight; fn renounce_candidacy_members() -> Weight; fn renounce_candidacy_runners_up() -> Weight; - fn remove_member_with_replacement() -> Weight; fn remove_member_without_replacement() -> Weight; + fn remove_member_with_replacement() -> Weight; fn remove_member_wrong_refund() -> Weight; fn clean_defunct_voters(v: u32, d: u32, ) -> Weight; fn election_phragmen(c: u32, v: u32, e: u32, ) -> Weight; @@ -69,9 +70,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Elections Voting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_equal(v: u32, ) -> Weight { - (42_509_000 as Weight) + (24_231_000 as Weight) // Standard Error: 4_000 - .saturating_add((372_000 as Weight).saturating_mul(v as Weight)) + .saturating_add((305_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -81,9 +82,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Elections Voting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_more(v: u32, ) -> Weight { - (65_311_000 as Weight) + (37_524_000 as Weight) // Standard Error: 6_000 - .saturating_add((419_000 as Weight).saturating_mul(v as Weight)) + .saturating_add((285_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -93,16 +94,16 @@ impl WeightInfo for SubstrateWeight { // Storage: Elections Voting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_less(v: u32, ) -> Weight { - (65_444_000 as Weight) - // Standard Error: 5_000 - .saturating_add((376_000 as Weight).saturating_mul(v as Weight)) + (37_350_000 as Weight) + // Standard Error: 7_000 + .saturating_add((311_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Elections Voting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn remove_voter() -> Weight { - (61_585_000 as Weight) + (35_119_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -110,53 +111,54 @@ impl WeightInfo for SubstrateWeight { // Storage: Elections Members (r:1 w:0) // Storage: Elections RunnersUp (r:1 w:0) fn submit_candidacy(c: u32, ) -> Weight { - (53_333_000 as Weight) + (36_110_000 as Weight) // Standard Error: 1_000 - .saturating_add((267_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((193_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Elections Candidates (r:1 w:1) fn renounce_candidacy_candidate(c: u32, ) -> Weight { - (49_128_000 as Weight) + (30_976_000 as Weight) // Standard Error: 1_000 - .saturating_add((144_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((129_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Elections Members (r:1 w:1) // Storage: Elections RunnersUp (r:1 w:1) - // Storage: Instance1Collective Prime (r:1 w:1) - // Storage: Instance1Collective Proposals (r:1 w:0) - // Storage: Instance1Collective Members (r:0 w:1) + // Storage: Council Prime (r:1 w:1) + // Storage: Council Proposals (r:1 w:0) + // Storage: Council Members (r:0 w:1) fn renounce_candidacy_members() -> Weight { - (70_685_000 as Weight) + (44_456_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } // Storage: Elections RunnersUp (r:1 w:1) fn renounce_candidacy_runners_up() -> Weight { - (49_766_000 as Weight) + (31_990_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } + // Storage: Benchmark Override (r:0 w:0) + fn remove_member_without_replacement() -> Weight { + (2_000_000_000_000 as Weight) + } // Storage: Elections RunnersUp (r:1 w:1) // Storage: Elections Members (r:1 w:1) // Storage: System Account (r:1 w:1) - // Storage: Instance1Collective Prime (r:1 w:1) - // Storage: Instance1Collective Proposals (r:1 w:0) - // Storage: Instance1Collective Members (r:0 w:1) + // Storage: Council Prime (r:1 w:1) + // Storage: Council Proposals (r:1 w:0) + // Storage: Council Members (r:0 w:1) fn remove_member_with_replacement() -> Weight { - (76_153_000 as Weight) + (51_221_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } - fn remove_member_without_replacement() -> Weight { - T::BlockWeights::get().max_block - } // Storage: Elections RunnersUp (r:1 w:0) fn remove_member_wrong_refund() -> Weight { - (6_697_000 as Weight) + (4_773_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) } // Storage: Elections Voting (r:251 w:250) @@ -167,8 +169,8 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:250 w:250) fn clean_defunct_voters(v: u32, _d: u32, ) -> Weight { (0 as Weight) - // Standard Error: 60_000 - .saturating_add((107_467_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 31_000 + .saturating_add((51_744_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(v as Weight))) .saturating_add(T::DbWeight::get().writes((3 as Weight).saturating_mul(v as Weight))) @@ -177,19 +179,19 @@ impl WeightInfo for SubstrateWeight { // Storage: Elections Members (r:1 w:1) // Storage: Elections RunnersUp (r:1 w:1) // Storage: Elections Voting (r:502 w:0) - // Storage: Instance1Collective Proposals (r:1 w:0) + // Storage: Council Proposals (r:1 w:0) // Storage: Elections ElectionRounds (r:1 w:1) - // Storage: Instance1Collective Members (r:0 w:1) - // Storage: Instance1Collective Prime (r:0 w:1) + // Storage: Council Members (r:0 w:1) + // Storage: Council Prime (r:0 w:1) // Storage: System Account (r:2 w:2) fn election_phragmen(c: u32, v: u32, e: u32, ) -> Weight { (0 as Weight) - // Standard Error: 1_846_000 - .saturating_add((39_843_000 as Weight).saturating_mul(c as Weight)) - // Standard Error: 768_000 - .saturating_add((60_623_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 52_000 - .saturating_add((3_884_000 as Weight).saturating_mul(e as Weight)) + // Standard Error: 1_744_000 + .saturating_add((29_677_000 as Weight).saturating_mul(c as Weight)) + // Standard Error: 725_000 + .saturating_add((51_480_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 49_000 + .saturating_add((3_491_000 as Weight).saturating_mul(e as Weight)) .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(c as Weight))) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(v as Weight))) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(c as Weight))) @@ -204,9 +206,9 @@ impl WeightInfo for () { // Storage: Elections Voting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_equal(v: u32, ) -> Weight { - (42_509_000 as Weight) + (24_231_000 as Weight) // Standard Error: 4_000 - .saturating_add((372_000 as Weight).saturating_mul(v as Weight)) + .saturating_add((305_000 as Weight).saturating_mul(v as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -216,9 +218,9 @@ impl WeightInfo for () { // Storage: Elections Voting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_more(v: u32, ) -> Weight { - (65_311_000 as Weight) + (37_524_000 as Weight) // Standard Error: 6_000 - .saturating_add((419_000 as Weight).saturating_mul(v as Weight)) + .saturating_add((285_000 as Weight).saturating_mul(v as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -228,16 +230,16 @@ impl WeightInfo for () { // Storage: Elections Voting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_less(v: u32, ) -> Weight { - (65_444_000 as Weight) - // Standard Error: 5_000 - .saturating_add((376_000 as Weight).saturating_mul(v as Weight)) + (37_350_000 as Weight) + // Standard Error: 7_000 + .saturating_add((311_000 as Weight).saturating_mul(v as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Elections Voting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn remove_voter() -> Weight { - (61_585_000 as Weight) + (35_119_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -245,55 +247,54 @@ impl WeightInfo for () { // Storage: Elections Members (r:1 w:0) // Storage: Elections RunnersUp (r:1 w:0) fn submit_candidacy(c: u32, ) -> Weight { - (53_333_000 as Weight) + (36_110_000 as Weight) // Standard Error: 1_000 - .saturating_add((267_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((193_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Elections Candidates (r:1 w:1) fn renounce_candidacy_candidate(c: u32, ) -> Weight { - (49_128_000 as Weight) + (30_976_000 as Weight) // Standard Error: 1_000 - .saturating_add((144_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((129_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Elections Members (r:1 w:1) // Storage: Elections RunnersUp (r:1 w:1) - // Storage: Instance1Collective Prime (r:1 w:1) - // Storage: Instance1Collective Proposals (r:1 w:0) - // Storage: Instance1Collective Members (r:0 w:1) + // Storage: Council Prime (r:1 w:1) + // Storage: Council Proposals (r:1 w:0) + // Storage: Council Members (r:0 w:1) fn renounce_candidacy_members() -> Weight { - (70_685_000 as Weight) + (44_456_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } // Storage: Elections RunnersUp (r:1 w:1) fn renounce_candidacy_runners_up() -> Weight { - (49_766_000 as Weight) + (31_990_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } + // Storage: Benchmark Override (r:0 w:0) + fn remove_member_without_replacement() -> Weight { + (2_000_000_000_000 as Weight) + } // Storage: Elections RunnersUp (r:1 w:1) // Storage: Elections Members (r:1 w:1) // Storage: System Account (r:1 w:1) - // Storage: Instance1Collective Prime (r:1 w:1) - // Storage: Instance1Collective Proposals (r:1 w:0) - // Storage: Instance1Collective Members (r:0 w:1) + // Storage: Council Prime (r:1 w:1) + // Storage: Council Proposals (r:1 w:0) + // Storage: Council Members (r:0 w:1) fn remove_member_with_replacement() -> Weight { - (76_153_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) - .saturating_add(RocksDbWeight::get().writes(5 as Weight)) - } - fn remove_member_without_replacement() -> Weight { - (76_153_000 as Weight) + (51_221_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } // Storage: Elections RunnersUp (r:1 w:0) fn remove_member_wrong_refund() -> Weight { - (6_697_000 as Weight) + (4_773_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) } // Storage: Elections Voting (r:251 w:250) @@ -304,8 +305,8 @@ impl WeightInfo for () { // Storage: System Account (r:250 w:250) fn clean_defunct_voters(v: u32, _d: u32, ) -> Weight { (0 as Weight) - // Standard Error: 60_000 - .saturating_add((107_467_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 31_000 + .saturating_add((51_744_000 as Weight).saturating_mul(v as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(v as Weight))) .saturating_add(RocksDbWeight::get().writes((3 as Weight).saturating_mul(v as Weight))) @@ -314,19 +315,19 @@ impl WeightInfo for () { // Storage: Elections Members (r:1 w:1) // Storage: Elections RunnersUp (r:1 w:1) // Storage: Elections Voting (r:502 w:0) - // Storage: Instance1Collective Proposals (r:1 w:0) + // Storage: Council Proposals (r:1 w:0) // Storage: Elections ElectionRounds (r:1 w:1) - // Storage: Instance1Collective Members (r:0 w:1) - // Storage: Instance1Collective Prime (r:0 w:1) + // Storage: Council Members (r:0 w:1) + // Storage: Council Prime (r:0 w:1) // Storage: System Account (r:2 w:2) fn election_phragmen(c: u32, v: u32, e: u32, ) -> Weight { (0 as Weight) - // Standard Error: 1_846_000 - .saturating_add((39_843_000 as Weight).saturating_mul(c as Weight)) - // Standard Error: 768_000 - .saturating_add((60_623_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 52_000 - .saturating_add((3_884_000 as Weight).saturating_mul(e as Weight)) + // Standard Error: 1_744_000 + .saturating_add((29_677_000 as Weight).saturating_mul(c as Weight)) + // Standard Error: 725_000 + .saturating_add((51_480_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 49_000 + .saturating_add((3_491_000 as Weight).saturating_mul(e as Weight)) .saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(c as Weight))) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(v as Weight))) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(c as Weight))) diff --git a/frame/gilt/src/weights.rs b/frame/gilt/src/weights.rs index fd4dcd1b5d5a..b56b6051a9ae 100644 --- a/frame/gilt/src/weights.rs +++ b/frame/gilt/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. +// Copyright (C) 2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_gilt //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-08-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 +//! DATE: 2022-01-17, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// target/release/substrate +// ./target/lto-fat-cg1/substrate // benchmark // --chain=dev // --steps=50 @@ -33,8 +33,9 @@ // --wasm-execution=compiled // --heap-pages=4096 // --output=./frame/gilt/src/weights.rs -// --template=./.maintain/frame-weight-template.hbs - +// --template=.maintain/frame-weight-template.hbs +// --header=LICENSE-APACHE2 +// --raw #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -61,44 +62,44 @@ impl WeightInfo for SubstrateWeight { // Storage: Gilt Queues (r:1 w:1) // Storage: Gilt QueueTotals (r:1 w:1) fn place_bid(l: u32, ) -> Weight { - (59_219_000 as Weight) + (32_876_000 as Weight) // Standard Error: 0 - .saturating_add((156_000 as Weight).saturating_mul(l as Weight)) + .saturating_add((97_000 as Weight).saturating_mul(l as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Gilt Queues (r:1 w:1) // Storage: Gilt QueueTotals (r:1 w:1) fn place_bid_max() -> Weight { - (184_943_000 as Weight) + (125_854_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Gilt Queues (r:1 w:1) // Storage: Gilt QueueTotals (r:1 w:1) fn retract_bid(l: u32, ) -> Weight { - (59_352_000 as Weight) + (33_643_000 as Weight) // Standard Error: 0 - .saturating_add((129_000 as Weight).saturating_mul(l as Weight)) + .saturating_add((88_000 as Weight).saturating_mul(l as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Gilt ActiveTotal (r:1 w:1) fn set_target() -> Weight { - (5_444_000 as Weight) + (2_570_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Gilt Active (r:1 w:1) // Storage: Gilt ActiveTotal (r:1 w:1) fn thaw() -> Weight { - (71_399_000 as Weight) + (40_854_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Gilt ActiveTotal (r:1 w:0) fn pursue_target_noop() -> Weight { - (3_044_000 as Weight) + (1_598_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) } // Storage: Gilt ActiveTotal (r:1 w:1) @@ -106,9 +107,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Gilt Queues (r:1 w:1) // Storage: Gilt Active (r:0 w:1) fn pursue_target_per_item(b: u32, ) -> Weight { - (54_478_000 as Weight) - // Standard Error: 2_000 - .saturating_add((10_150_000 as Weight).saturating_mul(b as Weight)) + (34_848_000 as Weight) + // Standard Error: 1_000 + .saturating_add((3_951_000 as Weight).saturating_mul(b as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(b as Weight))) @@ -118,9 +119,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Gilt Queues (r:1 w:1) // Storage: Gilt Active (r:0 w:1) fn pursue_target_per_queue(q: u32, ) -> Weight { - (20_099_000 as Weight) - // Standard Error: 7_000 - .saturating_add((16_603_000 as Weight).saturating_mul(q as Weight)) + (9_735_000 as Weight) + // Standard Error: 6_000 + .saturating_add((7_873_000 as Weight).saturating_mul(q as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(q as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -133,44 +134,44 @@ impl WeightInfo for () { // Storage: Gilt Queues (r:1 w:1) // Storage: Gilt QueueTotals (r:1 w:1) fn place_bid(l: u32, ) -> Weight { - (59_219_000 as Weight) + (32_876_000 as Weight) // Standard Error: 0 - .saturating_add((156_000 as Weight).saturating_mul(l as Weight)) + .saturating_add((97_000 as Weight).saturating_mul(l as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Gilt Queues (r:1 w:1) // Storage: Gilt QueueTotals (r:1 w:1) fn place_bid_max() -> Weight { - (184_943_000 as Weight) + (125_854_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Gilt Queues (r:1 w:1) // Storage: Gilt QueueTotals (r:1 w:1) fn retract_bid(l: u32, ) -> Weight { - (59_352_000 as Weight) + (33_643_000 as Weight) // Standard Error: 0 - .saturating_add((129_000 as Weight).saturating_mul(l as Weight)) + .saturating_add((88_000 as Weight).saturating_mul(l as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Gilt ActiveTotal (r:1 w:1) fn set_target() -> Weight { - (5_444_000 as Weight) + (2_570_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Gilt Active (r:1 w:1) // Storage: Gilt ActiveTotal (r:1 w:1) fn thaw() -> Weight { - (71_399_000 as Weight) + (40_854_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Gilt ActiveTotal (r:1 w:0) fn pursue_target_noop() -> Weight { - (3_044_000 as Weight) + (1_598_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) } // Storage: Gilt ActiveTotal (r:1 w:1) @@ -178,9 +179,9 @@ impl WeightInfo for () { // Storage: Gilt Queues (r:1 w:1) // Storage: Gilt Active (r:0 w:1) fn pursue_target_per_item(b: u32, ) -> Weight { - (54_478_000 as Weight) - // Standard Error: 2_000 - .saturating_add((10_150_000 as Weight).saturating_mul(b as Weight)) + (34_848_000 as Weight) + // Standard Error: 1_000 + .saturating_add((3_951_000 as Weight).saturating_mul(b as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(b as Weight))) @@ -190,9 +191,9 @@ impl WeightInfo for () { // Storage: Gilt Queues (r:1 w:1) // Storage: Gilt Active (r:0 w:1) fn pursue_target_per_queue(q: u32, ) -> Weight { - (20_099_000 as Weight) - // Standard Error: 7_000 - .saturating_add((16_603_000 as Weight).saturating_mul(q as Weight)) + (9_735_000 as Weight) + // Standard Error: 6_000 + .saturating_add((7_873_000 as Weight).saturating_mul(q as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(q as Weight))) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) diff --git a/frame/identity/src/weights.rs b/frame/identity/src/weights.rs index 9f04007431be..1d0a7825ec40 100644 --- a/frame/identity/src/weights.rs +++ b/frame/identity/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. +// Copyright (C) 2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_identity //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-11-17, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 +//! DATE: 2022-01-17, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// target/release/substrate +// ./target/lto-fat-cg1/substrate // benchmark // --chain=dev // --steps=50 @@ -33,7 +33,9 @@ // --wasm-execution=compiled // --heap-pages=4096 // --output=./frame/identity/src/weights.rs -// --template=./.maintain/frame-weight-template.hbs +// --template=.maintain/frame-weight-template.hbs +// --header=LICENSE-APACHE2 +// --raw #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -67,19 +69,19 @@ pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { // Storage: Identity Registrars (r:1 w:1) fn add_registrar(r: u32, ) -> Weight { - (19_176_000 as Weight) - // Standard Error: 5_000 - .saturating_add((313_000 as Weight).saturating_mul(r as Weight)) + (12_513_000 as Weight) + // Standard Error: 4_000 + .saturating_add((257_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Identity IdentityOf (r:1 w:1) fn set_identity(r: u32, x: u32, ) -> Weight { - (44_668_000 as Weight) - // Standard Error: 12_000 - .saturating_add((244_000 as Weight).saturating_mul(r as Weight)) - // Standard Error: 1_000 - .saturating_add((811_000 as Weight).saturating_mul(x as Weight)) + (27_904_000 as Weight) + // Standard Error: 7_000 + .saturating_add((215_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 0 + .saturating_add((294_000 as Weight).saturating_mul(x as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -87,9 +89,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Identity SubsOf (r:1 w:1) // Storage: Identity SuperOf (r:1 w:1) fn set_subs_new(s: u32, ) -> Weight { - (38_917_000 as Weight) - // Standard Error: 3_000 - .saturating_add((5_331_000 as Weight).saturating_mul(s as Weight)) + (24_530_000 as Weight) + // Standard Error: 1_000 + .saturating_add((2_914_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -99,9 +101,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Identity SubsOf (r:1 w:1) // Storage: Identity SuperOf (r:0 w:1) fn set_subs_old(p: u32, ) -> Weight { - (36_057_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_756_000 as Weight).saturating_mul(p as Weight)) + (23_957_000 as Weight) + // Standard Error: 0 + .saturating_add((954_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(p as Weight))) @@ -110,13 +112,13 @@ impl WeightInfo for SubstrateWeight { // Storage: Identity IdentityOf (r:1 w:1) // Storage: Identity SuperOf (r:0 w:100) fn clear_identity(r: u32, s: u32, x: u32, ) -> Weight { - (44_348_000 as Weight) - // Standard Error: 9_000 - .saturating_add((183_000 as Weight).saturating_mul(r as Weight)) - // Standard Error: 1_000 - .saturating_add((1_724_000 as Weight).saturating_mul(s as Weight)) - // Standard Error: 1_000 - .saturating_add((439_000 as Weight).saturating_mul(x as Weight)) + (31_213_000 as Weight) + // Standard Error: 8_000 + .saturating_add((99_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 0 + .saturating_add((931_000 as Weight).saturating_mul(s as Weight)) + // Standard Error: 0 + .saturating_add((188_000 as Weight).saturating_mul(x as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) @@ -124,56 +126,56 @@ impl WeightInfo for SubstrateWeight { // Storage: Identity Registrars (r:1 w:0) // Storage: Identity IdentityOf (r:1 w:1) fn request_judgement(r: u32, x: u32, ) -> Weight { - (46_592_000 as Weight) - // Standard Error: 5_000 - .saturating_add((321_000 as Weight).saturating_mul(r as Weight)) + (30_691_000 as Weight) + // Standard Error: 4_000 + .saturating_add((269_000 as Weight).saturating_mul(r as Weight)) // Standard Error: 0 - .saturating_add((858_000 as Weight).saturating_mul(x as Weight)) + .saturating_add((338_000 as Weight).saturating_mul(x as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Identity IdentityOf (r:1 w:1) fn cancel_request(r: u32, x: u32, ) -> Weight { - (43_556_000 as Weight) - // Standard Error: 6_000 - .saturating_add((174_000 as Weight).saturating_mul(r as Weight)) + (27_356_000 as Weight) + // Standard Error: 3_000 + .saturating_add((179_000 as Weight).saturating_mul(r as Weight)) // Standard Error: 0 - .saturating_add((850_000 as Weight).saturating_mul(x as Weight)) + .saturating_add((335_000 as Weight).saturating_mul(x as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Identity Registrars (r:1 w:1) fn set_fee(r: u32, ) -> Weight { - (7_971_000 as Weight) - // Standard Error: 4_000 - .saturating_add((283_000 as Weight).saturating_mul(r as Weight)) + (4_761_000 as Weight) + // Standard Error: 2_000 + .saturating_add((202_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Identity Registrars (r:1 w:1) fn set_account_id(r: u32, ) -> Weight { - (8_234_000 as Weight) - // Standard Error: 4_000 - .saturating_add((280_000 as Weight).saturating_mul(r as Weight)) + (4_801_000 as Weight) + // Standard Error: 3_000 + .saturating_add((211_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Identity Registrars (r:1 w:1) fn set_fields(r: u32, ) -> Weight { - (8_126_000 as Weight) - // Standard Error: 4_000 - .saturating_add((275_000 as Weight).saturating_mul(r as Weight)) + (4_756_000 as Weight) + // Standard Error: 2_000 + .saturating_add((204_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Identity Registrars (r:1 w:0) // Storage: Identity IdentityOf (r:1 w:1) fn provide_judgement(r: u32, x: u32, ) -> Weight { - (30_949_000 as Weight) - // Standard Error: 5_000 - .saturating_add((286_000 as Weight).saturating_mul(r as Weight)) + (21_047_000 as Weight) + // Standard Error: 3_000 + .saturating_add((246_000 as Weight).saturating_mul(r as Weight)) // Standard Error: 0 - .saturating_add((856_000 as Weight).saturating_mul(x as Weight)) + .saturating_add((341_000 as Weight).saturating_mul(x as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -182,11 +184,11 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:1 w:1) // Storage: Identity SuperOf (r:0 w:100) fn kill_identity(r: u32, s: u32, _x: u32, ) -> Weight { - (63_792_000 as Weight) - // Standard Error: 11_000 - .saturating_add((242_000 as Weight).saturating_mul(r as Weight)) - // Standard Error: 1_000 - .saturating_add((1_738_000 as Weight).saturating_mul(s as Weight)) + (41_324_000 as Weight) + // Standard Error: 7_000 + .saturating_add((192_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 0 + .saturating_add((951_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) @@ -195,18 +197,18 @@ impl WeightInfo for SubstrateWeight { // Storage: Identity SuperOf (r:1 w:1) // Storage: Identity SubsOf (r:1 w:1) fn add_sub(s: u32, ) -> Weight { - (48_751_000 as Weight) + (31_405_000 as Weight) // Standard Error: 1_000 - .saturating_add((193_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((160_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Identity IdentityOf (r:1 w:0) // Storage: Identity SuperOf (r:1 w:1) fn rename_sub(s: u32, ) -> Weight { - (15_892_000 as Weight) + (10_622_000 as Weight) // Standard Error: 0 - .saturating_add((49_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((47_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -214,18 +216,18 @@ impl WeightInfo for SubstrateWeight { // Storage: Identity SuperOf (r:1 w:1) // Storage: Identity SubsOf (r:1 w:1) fn remove_sub(s: u32, ) -> Weight { - (49_746_000 as Weight) + (32_765_000 as Weight) // Standard Error: 1_000 - .saturating_add((181_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((158_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Identity SuperOf (r:1 w:1) // Storage: Identity SubsOf (r:1 w:1) fn quit_sub(s: u32, ) -> Weight { - (32_286_000 as Weight) + (21_925_000 as Weight) // Standard Error: 1_000 - .saturating_add((166_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((156_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -235,19 +237,19 @@ impl WeightInfo for SubstrateWeight { impl WeightInfo for () { // Storage: Identity Registrars (r:1 w:1) fn add_registrar(r: u32, ) -> Weight { - (19_176_000 as Weight) - // Standard Error: 5_000 - .saturating_add((313_000 as Weight).saturating_mul(r as Weight)) + (12_513_000 as Weight) + // Standard Error: 4_000 + .saturating_add((257_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Identity IdentityOf (r:1 w:1) fn set_identity(r: u32, x: u32, ) -> Weight { - (44_668_000 as Weight) - // Standard Error: 12_000 - .saturating_add((244_000 as Weight).saturating_mul(r as Weight)) - // Standard Error: 1_000 - .saturating_add((811_000 as Weight).saturating_mul(x as Weight)) + (27_904_000 as Weight) + // Standard Error: 7_000 + .saturating_add((215_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 0 + .saturating_add((294_000 as Weight).saturating_mul(x as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -255,9 +257,9 @@ impl WeightInfo for () { // Storage: Identity SubsOf (r:1 w:1) // Storage: Identity SuperOf (r:1 w:1) fn set_subs_new(s: u32, ) -> Weight { - (38_917_000 as Weight) - // Standard Error: 3_000 - .saturating_add((5_331_000 as Weight).saturating_mul(s as Weight)) + (24_530_000 as Weight) + // Standard Error: 1_000 + .saturating_add((2_914_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -267,9 +269,9 @@ impl WeightInfo for () { // Storage: Identity SubsOf (r:1 w:1) // Storage: Identity SuperOf (r:0 w:1) fn set_subs_old(p: u32, ) -> Weight { - (36_057_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_756_000 as Weight).saturating_mul(p as Weight)) + (23_957_000 as Weight) + // Standard Error: 0 + .saturating_add((954_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(p as Weight))) @@ -278,13 +280,13 @@ impl WeightInfo for () { // Storage: Identity IdentityOf (r:1 w:1) // Storage: Identity SuperOf (r:0 w:100) fn clear_identity(r: u32, s: u32, x: u32, ) -> Weight { - (44_348_000 as Weight) - // Standard Error: 9_000 - .saturating_add((183_000 as Weight).saturating_mul(r as Weight)) - // Standard Error: 1_000 - .saturating_add((1_724_000 as Weight).saturating_mul(s as Weight)) - // Standard Error: 1_000 - .saturating_add((439_000 as Weight).saturating_mul(x as Weight)) + (31_213_000 as Weight) + // Standard Error: 8_000 + .saturating_add((99_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 0 + .saturating_add((931_000 as Weight).saturating_mul(s as Weight)) + // Standard Error: 0 + .saturating_add((188_000 as Weight).saturating_mul(x as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) @@ -292,56 +294,56 @@ impl WeightInfo for () { // Storage: Identity Registrars (r:1 w:0) // Storage: Identity IdentityOf (r:1 w:1) fn request_judgement(r: u32, x: u32, ) -> Weight { - (46_592_000 as Weight) - // Standard Error: 5_000 - .saturating_add((321_000 as Weight).saturating_mul(r as Weight)) + (30_691_000 as Weight) + // Standard Error: 4_000 + .saturating_add((269_000 as Weight).saturating_mul(r as Weight)) // Standard Error: 0 - .saturating_add((858_000 as Weight).saturating_mul(x as Weight)) + .saturating_add((338_000 as Weight).saturating_mul(x as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Identity IdentityOf (r:1 w:1) fn cancel_request(r: u32, x: u32, ) -> Weight { - (43_556_000 as Weight) - // Standard Error: 6_000 - .saturating_add((174_000 as Weight).saturating_mul(r as Weight)) + (27_356_000 as Weight) + // Standard Error: 3_000 + .saturating_add((179_000 as Weight).saturating_mul(r as Weight)) // Standard Error: 0 - .saturating_add((850_000 as Weight).saturating_mul(x as Weight)) + .saturating_add((335_000 as Weight).saturating_mul(x as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Identity Registrars (r:1 w:1) fn set_fee(r: u32, ) -> Weight { - (7_971_000 as Weight) - // Standard Error: 4_000 - .saturating_add((283_000 as Weight).saturating_mul(r as Weight)) + (4_761_000 as Weight) + // Standard Error: 2_000 + .saturating_add((202_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Identity Registrars (r:1 w:1) fn set_account_id(r: u32, ) -> Weight { - (8_234_000 as Weight) - // Standard Error: 4_000 - .saturating_add((280_000 as Weight).saturating_mul(r as Weight)) + (4_801_000 as Weight) + // Standard Error: 3_000 + .saturating_add((211_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Identity Registrars (r:1 w:1) fn set_fields(r: u32, ) -> Weight { - (8_126_000 as Weight) - // Standard Error: 4_000 - .saturating_add((275_000 as Weight).saturating_mul(r as Weight)) + (4_756_000 as Weight) + // Standard Error: 2_000 + .saturating_add((204_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Identity Registrars (r:1 w:0) // Storage: Identity IdentityOf (r:1 w:1) fn provide_judgement(r: u32, x: u32, ) -> Weight { - (30_949_000 as Weight) - // Standard Error: 5_000 - .saturating_add((286_000 as Weight).saturating_mul(r as Weight)) + (21_047_000 as Weight) + // Standard Error: 3_000 + .saturating_add((246_000 as Weight).saturating_mul(r as Weight)) // Standard Error: 0 - .saturating_add((856_000 as Weight).saturating_mul(x as Weight)) + .saturating_add((341_000 as Weight).saturating_mul(x as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -350,11 +352,11 @@ impl WeightInfo for () { // Storage: System Account (r:1 w:1) // Storage: Identity SuperOf (r:0 w:100) fn kill_identity(r: u32, s: u32, _x: u32, ) -> Weight { - (63_792_000 as Weight) - // Standard Error: 11_000 - .saturating_add((242_000 as Weight).saturating_mul(r as Weight)) - // Standard Error: 1_000 - .saturating_add((1_738_000 as Weight).saturating_mul(s as Weight)) + (41_324_000 as Weight) + // Standard Error: 7_000 + .saturating_add((192_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 0 + .saturating_add((951_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) @@ -363,18 +365,18 @@ impl WeightInfo for () { // Storage: Identity SuperOf (r:1 w:1) // Storage: Identity SubsOf (r:1 w:1) fn add_sub(s: u32, ) -> Weight { - (48_751_000 as Weight) + (31_405_000 as Weight) // Standard Error: 1_000 - .saturating_add((193_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((160_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Identity IdentityOf (r:1 w:0) // Storage: Identity SuperOf (r:1 w:1) fn rename_sub(s: u32, ) -> Weight { - (15_892_000 as Weight) + (10_622_000 as Weight) // Standard Error: 0 - .saturating_add((49_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((47_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -382,18 +384,18 @@ impl WeightInfo for () { // Storage: Identity SuperOf (r:1 w:1) // Storage: Identity SubsOf (r:1 w:1) fn remove_sub(s: u32, ) -> Weight { - (49_746_000 as Weight) + (32_765_000 as Weight) // Standard Error: 1_000 - .saturating_add((181_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((158_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Identity SuperOf (r:1 w:1) // Storage: Identity SubsOf (r:1 w:1) fn quit_sub(s: u32, ) -> Weight { - (32_286_000 as Weight) + (21_925_000 as Weight) // Standard Error: 1_000 - .saturating_add((166_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((156_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } diff --git a/frame/im-online/src/weights.rs b/frame/im-online/src/weights.rs index 19ac7e8ffc0f..4fa5727251b3 100644 --- a/frame/im-online/src/weights.rs +++ b/frame/im-online/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. +// Copyright (C) 2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_im_online //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-08-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 +//! DATE: 2022-01-19, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// target/release/substrate +// ./target/optimized/substrate // benchmark // --chain=dev // --steps=50 @@ -32,9 +32,10 @@ // --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/im-online/src/weights.rs -// --template=./.maintain/frame-weight-template.hbs - +// --output=./weights-optimized/frame/im-online/src//weights.rs +// --template=.maintain/frame-weight-template.hbs +// --header=HEADER-APACHE2 +// --raw #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -57,11 +58,11 @@ impl WeightInfo for SubstrateWeight { // Storage: ImOnline AuthoredBlocks (r:1 w:0) // Storage: ImOnline Keys (r:1 w:0) fn validate_unsigned_and_then_heartbeat(k: u32, e: u32, ) -> Weight { - (93_400_000 as Weight) + (73_594_000 as Weight) // Standard Error: 0 - .saturating_add((144_000 as Weight).saturating_mul(k as Weight)) + .saturating_add((128_000 as Weight).saturating_mul(k as Weight)) // Standard Error: 0 - .saturating_add((335_000 as Weight).saturating_mul(e as Weight)) + .saturating_add((295_000 as Weight).saturating_mul(e as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -75,11 +76,11 @@ impl WeightInfo for () { // Storage: ImOnline AuthoredBlocks (r:1 w:0) // Storage: ImOnline Keys (r:1 w:0) fn validate_unsigned_and_then_heartbeat(k: u32, e: u32, ) -> Weight { - (93_400_000 as Weight) + (73_594_000 as Weight) // Standard Error: 0 - .saturating_add((144_000 as Weight).saturating_mul(k as Weight)) + .saturating_add((128_000 as Weight).saturating_mul(k as Weight)) // Standard Error: 0 - .saturating_add((335_000 as Weight).saturating_mul(e as Weight)) + .saturating_add((295_000 as Weight).saturating_mul(e as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } diff --git a/frame/indices/src/weights.rs b/frame/indices/src/weights.rs index 590aa11dec84..569af75af6dc 100644 --- a/frame/indices/src/weights.rs +++ b/frame/indices/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. +// Copyright (C) 2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_indices //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-08-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 +//! DATE: 2022-01-17, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// target/release/substrate +// ./target/lto-fat-cg1/substrate // benchmark // --chain=dev // --steps=50 @@ -33,8 +33,9 @@ // --wasm-execution=compiled // --heap-pages=4096 // --output=./frame/indices/src/weights.rs -// --template=./.maintain/frame-weight-template.hbs - +// --template=.maintain/frame-weight-template.hbs +// --header=LICENSE-APACHE2 +// --raw #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -57,33 +58,33 @@ pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { // Storage: Indices Accounts (r:1 w:1) fn claim() -> Weight { - (38_814_000 as Weight) + (20_754_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Indices Accounts (r:1 w:1) // Storage: System Account (r:1 w:1) fn transfer() -> Weight { - (47_274_000 as Weight) + (26_655_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Indices Accounts (r:1 w:1) fn free() -> Weight { - (39_692_000 as Weight) + (22_112_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Indices Accounts (r:1 w:1) // Storage: System Account (r:1 w:1) fn force_transfer() -> Weight { - (40_250_000 as Weight) + (22_175_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Indices Accounts (r:1 w:1) fn freeze() -> Weight { - (37_358_000 as Weight) + (24_344_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -93,33 +94,33 @@ impl WeightInfo for SubstrateWeight { impl WeightInfo for () { // Storage: Indices Accounts (r:1 w:1) fn claim() -> Weight { - (38_814_000 as Weight) + (20_754_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Indices Accounts (r:1 w:1) // Storage: System Account (r:1 w:1) fn transfer() -> Weight { - (47_274_000 as Weight) + (26_655_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Indices Accounts (r:1 w:1) fn free() -> Weight { - (39_692_000 as Weight) + (22_112_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Indices Accounts (r:1 w:1) // Storage: System Account (r:1 w:1) fn force_transfer() -> Weight { - (40_250_000 as Weight) + (22_175_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Indices Accounts (r:1 w:1) fn freeze() -> Weight { - (37_358_000 as Weight) + (24_344_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } diff --git a/frame/lottery/src/weights.rs b/frame/lottery/src/weights.rs index 53ec2aa23156..080222125c84 100644 --- a/frame/lottery/src/weights.rs +++ b/frame/lottery/src/weights.rs @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_lottery //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-11, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 +//! DATE: 2022-01-17, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// target/release/substrate +// ./target/lto-fat-cg1/substrate // benchmark // --chain=dev // --steps=50 @@ -33,7 +33,9 @@ // --wasm-execution=compiled // --heap-pages=4096 // --output=./frame/lottery/src/weights.rs -// --template=./.maintain/frame-weight-template.hbs +// --template=.maintain/frame-weight-template.hbs +// --header=LICENSE-APACHE2 +// --raw #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -63,28 +65,28 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:1 w:1) // Storage: Lottery Tickets (r:0 w:1) fn buy_ticket() -> Weight { - (52_219_000 as Weight) + (38_270_000 as Weight) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } // Storage: Lottery CallIndices (r:0 w:1) fn set_calls(n: u32, ) -> Weight { - (13_249_000 as Weight) + (8_830_000 as Weight) // Standard Error: 7_000 - .saturating_add((378_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((291_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Lottery Lottery (r:1 w:1) // Storage: Lottery LotteryIndex (r:1 w:1) // Storage: System Account (r:1 w:1) fn start_lottery() -> Weight { - (44_636_000 as Weight) + (31_404_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Lottery Lottery (r:1 w:1) fn stop_repeat() -> Weight { - (5_654_000 as Weight) + (3_825_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -94,7 +96,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Lottery TicketsCount (r:1 w:1) // Storage: Lottery Tickets (r:1 w:0) fn on_initialize_end() -> Weight { - (72_990_000 as Weight) + (49_760_000 as Weight) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } @@ -105,7 +107,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Lottery Tickets (r:1 w:0) // Storage: Lottery LotteryIndex (r:1 w:1) fn on_initialize_repeat() -> Weight { - (75_323_000 as Weight) + (53_159_000 as Weight) .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } @@ -121,28 +123,28 @@ impl WeightInfo for () { // Storage: System Account (r:1 w:1) // Storage: Lottery Tickets (r:0 w:1) fn buy_ticket() -> Weight { - (52_219_000 as Weight) + (38_270_000 as Weight) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } // Storage: Lottery CallIndices (r:0 w:1) fn set_calls(n: u32, ) -> Weight { - (13_249_000 as Weight) + (8_830_000 as Weight) // Standard Error: 7_000 - .saturating_add((378_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((291_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Lottery Lottery (r:1 w:1) // Storage: Lottery LotteryIndex (r:1 w:1) // Storage: System Account (r:1 w:1) fn start_lottery() -> Weight { - (44_636_000 as Weight) + (31_404_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } // Storage: Lottery Lottery (r:1 w:1) fn stop_repeat() -> Weight { - (5_654_000 as Weight) + (3_825_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -152,7 +154,7 @@ impl WeightInfo for () { // Storage: Lottery TicketsCount (r:1 w:1) // Storage: Lottery Tickets (r:1 w:0) fn on_initialize_end() -> Weight { - (72_990_000 as Weight) + (49_760_000 as Weight) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } @@ -163,7 +165,7 @@ impl WeightInfo for () { // Storage: Lottery Tickets (r:1 w:0) // Storage: Lottery LotteryIndex (r:1 w:1) fn on_initialize_repeat() -> Weight { - (75_323_000 as Weight) + (53_159_000 as Weight) .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } diff --git a/frame/membership/src/weights.rs b/frame/membership/src/weights.rs index 5b34529c7c18..59215d3a5bff 100644 --- a/frame/membership/src/weights.rs +++ b/frame/membership/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. +// Copyright (C) 2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_membership //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-08-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 +//! DATE: 2022-01-17, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// target/release/substrate +// ./target/lto-fat-cg1/substrate // benchmark // --chain=dev // --steps=50 @@ -33,8 +33,9 @@ // --wasm-execution=compiled // --heap-pages=4096 // --output=./frame/membership/src/weights.rs -// --template=./.maintain/frame-weight-template.hbs - +// --template=.maintain/frame-weight-template.hbs +// --header=LICENSE-APACHE2 +// --raw #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -57,79 +58,79 @@ pub trait WeightInfo { /// Weights for pallet_membership using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - // Storage: Instance1Membership Members (r:1 w:1) - // Storage: Instance2Collective Proposals (r:1 w:0) - // Storage: Instance2Collective Members (r:0 w:1) - // Storage: Instance2Collective Prime (r:0 w:1) + // Storage: TechnicalMembership Members (r:1 w:1) + // Storage: TechnicalCommittee Proposals (r:1 w:0) + // Storage: TechnicalCommittee Members (r:0 w:1) + // Storage: TechnicalCommittee Prime (r:0 w:1) fn add_member(m: u32, ) -> Weight { - (23_668_000 as Weight) - // Standard Error: 3_000 - .saturating_add((142_000 as Weight).saturating_mul(m as Weight)) + (14_403_000 as Weight) + // Standard Error: 1_000 + .saturating_add((94_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } - // Storage: Instance1Membership Members (r:1 w:1) - // Storage: Instance2Collective Proposals (r:1 w:0) - // Storage: Instance1Membership Prime (r:1 w:0) - // Storage: Instance2Collective Members (r:0 w:1) - // Storage: Instance2Collective Prime (r:0 w:1) + // Storage: TechnicalMembership Members (r:1 w:1) + // Storage: TechnicalCommittee Proposals (r:1 w:0) + // Storage: TechnicalMembership Prime (r:1 w:0) + // Storage: TechnicalCommittee Members (r:0 w:1) + // Storage: TechnicalCommittee Prime (r:0 w:1) fn remove_member(m: u32, ) -> Weight { - (29_149_000 as Weight) + (17_005_000 as Weight) // Standard Error: 0 - .saturating_add((111_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((90_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } - // Storage: Instance1Membership Members (r:1 w:1) - // Storage: Instance2Collective Proposals (r:1 w:0) - // Storage: Instance1Membership Prime (r:1 w:0) - // Storage: Instance2Collective Members (r:0 w:1) - // Storage: Instance2Collective Prime (r:0 w:1) + // Storage: TechnicalMembership Members (r:1 w:1) + // Storage: TechnicalCommittee Proposals (r:1 w:0) + // Storage: TechnicalMembership Prime (r:1 w:0) + // Storage: TechnicalCommittee Members (r:0 w:1) + // Storage: TechnicalCommittee Prime (r:0 w:1) fn swap_member(m: u32, ) -> Weight { - (29_289_000 as Weight) + (17_210_000 as Weight) // Standard Error: 0 - .saturating_add((126_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((98_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } - // Storage: Instance1Membership Members (r:1 w:1) - // Storage: Instance2Collective Proposals (r:1 w:0) - // Storage: Instance1Membership Prime (r:1 w:0) - // Storage: Instance2Collective Members (r:0 w:1) - // Storage: Instance2Collective Prime (r:0 w:1) + // Storage: TechnicalMembership Members (r:1 w:1) + // Storage: TechnicalCommittee Proposals (r:1 w:0) + // Storage: TechnicalMembership Prime (r:1 w:0) + // Storage: TechnicalCommittee Members (r:0 w:1) + // Storage: TechnicalCommittee Prime (r:0 w:1) fn reset_member(m: u32, ) -> Weight { - (30_178_000 as Weight) - // Standard Error: 1_000 - .saturating_add((286_000 as Weight).saturating_mul(m as Weight)) + (17_425_000 as Weight) + // Standard Error: 0 + .saturating_add((194_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } - // Storage: Instance1Membership Members (r:1 w:1) - // Storage: Instance2Collective Proposals (r:1 w:0) - // Storage: Instance1Membership Prime (r:1 w:1) - // Storage: Instance2Collective Members (r:0 w:1) - // Storage: Instance2Collective Prime (r:0 w:1) + // Storage: TechnicalMembership Members (r:1 w:1) + // Storage: TechnicalCommittee Proposals (r:1 w:0) + // Storage: TechnicalMembership Prime (r:1 w:1) + // Storage: TechnicalCommittee Members (r:0 w:1) + // Storage: TechnicalCommittee Prime (r:0 w:1) fn change_key(m: u32, ) -> Weight { - (31_049_000 as Weight) + (17_948_000 as Weight) // Standard Error: 0 - .saturating_add((121_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((95_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } - // Storage: Instance1Membership Members (r:1 w:0) - // Storage: Instance1Membership Prime (r:0 w:1) - // Storage: Instance2Collective Prime (r:0 w:1) + // Storage: TechnicalMembership Members (r:1 w:0) + // Storage: TechnicalMembership Prime (r:0 w:1) + // Storage: TechnicalCommittee Prime (r:0 w:1) fn set_prime(m: u32, ) -> Weight { - (8_006_000 as Weight) + (4_579_000 as Weight) // Standard Error: 0 - .saturating_add((89_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((71_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } - // Storage: Instance1Membership Prime (r:0 w:1) - // Storage: Instance2Collective Prime (r:0 w:1) + // Storage: TechnicalMembership Prime (r:0 w:1) + // Storage: TechnicalCommittee Prime (r:0 w:1) fn clear_prime(m: u32, ) -> Weight { - (3_452_000 as Weight) + (1_481_000 as Weight) // Standard Error: 0 .saturating_add((2_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -138,79 +139,79 @@ impl WeightInfo for SubstrateWeight { // For backwards compatibility and tests impl WeightInfo for () { - // Storage: Instance1Membership Members (r:1 w:1) - // Storage: Instance2Collective Proposals (r:1 w:0) - // Storage: Instance2Collective Members (r:0 w:1) - // Storage: Instance2Collective Prime (r:0 w:1) + // Storage: TechnicalMembership Members (r:1 w:1) + // Storage: TechnicalCommittee Proposals (r:1 w:0) + // Storage: TechnicalCommittee Members (r:0 w:1) + // Storage: TechnicalCommittee Prime (r:0 w:1) fn add_member(m: u32, ) -> Weight { - (23_668_000 as Weight) - // Standard Error: 3_000 - .saturating_add((142_000 as Weight).saturating_mul(m as Weight)) + (14_403_000 as Weight) + // Standard Error: 1_000 + .saturating_add((94_000 as Weight).saturating_mul(m as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } - // Storage: Instance1Membership Members (r:1 w:1) - // Storage: Instance2Collective Proposals (r:1 w:0) - // Storage: Instance1Membership Prime (r:1 w:0) - // Storage: Instance2Collective Members (r:0 w:1) - // Storage: Instance2Collective Prime (r:0 w:1) + // Storage: TechnicalMembership Members (r:1 w:1) + // Storage: TechnicalCommittee Proposals (r:1 w:0) + // Storage: TechnicalMembership Prime (r:1 w:0) + // Storage: TechnicalCommittee Members (r:0 w:1) + // Storage: TechnicalCommittee Prime (r:0 w:1) fn remove_member(m: u32, ) -> Weight { - (29_149_000 as Weight) + (17_005_000 as Weight) // Standard Error: 0 - .saturating_add((111_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((90_000 as Weight).saturating_mul(m as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } - // Storage: Instance1Membership Members (r:1 w:1) - // Storage: Instance2Collective Proposals (r:1 w:0) - // Storage: Instance1Membership Prime (r:1 w:0) - // Storage: Instance2Collective Members (r:0 w:1) - // Storage: Instance2Collective Prime (r:0 w:1) + // Storage: TechnicalMembership Members (r:1 w:1) + // Storage: TechnicalCommittee Proposals (r:1 w:0) + // Storage: TechnicalMembership Prime (r:1 w:0) + // Storage: TechnicalCommittee Members (r:0 w:1) + // Storage: TechnicalCommittee Prime (r:0 w:1) fn swap_member(m: u32, ) -> Weight { - (29_289_000 as Weight) + (17_210_000 as Weight) // Standard Error: 0 - .saturating_add((126_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((98_000 as Weight).saturating_mul(m as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } - // Storage: Instance1Membership Members (r:1 w:1) - // Storage: Instance2Collective Proposals (r:1 w:0) - // Storage: Instance1Membership Prime (r:1 w:0) - // Storage: Instance2Collective Members (r:0 w:1) - // Storage: Instance2Collective Prime (r:0 w:1) + // Storage: TechnicalMembership Members (r:1 w:1) + // Storage: TechnicalCommittee Proposals (r:1 w:0) + // Storage: TechnicalMembership Prime (r:1 w:0) + // Storage: TechnicalCommittee Members (r:0 w:1) + // Storage: TechnicalCommittee Prime (r:0 w:1) fn reset_member(m: u32, ) -> Weight { - (30_178_000 as Weight) - // Standard Error: 1_000 - .saturating_add((286_000 as Weight).saturating_mul(m as Weight)) + (17_425_000 as Weight) + // Standard Error: 0 + .saturating_add((194_000 as Weight).saturating_mul(m as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } - // Storage: Instance1Membership Members (r:1 w:1) - // Storage: Instance2Collective Proposals (r:1 w:0) - // Storage: Instance1Membership Prime (r:1 w:1) - // Storage: Instance2Collective Members (r:0 w:1) - // Storage: Instance2Collective Prime (r:0 w:1) + // Storage: TechnicalMembership Members (r:1 w:1) + // Storage: TechnicalCommittee Proposals (r:1 w:0) + // Storage: TechnicalMembership Prime (r:1 w:1) + // Storage: TechnicalCommittee Members (r:0 w:1) + // Storage: TechnicalCommittee Prime (r:0 w:1) fn change_key(m: u32, ) -> Weight { - (31_049_000 as Weight) + (17_948_000 as Weight) // Standard Error: 0 - .saturating_add((121_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((95_000 as Weight).saturating_mul(m as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } - // Storage: Instance1Membership Members (r:1 w:0) - // Storage: Instance1Membership Prime (r:0 w:1) - // Storage: Instance2Collective Prime (r:0 w:1) + // Storage: TechnicalMembership Members (r:1 w:0) + // Storage: TechnicalMembership Prime (r:0 w:1) + // Storage: TechnicalCommittee Prime (r:0 w:1) fn set_prime(m: u32, ) -> Weight { - (8_006_000 as Weight) + (4_579_000 as Weight) // Standard Error: 0 - .saturating_add((89_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((71_000 as Weight).saturating_mul(m as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } - // Storage: Instance1Membership Prime (r:0 w:1) - // Storage: Instance2Collective Prime (r:0 w:1) + // Storage: TechnicalMembership Prime (r:0 w:1) + // Storage: TechnicalCommittee Prime (r:0 w:1) fn clear_prime(m: u32, ) -> Weight { - (3_452_000 as Weight) + (1_481_000 as Weight) // Standard Error: 0 .saturating_add((2_000 as Weight).saturating_mul(m as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) diff --git a/frame/multisig/src/weights.rs b/frame/multisig/src/weights.rs index eb78a88f1531..5dc40197db55 100644 --- a/frame/multisig/src/weights.rs +++ b/frame/multisig/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. +// Copyright (C) 2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_multisig //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-08-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 +//! DATE: 2022-01-17, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// target/release/substrate +// ./target/lto-fat-cg1/substrate // benchmark // --chain=dev // --steps=50 @@ -33,8 +33,9 @@ // --wasm-execution=compiled // --heap-pages=4096 // --output=./frame/multisig/src/weights.rs -// --template=./.maintain/frame-weight-template.hbs - +// --template=.maintain/frame-weight-template.hbs +// --header=LICENSE-APACHE2 +// --raw #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -61,18 +62,18 @@ pub trait WeightInfo { pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { fn as_multi_threshold_1(z: u32, ) -> Weight { - (19_405_000 as Weight) + (16_904_000 as Weight) // Standard Error: 0 .saturating_add((1_000 as Weight).saturating_mul(z as Weight)) } // Storage: Multisig Multisigs (r:1 w:1) // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) fn as_multi_create(s: u32, z: u32, ) -> Weight { - (54_364_000 as Weight) + (30_172_000 as Weight) // Standard Error: 0 - .saturating_add((163_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((142_000 as Weight).saturating_mul(s as Weight)) // Standard Error: 0 - .saturating_add((2_000 as Weight).saturating_mul(z as Weight)) + .saturating_add((1_000 as Weight).saturating_mul(z as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -80,32 +81,32 @@ impl WeightInfo for SubstrateWeight { // Storage: Multisig Calls (r:1 w:1) // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) fn as_multi_create_store(s: u32, z: u32, ) -> Weight { - (59_545_000 as Weight) - // Standard Error: 0 - .saturating_add((168_000 as Weight).saturating_mul(s as Weight)) + (33_039_000 as Weight) + // Standard Error: 1_000 + .saturating_add((140_000 as Weight).saturating_mul(s as Weight)) // Standard Error: 0 - .saturating_add((3_000 as Weight).saturating_mul(z as Weight)) + .saturating_add((2_000 as Weight).saturating_mul(z as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Multisig Multisigs (r:1 w:1) fn as_multi_approve(s: u32, z: u32, ) -> Weight { - (32_721_000 as Weight) + (20_752_000 as Weight) // Standard Error: 0 - .saturating_add((176_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((133_000 as Weight).saturating_mul(s as Weight)) // Standard Error: 0 - .saturating_add((2_000 as Weight).saturating_mul(z as Weight)) + .saturating_add((1_000 as Weight).saturating_mul(z as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Multisig Multisigs (r:1 w:1) // Storage: Multisig Calls (r:1 w:1) fn as_multi_approve_store(s: u32, z: u32, ) -> Weight { - (56_596_000 as Weight) + (33_198_000 as Weight) // Standard Error: 1_000 - .saturating_add((183_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((135_000 as Weight).saturating_mul(s as Weight)) // Standard Error: 0 - .saturating_add((3_000 as Weight).saturating_mul(z as Weight)) + .saturating_add((2_000 as Weight).saturating_mul(z as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -113,29 +114,29 @@ impl WeightInfo for SubstrateWeight { // Storage: Multisig Calls (r:1 w:1) // Storage: System Account (r:1 w:1) fn as_multi_complete(s: u32, z: u32, ) -> Weight { - (72_391_000 as Weight) + (39_407_000 as Weight) // Standard Error: 1_000 - .saturating_add((268_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((230_000 as Weight).saturating_mul(s as Weight)) // Standard Error: 0 - .saturating_add((4_000 as Weight).saturating_mul(z as Weight)) + .saturating_add((2_000 as Weight).saturating_mul(z as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Multisig Multisigs (r:1 w:1) // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) fn approve_as_multi_create(s: u32, ) -> Weight { - (52_543_000 as Weight) - // Standard Error: 0 - .saturating_add((164_000 as Weight).saturating_mul(s as Weight)) + (28_365_000 as Weight) + // Standard Error: 1_000 + .saturating_add((156_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Multisig Multisigs (r:1 w:1) // Storage: Multisig Calls (r:1 w:0) fn approve_as_multi_approve(s: u32, ) -> Weight { - (30_764_000 as Weight) + (17_960_000 as Weight) // Standard Error: 0 - .saturating_add((180_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((158_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -143,18 +144,18 @@ impl WeightInfo for SubstrateWeight { // Storage: Multisig Calls (r:1 w:1) // Storage: System Account (r:1 w:1) fn approve_as_multi_complete(s: u32, ) -> Weight { - (113_631_000 as Weight) - // Standard Error: 3_000 - .saturating_add((283_000 as Weight).saturating_mul(s as Weight)) + (56_920_000 as Weight) + // Standard Error: 1_000 + .saturating_add((243_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Multisig Multisigs (r:1 w:1) // Storage: Multisig Calls (r:1 w:1) fn cancel_as_multi(s: u32, ) -> Weight { - (86_310_000 as Weight) - // Standard Error: 0 - .saturating_add((166_000 as Weight).saturating_mul(s as Weight)) + (45_336_000 as Weight) + // Standard Error: 1_000 + .saturating_add((155_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -163,18 +164,18 @@ impl WeightInfo for SubstrateWeight { // For backwards compatibility and tests impl WeightInfo for () { fn as_multi_threshold_1(z: u32, ) -> Weight { - (19_405_000 as Weight) + (16_904_000 as Weight) // Standard Error: 0 .saturating_add((1_000 as Weight).saturating_mul(z as Weight)) } // Storage: Multisig Multisigs (r:1 w:1) // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) fn as_multi_create(s: u32, z: u32, ) -> Weight { - (54_364_000 as Weight) + (30_172_000 as Weight) // Standard Error: 0 - .saturating_add((163_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((142_000 as Weight).saturating_mul(s as Weight)) // Standard Error: 0 - .saturating_add((2_000 as Weight).saturating_mul(z as Weight)) + .saturating_add((1_000 as Weight).saturating_mul(z as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -182,32 +183,32 @@ impl WeightInfo for () { // Storage: Multisig Calls (r:1 w:1) // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) fn as_multi_create_store(s: u32, z: u32, ) -> Weight { - (59_545_000 as Weight) - // Standard Error: 0 - .saturating_add((168_000 as Weight).saturating_mul(s as Weight)) + (33_039_000 as Weight) + // Standard Error: 1_000 + .saturating_add((140_000 as Weight).saturating_mul(s as Weight)) // Standard Error: 0 - .saturating_add((3_000 as Weight).saturating_mul(z as Weight)) + .saturating_add((2_000 as Weight).saturating_mul(z as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Multisig Multisigs (r:1 w:1) fn as_multi_approve(s: u32, z: u32, ) -> Weight { - (32_721_000 as Weight) + (20_752_000 as Weight) // Standard Error: 0 - .saturating_add((176_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((133_000 as Weight).saturating_mul(s as Weight)) // Standard Error: 0 - .saturating_add((2_000 as Weight).saturating_mul(z as Weight)) + .saturating_add((1_000 as Weight).saturating_mul(z as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Multisig Multisigs (r:1 w:1) // Storage: Multisig Calls (r:1 w:1) fn as_multi_approve_store(s: u32, z: u32, ) -> Weight { - (56_596_000 as Weight) + (33_198_000 as Weight) // Standard Error: 1_000 - .saturating_add((183_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((135_000 as Weight).saturating_mul(s as Weight)) // Standard Error: 0 - .saturating_add((3_000 as Weight).saturating_mul(z as Weight)) + .saturating_add((2_000 as Weight).saturating_mul(z as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -215,29 +216,29 @@ impl WeightInfo for () { // Storage: Multisig Calls (r:1 w:1) // Storage: System Account (r:1 w:1) fn as_multi_complete(s: u32, z: u32, ) -> Weight { - (72_391_000 as Weight) + (39_407_000 as Weight) // Standard Error: 1_000 - .saturating_add((268_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((230_000 as Weight).saturating_mul(s as Weight)) // Standard Error: 0 - .saturating_add((4_000 as Weight).saturating_mul(z as Weight)) + .saturating_add((2_000 as Weight).saturating_mul(z as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } // Storage: Multisig Multisigs (r:1 w:1) // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) fn approve_as_multi_create(s: u32, ) -> Weight { - (52_543_000 as Weight) - // Standard Error: 0 - .saturating_add((164_000 as Weight).saturating_mul(s as Weight)) + (28_365_000 as Weight) + // Standard Error: 1_000 + .saturating_add((156_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Multisig Multisigs (r:1 w:1) // Storage: Multisig Calls (r:1 w:0) fn approve_as_multi_approve(s: u32, ) -> Weight { - (30_764_000 as Weight) + (17_960_000 as Weight) // Standard Error: 0 - .saturating_add((180_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((158_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -245,18 +246,18 @@ impl WeightInfo for () { // Storage: Multisig Calls (r:1 w:1) // Storage: System Account (r:1 w:1) fn approve_as_multi_complete(s: u32, ) -> Weight { - (113_631_000 as Weight) - // Standard Error: 3_000 - .saturating_add((283_000 as Weight).saturating_mul(s as Weight)) + (56_920_000 as Weight) + // Standard Error: 1_000 + .saturating_add((243_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } // Storage: Multisig Multisigs (r:1 w:1) // Storage: Multisig Calls (r:1 w:1) fn cancel_as_multi(s: u32, ) -> Weight { - (86_310_000 as Weight) - // Standard Error: 0 - .saturating_add((166_000 as Weight).saturating_mul(s as Weight)) + (45_336_000 as Weight) + // Standard Error: 1_000 + .saturating_add((155_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } diff --git a/frame/preimage/src/weights.rs b/frame/preimage/src/weights.rs index fab5cdfb6736..b0f22a49297b 100644 --- a/frame/preimage/src/weights.rs +++ b/frame/preimage/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. +// Copyright (C) 2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_preimage //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-12-10, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 +//! DATE: 2022-01-17, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// target/release/substrate +// ./target/lto-fat-cg1/substrate // benchmark // --chain=dev // --steps=50 @@ -33,7 +33,9 @@ // --wasm-execution=compiled // --heap-pages=4096 // --output=./frame/preimage/src/weights.rs -// --template=./.maintain/frame-weight-template.hbs +// --template=.maintain/frame-weight-template.hbs +// --header=LICENSE-APACHE2 +// --raw #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -91,58 +93,58 @@ impl WeightInfo for SubstrateWeight { // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:0 w:1) fn unnote_preimage() -> Weight { - (60_560_000 as Weight) + (38_155_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:0 w:1) fn unnote_no_deposit_preimage() -> Weight { - (37_575_000 as Weight) + (24_132_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Preimage StatusFor (r:1 w:1) fn request_preimage() -> Weight { - (56_868_000 as Weight) + (36_703_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Preimage StatusFor (r:1 w:1) fn request_no_deposit_preimage() -> Weight { - (37_058_000 as Weight) + (23_056_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Preimage StatusFor (r:1 w:1) fn request_unnoted_preimage() -> Weight { - (21_500_000 as Weight) + (12_937_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Preimage StatusFor (r:1 w:1) fn request_requested_preimage() -> Weight { - (7_798_000 as Weight) + (4_460_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:0 w:1) fn unrequest_preimage() -> Weight { - (37_771_000 as Weight) + (23_761_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:0 w:1) fn unrequest_unnoted_preimage() -> Weight { - (22_913_000 as Weight) + (13_829_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Preimage StatusFor (r:1 w:1) fn unrequest_multi_referenced_preimage() -> Weight { - (7_608_000 as Weight) + (4_595_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -180,58 +182,58 @@ impl WeightInfo for () { // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:0 w:1) fn unnote_preimage() -> Weight { - (60_560_000 as Weight) + (38_155_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:0 w:1) fn unnote_no_deposit_preimage() -> Weight { - (37_575_000 as Weight) + (24_132_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Preimage StatusFor (r:1 w:1) fn request_preimage() -> Weight { - (56_868_000 as Weight) + (36_703_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Preimage StatusFor (r:1 w:1) fn request_no_deposit_preimage() -> Weight { - (37_058_000 as Weight) + (23_056_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Preimage StatusFor (r:1 w:1) fn request_unnoted_preimage() -> Weight { - (21_500_000 as Weight) + (12_937_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Preimage StatusFor (r:1 w:1) fn request_requested_preimage() -> Weight { - (7_798_000 as Weight) + (4_460_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:0 w:1) fn unrequest_preimage() -> Weight { - (37_771_000 as Weight) + (23_761_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:0 w:1) fn unrequest_unnoted_preimage() -> Weight { - (22_913_000 as Weight) + (13_829_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Preimage StatusFor (r:1 w:1) fn unrequest_multi_referenced_preimage() -> Weight { - (7_608_000 as Weight) + (4_595_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } diff --git a/frame/proxy/src/weights.rs b/frame/proxy/src/weights.rs index bde4fd761179..4628ada8d3c8 100644 --- a/frame/proxy/src/weights.rs +++ b/frame/proxy/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. +// Copyright (C) 2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_proxy //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-08-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 +//! DATE: 2022-01-17, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// target/release/substrate +// ./target/lto-fat-cg1/substrate // benchmark // --chain=dev // --steps=50 @@ -33,8 +33,9 @@ // --wasm-execution=compiled // --heap-pages=4096 // --output=./frame/proxy/src/weights.rs -// --template=./.maintain/frame-weight-template.hbs - +// --template=.maintain/frame-weight-template.hbs +// --header=LICENSE-APACHE2 +// --raw #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -62,38 +63,42 @@ pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { // Storage: Proxy Proxies (r:1 w:0) fn proxy(p: u32, ) -> Weight { - (23_213_000 as Weight) + (13_623_000 as Weight) // Standard Error: 2_000 - .saturating_add((153_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((121_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) } // Storage: Proxy Proxies (r:1 w:0) // Storage: Proxy Announcements (r:1 w:1) // Storage: System Account (r:1 w:1) fn proxy_announced(a: u32, p: u32, ) -> Weight { - (53_286_000 as Weight) + (29_560_000 as Weight) // Standard Error: 2_000 - .saturating_add((549_000 as Weight).saturating_mul(a as Weight)) + .saturating_add((259_000 as Weight).saturating_mul(a as Weight)) // Standard Error: 2_000 - .saturating_add((138_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((121_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Proxy Announcements (r:1 w:1) // Storage: System Account (r:1 w:1) - fn remove_announcement(a: u32, _p: u32, ) -> Weight { - (36_864_000 as Weight) - // Standard Error: 2_000 - .saturating_add((550_000 as Weight).saturating_mul(a as Weight)) + fn remove_announcement(a: u32, p: u32, ) -> Weight { + (21_004_000 as Weight) + // Standard Error: 1_000 + .saturating_add((266_000 as Weight).saturating_mul(a as Weight)) + // Standard Error: 1_000 + .saturating_add((13_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Proxy Announcements (r:1 w:1) // Storage: System Account (r:1 w:1) - fn reject_announcement(a: u32, _p: u32, ) -> Weight { - (36_755_000 as Weight) + fn reject_announcement(a: u32, p: u32, ) -> Weight { + (20_992_000 as Weight) // Standard Error: 1_000 - .saturating_add((550_000 as Weight).saturating_mul(a as Weight)) + .saturating_add((266_000 as Weight).saturating_mul(a as Weight)) + // Standard Error: 1_000 + .saturating_add((14_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -101,52 +106,52 @@ impl WeightInfo for SubstrateWeight { // Storage: Proxy Announcements (r:1 w:1) // Storage: System Account (r:1 w:1) fn announce(a: u32, p: u32, ) -> Weight { - (50_765_000 as Weight) + (28_118_000 as Weight) // Standard Error: 2_000 - .saturating_add((547_000 as Weight).saturating_mul(a as Weight)) + .saturating_add((250_000 as Weight).saturating_mul(a as Weight)) // Standard Error: 2_000 - .saturating_add((141_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((118_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Proxy Proxies (r:1 w:1) fn add_proxy(p: u32, ) -> Weight { - (35_556_000 as Weight) - // Standard Error: 3_000 - .saturating_add((211_000 as Weight).saturating_mul(p as Weight)) + (23_077_000 as Weight) + // Standard Error: 2_000 + .saturating_add((159_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Proxy Proxies (r:1 w:1) fn remove_proxy(p: u32, ) -> Weight { - (35_284_000 as Weight) - // Standard Error: 3_000 - .saturating_add((229_000 as Weight).saturating_mul(p as Weight)) + (19_919_000 as Weight) + // Standard Error: 2_000 + .saturating_add((155_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Proxy Proxies (r:1 w:1) fn remove_proxies(p: u32, ) -> Weight { - (34_449_000 as Weight) + (19_625_000 as Weight) // Standard Error: 2_000 - .saturating_add((146_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((120_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) // Storage: Proxy Proxies (r:1 w:1) fn anonymous(p: u32, ) -> Weight { - (49_149_000 as Weight) + (26_066_000 as Weight) // Standard Error: 2_000 - .saturating_add((15_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((37_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Proxy Proxies (r:1 w:1) fn kill_anonymous(p: u32, ) -> Weight { - (36_399_000 as Weight) + (21_294_000 as Weight) // Standard Error: 2_000 - .saturating_add((152_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((112_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -156,38 +161,42 @@ impl WeightInfo for SubstrateWeight { impl WeightInfo for () { // Storage: Proxy Proxies (r:1 w:0) fn proxy(p: u32, ) -> Weight { - (23_213_000 as Weight) + (13_623_000 as Weight) // Standard Error: 2_000 - .saturating_add((153_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((121_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) } // Storage: Proxy Proxies (r:1 w:0) // Storage: Proxy Announcements (r:1 w:1) // Storage: System Account (r:1 w:1) fn proxy_announced(a: u32, p: u32, ) -> Weight { - (53_286_000 as Weight) + (29_560_000 as Weight) // Standard Error: 2_000 - .saturating_add((549_000 as Weight).saturating_mul(a as Weight)) + .saturating_add((259_000 as Weight).saturating_mul(a as Weight)) // Standard Error: 2_000 - .saturating_add((138_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((121_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Proxy Announcements (r:1 w:1) // Storage: System Account (r:1 w:1) - fn remove_announcement(a: u32, _p: u32, ) -> Weight { - (36_864_000 as Weight) - // Standard Error: 2_000 - .saturating_add((550_000 as Weight).saturating_mul(a as Weight)) + fn remove_announcement(a: u32, p: u32, ) -> Weight { + (21_004_000 as Weight) + // Standard Error: 1_000 + .saturating_add((266_000 as Weight).saturating_mul(a as Weight)) + // Standard Error: 1_000 + .saturating_add((13_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Proxy Announcements (r:1 w:1) // Storage: System Account (r:1 w:1) - fn reject_announcement(a: u32, _p: u32, ) -> Weight { - (36_755_000 as Weight) + fn reject_announcement(a: u32, p: u32, ) -> Weight { + (20_992_000 as Weight) // Standard Error: 1_000 - .saturating_add((550_000 as Weight).saturating_mul(a as Weight)) + .saturating_add((266_000 as Weight).saturating_mul(a as Weight)) + // Standard Error: 1_000 + .saturating_add((14_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -195,52 +204,52 @@ impl WeightInfo for () { // Storage: Proxy Announcements (r:1 w:1) // Storage: System Account (r:1 w:1) fn announce(a: u32, p: u32, ) -> Weight { - (50_765_000 as Weight) + (28_118_000 as Weight) // Standard Error: 2_000 - .saturating_add((547_000 as Weight).saturating_mul(a as Weight)) + .saturating_add((250_000 as Weight).saturating_mul(a as Weight)) // Standard Error: 2_000 - .saturating_add((141_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((118_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Proxy Proxies (r:1 w:1) fn add_proxy(p: u32, ) -> Weight { - (35_556_000 as Weight) - // Standard Error: 3_000 - .saturating_add((211_000 as Weight).saturating_mul(p as Weight)) + (23_077_000 as Weight) + // Standard Error: 2_000 + .saturating_add((159_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Proxy Proxies (r:1 w:1) fn remove_proxy(p: u32, ) -> Weight { - (35_284_000 as Weight) - // Standard Error: 3_000 - .saturating_add((229_000 as Weight).saturating_mul(p as Weight)) + (19_919_000 as Weight) + // Standard Error: 2_000 + .saturating_add((155_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Proxy Proxies (r:1 w:1) fn remove_proxies(p: u32, ) -> Weight { - (34_449_000 as Weight) + (19_625_000 as Weight) // Standard Error: 2_000 - .saturating_add((146_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((120_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) // Storage: Proxy Proxies (r:1 w:1) fn anonymous(p: u32, ) -> Weight { - (49_149_000 as Weight) + (26_066_000 as Weight) // Standard Error: 2_000 - .saturating_add((15_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((37_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Proxy Proxies (r:1 w:1) fn kill_anonymous(p: u32, ) -> Weight { - (36_399_000 as Weight) + (21_294_000 as Weight) // Standard Error: 2_000 - .saturating_add((152_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((112_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } diff --git a/frame/scheduler/src/weights.rs b/frame/scheduler/src/weights.rs index b8209c6031c8..281b25977cf4 100644 --- a/frame/scheduler/src/weights.rs +++ b/frame/scheduler/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. +// Copyright (C) 2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_scheduler //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-12-10, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 +//! DATE: 2022-01-17, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// target/release/substrate +// ./target/lto-fat-cg1/substrate // benchmark // --chain=dev // --steps=50 @@ -33,7 +33,9 @@ // --wasm-execution=compiled // --heap-pages=4096 // --output=./frame/scheduler/src/weights.rs -// --template=./.maintain/frame-weight-template.hbs +// --template=.maintain/frame-weight-template.hbs +// --header=LICENSE-APACHE2 +// --raw #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -68,9 +70,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Preimage StatusFor (r:1 w:1) // Storage: Scheduler Lookup (r:0 w:1) fn on_initialize_periodic_named_resolved(s: u32, ) -> Weight { - (8_183_000 as Weight) - // Standard Error: 36_000 - .saturating_add((34_670_000 as Weight).saturating_mul(s as Weight)) + (10_798_000 as Weight) + // Standard Error: 13_000 + .saturating_add((17_708_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(s as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -81,9 +83,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Preimage StatusFor (r:1 w:1) // Storage: Scheduler Lookup (r:0 w:1) fn on_initialize_named_resolved(s: u32, ) -> Weight { - (11_520_000 as Weight) - // Standard Error: 30_000 - .saturating_add((26_386_000 as Weight).saturating_mul(s as Weight)) + (8_722_000 as Weight) + // Standard Error: 10_000 + .saturating_add((13_706_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(s as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -93,9 +95,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Preimage PreimageFor (r:1 w:1) // Storage: Preimage StatusFor (r:1 w:1) fn on_initialize_periodic_resolved(s: u32, ) -> Weight { - (8_222_000 as Weight) - // Standard Error: 33_000 - .saturating_add((28_925_000 as Weight).saturating_mul(s as Weight)) + (9_414_000 as Weight) + // Standard Error: 9_000 + .saturating_add((15_176_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(s as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -105,9 +107,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Preimage PreimageFor (r:1 w:1) // Storage: Preimage StatusFor (r:1 w:1) fn on_initialize_resolved(s: u32, ) -> Weight { - (11_610_000 as Weight) - // Standard Error: 26_000 - .saturating_add((23_857_000 as Weight).saturating_mul(s as Weight)) + (9_572_000 as Weight) + // Standard Error: 12_000 + .saturating_add((12_505_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(s as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -117,9 +119,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Preimage PreimageFor (r:1 w:0) // Storage: Scheduler Lookup (r:0 w:1) fn on_initialize_named_aborted(s: u32, ) -> Weight { - (11_067_000 as Weight) - // Standard Error: 15_000 - .saturating_add((11_728_000 as Weight).saturating_mul(s as Weight)) + (6_900_000 as Weight) + // Standard Error: 4_000 + .saturating_add((5_486_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -128,9 +130,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Scheduler Agenda (r:2 w:2) // Storage: Preimage PreimageFor (r:1 w:0) fn on_initialize_aborted(s: u32, ) -> Weight { - (13_045_000 as Weight) - // Standard Error: 5_000 - .saturating_add((6_378_000 as Weight).saturating_mul(s as Weight)) + (8_346_000 as Weight) + // Standard Error: 3_000 + .saturating_add((3_079_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -138,9 +140,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Scheduler Agenda (r:2 w:2) // Storage: Scheduler Lookup (r:0 w:1) fn on_initialize_periodic_named(s: u32, ) -> Weight { - (13_496_000 as Weight) - // Standard Error: 27_000 - .saturating_add((17_932_000 as Weight).saturating_mul(s as Weight)) + (13_462_000 as Weight) + // Standard Error: 5_000 + .saturating_add((8_230_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -148,9 +150,9 @@ impl WeightInfo for SubstrateWeight { } // Storage: Scheduler Agenda (r:2 w:2) fn on_initialize_periodic(s: u32, ) -> Weight { - (17_074_000 as Weight) - // Standard Error: 16_000 - .saturating_add((11_982_000 as Weight).saturating_mul(s as Weight)) + (13_046_000 as Weight) + // Standard Error: 4_000 + .saturating_add((5_782_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -159,53 +161,53 @@ impl WeightInfo for SubstrateWeight { // Storage: Scheduler Agenda (r:1 w:1) // Storage: Scheduler Lookup (r:0 w:1) fn on_initialize_named(s: u32, ) -> Weight { - (18_730_000 as Weight) - // Standard Error: 10_000 - .saturating_add((9_909_000 as Weight).saturating_mul(s as Weight)) + (13_481_000 as Weight) + // Standard Error: 3_000 + .saturating_add((4_385_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) } // Storage: Scheduler Agenda (r:1 w:1) fn on_initialize(s: u32, ) -> Weight { - (17_844_000 as Weight) - // Standard Error: 9_000 - .saturating_add((7_719_000 as Weight).saturating_mul(s as Weight)) + (13_081_000 as Weight) + // Standard Error: 4_000 + .saturating_add((3_434_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Scheduler Agenda (r:1 w:1) fn schedule(s: u32, ) -> Weight { - (23_361_000 as Weight) + (13_863_000 as Weight) // Standard Error: 1_000 - .saturating_add((82_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((87_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Scheduler Agenda (r:1 w:1) // Storage: Scheduler Lookup (r:0 w:1) fn cancel(s: u32, ) -> Weight { - (22_359_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_219_000 as Weight).saturating_mul(s as Weight)) + (13_695_000 as Weight) + // Standard Error: 1_000 + .saturating_add((594_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Scheduler Lookup (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) fn schedule_named(s: u32, ) -> Weight { - (28_499_000 as Weight) + (16_506_000 as Weight) // Standard Error: 1_000 - .saturating_add((98_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((99_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Scheduler Lookup (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) fn cancel_named(s: u32, ) -> Weight { - (24_995_000 as Weight) + (15_685_000 as Weight) // Standard Error: 2_000 - .saturating_add((1_223_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((604_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -218,9 +220,9 @@ impl WeightInfo for () { // Storage: Preimage StatusFor (r:1 w:1) // Storage: Scheduler Lookup (r:0 w:1) fn on_initialize_periodic_named_resolved(s: u32, ) -> Weight { - (8_183_000 as Weight) - // Standard Error: 36_000 - .saturating_add((34_670_000 as Weight).saturating_mul(s as Weight)) + (10_798_000 as Weight) + // Standard Error: 13_000 + .saturating_add((17_708_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(s as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -231,9 +233,9 @@ impl WeightInfo for () { // Storage: Preimage StatusFor (r:1 w:1) // Storage: Scheduler Lookup (r:0 w:1) fn on_initialize_named_resolved(s: u32, ) -> Weight { - (11_520_000 as Weight) - // Standard Error: 30_000 - .saturating_add((26_386_000 as Weight).saturating_mul(s as Weight)) + (8_722_000 as Weight) + // Standard Error: 10_000 + .saturating_add((13_706_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(s as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -243,9 +245,9 @@ impl WeightInfo for () { // Storage: Preimage PreimageFor (r:1 w:1) // Storage: Preimage StatusFor (r:1 w:1) fn on_initialize_periodic_resolved(s: u32, ) -> Weight { - (8_222_000 as Weight) - // Standard Error: 33_000 - .saturating_add((28_925_000 as Weight).saturating_mul(s as Weight)) + (9_414_000 as Weight) + // Standard Error: 9_000 + .saturating_add((15_176_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(s as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -255,9 +257,9 @@ impl WeightInfo for () { // Storage: Preimage PreimageFor (r:1 w:1) // Storage: Preimage StatusFor (r:1 w:1) fn on_initialize_resolved(s: u32, ) -> Weight { - (11_610_000 as Weight) - // Standard Error: 26_000 - .saturating_add((23_857_000 as Weight).saturating_mul(s as Weight)) + (9_572_000 as Weight) + // Standard Error: 12_000 + .saturating_add((12_505_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(s as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -267,9 +269,9 @@ impl WeightInfo for () { // Storage: Preimage PreimageFor (r:1 w:0) // Storage: Scheduler Lookup (r:0 w:1) fn on_initialize_named_aborted(s: u32, ) -> Weight { - (11_067_000 as Weight) - // Standard Error: 15_000 - .saturating_add((11_728_000 as Weight).saturating_mul(s as Weight)) + (6_900_000 as Weight) + // Standard Error: 4_000 + .saturating_add((5_486_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) @@ -278,9 +280,9 @@ impl WeightInfo for () { // Storage: Scheduler Agenda (r:2 w:2) // Storage: Preimage PreimageFor (r:1 w:0) fn on_initialize_aborted(s: u32, ) -> Weight { - (13_045_000 as Weight) - // Standard Error: 5_000 - .saturating_add((6_378_000 as Weight).saturating_mul(s as Weight)) + (8_346_000 as Weight) + // Standard Error: 3_000 + .saturating_add((3_079_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) @@ -288,9 +290,9 @@ impl WeightInfo for () { // Storage: Scheduler Agenda (r:2 w:2) // Storage: Scheduler Lookup (r:0 w:1) fn on_initialize_periodic_named(s: u32, ) -> Weight { - (13_496_000 as Weight) - // Standard Error: 27_000 - .saturating_add((17_932_000 as Weight).saturating_mul(s as Weight)) + (13_462_000 as Weight) + // Standard Error: 5_000 + .saturating_add((8_230_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -298,9 +300,9 @@ impl WeightInfo for () { } // Storage: Scheduler Agenda (r:2 w:2) fn on_initialize_periodic(s: u32, ) -> Weight { - (17_074_000 as Weight) - // Standard Error: 16_000 - .saturating_add((11_982_000 as Weight).saturating_mul(s as Weight)) + (13_046_000 as Weight) + // Standard Error: 4_000 + .saturating_add((5_782_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -309,53 +311,53 @@ impl WeightInfo for () { // Storage: Scheduler Agenda (r:1 w:1) // Storage: Scheduler Lookup (r:0 w:1) fn on_initialize_named(s: u32, ) -> Weight { - (18_730_000 as Weight) - // Standard Error: 10_000 - .saturating_add((9_909_000 as Weight).saturating_mul(s as Weight)) + (13_481_000 as Weight) + // Standard Error: 3_000 + .saturating_add((4_385_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) } // Storage: Scheduler Agenda (r:1 w:1) fn on_initialize(s: u32, ) -> Weight { - (17_844_000 as Weight) - // Standard Error: 9_000 - .saturating_add((7_719_000 as Weight).saturating_mul(s as Weight)) + (13_081_000 as Weight) + // Standard Error: 4_000 + .saturating_add((3_434_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Scheduler Agenda (r:1 w:1) fn schedule(s: u32, ) -> Weight { - (23_361_000 as Weight) + (13_863_000 as Weight) // Standard Error: 1_000 - .saturating_add((82_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((87_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Scheduler Agenda (r:1 w:1) // Storage: Scheduler Lookup (r:0 w:1) fn cancel(s: u32, ) -> Weight { - (22_359_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_219_000 as Weight).saturating_mul(s as Weight)) + (13_695_000 as Weight) + // Standard Error: 1_000 + .saturating_add((594_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Scheduler Lookup (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) fn schedule_named(s: u32, ) -> Weight { - (28_499_000 as Weight) + (16_506_000 as Weight) // Standard Error: 1_000 - .saturating_add((98_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((99_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Scheduler Lookup (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) fn cancel_named(s: u32, ) -> Weight { - (24_995_000 as Weight) + (15_685_000 as Weight) // Standard Error: 2_000 - .saturating_add((1_223_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((604_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } diff --git a/frame/session/src/weights.rs b/frame/session/src/weights.rs index 35c9cc7230fb..2cf5cd9c4192 100644 --- a/frame/session/src/weights.rs +++ b/frame/session/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. +// Copyright (C) 2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_session //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-08-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 +//! DATE: 2022-01-17, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// target/release/substrate +// ./target/lto-fat-cg1/substrate // benchmark // --chain=dev // --steps=50 @@ -33,8 +33,9 @@ // --wasm-execution=compiled // --heap-pages=4096 // --output=./frame/session/src/weights.rs -// --template=./.maintain/frame-weight-template.hbs - +// --template=.maintain/frame-weight-template.hbs +// --header=LICENSE-APACHE2 +// --raw #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -56,7 +57,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Session NextKeys (r:1 w:1) // Storage: Session KeyOwner (r:4 w:4) fn set_keys() -> Weight { - (64_427_000 as Weight) + (42_449_000 as Weight) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } @@ -64,7 +65,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Session NextKeys (r:1 w:1) // Storage: Session KeyOwner (r:0 w:4) fn purge_keys() -> Weight { - (42_497_000 as Weight) + (32_778_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } @@ -76,7 +77,7 @@ impl WeightInfo for () { // Storage: Session NextKeys (r:1 w:1) // Storage: Session KeyOwner (r:4 w:4) fn set_keys() -> Weight { - (64_427_000 as Weight) + (42_449_000 as Weight) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } @@ -84,7 +85,7 @@ impl WeightInfo for () { // Storage: Session NextKeys (r:1 w:1) // Storage: Session KeyOwner (r:0 w:4) fn purge_keys() -> Weight { - (42_497_000 as Weight) + (32_778_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } diff --git a/frame/staking/src/weights.rs b/frame/staking/src/weights.rs index 4f5af6fcd5f8..7721fbbd2371 100644 --- a/frame/staking/src/weights.rs +++ b/frame/staking/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. +// Copyright (C) 2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_staking //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-11-29, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 +//! DATE: 2022-01-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// target/release/substrate +// ./target/lto-fat-cg1/substrate // benchmark // --chain=dev // --steps=50 @@ -33,7 +33,9 @@ // --wasm-execution=compiled // --heap-pages=4096 // --output=./frame/staking/src/weights.rs -// --template=./.maintain/frame-weight-template.hbs +// --template=.maintain/frame-weight-template.hbs +// --header=LICENSE-APACHE2 +// --raw #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -84,7 +86,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Balances Locks (r:1 w:1) // Storage: Staking Payee (r:0 w:1) fn bond() -> Weight { - (63_660_000 as Weight) + (38_457_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } @@ -94,7 +96,7 @@ impl WeightInfo for SubstrateWeight { // Storage: BagsList ListNodes (r:3 w:3) // Storage: BagsList ListBags (r:2 w:2) fn bond_extra() -> Weight { - (103_672_000 as Weight) + (65_678_000 as Weight) .saturating_add(T::DbWeight::get().reads(8 as Weight)) .saturating_add(T::DbWeight::get().writes(7 as Weight)) } @@ -108,7 +110,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking Bonded (r:1 w:0) // Storage: BagsList ListBags (r:2 w:2) fn unbond() -> Weight { - (110_884_000 as Weight) + (71_544_000 as Weight) .saturating_add(T::DbWeight::get().reads(12 as Weight)) .saturating_add(T::DbWeight::get().writes(8 as Weight)) } @@ -117,9 +119,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn withdraw_unbonded_update(s: u32, ) -> Weight { - (46_379_000 as Weight) + (30_127_000 as Weight) // Standard Error: 0 - .saturating_add((55_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((59_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -137,7 +139,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Balances Locks (r:1 w:1) // Storage: Staking Payee (r:0 w:1) fn withdraw_unbonded_kill(_s: u32, ) -> Weight { - (91_303_000 as Weight) + (59_131_000 as Weight) .saturating_add(T::DbWeight::get().reads(13 as Weight)) .saturating_add(T::DbWeight::get().writes(11 as Weight)) } @@ -153,16 +155,16 @@ impl WeightInfo for SubstrateWeight { // Storage: BagsList CounterForListNodes (r:1 w:1) // Storage: Staking CounterForValidators (r:1 w:1) fn validate() -> Weight { - (66_587_000 as Weight) + (45_519_000 as Weight) .saturating_add(T::DbWeight::get().reads(12 as Weight)) .saturating_add(T::DbWeight::get().writes(8 as Weight)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking Nominators (r:1 w:1) fn kick(k: u32, ) -> Weight { - (21_153_000 as Weight) - // Standard Error: 16_000 - .saturating_add((13_502_000 as Weight).saturating_mul(k as Weight)) + (16_645_000 as Weight) + // Standard Error: 12_000 + .saturating_add((8_194_000 as Weight).saturating_mul(k as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(k as Weight))) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) @@ -173,15 +175,15 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking MaxNominatorsCount (r:1 w:0) // Storage: Staking Validators (r:2 w:0) // Storage: Staking CurrentEra (r:1 w:0) - // Storage: Staking CounterForNominators (r:1 w:1) // Storage: Staking Bonded (r:1 w:0) // Storage: BagsList ListNodes (r:2 w:2) // Storage: BagsList ListBags (r:1 w:1) // Storage: BagsList CounterForListNodes (r:1 w:1) + // Storage: Staking CounterForNominators (r:1 w:1) fn nominate(n: u32, ) -> Weight { - (75_456_000 as Weight) + (50_227_000 as Weight) // Standard Error: 12_000 - .saturating_add((5_051_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((3_546_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(12 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(n as Weight))) .saturating_add(T::DbWeight::get().writes(6 as Weight)) @@ -194,49 +196,49 @@ impl WeightInfo for SubstrateWeight { // Storage: BagsList ListBags (r:1 w:1) // Storage: BagsList CounterForListNodes (r:1 w:1) fn chill() -> Weight { - (65_332_000 as Weight) + (44_294_000 as Weight) .saturating_add(T::DbWeight::get().reads(8 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking Payee (r:0 w:1) fn set_payee() -> Weight { - (11_757_000 as Weight) + (7_556_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Staking Bonded (r:1 w:1) // Storage: Staking Ledger (r:2 w:2) fn set_controller() -> Weight { - (24_252_000 as Weight) + (15_826_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Staking ValidatorCount (r:0 w:1) fn set_validator_count() -> Weight { - (2_252_000 as Weight) + (1_141_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Staking ForceEra (r:0 w:1) fn force_no_eras() -> Weight { - (2_431_000 as Weight) + (1_152_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Staking ForceEra (r:0 w:1) fn force_new_era() -> Weight { - (2_397_000 as Weight) + (1_169_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Staking ForceEra (r:0 w:1) fn force_new_era_always() -> Weight { - (2_423_000 as Weight) + (1_134_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Staking Invulnerables (r:0 w:1) fn set_invulnerables(v: u32, ) -> Weight { - (2_876_000 as Weight) + (1_641_000 as Weight) // Standard Error: 0 - .saturating_add((53_000 as Weight).saturating_mul(v as Weight)) + .saturating_add((52_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Staking Bonded (r:1 w:1) @@ -253,18 +255,18 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking Payee (r:0 w:1) // Storage: Staking SpanSlash (r:0 w:2) fn force_unstake(s: u32, ) -> Weight { - (87_540_000 as Weight) + (57_227_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_791_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((817_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(11 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) } // Storage: Staking UnappliedSlashes (r:1 w:1) fn cancel_deferred_slash(s: u32, ) -> Weight { - (2_769_801_000 as Weight) - // Standard Error: 181_000 - .saturating_add((16_225_000 as Weight).saturating_mul(s as Weight)) + (950_241_000 as Weight) + // Standard Error: 56_000 + .saturating_add((4_960_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -279,9 +281,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking Payee (r:2 w:0) // Storage: System Account (r:2 w:2) fn payout_stakers_dead_controller(n: u32, ) -> Weight { - (103_452_000 as Weight) - // Standard Error: 19_000 - .saturating_add((42_909_000 as Weight).saturating_mul(n as Weight)) + (73_561_000 as Weight) + // Standard Error: 13_000 + .saturating_add((24_039_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(10 as Weight)) .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(n as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -299,9 +301,9 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:2 w:2) // Storage: Balances Locks (r:2 w:2) fn payout_stakers_alive_staked(n: u32, ) -> Weight { - (145_995_000 as Weight) - // Standard Error: 27_000 - .saturating_add((55_974_000 as Weight).saturating_mul(n as Weight)) + (105_296_000 as Weight) + // Standard Error: 18_000 + .saturating_add((33_989_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(11 as Weight)) .saturating_add(T::DbWeight::get().reads((5 as Weight).saturating_mul(n as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -314,9 +316,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking Bonded (r:1 w:0) // Storage: BagsList ListBags (r:2 w:2) fn rebond(l: u32, ) -> Weight { - (101_568_000 as Weight) - // Standard Error: 2_000 - .saturating_add((66_000 as Weight).saturating_mul(l as Weight)) + (65_108_000 as Weight) + // Standard Error: 3_000 + .saturating_add((72_000 as Weight).saturating_mul(l as Weight)) .saturating_add(T::DbWeight::get().reads(9 as Weight)) .saturating_add(T::DbWeight::get().writes(8 as Weight)) } @@ -331,8 +333,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking ErasStartSessionIndex (r:0 w:1) fn set_history_depth(e: u32, ) -> Weight { (0 as Weight) - // Standard Error: 69_000 - .saturating_add((29_939_000 as Weight).saturating_mul(e as Weight)) + // Standard Error: 54_000 + .saturating_add((19_731_000 as Weight).saturating_mul(e as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) .saturating_add(T::DbWeight::get().writes((7 as Weight).saturating_mul(e as Weight))) @@ -351,9 +353,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking Payee (r:0 w:1) // Storage: Staking SpanSlash (r:0 w:1) fn reap_stash(s: u32, ) -> Weight { - (96_886_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_790_000 as Weight).saturating_mul(s as Weight)) + (63_115_000 as Weight) + // Standard Error: 0 + .saturating_add((812_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(12 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) @@ -378,10 +380,10 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking ErasStartSessionIndex (r:0 w:1) fn new_era(v: u32, n: u32, ) -> Weight { (0 as Weight) - // Standard Error: 873_000 - .saturating_add((286_141_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 43_000 - .saturating_add((44_712_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 800_000 + .saturating_add((219_877_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 40_000 + .saturating_add((31_701_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(208 as Weight)) .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(v as Weight))) .saturating_add(T::DbWeight::get().reads((4 as Weight).saturating_mul(n as Weight))) @@ -399,10 +401,10 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking Nominators (r:1000 w:0) fn get_npos_voters(v: u32, n: u32, s: u32, ) -> Weight { (0 as Weight) - // Standard Error: 87_000 - .saturating_add((24_049_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 87_000 - .saturating_add((27_514_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 88_000 + .saturating_add((18_183_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 88_000 + .saturating_add((21_345_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(204 as Weight)) .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(v as Weight))) .saturating_add(T::DbWeight::get().reads((4 as Weight).saturating_mul(n as Weight))) @@ -411,8 +413,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking Validators (r:501 w:0) fn get_npos_targets(v: u32, ) -> Weight { (0 as Weight) - // Standard Error: 32_000 - .saturating_add((10_128_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 25_000 + .saturating_add((7_691_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(v as Weight))) } @@ -423,7 +425,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Staking MaxNominatorsCount (r:0 w:1) // Storage: Staking MinNominatorBond (r:0 w:1) fn set_staking_configs() -> Weight { - (6_187_000 as Weight) + (3_324_000 as Weight) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } // Storage: Staking Ledger (r:1 w:0) @@ -437,7 +439,7 @@ impl WeightInfo for SubstrateWeight { // Storage: BagsList ListBags (r:1 w:1) // Storage: BagsList CounterForListNodes (r:1 w:1) fn chill_other() -> Weight { - (78_282_000 as Weight) + (54_254_000 as Weight) .saturating_add(T::DbWeight::get().reads(11 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } @@ -452,7 +454,7 @@ impl WeightInfo for () { // Storage: Balances Locks (r:1 w:1) // Storage: Staking Payee (r:0 w:1) fn bond() -> Weight { - (63_660_000 as Weight) + (38_457_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } @@ -462,7 +464,7 @@ impl WeightInfo for () { // Storage: BagsList ListNodes (r:3 w:3) // Storage: BagsList ListBags (r:2 w:2) fn bond_extra() -> Weight { - (103_672_000 as Weight) + (65_678_000 as Weight) .saturating_add(RocksDbWeight::get().reads(8 as Weight)) .saturating_add(RocksDbWeight::get().writes(7 as Weight)) } @@ -476,7 +478,7 @@ impl WeightInfo for () { // Storage: Staking Bonded (r:1 w:0) // Storage: BagsList ListBags (r:2 w:2) fn unbond() -> Weight { - (110_884_000 as Weight) + (71_544_000 as Weight) .saturating_add(RocksDbWeight::get().reads(12 as Weight)) .saturating_add(RocksDbWeight::get().writes(8 as Weight)) } @@ -485,9 +487,9 @@ impl WeightInfo for () { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn withdraw_unbonded_update(s: u32, ) -> Weight { - (46_379_000 as Weight) + (30_127_000 as Weight) // Standard Error: 0 - .saturating_add((55_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((59_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -505,7 +507,7 @@ impl WeightInfo for () { // Storage: Balances Locks (r:1 w:1) // Storage: Staking Payee (r:0 w:1) fn withdraw_unbonded_kill(_s: u32, ) -> Weight { - (91_303_000 as Weight) + (59_131_000 as Weight) .saturating_add(RocksDbWeight::get().reads(13 as Weight)) .saturating_add(RocksDbWeight::get().writes(11 as Weight)) } @@ -521,16 +523,16 @@ impl WeightInfo for () { // Storage: BagsList CounterForListNodes (r:1 w:1) // Storage: Staking CounterForValidators (r:1 w:1) fn validate() -> Weight { - (66_587_000 as Weight) + (45_519_000 as Weight) .saturating_add(RocksDbWeight::get().reads(12 as Weight)) .saturating_add(RocksDbWeight::get().writes(8 as Weight)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking Nominators (r:1 w:1) fn kick(k: u32, ) -> Weight { - (21_153_000 as Weight) - // Standard Error: 16_000 - .saturating_add((13_502_000 as Weight).saturating_mul(k as Weight)) + (16_645_000 as Weight) + // Standard Error: 12_000 + .saturating_add((8_194_000 as Weight).saturating_mul(k as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(k as Weight))) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) @@ -541,15 +543,15 @@ impl WeightInfo for () { // Storage: Staking MaxNominatorsCount (r:1 w:0) // Storage: Staking Validators (r:2 w:0) // Storage: Staking CurrentEra (r:1 w:0) - // Storage: Staking CounterForNominators (r:1 w:1) // Storage: Staking Bonded (r:1 w:0) // Storage: BagsList ListNodes (r:2 w:2) // Storage: BagsList ListBags (r:1 w:1) // Storage: BagsList CounterForListNodes (r:1 w:1) + // Storage: Staking CounterForNominators (r:1 w:1) fn nominate(n: u32, ) -> Weight { - (75_456_000 as Weight) + (50_227_000 as Weight) // Standard Error: 12_000 - .saturating_add((5_051_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((3_546_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(12 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(n as Weight))) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) @@ -562,49 +564,49 @@ impl WeightInfo for () { // Storage: BagsList ListBags (r:1 w:1) // Storage: BagsList CounterForListNodes (r:1 w:1) fn chill() -> Weight { - (65_332_000 as Weight) + (44_294_000 as Weight) .saturating_add(RocksDbWeight::get().reads(8 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking Payee (r:0 w:1) fn set_payee() -> Weight { - (11_757_000 as Weight) + (7_556_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Staking Bonded (r:1 w:1) // Storage: Staking Ledger (r:2 w:2) fn set_controller() -> Weight { - (24_252_000 as Weight) + (15_826_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } // Storage: Staking ValidatorCount (r:0 w:1) fn set_validator_count() -> Weight { - (2_252_000 as Weight) + (1_141_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Staking ForceEra (r:0 w:1) fn force_no_eras() -> Weight { - (2_431_000 as Weight) + (1_152_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Staking ForceEra (r:0 w:1) fn force_new_era() -> Weight { - (2_397_000 as Weight) + (1_169_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Staking ForceEra (r:0 w:1) fn force_new_era_always() -> Weight { - (2_423_000 as Weight) + (1_134_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Staking Invulnerables (r:0 w:1) fn set_invulnerables(v: u32, ) -> Weight { - (2_876_000 as Weight) + (1_641_000 as Weight) // Standard Error: 0 - .saturating_add((53_000 as Weight).saturating_mul(v as Weight)) + .saturating_add((52_000 as Weight).saturating_mul(v as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Staking Bonded (r:1 w:1) @@ -621,18 +623,18 @@ impl WeightInfo for () { // Storage: Staking Payee (r:0 w:1) // Storage: Staking SpanSlash (r:0 w:2) fn force_unstake(s: u32, ) -> Weight { - (87_540_000 as Weight) + (57_227_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_791_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((817_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(11 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) } // Storage: Staking UnappliedSlashes (r:1 w:1) fn cancel_deferred_slash(s: u32, ) -> Weight { - (2_769_801_000 as Weight) - // Standard Error: 181_000 - .saturating_add((16_225_000 as Weight).saturating_mul(s as Weight)) + (950_241_000 as Weight) + // Standard Error: 56_000 + .saturating_add((4_960_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -647,9 +649,9 @@ impl WeightInfo for () { // Storage: Staking Payee (r:2 w:0) // Storage: System Account (r:2 w:2) fn payout_stakers_dead_controller(n: u32, ) -> Weight { - (103_452_000 as Weight) - // Standard Error: 19_000 - .saturating_add((42_909_000 as Weight).saturating_mul(n as Weight)) + (73_561_000 as Weight) + // Standard Error: 13_000 + .saturating_add((24_039_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(10 as Weight)) .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(n as Weight))) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) @@ -667,9 +669,9 @@ impl WeightInfo for () { // Storage: System Account (r:2 w:2) // Storage: Balances Locks (r:2 w:2) fn payout_stakers_alive_staked(n: u32, ) -> Weight { - (145_995_000 as Weight) - // Standard Error: 27_000 - .saturating_add((55_974_000 as Weight).saturating_mul(n as Weight)) + (105_296_000 as Weight) + // Standard Error: 18_000 + .saturating_add((33_989_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(11 as Weight)) .saturating_add(RocksDbWeight::get().reads((5 as Weight).saturating_mul(n as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -682,9 +684,9 @@ impl WeightInfo for () { // Storage: Staking Bonded (r:1 w:0) // Storage: BagsList ListBags (r:2 w:2) fn rebond(l: u32, ) -> Weight { - (101_568_000 as Weight) - // Standard Error: 2_000 - .saturating_add((66_000 as Weight).saturating_mul(l as Weight)) + (65_108_000 as Weight) + // Standard Error: 3_000 + .saturating_add((72_000 as Weight).saturating_mul(l as Weight)) .saturating_add(RocksDbWeight::get().reads(9 as Weight)) .saturating_add(RocksDbWeight::get().writes(8 as Weight)) } @@ -699,8 +701,8 @@ impl WeightInfo for () { // Storage: Staking ErasStartSessionIndex (r:0 w:1) fn set_history_depth(e: u32, ) -> Weight { (0 as Weight) - // Standard Error: 69_000 - .saturating_add((29_939_000 as Weight).saturating_mul(e as Weight)) + // Standard Error: 54_000 + .saturating_add((19_731_000 as Weight).saturating_mul(e as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) .saturating_add(RocksDbWeight::get().writes((7 as Weight).saturating_mul(e as Weight))) @@ -719,9 +721,9 @@ impl WeightInfo for () { // Storage: Staking Payee (r:0 w:1) // Storage: Staking SpanSlash (r:0 w:1) fn reap_stash(s: u32, ) -> Weight { - (96_886_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_790_000 as Weight).saturating_mul(s as Weight)) + (63_115_000 as Weight) + // Standard Error: 0 + .saturating_add((812_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(12 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) @@ -746,10 +748,10 @@ impl WeightInfo for () { // Storage: Staking ErasStartSessionIndex (r:0 w:1) fn new_era(v: u32, n: u32, ) -> Weight { (0 as Weight) - // Standard Error: 873_000 - .saturating_add((286_141_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 43_000 - .saturating_add((44_712_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 800_000 + .saturating_add((219_877_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 40_000 + .saturating_add((31_701_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(208 as Weight)) .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(v as Weight))) .saturating_add(RocksDbWeight::get().reads((4 as Weight).saturating_mul(n as Weight))) @@ -767,10 +769,10 @@ impl WeightInfo for () { // Storage: Staking Nominators (r:1000 w:0) fn get_npos_voters(v: u32, n: u32, s: u32, ) -> Weight { (0 as Weight) - // Standard Error: 87_000 - .saturating_add((24_049_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 87_000 - .saturating_add((27_514_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 88_000 + .saturating_add((18_183_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 88_000 + .saturating_add((21_345_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(204 as Weight)) .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(v as Weight))) .saturating_add(RocksDbWeight::get().reads((4 as Weight).saturating_mul(n as Weight))) @@ -779,8 +781,8 @@ impl WeightInfo for () { // Storage: Staking Validators (r:501 w:0) fn get_npos_targets(v: u32, ) -> Weight { (0 as Weight) - // Standard Error: 32_000 - .saturating_add((10_128_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 25_000 + .saturating_add((7_691_000 as Weight).saturating_mul(v as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(v as Weight))) } @@ -791,7 +793,7 @@ impl WeightInfo for () { // Storage: Staking MaxNominatorsCount (r:0 w:1) // Storage: Staking MinNominatorBond (r:0 w:1) fn set_staking_configs() -> Weight { - (6_187_000 as Weight) + (3_324_000 as Weight) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } // Storage: Staking Ledger (r:1 w:0) @@ -805,7 +807,7 @@ impl WeightInfo for () { // Storage: BagsList ListBags (r:1 w:1) // Storage: BagsList CounterForListNodes (r:1 w:1) fn chill_other() -> Weight { - (78_282_000 as Weight) + (54_254_000 as Weight) .saturating_add(RocksDbWeight::get().reads(11 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } diff --git a/frame/system/src/weights.rs b/frame/system/src/weights.rs index ff6900032d96..1fc35a41752a 100644 --- a/frame/system/src/weights.rs +++ b/frame/system/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. +// Copyright (C) 2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,11 +18,11 @@ //! Autogenerated weights for frame_system //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-08-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 +//! DATE: 2022-01-19, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// target/release/substrate +// ./target/optimized/substrate // benchmark // --chain=dev // --steps=50 @@ -32,9 +32,10 @@ // --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/system/src/weights.rs -// --template=./.maintain/frame-weight-template.hbs - +// --output=./weights-optimized/frame/system/src//weights.rs +// --template=.maintain/frame-weight-template.hbs +// --header=HEADER-APACHE2 +// --raw #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -56,80 +57,80 @@ pub trait WeightInfo { /// Weights for frame_system using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - fn remark(b: u32, ) -> Weight { - (574_000 as Weight) - // Standard Error: 0 - .saturating_add((1_000 as Weight).saturating_mul(b as Weight)) + fn remark(_b: u32, ) -> Weight { + (0 as Weight) } fn remark_with_event(b: u32, ) -> Weight { (0 as Weight) // Standard Error: 0 - .saturating_add((2_000 as Weight).saturating_mul(b as Weight)) + .saturating_add((1_000 as Weight).saturating_mul(b as Weight)) } + // Storage: System Digest (r:1 w:1) // Storage: unknown [0x3a686561707061676573] (r:0 w:1) fn set_heap_pages() -> Weight { - (1_891_000 as Weight) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + (2_821_000 as Weight) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn set_storage(i: u32, ) -> Weight { (0 as Weight) // Standard Error: 0 - .saturating_add((848_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((385_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(i as Weight))) } // Storage: Skipped Metadata (r:0 w:0) fn kill_storage(i: u32, ) -> Weight { - (308_000 as Weight) + (0 as Weight) // Standard Error: 0 - .saturating_add((559_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((286_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(i as Weight))) } // Storage: Skipped Metadata (r:0 w:0) fn kill_prefix(p: u32, ) -> Weight { - (7_616_000 as Weight) - // Standard Error: 1_000 - .saturating_add((783_000 as Weight).saturating_mul(p as Weight)) + (1_292_000 as Weight) + // Standard Error: 0 + .saturating_add((633_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(p as Weight))) } } // For backwards compatibility and tests impl WeightInfo for () { - fn remark(b: u32, ) -> Weight { - (574_000 as Weight) - // Standard Error: 0 - .saturating_add((1_000 as Weight).saturating_mul(b as Weight)) + fn remark(_b: u32, ) -> Weight { + (0 as Weight) } fn remark_with_event(b: u32, ) -> Weight { (0 as Weight) // Standard Error: 0 - .saturating_add((2_000 as Weight).saturating_mul(b as Weight)) + .saturating_add((1_000 as Weight).saturating_mul(b as Weight)) } + // Storage: System Digest (r:1 w:1) // Storage: unknown [0x3a686561707061676573] (r:0 w:1) fn set_heap_pages() -> Weight { - (1_891_000 as Weight) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + (2_821_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn set_storage(i: u32, ) -> Weight { (0 as Weight) // Standard Error: 0 - .saturating_add((848_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((385_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(i as Weight))) } // Storage: Skipped Metadata (r:0 w:0) fn kill_storage(i: u32, ) -> Weight { - (308_000 as Weight) + (0 as Weight) // Standard Error: 0 - .saturating_add((559_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((286_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(i as Weight))) } // Storage: Skipped Metadata (r:0 w:0) fn kill_prefix(p: u32, ) -> Weight { - (7_616_000 as Weight) - // Standard Error: 1_000 - .saturating_add((783_000 as Weight).saturating_mul(p as Weight)) + (1_292_000 as Weight) + // Standard Error: 0 + .saturating_add((633_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(p as Weight))) } } diff --git a/frame/timestamp/src/weights.rs b/frame/timestamp/src/weights.rs index fb452ebe3595..b0f4b9d30588 100644 --- a/frame/timestamp/src/weights.rs +++ b/frame/timestamp/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. +// Copyright (C) 2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_timestamp //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-08-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 +//! DATE: 2022-01-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// target/release/substrate +// ./target/lto-fat-cg1/substrate // benchmark // --chain=dev // --steps=50 @@ -33,8 +33,9 @@ // --wasm-execution=compiled // --heap-pages=4096 // --output=./frame/timestamp/src/weights.rs -// --template=./.maintain/frame-weight-template.hbs - +// --template=.maintain/frame-weight-template.hbs +// --header=LICENSE-APACHE2 +// --raw #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -55,12 +56,12 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:1) // Storage: Babe CurrentSlot (r:1 w:0) fn set() -> Weight { - (10_391_000 as Weight) + (5_191_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn on_finalize() -> Weight { - (4_843_000 as Weight) + (2_563_000 as Weight) } } @@ -69,11 +70,11 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:1) // Storage: Babe CurrentSlot (r:1 w:0) fn set() -> Weight { - (10_391_000 as Weight) + (5_191_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn on_finalize() -> Weight { - (4_843_000 as Weight) + (2_563_000 as Weight) } } diff --git a/frame/tips/src/weights.rs b/frame/tips/src/weights.rs index 29e85ccad851..154b6a67d854 100644 --- a/frame/tips/src/weights.rs +++ b/frame/tips/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. +// Copyright (C) 2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_tips //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-08-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 +//! DATE: 2022-01-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// target/release/substrate +// ./target/lto-fat-cg1/substrate // benchmark // --chain=dev // --steps=50 @@ -33,8 +33,9 @@ // --wasm-execution=compiled // --heap-pages=4096 // --output=./frame/tips/src/weights.rs -// --template=./.maintain/frame-weight-template.hbs - +// --template=.maintain/frame-weight-template.hbs +// --header=LICENSE-APACHE2 +// --raw #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -56,60 +57,60 @@ pub trait WeightInfo { /// Weights for pallet_tips using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - // Storage: Treasury Reasons (r:1 w:1) - // Storage: Treasury Tips (r:1 w:1) + // Storage: Tips Reasons (r:1 w:1) + // Storage: Tips Tips (r:1 w:1) fn report_awesome(r: u32, ) -> Weight { - (50_921_000 as Weight) + (26_318_000 as Weight) // Standard Error: 0 .saturating_add((2_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } - // Storage: Treasury Tips (r:1 w:1) - // Storage: Treasury Reasons (r:0 w:1) + // Storage: Tips Tips (r:1 w:1) + // Storage: Tips Reasons (r:0 w:1) fn retract_tip() -> Weight { - (46_352_000 as Weight) + (24_688_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Elections Members (r:1 w:0) - // Storage: Treasury Reasons (r:1 w:1) - // Storage: Treasury Tips (r:0 w:1) + // Storage: Tips Reasons (r:1 w:1) + // Storage: Tips Tips (r:0 w:1) fn tip_new(r: u32, t: u32, ) -> Weight { - (33_338_000 as Weight) - // Standard Error: 0 - .saturating_add((2_000 as Weight).saturating_mul(r as Weight)) + (17_395_000 as Weight) // Standard Error: 0 - .saturating_add((115_000 as Weight).saturating_mul(t as Weight)) + .saturating_add((3_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 4_000 + .saturating_add((197_000 as Weight).saturating_mul(t as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Elections Members (r:1 w:0) - // Storage: Treasury Tips (r:1 w:1) + // Storage: Tips Tips (r:1 w:1) fn tip(t: u32, ) -> Weight { - (22_702_000 as Weight) - // Standard Error: 0 - .saturating_add((538_000 as Weight).saturating_mul(t as Weight)) + (10_783_000 as Weight) + // Standard Error: 6_000 + .saturating_add((568_000 as Weight).saturating_mul(t as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - // Storage: Treasury Tips (r:1 w:1) + // Storage: Tips Tips (r:1 w:1) // Storage: Elections Members (r:1 w:0) // Storage: System Account (r:1 w:1) - // Storage: Treasury Reasons (r:0 w:1) + // Storage: Tips Reasons (r:0 w:1) fn close_tip(t: u32, ) -> Weight { - (84_094_000 as Weight) - // Standard Error: 0 - .saturating_add((283_000 as Weight).saturating_mul(t as Weight)) + (41_658_000 as Weight) + // Standard Error: 13_000 + .saturating_add((391_000 as Weight).saturating_mul(t as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } - // Storage: Treasury Tips (r:1 w:1) - // Storage: Treasury Reasons (r:0 w:1) + // Storage: Tips Tips (r:1 w:1) + // Storage: Tips Reasons (r:0 w:1) fn slash_tip(t: u32, ) -> Weight { - (24_891_000 as Weight) - // Standard Error: 0 - .saturating_add((6_000 as Weight).saturating_mul(t as Weight)) + (14_935_000 as Weight) + // Standard Error: 6_000 + .saturating_add((40_000 as Weight).saturating_mul(t as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -117,60 +118,60 @@ impl WeightInfo for SubstrateWeight { // For backwards compatibility and tests impl WeightInfo for () { - // Storage: Treasury Reasons (r:1 w:1) - // Storage: Treasury Tips (r:1 w:1) + // Storage: Tips Reasons (r:1 w:1) + // Storage: Tips Tips (r:1 w:1) fn report_awesome(r: u32, ) -> Weight { - (50_921_000 as Weight) + (26_318_000 as Weight) // Standard Error: 0 .saturating_add((2_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } - // Storage: Treasury Tips (r:1 w:1) - // Storage: Treasury Reasons (r:0 w:1) + // Storage: Tips Tips (r:1 w:1) + // Storage: Tips Reasons (r:0 w:1) fn retract_tip() -> Weight { - (46_352_000 as Weight) + (24_688_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Elections Members (r:1 w:0) - // Storage: Treasury Reasons (r:1 w:1) - // Storage: Treasury Tips (r:0 w:1) + // Storage: Tips Reasons (r:1 w:1) + // Storage: Tips Tips (r:0 w:1) fn tip_new(r: u32, t: u32, ) -> Weight { - (33_338_000 as Weight) + (17_395_000 as Weight) // Standard Error: 0 - .saturating_add((2_000 as Weight).saturating_mul(r as Weight)) - // Standard Error: 0 - .saturating_add((115_000 as Weight).saturating_mul(t as Weight)) + .saturating_add((3_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 4_000 + .saturating_add((197_000 as Weight).saturating_mul(t as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Elections Members (r:1 w:0) - // Storage: Treasury Tips (r:1 w:1) + // Storage: Tips Tips (r:1 w:1) fn tip(t: u32, ) -> Weight { - (22_702_000 as Weight) - // Standard Error: 0 - .saturating_add((538_000 as Weight).saturating_mul(t as Weight)) + (10_783_000 as Weight) + // Standard Error: 6_000 + .saturating_add((568_000 as Weight).saturating_mul(t as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } - // Storage: Treasury Tips (r:1 w:1) + // Storage: Tips Tips (r:1 w:1) // Storage: Elections Members (r:1 w:0) // Storage: System Account (r:1 w:1) - // Storage: Treasury Reasons (r:0 w:1) + // Storage: Tips Reasons (r:0 w:1) fn close_tip(t: u32, ) -> Weight { - (84_094_000 as Weight) - // Standard Error: 0 - .saturating_add((283_000 as Weight).saturating_mul(t as Weight)) + (41_658_000 as Weight) + // Standard Error: 13_000 + .saturating_add((391_000 as Weight).saturating_mul(t as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } - // Storage: Treasury Tips (r:1 w:1) - // Storage: Treasury Reasons (r:0 w:1) + // Storage: Tips Tips (r:1 w:1) + // Storage: Tips Reasons (r:0 w:1) fn slash_tip(t: u32, ) -> Weight { - (24_891_000 as Weight) - // Standard Error: 0 - .saturating_add((6_000 as Weight).saturating_mul(t as Weight)) + (14_935_000 as Weight) + // Standard Error: 6_000 + .saturating_add((40_000 as Weight).saturating_mul(t as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } diff --git a/frame/transaction-storage/src/weights.rs b/frame/transaction-storage/src/weights.rs index ffea996b83d9..bdf4d2cf6222 100644 --- a/frame/transaction-storage/src/weights.rs +++ b/frame/transaction-storage/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. +// Copyright (C) 2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_transaction_storage //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-08-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 +//! DATE: 2022-01-19, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// target/release/substrate +// ./target/optimized/substrate // benchmark // --chain=dev // --steps=50 @@ -32,9 +32,10 @@ // --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/transaction-storage/src/weights.rs -// --template=./.maintain/frame-weight-template.hbs - +// --output=./weights-optimized/frame/transaction-storage/src//weights.rs +// --template=.maintain/frame-weight-template.hbs +// --header=HEADER-APACHE2 +// --raw #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -62,7 +63,7 @@ impl WeightInfo for SubstrateWeight { fn store(l: u32, ) -> Weight { (0 as Weight) // Standard Error: 0 - .saturating_add((8_000 as Weight).saturating_mul(l as Weight)) + .saturating_add((5_000 as Weight).saturating_mul(l as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -73,7 +74,7 @@ impl WeightInfo for SubstrateWeight { // Storage: TransactionStorage BlockTransactions (r:1 w:1) // Storage: TransactionStorage MaxBlockTransactions (r:1 w:0) fn renew() -> Weight { - (67_532_000 as Weight) + (43_773_000 as Weight) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -83,7 +84,7 @@ impl WeightInfo for SubstrateWeight { // Storage: System ParentHash (r:1 w:0) // Storage: TransactionStorage Transactions (r:1 w:0) fn check_proof_max() -> Weight { - (182_886_000 as Weight) + (139_490_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -100,7 +101,7 @@ impl WeightInfo for () { fn store(l: u32, ) -> Weight { (0 as Weight) // Standard Error: 0 - .saturating_add((8_000 as Weight).saturating_mul(l as Weight)) + .saturating_add((5_000 as Weight).saturating_mul(l as Weight)) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -111,7 +112,7 @@ impl WeightInfo for () { // Storage: TransactionStorage BlockTransactions (r:1 w:1) // Storage: TransactionStorage MaxBlockTransactions (r:1 w:0) fn renew() -> Weight { - (67_532_000 as Weight) + (43_773_000 as Weight) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -121,7 +122,7 @@ impl WeightInfo for () { // Storage: System ParentHash (r:1 w:0) // Storage: TransactionStorage Transactions (r:1 w:0) fn check_proof_max() -> Weight { - (182_886_000 as Weight) + (139_490_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } diff --git a/frame/treasury/src/weights.rs b/frame/treasury/src/weights.rs index 79635ac2a725..ebe823ddb8ce 100644 --- a/frame/treasury/src/weights.rs +++ b/frame/treasury/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. +// Copyright (C) 2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_treasury //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-08-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 +//! DATE: 2022-01-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// target/release/substrate +// ./target/lto-fat-cg1/substrate // benchmark // --chain=dev // --steps=50 @@ -33,8 +33,9 @@ // --wasm-execution=compiled // --heap-pages=4096 // --output=./frame/treasury/src/weights.rs -// --template=./.maintain/frame-weight-template.hbs - +// --template=.maintain/frame-weight-template.hbs +// --header=LICENSE-APACHE2 +// --raw #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -57,34 +58,34 @@ impl WeightInfo for SubstrateWeight { // Storage: Treasury ProposalCount (r:1 w:1) // Storage: Treasury Proposals (r:0 w:1) fn propose_spend() -> Weight { - (41_567_000 as Weight) + (21_666_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Treasury Proposals (r:1 w:1) // Storage: System Account (r:1 w:1) fn reject_proposal() -> Weight { - (38_993_000 as Weight) + (25_008_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Treasury Proposals (r:1 w:0) // Storage: Treasury Approvals (r:1 w:1) fn approve_proposal(p: u32, ) -> Weight { - (13_543_000 as Weight) + (8_032_000 as Weight) // Standard Error: 1_000 - .saturating_add((55_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((66_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Treasury Approvals (r:1 w:1) - // Storage: Treasury BountyApprovals (r:1 w:1) + // Storage: Bounties BountyApprovals (r:1 w:1) // Storage: Treasury Proposals (r:2 w:2) // Storage: System Account (r:4 w:4) fn on_initialize_proposals(p: u32, ) -> Weight { - (51_708_000 as Weight) - // Standard Error: 21_000 - .saturating_add((57_926_000 as Weight).saturating_mul(p as Weight)) + (25_541_000 as Weight) + // Standard Error: 19_000 + .saturating_add((27_399_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(p as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -97,34 +98,34 @@ impl WeightInfo for () { // Storage: Treasury ProposalCount (r:1 w:1) // Storage: Treasury Proposals (r:0 w:1) fn propose_spend() -> Weight { - (41_567_000 as Weight) + (21_666_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Treasury Proposals (r:1 w:1) // Storage: System Account (r:1 w:1) fn reject_proposal() -> Weight { - (38_993_000 as Weight) + (25_008_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Treasury Proposals (r:1 w:0) // Storage: Treasury Approvals (r:1 w:1) fn approve_proposal(p: u32, ) -> Weight { - (13_543_000 as Weight) + (8_032_000 as Weight) // Standard Error: 1_000 - .saturating_add((55_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((66_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Treasury Approvals (r:1 w:1) - // Storage: Treasury BountyApprovals (r:1 w:1) + // Storage: Bounties BountyApprovals (r:1 w:1) // Storage: Treasury Proposals (r:2 w:2) // Storage: System Account (r:4 w:4) fn on_initialize_proposals(p: u32, ) -> Weight { - (51_708_000 as Weight) - // Standard Error: 21_000 - .saturating_add((57_926_000 as Weight).saturating_mul(p as Weight)) + (25_541_000 as Weight) + // Standard Error: 19_000 + .saturating_add((27_399_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(p as Weight))) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) diff --git a/frame/uniques/src/weights.rs b/frame/uniques/src/weights.rs index 3a67eb09017b..190ce74bbaa5 100644 --- a/frame/uniques/src/weights.rs +++ b/frame/uniques/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. +// Copyright (C) 2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_uniques //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-11-02, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 +//! DATE: 2022-01-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// target/release/substrate +// ./target/lto-fat-cg1/substrate // benchmark // --chain=dev // --steps=50 @@ -33,8 +33,9 @@ // --wasm-execution=compiled // --heap-pages=4096 // --output=./frame/uniques/src/weights.rs -// --template=./.maintain/frame-weight-template.hbs - +// --template=.maintain/frame-weight-template.hbs +// --header=LICENSE-APACHE2 +// --raw #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -75,14 +76,14 @@ impl WeightInfo for SubstrateWeight { // Storage: Uniques Class (r:1 w:1) // Storage: Uniques ClassAccount (r:0 w:1) fn create() -> Weight { - (41_109_000 as Weight) + (23_715_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Uniques Class (r:1 w:1) // Storage: Uniques ClassAccount (r:0 w:1) fn force_create() -> Weight { - (22_986_000 as Weight) + (12_854_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -95,12 +96,12 @@ impl WeightInfo for SubstrateWeight { // Storage: Uniques Account (r:0 w:20) fn destroy(n: u32, m: u32, a: u32, ) -> Weight { (0 as Weight) - // Standard Error: 14_000 - .saturating_add((14_879_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 14_000 - .saturating_add((1_058_000 as Weight).saturating_mul(m as Weight)) - // Standard Error: 14_000 - .saturating_add((956_000 as Weight).saturating_mul(a as Weight)) + // Standard Error: 13_000 + .saturating_add((9_291_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 13_000 + .saturating_add((957_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 13_000 + .saturating_add((862_000 as Weight).saturating_mul(a as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(n as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -112,7 +113,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Uniques Class (r:1 w:1) // Storage: Uniques Account (r:0 w:1) fn mint() -> Weight { - (51_248_000 as Weight) + (29_659_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -120,7 +121,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Uniques Asset (r:1 w:1) // Storage: Uniques Account (r:0 w:1) fn burn() -> Weight { - (53_172_000 as Weight) + (31_363_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -128,7 +129,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Uniques Asset (r:1 w:1) // Storage: Uniques Account (r:0 w:2) fn transfer() -> Weight { - (39_680_000 as Weight) + (23_596_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -136,8 +137,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Uniques Asset (r:100 w:100) fn redeposit(i: u32, ) -> Weight { (0 as Weight) - // Standard Error: 12_000 - .saturating_add((22_759_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 11_000 + .saturating_add((11_793_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -146,26 +147,26 @@ impl WeightInfo for SubstrateWeight { // Storage: Uniques Asset (r:1 w:1) // Storage: Uniques Class (r:1 w:0) fn freeze() -> Weight { - (27_833_000 as Weight) + (17_708_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Uniques Asset (r:1 w:1) // Storage: Uniques Class (r:1 w:0) fn thaw() -> Weight { - (27_739_000 as Weight) + (17_959_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Uniques Class (r:1 w:1) fn freeze_class() -> Weight { - (20_890_000 as Weight) + (14_034_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Uniques Class (r:1 w:1) fn thaw_class() -> Weight { - (20_848_000 as Weight) + (13_751_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -173,20 +174,20 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:1 w:1) // Storage: Uniques ClassAccount (r:0 w:2) fn transfer_ownership() -> Weight { - (51_523_000 as Weight) + (31_328_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } // Storage: Uniques Class (r:1 w:1) fn set_team() -> Weight { - (22_034_000 as Weight) + (14_586_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Uniques Class (r:1 w:1) // Storage: Uniques ClassAccount (r:0 w:1) fn force_asset_status() -> Weight { - (25_877_000 as Weight) + (16_374_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -194,7 +195,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Uniques InstanceMetadataOf (r:1 w:0) // Storage: Uniques Attribute (r:1 w:1) fn set_attribute() -> Weight { - (63_365_000 as Weight) + (36_952_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -202,49 +203,49 @@ impl WeightInfo for SubstrateWeight { // Storage: Uniques InstanceMetadataOf (r:1 w:0) // Storage: Uniques Attribute (r:1 w:1) fn clear_attribute() -> Weight { - (56_849_000 as Weight) + (35_230_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Uniques Class (r:1 w:1) // Storage: Uniques InstanceMetadataOf (r:1 w:1) fn set_metadata() -> Weight { - (47_982_000 as Weight) + (28_148_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Uniques Class (r:1 w:1) // Storage: Uniques InstanceMetadataOf (r:1 w:1) fn clear_metadata() -> Weight { - (47_340_000 as Weight) + (29_027_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Uniques Class (r:1 w:1) // Storage: Uniques ClassMetadataOf (r:1 w:1) fn set_class_metadata() -> Weight { - (46_897_000 as Weight) + (27_535_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Uniques Class (r:1 w:0) // Storage: Uniques ClassMetadataOf (r:1 w:1) fn clear_class_metadata() -> Weight { - (41_745_000 as Weight) + (26_707_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Uniques Class (r:1 w:0) // Storage: Uniques Asset (r:1 w:1) fn approve_transfer() -> Weight { - (29_828_000 as Weight) + (19_108_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Uniques Class (r:1 w:0) // Storage: Uniques Asset (r:1 w:1) fn cancel_approval() -> Weight { - (29_759_000 as Weight) + (19_779_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -255,14 +256,14 @@ impl WeightInfo for () { // Storage: Uniques Class (r:1 w:1) // Storage: Uniques ClassAccount (r:0 w:1) fn create() -> Weight { - (41_109_000 as Weight) + (23_715_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Uniques Class (r:1 w:1) // Storage: Uniques ClassAccount (r:0 w:1) fn force_create() -> Weight { - (22_986_000 as Weight) + (12_854_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -275,12 +276,12 @@ impl WeightInfo for () { // Storage: Uniques Account (r:0 w:20) fn destroy(n: u32, m: u32, a: u32, ) -> Weight { (0 as Weight) - // Standard Error: 14_000 - .saturating_add((14_879_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 14_000 - .saturating_add((1_058_000 as Weight).saturating_mul(m as Weight)) - // Standard Error: 14_000 - .saturating_add((956_000 as Weight).saturating_mul(a as Weight)) + // Standard Error: 13_000 + .saturating_add((9_291_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 13_000 + .saturating_add((957_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 13_000 + .saturating_add((862_000 as Weight).saturating_mul(a as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(n as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -292,7 +293,7 @@ impl WeightInfo for () { // Storage: Uniques Class (r:1 w:1) // Storage: Uniques Account (r:0 w:1) fn mint() -> Weight { - (51_248_000 as Weight) + (29_659_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -300,7 +301,7 @@ impl WeightInfo for () { // Storage: Uniques Asset (r:1 w:1) // Storage: Uniques Account (r:0 w:1) fn burn() -> Weight { - (53_172_000 as Weight) + (31_363_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -308,7 +309,7 @@ impl WeightInfo for () { // Storage: Uniques Asset (r:1 w:1) // Storage: Uniques Account (r:0 w:2) fn transfer() -> Weight { - (39_680_000 as Weight) + (23_596_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -316,8 +317,8 @@ impl WeightInfo for () { // Storage: Uniques Asset (r:100 w:100) fn redeposit(i: u32, ) -> Weight { (0 as Weight) - // Standard Error: 12_000 - .saturating_add((22_759_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 11_000 + .saturating_add((11_793_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -326,26 +327,26 @@ impl WeightInfo for () { // Storage: Uniques Asset (r:1 w:1) // Storage: Uniques Class (r:1 w:0) fn freeze() -> Weight { - (27_833_000 as Weight) + (17_708_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Uniques Asset (r:1 w:1) // Storage: Uniques Class (r:1 w:0) fn thaw() -> Weight { - (27_739_000 as Weight) + (17_959_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Uniques Class (r:1 w:1) fn freeze_class() -> Weight { - (20_890_000 as Weight) + (14_034_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Uniques Class (r:1 w:1) fn thaw_class() -> Weight { - (20_848_000 as Weight) + (13_751_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -353,20 +354,20 @@ impl WeightInfo for () { // Storage: System Account (r:1 w:1) // Storage: Uniques ClassAccount (r:0 w:2) fn transfer_ownership() -> Weight { - (51_523_000 as Weight) + (31_328_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } // Storage: Uniques Class (r:1 w:1) fn set_team() -> Weight { - (22_034_000 as Weight) + (14_586_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Uniques Class (r:1 w:1) // Storage: Uniques ClassAccount (r:0 w:1) fn force_asset_status() -> Weight { - (25_877_000 as Weight) + (16_374_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -374,7 +375,7 @@ impl WeightInfo for () { // Storage: Uniques InstanceMetadataOf (r:1 w:0) // Storage: Uniques Attribute (r:1 w:1) fn set_attribute() -> Weight { - (63_365_000 as Weight) + (36_952_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -382,49 +383,49 @@ impl WeightInfo for () { // Storage: Uniques InstanceMetadataOf (r:1 w:0) // Storage: Uniques Attribute (r:1 w:1) fn clear_attribute() -> Weight { - (56_849_000 as Weight) + (35_230_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Uniques Class (r:1 w:1) // Storage: Uniques InstanceMetadataOf (r:1 w:1) fn set_metadata() -> Weight { - (47_982_000 as Weight) + (28_148_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Uniques Class (r:1 w:1) // Storage: Uniques InstanceMetadataOf (r:1 w:1) fn clear_metadata() -> Weight { - (47_340_000 as Weight) + (29_027_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Uniques Class (r:1 w:1) // Storage: Uniques ClassMetadataOf (r:1 w:1) fn set_class_metadata() -> Weight { - (46_897_000 as Weight) + (27_535_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Uniques Class (r:1 w:0) // Storage: Uniques ClassMetadataOf (r:1 w:1) fn clear_class_metadata() -> Weight { - (41_745_000 as Weight) + (26_707_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Uniques Class (r:1 w:0) // Storage: Uniques Asset (r:1 w:1) fn approve_transfer() -> Weight { - (29_828_000 as Weight) + (19_108_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Uniques Class (r:1 w:0) // Storage: Uniques Asset (r:1 w:1) fn cancel_approval() -> Weight { - (29_759_000 as Weight) + (19_779_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } diff --git a/frame/utility/src/weights.rs b/frame/utility/src/weights.rs index 15798007a9ba..3d80691210de 100644 --- a/frame/utility/src/weights.rs +++ b/frame/utility/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. +// Copyright (C) 2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_utility //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-10-30, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 +//! DATE: 2022-01-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// target/release/substrate +// ./target/lto-fat-cg1/substrate // benchmark // --chain=dev // --steps=50 @@ -33,8 +33,9 @@ // --wasm-execution=compiled // --heap-pages=4096 // --output=./frame/utility/src/weights.rs -// --template=./.maintain/frame-weight-template.hbs - +// --template=.maintain/frame-weight-template.hbs +// --header=LICENSE-APACHE2 +// --raw #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -55,39 +56,39 @@ pub trait WeightInfo { pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { fn batch(c: u32, ) -> Weight { - (18_293_000 as Weight) - // Standard Error: 3_000 - .saturating_add((5_530_000 as Weight).saturating_mul(c as Weight)) + (15_877_000 as Weight) + // Standard Error: 1_000 + .saturating_add((2_341_000 as Weight).saturating_mul(c as Weight)) } fn as_derivative() -> Weight { - (3_387_000 as Weight) + (1_754_000 as Weight) } fn batch_all(c: u32, ) -> Weight { - (19_223_000 as Weight) - // Standard Error: 4_000 - .saturating_add((5_998_000 as Weight).saturating_mul(c as Weight)) + (16_581_000 as Weight) + // Standard Error: 1_000 + .saturating_add((2_476_000 as Weight).saturating_mul(c as Weight)) } fn dispatch_as() -> Weight { - (14_340_000 as Weight) + (8_294_000 as Weight) } } // For backwards compatibility and tests impl WeightInfo for () { fn batch(c: u32, ) -> Weight { - (18_293_000 as Weight) - // Standard Error: 3_000 - .saturating_add((5_530_000 as Weight).saturating_mul(c as Weight)) + (15_877_000 as Weight) + // Standard Error: 1_000 + .saturating_add((2_341_000 as Weight).saturating_mul(c as Weight)) } fn as_derivative() -> Weight { - (3_387_000 as Weight) + (1_754_000 as Weight) } fn batch_all(c: u32, ) -> Weight { - (19_223_000 as Weight) - // Standard Error: 4_000 - .saturating_add((5_998_000 as Weight).saturating_mul(c as Weight)) + (16_581_000 as Weight) + // Standard Error: 1_000 + .saturating_add((2_476_000 as Weight).saturating_mul(c as Weight)) } fn dispatch_as() -> Weight { - (14_340_000 as Weight) + (8_294_000 as Weight) } } diff --git a/frame/vesting/src/weights.rs b/frame/vesting/src/weights.rs index 660f83965557..caf1880daefd 100644 --- a/frame/vesting/src/weights.rs +++ b/frame/vesting/src/weights.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. +// Copyright (C) 2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_vesting //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-08-10, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 +//! DATE: 2022-01-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// target/release/substrate +// ./target/lto-fat-cg1/substrate // benchmark // --chain=dev // --steps=50 @@ -33,8 +33,9 @@ // --wasm-execution=compiled // --heap-pages=4096 // --output=./frame/vesting/src/weights.rs -// --template=./.maintain/frame-weight-template.hbs - +// --template=.maintain/frame-weight-template.hbs +// --header=LICENSE-APACHE2 +// --raw #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -61,22 +62,22 @@ impl WeightInfo for SubstrateWeight { // Storage: Vesting Vesting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vest_locked(l: u32, s: u32, ) -> Weight { - (50_642_000 as Weight) + (27_545_000 as Weight) // Standard Error: 1_000 - .saturating_add((144_000 as Weight).saturating_mul(l as Weight)) - // Standard Error: 3_000 - .saturating_add((177_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((111_000 as Weight).saturating_mul(l as Weight)) + // Standard Error: 2_000 + .saturating_add((78_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Vesting Vesting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vest_unlocked(l: u32, s: u32, ) -> Weight { - (50_830_000 as Weight) + (27_638_000 as Weight) // Standard Error: 1_000 - .saturating_add((115_000 as Weight).saturating_mul(l as Weight)) - // Standard Error: 3_000 - .saturating_add((112_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((102_000 as Weight).saturating_mul(l as Weight)) + // Standard Error: 2_000 + .saturating_add((41_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -84,11 +85,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn vest_other_locked(l: u32, s: u32, ) -> Weight { - (52_151_000 as Weight) + (27_571_000 as Weight) // Standard Error: 1_000 - .saturating_add((130_000 as Weight).saturating_mul(l as Weight)) - // Standard Error: 3_000 - .saturating_add((162_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((105_000 as Weight).saturating_mul(l as Weight)) + // Standard Error: 2_000 + .saturating_add((76_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -96,11 +97,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn vest_other_unlocked(l: u32, s: u32, ) -> Weight { - (51_009_000 as Weight) - // Standard Error: 4_000 - .saturating_add((123_000 as Weight).saturating_mul(l as Weight)) - // Standard Error: 9_000 - .saturating_add((118_000 as Weight).saturating_mul(s as Weight)) + (27_470_000 as Weight) + // Standard Error: 1_000 + .saturating_add((99_000 as Weight).saturating_mul(l as Weight)) + // Standard Error: 2_000 + .saturating_add((48_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -108,11 +109,11 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vested_transfer(l: u32, s: u32, ) -> Weight { - (89_517_000 as Weight) - // Standard Error: 5_000 - .saturating_add((114_000 as Weight).saturating_mul(l as Weight)) - // Standard Error: 10_000 - .saturating_add((23_000 as Weight).saturating_mul(s as Weight)) + (42_886_000 as Weight) + // Standard Error: 1_000 + .saturating_add((100_000 as Weight).saturating_mul(l as Weight)) + // Standard Error: 3_000 + .saturating_add((49_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -120,11 +121,11 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:2 w:2) // Storage: Balances Locks (r:1 w:1) fn force_vested_transfer(l: u32, s: u32, ) -> Weight { - (87_903_000 as Weight) - // Standard Error: 6_000 - .saturating_add((121_000 as Weight).saturating_mul(l as Weight)) - // Standard Error: 12_000 - .saturating_add((56_000 as Weight).saturating_mul(s as Weight)) + (42_528_000 as Weight) + // Standard Error: 1_000 + .saturating_add((104_000 as Weight).saturating_mul(l as Weight)) + // Standard Error: 3_000 + .saturating_add((46_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } @@ -132,11 +133,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn not_unlocking_merge_schedules(l: u32, s: u32, ) -> Weight { - (54_463_000 as Weight) + (28_372_000 as Weight) + // Standard Error: 1_000 + .saturating_add((110_000 as Weight).saturating_mul(l as Weight)) // Standard Error: 2_000 - .saturating_add((123_000 as Weight).saturating_mul(l as Weight)) - // Standard Error: 5_000 - .saturating_add((149_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((71_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -144,11 +145,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn unlocking_merge_schedules(l: u32, s: u32, ) -> Weight { - (53_674_000 as Weight) + (28_117_000 as Weight) // Standard Error: 1_000 - .saturating_add((137_000 as Weight).saturating_mul(l as Weight)) - // Standard Error: 4_000 - .saturating_add((152_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((108_000 as Weight).saturating_mul(l as Weight)) + // Standard Error: 2_000 + .saturating_add((76_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -159,22 +160,22 @@ impl WeightInfo for () { // Storage: Vesting Vesting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vest_locked(l: u32, s: u32, ) -> Weight { - (50_642_000 as Weight) + (27_545_000 as Weight) // Standard Error: 1_000 - .saturating_add((144_000 as Weight).saturating_mul(l as Weight)) - // Standard Error: 3_000 - .saturating_add((177_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((111_000 as Weight).saturating_mul(l as Weight)) + // Standard Error: 2_000 + .saturating_add((78_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Vesting Vesting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vest_unlocked(l: u32, s: u32, ) -> Weight { - (50_830_000 as Weight) + (27_638_000 as Weight) // Standard Error: 1_000 - .saturating_add((115_000 as Weight).saturating_mul(l as Weight)) - // Standard Error: 3_000 - .saturating_add((112_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((102_000 as Weight).saturating_mul(l as Weight)) + // Standard Error: 2_000 + .saturating_add((41_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -182,11 +183,11 @@ impl WeightInfo for () { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn vest_other_locked(l: u32, s: u32, ) -> Weight { - (52_151_000 as Weight) + (27_571_000 as Weight) // Standard Error: 1_000 - .saturating_add((130_000 as Weight).saturating_mul(l as Weight)) - // Standard Error: 3_000 - .saturating_add((162_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((105_000 as Weight).saturating_mul(l as Weight)) + // Standard Error: 2_000 + .saturating_add((76_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -194,11 +195,11 @@ impl WeightInfo for () { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn vest_other_unlocked(l: u32, s: u32, ) -> Weight { - (51_009_000 as Weight) - // Standard Error: 4_000 - .saturating_add((123_000 as Weight).saturating_mul(l as Weight)) - // Standard Error: 9_000 - .saturating_add((118_000 as Weight).saturating_mul(s as Weight)) + (27_470_000 as Weight) + // Standard Error: 1_000 + .saturating_add((99_000 as Weight).saturating_mul(l as Weight)) + // Standard Error: 2_000 + .saturating_add((48_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -206,11 +207,11 @@ impl WeightInfo for () { // Storage: System Account (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vested_transfer(l: u32, s: u32, ) -> Weight { - (89_517_000 as Weight) - // Standard Error: 5_000 - .saturating_add((114_000 as Weight).saturating_mul(l as Weight)) - // Standard Error: 10_000 - .saturating_add((23_000 as Weight).saturating_mul(s as Weight)) + (42_886_000 as Weight) + // Standard Error: 1_000 + .saturating_add((100_000 as Weight).saturating_mul(l as Weight)) + // Standard Error: 3_000 + .saturating_add((49_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -218,11 +219,11 @@ impl WeightInfo for () { // Storage: System Account (r:2 w:2) // Storage: Balances Locks (r:1 w:1) fn force_vested_transfer(l: u32, s: u32, ) -> Weight { - (87_903_000 as Weight) - // Standard Error: 6_000 - .saturating_add((121_000 as Weight).saturating_mul(l as Weight)) - // Standard Error: 12_000 - .saturating_add((56_000 as Weight).saturating_mul(s as Weight)) + (42_528_000 as Weight) + // Standard Error: 1_000 + .saturating_add((104_000 as Weight).saturating_mul(l as Weight)) + // Standard Error: 3_000 + .saturating_add((46_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } @@ -230,11 +231,11 @@ impl WeightInfo for () { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn not_unlocking_merge_schedules(l: u32, s: u32, ) -> Weight { - (54_463_000 as Weight) + (28_372_000 as Weight) + // Standard Error: 1_000 + .saturating_add((110_000 as Weight).saturating_mul(l as Weight)) // Standard Error: 2_000 - .saturating_add((123_000 as Weight).saturating_mul(l as Weight)) - // Standard Error: 5_000 - .saturating_add((149_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((71_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -242,11 +243,11 @@ impl WeightInfo for () { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn unlocking_merge_schedules(l: u32, s: u32, ) -> Weight { - (53_674_000 as Weight) + (28_117_000 as Weight) // Standard Error: 1_000 - .saturating_add((137_000 as Weight).saturating_mul(l as Weight)) - // Standard Error: 4_000 - .saturating_add((152_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((108_000 as Weight).saturating_mul(l as Weight)) + // Standard Error: 2_000 + .saturating_add((76_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } From b0c14750c8403760c1bac61f20db512d129b1686 Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Mon, 24 Jan 2022 17:18:13 +0100 Subject: [PATCH 416/695] Proposal: Defensive trait for infallible frame operations (#10626) * add a blueprint of how defensive traits could look like * add something for arithmetic as well * add some use cases in different pallets * some build fixing * Some new stuff and examples * Fix deadly bug * add more doc. * undo faulty change to assets pallet * Update frame/support/src/traits/misc.rs Co-authored-by: Oliver Tale-Yazdi * some review comments * remove draft comment * Fix ident test * Fix proxy tests as well * a few new ideas * Fix build * Fix doc Co-authored-by: Oliver Tale-Yazdi --- frame/balances/src/lib.rs | 24 +- frame/democracy/src/lib.rs | 3 +- .../src/signed.rs | 4 +- frame/election-provider-support/src/lib.rs | 2 +- frame/elections-phragmen/src/lib.rs | 8 +- frame/gilt/src/lib.rs | 11 +- frame/identity/src/benchmarking.rs | 2 +- frame/proxy/src/benchmarking.rs | 16 +- frame/staking/src/pallet/impls.rs | 10 +- frame/support/src/traits.rs | 11 +- frame/support/src/traits/misc.rs | 355 ++++++++++++++++++ 11 files changed, 402 insertions(+), 44 deletions(-) diff --git a/frame/balances/src/lib.rs b/frame/balances/src/lib.rs index f94afec06942..8a6d54b54c8d 100644 --- a/frame/balances/src/lib.rs +++ b/frame/balances/src/lib.rs @@ -170,7 +170,7 @@ use frame_support::{ pallet_prelude::DispatchResult, traits::{ tokens::{fungible, BalanceStatus as Status, DepositConsequence, WithdrawConsequence}, - Currency, ExistenceRequirement, + Currency, DefensiveSaturating, ExistenceRequirement, ExistenceRequirement::{AllowDeath, KeepAlive}, Get, Imbalance, LockIdentifier, LockableCurrency, NamedReservableCurrency, OnUnbalanced, ReservableCurrency, SignedImbalance, StoredMap, TryDrop, WithdrawReasons, @@ -1783,7 +1783,7 @@ where account.reserved -= actual; // defensive only: this can never fail since total issuance which is at least // free+reserved fits into the same data type. - account.free = account.free.saturating_add(actual); + account.free = account.free.defensive_saturating_add(actual); actual }) { Ok(x) => x, @@ -1896,7 +1896,7 @@ where match reserves.binary_search_by_key(id, |data| data.id) { Ok(index) => { // this add can't overflow but just to be defensive. - reserves[index].amount = reserves[index].amount.saturating_add(value); + reserves[index].amount = reserves[index].amount.defensive_saturating_add(value); }, Err(index) => { reserves @@ -1929,8 +1929,8 @@ where let remain = >::unreserve(who, to_change); - // remain should always be zero but just to be defensive here - let actual = to_change.saturating_sub(remain); + // remain should always be zero but just to be defensive here. + let actual = to_change.defensive_saturating_sub(remain); // `actual <= to_change` and `to_change <= amount`; qed; reserves[index].amount -= actual; @@ -1976,8 +1976,8 @@ where let (imb, remain) = >::slash_reserved(who, to_change); - // remain should always be zero but just to be defensive here - let actual = to_change.saturating_sub(remain); + // remain should always be zero but just to be defensive here. + let actual = to_change.defensive_saturating_sub(remain); // `actual <= to_change` and `to_change <= amount`; qed; reserves[index].amount -= actual; @@ -2036,12 +2036,12 @@ where )?; // remain should always be zero but just to be defensive - // here - let actual = to_change.saturating_sub(remain); + // here. + let actual = to_change.defensive_saturating_sub(remain); // this add can't overflow but just to be defensive. reserves[index].amount = - reserves[index].amount.saturating_add(actual); + reserves[index].amount.defensive_saturating_add(actual); Ok(actual) }, @@ -2056,7 +2056,7 @@ where // remain should always be zero but just to be defensive // here - let actual = to_change.saturating_sub(remain); + let actual = to_change.defensive_saturating_sub(remain); reserves .try_insert( @@ -2079,7 +2079,7 @@ where )?; // remain should always be zero but just to be defensive here - to_change.saturating_sub(remain) + to_change.defensive_saturating_sub(remain) }; // `actual <= to_change` and `to_change <= amount`; qed; diff --git a/frame/democracy/src/lib.rs b/frame/democracy/src/lib.rs index 1c052ad2d417..4580767d875c 100644 --- a/frame/democracy/src/lib.rs +++ b/frame/democracy/src/lib.rs @@ -156,6 +156,7 @@ use codec::{Decode, Encode, Input}; use frame_support::{ ensure, traits::{ + defensive_prelude::*, schedule::{DispatchTime, Named as ScheduleNamed}, BalanceStatus, Currency, Get, LockIdentifier, LockableCurrency, OnUnbalanced, ReservableCurrency, WithdrawReasons, @@ -1630,7 +1631,7 @@ impl Pallet { let mut public_props = Self::public_props(); if let Some((winner_index, _)) = public_props.iter().enumerate().max_by_key( // defensive only: All current public proposals have an amount locked - |x| Self::backing_for((x.1).0).unwrap_or_else(Zero::zero), + |x| Self::backing_for((x.1).0).defensive_unwrap_or_else(Zero::zero), ) { let (prop_index, proposal, _) = public_props.swap_remove(winner_index); >::put(public_props); diff --git a/frame/election-provider-multi-phase/src/signed.rs b/frame/election-provider-multi-phase/src/signed.rs index c2cb5cf44823..3b314bce80ff 100644 --- a/frame/election-provider-multi-phase/src/signed.rs +++ b/frame/election-provider-multi-phase/src/signed.rs @@ -25,7 +25,7 @@ use crate::{ use codec::{Decode, Encode, HasCompact}; use frame_support::{ storage::bounded_btree_map::BoundedBTreeMap, - traits::{Currency, Get, OnUnbalanced, ReservableCurrency}, + traits::{defensive_prelude::*, Currency, Get, OnUnbalanced, ReservableCurrency}, }; use sp_arithmetic::traits::SaturatedConversion; use sp_npos_elections::{is_score_better, ElectionScore, NposSolution}; @@ -365,7 +365,7 @@ impl Pallet { let active_voters = raw_solution.solution.voter_count() as u32; let feasibility_weight = { // defensive only: at the end of signed phase, snapshot will exits. - let desired_targets = Self::desired_targets().unwrap_or_default(); + let desired_targets = Self::desired_targets().defensive_unwrap_or_default(); T::WeightInfo::feasibility_check(voters, targets, active_voters, desired_targets) }; // the feasibility check itself has some weight diff --git a/frame/election-provider-support/src/lib.rs b/frame/election-provider-support/src/lib.rs index d10504c88cc6..889606da3428 100644 --- a/frame/election-provider-support/src/lib.rs +++ b/frame/election-provider-support/src/lib.rs @@ -343,7 +343,7 @@ impl ElectionProvider for NoElection<(AccountId, BlockNu /// used on the implementing side of [`ElectionDataProvider`]. pub trait SortedListProvider { /// The list's error type. - type Error; + type Error: sp_std::fmt::Debug; /// An iterator over the list, which can have `take` called on it. fn iter() -> Box>; diff --git a/frame/elections-phragmen/src/lib.rs b/frame/elections-phragmen/src/lib.rs index 7f576144d136..2c53bb2222b7 100644 --- a/frame/elections-phragmen/src/lib.rs +++ b/frame/elections-phragmen/src/lib.rs @@ -102,9 +102,9 @@ use codec::{Decode, Encode}; use frame_support::{ dispatch::WithPostDispatchInfo, traits::{ - ChangeMembers, Contains, ContainsLengthBound, Currency, CurrencyToVote, Get, - InitializeMembers, LockIdentifier, LockableCurrency, OnUnbalanced, ReservableCurrency, - SortedMembers, StorageVersion, WithdrawReasons, + defensive_prelude::*, ChangeMembers, Contains, ContainsLengthBound, Currency, + CurrencyToVote, Get, InitializeMembers, LockIdentifier, LockableCurrency, OnUnbalanced, + ReservableCurrency, SortedMembers, StorageVersion, WithdrawReasons, }, weights::Weight, }; @@ -1028,7 +1028,7 @@ impl Pallet { candidates_and_deposit .iter() .find_map(|(c, d)| if c == x { Some(*d) } else { None }) - .unwrap_or_default() + .defensive_unwrap_or_default() }; // fetch deposits from the one recorded one. This will make sure that a candidate who // submitted candidacy before a change to candidacy deposit will have the correct amount diff --git a/frame/gilt/src/lib.rs b/frame/gilt/src/lib.rs index 6211b15d8c8c..ac56dc108b2f 100644 --- a/frame/gilt/src/lib.rs +++ b/frame/gilt/src/lib.rs @@ -79,7 +79,7 @@ pub mod pallet { pub use crate::weights::WeightInfo; use frame_support::{ pallet_prelude::*, - traits::{Currency, OnUnbalanced, ReservableCurrency}, + traits::{Currency, DefensiveSaturating, OnUnbalanced, ReservableCurrency}, }; use frame_system::pallet_prelude::*; use sp_arithmetic::{PerThing, Perquintill}; @@ -599,10 +599,12 @@ pub mod pallet { remaining -= amount; // Should never underflow since it should track the total of the // bids exactly, but we'll be defensive. - qs[queue_index].1 = qs[queue_index].1.saturating_sub(bid.amount); + qs[queue_index].1 = + qs[queue_index].1.defensive_saturating_sub(bid.amount); // Now to activate the bid... - let nongilt_issuance = total_issuance.saturating_sub(totals.frozen); + let nongilt_issuance = + total_issuance.defensive_saturating_sub(totals.frozen); let effective_issuance = totals .proportion .left_from_one() @@ -613,7 +615,8 @@ pub mod pallet { let who = bid.who; let index = totals.index; totals.frozen += bid.amount; - totals.proportion = totals.proportion.saturating_add(proportion); + totals.proportion = + totals.proportion.defensive_saturating_add(proportion); totals.index += 1; let e = Event::GiltIssued { index, expiry, who: who.clone(), amount }; diff --git a/frame/identity/src/benchmarking.rs b/frame/identity/src/benchmarking.rs index 2f52aff394b7..2145779ecf54 100644 --- a/frame/identity/src/benchmarking.rs +++ b/frame/identity/src/benchmarking.rs @@ -75,7 +75,7 @@ fn create_sub_accounts( } // Set identity so `set_subs` does not fail. - let _ = T::Currency::make_free_balance_be(&who, BalanceOf::::max_value()); + let _ = T::Currency::make_free_balance_be(&who, BalanceOf::::max_value() / 2u32.into()); let info = create_identity_info::(1); Identity::::set_identity(who_origin.clone().into(), Box::new(info))?; diff --git a/frame/proxy/src/benchmarking.rs b/frame/proxy/src/benchmarking.rs index ceed2e6ab22d..f3098c6ad127 100644 --- a/frame/proxy/src/benchmarking.rs +++ b/frame/proxy/src/benchmarking.rs @@ -33,7 +33,7 @@ fn assert_last_event(generic_event: ::Event) { fn add_proxies(n: u32, maybe_who: Option) -> Result<(), &'static str> { let caller = maybe_who.unwrap_or_else(|| whitelisted_caller()); - T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); + T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value() / 2u32.into()); for i in 0..n { Proxy::::add_proxy( RawOrigin::Signed(caller.clone()).into(), @@ -51,12 +51,12 @@ fn add_announcements( maybe_real: Option, ) -> Result<(), &'static str> { let caller = maybe_who.unwrap_or_else(|| account("caller", 0, SEED)); - T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); + T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value() / 2u32.into()); let real = if let Some(real) = maybe_real { real } else { let real = account("real", 0, SEED); - T::Currency::make_free_balance_be(&real, BalanceOf::::max_value()); + T::Currency::make_free_balance_be(&real, BalanceOf::::max_value() / 2u32.into()); Proxy::::add_proxy( RawOrigin::Signed(real.clone()).into(), caller.clone(), @@ -80,7 +80,7 @@ benchmarks! { let p in 1 .. (T::MaxProxies::get() - 1).into() => add_proxies::(p, None)?; // In this case the caller is the "target" proxy let caller: T::AccountId = account("target", p - 1, SEED); - T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); + T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value() / 2u32.into()); // ... and "real" is the traditional caller. This is not a typo. let real: T::AccountId = whitelisted_caller(); let call: ::Call = frame_system::Call::::remark { remark: vec![] }.into(); @@ -95,7 +95,7 @@ benchmarks! { // In this case the caller is the "target" proxy let caller: T::AccountId = account("anonymous", 0, SEED); let delegate: T::AccountId = account("target", p - 1, SEED); - T::Currency::make_free_balance_be(&delegate, BalanceOf::::max_value()); + T::Currency::make_free_balance_be(&delegate, BalanceOf::::max_value() / 2u32.into()); // ... and "real" is the traditional caller. This is not a typo. let real: T::AccountId = whitelisted_caller(); let call: ::Call = frame_system::Call::::remark { remark: vec![] }.into(); @@ -115,7 +115,7 @@ benchmarks! { let p in 1 .. (T::MaxProxies::get() - 1).into() => add_proxies::(p, None)?; // In this case the caller is the "target" proxy let caller: T::AccountId = account("target", p - 1, SEED); - T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); + T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value() / 2u32.into()); // ... and "real" is the traditional caller. This is not a typo. let real: T::AccountId = whitelisted_caller(); let call: ::Call = frame_system::Call::::remark { remark: vec![] }.into(); @@ -136,7 +136,7 @@ benchmarks! { let p in 1 .. (T::MaxProxies::get() - 1).into() => add_proxies::(p, None)?; // In this case the caller is the "target" proxy let caller: T::AccountId = account("target", p - 1, SEED); - T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); + T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value() / 2u32.into()); // ... and "real" is the traditional caller. This is not a typo. let real: T::AccountId = whitelisted_caller(); let call: ::Call = frame_system::Call::::remark { remark: vec![] }.into(); @@ -157,7 +157,7 @@ benchmarks! { let p in 1 .. (T::MaxProxies::get() - 1).into() => add_proxies::(p, None)?; // In this case the caller is the "target" proxy let caller: T::AccountId = account("target", p - 1, SEED); - T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); + T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value() / 2u32.into()); // ... and "real" is the traditional caller. This is not a typo. let real: T::AccountId = whitelisted_caller(); add_announcements::(a, Some(caller.clone()), None)?; diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 68b5c19027a9..a72d2774dee2 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -24,8 +24,8 @@ use frame_election_provider_support::{ use frame_support::{ pallet_prelude::*, traits::{ - Currency, CurrencyToVote, EstimateNextNewSession, Get, Imbalance, LockableCurrency, - OnUnbalanced, UnixTime, WithdrawReasons, + Currency, CurrencyToVote, Defensive, EstimateNextNewSession, Get, Imbalance, + LockableCurrency, OnUnbalanced, UnixTime, WithdrawReasons, }, weights::{Weight, WithPostDispatchInfo}, }; @@ -775,10 +775,8 @@ impl Pallet { pub fn do_add_nominator(who: &T::AccountId, nominations: Nominations) { if !Nominators::::contains_key(who) { // maybe update sorted list. Error checking is defensive-only - this should never fail. - if T::SortedListProvider::on_insert(who.clone(), Self::weight_of(who)).is_err() { - log!(warn, "attempt to insert duplicate nominator ({:#?})", who); - debug_assert!(false, "attempt to insert duplicate nominator"); - }; + let _ = T::SortedListProvider::on_insert(who.clone(), Self::weight_of(who)) + .defensive_unwrap_or_default(); debug_assert_eq!(T::SortedListProvider::sanity_check(), Ok(())); } diff --git a/frame/support/src/traits.rs b/frame/support/src/traits.rs index 85a0698759b6..1928023cfe66 100644 --- a/frame/support/src/traits.rs +++ b/frame/support/src/traits.rs @@ -50,12 +50,13 @@ pub use filter::{ClearFilterGuard, FilterStack, FilterStackGuard, InstanceFilter mod misc; pub use misc::{ + defensive_prelude::{self, *}, Backing, ConstBool, ConstI128, ConstI16, ConstI32, ConstI64, ConstI8, ConstU128, ConstU16, - ConstU32, ConstU64, ConstU8, EnsureInherentsAreFirst, EqualPrivilegeOnly, EstimateCallFee, - ExecuteBlock, ExtrinsicCall, Get, GetBacking, GetDefault, HandleLifetime, IsSubType, IsType, - Len, OffchainWorker, OnKilledAccount, OnNewAccount, PreimageProvider, PreimageRecipient, - PrivilegeCmp, SameOrOther, Time, TryCollect, TryDrop, UnixTime, WrapperKeepOpaque, - WrapperOpaque, + ConstU32, ConstU64, ConstU8, DefensiveSaturating, EnsureInherentsAreFirst, EqualPrivilegeOnly, + EstimateCallFee, ExecuteBlock, ExtrinsicCall, Get, GetBacking, GetDefault, HandleLifetime, + IsSubType, IsType, Len, OffchainWorker, OnKilledAccount, OnNewAccount, PreimageProvider, + PreimageRecipient, PrivilegeCmp, SameOrOther, Time, TryCollect, TryDrop, UnixTime, + WrapperKeepOpaque, WrapperOpaque, }; mod stored_map; diff --git a/frame/support/src/traits/misc.rs b/frame/support/src/traits/misc.rs index df21624c3cea..eaada3ea2c36 100644 --- a/frame/support/src/traits/misc.rs +++ b/frame/support/src/traits/misc.rs @@ -20,9 +20,363 @@ use crate::dispatch::Parameter; use codec::{CompactLen, Decode, DecodeAll, Encode, EncodeLike, Input, MaxEncodedLen}; use scale_info::{build::Fields, meta_type, Path, Type, TypeInfo, TypeParameter}; +use sp_arithmetic::traits::{CheckedAdd, CheckedMul, CheckedSub, Saturating}; use sp_runtime::{traits::Block as BlockT, DispatchError}; use sp_std::{cmp::Ordering, prelude::*}; +const DEFENSIVE_OP_PUBLIC_ERROR: &'static str = "a defensive failure has been triggered; please report the block number at https://github.com/paritytech/substrate/issues"; +const DEFENSIVE_OP_INTERNAL_ERROR: &'static str = "Defensive failure has been triggered!"; + +/// Prelude module for all defensive traits to be imported at once. +pub mod defensive_prelude { + pub use super::{Defensive, DefensiveOption, DefensiveResult}; +} + +/// A trait to handle errors and options when you are really sure that a condition must hold, but +/// not brave enough to `expect` on it, or a default fallback value makes more sense. +/// +/// This trait mostly focuses on methods that eventually unwrap the inner value. See +/// [`DefensiveResult`] and [`DefensiveOption`] for methods that specifically apply to the +/// respective types. +/// +/// Each function in this trait will have two side effects, aside from behaving exactly as the name +/// would suggest: +/// +/// 1. It panics on `#[debug_assertions]`, so if the infallible code is reached in any of the tests, +/// you realize. +/// 2. It will log an error using the runtime logging system. This might help you detect such bugs +/// in production as well. Note that the log message, as of now, are not super expressive. Your +/// best shot of fully diagnosing the error would be to infer the block number of which the log +/// message was emitted, then re-execute that block using `check-block` or `try-runtime` +/// subcommands in substrate client. +pub trait Defensive { + /// Exactly the same as `unwrap_or`, but it does the defensive warnings explained in the trait + /// docs. + fn defensive_unwrap_or(self, other: T) -> T; + + /// Exactly the same as `unwrap_or_else`, but it does the defensive warnings explained in the + /// trait docs. + fn defensive_unwrap_or_else T>(self, f: F) -> T; + + /// Exactly the same as `unwrap_or_default`, but it does the defensive warnings explained in the + /// trait docs. + fn defensive_unwrap_or_default(self) -> T + where + T: Default; + + /// Does not alter the inner value at all, but it will log warnings if the inner value is `None` + /// or `Err`. + /// + /// In some ways, this is like `.defensive_map(|x| x)`. + /// + /// This is useful as: + /// ```nocompile + /// if let Some(inner) = maybe_value().defensive() { + /// .. + /// } + /// ``` + fn defensive(self) -> Self; +} + +/// Subset of methods similar to [`Defensive`] that can only work for a `Result`. +pub trait DefensiveResult { + /// Defensively map the error into another return type, but you are really sure that this + /// conversion should never be needed. + fn defensive_map_err F>(self, o: O) -> Result; + + /// Defensively map and unpack the value to something else (`U`), or call the default callback + /// if `Err`, which should never happen. + fn defensive_map_or_else U, F: FnOnce(T) -> U>(self, default: D, f: F) -> U; + + /// Defensively transform this result into an option, discarding the `Err` variant if it + /// happens, which should never happen. + fn defensive_ok(self) -> Option; + + /// Exactly the same as `map`, but it prints the appropriate warnings if the value being mapped + /// is `Err`. + fn defensive_map U>(self, f: F) -> Result; +} + +/// Subset of methods similar to [`Defensive`] that can only work for a `Option`. +pub trait DefensiveOption { + /// Potentially map and unpack the value to something else (`U`), or call the default callback + /// if `None`, which should never happen. + fn defensive_map_or_else U, F: FnOnce(T) -> U>(self, default: D, f: F) -> U; + + /// Defensively transform this option to a result. + fn defensive_ok_or_else E>(self, err: F) -> Result; + + /// Exactly the same as `map`, but it prints the appropriate warnings if the value being mapped + /// is `None`. + fn defensive_map U>(self, f: F) -> Option; +} + +impl Defensive for Option { + fn defensive_unwrap_or(self, or: T) -> T { + match self { + Some(inner) => inner, + None => { + debug_assert!(false, "{}", DEFENSIVE_OP_INTERNAL_ERROR); + frame_support::log::error!( + target: "runtime", + "{}", + DEFENSIVE_OP_PUBLIC_ERROR + ); + or + }, + } + } + + fn defensive_unwrap_or_else T>(self, f: F) -> T { + match self { + Some(inner) => inner, + None => { + debug_assert!(false, "{}", DEFENSIVE_OP_INTERNAL_ERROR); + frame_support::log::error!( + target: "runtime", + "{}", + DEFENSIVE_OP_PUBLIC_ERROR + ); + f() + }, + } + } + + fn defensive_unwrap_or_default(self) -> T + where + T: Default, + { + match self { + Some(inner) => inner, + None => { + debug_assert!(false, "{}", DEFENSIVE_OP_INTERNAL_ERROR); + frame_support::log::error!( + target: "runtime", + "{}", + DEFENSIVE_OP_PUBLIC_ERROR + ); + Default::default() + }, + } + } + + fn defensive(self) -> Self { + match self { + Some(inner) => Some(inner), + None => { + debug_assert!(false, "{}", DEFENSIVE_OP_INTERNAL_ERROR); + frame_support::log::error!( + target: "runtime", + "{}", + DEFENSIVE_OP_PUBLIC_ERROR + ); + None + }, + } + } +} + +impl Defensive for Result { + fn defensive_unwrap_or(self, or: T) -> T { + match self { + Ok(inner) => inner, + Err(e) => { + debug_assert!(false, "{}: {:?}", DEFENSIVE_OP_INTERNAL_ERROR, e); + frame_support::log::error!( + target: "runtime", + "{}: {:?}", + DEFENSIVE_OP_PUBLIC_ERROR, + e + ); + or + }, + } + } + + fn defensive_unwrap_or_else T>(self, f: F) -> T { + match self { + Ok(inner) => inner, + Err(e) => { + debug_assert!(false, "{}: {:?}", DEFENSIVE_OP_INTERNAL_ERROR, e); + frame_support::log::error!( + target: "runtime", + "{}: {:?}", + DEFENSIVE_OP_PUBLIC_ERROR, + e + ); + f() + }, + } + } + + fn defensive_unwrap_or_default(self) -> T + where + T: Default, + { + match self { + Ok(inner) => inner, + Err(e) => { + debug_assert!(false, "{}: {:?}", DEFENSIVE_OP_INTERNAL_ERROR, e); + frame_support::log::error!( + target: "runtime", + "{}: {:?}", + DEFENSIVE_OP_PUBLIC_ERROR, + e + ); + Default::default() + }, + } + } + + fn defensive(self) -> Self { + match self { + Ok(inner) => Ok(inner), + Err(e) => { + debug_assert!(false, "{}: {:?}", DEFENSIVE_OP_INTERNAL_ERROR, e); + frame_support::log::error!( + target: "runtime", + "{}: {:?}", + DEFENSIVE_OP_PUBLIC_ERROR, + e + ); + Err(e) + }, + } + } +} + +impl DefensiveResult for Result { + fn defensive_map_err F>(self, o: O) -> Result { + self.map_err(|e| { + debug_assert!(false, "{}: {:?}", DEFENSIVE_OP_INTERNAL_ERROR, e); + frame_support::log::error!( + target: "runtime", + "{}: {:?}", + DEFENSIVE_OP_PUBLIC_ERROR, + e + ); + o(e) + }) + } + + fn defensive_map_or_else U, F: FnOnce(T) -> U>(self, default: D, f: F) -> U { + self.map_or_else( + |e| { + debug_assert!(false, "{}: {:?}", DEFENSIVE_OP_INTERNAL_ERROR, e); + frame_support::log::error!( + target: "runtime", + "{}: {:?}", + DEFENSIVE_OP_PUBLIC_ERROR, + e + ); + default(e) + }, + f, + ) + } + + fn defensive_ok(self) -> Option { + match self { + Ok(inner) => Some(inner), + Err(e) => { + debug_assert!(false, "{}: {:?}", DEFENSIVE_OP_INTERNAL_ERROR, e); + frame_support::log::error!( + target: "runtime", + "{}: {:?}", + DEFENSIVE_OP_PUBLIC_ERROR, + e + ); + None + }, + } + } + + fn defensive_map U>(self, f: F) -> Result { + match self { + Ok(inner) => Ok(f(inner)), + Err(e) => { + debug_assert!(false, "{}: {:?}", DEFENSIVE_OP_INTERNAL_ERROR, e); + frame_support::log::error!( + target: "runtime", + "{}: {:?}", + DEFENSIVE_OP_PUBLIC_ERROR, + e + ); + Err(e) + }, + } + } +} + +impl DefensiveOption for Option { + fn defensive_map_or_else U, F: FnOnce(T) -> U>(self, default: D, f: F) -> U { + self.map_or_else( + || { + debug_assert!(false, "{}", DEFENSIVE_OP_INTERNAL_ERROR); + frame_support::log::error!( + target: "runtime", + "{}", + DEFENSIVE_OP_PUBLIC_ERROR, + ); + default() + }, + f, + ) + } + + fn defensive_ok_or_else E>(self, err: F) -> Result { + self.ok_or_else(|| { + debug_assert!(false, "{}", DEFENSIVE_OP_INTERNAL_ERROR); + frame_support::log::error!( + target: "runtime", + "{}", + DEFENSIVE_OP_PUBLIC_ERROR, + ); + err() + }) + } + + fn defensive_map U>(self, f: F) -> Option { + match self { + Some(inner) => Some(f(inner)), + None => { + debug_assert!(false, "{}", DEFENSIVE_OP_INTERNAL_ERROR); + frame_support::log::error!( + target: "runtime", + "{}", + DEFENSIVE_OP_PUBLIC_ERROR, + ); + None + }, + } + } +} + +/// A variant of [`Defensive`] with the same rationale, for the arithmetic operations where in +/// case an infallible operation fails, it saturates. +pub trait DefensiveSaturating { + /// Add `self` and `other` defensively. + fn defensive_saturating_add(self, other: Self) -> Self; + /// Subtract `other` from `self` defensively. + fn defensive_saturating_sub(self, other: Self) -> Self; + /// Multiply `self` and `other` defensively. + fn defensive_saturating_mul(self, other: Self) -> Self; +} + +// NOTE: A bit unfortunate, since T has to be bound by all the traits needed. Could make it +// `DefensiveSaturating` to mitigate. +impl DefensiveSaturating for T { + fn defensive_saturating_add(self, other: Self) -> Self { + self.checked_add(&other).defensive_unwrap_or_else(|| self.saturating_add(other)) + } + fn defensive_saturating_sub(self, other: Self) -> Self { + self.checked_sub(&other).defensive_unwrap_or_else(|| self.saturating_sub(other)) + } + fn defensive_saturating_mul(self, other: Self) -> Self { + self.checked_mul(&other).defensive_unwrap_or_else(|| self.saturating_mul(other)) + } +} + /// Try and collect into a collection `C`. pub trait TryCollect { type Error; @@ -72,6 +426,7 @@ impl Get for GetDefault { macro_rules! impl_const_get { ($name:ident, $t:ty) => { + #[derive($crate::RuntimeDebug)] pub struct $name; impl Get<$t> for $name { fn get() -> $t { From 511e8c860aa448c6899f884eebe64131a65300b8 Mon Sep 17 00:00:00 2001 From: Qinxuan Chen Date: Tue, 25 Jan 2022 00:28:46 +0800 Subject: [PATCH 417/695] use clap3 instead of structopt (#10632) * use clap3 instead of structopt Signed-off-by: koushiro * format Signed-off-by: koushiro * update ss58-registry and revert some nits Signed-off-by: koushiro * Fix clippy and doc Signed-off-by: koushiro * update clap to 3.0.7 Signed-off-by: koushiro * Apply review suggestions Signed-off-by: koushiro * remove useless option long name Signed-off-by: koushiro * cargo fmt Signed-off-by: koushiro --- .maintain/node-template-release/Cargo.toml | 2 +- .maintain/node-template-release/src/main.rs | 13 +- Cargo.lock | 152 ++++++++++-------- bin/node-template/node/Cargo.toml | 6 +- bin/node-template/node/src/cli.rs | 13 +- bin/node/bench/Cargo.toml | 6 +- bin/node/bench/src/main.rs | 16 +- bin/node/cli/Cargo.toml | 25 ++- bin/node/cli/build.rs | 8 +- bin/node/cli/src/cli.rs | 31 ++-- bin/node/inspect/Cargo.toml | 2 +- bin/node/inspect/src/cli.rs | 16 +- bin/utils/chain-spec-builder/Cargo.toml | 5 +- bin/utils/chain-spec-builder/src/main.rs | 32 ++-- bin/utils/subkey/Cargo.toml | 2 +- bin/utils/subkey/src/lib.rs | 8 +- client/cli/Cargo.toml | 49 +++--- client/cli/src/arg_enums.rs | 141 ++++++++-------- client/cli/src/commands/build_spec_cmd.rs | 12 +- client/cli/src/commands/check_block_cmd.rs | 12 +- client/cli/src/commands/export_blocks_cmd.rs | 18 +-- client/cli/src/commands/export_state_cmd.rs | 10 +- client/cli/src/commands/generate.rs | 21 ++- client/cli/src/commands/generate_node_key.rs | 10 +- client/cli/src/commands/import_blocks_cmd.rs | 14 +- client/cli/src/commands/insert_key.rs | 24 ++- client/cli/src/commands/inspect_key.rs | 27 ++-- client/cli/src/commands/inspect_node_key.rs | 14 +- client/cli/src/commands/key.rs | 6 +- client/cli/src/commands/purge_chain_cmd.rs | 10 +- client/cli/src/commands/revert_cmd.rs | 10 +- client/cli/src/commands/run_cmd.rs | 97 +++++------ client/cli/src/commands/sign.rs | 21 ++- client/cli/src/commands/vanity.rs | 17 +- client/cli/src/commands/verify.rs | 12 +- client/cli/src/error.rs | 2 +- client/cli/src/lib.rs | 61 +++---- client/cli/src/params/database_params.rs | 14 +- client/cli/src/params/import_params.rs | 67 +++----- client/cli/src/params/keystore_params.rs | 25 ++- client/cli/src/params/mod.rs | 30 ++-- client/cli/src/params/network_params.rs | 40 ++--- client/cli/src/params/node_key_params.rs | 25 ++- .../cli/src/params/offchain_worker_params.rs | 12 +- client/cli/src/params/pruning_params.rs | 8 +- client/cli/src/params/shared_params.rs | 28 ++-- .../cli/src/params/transaction_pool_params.rs | 8 +- frame/bags-list/remote-tests/Cargo.toml | 4 +- primitives/core/Cargo.toml | 16 +- primitives/npos-elections/fuzzer/Cargo.toml | 7 +- .../npos-elections/fuzzer/src/common.rs | 12 +- .../npos-elections/fuzzer/src/phragmen_pjr.rs | 13 +- .../npos-elections/fuzzer/src/reduce.rs | 7 +- utils/frame/benchmarking-cli/Cargo.toml | 2 +- utils/frame/benchmarking-cli/src/lib.rs | 59 ++++--- utils/frame/frame-utilities-cli/Cargo.toml | 3 +- .../frame-utilities-cli/src/pallet_id.rs | 16 +- utils/frame/generate-bags/Cargo.toml | 1 - .../generate-bags/node-runtime/Cargo.toml | 2 +- .../generate-bags/node-runtime/src/main.rs | 13 +- utils/frame/try-runtime/cli/Cargo.toml | 7 +- .../cli/src/commands/execute_block.rs | 16 +- .../cli/src/commands/follow_chain.rs | 8 +- .../cli/src/commands/offchain_worker.rs | 14 +- .../cli/src/commands/on_runtime_upgrade.rs | 4 +- utils/frame/try-runtime/cli/src/lib.rs | 46 +++--- 66 files changed, 662 insertions(+), 770 deletions(-) diff --git a/.maintain/node-template-release/Cargo.toml b/.maintain/node-template-release/Cargo.toml index 26256e836330..667281f6dcad 100644 --- a/.maintain/node-template-release/Cargo.toml +++ b/.maintain/node-template-release/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0" toml = "0.4" tar = "0.4" glob = "0.2" -structopt = "0.3" +clap = { version = "3.0", features = ["derive"] } tempfile = "3" fs_extra = "1" git2 = "0.8" diff --git a/.maintain/node-template-release/src/main.rs b/.maintain/node-template-release/src/main.rs index 7dcb1f0f4d81..62e9b6671576 100644 --- a/.maintain/node-template-release/src/main.rs +++ b/.maintain/node-template-release/src/main.rs @@ -1,4 +1,4 @@ -use structopt::StructOpt; +use clap::Parser; use std::{ collections::HashMap, @@ -26,13 +26,13 @@ const SUBSTRATE_GIT_URL: &str = "https://github.com/paritytech/substrate.git"; type CargoToml = HashMap; -#[derive(StructOpt)] +#[derive(Parser)] struct Options { /// The path to the `node-template` source. - #[structopt(parse(from_os_str))] + #[clap(parse(from_os_str))] node_template: PathBuf, /// The path where to output the generated `tar.gz` file. - #[structopt(parse(from_os_str))] + #[clap(parse(from_os_str))] output: PathBuf, } @@ -209,7 +209,7 @@ fn build_and_test(path: &Path, cargo_tomls: &[PathBuf]) { } fn main() { - let options = Options::from_args(); + let options = Options::parse(); let build_dir = tempfile::tempdir().expect("Creates temp build dir"); @@ -261,8 +261,7 @@ fn main() { // adding root rustfmt to node template build path let node_template_rustfmt_toml_path = node_template_path.join("rustfmt.toml"); - let root_rustfmt_toml = - &options.node_template.join("../../rustfmt.toml"); + let root_rustfmt_toml = &options.node_template.join("../../rustfmt.toml"); if root_rustfmt_toml.exists() { fs::copy(&root_rustfmt_toml, &node_template_rustfmt_toml_path) .expect("Copying rustfmt.toml."); diff --git a/Cargo.lock b/Cargo.lock index 580da5ad074c..39cb42be7a85 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -928,13 +928,13 @@ name = "chain-spec-builder" version = "2.0.0" dependencies = [ "ansi_term", + "clap 3.0.7", "node-cli", - "rand 0.7.3", + "rand 0.8.4", "sc-chain-spec", "sc-keystore", "sp-core", "sp-keystore", - "structopt", ] [[package]] @@ -996,13 +996,48 @@ version = "2.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ - "ansi_term", - "atty", "bitflags", - "strsim 0.8.0", - "textwrap", + "textwrap 0.11.0", "unicode-width", - "vec_map", +] + +[[package]] +name = "clap" +version = "3.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12e8611f9ae4e068fa3e56931fded356ff745e70987ff76924a6e0ab1c8ef2e3" +dependencies = [ + "atty", + "bitflags", + "clap_derive", + "indexmap", + "lazy_static", + "os_str_bytes", + "strsim", + "termcolor", + "textwrap 0.14.2", +] + +[[package]] +name = "clap_complete" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a394f7ec0715b42a4e52b294984c27c9a61f77c8d82f7774c5198350be143f19" +dependencies = [ + "clap 3.0.7", +] + +[[package]] +name = "clap_derive" +version = "3.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41a0645a430ec9136d2d701e54a95d557de12649a9dd7109ced3187e648ac824" +dependencies = [ + "heck 0.4.0", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -1256,7 +1291,7 @@ checksum = "1604dafd25fba2fe2d5895a9da139f8dc9b319a5fe5354ca137cbbce4e178d10" dependencies = [ "atty", "cast", - "clap", + "clap 2.34.0", "criterion-plot", "csv", "futures 0.3.16", @@ -1483,7 +1518,7 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim 0.10.0", + "strsim", "syn", ] @@ -1741,7 +1776,7 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c5f0096a91d210159eceb2ff5e1c4da18388a170e1e3ce948aac9c8fdbbf595" dependencies = [ - "heck", + "heck 0.3.2", "proc-macro2", "quote", "syn", @@ -2020,6 +2055,7 @@ version = "4.0.0-dev" dependencies = [ "Inflector", "chrono", + "clap 3.0.7", "frame-benchmarking", "frame-support", "handlebars", @@ -2036,7 +2072,6 @@ dependencies = [ "sp-keystore", "sp-runtime", "sp-state-machine", - "structopt", ] [[package]] @@ -2450,7 +2485,6 @@ dependencies = [ "num-format", "pallet-staking", "sp-io", - "structopt", ] [[package]] @@ -2653,6 +2687,12 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" + [[package]] name = "hermit-abi" version = "0.1.18" @@ -4516,6 +4556,7 @@ dependencies = [ name = "node-bench" version = "0.9.0-dev" dependencies = [ + "clap 3.0.7", "derive_more", "fs_extra", "futures 0.3.16", @@ -4545,7 +4586,6 @@ dependencies = [ "sp-timestamp", "sp-tracing", "sp-trie", - "structopt", "tempfile", ] @@ -4555,6 +4595,8 @@ version = "3.0.0-dev" dependencies = [ "assert_cmd", "async-std", + "clap 3.0.7", + "clap_complete", "criterion", "frame-benchmarking-cli", "frame-system", @@ -4576,7 +4618,7 @@ dependencies = [ "pallet-transaction-payment", "parity-scale-codec", "platforms", - "rand 0.7.3", + "rand 0.8.4", "regex", "remote-externalities", "sc-authority-discovery", @@ -4622,7 +4664,6 @@ dependencies = [ "sp-transaction-pool", "sp-transaction-storage-proof", "sp-trie", - "structopt", "substrate-build-script-utils", "substrate-frame-cli", "tempfile", @@ -4668,6 +4709,7 @@ dependencies = [ name = "node-inspect" version = "0.9.0-dev" dependencies = [ + "clap 3.0.7", "derive_more", "parity-scale-codec", "sc-cli", @@ -4677,7 +4719,6 @@ dependencies = [ "sp-blockchain", "sp-core", "sp-runtime", - "structopt", ] [[package]] @@ -4811,15 +4852,16 @@ dependencies = [ name = "node-runtime-generate-bags" version = "3.0.0" dependencies = [ + "clap 3.0.7", "generate-bags", "node-runtime", - "structopt", ] [[package]] name = "node-template" version = "3.0.0" dependencies = [ + "clap 3.0.7", "frame-benchmarking", "frame-benchmarking-cli", "jsonrpc-core", @@ -4848,7 +4890,6 @@ dependencies = [ "sp-finality-grandpa", "sp-runtime", "sp-timestamp", - "structopt", "substrate-build-script-utils", "substrate-frame-rpc-system", ] @@ -5140,6 +5181,15 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "os_str_bytes" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" +dependencies = [ + "memchr", +] + [[package]] name = "output_vt100" version = "0.1.2" @@ -5323,7 +5373,6 @@ dependencies = [ name = "pallet-bags-list-remote-tests" version = "4.0.0-dev" dependencies = [ - "clap", "frame-election-provider-support", "frame-support", "frame-system", @@ -5336,7 +5385,6 @@ dependencies = [ "sp-std", "sp-storage", "sp-tracing", - "structopt", "tokio", ] @@ -6912,7 +6960,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62941722fb675d463659e49c4f3fe1fe792ff24fe5bbaa9c08cd3b98a1c354f5" dependencies = [ "bytes 1.1.0", - "heck", + "heck 0.3.2", "itertools", "lazy_static", "log 0.4.14", @@ -7695,6 +7743,7 @@ name = "sc-cli" version = "0.10.0-dev" dependencies = [ "chrono", + "clap 3.0.7", "fdlimit", "futures 0.3.16", "hex", @@ -7721,7 +7770,6 @@ dependencies = [ "sp-panic-handler", "sp-runtime", "sp-version", - "structopt", "tempfile", "thiserror", "tiny-bip39", @@ -9624,13 +9672,13 @@ dependencies = [ name = "sp-npos-elections-fuzzer" version = "2.0.0-alpha.5" dependencies = [ + "clap 3.0.7", "honggfuzz", "parity-scale-codec", - "rand 0.7.3", + "rand 0.8.4", "scale-info", "sp-npos-elections", "sp-runtime", - "structopt", ] [[package]] @@ -10001,9 +10049,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "ss58-registry" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c83f0afe7e571565ef9aae7b0e4fb30fcaec4ebb9aea2f00489b772782aa03a4" +checksum = "1230685dc82f8699110640244d361a7099c602f08bddc5c90765a5153b4881dc" dependencies = [ "Inflector", "proc-macro2", @@ -10038,42 +10086,12 @@ dependencies = [ "rand 0.8.4", ] -[[package]] -name = "strsim" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" - [[package]] name = "strsim" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" -[[package]] -name = "structopt" -version = "0.3.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40b9788f4202aa75c240ecc9c15c65185e6a39ccdeb0fd5d008b98825464c87c" -dependencies = [ - "clap", - "lazy_static", - "structopt-derive", -] - -[[package]] -name = "structopt-derive" -version = "0.4.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" -dependencies = [ - "heck", - "proc-macro-error", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "strum" version = "0.22.0" @@ -10089,7 +10107,7 @@ version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "339f799d8b549e3744c7ac7feb216383e4005d94bdb22561b3ab8f3b808ae9fb" dependencies = [ - "heck", + "heck 0.3.2", "proc-macro2", "quote", "syn", @@ -10101,7 +10119,7 @@ version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5bb0dc7ee9c15cea6199cde9a127fa16a4c5819af85395457ad72d68edc85a38" dependencies = [ - "heck", + "heck 0.3.2", "proc-macro2", "quote", "rustversion", @@ -10112,8 +10130,8 @@ dependencies = [ name = "subkey" version = "2.0.1" dependencies = [ + "clap 3.0.7", "sc-cli", - "structopt", ] [[package]] @@ -10140,12 +10158,12 @@ dependencies = [ name = "substrate-frame-cli" version = "4.0.0-dev" dependencies = [ + "clap 3.0.7", "frame-support", "frame-system", "sc-cli", "sp-core", "sp-runtime", - "structopt", ] [[package]] @@ -10428,6 +10446,12 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "textwrap" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" + [[package]] name = "thiserror" version = "1.0.30" @@ -10920,6 +10944,7 @@ checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" name = "try-runtime-cli" version = "0.10.0-dev" dependencies = [ + "clap 3.0.7", "jsonrpsee", "log 0.4.14", "parity-scale-codec", @@ -10936,7 +10961,6 @@ dependencies = [ "sp-runtime", "sp-state-machine", "sp-version", - "structopt", "zstd", ] @@ -11146,12 +11170,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eafc1b9b2dfc6f5529177b62cf806484db55b32dc7c9658a118e11bbeb33061d" -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - [[package]] name = "version_check" version = "0.1.5" diff --git a/bin/node-template/node/Cargo.toml b/bin/node-template/node/Cargo.toml index 2b280e1bf00d..6b69d691d945 100644 --- a/bin/node-template/node/Cargo.toml +++ b/bin/node-template/node/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] name = "node-template" [dependencies] -structopt = "0.3.25" +clap = { version = "3.0", features = ["derive"] } sc-cli = { version = "0.10.0-dev", path = "../../../client/cli", features = ["wasmtime"] } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } @@ -59,6 +59,4 @@ substrate-build-script-utils = { version = "3.0.0", path = "../../../utils/build [features] default = [] -runtime-benchmarks = [ - "node-template-runtime/runtime-benchmarks", -] +runtime-benchmarks = ["node-template-runtime/runtime-benchmarks"] diff --git a/bin/node-template/node/src/cli.rs b/bin/node-template/node/src/cli.rs index 8ed1d35ba5f9..d787f57f071a 100644 --- a/bin/node-template/node/src/cli.rs +++ b/bin/node-template/node/src/cli.rs @@ -1,19 +1,20 @@ use sc_cli::RunCmd; -use structopt::StructOpt; -#[derive(Debug, StructOpt)] +#[derive(Debug, clap::Parser)] pub struct Cli { - #[structopt(subcommand)] + #[clap(subcommand)] pub subcommand: Option, - #[structopt(flatten)] + #[clap(flatten)] pub run: RunCmd, } -#[derive(Debug, StructOpt)] +#[derive(Debug, clap::Subcommand)] pub enum Subcommand { /// Key management cli utilities + #[clap(subcommand)] Key(sc_cli::KeySubcommand), + /// Build a chain specification. BuildSpec(sc_cli::BuildSpecCmd), @@ -36,6 +37,6 @@ pub enum Subcommand { Revert(sc_cli::RevertCmd), /// The custom benchmark subcommand benchmarking runtime pallets. - #[structopt(name = "benchmark", about = "Benchmark runtime pallets.")] + #[clap(name = "benchmark", about = "Benchmark runtime pallets.")] Benchmark(frame_benchmarking_cli::BenchmarkCmd), } diff --git a/bin/node/bench/Cargo.toml b/bin/node/bench/Cargo.toml index 670f6c4d3ed8..6c28f14793a9 100644 --- a/bin/node/bench/Cargo.toml +++ b/bin/node/bench/Cargo.toml @@ -9,6 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +clap = { version = "3.0", features = ["derive"] } log = "0.4.8" node-primitives = { version = "2.0.0", path = "../primitives" } node-testing = { version = "3.0.0-dev", path = "../testing" } @@ -18,7 +19,6 @@ sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } sp-state-machine = { version = "0.10.0", path = "../../../primitives/state-machine" } serde = "1.0.132" serde_json = "1.0.74" -structopt = "0.3" derive_more = "0.99.16" kvdb = "0.10.0" kvdb-rocksdb = "0.14.0" @@ -35,9 +35,7 @@ fs_extra = "1" hex = "0.4.0" rand = { version = "0.7.2", features = ["small_rng"] } lazy_static = "1.4.0" -parity-util-mem = { version = "0.10.2", default-features = false, features = [ - "primitive-types", -] } +parity-util-mem = { version = "0.10.2", default-features = false, features = ["primitive-types"] } parity-db = { version = "0.3" } sc-transaction-pool = { version = "4.0.0-dev", path = "../../../client/transaction-pool" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../../../client/transaction-pool/api" } diff --git a/bin/node/bench/src/main.rs b/bin/node/bench/src/main.rs index f1800214e3e8..0e50447d464f 100644 --- a/bin/node/bench/src/main.rs +++ b/bin/node/bench/src/main.rs @@ -28,7 +28,7 @@ mod tempdb; mod trie; mod txpool; -use structopt::StructOpt; +use clap::Parser; use node_testing::bench::{BlockType, DatabaseType as BenchDataBaseType, KeyTypes, Profile}; @@ -42,19 +42,19 @@ use crate::{ txpool::PoolBenchmarkDescription, }; -#[derive(Debug, StructOpt)] -#[structopt(name = "node-bench", about = "Node integration benchmarks")] +#[derive(Debug, Parser)] +#[clap(name = "node-bench", about = "Node integration benchmarks")] struct Opt { /// Show list of all available benchmarks. /// /// Will output ("name", "path"). Benchmarks can then be filtered by path. - #[structopt(short, long)] + #[clap(short, long)] list: bool, /// Machine readable json output. /// /// This also suppresses all regular output (except to stderr) - #[structopt(short, long)] + #[clap(short, long)] json: bool, /// Filter benchmarks. @@ -63,7 +63,7 @@ struct Opt { filter: Option, /// Number of transactions for block import with `custom` size. - #[structopt(long)] + #[clap(long)] transactions: Option, /// Mode @@ -72,12 +72,12 @@ struct Opt { /// /// "profile" mode adds pauses between measurable runs, /// so that actual interval can be selected in the profiler of choice. - #[structopt(short, long, default_value = "regular")] + #[clap(short, long, default_value = "regular")] mode: BenchmarkMode, } fn main() { - let opt = Opt::from_args(); + let opt = Opt::parse(); if !opt.json { sp_tracing::try_init_simple(); diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index 248181ac5c8b..2eb1618a7c98 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -34,13 +34,13 @@ crate-type = ["cdylib", "rlib"] [dependencies] # third-party dependencies +clap = { version = "3.0", features = ["derive"], optional = true } codec = { package = "parity-scale-codec", version = "2.0.0" } serde = { version = "1.0.132", features = ["derive"] } futures = "0.3.16" hex-literal = "0.3.4" log = "0.4.8" -rand = "0.7.2" -structopt = { version = "0.3.25", optional = true } +rand = "0.8" # primitives sp-authority-discovery = { version = "4.0.0-dev", path = "../../../primitives/authority-discovery" } @@ -97,12 +97,8 @@ node-inspect = { version = "0.9.0-dev", optional = true, path = "../inspect" } try-runtime-cli = { version = "0.10.0-dev", optional = true, path = "../../../utils/frame/try-runtime/cli" } [target.'cfg(any(target_arch="x86_64", target_arch="aarch64"))'.dependencies] -node-executor = { version = "3.0.0-dev", path = "../executor", features = [ - "wasmtime", -] } -sc-cli = { version = "0.10.0-dev", optional = true, path = "../../../client/cli", features = [ - "wasmtime", -] } +node-executor = { version = "3.0.0-dev", path = "../executor", features = ["wasmtime"] } +sc-cli = { version = "0.10.0-dev", optional = true, path = "../../../client/cli", features = ["wasmtime"] } sc-service = { version = "0.10.0-dev", default-features = false, path = "../../../client/service", features = [ "wasmtime", ] } @@ -129,7 +125,7 @@ regex = "1" platforms = "2.0" async-std = { version = "1.10.0", features = ["attributes"] } soketto = "0.4.2" -criterion = { version = "0.3.5", features = [ "async_tokio" ] } +criterion = { version = "0.3.5", features = ["async_tokio"] } tokio = { version = "1.15", features = ["macros", "time"] } jsonrpsee-ws-client = "0.4.1" wait-timeout = "0.2" @@ -137,7 +133,8 @@ remote-externalities = { path = "../../../utils/frame/remote-externalities" } pallet-timestamp = { version = "4.0.0-dev", path = "../../../frame/timestamp" } [build-dependencies] -structopt = { version = "0.3.25", optional = true } +clap = { version = "3.0", optional = true } +clap_complete = { version = "3.0", optional = true } node-inspect = { version = "0.9.0-dev", optional = true, path = "../inspect" } frame-benchmarking-cli = { version = "4.0.0-dev", optional = true, path = "../../../utils/frame/benchmarking-cli" } substrate-build-script-utils = { version = "3.0.0", optional = true, path = "../../../utils/build-script-utils" } @@ -155,14 +152,12 @@ cli = [ "frame-benchmarking-cli", "substrate-frame-cli", "sc-service/db", - "structopt", + "clap", + "clap_complete", "substrate-build-script-utils", "try-runtime-cli", ] -runtime-benchmarks = [ - "node-runtime/runtime-benchmarks", - "frame-benchmarking-cli", -] +runtime-benchmarks = ["node-runtime/runtime-benchmarks", "frame-benchmarking-cli"] # Enable features that allow the runtime to be tried and debugged. Name might be subject to change # in the near future. try-runtime = ["node-runtime/try-runtime", "try-runtime-cli"] diff --git a/bin/node/cli/build.rs b/bin/node/cli/build.rs index e0d5dcea62ed..6a010d8858fe 100644 --- a/bin/node/cli/build.rs +++ b/bin/node/cli/build.rs @@ -25,7 +25,8 @@ fn main() { mod cli { include!("src/cli.rs"); - use sc_cli::structopt::clap::Shell; + use clap::{ArgEnum, IntoApp}; + use clap_complete::{generate_to, Shell}; use std::{env, fs, path::Path}; use substrate_build_script_utils::{generate_cargo_keys, rerun_if_git_head_changed}; @@ -37,9 +38,8 @@ mod cli { } /// Build shell completion scripts for all known shells - /// Full list in https://github.com/kbknapp/clap-rs/blob/e9d0562a1dc5dfe731ed7c767e6cee0af08f0cf9/src/app/parser.rs#L123 fn build_shell_completion() { - for shell in &[Shell::Bash, Shell::Fish, Shell::Zsh, Shell::Elvish, Shell::PowerShell] { + for shell in Shell::value_variants() { build_completion(shell); } } @@ -61,6 +61,6 @@ mod cli { fs::create_dir(&path).ok(); - Cli::clap().gen_completions("substrate-node", *shell, &path); + let _ = generate_to(*shell, &mut Cli::into_app(), "substrate-node", &path); } } diff --git a/bin/node/cli/src/cli.rs b/bin/node/cli/src/cli.rs index 59d219a01090..00393c52f8b6 100644 --- a/bin/node/cli/src/cli.rs +++ b/bin/node/cli/src/cli.rs @@ -16,35 +16,30 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use sc_cli::{KeySubcommand, RunCmd, SignCmd, VanityCmd, VerifyCmd}; -use structopt::StructOpt; - /// An overarching CLI command definition. -#[derive(Debug, StructOpt)] +#[derive(Debug, clap::Parser)] pub struct Cli { /// Possible subcommand with parameters. - #[structopt(subcommand)] + #[clap(subcommand)] pub subcommand: Option, + #[allow(missing_docs)] - #[structopt(flatten)] - pub run: RunCmd, + #[clap(flatten)] + pub run: sc_cli::RunCmd, } /// Possible subcommands of the main binary. -#[derive(Debug, StructOpt)] +#[derive(Debug, clap::Subcommand)] pub enum Subcommand { - /// Key management cli utilities - Key(KeySubcommand), - /// The custom inspect subcommmand for decoding blocks and extrinsics. - #[structopt( + #[clap( name = "inspect", about = "Decode given block or extrinsic using current native runtime." )] Inspect(node_inspect::cli::InspectCmd), /// The custom benchmark subcommmand benchmarking runtime pallets. - #[structopt(name = "benchmark", about = "Benchmark runtime pallets.")] + #[clap(name = "benchmark", about = "Benchmark runtime pallets.")] Benchmark(frame_benchmarking_cli::BenchmarkCmd), /// Try some command against runtime state. @@ -55,14 +50,18 @@ pub enum Subcommand { #[cfg(not(feature = "try-runtime"))] TryRuntime, + /// Key management cli utilities + #[clap(subcommand)] + Key(sc_cli::KeySubcommand), + /// Verify a signature for a message, provided on STDIN, with a given (public or secret) key. - Verify(VerifyCmd), + Verify(sc_cli::VerifyCmd), /// Generate a seed that provides a vanity address. - Vanity(VanityCmd), + Vanity(sc_cli::VanityCmd), /// Sign a message, with a given (secret) key. - Sign(SignCmd), + Sign(sc_cli::SignCmd), /// Build a chain specification. BuildSpec(sc_cli::BuildSpecCmd), diff --git a/bin/node/inspect/Cargo.toml b/bin/node/inspect/Cargo.toml index d72c6f43d005..49470a7e7b05 100644 --- a/bin/node/inspect/Cargo.toml +++ b/bin/node/inspect/Cargo.toml @@ -11,6 +11,7 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] +clap = { version = "3.0", features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.0.0" } derive_more = "0.99" sc-cli = { version = "0.10.0-dev", path = "../../../client/cli" } @@ -20,4 +21,3 @@ sc-service = { version = "0.10.0-dev", default-features = false, path = "../../. sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } -structopt = "0.3.8" diff --git a/bin/node/inspect/src/cli.rs b/bin/node/inspect/src/cli.rs index 6e019ca5b208..cc1f232e1fe0 100644 --- a/bin/node/inspect/src/cli.rs +++ b/bin/node/inspect/src/cli.rs @@ -19,27 +19,25 @@ //! Structs to easily compose inspect sub-command for CLI. use sc_cli::{ImportParams, SharedParams}; -use std::fmt::Debug; -use structopt::StructOpt; /// The `inspect` command used to print decoded chain data. -#[derive(Debug, StructOpt)] +#[derive(Debug, clap::Parser)] pub struct InspectCmd { #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(subcommand)] pub command: InspectSubCmd, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub shared_params: SharedParams, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub import_params: ImportParams, } /// A possible inspect sub-commands. -#[derive(Debug, StructOpt)] +#[derive(Debug, clap::Subcommand)] pub enum InspectSubCmd { /// Decode block with native version of runtime and print out the details. Block { @@ -48,7 +46,7 @@ pub enum InspectSubCmd { /// Can be either a block hash (no 0x prefix) or a number to retrieve existing block, /// or a 0x-prefixed bytes hex string, representing SCALE encoding of /// a block. - #[structopt(value_name = "HASH or NUMBER or BYTES")] + #[clap(value_name = "HASH or NUMBER or BYTES")] input: String, }, /// Decode extrinsic with native version of runtime and print out the details. @@ -58,7 +56,7 @@ pub enum InspectSubCmd { /// Can be either a block hash (no 0x prefix) or number and the index, in the form /// of `{block}:{index}` or a 0x-prefixed bytes hex string, /// representing SCALE encoding of an extrinsic. - #[structopt(value_name = "BLOCK:INDEX or BYTES")] + #[clap(value_name = "BLOCK:INDEX or BYTES")] input: String, }, } diff --git a/bin/utils/chain-spec-builder/Cargo.toml b/bin/utils/chain-spec-builder/Cargo.toml index f9bb4f94491a..452221ff6e13 100644 --- a/bin/utils/chain-spec-builder/Cargo.toml +++ b/bin/utils/chain-spec-builder/Cargo.toml @@ -15,10 +15,11 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] ansi_term = "0.12.1" +clap = { version = "3.0", features = ["derive"] } +rand = "0.8" + sc-keystore = { version = "4.0.0-dev", path = "../../../client/keystore" } sc-chain-spec = { version = "4.0.0-dev", path = "../../../client/chain-spec" } node-cli = { version = "3.0.0-dev", path = "../../node/cli" } sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sp-keystore = { version = "0.10.0", path = "../../../primitives/keystore" } -rand = "0.7.2" -structopt = "0.3.25" diff --git a/bin/utils/chain-spec-builder/src/main.rs b/bin/utils/chain-spec-builder/src/main.rs index 013fbeccfe0d..3e8b1f4ea752 100644 --- a/bin/utils/chain-spec-builder/src/main.rs +++ b/bin/utils/chain-spec-builder/src/main.rs @@ -23,8 +23,8 @@ use std::{ }; use ansi_term::Style; +use clap::Parser; use rand::{distributions::Alphanumeric, rngs::OsRng, Rng}; -use structopt::StructOpt; use node_cli::chain_spec::{self, AccountId}; use sc_keystore::LocalKeystore; @@ -36,52 +36,52 @@ use sp_keystore::{SyncCryptoStore, SyncCryptoStorePtr}; /// A utility to easily create a testnet chain spec definition with a given set /// of authorities and endowed accounts and/or generate random accounts. -#[derive(StructOpt)] -#[structopt(rename_all = "kebab-case")] +#[derive(Parser)] +#[clap(rename_all = "kebab-case")] enum ChainSpecBuilder { /// Create a new chain spec with the given authorities, endowed and sudo /// accounts. New { /// Authority key seed. - #[structopt(long, short, required = true)] + #[clap(long, short, required = true)] authority_seeds: Vec, /// Active nominators (SS58 format), each backing a random subset of the aforementioned /// authorities. - #[structopt(long, short, default_value = "0")] + #[clap(long, short, default_value = "0")] nominator_accounts: Vec, /// Endowed account address (SS58 format). - #[structopt(long, short)] + #[clap(long, short)] endowed_accounts: Vec, /// Sudo account address (SS58 format). - #[structopt(long, short)] + #[clap(long, short)] sudo_account: String, /// The path where the chain spec should be saved. - #[structopt(long, short, default_value = "./chain_spec.json")] + #[clap(long, short, default_value = "./chain_spec.json")] chain_spec_path: PathBuf, }, /// Create a new chain spec with the given number of authorities and endowed /// accounts. Random keys will be generated as required. Generate { /// The number of authorities. - #[structopt(long, short)] + #[clap(long, short)] authorities: usize, /// The number of nominators backing the aforementioned authorities. /// /// Will nominate a random subset of `authorities`. - #[structopt(long, short, default_value = "0")] + #[clap(long, short, default_value = "0")] nominators: usize, /// The number of endowed accounts. - #[structopt(long, short, default_value = "0")] + #[clap(long, short, default_value = "0")] endowed: usize, /// The path where the chain spec should be saved. - #[structopt(long, short, default_value = "./chain_spec.json")] + #[clap(long, short, default_value = "./chain_spec.json")] chain_spec_path: PathBuf, /// Path to use when saving generated keystores for each authority. /// /// At this path, a new folder will be created for each authority's /// keystore named `auth-$i` where `i` is the authority index, i.e. /// `auth-0`, `auth-1`, etc. - #[structopt(long, short)] + #[clap(long, short)] keystore_path: Option, }, } @@ -236,13 +236,15 @@ fn main() -> Result<(), String> { the chain spec builder binary in `--release` mode.\n", ); - let builder = ChainSpecBuilder::from_args(); + let builder = ChainSpecBuilder::parse(); let chain_spec_path = builder.chain_spec_path().to_path_buf(); let (authority_seeds, nominator_accounts, endowed_accounts, sudo_account) = match builder { ChainSpecBuilder::Generate { authorities, nominators, endowed, keystore_path, .. } => { let authorities = authorities.max(1); - let rand_str = || -> String { OsRng.sample_iter(&Alphanumeric).take(32).collect() }; + let rand_str = || -> String { + OsRng.sample_iter(&Alphanumeric).take(32).map(char::from).collect() + }; let authority_seeds = (0..authorities).map(|_| rand_str()).collect::>(); let nominator_seeds = (0..nominators).map(|_| rand_str()).collect::>(); diff --git a/bin/utils/subkey/Cargo.toml b/bin/utils/subkey/Cargo.toml index d3c38edb5771..85f864cfbfc1 100644 --- a/bin/utils/subkey/Cargo.toml +++ b/bin/utils/subkey/Cargo.toml @@ -17,5 +17,5 @@ path = "src/main.rs" name = "subkey" [dependencies] +clap = { version = "3.0", features = ["derive"] } sc-cli = { version = "0.10.0-dev", path = "../../../client/cli" } -structopt = "0.3.25" diff --git a/bin/utils/subkey/src/lib.rs b/bin/utils/subkey/src/lib.rs index 9a33ef2d2d6d..73698db0b7ea 100644 --- a/bin/utils/subkey/src/lib.rs +++ b/bin/utils/subkey/src/lib.rs @@ -16,14 +16,14 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +use clap::Parser; use sc_cli::{ Error, GenerateCmd, GenerateNodeKeyCmd, InspectKeyCmd, InspectNodeKeyCmd, SignCmd, VanityCmd, VerifyCmd, }; -use structopt::StructOpt; -#[derive(Debug, StructOpt)] -#[structopt( +#[derive(Debug, Parser)] +#[clap( name = "subkey", author = "Parity Team ", about = "Utility for generating and restoring with Substrate keys" @@ -54,7 +54,7 @@ pub enum Subkey { /// Run the subkey command, given the appropriate runtime. pub fn run() -> Result<(), Error> { - match Subkey::from_args() { + match Subkey::parse() { Subkey::GenerateNodeKey(cmd) => cmd.run(), Subkey::Generate(cmd) => cmd.run(), Subkey::Inspect(cmd) => cmd.run(), diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index 01f5aab25d5f..a33b3e13af35 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -13,42 +13,41 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -log = "0.4.11" -regex = "1.5.4" -tokio = { version = "1.15", features = [ "signal", "rt-multi-thread" ] } -futures = "0.3.9" +chrono = "0.4.10" +clap = { version = "3.0", features = ["derive"] } fdlimit = "0.2.1" -libp2p = "0.40.0" -parity-scale-codec = "2.3.1" +futures = "0.3.9" hex = "0.4.2" +libp2p = "0.40.0" +log = "0.4.11" +names = { version = "0.12.0", default-features = false } rand = "0.7.3" -tiny-bip39 = "0.8.2" +regex = "1.5.4" +rpassword = "5.0.0" +serde = "1.0.132" serde_json = "1.0.74" -sc-keystore = { version = "4.0.0-dev", path = "../keystore" } -sp-panic-handler = { version = "4.0.0", path = "../../primitives/panic-handler" } +thiserror = "1.0.30" +tiny-bip39 = "0.8.2" +tokio = { version = "1.15", features = ["signal", "rt-multi-thread"] } + +parity-scale-codec = "2.3.1" sc-client-api = { version = "4.0.0-dev", path = "../api" } -sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } +sc-keystore = { version = "4.0.0-dev", path = "../keystore" } sc-network = { version = "0.10.0-dev", path = "../network" } -sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } -sc-utils = { version = "4.0.0-dev", path = "../utils" } -sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } -sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } -sp-keystore = { version = "0.10.0", path = "../../primitives/keystore" } sc-service = { version = "0.10.0-dev", default-features = false, path = "../service" } sc-telemetry = { version = "4.0.0-dev", path = "../telemetry" } -sp-keyring = { version = "4.1.0-dev", path = "../../primitives/keyring" } -names = { version = "0.12.0", default-features = false } -structopt = "0.3.25" sc-tracing = { version = "4.0.0-dev", path = "../tracing" } -chrono = "0.4.10" -serde = "1.0.132" -thiserror = "1.0.30" -rpassword = "5.0.0" +sc-utils = { version = "4.0.0-dev", path = "../utils" } +sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } +sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } +sp-keyring = { version = "4.1.0-dev", path = "../../primitives/keyring" } +sp-keystore = { version = "0.10.0", path = "../../primitives/keystore" } +sp-panic-handler = { version = "4.0.0", path = "../../primitives/panic-handler" } +sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } +sp-version = { version = "4.0.0-dev", path = "../../primitives/version" } [dev-dependencies] tempfile = "3.1.0" [features] -wasmtime = [ - "sc-service/wasmtime", -] +wasmtime = ["sc-service/wasmtime"] diff --git a/client/cli/src/arg_enums.rs b/client/cli/src/arg_enums.rs index c13361a9ac2b..249e3c639e4e 100644 --- a/client/cli/src/arg_enums.rs +++ b/client/cli/src/arg_enums.rs @@ -18,7 +18,7 @@ // NOTE: we allow missing docs here because arg_enum! creates the function variants without doc #![allow(missing_docs)] -use structopt::clap::arg_enum; +use clap::ArgEnum; /// How to execute Wasm runtime code. #[derive(Debug, Clone, Copy)] @@ -86,12 +86,11 @@ impl Into for WasmExecutionMethod { } } -arg_enum! { - #[allow(missing_docs)] - #[derive(Debug, Copy, Clone, PartialEq, Eq)] - pub enum TracingReceiver { - Log, - } +#[allow(missing_docs)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, ArgEnum)] +#[clap(rename_all = "PascalCase")] +pub enum TracingReceiver { + Log, } impl Into for TracingReceiver { @@ -102,44 +101,40 @@ impl Into for TracingReceiver { } } -arg_enum! { - #[allow(missing_docs)] - #[derive(Debug, Copy, Clone, PartialEq, Eq)] - pub enum NodeKeyType { - Ed25519 - } +#[allow(missing_docs)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, ArgEnum)] +#[clap(rename_all = "PascalCase")] +pub enum NodeKeyType { + Ed25519, } -arg_enum! { - #[derive(Debug, Copy, Clone, PartialEq, Eq)] - pub enum CryptoScheme { - Ed25519, - Sr25519, - Ecdsa, - } +#[derive(Debug, Copy, Clone, PartialEq, Eq, ArgEnum)] +#[clap(rename_all = "PascalCase")] +pub enum CryptoScheme { + Ed25519, + Sr25519, + Ecdsa, } -arg_enum! { - #[derive(Debug, Copy, Clone, PartialEq, Eq)] - pub enum OutputType { - Json, - Text, - } +#[derive(Debug, Copy, Clone, PartialEq, Eq, ArgEnum)] +#[clap(rename_all = "PascalCase")] +pub enum OutputType { + Json, + Text, } -arg_enum! { - /// How to execute blocks - #[derive(Debug, Clone, Copy, PartialEq, Eq)] - pub enum ExecutionStrategy { - // Execute with native build (if available, WebAssembly otherwise). - Native, - // Only execute with the WebAssembly build. - Wasm, - // Execute with both native (where available) and WebAssembly builds. - Both, - // Execute with the native build if possible; if it fails, then execute with WebAssembly. - NativeElseWasm, - } +/// How to execute blocks +#[derive(Debug, Copy, Clone, PartialEq, Eq, ArgEnum)] +#[clap(rename_all = "PascalCase")] +pub enum ExecutionStrategy { + // Execute with native build (if available, WebAssembly otherwise). + Native, + // Only execute with the WebAssembly build. + Wasm, + // Execute with both native (where available) and WebAssembly builds. + Both, + // Execute with the native build if possible; if it fails, then execute with WebAssembly. + NativeElseWasm, } impl Into for ExecutionStrategy { @@ -165,19 +160,18 @@ impl ExecutionStrategy { } } -arg_enum! { - /// Available RPC methods. - #[allow(missing_docs)] - #[derive(Debug, Copy, Clone, PartialEq)] - pub enum RpcMethods { - // Expose every RPC method only when RPC is listening on `localhost`, - // otherwise serve only safe RPC methods. - Auto, - // Allow only a safe subset of RPC methods. - Safe, - // Expose every RPC method (even potentially unsafe ones). - Unsafe, - } +/// Available RPC methods. +#[allow(missing_docs)] +#[derive(Debug, Copy, Clone, PartialEq, ArgEnum)] +#[clap(rename_all = "PascalCase")] +pub enum RpcMethods { + // Expose every RPC method only when RPC is listening on `localhost`, + // otherwise serve only safe RPC methods. + Auto, + // Allow only a safe subset of RPC methods. + Safe, + // Expose every RPC method (even potentially unsafe ones). + Unsafe, } impl Into for RpcMethods { @@ -225,31 +219,28 @@ impl Database { } } -arg_enum! { - /// Whether off-chain workers are enabled. - #[allow(missing_docs)] - #[derive(Debug, Clone)] - pub enum OffchainWorkerEnabled { - Always, - Never, - WhenValidating, - } +/// Whether off-chain workers are enabled. +#[allow(missing_docs)] +#[derive(Debug, Clone, ArgEnum)] +#[clap(rename_all = "PascalCase")] +pub enum OffchainWorkerEnabled { + Always, + Never, + WhenValidating, } -arg_enum! { - /// Syncing mode. - #[allow(missing_docs)] - #[derive(Debug, Clone, Copy)] - pub enum SyncMode { - // Full sync. Donwnload end verify all blocks. - Full, - // Download blocks without executing them. Download latest state with proofs. - Fast, - // Download blocks without executing them. Download latest state without proofs. - FastUnsafe, - // Prove finality and download the latest state. - Warp, - } +/// Syncing mode. +#[derive(Debug, Clone, Copy, ArgEnum)] +#[clap(rename_all = "PascalCase")] +pub enum SyncMode { + // Full sync. Donwnload end verify all blocks. + Full, + // Download blocks without executing them. Download latest state with proofs. + Fast, + // Download blocks without executing them. Download latest state without proofs. + FastUnsafe, + // Prove finality and download the latest state. + Warp, } impl Into for SyncMode { diff --git a/client/cli/src/commands/build_spec_cmd.rs b/client/cli/src/commands/build_spec_cmd.rs index ad7cf455eb3b..3196a3e7b915 100644 --- a/client/cli/src/commands/build_spec_cmd.rs +++ b/client/cli/src/commands/build_spec_cmd.rs @@ -21,6 +21,7 @@ use crate::{ params::{NodeKeyParams, SharedParams}, CliConfiguration, }; +use clap::Parser; use log::info; use sc_network::config::build_multiaddr; use sc_service::{ @@ -28,28 +29,27 @@ use sc_service::{ ChainSpec, }; use std::io::Write; -use structopt::StructOpt; /// The `build-spec` command used to build a specification. -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, Clone, Parser)] pub struct BuildSpecCmd { /// Force raw genesis storage output. - #[structopt(long = "raw")] + #[clap(long)] pub raw: bool, /// Disable adding the default bootnode to the specification. /// /// By default the `/ip4/127.0.0.1/tcp/30333/p2p/NODE_PEER_ID` bootnode is added to the /// specification when no bootnode exists. - #[structopt(long = "disable-default-bootnode")] + #[clap(long)] pub disable_default_bootnode: bool, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub shared_params: SharedParams, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub node_key_params: NodeKeyParams, } diff --git a/client/cli/src/commands/check_block_cmd.rs b/client/cli/src/commands/check_block_cmd.rs index b5642cf4b629..b7e69b1360a0 100644 --- a/client/cli/src/commands/check_block_cmd.rs +++ b/client/cli/src/commands/check_block_cmd.rs @@ -21,30 +21,30 @@ use crate::{ params::{BlockNumberOrHash, ImportParams, SharedParams}, CliConfiguration, }; +use clap::Parser; use sc_client_api::{BlockBackend, HeaderBackend}; use sp_runtime::traits::{Block as BlockT, Header as HeaderT}; use std::{fmt::Debug, str::FromStr, sync::Arc}; -use structopt::StructOpt; /// The `check-block` command used to validate blocks. -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, Clone, Parser)] pub struct CheckBlockCmd { /// Block hash or number - #[structopt(value_name = "HASH or NUMBER")] + #[clap(value_name = "HASH or NUMBER")] pub input: BlockNumberOrHash, /// The default number of 64KB pages to ever allocate for Wasm execution. /// /// Don't alter this unless you know what you're doing. - #[structopt(long = "default-heap-pages", value_name = "COUNT")] + #[clap(long, value_name = "COUNT")] pub default_heap_pages: Option, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub shared_params: SharedParams, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub import_params: ImportParams, } diff --git a/client/cli/src/commands/export_blocks_cmd.rs b/client/cli/src/commands/export_blocks_cmd.rs index af7de3c12e77..4e0e155dd51c 100644 --- a/client/cli/src/commands/export_blocks_cmd.rs +++ b/client/cli/src/commands/export_blocks_cmd.rs @@ -21,46 +21,46 @@ use crate::{ params::{DatabaseParams, GenericNumber, PruningParams, SharedParams}, CliConfiguration, }; +use clap::Parser; use log::info; use sc_client_api::{BlockBackend, UsageProvider}; use sc_service::{chain_ops::export_blocks, config::DatabaseSource}; use sp_runtime::traits::{Block as BlockT, Header as HeaderT}; use std::{fmt::Debug, fs, io, path::PathBuf, str::FromStr, sync::Arc}; -use structopt::StructOpt; /// The `export-blocks` command used to export blocks. -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, Clone, Parser)] pub struct ExportBlocksCmd { /// Output file name or stdout if unspecified. - #[structopt(parse(from_os_str))] + #[clap(parse(from_os_str))] pub output: Option, /// Specify starting block number. /// /// Default is 1. - #[structopt(long = "from", value_name = "BLOCK")] + #[clap(long, value_name = "BLOCK")] pub from: Option, /// Specify last block number. /// /// Default is best block. - #[structopt(long = "to", value_name = "BLOCK")] + #[clap(long, value_name = "BLOCK")] pub to: Option, /// Use binary output rather than JSON. - #[structopt(long)] + #[clap(long)] pub binary: bool, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub shared_params: SharedParams, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub pruning_params: PruningParams, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub database_params: DatabaseParams, } diff --git a/client/cli/src/commands/export_state_cmd.rs b/client/cli/src/commands/export_state_cmd.rs index b322265aee2b..4d67ab5d13c9 100644 --- a/client/cli/src/commands/export_state_cmd.rs +++ b/client/cli/src/commands/export_state_cmd.rs @@ -21,26 +21,26 @@ use crate::{ params::{BlockNumberOrHash, PruningParams, SharedParams}, CliConfiguration, }; +use clap::Parser; use log::info; use sc_client_api::{StorageProvider, UsageProvider}; use sp_runtime::traits::{Block as BlockT, Header as HeaderT}; use std::{fmt::Debug, io::Write, str::FromStr, sync::Arc}; -use structopt::StructOpt; /// The `export-state` command used to export the state of a given block into /// a chain spec. -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, Clone, Parser)] pub struct ExportStateCmd { /// Block hash or number. - #[structopt(value_name = "HASH or NUMBER")] + #[clap(value_name = "HASH or NUMBER")] pub input: Option, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub shared_params: SharedParams, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub pruning_params: PruningParams, } diff --git a/client/cli/src/commands/generate.rs b/client/cli/src/commands/generate.rs index ce4c24fc7d8c..9c1e5b689584 100644 --- a/client/cli/src/commands/generate.rs +++ b/client/cli/src/commands/generate.rs @@ -21,30 +21,30 @@ use crate::{ NetworkSchemeFlag, OutputTypeFlag, }; use bip39::{Language, Mnemonic, MnemonicType}; -use structopt::StructOpt; +use clap::Parser; /// The `generate` command -#[derive(Debug, StructOpt, Clone)] -#[structopt(name = "generate", about = "Generate a random account")] +#[derive(Debug, Clone, Parser)] +#[clap(name = "generate", about = "Generate a random account")] pub struct GenerateCmd { /// The number of words in the phrase to generate. One of 12 (default), 15, 18, 21 and 24. - #[structopt(long, short = "w", value_name = "WORDS")] + #[clap(short = 'w', long, value_name = "WORDS")] words: Option, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub keystore_params: KeystoreParams, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub network_scheme: NetworkSchemeFlag, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub output_scheme: OutputTypeFlag, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub crypto_scheme: CryptoSchemeFlag, } @@ -78,12 +78,11 @@ impl GenerateCmd { #[cfg(test)] mod tests { - use super::GenerateCmd; - use structopt::StructOpt; + use super::*; #[test] fn generate() { - let generate = GenerateCmd::from_iter(&["generate", "--password", "12345"]); + let generate = GenerateCmd::parse_from(&["generate", "--password", "12345"]); assert!(generate.run().is_ok()) } } diff --git a/client/cli/src/commands/generate_node_key.rs b/client/cli/src/commands/generate_node_key.rs index 2221c8a99ded..8c634dca9acf 100644 --- a/client/cli/src/commands/generate_node_key.rs +++ b/client/cli/src/commands/generate_node_key.rs @@ -18,13 +18,13 @@ //! Implementation of the `generate-node-key` subcommand use crate::Error; +use clap::Parser; use libp2p::identity::{ed25519 as libp2p_ed25519, PublicKey}; use std::{fs, path::PathBuf}; -use structopt::StructOpt; /// The `generate-node-key` command -#[derive(Debug, StructOpt)] -#[structopt( +#[derive(Debug, Parser)] +#[clap( name = "generate-node-key", about = "Generate a random node libp2p key, save it to \ file or print it to stdout and print its peer ID to stderr" @@ -33,7 +33,7 @@ pub struct GenerateNodeKeyCmd { /// Name of file to save secret key to. /// /// If not given, the secret key is printed to stdout. - #[structopt(long)] + #[clap(long)] file: Option, } @@ -66,7 +66,7 @@ mod tests { fn generate_node_key() { let mut file = Builder::new().prefix("keyfile").tempfile().unwrap(); let file_path = file.path().display().to_string(); - let generate = GenerateNodeKeyCmd::from_iter(&["generate-node-key", "--file", &file_path]); + let generate = GenerateNodeKeyCmd::parse_from(&["generate-node-key", "--file", &file_path]); assert!(generate.run().is_ok()); let mut buf = String::new(); assert!(file.read_to_string(&mut buf).is_ok()); diff --git a/client/cli/src/commands/import_blocks_cmd.rs b/client/cli/src/commands/import_blocks_cmd.rs index d0a0b39a5bf8..fece33ba23a2 100644 --- a/client/cli/src/commands/import_blocks_cmd.rs +++ b/client/cli/src/commands/import_blocks_cmd.rs @@ -21,6 +21,7 @@ use crate::{ params::{ImportParams, SharedParams}, CliConfiguration, }; +use clap::Parser; use sc_client_api::HeaderBackend; use sc_service::chain_ops::import_blocks; use sp_runtime::traits::Block as BlockT; @@ -31,31 +32,30 @@ use std::{ path::PathBuf, sync::Arc, }; -use structopt::StructOpt; /// The `import-blocks` command used to import blocks. -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct ImportBlocksCmd { /// Input file or stdin if unspecified. - #[structopt(parse(from_os_str))] + #[clap(parse(from_os_str))] pub input: Option, /// The default number of 64KB pages to ever allocate for Wasm execution. /// /// Don't alter this unless you know what you're doing. - #[structopt(long = "default-heap-pages", value_name = "COUNT")] + #[clap(long, value_name = "COUNT")] pub default_heap_pages: Option, /// Try importing blocks from binary format rather than JSON. - #[structopt(long)] + #[clap(long)] pub binary: bool, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub shared_params: SharedParams, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub import_params: ImportParams, } diff --git a/client/cli/src/commands/insert_key.rs b/client/cli/src/commands/insert_key.rs index cf40fb7ec4bf..852b4e50376f 100644 --- a/client/cli/src/commands/insert_key.rs +++ b/client/cli/src/commands/insert_key.rs @@ -20,42 +20,37 @@ use crate::{ utils, with_crypto_scheme, CryptoScheme, Error, KeystoreParams, SharedParams, SubstrateCli, }; +use clap::Parser; use sc_keystore::LocalKeystore; use sc_service::config::{BasePath, KeystoreConfig}; use sp_core::crypto::{KeyTypeId, SecretString}; use sp_keystore::{SyncCryptoStore, SyncCryptoStorePtr}; use std::{convert::TryFrom, sync::Arc}; -use structopt::StructOpt; /// The `insert` command -#[derive(Debug, StructOpt, Clone)] -#[structopt(name = "insert", about = "Insert a key to the keystore of a node.")] +#[derive(Debug, Clone, Parser)] +#[clap(name = "insert", about = "Insert a key to the keystore of a node.")] pub struct InsertKeyCmd { /// The secret key URI. /// If the value is a file, the file content is used as URI. /// If not given, you will be prompted for the URI. - #[structopt(long)] + #[clap(long)] suri: Option, /// Key type, examples: "gran", or "imon" - #[structopt(long)] + #[clap(long)] key_type: String, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub shared_params: SharedParams, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub keystore_params: KeystoreParams, /// The cryptography scheme that should be used to generate the key out of the given URI. - #[structopt( - long, - value_name = "SCHEME", - possible_values = &CryptoScheme::variants(), - case_insensitive = true, - )] + #[clap(long, value_name = "SCHEME", arg_enum, ignore_case = true)] pub scheme: CryptoScheme, } @@ -100,7 +95,6 @@ mod tests { use super::*; use sc_service::{ChainSpec, ChainType, GenericChainSpec, NoExtension}; use sp_core::{sr25519::Pair, ByteArray, Pair as _}; - use structopt::StructOpt; use tempfile::TempDir; struct Cli; @@ -156,7 +150,7 @@ mod tests { let path_str = format!("{}", path.path().display()); let (key, uri, _) = Pair::generate_with_phrase(None); - let inspect = InsertKeyCmd::from_iter(&[ + let inspect = InsertKeyCmd::parse_from(&[ "insert-key", "-d", &path_str, diff --git a/client/cli/src/commands/inspect_key.rs b/client/cli/src/commands/inspect_key.rs index 34f51dc5ec42..61fa8d2157e3 100644 --- a/client/cli/src/commands/inspect_key.rs +++ b/client/cli/src/commands/inspect_key.rs @@ -21,13 +21,13 @@ use crate::{ utils::{self, print_from_public, print_from_uri}, with_crypto_scheme, CryptoSchemeFlag, Error, KeystoreParams, NetworkSchemeFlag, OutputTypeFlag, }; +use clap::Parser; use sp_core::crypto::{ExposeSecret, SecretString, SecretUri, Ss58Codec}; use std::str::FromStr; -use structopt::StructOpt; /// The `inspect` command -#[derive(Debug, StructOpt)] -#[structopt( +#[derive(Debug, Parser)] +#[clap( name = "inspect", about = "Gets a public key and a SS58 address from the provided Secret URI" )] @@ -44,23 +44,23 @@ pub struct InspectKeyCmd { uri: Option, /// Is the given `uri` a hex encoded public key? - #[structopt(long)] + #[clap(long)] public: bool, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub keystore_params: KeystoreParams, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub network_scheme: NetworkSchemeFlag, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub output_scheme: OutputTypeFlag, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub crypto_scheme: CryptoSchemeFlag, /// Expect that `--uri` has the given public key/account-id. @@ -72,7 +72,7 @@ pub struct InspectKeyCmd { /// /// If there is no derivation in `--uri`, the public key will be checked against the public key /// of `--uri` directly. - #[structopt(long, conflicts_with = "public")] + #[clap(long, conflicts_with = "public")] pub expect_public: Option, } @@ -158,7 +158,6 @@ mod tests { use super::*; use sp_core::crypto::{ByteArray, Pair}; use sp_runtime::traits::IdentifyAccount; - use structopt::StructOpt; #[test] fn inspect() { @@ -166,10 +165,10 @@ mod tests { "remember fiber forum demise paper uniform squirrel feel access exclude casual effort"; let seed = "0xad1fb77243b536b90cfe5f0d351ab1b1ac40e3890b41dc64f766ee56340cfca5"; - let inspect = InspectKeyCmd::from_iter(&["inspect-key", words, "--password", "12345"]); + let inspect = InspectKeyCmd::parse_from(&["inspect-key", words, "--password", "12345"]); assert!(inspect.run().is_ok()); - let inspect = InspectKeyCmd::from_iter(&["inspect-key", seed]); + let inspect = InspectKeyCmd::parse_from(&["inspect-key", seed]); assert!(inspect.run().is_ok()); } @@ -177,14 +176,14 @@ mod tests { fn inspect_public_key() { let public = "0x12e76e0ae8ce41b6516cce52b3f23a08dcb4cfeed53c6ee8f5eb9f7367341069"; - let inspect = InspectKeyCmd::from_iter(&["inspect-key", "--public", public]); + let inspect = InspectKeyCmd::parse_from(&["inspect-key", "--public", public]); assert!(inspect.run().is_ok()); } #[test] fn inspect_with_expected_public_key() { let check_cmd = |seed, expected_public, success| { - let inspect = InspectKeyCmd::from_iter(&[ + let inspect = InspectKeyCmd::parse_from(&[ "inspect-key", "--expect-public", expected_public, diff --git a/client/cli/src/commands/inspect_node_key.rs b/client/cli/src/commands/inspect_node_key.rs index a5793873dd68..4c0798cc0635 100644 --- a/client/cli/src/commands/inspect_node_key.rs +++ b/client/cli/src/commands/inspect_node_key.rs @@ -18,23 +18,23 @@ //! Implementation of the `inspect-node-key` subcommand use crate::{Error, NetworkSchemeFlag}; +use clap::Parser; use libp2p::identity::{ed25519, PublicKey}; use std::{fs, path::PathBuf}; -use structopt::StructOpt; /// The `inspect-node-key` command -#[derive(Debug, StructOpt)] -#[structopt( +#[derive(Debug, Parser)] +#[clap( name = "inspect-node-key", about = "Print the peer ID corresponding to the node key in the given file." )] pub struct InspectNodeKeyCmd { /// Name of file to read the secret key from. - #[structopt(long)] + #[clap(long)] file: PathBuf, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub network_scheme: NetworkSchemeFlag, } @@ -63,11 +63,11 @@ mod tests { fn inspect_node_key() { let path = tempfile::tempdir().unwrap().into_path().join("node-id").into_os_string(); let path = path.to_str().unwrap(); - let cmd = GenerateNodeKeyCmd::from_iter(&["generate-node-key", "--file", path.clone()]); + let cmd = GenerateNodeKeyCmd::parse_from(&["generate-node-key", "--file", path.clone()]); assert!(cmd.run().is_ok()); - let cmd = InspectNodeKeyCmd::from_iter(&["inspect-node-key", "--file", path]); + let cmd = InspectNodeKeyCmd::parse_from(&["inspect-node-key", "--file", path]); assert!(cmd.run().is_ok()); } } diff --git a/client/cli/src/commands/key.rs b/client/cli/src/commands/key.rs index 0bfc68f8c32e..e0f3524196e2 100644 --- a/client/cli/src/commands/key.rs +++ b/client/cli/src/commands/key.rs @@ -17,16 +17,14 @@ //! Key related CLI utilities -use crate::{Error, SubstrateCli}; -use structopt::StructOpt; - use super::{ generate::GenerateCmd, generate_node_key::GenerateNodeKeyCmd, insert_key::InsertKeyCmd, inspect_key::InspectKeyCmd, inspect_node_key::InspectNodeKeyCmd, }; +use crate::{Error, SubstrateCli}; /// Key utilities for the cli. -#[derive(Debug, StructOpt)] +#[derive(Debug, clap::Subcommand)] pub enum KeySubcommand { /// Generate a random node libp2p key, save it to file or print it to stdout /// and print its peer ID to stderr. diff --git a/client/cli/src/commands/purge_chain_cmd.rs b/client/cli/src/commands/purge_chain_cmd.rs index eb19762df7d8..7dd7c1f5a5a5 100644 --- a/client/cli/src/commands/purge_chain_cmd.rs +++ b/client/cli/src/commands/purge_chain_cmd.rs @@ -21,27 +21,27 @@ use crate::{ params::{DatabaseParams, SharedParams}, CliConfiguration, }; +use clap::Parser; use sc_service::DatabaseSource; use std::{ fmt::Debug, fs, io::{self, Write}, }; -use structopt::StructOpt; /// The `purge-chain` command used to remove the whole chain. -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, Clone, Parser)] pub struct PurgeChainCmd { /// Skip interactive prompt by answering yes automatically. - #[structopt(short = "y")] + #[clap(short = 'y')] pub yes: bool, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub shared_params: SharedParams, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub database_params: DatabaseParams, } diff --git a/client/cli/src/commands/revert_cmd.rs b/client/cli/src/commands/revert_cmd.rs index a671469ba7fd..c207d198d5a2 100644 --- a/client/cli/src/commands/revert_cmd.rs +++ b/client/cli/src/commands/revert_cmd.rs @@ -21,25 +21,25 @@ use crate::{ params::{GenericNumber, PruningParams, SharedParams}, CliConfiguration, }; +use clap::Parser; use sc_client_api::{Backend, UsageProvider}; use sc_service::chain_ops::revert_chain; use sp_runtime::traits::{Block as BlockT, Header as HeaderT}; use std::{fmt::Debug, str::FromStr, sync::Arc}; -use structopt::StructOpt; /// The `revert` command used revert the chain to a previous state. -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct RevertCmd { /// Number of blocks to revert. - #[structopt(default_value = "256")] + #[clap(default_value = "256")] pub num: GenericNumber, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub shared_params: SharedParams, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub pruning_params: PruningParams, } diff --git a/client/cli/src/commands/run_cmd.rs b/client/cli/src/commands/run_cmd.rs index 08b8fd87e2c8..b9318813b048 100644 --- a/client/cli/src/commands/run_cmd.rs +++ b/client/cli/src/commands/run_cmd.rs @@ -25,6 +25,7 @@ use crate::{ }, CliConfiguration, }; +use clap::Parser; use regex::Regex; use sc_service::{ config::{BasePath, PrometheusConfig, TransactionPoolOptions}, @@ -32,26 +33,25 @@ use sc_service::{ }; use sc_telemetry::TelemetryEndpoints; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; -use structopt::StructOpt; /// The `run` command used to run a node. -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, Clone, Parser)] pub struct RunCmd { /// Enable validator mode. /// /// The node will be started with the authority role and actively /// participate in any consensus task that it can (e.g. depending on /// availability of local keys). - #[structopt(long)] + #[clap(long)] pub validator: bool, /// Disable GRANDPA voter when running in validator mode, otherwise disable the GRANDPA /// observer. - #[structopt(long)] + #[clap(long)] pub no_grandpa: bool, /// Experimental: Run in light client mode. - #[structopt(long = "light")] + #[clap(long)] pub light: bool, /// Listen to all RPC interfaces. @@ -60,13 +60,13 @@ pub struct RunCmd { /// proxy server to filter out dangerous methods. More details: /// . /// Use `--unsafe-rpc-external` to suppress the warning if you understand the risks. - #[structopt(long = "rpc-external")] + #[clap(long)] pub rpc_external: bool, /// Listen to all RPC interfaces. /// /// Same as `--rpc-external`. - #[structopt(long)] + #[clap(long)] pub unsafe_rpc_external: bool, /// RPC methods to expose. @@ -75,11 +75,11 @@ pub struct RunCmd { /// - `Safe`: Exposes only a safe subset of RPC methods, denying unsafe RPC methods. /// - `Auto`: Acts as `Safe` if RPC is served externally, e.g. when `--{rpc,ws}-external` is /// passed, otherwise acts as `Unsafe`. - #[structopt( + #[clap( long, value_name = "METHOD SET", - possible_values = &RpcMethods::variants(), - case_insensitive = true, + arg_enum, + ignore_case = true, default_value = "Auto", verbatim_doc_comment )] @@ -91,44 +91,44 @@ pub struct RunCmd { /// proxy server to filter out dangerous methods. More details: /// . /// Use `--unsafe-ws-external` to suppress the warning if you understand the risks. - #[structopt(long = "ws-external")] + #[clap(long)] pub ws_external: bool, /// Listen to all Websocket interfaces. /// /// Same as `--ws-external` but doesn't warn you about it. - #[structopt(long = "unsafe-ws-external")] + #[clap(long)] pub unsafe_ws_external: bool, /// Set the the maximum RPC payload size for both requests and responses (both http and ws), in /// megabytes. Default is 15MiB. - #[structopt(long = "rpc-max-payload")] + #[clap(long)] pub rpc_max_payload: Option, /// Expose Prometheus exporter on all interfaces. /// /// Default is local. - #[structopt(long = "prometheus-external")] + #[clap(long)] pub prometheus_external: bool, /// Specify IPC RPC server path - #[structopt(long = "ipc-path", value_name = "PATH")] + #[clap(long, value_name = "PATH")] pub ipc_path: Option, /// Specify HTTP RPC server TCP port. - #[structopt(long = "rpc-port", value_name = "PORT")] + #[clap(long, value_name = "PORT")] pub rpc_port: Option, /// Specify WebSockets RPC server TCP port. - #[structopt(long = "ws-port", value_name = "PORT")] + #[clap(long, value_name = "PORT")] pub ws_port: Option, /// Maximum number of WS RPC server connections. - #[structopt(long = "ws-max-connections", value_name = "COUNT")] + #[clap(long, value_name = "COUNT")] pub ws_max_connections: Option, /// Set the the maximum WebSocket output buffer size in MiB. Default is 16. - #[structopt(long = "ws-max-out-buffer-capacity")] + #[clap(long)] pub ws_max_out_buffer_capacity: Option, /// Specify browser Origins allowed to access the HTTP & WS RPC servers. @@ -137,29 +137,29 @@ pub struct RunCmd { /// value). Value of `all` will disable origin validation. Default is to /// allow localhost and origins. When running in /// --dev mode the default is to allow all origins. - #[structopt(long = "rpc-cors", value_name = "ORIGINS", parse(try_from_str = parse_cors))] + #[clap(long, value_name = "ORIGINS", parse(from_str = parse_cors))] pub rpc_cors: Option, /// Specify Prometheus exporter TCP Port. - #[structopt(long = "prometheus-port", value_name = "PORT")] + #[clap(long, value_name = "PORT")] pub prometheus_port: Option, /// Do not expose a Prometheus exporter endpoint. /// /// Prometheus metric endpoint is enabled by default. - #[structopt(long = "no-prometheus")] + #[clap(long)] pub no_prometheus: bool, /// The human-readable name for this node. /// /// The node name will be reported to the telemetry server, if enabled. - #[structopt(long = "name", value_name = "NAME")] + #[clap(long, value_name = "NAME")] pub name: Option, /// Disable connecting to the Substrate telemetry server. /// /// Telemetry is on by default on global chains. - #[structopt(long = "no-telemetry")] + #[clap(long)] pub no_telemetry: bool, /// The URL of the telemetry server to connect to. @@ -168,78 +168,78 @@ pub struct RunCmd { /// telemetry endpoints. Verbosity levels range from 0-9, with 0 denoting /// the least verbosity. /// Expected format is 'URL VERBOSITY', e.g. `--telemetry-url 'wss://foo/bar 0'`. - #[structopt(long = "telemetry-url", value_name = "URL VERBOSITY", parse(try_from_str = parse_telemetry_endpoints))] + #[clap(long = "telemetry-url", value_name = "URL VERBOSITY", parse(try_from_str = parse_telemetry_endpoints))] pub telemetry_endpoints: Vec<(String, u8)>, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub offchain_worker_params: OffchainWorkerParams, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub shared_params: SharedParams, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub import_params: ImportParams, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub network_params: NetworkParams, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub pool_config: TransactionPoolParams, /// Shortcut for `--name Alice --validator` with session keys for `Alice` added to keystore. - #[structopt(long, conflicts_with_all = &["bob", "charlie", "dave", "eve", "ferdie", "one", "two"])] + #[clap(long, conflicts_with_all = &["bob", "charlie", "dave", "eve", "ferdie", "one", "two"])] pub alice: bool, /// Shortcut for `--name Bob --validator` with session keys for `Bob` added to keystore. - #[structopt(long, conflicts_with_all = &["alice", "charlie", "dave", "eve", "ferdie", "one", "two"])] + #[clap(long, conflicts_with_all = &["alice", "charlie", "dave", "eve", "ferdie", "one", "two"])] pub bob: bool, /// Shortcut for `--name Charlie --validator` with session keys for `Charlie` added to /// keystore. - #[structopt(long, conflicts_with_all = &["alice", "bob", "dave", "eve", "ferdie", "one", "two"])] + #[clap(long, conflicts_with_all = &["alice", "bob", "dave", "eve", "ferdie", "one", "two"])] pub charlie: bool, /// Shortcut for `--name Dave --validator` with session keys for `Dave` added to keystore. - #[structopt(long, conflicts_with_all = &["alice", "bob", "charlie", "eve", "ferdie", "one", "two"])] + #[clap(long, conflicts_with_all = &["alice", "bob", "charlie", "eve", "ferdie", "one", "two"])] pub dave: bool, /// Shortcut for `--name Eve --validator` with session keys for `Eve` added to keystore. - #[structopt(long, conflicts_with_all = &["alice", "bob", "charlie", "dave", "ferdie", "one", "two"])] + #[clap(long, conflicts_with_all = &["alice", "bob", "charlie", "dave", "ferdie", "one", "two"])] pub eve: bool, /// Shortcut for `--name Ferdie --validator` with session keys for `Ferdie` added to keystore. - #[structopt(long, conflicts_with_all = &["alice", "bob", "charlie", "dave", "eve", "one", "two"])] + #[clap(long, conflicts_with_all = &["alice", "bob", "charlie", "dave", "eve", "one", "two"])] pub ferdie: bool, /// Shortcut for `--name One --validator` with session keys for `One` added to keystore. - #[structopt(long, conflicts_with_all = &["alice", "bob", "charlie", "dave", "eve", "ferdie", "two"])] + #[clap(long, conflicts_with_all = &["alice", "bob", "charlie", "dave", "eve", "ferdie", "two"])] pub one: bool, /// Shortcut for `--name Two --validator` with session keys for `Two` added to keystore. - #[structopt(long, conflicts_with_all = &["alice", "bob", "charlie", "dave", "eve", "ferdie", "one"])] + #[clap(long, conflicts_with_all = &["alice", "bob", "charlie", "dave", "eve", "ferdie", "one"])] pub two: bool, /// Enable authoring even when offline. - #[structopt(long = "force-authoring")] + #[clap(long)] pub force_authoring: bool, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub keystore_params: KeystoreParams, /// The size of the instances cache for each runtime. /// /// The default value is 8 and the values higher than 256 are ignored. - #[structopt(long)] + #[clap(long)] pub max_runtime_instances: Option, /// Maximum number of different runtimes that can be cached. - #[structopt(long, default_value = "2")] + #[clap(long, default_value = "2")] pub runtime_cache_size: u8, /// Run a temporary node. @@ -251,7 +251,7 @@ pub struct RunCmd { /// which includes: database, node key and keystore. /// /// When `--dev` is given and no explicit `--base-path`, this option is implied. - #[structopt(long, conflicts_with = "base-path")] + #[clap(long, conflicts_with = "base-path")] pub tmp: bool, } @@ -562,8 +562,7 @@ fn parse_telemetry_endpoints(s: &str) -> std::result::Result<(String, u8), Telem /// CORS setting /// -/// The type is introduced to overcome `Option>` -/// handling of `structopt`. +/// The type is introduced to overcome `Option>` handling of `clap`. #[derive(Clone, Debug)] pub enum Cors { /// All hosts allowed. @@ -582,7 +581,7 @@ impl From for Option> { } /// Parse cors origins. -fn parse_cors(s: &str) -> std::result::Result> { +fn parse_cors(s: &str) -> Cors { let mut is_all = false; let mut origins = Vec::new(); for part in s.split(',') { @@ -595,7 +594,11 @@ fn parse_cors(s: &str) -> std::result::Result> } } - Ok(if is_all { Cors::All } else { Cors::List(origins) }) + if is_all { + Cors::All + } else { + Cors::List(origins) + } } #[cfg(test)] diff --git a/client/cli/src/commands/sign.rs b/client/cli/src/commands/sign.rs index 8d331d799459..e0a5fce353ef 100644 --- a/client/cli/src/commands/sign.rs +++ b/client/cli/src/commands/sign.rs @@ -18,34 +18,34 @@ //! Implementation of the `sign` subcommand use crate::{error, utils, with_crypto_scheme, CryptoSchemeFlag, KeystoreParams}; +use clap::Parser; use sp_core::crypto::SecretString; -use structopt::StructOpt; /// The `sign` command -#[derive(Debug, StructOpt, Clone)] -#[structopt(name = "sign", about = "Sign a message, with a given (secret) key")] +#[derive(Debug, Clone, Parser)] +#[clap(name = "sign", about = "Sign a message, with a given (secret) key")] pub struct SignCmd { /// The secret key URI. /// If the value is a file, the file content is used as URI. /// If not given, you will be prompted for the URI. - #[structopt(long)] + #[clap(long)] suri: Option, /// Message to sign, if not provided you will be prompted to /// pass the message via STDIN - #[structopt(long)] + #[clap(long)] message: Option, /// The message on STDIN is hex-encoded data - #[structopt(long)] + #[clap(long)] hex: bool, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub keystore_params: KeystoreParams, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub crypto_scheme: CryptoSchemeFlag, } @@ -75,14 +75,13 @@ fn sign( #[cfg(test)] mod test { - use super::SignCmd; - use structopt::StructOpt; + use super::*; #[test] fn sign() { let seed = "0xad1fb77243b536b90cfe5f0d351ab1b1ac40e3890b41dc64f766ee56340cfca5"; - let sign = SignCmd::from_iter(&[ + let sign = SignCmd::parse_from(&[ "sign", "--suri", seed, diff --git a/client/cli/src/commands/vanity.rs b/client/cli/src/commands/vanity.rs index f2959a33dbfd..834b220df638 100644 --- a/client/cli/src/commands/vanity.rs +++ b/client/cli/src/commands/vanity.rs @@ -21,30 +21,30 @@ use crate::{ error, utils, with_crypto_scheme, CryptoSchemeFlag, NetworkSchemeFlag, OutputTypeFlag, }; +use clap::Parser; use rand::{rngs::OsRng, RngCore}; use sp_core::crypto::{unwrap_or_default_ss58_version, Ss58AddressFormat, Ss58Codec}; use sp_runtime::traits::IdentifyAccount; -use structopt::StructOpt; use utils::print_from_uri; /// The `vanity` command -#[derive(Debug, StructOpt, Clone)] -#[structopt(name = "vanity", about = "Generate a seed that provides a vanity address")] +#[derive(Debug, Clone, Parser)] +#[clap(name = "vanity", about = "Generate a seed that provides a vanity address")] pub struct VanityCmd { /// Desired pattern - #[structopt(long, parse(try_from_str = assert_non_empty_string))] + #[clap(long, parse(try_from_str = assert_non_empty_string))] pattern: String, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] network_scheme: NetworkSchemeFlag, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] output_scheme: OutputTypeFlag, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] crypto_scheme: CryptoSchemeFlag, } @@ -166,13 +166,12 @@ mod tests { crypto::{default_ss58_version, Ss58AddressFormatRegistry, Ss58Codec}, sr25519, Pair, }; - use structopt::StructOpt; #[cfg(feature = "bench")] use test::Bencher; #[test] fn vanity() { - let vanity = VanityCmd::from_iter(&["vanity", "--pattern", "j"]); + let vanity = VanityCmd::parse_from(&["vanity", "--pattern", "j"]); assert!(vanity.run().is_ok()); } diff --git a/client/cli/src/commands/verify.rs b/client/cli/src/commands/verify.rs index 9ffd5d9d4844..a8879f42caaf 100644 --- a/client/cli/src/commands/verify.rs +++ b/client/cli/src/commands/verify.rs @@ -19,12 +19,12 @@ //! implementation of the `verify` subcommand use crate::{error, utils, with_crypto_scheme, CryptoSchemeFlag}; +use clap::Parser; use sp_core::crypto::{ByteArray, Ss58Codec}; -use structopt::StructOpt; /// The `verify` command -#[derive(Debug, StructOpt, Clone)] -#[structopt( +#[derive(Debug, Clone, Parser)] +#[clap( name = "verify", about = "Verify a signature for a message, provided on STDIN, with a given (public or secret) key" )] @@ -39,15 +39,15 @@ pub struct VerifyCmd { /// Message to verify, if not provided you will be prompted to /// pass the message via STDIN - #[structopt(long)] + #[clap(long)] message: Option, /// The message on STDIN is hex-encoded data - #[structopt(long)] + #[clap(long)] hex: bool, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub crypto_scheme: CryptoSchemeFlag, } diff --git a/client/cli/src/error.rs b/client/cli/src/error.rs index 7f3bd84148d1..69b2eeaaf618 100644 --- a/client/cli/src/error.rs +++ b/client/cli/src/error.rs @@ -31,7 +31,7 @@ pub enum Error { Io(#[from] std::io::Error), #[error(transparent)] - Cli(#[from] structopt::clap::Error), + Cli(#[from] clap::Error), #[error(transparent)] Service(#[from] sc_service::Error), diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index 8760e955c69b..c242050dbf32 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -30,6 +30,8 @@ mod params; mod runner; pub use arg_enums::*; +pub use clap; +use clap::{AppSettings, FromArgMatches, IntoApp, Parser}; pub use commands::*; pub use config::*; pub use error::*; @@ -39,12 +41,6 @@ use sc_service::Configuration; pub use sc_service::{ChainSpec, Role}; pub use sc_tracing::logging::LoggerBuilder; pub use sp_version::RuntimeVersion; -use std::io::Write; -pub use structopt; -use structopt::{ - clap::{self, AppSettings}, - StructOpt, -}; /// Substrate client CLI /// @@ -103,7 +99,7 @@ pub trait SubstrateCli: Sized { /// error message and quit the program in case of failure. fn from_args() -> Self where - Self: StructOpt + Sized, + Self: Parser + Sized, { ::from_iter(&mut std::env::args_os()) } @@ -120,11 +116,11 @@ pub trait SubstrateCli: Sized { /// Print the error message and quit the program in case of failure. fn from_iter(iter: I) -> Self where - Self: StructOpt + Sized, + Self: Parser + Sized, I: IntoIterator, I::Item: Into + Clone, { - let app = ::clap(); + let app = ::into_app(); let mut full_version = Self::impl_version(); full_version.push_str("\n"); @@ -137,34 +133,15 @@ pub trait SubstrateCli: Sized { .author(author.as_str()) .about(about.as_str()) .version(full_version.as_str()) - .settings(&[ - AppSettings::GlobalVersion, - AppSettings::ArgsNegateSubcommands, - AppSettings::SubcommandsNegateReqs, - AppSettings::ColoredHelp, - ]); - - let matches = match app.get_matches_from_safe(iter) { - Ok(matches) => matches, - Err(mut e) => { - // To support pipes, we can not use `writeln!` as any error - // results in a "broken pipe" error. - // - // Instead we write directly to `stdout` and ignore any error - // as we exit afterwards anyway. - e.message.extend("\n".chars()); - - if e.use_stderr() { - let _ = std::io::stderr().write_all(e.message.as_bytes()); - std::process::exit(1); - } else { - let _ = std::io::stdout().write_all(e.message.as_bytes()); - std::process::exit(0); - } - }, - }; - - ::from_clap(&matches) + .setting( + AppSettings::PropagateVersion | + AppSettings::ArgsNegateSubcommands | + AppSettings::SubcommandsNegateReqs, + ); + + let matches = app.try_get_matches_from(iter).unwrap_or_else(|e| e.exit()); + + ::from_arg_matches(&matches).unwrap_or_else(|e| e.exit()) } /// Helper function used to parse the command line arguments. This is the equivalent of @@ -180,15 +157,15 @@ pub trait SubstrateCli: Sized { /// /// **NOTE:** This method WILL NOT exit when `--help` or `--version` (or short versions) are /// used. It will return a [`clap::Error`], where the [`clap::Error::kind`] is a - /// [`clap::ErrorKind::HelpDisplayed`] or [`clap::ErrorKind::VersionDisplayed`] respectively. + /// [`clap::ErrorKind::DisplayHelp`] or [`clap::ErrorKind::DisplayVersion`] respectively. /// You must call [`clap::Error::exit`] or perform a [`std::process::exit`]. fn try_from_iter(iter: I) -> clap::Result where - Self: StructOpt + Sized, + Self: Parser + Sized, I: IntoIterator, I::Item: Into + Clone, { - let app = ::clap(); + let app = ::into_app(); let mut full_version = Self::impl_version(); full_version.push_str("\n"); @@ -202,9 +179,9 @@ pub trait SubstrateCli: Sized { .about(about.as_str()) .version(full_version.as_str()); - let matches = app.get_matches_from_safe(iter)?; + let matches = app.try_get_matches_from(iter)?; - Ok(::from_clap(&matches)) + ::from_arg_matches(&matches) } /// Returns the client ID: `{impl_name}/v{impl_version}` diff --git a/client/cli/src/params/database_params.rs b/client/cli/src/params/database_params.rs index f034ae00473c..dd11c21f432b 100644 --- a/client/cli/src/params/database_params.rs +++ b/client/cli/src/params/database_params.rs @@ -17,24 +17,24 @@ // along with this program. If not, see . use crate::arg_enums::Database; +use clap::Args; use sc_service::TransactionStorageMode; -use structopt::StructOpt; /// Parameters for block import. -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, Clone, Args)] pub struct DatabaseParams { /// Select database backend to use. - #[structopt( + #[clap( long, alias = "db", value_name = "DB", - case_insensitive = true, - possible_values = &Database::variants(), + ignore_case = true, + possible_values = Database::variants(), )] pub database: Option, /// Limit the memory the database cache can use. - #[structopt(long = "db-cache", value_name = "MiB")] + #[clap(long = "db-cache", value_name = "MiB")] pub database_cache_size: Option, /// Enable storage chain mode @@ -43,7 +43,7 @@ pub struct DatabaseParams { /// If this is enabled, each transaction is stored separately in the /// transaction database column and is only referenced by hash /// in the block body column. - #[structopt(long)] + #[clap(long)] pub storage_chain: bool, } diff --git a/client/cli/src/params/import_params.rs b/client/cli/src/params/import_params.rs index 7e1478d71e3f..1ec79800136d 100644 --- a/client/cli/src/params/import_params.rs +++ b/client/cli/src/params/import_params.rs @@ -24,9 +24,9 @@ use crate::{ }, params::{DatabaseParams, PruningParams}, }; +use clap::Args; use sc_client_api::execution_extensions::ExecutionStrategies; use std::path::PathBuf; -use structopt::StructOpt; #[cfg(feature = "wasmtime")] const WASM_METHOD_DEFAULT: &str = "Compiled"; @@ -35,14 +35,14 @@ const WASM_METHOD_DEFAULT: &str = "Compiled"; const WASM_METHOD_DEFAULT: &str = "interpreted-i-know-what-i-do"; /// Parameters for block import. -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, Clone, Args)] pub struct ImportParams { #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub pruning_params: PruningParams, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub database_params: DatabaseParams, /// Force start with unsafe pruning settings. @@ -50,15 +50,15 @@ pub struct ImportParams { /// When running as a validator it is highly recommended to disable state /// pruning (i.e. 'archive') which is the default. The node will refuse to /// start as a validator if pruning is enabled unless this option is set. - #[structopt(long = "unsafe-pruning")] + #[clap(long)] pub unsafe_pruning: bool, /// Method for executing Wasm runtime code. - #[structopt( + #[clap( long = "wasm-execution", value_name = "METHOD", - possible_values = &WasmExecutionMethod::variants(), - case_insensitive = true, + possible_values = WasmExecutionMethod::variants(), + ignore_case = true, default_value = WASM_METHOD_DEFAULT )] pub wasm_method: WasmExecutionMethod, @@ -66,15 +66,15 @@ pub struct ImportParams { /// Specify the path where local WASM runtimes are stored. /// /// These runtimes will override on-chain runtimes when the version matches. - #[structopt(long, value_name = "PATH", parse(from_os_str))] + #[clap(long, value_name = "PATH", parse(from_os_str))] pub wasm_runtime_overrides: Option, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub execution_strategies: ExecutionStrategiesParams, /// Specify the state cache size. - #[structopt(long = "state-cache-size", value_name = "Bytes", default_value = "67108864")] + #[clap(long, value_name = "Bytes", default_value = "67108864")] pub state_cache_size: usize, } @@ -127,62 +127,37 @@ impl ImportParams { } /// Execution strategies parameters. -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, Clone, Args)] pub struct ExecutionStrategiesParams { /// The means of execution used when calling into the runtime for importing blocks as /// part of an initial sync. - #[structopt( - long = "execution-syncing", - value_name = "STRATEGY", - possible_values = &ExecutionStrategy::variants(), - case_insensitive = true, - )] + #[clap(long, value_name = "STRATEGY", arg_enum, ignore_case = true)] pub execution_syncing: Option, /// The means of execution used when calling into the runtime for general block import /// (including locally authored blocks). - #[structopt( - long = "execution-import-block", - value_name = "STRATEGY", - possible_values = &ExecutionStrategy::variants(), - case_insensitive = true, - )] + #[clap(long, value_name = "STRATEGY", arg_enum, ignore_case = true)] pub execution_import_block: Option, /// The means of execution used when calling into the runtime while constructing blocks. - #[structopt( - long = "execution-block-construction", - value_name = "STRATEGY", - possible_values = &ExecutionStrategy::variants(), - case_insensitive = true, - )] + #[clap(long, value_name = "STRATEGY", arg_enum, ignore_case = true)] pub execution_block_construction: Option, /// The means of execution used when calling into the runtime while using an off-chain worker. - #[structopt( - long = "execution-offchain-worker", - value_name = "STRATEGY", - possible_values = &ExecutionStrategy::variants(), - case_insensitive = true, - )] + #[clap(long, value_name = "STRATEGY", arg_enum, ignore_case = true)] pub execution_offchain_worker: Option, /// The means of execution used when calling into the runtime while not syncing, importing or /// constructing blocks. - #[structopt( - long = "execution-other", - value_name = "STRATEGY", - possible_values = &ExecutionStrategy::variants(), - case_insensitive = true, - )] + #[clap(long, value_name = "STRATEGY", arg_enum, ignore_case = true)] pub execution_other: Option, /// The execution strategy that should be used by all execution contexts. - #[structopt( - long = "execution", + #[clap( + long, value_name = "STRATEGY", - possible_values = &ExecutionStrategy::variants(), - case_insensitive = true, + arg_enum, + ignore_case = true, conflicts_with_all = &[ "execution-other", "execution-offchain-worker", diff --git a/client/cli/src/params/keystore_params.rs b/client/cli/src/params/keystore_params.rs index 5dbab5d9e8e3..72b09134f57a 100644 --- a/client/cli/src/params/keystore_params.rs +++ b/client/cli/src/params/keystore_params.rs @@ -17,50 +17,47 @@ // along with this program. If not, see . use crate::{error, error::Result}; +use clap::Args; use sc_service::config::KeystoreConfig; use sp_core::crypto::SecretString; use std::{ fs, path::{Path, PathBuf}, }; -use structopt::StructOpt; /// default sub directory for the key store const DEFAULT_KEYSTORE_CONFIG_PATH: &'static str = "keystore"; /// Parameters of the keystore -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, Clone, Args)] pub struct KeystoreParams { /// Specify custom URIs to connect to for keystore-services - #[structopt(long = "keystore-uri")] + #[clap(long)] pub keystore_uri: Option, /// Specify custom keystore path. - #[structopt(long = "keystore-path", value_name = "PATH", parse(from_os_str))] + #[clap(long, value_name = "PATH", parse(from_os_str))] pub keystore_path: Option, /// Use interactive shell for entering the password used by the keystore. - #[structopt( - long = "password-interactive", - conflicts_with_all = &[ "password", "password-filename" ] - )] + #[clap(long, conflicts_with_all = &["password", "password-filename"])] pub password_interactive: bool, /// Password used by the keystore. This allows appending an extra user-defined secret to the /// seed. - #[structopt( - long = "password", + #[clap( + long, parse(try_from_str = secret_string_from_str), - conflicts_with_all = &[ "password-interactive", "password-filename" ] + conflicts_with_all = &["password-interactive", "password-filename"] )] pub password: Option, /// File that contains the password used by the keystore. - #[structopt( - long = "password-filename", + #[clap( + long, value_name = "PATH", parse(from_os_str), - conflicts_with_all = &[ "password-interactive", "password" ] + conflicts_with_all = &["password-interactive", "password"] )] pub password_filename: Option, } diff --git a/client/cli/src/params/mod.rs b/client/cli/src/params/mod.rs index e6f81079263d..e0571aa4bbbf 100644 --- a/client/cli/src/params/mod.rs +++ b/client/cli/src/params/mod.rs @@ -26,13 +26,13 @@ mod shared_params; mod transaction_pool_params; use crate::arg_enums::{CryptoScheme, OutputType}; +use clap::Args; use sp_core::crypto::Ss58AddressFormat; use sp_runtime::{ generic::BlockId, traits::{Block as BlockT, NumberFor}, }; use std::{convert::TryFrom, fmt::Debug, str::FromStr}; -use structopt::StructOpt; pub use crate::params::{ database_params::*, import_params::*, keystore_params::*, network_params::*, @@ -115,44 +115,32 @@ impl BlockNumberOrHash { } /// Optional flag for specifying crypto algorithm -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, Clone, Args)] pub struct CryptoSchemeFlag { /// cryptography scheme - #[structopt( - long, - value_name = "SCHEME", - possible_values = &CryptoScheme::variants(), - case_insensitive = true, - default_value = "Sr25519" - )] + #[clap(long, value_name = "SCHEME", arg_enum, ignore_case = true, default_value = "Sr25519")] pub scheme: CryptoScheme, } /// Optional flag for specifying output type -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, Clone, Args)] pub struct OutputTypeFlag { /// output format - #[structopt( - long, - value_name = "FORMAT", - possible_values = &OutputType::variants(), - case_insensitive = true, - default_value = "Text" - )] + #[clap(long, value_name = "FORMAT", arg_enum, ignore_case = true, default_value = "Text")] pub output_type: OutputType, } /// Optional flag for specifying network scheme -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, Clone, Args)] pub struct NetworkSchemeFlag { /// network address format - #[structopt( + #[clap( + short = 'n', long, value_name = "NETWORK", - short = "n", possible_values = &Ss58AddressFormat::all_names()[..], + ignore_case = true, parse(try_from_str = Ss58AddressFormat::try_from), - case_insensitive = true, )] pub network: Option, } diff --git a/client/cli/src/params/network_params.rs b/client/cli/src/params/network_params.rs index 86060486144a..1de2896cba73 100644 --- a/client/cli/src/params/network_params.rs +++ b/client/cli/src/params/network_params.rs @@ -17,6 +17,7 @@ // along with this program. If not, see . use crate::{arg_enums::SyncMode, params::node_key_params::NodeKeyParams}; +use clap::Args; use sc_network::{ config::{ NetworkConfiguration, NodeKeyConfig, NonReservedPeerMode, SetConfig, TransportConfig, @@ -28,17 +29,16 @@ use sc_service::{ ChainSpec, ChainType, }; use std::{borrow::Cow, path::PathBuf}; -use structopt::StructOpt; /// Parameters used to create the network configuration. -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, Clone, Args)] pub struct NetworkParams { /// Specify a list of bootnodes. - #[structopt(long = "bootnodes", value_name = "ADDR")] + #[clap(long, value_name = "ADDR")] pub bootnodes: Vec, /// Specify a list of reserved node addresses. - #[structopt(long = "reserved-nodes", value_name = "ADDR")] + #[clap(long, value_name = "ADDR")] pub reserved_nodes: Vec, /// Whether to only synchronize the chain with reserved nodes. @@ -49,12 +49,12 @@ pub struct NetworkParams { /// In particular, if you are a validator your node might still connect to other /// validator nodes and collator nodes regardless of whether they are defined as /// reserved nodes. - #[structopt(long = "reserved-only")] + #[clap(long)] pub reserved_only: bool, /// The public address that other nodes will use to connect to it. /// This can be used if there's a proxy in front of this node. - #[structopt(long, value_name = "PUBLIC_ADDR")] + #[clap(long, value_name = "PUBLIC_ADDR")] pub public_addr: Vec, /// Listen on this multiaddress. @@ -62,60 +62,60 @@ pub struct NetworkParams { /// By default: /// If `--validator` is passed: `/ip4/0.0.0.0/tcp/` and `/ip6/[::]/tcp/`. /// Otherwise: `/ip4/0.0.0.0/tcp//ws` and `/ip6/[::]/tcp//ws`. - #[structopt(long = "listen-addr", value_name = "LISTEN_ADDR")] + #[clap(long, value_name = "LISTEN_ADDR")] pub listen_addr: Vec, /// Specify p2p protocol TCP port. - #[structopt(long = "port", value_name = "PORT", conflicts_with_all = &[ "listen-addr" ])] + #[clap(long, value_name = "PORT", conflicts_with_all = &[ "listen-addr" ])] pub port: Option, /// Always forbid connecting to private IPv4 addresses (as specified in /// [RFC1918](https://tools.ietf.org/html/rfc1918)), unless the address was passed with /// `--reserved-nodes` or `--bootnodes`. Enabled by default for chains marked as "live" in /// their chain specifications. - #[structopt(long = "no-private-ipv4", conflicts_with_all = &["allow-private-ipv4"])] + #[clap(long, conflicts_with_all = &["allow-private-ipv4"])] pub no_private_ipv4: bool, /// Always accept connecting to private IPv4 addresses (as specified in /// [RFC1918](https://tools.ietf.org/html/rfc1918)). Enabled by default for chains marked as /// "local" in their chain specifications, or when `--dev` is passed. - #[structopt(long = "allow-private-ipv4", conflicts_with_all = &["no-private-ipv4"])] + #[clap(long, conflicts_with_all = &["no-private-ipv4"])] pub allow_private_ipv4: bool, /// Specify the number of outgoing connections we're trying to maintain. - #[structopt(long = "out-peers", value_name = "COUNT", default_value = "25")] + #[clap(long, value_name = "COUNT", default_value = "25")] pub out_peers: u32, /// Maximum number of inbound full nodes peers. - #[structopt(long = "in-peers", value_name = "COUNT", default_value = "25")] + #[clap(long, value_name = "COUNT", default_value = "25")] pub in_peers: u32, /// Maximum number of inbound light nodes peers. - #[structopt(long = "in-peers-light", value_name = "COUNT", default_value = "100")] + #[clap(long, value_name = "COUNT", default_value = "100")] pub in_peers_light: u32, /// Disable mDNS discovery. /// /// By default, the network will use mDNS to discover other nodes on the /// local network. This disables it. Automatically implied when using --dev. - #[structopt(long = "no-mdns")] + #[clap(long)] pub no_mdns: bool, /// Maximum number of peers from which to ask for the same blocks in parallel. /// /// This allows downloading announced blocks from multiple peers. Decrease to save /// traffic and risk increased latency. - #[structopt(long = "max-parallel-downloads", value_name = "COUNT", default_value = "5")] + #[clap(long, value_name = "COUNT", default_value = "5")] pub max_parallel_downloads: u32, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub node_key_params: NodeKeyParams, /// Enable peer discovery on local networks. /// /// By default this option is `true` for `--dev` or when the chain type is /// `Local`/`Development` and false otherwise. - #[structopt(long)] + #[clap(long)] pub discover_local: bool, /// Require iterative Kademlia DHT queries to use disjoint paths for increased resiliency in @@ -123,11 +123,11 @@ pub struct NetworkParams { /// /// See the S/Kademlia paper for more information on the high level design as well as its /// security improvements. - #[structopt(long)] + #[clap(long)] pub kademlia_disjoint_query_paths: bool, /// Join the IPFS network and serve transactions over bitswap protocol. - #[structopt(long)] + #[clap(long)] pub ipfs_server: bool, /// Blockchain syncing mode. @@ -137,7 +137,7 @@ pub struct NetworkParams { /// - `Fast`: Download blocks and the latest state only. /// /// - `FastUnsafe`: Same as `Fast`, but skip downloading state proofs. - #[structopt(long, value_name = "SYNC_MODE", default_value = "Full")] + #[clap(long, arg_enum, value_name = "SYNC_MODE", default_value = "Full")] pub sync: SyncMode, } diff --git a/client/cli/src/params/node_key_params.rs b/client/cli/src/params/node_key_params.rs index 23f3fba1cdb0..f31fd854cbb5 100644 --- a/client/cli/src/params/node_key_params.rs +++ b/client/cli/src/params/node_key_params.rs @@ -16,10 +16,10 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +use clap::Args; use sc_network::config::{identity::ed25519, NodeKeyConfig}; use sp_core::H256; use std::{path::PathBuf, str::FromStr}; -use structopt::StructOpt; use crate::{arg_enums::NodeKeyType, error}; @@ -30,7 +30,7 @@ const NODE_KEY_ED25519_FILE: &str = "secret_ed25519"; /// Parameters used to create the `NodeKeyConfig`, which determines the keypair /// used for libp2p networking. -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, Clone, Args)] pub struct NodeKeyParams { /// The secret key to use for libp2p networking. /// @@ -46,7 +46,7 @@ pub struct NodeKeyParams { /// WARNING: Secrets provided as command-line arguments are easily exposed. /// Use of this option should be limited to development and testing. To use /// an externally managed secret key, use `--node-key-file` instead. - #[structopt(long = "node-key", value_name = "KEY")] + #[clap(long, value_name = "KEY")] pub node_key: Option, /// The type of secret key to use for libp2p networking. @@ -66,13 +66,7 @@ pub struct NodeKeyParams { /// /// The node's secret key determines the corresponding public key and hence the /// node's peer ID in the context of libp2p. - #[structopt( - long = "node-key-type", - value_name = "TYPE", - possible_values = &NodeKeyType::variants(), - case_insensitive = true, - default_value = "Ed25519" - )] + #[clap(long, value_name = "TYPE", arg_enum, ignore_case = true, default_value = "Ed25519")] pub node_key_type: NodeKeyType, /// The file from which to read the node's secret key to use for libp2p networking. @@ -85,7 +79,7 @@ pub struct NodeKeyParams { /// /// If the file does not exist, it is created with a newly generated secret key of /// the chosen type. - #[structopt(long = "node-key-file", value_name = "FILE")] + #[clap(long, value_name = "FILE")] pub node_key_file: Option, } @@ -128,14 +122,15 @@ fn parse_ed25519_secret(hex: &str) -> error::Result error::Result<()> { - NodeKeyType::variants().iter().try_for_each(|t| { - let node_key_type = NodeKeyType::from_str(t).unwrap(); + NodeKeyType::value_variants().iter().try_for_each(|t| { + let node_key_type = *t; let sk = match node_key_type { NodeKeyType::Ed25519 => ed25519::SecretKey::generate().as_ref().to_vec(), }; @@ -194,8 +189,8 @@ mod tests { where F: Fn(NodeKeyParams) -> error::Result<()>, { - NodeKeyType::variants().iter().try_for_each(|t| { - let node_key_type = NodeKeyType::from_str(t).unwrap(); + NodeKeyType::value_variants().iter().try_for_each(|t| { + let node_key_type = *t; f(NodeKeyParams { node_key_type, node_key: None, node_key_file: None }) }) } diff --git a/client/cli/src/params/offchain_worker_params.rs b/client/cli/src/params/offchain_worker_params.rs index ac71d3a7580e..3ab507f10859 100644 --- a/client/cli/src/params/offchain_worker_params.rs +++ b/client/cli/src/params/offchain_worker_params.rs @@ -23,23 +23,23 @@ //! targeted at handling input parameter parsing providing //! a reasonable abstraction. +use clap::Args; use sc_network::config::Role; use sc_service::config::OffchainWorkerConfig; -use structopt::StructOpt; use crate::{error, OffchainWorkerEnabled}; /// Offchain worker related parameters. -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, Clone, Args)] pub struct OffchainWorkerParams { /// Should execute offchain workers on every block. /// /// By default it's only enabled for nodes that are authoring new blocks. - #[structopt( + #[clap( long = "offchain-worker", value_name = "ENABLED", - possible_values = &OffchainWorkerEnabled::variants(), - case_insensitive = true, + arg_enum, + ignore_case = true, default_value = "WhenValidating" )] pub enabled: OffchainWorkerEnabled, @@ -48,7 +48,7 @@ pub struct OffchainWorkerParams { /// /// Enables a runtime to write directly to a offchain workers /// DB during block import. - #[structopt(long = "enable-offchain-indexing", value_name = "ENABLE_OFFCHAIN_INDEXING")] + #[clap(long = "enable-offchain-indexing", value_name = "ENABLE_OFFCHAIN_INDEXING")] pub indexing_enabled: bool, } diff --git a/client/cli/src/params/pruning_params.rs b/client/cli/src/params/pruning_params.rs index facf982ef8dd..a8516ee1453a 100644 --- a/client/cli/src/params/pruning_params.rs +++ b/client/cli/src/params/pruning_params.rs @@ -17,23 +17,23 @@ // along with this program. If not, see . use crate::error; +use clap::Args; use sc_service::{KeepBlocks, PruningMode, Role}; -use structopt::StructOpt; /// Parameters to define the pruning mode -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, Clone, Args)] pub struct PruningParams { /// Specify the state pruning mode, a number of blocks to keep or 'archive'. /// /// Default is to keep all block states if the node is running as a /// validator (i.e. 'archive'), otherwise state is only kept for the last /// 256 blocks. - #[structopt(long = "pruning", value_name = "PRUNING_MODE")] + #[clap(long, value_name = "PRUNING_MODE")] pub pruning: Option, /// Specify the number of finalized blocks to keep in the database. /// /// Default is to keep all blocks. - #[structopt(long, value_name = "COUNT")] + #[clap(long, value_name = "COUNT")] pub keep_blocks: Option, } diff --git a/client/cli/src/params/shared_params.rs b/client/cli/src/params/shared_params.rs index d385efad4278..a4f2271e12c4 100644 --- a/client/cli/src/params/shared_params.rs +++ b/client/cli/src/params/shared_params.rs @@ -17,36 +17,36 @@ // along with this program. If not, see . use crate::arg_enums::TracingReceiver; +use clap::Args; use sc_service::config::BasePath; use std::path::PathBuf; -use structopt::StructOpt; /// Shared parameters used by all `CoreParams`. -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, Clone, Args)] pub struct SharedParams { /// Specify the chain specification. /// /// It can be one of the predefined ones (dev, local, or staging) or it can be a path to a file /// with the chainspec (such as one exported by the `build-spec` subcommand). - #[structopt(long, value_name = "CHAIN_SPEC")] + #[clap(long, value_name = "CHAIN_SPEC")] pub chain: Option, /// Specify the development chain. /// /// This flag sets `--chain=dev`, `--force-authoring`, `--rpc-cors=all`, /// `--alice`, and `--tmp` flags, unless explicitly overridden. - #[structopt(long, conflicts_with_all = &["chain"])] + #[clap(long, conflicts_with_all = &["chain"])] pub dev: bool, /// Specify custom base path. - #[structopt(long, short = "d", value_name = "PATH", parse(from_os_str))] + #[clap(long, short = 'd', value_name = "PATH", parse(from_os_str))] pub base_path: Option, /// Sets a custom logging filter. Syntax is =, e.g. -lsync=debug. /// /// Log levels (least to most verbose) are error, warn, info, debug, and trace. /// By default, all targets log `info`. The global log level can be set with -l. - #[structopt(short = "l", long, value_name = "LOG_PATTERN")] + #[clap(short = 'l', long, value_name = "LOG_PATTERN")] pub log: Vec, /// Enable detailed log output. @@ -54,11 +54,11 @@ pub struct SharedParams { /// This includes displaying the log target, log level and thread name. /// /// This is automatically enabled when something is logged with any higher level than `info`. - #[structopt(long)] + #[clap(long)] pub detailed_log_output: bool, /// Disable log color output. - #[structopt(long)] + #[clap(long)] pub disable_log_color: bool, /// Enable feature to dynamically update and reload the log filter. @@ -68,21 +68,15 @@ pub struct SharedParams { /// /// The `system_addLogFilter` and `system_resetLogFilter` RPCs will have no effect with this /// option not being set. - #[structopt(long)] + #[clap(long)] pub enable_log_reloading: bool, /// Sets a custom profiling filter. Syntax is the same as for logging: = - #[structopt(long = "tracing-targets", value_name = "TARGETS")] + #[clap(long, value_name = "TARGETS")] pub tracing_targets: Option, /// Receiver to process tracing messages. - #[structopt( - long = "tracing-receiver", - value_name = "RECEIVER", - possible_values = &TracingReceiver::variants(), - case_insensitive = true, - default_value = "Log" - )] + #[clap(long, value_name = "RECEIVER", arg_enum, ignore_case = true, default_value = "Log")] pub tracing_receiver: TracingReceiver, } diff --git a/client/cli/src/params/transaction_pool_params.rs b/client/cli/src/params/transaction_pool_params.rs index dee8f57eb39c..efb78430ced5 100644 --- a/client/cli/src/params/transaction_pool_params.rs +++ b/client/cli/src/params/transaction_pool_params.rs @@ -16,18 +16,18 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +use clap::Args; use sc_service::config::TransactionPoolOptions; -use structopt::StructOpt; /// Parameters used to create the pool configuration. -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, Clone, Args)] pub struct TransactionPoolParams { /// Maximum number of transactions in the transaction pool. - #[structopt(long = "pool-limit", value_name = "COUNT", default_value = "8192")] + #[clap(long, value_name = "COUNT", default_value = "8192")] pub pool_limit: usize, /// Maximum number of kilobytes of all transactions stored in the pool. - #[structopt(long = "pool-kbytes", value_name = "COUNT", default_value = "20480")] + #[clap(long, value_name = "COUNT", default_value = "20480")] pub pool_kbytes: usize, } diff --git a/frame/bags-list/remote-tests/Cargo.toml b/frame/bags-list/remote-tests/Cargo.toml index d8797ad360ba..b5122ebbafe7 100644 --- a/frame/bags-list/remote-tests/Cargo.toml +++ b/frame/bags-list/remote-tests/Cargo.toml @@ -31,7 +31,5 @@ sp-std = { path = "../../../primitives/std", version = "4.0.0" } remote-externalities = { path = "../../../utils/frame/remote-externalities", version = "0.10.0-dev" } # others -tokio = { version = "1", features = ["macros"] } log = "0.4.14" -structopt = "0.3.25" -clap = "2.34.0" +tokio = { version = "1", features = ["macros"] } diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index 83228b9251dd..43f2b54044c9 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -21,10 +21,7 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"] log = { version = "0.4.11", default-features = false } serde = { version = "1.0.132", optional = true, features = ["derive"] } byteorder = { version = "1.3.2", default-features = false } -primitive-types = { version = "0.10.1", default-features = false, features = [ - "codec", - "scale-info" -] } +primitive-types = { version = "0.10.1", default-features = false, features = ["codec", "scale-info"] } impl-serde = { version = "0.3.0", optional = true } wasmi = { version = "0.9.1", optional = true } hash-db = { version = "0.15.2", default-features = false } @@ -43,19 +40,14 @@ sp-std = { version = "4.0.0", default-features = false, path = "../std" } sp-debug-derive = { version = "4.0.0", default-features = false, path = "../debug-derive" } sp-storage = { version = "4.0.0", default-features = false, path = "../storage" } sp-externalities = { version = "0.10.0", optional = true, path = "../externalities" } -parity-util-mem = { version = "0.10.2", default-features = false, features = [ - "primitive-types", -] } +parity-util-mem = { version = "0.10.2", default-features = false, features = ["primitive-types"] } futures = { version = "0.3.1", optional = true } dyn-clonable = { version = "0.9.0", optional = true } thiserror = { version = "1.0.30", optional = true } bitflags = "1.3" # full crypto -ed25519-dalek = { version = "1.0.1", default-features = false, features = [ - "u64_backend", - "alloc", -], optional = true } +ed25519-dalek = { version = "1.0.1", default-features = false, features = ["u64_backend", "alloc"], optional = true } blake2-rfc = { version = "0.2.18", default-features = false, optional = true } tiny-keccak = { version = "2.0.1", features = ["keccak"], optional = true } schnorrkel = { version = "0.9.1", features = [ @@ -67,7 +59,7 @@ hex = { version = "0.4", default-features = false, optional = true } twox-hash = { version = "1.6.2", default-features = false, optional = true } libsecp256k1 = { version = "0.7", default-features = false, features = ["hmac", "static-context"], optional = true } merlin = { version = "2.0", default-features = false, optional = true } -ss58-registry = { version = "1.10.0", default-features = false } +ss58-registry = { version = "1.11.0", default-features = false } sp-core-hashing = { version = "4.0.0", path = "./hashing", default-features = false, optional = true } sp-runtime-interface = { version = "4.1.0-dev", default-features = false, path = "../runtime-interface" } diff --git a/primitives/npos-elections/fuzzer/Cargo.toml b/primitives/npos-elections/fuzzer/Cargo.toml index 17423b624760..3b6103552e21 100644 --- a/primitives/npos-elections/fuzzer/Cargo.toml +++ b/primitives/npos-elections/fuzzer/Cargo.toml @@ -14,13 +14,14 @@ publish = false targets = ["x86_64-unknown-linux-gnu"] [dependencies] +clap = { version = "3.0", features = ["derive"] } +honggfuzz = "0.5" +rand = { version = "0.8", features = ["std", "small_rng"] } + codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } -honggfuzz = "0.5" -rand = { version = "0.7.3", features = ["std", "small_rng"] } sp-npos-elections = { version = "4.0.0-dev", path = ".." } sp-runtime = { version = "4.1.0-dev", path = "../../runtime" } -structopt = "0.3.25" [[bin]] name = "reduce" diff --git a/primitives/npos-elections/fuzzer/src/common.rs b/primitives/npos-elections/fuzzer/src/common.rs index 7ca66f72dd92..ab765d20640e 100644 --- a/primitives/npos-elections/fuzzer/src/common.rs +++ b/primitives/npos-elections/fuzzer/src/common.rs @@ -68,7 +68,7 @@ pub fn generate_random_npos_inputs( // always generate a sensible desired number of candidates: elections are uninteresting if we // desire 0 candidates, or a number of candidates >= the actual number of candidates present - let rounds = rng.gen_range(1, candidate_count); + let rounds = rng.gen_range(1..candidate_count); // candidates are easy: just a completely random set of IDs let mut candidates: Vec = Vec::with_capacity(candidate_count); @@ -95,7 +95,7 @@ pub fn generate_random_npos_inputs( let vote_weight = rng.gen(); // it's not interesting if a voter chooses 0 or all candidates, so rule those cases out. - let n_candidates_chosen = rng.gen_range(1, candidates.len()); + let n_candidates_chosen = rng.gen_range(1..candidates.len()); let mut chosen_candidates = Vec::with_capacity(n_candidates_chosen); chosen_candidates.extend(candidates.choose_multiple(&mut rng, n_candidates_chosen)); @@ -132,25 +132,25 @@ pub fn generate_random_npos_result( (1..=target_count).for_each(|acc| { candidates.push(acc); - let stake_var = rng.gen_range(ed, 100 * ed); + let stake_var = rng.gen_range(ed..100 * ed); stake_of.insert(acc, base_stake + stake_var); }); let mut voters = Vec::with_capacity(voter_count as usize); (prefix..=(prefix + voter_count)).for_each(|acc| { - let edge_per_this_voter = rng.gen_range(1, candidates.len()); + let edge_per_this_voter = rng.gen_range(1..candidates.len()); // all possible targets let mut all_targets = candidates.clone(); // we remove and pop into `targets` `edge_per_this_voter` times. let targets = (0..edge_per_this_voter) .map(|_| { let upper = all_targets.len() - 1; - let idx = rng.gen_range(0, upper); + let idx = rng.gen_range(0..upper); all_targets.remove(idx) }) .collect::>(); - let stake_var = rng.gen_range(ed, 100 * ed); + let stake_var = rng.gen_range(ed..100 * ed); let stake = base_stake + stake_var; stake_of.insert(acc, stake); voters.push((acc, stake, targets)); diff --git a/primitives/npos-elections/fuzzer/src/phragmen_pjr.rs b/primitives/npos-elections/fuzzer/src/phragmen_pjr.rs index 59763a58686d..2396fdfa3b40 100644 --- a/primitives/npos-elections/fuzzer/src/phragmen_pjr.rs +++ b/primitives/npos-elections/fuzzer/src/phragmen_pjr.rs @@ -42,7 +42,7 @@ use honggfuzz::fuzz; #[cfg(not(fuzzing))] -use structopt::StructOpt; +use clap::Parser; mod common; use common::{generate_random_npos_inputs, to_range}; @@ -67,24 +67,25 @@ fn main() { } #[cfg(not(fuzzing))] -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] +#[clap(author, version, about)] struct Opt { /// How many candidates participate in this election - #[structopt(short, long)] + #[clap(short, long)] candidates: Option, /// How many voters participate in this election - #[structopt(short, long)] + #[clap(short, long)] voters: Option, /// Random seed to use in this election - #[structopt(long)] + #[clap(long)] seed: Option, } #[cfg(not(fuzzing))] fn main() { - let opt = Opt::from_args(); + let opt = Opt::parse(); // candidates and voters by default use the maxima, which turn out to be one less than // the constant. iteration( diff --git a/primitives/npos-elections/fuzzer/src/reduce.rs b/primitives/npos-elections/fuzzer/src/reduce.rs index ad3f7dc260ef..a77b40ca56d5 100644 --- a/primitives/npos-elections/fuzzer/src/reduce.rs +++ b/primitives/npos-elections/fuzzer/src/reduce.rs @@ -79,8 +79,7 @@ fn generate_random_phragmen_assignment( let mut targets_to_chose_from = all_targets.clone(); let targets_to_chose = if edge_per_voter_var > 0 { rng.gen_range( - avg_edge_per_voter - edge_per_voter_var, - avg_edge_per_voter + edge_per_voter_var, + avg_edge_per_voter - edge_per_voter_var..avg_edge_per_voter + edge_per_voter_var, ) } else { avg_edge_per_voter @@ -89,11 +88,11 @@ fn generate_random_phragmen_assignment( let distribution = (0..targets_to_chose) .map(|_| { let target = - targets_to_chose_from.remove(rng.gen_range(0, targets_to_chose_from.len())); + targets_to_chose_from.remove(rng.gen_range(0..targets_to_chose_from.len())); if winners.iter().all(|w| *w != target) { winners.push(target.clone()); } - (target, rng.gen_range(1 * KSM, 100 * KSM)) + (target, rng.gen_range(1 * KSM..100 * KSM)) }) .collect::>(); diff --git a/utils/frame/benchmarking-cli/Cargo.toml b/utils/frame/benchmarking-cli/Cargo.toml index fa91956ec794..a7e5b76ad97a 100644 --- a/utils/frame/benchmarking-cli/Cargo.toml +++ b/utils/frame/benchmarking-cli/Cargo.toml @@ -25,7 +25,7 @@ sp-keystore = { version = "0.10.0", path = "../../../primitives/keystore" } sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } sp-state-machine = { version = "0.10.0", path = "../../../primitives/state-machine" } codec = { version = "2.0.0", package = "parity-scale-codec" } -structopt = "0.3.25" +clap = { version = "3.0", features = ["derive"] } chrono = "0.4" serde = "1.0.132" handlebars = "4.1.6" diff --git a/utils/frame/benchmarking-cli/src/lib.rs b/utils/frame/benchmarking-cli/src/lib.rs index 664e526ae0d7..6afaa2b249fc 100644 --- a/utils/frame/benchmarking-cli/src/lib.rs +++ b/utils/frame/benchmarking-cli/src/lib.rs @@ -28,124 +28,119 @@ fn parse_pallet_name(pallet: &str) -> String { } /// The `benchmark` command used to benchmark FRAME Pallets. -#[derive(Debug, structopt::StructOpt)] +#[derive(Debug, clap::Parser)] pub struct BenchmarkCmd { /// Select a FRAME Pallet to benchmark, or `*` for all (in which case `extrinsic` must be `*`). - #[structopt(short, long, parse(from_str = parse_pallet_name), required_unless = "list")] + #[clap(short, long, parse(from_str = parse_pallet_name), required_unless_present = "list")] pub pallet: Option, /// Select an extrinsic inside the pallet to benchmark, or `*` for all. - #[structopt(short, long, required_unless = "list")] + #[clap(short, long, required_unless_present = "list")] pub extrinsic: Option, /// Select how many samples we should take across the variable components. - #[structopt(short, long, default_value = "1")] + #[clap(short, long, default_value = "1")] pub steps: u32, /// Indicates lowest values for each of the component ranges. - #[structopt(long = "low", use_delimiter = true)] + #[clap(long = "low", use_delimiter = true)] pub lowest_range_values: Vec, /// Indicates highest values for each of the component ranges. - #[structopt(long = "high", use_delimiter = true)] + #[clap(long = "high", use_delimiter = true)] pub highest_range_values: Vec, /// Select how many repetitions of this benchmark should run from within the wasm. - #[structopt(short, long, default_value = "1")] + #[clap(short, long, default_value = "1")] pub repeat: u32, /// Select how many repetitions of this benchmark should run from the client. /// /// NOTE: Using this alone may give slower results, but will afford you maximum Wasm memory. - #[structopt(long, default_value = "1")] + #[clap(long, default_value = "1")] pub external_repeat: u32, /// Print the raw results. - #[structopt(long = "raw")] + #[clap(long = "raw")] pub raw_data: bool, /// Don't print the median-slopes linear regression analysis. - #[structopt(long)] + #[clap(long)] pub no_median_slopes: bool, /// Don't print the min-squares linear regression analysis. - #[structopt(long)] + #[clap(long)] pub no_min_squares: bool, /// Output the benchmarks to a Rust file at the given path. - #[structopt(long)] + #[clap(long)] pub output: Option, /// Add a header file to your outputted benchmarks - #[structopt(long)] + #[clap(long)] pub header: Option, /// Path to Handlebars template file used for outputting benchmark results. (Optional) - #[structopt(long)] + #[clap(long)] pub template: Option, /// Which analysis function to use when outputting benchmarks: /// * min-squares (default) /// * median-slopes /// * max (max of min squares and median slopes for each value) - #[structopt(long)] + #[clap(long)] pub output_analysis: Option, /// Set the heap pages while running benchmarks. If not set, the default value from the client /// is used. - #[structopt(long)] + #[clap(long)] pub heap_pages: Option, /// Disable verification logic when running benchmarks. - #[structopt(long)] + #[clap(long)] pub no_verify: bool, /// Display and run extra benchmarks that would otherwise not be needed for weight /// construction. - #[structopt(long)] + #[clap(long)] pub extra: bool, /// Estimate PoV size. - #[structopt(long)] + #[clap(long)] pub record_proof: bool, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub shared_params: sc_cli::SharedParams, /// The execution strategy that should be used for benchmarks - #[structopt( - long = "execution", - value_name = "STRATEGY", - possible_values = &ExecutionStrategy::variants(), - case_insensitive = true, - )] + #[clap(long, value_name = "STRATEGY", arg_enum, ignore_case = true)] pub execution: Option, /// Method for executing Wasm runtime code. - #[structopt( + #[clap( long = "wasm-execution", value_name = "METHOD", - possible_values = &WasmExecutionMethod::variants(), - case_insensitive = true, + possible_values = WasmExecutionMethod::variants(), + ignore_case = true, default_value = "compiled" )] pub wasm_method: WasmExecutionMethod, /// Limit the memory the database cache can use. - #[structopt(long = "db-cache", value_name = "MiB", default_value = "1024")] + #[clap(long = "db-cache", value_name = "MiB", default_value = "1024")] pub database_cache_size: u32, /// List the benchmarks that match your query rather than running them. /// /// When nothing is provided, we list all benchmarks. - #[structopt(long)] + #[clap(long)] pub list: bool, /// If enabled, the storage info is not displayed in the output next to the analysis. /// /// This is independent of the storage info appearing in the *output file*. Use a Handlebar /// template for that purpose. - #[structopt(long)] + #[clap(long)] pub no_storage_info: bool, } diff --git a/utils/frame/frame-utilities-cli/Cargo.toml b/utils/frame/frame-utilities-cli/Cargo.toml index d256bba4b5b3..f330b205ea27 100644 --- a/utils/frame/frame-utilities-cli/Cargo.toml +++ b/utils/frame/frame-utilities-cli/Cargo.toml @@ -11,10 +11,11 @@ documentation = "https://docs.rs/substrate-frame-cli" readme = "README.md" [dependencies] +clap = { version = "3.0", features = ["derive"] } + sp-core = { version = "4.1.0-dev", path = "../../../primitives/core" } sc-cli = { version = "0.10.0-dev", path = "../../../client/cli" } sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } -structopt = "0.3.25" frame-system = { version = "4.0.0-dev", path = "../../../frame/system" } frame-support = { version = "4.0.0-dev", path = "../../../frame/support" } diff --git a/utils/frame/frame-utilities-cli/src/pallet_id.rs b/utils/frame/frame-utilities-cli/src/pallet_id.rs index 2e139c639fd4..c39bee8b8746 100644 --- a/utils/frame/frame-utilities-cli/src/pallet_id.rs +++ b/utils/frame/frame-utilities-cli/src/pallet_id.rs @@ -17,6 +17,7 @@ //! Implementation of the `palletid` subcommand +use clap::Parser; use frame_support::PalletId; use sc_cli::{ utils::print_from_uri, with_crypto_scheme, CryptoSchemeFlag, Error, KeystoreParams, @@ -24,35 +25,34 @@ use sc_cli::{ }; use sp_core::crypto::{unwrap_or_default_ss58_version, Ss58AddressFormat, Ss58Codec}; use sp_runtime::traits::AccountIdConversion; -use structopt::StructOpt; /// The `palletid` command -#[derive(Debug, StructOpt)] -#[structopt(name = "palletid", about = "Inspect a module ID address")] +#[derive(Debug, Parser)] +#[clap(name = "palletid", about = "Inspect a module ID address")] pub struct PalletIdCmd { /// The module ID used to derive the account id: String, /// network address format - #[structopt( + #[clap( long, value_name = "NETWORK", possible_values = &Ss58AddressFormat::all_names()[..], parse(try_from_str = Ss58AddressFormat::try_from), - case_insensitive = true, + ignore_case = true, )] pub network: Option, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub output_scheme: OutputTypeFlag, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub crypto_scheme: CryptoSchemeFlag, #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub keystore_params: KeystoreParams, } diff --git a/utils/frame/generate-bags/Cargo.toml b/utils/frame/generate-bags/Cargo.toml index 594683938517..55670c96f792 100644 --- a/utils/frame/generate-bags/Cargo.toml +++ b/utils/frame/generate-bags/Cargo.toml @@ -23,4 +23,3 @@ sp-io = { version = "4.0.0", path = "../../../primitives/io" } chrono = { version = "0.4.19" } git2 = { version = "0.13.25", default-features = false } num-format = { version = "0.4.0" } -structopt = "0.3.25" diff --git a/utils/frame/generate-bags/node-runtime/Cargo.toml b/utils/frame/generate-bags/node-runtime/Cargo.toml index b5a7e0b898c9..11dee7b8b68e 100644 --- a/utils/frame/generate-bags/node-runtime/Cargo.toml +++ b/utils/frame/generate-bags/node-runtime/Cargo.toml @@ -14,4 +14,4 @@ node-runtime = { version = "3.0.0-dev", path = "../../../../bin/node/runtime" } generate-bags = { version = "4.0.0-dev", path = "../" } # third-party -structopt = "0.3.25" +clap = { version = "3.0", features = ["derive"] } diff --git a/utils/frame/generate-bags/node-runtime/src/main.rs b/utils/frame/generate-bags/node-runtime/src/main.rs index 72d1f0d8d22b..12bcf8d28cf2 100644 --- a/utils/frame/generate-bags/node-runtime/src/main.rs +++ b/utils/frame/generate-bags/node-runtime/src/main.rs @@ -17,30 +17,31 @@ //! Make the set of bag thresholds to be used with pallet-bags-list. +use clap::Parser; use generate_bags::generate_thresholds; use std::path::PathBuf; -use structopt::StructOpt; -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] +// #[clap(author, version, about)] struct Opt { /// How many bags to generate. - #[structopt(long, default_value = "200")] + #[clap(long, default_value = "200")] n_bags: usize, /// Where to write the output. output: PathBuf, /// The total issuance of the currency used to create `VoteWeight`. - #[structopt(short, long)] + #[clap(short, long)] total_issuance: u128, /// The minimum account balance (i.e. existential deposit) for the currency used to create /// `VoteWeight`. - #[structopt(short, long)] + #[clap(short, long)] minimum_balance: u128, } fn main() -> Result<(), std::io::Error> { - let Opt { n_bags, output, total_issuance, minimum_balance } = Opt::from_args(); + let Opt { n_bags, output, total_issuance, minimum_balance } = Opt::parse(); generate_thresholds::(n_bags, &output, total_issuance, minimum_balance) } diff --git a/utils/frame/try-runtime/cli/Cargo.toml b/utils/frame/try-runtime/cli/Cargo.toml index 2e214ec2307b..812310ff17d2 100644 --- a/utils/frame/try-runtime/cli/Cargo.toml +++ b/utils/frame/try-runtime/cli/Cargo.toml @@ -13,10 +13,11 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] +clap = { version = "3.0", features = ["derive"] } log = "0.4.8" parity-scale-codec = { version = "2.3.1" } serde = "1.0.132" -structopt = "0.3.25" +zstd = "0.9.0" sc-service = { version = "0.10.0-dev", default-features = false, path = "../../../../client/service" } sc-cli = { version = "0.10.0-dev", path = "../../../../client/cli" } @@ -31,6 +32,4 @@ sp-externalities = { version = "0.10.0", path = "../../../../primitives/external sp-version = { version = "4.0.0-dev", path = "../../../../primitives/version" } remote-externalities = { version = "0.10.0-dev", path = "../../remote-externalities" } -jsonrpsee = { version = "0.4.1", default-features = false, features = ["ws-client"]} - -zstd = "0.9.0" +jsonrpsee = { version = "0.4.1", default-features = false, features = ["ws-client"] } diff --git a/utils/frame/try-runtime/cli/src/commands/execute_block.rs b/utils/frame/try-runtime/cli/src/commands/execute_block.rs index 68c33b17b99d..b1a56f7e8f8e 100644 --- a/utils/frame/try-runtime/cli/src/commands/execute_block.rs +++ b/utils/frame/try-runtime/cli/src/commands/execute_block.rs @@ -26,25 +26,25 @@ use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor}; use std::{fmt::Debug, str::FromStr}; /// Configurations of the [`Command::ExecuteBlock`]. -#[derive(Debug, Clone, structopt::StructOpt)] +#[derive(Debug, Clone, clap::Parser)] pub struct ExecuteBlockCmd { /// Overwrite the wasm code in state or not. - #[structopt(long)] + #[clap(long)] overwrite_wasm_code: bool, /// If set, then the state root check is disabled by the virtue of calling into /// `TryRuntime_execute_block_no_check` instead of /// `Core_execute_block`. - #[structopt(long)] + #[clap(long)] no_check: bool, /// The block hash at which to fetch the block. /// /// If the `live` state type is being used, then this can be omitted, and is equal to whatever /// the `state::at` is. Only use this (with care) when combined with a snapshot. - #[structopt( + #[clap( long, - multiple = false, + multiple_values = false, parse(try_from_str = crate::parse::hash) )] block_at: Option, @@ -53,9 +53,9 @@ pub struct ExecuteBlockCmd { /// /// If the `live` state type is being used, then this can be omitted, and is equal to whatever /// the `state::uri` is. Only use this (with care) when combined with a snapshot. - #[structopt( + #[clap( long, - multiple = false, + multiple_values = false, parse(try_from_str = crate::parse::url) )] block_ws_uri: Option, @@ -65,7 +65,7 @@ pub struct ExecuteBlockCmd { /// For this command only, if the `live` is used, then state of the parent block is fetched. /// /// If `block_at` is provided, then the [`State::Live::at`] is being ignored. - #[structopt(subcommand)] + #[clap(subcommand)] state: State, } diff --git a/utils/frame/try-runtime/cli/src/commands/follow_chain.rs b/utils/frame/try-runtime/cli/src/commands/follow_chain.rs index 445756f9eed9..82bc04880106 100644 --- a/utils/frame/try-runtime/cli/src/commands/follow_chain.rs +++ b/utils/frame/try-runtime/cli/src/commands/follow_chain.rs @@ -35,14 +35,10 @@ const SUB: &'static str = "chain_subscribeFinalizedHeads"; const UN_SUB: &'static str = "chain_unsubscribeFinalizedHeads"; /// Configurations of the [`Command::FollowChain`]. -#[derive(Debug, Clone, structopt::StructOpt)] +#[derive(Debug, Clone, clap::Parser)] pub struct FollowChainCmd { /// The url to connect to. - #[structopt( - short, - long, - parse(try_from_str = parse::url), - )] + #[clap(short, long, parse(try_from_str = parse::url))] uri: String, } diff --git a/utils/frame/try-runtime/cli/src/commands/offchain_worker.rs b/utils/frame/try-runtime/cli/src/commands/offchain_worker.rs index 47af85560398..72136e9236de 100644 --- a/utils/frame/try-runtime/cli/src/commands/offchain_worker.rs +++ b/utils/frame/try-runtime/cli/src/commands/offchain_worker.rs @@ -28,19 +28,19 @@ use sp_runtime::traits::{Block as BlockT, Header, NumberFor}; use std::{fmt::Debug, str::FromStr}; /// Configurations of the [`Command::OffchainWorker`]. -#[derive(Debug, Clone, structopt::StructOpt)] +#[derive(Debug, Clone, clap::Parser)] pub struct OffchainWorkerCmd { /// Overwrite the wasm code in state or not. - #[structopt(long)] + #[clap(long)] overwrite_wasm_code: bool, /// The block hash at which to fetch the header. /// /// If the `live` state type is being used, then this can be omitted, and is equal to whatever /// the `state::at` is. Only use this (with care) when combined with a snapshot. - #[structopt( + #[clap( long, - multiple = false, + multiple_values = false, parse(try_from_str = parse::hash) )] header_at: Option, @@ -49,15 +49,15 @@ pub struct OffchainWorkerCmd { /// /// If the `live` state type is being used, then this can be omitted, and is equal to whatever /// the `state::uri` is. Only use this (with care) when combined with a snapshot. - #[structopt( + #[clap( long, - multiple = false, + multiple_values = false, parse(try_from_str = parse::url) )] header_ws_uri: Option, /// The state type to use. - #[structopt(subcommand)] + #[clap(subcommand)] pub state: State, } diff --git a/utils/frame/try-runtime/cli/src/commands/on_runtime_upgrade.rs b/utils/frame/try-runtime/cli/src/commands/on_runtime_upgrade.rs index 30e638217448..616498da0249 100644 --- a/utils/frame/try-runtime/cli/src/commands/on_runtime_upgrade.rs +++ b/utils/frame/try-runtime/cli/src/commands/on_runtime_upgrade.rs @@ -28,10 +28,10 @@ use crate::{ }; /// Configurations of the [`Command::OnRuntimeUpgrade`]. -#[derive(Debug, Clone, structopt::StructOpt)] +#[derive(Debug, Clone, clap::Parser)] pub struct OnRuntimeUpgradeCmd { /// The state type to use. - #[structopt(subcommand)] + #[clap(subcommand)] pub state: State, } diff --git a/utils/frame/try-runtime/cli/src/lib.rs b/utils/frame/try-runtime/cli/src/lib.rs index 32c814b0443d..9a016b2e5369 100644 --- a/utils/frame/try-runtime/cli/src/lib.rs +++ b/utils/frame/try-runtime/cli/src/lib.rs @@ -293,7 +293,7 @@ pub(crate) mod parse; pub(crate) const LOG_TARGET: &'static str = "try-runtime::cli"; /// Possible commands of `try-runtime`. -#[derive(Debug, Clone, structopt::StructOpt)] +#[derive(Debug, Clone, clap::Subcommand)] pub enum Command { /// Execute the migrations of the "local runtime". /// @@ -373,70 +373,64 @@ pub enum Command { } /// Shared parameters of the `try-runtime` commands -#[derive(Debug, Clone, structopt::StructOpt)] +#[derive(Debug, Clone, clap::Parser)] pub struct SharedParams { /// Shared parameters of substrate cli. #[allow(missing_docs)] - #[structopt(flatten)] + #[clap(flatten)] pub shared_params: sc_cli::SharedParams, /// The execution strategy that should be used. - #[structopt( - long = "execution", - value_name = "STRATEGY", - possible_values = &ExecutionStrategy::variants(), - case_insensitive = true, - default_value = "Wasm", - )] + #[clap(long, value_name = "STRATEGY", arg_enum, ignore_case = true, default_value = "Wasm")] pub execution: ExecutionStrategy, /// Type of wasm execution used. - #[structopt( + #[clap( long = "wasm-execution", value_name = "METHOD", - possible_values = &WasmExecutionMethod::variants(), - case_insensitive = true, + possible_values = WasmExecutionMethod::variants(), + ignore_case = true, default_value = "Compiled" )] pub wasm_method: WasmExecutionMethod, /// The number of 64KB pages to allocate for Wasm execution. Defaults to /// [`sc_service::Configuration.default_heap_pages`]. - #[structopt(long)] + #[clap(long)] pub heap_pages: Option, /// When enabled, the spec name check will not panic, and instead only show a warning. - #[structopt(long)] + #[clap(long)] pub no_spec_name_check: bool, } /// Our `try-runtime` command. /// /// See [`Command`] for more info. -#[derive(Debug, Clone, structopt::StructOpt)] +#[derive(Debug, Clone, clap::Parser)] pub struct TryRuntimeCmd { - #[structopt(flatten)] + #[clap(flatten)] pub shared: SharedParams, - #[structopt(subcommand)] + #[clap(subcommand)] pub command: Command, } /// The source of runtime *state* to use. -#[derive(Debug, Clone, structopt::StructOpt)] +#[derive(Debug, Clone, clap::Subcommand)] pub enum State { /// Use a state snapshot as the source of runtime state. /// /// This can be crated by passing a value to [`State::Live::snapshot_path`]. Snap { - #[structopt(short, long)] + #[clap(short, long)] snapshot_path: PathBuf, }, /// Use a live chain as the source of runtime state. Live { /// The url to connect to. - #[structopt( + #[clap( short, long, parse(try_from_str = parse::url), @@ -447,20 +441,20 @@ pub enum State { /// /// If non provided, then the latest finalized head is used. This is particularly useful /// for [`Command::OnRuntimeUpgrade`]. - #[structopt( + #[clap( short, long, - multiple = false, + multiple_values = false, parse(try_from_str = parse::hash), )] at: Option, /// An optional state snapshot file to WRITE to. Not written if set to `None`. - #[structopt(short, long)] + #[clap(short, long)] snapshot_path: Option, /// The pallets to scrape. If empty, entire chain state will be scraped. - #[structopt(short, long, require_delimiter = true)] + #[clap(short, long, require_delimiter = true)] pallets: Option>, /// Fetch the child-keys as well. @@ -468,7 +462,7 @@ pub enum State { /// Default is `false`, if specific `pallets` are specified, true otherwise. In other /// words, if you scrape the whole state the child tree data is included out of the box. /// Otherwise, it must be enabled explicitly using this flag. - #[structopt(long, require_delimiter = true)] + #[clap(long, require_delimiter = true)] child_tree: bool, }, } From 28819000207c9bcdf37e31d7d167cd1d420faa7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Mon, 24 Jan 2022 21:14:31 +0100 Subject: [PATCH 418/695] Pre-Charge max size when contracts access storage (#10691) * Fix seal_get_storage * Fix seal_take_storage * Add more benchmarks * cargo run --quiet --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_contracts --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/contracts/src/weights.rs --template=./.maintain/frame-weight-template.hbs * Fix seal_set_storage * Fix seal_contains_storage and seal_clear_storage * Fix benchmarks * cargo run --quiet --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_contracts --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/contracts/src/weights.rs --template=./.maintain/frame-weight-template.hbs * Get rid of mem::size_of in benchmarks * Fix up code loading * Apply suggestions from code review Co-authored-by: Hernando Castano * Fix test to call same function twice * Replaced u32::MAX by SENTINEL const * Fix seal_contains_storage benchmark * cargo run --quiet --profile=production --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_contracts --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/contracts/src/weights.rs --template=./.maintain/frame-weight-template.hbs Co-authored-by: Parity Bot Co-authored-by: Hernando Castano --- frame/contracts/src/benchmarking/mod.rs | 270 ++++- frame/contracts/src/chain_extension.rs | 2 +- frame/contracts/src/exec.rs | 22 +- frame/contracts/src/lib.rs | 10 +- frame/contracts/src/schedule.rs | 18 +- frame/contracts/src/storage.rs | 38 +- frame/contracts/src/tests.rs | 2 +- frame/contracts/src/wasm/code_cache.rs | 35 +- frame/contracts/src/wasm/mod.rs | 25 +- frame/contracts/src/wasm/runtime.rs | 142 ++- frame/contracts/src/weights.rs | 1331 ++++++++++++----------- 11 files changed, 1055 insertions(+), 840 deletions(-) diff --git a/frame/contracts/src/benchmarking/mod.rs b/frame/contracts/src/benchmarking/mod.rs index 6d4ae959f31e..3537af3d0cf7 100644 --- a/frame/contracts/src/benchmarking/mod.rs +++ b/frame/contracts/src/benchmarking/mod.rs @@ -35,7 +35,7 @@ use crate::{ storage::Storage, Pallet as Contracts, *, }; -use codec::Encode; +use codec::{Encode, MaxEncodedLen}; use frame_benchmarking::{account, benchmarks, whitelisted_caller}; use frame_support::weights::Weight; use frame_system::RawOrigin; @@ -778,9 +778,10 @@ benchmarks! { seal_set_storage { let r in 0 .. API_BENCHMARK_BATCHES; let keys = (0 .. r * API_BENCHMARK_BATCH_SIZE) - .flat_map(|n| T::Hashing::hash_of(&n).as_ref().to_vec()) + .map(|n| T::Hashing::hash_of(&n).as_ref().to_vec()) .collect::>(); - let key_len = sp_std::mem::size_of::<::Output>(); + let key_len = keys.get(0).map(|i| i.len() as u32).unwrap_or(0); + let key_bytes = keys.iter().flatten().cloned().collect::>(); let code = WasmModule::::from(ModuleDefinition { memory: Some(ImportedMemory::max::()), imported_functions: vec![ImportedFunction { @@ -792,7 +793,7 @@ benchmarks! { data_segments: vec![ DataSegment { offset: 0, - value: keys, + value: key_bytes, }, ], call_body: Some(body::repeated_dyn(r * API_BENCHMARK_BATCH_SIZE, vec![ @@ -805,13 +806,28 @@ benchmarks! { .. Default::default() }); let instance = Contract::::new(code, vec![])?; + let info = instance.info()?; + for key in keys { + Storage::::write( + &info.trie_id, + key.as_slice().try_into().map_err(|e| "Key has wrong length")?, + Some(vec![]), + None, + false, + ) + .map_err(|_| "Failed to write to storage during setup.")?; + } let origin = RawOrigin::Signed(instance.caller.clone()); }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) - seal_set_storage_per_kb { + #[skip_meta] + seal_set_storage_per_new_kb { let n in 0 .. T::Schedule::get().limits.payload_len / 1024; - let key = T::Hashing::hash_of(&1u32).as_ref().to_vec(); - let key_len = key.len(); + let keys = (0 .. API_BENCHMARK_BATCH_SIZE) + .map(|n| T::Hashing::hash_of(&n).as_ref().to_vec()) + .collect::>(); + let key_len = keys.get(0).map(|i| i.len() as u32).unwrap_or(0); + let key_bytes = keys.iter().flatten().cloned().collect::>(); let code = WasmModule::::from(ModuleDefinition { memory: Some(ImportedMemory::max::()), imported_functions: vec![ImportedFunction { @@ -823,19 +839,76 @@ benchmarks! { data_segments: vec![ DataSegment { offset: 0, - value: key, + value: key_bytes, }, ], - call_body: Some(body::repeated(API_BENCHMARK_BATCH_SIZE, &[ - Instruction::I32Const(0), // key_ptr - Instruction::I32Const(0), // value_ptr - Instruction::I32Const((n * 1024) as i32), // value_len - Instruction::Call(0), - Instruction::Drop, + call_body: Some(body::repeated_dyn(API_BENCHMARK_BATCH_SIZE, vec![ + Counter(0, key_len as u32), // key_ptr + Regular(Instruction::I32Const(0)), // value_ptr + Regular(Instruction::I32Const((n * 1024) as i32)), // value_len + Regular(Instruction::Call(0)), + Regular(Instruction::Drop), + ])), + .. Default::default() + }); + let instance = Contract::::new(code, vec![])?; + let info = instance.info()?; + for key in keys { + Storage::::write( + &info.trie_id, + key.as_slice().try_into().map_err(|e| "Key has wrong length")?, + Some(vec![]), + None, + false, + ) + .map_err(|_| "Failed to write to storage during setup.")?; + } + let origin = RawOrigin::Signed(instance.caller.clone()); + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + + #[skip_meta] + seal_set_storage_per_old_kb { + let n in 0 .. T::Schedule::get().limits.payload_len / 1024; + let keys = (0 .. API_BENCHMARK_BATCH_SIZE) + .map(|n| T::Hashing::hash_of(&n).as_ref().to_vec()) + .collect::>(); + let key_len = keys.get(0).map(|i| i.len() as u32).unwrap_or(0); + let key_bytes = keys.iter().flatten().cloned().collect::>(); + let code = WasmModule::::from(ModuleDefinition { + memory: Some(ImportedMemory::max::()), + imported_functions: vec![ImportedFunction { + module: "__unstable__", + name: "seal_set_storage", + params: vec![ValueType::I32, ValueType::I32, ValueType::I32], + return_type: Some(ValueType::I32), + }], + data_segments: vec![ + DataSegment { + offset: 0, + value: key_bytes, + }, + ], + call_body: Some(body::repeated_dyn(API_BENCHMARK_BATCH_SIZE, vec![ + Counter(0, key_len as u32), // key_ptr + Regular(Instruction::I32Const(0)), // value_ptr + Regular(Instruction::I32Const(0)), // value_len + Regular(Instruction::Call(0)), + Regular(Instruction::Drop), ])), .. Default::default() }); let instance = Contract::::new(code, vec![])?; + let info = instance.info()?; + for key in keys { + Storage::::write( + &info.trie_id, + key.as_slice().try_into().map_err(|e| "Key has wrong length")?, + Some(vec![42u8; (n * 1024) as usize]), + None, + false, + ) + .map_err(|_| "Failed to write to storage during setup.")?; + } let origin = RawOrigin::Signed(instance.caller.clone()); }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) @@ -849,7 +922,7 @@ benchmarks! { .map(|n| T::Hashing::hash_of(&n).as_ref().to_vec()) .collect::>(); let key_bytes = keys.iter().flatten().cloned().collect::>(); - let key_len = sp_std::mem::size_of::<::Output>(); + let key_len = keys.get(0).map(|i| i.len() as u32).unwrap_or(0); let code = WasmModule::::from(ModuleDefinition { memory: Some(ImportedMemory::max::()), imported_functions: vec![ImportedFunction { @@ -877,7 +950,7 @@ benchmarks! { Storage::::write( &info.trie_id, key.as_slice().try_into().map_err(|e| "Key has wrong length")?, - Some(vec![42; T::Schedule::get().limits.payload_len as usize]), + Some(vec![]), None, false, ) @@ -887,6 +960,50 @@ benchmarks! { let origin = RawOrigin::Signed(instance.caller.clone()); }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[skip_meta] + seal_clear_storage_per_kb { + let n in 0 .. T::Schedule::get().limits.payload_len / 1024; + let keys = (0 .. API_BENCHMARK_BATCH_SIZE) + .map(|n| T::Hashing::hash_of(&n).as_ref().to_vec()) + .collect::>(); + let key_len = keys.get(0).map(|i| i.len() as u32).unwrap_or(0); + let key_bytes = keys.iter().flatten().cloned().collect::>(); + let code = WasmModule::::from(ModuleDefinition { + memory: Some(ImportedMemory::max::()), + imported_functions: vec![ImportedFunction { + module: "__unstable__", + name: "seal_clear_storage", + params: vec![ValueType::I32], + return_type: Some(ValueType::I32), + }], + data_segments: vec![ + DataSegment { + offset: 0, + value: key_bytes, + }, + ], + call_body: Some(body::repeated_dyn(API_BENCHMARK_BATCH_SIZE, vec![ + Counter(0, key_len as u32), // key_ptr + Regular(Instruction::Call(0)), + Regular(Instruction::Drop), + ])), + .. Default::default() + }); + let instance = Contract::::new(code, vec![])?; + let info = instance.info()?; + for key in keys { + Storage::::write( + &info.trie_id, + key.as_slice().try_into().map_err(|e| "Key has wrong length")?, + Some(vec![42u8; (n * 1024) as usize]), + None, + false, + ) + .map_err(|_| "Failed to write to storage during setup.")?; + } + let origin = RawOrigin::Signed(instance.caller.clone()); + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + // We make sure that all storage accesses are to unique keys. #[skip_meta] seal_get_storage { @@ -894,7 +1011,7 @@ benchmarks! { let keys = (0 .. r * API_BENCHMARK_BATCH_SIZE) .map(|n| T::Hashing::hash_of(&n).as_ref().to_vec()) .collect::>(); - let key_len = sp_std::mem::size_of::<::Output>(); + let key_len = keys.get(0).map(|i| i.len() as u32).unwrap_or(0); let key_bytes = keys.iter().flatten().cloned().collect::>(); let key_bytes_len = key_bytes.len(); let code = WasmModule::::from(ModuleDefinition { @@ -940,6 +1057,58 @@ benchmarks! { let origin = RawOrigin::Signed(instance.caller.clone()); }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[skip_meta] + seal_get_storage_per_kb { + let n in 0 .. T::Schedule::get().limits.payload_len / 1024; + let keys = (0 .. API_BENCHMARK_BATCH_SIZE) + .map(|n| T::Hashing::hash_of(&n).as_ref().to_vec()) + .collect::>(); + let key_len = keys.get(0).map(|i| i.len() as u32).unwrap_or(0); + let key_bytes = keys.iter().flatten().cloned().collect::>(); + let key_bytes_len = key_bytes.len(); + let code = WasmModule::::from(ModuleDefinition { + memory: Some(ImportedMemory::max::()), + imported_functions: vec![ImportedFunction { + module: "seal0", + name: "seal_get_storage", + params: vec![ValueType::I32, ValueType::I32, ValueType::I32], + return_type: Some(ValueType::I32), + }], + data_segments: vec![ + DataSegment { + offset: 0, + value: key_bytes, + }, + DataSegment { + offset: key_bytes_len as u32, + value: T::Schedule::get().limits.payload_len.to_le_bytes().into(), + }, + ], + call_body: Some(body::repeated_dyn(API_BENCHMARK_BATCH_SIZE, vec![ + Counter(0, key_len as u32), // key_ptr + Regular(Instruction::I32Const((key_bytes_len + 4) as i32)), // out_ptr + Regular(Instruction::I32Const(key_bytes_len as i32)), // out_len_ptr + Regular(Instruction::Call(0)), + Regular(Instruction::Drop), + ])), + .. Default::default() + }); + let instance = Contract::::new(code, vec![])?; + let info = instance.info()?; + for key in keys { + Storage::::write( + &info.trie_id, + key.as_slice().try_into().map_err(|e| "Key has wrong length")?, + Some(vec![42u8; (n * 1024) as usize]), + None, + false, + ) + .map_err(|_| "Failed to write to storage during setup.")?; + } + >::insert(&instance.account_id, info.clone()); + let origin = RawOrigin::Signed(instance.caller.clone()); + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + // We make sure that all storage accesses are to unique keys. #[skip_meta] seal_contains_storage { @@ -947,7 +1116,7 @@ benchmarks! { let keys = (0 .. r * API_BENCHMARK_BATCH_SIZE) .map(|n| T::Hashing::hash_of(&n).as_ref().to_vec()) .collect::>(); - let key_len = sp_std::mem::size_of::<::Output>(); + let key_len = keys.get(0).map(|i| i.len() as u32).unwrap_or(0); let key_bytes = keys.iter().flatten().cloned().collect::>(); let key_bytes_len = key_bytes.len(); let code = WasmModule::::from(ModuleDefinition { @@ -977,7 +1146,7 @@ benchmarks! { Storage::::write( &info.trie_id, key.as_slice().try_into().map_err(|e| "Key has wrong length")?, - Some(vec![42; T::Schedule::get().limits.payload_len as usize]), + Some(vec![]), None, false, ) @@ -987,48 +1156,47 @@ benchmarks! { let origin = RawOrigin::Signed(instance.caller.clone()); }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) - seal_get_storage_per_kb { + #[skip_meta] + seal_contains_storage_per_kb { let n in 0 .. T::Schedule::get().limits.payload_len / 1024; - let key = T::Hashing::hash_of(&1u32).as_ref().to_vec(); - let key_len = key.len(); + let keys = (0 .. API_BENCHMARK_BATCH_SIZE) + .map(|n| T::Hashing::hash_of(&n).as_ref().to_vec()) + .collect::>(); + let key_len = keys.get(0).map(|i| i.len() as u32).unwrap_or(0); + let key_bytes = keys.iter().flatten().cloned().collect::>(); let code = WasmModule::::from(ModuleDefinition { memory: Some(ImportedMemory::max::()), imported_functions: vec![ImportedFunction { - module: "seal0", - name: "seal_get_storage", - params: vec![ValueType::I32, ValueType::I32, ValueType::I32], + module: "__unstable__", + name: "seal_contains_storage", + params: vec![ValueType::I32], return_type: Some(ValueType::I32), }], data_segments: vec![ DataSegment { offset: 0, - value: key.clone(), - }, - DataSegment { - offset: key_len as u32, - value: T::Schedule::get().limits.payload_len.to_le_bytes().into(), + value: key_bytes, }, ], - call_body: Some(body::repeated(API_BENCHMARK_BATCH_SIZE, &[ - // call at key_ptr - Instruction::I32Const(0), // key_ptr - Instruction::I32Const((key_len + 4) as i32), // out_ptr - Instruction::I32Const(key_len as i32), // out_len_ptr - Instruction::Call(0), - Instruction::Drop, + call_body: Some(body::repeated_dyn(API_BENCHMARK_BATCH_SIZE, vec![ + Counter(0, key_len as u32), // key_ptr + Regular(Instruction::Call(0)), + Regular(Instruction::Drop), ])), .. Default::default() }); let instance = Contract::::new(code, vec![])?; let info = instance.info()?; - Storage::::write( - &info.trie_id, - key.as_slice().try_into().map_err(|e| "Key has wrong length")?, - Some(vec![42u8; (n * 1024) as usize]), - None, - false, - ) - .map_err(|_| "Failed to write to storage during setup.")?; + for key in keys { + Storage::::write( + &info.trie_id, + key.as_slice().try_into().map_err(|e| "Key has wrong length")?, + Some(vec![42u8; (n * 1024) as usize]), + None, + false, + ) + .map_err(|_| "Failed to write to storage during setup.")?; + } >::insert(&instance.account_id, info.clone()); let origin = RawOrigin::Signed(instance.caller.clone()); }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) @@ -1039,7 +1207,7 @@ benchmarks! { let keys = (0 .. r * API_BENCHMARK_BATCH_SIZE) .map(|n| T::Hashing::hash_of(&n).as_ref().to_vec()) .collect::>(); - let key_len = sp_std::mem::size_of::<::Output>(); + let key_len = keys.get(0).map(|i| i.len() as u32).unwrap_or(0); let key_bytes = keys.iter().flatten().cloned().collect::>(); let key_bytes_len = key_bytes.len(); let code = WasmModule::::from(ModuleDefinition { @@ -1091,7 +1259,7 @@ benchmarks! { let keys = (0 .. API_BENCHMARK_BATCH_SIZE) .map(|n| T::Hashing::hash_of(&n).as_ref().to_vec()) .collect::>(); - let key_len = sp_std::mem::size_of::<::Output>(); + let key_len = keys.get(0).map(|i| i.len() as u32).unwrap_or(0); let key_bytes = keys.iter().flatten().cloned().collect::>(); let key_bytes_len = key_bytes.len(); let code = WasmModule::::from(ModuleDefinition { @@ -1238,7 +1406,7 @@ benchmarks! { Regular(Instruction::I32Const(value_len as i32)), // value_len Regular(Instruction::I32Const(0)), // input_data_ptr Regular(Instruction::I32Const(0)), // input_data_len - Regular(Instruction::I32Const(u32::max_value() as i32)), // output_ptr + Regular(Instruction::I32Const(SENTINEL as i32)), // output_ptr Regular(Instruction::I32Const(0)), // output_len_ptr Regular(Instruction::Call(0)), Regular(Instruction::Drop), @@ -1361,7 +1529,7 @@ benchmarks! { assert!(value > 0u32.into()); let value_bytes = value.encode(); let value_len = value_bytes.len(); - let addr_len = sp_std::mem::size_of::(); + let addr_len = T::AccountId::max_encoded_len(); // offsets where to place static data in contract memory let value_offset = 0; @@ -1415,7 +1583,7 @@ benchmarks! { Regular(Instruction::I32Const(0)), // input_data_len Regular(Instruction::I32Const(addr_offset as i32)), // address_ptr Regular(Instruction::I32Const(addr_len_offset as i32)), // address_len_ptr - Regular(Instruction::I32Const(u32::max_value() as i32)), // output_ptr + Regular(Instruction::I32Const(SENTINEL as i32)), // output_ptr Regular(Instruction::I32Const(0)), // output_len_ptr Regular(Instruction::I32Const(0)), // salt_ptr Regular(Instruction::I32Const(0)), // salt_ptr_len @@ -1485,7 +1653,7 @@ benchmarks! { assert!(value > 0u32.into()); let value_bytes = value.encode(); let value_len = value_bytes.len(); - let addr_len = sp_std::mem::size_of::(); + let addr_len = T::AccountId::max_encoded_len(); // offsets where to place static data in contract memory let input_offset = 0; diff --git a/frame/contracts/src/chain_extension.rs b/frame/contracts/src/chain_extension.rs index b0e08df3adbb..ed447719933b 100644 --- a/frame/contracts/src/chain_extension.rs +++ b/frame/contracts/src/chain_extension.rs @@ -329,7 +329,7 @@ where /// /// If the contract supplied buffer is smaller than the passed `buffer` an `Err` is returned. /// If `allow_skip` is set to true the contract is allowed to skip the copying of the buffer - /// by supplying the guard value of `u32::MAX` as `out_ptr`. The + /// by supplying the guard value of `pallet-contracts::SENTINEL` as `out_ptr`. The /// `weight_per_byte` is only charged when the write actually happens and is not skipped or /// failed due to a too small output buffer. pub fn write( diff --git a/frame/contracts/src/exec.rs b/frame/contracts/src/exec.rs index 679a6adde922..e4988eea51d0 100644 --- a/frame/contracts/src/exec.rs +++ b/frame/contracts/src/exec.rs @@ -24,7 +24,7 @@ use crate::{ use frame_support::{ dispatch::{DispatchError, DispatchResult, DispatchResultWithPostInfo, Dispatchable}, storage::{with_transaction, TransactionOutcome}, - traits::{Contains, Currency, ExistenceRequirement, Get, OriginTrait, Randomness, Time}, + traits::{Contains, Currency, ExistenceRequirement, OriginTrait, Randomness, Time}, weights::Weight, }; use frame_system::RawOrigin; @@ -140,11 +140,11 @@ pub trait Ext: sealing::Sealed { /// was deleted. fn get_storage(&mut self, key: &StorageKey) -> Option>; - /// Returns true iff some storage entry exists under the supplied `key` + /// Returns `Some(len)` (in bytes) if a storage item exists at `key`. /// - /// Returns `false` if the `key` wasn't previously set by `set_storage` or + /// Returns `None` if the `key` wasn't previously set by `set_storage` or /// was deleted. - fn contains_storage(&mut self, key: &StorageKey) -> bool; + fn get_storage_size(&mut self, key: &StorageKey) -> Option; /// Sets the storage entry by the given key to the specified value. If `value` is `None` then /// the storage entry is deleted. @@ -996,8 +996,8 @@ where Storage::::read(&self.top_frame_mut().contract_info().trie_id, key) } - fn contains_storage(&mut self, key: &StorageKey) -> bool { - Storage::::contains(&self.top_frame_mut().contract_info().trie_id, key) + fn get_storage_size(&mut self, key: &StorageKey) -> Option { + Storage::::size(&self.top_frame_mut().contract_info().trie_id, key) } fn set_storage( @@ -1056,7 +1056,7 @@ where } fn max_value_size(&self) -> u32 { - T::Schedule::get().limits.payload_len + self.schedule.limits.payload_len } fn get_weight_price(&self, weight: Weight) -> BalanceOf { @@ -2432,16 +2432,16 @@ mod tests { } #[test] - fn contains_storage_works() { + fn get_storage_size_works() { let code_hash = MockLoader::insert(Call, |ctx, _| { assert_eq!( ctx.ext.set_storage([1; 32], Some(vec![1, 2, 3]), false), Ok(WriteOutcome::New) ); assert_eq!(ctx.ext.set_storage([2; 32], Some(vec![]), false), Ok(WriteOutcome::New)); - assert_eq!(ctx.ext.contains_storage(&[1; 32]), true); - assert_eq!(ctx.ext.contains_storage(&[1; 32]), true); - assert_eq!(ctx.ext.contains_storage(&[3; 32]), false); + assert_eq!(ctx.ext.get_storage_size(&[1; 32]), Some(3)); + assert_eq!(ctx.ext.get_storage_size(&[2; 32]), Some(0)); + assert_eq!(ctx.ext.get_storage_size(&[3; 32]), None); exec_success() }); diff --git a/frame/contracts/src/lib.rs b/frame/contracts/src/lib.rs index e57b88c5d038..9f9cc09f6430 100644 --- a/frame/contracts/src/lib.rs +++ b/frame/contracts/src/lib.rs @@ -136,6 +136,14 @@ type BalanceOf = /// The current storage version. const STORAGE_VERSION: StorageVersion = StorageVersion::new(6); +/// Used as a sentinel value when reading and writing contract memory. +/// +/// It is usually used to signal `None` to a contract when only a primitive is allowed +/// and we don't want to go through encoding a full Rust type. Using `u32::Max` is a safe +/// sentinel because contracts are never allowed to use such a large amount of resources +/// that this value makes sense for a memory location or length. +const SENTINEL: u32 = u32::MAX; + /// Provides the contract address generation method. /// /// See [`DefaultAddressGenerator`] for the default implementation. @@ -831,7 +839,7 @@ where module: &mut PrefabWasmModule, schedule: &Schedule, ) -> frame_support::dispatch::DispatchResult { - self::wasm::reinstrument(module, schedule) + self::wasm::reinstrument(module, schedule).map(|_| ()) } /// Internal function that does the actual call. diff --git a/frame/contracts/src/schedule.rs b/frame/contracts/src/schedule.rs index 459bd950ce46..f8ca182aea58 100644 --- a/frame/contracts/src/schedule.rs +++ b/frame/contracts/src/schedule.rs @@ -316,15 +316,24 @@ pub struct HostFnWeights { /// Weight of calling `seal_set_storage`. pub set_storage: Weight, - /// Weight per byte of an item stored with `seal_set_storage`. - pub set_storage_per_byte: Weight, + /// Weight per written byten of an item stored with `seal_set_storage`. + pub set_storage_per_new_byte: Weight, + + /// Weight per overwritten byte of an item stored with `seal_set_storage`. + pub set_storage_per_old_byte: Weight, /// Weight of calling `seal_clear_storage`. pub clear_storage: Weight, + /// Weight of calling `seal_clear_storage` per byte of the stored item. + pub clear_storage_per_byte: Weight, + /// Weight of calling `seal_contains_storage`. pub contains_storage: Weight, + /// Weight of calling `seal_contains_storage` per byte of the stored item. + pub contains_storage_per_byte: Weight, + /// Weight of calling `seal_get_storage`. pub get_storage: Weight, @@ -586,9 +595,12 @@ impl Default for HostFnWeights { ), debug_message: cost_batched!(seal_debug_message), set_storage: cost_batched!(seal_set_storage), - set_storage_per_byte: cost_byte_batched!(seal_set_storage_per_kb), + set_storage_per_new_byte: cost_byte_batched!(seal_set_storage_per_new_kb), + set_storage_per_old_byte: cost_byte_batched!(seal_set_storage_per_old_kb), clear_storage: cost_batched!(seal_clear_storage), + clear_storage_per_byte: cost_byte_batched!(seal_clear_storage_per_kb), contains_storage: cost_batched!(seal_contains_storage), + contains_storage_per_byte: cost_byte_batched!(seal_contains_storage_per_kb), get_storage: cost_batched!(seal_get_storage), get_storage_per_byte: cost_byte_batched!(seal_get_storage_per_kb), take_storage: cost_batched!(seal_take_storage), diff --git a/frame/contracts/src/storage.rs b/frame/contracts/src/storage.rs index b84cd1d2538e..de65059b5b17 100644 --- a/frame/contracts/src/storage.rs +++ b/frame/contracts/src/storage.rs @@ -22,7 +22,7 @@ pub mod meter; use crate::{ exec::{AccountIdOf, StorageKey}, weights::WeightInfo, - BalanceOf, CodeHash, Config, ContractInfoOf, DeletionQueue, Error, TrieId, + BalanceOf, CodeHash, Config, ContractInfoOf, DeletionQueue, Error, TrieId, SENTINEL, }; use codec::{Decode, Encode}; use frame_support::{ @@ -87,6 +87,33 @@ pub enum WriteOutcome { Taken(Vec), } +impl WriteOutcome { + /// Extracts the size of the overwritten value or `0` if there + /// was no value in storage. + pub fn old_len(&self) -> u32 { + match self { + Self::New => 0, + Self::Overwritten(len) => *len, + Self::Taken(value) => value.len() as u32, + } + } + + /// Extracts the size of the overwritten value or `SENTINEL` if there + /// was no value in storage. + /// + /// # Note + /// + /// We cannot use `0` as sentinel value because there could be a zero sized + /// storage entry which is different from a non existing one. + pub fn old_len_with_sentinel(&self) -> u32 { + match self { + Self::New => SENTINEL, + Self::Overwritten(len) => *len, + Self::Taken(value) => value.len() as u32, + } + } +} + pub struct Storage(PhantomData); impl Storage @@ -102,9 +129,12 @@ where child::get_raw(&child_trie_info(trie_id), &blake2_256(key)) } - /// Returns `true` iff the `key` exists in storage. - pub fn contains(trie_id: &TrieId, key: &StorageKey) -> bool { - child::exists(&child_trie_info(trie_id), &blake2_256(key)) + /// Returns `Some(len)` (in bytes) if a storage item exists at `key`. + /// + /// Returns `None` if the `key` wasn't previously set by `set_storage` or + /// was deleted. + pub fn size(trie_id: &TrieId, key: &StorageKey) -> Option { + child::len(&child_trie_info(trie_id), &blake2_256(key)) } /// Update a storage entry into a contract's kv storage. diff --git a/frame/contracts/src/tests.rs b/frame/contracts/src/tests.rs index fd5c8cfd34ec..3d39bc6d78d9 100644 --- a/frame/contracts/src/tests.rs +++ b/frame/contracts/src/tests.rs @@ -294,7 +294,7 @@ pub const BOB: AccountId32 = AccountId32::new([2u8; 32]); pub const CHARLIE: AccountId32 = AccountId32::new([3u8; 32]); pub const DJANGO: AccountId32 = AccountId32::new([4u8; 32]); -pub const GAS_LIMIT: Weight = 10_000_000_000; +pub const GAS_LIMIT: Weight = 100_000_000_000; pub struct ExtBuilder { existential_deposit: u64, diff --git a/frame/contracts/src/wasm/code_cache.rs b/frame/contracts/src/wasm/code_cache.rs index e3fe48ac12c2..a48f9838837c 100644 --- a/frame/contracts/src/wasm/code_cache.rs +++ b/frame/contracts/src/wasm/code_cache.rs @@ -38,7 +38,6 @@ use crate::{ use frame_support::{ dispatch::{DispatchError, DispatchResult}, ensure, - storage::StorageMap, traits::ReservableCurrency, }; use sp_core::crypto::UncheckedFrom; @@ -149,52 +148,38 @@ pub fn load( where T::AccountId: UncheckedFrom + AsRef<[u8]>, { - gas_meter.charge(CodeToken::Load(estimate_code_size::, _>(&code_hash)?))?; + let charged = gas_meter.charge(CodeToken::Load(schedule.limits.code_len))?; let mut prefab_module = >::get(code_hash).ok_or_else(|| Error::::CodeNotFound)?; + gas_meter.adjust_gas(charged, CodeToken::Load(prefab_module.code.len() as u32)); prefab_module.code_hash = code_hash; if prefab_module.instruction_weights_version < schedule.instruction_weights.version { // The instruction weights have changed. // We need to re-instrument the code with the new instruction weights. - gas_meter.charge(CodeToken::Reinstrument(estimate_code_size::, _>( - &code_hash, - )?))?; - reinstrument(&mut prefab_module, schedule)?; + let charged = gas_meter.charge(CodeToken::Reinstrument(schedule.limits.code_len))?; + let code_size = reinstrument(&mut prefab_module, schedule)?; + gas_meter.adjust_gas(charged, CodeToken::Reinstrument(code_size)); } Ok(prefab_module) } /// Instruments the passed prefab wasm module with the supplied schedule. +/// +/// Returns the size in bytes of the uninstrumented code. pub fn reinstrument( prefab_module: &mut PrefabWasmModule, schedule: &Schedule, -) -> Result<(), DispatchError> { +) -> Result { let original_code = >::get(&prefab_module.code_hash).ok_or_else(|| Error::::CodeNotFound)?; + let original_code_len = original_code.len(); prefab_module.code = prepare::reinstrument_contract::(original_code, schedule)?; prefab_module.instruction_weights_version = schedule.instruction_weights.version; >::insert(&prefab_module.code_hash, &*prefab_module); - Ok(()) -} - -/// Get the size of the code stored at `code_hash` without loading it. -/// -/// The returned value is slightly too large when using it for the [`PrefabWasmModule`] -/// because it has other fields in addition to the code itself. However, those are negligible -/// when compared to the code size. Additionally, charging too much weight is completely safe. -fn estimate_code_size(code_hash: &CodeHash) -> Result -where - T: Config, - M: StorageMap, V>, - V: codec::FullCodec, -{ - let key = M::hashed_key_for(code_hash); - let mut data = [0u8; 0]; - let len = sp_io::storage::read(&key, &mut data, 0).ok_or_else(|| Error::::CodeNotFound)?; - Ok(len) + Ok(original_code_len as u32) } /// Costs for operations that are related to code handling. diff --git a/frame/contracts/src/wasm/mod.rs b/frame/contracts/src/wasm/mod.rs index ee778982cdbd..41e940bcd9b6 100644 --- a/frame/contracts/src/wasm/mod.rs +++ b/frame/contracts/src/wasm/mod.rs @@ -385,8 +385,8 @@ mod tests { fn get_storage(&mut self, key: &StorageKey) -> Option> { self.storage.get(key).cloned() } - fn contains_storage(&mut self, key: &StorageKey) -> bool { - self.storage.contains_key(key) + fn get_storage_size(&mut self, key: &StorageKey) -> Option { + self.storage.get(key).map(|val| val.len() as u32) } fn set_storage( &mut self, @@ -2023,7 +2023,7 @@ mod tests { // value did not exist before -> sentinel returned let input = ([1u8; 32], [42u8, 48]).encode(); let result = execute(CODE, input, &mut ext).unwrap(); - assert_eq!(u32::from_le_bytes(result.data.0.try_into().unwrap()), u32::MAX); + assert_eq!(u32::from_le_bytes(result.data.0.try_into().unwrap()), crate::SENTINEL); assert_eq!(ext.storage.get(&[1u8; 32]).unwrap(), &[42u8, 48]); // value do exist -> length of old value returned @@ -2083,7 +2083,7 @@ mod tests { // value does not exist -> sentinel returned let result = execute(CODE, [3u8; 32].encode(), &mut ext).unwrap(); - assert_eq!(u32::from_le_bytes(result.data.0.try_into().unwrap()), u32::MAX); + assert_eq!(u32::from_le_bytes(result.data.0.try_into().unwrap()), crate::SENTINEL); assert_eq!(ext.storage.get(&[3u8; 32]), None); // value did exist -> length returned @@ -2228,25 +2228,16 @@ mod tests { ext.storage.insert([1u8; 32], vec![42u8]); ext.storage.insert([2u8; 32], vec![]); - // value does not exist -> error returned + // value does not exist -> sentinel value returned let result = execute(CODE, [3u8; 32].encode(), &mut ext).unwrap(); - assert_eq!( - u32::from_le_bytes(result.data.0.try_into().unwrap()), - ReturnCode::KeyNotFound as u32 - ); + assert_eq!(u32::from_le_bytes(result.data.0.try_into().unwrap()), crate::SENTINEL); // value did exist -> success let result = execute(CODE, [1u8; 32].encode(), &mut ext).unwrap(); - assert_eq!( - u32::from_le_bytes(result.data.0.try_into().unwrap()), - ReturnCode::Success as u32 - ); + assert_eq!(u32::from_le_bytes(result.data.0.try_into().unwrap()), 1,); // value did exist -> success (zero sized type) let result = execute(CODE, [2u8; 32].encode(), &mut ext).unwrap(); - assert_eq!( - u32::from_le_bytes(result.data.0.try_into().unwrap()), - ReturnCode::Success as u32 - ); + assert_eq!(u32::from_le_bytes(result.data.0.try_into().unwrap()), 0,); } } diff --git a/frame/contracts/src/wasm/runtime.rs b/frame/contracts/src/wasm/runtime.rs index 98d9d9a40cda..13aa93430697 100644 --- a/frame/contracts/src/wasm/runtime.rs +++ b/frame/contracts/src/wasm/runtime.rs @@ -21,9 +21,8 @@ use crate::{ exec::{ExecError, ExecResult, Ext, StorageKey, TopicOf}, gas::{ChargedAmount, Token}, schedule::HostFnWeights, - storage::WriteOutcome, wasm::env_def::ConvertibleToWasm, - BalanceOf, CodeHash, Config, Error, + BalanceOf, CodeHash, Config, Error, SENTINEL, }; use bitflags::bitflags; use codec::{Decode, DecodeAll, Encode, MaxEncodedLen}; @@ -169,23 +168,18 @@ pub enum RuntimeCosts { DepositEvent { num_topic: u32, len: u32 }, /// Weight of calling `seal_debug_message`. DebugMessage, - /// Weight of calling `seal_set_storage` for the given storage item size. - SetStorage(u32), - /// Weight of calling `seal_clear_storage`. - ClearStorage, - /// Weight of calling `seal_contains_storage`. + /// Weight of calling `seal_set_storage` for the given storage item sizes. + SetStorage { old_bytes: u32, new_bytes: u32 }, + /// Weight of calling `seal_clear_storage` per cleared byte. + ClearStorage(u32), + /// Weight of calling `seal_contains_storage` per byte of the checked item. #[cfg(feature = "unstable-interface")] - ContainsStorage, - /// Weight of calling `seal_get_storage` without output weight. - GetStorageBase, - /// Weight of an item received via `seal_get_storage` for the given size. - GetStorageCopyOut(u32), - /// Weight of calling `seal_take_storage` without output weight. + ContainsStorage(u32), + /// Weight of calling `seal_get_storage` with the specified size in storage. + GetStorage(u32), + /// Weight of calling `seal_take_storage` for the given size. #[cfg(feature = "unstable-interface")] - TakeStorageBase, - /// Weight of an item received via `seal_take_storage` for the given size. - #[cfg(feature = "unstable-interface")] - TakeStorageCopyOut(u32), + TakeStorage(u32), /// Weight of calling `seal_transfer`. Transfer, /// Weight of calling `seal_call` for the given input size. @@ -249,17 +243,23 @@ impl RuntimeCosts { .saturating_add(s.deposit_event_per_topic.saturating_mul(num_topic.into())) .saturating_add(s.deposit_event_per_byte.saturating_mul(len.into())), DebugMessage => s.debug_message, - SetStorage(len) => - s.set_storage.saturating_add(s.set_storage_per_byte.saturating_mul(len.into())), - ClearStorage => s.clear_storage, - #[cfg(feature = "unstable-interface")] - ContainsStorage => s.contains_storage, - GetStorageBase => s.get_storage, - GetStorageCopyOut(len) => s.get_storage_per_byte.saturating_mul(len.into()), + SetStorage { new_bytes, old_bytes } => s + .set_storage + .saturating_add(s.set_storage_per_new_byte.saturating_mul(new_bytes.into())) + .saturating_add(s.set_storage_per_old_byte.saturating_mul(old_bytes.into())), + ClearStorage(len) => s + .clear_storage + .saturating_add(s.clear_storage_per_byte.saturating_mul(len.into())), #[cfg(feature = "unstable-interface")] - TakeStorageBase => s.take_storage, + ContainsStorage(len) => s + .contains_storage + .saturating_add(s.contains_storage_per_byte.saturating_mul(len.into())), + GetStorage(len) => + s.get_storage.saturating_add(s.get_storage_per_byte.saturating_mul(len.into())), #[cfg(feature = "unstable-interface")] - TakeStorageCopyOut(len) => s.take_storage_per_byte.saturating_mul(len.into()), + TakeStorage(len) => s + .take_storage + .saturating_add(s.take_storage_per_byte.saturating_mul(len.into())), Transfer => s.transfer, CallBase(len) => s.call.saturating_add(s.call_per_input_byte.saturating_mul(len.into())), @@ -534,7 +534,7 @@ where /// length of the buffer located at `out_ptr`. If that buffer is large enough the actual /// `buf.len()` is written to this location. /// - /// If `out_ptr` is set to the sentinel value of `u32::MAX` and `allow_skip` is true the + /// If `out_ptr` is set to the sentinel value of `SENTINEL` and `allow_skip` is true the /// operation is skipped and `Ok` is returned. This is supposed to help callers to make copying /// output optional. For example to skip copying back the output buffer of an `seal_call` /// when the caller is not interested in the result. @@ -553,7 +553,7 @@ where allow_skip: bool, create_token: impl FnOnce(u32) -> Option, ) -> Result<(), DispatchError> { - if allow_skip && out_ptr == u32::MAX { + if allow_skip && out_ptr == SENTINEL { return Ok(()) } @@ -648,48 +648,36 @@ where } } - /// Extracts the size of the overwritten value or `u32::MAX` if there - /// was no value in storage. - /// - /// # Note - /// - /// We cannot use `0` as sentinel value because there could be a zero sized - /// storage entry which is different from a non existing one. - fn overwritten_len(outcome: WriteOutcome) -> u32 { - match outcome { - WriteOutcome::New => u32::MAX, - WriteOutcome::Overwritten(len) => len, - WriteOutcome::Taken(value) => value.len() as u32, - } - } - fn set_storage( &mut self, key_ptr: u32, value_ptr: u32, value_len: u32, ) -> Result { - self.charge_gas(RuntimeCosts::SetStorage(value_len))?; - if value_len > self.ext.max_value_size() { + let max_size = self.ext.max_value_size(); + let charged = self + .charge_gas(RuntimeCosts::SetStorage { new_bytes: value_len, old_bytes: max_size })?; + if value_len > max_size { Err(Error::::ValueTooLarge)?; } let mut key: StorageKey = [0; 32]; self.read_sandbox_memory_into_buf(key_ptr, &mut key)?; let value = Some(self.read_sandbox_memory(value_ptr, value_len)?); - self.ext - .set_storage(key, value, false) - .map(Self::overwritten_len) - .map_err(Into::into) + let write_outcome = self.ext.set_storage(key, value, false)?; + self.adjust_gas( + charged, + RuntimeCosts::SetStorage { new_bytes: value_len, old_bytes: write_outcome.old_len() }, + ); + Ok(write_outcome.old_len_with_sentinel()) } fn clear_storage(&mut self, key_ptr: u32) -> Result { - self.charge_gas(RuntimeCosts::ClearStorage)?; + let charged = self.charge_gas(RuntimeCosts::ClearStorage(self.ext.max_value_size()))?; let mut key: StorageKey = [0; 32]; self.read_sandbox_memory_into_buf(key_ptr, &mut key)?; - self.ext - .set_storage(key, None, false) - .map(Self::overwritten_len) - .map_err(Into::into) + let outcome = self.ext.set_storage(key, None, false)?; + self.adjust_gas(charged, RuntimeCosts::ClearStorage(outcome.old_len())); + Ok(outcome.old_len_with_sentinel()) } fn call( @@ -827,7 +815,7 @@ define_env!(Env, , // # Return Value // // Returns the size of the pre-existing value at the specified key if any. Otherwise - // `u32::MAX` is returned as a sentinel value. + // `SENTINEL` is returned as a sentinel value. [__unstable__] seal_set_storage(ctx, key_ptr: u32, value_ptr: u32, value_len: u32) -> u32 => { ctx.set_storage(key_ptr, value_ptr, value_len) }, @@ -849,7 +837,7 @@ define_env!(Env, , // # Return Value // // Returns the size of the pre-existing value at the specified key if any. Otherwise - // `u32::MAX` is returned as a sentinel value. + // `SENTINEL` is returned as a sentinel value. [__unstable__] seal_clear_storage(ctx, key_ptr: u32) -> u32 => { ctx.clear_storage(key_ptr).map_err(Into::into) }, @@ -867,39 +855,39 @@ define_env!(Env, , // // `ReturnCode::KeyNotFound` [seal0] seal_get_storage(ctx, key_ptr: u32, out_ptr: u32, out_len_ptr: u32) -> ReturnCode => { - ctx.charge_gas(RuntimeCosts::GetStorageBase)?; + let charged = ctx.charge_gas(RuntimeCosts::GetStorage(ctx.ext.max_value_size()))?; let mut key: StorageKey = [0; 32]; ctx.read_sandbox_memory_into_buf(key_ptr, &mut key)?; if let Some(value) = ctx.ext.get_storage(&key) { - ctx.write_sandbox_output(out_ptr, out_len_ptr, &value, false, |len| { - Some(RuntimeCosts::GetStorageCopyOut(len)) - })?; + ctx.adjust_gas(charged, RuntimeCosts::GetStorage(value.len() as u32)); + ctx.write_sandbox_output(out_ptr, out_len_ptr, &value, false, already_charged)?; Ok(ReturnCode::Success) } else { + ctx.adjust_gas(charged, RuntimeCosts::GetStorage(0)); Ok(ReturnCode::KeyNotFound) } }, // Checks whether there is a value stored under the given key. // - // Returns `ReturnCode::Success` if there is a key in storage. Otherwise an error - // is returned. - // // # Parameters // // - `key_ptr`: pointer into the linear memory where the key of the requested value is placed. // - // # Errors + // # Return Value // - // `ReturnCode::KeyNotFound` - [__unstable__] seal_contains_storage(ctx, key_ptr: u32) -> ReturnCode => { - ctx.charge_gas(RuntimeCosts::ContainsStorage)?; + // Returns the size of the pre-existing value at the specified key if any. Otherwise + // `SENTINEL` is returned as a sentinel value. + [__unstable__] seal_contains_storage(ctx, key_ptr: u32) -> u32 => { + let charged = ctx.charge_gas(RuntimeCosts::ContainsStorage(ctx.ext.max_value_size()))?; let mut key: StorageKey = [0; 32]; ctx.read_sandbox_memory_into_buf(key_ptr, &mut key)?; - if ctx.ext.contains_storage(&key) { - Ok(ReturnCode::Success) + if let Some(len) = ctx.ext.get_storage_size(&key) { + ctx.adjust_gas(charged, RuntimeCosts::ContainsStorage(len)); + Ok(len) } else { - Ok(ReturnCode::KeyNotFound) + ctx.adjust_gas(charged, RuntimeCosts::ContainsStorage(0)); + Ok(SENTINEL) } }, @@ -916,15 +904,15 @@ define_env!(Env, , // // `ReturnCode::KeyNotFound` [__unstable__] seal_take_storage(ctx, key_ptr: u32, out_ptr: u32, out_len_ptr: u32) -> ReturnCode => { - ctx.charge_gas(RuntimeCosts::TakeStorageBase)?; + let charged = ctx.charge_gas(RuntimeCosts::TakeStorage(ctx.ext.max_value_size()))?; let mut key: StorageKey = [0; 32]; ctx.read_sandbox_memory_into_buf(key_ptr, &mut key)?; - if let WriteOutcome::Taken(value) = ctx.ext.set_storage(key, None, true)? { - ctx.write_sandbox_output(out_ptr, out_len_ptr, &value, false, |len| { - Some(RuntimeCosts::TakeStorageCopyOut(len)) - })?; + if let crate::storage::WriteOutcome::Taken(value) = ctx.ext.set_storage(key, None, true)? { + ctx.adjust_gas(charged, RuntimeCosts::TakeStorage(value.len() as u32)); + ctx.write_sandbox_output(out_ptr, out_len_ptr, &value, false, already_charged)?; Ok(ReturnCode::Success) } else { + ctx.adjust_gas(charged, RuntimeCosts::TakeStorage(0)); Ok(ReturnCode::KeyNotFound) } }, @@ -1006,7 +994,7 @@ define_env!(Env, , // // The callees output buffer is copied to `output_ptr` and its length to `output_len_ptr`. // The copy of the output buffer can be skipped by supplying the sentinel value - // of `u32::MAX` to `output_ptr`. + // of `SENTINEL` to `output_ptr`. // // # Parameters // @@ -1103,7 +1091,7 @@ define_env!(Env, , // by the code hash. The address of this new account is copied to `address_ptr` and its length // to `address_len_ptr`. The constructors output buffer is copied to `output_ptr` and its // length to `output_len_ptr`. The copy of the output buffer and address can be skipped by - // supplying the sentinel value of `u32::MAX` to `output_ptr` or `address_ptr`. + // supplying the sentinel value of `SENTINEL` to `output_ptr` or `address_ptr`. // // `value` must be at least the minimum balance. Otherwise the instantiation fails and the // contract is not created. diff --git a/frame/contracts/src/weights.rs b/frame/contracts/src/weights.rs index 655cba5d3b9a..2d74df9627db 100644 --- a/frame/contracts/src/weights.rs +++ b/frame/contracts/src/weights.rs @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_contracts //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-17, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-01-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/lto-fat-cg1/substrate +// target/production/substrate // benchmark // --chain=dev // --steps=50 @@ -33,9 +33,7 @@ // --wasm-execution=compiled // --heap-pages=4096 // --output=./frame/contracts/src/weights.rs -// --template=.maintain/frame-weight-template.hbs -// --header=LICENSE-APACHE2 -// --raw +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -76,11 +74,14 @@ pub trait WeightInfo { fn seal_deposit_event_per_topic_and_kb(t: u32, n: u32, ) -> Weight; fn seal_debug_message(r: u32, ) -> Weight; fn seal_set_storage(r: u32, ) -> Weight; - fn seal_set_storage_per_kb(n: u32, ) -> Weight; + fn seal_set_storage_per_new_kb(n: u32, ) -> Weight; + fn seal_set_storage_per_old_kb(n: u32, ) -> Weight; fn seal_clear_storage(r: u32, ) -> Weight; + fn seal_clear_storage_per_kb(n: u32, ) -> Weight; fn seal_get_storage(r: u32, ) -> Weight; - fn seal_contains_storage(r: u32, ) -> Weight; fn seal_get_storage_per_kb(n: u32, ) -> Weight; + fn seal_contains_storage(r: u32, ) -> Weight; + fn seal_contains_storage_per_kb(n: u32, ) -> Weight; fn seal_take_storage(r: u32, ) -> Weight; fn seal_take_storage_per_kb(n: u32, ) -> Weight; fn seal_transfer(r: u32, ) -> Weight; @@ -155,32 +156,32 @@ pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize() -> Weight { - (1_585_000 as Weight) + (1_636_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn on_initialize_per_trie_key(k: u32, ) -> Weight { - (7_902_000 as Weight) + (7_840_000 as Weight) // Standard Error: 0 - .saturating_add((751_000 as Weight).saturating_mul(k as Weight)) + .saturating_add((752_000 as Weight).saturating_mul(k as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) } // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize_per_queue_item(q: u32, ) -> Weight { - (31_473_000 as Weight) + (31_915_000 as Weight) // Standard Error: 1_000 - .saturating_add((104_000 as Weight).saturating_mul(q as Weight)) + .saturating_add((98_000 as Weight).saturating_mul(q as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Contracts PristineCode (r:1 w:0) // Storage: Contracts CodeStorage (r:0 w:1) fn reinstrument(c: u32, ) -> Weight { - (15_462_000 as Weight) - // Standard Error: 35_000 - .saturating_add((81_710_000 as Weight).saturating_mul(c as Weight)) + (18_897_000 as Weight) + // Standard Error: 32_000 + .saturating_add((69_663_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -189,9 +190,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call_with_code_kb(c: u32, ) -> Weight { - (169_561_000 as Weight) - // Standard Error: 56_000 - .saturating_add((60_037_000 as Weight).saturating_mul(c as Weight)) + (204_947_000 as Weight) + // Standard Error: 54_000 + .saturating_add((58_293_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -203,11 +204,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn instantiate_with_code(c: u32, s: u32, ) -> Weight { - (169_885_000 as Weight) - // Standard Error: 127_000 - .saturating_add((170_680_000 as Weight).saturating_mul(c as Weight)) - // Standard Error: 8_000 - .saturating_add((1_788_000 as Weight).saturating_mul(s as Weight)) + (211_187_000 as Weight) + // Standard Error: 114_000 + .saturating_add((156_529_000 as Weight).saturating_mul(c as Weight)) + // Standard Error: 7_000 + .saturating_add((1_830_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } @@ -218,9 +219,9 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn instantiate(s: u32, ) -> Weight { - (150_265_000 as Weight) + (150_485_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_722_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((1_769_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } @@ -229,7 +230,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call() -> Weight { - (114_784_000 as Weight) + (117_274_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -237,9 +238,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn upload_code(c: u32, ) -> Weight { - (48_072_000 as Weight) - // Standard Error: 36_000 - .saturating_add((83_578_000 as Weight).saturating_mul(c as Weight)) + (51_126_000 as Weight) + // Standard Error: 49_000 + .saturating_add((72_622_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -247,7 +248,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:0 w:1) // Storage: Contracts PristineCode (r:0 w:1) fn remove_code() -> Weight { - (24_739_000 as Weight) + (24_221_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -256,9 +257,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_caller(r: u32, ) -> Weight { - (174_123_000 as Weight) - // Standard Error: 127_000 - .saturating_add((56_078_000 as Weight).saturating_mul(r as Weight)) + (219_790_000 as Weight) + // Standard Error: 126_000 + .saturating_add((56_383_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -267,9 +268,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_address(r: u32, ) -> Weight { - (180_168_000 as Weight) - // Standard Error: 122_000 - .saturating_add((56_154_000 as Weight).saturating_mul(r as Weight)) + (218_377_000 as Weight) + // Standard Error: 117_000 + .saturating_add((57_243_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -278,9 +279,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas_left(r: u32, ) -> Weight { - (179_464_000 as Weight) - // Standard Error: 96_000 - .saturating_add((55_350_000 as Weight).saturating_mul(r as Weight)) + (217_999_000 as Weight) + // Standard Error: 104_000 + .saturating_add((56_674_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -289,9 +290,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_balance(r: u32, ) -> Weight { - (181_031_000 as Weight) - // Standard Error: 154_000 - .saturating_add((149_508_000 as Weight).saturating_mul(r as Weight)) + (226_932_000 as Weight) + // Standard Error: 155_000 + .saturating_add((147_401_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -300,9 +301,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_value_transferred(r: u32, ) -> Weight { - (178_709_000 as Weight) - // Standard Error: 107_000 - .saturating_add((56_326_000 as Weight).saturating_mul(r as Weight)) + (233_107_000 as Weight) + // Standard Error: 110_000 + .saturating_add((55_334_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -311,9 +312,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_minimum_balance(r: u32, ) -> Weight { - (175_715_000 as Weight) - // Standard Error: 116_000 - .saturating_add((56_755_000 as Weight).saturating_mul(r as Weight)) + (235_364_000 as Weight) + // Standard Error: 122_000 + .saturating_add((54_700_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -322,9 +323,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_block_number(r: u32, ) -> Weight { - (178_552_000 as Weight) - // Standard Error: 121_000 - .saturating_add((55_756_000 as Weight).saturating_mul(r as Weight)) + (232_875_000 as Weight) + // Standard Error: 108_000 + .saturating_add((54_510_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -333,9 +334,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_now(r: u32, ) -> Weight { - (186_172_000 as Weight) - // Standard Error: 106_000 - .saturating_add((55_311_000 as Weight).saturating_mul(r as Weight)) + (226_089_000 as Weight) + // Standard Error: 126_000 + .saturating_add((54_899_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -345,9 +346,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0) fn seal_weight_to_fee(r: u32, ) -> Weight { - (183_750_000 as Weight) - // Standard Error: 140_000 - .saturating_add((131_877_000 as Weight).saturating_mul(r as Weight)) + (234_746_000 as Weight) + // Standard Error: 146_000 + .saturating_add((132_861_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -356,9 +357,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas(r: u32, ) -> Weight { - (97_350_000 as Weight) - // Standard Error: 54_000 - .saturating_add((27_606_000 as Weight).saturating_mul(r as Weight)) + (96_247_000 as Weight) + // Standard Error: 70_000 + .saturating_add((27_918_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -367,9 +368,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input(r: u32, ) -> Weight { - (179_058_000 as Weight) - // Standard Error: 106_000 - .saturating_add((53_258_000 as Weight).saturating_mul(r as Weight)) + (221_631_000 as Weight) + // Standard Error: 139_000 + .saturating_add((54_382_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -378,9 +379,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input_per_kb(n: u32, ) -> Weight { - (248_562_000 as Weight) - // Standard Error: 5_000 - .saturating_add((10_515_000 as Weight).saturating_mul(n as Weight)) + (306_449_000 as Weight) + // Standard Error: 3_000 + .saturating_add((11_919_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -389,9 +390,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return(r: u32, ) -> Weight { - (161_228_000 as Weight) - // Standard Error: 90_000 - .saturating_add((14_539_000 as Weight).saturating_mul(r as Weight)) + (222_176_000 as Weight) + // Standard Error: 72_000 + .saturating_add((3_223_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -400,9 +401,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return_per_kb(n: u32, ) -> Weight { - (177_866_000 as Weight) + (211_079_000 as Weight) // Standard Error: 0 - .saturating_add((188_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((237_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -413,9 +414,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts DeletionQueue (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_terminate(r: u32, ) -> Weight { - (164_572_000 as Weight) - // Standard Error: 1_817_000 - .saturating_add((68_480_000 as Weight).saturating_mul(r as Weight)) + (213_994_000 as Weight) + // Standard Error: 104_000 + .saturating_add((64_453_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((4 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -427,9 +428,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) fn seal_random(r: u32, ) -> Weight { - (168_658_000 as Weight) - // Standard Error: 189_000 - .saturating_add((166_190_000 as Weight).saturating_mul(r as Weight)) + (228_281_000 as Weight) + // Standard Error: 150_000 + .saturating_add((166_949_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -438,9 +439,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_deposit_event(r: u32, ) -> Weight { - (185_391_000 as Weight) - // Standard Error: 191_000 - .saturating_add((292_609_000 as Weight).saturating_mul(r as Weight)) + (230_348_000 as Weight) + // Standard Error: 163_000 + .saturating_add((288_679_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -450,11 +451,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: System EventTopics (r:100 w:100) fn seal_deposit_event_per_topic_and_kb(t: u32, n: u32, ) -> Weight { - (507_994_000 as Weight) - // Standard Error: 1_569_000 - .saturating_add((276_852_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 309_000 - .saturating_add((79_461_000 as Weight).saturating_mul(n as Weight)) + (601_613_000 as Weight) + // Standard Error: 1_566_000 + .saturating_add((279_038_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 308_000 + .saturating_add((84_818_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(t as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -465,79 +466,95 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_debug_message(r: u32, ) -> Weight { - (99_048_000 as Weight) - // Standard Error: 87_000 - .saturating_add((46_088_000 as Weight).saturating_mul(r as Weight)) + (113_578_000 as Weight) + // Standard Error: 67_000 + .saturating_add((44_899_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage(r: u32, ) -> Weight { - (142_559_000 as Weight) - // Standard Error: 603_000 - .saturating_add((269_723_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) + (59_019_000 as Weight) + // Standard Error: 995_000 + .saturating_add((414_759_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) - .saturating_add(T::DbWeight::get().writes(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) .saturating_add(T::DbWeight::get().writes((100 as Weight).saturating_mul(r as Weight))) } - // Storage: System Account (r:2 w:2) - // Storage: Contracts ContractInfoOf (r:1 w:1) - // Storage: Contracts CodeStorage (r:1 w:0) - // Storage: Timestamp Now (r:1 w:0) - // Storage: unknown [0x7afa01283080ef247df84e0ba38ea5a587d25ce6633a6bfbba02068c14023441] (r:1 w:1) - fn seal_set_storage_per_kb(n: u32, ) -> Weight { - (346_704_000 as Weight) - // Standard Error: 200_000 - .saturating_add((29_907_000 as Weight).saturating_mul(n as Weight)) - .saturating_add(T::DbWeight::get().reads(6 as Weight)) - .saturating_add(T::DbWeight::get().writes(4 as Weight)) + // Storage: Skipped Metadata (r:0 w:0) + fn seal_set_storage_per_new_kb(n: u32, ) -> Weight { + (620_483_000 as Weight) + // Standard Error: 242_000 + .saturating_add((30_945_000 as Weight).saturating_mul(n as Weight)) + .saturating_add(T::DbWeight::get().reads(105 as Weight)) + .saturating_add(T::DbWeight::get().writes(103 as Weight)) + } + // Storage: Skipped Metadata (r:0 w:0) + fn seal_set_storage_per_old_kb(n: u32, ) -> Weight { + (632_391_000 as Weight) + // Standard Error: 317_000 + .saturating_add((11_431_000 as Weight).saturating_mul(n as Weight)) + .saturating_add(T::DbWeight::get().reads(105 as Weight)) + .saturating_add(T::DbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage(r: u32, ) -> Weight { - (0 as Weight) - // Standard Error: 1_963_000 - .saturating_add((746_581_000 as Weight).saturating_mul(r as Weight)) + (96_628_000 as Weight) + // Standard Error: 878_000 + .saturating_add((387_212_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) .saturating_add(T::DbWeight::get().writes((100 as Weight).saturating_mul(r as Weight))) } // Storage: Skipped Metadata (r:0 w:0) + fn seal_clear_storage_per_kb(n: u32, ) -> Weight { + (625_960_000 as Weight) + // Standard Error: 270_000 + .saturating_add((11_170_000 as Weight).saturating_mul(n as Weight)) + .saturating_add(T::DbWeight::get().reads(105 as Weight)) + .saturating_add(T::DbWeight::get().writes(103 as Weight)) + } + // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage(r: u32, ) -> Weight { - (69_873_000 as Weight) - // Standard Error: 722_000 - .saturating_add((338_292_000 as Weight).saturating_mul(r as Weight)) + (115_155_000 as Weight) + // Standard Error: 741_000 + .saturating_add((331_711_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) + fn seal_get_storage_per_kb(n: u32, ) -> Weight { + (582_560_000 as Weight) + // Standard Error: 360_000 + .saturating_add((68_427_000 as Weight).saturating_mul(n as Weight)) + .saturating_add(T::DbWeight::get().reads(104 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + // Storage: Skipped Metadata (r:0 w:0) fn seal_contains_storage(r: u32, ) -> Weight { - (0 as Weight) - // Standard Error: 1_169_000 - .saturating_add((480_500_000 as Weight).saturating_mul(r as Weight)) + (130_096_000 as Weight) + // Standard Error: 555_000 + .saturating_add((294_514_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:0) - // Storage: Contracts ContractInfoOf (r:1 w:1) - // Storage: Contracts CodeStorage (r:1 w:0) - // Storage: Timestamp Now (r:1 w:0) - // Storage: unknown [0x7afa01283080ef247df84e0ba38ea5a587d25ce6633a6bfbba02068c14023441] (r:1 w:0) - fn seal_get_storage_per_kb(n: u32, ) -> Weight { - (327_625_000 as Weight) - // Standard Error: 146_000 - .saturating_add((55_028_000 as Weight).saturating_mul(n as Weight)) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) + // Storage: Skipped Metadata (r:0 w:0) + fn seal_contains_storage_per_kb(n: u32, ) -> Weight { + (528_701_000 as Weight) + // Standard Error: 246_000 + .saturating_add((10_375_000 as Weight).saturating_mul(n as Weight)) + .saturating_add(T::DbWeight::get().reads(104 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage(r: u32, ) -> Weight { - (41_931_000 as Weight) - // Standard Error: 933_000 - .saturating_add((433_619_000 as Weight).saturating_mul(r as Weight)) + (95_349_000 as Weight) + // Standard Error: 906_000 + .saturating_add((430_051_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -545,9 +562,9 @@ impl WeightInfo for SubstrateWeight { } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage_per_kb(n: u32, ) -> Weight { - (639_259_000 as Weight) - // Standard Error: 365_000 - .saturating_add((64_588_000 as Weight).saturating_mul(n as Weight)) + (676_606_000 as Weight) + // Standard Error: 389_000 + .saturating_add((70_517_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().writes(103 as Weight)) } @@ -556,9 +573,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_transfer(r: u32, ) -> Weight { - (71_335_000 as Weight) - // Standard Error: 1_489_000 - .saturating_add((1_765_321_000 as Weight).saturating_mul(r as Weight)) + (131_194_000 as Weight) + // Standard Error: 1_256_000 + .saturating_add((1_772_590_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -569,9 +586,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_call(r: u32, ) -> Weight { - (0 as Weight) - // Standard Error: 9_243_000 - .saturating_add((16_121_990_000 as Weight).saturating_mul(r as Weight)) + (2_463_174_000 as Weight) + // Standard Error: 19_404_000 + .saturating_add((19_548_986_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -582,13 +599,13 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:2 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_call_per_transfer_input_output_kb(t: u32, i: u32, o: u32, ) -> Weight { - (15_978_164_000 as Weight) - // Standard Error: 57_271_000 - .saturating_add((1_179_479_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 20_000 - .saturating_add((17_389_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 21_000 - .saturating_add((28_660_000 as Weight).saturating_mul(o as Weight)) + (21_356_548_000 as Weight) + // Standard Error: 31_719_000 + .saturating_add((1_874_230_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 11_000 + .saturating_add((23_243_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 12_000 + .saturating_add((34_825_000 as Weight).saturating_mul(o as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().reads((101 as Weight).saturating_mul(t as Weight))) .saturating_add(T::DbWeight::get().writes(101 as Weight)) @@ -602,8 +619,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts OwnerInfoOf (r:100 w:100) fn seal_instantiate(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 115_056_000 - .saturating_add((23_312_565_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 49_981_000 + .saturating_add((28_988_348_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().reads((400 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -616,13 +633,13 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts AccountCounter (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_instantiate_per_input_output_salt_kb(i: u32, o: u32, s: u32, ) -> Weight { - (18_724_034_000 as Weight) - // Standard Error: 66_000 - .saturating_add((18_363_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 66_000 - .saturating_add((29_093_000 as Weight).saturating_mul(o as Weight)) - // Standard Error: 66_000 - .saturating_add((158_645_000 as Weight).saturating_mul(s as Weight)) + (24_726_887_000 as Weight) + // Standard Error: 32_000 + .saturating_add((23_702_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 32_000 + .saturating_add((35_841_000 as Weight).saturating_mul(o as Weight)) + // Standard Error: 32_000 + .saturating_add((161_159_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(208 as Weight)) .saturating_add(T::DbWeight::get().writes(206 as Weight)) } @@ -631,9 +648,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256(r: u32, ) -> Weight { - (179_769_000 as Weight) - // Standard Error: 121_000 - .saturating_add((80_706_000 as Weight).saturating_mul(r as Weight)) + (221_804_000 as Weight) + // Standard Error: 150_000 + .saturating_add((84_131_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -642,9 +659,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256_per_kb(n: u32, ) -> Weight { - (279_632_000 as Weight) - // Standard Error: 17_000 - .saturating_add((372_618_000 as Weight).saturating_mul(n as Weight)) + (357_186_000 as Weight) + // Standard Error: 23_000 + .saturating_add((469_081_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -653,9 +670,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256(r: u32, ) -> Weight { - (182_040_000 as Weight) - // Standard Error: 119_000 - .saturating_add((88_916_000 as Weight).saturating_mul(r as Weight)) + (220_729_000 as Weight) + // Standard Error: 166_000 + .saturating_add((101_538_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -664,9 +681,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256_per_kb(n: u32, ) -> Weight { - (253_225_000 as Weight) - // Standard Error: 16_000 - .saturating_add((247_883_000 as Weight).saturating_mul(n as Weight)) + (272_756_000 as Weight) + // Standard Error: 18_000 + .saturating_add((311_130_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -675,9 +692,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256(r: u32, ) -> Weight { - (179_945_000 as Weight) - // Standard Error: 96_000 - .saturating_add((68_362_000 as Weight).saturating_mul(r as Weight)) + (215_784_000 as Weight) + // Standard Error: 150_000 + .saturating_add((68_809_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -686,9 +703,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256_per_kb(n: u32, ) -> Weight { - (191_286_000 as Weight) - // Standard Error: 38_000 - .saturating_add((121_358_000 as Weight).saturating_mul(n as Weight)) + (256_009_000 as Weight) + // Standard Error: 12_000 + .saturating_add((124_552_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -697,9 +714,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128(r: u32, ) -> Weight { - (179_381_000 as Weight) - // Standard Error: 101_000 - .saturating_add((68_158_000 as Weight).saturating_mul(r as Weight)) + (216_413_000 as Weight) + // Standard Error: 134_000 + .saturating_add((68_281_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -708,9 +725,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128_per_kb(n: u32, ) -> Weight { - (135_478_000 as Weight) - // Standard Error: 41_000 - .saturating_add((121_422_000 as Weight).saturating_mul(n as Weight)) + (254_477_000 as Weight) + // Standard Error: 13_000 + .saturating_add((124_483_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -719,266 +736,266 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_ecdsa_recover(r: u32, ) -> Weight { - (123_468_000 as Weight) - // Standard Error: 1_017_000 - .saturating_add((15_542_677_000 as Weight).saturating_mul(r as Weight)) + (179_001_000 as Weight) + // Standard Error: 1_674_000 + .saturating_add((15_397_995_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn instr_i64const(r: u32, ) -> Weight { - (52_702_000 as Weight) + (46_905_000 as Weight) // Standard Error: 12_000 - .saturating_add((844_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((794_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64load(r: u32, ) -> Weight { - (47_295_000 as Weight) - // Standard Error: 10_000 - .saturating_add((3_045_000 as Weight).saturating_mul(r as Weight)) + (53_636_000 as Weight) + // Standard Error: 12_000 + .saturating_add((2_476_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64store(r: u32, ) -> Weight { - (46_353_000 as Weight) - // Standard Error: 9_000 - .saturating_add((3_047_000 as Weight).saturating_mul(r as Weight)) + (53_199_000 as Weight) + // Standard Error: 12_000 + .saturating_add((2_547_000 as Weight).saturating_mul(r as Weight)) } fn instr_select(r: u32, ) -> Weight { - (49_811_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_408_000 as Weight).saturating_mul(r as Weight)) + (37_268_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_987_000 as Weight).saturating_mul(r as Weight)) } fn instr_if(r: u32, ) -> Weight { - (47_054_000 as Weight) - // Standard Error: 12_000 - .saturating_add((2_504_000 as Weight).saturating_mul(r as Weight)) + (37_138_000 as Weight) + // Standard Error: 16_000 + .saturating_add((3_057_000 as Weight).saturating_mul(r as Weight)) } fn instr_br(r: u32, ) -> Weight { - (49_912_000 as Weight) - // Standard Error: 16_000 - .saturating_add((1_460_000 as Weight).saturating_mul(r as Weight)) + (39_353_000 as Weight) + // Standard Error: 17_000 + .saturating_add((1_939_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_if(r: u32, ) -> Weight { - (43_860_000 as Weight) + (38_883_000 as Weight) // Standard Error: 17_000 - .saturating_add((2_150_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_495_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table(r: u32, ) -> Weight { - (37_009_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_762_000 as Weight).saturating_mul(r as Weight)) + (45_030_000 as Weight) + // Standard Error: 21_000 + .saturating_add((2_398_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table_per_entry(e: u32, ) -> Weight { - (45_776_000 as Weight) + (47_281_000 as Weight) // Standard Error: 3_000 - .saturating_add((17_000 as Weight).saturating_mul(e as Weight)) + .saturating_add((29_000 as Weight).saturating_mul(e as Weight)) } fn instr_call(r: u32, ) -> Weight { - (39_611_000 as Weight) - // Standard Error: 17_000 - .saturating_add((20_805_000 as Weight).saturating_mul(r as Weight)) + (49_074_000 as Weight) + // Standard Error: 20_000 + .saturating_add((19_991_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect(r: u32, ) -> Weight { - (45_523_000 as Weight) - // Standard Error: 27_000 - .saturating_add((31_622_000 as Weight).saturating_mul(r as Weight)) + (50_071_000 as Weight) + // Standard Error: 29_000 + .saturating_add((30_156_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect_per_param(p: u32, ) -> Weight { - (79_764_000 as Weight) - // Standard Error: 6_000 - .saturating_add((1_198_000 as Weight).saturating_mul(p as Weight)) + (84_902_000 as Weight) + // Standard Error: 5_000 + .saturating_add((1_124_000 as Weight).saturating_mul(p as Weight)) } fn instr_local_get(r: u32, ) -> Weight { - (46_510_000 as Weight) - // Standard Error: 11_000 - .saturating_add((810_000 as Weight).saturating_mul(r as Weight)) + (39_054_000 as Weight) + // Standard Error: 14_000 + .saturating_add((1_352_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_set(r: u32, ) -> Weight { - (46_567_000 as Weight) - // Standard Error: 11_000 - .saturating_add((833_000 as Weight).saturating_mul(r as Weight)) + (39_190_000 as Weight) + // Standard Error: 14_000 + .saturating_add((1_370_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_tee(r: u32, ) -> Weight { - (43_439_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_463_000 as Weight).saturating_mul(r as Weight)) + (41_830_000 as Weight) + // Standard Error: 13_000 + .saturating_add((1_878_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_get(r: u32, ) -> Weight { - (46_201_000 as Weight) - // Standard Error: 19_000 - .saturating_add((1_635_000 as Weight).saturating_mul(r as Weight)) + (40_764_000 as Weight) + // Standard Error: 13_000 + .saturating_add((1_931_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_set(r: u32, ) -> Weight { - (42_639_000 as Weight) - // Standard Error: 18_000 - .saturating_add((1_652_000 as Weight).saturating_mul(r as Weight)) + (46_309_000 as Weight) + // Standard Error: 12_000 + .saturating_add((1_745_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_current(r: u32, ) -> Weight { - (51_159_000 as Weight) - // Standard Error: 14_000 - .saturating_add((917_000 as Weight).saturating_mul(r as Weight)) + (47_071_000 as Weight) + // Standard Error: 12_000 + .saturating_add((797_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_grow(r: u32, ) -> Weight { - (36_462_000 as Weight) - // Standard Error: 867_000 - .saturating_add((187_724_000 as Weight).saturating_mul(r as Weight)) + (49_773_000 as Weight) + // Standard Error: 1_442_000 + .saturating_add((227_666_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64clz(r: u32, ) -> Weight { - (53_776_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_307_000 as Weight).saturating_mul(r as Weight)) + (43_879_000 as Weight) + // Standard Error: 12_000 + .saturating_add((1_486_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ctz(r: u32, ) -> Weight { - (53_674_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_304_000 as Weight).saturating_mul(r as Weight)) + (43_883_000 as Weight) + // Standard Error: 12_000 + .saturating_add((1_484_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64popcnt(r: u32, ) -> Weight { - (53_654_000 as Weight) - // Standard Error: 9_000 - .saturating_add((1_299_000 as Weight).saturating_mul(r as Weight)) + (43_415_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_495_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eqz(r: u32, ) -> Weight { - (53_493_000 as Weight) - // Standard Error: 9_000 - .saturating_add((1_299_000 as Weight).saturating_mul(r as Weight)) + (43_567_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_493_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendsi32(r: u32, ) -> Weight { - (43_373_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_492_000 as Weight).saturating_mul(r as Weight)) + (41_332_000 as Weight) + // Standard Error: 12_000 + .saturating_add((1_912_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendui32(r: u32, ) -> Weight { - (43_222_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_498_000 as Weight).saturating_mul(r as Weight)) + (41_331_000 as Weight) + // Standard Error: 12_000 + .saturating_add((1_911_000 as Weight).saturating_mul(r as Weight)) } fn instr_i32wrapi64(r: u32, ) -> Weight { - (53_706_000 as Weight) - // Standard Error: 9_000 - .saturating_add((1_292_000 as Weight).saturating_mul(r as Weight)) + (43_704_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_487_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eq(r: u32, ) -> Weight { - (48_994_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_888_000 as Weight).saturating_mul(r as Weight)) + (37_103_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_467_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ne(r: u32, ) -> Weight { - (49_464_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_876_000 as Weight).saturating_mul(r as Weight)) + (36_680_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_487_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64lts(r: u32, ) -> Weight { - (49_194_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_884_000 as Weight).saturating_mul(r as Weight)) + (36_659_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_494_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ltu(r: u32, ) -> Weight { - (49_291_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_883_000 as Weight).saturating_mul(r as Weight)) + (36_491_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_495_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gts(r: u32, ) -> Weight { - (49_227_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_886_000 as Weight).saturating_mul(r as Weight)) + (36_440_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_499_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gtu(r: u32, ) -> Weight { - (49_219_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_885_000 as Weight).saturating_mul(r as Weight)) + (36_477_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_500_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64les(r: u32, ) -> Weight { - (49_263_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_882_000 as Weight).saturating_mul(r as Weight)) + (36_561_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_498_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64leu(r: u32, ) -> Weight { - (49_251_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_882_000 as Weight).saturating_mul(r as Weight)) + (36_418_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_501_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ges(r: u32, ) -> Weight { - (49_257_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_882_000 as Weight).saturating_mul(r as Weight)) + (36_835_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_484_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64geu(r: u32, ) -> Weight { - (49_219_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_885_000 as Weight).saturating_mul(r as Weight)) + (36_873_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_469_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64add(r: u32, ) -> Weight { - (49_221_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_888_000 as Weight).saturating_mul(r as Weight)) + (37_013_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_466_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64sub(r: u32, ) -> Weight { - (48_936_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_900_000 as Weight).saturating_mul(r as Weight)) + (36_885_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_469_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64mul(r: u32, ) -> Weight { - (49_266_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_882_000 as Weight).saturating_mul(r as Weight)) + (36_696_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_487_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divs(r: u32, ) -> Weight { - (49_246_000 as Weight) - // Standard Error: 10_000 - .saturating_add((2_565_000 as Weight).saturating_mul(r as Weight)) + (36_924_000 as Weight) + // Standard Error: 16_000 + .saturating_add((3_118_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divu(r: u32, ) -> Weight { - (49_181_000 as Weight) - // Standard Error: 10_000 - .saturating_add((2_211_000 as Weight).saturating_mul(r as Weight)) + (36_819_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_784_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rems(r: u32, ) -> Weight { - (49_337_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_525_000 as Weight).saturating_mul(r as Weight)) + (36_855_000 as Weight) + // Standard Error: 17_000 + .saturating_add((3_047_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64remu(r: u32, ) -> Weight { - (49_387_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_241_000 as Weight).saturating_mul(r as Weight)) + (36_890_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_816_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64and(r: u32, ) -> Weight { - (49_137_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_900_000 as Weight).saturating_mul(r as Weight)) + (36_749_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_475_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64or(r: u32, ) -> Weight { - (49_366_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_882_000 as Weight).saturating_mul(r as Weight)) + (36_928_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_469_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64xor(r: u32, ) -> Weight { - (49_143_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_912_000 as Weight).saturating_mul(r as Weight)) + (36_868_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_470_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shl(r: u32, ) -> Weight { - (49_195_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_891_000 as Weight).saturating_mul(r as Weight)) + (36_919_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_470_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shrs(r: u32, ) -> Weight { - (49_228_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_900_000 as Weight).saturating_mul(r as Weight)) + (36_934_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_471_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shru(r: u32, ) -> Weight { - (49_279_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_888_000 as Weight).saturating_mul(r as Weight)) + (36_705_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_492_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotl(r: u32, ) -> Weight { - (49_091_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_909_000 as Weight).saturating_mul(r as Weight)) + (36_684_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_477_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotr(r: u32, ) -> Weight { - (49_436_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_883_000 as Weight).saturating_mul(r as Weight)) + (36_844_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_477_000 as Weight).saturating_mul(r as Weight)) } } @@ -986,32 +1003,32 @@ impl WeightInfo for SubstrateWeight { impl WeightInfo for () { // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize() -> Weight { - (1_585_000 as Weight) + (1_636_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn on_initialize_per_trie_key(k: u32, ) -> Weight { - (7_902_000 as Weight) + (7_840_000 as Weight) // Standard Error: 0 - .saturating_add((751_000 as Weight).saturating_mul(k as Weight)) + .saturating_add((752_000 as Weight).saturating_mul(k as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) } // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize_per_queue_item(q: u32, ) -> Weight { - (31_473_000 as Weight) + (31_915_000 as Weight) // Standard Error: 1_000 - .saturating_add((104_000 as Weight).saturating_mul(q as Weight)) + .saturating_add((98_000 as Weight).saturating_mul(q as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Contracts PristineCode (r:1 w:0) // Storage: Contracts CodeStorage (r:0 w:1) fn reinstrument(c: u32, ) -> Weight { - (15_462_000 as Weight) - // Standard Error: 35_000 - .saturating_add((81_710_000 as Weight).saturating_mul(c as Weight)) + (18_897_000 as Weight) + // Standard Error: 32_000 + .saturating_add((69_663_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1020,9 +1037,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call_with_code_kb(c: u32, ) -> Weight { - (169_561_000 as Weight) - // Standard Error: 56_000 - .saturating_add((60_037_000 as Weight).saturating_mul(c as Weight)) + (204_947_000 as Weight) + // Standard Error: 54_000 + .saturating_add((58_293_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -1034,11 +1051,11 @@ impl WeightInfo for () { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn instantiate_with_code(c: u32, s: u32, ) -> Weight { - (169_885_000 as Weight) - // Standard Error: 127_000 - .saturating_add((170_680_000 as Weight).saturating_mul(c as Weight)) - // Standard Error: 8_000 - .saturating_add((1_788_000 as Weight).saturating_mul(s as Weight)) + (211_187_000 as Weight) + // Standard Error: 114_000 + .saturating_add((156_529_000 as Weight).saturating_mul(c as Weight)) + // Standard Error: 7_000 + .saturating_add((1_830_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } @@ -1049,9 +1066,9 @@ impl WeightInfo for () { // Storage: System Account (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn instantiate(s: u32, ) -> Weight { - (150_265_000 as Weight) + (150_485_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_722_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((1_769_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } @@ -1060,7 +1077,7 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call() -> Weight { - (114_784_000 as Weight) + (117_274_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -1068,9 +1085,9 @@ impl WeightInfo for () { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn upload_code(c: u32, ) -> Weight { - (48_072_000 as Weight) - // Standard Error: 36_000 - .saturating_add((83_578_000 as Weight).saturating_mul(c as Weight)) + (51_126_000 as Weight) + // Standard Error: 49_000 + .saturating_add((72_622_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -1078,7 +1095,7 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:0 w:1) // Storage: Contracts PristineCode (r:0 w:1) fn remove_code() -> Weight { - (24_739_000 as Weight) + (24_221_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -1087,9 +1104,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_caller(r: u32, ) -> Weight { - (174_123_000 as Weight) - // Standard Error: 127_000 - .saturating_add((56_078_000 as Weight).saturating_mul(r as Weight)) + (219_790_000 as Weight) + // Standard Error: 126_000 + .saturating_add((56_383_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1098,9 +1115,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_address(r: u32, ) -> Weight { - (180_168_000 as Weight) - // Standard Error: 122_000 - .saturating_add((56_154_000 as Weight).saturating_mul(r as Weight)) + (218_377_000 as Weight) + // Standard Error: 117_000 + .saturating_add((57_243_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1109,9 +1126,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas_left(r: u32, ) -> Weight { - (179_464_000 as Weight) - // Standard Error: 96_000 - .saturating_add((55_350_000 as Weight).saturating_mul(r as Weight)) + (217_999_000 as Weight) + // Standard Error: 104_000 + .saturating_add((56_674_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1120,9 +1137,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_balance(r: u32, ) -> Weight { - (181_031_000 as Weight) - // Standard Error: 154_000 - .saturating_add((149_508_000 as Weight).saturating_mul(r as Weight)) + (226_932_000 as Weight) + // Standard Error: 155_000 + .saturating_add((147_401_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1131,9 +1148,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_value_transferred(r: u32, ) -> Weight { - (178_709_000 as Weight) - // Standard Error: 107_000 - .saturating_add((56_326_000 as Weight).saturating_mul(r as Weight)) + (233_107_000 as Weight) + // Standard Error: 110_000 + .saturating_add((55_334_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1142,9 +1159,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_minimum_balance(r: u32, ) -> Weight { - (175_715_000 as Weight) - // Standard Error: 116_000 - .saturating_add((56_755_000 as Weight).saturating_mul(r as Weight)) + (235_364_000 as Weight) + // Standard Error: 122_000 + .saturating_add((54_700_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1153,9 +1170,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_block_number(r: u32, ) -> Weight { - (178_552_000 as Weight) - // Standard Error: 121_000 - .saturating_add((55_756_000 as Weight).saturating_mul(r as Weight)) + (232_875_000 as Weight) + // Standard Error: 108_000 + .saturating_add((54_510_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1164,9 +1181,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_now(r: u32, ) -> Weight { - (186_172_000 as Weight) - // Standard Error: 106_000 - .saturating_add((55_311_000 as Weight).saturating_mul(r as Weight)) + (226_089_000 as Weight) + // Standard Error: 126_000 + .saturating_add((54_899_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1176,9 +1193,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0) fn seal_weight_to_fee(r: u32, ) -> Weight { - (183_750_000 as Weight) - // Standard Error: 140_000 - .saturating_add((131_877_000 as Weight).saturating_mul(r as Weight)) + (234_746_000 as Weight) + // Standard Error: 146_000 + .saturating_add((132_861_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1187,9 +1204,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas(r: u32, ) -> Weight { - (97_350_000 as Weight) - // Standard Error: 54_000 - .saturating_add((27_606_000 as Weight).saturating_mul(r as Weight)) + (96_247_000 as Weight) + // Standard Error: 70_000 + .saturating_add((27_918_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1198,9 +1215,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input(r: u32, ) -> Weight { - (179_058_000 as Weight) - // Standard Error: 106_000 - .saturating_add((53_258_000 as Weight).saturating_mul(r as Weight)) + (221_631_000 as Weight) + // Standard Error: 139_000 + .saturating_add((54_382_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1209,9 +1226,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input_per_kb(n: u32, ) -> Weight { - (248_562_000 as Weight) - // Standard Error: 5_000 - .saturating_add((10_515_000 as Weight).saturating_mul(n as Weight)) + (306_449_000 as Weight) + // Standard Error: 3_000 + .saturating_add((11_919_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1220,9 +1237,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return(r: u32, ) -> Weight { - (161_228_000 as Weight) - // Standard Error: 90_000 - .saturating_add((14_539_000 as Weight).saturating_mul(r as Weight)) + (222_176_000 as Weight) + // Standard Error: 72_000 + .saturating_add((3_223_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1231,9 +1248,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return_per_kb(n: u32, ) -> Weight { - (177_866_000 as Weight) + (211_079_000 as Weight) // Standard Error: 0 - .saturating_add((188_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((237_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1244,9 +1261,9 @@ impl WeightInfo for () { // Storage: Contracts DeletionQueue (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_terminate(r: u32, ) -> Weight { - (164_572_000 as Weight) - // Standard Error: 1_817_000 - .saturating_add((68_480_000 as Weight).saturating_mul(r as Weight)) + (213_994_000 as Weight) + // Standard Error: 104_000 + .saturating_add((64_453_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((4 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1258,9 +1275,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) fn seal_random(r: u32, ) -> Weight { - (168_658_000 as Weight) - // Standard Error: 189_000 - .saturating_add((166_190_000 as Weight).saturating_mul(r as Weight)) + (228_281_000 as Weight) + // Standard Error: 150_000 + .saturating_add((166_949_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1269,9 +1286,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_deposit_event(r: u32, ) -> Weight { - (185_391_000 as Weight) - // Standard Error: 191_000 - .saturating_add((292_609_000 as Weight).saturating_mul(r as Weight)) + (230_348_000 as Weight) + // Standard Error: 163_000 + .saturating_add((288_679_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1281,11 +1298,11 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: System EventTopics (r:100 w:100) fn seal_deposit_event_per_topic_and_kb(t: u32, n: u32, ) -> Weight { - (507_994_000 as Weight) - // Standard Error: 1_569_000 - .saturating_add((276_852_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 309_000 - .saturating_add((79_461_000 as Weight).saturating_mul(n as Weight)) + (601_613_000 as Weight) + // Standard Error: 1_566_000 + .saturating_add((279_038_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 308_000 + .saturating_add((84_818_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(t as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1296,79 +1313,95 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_debug_message(r: u32, ) -> Weight { - (99_048_000 as Weight) - // Standard Error: 87_000 - .saturating_add((46_088_000 as Weight).saturating_mul(r as Weight)) + (113_578_000 as Weight) + // Standard Error: 67_000 + .saturating_add((44_899_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage(r: u32, ) -> Weight { - (142_559_000 as Weight) - // Standard Error: 603_000 - .saturating_add((269_723_000 as Weight).saturating_mul(r as Weight)) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + (59_019_000 as Weight) + // Standard Error: 995_000 + .saturating_add((414_759_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) - .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) .saturating_add(RocksDbWeight::get().writes((100 as Weight).saturating_mul(r as Weight))) } - // Storage: System Account (r:2 w:2) - // Storage: Contracts ContractInfoOf (r:1 w:1) - // Storage: Contracts CodeStorage (r:1 w:0) - // Storage: Timestamp Now (r:1 w:0) - // Storage: unknown [0x7afa01283080ef247df84e0ba38ea5a587d25ce6633a6bfbba02068c14023441] (r:1 w:1) - fn seal_set_storage_per_kb(n: u32, ) -> Weight { - (346_704_000 as Weight) - // Standard Error: 200_000 - .saturating_add((29_907_000 as Weight).saturating_mul(n as Weight)) - .saturating_add(RocksDbWeight::get().reads(6 as Weight)) - .saturating_add(RocksDbWeight::get().writes(4 as Weight)) + // Storage: Skipped Metadata (r:0 w:0) + fn seal_set_storage_per_new_kb(n: u32, ) -> Weight { + (620_483_000 as Weight) + // Standard Error: 242_000 + .saturating_add((30_945_000 as Weight).saturating_mul(n as Weight)) + .saturating_add(RocksDbWeight::get().reads(105 as Weight)) + .saturating_add(RocksDbWeight::get().writes(103 as Weight)) + } + // Storage: Skipped Metadata (r:0 w:0) + fn seal_set_storage_per_old_kb(n: u32, ) -> Weight { + (632_391_000 as Weight) + // Standard Error: 317_000 + .saturating_add((11_431_000 as Weight).saturating_mul(n as Weight)) + .saturating_add(RocksDbWeight::get().reads(105 as Weight)) + .saturating_add(RocksDbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage(r: u32, ) -> Weight { - (0 as Weight) - // Standard Error: 1_963_000 - .saturating_add((746_581_000 as Weight).saturating_mul(r as Weight)) + (96_628_000 as Weight) + // Standard Error: 878_000 + .saturating_add((387_212_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) .saturating_add(RocksDbWeight::get().writes((100 as Weight).saturating_mul(r as Weight))) } // Storage: Skipped Metadata (r:0 w:0) + fn seal_clear_storage_per_kb(n: u32, ) -> Weight { + (625_960_000 as Weight) + // Standard Error: 270_000 + .saturating_add((11_170_000 as Weight).saturating_mul(n as Weight)) + .saturating_add(RocksDbWeight::get().reads(105 as Weight)) + .saturating_add(RocksDbWeight::get().writes(103 as Weight)) + } + // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage(r: u32, ) -> Weight { - (69_873_000 as Weight) - // Standard Error: 722_000 - .saturating_add((338_292_000 as Weight).saturating_mul(r as Weight)) + (115_155_000 as Weight) + // Standard Error: 741_000 + .saturating_add((331_711_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) + fn seal_get_storage_per_kb(n: u32, ) -> Weight { + (582_560_000 as Weight) + // Standard Error: 360_000 + .saturating_add((68_427_000 as Weight).saturating_mul(n as Weight)) + .saturating_add(RocksDbWeight::get().reads(104 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + // Storage: Skipped Metadata (r:0 w:0) fn seal_contains_storage(r: u32, ) -> Weight { - (0 as Weight) - // Standard Error: 1_169_000 - .saturating_add((480_500_000 as Weight).saturating_mul(r as Weight)) + (130_096_000 as Weight) + // Standard Error: 555_000 + .saturating_add((294_514_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } - // Storage: System Account (r:1 w:0) - // Storage: Contracts ContractInfoOf (r:1 w:1) - // Storage: Contracts CodeStorage (r:1 w:0) - // Storage: Timestamp Now (r:1 w:0) - // Storage: unknown [0x7afa01283080ef247df84e0ba38ea5a587d25ce6633a6bfbba02068c14023441] (r:1 w:0) - fn seal_get_storage_per_kb(n: u32, ) -> Weight { - (327_625_000 as Weight) - // Standard Error: 146_000 - .saturating_add((55_028_000 as Weight).saturating_mul(n as Weight)) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + // Storage: Skipped Metadata (r:0 w:0) + fn seal_contains_storage_per_kb(n: u32, ) -> Weight { + (528_701_000 as Weight) + // Standard Error: 246_000 + .saturating_add((10_375_000 as Weight).saturating_mul(n as Weight)) + .saturating_add(RocksDbWeight::get().reads(104 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage(r: u32, ) -> Weight { - (41_931_000 as Weight) - // Standard Error: 933_000 - .saturating_add((433_619_000 as Weight).saturating_mul(r as Weight)) + (95_349_000 as Weight) + // Standard Error: 906_000 + .saturating_add((430_051_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -1376,9 +1409,9 @@ impl WeightInfo for () { } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage_per_kb(n: u32, ) -> Weight { - (639_259_000 as Weight) - // Standard Error: 365_000 - .saturating_add((64_588_000 as Weight).saturating_mul(n as Weight)) + (676_606_000 as Weight) + // Standard Error: 389_000 + .saturating_add((70_517_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().writes(103 as Weight)) } @@ -1387,9 +1420,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_transfer(r: u32, ) -> Weight { - (71_335_000 as Weight) - // Standard Error: 1_489_000 - .saturating_add((1_765_321_000 as Weight).saturating_mul(r as Weight)) + (131_194_000 as Weight) + // Standard Error: 1_256_000 + .saturating_add((1_772_590_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) @@ -1400,9 +1433,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_call(r: u32, ) -> Weight { - (0 as Weight) - // Standard Error: 9_243_000 - .saturating_add((16_121_990_000 as Weight).saturating_mul(r as Weight)) + (2_463_174_000 as Weight) + // Standard Error: 19_404_000 + .saturating_add((19_548_986_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1413,13 +1446,13 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:2 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_call_per_transfer_input_output_kb(t: u32, i: u32, o: u32, ) -> Weight { - (15_978_164_000 as Weight) - // Standard Error: 57_271_000 - .saturating_add((1_179_479_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 20_000 - .saturating_add((17_389_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 21_000 - .saturating_add((28_660_000 as Weight).saturating_mul(o as Weight)) + (21_356_548_000 as Weight) + // Standard Error: 31_719_000 + .saturating_add((1_874_230_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 11_000 + .saturating_add((23_243_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 12_000 + .saturating_add((34_825_000 as Weight).saturating_mul(o as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().reads((101 as Weight).saturating_mul(t as Weight))) .saturating_add(RocksDbWeight::get().writes(101 as Weight)) @@ -1433,8 +1466,8 @@ impl WeightInfo for () { // Storage: Contracts OwnerInfoOf (r:100 w:100) fn seal_instantiate(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 115_056_000 - .saturating_add((23_312_565_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 49_981_000 + .saturating_add((28_988_348_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().reads((400 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -1447,13 +1480,13 @@ impl WeightInfo for () { // Storage: Contracts AccountCounter (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_instantiate_per_input_output_salt_kb(i: u32, o: u32, s: u32, ) -> Weight { - (18_724_034_000 as Weight) - // Standard Error: 66_000 - .saturating_add((18_363_000 as Weight).saturating_mul(i as Weight)) - // Standard Error: 66_000 - .saturating_add((29_093_000 as Weight).saturating_mul(o as Weight)) - // Standard Error: 66_000 - .saturating_add((158_645_000 as Weight).saturating_mul(s as Weight)) + (24_726_887_000 as Weight) + // Standard Error: 32_000 + .saturating_add((23_702_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 32_000 + .saturating_add((35_841_000 as Weight).saturating_mul(o as Weight)) + // Standard Error: 32_000 + .saturating_add((161_159_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(208 as Weight)) .saturating_add(RocksDbWeight::get().writes(206 as Weight)) } @@ -1462,9 +1495,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256(r: u32, ) -> Weight { - (179_769_000 as Weight) - // Standard Error: 121_000 - .saturating_add((80_706_000 as Weight).saturating_mul(r as Weight)) + (221_804_000 as Weight) + // Standard Error: 150_000 + .saturating_add((84_131_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1473,9 +1506,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256_per_kb(n: u32, ) -> Weight { - (279_632_000 as Weight) - // Standard Error: 17_000 - .saturating_add((372_618_000 as Weight).saturating_mul(n as Weight)) + (357_186_000 as Weight) + // Standard Error: 23_000 + .saturating_add((469_081_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1484,9 +1517,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256(r: u32, ) -> Weight { - (182_040_000 as Weight) - // Standard Error: 119_000 - .saturating_add((88_916_000 as Weight).saturating_mul(r as Weight)) + (220_729_000 as Weight) + // Standard Error: 166_000 + .saturating_add((101_538_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1495,9 +1528,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256_per_kb(n: u32, ) -> Weight { - (253_225_000 as Weight) - // Standard Error: 16_000 - .saturating_add((247_883_000 as Weight).saturating_mul(n as Weight)) + (272_756_000 as Weight) + // Standard Error: 18_000 + .saturating_add((311_130_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1506,9 +1539,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256(r: u32, ) -> Weight { - (179_945_000 as Weight) - // Standard Error: 96_000 - .saturating_add((68_362_000 as Weight).saturating_mul(r as Weight)) + (215_784_000 as Weight) + // Standard Error: 150_000 + .saturating_add((68_809_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1517,9 +1550,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256_per_kb(n: u32, ) -> Weight { - (191_286_000 as Weight) - // Standard Error: 38_000 - .saturating_add((121_358_000 as Weight).saturating_mul(n as Weight)) + (256_009_000 as Weight) + // Standard Error: 12_000 + .saturating_add((124_552_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1528,9 +1561,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128(r: u32, ) -> Weight { - (179_381_000 as Weight) - // Standard Error: 101_000 - .saturating_add((68_158_000 as Weight).saturating_mul(r as Weight)) + (216_413_000 as Weight) + // Standard Error: 134_000 + .saturating_add((68_281_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1539,9 +1572,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128_per_kb(n: u32, ) -> Weight { - (135_478_000 as Weight) - // Standard Error: 41_000 - .saturating_add((121_422_000 as Weight).saturating_mul(n as Weight)) + (254_477_000 as Weight) + // Standard Error: 13_000 + .saturating_add((124_483_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1550,265 +1583,265 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_ecdsa_recover(r: u32, ) -> Weight { - (123_468_000 as Weight) - // Standard Error: 1_017_000 - .saturating_add((15_542_677_000 as Weight).saturating_mul(r as Weight)) + (179_001_000 as Weight) + // Standard Error: 1_674_000 + .saturating_add((15_397_995_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn instr_i64const(r: u32, ) -> Weight { - (52_702_000 as Weight) + (46_905_000 as Weight) // Standard Error: 12_000 - .saturating_add((844_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((794_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64load(r: u32, ) -> Weight { - (47_295_000 as Weight) - // Standard Error: 10_000 - .saturating_add((3_045_000 as Weight).saturating_mul(r as Weight)) + (53_636_000 as Weight) + // Standard Error: 12_000 + .saturating_add((2_476_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64store(r: u32, ) -> Weight { - (46_353_000 as Weight) - // Standard Error: 9_000 - .saturating_add((3_047_000 as Weight).saturating_mul(r as Weight)) + (53_199_000 as Weight) + // Standard Error: 12_000 + .saturating_add((2_547_000 as Weight).saturating_mul(r as Weight)) } fn instr_select(r: u32, ) -> Weight { - (49_811_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_408_000 as Weight).saturating_mul(r as Weight)) + (37_268_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_987_000 as Weight).saturating_mul(r as Weight)) } fn instr_if(r: u32, ) -> Weight { - (47_054_000 as Weight) - // Standard Error: 12_000 - .saturating_add((2_504_000 as Weight).saturating_mul(r as Weight)) + (37_138_000 as Weight) + // Standard Error: 16_000 + .saturating_add((3_057_000 as Weight).saturating_mul(r as Weight)) } fn instr_br(r: u32, ) -> Weight { - (49_912_000 as Weight) - // Standard Error: 16_000 - .saturating_add((1_460_000 as Weight).saturating_mul(r as Weight)) + (39_353_000 as Weight) + // Standard Error: 17_000 + .saturating_add((1_939_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_if(r: u32, ) -> Weight { - (43_860_000 as Weight) + (38_883_000 as Weight) // Standard Error: 17_000 - .saturating_add((2_150_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_495_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table(r: u32, ) -> Weight { - (37_009_000 as Weight) - // Standard Error: 16_000 - .saturating_add((2_762_000 as Weight).saturating_mul(r as Weight)) + (45_030_000 as Weight) + // Standard Error: 21_000 + .saturating_add((2_398_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table_per_entry(e: u32, ) -> Weight { - (45_776_000 as Weight) + (47_281_000 as Weight) // Standard Error: 3_000 - .saturating_add((17_000 as Weight).saturating_mul(e as Weight)) + .saturating_add((29_000 as Weight).saturating_mul(e as Weight)) } fn instr_call(r: u32, ) -> Weight { - (39_611_000 as Weight) - // Standard Error: 17_000 - .saturating_add((20_805_000 as Weight).saturating_mul(r as Weight)) + (49_074_000 as Weight) + // Standard Error: 20_000 + .saturating_add((19_991_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect(r: u32, ) -> Weight { - (45_523_000 as Weight) - // Standard Error: 27_000 - .saturating_add((31_622_000 as Weight).saturating_mul(r as Weight)) + (50_071_000 as Weight) + // Standard Error: 29_000 + .saturating_add((30_156_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect_per_param(p: u32, ) -> Weight { - (79_764_000 as Weight) - // Standard Error: 6_000 - .saturating_add((1_198_000 as Weight).saturating_mul(p as Weight)) + (84_902_000 as Weight) + // Standard Error: 5_000 + .saturating_add((1_124_000 as Weight).saturating_mul(p as Weight)) } fn instr_local_get(r: u32, ) -> Weight { - (46_510_000 as Weight) - // Standard Error: 11_000 - .saturating_add((810_000 as Weight).saturating_mul(r as Weight)) + (39_054_000 as Weight) + // Standard Error: 14_000 + .saturating_add((1_352_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_set(r: u32, ) -> Weight { - (46_567_000 as Weight) - // Standard Error: 11_000 - .saturating_add((833_000 as Weight).saturating_mul(r as Weight)) + (39_190_000 as Weight) + // Standard Error: 14_000 + .saturating_add((1_370_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_tee(r: u32, ) -> Weight { - (43_439_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_463_000 as Weight).saturating_mul(r as Weight)) + (41_830_000 as Weight) + // Standard Error: 13_000 + .saturating_add((1_878_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_get(r: u32, ) -> Weight { - (46_201_000 as Weight) - // Standard Error: 19_000 - .saturating_add((1_635_000 as Weight).saturating_mul(r as Weight)) + (40_764_000 as Weight) + // Standard Error: 13_000 + .saturating_add((1_931_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_set(r: u32, ) -> Weight { - (42_639_000 as Weight) - // Standard Error: 18_000 - .saturating_add((1_652_000 as Weight).saturating_mul(r as Weight)) + (46_309_000 as Weight) + // Standard Error: 12_000 + .saturating_add((1_745_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_current(r: u32, ) -> Weight { - (51_159_000 as Weight) - // Standard Error: 14_000 - .saturating_add((917_000 as Weight).saturating_mul(r as Weight)) + (47_071_000 as Weight) + // Standard Error: 12_000 + .saturating_add((797_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_grow(r: u32, ) -> Weight { - (36_462_000 as Weight) - // Standard Error: 867_000 - .saturating_add((187_724_000 as Weight).saturating_mul(r as Weight)) + (49_773_000 as Weight) + // Standard Error: 1_442_000 + .saturating_add((227_666_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64clz(r: u32, ) -> Weight { - (53_776_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_307_000 as Weight).saturating_mul(r as Weight)) + (43_879_000 as Weight) + // Standard Error: 12_000 + .saturating_add((1_486_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ctz(r: u32, ) -> Weight { - (53_674_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_304_000 as Weight).saturating_mul(r as Weight)) + (43_883_000 as Weight) + // Standard Error: 12_000 + .saturating_add((1_484_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64popcnt(r: u32, ) -> Weight { - (53_654_000 as Weight) - // Standard Error: 9_000 - .saturating_add((1_299_000 as Weight).saturating_mul(r as Weight)) + (43_415_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_495_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eqz(r: u32, ) -> Weight { - (53_493_000 as Weight) - // Standard Error: 9_000 - .saturating_add((1_299_000 as Weight).saturating_mul(r as Weight)) + (43_567_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_493_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendsi32(r: u32, ) -> Weight { - (43_373_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_492_000 as Weight).saturating_mul(r as Weight)) + (41_332_000 as Weight) + // Standard Error: 12_000 + .saturating_add((1_912_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendui32(r: u32, ) -> Weight { - (43_222_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_498_000 as Weight).saturating_mul(r as Weight)) + (41_331_000 as Weight) + // Standard Error: 12_000 + .saturating_add((1_911_000 as Weight).saturating_mul(r as Weight)) } fn instr_i32wrapi64(r: u32, ) -> Weight { - (53_706_000 as Weight) - // Standard Error: 9_000 - .saturating_add((1_292_000 as Weight).saturating_mul(r as Weight)) + (43_704_000 as Weight) + // Standard Error: 11_000 + .saturating_add((1_487_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eq(r: u32, ) -> Weight { - (48_994_000 as Weight) - // Standard Error: 10_000 - .saturating_add((1_888_000 as Weight).saturating_mul(r as Weight)) + (37_103_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_467_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ne(r: u32, ) -> Weight { - (49_464_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_876_000 as Weight).saturating_mul(r as Weight)) + (36_680_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_487_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64lts(r: u32, ) -> Weight { - (49_194_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_884_000 as Weight).saturating_mul(r as Weight)) + (36_659_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_494_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ltu(r: u32, ) -> Weight { - (49_291_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_883_000 as Weight).saturating_mul(r as Weight)) + (36_491_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_495_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gts(r: u32, ) -> Weight { - (49_227_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_886_000 as Weight).saturating_mul(r as Weight)) + (36_440_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_499_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gtu(r: u32, ) -> Weight { - (49_219_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_885_000 as Weight).saturating_mul(r as Weight)) + (36_477_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_500_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64les(r: u32, ) -> Weight { - (49_263_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_882_000 as Weight).saturating_mul(r as Weight)) + (36_561_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_498_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64leu(r: u32, ) -> Weight { - (49_251_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_882_000 as Weight).saturating_mul(r as Weight)) + (36_418_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_501_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ges(r: u32, ) -> Weight { - (49_257_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_882_000 as Weight).saturating_mul(r as Weight)) + (36_835_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_484_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64geu(r: u32, ) -> Weight { - (49_219_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_885_000 as Weight).saturating_mul(r as Weight)) + (36_873_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_469_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64add(r: u32, ) -> Weight { - (49_221_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_888_000 as Weight).saturating_mul(r as Weight)) + (37_013_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_466_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64sub(r: u32, ) -> Weight { - (48_936_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_900_000 as Weight).saturating_mul(r as Weight)) + (36_885_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_469_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64mul(r: u32, ) -> Weight { - (49_266_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_882_000 as Weight).saturating_mul(r as Weight)) + (36_696_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_487_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divs(r: u32, ) -> Weight { - (49_246_000 as Weight) - // Standard Error: 10_000 - .saturating_add((2_565_000 as Weight).saturating_mul(r as Weight)) + (36_924_000 as Weight) + // Standard Error: 16_000 + .saturating_add((3_118_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divu(r: u32, ) -> Weight { - (49_181_000 as Weight) - // Standard Error: 10_000 - .saturating_add((2_211_000 as Weight).saturating_mul(r as Weight)) + (36_819_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_784_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rems(r: u32, ) -> Weight { - (49_337_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_525_000 as Weight).saturating_mul(r as Weight)) + (36_855_000 as Weight) + // Standard Error: 17_000 + .saturating_add((3_047_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64remu(r: u32, ) -> Weight { - (49_387_000 as Weight) - // Standard Error: 11_000 - .saturating_add((2_241_000 as Weight).saturating_mul(r as Weight)) + (36_890_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_816_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64and(r: u32, ) -> Weight { - (49_137_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_900_000 as Weight).saturating_mul(r as Weight)) + (36_749_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_475_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64or(r: u32, ) -> Weight { - (49_366_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_882_000 as Weight).saturating_mul(r as Weight)) + (36_928_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_469_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64xor(r: u32, ) -> Weight { - (49_143_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_912_000 as Weight).saturating_mul(r as Weight)) + (36_868_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_470_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shl(r: u32, ) -> Weight { - (49_195_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_891_000 as Weight).saturating_mul(r as Weight)) + (36_919_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_470_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shrs(r: u32, ) -> Weight { - (49_228_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_900_000 as Weight).saturating_mul(r as Weight)) + (36_934_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_471_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shru(r: u32, ) -> Weight { - (49_279_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_888_000 as Weight).saturating_mul(r as Weight)) + (36_705_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_492_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotl(r: u32, ) -> Weight { - (49_091_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_909_000 as Weight).saturating_mul(r as Weight)) + (36_684_000 as Weight) + // Standard Error: 16_000 + .saturating_add((2_477_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotr(r: u32, ) -> Weight { - (49_436_000 as Weight) - // Standard Error: 11_000 - .saturating_add((1_883_000 as Weight).saturating_mul(r as Weight)) + (36_844_000 as Weight) + // Standard Error: 17_000 + .saturating_add((2_477_000 as Weight).saturating_mul(r as Weight)) } } From 9230ff53ad50f136c8a2ed3ac1a4c5fd4e7e885a Mon Sep 17 00:00:00 2001 From: driemworks Date: Mon, 24 Jan 2022 20:49:31 -0500 Subject: [PATCH 419/695] storage provider runtime storage updates and WIP insert pin --- .../pallets/iris-assets/src/lib.rs | 158 ++++-------------- .../pallets/iris-session/src/lib.rs | 109 +++++++++--- 2 files changed, 120 insertions(+), 147 deletions(-) diff --git a/bin/node-template/pallets/iris-assets/src/lib.rs b/bin/node-template/pallets/iris-assets/src/lib.rs index 7153314eb2f6..e8e2bbfa2fa4 100644 --- a/bin/node-template/pallets/iris-assets/src/lib.rs +++ b/bin/node-template/pallets/iris-assets/src/lib.rs @@ -64,8 +64,10 @@ use sp_std::{ pub enum DataCommand { /// (ipfs_address, cid, requesting node address, filename, asset id, balance) AddBytes(OpaqueMultiaddr, Vec, LookupSource, Vec, AssetId, Balance), - // /// owner, cid - CatBytes(AccountId, Vec, AccountId), + /// (owner, assetid, recipient) + CatBytes(AccountId, AssetId, AccountId), + /// (node, CID) + PinCID(AccountId, Vec), } #[derive(Encode, Decode, RuntimeDebug, Clone, Default, Eq, PartialEq, TypeInfo)] @@ -142,6 +144,17 @@ pub mod pallet { ValueQuery >; + /// not readlly sure if this will stay forever, + /// using this for now until I come up with an actual solution for + /// moving candidate storage providers map to the active storage providers map + #[pallet::storage] + #[pallet::getter(fn asset_ids)] + pub(super) type AssetIds = StorageValue< + _, + Vec, + ValueQuery, + >; + /// Store the map associating owned CID to a specific asset ID /// /// asset_admin_accountid -> CID -> asset id @@ -152,8 +165,8 @@ pub mod pallet { Blake2_128Concat, T::AccountId, Blake2_128Concat, - Vec, T::AssetId, + Vec, ValueQuery, >; @@ -182,18 +195,6 @@ pub mod pallet { ValueQuery, >; - #[pallet::storage] - #[pallet::getter(fn storage_pool_config)] - pub(super) type StoragePoolConfig = StorageDoubleMap< - _, - Blake2_128Concat, - T::AccountId, - Blake2_128Concat, - T::AssetId, - StoragePool, - ValueQuery, - >; - #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { @@ -209,8 +210,6 @@ pub mod pallet { DataReady(T::AccountId), /// A node has published ipfs identity results on chain PublishedIdentity(T::AccountId), - /// a storage pool was configured succesfully for some asset class - StoragePoolConfigurationSuccess(T::AccountId, T::AssetId), } #[pallet::error] @@ -247,26 +246,6 @@ pub mod pallet { 0 } - fn offchain_worker(block_number: T::BlockNumber) { - // // every 5 blocks - // if block_number % 5u32.into() == 0u32.into() { - // if let Err(e) = Self::connection_housekeeping() { - // log::error!("IPFS: Encountered an error while processing data requests: {:?}", e); - // } - // } - - // // handle data requests each block - // if let Err(e) = Self::handle_data_requests() { - // log::error!("IPFS: Encountered an error while processing data requests: {:?}", e); - // } - - // // every 5 blocks - // if block_number % 5u32.into() == 0u32.into() { - // if let Err(e) = Self::print_metadata() { - // log::error!("IPFS: Encountered an error while obtaining metadata: {:?}", e); - // } - // } - } } #[pallet::call] @@ -315,7 +294,7 @@ pub mod pallet { pub fn request_data( origin: OriginFor, owner: ::Source, - cid: Vec, + asset_id: T::AssetId, ) -> DispatchResult { let who = ensure_signed(origin)?; let owner_account = T::Lookup::lookup(owner)?; @@ -323,7 +302,7 @@ pub mod pallet { >::mutate( |queue| queue.push(DataCommand::CatBytes( owner_account.clone(), - cid.clone(), + asset_id.clone(), who.clone(), ) )); @@ -360,49 +339,14 @@ pub mod pallet { .map_err(|_| Error::::CantCreateAssetClass)?; let which_admin = T::Lookup::lookup(admin.clone())?; - >::insert(which_admin, cid.clone(), id.clone()); + >::insert(which_admin, id.clone(), cid.clone()); + >::mutate(|ids| ids.push(id.clone())); Self::deposit_event(Event::AssetClassCreated(id.clone())); Ok(()) } - // /// Should only be callable by OCWs (TODO) - // /// Submit the results of an `ipfs identity` call to be stored on chain - // /// - // /// * origin: a validator node - // /// * public_key: The IPFS node's public key - // /// * multiaddresses: A vector of multiaddresses associate with the public key - // /// - // #[pallet::weight(0)] - // pub fn submit_ipfs_identity( - // origin: OriginFor, - // public_key: Vec, - // multiaddresses: Vec, - // ) -> DispatchResult { - // let who = ensure_signed(origin)?; - // >::insert(public_key.clone(), multiaddresses.clone()); - // Self::deposit_event(Event::PublishedIdentity(who.clone())); - // Ok(()) - // } - - // /// Should only be callable by OCWs (TODO) - // /// Submit the results onchain to notify a beneficiary that their data is available: TODO: how to safely share host? spam protection on rpc endpoints? - // /// - // /// * `beneficiary`: The account that requested the data - // /// * `host`: The node's host where the data has been made available (RPC endpoint) - // /// - // #[pallet::weight(0)] - // pub fn submit_rpc_ready( - // origin: OriginFor, - // beneficiary: T::AccountId, - // // host: Vec, - // ) -> DispatchResult { - // ensure_signed(origin)?; - // Self::deposit_event(Event::DataReady(beneficiary)); - // Ok(()) - // } - /// Only callable by the owner of the asset class /// mint a static number of assets (tickets) for some asset class /// @@ -415,19 +359,19 @@ pub mod pallet { pub fn mint_tickets( origin: OriginFor, beneficiary: ::Source, - cid: Vec, + asset_id: T::AssetId, #[pallet::compact] amount: T::Balance, ) -> DispatchResult { let who = ensure_signed(origin)?; let new_origin = system::RawOrigin::Signed(who.clone()).into(); let beneficiary_accountid = T::Lookup::lookup(beneficiary.clone())?; - ensure!(AssetClassOwnership::::contains_key(who.clone(), cid.clone()), Error::::NoSuchOwnedContent); + ensure!(AssetClassOwnership::::contains_key(who.clone(), asset_id.clone()), Error::::NoSuchOwnedContent); - let asset_id = AssetClassOwnership::::get(who.clone(), cid.clone(),); + // let asset_id = AssetClassOwnership::::get(who.clone(), cid.clone(),); >::mint(new_origin, asset_id.clone(), beneficiary.clone(), amount) .map_err(|_| Error::::CantMintAssets)?; - + let cid = >::get(who.clone(), asset_id.clone()); >::insert(beneficiary_accountid.clone(), cid.clone(), who.clone()); Self::deposit_event(Event::AssetCreated(asset_id.clone())); @@ -435,58 +379,28 @@ pub mod pallet { } #[pallet::weight(0)] - pub fn configure_storage_pool( + pub fn insert_pin_request( origin: OriginFor, + asset_owner: T::AccountId, asset_id: T::AssetId, - max_redundancy: u32, - ) -> DispatchResult { - let who = ensure_signed(origin)?; - // TODO: Ensure asset is owned by origin -> maybe restructure runtime storage? - let new_sp_config = StoragePool { - max_redundancy: max_redundancy, - candidate_storage_providers: Vec::new(), - current_session_storage_providers: Vec::new(), - owner: who.clone(), - }; - >::insert(who.clone(), asset_id.clone(), new_sp_config); - Self::deposit_event( - Event::StoragePoolConfigurationSuccess( - who.clone(), asset_id.clone())); - Ok(()) - } - - #[pallet::weight(0)] - pub fn try_add_candidate_storage_provider( - origin: OriginFor, - pool_owner: T::AccountId, - pool_id: T::AssetId, ) -> DispatchResult { let who = ensure_signed(origin)?; - - Self::do_add_candidate_storage_provider( - pool_owner.clone(), pool_id.clone(), who.clone() + ensure!(>::contains_key(asset_owner.clone(), asset_id.clone()), Error::::NoSuchOwnedContent); + let cid = >::get( + asset_owner.clone(), + asset_id.clone(), ); - + >::mutate( + |queue| queue.push(DataCommand::PinCID( + who.clone(), + cid.clone(), + ))); Ok(()) } + } } impl Pallet { - fn do_add_candidate_storage_provider( - pool_admin: T::AccountId, - pool_id: T::AssetId, - candidate_storage_provider: T::AccountId, - ) -> Result<(), Error> { - let mut sp = StoragePoolConfig::::get(pool_admin.clone(), pool_id.clone()); - // TODO: check duplicates - sp.candidate_storage_providers.push(candidate_storage_provider); - >::insert( - pool_admin.clone(), pool_id.clone(), sp - ); - - Ok(()) - } - } \ No newline at end of file diff --git a/bin/node-template/pallets/iris-session/src/lib.rs b/bin/node-template/pallets/iris-session/src/lib.rs index a569fb95985e..eeea63052baf 100644 --- a/bin/node-template/pallets/iris-session/src/lib.rs +++ b/bin/node-template/pallets/iris-session/src/lib.rs @@ -125,7 +125,6 @@ pub mod pallet { pub struct Pallet(_); /// map the ipfs public key to a list of multiaddresses - /// this could be moved to the session pallet #[pallet::storage] #[pallet::getter(fn bootstrap_nodes)] pub(super) type BootstrapNodes = StorageMap< @@ -136,6 +135,38 @@ pub mod pallet { ValueQuery, >; + #[pallet::storage] + #[pallet::getter(fn substrate_ipfs_bridge)] + pub(super) type SubstrateIpfsBridge = StorageMap< + _, + Blake2_128Concat, + T::AccountId, + Vec, + ValueQuery, + >; + + /// Maps an asset id to a collection of nodes that want to provider storage + #[pallet::storage] + #[pallet::getter(fn candidate_storage_providers)] + pub(super) type CandidateStorageProviders = StorageMap< + _, + Blake2_128Concat, + T::AssetId, + Vec, + ValueQuery, + >; + + /// maps an asset id to a collection of nodes that are providing storage + #[pallet::storage] + #[pallet::getter(fn storage_providers)] + pub(super) type StorageProviders = StorageMap< + _, + Blake2_128Concat, + T::AssetId, + Vec, + ValueQuery, + >; + #[pallet::storage] #[pallet::getter(fn validators)] pub type Validators = StorageValue<_, Vec, ValueQuery>; @@ -182,6 +213,8 @@ pub mod pallet { NoSuchOwnedContent, /// the nodes balance is insufficient to complete this operation InsufficientBalance, + /// the node is already a candidate for some storage pool + AlreadyACandidate, } #[pallet::hooks] @@ -291,13 +324,14 @@ pub mod pallet { // submit a request to join a storage pool in the next session let who = ensure_signed(origin)?; let new_origin = system::RawOrigin::Signed(who.clone()).into(); + let csp = >::get(pool_id.clone()); + ensure!(!csp.contains(&who), Error::::AlreadyACandidate); + // TODO: we need a better scheme for *generating* pool ids -> should always be unique (cid + owner maybe?) + >::mutate(pool_id.clone(), |sp| { + sp.push(who.clone()); + }); let owner = T::Lookup::lookup(pool_owner)?; - >::try_add_candidate_storage_provider( - new_origin, - owner, - pool_id.clone(), - )?; - + >::insert_pin_request(new_origin, owner, pool_id); Self::deposit_event(Event::RequestJoinStoragePoolSuccess(who.clone(), pool_id.clone())); Ok(()) } @@ -345,7 +379,8 @@ pub mod pallet { ) -> DispatchResult { let who = ensure_signed(origin)?; >::insert(public_key.clone(), multiaddresses.clone()); - Self::deposit_event(Event::PublishedIdentity(who.clone())); + >::insert(who.clone(), public_key.clone()); + Self::deposit_event(Event::PublishedIdentity(who.clone())); Ok(()) } @@ -408,13 +443,10 @@ impl Pallet { } /// Ensure the candidate validator is eligible to be a validator - /// 1) Check that it is not a duplicate - /// 2) fn approve_validator(validator_id: T::AccountId) -> DispatchResult { let approved_set: BTreeSet<_> = >::get().into_iter().collect(); ensure!(!approved_set.contains(&validator_id), Error::::Duplicate); >::mutate(|v| v.push(validator_id.clone())); - // In storage pool -> move from candidate storage provider to storage provider Ok(()) } @@ -451,6 +483,20 @@ impl Pallet { >::put(Vec::::new()); } + /// move candidates to the active provider pool for some asset id + fn select_candidate_storage_providers() { + // TODO: for now, we will just copy the candidates to the active providers map + // no real selection is happening yet, just doing this to get it in place for now + for assetid in >::asset_ids().into_iter() { + // if there are candidates for the asset id + if >::contains_key(assetid.clone()) { + let candidates = >::get(assetid.clone()); + // need to only move candidates that have actually proved they pinned the content + >::insert(assetid.clone(), candidates); + } + } + } + /// implementation for RPC runtime aPI to retrieve bytes from the node's local storage /// /// * public_key: The account's public key as bytes @@ -591,12 +637,6 @@ impl Pallet { ); } let results = signer.send_signed_transaction(|_account| { - // Ca::submit_ipfs_add_results{ - // admin: admin.clone(), - // cid: new_cid.clone(), - // id: id.clone(), - // balance: balance.clone(), - // } Call::submit_ipfs_add_results{ admin: admin.clone(), cid: new_cid.clone(), @@ -620,9 +660,9 @@ impl Pallet { Err(e) => log::error!("IPFS: cat error: {:?}", e), } }, - DataCommand::CatBytes(owner, cid, recipient) => { - if let asset_id = >::asset_class_ownership( - owner.clone(), cid.clone() + DataCommand::CatBytes(owner, asset_id, recipient) => { + if let cid = >::asset_class_ownership( + owner.clone(), asset_id.clone() ) { let balance = >::balance(asset_id.clone(), recipient.clone()); let balance_primitive = TryInto::::try_into(balance).ok(); @@ -660,9 +700,30 @@ impl Pallet { Err(e) => log::error!("IPFS: cat error: {:?}", e), } } else { - log::error!("the provided owner/cid does not map to a valid asset id: {:?}, {:?}", owner, cid) + log::error!("the provided owner/cid does not map to a valid asset id: {:?}, {:?}", owner, asset_id) } - } + }, + DataCommand::PinCID(acct, cid) => { + let (public_key, addrs) = + if let IpfsResponse::Identity(public_key, addrs) = + Self::ipfs_request(IpfsRequest::Identity, deadline)? { + (public_key, addrs) + } else { + unreachable!("only `Identity` is a valid response type."); + }; + let expected_pub_key = >::get(acct); + ensure!(public_key == expected_pub_key, Error::::BadOrigin); + match Self::ipfs_request(IpfsRequest::InsertPin(cid.clone(), false), deadline) { + // todo: create new error enum if this is the route i choose + Ok(IpfsResponse::Success) => { + log::info!("IPFS: Pinned CID {:?}", cid.clone()); + // TODO: Call some extrinsic to report you have pinned + // the cid. 'submit_ipfs_pin_results' + }, + Ok(_) => unreachable!("only Success can be a response for that request type"), + Err(e) => log::error!("IPFS: insert pin error: {:?}", e), + } + } } } @@ -698,10 +759,8 @@ impl pallet_session::SessionManager for Pallet { // Remove any offline validators. This will only work when the runtime // also has the im-online pallet. Self::remove_offline_validators(); + // Self::select_candidate_storage_providers(); log::debug!(target: LOG_TARGET, "New session called; updated validator set provided."); - - // TODO: Need to verify that storage providers have data pinned... - Some(Self::validators()) } From 31d90c202d6df9ce3837ee55587b604619a912ba Mon Sep 17 00:00:00 2001 From: Enoch Chejieh Date: Tue, 25 Jan 2022 10:04:07 +0100 Subject: [PATCH 420/695] chore: add example for balance AccountStore (#10361) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: modified example for balance AccountStore * add example for account store balance * add example for account store balance * Update frame/balances/src/lib.rs * Update frame/balances/src/lib.rs * balance account store example * balance account store example * Update frame/balances/src/lib.rs * Update frame/balances/src/lib.rs * balance account store example Co-authored-by: Bastian Köcher Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> --- frame/balances/src/lib.rs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/frame/balances/src/lib.rs b/frame/balances/src/lib.rs index 8a6d54b54c8d..80e8bf577abe 100644 --- a/frame/balances/src/lib.rs +++ b/frame/balances/src/lib.rs @@ -488,8 +488,29 @@ pub mod pallet { #[pallet::getter(fn total_issuance)] pub type TotalIssuance, I: 'static = ()> = StorageValue<_, T::Balance, ValueQuery>; - /// The balance of an account. + /// The Balances pallet example of storing the balance of an account. /// + /// # Example + /// + /// ```nocompile + /// impl pallet_balances::Config for Runtime { + /// type AccountStore = StorageMapShim, frame_system::Provider, AccountId, Self::AccountData> + /// } + /// ``` + /// + /// You can also store the balance of an account in the `System` pallet. + /// + /// # Example + /// + /// ```nocompile + /// impl pallet_balances::Config for Runtime { + /// type AccountStore = System + /// } + /// ``` + /// + /// But this comes with tradeoffs, storing account balances in the system pallet stores + /// `frame_system` data alongside the account data contrary to storing account balances in the + /// `Balances` pallet, which uses a `StorageMap` to store balances data only. /// NOTE: This is only used in the case that this pallet is used to store balances. #[pallet::storage] pub type Account, I: 'static = ()> = StorageMap< From 9e9e4d3963ac43d167bd52458bcfe860aabe7e0b Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Tue, 25 Jan 2022 15:44:10 +0100 Subject: [PATCH 421/695] Use proper bounded vector type for nominations (#10601) * Use proper bounded vector type for nominations * add docs and tweak chill_other for cleanup purposes * Fix the build * remove TODO * add a bit more doc * even more docs gushc * Update frame/staking/src/pallet/mod.rs Co-authored-by: Zeke Mostov * Update frame/staking/src/pallet/mod.rs Co-authored-by: Zeke Mostov * Fix the nasty bug * also bound the Snapshot type * fix doc test * document bounded_vec * self-review * remove unused * Fix build * frame-support: repetition overload for bounded_vec Signed-off-by: Oliver Tale-Yazdi * fix * remove the need to allocate into unbounded voters etc etc * Don't expect * unbreal the build again * handle macro a bit better Co-authored-by: Zeke Mostov Co-authored-by: Oliver Tale-Yazdi --- bin/node/cli/src/chain_spec.rs | 6 +- bin/node/runtime/src/lib.rs | 8 +- frame/babe/src/mock.rs | 2 +- .../src/benchmarking.rs | 26 +++-- .../src/helpers.rs | 12 +-- .../election-provider-multi-phase/src/lib.rs | 19 ++-- .../election-provider-multi-phase/src/mock.rs | 71 +++++++------ .../src/unsigned.rs | 14 ++- frame/election-provider-support/src/lib.rs | 44 +++++--- .../election-provider-support/src/onchain.rs | 21 ++-- frame/elections-phragmen/src/lib.rs | 4 +- frame/grandpa/src/mock.rs | 2 +- frame/offences/benchmarking/src/lib.rs | 8 +- frame/offences/benchmarking/src/mock.rs | 2 +- frame/session/benchmarking/src/lib.rs | 10 +- frame/session/benchmarking/src/mock.rs | 2 +- frame/staking/src/benchmarking.rs | 28 ++--- frame/staking/src/lib.rs | 9 +- frame/staking/src/mock.rs | 5 +- frame/staking/src/pallet/impls.rs | 41 ++++--- frame/staking/src/pallet/mod.rs | 97 +++++++++-------- frame/staking/src/tests.rs | 100 +++++++++++++++++- frame/support/src/lib.rs | 23 ++++ frame/support/src/storage/bounded_vec.rs | 13 +++ .../support/src/storage/types/counted_map.rs | 7 ++ frame/system/src/lib.rs | 5 - .../npos-elections/fuzzer/src/common.rs | 18 +--- .../fuzzer/src/phragmen_balancing.rs | 11 +- .../fuzzer/src/phragmms_balancing.rs | 13 +-- primitives/npos-elections/src/lib.rs | 4 +- primitives/npos-elections/src/mock.rs | 2 +- primitives/npos-elections/src/phragmen.rs | 2 +- primitives/npos-elections/src/phragmms.rs | 14 +-- primitives/npos-elections/src/tests.rs | 28 ++--- 34 files changed, 419 insertions(+), 252 deletions(-) diff --git a/bin/node/cli/src/chain_spec.rs b/bin/node/cli/src/chain_spec.rs index 747bc71c5007..6fd57e31e466 100644 --- a/bin/node/cli/src/chain_spec.rs +++ b/bin/node/cli/src/chain_spec.rs @@ -23,8 +23,8 @@ use hex_literal::hex; use node_runtime::{ constants::currency::*, wasm_binary_unwrap, AuthorityDiscoveryConfig, BabeConfig, BalancesConfig, Block, CouncilConfig, DemocracyConfig, ElectionsConfig, GrandpaConfig, - ImOnlineConfig, IndicesConfig, SessionConfig, SessionKeys, SocietyConfig, StakerStatus, - StakingConfig, SudoConfig, SystemConfig, TechnicalCommitteeConfig, MAX_NOMINATIONS, + ImOnlineConfig, IndicesConfig, MaxNominations, SessionConfig, SessionKeys, SocietyConfig, + StakerStatus, StakingConfig, SudoConfig, SystemConfig, TechnicalCommitteeConfig, }; use pallet_im_online::sr25519::AuthorityId as ImOnlineId; use sc_chain_spec::ChainSpecExtension; @@ -278,7 +278,7 @@ pub fn testnet_genesis( .map(|x| (x.0.clone(), x.1.clone(), STASH, StakerStatus::Validator)) .chain(initial_nominators.iter().map(|x| { use rand::{seq::SliceRandom, Rng}; - let limit = (MAX_NOMINATIONS as usize).min(initial_authorities.len()); + let limit = (MaxNominations::get() as usize).min(initial_authorities.len()); let count = rng.gen::() % limit; let nominations = initial_authorities .as_slice() diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 6034b86987ff..8f00dd8f64b4 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -541,7 +541,7 @@ impl pallet_staking::BenchmarkingConfig for StakingBenchmarkingConfig { } impl pallet_staking::Config for Runtime { - const MAX_NOMINATIONS: u32 = MAX_NOMINATIONS; + type MaxNominations = MaxNominations; type Currency = Balances; type UnixTime = Timestamp; type CurrencyToVote = U128CurrencyToVote; @@ -605,7 +605,9 @@ sp_npos_elections::generate_solution_type!( >(16) ); -pub const MAX_NOMINATIONS: u32 = ::LIMIT as u32; +parameter_types! { + pub MaxNominations: u32 = ::LIMIT as u32; +} /// The numbers configured here could always be more than the the maximum limits of staking pallet /// to ensure election snapshot will not run out of memory. For now, we set them to smaller values @@ -1792,7 +1794,7 @@ mod tests { #[test] fn perbill_as_onchain_accuracy() { type OnChainAccuracy = ::Accuracy; - let maximum_chain_accuracy: Vec> = (0..MAX_NOMINATIONS) + let maximum_chain_accuracy: Vec> = (0..MaxNominations::get()) .map(|_| >::from(OnChainAccuracy::one().deconstruct())) .collect(); let _: UpperOf = diff --git a/frame/babe/src/mock.rs b/frame/babe/src/mock.rs index fa7a7b185b34..2e4b6023f1e5 100644 --- a/frame/babe/src/mock.rs +++ b/frame/babe/src/mock.rs @@ -178,7 +178,7 @@ impl onchain::Config for Test { } impl pallet_staking::Config for Test { - const MAX_NOMINATIONS: u32 = 16; + type MaxNominations = ConstU32<16>; type RewardRemainder = (); type CurrencyToVote = frame_support::traits::SaturatingCurrencyToVote; type Event = Event; diff --git a/frame/election-provider-multi-phase/src/benchmarking.rs b/frame/election-provider-multi-phase/src/benchmarking.rs index d605c5131cf7..d37b9451b770 100644 --- a/frame/election-provider-multi-phase/src/benchmarking.rs +++ b/frame/election-provider-multi-phase/src/benchmarking.rs @@ -20,7 +20,11 @@ use super::*; use crate::{unsigned::IndexAssignmentOf, Pallet as MultiPhase}; use frame_benchmarking::account; -use frame_support::{assert_ok, traits::Hooks}; +use frame_support::{ + assert_ok, + traits::{Hooks, TryCollect}, + BoundedVec, +}; use frame_system::RawOrigin; use rand::{prelude::SliceRandom, rngs::SmallRng, SeedableRng}; use sp_arithmetic::{per_things::Percent, traits::One}; @@ -69,11 +73,12 @@ fn solution_with_size( let active_voters = (0..active_voters_count) .map(|i| { // chose a random subset of winners. - let winner_votes = winners + let winner_votes: BoundedVec<_, _> = winners .as_slice() .choose_multiple(&mut rng, >::LIMIT) .cloned() - .collect::>(); + .try_collect() + .expect(">::LIMIT is the correct bound; qed."); let voter = frame_benchmarking::account::("Voter", i, SEED); (voter, stake, winner_votes) }) @@ -87,10 +92,11 @@ fn solution_with_size( .collect::>(); let rest_voters = (active_voters_count..size.voters) .map(|i| { - let votes = (&non_winners) + let votes: BoundedVec<_, _> = (&non_winners) .choose_multiple(&mut rng, >::LIMIT) .cloned() - .collect::>(); + .try_collect() + .expect(">::LIMIT is the correct bound; qed."); let voter = frame_benchmarking::account::("Voter", i, SEED); (voter, stake, votes) }) @@ -152,7 +158,7 @@ fn set_up_data_provider(v: u32, t: u32) { info, "setting up with voters = {} [degree = {}], targets = {}", v, - T::DataProvider::MAXIMUM_VOTES_PER_VOTER, + ::MaxVotesPerVoter::get(), t ); @@ -165,14 +171,16 @@ fn set_up_data_provider(v: u32, t: u32) { }) .collect::>(); // we should always have enough voters to fill. - assert!(targets.len() > T::DataProvider::MAXIMUM_VOTES_PER_VOTER as usize); - targets.truncate(T::DataProvider::MAXIMUM_VOTES_PER_VOTER as usize); + assert!( + targets.len() > ::MaxVotesPerVoter::get() as usize + ); + targets.truncate(::MaxVotesPerVoter::get() as usize); // fill voters. (0..v).for_each(|i| { let voter = frame_benchmarking::account::("Voter", i, SEED); let weight = T::Currency::minimum_balance().saturated_into::() * 1000; - T::DataProvider::add_voter(voter, weight, targets.clone()); + T::DataProvider::add_voter(voter, weight, targets.clone().try_into().unwrap()); }); } diff --git a/frame/election-provider-multi-phase/src/helpers.rs b/frame/election-provider-multi-phase/src/helpers.rs index 9bd5b5dbabd2..48da194cc65d 100644 --- a/frame/election-provider-multi-phase/src/helpers.rs +++ b/frame/election-provider-multi-phase/src/helpers.rs @@ -17,7 +17,7 @@ //! Some helper functions/macros for this crate. -use super::{Config, SolutionTargetIndexOf, SolutionVoterIndexOf, VoteWeight}; +use crate::{unsigned::VoterOf, Config, SolutionTargetIndexOf, SolutionVoterIndexOf, VoteWeight}; use sp_std::{collections::btree_map::BTreeMap, prelude::*}; #[macro_export] @@ -34,7 +34,7 @@ macro_rules! log { /// /// This can be used to efficiently build index getter closures. pub fn generate_voter_cache( - snapshot: &Vec<(T::AccountId, VoteWeight, Vec)>, + snapshot: &Vec>, ) -> BTreeMap { let mut cache: BTreeMap = BTreeMap::new(); snapshot.iter().enumerate().for_each(|(i, (x, _, _))| { @@ -97,7 +97,7 @@ pub fn voter_index_fn_usize( /// Not meant to be used in production. #[cfg(test)] pub fn voter_index_fn_linear( - snapshot: &Vec<(T::AccountId, VoteWeight, Vec)>, + snapshot: &Vec>, ) -> impl Fn(&T::AccountId) -> Option> + '_ { move |who| { snapshot @@ -148,7 +148,7 @@ pub fn target_index_fn_linear( /// Create a function that can map a voter index ([`SolutionVoterIndexOf`]) to the actual voter /// account using a linearly indexible snapshot. pub fn voter_at_fn( - snapshot: &Vec<(T::AccountId, VoteWeight, Vec)>, + snapshot: &Vec>, ) -> impl Fn(SolutionVoterIndexOf) -> Option + '_ { move |i| { as TryInto>::try_into(i) @@ -174,7 +174,7 @@ pub fn target_at_fn( /// This is not optimized and uses a linear search. #[cfg(test)] pub fn stake_of_fn_linear( - snapshot: &Vec<(T::AccountId, VoteWeight, Vec)>, + snapshot: &Vec>, ) -> impl Fn(&T::AccountId) -> VoteWeight + '_ { move |who| { snapshot @@ -192,7 +192,7 @@ pub fn stake_of_fn_linear( /// The cache need must be derived from the same snapshot. Zero is returned if a voter is /// non-existent. pub fn stake_of_fn<'a, T: Config>( - snapshot: &'a Vec<(T::AccountId, VoteWeight, Vec)>, + snapshot: &'a Vec>, cache: &'a BTreeMap, ) -> impl Fn(&T::AccountId) -> VoteWeight + 'a { move |who| { diff --git a/frame/election-provider-multi-phase/src/lib.rs b/frame/election-provider-multi-phase/src/lib.rs index 4716bcd6c859..f1d1d78912c4 100644 --- a/frame/election-provider-multi-phase/src/lib.rs +++ b/frame/election-provider-multi-phase/src/lib.rs @@ -269,6 +269,7 @@ const LOG_TARGET: &'static str = "runtime::election-provider"; pub mod signed; pub mod unsigned; pub mod weights; +use unsigned::VoterOf; pub use weights::WeightInfo; pub use signed::{ @@ -448,11 +449,13 @@ pub struct ReadySolution { /// /// These are stored together because they are often accessed together. #[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, Default, TypeInfo)] -pub struct RoundSnapshot { +#[codec(mel_bound(T: Config))] +#[scale_info(skip_type_params(T))] +pub struct RoundSnapshot { /// All of the voters. - pub voters: Vec<(A, VoteWeight, Vec)>, + pub voters: Vec>, /// All of the targets. - pub targets: Vec, + pub targets: Vec, } /// Encodes the length of a solution or a snapshot. @@ -820,7 +823,7 @@ pub mod pallet { // NOTE that this pallet does not really need to enforce this in runtime. The // solution cannot represent any voters more than `LIMIT` anyhow. assert_eq!( - ::MAXIMUM_VOTES_PER_VOTER, + ::MaxVotesPerVoter::get(), as NposSolution>::LIMIT as u32, ); } @@ -1140,7 +1143,7 @@ pub mod pallet { /// This is created at the beginning of the signed phase and cleared upon calling `elect`. #[pallet::storage] #[pallet::getter(fn snapshot)] - pub type Snapshot = StorageValue<_, RoundSnapshot>; + pub type Snapshot = StorageValue<_, RoundSnapshot>; /// Desired number of targets to elect for this round. /// @@ -1257,7 +1260,7 @@ impl Pallet { /// Extracted for easier weight calculation. fn create_snapshot_internal( targets: Vec, - voters: Vec>, + voters: Vec>, desired_targets: u32, ) { let metadata = @@ -1270,7 +1273,7 @@ impl Pallet { // instead of using storage APIs, we do a manual encoding into a fixed-size buffer. // `encoded_size` encodes it without storing it anywhere, this should not cause any // allocation. - let snapshot = RoundSnapshot { voters, targets }; + let snapshot = RoundSnapshot:: { voters, targets }; let size = snapshot.encoded_size(); log!(debug, "snapshot pre-calculated size {:?}", size); let mut buffer = Vec::with_capacity(size); @@ -1288,7 +1291,7 @@ impl Pallet { /// /// Extracted for easier weight calculation. fn create_snapshot_external( - ) -> Result<(Vec, Vec>, u32), ElectionError> { + ) -> Result<(Vec, Vec>, u32), ElectionError> { let target_limit = >::max_value().saturated_into::(); // for now we have just a single block snapshot. let voter_limit = T::VoterSnapshotPerBlock::get().saturated_into::(); diff --git a/frame/election-provider-multi-phase/src/mock.rs b/frame/election-provider-multi-phase/src/mock.rs index 409ebd3f1e10..1be93c363e32 100644 --- a/frame/election-provider-multi-phase/src/mock.rs +++ b/frame/election-provider-multi-phase/src/mock.rs @@ -22,11 +22,12 @@ use frame_election_provider_support::{ }; pub use frame_support::{assert_noop, assert_ok}; use frame_support::{ - parameter_types, + bounded_vec, parameter_types, traits::{ConstU32, Hooks}, weights::Weight, + BoundedVec, }; -use multi_phase::unsigned::{IndexAssignmentOf, Voter}; +use multi_phase::unsigned::{IndexAssignmentOf, VoterOf}; use parking_lot::RwLock; use sp_core::{ offchain::{ @@ -100,7 +101,7 @@ pub fn roll_to_with_ocw(n: BlockNumber) { } pub struct TrimHelpers { - pub voters: Vec>, + pub voters: Vec>, pub assignments: Vec>, pub encoded_size_of: Box]) -> Result>, @@ -131,13 +132,8 @@ pub fn trim_helpers() -> TrimHelpers { let desired_targets = MultiPhase::desired_targets().unwrap(); - let ElectionResult { mut assignments, .. } = seq_phragmen::<_, SolutionAccuracyOf>( - desired_targets as usize, - targets.clone(), - voters.clone(), - None, - ) - .unwrap(); + let ElectionResult::<_, SolutionAccuracyOf> { mut assignments, .. } = + seq_phragmen(desired_targets as usize, targets.clone(), voters.clone(), None).unwrap(); // sort by decreasing order of stake assignments.sort_unstable_by_key(|assignment| { @@ -163,14 +159,8 @@ pub fn raw_solution() -> RawSolution> { let RoundSnapshot { voters, targets } = MultiPhase::snapshot().unwrap(); let desired_targets = MultiPhase::desired_targets().unwrap(); - let ElectionResult { winners: _, assignments } = - seq_phragmen::<_, SolutionAccuracyOf>( - desired_targets as usize, - targets.clone(), - voters.clone(), - None, - ) - .unwrap(); + let ElectionResult::<_, SolutionAccuracyOf> { winners: _, assignments } = + seq_phragmen(desired_targets as usize, targets.clone(), voters.clone(), None).unwrap(); // closures let cache = helpers::generate_voter_cache::(&voters); @@ -246,16 +236,16 @@ impl pallet_balances::Config for Runtime { parameter_types! { pub static Targets: Vec = vec![10, 20, 30, 40]; - pub static Voters: Vec<(AccountId, VoteWeight, Vec)> = vec![ - (1, 10, vec![10, 20]), - (2, 10, vec![30, 40]), - (3, 10, vec![40]), - (4, 10, vec![10, 20, 30, 40]), + pub static Voters: Vec> = vec![ + (1, 10, bounded_vec![10, 20]), + (2, 10, bounded_vec![30, 40]), + (3, 10, bounded_vec![40]), + (4, 10, bounded_vec![10, 20, 30, 40]), // self votes. - (10, 10, vec![10]), - (20, 20, vec![20]), - (30, 30, vec![30]), - (40, 40, vec![40]), + (10, 10, bounded_vec![10]), + (20, 20, bounded_vec![20]), + (30, 30, bounded_vec![30]), + (40, 40, bounded_vec![40]), ]; pub static DesiredTargets: u32 = 2; @@ -436,6 +426,10 @@ where pub type Extrinsic = sp_runtime::testing::TestXt; +parameter_types! { + pub MaxNominations: u32 = ::LIMIT as u32; +} + #[derive(Default)] pub struct ExtBuilder {} @@ -443,7 +437,7 @@ pub struct StakingMock; impl ElectionDataProvider for StakingMock { type AccountId = AccountId; type BlockNumber = u64; - const MAXIMUM_VOTES_PER_VOTER: u32 = ::LIMIT as u32; + type MaxVotesPerVoter = MaxNominations; fn targets(maybe_max_len: Option) -> data_provider::Result> { let targets = Targets::get(); @@ -454,9 +448,7 @@ impl ElectionDataProvider for StakingMock { Ok(targets) } - fn voters( - maybe_max_len: Option, - ) -> data_provider::Result)>> { + fn voters(maybe_max_len: Option) -> data_provider::Result>> { let mut voters = Voters::get(); if let Some(max_len) = maybe_max_len { voters.truncate(max_len) @@ -475,7 +467,7 @@ impl ElectionDataProvider for StakingMock { #[cfg(feature = "runtime-benchmarks")] fn put_snapshot( - voters: Vec<(AccountId, VoteWeight, Vec)>, + voters: Vec>, targets: Vec, _target_stake: Option, ) { @@ -490,7 +482,11 @@ impl ElectionDataProvider for StakingMock { } #[cfg(feature = "runtime-benchmarks")] - fn add_voter(voter: AccountId, weight: VoteWeight, targets: Vec) { + fn add_voter( + voter: AccountId, + weight: VoteWeight, + targets: frame_support::BoundedVec, + ) { let mut current = Voters::get(); current.push((voter, weight, targets)); Voters::set(current); @@ -505,7 +501,7 @@ impl ElectionDataProvider for StakingMock { // to be on-par with staking, we add a self vote as well. the stake is really not that // important. let mut current = Voters::get(); - current.push((target, ExistentialDeposit::get() as u64, vec![target])); + current.push((target, ExistentialDeposit::get() as u64, bounded_vec![target])); Voters::set(current); } } @@ -540,7 +536,12 @@ impl ExtBuilder { ::set(t); self } - pub fn add_voter(self, who: AccountId, stake: Balance, targets: Vec) -> Self { + pub fn add_voter( + self, + who: AccountId, + stake: Balance, + targets: BoundedVec, + ) -> Self { VOTERS.with(|v| v.borrow_mut().push((who, stake, targets))); self } diff --git a/frame/election-provider-multi-phase/src/unsigned.rs b/frame/election-provider-multi-phase/src/unsigned.rs index da56dd4d073d..936993b41fb6 100644 --- a/frame/election-provider-multi-phase/src/unsigned.rs +++ b/frame/election-provider-multi-phase/src/unsigned.rs @@ -47,11 +47,7 @@ pub(crate) const OFFCHAIN_CACHED_CALL: &[u8] = b"parity/multi-phase-unsigned-ele /// A voter's fundamental data: their ID, their stake, and the list of candidates for whom they /// voted. -pub type Voter = ( - ::AccountId, - sp_npos_elections::VoteWeight, - Vec<::AccountId>, -); +pub type VoterOf = frame_election_provider_support::VoterOf<::DataProvider>; /// The relative distribution of a voter's stake among the winning targets. pub type Assignment = @@ -749,7 +745,9 @@ mod tests { }; use codec::Decode; use frame_benchmarking::Zero; - use frame_support::{assert_noop, assert_ok, dispatch::Dispatchable, traits::OffchainWorker}; + use frame_support::{ + assert_noop, assert_ok, bounded_vec, dispatch::Dispatchable, traits::OffchainWorker, + }; use sp_npos_elections::IndexAssignment; use sp_runtime::{ offchain::storage_lock::{BlockAndTime, StorageLock}, @@ -1048,8 +1046,8 @@ mod tests { fn unsigned_per_dispatch_checks_can_only_submit_threshold_better() { ExtBuilder::default() .desired_targets(1) - .add_voter(7, 2, vec![10]) - .add_voter(8, 5, vec![10]) + .add_voter(7, 2, bounded_vec![10]) + .add_voter(8, 5, bounded_vec![10]) .solution_improvement_threshold(Perbill::from_percent(50)) .build_and_execute(|| { roll_to(25); diff --git a/frame/election-provider-support/src/lib.rs b/frame/election-provider-support/src/lib.rs index 889606da3428..3374e1e97b8b 100644 --- a/frame/election-provider-support/src/lib.rs +++ b/frame/election-provider-support/src/lib.rs @@ -80,6 +80,7 @@ //! ```rust //! # use frame_election_provider_support::{*, data_provider}; //! # use sp_npos_elections::{Support, Assignment}; +//! # use frame_support::traits::ConstU32; //! //! type AccountId = u64; //! type Balance = u64; @@ -101,13 +102,13 @@ //! impl ElectionDataProvider for Pallet { //! type AccountId = AccountId; //! type BlockNumber = BlockNumber; -//! const MAXIMUM_VOTES_PER_VOTER: u32 = 1; +//! type MaxVotesPerVoter = ConstU32<1>; //! //! fn desired_targets() -> data_provider::Result { //! Ok(1) //! } //! fn voters(maybe_max_len: Option) -//! -> data_provider::Result)>> +//! -> data_provider::Result>> //! { //! Ok(Default::default()) //! } @@ -166,7 +167,7 @@ #![cfg_attr(not(feature = "std"), no_std)] pub mod onchain; -use frame_support::traits::Get; +use frame_support::{traits::Get, BoundedVec}; use sp_std::{fmt::Debug, prelude::*}; /// Re-export some type as they are used in the interface. @@ -191,7 +192,7 @@ pub trait ElectionDataProvider { type BlockNumber; /// Maximum number of votes per voter that this data provider is providing. - const MAXIMUM_VOTES_PER_VOTER: u32; + type MaxVotesPerVoter: Get; /// All possible targets for the election, i.e. the candidates. /// @@ -211,9 +212,7 @@ pub trait ElectionDataProvider { /// /// This should be implemented as a self-weighing function. The implementor should register its /// appropriate weight at the end of execution with the system pallet directly. - fn voters( - maybe_max_len: Option, - ) -> data_provider::Result)>>; + fn voters(maybe_max_len: Option) -> data_provider::Result>>; /// The number of targets to elect. /// @@ -233,7 +232,7 @@ pub trait ElectionDataProvider { /// else a noop. #[cfg(any(feature = "runtime-benchmarks", test))] fn put_snapshot( - _voters: Vec<(Self::AccountId, VoteWeight, Vec)>, + _voters: Vec>, _targets: Vec, _target_stake: Option, ) { @@ -244,7 +243,12 @@ pub trait ElectionDataProvider { /// /// Same as `put_snapshot`, but can add a single voter one by one. #[cfg(any(feature = "runtime-benchmarks", test))] - fn add_voter(_voter: Self::AccountId, _weight: VoteWeight, _targets: Vec) {} + fn add_voter( + _voter: Self::AccountId, + _weight: VoteWeight, + _targets: BoundedVec, + ) { + } /// Utility function only to be used in benchmarking scenarios, to be implemented optionally, /// else a noop. @@ -266,19 +270,20 @@ pub struct TestDataProvider(sp_std::marker::PhantomData); impl ElectionDataProvider for TestDataProvider<(AccountId, BlockNumber)> { type AccountId = AccountId; type BlockNumber = BlockNumber; + type MaxVotesPerVoter = (); - const MAXIMUM_VOTES_PER_VOTER: u32 = 0; fn targets(_maybe_max_len: Option) -> data_provider::Result> { Ok(Default::default()) } - fn voters( - _maybe_max_len: Option, - ) -> data_provider::Result)>> { + + fn voters(_maybe_max_len: Option) -> data_provider::Result>> { Ok(Default::default()) } + fn desired_targets() -> data_provider::Result { Ok(Default::default()) } + fn next_election_prediction(now: BlockNumber) -> BlockNumber { now } @@ -421,7 +426,7 @@ pub trait NposSolver { fn solve( to_elect: usize, targets: Vec, - voters: Vec<(Self::AccountId, VoteWeight, Vec)>, + voters: Vec<(Self::AccountId, VoteWeight, impl IntoIterator)>, ) -> Result, Self::Error>; } @@ -443,7 +448,7 @@ impl< fn solve( winners: usize, targets: Vec, - voters: Vec<(Self::AccountId, VoteWeight, Vec)>, + voters: Vec<(Self::AccountId, VoteWeight, impl IntoIterator)>, ) -> Result, Self::Error> { sp_npos_elections::seq_phragmen(winners, targets, voters, Balancing::get()) } @@ -467,8 +472,15 @@ impl< fn solve( winners: usize, targets: Vec, - voters: Vec<(Self::AccountId, VoteWeight, Vec)>, + voters: Vec<(Self::AccountId, VoteWeight, impl IntoIterator)>, ) -> Result, Self::Error> { sp_npos_elections::phragmms(winners, targets, voters, Balancing::get()) } } + +/// A voter, at the level of abstraction of this crate. +pub type Voter = (AccountId, VoteWeight, BoundedVec); + +/// Same as [`Voter`], but parameterized by an [`ElectionDataProvider`]. +pub type VoterOf = + Voter<::AccountId, ::MaxVotesPerVoter>; diff --git a/frame/election-provider-support/src/onchain.rs b/frame/election-provider-support/src/onchain.rs index d325daf51475..808b49ba6234 100644 --- a/frame/election-provider-support/src/onchain.rs +++ b/frame/election-provider-support/src/onchain.rs @@ -87,9 +87,8 @@ impl ElectionProvider for OnChainSequentialPhragmen { let stake_of = |w: &T::AccountId| -> VoteWeight { stake_map.get(w).cloned().unwrap_or_default() }; - let ElectionResult { winners: _, assignments } = - seq_phragmen::<_, T::Accuracy>(desired_targets as usize, targets, voters, None) - .map_err(Error::from)?; + let ElectionResult::<_, T::Accuracy> { winners: _, assignments } = + seq_phragmen(desired_targets as usize, targets, voters, None).map_err(Error::from)?; let staked = assignment_ratio_to_staked_normalized(assignments, &stake_of)?; @@ -161,18 +160,22 @@ mod tests { type OnChainPhragmen = OnChainSequentialPhragmen; mod mock_data_provider { + use frame_support::{bounded_vec, traits::ConstU32}; + use super::*; - use crate::data_provider; + use crate::{data_provider, VoterOf}; pub struct DataProvider; impl ElectionDataProvider for DataProvider { type AccountId = AccountId; type BlockNumber = BlockNumber; - const MAXIMUM_VOTES_PER_VOTER: u32 = 2; - fn voters( - _: Option, - ) -> data_provider::Result)>> { - Ok(vec![(1, 10, vec![10, 20]), (2, 20, vec![30, 20]), (3, 30, vec![10, 30])]) + type MaxVotesPerVoter = ConstU32<2>; + fn voters(_: Option) -> data_provider::Result>> { + Ok(vec![ + (1, 10, bounded_vec![10, 20]), + (2, 20, bounded_vec![30, 20]), + (3, 30, bounded_vec![10, 30]), + ]) } fn targets(_: Option) -> data_provider::Result> { diff --git a/frame/elections-phragmen/src/lib.rs b/frame/elections-phragmen/src/lib.rs index 2c53bb2222b7..bc6a81125e8b 100644 --- a/frame/elections-phragmen/src/lib.rs +++ b/frame/elections-phragmen/src/lib.rs @@ -926,13 +926,13 @@ impl Pallet { let weight_candidates = candidates_and_deposit.len() as u32; let weight_voters = voters_and_votes.len() as u32; let weight_edges = num_edges; - let _ = sp_npos_elections::seq_phragmen::( + let _ = sp_npos_elections::seq_phragmen( num_to_elect, candidate_ids, voters_and_votes.clone(), None, ) - .map(|ElectionResult { winners, assignments: _ }| { + .map(|ElectionResult:: { winners, assignments: _ }| { // this is already sorted by id. let old_members_ids_sorted = >::take().into_iter().map(|m| m.who).collect::>(); diff --git a/frame/grandpa/src/mock.rs b/frame/grandpa/src/mock.rs index 34787c93bb9c..d07f3136d9a0 100644 --- a/frame/grandpa/src/mock.rs +++ b/frame/grandpa/src/mock.rs @@ -186,7 +186,7 @@ impl onchain::Config for Test { } impl pallet_staking::Config for Test { - const MAX_NOMINATIONS: u32 = 16; + type MaxNominations = ConstU32<16>; type RewardRemainder = (); type CurrencyToVote = frame_support::traits::SaturatingCurrencyToVote; type Event = Event; diff --git a/frame/offences/benchmarking/src/lib.rs b/frame/offences/benchmarking/src/lib.rs index 4d6a182034c9..c2e29f0d0fdd 100644 --- a/frame/offences/benchmarking/src/lib.rs +++ b/frame/offences/benchmarking/src/lib.rs @@ -24,7 +24,7 @@ mod mock; use sp_std::{prelude::*, vec}; use frame_benchmarking::{account, benchmarks}; -use frame_support::traits::{Currency, ValidatorSet, ValidatorSetWithIdentification}; +use frame_support::traits::{Currency, Get, ValidatorSet, ValidatorSetWithIdentification}; use frame_system::{Config as SystemConfig, Pallet as System, RawOrigin}; use sp_runtime::{ @@ -275,7 +275,7 @@ benchmarks! { let r in 1 .. MAX_REPORTERS; // we skip 1 offender, because in such case there is no slashing let o in 2 .. MAX_OFFENDERS; - let n in 0 .. MAX_NOMINATORS.min(::MAX_NOMINATIONS); + let n in 0 .. MAX_NOMINATORS.min(::MaxNominations::get()); // Make r reporters let mut reporters = vec![]; @@ -381,7 +381,7 @@ benchmarks! { } report_offence_grandpa { - let n in 0 .. MAX_NOMINATORS.min(::MAX_NOMINATIONS); + let n in 0 .. MAX_NOMINATORS.min(::MaxNominations::get()); // for grandpa equivocation reports the number of reporters // and offenders is always 1 @@ -416,7 +416,7 @@ benchmarks! { } report_offence_babe { - let n in 0 .. MAX_NOMINATORS.min(::MAX_NOMINATIONS); + let n in 0 .. MAX_NOMINATORS.min(::MaxNominations::get()); // for babe equivocation reports the number of reporters // and offenders is always 1 diff --git a/frame/offences/benchmarking/src/mock.rs b/frame/offences/benchmarking/src/mock.rs index 598ba650dfff..3b5e640867c5 100644 --- a/frame/offences/benchmarking/src/mock.rs +++ b/frame/offences/benchmarking/src/mock.rs @@ -156,7 +156,7 @@ impl onchain::Config for Test { } impl pallet_staking::Config for Test { - const MAX_NOMINATIONS: u32 = 16; + type MaxNominations = ConstU32<16>; type Currency = Balances; type UnixTime = pallet_timestamp::Pallet; type CurrencyToVote = frame_support::traits::SaturatingCurrencyToVote; diff --git a/frame/session/benchmarking/src/lib.rs b/frame/session/benchmarking/src/lib.rs index 7beb4631e051..265c35cbe490 100644 --- a/frame/session/benchmarking/src/lib.rs +++ b/frame/session/benchmarking/src/lib.rs @@ -28,7 +28,7 @@ use sp_std::{prelude::*, vec}; use frame_benchmarking::benchmarks; use frame_support::{ codec::Decode, - traits::{KeyOwnerProofSystem, OnInitialize}, + traits::{Get, KeyOwnerProofSystem, OnInitialize}, }; use frame_system::RawOrigin; use pallet_session::{historical::Pallet as Historical, Pallet as Session, *}; @@ -53,10 +53,10 @@ impl OnInitialize for Pallet { benchmarks! { set_keys { - let n = ::MAX_NOMINATIONS; + let n = ::MaxNominations::get(); let (v_stash, _) = create_validator_with_nominators::( n, - ::MAX_NOMINATIONS, + ::MaxNominations::get(), false, RewardDestination::Staked, )?; @@ -70,10 +70,10 @@ benchmarks! { }: _(RawOrigin::Signed(v_controller), keys, proof) purge_keys { - let n = ::MAX_NOMINATIONS; + let n = ::MaxNominations::get(); let (v_stash, _) = create_validator_with_nominators::( n, - ::MAX_NOMINATIONS, + ::MaxNominations::get(), false, RewardDestination::Staked )?; diff --git a/frame/session/benchmarking/src/mock.rs b/frame/session/benchmarking/src/mock.rs index 1f0023660513..37305437ca09 100644 --- a/frame/session/benchmarking/src/mock.rs +++ b/frame/session/benchmarking/src/mock.rs @@ -162,7 +162,7 @@ impl onchain::Config for Test { } impl pallet_staking::Config for Test { - const MAX_NOMINATIONS: u32 = 16; + type MaxNominations = ConstU32<16>; type Currency = Balances; type UnixTime = pallet_timestamp::Pallet; type CurrencyToVote = frame_support::traits::SaturatingCurrencyToVote; diff --git a/frame/staking/src/benchmarking.rs b/frame/staking/src/benchmarking.rs index 8328adc00a97..564172d91241 100644 --- a/frame/staking/src/benchmarking.rs +++ b/frame/staking/src/benchmarking.rs @@ -355,17 +355,17 @@ benchmarks! { kick { // scenario: we want to kick `k` nominators from nominating us (we are a validator). // we'll assume that `k` is under 128 for the purposes of determining the slope. - // each nominator should have `T::MAX_NOMINATIONS` validators nominated, and our validator + // each nominator should have `T::MaxNominations::get()` validators nominated, and our validator // should be somewhere in there. let k in 1 .. 128; - // these are the other validators; there are `T::MAX_NOMINATIONS - 1` of them, so - // there are a total of `T::MAX_NOMINATIONS` validators in the system. - let rest_of_validators = create_validators_with_seed::(T::MAX_NOMINATIONS - 1, 100, 415)?; + // these are the other validators; there are `T::MaxNominations::get() - 1` of them, so + // there are a total of `T::MaxNominations::get()` validators in the system. + let rest_of_validators = create_validators_with_seed::(T::MaxNominations::get() - 1, 100, 415)?; // this is the validator that will be kicking. let (stash, controller) = create_stash_controller::( - T::MAX_NOMINATIONS - 1, + T::MaxNominations::get() - 1, 100, Default::default(), )?; @@ -380,7 +380,7 @@ benchmarks! { for i in 0 .. k { // create a nominator stash. let (n_stash, n_controller) = create_stash_controller::( - T::MAX_NOMINATIONS + i, + T::MaxNominations::get() + i, 100, Default::default(), )?; @@ -415,9 +415,9 @@ benchmarks! { } } - // Worst case scenario, T::MAX_NOMINATIONS + // Worst case scenario, T::MaxNominations::get() nominate { - let n in 1 .. T::MAX_NOMINATIONS; + let n in 1 .. T::MaxNominations::get(); // clean up any existing state. clear_validators_and_nominators::(); @@ -428,7 +428,7 @@ benchmarks! { // we are just doing an insert into the origin position. let scenario = ListScenario::::new(origin_weight, true)?; let (stash, controller) = create_stash_controller_with_balance::( - SEED + T::MAX_NOMINATIONS + 1, // make sure the account does not conflict with others + SEED + T::MaxNominations::get() + 1, // make sure the account does not conflict with others origin_weight, Default::default(), ).unwrap(); @@ -724,7 +724,7 @@ benchmarks! { create_validators_with_nominators_for_era::( v, n, - ::MAX_NOMINATIONS as usize, + ::MaxNominations::get() as usize, false, None, )?; @@ -742,7 +742,7 @@ benchmarks! { create_validators_with_nominators_for_era::( v, n, - ::MAX_NOMINATIONS as usize, + ::MaxNominations::get() as usize, false, None, )?; @@ -822,7 +822,7 @@ benchmarks! { let s in 1 .. 20; let validators = create_validators_with_nominators_for_era::( - v, n, T::MAX_NOMINATIONS as usize, false, None + v, n, T::MaxNominations::get() as usize, false, None )? .into_iter() .map(|v| T::Lookup::lookup(v).unwrap()) @@ -845,7 +845,7 @@ benchmarks! { let n = MaxNominators::::get(); let _ = create_validators_with_nominators_for_era::( - v, n, T::MAX_NOMINATIONS as usize, false, None + v, n, T::MaxNominations::get() as usize, false, None )?; }: { let targets = >::get_npos_targets(); @@ -923,7 +923,7 @@ mod tests { create_validators_with_nominators_for_era::( v, n, - ::MAX_NOMINATIONS as usize, + ::MaxNominations::get() as usize, false, None, ) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index efe67c8b00c8..f1d4cd1e07c2 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -303,6 +303,7 @@ use codec::{Decode, Encode, HasCompact}; use frame_support::{ traits::{ConstU32, Currency, Get}, weights::Weight, + BoundedVec, EqNoBound, PartialEqNoBound, RuntimeDebugNoBound, }; use scale_info::TypeInfo; use sp_runtime::{ @@ -574,10 +575,12 @@ where } /// A record of the nominations made by a specific account. -#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo)] -pub struct Nominations { +#[derive(PartialEqNoBound, EqNoBound, Clone, Encode, Decode, RuntimeDebugNoBound, TypeInfo)] +#[codec(mel_bound(T: Config))] +#[scale_info(skip_type_params(T))] +pub struct Nominations { /// The targets of nomination. - pub targets: Vec, + pub targets: BoundedVec, /// The era the nominations were submitted. /// /// Except for initial nominations which are considered submitted at era 0. diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index 3bf46588044a..95f305dfdd22 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -234,6 +234,7 @@ const THRESHOLDS: [sp_npos_elections::VoteWeight; 9] = parameter_types! { pub static BagThresholds: &'static [sp_npos_elections::VoteWeight] = &THRESHOLDS; + pub static MaxNominations: u32 = 16; } impl pallet_bags_list::Config for Test { @@ -249,7 +250,7 @@ impl onchain::Config for Test { } impl crate::pallet::pallet::Config for Test { - const MAX_NOMINATIONS: u32 = 16; + type MaxNominations = MaxNominations; type Currency = Balances; type UnixTime = Timestamp; type CurrencyToVote = frame_support::traits::SaturatingCurrencyToVote; @@ -533,7 +534,7 @@ fn post_conditions() { } fn check_count() { - let nominator_count = Nominators::::iter().count() as u32; + let nominator_count = Nominators::::iter_keys().count() as u32; let validator_count = Validators::::iter().count() as u32; assert_eq!(nominator_count, Nominators::::count()); assert_eq!(validator_count, Validators::::count()); diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index a72d2774dee2..ae20550cd40b 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -19,7 +19,7 @@ use frame_election_provider_support::{ data_provider, ElectionDataProvider, ElectionProvider, SortedListProvider, Supports, - VoteWeight, VoteWeightProvider, + VoteWeight, VoteWeightProvider, VoterOf, }; use frame_support::{ pallet_prelude::*, @@ -661,9 +661,7 @@ impl Pallet { /// /// All nominations that have been submitted before the last non-zero slash of the validator are /// auto-chilled, but still count towards the limit imposed by `maybe_max_len`. - pub fn get_npos_voters( - maybe_max_len: Option, - ) -> Vec<(T::AccountId, VoteWeight, Vec)> { + pub fn get_npos_voters(maybe_max_len: Option) -> Vec> { let max_allowed_len = { let nominator_count = Nominators::::count() as usize; let validator_count = Validators::::count() as usize; @@ -677,8 +675,13 @@ impl Pallet { let mut validators_taken = 0u32; for (validator, _) in >::iter().take(max_allowed_len) { // Append self vote. - let self_vote = - (validator.clone(), Self::weight_of(&validator), vec![validator.clone()]); + let self_vote = ( + validator.clone(), + Self::weight_of(&validator), + vec![validator.clone()] + .try_into() + .expect("`MaxVotesPerVoter` must be greater than or equal to 1"), + ); all_voters.push(self_vote); validators_taken.saturating_inc(); } @@ -724,7 +727,12 @@ impl Pallet { nominators_taken.saturating_inc(); } } else { - log!(error, "DEFENSIVE: invalid item in `SortedListProvider`: {:?}", nominator) + // this can only happen if: 1. there a pretty bad bug in the bags-list (or whatever + // is the sorted list) logic and the state of the two pallets is no longer + // compatible, or because the nominators is not decodable since they have more + // nomination than `T::MaxNominations`. This can rarely happen, and is not really an + // emergency or bug if it does. + log!(warn, "DEFENSIVE: invalid item in `SortedListProvider`: {:?}, this nominator probably has too many nominations now", nominator) } } @@ -772,7 +780,7 @@ impl Pallet { /// NOTE: you must ALWAYS use this function to add nominator or update their targets. Any access /// to `Nominators` or `VoterList` outside of this function is almost certainly /// wrong. - pub fn do_add_nominator(who: &T::AccountId, nominations: Nominations) { + pub fn do_add_nominator(who: &T::AccountId, nominations: Nominations) { if !Nominators::::contains_key(who) { // maybe update sorted list. Error checking is defensive-only - this should never fail. let _ = T::SortedListProvider::on_insert(who.clone(), Self::weight_of(who)) @@ -845,16 +853,14 @@ impl Pallet { impl ElectionDataProvider for Pallet { type AccountId = T::AccountId; type BlockNumber = BlockNumberFor; - const MAXIMUM_VOTES_PER_VOTER: u32 = T::MAX_NOMINATIONS; + type MaxVotesPerVoter = T::MaxNominations; fn desired_targets() -> data_provider::Result { Self::register_weight(T::DbWeight::get().reads(1)); Ok(Self::validator_count()) } - fn voters( - maybe_max_len: Option, - ) -> data_provider::Result)>> { + fn voters(maybe_max_len: Option) -> data_provider::Result>> { // This can never fail -- if `maybe_max_len` is `Some(_)` we handle it. let voters = Self::get_npos_voters(maybe_max_len); debug_assert!(maybe_max_len.map_or(true, |max| voters.len() <= max)); @@ -907,7 +913,11 @@ impl ElectionDataProvider for Pallet { } #[cfg(feature = "runtime-benchmarks")] - fn add_voter(voter: T::AccountId, weight: VoteWeight, targets: Vec) { + fn add_voter( + voter: T::AccountId, + weight: VoteWeight, + targets: BoundedVec, + ) { let stake = >::try_from(weight).unwrap_or_else(|_| { panic!("cannot convert a VoteWeight into BalanceOf, benchmark needs reconfiguring.") }); @@ -922,6 +932,7 @@ impl ElectionDataProvider for Pallet { claimed_rewards: vec![], }, ); + Self::do_add_nominator(&voter, Nominations { targets, submitted_in: 0, suppressed: false }); } @@ -957,7 +968,7 @@ impl ElectionDataProvider for Pallet { #[cfg(feature = "runtime-benchmarks")] fn put_snapshot( - voters: Vec<(T::AccountId, VoteWeight, Vec)>, + voters: Vec>, targets: Vec, target_stake: Option, ) { @@ -999,7 +1010,7 @@ impl ElectionDataProvider for Pallet { ); Self::do_add_nominator( &v, - Nominations { targets: t, submitted_in: 0, suppressed: false }, + Nominations { targets: t.try_into().unwrap(), submitted_in: 0, suppressed: false }, ); }); } diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 20864e4829e6..2a870fda063d 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -32,7 +32,7 @@ use sp_runtime::{ DispatchError, Perbill, Percent, }; use sp_staking::{EraIndex, SessionIndex}; -use sp_std::{convert::From, prelude::*, result}; +use sp_std::{convert::From, prelude::*}; mod impls; @@ -50,6 +50,8 @@ const STAKING_ID: LockIdentifier = *b"staking "; #[frame_support::pallet] pub mod pallet { + use frame_election_provider_support::ElectionDataProvider; + use crate::BenchmarkingConfig; use super::*; @@ -94,7 +96,7 @@ pub mod pallet { >; /// Maximum number of nominations per nominator. - const MAX_NOMINATIONS: u32; + type MaxNominations: Get; /// Tokens have been minted and are unused for validator-reward. /// See [Era payout](./index.html#era-payout). @@ -161,15 +163,6 @@ pub mod pallet { type WeightInfo: WeightInfo; } - #[pallet::extra_constants] - impl Pallet { - // TODO: rename to snake case after https://github.com/paritytech/substrate/issues/8826 fixed. - #[allow(non_snake_case)] - fn MaxNominations() -> u32 { - T::MAX_NOMINATIONS - } - } - #[pallet::type_value] pub(crate) fn HistoryDepthOnEmpty() -> u32 { 84u32 @@ -246,11 +239,26 @@ pub mod pallet { #[pallet::storage] pub type MaxValidatorsCount = StorageValue<_, u32, OptionQuery>; - /// The map from nominator stash key to the set of stash keys of all validators to nominate. + /// The map from nominator stash key to their nomination preferences, namely the validators that + /// they wish to support. + /// + /// Note that the keys of this storage map might become non-decodable in case the + /// [`Config::MaxNominations`] configuration is decreased. In this rare case, these nominators + /// are still existent in storage, their key is correct and retrievable (i.e. `contains_key` + /// indicates that they exist), but their value cannot be decoded. Therefore, the non-decodable + /// nominators will effectively not-exist, until they re-submit their preferences such that it + /// is within the bounds of the newly set `Config::MaxNominations`. + /// + /// This implies that `::iter_keys().count()` and `::iter().count()` might return different + /// values for this map. Moreover, the main `::count()` is aligned with the former, namely the + /// number of keys that exist. + /// + /// Lastly, if any of the nominators become non-decodable, they can be chilled immediately via + /// [`Call::chill_other`] dispatchable by anyone. #[pallet::storage] #[pallet::getter(fn nominators)] pub type Nominators = - CountedStorageMap<_, Twox64Concat, T::AccountId, Nominations>; + CountedStorageMap<_, Twox64Concat, T::AccountId, Nominations>; /// The maximum nominator count before we stop allowing new validators to join. /// @@ -681,6 +689,14 @@ pub mod pallet { } fn integrity_test() { + // ensure that we funnel the correct value to the `DataProvider::MaxVotesPerVoter`; + assert_eq!( + T::MaxNominations::get(), + ::MaxVotesPerVoter::get() + ); + // and that MaxNominations is always greater than 1, since we count on this. + assert!(!T::MaxNominations::get().is_zero()); + sp_std::if_std! { sp_io::TestExternalities::new_empty().execute_with(|| assert!( @@ -978,7 +994,7 @@ pub mod pallet { /// /// # /// - The transaction's complexity is proportional to the size of `targets` (N) - /// which is capped at CompactAssignments::LIMIT (MAX_NOMINATIONS). + /// which is capped at CompactAssignments::LIMIT (T::MaxNominations). /// - Both the reads and writes follow a similar pattern. /// # #[pallet::weight(T::WeightInfo::nominate(targets.len() as u32))] @@ -1006,11 +1022,11 @@ pub mod pallet { } ensure!(!targets.is_empty(), Error::::EmptyTargets); - ensure!(targets.len() <= T::MAX_NOMINATIONS as usize, Error::::TooManyTargets); + ensure!(targets.len() <= T::MaxNominations::get() as usize, Error::::TooManyTargets); - let old = Nominators::::get(stash).map_or_else(Vec::new, |x| x.targets); + let old = Nominators::::get(stash).map_or_else(Vec::new, |x| x.targets.into_inner()); - let targets = targets + let targets: BoundedVec<_, _> = targets .into_iter() .map(|t| T::Lookup::lookup(t).map_err(DispatchError::from)) .map(|n| { @@ -1022,11 +1038,13 @@ pub mod pallet { } }) }) - .collect::, _>>()?; + .collect::, _>>()? + .try_into() + .map_err(|_| Error::::TooManyNominators)?; let nominations = Nominations { targets, - // Initial nominations are considered submitted at era 0. See `Nominations` doc + // Initial nominations are considered submitted at era 0. See `Nominations` doc. submitted_in: Self::current_era().unwrap_or(0), suppressed: false, }; @@ -1216,11 +1234,6 @@ pub mod pallet { /// Set the validators who cannot be slashed (if any). /// /// The dispatch origin must be Root. - /// - /// # - /// - O(V) - /// - Write: Invulnerables - /// # #[pallet::weight(T::WeightInfo::set_invulnerables(invulnerables.len() as u32))] pub fn set_invulnerables( origin: OriginFor, @@ -1234,13 +1247,6 @@ pub mod pallet { /// Force a current staker to become completely unstaked, immediately. /// /// The dispatch origin must be Root. - /// - /// # - /// O(S) where S is the number of slashing spans to be removed - /// Reads: Bonded, Slashing Spans, Account, Locks - /// Writes: Bonded, Slashing Spans (if S > 0), Ledger, Payee, Validators, Nominators, - /// Account, Locks Writes Each: SpanSlash * S - /// # #[pallet::weight(T::WeightInfo::force_unstake(*num_slashing_spans))] pub fn force_unstake( origin: OriginFor, @@ -1266,11 +1272,6 @@ pub mod pallet { /// The election process starts multiple blocks before the end of the era. /// If this is called just before a new era is triggered, the election process may not /// have enough blocks to get a result. - /// - /// # - /// - Weight: O(1) - /// - Write: ForceEra - /// # #[pallet::weight(T::WeightInfo::force_new_era_always())] pub fn force_new_era_always(origin: OriginFor) -> DispatchResult { ensure_root(origin)?; @@ -1283,14 +1284,6 @@ pub mod pallet { /// Can be called by the `T::SlashCancelOrigin`. /// /// Parameters: era and indices of the slashes for that era to kill. - /// - /// # - /// Complexity: O(U + S) - /// with U unapplied slashes weighted with U=1000 - /// and S is the number of slash indices to be canceled. - /// - Read: Unapplied Slashes - /// - Write: Unapplied Slashes - /// # #[pallet::weight(T::WeightInfo::cancel_deferred_slash(slash_indices.len() as u32))] pub fn cancel_deferred_slash( origin: OriginFor, @@ -1550,6 +1543,11 @@ pub mod pallet { /// /// If the caller is different than the controller being targeted, the following conditions /// must be met: + /// + /// * `controller` must belong to a nominator who has become non-decodable, + /// + /// Or: + /// /// * A `ChillThreshold` must be set and checked which defines how close to the max /// nominators or validators we must reach before users can start chilling one-another. /// * A `MaxNominatorCount` and `MaxValidatorCount` must be set which is used to determine @@ -1568,6 +1566,11 @@ pub mod pallet { let stash = ledger.stash; // In order for one user to chill another user, the following conditions must be met: + // + // * `controller` belongs to a nominator who has become non-decodable, + // + // Or + // // * A `ChillThreshold` is set which defines how close to the max nominators or // validators we must reach before users can start chilling one-another. // * A `MaxNominatorCount` and `MaxValidatorCount` which is used to determine how close @@ -1577,6 +1580,12 @@ pub mod pallet { // threshold bond required. // // Otherwise, if caller is the same as the controller, this is just like `chill`. + + if Nominators::::contains_key(&stash) && Nominators::::get(&stash).is_none() { + Self::chill_stash(&stash); + return Ok(()) + } + if caller != controller { let threshold = ChillThreshold::::get().ok_or(Error::::CannotChillOther)?; let min_active_bond = if Nominators::::contains_key(&stash) { diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 8d465c8c93dc..538b75ead340 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -4248,7 +4248,11 @@ fn count_check_works() { Validators::::insert(987654321, ValidatorPrefs::default()); Nominators::::insert( 987654321, - Nominations { targets: vec![], submitted_in: Default::default(), suppressed: false }, + Nominations { + targets: Default::default(), + submitted_in: Default::default(), + suppressed: false, + }, ); }) } @@ -4589,6 +4593,100 @@ fn min_commission_works() { }) } +#[test] +fn change_of_max_nominations() { + use frame_election_provider_support::ElectionDataProvider; + ExtBuilder::default() + .add_staker(60, 61, 10, StakerStatus::Nominator(vec![1])) + .add_staker(70, 71, 10, StakerStatus::Nominator(vec![1, 2, 3])) + .balance_factor(10) + .build_and_execute(|| { + // pre-condition + assert_eq!(MaxNominations::get(), 16); + + assert_eq!( + Nominators::::iter() + .map(|(k, n)| (k, n.targets.len())) + .collect::>(), + vec![(70, 3), (101, 2), (60, 1)] + ); + // 3 validators and 3 nominators + assert_eq!(Staking::voters(None).unwrap().len(), 3 + 3); + + // abrupt change from 16 to 4, everyone should be fine. + MaxNominations::set(4); + + assert_eq!( + Nominators::::iter() + .map(|(k, n)| (k, n.targets.len())) + .collect::>(), + vec![(70, 3), (101, 2), (60, 1)] + ); + assert_eq!(Staking::voters(None).unwrap().len(), 3 + 3); + + // abrupt change from 4 to 3, everyone should be fine. + MaxNominations::set(3); + + assert_eq!( + Nominators::::iter() + .map(|(k, n)| (k, n.targets.len())) + .collect::>(), + vec![(70, 3), (101, 2), (60, 1)] + ); + assert_eq!(Staking::voters(None).unwrap().len(), 3 + 3); + + // abrupt change from 3 to 2, this should cause some nominators to be non-decodable, and + // thus non-existent unless if they update. + MaxNominations::set(2); + + assert_eq!( + Nominators::::iter() + .map(|(k, n)| (k, n.targets.len())) + .collect::>(), + vec![(101, 2), (60, 1)] + ); + // 70 is still in storage.. + assert!(Nominators::::contains_key(70)); + // but its value cannot be decoded and default is returned. + assert!(Nominators::::get(70).is_none()); + + assert_eq!(Staking::voters(None).unwrap().len(), 3 + 2); + assert!(Nominators::::contains_key(101)); + + // abrupt change from 2 to 1, this should cause some nominators to be non-decodable, and + // thus non-existent unless if they update. + MaxNominations::set(1); + + assert_eq!( + Nominators::::iter() + .map(|(k, n)| (k, n.targets.len())) + .collect::>(), + vec![(60, 1)] + ); + assert!(Nominators::::contains_key(70)); + assert!(Nominators::::contains_key(60)); + assert!(Nominators::::get(70).is_none()); + assert!(Nominators::::get(60).is_some()); + assert_eq!(Staking::voters(None).unwrap().len(), 3 + 1); + + // now one of them can revive themselves by re-nominating to a proper value. + assert_ok!(Staking::nominate(Origin::signed(71), vec![1])); + assert_eq!( + Nominators::::iter() + .map(|(k, n)| (k, n.targets.len())) + .collect::>(), + vec![(70, 1), (60, 1)] + ); + + // or they can be chilled by any account. + assert!(Nominators::::contains_key(101)); + assert!(Nominators::::get(101).is_none()); + assert_ok!(Staking::chill_other(Origin::signed(70), 100)); + assert!(!Nominators::::contains_key(101)); + assert!(Nominators::::get(101).is_none()); + }) +} + mod sorted_list_provider { use super::*; use frame_election_provider_support::SortedListProvider; diff --git a/frame/support/src/lib.rs b/frame/support/src/lib.rs index fc2754c5c555..ef60729f6d86 100644 --- a/frame/support/src/lib.rs +++ b/frame/support/src/lib.rs @@ -114,6 +114,29 @@ impl TypeId for PalletId { const TYPE_ID: [u8; 4] = *b"modl"; } +/// Build a bounded vec from the given literals. +/// +/// The type of the outcome must be known. +/// +/// Will not handle any errors and just panic if the given literals cannot fit in the corresponding +/// bounded vec type. Thus, this is only suitable for testing and non-consensus code. +#[macro_export] +#[cfg(feature = "std")] +macro_rules! bounded_vec { + ($ ($values:expr),* ) => { + { + use $crate::sp_std::convert::TryInto as _; + $crate::sp_std::vec![$($values),*].try_into().unwrap() + } + }; + ( $value:expr ; $repetition:expr ) => { + { + use $crate::sp_std::convert::TryInto as _; + $crate::sp_std::vec![$value ; $repetition].try_into().unwrap() + } + } +} + /// Generate a new type alias for [`storage::types::StorageValue`], /// [`storage::types::StorageMap`], [`storage::types::StorageDoubleMap`] /// and [`storage::types::StorageNMap`]. diff --git a/frame/support/src/storage/bounded_vec.rs b/frame/support/src/storage/bounded_vec.rs index 6b20ed2bba90..9298a5d98b00 100644 --- a/frame/support/src/storage/bounded_vec.rs +++ b/frame/support/src/storage/bounded_vec.rs @@ -664,6 +664,19 @@ pub mod test { assert_eq!(*bounded, vec![1, 0, 2, 3]); } + #[test] + fn constructor_macro_works() { + use frame_support::bounded_vec; + + // With values. Use some brackets to make sure the macro doesn't expand. + let bv: BoundedVec<(u32, u32), ConstU32<3>> = bounded_vec![(1, 2), (1, 2), (1, 2)]; + assert_eq!(bv, vec![(1, 2), (1, 2), (1, 2)]); + + // With repetition. + let bv: BoundedVec<(u32, u32), ConstU32<3>> = bounded_vec![(1, 2); 3]; + assert_eq!(bv, vec![(1, 2), (1, 2), (1, 2)]); + } + #[test] #[should_panic(expected = "insertion index (is 9) should be <= len (is 3)")] fn try_inert_panics_if_oob() { diff --git a/frame/support/src/storage/types/counted_map.rs b/frame/support/src/storage/types/counted_map.rs index 0f98b13282a7..7f53b196c815 100644 --- a/frame/support/src/storage/types/counted_map.rs +++ b/frame/support/src/storage/types/counted_map.rs @@ -401,6 +401,13 @@ where ) -> crate::storage::PrefixIterator<(Key, Value), OnRemovalCounterUpdate> { ::Map::iter_from(starting_raw_key).convert_on_removal() } + + /// Enumerate all keys in the counted map. + /// + /// If you alter the map while doing this, you'll get undefined results. + pub fn iter_keys() -> crate::storage::KeyPrefixIterator { + ::Map::iter_keys() + } } impl StorageEntryMetadataBuilder diff --git a/frame/system/src/lib.rs b/frame/system/src/lib.rs index 800ffbfd20dc..878edd7840e7 100644 --- a/frame/system/src/lib.rs +++ b/frame/system/src/lib.rs @@ -479,11 +479,6 @@ pub mod pallet { } /// Make some on-chain remark and emit event. - /// - /// # - /// - `O(b)` where b is the length of the remark. - /// - 1 event. - /// # #[pallet::weight(T::SystemWeightInfo::remark_with_event(remark.len() as u32))] pub fn remark_with_event( origin: OriginFor, diff --git a/primitives/npos-elections/fuzzer/src/common.rs b/primitives/npos-elections/fuzzer/src/common.rs index ab765d20640e..1bef899d5e54 100644 --- a/primitives/npos-elections/fuzzer/src/common.rs +++ b/primitives/npos-elections/fuzzer/src/common.rs @@ -158,20 +158,10 @@ pub fn generate_random_npos_result( ( match election_type { - ElectionType::Phragmen(conf) => seq_phragmen::( - to_elect, - candidates.clone(), - voters.clone(), - conf, - ) - .unwrap(), - ElectionType::Phragmms(conf) => phragmms::( - to_elect, - candidates.clone(), - voters.clone(), - conf, - ) - .unwrap(), + ElectionType::Phragmen(conf) => + seq_phragmen(to_elect, candidates.clone(), voters.clone(), conf).unwrap(), + ElectionType::Phragmms(conf) => + phragmms(to_elect, candidates.clone(), voters.clone(), conf).unwrap(), }, candidates, voters, diff --git a/primitives/npos-elections/fuzzer/src/phragmen_balancing.rs b/primitives/npos-elections/fuzzer/src/phragmen_balancing.rs index 2af6a4c0f815..8f782405df52 100644 --- a/primitives/npos-elections/fuzzer/src/phragmen_balancing.rs +++ b/primitives/npos-elections/fuzzer/src/phragmen_balancing.rs @@ -24,7 +24,7 @@ use honggfuzz::fuzz; use rand::{self, SeedableRng}; use sp_npos_elections::{ assignment_ratio_to_staked_normalized, is_score_better, seq_phragmen, to_supports, - EvaluateSupport, VoteWeight, + ElectionResult, EvaluateSupport, VoteWeight, }; use sp_runtime::Perbill; @@ -68,13 +68,8 @@ fn main() { }; if iterations > 0 { - let balanced = seq_phragmen::( - to_elect, - candidates, - voters, - Some((iterations, 0)), - ) - .unwrap(); + let balanced: ElectionResult = + seq_phragmen(to_elect, candidates, voters, Some((iterations, 0))).unwrap(); let balanced_score = { let staked = assignment_ratio_to_staked_normalized( diff --git a/primitives/npos-elections/fuzzer/src/phragmms_balancing.rs b/primitives/npos-elections/fuzzer/src/phragmms_balancing.rs index 0cd49c3f8044..f2b12b137883 100644 --- a/primitives/npos-elections/fuzzer/src/phragmms_balancing.rs +++ b/primitives/npos-elections/fuzzer/src/phragmms_balancing.rs @@ -23,8 +23,8 @@ use common::*; use honggfuzz::fuzz; use rand::{self, SeedableRng}; use sp_npos_elections::{ - assignment_ratio_to_staked_normalized, is_score_better, phragmms, to_supports, EvaluateSupport, - VoteWeight, + assignment_ratio_to_staked_normalized, is_score_better, phragmms, to_supports, ElectionResult, + EvaluateSupport, VoteWeight, }; use sp_runtime::Perbill; @@ -67,13 +67,8 @@ fn main() { score }; - let balanced = phragmms::( - to_elect, - candidates, - voters, - Some((iterations, 0)), - ) - .unwrap(); + let balanced: ElectionResult = + phragmms(to_elect, candidates, voters, Some((iterations, 0))).unwrap(); let balanced_score = { let staked = diff --git a/primitives/npos-elections/src/lib.rs b/primitives/npos-elections/src/lib.rs index bb1c38d3077c..7b3b09a4c734 100644 --- a/primitives/npos-elections/src/lib.rs +++ b/primitives/npos-elections/src/lib.rs @@ -471,7 +471,7 @@ pub fn is_score_better(this: ElectionScore, that: ElectionScore, ep /// - It drops duplicate targets within a voter. pub fn setup_inputs( initial_candidates: Vec, - initial_voters: Vec<(AccountId, VoteWeight, Vec)>, + initial_voters: Vec<(AccountId, VoteWeight, impl IntoIterator)>, ) -> (Vec>, Vec>) { // used to cache and access candidates index. let mut c_idx_cache = BTreeMap::::new(); @@ -496,7 +496,7 @@ pub fn setup_inputs( let voters = initial_voters .into_iter() .filter_map(|(who, voter_stake, votes)| { - let mut edges: Vec> = Vec::with_capacity(votes.len()); + let mut edges: Vec> = Vec::new(); for v in votes { if edges.iter().any(|e| e.who == v) { // duplicate edge. diff --git a/primitives/npos-elections/src/mock.rs b/primitives/npos-elections/src/mock.rs index 8e8e7ebc1c0c..85c970d7b418 100644 --- a/primitives/npos-elections/src/mock.rs +++ b/primitives/npos-elections/src/mock.rs @@ -344,7 +344,7 @@ pub(crate) fn run_and_compare( FS: Fn(&AccountId) -> VoteWeight, { // run fixed point code. - let ElectionResult { winners, assignments } = seq_phragmen::<_, Output>( + let ElectionResult::<_, Output> { winners, assignments } = seq_phragmen( to_elect, candidates.clone(), voters diff --git a/primitives/npos-elections/src/phragmen.rs b/primitives/npos-elections/src/phragmen.rs index c582c5910d69..e8e925935f77 100644 --- a/primitives/npos-elections/src/phragmen.rs +++ b/primitives/npos-elections/src/phragmen.rs @@ -70,7 +70,7 @@ const DEN: ExtendedBalance = ExtendedBalance::max_value(); pub fn seq_phragmen( to_elect: usize, candidates: Vec, - voters: Vec<(AccountId, VoteWeight, Vec)>, + voters: Vec<(AccountId, VoteWeight, impl IntoIterator)>, balancing: Option<(usize, ExtendedBalance)>, ) -> Result, crate::Error> { let (candidates, voters) = setup_inputs(candidates, voters); diff --git a/primitives/npos-elections/src/phragmms.rs b/primitives/npos-elections/src/phragmms.rs index 7c51da9ee92e..6220cacd157b 100644 --- a/primitives/npos-elections/src/phragmms.rs +++ b/primitives/npos-elections/src/phragmms.rs @@ -44,7 +44,7 @@ use sp_std::{prelude::*, rc::Rc}; pub fn phragmms( to_elect: usize, candidates: Vec, - voters: Vec<(AccountId, VoteWeight, Vec)>, + voters: Vec<(AccountId, VoteWeight, impl IntoIterator)>, balancing: Option<(usize, ExtendedBalance)>, ) -> Result, crate::Error> { let (candidates, mut voters) = setup_inputs(candidates, voters); @@ -351,8 +351,8 @@ mod tests { let candidates = vec![1, 2, 3]; let voters = vec![(10, 10, vec![1, 2]), (20, 20, vec![1, 3]), (30, 30, vec![2, 3])]; - let ElectionResult { winners, assignments } = - phragmms::<_, Perbill>(2, candidates, voters, Some((2, 0))).unwrap(); + let ElectionResult::<_, Perbill> { winners, assignments } = + phragmms(2, candidates, voters, Some((2, 0))).unwrap(); assert_eq!(winners, vec![(3, 30), (2, 30)]); assert_eq!( assignments, @@ -383,8 +383,8 @@ mod tests { (130, 1000, vec![61, 71]), ]; - let ElectionResult { winners, assignments: _ } = - phragmms::<_, Perbill>(4, candidates, voters, Some((2, 0))).unwrap(); + let ElectionResult::<_, Perbill> { winners, assignments: _ } = + phragmms(4, candidates, voters, Some((2, 0))).unwrap(); assert_eq!(winners, vec![(11, 3000), (31, 2000), (51, 1500), (61, 1500),]); } @@ -396,8 +396,8 @@ mod tests { // give a bit more to 1 and 3. voters.push((2, u64::MAX, vec![1, 3])); - let ElectionResult { winners, assignments: _ } = - phragmms::<_, Perbill>(2, candidates, voters, Some((2, 0))).unwrap(); + let ElectionResult::<_, Perbill> { winners, assignments: _ } = + phragmms(2, candidates, voters, Some((2, 0))).unwrap(); assert_eq!(winners.into_iter().map(|(w, _)| w).collect::>(), vec![1u32, 3]); } } diff --git a/primitives/npos-elections/src/tests.rs b/primitives/npos-elections/src/tests.rs index e7d0078b1fbe..c6748b29e985 100644 --- a/primitives/npos-elections/src/tests.rs +++ b/primitives/npos-elections/src/tests.rs @@ -230,7 +230,7 @@ fn phragmen_poc_works() { let voters = vec![(10, vec![1, 2]), (20, vec![1, 3]), (30, vec![2, 3])]; let stake_of = create_stake_of(&[(10, 10), (20, 20), (30, 30)]); - let ElectionResult { winners, assignments } = seq_phragmen::<_, Perbill>( + let ElectionResult::<_, Perbill> { winners, assignments } = seq_phragmen( 2, candidates, voters @@ -285,7 +285,7 @@ fn phragmen_poc_works_with_balancing() { let voters = vec![(10, vec![1, 2]), (20, vec![1, 3]), (30, vec![2, 3])]; let stake_of = create_stake_of(&[(10, 10), (20, 20), (30, 30)]); - let ElectionResult { winners, assignments } = seq_phragmen::<_, Perbill>( + let ElectionResult::<_, Perbill> { winners, assignments } = seq_phragmen( 2, candidates, voters @@ -372,7 +372,7 @@ fn phragmen_accuracy_on_large_scale_only_candidates() { (5, (u64::MAX - 2).into()), ]); - let ElectionResult { winners, assignments } = seq_phragmen::<_, Perbill>( + let ElectionResult::<_, Perbill> { winners, assignments } = seq_phragmen( 2, candidates.clone(), auto_generate_self_voters(&candidates) @@ -403,7 +403,7 @@ fn phragmen_accuracy_on_large_scale_voters_and_candidates() { (14, u64::MAX.into()), ]); - let ElectionResult { winners, assignments } = seq_phragmen::<_, Perbill>( + let ElectionResult::<_, Perbill> { winners, assignments } = seq_phragmen( 2, candidates, voters @@ -435,7 +435,7 @@ fn phragmen_accuracy_on_small_scale_self_vote() { let voters = auto_generate_self_voters(&candidates); let stake_of = create_stake_of(&[(40, 0), (10, 1), (20, 2), (30, 1)]); - let ElectionResult { winners, assignments } = seq_phragmen::<_, Perbill>( + let ElectionResult::<_, Perbill> { winners, assignments } = seq_phragmen( 3, candidates, voters @@ -465,7 +465,7 @@ fn phragmen_accuracy_on_small_scale_no_self_vote() { (3, 1), ]); - let ElectionResult { winners, assignments } = seq_phragmen::<_, Perbill>( + let ElectionResult::<_, Perbill> { winners, assignments } = seq_phragmen( 3, candidates, voters @@ -501,7 +501,7 @@ fn phragmen_large_scale_test() { (50, 990000000000000000), ]); - let ElectionResult { winners, assignments } = seq_phragmen::<_, Perbill>( + let ElectionResult::<_, Perbill> { winners, assignments } = seq_phragmen( 2, candidates, voters @@ -528,7 +528,7 @@ fn phragmen_large_scale_test_2() { let stake_of = create_stake_of(&[(2, c_budget.into()), (4, c_budget.into()), (50, nom_budget.into())]); - let ElectionResult { winners, assignments } = seq_phragmen::<_, Perbill>( + let ElectionResult::<_, Perbill> { winners, assignments } = seq_phragmen( 2, candidates, voters @@ -597,7 +597,7 @@ fn elect_has_no_entry_barrier() { let voters = vec![(1, vec![10]), (2, vec![20])]; let stake_of = create_stake_of(&[(1, 10), (2, 10)]); - let ElectionResult { winners, assignments: _ } = seq_phragmen::<_, Perbill>( + let ElectionResult::<_, Perbill> { winners, assignments: _ } = seq_phragmen( 3, candidates, voters @@ -618,7 +618,7 @@ fn phragmen_self_votes_should_be_kept() { let voters = vec![(5, vec![5]), (10, vec![10]), (20, vec![20]), (1, vec![10, 20])]; let stake_of = create_stake_of(&[(5, 5), (10, 10), (20, 20), (1, 8)]); - let result = seq_phragmen::<_, Perbill>( + let result: ElectionResult<_, Perbill> = seq_phragmen( 2, candidates, voters @@ -664,8 +664,8 @@ fn duplicate_target_is_ignored() { let candidates = vec![1, 2, 3]; let voters = vec![(10, 100, vec![1, 1, 2, 3]), (20, 100, vec![2, 3]), (30, 50, vec![1, 1, 2])]; - let ElectionResult { winners, assignments } = - seq_phragmen::<_, Perbill>(2, candidates, voters, None).unwrap(); + let ElectionResult::<_, Perbill> { winners, assignments } = + seq_phragmen(2, candidates, voters, None).unwrap(); assert_eq!(winners, vec![(2, 140), (3, 110)]); assert_eq!( @@ -682,8 +682,8 @@ fn duplicate_target_is_ignored_when_winner() { let candidates = vec![1, 2, 3]; let voters = vec![(10, 100, vec![1, 1, 2, 3]), (20, 100, vec![1, 2])]; - let ElectionResult { winners, assignments } = - seq_phragmen::<_, Perbill>(2, candidates, voters, None).unwrap(); + let ElectionResult::<_, Perbill> { winners, assignments } = + seq_phragmen(2, candidates, voters, None).unwrap(); assert_eq!(winners, vec![(1, 100), (2, 100)]); assert_eq!( From f2f99707af3c3c0ba7b5d0cf1bbd48d8408474c2 Mon Sep 17 00:00:00 2001 From: Qinxuan Chen Date: Wed, 26 Jan 2022 03:48:46 +0800 Subject: [PATCH 422/695] use `thiserror` instead of `derive_more` for error handling (#10696) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * use thiserror instead of derive_more for error handling Signed-off-by: koushiro * Update utils/prometheus/src/lib.rs * Update utils/prometheus/src/lib.rs Co-authored-by: Bastian Köcher --- Cargo.lock | 30 ++++---- bin/node/inspect/Cargo.toml | 2 +- bin/node/inspect/src/lib.rs | 19 ++---- client/authority-discovery/Cargo.toml | 2 +- client/authority-discovery/src/error.rs | 68 ++++++++++++------- client/beefy/rpc/Cargo.toml | 1 - client/beefy/rpc/src/lib.rs | 8 +-- client/consensus/aura/Cargo.toml | 2 +- client/consensus/aura/src/lib.rs | 19 +++--- client/consensus/babe/Cargo.toml | 2 +- client/consensus/babe/rpc/Cargo.toml | 4 +- client/consensus/babe/rpc/src/lib.rs | 6 +- client/consensus/babe/src/lib.rs | 61 ++++++++--------- client/consensus/manual-seal/Cargo.toml | 2 +- client/consensus/manual-seal/src/error.rs | 50 ++++++++------ client/consensus/pow/Cargo.toml | 2 +- client/consensus/pow/src/lib.rs | 41 ++++++----- client/executor/common/Cargo.toml | 1 - client/executor/common/src/error.rs | 28 +++++--- client/finality-grandpa/Cargo.toml | 3 +- client/finality-grandpa/rpc/Cargo.toml | 2 +- client/finality-grandpa/rpc/src/error.rs | 12 ++-- client/finality-grandpa/src/authorities.rs | 19 +++--- client/finality-grandpa/src/finality_proof.rs | 9 +-- client/finality-grandpa/src/warp_proof.rs | 17 +++-- client/keystore/Cargo.toml | 2 +- client/keystore/src/lib.rs | 30 +++----- client/network/Cargo.toml | 3 +- client/network/src/bitswap.rs | 26 ++++--- client/network/src/block_request_handler.rs | 23 ++++--- client/network/src/error.rs | 39 ++++------- .../src/light_client_requests/handler.rs | 18 ++--- .../src/protocol/notifications/handler.rs | 4 +- .../notifications/upgrade/notifications.rs | 15 ++-- client/network/src/request_responses.rs | 23 ++++--- client/network/src/service.rs | 4 +- client/network/src/state_request_handler.rs | 23 ++++--- client/network/src/warp_request_handler.rs | 29 ++++---- client/transaction-pool/api/Cargo.toml | 9 ++- client/transaction-pool/api/src/error.rs | 3 +- client/transaction-pool/src/lib.rs | 8 +-- primitives/keystore/Cargo.toml | 10 +-- primitives/keystore/src/lib.rs | 10 +-- .../runtime/transaction-pool/Cargo.toml | 2 +- .../runtime/transaction-pool/src/lib.rs | 11 +-- utils/prometheus/Cargo.toml | 2 +- utils/prometheus/src/lib.rs | 27 +++----- 47 files changed, 376 insertions(+), 355 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 39cb42be7a85..a8092fffa7c0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -520,7 +520,6 @@ version = "4.0.0-dev" dependencies = [ "beefy-gadget", "beefy-primitives", - "derive_more", "futures 0.3.16", "jsonrpc-core", "jsonrpc-core-client", @@ -4710,7 +4709,6 @@ name = "node-inspect" version = "0.9.0-dev" dependencies = [ "clap 3.0.7", - "derive_more", "parity-scale-codec", "sc-cli", "sc-client-api", @@ -4719,6 +4717,7 @@ dependencies = [ "sp-blockchain", "sp-core", "sp-runtime", + "thiserror", ] [[package]] @@ -7647,7 +7646,6 @@ name = "sc-authority-discovery" version = "0.10.0-dev" dependencies = [ "async-trait", - "derive_more", "futures 0.3.16", "futures-timer", "ip_network", @@ -7669,6 +7667,7 @@ dependencies = [ "sp-tracing", "substrate-prometheus-endpoint", "substrate-test-runtime-client", + "thiserror", ] [[package]] @@ -7863,7 +7862,6 @@ name = "sc-consensus-aura" version = "0.10.0-dev" dependencies = [ "async-trait", - "derive_more", "futures 0.3.16", "getrandom 0.2.3", "log 0.4.14", @@ -7894,6 +7892,7 @@ dependencies = [ "substrate-prometheus-endpoint", "substrate-test-runtime-client", "tempfile", + "thiserror", ] [[package]] @@ -7901,7 +7900,6 @@ name = "sc-consensus-babe" version = "0.10.0-dev" dependencies = [ "async-trait", - "derive_more", "fork-tree", "futures 0.3.16", "log 0.4.14", @@ -7944,13 +7942,13 @@ dependencies = [ "substrate-prometheus-endpoint", "substrate-test-runtime-client", "tempfile", + "thiserror", ] [[package]] name = "sc-consensus-babe-rpc" version = "0.10.0-dev" dependencies = [ - "derive_more", "futures 0.3.16", "jsonrpc-core", "jsonrpc-core-client", @@ -7973,6 +7971,7 @@ dependencies = [ "sp-runtime", "substrate-test-runtime-client", "tempfile", + "thiserror", ] [[package]] @@ -7993,7 +7992,6 @@ version = "0.10.0-dev" dependencies = [ "assert_matches", "async-trait", - "derive_more", "futures 0.3.16", "jsonrpc-core", "jsonrpc-core-client", @@ -8023,6 +8021,7 @@ dependencies = [ "substrate-prometheus-endpoint", "substrate-test-runtime-client", "substrate-test-runtime-transaction-pool", + "thiserror", "tokio", ] @@ -8031,7 +8030,6 @@ name = "sc-consensus-pow" version = "0.10.0-dev" dependencies = [ "async-trait", - "derive_more", "futures 0.3.16", "futures-timer", "log 0.4.14", @@ -8048,6 +8046,7 @@ dependencies = [ "sp-inherents", "sp-runtime", "substrate-prometheus-endpoint", + "thiserror", ] [[package]] @@ -8128,7 +8127,6 @@ dependencies = [ name = "sc-executor-common" version = "0.10.0-dev" dependencies = [ - "derive_more", "environmental", "parity-scale-codec", "sc-allocator", @@ -8184,7 +8182,6 @@ version = "0.10.0-dev" dependencies = [ "assert_matches", "async-trait", - "derive_more", "dyn-clone", "finality-grandpa", "fork-tree", @@ -8219,6 +8216,7 @@ dependencies = [ "substrate-prometheus-endpoint", "substrate-test-runtime-client", "tempfile", + "thiserror", "tokio", ] @@ -8226,7 +8224,6 @@ dependencies = [ name = "sc-finality-grandpa-rpc" version = "0.10.0-dev" dependencies = [ - "derive_more", "finality-grandpa", "futures 0.3.16", "jsonrpc-core", @@ -8247,6 +8244,7 @@ dependencies = [ "sp-keyring", "sp-runtime", "substrate-test-runtime-client", + "thiserror", ] [[package]] @@ -8270,7 +8268,6 @@ name = "sc-keystore" version = "4.0.0-dev" dependencies = [ "async-trait", - "derive_more", "hex", "parking_lot 0.11.2", "serde_json", @@ -8278,6 +8275,7 @@ dependencies = [ "sp-core", "sp-keystore", "tempfile", + "thiserror", ] [[package]] @@ -8291,7 +8289,6 @@ dependencies = [ "bitflags", "bytes 1.1.0", "cid", - "derive_more", "either", "fnv", "fork-tree", @@ -8762,7 +8759,6 @@ dependencies = [ name = "sc-transaction-pool-api" version = "4.0.0-dev" dependencies = [ - "derive_more", "futures 0.3.16", "log 0.4.14", "serde", @@ -9632,7 +9628,6 @@ name = "sp-keystore" version = "0.10.0" dependencies = [ "async-trait", - "derive_more", "futures 0.3.16", "merlin", "parity-scale-codec", @@ -9643,6 +9638,7 @@ dependencies = [ "serde", "sp-core", "sp-externalities", + "thiserror", ] [[package]] @@ -10211,11 +10207,11 @@ name = "substrate-prometheus-endpoint" version = "0.10.0-dev" dependencies = [ "async-std", - "derive_more", "futures-util", "hyper 0.14.16", "log 0.4.14", "prometheus", + "thiserror", "tokio", ] @@ -10312,7 +10308,6 @@ dependencies = [ name = "substrate-test-runtime-transaction-pool" version = "2.0.0" dependencies = [ - "derive_more", "futures 0.3.16", "parity-scale-codec", "parking_lot 0.11.2", @@ -10321,6 +10316,7 @@ dependencies = [ "sp-blockchain", "sp-runtime", "substrate-test-runtime-client", + "thiserror", ] [[package]] diff --git a/bin/node/inspect/Cargo.toml b/bin/node/inspect/Cargo.toml index 49470a7e7b05..bb9af8c66988 100644 --- a/bin/node/inspect/Cargo.toml +++ b/bin/node/inspect/Cargo.toml @@ -13,7 +13,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] clap = { version = "3.0", features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.0.0" } -derive_more = "0.99" +thiserror = "1.0" sc-cli = { version = "0.10.0-dev", path = "../../../client/cli" } sc-client-api = { version = "4.0.0-dev", path = "../../../client/api" } sc-executor = { version = "0.10.0-dev", path = "../../../client/executor" } diff --git a/bin/node/inspect/src/lib.rs b/bin/node/inspect/src/lib.rs index ff1eecd219a9..b37c5aa7ca2e 100644 --- a/bin/node/inspect/src/lib.rs +++ b/bin/node/inspect/src/lib.rs @@ -78,26 +78,19 @@ impl PrettyPrinter for DebugPrinter { } /// Aggregated error for `Inspector` operations. -#[derive(Debug, derive_more::From, derive_more::Display)] +#[derive(Debug, thiserror::Error)] pub enum Error { /// Could not decode Block or Extrinsic. - Codec(codec::Error), + #[error(transparent)] + Codec(#[from] codec::Error), /// Error accessing blockchain DB. - Blockchain(sp_blockchain::Error), + #[error(transparent)] + Blockchain(#[from] sp_blockchain::Error), /// Given block has not been found. + #[error("{0}")] NotFound(String), } -impl std::error::Error for Error { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match *self { - Self::Codec(ref e) => Some(e), - Self::Blockchain(ref e) => Some(e), - Self::NotFound(_) => None, - } - } -} - /// A helper trait to access block headers and bodies. pub trait ChainAccess: HeaderBackend + BlockBackend {} diff --git a/client/authority-discovery/Cargo.toml b/client/authority-discovery/Cargo.toml index c6c523fa5eec..ec43112a7145 100644 --- a/client/authority-discovery/Cargo.toml +++ b/client/authority-discovery/Cargo.toml @@ -19,7 +19,7 @@ prost-build = "0.9" [dependencies] async-trait = "0.1" codec = { package = "parity-scale-codec", default-features = false, version = "2.0.0" } -derive_more = "0.99.16" +thiserror = "1.0" futures = "0.3.9" futures-timer = "3.0.1" ip_network = "0.4.1" diff --git a/client/authority-discovery/src/error.rs b/client/authority-discovery/src/error.rs index 26ee02ef8532..bad53e905cb9 100644 --- a/client/authority-discovery/src/error.rs +++ b/client/authority-discovery/src/error.rs @@ -24,40 +24,56 @@ use sp_core::crypto::CryptoTypePublicPair; pub type Result = std::result::Result; /// Error type for the authority discovery module. -#[derive(Debug, derive_more::Display, derive_more::From)] +#[derive(Debug, thiserror::Error)] pub enum Error { - /// Received dht value found event with records with different keys. + #[error("Received dht value found event with records with different keys.")] ReceivingDhtValueFoundEventWithDifferentKeys, - /// Received dht value found event with no records. + + #[error("Received dht value found event with no records.")] ReceivingDhtValueFoundEventWithNoRecords, - /// Failed to verify a dht payload with the given signature. + + #[error("Failed to verify a dht payload with the given signature.")] VerifyingDhtPayload, - /// Failed to hash the authority id to be used as a dht key. - HashingAuthorityId(libp2p::core::multiaddr::multihash::Error), - /// Failed calling into the Substrate runtime. - CallingRuntime(sp_blockchain::Error), - /// Received a dht record with a key that does not match any in-flight awaited keys. + + #[error("Failed to hash the authority id to be used as a dht key.")] + HashingAuthorityId(#[from] libp2p::core::multiaddr::multihash::Error), + + #[error("Failed calling into the Substrate runtime.")] + CallingRuntime(#[from] sp_blockchain::Error), + + #[error("Received a dht record with a key that does not match any in-flight awaited keys.")] ReceivingUnexpectedRecord, - /// Failed to encode a protobuf payload. - EncodingProto(prost::EncodeError), - /// Failed to decode a protobuf payload. - DecodingProto(prost::DecodeError), - /// Failed to encode or decode scale payload. - EncodingDecodingScale(codec::Error), - /// Failed to parse a libp2p multi address. - ParsingMultiaddress(libp2p::core::multiaddr::Error), - /// Failed to parse a libp2p key. - ParsingLibp2pIdentity(sc_network::DecodingError), - /// Failed to sign using a specific public key. + + #[error("Failed to encode a protobuf payload.")] + EncodingProto(#[from] prost::EncodeError), + + #[error("Failed to decode a protobuf payload.")] + DecodingProto(#[from] prost::DecodeError), + + #[error("Failed to encode or decode scale payload.")] + EncodingDecodingScale(#[from] codec::Error), + + #[error("Failed to parse a libp2p multi address.")] + ParsingMultiaddress(#[from] libp2p::core::multiaddr::Error), + + #[error("Failed to parse a libp2p key.")] + ParsingLibp2pIdentity(#[from] sc_network::DecodingError), + + #[error("Failed to sign using a specific public key.")] MissingSignature(CryptoTypePublicPair), - /// Failed to sign using all public keys. + + #[error("Failed to sign using all public keys.")] Signing, - /// Failed to register Prometheus metric. - Prometheus(prometheus_endpoint::PrometheusError), - /// Received authority record that contains addresses with multiple peer ids + + #[error("Failed to register Prometheus metric.")] + Prometheus(#[from] prometheus_endpoint::PrometheusError), + + #[error("Received authority record that contains addresses with multiple peer ids")] ReceivingDhtValueFoundEventWithDifferentPeerIds, - /// Received authority record without any addresses having a peer id + + #[error("Received authority record without any addresses having a peer id")] ReceivingDhtValueFoundEventWithNoPeerIds, - /// Received authority record without a valid signature for the remote peer id. + + #[error("Received authority record without a valid signature for the remote peer id.")] MissingPeerIdSignature, } diff --git a/client/beefy/rpc/Cargo.toml b/client/beefy/rpc/Cargo.toml index a72af62fdeea..444f1ff4aaf9 100644 --- a/client/beefy/rpc/Cargo.toml +++ b/client/beefy/rpc/Cargo.toml @@ -8,7 +8,6 @@ repository = "https://github.com/paritytech/substrate" description = "RPC for the BEEFY Client gadget for substrate" [dependencies] -derive_more = "0.99" futures = "0.3.16" log = "0.4" parking_lot = "0.11" diff --git a/client/beefy/rpc/src/lib.rs b/client/beefy/rpc/src/lib.rs index dc9ee8b94701..4c1bc03e222e 100644 --- a/client/beefy/rpc/src/lib.rs +++ b/client/beefy/rpc/src/lib.rs @@ -36,15 +36,15 @@ mod notification; type FutureResult = jsonrpc_core::BoxFuture>; -#[derive(Debug, derive_more::Display, derive_more::From, thiserror::Error)] +#[derive(Debug, thiserror::Error)] /// Top-level error type for the RPC handler pub enum Error { /// The BEEFY RPC endpoint is not ready. - #[display(fmt = "BEEFY RPC endpoint not ready")] + #[error("BEEFY RPC endpoint not ready")] EndpointNotReady, /// The BEEFY RPC background task failed to spawn. - #[display(fmt = "BEEFY RPC background task failed to spawn")] - RpcTaskFailure(SpawnError), + #[error("BEEFY RPC background task failed to spawn")] + RpcTaskFailure(#[from] SpawnError), } /// The error codes returned by jsonrpc. diff --git a/client/consensus/aura/Cargo.toml b/client/consensus/aura/Cargo.toml index 97409c5944db..bcae7648ce2e 100644 --- a/client/consensus/aura/Cargo.toml +++ b/client/consensus/aura/Cargo.toml @@ -22,7 +22,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0" } sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" } sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/common" } sp-consensus-slots = { version = "0.10.0-dev", path = "../../../primitives/consensus/slots" } -derive_more = "0.99.16" +thiserror = "1.0" futures = "0.3.9" sp-inherents = { version = "4.0.0-dev", path = "../../../primitives/inherents" } log = "0.4.8" diff --git a/client/consensus/aura/src/lib.rs b/client/consensus/aura/src/lib.rs index d7fe61313938..61c561088314 100644 --- a/client/consensus/aura/src/lib.rs +++ b/client/consensus/aura/src/lib.rs @@ -491,33 +491,34 @@ fn aura_err(error: Error) -> Error { } /// Aura Errors -#[derive(derive_more::Display, Debug)] +#[derive(Debug, thiserror::Error)] pub enum Error { /// Multiple Aura pre-runtime headers - #[display(fmt = "Multiple Aura pre-runtime headers")] + #[error("Multiple Aura pre-runtime headers")] MultipleHeaders, /// No Aura pre-runtime digest found - #[display(fmt = "No Aura pre-runtime digest found")] + #[error("No Aura pre-runtime digest found")] NoDigestFound, /// Header is unsealed - #[display(fmt = "Header {:?} is unsealed", _0)] + #[error("Header {0:?} is unsealed")] HeaderUnsealed(B::Hash), /// Header has a bad seal - #[display(fmt = "Header {:?} has a bad seal", _0)] + #[error("Header {0:?} has a bad seal")] HeaderBadSeal(B::Hash), /// Slot Author not found - #[display(fmt = "Slot Author not found")] + #[error("Slot Author not found")] SlotAuthorNotFound, /// Bad signature - #[display(fmt = "Bad signature on {:?}", _0)] + #[error("Bad signature on {0:?}")] BadSignature(B::Hash), /// Client Error + #[error(transparent)] Client(sp_blockchain::Error), /// Unknown inherent error for identifier - #[display(fmt = "Unknown inherent error for identifier: {}", "String::from_utf8_lossy(_0)")] + #[error("Unknown inherent error for identifier: {}", String::from_utf8_lossy(.0))] UnknownInherentError(sp_inherents::InherentIdentifier), - #[display(fmt = "Inherent error: {}", _0)] /// Inherents Error + #[error("Inherent error: {0}")] Inherent(sp_inherents::Error), } diff --git a/client/consensus/babe/Cargo.toml b/client/consensus/babe/Cargo.toml index e4d66fcad87c..5dd029f0ad4a 100644 --- a/client/consensus/babe/Cargo.toml +++ b/client/consensus/babe/Cargo.toml @@ -49,7 +49,7 @@ log = "0.4.8" schnorrkel = { version = "0.9.1", features = ["preaudit_deprecated"] } rand = "0.7.2" merlin = "2.0" -derive_more = "0.99.16" +thiserror = "1.0" retain_mut = "0.1.4" async-trait = "0.1.50" diff --git a/client/consensus/babe/rpc/Cargo.toml b/client/consensus/babe/rpc/Cargo.toml index 93be56b9d360..4997cfdd1eec 100644 --- a/client/consensus/babe/rpc/Cargo.toml +++ b/client/consensus/babe/rpc/Cargo.toml @@ -19,12 +19,12 @@ jsonrpc-core = "18.0.0" jsonrpc-core-client = "18.0.0" jsonrpc-derive = "18.0.0" sp-consensus-babe = { version = "0.10.0-dev", path = "../../../../primitives/consensus/babe" } -serde = { version = "1.0.132", features=["derive"] } +serde = { version = "1.0.132", features = ["derive"] } sp-blockchain = { version = "4.0.0-dev", path = "../../../../primitives/blockchain" } sp-runtime = { version = "4.1.0-dev", path = "../../../../primitives/runtime" } sc-consensus-epochs = { version = "0.10.0-dev", path = "../../epochs" } futures = "0.3.16" -derive_more = "0.99.16" +thiserror = "1.0" sp-api = { version = "4.0.0-dev", path = "../../../../primitives/api" } sp-consensus = { version = "0.10.0-dev", path = "../../../../primitives/consensus/common" } sp-core = { version = "4.1.0-dev", path = "../../../../primitives/core" } diff --git a/client/consensus/babe/rpc/src/lib.rs b/client/consensus/babe/rpc/src/lib.rs index c9d2f9b76c2a..462620f26e5b 100644 --- a/client/consensus/babe/rpc/src/lib.rs +++ b/client/consensus/babe/rpc/src/lib.rs @@ -166,11 +166,13 @@ pub struct EpochAuthorship { } /// Errors encountered by the RPC -#[derive(Debug, derive_more::Display, derive_more::From)] +#[derive(Debug, thiserror::Error)] pub enum Error { /// Consensus error - Consensus(ConsensusError), + #[error(transparent)] + Consensus(#[from] ConsensusError), /// Errors that can be formatted as a String + #[error("{0}")] StringError(String), } diff --git a/client/consensus/babe/src/lib.rs b/client/consensus/babe/src/lib.rs index a86eac35a100..3e9cf5aab649 100644 --- a/client/consensus/babe/src/lib.rs +++ b/client/consensus/babe/src/lib.rs @@ -217,95 +217,94 @@ impl Epoch { } /// Errors encountered by the babe authorship task. -#[derive(derive_more::Display, Debug)] +#[derive(Debug, thiserror::Error)] pub enum Error { /// Multiple BABE pre-runtime digests - #[display(fmt = "Multiple BABE pre-runtime digests, rejecting!")] + #[error("Multiple BABE pre-runtime digests, rejecting!")] MultiplePreRuntimeDigests, /// No BABE pre-runtime digest found - #[display(fmt = "No BABE pre-runtime digest found")] + #[error("No BABE pre-runtime digest found")] NoPreRuntimeDigest, /// Multiple BABE epoch change digests - #[display(fmt = "Multiple BABE epoch change digests, rejecting!")] + #[error("Multiple BABE epoch change digests, rejecting!")] MultipleEpochChangeDigests, /// Multiple BABE config change digests - #[display(fmt = "Multiple BABE config change digests, rejecting!")] + #[error("Multiple BABE config change digests, rejecting!")] MultipleConfigChangeDigests, /// Could not extract timestamp and slot - #[display(fmt = "Could not extract timestamp and slot: {:?}", _0)] + #[error("Could not extract timestamp and slot: {0:?}")] Extraction(sp_consensus::Error), /// Could not fetch epoch - #[display(fmt = "Could not fetch epoch at {:?}", _0)] + #[error("Could not fetch epoch at {0:?}")] FetchEpoch(B::Hash), /// Header rejected: too far in the future - #[display(fmt = "Header {:?} rejected: too far in the future", _0)] + #[error("Header {0:?} rejected: too far in the future")] TooFarInFuture(B::Hash), /// Parent unavailable. Cannot import - #[display(fmt = "Parent ({}) of {} unavailable. Cannot import", _0, _1)] + #[error("Parent ({0}) of {1} unavailable. Cannot import")] ParentUnavailable(B::Hash, B::Hash), /// Slot number must increase - #[display(fmt = "Slot number must increase: parent slot: {}, this slot: {}", _0, _1)] + #[error("Slot number must increase: parent slot: {0}, this slot: {1}")] SlotMustIncrease(Slot, Slot), /// Header has a bad seal - #[display(fmt = "Header {:?} has a bad seal", _0)] + #[error("Header {0:?} has a bad seal")] HeaderBadSeal(B::Hash), /// Header is unsealed - #[display(fmt = "Header {:?} is unsealed", _0)] + #[error("Header {0:?} is unsealed")] HeaderUnsealed(B::Hash), /// Slot author not found - #[display(fmt = "Slot author not found")] + #[error("Slot author not found")] SlotAuthorNotFound, /// Secondary slot assignments are disabled for the current epoch. - #[display(fmt = "Secondary slot assignments are disabled for the current epoch.")] + #[error("Secondary slot assignments are disabled for the current epoch.")] SecondarySlotAssignmentsDisabled, /// Bad signature - #[display(fmt = "Bad signature on {:?}", _0)] + #[error("Bad signature on {0:?}")] BadSignature(B::Hash), /// Invalid author: Expected secondary author - #[display(fmt = "Invalid author: Expected secondary author: {:?}, got: {:?}.", _0, _1)] + #[error("Invalid author: Expected secondary author: {0:?}, got: {1:?}.")] InvalidAuthor(AuthorityId, AuthorityId), /// No secondary author expected. - #[display(fmt = "No secondary author expected.")] + #[error("No secondary author expected.")] NoSecondaryAuthorExpected, /// VRF verification of block by author failed - #[display( - fmt = "VRF verification of block by author {:?} failed: threshold {} exceeded", - _0, - _1 - )] + #[error("VRF verification of block by author {0:?} failed: threshold {1} exceeded")] VRFVerificationOfBlockFailed(AuthorityId, u128), /// VRF verification failed - #[display(fmt = "VRF verification failed: {:?}", _0)] + #[error("VRF verification failed: {0:?}")] VRFVerificationFailed(SignatureError), /// Could not fetch parent header - #[display(fmt = "Could not fetch parent header: {:?}", _0)] + #[error("Could not fetch parent header: {0:?}")] FetchParentHeader(sp_blockchain::Error), /// Expected epoch change to happen. - #[display(fmt = "Expected epoch change to happen at {:?}, s{}", _0, _1)] + #[error("Expected epoch change to happen at {0:?}, s{1}")] ExpectedEpochChange(B::Hash, Slot), /// Unexpected config change. - #[display(fmt = "Unexpected config change")] + #[error("Unexpected config change")] UnexpectedConfigChange, /// Unexpected epoch change - #[display(fmt = "Unexpected epoch change")] + #[error("Unexpected epoch change")] UnexpectedEpochChange, /// Parent block has no associated weight - #[display(fmt = "Parent block of {} has no associated weight", _0)] + #[error("Parent block of {0} has no associated weight")] ParentBlockNoAssociatedWeight(B::Hash), /// Check inherents error - #[display(fmt = "Checking inherents failed: {}", _0)] + #[error("Checking inherents failed: {0}")] CheckInherents(sp_inherents::Error), /// Unhandled check inherents error - #[display(fmt = "Checking inherents unhandled error: {}", "String::from_utf8_lossy(_0)")] + #[error("Checking inherents unhandled error: {}", String::from_utf8_lossy(.0))] CheckInherentsUnhandled(sp_inherents::InherentIdentifier), /// Create inherents error. - #[display(fmt = "Creating inherents failed: {}", _0)] + #[error("Creating inherents failed: {0}")] CreateInherents(sp_inherents::Error), /// Client error + #[error(transparent)] Client(sp_blockchain::Error), /// Runtime Api error. + #[error(transparent)] RuntimeApi(sp_api::ApiError), /// Fork tree error + #[error(transparent)] ForkTree(Box>), } diff --git a/client/consensus/manual-seal/Cargo.toml b/client/consensus/manual-seal/Cargo.toml index 89f3335899f1..ff2264e64174 100644 --- a/client/consensus/manual-seal/Cargo.toml +++ b/client/consensus/manual-seal/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -derive_more = "0.99.16" +thiserror = "1.0" futures = "0.3.9" jsonrpc-core = "18.0.0" jsonrpc-core-client = "18.0.0" diff --git a/client/consensus/manual-seal/src/error.rs b/client/consensus/manual-seal/src/error.rs index 3a67b36bc62b..2f946f3de3cc 100644 --- a/client/consensus/manual-seal/src/error.rs +++ b/client/consensus/manual-seal/src/error.rs @@ -38,40 +38,52 @@ mod codes { } /// errors encountered by background block authorship task -#[derive(Debug, derive_more::Display, derive_more::From)] +#[derive(Debug, thiserror::Error)] pub enum Error { /// An error occurred while importing the block - #[display(fmt = "Block import failed: {:?}", _0)] + #[error("Block import failed: {0:?}")] BlockImportError(ImportResult), /// Transaction pool is empty, cannot create a block - #[display(fmt = "Transaction pool is empty, set create_empty to true,\ - if you want to create empty blocks")] + #[error( + "Transaction pool is empty, set create_empty to true, if you want to create empty blocks" + )] EmptyTransactionPool, /// encountered during creation of Proposer. - #[display(fmt = "Consensus Error: {}", _0)] - ConsensusError(ConsensusError), + #[error("Consensus Error: {0}")] + ConsensusError(#[from] ConsensusError), /// Failed to create Inherents data - #[display(fmt = "Inherents Error: {}", _0)] - InherentError(InherentsError), + #[error("Inherents Error: {0}")] + InherentError(#[from] InherentsError), /// error encountered during finalization - #[display(fmt = "Finalization Error: {}", _0)] - BlockchainError(BlockchainError), + #[error("Finalization Error: {0}")] + BlockchainError(#[from] BlockchainError), /// Supplied parent_hash doesn't exist in chain - #[display(fmt = "Supplied parent_hash: {} doesn't exist in chain", _0)] - #[from(ignore)] + #[error("Supplied parent_hash: {0} doesn't exist in chain")] BlockNotFound(String), /// Some string error - #[display(fmt = "{}", _0)] + #[error("{0}")] StringError(String), /// send error - #[display(fmt = "Consensus process is terminating")] - Canceled(oneshot::Canceled), + #[error("Consensus process is terminating")] + Canceled(#[from] oneshot::Canceled), /// send error - #[display(fmt = "Consensus process is terminating")] - SendError(SendError), + #[error("Consensus process is terminating")] + SendError(#[from] SendError), /// Some other error. - #[display(fmt = "Other error: {}", _0)] - Other(Box), + #[error("Other error: {0}")] + Other(#[from] Box), +} + +impl From for Error { + fn from(err: ImportResult) -> Self { + Error::BlockImportError(err) + } +} + +impl From for Error { + fn from(s: String) -> Self { + Error::StringError(s) + } } impl Error { diff --git a/client/consensus/pow/Cargo.toml b/client/consensus/pow/Cargo.toml index db9e4e164e4e..e5bf87487c71 100644 --- a/client/consensus/pow/Cargo.toml +++ b/client/consensus/pow/Cargo.toml @@ -28,6 +28,6 @@ log = "0.4.8" futures = "0.3.16" futures-timer = "3.0.1" parking_lot = "0.11.2" -derive_more = "0.99.16" +thiserror = "1.0" prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.10.0-dev"} async-trait = "0.1.50" diff --git a/client/consensus/pow/src/lib.rs b/client/consensus/pow/src/lib.rs index 0bcb9f3d00a5..ef81faff46a9 100644 --- a/client/consensus/pow/src/lib.rs +++ b/client/consensus/pow/src/lib.rs @@ -72,45 +72,50 @@ use std::{ time::Duration, }; -#[derive(derive_more::Display, Debug)] +#[derive(Debug, thiserror::Error)] pub enum Error { - #[display(fmt = "Header uses the wrong engine {:?}", _0)] + #[error("Header uses the wrong engine {0:?}")] WrongEngine([u8; 4]), - #[display(fmt = "Header {:?} is unsealed", _0)] + #[error("Header {0:?} is unsealed")] HeaderUnsealed(B::Hash), - #[display(fmt = "PoW validation error: invalid seal")] + #[error("PoW validation error: invalid seal")] InvalidSeal, - #[display(fmt = "PoW validation error: preliminary verification failed")] + #[error("PoW validation error: preliminary verification failed")] FailedPreliminaryVerify, - #[display(fmt = "Rejecting block too far in future")] + #[error("Rejecting block too far in future")] TooFarInFuture, - #[display(fmt = "Fetching best header failed using select chain: {:?}", _0)] + #[error("Fetching best header failed using select chain: {0:?}")] BestHeaderSelectChain(ConsensusError), - #[display(fmt = "Fetching best header failed: {:?}", _0)] + #[error("Fetching best header failed: {0:?}")] BestHeader(sp_blockchain::Error), - #[display(fmt = "Best header does not exist")] + #[error("Best header does not exist")] NoBestHeader, - #[display(fmt = "Block proposing error: {:?}", _0)] + #[error("Block proposing error: {0:?}")] BlockProposingError(String), - #[display(fmt = "Fetch best hash failed via select chain: {:?}", _0)] + #[error("Fetch best hash failed via select chain: {0:?}")] BestHashSelectChain(ConsensusError), - #[display(fmt = "Error with block built on {:?}: {:?}", _0, _1)] + #[error("Error with block built on {0:?}: {1:?}")] BlockBuiltError(B::Hash, ConsensusError), - #[display(fmt = "Creating inherents failed: {}", _0)] + #[error("Creating inherents failed: {0}")] CreateInherents(sp_inherents::Error), - #[display(fmt = "Checking inherents failed: {}", _0)] + #[error("Checking inherents failed: {0}")] CheckInherents(sp_inherents::Error), - #[display( - fmt = "Checking inherents unknown error for identifier: {:?}", - "String::from_utf8_lossy(_0)" + #[error( + "Checking inherents unknown error for identifier: {:?}", + String::from_utf8_lossy(.0) )] CheckInherentsUnknownError(sp_inherents::InherentIdentifier), - #[display(fmt = "Multiple pre-runtime digests")] + #[error("Multiple pre-runtime digests")] MultiplePreRuntimeDigests, + #[error(transparent)] Client(sp_blockchain::Error), + #[error(transparent)] Codec(codec::Error), + #[error("{0}")] Environment(String), + #[error("{0}")] Runtime(RuntimeString), + #[error("{0}")] Other(String), } diff --git a/client/executor/common/Cargo.toml b/client/executor/common/Cargo.toml index 8e4b11f8f8fa..104d24876d9a 100644 --- a/client/executor/common/Cargo.toml +++ b/client/executor/common/Cargo.toml @@ -14,7 +14,6 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -derive_more = "0.99.16" wasm-instrument = "0.1" codec = { package = "parity-scale-codec", version = "2.0.0" } wasmi = "0.9.1" diff --git a/client/executor/common/src/error.rs b/client/executor/common/src/error.rs index 90e658a89628..606f97317b9a 100644 --- a/client/executor/common/src/error.rs +++ b/client/executor/common/src/error.rs @@ -125,28 +125,38 @@ impl From for Error { } /// Type for errors occurring during Wasm runtime construction. -#[derive(Debug, derive_more::Display)] +#[derive(Debug, thiserror::Error)] +#[allow(missing_docs)] pub enum WasmError { - /// Code could not be read from the state. + #[error("Code could not be read from the state.")] CodeNotFound, - /// Failure to reinitialize runtime instance from snapshot. + + #[error("Failure to reinitialize runtime instance from snapshot.")] ApplySnapshotFailed, + /// Failure to erase the wasm memory. /// /// Depending on the implementation might mean failure of allocating memory. + #[error("Failure to erase the wasm memory: {0}")] ErasingFailed(String), - /// Wasm code failed validation. + + #[error("Wasm code failed validation.")] InvalidModule, - /// Wasm code could not be deserialized. + + #[error("Wasm code could not be deserialized.")] CantDeserializeWasm, - /// The module does not export a linear memory named `memory`. + + #[error("The module does not export a linear memory named `memory`.")] InvalidMemory, - /// The number of heap pages requested is disallowed by the module. + + #[error("The number of heap pages requested is disallowed by the module.")] InvalidHeapPages, + /// Instantiation error. + #[error("{0}")] Instantiation(String), + /// Other error happenend. + #[error("{0}")] Other(String), } - -impl std::error::Error for WasmError {} diff --git a/client/finality-grandpa/Cargo.toml b/client/finality-grandpa/Cargo.toml index 3f9261c0c17a..2e6d3407a191 100644 --- a/client/finality-grandpa/Cargo.toml +++ b/client/finality-grandpa/Cargo.toml @@ -13,9 +13,8 @@ readme = "README.md" [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] - [dependencies] -derive_more = "0.99.16" +thiserror = "1.0" dyn-clone = "1.0" fork-tree = { version = "3.0.0", path = "../../utils/fork-tree" } futures = "0.3.9" diff --git a/client/finality-grandpa/rpc/Cargo.toml b/client/finality-grandpa/rpc/Cargo.toml index be6dfc371e4a..39bf398fe312 100644 --- a/client/finality-grandpa/rpc/Cargo.toml +++ b/client/finality-grandpa/rpc/Cargo.toml @@ -23,7 +23,7 @@ futures = "0.3.16" serde = { version = "1.0.105", features = ["derive"] } serde_json = "1.0.50" log = "0.4.8" -derive_more = "0.99.2" +thiserror = "1.0" parity-scale-codec = { version = "2.0.0", features = ["derive"] } sc-client-api = { version = "4.0.0-dev", path = "../../api" } diff --git a/client/finality-grandpa/rpc/src/error.rs b/client/finality-grandpa/rpc/src/error.rs index 1c1361bcaeda..845b4d99dcc1 100644 --- a/client/finality-grandpa/rpc/src/error.rs +++ b/client/finality-grandpa/rpc/src/error.rs @@ -16,21 +16,21 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -#[derive(derive_more::Display, derive_more::From)] +#[derive(Debug, thiserror::Error)] /// Top-level error type for the RPC handler pub enum Error { /// The GRANDPA RPC endpoint is not ready. - #[display(fmt = "GRANDPA RPC endpoint not ready")] + #[error("GRANDPA RPC endpoint not ready")] EndpointNotReady, /// GRANDPA reports the authority set id to be larger than 32-bits. - #[display(fmt = "GRANDPA reports authority set id unreasonably large")] + #[error("GRANDPA reports authority set id unreasonably large")] AuthoritySetIdReportedAsUnreasonablyLarge, /// GRANDPA reports voter state with round id or weights larger than 32-bits. - #[display(fmt = "GRANDPA reports voter state as unreasonably large")] + #[error("GRANDPA reports voter state as unreasonably large")] VoterStateReportsUnreasonablyLargeNumbers, /// GRANDPA prove finality failed. - #[display(fmt = "GRANDPA prove finality rpc failed: {}", _0)] - ProveFinalityFailed(sc_finality_grandpa::FinalityProofError), + #[error("GRANDPA prove finality rpc failed: {0}")] + ProveFinalityFailed(#[from] sc_finality_grandpa::FinalityProofError), } /// The error codes returned by jsonrpc. diff --git a/client/finality-grandpa/src/authorities.rs b/client/finality-grandpa/src/authorities.rs index aa8be83b9529..033a1c4bbb23 100644 --- a/client/finality-grandpa/src/authorities.rs +++ b/client/finality-grandpa/src/authorities.rs @@ -32,23 +32,22 @@ use sp_finality_grandpa::{AuthorityId, AuthorityList}; use crate::SetId; /// Error type returned on operations on the `AuthoritySet`. -#[derive(Debug, derive_more::Display)] +#[derive(Debug, thiserror::Error)] pub enum Error { - #[display(fmt = "Invalid authority set, either empty or with an authority weight set to 0.")] + #[error("Invalid authority set, either empty or with an authority weight set to 0.")] InvalidAuthoritySet, - #[display(fmt = "Client error during ancestry lookup: {}", _0)] + #[error("Client error during ancestry lookup: {0}")] Client(E), - #[display(fmt = "Duplicate authority set change.")] + #[error("Duplicate authority set change.")] DuplicateAuthoritySetChange, - #[display(fmt = "Multiple pending forced authority set changes are not allowed.")] + #[error("Multiple pending forced authority set changes are not allowed.")] MultiplePendingForcedAuthoritySetChanges, - #[display( - fmt = "A pending forced authority set change could not be applied since it must be applied \ - after the pending standard change at #{}", - _0 + #[error( + "A pending forced authority set change could not be applied since it must be applied \ + after the pending standard change at #{0}" )] ForcedAuthoritySetChangeDependencyUnsatisfied(N), - #[display(fmt = "Invalid operation in the pending changes tree: {}", _0)] + #[error("Invalid operation in the pending changes tree: {0}")] ForkTree(fork_tree::Error), } diff --git a/client/finality-grandpa/src/finality_proof.rs b/client/finality-grandpa/src/finality_proof.rs index cc6853bee3b0..03a4f2ff450a 100644 --- a/client/finality-grandpa/src/finality_proof.rs +++ b/client/finality-grandpa/src/finality_proof.rs @@ -132,17 +132,18 @@ pub struct FinalityProof { } /// Errors occurring when trying to prove finality -#[derive(Debug, derive_more::Display, derive_more::From)] +#[derive(Debug, thiserror::Error)] pub enum FinalityProofError { /// The requested block has not yet been finalized. - #[display(fmt = "Block not yet finalized")] + #[error("Block not yet finalized")] BlockNotYetFinalized, /// The requested block is not covered by authority set changes. Likely this means the block is /// in the latest authority set, and the subscription API is more appropriate. - #[display(fmt = "Block not covered by authority set changes")] + #[error("Block not covered by authority set changes")] BlockNotInAuthoritySetChanges, /// Errors originating from the client. - Client(sp_blockchain::Error), + #[error(transparent)] + Client(#[from] sp_blockchain::Error), } fn prove_finality( diff --git a/client/finality-grandpa/src/warp_proof.rs b/client/finality-grandpa/src/warp_proof.rs index 39d570d22bd7..bdb8e36373de 100644 --- a/client/finality-grandpa/src/warp_proof.rs +++ b/client/finality-grandpa/src/warp_proof.rs @@ -34,26 +34,25 @@ use sp_runtime::{ use std::{collections::HashMap, sync::Arc}; /// Warp proof processing error. -#[derive(Debug, derive_more::Display, derive_more::From)] +#[derive(Debug, thiserror::Error)] pub enum Error { /// Decoding error. - #[display(fmt = "Failed to decode block hash: {}.", _0)] - DecodeScale(codec::Error), + #[error("Failed to decode block hash: {0}.")] + DecodeScale(#[from] codec::Error), /// Client backend error. - Client(sp_blockchain::Error), + #[error("{0}")] + Client(#[from] sp_blockchain::Error), /// Invalid request data. - #[from(ignore)] + #[error("{0}")] InvalidRequest(String), /// Invalid warp proof. - #[from(ignore)] + #[error("{0}")] InvalidProof(String), /// Missing header or authority set change data. - #[display(fmt = "Missing required data to be able to answer request.")] + #[error("Missing required data to be able to answer request.")] MissingData, } -impl std::error::Error for Error {} - /// The maximum size in bytes of the `WarpSyncProof`. pub(super) const MAX_WARP_SYNC_PROOF_SIZE: usize = 8 * 1024 * 1024; diff --git a/client/keystore/Cargo.toml b/client/keystore/Cargo.toml index 7fe9e182efbd..56d4ee0d556f 100644 --- a/client/keystore/Cargo.toml +++ b/client/keystore/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] async-trait = "0.1.50" -derive_more = "0.99.16" +thiserror = "1.0" sp-application-crypto = { version = "4.0.0", path = "../../primitives/application-crypto" } sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-keystore = { version = "0.10.0", path = "../../primitives/keystore" } diff --git a/client/keystore/src/lib.rs b/client/keystore/src/lib.rs index 359326bb4cae..cf94a16f08d8 100644 --- a/client/keystore/src/lib.rs +++ b/client/keystore/src/lib.rs @@ -28,29 +28,31 @@ mod local; pub use local::LocalKeystore; /// Keystore error. -#[derive(Debug, derive_more::Display, derive_more::From)] +#[derive(Debug, thiserror::Error)] pub enum Error { /// IO error. - Io(io::Error), + #[error(transparent)] + Io(#[from] io::Error), /// JSON error. - Json(serde_json::Error), + #[error(transparent)] + Json(#[from] serde_json::Error), /// Invalid password. - #[display( - fmt = "Requested public key and public key of the loaded private key do not match. \n + #[error( + "Requested public key and public key of the loaded private key do not match. \n This means either that the keystore password is incorrect or that the private key was stored under a wrong public key." )] PublicKeyMismatch, /// Invalid BIP39 phrase - #[display(fmt = "Invalid recovery phrase (BIP39) data")] + #[error("Invalid recovery phrase (BIP39) data")] InvalidPhrase, /// Invalid seed - #[display(fmt = "Invalid seed")] + #[error("Invalid seed")] InvalidSeed, /// Public key type is not supported - #[display(fmt = "Key crypto type is not supported")] + #[error("Key crypto type is not supported")] KeyNotSupported(KeyTypeId), /// Keystore unavailable - #[display(fmt = "Keystore unavailable")] + #[error("Keystore unavailable")] Unavailable, } @@ -69,13 +71,3 @@ impl From for TraitError { } } } - -impl std::error::Error for Error { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self { - Error::Io(ref err) => Some(err), - Error::Json(ref err) => Some(err), - _ => None, - } - } -} diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index f378b75990cb..354991b32ba5 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -25,7 +25,6 @@ bytes = "1" codec = { package = "parity-scale-codec", version = "2.0.0", features = [ "derive", ] } -derive_more = "0.99.16" either = "1.5.3" fnv = "1.0.6" fork-tree = { version = "3.0.0", path = "../../utils/fork-tree" } @@ -57,7 +56,7 @@ sp-core = { version = "4.1.0-dev", path = "../../primitives/core" } sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" } sc-utils = { version = "4.0.0-dev", path = "../utils" } sp-finality-grandpa = { version = "4.0.0-dev", path = "../../primitives/finality-grandpa" } -thiserror = "1" +thiserror = "1.0" unsigned-varint = { version = "0.6.0", features = [ "futures", "asynchronous_codec", diff --git a/client/network/src/bitswap.rs b/client/network/src/bitswap.rs index e6cb1d9d79e3..e7c37968b5f9 100644 --- a/client/network/src/bitswap.rs +++ b/client/network/src/bitswap.rs @@ -313,21 +313,29 @@ impl NetworkBehaviour for Bitswap { } /// Bitswap protocol error. -#[derive(derive_more::Display, derive_more::From)] +#[derive(Debug, thiserror::Error)] pub enum BitswapError { /// Protobuf decoding error. - #[display(fmt = "Failed to decode request: {}.", _0)] - DecodeProto(prost::DecodeError), + #[error("Failed to decode request: {0}.")] + DecodeProto(#[from] prost::DecodeError), + /// Protobuf encoding error. - #[display(fmt = "Failed to encode response: {}.", _0)] - EncodeProto(prost::EncodeError), + #[error("Failed to encode response: {0}.")] + EncodeProto(#[from] prost::EncodeError), + /// Client backend error. - Client(sp_blockchain::Error), + #[error(transparent)] + Client(#[from] sp_blockchain::Error), + /// Error parsing CID - BadCid(cid::Error), + #[error(transparent)] + BadCid(#[from] cid::Error), + /// Packet read error. - Read(io::Error), + #[error(transparent)] + Read(#[from] io::Error), + /// Error sending response. - #[display(fmt = "Failed to send response.")] + #[error("Failed to send response.")] SendResponse, } diff --git a/client/network/src/block_request_handler.rs b/client/network/src/block_request_handler.rs index 9d963480a7e0..2f17cdac0744 100644 --- a/client/network/src/block_request_handler.rs +++ b/client/network/src/block_request_handler.rs @@ -379,19 +379,20 @@ impl BlockRequestHandler { } } -#[derive(derive_more::Display, derive_more::From)] +#[derive(Debug, thiserror::Error)] enum HandleRequestError { - #[display(fmt = "Failed to decode request: {}.", _0)] - DecodeProto(prost::DecodeError), - #[display(fmt = "Failed to encode response: {}.", _0)] - EncodeProto(prost::EncodeError), - #[display(fmt = "Failed to decode block hash: {}.", _0)] - DecodeScale(codec::Error), - #[display(fmt = "Missing `BlockRequest::from_block` field.")] + #[error("Failed to decode request: {0}.")] + DecodeProto(#[from] prost::DecodeError), + #[error("Failed to encode response: {0}.")] + EncodeProto(#[from] prost::EncodeError), + #[error("Failed to decode block hash: {0}.")] + DecodeScale(#[from] codec::Error), + #[error("Missing `BlockRequest::from_block` field.")] MissingFromField, - #[display(fmt = "Failed to parse BlockRequest::direction.")] + #[error("Failed to parse BlockRequest::direction.")] ParseDirection, - Client(sp_blockchain::Error), - #[display(fmt = "Failed to send response.")] + #[error(transparent)] + Client(#[from] sp_blockchain::Error), + #[error("Failed to send response.")] SendResponse, } diff --git a/client/network/src/error.rs b/client/network/src/error.rs index 1dafddd7bcc5..716235193a80 100644 --- a/client/network/src/error.rs +++ b/client/network/src/error.rs @@ -27,18 +27,18 @@ use std::{borrow::Cow, fmt}; pub type Result = std::result::Result; /// Error type for the network. -#[derive(derive_more::Display, derive_more::From)] +#[derive(thiserror::Error)] pub enum Error { /// Io error - Io(std::io::Error), + #[error(transparent)] + Io(#[from] std::io::Error), + /// Client error - Client(Box), + #[error(transparent)] + Client(#[from] Box), /// The same bootnode (based on address) is registered with two different peer ids. - #[display( - fmt = "The same bootnode (`{}`) is registered with two different peer ids: `{}` and `{}`", - address, - first_id, - second_id + #[error( + "The same bootnode (`{address}`) is registered with two different peer ids: `{first_id}` and `{second_id}`" )] DuplicateBootnode { /// The address of the bootnode. @@ -49,11 +49,11 @@ pub enum Error { second_id: PeerId, }, /// Prometheus metrics error. - Prometheus(prometheus_endpoint::PrometheusError), + #[error(transparent)] + Prometheus(#[from] prometheus_endpoint::PrometheusError), /// The network addresses are invalid because they don't match the transport. - #[display( - fmt = "The following addresses are invalid because they don't match the transport: {:?}", - addresses + #[error( + "The following addresses are invalid because they don't match the transport: {addresses:?}" )] AddressesForAnotherTransport { /// Transport used. @@ -62,7 +62,7 @@ pub enum Error { addresses: Vec, }, /// The same request-response protocol has been registered multiple times. - #[display(fmt = "Request-response protocol registered multiple times: {}", protocol)] + #[error("Request-response protocol registered multiple times: {protocol}")] DuplicateRequestResponseProtocol { /// Name of the protocol registered multiple times. protocol: Cow<'static, str>, @@ -75,16 +75,3 @@ impl fmt::Debug for Error { fmt::Display::fmt(self, f) } } - -impl std::error::Error for Error { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self { - Self::Io(ref err) => Some(err), - Self::Client(ref err) => Some(err), - Self::Prometheus(ref err) => Some(err), - Self::DuplicateBootnode { .. } | - Self::AddressesForAnotherTransport { .. } | - Self::DuplicateRequestResponseProtocol { .. } => None, - } - } -} diff --git a/client/network/src/light_client_requests/handler.rs b/client/network/src/light_client_requests/handler.rs index b5c6ccb196d5..fb258304f2e8 100644 --- a/client/network/src/light_client_requests/handler.rs +++ b/client/network/src/light_client_requests/handler.rs @@ -284,20 +284,20 @@ impl LightClientRequestHandler { } } -#[derive(derive_more::Display, derive_more::From)] +#[derive(Debug, thiserror::Error)] enum HandleRequestError { - #[display(fmt = "Failed to decode request: {}.", _0)] - DecodeProto(prost::DecodeError), - #[display(fmt = "Failed to encode response: {}.", _0)] - EncodeProto(prost::EncodeError), - #[display(fmt = "Failed to send response.")] + #[error("Failed to decode request: {0}.")] + DecodeProto(#[from] prost::DecodeError), + #[error("Failed to encode response: {0}.")] + EncodeProto(#[from] prost::EncodeError), + #[error("Failed to send response.")] SendResponse, /// A bad request has been received. - #[display(fmt = "bad request: {}", _0)] + #[error("bad request: {0}")] BadRequest(&'static str), /// Encoding or decoding of some data failed. - #[display(fmt = "codec error: {}", _0)] - Codec(codec::Error), + #[error("codec error: {0}")] + Codec(#[from] codec::Error), } fn fmt_keys(first: Option<&Vec>, last: Option<&Vec>) -> String { diff --git a/client/network/src/protocol/notifications/handler.rs b/client/network/src/protocol/notifications/handler.rs index 158ab2ae379c..91225f54203a 100644 --- a/client/network/src/protocol/notifications/handler.rs +++ b/client/network/src/protocol/notifications/handler.rs @@ -457,9 +457,9 @@ impl<'a> Ready<'a> { } /// Error specific to the collection of protocols. -#[derive(Debug, derive_more::Display, derive_more::Error)] +#[derive(Debug, thiserror::Error)] pub enum NotifsHandlerError { - /// Channel of synchronous notifications is full. + #[error("Channel of synchronous notifications is full.")] SyncNotificationsClogged, } diff --git a/client/network/src/protocol/notifications/upgrade/notifications.rs b/client/network/src/protocol/notifications/upgrade/notifications.rs index 5171d459fa40..53270975a5b0 100644 --- a/client/network/src/protocol/notifications/upgrade/notifications.rs +++ b/client/network/src/protocol/notifications/upgrade/notifications.rs @@ -457,13 +457,14 @@ where } /// Error generated by sending on a notifications out substream. -#[derive(Debug, derive_more::From, derive_more::Display)] +#[derive(Debug, thiserror::Error)] pub enum NotificationsHandshakeError { /// I/O error on the substream. - Io(io::Error), + #[error(transparent)] + Io(#[from] io::Error), /// Initial message or handshake was too large. - #[display(fmt = "Initial message or handshake was too large: {}", requested)] + #[error("Initial message or handshake was too large: {requested}")] TooLarge { /// Size requested by the remote. requested: usize, @@ -472,7 +473,8 @@ pub enum NotificationsHandshakeError { }, /// Error while decoding the variable-length integer. - VarintDecode(unsigned_varint::decode::Error), + #[error(transparent)] + VarintDecode(#[from] unsigned_varint::decode::Error), } impl From for NotificationsHandshakeError { @@ -489,10 +491,11 @@ impl From for NotificationsHandshakeError { } /// Error generated by sending on a notifications out substream. -#[derive(Debug, derive_more::From, derive_more::Display)] +#[derive(Debug, thiserror::Error)] pub enum NotificationsOutError { /// I/O error on the substream. - Io(io::Error), + #[error(transparent)] + Io(#[from] io::Error), } #[cfg(test)] diff --git a/client/network/src/request_responses.rs b/client/network/src/request_responses.rs index 24b3d3df00b2..58007c7bc5ce 100644 --- a/client/network/src/request_responses.rs +++ b/client/network/src/request_responses.rs @@ -884,34 +884,35 @@ impl NetworkBehaviour for RequestResponsesBehaviour { } /// Error when registering a protocol. -#[derive(Debug, derive_more::Display, derive_more::Error)] +#[derive(Debug, thiserror::Error)] pub enum RegisterError { /// A protocol has been specified multiple times. - DuplicateProtocol(#[error(ignore)] Cow<'static, str>), + #[error("{0}")] + DuplicateProtocol(Cow<'static, str>), } /// Error in a request. -#[derive(Debug, derive_more::Display, derive_more::Error)] +#[derive(Debug, thiserror::Error)] +#[allow(missing_docs)] pub enum RequestFailure { - /// We are not currently connected to the requested peer. + #[error("We are not currently connected to the requested peer.")] NotConnected, - /// Given protocol hasn't been registered. + #[error("Given protocol hasn't been registered.")] UnknownProtocol, - /// Remote has closed the substream before answering, thereby signaling that it considers the - /// request as valid, but refused to answer it. + #[error("Remote has closed the substream before answering, thereby signaling that it considers the request as valid, but refused to answer it.")] Refused, - /// The remote replied, but the local node is no longer interested in the response. + #[error("The remote replied, but the local node is no longer interested in the response.")] Obsolete, /// Problem on the network. - #[display(fmt = "Problem on the network: {}", _0)] + #[error("Problem on the network: {0}")] Network(OutboundFailure), } /// Error when processing a request sent by a remote. -#[derive(Debug, derive_more::Display, derive_more::Error)] +#[derive(Debug, thiserror::Error)] pub enum ResponseFailure { /// Problem on the network. - #[display(fmt = "Problem on the network: {}", _0)] + #[error("Problem on the network: {0}")] Network(InboundFailure), } diff --git a/client/network/src/service.rs b/client/network/src/service.rs index 9c8c58ef49e4..b6a1d3c88e7f 100644 --- a/client/network/src/service.rs +++ b/client/network/src/service.rs @@ -1391,7 +1391,7 @@ impl<'a> NotificationSenderReady<'a> { } /// Error returned by [`NetworkService::send_notification`]. -#[derive(Debug, derive_more::Display, derive_more::Error)] +#[derive(Debug, thiserror::Error)] pub enum NotificationSenderError { /// The notification receiver has been closed, usually because the underlying connection /// closed. @@ -1399,8 +1399,10 @@ pub enum NotificationSenderError { /// Some of the notifications most recently sent may not have been received. However, /// the peer may still be connected and a new `NotificationSender` for the same /// protocol obtained from [`NetworkService::notification_sender`]. + #[error("The notification receiver has been closed")] Closed, /// Protocol name hasn't been registered. + #[error("Protocol name hasn't been registered")] BadProtocol, } diff --git a/client/network/src/state_request_handler.rs b/client/network/src/state_request_handler.rs index 89f1f2b363c4..10a77061a031 100644 --- a/client/network/src/state_request_handler.rs +++ b/client/network/src/state_request_handler.rs @@ -241,15 +241,20 @@ impl StateRequestHandler { } } -#[derive(derive_more::Display, derive_more::From)] +#[derive(Debug, thiserror::Error)] enum HandleRequestError { - #[display(fmt = "Failed to decode request: {}.", _0)] - DecodeProto(prost::DecodeError), - #[display(fmt = "Failed to encode response: {}.", _0)] - EncodeProto(prost::EncodeError), - #[display(fmt = "Failed to decode block hash: {}.", _0)] - InvalidHash(codec::Error), - Client(sp_blockchain::Error), - #[display(fmt = "Failed to send response.")] + #[error("Failed to decode request: {0}.")] + DecodeProto(#[from] prost::DecodeError), + + #[error("Failed to encode response: {0}.")] + EncodeProto(#[from] prost::EncodeError), + + #[error("Failed to decode block hash: {0}.")] + InvalidHash(#[from] codec::Error), + + #[error(transparent)] + Client(#[from] sp_blockchain::Error), + + #[error("Failed to send response.")] SendResponse, } diff --git a/client/network/src/warp_request_handler.rs b/client/network/src/warp_request_handler.rs index ca5a93b752b6..4c839825ff5e 100644 --- a/client/network/src/warp_request_handler.rs +++ b/client/network/src/warp_request_handler.rs @@ -149,18 +149,23 @@ impl RequestHandler { } } -#[derive(Debug, derive_more::Display, derive_more::From)] +#[derive(Debug, thiserror::Error)] enum HandleRequestError { - #[display(fmt = "Failed to decode request: {}.", _0)] - DecodeProto(prost::DecodeError), - #[display(fmt = "Failed to encode response: {}.", _0)] - EncodeProto(prost::EncodeError), - #[display(fmt = "Failed to decode block hash: {}.", _0)] - DecodeScale(codec::Error), - Client(sp_blockchain::Error), - #[from(ignore)] - #[display(fmt = "Invalid request {}.", _0)] - InvalidRequest(Box), - #[display(fmt = "Failed to send response.")] + #[error("Failed to decode request: {0}.")] + DecodeProto(#[from] prost::DecodeError), + + #[error("Failed to encode response: {0}.")] + EncodeProto(#[from] prost::EncodeError), + + #[error("Failed to decode block hash: {0}.")] + DecodeScale(#[from] codec::Error), + + #[error(transparent)] + Client(#[from] sp_blockchain::Error), + + #[error("Invalid request {0}.")] + InvalidRequest(#[from] Box), + + #[error("Failed to send response.")] SendResponse, } diff --git a/client/transaction-pool/api/Cargo.toml b/client/transaction-pool/api/Cargo.toml index 95b82e26fc5d..a544248a4f2c 100644 --- a/client/transaction-pool/api/Cargo.toml +++ b/client/transaction-pool/api/Cargo.toml @@ -9,11 +9,10 @@ repository = "https://github.com/paritytech/substrate/" description = "Transaction pool client facing API." [dependencies] -futures = { version = "0.3.1" } -log = { version = "0.4.8" } +futures = "0.3.1" +log = "0.4.8" serde = { version = "1.0.132", features = ["derive"] } -thiserror = { version = "1.0.30" } -sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/runtime" } +thiserror = "1.0.30" -derive_more = { version = "0.99.16" } +sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/runtime" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } diff --git a/client/transaction-pool/api/src/error.rs b/client/transaction-pool/api/src/error.rs index f1ac2798e62d..b093657f739b 100644 --- a/client/transaction-pool/api/src/error.rs +++ b/client/transaction-pool/api/src/error.rs @@ -26,7 +26,7 @@ use sp_runtime::transaction_validity::{ pub type Result = std::result::Result; /// Transaction pool error type. -#[derive(Debug, thiserror::Error, derive_more::From)] +#[derive(Debug, thiserror::Error)] #[allow(missing_docs)] pub enum Error { #[error("Unknown transaction validity: {0:?}")] @@ -64,7 +64,6 @@ pub enum Error { #[error("Transaction cannot be propagated and the local node does not author blocks")] Unactionable, - #[from(ignore)] #[error("{0}")] InvalidBlockId(String), diff --git a/client/transaction-pool/src/lib.rs b/client/transaction-pool/src/lib.rs index 2d07815e4baa..b5af2d12d65c 100644 --- a/client/transaction-pool/src/lib.rs +++ b/client/transaction-pool/src/lib.rs @@ -47,8 +47,8 @@ use std::{ use graph::{ExtrinsicHash, IsValidator}; use sc_transaction_pool_api::{ - ChainEvent, ImportNotificationStream, MaintainedTransactionPool, PoolFuture, PoolStatus, - ReadyTransactions, TransactionFor, TransactionPool, TransactionSource, + error::Error as TxPoolError, ChainEvent, ImportNotificationStream, MaintainedTransactionPool, + PoolFuture, PoolStatus, ReadyTransactions, TransactionFor, TransactionPool, TransactionSource, TransactionStatusStreamFor, TxHash, }; use sp_core::traits::SpawnEssentialNamed; @@ -418,8 +418,8 @@ where .validate_transaction_blocking(at, TransactionSource::Local, xt.clone())? .map_err(|e| { Self::Error::Pool(match e { - TransactionValidityError::Invalid(i) => i.into(), - TransactionValidityError::Unknown(u) => u.into(), + TransactionValidityError::Invalid(i) => TxPoolError::InvalidTransaction(i), + TransactionValidityError::Unknown(u) => TxPoolError::UnknownTransaction(u), }) })?; diff --git a/primitives/keystore/Cargo.toml b/primitives/keystore/Cargo.toml index e918f5d2c6d7..28802cbec35e 100644 --- a/primitives/keystore/Cargo.toml +++ b/primitives/keystore/Cargo.toml @@ -14,13 +14,14 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] async-trait = "0.1.50" -derive_more = "0.99.16" +futures = "0.3.1" +parking_lot = { version = "0.11.2", default-features = false } +serde = { version = "1.0", optional = true } +thiserror = "1.0" + codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } -futures = { version = "0.3.1" } schnorrkel = { version = "0.9.1", features = ["preaudit_deprecated", "u64_backend"], default-features = false } merlin = { version = "2.0", default-features = false } -parking_lot = { version = "0.11.2", default-features = false } -serde = { version = "1.0", optional = true} sp-core = { version = "4.1.0-dev", path = "../core" } sp-externalities = { version = "0.10.0", path = "../externalities", default-features = false } @@ -28,7 +29,6 @@ sp-externalities = { version = "0.10.0", path = "../externalities", default-feat rand = "0.7.2" rand_chacha = "0.2.2" - [features] default = ["std"] std = [ diff --git a/primitives/keystore/src/lib.rs b/primitives/keystore/src/lib.rs index 6c27e3df7ce0..6540e71bc3fe 100644 --- a/primitives/keystore/src/lib.rs +++ b/primitives/keystore/src/lib.rs @@ -29,19 +29,19 @@ use sp_core::{ use std::sync::Arc; /// CryptoStore error -#[derive(Debug, derive_more::Display)] +#[derive(Debug, thiserror::Error)] pub enum Error { /// Public key type is not supported - #[display(fmt = "Key not supported: {:?}", _0)] + #[error("Key not supported: {0:?}")] KeyNotSupported(KeyTypeId), /// Validation error - #[display(fmt = "Validation error: {}", _0)] + #[error("Validation error: {0}")] ValidationError(String), /// Keystore unavailable - #[display(fmt = "Keystore unavailable")] + #[error("Keystore unavailable")] Unavailable, /// Programming errors - #[display(fmt = "An unknown keystore error occurred: {}", _0)] + #[error("An unknown keystore error occurred: {0}")] Other(String), } diff --git a/test-utils/runtime/transaction-pool/Cargo.toml b/test-utils/runtime/transaction-pool/Cargo.toml index 39221a2d1579..2a94f2484587 100644 --- a/test-utils/runtime/transaction-pool/Cargo.toml +++ b/test-utils/runtime/transaction-pool/Cargo.toml @@ -20,4 +20,4 @@ sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" } sc-transaction-pool = { version = "4.0.0-dev", path = "../../../client/transaction-pool" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../../../client/transaction-pool/api" } futures = "0.3.16" -derive_more = "0.99.16" +thiserror = "1.0" diff --git a/test-utils/runtime/transaction-pool/src/lib.rs b/test-utils/runtime/transaction-pool/src/lib.rs index ba317f57f531..400842762349 100644 --- a/test-utils/runtime/transaction-pool/src/lib.rs +++ b/test-utils/runtime/transaction-pool/src/lib.rs @@ -40,8 +40,9 @@ use substrate_test_runtime_client::{ }; /// Error type used by [`TestApi`]. -#[derive(Debug, derive_more::From, derive_more::Display)] -pub struct Error(sc_transaction_pool_api::error::Error); +#[derive(Debug, thiserror::Error)] +#[error(transparent)] +pub struct Error(#[from] sc_transaction_pool_api::error::Error); impl sc_transaction_pool_api::error::IntoPoolError for Error { fn into_pool_error(self) -> Result { @@ -49,12 +50,6 @@ impl sc_transaction_pool_api::error::IntoPoolError for Error { } } -impl std::error::Error for Error { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - Some(&self.0) - } -} - pub enum IsBestBlock { Yes, No, diff --git a/utils/prometheus/Cargo.toml b/utils/prometheus/Cargo.toml index 4ae38f645532..27b5f94305fd 100644 --- a/utils/prometheus/Cargo.toml +++ b/utils/prometheus/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] log = "0.4.8" prometheus = { version = "0.13.0", default-features = false } futures-util = { version = "0.3.19", default-features = false, features = ["io"] } -derive_more = "0.99" +thiserror = "1.0" async-std = { version = "1.10.0", features = ["unstable"] } tokio = "1.15" hyper = { version = "0.14.16", default-features = false, features = ["http1", "server", "tcp"] } diff --git a/utils/prometheus/src/lib.rs b/utils/prometheus/src/lib.rs index f1d87ac9f729..3d28d9cd6f1c 100644 --- a/utils/prometheus/src/lib.rs +++ b/utils/prometheus/src/lib.rs @@ -47,27 +47,22 @@ pub fn register( Ok(metric) } -#[derive(Debug, derive_more::Display, derive_more::From)] +#[derive(Debug, thiserror::Error)] pub enum Error { /// Hyper internal error. - Hyper(hyper::Error), + #[error(transparent)] + Hyper(#[from] hyper::Error), + /// Http request error. - Http(hyper::http::Error), + #[error(transparent)] + Http(#[from] hyper::http::Error), + /// i/o error. - Io(std::io::Error), - #[display(fmt = "Prometheus port {} already in use.", _0)] - PortInUse(SocketAddr), -} + #[error(transparent)] + Io(#[from] std::io::Error), -impl std::error::Error for Error { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self { - Error::Hyper(error) => Some(error), - Error::Http(error) => Some(error), - Error::Io(error) => Some(error), - Error::PortInUse(_) => None, - } - } + #[error("Prometheus port {0} already in use.")] + PortInUse(SocketAddr), } async fn request_metrics(req: Request, registry: Registry) -> Result, Error> { From e4f9551a4d63f2f1761082439590d9865adf4dec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Tue, 25 Jan 2022 20:57:56 +0100 Subject: [PATCH 423/695] basic-authorship: Add new metrics for block size limit and weight limit (#10697) * basic-authorship: Add new metriscs for block size limit and weight limit * Review feedback --- .../basic-authorship/src/basic_authorship.rs | 28 +++++++++------ client/proposer-metrics/src/lib.rs | 36 +++++++++++++++++-- 2 files changed, 51 insertions(+), 13 deletions(-) diff --git a/client/basic-authorship/src/basic_authorship.rs b/client/basic-authorship/src/basic_authorship.rs index 5ab207e39e58..23725e513869 100644 --- a/client/basic-authorship/src/basic_authorship.rs +++ b/client/basic-authorship/src/basic_authorship.rs @@ -47,7 +47,7 @@ use sp_runtime::{ use std::{marker::PhantomData, pin::Pin, sync::Arc, time}; use prometheus_endpoint::Registry as PrometheusRegistry; -use sc_proposer_metrics::MetricsLink as PrometheusMetrics; +use sc_proposer_metrics::{EndProposingReason, MetricsLink as PrometheusMetrics}; /// Default block size limit in bytes used by [`Proposer`]. /// @@ -412,16 +412,21 @@ where debug!("Attempting to push transactions from the pool."); debug!("Pool status: {:?}", self.transaction_pool.status()); let mut transaction_pushed = false; - let mut hit_block_size_limit = false; - while let Some(pending_tx) = pending_iterator.next() { + let end_reason = loop { + let pending_tx = if let Some(pending_tx) = pending_iterator.next() { + pending_tx + } else { + break EndProposingReason::NoMoreTransactions + }; + let now = (self.now)(); if now > deadline { debug!( "Consensus deadline reached when pushing block transactions, \ proceeding with proposing." ); - break + break EndProposingReason::HitDeadline } let pending_tx_data = pending_tx.data().clone(); @@ -448,8 +453,7 @@ where continue } else { debug!("Reached block size limit, proceeding with proposing."); - hit_block_size_limit = true; - break + break EndProposingReason::HitBlockSizeLimit } } @@ -473,8 +477,8 @@ where so we will try a bit more before quitting." ); } else { - debug!("Block is full, proceed with proposing."); - break + debug!("Reached block weight limit, proceeding with proposing."); + break EndProposingReason::HitBlockWeightLimit } }, Err(e) if skipped > 0 => { @@ -491,9 +495,9 @@ where unqueue_invalid.push(pending_tx_hash); }, } - } + }; - if hit_block_size_limit && !transaction_pushed { + if matches!(end_reason, EndProposingReason::HitBlockSizeLimit) && !transaction_pushed { warn!( "Hit block size limit of `{}` without including any transaction!", block_size_limit, @@ -507,6 +511,8 @@ where self.metrics.report(|metrics| { metrics.number_of_transactions.set(block.extrinsics().len() as u64); metrics.block_constructed.observe(block_timer.elapsed().as_secs_f64()); + + metrics.report_end_proposing_reason(end_reason); }); info!( @@ -518,7 +524,7 @@ where block.extrinsics().len(), block.extrinsics() .iter() - .map(|xt| format!("{}", BlakeTwo256::hash_of(xt))) + .map(|xt| BlakeTwo256::hash_of(xt).to_string()) .collect::>() .join(", ") ); diff --git a/client/proposer-metrics/src/lib.rs b/client/proposer-metrics/src/lib.rs index a34660faab5d..c27d16ea04d7 100644 --- a/client/proposer-metrics/src/lib.rs +++ b/client/proposer-metrics/src/lib.rs @@ -19,7 +19,8 @@ //! Prometheus basic proposer metrics. use prometheus_endpoint::{ - register, Gauge, Histogram, HistogramOpts, PrometheusError, Registry, U64, + prometheus::CounterVec, register, Gauge, Histogram, HistogramOpts, Opts, PrometheusError, + Registry, U64, }; /// Optional shareable link to basic authorship metrics. @@ -38,15 +39,24 @@ impl MetricsLink { } pub fn report(&self, do_this: impl FnOnce(&Metrics) -> O) -> Option { - Some(do_this(self.0.as_ref()?)) + self.0.as_ref().map(do_this) } } +/// The reason why proposing a block ended. +pub enum EndProposingReason { + NoMoreTransactions, + HitDeadline, + HitBlockSizeLimit, + HitBlockWeightLimit, +} + /// Authorship metrics. #[derive(Clone)] pub struct Metrics { pub block_constructed: Histogram, pub number_of_transactions: Gauge, + pub end_proposing_reason: CounterVec, pub create_inherents_time: Histogram, pub create_block_proposal_time: Histogram, } @@ -82,6 +92,28 @@ impl Metrics { ))?, registry, )?, + end_proposing_reason: register( + CounterVec::new( + Opts::new( + "substrate_proposer_end_proposal_reason", + "The reason why the block proposing was ended. This doesn't include errors.", + ), + &["reason"], + )?, + registry, + )?, }) } + + /// Report the reason why the proposing ended. + pub fn report_end_proposing_reason(&self, reason: EndProposingReason) { + let reason = match reason { + EndProposingReason::HitDeadline => "hit_deadline", + EndProposingReason::NoMoreTransactions => "no_more_transactions", + EndProposingReason::HitBlockSizeLimit => "hit_block_size_limit", + EndProposingReason::HitBlockWeightLimit => "hit_block_weight_limit", + }; + + self.end_proposing_reason.with_label_values(&[reason]).inc(); + } } From 23b2158676a9e271e215620d7927e08d024cb66b Mon Sep 17 00:00:00 2001 From: driemworks Date: Tue, 25 Jan 2022 18:47:48 -0500 Subject: [PATCH 424/695] pin files and become storage provider works, signers use aura keys for now --- bin/node-template/node/src/service.rs | 10 +-- .../pallets/iris-assets/src/lib.rs | 5 +- .../pallets/iris-session/src/lib.rs | 72 ++++++++++++++----- 3 files changed, 62 insertions(+), 25 deletions(-) diff --git a/bin/node-template/node/src/service.rs b/bin/node-template/node/src/service.rs index 7bafe6086196..6c0a12bf4b85 100644 --- a/bin/node-template/node/src/service.rs +++ b/bin/node-template/node/src/service.rs @@ -195,11 +195,11 @@ pub fn new_full(mut config: Configuration) -> Result })?; let keystore = keystore_container.sync_keystore(); if config.offchain_worker.enabled { - sp_keystore::SyncCryptoStore::sr25519_generate_new( - &*keystore, - KeyTypeId(*b"iris"), - Some("//Alice"), - ).expect("Creating key with account Alice should succeed."); + // sp_keystore::SyncCryptoStore::sr25519_generate_new( + // &*keystore, + // KeyTypeId(*b"iris"), + // Some("//Alice"), + // ).expect("Creating key with account Alice should succeed."); sc_service::build_offchain_workers( &config, task_manager.spawn_handle(), diff --git a/bin/node-template/pallets/iris-assets/src/lib.rs b/bin/node-template/pallets/iris-assets/src/lib.rs index e8e2bbfa2fa4..5d0304bea8a7 100644 --- a/bin/node-template/pallets/iris-assets/src/lib.rs +++ b/bin/node-template/pallets/iris-assets/src/lib.rs @@ -66,8 +66,8 @@ pub enum DataCommand { AddBytes(OpaqueMultiaddr, Vec, LookupSource, Vec, AssetId, Balance), /// (owner, assetid, recipient) CatBytes(AccountId, AssetId, AccountId), - /// (node, CID) - PinCID(AccountId, Vec), + /// (node, assetid, CID) + PinCID(AccountId, AssetId, Vec), } #[derive(Encode, Decode, RuntimeDebug, Clone, Default, Eq, PartialEq, TypeInfo)] @@ -393,6 +393,7 @@ pub mod pallet { >::mutate( |queue| queue.push(DataCommand::PinCID( who.clone(), + asset_id.clone(), cid.clone(), ))); Ok(()) diff --git a/bin/node-template/pallets/iris-session/src/lib.rs b/bin/node-template/pallets/iris-session/src/lib.rs index 684e6ce0d4c1..ff1f83c83109 100644 --- a/bin/node-template/pallets/iris-session/src/lib.rs +++ b/bin/node-template/pallets/iris-session/src/lib.rs @@ -59,7 +59,8 @@ use pallet_iris_assets::{ }; pub const LOG_TARGET: &'static str = "runtime::iris-session"; -pub const KEY_TYPE: KeyTypeId = KeyTypeId(*b"iris"); +// pub const KEY_TYPE: KeyTypeId = KeyTypeId(*b"iris"); +pub const KEY_TYPE: KeyTypeId = KeyTypeId(*b"aura"); pub mod crypto { use crate::KEY_TYPE; @@ -146,16 +147,6 @@ pub mod pallet { ValueQuery, >; - #[pallet::storage] - #[pallet::getter(fn substrate_ipfs_bridge)] - pub(super) type SubstrateIpfsBridge = StorageMap< - _, - Blake2_128Concat, - T::AccountId, - Vec, - ValueQuery, - >; - /// Maps an asset id to a collection of nodes that want to provider storage #[pallet::storage] #[pallet::getter(fn candidate_storage_providers)] @@ -178,6 +169,17 @@ pub mod pallet { ValueQuery, >; + /// maps an asset id to a collection of nodes that have inserted the pin for the underlying cid + #[pallet::storage] + #[pallet::getter(fn pinners)] + pub(super) type Pinners = StorageMap< + _, + Blake2_128Concat, + T::AssetId, + Vec, + ValueQuery, + >; + #[pallet::storage] #[pallet::getter(fn validators)] pub type Validators = StorageValue<_, Vec, ValueQuery>; @@ -226,6 +228,8 @@ pub mod pallet { InsufficientBalance, /// the node is already a candidate for some storage pool AlreadyACandidate, + /// the node has already pinned the CID + AlreadyPinned, } #[pallet::hooks] @@ -335,8 +339,8 @@ pub mod pallet { // submit a request to join a storage pool in the next session let who = ensure_signed(origin)?; let new_origin = system::RawOrigin::Signed(who.clone()).into(); - let csp = >::get(pool_id.clone()); - ensure!(!csp.contains(&who), Error::::AlreadyACandidate); + let candidate_storage_providers = >::get(pool_id.clone()); + ensure!(!candidate_storage_providers.contains(&who), Error::::AlreadyACandidate); // TODO: we need a better scheme for *generating* pool ids -> should always be unique (cid + owner maybe?) >::mutate(pool_id.clone(), |sp| { sp.push(who.clone()); @@ -365,6 +369,7 @@ pub mod pallet { ) -> DispatchResult { let who = ensure_signed(origin)?; let new_origin = system::RawOrigin::Signed(who.clone()).into(); + // creates the asset class >::submit_ipfs_add_results( new_origin, admin, @@ -395,6 +400,21 @@ pub mod pallet { Ok(()) } + #[pallet::weight(0)] + pub fn submit_ipfs_pin_result( + origin: OriginFor, + asset_id: T::AssetId, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + let current_pinners = >::get(asset_id.clone()); + ensure!(!current_pinners.contains(&who), Error::::AlreadyPinned); + // TODO: we need a better scheme for *generating* pool ids -> should always be unique (cid + owner maybe?) + >::mutate(asset_id.clone(), |p| { + p.push(who.clone()); + }); + Ok(()) + } + /// Should only be callable by OCWs (TODO) /// Submit the results onchain to notify a beneficiary that their data is available: TODO: how to safely share host? spam protection on rpc endpoints? /// @@ -714,7 +734,7 @@ impl Pallet { log::error!("the provided owner/cid does not map to a valid asset id: {:?}, {:?}", owner, asset_id) } }, - DataCommand::PinCID(acct, cid) => { + DataCommand::PinCID(acct, asset_id, cid) => { let (public_key, addrs) = if let IpfsResponse::Identity(public_key, addrs) = Self::ipfs_request(IpfsRequest::Identity, deadline)? { @@ -723,13 +743,29 @@ impl Pallet { unreachable!("only `Identity` is a valid response type."); }; let expected_pub_key = >::get(acct); + // todo: create new error enum if this is the route i choose ensure!(public_key == expected_pub_key, Error::::BadOrigin); match Self::ipfs_request(IpfsRequest::InsertPin(cid.clone(), false), deadline) { - // todo: create new error enum if this is the route i choose Ok(IpfsResponse::Success) => { log::info!("IPFS: Pinned CID {:?}", cid.clone()); - // TODO: Call some extrinsic to report you have pinned - // the cid. 'submit_ipfs_pin_results' + let signer = Signer::::all_accounts(); + if !signer.can_sign() { + log::error!( + "No local accounts available. Consider adding one via `author_insertKey` RPC.", + ); + } + let results = signer.send_signed_transaction(|_account| { + Call::submit_ipfs_pin_result{ + asset_id: asset_id, + } + }); + + for (_, res) in &results { + match res { + Ok(()) => log::info!("Submitted ipfs results"), + Err(e) => log::error!("Failed to submit transaction: {:?}", e), + } + } }, Ok(_) => unreachable!("only Success can be a response for that request type"), Err(e) => log::error!("IPFS: insert pin error: {:?}", e), @@ -770,7 +806,7 @@ impl pallet_session::SessionManager for Pallet { // Remove any offline validators. This will only work when the runtime // also has the im-online pallet. Self::remove_offline_validators(); - // Self::select_candidate_storage_providers(); + Self::select_candidate_storage_providers(); log::debug!(target: LOG_TARGET, "New session called; updated validator set provided."); Some(Self::validators()) } From 49606566a339aa33fb06ce3895e7c2ef15bc8294 Mon Sep 17 00:00:00 2001 From: driemworks Date: Tue, 25 Jan 2022 20:06:35 -0500 Subject: [PATCH 425/695] intersection of candidates and pinners become storage providers --- bin/node-template/pallets/iris-session/src/lib.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/bin/node-template/pallets/iris-session/src/lib.rs b/bin/node-template/pallets/iris-session/src/lib.rs index ff1f83c83109..6518319d2f28 100644 --- a/bin/node-template/pallets/iris-session/src/lib.rs +++ b/bin/node-template/pallets/iris-session/src/lib.rs @@ -518,12 +518,17 @@ impl Pallet { fn select_candidate_storage_providers() { // TODO: for now, we will just copy the candidates to the active providers map // no real selection is happening yet, just doing this to get it in place for now + // iterate over asset ids + // if there are candidate storage providers => for each candidate that pinned the file, move them to storage providers for assetid in >::asset_ids().into_iter() { // if there are candidates for the asset id if >::contains_key(assetid.clone()) { let candidates = >::get(assetid.clone()); - // need to only move candidates that have actually proved they pinned the content - >::insert(assetid.clone(), candidates); + let pinners = >::get(assetid.clone()); + let pinner_candidate_intersection = + candidates.into_iter().filter(|c| pinners.contains(c)).collect::>(); + // need to only move candidates that have actually proved they pinned the content + >::insert(assetid.clone(), pinner_candidate_intersection); } } } From 293fbeb6903904a7d02d462d9cf8614715c1f117 Mon Sep 17 00:00:00 2001 From: Alexander Popiak Date: Wed, 26 Jan 2022 12:12:20 +0100 Subject: [PATCH 426/695] add CheckNonZeroSender in node-template-runtime (#10735) --- bin/node-template/runtime/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index 2aa6bf1f1ae7..0b39d76fe495 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -299,6 +299,7 @@ pub type Header = generic::Header; pub type Block = generic::Block; /// The SignedExtension to the basic transaction logic. pub type SignedExtra = ( + frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, frame_system::CheckGenesis, From b62e6183cfbdd0c7f901ef851084f07241ac22c0 Mon Sep 17 00:00:00 2001 From: Alexander Samusev <41779041+alvicsam@users.noreply.github.com> Date: Wed, 26 Jan 2022 18:03:37 +0100 Subject: [PATCH 427/695] [ci] pipeline chores (#10734) * [ci] pipeline chores --- .gitlab-ci.yml | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b2716b018d6c..f6f714ea52b1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -209,18 +209,6 @@ default: AWS_SECRET_ACCESS_KEY: vault: cicd/gitlab/$CI_PROJECT_PATH/AWS_SECRET_ACCESS_KEY@kv file: false - AWX_TOKEN: - vault: cicd/gitlab/$CI_PROJECT_PATH/AWX_TOKEN@kv - file: false - CRATES_TOKEN: - vault: cicd/gitlab/$CI_PROJECT_PATH/CRATES_TOKEN@kv - file: false - DOCKER_CHAOS_TOKEN: - vault: cicd/gitlab/$CI_PROJECT_PATH/DOCKER_CHAOS_TOKEN@kv - file: false - DOCKER_CHAOS_USER: - vault: cicd/gitlab/$CI_PROJECT_PATH/DOCKER_CHAOS_USER@kv - file: false GITHUB_EMAIL: vault: cicd/gitlab/$CI_PROJECT_PATH/GITHUB_EMAIL@kv file: false @@ -239,22 +227,13 @@ default: MATRIX_ROOM_ID: vault: cicd/gitlab/$CI_PROJECT_PATH/MATRIX_ROOM_ID@kv file: false - PIPELINE_TOKEN: - vault: cicd/gitlab/$CI_PROJECT_PATH/PIPELINE_TOKEN@kv - file: false - VALIDATOR_KEYS: - vault: cicd/gitlab/$CI_PROJECT_PATH/VALIDATOR_KEYS@kv - file: false - VALIDATOR_KEYS_CHAOS: - vault: cicd/gitlab/$CI_PROJECT_PATH/VALIDATOR_KEYS_CHAOS@kv - file: false + #### stage: .pre skip-if-draft: image: paritytech/tools:latest <<: *kubernetes-env - <<: *vault-secrets stage: .pre rules: - if: $CI_COMMIT_REF_NAME =~ /^[0-9]+$/ # PRs @@ -270,7 +249,6 @@ check-runtime: stage: check image: paritytech/tools:latest <<: *kubernetes-env - <<: *vault-secrets rules: - if: $CI_COMMIT_REF_NAME =~ /^[0-9]+$/ # PRs variables: @@ -285,7 +263,6 @@ check-signed-tag: stage: check image: paritytech/tools:latest <<: *kubernetes-env - <<: *vault-secrets rules: - if: $CI_COMMIT_REF_NAME =~ /^ci-release-.*$/ - if: $CI_COMMIT_REF_NAME =~ /^v[0-9]+\.[0-9]+.*$/ # i.e. v1.0, v2.1rc1 @@ -548,7 +525,6 @@ cargo-check-macos: stage: build <<: *docker-env <<: *test-refs-no-trigger-prs-only - <<: *vault-secrets script: - git clone --depth=1 From c536b016a57786abbbbbb4154decc264ec64d561 Mon Sep 17 00:00:00 2001 From: driemworks Date: Wed, 26 Jan 2022 16:21:13 -0500 Subject: [PATCH 428/695] add validator checks --- .../pallets/iris-session/src/lib.rs | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/bin/node-template/pallets/iris-session/src/lib.rs b/bin/node-template/pallets/iris-session/src/lib.rs index 6518319d2f28..537b0411155c 100644 --- a/bin/node-template/pallets/iris-session/src/lib.rs +++ b/bin/node-template/pallets/iris-session/src/lib.rs @@ -235,23 +235,25 @@ pub mod pallet { #[pallet::hooks] impl Hooks> for Pallet { fn offchain_worker(block_number: T::BlockNumber) { - // every 5 blocks - if block_number % 5u32.into() == 0u32.into() { - if let Err(e) = Self::connection_housekeeping() { - log::error!("IPFS: Encountered an error while processing data requests: {:?}", e); - } - } - // handle data requests each block - if let Err(e) = Self::handle_data_requests() { - log::error!("IPFS: Encountered an error while processing data requests: {:?}", e); - } + if sp_io::offchain::is_validator() { + // every 5 blocks + if block_number % 5u32.into() == 0u32.into() { + if let Err(e) = Self::connection_housekeeping() { + log::error!("IPFS: Encountered an error while processing data requests: {:?}", e); + } + } + // handle data requests each block + if let Err(e) = Self::handle_data_requests() { + log::error!("IPFS: Encountered an error while processing data requests: {:?}", e); + } - // every 5 blocks - if block_number % 5u32.into() == 0u32.into() { - if let Err(e) = Self::print_metadata() { - log::error!("IPFS: Encountered an error while obtaining metadata: {:?}", e); - } - } + // every 5 blocks + if block_number % 5u32.into() == 0u32.into() { + if let Err(e) = Self::print_metadata() { + log::error!("IPFS: Encountered an error while obtaining metadata: {:?}", e); + } + } + } } } @@ -697,6 +699,7 @@ impl Pallet { } }, DataCommand::CatBytes(owner, asset_id, recipient) => { + // TODO: Could potentially remove the owner here by restructuring runtime storage -> would need unique asset ids if let cid = >::asset_class_ownership( owner.clone(), asset_id.clone() ) { From 71baca710bae30b4779ea3452e41afb1de6bd1fe Mon Sep 17 00:00:00 2001 From: Dan Shields <35669742+NukeManDan@users.noreply.github.com> Date: Wed, 26 Jan 2022 15:47:17 -0700 Subject: [PATCH 429/695] Update Node Template (#10710) * update node template from downsteam template version = 4.0.0-dev rust setup updated * Update bin/node-template/runtime/Cargo.toml Co-authored-by: Shawn Tabrizi * Review Rust setup README * Apply suggestions from code review Co-authored-by: Shawn Tabrizi Co-authored-by: Sacha Lansky --- Cargo.lock | 6 +- bin/node-template/README.md | 17 +- bin/node-template/docs/rust-setup.md | 219 +++++++++++++++--- bin/node-template/node/Cargo.toml | 5 +- bin/node-template/pallets/template/Cargo.toml | 2 +- bin/node-template/runtime/Cargo.toml | 11 +- 6 files changed, 203 insertions(+), 57 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a8092fffa7c0..0dbafc147f6b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4858,7 +4858,7 @@ dependencies = [ [[package]] name = "node-template" -version = "3.0.0" +version = "4.0.0-dev" dependencies = [ "clap 3.0.7", "frame-benchmarking", @@ -4895,7 +4895,7 @@ dependencies = [ [[package]] name = "node-template-runtime" -version = "3.0.0" +version = "4.0.0-dev" dependencies = [ "frame-benchmarking", "frame-executive", @@ -6200,7 +6200,7 @@ dependencies = [ [[package]] name = "pallet-template" -version = "3.0.0" +version = "4.0.0-dev" dependencies = [ "frame-benchmarking", "frame-support", diff --git a/bin/node-template/README.md b/bin/node-template/README.md index bb4df52f41a8..a04f6a12ed73 100644 --- a/bin/node-template/README.md +++ b/bin/node-template/README.md @@ -72,20 +72,20 @@ Start the development chain with detailed logging: ```bash RUST_BACKTRACE=1 ./target/release/node-template -ldebug --dev ``` + > Development chain means that the state of our chain will be in a tmp folder while the nodes are -> running. Also, **alice** account will be authority and sudo account as declared in the [genesis -> state](https://github.com/substrate-developer-hub/substrate-node-template/blob/main/node/src/chain_spec.rs#L49). -> At the same time the following accounts will be prefunded: +> running. Also, **alice** account will be authority and sudo account as declared in the +> [genesis state](https://github.com/substrate-developer-hub/substrate-node-template/blob/main/node/src/chain_spec.rs#L49). +> At the same time the following accounts will be pre-funded: > - Alice > - Bob > - Alice//stash > - Bob//stash -In case of being interested in maintaining the chain' state futher in time a base path other than -a temporary directory must be added so the db can be stored in the provided folder. We could use -this folder to store different chain databases, as a different folder will be created per different - chain that is ran. The following commands shows how to use a newly created folder as our db base - path. +In case of being interested in maintaining the chain' state between runs a base path must be added +so the db can be stored in the provided folder instead of a temporal one. We could use this folder +to store different chain databases, as a different folder will be created per different chain that +is ran. The following commands shows how to use a newly created folder as our db base path. ```bash // Create a folder to use as the db base path @@ -103,6 +103,7 @@ $ ls ./my-chain-state/chains/dev db keystore network ``` + ### Connect with Polkadot-JS Apps Front-end Once the node template is running locally, you can connect it with **Polkadot-JS Apps** front-end diff --git a/bin/node-template/docs/rust-setup.md b/bin/node-template/docs/rust-setup.md index 4b96da1146b8..ea133ca847af 100644 --- a/bin/node-template/docs/rust-setup.md +++ b/bin/node-template/docs/rust-setup.md @@ -2,32 +2,21 @@ title: Installation --- -This page will guide you through the steps needed to prepare a computer for development with the -Substrate Node Template. Since Substrate is built with -[the Rust programming language](https://www.rust-lang.org/), the first thing you will need to do is -prepare the computer for Rust development - these steps will vary based on the computer's operating -system. Once Rust is configured, you will use its toolchains to interact with Rust projects; the -commands for Rust's toolchains will be the same for all supported, Unix-based operating systems. +This guide is for reference only, please check the latest information on getting starting with Substrate +[here](https://docs.substrate.io/v3/getting-started/installation/). -## Unix-Based Operating Systems +This page will guide you through the **2 steps** needed to prepare a computer for **Substrate** development. +Since Substrate is built with [the Rust programming language](https://www.rust-lang.org/), the first +thing you will need to do is prepare the computer for Rust development - these steps will vary based +on the computer's operating system. Once Rust is configured, you will use its toolchains to interact +with Rust projects; the commands for Rust's toolchains will be the same for all supported, +Unix-based operating systems. -Substrate development is easiest on Unix-based operating systems like macOS or Linux. The examples -in the Substrate [Tutorials](https://docs.substrate.io/tutorials/v3) and -[How-to Guides](https://docs.substrate.io/how-to-guides/v3) use Unix-style terminals to demonstrate -how to interact with Substrate from the command line. - -### macOS +## Build dependencies -Open the Terminal application and execute the following commands: - -```bash -# Install Homebrew if necessary https://brew.sh/ -/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" - -# Make sure Homebrew is up-to-date, install openssl and cmake -brew update -brew install openssl cmake -``` +Substrate development is easiest on Unix-based operating systems like macOS or Linux. The examples +in the [Substrate Docs](https://docs.substrate.io) use Unix-style terminals to demonstrate how to +interact with Substrate from the command line. ### Ubuntu/Debian @@ -36,7 +25,7 @@ Use a terminal shell to execute the following commands: ```bash sudo apt update # May prompt for location information -sudo apt install -y cmake pkg-config libssl-dev git build-essential clang libclang-dev curl +sudo apt install -y git clang curl libssl-dev llvm libudev-dev ``` ### Arch Linux @@ -44,39 +33,193 @@ sudo apt install -y cmake pkg-config libssl-dev git build-essential clang libcla Run these commands from a terminal: ```bash -pacman -Syu --needed --noconfirm cmake gcc openssl-1.0 pkgconf git clang -export OPENSSL_LIB_DIR="/usr/lib/openssl-1.0" -export OPENSSL_INCLUDE_DIR="/usr/include/openssl-1.0" +pacman -Syu --needed --noconfirm curl git clang ``` -### Fedora/RHEL/CentOS +### Fedora -Use a terminal to run the following commands: +Run these commands from a terminal: ```bash -# Update sudo dnf update -# Install packages -sudo dnf install cmake pkgconfig rocksdb rocksdb-devel llvm git libcurl libcurl-devel curl-devel clang +sudo dnf install clang curl git openssl-devel +``` + +### OpenSUSE + +Run these commands from a terminal: + +```bash +sudo zypper install clang curl git openssl-devel llvm-devel libudev-devel +``` + +### macOS + +> **Apple M1 ARM** +> If you have an Apple M1 ARM system on a chip, make sure that you have Apple Rosetta 2 +> installed through `softwareupdate --install-rosetta`. This is only needed to run the +> `protoc` tool during the build. The build itself and the target binaries would remain native. + +Open the Terminal application and execute the following commands: + +```bash +# Install Homebrew if necessary https://brew.sh/ +/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" + +# Make sure Homebrew is up-to-date, install openssl +brew update +brew install openssl ``` -## Rust Developer Environment +### Windows + +**_PLEASE NOTE:_** Native development of Substrate is _not_ very well supported! It is _highly_ +recommend to use [Windows Subsystem Linux](https://docs.microsoft.com/en-us/windows/wsl/install-win10) +(WSL) and follow the instructions for [Ubuntu/Debian](#ubuntudebian). +Please refer to the separate +[guide for native Windows development](https://docs.substrate.io/v3/getting-started/windows-users/). -This project uses [`rustup`](https://rustup.rs/) to help manage the Rust toolchain. First install -and configure `rustup`: +## Rust developer environment + +This guide uses installer and the `rustup` tool to manage the Rust toolchain. +First install and configure `rustup`: ```bash # Install -curl https://sh.rustup.rs -sSf | sh +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh # Configure source ~/.cargo/env ``` -Finally, configure the Rust toolchain: +Configure the Rust toolchain to default to the latest stable version, add nightly and the nightly wasm target: ```bash rustup default stable +rustup update +rustup update nightly +rustup target add wasm32-unknown-unknown --toolchain nightly +``` + +## Test your set-up + +Now the best way to ensure that you have successfully prepared a computer for Substrate +development is to follow the steps in [our first Substrate tutorial](https://docs.substrate.io/tutorials/v3/create-your-first-substrate-chain/). + +## Troubleshooting Substrate builds + +Sometimes you can't get the Substrate node template +to compile out of the box. Here are some tips to help you work through that. + +### Rust configuration check + +To see what Rust toolchain you are presently using, run: + +```bash +rustup show +``` + +This will show something like this (Ubuntu example) output: + +```text +Default host: x86_64-unknown-linux-gnu +rustup home: /home/user/.rustup + +installed toolchains +-------------------- + +stable-x86_64-unknown-linux-gnu (default) +nightly-2020-10-06-x86_64-unknown-linux-gnu +nightly-x86_64-unknown-linux-gnu + +installed targets for active toolchain +-------------------------------------- + +wasm32-unknown-unknown +x86_64-unknown-linux-gnu + +active toolchain +---------------- + +stable-x86_64-unknown-linux-gnu (default) +rustc 1.50.0 (cb75ad5db 2021-02-10) +``` + +As you can see above, the default toolchain is stable, and the +`nightly-x86_64-unknown-linux-gnu` toolchain as well as its `wasm32-unknown-unknown` target is installed. +You also see that `nightly-2020-10-06-x86_64-unknown-linux-gnu` is installed, but is not used unless explicitly defined as illustrated in the [specify your nightly version](#specifying-nightly-version) +section. + +### WebAssembly compilation + +Substrate uses [WebAssembly](https://webassembly.org) (Wasm) to produce portable blockchain +runtimes. You will need to configure your Rust compiler to use +[`nightly` builds](https://doc.rust-lang.org/book/appendix-07-nightly-rust.html) to allow you to +compile Substrate runtime code to the Wasm target. + +> There are upstream issues in Rust that need to be resolved before all of Substrate can use the stable Rust toolchain. +> [This is our tracking issue](https://github.com/paritytech/substrate/issues/1252) if you're curious as to why and how this will be resolved. + +#### Latest nightly for Substrate `master` + +Developers who are building Substrate _itself_ should always use the latest bug-free versions of +Rust stable and nightly. This is because the Substrate codebase follows the tip of Rust nightly, +which means that changes in Substrate often depend on upstream changes in the Rust nightly compiler. +To ensure your Rust compiler is always up to date, you should run: + +```bash +rustup update rustup update nightly -rustup update stable rustup target add wasm32-unknown-unknown --toolchain nightly ``` + +> NOTE: It may be necessary to occasionally rerun `rustup update` if a change in the upstream Substrate +> codebase depends on a new feature of the Rust compiler. When you do this, both your nightly +> and stable toolchains will be pulled to the most recent release, and for nightly, it is +> generally _not_ expected to compile WASM without error (although it very often does). +> Be sure to [specify your nightly version](#specifying-nightly-version) if you get WASM build errors +> from `rustup` and [downgrade nightly as needed](#downgrading-rust-nightly). + +#### Rust nightly toolchain + +If you want to guarantee that your build works on your computer as you update Rust and other +dependencies, you should use a specific Rust nightly version that is known to be +compatible with the version of Substrate they are using; this version will vary from project to +project and different projects may use different mechanisms to communicate this version to +developers. For instance, the Polkadot client specifies this information in its +[release notes](https://github.com/paritytech/polkadot/releases). + +```bash +# Specify the specific nightly toolchain in the date below: +rustup install nightly- +``` + +#### Wasm toolchain + +Now, configure the nightly version to work with the Wasm compilation target: + +```bash +rustup target add wasm32-unknown-unknown --toolchain nightly- +``` + +### Specifying nightly version + +Use the `WASM_BUILD_TOOLCHAIN` environment variable to specify the Rust nightly version a Substrate +project should use for Wasm compilation: + +```bash +WASM_BUILD_TOOLCHAIN=nightly- cargo build --release +``` + +> Note that this only builds _the runtime_ with the specified nightly. The rest of project will be +> compiled with **your default toolchain**, i.e. the latest installed stable toolchain. + +### Downgrading Rust nightly + +If your computer is configured to use the latest Rust nightly and you would like to downgrade to a +specific nightly version, follow these steps: + +```bash +rustup uninstall nightly +rustup install nightly- +rustup target add wasm32-unknown-unknown --toolchain nightly- +``` diff --git a/bin/node-template/node/Cargo.toml b/bin/node-template/node/Cargo.toml index 6b69d691d945..300a35252c05 100644 --- a/bin/node-template/node/Cargo.toml +++ b/bin/node-template/node/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "node-template" -version = "3.0.0" +version = "4.0.0-dev" description = "A fresh FRAME-based Substrate node, ready for hacking." authors = ["Substrate DevHub "] homepage = "https://substrate.io/" @@ -52,7 +52,8 @@ pallet-transaction-payment-rpc = { version = "4.0.0-dev", path = "../../../frame frame-benchmarking = { version = "4.0.0-dev", path = "../../../frame/benchmarking" } frame-benchmarking-cli = { version = "4.0.0-dev", path = "../../../utils/frame/benchmarking-cli" } -node-template-runtime = { version = "3.0.0", path = "../runtime" } +# Local Dependencies +node-template-runtime = { version = "4.0.0-dev", path = "../runtime" } [build-dependencies] substrate-build-script-utils = { version = "3.0.0", path = "../../../utils/build-script-utils" } diff --git a/bin/node-template/pallets/template/Cargo.toml b/bin/node-template/pallets/template/Cargo.toml index 9702501a3e0e..4dc4fb3c6e52 100644 --- a/bin/node-template/pallets/template/Cargo.toml +++ b/bin/node-template/pallets/template/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pallet-template" -version = "3.0.0" +version = "4.0.0-dev" description = "FRAME pallet template for defining custom runtime logic." authors = ["Substrate DevHub "] homepage = "https://substrate.io/" diff --git a/bin/node-template/runtime/Cargo.toml b/bin/node-template/runtime/Cargo.toml index b757029f2581..eb8fb9eb52a8 100644 --- a/bin/node-template/runtime/Cargo.toml +++ b/bin/node-template/runtime/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "node-template-runtime" -version = "3.0.0" -description = "A fresh FRAME-based Substrate runtime, ready for hacking." +version = "4.0.0-dev" +description = "A fresh FRAME-based Substrate node, ready for hacking." authors = ["Substrate DevHub "] homepage = "https://substrate.io/" edition = "2021" @@ -27,10 +27,10 @@ pallet-timestamp = { version = "4.0.0-dev", default-features = false, path = ".. pallet-transaction-payment = { version = "4.0.0-dev", default-features = false, path = "../../../frame/transaction-payment" } frame-executive = { version = "4.0.0-dev", default-features = false, path = "../../../frame/executive" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/api" } -sp-block-builder = { path = "../../../primitives/block-builder", default-features = false, version = "4.0.0-dev"} +sp-block-builder = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/block-builder"} sp-consensus-aura = { version = "0.10.0-dev", default-features = false, path = "../../../primitives/consensus/aura" } sp-core = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/core" } -sp-inherents = { path = "../../../primitives/inherents", default-features = false, version = "4.0.0-dev"} +sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/inherents"} sp-offchain = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/offchain" } sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/runtime" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/session" } @@ -47,7 +47,8 @@ frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = " frame-system-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../../../frame/system/benchmarking", optional = true } hex-literal = { version = "0.3.4", optional = true } -pallet-template = { version = "3.0.0", default-features = false, path = "../pallets/template" } +# Local Dependencies +pallet-template = { version = "4.0.0-dev", default-features = false, path = "../pallets/template" } [build-dependencies] substrate-wasm-builder = { version = "5.0.0-dev", path = "../../../utils/wasm-builder" } From da534d7f945c72b373f157826a95786543a6ec9c Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Thu, 27 Jan 2022 11:00:48 +0100 Subject: [PATCH 430/695] better way to resolve `Phase::Emergency` via governance (#10663) * better way to resolve Phase::Emergency via governance * Update frame/election-provider-multi-phase/src/lib.rs Co-authored-by: Zeke Mostov * review grumbles * Update frame/election-provider-support/src/onchain.rs Co-authored-by: Shawn Tabrizi * revert usize -> u32 Co-authored-by: Zeke Mostov Co-authored-by: Shawn Tabrizi --- bin/node/runtime/src/lib.rs | 14 +++-- .../election-provider-multi-phase/src/lib.rs | 60 ++++++++++++++++++- .../election-provider-multi-phase/src/mock.rs | 1 + frame/election-provider-support/src/lib.rs | 16 +++++ .../election-provider-support/src/onchain.rs | 53 ++++++++++++---- 5 files changed, 122 insertions(+), 22 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 8f00dd8f64b4..e70adc6aa723 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -23,6 +23,7 @@ #![recursion_limit = "256"] use codec::{Decode, Encode, MaxEncodedLen}; +use frame_election_provider_support::onchain; use frame_support::{ construct_runtime, parameter_types, traits::{ @@ -528,12 +529,6 @@ parameter_types! { pub OffchainRepeat: BlockNumber = 5; } -use frame_election_provider_support::onchain; -impl onchain::Config for Runtime { - type Accuracy = Perbill; - type DataProvider = Staking; -} - pub struct StakingBenchmarkingConfig; impl pallet_staking::BenchmarkingConfig for StakingBenchmarkingConfig { type MaxNominators = ConstU32<1000>; @@ -649,6 +644,11 @@ impl frame_support::pallet_prelude::Get::DataProvider; +} + impl pallet_election_provider_multi_phase::Config for Runtime { type Event = Event; type Currency = Balances; @@ -671,6 +671,8 @@ impl pallet_election_provider_multi_phase::Config for Runtime { type DataProvider = Staking; type Solution = NposSolution16; type Fallback = pallet_election_provider_multi_phase::NoFallback; + type GovernanceFallback = + frame_election_provider_support::onchain::OnChainSequentialPhragmen; type Solver = frame_election_provider_support::SequentialPhragmen< AccountId, pallet_election_provider_multi_phase::SolutionAccuracyOf, diff --git a/frame/election-provider-multi-phase/src/lib.rs b/frame/election-provider-multi-phase/src/lib.rs index f1d1d78912c4..2b48373c5b0e 100644 --- a/frame/election-provider-multi-phase/src/lib.rs +++ b/frame/election-provider-multi-phase/src/lib.rs @@ -230,7 +230,9 @@ #![cfg_attr(not(feature = "std"), no_std)] use codec::{Decode, Encode}; -use frame_election_provider_support::{ElectionDataProvider, ElectionProvider}; +use frame_election_provider_support::{ + ElectionDataProvider, ElectionProvider, InstantElectionProvider, +}; use frame_support::{ dispatch::DispatchResultWithPostInfo, ensure, @@ -322,6 +324,15 @@ impl ElectionProvider for NoFallback { } } +impl InstantElectionProvider for NoFallback { + fn instant_elect( + _: Option, + _: Option, + ) -> Result, Self::Error> { + Err("NoFallback.") + } +} + /// Current phase of the pallet. #[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, Debug, TypeInfo)] pub enum Phase { @@ -555,7 +566,7 @@ pub use pallet::*; #[frame_support::pallet] pub mod pallet { use super::*; - use frame_election_provider_support::NposSolver; + use frame_election_provider_support::{InstantElectionProvider, NposSolver}; use frame_support::{pallet_prelude::*, traits::EstimateCallFee}; use frame_system::pallet_prelude::*; @@ -672,13 +683,23 @@ pub mod pallet { + NposSolution + TypeInfo; - /// Configuration for the fallback + /// Configuration for the fallback. type Fallback: ElectionProvider< AccountId = Self::AccountId, BlockNumber = Self::BlockNumber, DataProvider = Self::DataProvider, >; + /// Configuration of the governance-only fallback. + /// + /// As a side-note, it is recommend for test-nets to use `type ElectionProvider = + /// OnChainSeqPhragmen<_>` if the test-net is not expected to have thousands of nominators. + type GovernanceFallback: InstantElectionProvider< + AccountId = Self::AccountId, + BlockNumber = Self::BlockNumber, + DataProvider = Self::DataProvider, + >; + /// OCW election solution miner algorithm implementation. type Solver: NposSolver; @@ -1013,6 +1034,37 @@ pub mod pallet { }); Ok(()) } + + /// Trigger the governance fallback. + /// + /// This can only be called when [`Phase::Emergency`] is enabled, as an alternative to + /// calling [`Call::set_emergency_election_result`]. + #[pallet::weight(T::DbWeight::get().reads_writes(1, 1))] + pub fn governance_fallback( + origin: OriginFor, + maybe_max_voters: Option, + maybe_max_targets: Option, + ) -> DispatchResult { + T::ForceOrigin::ensure_origin(origin)?; + ensure!(Self::current_phase().is_emergency(), >::CallNotAllowed); + + let maybe_max_voters = maybe_max_voters.map(|x| x as usize); + let maybe_max_targets = maybe_max_targets.map(|x| x as usize); + + let supports = + T::GovernanceFallback::instant_elect(maybe_max_voters, maybe_max_targets).map_err( + |e| { + log!(error, "GovernanceFallback failed: {:?}", e); + Error::::FallbackFailed + }, + )?; + + let solution = + ReadySolution { supports, score: [0, 0, 0], compute: ElectionCompute::Fallback }; + + >::put(solution); + Ok(()) + } } #[pallet::event] @@ -1063,6 +1115,8 @@ pub mod pallet { InvalidSubmissionIndex, /// The call is not allowed at this point. CallNotAllowed, + /// The fallback failed + FallbackFailed, } #[pallet::validate_unsigned] diff --git a/frame/election-provider-multi-phase/src/mock.rs b/frame/election-provider-multi-phase/src/mock.rs index 1be93c363e32..9ac0ecfef5dc 100644 --- a/frame/election-provider-multi-phase/src/mock.rs +++ b/frame/election-provider-multi-phase/src/mock.rs @@ -410,6 +410,7 @@ impl crate::Config for Runtime { type WeightInfo = DualMockWeightInfo; type BenchmarkingConfig = TestBenchmarkingConfig; type Fallback = MockFallback; + type GovernanceFallback = NoFallback; type ForceOrigin = frame_system::EnsureRoot; type Solution = TestNposSolution; type VoterSnapshotPerBlock = VoterSnapshotPerBlock; diff --git a/frame/election-provider-support/src/lib.rs b/frame/election-provider-support/src/lib.rs index 3374e1e97b8b..26efe5107b67 100644 --- a/frame/election-provider-support/src/lib.rs +++ b/frame/election-provider-support/src/lib.rs @@ -319,6 +319,22 @@ pub trait ElectionProvider { fn elect() -> Result, Self::Error>; } +/// A sub-trait of the [`ElectionProvider`] for cases where we need to be sure an election needs to +/// happen instantly, not asynchronously. +/// +/// The same `DataProvider` is assumed to be used. +/// +/// Consequently, allows for control over the amount of data that is being fetched from the +/// [`ElectionProvider::DataProvider`]. +pub trait InstantElectionProvider: ElectionProvider { + /// Elect a new set of winners, instantly, with the given given limits set on the + /// `DataProvider`. + fn instant_elect( + maybe_max_voters: Option, + maybe_max_targets: Option, + ) -> Result, Self::Error>; +} + /// An election provider to be used only for testing. #[cfg(feature = "std")] pub struct NoElection(sp_std::marker::PhantomData); diff --git a/frame/election-provider-support/src/onchain.rs b/frame/election-provider-support/src/onchain.rs index 808b49ba6234..41245f67fb02 100644 --- a/frame/election-provider-support/src/onchain.rs +++ b/frame/election-provider-support/src/onchain.rs @@ -17,7 +17,7 @@ //! An implementation of [`ElectionProvider`] that does an on-chain sequential phragmen. -use crate::{ElectionDataProvider, ElectionProvider}; +use crate::{ElectionDataProvider, ElectionProvider, InstantElectionProvider}; use frame_support::{traits::Get, weights::DispatchClass}; use sp_npos_elections::*; use sp_std::{collections::btree_map::BTreeMap, marker::PhantomData, prelude::*}; @@ -47,8 +47,14 @@ impl From for Error { /// implementation ignores the additional data of the election data provider and gives no insight on /// how much weight was consumed. /// -/// Finally, this implementation does not impose any limits on the number of voters and targets that -/// are provided. +/// Finally, the [`ElectionProvider`] implementation of this type does not impose any limits on the +/// number of voters and targets that are fetched. This could potentially make this unsuitable for +/// execution onchain. On the other hand, the [`InstantElectionProvider`] implementation does limit +/// these inputs. +/// +/// It is advisable to use the former ([`ElectionProvider::elect`]) only at genesis, or for testing, +/// the latter [`InstantElectionProvider::instant_elect`] for onchain operations, with thoughtful +/// bounds. pub struct OnChainSequentialPhragmen(PhantomData); /// Configuration trait of [`OnChainSequentialPhragmen`]. @@ -68,16 +74,17 @@ pub trait Config: frame_system::Config { >; } -impl ElectionProvider for OnChainSequentialPhragmen { - type AccountId = T::AccountId; - type BlockNumber = T::BlockNumber; - type Error = Error; - type DataProvider = T::DataProvider; - - fn elect() -> Result, Self::Error> { - let voters = Self::DataProvider::voters(None).map_err(Error::DataProvider)?; - let targets = Self::DataProvider::targets(None).map_err(Error::DataProvider)?; - let desired_targets = Self::DataProvider::desired_targets().map_err(Error::DataProvider)?; +impl OnChainSequentialPhragmen { + fn elect_with( + maybe_max_voters: Option, + maybe_max_targets: Option, + ) -> Result, Error> { + let voters = ::DataProvider::voters(maybe_max_voters) + .map_err(Error::DataProvider)?; + let targets = ::DataProvider::targets(maybe_max_targets) + .map_err(Error::DataProvider)?; + let desired_targets = ::DataProvider::desired_targets() + .map_err(Error::DataProvider)?; let stake_map: BTreeMap = voters .iter() @@ -102,6 +109,26 @@ impl ElectionProvider for OnChainSequentialPhragmen { } } +impl ElectionProvider for OnChainSequentialPhragmen { + type AccountId = T::AccountId; + type BlockNumber = T::BlockNumber; + type Error = Error; + type DataProvider = T::DataProvider; + + fn elect() -> Result, Self::Error> { + Self::elect_with(None, None) + } +} + +impl InstantElectionProvider for OnChainSequentialPhragmen { + fn instant_elect( + maybe_max_voters: Option, + maybe_max_targets: Option, + ) -> Result, Self::Error> { + Self::elect_with(maybe_max_voters, maybe_max_targets) + } +} + #[cfg(test)] mod tests { use super::*; From 3c1d5b9a53ee1f6c045296666772e3b78f6da733 Mon Sep 17 00:00:00 2001 From: Davide Galassi Date: Thu, 27 Jan 2022 18:21:58 +0100 Subject: [PATCH 431/695] Add stale branches heads to finality notifications (#10639) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add stale branches heads to finality notifications Warning. Previous implementation was sending a notification for each block between the previous (explicitly) finalized block and the new finalized one (with an hardcoded limit of 256). Now finality notification is sent only for the new finalized head and it contains the hash of the new finalized head, new finalized head header, a list of all the implicitly finalized blocks and a list of stale branches heads (i.e. the branches heads that are not part of the canonical chain anymore). * Add implicitly finalized blocks list to `ChainEvent::Finalized` message The list contains all the blocks between the previously finalized block up to the parent of the currently finalized one, sorted by block number. `Finalized` messages handler, part of the `MaintainedTransactionPool` implementation for `BasicPool`, still propagate full set of finalized blocks to the txpool by iterating over implicitly finalized blocks list. * Rust fmt * Greedy evaluation of `stale_heads` during finalization * Fix outdated assumption in a comment * Removed a test optimization that is no more relevant The loop was there to prevent sending to `peer.network.on_block_finalized` the full list of finalized blocks. Now only the finalized heads are received. * Last finalized block lookup not required anymore * Tests for block finality notifications payloads * Document a bit tricky condition to avoid duplicate finalization notifications * More idiomatic way to skip an iterator entry Co-authored-by: Bastian Köcher * Cargo fmt iteration * Typo fix Co-authored-by: Bastian Köcher * Fix potential failure when a finalized orphan block is imported * Apply suggestions from code review Co-authored-by: Bastian Köcher * Apply suggestions from code review Co-authored-by: Bastian Köcher Co-authored-by: Bastian Köcher --- client/api/src/backend.rs | 18 +- client/api/src/client.rs | 10 +- .../src/protocol/sync/extra_requests.rs | 4 +- client/network/test/src/lib.rs | 8 +- client/service/src/client/client.rs | 162 ++++++++++++------ client/service/src/lib.rs | 25 +-- client/service/test/src/client/mod.rs | 151 +++++++++++++++- client/transaction-pool/api/src/lib.rs | 6 +- client/transaction-pool/src/lib.rs | 16 +- client/transaction-pool/tests/pool.rs | 14 +- 10 files changed, 303 insertions(+), 111 deletions(-) diff --git a/client/api/src/backend.rs b/client/api/src/backend.rs index 004c0574fcbe..bb2579e4a420 100644 --- a/client/api/src/backend.rs +++ b/client/api/src/backend.rs @@ -70,14 +70,26 @@ pub struct ImportSummary { pub tree_route: Option>, } -/// Import operation wrapper +/// Finalization operation summary. +/// +/// Contains information about the block that just got finalized, +/// including tree heads that became stale at the moment of finalization. +pub struct FinalizeSummary { + /// Blocks that were finalized. + /// The last entry is the one that has been explicitly finalized. + pub finalized: Vec, + /// Heads that became stale during this finalization operation. + pub stale_heads: Vec, +} + +/// Import operation wrapper. pub struct ClientImportOperation> { /// DB Operation. pub op: B::BlockImportOperation, /// Summary of imported block. pub notify_imported: Option>, - /// A list of hashes of blocks that got finalized. - pub notify_finalized: Vec, + /// Summary of finalized block. + pub notify_finalized: Option>, } /// Helper function to apply auxiliary data insertion into an operation. diff --git a/client/api/src/client.rs b/client/api/src/client.rs index b6a5fbfad47a..9bb212099565 100644 --- a/client/api/src/client.rs +++ b/client/api/src/client.rs @@ -273,10 +273,14 @@ pub struct BlockImportNotification { /// Summary of a finalized block. #[derive(Clone, Debug)] pub struct FinalityNotification { - /// Imported block header hash. + /// Finalized block header hash. pub hash: Block::Hash, - /// Imported block header. + /// Finalized block header. pub header: Block::Header, + /// Path from the old finalized to new finalized parent (implicitly finalized blocks). + pub tree_route: Arc>, + /// Stale branches heads. + pub stale_heads: Arc>, } impl TryFrom> for ChainEvent { @@ -293,6 +297,6 @@ impl TryFrom> for ChainEvent { impl From> for ChainEvent { fn from(n: FinalityNotification) -> Self { - Self::Finalized { hash: n.hash } + Self::Finalized { hash: n.hash, tree_route: n.tree_route } } } diff --git a/client/network/src/protocol/sync/extra_requests.rs b/client/network/src/protocol/sync/extra_requests.rs index 680094a74143..224fbd1a1e01 100644 --- a/client/network/src/protocol/sync/extra_requests.rs +++ b/client/network/src/protocol/sync/extra_requests.rs @@ -173,9 +173,7 @@ impl ExtraRequests { } if best_finalized_number > self.best_seen_finalized_number { - // normally we'll receive finality notifications for every block => finalize would be - // enough but if many blocks are finalized at once, some notifications may be omitted - // => let's use finalize_with_ancestors here + // we receive finality notification only for the finalized branch head. match self.tree.finalize_with_ancestors( best_finalized_hash, best_finalized_number, diff --git a/client/network/test/src/lib.rs b/client/network/test/src/lib.rs index d9e27ce57511..b2345f3701b0 100644 --- a/client/network/test/src/lib.rs +++ b/client/network/test/src/lib.rs @@ -976,14 +976,10 @@ where peer.network.service().announce_block(notification.hash, None); } - // We poll `finality_notification_stream`, but we only take the last event. - let mut last = None; - while let Poll::Ready(Some(item)) = + // We poll `finality_notification_stream`. + while let Poll::Ready(Some(notification)) = peer.finality_notification_stream.as_mut().poll_next(cx) { - last = Some(item); - } - if let Some(notification) = last { peer.network.on_block_finalized(notification.hash, notification.header); } } diff --git a/client/service/src/client/client.rs b/client/service/src/client/client.rs index 7673a7b4c538..e8ca5343aa0d 100644 --- a/client/service/src/client/client.rs +++ b/client/service/src/client/client.rs @@ -30,8 +30,8 @@ use rand::Rng; use sc_block_builder::{BlockBuilderApi, BlockBuilderProvider, RecordProof}; use sc_client_api::{ backend::{ - self, apply_aux, BlockImportOperation, ClientImportOperation, Finalizer, ImportSummary, - LockImportRun, NewBlockState, StorageProvider, + self, apply_aux, BlockImportOperation, ClientImportOperation, FinalizeSummary, Finalizer, + ImportSummary, LockImportRun, NewBlockState, StorageProvider, }, client::{ BadBlocks, BlockBackend, BlockImportNotification, BlockOf, BlockchainEvents, ClientInfo, @@ -274,7 +274,7 @@ where let mut op = ClientImportOperation { op: self.backend.begin_operation()?, notify_imported: None, - notify_finalized: Vec::new(), + notify_finalized: None, }; let r = f(&mut op)?; @@ -622,18 +622,6 @@ where None }, }; - // Ensure parent chain is finalized to maintain invariant that - // finality is called sequentially. This will also send finality - // notifications for top 250 newly finalized blocks. - if finalized && parent_exists { - self.apply_finality_with_block_hash( - operation, - parent_hash, - None, - info.best_hash, - make_notifications, - )?; - } operation.op.update_cache(new_cache); storage_changes @@ -641,6 +629,18 @@ where None => None, }; + // Ensure parent chain is finalized to maintain invariant that finality is called + // sequentially. + if finalized && parent_exists { + self.apply_finality_with_block_hash( + operation, + parent_hash, + None, + info.best_hash, + make_notifications, + )?; + } + let is_new_best = !gap_block && (finalized || match fork_choice { @@ -683,11 +683,36 @@ where operation.op.insert_aux(aux)?; - // we only notify when we are already synced to the tip of the chain + // We only notify when we are already synced to the tip of the chain // or if this import triggers a re-org if make_notifications || tree_route.is_some() { if finalized { - operation.notify_finalized.push(hash); + let mut summary = match operation.notify_finalized.take() { + Some(summary) => summary, + None => FinalizeSummary { finalized: Vec::new(), stale_heads: Vec::new() }, + }; + summary.finalized.push(hash); + if parent_exists { + // Add to the stale list all heads that are branching from parent besides our + // current `head`. + for head in self + .backend + .blockchain() + .leaves()? + .into_iter() + .filter(|h| *h != parent_hash) + { + let route_from_parent = sp_blockchain::tree_route( + self.backend.blockchain(), + parent_hash, + head, + )?; + if route_from_parent.retracted().is_empty() { + summary.stale_heads.push(head); + } + } + } + operation.notify_finalized = Some(summary); } operation.notify_imported = Some(ImportSummary { @@ -831,58 +856,82 @@ where operation.op.mark_finalized(BlockId::Hash(block), justification)?; if notify { - // sometimes when syncing, tons of blocks can be finalized at once. - // we'll send notifications spuriously in that case. - const MAX_TO_NOTIFY: usize = 256; - let enacted = route_from_finalized.enacted(); - let start = enacted.len() - std::cmp::min(enacted.len(), MAX_TO_NOTIFY); - for finalized in &enacted[start..] { - operation.notify_finalized.push(finalized.hash); + let finalized = + route_from_finalized.enacted().iter().map(|elem| elem.hash).collect::>(); + + let last_finalized_number = self + .backend + .blockchain() + .number(last_finalized)? + .expect("Finalized block expected to be onchain; qed"); + let mut stale_heads = Vec::new(); + for head in self.backend.blockchain().leaves()? { + let route_from_finalized = + sp_blockchain::tree_route(self.backend.blockchain(), block, head)?; + let retracted = route_from_finalized.retracted(); + let pivot = route_from_finalized.common_block(); + // It is not guaranteed that `backend.blockchain().leaves()` doesn't return + // heads that were in a stale state before this finalization and thus already + // included in previous notifications. We want to skip such heads. + // Given the "route" from the currently finalized block to the head under + // analysis, the condition for it to be added to the new stale heads list is: + // `!retracted.is_empty() && last_finalized_number <= pivot.number` + // 1. "route" has some "retractions". + // 2. previously finalized block number is not greater than the "route" pivot: + // - if `last_finalized_number <= pivot.number` then this is a new stale head; + // - else the stale head was already included by some previous finalization. + if !retracted.is_empty() && last_finalized_number <= pivot.number { + stale_heads.push(head); + } } + operation.notify_finalized = Some(FinalizeSummary { finalized, stale_heads }); } Ok(()) } - fn notify_finalized(&self, notify_finalized: Vec) -> sp_blockchain::Result<()> { + fn notify_finalized( + &self, + notify_finalized: Option>, + ) -> sp_blockchain::Result<()> { let mut sinks = self.finality_notification_sinks.lock(); - if notify_finalized.is_empty() { - // cleanup any closed finality notification sinks - // since we won't be running the loop below which - // would also remove any closed sinks. - sinks.retain(|sink| !sink.is_closed()); - - return Ok(()) - } + let mut notify_finalized = match notify_finalized { + Some(notify_finalized) => notify_finalized, + None => { + // Cleanup any closed finality notification sinks + // since we won't be running the loop below which + // would also remove any closed sinks. + sinks.retain(|sink| !sink.is_closed()); + return Ok(()) + }, + }; - // We assume the list is sorted and only want to inform the - // telemetry once about the finalized block. - if let Some(last) = notify_finalized.last() { - let header = self.header(&BlockId::Hash(*last))?.expect( - "Header already known to exist in DB because it is indicated in the tree route; \ - qed", - ); + let last = notify_finalized.finalized.pop().expect( + "At least one finalized block shall exist within a valid finalization summary; qed", + ); - telemetry!( - self.telemetry; - SUBSTRATE_INFO; - "notify.finalized"; - "height" => format!("{}", header.number()), - "best" => ?last, - ); - } + let header = self.header(&BlockId::Hash(last))?.expect( + "Header already known to exist in DB because it is indicated in the tree route; \ + qed", + ); - for finalized_hash in notify_finalized { - let header = self.header(&BlockId::Hash(finalized_hash))?.expect( - "Header already known to exist in DB because it is indicated in the tree route; \ - qed", - ); + telemetry!( + self.telemetry; + SUBSTRATE_INFO; + "notify.finalized"; + "height" => format!("{}", header.number()), + "best" => ?last, + ); - let notification = FinalityNotification { header, hash: finalized_hash }; + let notification = FinalityNotification { + hash: last, + header, + tree_route: Arc::new(notify_finalized.finalized), + stale_heads: Arc::new(notify_finalized.stale_heads), + }; - sinks.retain(|sink| sink.unbounded_send(notification.clone()).is_ok()); - } + sinks.retain(|sink| sink.unbounded_send(notification.clone()).is_ok()); Ok(()) } @@ -901,7 +950,6 @@ where // temporary leak of closed/discarded notification sinks (e.g. // from consensus code). self.import_notification_sinks.lock().retain(|sink| !sink.is_closed()); - return Ok(()) }, }; diff --git a/client/service/src/lib.rs b/client/service/src/lib.rs index 9710ba9e3d84..430a818c0f47 100644 --- a/client/service/src/lib.rs +++ b/client/service/src/lib.rs @@ -34,10 +34,10 @@ mod client; mod metrics; mod task_manager; -use std::{collections::HashMap, io, net::SocketAddr, pin::Pin, task::Poll}; +use std::{collections::HashMap, io, net::SocketAddr, pin::Pin}; use codec::{Decode, Encode}; -use futures::{stream, Future, FutureExt, Stream, StreamExt}; +use futures::{Future, FutureExt, StreamExt}; use log::{debug, error, warn}; use sc_network::PeerId; use sc_utils::mpsc::TracingUnboundedReceiver; @@ -152,26 +152,7 @@ async fn build_network_future< let starting_block = client.info().best_number; // Stream of finalized blocks reported by the client. - let mut finality_notification_stream = { - let mut finality_notification_stream = client.finality_notification_stream().fuse(); - - // We tweak the `Stream` in order to merge together multiple items if they happen to be - // ready. This way, we only get the latest finalized block. - stream::poll_fn(move |cx| { - let mut last = None; - while let Poll::Ready(Some(item)) = - Pin::new(&mut finality_notification_stream).poll_next(cx) - { - last = Some(item); - } - if let Some(last) = last { - Poll::Ready(Some(last)) - } else { - Poll::Pending - } - }) - .fuse() - }; + let mut finality_notification_stream = client.finality_notification_stream().fuse(); loop { futures::select! { diff --git a/client/service/test/src/client/mod.rs b/client/service/test/src/client/mod.rs index 535edfadaf29..2b0ea460c4dd 100644 --- a/client/service/test/src/client/mod.rs +++ b/client/service/test/src/client/mod.rs @@ -20,7 +20,9 @@ use futures::executor::block_on; use hex_literal::hex; use parity_scale_codec::{Decode, Encode, Joiner}; use sc_block_builder::BlockBuilderProvider; -use sc_client_api::{in_mem, BlockBackend, BlockchainEvents, StorageProvider}; +use sc_client_api::{ + in_mem, BlockBackend, BlockchainEvents, FinalityNotifications, StorageProvider, +}; use sc_client_db::{ Backend, DatabaseSettings, DatabaseSource, KeepBlocks, PruningMode, TransactionStorageMode, }; @@ -165,6 +167,24 @@ fn block1(genesis_hash: Hash, backend: &InMemoryBackend) -> (Vec, + finalized: &[Hash], + stale_heads: &[Hash], +) { + match notifications.try_next() { + Ok(Some(notif)) => { + let stale_heads_expected: HashSet<_> = stale_heads.iter().collect(); + let stale_heads: HashSet<_> = notif.stale_heads.iter().collect(); + assert_eq!(notif.tree_route.as_ref(), &finalized[..finalized.len() - 1]); + assert_eq!(notif.hash, *finalized.last().unwrap()); + assert_eq!(stale_heads, stale_heads_expected); + }, + Ok(None) => panic!("unexpected notification result, client send channel was closed"), + Err(_) => assert!(finalized.is_empty()), + } +} + #[test] fn construct_genesis_should_work_with_native() { let mut storage = GenesisConfig::new( @@ -822,8 +842,12 @@ fn best_containing_on_longest_chain_with_max_depth_higher_than_best() { #[test] fn import_with_justification() { + // block tree: + // G -> A1 -> A2 -> A3 let mut client = substrate_test_runtime_client::new(); + let mut finality_notifications = client.finality_notification_stream(); + // G -> A1 let a1 = client.new_block(Default::default()).unwrap().build().unwrap().block; block_on(client.import(BlockOrigin::Own, a1.clone())).unwrap(); @@ -855,6 +879,10 @@ fn import_with_justification() { assert_eq!(client.justifications(&BlockId::Hash(a1.hash())).unwrap(), None); assert_eq!(client.justifications(&BlockId::Hash(a2.hash())).unwrap(), None); + + finality_notification_check(&mut finality_notifications, &[a1.hash(), a2.hash()], &[]); + finality_notification_check(&mut finality_notifications, &[a3.hash()], &[]); + assert!(finality_notifications.try_next().is_err()); } #[test] @@ -864,6 +892,9 @@ fn importing_diverged_finalized_block_should_trigger_reorg() { // G -> A1 -> A2 // \ // -> B1 + + let mut finality_notifications = client.finality_notification_stream(); + let a1 = client .new_block_at(&BlockId::Number(0), Default::default(), false) .unwrap() @@ -902,6 +933,9 @@ fn importing_diverged_finalized_block_should_trigger_reorg() { assert_eq!(client.chain_info().best_hash, b1.hash()); assert_eq!(client.chain_info().finalized_hash, b1.hash()); + + finality_notification_check(&mut finality_notifications, &[b1.hash()], &[a2.hash()]); + assert!(finality_notifications.try_next().is_err()); } #[test] @@ -911,6 +945,9 @@ fn finalizing_diverged_block_should_trigger_reorg() { // G -> A1 -> A2 // \ // -> B1 -> B2 + + let mut finality_notifications = client.finality_notification_stream(); + let a1 = client .new_block_at(&BlockId::Number(0), Default::default(), false) .unwrap() @@ -975,6 +1012,113 @@ fn finalizing_diverged_block_should_trigger_reorg() { block_on(client.import(BlockOrigin::Own, b3.clone())).unwrap(); assert_eq!(client.chain_info().best_hash, b3.hash()); + + finality_notification_check(&mut finality_notifications, &[b1.hash()], &[a2.hash()]); + assert!(finality_notifications.try_next().is_err()); +} + +#[test] +fn finality_notifications_content() { + let (mut client, _select_chain) = TestClientBuilder::new().build_with_longest_chain(); + + // -> D3 -> D4 + // G -> A1 -> A2 -> A3 + // -> B1 -> B2 + // -> C1 + + let mut finality_notifications = client.finality_notification_stream(); + + let a1 = client + .new_block_at(&BlockId::Number(0), Default::default(), false) + .unwrap() + .build() + .unwrap() + .block; + block_on(client.import(BlockOrigin::Own, a1.clone())).unwrap(); + + let a2 = client + .new_block_at(&BlockId::Hash(a1.hash()), Default::default(), false) + .unwrap() + .build() + .unwrap() + .block; + block_on(client.import(BlockOrigin::Own, a2.clone())).unwrap(); + + let a3 = client + .new_block_at(&BlockId::Hash(a2.hash()), Default::default(), false) + .unwrap() + .build() + .unwrap() + .block; + block_on(client.import(BlockOrigin::Own, a3.clone())).unwrap(); + + let mut b1 = client.new_block_at(&BlockId::Number(0), Default::default(), false).unwrap(); + // needed to make sure B1 gets a different hash from A1 + b1.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 1, + nonce: 0, + }) + .unwrap(); + let b1 = b1.build().unwrap().block; + block_on(client.import(BlockOrigin::Own, b1.clone())).unwrap(); + + let b2 = client + .new_block_at(&BlockId::Hash(b1.hash()), Default::default(), false) + .unwrap() + .build() + .unwrap() + .block; + block_on(client.import(BlockOrigin::Own, b2.clone())).unwrap(); + + let mut c1 = client.new_block_at(&BlockId::Number(0), Default::default(), false).unwrap(); + // needed to make sure B1 gets a different hash from A1 + c1.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 2, + nonce: 0, + }) + .unwrap(); + let c1 = c1.build().unwrap().block; + block_on(client.import(BlockOrigin::Own, c1.clone())).unwrap(); + + let mut d3 = client + .new_block_at(&BlockId::Hash(a2.hash()), Default::default(), false) + .unwrap(); + // needed to make sure D3 gets a different hash from A3 + d3.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 2, + nonce: 0, + }) + .unwrap(); + let d3 = d3.build().unwrap().block; + block_on(client.import(BlockOrigin::Own, d3.clone())).unwrap(); + + let d4 = client + .new_block_at(&BlockId::Hash(d3.hash()), Default::default(), false) + .unwrap() + .build() + .unwrap() + .block; + + // Postpone import to test behavior of import of finalized block. + + ClientExt::finalize_block(&client, BlockId::Hash(a2.hash()), None).unwrap(); + + // Import and finalize D4 + block_on(client.import_as_final(BlockOrigin::Own, d4.clone())).unwrap(); + + finality_notification_check( + &mut finality_notifications, + &[a1.hash(), a2.hash()], + &[c1.hash(), b2.hash()], + ); + finality_notification_check(&mut finality_notifications, &[d3.hash(), d4.hash()], &[a3.hash()]); + assert!(finality_notifications.try_next().is_err()); } #[test] @@ -1069,6 +1213,8 @@ fn doesnt_import_blocks_that_revert_finality() { let mut client = TestClientBuilder::with_backend(backend).build(); + let mut finality_notifications = client.finality_notification_stream(); + // -> C1 // / // G -> A1 -> A2 @@ -1150,6 +1296,9 @@ fn doesnt_import_blocks_that_revert_finality() { ConsensusError::ClientImport(sp_blockchain::Error::NotInFinalizedChain.to_string()); assert_eq!(import_err.to_string(), expected_err.to_string()); + + finality_notification_check(&mut finality_notifications, &[a1.hash(), a2.hash()], &[b2.hash()]); + assert!(finality_notifications.try_next().is_err()); } #[test] diff --git a/client/transaction-pool/api/src/lib.rs b/client/transaction-pool/api/src/lib.rs index f19a994b1b94..757674a03e85 100644 --- a/client/transaction-pool/api/src/lib.rs +++ b/client/transaction-pool/api/src/lib.rs @@ -278,7 +278,7 @@ impl ReadyTransactions for std::iter::Empty { /// Events that the transaction pool listens for. pub enum ChainEvent { - /// New best block have been added to the chain + /// New best block have been added to the chain. NewBestBlock { /// Hash of the block. hash: B::Hash, @@ -289,8 +289,10 @@ pub enum ChainEvent { }, /// An existing block has been finalized. Finalized { - /// Hash of just finalized block + /// Hash of just finalized block. hash: B::Hash, + /// Path from old finalized to new finalized parent. + tree_route: Arc>, }, } diff --git a/client/transaction-pool/src/lib.rs b/client/transaction-pool/src/lib.rs index b5af2d12d65c..260d938217ad 100644 --- a/client/transaction-pool/src/lib.rs +++ b/client/transaction-pool/src/lib.rs @@ -709,15 +709,17 @@ where } .boxed() }, - ChainEvent::Finalized { hash } => { + ChainEvent::Finalized { hash, tree_route } => { let pool = self.pool.clone(); async move { - if let Err(e) = pool.validated_pool().on_block_finalized(hash).await { - log::warn!( - target: "txpool", - "Error [{}] occurred while attempting to notify watchers of finalization {}", - e, hash - ) + for hash in tree_route.iter().chain(&[hash]) { + if let Err(e) = pool.validated_pool().on_block_finalized(*hash).await { + log::warn!( + target: "txpool", + "Error [{}] occurred while attempting to notify watchers of finalization {}", + e, hash + ) + } } } .boxed() diff --git a/client/transaction-pool/tests/pool.rs b/client/transaction-pool/tests/pool.rs index 4aeaf79a6154..21a87f6e006e 100644 --- a/client/transaction-pool/tests/pool.rs +++ b/client/transaction-pool/tests/pool.rs @@ -387,7 +387,7 @@ fn should_push_watchers_during_maintenance() { let header_hash = header.hash(); block_on(pool.maintain(block_event(header))); - let event = ChainEvent::Finalized { hash: header_hash.clone() }; + let event = ChainEvent::Finalized { hash: header_hash.clone(), tree_route: Arc::new(vec![]) }; block_on(pool.maintain(event)); // then @@ -445,7 +445,7 @@ fn finalization() { let event = ChainEvent::NewBestBlock { hash: header.hash(), tree_route: None }; block_on(pool.maintain(event)); - let event = ChainEvent::Finalized { hash: header.hash() }; + let event = ChainEvent::Finalized { hash: header.hash(), tree_route: Arc::new(vec![]) }; block_on(pool.maintain(event)); let mut stream = futures::executor::block_on_stream(watcher); @@ -493,7 +493,7 @@ fn fork_aware_finalization() { b1 = header.hash(); block_on(pool.maintain(event)); assert_eq!(pool.status().ready, 0); - let event = ChainEvent::Finalized { hash: b1 }; + let event = ChainEvent::Finalized { hash: b1, tree_route: Arc::new(vec![]) }; block_on(pool.maintain(event)); } @@ -537,7 +537,7 @@ fn fork_aware_finalization() { block_on(pool.maintain(event)); assert_eq!(pool.status().ready, 2); - let event = ChainEvent::Finalized { hash: header.hash() }; + let event = ChainEvent::Finalized { hash: header.hash(), tree_route: Arc::new(vec![]) }; block_on(pool.maintain(event)); } @@ -554,7 +554,7 @@ fn fork_aware_finalization() { d1 = header.hash(); block_on(pool.maintain(event)); assert_eq!(pool.status().ready, 2); - let event = ChainEvent::Finalized { hash: d1 }; + let event = ChainEvent::Finalized { hash: d1, tree_route: Arc::new(vec![]) }; block_on(pool.maintain(event)); } @@ -567,7 +567,7 @@ fn fork_aware_finalization() { let event = ChainEvent::NewBestBlock { hash: header.hash(), tree_route: None }; block_on(pool.maintain(event)); assert_eq!(pool.status().ready, 0); - block_on(pool.maintain(ChainEvent::Finalized { hash: e1 })); + block_on(pool.maintain(ChainEvent::Finalized { hash: e1, tree_route: Arc::new(vec![]) })); } for (canon_watcher, h) in canon_watchers { @@ -637,7 +637,7 @@ fn prune_and_retract_tx_at_same_time() { block_on(pool.maintain(event)); assert_eq!(pool.status().ready, 0); - let event = ChainEvent::Finalized { hash: header.hash() }; + let event = ChainEvent::Finalized { hash: header.hash(), tree_route: Arc::new(vec![]) }; block_on(pool.maintain(event)); header.hash() From 8c3992521c135b8c07e5ec767bbcfabdcc06e090 Mon Sep 17 00:00:00 2001 From: Niklas Adolfsson Date: Fri, 28 Jan 2022 10:04:52 +0100 Subject: [PATCH 432/695] remote ext: make it possible to use an existing ws connection (#10737) * remote ext: make it possible to pass ws client * grumbles: introduce `map_uri` --- Cargo.lock | 216 +++++++++++++++--- utils/frame/remote-externalities/Cargo.toml | 2 +- utils/frame/remote-externalities/src/lib.rs | 70 ++++-- .../frame/remote-externalities/src/rpc_api.rs | 4 +- 4 files changed, 232 insertions(+), 60 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0dbafc147f6b..b57f06c50ed2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1438,7 +1438,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1a816186fa68d9e426e3cb4ae4dff1fcd8e4a2c34b781bf7a822574a0d0aac8" dependencies = [ - "sct", + "sct 0.6.0", ] [[package]] @@ -2425,8 +2425,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a1387e07917c711fb4ee4f48ea0adb04a3c9739e53ef85bf43ae1edc2937a8b" dependencies = [ "futures-io", - "rustls", - "webpki", + "rustls 0.19.1", + "webpki 0.21.4", ] [[package]] @@ -2874,11 +2874,11 @@ dependencies = [ "futures-util", "hyper 0.14.16", "log 0.4.14", - "rustls", - "rustls-native-certs", + "rustls 0.19.1", + "rustls-native-certs 0.5.0", "tokio", - "tokio-rustls", - "webpki", + "tokio-rustls 0.22.0", + "webpki 0.21.4", ] [[package]] @@ -3240,19 +3240,73 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6373a33d987866ccfe1af4bc11b089dce941764313f9fd8b7cf13fcb51b72dc5" dependencies = [ - "jsonrpsee-proc-macros", - "jsonrpsee-types", + "jsonrpsee-types 0.4.1", "jsonrpsee-utils", - "jsonrpsee-ws-client", + "jsonrpsee-ws-client 0.4.1", +] + +[[package]] +name = "jsonrpsee" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05fd8cd6c6b1bbd06881d2cf88f1fc83cc36c98f2219090f839115fb4a956cb9" +dependencies = [ + "jsonrpsee-core", + "jsonrpsee-proc-macros", + "jsonrpsee-types 0.8.0", + "jsonrpsee-ws-client 0.8.0", +] + +[[package]] +name = "jsonrpsee-client-transport" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3303cdf246e6ab76e2866fb3d9acb6c76a068b1b28bd923a1b7a8122257ad7b5" +dependencies = [ + "futures 0.3.16", + "http", + "jsonrpsee-core", + "jsonrpsee-types 0.8.0", + "pin-project 1.0.10", + "rustls-native-certs 0.6.1", + "soketto 0.7.1", + "thiserror", + "tokio", + "tokio-rustls 0.23.2", + "tokio-util", + "tracing", + "webpki-roots 0.22.2", +] + +[[package]] +name = "jsonrpsee-core" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f220b5a238dc7992b90f1144fbf6eaa585872c9376afe6fe6863ffead6191bf3" +dependencies = [ + "anyhow", + "arrayvec 0.7.1", + "async-trait", + "beef", + "futures-channel", + "futures-util", + "hyper 0.14.16", + "jsonrpsee-types 0.8.0", + "rustc-hash", + "serde", + "serde_json", + "soketto 0.7.1", + "thiserror", + "tokio", + "tracing", ] [[package]] name = "jsonrpsee-proc-macros" -version = "0.4.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d802063f7a3c867456955f9d2f15eb3ee0edb5ec9ec2b5526324756759221c0f" +checksum = "4299ebf790ea9de1cb72e73ff2ae44c723ef264299e5e2d5ef46a371eb3ac3d8" dependencies = [ - "log 0.4.14", "proc-macro-crate 1.1.0", "proc-macro2", "quote", @@ -3274,10 +3328,24 @@ dependencies = [ "log 0.4.14", "serde", "serde_json", - "soketto 0.7.0", + "soketto 0.7.1", "thiserror", ] +[[package]] +name = "jsonrpsee-types" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1b3f601bbbe45cd63f5407b6f7d7950e08a7d4f82aa699ff41a4a5e9e54df58" +dependencies = [ + "anyhow", + "beef", + "serde", + "serde_json", + "thiserror", + "tracing", +] + [[package]] name = "jsonrpsee-utils" version = "0.4.1" @@ -3286,7 +3354,7 @@ checksum = "0109c4f972058f3b1925b73a17210aff7b63b65967264d0045d15ee88fe84f0c" dependencies = [ "arrayvec 0.7.1", "beef", - "jsonrpsee-types", + "jsonrpsee-types 0.4.1", ] [[package]] @@ -3300,19 +3368,30 @@ dependencies = [ "fnv", "futures 0.3.16", "http", - "jsonrpsee-types", + "jsonrpsee-types 0.4.1", "log 0.4.14", "pin-project 1.0.10", - "rustls-native-certs", + "rustls-native-certs 0.5.0", "serde", "serde_json", - "soketto 0.7.0", + "soketto 0.7.1", "thiserror", "tokio", - "tokio-rustls", + "tokio-rustls 0.22.0", "tokio-util", ] +[[package]] +name = "jsonrpsee-ws-client" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aff425cee7c779e33920913bc695447416078ee6d119f443f3060feffa4e86b5" +dependencies = [ + "jsonrpsee-client-transport", + "jsonrpsee-core", + "jsonrpsee-types 0.8.0", +] + [[package]] name = "keccak" version = "0.1.0" @@ -3920,9 +3999,9 @@ dependencies = [ "log 0.4.14", "quicksink", "rw-stream-sink", - "soketto 0.7.0", + "soketto 0.7.1", "url 2.2.1", - "webpki-roots", + "webpki-roots 0.21.0", ] [[package]] @@ -4602,7 +4681,7 @@ dependencies = [ "frame-system-rpc-runtime-api", "futures 0.3.16", "hex-literal", - "jsonrpsee-ws-client", + "jsonrpsee-ws-client 0.4.1", "log 0.4.14", "nix", "node-executor", @@ -7427,7 +7506,7 @@ version = "0.10.0-dev" dependencies = [ "env_logger 0.9.0", "frame-support", - "jsonrpsee", + "jsonrpsee 0.8.0", "log 0.4.14", "pallet-elections-phragmen", "parity-scale-codec", @@ -7559,8 +7638,20 @@ dependencies = [ "base64 0.13.0", "log 0.4.14", "ring", - "sct", - "webpki", + "sct 0.6.0", + "webpki 0.21.4", +] + +[[package]] +name = "rustls" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d37e5e2290f3e040b594b1a9e04377c2c671f1a1cfd9bfdef82106ac1c113f84" +dependencies = [ + "log 0.4.14", + "ring", + "sct 0.7.0", + "webpki 0.22.0", ] [[package]] @@ -7570,11 +7661,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a07b7c1885bd8ed3831c289b7870b13ef46fe0e856d288c30d9cc17d75a2092" dependencies = [ "openssl-probe", - "rustls", + "rustls 0.19.1", "schannel", "security-framework", ] +[[package]] +name = "rustls-native-certs" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca9ebdfa27d3fc180e42879037b5338ab1c040c06affd00d8338598e7800943" +dependencies = [ + "openssl-probe", + "rustls-pemfile", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pemfile" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eebeaeb360c87bfb72e84abdb3447159c0eaececf1bef2aecd65a8be949d1c9" +dependencies = [ + "base64 0.13.0", +] + [[package]] name = "rustversion" version = "1.0.6" @@ -8855,6 +8967,16 @@ dependencies = [ "untrusted", ] +[[package]] +name = "sct" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "secrecy" version = "0.8.0" @@ -9202,9 +9324,9 @@ dependencies = [ [[package]] name = "soketto" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "083624472e8817d44d02c0e55df043737ff11f279af924abdf93845717c2b75c" +checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2" dependencies = [ "base64 0.13.0", "bytes 1.1.0", @@ -10647,9 +10769,20 @@ version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6" dependencies = [ - "rustls", + "rustls 0.19.1", + "tokio", + "webpki 0.21.4", +] + +[[package]] +name = "tokio-rustls" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a27d5f2b839802bd8267fa19b0530f5a08b9c08cd417976be2a65d130fe1c11b" +dependencies = [ + "rustls 0.20.2", "tokio", - "webpki", + "webpki 0.22.0", ] [[package]] @@ -10941,7 +11074,7 @@ name = "try-runtime-cli" version = "0.10.0-dev" dependencies = [ "clap 3.0.7", - "jsonrpsee", + "jsonrpsee 0.4.1", "log 0.4.14", "parity-scale-codec", "remote-externalities", @@ -11755,13 +11888,32 @@ dependencies = [ "untrusted", ] +[[package]] +name = "webpki" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "webpki-roots" version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "82015b7e0b8bad8185994674a13a93306bea76cf5a16c5a181382fd3a5ec2376" dependencies = [ - "webpki", + "webpki 0.21.4", +] + +[[package]] +name = "webpki-roots" +version = "0.22.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552ceb903e957524388c4d3475725ff2c8b7960922063af6ce53c9a43da07449" +dependencies = [ + "webpki 0.22.0", ] [[package]] diff --git a/utils/frame/remote-externalities/Cargo.toml b/utils/frame/remote-externalities/Cargo.toml index 6d926846b4a3..9e0b17a7b58f 100644 --- a/utils/frame/remote-externalities/Cargo.toml +++ b/utils/frame/remote-externalities/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -jsonrpsee = { version = "0.4.1", features = ["ws-client", "macros"] } +jsonrpsee = { version = "0.8", features = ["ws-client", "macros"] } env_logger = "0.9" frame-support = { path = "../../../frame/support", optional = true, version = "4.0.0-dev" } diff --git a/utils/frame/remote-externalities/src/lib.rs b/utils/frame/remote-externalities/src/lib.rs index 16aa60db1841..d6dfd1c59d4e 100644 --- a/utils/frame/remote-externalities/src/lib.rs +++ b/utils/frame/remote-externalities/src/lib.rs @@ -23,9 +23,9 @@ use codec::{Decode, Encode}; use jsonrpsee::{ + core::{client::ClientT, Error as RpcError}, proc_macros::rpc, rpc_params, - types::{traits::Client, Error as RpcError}, ws_client::{WsClient, WsClientBuilder}, }; @@ -44,6 +44,7 @@ use sp_runtime::traits::Block as BlockT; use std::{ fs, path::{Path, PathBuf}, + sync::Arc, }; pub mod rpc_api; @@ -123,21 +124,52 @@ impl> From

l*E$vGr!b0mzpPvxmv|Kn@YID>qCb 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

V_ga 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

`Dr66(fQTy| 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

6{u>RgkeeoM-jy+Hb*aa*^iCl~@))V-T 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 Result<(), WasmError> { + let import_section = match self.raw_module.import_section_mut() { + Some(import_section) => import_section, + None => return Ok(()), + }; + + let import_entries = import_section.entries_mut(); + for index in 0..import_entries.len() { + let entry = &import_entries[index]; + let memory_ty = match entry.external() { + External::Memory(memory_ty) => *memory_ty, + _ => continue, + }; + + let memory_name = entry.field().to_owned(); + import_entries.remove(index); + + self.raw_module + .insert_section(Section::Memory(MemorySection::with_entries(vec![memory_ty]))) + .map_err(|error| { + WasmError::Other(format!( + "can't convert a memory import into an export: failed to insert a new memory section: {}", + error + )) + })?; + + if self.raw_module.export_section_mut().is_none() { + // A module without an export section is somewhat unrealistic, but let's do this + // just in case to cover all of our bases. + self.raw_module + .insert_section(Section::Export(Default::default())) + .expect("an export section can be always inserted if it doesn't exist; qed"); + } + self.raw_module + .export_section_mut() + .expect("export section already existed or we just added it above, so it always exists; qed") + .entries_mut() + .push(ExportEntry::new(memory_name, Internal::Memory(0))); + + break + } + + Ok(()) + } + + /// Increases the number of memory pages requested by the WASM blob by + /// the given amount of `extra_heap_pages`. + /// + /// Will return an error in case there is no memory section present, + /// or if the memory section is empty. + /// + /// Only modifies the initial size of the memory; the maximum is unmodified + /// unless it's smaller than the initial size, in which case it will be increased + /// so that it's at least as big as the initial size. + pub fn add_extra_heap_pages_to_memory_section( + &mut self, + extra_heap_pages: u32, + ) -> Result<(), WasmError> { + let memory_section = self + .raw_module + .memory_section_mut() + .ok_or_else(|| WasmError::Other("no memory section found".into()))?; + + if memory_section.entries().is_empty() { + return Err(WasmError::Other("memory section is empty".into())) + } + for memory_ty in memory_section.entries_mut() { + let min = memory_ty.limits().initial().saturating_add(extra_heap_pages); + let max = memory_ty.limits().maximum().map(|max| std::cmp::max(min, max)); + *memory_ty = MemoryType::new(min, max); + } + Ok(()) + } + /// Returns an iterator of all globals which were exported by [`expose_mutable_globals`]. pub(super) fn exported_internal_global_names<'module>( &'module self, diff --git a/client/executor/wasmtime/src/imports.rs b/client/executor/wasmtime/src/imports.rs index 636a5761c947..4aad57102931 100644 --- a/client/executor/wasmtime/src/imports.rs +++ b/client/executor/wasmtime/src/imports.rs @@ -16,37 +16,24 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use crate::{ - host::HostContext, - runtime::{Store, StoreData}, -}; +use crate::{host::HostContext, runtime::StoreData}; use sc_executor_common::error::WasmError; use sp_wasm_interface::{FunctionContext, HostFunctions}; -use std::{collections::HashMap, convert::TryInto}; -use wasmtime::{Extern, ExternType, Func, FuncType, ImportType, Memory, MemoryType, Module, Trap}; - -pub struct Imports { - /// Contains the index into `externs` where the memory import is stored if any. `None` if there - /// is none. - pub memory_import_index: Option, - pub externs: Vec, -} +use std::collections::HashMap; +use wasmtime::{ExternType, FuncType, ImportType, Linker, Module, Trap}; -/// Goes over all imports of a module and prepares a vector of `Extern`s that can be used for -/// instantiation of the module. Returns an error if there are imports that cannot be satisfied. -pub(crate) fn resolve_imports( - store: &mut Store, +/// Goes over all imports of a module and prepares the given linker for instantiation of the module. +/// Returns an error if there are imports that cannot be satisfied. +pub(crate) fn prepare_imports( + linker: &mut Linker, module: &Module, - heap_pages: u64, allow_missing_func_imports: bool, -) -> Result +) -> Result<(), WasmError> where H: HostFunctions, { - let mut externs = vec![]; - let mut memory_import_index = None; let mut pending_func_imports = HashMap::new(); - for (index, import_ty) in module.imports().enumerate() { + for import_ty in module.imports() { let name = import_name(&import_ty)?; if import_ty.module() != "env" { @@ -57,41 +44,36 @@ where ))) } - if name == "memory" { - memory_import_index = Some(index); - externs.push((index, resolve_memory_import(store, &import_ty, heap_pages)?)); - continue - } - match import_ty.ty() { ExternType::Func(func_ty) => { - pending_func_imports.insert(name.to_owned(), (index, import_ty, func_ty)); + pending_func_imports.insert(name.to_owned(), (import_ty, func_ty)); }, _ => return Err(WasmError::Other(format!( - "host doesn't provide any non function imports besides 'memory': {}:{}", + "host doesn't provide any non function imports: {}:{}", import_ty.module(), name, ))), }; } - let mut registry = Registry { store, externs, pending_func_imports }; - + let mut registry = Registry { linker, pending_func_imports }; H::register_static(&mut registry)?; - let mut externs = registry.externs; if !registry.pending_func_imports.is_empty() { if allow_missing_func_imports { - for (_, (index, import_ty, func_ty)) in registry.pending_func_imports { - externs.push(( - index, - MissingHostFuncHandler::new(&import_ty)?.into_extern(store, &func_ty), - )); + for (name, (import_ty, func_ty)) in registry.pending_func_imports { + let error = format!("call to a missing function {}:{}", import_ty.module(), name); + log::debug!("Missing import: '{}' {:?}", name, func_ty); + linker + .func_new("env", &name, func_ty.clone(), move |_, _, _| { + Err(Trap::new(error.clone())) + }) + .expect("adding a missing import stub can only fail when the item already exists, and it is missing here; qed"); } } else { let mut names = Vec::new(); - for (name, (_, import_ty, _)) in registry.pending_func_imports { + for (name, (import_ty, _)) in registry.pending_func_imports { names.push(format!("'{}:{}'", import_ty.module(), name)); } let names = names.join(", "); @@ -102,16 +84,12 @@ where } } - externs.sort_unstable_by_key(|&(index, _)| index); - let externs = externs.into_iter().map(|(_, ext)| ext).collect(); - - Ok(Imports { memory_import_index, externs }) + Ok(()) } struct Registry<'a, 'b> { - store: &'a mut Store, - externs: Vec<(usize, Extern)>, - pending_func_imports: HashMap, FuncType)>, + linker: &'a mut Linker, + pending_func_imports: HashMap, FuncType)>, } impl<'a, 'b> sp_wasm_interface::HostFunctionRegistry for Registry<'a, 'b> { @@ -131,9 +109,13 @@ impl<'a, 'b> sp_wasm_interface::HostFunctionRegistry for Registry<'a, 'b> { fn_name: &str, func: impl wasmtime::IntoFunc, ) -> Result<(), Self::Error> { - if let Some((index, _, _)) = self.pending_func_imports.remove(fn_name) { - let func = Func::wrap(&mut *self.store, func); - self.externs.push((index, Extern::Func(func))); + if self.pending_func_imports.remove(fn_name).is_some() { + self.linker.func_wrap("env", fn_name, func).map_err(|error| { + WasmError::Other(format!( + "failed to register host function '{}' with the WASM linker: {}", + fn_name, error + )) + })?; } Ok(()) @@ -149,85 +131,3 @@ fn import_name<'a, 'b: 'a>(import: &'a ImportType<'b>) -> Result<&'a str, WasmEr })?; Ok(name) } - -fn resolve_memory_import( - store: &mut Store, - import_ty: &ImportType, - heap_pages: u64, -) -> Result { - let requested_memory_ty = match import_ty.ty() { - ExternType::Memory(memory_ty) => memory_ty, - _ => - return Err(WasmError::Other(format!( - "this import must be of memory type: {}:{}", - import_ty.module(), - import_name(&import_ty)?, - ))), - }; - - // Increment the min (a.k.a initial) number of pages by `heap_pages` and check if it exceeds the - // maximum specified by the import. - let initial = requested_memory_ty.minimum().saturating_add(heap_pages); - if let Some(max) = requested_memory_ty.maximum() { - if initial > max { - return Err(WasmError::Other(format!( - "incremented number of pages by heap_pages (total={}) is more than maximum requested\ - by the runtime wasm module {}", - initial, - max, - ))) - } - } - - // Note that the return value of `maximum` and `minimum`, while a u64, - // will always fit into a u32 for 32-bit memories. - // 64-bit memories are part of the memory64 proposal for WebAssembly which is not standardized - // yet. - let minimum: u32 = initial.try_into().map_err(|_| { - WasmError::Other(format!( - "minimum number of memory pages ({}) doesn't fit into u32", - initial - )) - })?; - let maximum: Option = match requested_memory_ty.maximum() { - Some(max) => Some(max.try_into().map_err(|_| { - WasmError::Other(format!( - "maximum number of memory pages ({}) doesn't fit into u32", - max - )) - })?), - None => None, - }; - - let memory_ty = MemoryType::new(minimum, maximum); - let memory = Memory::new(store, memory_ty).map_err(|e| { - WasmError::Other(format!( - "failed to create a memory during resolving of memory import: {}", - e, - )) - })?; - Ok(Extern::Memory(memory)) -} - -/// A `Callable` handler for missing functions. -struct MissingHostFuncHandler { - module: String, - name: String, -} - -impl MissingHostFuncHandler { - fn new(import_ty: &ImportType) -> Result { - Ok(Self { - module: import_ty.module().to_string(), - name: import_name(import_ty)?.to_string(), - }) - } - - fn into_extern(self, store: &mut Store, func_ty: &FuncType) -> Extern { - let Self { module, name } = self; - let func = Func::new(store, func_ty.clone(), move |_, _, _| { - Err(Trap::new(format!("call to a missing function {}:{}", module, name))) - }); - Extern::Func(func) - } -} diff --git a/client/executor/wasmtime/src/instance_wrapper.rs b/client/executor/wasmtime/src/instance_wrapper.rs index 896b71cea21d..6abcbca1bba6 100644 --- a/client/executor/wasmtime/src/instance_wrapper.rs +++ b/client/executor/wasmtime/src/instance_wrapper.rs @@ -21,12 +21,13 @@ use crate::runtime::{Store, StoreData}; use sc_executor_common::{ - error::{Backtrace, Error, MessageWithBacktrace, Result}, + error::{Backtrace, Error, MessageWithBacktrace, Result, WasmError}, wasm_runtime::InvokeMethod, }; -use sp_wasm_interface::{HostFunctions, Pointer, Value, WordSize}; +use sp_wasm_interface::{Pointer, Value, WordSize}; use wasmtime::{ - AsContext, AsContextMut, Extern, Func, Global, Instance, Memory, Module, Table, Val, + AsContext, AsContextMut, Engine, Extern, Func, Global, Instance, InstancePre, Memory, Table, + Val, }; /// Invoked entrypoint format. @@ -162,62 +163,41 @@ fn extern_func(extern_: &Extern) -> Option<&Func> { } } +pub(crate) fn create_store(engine: &wasmtime::Engine, max_memory_size: Option) -> Store { + let limits = if let Some(max_memory_size) = max_memory_size { + wasmtime::StoreLimitsBuilder::new().memory_size(max_memory_size).build() + } else { + Default::default() + }; + + let mut store = + Store::new(engine, StoreData { limits, host_state: None, memory: None, table: None }); + if max_memory_size.is_some() { + store.limiter(|s| &mut s.limits); + } + store +} + impl InstanceWrapper { - /// Create a new instance wrapper from the given wasm module. - pub fn new( - module: &Module, - heap_pages: u64, - allow_missing_func_imports: bool, + pub(crate) fn new( + engine: &Engine, + instance_pre: &InstancePre, max_memory_size: Option, - ) -> Result - where - H: HostFunctions, - { - let limits = if let Some(max_memory_size) = max_memory_size { - wasmtime::StoreLimitsBuilder::new().memory_size(max_memory_size).build() - } else { - Default::default() - }; - - let mut store = Store::new( - module.engine(), - StoreData { limits, host_state: None, memory: None, table: None }, - ); - if max_memory_size.is_some() { - store.limiter(|s| &mut s.limits); - } - - // Scan all imports, find the matching host functions, and create stubs that adapt arguments - // and results. - let imports = crate::imports::resolve_imports::( - &mut store, - module, - heap_pages, - allow_missing_func_imports, - )?; - - let instance = Instance::new(&mut store, module, &imports.externs) - .map_err(|e| Error::from(format!("cannot instantiate: {}", e)))?; - - let memory = match imports.memory_import_index { - Some(memory_idx) => extern_memory(&imports.externs[memory_idx]) - .expect("only memory can be at the `memory_idx`; qed") - .clone(), - None => { - let memory = get_linear_memory(&instance, &mut store)?; - if !memory.grow(&mut store, heap_pages).is_ok() { - return Err("failed top increase the linear memory size".into()) - } - memory - }, - }; - + ) -> Result { + let mut store = create_store(engine, max_memory_size); + let instance = instance_pre.instantiate(&mut store).map_err(|error| { + WasmError::Other( + format!("failed to instantiate a new WASM module instance: {}", error,), + ) + })?; + + let memory = get_linear_memory(&instance, &mut store)?; let table = get_table(&instance, &mut store); store.data_mut().memory = Some(memory); store.data_mut().table = table; - Ok(Self { instance, memory, store }) + Ok(InstanceWrapper { instance, memory, store }) } /// Resolves a substrate entrypoint by the given name. @@ -435,8 +415,11 @@ impl InstanceWrapper { fn decommit_works() { let engine = wasmtime::Engine::default(); let code = wat::parse_str("(module (memory (export \"memory\") 1 4))").unwrap(); - let module = Module::new(&engine, code).unwrap(); - let mut wrapper = InstanceWrapper::new::<()>(&module, 2, true, None).unwrap(); + let module = wasmtime::Module::new(&engine, code).unwrap(); + let linker = wasmtime::Linker::new(&engine); + let mut store = create_store(&engine, None); + let instance_pre = linker.instantiate_pre(&mut store, &module).unwrap(); + let mut wrapper = InstanceWrapper::new(&engine, &instance_pre, None).unwrap(); unsafe { *wrapper.memory.data_ptr(&wrapper.store) = 42 }; assert_eq!(unsafe { *wrapper.memory.data_ptr(&wrapper.store) }, 42); wrapper.decommit(); diff --git a/client/executor/wasmtime/src/runtime.rs b/client/executor/wasmtime/src/runtime.rs index 6533aa194e4c..acf54e04e07f 100644 --- a/client/executor/wasmtime/src/runtime.rs +++ b/client/executor/wasmtime/src/runtime.rs @@ -23,7 +23,6 @@ use crate::{ instance_wrapper::{EntryPoint, InstanceWrapper}, util, }; -use core::marker::PhantomData; use sc_allocator::FreeingBumpHeapAllocator; use sc_executor_common::{ @@ -80,35 +79,25 @@ impl StoreData { pub(crate) type Store = wasmtime::Store; -enum Strategy { +enum Strategy { FastInstanceReuse { instance_wrapper: InstanceWrapper, globals_snapshot: GlobalsSnapshot, data_segments_snapshot: Arc, heap_base: u32, }, - RecreateInstance(InstanceCreator), + RecreateInstance(InstanceCreator), } -struct InstanceCreator { - module: Arc, - heap_pages: u64, - allow_missing_func_imports: bool, +struct InstanceCreator { + engine: wasmtime::Engine, + instance_pre: Arc>, max_memory_size: Option, - phantom: PhantomData, } -impl InstanceCreator -where - H: HostFunctions, -{ +impl InstanceCreator { fn instantiate(&mut self) -> Result { - InstanceWrapper::new::( - &*self.module, - self.heap_pages, - self.allow_missing_func_imports, - self.max_memory_size, - ) + InstanceWrapper::new(&self.engine, &self.instance_pre, self.max_memory_size) } } @@ -144,23 +133,19 @@ struct InstanceSnapshotData { /// A `WasmModule` implementation using wasmtime to compile the runtime module to machine code /// and execute the compiled code. -pub struct WasmtimeRuntime { - module: Arc, +pub struct WasmtimeRuntime { + engine: wasmtime::Engine, + instance_pre: Arc>, snapshot_data: Option, config: Config, - phantom: PhantomData, } -impl WasmModule for WasmtimeRuntime -where - H: HostFunctions, -{ +impl WasmModule for WasmtimeRuntime { fn new_instance(&self) -> Result> { let strategy = if let Some(ref snapshot_data) = self.snapshot_data { - let mut instance_wrapper = InstanceWrapper::new::( - &self.module, - self.config.heap_pages, - self.config.allow_missing_func_imports, + let mut instance_wrapper = InstanceWrapper::new( + &self.engine, + &self.instance_pre, self.config.max_memory_size, )?; let heap_base = instance_wrapper.extract_heap_base()?; @@ -174,19 +159,17 @@ where &mut InstanceGlobals { instance: &mut instance_wrapper }, ); - Strategy::::FastInstanceReuse { + Strategy::FastInstanceReuse { instance_wrapper, globals_snapshot, data_segments_snapshot: snapshot_data.data_segments_snapshot.clone(), heap_base, } } else { - Strategy::::RecreateInstance(InstanceCreator { - module: self.module.clone(), - heap_pages: self.config.heap_pages, - allow_missing_func_imports: self.config.allow_missing_func_imports, + Strategy::RecreateInstance(InstanceCreator { + engine: self.engine.clone(), + instance_pre: self.instance_pre.clone(), max_memory_size: self.config.max_memory_size, - phantom: PhantomData, }) }; @@ -196,14 +179,11 @@ where /// A `WasmInstance` implementation that reuses compiled module and spawns instances /// to execute the compiled code. -pub struct WasmtimeInstance { - strategy: Strategy, +pub struct WasmtimeInstance { + strategy: Strategy, } -impl WasmInstance for WasmtimeInstance -where - H: HostFunctions, -{ +impl WasmInstance for WasmtimeInstance { fn call(&mut self, method: InvokeMethod, data: &[u8]) -> Result> { match &mut self.strategy { Strategy::FastInstanceReuse { @@ -498,7 +478,7 @@ enum CodeSupplyMode<'a> { pub fn create_runtime( blob: RuntimeBlob, config: Config, -) -> std::result::Result, WasmError> +) -> std::result::Result where H: HostFunctions, { @@ -520,7 +500,7 @@ where pub unsafe fn create_runtime_from_artifact( compiled_artifact: &[u8], config: Config, -) -> std::result::Result, WasmError> +) -> std::result::Result where H: HostFunctions, { @@ -534,7 +514,7 @@ where unsafe fn do_create_runtime( code_supply_mode: CodeSupplyMode<'_>, config: Config, -) -> std::result::Result, WasmError> +) -> std::result::Result where H: HostFunctions, { @@ -550,27 +530,39 @@ where } let engine = Engine::new(&wasmtime_config) - .map_err(|e| WasmError::Other(format!("cannot create the engine for runtime: {}", e)))?; + .map_err(|e| WasmError::Other(format!("cannot create the wasmtime engine: {}", e)))?; let (module, snapshot_data) = match code_supply_mode { CodeSupplyMode::Verbatim { blob } => { - let blob = instrument(blob, &config.semantics)?; + let mut blob = instrument(blob, &config.semantics)?; + + // We don't actually need the memory to be imported so we can just convert any memory + // import into an export with impunity. This simplifies our code since `wasmtime` will + // now automatically take care of creating the memory for us, and it also allows us + // to potentially enable `wasmtime`'s instance pooling at a later date. (Imported + // memories are ineligible for pooling.) + blob.convert_memory_import_into_export()?; + blob.add_extra_heap_pages_to_memory_section( + config + .heap_pages + .try_into() + .map_err(|e| WasmError::Other(format!("invalid `heap_pages`: {}", e)))?, + )?; + + let serialized_blob = blob.clone().serialize(); + + let module = wasmtime::Module::new(&engine, &serialized_blob) + .map_err(|e| WasmError::Other(format!("cannot create module: {}", e)))?; if config.semantics.fast_instance_reuse { let data_segments_snapshot = DataSegmentsSnapshot::take(&blob).map_err(|e| { WasmError::Other(format!("cannot take data segments snapshot: {}", e)) })?; let data_segments_snapshot = Arc::new(data_segments_snapshot); - let mutable_globals = ExposedMutableGlobalsSet::collect(&blob); - let module = wasmtime::Module::new(&engine, &blob.serialize()) - .map_err(|e| WasmError::Other(format!("cannot create module: {}", e)))?; - (module, Some(InstanceSnapshotData { data_segments_snapshot, mutable_globals })) } else { - let module = wasmtime::Module::new(&engine, &blob.serialize()) - .map_err(|e| WasmError::Other(format!("cannot create module: {}", e)))?; (module, None) } }, @@ -584,7 +576,15 @@ where }, }; - Ok(WasmtimeRuntime { module: Arc::new(module), snapshot_data, config, phantom: PhantomData }) + let mut linker = wasmtime::Linker::new(&engine); + crate::imports::prepare_imports::(&mut linker, &module, config.allow_missing_func_imports)?; + + let mut store = crate::instance_wrapper::create_store(module.engine(), config.max_memory_size); + let instance_pre = linker + .instantiate_pre(&mut store, &module) + .map_err(|e| WasmError::Other(format!("cannot preinstantiate module: {}", e)))?; + + Ok(WasmtimeRuntime { engine, instance_pre: Arc::new(instance_pre), snapshot_data, config }) } fn instrument( diff --git a/client/executor/wasmtime/src/tests.rs b/client/executor/wasmtime/src/tests.rs index 664d05f5387f..a4ca0959da86 100644 --- a/client/executor/wasmtime/src/tests.rs +++ b/client/executor/wasmtime/src/tests.rs @@ -24,7 +24,7 @@ use std::sync::Arc; type HostFunctions = sp_io::SubstrateHostFunctions; struct RuntimeBuilder { - code: Option<&'static str>, + code: Option, fast_instance_reuse: bool, canonicalize_nans: bool, deterministic_stack: bool, @@ -46,7 +46,7 @@ impl RuntimeBuilder { } } - fn use_wat(&mut self, code: &'static str) { + fn use_wat(&mut self, code: String) { self.code = Some(code); } @@ -152,7 +152,7 @@ fn test_stack_depth_reaching() { let runtime = { let mut builder = RuntimeBuilder::new_on_demand(); - builder.use_wat(TEST_GUARD_PAGE_SKIP); + builder.use_wat(TEST_GUARD_PAGE_SKIP.to_string()); builder.deterministic_stack(true); builder.build() }; @@ -168,10 +168,19 @@ fn test_stack_depth_reaching() { } #[test] -fn test_max_memory_pages() { +fn test_max_memory_pages_imported_memory() { + test_max_memory_pages(true); +} + +#[test] +fn test_max_memory_pages_exported_memory() { + test_max_memory_pages(false); +} + +fn test_max_memory_pages(import_memory: bool) { fn try_instantiate( max_memory_size: Option, - wat: &'static str, + wat: String, ) -> Result<(), Box> { let runtime = { let mut builder = RuntimeBuilder::new_on_demand(); @@ -184,31 +193,48 @@ fn test_max_memory_pages() { Ok(()) } + fn memory(initial: u32, maximum: Option, import: bool) -> String { + let memory = if let Some(maximum) = maximum { + format!("(memory $0 {} {})", initial, maximum) + } else { + format!("(memory $0 {})", initial) + }; + + if import { + format!("(import \"env\" \"memory\" {})", memory) + } else { + format!("{}\n(export \"memory\" (memory $0))", memory) + } + } + const WASM_PAGE_SIZE: usize = 65536; // check the old behavior if preserved. That is, if no limit is set we allow 4 GiB of memory. try_instantiate( None, - r#" - (module - ;; we want to allocate the maximum number of pages supported in wasm for this test. - ;; - ;; However, due to a bug in wasmtime (I think wasmi is also affected) it is only possible - ;; to allocate 65536 - 1 pages. - ;; - ;; Then, during creation of the Substrate Runtime instance, 1024 (heap_pages) pages are - ;; mounted. - ;; - ;; Thus 65535 = 64511 + 1024 - (import "env" "memory" (memory 64511)) - - (global (export "__heap_base") i32 (i32.const 0)) - (func (export "main") - (param i32 i32) (result i64) - (i64.const 0) + format!( + r#" + (module + {} + (global (export "__heap_base") i32 (i32.const 0)) + (func (export "main") + (param i32 i32) (result i64) + (i64.const 0) + ) ) - ) - "#, + "#, + /* + We want to allocate the maximum number of pages supported in wasm for this test. + However, due to a bug in wasmtime (I think wasmi is also affected) it is only possible + to allocate 65536 - 1 pages. + + Then, during creation of the Substrate Runtime instance, 1024 (heap_pages) pages are + mounted. + + Thus 65535 = 64511 + 1024 + */ + memory(64511, None, import_memory) + ), ) .unwrap(); @@ -217,94 +243,104 @@ fn test_max_memory_pages() { // max_memory_size = (1 (initial) + 1024 (heap_pages)) * WASM_PAGE_SIZE try_instantiate( Some((1 + 1024) * WASM_PAGE_SIZE), - r#" - (module - - (import "env" "memory" (memory 1)) ;; <- 1 initial, max is not specified - - (global (export "__heap_base") i32 (i32.const 0)) - (func (export "main") - (param i32 i32) (result i64) - (i64.const 0) + format!( + r#" + (module + {} + (global (export "__heap_base") i32 (i32.const 0)) + (func (export "main") + (param i32 i32) (result i64) + (i64.const 0) + ) ) - ) - "#, + "#, + // 1 initial, max is not specified. + memory(1, None, import_memory) + ), ) .unwrap(); // max is specified explicitly to 2048 pages. try_instantiate( Some((1 + 1024) * WASM_PAGE_SIZE), - r#" - (module - - (import "env" "memory" (memory 1 2048)) ;; <- max is 2048 - - (global (export "__heap_base") i32 (i32.const 0)) - (func (export "main") - (param i32 i32) (result i64) - (i64.const 0) + format!( + r#" + (module + {} + (global (export "__heap_base") i32 (i32.const 0)) + (func (export "main") + (param i32 i32) (result i64) + (i64.const 0) + ) ) - ) - "#, + "#, + // Max is 2048. + memory(1, Some(2048), import_memory) + ), ) .unwrap(); // memory grow should work as long as it doesn't exceed 1025 pages in total. try_instantiate( Some((0 + 1024 + 25) * WASM_PAGE_SIZE), - r#" - (module - (import "env" "memory" (memory 0)) ;; <- zero starting pages. - - (global (export "__heap_base") i32 (i32.const 0)) - (func (export "main") - (param i32 i32) (result i64) - - ;; assert(memory.grow returns != -1) - (if - (i32.eq - (memory.grow - (i32.const 25) + format!( + r#" + (module + {} + (global (export "__heap_base") i32 (i32.const 0)) + (func (export "main") + (param i32 i32) (result i64) + + ;; assert(memory.grow returns != -1) + (if + (i32.eq + (memory.grow + (i32.const 25) + ) + (i32.const -1) ) - (i32.const -1) + (unreachable) ) - (unreachable) - ) - (i64.const 0) + (i64.const 0) + ) ) - ) - "#, + "#, + // Zero starting pages. + memory(0, None, import_memory) + ), ) .unwrap(); // We start with 1025 pages and try to grow at least one. try_instantiate( Some((1 + 1024) * WASM_PAGE_SIZE), - r#" - (module - (import "env" "memory" (memory 1)) ;; <- initial=1, meaning after heap pages mount the - ;; total will be already 1025 - (global (export "__heap_base") i32 (i32.const 0)) - (func (export "main") - (param i32 i32) (result i64) - - ;; assert(memory.grow returns == -1) - (if - (i32.ne - (memory.grow - (i32.const 1) + format!( + r#" + (module + {} + (global (export "__heap_base") i32 (i32.const 0)) + (func (export "main") + (param i32 i32) (result i64) + + ;; assert(memory.grow returns == -1) + (if + (i32.ne + (memory.grow + (i32.const 1) + ) + (i32.const -1) ) - (i32.const -1) + (unreachable) ) - (unreachable) - ) - (i64.const 0) + (i64.const 0) + ) ) - ) - "#, + "#, + // Initial=1, meaning after heap pages mount the total will be already 1025. + memory(1, None, import_memory) + ), ) .unwrap(); } From babf752334dd484e5d0900d2a4f7be1a9ac31c2e Mon Sep 17 00:00:00 2001 From: Dan Shields <35669742+NukeManDan@users.noreply.github.com> Date: Sat, 19 Mar 2022 13:19:00 -0600 Subject: [PATCH 616/695] Add github issue form templates (#11061) * add issue form templates * Apply suggestions from code review Co-authored-by: Sacha Lansky Co-authored-by: Sacha Lansky --- .github/ISSUE_TEMPLATE/bug.yaml | 34 +++++++++++++++++++ .github/ISSUE_TEMPLATE/config.yml | 7 ++++ .github/ISSUE_TEMPLATE/feature.yaml | 52 +++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug.yaml create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature.yaml diff --git a/.github/ISSUE_TEMPLATE/bug.yaml b/.github/ISSUE_TEMPLATE/bug.yaml new file mode 100644 index 000000000000..ae40df08eca7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug.yaml @@ -0,0 +1,34 @@ +name: Bug Report +description: Let us know about an issue you experienced with this software +# labels: ["some existing label","another one"] +body: + - type: checkboxes + attributes: + label: Is there an existing issue? + description: Please search to see if an issue already exists and leave a comment that you also experienced this issue or add your specifics that are related to an existing issue. + options: + - label: I have searched the existing issues + required: true + - type: checkboxes + attributes: + label: Experiencing problems? Have you tried our Stack Exchange first? + description: Please search to see if an post already exists, and ask if not. Please do not file support issues here. + options: + - label: This is not a support question. + required: true + - type: textarea + id: bug + attributes: + label: Description of bug + # description: What seems to be the problem? + # placeholder: Describe the problem. + validations: + required: true + - type: textarea + id: steps + attributes: + label: Steps to reproduce + description: Provide the steps that led to the discovery of the issue. + # placeholder: Describe what you were doing so we can reproduce the problem. + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000000..e422e317411f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,7 @@ +blank_issues_enabled: true +contact_links: + - name: Support & Troubleshooting with the Substrate Stack Exchange Community + url: https://substrate.stackexchange.com + about: | + For general problems with Substrate or related technologies, please search here first + for solutions, by keyword and tags. If you discover no solution, please then ask and questions in our community! We highly encourage everyone also share their understanding by answering questions for others. diff --git a/.github/ISSUE_TEMPLATE/feature.yaml b/.github/ISSUE_TEMPLATE/feature.yaml new file mode 100644 index 000000000000..92b2fea3e88d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature.yaml @@ -0,0 +1,52 @@ +name: Feature Request +description: Submit your requests and suggestions to improve! +body: + - type: checkboxes + attributes: + label: Is there an existing issue? + description: Please search to see if an issue already exists and leave a comment that you also experienced this issue or add your specifics that are related to an existing issue. + options: + - label: I have searched the existing issues + required: true + - type: checkboxes + attributes: + label: Experiencing problems? Have you tried our Stack Exchange first? + description: Please search to see if an post already exists, and ask if not. Please do not file support issues here. + options: + - label: This is not a support question. + required: true + - type: textarea + id: content + attributes: + label: Motivation + description: Please give precedence as to what lead you to file this issue. + # placeholder: Describe ... + validations: + required: false + - type: textarea + id: content + attributes: + label: Request + description: Please describe what is needed. + # placeholder: Describe what you would like to see added or changed. + validations: + required: true + - type: textarea + id: content + attributes: + label: Solution + description: If possible, please describe what a solution could be. + # placeholder: Describe what you would like to see added or changed. + validations: + required: false + - type: dropdown + id: help + attributes: + label: Are you willing to help with this request? + multiple: true + options: + - Yes! + - No. + - Maybe (please elaborate above) + validations: + required: true From 81d253ed66c2597d5ca6a1852c80a6ecb03ce45f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 19 Mar 2022 21:07:18 +0000 Subject: [PATCH 617/695] Bump cargo_metadata from 0.14.1 to 0.14.2 (#11066) Bumps [cargo_metadata](https://github.com/oli-obk/cargo_metadata) from 0.14.1 to 0.14.2. - [Release notes](https://github.com/oli-obk/cargo_metadata/releases) - [Commits](https://github.com/oli-obk/cargo_metadata/compare/0.14.1...0.14.2) --- updated-dependencies: - dependency-name: cargo_metadata dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- utils/wasm-builder/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2760ee0570d4..e847dcd23d32 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -851,9 +851,9 @@ dependencies = [ [[package]] name = "cargo_metadata" -version = "0.14.1" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba2ae6de944143141f6155a473a6b02f66c7c3f9f47316f802f80204ebfe6e12" +checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa" dependencies = [ "camino", "cargo-platform", diff --git a/utils/wasm-builder/Cargo.toml b/utils/wasm-builder/Cargo.toml index ce9687f9ae0e..66c04432c5de 100644 --- a/utils/wasm-builder/Cargo.toml +++ b/utils/wasm-builder/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] build-helper = "0.1.1" -cargo_metadata = "0.14.1" +cargo_metadata = "0.14.2" tempfile = "3.1.0" toml = "0.5.4" walkdir = "2.3.2" From 6506784c95c2b6ee1db19cdbfc8142e9c7a071dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Sat, 19 Mar 2022 23:58:32 +0100 Subject: [PATCH 618/695] sc-consensus-aura: Remove obsolete dependency (#11074) --- Cargo.lock | 3 --- client/consensus/aura/Cargo.toml | 3 --- 2 files changed, 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e847dcd23d32..3de4fc3f7020 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2646,10 +2646,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" dependencies = [ "cfg-if 1.0.0", - "js-sys", "libc", "wasi 0.10.0+wasi-snapshot-preview1", - "wasm-bindgen", ] [[package]] @@ -8239,7 +8237,6 @@ version = "0.10.0-dev" dependencies = [ "async-trait", "futures 0.3.19", - "getrandom 0.2.3", "log 0.4.14", "parity-scale-codec", "parking_lot 0.12.0", diff --git a/client/consensus/aura/Cargo.toml b/client/consensus/aura/Cargo.toml index 6f5ff3c221fa..2ad61f2bc48d 100644 --- a/client/consensus/aura/Cargo.toml +++ b/client/consensus/aura/Cargo.toml @@ -35,9 +35,6 @@ sp-keystore = { version = "0.12.0", path = "../../../primitives/keystore" } sc-telemetry = { version = "4.0.0-dev", path = "../../telemetry" } prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.10.0-dev" } async-trait = "0.1.50" -# We enable it only for web-wasm check -# See https://docs.rs/getrandom/0.2.1/getrandom/#webassembly-support -getrandom = { version = "0.2", features = ["js"], optional = true } [dev-dependencies] sp-timestamp = { version = "4.0.0-dev", path = "../../../primitives/timestamp" } From 4ad64453048066ee34153db0da576ec95338fdb6 Mon Sep 17 00:00:00 2001 From: Qinxuan Chen Date: Mon, 21 Mar 2022 16:37:59 +0800 Subject: [PATCH 619/695] pallet-whitelist: add sp-api/std to std feature to fix compile error (#11077) Signed-off-by: koushiro --- frame/whitelist/Cargo.toml | 11 ++++++----- frame/whitelist/src/benchmarking.rs | 7 ++++--- frame/whitelist/src/lib.rs | 17 +++++++---------- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/frame/whitelist/Cargo.toml b/frame/whitelist/Cargo.toml index 6bc43ff96178..5f414e5d3203 100644 --- a/frame/whitelist/Cargo.toml +++ b/frame/whitelist/Cargo.toml @@ -17,25 +17,26 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = scale-info = { version = "2.0", default-features = false, features = ["derive"] } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../primitives/api" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } + frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] sp-core = { version = "6.0.0", path = "../../primitives/core" } -pallet-preimage = { version = "4.0.0-dev", path = "../preimage/" } -pallet-balances = { version = "4.0.0-dev", path = "../balances/" } +sp-io = { version = "6.0.0", path = "../../primitives/io" } +pallet-balances = { version = "4.0.0-dev", path = "../balances" } +pallet-preimage = { version = "4.0.0-dev", path = "../preimage" } [features] default = ["std"] std = [ "codec/std", "scale-info/std", - "sp-std/std", - "sp-io/std", + "sp-api/std", "sp-runtime/std", + "sp-std/std", "frame-support/std", "frame-system/std", ] diff --git a/frame/whitelist/src/benchmarking.rs b/frame/whitelist/src/benchmarking.rs index c51ea0a0a324..50809ddef7ec 100644 --- a/frame/whitelist/src/benchmarking.rs +++ b/frame/whitelist/src/benchmarking.rs @@ -20,10 +20,11 @@ #![cfg(feature = "runtime-benchmarks")] use super::*; -use core::convert::TryInto; use frame_benchmarking::benchmarks; -use frame_support::{ensure, traits::PreimageRecipient}; -use sp_runtime::traits::Hash; +use frame_support::{ + ensure, + traits::{EnsureOrigin, Get, PreimageRecipient}, +}; #[cfg(test)] use crate::Pallet as Whitelist; diff --git a/frame/whitelist/src/lib.rs b/frame/whitelist/src/lib.rs index 9f20386da85f..c2de16964a49 100644 --- a/frame/whitelist/src/lib.rs +++ b/frame/whitelist/src/lib.rs @@ -39,21 +39,15 @@ mod mock; mod tests; pub mod weights; -use sp_runtime::traits::Dispatchable; -use sp_std::prelude::*; - use codec::{Decode, DecodeLimit, Encode, FullCodec, MaxEncodedLen}; use frame_support::{ ensure, traits::{PreimageProvider, PreimageRecipient}, - weights::{GetDispatchInfo, PostDispatchInfo}, + weights::{GetDispatchInfo, PostDispatchInfo, Weight}, }; use scale_info::TypeInfo; -use sp_api::HashT; -use weights::WeightInfo; - -use frame_support::pallet_prelude::*; -use frame_system::pallet_prelude::*; +use sp_runtime::traits::{Dispatchable, Hash}; +use sp_std::prelude::*; pub use pallet::*; @@ -66,6 +60,9 @@ pub struct Preimage { #[frame_support::pallet] pub mod pallet { use super::*; + use crate::weights::WeightInfo; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; #[pallet::config] pub trait Config: frame_system::Config { @@ -92,7 +89,7 @@ pub mod pallet { type PreimageProvider: PreimageProvider + PreimageRecipient; /// The weight information for this pallet. - type WeightInfo: weights::WeightInfo; + type WeightInfo: WeightInfo; } #[pallet::pallet] From 28eaae58daa52341c2128531be510ac039437f5c Mon Sep 17 00:00:00 2001 From: zqhxuyuan Date: Mon, 21 Mar 2022 16:41:37 +0800 Subject: [PATCH 620/695] add MaxEncodedLen trait to Time (#11078) --- frame/support/src/traits/misc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frame/support/src/traits/misc.rs b/frame/support/src/traits/misc.rs index 8c61874003bc..2a0d6f0523e7 100644 --- a/frame/support/src/traits/misc.rs +++ b/frame/support/src/traits/misc.rs @@ -510,7 +510,7 @@ pub trait HandleLifetime { impl HandleLifetime for () {} pub trait Time { - type Moment: sp_arithmetic::traits::AtLeast32Bit + Parameter + Default + Copy; + type Moment: sp_arithmetic::traits::AtLeast32Bit + Parameter + Default + Copy + MaxEncodedLen; fn now() -> Self::Moment; } From 5917c0e1a0b3746b08fc86f26e270fcca1492bd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Mon, 21 Mar 2022 11:35:49 +0100 Subject: [PATCH 621/695] pallet-macro: Ensure that building with `missing_docs` works (#11075) * pallet-macro: Ensure that building with `missing_docs` works Before this pr it was failing when compiling with `missing_docs`, because the macro was generating functions etc without the appropriate docs. In the case of this pr it is mainly about hiding these functions in the docs as they are internal api anyway. * Fix UI test --- .../support/procedural/src/pallet/expand/call.rs | 5 ++++- .../procedural/src/pallet/expand/error.rs | 2 ++ .../src/pallet/expand/pallet_struct.rs | 2 ++ .../procedural/src/pallet/expand/storage.rs | 2 ++ frame/support/test/Cargo.toml | 2 +- frame/support/test/pallet/src/lib.rs | 16 ++++++++++++++++ .../call_argument_invalid_bound_2.stderr | 6 +++--- 7 files changed, 30 insertions(+), 5 deletions(-) diff --git a/frame/support/procedural/src/pallet/expand/call.rs b/frame/support/procedural/src/pallet/expand/call.rs index 355d4f87d3db..2d7c550a4486 100644 --- a/frame/support/procedural/src/pallet/expand/call.rs +++ b/frame/support/procedural/src/pallet/expand/call.rs @@ -178,7 +178,10 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream { #( #( #[doc = #fn_doc] )* #fn_name { - #( #args_compact_attr #args_name_stripped: #args_type ),* + #( + #[allow(missing_docs)] + #args_compact_attr #args_name_stripped: #args_type + ),* }, )* } diff --git a/frame/support/procedural/src/pallet/expand/error.rs b/frame/support/procedural/src/pallet/expand/error.rs index 9e2b801083e4..184fa86d3ae1 100644 --- a/frame/support/procedural/src/pallet/expand/error.rs +++ b/frame/support/procedural/src/pallet/expand/error.rs @@ -90,6 +90,7 @@ pub fn expand_error(def: &mut Def) -> proc_macro2::TokenStream { } impl<#type_impl_gen> #error_ident<#type_use_gen> #config_where_clause { + #[doc(hidden)] pub fn as_u8(&self) -> u8 { match &self { Self::__Ignore(_, _) => unreachable!("`__Ignore` can never be constructed"), @@ -97,6 +98,7 @@ pub fn expand_error(def: &mut Def) -> proc_macro2::TokenStream { } } + #[doc(hidden)] pub fn as_str(&self) -> &'static str { match &self { Self::__Ignore(_, _) => unreachable!("`__Ignore` can never be constructed"), diff --git a/frame/support/procedural/src/pallet/expand/pallet_struct.rs b/frame/support/procedural/src/pallet/expand/pallet_struct.rs index 61c6d001a6f9..52586a70a521 100644 --- a/frame/support/procedural/src/pallet/expand/pallet_struct.rs +++ b/frame/support/procedural/src/pallet/expand/pallet_struct.rs @@ -81,6 +81,7 @@ pub fn expand_pallet_struct(def: &mut Def) -> proc_macro2::TokenStream { let error_ident = &error_def.error; quote::quote_spanned!(def.pallet_struct.attr_span => impl<#type_impl_gen> #pallet_ident<#type_use_gen> #config_where_clause { + #[doc(hidden)] pub fn error_metadata() -> Option<#frame_support::metadata::PalletErrorMetadata> { Some(#frame_support::metadata::PalletErrorMetadata { ty: #frame_support::scale_info::meta_type::<#error_ident<#type_use_gen>>() @@ -91,6 +92,7 @@ pub fn expand_pallet_struct(def: &mut Def) -> proc_macro2::TokenStream { } else { quote::quote_spanned!(def.pallet_struct.attr_span => impl<#type_impl_gen> #pallet_ident<#type_use_gen> #config_where_clause { + #[doc(hidden)] pub fn error_metadata() -> Option<#frame_support::metadata::PalletErrorMetadata> { None } diff --git a/frame/support/procedural/src/pallet/expand/storage.rs b/frame/support/procedural/src/pallet/expand/storage.rs index f45223c1cc84..d59dd4605139 100644 --- a/frame/support/procedural/src/pallet/expand/storage.rs +++ b/frame/support/procedural/src/pallet/expand/storage.rs @@ -406,6 +406,7 @@ pub fn expand_storages(def: &mut Def) -> proc_macro2::TokenStream { quote::quote_spanned!(storage_def.attr_span => #(#cfg_attrs)* + #[doc(hidden)] #prefix_struct_vis struct #counter_prefix_struct_ident<#type_use_gen>( core::marker::PhantomData<(#type_use_gen,)> ); @@ -439,6 +440,7 @@ pub fn expand_storages(def: &mut Def) -> proc_macro2::TokenStream { #maybe_counter #(#cfg_attrs)* + #[doc(hidden)] #prefix_struct_vis struct #prefix_struct_ident<#type_use_gen>( core::marker::PhantomData<(#type_use_gen,)> ); diff --git a/frame/support/test/Cargo.toml b/frame/support/test/Cargo.toml index d99889cf99bc..383b7cf812b4 100644 --- a/frame/support/test/Cargo.toml +++ b/frame/support/test/Cargo.toml @@ -23,7 +23,7 @@ sp-runtime = { version = "6.0.0", default-features = false, path = "../../../pri sp-core = { version = "6.0.0", default-features = false, path = "../../../primitives/core" } sp-std = { version = "4.0.0", default-features = false, path = "../../../primitives/std" } sp-version = { version = "5.0.0", default-features = false, path = "../../../primitives/version" } -trybuild = "1.0.53" +trybuild = { version = "1.0.53", features = [ "diff" ] } pretty_assertions = "1.0.0" rustversion = "1.0.6" frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" } diff --git a/frame/support/test/pallet/src/lib.rs b/frame/support/test/pallet/src/lib.rs index 25741313c2a0..37678e056f3e 100644 --- a/frame/support/test/pallet/src/lib.rs +++ b/frame/support/test/pallet/src/lib.rs @@ -14,6 +14,12 @@ // 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. + +//! Testing pallet macro + +// Ensure docs are propagated properly by the macros. +#![warn(missing_docs)] + pub use pallet::*; #[frame_support::pallet] @@ -29,6 +35,10 @@ pub mod pallet { #[pallet::config] pub trait Config: frame_system::Config {} + /// I'm the documentation + #[pallet::storage] + pub type Value = StorageValue; + #[pallet::genesis_config] #[cfg_attr(feature = "std", derive(Default))] pub struct GenesisConfig {} @@ -37,4 +47,10 @@ pub mod pallet { impl GenesisBuild for GenesisConfig { fn build(&self) {} } + + #[pallet::error] + pub enum Error { + /// Something failed + Test, + } } diff --git a/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr b/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr index e9d267274a6e..aff066162087 100644 --- a/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr +++ b/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr @@ -56,10 +56,10 @@ note: required by a bound in `encode_to` = note: this error originates in the derive macro `frame_support::codec::Encode` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `::Bar: WrapperTypeDecode` is not satisfied - --> tests/pallet_ui/call_argument_invalid_bound_2.rs:20:36 + --> tests/pallet_ui/call_argument_invalid_bound_2.rs:17:12 | -20 | pub fn foo(origin: OriginFor, bar: T::Bar) -> DispatchResultWithPostInfo { - | ^^^ the trait `WrapperTypeDecode` is not implemented for `::Bar` +17 | #[pallet::call] + | ^^^^ the trait `WrapperTypeDecode` is not implemented for `::Bar` | = note: required because of the requirements on the impl of `Decode` for `::Bar` note: required by a bound in `parity_scale_codec::Decode::decode` From 5d630dd5d0387e297617b407db3deae7bf584df3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Mon, 21 Mar 2022 13:15:37 +0100 Subject: [PATCH 622/695] import-blocks: Do not read `stdin` to memory (#11072) * import-blocks: Do not read `stdin` to memory This fixes a bug with `import-blocks` reading the entire `stdin` before starting to import the blocks. However, for huge files that uses quite a lot of memory. We can just read from `stdin` step by step as we do it with a file. This ensures that we don't read the entire input at once into memory. * FMT * Fix warning --- client/cli/src/commands/import_blocks_cmd.rs | 8 ++------ client/service/src/chain_ops/import_blocks.rs | 15 ++++++++------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/client/cli/src/commands/import_blocks_cmd.rs b/client/cli/src/commands/import_blocks_cmd.rs index fece33ba23a2..749824834bf7 100644 --- a/client/cli/src/commands/import_blocks_cmd.rs +++ b/client/cli/src/commands/import_blocks_cmd.rs @@ -72,13 +72,9 @@ impl ImportBlocksCmd { B: BlockT + for<'de> serde::Deserialize<'de>, IQ: sc_service::ImportQueue + 'static, { - let file: Box = match &self.input { + let file: Box = match &self.input { Some(filename) => Box::new(fs::File::open(filename)?), - None => { - let mut buffer = Vec::new(); - io::stdin().read_to_end(&mut buffer)?; - Box::new(io::Cursor::new(buffer)) - }, + None => Box::new(io::stdin()), }; import_blocks(client, import_queue, file, false, self.binary) diff --git a/client/service/src/chain_ops/import_blocks.rs b/client/service/src/chain_ops/import_blocks.rs index 9d74fa1c276f..dc03cdcedae0 100644 --- a/client/service/src/chain_ops/import_blocks.rs +++ b/client/service/src/chain_ops/import_blocks.rs @@ -36,7 +36,7 @@ use sp_runtime::{ }; use std::{ convert::{TryFrom, TryInto}, - io::{Read, Seek}, + io::Read, pin::Pin, task::Poll, time::{Duration, Instant}, @@ -63,7 +63,7 @@ pub fn build_spec(spec: &dyn ChainSpec, raw: bool) -> error::Result { /// SignedBlock and return it. enum BlockIter where - R: std::io::Read + std::io::Seek, + R: std::io::Read, { Binary { // Total number of blocks we are expecting to decode. @@ -83,7 +83,7 @@ where impl BlockIter where - R: Read + Seek + 'static, + R: Read + 'static, B: BlockT + MaybeSerializeDeserialize, { fn new(input: R, binary: bool) -> Result { @@ -119,7 +119,7 @@ where impl Iterator for BlockIter where - R: Read + Seek + 'static, + R: Read + 'static, B: BlockT + MaybeSerializeDeserialize, { type Item = Result, String>; @@ -267,10 +267,11 @@ impl Speedometer { /// Different State that the `import_blocks` future could be in. enum ImportState where - R: Read + Seek + 'static, + R: Read + 'static, B: BlockT + MaybeSerializeDeserialize, { - /// We are reading from the BlockIter structure, adding those blocks to the queue if possible. + /// We are reading from the [`BlockIter`] structure, adding those blocks to the queue if + /// possible. Reading { block_iter: BlockIter }, /// The queue is full (contains at least MAX_PENDING_BLOCKS blocks) and we are waiting for it /// to catch up. @@ -291,7 +292,7 @@ where pub fn import_blocks( client: Arc, mut import_queue: IQ, - input: impl Read + Seek + Send + 'static, + input: impl Read + Send + 'static, force: bool, binary: bool, ) -> Pin> + Send>> From 1bd5d786fda99d5a0c27c339226789ac047ea4ae Mon Sep 17 00:00:00 2001 From: Nathan Whitaker <17734409+nathanwhit@users.noreply.github.com> Date: Mon, 21 Mar 2022 08:21:53 -0400 Subject: [PATCH 623/695] Don't return the same block twice in ancestor binary search (#11067) * Don't return the same block in ancestor search * Add regression test for ancestor search repeat --- client/network/src/protocol/sync.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/client/network/src/protocol/sync.rs b/client/network/src/protocol/sync.rs index f31afc828bd8..749366f6c165 100644 --- a/client/network/src/protocol/sync.rs +++ b/client/network/src/protocol/sync.rs @@ -2320,7 +2320,11 @@ fn handle_ancestor_search_state( } assert!(right >= left); let middle = left + (right - left) / two; - Some((AncestorSearchState::BinarySearch(left, right), middle)) + if middle == curr_block_num { + None + } else { + Some((AncestorSearchState::BinarySearch(left, right), middle)) + } }, } } @@ -3238,4 +3242,9 @@ mod test { sync.on_block_data(&peer_id1, Some(request), response).unwrap(); assert_eq!(sync.best_queued_number, 4); } + #[test] + fn ancestor_search_repeat() { + let state = AncestorSearchState::::BinarySearch(1, 3); + assert!(handle_ancestor_search_state(&state, 2, true).is_none()); + } } From ec0258e48f21705ed92499d71fe9ee17f57af616 Mon Sep 17 00:00:00 2001 From: Nathan Whitaker <17734409+nathanwhit@users.noreply.github.com> Date: Tue, 22 Mar 2022 03:47:05 -0400 Subject: [PATCH 624/695] Don't ban peers for small duplicate requests (#11084) * Don't ban peers for small duplicate requests * Address review comment --- client/network/src/block_request_handler.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/client/network/src/block_request_handler.rs b/client/network/src/block_request_handler.rs index 2f17cdac0744..e1fe9ebf8d06 100644 --- a/client/network/src/block_request_handler.rs +++ b/client/network/src/block_request_handler.rs @@ -54,6 +54,10 @@ mod rep { /// Reputation change when a peer sent us the same request multiple times. pub const SAME_REQUEST: Rep = Rep::new_fatal("Same block request multiple times"); + + /// Reputation change when a peer sent us the same "small" request multiple times. + pub const SAME_SMALL_REQUEST: Rep = + Rep::new(-(1 << 10), "same small block request multiple times"); } /// Generates a [`ProtocolConfig`] for the block request protocol, refusing incoming requests. @@ -200,8 +204,16 @@ impl BlockRequestHandler { Some(SeenRequestsValue::Fulfilled(ref mut requests)) => { *requests = requests.saturating_add(1); + let small_request = attributes + .difference(BlockAttributes::HEADER | BlockAttributes::JUSTIFICATION) + .is_empty(); + if *requests > MAX_NUMBER_OF_SAME_REQUESTS_PER_PEER { - reputation_change = Some(rep::SAME_REQUEST); + reputation_change = Some(if small_request { + rep::SAME_SMALL_REQUEST + } else { + rep::SAME_REQUEST + }); } }, None => { From c558351a601f8b6f68aec7e1469972f6d265b0c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Tue, 22 Mar 2022 09:23:47 +0100 Subject: [PATCH 625/695] Add `dev_getBlockStats` RPC (#10939) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add chain_getBlockStats rpc * Fix broken doc link * Apply suggestions from code review Co-authored-by: Niklas Adolfsson * Apply suggestions from code review Co-authored-by: Bastian Köcher * fmt * Fix compilation * Move Blockstats * Apply suggestions from code review Co-authored-by: David * fmt Co-authored-by: ascjones Co-authored-by: Niklas Adolfsson Co-authored-by: Bastian Köcher Co-authored-by: David --- Cargo.lock | 1 + bin/node/rpc/src/lib.rs | 7 +- client/rpc-api/Cargo.toml | 1 + client/rpc-api/src/dev/error.rs | 71 +++++++++++++++++++ client/rpc-api/src/dev/mod.rs | 64 +++++++++++++++++ client/rpc-api/src/lib.rs | 1 + client/rpc/src/dev/mod.rs | 118 ++++++++++++++++++++++++++++++++ client/rpc/src/dev/tests.rs | 58 ++++++++++++++++ client/rpc/src/lib.rs | 1 + 9 files changed, 319 insertions(+), 3 deletions(-) create mode 100644 client/rpc-api/src/dev/error.rs create mode 100644 client/rpc-api/src/dev/mod.rs create mode 100644 client/rpc/src/dev/mod.rs create mode 100644 client/rpc/src/dev/tests.rs diff --git a/Cargo.lock b/Cargo.lock index 3de4fc3f7020..3d9068f8ebd7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8864,6 +8864,7 @@ dependencies = [ "parking_lot 0.12.0", "sc-chain-spec", "sc-transaction-pool-api", + "scale-info", "serde", "serde_json", "sp-core", diff --git a/bin/node/rpc/src/lib.rs b/bin/node/rpc/src/lib.rs index 09f350ed3dcf..b8349e26cd1d 100644 --- a/bin/node/rpc/src/lib.rs +++ b/bin/node/rpc/src/lib.rs @@ -103,6 +103,7 @@ pub fn create_full( ) -> Result, Box> where C: ProvideRuntimeApi + + sc_client_api::BlockBackend + HeaderBackend + AuxStore + HeaderMetadata @@ -123,6 +124,7 @@ where use pallet_contracts_rpc::{Contracts, ContractsApi}; use pallet_mmr_rpc::{Mmr, MmrApi}; use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApi}; + use sc_rpc::dev::{Dev, DevApi}; use substrate_frame_rpc_system::{FullSystem, SystemApi}; let mut io = jsonrpc_core::IoHandler::default(); @@ -159,19 +161,18 @@ where subscription_executor, finality_provider, ))); - io.extend_with(substrate_state_trie_migration_rpc::StateMigrationApi::to_delegate( substrate_state_trie_migration_rpc::MigrationRpc::new(client.clone(), backend, deny_unsafe), )); - io.extend_with(sc_sync_state_rpc::SyncStateRpcApi::to_delegate( sc_sync_state_rpc::SyncStateRpcHandler::new( chain_spec, - client, + client.clone(), shared_authority_set, shared_epoch_changes, )?, )); + io.extend_with(DevApi::to_delegate(Dev::new(client, deny_unsafe))); Ok(io) } diff --git a/client/rpc-api/Cargo.toml b/client/rpc-api/Cargo.toml index 38ac1fc44335..06deb0eef0ce 100644 --- a/client/rpc-api/Cargo.toml +++ b/client/rpc-api/Cargo.toml @@ -23,6 +23,7 @@ log = "0.4.8" parking_lot = "0.12.0" thiserror = "1.0" +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } sp-core = { version = "6.0.0", path = "../../primitives/core" } sp-version = { version = "5.0.0", path = "../../primitives/version" } sp-runtime = { version = "6.0.0", path = "../../primitives/runtime" } diff --git a/client/rpc-api/src/dev/error.rs b/client/rpc-api/src/dev/error.rs new file mode 100644 index 000000000000..1a14b0d78994 --- /dev/null +++ b/client/rpc-api/src/dev/error.rs @@ -0,0 +1,71 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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 . + +//! Error helpers for Dev RPC module. + +use crate::errors; +use jsonrpc_core as rpc; + +/// Dev RPC Result type. +pub type Result = std::result::Result; + +/// Dev RPC future Result type. +pub type FutureResult = jsonrpc_core::BoxFuture>; + +/// Dev RPC errors. +#[derive(Debug, thiserror::Error)] +pub enum Error { + /// Failed to query specified block or its parent: Probably an invalid hash. + #[error("Error while querying block: {0}")] + BlockQueryError(Box), + /// The re-execution of the specified block failed. + #[error("Failed to re-execute the specified block")] + BlockExecutionFailed, + /// The witness compaction failed. + #[error("Failed to create to compact the witness")] + WitnessCompactionFailed, + /// The method is marked as unsafe but unsafe flag wasn't supplied on the CLI. + #[error(transparent)] + UnsafeRpcCalled(#[from] crate::policy::UnsafeRpcError), +} + +/// Base error code for all dev errors. +const BASE_ERROR: i64 = 6000; + +impl From for rpc::Error { + fn from(e: Error) -> Self { + match e { + Error::BlockQueryError(_) => rpc::Error { + code: rpc::ErrorCode::ServerError(BASE_ERROR + 1), + message: e.to_string(), + data: None, + }, + Error::BlockExecutionFailed => rpc::Error { + code: rpc::ErrorCode::ServerError(BASE_ERROR + 3), + message: e.to_string(), + data: None, + }, + Error::WitnessCompactionFailed => rpc::Error { + code: rpc::ErrorCode::ServerError(BASE_ERROR + 4), + message: e.to_string(), + data: None, + }, + e => errors::internal(e), + } + } +} diff --git a/client/rpc-api/src/dev/mod.rs b/client/rpc-api/src/dev/mod.rs new file mode 100644 index 000000000000..b1ae8934af8a --- /dev/null +++ b/client/rpc-api/src/dev/mod.rs @@ -0,0 +1,64 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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 . + +//! Substrate dev API containing RPCs that are mainly meant for debugging and stats collection for +//! developers. The endpoints in this RPC module are not meant to be available to non-local users +//! and are all marked `unsafe`. + +pub mod error; + +use self::error::Result; +use codec::{Decode, Encode}; +use jsonrpc_derive::rpc; +use scale_info::TypeInfo; +use serde::{Deserialize, Serialize}; + +/// Statistics of a block returned by the `dev_getBlockStats` RPC. +#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, Debug, TypeInfo, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct BlockStats { + /// The length in bytes of the storage proof produced by executing the block. + pub witness_len: u64, + /// The length in bytes of the storage proof after compaction. + pub witness_compact_len: u64, + /// Length of the block in bytes. + /// + /// This information can also be acquired by downloading the whole block. This merely + /// saves some complexity on the client side. + pub block_len: u64, + /// Number of extrinsics in the block. + /// + /// This information can also be acquired by downloading the whole block. This merely + /// saves some complexity on the client side. + pub num_extrinsics: u64, +} + +/// Substrate dev API. +/// +/// This API contains unstable and unsafe methods only meant for development nodes. They +/// are all flagged as unsafe for this reason. +#[rpc] +pub trait DevApi { + /// Reexecute the specified `block_hash` and gather statistics while doing so. + /// + /// This function requires the specified block and its parent to be available + /// at the queried node. If either the specified block or the parent is pruned, + /// this function will return `None`. + #[rpc(name = "dev_getBlockStats")] + fn block_stats(&self, block_hash: Hash) -> Result>; +} diff --git a/client/rpc-api/src/lib.rs b/client/rpc-api/src/lib.rs index 2b2e09e709aa..e06f30bf9cd8 100644 --- a/client/rpc-api/src/lib.rs +++ b/client/rpc-api/src/lib.rs @@ -35,6 +35,7 @@ pub use policy::{DenyUnsafe, UnsafeRpcError}; pub mod author; pub mod chain; pub mod child_state; +pub mod dev; pub mod offchain; pub mod state; pub mod system; diff --git a/client/rpc/src/dev/mod.rs b/client/rpc/src/dev/mod.rs new file mode 100644 index 000000000000..d782a03feae4 --- /dev/null +++ b/client/rpc/src/dev/mod.rs @@ -0,0 +1,118 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2022 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 . + +//! Implementation of the [`DevApi`] trait providing debug utilities for Substrate based +//! blockchains. + +#[cfg(test)] +mod tests; + +pub use sc_rpc_api::dev::{BlockStats, DevApi}; + +use sc_client_api::{BlockBackend, HeaderBackend}; +use sc_rpc_api::{ + dev::error::{Error, Result}, + DenyUnsafe, +}; +use sp_api::{ApiExt, Core, ProvideRuntimeApi}; +use sp_core::Encode; +use sp_runtime::{ + generic::{BlockId, DigestItem}, + traits::{Block as BlockT, Header}, +}; +use std::{ + marker::{PhantomData, Send, Sync}, + sync::Arc, +}; + +type HasherOf = <::Header as Header>::Hashing; + +/// The Dev API. All methods are unsafe. +pub struct Dev { + client: Arc, + deny_unsafe: DenyUnsafe, + _phantom: PhantomData, +} + +impl Dev { + /// Create a new Dev API. + pub fn new(client: Arc, deny_unsafe: DenyUnsafe) -> Self { + Self { client, deny_unsafe, _phantom: PhantomData::default() } + } +} + +impl DevApi for Dev +where + Block: BlockT + 'static, + Client: BlockBackend + + HeaderBackend + + ProvideRuntimeApi + + Send + + Sync + + 'static, + Client::Api: Core, +{ + fn block_stats(&self, hash: Block::Hash) -> Result> { + self.deny_unsafe.check_if_safe()?; + + let block = { + let block = self + .client + .block(&BlockId::Hash(hash)) + .map_err(|e| Error::BlockQueryError(Box::new(e)))?; + if let Some(block) = block { + let (mut header, body) = block.block.deconstruct(); + // Remove the `Seal` to ensure we have the number of digests as expected by the + // runtime. + header.digest_mut().logs.retain(|item| !matches!(item, DigestItem::Seal(_, _))); + Block::new(header, body) + } else { + return Ok(None) + } + }; + let parent_header = { + let parent_hash = *block.header().parent_hash(); + let parent_header = self + .client + .header(BlockId::Hash(parent_hash)) + .map_err(|e| Error::BlockQueryError(Box::new(e)))?; + if let Some(header) = parent_header { + header + } else { + return Ok(None) + } + }; + let block_len = block.encoded_size() as u64; + let num_extrinsics = block.extrinsics().len() as u64; + let pre_root = *parent_header.state_root(); + let mut runtime_api = self.client.runtime_api(); + runtime_api.record_proof(); + runtime_api + .execute_block(&BlockId::Hash(parent_header.hash()), block) + .map_err(|_| Error::BlockExecutionFailed)?; + let witness = runtime_api + .extract_proof() + .expect("We enabled proof recording. A proof must be available; qed"); + let witness_len = witness.encoded_size() as u64; + let witness_compact_len = witness + .into_compact_proof::>(pre_root) + .map_err(|_| Error::WitnessCompactionFailed)? + .encoded_size() as u64; + Ok(Some(BlockStats { witness_len, witness_compact_len, block_len, num_extrinsics })) + } +} diff --git a/client/rpc/src/dev/tests.rs b/client/rpc/src/dev/tests.rs new file mode 100644 index 000000000000..1d31abe38b64 --- /dev/null +++ b/client/rpc/src/dev/tests.rs @@ -0,0 +1,58 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2022 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 . + +use super::*; +use assert_matches::assert_matches; +use futures::executor; +use sc_block_builder::BlockBuilderProvider; +use sp_blockchain::HeaderBackend; +use sp_consensus::BlockOrigin; +use substrate_test_runtime_client::{prelude::*, runtime::Block}; + +#[test] +fn block_stats_work() { + let mut client = Arc::new(substrate_test_runtime_client::new()); + let api = >::new(client.clone(), DenyUnsafe::No); + + let block = client.new_block(Default::default()).unwrap().build().unwrap().block; + executor::block_on(client.import(BlockOrigin::Own, block)).unwrap(); + + // Can't gather stats for a block without a parent. + assert_eq!(api.block_stats(client.genesis_hash()).unwrap(), None); + + assert_eq!( + api.block_stats(client.info().best_hash).unwrap(), + Some(BlockStats { + witness_len: 597, + witness_compact_len: 500, + block_len: 99, + num_extrinsics: 0, + }), + ); +} + +#[test] +fn deny_unsafe_works() { + let mut client = Arc::new(substrate_test_runtime_client::new()); + let api = >::new(client.clone(), DenyUnsafe::Yes); + + let block = client.new_block(Default::default()).unwrap().build().unwrap().block; + executor::block_on(client.import(BlockOrigin::Own, block)).unwrap(); + + assert_matches!(api.block_stats(client.info().best_hash), Err(Error::UnsafeRpcCalled(_))); +} diff --git a/client/rpc/src/lib.rs b/client/rpc/src/lib.rs index 3966baf13c75..59a1d542d365 100644 --- a/client/rpc/src/lib.rs +++ b/client/rpc/src/lib.rs @@ -34,6 +34,7 @@ pub use sc_rpc_api::{DenyUnsafe, Metadata}; pub mod author; pub mod chain; +pub mod dev; pub mod offchain; pub mod state; pub mod system; From c9fc99d296a6bd3ac4a47d77cc855a1380b7cf69 Mon Sep 17 00:00:00 2001 From: Xiliang Chen Date: Tue, 22 Mar 2022 21:45:35 +1300 Subject: [PATCH 626/695] Add ProxyRemoved event (#11085) --- frame/proxy/src/lib.rs | 19 ++++++++++++++++++- frame/proxy/src/tests.rs | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/frame/proxy/src/lib.rs b/frame/proxy/src/lib.rs index 425af1836785..84f1a84badc9 100644 --- a/frame/proxy/src/lib.rs +++ b/frame/proxy/src/lib.rs @@ -570,6 +570,13 @@ pub mod pallet { proxy_type: T::ProxyType, delay: T::BlockNumber, }, + /// A proxy was removed. + ProxyRemoved { + delegator: T::AccountId, + delegatee: T::AccountId, + proxy_type: T::ProxyType, + delay: T::BlockNumber, + }, } /// Old name generated by `decl_event`. @@ -712,7 +719,11 @@ impl Pallet { ) -> DispatchResult { Proxies::::try_mutate_exists(delegator, |x| { let (mut proxies, old_deposit) = x.take().ok_or(Error::::NotFound)?; - let proxy_def = ProxyDefinition { delegate: delegatee, proxy_type, delay }; + let proxy_def = ProxyDefinition { + delegate: delegatee.clone(), + proxy_type: proxy_type.clone(), + delay, + }; let i = proxies.binary_search(&proxy_def).ok().ok_or(Error::::NotFound)?; proxies.remove(i); let new_deposit = Self::deposit(proxies.len() as u32); @@ -724,6 +735,12 @@ impl Pallet { if !proxies.is_empty() { *x = Some((proxies, new_deposit)) } + Self::deposit_event(Event::::ProxyRemoved { + delegator: delegator.clone(), + delegatee, + proxy_type, + delay, + }); Ok(()) }) } diff --git a/frame/proxy/src/tests.rs b/frame/proxy/src/tests.rs index b4f30ab4029a..a0807f1d3d0b 100644 --- a/frame/proxy/src/tests.rs +++ b/frame/proxy/src/tests.rs @@ -436,13 +436,49 @@ fn add_remove_proxies_works() { Error::::NotFound ); assert_ok!(Proxy::remove_proxy(Origin::signed(1), 4, ProxyType::JustUtility, 0)); + System::assert_last_event( + ProxyEvent::ProxyRemoved { + delegator: 1, + delegatee: 4, + proxy_type: ProxyType::JustUtility, + delay: 0, + } + .into(), + ); assert_eq!(Balances::reserved_balance(1), 4); assert_ok!(Proxy::remove_proxy(Origin::signed(1), 3, ProxyType::Any, 0)); assert_eq!(Balances::reserved_balance(1), 3); + System::assert_last_event( + ProxyEvent::ProxyRemoved { + delegator: 1, + delegatee: 3, + proxy_type: ProxyType::Any, + delay: 0, + } + .into(), + ); assert_ok!(Proxy::remove_proxy(Origin::signed(1), 2, ProxyType::Any, 0)); assert_eq!(Balances::reserved_balance(1), 2); + System::assert_last_event( + ProxyEvent::ProxyRemoved { + delegator: 1, + delegatee: 2, + proxy_type: ProxyType::Any, + delay: 0, + } + .into(), + ); assert_ok!(Proxy::remove_proxy(Origin::signed(1), 2, ProxyType::JustTransfer, 0)); assert_eq!(Balances::reserved_balance(1), 0); + System::assert_last_event( + ProxyEvent::ProxyRemoved { + delegator: 1, + delegatee: 2, + proxy_type: ProxyType::JustTransfer, + delay: 0, + } + .into(), + ); assert_noop!( Proxy::add_proxy(Origin::signed(1), 1, ProxyType::Any, 0), Error::::NoSelfProxy From 715d004061cccbe900d9b2e6d3d624087a34eeef Mon Sep 17 00:00:00 2001 From: cheme Date: Tue, 22 Mar 2022 10:53:49 +0100 Subject: [PATCH 627/695] Do not upgrade db_version on metadata reading failure. (#11081) --- Cargo.lock | 4 ++-- client/db/Cargo.toml | 2 +- client/db/src/parity_db.rs | 2 +- client/db/src/utils.rs | 1 + 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3d9068f8ebd7..8e725af983a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6697,9 +6697,9 @@ dependencies = [ [[package]] name = "parity-db" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "865edee5b792f537356d9e55cbc138e7f4718dc881a7ea45a18b37bf61c21e3d" +checksum = "3d121a9af17a43efd0a38c6afa508b927ba07785bd4709efb2ac03bf77efef8d" dependencies = [ "blake2-rfc", "crc32fast", diff --git a/client/db/Cargo.toml b/client/db/Cargo.toml index 7b1e4da20861..105bc43c61bc 100644 --- a/client/db/Cargo.toml +++ b/client/db/Cargo.toml @@ -33,7 +33,7 @@ sc-state-db = { version = "0.10.0-dev", path = "../state-db" } sp-trie = { version = "6.0.0", path = "../../primitives/trie" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-database = { version = "4.0.0-dev", path = "../../primitives/database" } -parity-db = { version = "0.3.8", optional = true } +parity-db = { version = "0.3.9", optional = true } [dev-dependencies] sp-tracing = { version = "5.0.0", path = "../../primitives/tracing" } diff --git a/client/db/src/parity_db.rs b/client/db/src/parity_db.rs index c81a346bb023..f88e6f2e9167 100644 --- a/client/db/src/parity_db.rs +++ b/client/db/src/parity_db.rs @@ -73,7 +73,7 @@ pub fn open>( if upgrade { log::info!("Upgrading database metadata."); if let Some(meta) = parity_db::Options::load_metadata(path)? { - config.write_metadata(path, &meta.salt)?; + config.write_metadata_with_version(path, &meta.salt, Some(meta.version))?; } } diff --git a/client/db/src/utils.rs b/client/db/src/utils.rs index 7dcb6676a175..29aa8424221a 100644 --- a/client/db/src/utils.rs +++ b/client/db/src/utils.rs @@ -275,6 +275,7 @@ fn open_parity_db(path: &Path, db_type: DatabaseType, create: boo match crate::parity_db::open(path, db_type, create, false) { Ok(db) => Ok(db), Err(parity_db::Error::InvalidConfiguration(_)) => { + log::warn!("Invalid parity db configuration, attempting database metadata update."); // Try to update the database with the new config Ok(crate::parity_db::open(path, db_type, create, true)?) }, From 77c15d2546276a865b6e8f1c5d4b1d0ec1961e72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Tue, 22 Mar 2022 13:25:34 +0100 Subject: [PATCH 628/695] warp-sync: Return an error when trying to enable it for archive nodes. (#11086) * warp-sync: Return an error when trying to enable it for archive nodes. * Fix checks * Ups * FMT --- client/network/src/config.rs | 14 +++++++++++++- client/service/src/builder.rs | 14 +++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/client/network/src/config.rs b/client/network/src/config.rs index a7e4e5cc8766..eedf3fc22b96 100644 --- a/client/network/src/config.rs +++ b/client/network/src/config.rs @@ -377,8 +377,8 @@ impl From for ParseErr { } } -#[derive(Clone, Debug, Eq, PartialEq)] /// Sync operation mode. +#[derive(Clone, Debug, Eq, PartialEq)] pub enum SyncMode { /// Full block download and verification. Full, @@ -393,6 +393,18 @@ pub enum SyncMode { Warp, } +impl SyncMode { + /// Returns if `self` is [`Self::Warp`]. + pub fn is_warp(&self) -> bool { + matches!(self, Self::Warp) + } + + /// Returns if `self` is [`Self::Fast`]. + pub fn is_fast(&self) -> bool { + matches!(self, Self::Fast { .. }) + } +} + impl Default for SyncMode { fn default() -> Self { Self::Full diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index e9c1691107c7..f4ff93243575 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -39,7 +39,7 @@ use sc_executor::RuntimeVersionOf; use sc_keystore::LocalKeystore; use sc_network::{ block_request_handler::{self, BlockRequestHandler}, - config::Role, + config::{Role, SyncMode}, light_client_requests::{self, handler::LightClientRequestHandler}, state_request_handler::{self, StateRequestHandler}, warp_request_handler::{self, RequestHandler as WarpSyncRequestHandler, WarpSyncProvider}, @@ -767,6 +767,18 @@ where warp_sync, } = params; + if warp_sync.is_none() && config.network.sync_mode.is_warp() { + return Err("Warp sync enabled, but no warp sync provider configured.".into()) + } + + if config.state_pruning.is_archive() { + match config.network.sync_mode { + SyncMode::Fast { .. } => return Err("Fast sync doesn't work for archive nodes".into()), + SyncMode::Warp => return Err("Warp sync doesn't work for archive nodes".into()), + SyncMode::Full => {}, + }; + } + let transaction_pool_adapter = Arc::new(TransactionPoolAdapter { imports_external_transactions: !matches!(config.role, Role::Light), pool: transaction_pool, From 096f205d82303a889cf566792262e8ffe61bb7fb Mon Sep 17 00:00:00 2001 From: Georges Date: Wed, 23 Mar 2022 09:14:44 +0000 Subject: [PATCH 629/695] Implementing `MaxEncodedLen` for `generate_solution_type` (#11032) * Move `sp-npos-elections-solution-type` to `frame-election-provider-support` First stab at it, will need to amend some more stuff * Fixing tests * Fixing tests * Fixing cargo.toml for std configuration * Implementing `MaxEncodedLen` on `generate_solution_type` * Full implementation of `max_encoded_len` * Fixing implementation bug adding some comments and documentation * fmt * Committing suggested changes renaming, and re exporting macro. * Removing unneeded imports * Implementing `MaxEncodedLen` on `generate_solution_type` * Full implementation of `max_encoded_len` * Fixing implementation bug adding some comments and documentation * Move `NposSolution` to frame * Implementing `MaxEncodedLen` on `generate_solution_type` * Full implementation of `max_encoded_len` * Fixing implementation bug adding some comments and documentation * Fixing test * Removing unneeded dependencies * `VoterSnapshotPerBlock` -> `MaxElectingVoters` * rename `SizeBound` to `MaxVoters` * Removing TODO and change bound * renaming `size_bound` to `max_voters` * Enabling tests for `solution-type` These got dropped off after the crate was moved from `sp_npos_elections` * Adding tests for `MaxEncodedLen` of solution_type * Better rustdocs. Better indenting and comments. Removing unneeded imports in tests. --- Cargo.lock | 3 + bin/node/runtime/src/lib.rs | 4 +- .../election-provider-multi-phase/src/mock.rs | 7 +- frame/election-provider-support/Cargo.toml | 1 + .../solution-type/Cargo.toml | 1 + .../solution-type/fuzzer/Cargo.toml | 1 + .../solution-type/fuzzer/src/compact.rs | 1 + .../solution-type/src/lib.rs | 35 ++++++-- .../solution-type/src/single_page.rs | 22 +++++ .../tests/ui/fail/missing_accuracy.rs | 1 + .../tests/ui/fail/missing_size_bound.rs | 10 +++ .../tests/ui/fail/missing_size_bound.stderr | 5 ++ .../tests/ui/fail/missing_target.rs | 1 + .../tests/ui/fail/missing_voter.rs | 1 + .../tests/ui/fail/no_annotations.rs | 1 + .../tests/ui/fail/swap_voter_target.rs | 1 + .../tests/ui/fail/wrong_attribute.rs | 1 + frame/election-provider-support/src/lib.rs | 5 ++ .../{solution-type => }/src/mock.rs | 11 ++- .../{solution-type => }/src/tests.rs | 84 ++++++++++++++++++- 20 files changed, 184 insertions(+), 12 deletions(-) create mode 100644 frame/election-provider-support/solution-type/tests/ui/fail/missing_size_bound.rs create mode 100644 frame/election-provider-support/solution-type/tests/ui/fail/missing_size_bound.stderr rename frame/election-provider-support/{solution-type => }/src/mock.rs (96%) rename frame/election-provider-support/{solution-type => }/src/tests.rs (80%) diff --git a/Cargo.lock b/Cargo.lock index 8e725af983a5..1b478fcc18a7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2167,6 +2167,7 @@ name = "frame-election-provider-solution-type" version = "4.0.0-dev" dependencies = [ "frame-election-provider-support", + "frame-support", "parity-scale-codec", "proc-macro-crate 1.1.3", "proc-macro2", @@ -2185,6 +2186,7 @@ dependencies = [ "frame-support", "frame-system", "parity-scale-codec", + "rand 0.7.3", "scale-info", "sp-arithmetic", "sp-core", @@ -2201,6 +2203,7 @@ dependencies = [ "clap 3.1.6", "frame-election-provider-solution-type", "frame-election-provider-support", + "frame-support", "honggfuzz", "parity-scale-codec", "rand 0.8.4", diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 64bdcfc87020..b7137de48fb1 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -597,11 +597,13 @@ frame_election_provider_support::generate_solution_type!( VoterIndex = u32, TargetIndex = u16, Accuracy = sp_runtime::PerU16, + MaxVoters = MaxElectingVoters, >(16) ); parameter_types! { pub MaxNominations: u32 = ::LIMIT as u32; + pub MaxElectingVoters: u32 = 10_000; } /// The numbers configured here could always be more than the the maximum limits of staking pallet @@ -677,7 +679,7 @@ impl pallet_election_provider_multi_phase::Config for Runtime { >; type ForceOrigin = EnsureRootOrHalfCouncil; type MaxElectableTargets = ConstU16<{ u16::MAX }>; - type MaxElectingVoters = ConstU32<10_000>; + type MaxElectingVoters = MaxElectingVoters; type BenchmarkingConfig = ElectionProviderBenchmarkConfig; type WeightInfo = pallet_election_provider_multi_phase::weights::SubstrateWeight; } diff --git a/frame/election-provider-multi-phase/src/mock.rs b/frame/election-provider-multi-phase/src/mock.rs index 89b5b72565dc..e2384d2f1576 100644 --- a/frame/election-provider-multi-phase/src/mock.rs +++ b/frame/election-provider-multi-phase/src/mock.rs @@ -70,7 +70,12 @@ pub(crate) type TargetIndex = u16; frame_election_provider_support::generate_solution_type!( #[compact] - pub struct TestNposSolution::(16) + pub struct TestNposSolution::< + VoterIndex = VoterIndex, + TargetIndex = TargetIndex, + Accuracy = PerU16, + MaxVoters = ConstU32::<20> + >(16) ); /// All events of this pallet. diff --git a/frame/election-provider-support/Cargo.toml b/frame/election-provider-support/Cargo.toml index 16b79dbb098d..be0c05e46df3 100644 --- a/frame/election-provider-support/Cargo.toml +++ b/frame/election-provider-support/Cargo.toml @@ -24,6 +24,7 @@ frame-system = { version = "4.0.0-dev", default-features = false, path = "../sys frame-election-provider-solution-type = { version = "4.0.0-dev", path = "solution-type" } [dev-dependencies] +rand = "0.7.3" sp-npos-elections = { version = "4.0.0-dev", path = "../../primitives/npos-elections" } sp-core = { version = "6.0.0", path = "../../primitives/core" } sp-io = { version = "6.0.0", path = "../../primitives/io" } diff --git a/frame/election-provider-support/solution-type/Cargo.toml b/frame/election-provider-support/solution-type/Cargo.toml index e59bbcc8e7b3..ca3038c9145c 100644 --- a/frame/election-provider-support/solution-type/Cargo.toml +++ b/frame/election-provider-support/solution-type/Cargo.toml @@ -26,4 +26,5 @@ scale-info = "2.0.1" sp-arithmetic = { version = "5.0.0", path = "../../../primitives/arithmetic" } # used by generate_solution_type: frame-election-provider-support = { version = "4.0.0-dev", path = ".." } +frame-support = { version = "4.0.0-dev", path = "../../support" } trybuild = "1.0.53" diff --git a/frame/election-provider-support/solution-type/fuzzer/Cargo.toml b/frame/election-provider-support/solution-type/fuzzer/Cargo.toml index f6c2f2fe491e..e2bae3f72a4f 100644 --- a/frame/election-provider-support/solution-type/fuzzer/Cargo.toml +++ b/frame/election-provider-support/solution-type/fuzzer/Cargo.toml @@ -25,6 +25,7 @@ sp-arithmetic = { version = "5.0.0", path = "../../../../primitives/arithmetic" sp-runtime = { version = "6.0.0", path = "../../../../primitives/runtime" } # used by generate_solution_type: sp-npos-elections = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/npos-elections" } +frame-support = { version = "4.0.0-dev", path = "../../../support" } [[bin]] name = "compact" diff --git a/frame/election-provider-support/solution-type/fuzzer/src/compact.rs b/frame/election-provider-support/solution-type/fuzzer/src/compact.rs index 501d241b2b80..e7ef440ff219 100644 --- a/frame/election-provider-support/solution-type/fuzzer/src/compact.rs +++ b/frame/election-provider-support/solution-type/fuzzer/src/compact.rs @@ -8,6 +8,7 @@ fn main() { VoterIndex = u32, TargetIndex = u32, Accuracy = Percent, + MaxVoters = frame_support::traits::ConstU32::<100_000>, >(16)); loop { fuzz!(|fuzzer_data: &[u8]| { diff --git a/frame/election-provider-support/solution-type/src/lib.rs b/frame/election-provider-support/solution-type/src/lib.rs index 6e2788f06007..57d939377b62 100644 --- a/frame/election-provider-support/solution-type/src/lib.rs +++ b/frame/election-provider-support/solution-type/src/lib.rs @@ -49,6 +49,12 @@ pub(crate) fn syn_err(message: &'static str) -> syn::Error { /// compact encoding. /// - The accuracy of the ratios. This must be one of the `PerThing` types defined in /// `sp-arithmetic`. +/// - The maximum number of voters. This must be of type `Get`. Check +/// for more details. This is used to bound the struct, by leveraging the fact that `votes1.len() +/// < votes2.len() < ... < votesn.len()` (the details of the struct is explained further below). +/// We know that `sum_i votes_i.len() <= MaxVoters`, and we know that the maximum size of the +/// struct would be achieved if all voters fall in the last bucket. One can also check the tests +/// and more specifically `max_encoded_len_exact` for a concrete example. /// /// Moreover, the maximum number of edges per voter (distribution per assignment) also need to be /// specified. Attempting to convert from/to an assignment with more distributions will fail. @@ -59,10 +65,12 @@ pub(crate) fn syn_err(message: &'static str) -> syn::Error { /// ``` /// # use frame_election_provider_solution_type::generate_solution_type; /// # use sp_arithmetic::per_things::Perbill; +/// # use frame_support::traits::ConstU32; /// generate_solution_type!(pub struct TestSolution::< /// VoterIndex = u16, /// TargetIndex = u8, /// Accuracy = Perbill, +/// MaxVoters = ConstU32::<10>, /// >(4)); /// ``` /// @@ -103,9 +111,15 @@ pub(crate) fn syn_err(message: &'static str) -> syn::Error { /// # use frame_election_provider_solution_type::generate_solution_type; /// # use frame_election_provider_support::NposSolution; /// # use sp_arithmetic::per_things::Perbill; +/// # use frame_support::traits::ConstU32; /// generate_solution_type!( /// #[compact] -/// pub struct TestSolutionCompact::(8) +/// pub struct TestSolutionCompact::< +/// VoterIndex = u16, +/// TargetIndex = u8, +/// Accuracy = Perbill, +/// MaxVoters = ConstU32::<10>, +/// >(8) /// ); /// ``` #[proc_macro] @@ -129,6 +143,7 @@ struct SolutionDef { voter_type: syn::Type, target_type: syn::Type, weight_type: syn::Type, + max_voters: syn::Type, count: usize, compact_encoding: bool, } @@ -167,11 +182,11 @@ impl Parse for SolutionDef { let _ = ::parse(input)?; let generics: syn::AngleBracketedGenericArguments = input.parse()?; - if generics.args.len() != 3 { - return Err(syn_err("Must provide 3 generic args.")) + if generics.args.len() != 4 { + return Err(syn_err("Must provide 4 generic args.")) } - let expected_types = ["VoterIndex", "TargetIndex", "Accuracy"]; + let expected_types = ["VoterIndex", "TargetIndex", "Accuracy", "MaxVoters"]; let mut types: Vec = generics .args @@ -197,6 +212,7 @@ impl Parse for SolutionDef { }) .collect::>()?; + let max_voters = types.pop().expect("Vector of length 4 can be popped; qed"); let weight_type = types.pop().expect("Vector of length 3 can be popped; qed"); let target_type = types.pop().expect("Vector of length 2 can be popped; qed"); let voter_type = types.pop().expect("Vector of length 1 can be popped; qed"); @@ -205,7 +221,16 @@ impl Parse for SolutionDef { let count_expr: syn::ExprParen = input.parse()?; let count = parse_parenthesized_number::(count_expr)?; - Ok(Self { vis, ident, voter_type, target_type, weight_type, count, compact_encoding }) + Ok(Self { + vis, + ident, + voter_type, + target_type, + weight_type, + max_voters, + count, + compact_encoding, + }) } } diff --git a/frame/election-provider-support/solution-type/src/single_page.rs b/frame/election-provider-support/solution-type/src/single_page.rs index c1d897444da3..5a3ddc22f61c 100644 --- a/frame/election-provider-support/solution-type/src/single_page.rs +++ b/frame/election-provider-support/solution-type/src/single_page.rs @@ -28,6 +28,7 @@ pub(crate) fn generate(def: crate::SolutionDef) -> Result { voter_type, target_type, weight_type, + max_voters, compact_encoding, } = def; @@ -178,6 +179,27 @@ pub(crate) fn generate(def: crate::SolutionDef) -> Result { <#ident as _feps::NposSolution>::TargetIndex, <#ident as _feps::NposSolution>::Accuracy, >; + impl _feps::codec::MaxEncodedLen for #ident { + fn max_encoded_len() -> usize { + use frame_support::traits::Get; + use _feps::codec::Encode; + let s: u32 = #max_voters::get(); + let max_element_size = + // the first voter.. + #voter_type::max_encoded_len() + // #count - 1 tuples.. + .saturating_add( + (#count - 1).saturating_mul( + #target_type::max_encoded_len().saturating_add(#weight_type::max_encoded_len()))) + // and the last target. + .saturating_add(#target_type::max_encoded_len()); + // The assumption is that it contains #count-1 empty elements + // and then last element with full size + #count + .saturating_mul(_feps::codec::Compact(0u32).encoded_size()) + .saturating_add((s as usize).saturating_mul(max_element_size)) + } + } impl<'a> _feps::sp_std::convert::TryFrom<&'a [__IndexAssignment]> for #ident { type Error = _feps::Error; fn try_from(index_assignments: &'a [__IndexAssignment]) -> Result { diff --git a/frame/election-provider-support/solution-type/tests/ui/fail/missing_accuracy.rs b/frame/election-provider-support/solution-type/tests/ui/fail/missing_accuracy.rs index 22693cd875e1..52ae9623fd38 100644 --- a/frame/election-provider-support/solution-type/tests/ui/fail/missing_accuracy.rs +++ b/frame/election-provider-support/solution-type/tests/ui/fail/missing_accuracy.rs @@ -4,6 +4,7 @@ generate_solution_type!(pub struct TestSolution::< VoterIndex = u16, TargetIndex = u8, Perbill, + MaxVoters = ConstU32::<10>, >(8)); fn main() {} diff --git a/frame/election-provider-support/solution-type/tests/ui/fail/missing_size_bound.rs b/frame/election-provider-support/solution-type/tests/ui/fail/missing_size_bound.rs new file mode 100644 index 000000000000..fe8ac04cc8d6 --- /dev/null +++ b/frame/election-provider-support/solution-type/tests/ui/fail/missing_size_bound.rs @@ -0,0 +1,10 @@ +use frame_election_provider_solution_type::generate_solution_type; + +generate_solution_type!(pub struct TestSolution::< + VoterIndex = u16, + TargetIndex = u8, + Accuracy = Perbill, + ConstU32::<10>, +>(8)); + +fn main() {} diff --git a/frame/election-provider-support/solution-type/tests/ui/fail/missing_size_bound.stderr b/frame/election-provider-support/solution-type/tests/ui/fail/missing_size_bound.stderr new file mode 100644 index 000000000000..c685ab816d39 --- /dev/null +++ b/frame/election-provider-support/solution-type/tests/ui/fail/missing_size_bound.stderr @@ -0,0 +1,5 @@ +error: Expected binding: `MaxVoters = ...` + --> tests/ui/fail/missing_size_bound.rs:7:2 + | +7 | ConstU32::<10>, + | ^^^^^^^^^^^^^^ diff --git a/frame/election-provider-support/solution-type/tests/ui/fail/missing_target.rs b/frame/election-provider-support/solution-type/tests/ui/fail/missing_target.rs index 8d0ca927c5fb..b457c4abada6 100644 --- a/frame/election-provider-support/solution-type/tests/ui/fail/missing_target.rs +++ b/frame/election-provider-support/solution-type/tests/ui/fail/missing_target.rs @@ -4,6 +4,7 @@ generate_solution_type!(pub struct TestSolution::< VoterIndex = u16, u8, Accuracy = Perbill, + MaxVoters = ConstU32::<10>, >(8)); fn main() {} diff --git a/frame/election-provider-support/solution-type/tests/ui/fail/missing_voter.rs b/frame/election-provider-support/solution-type/tests/ui/fail/missing_voter.rs index ad4b7f521779..3d12e3e6b5ec 100644 --- a/frame/election-provider-support/solution-type/tests/ui/fail/missing_voter.rs +++ b/frame/election-provider-support/solution-type/tests/ui/fail/missing_voter.rs @@ -4,6 +4,7 @@ generate_solution_type!(pub struct TestSolution::< u16, TargetIndex = u8, Accuracy = Perbill, + MaxVoters = ConstU32::<10>, >(8)); fn main() {} diff --git a/frame/election-provider-support/solution-type/tests/ui/fail/no_annotations.rs b/frame/election-provider-support/solution-type/tests/ui/fail/no_annotations.rs index 87673a382351..9aab15e7ec9a 100644 --- a/frame/election-provider-support/solution-type/tests/ui/fail/no_annotations.rs +++ b/frame/election-provider-support/solution-type/tests/ui/fail/no_annotations.rs @@ -4,6 +4,7 @@ generate_solution_type!(pub struct TestSolution::< u16, u8, Perbill, + MaxVoters = ConstU32::<10>, >(8)); fn main() {} diff --git a/frame/election-provider-support/solution-type/tests/ui/fail/swap_voter_target.rs b/frame/election-provider-support/solution-type/tests/ui/fail/swap_voter_target.rs index f1d5d0e7bf99..4275aae045a6 100644 --- a/frame/election-provider-support/solution-type/tests/ui/fail/swap_voter_target.rs +++ b/frame/election-provider-support/solution-type/tests/ui/fail/swap_voter_target.rs @@ -4,6 +4,7 @@ generate_solution_type!(pub struct TestSolution::< TargetIndex = u16, VoterIndex = u8, Accuracy = Perbill, + MaxVoters = ConstU32::<10>, >(8)); fn main() {} diff --git a/frame/election-provider-support/solution-type/tests/ui/fail/wrong_attribute.rs b/frame/election-provider-support/solution-type/tests/ui/fail/wrong_attribute.rs index d04cc4a7a966..a51cc724ad15 100644 --- a/frame/election-provider-support/solution-type/tests/ui/fail/wrong_attribute.rs +++ b/frame/election-provider-support/solution-type/tests/ui/fail/wrong_attribute.rs @@ -5,6 +5,7 @@ generate_solution_type!( VoterIndex = u8, TargetIndex = u16, Accuracy = Perbill, + MaxVoters = ConstU32::<10>, >(8) ); diff --git a/frame/election-provider-support/src/lib.rs b/frame/election-provider-support/src/lib.rs index 81fd841a6dc4..2cc27472e884 100644 --- a/frame/election-provider-support/src/lib.rs +++ b/frame/election-provider-support/src/lib.rs @@ -192,6 +192,11 @@ pub use scale_info; pub use sp_arithmetic; #[doc(hidden)] pub use sp_std; + +#[cfg(test)] +mod mock; +#[cfg(test)] +mod tests; // Simple Extension trait to easily convert `None` from index closures to `Err`. // // This is only generated and re-exported for the solution code to use. diff --git a/frame/election-provider-support/solution-type/src/mock.rs b/frame/election-provider-support/src/mock.rs similarity index 96% rename from frame/election-provider-support/solution-type/src/mock.rs rename to frame/election-provider-support/src/mock.rs index c3d032f2eb25..1ea8dddf7eb1 100644 --- a/frame/election-provider-support/solution-type/src/mock.rs +++ b/frame/election-provider-support/src/mock.rs @@ -19,10 +19,16 @@ #![cfg(test)] -use std::{collections::HashMap, convert::TryInto, hash::Hash, HashSet}; +use std::{ + collections::{HashMap, HashSet}, + convert::TryInto, + hash::Hash, +}; use rand::{seq::SliceRandom, Rng}; +pub type AccountId = u64; + /// The candidate mask allows easy disambiguation between voters and candidates: accounts /// for which this bit is set are candidates, and without it, are voters. pub const CANDIDATE_MASK: AccountId = 1 << ((std::mem::size_of::() * 8) - 1); @@ -34,13 +40,14 @@ pub fn p(p: u8) -> TestAccuracy { } pub type MockAssignment = crate::Assignment; -pub type Voter = (AccountId, VoteWeight, Vec); +pub type Voter = (AccountId, crate::VoteWeight, Vec); crate::generate_solution_type! { pub struct TestSolution::< VoterIndex = u32, TargetIndex = u16, Accuracy = TestAccuracy, + MaxVoters = frame_support::traits::ConstU32::<20>, >(16) } diff --git a/frame/election-provider-support/solution-type/src/tests.rs b/frame/election-provider-support/src/tests.rs similarity index 80% rename from frame/election-provider-support/solution-type/src/tests.rs rename to frame/election-provider-support/src/tests.rs index f173e425b518..7b4e46d83617 100644 --- a/frame/election-provider-support/solution-type/src/tests.rs +++ b/frame/election-provider-support/src/tests.rs @@ -20,13 +20,15 @@ #![cfg(test)] use crate::{mock::*, IndexAssignment, NposSolution}; +use frame_support::traits::ConstU32; use rand::SeedableRng; use std::convert::TryInto; mod solution_type { use super::*; - use codec::{Decode, Encode}; - // these need to come from the same dev-dependency `sp-npos-elections`, not from the crate. + use codec::{Decode, Encode, MaxEncodedLen}; + // these need to come from the same dev-dependency `frame-election-provider-support`, not from + // the crate. use crate::{generate_solution_type, Assignment, Error as NposError, NposSolution}; use sp_std::{convert::TryInto, fmt::Debug}; @@ -37,7 +39,12 @@ mod solution_type { use crate::generate_solution_type; generate_solution_type!( #[compact] - struct InnerTestSolutionIsolated::(12) + struct InnerTestSolutionIsolated::< + VoterIndex = u32, + TargetIndex = u8, + Accuracy = sp_runtime::Percent, + MaxVoters = crate::tests::ConstU32::<20>, + >(12) ); } @@ -50,6 +57,7 @@ mod solution_type { VoterIndex = u32, TargetIndex = u32, Accuracy = TestAccuracy, + MaxVoters = ConstU32::<20>, >(16) ); let solution = InnerTestSolution { @@ -68,6 +76,7 @@ mod solution_type { VoterIndex = u32, TargetIndex = u32, Accuracy = TestAccuracy, + MaxVoters = ConstU32::<20>, >(16) ); let compact = InnerTestSolutionCompact { @@ -82,6 +91,75 @@ mod solution_type { assert!(with_compact < without_compact); } + #[test] + fn max_encoded_len_too_small() { + generate_solution_type!( + pub struct InnerTestSolution::< + VoterIndex = u32, + TargetIndex = u32, + Accuracy = TestAccuracy, + MaxVoters = ConstU32::<1>, + >(3) + ); + let solution = InnerTestSolution { + votes1: vec![(2, 20), (4, 40)], + votes2: vec![(1, [(10, p(80))], 11), (5, [(50, p(85))], 51)], + ..Default::default() + }; + + // We actually have 4 voters, but the bound is 1 voter, so the implemented bound is too + // small. + assert!(solution.encode().len() > InnerTestSolution::max_encoded_len()); + } + + #[test] + fn max_encoded_len_upper_bound() { + generate_solution_type!( + pub struct InnerTestSolution::< + VoterIndex = u32, + TargetIndex = u32, + Accuracy = TestAccuracy, + MaxVoters = ConstU32::<4>, + >(3) + ); + let solution = InnerTestSolution { + votes1: vec![(2, 20), (4, 40)], + votes2: vec![(1, [(10, p(80))], 11), (5, [(50, p(85))], 51)], + ..Default::default() + }; + + // We actually have 4 voters, and the bound is 4 voters, so the implemented bound should be + // larger than the encoded len. + assert!(solution.encode().len() < InnerTestSolution::max_encoded_len()); + } + + #[test] + fn max_encoded_len_exact() { + generate_solution_type!( + pub struct InnerTestSolution::< + VoterIndex = u32, + TargetIndex = u32, + Accuracy = TestAccuracy, + MaxVoters = ConstU32::<4>, + >(3) + ); + let solution = InnerTestSolution { + votes1: vec![], + votes2: vec![], + votes3: vec![ + (1, [(10, p(50)), (11, p(20))], 12), + (2, [(20, p(50)), (21, p(20))], 22), + (3, [(30, p(50)), (31, p(20))], 32), + (4, [(40, p(50)), (41, p(20))], 42), + ], + }; + + // We have 4 voters, the bound is 4 voters, and all the voters voted for 3 targets, which is + // the max number of targets. This should represent the upper bound that `max_encoded_len` + // represents. + assert_eq!(solution.encode().len(), InnerTestSolution::max_encoded_len()); + } + #[test] fn solution_struct_is_codec() { let solution = TestSolution { From 7a09b82772b0597cdae224f4b124d660dda9e82b Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Wed, 23 Mar 2022 14:17:26 +0000 Subject: [PATCH 630/695] Store validator self-vote in bags-list, and allow them to be trimmed for election (#10821) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Implement the new validator-in-bags-list scenario + migration * Apply suggestions from code review Co-authored-by: Zeke Mostov * some review comments * guard the migration * some review comments * Fix tests 🤦‍♂️ * Fix build * fix weight_of_fn * reformat line width * make const * use weight of fn cached * SortedListProvider -> VoterList * Fix all build and docs * check post migration Co-authored-by: Zeke Mostov --- bin/node/runtime/src/lib.rs | 4 +- frame/babe/src/mock.rs | 2 +- frame/bags-list/remote-tests/src/lib.rs | 2 +- frame/bags-list/remote-tests/src/migration.rs | 11 +- frame/bags-list/remote-tests/src/snapshot.rs | 5 +- frame/grandpa/src/mock.rs | 2 +- frame/offences/benchmarking/src/mock.rs | 2 +- frame/session/benchmarking/src/mock.rs | 2 +- frame/session/src/migrations/v1.rs | 4 +- frame/staking/src/benchmarking.rs | 50 +++-- frame/staking/src/lib.rs | 3 +- frame/staking/src/migrations.rs | 83 ++++++++- frame/staking/src/mock.rs | 10 +- frame/staking/src/pallet/impls.rs | 176 ++++++++++-------- frame/staking/src/pallet/mod.rs | 35 ++-- frame/staking/src/testing_utils.rs | 4 +- frame/staking/src/tests.rs | 114 ++++++------ 17 files changed, 305 insertions(+), 204 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index b7137de48fb1..a6d97cb299b2 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -558,9 +558,7 @@ impl pallet_staking::Config for Runtime { type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type ElectionProvider = ElectionProviderMultiPhase; type GenesisElectionProvider = onchain::OnChainSequentialPhragmen; - // Alternatively, use pallet_staking::UseNominatorsMap to just use the nominators map. - // Note that the aforementioned does not scale to a very large number of nominators. - type SortedListProvider = BagsList; + type VoterList = BagsList; type MaxUnlockingChunks = ConstU32<32>; type WeightInfo = pallet_staking::weights::SubstrateWeight; type BenchmarkingConfig = StakingBenchmarkingConfig; diff --git a/frame/babe/src/mock.rs b/frame/babe/src/mock.rs index 152ec5ab206e..e74288577c9e 100644 --- a/frame/babe/src/mock.rs +++ b/frame/babe/src/mock.rs @@ -197,7 +197,7 @@ impl pallet_staking::Config for Test { type NextNewSession = Session; type ElectionProvider = onchain::OnChainSequentialPhragmen; type GenesisElectionProvider = Self::ElectionProvider; - type SortedListProvider = pallet_staking::UseNominatorsMap; + type VoterList = pallet_staking::UseNominatorsAndValidatorsMap; type MaxUnlockingChunks = ConstU32<32>; type BenchmarkingConfig = pallet_staking::TestBenchmarkingConfig; type WeightInfo = (); diff --git a/frame/bags-list/remote-tests/src/lib.rs b/frame/bags-list/remote-tests/src/lib.rs index 83c322f93134..caf7a2a547e0 100644 --- a/frame/bags-list/remote-tests/src/lib.rs +++ b/frame/bags-list/remote-tests/src/lib.rs @@ -48,7 +48,7 @@ pub fn display_and_check_bags(currency_unit: u64, currency_na let min_nominator_bond = >::get(); log::info!(target: LOG_TARGET, "min nominator bond is {:?}", min_nominator_bond); - let voter_list_count = ::SortedListProvider::count(); + let voter_list_count = ::VoterList::count(); // go through every bag to track the total number of voters within bags and log some info about // how voters are distributed within the bags. diff --git a/frame/bags-list/remote-tests/src/migration.rs b/frame/bags-list/remote-tests/src/migration.rs index 4d5169fcc6df..c4cd73c45d37 100644 --- a/frame/bags-list/remote-tests/src/migration.rs +++ b/frame/bags-list/remote-tests/src/migration.rs @@ -17,7 +17,6 @@ //! Test to check the migration of the voter bag. use crate::{RuntimeT, LOG_TARGET}; -use frame_election_provider_support::SortedListProvider; use frame_support::traits::PalletInfoAccess; use pallet_staking::Nominators; use remote_externalities::{Builder, Mode, OnlineConfig}; @@ -45,16 +44,16 @@ pub async fn execute( let pre_migrate_nominator_count = >::iter().count() as u32; log::info!(target: LOG_TARGET, "Nominator count: {}", pre_migrate_nominator_count); - // run the actual migration, - let moved = ::SortedListProvider::unsafe_regenerate( + use frame_election_provider_support::SortedListProvider; + // run the actual migration + let moved = ::VoterList::unsafe_regenerate( pallet_staking::Nominators::::iter().map(|(n, _)| n), pallet_staking::Pallet::::weight_of_fn(), ); log::info!(target: LOG_TARGET, "Moved {} nominators", moved); - let voter_list_len = - ::SortedListProvider::iter().count() as u32; - let voter_list_count = ::SortedListProvider::count(); + let voter_list_len = ::VoterList::iter().count() as u32; + let voter_list_count = ::VoterList::count(); // and confirm it is equal to the length of the `VoterList`. assert_eq!(pre_migrate_nominator_count, voter_list_len); assert_eq!(pre_migrate_nominator_count, voter_list_count); diff --git a/frame/bags-list/remote-tests/src/snapshot.rs b/frame/bags-list/remote-tests/src/snapshot.rs index 2d996746a29c..408f5f2bd8aa 100644 --- a/frame/bags-list/remote-tests/src/snapshot.rs +++ b/frame/bags-list/remote-tests/src/snapshot.rs @@ -16,6 +16,7 @@ //! Test to execute the snapshot using the voter bag. +use frame_election_provider_support::SortedListProvider; use frame_support::traits::PalletInfoAccess; use remote_externalities::{Builder, Mode, OnlineConfig}; use sp_runtime::{traits::Block as BlockT, DeserializeOwned}; @@ -48,11 +49,11 @@ pub async fn execute .unwrap(); ext.execute_with(|| { - use frame_election_provider_support::{ElectionDataProvider, SortedListProvider}; + use frame_election_provider_support::ElectionDataProvider; log::info!( target: crate::LOG_TARGET, "{} nodes in bags list.", - ::SortedListProvider::count(), + ::VoterList::count(), ); let voters = diff --git a/frame/grandpa/src/mock.rs b/frame/grandpa/src/mock.rs index 9dac33f97984..6490a2b6992b 100644 --- a/frame/grandpa/src/mock.rs +++ b/frame/grandpa/src/mock.rs @@ -205,7 +205,7 @@ impl pallet_staking::Config for Test { type NextNewSession = Session; type ElectionProvider = onchain::OnChainSequentialPhragmen; type GenesisElectionProvider = Self::ElectionProvider; - type SortedListProvider = pallet_staking::UseNominatorsMap; + type VoterList = pallet_staking::UseNominatorsAndValidatorsMap; type MaxUnlockingChunks = ConstU32<32>; type BenchmarkingConfig = pallet_staking::TestBenchmarkingConfig; type WeightInfo = (); diff --git a/frame/offences/benchmarking/src/mock.rs b/frame/offences/benchmarking/src/mock.rs index 22c9af0f4c3c..4359b7745ddd 100644 --- a/frame/offences/benchmarking/src/mock.rs +++ b/frame/offences/benchmarking/src/mock.rs @@ -175,7 +175,7 @@ impl pallet_staking::Config for Test { type OffendingValidatorsThreshold = (); type ElectionProvider = onchain::OnChainSequentialPhragmen; type GenesisElectionProvider = Self::ElectionProvider; - type SortedListProvider = pallet_staking::UseNominatorsMap; + type VoterList = pallet_staking::UseNominatorsAndValidatorsMap; type MaxUnlockingChunks = ConstU32<32>; type BenchmarkingConfig = pallet_staking::TestBenchmarkingConfig; type WeightInfo = (); diff --git a/frame/session/benchmarking/src/mock.rs b/frame/session/benchmarking/src/mock.rs index a9328b6546c9..5ebc75245630 100644 --- a/frame/session/benchmarking/src/mock.rs +++ b/frame/session/benchmarking/src/mock.rs @@ -182,7 +182,7 @@ impl pallet_staking::Config for Test { type ElectionProvider = onchain::OnChainSequentialPhragmen; type GenesisElectionProvider = Self::ElectionProvider; type MaxUnlockingChunks = ConstU32<32>; - type SortedListProvider = pallet_staking::UseNominatorsMap; + type VoterList = pallet_staking::UseNominatorsAndValidatorsMap; type BenchmarkingConfig = pallet_staking::TestBenchmarkingConfig; type WeightInfo = (); } diff --git a/frame/session/src/migrations/v1.rs b/frame/session/src/migrations/v1.rs index 2a69cd6d6a55..3c687ea7d9d6 100644 --- a/frame/session/src/migrations/v1.rs +++ b/frame/session/src/migrations/v1.rs @@ -87,7 +87,7 @@ pub fn migrate ListScenario { /// - the destination bag has at least one node, which will need its next pointer updated. /// /// NOTE: while this scenario specifically targets a worst case for the bags-list, it should - /// also elicit a worst case for other known `SortedListProvider` implementations; although - /// this may not be true against unknown `SortedListProvider` implementations. + /// also elicit a worst case for other known `VoterList` implementations; although + /// this may not be true against unknown `VoterList` implementations. fn new(origin_weight: BalanceOf, is_increase: bool) -> Result { ensure!(!origin_weight.is_zero(), "origin weight must be greater than 0"); @@ -189,7 +189,7 @@ impl ListScenario { // find a destination weight that will trigger the worst case scenario let dest_weight_as_vote = - T::SortedListProvider::score_update_worst_case(&origin_stash1, is_increase); + T::VoterList::score_update_worst_case(&origin_stash1, is_increase); let total_issuance = T::Currency::total_issuance(); @@ -316,7 +316,7 @@ benchmarks! { let scenario = ListScenario::::new(origin_weight, true)?; let controller = scenario.origin_controller1.clone(); let stash = scenario.origin_stash1.clone(); - assert!(T::SortedListProvider::contains(&stash)); + assert!(T::VoterList::contains(&stash)); let ed = T::Currency::minimum_balance(); let mut ledger = Ledger::::get(&controller).unwrap(); @@ -328,28 +328,24 @@ benchmarks! { }: withdraw_unbonded(RawOrigin::Signed(controller.clone()), s) verify { assert!(!Ledger::::contains_key(controller)); - assert!(!T::SortedListProvider::contains(&stash)); + assert!(!T::VoterList::contains(&stash)); } validate { - // clean up any existing state. - clear_validators_and_nominators::(); - - let origin_weight = MinNominatorBond::::get().max(T::Currency::minimum_balance()); - - // setup a worst case scenario where the user calling validate was formerly a nominator so - // they must be removed from the list. - let scenario = ListScenario::::new(origin_weight, true)?; - let controller = scenario.origin_controller1.clone(); - let stash = scenario.origin_stash1.clone(); - assert!(T::SortedListProvider::contains(&stash)); + let (stash, controller) = create_stash_controller::( + T::MaxNominations::get() - 1, + 100, + Default::default(), + )?; + // because it is chilled. + assert!(!T::VoterList::contains(&stash)); let prefs = ValidatorPrefs::default(); whitelist_account!(controller); }: _(RawOrigin::Signed(controller), prefs) verify { assert!(Validators::::contains_key(&stash)); - assert!(!T::SortedListProvider::contains(&stash)); + assert!(T::VoterList::contains(&stash)); } kick { @@ -434,14 +430,14 @@ benchmarks! { ).unwrap(); assert!(!Nominators::::contains_key(&stash)); - assert!(!T::SortedListProvider::contains(&stash)); + assert!(!T::VoterList::contains(&stash)); let validators = create_validators::(n, 100).unwrap(); whitelist_account!(controller); }: _(RawOrigin::Signed(controller), validators) verify { assert!(Nominators::::contains_key(&stash)); - assert!(T::SortedListProvider::contains(&stash)) + assert!(T::VoterList::contains(&stash)) } chill { @@ -455,12 +451,12 @@ benchmarks! { let scenario = ListScenario::::new(origin_weight, true)?; let controller = scenario.origin_controller1.clone(); let stash = scenario.origin_stash1.clone(); - assert!(T::SortedListProvider::contains(&stash)); + assert!(T::VoterList::contains(&stash)); whitelist_account!(controller); }: _(RawOrigin::Signed(controller)) verify { - assert!(!T::SortedListProvider::contains(&stash)); + assert!(!T::VoterList::contains(&stash)); } set_payee { @@ -523,13 +519,13 @@ benchmarks! { let scenario = ListScenario::::new(origin_weight, true)?; let controller = scenario.origin_controller1.clone(); let stash = scenario.origin_stash1.clone(); - assert!(T::SortedListProvider::contains(&stash)); + assert!(T::VoterList::contains(&stash)); add_slashing_spans::(&stash, s); }: _(RawOrigin::Root, stash.clone(), s) verify { assert!(!Ledger::::contains_key(&controller)); - assert!(!T::SortedListProvider::contains(&stash)); + assert!(!T::VoterList::contains(&stash)); } cancel_deferred_slash { @@ -708,13 +704,13 @@ benchmarks! { Ledger::::insert(&controller, l); assert!(Bonded::::contains_key(&stash)); - assert!(T::SortedListProvider::contains(&stash)); + assert!(T::VoterList::contains(&stash)); whitelist_account!(controller); }: _(RawOrigin::Signed(controller), stash.clone(), s) verify { assert!(!Bonded::::contains_key(&stash)); - assert!(!T::SortedListProvider::contains(&stash)); + assert!(!T::VoterList::contains(&stash)); } new_era { @@ -899,7 +895,7 @@ benchmarks! { let scenario = ListScenario::::new(origin_weight, true)?; let controller = scenario.origin_controller1.clone(); let stash = scenario.origin_stash1.clone(); - assert!(T::SortedListProvider::contains(&stash)); + assert!(T::VoterList::contains(&stash)); Staking::::set_staking_configs( RawOrigin::Root.into(), @@ -914,7 +910,7 @@ benchmarks! { let caller = whitelisted_caller(); }: _(RawOrigin::Signed(caller), controller.clone()) verify { - assert!(!T::SortedListProvider::contains(&stash)); + assert!(!T::VoterList::contains(&stash)); } force_apply_min_commission { diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 4c1bb438457e..2a0716721dd5 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -780,7 +780,8 @@ enum Releases { V5_0_0, // blockable validators. V6_0_0, // removal of all storage associated with offchain phragmen. V7_0_0, // keep track of number of nominators / validators in map - V8_0_0, // populate `SortedListProvider`. + V8_0_0, // populate `VoterList`. + V9_0_0, // inject validators into `VoterList` as well. } impl Default for Releases { diff --git a/frame/staking/src/migrations.rs b/frame/staking/src/migrations.rs index 3991c4a66076..96c905f4e594 100644 --- a/frame/staking/src/migrations.rs +++ b/frame/staking/src/migrations.rs @@ -17,13 +17,83 @@ //! Storage migrations for the Staking pallet. use super::*; +use frame_election_provider_support::SortedListProvider; +use frame_support::traits::OnRuntimeUpgrade; + +pub mod v9 { + use super::*; + + /// Migration implementation that injects all validators into sorted list. + /// + /// This is only useful for chains that started their `VoterList` just based on nominators. + pub struct InjectValidatorsIntoVoterList(sp_std::marker::PhantomData); + impl OnRuntimeUpgrade for InjectValidatorsIntoVoterList { + fn on_runtime_upgrade() -> Weight { + if StorageVersion::::get() == Releases::V8_0_0 { + let prev_count = T::VoterList::count(); + let weight_of_cached = Pallet::::weight_of_fn(); + for (v, _) in Validators::::iter() { + let weight = weight_of_cached(&v); + let _ = T::VoterList::on_insert(v.clone(), weight).map_err(|err| { + log!(warn, "failed to insert {:?} into VoterList: {:?}", v, err) + }); + } + + log!( + info, + "injected a total of {} new voters, prev count: {} next count: {}, updating to version 9", + Validators::::count(), + prev_count, + T::VoterList::count(), + ); + + StorageVersion::::put(crate::Releases::V9_0_0); + T::BlockWeights::get().max_block + } else { + log!( + warn, + "InjectValidatorsIntoVoterList being executed on the wrong storage \ + version, expected Releases::V8_0_0" + ); + T::DbWeight::get().reads(1) + } + } + + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result<(), &'static str> { + use frame_support::traits::OnRuntimeUpgradeHelpersExt; + frame_support::ensure!( + StorageVersion::::get() == crate::Releases::V8_0_0, + "must upgrade linearly" + ); + + let prev_count = T::VoterList::count(); + Self::set_temp_storage(prev_count, "prev"); + Ok(()) + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade() -> Result<(), &'static str> { + use frame_support::traits::OnRuntimeUpgradeHelpersExt; + let post_count = T::VoterList::count(); + let prev_count = Self::get_temp_storage::("prev").unwrap(); + let validators = Validators::::count(); + assert!(post_count == prev_count + validators); + + frame_support::ensure!( + StorageVersion::::get() == crate::Releases::V9_0_0, + "must upgrade " + ); + Ok(()) + } + } +} pub mod v8 { + use crate::{Config, Nominators, Pallet, StorageVersion, Weight}; use frame_election_provider_support::SortedListProvider; use frame_support::traits::Get; - use crate::{Config, Nominators, Pallet, StorageVersion, Weight}; - #[cfg(feature = "try-runtime")] pub fn pre_migrate() -> Result<(), &'static str> { frame_support::ensure!( @@ -35,16 +105,16 @@ pub mod v8 { Ok(()) } - /// Migration to sorted [`SortedListProvider`]. + /// Migration to sorted `VoterList`. pub fn migrate() -> Weight { if StorageVersion::::get() == crate::Releases::V7_0_0 { crate::log!(info, "migrating staking to Releases::V8_0_0"); - let migrated = T::SortedListProvider::unsafe_regenerate( + let migrated = T::VoterList::unsafe_regenerate( Nominators::::iter().map(|(id, _)| id), Pallet::::weight_of_fn(), ); - debug_assert_eq!(T::SortedListProvider::sanity_check(), Ok(())); + debug_assert_eq!(T::VoterList::sanity_check(), Ok(())); StorageVersion::::put(crate::Releases::V8_0_0); crate::log!( @@ -61,8 +131,7 @@ pub mod v8 { #[cfg(feature = "try-runtime")] pub fn post_migrate() -> Result<(), &'static str> { - T::SortedListProvider::sanity_check() - .map_err(|_| "SortedListProvider is not in a sane state.")?; + T::VoterList::sanity_check().map_err(|_| "VoterList is not in a sane state.")?; crate::log!(info, "👜 staking bags-list migration passes POST migrate checks ✅",); Ok(()) } diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index 843791a46ade..bb71232c3467 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -270,8 +270,8 @@ impl crate::pallet::pallet::Config for Test { type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type ElectionProvider = onchain::OnChainSequentialPhragmen; type GenesisElectionProvider = Self::ElectionProvider; - // NOTE: consider a macro and use `UseNominatorsMap` as well. - type SortedListProvider = BagsList; + // NOTE: consider a macro and use `UseNominatorsAndValidatorsMap` as well. + type VoterList = BagsList; type MaxUnlockingChunks = ConstU32<32>; type BenchmarkingConfig = TestBenchmarkingConfig; type WeightInfo = (); @@ -541,9 +541,9 @@ fn check_count() { assert_eq!(nominator_count, Nominators::::count()); assert_eq!(validator_count, Validators::::count()); - // the voters that the `SortedListProvider` list is storing for us. - let external_voters = ::SortedListProvider::count(); - assert_eq!(external_voters, nominator_count); + // the voters that the `VoterList` list is storing for us. + let external_voters = ::VoterList::count(); + assert_eq!(external_voters, nominator_count + validator_count); } fn check_ledgers() { diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index cb024ba2bc52..9d5a3ed48418 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -49,6 +49,14 @@ use crate::{ use super::{pallet::*, STAKING_ID}; +/// The maximum number of iterations that we do whilst iterating over `T::VoterList` in +/// `get_npos_voters`. +/// +/// In most cases, if we want n items, we iterate exactly n times. In rare cases, if a voter is +/// invalid (for any reason) the iteration continues. With this constant, we iterate at most 2 * n +/// times and then give up. +const NPOS_MAX_ITERATIONS_COEFFICIENT: u32 = 2; + impl Pallet { /// The total balance that can be slashed from a stash account as of right now. pub fn slashable_balance_of(stash: &T::AccountId) -> BalanceOf { @@ -649,90 +657,77 @@ impl Pallet { /// Get all of the voters that are eligible for the npos election. /// - /// `maybe_max_len` can imposes a cap on the number of voters returned; First all the validator - /// are included in no particular order, then remainder is taken from the nominators, as - /// returned by [`Config::SortedListProvider`]. - /// - /// This will use nominators, and all the validators will inject a self vote. + /// `maybe_max_len` can imposes a cap on the number of voters returned; /// /// This function is self-weighing as [`DispatchClass::Mandatory`]. /// /// ### Slashing /// - /// All nominations that have been submitted before the last non-zero slash of the validator are - /// auto-chilled, but still count towards the limit imposed by `maybe_max_len`. + /// All votes that have been submitted before the last non-zero slash of the corresponding + /// target are *auto-chilled*, but still count towards the limit imposed by `maybe_max_len`. pub fn get_npos_voters(maybe_max_len: Option) -> Vec> { let max_allowed_len = { - let nominator_count = Nominators::::count() as usize; - let validator_count = Validators::::count() as usize; - let all_voter_count = validator_count.saturating_add(nominator_count); + let all_voter_count = T::VoterList::count() as usize; maybe_max_len.unwrap_or(all_voter_count).min(all_voter_count) }; let mut all_voters = Vec::<_>::with_capacity(max_allowed_len); - // first, grab all validators in no particular order, capped by the maximum allowed length. - let mut validators_taken = 0u32; - for (validator, _) in >::iter().take(max_allowed_len) { - // Append self vote. - let self_vote = ( - validator.clone(), - Self::weight_of(&validator), - vec![validator.clone()] - .try_into() - .expect("`MaxVotesPerVoter` must be greater than or equal to 1"), - ); - all_voters.push(self_vote); - validators_taken.saturating_inc(); - } - - // .. and grab whatever we have left from nominators. - let nominators_quota = (max_allowed_len as u32).saturating_sub(validators_taken); + // cache a few things. + let weight_of = Self::weight_of_fn(); let slashing_spans = >::iter().collect::>(); - // track the count of nominators added to `all_voters + let mut voters_seen = 0u32; + let mut validators_taken = 0u32; let mut nominators_taken = 0u32; - // track every nominator iterated over, but not necessarily added to `all_voters` - let mut nominators_seen = 0u32; - // cache the total-issuance once in this function - let weight_of = Self::weight_of_fn(); - - let mut nominators_iter = T::SortedListProvider::iter(); - while nominators_taken < nominators_quota && nominators_seen < nominators_quota * 2 { - let nominator = match nominators_iter.next() { - Some(nominator) => { - nominators_seen.saturating_inc(); - nominator + let mut sorted_voters = T::VoterList::iter(); + while all_voters.len() < max_allowed_len && + voters_seen < (NPOS_MAX_ITERATIONS_COEFFICIENT * max_allowed_len as u32) + { + let voter = match sorted_voters.next() { + Some(voter) => { + voters_seen.saturating_inc(); + voter }, None => break, }; if let Some(Nominations { submitted_in, mut targets, suppressed: _ }) = - >::get(&nominator) + >::get(&voter) { - log!( - trace, - "fetched nominator {:?} with weight {:?}", - nominator, - weight_of(&nominator) - ); + // if this voter is a nominator: targets.retain(|stash| { slashing_spans .get(stash) .map_or(true, |spans| submitted_in >= spans.last_nonzero_slash()) }); if !targets.len().is_zero() { - all_voters.push((nominator.clone(), weight_of(&nominator), targets)); + all_voters.push((voter.clone(), weight_of(&voter), targets)); nominators_taken.saturating_inc(); } + } else if Validators::::contains_key(&voter) { + // if this voter is a validator: + let self_vote = ( + voter.clone(), + weight_of(&voter), + vec![voter.clone()] + .try_into() + .expect("`MaxVotesPerVoter` must be greater than or equal to 1"), + ); + all_voters.push(self_vote); + validators_taken.saturating_inc(); } else { - // this can only happen if: 1. there a pretty bad bug in the bags-list (or whatever - // is the sorted list) logic and the state of the two pallets is no longer - // compatible, or because the nominators is not decodable since they have more - // nomination than `T::MaxNominations`. This can rarely happen, and is not really an - // emergency or bug if it does. - log!(warn, "DEFENSIVE: invalid item in `SortedListProvider`: {:?}, this nominator probably has too many nominations now", nominator) + // this can only happen if: 1. there a bug in the bags-list (or whatever is the + // sorted list) logic and the state of the two pallets is no longer compatible, or + // because the nominators is not decodable since they have more nomination than + // `T::MaxNominations`. The latter can rarely happen, and is not really an emergency + // or bug if it does. + log!( + warn, + "DEFENSIVE: invalid item in `VoterList`: {:?}, this nominator probably has too many nominations now", + voter + ) } } @@ -752,6 +747,7 @@ impl Pallet { validators_taken, nominators_taken ); + all_voters } @@ -773,7 +769,7 @@ impl Pallet { } /// This function will add a nominator to the `Nominators` storage map, - /// and [`SortedListProvider`]. + /// and `VoterList`. /// /// If the nominator already exists, their nominations will be updated. /// @@ -782,18 +778,21 @@ impl Pallet { /// wrong. pub fn do_add_nominator(who: &T::AccountId, nominations: Nominations) { if !Nominators::::contains_key(who) { - // maybe update sorted list. Error checking is defensive-only - this should never fail. - let _ = T::SortedListProvider::on_insert(who.clone(), Self::weight_of(who)) + // maybe update sorted list. + let _ = T::VoterList::on_insert(who.clone(), Self::weight_of(who)) .defensive_unwrap_or_default(); - - debug_assert_eq!(T::SortedListProvider::sanity_check(), Ok(())); } - Nominators::::insert(who, nominations); + + debug_assert_eq!( + Nominators::::count() + Validators::::count(), + T::VoterList::count() + ); + debug_assert_eq!(T::VoterList::sanity_check(), Ok(())); } /// This function will remove a nominator from the `Nominators` storage map, - /// and [`SortedListProvider`]. + /// and `VoterList`. /// /// Returns true if `who` was removed from `Nominators`, otherwise false. /// @@ -801,15 +800,21 @@ impl Pallet { /// `Nominators` or `VoterList` outside of this function is almost certainly /// wrong. pub fn do_remove_nominator(who: &T::AccountId) -> bool { - if Nominators::::contains_key(who) { + let outcome = if Nominators::::contains_key(who) { Nominators::::remove(who); - T::SortedListProvider::on_remove(who); - debug_assert_eq!(T::SortedListProvider::sanity_check(), Ok(())); - debug_assert_eq!(Nominators::::count(), T::SortedListProvider::count()); + T::VoterList::on_remove(who); true } else { false - } + }; + + debug_assert_eq!(T::VoterList::sanity_check(), Ok(())); + debug_assert_eq!( + Nominators::::count() + Validators::::count(), + T::VoterList::count() + ); + + outcome } /// This function will add a validator to the `Validators` storage map. @@ -820,7 +825,18 @@ impl Pallet { /// `Validators` or `VoterList` outside of this function is almost certainly /// wrong. pub fn do_add_validator(who: &T::AccountId, prefs: ValidatorPrefs) { + if !Validators::::contains_key(who) { + // maybe update sorted list. + let _ = T::VoterList::on_insert(who.clone(), Self::weight_of(who)) + .defensive_unwrap_or_default(); + } Validators::::insert(who, prefs); + + debug_assert_eq!( + Nominators::::count() + Validators::::count(), + T::VoterList::count() + ); + debug_assert_eq!(T::VoterList::sanity_check(), Ok(())); } /// This function will remove a validator from the `Validators` storage map. @@ -831,12 +847,21 @@ impl Pallet { /// `Validators` or `VoterList` outside of this function is almost certainly /// wrong. pub fn do_remove_validator(who: &T::AccountId) -> bool { - if Validators::::contains_key(who) { + let outcome = if Validators::::contains_key(who) { Validators::::remove(who); + T::VoterList::on_remove(who); true } else { false - } + }; + + debug_assert_eq!(T::VoterList::sanity_check(), Ok(())); + debug_assert_eq!( + Nominators::::count() + Validators::::count(), + T::VoterList::count() + ); + + outcome } /// Register some amount of weight directly with the system pallet. @@ -963,7 +988,7 @@ impl ElectionDataProvider for Pallet { >::remove_all(); >::remove_all(); - T::SortedListProvider::unsafe_clear(); + T::VoterList::unsafe_clear(); } #[cfg(feature = "runtime-benchmarks")] @@ -1278,20 +1303,24 @@ impl ScoreProvider for Pallet { /// A simple voter list implementation that does not require any additional pallets. Note, this /// does not provided nominators in sorted ordered. If you desire nominators in a sorted order take /// a look at [`pallet-bags-list]. -pub struct UseNominatorsMap(sp_std::marker::PhantomData); -impl SortedListProvider for UseNominatorsMap { +pub struct UseNominatorsAndValidatorsMap(sp_std::marker::PhantomData); +impl SortedListProvider for UseNominatorsAndValidatorsMap { type Error = (); type Score = VoteWeight; /// Returns iterator over voter list, which can have `take` called on it. fn iter() -> Box> { - Box::new(Nominators::::iter().map(|(n, _)| n)) + Box::new( + Validators::::iter() + .map(|(v, _)| v) + .chain(Nominators::::iter().map(|(n, _)| n)), + ) } fn count() -> u32 { - Nominators::::count() + Nominators::::count().saturating_add(Validators::::count()) } fn contains(id: &T::AccountId) -> bool { - Nominators::::contains_key(id) + Nominators::::contains_key(id) || Validators::::contains_key(id) } fn on_insert(_: T::AccountId, _weight: Self::Score) -> Result<(), Self::Error> { // nothing to do on insert. @@ -1318,5 +1347,6 @@ impl SortedListProvider for UseNominatorsMap { // NOTE: Caller must ensure this doesn't lead to too many storage accesses. This is a // condition of SortedListProvider::unsafe_clear. Nominators::::remove_all(); + Validators::::remove_all(); } } diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 39173bf61c83..306bd34390d8 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -17,7 +17,7 @@ //! Staking FRAME Pallet. -use frame_election_provider_support::SortedListProvider; +use frame_election_provider_support::{SortedListProvider, VoteWeight}; use frame_support::{ dispatch::Codec, pallet_prelude::*, @@ -163,13 +163,12 @@ pub mod pallet { /// After the threshold is reached a new era will be forced. type OffendingValidatorsThreshold: Get; - /// Something that can provide a sorted list of voters in a somewhat sorted way. The - /// original use case for this was designed with `pallet_bags_list::Pallet` in mind. If - /// the bags-list is not desired, [`impls::UseNominatorsMap`] is likely the desired option. - type SortedListProvider: SortedListProvider< - Self::AccountId, - Score = frame_election_provider_support::VoteWeight, - >; + /// Something that provides a best-effort sorted list of voters aka electing nominators, + /// used for NPoS election. + /// + /// The changes to nominators are reported to this. Moreover, each validator's self-vote is + /// also reported as one independent vote. + type VoterList: SortedListProvider; /// The maximum number of `unlocking` chunks a [`StakingLedger`] can have. Effectively /// determines how many unique eras a staker may be unbonding in. @@ -584,10 +583,10 @@ pub mod pallet { }); } - // all voters are reported to the `SortedListProvider`. + // all voters are reported to the `VoterList`. assert_eq!( - T::SortedListProvider::count(), - Nominators::::count(), + T::VoterList::count(), + Nominators::::count() + Validators::::count(), "not all genesis stakers were inserted into sorted list provider, something is wrong." ); } @@ -837,9 +836,9 @@ pub mod pallet { // NOTE: ledger must be updated prior to calling `Self::weight_of`. Self::update_ledger(&controller, &ledger); // update this staker in the sorted list, if they exist in it. - if T::SortedListProvider::contains(&stash) { - T::SortedListProvider::on_update(&stash, Self::weight_of(&ledger.stash)); - debug_assert_eq!(T::SortedListProvider::sanity_check(), Ok(())); + if T::VoterList::contains(&stash) { + T::VoterList::on_update(&stash, Self::weight_of(&ledger.stash)); + debug_assert_eq!(T::VoterList::sanity_check(), Ok(())); } Self::deposit_event(Event::::Bonded(stash.clone(), extra)); @@ -920,8 +919,8 @@ pub mod pallet { Self::update_ledger(&controller, &ledger); // update this staker in the sorted list, if they exist in it. - if T::SortedListProvider::contains(&ledger.stash) { - T::SortedListProvider::on_update(&ledger.stash, Self::weight_of(&ledger.stash)); + if T::VoterList::contains(&ledger.stash) { + T::VoterList::on_update(&ledger.stash, Self::weight_of(&ledger.stash)); } Self::deposit_event(Event::::Unbonded(ledger.stash, value)); @@ -1403,8 +1402,8 @@ pub mod pallet { // NOTE: ledger must be updated prior to calling `Self::weight_of`. Self::update_ledger(&controller, &ledger); - if T::SortedListProvider::contains(&ledger.stash) { - T::SortedListProvider::on_update(&ledger.stash, Self::weight_of(&ledger.stash)); + if T::VoterList::contains(&ledger.stash) { + T::VoterList::on_update(&ledger.stash, Self::weight_of(&ledger.stash)); } let removed_chunks = 1u32 // for the case where the last iterated chunk is not removed diff --git a/frame/staking/src/testing_utils.rs b/frame/staking/src/testing_utils.rs index 8e6bd8846893..5f9f378b1061 100644 --- a/frame/staking/src/testing_utils.rs +++ b/frame/staking/src/testing_utils.rs @@ -38,11 +38,11 @@ const SEED: u32 = 0; pub fn clear_validators_and_nominators() { Validators::::remove_all(); - // whenever we touch nominators counter we should update `T::SortedListProvider` as well. + // whenever we touch nominators counter we should update `T::VoterList` as well. Nominators::::remove_all(); // NOTE: safe to call outside block production - T::SortedListProvider::unsafe_clear(); + T::VoterList::unsafe_clear(); } /// Grab a funded user. diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 2d4145242a45..11dfe3e4777f 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -4113,11 +4113,7 @@ mod election_data_provider { .set_status(41, StakerStatus::Validator) .build_and_execute(|| { // sum of all nominators who'd be voters (1), plus the self-votes (4). - assert_eq!( - ::SortedListProvider::count() + - >::iter().count() as u32, - 5 - ); + assert_eq!(::VoterList::count(), 5); // if limits is less.. assert_eq!(Staking::electing_voters(Some(1)).unwrap().len(), 1); @@ -4140,43 +4136,43 @@ mod election_data_provider { }); } + // Tests the criteria that in `ElectionDataProvider::voters` function, we try to get at most + // `maybe_max_len` voters, and if some of them end up being skipped, we iterate at most `2 * + // maybe_max_len`. #[test] - fn only_iterates_max_2_times_nominators_quota() { + fn only_iterates_max_2_times_max_allowed_len() { ExtBuilder::default() - .nominate(true) // add nominator 101, who nominates [11, 21] + .nominate(false) // the other nominators only nominate 21 .add_staker(61, 60, 2_000, StakerStatus::::Nominator(vec![21])) .add_staker(71, 70, 2_000, StakerStatus::::Nominator(vec![21])) .add_staker(81, 80, 2_000, StakerStatus::::Nominator(vec![21])) .build_and_execute(|| { - // given our nominators ordered by stake, - assert_eq!( - ::SortedListProvider::iter().collect::>(), - vec![61, 71, 81, 101] - ); - - // and total voters + // all voters ordered by stake, assert_eq!( - ::SortedListProvider::count() + - >::iter().count() as u32, - 7 + ::VoterList::iter().collect::>(), + vec![61, 71, 81, 11, 21, 31] ); - // roll to session 5 run_to_block(25); // slash 21, the only validator nominated by our first 3 nominators add_slash(&21); - // we take 4 voters: 2 validators and 2 nominators (so nominators quota = 2) + // we want 2 voters now, and in maximum we allow 4 iterations. This is what happens: + // 61 is pruned; + // 71 is pruned; + // 81 is pruned; + // 11 is taken; + // we finish since the 2x limit is reached. assert_eq!( - Staking::electing_voters(Some(3)) + Staking::electing_voters(Some(2)) .unwrap() .iter() .map(|(stash, _, _)| stash) .copied() .collect::>(), - vec![31, 11], // 2 validators, but no nominators because we hit the quota + vec![11], ); }); } @@ -4189,46 +4185,35 @@ mod election_data_provider { #[test] fn get_max_len_voters_even_if_some_nominators_are_slashed() { ExtBuilder::default() - .nominate(true) // add nominator 101, who nominates [11, 21] + .nominate(false) .add_staker(61, 60, 20, StakerStatus::::Nominator(vec![21])) - // 61 only nominates validator 21 ^^ .add_staker(71, 70, 10, StakerStatus::::Nominator(vec![11, 21])) + .add_staker(81, 80, 10, StakerStatus::::Nominator(vec![11, 21])) .build_and_execute(|| { - // given our nominators ordered by stake, + // given our voters ordered by stake, assert_eq!( - ::SortedListProvider::iter().collect::>(), - vec![101, 61, 71] + ::VoterList::iter().collect::>(), + vec![11, 21, 31, 61, 71, 81] ); - // and total voters - assert_eq!( - ::SortedListProvider::count() + - >::iter().count() as u32, - 6 - ); - - // we take 5 voters + // we take 4 voters assert_eq!( - Staking::electing_voters(Some(5)) + Staking::electing_voters(Some(4)) .unwrap() .iter() .map(|(stash, _, _)| stash) .copied() .collect::>(), - // then - vec![ - 31, 21, 11, // 3 nominators - 101, 61 // 2 validators, and 71 is excluded - ], + vec![11, 21, 31, 61], ); // roll to session 5 run_to_block(25); - // slash 21, the only validator nominated by 61 + // slash 21, the only validator nominated by 61. add_slash(&21); - // we take 4 voters + // we take 4 voters; 71 and 81 are replacing the ejected ones. assert_eq!( Staking::electing_voters(Some(4)) .unwrap() @@ -4236,10 +4221,7 @@ mod election_data_provider { .map(|(stash, _, _)| stash) .copied() .collect::>(), - vec![ - 31, 11, // 2 validators (21 was slashed) - 101, 71 // 2 nominators, excluding 61 - ], + vec![11, 31, 71, 81], ); }); } @@ -4755,19 +4737,45 @@ mod sorted_list_provider { fn re_nominate_does_not_change_counters_or_list() { ExtBuilder::default().nominate(true).build_and_execute(|| { // given - let pre_insert_nominator_count = Nominators::::iter().count() as u32; - assert_eq!(::SortedListProvider::count(), pre_insert_nominator_count); - assert!(Nominators::::contains_key(101)); - assert_eq!(::SortedListProvider::iter().collect::>(), vec![101]); + let pre_insert_voter_count = + (Nominators::::count() + Validators::::count()) as u32; + assert_eq!(::VoterList::count(), pre_insert_voter_count); + + assert_eq!( + ::VoterList::iter().collect::>(), + vec![11, 21, 31, 101] + ); // when account 101 renominates assert_ok!(Staking::nominate(Origin::signed(100), vec![41])); // then counts don't change - assert_eq!(::SortedListProvider::count(), pre_insert_nominator_count); - assert_eq!(Nominators::::iter().count() as u32, pre_insert_nominator_count); + assert_eq!(::VoterList::count(), pre_insert_voter_count); + // and the list is the same + assert_eq!( + ::VoterList::iter().collect::>(), + vec![11, 21, 31, 101] + ); + }); + } + + #[test] + fn re_validate_does_not_change_counters_or_list() { + ExtBuilder::default().nominate(false).build_and_execute(|| { + // given + let pre_insert_voter_count = + (Nominators::::count() + Validators::::count()) as u32; + assert_eq!(::VoterList::count(), pre_insert_voter_count); + + assert_eq!(::VoterList::iter().collect::>(), vec![11, 21, 31]); + + // when account 11 re-validates + assert_ok!(Staking::validate(Origin::signed(10), Default::default())); + + // then counts don't change + assert_eq!(::VoterList::count(), pre_insert_voter_count); // and the list is the same - assert_eq!(::SortedListProvider::iter().collect::>(), vec![101]); + assert_eq!(::VoterList::iter().collect::>(), vec![11, 21, 31]); }); } } From 97ee3d1de19e3f7442b6c0aa4ad360a49d5ea663 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Wed, 23 Mar 2022 18:10:13 -0400 Subject: [PATCH 631/695] Fix `generate_storage_alias!` (#11102) * add test * fix issues * make order intuitive --- frame/support/src/lib.rs | 42 ++++++++++++------- .../support/src/storage/bounded_btree_map.rs | 4 +- .../support/src/storage/bounded_btree_set.rs | 4 +- frame/support/src/storage/bounded_vec.rs | 4 +- .../src/storage/generator/double_map.rs | 2 +- frame/support/src/storage/generator/map.rs | 2 +- frame/support/src/storage/generator/nmap.rs | 6 +-- frame/support/src/storage/mod.rs | 6 +-- frame/support/src/storage/types/nmap.rs | 2 +- frame/support/src/storage/weak_bounded_vec.rs | 4 +- 10 files changed, 45 insertions(+), 31 deletions(-) diff --git a/frame/support/src/lib.rs b/frame/support/src/lib.rs index 3988b5e9af21..5f62995c5227 100644 --- a/frame/support/src/lib.rs +++ b/frame/support/src/lib.rs @@ -154,8 +154,8 @@ macro_rules! bounded_vec { /// // to `Vec` /// generate_storage_alias!( /// OtherPrefix, OtherStorageName => DoubleMap< -/// (u32, Twox64Concat), -/// (u32, Twox64Concat), +/// (Twox64Concat, u32), +/// (Twox64Concat, u32), /// Vec /// > /// ); @@ -165,8 +165,8 @@ macro_rules! bounded_vec { /// generate_storage_alias!(Prefix, ValueName => Value); /// generate_storage_alias!( /// Prefix, SomeStorageName => DoubleMap< -/// (u32, Twox64Concat), -/// (u32, Twox64Concat), +/// (Twox64Concat, u32), +/// (Twox64Concat, u32), /// Vec, /// ValueQuery /// > @@ -175,14 +175,14 @@ macro_rules! bounded_vec { /// // generate a map from `Config::AccountId` (with hasher `Twox64Concat`) to `Vec` /// trait Config { type AccountId: codec::FullCodec; } /// generate_storage_alias!( -/// Prefix, GenericStorage => Map<(T::AccountId, Twox64Concat), Vec> +/// Prefix, GenericStorage => Map<(Twox64Concat, T::AccountId), Vec> /// ); /// # fn main() {} /// ``` #[macro_export] macro_rules! generate_storage_alias { // without generic for $name. - ($pallet:ident, $name:ident => Map<($key:ty, $hasher:ty), $value:ty $(, $querytype:ty)?>) => { + ($pallet:ident, $name:ident => Map<($hasher:ty, $key:ty), $value:ty $(, $querytype:ty)?>) => { $crate::paste::paste! { $crate::generate_storage_alias!(@GENERATE_INSTANCE_STRUCT $pallet, $name); type $name = $crate::storage::types::StorageMap< @@ -197,7 +197,7 @@ macro_rules! generate_storage_alias { ( $pallet:ident, $name:ident - => DoubleMap<($key1:ty, $hasher1:ty), ($key2:ty, $hasher2:ty), $value:ty $(, $querytype:ty)?> + => DoubleMap<($hasher1:ty, $key1:ty), ($hasher2:ty, $key2:ty), $value:ty $(, $querytype:ty)?> ) => { $crate::paste::paste! { $crate::generate_storage_alias!(@GENERATE_INSTANCE_STRUCT $pallet, $name); @@ -215,7 +215,7 @@ macro_rules! generate_storage_alias { ( $pallet:ident, $name:ident - => NMap, $value:ty $(, $querytype:ty)?> + => NMap, $value:ty $(, $querytype:ty)?> ) => { $crate::paste::paste! { $crate::generate_storage_alias!(@GENERATE_INSTANCE_STRUCT $pallet, $name); @@ -243,15 +243,15 @@ macro_rules! generate_storage_alias { ( $pallet:ident, $name:ident<$t:ident : $bounds:tt> - => Map<($key:ty, $hasher:ty), $value:ty $(, $querytype:ty)?> + => Map<($hasher:ty, $key:ty), $value:ty $(, $querytype:ty)?> ) => { $crate::paste::paste! { $crate::generate_storage_alias!(@GENERATE_INSTANCE_STRUCT $pallet, $name); #[allow(type_alias_bounds)] type $name<$t : $bounds> = $crate::storage::types::StorageMap< [<$name Instance>], - $key, $hasher, + $key, $value, $( $querytype )? >; @@ -260,17 +260,17 @@ macro_rules! generate_storage_alias { ( $pallet:ident, $name:ident<$t:ident : $bounds:tt> - => DoubleMap<($key1:ty, $hasher1:ty), ($key2:ty, $hasher2:ty), $value:ty $(, $querytype:ty)?> + => DoubleMap<($hasher1:ty, $key1:ty), ($hasher2:ty, $key2:ty), $value:ty $(, $querytype:ty)?> ) => { $crate::paste::paste! { $crate::generate_storage_alias!(@GENERATE_INSTANCE_STRUCT $pallet, $name); #[allow(type_alias_bounds)] type $name<$t : $bounds> = $crate::storage::types::StorageDoubleMap< [<$name Instance>], - $key1, $hasher1, - $key2, + $key1, $hasher2, + $key2, $value, $( $querytype )? >; @@ -279,7 +279,7 @@ macro_rules! generate_storage_alias { ( $pallet:ident, $name:ident<$t:ident : $bounds:tt> - => NMap<$(($key:ty, $hasher:ty),)+ $value:ty $(, $querytype:ty)?> + => NMap<$(($hasher:ty, $key:ty),)+ $value:ty $(, $querytype:ty)?> ) => { $crate::paste::paste! { $crate::generate_storage_alias!(@GENERATE_INSTANCE_STRUCT $pallet, $name); @@ -945,6 +945,20 @@ pub mod tests { } } + #[test] + fn generate_storage_alias_works() { + new_test_ext().execute_with(|| { + generate_storage_alias!( + Test, + GenericData2 => Map<(Blake2_128Concat, T::BlockNumber), T::BlockNumber> + ); + + assert_eq!(Module::::generic_data2(5), None); + GenericData2::::insert(5, 5); + assert_eq!(Module::::generic_data2(5), Some(5)); + }); + } + #[test] fn map_issue_3318() { new_test_ext().execute_with(|| { diff --git a/frame/support/src/storage/bounded_btree_map.rs b/frame/support/src/storage/bounded_btree_map.rs index ed132adac657..6190552476a4 100644 --- a/frame/support/src/storage/bounded_btree_map.rs +++ b/frame/support/src/storage/bounded_btree_map.rs @@ -344,10 +344,10 @@ pub mod test { use sp_io::TestExternalities; crate::generate_storage_alias! { Prefix, Foo => Value>> } - crate::generate_storage_alias! { Prefix, FooMap => Map<(u32, Twox128), BoundedBTreeMap>> } + crate::generate_storage_alias! { Prefix, FooMap => Map<(Twox128, u32), BoundedBTreeMap>> } crate::generate_storage_alias! { Prefix, - FooDoubleMap => DoubleMap<(u32, Twox128), (u32, Twox128), BoundedBTreeMap>> + FooDoubleMap => DoubleMap<(Twox128, u32), (Twox128, u32), BoundedBTreeMap>> } fn map_from_keys(keys: &[K]) -> BTreeMap diff --git a/frame/support/src/storage/bounded_btree_set.rs b/frame/support/src/storage/bounded_btree_set.rs index 7d543549c6ba..543b997e94e3 100644 --- a/frame/support/src/storage/bounded_btree_set.rs +++ b/frame/support/src/storage/bounded_btree_set.rs @@ -327,10 +327,10 @@ pub mod test { use sp_std::convert::TryInto; crate::generate_storage_alias! { Prefix, Foo => Value>> } - crate::generate_storage_alias! { Prefix, FooMap => Map<(u32, Twox128), BoundedBTreeSet>> } + crate::generate_storage_alias! { Prefix, FooMap => Map<(Twox128, u32), BoundedBTreeSet>> } crate::generate_storage_alias! { Prefix, - FooDoubleMap => DoubleMap<(u32, Twox128), (u32, Twox128), BoundedBTreeSet>> + FooDoubleMap => DoubleMap<(Twox128, u32), (Twox128, u32), BoundedBTreeSet>> } fn set_from_keys(keys: &[T]) -> BTreeSet diff --git a/frame/support/src/storage/bounded_vec.rs b/frame/support/src/storage/bounded_vec.rs index 4e513258f968..cf585af39558 100644 --- a/frame/support/src/storage/bounded_vec.rs +++ b/frame/support/src/storage/bounded_vec.rs @@ -589,10 +589,10 @@ pub mod test { use sp_io::TestExternalities; crate::generate_storage_alias! { Prefix, Foo => Value>> } - crate::generate_storage_alias! { Prefix, FooMap => Map<(u32, Twox128), BoundedVec>> } + crate::generate_storage_alias! { Prefix, FooMap => Map<(Twox128, u32), BoundedVec>> } crate::generate_storage_alias! { Prefix, - FooDoubleMap => DoubleMap<(u32, Twox128), (u32, Twox128), BoundedVec>> + FooDoubleMap => DoubleMap<(Twox128, u32), (Twox128, u32), BoundedVec>> } #[test] diff --git a/frame/support/src/storage/generator/double_map.rs b/frame/support/src/storage/generator/double_map.rs index d63dda7d5b32..12e1764bfb65 100644 --- a/frame/support/src/storage/generator/double_map.rs +++ b/frame/support/src/storage/generator/double_map.rs @@ -527,7 +527,7 @@ mod test_iterators { use crate::hash::Identity; crate::generate_storage_alias!( MyModule, - MyDoubleMap => DoubleMap<(u64, Identity), (u64, Identity), u64> + MyDoubleMap => DoubleMap<(Identity, u64), (Identity, u64), u64> ); MyDoubleMap::insert(1, 10, 100); diff --git a/frame/support/src/storage/generator/map.rs b/frame/support/src/storage/generator/map.rs index 4157edefeac4..da48952bcba8 100644 --- a/frame/support/src/storage/generator/map.rs +++ b/frame/support/src/storage/generator/map.rs @@ -384,7 +384,7 @@ mod test_iterators { fn map_iter_from() { sp_io::TestExternalities::default().execute_with(|| { use crate::hash::Identity; - crate::generate_storage_alias!(MyModule, MyMap => Map<(u64, Identity), u64>); + crate::generate_storage_alias!(MyModule, MyMap => Map<(Identity, u64), u64>); MyMap::insert(1, 10); MyMap::insert(2, 20); diff --git a/frame/support/src/storage/generator/nmap.rs b/frame/support/src/storage/generator/nmap.rs index 1ad308bb22c7..be085ca2d9db 100755 --- a/frame/support/src/storage/generator/nmap.rs +++ b/frame/support/src/storage/generator/nmap.rs @@ -477,7 +477,7 @@ mod test_iterators { use crate::{hash::Identity, storage::Key as NMapKey}; crate::generate_storage_alias!( MyModule, - MyNMap => NMap, u64> + MyNMap => NMap, u64> ); MyNMap::insert((1, 1, 1), 11); @@ -519,8 +519,8 @@ mod test_iterators { { crate::generate_storage_alias!(Test, NMap => DoubleMap< - (u16, crate::Blake2_128Concat), - (u32, crate::Twox64Concat), + (crate::Blake2_128Concat, u16), + (crate::Twox64Concat, u32), u64 >); diff --git a/frame/support/src/storage/mod.rs b/frame/support/src/storage/mod.rs index 3d777fa3ace5..226682eecf10 100644 --- a/frame/support/src/storage/mod.rs +++ b/frame/support/src/storage/mod.rs @@ -1618,7 +1618,7 @@ mod test { use crate::{hash::Identity, storage::generator::map::StorageMap}; crate::generate_storage_alias! { MyModule, - MyStorageMap => Map<(u64, Identity), u64> + MyStorageMap => Map<(Identity, u64), u64> } MyStorageMap::insert(1, 10); @@ -1735,10 +1735,10 @@ mod test { } crate::generate_storage_alias! { Prefix, Foo => Value>> } - crate::generate_storage_alias! { Prefix, FooMap => Map<(u32, Twox128), BoundedVec>> } + crate::generate_storage_alias! { Prefix, FooMap => Map<(Twox128, u32), BoundedVec>> } crate::generate_storage_alias! { Prefix, - FooDoubleMap => DoubleMap<(u32, Twox128), (u32, Twox128), BoundedVec>> + FooDoubleMap => DoubleMap<(Twox128, u32), (Twox128, u32), BoundedVec>> } #[test] diff --git a/frame/support/src/storage/types/nmap.rs b/frame/support/src/storage/types/nmap.rs index 5b51ed1ffdf4..561bf5298e18 100755 --- a/frame/support/src/storage/types/nmap.rs +++ b/frame/support/src/storage/types/nmap.rs @@ -569,7 +569,7 @@ mod test { { crate::generate_storage_alias!(test, Foo => NMap< - Key<(u16, Blake2_128Concat)>, + Key<(Blake2_128Concat, u16)>, u32 >); diff --git a/frame/support/src/storage/weak_bounded_vec.rs b/frame/support/src/storage/weak_bounded_vec.rs index db62d7303539..4b3d87f776b4 100644 --- a/frame/support/src/storage/weak_bounded_vec.rs +++ b/frame/support/src/storage/weak_bounded_vec.rs @@ -323,10 +323,10 @@ pub mod test { use sp_std::convert::TryInto; crate::generate_storage_alias! { Prefix, Foo => Value>> } - crate::generate_storage_alias! { Prefix, FooMap => Map<(u32, Twox128), WeakBoundedVec>> } + crate::generate_storage_alias! { Prefix, FooMap => Map<(Twox128, u32), WeakBoundedVec>> } crate::generate_storage_alias! { Prefix, - FooDoubleMap => DoubleMap<(u32, Twox128), (u32, Twox128), WeakBoundedVec>> + FooDoubleMap => DoubleMap<(Twox128, u32), (Twox128, u32), WeakBoundedVec>> } #[test] From 6c92fc317bb9dd0b11f4c436fae972bff4d58c66 Mon Sep 17 00:00:00 2001 From: Keith Yeung Date: Thu, 24 Mar 2022 09:11:14 +0100 Subject: [PATCH 632/695] Allow pallet error enum variants to contain fields (#10242) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Allow pallet errors to contain at most one field * Update docs on pallet::error * Reword documentation * cargo fmt * Introduce CompactPalletError trait and require #[pallet::error] fields to implement them * cargo fmt * Do not assume tuple variants * Add CompactPalletError derive macro * Check for error type compactness in construct_runtime * cargo fmt * Derive CompactPalletError instead of implementing it directly during macro expansion * Implement CompactPalletError on OptionBool instead of Option * Check for type idents instead of variant ident * Add doc comments for ErrorCompactnessTest * Add an trait implementation of ErrorCompactnessTest for () * Convert the error field of DispatchError to a 4-element byte array * Add static check for pallet error size * Rename to MAX_PALLET_ERROR_ENCODED_SIZE * Remove ErrorCompactnessTest trait * Remove check_compactness * Return only the most significant byte when constructing a custom InvalidTransaction * Rename CompactPalletError to PalletError * Use counter to generate unique idents for assert macros * Make declarative pallet macros compile with pallet error size checks * Remove unused doc comment * Try and fix build errors * Fix build errors * Add macro_use for some test modules * Test fix * Fix compilation errors * Remove unneeded #[macro_use] * Resolve import ambiguity * Make path to pallet Error enum more specific * Fix test expectation * Disambiguate imports * Fix test expectations * Revert appending pallet module name to path * Rename bags_list::list::Error to BagError * Fixes * Fixes * Fixes * Fix test expectations * Fix test expectation * Add more implementations for PalletError * Lift the 1-field requirement for nested pallet errors * Fix UI test expectation * Remove PalletError impl for OptionBool * Use saturating operations * cargo fmt * Delete obsolete test * Fix test expectation * Try and use assert macro in const context * Pull out the pallet error size check macro * Fix UI test for const assertion * cargo fmt * Apply clippy suggestion * Fix doc comment * Docs for create_tt_return_macro * Ensure TryInto is imported in earlier Rust editions * Apply suggestions from code review Co-authored-by: Bastian Köcher * Fix up comments and names * Implement PalletError for Never * cargo fmt * Don't compile example code * Bump API version for block builder * Factor in codec attributes while derving PalletError * Rename module and fix unit test * Add missing attribute * Check API version and convert ApplyExtrinsicResult accordingly * Rename BagError to ListError Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> * Use codec crate re-exported from frame support * Add links to types mentioned in doc comments Co-authored-by: Bastian Köcher * cargo fmt * cargo fmt * Re-add attribute for hidden docs Co-authored-by: Bastian Köcher Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> --- client/block-builder/src/lib.rs | 30 ++- client/rpc/src/state/tests.rs | 2 +- frame/bags-list/src/lib.rs | 6 +- frame/bags-list/src/list/mod.rs | 6 +- frame/bags-list/src/list/tests.rs | 2 +- frame/bags-list/src/tests.rs | 2 +- .../election-provider-multi-phase/src/lib.rs | 2 +- .../src/unsigned.rs | 4 +- frame/scheduler/src/mock.rs | 4 +- frame/sudo/src/mock.rs | 1 - .../procedural/src/construct_runtime/mod.rs | 34 +++ frame/support/procedural/src/lib.rs | 19 +- .../procedural/src/pallet/expand/error.rs | 96 ++++++-- .../procedural/src/pallet/parse/error.rs | 25 +- frame/support/procedural/src/pallet_error.rs | 197 ++++++++++++++++ frame/support/procedural/src/tt_macro.rs | 110 +++++++++ frame/support/src/dispatch.rs | 4 + frame/support/src/error.rs | 54 +---- frame/support/src/lib.rs | 55 ++++- frame/support/src/traits.rs | 3 + frame/support/src/traits/error.rs | 95 ++++++++ frame/support/test/tests/construct_runtime.rs | 154 +++++-------- .../pallet_error_too_large.rs | 85 +++++++ .../pallet_error_too_large.stderr | 13 ++ frame/support/test/tests/origin.rs | 214 ++++++++++++++++++ frame/support/test/tests/pallet.rs | 10 +- frame/support/test/tests/pallet_instance.rs | 4 +- ... => error_does_not_derive_pallet_error.rs} | 14 +- .../error_does_not_derive_pallet_error.stderr | 12 + .../tests/pallet_ui/error_no_fieldless.stderr | 5 - .../pallet_ui/pass/error_nested_types.rs | 41 ++++ frame/utility/src/tests.rs | 1 - primitives/block-builder/src/lib.rs | 10 +- primitives/runtime/src/legacy.rs | 20 ++ .../runtime/src/legacy/byte_sized_error.rs | 100 ++++++++ primitives/runtime/src/lib.rs | 23 +- primitives/runtime/src/traits.rs | 6 + utils/frame/rpc/system/src/lib.rs | 41 +++- 38 files changed, 1263 insertions(+), 241 deletions(-) create mode 100644 frame/support/procedural/src/pallet_error.rs create mode 100644 frame/support/procedural/src/tt_macro.rs create mode 100644 frame/support/src/traits/error.rs create mode 100644 frame/support/test/tests/construct_runtime_ui/pallet_error_too_large.rs create mode 100644 frame/support/test/tests/construct_runtime_ui/pallet_error_too_large.stderr create mode 100644 frame/support/test/tests/origin.rs rename frame/support/test/tests/pallet_ui/{error_no_fieldless.rs => error_does_not_derive_pallet_error.rs} (50%) create mode 100644 frame/support/test/tests/pallet_ui/error_does_not_derive_pallet_error.stderr delete mode 100644 frame/support/test/tests/pallet_ui/error_no_fieldless.stderr create mode 100644 frame/support/test/tests/pallet_ui/pass/error_nested_types.rs create mode 100644 primitives/runtime/src/legacy.rs create mode 100644 primitives/runtime/src/legacy/byte_sized_error.rs diff --git a/client/block-builder/src/lib.rs b/client/block-builder/src/lib.rs index a4c6f5aad2ae..3f9fecbccbb9 100644 --- a/client/block-builder/src/lib.rs +++ b/client/block-builder/src/lib.rs @@ -35,6 +35,7 @@ use sp_blockchain::{ApplyExtrinsicFailed, Error}; use sp_core::ExecutionContext; use sp_runtime::{ generic::BlockId, + legacy, traits::{Block as BlockT, Hash, HashFor, Header as HeaderT, NumberFor, One}, Digest, }; @@ -135,6 +136,7 @@ where pub struct BlockBuilder<'a, Block: BlockT, A: ProvideRuntimeApi, B> { extrinsics: Vec, api: ApiRef<'a, A::Api>, + version: u32, block_id: BlockId, parent_hash: Block::Hash, backend: &'a B, @@ -183,10 +185,15 @@ where api.initialize_block_with_context(&block_id, ExecutionContext::BlockConstruction, &header)?; + let version = api + .api_version::>(&block_id)? + .ok_or_else(|| Error::VersionInvalid("BlockBuilderApi".to_string()))?; + Ok(Self { parent_hash, extrinsics: Vec::new(), api, + version, block_id, backend, estimated_header_size, @@ -199,13 +206,26 @@ where pub fn push(&mut self, xt: ::Extrinsic) -> Result<(), Error> { let block_id = &self.block_id; let extrinsics = &mut self.extrinsics; + let version = self.version; self.api.execute_in_transaction(|api| { - match api.apply_extrinsic_with_context( - block_id, - ExecutionContext::BlockConstruction, - xt.clone(), - ) { + let res = if version < 6 { + #[allow(deprecated)] + api.apply_extrinsic_before_version_6_with_context( + block_id, + ExecutionContext::BlockConstruction, + xt.clone(), + ) + .map(legacy::byte_sized_error::convert_to_latest) + } else { + api.apply_extrinsic_with_context( + block_id, + ExecutionContext::BlockConstruction, + xt.clone(), + ) + }; + + match res { Ok(Ok(_)) => { extrinsics.push(xt); TransactionOutcome::Commit(Ok(())) diff --git a/client/rpc/src/state/tests.rs b/client/rpc/src/state/tests.rs index 9dbe02cdb7d6..287dfac8c6ba 100644 --- a/client/rpc/src/state/tests.rs +++ b/client/rpc/src/state/tests.rs @@ -527,7 +527,7 @@ fn should_return_runtime_version() { let result = "{\"specName\":\"test\",\"implName\":\"parity-test\",\"authoringVersion\":1,\ \"specVersion\":2,\"implVersion\":2,\"apis\":[[\"0xdf6acb689907609b\",4],\ - [\"0x37e397fc7c91f5e4\",1],[\"0xd2bc9897eed08f15\",3],[\"0x40fe3ad401f8959a\",5],\ + [\"0x37e397fc7c91f5e4\",1],[\"0xd2bc9897eed08f15\",3],[\"0x40fe3ad401f8959a\",6],\ [\"0xc6e9a76309f39b09\",1],[\"0xdd718d5cc53262d4\",1],[\"0xcbca25e39f142387\",2],\ [\"0xf78b278be53f454c\",2],[\"0xab3c0572291feb8b\",1],[\"0xbc9d89904f5b923f\",1]],\ \"transactionVersion\":1,\"stateVersion\":1}"; diff --git a/frame/bags-list/src/lib.rs b/frame/bags-list/src/lib.rs index c502245409fd..aa9f1c80dfdb 100644 --- a/frame/bags-list/src/lib.rs +++ b/frame/bags-list/src/lib.rs @@ -70,7 +70,7 @@ pub mod mock; mod tests; pub mod weights; -pub use list::{notional_bag_for, Bag, Error, List, Node}; +pub use list::{notional_bag_for, Bag, List, ListError, Node}; pub use pallet::*; pub use weights::WeightInfo; @@ -270,7 +270,7 @@ impl, I: 'static> Pallet { } impl, I: 'static> SortedListProvider for Pallet { - type Error = Error; + type Error = ListError; type Score = T::Score; @@ -286,7 +286,7 @@ impl, I: 'static> SortedListProvider for Pallet List::::contains(id) } - fn on_insert(id: T::AccountId, score: T::Score) -> Result<(), Error> { + fn on_insert(id: T::AccountId, score: T::Score) -> Result<(), ListError> { List::::insert(id, score) } diff --git a/frame/bags-list/src/list/mod.rs b/frame/bags-list/src/list/mod.rs index 4921817c7e14..4e1287458bcb 100644 --- a/frame/bags-list/src/list/mod.rs +++ b/frame/bags-list/src/list/mod.rs @@ -39,7 +39,7 @@ use sp_std::{ }; #[derive(Debug, PartialEq, Eq)] -pub enum Error { +pub enum ListError { /// A duplicate id has been detected. Duplicate, } @@ -266,9 +266,9 @@ impl, I: 'static> List { /// Insert a new id into the appropriate bag in the list. /// /// Returns an error if the list already contains `id`. - pub(crate) fn insert(id: T::AccountId, score: T::Score) -> Result<(), Error> { + pub(crate) fn insert(id: T::AccountId, score: T::Score) -> Result<(), ListError> { if Self::contains(&id) { - return Err(Error::Duplicate) + return Err(ListError::Duplicate) } let bag_score = notional_bag_for::(score); diff --git a/frame/bags-list/src/list/tests.rs b/frame/bags-list/src/list/tests.rs index 9b7a078b4428..c8e233f1e62c 100644 --- a/frame/bags-list/src/list/tests.rs +++ b/frame/bags-list/src/list/tests.rs @@ -248,7 +248,7 @@ mod list { // then assert_storage_noop!(assert_eq!( List::::insert(3, 20).unwrap_err(), - Error::Duplicate + ListError::Duplicate )); }); } diff --git a/frame/bags-list/src/tests.rs b/frame/bags-list/src/tests.rs index 99396c9cbb3e..0d6ba4721b9a 100644 --- a/frame/bags-list/src/tests.rs +++ b/frame/bags-list/src/tests.rs @@ -518,7 +518,7 @@ mod sorted_list_provider { // then assert_storage_noop!(assert_eq!( BagsList::on_insert(3, 20).unwrap_err(), - Error::Duplicate + ListError::Duplicate )); }); } diff --git a/frame/election-provider-multi-phase/src/lib.rs b/frame/election-provider-multi-phase/src/lib.rs index b57d24d2d530..ddc06ce0aecf 100644 --- a/frame/election-provider-multi-phase/src/lib.rs +++ b/frame/election-provider-multi-phase/src/lib.rs @@ -1583,7 +1583,7 @@ impl ElectionProvider for Pallet { /// number. pub fn dispatch_error_to_invalid(error: DispatchError) -> InvalidTransaction { let error_number = match error { - DispatchError::Module(ModuleError { error, .. }) => error, + DispatchError::Module(ModuleError { error, .. }) => error[0], _ => 0, }; InvalidTransaction::Custom(error_number) diff --git a/frame/election-provider-multi-phase/src/unsigned.rs b/frame/election-provider-multi-phase/src/unsigned.rs index c52a4da22cb8..d210852bac19 100644 --- a/frame/election-provider-multi-phase/src/unsigned.rs +++ b/frame/election-provider-multi-phase/src/unsigned.rs @@ -931,7 +931,7 @@ mod tests { #[test] #[should_panic(expected = "Invalid unsigned submission must produce invalid block and \ deprive validator from their authoring reward.: \ - Module(ModuleError { index: 2, error: 1, message: \ + Module(ModuleError { index: 2, error: [1, 0, 0, 0], message: \ Some(\"PreDispatchWrongWinnerCount\") })")] fn unfeasible_solution_panics() { ExtBuilder::default().build_and_execute(|| { @@ -1053,7 +1053,7 @@ mod tests { MultiPhase::basic_checks(&solution, "mined").unwrap_err(), MinerError::PreDispatchChecksFailed(DispatchError::Module(ModuleError { index: 2, - error: 1, + error: [1, 0, 0, 0], message: Some("PreDispatchWrongWinnerCount"), })), ); diff --git a/frame/scheduler/src/mock.rs b/frame/scheduler/src/mock.rs index 869425c2ff53..ecd04c3e48b5 100644 --- a/frame/scheduler/src/mock.rs +++ b/frame/scheduler/src/mock.rs @@ -38,7 +38,7 @@ use sp_runtime::{ // Logger module to track execution. #[frame_support::pallet] pub mod logger { - use super::*; + use super::{OriginCaller, OriginTrait}; use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; use std::cell::RefCell; @@ -71,7 +71,7 @@ pub mod logger { #[pallet::call] impl Pallet where - ::Origin: OriginTrait, + ::Origin: OriginTrait, { #[pallet::weight(*weight)] pub fn log(origin: OriginFor, i: u32, weight: Weight) -> DispatchResult { diff --git a/frame/sudo/src/mock.rs b/frame/sudo/src/mock.rs index 410807789069..2e2a4abafcd9 100644 --- a/frame/sudo/src/mock.rs +++ b/frame/sudo/src/mock.rs @@ -34,7 +34,6 @@ use sp_runtime::{ // Logger module to track execution. #[frame_support::pallet] pub mod logger { - use super::*; use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; diff --git a/frame/support/procedural/src/construct_runtime/mod.rs b/frame/support/procedural/src/construct_runtime/mod.rs index 249eb072001c..2a86869382c9 100644 --- a/frame/support/procedural/src/construct_runtime/mod.rs +++ b/frame/support/procedural/src/construct_runtime/mod.rs @@ -241,6 +241,7 @@ fn construct_runtime_final_expansion( expand::expand_outer_inherent(&name, &block, &unchecked_extrinsic, &pallets, &scrate); let validate_unsigned = expand::expand_outer_validate_unsigned(&name, &pallets, &scrate); let integrity_test = decl_integrity_test(&scrate); + let static_assertions = decl_static_assertions(&name, &pallets, &scrate); let res = quote!( #scrate_decl @@ -282,6 +283,8 @@ fn construct_runtime_final_expansion( #validate_unsigned #integrity_test + + #static_assertions ); Ok(res) @@ -471,3 +474,34 @@ fn decl_integrity_test(scrate: &TokenStream2) -> TokenStream2 { } ) } + +fn decl_static_assertions( + runtime: &Ident, + pallet_decls: &[Pallet], + scrate: &TokenStream2, +) -> TokenStream2 { + let error_encoded_size_check = pallet_decls.iter().map(|decl| { + let path = &decl.path; + let assert_message = format!( + "The maximum encoded size of the error type in the `{}` pallet exceeds \ + `MAX_MODULE_ERROR_ENCODED_SIZE`", + decl.name, + ); + + quote! { + #scrate::tt_call! { + macro = [{ #path::tt_error_token }] + frame_support = [{ #scrate }] + ~~> #scrate::assert_error_encoded_size! { + path = [{ #path }] + runtime = [{ #runtime }] + assert_message = [{ #assert_message }] + } + } + } + }); + + quote! { + #(#error_encoded_size_check)* + } +} diff --git a/frame/support/procedural/src/lib.rs b/frame/support/procedural/src/lib.rs index e2233fff7228..92564e94493c 100644 --- a/frame/support/procedural/src/lib.rs +++ b/frame/support/procedural/src/lib.rs @@ -28,9 +28,11 @@ mod dummy_part_checker; mod key_prefix; mod match_and_insert; mod pallet; +mod pallet_error; mod partial_eq_no_bound; mod storage; mod transactional; +mod tt_macro; use proc_macro::TokenStream; use std::{cell::RefCell, str::FromStr}; @@ -41,9 +43,9 @@ thread_local! { static COUNTER: RefCell = RefCell::new(Counter(0)); } -/// Counter to generate a relatively unique identifier for macros querying for the existence of -/// pallet parts. This is necessary because declarative macros gets hoisted to the crate root, -/// which shares the namespace with other pallets containing the very same query macros. +/// Counter to generate a relatively unique identifier for macros. This is necessary because +/// declarative macros gets hoisted to the crate root, which shares the namespace with other pallets +/// containing the very same macros. struct Counter(u64); impl Counter { @@ -562,3 +564,14 @@ pub fn __generate_dummy_part_checker(input: TokenStream) -> TokenStream { pub fn match_and_insert(input: TokenStream) -> TokenStream { match_and_insert::match_and_insert(input) } + +#[proc_macro_derive(PalletError, attributes(codec))] +pub fn derive_pallet_error(input: TokenStream) -> TokenStream { + pallet_error::derive_pallet_error(input) +} + +/// Internal macro used by `frame_support` to create tt-call-compliant macros +#[proc_macro] +pub fn __create_tt_macro(input: TokenStream) -> TokenStream { + tt_macro::create_tt_return_macro(input) +} diff --git a/frame/support/procedural/src/pallet/expand/error.rs b/frame/support/procedural/src/pallet/expand/error.rs index 184fa86d3ae1..86b06d737dec 100644 --- a/frame/support/procedural/src/pallet/expand/error.rs +++ b/frame/support/procedural/src/pallet/expand/error.rs @@ -15,20 +15,48 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::pallet::Def; +use crate::{ + pallet::{parse::error::VariantField, Def}, + COUNTER, +}; use frame_support_procedural_tools::get_doc_literals; +use syn::spanned::Spanned; /// /// * impl various trait on Error pub fn expand_error(def: &mut Def) -> proc_macro2::TokenStream { - let error = if let Some(error) = &def.error { error } else { return Default::default() }; + let count = COUNTER.with(|counter| counter.borrow_mut().inc()); + let error_token_unique_id = + syn::Ident::new(&format!("__tt_error_token_{}", count), def.item.span()); - let error_ident = &error.error; let frame_support = &def.frame_support; let frame_system = &def.frame_system; + let config_where_clause = &def.config.where_clause; + + let error = if let Some(error) = &def.error { + error + } else { + return quote::quote! { + #[macro_export] + #[doc(hidden)] + macro_rules! #error_token_unique_id { + { + $caller:tt + frame_support = [{ $($frame_support:ident)::* }] + } => { + $($frame_support::)*tt_return! { + $caller + } + }; + } + + pub use #error_token_unique_id as tt_error_token; + } + }; + + let error_ident = &error.error; let type_impl_gen = &def.type_impl_generics(error.attr_span); let type_use_gen = &def.type_use_generics(error.attr_span); - let config_where_clause = &def.config.where_clause; let phantom_variant: syn::Variant = syn::parse_quote!( #[doc(hidden)] @@ -39,13 +67,19 @@ pub fn expand_error(def: &mut Def) -> proc_macro2::TokenStream { ) ); - let as_u8_matches = error.variants.iter().enumerate().map( - |(i, (variant, _))| quote::quote_spanned!(error.attr_span => Self::#variant => #i as u8,), - ); - - let as_str_matches = error.variants.iter().map(|(variant, _)| { - let variant_str = format!("{}", variant); - quote::quote_spanned!(error.attr_span => Self::#variant => #variant_str,) + let as_str_matches = error.variants.iter().map(|(variant, field_ty, _)| { + let variant_str = variant.to_string(); + match field_ty { + Some(VariantField { is_named: true }) => { + quote::quote_spanned!(error.attr_span => Self::#variant { .. } => #variant_str,) + }, + Some(VariantField { is_named: false }) => { + quote::quote_spanned!(error.attr_span => Self::#variant(..) => #variant_str,) + }, + None => { + quote::quote_spanned!(error.attr_span => Self::#variant => #variant_str,) + }, + } }); let error_item = { @@ -62,9 +96,14 @@ pub fn expand_error(def: &mut Def) -> proc_macro2::TokenStream { let capture_docs = if cfg!(feature = "no-metadata-docs") { "never" } else { "always" }; // derive TypeInfo for error metadata - error_item - .attrs - .push(syn::parse_quote!( #[derive(#frame_support::scale_info::TypeInfo)] )); + error_item.attrs.push(syn::parse_quote! { + #[derive( + #frame_support::codec::Encode, + #frame_support::codec::Decode, + #frame_support::scale_info::TypeInfo, + #frame_support::PalletError, + )] + }); error_item.attrs.push(syn::parse_quote!( #[scale_info(skip_type_params(#type_use_gen), capture_docs = #capture_docs)] )); @@ -90,14 +129,6 @@ pub fn expand_error(def: &mut Def) -> proc_macro2::TokenStream { } impl<#type_impl_gen> #error_ident<#type_use_gen> #config_where_clause { - #[doc(hidden)] - pub fn as_u8(&self) -> u8 { - match &self { - Self::__Ignore(_, _) => unreachable!("`__Ignore` can never be constructed"), - #( #as_u8_matches )* - } - } - #[doc(hidden)] pub fn as_str(&self) -> &'static str { match &self { @@ -120,18 +151,37 @@ pub fn expand_error(def: &mut Def) -> proc_macro2::TokenStream { #config_where_clause { fn from(err: #error_ident<#type_use_gen>) -> Self { + use #frame_support::codec::Encode; let index = < ::PalletInfo as #frame_support::traits::PalletInfo >::index::>() .expect("Every active module has an index in the runtime; qed") as u8; + let mut encoded = err.encode(); + encoded.resize(#frame_support::MAX_MODULE_ERROR_ENCODED_SIZE, 0); #frame_support::sp_runtime::DispatchError::Module(#frame_support::sp_runtime::ModuleError { index, - error: err.as_u8(), + error: core::convert::TryInto::try_into(encoded).expect("encoded error is resized to be equal to the maximum encoded error size; qed"), message: Some(err.as_str()), }) } } + + #[macro_export] + #[doc(hidden)] + macro_rules! #error_token_unique_id { + { + $caller:tt + frame_support = [{ $($frame_support:ident)::* }] + } => { + $($frame_support::)*tt_return! { + $caller + error = [{ #error_ident }] + } + }; + } + + pub use #error_token_unique_id as tt_error_token; ) } diff --git a/frame/support/procedural/src/pallet/parse/error.rs b/frame/support/procedural/src/pallet/parse/error.rs index 419770386bf6..0ec49aa0adb4 100644 --- a/frame/support/procedural/src/pallet/parse/error.rs +++ b/frame/support/procedural/src/pallet/parse/error.rs @@ -18,20 +18,26 @@ use super::helper; use frame_support_procedural_tools::get_doc_literals; use quote::ToTokens; -use syn::spanned::Spanned; +use syn::{spanned::Spanned, Fields}; /// List of additional token to be used for parsing. mod keyword { syn::custom_keyword!(Error); } +/// Records information about the error enum variants. +pub struct VariantField { + /// Whether or not the field is named, i.e. whether it is a tuple variant or struct variant. + pub is_named: bool, +} + /// This checks error declaration as a enum declaration with only variants without fields nor /// discriminant. pub struct ErrorDef { /// The index of error item in pallet module. pub index: usize, - /// Variants ident and doc literals (ordered as declaration order) - pub variants: Vec<(syn::Ident, Vec)>, + /// Variants ident, optional field and doc literals (ordered as declaration order) + pub variants: Vec<(syn::Ident, Option, Vec)>, /// A set of usage of instance, must be check for consistency with trait. pub instances: Vec, /// The keyword error used (contains span). @@ -70,18 +76,19 @@ impl ErrorDef { .variants .iter() .map(|variant| { - if !matches!(variant.fields, syn::Fields::Unit) { - let msg = "Invalid pallet::error, unexpected fields, must be `Unit`"; - return Err(syn::Error::new(variant.fields.span(), msg)) - } + let field_ty = match &variant.fields { + Fields::Unit => None, + Fields::Named(_) => Some(VariantField { is_named: true }), + Fields::Unnamed(_) => Some(VariantField { is_named: false }), + }; if variant.discriminant.is_some() { - let msg = "Invalid pallet::error, unexpected discriminant, discriminant \ + let msg = "Invalid pallet::error, unexpected discriminant, discriminants \ are not supported"; let span = variant.discriminant.as_ref().unwrap().0.span(); return Err(syn::Error::new(span, msg)) } - Ok((variant.ident.clone(), get_doc_literals(&variant.attrs))) + Ok((variant.ident.clone(), field_ty, get_doc_literals(&variant.attrs))) }) .collect::>()?; diff --git a/frame/support/procedural/src/pallet_error.rs b/frame/support/procedural/src/pallet_error.rs new file mode 100644 index 000000000000..216168131e43 --- /dev/null +++ b/frame/support/procedural/src/pallet_error.rs @@ -0,0 +1,197 @@ +// This file is part of Substrate. + +// Copyright (C) 2021 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. + +use frame_support_procedural_tools::generate_crate_access_2018; +use quote::ToTokens; +use std::str::FromStr; + +// Derive `PalletError` +pub fn derive_pallet_error(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + let syn::DeriveInput { ident: name, generics, data, .. } = match syn::parse(input) { + Ok(input) => input, + Err(e) => return e.to_compile_error().into(), + }; + + let frame_support = match generate_crate_access_2018("frame-support") { + Ok(c) => c, + Err(e) => return e.into_compile_error().into(), + }; + let frame_support = &frame_support; + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + + let max_encoded_size = match data { + syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields { + syn::Fields::Named(syn::FieldsNamed { named: fields, .. }) | + syn::Fields::Unnamed(syn::FieldsUnnamed { unnamed: fields, .. }) => { + let maybe_field_tys = fields + .iter() + .map(|f| generate_field_types(f, &frame_support)) + .collect::>>(); + let field_tys = match maybe_field_tys { + Ok(tys) => tys.into_iter().flatten(), + Err(e) => return e.into_compile_error().into(), + }; + quote::quote! { + 0_usize + #( + .saturating_add(< + #field_tys as #frame_support::traits::PalletError + >::MAX_ENCODED_SIZE) + )* + } + }, + syn::Fields::Unit => quote::quote!(0), + }, + syn::Data::Enum(syn::DataEnum { variants, .. }) => { + let field_tys = variants + .iter() + .map(|variant| generate_variant_field_types(variant, &frame_support)) + .collect::>>, syn::Error>>(); + + let field_tys = match field_tys { + Ok(tys) => tys.into_iter().flatten().collect::>(), + Err(e) => return e.to_compile_error().into(), + }; + + // We start with `1`, because the discriminant of an enum is stored as u8 + if field_tys.is_empty() { + quote::quote!(1) + } else { + let variant_sizes = field_tys.into_iter().map(|variant_field_tys| { + quote::quote! { + 1_usize + #(.saturating_add(< + #variant_field_tys as #frame_support::traits::PalletError + >::MAX_ENCODED_SIZE))* + } + }); + + quote::quote! {{ + let mut size = 1_usize; + let mut tmp = 0_usize; + #( + tmp = #variant_sizes; + size = if tmp > size { tmp } else { size }; + tmp = 0_usize; + )* + size + }} + } + }, + syn::Data::Union(syn::DataUnion { union_token, .. }) => { + let msg = "Cannot derive `PalletError` for union; please implement it directly"; + return syn::Error::new(union_token.span, msg).into_compile_error().into() + }, + }; + + quote::quote!( + const _: () = { + impl #impl_generics #frame_support::traits::PalletError + for #name #ty_generics #where_clause + { + const MAX_ENCODED_SIZE: usize = #max_encoded_size; + } + }; + ) + .into() +} + +fn generate_field_types( + field: &syn::Field, + scrate: &syn::Ident, +) -> syn::Result> { + let attrs = &field.attrs; + + for attr in attrs { + if attr.path.is_ident("codec") { + match attr.parse_meta()? { + syn::Meta::List(ref meta_list) if meta_list.nested.len() == 1 => { + match meta_list + .nested + .first() + .expect("Just checked that there is one item; qed") + { + syn::NestedMeta::Meta(syn::Meta::Path(path)) + if path.get_ident().map_or(false, |i| i == "skip") => + return Ok(None), + + syn::NestedMeta::Meta(syn::Meta::Path(path)) + if path.get_ident().map_or(false, |i| i == "compact") => + { + let field_ty = &field.ty; + return Ok(Some(quote::quote!(#scrate::codec::Compact<#field_ty>))) + }, + + syn::NestedMeta::Meta(syn::Meta::NameValue(syn::MetaNameValue { + path, + lit: syn::Lit::Str(lit_str), + .. + })) if path.get_ident().map_or(false, |i| i == "encoded_as") => { + let ty = proc_macro2::TokenStream::from_str(&lit_str.value())?; + return Ok(Some(ty)) + }, + + _ => (), + } + }, + _ => (), + } + } + } + + Ok(Some(field.ty.to_token_stream())) +} + +fn generate_variant_field_types( + variant: &syn::Variant, + scrate: &syn::Ident, +) -> syn::Result>> { + let attrs = &variant.attrs; + + for attr in attrs { + if attr.path.is_ident("codec") { + match attr.parse_meta()? { + syn::Meta::List(ref meta_list) if meta_list.nested.len() == 1 => { + match meta_list + .nested + .first() + .expect("Just checked that there is one item; qed") + { + syn::NestedMeta::Meta(syn::Meta::Path(path)) + if path.get_ident().map_or(false, |i| i == "skip") => + return Ok(None), + + _ => (), + } + }, + _ => (), + } + } + } + + match &variant.fields { + syn::Fields::Named(syn::FieldsNamed { named: fields, .. }) | + syn::Fields::Unnamed(syn::FieldsUnnamed { unnamed: fields, .. }) => { + let field_tys = fields + .iter() + .map(|field| generate_field_types(field, scrate)) + .collect::>>()?; + Ok(Some(field_tys.into_iter().flatten().collect())) + }, + syn::Fields::Unit => Ok(None), + } +} diff --git a/frame/support/procedural/src/tt_macro.rs b/frame/support/procedural/src/tt_macro.rs new file mode 100644 index 000000000000..0a270a7173cf --- /dev/null +++ b/frame/support/procedural/src/tt_macro.rs @@ -0,0 +1,110 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +//! Implementation of the `create_tt_return_macro` macro + +use crate::COUNTER; +use frame_support_procedural_tools::generate_crate_access_2018; +use proc_macro2::{Ident, TokenStream}; +use quote::format_ident; + +struct CreateTtReturnMacroDef { + name: Ident, + args: Vec<(Ident, TokenStream)>, +} + +impl syn::parse::Parse for CreateTtReturnMacroDef { + fn parse(input: syn::parse::ParseStream) -> syn::Result { + let name = input.parse()?; + let _ = input.parse::()?; + + let mut args = Vec::new(); + while !input.is_empty() { + let mut value; + let key: Ident = input.parse()?; + let _ = input.parse::()?; + let _: syn::token::Bracket = syn::bracketed!(value in input); + let _: syn::token::Brace = syn::braced!(value in value); + let value: TokenStream = value.parse()?; + + args.push((key, value)) + } + + Ok(Self { name, args }) + } +} + +/// A proc macro that accepts a name and any number of key-value pairs, to be used to create a +/// declarative macro that follows tt-call conventions and simply calls [`tt_call::tt_return`], +/// accepting an optional `frame-support` argument and returning the key-value pairs that were +/// supplied to the proc macro. +/// +/// # Example +/// ```ignore +/// __create_tt_macro! { +/// my_tt_macro, +/// foo = [{ bar }] +/// } +/// +/// // Creates the following declarative macro: +/// +/// macro_rules! my_tt_macro { +/// { +/// $caller:tt +/// $(frame_support = [{ $($frame_support:ident)::* }])? +/// } => { +/// frame_support::tt_return! { +/// $caller +/// foo = [{ bar }] +/// } +/// } +/// } +/// ``` +pub fn create_tt_return_macro(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + let CreateTtReturnMacroDef { name, args } = + syn::parse_macro_input!(input as CreateTtReturnMacroDef); + + let frame_support = match generate_crate_access_2018("frame-support") { + Ok(i) => i, + Err(e) => return e.into_compile_error().into(), + }; + let (keys, values): (Vec<_>, Vec<_>) = args.into_iter().unzip(); + let count = COUNTER.with(|counter| counter.borrow_mut().inc()); + let unique_name = format_ident!("{}_{}", name, count); + + let decl_macro = quote::quote! { + #[macro_export] + #[doc(hidden)] + macro_rules! #unique_name { + { + $caller:tt + $(frame_support = [{ $($frame_support:ident)::* }])? + } => { + #frame_support::tt_return! { + $caller + #( + #keys = [{ #values }] + )* + } + } + } + + pub use #unique_name as #name; + }; + + decl_macro.into() +} diff --git a/frame/support/src/dispatch.rs b/frame/support/src/dispatch.rs index ece5173f2f4c..7ccf79616729 100644 --- a/frame/support/src/dispatch.rs +++ b/frame/support/src/dispatch.rs @@ -2003,6 +2003,10 @@ macro_rules! decl_module { pub type Pallet<$trait_instance $(, $instance $( = $module_default_instance)?)?> = $mod_type<$trait_instance $(, $instance)?>; + $crate::__create_tt_macro! { + tt_error_token, + } + $crate::decl_module! { @impl_on_initialize { $system } diff --git a/frame/support/src/error.rs b/frame/support/src/error.rs index 4880bba5c5e9..764376a4e1dc 100644 --- a/frame/support/src/error.rs +++ b/frame/support/src/error.rs @@ -85,7 +85,12 @@ macro_rules! decl_error { } ) => { $(#[$attr])* - #[derive($crate::scale_info::TypeInfo)] + #[derive( + $crate::codec::Encode, + $crate::codec::Decode, + $crate::scale_info::TypeInfo, + $crate::PalletError, + )] #[scale_info(skip_type_params($generic $(, $inst_generic)?), capture_docs = "always")] pub enum $error<$generic: $trait $(, $inst_generic: $instance)?> $( where $( $where_ty: $where_bound ),* )? @@ -114,17 +119,6 @@ macro_rules! decl_error { impl<$generic: $trait $(, $inst_generic: $instance)?> $error<$generic $(, $inst_generic)?> $( where $( $where_ty: $where_bound ),* )? { - fn as_u8(&self) -> u8 { - $crate::decl_error! { - @GENERATE_AS_U8 - self - $error - {} - 0, - $( $name ),* - } - } - fn as_str(&self) -> &'static str { match self { Self::__Ignore(_, _) => unreachable!("`__Ignore` can never be constructed"), @@ -149,47 +143,19 @@ macro_rules! decl_error { $( where $( $where_ty: $where_bound ),* )? { fn from(err: $error<$generic $(, $inst_generic)?>) -> Self { + use $crate::codec::Encode; let index = <$generic::PalletInfo as $crate::traits::PalletInfo> ::index::<$module<$generic $(, $inst_generic)?>>() .expect("Every active module has an index in the runtime; qed") as u8; + let mut error = err.encode(); + error.resize($crate::MAX_MODULE_ERROR_ENCODED_SIZE, 0); $crate::sp_runtime::DispatchError::Module($crate::sp_runtime::ModuleError { index, - error: err.as_u8(), + error: core::convert::TryInto::try_into(error).expect("encoded error is resized to be equal to the maximum encoded error size; qed"), message: Some(err.as_str()), }) } } }; - (@GENERATE_AS_U8 - $self:ident - $error:ident - { $( $generated:tt )* } - $index:expr, - $name:ident - $( , $rest:ident )* - ) => { - $crate::decl_error! { - @GENERATE_AS_U8 - $self - $error - { - $( $generated )* - $error::$name => $index, - } - $index + 1, - $( $rest ),* - } - }; - (@GENERATE_AS_U8 - $self:ident - $error:ident - { $( $generated:tt )* } - $index:expr, - ) => { - match $self { - $error::__Ignore(_, _) => unreachable!("`__Ignore` can never be constructed"), - $( $generated )* - } - } } diff --git a/frame/support/src/lib.rs b/frame/support/src/lib.rs index 5f62995c5227..70a79c07189d 100644 --- a/frame/support/src/lib.rs +++ b/frame/support/src/lib.rs @@ -93,7 +93,9 @@ pub use self::{ StorageMap, StorageNMap, StoragePrefixedMap, StorageValue, }, }; -pub use sp_runtime::{self, print, traits::Printable, ConsensusEngineId}; +pub use sp_runtime::{ + self, print, traits::Printable, ConsensusEngineId, MAX_MODULE_ERROR_ENCODED_SIZE, +}; use codec::{Decode, Encode}; use scale_info::TypeInfo; @@ -103,7 +105,7 @@ use sp_runtime::TypeId; pub const LOG_TARGET: &'static str = "runtime::frame-support"; /// A type that cannot be instantiated. -#[derive(Debug, PartialEq, Eq, Clone, TypeInfo)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] pub enum Never {} /// A pallet identifier. These are per pallet and should be stored in a registry somewhere. @@ -598,11 +600,12 @@ pub fn debug(data: &impl sp_std::fmt::Debug) { #[doc(inline)] pub use frame_support_procedural::{ - construct_runtime, decl_storage, match_and_insert, transactional, RuntimeDebugNoBound, + construct_runtime, decl_storage, match_and_insert, transactional, PalletError, + RuntimeDebugNoBound, }; #[doc(hidden)] -pub use frame_support_procedural::__generate_dummy_part_checker; +pub use frame_support_procedural::{__create_tt_macro, __generate_dummy_part_checker}; /// Derive [`Clone`] but do not bound any generic. /// @@ -847,6 +850,32 @@ macro_rules! assert_ok { }; } +/// Assert that the maximum encoding size does not exceed the value defined in +/// [`MAX_MODULE_ERROR_ENCODED_SIZE`] during compilation. +/// +/// This macro is intended to be used in conjunction with `tt_call!`. +#[macro_export] +macro_rules! assert_error_encoded_size { + { + path = [{ $($path:ident)::+ }] + runtime = [{ $runtime:ident }] + assert_message = [{ $assert_message:literal }] + error = [{ $error:ident }] + } => { + const _: () = assert!( + < + $($path::)+$error<$runtime> as $crate::traits::PalletError + >::MAX_ENCODED_SIZE <= $crate::MAX_MODULE_ERROR_ENCODED_SIZE, + $assert_message + ); + }; + { + path = [{ $($path:ident)::+ }] + runtime = [{ $runtime:ident }] + assert_message = [{ $assert_message:literal }] + } => {}; +} + #[cfg(feature = "std")] #[doc(hidden)] pub use serde::{Deserialize, Serialize}; @@ -1375,6 +1404,7 @@ pub mod pallet_prelude { TransactionTag, TransactionValidity, TransactionValidityError, UnknownTransaction, ValidTransaction, }, + MAX_MODULE_ERROR_ENCODED_SIZE, }; pub use sp_std::marker::PhantomData; } @@ -1652,10 +1682,25 @@ pub mod pallet_prelude { /// pub enum Error { /// /// $some_optional_doc /// $SomeFieldLessVariant, +/// /// $some_more_optional_doc +/// $SomeVariantWithOneField(FieldType), /// ... /// } /// ``` -/// I.e. a regular rust enum named `Error`, with generic `T` and fieldless variants. +/// I.e. a regular rust enum named `Error`, with generic `T` and fieldless or multiple-field +/// variants. +/// +/// Any field type in the enum variants must implement [`scale_info::TypeInfo`] in order to be +/// properly used in the metadata, and its encoded size should be as small as possible, +/// preferably 1 byte in size in order to reduce storage size. The error enum itself has an +/// absolute maximum encoded size specified by [`MAX_MODULE_ERROR_ENCODED_SIZE`]. +/// +/// Field types in enum variants must also implement [`PalletError`](traits::PalletError), +/// otherwise the pallet will fail to compile. Rust primitive types have already implemented +/// the [`PalletError`](traits::PalletError) trait along with some commonly used stdlib types +/// such as `Option` and `PhantomData`, and hence in most use cases, a manual implementation is +/// not necessary and is discouraged. +/// /// The generic `T` mustn't bound anything and where clause is not allowed. But bounds and /// where clause shouldn't be needed for any usecase. /// diff --git a/frame/support/src/traits.rs b/frame/support/src/traits.rs index a8ce78ae9dab..40afc0d337f4 100644 --- a/frame/support/src/traits.rs +++ b/frame/support/src/traits.rs @@ -46,6 +46,9 @@ pub use validation::{ ValidatorSetWithIdentification, VerifySeal, }; +mod error; +pub use error::PalletError; + mod filter; pub use filter::{ClearFilterGuard, FilterStack, FilterStackGuard, InstanceFilter, IntegrityTest}; diff --git a/frame/support/src/traits/error.rs b/frame/support/src/traits/error.rs new file mode 100644 index 000000000000..8e26891669e6 --- /dev/null +++ b/frame/support/src/traits/error.rs @@ -0,0 +1,95 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +//! Traits for describing and constraining pallet error types. +use codec::{Compact, Decode, Encode}; +use sp_std::marker::PhantomData; + +/// Trait indicating that the implementing type is going to be included as a field in a variant of +/// the `#[pallet::error]` enum type. +/// +/// ## Notes +/// +/// The pallet error enum has a maximum encoded size as defined by +/// [`frame_support::MAX_MODULE_ERROR_ENCODED_SIZE`]. If the pallet error type exceeds this size +/// limit, a static assertion during compilation will fail. The compilation error will be in the +/// format of `error[E0080]: evaluation of constant value failed` due to the usage of +/// const assertions. +pub trait PalletError: Encode + Decode { + /// The maximum encoded size for the implementing type. + /// + /// This will be used to check whether the pallet error type is less than or equal to + /// [`frame_support::MAX_MODULE_ERROR_ENCODED_SIZE`], and if it is, a compilation error will be + /// thrown. + const MAX_ENCODED_SIZE: usize; +} + +macro_rules! impl_for_types { + (size: $size:expr, $($typ:ty),+) => { + $( + impl PalletError for $typ { + const MAX_ENCODED_SIZE: usize = $size; + } + )+ + }; +} + +impl_for_types!(size: 0, (), crate::Never); +impl_for_types!(size: 1, u8, i8, bool); +impl_for_types!(size: 2, u16, i16, Compact); +impl_for_types!(size: 4, u32, i32, Compact); +impl_for_types!(size: 5, Compact); +impl_for_types!(size: 8, u64, i64); +impl_for_types!(size: 9, Compact); +// Contains a u64 for secs and u32 for nanos, hence 12 bytes +impl_for_types!(size: 12, core::time::Duration); +impl_for_types!(size: 16, u128, i128); +impl_for_types!(size: 17, Compact); + +impl PalletError for PhantomData { + const MAX_ENCODED_SIZE: usize = 0; +} + +impl PalletError for core::ops::Range { + const MAX_ENCODED_SIZE: usize = T::MAX_ENCODED_SIZE.saturating_mul(2); +} + +impl PalletError for [T; N] { + const MAX_ENCODED_SIZE: usize = T::MAX_ENCODED_SIZE.saturating_mul(N); +} + +impl PalletError for Option { + const MAX_ENCODED_SIZE: usize = T::MAX_ENCODED_SIZE.saturating_add(1); +} + +impl PalletError for Result { + const MAX_ENCODED_SIZE: usize = if T::MAX_ENCODED_SIZE > E::MAX_ENCODED_SIZE { + T::MAX_ENCODED_SIZE + } else { + E::MAX_ENCODED_SIZE + } + .saturating_add(1); +} + +#[impl_trait_for_tuples::impl_for_tuples(1, 18)] +impl PalletError for Tuple { + const MAX_ENCODED_SIZE: usize = { + let mut size = 0_usize; + for_tuples!( #(size = size.saturating_add(Tuple::MAX_ENCODED_SIZE);)* ); + size + }; +} diff --git a/frame/support/test/tests/construct_runtime.rs b/frame/support/test/tests/construct_runtime.rs index b3f8feb8aa4b..804deb08919a 100644 --- a/frame/support/test/tests/construct_runtime.rs +++ b/frame/support/test/tests/construct_runtime.rs @@ -271,139 +271,95 @@ pub type Header = generic::Header; pub type Block = generic::Block; pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; -mod origin_test { - use super::{module3, nested, system, Block, UncheckedExtrinsic}; - use frame_support::traits::{Contains, OriginTrait}; - - impl nested::module3::Config for RuntimeOriginTest {} - impl module3::Config for RuntimeOriginTest {} - - pub struct BaseCallFilter; - impl Contains for BaseCallFilter { - fn contains(c: &Call) -> bool { - match c { - Call::NestedModule3(_) => true, - _ => false, - } - } - } - - impl system::Config for RuntimeOriginTest { - type BaseCallFilter = BaseCallFilter; - type Hash = super::H256; - type Origin = Origin; - type BlockNumber = super::BlockNumber; - type AccountId = u32; - type Event = Event; - type PalletInfo = PalletInfo; - type Call = Call; - type DbWeight = (); - } - - frame_support::construct_runtime!( - pub enum RuntimeOriginTest where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic - { - System: system::{Pallet, Event, Origin}, - NestedModule3: nested::module3::{Pallet, Origin, Call}, - Module3: module3::{Pallet, Origin, Call}, - } - ); - - #[test] - fn origin_default_filter() { - let accepted_call = nested::module3::Call::fail {}.into(); - let rejected_call = module3::Call::fail {}.into(); - - assert_eq!(Origin::root().filter_call(&accepted_call), true); - assert_eq!(Origin::root().filter_call(&rejected_call), true); - assert_eq!(Origin::none().filter_call(&accepted_call), true); - assert_eq!(Origin::none().filter_call(&rejected_call), false); - assert_eq!(Origin::signed(0).filter_call(&accepted_call), true); - assert_eq!(Origin::signed(0).filter_call(&rejected_call), false); - assert_eq!(Origin::from(Some(0)).filter_call(&accepted_call), true); - assert_eq!(Origin::from(Some(0)).filter_call(&rejected_call), false); - assert_eq!(Origin::from(None).filter_call(&accepted_call), true); - assert_eq!(Origin::from(None).filter_call(&rejected_call), false); - assert_eq!(Origin::from(super::nested::module3::Origin).filter_call(&accepted_call), true); - assert_eq!(Origin::from(super::nested::module3::Origin).filter_call(&rejected_call), false); - - let mut origin = Origin::from(Some(0)); - origin.add_filter(|c| matches!(c, Call::Module3(_))); - assert_eq!(origin.filter_call(&accepted_call), false); - assert_eq!(origin.filter_call(&rejected_call), false); - - // Now test for root origin and filters: - let mut origin = Origin::from(Some(0)); - origin.set_caller_from(Origin::root()); - assert!(matches!(origin.caller, OriginCaller::system(super::system::RawOrigin::Root))); - - // Root origin bypass all filter. - assert_eq!(origin.filter_call(&accepted_call), true); - assert_eq!(origin.filter_call(&rejected_call), true); - - origin.set_caller_from(Origin::from(Some(0))); - - // Back to another signed origin, the filtered are now effective again - assert_eq!(origin.filter_call(&accepted_call), true); - assert_eq!(origin.filter_call(&rejected_call), false); - - origin.set_caller_from(Origin::root()); - origin.reset_filter(); - - // Root origin bypass all filter, even when they are reset. - assert_eq!(origin.filter_call(&accepted_call), true); - assert_eq!(origin.filter_call(&rejected_call), true); - } -} - #[test] fn check_modules_error_type() { assert_eq!( Module1_1::fail(system::Origin::::Root.into()), - Err(DispatchError::Module(ModuleError { index: 31, error: 0, message: Some("Something") })), + Err(DispatchError::Module(ModuleError { + index: 31, + error: [0; 4], + message: Some("Something") + })), ); assert_eq!( Module2::fail(system::Origin::::Root.into()), - Err(DispatchError::Module(ModuleError { index: 32, error: 0, message: Some("Something") })), + Err(DispatchError::Module(ModuleError { + index: 32, + error: [0; 4], + message: Some("Something") + })), ); assert_eq!( Module1_2::fail(system::Origin::::Root.into()), - Err(DispatchError::Module(ModuleError { index: 33, error: 0, message: Some("Something") })), + Err(DispatchError::Module(ModuleError { + index: 33, + error: [0; 4], + message: Some("Something") + })), ); assert_eq!( NestedModule3::fail(system::Origin::::Root.into()), - Err(DispatchError::Module(ModuleError { index: 34, error: 0, message: Some("Something") })), + Err(DispatchError::Module(ModuleError { + index: 34, + error: [0; 4], + message: Some("Something") + })), ); assert_eq!( Module1_3::fail(system::Origin::::Root.into()), - Err(DispatchError::Module(ModuleError { index: 6, error: 0, message: Some("Something") })), + Err(DispatchError::Module(ModuleError { + index: 6, + error: [0; 4], + message: Some("Something") + })), ); assert_eq!( Module1_4::fail(system::Origin::::Root.into()), - Err(DispatchError::Module(ModuleError { index: 3, error: 0, message: Some("Something") })), + Err(DispatchError::Module(ModuleError { + index: 3, + error: [0; 4], + message: Some("Something") + })), ); assert_eq!( Module1_5::fail(system::Origin::::Root.into()), - Err(DispatchError::Module(ModuleError { index: 4, error: 0, message: Some("Something") })), + Err(DispatchError::Module(ModuleError { + index: 4, + error: [0; 4], + message: Some("Something") + })), ); assert_eq!( Module1_6::fail(system::Origin::::Root.into()), - Err(DispatchError::Module(ModuleError { index: 1, error: 0, message: Some("Something") })), + Err(DispatchError::Module(ModuleError { + index: 1, + error: [0; 4], + message: Some("Something") + })), ); assert_eq!( Module1_7::fail(system::Origin::::Root.into()), - Err(DispatchError::Module(ModuleError { index: 2, error: 0, message: Some("Something") })), + Err(DispatchError::Module(ModuleError { + index: 2, + error: [0; 4], + message: Some("Something") + })), ); assert_eq!( Module1_8::fail(system::Origin::::Root.into()), - Err(DispatchError::Module(ModuleError { index: 12, error: 0, message: Some("Something") })), + Err(DispatchError::Module(ModuleError { + index: 12, + error: [0; 4], + message: Some("Something") + })), ); assert_eq!( Module1_9::fail(system::Origin::::Root.into()), - Err(DispatchError::Module(ModuleError { index: 13, error: 0, message: Some("Something") })), + Err(DispatchError::Module(ModuleError { + index: 13, + error: [0; 4], + message: Some("Something") + })), ); } diff --git a/frame/support/test/tests/construct_runtime_ui/pallet_error_too_large.rs b/frame/support/test/tests/construct_runtime_ui/pallet_error_too_large.rs new file mode 100644 index 000000000000..827d8a58af73 --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/pallet_error_too_large.rs @@ -0,0 +1,85 @@ +use frame_support::construct_runtime; +use sp_runtime::{generic, traits::BlakeTwo256}; +use sp_core::sr25519; + +#[frame_support::pallet] +mod pallet { + #[pallet::config] + pub trait Config: frame_system::Config {} + + #[pallet::pallet] + pub struct Pallet(core::marker::PhantomData); + + #[pallet::error] + pub enum Error { + MyError(crate::Nested1), + } +} + +#[derive(scale_info::TypeInfo, frame_support::PalletError, codec::Encode, codec::Decode)] +pub enum Nested1 { + Nested2(Nested2) +} + +#[derive(scale_info::TypeInfo, frame_support::PalletError, codec::Encode, codec::Decode)] +pub enum Nested2 { + Nested3(Nested3) +} + +#[derive(scale_info::TypeInfo, frame_support::PalletError, codec::Encode, codec::Decode)] +pub enum Nested3 { + Nested4(Nested4) +} + +#[derive(scale_info::TypeInfo, frame_support::PalletError, codec::Encode, codec::Decode)] +pub enum Nested4 { + Num(u8) +} + +pub type Signature = sr25519::Signature; +pub type BlockNumber = u32; +pub type Header = generic::Header; +pub type Block = generic::Block; +pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; + +impl pallet::Config for Runtime {} + +impl frame_system::Config for Runtime { + type BaseCallFilter = frame_support::traits::Everything; + type Origin = Origin; + type Index = u64; + type BlockNumber = u32; + type Call = Call; + type Hash = sp_runtime::testing::H256; + type Hashing = sp_runtime::traits::BlakeTwo256; + type AccountId = u64; + type Lookup = sp_runtime::traits::IdentityLookup; + type Header = Header; + type Event = Event; + type BlockHashCount = frame_support::traits::ConstU32<250>; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + +construct_runtime! { + pub enum Runtime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + System: frame_system::{Pallet, Call, Storage, Config, Event}, + Pallet: pallet::{Pallet}, + } +} + +fn main() {} diff --git a/frame/support/test/tests/construct_runtime_ui/pallet_error_too_large.stderr b/frame/support/test/tests/construct_runtime_ui/pallet_error_too_large.stderr new file mode 100644 index 000000000000..161873866b6f --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/pallet_error_too_large.stderr @@ -0,0 +1,13 @@ +error[E0080]: evaluation of constant value failed + --> tests/construct_runtime_ui/pallet_error_too_large.rs:74:1 + | +74 | / construct_runtime! { +75 | | pub enum Runtime where +76 | | Block = Block, +77 | | NodeBlock = Block, +... | +82 | | } +83 | | } + | |_^ the evaluated program panicked at 'The maximum encoded size of the error type in the `Pallet` pallet exceeds `MAX_MODULE_ERROR_ENCODED_SIZE`', $DIR/tests/construct_runtime_ui/pallet_error_too_large.rs:74:1 + | + = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/frame/support/test/tests/origin.rs b/frame/support/test/tests/origin.rs new file mode 100644 index 000000000000..1def44c15b48 --- /dev/null +++ b/frame/support/test/tests/origin.rs @@ -0,0 +1,214 @@ +// This file is part of Substrate. + +// Copyright (C) 2021 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. + +//! Origin tests for construct_runtime macro + +#![recursion_limit = "128"] + +use frame_support::traits::{Contains, OriginTrait}; +use scale_info::TypeInfo; +use sp_core::{sr25519, H256}; +use sp_runtime::{generic, traits::BlakeTwo256}; + +mod system; + +mod nested { + use super::*; + + pub mod module { + use super::*; + + pub trait Config: system::Config {} + + frame_support::decl_module! { + pub struct Module for enum Call + where origin: ::Origin, system=system + { + #[weight = 0] + pub fn fail(_origin) -> frame_support::dispatch::DispatchResult { + Err(Error::::Something.into()) + } + } + } + + #[derive(Clone, PartialEq, Eq, Debug, codec::Encode, codec::Decode, TypeInfo)] + pub struct Origin; + + frame_support::decl_event! { + pub enum Event { + A, + } + } + + frame_support::decl_error! { + pub enum Error for Module { + Something + } + } + + frame_support::decl_storage! { + trait Store for Module as Module {} + add_extra_genesis { + build(|_config| {}) + } + } + } +} + +pub mod module { + use super::*; + + pub trait Config: system::Config {} + + frame_support::decl_module! { + pub struct Module for enum Call + where origin: ::Origin, system=system + { + #[weight = 0] + pub fn fail(_origin) -> frame_support::dispatch::DispatchResult { + Err(Error::::Something.into()) + } + #[weight = 0] + pub fn aux_1(_origin, #[compact] _data: u32) -> frame_support::dispatch::DispatchResult { + unreachable!() + } + #[weight = 0] + pub fn aux_2(_origin, _data: i32, #[compact] _data2: u32) -> frame_support::dispatch::DispatchResult { + unreachable!() + } + #[weight = 0] + fn aux_3(_origin, _data: i32, _data2: String) -> frame_support::dispatch::DispatchResult { + unreachable!() + } + #[weight = 3] + fn aux_4(_origin) -> frame_support::dispatch::DispatchResult { unreachable!() } + #[weight = (5, frame_support::weights::DispatchClass::Operational)] + fn operational(_origin) { unreachable!() } + } + } + + #[derive(Clone, PartialEq, Eq, Debug, codec::Encode, codec::Decode, TypeInfo)] + pub struct Origin(pub core::marker::PhantomData); + + frame_support::decl_event! { + pub enum Event { + A, + } + } + + frame_support::decl_error! { + pub enum Error for Module { + Something + } + } + + frame_support::decl_storage! { + trait Store for Module as Module {} + add_extra_genesis { + build(|_config| {}) + } + } +} + +impl nested::module::Config for RuntimeOriginTest {} +impl module::Config for RuntimeOriginTest {} + +pub struct BaseCallFilter; +impl Contains for BaseCallFilter { + fn contains(c: &Call) -> bool { + match c { + Call::NestedModule(_) => true, + _ => false, + } + } +} + +impl system::Config for RuntimeOriginTest { + type BaseCallFilter = BaseCallFilter; + type Hash = H256; + type Origin = Origin; + type BlockNumber = BlockNumber; + type AccountId = u32; + type Event = Event; + type PalletInfo = PalletInfo; + type Call = Call; + type DbWeight = (); +} + +frame_support::construct_runtime!( + pub enum RuntimeOriginTest where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + System: system::{Pallet, Event, Origin}, + NestedModule: nested::module::{Pallet, Origin, Call}, + Module: module::{Pallet, Origin, Call}, + } +); + +pub type Signature = sr25519::Signature; +pub type BlockNumber = u64; +pub type Header = generic::Header; +pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; +pub type Block = generic::Block; + +#[test] +fn origin_default_filter() { + let accepted_call = nested::module::Call::fail {}.into(); + let rejected_call = module::Call::fail {}.into(); + + assert_eq!(Origin::root().filter_call(&accepted_call), true); + assert_eq!(Origin::root().filter_call(&rejected_call), true); + assert_eq!(Origin::none().filter_call(&accepted_call), true); + assert_eq!(Origin::none().filter_call(&rejected_call), false); + assert_eq!(Origin::signed(0).filter_call(&accepted_call), true); + assert_eq!(Origin::signed(0).filter_call(&rejected_call), false); + assert_eq!(Origin::from(Some(0)).filter_call(&accepted_call), true); + assert_eq!(Origin::from(Some(0)).filter_call(&rejected_call), false); + assert_eq!(Origin::from(None).filter_call(&accepted_call), true); + assert_eq!(Origin::from(None).filter_call(&rejected_call), false); + assert_eq!(Origin::from(nested::module::Origin).filter_call(&accepted_call), true); + assert_eq!(Origin::from(nested::module::Origin).filter_call(&rejected_call), false); + + let mut origin = Origin::from(Some(0)); + origin.add_filter(|c| matches!(c, Call::Module(_))); + assert_eq!(origin.filter_call(&accepted_call), false); + assert_eq!(origin.filter_call(&rejected_call), false); + + // Now test for root origin and filters: + let mut origin = Origin::from(Some(0)); + origin.set_caller_from(Origin::root()); + assert!(matches!(origin.caller, OriginCaller::system(system::RawOrigin::Root))); + + // Root origin bypass all filter. + assert_eq!(origin.filter_call(&accepted_call), true); + assert_eq!(origin.filter_call(&rejected_call), true); + + origin.set_caller_from(Origin::from(Some(0))); + + // Back to another signed origin, the filtered are now effective again + assert_eq!(origin.filter_call(&accepted_call), true); + assert_eq!(origin.filter_call(&rejected_call), false); + + origin.set_caller_from(Origin::root()); + origin.reset_filter(); + + // Root origin bypass all filter, even when they are reset. + assert_eq!(origin.filter_call(&accepted_call), true); + assert_eq!(origin.filter_call(&rejected_call), true); +} diff --git a/frame/support/test/tests/pallet.rs b/frame/support/test/tests/pallet.rs index 451cb2e7b889..83f6a722f93a 100644 --- a/frame/support/test/tests/pallet.rs +++ b/frame/support/test/tests/pallet.rs @@ -20,7 +20,7 @@ use frame_support::{ storage::unhashed, traits::{ ConstU32, GetCallName, GetStorageVersion, OnFinalize, OnGenesis, OnInitialize, - OnRuntimeUpgrade, PalletInfoAccess, StorageVersion, + OnRuntimeUpgrade, PalletError, PalletInfoAccess, StorageVersion, }, weights::{DispatchClass, DispatchInfo, GetDispatchInfo, Pays, RuntimeDbWeight}, }; @@ -229,9 +229,14 @@ pub mod pallet { } #[pallet::error] + #[derive(PartialEq, Eq)] pub enum Error { /// doc comment put into metadata InsufficientProposersBalance, + Code(u8), + #[codec(skip)] + Skipped(u128), + CompactU8(#[codec(compact)] u8), } #[pallet::event] @@ -656,10 +661,11 @@ fn error_expand() { DispatchError::from(pallet::Error::::InsufficientProposersBalance), DispatchError::Module(ModuleError { index: 1, - error: 0, + error: [0, 0, 0, 0], message: Some("InsufficientProposersBalance") }), ); + assert_eq!( as PalletError>::MAX_ENCODED_SIZE, 3); } #[test] diff --git a/frame/support/test/tests/pallet_instance.rs b/frame/support/test/tests/pallet_instance.rs index 30b9bcda88d1..118794e2fa20 100644 --- a/frame/support/test/tests/pallet_instance.rs +++ b/frame/support/test/tests/pallet_instance.rs @@ -343,7 +343,7 @@ fn error_expand() { DispatchError::from(pallet::Error::::InsufficientProposersBalance), DispatchError::Module(ModuleError { index: 1, - error: 0, + error: [0; 4], message: Some("InsufficientProposersBalance") }), ); @@ -364,7 +364,7 @@ fn error_expand() { ), DispatchError::Module(ModuleError { index: 2, - error: 0, + error: [0; 4], message: Some("InsufficientProposersBalance") }), ); diff --git a/frame/support/test/tests/pallet_ui/error_no_fieldless.rs b/frame/support/test/tests/pallet_ui/error_does_not_derive_pallet_error.rs similarity index 50% rename from frame/support/test/tests/pallet_ui/error_no_fieldless.rs rename to frame/support/test/tests/pallet_ui/error_does_not_derive_pallet_error.rs index c9d444d6f90d..254d65866774 100644 --- a/frame/support/test/tests/pallet_ui/error_no_fieldless.rs +++ b/frame/support/test/tests/pallet_ui/error_does_not_derive_pallet_error.rs @@ -1,25 +1,19 @@ #[frame_support::pallet] mod pallet { - use frame_support::pallet_prelude::Hooks; - use frame_system::pallet_prelude::BlockNumberFor; - #[pallet::config] pub trait Config: frame_system::Config {} #[pallet::pallet] pub struct Pallet(core::marker::PhantomData); - #[pallet::hooks] - impl Hooks> for Pallet {} - - #[pallet::call] - impl Pallet {} - #[pallet::error] pub enum Error { - U8(u8), + CustomError(crate::MyError), } } +#[derive(scale_info::TypeInfo, codec::Encode, codec::Decode)] +enum MyError {} + fn main() { } diff --git a/frame/support/test/tests/pallet_ui/error_does_not_derive_pallet_error.stderr b/frame/support/test/tests/pallet_ui/error_does_not_derive_pallet_error.stderr new file mode 100644 index 000000000000..2a8149e309ac --- /dev/null +++ b/frame/support/test/tests/pallet_ui/error_does_not_derive_pallet_error.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `MyError: PalletError` is not satisfied + --> tests/pallet_ui/error_does_not_derive_pallet_error.rs:1:1 + | +1 | #[frame_support::pallet] + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `PalletError` is not implemented for `MyError` + | +note: required by `MAX_ENCODED_SIZE` + --> $WORKSPACE/frame/support/src/traits/error.rs + | + | const MAX_ENCODED_SIZE: usize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in the derive macro `frame_support::PalletError` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/frame/support/test/tests/pallet_ui/error_no_fieldless.stderr b/frame/support/test/tests/pallet_ui/error_no_fieldless.stderr deleted file mode 100644 index 1d69fbeff9aa..000000000000 --- a/frame/support/test/tests/pallet_ui/error_no_fieldless.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: Invalid pallet::error, unexpected fields, must be `Unit` - --> $DIR/error_no_fieldless.rs:20:5 - | -20 | U8(u8), - | ^^^^ diff --git a/frame/support/test/tests/pallet_ui/pass/error_nested_types.rs b/frame/support/test/tests/pallet_ui/pass/error_nested_types.rs new file mode 100644 index 000000000000..1b6f584af23b --- /dev/null +++ b/frame/support/test/tests/pallet_ui/pass/error_nested_types.rs @@ -0,0 +1,41 @@ +use codec::{Decode, Encode}; +use frame_support::PalletError; + +#[frame_support::pallet] +mod pallet { + #[pallet::config] + pub trait Config: frame_system::Config {} + + #[pallet::pallet] + pub struct Pallet(core::marker::PhantomData); + + #[pallet::error] + pub enum Error { + CustomError(crate::MyError), + } +} + +#[derive(Encode, Decode, PalletError, scale_info::TypeInfo)] +pub enum MyError { + Foo, + Bar, + Baz(NestedError), + Struct(MyStruct), + Wrapper(Wrapper), +} + +#[derive(Encode, Decode, PalletError, scale_info::TypeInfo)] +pub enum NestedError { + Quux +} + +#[derive(Encode, Decode, PalletError, scale_info::TypeInfo)] +pub struct MyStruct { + field: u8, +} + +#[derive(Encode, Decode, PalletError, scale_info::TypeInfo)] +pub struct Wrapper(bool); + +fn main() { +} diff --git a/frame/utility/src/tests.rs b/frame/utility/src/tests.rs index 9a1e11f54d6e..44b07f70db14 100644 --- a/frame/utility/src/tests.rs +++ b/frame/utility/src/tests.rs @@ -38,7 +38,6 @@ use sp_runtime::{ // example module to test behaviors. #[frame_support::pallet] pub mod example { - use super::*; use frame_support::{dispatch::WithPostDispatchInfo, pallet_prelude::*}; use frame_system::pallet_prelude::*; diff --git a/primitives/block-builder/src/lib.rs b/primitives/block-builder/src/lib.rs index 229f115c6667..1b74c27b7ae4 100644 --- a/primitives/block-builder/src/lib.rs +++ b/primitives/block-builder/src/lib.rs @@ -20,11 +20,14 @@ #![cfg_attr(not(feature = "std"), no_std)] use sp_inherents::{CheckInherentsResult, InherentData}; -use sp_runtime::{traits::Block as BlockT, ApplyExtrinsicResult}; +use sp_runtime::{ + legacy::byte_sized_error::ApplyExtrinsicResult as ApplyExtrinsicResultBeforeV6, + traits::Block as BlockT, ApplyExtrinsicResult, +}; sp_api::decl_runtime_apis! { /// The `BlockBuilder` api trait that provides the required functionality for building a block. - #[api_version(5)] + #[api_version(6)] pub trait BlockBuilder { /// Apply the given extrinsic. /// @@ -32,6 +35,9 @@ sp_api::decl_runtime_apis! { /// this block or not. fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyExtrinsicResult; + #[changed_in(6)] + fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyExtrinsicResultBeforeV6; + /// Finish the current block. #[renamed("finalise_block", 3)] fn finalize_block() -> ::Header; diff --git a/primitives/runtime/src/legacy.rs b/primitives/runtime/src/legacy.rs new file mode 100644 index 000000000000..7bc7c88a7e10 --- /dev/null +++ b/primitives/runtime/src/legacy.rs @@ -0,0 +1,20 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +//! Runtime types that existed in old API versions. + +pub mod byte_sized_error; diff --git a/primitives/runtime/src/legacy/byte_sized_error.rs b/primitives/runtime/src/legacy/byte_sized_error.rs new file mode 100644 index 000000000000..049abff69ff1 --- /dev/null +++ b/primitives/runtime/src/legacy/byte_sized_error.rs @@ -0,0 +1,100 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +//! Runtime types that existed prior to BlockBuilder API version 6. + +use crate::{ArithmeticError, TokenError}; +use codec::{Decode, Encode}; +use scale_info::TypeInfo; +#[cfg(feature = "std")] +use serde::{Deserialize, Serialize}; + +/// [`ModuleError`] type definition before BlockBuilder API version 6. +#[derive(Eq, Clone, Copy, Encode, Decode, Debug, TypeInfo)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct ModuleError { + /// Module index, matching the metadata module index. + pub index: u8, + /// Module specific error value. + pub error: u8, + /// Optional error message. + #[codec(skip)] + #[cfg_attr(feature = "std", serde(skip_deserializing))] + pub message: Option<&'static str>, +} + +impl PartialEq for ModuleError { + fn eq(&self, other: &Self) -> bool { + (self.index == other.index) && (self.error == other.error) + } +} + +/// [`DispatchError`] type definition before BlockBuilder API version 6. +#[derive(Eq, Clone, Copy, Encode, Decode, Debug, TypeInfo, PartialEq)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub enum DispatchError { + /// Some error occurred. + Other( + #[codec(skip)] + #[cfg_attr(feature = "std", serde(skip_deserializing))] + &'static str, + ), + /// Failed to lookup some data. + CannotLookup, + /// A bad origin. + BadOrigin, + /// A custom error in a module. + Module(ModuleError), + /// At least one consumer is remaining so the account cannot be destroyed. + ConsumerRemaining, + /// There are no providers so the account cannot be created. + NoProviders, + /// There are too many consumers so the account cannot be created. + TooManyConsumers, + /// An error to do with tokens. + Token(TokenError), + /// An arithmetic error. + Arithmetic(ArithmeticError), +} + +/// [`DispatchOutcome`] type definition before BlockBuilder API version 6. +pub type DispatchOutcome = Result<(), DispatchError>; + +/// [`ApplyExtrinsicResult`] type definition before BlockBuilder API version 6. +pub type ApplyExtrinsicResult = + Result; + +/// Convert the legacy `ApplyExtrinsicResult` type to the latest version. +pub fn convert_to_latest(old: ApplyExtrinsicResult) -> crate::ApplyExtrinsicResult { + old.map(|outcome| { + outcome.map_err(|e| match e { + DispatchError::Other(s) => crate::DispatchError::Other(s), + DispatchError::CannotLookup => crate::DispatchError::CannotLookup, + DispatchError::BadOrigin => crate::DispatchError::BadOrigin, + DispatchError::Module(err) => crate::DispatchError::Module(crate::ModuleError { + index: err.index, + error: [err.error, 0, 0, 0], + message: err.message, + }), + DispatchError::ConsumerRemaining => crate::DispatchError::ConsumerRemaining, + DispatchError::NoProviders => crate::DispatchError::NoProviders, + DispatchError::TooManyConsumers => crate::DispatchError::TooManyConsumers, + DispatchError::Token(err) => crate::DispatchError::Token(err), + DispatchError::Arithmetic(err) => crate::DispatchError::Arithmetic(err), + }) + }) +} diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index a428da59f6a0..337fac5812ae 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -57,6 +57,7 @@ use scale_info::TypeInfo; pub mod curve; pub mod generic; +pub mod legacy; mod multiaddress; pub mod offchain; pub mod runtime_logger; @@ -97,6 +98,10 @@ pub use sp_arithmetic::{ pub use either::Either; +/// The number of bytes of the module-specific `error` field defined in [`ModuleError`]. +/// In FRAME, this is the maximum encoded size of a pallet error type. +pub const MAX_MODULE_ERROR_ENCODED_SIZE: usize = 4; + /// An abstraction over justification for a block's validity under a consensus algorithm. /// /// Essentially a finality proof. The exact formulation will vary between consensus @@ -468,7 +473,7 @@ pub struct ModuleError { /// Module index, matching the metadata module index. pub index: u8, /// Module specific error value. - pub error: u8, + pub error: [u8; MAX_MODULE_ERROR_ENCODED_SIZE], /// Optional error message. #[codec(skip)] #[cfg_attr(feature = "std", serde(skip_deserializing))] @@ -922,15 +927,15 @@ mod tests { fn dispatch_error_encoding() { let error = DispatchError::Module(ModuleError { index: 1, - error: 2, + error: [2, 0, 0, 0], message: Some("error message"), }); let encoded = error.encode(); let decoded = DispatchError::decode(&mut &encoded[..]).unwrap(); - assert_eq!(encoded, vec![3, 1, 2]); + assert_eq!(encoded, vec![3, 1, 2, 0, 0, 0]); assert_eq!( decoded, - DispatchError::Module(ModuleError { index: 1, error: 2, message: None }) + DispatchError::Module(ModuleError { index: 1, error: [2, 0, 0, 0], message: None }) ); } @@ -943,9 +948,9 @@ mod tests { Other("bar"), CannotLookup, BadOrigin, - Module(ModuleError { index: 1, error: 1, message: None }), - Module(ModuleError { index: 1, error: 2, message: None }), - Module(ModuleError { index: 2, error: 1, message: None }), + Module(ModuleError { index: 1, error: [1, 0, 0, 0], message: None }), + Module(ModuleError { index: 1, error: [2, 0, 0, 0], message: None }), + Module(ModuleError { index: 2, error: [1, 0, 0, 0], message: None }), ConsumerRemaining, NoProviders, Token(TokenError::NoFunds), @@ -970,8 +975,8 @@ mod tests { // Ignores `message` field in `Module` variant. assert_eq!( - Module(ModuleError { index: 1, error: 1, message: Some("foo") }), - Module(ModuleError { index: 1, error: 1, message: None }), + Module(ModuleError { index: 1, error: [1, 0, 0, 0], message: Some("foo") }), + Module(ModuleError { index: 1, error: [1, 0, 0, 0], message: None }), ); } diff --git a/primitives/runtime/src/traits.rs b/primitives/runtime/src/traits.rs index 1cea7c4e805c..ba4ca790a919 100644 --- a/primitives/runtime/src/traits.rs +++ b/primitives/runtime/src/traits.rs @@ -1554,6 +1554,12 @@ impl Printable for &[u8] { } } +impl Printable for [u8; N] { + fn print(&self) { + sp_io::misc::print_hex(&self[..]); + } +} + impl Printable for &str { fn print(&self) { sp_io::misc::print_utf8(self.as_bytes()); diff --git a/utils/frame/rpc/system/src/lib.rs b/utils/frame/rpc/system/src/lib.rs index eb1b258c97ec..0eae4d061afb 100644 --- a/utils/frame/rpc/system/src/lib.rs +++ b/utils/frame/rpc/system/src/lib.rs @@ -25,10 +25,11 @@ use jsonrpc_core::{Error as RpcError, ErrorCode}; use jsonrpc_derive::rpc; use sc_rpc_api::DenyUnsafe; use sc_transaction_pool_api::{InPoolTransaction, TransactionPool}; +use sp_api::ApiExt; use sp_block_builder::BlockBuilder; use sp_blockchain::HeaderBackend; use sp_core::{hexdisplay::HexDisplay, Bytes}; -use sp_runtime::{generic::BlockId, traits}; +use sp_runtime::{generic::BlockId, legacy, traits}; pub use self::gen_client::Client as SystemClient; pub use frame_system_rpc_runtime_api::AccountNonceApi; @@ -135,14 +136,40 @@ where .map_err(|e| RpcError { code: ErrorCode::ServerError(Error::DecodeError.into()), message: "Unable to dry run extrinsic.".into(), - data: Some(format!("{:?}", e).into()), + data: Some(e.to_string().into()), })?; - let result = api.apply_extrinsic(&at, uxt).map_err(|e| RpcError { - code: ErrorCode::ServerError(Error::RuntimeError.into()), - message: "Unable to dry run extrinsic.".into(), - data: Some(e.to_string().into()), - })?; + let api_version = api + .api_version::>(&at) + .map_err(|e| RpcError { + code: ErrorCode::ServerError(Error::RuntimeError.into()), + message: "Unable to dry run extrinsic.".into(), + data: Some(e.to_string().into()), + })? + .ok_or_else(|| RpcError { + code: ErrorCode::ServerError(Error::RuntimeError.into()), + message: "Unable to dry run extrinsic.".into(), + data: Some( + format!("Could not find `BlockBuilder` api for block `{:?}`.", at).into(), + ), + })?; + + let result = if api_version < 6 { + #[allow(deprecated)] + api.apply_extrinsic_before_version_6(&at, uxt) + .map(legacy::byte_sized_error::convert_to_latest) + .map_err(|e| RpcError { + code: ErrorCode::ServerError(Error::RuntimeError.into()), + message: "Unable to dry run extrinsic.".into(), + data: Some(e.to_string().into()), + })? + } else { + api.apply_extrinsic(&at, uxt).map_err(|e| RpcError { + code: ErrorCode::ServerError(Error::RuntimeError.into()), + message: "Unable to dry run extrinsic.".into(), + data: Some(e.to_string().into()), + })? + }; Ok(Encode::encode(&result).into()) }; From 56c28e858b2c3d7a6649988bdf3f48fd2eeb6fc5 Mon Sep 17 00:00:00 2001 From: Davide Galassi Date: Thu, 24 Mar 2022 09:51:55 +0100 Subject: [PATCH 633/695] BABE's revert procedure (#11022) * First rough draft for BABE revert * Proper babe revert test * Cleanup * Test trivial cleanup * Fix to make clippy happy * Check polkadot companion * Check cumulus companion * Remove babe's blocks weight on revert * Handle "empty" blockchain edge case * Run companions * Simplify the filter predicate * Saturating sub is not required * Run pipeline * Run pipeline again... --- bin/node-template/node/src/command.rs | 2 +- bin/node/cli/src/command.rs | 8 ++- client/cli/src/commands/revert_cmd.rs | 16 ++++- client/consensus/babe/src/lib.rs | 79 ++++++++++++++++++++- client/consensus/babe/src/tests.rs | 82 ++++++++++++++++++++++ client/consensus/epochs/src/lib.rs | 51 +++++++++++--- utils/fork-tree/src/lib.rs | 98 +++++++++++++++++++++++++-- 7 files changed, 314 insertions(+), 22 deletions(-) diff --git a/bin/node-template/node/src/command.rs b/bin/node-template/node/src/command.rs index 72c7a75b387b..66ee9fe45a55 100644 --- a/bin/node-template/node/src/command.rs +++ b/bin/node-template/node/src/command.rs @@ -95,7 +95,7 @@ pub fn run() -> sc_cli::Result<()> { runner.async_run(|config| { let PartialComponents { client, task_manager, backend, .. } = service::new_partial(&config)?; - Ok((cmd.run(client, backend), task_manager)) + Ok((cmd.run(client, backend, None), task_manager)) }) }, Some(Subcommand::Benchmark(cmd)) => diff --git a/bin/node/cli/src/command.rs b/bin/node/cli/src/command.rs index e208e324ee2a..3c2039fde475 100644 --- a/bin/node/cli/src/command.rs +++ b/bin/node/cli/src/command.rs @@ -168,7 +168,13 @@ pub fn run() -> Result<()> { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { let PartialComponents { client, task_manager, backend, .. } = new_partial(&config)?; - Ok((cmd.run(client, backend), task_manager)) + let revert_aux = Box::new(|client, backend, blocks| { + sc_consensus_babe::revert(client, backend, blocks)?; + // TODO: grandpa revert + Ok(()) + }); + + Ok((cmd.run(client, backend, Some(revert_aux)), task_manager)) }) }, #[cfg(feature = "try-runtime")] diff --git a/client/cli/src/commands/revert_cmd.rs b/client/cli/src/commands/revert_cmd.rs index c207d198d5a2..f65e348b37b8 100644 --- a/client/cli/src/commands/revert_cmd.rs +++ b/client/cli/src/commands/revert_cmd.rs @@ -24,7 +24,7 @@ use crate::{ use clap::Parser; use sc_client_api::{Backend, UsageProvider}; use sc_service::chain_ops::revert_chain; -use sp_runtime::traits::{Block as BlockT, Header as HeaderT}; +use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor}; use std::{fmt::Debug, str::FromStr, sync::Arc}; /// The `revert` command used revert the chain to a previous state. @@ -43,9 +43,18 @@ pub struct RevertCmd { pub pruning_params: PruningParams, } +/// Revert handler for auxiliary data (e.g. consensus). +type AuxRevertHandler = + Box, Arc, NumberFor) -> error::Result<()>>; + impl RevertCmd { /// Run the revert command - pub async fn run(&self, client: Arc, backend: Arc) -> error::Result<()> + pub async fn run( + &self, + client: Arc, + backend: Arc, + aux_revert: Option>, + ) -> error::Result<()> where B: BlockT, BA: Backend, @@ -53,6 +62,9 @@ impl RevertCmd { <<::Header as HeaderT>::Number as FromStr>::Err: Debug, { let blocks = self.num.parse()?; + if let Some(aux_revert) = aux_revert { + aux_revert(client.clone(), backend.clone(), blocks)?; + } revert_chain(client, backend, blocks)?; Ok(()) diff --git a/client/consensus/babe/src/lib.rs b/client/consensus/babe/src/lib.rs index 442dbab77e12..4f3139a013d4 100644 --- a/client/consensus/babe/src/lib.rs +++ b/client/consensus/babe/src/lib.rs @@ -92,8 +92,8 @@ use retain_mut::RetainMut; use schnorrkel::SignatureError; use sc_client_api::{ - backend::AuxStore, AuxDataOperations, BlockchainEvents, FinalityNotification, PreCommitActions, - ProvideUncles, UsageProvider, + backend::AuxStore, AuxDataOperations, Backend as BackendT, BlockchainEvents, + FinalityNotification, PreCommitActions, ProvideUncles, UsageProvider, }; use sc_consensus::{ block_import::{ @@ -113,7 +113,9 @@ use sc_telemetry::{telemetry, TelemetryHandle, CONSENSUS_DEBUG, CONSENSUS_TRACE} use sp_api::{ApiExt, ProvideRuntimeApi}; use sp_application_crypto::AppKey; use sp_block_builder::BlockBuilder as BlockBuilderApi; -use sp_blockchain::{Error as ClientError, HeaderBackend, HeaderMetadata, Result as ClientResult}; +use sp_blockchain::{ + Backend as _, Error as ClientError, HeaderBackend, HeaderMetadata, Result as ClientResult, +}; use sp_consensus::{ BlockOrigin, CacheKeyId, CanAuthorWith, Environment, Error as ConsensusError, Proposer, SelectChain, @@ -1830,3 +1832,74 @@ where Ok(BasicQueue::new(verifier, Box::new(block_import), justification_import, spawner, registry)) } + +/// Reverts aux data. +pub fn revert( + client: Arc, + backend: Arc, + blocks: NumberFor, +) -> ClientResult<()> +where + Block: BlockT, + Client: AuxStore + + HeaderMetadata + + HeaderBackend + + ProvideRuntimeApi + + UsageProvider, + Client::Api: BabeApi, + Backend: BackendT, +{ + let best_number = client.info().best_number; + let finalized = client.info().finalized_number; + let revertible = blocks.min(best_number - finalized); + + let number = best_number - revertible; + let hash = client + .block_hash_from_id(&BlockId::Number(number))? + .ok_or(ClientError::Backend(format!( + "Unexpected hash lookup failure for block number: {}", + number + )))?; + + // Revert epoch changes tree. + + let config = Config::get(&*client)?; + let epoch_changes = + aux_schema::load_epoch_changes::(&*client, config.genesis_config())?; + let mut epoch_changes = epoch_changes.shared_data(); + + if number == Zero::zero() { + // Special case, no epoch changes data were present on genesis. + *epoch_changes = EpochChangesFor::::default(); + } else { + epoch_changes.revert(descendent_query(&*client), hash, number); + } + + // Remove block weights added after the revert point. + + let mut weight_keys = HashSet::with_capacity(revertible.saturated_into()); + let leaves = backend.blockchain().leaves()?.into_iter().filter(|&leaf| { + sp_blockchain::tree_route(&*client, hash, leaf) + .map(|route| route.retracted().is_empty()) + .unwrap_or_default() + }); + for leaf in leaves { + let mut hash = leaf; + // Insert parent after parent until we don't hit an already processed + // branch or we reach a direct child of the rollback point. + while weight_keys.insert(aux_schema::block_weight_key(hash)) { + let meta = client.header_metadata(hash)?; + if meta.number <= number + One::one() { + // We've reached a child of the revert point, stop here. + break + } + hash = client.header_metadata(hash)?.parent; + } + } + let weight_keys: Vec<_> = weight_keys.iter().map(|val| val.as_slice()).collect(); + + // Write epoch changes and remove weights in one shot. + aux_schema::write_epoch_changes::(&epoch_changes, |values| { + client.insert_aux(values, weight_keys.iter()) + }) +} diff --git a/client/consensus/babe/src/tests.rs b/client/consensus/babe/src/tests.rs index d2de05bc9195..080387c88655 100644 --- a/client/consensus/babe/src/tests.rs +++ b/client/consensus/babe/src/tests.rs @@ -735,6 +735,88 @@ fn importing_block_one_sets_genesis_epoch() { assert_eq!(epoch_for_second_block, genesis_epoch); } +#[test] +fn revert_prunes_epoch_changes_and_removes_weights() { + let mut net = BabeTestNet::new(1); + + let peer = net.peer(0); + let data = peer.data.as_ref().expect("babe link set up during initialization"); + + let client = peer.client().as_client(); + let backend = peer.client().as_backend(); + let mut block_import = data.block_import.lock().take().expect("import set up during init"); + let epoch_changes = data.link.epoch_changes.clone(); + + let mut proposer_factory = DummyFactory { + client: client.clone(), + config: data.link.config.clone(), + epoch_changes: data.link.epoch_changes.clone(), + mutator: Arc::new(|_, _| ()), + }; + + let mut propose_and_import_blocks_wrap = |parent_id, n| { + propose_and_import_blocks(&client, &mut proposer_factory, &mut block_import, parent_id, n) + }; + + // Test scenario. + // Information for epoch 19 is produced on three different forks at block #13. + // One branch starts before the revert point (epoch data should be maintained). + // One branch starts after the revert point (epoch data should be removed). + // + // *----------------- F(#13) --#18 < fork #2 + // / + // A(#1) ---- B(#7) ----#8----+-----#12----- C(#13) ---- D(#19) ------#21 < canon + // \ ^ \ + // \ revert *---- G(#13) ---- H(#19) ---#20 < fork #3 + // \ to #10 + // *-----E(#7)---#11 < fork #1 + let canon = propose_and_import_blocks_wrap(BlockId::Number(0), 21); + let fork1 = propose_and_import_blocks_wrap(BlockId::Hash(canon[0]), 10); + let fork2 = propose_and_import_blocks_wrap(BlockId::Hash(canon[7]), 10); + let fork3 = propose_and_import_blocks_wrap(BlockId::Hash(canon[11]), 8); + + // We should be tracking a total of 9 epochs in the fork tree + assert_eq!(epoch_changes.shared_data().tree().iter().count(), 8); + // And only one root + assert_eq!(epoch_changes.shared_data().tree().roots().count(), 1); + + // Revert canon chain to block #10 (best(21) - 11) + revert(client.clone(), backend, 11).expect("revert should work for baked test scenario"); + + // Load and check epoch changes. + + let actual_nodes = aux_schema::load_epoch_changes::( + &*client, + data.link.config.genesis_config(), + ) + .expect("load epoch changes") + .shared_data() + .tree() + .iter() + .map(|(h, _, _)| *h) + .collect::>(); + + let expected_nodes = vec![ + canon[0], // A + canon[6], // B + fork2[4], // F + fork1[5], // E + ]; + + assert_eq!(actual_nodes, expected_nodes); + + let weight_data_check = |hashes: &[Hash], expected: bool| { + hashes.iter().all(|hash| { + aux_schema::load_block_weight(&*client, hash).unwrap().is_some() == expected + }) + }; + assert!(weight_data_check(&canon[..10], true)); + assert!(weight_data_check(&canon[10..], false)); + assert!(weight_data_check(&fork1, true)); + assert!(weight_data_check(&fork2, true)); + assert!(weight_data_check(&fork3, false)); +} + #[test] fn importing_epoch_change_block_prunes_tree() { let mut net = BabeTestNet::new(1); diff --git a/client/consensus/epochs/src/lib.rs b/client/consensus/epochs/src/lib.rs index b380d8ed5490..90081bf9af44 100644 --- a/client/consensus/epochs/src/lib.rs +++ b/client/consensus/epochs/src/lib.rs @@ -21,7 +21,7 @@ pub mod migration; use codec::{Decode, Encode}; -use fork_tree::ForkTree; +use fork_tree::{FilterAction, ForkTree}; use sc_client_api::utils::is_descendent_of; use sp_blockchain::{Error as ClientError, HeaderBackend, HeaderMetadata}; use sp_runtime::traits::{Block as BlockT, NumberFor, One, Zero}; @@ -660,15 +660,6 @@ where parent_number: Number, slot: E::Slot, ) -> Result>, fork_tree::Error> { - // find_node_where will give you the node in the fork-tree which is an ancestor - // of the `parent_hash` by default. if the last epoch was signalled at the parent_hash, - // then it won't be returned. we need to create a new fake chain head hash which - // "descends" from our parent-hash. - let fake_head_hash = fake_head_hash(parent_hash); - - let is_descendent_of = - descendent_of_builder.build_is_descendent_of(Some((fake_head_hash, *parent_hash))); - if parent_number == Zero::zero() { // need to insert the genesis epoch. return Ok(Some(ViableEpochDescriptor::UnimportedGenesis(slot))) @@ -683,6 +674,15 @@ where } } + // find_node_where will give you the node in the fork-tree which is an ancestor + // of the `parent_hash` by default. if the last epoch was signalled at the parent_hash, + // then it won't be returned. we need to create a new fake chain head hash which + // "descends" from our parent-hash. + let fake_head_hash = fake_head_hash(parent_hash); + + let is_descendent_of = + descendent_of_builder.build_is_descendent_of(Some((fake_head_hash, *parent_hash))); + // We want to find the deepest node in the tree which is an ancestor // of our block and where the start slot of the epoch was before the // slot of our block. The genesis special-case doesn't need to look @@ -798,6 +798,37 @@ where }); self.epochs.insert((hash, number), persisted); } + + /// Revert to a specified block given its `hash` and `number`. + /// This removes all the epoch changes information that were announced by + /// all the given block descendents. + pub fn revert>( + &mut self, + descendent_of_builder: D, + hash: Hash, + number: Number, + ) { + let is_descendent_of = descendent_of_builder.build_is_descendent_of(None); + + let filter = |node_hash: &Hash, node_num: &Number, _: &PersistedEpochHeader| { + if number >= *node_num && + (is_descendent_of(node_hash, &hash).unwrap_or_default() || *node_hash == hash) + { + // Continue the search in this subtree. + FilterAction::KeepNode + } else if number < *node_num && is_descendent_of(&hash, node_hash).unwrap_or_default() { + // Found a node to be removed. + FilterAction::Remove + } else { + // Not a parent or child of the one we're looking for, stop processing this branch. + FilterAction::KeepTree + } + }; + + self.inner.drain_filter(filter).for_each(|(h, n, _)| { + self.epochs.remove(&(h, n)); + }); + } } /// Type alias to produce the epoch-changes tree from a block type. diff --git a/utils/fork-tree/src/lib.rs b/utils/fork-tree/src/lib.rs index a718ff26213e..1d9b39f7dc04 100644 --- a/utils/fork-tree/src/lib.rs +++ b/utils/fork-tree/src/lib.rs @@ -69,6 +69,17 @@ pub enum FinalizationResult { Unchanged, } +/// Filtering action. +#[derive(Debug, PartialEq)] +pub enum FilterAction { + /// Remove the node and its subtree. + Remove, + /// Maintain the node. + KeepNode, + /// Maintain the node and its subtree. + KeepTree, +} + /// A tree data structure that stores several nodes across multiple branches. /// Top-level branches are called roots. The tree has functionality for /// finalizing nodes, which means that that node is traversed, and all competing @@ -624,6 +635,29 @@ where (None, false) => Ok(FinalizationResult::Unchanged), } } + + /// Remove from the tree some nodes (and their subtrees) using a `filter` predicate. + /// The `filter` is called over tree nodes and returns a filter action: + /// - `Remove` if the node and its subtree should be removed; + /// - `KeepNode` if we should maintain the node and keep processing the tree. + /// - `KeepTree` if we should maintain the node and its entire subtree. + /// An iterator over all the pruned nodes is returned. + pub fn drain_filter(&mut self, mut filter: F) -> impl Iterator + where + F: FnMut(&H, &N, &V) -> FilterAction, + { + let mut removed = Vec::new(); + let mut i = 0; + while i < self.roots.len() { + if self.roots[i].drain_filter(&mut filter, &mut removed) { + removed.push(self.roots.remove(i)); + } else { + i += 1; + } + } + self.rebalance(); + RemovedIterator { stack: removed } + } } // Workaround for: https://github.com/rust-lang/rust/issues/34537 @@ -849,6 +883,34 @@ mod node_implementation { }, } } + + /// Calls a `filter` predicate for the given node. + /// The `filter` is called over tree nodes and returns a filter action: + /// - `Remove` if the node and its subtree should be removed; + /// - `KeepNode` if we should maintain the node and keep processing the tree; + /// - `KeepTree` if we should maintain the node and its entire subtree. + /// Pruned subtrees are added to the `removed` list. + /// Returns a booleans indicateing if this node (and its subtree) should be removed. + pub fn drain_filter(&mut self, filter: &mut F, removed: &mut Vec>) -> bool + where + F: FnMut(&H, &N, &V) -> FilterAction, + { + match filter(&self.hash, &self.number, &self.data) { + FilterAction::KeepNode => { + let mut i = 0; + while i < self.children.len() { + if self.children[i].drain_filter(filter, removed) { + removed.push(self.children.remove(i)); + } else { + i += 1; + } + } + false + }, + FilterAction::KeepTree => false, + FilterAction::Remove => true, + } + } } } @@ -895,6 +957,8 @@ impl Iterator for RemovedIterator { #[cfg(test)] mod test { + use crate::FilterAction; + use super::{Error, FinalizationResult, ForkTree}; #[derive(Debug, PartialEq)] @@ -919,11 +983,11 @@ mod test { // / - G // / / // A - F - H - I - // \ - // - L - M \ - // - O - // \ - // — J - K + // \ \ + // \ - L - M + // \ \ + // \ - O + // - J - K // // (where N is not a part of fork tree) // @@ -1458,4 +1522,28 @@ mod test { ["A", "F", "H", "L", "O", "P", "M", "I", "G", "B", "C", "D", "E", "J", "K"] ); } + + #[test] + fn tree_drain_filter() { + let (mut tree, _) = test_fork_tree(); + + let filter = |h: &&str, _: &u64, _: &()| match *h { + "A" | "B" | "F" | "G" => FilterAction::KeepNode, + "C" => FilterAction::KeepTree, + "H" | "J" => FilterAction::Remove, + _ => panic!("Unexpected filtering for node: {}", *h), + }; + + let removed = tree.drain_filter(filter); + + assert_eq!( + tree.iter().map(|(h, _, _)| *h).collect::>(), + ["A", "B", "C", "D", "E", "F", "G"] + ); + + assert_eq!( + removed.map(|(h, _, _)| h).collect::>(), + ["J", "K", "H", "L", "M", "O", "I"] + ); + } } From dfb2a8cc35244a688e0b052eafb96c6e534ca5a4 Mon Sep 17 00:00:00 2001 From: Koute Date: Thu, 24 Mar 2022 22:19:17 +0900 Subject: [PATCH 634/695] Add extra WASM heap pages when precompiling the runtime blob (#11107) * Add extra WASM heap pages when precompiling the runtime blob * Fix compilation * Fix rustdoc * Fix rustdoc for real this time * Fix benches compilation * Improve the builder in `sc-executor-wasmtime`'s tests --- client/executor/benches/bench.rs | 2 +- client/executor/src/wasm_runtime.rs | 2 +- client/executor/wasmtime/src/runtime.rs | 47 ++++----- client/executor/wasmtime/src/tests.rs | 124 ++++++++++++++---------- 4 files changed, 100 insertions(+), 75 deletions(-) diff --git a/client/executor/benches/bench.rs b/client/executor/benches/bench.rs index 20632536571b..49ea8be50624 100644 --- a/client/executor/benches/bench.rs +++ b/client/executor/benches/bench.rs @@ -55,11 +55,11 @@ fn initialize(runtime: &[u8], method: Method) -> Arc { sc_executor_wasmtime::create_runtime::( blob, sc_executor_wasmtime::Config { - heap_pages, max_memory_size: None, allow_missing_func_imports, cache_path: None, semantics: sc_executor_wasmtime::Semantics { + extra_heap_pages: heap_pages, fast_instance_reuse, deterministic_stack_limit: None, canonicalize_nans: false, diff --git a/client/executor/src/wasm_runtime.rs b/client/executor/src/wasm_runtime.rs index d996d7b490e8..952130e98087 100644 --- a/client/executor/src/wasm_runtime.rs +++ b/client/executor/src/wasm_runtime.rs @@ -317,11 +317,11 @@ where WasmExecutionMethod::Compiled => sc_executor_wasmtime::create_runtime::( blob, sc_executor_wasmtime::Config { - heap_pages, max_memory_size: None, allow_missing_func_imports, cache_path: cache_path.map(ToOwned::to_owned), semantics: sc_executor_wasmtime::Semantics { + extra_heap_pages: heap_pages, fast_instance_reuse: true, deterministic_stack_limit: None, canonicalize_nans: false, diff --git a/client/executor/wasmtime/src/runtime.rs b/client/executor/wasmtime/src/runtime.rs index acf54e04e07f..cbe1359d28a6 100644 --- a/client/executor/wasmtime/src/runtime.rs +++ b/client/executor/wasmtime/src/runtime.rs @@ -414,20 +414,22 @@ pub struct Semantics { /// Configures wasmtime to use multiple threads for compiling. pub parallel_compilation: bool, + + /// The number of extra WASM pages which will be allocated + /// on top of what is requested by the WASM blob itself. + pub extra_heap_pages: u64, } pub struct Config { - /// The number of wasm pages to be mounted after instantiation. - pub heap_pages: u64, - /// The total amount of memory in bytes an instance can request. /// /// If specified, the runtime will be able to allocate only that much of wasm memory. - /// This is the total number and therefore the [`Config::heap_pages`] is accounted for. + /// This is the total number and therefore the [`Semantics::extra_heap_pages`] is accounted + /// for. /// /// That means that the initial number of pages of a linear memory plus the - /// [`Config::heap_pages`] multiplied by the wasm page size (64KiB) should be less than or - /// equal to `max_memory_size`, otherwise the instance won't be created. + /// [`Semantics::extra_heap_pages`] multiplied by the wasm page size (64KiB) should be less + /// than or equal to `max_memory_size`, otherwise the instance won't be created. /// /// Moreover, `memory.grow` will fail (return -1) if the sum of sizes of currently mounted /// and additional pages exceeds `max_memory_size`. @@ -534,21 +536,7 @@ where let (module, snapshot_data) = match code_supply_mode { CodeSupplyMode::Verbatim { blob } => { - let mut blob = instrument(blob, &config.semantics)?; - - // We don't actually need the memory to be imported so we can just convert any memory - // import into an export with impunity. This simplifies our code since `wasmtime` will - // now automatically take care of creating the memory for us, and it also allows us - // to potentially enable `wasmtime`'s instance pooling at a later date. (Imported - // memories are ineligible for pooling.) - blob.convert_memory_import_into_export()?; - blob.add_extra_heap_pages_to_memory_section( - config - .heap_pages - .try_into() - .map_err(|e| WasmError::Other(format!("invalid `heap_pages`: {}", e)))?, - )?; - + let blob = prepare_blob_for_compilation(blob, &config.semantics)?; let serialized_blob = blob.clone().serialize(); let module = wasmtime::Module::new(&engine, &serialized_blob) @@ -587,7 +575,7 @@ where Ok(WasmtimeRuntime { engine, instance_pre: Arc::new(instance_pre), snapshot_data, config }) } -fn instrument( +fn prepare_blob_for_compilation( mut blob: RuntimeBlob, semantics: &Semantics, ) -> std::result::Result { @@ -600,6 +588,19 @@ fn instrument( blob.expose_mutable_globals(); } + // We don't actually need the memory to be imported so we can just convert any memory + // import into an export with impunity. This simplifies our code since `wasmtime` will + // now automatically take care of creating the memory for us, and it also allows us + // to potentially enable `wasmtime`'s instance pooling at a later date. (Imported + // memories are ineligible for pooling.) + blob.convert_memory_import_into_export()?; + blob.add_extra_heap_pages_to_memory_section( + semantics + .extra_heap_pages + .try_into() + .map_err(|e| WasmError::Other(format!("invalid `extra_heap_pages`: {}", e)))?, + )?; + Ok(blob) } @@ -609,7 +610,7 @@ pub fn prepare_runtime_artifact( blob: RuntimeBlob, semantics: &Semantics, ) -> std::result::Result, WasmError> { - let blob = instrument(blob, semantics)?; + let blob = prepare_blob_for_compilation(blob, semantics)?; let engine = Engine::new(&common_config(semantics)?) .map_err(|e| WasmError::Other(format!("cannot create the engine: {}", e)))?; diff --git a/client/executor/wasmtime/src/tests.rs b/client/executor/wasmtime/src/tests.rs index a4ca0959da86..d5b92f2f24a7 100644 --- a/client/executor/wasmtime/src/tests.rs +++ b/client/executor/wasmtime/src/tests.rs @@ -28,8 +28,9 @@ struct RuntimeBuilder { fast_instance_reuse: bool, canonicalize_nans: bool, deterministic_stack: bool, - heap_pages: u64, + extra_heap_pages: u64, max_memory_size: Option, + precompile_runtime: bool, } impl RuntimeBuilder { @@ -41,34 +42,44 @@ impl RuntimeBuilder { fast_instance_reuse: false, canonicalize_nans: false, deterministic_stack: false, - heap_pages: 1024, + extra_heap_pages: 1024, max_memory_size: None, + precompile_runtime: false, } } - fn use_wat(&mut self, code: String) { + fn use_wat(&mut self, code: String) -> &mut Self { self.code = Some(code); + self } - fn canonicalize_nans(&mut self, canonicalize_nans: bool) { + fn canonicalize_nans(&mut self, canonicalize_nans: bool) -> &mut Self { self.canonicalize_nans = canonicalize_nans; + self } - fn deterministic_stack(&mut self, deterministic_stack: bool) { + fn deterministic_stack(&mut self, deterministic_stack: bool) -> &mut Self { self.deterministic_stack = deterministic_stack; + self } - fn max_memory_size(&mut self, max_memory_size: Option) { + fn precompile_runtime(&mut self, precompile_runtime: bool) -> &mut Self { + self.precompile_runtime = precompile_runtime; + self + } + + fn max_memory_size(&mut self, max_memory_size: Option) -> &mut Self { self.max_memory_size = max_memory_size; + self } - fn build(self) -> Arc { + fn build(&mut self) -> Arc { let blob = { let wasm: Vec; let wasm = match self.code { None => wasm_binary_unwrap(), - Some(wat) => { + Some(ref wat) => { wasm = wat::parse_str(wat).expect("wat parsing failed"); &wasm }, @@ -78,27 +89,31 @@ impl RuntimeBuilder { .expect("failed to create a runtime blob out of test runtime") }; - let rt = crate::create_runtime::( - blob, - crate::Config { - heap_pages: self.heap_pages, - max_memory_size: self.max_memory_size, - allow_missing_func_imports: true, - cache_path: None, - semantics: crate::Semantics { - fast_instance_reuse: self.fast_instance_reuse, - deterministic_stack_limit: match self.deterministic_stack { - true => Some(crate::DeterministicStackLimit { - logical_max: 65536, - native_stack_max: 256 * 1024 * 1024, - }), - false => None, - }, - canonicalize_nans: self.canonicalize_nans, - parallel_compilation: true, + let config = crate::Config { + max_memory_size: self.max_memory_size, + allow_missing_func_imports: true, + cache_path: None, + semantics: crate::Semantics { + fast_instance_reuse: self.fast_instance_reuse, + deterministic_stack_limit: match self.deterministic_stack { + true => Some(crate::DeterministicStackLimit { + logical_max: 65536, + native_stack_max: 256 * 1024 * 1024, + }), + false => None, }, + canonicalize_nans: self.canonicalize_nans, + parallel_compilation: true, + extra_heap_pages: self.extra_heap_pages, }, - ) + }; + + let rt = if self.precompile_runtime { + let artifact = crate::prepare_runtime_artifact(blob, &config.semantics).unwrap(); + unsafe { crate::create_runtime_from_artifact::(&artifact, config) } + } else { + crate::create_runtime::(blob, config) + } .expect("cannot create runtime"); Arc::new(rt) as Arc @@ -107,11 +122,7 @@ impl RuntimeBuilder { #[test] fn test_nan_canonicalization() { - let runtime = { - let mut builder = RuntimeBuilder::new_on_demand(); - builder.canonicalize_nans(true); - builder.build() - }; + let runtime = RuntimeBuilder::new_on_demand().canonicalize_nans(true).build(); let mut instance = runtime.new_instance().expect("failed to instantiate a runtime"); @@ -150,12 +161,10 @@ fn test_nan_canonicalization() { fn test_stack_depth_reaching() { const TEST_GUARD_PAGE_SKIP: &str = include_str!("test-guard-page-skip.wat"); - let runtime = { - let mut builder = RuntimeBuilder::new_on_demand(); - builder.use_wat(TEST_GUARD_PAGE_SKIP.to_string()); - builder.deterministic_stack(true); - builder.build() - }; + let runtime = RuntimeBuilder::new_on_demand() + .use_wat(TEST_GUARD_PAGE_SKIP.to_string()) + .deterministic_stack(true) + .build(); let mut instance = runtime.new_instance().expect("failed to instantiate a runtime"); match instance.call_export("test-many-locals", &[]).unwrap_err() { @@ -168,26 +177,36 @@ fn test_stack_depth_reaching() { } #[test] -fn test_max_memory_pages_imported_memory() { - test_max_memory_pages(true); +fn test_max_memory_pages_imported_memory_without_precompilation() { + test_max_memory_pages(true, false); +} + +#[test] +fn test_max_memory_pages_exported_memory_without_precompilation() { + test_max_memory_pages(false, false); } #[test] -fn test_max_memory_pages_exported_memory() { - test_max_memory_pages(false); +fn test_max_memory_pages_imported_memory_with_precompilation() { + test_max_memory_pages(true, true); } -fn test_max_memory_pages(import_memory: bool) { +#[test] +fn test_max_memory_pages_exported_memory_with_precompilation() { + test_max_memory_pages(false, true); +} + +fn test_max_memory_pages(import_memory: bool, precompile_runtime: bool) { fn try_instantiate( max_memory_size: Option, wat: String, + precompile_runtime: bool, ) -> Result<(), Box> { - let runtime = { - let mut builder = RuntimeBuilder::new_on_demand(); - builder.use_wat(wat); - builder.max_memory_size(max_memory_size); - builder.build() - }; + let runtime = RuntimeBuilder::new_on_demand() + .use_wat(wat) + .max_memory_size(max_memory_size) + .precompile_runtime(precompile_runtime) + .build(); let mut instance = runtime.new_instance()?; let _ = instance.call_export("main", &[])?; Ok(()) @@ -235,6 +254,7 @@ fn test_max_memory_pages(import_memory: bool) { */ memory(64511, None, import_memory) ), + precompile_runtime, ) .unwrap(); @@ -257,6 +277,7 @@ fn test_max_memory_pages(import_memory: bool) { // 1 initial, max is not specified. memory(1, None, import_memory) ), + precompile_runtime, ) .unwrap(); @@ -277,6 +298,7 @@ fn test_max_memory_pages(import_memory: bool) { // Max is 2048. memory(1, Some(2048), import_memory) ), + precompile_runtime, ) .unwrap(); @@ -309,6 +331,7 @@ fn test_max_memory_pages(import_memory: bool) { // Zero starting pages. memory(0, None, import_memory) ), + precompile_runtime, ) .unwrap(); @@ -341,6 +364,7 @@ fn test_max_memory_pages(import_memory: bool) { // Initial=1, meaning after heap pages mount the total will be already 1025. memory(1, None, import_memory) ), + precompile_runtime, ) .unwrap(); } @@ -353,7 +377,6 @@ fn test_instances_without_reuse_are_not_leaked() { let runtime = crate::create_runtime::( RuntimeBlob::uncompress_if_needed(wasm_binary_unwrap()).unwrap(), crate::Config { - heap_pages: 2048, max_memory_size: None, allow_missing_func_imports: true, cache_path: None, @@ -362,6 +385,7 @@ fn test_instances_without_reuse_are_not_leaked() { deterministic_stack_limit: None, canonicalize_nans: false, parallel_compilation: true, + extra_heap_pages: 2048, }, }, ) From 666f39b8a22108f57732215de006518738034ba2 Mon Sep 17 00:00:00 2001 From: Qinxuan Chen Date: Fri, 25 Mar 2022 00:36:58 +0800 Subject: [PATCH 635/695] pallet-referenda: make the pallet instanceable (#11089) Signed-off-by: koushiro --- frame/referenda/src/branch.rs | 14 +- frame/referenda/src/lib.rs | 244 ++++++++++++++++++---------------- frame/referenda/src/types.rs | 43 +++--- 3 files changed, 160 insertions(+), 141 deletions(-) diff --git a/frame/referenda/src/branch.rs b/frame/referenda/src/branch.rs index 6a4efa31e15e..f381f5fe5b70 100644 --- a/frame/referenda/src/branch.rs +++ b/frame/referenda/src/branch.rs @@ -59,7 +59,7 @@ impl From for ServiceBranch { impl ServiceBranch { /// Return the weight of the `nudge` function when it takes the branch denoted by `self`. - pub fn weight_of_nudge(self) -> frame_support::weights::Weight { + pub fn weight_of_nudge, I: 'static>(self) -> frame_support::weights::Weight { use ServiceBranch::*; match self { NoDeposit => T::WeightInfo::nudge_referendum_no_deposit(), @@ -81,7 +81,7 @@ impl ServiceBranch { } /// Return the maximum possible weight of the `nudge` function. - pub fn max_weight_of_nudge() -> frame_support::weights::Weight { + pub fn max_weight_of_nudge, I: 'static>() -> frame_support::weights::Weight { 0.max(T::WeightInfo::nudge_referendum_no_deposit()) .max(T::WeightInfo::nudge_referendum_preparing()) .max(T::WeightInfo::nudge_referendum_queued()) @@ -101,7 +101,9 @@ impl ServiceBranch { /// Return the weight of the `place_decision_deposit` function when it takes the branch denoted /// by `self`. - pub fn weight_of_deposit(self) -> Option { + pub fn weight_of_deposit, I: 'static>( + self, + ) -> Option { use ServiceBranch::*; Some(match self { Preparing => T::WeightInfo::place_decision_deposit_preparing(), @@ -124,7 +126,7 @@ impl ServiceBranch { } /// Return the maximum possible weight of the `place_decision_deposit` function. - pub fn max_weight_of_deposit() -> frame_support::weights::Weight { + pub fn max_weight_of_deposit, I: 'static>() -> frame_support::weights::Weight { 0.max(T::WeightInfo::place_decision_deposit_preparing()) .max(T::WeightInfo::place_decision_deposit_queued()) .max(T::WeightInfo::place_decision_deposit_not_queued()) @@ -154,7 +156,7 @@ impl From for OneFewerDecidingBranch { impl OneFewerDecidingBranch { /// Return the weight of the `one_fewer_deciding` function when it takes the branch denoted /// by `self`. - pub fn weight(self) -> frame_support::weights::Weight { + pub fn weight, I: 'static>(self) -> frame_support::weights::Weight { use OneFewerDecidingBranch::*; match self { QueueEmpty => T::WeightInfo::one_fewer_deciding_queue_empty(), @@ -164,7 +166,7 @@ impl OneFewerDecidingBranch { } /// Return the maximum possible weight of the `one_fewer_deciding` function. - pub fn max_weight() -> frame_support::weights::Weight { + pub fn max_weight, I: 'static>() -> frame_support::weights::Weight { 0.max(T::WeightInfo::one_fewer_deciding_queue_empty()) .max(T::WeightInfo::one_fewer_deciding_passing()) .max(T::WeightInfo::one_fewer_deciding_failing()) diff --git a/frame/referenda/src/lib.rs b/frame/referenda/src/lib.rs index fb19d2b9ed24..067775fd336d 100644 --- a/frame/referenda/src/lib.rs +++ b/frame/referenda/src/lib.rs @@ -83,15 +83,18 @@ use sp_std::{fmt::Debug, prelude::*}; mod branch; mod types; pub mod weights; -use branch::{BeginDecidingBranch, OneFewerDecidingBranch, ServiceBranch}; -pub use pallet::*; -pub use types::{ - BalanceOf, CallOf, Curve, DecidingStatus, DecidingStatusOf, Deposit, InsertSorted, - NegativeImbalanceOf, PalletsOriginOf, ReferendumIndex, ReferendumInfo, ReferendumInfoOf, - ReferendumStatus, ReferendumStatusOf, ScheduleAddressOf, TallyOf, TrackIdOf, TrackInfo, - TrackInfoOf, TracksInfo, VotesOf, + +use self::branch::{BeginDecidingBranch, OneFewerDecidingBranch, ServiceBranch}; +pub use self::{ + pallet::*, + types::{ + BalanceOf, CallOf, Curve, DecidingStatus, DecidingStatusOf, Deposit, InsertSorted, + NegativeImbalanceOf, PalletsOriginOf, ReferendumIndex, ReferendumInfo, ReferendumInfoOf, + ReferendumStatus, ReferendumStatusOf, ScheduleAddressOf, TallyOf, TrackIdOf, TrackInfo, + TrackInfoOf, TracksInfo, VotesOf, + }, + weights::WeightInfo, }; -pub use weights::WeightInfo; #[cfg(test)] mod mock; @@ -106,25 +109,33 @@ const ASSEMBLY_ID: LockIdentifier = *b"assembly"; #[frame_support::pallet] pub mod pallet { use super::*; - use frame_support::{pallet_prelude::*, traits::EnsureOrigin, Parameter}; + use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; - use sp_runtime::DispatchResult; #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] #[pallet::without_storage_info] - pub struct Pallet(_); + pub struct Pallet(_); #[pallet::config] - pub trait Config: frame_system::Config + Sized { + pub trait Config: frame_system::Config + Sized { // System level stuff. - type Call: Parameter + Dispatchable + From>; - type Event: From> + IsType<::Event>; + type Call: Parameter + Dispatchable + From>; + type Event: From> + IsType<::Event>; /// Weight information for extrinsics in this pallet. type WeightInfo: WeightInfo; /// The Scheduler. - type Scheduler: ScheduleAnon, PalletsOriginOf, Hash = Self::Hash> - + ScheduleNamed, PalletsOriginOf, Hash = Self::Hash>; + type Scheduler: ScheduleAnon< + Self::BlockNumber, + CallOf, + PalletsOriginOf, + Hash = Self::Hash, + > + ScheduleNamed< + Self::BlockNumber, + CallOf, + PalletsOriginOf, + Hash = Self::Hash, + >; /// Currency type for this pallet. type Currency: ReservableCurrency; // Origins and unbalances. @@ -133,7 +144,7 @@ pub mod pallet { /// Origin from which any vote may be killed. type KillOrigin: EnsureOrigin; /// Handler for the unbalanced reduction when slashing a preimage deposit. - type Slash: OnUnbalanced>; + type Slash: OnUnbalanced>; /// The counting type for votes. Usually just balance. type Votes: AtLeast32BitUnsigned + Copy + Parameter + Member; /// The tallying type. @@ -142,7 +153,7 @@ pub mod pallet { // Constants /// The minimum amount to be used as a deposit for a public referendum proposal. #[pallet::constant] - type SubmissionDeposit: Get>; + type SubmissionDeposit: Get>; /// Maximum size of the referendum queue for a single track. #[pallet::constant] @@ -162,7 +173,7 @@ pub mod pallet { // The other stuff. /// Information concerning the different referendum tracks. type Tracks: TracksInfo< - BalanceOf, + BalanceOf, Self::BlockNumber, Origin = ::PalletsOrigin, >; @@ -170,39 +181,40 @@ pub mod pallet { /// The next free referendum index, aka the number of referenda started so far. #[pallet::storage] - pub type ReferendumCount = StorageValue<_, ReferendumIndex, ValueQuery>; + pub type ReferendumCount = StorageValue<_, ReferendumIndex, ValueQuery>; /// Information concerning any given referendum. #[pallet::storage] - pub type ReferendumInfoFor = - StorageMap<_, Blake2_128Concat, ReferendumIndex, ReferendumInfoOf>; + pub type ReferendumInfoFor, I: 'static = ()> = + StorageMap<_, Blake2_128Concat, ReferendumIndex, ReferendumInfoOf>; /// The sorted list of referenda ready to be decided but not yet being decided, ordered by /// conviction-weighted approvals. /// /// This should be empty if `DecidingCount` is less than `TrackInfo::max_deciding`. #[pallet::storage] - pub type TrackQueue = StorageMap< + pub type TrackQueue, I: 'static = ()> = StorageMap< _, Twox64Concat, - TrackIdOf, + TrackIdOf, BoundedVec<(ReferendumIndex, T::Votes), T::MaxQueued>, ValueQuery, >; /// The number of referenda being decided currently. #[pallet::storage] - pub type DecidingCount = StorageMap<_, Twox64Concat, TrackIdOf, u32, ValueQuery>; + pub type DecidingCount, I: 'static = ()> = + StorageMap<_, Twox64Concat, TrackIdOf, u32, ValueQuery>; #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] - pub enum Event { + pub enum Event, I: 'static = ()> { /// A referendum has being submitted. Submitted { /// Index of the referendum. index: ReferendumIndex, /// The track (and by extension proposal dispatch origin) of this referendum. - track: TrackIdOf, + track: TrackIdOf, /// The hash of the proposal up for referendum. proposal_hash: T::Hash, }, @@ -213,7 +225,7 @@ pub mod pallet { /// The account who placed the deposit. who: T::AccountId, /// The amount placed by the account. - amount: BalanceOf, + amount: BalanceOf, }, /// The decision deposit has been refunded. DecisionDepositRefunded { @@ -222,21 +234,21 @@ pub mod pallet { /// The account who placed the deposit. who: T::AccountId, /// The amount placed by the account. - amount: BalanceOf, + amount: BalanceOf, }, /// A deposit has been slashaed. DepositSlashed { /// The account who placed the deposit. who: T::AccountId, /// The amount placed by the account. - amount: BalanceOf, + amount: BalanceOf, }, /// A referendum has moved into the deciding phase. DecisionStarted { /// Index of the referendum. index: ReferendumIndex, /// The track (and by extension proposal dispatch origin) of this referendum. - track: TrackIdOf, + track: TrackIdOf, /// The hash of the proposal up for referendum. proposal_hash: T::Hash, /// The current tally of votes in this referendum. @@ -293,7 +305,7 @@ pub mod pallet { } #[pallet::error] - pub enum Error { + pub enum Error { /// Referendum is not ongoing. NotOngoing, /// Referendum's decision deposit is already paid. @@ -319,7 +331,7 @@ pub mod pallet { } #[pallet::call] - impl Pallet { + impl, I: 'static> Pallet { /// Propose a referendum on a privileged action. /// /// - `origin`: must be `Signed` and the account must have `SubmissionDeposit` funds @@ -338,9 +350,10 @@ pub mod pallet { ) -> DispatchResult { let who = ensure_signed(origin)?; - let track = T::Tracks::track_for(&proposal_origin).map_err(|_| Error::::NoTrack)?; + let track = + T::Tracks::track_for(&proposal_origin).map_err(|_| Error::::NoTrack)?; let submission_deposit = Self::take_deposit(who, T::SubmissionDeposit::get())?; - let index = ReferendumCount::::mutate(|x| { + let index = ReferendumCount::::mutate(|x| { let r = *x; *x += 1; r @@ -360,9 +373,9 @@ pub mod pallet { in_queue: false, alarm: Self::set_alarm(nudge_call, now.saturating_add(T::UndecidingTimeout::get())), }; - ReferendumInfoFor::::insert(index, ReferendumInfo::Ongoing(status)); + ReferendumInfoFor::::insert(index, ReferendumInfo::Ongoing(status)); - Self::deposit_event(Event::::Submitted { index, track, proposal_hash }); + Self::deposit_event(Event::::Submitted { index, track, proposal_hash }); Ok(()) } @@ -374,24 +387,24 @@ pub mod pallet { /// posted. /// /// Emits `DecisionDepositPlaced`. - #[pallet::weight(ServiceBranch::max_weight_of_deposit::())] + #[pallet::weight(ServiceBranch::max_weight_of_deposit::())] pub fn place_decision_deposit( origin: OriginFor, index: ReferendumIndex, ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; let mut status = Self::ensure_ongoing(index)?; - ensure!(status.decision_deposit.is_none(), Error::::HasDeposit); - let track = Self::track(status.track).ok_or(Error::::NoTrack)?; + ensure!(status.decision_deposit.is_none(), Error::::HasDeposit); + let track = Self::track(status.track).ok_or(Error::::NoTrack)?; status.decision_deposit = Some(Self::take_deposit(who.clone(), track.decision_deposit)?); let now = frame_system::Pallet::::block_number(); let (info, _, branch) = Self::service_referendum(now, index, status); - ReferendumInfoFor::::insert(index, info); + ReferendumInfoFor::::insert(index, info); let e = - Event::::DecisionDepositPlaced { index, who, amount: track.decision_deposit }; + Event::::DecisionDepositPlaced { index, who, amount: track.decision_deposit }; Self::deposit_event(e); - Ok(branch.weight_of_deposit::().into()) + Ok(branch.weight_of_deposit::().into()) } /// Refund the Decision Deposit for a closed referendum back to the depositor. @@ -407,14 +420,15 @@ pub mod pallet { index: ReferendumIndex, ) -> DispatchResult { ensure_signed_or_root(origin)?; - let mut info = ReferendumInfoFor::::get(index).ok_or(Error::::BadReferendum)?; + let mut info = + ReferendumInfoFor::::get(index).ok_or(Error::::BadReferendum)?; let deposit = info .take_decision_deposit() - .map_err(|_| Error::::Unfinished)? - .ok_or(Error::::NoDeposit)?; + .map_err(|_| Error::::Unfinished)? + .ok_or(Error::::NoDeposit)?; Self::refund_deposit(Some(deposit.clone())); - ReferendumInfoFor::::insert(index, info); - let e = Event::::DecisionDepositRefunded { + ReferendumInfoFor::::insert(index, info); + let e = Event::::DecisionDepositRefunded { index, who: deposit.who, amount: deposit.amount, @@ -437,13 +451,13 @@ pub mod pallet { let _ = T::Scheduler::cancel(last_alarm); } Self::note_one_fewer_deciding(status.track); - Self::deposit_event(Event::::Cancelled { index, tally: status.tally }); + Self::deposit_event(Event::::Cancelled { index, tally: status.tally }); let info = ReferendumInfo::Cancelled( frame_system::Pallet::::block_number(), status.submission_deposit, status.decision_deposit, ); - ReferendumInfoFor::::insert(index, info); + ReferendumInfoFor::::insert(index, info); Ok(()) } @@ -461,11 +475,11 @@ pub mod pallet { let _ = T::Scheduler::cancel(last_alarm); } Self::note_one_fewer_deciding(status.track); - Self::deposit_event(Event::::Killed { index, tally: status.tally }); + Self::deposit_event(Event::::Killed { index, tally: status.tally }); Self::slash_deposit(Some(status.submission_deposit.clone())); Self::slash_deposit(status.decision_deposit.clone()); let info = ReferendumInfo::Killed(frame_system::Pallet::::block_number()); - ReferendumInfoFor::::insert(index, info); + ReferendumInfoFor::::insert(index, info); Ok(()) } @@ -473,7 +487,7 @@ pub mod pallet { /// /// - `origin`: must be `Root`. /// - `index`: the referendum to be advanced. - #[pallet::weight(ServiceBranch::max_weight_of_nudge::())] + #[pallet::weight(ServiceBranch::max_weight_of_nudge::())] pub fn nudge_referendum( origin: OriginFor, index: ReferendumIndex, @@ -485,9 +499,9 @@ pub mod pallet { status.alarm = None; let (info, dirty, branch) = Self::service_referendum(now, index, status); if dirty { - ReferendumInfoFor::::insert(index, info); + ReferendumInfoFor::::insert(index, info); } - Ok(Some(branch.weight_of_nudge::()).into()) + Ok(Some(branch.weight_of_nudge::()).into()) } /// Advance a track onto its next logical state. Only used internally. @@ -499,14 +513,14 @@ pub mod pallet { /// `DecidingCount` is not yet updated. This means that we should either: /// - begin deciding another referendum (and leave `DecidingCount` alone); or /// - decrement `DecidingCount`. - #[pallet::weight(OneFewerDecidingBranch::max_weight::())] + #[pallet::weight(OneFewerDecidingBranch::max_weight::())] pub fn one_fewer_deciding( origin: OriginFor, - track: TrackIdOf, + track: TrackIdOf, ) -> DispatchResultWithPostInfo { ensure_root(origin)?; - let track_info = T::Tracks::info(track).ok_or(Error::::BadTrack)?; - let mut track_queue = TrackQueue::::get(track); + let track_info = T::Tracks::info(track).ok_or(Error::::BadTrack)?; + let mut track_queue = TrackQueue::::get(track); let branch = if let Some((index, mut status)) = Self::next_for_deciding(&mut track_queue) { let now = frame_system::Pallet::::block_number(); @@ -515,23 +529,23 @@ pub mod pallet { if let Some(set_alarm) = maybe_alarm { Self::ensure_alarm_at(&mut status, index, set_alarm); } - ReferendumInfoFor::::insert(index, ReferendumInfo::Ongoing(status)); - TrackQueue::::insert(track, track_queue); + ReferendumInfoFor::::insert(index, ReferendumInfo::Ongoing(status)); + TrackQueue::::insert(track, track_queue); branch.into() } else { - DecidingCount::::mutate(track, |x| x.saturating_dec()); + DecidingCount::::mutate(track, |x| x.saturating_dec()); OneFewerDecidingBranch::QueueEmpty }; - Ok(Some(branch.weight::()).into()) + Ok(Some(branch.weight::()).into()) } } } -impl Polling for Pallet { +impl, I: 'static> Polling for Pallet { type Index = ReferendumIndex; - type Votes = VotesOf; + type Votes = VotesOf; type Moment = T::BlockNumber; - type Class = TrackIdOf; + type Class = TrackIdOf; fn classes() -> Vec { T::Tracks::tracks().iter().map(|x| x.0).collect() @@ -539,14 +553,14 @@ impl Polling for Pallet { fn access_poll( index: Self::Index, - f: impl FnOnce(PollStatus<&mut T::Tally, T::BlockNumber, TrackIdOf>) -> R, + f: impl FnOnce(PollStatus<&mut T::Tally, T::BlockNumber, TrackIdOf>) -> R, ) -> R { - match ReferendumInfoFor::::get(index) { + match ReferendumInfoFor::::get(index) { Some(ReferendumInfo::Ongoing(mut status)) => { let result = f(PollStatus::Ongoing(&mut status.tally, status.track)); let now = frame_system::Pallet::::block_number(); Self::ensure_alarm_at(&mut status, index, now + One::one()); - ReferendumInfoFor::::insert(index, ReferendumInfo::Ongoing(status)); + ReferendumInfoFor::::insert(index, ReferendumInfo::Ongoing(status)); result }, Some(ReferendumInfo::Approved(end, ..)) => f(PollStatus::Completed(end, true)), @@ -558,15 +572,15 @@ impl Polling for Pallet { fn try_access_poll( index: Self::Index, f: impl FnOnce( - PollStatus<&mut T::Tally, T::BlockNumber, TrackIdOf>, + PollStatus<&mut T::Tally, T::BlockNumber, TrackIdOf>, ) -> Result, ) -> Result { - match ReferendumInfoFor::::get(index) { + match ReferendumInfoFor::::get(index) { Some(ReferendumInfo::Ongoing(mut status)) => { let result = f(PollStatus::Ongoing(&mut status.tally, status.track))?; let now = frame_system::Pallet::::block_number(); Self::ensure_alarm_at(&mut status, index, now + One::one()); - ReferendumInfoFor::::insert(index, ReferendumInfo::Ongoing(status)); + ReferendumInfoFor::::insert(index, ReferendumInfo::Ongoing(status)); Ok(result) }, Some(ReferendumInfo::Approved(end, ..)) => f(PollStatus::Completed(end, true)), @@ -575,13 +589,13 @@ impl Polling for Pallet { } } - fn as_ongoing(index: Self::Index) -> Option<(T::Tally, TrackIdOf)> { + fn as_ongoing(index: Self::Index) -> Option<(T::Tally, TrackIdOf)> { Self::ensure_ongoing(index).ok().map(|x| (x.tally, x.track)) } #[cfg(feature = "runtime-benchmarks")] fn create_ongoing(class: Self::Class) -> Result { - let index = ReferendumCount::::mutate(|x| { + let index = ReferendumCount::::mutate(|x| { let r = *x; *x += 1; r @@ -590,7 +604,7 @@ impl Polling for Pallet { let dummy_account_id = codec::Decode::decode(&mut sp_runtime::traits::TrailingZeroInput::new(&b"dummy"[..])) .expect("infinite length input; no invalid inputs for type; qed"); - let mut status = ReferendumStatusOf:: { + let mut status = ReferendumStatusOf:: { track: class, origin: frame_support::dispatch::RawOrigin::Root.into(), proposal_hash: ::hash_of(&index), @@ -604,7 +618,7 @@ impl Polling for Pallet { alarm: None, }; Self::ensure_alarm_at(&mut status, index, sp_runtime::traits::Bounded::max_value()); - ReferendumInfoFor::::insert(index, ReferendumInfo::Ongoing(status)); + ReferendumInfoFor::::insert(index, ReferendumInfo::Ongoing(status)); Ok(index) } @@ -619,7 +633,7 @@ impl Polling for Pallet { } else { ReferendumInfo::Rejected(now, status.submission_deposit, status.decision_deposit) }; - ReferendumInfoFor::::insert(index, info); + ReferendumInfoFor::::insert(index, info); Ok(()) } @@ -633,20 +647,22 @@ impl Polling for Pallet { } } -impl Pallet { +impl, I: 'static> Pallet { /// Check that referendum `index` is in the `Ongoing` state and return the `ReferendumStatus` /// value, or `Err` otherwise. - pub fn ensure_ongoing(index: ReferendumIndex) -> Result, DispatchError> { - match ReferendumInfoFor::::get(index) { + pub fn ensure_ongoing( + index: ReferendumIndex, + ) -> Result, DispatchError> { + match ReferendumInfoFor::::get(index) { Some(ReferendumInfo::Ongoing(status)) => Ok(status), - _ => Err(Error::::NotOngoing.into()), + _ => Err(Error::::NotOngoing.into()), } } // Enqueue a proposal from a referendum which has presumably passed. fn schedule_enactment( index: ReferendumIndex, - track: &TrackInfoOf, + track: &TrackInfoOf, desired: DispatchTime, origin: PalletsOriginOf, call_hash: T::Hash, @@ -668,9 +684,9 @@ impl Pallet { /// Set an alarm to dispatch `call` at block number `when`. fn set_alarm( - call: impl Into>, + call: impl Into>, when: T::BlockNumber, - ) -> Option<(T::BlockNumber, ScheduleAddressOf)> { + ) -> Option<(T::BlockNumber, ScheduleAddressOf)> { let alarm_interval = T::AlarmInterval::get().max(One::one()); let when = (when + alarm_interval - One::one()) / alarm_interval * alarm_interval; let maybe_result = T::Scheduler::schedule( @@ -698,10 +714,10 @@ impl Pallet { /// /// This will properly set up the `confirming` item. fn begin_deciding( - status: &mut ReferendumStatusOf, + status: &mut ReferendumStatusOf, index: ReferendumIndex, now: T::BlockNumber, - track: &TrackInfoOf, + track: &TrackInfoOf, ) -> (Option, BeginDecidingBranch) { let is_passing = Self::is_passing( &status.tally, @@ -711,14 +727,14 @@ impl Pallet { &track.min_approval, ); status.in_queue = false; - Self::deposit_event(Event::::DecisionStarted { + Self::deposit_event(Event::::DecisionStarted { index, tally: status.tally.clone(), proposal_hash: status.proposal_hash.clone(), track: status.track.clone(), }); let confirming = if is_passing { - Self::deposit_event(Event::::ConfirmStarted { index }); + Self::deposit_event(Event::::ConfirmStarted { index }); Some(now.saturating_add(track.confirm_period)) } else { None @@ -737,21 +753,21 @@ impl Pallet { /// If `None`, then it is queued and should be nudged automatically as the queue gets drained. fn ready_for_deciding( now: T::BlockNumber, - track: &TrackInfoOf, + track: &TrackInfoOf, index: ReferendumIndex, - status: &mut ReferendumStatusOf, + status: &mut ReferendumStatusOf, ) -> (Option, ServiceBranch) { - let deciding_count = DecidingCount::::get(status.track); + let deciding_count = DecidingCount::::get(status.track); if deciding_count < track.max_deciding { // Begin deciding. - DecidingCount::::insert(status.track, deciding_count.saturating_add(1)); + DecidingCount::::insert(status.track, deciding_count.saturating_add(1)); let r = Self::begin_deciding(status, index, now, track); (r.0, r.1.into()) } else { // Add to queue. let item = (index, status.tally.ayes()); status.in_queue = true; - TrackQueue::::mutate(status.track, |q| q.insert_sorted_by_key(item, |x| x.1)); + TrackQueue::::mutate(status.track, |q| q.insert_sorted_by_key(item, |x| x.1)); (None, ServiceBranch::Queued) } } @@ -759,8 +775,8 @@ impl Pallet { /// Grab the index and status for the referendum which is the highest priority of those for the /// given track which are ready for being decided. fn next_for_deciding( - track_queue: &mut BoundedVec<(u32, VotesOf), T::MaxQueued>, - ) -> Option<(ReferendumIndex, ReferendumStatusOf)> { + track_queue: &mut BoundedVec<(u32, VotesOf), T::MaxQueued>, + ) -> Option<(ReferendumIndex, ReferendumStatusOf)> { loop { let (index, _) = track_queue.pop()?; match Self::ensure_ongoing(index) { @@ -773,7 +789,7 @@ impl Pallet { /// Schedule a call to `one_fewer_deciding` function via the dispatchable /// `defer_one_fewer_deciding`. We could theoretically call it immediately (and it would be /// overall more efficient), however the weights become rather less easy to measure. - fn note_one_fewer_deciding(track: TrackIdOf) { + fn note_one_fewer_deciding(track: TrackIdOf) { // Set an alarm call for the next block to nudge the track along. let now = frame_system::Pallet::::block_number(); let next_block = now + One::one(); @@ -801,7 +817,7 @@ impl Pallet { /// /// Returns `false` if nothing changed. fn ensure_alarm_at( - status: &mut ReferendumStatusOf, + status: &mut ReferendumStatusOf, index: ReferendumIndex, alarm: T::BlockNumber, ) -> bool { @@ -839,8 +855,8 @@ impl Pallet { fn service_referendum( now: T::BlockNumber, index: ReferendumIndex, - mut status: ReferendumStatusOf, - ) -> (ReferendumInfoOf, bool, ServiceBranch) { + mut status: ReferendumStatusOf, + ) -> (ReferendumInfoOf, bool, ServiceBranch) { let mut dirty = false; // Should it begin being decided? let track = match Self::track(status.track) { @@ -857,7 +873,7 @@ impl Pallet { if status.in_queue { // Does our position in the queue need updating? let ayes = status.tally.ayes(); - let mut queue = TrackQueue::::get(status.track); + let mut queue = TrackQueue::::get(status.track); let maybe_old_pos = queue.iter().position(|(x, _)| *x == index); let new_pos = queue.binary_search_by_key(&ayes, |x| x.1).unwrap_or_else(|x| x); branch = if maybe_old_pos.is_none() && new_pos > 0 { @@ -872,7 +888,7 @@ impl Pallet { } else { ServiceBranch::NotQueued }; - TrackQueue::::insert(status.track, queue); + TrackQueue::::insert(status.track, queue); } else { // Are we ready for deciding? branch = if status.decision_deposit.is_some() { @@ -897,7 +913,7 @@ impl Pallet { if status.deciding.is_none() && now >= timeout { // Too long without being decided - end it. Self::ensure_no_alarm(&mut status); - Self::deposit_event(Event::::TimedOut { index, tally: status.tally }); + Self::deposit_event(Event::::TimedOut { index, tally: status.tally }); return ( ReferendumInfo::TimedOut( now, @@ -931,7 +947,7 @@ impl Pallet { status.origin, call_hash, ); - Self::deposit_event(Event::::Confirmed { + Self::deposit_event(Event::::Confirmed { index, tally: status.tally, }); @@ -950,7 +966,7 @@ impl Pallet { // Start confirming dirty = true; deciding.confirming = Some(now.saturating_add(track.confirm_period)); - Self::deposit_event(Event::::ConfirmStarted { index }); + Self::deposit_event(Event::::ConfirmStarted { index }); ServiceBranch::BeginConfirming }, } @@ -959,7 +975,7 @@ impl Pallet { // Failed! Self::ensure_no_alarm(&mut status); Self::note_one_fewer_deciding(status.track); - Self::deposit_event(Event::::Rejected { index, tally: status.tally }); + Self::deposit_event(Event::::Rejected { index, tally: status.tally }); return ( ReferendumInfo::Rejected( now, @@ -974,7 +990,7 @@ impl Pallet { // Stop confirming dirty = true; deciding.confirming = None; - Self::deposit_event(Event::::ConfirmAborted { index }); + Self::deposit_event(Event::::ConfirmAborted { index }); ServiceBranch::EndConfirming } else { ServiceBranch::ContinueNotConfirming @@ -993,7 +1009,7 @@ impl Pallet { fn decision_time( deciding: &DecidingStatusOf, tally: &T::Tally, - track: &TrackInfoOf, + track: &TrackInfoOf, ) -> T::BlockNumber { deciding.confirming.unwrap_or_else(|| { // Set alarm to the point where the current voting would make it pass. @@ -1007,7 +1023,7 @@ impl Pallet { } /// Cancel the alarm in `status`, if one exists. - fn ensure_no_alarm(status: &mut ReferendumStatusOf) { + fn ensure_no_alarm(status: &mut ReferendumStatusOf) { if let Some((_, last_alarm)) = status.alarm.take() { // Incorrect alarm - cancel it. let _ = T::Scheduler::cancel(last_alarm); @@ -1017,29 +1033,29 @@ impl Pallet { /// Reserve a deposit and return the `Deposit` instance. fn take_deposit( who: T::AccountId, - amount: BalanceOf, - ) -> Result>, DispatchError> { + amount: BalanceOf, + ) -> Result>, DispatchError> { T::Currency::reserve(&who, amount)?; Ok(Deposit { who, amount }) } /// Return a deposit, if `Some`. - fn refund_deposit(deposit: Option>>) { + fn refund_deposit(deposit: Option>>) { if let Some(Deposit { who, amount }) = deposit { T::Currency::unreserve(&who, amount); } } /// Slash a deposit, if `Some`. - fn slash_deposit(deposit: Option>>) { + fn slash_deposit(deposit: Option>>) { if let Some(Deposit { who, amount }) = deposit { T::Slash::on_unbalanced(T::Currency::slash_reserved(&who, amount).0); - Self::deposit_event(Event::::DepositSlashed { who, amount }); + Self::deposit_event(Event::::DepositSlashed { who, amount }); } } /// Get the track info value for the track `id`. - fn track(id: TrackIdOf) -> Option<&'static TrackInfoOf> { + fn track(id: TrackIdOf) -> Option<&'static TrackInfoOf> { let tracks = T::Tracks::tracks(); let index = tracks.binary_search_by_key(&id, |x| x.0).unwrap_or_else(|x| x); Some(&tracks[index].1) diff --git a/frame/referenda/src/types.rs b/frame/referenda/src/types.rs index 8ea9fc3faf3d..622075100631 100644 --- a/frame/referenda/src/types.rs +++ b/frame/referenda/src/types.rs @@ -24,44 +24,45 @@ use scale_info::TypeInfo; use sp_runtime::RuntimeDebug; use sp_std::fmt::Debug; -pub type BalanceOf = - <::Currency as Currency<::AccountId>>::Balance; -pub type NegativeImbalanceOf = <::Currency as Currency< +pub type BalanceOf = + <>::Currency as Currency<::AccountId>>::Balance; +pub type NegativeImbalanceOf = <>::Currency as Currency< ::AccountId, >>::NegativeImbalance; -pub type CallOf = ::Call; -pub type VotesOf = ::Votes; -pub type TallyOf = ::Tally; +pub type CallOf = >::Call; +pub type VotesOf = >::Votes; +pub type TallyOf = >::Tally; pub type PalletsOriginOf = <::Origin as OriginTrait>::PalletsOrigin; -pub type ReferendumInfoOf = ReferendumInfo< - TrackIdOf, +pub type ReferendumInfoOf = ReferendumInfo< + TrackIdOf, PalletsOriginOf, ::BlockNumber, ::Hash, - BalanceOf, - TallyOf, + BalanceOf, + TallyOf, ::AccountId, - ScheduleAddressOf, + ScheduleAddressOf, >; -pub type ReferendumStatusOf = ReferendumStatus< - TrackIdOf, +pub type ReferendumStatusOf = ReferendumStatus< + TrackIdOf, PalletsOriginOf, ::BlockNumber, ::Hash, - BalanceOf, - TallyOf, + BalanceOf, + TallyOf, ::AccountId, - ScheduleAddressOf, + ScheduleAddressOf, >; pub type DecidingStatusOf = DecidingStatus<::BlockNumber>; -pub type TrackInfoOf = TrackInfo, ::BlockNumber>; -pub type TrackIdOf = <::Tracks as TracksInfo< - BalanceOf, +pub type TrackInfoOf = + TrackInfo, ::BlockNumber>; +pub type TrackIdOf = <>::Tracks as TracksInfo< + BalanceOf, ::BlockNumber, >>::Id; -pub type ScheduleAddressOf = <::Scheduler as Anon< +pub type ScheduleAddressOf = <>::Scheduler as Anon< ::BlockNumber, - CallOf, + CallOf, PalletsOriginOf, >>::Address; From 676932fb5543d5b316b4e494631d8e48f98b760d Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Thu, 24 Mar 2022 22:12:48 +0100 Subject: [PATCH 636/695] Clear storage before running the bench (#11109) Signed-off-by: Oliver Tale-Yazdi Co-authored-by: Shawn Tabrizi --- frame/bags-list/src/benchmarks.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frame/bags-list/src/benchmarks.rs b/frame/bags-list/src/benchmarks.rs index b94a97093d00..bcfd1e3392b0 100644 --- a/frame/bags-list/src/benchmarks.rs +++ b/frame/bags-list/src/benchmarks.rs @@ -144,6 +144,10 @@ frame_benchmarking::benchmarks! { // - both heavier's `prev` and `next` are nodes that will need to be read and written. // - `lighter` is the bag's `head`, so the bag will need to be read and written. + // clear any pre-existing storage. + // NOTE: safe to call outside block production + List::::unsafe_clear(); + let bag_thresh = T::BagThresholds::get()[0]; // insert the nodes in order From c16fa70d536b3733f83c3e50c9662cdfc4cb95f1 Mon Sep 17 00:00:00 2001 From: driemworks Date: Thu, 24 Mar 2022 21:12:20 -0500 Subject: [PATCH 637/695] update assetclassownership map --- bin/node-template/pallets/iris-assets/src/lib.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/bin/node-template/pallets/iris-assets/src/lib.rs b/bin/node-template/pallets/iris-assets/src/lib.rs index dcb9b8914213..f8b80e0dcd32 100644 --- a/bin/node-template/pallets/iris-assets/src/lib.rs +++ b/bin/node-template/pallets/iris-assets/src/lib.rs @@ -134,6 +134,8 @@ pub mod pallet { /// Store the map associating a node with the assets to which they have access /// /// asset_owner_accountid -> CID -> asset_class_owner_accountid + /// TODO: Make this a regular StorageMap, T::AccountId -> Vec + /// #[pallet::storage] #[pallet::getter(fn asset_access)] pub(super) type AssetAccess = StorageDoubleMap< @@ -376,8 +378,10 @@ pub mod pallet { >::insert(id.clone(), cid.clone()); let which_admin = T::Lookup::lookup(admin.clone())?; - let mut asset_ids = >::get(which_admin); - asset_ids.push(id.clone()); + + // let mut asset_ids = >::get(which_admin); + // asset_ids.push(id.clone()); + >::mutate(which_admin, |ids| { ids.push(id) }); >::mutate(|ids| ids.push(id.clone())); Self::deposit_event(Event::AssetClassCreated(id.clone())); From 08fd14d8d1b34798390d454632e0b6ab794d17ac Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Fri, 25 Mar 2022 12:27:43 +0100 Subject: [PATCH 638/695] Add `benchmark-block` command (#11091) * Add benchmark-block command Signed-off-by: Oliver Tale-Yazdi * Apply suggestions from code review Co-authored-by: Shawn Tabrizi * Beauty fixes Signed-off-by: Oliver Tale-Yazdi * Beauty fixes Signed-off-by: Oliver Tale-Yazdi Co-authored-by: Shawn Tabrizi Co-authored-by: parity-processbot <> --- Cargo.lock | 2 + bin/node/cli/src/cli.rs | 7 + bin/node/cli/src/command.rs | 7 + utils/frame/benchmarking-cli/Cargo.toml | 2 + .../frame/benchmarking-cli/src/block/bench.rs | 176 ++++++++++++++++++ utils/frame/benchmarking-cli/src/block/cmd.rs | 101 ++++++++++ utils/frame/benchmarking-cli/src/block/mod.rs | 24 +++ utils/frame/benchmarking-cli/src/lib.rs | 2 + .../benchmarking-cli/src/overhead/cmd.rs | 10 +- 9 files changed, 330 insertions(+), 1 deletion(-) create mode 100644 utils/frame/benchmarking-cli/src/block/bench.rs create mode 100644 utils/frame/benchmarking-cli/src/block/cmd.rs create mode 100644 utils/frame/benchmarking-cli/src/block/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 1b478fcc18a7..1731ded2906c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2129,6 +2129,7 @@ dependencies = [ "clap 3.1.6", "frame-benchmarking", "frame-support", + "frame-system", "handlebars", "hash-db", "hex", @@ -2160,6 +2161,7 @@ dependencies = [ "sp-std", "sp-storage", "sp-trie", + "thousands", ] [[package]] diff --git a/bin/node/cli/src/cli.rs b/bin/node/cli/src/cli.rs index a911cc26ef87..952c6311f8b3 100644 --- a/bin/node/cli/src/cli.rs +++ b/bin/node/cli/src/cli.rs @@ -42,6 +42,13 @@ pub enum Subcommand { #[clap(name = "benchmark", about = "Benchmark runtime pallets.")] Benchmark(frame_benchmarking_cli::BenchmarkCmd), + /// Benchmark the execution time of historic blocks and compare it to their consumed weight. + #[clap( + name = "benchmark-block", + about = "Benchmark the execution time of historic blocks and compare it to their consumed weight." + )] + BenchmarkBlock(frame_benchmarking_cli::BlockCmd), + /// Sub command for benchmarking the per-block and per-extrinsic execution overhead. #[clap( name = "benchmark-overhead", diff --git a/bin/node/cli/src/command.rs b/bin/node/cli/src/command.rs index 3c2039fde475..bd324b20fb01 100644 --- a/bin/node/cli/src/command.rs +++ b/bin/node/cli/src/command.rs @@ -98,6 +98,13 @@ pub fn run() -> Result<()> { You can enable it with `--features runtime-benchmarks`." .into()) }, + Some(Subcommand::BenchmarkBlock(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { + let PartialComponents { client, task_manager, .. } = new_partial(&config)?; + Ok((cmd.run(client), task_manager)) + }) + }, Some(Subcommand::BenchmarkOverhead(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|mut config| { diff --git a/utils/frame/benchmarking-cli/Cargo.toml b/utils/frame/benchmarking-cli/Cargo.toml index b28fe195a2f3..11bba2b37957 100644 --- a/utils/frame/benchmarking-cli/Cargo.toml +++ b/utils/frame/benchmarking-cli/Cargo.toml @@ -15,6 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] frame-benchmarking = { version = "4.0.0-dev", path = "../../../frame/benchmarking" } frame-support = { version = "4.0.0-dev", path = "../../../frame/support" } +frame-system = { version = "4.0.0-dev", path = "../../../frame/system" } sp-core = { version = "6.0.0", path = "../../../primitives/core" } sc-block-builder = { version = "0.10.0-dev", path = "../../../client/block-builder" } sc-service = { version = "0.10.0-dev", default-features = false, path = "../../../client/service" } @@ -50,6 +51,7 @@ hash-db = "0.15.2" hex = "0.4.3" memory-db = "0.29.0" rand = { version = "0.8.4", features = ["small_rng"] } +thousands = "0.2.0" [features] default = ["db", "sc-client-db/runtime-benchmarks"] diff --git a/utils/frame/benchmarking-cli/src/block/bench.rs b/utils/frame/benchmarking-cli/src/block/bench.rs new file mode 100644 index 000000000000..d3c1c97b04ab --- /dev/null +++ b/utils/frame/benchmarking-cli/src/block/bench.rs @@ -0,0 +1,176 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +//! Contains the core benchmarking logic. + +use codec::DecodeAll; +use frame_support::weights::constants::WEIGHT_PER_NANOS; +use frame_system::ConsumedWeight; +use sc_block_builder::{BlockBuilderApi, BlockBuilderProvider}; +use sc_cli::{Error, Result}; +use sc_client_api::{Backend as ClientBackend, BlockBackend, StorageProvider, UsageProvider}; +use sp_api::{ApiExt, Core, HeaderT, ProvideRuntimeApi}; +use sp_blockchain::Error::RuntimeApiError; +use sp_runtime::{generic::BlockId, traits::Block as BlockT, DigestItem, OpaqueExtrinsic}; +use sp_storage::StorageKey; + +use clap::Args; +use log::{info, warn}; +use serde::Serialize; +use std::{fmt::Debug, marker::PhantomData, sync::Arc, time::Instant}; +use thousands::Separable; + +use crate::storage::record::{StatSelect, Stats}; + +/// Log target for printing block weight info. +const LOG_TARGET: &'static str = "benchmark::block::weight"; + +/// Parameters for modifying the benchmark behaviour. +#[derive(Debug, Default, Serialize, Clone, PartialEq, Args)] +pub struct BenchmarkParams { + /// Number of the first block to consider. + #[clap(long)] + pub from: u32, + + /// Last block number to consider. + #[clap(long)] + pub to: u32, + + /// Number of times that the benchmark should be repeated for each block. + #[clap(long, default_value = "10")] + pub repeat: u32, +} + +/// Convenience closure for the [`Benchmark::run()`] function. +pub struct Benchmark { + client: Arc, + params: BenchmarkParams, + _p: PhantomData<(Block, BA, C)>, +} + +/// Helper for nano seconds. +type NanoSeconds = u64; + +impl Benchmark +where + Block: BlockT, + BA: ClientBackend, + C: BlockBuilderProvider + + ProvideRuntimeApi + + StorageProvider + + UsageProvider + + BlockBackend, + C::Api: ApiExt + BlockBuilderApi, +{ + /// Returns a new [`Self`] from the arguments. + pub fn new(client: Arc, params: BenchmarkParams) -> Self { + Self { client, params, _p: PhantomData } + } + + /// Benchmark the execution speed of historic blocks and log the results. + pub fn run(&self) -> Result<()> { + if self.params.from == 0 { + return Err("Cannot benchmark the genesis block".into()) + } + + for i in self.params.from..=self.params.to { + let block_num = BlockId::Number(i.into()); + let parent_num = BlockId::Number(((i - 1) as u32).into()); + let consumed = self.consumed_weight(&block_num)?; + + let block = + self.client.block(&block_num)?.ok_or(format!("Block {} not found", block_num))?; + let block = self.unsealed(block.block); + let took = self.measure_block(&block, &parent_num)?; + + self.log_weight(i, block.extrinsics().len(), consumed, took); + } + + Ok(()) + } + + /// Return the average *execution* aka. *import* time of the block. + fn measure_block(&self, block: &Block, parent_num: &BlockId) -> Result { + let mut record = Vec::::default(); + // Interesting part here: + // Execute the block multiple times and collect stats about its execution time. + for _ in 0..self.params.repeat { + let block = block.clone(); + let runtime_api = self.client.runtime_api(); + let start = Instant::now(); + + runtime_api + .execute_block(&parent_num, block) + .map_err(|e| Error::Client(RuntimeApiError(e)))?; + + record.push(start.elapsed().as_nanos() as NanoSeconds); + } + + let took = Stats::new(&record)?.select(StatSelect::Average); + Ok(took) + } + + /// Returns the total nanoseconds of a [`frame_system::ConsumedWeight`] for a block number. + /// + /// This is the post-dispatch corrected weight and is only available + /// after executing the block. + fn consumed_weight(&self, block: &BlockId) -> Result { + // Hard-coded key for System::BlockWeight. It could also be passed in as argument + // for the benchmark, but I think this should work as well. + let hash = hex::decode("26aa394eea5630e07c48ae0c9558cef734abf5cb34d6244378cddbf18e849d96")?; + let key = StorageKey(hash); + + let mut raw_weight = &self + .client + .storage(&block, &key)? + .ok_or(format!("Could not find System::BlockWeight for block: {}", block))? + .0[..]; + + let weight = ConsumedWeight::decode_all(&mut raw_weight)?; + // Should be divisible, but still use floats in case we ever change that. + Ok((weight.total() as f64 / WEIGHT_PER_NANOS as f64).floor() as NanoSeconds) + } + + /// Prints the weight info of a block to the console. + fn log_weight(&self, num: u32, num_ext: usize, consumed: NanoSeconds, took: NanoSeconds) { + // The ratio of weight that the block used vs what it consumed. + // This should in general not exceed 100% (minus outliers). + let percent = (took as f64 / consumed as f64) * 100.0; + + let msg = format!( + "Block {} with {: >5} tx used {: >6.2}% of its weight ({: >14} of {: >14} ns)", + num, + num_ext, + percent, + took.separate_with_commas(), + consumed.separate_with_commas() + ); + + if took <= consumed { + info!(target: LOG_TARGET, "{}", msg); + } else { + warn!(target: LOG_TARGET, "{} - OVER WEIGHT!", msg); + } + } + + /// Removes the consensus seal from the block. + fn unsealed(&self, block: Block) -> Block { + let (mut header, exts) = block.deconstruct(); + header.digest_mut().logs.retain(|item| !matches!(item, DigestItem::Seal(_, _))); + Block::new(header, exts) + } +} diff --git a/utils/frame/benchmarking-cli/src/block/cmd.rs b/utils/frame/benchmarking-cli/src/block/cmd.rs new file mode 100644 index 000000000000..4618c1dd894e --- /dev/null +++ b/utils/frame/benchmarking-cli/src/block/cmd.rs @@ -0,0 +1,101 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +//! Contains the [`BlockCmd`] as entry point for the CLI to execute +//! the *block* benchmark. + +use sc_block_builder::{BlockBuilderApi, BlockBuilderProvider}; +use sc_cli::{CliConfiguration, ImportParams, Result, SharedParams}; +use sc_client_api::{Backend as ClientBackend, BlockBackend, StorageProvider, UsageProvider}; +use sp_api::{ApiExt, ProvideRuntimeApi}; +use sp_runtime::{traits::Block as BlockT, OpaqueExtrinsic}; + +use clap::Parser; +use std::{fmt::Debug, sync::Arc}; + +use super::bench::{Benchmark, BenchmarkParams}; + +/// Benchmark the execution time historic blocks. +/// +/// This can be used to verify that blocks do not use more weight than they consumed +/// in their `WeightInfo`. Example: +/// +/// Let's say you are on a Substrate chain and want to verify that the first 3 blocks +/// did not use more weight than declared which would otherwise be an issue. +/// To test this with a dev node, first create one with a temp directory: +/// +/// $ substrate --dev -d /tmp/my-dev --execution wasm --wasm-execution compiled +/// +/// And wait some time to let it produce 3 blocks. Then benchmark them with: +/// +/// $ substrate benchmark-block --from 1 --to 3 --dev -d /tmp/my-dev +/// --execution wasm --wasm-execution compiled --pruning archive +/// +/// The output will be similar to this: +/// +/// Block 1 with 1 tx used 77.34% of its weight ( 5,308,964 of 6,864,645 ns) +/// Block 2 with 1 tx used 77.99% of its weight ( 5,353,992 of 6,864,645 ns) +/// Block 3 with 1 tx used 75.91% of its weight ( 5,305,938 of 6,989,645 ns) +/// +/// The percent number is important and indicates how much weight +/// was used as compared to the consumed weight. +/// This number should be below 100% for reference hardware. +#[derive(Debug, Parser)] +pub struct BlockCmd { + #[allow(missing_docs)] + #[clap(flatten)] + pub shared_params: SharedParams, + + #[allow(missing_docs)] + #[clap(flatten)] + pub import_params: ImportParams, + + #[allow(missing_docs)] + #[clap(flatten)] + pub params: BenchmarkParams, +} + +impl BlockCmd { + /// Benchmark the execution time of historic blocks and compare it to their consumed weight. + /// + /// Output will be printed to console. + pub async fn run(&self, client: Arc) -> Result<()> + where + Block: BlockT, + BA: ClientBackend, + C: BlockBuilderProvider + + BlockBackend + + ProvideRuntimeApi + + StorageProvider + + UsageProvider, + C::Api: ApiExt + BlockBuilderApi, + { + // Put everything in the benchmark type to have the generic types handy. + Benchmark::new(client, self.params.clone()).run() + } +} + +// Boilerplate +impl CliConfiguration for BlockCmd { + fn shared_params(&self) -> &SharedParams { + &self.shared_params + } + + fn import_params(&self) -> Option<&ImportParams> { + Some(&self.import_params) + } +} diff --git a/utils/frame/benchmarking-cli/src/block/mod.rs b/utils/frame/benchmarking-cli/src/block/mod.rs new file mode 100644 index 000000000000..97fdb6ad2c20 --- /dev/null +++ b/utils/frame/benchmarking-cli/src/block/mod.rs @@ -0,0 +1,24 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +//! Crate to benchmark the execution time of historic blocks +//! and compare it to their consumed weight. + +mod bench; +mod cmd; + +pub use cmd::BlockCmd; diff --git a/utils/frame/benchmarking-cli/src/lib.rs b/utils/frame/benchmarking-cli/src/lib.rs index e06d57963dad..288e6b4b8615 100644 --- a/utils/frame/benchmarking-cli/src/lib.rs +++ b/utils/frame/benchmarking-cli/src/lib.rs @@ -15,6 +15,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +mod block; mod command; pub mod overhead; mod post_processing; @@ -24,6 +25,7 @@ mod writer; use sc_cli::{ExecutionStrategy, WasmExecutionMethod, DEFAULT_WASM_EXECUTION_METHOD}; use std::{fmt::Debug, path::PathBuf}; +pub use block::BlockCmd; pub use overhead::{ExtrinsicBuilder, OverheadCmd}; pub use storage::StorageCmd; diff --git a/utils/frame/benchmarking-cli/src/overhead/cmd.rs b/utils/frame/benchmarking-cli/src/overhead/cmd.rs index 8c75627fe246..f74c32ba72a8 100644 --- a/utils/frame/benchmarking-cli/src/overhead/cmd.rs +++ b/utils/frame/benchmarking-cli/src/overhead/cmd.rs @@ -19,7 +19,7 @@ //! the *overhead* benchmarks. use sc_block_builder::{BlockBuilderApi, BlockBuilderProvider}; -use sc_cli::{CliConfiguration, Result, SharedParams}; +use sc_cli::{CliConfiguration, ImportParams, Result, SharedParams}; use sc_client_api::Backend as ClientBackend; use sc_service::Configuration; use sp_api::{ApiExt, ProvideRuntimeApi}; @@ -45,6 +45,10 @@ pub struct OverheadCmd { #[clap(flatten)] pub shared_params: SharedParams, + #[allow(missing_docs)] + #[clap(flatten)] + pub import_params: ImportParams, + #[allow(missing_docs)] #[clap(flatten)] pub params: OverheadParams, @@ -115,4 +119,8 @@ impl CliConfiguration for OverheadCmd { fn shared_params(&self) -> &SharedParams { &self.shared_params } + + fn import_params(&self) -> Option<&ImportParams> { + Some(&self.import_params) + } } From 26ea75756b44de8b83f927c63c6ed46a0f040386 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Fri, 25 Mar 2022 09:42:54 -0400 Subject: [PATCH 639/695] Improve Bounties and Child Bounties Deposit Logic (#11014) * basic idea * make tests better * update bounties pallet to also have similar logic * new test verifies logic for bounty pallet * add test for new child logic * better name * make `node` compile with bounties changes * * formatting * use uniform notion of parent and child, no "master" or "general" entity * README updated to match comments * Revert "* formatting" This reverts commit 1ab729e7c23b5db24a8e229d487bbc2ed81d38c3. * update bounties logic to use bounds * fix child * bounties test for max * update tests * check min bound * update node * remove stale comment * Update frame/bounties/src/lib.rs Co-authored-by: Dan Shields --- bin/node/runtime/src/lib.rs | 34 +-- frame/bounties/src/lib.rs | 32 ++- frame/bounties/src/tests.rs | 134 +++++++++-- frame/child-bounties/src/lib.rs | 35 ++- frame/child-bounties/src/tests.rs | 358 +++++++++++++++++++++++------- 5 files changed, 460 insertions(+), 133 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index a6d97cb299b2..47bdedbab83a 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -220,7 +220,7 @@ impl frame_system::Config for Runtime { type SystemWeightInfo = frame_system::weights::SubstrateWeight; type SS58Prefix = ConstU16<42>; type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type MaxConsumers = ConstU32<16>; } impl pallet_randomness_collective_flip::Config for Runtime {} @@ -827,7 +827,7 @@ impl pallet_democracy::Config for Runtime { type Slash = Treasury; type Scheduler = Scheduler; type PalletsOrigin = OriginCaller; - type MaxVotes = frame_support::traits::ConstU32<100>; + type MaxVotes = ConstU32<100>; type WeightInfo = pallet_democracy::weights::SubstrateWeight; type MaxProposals = MaxProposals; } @@ -929,17 +929,9 @@ parameter_types! { pub const TipFindersFee: Percent = Percent::from_percent(20); pub const TipReportDepositBase: Balance = 1 * DOLLARS; pub const DataDepositPerByte: Balance = 1 * CENTS; - pub const BountyDepositBase: Balance = 1 * DOLLARS; - pub const BountyDepositPayoutDelay: BlockNumber = 1 * DAYS; pub const TreasuryPalletId: PalletId = PalletId(*b"py/trsry"); - pub const BountyUpdatePeriod: BlockNumber = 14 * DAYS; pub const MaximumReasonLength: u32 = 300; - pub const BountyCuratorDeposit: Permill = Permill::from_percent(50); - pub const BountyValueMinimum: Balance = 5 * DOLLARS; pub const MaxApprovals: u32 = 100; - pub const MaxActiveChildBountyCount: u32 = 5; - pub const ChildBountyValueMinimum: Balance = 1 * DOLLARS; - pub const ChildBountyCuratorDepositBase: Permill = Permill::from_percent(10); } impl pallet_treasury::Config for Runtime { @@ -966,12 +958,25 @@ impl pallet_treasury::Config for Runtime { type MaxApprovals = MaxApprovals; } +parameter_types! { + pub const BountyCuratorDeposit: Permill = Permill::from_percent(50); + pub const BountyValueMinimum: Balance = 5 * DOLLARS; + pub const BountyDepositBase: Balance = 1 * DOLLARS; + pub const CuratorDepositMultiplier: Permill = Permill::from_percent(50); + pub const CuratorDepositMin: Balance = 1 * DOLLARS; + pub const CuratorDepositMax: Balance = 100 * DOLLARS; + pub const BountyDepositPayoutDelay: BlockNumber = 1 * DAYS; + pub const BountyUpdatePeriod: BlockNumber = 14 * DAYS; +} + impl pallet_bounties::Config for Runtime { type Event = Event; type BountyDepositBase = BountyDepositBase; type BountyDepositPayoutDelay = BountyDepositPayoutDelay; type BountyUpdatePeriod = BountyUpdatePeriod; - type BountyCuratorDeposit = BountyCuratorDeposit; + type CuratorDepositMultiplier = CuratorDepositMultiplier; + type CuratorDepositMin = CuratorDepositMin; + type CuratorDepositMax = CuratorDepositMax; type BountyValueMinimum = BountyValueMinimum; type DataDepositPerByte = DataDepositPerByte; type MaximumReasonLength = MaximumReasonLength; @@ -979,11 +984,14 @@ impl pallet_bounties::Config for Runtime { type ChildBountyManager = ChildBounties; } +parameter_types! { + pub const ChildBountyValueMinimum: Balance = 1 * DOLLARS; +} + impl pallet_child_bounties::Config for Runtime { type Event = Event; - type MaxActiveChildBountyCount = MaxActiveChildBountyCount; + type MaxActiveChildBountyCount = ConstU32<5>; type ChildBountyValueMinimum = ChildBountyValueMinimum; - type ChildBountyCuratorDepositBase = ChildBountyCuratorDepositBase; type WeightInfo = pallet_child_bounties::weights::SubstrateWeight; } diff --git a/frame/bounties/src/lib.rs b/frame/bounties/src/lib.rs index 988b15c58a13..98f2da305a06 100644 --- a/frame/bounties/src/lib.rs +++ b/frame/bounties/src/lib.rs @@ -196,10 +196,20 @@ pub mod pallet { #[pallet::constant] type BountyUpdatePeriod: Get; - /// Percentage of the curator fee that will be reserved upfront as deposit for bounty - /// curator. + /// The curator deposit is calculated as a percentage of the curator fee. + /// + /// This deposit has optional upper and lower bounds with `CuratorDepositMax` and + /// `CuratorDepositMin`. + #[pallet::constant] + type CuratorDepositMultiplier: Get; + + /// Maximum amount of funds that should be placed in a deposit for making a proposal. #[pallet::constant] - type BountyCuratorDeposit: Get; + type CuratorDepositMax: Get>>; + + /// Minimum amount of funds that should be placed in a deposit for making a proposal. + #[pallet::constant] + type CuratorDepositMin: Get>>; /// Minimum value for a bounty. #[pallet::constant] @@ -502,7 +512,7 @@ pub mod pallet { BountyStatus::CuratorProposed { ref curator } => { ensure!(signer == *curator, Error::::RequireCurator); - let deposit = T::BountyCuratorDeposit::get() * bounty.fee; + let deposit = Self::calculate_curator_deposit(&bounty.fee); T::Currency::reserve(curator, deposit)?; bounty.curator_deposit = deposit; @@ -762,7 +772,19 @@ pub mod pallet { } impl Pallet { - // Add public immutables and private mutables. + pub fn calculate_curator_deposit(fee: &BalanceOf) -> BalanceOf { + let mut deposit = T::CuratorDepositMultiplier::get() * *fee; + + if let Some(max_deposit) = T::CuratorDepositMax::get() { + deposit = deposit.min(max_deposit) + } + + if let Some(min_deposit) = T::CuratorDepositMin::get() { + deposit = deposit.max(min_deposit) + } + + deposit + } /// The account ID of the treasury pot. /// diff --git a/frame/bounties/src/tests.rs b/frame/bounties/src/tests.rs index 3206fce9912f..9a84bd687abc 100644 --- a/frame/bounties/src/tests.rs +++ b/frame/bounties/src/tests.rs @@ -60,6 +60,8 @@ parameter_types! { pub const AvailableBlockRatio: Perbill = Perbill::one(); } +type Balance = u64; + impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); @@ -91,7 +93,7 @@ impl pallet_balances::Config for Test { type MaxLocks = (); type MaxReserves = (); type ReserveIdentifier = [u8; 8]; - type Balance = u64; + type Balance = Balance; type Event = Event; type DustRemoval = (); type ExistentialDeposit = ConstU64<1>; @@ -125,15 +127,23 @@ impl pallet_treasury::Config for Test { type SpendFunds = Bounties; type MaxApprovals = ConstU32<100>; } + parameter_types! { - pub const BountyCuratorDeposit: Permill = Permill::from_percent(50); + // This will be 50% of the bounty fee. + pub const CuratorDepositMultiplier: Permill = Permill::from_percent(50); + pub const CuratorDepositMax: Balance = 1_000; + pub const CuratorDepositMin: Balance = 3; + } + impl Config for Test { type Event = Event; type BountyDepositBase = ConstU64<80>; type BountyDepositPayoutDelay = ConstU64<3>; type BountyUpdatePeriod = ConstU64<20>; - type BountyCuratorDeposit = BountyCuratorDeposit; + type CuratorDepositMultiplier = CuratorDepositMultiplier; + type CuratorDepositMax = CuratorDepositMax; + type CuratorDepositMin = CuratorDepositMin; type BountyValueMinimum = ConstU64<1>; type DataDepositPerByte = ConstU64<1>; type MaximumReasonLength = ConstU32<16384>; @@ -543,13 +553,14 @@ fn assign_curator_works() { Error::::InvalidFee ); - assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, 4)); + let fee = 4; + assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, fee)); assert_eq!( Bounties::bounties(0).unwrap(), Bounty { proposer: 0, - fee: 4, + fee, curator_deposit: 0, value: 50, bond: 85, @@ -567,20 +578,22 @@ fn assign_curator_works() { assert_ok!(Bounties::accept_curator(Origin::signed(4), 0)); + let expected_deposit = Bounties::calculate_curator_deposit(&fee); + assert_eq!( Bounties::bounties(0).unwrap(), Bounty { proposer: 0, - fee: 4, - curator_deposit: 2, + fee, + curator_deposit: expected_deposit, value: 50, bond: 85, status: BountyStatus::Active { curator: 4, update_due: 22 }, } ); - assert_eq!(Balances::free_balance(&4), 8); - assert_eq!(Balances::reserved_balance(&4), 2); + assert_eq!(Balances::free_balance(&4), 10 - expected_deposit); + assert_eq!(Balances::reserved_balance(&4), expected_deposit); }); } @@ -596,17 +609,17 @@ fn unassign_curator_works() { System::set_block_number(2); >::on_initialize(2); - assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, 4)); + let fee = 4; + assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, fee)); assert_noop!(Bounties::unassign_curator(Origin::signed(1), 0), BadOrigin); - assert_ok!(Bounties::unassign_curator(Origin::signed(4), 0)); assert_eq!( Bounties::bounties(0).unwrap(), Bounty { proposer: 0, - fee: 4, + fee, curator_deposit: 0, value: 50, bond: 85, @@ -614,19 +627,17 @@ fn unassign_curator_works() { } ); - assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, 4)); - + assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, fee)); Balances::make_free_balance_be(&4, 10); - assert_ok!(Bounties::accept_curator(Origin::signed(4), 0)); - + let expected_deposit = Bounties::calculate_curator_deposit(&fee); assert_ok!(Bounties::unassign_curator(Origin::root(), 0)); assert_eq!( Bounties::bounties(0).unwrap(), Bounty { proposer: 0, - fee: 4, + fee, curator_deposit: 0, value: 50, bond: 85, @@ -634,8 +645,8 @@ fn unassign_curator_works() { } ); - assert_eq!(Balances::free_balance(&4), 8); - assert_eq!(Balances::reserved_balance(&4), 0); // slashed 2 + assert_eq!(Balances::free_balance(&4), 10 - expected_deposit); + assert_eq!(Balances::reserved_balance(&4), 0); // slashed curator deposit }); } @@ -652,10 +663,12 @@ fn award_and_claim_bounty_works() { System::set_block_number(2); >::on_initialize(2); - assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, 4)); + let fee = 4; + assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, fee)); assert_ok!(Bounties::accept_curator(Origin::signed(4), 0)); - assert_eq!(Balances::free_balance(4), 8); // inital 10 - 2 deposit + let expected_deposit = Bounties::calculate_curator_deposit(&fee); + assert_eq!(Balances::free_balance(4), 10 - expected_deposit); assert_noop!( Bounties::award_bounty(Origin::signed(1), 0, 3), @@ -668,8 +681,8 @@ fn award_and_claim_bounty_works() { Bounties::bounties(0).unwrap(), Bounty { proposer: 0, - fee: 4, - curator_deposit: 2, + fee, + curator_deposit: expected_deposit, value: 50, bond: 85, status: BountyStatus::PendingPayout { curator: 4, beneficiary: 3, unlock_at: 5 }, @@ -1034,3 +1047,78 @@ fn unassign_curator_self() { assert_eq!(Balances::reserved_balance(1), 0); // not slashed }); } + +#[test] +fn accept_curator_handles_different_deposit_calculations() { + // This test will verify that a bounty with and without a fee results + // in a different curator deposit: one using the value, and one using the fee. + new_test_ext().execute_with(|| { + // Case 1: With a fee + let user = 1; + let bounty_index = 0; + let value = 88; + let fee = 42; + + System::set_block_number(1); + Balances::make_free_balance_be(&Treasury::account_id(), 101); + Balances::make_free_balance_be(&user, 100); + assert_ok!(Bounties::propose_bounty(Origin::signed(0), value, b"12345".to_vec())); + assert_ok!(Bounties::approve_bounty(Origin::root(), bounty_index)); + + System::set_block_number(2); + >::on_initialize(2); + + assert_ok!(Bounties::propose_curator(Origin::root(), bounty_index, user, fee)); + assert_ok!(Bounties::accept_curator(Origin::signed(user), bounty_index)); + + let expected_deposit = CuratorDepositMultiplier::get() * fee; + assert_eq!(Balances::free_balance(&user), 100 - expected_deposit); + assert_eq!(Balances::reserved_balance(&user), expected_deposit); + + // Case 2: Lower bound + let user = 2; + let bounty_index = 1; + let value = 35; + let fee = 0; + + Balances::make_free_balance_be(&Treasury::account_id(), 101); + Balances::make_free_balance_be(&user, 100); + + assert_ok!(Bounties::propose_bounty(Origin::signed(0), value, b"12345".to_vec())); + assert_ok!(Bounties::approve_bounty(Origin::root(), bounty_index)); + + System::set_block_number(3); + >::on_initialize(3); + + assert_ok!(Bounties::propose_curator(Origin::root(), bounty_index, user, fee)); + assert_ok!(Bounties::accept_curator(Origin::signed(user), bounty_index)); + + let expected_deposit = CuratorDepositMin::get(); + assert_eq!(Balances::free_balance(&user), 100 - expected_deposit); + assert_eq!(Balances::reserved_balance(&user), expected_deposit); + + // Case 3: Upper bound + let user = 3; + let bounty_index = 2; + let value = 1_000_000; + let fee = 50_000; + let starting_balance = fee * 2; + + Balances::make_free_balance_be(&Treasury::account_id(), value * 2); + Balances::make_free_balance_be(&user, starting_balance); + Balances::make_free_balance_be(&0, starting_balance); + + assert_ok!(Bounties::propose_bounty(Origin::signed(0), value, b"12345".to_vec())); + assert_ok!(Bounties::approve_bounty(Origin::root(), bounty_index)); + + System::set_block_number(3); + >::on_initialize(3); + + assert_ok!(Bounties::propose_curator(Origin::root(), bounty_index, user, fee)); + assert_ok!(Bounties::accept_curator(Origin::signed(user), bounty_index)); + + let expected_deposit = CuratorDepositMax::get(); + assert_eq!(Balances::free_balance(&user), starting_balance - expected_deposit); + assert_eq!(Balances::reserved_balance(&user), expected_deposit); + }); +} diff --git a/frame/child-bounties/src/lib.rs b/frame/child-bounties/src/lib.rs index 36acc7766bf6..2fea61c045cf 100644 --- a/frame/child-bounties/src/lib.rs +++ b/frame/child-bounties/src/lib.rs @@ -66,7 +66,7 @@ use frame_support::traits::{ use sp_runtime::{ traits::{AccountIdConversion, BadOrigin, CheckedSub, Saturating, StaticLookup, Zero}, - DispatchResult, Permill, RuntimeDebug, + DispatchResult, RuntimeDebug, }; use frame_support::pallet_prelude::*; @@ -144,11 +144,6 @@ pub mod pallet { #[pallet::constant] type ChildBountyValueMinimum: Get>; - /// Percentage of child-bounty value to be reserved as curator deposit - /// when curator fee is zero. - #[pallet::constant] - type ChildBountyCuratorDepositBase: Get; - /// The overarching event type. type Event: From> + IsType<::Event>; @@ -392,7 +387,7 @@ pub mod pallet { ) -> DispatchResult { let signer = ensure_signed(origin)?; - let _ = Self::ensure_bounty_active(parent_bounty_id)?; + let (parent_curator, _) = Self::ensure_bounty_active(parent_bounty_id)?; // Mutate child-bounty. ChildBounties::::try_mutate_exists( parent_bounty_id, @@ -406,11 +401,13 @@ pub mod pallet { { ensure!(signer == *curator, BountiesError::::RequireCurator); - // Reserve child-bounty curator deposit. Curator deposit - // is reserved based on a percentage of child-bounty - // value instead of fee, to avoid no deposit in case the - // fee is set as zero. - let deposit = T::ChildBountyCuratorDepositBase::get() * child_bounty.value; + // Reserve child-bounty curator deposit. + let deposit = Self::calculate_curator_deposit( + &parent_curator, + curator, + &child_bounty.fee, + ); + T::Currency::reserve(curator, deposit)?; child_bounty.curator_deposit = deposit; @@ -770,6 +767,20 @@ pub mod pallet { } impl Pallet { + // This function will calculate the deposit of a curator. + fn calculate_curator_deposit( + parent_curator: &T::AccountId, + child_curator: &T::AccountId, + bounty_fee: &BalanceOf, + ) -> BalanceOf { + if parent_curator == child_curator { + return Zero::zero() + } + + // We just use the same logic from the parent bounties pallet. + pallet_bounties::Pallet::::calculate_curator_deposit(bounty_fee) + } + /// The account ID of a child-bounty account. pub fn child_bounty_account_id(id: BountyIndex) -> T::AccountId { // This function is taken from the parent (bounties) pallet, but the diff --git a/frame/child-bounties/src/tests.rs b/frame/child-bounties/src/tests.rs index a6748c47b73d..61545561a26c 100644 --- a/frame/child-bounties/src/tests.rs +++ b/frame/child-bounties/src/tests.rs @@ -65,6 +65,8 @@ parameter_types! { pub const AvailableBlockRatio: Perbill = Perbill::one(); } +type Balance = u64; + impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); @@ -96,7 +98,7 @@ impl pallet_balances::Config for Test { type MaxLocks = (); type MaxReserves = (); type ReserveIdentifier = [u8; 8]; - type Balance = u64; + type Balance = Balance; type Event = Event; type DustRemoval = (); type ExistentialDeposit = ConstU64<1>; @@ -130,28 +132,30 @@ impl pallet_treasury::Config for Test { type MaxApprovals = ConstU32<100>; } parameter_types! { - pub const BountyCuratorDeposit: Permill = Permill::from_percent(50); + // This will be 50% of the bounty fee. + pub const CuratorDepositMultiplier: Permill = Permill::from_percent(50); + pub const CuratorDepositMax: Balance = 1_000; + pub const CuratorDepositMin: Balance = 3; + } impl pallet_bounties::Config for Test { type Event = Event; type BountyDepositBase = ConstU64<80>; type BountyDepositPayoutDelay = ConstU64<3>; type BountyUpdatePeriod = ConstU64<10>; - type BountyCuratorDeposit = BountyCuratorDeposit; + type CuratorDepositMultiplier = CuratorDepositMultiplier; + type CuratorDepositMax = CuratorDepositMax; + type CuratorDepositMin = CuratorDepositMin; type BountyValueMinimum = ConstU64<5>; type DataDepositPerByte = ConstU64<1>; type MaximumReasonLength = ConstU32<300>; type WeightInfo = (); type ChildBountyManager = ChildBounties; } -parameter_types! { - pub const ChildBountyCuratorDepositBase: Permill = Permill::from_percent(10); -} impl pallet_child_bounties::Config for Test { type Event = Event; type MaxActiveChildBountyCount = ConstU32<2>; type ChildBountyValueMinimum = ConstU64<1>; - type ChildBountyCuratorDepositBase = ChildBountyCuratorDepositBase; type WeightInfo = (); } @@ -197,10 +201,10 @@ fn minting_works() { fn add_child_bounty() { new_test_ext().execute_with(|| { // TestProcedure. - // 1, Create bounty & move to active state with enough bounty fund & master-curator. - // 2, Master-curator adds child-bounty child-bounty-1, test for error like RequireCurator + // 1, Create bounty & move to active state with enough bounty fund & parent curator. + // 2, Parent curator adds child-bounty child-bounty-1, test for error like RequireCurator // ,InsufficientProposersBalance, InsufficientBountyBalance with invalid arguments. - // 3, Master-curator adds child-bounty child-bounty-1, moves to "Approved" state & + // 3, Parent curator adds child-bounty child-bounty-1, moves to "Approved" state & // test for the event Added. // 4, Test for DB state of `Bounties` & `ChildBounties`. // 5, Observe fund transaction moment between Bounty, Child-bounty, @@ -217,27 +221,30 @@ fn add_child_bounty() { System::set_block_number(2); >::on_initialize(2); - assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, 4)); + let fee = 8; + assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, fee)); Balances::make_free_balance_be(&4, 10); assert_ok!(Bounties::accept_curator(Origin::signed(4), 0)); - assert_eq!(Balances::free_balance(&4), 8); - assert_eq!(Balances::reserved_balance(&4), 2); + // This verifies that the accept curator logic took a deposit. + let expected_deposit = CuratorDepositMultiplier::get() * fee; + assert_eq!(Balances::reserved_balance(&4), expected_deposit); + assert_eq!(Balances::free_balance(&4), 10 - expected_deposit); // Add child-bounty. - // Acc-4 is the master curator. + // Acc-4 is the parent curator. // Call from invalid origin & check for error "RequireCurator". assert_noop!( ChildBounties::add_child_bounty(Origin::signed(0), 0, 10, b"12345-p1".to_vec()), BountiesError::RequireCurator, ); - // Update the master curator balance. + // Update the parent curator balance. Balances::make_free_balance_be(&4, 101); - // Master curator fee is reserved on parent bounty account. + // parent curator fee is reserved on parent bounty account. assert_eq!(Balances::free_balance(Bounties::bounty_account_id(0)), 50); assert_eq!(Balances::reserved_balance(Bounties::bounty_account_id(0)), 0); @@ -258,7 +265,7 @@ fn add_child_bounty() { assert_eq!(last_event(), ChildBountiesEvent::Added { index: 0, child_index: 0 }); assert_eq!(Balances::free_balance(4), 101); - assert_eq!(Balances::reserved_balance(4), 2); + assert_eq!(Balances::reserved_balance(4), expected_deposit); // DB check. // Check the child-bounty status. @@ -285,8 +292,8 @@ fn add_child_bounty() { fn child_bounty_assign_curator() { new_test_ext().execute_with(|| { // TestProcedure - // 1, Create bounty & move to active state with enough bounty fund & master-curator. - // 2, Master-curator adds child-bounty child-bounty-1, moves to "Active" state. + // 1, Create bounty & move to active state with enough bounty fund & parent curator. + // 2, Parent curator adds child-bounty child-bounty-1, moves to "Active" state. // 3, Test for DB state of `ChildBounties`. // Make the parent bounty. @@ -302,21 +309,22 @@ fn child_bounty_assign_curator() { System::set_block_number(2); >::on_initialize(2); - assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, 4)); - + let fee = 4; + assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, fee)); assert_ok!(Bounties::accept_curator(Origin::signed(4), 0)); // Bounty account status before adding child-bounty. assert_eq!(Balances::free_balance(Bounties::bounty_account_id(0)), 50); assert_eq!(Balances::reserved_balance(Bounties::bounty_account_id(0)), 0); - // Check the balance of master curator. - // Curator deposit is reserved for master curator on parent bounty. - assert_eq!(Balances::free_balance(4), 99); - assert_eq!(Balances::reserved_balance(4), 2); + // Check the balance of parent curator. + // Curator deposit is reserved for parent curator on parent bounty. + let expected_deposit = Bounties::calculate_curator_deposit(&fee); + assert_eq!(Balances::free_balance(4), 101 - expected_deposit); + assert_eq!(Balances::reserved_balance(4), expected_deposit); // Add child-bounty. - // Acc-4 is the master curator & make sure enough deposit. + // Acc-4 is the parent curator & make sure enough deposit. assert_ok!(ChildBounties::add_child_bounty(Origin::signed(4), 0, 10, b"12345-p1".to_vec())); assert_eq!(last_event(), ChildBountiesEvent::Added { index: 0, child_index: 0 }); @@ -329,22 +337,23 @@ fn child_bounty_assign_curator() { assert_eq!(Balances::free_balance(ChildBounties::child_bounty_account_id(0)), 10); assert_eq!(Balances::reserved_balance(ChildBounties::child_bounty_account_id(0)), 0); - assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 8, 2)); + let fee = 6u64; + assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 8, fee)); assert_eq!( ChildBounties::child_bounties(0, 0).unwrap(), ChildBounty { parent_bounty: 0, value: 10, - fee: 2, + fee, curator_deposit: 0, status: ChildBountyStatus::CuratorProposed { curator: 8 }, } ); - // Check the balance of master curator. - assert_eq!(Balances::free_balance(4), 99); - assert_eq!(Balances::reserved_balance(4), 2); + // Check the balance of parent curator. + assert_eq!(Balances::free_balance(4), 101 - expected_deposit); + assert_eq!(Balances::reserved_balance(4), expected_deposit); assert_noop!( ChildBounties::accept_curator(Origin::signed(3), 0, 0), @@ -353,20 +362,22 @@ fn child_bounty_assign_curator() { assert_ok!(ChildBounties::accept_curator(Origin::signed(8), 0, 0)); + let expected_child_deposit = CuratorDepositMultiplier::get() * fee; + assert_eq!( ChildBounties::child_bounties(0, 0).unwrap(), ChildBounty { parent_bounty: 0, value: 10, - fee: 2, - curator_deposit: 1, + fee, + curator_deposit: expected_child_deposit, status: ChildBountyStatus::Active { curator: 8 }, } ); - // Deposit for child-bounty curator is reserved. - assert_eq!(Balances::free_balance(8), 100); - assert_eq!(Balances::reserved_balance(8), 1); + // Deposit for child-bounty curator deposit is reserved. + assert_eq!(Balances::free_balance(8), 101 - expected_child_deposit); + assert_eq!(Balances::reserved_balance(8), expected_child_deposit); // Bounty account status at exit. assert_eq!(Balances::free_balance(Bounties::bounty_account_id(0)), 40); @@ -411,7 +422,8 @@ fn award_claim_child_bounty() { assert_eq!(last_event(), ChildBountiesEvent::Added { index: 0, child_index: 0 }); // Propose and accept curator for child-bounty. - assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 8, 2)); + let fee = 8; + assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 8, fee)); assert_ok!(ChildBounties::accept_curator(Origin::signed(8), 0, 0)); // Award child-bounty. @@ -423,13 +435,14 @@ fn award_claim_child_bounty() { assert_ok!(ChildBounties::award_child_bounty(Origin::signed(8), 0, 0, 7)); + let expected_deposit = CuratorDepositMultiplier::get() * fee; assert_eq!( ChildBounties::child_bounties(0, 0).unwrap(), ChildBounty { parent_bounty: 0, value: 10, - fee: 2, - curator_deposit: 1, + fee, + curator_deposit: expected_deposit, status: ChildBountyStatus::PendingPayout { curator: 8, beneficiary: 7, @@ -450,11 +463,11 @@ fn award_claim_child_bounty() { assert_ok!(ChildBounties::claim_child_bounty(Origin::signed(7), 0, 0)); // Ensure child-bounty curator is paid with curator fee & deposit refund. - assert_eq!(Balances::free_balance(8), 103); + assert_eq!(Balances::free_balance(8), 101 + fee); assert_eq!(Balances::reserved_balance(8), 0); // Ensure executor is paid with beneficiary amount. - assert_eq!(Balances::free_balance(7), 8); + assert_eq!(Balances::free_balance(7), 10 - fee); assert_eq!(Balances::reserved_balance(7), 0); // Child-bounty account status. @@ -591,8 +604,8 @@ fn close_child_bounty_pending() { System::set_block_number(2); >::on_initialize(2); - assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, 6)); - + let parent_fee = 6; + assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, parent_fee)); assert_ok!(Bounties::accept_curator(Origin::signed(4), 0)); // Child-bounty. @@ -601,8 +614,10 @@ fn close_child_bounty_pending() { assert_eq!(last_event(), ChildBountiesEvent::Added { index: 0, child_index: 0 }); // Propose and accept curator for child-bounty. - assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 8, 2)); + let child_fee = 4; + assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 8, child_fee)); assert_ok!(ChildBounties::accept_curator(Origin::signed(8), 0, 0)); + let expected_child_deposit = CuratorDepositMin::get(); assert_ok!(ChildBounties::award_child_bounty(Origin::signed(8), 0, 0, 7)); @@ -616,8 +631,8 @@ fn close_child_bounty_pending() { assert_eq!(ChildBounties::parent_child_bounties(0), 1); // Ensure no changes in child-bounty curator balance. - assert_eq!(Balances::free_balance(8), 100); - assert_eq!(Balances::reserved_balance(8), 1); + assert_eq!(Balances::reserved_balance(8), expected_child_deposit); + assert_eq!(Balances::free_balance(8), 101 - expected_child_deposit); // Child-bounty account status. assert_eq!(Balances::free_balance(ChildBounties::child_bounty_account_id(0)), 10); @@ -755,7 +770,6 @@ fn child_bounty_active_unassign_curator() { >::on_initialize(2); assert_ok!(Bounties::propose_curator(Origin::root(), 0, 4, 6)); - assert_ok!(Bounties::accept_curator(Origin::signed(4), 0)); // Create Child-bounty. @@ -766,16 +780,18 @@ fn child_bounty_active_unassign_curator() { >::on_initialize(3); // Propose and accept curator for child-bounty. - assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 8, 2)); + let fee = 6; + assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 8, fee)); assert_ok!(ChildBounties::accept_curator(Origin::signed(8), 0, 0)); + let expected_child_deposit = CuratorDepositMultiplier::get() * fee; assert_eq!( ChildBounties::child_bounties(0, 0).unwrap(), ChildBounty { parent_bounty: 0, value: 10, - fee: 2, - curator_deposit: 1, + fee, + curator_deposit: expected_child_deposit, status: ChildBountyStatus::Active { curator: 8 }, } ); @@ -792,27 +808,29 @@ fn child_bounty_active_unassign_curator() { ChildBounty { parent_bounty: 0, value: 10, - fee: 2, + fee, curator_deposit: 0, status: ChildBountyStatus::Added, } ); // Ensure child-bounty curator was slashed. - assert_eq!(Balances::free_balance(8), 100); + assert_eq!(Balances::free_balance(8), 101 - expected_child_deposit); assert_eq!(Balances::reserved_balance(8), 0); // slashed // Propose and accept curator for child-bounty again. - assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 7, 2)); + let fee = 2; + assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 7, fee)); assert_ok!(ChildBounties::accept_curator(Origin::signed(7), 0, 0)); + let expected_child_deposit = CuratorDepositMin::get(); assert_eq!( ChildBounties::child_bounties(0, 0).unwrap(), ChildBounty { parent_bounty: 0, value: 10, - fee: 2, - curator_deposit: 1, + fee, + curator_deposit: expected_child_deposit, status: ChildBountyStatus::Active { curator: 7 }, } ); @@ -820,7 +838,7 @@ fn child_bounty_active_unassign_curator() { System::set_block_number(5); >::on_initialize(5); - // Unassign curator again - from master curator. + // Unassign curator again - from parent curator. assert_ok!(ChildBounties::unassign_curator(Origin::signed(4), 0, 0)); // Verify updated child-bounty status. @@ -836,7 +854,7 @@ fn child_bounty_active_unassign_curator() { ); // Ensure child-bounty curator was slashed. - assert_eq!(Balances::free_balance(7), 100); + assert_eq!(Balances::free_balance(7), 101 - expected_child_deposit); assert_eq!(Balances::reserved_balance(7), 0); // slashed // Propose and accept curator for child-bounty again. @@ -848,8 +866,8 @@ fn child_bounty_active_unassign_curator() { ChildBounty { parent_bounty: 0, value: 10, - fee: 2, - curator_deposit: 1, + fee, + curator_deposit: expected_child_deposit, status: ChildBountyStatus::Active { curator: 6 }, } ); @@ -877,16 +895,18 @@ fn child_bounty_active_unassign_curator() { assert_eq!(Balances::reserved_balance(6), 0); // Propose and accept curator for child-bounty one last time. - assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 6, 2)); + let fee = 2; + assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 6, fee)); assert_ok!(ChildBounties::accept_curator(Origin::signed(6), 0, 0)); + let expected_child_deposit = CuratorDepositMin::get(); assert_eq!( ChildBounties::child_bounties(0, 0).unwrap(), ChildBounty { parent_bounty: 0, value: 10, - fee: 2, - curator_deposit: 1, + fee, + curator_deposit: expected_child_deposit, status: ChildBountyStatus::Active { curator: 6 }, } ); @@ -920,7 +940,7 @@ fn child_bounty_active_unassign_curator() { ); // Ensure child-bounty curator was slashed. - assert_eq!(Balances::free_balance(6), 100); // slashed + assert_eq!(Balances::free_balance(6), 101 - expected_child_deposit); // slashed assert_eq!(Balances::reserved_balance(6), 0); }); } @@ -960,16 +980,18 @@ fn parent_bounty_inactive_unassign_curator_child_bounty() { >::on_initialize(3); // Propose and accept curator for child-bounty. - assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 8, 2)); + let fee = 8; + assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 8, fee)); assert_ok!(ChildBounties::accept_curator(Origin::signed(8), 0, 0)); + let expected_child_deposit = CuratorDepositMultiplier::get() * fee; assert_eq!( ChildBounties::child_bounties(0, 0).unwrap(), ChildBounty { parent_bounty: 0, value: 10, - fee: 2, - curator_deposit: 1, + fee, + curator_deposit: expected_child_deposit, status: ChildBountyStatus::Active { curator: 8 }, } ); @@ -999,14 +1021,14 @@ fn parent_bounty_inactive_unassign_curator_child_bounty() { ChildBounty { parent_bounty: 0, value: 10, - fee: 2, + fee, curator_deposit: 0, status: ChildBountyStatus::Added, } ); // Ensure child-bounty curator was slashed. - assert_eq!(Balances::free_balance(8), 100); + assert_eq!(Balances::free_balance(8), 101 - expected_child_deposit); assert_eq!(Balances::reserved_balance(8), 0); // slashed System::set_block_number(6); @@ -1020,16 +1042,18 @@ fn parent_bounty_inactive_unassign_curator_child_bounty() { >::on_initialize(7); // Propose and accept curator for child-bounty again. - assert_ok!(ChildBounties::propose_curator(Origin::signed(5), 0, 0, 7, 2)); + let fee = 2; + assert_ok!(ChildBounties::propose_curator(Origin::signed(5), 0, 0, 7, fee)); assert_ok!(ChildBounties::accept_curator(Origin::signed(7), 0, 0)); + let expected_deposit = CuratorDepositMin::get(); assert_eq!( ChildBounties::child_bounties(0, 0).unwrap(), ChildBounty { parent_bounty: 0, value: 10, - fee: 2, - curator_deposit: 1, + fee, + curator_deposit: expected_deposit, status: ChildBountyStatus::Active { curator: 7 }, } ); @@ -1048,7 +1072,7 @@ fn parent_bounty_inactive_unassign_curator_child_bounty() { System::set_block_number(9); >::on_initialize(9); - // Unassign curator again - from master curator. + // Unassign curator again - from parent curator. assert_ok!(ChildBounties::unassign_curator(Origin::signed(7), 0, 0)); // Verify updated child-bounty status. @@ -1157,25 +1181,26 @@ fn children_curator_fee_calculation_test() { System::set_block_number(4); >::on_initialize(4); - // Propose curator for child-bounty. - assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 8, 2)); + let fee = 6; + // Propose curator for child-bounty. + assert_ok!(ChildBounties::propose_curator(Origin::signed(4), 0, 0, 8, fee)); // Check curator fee added to the sum. - assert_eq!(ChildBounties::children_curator_fees(0), 2); - + assert_eq!(ChildBounties::children_curator_fees(0), fee); // Accept curator for child-bounty. assert_ok!(ChildBounties::accept_curator(Origin::signed(8), 0, 0)); - // Award child-bounty. assert_ok!(ChildBounties::award_child_bounty(Origin::signed(8), 0, 0, 7)); + let expected_child_deposit = CuratorDepositMultiplier::get() * fee; + assert_eq!( ChildBounties::child_bounties(0, 0).unwrap(), ChildBounty { parent_bounty: 0, value: 10, - fee: 2, - curator_deposit: 1, + fee, + curator_deposit: expected_child_deposit, status: ChildBountyStatus::PendingPayout { curator: 8, beneficiary: 7, @@ -1201,7 +1226,7 @@ fn children_curator_fee_calculation_test() { assert_ok!(Bounties::claim_bounty(Origin::signed(9), 0)); // Ensure parent-bounty curator received correctly reduced fee. - assert_eq!(Balances::free_balance(4), 105); // 101 + 6 - 2 + assert_eq!(Balances::free_balance(4), 101 + 6 - fee); // 101 + 6 - 2 assert_eq!(Balances::reserved_balance(4), 0); // Verify parent-bounty beneficiary balance. @@ -1209,3 +1234,176 @@ fn children_curator_fee_calculation_test() { assert_eq!(Balances::reserved_balance(9), 0); }); } + +#[test] +fn accept_curator_handles_different_deposit_calculations() { + // This test will verify that a bounty with and without a fee results + // in a different curator deposit, and if the child curator matches the parent curator. + new_test_ext().execute_with(|| { + // Setup a parent bounty. + let parent_curator = 0; + let parent_index = 0; + let parent_value = 1_000_000; + let parent_fee = 10_000; + + System::set_block_number(1); + Balances::make_free_balance_be(&Treasury::account_id(), parent_value * 3); + Balances::make_free_balance_be(&parent_curator, parent_fee * 100); + assert_ok!(Bounties::propose_bounty( + Origin::signed(parent_curator), + parent_value, + b"12345".to_vec() + )); + assert_ok!(Bounties::approve_bounty(Origin::root(), parent_index)); + + System::set_block_number(2); + >::on_initialize(2); + + assert_ok!(Bounties::propose_curator( + Origin::root(), + parent_index, + parent_curator, + parent_fee + )); + assert_ok!(Bounties::accept_curator(Origin::signed(parent_curator), parent_index)); + + // Now we can start creating some child bounties. + // Case 1: Parent and child curator are not the same. + + let child_index = 0; + let child_curator = 1; + let child_value = 1_000; + let child_fee = 100; + let starting_balance = 100 * child_fee + child_value; + + Balances::make_free_balance_be(&child_curator, starting_balance); + assert_ok!(ChildBounties::add_child_bounty( + Origin::signed(parent_curator), + parent_index, + child_value, + b"12345-p1".to_vec() + )); + System::set_block_number(3); + >::on_initialize(3); + assert_ok!(ChildBounties::propose_curator( + Origin::signed(parent_curator), + parent_index, + child_index, + child_curator, + child_fee + )); + assert_ok!(ChildBounties::accept_curator( + Origin::signed(child_curator), + parent_index, + child_index + )); + + let expected_deposit = CuratorDepositMultiplier::get() * child_fee; + assert_eq!(Balances::free_balance(child_curator), starting_balance - expected_deposit); + assert_eq!(Balances::reserved_balance(child_curator), expected_deposit); + + // Case 2: Parent and child curator are the same. + + let child_index = 1; + let child_curator = parent_curator; // The same as parent bounty curator + let child_value = 1_000; + let child_fee = 10; + + let free_before = Balances::free_balance(&parent_curator); + let reserved_before = Balances::reserved_balance(&parent_curator); + + assert_ok!(ChildBounties::add_child_bounty( + Origin::signed(parent_curator), + parent_index, + child_value, + b"12345-p1".to_vec() + )); + System::set_block_number(4); + >::on_initialize(4); + assert_ok!(ChildBounties::propose_curator( + Origin::signed(parent_curator), + parent_index, + child_index, + child_curator, + child_fee + )); + assert_ok!(ChildBounties::accept_curator( + Origin::signed(child_curator), + parent_index, + child_index + )); + + // No expected deposit + assert_eq!(Balances::free_balance(child_curator), free_before); + assert_eq!(Balances::reserved_balance(child_curator), reserved_before); + + // Case 3: Upper Limit + + let child_index = 2; + let child_curator = 2; + let child_value = 10_000; + let child_fee = 5_000; + + Balances::make_free_balance_be(&child_curator, starting_balance); + assert_ok!(ChildBounties::add_child_bounty( + Origin::signed(parent_curator), + parent_index, + child_value, + b"12345-p1".to_vec() + )); + System::set_block_number(5); + >::on_initialize(5); + assert_ok!(ChildBounties::propose_curator( + Origin::signed(parent_curator), + parent_index, + child_index, + child_curator, + child_fee + )); + assert_ok!(ChildBounties::accept_curator( + Origin::signed(child_curator), + parent_index, + child_index + )); + + let expected_deposit = CuratorDepositMax::get(); + assert_eq!(Balances::free_balance(child_curator), starting_balance - expected_deposit); + assert_eq!(Balances::reserved_balance(child_curator), expected_deposit); + + // There is a max number of child bounties at a time. + assert_ok!(ChildBounties::impl_close_child_bounty(parent_index, child_index)); + + // Case 4: Lower Limit + + let child_index = 3; + let child_curator = 3; + let child_value = 10_000; + let child_fee = 0; + + Balances::make_free_balance_be(&child_curator, starting_balance); + assert_ok!(ChildBounties::add_child_bounty( + Origin::signed(parent_curator), + parent_index, + child_value, + b"12345-p1".to_vec() + )); + System::set_block_number(5); + >::on_initialize(5); + assert_ok!(ChildBounties::propose_curator( + Origin::signed(parent_curator), + parent_index, + child_index, + child_curator, + child_fee + )); + assert_ok!(ChildBounties::accept_curator( + Origin::signed(child_curator), + parent_index, + child_index + )); + + let expected_deposit = CuratorDepositMin::get(); + assert_eq!(Balances::free_balance(child_curator), starting_balance - expected_deposit); + assert_eq!(Balances::reserved_balance(child_curator), expected_deposit); + }); +} From 318dea38c9d8af7b526b35a619c393b08ad236ce Mon Sep 17 00:00:00 2001 From: Qinxuan Chen Date: Fri, 25 Mar 2022 21:45:01 +0800 Subject: [PATCH 640/695] pallet-conviction-voting: make the pallet instantiable (#11088) * pallet-conviction-voting: make the pallet instanceable Signed-off-by: koushiro * Add default type param for some type alias Signed-off-by: koushiro --- frame/conviction-voting/src/conviction.rs | 4 +- frame/conviction-voting/src/lib.rs | 185 ++++++++++++---------- frame/conviction-voting/src/tests.rs | 5 +- frame/conviction-voting/src/types.rs | 5 +- 4 files changed, 109 insertions(+), 90 deletions(-) diff --git a/frame/conviction-voting/src/conviction.rs b/frame/conviction-voting/src/conviction.rs index 129f2771124b..1feff35b19fc 100644 --- a/frame/conviction-voting/src/conviction.rs +++ b/frame/conviction-voting/src/conviction.rs @@ -17,14 +17,14 @@ //! The conviction datatype. -use crate::types::Delegations; use codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; use sp_runtime::{ traits::{Bounded, CheckedDiv, CheckedMul, Zero}, RuntimeDebug, }; -use sp_std::{convert::TryFrom, result::Result}; + +use crate::types::Delegations; /// A value denoting the strength of conviction of a vote. #[derive( diff --git a/frame/conviction-voting/src/lib.rs b/frame/conviction-voting/src/lib.rs index 8e7e0d91b1cf..af91e99fb379 100644 --- a/frame/conviction-voting/src/lib.rs +++ b/frame/conviction-voting/src/lib.rs @@ -28,6 +28,7 @@ #![cfg_attr(not(feature = "std"), no_std)] use frame_support::{ + dispatch::{DispatchError, DispatchResult}, ensure, traits::{ fungible, Currency, Get, LockIdentifier, LockableCurrency, PollStatus, Polling, @@ -36,7 +37,7 @@ use frame_support::{ }; use sp_runtime::{ traits::{AtLeast32BitUnsigned, Saturating, Zero}, - ArithmeticError, DispatchError, DispatchResult, Perbill, + ArithmeticError, Perbill, }; use sp_std::prelude::*; @@ -44,11 +45,14 @@ mod conviction; mod types; mod vote; pub mod weights; -pub use conviction::Conviction; -pub use pallet::*; -pub use types::{Delegations, Tally, UnvoteScope}; -pub use vote::{AccountVote, Casting, Delegating, Vote, Voting}; -pub use weights::WeightInfo; + +pub use self::{ + conviction::Conviction, + pallet::*, + types::{Delegations, Tally, UnvoteScope}, + vote::{AccountVote, Casting, Delegating, Vote, Voting}, + weights::WeightInfo, +}; #[cfg(test)] mod tests; @@ -58,44 +62,43 @@ pub mod benchmarking; const CONVICTION_VOTING_ID: LockIdentifier = *b"pyconvot"; -type BalanceOf = - <::Currency as Currency<::AccountId>>::Balance; -type VotingOf = Voting< - BalanceOf, +type BalanceOf = + <>::Currency as Currency<::AccountId>>::Balance; +type VotingOf = Voting< + BalanceOf, ::AccountId, ::BlockNumber, - PollIndexOf, - ::MaxVotes, + PollIndexOf, + >::MaxVotes, >; #[allow(dead_code)] -type DelegatingOf = Delegating< - BalanceOf, +type DelegatingOf = Delegating< + BalanceOf, ::AccountId, ::BlockNumber, >; -pub type TallyOf = Tally, ::MaxTurnout>; -pub type VotesOf = BalanceOf; -type PollIndexOf = <::Polls as Polling>>::Index; +pub type TallyOf = Tally, >::MaxTurnout>; +pub type VotesOf = BalanceOf; +type PollIndexOf = <>::Polls as Polling>>::Index; #[cfg(feature = "runtime-benchmarks")] -type IndexOf = <::Polls as Polling>>::Index; -type ClassOf = <::Polls as Polling>>::Class; +type IndexOf = <>::Polls as Polling>>::Index; +type ClassOf = <>::Polls as Polling>>::Class; #[frame_support::pallet] pub mod pallet { use super::*; use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; - use sp_runtime::DispatchResult; #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] #[pallet::without_storage_info] - pub struct Pallet(_); + pub struct Pallet(_); #[pallet::config] - pub trait Config: frame_system::Config + Sized { + pub trait Config: frame_system::Config + Sized { // System level stuff. - type Event: From> + IsType<::Event>; + type Event: From> + IsType<::Event>; /// Weight information for extrinsics in this pallet. type WeightInfo: WeightInfo; /// Currency type with which voting happens. @@ -104,12 +107,16 @@ pub mod pallet { + fungible::Inspect; /// The implementation of the logic which conducts polls. - type Polls: Polling, Votes = BalanceOf, Moment = Self::BlockNumber>; + type Polls: Polling< + TallyOf, + Votes = BalanceOf, + Moment = Self::BlockNumber, + >; /// The maximum amount of tokens which may be used for voting. May just be /// `Currency::total_issuance`, but you might want to reduce this in order to account for /// funds in the system which are unable to vote (e.g. parachain auction deposits). - type MaxTurnout: Get>; + type MaxTurnout: Get>; /// The maximum number of concurrent votes an account may have. /// @@ -129,13 +136,13 @@ pub mod pallet { /// All voting for a particular voter in a particular voting class. We store the balance for the /// number of votes that we have recorded. #[pallet::storage] - pub type VotingFor = StorageDoubleMap< + pub type VotingFor, I: 'static = ()> = StorageDoubleMap< _, Twox64Concat, T::AccountId, Twox64Concat, - ClassOf, - VotingOf, + ClassOf, + VotingOf, ValueQuery, >; @@ -143,12 +150,17 @@ pub mod pallet { /// require. The actual amount locked on behalf of this pallet should always be the maximum of /// this list. #[pallet::storage] - pub type ClassLocksFor = - StorageMap<_, Twox64Concat, T::AccountId, Vec<(ClassOf, BalanceOf)>, ValueQuery>; + pub type ClassLocksFor, I: 'static = ()> = StorageMap< + _, + Twox64Concat, + T::AccountId, + Vec<(ClassOf, BalanceOf)>, + ValueQuery, + >; #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] - pub enum Event { + pub enum Event, I: 'static = ()> { /// An account has delegated their vote to another account. \[who, target\] Delegated(T::AccountId, T::AccountId), /// An \[account\] has cancelled a previous delegation operation. @@ -156,7 +168,7 @@ pub mod pallet { } #[pallet::error] - pub enum Error { + pub enum Error { /// Poll is not ongoing. NotOngoing, /// The given account did not vote on the poll. @@ -185,7 +197,7 @@ pub mod pallet { } #[pallet::call] - impl Pallet { + impl, I: 'static> Pallet { /// Vote in a poll. If `vote.is_aye()`, the vote is to enact the proposal; /// otherwise it is a vote to keep the status quo. /// @@ -198,8 +210,8 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::vote_new().max(T::WeightInfo::vote_existing()))] pub fn vote( origin: OriginFor, - #[pallet::compact] poll_index: PollIndexOf, - vote: AccountVote>, + #[pallet::compact] poll_index: PollIndexOf, + vote: AccountVote>, ) -> DispatchResult { let who = ensure_signed(origin)?; Self::try_vote(&who, poll_index, vote) @@ -233,10 +245,10 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::delegate(T::MaxVotes::get()))] pub fn delegate( origin: OriginFor, - class: ClassOf, + class: ClassOf, to: T::AccountId, conviction: Conviction, - balance: BalanceOf, + balance: BalanceOf, ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; let votes = Self::try_delegate(who, class, to, conviction, balance)?; @@ -261,7 +273,10 @@ pub mod pallet { // NOTE: weight must cover an incorrect voting of origin with max votes, this is ensure // because a valid delegation cover decoding a direct voting with max votes. #[pallet::weight(T::WeightInfo::undelegate(T::MaxVotes::get().into()))] - pub fn undelegate(origin: OriginFor, class: ClassOf) -> DispatchResultWithPostInfo { + pub fn undelegate( + origin: OriginFor, + class: ClassOf, + ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; let votes = Self::try_undelegate(who, class)?; Ok(Some(T::WeightInfo::undelegate(votes)).into()) @@ -279,7 +294,7 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::unlock())] pub fn unlock( origin: OriginFor, - class: ClassOf, + class: ClassOf, target: T::AccountId, ) -> DispatchResult { ensure_signed(origin)?; @@ -319,8 +334,8 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::remove_vote())] pub fn remove_vote( origin: OriginFor, - class: Option>, - index: PollIndexOf, + class: Option>, + index: PollIndexOf, ) -> DispatchResult { let who = ensure_signed(origin)?; Self::try_remove_vote(&who, index, class, UnvoteScope::Any) @@ -346,8 +361,8 @@ pub mod pallet { pub fn remove_other_vote( origin: OriginFor, target: T::AccountId, - class: ClassOf, - index: PollIndexOf, + class: ClassOf, + index: PollIndexOf, ) -> DispatchResult { let who = ensure_signed(origin)?; let scope = if target == who { UnvoteScope::Any } else { UnvoteScope::OnlyExpired }; @@ -357,17 +372,17 @@ pub mod pallet { } } -impl Pallet { +impl, I: 'static> Pallet { /// Actually enact a vote, if legit. fn try_vote( who: &T::AccountId, - poll_index: PollIndexOf, - vote: AccountVote>, + poll_index: PollIndexOf, + vote: AccountVote>, ) -> DispatchResult { - ensure!(vote.balance() <= T::Currency::free_balance(who), Error::::InsufficientFunds); + ensure!(vote.balance() <= T::Currency::free_balance(who), Error::::InsufficientFunds); T::Polls::try_access_poll(poll_index, |poll_status| { - let (tally, class) = poll_status.ensure_ongoing().ok_or(Error::::NotOngoing)?; - VotingFor::::try_mutate(who, &class, |voting| { + let (tally, class) = poll_status.ensure_ongoing().ok_or(Error::::NotOngoing)?; + VotingFor::::try_mutate(who, &class, |voting| { if let Voting::Casting(Casting { ref mut votes, delegations, .. }) = voting { match votes.binary_search_by_key(&poll_index, |i| i.0) { Ok(i) => { @@ -381,7 +396,7 @@ impl Pallet { Err(i) => { votes .try_insert(i, (poll_index, vote)) - .map_err(|()| Error::::MaxVotesReached)?; + .map_err(|()| Error::::MaxVotesReached)?; }, } // Shouldn't be possible to fail, but we handle it gracefully. @@ -390,7 +405,7 @@ impl Pallet { tally.increase(approve, *delegations); } } else { - return Err(Error::::AlreadyDelegating.into()) + return Err(Error::::AlreadyDelegating.into()) } // Extend the lock to `balance` (rather than setting it) since we don't know what // other votes are in place. @@ -408,23 +423,23 @@ impl Pallet { /// This will generally be combined with a call to `unlock`. fn try_remove_vote( who: &T::AccountId, - poll_index: PollIndexOf, - class_hint: Option>, + poll_index: PollIndexOf, + class_hint: Option>, scope: UnvoteScope, ) -> DispatchResult { let class = class_hint .or_else(|| Some(T::Polls::as_ongoing(poll_index)?.1)) - .ok_or(Error::::ClassNeeded)?; - VotingFor::::try_mutate(who, class, |voting| { + .ok_or(Error::::ClassNeeded)?; + VotingFor::::try_mutate(who, class, |voting| { if let Voting::Casting(Casting { ref mut votes, delegations, ref mut prior }) = voting { let i = votes .binary_search_by_key(&poll_index, |i| i.0) - .map_err(|_| Error::::NotVoter)?; + .map_err(|_| Error::::NotVoter)?; let v = votes.remove(i); T::Polls::try_access_poll(poll_index, |poll_status| match poll_status { PollStatus::Ongoing(tally, _) => { - ensure!(matches!(scope, UnvoteScope::Any), Error::::NoPermission); + ensure!(matches!(scope, UnvoteScope::Any), Error::::NoPermission); // Shouldn't be possible to fail, but we handle it gracefully. tally.remove(v.1).ok_or(ArithmeticError::Underflow)?; if let Some(approve) = v.1.as_standard() { @@ -441,7 +456,7 @@ impl Pallet { if now < unlock_at { ensure!( matches!(scope, UnvoteScope::Any), - Error::::NoPermissionYet + Error::::NoPermissionYet ); prior.accumulate(unlock_at, balance) } @@ -459,10 +474,10 @@ impl Pallet { /// Return the number of votes for `who` fn increase_upstream_delegation( who: &T::AccountId, - class: &ClassOf, - amount: Delegations>, + class: &ClassOf, + amount: Delegations>, ) -> u32 { - VotingFor::::mutate(who, class, |voting| match voting { + VotingFor::::mutate(who, class, |voting| match voting { Voting::Delegating(Delegating { delegations, .. }) => { // We don't support second level delegating, so we don't need to do anything more. *delegations = delegations.saturating_add(amount); @@ -487,10 +502,10 @@ impl Pallet { /// Return the number of votes for `who` fn reduce_upstream_delegation( who: &T::AccountId, - class: &ClassOf, - amount: Delegations>, + class: &ClassOf, + amount: Delegations>, ) -> u32 { - VotingFor::::mutate(who, class, |voting| match voting { + VotingFor::::mutate(who, class, |voting| match voting { Voting::Delegating(Delegating { delegations, .. }) => { // We don't support second level delegating, so we don't need to do anything more. *delegations = delegations.saturating_sub(amount); @@ -517,16 +532,16 @@ impl Pallet { /// Return the upstream number of votes. fn try_delegate( who: T::AccountId, - class: ClassOf, + class: ClassOf, target: T::AccountId, conviction: Conviction, - balance: BalanceOf, + balance: BalanceOf, ) -> Result { - ensure!(who != target, Error::::Nonsense); - T::Polls::classes().binary_search(&class).map_err(|_| Error::::BadClass)?; - ensure!(balance <= T::Currency::free_balance(&who), Error::::InsufficientFunds); + ensure!(who != target, Error::::Nonsense); + T::Polls::classes().binary_search(&class).map_err(|_| Error::::BadClass)?; + ensure!(balance <= T::Currency::free_balance(&who), Error::::InsufficientFunds); let votes = - VotingFor::::try_mutate(&who, &class, |voting| -> Result { + VotingFor::::try_mutate(&who, &class, |voting| -> Result { let old = sp_std::mem::replace( voting, Voting::Delegating(Delegating { @@ -538,10 +553,10 @@ impl Pallet { }), ); match old { - Voting::Delegating(Delegating { .. }) => Err(Error::::AlreadyDelegating)?, + Voting::Delegating(Delegating { .. }) => Err(Error::::AlreadyDelegating)?, Voting::Casting(Casting { votes, delegations, prior }) => { // here we just ensure that we're currently idling with no votes recorded. - ensure!(votes.is_empty(), Error::::AlreadyVoting); + ensure!(votes.is_empty(), Error::::AlreadyVoting); voting.set_common(delegations, prior); }, } @@ -553,16 +568,16 @@ impl Pallet { Self::extend_lock(&who, &class, balance); Ok(votes) })?; - Self::deposit_event(Event::::Delegated(who, target)); + Self::deposit_event(Event::::Delegated(who, target)); Ok(votes) } /// Attempt to end the current delegation. /// /// Return the number of votes of upstream. - fn try_undelegate(who: T::AccountId, class: ClassOf) -> Result { + fn try_undelegate(who: T::AccountId, class: ClassOf) -> Result { let votes = - VotingFor::::try_mutate(&who, &class, |voting| -> Result { + VotingFor::::try_mutate(&who, &class, |voting| -> Result { match sp_std::mem::replace(voting, Voting::default()) { Voting::Delegating(Delegating { balance, @@ -589,29 +604,31 @@ impl Pallet { Ok(votes) }, - Voting::Casting(_) => Err(Error::::NotDelegating.into()), + Voting::Casting(_) => Err(Error::::NotDelegating.into()), } })?; - Self::deposit_event(Event::::Undelegated(who)); + Self::deposit_event(Event::::Undelegated(who)); Ok(votes) } - fn extend_lock(who: &T::AccountId, class: &ClassOf, amount: BalanceOf) { - ClassLocksFor::::mutate(who, |locks| match locks.iter().position(|x| &x.0 == class) { - Some(i) => locks[i].1 = locks[i].1.max(amount), - None => locks.push((class.clone(), amount)), + fn extend_lock(who: &T::AccountId, class: &ClassOf, amount: BalanceOf) { + ClassLocksFor::::mutate(who, |locks| { + match locks.iter().position(|x| &x.0 == class) { + Some(i) => locks[i].1 = locks[i].1.max(amount), + None => locks.push((class.clone(), amount)), + } }); T::Currency::extend_lock(CONVICTION_VOTING_ID, who, amount, WithdrawReasons::TRANSFER); } /// Rejig the lock on an account. It will never get more stringent (since that would indicate /// a security hole) but may be reduced from what they are currently. - fn update_lock(class: &ClassOf, who: &T::AccountId) { - let class_lock_needed = VotingFor::::mutate(who, class, |voting| { + fn update_lock(class: &ClassOf, who: &T::AccountId) { + let class_lock_needed = VotingFor::::mutate(who, class, |voting| { voting.rejig(frame_system::Pallet::::block_number()); voting.locked_balance() }); - let lock_needed = ClassLocksFor::::mutate(who, |locks| { + let lock_needed = ClassLocksFor::::mutate(who, |locks| { locks.retain(|x| &x.0 != class); if !class_lock_needed.is_zero() { locks.push((class.clone(), class_lock_needed)); diff --git a/frame/conviction-voting/src/tests.rs b/frame/conviction-voting/src/tests.rs index cedb23b02a8d..6a8bad5d8944 100644 --- a/frame/conviction-voting/src/tests.rs +++ b/frame/conviction-voting/src/tests.rs @@ -19,8 +19,6 @@ use std::collections::BTreeMap; -use super::*; -use crate as pallet_conviction_voting; use frame_support::{ assert_noop, assert_ok, parameter_types, traits::{ConstU32, ConstU64, Contains, Polling}, @@ -31,6 +29,9 @@ use sp_runtime::{ traits::{BlakeTwo256, IdentityLookup}, }; +use super::*; +use crate as pallet_conviction_voting; + type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; type Block = frame_system::mocking::MockBlock; diff --git a/frame/conviction-voting/src/types.rs b/frame/conviction-voting/src/types.rs index 2ad1a164dd14..e2b5844ddd5d 100644 --- a/frame/conviction-voting/src/types.rs +++ b/frame/conviction-voting/src/types.rs @@ -19,8 +19,6 @@ use sp_std::marker::PhantomData; -use super::*; -use crate::{AccountVote, Conviction, Vote}; use codec::{Codec, Decode, Encode, MaxEncodedLen}; use frame_support::{ traits::VoteTally, CloneNoBound, DefaultNoBound, EqNoBound, PartialEqNoBound, @@ -32,6 +30,9 @@ use sp_runtime::{ RuntimeDebug, }; +use super::*; +use crate::{AccountVote, Conviction, Vote}; + /// Info regarding an ongoing referendum. #[derive( CloneNoBound, From 411d9bb4c551c65acb55bc67443f05fe631f9330 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Fri, 25 Mar 2022 17:31:42 +0200 Subject: [PATCH 641/695] Implement Lean BEEFY (#10882) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Simplified BEEFY worker logic based on the invariant that GRANDPA will always finalize 1st block of each new session, meaning BEEFY worker is guaranteed to receive finality notification for the BEEFY mandatory blocks. Under these conditions the current design is as follows: - session changes are detected based on BEEFY Digest present in BEEFY mandatory blocks, - on each new session new `Rounds` of voting is created, with old rounds being dropped (for gossip rounds, last 3 are still alive so votes are still being gossiped), - after processing finality for a block, the worker votes if a new voting target has become available as a result of said block finality processing, - incoming votes as well as self-created votes are processed and signed commitments are created for completed BEEFY voting rounds, - the worker votes if a new voting target becomes available once a round successfully completes. On worker startup, the current validator set is retrieved from the BEEFY pallet. If it is the genesis validator set, worker starts voting right away considering Block #1 as session start. Otherwise (not genesis), the worker will vote starting with mandatory block of the next session. Later on when we add the BEEFY initial-sync (catch-up) logic, the worker will sync all past mandatory blocks Signed Commitments and will be able to start voting right away. BEEFY mandatory block is the block with header containing the BEEFY `AuthoritiesChange` Digest, this block is guaranteed to be finalized by GRANDPA. This session-boundary block is signed by the ending-session's validator set. Next blocks will be signed by the new session's validator set. This behavior is consistent with what GRANDPA does as well. Also drop the limit N on active gossip rounds. In an adversarial network, a bad actor could create and gossip N invalid votes with round numbers larger than the current correct round number. This would lead to votes for correct rounds to no longer be gossiped. Add unit-tests for all components, including full voter consensus tests. Signed-off-by: Adrian Catangiu Co-authored-by: Tomasz Drwięga Co-authored-by: David Salami --- Cargo.lock | 10 + client/beefy/Cargo.toml | 14 +- client/beefy/src/gossip.rs | 306 ++++++----- client/beefy/src/lib.rs | 73 +-- client/beefy/src/metrics.rs | 13 +- client/beefy/src/round.rs | 358 +++++++++---- client/beefy/src/tests.rs | 590 ++++++++++++++++++++ client/beefy/src/worker.rs | 978 ++++++++++++++++++++++++---------- frame/beefy/src/lib.rs | 28 +- primitives/beefy/Cargo.toml | 5 + test-utils/runtime/Cargo.toml | 2 + test-utils/runtime/src/lib.rs | 6 + 12 files changed, 1815 insertions(+), 568 deletions(-) create mode 100644 client/beefy/src/tests.rs diff --git a/Cargo.lock b/Cargo.lock index 1731ded2906c..81a53ed85885 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -484,12 +484,15 @@ dependencies = [ "beefy-primitives", "fnv", "futures 0.3.19", + "futures-timer", "hex", "log 0.4.14", "parity-scale-codec", "parking_lot 0.12.0", "sc-chain-spec", "sc-client-api", + "sc-consensus", + "sc-finality-grandpa", "sc-keystore", "sc-network", "sc-network-gossip", @@ -500,13 +503,19 @@ dependencies = [ "sp-application-crypto", "sp-arithmetic", "sp-blockchain", + "sp-consensus", "sp-core", + "sp-finality-grandpa", + "sp-keyring", "sp-keystore", "sp-runtime", "sp-tracing", "strum", "substrate-prometheus-endpoint", + "substrate-test-runtime-client", + "tempfile", "thiserror", + "tokio", "wasm-timer", ] @@ -10688,6 +10697,7 @@ dependencies = [ name = "substrate-test-runtime" version = "2.0.0" dependencies = [ + "beefy-primitives", "cfg-if 1.0.0", "frame-support", "frame-system", diff --git a/client/beefy/Cargo.toml b/client/beefy/Cargo.toml index 1cd0f1fd50d8..02be645b3fc0 100644 --- a/client/beefy/Cargo.toml +++ b/client/beefy/Cargo.toml @@ -10,6 +10,7 @@ description = "BEEFY Client gadget for substrate" [dependencies] fnv = "1.0.6" futures = "0.3" +futures-timer = "3.0.1" hex = "0.4.2" log = "0.4" parking_lot = "0.12.0" @@ -23,22 +24,31 @@ sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } sp-application-crypto = { version = "6.0.0", path = "../../primitives/application-crypto" } sp-arithmetic = { version = "5.0.0", path = "../../primitives/arithmetic" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } +sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } sp-core = { version = "6.0.0", path = "../../primitives/core" } sp-keystore = { version = "0.12.0", path = "../../primitives/keystore" } sp-runtime = { version = "6.0.0", path = "../../primitives/runtime" } sc-chain-spec = { version = "4.0.0-dev", path = "../../client/chain-spec" } -sc-utils = { version = "4.0.0-dev", path = "../utils" } sc-client-api = { version = "4.0.0-dev", path = "../api" } +sc-finality-grandpa = { version = "0.10.0-dev", path = "../../client/finality-grandpa" } sc-keystore = { version = "4.0.0-dev", path = "../keystore" } sc-network = { version = "0.10.0-dev", path = "../network" } sc-network-gossip = { version = "0.10.0-dev", path = "../network-gossip" } +sc-utils = { version = "4.0.0-dev", path = "../utils" } beefy-primitives = { version = "4.0.0-dev", path = "../../primitives/beefy" } [dev-dependencies] -sp-tracing = { version = "5.0.0", path = "../../primitives/tracing" } +sc-consensus = { version = "0.10.0-dev", path = "../consensus/common" } sc-network-test = { version = "0.8.0", path = "../network/test" } +sp-finality-grandpa = { version = "4.0.0-dev", path = "../../primitives/finality-grandpa" } +sp-keyring = { version = "6.0.0", path = "../../primitives/keyring" } +sp-tracing = { version = "5.0.0", path = "../../primitives/tracing" } +substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } + serde = "1.0.136" strum = { version = "0.23", features = ["derive"] } +tokio = "1.15" +tempfile = "3.1.0" diff --git a/client/beefy/src/gossip.rs b/client/beefy/src/gossip.rs index 37358441ef88..54d283fede32 100644 --- a/client/beefy/src/gossip.rs +++ b/client/beefy/src/gossip.rs @@ -35,9 +35,6 @@ use beefy_primitives::{ use crate::keystore::BeefyKeystore; -// Limit BEEFY gossip by keeping only a bound number of voting rounds alive. -const MAX_LIVE_GOSSIP_ROUNDS: usize = 3; - // Timeout for rebroadcasting messages. const REBROADCAST_AFTER: Duration = Duration::from_secs(60 * 5); @@ -52,13 +49,50 @@ where /// A type that represents hash of the message. pub type MessageHash = [u8; 8]; -type KnownVotes = BTreeMap, fnv::FnvHashSet>; +struct KnownVotes { + last_done: Option>, + live: BTreeMap, fnv::FnvHashSet>, +} + +impl KnownVotes { + pub fn new() -> Self { + Self { last_done: None, live: BTreeMap::new() } + } + + /// Create new round votes set if not already present. + fn insert(&mut self, round: NumberFor) { + self.live.entry(round).or_default(); + } + + /// Remove `round` and older from live set, update `last_done` accordingly. + fn conclude(&mut self, round: NumberFor) { + self.live.retain(|&number, _| number > round); + self.last_done = self.last_done.max(Some(round)); + } + + /// Return true if `round` is newer than previously concluded rounds. + /// + /// Latest concluded round is still considered alive to allow proper gossiping for it. + fn is_live(&self, round: &NumberFor) -> bool { + Some(*round) >= self.last_done + } + + /// Add new _known_ `hash` to the round's known votes. + fn add_known(&mut self, round: &NumberFor, hash: MessageHash) { + self.live.get_mut(round).map(|known| known.insert(hash)); + } + + /// Check if `hash` is already part of round's known votes. + fn is_known(&self, round: &NumberFor, hash: &MessageHash) -> bool { + self.live.get(round).map(|known| known.contains(hash)).unwrap_or(false) + } +} /// BEEFY gossip validator /// /// Validate BEEFY gossip messages and limit the number of live BEEFY voting rounds. /// -/// Allows messages from last [`MAX_LIVE_GOSSIP_ROUNDS`] to flow, everything else gets +/// Allows messages for 'rounds >= last concluded' to flow, everything else gets /// rejected/expired. /// ///All messaging is handled in a single BEEFY global topic. @@ -78,57 +112,25 @@ where pub fn new() -> GossipValidator { GossipValidator { topic: topic::(), - known_votes: RwLock::new(BTreeMap::new()), + known_votes: RwLock::new(KnownVotes::new()), next_rebroadcast: Mutex::new(Instant::now() + REBROADCAST_AFTER), } } /// Note a voting round. /// - /// Noting `round` will keep `round` live. - /// - /// We retain the [`MAX_LIVE_GOSSIP_ROUNDS`] most **recent** voting rounds as live. - /// As long as a voting round is live, it will be gossiped to peer nodes. + /// Noting round will start a live `round`. pub(crate) fn note_round(&self, round: NumberFor) { - debug!(target: "beefy", "🥩 About to note round #{}", round); - - let mut live = self.known_votes.write(); - - if !live.contains_key(&round) { - live.insert(round, Default::default()); - } - - if live.len() > MAX_LIVE_GOSSIP_ROUNDS { - let to_remove = live.iter().next().map(|x| x.0).copied(); - if let Some(first) = to_remove { - live.remove(&first); - } - } - } - - fn add_known(known_votes: &mut KnownVotes, round: &NumberFor, hash: MessageHash) { - known_votes.get_mut(round).map(|known| known.insert(hash)); - } - - // Note that we will always keep the most recent unseen round alive. - // - // This is a preliminary fix and the detailed description why we are - // doing this can be found as part of the issue below - // - // https://github.com/paritytech/grandpa-bridge-gadget/issues/237 - // - fn is_live(known_votes: &KnownVotes, round: &NumberFor) -> bool { - let unseen_round = if let Some(max_known_round) = known_votes.keys().last() { - round > max_known_round - } else { - known_votes.is_empty() - }; - - known_votes.contains_key(round) || unseen_round + debug!(target: "beefy", "🥩 About to note gossip round #{}", round); + self.known_votes.write().insert(round); } - fn is_known(known_votes: &KnownVotes, round: &NumberFor, hash: &MessageHash) -> bool { - known_votes.get(round).map(|known| known.contains(hash)).unwrap_or(false) + /// Conclude a voting round. + /// + /// This can be called once round is complete so we stop gossiping for it. + pub(crate) fn conclude_round(&self, round: NumberFor) { + debug!(target: "beefy", "🥩 About to drop gossip round #{}", round); + self.known_votes.write().conclude(round); } } @@ -152,17 +154,17 @@ where { let known_votes = self.known_votes.read(); - if !GossipValidator::::is_live(&known_votes, &round) { + if !known_votes.is_live(&round) { return ValidationResult::Discard } - if GossipValidator::::is_known(&known_votes, &round, &msg_hash) { + if known_votes.is_known(&round, &msg_hash) { return ValidationResult::ProcessAndKeep(self.topic) } } if BeefyKeystore::verify(&msg.id, &msg.signature, &msg.commitment.encode()) { - GossipValidator::::add_known(&mut *self.known_votes.write(), &round, msg_hash); + self.known_votes.write().add_known(&round, msg_hash); return ValidationResult::ProcessAndKeep(self.topic) } else { // TODO: report peer @@ -182,7 +184,7 @@ where }; let round = msg.commitment.block_number; - let expired = !GossipValidator::::is_live(&known_votes, &round); + let expired = !known_votes.is_live(&round); trace!(target: "beefy", "🥩 Message for round #{} expired: {}", round, expired); @@ -212,11 +214,11 @@ where let msg = match VoteMessage::, Public, Signature>::decode(&mut data) { Ok(vote) => vote, - Err(_) => return true, + Err(_) => return false, }; let round = msg.commitment.block_number; - let allowed = GossipValidator::::is_live(&known_votes, &round); + let allowed = known_votes.is_live(&round); debug!(target: "beefy", "🥩 Message for round #{} allowed: {}", round, allowed); @@ -240,60 +242,58 @@ mod tests { use super::*; #[test] - fn note_round_works() { - let gv = GossipValidator::::new(); - - gv.note_round(1u64); - - let live = gv.known_votes.read(); - assert!(GossipValidator::::is_live(&live, &1u64)); - - drop(live); - - gv.note_round(3u64); - gv.note_round(7u64); - gv.note_round(10u64); - - let live = gv.known_votes.read(); - - assert_eq!(live.len(), MAX_LIVE_GOSSIP_ROUNDS); - - assert!(!GossipValidator::::is_live(&live, &1u64)); - assert!(GossipValidator::::is_live(&live, &3u64)); - assert!(GossipValidator::::is_live(&live, &7u64)); - assert!(GossipValidator::::is_live(&live, &10u64)); + fn known_votes_insert_remove() { + let mut kv = KnownVotes::::new(); + + kv.insert(1); + kv.insert(1); + kv.insert(2); + assert_eq!(kv.live.len(), 2); + + let mut kv = KnownVotes::::new(); + kv.insert(1); + kv.insert(2); + kv.insert(3); + + assert!(kv.last_done.is_none()); + kv.conclude(2); + assert_eq!(kv.live.len(), 1); + assert!(!kv.live.contains_key(&2)); + assert_eq!(kv.last_done, Some(2)); + + kv.conclude(1); + assert_eq!(kv.last_done, Some(2)); + + kv.conclude(3); + assert_eq!(kv.last_done, Some(3)); + assert!(kv.live.is_empty()); } #[test] - fn keeps_most_recent_max_rounds() { + fn note_and_drop_round_works() { let gv = GossipValidator::::new(); - gv.note_round(3u64); - gv.note_round(7u64); - gv.note_round(10u64); gv.note_round(1u64); - let live = gv.known_votes.read(); - - assert_eq!(live.len(), MAX_LIVE_GOSSIP_ROUNDS); + assert!(gv.known_votes.read().is_live(&1u64)); - assert!(GossipValidator::::is_live(&live, &3u64)); - assert!(!GossipValidator::::is_live(&live, &1u64)); - - drop(live); + gv.note_round(3u64); + gv.note_round(7u64); + gv.note_round(10u64); - gv.note_round(23u64); - gv.note_round(15u64); - gv.note_round(20u64); - gv.note_round(2u64); + assert_eq!(gv.known_votes.read().live.len(), 4); - let live = gv.known_votes.read(); + gv.conclude_round(7u64); - assert_eq!(live.len(), MAX_LIVE_GOSSIP_ROUNDS); + let votes = gv.known_votes.read(); - assert!(GossipValidator::::is_live(&live, &15u64)); - assert!(GossipValidator::::is_live(&live, &20u64)); - assert!(GossipValidator::::is_live(&live, &23u64)); + // rounds 1 and 3 are outdated, don't gossip anymore + assert!(!votes.is_live(&1u64)); + assert!(!votes.is_live(&3u64)); + // latest concluded round is still gossiped + assert!(votes.is_live(&7u64)); + // round 10 is alive and in-progress + assert!(votes.is_live(&10u64)); } #[test] @@ -304,22 +304,18 @@ mod tests { gv.note_round(7u64); gv.note_round(10u64); - let live = gv.known_votes.read(); - - assert_eq!(live.len(), MAX_LIVE_GOSSIP_ROUNDS); - - drop(live); + assert_eq!(gv.known_votes.read().live.len(), 3); // note round #7 again -> should not change anything gv.note_round(7u64); - let live = gv.known_votes.read(); + let votes = gv.known_votes.read(); - assert_eq!(live.len(), MAX_LIVE_GOSSIP_ROUNDS); + assert_eq!(votes.live.len(), 3); - assert!(GossipValidator::::is_live(&live, &3u64)); - assert!(GossipValidator::::is_live(&live, &7u64)); - assert!(GossipValidator::::is_live(&live, &10u64)); + assert!(votes.is_live(&3u64)); + assert!(votes.is_live(&7u64)); + assert!(votes.is_live(&10u64)); } struct TestContext; @@ -349,29 +345,32 @@ mod tests { beefy_keystore.sign(&who.public(), &commitment.encode()).unwrap() } + fn dummy_vote(block_number: u64) -> VoteMessage { + let payload = Payload::new(known_payload_ids::MMR_ROOT_ID, MmrRootHash::default().encode()); + let commitment = Commitment { payload, block_number, validator_set_id: 0 }; + let signature = sign_commitment(&Keyring::Alice, &commitment); + + VoteMessage { commitment, id: Keyring::Alice.public(), signature } + } + #[test] fn should_avoid_verifying_signatures_twice() { let gv = GossipValidator::::new(); let sender = sc_network::PeerId::random(); let mut context = TestContext; - let payload = Payload::new(known_payload_ids::MMR_ROOT_ID, MmrRootHash::default().encode()); - let commitment = Commitment { payload, block_number: 3_u64, validator_set_id: 0 }; - - let signature = sign_commitment(&Keyring::Alice, &commitment); - - let vote = VoteMessage { commitment, id: Keyring::Alice.public(), signature }; + let vote = dummy_vote(3); gv.note_round(3u64); gv.note_round(7u64); gv.note_round(10u64); - // first time the cache should be populated. + // first time the cache should be populated let res = gv.validate(&mut context, &sender, &vote.encode()); assert!(matches!(res, ValidationResult::ProcessAndKeep(_))); assert_eq!( - gv.known_votes.read().get(&vote.commitment.block_number).map(|x| x.len()), + gv.known_votes.read().live.get(&vote.commitment.block_number).map(|x| x.len()), Some(1) ); @@ -380,17 +379,84 @@ mod tests { assert!(matches!(res, ValidationResult::ProcessAndKeep(_))); - // next we should quickly reject if the round is not live. - gv.note_round(11_u64); - gv.note_round(12_u64); + // next we should quickly reject if the round is not live + gv.conclude_round(7_u64); - assert!(!GossipValidator::::is_live( - &*gv.known_votes.read(), - &vote.commitment.block_number - )); + assert!(!gv.known_votes.read().is_live(&vote.commitment.block_number)); let res = gv.validate(&mut context, &sender, &vote.encode()); assert!(matches!(res, ValidationResult::Discard)); } + + #[test] + fn messages_allowed_and_expired() { + let gv = GossipValidator::::new(); + let sender = sc_network::PeerId::random(); + let topic = Default::default(); + let intent = MessageIntent::Broadcast; + + // note round 2 and 3, then conclude 2 + gv.note_round(2u64); + gv.note_round(3u64); + gv.conclude_round(2u64); + let mut allowed = gv.message_allowed(); + let mut expired = gv.message_expired(); + + // check bad vote format + assert!(!allowed(&sender, intent, &topic, &mut [0u8; 16])); + assert!(expired(topic, &mut [0u8; 16])); + + // inactive round 1 -> expired + let vote = dummy_vote(1); + let mut encoded_vote = vote.encode(); + assert!(!allowed(&sender, intent, &topic, &mut encoded_vote)); + assert!(expired(topic, &mut encoded_vote)); + + // active round 2 -> !expired - concluded but still gossiped + let vote = dummy_vote(2); + let mut encoded_vote = vote.encode(); + assert!(allowed(&sender, intent, &topic, &mut encoded_vote)); + assert!(!expired(topic, &mut encoded_vote)); + + // in progress round 3 -> !expired + let vote = dummy_vote(3); + let mut encoded_vote = vote.encode(); + assert!(allowed(&sender, intent, &topic, &mut encoded_vote)); + assert!(!expired(topic, &mut encoded_vote)); + + // unseen round 4 -> !expired + let vote = dummy_vote(3); + let mut encoded_vote = vote.encode(); + assert!(allowed(&sender, intent, &topic, &mut encoded_vote)); + assert!(!expired(topic, &mut encoded_vote)); + } + + #[test] + fn messages_rebroadcast() { + let gv = GossipValidator::::new(); + let sender = sc_network::PeerId::random(); + let topic = Default::default(); + + let vote = dummy_vote(1); + let mut encoded_vote = vote.encode(); + + // re-broadcasting only allowed at `REBROADCAST_AFTER` intervals + let intent = MessageIntent::PeriodicRebroadcast; + let mut allowed = gv.message_allowed(); + + // rebroadcast not allowed so soon after GossipValidator creation + assert!(!allowed(&sender, intent, &topic, &mut encoded_vote)); + + // hack the inner deadline to be `now` + *gv.next_rebroadcast.lock() = Instant::now(); + + // still not allowed on old `allowed` closure result + assert!(!allowed(&sender, intent, &topic, &mut encoded_vote)); + + // renew closure result + let mut allowed = gv.message_allowed(); + // rebroadcast should be allowed now + assert!(allowed(&sender, intent, &topic, &mut encoded_vote)); + } } diff --git a/client/beefy/src/lib.rs b/client/beefy/src/lib.rs index 29d74c15dd59..8a6e175f5832 100644 --- a/client/beefy/src/lib.rs +++ b/client/beefy/src/lib.rs @@ -18,14 +18,14 @@ use std::sync::Arc; -use log::debug; use prometheus::Registry; use sc_client_api::{Backend, BlockchainEvents, Finalizer}; -use sc_network_gossip::{GossipEngine, Network as GossipNetwork}; +use sc_network_gossip::Network as GossipNetwork; use sp_api::ProvideRuntimeApi; use sp_blockchain::HeaderBackend; +use sp_consensus::SyncOracle; use sp_keystore::SyncCryptoStorePtr; use sp_runtime::traits::Block; @@ -41,6 +41,10 @@ mod round; mod worker; pub mod notification; + +#[cfg(test)] +mod tests; + pub use beefy_protocol_name::standard_name as protocol_standard_name; pub(crate) mod beefy_protocol_name { @@ -112,7 +116,7 @@ where BE: Backend, C: Client, C::Api: BeefyApi, - N: GossipNetwork + Clone + Send + 'static, + N: GossipNetwork + Clone + SyncOracle + Send + Sync + 'static, { /// BEEFY client pub client: Arc, @@ -134,6 +138,7 @@ where pub protocol_name: std::borrow::Cow<'static, str>, } +#[cfg(not(test))] /// Start the BEEFY gadget. /// /// This is a thin shim around running and awaiting a BEEFY worker. @@ -143,7 +148,7 @@ where BE: Backend, C: Client, C::Api: BeefyApi, - N: GossipNetwork + Clone + Send + 'static, + N: GossipNetwork + Clone + SyncOracle + Send + Sync + 'static, { let BeefyParams { client, @@ -157,18 +162,24 @@ where protocol_name, } = beefy_params; + let sync_oracle = network.clone(); let gossip_validator = Arc::new(gossip::GossipValidator::new()); - let gossip_engine = GossipEngine::new(network, protocol_name, gossip_validator.clone(), None); + let gossip_engine = sc_network_gossip::GossipEngine::new( + network, + protocol_name, + gossip_validator.clone(), + None, + ); let metrics = prometheus_registry.as_ref().map(metrics::Metrics::register).and_then( |result| match result { Ok(metrics) => { - debug!(target: "beefy", "🥩 Registered metrics"); + log::debug!(target: "beefy", "🥩 Registered metrics"); Some(metrics) }, Err(err) => { - debug!(target: "beefy", "🥩 Failed to register metrics: {:?}", err); + log::debug!(target: "beefy", "🥩 Failed to register metrics: {:?}", err); None }, }, @@ -184,54 +195,10 @@ where gossip_validator, min_block_delta, metrics, + sync_oracle, }; - let worker = worker::BeefyWorker::<_, _, _>::new(worker_params); + let worker = worker::BeefyWorker::<_, _, _, _>::new(worker_params); worker.run().await } - -#[cfg(test)] -mod tests { - use super::*; - use sc_chain_spec::{ChainSpec, GenericChainSpec}; - use serde::{Deserialize, Serialize}; - use sp_core::H256; - use sp_runtime::{BuildStorage, Storage}; - - #[derive(Debug, Serialize, Deserialize)] - struct Genesis(std::collections::BTreeMap); - impl BuildStorage for Genesis { - fn assimilate_storage(&self, storage: &mut Storage) -> Result<(), String> { - storage.top.extend( - self.0.iter().map(|(a, b)| (a.clone().into_bytes(), b.clone().into_bytes())), - ); - Ok(()) - } - } - - #[test] - fn beefy_protocol_name() { - let chain_spec = GenericChainSpec::::from_json_file(std::path::PathBuf::from( - "../chain-spec/res/chain_spec.json", - )) - .unwrap() - .cloned_box(); - - // Create protocol name using random genesis hash. - let genesis_hash = H256::random(); - let expected = format!("/{}/beefy/1", hex::encode(genesis_hash)); - let proto_name = beefy_protocol_name::standard_name(&genesis_hash, &chain_spec); - assert_eq!(proto_name.to_string(), expected); - - // Create protocol name using hardcoded genesis hash. Verify exact representation. - let genesis_hash = [ - 50, 4, 60, 123, 58, 106, 216, 246, 194, 188, 139, 193, 33, 212, 202, 171, 9, 55, 123, - 94, 8, 43, 12, 251, 187, 57, 173, 19, 188, 74, 205, 147, - ]; - let expected = - "/32043c7b3a6ad8f6c2bc8bc121d4caab09377b5e082b0cfbbb39ad13bc4acd93/beefy/1".to_string(); - let proto_name = beefy_protocol_name::standard_name(&genesis_hash, &chain_spec); - assert_eq!(proto_name.to_string(), expected); - } -} diff --git a/client/beefy/src/metrics.rs b/client/beefy/src/metrics.rs index 4b2a5c8dfd5c..20fa98e52fdd 100644 --- a/client/beefy/src/metrics.rs +++ b/client/beefy/src/metrics.rs @@ -18,7 +18,9 @@ //! BEEFY Prometheus metrics definition -use prometheus::{register, Counter, Gauge, PrometheusError, Registry, U64}; +#[cfg(not(test))] +use prometheus::{register, PrometheusError, Registry}; +use prometheus::{Counter, Gauge, U64}; /// BEEFY metrics exposed through Prometheus pub(crate) struct Metrics { @@ -37,6 +39,7 @@ pub(crate) struct Metrics { } impl Metrics { + #[cfg(not(test))] pub(crate) fn register(registry: &Registry) -> Result { Ok(Self { beefy_validator_set_id: register( @@ -97,3 +100,11 @@ macro_rules! metric_inc { } }}; } + +#[cfg(test)] +#[macro_export] +macro_rules! metric_get { + ($self:ident, $m:ident) => {{ + $self.metrics.as_ref().map(|metrics| metrics.$m.clone()) + }}; +} diff --git a/client/beefy/src/round.rs b/client/beefy/src/round.rs index e5404cfa6d21..eba769b2356f 100644 --- a/client/beefy/src/round.rs +++ b/client/beefy/src/round.rs @@ -16,7 +16,10 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::{collections::BTreeMap, hash::Hash}; +use std::{ + collections::{BTreeMap, HashMap}, + hash::Hash, +}; use log::{debug, trace}; @@ -24,25 +27,33 @@ use beefy_primitives::{ crypto::{Public, Signature}, ValidatorSet, ValidatorSetId, }; -use sp_arithmetic::traits::AtLeast32BitUnsigned; -use sp_runtime::traits::MaybeDisplay; +use sp_runtime::traits::{Block, NumberFor}; +/// Tracks for each round which validators have voted/signed and +/// whether the local `self` validator has voted/signed. +/// +/// Does not do any validation on votes or signatures, layers above need to handle that (gossip). #[derive(Default)] struct RoundTracker { - votes: Vec<(Public, Signature)>, + self_vote: bool, + votes: HashMap, } impl RoundTracker { - fn add_vote(&mut self, vote: (Public, Signature)) -> bool { - // this needs to handle equivocations in the future - if self.votes.contains(&vote) { + fn add_vote(&mut self, vote: (Public, Signature), self_vote: bool) -> bool { + if self.votes.contains_key(&vote.0) { return false } - self.votes.push(vote); + self.self_vote = self.self_vote || self_vote; + self.votes.insert(vote.0, vote.1); true } + fn has_self_vote(&self) -> bool { + self.self_vote + } + fn is_done(&self, threshold: usize) -> bool { self.votes.len() >= threshold } @@ -53,74 +64,125 @@ fn threshold(authorities: usize) -> usize { authorities - faulty } -pub(crate) struct Rounds { - rounds: BTreeMap<(Payload, Number), RoundTracker>, +/// Keeps track of all voting rounds (block numbers) within a session. +/// Only round numbers > `best_done` are of interest, all others are considered stale. +/// +/// Does not do any validation on votes or signatures, layers above need to handle that (gossip). +pub(crate) struct Rounds { + rounds: BTreeMap<(Payload, NumberFor), RoundTracker>, + best_done: Option>, + session_start: NumberFor, validator_set: ValidatorSet, + prev_validator_set: ValidatorSet, } -impl Rounds +impl Rounds where - P: Ord + Hash, - N: Ord + AtLeast32BitUnsigned + MaybeDisplay, + P: Ord + Hash + Clone, + B: Block, { - pub(crate) fn new(validator_set: ValidatorSet) -> Self { - Rounds { rounds: BTreeMap::new(), validator_set } + pub(crate) fn new( + session_start: NumberFor, + validator_set: ValidatorSet, + prev_validator_set: ValidatorSet, + ) -> Self { + Rounds { + rounds: BTreeMap::new(), + best_done: None, + session_start, + validator_set, + prev_validator_set, + } } } -impl Rounds +impl Rounds where - H: Ord + Hash + Clone, - N: Ord + AtLeast32BitUnsigned + MaybeDisplay + Clone, + P: Ord + Hash + Clone, + B: Block, { - pub(crate) fn validator_set_id(&self) -> ValidatorSetId { - self.validator_set.id() + pub(crate) fn validator_set_id_for(&self, block_number: NumberFor) -> ValidatorSetId { + if block_number > self.session_start { + self.validator_set.id() + } else { + self.prev_validator_set.id() + } } - pub(crate) fn validators(&self) -> &[Public] { - self.validator_set.validators() + pub(crate) fn validators_for(&self, block_number: NumberFor) -> &[Public] { + if block_number > self.session_start { + self.validator_set.validators() + } else { + self.prev_validator_set.validators() + } } - pub(crate) fn add_vote(&mut self, round: &(H, N), vote: (Public, Signature)) -> bool { - if self.validator_set.validators().iter().any(|id| vote.0 == *id) { - self.rounds.entry(round.clone()).or_default().add_vote(vote) - } else { + pub(crate) fn validator_set(&self) -> &ValidatorSet { + &self.validator_set + } + + pub(crate) fn session_start(&self) -> &NumberFor { + &self.session_start + } + + pub(crate) fn should_self_vote(&self, round: &(P, NumberFor)) -> bool { + Some(round.1.clone()) > self.best_done && + self.rounds.get(round).map(|tracker| !tracker.has_self_vote()).unwrap_or(true) + } + + pub(crate) fn add_vote( + &mut self, + round: &(P, NumberFor), + vote: (Public, Signature), + self_vote: bool, + ) -> bool { + if Some(round.1.clone()) <= self.best_done { + debug!( + target: "beefy", + "🥩 received vote for old stale round {:?}, ignoring", + round.1 + ); + false + } else if !self.validator_set.validators().iter().any(|id| vote.0 == *id) { + debug!( + target: "beefy", + "🥩 received vote {:?} from validator that is not in the validator set, ignoring", + vote + ); false + } else { + self.rounds.entry(round.clone()).or_default().add_vote(vote, self_vote) } } - pub(crate) fn is_done(&self, round: &(H, N)) -> bool { + pub(crate) fn try_conclude( + &mut self, + round: &(P, NumberFor), + ) -> Option>> { let done = self .rounds .get(round) .map(|tracker| tracker.is_done(threshold(self.validator_set.len()))) .unwrap_or(false); - - debug!(target: "beefy", "🥩 Round #{} done: {}", round.1, done); - - done - } - - pub(crate) fn drop(&mut self, round: &(H, N)) -> Option>> { - trace!(target: "beefy", "🥩 About to drop round #{}", round.1); - - let signatures = self.rounds.remove(round)?.votes; - - Some( - self.validator_set - .validators() - .iter() - .map(|authority_id| { - signatures.iter().find_map(|(id, sig)| { - if id == authority_id { - Some(sig.clone()) - } else { - None - } - }) - }) - .collect(), - ) + trace!(target: "beefy", "🥩 Round #{} done: {}", round.1, done); + + if done { + // remove this and older (now stale) rounds + let signatures = self.rounds.remove(round)?.votes; + self.rounds.retain(|&(_, number), _| number > round.1); + self.best_done = self.best_done.clone().max(Some(round.1.clone())); + trace!(target: "beefy", "🥩 Concluded round #{}", round.1); + + Some( + self.validator_set + .validators() + .iter() + .map(|authority_id| signatures.get(authority_id).cloned()) + .collect(), + ) + } else { + None + } } } @@ -128,13 +190,52 @@ where mod tests { use sc_network_test::Block; use sp_core::H256; - use sp_runtime::traits::NumberFor; use beefy_primitives::{crypto::Public, ValidatorSet}; - use super::Rounds; + use super::{threshold, RoundTracker, Rounds}; use crate::keystore::tests::Keyring; + #[test] + fn round_tracker() { + let mut rt = RoundTracker::default(); + let bob_vote = (Keyring::Bob.public(), Keyring::Bob.sign(b"I am committed")); + let threshold = 2; + + // self vote not added yet + assert!(!rt.has_self_vote()); + + // adding new vote allowed + assert!(rt.add_vote(bob_vote.clone(), false)); + // adding existing vote not allowed + assert!(!rt.add_vote(bob_vote, false)); + + // self vote still not added yet + assert!(!rt.has_self_vote()); + + // vote is not done + assert!(!rt.is_done(threshold)); + + let alice_vote = (Keyring::Alice.public(), Keyring::Alice.sign(b"I am committed")); + // adding new vote (self vote this time) allowed + assert!(rt.add_vote(alice_vote, true)); + + // self vote registered + assert!(rt.has_self_vote()); + // vote is now done + assert!(rt.is_done(threshold)); + } + + #[test] + fn vote_threshold() { + assert_eq!(threshold(1), 1); + assert_eq!(threshold(2), 2); + assert_eq!(threshold(3), 3); + assert_eq!(threshold(4), 3); + assert_eq!(threshold(100), 67); + assert_eq!(threshold(300), 201); + } + #[test] fn new_rounds() { sp_tracing::try_init_simple(); @@ -145,116 +246,175 @@ mod tests { ) .unwrap(); - let rounds = Rounds::>::new(validators); - - assert_eq!(42, rounds.validator_set_id()); + let session_start = 1u64.into(); + let rounds = Rounds::::new(session_start, validators.clone(), validators); + assert_eq!(42, rounds.validator_set_id_for(session_start)); + assert_eq!(1, *rounds.session_start()); assert_eq!( &vec![Keyring::Alice.public(), Keyring::Bob.public(), Keyring::Charlie.public()], - rounds.validators() + rounds.validators_for(session_start) ); } #[test] - fn add_vote() { + fn add_and_conclude_votes() { sp_tracing::try_init_simple(); let validators = ValidatorSet::::new( - vec![Keyring::Alice.public(), Keyring::Bob.public(), Keyring::Charlie.public()], + vec![ + Keyring::Alice.public(), + Keyring::Bob.public(), + Keyring::Charlie.public(), + Keyring::Eve.public(), + ], Default::default(), ) .unwrap(); + let round = (H256::from_low_u64_le(1), 1); - let mut rounds = Rounds::>::new(validators); + let session_start = 1u64.into(); + let mut rounds = Rounds::::new(session_start, validators.clone(), validators); + // no self vote yet, should self vote + assert!(rounds.should_self_vote(&round)); + + // add 1st good vote assert!(rounds.add_vote( - &(H256::from_low_u64_le(1), 1), - (Keyring::Alice.public(), Keyring::Alice.sign(b"I am committed")) + &round, + (Keyring::Alice.public(), Keyring::Alice.sign(b"I am committed")), + true )); + // round not concluded + assert!(rounds.try_conclude(&round).is_none()); + // self vote already present, should not self vote + assert!(!rounds.should_self_vote(&round)); - assert!(!rounds.is_done(&(H256::from_low_u64_le(1), 1))); - - // invalid vote + // double voting not allowed assert!(!rounds.add_vote( - &(H256::from_low_u64_le(1), 1), - (Keyring::Dave.public(), Keyring::Dave.sign(b"I am committed")) + &round, + (Keyring::Alice.public(), Keyring::Alice.sign(b"I am committed")), + true )); - assert!(!rounds.is_done(&(H256::from_low_u64_le(1), 1))); + // invalid vote (Dave is not a validator) + assert!(!rounds.add_vote( + &round, + (Keyring::Dave.public(), Keyring::Dave.sign(b"I am committed")), + false + )); + assert!(rounds.try_conclude(&round).is_none()); + // add 2nd good vote assert!(rounds.add_vote( - &(H256::from_low_u64_le(1), 1), - (Keyring::Bob.public(), Keyring::Bob.sign(b"I am committed")) + &round, + (Keyring::Bob.public(), Keyring::Bob.sign(b"I am committed")), + false )); + // round not concluded + assert!(rounds.try_conclude(&round).is_none()); - assert!(!rounds.is_done(&(H256::from_low_u64_le(1), 1))); - + // add 3rd good vote assert!(rounds.add_vote( - &(H256::from_low_u64_le(1), 1), - (Keyring::Charlie.public(), Keyring::Charlie.sign(b"I am committed")) + &round, + (Keyring::Charlie.public(), Keyring::Charlie.sign(b"I am committed")), + false )); + // round concluded + assert!(rounds.try_conclude(&round).is_some()); - assert!(rounds.is_done(&(H256::from_low_u64_le(1), 1))); + // Eve is a validator, but round was concluded, adding vote disallowed + assert!(!rounds.add_vote( + &round, + (Keyring::Eve.public(), Keyring::Eve.sign(b"I am committed")), + false + )); } #[test] - fn drop() { + fn multiple_rounds() { sp_tracing::try_init_simple(); let validators = ValidatorSet::::new( - vec![Keyring::Alice.public(), Keyring::Bob.public(), Keyring::Charlie.public()], + vec![ + Keyring::Alice.public(), + Keyring::Bob.public(), + Keyring::Charlie.public(), + Keyring::Dave.public(), + ], Default::default(), ) .unwrap(); - let mut rounds = Rounds::>::new(validators); + let session_start = 1u64.into(); + let mut rounds = Rounds::::new(session_start, validators.clone(), validators); // round 1 - rounds.add_vote( + assert!(rounds.add_vote( &(H256::from_low_u64_le(1), 1), (Keyring::Alice.public(), Keyring::Alice.sign(b"I am committed")), - ); - rounds.add_vote( + true, + )); + assert!(rounds.add_vote( &(H256::from_low_u64_le(1), 1), (Keyring::Bob.public(), Keyring::Bob.sign(b"I am committed")), - ); + false, + )); + assert!(rounds.add_vote( + &(H256::from_low_u64_le(1), 1), + (Keyring::Charlie.public(), Keyring::Charlie.sign(b"I am committed")), + false, + )); // round 2 - rounds.add_vote( + assert!(rounds.add_vote( &(H256::from_low_u64_le(2), 2), (Keyring::Alice.public(), Keyring::Alice.sign(b"I am again committed")), - ); - rounds.add_vote( + true, + )); + assert!(rounds.add_vote( &(H256::from_low_u64_le(2), 2), (Keyring::Bob.public(), Keyring::Bob.sign(b"I am again committed")), - ); + false, + )); + assert!(rounds.add_vote( + &(H256::from_low_u64_le(2), 2), + (Keyring::Charlie.public(), Keyring::Charlie.sign(b"I am again committed")), + false, + )); // round 3 - rounds.add_vote( + assert!(rounds.add_vote( &(H256::from_low_u64_le(3), 3), (Keyring::Alice.public(), Keyring::Alice.sign(b"I am still committed")), - ); - rounds.add_vote( + true, + )); + assert!(rounds.add_vote( &(H256::from_low_u64_le(3), 3), (Keyring::Bob.public(), Keyring::Bob.sign(b"I am still committed")), - ); - + false, + )); + assert!(rounds.add_vote( + &(H256::from_low_u64_le(3), 3), + (Keyring::Charlie.public(), Keyring::Charlie.sign(b"I am still committed")), + false, + )); assert_eq!(3, rounds.rounds.len()); - // drop unknown round - assert!(rounds.drop(&(H256::from_low_u64_le(5), 5)).is_none()); + // conclude unknown round + assert!(rounds.try_conclude(&(H256::from_low_u64_le(5), 5)).is_none()); assert_eq!(3, rounds.rounds.len()); - // drop round 2 - let signatures = rounds.drop(&(H256::from_low_u64_le(2), 2)).unwrap(); - - assert_eq!(2, rounds.rounds.len()); + // conclude round 2 + let signatures = rounds.try_conclude(&(H256::from_low_u64_le(2), 2)).unwrap(); + assert_eq!(1, rounds.rounds.len()); assert_eq!( signatures, vec![ Some(Keyring::Alice.sign(b"I am again committed")), Some(Keyring::Bob.sign(b"I am again committed")), + Some(Keyring::Charlie.sign(b"I am again committed")), None ] ); diff --git a/client/beefy/src/tests.rs b/client/beefy/src/tests.rs new file mode 100644 index 000000000000..92b5ad91c11e --- /dev/null +++ b/client/beefy/src/tests.rs @@ -0,0 +1,590 @@ +// This file is part of Substrate. + +// Copyright (C) 2018-2022 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 . + +//! Tests and test helpers for BEEFY. + +use futures::{future, stream::FuturesUnordered, Future, StreamExt}; +use parking_lot::Mutex; +use serde::{Deserialize, Serialize}; +use std::{sync::Arc, task::Poll}; +use tokio::{runtime::Runtime, time::Duration}; + +use sc_chain_spec::{ChainSpec, GenericChainSpec}; +use sc_client_api::HeaderBackend; +use sc_consensus::BoxJustificationImport; +use sc_keystore::LocalKeystore; +use sc_network::{config::ProtocolConfig, NetworkService}; +use sc_network_gossip::GossipEngine; +use sc_network_test::{ + Block, BlockImportAdapter, FullPeerConfig, PassThroughVerifier, Peer, PeersClient, + PeersFullClient, TestNetFactory, +}; +use sc_utils::notification::NotificationReceiver; + +use beefy_primitives::{ + crypto::AuthorityId, ConsensusLog, MmrRootHash, ValidatorSet, BEEFY_ENGINE_ID, + KEY_TYPE as BeefyKeyType, +}; +use sp_consensus::BlockOrigin; +use sp_core::H256; +use sp_keystore::{SyncCryptoStore, SyncCryptoStorePtr}; +use sp_runtime::{ + codec::Encode, generic::BlockId, traits::Header as HeaderT, BuildStorage, DigestItem, Storage, +}; + +use substrate_test_runtime_client::{runtime::Header, Backend, ClientExt}; + +use crate::{ + beefy_protocol_name, + keystore::tests::Keyring as BeefyKeyring, + notification::*, + worker::{tests::TestModifiers, BeefyWorker}, +}; + +const BEEFY_PROTOCOL_NAME: &'static str = "/beefy/1"; + +type BeefyValidatorSet = ValidatorSet; +type BeefyPeer = Peer; + +#[derive(Debug, Serialize, Deserialize)] +struct Genesis(std::collections::BTreeMap); +impl BuildStorage for Genesis { + fn assimilate_storage(&self, storage: &mut Storage) -> Result<(), String> { + storage + .top + .extend(self.0.iter().map(|(a, b)| (a.clone().into_bytes(), b.clone().into_bytes()))); + Ok(()) + } +} + +#[test] +fn beefy_protocol_name() { + let chain_spec = GenericChainSpec::::from_json_file(std::path::PathBuf::from( + "../chain-spec/res/chain_spec.json", + )) + .unwrap() + .cloned_box(); + + // Create protocol name using random genesis hash. + let genesis_hash = H256::random(); + let expected = format!("/{}/beefy/1", hex::encode(genesis_hash)); + let proto_name = beefy_protocol_name::standard_name(&genesis_hash, &chain_spec); + assert_eq!(proto_name.to_string(), expected); + + // Create protocol name using hardcoded genesis hash. Verify exact representation. + let genesis_hash = [ + 50, 4, 60, 123, 58, 106, 216, 246, 194, 188, 139, 193, 33, 212, 202, 171, 9, 55, 123, 94, + 8, 43, 12, 251, 187, 57, 173, 19, 188, 74, 205, 147, + ]; + let expected = + "/32043c7b3a6ad8f6c2bc8bc121d4caab09377b5e082b0cfbbb39ad13bc4acd93/beefy/1".to_string(); + let proto_name = beefy_protocol_name::standard_name(&genesis_hash, &chain_spec); + assert_eq!(proto_name.to_string(), expected); +} + +// TODO: compiler warns us about unused `signed_commitment_stream`, will use in later tests +#[allow(dead_code)] +#[derive(Clone)] +pub(crate) struct BeefyLinkHalf { + signed_commitment_stream: BeefySignedCommitmentStream, + beefy_best_block_stream: BeefyBestBlockStream, +} + +#[derive(Default)] +pub(crate) struct PeerData { + pub(crate) beefy_link_half: Mutex>, + pub(crate) test_modifiers: Option, +} + +impl PeerData { + pub(crate) fn use_validator_set(&mut self, validator_set: &ValidatorSet) { + if let Some(tm) = self.test_modifiers.as_mut() { + tm.active_validators = validator_set.clone(); + } else { + self.test_modifiers = Some(TestModifiers { + active_validators: validator_set.clone(), + corrupt_mmr_roots: false, + }); + } + } +} + +pub(crate) struct BeefyTestNet { + peers: Vec, +} + +impl BeefyTestNet { + pub(crate) fn new(n_authority: usize, n_full: usize) -> Self { + let mut net = BeefyTestNet { peers: Vec::with_capacity(n_authority + n_full) }; + for _ in 0..n_authority { + net.add_authority_peer(); + } + for _ in 0..n_full { + net.add_full_peer(); + } + net + } + + pub(crate) fn add_authority_peer(&mut self) { + self.add_full_peer_with_config(FullPeerConfig { + notifications_protocols: vec![BEEFY_PROTOCOL_NAME.into()], + is_authority: true, + ..Default::default() + }) + } + + pub(crate) fn generate_blocks( + &mut self, + count: usize, + session_length: u64, + validator_set: &BeefyValidatorSet, + ) { + self.peer(0).generate_blocks(count, BlockOrigin::File, |builder| { + let mut block = builder.build().unwrap().block; + + let block_num = *block.header.number(); + let num_byte = block_num.to_le_bytes().into_iter().next().unwrap(); + let mmr_root = MmrRootHash::repeat_byte(num_byte); + + add_mmr_digest(&mut block.header, mmr_root); + + if block_num % session_length == 0 { + add_auth_change_digest(&mut block.header, validator_set.clone()); + } + + block + }); + } +} + +impl TestNetFactory for BeefyTestNet { + type Verifier = PassThroughVerifier; + type BlockImport = PeersClient; + type PeerData = PeerData; + + /// Create new test network with peers and given config. + fn from_config(_config: &ProtocolConfig) -> Self { + BeefyTestNet { peers: Vec::new() } + } + + fn make_verifier( + &self, + _client: PeersClient, + _cfg: &ProtocolConfig, + _: &PeerData, + ) -> Self::Verifier { + PassThroughVerifier::new(false) // use non-instant finality. + } + + fn make_block_import( + &self, + client: PeersClient, + ) -> ( + BlockImportAdapter, + Option>, + Self::PeerData, + ) { + (client.as_block_import(), None, PeerData::default()) + } + + fn peer(&mut self, i: usize) -> &mut BeefyPeer { + &mut self.peers[i] + } + + fn peers(&self) -> &Vec { + &self.peers + } + + fn mut_peers)>(&mut self, closure: F) { + closure(&mut self.peers); + } + + fn add_full_peer(&mut self) { + self.add_full_peer_with_config(FullPeerConfig { + notifications_protocols: vec![BEEFY_PROTOCOL_NAME.into()], + is_authority: false, + ..Default::default() + }) + } +} + +fn add_mmr_digest(header: &mut Header, mmr_hash: MmrRootHash) { + header.digest_mut().push(DigestItem::Consensus( + BEEFY_ENGINE_ID, + ConsensusLog::::MmrRoot(mmr_hash).encode(), + )); +} + +fn add_auth_change_digest(header: &mut Header, new_auth_set: BeefyValidatorSet) { + header.digest_mut().push(DigestItem::Consensus( + BEEFY_ENGINE_ID, + ConsensusLog::::AuthoritiesChange(new_auth_set).encode(), + )); +} + +pub(crate) fn make_beefy_ids(keys: &[BeefyKeyring]) -> Vec { + keys.iter().map(|key| key.clone().public().into()).collect() +} + +pub(crate) fn create_beefy_keystore(authority: BeefyKeyring) -> SyncCryptoStorePtr { + let keystore = Arc::new(LocalKeystore::in_memory()); + SyncCryptoStore::ecdsa_generate_new(&*keystore, BeefyKeyType, Some(&authority.to_seed())) + .expect("Creates authority key"); + keystore +} + +pub(crate) fn create_beefy_worker( + peer: &BeefyPeer, + key: &BeefyKeyring, + min_block_delta: u32, +) -> BeefyWorker>> { + let keystore = create_beefy_keystore(*key); + + let (signed_commitment_sender, signed_commitment_stream) = + BeefySignedCommitmentStream::::channel(); + let (beefy_best_block_sender, beefy_best_block_stream) = + BeefyBestBlockStream::::channel(); + + let beefy_link_half = BeefyLinkHalf { signed_commitment_stream, beefy_best_block_stream }; + *peer.data.beefy_link_half.lock() = Some(beefy_link_half); + let test_modifiers = peer.data.test_modifiers.clone().unwrap(); + + let network = peer.network_service().clone(); + let sync_oracle = network.clone(); + let gossip_validator = Arc::new(crate::gossip::GossipValidator::new()); + let gossip_engine = + GossipEngine::new(network, BEEFY_PROTOCOL_NAME, gossip_validator.clone(), None); + let worker_params = crate::worker::WorkerParams { + client: peer.client().as_client(), + backend: peer.client().as_backend(), + key_store: Some(keystore).into(), + signed_commitment_sender, + beefy_best_block_sender, + gossip_engine, + gossip_validator, + min_block_delta, + metrics: None, + sync_oracle, + }; + + BeefyWorker::<_, _, _, _>::new(worker_params, test_modifiers) +} + +// Spawns beefy voters. Returns a future to spawn on the runtime. +fn initialize_beefy( + net: &mut BeefyTestNet, + peers: &[BeefyKeyring], + min_block_delta: u32, +) -> impl Future { + let voters = FuturesUnordered::new(); + + for (peer_id, key) in peers.iter().enumerate() { + let worker = create_beefy_worker(&net.peers[peer_id], key, min_block_delta); + let gadget = worker.run(); + + fn assert_send(_: &T) {} + assert_send(&gadget); + voters.push(gadget); + } + + voters.for_each(|_| async move {}) +} + +fn block_until(future: impl Future + Unpin, net: &Arc>, runtime: &mut Runtime) { + let drive_to_completion = futures::future::poll_fn(|cx| { + net.lock().poll(cx); + Poll::<()>::Pending + }); + runtime.block_on(future::select(future, drive_to_completion)); +} + +fn run_for(duration: Duration, net: &Arc>, runtime: &mut Runtime) { + let sleep = runtime.spawn(async move { tokio::time::sleep(duration).await }); + block_until(sleep, net, runtime); +} + +pub(crate) fn get_beefy_streams( + net: &mut BeefyTestNet, + peers: &[BeefyKeyring], +) -> (Vec>, Vec>>) { + let mut best_block_streams = Vec::new(); + let mut signed_commitment_streams = Vec::new(); + for peer_id in 0..peers.len() { + let beefy_link_half = + net.peer(peer_id).data.beefy_link_half.lock().as_ref().unwrap().clone(); + let BeefyLinkHalf { signed_commitment_stream, beefy_best_block_stream } = beefy_link_half; + best_block_streams.push(beefy_best_block_stream.subscribe()); + signed_commitment_streams.push(signed_commitment_stream.subscribe()); + } + (best_block_streams, signed_commitment_streams) +} + +fn wait_for_best_beefy_blocks( + streams: Vec>, + net: &Arc>, + runtime: &mut Runtime, + expected_beefy_blocks: &[u64], +) { + let mut wait_for = Vec::new(); + let len = expected_beefy_blocks.len(); + streams.into_iter().enumerate().for_each(|(i, stream)| { + let mut expected = expected_beefy_blocks.iter(); + wait_for.push(Box::pin(stream.take(len).for_each(move |best_beefy_hash| { + let expected = expected.next(); + async move { + let block_id = BlockId::hash(best_beefy_hash); + let header = + net.lock().peer(i).client().as_client().expect_header(block_id).unwrap(); + let best_beefy = *header.number(); + + assert_eq!(expected, Some(best_beefy).as_ref()); + } + }))); + }); + let wait_for = futures::future::join_all(wait_for); + block_until(wait_for, net, runtime); +} + +fn wait_for_beefy_signed_commitments( + streams: Vec>>, + net: &Arc>, + runtime: &mut Runtime, + expected_commitment_block_nums: &[u64], +) { + let mut wait_for = Vec::new(); + let len = expected_commitment_block_nums.len(); + streams.into_iter().for_each(|stream| { + let mut expected = expected_commitment_block_nums.iter(); + wait_for.push(Box::pin(stream.take(len).for_each(move |signed_commitment| { + let expected = expected.next(); + async move { + let commitment_block_num = signed_commitment.commitment.block_number; + assert_eq!(expected, Some(commitment_block_num).as_ref()); + // TODO: also verify commitment payload, validator set id, and signatures. + } + }))); + }); + let wait_for = futures::future::join_all(wait_for); + block_until(wait_for, net, runtime); +} + +fn streams_empty_after_timeout( + streams: Vec>, + net: &Arc>, + runtime: &mut Runtime, + timeout: Option, +) where + T: std::fmt::Debug, + T: std::cmp::PartialEq, +{ + if let Some(timeout) = timeout { + run_for(timeout, net, runtime); + } + streams.into_iter().for_each(|mut stream| { + runtime.block_on(future::poll_fn(move |cx| { + assert_eq!(stream.poll_next_unpin(cx), Poll::Pending); + Poll::Ready(()) + })); + }); +} + +fn finalize_block_and_wait_for_beefy( + net: &Arc>, + peers: &[BeefyKeyring], + runtime: &mut Runtime, + finalize_targets: &[u64], + expected_beefy: &[u64], +) { + let (best_blocks, signed_commitments) = get_beefy_streams(&mut *net.lock(), peers); + + for block in finalize_targets { + let finalize = BlockId::number(*block); + for i in 0..peers.len() { + net.lock().peer(i).client().as_client().finalize_block(finalize, None).unwrap(); + } + } + + if expected_beefy.is_empty() { + // run for 1 second then verify no new best beefy block available + let timeout = Some(Duration::from_millis(500)); + streams_empty_after_timeout(best_blocks, &net, runtime, timeout); + streams_empty_after_timeout(signed_commitments, &net, runtime, None); + } else { + // run until expected beefy blocks are received + wait_for_best_beefy_blocks(best_blocks, &net, runtime, expected_beefy); + wait_for_beefy_signed_commitments(signed_commitments, &net, runtime, expected_beefy); + } +} + +#[test] +fn beefy_finalizing_blocks() { + sp_tracing::try_init_simple(); + + let mut runtime = Runtime::new().unwrap(); + let peers = &[BeefyKeyring::Alice, BeefyKeyring::Bob]; + let validator_set = ValidatorSet::new(make_beefy_ids(peers), 0).unwrap(); + let session_len = 10; + let min_block_delta = 4; + + let mut net = BeefyTestNet::new(2, 0); + + for i in 0..peers.len() { + net.peer(i).data.use_validator_set(&validator_set); + } + runtime.spawn(initialize_beefy(&mut net, peers, min_block_delta)); + + // push 42 blocks including `AuthorityChange` digests every 10 blocks. + net.generate_blocks(42, session_len, &validator_set); + net.block_until_sync(); + + let net = Arc::new(Mutex::new(net)); + + // Minimum BEEFY block delta is 4. + + // finalize block #5 -> BEEFY should finalize #1 (mandatory) and #5 from diff-power-of-two rule. + finalize_block_and_wait_for_beefy(&net, peers, &mut runtime, &[5], &[1, 5]); + + // GRANDPA finalize #10 -> BEEFY finalize #10 (mandatory) + finalize_block_and_wait_for_beefy(&net, peers, &mut runtime, &[10], &[10]); + + // GRANDPA finalize #18 -> BEEFY finalize #14, then #18 (diff-power-of-two rule) + finalize_block_and_wait_for_beefy(&net, peers, &mut runtime, &[18], &[14, 18]); + + // GRANDPA finalize #20 -> BEEFY finalize #20 (mandatory) + finalize_block_and_wait_for_beefy(&net, peers, &mut runtime, &[20], &[20]); + + // GRANDPA finalize #21 -> BEEFY finalize nothing (yet) because min delta is 4 + finalize_block_and_wait_for_beefy(&net, peers, &mut runtime, &[21], &[]); +} + +#[test] +fn lagging_validators() { + sp_tracing::try_init_simple(); + + let mut runtime = Runtime::new().unwrap(); + let peers = &[BeefyKeyring::Charlie, BeefyKeyring::Dave]; + let validator_set = ValidatorSet::new(make_beefy_ids(peers), 0).unwrap(); + let session_len = 30; + let min_block_delta = 1; + + let mut net = BeefyTestNet::new(2, 0); + for i in 0..peers.len() { + net.peer(i).data.use_validator_set(&validator_set); + } + runtime.spawn(initialize_beefy(&mut net, peers, min_block_delta)); + + // push 42 blocks including `AuthorityChange` digests every 30 blocks. + net.generate_blocks(42, session_len, &validator_set); + net.block_until_sync(); + + let net = Arc::new(Mutex::new(net)); + + // finalize block #15 -> BEEFY should finalize #1 (mandatory) and #9, #13, #14, #15 from + // diff-power-of-two rule. + finalize_block_and_wait_for_beefy(&net, peers, &mut runtime, &[15], &[1, 9, 13, 14, 15]); + + // Charlie finalizes #25, Dave lags behind + let finalize = BlockId::number(25); + let (best_blocks, signed_commitments) = get_beefy_streams(&mut *net.lock(), peers); + net.lock().peer(0).client().as_client().finalize_block(finalize, None).unwrap(); + // verify nothing gets finalized by BEEFY + let timeout = Some(Duration::from_millis(500)); + streams_empty_after_timeout(best_blocks, &net, &mut runtime, timeout); + streams_empty_after_timeout(signed_commitments, &net, &mut runtime, None); + + // Dave catches up and also finalizes #25 + let (best_blocks, signed_commitments) = get_beefy_streams(&mut *net.lock(), peers); + net.lock().peer(1).client().as_client().finalize_block(finalize, None).unwrap(); + // expected beefy finalizes block #17 from diff-power-of-two + wait_for_best_beefy_blocks(best_blocks, &net, &mut runtime, &[23, 24, 25]); + wait_for_beefy_signed_commitments(signed_commitments, &net, &mut runtime, &[23, 24, 25]); + + // Both finalize #30 (mandatory session) and #32 -> BEEFY finalize #30 (mandatory), #31, #32 + finalize_block_and_wait_for_beefy(&net, peers, &mut runtime, &[30, 32], &[30, 31, 32]); +} + +#[test] +fn correct_beefy_payload() { + sp_tracing::try_init_simple(); + + let mut runtime = Runtime::new().unwrap(); + let peers = + &[BeefyKeyring::Alice, BeefyKeyring::Bob, BeefyKeyring::Charlie, BeefyKeyring::Dave]; + let validator_set = ValidatorSet::new(make_beefy_ids(peers), 0).unwrap(); + let session_len = 20; + let min_block_delta = 2; + + let mut net = BeefyTestNet::new(4, 0); + for i in 0..peers.len() { + net.peer(i).data.use_validator_set(&validator_set); + } + + // Dave will vote on bad mmr roots + net.peer(3).data.test_modifiers.as_mut().map(|tm| tm.corrupt_mmr_roots = true); + runtime.spawn(initialize_beefy(&mut net, peers, min_block_delta)); + + // push 10 blocks + net.generate_blocks(12, session_len, &validator_set); + net.block_until_sync(); + + let net = Arc::new(Mutex::new(net)); + // with 3 good voters and 1 bad one, consensus should happen and best blocks produced. + finalize_block_and_wait_for_beefy(&net, peers, &mut runtime, &[10], &[1, 9]); + + let (best_blocks, signed_commitments) = + get_beefy_streams(&mut *net.lock(), &[BeefyKeyring::Alice]); + + // now 2 good validators and 1 bad one are voting + net.lock() + .peer(0) + .client() + .as_client() + .finalize_block(BlockId::number(11), None) + .unwrap(); + net.lock() + .peer(1) + .client() + .as_client() + .finalize_block(BlockId::number(11), None) + .unwrap(); + net.lock() + .peer(3) + .client() + .as_client() + .finalize_block(BlockId::number(11), None) + .unwrap(); + + // verify consensus is _not_ reached + let timeout = Some(Duration::from_millis(500)); + streams_empty_after_timeout(best_blocks, &net, &mut runtime, timeout); + streams_empty_after_timeout(signed_commitments, &net, &mut runtime, None); + + // 3rd good validator catches up and votes as well + let (best_blocks, signed_commitments) = + get_beefy_streams(&mut *net.lock(), &[BeefyKeyring::Alice]); + net.lock() + .peer(2) + .client() + .as_client() + .finalize_block(BlockId::number(11), None) + .unwrap(); + + // verify consensus is reached + wait_for_best_beefy_blocks(best_blocks, &net, &mut runtime, &[11]); + wait_for_beefy_signed_commitments(signed_commitments, &net, &mut runtime, &[11]); +} diff --git a/client/beefy/src/worker.rs b/client/beefy/src/worker.rs index 3f23638758ec..85674c09a278 100644 --- a/client/beefy/src/worker.rs +++ b/client/beefy/src/worker.rs @@ -16,7 +16,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::{collections::BTreeSet, fmt::Debug, marker::PhantomData, sync::Arc}; +use std::{collections::BTreeSet, fmt::Debug, marker::PhantomData, sync::Arc, time::Duration}; use codec::{Codec, Decode, Encode}; use futures::{future, FutureExt, StreamExt}; @@ -28,6 +28,7 @@ use sc_network_gossip::GossipEngine; use sp_api::BlockId; use sp_arithmetic::traits::AtLeast32Bit; +use sp_consensus::SyncOracle; use sp_runtime::{ generic::OpaqueDigestItemId, traits::{Block, Header, NumberFor}, @@ -35,7 +36,7 @@ use sp_runtime::{ }; use beefy_primitives::{ - crypto::{AuthorityId, Public, Signature}, + crypto::{AuthorityId, Signature}, known_payload_ids, BeefyApi, Commitment, ConsensusLog, MmrRootHash, Payload, SignedCommitment, ValidatorSet, VersionedFinalityProof, VoteMessage, BEEFY_ENGINE_ID, GENESIS_AUTHORITY_SET_ID, }; @@ -47,10 +48,11 @@ use crate::{ metric_inc, metric_set, metrics::Metrics, notification::{BeefyBestBlockSender, BeefySignedCommitmentSender}, - round, Client, + round::Rounds, + Client, }; -pub(crate) struct WorkerParams +pub(crate) struct WorkerParams where B: Block, { @@ -63,14 +65,16 @@ where pub gossip_validator: Arc>, pub min_block_delta: u32, pub metrics: Option, + pub sync_oracle: SO, } /// A BEEFY worker plays the BEEFY protocol -pub(crate) struct BeefyWorker +pub(crate) struct BeefyWorker where B: Block, BE: Backend, C: Client, + SO: SyncOracle + Send + Sync + Clone + 'static, { client: Arc, backend: Arc, @@ -81,26 +85,32 @@ where /// Min delta in block numbers between two blocks, BEEFY should vote on min_block_delta: u32, metrics: Option, - rounds: Option>>, + rounds: Option>, finality_notifications: FinalityNotifications, /// Best block we received a GRANDPA notification for - best_grandpa_block: NumberFor, + best_grandpa_block_header: ::Header, /// Best block a BEEFY voting round has been concluded for best_beefy_block: Option>, /// Used to keep RPC worker up to date on latest/best beefy beefy_best_block_sender: BeefyBestBlockSender, /// Validator set id for the last signed commitment last_signed_id: u64, + /// Handle to the sync oracle + sync_oracle: SO, // keep rustc happy _backend: PhantomData, + #[cfg(test)] + // behavior modifiers used in tests + test_res: tests::TestModifiers, } -impl BeefyWorker +impl BeefyWorker where B: Block + Codec, BE: Backend, C: Client, C::Api: BeefyApi, + SO: SyncOracle + Send + Sync + Clone + 'static, { /// Return a new BEEFY worker instance. /// @@ -108,7 +118,12 @@ where /// BEEFY pallet has been deployed on-chain. /// /// The BEEFY pallet is needed in order to keep track of the BEEFY authority set. - pub(crate) fn new(worker_params: WorkerParams) -> Self { + pub(crate) fn new( + worker_params: WorkerParams, + #[cfg(test)] + // behavior modifiers used in tests + test_res: tests::TestModifiers, + ) -> Self { let WorkerParams { client, backend, @@ -119,8 +134,13 @@ where gossip_validator, min_block_delta, metrics, + sync_oracle, } = worker_params; + let last_finalized_header = client + .expect_header(BlockId::number(client.info().finalized_number)) + .expect("latest block always has header available; qed."); + BeefyWorker { client: client.clone(), backend, @@ -128,200 +148,176 @@ where signed_commitment_sender, gossip_engine: Arc::new(Mutex::new(gossip_engine)), gossip_validator, - min_block_delta, + // always target at least one block better than current best beefy + min_block_delta: min_block_delta.max(1), metrics, rounds: None, finality_notifications: client.finality_notification_stream(), - best_grandpa_block: client.info().finalized_number, + best_grandpa_block_header: last_finalized_header, best_beefy_block: None, last_signed_id: 0, beefy_best_block_sender, + sync_oracle, _backend: PhantomData, + #[cfg(test)] + test_res, } } } -impl BeefyWorker +impl BeefyWorker where B: Block, BE: Backend, C: Client, C::Api: BeefyApi, + SO: SyncOracle + Send + Sync + Clone + 'static, { - /// Return `true`, if we should vote on block `number` - fn should_vote_on(&self, number: NumberFor) -> bool { - let best_beefy_block = if let Some(block) = self.best_beefy_block { - block - } else { - debug!(target: "beefy", "🥩 Missing best BEEFY block - won't vote for: {:?}", number); - return false - }; - - let target = vote_target(self.best_grandpa_block, best_beefy_block, self.min_block_delta); - - trace!(target: "beefy", "🥩 should_vote_on: #{:?}, next_block_to_vote_on: #{:?}", number, target); - - metric_set!(self, beefy_should_vote_on, target); - - number == target - } - - /// Return the current active validator set at header `header`. - /// - /// Note that the validator set could be `None`. This is the case if we don't find - /// a BEEFY authority set change and we can't fetch the authority set from the - /// BEEFY on-chain state. - /// - /// Such a failure is usually an indication that the BEEFY pallet has not been deployed (yet). - fn validator_set(&self, header: &B::Header) -> Option> { - let new = if let Some(new) = find_authorities_change::(header) { - Some(new) + /// Return `Some(number)` if we should be voting on block `number` now, + /// return `None` if there is no block we should vote on now. + fn current_vote_target(&self) -> Option> { + let rounds = if let Some(r) = &self.rounds { + r } else { - let at = BlockId::hash(header.hash()); - self.client.runtime_api().validator_set(&at).ok().flatten() + debug!(target: "beefy", "🥩 No voting round started"); + return None }; - trace!(target: "beefy", "🥩 active validator set: {:?}", new); - - new + let best_finalized = *self.best_grandpa_block_header.number(); + // `target` is guaranteed > `best_beefy` since `min_block_delta` is at least `1`. + let target = vote_target( + best_finalized, + self.best_beefy_block, + *rounds.session_start(), + self.min_block_delta, + ); + trace!( + target: "beefy", + "🥩 best beefy: #{:?}, best finalized: #{:?}, current_vote_target: {:?}", + self.best_beefy_block, + best_finalized, + target + ); + if let Some(target) = &target { + metric_set!(self, beefy_should_vote_on, target); + } + target } /// Verify `active` validator set for `block` against the key store /// - /// The critical case is, if we do have a public key in the key store which is not - /// part of the active validator set. + /// We want to make sure that we have _at least one_ key in our keystore that + /// is part of the validator set, that's because if there are no local keys + /// then we can't perform our job as a validator. /// /// Note that for a non-authority node there will be no keystore, and we will /// return an error and don't check. The error can usually be ignored. fn verify_validator_set( &self, block: &NumberFor, - active: &ValidatorSet, + active: &ValidatorSet, ) -> Result<(), error::Error> { - let active: BTreeSet<&Public> = active.validators().iter().collect(); + let active: BTreeSet<&AuthorityId> = active.validators().iter().collect(); let public_keys = self.key_store.public_keys()?; - let store: BTreeSet<&Public> = public_keys.iter().collect(); + let store: BTreeSet<&AuthorityId> = public_keys.iter().collect(); - let missing: Vec<_> = store.difference(&active).cloned().collect(); - - if !missing.is_empty() { - debug!(target: "beefy", "🥩 for block {:?} public key missing in validator set: {:?}", block, missing); + if store.intersection(&active).count() == 0 { + let msg = "no authority public key found in store".to_string(); + debug!(target: "beefy", "🥩 for block {:?} {}", block, msg); + Err(error::Error::Keystore(msg)) + } else { + Ok(()) } - - Ok(()) } - fn handle_finality_notification(&mut self, notification: FinalityNotification) { - trace!(target: "beefy", "🥩 Finality notification: {:?}", notification); - - // update best GRANDPA finalized block we have seen - self.best_grandpa_block = *notification.header.number(); - - if let Some(active) = self.validator_set(¬ification.header) { - // Authority set change or genesis set id triggers new voting rounds - // - // TODO: (grandpa-bridge-gadget#366) Enacting a new authority set will also - // implicitly 'conclude' the currently active BEEFY voting round by starting a - // new one. This should be replaced by proper round life-cycle handling. - if self.rounds.is_none() || - active.id() != self.rounds.as_ref().unwrap().validator_set_id() || - (active.id() == GENESIS_AUTHORITY_SET_ID && self.best_beefy_block.is_none()) - { - debug!(target: "beefy", "🥩 New active validator set id: {:?}", active); - metric_set!(self, beefy_validator_set_id, active.id()); - - // BEEFY should produce a signed commitment for each session - if active.id() != self.last_signed_id + 1 && active.id() != GENESIS_AUTHORITY_SET_ID - { - metric_inc!(self, beefy_skipped_sessions); - } - - if log_enabled!(target: "beefy", log::Level::Debug) { - // verify the new validator set - only do it if we're also logging the warning - let _ = self.verify_validator_set(notification.header.number(), &active); - } - - let id = active.id(); - self.rounds = Some(round::Rounds::new(active)); - - debug!(target: "beefy", "🥩 New Rounds for id: {:?}", id); - - self.best_beefy_block = Some(*notification.header.number()); + /// Set best BEEFY block to `block_num`. + /// + /// Also sends/updates the best BEEFY block hash to the RPC worker. + fn set_best_beefy_block(&mut self, block_num: NumberFor) { + if Some(block_num) > self.best_beefy_block { + // Try to get block hash ourselves. + let block_hash = match self.client.hash(block_num) { + Ok(h) => h, + Err(e) => { + error!(target: "beefy", "🥩 Failed to get hash for block number {}: {}", + block_num, e); + None + }, + }; + // Update RPC worker with new best BEEFY block hash. + block_hash.map(|hash| { self.beefy_best_block_sender - .notify(|| Ok::<_, ()>(notification.hash.clone())) - .expect("forwards closure result; the closure always returns Ok; qed."); - - // this metric is kind of 'fake'. Best BEEFY block should only be updated once we - // have a signed commitment for the block. Remove once the above TODO is done. - metric_set!(self, beefy_best_block, *notification.header.number()); - } + .notify(|| Ok::<_, ()>(hash)) + .expect("forwards closure result; the closure always returns Ok; qed.") + }); + // Set new best BEEFY block number. + self.best_beefy_block = Some(block_num); + metric_set!(self, beefy_best_block, block_num); + } else { + debug!(target: "beefy", "🥩 Can't set best beefy to older: {}", block_num); } + } - if self.should_vote_on(*notification.header.number()) { - let (validators, validator_set_id) = if let Some(rounds) = &self.rounds { - (rounds.validators(), rounds.validator_set_id()) - } else { - debug!(target: "beefy", "🥩 Missing validator set - can't vote for: {:?}", notification.header.hash()); - return - }; - let authority_id = if let Some(id) = self.key_store.authority_id(validators) { - debug!(target: "beefy", "🥩 Local authority id: {:?}", id); - id - } else { - debug!(target: "beefy", "🥩 Missing validator id - can't vote for: {:?}", notification.header.hash()); - return - }; - - let mmr_root = - if let Some(hash) = find_mmr_root_digest::(¬ification.header) { - hash - } else { - warn!(target: "beefy", "🥩 No MMR root digest found for: {:?}", notification.header.hash()); - return - }; - - let payload = Payload::new(known_payload_ids::MMR_ROOT_ID, mmr_root.encode()); - let commitment = Commitment { - payload, - block_number: notification.header.number(), - validator_set_id, - }; - let encoded_commitment = commitment.encode(); + /// Handle session changes by starting new voting round for mandatory blocks. + fn init_session_at(&mut self, active: ValidatorSet, session_start: NumberFor) { + debug!(target: "beefy", "🥩 New active validator set: {:?}", active); + metric_set!(self, beefy_validator_set_id, active.id()); + // BEEFY should produce a signed commitment for each session + if active.id() != self.last_signed_id + 1 && active.id() != GENESIS_AUTHORITY_SET_ID { + metric_inc!(self, beefy_skipped_sessions); + } - let signature = match self.key_store.sign(&authority_id, &*encoded_commitment) { - Ok(sig) => sig, - Err(err) => { - warn!(target: "beefy", "🥩 Error signing commitment: {:?}", err); - return - }, - }; + if log_enabled!(target: "beefy", log::Level::Debug) { + // verify the new validator set - only do it if we're also logging the warning + let _ = self.verify_validator_set(&session_start, &active); + } - trace!( - target: "beefy", - "🥩 Produced signature using {:?}, is_valid: {:?}", - authority_id, - BeefyKeystore::verify(&authority_id, &signature, &*encoded_commitment) - ); + let prev_validator_set = if let Some(r) = &self.rounds { + r.validator_set().clone() + } else { + // no previous rounds present use new validator set instead (genesis case) + active.clone() + }; + let id = active.id(); + self.rounds = Some(Rounds::new(session_start, active, prev_validator_set)); + info!(target: "beefy", "🥩 New Rounds for validator set id: {:?} with session_start {:?}", id, session_start); + } - let message = VoteMessage { commitment, id: authority_id, signature }; + fn handle_finality_notification(&mut self, notification: &FinalityNotification) { + trace!(target: "beefy", "🥩 Finality notification: {:?}", notification); + let number = *notification.header.number(); - let encoded_message = message.encode(); + // On start-up ignore old finality notifications that we're not interested in. + if number <= *self.best_grandpa_block_header.number() { + debug!(target: "beefy", "🥩 Got unexpected finality for old block #{:?}", number); + return + } - metric_inc!(self, beefy_votes_sent); + // update best GRANDPA finalized block we have seen + self.best_grandpa_block_header = notification.header.clone(); - debug!(target: "beefy", "🥩 Sent vote message: {:?}", message); + self.handle_finality(¬ification.header); + } - self.handle_vote( - (message.commitment.payload, *message.commitment.block_number), - (message.id, message.signature), - ); + fn handle_finality(&mut self, header: &B::Header) { + // Check for and handle potential new session. + if let Some(new_validator_set) = find_authorities_change::(header) { + self.init_session_at(new_validator_set, *header.number()); + } - self.gossip_engine.lock().gossip_message(topic::(), encoded_message, false); + // Vote if there's now a new vote target. + if let Some(target_number) = self.current_vote_target() { + self.do_vote(target_number); } } - fn handle_vote(&mut self, round: (Payload, NumberFor), vote: (Public, Signature)) { + fn handle_vote( + &mut self, + round: (Payload, NumberFor), + vote: (AuthorityId, Signature), + self_vote: bool, + ) { self.gossip_validator.note_round(round.1); let rounds = if let Some(rounds) = self.rounds.as_mut() { @@ -331,12 +327,12 @@ where return }; - let vote_added = rounds.add_vote(&round, vote); + if rounds.add_vote(&round, vote, self_vote) { + if let Some(signatures) = rounds.try_conclude(&round) { + self.gossip_validator.conclude_round(round.1); - if vote_added && rounds.is_done(&round) { - if let Some(signatures) = rounds.drop(&round) { // id is stored for skipped session metric calculation - self.last_signed_id = rounds.validator_set_id(); + self.last_signed_id = rounds.validator_set_id_for(round.1); let block_num = round.1; let commitment = Commitment { @@ -351,48 +347,167 @@ where info!(target: "beefy", "🥩 Round #{} concluded, committed: {:?}.", round.1, signed_commitment); - if self - .backend - .append_justification( - BlockId::Number(block_num), - ( - BEEFY_ENGINE_ID, - VersionedFinalityProof::V1(signed_commitment.clone()).encode(), - ), - ) - .is_err() - { - // just a trace, because until the round lifecycle is improved, we will - // conclude certain rounds multiple times. - trace!(target: "beefy", "🥩 Failed to append justification: {:?}", signed_commitment); + if let Err(e) = self.backend.append_justification( + BlockId::Number(block_num), + ( + BEEFY_ENGINE_ID, + VersionedFinalityProof::V1(signed_commitment.clone()).encode(), + ), + ) { + trace!(target: "beefy", "🥩 Error {:?} on appending justification: {:?}", e, signed_commitment); } self.signed_commitment_sender .notify(|| Ok::<_, ()>(signed_commitment)) .expect("forwards closure result; the closure always returns Ok; qed."); - self.best_beefy_block = Some(block_num); - if let Err(err) = self.client.hash(block_num).map(|h| { - if let Some(hash) = h { - self.beefy_best_block_sender - .notify(|| Ok::<_, ()>(hash)) - .expect("forwards closure result; the closure always returns Ok; qed."); - } - }) { - error!(target: "beefy", "🥩 Failed to get hash for block number {}: {}", - block_num, err); - } + self.set_best_beefy_block(block_num); - metric_set!(self, beefy_best_block, block_num); + // Vote if there's now a new vote target. + if let Some(target_number) = self.current_vote_target() { + self.do_vote(target_number); + } } } } + /// Create and gossip Signed Commitment for block number `target_number`. + /// + /// Also handle this self vote by calling `self.handle_vote()` for it. + fn do_vote(&mut self, target_number: NumberFor) { + trace!(target: "beefy", "🥩 Try voting on {}", target_number); + + // Most of the time we get here, `target` is actually `best_grandpa`, + // avoid asking `client` for header in that case. + let target_header = if target_number == *self.best_grandpa_block_header.number() { + self.best_grandpa_block_header.clone() + } else { + match self.client.expect_header(BlockId::Number(target_number)) { + Ok(h) => h, + Err(err) => { + debug!( + target: "beefy", + "🥩 Could not get header for block #{:?} (error: {:?}), skipping vote..", + target_number, + err + ); + return + }, + } + }; + let target_hash = target_header.hash(); + + let mmr_root = if let Some(hash) = self.extract_mmr_root_digest(&target_header) { + hash + } else { + warn!(target: "beefy", "🥩 No MMR root digest found for: {:?}", target_hash); + return + }; + let payload = Payload::new(known_payload_ids::MMR_ROOT_ID, mmr_root.encode()); + + let (validators, validator_set_id) = if let Some(rounds) = &self.rounds { + if !rounds.should_self_vote(&(payload.clone(), target_number)) { + debug!(target: "beefy", "🥩 Don't double vote for block number: {:?}", target_number); + return + } + (rounds.validators_for(target_number), rounds.validator_set_id_for(target_number)) + } else { + debug!(target: "beefy", "🥩 Missing validator set - can't vote for: {:?}", target_hash); + return + }; + let authority_id = if let Some(id) = self.key_store.authority_id(validators) { + debug!(target: "beefy", "🥩 Local authority id: {:?}", id); + id + } else { + debug!(target: "beefy", "🥩 Missing validator id - can't vote for: {:?}", target_hash); + return + }; + + let commitment = Commitment { payload, block_number: target_number, validator_set_id }; + let encoded_commitment = commitment.encode(); + + let signature = match self.key_store.sign(&authority_id, &*encoded_commitment) { + Ok(sig) => sig, + Err(err) => { + warn!(target: "beefy", "🥩 Error signing commitment: {:?}", err); + return + }, + }; + + trace!( + target: "beefy", + "🥩 Produced signature using {:?}, is_valid: {:?}", + authority_id, + BeefyKeystore::verify(&authority_id, &signature, &*encoded_commitment) + ); + + let message = VoteMessage { commitment, id: authority_id, signature }; + + let encoded_message = message.encode(); + + metric_inc!(self, beefy_votes_sent); + + debug!(target: "beefy", "🥩 Sent vote message: {:?}", message); + + self.handle_vote( + (message.commitment.payload, message.commitment.block_number), + (message.id, message.signature), + true, + ); + + self.gossip_engine.lock().gossip_message(topic::(), encoded_message, false); + } + + /// Wait for BEEFY runtime pallet to be available. + #[cfg(not(test))] + async fn wait_for_runtime_pallet(&mut self) { + self.client + .finality_notification_stream() + .take_while(|notif| { + let at = BlockId::hash(notif.header.hash()); + if let Some(active) = self.client.runtime_api().validator_set(&at).ok().flatten() { + if active.id() == GENESIS_AUTHORITY_SET_ID { + // When starting from genesis, there is no session boundary digest. + // Just initialize `rounds` to Block #1 as BEEFY mandatory block. + self.init_session_at(active, 1u32.into()); + } + // In all other cases, we just go without `rounds` initialized, meaning the + // worker won't vote until it witnesses a session change. + // Once we'll implement 'initial sync' (catch-up), the worker will be able to + // start voting right away. + self.handle_finality_notification(notif); + future::ready(false) + } else { + trace!(target: "beefy", "🥩 Finality notification: {:?}", notif); + trace!(target: "beefy", "🥩 Waiting for BEEFY pallet to become available..."); + future::ready(true) + } + }) + .for_each(|_| future::ready(())) + .await; + // get a new stream that provides _new_ notifications (from here on out) + self.finality_notifications = self.client.finality_notification_stream(); + } + + /// For tests don't use runtime pallet. Start rounds from block #1. + #[cfg(test)] + async fn wait_for_runtime_pallet(&mut self) { + let active = self.test_res.active_validators.clone(); + self.init_session_at(active, 1u32.into()); + } + + /// Main loop for BEEFY worker. + /// + /// Wait for BEEFY runtime pallet to be available, then start the main async loop + /// which is driven by finality notifications and gossiped votes. pub(crate) async fn run(mut self) { + info!(target: "beefy", "🥩 run BEEFY worker, best grandpa: #{:?}.", self.best_grandpa_block_header.number()); + self.wait_for_runtime_pallet().await; + let mut votes = Box::pin(self.gossip_engine.lock().messages_for(topic::()).filter_map( |notification| async move { debug!(target: "beefy", "🥩 Got vote message: {:?}", notification); - VoteMessage::, Public, Signature>::decode( + VoteMessage::, AuthorityId, Signature>::decode( &mut ¬ification.message[..], ) .ok() @@ -400,13 +515,18 @@ where )); loop { + while self.sync_oracle.is_major_syncing() { + debug!(target: "beefy", "Waiting for major sync to complete..."); + futures_timer::Delay::new(Duration::from_secs(5)).await; + } + let engine = self.gossip_engine.clone(); let gossip_engine = future::poll_fn(|cx| engine.lock().poll_unpin(cx)); futures::select! { notification = self.finality_notifications.next().fuse() => { if let Some(notification) = notification { - self.handle_finality_notification(notification); + self.handle_finality_notification(¬ification); } else { return; } @@ -416,6 +536,7 @@ where self.handle_vote( (vote.commitment.payload, vote.commitment.block_number), (vote.id, vote.signature), + false ); } else { return; @@ -428,20 +549,36 @@ where } } } + + /// Simple wrapper over mmr root extraction. + #[cfg(not(test))] + fn extract_mmr_root_digest(&self, header: &B::Header) -> Option { + find_mmr_root_digest::(header) + } + + /// For tests, have the option to modify mmr root. + #[cfg(test)] + fn extract_mmr_root_digest(&self, header: &B::Header) -> Option { + let mut mmr_root = find_mmr_root_digest::(header); + if self.test_res.corrupt_mmr_roots { + mmr_root.as_mut().map(|hash| *hash ^= MmrRootHash::random()); + } + mmr_root + } } /// Extract the MMR root hash from a digest in the given header, if it exists. -fn find_mmr_root_digest(header: &B::Header) -> Option +fn find_mmr_root_digest(header: &B::Header) -> Option where B: Block, - Id: Codec, { - header.digest().logs().iter().find_map(|log| { - match log.try_to::>(OpaqueDigestItemId::Consensus(&BEEFY_ENGINE_ID)) { - Some(ConsensusLog::MmrRoot(root)) => Some(root), - _ => None, - } - }) + let id = OpaqueDigestItemId::Consensus(&BEEFY_ENGINE_ID); + + let filter = |log: ConsensusLog| match log { + ConsensusLog::MmrRoot(root) => Some(root), + _ => None, + }; + header.digest().convert_first(|l| l.try_to(id).and_then(filter)) } /// Scan the `header` digest log for a BEEFY validator set change. Return either the new @@ -456,119 +593,402 @@ where ConsensusLog::AuthoritiesChange(validator_set) => Some(validator_set), _ => None, }; - header.digest().convert_first(|l| l.try_to(id).and_then(filter)) } -/// Calculate next block number to vote on -fn vote_target(best_grandpa: N, best_beefy: N, min_delta: u32) -> N +/// Calculate next block number to vote on. +/// +/// Return `None` if there is no voteable target yet. +fn vote_target( + best_grandpa: N, + best_beefy: Option, + session_start: N, + min_delta: u32, +) -> Option where N: AtLeast32Bit + Copy + Debug, { - let diff = best_grandpa.saturating_sub(best_beefy); - let diff = diff.saturated_into::(); - let target = best_beefy + min_delta.max(diff.next_power_of_two()).into(); - - trace!( - target: "beefy", - "🥩 vote target - diff: {:?}, next_power_of_two: {:?}, target block: #{:?}", - diff, - diff.next_power_of_two(), - target, - ); - - target + // if the mandatory block (session_start) does not have a beefy justification yet, + // we vote on it + let target = match best_beefy { + None => { + trace!( + target: "beefy", + "🥩 vote target - mandatory block: #{:?}", + session_start, + ); + session_start + }, + Some(bbb) if bbb < session_start => { + trace!( + target: "beefy", + "🥩 vote target - mandatory block: #{:?}", + session_start, + ); + session_start + }, + Some(bbb) => { + let diff = best_grandpa.saturating_sub(bbb) + 1u32.into(); + let diff = diff.saturated_into::() / 2; + let target = bbb + min_delta.max(diff.next_power_of_two()).into(); + + trace!( + target: "beefy", + "🥩 vote target - diff: {:?}, next_power_of_two: {:?}, target block: #{:?}", + diff, + diff.next_power_of_two(), + target, + ); + + target + }, + }; + + // Don't vote for targets until they've been finalized + // (`target` can be > `best_grandpa` when `min_delta` is big enough). + if target > best_grandpa { + None + } else { + Some(target) + } } #[cfg(test)] -mod tests { - use super::vote_target; +pub(crate) mod tests { + use super::*; + use crate::{ + keystore::tests::Keyring, + tests::{create_beefy_worker, get_beefy_streams, make_beefy_ids, BeefyTestNet}, + }; + + use futures::{executor::block_on, future::poll_fn, task::Poll}; + + use sc_client_api::HeaderBackend; + use sc_network::NetworkService; + use sc_network_test::{PeersFullClient, TestNetFactory}; + use sp_api::HeaderT; + use substrate_test_runtime_client::{ + runtime::{Block, Digest, DigestItem, Header, H256}, + Backend, + }; + + #[derive(Clone)] + pub struct TestModifiers { + pub active_validators: ValidatorSet, + pub corrupt_mmr_roots: bool, + } #[test] fn vote_on_min_block_delta() { - let t = vote_target(1u32, 0, 4); - assert_eq!(4, t); - let t = vote_target(2u32, 0, 4); - assert_eq!(4, t); - let t = vote_target(3u32, 0, 4); - assert_eq!(4, t); - let t = vote_target(4u32, 0, 4); - assert_eq!(4, t); - - let t = vote_target(4u32, 4, 4); - assert_eq!(8, t); - - let t = vote_target(10u32, 10, 4); - assert_eq!(14, t); - let t = vote_target(11u32, 10, 4); - assert_eq!(14, t); - let t = vote_target(12u32, 10, 4); - assert_eq!(14, t); - let t = vote_target(13u32, 10, 4); - assert_eq!(14, t); - - let t = vote_target(10u32, 10, 8); - assert_eq!(18, t); - let t = vote_target(11u32, 10, 8); - assert_eq!(18, t); - let t = vote_target(12u32, 10, 8); - assert_eq!(18, t); - let t = vote_target(13u32, 10, 8); - assert_eq!(18, t); + let t = vote_target(1u32, Some(1), 1, 4); + assert_eq!(None, t); + let t = vote_target(2u32, Some(1), 1, 4); + assert_eq!(None, t); + let t = vote_target(4u32, Some(2), 1, 4); + assert_eq!(None, t); + let t = vote_target(6u32, Some(2), 1, 4); + assert_eq!(Some(6), t); + + let t = vote_target(9u32, Some(4), 1, 4); + assert_eq!(Some(8), t); + + let t = vote_target(10u32, Some(10), 1, 8); + assert_eq!(None, t); + let t = vote_target(12u32, Some(10), 1, 8); + assert_eq!(None, t); + let t = vote_target(18u32, Some(10), 1, 8); + assert_eq!(Some(18), t); } #[test] fn vote_on_power_of_two() { - let t = vote_target(1008u32, 1000, 4); - assert_eq!(1008, t); + let t = vote_target(1008u32, Some(1000), 1, 4); + assert_eq!(Some(1004), t); - let t = vote_target(1016u32, 1000, 4); - assert_eq!(1016, t); + let t = vote_target(1016u32, Some(1000), 1, 4); + assert_eq!(Some(1008), t); - let t = vote_target(1032u32, 1000, 4); - assert_eq!(1032, t); + let t = vote_target(1032u32, Some(1000), 1, 4); + assert_eq!(Some(1016), t); - let t = vote_target(1064u32, 1000, 4); - assert_eq!(1064, t); + let t = vote_target(1064u32, Some(1000), 1, 4); + assert_eq!(Some(1032), t); - let t = vote_target(1128u32, 1000, 4); - assert_eq!(1128, t); + let t = vote_target(1128u32, Some(1000), 1, 4); + assert_eq!(Some(1064), t); - let t = vote_target(1256u32, 1000, 4); - assert_eq!(1256, t); + let t = vote_target(1256u32, Some(1000), 1, 4); + assert_eq!(Some(1128), t); - let t = vote_target(1512u32, 1000, 4); - assert_eq!(1512, t); + let t = vote_target(1512u32, Some(1000), 1, 4); + assert_eq!(Some(1256), t); - let t = vote_target(1024u32, 0, 4); - assert_eq!(1024, t); + let t = vote_target(1024u32, Some(1), 1, 4); + assert_eq!(Some(513), t); } #[test] fn vote_on_target_block() { - let t = vote_target(1008u32, 1002, 4); - assert_eq!(1010, t); - let t = vote_target(1010u32, 1002, 4); - assert_eq!(1010, t); - - let t = vote_target(1016u32, 1006, 4); - assert_eq!(1022, t); - let t = vote_target(1022u32, 1006, 4); - assert_eq!(1022, t); - - let t = vote_target(1032u32, 1012, 4); - assert_eq!(1044, t); - let t = vote_target(1044u32, 1012, 4); - assert_eq!(1044, t); - - let t = vote_target(1064u32, 1014, 4); - assert_eq!(1078, t); - let t = vote_target(1078u32, 1014, 4); - assert_eq!(1078, t); - - let t = vote_target(1128u32, 1008, 4); - assert_eq!(1136, t); - let t = vote_target(1136u32, 1008, 4); - assert_eq!(1136, t); + let t = vote_target(1008u32, Some(1002), 1, 4); + assert_eq!(Some(1006), t); + let t = vote_target(1010u32, Some(1002), 1, 4); + assert_eq!(Some(1006), t); + + let t = vote_target(1016u32, Some(1006), 1, 4); + assert_eq!(Some(1014), t); + let t = vote_target(1022u32, Some(1006), 1, 4); + assert_eq!(Some(1014), t); + + let t = vote_target(1032u32, Some(1012), 1, 4); + assert_eq!(Some(1028), t); + let t = vote_target(1044u32, Some(1012), 1, 4); + assert_eq!(Some(1028), t); + + let t = vote_target(1064u32, Some(1014), 1, 4); + assert_eq!(Some(1046), t); + let t = vote_target(1078u32, Some(1014), 1, 4); + assert_eq!(Some(1046), t); + + let t = vote_target(1128u32, Some(1008), 1, 4); + assert_eq!(Some(1072), t); + let t = vote_target(1136u32, Some(1008), 1, 4); + assert_eq!(Some(1072), t); + } + + #[test] + fn vote_on_mandatory_block() { + let t = vote_target(1008u32, Some(1002), 1004, 4); + assert_eq!(Some(1004), t); + let t = vote_target(1016u32, Some(1006), 1007, 4); + assert_eq!(Some(1007), t); + let t = vote_target(1064u32, Some(1014), 1063, 4); + assert_eq!(Some(1063), t); + let t = vote_target(1320u32, Some(1012), 1234, 4); + assert_eq!(Some(1234), t); + + let t = vote_target(1128u32, Some(1008), 1008, 4); + assert_eq!(Some(1072), t); + } + + #[test] + fn extract_authorities_change_digest() { + let mut header = Header::new( + 1u32.into(), + Default::default(), + Default::default(), + Default::default(), + Digest::default(), + ); + + // verify empty digest shows nothing + assert!(find_authorities_change::(&header).is_none()); + + let peers = &[Keyring::One, Keyring::Two]; + let id = 42; + let validator_set = ValidatorSet::new(make_beefy_ids(peers), id).unwrap(); + header.digest_mut().push(DigestItem::Consensus( + BEEFY_ENGINE_ID, + ConsensusLog::::AuthoritiesChange(validator_set.clone()).encode(), + )); + + // verify validator set is correctly extracted from digest + let extracted = find_authorities_change::(&header); + assert_eq!(extracted, Some(validator_set)); + } + + #[test] + fn extract_mmr_root_digest() { + let mut header = Header::new( + 1u32.into(), + Default::default(), + Default::default(), + Default::default(), + Digest::default(), + ); + + // verify empty digest shows nothing + assert!(find_mmr_root_digest::(&header).is_none()); + + let mmr_root_hash = H256::random(); + header.digest_mut().push(DigestItem::Consensus( + BEEFY_ENGINE_ID, + ConsensusLog::::MmrRoot(mmr_root_hash.clone()).encode(), + )); + + // verify validator set is correctly extracted from digest + let extracted = find_mmr_root_digest::(&header); + assert_eq!(extracted, Some(mmr_root_hash)); + } + + #[test] + fn should_vote_target() { + let keys = &[Keyring::Alice]; + let validator_set = ValidatorSet::new(make_beefy_ids(keys), 0).unwrap(); + let mut net = BeefyTestNet::new(1, 0); + net.peer(0).data.use_validator_set(&validator_set); + let mut worker = create_beefy_worker(&net.peer(0), &keys[0], 1); + + // rounds not initialized -> should vote: `None` + assert_eq!(worker.current_vote_target(), None); + + let set_up = |worker: &mut BeefyWorker< + Block, + PeersFullClient, + Backend, + Arc>, + >, + best_grandpa: u64, + best_beefy: Option, + session_start: u64, + min_delta: u32| { + let grandpa_header = Header::new( + best_grandpa, + Default::default(), + Default::default(), + Default::default(), + Default::default(), + ); + worker.best_grandpa_block_header = grandpa_header; + worker.best_beefy_block = best_beefy; + worker.min_block_delta = min_delta; + worker.rounds = + Some(Rounds::new(session_start, validator_set.clone(), validator_set.clone())); + }; + + // under min delta + set_up(&mut worker, 1, Some(1), 1, 4); + assert_eq!(worker.current_vote_target(), None); + set_up(&mut worker, 5, Some(2), 1, 4); + assert_eq!(worker.current_vote_target(), None); + + // vote on min delta + set_up(&mut worker, 9, Some(4), 1, 4); + assert_eq!(worker.current_vote_target(), Some(8)); + set_up(&mut worker, 18, Some(10), 1, 8); + assert_eq!(worker.current_vote_target(), Some(18)); + + // vote on power of two + set_up(&mut worker, 1008, Some(1000), 1, 1); + assert_eq!(worker.current_vote_target(), Some(1004)); + set_up(&mut worker, 1016, Some(1000), 1, 2); + assert_eq!(worker.current_vote_target(), Some(1008)); + + // nothing new to vote on + set_up(&mut worker, 1000, Some(1000), 1, 1); + assert_eq!(worker.current_vote_target(), None); + + // vote on mandatory + set_up(&mut worker, 1008, None, 1000, 8); + assert_eq!(worker.current_vote_target(), Some(1000)); + set_up(&mut worker, 1008, Some(1000), 1001, 8); + assert_eq!(worker.current_vote_target(), Some(1001)); + } + + #[test] + fn keystore_vs_validator_set() { + let keys = &[Keyring::Alice]; + let validator_set = ValidatorSet::new(make_beefy_ids(keys), 0).unwrap(); + let mut net = BeefyTestNet::new(1, 0); + net.peer(0).data.use_validator_set(&validator_set); + let mut worker = create_beefy_worker(&net.peer(0), &keys[0], 1); + + // keystore doesn't contain other keys than validators' + assert_eq!(worker.verify_validator_set(&1, &validator_set), Ok(())); + + // unknown `Bob` key + let keys = &[Keyring::Bob]; + let validator_set = ValidatorSet::new(make_beefy_ids(keys), 0).unwrap(); + let err_msg = "no authority public key found in store".to_string(); + let expected = Err(error::Error::Keystore(err_msg)); + assert_eq!(worker.verify_validator_set(&1, &validator_set), expected); + + // worker has no keystore + worker.key_store = None.into(); + let expected_err = Err(error::Error::Keystore("no Keystore".into())); + assert_eq!(worker.verify_validator_set(&1, &validator_set), expected_err); + } + + #[test] + fn setting_best_beefy_block() { + let keys = &[Keyring::Alice]; + let validator_set = ValidatorSet::new(make_beefy_ids(keys), 0).unwrap(); + let mut net = BeefyTestNet::new(1, 0); + net.peer(0).data.use_validator_set(&validator_set); + let mut worker = create_beefy_worker(&net.peer(0), &keys[0], 1); + + let (mut best_block_streams, _) = get_beefy_streams(&mut net, keys); + let mut best_block_stream = best_block_streams.drain(..).next().unwrap(); + + // no 'best beefy block' + assert_eq!(worker.best_beefy_block, None); + block_on(poll_fn(move |cx| { + assert_eq!(best_block_stream.poll_next_unpin(cx), Poll::Pending); + Poll::Ready(()) + })); + + // unknown hash for block #1 + let (mut best_block_streams, _) = get_beefy_streams(&mut net, keys); + let mut best_block_stream = best_block_streams.drain(..).next().unwrap(); + worker.set_best_beefy_block(1); + assert_eq!(worker.best_beefy_block, Some(1)); + block_on(poll_fn(move |cx| { + assert_eq!(best_block_stream.poll_next_unpin(cx), Poll::Pending); + Poll::Ready(()) + })); + + // generate 2 blocks, try again expect success + let (mut best_block_streams, _) = get_beefy_streams(&mut net, keys); + let mut best_block_stream = best_block_streams.drain(..).next().unwrap(); + net.generate_blocks(2, 10, &validator_set); + + worker.set_best_beefy_block(2); + assert_eq!(worker.best_beefy_block, Some(2)); + block_on(poll_fn(move |cx| { + match best_block_stream.poll_next_unpin(cx) { + // expect Some(hash-of-block-2) + Poll::Ready(Some(hash)) => { + let block_num = net.peer(0).client().as_client().number(hash).unwrap(); + assert_eq!(block_num, Some(2)); + }, + v => panic!("unexpected value: {:?}", v), + } + Poll::Ready(()) + })); + } + + #[test] + fn setting_initial_session() { + let keys = &[Keyring::Alice]; + let validator_set = ValidatorSet::new(make_beefy_ids(keys), 0).unwrap(); + let mut net = BeefyTestNet::new(1, 0); + net.peer(0).data.use_validator_set(&validator_set); + let mut worker = create_beefy_worker(&net.peer(0), &keys[0], 1); + + assert!(worker.rounds.is_none()); + + // verify setting the correct validator sets and boundary for genesis session + worker.init_session_at(validator_set.clone(), 1); + + let worker_rounds = worker.rounds.as_ref().unwrap(); + assert_eq!(worker_rounds.validator_set(), &validator_set); + assert_eq!(worker_rounds.session_start(), &1); + // in genesis case both current and prev validator sets are the same + assert_eq!(worker_rounds.validator_set_id_for(1), validator_set.id()); + assert_eq!(worker_rounds.validator_set_id_for(2), validator_set.id()); + + // new validator set + let keys = &[Keyring::Bob]; + let new_validator_set = ValidatorSet::new(make_beefy_ids(keys), 1).unwrap(); + + // verify setting the correct validator sets and boundary for non-genesis session + worker.init_session_at(new_validator_set.clone(), 11); + + let worker_rounds = worker.rounds.as_ref().unwrap(); + assert_eq!(worker_rounds.validator_set(), &new_validator_set); + assert_eq!(worker_rounds.session_start(), &11); + // mandatory block gets prev set, further blocks get new set + assert_eq!(worker_rounds.validator_set_id_for(11), validator_set.id()); + assert_eq!(worker_rounds.validator_set_id_for(12), new_validator_set.id()); + assert_eq!(worker_rounds.validator_set_id_for(13), new_validator_set.id()); } } diff --git a/frame/beefy/src/lib.rs b/frame/beefy/src/lib.rs index 4aa1d1337cd0..744a06561e8c 100644 --- a/frame/beefy/src/lib.rs +++ b/frame/beefy/src/lib.rs @@ -105,20 +105,20 @@ impl Pallet { } fn change_authorities(new: Vec, queued: Vec) { - // As in GRANDPA, we trigger a validator set change only if the the validator - // set has actually changed. - if new != Self::authorities() { - >::put(&new); - - let next_id = Self::validator_set_id() + 1u64; - >::put(next_id); - if let Some(validator_set) = ValidatorSet::::new(new, next_id) { - let log = DigestItem::Consensus( - BEEFY_ENGINE_ID, - ConsensusLog::AuthoritiesChange(validator_set).encode(), - ); - >::deposit_log(log); - } + // Always issue a change if `session` says that the validators have changed. + // Even if their session keys are the same as before, the underlying economic + // identities have changed. Furthermore, the digest below is used to signal + // BEEFY mandatory blocks. + >::put(&new); + + let next_id = Self::validator_set_id() + 1u64; + >::put(next_id); + if let Some(validator_set) = ValidatorSet::::new(new, next_id) { + let log = DigestItem::Consensus( + BEEFY_ENGINE_ID, + ConsensusLog::AuthoritiesChange(validator_set).encode(), + ); + >::deposit_log(log); } >::put(&queued); diff --git a/primitives/beefy/Cargo.toml b/primitives/beefy/Cargo.toml index 4aa53aff2c3c..cf901f4a34fc 100644 --- a/primitives/beefy/Cargo.toml +++ b/primitives/beefy/Cargo.toml @@ -4,8 +4,13 @@ version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2021" license = "Apache-2.0" +homepage = "https://substrate.io" repository = "https://github.com/paritytech/substrate" description = "Primitives for BEEFY protocol." +readme = "README.md" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { version = "3.0.0", package = "parity-scale-codec", default-features = false, features = ["derive"] } diff --git a/test-utils/runtime/Cargo.toml b/test-utils/runtime/Cargo.toml index 8c61cbbf8adb..ad7dca5e08fb 100644 --- a/test-utils/runtime/Cargo.toml +++ b/test-utils/runtime/Cargo.toml @@ -13,6 +13,7 @@ publish = false targets = ["x86_64-unknown-linux-gnu"] [dependencies] +beefy-primitives = { version = "4.0.0-dev", default-features = false, path = "../../primitives/beefy" } sp-application-crypto = { version = "6.0.0", default-features = false, path = "../../primitives/application-crypto" } sp-consensus-aura = { version = "0.10.0-dev", default-features = false, path = "../../primitives/consensus/aura" } sp-consensus-babe = { version = "0.10.0-dev", default-features = false, path = "../../primitives/consensus/babe" } @@ -65,6 +66,7 @@ default = [ "std", ] std = [ + "beefy-primitives/std", "sp-application-crypto/std", "sp-consensus-aura/std", "sp-consensus-babe/std", diff --git a/test-utils/runtime/src/lib.rs b/test-utils/runtime/src/lib.rs index 861d95efb308..743652a0ee89 100644 --- a/test-utils/runtime/src/lib.rs +++ b/test-utils/runtime/src/lib.rs @@ -926,6 +926,12 @@ cfg_if! { } } + impl beefy_primitives::BeefyApi for RuntimeApi { + fn validator_set() -> Option> { + None + } + } + impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { fn account_nonce(_account: AccountId) -> Index { 0 From b8aea6225c4c97ddebd5b502b17952fa45e359b2 Mon Sep 17 00:00:00 2001 From: Gavin Wood Date: Fri, 25 Mar 2022 19:38:39 +0000 Subject: [PATCH 642/695] Remove unneeded code (#11117) * Remove unneeded code * Remove unused imports Signed-off-by: Oliver Tale-Yazdi Co-authored-by: Oliver Tale-Yazdi --- frame/whitelist/src/lib.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/frame/whitelist/src/lib.rs b/frame/whitelist/src/lib.rs index c2de16964a49..239f0fd28016 100644 --- a/frame/whitelist/src/lib.rs +++ b/frame/whitelist/src/lib.rs @@ -39,7 +39,7 @@ mod mock; mod tests; pub mod weights; -use codec::{Decode, DecodeLimit, Encode, FullCodec, MaxEncodedLen}; +use codec::{DecodeLimit, Encode, FullCodec}; use frame_support::{ ensure, traits::{PreimageProvider, PreimageRecipient}, @@ -51,12 +51,6 @@ use sp_std::prelude::*; pub use pallet::*; -#[derive(Clone, Encode, Decode, TypeInfo, MaxEncodedLen)] -pub struct Preimage { - preimage: BoundedVec, - deposit: Option<(AccountId, Balance)>, -} - #[frame_support::pallet] pub mod pallet { use super::*; From 69079b58579ea36812c4a375a118f27aac0fb281 Mon Sep 17 00:00:00 2001 From: Georges Date: Fri, 25 Mar 2022 20:15:50 +0000 Subject: [PATCH 643/695] Add a bounded fallback on failed elections (#10988) * Allow `pallet-election-provider` to accept smaller solutions, issue #9478 * Fixing a typo * Adding some more tests Removing a seemingly outdated comment * making it a URL * Updating test name as per suggestion Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> * Updating documentation to be more explicit And to follow the general guidelines Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> * Fixing formatting * `Fallback` now of type `InstantElectionProvider` Some cleanups * Allow `pallet-election-provider` to accept smaller solutions, issue #9478 * Fixing a typo * Adding some more tests Removing a seemingly outdated comment * making it a URL * Updating test name as per suggestion Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> * Updating documentation to be more explicit And to follow the general guidelines Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> * Fixing formatting * `Fallback` now of type `InstantElectionProvider` Some cleanups * Merging types into one type with generics * Removing `ConstUSize` and use `ConstU32` * cleaning up the code * deprecating `OnChainSequentialPhragmen` Renaming it to `UnboundedSequentialPhragmen` which should only be used at genesis and for testing. Use preferrably `BoundedOnChainSequentialPhragmen` * Amending docs * Adding some explicit imports * Implementing generic `BoundedOnchainExecution` Removing the deprecated `OnChainSequentialPhragmen` * Use the right Balancing strategy * Refactoring `onchain::Config` Creating `onchain::ExecutionConfig` * Merge master * fmt * Name cleanups after review suggestions * cosmetics * renaming `instant_elect` to `elect_with_bounds` Other corresponding changes as per @kianenigma feedback * `BoundedOnchainExecution` -> `BoundedExecution` And `UnboundedOnchainExecution` -> `UnboundedExecution` * feedback from kian * fmt + unneeded import Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Co-authored-by: kianenigma --- bin/node/runtime/src/lib.rs | 34 ++-- frame/babe/src/mock.rs | 10 +- .../election-provider-multi-phase/src/lib.rs | 26 ++- .../election-provider-multi-phase/src/mock.rs | 30 ++- frame/election-provider-support/src/lib.rs | 20 +- .../election-provider-support/src/onchain.rs | 189 +++++++++++------- frame/grandpa/src/mock.rs | 10 +- .../merkle-mountain-range/src/mmr/storage.rs | 7 +- frame/offences/benchmarking/src/mock.rs | 10 +- frame/session/benchmarking/src/mock.rs | 10 +- frame/staking/src/mock.rs | 12 +- 11 files changed, 223 insertions(+), 135 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 47bdedbab83a..565f151ce2a0 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -23,7 +23,7 @@ #![recursion_limit = "256"] use codec::{Decode, Encode, MaxEncodedLen}; -use frame_election_provider_support::{onchain, ExtendedBalance, VoteWeight}; +use frame_election_provider_support::{onchain, ExtendedBalance, SequentialPhragmen, VoteWeight}; use frame_support::{ construct_runtime, pallet_prelude::Get, @@ -557,7 +557,7 @@ impl pallet_staking::Config for Runtime { type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator; type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type ElectionProvider = ElectionProviderMultiPhase; - type GenesisElectionProvider = onchain::OnChainSequentialPhragmen; + type GenesisElectionProvider = onchain::UnboundedExecution; type VoterList = BagsList; type MaxUnlockingChunks = ConstU32<32>; type WeightInfo = pallet_staking::weights::SubstrateWeight; @@ -642,9 +642,19 @@ impl Get> for OffchainRandomBalancing { } } -impl onchain::Config for Runtime { - type Accuracy = Perbill; - type DataProvider = ::DataProvider; +pub struct OnChainSeqPhragmen; +impl onchain::ExecutionConfig for OnChainSeqPhragmen { + type System = Runtime; + type Solver = SequentialPhragmen< + AccountId, + pallet_election_provider_multi_phase::SolutionAccuracyOf, + >; + type DataProvider = ::DataProvider; +} + +impl onchain::BoundedExecutionConfig for OnChainSeqPhragmen { + type VotersBound = ConstU32<20_000>; + type TargetsBound = ConstU32<2_000>; } impl pallet_election_provider_multi_phase::Config for Runtime { @@ -668,13 +678,9 @@ impl pallet_election_provider_multi_phase::Config for Runtime { type RewardHandler = (); // nothing to do upon rewards type DataProvider = Staking; type Solution = NposSolution16; - type Fallback = pallet_election_provider_multi_phase::NoFallback; - type GovernanceFallback = onchain::OnChainSequentialPhragmen; - type Solver = frame_election_provider_support::SequentialPhragmen< - AccountId, - SolutionAccuracyOf, - OffchainRandomBalancing, - >; + type Fallback = onchain::BoundedExecution; + type GovernanceFallback = onchain::BoundedExecution; + type Solver = SequentialPhragmen, OffchainRandomBalancing>; type ForceOrigin = EnsureRootOrHalfCouncil; type MaxElectableTargets = ConstU16<{ u16::MAX }>; type MaxElectingVoters = MaxElectingVoters; @@ -1899,6 +1905,7 @@ impl_runtime_apis! { #[cfg(test)] mod tests { use super::*; + use frame_election_provider_support::NposSolution; use frame_system::offchain::CreateSignedTransaction; use sp_runtime::UpperOf; @@ -1915,7 +1922,8 @@ mod tests { #[test] fn perbill_as_onchain_accuracy() { - type OnChainAccuracy = ::Accuracy; + type OnChainAccuracy = + <::Solution as NposSolution>::Accuracy; let maximum_chain_accuracy: Vec> = (0..MaxNominations::get()) .map(|_| >::from(OnChainAccuracy::one().deconstruct())) .collect(); diff --git a/frame/babe/src/mock.rs b/frame/babe/src/mock.rs index e74288577c9e..37d8e9e37a5f 100644 --- a/frame/babe/src/mock.rs +++ b/frame/babe/src/mock.rs @@ -19,7 +19,7 @@ use crate::{self as pallet_babe, Config, CurrentSlot}; use codec::Encode; -use frame_election_provider_support::onchain; +use frame_election_provider_support::{onchain, SequentialPhragmen}; use frame_support::{ parameter_types, traits::{ConstU128, ConstU32, ConstU64, GenesisBuild, KeyOwnerProofSystem, OnInitialize}, @@ -172,8 +172,10 @@ parameter_types! { pub const OffendingValidatorsThreshold: Perbill = Perbill::from_percent(16); } -impl onchain::Config for Test { - type Accuracy = Perbill; +pub struct OnChainSeqPhragmen; +impl onchain::ExecutionConfig for OnChainSeqPhragmen { + type System = Test; + type Solver = SequentialPhragmen; type DataProvider = Staking; } @@ -195,7 +197,7 @@ impl pallet_staking::Config for Test { type MaxNominatorRewardedPerValidator = ConstU32<64>; type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type NextNewSession = Session; - type ElectionProvider = onchain::OnChainSequentialPhragmen; + type ElectionProvider = onchain::UnboundedExecution; type GenesisElectionProvider = Self::ElectionProvider; type VoterList = pallet_staking::UseNominatorsAndValidatorsMap; type MaxUnlockingChunks = ConstU32<32>; diff --git a/frame/election-provider-multi-phase/src/lib.rs b/frame/election-provider-multi-phase/src/lib.rs index ddc06ce0aecf..e67a5cab8d64 100644 --- a/frame/election-provider-multi-phase/src/lib.rs +++ b/frame/election-provider-multi-phase/src/lib.rs @@ -242,7 +242,7 @@ use frame_support::{ use frame_system::{ensure_none, offchain::SendTransactionTypes}; use scale_info::TypeInfo; use sp_arithmetic::{ - traits::{CheckedAdd, Saturating, Zero}, + traits::{Bounded, CheckedAdd, Saturating, Zero}, UpperOf, }; use sp_npos_elections::{ @@ -323,10 +323,7 @@ impl ElectionProvider for NoFallback { } impl InstantElectionProvider for NoFallback { - fn instant_elect( - _: Option, - _: Option, - ) -> Result, Self::Error> { + fn elect_with_bounds(_: usize, _: usize) -> Result, Self::Error> { Err("NoFallback.") } } @@ -683,7 +680,7 @@ pub mod pallet { + TypeInfo; /// Configuration for the fallback. - type Fallback: ElectionProvider< + type Fallback: InstantElectionProvider< AccountId = Self::AccountId, BlockNumber = Self::BlockNumber, DataProvider = Self::DataProvider, @@ -692,7 +689,7 @@ pub mod pallet { /// Configuration of the governance-only fallback. /// /// As a side-note, it is recommend for test-nets to use `type ElectionProvider = - /// OnChainSeqPhragmen<_>` if the test-net is not expected to have thousands of nominators. + /// BoundedExecution<_>` if the test-net is not expected to have thousands of nominators. type GovernanceFallback: InstantElectionProvider< AccountId = Self::AccountId, BlockNumber = Self::BlockNumber, @@ -1040,13 +1037,14 @@ pub mod pallet { let maybe_max_voters = maybe_max_voters.map(|x| x as usize); let maybe_max_targets = maybe_max_targets.map(|x| x as usize); - let supports = - T::GovernanceFallback::instant_elect(maybe_max_voters, maybe_max_targets).map_err( - |e| { - log!(error, "GovernanceFallback failed: {:?}", e); - Error::::FallbackFailed - }, - )?; + let supports = T::GovernanceFallback::elect_with_bounds( + maybe_max_voters.unwrap_or(Bounded::max_value()), + maybe_max_targets.unwrap_or(Bounded::max_value()), + ) + .map_err(|e| { + log!(error, "GovernanceFallback failed: {:?}", e); + Error::::FallbackFailed + })?; let solution = ReadySolution { supports, diff --git a/frame/election-provider-multi-phase/src/mock.rs b/frame/election-provider-multi-phase/src/mock.rs index e2384d2f1576..1b3c4d930624 100644 --- a/frame/election-provider-multi-phase/src/mock.rs +++ b/frame/election-provider-multi-phase/src/mock.rs @@ -272,11 +272,13 @@ parameter_types! { pub static MaxElectableTargets: TargetIndex = TargetIndex::max_value(); pub static EpochLength: u64 = 30; - pub static OnChianFallback: bool = true; + pub static OnChainFallback: bool = true; } -impl onchain::Config for Runtime { - type Accuracy = sp_runtime::Perbill; +pub struct OnChainSeqPhragmen; +impl onchain::ExecutionConfig for OnChainSeqPhragmen { + type System = Runtime; + type Solver = SequentialPhragmen, Balancing>; type DataProvider = StakingMock; } @@ -288,11 +290,23 @@ impl ElectionProvider for MockFallback { type DataProvider = StakingMock; fn elect() -> Result, Self::Error> { - if OnChianFallback::get() { - onchain::OnChainSequentialPhragmen::::elect() - .map_err(|_| "OnChainSequentialPhragmen failed") + Self::elect_with_bounds(Bounded::max_value(), Bounded::max_value()) + } +} + +impl InstantElectionProvider for MockFallback { + fn elect_with_bounds( + max_voters: usize, + max_targets: usize, + ) -> Result, Self::Error> { + if OnChainFallback::get() { + onchain::UnboundedExecution::::elect_with_bounds( + max_voters, + max_targets, + ) + .map_err(|_| "UnboundedExecution failed") } else { - super::NoFallback::::elect() + super::NoFallback::::elect_with_bounds(max_voters, max_targets) } } } @@ -532,7 +546,7 @@ impl ExtBuilder { self } pub fn onchain_fallback(self, onchain: bool) -> Self { - ::set(onchain); + ::set(onchain); self } pub fn miner_weight(self, weight: Weight) -> Self { diff --git a/frame/election-provider-support/src/lib.rs b/frame/election-provider-support/src/lib.rs index 2cc27472e884..d79b5289dffe 100644 --- a/frame/election-provider-support/src/lib.rs +++ b/frame/election-provider-support/src/lib.rs @@ -168,6 +168,7 @@ pub mod onchain; pub mod traits; +#[cfg(feature = "std")] use codec::{Decode, Encode}; use frame_support::{traits::Get, BoundedVec, RuntimeDebug}; use sp_runtime::traits::Bounded; @@ -368,9 +369,10 @@ pub trait ElectionProvider { BlockNumber = Self::BlockNumber, >; - /// Elect a new set of winners. + /// Elect a new set of winners, without specifying any bounds on the amount of data fetched from + /// [`Self::DataProvider`]. An implementation could nonetheless impose its own custom limits. /// - /// The result is returned in a target major format, namely as vector of supports. + /// The result is returned in a target major format, namely as *vector of supports*. /// /// This should be implemented as a self-weighing function. The implementor should register its /// appropriate weight at the end of execution with the system pallet directly. @@ -385,11 +387,17 @@ pub trait ElectionProvider { /// Consequently, allows for control over the amount of data that is being fetched from the /// [`ElectionProvider::DataProvider`]. pub trait InstantElectionProvider: ElectionProvider { - /// Elect a new set of winners, instantly, with the given given limits set on the + /// Elect a new set of winners, but unlike [`ElectionProvider::elect`] which cannot enforce + /// bounds, this trait method can enforce bounds on the amount of data provided by the /// `DataProvider`. - fn instant_elect( - maybe_max_voters: Option, - maybe_max_targets: Option, + /// + /// An implementing type, if itself bounded, should choose the minimum of the two bounds to + /// choose the final value of `max_voters` and `max_targets`. In other words, an implementation + /// should guarantee that `max_voter` and `max_targets` provided to this method are absolutely + /// respected. + fn elect_with_bounds( + max_voters: usize, + max_targets: usize, ) -> Result, Self::Error>; } diff --git a/frame/election-provider-support/src/onchain.rs b/frame/election-provider-support/src/onchain.rs index 7d845c2dc5ab..57fd931a467d 100644 --- a/frame/election-provider-support/src/onchain.rs +++ b/frame/election-provider-support/src/onchain.rs @@ -15,9 +15,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! An implementation of [`ElectionProvider`] that does an on-chain sequential phragmen. +//! An implementation of [`ElectionProvider`] that uses an `NposSolver` to do the election. -use crate::{ElectionDataProvider, ElectionProvider, InstantElectionProvider}; +use crate::{ElectionDataProvider, ElectionProvider, InstantElectionProvider, NposSolver}; use frame_support::{traits::Get, weights::DispatchClass}; use sp_npos_elections::*; use sp_std::{collections::btree_map::BTreeMap, marker::PhantomData, prelude::*}; @@ -41,92 +41,141 @@ impl From for Error { /// /// This will accept voting data on the fly and produce the results immediately. /// -/// ### Warning -/// -/// This can be very expensive to run frequently on-chain. Use with care. Moreover, this -/// implementation ignores the additional data of the election data provider and gives no insight on -/// how much weight was consumed. -/// /// Finally, the [`ElectionProvider`] implementation of this type does not impose any limits on the /// number of voters and targets that are fetched. This could potentially make this unsuitable for -/// execution onchain. On the other hand, the [`InstantElectionProvider`] implementation does limit -/// these inputs. +/// execution onchain. One could, however, impose bounds on it by using for example +/// `BoundedExecution` which will the bounds provided in the configuration. +/// +/// On the other hand, the [`InstantElectionProvider`] implementation does limit these inputs, +/// either via using `BoundedExecution` and imposing the bounds there, or dynamically via calling +/// `elect_with_bounds` providing these bounds. If you use `elect_with_bounds` along with +/// `InstantElectionProvider`, the bound that would be used is the minimum of the 2 bounds. /// /// It is advisable to use the former ([`ElectionProvider::elect`]) only at genesis, or for testing, -/// the latter [`InstantElectionProvider::instant_elect`] for onchain operations, with thoughtful -/// bounds. -pub struct OnChainSequentialPhragmen(PhantomData); +/// the latter [`InstantElectionProvider::elect_with_bounds`] for onchain operations, with +/// thoughtful bounds. +/// +/// Please use `BoundedExecution` at all times except at genesis or for testing, with thoughtful +/// bounds in order to bound the potential execution time. Limit the use `UnboundedExecution` at +/// genesis or for testing, as it does not bound the inputs. However, this can be used with +/// `[InstantElectionProvider::elect_with_bounds`] that dynamically imposes limits. +pub struct BoundedExecution(PhantomData); -/// Configuration trait of [`OnChainSequentialPhragmen`]. +/// An unbounded variant of [`BoundedExecution`]. /// -/// Note that this is similar to a pallet traits, but [`OnChainSequentialPhragmen`] is not a pallet. +/// ### Warning /// -/// WARNING: the user of this pallet must ensure that the `Accuracy` type will work nicely with the -/// normalization operation done inside `seq_phragmen`. See -/// [`sp_npos_elections::Assignment::try_normalize`] for more info. -pub trait Config: frame_system::Config { - /// The accuracy used to compute the election: - type Accuracy: PerThing128; +/// This can be very expensive to run frequently on-chain. Use with care. Moreover, this +/// implementation ignores the additional data of the election data provider and gives no insight on +/// how much weight was consumed. +pub struct UnboundedExecution(PhantomData); + +/// Configuration trait of [`UnboundedExecution`]. +pub trait ExecutionConfig { + /// Something that implements the system pallet configs. This is to enable to register extra + /// weight. + type System: frame_system::Config; + /// `NposSolver` that should be used, an example would be `PhragMMS`. + type Solver: NposSolver< + AccountId = ::AccountId, + Error = sp_npos_elections::Error, + >; /// Something that provides the data for election. type DataProvider: ElectionDataProvider< - AccountId = Self::AccountId, - BlockNumber = Self::BlockNumber, + AccountId = ::AccountId, + BlockNumber = ::BlockNumber, >; } -impl OnChainSequentialPhragmen { - fn elect_with( - maybe_max_voters: Option, - maybe_max_targets: Option, - ) -> Result, Error> { - let voters = ::DataProvider::electing_voters(maybe_max_voters) - .map_err(Error::DataProvider)?; - let targets = - ::DataProvider::electable_targets(maybe_max_targets) - .map_err(Error::DataProvider)?; - let desired_targets = ::DataProvider::desired_targets() - .map_err(Error::DataProvider)?; - - let stake_map: BTreeMap = voters - .iter() - .map(|(validator, vote_weight, _)| (validator.clone(), *vote_weight)) - .collect(); - - let stake_of = - |w: &T::AccountId| -> VoteWeight { stake_map.get(w).cloned().unwrap_or_default() }; - - let ElectionResult::<_, T::Accuracy> { winners: _, assignments } = - seq_phragmen(desired_targets as usize, targets, voters, None).map_err(Error::from)?; - - let staked = assignment_ratio_to_staked_normalized(assignments, &stake_of)?; - - let weight = T::BlockWeights::get().max_block; - frame_system::Pallet::::register_extra_weight_unchecked( - weight, - DispatchClass::Mandatory, - ); - - Ok(to_supports(&staked)) +/// Configuration trait of [`BoundedExecution`]. +pub trait BoundedExecutionConfig: ExecutionConfig { + /// Bounds the number of voters. + type VotersBound: Get; + /// Bounds the number of targets. + type TargetsBound: Get; +} + +fn elect_with( + maybe_max_voters: Option, + maybe_max_targets: Option, +) -> Result::AccountId>, Error> { + let voters = T::DataProvider::electing_voters(maybe_max_voters).map_err(Error::DataProvider)?; + let targets = + T::DataProvider::electable_targets(maybe_max_targets).map_err(Error::DataProvider)?; + let desired_targets = T::DataProvider::desired_targets().map_err(Error::DataProvider)?; + + let stake_map: BTreeMap<_, _> = voters + .iter() + .map(|(validator, vote_weight, _)| (validator.clone(), *vote_weight)) + .collect(); + + let stake_of = |w: &::AccountId| -> VoteWeight { + stake_map.get(w).cloned().unwrap_or_default() + }; + + let ElectionResult { winners: _, assignments } = + T::Solver::solve(desired_targets as usize, targets, voters).map_err(Error::from)?; + + let staked = assignment_ratio_to_staked_normalized(assignments, &stake_of)?; + + let weight = ::BlockWeights::get().max_block; + frame_system::Pallet::::register_extra_weight_unchecked( + weight, + DispatchClass::Mandatory, + ); + + Ok(to_supports(&staked)) +} + +impl ElectionProvider for UnboundedExecution { + type AccountId = ::AccountId; + type BlockNumber = ::BlockNumber; + type Error = Error; + type DataProvider = T::DataProvider; + + fn elect() -> Result::AccountId>, Self::Error> { + // This should not be called if not in `std` mode (and therefore neither in genesis nor in + // testing) + if cfg!(not(feature = "std")) { + frame_support::log::error!( + "Please use `InstantElectionProvider` instead to provide bounds on election if not in \ + genesis or testing mode" + ); + } + + elect_with::(None, None) } } -impl ElectionProvider for OnChainSequentialPhragmen { - type AccountId = T::AccountId; - type BlockNumber = T::BlockNumber; +impl InstantElectionProvider for UnboundedExecution { + fn elect_with_bounds( + max_voters: usize, + max_targets: usize, + ) -> Result, Self::Error> { + elect_with::(Some(max_voters), Some(max_targets)) + } +} + +impl ElectionProvider for BoundedExecution { + type AccountId = ::AccountId; + type BlockNumber = ::BlockNumber; type Error = Error; type DataProvider = T::DataProvider; - fn elect() -> Result, Self::Error> { - Self::elect_with(None, None) + fn elect() -> Result::AccountId>, Self::Error> { + elect_with::(Some(T::VotersBound::get() as usize), Some(T::TargetsBound::get() as usize)) } } -impl InstantElectionProvider for OnChainSequentialPhragmen { - fn instant_elect( - maybe_max_voters: Option, - maybe_max_targets: Option, +impl InstantElectionProvider for BoundedExecution { + fn elect_with_bounds( + max_voters: usize, + max_targets: usize, ) -> Result, Self::Error> { - Self::elect_with(maybe_max_voters, maybe_max_targets) + elect_with::( + Some(max_voters.min(T::VotersBound::get() as usize)), + Some(max_targets.min(T::TargetsBound::get() as usize)), + ) } } @@ -135,7 +184,6 @@ mod tests { use super::*; use sp_npos_elections::Support; use sp_runtime::Perbill; - type AccountId = u64; type BlockNumber = u64; @@ -180,12 +228,13 @@ mod tests { type MaxConsumers = frame_support::traits::ConstU32<16>; } - impl Config for Runtime { - type Accuracy = Perbill; + impl ExecutionConfig for Runtime { + type System = Self; + type Solver = crate::SequentialPhragmen; type DataProvider = mock_data_provider::DataProvider; } - type OnChainPhragmen = OnChainSequentialPhragmen; + type OnChainPhragmen = UnboundedExecution; mod mock_data_provider { use frame_support::{bounded_vec, traits::ConstU32}; diff --git a/frame/grandpa/src/mock.rs b/frame/grandpa/src/mock.rs index 6490a2b6992b..0296cd2e28d8 100644 --- a/frame/grandpa/src/mock.rs +++ b/frame/grandpa/src/mock.rs @@ -22,7 +22,7 @@ use crate::{self as pallet_grandpa, AuthorityId, AuthorityList, Config, ConsensusLog}; use ::grandpa as finality_grandpa; use codec::Encode; -use frame_election_provider_support::onchain; +use frame_election_provider_support::{onchain, SequentialPhragmen}; use frame_support::{ parameter_types, traits::{ @@ -180,8 +180,10 @@ parameter_types! { pub const OffendingValidatorsThreshold: Perbill = Perbill::from_percent(17); } -impl onchain::Config for Test { - type Accuracy = Perbill; +pub struct OnChainSeqPhragmen; +impl onchain::ExecutionConfig for OnChainSeqPhragmen { + type System = Test; + type Solver = SequentialPhragmen<::AccountId, Perbill>; type DataProvider = Staking; } @@ -203,7 +205,7 @@ impl pallet_staking::Config for Test { type MaxNominatorRewardedPerValidator = ConstU32<64>; type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type NextNewSession = Session; - type ElectionProvider = onchain::OnChainSequentialPhragmen; + type ElectionProvider = onchain::UnboundedExecution; type GenesisElectionProvider = Self::ElectionProvider; type VoterList = pallet_staking::UseNominatorsAndValidatorsMap; type MaxUnlockingChunks = ConstU32<32>; diff --git a/frame/merkle-mountain-range/src/mmr/storage.rs b/frame/merkle-mountain-range/src/mmr/storage.rs index a48f60183d67..535057ca80da 100644 --- a/frame/merkle-mountain-range/src/mmr/storage.rs +++ b/frame/merkle-mountain-range/src/mmr/storage.rs @@ -18,7 +18,6 @@ //! A MMR storage implementations. use codec::Encode; -use frame_support::log; use mmr_lib::helper; use sp_io::offchain_index; use sp_std::iter::Peekable; @@ -93,7 +92,7 @@ where } sp_std::if_std! { - log::trace!("elems: {:?}", elems.iter().map(|elem| elem.hash()).collect::>()); + frame_support::log::trace!("elems: {:?}", elems.iter().map(|elem| elem.hash()).collect::>()); } let leaves = NumberOfLeaves::::get(); @@ -152,8 +151,8 @@ fn peaks_to_prune_and_store( let peaks_before = if old_size == 0 { vec![] } else { helper::get_peaks(old_size) }; let peaks_after = helper::get_peaks(new_size); sp_std::if_std! { - log::trace!("peaks_before: {:?}", peaks_before); - log::trace!("peaks_after: {:?}", peaks_after); + frame_support::log::trace!("peaks_before: {:?}", peaks_before); + frame_support::log::trace!("peaks_after: {:?}", peaks_after); } let mut peaks_before = peaks_before.into_iter().peekable(); let mut peaks_after = peaks_after.into_iter().peekable(); diff --git a/frame/offences/benchmarking/src/mock.rs b/frame/offences/benchmarking/src/mock.rs index 4359b7745ddd..1a4414de0b0b 100644 --- a/frame/offences/benchmarking/src/mock.rs +++ b/frame/offences/benchmarking/src/mock.rs @@ -20,7 +20,7 @@ #![cfg(test)] use super::*; -use frame_election_provider_support::onchain; +use frame_election_provider_support::{onchain, SequentialPhragmen}; use frame_support::{ parameter_types, traits::{ConstU32, ConstU64}, @@ -150,8 +150,10 @@ parameter_types! { pub type Extrinsic = sp_runtime::testing::TestXt; -impl onchain::Config for Test { - type Accuracy = Perbill; +pub struct OnChainSeqPhragmen; +impl onchain::ExecutionConfig for OnChainSeqPhragmen { + type System = Test; + type Solver = SequentialPhragmen; type DataProvider = Staking; } @@ -173,7 +175,7 @@ impl pallet_staking::Config for Test { type NextNewSession = Session; type MaxNominatorRewardedPerValidator = ConstU32<64>; type OffendingValidatorsThreshold = (); - type ElectionProvider = onchain::OnChainSequentialPhragmen; + type ElectionProvider = onchain::UnboundedExecution; type GenesisElectionProvider = Self::ElectionProvider; type VoterList = pallet_staking::UseNominatorsAndValidatorsMap; type MaxUnlockingChunks = ConstU32<32>; diff --git a/frame/session/benchmarking/src/mock.rs b/frame/session/benchmarking/src/mock.rs index 5ebc75245630..24b42b3e9f4b 100644 --- a/frame/session/benchmarking/src/mock.rs +++ b/frame/session/benchmarking/src/mock.rs @@ -19,7 +19,7 @@ #![cfg(test)] -use frame_election_provider_support::onchain; +use frame_election_provider_support::{onchain, SequentialPhragmen}; use frame_support::{ parameter_types, traits::{ConstU32, ConstU64}, @@ -156,8 +156,10 @@ where type Extrinsic = Extrinsic; } -impl onchain::Config for Test { - type Accuracy = sp_runtime::Perbill; +pub struct OnChainSeqPhragmen; +impl onchain::ExecutionConfig for OnChainSeqPhragmen { + type System = Test; + type Solver = SequentialPhragmen; type DataProvider = Staking; } @@ -179,7 +181,7 @@ impl pallet_staking::Config for Test { type NextNewSession = Session; type MaxNominatorRewardedPerValidator = ConstU32<64>; type OffendingValidatorsThreshold = (); - type ElectionProvider = onchain::OnChainSequentialPhragmen; + type ElectionProvider = onchain::UnboundedExecution; type GenesisElectionProvider = Self::ElectionProvider; type MaxUnlockingChunks = ConstU32<32>; type VoterList = pallet_staking::UseNominatorsAndValidatorsMap; diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index bb71232c3467..bb90aded852e 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -18,7 +18,9 @@ //! Test utilities use crate::{self as pallet_staking, *}; -use frame_election_provider_support::{onchain, SortedListProvider, VoteWeight}; +use frame_election_provider_support::{ + onchain, SequentialPhragmen, SortedListProvider, VoteWeight, +}; use frame_support::{ assert_ok, parameter_types, traits::{ @@ -245,8 +247,10 @@ impl pallet_bags_list::Config for Test { type Score = VoteWeight; } -impl onchain::Config for Test { - type Accuracy = Perbill; +pub struct OnChainSeqPhragmen; +impl onchain::ExecutionConfig for OnChainSeqPhragmen { + type System = Test; + type Solver = SequentialPhragmen; type DataProvider = Staking; } @@ -268,7 +272,7 @@ impl crate::pallet::pallet::Config for Test { type NextNewSession = Session; type MaxNominatorRewardedPerValidator = ConstU32<64>; type OffendingValidatorsThreshold = OffendingValidatorsThreshold; - type ElectionProvider = onchain::OnChainSequentialPhragmen; + type ElectionProvider = onchain::UnboundedExecution; type GenesisElectionProvider = Self::ElectionProvider; // NOTE: consider a macro and use `UseNominatorsAndValidatorsMap` as well. type VoterList = BagsList; From 0d45c9a4d1c98c0738952d79aadf075b55880a06 Mon Sep 17 00:00:00 2001 From: driemworks Date: Fri, 25 Mar 2022 20:25:23 -0500 Subject: [PATCH 644/695] storageDoubleMap -> storage map --- bin/node-template/pallets/iris-assets/src/lib.rs | 12 +++++------- bin/node-template/pallets/iris-session/src/lib.rs | 4 +++- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/bin/node-template/pallets/iris-assets/src/lib.rs b/bin/node-template/pallets/iris-assets/src/lib.rs index f8b80e0dcd32..c02e3a56bb0b 100644 --- a/bin/node-template/pallets/iris-assets/src/lib.rs +++ b/bin/node-template/pallets/iris-assets/src/lib.rs @@ -138,13 +138,11 @@ pub mod pallet { /// #[pallet::storage] #[pallet::getter(fn asset_access)] - pub(super) type AssetAccess = StorageDoubleMap< + pub(super) type AssetAccess = StorageMap< _, Blake2_128Concat, T::AccountId, - Blake2_128Concat, - T::AssetId, - T::AccountId, + Vec, ValueQuery, >; @@ -267,7 +265,7 @@ pub mod pallet { amount )?; - >::insert(beneficiary_accountid.clone(), asset_id.clone(), who.clone()); + >::mutate(beneficiary_accountid.clone(), |ids| { ids.push(asset_id.clone()) }); Self::deposit_event(Event::AssetCreated(asset_id.clone())); Ok(()) @@ -298,8 +296,8 @@ pub mod pallet { let target_account = T::Lookup::lookup(target)?; - let asset_id_owner = >::asset(asset_id.clone()).unwrap().owner; - >::insert(target_account.clone(), asset_id.clone(), asset_id_owner.clone()); + // let asset_id_owner = >::asset(asset_id.clone()).unwrap().owner; + >::mutate(target_account.clone(), |ids| { ids.push(asset_id.clone()) }); Ok(()) } diff --git a/bin/node-template/pallets/iris-session/src/lib.rs b/bin/node-template/pallets/iris-session/src/lib.rs index beb2b3ced134..95b7c8ad6ea1 100644 --- a/bin/node-template/pallets/iris-session/src/lib.rs +++ b/bin/node-template/pallets/iris-session/src/lib.rs @@ -901,8 +901,10 @@ impl Pallet { let cid = >::metadata( asset_id.clone() ); + // check balance: TODO: This is bad... should really check the pallet_assets storage to verify this + // but this works for now ensure!( - owner.clone() == >::asset_access(requestor.clone(), asset_id.clone()), + >::asset_access(requestor.clone()).contains(&asset_id), Error::::InsufficientBalance ); match Self::ipfs_request(IpfsRequest::CatBytes(cid.clone()), deadline) { From 4b8cbaa8eb0e9734095425da0e9f952004b5450f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 26 Mar 2022 08:19:07 +0100 Subject: [PATCH 645/695] Bump handlebars from 4.1.6 to 4.2.2 (#11073) Bumps [handlebars](https://github.com/sunng87/handlebars-rust) from 4.1.6 to 4.2.2. - [Release notes](https://github.com/sunng87/handlebars-rust/releases) - [Changelog](https://github.com/sunng87/handlebars-rust/blob/master/CHANGELOG.md) - [Commits](https://github.com/sunng87/handlebars-rust/compare/v4.1.6...v4.2.2) --- updated-dependencies: - dependency-name: handlebars dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- utils/frame/benchmarking-cli/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 81a53ed85885..2a761b9a761e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2779,9 +2779,9 @@ checksum = "62aca2aba2d62b4a7f5b33f3712cb1b0692779a56fb510499d5c0aa594daeaf3" [[package]] name = "handlebars" -version = "4.1.6" +version = "4.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167fa173496c9eadd8749cca6f8339ac88e248f3ad2442791d0b743318a94fc0" +checksum = "99d6a30320f094710245150395bc763ad23128d6a1ebbad7594dc4164b62c56b" dependencies = [ "log 0.4.14", "pest", diff --git a/utils/frame/benchmarking-cli/Cargo.toml b/utils/frame/benchmarking-cli/Cargo.toml index 11bba2b37957..5cb81232085a 100644 --- a/utils/frame/benchmarking-cli/Cargo.toml +++ b/utils/frame/benchmarking-cli/Cargo.toml @@ -40,7 +40,7 @@ clap = { version = "3.1.6", features = ["derive"] } chrono = "0.4" serde = "1.0.136" serde_json = "1.0.79" -handlebars = "4.1.6" +handlebars = "4.2.2" Inflector = "0.11.4" linked-hash-map = "0.5.4" log = "0.4.8" From 12b32cb5dc8c5d3fd5959febd0f1b8693b3aaba0 Mon Sep 17 00:00:00 2001 From: driemworks Date: Sat, 26 Mar 2022 14:34:40 -0500 Subject: [PATCH 646/695] owner matches admin on creation --- bin/node-template/pallets/iris-assets/src/lib.rs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/bin/node-template/pallets/iris-assets/src/lib.rs b/bin/node-template/pallets/iris-assets/src/lib.rs index c02e3a56bb0b..1614307cc0ff 100644 --- a/bin/node-template/pallets/iris-assets/src/lib.rs +++ b/bin/node-template/pallets/iris-assets/src/lib.rs @@ -295,8 +295,6 @@ pub mod pallet { )?; let target_account = T::Lookup::lookup(target)?; - - // let asset_id_owner = >::asset(asset_id.clone()).unwrap().owner; >::mutate(target_account.clone(), |ids| { ids.push(asset_id.clone()) }); Ok(()) @@ -368,17 +366,11 @@ pub mod pallet { #[pallet::compact] balance: T::Balance, ) -> DispatchResult { let who = ensure_signed(origin)?; - let new_origin = system::RawOrigin::Signed(who).into(); - + let which_admin = T::Lookup::lookup(admin.clone())?; + let new_origin = system::RawOrigin::Signed(which_admin.clone()).into(); >::create(new_origin, id.clone(), admin.clone(), balance) .map_err(|_| Error::::CantCreateAssetClass)?; - >::insert(id.clone(), cid.clone()); - - let which_admin = T::Lookup::lookup(admin.clone())?; - - // let mut asset_ids = >::get(which_admin); - // asset_ids.push(id.clone()); >::mutate(which_admin, |ids| { ids.push(id) }); >::mutate(|ids| ids.push(id.clone())); From d26123aec44e3df00b921ab0d27cbc1de0b11fa9 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Sun, 27 Mar 2022 02:43:47 -0400 Subject: [PATCH 647/695] remove misleading sentence (#11125) --- frame/support/src/storage/mod.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/frame/support/src/storage/mod.rs b/frame/support/src/storage/mod.rs index 226682eecf10..4a0eebf56799 100644 --- a/frame/support/src/storage/mod.rs +++ b/frame/support/src/storage/mod.rs @@ -517,9 +517,6 @@ pub trait IterableStorageNMap: StorageN /// An implementation of a map with a two keys. /// -/// It provides an important ability to efficiently remove all entries -/// that have a common first key. -/// /// Details on implementation can be found at [`generator::StorageDoubleMap`]. pub trait StorageDoubleMap { /// The type that get/take returns. From 6615ae4751ab35a913ac32a3ba210b35899db3d2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 27 Mar 2022 21:19:55 +0200 Subject: [PATCH 648/695] Bump zeroize from 1.4.3 to 1.5.4 (#11123) Bumps [zeroize](https://github.com/RustCrypto/utils) from 1.4.3 to 1.5.4. - [Release notes](https://github.com/RustCrypto/utils/releases) - [Commits](https://github.com/RustCrypto/utils/compare/zeroize-v1.4.3...zeroize-v1.5.4) --- updated-dependencies: - dependency-name: zeroize dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- client/network/Cargo.toml | 2 +- primitives/core/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2a761b9a761e..ac30433c5ea2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12474,18 +12474,18 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.4.3" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d68d9dcec5f9b43a30d38c49f91dfedfaac384cb8f085faca366c26207dd1619" +checksum = "7eb5728b8afd3f280a869ce1d4c554ffaed35f45c231fc41bfbd0381bef50317" dependencies = [ "zeroize_derive", ] [[package]] name = "zeroize_derive" -version = "1.2.0" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdff2024a851a322b08f179173ae2ba620445aef1e838f0c196820eade4ae0c7" +checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17" dependencies = [ "proc-macro2", "quote", diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index 671271fcb3b7..d6bc90016ab8 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -61,7 +61,7 @@ unsigned-varint = { version = "0.6.0", features = [ "asynchronous_codec", ] } void = "1.0.2" -zeroize = "1.4.3" +zeroize = "1.5.4" libp2p = "0.40.0" [dev-dependencies] diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index 55d00362033d..413a11c9dc0a 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -32,7 +32,7 @@ substrate-bip39 = { version = "0.4.4", optional = true } tiny-bip39 = { version = "0.8.2", optional = true } regex = { version = "1.5.4", optional = true } num-traits = { version = "0.2.8", default-features = false } -zeroize = { version = "1.4.3", default-features = false } +zeroize = { version = "1.5.4", default-features = false } secrecy = { version = "0.8.0", default-features = false } lazy_static = { version = "1.4.0", default-features = false, optional = true } parking_lot = { version = "0.12.0", optional = true } From 65b44e91bedd6961ef30cef08e89273b7d98b4ed Mon Sep 17 00:00:00 2001 From: Alexander Popiak Date: Sun, 27 Mar 2022 23:35:52 +0200 Subject: [PATCH 649/695] add notes and warnings to ProvideInherent docs (#9730) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add notes and warnings to ProvideInherent docs * rephrase ProvideInherent doc comments * more comment refinement * remove multiple inherents note * remove repetition Co-authored-by: Bastian Köcher * replace inherent example in docs * add note about who checks is_inherent_required * Apply suggestions from code review Co-authored-by: Bastian Köcher Co-authored-by: Bastian Köcher --- frame/support/src/inherent.rs | 35 ++++++++++++++++++++++++--------- primitives/inherents/src/lib.rs | 12 +++++------ 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/frame/support/src/inherent.rs b/frame/support/src/inherent.rs index 59d55b1df3f3..0aa6b9d3f75a 100644 --- a/frame/support/src/inherent.rs +++ b/frame/support/src/inherent.rs @@ -24,9 +24,12 @@ pub use sp_inherents::{ CheckInherentsResult, InherentData, InherentIdentifier, IsFatalError, MakeFatalError, }; -/// A pallet that provides or verifies an inherent extrinsic. +/// A pallet that provides or verifies an inherent extrinsic will implement this trait. /// -/// The pallet may provide the inherent, verify an inherent, or both provide and verify. +/// The pallet may provide an inherent, verify an inherent, or both provide and verify. +/// +/// Briefly, inherent extrinsics ("inherents") are extrinsics that are added to a block by the block +/// producer. See [`sp_inherents`] for more documentation on inherents. pub trait ProvideInherent { /// The call type of the pallet. type Call; @@ -36,6 +39,12 @@ pub trait ProvideInherent { const INHERENT_IDENTIFIER: self::InherentIdentifier; /// Create an inherent out of the given `InherentData`. + /// + /// NOTE: All checks necessary to ensure that the inherent is correct and that can be done in + /// the runtime should happen in the returned `Call`. + /// E.g. if this provides the timestamp, the call will check that the given timestamp is + /// increasing the old timestamp by more than a minimum and it will also check that the + /// timestamp hasn't already been set in the current block. fn create_inherent(data: &InherentData) -> Option; /// Determines whether this inherent is required in this block. @@ -44,15 +53,17 @@ pub trait ProvideInherent { /// implementation returns this. /// /// - `Ok(Some(e))` indicates that this inherent is required in this block. `construct_runtime!` - /// will call this function from in its implementation of `fn check_extrinsics`. + /// will call this function in its implementation of `fn check_extrinsics`. /// If the inherent is not present, it will return `e`. /// /// - `Err(_)` indicates that this function failed and further operations should be aborted. /// - /// NOTE: If inherent is required then the runtime asserts that the block contains at least + /// NOTE: If the inherent is required then the runtime asserts that the block contains at least /// one inherent for which: /// * type is [`Self::Call`], /// * [`Self::is_inherent`] returns true. + /// + /// NOTE: This is currently only checked by block producers, not all full nodes. fn is_inherent_required(_: &InherentData) -> Result, Self::Error> { Ok(None) } @@ -64,21 +75,27 @@ pub trait ProvideInherent { /// included in the block by its author. Whereas the second parameter represents the inherent /// data that the verifying node calculates. /// - /// NOTE: A block can contains multiple inherent. + /// This is intended to allow for checks that cannot be done within the runtime such as, e.g., + /// the timestamp. + /// + /// # Warning + /// + /// This check is not guaranteed to be run by all full nodes and cannot be relied upon for + /// ensuring that the block is correct. fn check_inherent(_: &Self::Call, _: &InherentData) -> Result<(), Self::Error> { Ok(()) } /// Return whether the call is an inherent call. /// - /// NOTE: Signed extrinsics are not inherent, but signed extrinsic with the given call variant - /// can be dispatched. + /// NOTE: Signed extrinsics are not inherents, but a signed extrinsic with the given call + /// variant can be dispatched. /// /// # Warning /// - /// In FRAME, inherent are enforced to be before other extrinsics, for this reason, + /// In FRAME, inherents are enforced to be executed before other extrinsics. For this reason, /// pallets with unsigned transactions **must ensure** that no unsigned transaction call /// is an inherent call, when implementing `ValidateUnsigned::validate_unsigned`. - /// Otherwise block producer can produce invalid blocks by including them after non inherent. + /// Otherwise block producers can produce invalid blocks by including them after non inherents. fn is_inherent(call: &Self::Call) -> bool; } diff --git a/primitives/inherents/src/lib.rs b/primitives/inherents/src/lib.rs index cd04a1bc3b3d..a3ef963c47b3 100644 --- a/primitives/inherents/src/lib.rs +++ b/primitives/inherents/src/lib.rs @@ -15,14 +15,14 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Substrate inherent extrinsics +//! Substrate Inherent Extrinsics //! //! Inherent extrinsics are extrinsics that are inherently added to each block. However, it is up to -//! runtime implementation to require an inherent for each block or to make it optional. Inherents -//! are mainly used to pass data from the block producer to the runtime. So, inherents require some -//! part that is running on the client side and some part that is running on the runtime side. Any -//! data that is required by an inherent is passed as [`InherentData`] from the client to the -//! runtime when the inherents are constructed. +//! the runtime implementation to require an inherent for each block or to make it optional. +//! Inherents are mainly used to pass data from the block producer to the runtime. So, inherents +//! require some part that is running on the client side and some part that is running on the +//! runtime side. Any data that is required by an inherent is passed as [`InherentData`] from the +//! client to the runtime when the inherents are constructed. //! //! The process of constructing and applying inherents is the following: //! From a5f3dbe4fa0417be6f1b13934c38db74cbb1b34d Mon Sep 17 00:00:00 2001 From: Koute Date: Tue, 29 Mar 2022 06:42:01 +0900 Subject: [PATCH 650/695] Bump `tokio` to 1.17.0 (#10894) * Bump `tokio` to 0.17.0 * Revert version changes to scale-info Co-authored-by: Keith Yeung --- Cargo.lock | 23 +++++++++++---------- bin/node/cli/Cargo.toml | 2 +- client/cli/Cargo.toml | 2 +- client/consensus/manual-seal/Cargo.toml | 2 +- client/finality-grandpa/Cargo.toml | 2 +- client/offchain/Cargo.toml | 2 +- client/rpc-servers/Cargo.toml | 2 +- client/service/Cargo.toml | 2 +- client/service/test/Cargo.toml | 2 +- test-utils/Cargo.toml | 2 +- test-utils/test-crate/Cargo.toml | 2 +- utils/frame/remote-externalities/Cargo.toml | 2 +- utils/frame/rpc/support/Cargo.toml | 2 +- utils/prometheus/Cargo.toml | 4 ++-- 14 files changed, 26 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ac30433c5ea2..873da8abaca3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3010,7 +3010,7 @@ dependencies = [ "httpdate", "itoa 0.4.8", "pin-project-lite 0.2.6", - "socket2 0.4.0", + "socket2 0.4.4", "tokio", "tower-service", "tracing", @@ -3914,7 +3914,7 @@ dependencies = [ "log 0.4.14", "rand 0.8.4", "smallvec 1.8.0", - "socket2 0.4.0", + "socket2 0.4.4", "void", ] @@ -4122,7 +4122,7 @@ dependencies = [ "libc", "libp2p-core", "log 0.4.14", - "socket2 0.4.0", + "socket2 0.4.4", ] [[package]] @@ -4559,9 +4559,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.7.13" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c2bdb6314ec10835cd3293dd268473a835c02b7b352e788be788b3c6ca6bb16" +checksum = "ba272f85fa0b41fc91872be579b3bbe0f56b792aa361a380eb669469f68dafb2" dependencies = [ "libc", "log 0.4.14", @@ -9623,9 +9623,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.4.0" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e3dfc207c526015c632472a77be09cf1b6e46866581aecae5cc38fb4235dea2" +checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" dependencies = [ "libc", "winapi 0.3.9", @@ -11024,19 +11024,20 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.15.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbbf1c778ec206785635ce8ad57fe52b3009ae9e0c9f574a728f3049d3e55838" +checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee" dependencies = [ "bytes 1.1.0", "libc", "memchr", - "mio 0.7.13", + "mio 0.8.0", "num_cpus", "once_cell", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "pin-project-lite 0.2.6", "signal-hook-registry", + "socket2 0.4.4", "tokio-macros", "winapi 0.3.9", ] diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index 24e069d21f69..0e8cdfd7c3fe 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -126,7 +126,7 @@ platforms = "2.0" async-std = { version = "1.10.0", features = ["attributes"] } soketto = "0.4.2" criterion = { version = "0.3.5", features = ["async_tokio"] } -tokio = { version = "1.15", features = ["macros", "time", "parking_lot"] } +tokio = { version = "1.17.0", features = ["macros", "time", "parking_lot"] } jsonrpsee-ws-client = "0.4.1" wait-timeout = "0.2" remote-externalities = { path = "../../../utils/frame/remote-externalities" } diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index 665bd6acfaf3..0fbb06e8aa4a 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -28,7 +28,7 @@ serde = "1.0.136" serde_json = "1.0.79" thiserror = "1.0.30" tiny-bip39 = "0.8.2" -tokio = { version = "1.15", features = ["signal", "rt-multi-thread", "parking_lot"] } +tokio = { version = "1.17.0", features = ["signal", "rt-multi-thread", "parking_lot"] } parity-scale-codec = "3.0.0" sc-client-api = { version = "4.0.0-dev", path = "../api" } diff --git a/client/consensus/manual-seal/Cargo.toml b/client/consensus/manual-seal/Cargo.toml index 7aaad863af55..62650d50ce4a 100644 --- a/client/consensus/manual-seal/Cargo.toml +++ b/client/consensus/manual-seal/Cargo.toml @@ -47,7 +47,7 @@ sp-timestamp = { path = "../../../primitives/timestamp", version = "4.0.0-dev" } prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.10.0-dev" } [dev-dependencies] -tokio = { version = "1.15.0", features = ["rt-multi-thread", "macros"] } +tokio = { version = "1.17.0", features = ["rt-multi-thread", "macros"] } sc-basic-authorship = { path = "../../basic-authorship", version = "0.10.0-dev" } substrate-test-runtime-client = { path = "../../../test-utils/runtime/client", version = "2.0.0" } substrate-test-runtime-transaction-pool = { path = "../../../test-utils/runtime/transaction-pool", version = "2.0.0" } diff --git a/client/finality-grandpa/Cargo.toml b/client/finality-grandpa/Cargo.toml index 86cd57fc7c09..b8b41ba70365 100644 --- a/client/finality-grandpa/Cargo.toml +++ b/client/finality-grandpa/Cargo.toml @@ -61,5 +61,5 @@ substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/ru sp-tracing = { version = "5.0.0", path = "../../primitives/tracing" } serde = "1.0.136" -tokio = "1.15" +tokio = "1.17.0" tempfile = "3.1.0" diff --git a/client/offchain/Cargo.toml b/client/offchain/Cargo.toml index e542759b4809..3edba1f45704 100644 --- a/client/offchain/Cargo.toml +++ b/client/offchain/Cargo.toml @@ -43,7 +43,7 @@ sc-transaction-pool-api = { version = "4.0.0-dev", path = "../transaction-pool/a sp-tracing = { version = "5.0.0", path = "../../primitives/tracing" } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } -tokio = "1.15" +tokio = "1.17.0" lazy_static = "1.4.0" [features] diff --git a/client/rpc-servers/Cargo.toml b/client/rpc-servers/Cargo.toml index f0c3fd496aa7..6b2c9f5aa373 100644 --- a/client/rpc-servers/Cargo.toml +++ b/client/rpc-servers/Cargo.toml @@ -19,7 +19,7 @@ pubsub = { package = "jsonrpc-pubsub", version = "18.0.0" } log = "0.4.8" prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.10.0-dev"} serde_json = "1.0.79" -tokio = { version = "1.15", features = ["parking_lot"] } +tokio = { version = "1.17.0", features = ["parking_lot"] } http = { package = "jsonrpc-http-server", version = "18.0.0" } ipc = { package = "jsonrpc-ipc-server", version = "18.0.0" } ws = { package = "jsonrpc-ws-server", version = "18.0.0" } diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index 737a29f1db0c..2cb23fed40f2 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -78,7 +78,7 @@ parity-util-mem = { version = "0.11.0", default-features = false, features = [ "primitive-types", ] } async-trait = "0.1.50" -tokio = { version = "1.15", features = ["time", "rt-multi-thread", "parking_lot"] } +tokio = { version = "1.17.0", features = ["time", "rt-multi-thread", "parking_lot"] } tempfile = "3.1.0" directories = "4.0.1" diff --git a/client/service/test/Cargo.toml b/client/service/test/Cargo.toml index 0b99b9c5aeb9..fa3c49a2340a 100644 --- a/client/service/test/Cargo.toml +++ b/client/service/test/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] hex = "0.4" hex-literal = "0.3.4" tempfile = "3.1.0" -tokio = { version = "1.15.0", features = ["time"] } +tokio = { version = "1.17.0", features = ["time"] } log = "0.4.8" fdlimit = "0.2.1" parking_lot = "0.12.0" diff --git a/test-utils/Cargo.toml b/test-utils/Cargo.toml index 756de5803280..9f66fa812bb4 100644 --- a/test-utils/Cargo.toml +++ b/test-utils/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] futures = "0.3.16" substrate-test-utils-derive = { version = "0.10.0-dev", path = "./derive" } -tokio = { version = "1.10", features = ["macros", "time"] } +tokio = { version = "1.17.0", features = ["macros", "time"] } [dev-dependencies] sc-service = { version = "0.10.0-dev", path = "../client/service" } diff --git a/test-utils/test-crate/Cargo.toml b/test-utils/test-crate/Cargo.toml index 4e07f92e86ea..f6fea8407eaa 100644 --- a/test-utils/test-crate/Cargo.toml +++ b/test-utils/test-crate/Cargo.toml @@ -12,6 +12,6 @@ publish = false targets = ["x86_64-unknown-linux-gnu"] [dev-dependencies] -tokio = { version = "1.15", features = ["macros"] } +tokio = { version = "1.17.0", features = ["macros"] } test-utils = { version = "4.0.0-dev", path = "..", package = "substrate-test-utils" } sc-service = { version = "0.10.0-dev", path = "../../client/service" } diff --git a/utils/frame/remote-externalities/Cargo.toml b/utils/frame/remote-externalities/Cargo.toml index d5042444119d..fc44c63b8acd 100644 --- a/utils/frame/remote-externalities/Cargo.toml +++ b/utils/frame/remote-externalities/Cargo.toml @@ -28,7 +28,7 @@ sp-runtime = { version = "6.0.0", path = "../../../primitives/runtime" } sp-version = { version = "5.0.0", path = "../../../primitives/version" } [dev-dependencies] -tokio = { version = "1.15", features = ["macros", "rt-multi-thread"] } +tokio = { version = "1.17.0", features = ["macros", "rt-multi-thread"] } pallet-elections-phragmen = { path = "../../../frame/elections-phragmen", version = "5.0.0-dev" } frame-support = { path = "../../../frame/support", version = "4.0.0-dev" } diff --git a/utils/frame/rpc/support/Cargo.toml b/utils/frame/rpc/support/Cargo.toml index 0055ef47f8f4..91ec47e34bd3 100644 --- a/utils/frame/rpc/support/Cargo.toml +++ b/utils/frame/rpc/support/Cargo.toml @@ -26,4 +26,4 @@ sc-rpc-api = { version = "0.10.0-dev", path = "../../../../client/rpc-api" } [dev-dependencies] frame-system = { version = "4.0.0-dev", path = "../../../../frame/system" } scale-info = "2.0.1" -tokio = "1.15" +tokio = "1.17.0" diff --git a/utils/prometheus/Cargo.toml b/utils/prometheus/Cargo.toml index fb998d2809fa..4940712f2f4d 100644 --- a/utils/prometheus/Cargo.toml +++ b/utils/prometheus/Cargo.toml @@ -17,9 +17,9 @@ log = "0.4.8" prometheus = { version = "0.13.0", default-features = false } futures-util = { version = "0.3.19", default-features = false, features = ["io"] } thiserror = "1.0" -tokio = { version = "1.15", features = ["parking_lot"] } +tokio = { version = "1.17.0", features = ["parking_lot"] } hyper = { version = "0.14.16", default-features = false, features = ["http1", "server", "tcp"] } [dev-dependencies] hyper = { version = "0.14.16", features = ["client"] } -tokio = { version = "1.15", features = ["rt-multi-thread"] } +tokio = { version = "1.17.0", features = ["rt-multi-thread"] } From 297a5e4a548744a07aabb6a8e200f808c54231f5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Mar 2022 23:43:30 +0200 Subject: [PATCH 651/695] Bump libc from 0.2.119 to 0.2.121 (#11127) Bumps [libc](https://github.com/rust-lang/libc) from 0.2.119 to 0.2.121. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.119...0.2.121) --- updated-dependencies: - dependency-name: libc dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- client/executor/wasmtime/Cargo.toml | 2 +- client/tracing/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 873da8abaca3..2fe01c905d7c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3658,9 +3658,9 @@ checksum = "3576a87f2ba00f6f106fdfcd16db1d698d648a26ad8e0573cad8537c3c362d2a" [[package]] name = "libc" -version = "0.2.119" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4" +checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f" [[package]] name = "libgit2-sys" diff --git a/client/executor/wasmtime/Cargo.toml b/client/executor/wasmtime/Cargo.toml index 13bf196c4d44..f0155204f544 100644 --- a/client/executor/wasmtime/Cargo.toml +++ b/client/executor/wasmtime/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -libc = "0.2.119" +libc = "0.2.121" cfg-if = "1.0" log = "0.4.8" parity-wasm = "0.42.0" diff --git a/client/tracing/Cargo.toml b/client/tracing/Cargo.toml index 3c4401e2d342..76cdcb4e4b02 100644 --- a/client/tracing/Cargo.toml +++ b/client/tracing/Cargo.toml @@ -17,7 +17,7 @@ ansi_term = "0.12.1" atty = "0.2.13" chrono = "0.4.19" lazy_static = "1.4.0" -libc = "0.2.119" +libc = "0.2.121" log = { version = "0.4.8" } once_cell = "1.8.0" parking_lot = "0.12.0" From d587fd75f54af0b16d8da1ad2273d83dbca889b2 Mon Sep 17 00:00:00 2001 From: driemworks Date: Mon, 28 Mar 2022 20:11:30 -0500 Subject: [PATCH 652/695] remove owner param --- bin/node-template/pallets/iris-assets/src/lib.rs | 5 ++--- bin/node-template/pallets/iris-assets/src/tests.rs | 1 - 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/bin/node-template/pallets/iris-assets/src/lib.rs b/bin/node-template/pallets/iris-assets/src/lib.rs index 1614307cc0ff..060ba9cdcb35 100644 --- a/bin/node-template/pallets/iris-assets/src/lib.rs +++ b/bin/node-template/pallets/iris-assets/src/lib.rs @@ -335,15 +335,14 @@ pub mod pallet { #[pallet::weight(100)] pub fn request_bytes( origin: OriginFor, - owner: ::Source, #[pallet::compact] asset_id: T::AssetId, ) -> DispatchResult { let who = ensure_signed(origin)?; - let owner_account = T::Lookup::lookup(owner)?; + let owner = >::asset(asset_id.clone()).unwrap().owner; >::mutate( |queue| queue.push(DataCommand::CatBytes( who.clone(), - owner_account.clone(), + owner.clone(), asset_id.clone(), ))); Ok(()) diff --git a/bin/node-template/pallets/iris-assets/src/tests.rs b/bin/node-template/pallets/iris-assets/src/tests.rs index f231636a7f34..fcad291b8a7c 100644 --- a/bin/node-template/pallets/iris-assets/src/tests.rs +++ b/bin/node-template/pallets/iris-assets/src/tests.rs @@ -78,7 +78,6 @@ fn iris_assets_request_data_works_for_valid_values() { // WHEN: I invoke the request_data extrinsic assert_ok!(Iris::request_bytes( Origin::signed(p.clone().public()), - p.clone().public(), asset_id.clone(), )); From ab8bb40470cb1d10f7e63e6ef4ad9cdeb2dce821 Mon Sep 17 00:00:00 2001 From: driemworks Date: Mon, 28 Mar 2022 21:44:43 -0500 Subject: [PATCH 653/695] update rpc endpoint to accept asset_id instead of cid --- .../pallets/iris-session/Cargo.toml | 4 +++- .../iris-session/rpc/runtime-api/src/lib.rs | 2 +- .../pallets/iris-session/rpc/src/lib.rs | 6 +++--- .../pallets/iris-session/src/lib.rs | 16 +++++++++++----- bin/node-template/runtime/src/lib.rs | 4 ++-- 5 files changed, 20 insertions(+), 12 deletions(-) diff --git a/bin/node-template/pallets/iris-session/Cargo.toml b/bin/node-template/pallets/iris-session/Cargo.toml index 12bcecd73f8a..4e3a57fc83e4 100644 --- a/bin/node-template/pallets/iris-session/Cargo.toml +++ b/bin/node-template/pallets/iris-session/Cargo.toml @@ -34,10 +34,11 @@ log = { version = "0.4.14", default-features = false } pallet-im-online = { version = "4.0.0-dev", default-features = false, path = "../../../../frame/im-online" } pallet-session = { version = "4.0.0-dev", default-features = false, features = ["historical"], path = "../../../../frame/session" } pallet-iris-assets = { version = "1.0.0", default-features = false, path = "../iris-assets" } +pallet-assets = { version = "4.0.0-dev", default-features = false, path = "../../../../frame/assets" } [dev-dependencies] pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../../../../frame/balances" } -pallet-assets = { version = "4.0.0-dev", default-features = false, path = "../../../../frame/assets" } +# pallet-assets = { version = "4.0.0-dev", default-features = false, path = "../../../../frame/assets" } [features] default = ['std'] @@ -56,6 +57,7 @@ std = [ 'log/std', 'pallet-im-online/std', 'pallet-session/std', + 'pallet-assets/std', 'pallet-iris-assets/std', ] diff --git a/bin/node-template/pallets/iris-session/rpc/runtime-api/src/lib.rs b/bin/node-template/pallets/iris-session/rpc/runtime-api/src/lib.rs index 33f0dc29eff1..1ba4ba5fd5f5 100644 --- a/bin/node-template/pallets/iris-session/rpc/runtime-api/src/lib.rs +++ b/bin/node-template/pallets/iris-session/rpc/runtime-api/src/lib.rs @@ -10,7 +10,7 @@ sp_api::decl_runtime_apis! { pub trait IrisApi { fn retrieve_bytes( - message: Bytes, + asset_id: Bytes, ) -> Bytes; } } diff --git a/bin/node-template/pallets/iris-session/rpc/src/lib.rs b/bin/node-template/pallets/iris-session/rpc/src/lib.rs index a6c4a30c2c65..e71b55c9c8f8 100644 --- a/bin/node-template/pallets/iris-session/rpc/src/lib.rs +++ b/bin/node-template/pallets/iris-session/rpc/src/lib.rs @@ -16,7 +16,7 @@ pub trait IrisApi { #[rpc(name = "iris_retrieveBytes")] fn retrieve_bytes( &self, - message: Bytes, + asset_id: Bytes, at: Option, ) -> Result; } @@ -59,14 +59,14 @@ where { fn retrieve_bytes( &self, - message: Bytes, + asset_id: Bytes, at: Option<::Hash>, ) -> Result { let api = self.client.runtime_api(); let at = BlockId::hash(at.unwrap_or_else(|| self.client.info().best_hash )); - let runtime_api_result = api.retrieve_bytes(&at, message); + let runtime_api_result = api.retrieve_bytes(&at, asset_id); runtime_api_result.map_err(|e| RpcError{ code: ErrorCode::ServerError(Error::DecodeError.into()), message: "unable to query runtime api".into(), diff --git a/bin/node-template/pallets/iris-session/src/lib.rs b/bin/node-template/pallets/iris-session/src/lib.rs index 95b7c8ad6ea1..af7be0c75ec9 100644 --- a/bin/node-template/pallets/iris-session/src/lib.rs +++ b/bin/node-template/pallets/iris-session/src/lib.rs @@ -28,6 +28,8 @@ mod mock; mod tests; +use std::convert::TryInto; + use frame_support::{ ensure, pallet_prelude::*, @@ -145,6 +147,7 @@ pub mod pallet { pub trait Config: CreateSignedTransaction> + frame_system::Config + pallet_session::Config + + pallet_assets::Config + pallet_iris_assets::Config { /// The Event type. @@ -722,7 +725,6 @@ impl Pallet { .propagate(true) .build() } - /// implementation for RPC runtime API to retrieve bytes from the node's local storage /// /// * public_key: The account's public key as bytes @@ -730,10 +732,14 @@ impl Pallet { /// * message: The signed message as bytes /// pub fn retrieve_bytes( - message: Bytes, - ) -> Bytes { - let message_vec: Vec = message.to_vec(); - if let Some(data) = sp_io::offchain::local_storage_get(StorageKind::PERSISTENT, &message_vec) { + asset_id: Bytes, + ) -> Bytes + where ::AssetId: From { + let asset_id_u32: u32 = String::from_utf8(asset_id.to_vec()).unwrap().parse().unwrap(); + let asset_id_type: T::AssetId = asset_id_u32.try_into().unwrap(); + let cid = >::metadata(asset_id_type).to_vec(); + // // let message_vec: Vec = message.to_vec(); + if let Some(data) = sp_io::offchain::local_storage_get(StorageKind::PERSISTENT, &cid) { Bytes(data.clone()) } else { Bytes(Vec::new()) diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index 0645488c17a9..d5dfd9ea63ad 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -744,9 +744,9 @@ impl_runtime_apis! { */ impl pallet_iris_rpc_runtime_api::IrisApi for Runtime { fn retrieve_bytes( - message: Bytes + asset_id: Bytes ) -> Bytes { - IrisSession::retrieve_bytes(message) + IrisSession::retrieve_bytes(asset_id) } } From 09073d367745837ba81f1bbd749a0fea3439b5ba Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Tue, 29 Mar 2022 14:07:51 +0200 Subject: [PATCH 654/695] Spellcheck HBS templates and add test (#11119) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Spellcheck HBS templates and fix vars Signed-off-by: Oliver Tale-Yazdi * Add test for benchmark-storage Signed-off-by: Oliver Tale-Yazdi * Fmt templates Signed-off-by: Oliver Tale-Yazdi * fmt Signed-off-by: Oliver Tale-Yazdi * Review fixes Co-authored-by: Bastian Köcher Co-authored-by: Bastian Köcher --- bin/node/cli/tests/benchmark_storage_works.rs | 52 +++++++++++++++++++ .../benchmarking-cli/src/overhead/weights.hbs | 28 +++------- .../benchmarking-cli/src/storage/weights.hbs | 31 ++++++----- 3 files changed, 77 insertions(+), 34 deletions(-) create mode 100644 bin/node/cli/tests/benchmark_storage_works.rs diff --git a/bin/node/cli/tests/benchmark_storage_works.rs b/bin/node/cli/tests/benchmark_storage_works.rs new file mode 100644 index 000000000000..1628f9a7e97b --- /dev/null +++ b/bin/node/cli/tests/benchmark_storage_works.rs @@ -0,0 +1,52 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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 . + +use assert_cmd::cargo::cargo_bin; +use std::{ + path::Path, + process::{Command, ExitStatus}, +}; +use tempfile::tempdir; + +/// Tests that the `benchmark-storage` command works for the dev runtime. +#[test] +fn benchmark_storage_works() { + let tmp_dir = tempdir().expect("could not create a temp dir"); + let base_path = tmp_dir.path(); + + // Benchmarking the storage works and creates the correct weight file. + assert!(benchmark_storage("rocksdb", base_path).success()); + assert!(base_path.join("rocksdb_weights.rs").exists()); + + assert!(benchmark_storage("paritydb", base_path).success()); + assert!(base_path.join("paritydb_weights.rs").exists()); +} + +fn benchmark_storage(db: &str, base_path: &Path) -> ExitStatus { + Command::new(cargo_bin("substrate")) + .args(&["benchmark-storage", "--dev"]) + .arg("--db") + .arg(db) + .arg("--weight-path") + .arg(base_path) + .args(["--state-version", "1"]) + .args(["--warmups", "0"]) + .args(["--add", "100", "--mul", "1.2", "--metric", "p75"]) + .status() + .unwrap() +} diff --git a/utils/frame/benchmarking-cli/src/overhead/weights.hbs b/utils/frame/benchmarking-cli/src/overhead/weights.hbs index 0f6b7f3e9119..ad33f55a9f36 100644 --- a/utils/frame/benchmarking-cli/src/overhead/weights.hbs +++ b/utils/frame/benchmarking-cli/src/overhead/weights.hbs @@ -37,17 +37,17 @@ parameter_types! { {{#if (eq short_name "block")}} /// Time to execute an empty block. {{else}} - /// Time to execute a NO-OP extrinsic eg. `System::remark`. + /// Time to execute a NO-OP extrinsic, for example `System::remark`. {{/if}} /// Calculated by multiplying the *{{params.weight.weight_metric}}* with `{{params.weight.weight_mul}}` and adding `{{params.weight.weight_add}}`. /// - /// Stats [ns]: + /// Stats [NS]: /// Min, Max: {{underscore stats.min}}, {{underscore stats.max}} /// Average: {{underscore stats.avg}} /// Median: {{underscore stats.median}} - /// StdDev: {{stats.stddev}} + /// Std-Dev: {{stats.stddev}} /// - /// Percentiles [ns]: + /// Percentiles [NS]: /// 99th: {{underscore stats.p99}} /// 95th: {{underscore stats.p95}} /// 75th: {{underscore stats.p75}} @@ -67,26 +67,14 @@ mod test_weights { {{#if (eq short_name "block")}} // At least 100 µs. - assert!( - w >= 100 * constants::WEIGHT_PER_MICROS, - "Weight should be at least 100 µs." - ); + assert!(w >= 100 * constants::WEIGHT_PER_MICROS, "Weight should be at least 100 µs."); // At most 50 ms. - assert!( - w <= 50 * constants::WEIGHT_PER_MILLIS, - "Weight should be at most 50 ms." - ); + assert!(w <= 50 * constants::WEIGHT_PER_MILLIS, "Weight should be at most 50 ms."); {{else}} // At least 10 µs. - assert!( - w >= 10 * constants::WEIGHT_PER_MICROS, - "Weight should be at least 10 µs." - ); + assert!(w >= 10 * constants::WEIGHT_PER_MICROS, "Weight should be at least 10 µs."); // At most 1 ms. - assert!( - w <= constants::WEIGHT_PER_MILLIS, - "Weight should be at most 1 ms." - ); + assert!(w <= constants::WEIGHT_PER_MILLIS, "Weight should be at most 1 ms."); {{/if}} } } diff --git a/utils/frame/benchmarking-cli/src/storage/weights.hbs b/utils/frame/benchmarking-cli/src/storage/weights.hbs index bfb832cb847f..63f896e1104b 100644 --- a/utils/frame/benchmarking-cli/src/storage/weights.hbs +++ b/utils/frame/benchmarking-cli/src/storage/weights.hbs @@ -22,52 +22,55 @@ //! BLOCK-NUM: `{{block_number}}` //! SKIP-WRITE: `{{params.skip_write}}`, SKIP-READ: `{{params.skip_read}}`, WARMUPS: `{{params.warmups}}` //! STATE-VERSION: `V{{params.state_version}}`, STATE-CACHE-SIZE: `{{params.state_cache_size}}` -//! WEIGHT-PATH: `{{params.weight_path}}` -//! METRIC: `{{params.weight_metric}}`, WEIGHT-MUL: `{{params.weight_mul}}`, WEIGHT-ADD: `{{params.weight_add}}` +//! WEIGHT-PATH: `{{params.weight_params.weight_path}}` +//! METRIC: `{{params.weight_params.weight_metric}}`, WEIGHT-MUL: `{{params.weight_params.weight_mul}}`, WEIGHT-ADD: `{{params.weight_params.weight_add}}` // Executed Command: {{#each args as |arg|}} // {{arg}} {{/each}} -/// Storage DB weights for the {{runtime_name}} runtime and {{db_name}}. +/// Storage DB weights for the `{{runtime_name}}` runtime and `{{db_name}}`. pub mod constants { - use frame_support::{parameter_types, weights::{RuntimeDbWeight, constants}}; + use frame_support::{ + parameter_types, + weights::{constants, RuntimeDbWeight}, + }; parameter_types! { {{#if (eq db_name "ParityDb")}} - /// ParityDB can be enabled with a feature flag, but is still experimental. These weights + /// `ParityDB` can be enabled with a feature flag, but is still experimental. These weights /// are available for brave runtime engineers who may want to try this out as default. {{else}} - /// By default, Substrate uses RocksDB, so this will be the weight used throughout + /// By default, Substrate uses `RocksDB`, so this will be the weight used throughout /// the runtime. {{/if}} pub const {{db_name}}Weight: RuntimeDbWeight = RuntimeDbWeight { /// Time to read one storage item. - /// Calculated by multiplying the *{{params.weight_metric}}* of all values with `{{params.weight_mul}}` and adding `{{params.weight_add}}`. + /// Calculated by multiplying the *{{params.weight_params.weight_metric}}* of all values with `{{params.weight_params.weight_mul}}` and adding `{{params.weight_params.weight_add}}`. /// - /// Stats [ns]: + /// Stats [NS]: /// Min, Max: {{underscore read.0.min}}, {{underscore read.0.max}} /// Average: {{underscore read.0.avg}} /// Median: {{underscore read.0.median}} - /// StdDev: {{read.0.stddev}} + /// Std-Dev: {{read.0.stddev}} /// - /// Percentiles [ns]: + /// Percentiles [NS]: /// 99th: {{underscore read.0.p99}} /// 95th: {{underscore read.0.p95}} /// 75th: {{underscore read.0.p75}} read: {{underscore read_weight}} * constants::WEIGHT_PER_NANOS, /// Time to write one storage item. - /// Calculated by multiplying the *{{params.weight_metric}}* of all values with `{{params.weight_mul}}` and adding `{{params.weight_add}}`. + /// Calculated by multiplying the *{{params.weight_params.weight_metric}}* of all values with `{{params.weight_params.weight_mul}}` and adding `{{params.weight_params.weight_add}}`. /// - /// Stats [ns]: + /// Stats [NS]: /// Min, Max: {{underscore write.0.min}}, {{underscore write.0.max}} /// Average: {{underscore write.0.avg}} /// Median: {{underscore write.0.median}} - /// StdDev: {{write.0.stddev}} + /// Std-Dev: {{write.0.stddev}} /// - /// Percentiles [ns]: + /// Percentiles [NS]: /// 99th: {{underscore write.0.p99}} /// 95th: {{underscore write.0.p95}} /// 75th: {{underscore write.0.p75}} From 71bb50c0ee15f80f98810248cc3461789d91065f Mon Sep 17 00:00:00 2001 From: Koute Date: Tue, 29 Mar 2022 23:19:19 +0900 Subject: [PATCH 655/695] Update `lru`, `regex` and `thread_local` (#11135) * Update `lru` to 0.7.3 * Update `regex` to 1.5.5 * Update `thread_local` to 1.1.4 --- Cargo.lock | 22 +++++++++++----------- bin/node/cli/Cargo.toml | 2 +- client/cli/Cargo.toml | 2 +- client/executor/Cargo.toml | 4 ++-- client/network-gossip/Cargo.toml | 2 +- client/network/Cargo.toml | 2 +- client/tracing/Cargo.toml | 2 +- primitives/blockchain/Cargo.toml | 2 +- primitives/panic-handler/Cargo.toml | 2 +- 9 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2fe01c905d7c..03a04cedcbf2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4075,7 +4075,7 @@ dependencies = [ "libp2p-core", "libp2p-swarm", "log 0.4.14", - "lru 0.7.0", + "lru 0.7.3", "rand 0.7.3", "smallvec 1.8.0", "unsigned-varint 0.7.0", @@ -4354,9 +4354,9 @@ dependencies = [ [[package]] name = "lru" -version = "0.7.0" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c748cfe47cb8da225c37595b3108bea1c198c84aaae8ea0ba76d01dda9fc803" +checksum = "fcb87f3080f6d1d69e8c564c0fcfde1d7aa8cc451ce40cae89479111f03bc0eb" dependencies = [ "hashbrown 0.11.2", ] @@ -7739,9 +7739,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.5.4" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" dependencies = [ "aho-corasick", "memchr", @@ -8479,7 +8479,7 @@ dependencies = [ "env_logger 0.9.0", "hex-literal", "lazy_static", - "lru 0.6.6", + "lru 0.7.3", "parity-scale-codec", "parking_lot 0.12.0", "paste 1.0.6", @@ -8690,7 +8690,7 @@ dependencies = [ "linked-hash-map", "linked_hash_set", "log 0.4.14", - "lru 0.7.0", + "lru 0.7.3", "parity-scale-codec", "parking_lot 0.12.0", "pin-project 1.0.10", @@ -8734,7 +8734,7 @@ dependencies = [ "futures-timer", "libp2p", "log 0.4.14", - "lru 0.7.0", + "lru 0.7.3", "quickcheck", "sc-network", "sp-runtime", @@ -9802,7 +9802,7 @@ version = "4.0.0-dev" dependencies = [ "futures 0.3.19", "log 0.4.14", - "lru 0.7.0", + "lru 0.7.3", "parity-scale-codec", "parking_lot 0.12.0", "sp-api", @@ -10931,9 +10931,9 @@ checksum = "3bf63baf9f5039dadc247375c29eb13706706cfde997d0330d05aa63a77d8820" [[package]] name = "thread_local" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd" +checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" dependencies = [ "once_cell", ] diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index 0e8cdfd7c3fe..a1aa695bf3a1 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -121,7 +121,7 @@ tempfile = "3.1.0" assert_cmd = "2.0.2" nix = "0.23" serde_json = "1.0" -regex = "1" +regex = "1.5.5" platforms = "2.0" async-std = { version = "1.10.0", features = ["attributes"] } soketto = "0.4.2" diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index 0fbb06e8aa4a..7725e25c0b81 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -22,7 +22,7 @@ libp2p = "0.40.0" log = "0.4.11" names = { version = "0.13.0", default-features = false } rand = "0.7.3" -regex = "1.5.4" +regex = "1.5.5" rpassword = "5.0.0" serde = "1.0.136" serde_json = "1.0.79" diff --git a/client/executor/Cargo.toml b/client/executor/Cargo.toml index cba5892eace1..34416b1e0d46 100644 --- a/client/executor/Cargo.toml +++ b/client/executor/Cargo.toml @@ -32,7 +32,7 @@ sc-executor-wasmi = { version = "0.10.0-dev", path = "wasmi" } sc-executor-wasmtime = { version = "0.10.0-dev", path = "wasmtime", optional = true } parking_lot = "0.12.0" sp-core-hashing-proc-macro = { version = "5.0.0", path = "../../primitives/core/hashing/proc-macro" } -lru = "0.6.6" +lru = "0.7.3" tracing = "0.1.29" [dev-dependencies] @@ -46,7 +46,7 @@ sp-maybe-compressed-blob = { version = "4.1.0-dev", path = "../../primitives/may sc-tracing = { version = "4.0.0-dev", path = "../tracing" } tracing-subscriber = "0.2.19" paste = "1.0" -regex = "1" +regex = "1.5.5" criterion = "0.3" env_logger = "0.9" diff --git a/client/network-gossip/Cargo.toml b/client/network-gossip/Cargo.toml index ade44dc94aa8..c8410d6d1878 100644 --- a/client/network-gossip/Cargo.toml +++ b/client/network-gossip/Cargo.toml @@ -19,7 +19,7 @@ futures = "0.3.19" futures-timer = "3.0.1" libp2p = { version = "0.40.0", default-features = false } log = "0.4.8" -lru = "0.7.0" +lru = "0.7.3" ahash = "0.7.6" prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.10.0-dev", path = "../../utils/prometheus" } sc-network = { version = "0.10.0-dev", path = "../network" } diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index d6bc90016ab8..cd33830c1efe 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -34,7 +34,7 @@ hex = "0.4.0" ip_network = "0.4.1" linked-hash-map = "0.5.4" linked_hash_set = "0.1.3" -lru = "0.7.0" +lru = "0.7.3" log = "0.4.8" parking_lot = "0.12.0" pin-project = "1.0.10" diff --git a/client/tracing/Cargo.toml b/client/tracing/Cargo.toml index 76cdcb4e4b02..599e310a8515 100644 --- a/client/tracing/Cargo.toml +++ b/client/tracing/Cargo.toml @@ -21,7 +21,7 @@ libc = "0.2.121" log = { version = "0.4.8" } once_cell = "1.8.0" parking_lot = "0.12.0" -regex = "1.5.4" +regex = "1.5.5" rustc-hash = "1.1.0" serde = "1.0.136" thiserror = "1.0.30" diff --git a/primitives/blockchain/Cargo.toml b/primitives/blockchain/Cargo.toml index bdb326bdb2e9..4c9946b7a312 100644 --- a/primitives/blockchain/Cargo.toml +++ b/primitives/blockchain/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] log = "0.4.11" -lru = "0.7.0" +lru = "0.7.3" parking_lot = "0.12.0" thiserror = "1.0.30" futures = "0.3.19" diff --git a/primitives/panic-handler/Cargo.toml b/primitives/panic-handler/Cargo.toml index abab34d29519..0155b6532876 100644 --- a/primitives/panic-handler/Cargo.toml +++ b/primitives/panic-handler/Cargo.toml @@ -15,5 +15,5 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] backtrace = "0.3.63" -regex = "1.5.4" +regex = "1.5.5" lazy_static = "1.4.0" From 62fa7d2aaeaabdc478ae3b0fab2929a0fcc89e40 Mon Sep 17 00:00:00 2001 From: Alexander Gryaznov Date: Tue, 29 Mar 2022 17:14:49 +0200 Subject: [PATCH 656/695] contracts: add `seal_code_hash` and `seal_own_code_hash` to API (#10933) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * `seal_origin` + tests added * `seal_origin` benchmark added * `seal_code_hash` + tests added * `seal_code_hash` benchmark added * `seal_own_code_hash` + tests added * `seal_own_code_hash` benchmark added * fmt lil fix * akward accident bug fix * Apply suggestions from code review Co-authored-by: Alexander Theißen * Apply suggestions from code review Co-authored-by: Alexander Theißen * benchmark fix * `WasmModule::getter()` to take `module_name` arg * test enhanced * fixes based on review feedback * Apply suggestions from code review Co-authored-by: Alexander Theißen * Hash left as const to return a ref to it from mock * HASH test val to local const in mock * Apply suggestions from code review Co-authored-by: Alexander Theißen * fixes to benchmarks according to review feedback * cargo run --quiet --profile=production --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_contracts --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/contracts/src/weights.rs --template=./.maintain/frame-weight-template.hbs * removed `seal_origin` from API Co-authored-by: Alexander Theißen Co-authored-by: Parity Bot --- frame/contracts/src/benchmarking/code.rs | 4 +- frame/contracts/src/benchmarking/mod.rs | 71 +- frame/contracts/src/exec.rs | 72 ++ frame/contracts/src/schedule.rs | 8 + frame/contracts/src/wasm/mod.rs | 120 ++- frame/contracts/src/wasm/runtime.rs | 48 + frame/contracts/src/weights.rs | 1242 +++++++++++----------- 7 files changed, 951 insertions(+), 614 deletions(-) diff --git a/frame/contracts/src/benchmarking/code.rs b/frame/contracts/src/benchmarking/code.rs index f9d71fde6588..2544fd6b7f92 100644 --- a/frame/contracts/src/benchmarking/code.rs +++ b/frame/contracts/src/benchmarking/code.rs @@ -339,12 +339,12 @@ where /// Creates a wasm module that calls the imported function named `getter_name` `repeat` /// times. The imported function is expected to have the "getter signature" of /// (out_ptr: u32, len_ptr: u32) -> (). - pub fn getter(getter_name: &'static str, repeat: u32) -> Self { + pub fn getter(module_name: &'static str, getter_name: &'static str, repeat: u32) -> Self { let pages = max_pages::(); ModuleDefinition { memory: Some(ImportedMemory::max::()), imported_functions: vec![ImportedFunction { - module: "seal0", + module: module_name, name: getter_name, params: vec![ValueType::I32, ValueType::I32], return_type: None, diff --git a/frame/contracts/src/benchmarking/mod.rs b/frame/contracts/src/benchmarking/mod.rs index 8539978bd6b3..de83f51a0152 100644 --- a/frame/contracts/src/benchmarking/mod.rs +++ b/frame/contracts/src/benchmarking/mod.rs @@ -394,7 +394,7 @@ benchmarks! { seal_caller { let r in 0 .. API_BENCHMARK_BATCHES; let instance = Contract::::new(WasmModule::getter( - "seal_caller", r * API_BENCHMARK_BATCH_SIZE + "seal0", "seal_caller", r * API_BENCHMARK_BATCH_SIZE ), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) @@ -436,6 +436,59 @@ benchmarks! { let origin = RawOrigin::Signed(instance.caller.clone()); }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + seal_code_hash { + let r in 0 .. API_BENCHMARK_BATCHES; + let accounts = (0 .. r * API_BENCHMARK_BATCH_SIZE) + .map(|n| account::("account", n, 0)) + .collect::>(); + let account_len = accounts.get(0).map(|i| i.encode().len()).unwrap_or(0); + let accounts_bytes = accounts.iter().map(|a| a.encode()).flatten().collect::>(); + let accounts_len = accounts_bytes.len(); + let pages = code::max_pages::(); + let code = WasmModule::::from(ModuleDefinition { + memory: Some(ImportedMemory::max::()), + imported_functions: vec![ImportedFunction { + module: "__unstable__", + name: "seal_code_hash", + params: vec![ValueType::I32, ValueType::I32, ValueType::I32], + return_type: Some(ValueType::I32), + }], + data_segments: vec![ + DataSegment { + offset: 0, + value: 32u32.to_le_bytes().to_vec(), // output length + }, + DataSegment { + offset: 36, + value: accounts_bytes, + }, + ], + call_body: Some(body::repeated_dyn(r * API_BENCHMARK_BATCH_SIZE, vec![ + Counter(36, account_len as u32), // address_ptr + Regular(Instruction::I32Const(4)), // ptr to output data + Regular(Instruction::I32Const(0)), // ptr to output length + Regular(Instruction::Call(0)), + Regular(Instruction::Drop), + ])), + .. Default::default() + }); + let instance = Contract::::new(code, vec![])?; + let info = instance.info()?; + // every account would be a contract (worst case) + for acc in accounts.iter() { + >::insert(acc, info.clone()); + } + let origin = RawOrigin::Signed(instance.caller.clone()); + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + + seal_own_code_hash { + let r in 0 .. API_BENCHMARK_BATCHES; + let instance = Contract::::new(WasmModule::getter( + "__unstable__", "seal_own_code_hash", r * API_BENCHMARK_BATCH_SIZE + ), vec![])?; + let origin = RawOrigin::Signed(instance.caller.clone()); + }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + seal_caller_is_origin { let r in 0 .. API_BENCHMARK_BATCHES; let code = WasmModule::::from(ModuleDefinition { @@ -459,7 +512,7 @@ benchmarks! { seal_address { let r in 0 .. API_BENCHMARK_BATCHES; let instance = Contract::::new(WasmModule::getter( - "seal_address", r * API_BENCHMARK_BATCH_SIZE + "seal0", "seal_address", r * API_BENCHMARK_BATCH_SIZE ), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) @@ -467,7 +520,7 @@ benchmarks! { seal_gas_left { let r in 0 .. API_BENCHMARK_BATCHES; let instance = Contract::::new(WasmModule::getter( - "seal_gas_left", r * API_BENCHMARK_BATCH_SIZE + "seal0", "seal_gas_left", r * API_BENCHMARK_BATCH_SIZE ), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) @@ -475,7 +528,7 @@ benchmarks! { seal_balance { let r in 0 .. API_BENCHMARK_BATCHES; let instance = Contract::::new(WasmModule::getter( - "seal_balance", r * API_BENCHMARK_BATCH_SIZE + "seal0", "seal_balance", r * API_BENCHMARK_BATCH_SIZE ), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) @@ -483,7 +536,7 @@ benchmarks! { seal_value_transferred { let r in 0 .. API_BENCHMARK_BATCHES; let instance = Contract::::new(WasmModule::getter( - "seal_value_transferred", r * API_BENCHMARK_BATCH_SIZE + "seal0", "seal_value_transferred", r * API_BENCHMARK_BATCH_SIZE ), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) @@ -491,7 +544,7 @@ benchmarks! { seal_minimum_balance { let r in 0 .. API_BENCHMARK_BATCHES; let instance = Contract::::new(WasmModule::getter( - "seal_minimum_balance", r * API_BENCHMARK_BATCH_SIZE + "seal0", "seal_minimum_balance", r * API_BENCHMARK_BATCH_SIZE ), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) @@ -499,7 +552,7 @@ benchmarks! { seal_block_number { let r in 0 .. API_BENCHMARK_BATCHES; let instance = Contract::::new(WasmModule::getter( - "seal_block_number", r * API_BENCHMARK_BATCH_SIZE + "seal0", "seal_block_number", r * API_BENCHMARK_BATCH_SIZE ), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) @@ -507,7 +560,7 @@ benchmarks! { seal_now { let r in 0 .. API_BENCHMARK_BATCHES; let instance = Contract::::new(WasmModule::getter( - "seal_now", r * API_BENCHMARK_BATCH_SIZE + "seal0", "seal_now", r * API_BENCHMARK_BATCH_SIZE ), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) @@ -2341,7 +2394,7 @@ benchmarks! { } // w_memory_grow = w_bench - 2 * w_param - // We can only allow allocate as much memory as it is allowed in a a contract. + // We can only allow allocate as much memory as it is allowed in a contract. // Therefore the repeat count is limited by the maximum memory any contract can have. // Using a contract with more memory will skew the benchmark because the runtime of grow // depends on how much memory is already allocated. diff --git a/frame/contracts/src/exec.rs b/frame/contracts/src/exec.rs index 455665687d97..e73b29e54378 100644 --- a/frame/contracts/src/exec.rs +++ b/frame/contracts/src/exec.rs @@ -162,6 +162,14 @@ pub trait Ext: sealing::Sealed { /// Check if a contract lives at the specified `address`. fn is_contract(&self, address: &AccountIdOf) -> bool; + /// Returns the code hash of the contract for the given `address`. + /// + /// Returns `None` if the `address` does not belong to a contract. + fn code_hash(&self, address: &AccountIdOf) -> Option>; + + /// Returns the code hash of the contract being executed. + fn own_code_hash(&mut self) -> &CodeHash; + /// Check if the caller of the current contract is the origin of the whole call stack. /// /// This can be checked with `is_contract(self.caller())` as well. @@ -1103,6 +1111,14 @@ where ContractInfoOf::::contains_key(&address) } + fn code_hash(&self, address: &T::AccountId) -> Option> { + >::get(&address).map(|contract| contract.code_hash) + } + + fn own_code_hash(&mut self) -> &CodeHash { + &self.top_frame_mut().contract_info().code_hash + } + fn caller_is_origin(&self) -> bool { self.caller() == &self.origin } @@ -1753,6 +1769,62 @@ mod tests { }); } + #[test] + fn code_hash_returns_proper_values() { + let code_bob = MockLoader::insert(Call, |ctx, _| { + // ALICE is not a contract and hence she does not have a code_hash + assert!(ctx.ext.code_hash(&ALICE).is_none()); + // BOB is a contract and hence he has a code_hash + assert!(ctx.ext.code_hash(&BOB).is_some()); + exec_success() + }); + + ExtBuilder::default().build().execute_with(|| { + let schedule = ::Schedule::get(); + place_contract(&BOB, code_bob); + let mut storage_meter = storage::meter::Meter::new(&ALICE, Some(0), 0).unwrap(); + // ALICE (not contract) -> BOB (contract) + let result = MockStack::run_call( + ALICE, + BOB, + &mut GasMeter::::new(GAS_LIMIT), + &mut storage_meter, + &schedule, + 0, + vec![0], + None, + ); + assert_matches!(result, Ok(_)); + }); + } + + #[test] + fn own_code_hash_returns_proper_values() { + let bob_ch = MockLoader::insert(Call, |ctx, _| { + let code_hash = ctx.ext.code_hash(&BOB).unwrap(); + assert_eq!(*ctx.ext.own_code_hash(), code_hash); + exec_success() + }); + + ExtBuilder::default().build().execute_with(|| { + let schedule = ::Schedule::get(); + place_contract(&BOB, bob_ch); + let mut storage_meter = storage::meter::Meter::new(&ALICE, Some(0), 0).unwrap(); + // ALICE (not contract) -> BOB (contract) + let result = MockStack::run_call( + ALICE, + BOB, + &mut GasMeter::::new(GAS_LIMIT), + &mut storage_meter, + &schedule, + 0, + vec![0], + None, + ); + assert_matches!(result, Ok(_)); + }); + } + #[test] fn caller_is_origin_returns_proper_values() { let code_charlie = MockLoader::insert(Call, |ctx, _| { diff --git a/frame/contracts/src/schedule.rs b/frame/contracts/src/schedule.rs index 8535166a6ac5..b0c58d721d57 100644 --- a/frame/contracts/src/schedule.rs +++ b/frame/contracts/src/schedule.rs @@ -265,6 +265,12 @@ pub struct HostFnWeights { /// Weight of calling `seal_is_contract`. pub is_contract: Weight, + /// Weight of calling `seal_code_hash`. + pub code_hash: Weight, + + /// Weight of calling `seal_own_code_hash`. + pub own_code_hash: Weight, + /// Weight of calling `seal_caller_is_origin`. pub caller_is_origin: Weight, @@ -584,6 +590,8 @@ impl Default for HostFnWeights { Self { caller: cost_batched!(seal_caller), is_contract: cost_batched!(seal_is_contract), + code_hash: cost_batched!(seal_code_hash), + own_code_hash: cost_batched!(seal_own_code_hash), caller_is_origin: cost_batched!(seal_caller_is_origin), address: cost_batched!(seal_address), gas_left: cost_batched!(seal_gas_left), diff --git a/frame/contracts/src/wasm/mod.rs b/frame/contracts/src/wasm/mod.rs index 3912a936684c..c38613cb6810 100644 --- a/frame/contracts/src/wasm/mod.rs +++ b/frame/contracts/src/wasm/mod.rs @@ -438,6 +438,13 @@ mod tests { fn is_contract(&self, _address: &AccountIdOf) -> bool { true } + fn code_hash(&self, _address: &AccountIdOf) -> Option> { + Some(H256::from_slice(&[0x11; 32])) + } + fn own_code_hash(&mut self) -> &CodeHash { + const HASH: H256 = H256::repeat_byte(0x10); + &HASH + } fn caller_is_origin(&self) -> bool { false } @@ -1155,7 +1162,7 @@ mod tests { ); } - /// calls `seal_caller` and compares the result with the constant 42. + /// calls `seal_caller` and compares the result with the constant (ALICE's address part). const CODE_CALLER: &str = r#" (module (import "seal0" "seal_caller" (func $seal_caller (param i32 i32))) @@ -1185,7 +1192,7 @@ mod tests { ) ) - ;; assert that the first 64 byte are the beginning of "ALICE" + ;; assert that the first 8 bytes are the beginning of "ALICE" (call $assert (i64.eq (i64.load (i32.const 0)) @@ -1203,7 +1210,7 @@ mod tests { assert_ok!(execute(CODE_CALLER, vec![], MockExt::default())); } - /// calls `seal_address` and compares the result with the constant 69. + /// calls `seal_address` and compares the result with the constant (BOB's address part). const CODE_ADDRESS: &str = r#" (module (import "seal0" "seal_address" (func $seal_address (param i32 i32))) @@ -1233,7 +1240,7 @@ mod tests { ) ) - ;; assert that the first 64 byte are the beginning of "BOB" + ;; assert that the first 8 bytes are the beginning of "BOB" (call $assert (i64.eq (i64.load (i32.const 0)) @@ -2361,6 +2368,111 @@ mod tests { } #[test] + #[cfg(feature = "unstable-interface")] + fn code_hash_works() { + /// calls `seal_code_hash` and compares the result with the constant. + const CODE_CODE_HASH: &str = r#" +(module + (import "__unstable__" "seal_code_hash" (func $seal_code_hash (param i32 i32 i32) (result i32))) + (import "env" "memory" (memory 1 1)) + + ;; size of our buffer is 32 bytes + (data (i32.const 32) "\20") + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func (export "call") + ;; fill the buffer with the code hash. + (call $seal_code_hash + (i32.const 0) ;; input: address_ptr (before call) + (i32.const 0) ;; output: code_hash_ptr (after call) + (i32.const 32) ;; same 32 bytes length for input and output + ) + + ;; assert size == 32 + (call $assert + (i32.eq + (i32.load (i32.const 32)) + (i32.const 32) + ) + ) + + ;; assert that the first 8 bytes are "1111111111111111" + (call $assert + (i64.eq + (i64.load (i32.const 0)) + (i64.const 0x1111111111111111) + ) + ) + drop + ) + + (func (export "deploy")) +) +"#; + assert_ok!(execute(CODE_CODE_HASH, vec![], MockExt::default())); + } + + #[test] + #[cfg(feature = "unstable-interface")] + fn own_code_hash_works() { + /// calls `seal_own_code_hash` and compares the result with the constant. + const CODE_OWN_CODE_HASH: &str = r#" +(module + (import "__unstable__" "seal_own_code_hash" (func $seal_own_code_hash (param i32 i32))) + (import "env" "memory" (memory 1 1)) + + ;; size of our buffer is 32 bytes + (data (i32.const 32) "\20") + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func (export "call") + ;; fill the buffer with the code hash + (call $seal_own_code_hash + (i32.const 0) ;; output: code_hash_ptr + (i32.const 32) ;; 32 bytes length of code_hash output + ) + + ;; assert size == 32 + (call $assert + (i32.eq + (i32.load (i32.const 32)) + (i32.const 32) + ) + ) + + ;; assert that the first 8 bytes are "1010101010101010" + (call $assert + (i64.eq + (i64.load (i32.const 0)) + (i64.const 0x1010101010101010) + ) + ) + ) + + (func (export "deploy")) +) +"#; + assert_ok!(execute(CODE_OWN_CODE_HASH, vec![], MockExt::default())); + } + + #[test] + #[cfg(feature = "unstable-interface")] fn caller_is_origin_works() { const CODE_CALLER_IS_ORIGIN: &str = r#" ;; This runs `caller_is_origin` check on zero account address diff --git a/frame/contracts/src/wasm/runtime.rs b/frame/contracts/src/wasm/runtime.rs index 043b45e6a76e..975cfcdd12db 100644 --- a/frame/contracts/src/wasm/runtime.rs +++ b/frame/contracts/src/wasm/runtime.rs @@ -144,6 +144,12 @@ pub enum RuntimeCosts { Caller, /// Weight of calling `seal_is_contract`. IsContract, + /// Weight of calling `seal_code_hash`. + #[cfg(feature = "unstable-interface")] + CodeHash, + /// Weight of calling `seal_own_code_hash`. + #[cfg(feature = "unstable-interface")] + OwnCodeHash, /// Weight of calling `seal_caller_is_origin`. CallerIsOrigin, /// Weight of calling `seal_address`. @@ -234,6 +240,10 @@ impl RuntimeCosts { CopyToContract(len) => s.input_per_byte.saturating_mul(len.into()), Caller => s.caller, IsContract => s.is_contract, + #[cfg(feature = "unstable-interface")] + CodeHash => s.code_hash, + #[cfg(feature = "unstable-interface")] + OwnCodeHash => s.own_code_hash, CallerIsOrigin => s.caller_is_origin, Address => s.address, GasLeft => s.gas_left, @@ -1371,6 +1381,44 @@ define_env!(Env, , Ok(ctx.ext.is_contract(&address) as u32) }, + // Retrieve the code hash for a specified contract address. + // + // # Parameters + // + // - `account_ptr`: a pointer to the address in question. + // Should be decodable as an `T::AccountId`. Traps otherwise. + // - `out_ptr`: pointer to the linear memory where the returning value is written to. + // - `out_len_ptr`: in-out pointer into linear memory where the buffer length + // is read from and the value length is written to. + // + // # Errors + // + // `ReturnCode::KeyNotFound` + [__unstable__] seal_code_hash(ctx, account_ptr: u32, out_ptr: u32, out_len_ptr: u32) -> ReturnCode => { + ctx.charge_gas(RuntimeCosts::CodeHash)?; + let address: <::T as frame_system::Config>::AccountId = + ctx.read_sandbox_memory_as(account_ptr)?; + if let Some(value) = ctx.ext.code_hash(&address) { + ctx.write_sandbox_output(out_ptr, out_len_ptr, &value.encode(), false, already_charged)?; + Ok(ReturnCode::Success) + } else { + Ok(ReturnCode::KeyNotFound) + } + }, + + // Retrieve the code hash of the currently executing contract. + // + // # Parameters + // + // - `out_ptr`: pointer to the linear memory where the returning value is written to. + // - `out_len_ptr`: in-out pointer into linear memory where the buffer length + // is read from and the value length is written to. + [__unstable__] seal_own_code_hash(ctx, out_ptr: u32, out_len_ptr: u32) => { + ctx.charge_gas(RuntimeCosts::OwnCodeHash)?; + let code_hash_encoded = &ctx.ext.own_code_hash().encode(); + Ok(ctx.write_sandbox_output(out_ptr, out_len_ptr, code_hash_encoded, false, already_charged)?) + }, + // Checks whether the caller of the current contract is the origin of the whole call stack. // // Prefer this over `seal_is_contract` when checking whether your contract is being called by a contract diff --git a/frame/contracts/src/weights.rs b/frame/contracts/src/weights.rs index b438ad51cbfc..43f00196ab3b 100644 --- a/frame/contracts/src/weights.rs +++ b/frame/contracts/src/weights.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_contracts //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-02-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -56,6 +56,8 @@ pub trait WeightInfo { fn remove_code() -> Weight; fn seal_caller(r: u32, ) -> Weight; fn seal_is_contract(r: u32, ) -> Weight; + fn seal_code_hash(r: u32, ) -> Weight; + fn seal_own_code_hash(r: u32, ) -> Weight; fn seal_caller_is_origin(r: u32, ) -> Weight; fn seal_address(r: u32, ) -> Weight; fn seal_gas_left(r: u32, ) -> Weight; @@ -160,14 +162,14 @@ pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize() -> Weight { - (1_512_000 as Weight) + (1_569_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn on_initialize_per_trie_key(k: u32, ) -> Weight { - (8_089_000 as Weight) + (9_620_000 as Weight) // Standard Error: 0 - .saturating_add((741_000 as Weight).saturating_mul(k as Weight)) + .saturating_add((748_000 as Weight).saturating_mul(k as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) @@ -175,17 +177,17 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize_per_queue_item(q: u32, ) -> Weight { (0 as Weight) - // Standard Error: 5_000 - .saturating_add((2_287_000 as Weight).saturating_mul(q as Weight)) + // Standard Error: 4_000 + .saturating_add((1_795_000 as Weight).saturating_mul(q as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Contracts PristineCode (r:1 w:0) // Storage: Contracts CodeStorage (r:0 w:1) fn reinstrument(c: u32, ) -> Weight { - (15_212_000 as Weight) + (12_256_000 as Weight) // Standard Error: 0 - .saturating_add((51_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((49_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -194,9 +196,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call_with_code_per_byte(c: u32, ) -> Weight { - (218_406_000 as Weight) + (213_494_000 as Weight) // Standard Error: 0 - .saturating_add((55_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((53_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -208,9 +210,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn instantiate_with_code(c: u32, s: u32, ) -> Weight { - (265_773_000 as Weight) + (231_180_000 as Weight) // Standard Error: 0 - .saturating_add((127_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((125_000 as Weight).saturating_mul(c as Weight)) // Standard Error: 0 .saturating_add((2_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) @@ -223,7 +225,7 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn instantiate(s: u32, ) -> Weight { - (173_852_000 as Weight) + (172_238_000 as Weight) // Standard Error: 0 .saturating_add((2_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) @@ -234,7 +236,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call() -> Weight { - (140_088_000 as Weight) + (140_912_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -242,9 +244,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn upload_code(c: u32, ) -> Weight { - (44_290_000 as Weight) + (42_493_000 as Weight) // Standard Error: 0 - .saturating_add((51_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((49_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -252,7 +254,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:0 w:1) // Storage: Contracts PristineCode (r:0 w:1) fn remove_code() -> Weight { - (24_364_000 as Weight) + (24_533_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -261,9 +263,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_caller(r: u32, ) -> Weight { - (219_617_000 as Weight) - // Standard Error: 119_000 - .saturating_add((50_409_000 as Weight).saturating_mul(r as Weight)) + (220_009_000 as Weight) + // Standard Error: 80_000 + .saturating_add((47_887_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -272,9 +274,21 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_is_contract(r: u32, ) -> Weight { - (102_073_000 as Weight) - // Standard Error: 843_000 - .saturating_add((369_025_000 as Weight).saturating_mul(r as Weight)) + (71_779_000 as Weight) + // Standard Error: 900_000 + .saturating_add((371_278_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + // Storage: System Account (r:1 w:0) + // Storage: Contracts ContractInfoOf (r:1 w:1) + // Storage: Contracts CodeStorage (r:1 w:0) + // Storage: Timestamp Now (r:1 w:0) + fn seal_code_hash(r: u32, ) -> Weight { + (0 as Weight) + // Standard Error: 2_329_000 + .saturating_add((451_731_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -283,10 +297,21 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) + fn seal_own_code_hash(r: u32, ) -> Weight { + (227_824_000 as Weight) + // Standard Error: 128_000 + .saturating_add((52_843_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + // Storage: System Account (r:1 w:0) + // Storage: Contracts ContractInfoOf (r:1 w:1) + // Storage: Contracts CodeStorage (r:1 w:0) + // Storage: Timestamp Now (r:1 w:0) fn seal_caller_is_origin(r: u32, ) -> Weight { - (213_550_000 as Weight) - // Standard Error: 63_000 - .saturating_add((21_519_000 as Weight).saturating_mul(r as Weight)) + (213_057_000 as Weight) + // Standard Error: 43_000 + .saturating_add((21_023_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -295,9 +320,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_address(r: u32, ) -> Weight { - (220_649_000 as Weight) - // Standard Error: 95_000 - .saturating_add((50_197_000 as Weight).saturating_mul(r as Weight)) + (219_066_000 as Weight) + // Standard Error: 117_000 + .saturating_add((48_056_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -306,9 +331,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas_left(r: u32, ) -> Weight { - (218_190_000 as Weight) - // Standard Error: 99_000 - .saturating_add((49_817_000 as Weight).saturating_mul(r as Weight)) + (218_844_000 as Weight) + // Standard Error: 101_000 + .saturating_add((47_325_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -317,9 +342,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_balance(r: u32, ) -> Weight { - (223_133_000 as Weight) - // Standard Error: 188_000 - .saturating_add((142_288_000 as Weight).saturating_mul(r as Weight)) + (219_234_000 as Weight) + // Standard Error: 171_000 + .saturating_add((142_534_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -328,9 +353,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_value_transferred(r: u32, ) -> Weight { - (216_612_000 as Weight) - // Standard Error: 103_000 - .saturating_add((49_956_000 as Weight).saturating_mul(r as Weight)) + (215_128_000 as Weight) + // Standard Error: 119_000 + .saturating_add((48_392_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -339,9 +364,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_minimum_balance(r: u32, ) -> Weight { - (218_349_000 as Weight) - // Standard Error: 93_000 - .saturating_add((49_656_000 as Weight).saturating_mul(r as Weight)) + (214_603_000 as Weight) + // Standard Error: 115_000 + .saturating_add((48_041_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -350,9 +375,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_block_number(r: u32, ) -> Weight { - (213_151_000 as Weight) - // Standard Error: 110_000 - .saturating_add((50_099_000 as Weight).saturating_mul(r as Weight)) + (214_091_000 as Weight) + // Standard Error: 126_000 + .saturating_add((48_067_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -361,9 +386,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_now(r: u32, ) -> Weight { - (216_816_000 as Weight) - // Standard Error: 95_000 - .saturating_add((49_724_000 as Weight).saturating_mul(r as Weight)) + (214_418_000 as Weight) + // Standard Error: 100_000 + .saturating_add((47_791_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -373,9 +398,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0) fn seal_weight_to_fee(r: u32, ) -> Weight { - (223_053_000 as Weight) - // Standard Error: 148_000 - .saturating_add((124_240_000 as Weight).saturating_mul(r as Weight)) + (229_261_000 as Weight) + // Standard Error: 150_000 + .saturating_add((121_988_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -384,9 +409,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas(r: u32, ) -> Weight { - (127_253_000 as Weight) - // Standard Error: 27_000 - .saturating_add((25_608_000 as Weight).saturating_mul(r as Weight)) + (127_983_000 as Weight) + // Standard Error: 56_000 + .saturating_add((24_016_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -395,9 +420,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input(r: u32, ) -> Weight { - (218_057_000 as Weight) - // Standard Error: 98_000 - .saturating_add((49_061_000 as Weight).saturating_mul(r as Weight)) + (216_634_000 as Weight) + // Standard Error: 114_000 + .saturating_add((46_864_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -406,9 +431,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input_per_kb(n: u32, ) -> Weight { - (293_563_000 as Weight) - // Standard Error: 3_000 - .saturating_add((11_877_000 as Weight).saturating_mul(n as Weight)) + (285_180_000 as Weight) + // Standard Error: 4_000 + .saturating_add((11_899_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -416,10 +441,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) - fn seal_return(r: u32, ) -> Weight { - (211_511_000 as Weight) - // Standard Error: 70_000 - .saturating_add((2_085_000 as Weight).saturating_mul(r as Weight)) + fn seal_return(_r: u32, ) -> Weight { + (215_379_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -428,9 +451,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return_per_kb(n: u32, ) -> Weight { - (213_876_000 as Weight) + (213_957_000 as Weight) // Standard Error: 0 - .saturating_add((193_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((201_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -441,9 +464,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts DeletionQueue (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_terminate(r: u32, ) -> Weight { - (214_736_000 as Weight) - // Standard Error: 206_000 - .saturating_add((53_637_000 as Weight).saturating_mul(r as Weight)) + (215_782_000 as Weight) + // Standard Error: 149_000 + .saturating_add((52_421_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((4 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -455,9 +478,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) fn seal_random(r: u32, ) -> Weight { - (222_037_000 as Weight) - // Standard Error: 191_000 - .saturating_add((160_114_000 as Weight).saturating_mul(r as Weight)) + (217_910_000 as Weight) + // Standard Error: 149_000 + .saturating_add((157_525_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -466,9 +489,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_deposit_event(r: u32, ) -> Weight { - (219_211_000 as Weight) - // Standard Error: 239_000 - .saturating_add((296_722_000 as Weight).saturating_mul(r as Weight)) + (230_787_000 as Weight) + // Standard Error: 210_000 + .saturating_add((296_973_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -478,11 +501,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) // Storage: System EventTopics (r:100 w:100) fn seal_deposit_event_per_topic_and_kb(t: u32, n: u32, ) -> Weight { - (519_643_000 as Weight) - // Standard Error: 1_842_000 - .saturating_add((300_853_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 363_000 - .saturating_add((82_577_000 as Weight).saturating_mul(n as Weight)) + (539_238_000 as Weight) + // Standard Error: 1_701_000 + .saturating_add((294_348_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 335_000 + .saturating_add((82_116_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(t as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -493,17 +516,17 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_debug_message(r: u32, ) -> Weight { - (132_710_000 as Weight) - // Standard Error: 77_000 - .saturating_add((41_623_000 as Weight).saturating_mul(r as Weight)) + (135_081_000 as Weight) + // Standard Error: 94_000 + .saturating_add((39_247_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage(r: u32, ) -> Weight { - (40_644_000 as Weight) - // Standard Error: 1_072_000 - .saturating_add((412_308_000 as Weight).saturating_mul(r as Weight)) + (41_752_000 as Weight) + // Standard Error: 1_107_000 + .saturating_add((403_473_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -511,25 +534,25 @@ impl WeightInfo for SubstrateWeight { } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage_per_new_kb(n: u32, ) -> Weight { - (609_052_000 as Weight) - // Standard Error: 258_000 - .saturating_add((28_633_000 as Weight).saturating_mul(n as Weight)) + (602_028_000 as Weight) + // Standard Error: 255_000 + .saturating_add((28_303_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage_per_old_kb(n: u32, ) -> Weight { - (629_665_000 as Weight) - // Standard Error: 300_000 - .saturating_add((10_947_000 as Weight).saturating_mul(n as Weight)) + (620_964_000 as Weight) + // Standard Error: 308_000 + .saturating_add((11_338_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage(r: u32, ) -> Weight { - (91_519_000 as Weight) - // Standard Error: 889_000 - .saturating_add((386_498_000 as Weight).saturating_mul(r as Weight)) + (88_113_000 as Weight) + // Standard Error: 851_000 + .saturating_add((381_671_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -537,51 +560,51 @@ impl WeightInfo for SubstrateWeight { } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage_per_kb(n: u32, ) -> Weight { - (612_224_000 as Weight) - // Standard Error: 269_000 - .saturating_add((10_709_000 as Weight).saturating_mul(n as Weight)) + (603_193_000 as Weight) + // Standard Error: 262_000 + .saturating_add((10_286_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage(r: u32, ) -> Weight { - (112_236_000 as Weight) - // Standard Error: 624_000 - .saturating_add((327_655_000 as Weight).saturating_mul(r as Weight)) + (112_477_000 as Weight) + // Standard Error: 666_000 + .saturating_add((324_824_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage_per_kb(n: u32, ) -> Weight { - (567_711_000 as Weight) - // Standard Error: 387_000 - .saturating_add((63_984_000 as Weight).saturating_mul(n as Weight)) + (564_781_000 as Weight) + // Standard Error: 403_000 + .saturating_add((63_824_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(104 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_contains_storage(r: u32, ) -> Weight { - (109_996_000 as Weight) - // Standard Error: 681_000 - .saturating_add((298_317_000 as Weight).saturating_mul(r as Weight)) + (115_207_000 as Weight) + // Standard Error: 672_000 + .saturating_add((290_919_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_contains_storage_per_kb(n: u32, ) -> Weight { - (518_342_000 as Weight) - // Standard Error: 251_000 - .saturating_add((9_666_000 as Weight).saturating_mul(n as Weight)) + (511_026_000 as Weight) + // Standard Error: 224_000 + .saturating_add((10_138_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(104 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage(r: u32, ) -> Weight { - (75_974_000 as Weight) - // Standard Error: 1_000_000 - .saturating_add((417_954_000 as Weight).saturating_mul(r as Weight)) + (79_113_000 as Weight) + // Standard Error: 904_000 + .saturating_add((417_022_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -589,9 +612,9 @@ impl WeightInfo for SubstrateWeight { } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage_per_kb(n: u32, ) -> Weight { - (653_188_000 as Weight) - // Standard Error: 333_000 - .saturating_add((64_810_000 as Weight).saturating_mul(n as Weight)) + (651_769_000 as Weight) + // Standard Error: 338_000 + .saturating_add((65_576_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().writes(103 as Weight)) } @@ -600,9 +623,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_transfer(r: u32, ) -> Weight { - (127_056_000 as Weight) - // Standard Error: 1_106_000 - .saturating_add((1_784_183_000 as Weight).saturating_mul(r as Weight)) + (93_588_000 as Weight) + // Standard Error: 1_444_000 + .saturating_add((1_803_217_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -614,8 +637,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) fn seal_call(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 2_621_000 - .saturating_add((19_757_765_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 3_050_000 + .saturating_add((19_925_209_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -627,8 +650,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Timestamp Now (r:1 w:0) fn seal_delegate_call(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 6_286_000 - .saturating_add((19_798_229_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 7_377_000 + .saturating_add((19_978_301_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads((99 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -637,11 +660,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:2 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_call_per_transfer_clone_kb(t: u32, c: u32, ) -> Weight { - (10_922_130_000 as Weight) - // Standard Error: 15_556_000 - .saturating_add((1_672_276_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 6_000 - .saturating_add((11_984_000 as Weight).saturating_mul(c as Weight)) + (11_124_804_000 as Weight) + // Standard Error: 21_475_000 + .saturating_add((1_635_442_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 9_000 + .saturating_add((11_981_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(105 as Weight)) .saturating_add(T::DbWeight::get().reads((101 as Weight).saturating_mul(t as Weight))) .saturating_add(T::DbWeight::get().writes(101 as Weight)) @@ -655,8 +678,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts OwnerInfoOf (r:100 w:100) fn seal_instantiate(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 46_147_000 - .saturating_add((27_589_519_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 47_682_000 + .saturating_add((27_883_754_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().reads((400 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -669,11 +692,11 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts Nonce (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_instantiate_per_transfer_salt_kb(t: u32, s: u32, ) -> Weight { - (14_790_752_000 as Weight) - // Standard Error: 37_838_000 - .saturating_add((714_016_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 17_000 - .saturating_add((155_605_000 as Weight).saturating_mul(s as Weight)) + (14_824_308_000 as Weight) + // Standard Error: 39_823_000 + .saturating_add((880_630_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 18_000 + .saturating_add((156_232_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(207 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(t as Weight))) .saturating_add(T::DbWeight::get().writes(205 as Weight)) @@ -684,9 +707,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256(r: u32, ) -> Weight { - (216_547_000 as Weight) - // Standard Error: 126_000 - .saturating_add((81_132_000 as Weight).saturating_mul(r as Weight)) + (218_378_000 as Weight) + // Standard Error: 131_000 + .saturating_add((78_260_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -695,9 +718,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256_per_kb(n: u32, ) -> Weight { - (459_912_000 as Weight) - // Standard Error: 27_000 - .saturating_add((464_750_000 as Weight).saturating_mul(n as Weight)) + (202_849_000 as Weight) + // Standard Error: 61_000 + .saturating_add((466_532_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -706,9 +729,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256(r: u32, ) -> Weight { - (212_653_000 as Weight) + (220_258_000 as Weight) // Standard Error: 147_000 - .saturating_add((93_380_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((90_363_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -717,9 +740,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256_per_kb(n: u32, ) -> Weight { - (324_536_000 as Weight) - // Standard Error: 20_000 - .saturating_add((306_160_000 as Weight).saturating_mul(n as Weight)) + (232_371_000 as Weight) + // Standard Error: 23_000 + .saturating_add((307_036_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -728,9 +751,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256(r: u32, ) -> Weight { - (218_574_000 as Weight) - // Standard Error: 123_000 - .saturating_add((65_035_000 as Weight).saturating_mul(r as Weight)) + (217_991_000 as Weight) + // Standard Error: 124_000 + .saturating_add((62_273_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -739,9 +762,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256_per_kb(n: u32, ) -> Weight { - (345_804_000 as Weight) - // Standard Error: 14_000 - .saturating_add((118_896_000 as Weight).saturating_mul(n as Weight)) + (396_282_000 as Weight) + // Standard Error: 13_000 + .saturating_add((119_575_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -750,9 +773,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128(r: u32, ) -> Weight { - (215_898_000 as Weight) - // Standard Error: 108_000 - .saturating_add((64_332_000 as Weight).saturating_mul(r as Weight)) + (217_578_000 as Weight) + // Standard Error: 104_000 + .saturating_add((62_189_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -761,9 +784,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128_per_kb(n: u32, ) -> Weight { - (351_569_000 as Weight) - // Standard Error: 18_000 - .saturating_add((118_896_000 as Weight).saturating_mul(n as Weight)) + (358_167_000 as Weight) + // Standard Error: 15_000 + .saturating_add((119_692_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -772,9 +795,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_ecdsa_recover(r: u32, ) -> Weight { - (272_893_000 as Weight) - // Standard Error: 1_438_000 - .saturating_add((15_412_877_000 as Weight).saturating_mul(r as Weight)) + (292_884_000 as Weight) + // Standard Error: 683_000 + .saturating_add((3_824_902_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -785,265 +808,265 @@ impl WeightInfo for SubstrateWeight { // Storage: Contracts OwnerInfoOf (r:36 w:36) fn seal_set_code_hash(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 2_132_000 - .saturating_add((937_623_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 2_302_000 + .saturating_add((922_467_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads((99 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes((99 as Weight).saturating_mul(r as Weight))) } fn instr_i64const(r: u32, ) -> Weight { - (74_268_000 as Weight) + (74_516_000 as Weight) // Standard Error: 1_000 - .saturating_add((595_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((592_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64load(r: u32, ) -> Weight { - (74_515_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_300_000 as Weight).saturating_mul(r as Weight)) + (74_430_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_320_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64store(r: u32, ) -> Weight { - (74_217_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_411_000 as Weight).saturating_mul(r as Weight)) + (74_440_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_428_000 as Weight).saturating_mul(r as Weight)) } fn instr_select(r: u32, ) -> Weight { - (73_689_000 as Weight) - // Standard Error: 4_000 - .saturating_add((1_792_000 as Weight).saturating_mul(r as Weight)) + (74_151_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_782_000 as Weight).saturating_mul(r as Weight)) } fn instr_if(r: u32, ) -> Weight { - (73_755_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_899_000 as Weight).saturating_mul(r as Weight)) + (74_225_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_887_000 as Weight).saturating_mul(r as Weight)) } fn instr_br(r: u32, ) -> Weight { - (73_735_000 as Weight) - // Standard Error: 0 - .saturating_add((903_000 as Weight).saturating_mul(r as Weight)) + (73_987_000 as Weight) + // Standard Error: 1_000 + .saturating_add((898_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_if(r: u32, ) -> Weight { - (73_595_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_448_000 as Weight).saturating_mul(r as Weight)) + (73_305_000 as Weight) + // Standard Error: 4_000 + .saturating_add((1_465_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table(r: u32, ) -> Weight { - (73_524_000 as Weight) + (73_037_000 as Weight) // Standard Error: 3_000 - .saturating_add((1_572_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_605_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table_per_entry(e: u32, ) -> Weight { - (76_361_000 as Weight) + (76_434_000 as Weight) // Standard Error: 0 .saturating_add((4_000 as Weight).saturating_mul(e as Weight)) } fn instr_call(r: u32, ) -> Weight { - (76_131_000 as Weight) - // Standard Error: 7_000 - .saturating_add((7_271_000 as Weight).saturating_mul(r as Weight)) + (75_461_000 as Weight) + // Standard Error: 10_000 + .saturating_add((7_446_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect(r: u32, ) -> Weight { - (87_948_000 as Weight) - // Standard Error: 14_000 - .saturating_add((9_429_000 as Weight).saturating_mul(r as Weight)) + (87_222_000 as Weight) + // Standard Error: 15_000 + .saturating_add((9_406_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect_per_param(p: u32, ) -> Weight { - (98_091_000 as Weight) + (97_204_000 as Weight) // Standard Error: 1_000 - .saturating_add((481_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((472_000 as Weight).saturating_mul(p as Weight)) } fn instr_local_get(r: u32, ) -> Weight { - (74_311_000 as Weight) + (75_299_000 as Weight) // Standard Error: 1_000 - .saturating_add((627_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((601_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_set(r: u32, ) -> Weight { - (74_701_000 as Weight) - // Standard Error: 1_000 - .saturating_add((677_000 as Weight).saturating_mul(r as Weight)) + (74_827_000 as Weight) + // Standard Error: 3_000 + .saturating_add((686_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_tee(r: u32, ) -> Weight { - (74_645_000 as Weight) - // Standard Error: 1_000 - .saturating_add((890_000 as Weight).saturating_mul(r as Weight)) + (74_624_000 as Weight) + // Standard Error: 2_000 + .saturating_add((895_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_get(r: u32, ) -> Weight { - (77_130_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_156_000 as Weight).saturating_mul(r as Weight)) + (77_435_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_201_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_set(r: u32, ) -> Weight { - (77_199_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_366_000 as Weight).saturating_mul(r as Weight)) + (76_693_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_410_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_current(r: u32, ) -> Weight { - (74_024_000 as Weight) - // Standard Error: 2_000 - .saturating_add((675_000 as Weight).saturating_mul(r as Weight)) + (74_244_000 as Weight) + // Standard Error: 1_000 + .saturating_add((660_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_grow(r: u32, ) -> Weight { - (75_226_000 as Weight) - // Standard Error: 170_000 - .saturating_add((186_225_000 as Weight).saturating_mul(r as Weight)) + (73_527_000 as Weight) + // Standard Error: 931_000 + .saturating_add((184_946_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64clz(r: u32, ) -> Weight { - (74_307_000 as Weight) - // Standard Error: 2_000 - .saturating_add((896_000 as Weight).saturating_mul(r as Weight)) + (74_181_000 as Weight) + // Standard Error: 6_000 + .saturating_add((906_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ctz(r: u32, ) -> Weight { - (74_408_000 as Weight) - // Standard Error: 3_000 - .saturating_add((895_000 as Weight).saturating_mul(r as Weight)) + (74_339_000 as Weight) + // Standard Error: 1_000 + .saturating_add((896_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64popcnt(r: u32, ) -> Weight { - (74_418_000 as Weight) - // Standard Error: 1_000 - .saturating_add((885_000 as Weight).saturating_mul(r as Weight)) + (74_444_000 as Weight) + // Standard Error: 3_000 + .saturating_add((889_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eqz(r: u32, ) -> Weight { - (74_130_000 as Weight) - // Standard Error: 2_000 - .saturating_add((920_000 as Weight).saturating_mul(r as Weight)) + (74_572_000 as Weight) + // Standard Error: 1_000 + .saturating_add((908_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendsi32(r: u32, ) -> Weight { - (74_318_000 as Weight) + (74_349_000 as Weight) // Standard Error: 2_000 - .saturating_add((876_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((881_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendui32(r: u32, ) -> Weight { - (74_496_000 as Weight) + (74_426_000 as Weight) // Standard Error: 1_000 - .saturating_add((871_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((875_000 as Weight).saturating_mul(r as Weight)) } fn instr_i32wrapi64(r: u32, ) -> Weight { - (73_938_000 as Weight) - // Standard Error: 0 - .saturating_add((897_000 as Weight).saturating_mul(r as Weight)) + (74_172_000 as Weight) + // Standard Error: 2_000 + .saturating_add((906_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eq(r: u32, ) -> Weight { - (73_943_000 as Weight) + (74_169_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_367_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_362_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ne(r: u32, ) -> Weight { - (74_305_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_353_000 as Weight).saturating_mul(r as Weight)) + (74_205_000 as Weight) + // Standard Error: 4_000 + .saturating_add((1_360_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64lts(r: u32, ) -> Weight { - (73_948_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_361_000 as Weight).saturating_mul(r as Weight)) + (74_237_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_356_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ltu(r: u32, ) -> Weight { - (74_188_000 as Weight) - // Standard Error: 4_000 - .saturating_add((1_354_000 as Weight).saturating_mul(r as Weight)) + (74_181_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_357_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gts(r: u32, ) -> Weight { - (74_156_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_353_000 as Weight).saturating_mul(r as Weight)) + (74_038_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_360_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gtu(r: u32, ) -> Weight { - (73_972_000 as Weight) - // Standard Error: 0 - .saturating_add((1_365_000 as Weight).saturating_mul(r as Weight)) + (73_881_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_372_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64les(r: u32, ) -> Weight { - (74_082_000 as Weight) - // Standard Error: 5_000 - .saturating_add((1_360_000 as Weight).saturating_mul(r as Weight)) + (73_969_000 as Weight) + // Standard Error: 0 + .saturating_add((1_361_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64leu(r: u32, ) -> Weight { - (74_190_000 as Weight) - // Standard Error: 1_000 + (74_497_000 as Weight) + // Standard Error: 3_000 .saturating_add((1_359_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ges(r: u32, ) -> Weight { - (73_803_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_370_000 as Weight).saturating_mul(r as Weight)) + (74_275_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_354_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64geu(r: u32, ) -> Weight { - (74_063_000 as Weight) - // Standard Error: 1_000 + (74_349_000 as Weight) + // Standard Error: 3_000 .saturating_add((1_357_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64add(r: u32, ) -> Weight { - (73_750_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_345_000 as Weight).saturating_mul(r as Weight)) + (74_192_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_333_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64sub(r: u32, ) -> Weight { - (73_979_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_341_000 as Weight).saturating_mul(r as Weight)) + (74_271_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_340_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64mul(r: u32, ) -> Weight { - (74_197_000 as Weight) - // Standard Error: 4_000 - .saturating_add((1_332_000 as Weight).saturating_mul(r as Weight)) + (73_971_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_340_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divs(r: u32, ) -> Weight { - (73_624_000 as Weight) - // Standard Error: 5_000 - .saturating_add((2_020_000 as Weight).saturating_mul(r as Weight)) + (74_546_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_995_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divu(r: u32, ) -> Weight { - (74_074_000 as Weight) + (74_194_000 as Weight) // Standard Error: 2_000 .saturating_add((2_050_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rems(r: u32, ) -> Weight { - (73_766_000 as Weight) - // Standard Error: 5_000 - .saturating_add((2_016_000 as Weight).saturating_mul(r as Weight)) + (74_106_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_997_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64remu(r: u32, ) -> Weight { - (73_978_000 as Weight) - // Standard Error: 3_000 - .saturating_add((2_064_000 as Weight).saturating_mul(r as Weight)) + (74_219_000 as Weight) + // Standard Error: 5_000 + .saturating_add((2_061_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64and(r: u32, ) -> Weight { - (73_996_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_336_000 as Weight).saturating_mul(r as Weight)) + (74_157_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_338_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64or(r: u32, ) -> Weight { - (74_058_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_335_000 as Weight).saturating_mul(r as Weight)) + (74_135_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_336_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64xor(r: u32, ) -> Weight { - (73_983_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_337_000 as Weight).saturating_mul(r as Weight)) + (74_038_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_345_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shl(r: u32, ) -> Weight { - (74_061_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_351_000 as Weight).saturating_mul(r as Weight)) + (74_011_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_362_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shrs(r: u32, ) -> Weight { - (73_940_000 as Weight) - // Standard Error: 5_000 - .saturating_add((1_360_000 as Weight).saturating_mul(r as Weight)) + (74_054_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_356_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shru(r: u32, ) -> Weight { - (73_954_000 as Weight) + (73_900_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_359_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_358_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotl(r: u32, ) -> Weight { - (74_026_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_354_000 as Weight).saturating_mul(r as Weight)) + (73_948_000 as Weight) + // Standard Error: 0 + .saturating_add((1_357_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotr(r: u32, ) -> Weight { - (74_149_000 as Weight) + (73_972_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_352_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_358_000 as Weight).saturating_mul(r as Weight)) } } @@ -1051,14 +1074,14 @@ impl WeightInfo for SubstrateWeight { impl WeightInfo for () { // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize() -> Weight { - (1_512_000 as Weight) + (1_569_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn on_initialize_per_trie_key(k: u32, ) -> Weight { - (8_089_000 as Weight) + (9_620_000 as Weight) // Standard Error: 0 - .saturating_add((741_000 as Weight).saturating_mul(k as Weight)) + .saturating_add((748_000 as Weight).saturating_mul(k as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(k as Weight))) @@ -1066,17 +1089,17 @@ impl WeightInfo for () { // Storage: Contracts DeletionQueue (r:1 w:0) fn on_initialize_per_queue_item(q: u32, ) -> Weight { (0 as Weight) - // Standard Error: 5_000 - .saturating_add((2_287_000 as Weight).saturating_mul(q as Weight)) + // Standard Error: 4_000 + .saturating_add((1_795_000 as Weight).saturating_mul(q as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Contracts PristineCode (r:1 w:0) // Storage: Contracts CodeStorage (r:0 w:1) fn reinstrument(c: u32, ) -> Weight { - (15_212_000 as Weight) + (12_256_000 as Weight) // Standard Error: 0 - .saturating_add((51_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((49_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1085,9 +1108,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call_with_code_per_byte(c: u32, ) -> Weight { - (218_406_000 as Weight) + (213_494_000 as Weight) // Standard Error: 0 - .saturating_add((55_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((53_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -1099,9 +1122,9 @@ impl WeightInfo for () { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn instantiate_with_code(c: u32, s: u32, ) -> Weight { - (265_773_000 as Weight) + (231_180_000 as Weight) // Standard Error: 0 - .saturating_add((127_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((125_000 as Weight).saturating_mul(c as Weight)) // Standard Error: 0 .saturating_add((2_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) @@ -1114,7 +1137,7 @@ impl WeightInfo for () { // Storage: System Account (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn instantiate(s: u32, ) -> Weight { - (173_852_000 as Weight) + (172_238_000 as Weight) // Standard Error: 0 .saturating_add((2_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) @@ -1125,7 +1148,7 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: System Account (r:1 w:1) fn call() -> Weight { - (140_088_000 as Weight) + (140_912_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -1133,9 +1156,9 @@ impl WeightInfo for () { // Storage: Contracts PristineCode (r:0 w:1) // Storage: Contracts OwnerInfoOf (r:0 w:1) fn upload_code(c: u32, ) -> Weight { - (44_290_000 as Weight) + (42_493_000 as Weight) // Standard Error: 0 - .saturating_add((51_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((49_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -1143,7 +1166,7 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:0 w:1) // Storage: Contracts PristineCode (r:0 w:1) fn remove_code() -> Weight { - (24_364_000 as Weight) + (24_533_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } @@ -1152,9 +1175,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_caller(r: u32, ) -> Weight { - (219_617_000 as Weight) - // Standard Error: 119_000 - .saturating_add((50_409_000 as Weight).saturating_mul(r as Weight)) + (220_009_000 as Weight) + // Standard Error: 80_000 + .saturating_add((47_887_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1163,9 +1186,21 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_is_contract(r: u32, ) -> Weight { - (102_073_000 as Weight) - // Standard Error: 843_000 - .saturating_add((369_025_000 as Weight).saturating_mul(r as Weight)) + (71_779_000 as Weight) + // Standard Error: 900_000 + .saturating_add((371_278_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + // Storage: System Account (r:1 w:0) + // Storage: Contracts ContractInfoOf (r:1 w:1) + // Storage: Contracts CodeStorage (r:1 w:0) + // Storage: Timestamp Now (r:1 w:0) + fn seal_code_hash(r: u32, ) -> Weight { + (0 as Weight) + // Standard Error: 2_329_000 + .saturating_add((451_731_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1174,10 +1209,21 @@ impl WeightInfo for () { // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) + fn seal_own_code_hash(r: u32, ) -> Weight { + (227_824_000 as Weight) + // Standard Error: 128_000 + .saturating_add((52_843_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + // Storage: System Account (r:1 w:0) + // Storage: Contracts ContractInfoOf (r:1 w:1) + // Storage: Contracts CodeStorage (r:1 w:0) + // Storage: Timestamp Now (r:1 w:0) fn seal_caller_is_origin(r: u32, ) -> Weight { - (213_550_000 as Weight) - // Standard Error: 63_000 - .saturating_add((21_519_000 as Weight).saturating_mul(r as Weight)) + (213_057_000 as Weight) + // Standard Error: 43_000 + .saturating_add((21_023_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1186,9 +1232,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_address(r: u32, ) -> Weight { - (220_649_000 as Weight) - // Standard Error: 95_000 - .saturating_add((50_197_000 as Weight).saturating_mul(r as Weight)) + (219_066_000 as Weight) + // Standard Error: 117_000 + .saturating_add((48_056_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1197,9 +1243,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas_left(r: u32, ) -> Weight { - (218_190_000 as Weight) - // Standard Error: 99_000 - .saturating_add((49_817_000 as Weight).saturating_mul(r as Weight)) + (218_844_000 as Weight) + // Standard Error: 101_000 + .saturating_add((47_325_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1208,9 +1254,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_balance(r: u32, ) -> Weight { - (223_133_000 as Weight) - // Standard Error: 188_000 - .saturating_add((142_288_000 as Weight).saturating_mul(r as Weight)) + (219_234_000 as Weight) + // Standard Error: 171_000 + .saturating_add((142_534_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1219,9 +1265,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_value_transferred(r: u32, ) -> Weight { - (216_612_000 as Weight) - // Standard Error: 103_000 - .saturating_add((49_956_000 as Weight).saturating_mul(r as Weight)) + (215_128_000 as Weight) + // Standard Error: 119_000 + .saturating_add((48_392_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1230,9 +1276,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_minimum_balance(r: u32, ) -> Weight { - (218_349_000 as Weight) - // Standard Error: 93_000 - .saturating_add((49_656_000 as Weight).saturating_mul(r as Weight)) + (214_603_000 as Weight) + // Standard Error: 115_000 + .saturating_add((48_041_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1241,9 +1287,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_block_number(r: u32, ) -> Weight { - (213_151_000 as Weight) - // Standard Error: 110_000 - .saturating_add((50_099_000 as Weight).saturating_mul(r as Weight)) + (214_091_000 as Weight) + // Standard Error: 126_000 + .saturating_add((48_067_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1252,9 +1298,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_now(r: u32, ) -> Weight { - (216_816_000 as Weight) - // Standard Error: 95_000 - .saturating_add((49_724_000 as Weight).saturating_mul(r as Weight)) + (214_418_000 as Weight) + // Standard Error: 100_000 + .saturating_add((47_791_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1264,9 +1310,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0) fn seal_weight_to_fee(r: u32, ) -> Weight { - (223_053_000 as Weight) - // Standard Error: 148_000 - .saturating_add((124_240_000 as Weight).saturating_mul(r as Weight)) + (229_261_000 as Weight) + // Standard Error: 150_000 + .saturating_add((121_988_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1275,9 +1321,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_gas(r: u32, ) -> Weight { - (127_253_000 as Weight) - // Standard Error: 27_000 - .saturating_add((25_608_000 as Weight).saturating_mul(r as Weight)) + (127_983_000 as Weight) + // Standard Error: 56_000 + .saturating_add((24_016_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1286,9 +1332,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input(r: u32, ) -> Weight { - (218_057_000 as Weight) - // Standard Error: 98_000 - .saturating_add((49_061_000 as Weight).saturating_mul(r as Weight)) + (216_634_000 as Weight) + // Standard Error: 114_000 + .saturating_add((46_864_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1297,9 +1343,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_input_per_kb(n: u32, ) -> Weight { - (293_563_000 as Weight) - // Standard Error: 3_000 - .saturating_add((11_877_000 as Weight).saturating_mul(n as Weight)) + (285_180_000 as Weight) + // Standard Error: 4_000 + .saturating_add((11_899_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1307,10 +1353,8 @@ impl WeightInfo for () { // Storage: Contracts ContractInfoOf (r:1 w:1) // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) - fn seal_return(r: u32, ) -> Weight { - (211_511_000 as Weight) - // Standard Error: 70_000 - .saturating_add((2_085_000 as Weight).saturating_mul(r as Weight)) + fn seal_return(_r: u32, ) -> Weight { + (215_379_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1319,9 +1363,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_return_per_kb(n: u32, ) -> Weight { - (213_876_000 as Weight) + (213_957_000 as Weight) // Standard Error: 0 - .saturating_add((193_000 as Weight).saturating_mul(n as Weight)) + .saturating_add((201_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1332,9 +1376,9 @@ impl WeightInfo for () { // Storage: Contracts DeletionQueue (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_terminate(r: u32, ) -> Weight { - (214_736_000 as Weight) - // Standard Error: 206_000 - .saturating_add((53_637_000 as Weight).saturating_mul(r as Weight)) + (215_782_000 as Weight) + // Standard Error: 149_000 + .saturating_add((52_421_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((4 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1346,9 +1390,9 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) fn seal_random(r: u32, ) -> Weight { - (222_037_000 as Weight) - // Standard Error: 191_000 - .saturating_add((160_114_000 as Weight).saturating_mul(r as Weight)) + (217_910_000 as Weight) + // Standard Error: 149_000 + .saturating_add((157_525_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1357,9 +1401,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_deposit_event(r: u32, ) -> Weight { - (219_211_000 as Weight) - // Standard Error: 239_000 - .saturating_add((296_722_000 as Weight).saturating_mul(r as Weight)) + (230_787_000 as Weight) + // Standard Error: 210_000 + .saturating_add((296_973_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1369,11 +1413,11 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) // Storage: System EventTopics (r:100 w:100) fn seal_deposit_event_per_topic_and_kb(t: u32, n: u32, ) -> Weight { - (519_643_000 as Weight) - // Standard Error: 1_842_000 - .saturating_add((300_853_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 363_000 - .saturating_add((82_577_000 as Weight).saturating_mul(n as Weight)) + (539_238_000 as Weight) + // Standard Error: 1_701_000 + .saturating_add((294_348_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 335_000 + .saturating_add((82_116_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(t as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1384,17 +1428,17 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_debug_message(r: u32, ) -> Weight { - (132_710_000 as Weight) - // Standard Error: 77_000 - .saturating_add((41_623_000 as Weight).saturating_mul(r as Weight)) + (135_081_000 as Weight) + // Standard Error: 94_000 + .saturating_add((39_247_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage(r: u32, ) -> Weight { - (40_644_000 as Weight) - // Standard Error: 1_072_000 - .saturating_add((412_308_000 as Weight).saturating_mul(r as Weight)) + (41_752_000 as Weight) + // Standard Error: 1_107_000 + .saturating_add((403_473_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1402,25 +1446,25 @@ impl WeightInfo for () { } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage_per_new_kb(n: u32, ) -> Weight { - (609_052_000 as Weight) - // Standard Error: 258_000 - .saturating_add((28_633_000 as Weight).saturating_mul(n as Weight)) + (602_028_000 as Weight) + // Standard Error: 255_000 + .saturating_add((28_303_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_set_storage_per_old_kb(n: u32, ) -> Weight { - (629_665_000 as Weight) - // Standard Error: 300_000 - .saturating_add((10_947_000 as Weight).saturating_mul(n as Weight)) + (620_964_000 as Weight) + // Standard Error: 308_000 + .saturating_add((11_338_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage(r: u32, ) -> Weight { - (91_519_000 as Weight) - // Standard Error: 889_000 - .saturating_add((386_498_000 as Weight).saturating_mul(r as Weight)) + (88_113_000 as Weight) + // Standard Error: 851_000 + .saturating_add((381_671_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -1428,51 +1472,51 @@ impl WeightInfo for () { } // Storage: Skipped Metadata (r:0 w:0) fn seal_clear_storage_per_kb(n: u32, ) -> Weight { - (612_224_000 as Weight) - // Standard Error: 269_000 - .saturating_add((10_709_000 as Weight).saturating_mul(n as Weight)) + (603_193_000 as Weight) + // Standard Error: 262_000 + .saturating_add((10_286_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().writes(103 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage(r: u32, ) -> Weight { - (112_236_000 as Weight) - // Standard Error: 624_000 - .saturating_add((327_655_000 as Weight).saturating_mul(r as Weight)) + (112_477_000 as Weight) + // Standard Error: 666_000 + .saturating_add((324_824_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_get_storage_per_kb(n: u32, ) -> Weight { - (567_711_000 as Weight) - // Standard Error: 387_000 - .saturating_add((63_984_000 as Weight).saturating_mul(n as Weight)) + (564_781_000 as Weight) + // Standard Error: 403_000 + .saturating_add((63_824_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(104 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_contains_storage(r: u32, ) -> Weight { - (109_996_000 as Weight) - // Standard Error: 681_000 - .saturating_add((298_317_000 as Weight).saturating_mul(r as Weight)) + (115_207_000 as Weight) + // Standard Error: 672_000 + .saturating_add((290_919_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_contains_storage_per_kb(n: u32, ) -> Weight { - (518_342_000 as Weight) - // Standard Error: 251_000 - .saturating_add((9_666_000 as Weight).saturating_mul(n as Weight)) + (511_026_000 as Weight) + // Standard Error: 224_000 + .saturating_add((10_138_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(104 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage(r: u32, ) -> Weight { - (75_974_000 as Weight) - // Standard Error: 1_000_000 - .saturating_add((417_954_000 as Weight).saturating_mul(r as Weight)) + (79_113_000 as Weight) + // Standard Error: 904_000 + .saturating_add((417_022_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -1480,9 +1524,9 @@ impl WeightInfo for () { } // Storage: Skipped Metadata (r:0 w:0) fn seal_take_storage_per_kb(n: u32, ) -> Weight { - (653_188_000 as Weight) - // Standard Error: 333_000 - .saturating_add((64_810_000 as Weight).saturating_mul(n as Weight)) + (651_769_000 as Weight) + // Standard Error: 338_000 + .saturating_add((65_576_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().writes(103 as Weight)) } @@ -1491,9 +1535,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_transfer(r: u32, ) -> Weight { - (127_056_000 as Weight) - // Standard Error: 1_106_000 - .saturating_add((1_784_183_000 as Weight).saturating_mul(r as Weight)) + (93_588_000 as Weight) + // Standard Error: 1_444_000 + .saturating_add((1_803_217_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) @@ -1505,8 +1549,8 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) fn seal_call(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 2_621_000 - .saturating_add((19_757_765_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 3_050_000 + .saturating_add((19_925_209_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) @@ -1518,8 +1562,8 @@ impl WeightInfo for () { // Storage: Timestamp Now (r:1 w:0) fn seal_delegate_call(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 6_286_000 - .saturating_add((19_798_229_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 7_377_000 + .saturating_add((19_978_301_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads((99 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1528,11 +1572,11 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:2 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_call_per_transfer_clone_kb(t: u32, c: u32, ) -> Weight { - (10_922_130_000 as Weight) - // Standard Error: 15_556_000 - .saturating_add((1_672_276_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 6_000 - .saturating_add((11_984_000 as Weight).saturating_mul(c as Weight)) + (11_124_804_000 as Weight) + // Standard Error: 21_475_000 + .saturating_add((1_635_442_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 9_000 + .saturating_add((11_981_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(105 as Weight)) .saturating_add(RocksDbWeight::get().reads((101 as Weight).saturating_mul(t as Weight))) .saturating_add(RocksDbWeight::get().writes(101 as Weight)) @@ -1546,8 +1590,8 @@ impl WeightInfo for () { // Storage: Contracts OwnerInfoOf (r:100 w:100) fn seal_instantiate(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 46_147_000 - .saturating_add((27_589_519_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 47_682_000 + .saturating_add((27_883_754_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().reads((400 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) @@ -1560,11 +1604,11 @@ impl WeightInfo for () { // Storage: Contracts Nonce (r:1 w:1) // Storage: Contracts OwnerInfoOf (r:1 w:1) fn seal_instantiate_per_transfer_salt_kb(t: u32, s: u32, ) -> Weight { - (14_790_752_000 as Weight) - // Standard Error: 37_838_000 - .saturating_add((714_016_000 as Weight).saturating_mul(t as Weight)) - // Standard Error: 17_000 - .saturating_add((155_605_000 as Weight).saturating_mul(s as Weight)) + (14_824_308_000 as Weight) + // Standard Error: 39_823_000 + .saturating_add((880_630_000 as Weight).saturating_mul(t as Weight)) + // Standard Error: 18_000 + .saturating_add((156_232_000 as Weight).saturating_mul(s as Weight)) .saturating_add(RocksDbWeight::get().reads(207 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(t as Weight))) .saturating_add(RocksDbWeight::get().writes(205 as Weight)) @@ -1575,9 +1619,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256(r: u32, ) -> Weight { - (216_547_000 as Weight) - // Standard Error: 126_000 - .saturating_add((81_132_000 as Weight).saturating_mul(r as Weight)) + (218_378_000 as Weight) + // Standard Error: 131_000 + .saturating_add((78_260_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1586,9 +1630,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_sha2_256_per_kb(n: u32, ) -> Weight { - (459_912_000 as Weight) - // Standard Error: 27_000 - .saturating_add((464_750_000 as Weight).saturating_mul(n as Weight)) + (202_849_000 as Weight) + // Standard Error: 61_000 + .saturating_add((466_532_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1597,9 +1641,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256(r: u32, ) -> Weight { - (212_653_000 as Weight) + (220_258_000 as Weight) // Standard Error: 147_000 - .saturating_add((93_380_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((90_363_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1608,9 +1652,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_keccak_256_per_kb(n: u32, ) -> Weight { - (324_536_000 as Weight) - // Standard Error: 20_000 - .saturating_add((306_160_000 as Weight).saturating_mul(n as Weight)) + (232_371_000 as Weight) + // Standard Error: 23_000 + .saturating_add((307_036_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1619,9 +1663,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256(r: u32, ) -> Weight { - (218_574_000 as Weight) - // Standard Error: 123_000 - .saturating_add((65_035_000 as Weight).saturating_mul(r as Weight)) + (217_991_000 as Weight) + // Standard Error: 124_000 + .saturating_add((62_273_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1630,9 +1674,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_256_per_kb(n: u32, ) -> Weight { - (345_804_000 as Weight) - // Standard Error: 14_000 - .saturating_add((118_896_000 as Weight).saturating_mul(n as Weight)) + (396_282_000 as Weight) + // Standard Error: 13_000 + .saturating_add((119_575_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1641,9 +1685,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128(r: u32, ) -> Weight { - (215_898_000 as Weight) - // Standard Error: 108_000 - .saturating_add((64_332_000 as Weight).saturating_mul(r as Weight)) + (217_578_000 as Weight) + // Standard Error: 104_000 + .saturating_add((62_189_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1652,9 +1696,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_hash_blake2_128_per_kb(n: u32, ) -> Weight { - (351_569_000 as Weight) - // Standard Error: 18_000 - .saturating_add((118_896_000 as Weight).saturating_mul(n as Weight)) + (358_167_000 as Weight) + // Standard Error: 15_000 + .saturating_add((119_692_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1663,9 +1707,9 @@ impl WeightInfo for () { // Storage: Contracts CodeStorage (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn seal_ecdsa_recover(r: u32, ) -> Weight { - (272_893_000 as Weight) - // Standard Error: 1_438_000 - .saturating_add((15_412_877_000 as Weight).saturating_mul(r as Weight)) + (292_884_000 as Weight) + // Standard Error: 683_000 + .saturating_add((3_824_902_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -1676,264 +1720,264 @@ impl WeightInfo for () { // Storage: Contracts OwnerInfoOf (r:36 w:36) fn seal_set_code_hash(r: u32, ) -> Weight { (0 as Weight) - // Standard Error: 2_132_000 - .saturating_add((937_623_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 2_302_000 + .saturating_add((922_467_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads((99 as Weight).saturating_mul(r as Weight))) .saturating_add(RocksDbWeight::get().writes((99 as Weight).saturating_mul(r as Weight))) } fn instr_i64const(r: u32, ) -> Weight { - (74_268_000 as Weight) + (74_516_000 as Weight) // Standard Error: 1_000 - .saturating_add((595_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((592_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64load(r: u32, ) -> Weight { - (74_515_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_300_000 as Weight).saturating_mul(r as Weight)) + (74_430_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_320_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64store(r: u32, ) -> Weight { - (74_217_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_411_000 as Weight).saturating_mul(r as Weight)) + (74_440_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_428_000 as Weight).saturating_mul(r as Weight)) } fn instr_select(r: u32, ) -> Weight { - (73_689_000 as Weight) - // Standard Error: 4_000 - .saturating_add((1_792_000 as Weight).saturating_mul(r as Weight)) + (74_151_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_782_000 as Weight).saturating_mul(r as Weight)) } fn instr_if(r: u32, ) -> Weight { - (73_755_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_899_000 as Weight).saturating_mul(r as Weight)) + (74_225_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_887_000 as Weight).saturating_mul(r as Weight)) } fn instr_br(r: u32, ) -> Weight { - (73_735_000 as Weight) - // Standard Error: 0 - .saturating_add((903_000 as Weight).saturating_mul(r as Weight)) + (73_987_000 as Weight) + // Standard Error: 1_000 + .saturating_add((898_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_if(r: u32, ) -> Weight { - (73_595_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_448_000 as Weight).saturating_mul(r as Weight)) + (73_305_000 as Weight) + // Standard Error: 4_000 + .saturating_add((1_465_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table(r: u32, ) -> Weight { - (73_524_000 as Weight) + (73_037_000 as Weight) // Standard Error: 3_000 - .saturating_add((1_572_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_605_000 as Weight).saturating_mul(r as Weight)) } fn instr_br_table_per_entry(e: u32, ) -> Weight { - (76_361_000 as Weight) + (76_434_000 as Weight) // Standard Error: 0 .saturating_add((4_000 as Weight).saturating_mul(e as Weight)) } fn instr_call(r: u32, ) -> Weight { - (76_131_000 as Weight) - // Standard Error: 7_000 - .saturating_add((7_271_000 as Weight).saturating_mul(r as Weight)) + (75_461_000 as Weight) + // Standard Error: 10_000 + .saturating_add((7_446_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect(r: u32, ) -> Weight { - (87_948_000 as Weight) - // Standard Error: 14_000 - .saturating_add((9_429_000 as Weight).saturating_mul(r as Weight)) + (87_222_000 as Weight) + // Standard Error: 15_000 + .saturating_add((9_406_000 as Weight).saturating_mul(r as Weight)) } fn instr_call_indirect_per_param(p: u32, ) -> Weight { - (98_091_000 as Weight) + (97_204_000 as Weight) // Standard Error: 1_000 - .saturating_add((481_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((472_000 as Weight).saturating_mul(p as Weight)) } fn instr_local_get(r: u32, ) -> Weight { - (74_311_000 as Weight) + (75_299_000 as Weight) // Standard Error: 1_000 - .saturating_add((627_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((601_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_set(r: u32, ) -> Weight { - (74_701_000 as Weight) - // Standard Error: 1_000 - .saturating_add((677_000 as Weight).saturating_mul(r as Weight)) + (74_827_000 as Weight) + // Standard Error: 3_000 + .saturating_add((686_000 as Weight).saturating_mul(r as Weight)) } fn instr_local_tee(r: u32, ) -> Weight { - (74_645_000 as Weight) - // Standard Error: 1_000 - .saturating_add((890_000 as Weight).saturating_mul(r as Weight)) + (74_624_000 as Weight) + // Standard Error: 2_000 + .saturating_add((895_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_get(r: u32, ) -> Weight { - (77_130_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_156_000 as Weight).saturating_mul(r as Weight)) + (77_435_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_201_000 as Weight).saturating_mul(r as Weight)) } fn instr_global_set(r: u32, ) -> Weight { - (77_199_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_366_000 as Weight).saturating_mul(r as Weight)) + (76_693_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_410_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_current(r: u32, ) -> Weight { - (74_024_000 as Weight) - // Standard Error: 2_000 - .saturating_add((675_000 as Weight).saturating_mul(r as Weight)) + (74_244_000 as Weight) + // Standard Error: 1_000 + .saturating_add((660_000 as Weight).saturating_mul(r as Weight)) } fn instr_memory_grow(r: u32, ) -> Weight { - (75_226_000 as Weight) - // Standard Error: 170_000 - .saturating_add((186_225_000 as Weight).saturating_mul(r as Weight)) + (73_527_000 as Weight) + // Standard Error: 931_000 + .saturating_add((184_946_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64clz(r: u32, ) -> Weight { - (74_307_000 as Weight) - // Standard Error: 2_000 - .saturating_add((896_000 as Weight).saturating_mul(r as Weight)) + (74_181_000 as Weight) + // Standard Error: 6_000 + .saturating_add((906_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ctz(r: u32, ) -> Weight { - (74_408_000 as Weight) - // Standard Error: 3_000 - .saturating_add((895_000 as Weight).saturating_mul(r as Weight)) + (74_339_000 as Weight) + // Standard Error: 1_000 + .saturating_add((896_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64popcnt(r: u32, ) -> Weight { - (74_418_000 as Weight) - // Standard Error: 1_000 - .saturating_add((885_000 as Weight).saturating_mul(r as Weight)) + (74_444_000 as Weight) + // Standard Error: 3_000 + .saturating_add((889_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eqz(r: u32, ) -> Weight { - (74_130_000 as Weight) - // Standard Error: 2_000 - .saturating_add((920_000 as Weight).saturating_mul(r as Weight)) + (74_572_000 as Weight) + // Standard Error: 1_000 + .saturating_add((908_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendsi32(r: u32, ) -> Weight { - (74_318_000 as Weight) + (74_349_000 as Weight) // Standard Error: 2_000 - .saturating_add((876_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((881_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64extendui32(r: u32, ) -> Weight { - (74_496_000 as Weight) + (74_426_000 as Weight) // Standard Error: 1_000 - .saturating_add((871_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((875_000 as Weight).saturating_mul(r as Weight)) } fn instr_i32wrapi64(r: u32, ) -> Weight { - (73_938_000 as Weight) - // Standard Error: 0 - .saturating_add((897_000 as Weight).saturating_mul(r as Weight)) + (74_172_000 as Weight) + // Standard Error: 2_000 + .saturating_add((906_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64eq(r: u32, ) -> Weight { - (73_943_000 as Weight) + (74_169_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_367_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_362_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ne(r: u32, ) -> Weight { - (74_305_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_353_000 as Weight).saturating_mul(r as Weight)) + (74_205_000 as Weight) + // Standard Error: 4_000 + .saturating_add((1_360_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64lts(r: u32, ) -> Weight { - (73_948_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_361_000 as Weight).saturating_mul(r as Weight)) + (74_237_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_356_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ltu(r: u32, ) -> Weight { - (74_188_000 as Weight) - // Standard Error: 4_000 - .saturating_add((1_354_000 as Weight).saturating_mul(r as Weight)) + (74_181_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_357_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gts(r: u32, ) -> Weight { - (74_156_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_353_000 as Weight).saturating_mul(r as Weight)) + (74_038_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_360_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64gtu(r: u32, ) -> Weight { - (73_972_000 as Weight) - // Standard Error: 0 - .saturating_add((1_365_000 as Weight).saturating_mul(r as Weight)) + (73_881_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_372_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64les(r: u32, ) -> Weight { - (74_082_000 as Weight) - // Standard Error: 5_000 - .saturating_add((1_360_000 as Weight).saturating_mul(r as Weight)) + (73_969_000 as Weight) + // Standard Error: 0 + .saturating_add((1_361_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64leu(r: u32, ) -> Weight { - (74_190_000 as Weight) - // Standard Error: 1_000 + (74_497_000 as Weight) + // Standard Error: 3_000 .saturating_add((1_359_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64ges(r: u32, ) -> Weight { - (73_803_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_370_000 as Weight).saturating_mul(r as Weight)) + (74_275_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_354_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64geu(r: u32, ) -> Weight { - (74_063_000 as Weight) - // Standard Error: 1_000 + (74_349_000 as Weight) + // Standard Error: 3_000 .saturating_add((1_357_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64add(r: u32, ) -> Weight { - (73_750_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_345_000 as Weight).saturating_mul(r as Weight)) + (74_192_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_333_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64sub(r: u32, ) -> Weight { - (73_979_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_341_000 as Weight).saturating_mul(r as Weight)) + (74_271_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_340_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64mul(r: u32, ) -> Weight { - (74_197_000 as Weight) - // Standard Error: 4_000 - .saturating_add((1_332_000 as Weight).saturating_mul(r as Weight)) + (73_971_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_340_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divs(r: u32, ) -> Weight { - (73_624_000 as Weight) - // Standard Error: 5_000 - .saturating_add((2_020_000 as Weight).saturating_mul(r as Weight)) + (74_546_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_995_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64divu(r: u32, ) -> Weight { - (74_074_000 as Weight) + (74_194_000 as Weight) // Standard Error: 2_000 .saturating_add((2_050_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rems(r: u32, ) -> Weight { - (73_766_000 as Weight) - // Standard Error: 5_000 - .saturating_add((2_016_000 as Weight).saturating_mul(r as Weight)) + (74_106_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_997_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64remu(r: u32, ) -> Weight { - (73_978_000 as Weight) - // Standard Error: 3_000 - .saturating_add((2_064_000 as Weight).saturating_mul(r as Weight)) + (74_219_000 as Weight) + // Standard Error: 5_000 + .saturating_add((2_061_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64and(r: u32, ) -> Weight { - (73_996_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_336_000 as Weight).saturating_mul(r as Weight)) + (74_157_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_338_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64or(r: u32, ) -> Weight { - (74_058_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_335_000 as Weight).saturating_mul(r as Weight)) + (74_135_000 as Weight) + // Standard Error: 1_000 + .saturating_add((1_336_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64xor(r: u32, ) -> Weight { - (73_983_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_337_000 as Weight).saturating_mul(r as Weight)) + (74_038_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_345_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shl(r: u32, ) -> Weight { - (74_061_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_351_000 as Weight).saturating_mul(r as Weight)) + (74_011_000 as Weight) + // Standard Error: 3_000 + .saturating_add((1_362_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shrs(r: u32, ) -> Weight { - (73_940_000 as Weight) - // Standard Error: 5_000 - .saturating_add((1_360_000 as Weight).saturating_mul(r as Weight)) + (74_054_000 as Weight) + // Standard Error: 2_000 + .saturating_add((1_356_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64shru(r: u32, ) -> Weight { - (73_954_000 as Weight) + (73_900_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_359_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_358_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotl(r: u32, ) -> Weight { - (74_026_000 as Weight) - // Standard Error: 1_000 - .saturating_add((1_354_000 as Weight).saturating_mul(r as Weight)) + (73_948_000 as Weight) + // Standard Error: 0 + .saturating_add((1_357_000 as Weight).saturating_mul(r as Weight)) } fn instr_i64rotr(r: u32, ) -> Weight { - (74_149_000 as Weight) + (73_972_000 as Weight) // Standard Error: 1_000 - .saturating_add((1_352_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((1_358_000 as Weight).saturating_mul(r as Weight)) } } From 41567c30da77a2546a90c1049042ebd7b0b09bc4 Mon Sep 17 00:00:00 2001 From: wigy <1888808+wigy-opensource-developer@users.noreply.github.com> Date: Tue, 29 Mar 2022 20:33:20 +0000 Subject: [PATCH 657/695] Unignore test (#11097) --- client/network/src/service/tests.rs | 53 ++++++++++++++--------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/client/network/src/service/tests.rs b/client/network/src/service/tests.rs index 3dfd7392cd4d..03d647eade17 100644 --- a/client/network/src/service/tests.rs +++ b/client/network/src/service/tests.rs @@ -186,7 +186,6 @@ fn build_nodes_one_proto() -> ( (node1, events_stream1, node2, events_stream2) } -#[ignore] #[test] fn notifications_state_consistent() { // Runs two nodes and ensures that events are propagated out of the API in a consistent @@ -272,38 +271,38 @@ fn notifications_state_consistent() { match next_event { future::Either::Left(Event::NotificationStreamOpened { remote, protocol, .. - }) => { - something_happened = true; - assert!(!node1_to_node2_open); - node1_to_node2_open = true; - assert_eq!(remote, *node2.local_peer_id()); - assert_eq!(protocol, PROTOCOL_NAME); - }, + }) => + if protocol == PROTOCOL_NAME { + something_happened = true; + assert!(!node1_to_node2_open); + node1_to_node2_open = true; + assert_eq!(remote, *node2.local_peer_id()); + }, future::Either::Right(Event::NotificationStreamOpened { remote, protocol, .. - }) => { - something_happened = true; - assert!(!node2_to_node1_open); - node2_to_node1_open = true; - assert_eq!(remote, *node1.local_peer_id()); - assert_eq!(protocol, PROTOCOL_NAME); - }, + }) => + if protocol == PROTOCOL_NAME { + something_happened = true; + assert!(!node2_to_node1_open); + node2_to_node1_open = true; + assert_eq!(remote, *node1.local_peer_id()); + }, future::Either::Left(Event::NotificationStreamClosed { remote, protocol, .. - }) => { - assert!(node1_to_node2_open); - node1_to_node2_open = false; - assert_eq!(remote, *node2.local_peer_id()); - assert_eq!(protocol, PROTOCOL_NAME); - }, + }) => + if protocol == PROTOCOL_NAME { + assert!(node1_to_node2_open); + node1_to_node2_open = false; + assert_eq!(remote, *node2.local_peer_id()); + }, future::Either::Right(Event::NotificationStreamClosed { remote, protocol, .. - }) => { - assert!(node2_to_node1_open); - node2_to_node1_open = false; - assert_eq!(remote, *node1.local_peer_id()); - assert_eq!(protocol, PROTOCOL_NAME); - }, + }) => + if protocol == PROTOCOL_NAME { + assert!(node2_to_node1_open); + node2_to_node1_open = false; + assert_eq!(remote, *node1.local_peer_id()); + }, future::Either::Left(Event::NotificationsReceived { remote, .. }) => { assert!(node1_to_node2_open); assert_eq!(remote, *node2.local_peer_id()); From f2d34943b1e74a212e18dd1483755e72bb0f2f45 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Wed, 30 Mar 2022 20:16:19 +0200 Subject: [PATCH 658/695] Fix Phragmen benchmark (#11137) * Fix phragmen benchmark Signed-off-by: Oliver Tale-Yazdi * cargo run --quiet --profile=production --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_elections_phragmen --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/elections-phragmen/src/weights.rs --template=./.maintain/frame-weight-template.hbs Co-authored-by: Parity Bot --- frame/elections-phragmen/src/benchmarking.rs | 29 ++--- frame/elections-phragmen/src/weights.rs | 112 +++++++++---------- 2 files changed, 71 insertions(+), 70 deletions(-) diff --git a/frame/elections-phragmen/src/benchmarking.rs b/frame/elections-phragmen/src/benchmarking.rs index ae98de4be7e4..05e9df60c7fb 100644 --- a/frame/elections-phragmen/src/benchmarking.rs +++ b/frame/elections-phragmen/src/benchmarking.rs @@ -39,7 +39,9 @@ type Lookup = <::Lookup as StaticLookup>::Source; /// grab new account with infinite balance. fn endowed_account(name: &'static str, index: u32) -> T::AccountId { let account: T::AccountId = account(name, index, 0); - let amount = default_stake::(BALANCE_FACTOR); + // Fund each account with at-least his stake but still a sane amount as to not mess up + // the vote calculation. + let amount = default_stake::(MAX_VOTERS) * BalanceOf::::from(BALANCE_FACTOR); let _ = T::Currency::make_free_balance_be(&account, amount); // important to increase the total issuance since T::CurrencyToVote will need it to be sane for // phragmen to work. @@ -54,9 +56,9 @@ fn as_lookup(account: T::AccountId) -> Lookup { } /// Get a reasonable amount of stake based on the execution trait's configuration -fn default_stake(factor: u32) -> BalanceOf { - let factor = BalanceOf::::from(factor); - T::Currency::minimum_balance() * factor +fn default_stake(num_votes: u32) -> BalanceOf { + let min = T::Currency::minimum_balance(); + Elections::::deposit_of(num_votes as usize).max(min) } /// Get the current number of candidates. @@ -88,7 +90,7 @@ fn submit_candidates_with_self_vote( prefix: &'static str, ) -> Result, &'static str> { let candidates = submit_candidates::(c, prefix)?; - let stake = default_stake::(BALANCE_FACTOR); + let stake = default_stake::(c); let _ = candidates .iter() .map(|c| submit_voter::(c.clone(), vec![c.clone()], stake).map(|_| ())) @@ -112,7 +114,7 @@ fn distribute_voters( num_voters: u32, votes: usize, ) -> Result<(), &'static str> { - let stake = default_stake::(BALANCE_FACTOR); + let stake = default_stake::(num_voters); for i in 0..num_voters { // to ensure that votes are different all_candidates.rotate_left(1); @@ -160,7 +162,7 @@ benchmarks! { let all_candidates = submit_candidates::(v, "candidates")?; let caller = endowed_account::("caller", 0); - let stake = default_stake::(BALANCE_FACTOR); + let stake = default_stake::(v); // original votes. let mut votes = all_candidates; @@ -173,14 +175,15 @@ benchmarks! { }: vote(RawOrigin::Signed(caller), votes, stake) vote_more { - let v in 2 .. (MAXIMUM_VOTE as u32); + let v in 2 .. (MAXIMUM_VOTE as u32); clean::(); // create a bunch of candidates. let all_candidates = submit_candidates::(v, "candidates")?; let caller = endowed_account::("caller", 0); - let stake = default_stake::(BALANCE_FACTOR); + // Multiply the stake with 10 since we want to be able to divide it by 10 again. + let stake = default_stake::(v) * BalanceOf::::from(10u32); // original votes. let mut votes = all_candidates.iter().skip(1).cloned().collect::>(); @@ -194,14 +197,14 @@ benchmarks! { }: vote(RawOrigin::Signed(caller), votes, stake / >::from(10u32)) vote_less { - let v in 2 .. (MAXIMUM_VOTE as u32); + let v in 2 .. (MAXIMUM_VOTE as u32); clean::(); // create a bunch of candidates. let all_candidates = submit_candidates::(v, "candidates")?; let caller = endowed_account::("caller", 0); - let stake = default_stake::(BALANCE_FACTOR); + let stake = default_stake::(v); // original votes. let mut votes = all_candidates; @@ -224,7 +227,7 @@ benchmarks! { let caller = endowed_account::("caller", 0); - let stake = default_stake::(BALANCE_FACTOR); + let stake = default_stake::(v); submit_voter::(caller.clone(), all_candidates, stake)?; whitelist!(caller); @@ -238,7 +241,7 @@ benchmarks! { let m = T::DesiredMembers::get() + T::DesiredRunnersUp::get(); clean::(); - let stake = default_stake::(BALANCE_FACTOR); + let stake = default_stake::(c); // create m members and runners combined. let _ = fill_seats_up_to::(m)?; diff --git a/frame/elections-phragmen/src/weights.rs b/frame/elections-phragmen/src/weights.rs index 22c1c1cbeb40..e973334b833c 100644 --- a/frame/elections-phragmen/src/weights.rs +++ b/frame/elections-phragmen/src/weights.rs @@ -18,11 +18,11 @@ //! Autogenerated weights for pallet_elections_phragmen //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-30, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-03-29, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate +// target/production/substrate // benchmark // --chain=dev // --steps=50 @@ -33,9 +33,7 @@ // --wasm-execution=compiled // --heap-pages=4096 // --output=./frame/elections-phragmen/src/weights.rs -// --template=.maintain/frame-weight-template.hbs -// --header=HEADER-APACHE2 -// --raw +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -70,9 +68,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Elections Voting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_equal(v: u32, ) -> Weight { - (23_406_000 as Weight) + (22_981_000 as Weight) // Standard Error: 6_000 - .saturating_add((270_000 as Weight).saturating_mul(v as Weight)) + .saturating_add((232_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -82,9 +80,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Elections Voting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_more(v: u32, ) -> Weight { - (35_660_000 as Weight) - // Standard Error: 6_000 - .saturating_add((316_000 as Weight).saturating_mul(v as Weight)) + (36_170_000 as Weight) + // Standard Error: 8_000 + .saturating_add((219_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -94,16 +92,16 @@ impl WeightInfo for SubstrateWeight { // Storage: Elections Voting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_less(v: u32, ) -> Weight { - (35_999_000 as Weight) - // Standard Error: 6_000 - .saturating_add((299_000 as Weight).saturating_mul(v as Weight)) + (35_798_000 as Weight) + // Standard Error: 8_000 + .saturating_add((241_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Elections Voting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn remove_voter() -> Weight { - (33_692_000 as Weight) + (33_060_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -111,17 +109,17 @@ impl WeightInfo for SubstrateWeight { // Storage: Elections Members (r:1 w:0) // Storage: Elections RunnersUp (r:1 w:0) fn submit_candidacy(c: u32, ) -> Weight { - (35_506_000 as Weight) - // Standard Error: 1_000 - .saturating_add((192_000 as Weight).saturating_mul(c as Weight)) + (35_384_000 as Weight) + // Standard Error: 0 + .saturating_add((124_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Elections Candidates (r:1 w:1) fn renounce_candidacy_candidate(c: u32, ) -> Weight { - (31_402_000 as Weight) + (31_555_000 as Weight) // Standard Error: 1_000 - .saturating_add((113_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((78_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -131,13 +129,13 @@ impl WeightInfo for SubstrateWeight { // Storage: Council Proposals (r:1 w:0) // Storage: Council Members (r:0 w:1) fn renounce_candidacy_members() -> Weight { - (42_727_000 as Weight) + (41_531_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } // Storage: Elections RunnersUp (r:1 w:1) fn renounce_candidacy_runners_up() -> Weight { - (30_638_000 as Weight) + (30_762_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -152,13 +150,13 @@ impl WeightInfo for SubstrateWeight { // Storage: Council Proposals (r:1 w:0) // Storage: Council Members (r:0 w:1) fn remove_member_with_replacement() -> Weight { - (49_317_000 as Weight) + (48_287_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } // Storage: Elections RunnersUp (r:1 w:0) fn remove_member_wrong_refund() -> Weight { - (4_688_000 as Weight) + (4_747_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) } // Storage: Elections Voting (r:251 w:250) @@ -169,8 +167,8 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:250 w:250) fn clean_defunct_voters(v: u32, _d: u32, ) -> Weight { (0 as Weight) - // Standard Error: 36_000 - .saturating_add((51_016_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 37_000 + .saturating_add((49_564_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(v as Weight))) .saturating_add(T::DbWeight::get().writes((3 as Weight).saturating_mul(v as Weight))) @@ -186,12 +184,12 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:2 w:2) fn election_phragmen(c: u32, v: u32, e: u32, ) -> Weight { (0 as Weight) - // Standard Error: 1_760_000 - .saturating_add((29_569_000 as Weight).saturating_mul(c as Weight)) - // Standard Error: 732_000 - .saturating_add((51_842_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 49_000 - .saturating_add((3_546_000 as Weight).saturating_mul(e as Weight)) + // Standard Error: 1_656_000 + .saturating_add((29_011_000 as Weight).saturating_mul(c as Weight)) + // Standard Error: 689_000 + .saturating_add((49_204_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 47_000 + .saturating_add((3_352_000 as Weight).saturating_mul(e as Weight)) .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(c as Weight))) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(v as Weight))) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(c as Weight))) @@ -206,9 +204,9 @@ impl WeightInfo for () { // Storage: Elections Voting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_equal(v: u32, ) -> Weight { - (23_406_000 as Weight) + (22_981_000 as Weight) // Standard Error: 6_000 - .saturating_add((270_000 as Weight).saturating_mul(v as Weight)) + .saturating_add((232_000 as Weight).saturating_mul(v as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -218,9 +216,9 @@ impl WeightInfo for () { // Storage: Elections Voting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_more(v: u32, ) -> Weight { - (35_660_000 as Weight) - // Standard Error: 6_000 - .saturating_add((316_000 as Weight).saturating_mul(v as Weight)) + (36_170_000 as Weight) + // Standard Error: 8_000 + .saturating_add((219_000 as Weight).saturating_mul(v as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -230,16 +228,16 @@ impl WeightInfo for () { // Storage: Elections Voting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_less(v: u32, ) -> Weight { - (35_999_000 as Weight) - // Standard Error: 6_000 - .saturating_add((299_000 as Weight).saturating_mul(v as Weight)) + (35_798_000 as Weight) + // Standard Error: 8_000 + .saturating_add((241_000 as Weight).saturating_mul(v as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Elections Voting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn remove_voter() -> Weight { - (33_692_000 as Weight) + (33_060_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -247,17 +245,17 @@ impl WeightInfo for () { // Storage: Elections Members (r:1 w:0) // Storage: Elections RunnersUp (r:1 w:0) fn submit_candidacy(c: u32, ) -> Weight { - (35_506_000 as Weight) - // Standard Error: 1_000 - .saturating_add((192_000 as Weight).saturating_mul(c as Weight)) + (35_384_000 as Weight) + // Standard Error: 0 + .saturating_add((124_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Elections Candidates (r:1 w:1) fn renounce_candidacy_candidate(c: u32, ) -> Weight { - (31_402_000 as Weight) + (31_555_000 as Weight) // Standard Error: 1_000 - .saturating_add((113_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((78_000 as Weight).saturating_mul(c as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -267,13 +265,13 @@ impl WeightInfo for () { // Storage: Council Proposals (r:1 w:0) // Storage: Council Members (r:0 w:1) fn renounce_candidacy_members() -> Weight { - (42_727_000 as Weight) + (41_531_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } // Storage: Elections RunnersUp (r:1 w:1) fn renounce_candidacy_runners_up() -> Weight { - (30_638_000 as Weight) + (30_762_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -288,13 +286,13 @@ impl WeightInfo for () { // Storage: Council Proposals (r:1 w:0) // Storage: Council Members (r:0 w:1) fn remove_member_with_replacement() -> Weight { - (49_317_000 as Weight) + (48_287_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } // Storage: Elections RunnersUp (r:1 w:0) fn remove_member_wrong_refund() -> Weight { - (4_688_000 as Weight) + (4_747_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) } // Storage: Elections Voting (r:251 w:250) @@ -305,8 +303,8 @@ impl WeightInfo for () { // Storage: System Account (r:250 w:250) fn clean_defunct_voters(v: u32, _d: u32, ) -> Weight { (0 as Weight) - // Standard Error: 36_000 - .saturating_add((51_016_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 37_000 + .saturating_add((49_564_000 as Weight).saturating_mul(v as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((3 as Weight).saturating_mul(v as Weight))) .saturating_add(RocksDbWeight::get().writes((3 as Weight).saturating_mul(v as Weight))) @@ -322,12 +320,12 @@ impl WeightInfo for () { // Storage: System Account (r:2 w:2) fn election_phragmen(c: u32, v: u32, e: u32, ) -> Weight { (0 as Weight) - // Standard Error: 1_760_000 - .saturating_add((29_569_000 as Weight).saturating_mul(c as Weight)) - // Standard Error: 732_000 - .saturating_add((51_842_000 as Weight).saturating_mul(v as Weight)) - // Standard Error: 49_000 - .saturating_add((3_546_000 as Weight).saturating_mul(e as Weight)) + // Standard Error: 1_656_000 + .saturating_add((29_011_000 as Weight).saturating_mul(c as Weight)) + // Standard Error: 689_000 + .saturating_add((49_204_000 as Weight).saturating_mul(v as Weight)) + // Standard Error: 47_000 + .saturating_add((3_352_000 as Weight).saturating_mul(e as Weight)) .saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(c as Weight))) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(v as Weight))) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(c as Weight))) From b2543516dc83bb1dda2d27d40ace959d994799c9 Mon Sep 17 00:00:00 2001 From: Georges Date: Thu, 31 Mar 2022 13:54:44 +0100 Subject: [PATCH 659/695] Enforce `MaxEncodedLen` impl for `NposSolution` (#11103) * Fail if `MaxVoters` too small * Fixing benchmarking test, better naming of error * reverting accidental change * use fully qualified syntax no need to interate to calculate len * Fail directly if too many voters --- .../election-provider-multi-phase/src/mock.rs | 2 +- .../solution-type/src/single_page.rs | 6 +++++ frame/election-provider-support/src/lib.rs | 3 ++- frame/election-provider-support/src/mock.rs | 2 +- frame/election-provider-support/src/tests.rs | 27 +++++++++++++++++++ primitives/npos-elections/src/lib.rs | 4 ++- 6 files changed, 40 insertions(+), 4 deletions(-) diff --git a/frame/election-provider-multi-phase/src/mock.rs b/frame/election-provider-multi-phase/src/mock.rs index 1b3c4d930624..d6f040363dba 100644 --- a/frame/election-provider-multi-phase/src/mock.rs +++ b/frame/election-provider-multi-phase/src/mock.rs @@ -74,7 +74,7 @@ frame_election_provider_support::generate_solution_type!( VoterIndex = VoterIndex, TargetIndex = TargetIndex, Accuracy = PerU16, - MaxVoters = ConstU32::<20> + MaxVoters = ConstU32::<2_000> >(16) ); diff --git a/frame/election-provider-support/solution-type/src/single_page.rs b/frame/election-provider-support/solution-type/src/single_page.rs index 5a3ddc22f61c..a20f0542984d 100644 --- a/frame/election-provider-support/solution-type/src/single_page.rs +++ b/frame/election-provider-support/solution-type/src/single_page.rs @@ -124,6 +124,11 @@ pub(crate) fn generate(def: crate::SolutionDef) -> Result { for<'r> FV: Fn(&'r A) -> Option, for<'r> FT: Fn(&'r A) -> Option, { + // Make sure that the voter bound is binding. + // `assignments.len()` actually represents the number of voters + if assignments.len() as u32 > <#max_voters as _feps::Get>::get() { + return Err(_feps::Error::TooManyVoters); + } let mut #struct_name: #ident = Default::default(); for _feps::Assignment { who, distribution } in assignments { match distribution.len() { @@ -134,6 +139,7 @@ pub(crate) fn generate(def: crate::SolutionDef) -> Result { } } }; + Ok(#struct_name) } diff --git a/frame/election-provider-support/src/lib.rs b/frame/election-provider-support/src/lib.rs index d79b5289dffe..453cef8956fe 100644 --- a/frame/election-provider-support/src/lib.rs +++ b/frame/election-provider-support/src/lib.rs @@ -170,12 +170,13 @@ pub mod onchain; pub mod traits; #[cfg(feature = "std")] use codec::{Decode, Encode}; -use frame_support::{traits::Get, BoundedVec, RuntimeDebug}; +use frame_support::{BoundedVec, RuntimeDebug}; use sp_runtime::traits::Bounded; use sp_std::{fmt::Debug, prelude::*}; /// Re-export the solution generation macro. pub use frame_election_provider_solution_type::generate_solution_type; +pub use frame_support::traits::Get; /// Re-export some type as they are used in the interface. pub use sp_arithmetic::PerThing; pub use sp_npos_elections::{ diff --git a/frame/election-provider-support/src/mock.rs b/frame/election-provider-support/src/mock.rs index 1ea8dddf7eb1..d10b1724c95d 100644 --- a/frame/election-provider-support/src/mock.rs +++ b/frame/election-provider-support/src/mock.rs @@ -47,7 +47,7 @@ crate::generate_solution_type! { VoterIndex = u32, TargetIndex = u16, Accuracy = TestAccuracy, - MaxVoters = frame_support::traits::ConstU32::<20>, + MaxVoters = frame_support::traits::ConstU32::<2_500>, >(16) } diff --git a/frame/election-provider-support/src/tests.rs b/frame/election-provider-support/src/tests.rs index 7b4e46d83617..f88f3653c681 100644 --- a/frame/election-provider-support/src/tests.rs +++ b/frame/election-provider-support/src/tests.rs @@ -91,6 +91,33 @@ mod solution_type { assert!(with_compact < without_compact); } + #[test] + fn from_assignment_fail_too_many_voters() { + let rng = rand::rngs::SmallRng::seed_from_u64(0); + + // This will produce 24 voters.. + let (voters, assignments, candidates) = generate_random_votes(10, 25, rng); + let voter_index = make_voter_fn(&voters); + let target_index = make_target_fn(&candidates); + + // Limit the voters to 20.. + generate_solution_type!( + pub struct InnerTestSolution::< + VoterIndex = u32, + TargetIndex = u16, + Accuracy = TestAccuracy, + MaxVoters = frame_support::traits::ConstU32::<20>, + >(16) + ); + + // 24 > 20, so this should fail. + assert_eq!( + InnerTestSolution::from_assignment(&assignments, &voter_index, &target_index) + .unwrap_err(), + NposError::TooManyVoters, + ); + } + #[test] fn max_encoded_len_too_small() { generate_solution_type!( diff --git a/primitives/npos-elections/src/lib.rs b/primitives/npos-elections/src/lib.rs index 11d531fa56d8..93fb24eb4a3c 100644 --- a/primitives/npos-elections/src/lib.rs +++ b/primitives/npos-elections/src/lib.rs @@ -119,12 +119,14 @@ pub enum Error { SolutionTargetOverflow, /// One of the index functions returned none. SolutionInvalidIndex, - /// One of the page indices was invalid + /// One of the page indices was invalid. SolutionInvalidPageIndex, /// An error occurred in some arithmetic operation. ArithmeticError(&'static str), /// The data provided to create support map was invalid. InvalidSupportEdge, + /// The number of voters is bigger than the `MaxVoters` bound. + TooManyVoters, } /// A type which is used in the API of this crate as a numeric weight of a vote, most often the From 64f1663a18b511a43280aa457da9183a62b70477 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Thu, 31 Mar 2022 15:13:34 +0200 Subject: [PATCH 660/695] frame-support: Rename tests to express what they are doing (#11147) Fixes: https://github.com/paritytech/substrate/issues/11145 --- frame/support/src/storage/bounded_vec.rs | 2 +- frame/support/src/storage/weak_bounded_vec.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frame/support/src/storage/bounded_vec.rs b/frame/support/src/storage/bounded_vec.rs index cf585af39558..137015098cfa 100644 --- a/frame/support/src/storage/bounded_vec.rs +++ b/frame/support/src/storage/bounded_vec.rs @@ -693,7 +693,7 @@ pub mod test { } #[test] - fn try_append_is_correct() { + fn bound_returns_correct_value() { assert_eq!(BoundedVec::>::bound(), 7); } diff --git a/frame/support/src/storage/weak_bounded_vec.rs b/frame/support/src/storage/weak_bounded_vec.rs index 4b3d87f776b4..aa6dc88eaa4f 100644 --- a/frame/support/src/storage/weak_bounded_vec.rs +++ b/frame/support/src/storage/weak_bounded_vec.rs @@ -330,7 +330,7 @@ pub mod test { } #[test] - fn try_append_is_correct() { + fn bound_returns_correct_value() { assert_eq!(WeakBoundedVec::>::bound(), 7); } From 2287cd80830b081bd51bd8c313c6213d312e541e Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Thu, 31 Mar 2022 15:16:34 +0100 Subject: [PATCH 661/695] add iter-from for bags-list (#11104) * add iter-from for bags-list * Fix * Apply suggestions from code review Co-authored-by: Oliver Tale-Yazdi * Fix Co-authored-by: Oliver Tale-Yazdi --- frame/bags-list/src/lib.rs | 8 +++++- frame/bags-list/src/list/mod.rs | 29 ++++++++++++++++++++++ frame/bags-list/src/tests.rs | 21 ++++++++++++++++ frame/election-provider-support/src/lib.rs | 5 ++++ frame/staking/src/pallet/impls.rs | 18 +++++++++++++- 5 files changed, 79 insertions(+), 2 deletions(-) diff --git a/frame/bags-list/src/lib.rs b/frame/bags-list/src/lib.rs index aa9f1c80dfdb..94553433e230 100644 --- a/frame/bags-list/src/lib.rs +++ b/frame/bags-list/src/lib.rs @@ -271,13 +271,19 @@ impl, I: 'static> Pallet { impl, I: 'static> SortedListProvider for Pallet { type Error = ListError; - type Score = T::Score; fn iter() -> Box> { Box::new(List::::iter().map(|n| n.id().clone())) } + fn iter_from( + start: &T::AccountId, + ) -> Result>, Self::Error> { + let iter = List::::iter_from(start)?; + Ok(Box::new(iter.map(|n| n.id().clone()))) + } + fn count() -> u32 { ListNodes::::count() } diff --git a/frame/bags-list/src/list/mod.rs b/frame/bags-list/src/list/mod.rs index 4e1287458bcb..db8c06a38d67 100644 --- a/frame/bags-list/src/list/mod.rs +++ b/frame/bags-list/src/list/mod.rs @@ -42,6 +42,8 @@ use sp_std::{ pub enum ListError { /// A duplicate id has been detected. Duplicate, + /// Given node id was not found. + NodeNotFound, } #[cfg(test)] @@ -244,6 +246,33 @@ impl, I: 'static> List { iter.filter_map(Bag::get).flat_map(|bag| bag.iter()) } + /// Same as `iter`, but we start from a specific node. + /// + /// All items after this node are returned, excluding `start` itself. + pub(crate) fn iter_from( + start: &T::AccountId, + ) -> Result>, ListError> { + // We chain two iterators: + // 1. from the given `start` till the end of the bag + // 2. all the bags that come after `start`'s bag. + + let start_node = Node::::get(start).ok_or(ListError::NodeNotFound)?; + let start_node_upper = start_node.bag_upper; + let start_bag = sp_std::iter::successors(start_node.next(), |prev| prev.next()); + + let thresholds = T::BagThresholds::get(); + let idx = thresholds.partition_point(|&threshold| start_node_upper > threshold); + let leftover_bags = thresholds + .into_iter() + .take(idx) + .copied() + .rev() + .filter_map(Bag::get) + .flat_map(|bag| bag.iter()); + + Ok(start_bag.chain(leftover_bags)) + } + /// Insert several ids into the appropriate bags in the list. Continues with insertions /// if duplicates are detected. /// diff --git a/frame/bags-list/src/tests.rs b/frame/bags-list/src/tests.rs index 0d6ba4721b9a..941623229dc2 100644 --- a/frame/bags-list/src/tests.rs +++ b/frame/bags-list/src/tests.rs @@ -458,6 +458,27 @@ mod sorted_list_provider { }); } + #[test] + fn iter_from_works() { + ExtBuilder::default().add_ids(vec![(5, 5), (6, 15)]).build_and_execute(|| { + // given + assert_eq!( + List::::get_bags(), + vec![(10, vec![1, 5]), (20, vec![6]), (1000, vec![2, 3, 4])] + ); + + assert_eq!(BagsList::iter_from(&2).unwrap().collect::>(), vec![3, 4, 6, 1, 5]); + assert_eq!(BagsList::iter_from(&3).unwrap().collect::>(), vec![4, 6, 1, 5]); + assert_eq!(BagsList::iter_from(&4).unwrap().collect::>(), vec![6, 1, 5]); + assert_eq!(BagsList::iter_from(&6).unwrap().collect::>(), vec![1, 5]); + assert_eq!(BagsList::iter_from(&1).unwrap().collect::>(), vec![5]); + assert!(BagsList::iter_from(&5).unwrap().collect::>().is_empty()); + assert!(BagsList::iter_from(&7).is_err()); + + assert_storage_noop!(assert!(BagsList::iter_from(&8).is_err())); + }); + } + #[test] fn count_works() { ExtBuilder::default().build_and_execute(|| { diff --git a/frame/election-provider-support/src/lib.rs b/frame/election-provider-support/src/lib.rs index 453cef8956fe..19735cf6035a 100644 --- a/frame/election-provider-support/src/lib.rs +++ b/frame/election-provider-support/src/lib.rs @@ -441,6 +441,11 @@ pub trait SortedListProvider { /// An iterator over the list, which can have `take` called on it. fn iter() -> Box>; + /// Returns an iterator over the list, starting right after from the given voter. + /// + /// May return an error if `start` is invalid. + fn iter_from(start: &AccountId) -> Result>, Self::Error>; + /// The current count of ids in the list. fn count() -> u32; diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index 9d5a3ed48418..90f19c6badd8 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -1308,7 +1308,6 @@ impl SortedListProvider for UseNominatorsAndValidatorsM type Error = (); type Score = VoteWeight; - /// Returns iterator over voter list, which can have `take` called on it. fn iter() -> Box> { Box::new( Validators::::iter() @@ -1316,6 +1315,23 @@ impl SortedListProvider for UseNominatorsAndValidatorsM .chain(Nominators::::iter().map(|(n, _)| n)), ) } + fn iter_from( + start: &T::AccountId, + ) -> Result>, Self::Error> { + if Validators::::contains_key(start) { + let start_key = Validators::::hashed_key_for(start); + Ok(Box::new( + Validators::::iter_from(start_key) + .map(|(n, _)| n) + .chain(Nominators::::iter().map(|(x, _)| x)), + )) + } else if Nominators::::contains_key(start) { + let start_key = Nominators::::hashed_key_for(start); + Ok(Box::new(Nominators::::iter_from(start_key).map(|(n, _)| n))) + } else { + Err(()) + } + } fn count() -> u32 { Nominators::::count().saturating_add(Validators::::count()) } From 4abe94ccece262efd2daac8f0b96548724ab9f4e Mon Sep 17 00:00:00 2001 From: driemworks Date: Thu, 31 Mar 2022 13:35:46 -0500 Subject: [PATCH 662/695] move rpc back to assets, signature verification --- Cargo.lock | 24 ++++++ bin/node-template/node/Cargo.toml | 2 +- .../rpc/Cargo.toml | 0 .../rpc/README.md | 0 .../rpc/runtime-api/Cargo.toml | 0 .../rpc/runtime-api/README.md | 0 .../rpc/runtime-api/src/lib.rs | 3 + .../rpc/src/lib.rs | 8 +- .../pallets/iris-assets/src/lib.rs | 76 ++++++++++++++++++- .../pallets/iris-session/Cargo.toml | 2 - .../pallets/iris-session/src/lib.rs | 29 +------ .../pallets/iris-session/src/tests.rs | 13 ---- bin/node-template/runtime/Cargo.toml | 2 +- bin/node-template/runtime/src/lib.rs | 8 +- bin/node/rpc/Cargo.toml | 2 +- client/consensus/aura/Cargo.toml | 2 +- 16 files changed, 120 insertions(+), 51 deletions(-) rename bin/node-template/pallets/{iris-session => iris-assets}/rpc/Cargo.toml (100%) rename bin/node-template/pallets/{iris-session => iris-assets}/rpc/README.md (100%) rename bin/node-template/pallets/{iris-session => iris-assets}/rpc/runtime-api/Cargo.toml (100%) rename bin/node-template/pallets/{iris-session => iris-assets}/rpc/runtime-api/README.md (100%) rename bin/node-template/pallets/{iris-session => iris-assets}/rpc/runtime-api/src/lib.rs (85%) rename bin/node-template/pallets/{iris-session => iris-assets}/rpc/src/lib.rs (89%) diff --git a/Cargo.lock b/Cargo.lock index 0585177784ae..f62fbd3ca01b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2487,8 +2487,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d39cd93900197114fa1fcb7ae84ca742095eed9442088988ae74fa744e930e77" dependencies = [ "cfg-if 1.0.0", + "js-sys", "libc", "wasi 0.10.0+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] @@ -4984,6 +4986,7 @@ dependencies = [ "pallet-im-online", "pallet-iris-assets", "pallet-iris-ledger", + "pallet-iris-offchain", "pallet-iris-rpc-runtime-api", "pallet-iris-session", "pallet-randomness-collective-flip", @@ -5838,6 +5841,26 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-iris-offchain" +version = "1.0.0" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log 0.4.14", + "pallet-assets", + "pallet-balances", + "pallet-iris-assets", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-keystore", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-iris-rpc" version = "4.0.0-dev" @@ -7951,6 +7974,7 @@ dependencies = [ "async-trait", "derive_more", "futures 0.3.21", + "getrandom 0.2.5", "log 0.4.14", "parity-scale-codec", "parking_lot 0.11.2", diff --git a/bin/node-template/node/Cargo.toml b/bin/node-template/node/Cargo.toml index f276c2fdb8b0..9493ab3c338d 100644 --- a/bin/node-template/node/Cargo.toml +++ b/bin/node-template/node/Cargo.toml @@ -50,7 +50,7 @@ sp-block-builder = { version = "4.0.0-dev", path = "../../../primitives/block-bu sc-basic-authorship = { version = "0.10.0-dev", path = "../../../client/basic-authorship" } substrate-frame-rpc-system = { version = "4.0.0-dev", path = "../../../utils/frame/rpc/system" } pallet-transaction-payment-rpc = { version = "4.0.0-dev", path = "../../../frame/transaction-payment/rpc/" } -pallet-iris-rpc = { version = "4.0.0-dev", path = "../pallets/iris-session/rpc/" } +pallet-iris-rpc = { version = "4.0.0-dev", path = "../pallets/iris-assets/rpc/" } pallet-contracts-rpc = { version = "4.0.0-dev", path = "../../../frame/contracts/rpc/" } # These dependencies are used for runtime benchmarking diff --git a/bin/node-template/pallets/iris-session/rpc/Cargo.toml b/bin/node-template/pallets/iris-assets/rpc/Cargo.toml similarity index 100% rename from bin/node-template/pallets/iris-session/rpc/Cargo.toml rename to bin/node-template/pallets/iris-assets/rpc/Cargo.toml diff --git a/bin/node-template/pallets/iris-session/rpc/README.md b/bin/node-template/pallets/iris-assets/rpc/README.md similarity index 100% rename from bin/node-template/pallets/iris-session/rpc/README.md rename to bin/node-template/pallets/iris-assets/rpc/README.md diff --git a/bin/node-template/pallets/iris-session/rpc/runtime-api/Cargo.toml b/bin/node-template/pallets/iris-assets/rpc/runtime-api/Cargo.toml similarity index 100% rename from bin/node-template/pallets/iris-session/rpc/runtime-api/Cargo.toml rename to bin/node-template/pallets/iris-assets/rpc/runtime-api/Cargo.toml diff --git a/bin/node-template/pallets/iris-session/rpc/runtime-api/README.md b/bin/node-template/pallets/iris-assets/rpc/runtime-api/README.md similarity index 100% rename from bin/node-template/pallets/iris-session/rpc/runtime-api/README.md rename to bin/node-template/pallets/iris-assets/rpc/runtime-api/README.md diff --git a/bin/node-template/pallets/iris-session/rpc/runtime-api/src/lib.rs b/bin/node-template/pallets/iris-assets/rpc/runtime-api/src/lib.rs similarity index 85% rename from bin/node-template/pallets/iris-session/rpc/runtime-api/src/lib.rs rename to bin/node-template/pallets/iris-assets/rpc/runtime-api/src/lib.rs index 1ba4ba5fd5f5..4e5d901c2c90 100644 --- a/bin/node-template/pallets/iris-session/rpc/runtime-api/src/lib.rs +++ b/bin/node-template/pallets/iris-assets/rpc/runtime-api/src/lib.rs @@ -10,6 +10,9 @@ sp_api::decl_runtime_apis! { pub trait IrisApi { fn retrieve_bytes( + signature: Bytes, + message: Bytes, + signer: Bytes, asset_id: Bytes, ) -> Bytes; } diff --git a/bin/node-template/pallets/iris-session/rpc/src/lib.rs b/bin/node-template/pallets/iris-assets/rpc/src/lib.rs similarity index 89% rename from bin/node-template/pallets/iris-session/rpc/src/lib.rs rename to bin/node-template/pallets/iris-assets/rpc/src/lib.rs index e71b55c9c8f8..5ba3a55c3cd9 100644 --- a/bin/node-template/pallets/iris-session/rpc/src/lib.rs +++ b/bin/node-template/pallets/iris-assets/rpc/src/lib.rs @@ -16,6 +16,9 @@ pub trait IrisApi { #[rpc(name = "iris_retrieveBytes")] fn retrieve_bytes( &self, + signature: Bytes, + message: Bytes, + signer: Bytes, asset_id: Bytes, at: Option, ) -> Result; @@ -59,6 +62,9 @@ where { fn retrieve_bytes( &self, + signature: Bytes, + message: Bytes, + signer: Bytes, asset_id: Bytes, at: Option<::Hash>, ) -> Result { @@ -66,7 +72,7 @@ where let at = BlockId::hash(at.unwrap_or_else(|| self.client.info().best_hash )); - let runtime_api_result = api.retrieve_bytes(&at, asset_id); + let runtime_api_result = api.retrieve_bytes(&at, signature, message, signer, asset_id); runtime_api_result.map_err(|e| RpcError{ code: ErrorCode::ServerError(Error::DecodeError.into()), message: "unable to query runtime api".into(), diff --git a/bin/node-template/pallets/iris-assets/src/lib.rs b/bin/node-template/pallets/iris-assets/src/lib.rs index 060ba9cdcb35..ae880ce6306a 100644 --- a/bin/node-template/pallets/iris-assets/src/lib.rs +++ b/bin/node-template/pallets/iris-assets/src/lib.rs @@ -26,16 +26,23 @@ use frame_system::{ self as system, ensure_signed, }; -use sp_core::offchain::OpaqueMultiaddr; +use sp_core::{ + offchain::{OpaqueMultiaddr, StorageKind}, + Bytes, +}; use sp_runtime::{ RuntimeDebug, - traits::StaticLookup, + traits::{StaticLookup, Verify, IdentifyAccount}, }; use sp_std::{ vec::Vec, prelude::*, }; +use scale_info::prelude::string::String; + +use core::convert::TryInto; +use sp_core::sr25519; #[derive(Encode, Decode, RuntimeDebug, PartialEq, TypeInfo)] pub enum DataCommand { @@ -338,6 +345,10 @@ pub mod pallet { #[pallet::compact] asset_id: T::AssetId, ) -> DispatchResult { let who = ensure_signed(origin)?; + // verify asset access -> should check assets pallet + // ensure!(>::get(who.clone()).contains(asset_id), + // Error::::InvalidAssetId); + // submit command to dataqueue let owner = >::asset(asset_id.clone()).unwrap().owner; >::mutate( |queue| queue.push(DataCommand::CatBytes( @@ -414,5 +425,64 @@ pub mod pallet { } impl Pallet { - +/// implementation for RPC runtime API to retrieve bytes from the node's local storage + /// + /// * `signature`: The signer's signature as bytes + /// * `message`: The signed message as bytes + /// * `signer`: The public key of the message signer as bytes + /// * `asset_id`: The asset id associated with some data + /// + /// Note: If in the future you want to make sig/key types dynamic, add to trait def: + /// + ///``` + /// pub trait Config: frame_system::Config { + /// ... + /// type Signature: Verify + Encode + Decode + Member; + /// type PublicKey: IdentifyAccount + Encode + Decode + Member; + /// ... + /// } + /// ``` + /// + /// And in your runtime: + /// ``` + /// my_pallet::Config for runtime { + /// ... + /// type Signature = + /// type PublicKey = + /// .... + /// } + /// ``` + /// + pub fn retrieve_bytes( + signature: Bytes, + message: Bytes, + signer: Bytes, + asset_id: Bytes, + ) -> Bytes + where ::AssetId: From { + // convert Bytes type to types needed for verification + let sig: sp_core::sr25519::Signature = sr25519::Signature::from_slice(signature.to_vec().as_ref()); + let msg: Vec = message.to_vec(); + let account_bytes: [u8; 32] = signer.to_vec().try_into().unwrap(); + let public_key = sr25519::Public::from_raw(account_bytes); + + // signature verification + if sig.verify(msg.as_slice(), &public_key) { + // parse asset id + let asset_id_u32: u32 = String::from_utf8(asset_id.to_vec()).unwrap().parse().unwrap(); + let asset_id_type: T::AssetId = asset_id_u32.try_into().unwrap(); + // verify asset access + // if !>::get(public_key).contains(asset_id_type) { + // return Bytes(Vec::new()); + // } + // get CID and fetch from offchain storage + let cid = >::get(asset_id_type).to_vec(); + if let Some(data) = sp_io::offchain::local_storage_get(StorageKind::PERSISTENT, &cid) { + return Bytes(data.clone()); + } else { + return Bytes(Vec::new()); + } + } + Bytes(Vec::new()) + } } \ No newline at end of file diff --git a/bin/node-template/pallets/iris-session/Cargo.toml b/bin/node-template/pallets/iris-session/Cargo.toml index 4e3a57fc83e4..53d0aae68025 100644 --- a/bin/node-template/pallets/iris-session/Cargo.toml +++ b/bin/node-template/pallets/iris-session/Cargo.toml @@ -38,7 +38,6 @@ pallet-assets = { version = "4.0.0-dev", default-features = false, path = "../.. [dev-dependencies] pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../../../../frame/balances" } -# pallet-assets = { version = "4.0.0-dev", default-features = false, path = "../../../../frame/assets" } [features] default = ['std'] @@ -52,7 +51,6 @@ std = [ 'sp-std/std', 'sp-keystore/std', 'sp-runtime/std', - # todo: can remove this dependency 'sp-staking/std', 'log/std', 'pallet-im-online/std', diff --git a/bin/node-template/pallets/iris-session/src/lib.rs b/bin/node-template/pallets/iris-session/src/lib.rs index af7be0c75ec9..07f7b650823c 100644 --- a/bin/node-template/pallets/iris-session/src/lib.rs +++ b/bin/node-template/pallets/iris-session/src/lib.rs @@ -28,8 +28,6 @@ mod mock; mod tests; -use std::convert::TryInto; - use frame_support::{ ensure, pallet_prelude::*, @@ -44,14 +42,15 @@ pub use pallet::*; use sp_runtime::traits::{Convert, Zero}; use sp_staking::offence::{Offence, OffenceError, ReportOffence}; use sp_std::{ - collections::{ btree_set::BTreeSet, btree_map::BTreeMap }, + collections::{btree_set::BTreeSet, btree_map::BTreeMap}, str, vec::Vec, prelude::* }; use sp_core::{ offchain::{ - Duration, IpfsRequest, IpfsResponse, OpaqueMultiaddr, Timestamp, StorageKind, + Duration, IpfsRequest, IpfsResponse, + OpaqueMultiaddr, Timestamp, StorageKind, }, crypto::KeyTypeId, Bytes, @@ -725,27 +724,7 @@ impl Pallet { .propagate(true) .build() } - /// implementation for RPC runtime API to retrieve bytes from the node's local storage - /// - /// * public_key: The account's public key as bytes - /// * signature: The signer's signature as bytes - /// * message: The signed message as bytes - /// - pub fn retrieve_bytes( - asset_id: Bytes, - ) -> Bytes - where ::AssetId: From { - let asset_id_u32: u32 = String::from_utf8(asset_id.to_vec()).unwrap().parse().unwrap(); - let asset_id_type: T::AssetId = asset_id_u32.try_into().unwrap(); - let cid = >::metadata(asset_id_type).to_vec(); - // // let message_vec: Vec = message.to_vec(); - if let Some(data) = sp_io::offchain::local_storage_get(StorageKind::PERSISTENT, &cid) { - Bytes(data.clone()) - } else { - Bytes(Vec::new()) - } - } - + /// send a request to the local IPFS node; can only be called be an off-chain worker fn ipfs_request( req: IpfsRequest, diff --git a/bin/node-template/pallets/iris-session/src/tests.rs b/bin/node-template/pallets/iris-session/src/tests.rs index 8e09d79f64cb..390339a2e854 100644 --- a/bin/node-template/pallets/iris-session/src/tests.rs +++ b/bin/node-template/pallets/iris-session/src/tests.rs @@ -253,19 +253,6 @@ fn iris_session_join_storage_pool() { }); } -// RPC tests - -#[test] -fn iris_session_submit_rpc_ready_works_for_valid_values() { - let (p, _) = sp_core::sr25519::Pair::generate(); - new_test_ext_funded(p.clone()).execute_with(|| { - assert_ok!(IrisSession::submit_rpc_ready( - Origin::signed(p.clone().public()), - 1, - )); - }); -} - // test OCW functionality // can add bytes to network #[test] diff --git a/bin/node-template/runtime/Cargo.toml b/bin/node-template/runtime/Cargo.toml index 18b6678e1006..0a7f9c7e3343 100644 --- a/bin/node-template/runtime/Cargo.toml +++ b/bin/node-template/runtime/Cargo.toml @@ -52,7 +52,7 @@ sp-version = { version = "4.0.0-dev", default-features = false, path = "../../.. # Used for the node template's RPCs frame-system-rpc-runtime-api = { version = "4.0.0-dev", default-features = false, path = "../../../frame/system/rpc/runtime-api/" } pallet-transaction-payment-rpc-runtime-api = { version = "4.0.0-dev", default-features = false, path = "../../../frame/transaction-payment/rpc/runtime-api/" } -pallet-iris-rpc-runtime-api = { version = "4.0.0-dev", default-features = false, path = "../pallets/iris-session/rpc/runtime-api/" } +pallet-iris-rpc-runtime-api = { version = "4.0.0-dev", default-features = false, path = "../pallets/iris-assets/rpc/runtime-api/" } pallet-contracts-rpc-runtime-api = { version = "4.0.0-dev", default-features = false, path = "../../../frame/contracts/rpc/runtime-api/" } # Used for runtime benchmarking frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../../../frame/benchmarking", optional = true } diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index d5dfd9ea63ad..c0c553e7632a 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -51,7 +51,6 @@ pub use frame_support::{ pub use pallet_balances::Call as BalancesCall; pub use pallet_timestamp::Call as TimestampCall; pub use pallet_assets::Call as AssetsCall; -// pub use pallet_iris_asset::Call as IrisAssetsCall; use pallet_transaction_payment::CurrencyAdapter; #[cfg(any(feature = "std", test))] pub use sp_runtime::BuildStorage; @@ -744,9 +743,12 @@ impl_runtime_apis! { */ impl pallet_iris_rpc_runtime_api::IrisApi for Runtime { fn retrieve_bytes( - asset_id: Bytes + signature: Bytes, + message: Bytes, + signer: Bytes, + asset_id: Bytes, ) -> Bytes { - IrisSession::retrieve_bytes(asset_id) + IrisAssets::retrieve_bytes(signature, message, signer, asset_id) } } diff --git a/bin/node/rpc/Cargo.toml b/bin/node/rpc/Cargo.toml index ecb581955f0b..06c0cee87886 100644 --- a/bin/node/rpc/Cargo.toml +++ b/bin/node/rpc/Cargo.toml @@ -16,7 +16,7 @@ node-primitives = { version = "2.0.0", path = "../primitives" } pallet-contracts-rpc = { version = "4.0.0-dev", path = "../../../frame/contracts/rpc/" } pallet-mmr-rpc = { version = "3.0.0", path = "../../../frame/merkle-mountain-range/rpc/" } pallet-transaction-payment-rpc = { version = "4.0.0-dev", path = "../../../frame/transaction-payment/rpc/" } -pallet-iris-rpc = { version = "4.0.0-dev", path = "../../node-template/pallets/iris-session/rpc/" } +pallet-iris-rpc = { version = "4.0.0-dev", path = "../../node-template/pallets/iris-assets/rpc/" } sc-client-api = { version = "4.0.0-dev", path = "../../../client/api" } sc-consensus-babe = { version = "0.10.0-dev", path = "../../../client/consensus/babe" } sc-consensus-babe-rpc = { version = "0.10.0-dev", path = "../../../client/consensus/babe/rpc" } diff --git a/client/consensus/aura/Cargo.toml b/client/consensus/aura/Cargo.toml index c7a38b1bbfdf..75595779427b 100644 --- a/client/consensus/aura/Cargo.toml +++ b/client/consensus/aura/Cargo.toml @@ -37,7 +37,7 @@ prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../.. async-trait = "0.1.50" # We enable it only for web-wasm check # See https://docs.rs/getrandom/0.2.1/getrandom/#webassembly-support -# getrandom = { version = "0.2", features = ["js"], optional = true } +getrandom = { version = "0.2", features = ["js"], optional = true } [dev-dependencies] sp-timestamp = { version = "4.0.0-dev", path = "../../../primitives/timestamp" } From 56dc6d1a3d9ae166f47368f9006ff4fe5457d889 Mon Sep 17 00:00:00 2001 From: David Salami <31099392+Wizdave97@users.noreply.github.com> Date: Fri, 1 Apr 2022 09:50:11 +0100 Subject: [PATCH 663/695] Refactor Beefy MMR and remove parachain specific implementations (#10664) * refactor beefy mmr * use plain vector of bytes for leaf extra * update comment * update comments * remove unused vars * Use sp_std::vec::Vec Co-authored-by: Adrian Catangiu * make extra data generic * fix tests * refactor beefy-mmr * Update frame/beefy-mmr/src/lib.rs * minor fix * fmt * Update frame/beefy-mmr/src/lib.rs Co-authored-by: Adrian Catangiu --- frame/beefy-mmr/src/lib.rs | 55 +++++++----------------------------- frame/beefy-mmr/src/mock.rs | 23 +++++++++++---- frame/beefy-mmr/src/tests.rs | 18 +++++------- primitives/beefy/src/mmr.rs | 21 ++++++++++++-- 4 files changed, 52 insertions(+), 65 deletions(-) diff --git a/frame/beefy-mmr/src/lib.rs b/frame/beefy-mmr/src/lib.rs index 476589717e06..9ee7bd770f64 100644 --- a/frame/beefy-mmr/src/lib.rs +++ b/frame/beefy-mmr/src/lib.rs @@ -29,17 +29,16 @@ //! The MMR leaf contains: //! 1. Block number and parent block hash. //! 2. Merkle Tree Root Hash of next BEEFY validator set. -//! 3. Merkle Tree Root Hash of current parachain heads state. +//! 3. Arbitrary extra leaf data to be used by downstream pallets to include custom data. //! //! and thanks to versioning can be easily updated in the future. -use sp_runtime::traits::{Convert, Hash}; +use sp_runtime::traits::{Convert, Hash, Member}; use sp_std::prelude::*; -use beefy_primitives::mmr::{BeefyNextAuthoritySet, MmrLeaf, MmrLeafVersion}; +use beefy_primitives::mmr::{BeefyDataProvider, BeefyNextAuthoritySet, MmrLeaf, MmrLeafVersion}; use pallet_mmr::primitives::LeafDataProvider; -use codec::Encode; use frame_support::traits::Get; pub use pallet::*; @@ -90,23 +89,6 @@ impl Convert> for BeefyEcdsaToEth } type MerkleRootOf = ::Hash; -type ParaId = u32; -type ParaHead = Vec; - -/// A type that is able to return current list of parachain heads that end up in the MMR leaf. -pub trait ParachainHeadsProvider { - /// Return a list of tuples containing a `ParaId` and Parachain Header data (ParaHead). - /// - /// The returned data does not have to be sorted. - fn parachain_heads() -> Vec<(ParaId, ParaHead)>; -} - -/// A default implementation for runtimes without parachains. -impl ParachainHeadsProvider for () { - fn parachain_heads() -> Vec<(ParaId, ParaHead)> { - Default::default() - } -} #[frame_support::pallet] pub mod pallet { @@ -138,12 +120,11 @@ pub mod pallet { /// efficiency reasons. type BeefyAuthorityToMerkleLeaf: Convert<::BeefyId, Vec>; - /// Retrieve a list of current parachain heads. - /// - /// The trait is implemented for `paras` module, but since not all chains might have - /// parachains, and we want to keep the MMR leaf structure uniform, it's possible to use - /// `()` as well to simply put dummy data to the leaf. - type ParachainHeads: ParachainHeadsProvider; + /// The type expected for the leaf extra data + type LeafExtra: Member + codec::FullCodec; + + /// Retrieve arbitrary data that should be added to the mmr leaf + type BeefyDataProvider: BeefyDataProvider; } /// Details of next BEEFY authority set. @@ -163,13 +144,14 @@ where ::BlockNumber, ::Hash, MerkleRootOf, + T::LeafExtra, >; fn leaf_data() -> Self::LeafData { MmrLeaf { version: T::LeafVersion::get(), parent_number_and_hash: frame_system::Pallet::::leaf_data(), - parachain_heads: Pallet::::parachain_heads_merkle_root(), + leaf_extra: T::BeefyDataProvider::extra_data(), beefy_next_authority_set: Pallet::::update_beefy_next_authority_set(), } } @@ -188,23 +170,6 @@ impl Pallet where MerkleRootOf: From + Into, { - /// Returns latest root hash of a merkle tree constructed from all active parachain headers. - /// - /// The leafs are sorted by `ParaId` to allow more efficient lookups and non-existence proofs. - /// - /// NOTE this does not include parathreads - only parachains are part of the merkle tree. - /// - /// NOTE This is an initial and inefficient implementation, which re-constructs - /// the merkle tree every block. Instead we should update the merkle root in - /// [Self::on_initialize] call of this pallet and update the merkle tree efficiently (use - /// on-chain storage to persist inner nodes). - fn parachain_heads_merkle_root() -> MerkleRootOf { - let mut para_heads = T::ParachainHeads::parachain_heads(); - para_heads.sort(); - let para_heads = para_heads.into_iter().map(|pair| pair.encode()); - beefy_merkle_tree::merkle_root::(para_heads).into() - } - /// Returns details of the next BEEFY authority set. /// /// Details contain authority set id, authority set length and a merkle root, diff --git a/frame/beefy-mmr/src/mock.rs b/frame/beefy-mmr/src/mock.rs index dcee901ec14c..f6a35f68a4a1 100644 --- a/frame/beefy-mmr/src/mock.rs +++ b/frame/beefy-mmr/src/mock.rs @@ -18,6 +18,7 @@ use std::vec; use beefy_primitives::mmr::MmrLeafVersion; +use codec::Encode; use frame_support::{ construct_runtime, parameter_types, sp_io::TestExternalities, @@ -34,7 +35,9 @@ use sp_runtime::{ use crate as pallet_beefy_mmr; -pub use beefy_primitives::{crypto::AuthorityId as BeefyId, ConsensusLog, BEEFY_ENGINE_ID}; +pub use beefy_primitives::{ + crypto::AuthorityId as BeefyId, mmr::BeefyDataProvider, ConsensusLog, BEEFY_ENGINE_ID, +}; impl_opaque_keys! { pub struct MockSessionKeys { @@ -102,6 +105,7 @@ pub type MmrLeaf = beefy_primitives::mmr::MmrLeaf< ::BlockNumber, ::Hash, ::Hash, + Vec, >; impl pallet_mmr::Config for Test { @@ -131,13 +135,20 @@ impl pallet_beefy_mmr::Config for Test { type BeefyAuthorityToMerkleLeaf = pallet_beefy_mmr::BeefyEcdsaToEthereum; - type ParachainHeads = DummyParaHeads; + type LeafExtra = Vec; + + type BeefyDataProvider = DummyDataProvider; } -pub struct DummyParaHeads; -impl pallet_beefy_mmr::ParachainHeadsProvider for DummyParaHeads { - fn parachain_heads() -> Vec<(pallet_beefy_mmr::ParaId, pallet_beefy_mmr::ParaHead)> { - vec![(15, vec![1, 2, 3]), (5, vec![4, 5, 6])] +pub struct DummyDataProvider; +impl BeefyDataProvider> for DummyDataProvider { + fn extra_data() -> Vec { + let mut col = vec![(15, vec![1, 2, 3]), (5, vec![4, 5, 6])]; + col.sort(); + beefy_merkle_tree::merkle_root::, _, _>( + col.into_iter().map(|pair| pair.encode()), + ) + .to_vec() } } diff --git a/frame/beefy-mmr/src/tests.rs b/frame/beefy-mmr/src/tests.rs index 452b8736a791..fd383adb1d4a 100644 --- a/frame/beefy-mmr/src/tests.rs +++ b/frame/beefy-mmr/src/tests.rs @@ -71,7 +71,7 @@ fn should_contain_mmr_digest() { assert_eq!( System::digest().logs, vec![beefy_log(ConsensusLog::MmrRoot( - hex!("969d516e5279540ef38e4a710fb0645cab4c3b01e528be7285b85ec9c5fb55c8").into() + hex!("fa0275b19b2565089f7e2377ee73b9050e8d53bce108ef722a3251fd9d371d4b").into() ))] ); @@ -82,13 +82,13 @@ fn should_contain_mmr_digest() { System::digest().logs, vec![ beefy_log(ConsensusLog::MmrRoot( - hex!("969d516e5279540ef38e4a710fb0645cab4c3b01e528be7285b85ec9c5fb55c8").into() + hex!("fa0275b19b2565089f7e2377ee73b9050e8d53bce108ef722a3251fd9d371d4b").into() )), beefy_log(ConsensusLog::AuthoritiesChange( ValidatorSet::new(vec![mock_beefy_id(3), mock_beefy_id(4),], 1,).unwrap() )), beefy_log(ConsensusLog::MmrRoot( - hex!("8c42b7b040d262f7f2e26abeb61ab0c3c448f60c7f2f19e6ca0035d9bb3ae7e2").into() + hex!("85554fa7d4e863cce3cdce668c1ae82c0174ad37f8d1399284018bec9f9971c3").into() )), ] ); @@ -114,10 +114,8 @@ fn should_contain_valid_leaf_data() { root: hex!("176e73f1bf656478b728e28dd1a7733c98621b8acf830bff585949763dca7a96") .into(), }, - parachain_heads: hex!( - "ed893c8f8cc87195a5d4d2805b011506322036bcace79642aa3e94ab431e442e" - ) - .into(), + leaf_extra: hex!("55b8e9e1cc9f0db7776fac0ca66318ef8acfb8ec26db11e373120583e07ee648") + .to_vec(), } ); @@ -138,10 +136,8 @@ fn should_contain_valid_leaf_data() { root: hex!("9c6b2c1b0d0b25a008e6c882cc7b415f309965c72ad2b944ac0931048ca31cd5") .into(), }, - parachain_heads: hex!( - "ed893c8f8cc87195a5d4d2805b011506322036bcace79642aa3e94ab431e442e" - ) - .into(), + leaf_extra: hex!("55b8e9e1cc9f0db7776fac0ca66318ef8acfb8ec26db11e373120583e07ee648") + .to_vec() } ); } diff --git a/primitives/beefy/src/mmr.rs b/primitives/beefy/src/mmr.rs index 29f513629d01..426a1ba5ff80 100644 --- a/primitives/beefy/src/mmr.rs +++ b/primitives/beefy/src/mmr.rs @@ -26,12 +26,26 @@ //! but we imagine they will be useful for other chains that either want to bridge with Polkadot //! or are completely standalone, but heavily inspired by Polkadot. +use crate::Vec; use codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; +/// A provider for extra data that gets added to the Mmr leaf +pub trait BeefyDataProvider { + /// Return a vector of bytes, ideally should be a merkle root hash + fn extra_data() -> ExtraData; +} + +/// A default implementation for runtimes. +impl BeefyDataProvider> for () { + fn extra_data() -> Vec { + Vec::new() + } +} + /// A standard leaf that gets added every block to the MMR constructed by Substrate's `pallet_mmr`. #[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] -pub struct MmrLeaf { +pub struct MmrLeaf { /// Version of the leaf format. /// /// Can be used to enable future format migrations and compatibility. @@ -41,8 +55,9 @@ pub struct MmrLeaf { pub parent_number_and_hash: (BlockNumber, Hash), /// A merkle root of the next BEEFY authority set. pub beefy_next_authority_set: BeefyNextAuthoritySet, - /// A merkle root of all registered parachain heads. - pub parachain_heads: MerkleRoot, + /// Arbitrary extra leaf data to be used by downstream pallets to include custom data in the + /// [`MmrLeaf`] + pub leaf_extra: ExtraData, } /// A MMR leaf versioning scheme. From f9e909908ac74d43146f906edd3c5a8a79743aac Mon Sep 17 00:00:00 2001 From: driemworks Date: Fri, 1 Apr 2022 17:32:37 -0500 Subject: [PATCH 664/695] rpc accepts asset id, check for ownership when requesting bytes --- Cargo.lock | 23 +------ .../pallets/iris-assets/rpc/Cargo.toml | 1 + .../iris-assets/rpc/runtime-api/Cargo.toml | 2 + .../iris-assets/rpc/runtime-api/src/lib.rs | 8 +-- .../pallets/iris-assets/rpc/src/lib.rs | 19 +++--- .../pallets/iris-assets/src/lib.rs | 67 ++++++++++--------- .../pallets/iris-session/README.md | 4 +- .../pallets/iris-session/src/lib.rs | 4 +- bin/node-template/runtime/src/lib.rs | 7 +- frame/assets/src/lib.rs | 1 + frame/assets/src/types.rs | 2 +- 11 files changed, 62 insertions(+), 76 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f62fbd3ca01b..0756371a4ecf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4986,7 +4986,6 @@ dependencies = [ "pallet-im-online", "pallet-iris-assets", "pallet-iris-ledger", - "pallet-iris-offchain", "pallet-iris-rpc-runtime-api", "pallet-iris-session", "pallet-randomness-collective-flip", @@ -5841,26 +5840,6 @@ dependencies = [ "sp-std", ] -[[package]] -name = "pallet-iris-offchain" -version = "1.0.0" -dependencies = [ - "frame-benchmarking", - "frame-support", - "frame-system", - "log 0.4.14", - "pallet-assets", - "pallet-balances", - "pallet-iris-assets", - "parity-scale-codec", - "scale-info", - "sp-core", - "sp-io", - "sp-keystore", - "sp-runtime", - "sp-std", -] - [[package]] name = "pallet-iris-rpc" version = "4.0.0-dev" @@ -5875,6 +5854,7 @@ dependencies = [ "sp-core", "sp-rpc", "sp-runtime", + "sp-std", ] [[package]] @@ -5886,6 +5866,7 @@ dependencies = [ "sp-api", "sp-core", "sp-runtime", + "sp-std", ] [[package]] diff --git a/bin/node-template/pallets/iris-assets/rpc/Cargo.toml b/bin/node-template/pallets/iris-assets/rpc/Cargo.toml index 21f598288cb1..e35392debab3 100644 --- a/bin/node-template/pallets/iris-assets/rpc/Cargo.toml +++ b/bin/node-template/pallets/iris-assets/rpc/Cargo.toml @@ -19,6 +19,7 @@ jsonrpc-core-client = "18.0.0" jsonrpc-derive = "18.0.0" sp-api = { version = "4.0.0-dev", path = "../../../../../primitives/api" } +sp-std = { default-features = false, version = "4.0.0-dev", path = "../../../../../primitives/std" } sp-blockchain = { version = "4.0.0-dev", path = "../../../../../primitives/blockchain" } sp-core = { version = "4.0.0-dev", path = "../../../../../primitives/core" } sp-rpc = { version = "4.0.0-dev", path = "../../../../../primitives/rpc" } diff --git a/bin/node-template/pallets/iris-assets/rpc/runtime-api/Cargo.toml b/bin/node-template/pallets/iris-assets/rpc/runtime-api/Cargo.toml index 33d6e1bb675b..f5c23fc281be 100644 --- a/bin/node-template/pallets/iris-assets/rpc/runtime-api/Cargo.toml +++ b/bin/node-template/pallets/iris-assets/rpc/runtime-api/Cargo.toml @@ -16,6 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../../../../primitives/api" } sp-core = { version = "4.0.0-dev", default-features = false, path = "../../../../../../primitives/core" } +sp-std = { default-features = false, version = "4.0.0-dev", path = "../../../../../../primitives/std" } sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../../../../primitives/runtime" } pallet-iris-session = { version = "1.0.0", default-features = false, path = "../../../iris-session" } @@ -26,5 +27,6 @@ std = [ "sp-api/std", "sp-core/std", "sp-runtime/std", + "sp-std/std", "pallet-iris-session/std", ] diff --git a/bin/node-template/pallets/iris-assets/rpc/runtime-api/src/lib.rs b/bin/node-template/pallets/iris-assets/rpc/runtime-api/src/lib.rs index 4e5d901c2c90..3785b6f9e1ec 100644 --- a/bin/node-template/pallets/iris-assets/rpc/runtime-api/src/lib.rs +++ b/bin/node-template/pallets/iris-assets/rpc/runtime-api/src/lib.rs @@ -3,17 +3,13 @@ #![cfg_attr(not(feature = "std"), no_std)] use sp_core::Bytes; +use sp_std::vec::Vec; // declare the runtime API // it is implemented in the 'impl' block in the runtime amalgamator file (runtime/src/lib.rs) sp_api::decl_runtime_apis! { pub trait IrisApi { - fn retrieve_bytes( - signature: Bytes, - message: Bytes, - signer: Bytes, - asset_id: Bytes, - ) -> Bytes; + fn retrieve_bytes(asset_id: u32) -> Bytes; } } diff --git a/bin/node-template/pallets/iris-assets/rpc/src/lib.rs b/bin/node-template/pallets/iris-assets/rpc/src/lib.rs index 5ba3a55c3cd9..3d11bf76ae5f 100644 --- a/bin/node-template/pallets/iris-assets/rpc/src/lib.rs +++ b/bin/node-template/pallets/iris-assets/rpc/src/lib.rs @@ -4,22 +4,24 @@ use jsonrpc_derive::rpc; pub use pallet_iris_rpc_runtime_api::IrisApi as IrisRuntimeApi; use sp_api::ProvideRuntimeApi; use sp_blockchain::HeaderBackend; -use sp_core::Bytes; +use sp_core::{ + Bytes, + sr25519::{Signature, Public} +}; use sp_runtime::{ generic::BlockId, traits::{Block as BlockT}, }; use std::sync::Arc; +use codec::{Codec, Decode, Encode}; +use sp_std::vec::Vec; #[rpc] pub trait IrisApi { #[rpc(name = "iris_retrieveBytes")] fn retrieve_bytes( &self, - signature: Bytes, - message: Bytes, - signer: Bytes, - asset_id: Bytes, + asset_id: u32, at: Option, ) -> Result; } @@ -62,17 +64,14 @@ where { fn retrieve_bytes( &self, - signature: Bytes, - message: Bytes, - signer: Bytes, - asset_id: Bytes, + asset_id: u32, at: Option<::Hash>, ) -> Result { let api = self.client.runtime_api(); let at = BlockId::hash(at.unwrap_or_else(|| self.client.info().best_hash )); - let runtime_api_result = api.retrieve_bytes(&at, signature, message, signer, asset_id); + let runtime_api_result = api.retrieve_bytes(&at, asset_id); runtime_api_result.map_err(|e| RpcError{ code: ErrorCode::ServerError(Error::DecodeError.into()), message: "unable to query runtime api".into(), diff --git a/bin/node-template/pallets/iris-assets/src/lib.rs b/bin/node-template/pallets/iris-assets/src/lib.rs index ae880ce6306a..0a285ef1f8c1 100644 --- a/bin/node-template/pallets/iris-assets/src/lib.rs +++ b/bin/node-template/pallets/iris-assets/src/lib.rs @@ -332,7 +332,7 @@ pub mod pallet { Self::deposit_event(Event::AssetBurned(asset_id.clone())); Ok(()) - } + } /// request to fetch bytes from ipfs and add to offchain storage /// @@ -345,9 +345,12 @@ pub mod pallet { #[pallet::compact] asset_id: T::AssetId, ) -> DispatchResult { let who = ensure_signed(origin)?; - // verify asset access -> should check assets pallet - // ensure!(>::get(who.clone()).contains(asset_id), - // Error::::InvalidAssetId); + // verify asset access + // in the future this is where the composable access rules will be executed + // for now we just check if they account has a positive balance of assets + let true_asset_balance = >::account(asset_id.clone(), who.clone()).balance; + let zero_balance: T::Balance = 0u32.into(); + ensure!(true_asset_balance != zero_balance, Error::::InsufficientBalance); // submit command to dataqueue let owner = >::asset(asset_id.clone()).unwrap().owner; >::mutate( @@ -454,35 +457,39 @@ impl Pallet { /// ``` /// pub fn retrieve_bytes( - signature: Bytes, - message: Bytes, - signer: Bytes, - asset_id: Bytes, + asset_id: u32, ) -> Bytes where ::AssetId: From { + // TODO: remove all of this.. leaving it for now for posterity // convert Bytes type to types needed for verification - let sig: sp_core::sr25519::Signature = sr25519::Signature::from_slice(signature.to_vec().as_ref()); - let msg: Vec = message.to_vec(); - let account_bytes: [u8; 32] = signer.to_vec().try_into().unwrap(); - let public_key = sr25519::Public::from_raw(account_bytes); - - // signature verification - if sig.verify(msg.as_slice(), &public_key) { - // parse asset id - let asset_id_u32: u32 = String::from_utf8(asset_id.to_vec()).unwrap().parse().unwrap(); - let asset_id_type: T::AssetId = asset_id_u32.try_into().unwrap(); - // verify asset access - // if !>::get(public_key).contains(asset_id_type) { - // return Bytes(Vec::new()); - // } - // get CID and fetch from offchain storage - let cid = >::get(asset_id_type).to_vec(); - if let Some(data) = sp_io::offchain::local_storage_get(StorageKind::PERSISTENT, &cid) { - return Bytes(data.clone()); - } else { - return Bytes(Vec::new()); - } - } + // let sig: sp_core::sr25519::Signature = sr25519::Signature::from_slice(signature.to_vec().as_ref()); + // let msg: Vec = message.to_vec(); + // let account_bytes: [u8; 32] = signer.to_vec().try_into().unwrap(); + // let public_key = sr25519::Public::from_raw(account_bytes); + + // // signature verification + // if sig.verify(msg.as_slice(), &public_key) { + // // parse asset id + // let asset_id_u32: u32 = String::from_utf8(asset_id.to_vec()).unwrap().parse().unwrap(); + // let asset_id_type: T::AssetId = asset_id_u32.try_into().unwrap(); + // // verify asset access + // // if !>::get(public_key).contains(asset_id_type) { + // // return Bytes(Vec::new()); + // // } + // // get CID and fetch from offchain storage + // let cid = >::get(asset_id_type).to_vec(); + // if let Some(data) = sp_io::offchain::local_storage_get(StorageKind::PERSISTENT, &cid) { + // return Bytes(data.clone()); + // } else { + // return Bytes(Vec::new()); + // } + // } + let asset_id_type: T::AssetId = asset_id.try_into().unwrap(); + // get CID and fetch from offchain storage + let cid = >::get(asset_id_type).to_vec(); + if let Some(data) = sp_io::offchain::local_storage_get(StorageKind::PERSISTENT, &cid) { + return Bytes(data.clone()); + } Bytes(Vec::new()) } } \ No newline at end of file diff --git a/bin/node-template/pallets/iris-session/README.md b/bin/node-template/pallets/iris-session/README.md index 8d751a42207d..c469f24f376e 100644 --- a/bin/node-template/pallets/iris-session/README.md +++ b/bin/node-template/pallets/iris-session/README.md @@ -1 +1,3 @@ -License: Unlicense \ No newline at end of file +# Iris-Session + +License: Unlicense diff --git a/bin/node-template/pallets/iris-session/src/lib.rs b/bin/node-template/pallets/iris-session/src/lib.rs index 07f7b650823c..d6bece9622b6 100644 --- a/bin/node-template/pallets/iris-session/src/lib.rs +++ b/bin/node-template/pallets/iris-session/src/lib.rs @@ -886,8 +886,8 @@ impl Pallet { let cid = >::metadata( asset_id.clone() ); - // check balance: TODO: This is bad... should really check the pallet_assets storage to verify this - // but this works for now + // TODO: is this needed here? at this point we (will) have already + // verified the access rules ensure!( >::asset_access(requestor.clone()).contains(&asset_id), Error::::InsufficientBalance diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index c0c553e7632a..5380b5e0b270 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -743,12 +743,9 @@ impl_runtime_apis! { */ impl pallet_iris_rpc_runtime_api::IrisApi for Runtime { fn retrieve_bytes( - signature: Bytes, - message: Bytes, - signer: Bytes, - asset_id: Bytes, + asset_id: u32, ) -> Bytes { - IrisAssets::retrieve_bytes(signature, message, signer, asset_id) + IrisAssets::retrieve_bytes(asset_id) } } diff --git a/frame/assets/src/lib.rs b/frame/assets/src/lib.rs index 5cdb48b9672b..cf32e289446d 100644 --- a/frame/assets/src/lib.rs +++ b/frame/assets/src/lib.rs @@ -235,6 +235,7 @@ pub mod pallet { >; #[pallet::storage] + #[pallet::getter(fn account)] /// The number of units of assets held by any given account. pub(super) type Account, I: 'static = ()> = StorageDoubleMap< _, diff --git a/frame/assets/src/types.rs b/frame/assets/src/types.rs index 8e0de6f1173d..d3f349b9620d 100644 --- a/frame/assets/src/types.rs +++ b/frame/assets/src/types.rs @@ -79,7 +79,7 @@ pub struct Approval { #[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, Default, MaxEncodedLen, TypeInfo)] pub struct AssetBalance { /// The balance. - pub(super) balance: Balance, + pub balance: Balance, /// Whether the account is frozen. pub(super) is_frozen: bool, /// `true` if this balance gave the account a self-sufficient reference. From 1cb6c4624e595f2501981fa89a434cb68fcda09e Mon Sep 17 00:00:00 2001 From: driemworks Date: Fri, 1 Apr 2022 20:11:04 -0500 Subject: [PATCH 665/695] update docs --- .../pallets/iris-assets/src/tests.rs | 17 +++-------- .../pallets/iris-ledger/src/mock.rs | 4 +-- .../pallets/iris-ledger/src/tests.rs | 28 ++++--------------- 3 files changed, 12 insertions(+), 37 deletions(-) diff --git a/bin/node-template/pallets/iris-assets/src/tests.rs b/bin/node-template/pallets/iris-assets/src/tests.rs index fcad291b8a7c..2a79f9eb0fc7 100644 --- a/bin/node-template/pallets/iris-assets/src/tests.rs +++ b/bin/node-template/pallets/iris-assets/src/tests.rs @@ -2,11 +2,6 @@ use super::*; use frame_support::{assert_ok}; use mock::*; use sp_core::Pair; -// use sp_core::{ -// offchain::{testing, OffchainWorkerExt, TransactionPoolExt, OffchainDbExt} -// }; -// use sp_keystore::{testing::KeyStore, KeystoreExt, SyncCryptoStore}; -// use std::sync::Arc; #[test] fn iris_assets_initial_state() { @@ -111,8 +106,8 @@ fn iris_assets_submit_ipfs_add_results_works_for_valid_values() { // THEN: a new asset class is created // AND: A new entry is added to the AssetClassOwnership StorageDoubleMap - let asset_class_owner = crate::AssetClassOwnership::::get(id.clone()); - assert_eq!(asset_class_owner, p.clone().public()); + let new_asset_exists = crate::AssetClassOwnership::::get(p.public().clone()).contains(&id); + assert_eq!(new_asset_exists, true); }); } @@ -143,8 +138,8 @@ fn iris_assets_mint_tickets_works_for_valid_values() { )); // THEN: new assets are created and awarded to the benficiary // AND: A new entry is added to the AssetAccess StorageDoubleMap - let asset_class_owner = crate::AssetAccess::::get(p.clone().public(), id.clone()); - assert_eq!(asset_class_owner, p.clone().public()) + let asset_id_is_owned = crate::AssetAccess::::get(p.clone().public()).contains(&id); + assert_eq!(asset_id_is_owned, true); }); } @@ -174,10 +169,6 @@ fn iris_assets_can_transer_assets() { id.clone(), balance.clone(), )); - // THEN: new assets are created and awarded to the benficiary - // AND: A new entry is added to the AssetAccess StorageDoubleMap - let asset_class_owner = crate::AssetAccess::::get(p.clone().public(), id.clone()); - assert_eq!(asset_class_owner, p.clone().public()); // THEN: I can transfer my owned asset to another address assert_ok!(Iris::transfer_asset( Origin::signed(p.clone().public()), diff --git a/bin/node-template/pallets/iris-ledger/src/mock.rs b/bin/node-template/pallets/iris-ledger/src/mock.rs index 4e0743440e13..1253b115fc27 100644 --- a/bin/node-template/pallets/iris-ledger/src/mock.rs +++ b/bin/node-template/pallets/iris-ledger/src/mock.rs @@ -1,5 +1,5 @@ #![cfg(test)] -use crate::{self as pallet_iris_assets, Config}; +use crate::{self as pallet_iris_ledger, Config}; use frame_support::{construct_runtime, parameter_types}; use sp_core::{ Pair, @@ -78,9 +78,9 @@ impl pallet_balances::Config for Test { } impl Config for Test { - type Currency = Balances; type Call = Call; type Event = Event; + type IrisCurrency = Balances; } pub fn new_test_ext() -> sp_io::TestExternalities { diff --git a/bin/node-template/pallets/iris-ledger/src/tests.rs b/bin/node-template/pallets/iris-ledger/src/tests.rs index 0d6edf1beb8b..1f1897d91e23 100644 --- a/bin/node-template/pallets/iris-ledger/src/tests.rs +++ b/bin/node-template/pallets/iris-ledger/src/tests.rs @@ -8,27 +8,12 @@ use sp_core::{ use sp_keystore::{testing::KeyStore, KeystoreExt, SyncCryptoStore}; use std::sync::Arc; -#[test] -fn iris_ledger_initial_state() { - new_test_ext().execute_with(|| { - // Given: The node is initialized at block 0 - // When: I query runtime storagey - let ledger = crate::Ledger::::get(); - let len = ledger.len(); - // Then: Runtime storage is empty - assert_eq!(len, 0); - }); -} - #[test] fn iris_ledger_can_lock() { let (p, _) = sp_core::sr25519::Pair::generate(); let pairs = vec![(p.clone().public(), 10)]; new_test_ext_funded(pairs).execute_with(|| { - assert_ok!( - Origin::signed(p.clone().public()), - 1, - ); + assert_ok!(IrisLedger::lock_currency(Origin::signed(p.clone().public()), 1)); let mut locked_amount = crate::Ledger::::get(p.public().clone()); assert_eq!(1, locked_amount); }); @@ -41,14 +26,13 @@ fn iris_ledger_can_unlock_and_transfer() { let pairs = vec![(p.clone().public(), 10)]; new_test_ext_funded(pairs).execute_with(|| { - assert_ok!( - Origin::signed(p.clone().public()), - 1, - ); + assert_ok!(IrisLedger::lock_currency(Origin::signed(p.clone().public()), 1)); assert_ok!( - Origin::signed(p.clone().public()), - p2.clone().public(), + IrisLedger::unlock_currency_and_transfer( + Origin::signed(p.clone().public()), + p2.clone().public(), + ) ); let mut locked_amount = crate::Ledger::::get(p.public().clone()); assert_eq!(0, locked_amount); From 62fcc8abb7679221814fd3a76d36ad5eafb65657 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Sat, 2 Apr 2022 13:12:54 -0400 Subject: [PATCH 666/695] Add Limit to Tranasctional Layers (#10808) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * introduce hard limit to transactional * add single layer transactional * remove single_transactional * Update mod.rs * add tests * maybe fix contracts cc @athei * fmt * fix contract logic * Update frame/contracts/src/exec.rs Co-authored-by: Alexander Theißen * Update exec.rs * add unchecked and custom errors * Update lib.rs * Apply suggestions from code review Co-authored-by: Alexander Theißen * Replace storage access by atomics Co-authored-by: Alexander Theißen --- frame/contracts/src/exec.rs | 29 ++- frame/support/procedural/src/transactional.rs | 4 +- frame/support/src/storage/mod.rs | 208 +++++++++++++----- .../support/test/tests/storage_transaction.rs | 108 +++++---- primitives/runtime/src/lib.rs | 33 +++ 5 files changed, 273 insertions(+), 109 deletions(-) diff --git a/frame/contracts/src/exec.rs b/frame/contracts/src/exec.rs index e73b29e54378..7aa5c0b731fa 100644 --- a/frame/contracts/src/exec.rs +++ b/frame/contracts/src/exec.rs @@ -774,14 +774,27 @@ where // All changes performed by the contract are executed under a storage transaction. // This allows for roll back on error. Changes to the cached contract_info are - // comitted or rolled back when popping the frame. - let (success, output) = with_transaction(|| { - let output = do_transaction(); - match &output { - Ok(result) if !result.did_revert() => TransactionOutcome::Commit((true, output)), - _ => TransactionOutcome::Rollback((false, output)), - } - }); + // committed or rolled back when popping the frame. + // + // `with_transactional` may return an error caused by a limit in the + // transactional storage depth. + let transaction_outcome = + with_transaction(|| -> TransactionOutcome> { + let output = do_transaction(); + match &output { + Ok(result) if !result.did_revert() => + TransactionOutcome::Commit(Ok((true, output))), + _ => TransactionOutcome::Rollback(Ok((false, output))), + } + }); + + let (success, output) = match transaction_outcome { + // `with_transactional` executed successfully, and we have the expected output. + Ok((success, output)) => (success, output), + // `with_transactional` returned an error, and we propagate that error and note no state + // has changed. + Err(error) => (false, Err(error.into())), + }; self.pop_frame(success); output } diff --git a/frame/support/procedural/src/transactional.rs b/frame/support/procedural/src/transactional.rs index 66a8d083fb56..ba75fbc9737a 100644 --- a/frame/support/procedural/src/transactional.rs +++ b/frame/support/procedural/src/transactional.rs @@ -49,7 +49,9 @@ pub fn require_transactional(_attr: TokenStream, input: TokenStream) -> Result = RefCell::new(0); + pub fn get_transaction_level() -> Layer { + NUM_LEVELS.load(Ordering::SeqCst) } - pub fn require_transaction() { - let level = TRANSACTION_LEVEL.with(|v| *v.borrow()); - if level == 0 { - panic!("Require transaction not called within with_transaction"); - } + /// Increments the transaction level. Returns an error if levels go past the limit. + /// + /// Returns a guard that when dropped decrements the transaction level automatically. + pub fn inc_transaction_level() -> Result { + NUM_LEVELS + .fetch_update(Ordering::SeqCst, Ordering::SeqCst, |existing_levels| { + if existing_levels >= TRANSACTIONAL_LIMIT { + return None + } + // Cannot overflow because of check above. + Some(existing_levels + 1) + }) + .map_err(|_| ())?; + Ok(StorageLayerGuard) } - pub struct TransactionLevelGuard; + fn dec_transaction_level() { + NUM_LEVELS + .fetch_update(Ordering::SeqCst, Ordering::SeqCst, |existing_levels| { + if existing_levels == 0 { + log::warn!( + "We are underflowing with calculating transactional levels. Not great, but let's not panic...", + ); + None + } else { + // Cannot underflow because of checks above. + Some(existing_levels - 1) + } + }) + .ok(); + } - impl Drop for TransactionLevelGuard { - fn drop(&mut self) { - TRANSACTION_LEVEL.with(|v| *v.borrow_mut() -= 1); - } + pub fn is_transactional() -> bool { + get_transaction_level() > 0 } - /// Increments the transaction level. - /// - /// Returns a guard that when dropped decrements the transaction level automatically. - pub fn inc_transaction_level() -> TransactionLevelGuard { - TRANSACTION_LEVEL.with(|v| { - let mut val = v.borrow_mut(); - *val += 1; - if *val > 10 { - log::warn!( - "Detected with_transaction with nest level {}. Nested usage of with_transaction is not recommended.", - *val - ); - } - }); + pub struct StorageLayerGuard; - TransactionLevelGuard + impl Drop for StorageLayerGuard { + fn drop(&mut self) { + dec_transaction_level() + } } } -/// Assert this method is called within a storage transaction. -/// This will **panic** if is not called within a storage transaction. -/// -/// This assertion is enabled for native execution and when `debug_assertions` are enabled. -pub fn require_transaction() { - #[cfg(all(feature = "std", any(test, debug_assertions)))] - debug_helper::require_transaction(); +/// Check if the current call is within a transactional layer. +pub fn is_transactional() -> bool { + transaction_level_tracker::is_transactional() } /// Execute the supplied function in a new storage transaction. @@ -100,15 +113,55 @@ pub fn require_transaction() { /// All changes to storage performed by the supplied function are discarded if the returned /// outcome is `TransactionOutcome::Rollback`. /// -/// Transactions can be nested to any depth. Commits happen to the parent transaction. -pub fn with_transaction(f: impl FnOnce() -> TransactionOutcome) -> R { +/// Transactions can be nested up to `TRANSACTIONAL_LIMIT` times; more than that will result in an +/// error. +/// +/// Commits happen to the parent transaction. +pub fn with_transaction(f: impl FnOnce() -> TransactionOutcome>) -> Result +where + E: From, +{ use sp_io::storage::{commit_transaction, rollback_transaction, start_transaction}; use TransactionOutcome::*; + let _guard = transaction_level_tracker::inc_transaction_level() + .map_err(|()| TransactionalError::LimitReached.into())?; + start_transaction(); - #[cfg(all(feature = "std", any(test, debug_assertions)))] - let _guard = debug_helper::inc_transaction_level(); + match f() { + Commit(res) => { + commit_transaction(); + res + }, + Rollback(res) => { + rollback_transaction(); + res + }, + } +} + +/// Same as [`with_transaction`] but without a limit check on nested transactional layers. +/// +/// This is mostly for backwards compatibility before there was a transactional layer limit. +/// It is recommended to only use [`with_transaction`] to avoid users from generating too many +/// transactional layers. +pub fn with_transaction_unchecked(f: impl FnOnce() -> TransactionOutcome) -> R { + use sp_io::storage::{commit_transaction, rollback_transaction, start_transaction}; + use TransactionOutcome::*; + + let maybe_guard = transaction_level_tracker::inc_transaction_level(); + + if maybe_guard.is_err() { + log::warn!( + "The transactional layer limit has been reached, and new transactional layers are being + spawned with `with_transaction_unchecked`. This could be caused by someone trying to + attack your chain, and you should investigate usage of `with_transaction_unchecked` and + potentially migrate to `with_transaction`, which enforces a transactional limit.", + ); + } + + start_transaction(); match f() { Commit(res) => { @@ -1418,12 +1471,13 @@ pub fn storage_prefix(pallet_name: &[u8], storage_name: &[u8]) -> [u8; 32] { #[cfg(test)] mod test { use super::*; - use crate::{assert_ok, hash::Identity, Twox128}; + use crate::{assert_noop, assert_ok, hash::Identity, Twox128}; use bounded_vec::BoundedVec; use frame_support::traits::ConstU32; use generator::StorageValue as _; use sp_core::hashing::twox_128; use sp_io::TestExternalities; + use sp_runtime::DispatchResult; use weak_bounded_vec::WeakBoundedVec; #[test] @@ -1535,25 +1589,67 @@ mod test { } #[test] - #[should_panic(expected = "Require transaction not called within with_transaction")] - fn require_transaction_should_panic() { + fn is_transactional_should_return_false() { TestExternalities::default().execute_with(|| { - require_transaction(); + assert!(!is_transactional()); }); } #[test] - fn require_transaction_should_not_panic_in_with_transaction() { + fn is_transactional_should_not_error_in_with_transaction() { TestExternalities::default().execute_with(|| { - with_transaction(|| { - require_transaction(); - TransactionOutcome::Commit(()) - }); - - with_transaction(|| { - require_transaction(); - TransactionOutcome::Rollback(()) - }); + assert_ok!(with_transaction(|| -> TransactionOutcome { + assert!(is_transactional()); + TransactionOutcome::Commit(Ok(())) + })); + + assert_noop!( + with_transaction(|| -> TransactionOutcome { + assert!(is_transactional()); + TransactionOutcome::Rollback(Err("revert".into())) + }), + "revert" + ); + }); + } + + fn recursive_transactional(num: u32) -> DispatchResult { + if num == 0 { + return Ok(()) + } + + with_transaction(|| -> TransactionOutcome { + let res = recursive_transactional(num - 1); + TransactionOutcome::Commit(res) + }) + } + + #[test] + fn transaction_limit_should_work() { + TestExternalities::default().execute_with(|| { + assert_eq!(transaction_level_tracker::get_transaction_level(), 0); + + assert_ok!(with_transaction(|| -> TransactionOutcome { + assert_eq!(transaction_level_tracker::get_transaction_level(), 1); + TransactionOutcome::Commit(Ok(())) + })); + + assert_ok!(with_transaction(|| -> TransactionOutcome { + assert_eq!(transaction_level_tracker::get_transaction_level(), 1); + let res = with_transaction(|| -> TransactionOutcome { + assert_eq!(transaction_level_tracker::get_transaction_level(), 2); + TransactionOutcome::Commit(Ok(())) + }); + TransactionOutcome::Commit(res) + })); + + assert_ok!(recursive_transactional(255)); + assert_noop!( + recursive_transactional(256), + sp_runtime::TransactionalError::LimitReached + ); + + assert_eq!(transaction_level_tracker::get_transaction_level(), 0); }); } diff --git a/frame/support/test/tests/storage_transaction.rs b/frame/support/test/tests/storage_transaction.rs index 0f1c3a2e0c53..848a91a7f5a8 100644 --- a/frame/support/test/tests/storage_transaction.rs +++ b/frame/support/test/tests/storage_transaction.rs @@ -16,12 +16,13 @@ // limitations under the License. use frame_support::{ - assert_noop, assert_ok, + assert_noop, assert_ok, assert_storage_noop, dispatch::{DispatchError, DispatchResult}, storage::{with_transaction, TransactionOutcome::*}, transactional, StorageMap, StorageValue, }; use sp_io::TestExternalities; +use sp_runtime::TransactionOutcome; use sp_std::result; pub trait Config: frame_support_test::Config {} @@ -67,13 +68,13 @@ fn storage_transaction_basic_commit() { assert_eq!(Value::get(), 0); assert!(!Map::contains_key("val0")); - with_transaction(|| { + assert_ok!(with_transaction(|| -> TransactionOutcome { Value::set(99); Map::insert("val0", 99); assert_eq!(Value::get(), 99); assert_eq!(Map::get("val0"), 99); - Commit(()) - }); + Commit(Ok(())) + })); assert_eq!(Value::get(), 99); assert_eq!(Map::get("val0"), 99); @@ -86,13 +87,26 @@ fn storage_transaction_basic_rollback() { assert_eq!(Value::get(), 0); assert_eq!(Map::get("val0"), 0); - with_transaction(|| { - Value::set(99); - Map::insert("val0", 99); - assert_eq!(Value::get(), 99); - assert_eq!(Map::get("val0"), 99); - Rollback(()) - }); + assert_noop!( + with_transaction(|| -> TransactionOutcome { + Value::set(99); + Map::insert("val0", 99); + assert_eq!(Value::get(), 99); + assert_eq!(Map::get("val0"), 99); + Rollback(Err("revert".into())) + }), + "revert" + ); + + assert_storage_noop!(assert_ok!(with_transaction( + || -> TransactionOutcome { + Value::set(99); + Map::insert("val0", 99); + assert_eq!(Value::get(), 99); + assert_eq!(Map::get("val0"), 99); + Rollback(Ok(())) + } + ))); assert_eq!(Value::get(), 0); assert_eq!(Map::get("val0"), 0); @@ -105,32 +119,35 @@ fn storage_transaction_rollback_then_commit() { Value::set(1); Map::insert("val1", 1); - with_transaction(|| { + assert_ok!(with_transaction(|| -> TransactionOutcome { Value::set(2); Map::insert("val1", 2); Map::insert("val2", 2); - with_transaction(|| { - Value::set(3); - Map::insert("val1", 3); - Map::insert("val2", 3); - Map::insert("val3", 3); + assert_noop!( + with_transaction(|| -> TransactionOutcome { + Value::set(3); + Map::insert("val1", 3); + Map::insert("val2", 3); + Map::insert("val3", 3); - assert_eq!(Value::get(), 3); - assert_eq!(Map::get("val1"), 3); - assert_eq!(Map::get("val2"), 3); - assert_eq!(Map::get("val3"), 3); + assert_eq!(Value::get(), 3); + assert_eq!(Map::get("val1"), 3); + assert_eq!(Map::get("val2"), 3); + assert_eq!(Map::get("val3"), 3); - Rollback(()) - }); + Rollback(Err("revert".into())) + }), + "revert" + ); assert_eq!(Value::get(), 2); assert_eq!(Map::get("val1"), 2); assert_eq!(Map::get("val2"), 2); assert_eq!(Map::get("val3"), 0); - Commit(()) - }); + Commit(Ok(())) + })); assert_eq!(Value::get(), 2); assert_eq!(Map::get("val1"), 2); @@ -145,32 +162,35 @@ fn storage_transaction_commit_then_rollback() { Value::set(1); Map::insert("val1", 1); - with_transaction(|| { - Value::set(2); - Map::insert("val1", 2); - Map::insert("val2", 2); + assert_noop!( + with_transaction(|| -> TransactionOutcome { + Value::set(2); + Map::insert("val1", 2); + Map::insert("val2", 2); + + assert_ok!(with_transaction(|| -> TransactionOutcome { + Value::set(3); + Map::insert("val1", 3); + Map::insert("val2", 3); + Map::insert("val3", 3); - with_transaction(|| { - Value::set(3); - Map::insert("val1", 3); - Map::insert("val2", 3); - Map::insert("val3", 3); + assert_eq!(Value::get(), 3); + assert_eq!(Map::get("val1"), 3); + assert_eq!(Map::get("val2"), 3); + assert_eq!(Map::get("val3"), 3); + + Commit(Ok(())) + })); assert_eq!(Value::get(), 3); assert_eq!(Map::get("val1"), 3); assert_eq!(Map::get("val2"), 3); assert_eq!(Map::get("val3"), 3); - Commit(()) - }); - - assert_eq!(Value::get(), 3); - assert_eq!(Map::get("val1"), 3); - assert_eq!(Map::get("val2"), 3); - assert_eq!(Map::get("val3"), 3); - - Rollback(()) - }); + Rollback(Err("revert".into())) + }), + "revert" + ); assert_eq!(Value::get(), 1); assert_eq!(Map::get("val1"), 1); diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 337fac5812ae..c09db5124cc1 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -486,6 +486,31 @@ impl PartialEq for ModuleError { } } +/// Errors related to transactional storage layers. +#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, Debug, TypeInfo)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub enum TransactionalError { + /// Too many transactional layers have been spawned. + LimitReached, + /// A transactional layer was expected, but does not exist. + NoLayer, +} + +impl From for &'static str { + fn from(e: TransactionalError) -> &'static str { + match e { + TransactionalError::LimitReached => "Too many transactional layers have been spawned", + TransactionalError::NoLayer => "A transactional layer was expected, but does not exist", + } + } +} + +impl From for DispatchError { + fn from(e: TransactionalError) -> DispatchError { + Self::Transactional(e) + } +} + /// Reason why a dispatch call failed. #[derive(Eq, Clone, Copy, Encode, Decode, Debug, TypeInfo, PartialEq)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] @@ -512,6 +537,9 @@ pub enum DispatchError { Token(TokenError), /// An arithmetic error. Arithmetic(ArithmeticError), + /// The number of transactional layers has been reached, or we are not in a transactional + /// layer. + Transactional(TransactionalError), } /// Result of a `Dispatchable` which contains the `DispatchResult` and additional information about @@ -647,6 +675,7 @@ impl From for &'static str { DispatchError::TooManyConsumers => "Too many consumers", DispatchError::Token(e) => e.into(), DispatchError::Arithmetic(e) => e.into(), + DispatchError::Transactional(e) => e.into(), } } } @@ -685,6 +714,10 @@ impl traits::Printable for DispatchError { "Arithmetic error: ".print(); <&'static str>::from(*e).print(); }, + Self::Transactional(e) => { + "Transactional error: ".print(); + <&'static str>::from(*e).print(); + }, } } } From 284d38f9451b8fe52d780227ebb8d4776f2db017 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 3 Apr 2022 19:34:13 +0000 Subject: [PATCH 667/695] Bump futures from 0.3.19 to 0.3.21 (#11133) Bumps [futures](https://github.com/rust-lang/futures-rs) from 0.3.19 to 0.3.21. - [Release notes](https://github.com/rust-lang/futures-rs/releases) - [Changelog](https://github.com/rust-lang/futures-rs/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/futures-rs/compare/0.3.19...0.3.21) --- updated-dependencies: - dependency-name: futures dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 220 +++++++++--------- bin/node/bench/Cargo.toml | 2 +- bin/node/cli/Cargo.toml | 4 +- bin/node/executor/Cargo.toml | 2 +- bin/node/testing/Cargo.toml | 2 +- client/api/Cargo.toml | 2 +- client/authority-discovery/Cargo.toml | 2 +- client/basic-authorship/Cargo.toml | 2 +- client/beefy/rpc/Cargo.toml | 2 +- client/cli/Cargo.toml | 2 +- client/consensus/aura/Cargo.toml | 2 +- client/consensus/babe/Cargo.toml | 2 +- client/consensus/babe/rpc/Cargo.toml | 2 +- client/consensus/common/Cargo.toml | 2 +- client/consensus/manual-seal/Cargo.toml | 2 +- client/consensus/pow/Cargo.toml | 2 +- client/consensus/slots/Cargo.toml | 2 +- client/finality-grandpa/Cargo.toml | 2 +- client/informant/Cargo.toml | 2 +- client/network-gossip/Cargo.toml | 2 +- client/network/Cargo.toml | 2 +- client/network/test/Cargo.toml | 2 +- client/offchain/Cargo.toml | 2 +- client/peerset/Cargo.toml | 2 +- client/rpc-api/Cargo.toml | 2 +- client/rpc-servers/Cargo.toml | 2 +- client/rpc/Cargo.toml | 2 +- client/service/Cargo.toml | 2 +- client/service/test/Cargo.toml | 2 +- client/telemetry/Cargo.toml | 2 +- client/transaction-pool/Cargo.toml | 2 +- client/transaction-pool/api/Cargo.toml | 2 +- client/utils/Cargo.toml | 2 +- primitives/api/test/Cargo.toml | 2 +- primitives/blockchain/Cargo.toml | 2 +- primitives/consensus/common/Cargo.toml | 4 +- primitives/core/Cargo.toml | 2 +- primitives/inherents/Cargo.toml | 2 +- primitives/io/Cargo.toml | 2 +- primitives/keystore/Cargo.toml | 2 +- test-utils/client/Cargo.toml | 2 +- test-utils/runtime/Cargo.toml | 2 +- test-utils/runtime/client/Cargo.toml | 2 +- .../runtime/transaction-pool/Cargo.toml | 2 +- utils/frame/rpc/support/Cargo.toml | 2 +- utils/frame/rpc/system/Cargo.toml | 2 +- 46 files changed, 157 insertions(+), 157 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 03a04cedcbf2..6fb6f5814565 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -483,7 +483,7 @@ version = "4.0.0-dev" dependencies = [ "beefy-primitives", "fnv", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "hex", "log 0.4.14", @@ -525,7 +525,7 @@ version = "4.0.0-dev" dependencies = [ "beefy-gadget", "beefy-primitives", - "futures 0.3.19", + "futures 0.3.21", "jsonrpc-core", "jsonrpc-core-client", "jsonrpc-derive", @@ -1312,7 +1312,7 @@ dependencies = [ "clap 2.34.0", "criterion-plot", "csv", - "futures 0.3.19", + "futures 0.3.21", "itertools", "lazy_static", "num-traits", @@ -1967,7 +1967,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e43f2f1833d64e33f15592464d6fdd70f349dda7b1a53088eb83cd94014008c5" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", ] [[package]] @@ -2027,7 +2027,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9def033d8505edf199f6a5d07aa7e6d2d6185b164293b77f0efd108f4f3e11d" dependencies = [ "either", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "log 0.4.14", "num-traits", @@ -2480,9 +2480,9 @@ checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" [[package]] name = "futures" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28560757fe2bb34e79f907794bb6b22ae8b0e5c669b638a1132f2592b19035b4" +checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" dependencies = [ "futures-channel", "futures-core", @@ -2495,9 +2495,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3dda0b6588335f360afc675d0564c17a77a2bda81ca178a4b6081bd86c7f0b" +checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" dependencies = [ "futures-core", "futures-sink", @@ -2505,15 +2505,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c8ff0461b82559810cdccfde3215c3f373807f5e5232b71479bff7bb2583d7" +checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" [[package]] name = "futures-executor" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29d6d2ff5bb10fb95c85b8ce46538a2e5f5e7fdc755623a7d4529ab8a4ed9d2a" +checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" dependencies = [ "futures-core", "futures-task", @@ -2523,9 +2523,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f9d34af5a1aac6fb380f735fe510746c38067c5bf16c7fd250280503c971b2" +checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" [[package]] name = "futures-lite" @@ -2544,9 +2544,9 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dbd947adfffb0efc70599b3ddcf7b5597bb5fa9e245eb99f62b3a5f7bb8bd3c" +checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" dependencies = [ "proc-macro2", "quote", @@ -2566,15 +2566,15 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3055baccb68d74ff6480350f8d6eb8fcfa3aa11bdc1a1ae3afdd0514617d508" +checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" [[package]] name = "futures-task" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ee7c6485c30167ce4dfb83ac568a849fe53274c831081476ee13e0dce1aad72" +checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" [[package]] name = "futures-timer" @@ -2584,9 +2584,9 @@ checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" [[package]] name = "futures-util" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b5cf40b47a271f77a8b1bec03ca09044d99d2372c0de244e66430761127164" +checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" dependencies = [ "futures 0.1.31", "futures-channel", @@ -3103,7 +3103,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a6d52908d4ea4ab2bc22474ba149bf1011c8e2c3ebc1ff593ae28ac44f494b6" dependencies = [ "async-io", - "futures 0.3.19", + "futures 0.3.21", "futures-lite", "if-addrs", "ipnet", @@ -3258,7 +3258,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2b99d4207e2a04fb4581746903c2bb7eb376f88de9c699d0f3e10feeac0cd3a" dependencies = [ "derive_more", - "futures 0.3.19", + "futures 0.3.21", "hyper 0.14.16", "hyper-tls", "jsonrpc-core", @@ -3277,7 +3277,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14f7f76aef2d054868398427f6c54943cf3d1caa9a7ec7d0c38d69df97a965eb" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "futures-executor", "futures-util", "log 0.4.14", @@ -3292,7 +3292,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b51da17abecbdab3e3d4f26b01c5ec075e88d3abe3ab3b05dc9aa69392764ec0" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "jsonrpc-client-transports", ] @@ -3314,7 +3314,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1dea6e07251d9ce6a552abfb5d7ad6bc290a4596c8dcc3d795fae2bbdc1f3ff" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "hyper 0.14.16", "jsonrpc-core", "jsonrpc-server-utils", @@ -3330,7 +3330,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "382bb0206323ca7cda3dcd7e245cea86d37d02457a02a975e3378fb149a48845" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "jsonrpc-core", "jsonrpc-server-utils", "log 0.4.14", @@ -3345,7 +3345,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240f87695e6c6f62fb37f05c02c04953cf68d6408b8c1c89de85c7a0125b1011" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "jsonrpc-core", "lazy_static", "log 0.4.14", @@ -3361,7 +3361,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa4fdea130485b572c39a460d50888beb00afb3e35de23ccd7fad8ff19f0e0d4" dependencies = [ "bytes 1.1.0", - "futures 0.3.19", + "futures 0.3.21", "globset", "jsonrpc-core", "lazy_static", @@ -3378,7 +3378,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f892c7d766369475ab7b0669f417906302d7c0fb521285c0a0c92e52e7c8e946" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "jsonrpc-core", "jsonrpc-server-utils", "log 0.4.14", @@ -3416,7 +3416,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3303cdf246e6ab76e2866fb3d9acb6c76a068b1b28bd923a1b7a8122257ad7b5" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "http", "jsonrpsee-core", "jsonrpsee-types 0.8.0", @@ -3519,7 +3519,7 @@ dependencies = [ "arrayvec 0.7.1", "async-trait", "fnv", - "futures 0.3.19", + "futures 0.3.21", "http", "jsonrpsee-types 0.4.1", "log 0.4.14", @@ -3718,7 +3718,7 @@ checksum = "3bec54343492ba5940a6c555e512c6721139835d28c59bc22febece72dfd0d9d" dependencies = [ "atomic", "bytes 1.1.0", - "futures 0.3.19", + "futures 0.3.21", "lazy_static", "libp2p-core", "libp2p-deflate", @@ -3762,7 +3762,7 @@ dependencies = [ "ed25519-dalek", "either", "fnv", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "lazy_static", "libsecp256k1", @@ -3792,7 +3792,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51a800adb195f33de63f4b17b63fe64cfc23bf2c6a0d3d0d5321328664e65197" dependencies = [ "flate2", - "futures 0.3.19", + "futures 0.3.21", "libp2p-core", ] @@ -3803,7 +3803,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb8f89d15cb6e3c5bc22afff7513b11bab7856f2872d3cfba86f7f63a06bc498" dependencies = [ "async-std-resolver", - "futures 0.3.19", + "futures 0.3.21", "libp2p-core", "log 0.4.14", "smallvec 1.8.0", @@ -3818,7 +3818,7 @@ checksum = "aab3d7210901ea51b7bae2b581aa34521797af8c4ec738c980bda4a06434067f" dependencies = [ "cuckoofilter", "fnv", - "futures 0.3.19", + "futures 0.3.21", "libp2p-core", "libp2p-swarm", "log 0.4.14", @@ -3839,7 +3839,7 @@ dependencies = [ "byteorder", "bytes 1.1.0", "fnv", - "futures 0.3.19", + "futures 0.3.21", "hex_fmt", "libp2p-core", "libp2p-swarm", @@ -3860,7 +3860,7 @@ version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cca1275574183f288ff8b72d535d5ffa5ea9292ef7829af8b47dcb197c7b0dcd" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "libp2p-core", "libp2p-swarm", "log 0.4.14", @@ -3882,7 +3882,7 @@ dependencies = [ "bytes 1.1.0", "either", "fnv", - "futures 0.3.19", + "futures 0.3.21", "libp2p-core", "libp2p-swarm", "log 0.4.14", @@ -3906,7 +3906,7 @@ dependencies = [ "async-io", "data-encoding", "dns-parser", - "futures 0.3.19", + "futures 0.3.21", "if-watch", "lazy_static", "libp2p-core", @@ -3940,7 +3940,7 @@ checksum = "7f2cd64ef597f40e14bfce0497f50ecb63dd6d201c61796daeb4227078834fbf" dependencies = [ "asynchronous-codec 0.6.0", "bytes 1.1.0", - "futures 0.3.19", + "futures 0.3.21", "libp2p-core", "log 0.4.14", "nohash-hasher", @@ -3958,7 +3958,7 @@ checksum = "a8772c7a99088221bb7ca9c5c0574bf55046a7ab4c319f3619b275f28c8fb87a" dependencies = [ "bytes 1.1.0", "curve25519-dalek 3.0.2", - "futures 0.3.19", + "futures 0.3.21", "lazy_static", "libp2p-core", "log 0.4.14", @@ -3978,7 +3978,7 @@ version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80ef7b0ec5cf06530d9eb6cf59ae49d46a2c45663bde31c25a12f682664adbcf" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "libp2p-core", "libp2p-swarm", "log 0.4.14", @@ -3995,7 +3995,7 @@ checksum = "5fba1a6ff33e4a274c89a3b1d78b9f34f32af13265cc5c46c16938262d4e945a" dependencies = [ "asynchronous-codec 0.6.0", "bytes 1.1.0", - "futures 0.3.19", + "futures 0.3.21", "libp2p-core", "log 0.4.14", "prost", @@ -4010,7 +4010,7 @@ version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f1a458bbda880107b5b36fcb9b5a1ef0c329685da0e203ed692a8ebe64cc92c" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "log 0.4.14", "pin-project 1.0.10", "rand 0.7.3", @@ -4026,7 +4026,7 @@ checksum = "2852b61c90fa8ce3c8fcc2aba76e6cefc20d648f9df29157d6b3a916278ef3e3" dependencies = [ "asynchronous-codec 0.6.0", "bytes 1.1.0", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "libp2p-core", "libp2p-swarm", @@ -4049,7 +4049,7 @@ checksum = "14a6d2b9e7677eff61dc3d2854876aaf3976d84a01ef6664b610c77a0c9407c5" dependencies = [ "asynchronous-codec 0.6.0", "bimap", - "futures 0.3.19", + "futures 0.3.21", "libp2p-core", "libp2p-swarm", "log 0.4.14", @@ -4071,7 +4071,7 @@ checksum = "a877a4ced6d46bf84677e1974e8cf61fb434af73b2e96fb48d6cb6223a4634d8" dependencies = [ "async-trait", "bytes 1.1.0", - "futures 0.3.19", + "futures 0.3.21", "libp2p-core", "libp2p-swarm", "log 0.4.14", @@ -4089,7 +4089,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f5184a508f223bc100a12665517773fb8730e9f36fc09eefb670bf01b107ae9" dependencies = [ "either", - "futures 0.3.19", + "futures 0.3.21", "libp2p-core", "log 0.4.14", "rand 0.7.3", @@ -4115,7 +4115,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7399c5b6361ef525d41c11fcf51635724f832baf5819b30d3d873eabb4fbae4b" dependencies = [ "async-io", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "if-watch", "ipnet", @@ -4132,7 +4132,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8b7563e46218165dfd60f64b96f7ce84590d75f53ecbdc74a7dd01450dc5973" dependencies = [ "async-std", - "futures 0.3.19", + "futures 0.3.21", "libp2p-core", "log 0.4.14", ] @@ -4143,7 +4143,7 @@ version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1008a302b73c5020251f9708c653f5ed08368e530e247cc9cd2f109ff30042cf" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "js-sys", "libp2p-core", "parity-send-wrapper", @@ -4158,7 +4158,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22e12df82d1ed64969371a9e65ea92b91064658604cc2576c2757f18ead9a1cf" dependencies = [ "either", - "futures 0.3.19", + "futures 0.3.21", "futures-rustls", "libp2p-core", "log 0.4.14", @@ -4175,7 +4175,7 @@ version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e7362abb8867d7187e7e93df17f460d554c997fc5c8ac57dc1259057f6889af" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "libp2p-core", "parking_lot 0.11.2", "thiserror", @@ -4696,7 +4696,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d91ec0a2440aaff5f78ec35631a7027d50386c6163aa975f7caa0d5da4b6ff8" dependencies = [ "bytes 1.1.0", - "futures 0.3.19", + "futures 0.3.21", "log 0.4.14", "pin-project 1.0.10", "smallvec 1.8.0", @@ -4800,7 +4800,7 @@ dependencies = [ "clap 3.1.6", "derive_more", "fs_extra", - "futures 0.3.19", + "futures 0.3.21", "hash-db", "hex", "kvdb", @@ -4842,7 +4842,7 @@ dependencies = [ "frame-benchmarking-cli", "frame-system", "frame-system-rpc-runtime-api", - "futures 0.3.19", + "futures 0.3.21", "hex-literal", "jsonrpsee-ws-client 0.4.1", "log 0.4.14", @@ -4921,7 +4921,7 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", - "futures 0.3.19", + "futures 0.3.21", "node-primitives", "node-runtime", "node-testing", @@ -5182,7 +5182,7 @@ version = "3.0.0-dev" dependencies = [ "frame-system", "fs_extra", - "futures 0.3.19", + "futures 0.3.21", "log 0.4.14", "node-executor", "node-primitives", @@ -6766,7 +6766,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9981e32fb75e004cc148f5fb70342f393830e0a4aa62e3cc93b50976218d42b6" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "libc", "log 0.4.14", "rand 0.7.3", @@ -7975,7 +7975,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4da5fcb054c46f5a5dff833b129285a93d3f0179531735e6c866e8cc307d2020" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "pin-project 0.4.27", "static_assertions", ] @@ -8034,7 +8034,7 @@ name = "sc-authority-discovery" version = "0.10.0-dev" dependencies = [ "async-trait", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "ip_network", "libp2p", @@ -8062,7 +8062,7 @@ dependencies = [ name = "sc-basic-authorship" version = "0.10.0-dev" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "log 0.4.14", "parity-scale-codec", @@ -8132,7 +8132,7 @@ dependencies = [ "chrono", "clap 3.1.6", "fdlimit", - "futures 0.3.19", + "futures 0.3.21", "hex", "libp2p", "log 0.4.14", @@ -8168,7 +8168,7 @@ name = "sc-client-api" version = "4.0.0-dev" dependencies = [ "fnv", - "futures 0.3.19", + "futures 0.3.21", "hash-db", "log 0.4.14", "parity-scale-codec", @@ -8226,7 +8226,7 @@ name = "sc-consensus" version = "0.10.0-dev" dependencies = [ "async-trait", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "libp2p", "log 0.4.14", @@ -8250,7 +8250,7 @@ name = "sc-consensus-aura" version = "0.10.0-dev" dependencies = [ "async-trait", - "futures 0.3.19", + "futures 0.3.21", "log 0.4.14", "parity-scale-codec", "parking_lot 0.12.0", @@ -8288,7 +8288,7 @@ version = "0.10.0-dev" dependencies = [ "async-trait", "fork-tree", - "futures 0.3.19", + "futures 0.3.21", "log 0.4.14", "merlin", "num-bigint", @@ -8336,7 +8336,7 @@ dependencies = [ name = "sc-consensus-babe-rpc" version = "0.10.0-dev" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "jsonrpc-core", "jsonrpc-core-client", "jsonrpc-derive", @@ -8379,7 +8379,7 @@ version = "0.10.0-dev" dependencies = [ "assert_matches", "async-trait", - "futures 0.3.19", + "futures 0.3.21", "jsonrpc-core", "jsonrpc-core-client", "jsonrpc-derive", @@ -8417,7 +8417,7 @@ name = "sc-consensus-pow" version = "0.10.0-dev" dependencies = [ "async-trait", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "log 0.4.14", "parity-scale-codec", @@ -8441,7 +8441,7 @@ name = "sc-consensus-slots" version = "0.10.0-dev" dependencies = [ "async-trait", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "log 0.4.14", "parity-scale-codec", @@ -8573,7 +8573,7 @@ dependencies = [ "dyn-clone", "finality-grandpa", "fork-tree", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "hex", "log 0.4.14", @@ -8615,7 +8615,7 @@ name = "sc-finality-grandpa-rpc" version = "0.10.0-dev" dependencies = [ "finality-grandpa", - "futures 0.3.19", + "futures 0.3.21", "jsonrpc-core", "jsonrpc-core-client", "jsonrpc-derive", @@ -8642,7 +8642,7 @@ name = "sc-informant" version = "0.10.0-dev" dependencies = [ "ansi_term", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "log 0.4.14", "parity-util-mem", @@ -8682,7 +8682,7 @@ dependencies = [ "either", "fnv", "fork-tree", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "hex", "ip_network", @@ -8730,7 +8730,7 @@ version = "0.10.0-dev" dependencies = [ "ahash", "async-std", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "libp2p", "log 0.4.14", @@ -8749,7 +8749,7 @@ version = "0.8.0" dependencies = [ "async-std", "async-trait", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "libp2p", "log 0.4.14", @@ -8776,7 +8776,7 @@ version = "4.0.0-dev" dependencies = [ "bytes 1.1.0", "fnv", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "hex", "hyper 0.14.16", @@ -8810,7 +8810,7 @@ dependencies = [ name = "sc-peerset" version = "4.0.0-dev" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "libp2p", "log 0.4.14", "rand 0.7.3", @@ -8832,7 +8832,7 @@ name = "sc-rpc" version = "4.0.0-dev" dependencies = [ "assert_matches", - "futures 0.3.19", + "futures 0.3.21", "hash-db", "jsonrpc-core", "jsonrpc-pubsub", @@ -8868,7 +8868,7 @@ dependencies = [ name = "sc-rpc-api" version = "0.10.0-dev" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "jsonrpc-core", "jsonrpc-core-client", "jsonrpc-derive", @@ -8893,7 +8893,7 @@ dependencies = [ name = "sc-rpc-server" version = "4.0.0-dev" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "jsonrpc-core", "jsonrpc-http-server", "jsonrpc-ipc-server", @@ -8927,7 +8927,7 @@ dependencies = [ "async-trait", "directories", "exit-future", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "hash-db", "jsonrpc-core", @@ -8990,7 +8990,7 @@ name = "sc-service-test" version = "2.0.0" dependencies = [ "fdlimit", - "futures 0.3.19", + "futures 0.3.21", "hex", "hex-literal", "log 0.4.14", @@ -9059,7 +9059,7 @@ name = "sc-telemetry" version = "4.0.0-dev" dependencies = [ "chrono", - "futures 0.3.19", + "futures 0.3.21", "libp2p", "log 0.4.14", "parking_lot 0.12.0", @@ -9118,7 +9118,7 @@ version = "4.0.0-dev" dependencies = [ "assert_matches", "criterion", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "hex", "linked-hash-map", @@ -9150,7 +9150,7 @@ dependencies = [ name = "sc-transaction-pool-api" version = "4.0.0-dev" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "log 0.4.14", "serde", "sp-blockchain", @@ -9162,7 +9162,7 @@ dependencies = [ name = "sc-utils" version = "4.0.0-dev" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "lazy_static", "log 0.4.14", @@ -9639,7 +9639,7 @@ checksum = "b5c71ed3d54db0a699f4948e1bb3e45b450fa31fe602621dee6680361d569c88" dependencies = [ "base64 0.12.3", "bytes 0.5.6", - "futures 0.3.19", + "futures 0.3.21", "httparse", "log 0.4.14", "rand 0.7.3", @@ -9655,7 +9655,7 @@ dependencies = [ "base64 0.13.0", "bytes 1.1.0", "flate2", - "futures 0.3.19", + "futures 0.3.21", "httparse", "log 0.4.14", "rand 0.8.4", @@ -9695,7 +9695,7 @@ name = "sp-api-test" version = "2.0.1" dependencies = [ "criterion", - "futures 0.3.19", + "futures 0.3.21", "log 0.4.14", "parity-scale-codec", "rustversion", @@ -9800,7 +9800,7 @@ dependencies = [ name = "sp-blockchain" version = "4.0.0-dev" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "log 0.4.14", "lru 0.7.3", "parity-scale-codec", @@ -9818,7 +9818,7 @@ name = "sp-consensus" version = "0.10.0-dev" dependencies = [ "async-trait", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "log 0.4.14", "parity-scale-codec", @@ -9917,7 +9917,7 @@ dependencies = [ "criterion", "dyn-clonable", "ed25519-dalek", - "futures 0.3.19", + "futures 0.3.21", "hash-db", "hash256-std-hasher", "hex", @@ -10028,7 +10028,7 @@ name = "sp-inherents" version = "4.0.0-dev" dependencies = [ "async-trait", - "futures 0.3.19", + "futures 0.3.21", "impl-trait-for-tuples", "parity-scale-codec", "sp-core", @@ -10041,7 +10041,7 @@ dependencies = [ name = "sp-io" version = "6.0.0" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "hash-db", "libsecp256k1", "log 0.4.14", @@ -10076,7 +10076,7 @@ name = "sp-keystore" version = "0.12.0" dependencies = [ "async-trait", - "futures 0.3.19", + "futures 0.3.21", "merlin", "parity-scale-codec", "parking_lot 0.12.0", @@ -10599,7 +10599,7 @@ version = "3.0.0" dependencies = [ "frame-support", "frame-system", - "futures 0.3.19", + "futures 0.3.21", "jsonrpc-client-transports", "parity-scale-codec", "sc-rpc-api", @@ -10614,7 +10614,7 @@ name = "substrate-frame-rpc-system" version = "4.0.0-dev" dependencies = [ "frame-system-rpc-runtime-api", - "futures 0.3.19", + "futures 0.3.21", "jsonrpc-core", "jsonrpc-core-client", "jsonrpc-derive", @@ -10673,7 +10673,7 @@ name = "substrate-test-client" version = "2.0.1" dependencies = [ "async-trait", - "futures 0.3.19", + "futures 0.3.21", "hex", "parity-scale-codec", "sc-client-api", @@ -10702,7 +10702,7 @@ dependencies = [ "frame-support", "frame-system", "frame-system-rpc-runtime-api", - "futures 0.3.19", + "futures 0.3.21", "log 0.4.14", "memory-db", "pallet-babe", @@ -10744,7 +10744,7 @@ dependencies = [ name = "substrate-test-runtime-client" version = "2.0.0" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "parity-scale-codec", "sc-block-builder", "sc-client-api", @@ -10762,7 +10762,7 @@ dependencies = [ name = "substrate-test-runtime-transaction-pool" version = "2.0.0" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "parity-scale-codec", "parking_lot 0.12.0", "sc-transaction-pool", @@ -10777,7 +10777,7 @@ dependencies = [ name = "substrate-test-utils" version = "4.0.0-dev" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "sc-service", "substrate-test-utils-derive", "tokio", @@ -11809,7 +11809,7 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "js-sys", "parking_lot 0.11.2", "pin-utils", @@ -12465,7 +12465,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7d9028f208dd5e63c614be69f115c1b53cacc1111437d4c765185856666c107" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "log 0.4.14", "nohash-hasher", "parking_lot 0.11.2", diff --git a/bin/node/bench/Cargo.toml b/bin/node/bench/Cargo.toml index 7bdf46e2b660..45a959ac16b1 100644 --- a/bin/node/bench/Cargo.toml +++ b/bin/node/bench/Cargo.toml @@ -39,4 +39,4 @@ parity-util-mem = { version = "0.11.0", default-features = false, features = ["p parity-db = { version = "0.3" } sc-transaction-pool = { version = "4.0.0-dev", path = "../../../client/transaction-pool" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../../../client/transaction-pool/api" } -futures = { version = "0.3.19", features = ["thread-pool"] } +futures = { version = "0.3.21", features = ["thread-pool"] } diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index a1aa695bf3a1..d25c1b1f0bf8 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -37,7 +37,7 @@ crate-type = ["cdylib", "rlib"] clap = { version = "3.1.6", features = ["derive"], optional = true } codec = { package = "parity-scale-codec", version = "3.0.0" } serde = { version = "1.0.136", features = ["derive"] } -futures = "0.3.19" +futures = "0.3.21" hex-literal = "0.3.4" log = "0.4.8" rand = "0.8" @@ -116,7 +116,7 @@ sc-service-test = { version = "2.0.0", path = "../../../client/service/test" } sc-block-builder = { version = "0.10.0-dev", path = "../../../client/block-builder" } sp-tracing = { version = "5.0.0", path = "../../../primitives/tracing" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } -futures = "0.3.19" +futures = "0.3.21" tempfile = "3.1.0" assert_cmd = "2.0.2" nix = "0.23" diff --git a/bin/node/executor/Cargo.toml b/bin/node/executor/Cargo.toml index 21862ecf81b5..3425a0df65d9 100644 --- a/bin/node/executor/Cargo.toml +++ b/bin/node/executor/Cargo.toml @@ -40,7 +40,7 @@ sp-runtime = { version = "6.0.0", path = "../../../primitives/runtime" } sp-externalities = { version = "0.12.0", path = "../../../primitives/externalities" } sp-keyring = { version = "6.0.0", path = "../../../primitives/keyring" } wat = "1.0" -futures = "0.3.19" +futures = "0.3.21" [features] wasmtime = ["sc-executor/wasmtime"] diff --git a/bin/node/testing/Cargo.toml b/bin/node/testing/Cargo.toml index 36a25ab7d4a7..02d13f0c6471 100644 --- a/bin/node/testing/Cargo.toml +++ b/bin/node/testing/Cargo.toml @@ -48,4 +48,4 @@ sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" log = "0.4.8" tempfile = "3.1.0" fs_extra = "1" -futures = "0.3.19" +futures = "0.3.21" diff --git a/client/api/Cargo.toml b/client/api/Cargo.toml index 3d1802c379f0..d209a311f45b 100644 --- a/client/api/Cargo.toml +++ b/client/api/Cargo.toml @@ -21,7 +21,7 @@ sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/comm sc-executor = { version = "0.10.0-dev", path = "../executor" } sp-externalities = { version = "0.12.0", path = "../../primitives/externalities" } fnv = "1.0.6" -futures = "0.3.19" +futures = "0.3.21" hash-db = { version = "0.15.2", default-features = false } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } log = "0.4.8" diff --git a/client/authority-discovery/Cargo.toml b/client/authority-discovery/Cargo.toml index d866bafb29dc..ba432d073698 100644 --- a/client/authority-discovery/Cargo.toml +++ b/client/authority-discovery/Cargo.toml @@ -20,7 +20,7 @@ prost-build = "0.9" async-trait = "0.1" codec = { package = "parity-scale-codec", default-features = false, version = "3.0.0" } thiserror = "1.0" -futures = "0.3.19" +futures = "0.3.21" futures-timer = "3.0.1" ip_network = "0.4.1" libp2p = { version = "0.40.0", default-features = false, features = ["kad"] } diff --git a/client/basic-authorship/Cargo.toml b/client/basic-authorship/Cargo.toml index 4fd140835525..20560d4c834e 100644 --- a/client/basic-authorship/Cargo.toml +++ b/client/basic-authorship/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0" } -futures = "0.3.19" +futures = "0.3.21" futures-timer = "3.0.1" log = "0.4.8" prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.10.0-dev"} diff --git a/client/beefy/rpc/Cargo.toml b/client/beefy/rpc/Cargo.toml index ebbb9527f936..47f2558c5ee7 100644 --- a/client/beefy/rpc/Cargo.toml +++ b/client/beefy/rpc/Cargo.toml @@ -8,7 +8,7 @@ repository = "https://github.com/paritytech/substrate" description = "RPC for the BEEFY Client gadget for substrate" [dependencies] -futures = "0.3.19" +futures = "0.3.21" log = "0.4" parking_lot = "0.12.0" thiserror = "1.0" diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index 7725e25c0b81..1fabbca46968 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] chrono = "0.4.10" clap = { version = "3.1.6", features = ["derive"] } fdlimit = "0.2.1" -futures = "0.3.19" +futures = "0.3.21" hex = "0.4.2" libp2p = "0.40.0" log = "0.4.11" diff --git a/client/consensus/aura/Cargo.toml b/client/consensus/aura/Cargo.toml index 2ad61f2bc48d..ac90d35dbce3 100644 --- a/client/consensus/aura/Cargo.toml +++ b/client/consensus/aura/Cargo.toml @@ -23,7 +23,7 @@ sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/c sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/common" } sp-consensus-slots = { version = "0.10.0-dev", path = "../../../primitives/consensus/slots" } thiserror = "1.0" -futures = "0.3.19" +futures = "0.3.21" sp-inherents = { version = "4.0.0-dev", path = "../../../primitives/inherents" } log = "0.4.8" sp-core = { version = "6.0.0", path = "../../../primitives/core" } diff --git a/client/consensus/babe/Cargo.toml b/client/consensus/babe/Cargo.toml index a135807d707e..20cc359849f5 100644 --- a/client/consensus/babe/Cargo.toml +++ b/client/consensus/babe/Cargo.toml @@ -43,7 +43,7 @@ sc-consensus-slots = { version = "0.10.0-dev", path = "../slots" } sp-runtime = { version = "6.0.0", path = "../../../primitives/runtime" } fork-tree = { version = "3.0.0", path = "../../../utils/fork-tree" } prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.10.0-dev" } -futures = "0.3.19" +futures = "0.3.21" parking_lot = "0.12.0" log = "0.4.8" schnorrkel = { version = "0.9.1", features = ["preaudit_deprecated"] } diff --git a/client/consensus/babe/rpc/Cargo.toml b/client/consensus/babe/rpc/Cargo.toml index ee6549480a6d..cce4544f0970 100644 --- a/client/consensus/babe/rpc/Cargo.toml +++ b/client/consensus/babe/rpc/Cargo.toml @@ -23,7 +23,7 @@ serde = { version = "1.0.136", features = ["derive"] } sp-blockchain = { version = "4.0.0-dev", path = "../../../../primitives/blockchain" } sp-runtime = { version = "6.0.0", path = "../../../../primitives/runtime" } sc-consensus-epochs = { version = "0.10.0-dev", path = "../../epochs" } -futures = "0.3.19" +futures = "0.3.21" thiserror = "1.0" sp-api = { version = "4.0.0-dev", path = "../../../../primitives/api" } sp-consensus = { version = "0.10.0-dev", path = "../../../../primitives/consensus/common" } diff --git a/client/consensus/common/Cargo.toml b/client/consensus/common/Cargo.toml index 3c640a2363b6..4bd5cff457f5 100644 --- a/client/consensus/common/Cargo.toml +++ b/client/consensus/common/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] thiserror = "1.0.30" libp2p = { version = "0.40.0", default-features = false } log = "0.4.8" -futures = { version = "0.3.19", features = ["thread-pool"] } +futures = { version = "0.3.21", features = ["thread-pool"] } futures-timer = "3.0.1" sc-client-api = { version = "4.0.0-dev", path = "../../api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } diff --git a/client/consensus/manual-seal/Cargo.toml b/client/consensus/manual-seal/Cargo.toml index 62650d50ce4a..360cfe862f87 100644 --- a/client/consensus/manual-seal/Cargo.toml +++ b/client/consensus/manual-seal/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] thiserror = "1.0" -futures = "0.3.19" +futures = "0.3.21" jsonrpc-core = "18.0.0" jsonrpc-core-client = "18.0.0" jsonrpc-derive = "18.0.0" diff --git a/client/consensus/pow/Cargo.toml b/client/consensus/pow/Cargo.toml index 553ef60e8145..4ddbf0c0ead7 100644 --- a/client/consensus/pow/Cargo.toml +++ b/client/consensus/pow/Cargo.toml @@ -25,7 +25,7 @@ sp-consensus-pow = { version = "0.10.0-dev", path = "../../../primitives/consens sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" } sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/common" } log = "0.4.8" -futures = "0.3.19" +futures = "0.3.21" futures-timer = "3.0.1" parking_lot = "0.12.0" thiserror = "1.0" diff --git a/client/consensus/slots/Cargo.toml b/client/consensus/slots/Cargo.toml index 07e0c291f4a3..2884f8443e30 100644 --- a/client/consensus/slots/Cargo.toml +++ b/client/consensus/slots/Cargo.toml @@ -27,7 +27,7 @@ sc-telemetry = { version = "4.0.0-dev", path = "../../telemetry" } sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" } sp-inherents = { version = "4.0.0-dev", path = "../../../primitives/inherents" } sp-timestamp = { version = "4.0.0-dev", path = "../../../primitives/timestamp" } -futures = "0.3.19" +futures = "0.3.21" futures-timer = "3.0.1" log = "0.4.11" thiserror = "1.0.30" diff --git a/client/finality-grandpa/Cargo.toml b/client/finality-grandpa/Cargo.toml index b8b41ba70365..58dc22192c0c 100644 --- a/client/finality-grandpa/Cargo.toml +++ b/client/finality-grandpa/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] thiserror = "1.0" dyn-clone = "1.0" fork-tree = { version = "3.0.0", path = "../../utils/fork-tree" } -futures = "0.3.19" +futures = "0.3.21" futures-timer = "3.0.1" hex = "0.4.2" log = "0.4.8" diff --git a/client/informant/Cargo.toml b/client/informant/Cargo.toml index dba0555c6896..e58763a4ebcc 100644 --- a/client/informant/Cargo.toml +++ b/client/informant/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] ansi_term = "0.12.1" -futures = "0.3.19" +futures = "0.3.21" futures-timer = "3.0.1" log = "0.4.8" parity-util-mem = { version = "0.11.0", default-features = false, features = ["primitive-types"] } diff --git a/client/network-gossip/Cargo.toml b/client/network-gossip/Cargo.toml index c8410d6d1878..51f5b658402e 100644 --- a/client/network-gossip/Cargo.toml +++ b/client/network-gossip/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] -futures = "0.3.19" +futures = "0.3.21" futures-timer = "3.0.1" libp2p = { version = "0.40.0", default-features = false } log = "0.4.8" diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index cd33830c1efe..be69663b9a54 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -27,7 +27,7 @@ codec = { package = "parity-scale-codec", version = "3.0.0", features = [ either = "1.5.3" fnv = "1.0.6" fork-tree = { version = "3.0.0", path = "../../utils/fork-tree" } -futures = "0.3.19" +futures = "0.3.21" futures-timer = "3.0.2" asynchronous-codec = "0.5" hex = "0.4.0" diff --git a/client/network/test/Cargo.toml b/client/network/test/Cargo.toml index be15cbc807e2..b9505f97d14c 100644 --- a/client/network/test/Cargo.toml +++ b/client/network/test/Cargo.toml @@ -17,7 +17,7 @@ async-std = "1.10.0" sc-network = { version = "0.10.0-dev", path = "../" } log = "0.4.8" parking_lot = "0.12.0" -futures = "0.3.19" +futures = "0.3.21" futures-timer = "3.0.1" rand = "0.7.2" libp2p = { version = "0.40.0", default-features = false } diff --git a/client/offchain/Cargo.toml b/client/offchain/Cargo.toml index 3edba1f45704..6cb1f83e360b 100644 --- a/client/offchain/Cargo.toml +++ b/client/offchain/Cargo.toml @@ -17,7 +17,7 @@ bytes = "1.1" codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"] } hex = "0.4" fnv = "1.0.6" -futures = "0.3.19" +futures = "0.3.21" futures-timer = "3.0.2" num_cpus = "1.13" parking_lot = "0.12.0" diff --git a/client/peerset/Cargo.toml b/client/peerset/Cargo.toml index 12991eac81bd..b292f300ba35 100644 --- a/client/peerset/Cargo.toml +++ b/client/peerset/Cargo.toml @@ -14,7 +14,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -futures = "0.3.19" +futures = "0.3.21" libp2p = { version = "0.40.0", default-features = false } sc-utils = { version = "4.0.0-dev", path = "../utils"} log = "0.4.8" diff --git a/client/rpc-api/Cargo.toml b/client/rpc-api/Cargo.toml index 06deb0eef0ce..20a18ec6c61c 100644 --- a/client/rpc-api/Cargo.toml +++ b/client/rpc-api/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0" } -futures = "0.3.19" +futures = "0.3.21" jsonrpc-core = "18.0.0" jsonrpc-core-client = "18.0.0" jsonrpc-derive = "18.0.0" diff --git a/client/rpc-servers/Cargo.toml b/client/rpc-servers/Cargo.toml index 6b2c9f5aa373..c5af4ba200fe 100644 --- a/client/rpc-servers/Cargo.toml +++ b/client/rpc-servers/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -futures = "0.3.19" +futures = "0.3.21" jsonrpc-core = "18.0.0" pubsub = { package = "jsonrpc-pubsub", version = "18.0.0" } log = "0.4.8" diff --git a/client/rpc/Cargo.toml b/client/rpc/Cargo.toml index eeeb67f36261..4fea6501f693 100644 --- a/client/rpc/Cargo.toml +++ b/client/rpc/Cargo.toml @@ -17,7 +17,7 @@ sc-rpc-api = { version = "0.10.0-dev", path = "../rpc-api" } sc-client-api = { version = "4.0.0-dev", path = "../api" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } codec = { package = "parity-scale-codec", version = "3.0.0" } -futures = "0.3.19" +futures = "0.3.21" jsonrpc-pubsub = "18.0.0" log = "0.4.8" sp-core = { version = "6.0.0", path = "../../primitives/core" } diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index 2cb23fed40f2..47474217ebd2 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -23,7 +23,7 @@ test-helpers = [] [dependencies] thiserror = "1.0.30" -futures = "0.3.19" +futures = "0.3.21" jsonrpc-pubsub = "18.0" jsonrpc-core = "18.0" rand = "0.7.3" diff --git a/client/service/test/Cargo.toml b/client/service/test/Cargo.toml index fa3c49a2340a..ab92de4e84f8 100644 --- a/client/service/test/Cargo.toml +++ b/client/service/test/Cargo.toml @@ -26,7 +26,7 @@ sp-externalities = { version = "0.12.0", path = "../../../primitives/externaliti sp-trie = { version = "6.0.0", path = "../../../primitives/trie" } sp-storage = { version = "6.0.0", path = "../../../primitives/storage" } sc-client-db = { version = "0.10.0-dev", default-features = false, path = "../../db" } -futures = "0.3.19" +futures = "0.3.21" sc-service = { version = "0.10.0-dev", features = ["test-helpers"], path = "../../service" } sc-network = { version = "0.10.0-dev", path = "../../network" } sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" } diff --git a/client/telemetry/Cargo.toml b/client/telemetry/Cargo.toml index 6daa75f45362..67583e325f34 100644 --- a/client/telemetry/Cargo.toml +++ b/client/telemetry/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] parking_lot = "0.12.0" -futures = "0.3.19" +futures = "0.3.21" wasm-timer = "0.2.5" libp2p = { version = "0.40.0", default-features = false, features = ["dns-async-std", "tcp-async-io", "wasm-ext", "websocket"] } log = "0.4.8" diff --git a/client/transaction-pool/Cargo.toml b/client/transaction-pool/Cargo.toml index 4c9a341db6a2..df309760b847 100644 --- a/client/transaction-pool/Cargo.toml +++ b/client/transaction-pool/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0" } thiserror = "1.0.30" -futures = "0.3.19" +futures = "0.3.21" futures-timer = "3.0.2" log = "0.4.8" parity-util-mem = { version = "0.11.0", default-features = false, features = ["primitive-types"] } diff --git a/client/transaction-pool/api/Cargo.toml b/client/transaction-pool/api/Cargo.toml index b444be6c6e78..8dd5e7253f96 100644 --- a/client/transaction-pool/api/Cargo.toml +++ b/client/transaction-pool/api/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/paritytech/substrate/" description = "Transaction pool client facing API." [dependencies] -futures = "0.3.19" +futures = "0.3.21" log = "0.4.8" serde = { version = "1.0.136", features = ["derive"] } thiserror = "1.0.30" diff --git a/client/utils/Cargo.toml b/client/utils/Cargo.toml index a107aab1dbd6..2f1338577e37 100644 --- a/client/utils/Cargo.toml +++ b/client/utils/Cargo.toml @@ -10,7 +10,7 @@ description = "I/O for Substrate runtimes" readme = "README.md" [dependencies] -futures = "0.3.19" +futures = "0.3.21" lazy_static = "1.4.0" parking_lot = "0.12.0" prometheus = { version = "0.13.0", default-features = false } diff --git a/primitives/api/test/Cargo.toml b/primitives/api/test/Cargo.toml index 786639f393e9..9f9f399234db 100644 --- a/primitives/api/test/Cargo.toml +++ b/primitives/api/test/Cargo.toml @@ -26,7 +26,7 @@ rustversion = "1.0.6" [dev-dependencies] criterion = "0.3.0" -futures = "0.3.19" +futures = "0.3.21" log = "0.4.14" sp-core = { version = "6.0.0", path = "../../core" } diff --git a/primitives/blockchain/Cargo.toml b/primitives/blockchain/Cargo.toml index 4c9946b7a312..a79bc9c5591c 100644 --- a/primitives/blockchain/Cargo.toml +++ b/primitives/blockchain/Cargo.toml @@ -18,7 +18,7 @@ log = "0.4.11" lru = "0.7.3" parking_lot = "0.12.0" thiserror = "1.0.30" -futures = "0.3.19" +futures = "0.3.21" codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } sp-consensus = { version = "0.10.0-dev", path = "../consensus/common" } sp-runtime = { version = "6.0.0", path = "../runtime" } diff --git a/primitives/consensus/common/Cargo.toml b/primitives/consensus/common/Cargo.toml index c712eff28500..35bd7f33fbf4 100644 --- a/primitives/consensus/common/Cargo.toml +++ b/primitives/consensus/common/Cargo.toml @@ -18,7 +18,7 @@ async-trait = "0.1.42" codec = { package = "parity-scale-codec", version = "3.0.0", features = [ "derive", ] } -futures = { version = "0.3.19", features = ["thread-pool"] } +futures = { version = "0.3.21", features = ["thread-pool"] } log = "0.4.8" sp-core = { path = "../../core", version = "6.0.0"} sp-inherents = { version = "4.0.0-dev", path = "../../inherents" } @@ -30,7 +30,7 @@ sp-runtime = { version = "6.0.0", path = "../../runtime" } thiserror = "1.0.30" [dev-dependencies] -futures = "0.3.19" +futures = "0.3.21" sp-test-primitives = { version = "2.0.0", path = "../../test-primitives" } [features] diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index 413a11c9dc0a..74a159b2e7d3 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -41,7 +41,7 @@ sp-debug-derive = { version = "4.0.0", default-features = false, path = "../debu sp-storage = { version = "6.0.0", default-features = false, path = "../storage" } sp-externalities = { version = "0.12.0", optional = true, path = "../externalities" } parity-util-mem = { version = "0.11.0", default-features = false, features = ["primitive-types"] } -futures = { version = "0.3.19", optional = true } +futures = { version = "0.3.21", optional = true } dyn-clonable = { version = "0.9.0", optional = true } thiserror = { version = "1.0.30", optional = true } bitflags = "1.3" diff --git a/primitives/inherents/Cargo.toml b/primitives/inherents/Cargo.toml index a90fb67e2385..f7beb7bdfcf5 100644 --- a/primitives/inherents/Cargo.toml +++ b/primitives/inherents/Cargo.toml @@ -24,7 +24,7 @@ impl-trait-for-tuples = "0.2.0" async-trait = { version = "0.1.50", optional = true } [dev-dependencies] -futures = "0.3.19" +futures = "0.3.21" [features] default = [ "std" ] diff --git a/primitives/io/Cargo.toml b/primitives/io/Cargo.toml index c51e34b861b9..bdae6174a87c 100644 --- a/primitives/io/Cargo.toml +++ b/primitives/io/Cargo.toml @@ -28,7 +28,7 @@ sp-trie = { version = "6.0.0", optional = true, path = "../trie" } sp-externalities = { version = "0.12.0", optional = true, path = "../externalities" } sp-tracing = { version = "5.0.0", default-features = false, path = "../tracing" } log = { version = "0.4.8", optional = true } -futures = { version = "0.3.19", features = ["thread-pool"], optional = true } +futures = { version = "0.3.21", features = ["thread-pool"], optional = true } parking_lot = { version = "0.12.0", optional = true } secp256k1 = { version = "0.21.2", features = ["recovery", "global-context"], optional = true } tracing = { version = "0.1.29", default-features = false } diff --git a/primitives/keystore/Cargo.toml b/primitives/keystore/Cargo.toml index 7b1d1dd4ebc4..f201cb8518bc 100644 --- a/primitives/keystore/Cargo.toml +++ b/primitives/keystore/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] async-trait = "0.1.50" -futures = "0.3.19" +futures = "0.3.21" parking_lot = { version = "0.12.0", default-features = false } serde = { version = "1.0", optional = true } thiserror = "1.0" diff --git a/test-utils/client/Cargo.toml b/test-utils/client/Cargo.toml index 1f7115cf16cf..f99300f27eac 100644 --- a/test-utils/client/Cargo.toml +++ b/test-utils/client/Cargo.toml @@ -13,7 +13,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0" } -futures = "0.3.19" +futures = "0.3.21" hex = "0.4" serde = "1.0.136" serde_json = "1.0.79" diff --git a/test-utils/runtime/Cargo.toml b/test-utils/runtime/Cargo.toml index ad7dca5e08fb..cbefed27ca9b 100644 --- a/test-utils/runtime/Cargo.toml +++ b/test-utils/runtime/Cargo.toml @@ -56,7 +56,7 @@ sc-block-builder = { version = "0.10.0-dev", path = "../../client/block-builder" sc-executor = { version = "0.10.0-dev", path = "../../client/executor" } sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" } substrate-test-runtime-client = { version = "2.0.0", path = "./client" } -futures = "0.3.19" +futures = "0.3.21" [build-dependencies] substrate-wasm-builder = { version = "5.0.0-dev", path = "../../utils/wasm-builder" } diff --git a/test-utils/runtime/client/Cargo.toml b/test-utils/runtime/client/Cargo.toml index 642d754868f7..a22d9f302a9e 100644 --- a/test-utils/runtime/client/Cargo.toml +++ b/test-utils/runtime/client/Cargo.toml @@ -23,4 +23,4 @@ sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } codec = { package = "parity-scale-codec", version = "3.0.0" } sc-client-api = { version = "4.0.0-dev", path = "../../../client/api" } -futures = "0.3.19" +futures = "0.3.21" diff --git a/test-utils/runtime/transaction-pool/Cargo.toml b/test-utils/runtime/transaction-pool/Cargo.toml index 8bc75c9d4c05..59d576acdcb8 100644 --- a/test-utils/runtime/transaction-pool/Cargo.toml +++ b/test-utils/runtime/transaction-pool/Cargo.toml @@ -19,5 +19,5 @@ sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" sp-runtime = { version = "6.0.0", path = "../../../primitives/runtime" } sc-transaction-pool = { version = "4.0.0-dev", path = "../../../client/transaction-pool" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "../../../client/transaction-pool/api" } -futures = "0.3.19" +futures = "0.3.21" thiserror = "1.0" diff --git a/utils/frame/rpc/support/Cargo.toml b/utils/frame/rpc/support/Cargo.toml index 91ec47e34bd3..fe304370727f 100644 --- a/utils/frame/rpc/support/Cargo.toml +++ b/utils/frame/rpc/support/Cargo.toml @@ -15,7 +15,7 @@ description = "Substrate RPC for FRAME's support" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -futures = "0.3.19" +futures = "0.3.21" jsonrpc-client-transports = { version = "18.0.0", features = ["http"] } codec = { package = "parity-scale-codec", version = "3.0.0" } serde = "1" diff --git a/utils/frame/rpc/system/Cargo.toml b/utils/frame/rpc/system/Cargo.toml index 1015760efee6..31a6f93e847b 100644 --- a/utils/frame/rpc/system/Cargo.toml +++ b/utils/frame/rpc/system/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sc-client-api = { version = "4.0.0-dev", path = "../../../../client/api" } codec = { package = "parity-scale-codec", version = "3.0.0" } -futures = "0.3.19" +futures = "0.3.21" jsonrpc-core = "18.0.0" jsonrpc-core-client = "18.0.0" jsonrpc-derive = "18.0.0" From 01a3ad65d933cc58e79c04d114edb4d6c69b470a Mon Sep 17 00:00:00 2001 From: Qinxuan Chen Date: Mon, 4 Apr 2022 03:44:29 +0800 Subject: [PATCH 668/695] Remove useless imports (#11136) Because `TryInto`/`TryFrom` are in prelude by default from edition 2021 Signed-off-by: koushiro --- bin/node/cli/src/service.rs | 2 +- bin/node/cli/tests/common.rs | 1 - bin/node/cli/tests/running_the_node_and_interrupt.rs | 5 +---- bin/node/cli/tests/telemetry.rs | 2 +- bin/node/cli/tests/temp_base_path_works.rs | 1 - client/allocator/src/freeing_bump.rs | 1 - client/api/src/client.rs | 2 +- client/authority-discovery/src/worker.rs | 10 +++------- client/beefy/src/keystore.rs | 2 -- client/cli/src/commands/insert_key.rs | 2 +- client/cli/src/commands/utils.rs | 2 +- client/cli/src/commands/verify.rs | 2 +- client/cli/src/error.rs | 6 +++--- client/cli/src/params/mod.rs | 2 +- client/consensus/aura/src/lib.rs | 11 ++--------- client/consensus/babe/src/lib.rs | 3 +-- client/consensus/manual-seal/src/error.rs | 2 +- client/consensus/pow/src/lib.rs | 4 ++-- client/db/src/utils.rs | 2 +- client/executor/common/src/sandbox/wasmer_backend.rs | 2 +- client/finality-grandpa/rpc/src/lib.rs | 2 +- client/informant/src/display.rs | 6 +----- client/network-gossip/src/bridge.rs | 1 - client/network/src/config.rs | 1 - client/network/src/protocol.rs | 1 - .../protocol/notifications/upgrade/notifications.rs | 2 +- client/network/src/request_responses.rs | 1 - client/network/src/service.rs | 1 - client/network/src/service/out_events.rs | 1 - client/offchain/src/api.rs | 7 ++----- client/offchain/src/api/http.rs | 1 - client/offchain/src/api/timestamp.rs | 5 +---- client/rpc/src/author/mod.rs | 2 +- client/service/src/chain_ops/import_blocks.rs | 1 - client/service/src/config.rs | 2 +- client/service/src/metrics.rs | 2 +- client/transaction-pool/src/lib.rs | 1 - client/transaction-pool/tests/pool.rs | 4 +--- frame/assets/src/lib.rs | 2 +- frame/bags-list/fuzzer/src/main.rs | 1 - frame/bags-list/remote-tests/src/sanity_check.rs | 1 - frame/contracts/src/tests.rs | 1 - frame/conviction-voting/src/vote.rs | 2 +- frame/election-provider-support/src/mock.rs | 1 - frame/election-provider-support/src/tests.rs | 3 +-- frame/election-provider-support/src/traits.rs | 8 ++------ frame/im-online/src/lib.rs | 2 +- frame/preimage/src/lib.rs | 2 +- frame/proxy/src/lib.rs | 2 +- frame/randomness-collective-flip/src/lib.rs | 1 - frame/staking/reward-curve/src/lib.rs | 1 - frame/staking/src/lib.rs | 2 +- frame/staking/src/pallet/mod.rs | 2 +- .../procedural/src/construct_runtime/expand/event.rs | 2 +- .../procedural/src/construct_runtime/expand/origin.rs | 4 ++-- frame/support/procedural/src/pallet/expand/error.rs | 2 +- frame/support/src/error.rs | 2 +- frame/support/src/lib.rs | 2 -- frame/support/src/storage/bounded_btree_map.rs | 5 +---- frame/support/src/storage/bounded_btree_set.rs | 6 +----- frame/support/src/storage/weak_bounded_vec.rs | 3 +-- frame/uniques/src/benchmarking.rs | 2 +- frame/vesting/src/lib.rs | 2 +- primitives/application-crypto/src/lib.rs | 8 ++++---- primitives/arithmetic/fuzzer/src/biguint.rs | 1 - primitives/arithmetic/fuzzer/src/normalize.rs | 1 - primitives/arithmetic/src/biguint.rs | 3 +-- primitives/arithmetic/src/fixed_point.rs | 1 - primitives/arithmetic/src/helpers_128bit.rs | 1 - primitives/arithmetic/src/lib.rs | 2 +- primitives/arithmetic/src/per_things.rs | 1 - primitives/arithmetic/src/traits.rs | 8 ++------ primitives/consensus/common/src/error.rs | 4 ++-- primitives/consensus/vrf/src/schnorrkel.rs | 1 - primitives/core/src/crypto.rs | 4 ++-- primitives/core/src/ecdsa.rs | 4 ++-- primitives/core/src/ed25519.rs | 6 ++---- primitives/core/src/offchain/mod.rs | 5 +---- primitives/core/src/sr25519.rs | 6 ++---- primitives/rpc/src/number.rs | 5 +---- .../runtime-interface/proc-macro/src/pass_by/enum_.rs | 2 +- primitives/runtime-interface/src/pass_by.rs | 4 ++-- primitives/runtime-interface/test-wasm/src/lib.rs | 2 +- primitives/runtime/src/curve.rs | 4 ---- primitives/runtime/src/generic/header.rs | 2 +- primitives/runtime/src/lib.rs | 2 +- primitives/runtime/src/traits.rs | 8 +------- primitives/std/src/lib.rs | 1 - primitives/storage/src/lib.rs | 2 +- primitives/wasm-interface/src/lib.rs | 2 +- utils/prometheus/src/lib.rs | 1 - 91 files changed, 81 insertions(+), 176 deletions(-) diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index 038c14029cf3..03e7311fb3c0 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -562,7 +562,7 @@ mod tests { RuntimeAppPublic, }; use sp_timestamp; - use std::{borrow::Cow, convert::TryInto, sync::Arc}; + use std::{borrow::Cow, sync::Arc}; type AccountPublic = ::Signer; diff --git a/bin/node/cli/tests/common.rs b/bin/node/cli/tests/common.rs index 8391cff35596..c17cabfa1d38 100644 --- a/bin/node/cli/tests/common.rs +++ b/bin/node/cli/tests/common.rs @@ -26,7 +26,6 @@ use nix::{ use node_primitives::Block; use remote_externalities::rpc_api; use std::{ - convert::TryInto, ops::{Deref, DerefMut}, path::Path, process::{Child, Command, ExitStatus}, diff --git a/bin/node/cli/tests/running_the_node_and_interrupt.rs b/bin/node/cli/tests/running_the_node_and_interrupt.rs index edce2bbc6e4c..703123faf0e6 100644 --- a/bin/node/cli/tests/running_the_node_and_interrupt.rs +++ b/bin/node/cli/tests/running_the_node_and_interrupt.rs @@ -25,10 +25,7 @@ use nix::{ }, unistd::Pid, }; -use std::{ - convert::TryInto, - process::{Child, Command}, -}; +use std::process::{Child, Command}; use tempfile::tempdir; pub mod common; diff --git a/bin/node/cli/tests/telemetry.rs b/bin/node/cli/tests/telemetry.rs index 212fec7a02cf..64da4bd4b68f 100644 --- a/bin/node/cli/tests/telemetry.rs +++ b/bin/node/cli/tests/telemetry.rs @@ -21,7 +21,7 @@ use nix::{ sys::signal::{kill, Signal::SIGINT}, unistd::Pid, }; -use std::{convert::TryInto, process}; +use std::process; pub mod common; pub mod websocket_server; diff --git a/bin/node/cli/tests/temp_base_path_works.rs b/bin/node/cli/tests/temp_base_path_works.rs index a5b9b7499fc4..306c490c2f76 100644 --- a/bin/node/cli/tests/temp_base_path_works.rs +++ b/bin/node/cli/tests/temp_base_path_works.rs @@ -25,7 +25,6 @@ use nix::{ }; use regex::Regex; use std::{ - convert::TryInto, io::Read, path::PathBuf, process::{Command, Stdio}, diff --git a/client/allocator/src/freeing_bump.rs b/client/allocator/src/freeing_bump.rs index d7152f5a209e..7eeda45370b8 100644 --- a/client/allocator/src/freeing_bump.rs +++ b/client/allocator/src/freeing_bump.rs @@ -71,7 +71,6 @@ use crate::Error; pub use sp_core::MAX_POSSIBLE_ALLOCATION; use sp_wasm_interface::{Pointer, WordSize}; use std::{ - convert::{TryFrom, TryInto}, mem, ops::{Index, IndexMut, Range}, }; diff --git a/client/api/src/client.rs b/client/api/src/client.rs index 11195e1def28..9c55be323813 100644 --- a/client/api/src/client.rs +++ b/client/api/src/client.rs @@ -25,7 +25,7 @@ use sp_runtime::{ traits::{Block as BlockT, NumberFor}, Justifications, }; -use std::{collections::HashSet, convert::TryFrom, fmt, sync::Arc}; +use std::{collections::HashSet, fmt, sync::Arc}; use crate::{blockchain::Info, notifications::StorageEventStream, FinalizeSummary, ImportSummary}; diff --git a/client/authority-discovery/src/worker.rs b/client/authority-discovery/src/worker.rs index 019abaac3cfc..726c032281cd 100644 --- a/client/authority-discovery/src/worker.rs +++ b/client/authority-discovery/src/worker.rs @@ -24,7 +24,6 @@ use crate::{ use std::{ collections::{HashMap, HashSet}, - convert::TryInto, marker::PhantomData, sync::Arc, time::Duration, @@ -581,14 +580,11 @@ where .authorities(&id) .map_err(|e| Error::CallingRuntime(e.into()))? .into_iter() - .map(std::convert::Into::into) + .map(Into::into) .collect::>(); - let intersection = local_pub_keys - .intersection(&authorities) - .cloned() - .map(std::convert::Into::into) - .collect(); + let intersection = + local_pub_keys.intersection(&authorities).cloned().map(Into::into).collect(); Ok(intersection) } diff --git a/client/beefy/src/keystore.rs b/client/beefy/src/keystore.rs index 32478a11434f..b0259a42075e 100644 --- a/client/beefy/src/keystore.rs +++ b/client/beefy/src/keystore.rs @@ -16,8 +16,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::convert::{From, TryInto}; - use sp_application_crypto::RuntimeAppPublic; use sp_core::keccak_256; use sp_keystore::{SyncCryptoStore, SyncCryptoStorePtr}; diff --git a/client/cli/src/commands/insert_key.rs b/client/cli/src/commands/insert_key.rs index 852b4e50376f..68201d7b4bff 100644 --- a/client/cli/src/commands/insert_key.rs +++ b/client/cli/src/commands/insert_key.rs @@ -25,7 +25,7 @@ use sc_keystore::LocalKeystore; use sc_service::config::{BasePath, KeystoreConfig}; use sp_core::crypto::{KeyTypeId, SecretString}; use sp_keystore::{SyncCryptoStore, SyncCryptoStorePtr}; -use std::{convert::TryFrom, sync::Arc}; +use std::sync::Arc; /// The `insert` command #[derive(Debug, Clone, Parser)] diff --git a/client/cli/src/commands/utils.rs b/client/cli/src/commands/utils.rs index d20df01e5a90..fa776c25a2ed 100644 --- a/client/cli/src/commands/utils.rs +++ b/client/cli/src/commands/utils.rs @@ -31,7 +31,7 @@ use sp_core::{ Pair, }; use sp_runtime::{traits::IdentifyAccount, MultiSigner}; -use std::{convert::TryFrom, io::Read, path::PathBuf}; +use std::{io::Read, path::PathBuf}; /// Public key type for Runtime pub type PublicFor

=

::Public; diff --git a/client/cli/src/commands/verify.rs b/client/cli/src/commands/verify.rs index a8879f42caaf..b004a948a7a4 100644 --- a/client/cli/src/commands/verify.rs +++ b/client/cli/src/commands/verify.rs @@ -66,7 +66,7 @@ impl VerifyCmd { fn verify(sig_data: Vec, message: Vec, uri: &str) -> error::Result<()> where Pair: sp_core::Pair, - Pair::Signature: for<'a> std::convert::TryFrom<&'a [u8]>, + Pair::Signature: for<'a> TryFrom<&'a [u8]>, { let signature = Pair::Signature::try_from(&sig_data).map_err(|_| error::Error::SignatureFormatInvalid)?; diff --git a/client/cli/src/error.rs b/client/cli/src/error.rs index 69b2eeaaf618..f38a95e0115f 100644 --- a/client/cli/src/error.rs +++ b/client/cli/src/error.rs @@ -80,19 +80,19 @@ pub enum Error { GlobalLoggerError(#[from] sc_tracing::logging::Error), } -impl std::convert::From<&str> for Error { +impl From<&str> for Error { fn from(s: &str) -> Error { Error::Input(s.to_string()) } } -impl std::convert::From for Error { +impl From for Error { fn from(s: String) -> Error { Error::Input(s) } } -impl std::convert::From for Error { +impl From for Error { fn from(e: crypto::PublicError) -> Error { Error::InvalidUri(e) } diff --git a/client/cli/src/params/mod.rs b/client/cli/src/params/mod.rs index e0571aa4bbbf..33e714ec138b 100644 --- a/client/cli/src/params/mod.rs +++ b/client/cli/src/params/mod.rs @@ -32,7 +32,7 @@ use sp_runtime::{ generic::BlockId, traits::{Block as BlockT, NumberFor}, }; -use std::{convert::TryFrom, fmt::Debug, str::FromStr}; +use std::{fmt::Debug, str::FromStr}; pub use crate::params::{ database_params::*, import_params::*, keystore_params::*, network_params::*, diff --git a/client/consensus/aura/src/lib.rs b/client/consensus/aura/src/lib.rs index 4d91eaaae92a..f6ea2e08e1e8 100644 --- a/client/consensus/aura/src/lib.rs +++ b/client/consensus/aura/src/lib.rs @@ -30,14 +30,7 @@ //! //! NOTE: Aura itself is designed to be generic over the crypto used. #![forbid(missing_docs, unsafe_code)] -use std::{ - convert::{TryFrom, TryInto}, - fmt::Debug, - hash::Hash, - marker::PhantomData, - pin::Pin, - sync::Arc, -}; +use std::{fmt::Debug, hash::Hash, marker::PhantomData, pin::Pin, sync::Arc}; use futures::prelude::*; use log::{debug, trace}; @@ -517,7 +510,7 @@ pub enum Error { Inherent(sp_inherents::Error), } -impl std::convert::From> for String { +impl From> for String { fn from(error: Error) -> String { error.to_string() } diff --git a/client/consensus/babe/src/lib.rs b/client/consensus/babe/src/lib.rs index 4f3139a013d4..818384a5c3d7 100644 --- a/client/consensus/babe/src/lib.rs +++ b/client/consensus/babe/src/lib.rs @@ -69,7 +69,6 @@ use std::{ borrow::Cow, collections::{HashMap, HashSet}, - convert::TryInto, future::Future, pin::Pin, sync::Arc, @@ -320,7 +319,7 @@ pub enum Error { ForkTree(Box>), } -impl std::convert::From> for String { +impl From> for String { fn from(error: Error) -> String { error.to_string() } diff --git a/client/consensus/manual-seal/src/error.rs b/client/consensus/manual-seal/src/error.rs index 2f946f3de3cc..7c3211203bf5 100644 --- a/client/consensus/manual-seal/src/error.rs +++ b/client/consensus/manual-seal/src/error.rs @@ -102,7 +102,7 @@ impl Error { } } -impl std::convert::From for jsonrpc_core::Error { +impl From for jsonrpc_core::Error { fn from(error: Error) -> Self { jsonrpc_core::Error { code: jsonrpc_core::ErrorCode::ServerError(error.to_code()), diff --git a/client/consensus/pow/src/lib.rs b/client/consensus/pow/src/lib.rs index 6d0bc3fc5a19..8885099ceb51 100644 --- a/client/consensus/pow/src/lib.rs +++ b/client/consensus/pow/src/lib.rs @@ -119,13 +119,13 @@ pub enum Error { Other(String), } -impl std::convert::From> for String { +impl From> for String { fn from(error: Error) -> String { error.to_string() } } -impl std::convert::From> for ConsensusError { +impl From> for ConsensusError { fn from(error: Error) -> ConsensusError { ConsensusError::ClientImport(error.to_string()) } diff --git a/client/db/src/utils.rs b/client/db/src/utils.rs index 29aa8424221a..1798838ecc15 100644 --- a/client/db/src/utils.rs +++ b/client/db/src/utils.rs @@ -19,7 +19,7 @@ //! Db-based backend utility structures and functions, used by both //! full and light storages. -use std::{convert::TryInto, fmt, fs, io, path::Path, sync::Arc}; +use std::{fmt, fs, io, path::Path, sync::Arc}; use log::{debug, info}; diff --git a/client/executor/common/src/sandbox/wasmer_backend.rs b/client/executor/common/src/sandbox/wasmer_backend.rs index dfb26c4a8ded..904afc947040 100644 --- a/client/executor/common/src/sandbox/wasmer_backend.rs +++ b/client/executor/common/src/sandbox/wasmer_backend.rs @@ -26,7 +26,7 @@ use crate::{ use codec::{Decode, Encode}; use sp_core::sandbox::HostError; use sp_wasm_interface::{FunctionContext, Pointer, ReturnValue, Value, WordSize}; -use std::{cell::RefCell, collections::HashMap, convert::TryInto, rc::Rc}; +use std::{cell::RefCell, collections::HashMap, rc::Rc}; use wasmer::RuntimeError; use crate::sandbox::{ diff --git a/client/finality-grandpa/rpc/src/lib.rs b/client/finality-grandpa/rpc/src/lib.rs index bde2e5612b2e..9c51bc3d226a 100644 --- a/client/finality-grandpa/rpc/src/lib.rs +++ b/client/finality-grandpa/rpc/src/lib.rs @@ -171,7 +171,7 @@ where mod tests { use super::*; use jsonrpc_core::{types::Params, Notification, Output}; - use std::{collections::HashSet, convert::TryInto, sync::Arc}; + use std::{collections::HashSet, sync::Arc}; use parity_scale_codec::{Decode, Encode}; use sc_block_builder::{BlockBuilder, RecordProof}; diff --git a/client/informant/src/display.rs b/client/informant/src/display.rs index 8d76939fddd6..77b28dec5565 100644 --- a/client/informant/src/display.rs +++ b/client/informant/src/display.rs @@ -22,11 +22,7 @@ use log::info; use sc_client_api::ClientInfo; use sc_network::{NetworkStatus, SyncState, WarpSyncPhase, WarpSyncProgress}; use sp_runtime::traits::{Block as BlockT, CheckedDiv, NumberFor, Saturating, Zero}; -use std::{ - convert::{TryFrom, TryInto}, - fmt, - time::Instant, -}; +use std::{fmt, time::Instant}; /// State of the informant display system. /// diff --git a/client/network-gossip/src/bridge.rs b/client/network-gossip/src/bridge.rs index f72cd1561651..2e09e7cc614a 100644 --- a/client/network-gossip/src/bridge.rs +++ b/client/network-gossip/src/bridge.rs @@ -303,7 +303,6 @@ mod tests { use sp_runtime::{testing::H256, traits::Block as BlockT}; use std::{ borrow::Cow, - convert::TryInto, sync::{Arc, Mutex}, }; use substrate_test_runtime_client::runtime::Block; diff --git a/client/network/src/config.rs b/client/network/src/config.rs index eedf3fc22b96..7c2dfef7fe89 100644 --- a/client/network/src/config.rs +++ b/client/network/src/config.rs @@ -50,7 +50,6 @@ use sp_runtime::traits::Block as BlockT; use std::{ borrow::Cow, collections::HashMap, - convert::TryFrom, error::Error, fs, future::Future, diff --git a/client/network/src/protocol.rs b/client/network/src/protocol.rs index c00d4302f827..80694210e77d 100644 --- a/client/network/src/protocol.rs +++ b/client/network/src/protocol.rs @@ -60,7 +60,6 @@ use sp_runtime::{ use std::{ borrow::Cow, collections::{HashMap, HashSet, VecDeque}, - convert::TryFrom as _, io, iter, num::NonZeroUsize, pin::Pin, diff --git a/client/network/src/protocol/notifications/upgrade/notifications.rs b/client/network/src/protocol/notifications/upgrade/notifications.rs index 53270975a5b0..3fbb59d399a0 100644 --- a/client/network/src/protocol/notifications/upgrade/notifications.rs +++ b/client/network/src/protocol/notifications/upgrade/notifications.rs @@ -41,7 +41,7 @@ use libp2p::core::{upgrade, InboundUpgrade, OutboundUpgrade, UpgradeInfo}; use log::{error, warn}; use std::{ borrow::Cow, - convert::{Infallible, TryFrom as _}, + convert::Infallible, io, mem, pin::Pin, task::{Context, Poll}, diff --git a/client/network/src/request_responses.rs b/client/network/src/request_responses.rs index 58007c7bc5ce..4613a15af936 100644 --- a/client/network/src/request_responses.rs +++ b/client/network/src/request_responses.rs @@ -56,7 +56,6 @@ use libp2p::{ use std::{ borrow::Cow, collections::{hash_map::Entry, HashMap}, - convert::TryFrom as _, io, iter, pin::Pin, task::{Context, Poll}, diff --git a/client/network/src/service.rs b/client/network/src/service.rs index a02aa982318a..e89be325fa48 100644 --- a/client/network/src/service.rs +++ b/client/network/src/service.rs @@ -73,7 +73,6 @@ use std::{ borrow::Cow, cmp, collections::{HashMap, HashSet}, - convert::TryFrom as _, fs, iter, marker::PhantomData, num::NonZeroUsize, diff --git a/client/network/src/service/out_events.rs b/client/network/src/service/out_events.rs index 1fe13bc30faf..3bff5a16fd0c 100644 --- a/client/network/src/service/out_events.rs +++ b/client/network/src/service/out_events.rs @@ -38,7 +38,6 @@ use parking_lot::Mutex; use prometheus_endpoint::{register, CounterVec, GaugeVec, Opts, PrometheusError, Registry, U64}; use std::{ cell::RefCell, - convert::TryFrom as _, fmt, pin::Pin, sync::Arc, diff --git a/client/offchain/src/api.rs b/client/offchain/src/api.rs index 30c7969279ee..c80b511c84d1 100644 --- a/client/offchain/src/api.rs +++ b/client/offchain/src/api.rs @@ -16,7 +16,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::{collections::HashSet, convert::TryFrom, str::FromStr, sync::Arc, thread::sleep}; +use std::{collections::HashSet, str::FromStr, sync::Arc, thread::sleep}; use crate::NetworkProvider; use codec::{Decode, Encode}; @@ -327,10 +327,7 @@ mod tests { use sc_client_db::offchain::LocalStorage; use sc_network::{NetworkStateInfo, PeerId}; use sp_core::offchain::{DbExternalities, Externalities}; - use std::{ - convert::{TryFrom, TryInto}, - time::SystemTime, - }; + use std::time::SystemTime; pub(super) struct TestNetwork(); diff --git a/client/offchain/src/api/http.rs b/client/offchain/src/api/http.rs index 2a7514116cb5..012de78c5f64 100644 --- a/client/offchain/src/api/http.rs +++ b/client/offchain/src/api/http.rs @@ -37,7 +37,6 @@ use once_cell::sync::Lazy; use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender}; use sp_core::offchain::{HttpError, HttpRequestId, HttpRequestStatus, Timestamp}; use std::{ - convert::TryFrom, fmt, io::Read as _, pin::Pin, diff --git a/client/offchain/src/api/timestamp.rs b/client/offchain/src/api/timestamp.rs index 6622331f570d..4b3f5efddf27 100644 --- a/client/offchain/src/api/timestamp.rs +++ b/client/offchain/src/api/timestamp.rs @@ -19,10 +19,7 @@ //! Helper methods dedicated to timestamps. use sp_core::offchain::Timestamp; -use std::{ - convert::TryInto, - time::{Duration, SystemTime}, -}; +use std::time::{Duration, SystemTime}; /// Returns the current time as a `Timestamp`. pub fn now() -> Timestamp { diff --git a/client/rpc/src/author/mod.rs b/client/rpc/src/author/mod.rs index 2b604d2897c5..5064e6134210 100644 --- a/client/rpc/src/author/mod.rs +++ b/client/rpc/src/author/mod.rs @@ -21,7 +21,7 @@ #[cfg(test)] mod tests; -use std::{convert::TryInto, sync::Arc}; +use std::sync::Arc; use sp_blockchain::HeaderBackend; diff --git a/client/service/src/chain_ops/import_blocks.rs b/client/service/src/chain_ops/import_blocks.rs index dc03cdcedae0..c0612124dd0c 100644 --- a/client/service/src/chain_ops/import_blocks.rs +++ b/client/service/src/chain_ops/import_blocks.rs @@ -35,7 +35,6 @@ use sp_runtime::{ }, }; use std::{ - convert::{TryFrom, TryInto}, io::Read, pin::Pin, task::Poll, diff --git a/client/service/src/config.rs b/client/service/src/config.rs index fd32aebdebdd..7c7bb480aa5c 100644 --- a/client/service/src/config.rs +++ b/client/service/src/config.rs @@ -294,7 +294,7 @@ impl BasePath { } } -impl std::convert::From for BasePath { +impl From for BasePath { fn from(path: PathBuf) -> Self { BasePath::new(path) } diff --git a/client/service/src/metrics.rs b/client/service/src/metrics.rs index 02e3ab95f118..9fbf2c3ea3fc 100644 --- a/client/service/src/metrics.rs +++ b/client/service/src/metrics.rs @@ -16,7 +16,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::{convert::TryFrom, time::SystemTime}; +use std::time::SystemTime; use crate::config::Configuration; use futures_timer::Delay; diff --git a/client/transaction-pool/src/lib.rs b/client/transaction-pool/src/lib.rs index ec93d1f7c51f..9fd2ef1deef4 100644 --- a/client/transaction-pool/src/lib.rs +++ b/client/transaction-pool/src/lib.rs @@ -40,7 +40,6 @@ pub use graph::{base_pool::Limit as PoolLimit, ChainApi, Options, Pool, Transact use parking_lot::Mutex; use std::{ collections::{HashMap, HashSet}, - convert::TryInto, pin::Pin, sync::Arc, }; diff --git a/client/transaction-pool/tests/pool.rs b/client/transaction-pool/tests/pool.rs index 08ecdbc86cca..2243f140cb22 100644 --- a/client/transaction-pool/tests/pool.rs +++ b/client/transaction-pool/tests/pool.rs @@ -36,7 +36,7 @@ use sp_runtime::{ traits::Block as _, transaction_validity::{InvalidTransaction, TransactionSource, ValidTransaction}, }; -use std::{collections::BTreeSet, convert::TryInto, sync::Arc}; +use std::{collections::BTreeSet, sync::Arc}; use substrate_test_runtime_client::{ runtime::{Block, Extrinsic, Hash, Header, Index, Transfer}, AccountKeyring::*, @@ -864,8 +864,6 @@ fn ready_set_should_eventually_resolve_when_block_update_arrives() { #[test] fn should_not_accept_old_signatures() { - use std::convert::TryFrom; - let client = Arc::new(substrate_test_runtime_client::new()); let pool = Arc::new( diff --git a/frame/assets/src/lib.rs b/frame/assets/src/lib.rs index 71ba7b4d2491..9b0f23a0a178 100644 --- a/frame/assets/src/lib.rs +++ b/frame/assets/src/lib.rs @@ -147,7 +147,7 @@ use sp_runtime::{ }, ArithmeticError, TokenError, }; -use sp_std::{borrow::Borrow, convert::TryInto, prelude::*}; +use sp_std::{borrow::Borrow, prelude::*}; use frame_support::{ dispatch::{DispatchError, DispatchResult}, diff --git a/frame/bags-list/fuzzer/src/main.rs b/frame/bags-list/fuzzer/src/main.rs index 3ff59b450bef..6f538eb28e7e 100644 --- a/frame/bags-list/fuzzer/src/main.rs +++ b/frame/bags-list/fuzzer/src/main.rs @@ -30,7 +30,6 @@ use frame_election_provider_support::{SortedListProvider, VoteWeight}; use honggfuzz::fuzz; use pallet_bags_list::mock::{AccountId, BagsList, ExtBuilder}; -use std::convert::From; const ID_RANGE: AccountId = 25_000; diff --git a/frame/bags-list/remote-tests/src/sanity_check.rs b/frame/bags-list/remote-tests/src/sanity_check.rs index f2b6881edea7..1027efb8539e 100644 --- a/frame/bags-list/remote-tests/src/sanity_check.rs +++ b/frame/bags-list/remote-tests/src/sanity_check.rs @@ -23,7 +23,6 @@ use frame_support::{ }; use remote_externalities::{Builder, Mode, OnlineConfig}; use sp_runtime::{traits::Block as BlockT, DeserializeOwned}; -use sp_std::prelude::*; /// Execute the sanity check of the bags-list. pub async fn execute( diff --git a/frame/contracts/src/tests.rs b/frame/contracts/src/tests.rs index 2b01cbe3c742..ce59f5bb858a 100644 --- a/frame/contracts/src/tests.rs +++ b/frame/contracts/src/tests.rs @@ -96,7 +96,6 @@ pub mod test_utils { } macro_rules! assert_return_code { ( $x:expr , $y:expr $(,)? ) => {{ - use sp_std::convert::TryInto; assert_eq!(u32::from_le_bytes($x.data[..].try_into().unwrap()), $y as u32); }}; } diff --git a/frame/conviction-voting/src/vote.rs b/frame/conviction-voting/src/vote.rs index d7ca931de35a..e608a6dcfd01 100644 --- a/frame/conviction-voting/src/vote.rs +++ b/frame/conviction-voting/src/vote.rs @@ -25,7 +25,7 @@ use sp_runtime::{ traits::{Saturating, Zero}, RuntimeDebug, }; -use sp_std::{convert::TryFrom, prelude::*, result::Result}; +use sp_std::prelude::*; /// A number of lock periods, plus a vote, one way or the other. #[derive(Copy, Clone, Eq, PartialEq, Default, RuntimeDebug, MaxEncodedLen)] diff --git a/frame/election-provider-support/src/mock.rs b/frame/election-provider-support/src/mock.rs index d10b1724c95d..7c834f06f3cd 100644 --- a/frame/election-provider-support/src/mock.rs +++ b/frame/election-provider-support/src/mock.rs @@ -21,7 +21,6 @@ use std::{ collections::{HashMap, HashSet}, - convert::TryInto, hash::Hash, }; diff --git a/frame/election-provider-support/src/tests.rs b/frame/election-provider-support/src/tests.rs index f88f3653c681..1ccff79f3efd 100644 --- a/frame/election-provider-support/src/tests.rs +++ b/frame/election-provider-support/src/tests.rs @@ -22,7 +22,6 @@ use crate::{mock::*, IndexAssignment, NposSolution}; use frame_support::traits::ConstU32; use rand::SeedableRng; -use std::convert::TryInto; mod solution_type { use super::*; @@ -30,7 +29,7 @@ mod solution_type { // these need to come from the same dev-dependency `frame-election-provider-support`, not from // the crate. use crate::{generate_solution_type, Assignment, Error as NposError, NposSolution}; - use sp_std::{convert::TryInto, fmt::Debug}; + use sp_std::fmt::Debug; #[allow(dead_code)] mod __private { diff --git a/frame/election-provider-support/src/traits.rs b/frame/election-provider-support/src/traits.rs index e1fc0663e7d1..ed812e2e0f2c 100644 --- a/frame/election-provider-support/src/traits.rs +++ b/frame/election-provider-support/src/traits.rs @@ -22,16 +22,12 @@ use codec::Encode; use scale_info::TypeInfo; use sp_arithmetic::traits::{Bounded, UniqueSaturatedInto}; use sp_npos_elections::{ElectionScore, Error, EvaluateSupport}; -use sp_std::{ - convert::{TryFrom, TryInto}, - fmt::Debug, - prelude::*, -}; +use sp_std::{fmt::Debug, prelude::*}; /// An opaque index-based, NPoS solution type. pub trait NposSolution where - Self: Sized + for<'a> sp_std::convert::TryFrom<&'a [IndexAssignmentOf], Error = Error>, + Self: Sized + for<'a> TryFrom<&'a [IndexAssignmentOf], Error = Error>, { /// The maximum number of votes that are allowed. const LIMIT: usize; diff --git a/frame/im-online/src/lib.rs b/frame/im-online/src/lib.rs index e2213ef4169b..5ef515db0b23 100644 --- a/frame/im-online/src/lib.rs +++ b/frame/im-online/src/lib.rs @@ -104,7 +104,7 @@ use sp_staking::{ offence::{Kind, Offence, ReportOffence}, SessionIndex, }; -use sp_std::{convert::TryInto, prelude::*}; +use sp_std::prelude::*; pub use weights::WeightInfo; pub mod sr25519 { diff --git a/frame/preimage/src/lib.rs b/frame/preimage/src/lib.rs index c34057a1034d..a5d8ee28b595 100644 --- a/frame/preimage/src/lib.rs +++ b/frame/preimage/src/lib.rs @@ -37,7 +37,7 @@ mod tests; pub mod weights; use sp_runtime::traits::{BadOrigin, Hash, Saturating}; -use sp_std::{convert::TryFrom, prelude::*}; +use sp_std::prelude::*; use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::{ diff --git a/frame/proxy/src/lib.rs b/frame/proxy/src/lib.rs index 84f1a84badc9..891315c92aa3 100644 --- a/frame/proxy/src/lib.rs +++ b/frame/proxy/src/lib.rs @@ -48,7 +48,7 @@ use sp_runtime::{ traits::{Dispatchable, Hash, Saturating, TrailingZeroInput, Zero}, DispatchResult, }; -use sp_std::{convert::TryInto, prelude::*}; +use sp_std::prelude::*; pub use weights::WeightInfo; pub use pallet::*; diff --git a/frame/randomness-collective-flip/src/lib.rs b/frame/randomness-collective-flip/src/lib.rs index b72aa665550c..f709578f6941 100644 --- a/frame/randomness-collective-flip/src/lib.rs +++ b/frame/randomness-collective-flip/src/lib.rs @@ -71,7 +71,6 @@ use safe_mix::TripletMix; use codec::Encode; use frame_support::traits::Randomness; use sp_runtime::traits::{Hash, Saturating}; -use sp_std::prelude::*; const RANDOM_MATERIAL_LEN: u32 = 81; diff --git a/frame/staking/reward-curve/src/lib.rs b/frame/staking/reward-curve/src/lib.rs index 9b2f3100b487..e66f6fde3759 100644 --- a/frame/staking/reward-curve/src/lib.rs +++ b/frame/staking/reward-curve/src/lib.rs @@ -24,7 +24,6 @@ use proc_macro::TokenStream; use proc_macro2::{Span, TokenStream as TokenStream2}; use proc_macro_crate::{crate_name, FoundCrate}; use quote::{quote, ToTokens}; -use std::convert::TryInto; use syn::parse::{Parse, ParseStream}; /// Accepts a number of expressions to create a instance of PiecewiseLinear which represents the diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 2a0716721dd5..872ed2e1af40 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -316,7 +316,7 @@ use sp_staking::{ offence::{Offence, OffenceError, ReportOffence}, EraIndex, SessionIndex, }; -use sp_std::{collections::btree_map::BTreeMap, convert::From, prelude::*}; +use sp_std::{collections::btree_map::BTreeMap, prelude::*}; pub use weights::WeightInfo; pub use pallet::{pallet::*, *}; diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index 306bd34390d8..fa8c453c2b0f 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -33,7 +33,7 @@ use sp_runtime::{ DispatchError, Perbill, Percent, }; use sp_staking::{EraIndex, SessionIndex}; -use sp_std::{cmp::max, convert::From, prelude::*}; +use sp_std::{cmp::max, prelude::*}; mod impls; diff --git a/frame/support/procedural/src/construct_runtime/expand/event.rs b/frame/support/procedural/src/construct_runtime/expand/event.rs index ef071a9fc7ef..b242f9641562 100644 --- a/frame/support/procedural/src/construct_runtime/expand/event.rs +++ b/frame/support/procedural/src/construct_runtime/expand/event.rs @@ -127,7 +127,7 @@ fn expand_event_conversion( Event::#variant_name(x) } } - impl #scrate::sp_std::convert::TryInto<#pallet_event> for Event { + impl TryInto<#pallet_event> for Event { type Error = (); fn try_into(self) -> #scrate::sp_std::result::Result<#pallet_event, Self::Error> { diff --git a/frame/support/procedural/src/construct_runtime/expand/origin.rs b/frame/support/procedural/src/construct_runtime/expand/origin.rs index 077bef3744a5..342a002b52b9 100644 --- a/frame/support/procedural/src/construct_runtime/expand/origin.rs +++ b/frame/support/procedural/src/construct_runtime/expand/origin.rs @@ -230,7 +230,7 @@ pub fn expand_outer_origin( } } - impl #scrate::sp_std::convert::TryFrom for #system_path::Origin<#runtime> { + impl TryFrom for #system_path::Origin<#runtime> { type Error = OriginCaller; fn try_from(x: OriginCaller) -> #scrate::sp_std::result::Result<#system_path::Origin<#runtime>, OriginCaller> @@ -359,7 +359,7 @@ fn expand_origin_pallet_conversions( } } - impl #scrate::sp_std::convert::TryFrom for #pallet_origin { + impl TryFrom for #pallet_origin { type Error = OriginCaller; fn try_from( x: OriginCaller, diff --git a/frame/support/procedural/src/pallet/expand/error.rs b/frame/support/procedural/src/pallet/expand/error.rs index 86b06d737dec..124e8b312ce3 100644 --- a/frame/support/procedural/src/pallet/expand/error.rs +++ b/frame/support/procedural/src/pallet/expand/error.rs @@ -162,7 +162,7 @@ pub fn expand_error(def: &mut Def) -> proc_macro2::TokenStream { #frame_support::sp_runtime::DispatchError::Module(#frame_support::sp_runtime::ModuleError { index, - error: core::convert::TryInto::try_into(encoded).expect("encoded error is resized to be equal to the maximum encoded error size; qed"), + error: TryInto::try_into(encoded).expect("encoded error is resized to be equal to the maximum encoded error size; qed"), message: Some(err.as_str()), }) } diff --git a/frame/support/src/error.rs b/frame/support/src/error.rs index 764376a4e1dc..0ffe4334e2e3 100644 --- a/frame/support/src/error.rs +++ b/frame/support/src/error.rs @@ -152,7 +152,7 @@ macro_rules! decl_error { $crate::sp_runtime::DispatchError::Module($crate::sp_runtime::ModuleError { index, - error: core::convert::TryInto::try_into(error).expect("encoded error is resized to be equal to the maximum encoded error size; qed"), + error: TryInto::try_into(error).expect("encoded error is resized to be equal to the maximum encoded error size; qed"), message: Some(err.as_str()), }) } diff --git a/frame/support/src/lib.rs b/frame/support/src/lib.rs index 70a79c07189d..714449eec784 100644 --- a/frame/support/src/lib.rs +++ b/frame/support/src/lib.rs @@ -127,13 +127,11 @@ impl TypeId for PalletId { macro_rules! bounded_vec { ($ ($values:expr),* $(,)?) => { { - use $crate::sp_std::convert::TryInto as _; $crate::sp_std::vec![$($values),*].try_into().unwrap() } }; ( $value:expr ; $repetition:expr ) => { { - use $crate::sp_std::convert::TryInto as _; $crate::sp_std::vec![$value ; $repetition].try_into().unwrap() } } diff --git a/frame/support/src/storage/bounded_btree_map.rs b/frame/support/src/storage/bounded_btree_map.rs index 6190552476a4..eca4b17821c7 100644 --- a/frame/support/src/storage/bounded_btree_map.rs +++ b/frame/support/src/storage/bounded_btree_map.rs @@ -22,10 +22,7 @@ use crate::{ traits::{Get, TryCollect}, }; use codec::{Decode, Encode, MaxEncodedLen}; -use sp_std::{ - borrow::Borrow, collections::btree_map::BTreeMap, convert::TryFrom, marker::PhantomData, - ops::Deref, -}; +use sp_std::{borrow::Borrow, collections::btree_map::BTreeMap, marker::PhantomData, ops::Deref}; /// A bounded map based on a B-Tree. /// diff --git a/frame/support/src/storage/bounded_btree_set.rs b/frame/support/src/storage/bounded_btree_set.rs index 543b997e94e3..f38952bf545d 100644 --- a/frame/support/src/storage/bounded_btree_set.rs +++ b/frame/support/src/storage/bounded_btree_set.rs @@ -22,10 +22,7 @@ use crate::{ traits::{Get, TryCollect}, }; use codec::{Decode, Encode, MaxEncodedLen}; -use sp_std::{ - borrow::Borrow, collections::btree_set::BTreeSet, convert::TryFrom, marker::PhantomData, - ops::Deref, -}; +use sp_std::{borrow::Borrow, collections::btree_set::BTreeSet, marker::PhantomData, ops::Deref}; /// A bounded set based on a B-Tree. /// @@ -324,7 +321,6 @@ pub mod test { use crate::Twox128; use frame_support::traits::ConstU32; use sp_io::TestExternalities; - use sp_std::convert::TryInto; crate::generate_storage_alias! { Prefix, Foo => Value>> } crate::generate_storage_alias! { Prefix, FooMap => Map<(Twox128, u32), BoundedBTreeSet>> } diff --git a/frame/support/src/storage/weak_bounded_vec.rs b/frame/support/src/storage/weak_bounded_vec.rs index aa6dc88eaa4f..21cc487b4908 100644 --- a/frame/support/src/storage/weak_bounded_vec.rs +++ b/frame/support/src/storage/weak_bounded_vec.rs @@ -27,7 +27,7 @@ use core::{ ops::{Deref, Index, IndexMut}, slice::SliceIndex, }; -use sp_std::{convert::TryFrom, marker::PhantomData, prelude::*}; +use sp_std::{marker::PhantomData, prelude::*}; /// A weakly bounded vector. /// @@ -320,7 +320,6 @@ pub mod test { use crate::Twox128; use frame_support::traits::ConstU32; use sp_io::TestExternalities; - use sp_std::convert::TryInto; crate::generate_storage_alias! { Prefix, Foo => Value>> } crate::generate_storage_alias! { Prefix, FooMap => Map<(Twox128, u32), WeakBoundedVec>> } diff --git a/frame/uniques/src/benchmarking.rs b/frame/uniques/src/benchmarking.rs index d6223ec88f81..19d3dfac6e5a 100644 --- a/frame/uniques/src/benchmarking.rs +++ b/frame/uniques/src/benchmarking.rs @@ -30,7 +30,7 @@ use frame_support::{ }; use frame_system::RawOrigin as SystemOrigin; use sp_runtime::traits::Bounded; -use sp_std::{convert::TryInto, prelude::*}; +use sp_std::prelude::*; use crate::Pallet as Uniques; diff --git a/frame/vesting/src/lib.rs b/frame/vesting/src/lib.rs index 775902f223ba..13841a0443ce 100644 --- a/frame/vesting/src/lib.rs +++ b/frame/vesting/src/lib.rs @@ -74,7 +74,7 @@ use sp_runtime::{ }, RuntimeDebug, }; -use sp_std::{convert::TryInto, fmt::Debug, prelude::*}; +use sp_std::{fmt::Debug, prelude::*}; pub use vesting_info::*; pub use weights::WeightInfo; diff --git a/primitives/application-crypto/src/lib.rs b/primitives/application-crypto/src/lib.rs index b12fe72b271a..05f89c40ef99 100644 --- a/primitives/application-crypto/src/lib.rs +++ b/primitives/application-crypto/src/lib.rs @@ -42,7 +42,7 @@ pub use scale_info; #[cfg(feature = "std")] pub use serde; #[doc(hidden)] -pub use sp_std::{convert::TryFrom, ops::Deref, vec::Vec}; +pub use sp_std::{ops::Deref, vec::Vec}; pub mod ecdsa; pub mod ed25519; @@ -363,7 +363,7 @@ macro_rules! app_crypto_public_common { } } - impl<'a> $crate::TryFrom<&'a [u8]> for Public { + impl<'a> TryFrom<&'a [u8]> for Public { type Error = (); fn try_from(data: &'a [u8]) -> Result { @@ -518,7 +518,7 @@ macro_rules! app_crypto_signature_common { type Generic = $sig; } - impl<'a> $crate::TryFrom<&'a [u8]> for Signature { + impl<'a> TryFrom<&'a [u8]> for Signature { type Error = (); fn try_from(data: &'a [u8]) -> Result { @@ -526,7 +526,7 @@ macro_rules! app_crypto_signature_common { } } - impl $crate::TryFrom<$crate::Vec> for Signature { + impl TryFrom<$crate::Vec> for Signature { type Error = (); fn try_from(data: $crate::Vec) -> Result { diff --git a/primitives/arithmetic/fuzzer/src/biguint.rs b/primitives/arithmetic/fuzzer/src/biguint.rs index e4c088a2e8ab..f49743a4b8a6 100644 --- a/primitives/arithmetic/fuzzer/src/biguint.rs +++ b/primitives/arithmetic/fuzzer/src/biguint.rs @@ -29,7 +29,6 @@ use honggfuzz::fuzz; use sp_arithmetic::biguint::{BigUint, Single}; -use std::convert::TryFrom; fn main() { loop { diff --git a/primitives/arithmetic/fuzzer/src/normalize.rs b/primitives/arithmetic/fuzzer/src/normalize.rs index e4f90dbc1c41..dd717115a5c9 100644 --- a/primitives/arithmetic/fuzzer/src/normalize.rs +++ b/primitives/arithmetic/fuzzer/src/normalize.rs @@ -25,7 +25,6 @@ use honggfuzz::fuzz; use sp_arithmetic::Normalizable; -use std::convert::TryInto; type Ty = u64; diff --git a/primitives/arithmetic/src/biguint.rs b/primitives/arithmetic/src/biguint.rs index b26ac4294d11..33f0960ee378 100644 --- a/primitives/arithmetic/src/biguint.rs +++ b/primitives/arithmetic/src/biguint.rs @@ -19,7 +19,7 @@ use codec::{Decode, Encode}; use num_traits::{One, Zero}; -use sp_std::{cell::RefCell, cmp::Ordering, convert::TryFrom, ops, prelude::*, vec}; +use sp_std::{cell::RefCell, cmp::Ordering, ops, prelude::*, vec}; // A sensible value for this would be half of the dword size of the host machine. Since the // runtime is compiled to 32bit webassembly, using 32 and 64 for single and double respectively @@ -664,7 +664,6 @@ pub mod tests { #[test] fn can_try_build_numbers_from_types() { - use sp_std::convert::TryFrom; assert_eq!(u64::try_from(with_limbs(1)).unwrap(), 1); assert_eq!(u64::try_from(with_limbs(2)).unwrap(), u32::MAX as u64 + 2); assert_eq!(u64::try_from(with_limbs(3)).unwrap_err(), "cannot fit a number into u64"); diff --git a/primitives/arithmetic/src/fixed_point.rs b/primitives/arithmetic/src/fixed_point.rs index 1c61d6c3806a..3ecfb60ee0f5 100644 --- a/primitives/arithmetic/src/fixed_point.rs +++ b/primitives/arithmetic/src/fixed_point.rs @@ -27,7 +27,6 @@ use crate::{ }; use codec::{CompactAs, Decode, Encode}; use sp_std::{ - convert::{TryFrom, TryInto}, fmt::Debug, ops::{self, Add, Div, Mul, Sub}, prelude::*, diff --git a/primitives/arithmetic/src/helpers_128bit.rs b/primitives/arithmetic/src/helpers_128bit.rs index af9729c9702c..735b11287cbe 100644 --- a/primitives/arithmetic/src/helpers_128bit.rs +++ b/primitives/arithmetic/src/helpers_128bit.rs @@ -24,7 +24,6 @@ use crate::biguint; use num_traits::Zero; use sp_std::{ cmp::{max, min}, - convert::TryInto, mem, }; diff --git a/primitives/arithmetic/src/lib.rs b/primitives/arithmetic/src/lib.rs index 273608a3d171..729da123757c 100644 --- a/primitives/arithmetic/src/lib.rs +++ b/primitives/arithmetic/src/lib.rs @@ -44,7 +44,7 @@ pub use fixed_point::{FixedI128, FixedI64, FixedPointNumber, FixedPointOperand, pub use per_things::{InnerOf, PerThing, PerU16, Perbill, Percent, Permill, Perquintill, UpperOf}; pub use rational::{Rational128, RationalInfinite}; -use sp_std::{cmp::Ordering, convert::TryInto, fmt::Debug, prelude::*}; +use sp_std::{cmp::Ordering, fmt::Debug, prelude::*}; use traits::{BaseArithmetic, One, SaturatedConversion, Unsigned, Zero}; /// Trait for comparing two numbers with an threshold. diff --git a/primitives/arithmetic/src/per_things.rs b/primitives/arithmetic/src/per_things.rs index c3ccca56ca33..1b9e6d91a2cd 100644 --- a/primitives/arithmetic/src/per_things.rs +++ b/primitives/arithmetic/src/per_things.rs @@ -25,7 +25,6 @@ use crate::traits::{ use codec::{CompactAs, Encode}; use num_traits::{Pow, SaturatingAdd, SaturatingSub}; use sp_std::{ - convert::{TryFrom, TryInto}, fmt, ops, ops::{Add, Sub}, prelude::*, diff --git a/primitives/arithmetic/src/traits.rs b/primitives/arithmetic/src/traits.rs index 447f8cef51f9..748aaed2a7cf 100644 --- a/primitives/arithmetic/src/traits.rs +++ b/primitives/arithmetic/src/traits.rs @@ -23,12 +23,8 @@ pub use num_traits::{ checked_pow, Bounded, CheckedAdd, CheckedDiv, CheckedMul, CheckedNeg, CheckedRem, CheckedShl, CheckedShr, CheckedSub, One, Signed, Unsigned, Zero, }; -use sp_std::{ - self, - convert::{TryFrom, TryInto}, - ops::{ - Add, AddAssign, Div, DivAssign, Mul, MulAssign, Rem, RemAssign, Shl, Shr, Sub, SubAssign, - }, +use sp_std::ops::{ + Add, AddAssign, Div, DivAssign, Mul, MulAssign, Rem, RemAssign, Shl, Shr, Sub, SubAssign, }; /// A meta trait for arithmetic type operations, regardless of any limitation on size. diff --git a/primitives/consensus/common/src/error.rs b/primitives/consensus/common/src/error.rs index 280ff2322898..0656b5761fb3 100644 --- a/primitives/consensus/common/src/error.rs +++ b/primitives/consensus/common/src/error.rs @@ -86,13 +86,13 @@ pub enum Error { CannotSign(Vec, String), } -impl core::convert::From for Error { +impl From for Error { fn from(p: Public) -> Self { Self::InvalidAuthority(p) } } -impl core::convert::From for Error { +impl From for Error { fn from(s: String) -> Self { Self::StateUnavailable(s) } diff --git a/primitives/consensus/vrf/src/schnorrkel.rs b/primitives/consensus/vrf/src/schnorrkel.rs index 1ef23427e0ed..094a398893ff 100644 --- a/primitives/consensus/vrf/src/schnorrkel.rs +++ b/primitives/consensus/vrf/src/schnorrkel.rs @@ -21,7 +21,6 @@ use codec::{Decode, Encode, EncodeLike}; use schnorrkel::errors::MultiSignatureStage; use sp_core::U512; use sp_std::{ - convert::TryFrom, ops::{Deref, DerefMut}, prelude::*, }; diff --git a/primitives/core/src/crypto.rs b/primitives/core/src/crypto.rs index 12f8397eee4a..f994da151535 100644 --- a/primitives/core/src/crypto.rs +++ b/primitives/core/src/crypto.rs @@ -38,7 +38,7 @@ pub use secrecy::SecretString; use sp_runtime_interface::pass_by::PassByInner; #[doc(hidden)] pub use sp_std::ops::Deref; -use sp_std::{convert::TryFrom, hash::Hash, str, vec::Vec}; +use sp_std::{hash::Hash, str, vec::Vec}; /// Trait to zeroize a memory buffer. pub use zeroize::Zeroize; @@ -535,7 +535,7 @@ impl From<[u8; 32]> for AccountId32 { } } -impl<'a> sp_std::convert::TryFrom<&'a [u8]> for AccountId32 { +impl<'a> TryFrom<&'a [u8]> for AccountId32 { type Error = (); fn try_from(x: &'a [u8]) -> Result { if x.len() == 32 { diff --git a/primitives/core/src/ecdsa.rs b/primitives/core/src/ecdsa.rs index 7a4e4399913d..6343e3f4dfd0 100644 --- a/primitives/core/src/ecdsa.rs +++ b/primitives/core/src/ecdsa.rs @@ -137,7 +137,7 @@ impl AsMut<[u8]> for Public { } } -impl sp_std::convert::TryFrom<&[u8]> for Public { +impl TryFrom<&[u8]> for Public { type Error = (); fn try_from(data: &[u8]) -> Result { @@ -209,7 +209,7 @@ impl<'de> Deserialize<'de> for Public { #[derive(Encode, Decode, MaxEncodedLen, PassByInner, TypeInfo, PartialEq, Eq)] pub struct Signature(pub [u8; 65]); -impl sp_std::convert::TryFrom<&[u8]> for Signature { +impl TryFrom<&[u8]> for Signature { type Error = (); fn try_from(data: &[u8]) -> Result { diff --git a/primitives/core/src/ed25519.rs b/primitives/core/src/ed25519.rs index 555c23c6b60c..0bde9e2e5303 100644 --- a/primitives/core/src/ed25519.rs +++ b/primitives/core/src/ed25519.rs @@ -39,8 +39,6 @@ use crate::crypto::{DeriveJunction, Pair as TraitPair, SecretStringError}; #[cfg(feature = "std")] use bip39::{Language, Mnemonic, MnemonicType}; #[cfg(feature = "full_crypto")] -use core::convert::TryFrom; -#[cfg(feature = "full_crypto")] use ed25519_dalek::{Signer as _, Verifier as _}; #[cfg(feature = "std")] use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; @@ -116,7 +114,7 @@ impl Deref for Public { } } -impl sp_std::convert::TryFrom<&[u8]> for Public { +impl TryFrom<&[u8]> for Public { type Error = (); fn try_from(data: &[u8]) -> Result { @@ -215,7 +213,7 @@ impl<'de> Deserialize<'de> for Public { #[derive(Encode, Decode, MaxEncodedLen, PassByInner, TypeInfo, PartialEq, Eq)] pub struct Signature(pub [u8; 64]); -impl sp_std::convert::TryFrom<&[u8]> for Signature { +impl TryFrom<&[u8]> for Signature { type Error = (); fn try_from(data: &[u8]) -> Result { diff --git a/primitives/core/src/offchain/mod.rs b/primitives/core/src/offchain/mod.rs index b9e310dc1fb1..4ffadc3e4031 100644 --- a/primitives/core/src/offchain/mod.rs +++ b/primitives/core/src/offchain/mod.rs @@ -21,10 +21,7 @@ use crate::{OpaquePeerId, RuntimeDebug}; use codec::{Decode, Encode}; use scale_info::TypeInfo; use sp_runtime_interface::pass_by::{PassByCodec, PassByEnum, PassByInner}; -use sp_std::{ - convert::TryFrom, - prelude::{Box, Vec}, -}; +use sp_std::prelude::{Box, Vec}; pub use crate::crypto::KeyTypeId; diff --git a/primitives/core/src/sr25519.rs b/primitives/core/src/sr25519.rs index 2f298fa2a266..ef033c2099b5 100644 --- a/primitives/core/src/sr25519.rs +++ b/primitives/core/src/sr25519.rs @@ -35,8 +35,6 @@ use schnorrkel::{ #[cfg(feature = "full_crypto")] use sp_std::vec::Vec; #[cfg(feature = "std")] -use std::convert::TryFrom; -#[cfg(feature = "std")] use substrate_bip39::mini_secret_from_entropy; use crate::{ @@ -142,7 +140,7 @@ impl std::str::FromStr for Public { } } -impl sp_std::convert::TryFrom<&[u8]> for Public { +impl TryFrom<&[u8]> for Public { type Error = (); fn try_from(data: &[u8]) -> Result { @@ -215,7 +213,7 @@ impl<'de> Deserialize<'de> for Public { #[derive(Encode, Decode, MaxEncodedLen, PassByInner, TypeInfo, PartialEq, Eq)] pub struct Signature(pub [u8; 64]); -impl sp_std::convert::TryFrom<&[u8]> for Signature { +impl TryFrom<&[u8]> for Signature { type Error = (); fn try_from(data: &[u8]) -> Result { diff --git a/primitives/rpc/src/number.rs b/primitives/rpc/src/number.rs index 5a433a9598e0..81084a09d4ac 100644 --- a/primitives/rpc/src/number.rs +++ b/primitives/rpc/src/number.rs @@ -20,10 +20,7 @@ use serde::{Deserialize, Serialize}; use sp_core::U256; -use std::{ - convert::{TryFrom, TryInto}, - fmt::Debug, -}; +use std::fmt::Debug; /// A number type that can be serialized both as a number or a string that encodes a number in a /// string. diff --git a/primitives/runtime-interface/proc-macro/src/pass_by/enum_.rs b/primitives/runtime-interface/proc-macro/src/pass_by/enum_.rs index 1fd22c6a2538..7c3f066f6c83 100644 --- a/primitives/runtime-interface/proc-macro/src/pass_by/enum_.rs +++ b/primitives/runtime-interface/proc-macro/src/pass_by/enum_.rs @@ -51,7 +51,7 @@ pub fn derive_impl(input: DeriveInput) -> Result { type PassBy = #crate_::pass_by::Enum<#ident>; } - impl #crate_::sp_std::convert::TryFrom for #ident { + impl TryFrom for #ident { type Error = (); fn try_from(inner: u8) -> #crate_::sp_std::result::Result { diff --git a/primitives/runtime-interface/src/pass_by.rs b/primitives/runtime-interface/src/pass_by.rs index fb2d6b818d17..5d895ff5b3f8 100644 --- a/primitives/runtime-interface/src/pass_by.rs +++ b/primitives/runtime-interface/src/pass_by.rs @@ -33,7 +33,7 @@ use crate::wasm::*; #[cfg(feature = "std")] use sp_wasm_interface::{FunctionContext, Pointer, Result}; -use sp_std::{convert::TryFrom, marker::PhantomData}; +use sp_std::marker::PhantomData; #[cfg(not(feature = "std"))] use sp_std::vec::Vec; @@ -382,7 +382,7 @@ impl, I: RIType> RIType for Inner { /// } /// } /// -/// impl std::convert::TryFrom for Test { +/// impl TryFrom for Test { /// type Error = (); /// /// fn try_from(val: u8) -> Result { diff --git a/primitives/runtime-interface/test-wasm/src/lib.rs b/primitives/runtime-interface/test-wasm/src/lib.rs index 0c8a9c04ab1e..f518a2e17498 100644 --- a/primitives/runtime-interface/test-wasm/src/lib.rs +++ b/primitives/runtime-interface/test-wasm/src/lib.rs @@ -22,7 +22,7 @@ use sp_runtime_interface::runtime_interface; #[cfg(not(feature = "std"))] -use sp_std::{convert::TryFrom, mem, prelude::*}; +use sp_std::{mem, prelude::*}; use sp_core::{sr25519::Public, wasm_export_functions}; diff --git a/primitives/runtime/src/curve.rs b/primitives/runtime/src/curve.rs index b5532c3d8cef..c6bfa6601787 100644 --- a/primitives/runtime/src/curve.rs +++ b/primitives/runtime/src/curve.rs @@ -110,8 +110,6 @@ where #[test] fn test_multiply_by_rational_saturating() { - use std::convert::TryInto; - let div = 100u32; for value in 0..=div { for p in 0..=div { @@ -132,8 +130,6 @@ fn test_multiply_by_rational_saturating() { #[test] fn test_calculate_for_fraction_times_denominator() { - use std::convert::TryInto; - let curve = PiecewiseLinear { points: &[ (Perbill::from_parts(0_000_000_000), Perbill::from_parts(0_500_000_000)), diff --git a/primitives/runtime/src/generic/header.rs b/primitives/runtime/src/generic/header.rs index 3e1a673d257a..a7b43608f2b7 100644 --- a/primitives/runtime/src/generic/header.rs +++ b/primitives/runtime/src/generic/header.rs @@ -29,7 +29,7 @@ use crate::{ #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; use sp_core::U256; -use sp_std::{convert::TryFrom, fmt::Debug}; +use sp_std::fmt::Debug; /// Abstraction over a block header for a substrate chain. #[derive(Encode, Decode, PartialEq, Eq, Clone, sp_core::RuntimeDebug, TypeInfo)] diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index c09db5124cc1..39e606eb9b5f 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -50,7 +50,7 @@ use sp_core::{ hash::{H256, H512}, sr25519, }; -use sp_std::{convert::TryFrom, prelude::*}; +use sp_std::prelude::*; use codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; diff --git a/primitives/runtime/src/traits.rs b/primitives/runtime/src/traits.rs index ba4ca790a919..9c71b2023d3f 100644 --- a/primitives/runtime/src/traits.rs +++ b/primitives/runtime/src/traits.rs @@ -37,13 +37,7 @@ pub use sp_arithmetic::traits::{ UniqueSaturatedFrom, UniqueSaturatedInto, Zero, }; use sp_core::{self, storage::StateVersion, Hasher, RuntimeDebug, TypeId}; -use sp_std::{ - self, - convert::{TryFrom, TryInto}, - fmt::Debug, - marker::PhantomData, - prelude::*, -}; +use sp_std::{self, fmt::Debug, marker::PhantomData, prelude::*}; #[cfg(feature = "std")] use std::fmt::Display; #[cfg(feature = "std")] diff --git a/primitives/std/src/lib.rs b/primitives/std/src/lib.rs index 05dff0f3077b..6653c3d7eade 100644 --- a/primitives/std/src/lib.rs +++ b/primitives/std/src/lib.rs @@ -103,7 +103,6 @@ pub mod prelude { boxed::Box, clone::Clone, cmp::{Eq, PartialEq, Reverse}, - convert::{TryFrom, TryInto}, iter::IntoIterator, vec::Vec, }; diff --git a/primitives/storage/src/lib.rs b/primitives/storage/src/lib.rs index d377ea931df2..fecd2b24dbb0 100644 --- a/primitives/storage/src/lib.rs +++ b/primitives/storage/src/lib.rs @@ -423,7 +423,7 @@ impl From for u8 { } } -impl sp_std::convert::TryFrom for StateVersion { +impl TryFrom for StateVersion { type Error = (); fn try_from(val: u8) -> sp_std::result::Result { match val { diff --git a/primitives/wasm-interface/src/lib.rs b/primitives/wasm-interface/src/lib.rs index d57666f12689..6dfc3116ddc4 100644 --- a/primitives/wasm-interface/src/lib.rs +++ b/primitives/wasm-interface/src/lib.rs @@ -73,7 +73,7 @@ impl From for u8 { } } -impl sp_std::convert::TryFrom for ValueType { +impl TryFrom for ValueType { type Error = (); fn try_from(val: u8) -> sp_std::result::Result { diff --git a/utils/prometheus/src/lib.rs b/utils/prometheus/src/lib.rs index 1892741eff5d..3ea9d45d48b1 100644 --- a/utils/prometheus/src/lib.rs +++ b/utils/prometheus/src/lib.rs @@ -122,7 +122,6 @@ async fn init_prometheus_with_listener( mod tests { use super::*; use hyper::{Client, Uri}; - use std::convert::TryFrom; #[test] fn prometheus_works() { From 1373db0655258202f441c8545374b7352a8e808f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Apr 2022 11:21:45 +0200 Subject: [PATCH 669/695] Bump backtrace from 0.3.63 to 0.3.64 (#11157) Bumps [backtrace](https://github.com/rust-lang/backtrace-rs) from 0.3.63 to 0.3.64. - [Release notes](https://github.com/rust-lang/backtrace-rs/releases) - [Commits](https://github.com/rust-lang/backtrace-rs/compare/0.3.63...0.3.64) --- updated-dependencies: - dependency-name: backtrace dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- primitives/panic-handler/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6fb6f5814565..74ad907f55d3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -400,9 +400,9 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "backtrace" -version = "0.3.63" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "321629d8ba6513061f26707241fa9bc89524ff1cd7a915a97ef0c62c666ce1b6" +checksum = "5e121dee8023ce33ab248d9ce1493df03c3b38a659b240096fcbd7048ff9c31f" dependencies = [ "addr2line", "cc", diff --git a/primitives/panic-handler/Cargo.toml b/primitives/panic-handler/Cargo.toml index 0155b6532876..7b2023eff0bf 100644 --- a/primitives/panic-handler/Cargo.toml +++ b/primitives/panic-handler/Cargo.toml @@ -14,6 +14,6 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -backtrace = "0.3.63" +backtrace = "0.3.64" regex = "1.5.5" lazy_static = "1.4.0" From 51d47a8a27c7e3b5227ab51591e119e481ec4d6c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Apr 2022 11:22:18 +0200 Subject: [PATCH 670/695] Bump dyn-clone from 1.0.4 to 1.0.5 (#11048) Bumps [dyn-clone](https://github.com/dtolnay/dyn-clone) from 1.0.4 to 1.0.5. - [Release notes](https://github.com/dtolnay/dyn-clone/releases) - [Commits](https://github.com/dtolnay/dyn-clone/compare/1.0.4...1.0.5) --- updated-dependencies: - dependency-name: dyn-clone dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 74ad907f55d3..690661dacaee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1751,9 +1751,9 @@ dependencies = [ [[package]] name = "dyn-clone" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee2626afccd7561a06cf1367e2950c4718ea04565e20fb5029b6c7d8ad09abcf" +checksum = "21e50f3adc76d6a43f5ed73b698a87d0760ca74617f60f7c3b879003536fdd28" [[package]] name = "dynasm" From 5c898d36d81fa1bde73728ba4b75020df303cccf Mon Sep 17 00:00:00 2001 From: moh-eulith <101080211+moh-eulith@users.noreply.github.com> Date: Mon, 4 Apr 2022 05:23:17 -0400 Subject: [PATCH 671/695] Update kvdb-rocksdb to 0.15.2 (#11144) --- Cargo.lock | 4 ++-- client/db/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 690661dacaee..23f11860ca6f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3616,9 +3616,9 @@ dependencies = [ [[package]] name = "kvdb-rocksdb" -version = "0.15.1" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1e72a631a32527fafe22d0751c002e67d28173c49dcaecf79d1aaa323c520e9" +checksum = "ca7fbdfd71cd663dceb0faf3367a99f8cf724514933e9867cec4995b6027cbc1" dependencies = [ "fs-swap", "kvdb", diff --git a/client/db/Cargo.toml b/client/db/Cargo.toml index 105bc43c61bc..12bb29958cfe 100644 --- a/client/db/Cargo.toml +++ b/client/db/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] parking_lot = "0.12.0" log = "0.4.8" kvdb = "0.11.0" -kvdb-rocksdb = { version = "0.15.1", optional = true } +kvdb-rocksdb = { version = "0.15.2", optional = true } kvdb-memorydb = "0.11.0" linked-hash-map = "0.5.4" hash-db = "0.15.2" From 0d888039be6afc8950c087257c8e32448ec193b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Mon, 4 Apr 2022 13:19:46 +0200 Subject: [PATCH 672/695] Revert "Replace storage access by atomics" (#11156) This reverts commit a69b8eb4a28f365a4a4b2fc295a693ec4d3d3cd5. --- frame/support/src/storage/mod.rs | 54 +++++++++++++++++--------------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/frame/support/src/storage/mod.rs b/frame/support/src/storage/mod.rs index c9814e28a7ae..106d3e3f459a 100644 --- a/frame/support/src/storage/mod.rs +++ b/frame/support/src/storage/mod.rs @@ -48,46 +48,48 @@ pub mod unhashed; pub mod weak_bounded_vec; mod transaction_level_tracker { - use core::sync::atomic::{AtomicU32, Ordering}; - type Layer = u32; - static NUM_LEVELS: AtomicU32 = AtomicU32::new(0); + const TRANSACTION_LEVEL_KEY: &'static [u8] = b":transaction_level:"; const TRANSACTIONAL_LIMIT: Layer = 255; pub fn get_transaction_level() -> Layer { - NUM_LEVELS.load(Ordering::SeqCst) + crate::storage::unhashed::get_or_default::(TRANSACTION_LEVEL_KEY) + } + + fn set_transaction_level(level: &Layer) { + crate::storage::unhashed::put::(TRANSACTION_LEVEL_KEY, level); + } + + fn kill_transaction_level() { + crate::storage::unhashed::kill(TRANSACTION_LEVEL_KEY); } /// Increments the transaction level. Returns an error if levels go past the limit. /// /// Returns a guard that when dropped decrements the transaction level automatically. pub fn inc_transaction_level() -> Result { - NUM_LEVELS - .fetch_update(Ordering::SeqCst, Ordering::SeqCst, |existing_levels| { - if existing_levels >= TRANSACTIONAL_LIMIT { - return None - } - // Cannot overflow because of check above. - Some(existing_levels + 1) - }) - .map_err(|_| ())?; + let existing_levels = get_transaction_level(); + if existing_levels >= TRANSACTIONAL_LIMIT { + return Err(()) + } + // Cannot overflow because of check above. + set_transaction_level(&(existing_levels + 1)); Ok(StorageLayerGuard) } fn dec_transaction_level() { - NUM_LEVELS - .fetch_update(Ordering::SeqCst, Ordering::SeqCst, |existing_levels| { - if existing_levels == 0 { - log::warn!( - "We are underflowing with calculating transactional levels. Not great, but let's not panic...", - ); - None - } else { - // Cannot underflow because of checks above. - Some(existing_levels - 1) - } - }) - .ok(); + let existing_levels = get_transaction_level(); + if existing_levels == 0 { + log::warn!( + "We are underflowing with calculating transactional levels. Not great, but let's not panic...", + ); + } else if existing_levels == 1 { + // Don't leave any trace of this storage item. + kill_transaction_level(); + } else { + // Cannot underflow because of checks above. + set_transaction_level(&(existing_levels - 1)); + } } pub fn is_transactional() -> bool { From 6f411cdb9cb68d1a5b140d448e9259ba9c926962 Mon Sep 17 00:00:00 2001 From: Davide Galassi Date: Mon, 4 Apr 2022 16:29:29 +0200 Subject: [PATCH 673/695] Remove not required DigestItem conversion (#11165) --- frame/aura/src/lib.rs | 4 ++-- frame/babe/src/lib.rs | 2 +- frame/grandpa/src/lib.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/frame/aura/src/lib.rs b/frame/aura/src/lib.rs index 657965c60a3f..0f474770017d 100644 --- a/frame/aura/src/lib.rs +++ b/frame/aura/src/lib.rs @@ -153,7 +153,7 @@ impl Pallet { AURA_ENGINE_ID, ConsensusLog::AuthoritiesChange(new.into_inner()).encode(), ); - >::deposit_log(log.into()); + >::deposit_log(log); } fn initialize_authorities(authorities: &[T::AuthorityId]) { @@ -225,7 +225,7 @@ impl OneSessionHandler for Pallet { ConsensusLog::::OnDisabled(i as AuthorityIndex).encode(), ); - >::deposit_log(log.into()); + >::deposit_log(log); } } diff --git a/frame/babe/src/lib.rs b/frame/babe/src/lib.rs index f673c8b43bee..87ae762707cc 100644 --- a/frame/babe/src/lib.rs +++ b/frame/babe/src/lib.rs @@ -627,7 +627,7 @@ impl Pallet { fn deposit_consensus(new: U) { let log = DigestItem::Consensus(BABE_ENGINE_ID, new.encode()); - >::deposit_log(log.into()) + >::deposit_log(log) } fn deposit_randomness(randomness: &schnorrkel::Randomness) { diff --git a/frame/grandpa/src/lib.rs b/frame/grandpa/src/lib.rs index 68d4cf26a2e2..e30d65acbc6a 100644 --- a/frame/grandpa/src/lib.rs +++ b/frame/grandpa/src/lib.rs @@ -498,7 +498,7 @@ impl Pallet { /// Deposit one of this module's logs. fn deposit_log(log: ConsensusLog) { let log = DigestItem::Consensus(GRANDPA_ENGINE_ID, log.encode()); - >::deposit_log(log.into()); + >::deposit_log(log); } // Perform module initialization, abstracted so that it can be called either through genesis From ad95f431e93ec16ef46cef06d47fb83a44148b51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Mon, 4 Apr 2022 22:28:57 +0200 Subject: [PATCH 674/695] transactional: Fix some nitpicks (#11163) * transactional: Fix some nitpicks This fixes some nitpicks related to the transactional storage stuff from me. As everything was merged too fast, here are some nitpicks from me. First, the entire functionality is moved into its own file to have a clear separation. Secondly I changed the `set_transactional_level` to not take `Layer` by reference. Besides that I have added some docs etc. * Add some comment * Move tests * :facepalm: --- frame/support/procedural/src/transactional.rs | 2 +- frame/support/src/storage/mod.rs | 212 +--------------- frame/support/src/storage/transactional.rs | 232 ++++++++++++++++++ 3 files changed, 242 insertions(+), 204 deletions(-) create mode 100644 frame/support/src/storage/transactional.rs diff --git a/frame/support/procedural/src/transactional.rs b/frame/support/procedural/src/transactional.rs index ba75fbc9737a..eb77a320a509 100644 --- a/frame/support/procedural/src/transactional.rs +++ b/frame/support/procedural/src/transactional.rs @@ -49,7 +49,7 @@ pub fn require_transactional(_attr: TokenStream, input: TokenStream) -> Result Layer { - crate::storage::unhashed::get_or_default::(TRANSACTION_LEVEL_KEY) - } - - fn set_transaction_level(level: &Layer) { - crate::storage::unhashed::put::(TRANSACTION_LEVEL_KEY, level); - } - - fn kill_transaction_level() { - crate::storage::unhashed::kill(TRANSACTION_LEVEL_KEY); - } - - /// Increments the transaction level. Returns an error if levels go past the limit. - /// - /// Returns a guard that when dropped decrements the transaction level automatically. - pub fn inc_transaction_level() -> Result { - let existing_levels = get_transaction_level(); - if existing_levels >= TRANSACTIONAL_LIMIT { - return Err(()) - } - // Cannot overflow because of check above. - set_transaction_level(&(existing_levels + 1)); - Ok(StorageLayerGuard) - } - - fn dec_transaction_level() { - let existing_levels = get_transaction_level(); - if existing_levels == 0 { - log::warn!( - "We are underflowing with calculating transactional levels. Not great, but let's not panic...", - ); - } else if existing_levels == 1 { - // Don't leave any trace of this storage item. - kill_transaction_level(); - } else { - // Cannot underflow because of checks above. - set_transaction_level(&(existing_levels - 1)); - } - } - - pub fn is_transactional() -> bool { - get_transaction_level() > 0 - } - - pub struct StorageLayerGuard; - - impl Drop for StorageLayerGuard { - fn drop(&mut self) { - dec_transaction_level() - } - } -} - -/// Check if the current call is within a transactional layer. -pub fn is_transactional() -> bool { - transaction_level_tracker::is_transactional() -} - -/// Execute the supplied function in a new storage transaction. -/// -/// All changes to storage performed by the supplied function are discarded if the returned -/// outcome is `TransactionOutcome::Rollback`. -/// -/// Transactions can be nested up to `TRANSACTIONAL_LIMIT` times; more than that will result in an -/// error. -/// -/// Commits happen to the parent transaction. -pub fn with_transaction(f: impl FnOnce() -> TransactionOutcome>) -> Result -where - E: From, -{ - use sp_io::storage::{commit_transaction, rollback_transaction, start_transaction}; - use TransactionOutcome::*; - - let _guard = transaction_level_tracker::inc_transaction_level() - .map_err(|()| TransactionalError::LimitReached.into())?; - - start_transaction(); - - match f() { - Commit(res) => { - commit_transaction(); - res - }, - Rollback(res) => { - rollback_transaction(); - res - }, - } -} - -/// Same as [`with_transaction`] but without a limit check on nested transactional layers. -/// -/// This is mostly for backwards compatibility before there was a transactional layer limit. -/// It is recommended to only use [`with_transaction`] to avoid users from generating too many -/// transactional layers. -pub fn with_transaction_unchecked(f: impl FnOnce() -> TransactionOutcome) -> R { - use sp_io::storage::{commit_transaction, rollback_transaction, start_transaction}; - use TransactionOutcome::*; - - let maybe_guard = transaction_level_tracker::inc_transaction_level(); - - if maybe_guard.is_err() { - log::warn!( - "The transactional layer limit has been reached, and new transactional layers are being - spawned with `with_transaction_unchecked`. This could be caused by someone trying to - attack your chain, and you should investigate usage of `with_transaction_unchecked` and - potentially migrate to `with_transaction`, which enforces a transactional limit.", - ); - } - - start_transaction(); - - match f() { - Commit(res) => { - commit_transaction(); - res - }, - Rollback(res) => { - rollback_transaction(); - res - }, - } -} - /// A trait for working with macro-generated storage values under the substrate storage API. /// /// Details on implementation can be found at [`generator::StorageValue`]. @@ -1473,13 +1345,12 @@ pub fn storage_prefix(pallet_name: &[u8], storage_name: &[u8]) -> [u8; 32] { #[cfg(test)] mod test { use super::*; - use crate::{assert_noop, assert_ok, hash::Identity, Twox128}; + use crate::{assert_ok, hash::Identity, Twox128}; use bounded_vec::BoundedVec; use frame_support::traits::ConstU32; use generator::StorageValue as _; use sp_core::hashing::twox_128; use sp_io::TestExternalities; - use sp_runtime::DispatchResult; use weak_bounded_vec::WeakBoundedVec; #[test] @@ -1590,71 +1461,6 @@ mod test { }); } - #[test] - fn is_transactional_should_return_false() { - TestExternalities::default().execute_with(|| { - assert!(!is_transactional()); - }); - } - - #[test] - fn is_transactional_should_not_error_in_with_transaction() { - TestExternalities::default().execute_with(|| { - assert_ok!(with_transaction(|| -> TransactionOutcome { - assert!(is_transactional()); - TransactionOutcome::Commit(Ok(())) - })); - - assert_noop!( - with_transaction(|| -> TransactionOutcome { - assert!(is_transactional()); - TransactionOutcome::Rollback(Err("revert".into())) - }), - "revert" - ); - }); - } - - fn recursive_transactional(num: u32) -> DispatchResult { - if num == 0 { - return Ok(()) - } - - with_transaction(|| -> TransactionOutcome { - let res = recursive_transactional(num - 1); - TransactionOutcome::Commit(res) - }) - } - - #[test] - fn transaction_limit_should_work() { - TestExternalities::default().execute_with(|| { - assert_eq!(transaction_level_tracker::get_transaction_level(), 0); - - assert_ok!(with_transaction(|| -> TransactionOutcome { - assert_eq!(transaction_level_tracker::get_transaction_level(), 1); - TransactionOutcome::Commit(Ok(())) - })); - - assert_ok!(with_transaction(|| -> TransactionOutcome { - assert_eq!(transaction_level_tracker::get_transaction_level(), 1); - let res = with_transaction(|| -> TransactionOutcome { - assert_eq!(transaction_level_tracker::get_transaction_level(), 2); - TransactionOutcome::Commit(Ok(())) - }); - TransactionOutcome::Commit(res) - })); - - assert_ok!(recursive_transactional(255)); - assert_noop!( - recursive_transactional(256), - sp_runtime::TransactionalError::LimitReached - ); - - assert_eq!(transaction_level_tracker::get_transaction_level(), 0); - }); - } - #[test] fn key_prefix_iterator_works() { TestExternalities::default().execute_with(|| { diff --git a/frame/support/src/storage/transactional.rs b/frame/support/src/storage/transactional.rs new file mode 100644 index 000000000000..d1c59d44e258 --- /dev/null +++ b/frame/support/src/storage/transactional.rs @@ -0,0 +1,232 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +//! Provides functionality around the transaction storage. +//! +//! Transactional storage provides functionality to run an entire code block +//! in a storage transaction. This means that either the entire changes to the +//! storage are committed or everything is thrown away. This simplifies the +//! writing of functionality that may bail at any point of operation. Otherwise +//! you would need to first verify all storage accesses and then do the storage +//! modifications. +//! +//! [`with_transaction`] provides a way to run a given closure in a transactional context. + +use sp_io::storage::{commit_transaction, rollback_transaction, start_transaction}; +use sp_runtime::{DispatchError, TransactionOutcome, TransactionalError}; + +/// The type that is being used to store the current number of active layers. +type Layer = u32; +/// The key that is holds the current number of active layers. +const TRANSACTION_LEVEL_KEY: &[u8] = b":transaction_level:"; +/// The maximum number of nested layers. +const TRANSACTIONAL_LIMIT: Layer = 255; + +/// Returns the current number of nested transactional layers. +fn get_transaction_level() -> Layer { + crate::storage::unhashed::get_or_default::(TRANSACTION_LEVEL_KEY) +} + +/// Set the current number of nested transactional layers. +fn set_transaction_level(level: Layer) { + crate::storage::unhashed::put::(TRANSACTION_LEVEL_KEY, &level); +} + +/// Kill the transactional layers storage. +fn kill_transaction_level() { + crate::storage::unhashed::kill(TRANSACTION_LEVEL_KEY); +} + +/// Increments the transaction level. Returns an error if levels go past the limit. +/// +/// Returns a guard that when dropped decrements the transaction level automatically. +fn inc_transaction_level() -> Result { + let existing_levels = get_transaction_level(); + if existing_levels >= TRANSACTIONAL_LIMIT { + return Err(()) + } + // Cannot overflow because of check above. + set_transaction_level(existing_levels + 1); + Ok(StorageLayerGuard) +} + +fn dec_transaction_level() { + let existing_levels = get_transaction_level(); + if existing_levels == 0 { + log::warn!( + "We are underflowing with calculating transactional levels. Not great, but let's not panic...", + ); + } else if existing_levels == 1 { + // Don't leave any trace of this storage item. + kill_transaction_level(); + } else { + // Cannot underflow because of checks above. + set_transaction_level(existing_levels - 1); + } +} + +struct StorageLayerGuard; + +impl Drop for StorageLayerGuard { + fn drop(&mut self) { + dec_transaction_level() + } +} + +/// Check if the current call is within a transactional layer. +pub fn is_transactional() -> bool { + get_transaction_level() > 0 +} + +/// Execute the supplied function in a new storage transaction. +/// +/// All changes to storage performed by the supplied function are discarded if the returned +/// outcome is `TransactionOutcome::Rollback`. +/// +/// Transactions can be nested up to `TRANSACTIONAL_LIMIT` times; more than that will result in an +/// error. +/// +/// Commits happen to the parent transaction. +pub fn with_transaction(f: impl FnOnce() -> TransactionOutcome>) -> Result +where + E: From, +{ + // This needs to happen before `start_transaction` below. + // Otherwise we may rollback the increase, then decrease as the guard goes out of scope + // and then end in some bad state. + let _guard = inc_transaction_level().map_err(|()| TransactionalError::LimitReached.into())?; + + start_transaction(); + + match f() { + TransactionOutcome::Commit(res) => { + commit_transaction(); + res + }, + TransactionOutcome::Rollback(res) => { + rollback_transaction(); + res + }, + } +} + +/// Same as [`with_transaction`] but without a limit check on nested transactional layers. +/// +/// This is mostly for backwards compatibility before there was a transactional layer limit. +/// It is recommended to only use [`with_transaction`] to avoid users from generating too many +/// transactional layers. +pub fn with_transaction_unchecked(f: impl FnOnce() -> TransactionOutcome) -> R { + // This needs to happen before `start_transaction` below. + // Otherwise we may rollback the increase, then decrease as the guard goes out of scope + // and then end in some bad state. + let maybe_guard = inc_transaction_level(); + + if maybe_guard.is_err() { + log::warn!( + "The transactional layer limit has been reached, and new transactional layers are being + spawned with `with_transaction_unchecked`. This could be caused by someone trying to + attack your chain, and you should investigate usage of `with_transaction_unchecked` and + potentially migrate to `with_transaction`, which enforces a transactional limit.", + ); + } + + start_transaction(); + + match f() { + TransactionOutcome::Commit(res) => { + commit_transaction(); + res + }, + TransactionOutcome::Rollback(res) => { + rollback_transaction(); + res + }, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{assert_noop, assert_ok}; + use sp_io::TestExternalities; + use sp_runtime::DispatchResult; + + #[test] + fn is_transactional_should_return_false() { + TestExternalities::default().execute_with(|| { + assert!(!is_transactional()); + }); + } + + #[test] + fn is_transactional_should_not_error_in_with_transaction() { + TestExternalities::default().execute_with(|| { + assert_ok!(with_transaction(|| -> TransactionOutcome { + assert!(is_transactional()); + TransactionOutcome::Commit(Ok(())) + })); + + assert_noop!( + with_transaction(|| -> TransactionOutcome { + assert!(is_transactional()); + TransactionOutcome::Rollback(Err("revert".into())) + }), + "revert" + ); + }); + } + + fn recursive_transactional(num: u32) -> DispatchResult { + if num == 0 { + return Ok(()) + } + + with_transaction(|| -> TransactionOutcome { + let res = recursive_transactional(num - 1); + TransactionOutcome::Commit(res) + }) + } + + #[test] + fn transaction_limit_should_work() { + TestExternalities::default().execute_with(|| { + assert_eq!(get_transaction_level(), 0); + + assert_ok!(with_transaction(|| -> TransactionOutcome { + assert_eq!(get_transaction_level(), 1); + TransactionOutcome::Commit(Ok(())) + })); + + assert_ok!(with_transaction(|| -> TransactionOutcome { + assert_eq!(get_transaction_level(), 1); + let res = with_transaction(|| -> TransactionOutcome { + assert_eq!(get_transaction_level(), 2); + TransactionOutcome::Commit(Ok(())) + }); + TransactionOutcome::Commit(res) + })); + + assert_ok!(recursive_transactional(255)); + assert_noop!( + recursive_transactional(256), + sp_runtime::TransactionalError::LimitReached + ); + + assert_eq!(get_transaction_level(), 0); + }); + } +} From 9bf7aaa2f5411db7f6efd5aa00360d04f09d1b53 Mon Sep 17 00:00:00 2001 From: Zhenghao Lu <54395432+EmisonLu@users.noreply.github.com> Date: Tue, 5 Apr 2022 16:39:46 +0800 Subject: [PATCH 675/695] Correct a spelling mistake (#11167) --- client/executor/wasmtime/src/runtime.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/executor/wasmtime/src/runtime.rs b/client/executor/wasmtime/src/runtime.rs index cbe1359d28a6..fa3b567cc0ab 100644 --- a/client/executor/wasmtime/src/runtime.rs +++ b/client/executor/wasmtime/src/runtime.rs @@ -386,7 +386,7 @@ pub struct Semantics { // I.e. if [`CodeSupplyMode::Verbatim`] is used. pub fast_instance_reuse: bool, - /// Specifiying `Some` will enable deterministic stack height. That is, all executor + /// Specifying `Some` will enable deterministic stack height. That is, all executor /// invocations will reach stack overflow at the exactly same point across different wasmtime /// versions and architectures. /// From 585e7e8cc2a24874898e6490ea96462db7d9c3ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Tue, 5 Apr 2022 19:01:45 +0200 Subject: [PATCH 676/695] Upgrade to wasmer 2.2 (#11168) --- Cargo.lock | 389 ++++++++++++------ client/executor/common/Cargo.toml | 5 +- client/executor/common/src/sandbox.rs | 2 + .../common/src/sandbox/wasmer_backend.rs | 6 +- .../src/communication/gossip.rs | 2 +- client/finality-grandpa/src/justification.rs | 2 +- 6 files changed, 270 insertions(+), 136 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 23f11860ca6f..17931984c41e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -795,6 +795,27 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" +[[package]] +name = "bytecheck" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "314889ea31cda264cb7c3d6e6e5c9415a987ecb0e72c17c00d36fbb881d34abe" +dependencies = [ + "bytecheck_derive", + "ptr_meta", +] + +[[package]] +name = "bytecheck_derive" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a2b3b92c135dae665a6f760205b89187638e83bed17ef3e44e83c712cf30600" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "byteorder" version = "1.3.4" @@ -1140,11 +1161,11 @@ checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634" [[package]] name = "cranelift-bforest" -version = "0.68.0" +version = "0.76.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9221545c0507dc08a62b2d8b5ffe8e17ac580b0a74d1813b496b8d70b070fbd0" +checksum = "7e6bea67967505247f54fa2c85cf4f6e0e31c4e5692c9b70e4ae58e339067333" dependencies = [ - "cranelift-entity 0.68.0", + "cranelift-entity 0.76.0", ] [[package]] @@ -1158,21 +1179,19 @@ dependencies = [ [[package]] name = "cranelift-codegen" -version = "0.68.0" +version = "0.76.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e9936ea608b6cd176f107037f6adbb4deac933466fc7231154f96598b2d3ab1" +checksum = "48194035d2752bdd5bdae429e3ab88676e95f52a2b1355a5d4e809f9e39b1d74" dependencies = [ - "byteorder", - "cranelift-bforest 0.68.0", - "cranelift-codegen-meta 0.68.0", - "cranelift-codegen-shared 0.68.0", - "cranelift-entity 0.68.0", - "gimli 0.22.0", + "cranelift-bforest 0.76.0", + "cranelift-codegen-meta 0.76.0", + "cranelift-codegen-shared 0.76.0", + "cranelift-entity 0.76.0", + "gimli 0.25.0", "log 0.4.14", "regalloc 0.0.31", "smallvec 1.8.0", - "target-lexicon 0.11.2", - "thiserror", + "target-lexicon", ] [[package]] @@ -1189,17 +1208,17 @@ dependencies = [ "log 0.4.14", "regalloc 0.0.33", "smallvec 1.8.0", - "target-lexicon 0.12.0", + "target-lexicon", ] [[package]] name = "cranelift-codegen-meta" -version = "0.68.0" +version = "0.76.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ef2b2768568306540f4c8db3acce9105534d34c4a1e440529c1e702d7f8c8d7" +checksum = "976efb22fcab4f2cd6bd4e9913764616a54d895c1a23530128d04e03633c555f" dependencies = [ - "cranelift-codegen-shared 0.68.0", - "cranelift-entity 0.68.0", + "cranelift-codegen-shared 0.76.0", + "cranelift-entity 0.76.0", ] [[package]] @@ -1213,9 +1232,9 @@ dependencies = [ [[package]] name = "cranelift-codegen-shared" -version = "0.68.0" +version = "0.76.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6759012d6d19c4caec95793f052613e9d4113e925e7f14154defbac0f1d4c938" +checksum = "9dabb5fe66e04d4652e434195b45ae65b5c8172d520247b8f66d8df42b2b45dc" [[package]] name = "cranelift-codegen-shared" @@ -1225,12 +1244,9 @@ checksum = "981da52d8f746af1feb96290c83977ff8d41071a7499e991d8abae0d4869f564" [[package]] name = "cranelift-entity" -version = "0.68.0" +version = "0.76.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86badbce14e15f52a45b666b38abe47b204969dd7f8fb7488cb55dd46b361fa6" -dependencies = [ - "serde", -] +checksum = "3329733e4d4b8e91c809efcaa4faee80bf66f20164e3dd16d707346bd3494799" [[package]] name = "cranelift-entity" @@ -1243,14 +1259,14 @@ dependencies = [ [[package]] name = "cranelift-frontend" -version = "0.68.0" +version = "0.76.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b608bb7656c554d0a4cf8f50c7a10b857e80306f6ff829ad6d468a7e2323c8d8" +checksum = "279afcc0d3e651b773f94837c3d581177b348c8d69e928104b2e9fccb226f921" dependencies = [ - "cranelift-codegen 0.68.0", + "cranelift-codegen 0.76.0", "log 0.4.14", "smallvec 1.8.0", - "target-lexicon 0.11.2", + "target-lexicon", ] [[package]] @@ -1262,7 +1278,7 @@ dependencies = [ "cranelift-codegen 0.80.0", "log 0.4.14", "smallvec 1.8.0", - "target-lexicon 0.12.0", + "target-lexicon", ] [[package]] @@ -1273,7 +1289,7 @@ checksum = "166028ca0343a6ee7bddac0e70084e142b23f99c701bd6f6ea9123afac1a7a46" dependencies = [ "cranelift-codegen 0.80.0", "libc", - "target-lexicon 0.12.0", + "target-lexicon", ] [[package]] @@ -1757,9 +1773,9 @@ checksum = "21e50f3adc76d6a43f5ed73b698a87d0760ca74617f60f7c3b879003536fdd28" [[package]] name = "dynasm" -version = "1.1.0" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdc2d9a5e44da60059bd38db2d05cbb478619541b8c79890547861ec1e3194f0" +checksum = "add9a102807b524ec050363f09e06f1504214b0e1c7797f64261c891022dce8b" dependencies = [ "bitflags", "byteorder", @@ -1772,13 +1788,13 @@ dependencies = [ [[package]] name = "dynasmrt" -version = "1.1.0" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42276e3f205fe63887cca255aa9a65a63fb72764c30b9a6252a7c7e46994f689" +checksum = "64fba5a42bd76a17cad4bfa00de168ee1cbfa06a5e8ce992ae880218c05641a9" dependencies = [ "byteorder", "dynasm", - "memmap2 0.2.1", + "memmap2 0.5.0", ] [[package]] @@ -1851,6 +1867,26 @@ dependencies = [ "syn", ] +[[package]] +name = "enum-iterator" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eeac5c5edb79e4e39fe8439ef35207780a11f69c52cbe424ce3dfad4cb78de6" +dependencies = [ + "enum-iterator-derive", +] + +[[package]] +name = "enum-iterator-derive" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c134c37760b27a871ba422106eedbb8247da973a09e82558bf26d619c882b159" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "enumflags2" version = "0.6.4" @@ -2676,9 +2712,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.22.0" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaf91faf136cb47367fa430cd46e37a788775e7fa104f8b4bcb3861dc389b724" +checksum = "f0a01e0497841a3b2db4f8afa483cce65f7e96a3498bd6c541734792aeac8fe7" dependencies = [ "fallible-iterator", "indexmap", @@ -3684,16 +3720,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "libloading" -version = "0.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "351a32417a12d5f7e82c368a66781e307834dae04c6ce0cd4456d52989229883" -dependencies = [ - "cfg-if 1.0.0", - "winapi 0.3.9", -] - [[package]] name = "libloading" version = "0.7.0" @@ -4343,6 +4369,27 @@ dependencies = [ "value-bag", ] +[[package]] +name = "loupe" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6a72dfa44fe15b5e76b94307eeb2ff995a8c5b283b55008940c02e0c5b634d" +dependencies = [ + "indexmap", + "loupe-derive", + "rustversion", +] + +[[package]] +name = "loupe-derive" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0fbfc88337168279f2e9ae06e157cfed4efd3316e14dc96ed074d4f2e6c5952" +dependencies = [ + "quote", + "syn", +] + [[package]] name = "lru" version = "0.6.6" @@ -5327,21 +5374,23 @@ dependencies = [ [[package]] name = "object" -version = "0.22.0" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397" +checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9" dependencies = [ "crc32fast", "indexmap", + "memchr", ] [[package]] name = "object" -version = "0.27.1" +version = "0.28.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9" +checksum = "40bec70ba014595f99f7aa110b84331ffe1ee9aece7fe6f387cc7e3ecda4d456" dependencies = [ "crc32fast", + "hashbrown 0.11.2", "indexmap", "memchr", ] @@ -7365,6 +7414,26 @@ dependencies = [ "cc", ] +[[package]] +name = "ptr_meta" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" +dependencies = [ + "ptr_meta_derive", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "quick-error" version = "1.2.3" @@ -7776,6 +7845,18 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "region" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76e189c2369884dce920945e2ddf79b3dff49e071a167dd1817fa9c4c00d512e" +dependencies = [ + "bitflags", + "libc", + "mach", + "winapi 0.3.9", +] + [[package]] name = "remote-externalities" version = "0.10.0-dev" @@ -7804,6 +7885,15 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "rend" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79af64b4b6362ffba04eef3a4e10829718a4896dac19daa741851c86781edf95" +dependencies = [ + "bytecheck", +] + [[package]] name = "resolv-conf" version = "0.7.0" @@ -7835,6 +7925,31 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "rkyv" +version = "0.7.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f08c8062c1fe1253064043b8fc07bfea1b9702b71b4a86c11ea3588183b12e1" +dependencies = [ + "bytecheck", + "hashbrown 0.12.0", + "ptr_meta", + "rend", + "rkyv_derive", + "seahash", +] + +[[package]] +name = "rkyv_derive" +version = "0.7.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e289706df51226e84814bf6ba1a9e1013112ae29bc7a9878f73fce360520c403" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "rocksdb" version = "0.18.0" @@ -8524,7 +8639,6 @@ dependencies = [ "thiserror", "wasm-instrument", "wasmer", - "wasmer-compiler-singlepass", "wasmi", ] @@ -9257,6 +9371,12 @@ dependencies = [ "untrusted", ] +[[package]] +name = "seahash" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" + [[package]] name = "sec1" version = "0.2.1" @@ -10855,15 +10975,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "target-lexicon" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "422045212ea98508ae3d28025bc5aaa2bd4a9cdaecd442a08da2ee620ee9ea95" - -[[package]] -name = "target-lexicon" -version = "0.12.0" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64ae3b39281e4b14b8123bdbaddd472b7dfe215e444181f2f9d2443c2444f834" +checksum = "d7fa7e55043acb85fca6b3c01485a2eeb6b69c5d21002e273c79e465f43b7ac1" [[package]] name = "tempfile" @@ -11232,6 +11346,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" dependencies = [ "cfg-if 1.0.0", + "log 0.4.14", "pin-project-lite 0.2.6", "tracing-attributes", "tracing-core", @@ -11471,9 +11586,9 @@ version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ee73e6e4924fe940354b8d4d98cad5231175d615cd855b758adc658c0aac6a0" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 0.1.10", "digest 0.10.3", - "rand 0.8.4", + "rand 0.6.5", "static_assertions", ] @@ -11820,21 +11935,25 @@ dependencies = [ [[package]] name = "wasmer" -version = "1.0.2" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a70cfae554988d904d64ca17ab0e7cd652ee5c8a0807094819c1ea93eb9d6866" +checksum = "f727a39e7161f7438ddb8eafe571b67c576a8c2fb459f666d9053b5bba4afdea" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "indexmap", + "js-sys", + "loupe", "more-asserts", - "target-lexicon 0.11.2", + "target-lexicon", "thiserror", + "wasm-bindgen", "wasmer-compiler", "wasmer-compiler-cranelift", + "wasmer-compiler-singlepass", "wasmer-derive", "wasmer-engine", - "wasmer-engine-jit", - "wasmer-engine-native", + "wasmer-engine-dylib", + "wasmer-engine-universal", "wasmer-types", "wasmer-vm", "wat", @@ -11843,34 +11962,38 @@ dependencies = [ [[package]] name = "wasmer-compiler" -version = "1.0.2" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b7732a9cab472bd921d5a0c422f45b3d03f62fa2c40a89e0770cef6d47e383e" +checksum = "4e9951599222eb12bd13d4d91bcded0a880e4c22c2dfdabdf5dc7e5e803b7bf3" dependencies = [ "enumset", + "loupe", + "rkyv", "serde", "serde_bytes", "smallvec 1.8.0", - "target-lexicon 0.11.2", + "target-lexicon", "thiserror", "wasmer-types", "wasmer-vm", - "wasmparser 0.65.0", + "wasmparser 0.78.2", ] [[package]] name = "wasmer-compiler-cranelift" -version = "1.0.2" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48cb9395f094e1d81534f4c5e330ed4cdb424e8df870d29ad585620284f5fddb" +checksum = "44c83273bce44e668f3a2b9ccb7f1193db918b1d6806f64acc5ff71f6ece5f20" dependencies = [ - "cranelift-codegen 0.68.0", - "cranelift-frontend 0.68.0", - "gimli 0.22.0", + "cranelift-codegen 0.76.0", + "cranelift-entity 0.76.0", + "cranelift-frontend 0.76.0", + "gimli 0.25.0", + "loupe", "more-asserts", "rayon", - "serde", "smallvec 1.8.0", + "target-lexicon", "tracing", "wasmer-compiler", "wasmer-types", @@ -11879,17 +12002,17 @@ dependencies = [ [[package]] name = "wasmer-compiler-singlepass" -version = "1.0.2" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "426ae6ef0f606ca815510f3e2ef6f520e217514bfb7a664defe180b9a9e75d07" +checksum = "5432e993840cdb8e6875ddc8c9eea64e7a129579b4706bd91b8eb474d9c4a860" dependencies = [ "byteorder", "dynasm", "dynasmrt", "lazy_static", + "loupe", "more-asserts", "rayon", - "serde", "smallvec 1.8.0", "wasmer-compiler", "wasmer-types", @@ -11898,9 +12021,9 @@ dependencies = [ [[package]] name = "wasmer-derive" -version = "1.0.2" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b86dcd2c3efdb8390728a2b56f762db07789aaa5aa872a9dc776ba3a7912ed" +checksum = "458dbd9718a837e6dbc52003aef84487d79eedef5fa28c7d28b6784be98ac08e" dependencies = [ "proc-macro-error", "proc-macro2", @@ -11910,19 +12033,20 @@ dependencies = [ [[package]] name = "wasmer-engine" -version = "1.0.2" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efe4667d6bd888f26ae8062a63a9379fa697415b4b4e380f33832e8418fd71b5" +checksum = "6ed603a6d037ebbb14014d7f739ae996a78455a4b86c41cfa4e81c590a1253b9" dependencies = [ "backtrace", - "bincode", + "enumset", "lazy_static", - "memmap2 0.2.1", + "loupe", + "memmap2 0.5.0", "more-asserts", "rustc-demangle", "serde", "serde_bytes", - "target-lexicon 0.11.2", + "target-lexicon", "thiserror", "wasmer-compiler", "wasmer-types", @@ -11930,51 +12054,57 @@ dependencies = [ ] [[package]] -name = "wasmer-engine-jit" -version = "1.0.2" +name = "wasmer-engine-dylib" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26770be802888011b4a3072f2a282fc2faa68aa48c71b3db6252a3937a85f3da" +checksum = "ccd7fdc60e252a795c849b3f78a81a134783051407e7e279c10b7019139ef8dc" dependencies = [ - "bincode", - "cfg-if 0.1.10", - "region", + "cfg-if 1.0.0", + "enum-iterator", + "enumset", + "leb128", + "libloading 0.7.0", + "loupe", + "object 0.28.3", + "rkyv", "serde", - "serde_bytes", + "tempfile", + "tracing", "wasmer-compiler", "wasmer-engine", + "wasmer-object", "wasmer-types", "wasmer-vm", - "winapi 0.3.9", + "which", ] [[package]] -name = "wasmer-engine-native" -version = "1.0.2" +name = "wasmer-engine-universal" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bb4083a6c69f2cd4b000b82a80717f37c6cc2e536aee3a8ffe9af3edc276a8b" +checksum = "dcff0cd2c01a8de6009fd863b14ea883132a468a24f2d2ee59dc34453d3a31b5" dependencies = [ - "bincode", - "cfg-if 0.1.10", + "cfg-if 1.0.0", + "enum-iterator", + "enumset", "leb128", - "libloading 0.6.7", - "serde", - "tempfile", - "tracing", + "loupe", + "region 3.0.0", + "rkyv", "wasmer-compiler", "wasmer-engine", - "wasmer-object", "wasmer-types", "wasmer-vm", - "which", + "winapi 0.3.9", ] [[package]] name = "wasmer-object" -version = "1.0.2" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abf8e0c12b82ff81ebecd30d7e118be5fec871d6de885a90eeb105df0a769a7b" +checksum = "24ce18ac2877050e59580d27ee1a88f3192d7a31e77fbba0852abc7888d6e0b5" dependencies = [ - "object 0.22.0", + "object 0.28.3", "thiserror", "wasmer-compiler", "wasmer-types", @@ -11982,29 +12112,34 @@ dependencies = [ [[package]] name = "wasmer-types" -version = "1.0.2" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f4ac28c2951cd792c18332f03da523ed06b170f5cf6bb5b1bdd7e36c2a8218" +checksum = "659fa3dd6c76f62630deff4ac8c7657b07f0b1e4d7e0f8243a552b9d9b448e24" dependencies = [ - "cranelift-entity 0.68.0", + "indexmap", + "loupe", + "rkyv", "serde", "thiserror", ] [[package]] name = "wasmer-vm" -version = "1.0.2" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7635ba0b6d2fd325f588d69a950ad9fa04dddbf6ad08b6b2a183146319bf6ae" +checksum = "afdc46158517c2769f9938bc222a7d41b3bb330824196279d8aa2d667cd40641" dependencies = [ "backtrace", "cc", - "cfg-if 0.1.10", + "cfg-if 1.0.0", + "enum-iterator", "indexmap", "libc", + "loupe", "memoffset", "more-asserts", - "region", + "region 3.0.0", + "rkyv", "serde", "thiserror", "wasmer-types", @@ -12039,9 +12174,9 @@ dependencies = [ [[package]] name = "wasmparser" -version = "0.65.0" +version = "0.78.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc2fe6350834b4e528ba0901e7aa405d78b89dc1fa3145359eb4de0e323fcf" +checksum = "52144d4c78e5cf8b055ceab8e5fa22814ce4315d6002ad32cfd914f37c12fd65" [[package]] name = "wasmparser" @@ -12068,10 +12203,10 @@ dependencies = [ "paste 1.0.6", "psm", "rayon", - "region", + "region 2.2.0", "rustc-demangle", "serde", - "target-lexicon 0.12.0", + "target-lexicon", "wasmparser 0.81.0", "wasmtime-cache", "wasmtime-cranelift", @@ -12117,7 +12252,7 @@ dependencies = [ "log 0.4.14", "more-asserts", "object 0.27.1", - "target-lexicon 0.12.0", + "target-lexicon", "thiserror", "wasmparser 0.81.0", "wasmtime-environ", @@ -12137,7 +12272,7 @@ dependencies = [ "more-asserts", "object 0.27.1", "serde", - "target-lexicon 0.12.0", + "target-lexicon", "thiserror", "wasmparser 0.81.0", "wasmtime-types", @@ -12155,10 +12290,10 @@ dependencies = [ "cfg-if 1.0.0", "gimli 0.26.1", "object 0.27.1", - "region", + "region 2.2.0", "rustix", "serde", - "target-lexicon 0.12.0", + "target-lexicon", "thiserror", "wasmtime-environ", "wasmtime-runtime", @@ -12183,7 +12318,7 @@ dependencies = [ "memoffset", "more-asserts", "rand 0.8.4", - "region", + "region 2.2.0", "rustix", "thiserror", "wasmtime-environ", diff --git a/client/executor/common/Cargo.toml b/client/executor/common/Cargo.toml index 9282fe3b03dd..149d9fdc236c 100644 --- a/client/executor/common/Cargo.toml +++ b/client/executor/common/Cargo.toml @@ -24,13 +24,10 @@ sp-maybe-compressed-blob = { version = "4.1.0-dev", path = "../../../primitives/ sp-serializer = { version = "4.0.0-dev", path = "../../../primitives/serializer" } thiserror = "1.0.30" environmental = "1.1.3" - -wasmer = { version = "1.0", optional = true } -wasmer-compiler-singlepass = { version = "1.0", optional = true } +wasmer = { version = "2.2", optional = true, features = ["singlepass"] } [features] default = [] wasmer-sandbox = [ "wasmer", - "wasmer-compiler-singlepass", ] diff --git a/client/executor/common/src/sandbox.rs b/client/executor/common/src/sandbox.rs index 3f46ec53bdfe..a2c1f602b1c9 100644 --- a/client/executor/common/src/sandbox.rs +++ b/client/executor/common/src/sandbox.rs @@ -251,6 +251,8 @@ pub enum InstantiationError { /// Module is well-formed, instantiated and linked, but while executing the start function /// a trap was generated. StartTrapped, + /// The code was compiled with a CPU feature not available on the host. + CpuFeature, } fn decode_environment_definition( diff --git a/client/executor/common/src/sandbox/wasmer_backend.rs b/client/executor/common/src/sandbox/wasmer_backend.rs index 904afc947040..44b43757148d 100644 --- a/client/executor/common/src/sandbox/wasmer_backend.rs +++ b/client/executor/common/src/sandbox/wasmer_backend.rs @@ -43,9 +43,8 @@ pub struct Backend { impl Backend { pub fn new() -> Self { - let compiler = wasmer_compiler_singlepass::Singlepass::default(); - - Backend { store: wasmer::Store::new(&wasmer::JIT::new(compiler).engine()) } + let compiler = wasmer::Singlepass::default(); + Backend { store: wasmer::Store::new(&wasmer::Universal::new(compiler).engine()) } } } @@ -191,6 +190,7 @@ pub fn instantiate( wasmer::InstantiationError::Start(_) => InstantiationError::StartTrapped, wasmer::InstantiationError::HostEnvInitialization(_) => InstantiationError::EnvironmentDefinitionCorrupted, + wasmer::InstantiationError::CpuFeature(_) => InstantiationError::CpuFeature, }) })?; diff --git a/client/finality-grandpa/src/communication/gossip.rs b/client/finality-grandpa/src/communication/gossip.rs index 7ac4066780d0..c39e2e82a621 100644 --- a/client/finality-grandpa/src/communication/gossip.rs +++ b/client/finality-grandpa/src/communication/gossip.rs @@ -799,7 +799,7 @@ impl Inner { Some(ref mut v) => if v.set_id == set_id { let diff_authorities = self.authorities.iter().collect::>() != - authorities.iter().collect(); + authorities.iter().collect::>(); if diff_authorities { debug!(target: "afg", diff --git a/client/finality-grandpa/src/justification.rs b/client/finality-grandpa/src/justification.rs index 5ee5f278ed8b..39f24cb8ea57 100644 --- a/client/finality-grandpa/src/justification.rs +++ b/client/finality-grandpa/src/justification.rs @@ -185,7 +185,7 @@ impl GrandpaJustification { } } - let ancestry_hashes = + let ancestry_hashes: HashSet<_> = self.votes_ancestries.iter().map(|h: &Block::Header| h.hash()).collect(); if visited_hashes != ancestry_hashes { From d4ca1fdd6c8ab9c43c4349761b0b63e47be1081b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Apr 2022 21:14:49 +0000 Subject: [PATCH 677/695] Bump enumflags2 from 0.6.4 to 0.7.4 (#11108) * Bump enumflags2 from 0.6.4 to 0.7.4 Bumps [enumflags2](https://github.com/NieDzejkob/enumflags2) from 0.6.4 to 0.7.4. - [Release notes](https://github.com/NieDzejkob/enumflags2/releases) - [Commits](https://github.com/NieDzejkob/enumflags2/compare/v0.6.4...v0.7.4) --- updated-dependencies: - dependency-name: enumflags2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * use `#[bitflags]` attribute macro Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Shawn Tabrizi --- Cargo.lock | 12 ++++++------ frame/identity/Cargo.toml | 2 +- frame/identity/src/types.rs | 5 +++-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 17931984c41e..bd6db8027211 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1889,18 +1889,18 @@ dependencies = [ [[package]] name = "enumflags2" -version = "0.6.4" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83c8d82922337cd23a15f88b70d8e4ef5f11da38dd7cdb55e84dd5de99695da0" +checksum = "1b3ab37dc79652c9d85f1f7b6070d77d321d2467f5fe7b00d6b7a86c57b092ae" dependencies = [ "enumflags2_derive", ] [[package]] name = "enumflags2_derive" -version = "0.6.4" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "946ee94e3dbf58fdd324f9ce245c7b238d46a66f00e86a020b71996349e46cce" +checksum = "f58dc3c5e468259f19f2d46304a6b28f1c3d034442e14b322d2b850e36f6d5ae" dependencies = [ "proc-macro2", "quote", @@ -11586,9 +11586,9 @@ version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ee73e6e4924fe940354b8d4d98cad5231175d615cd855b758adc658c0aac6a0" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "digest 0.10.3", - "rand 0.6.5", + "rand 0.8.4", "static_assertions", ] diff --git a/frame/identity/Cargo.toml b/frame/identity/Cargo.toml index 7ebfda7cf176..5dff7acc73e2 100644 --- a/frame/identity/Cargo.toml +++ b/frame/identity/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } -enumflags2 = { version = "0.6.2" } +enumflags2 = { version = "0.7.4" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } diff --git a/frame/identity/src/types.rs b/frame/identity/src/types.rs index cb79ace98d81..18fc54c941cb 100644 --- a/frame/identity/src/types.rs +++ b/frame/identity/src/types.rs @@ -17,7 +17,7 @@ use super::*; use codec::{Decode, Encode, MaxEncodedLen}; -use enumflags2::BitFlags; +use enumflags2::{bitflags, BitFlags}; use frame_support::{ traits::{ConstU32, Get}, BoundedVec, CloneNoBound, PartialEqNoBound, RuntimeDebugNoBound, @@ -230,8 +230,9 @@ impl Date: Wed, 6 Apr 2022 09:55:55 +0200 Subject: [PATCH 678/695] Change default execution strategies to `Wasm` (#11170) This pr changes all default execution strategies to `Wasm`. This is basically a deprecation of the native runtime. While the native runtime isn't removed and can still be used, it will not be used anymore by default. This will also improve the usage for people who want to run random commits, which most often forget to run with `--execution wasm`. Otherwise they often run into storage root mismatches because of using the native runtime. --- client/cli/src/arg_enums.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/cli/src/arg_enums.rs b/client/cli/src/arg_enums.rs index df4b68ff5c32..a09b7f824c7b 100644 --- a/client/cli/src/arg_enums.rs +++ b/client/cli/src/arg_enums.rs @@ -281,14 +281,14 @@ impl Into for SyncMode { } /// Default value for the `--execution-syncing` parameter. -pub const DEFAULT_EXECUTION_SYNCING: ExecutionStrategy = ExecutionStrategy::NativeElseWasm; +pub const DEFAULT_EXECUTION_SYNCING: ExecutionStrategy = ExecutionStrategy::Wasm; /// Default value for the `--execution-import-block` parameter. -pub const DEFAULT_EXECUTION_IMPORT_BLOCK: ExecutionStrategy = ExecutionStrategy::NativeElseWasm; +pub const DEFAULT_EXECUTION_IMPORT_BLOCK: ExecutionStrategy = ExecutionStrategy::Wasm; /// Default value for the `--execution-import-block` parameter when the node is a validator. pub const DEFAULT_EXECUTION_IMPORT_BLOCK_VALIDATOR: ExecutionStrategy = ExecutionStrategy::Wasm; /// Default value for the `--execution-block-construction` parameter. pub const DEFAULT_EXECUTION_BLOCK_CONSTRUCTION: ExecutionStrategy = ExecutionStrategy::Wasm; /// Default value for the `--execution-offchain-worker` parameter. -pub const DEFAULT_EXECUTION_OFFCHAIN_WORKER: ExecutionStrategy = ExecutionStrategy::Native; +pub const DEFAULT_EXECUTION_OFFCHAIN_WORKER: ExecutionStrategy = ExecutionStrategy::Wasm; /// Default value for the `--execution-other` parameter. -pub const DEFAULT_EXECUTION_OTHER: ExecutionStrategy = ExecutionStrategy::Native; +pub const DEFAULT_EXECUTION_OTHER: ExecutionStrategy = ExecutionStrategy::Wasm; From 184d29caf8302053fac74ad74cd68bf43572108e Mon Sep 17 00:00:00 2001 From: Davide Galassi Date: Wed, 6 Apr 2022 10:19:14 +0200 Subject: [PATCH 679/695] Fix fork-tree descendent check (#11150) * Fix fork-tree descendent check * Add test assertions for the fix * Improve documentation * Nitpicks --- utils/fork-tree/src/lib.rs | 76 +++++++++++++++++++++++--------------- 1 file changed, 46 insertions(+), 30 deletions(-) diff --git a/utils/fork-tree/src/lib.rs b/utils/fork-tree/src/lib.rs index 1d9b39f7dc04..c23a4f55f44a 100644 --- a/utils/fork-tree/src/lib.rs +++ b/utils/fork-tree/src/lib.rs @@ -509,14 +509,14 @@ where } /// Checks if any node in the tree is finalized by either finalizing the - /// node itself or a child node that's not in the tree, guaranteeing that - /// the node being finalized isn't a descendent of any of the node's - /// children. Returns `Some(true)` if the node being finalized is a root, - /// `Some(false)` if the node being finalized is not a root, and `None` if - /// no node in the tree is finalized. The given `predicate` is checked on - /// the prospective finalized root and must pass for finalization to occur. - /// The given function `is_descendent_of` should return `true` if the second - /// hash (target) is a descendent of the first hash (base). + /// node itself or a node's descendent that's not in the tree, guaranteeing + /// that the node being finalized isn't a descendent of (or equal to) any of + /// the node's children. Returns `Some(true)` if the node being finalized is + /// a root, `Some(false)` if the node being finalized is not a root, and + /// `None` if no node in the tree is finalized. The given `predicate` is + /// checked on the prospective finalized root and must pass for finalization + /// to occur. The given function `is_descendent_of` should return `true` if + /// the second hash (target) is a descendent of the first hash (base). pub fn finalizes_any_with_descendent_if( &self, hash: &H, @@ -541,8 +541,10 @@ where for node in self.node_iter() { if predicate(&node.data) { if node.hash == *hash || is_descendent_of(&node.hash, hash)? { - for node in node.children.iter() { - if node.number <= number && is_descendent_of(&node.hash, &hash)? { + for child in node.children.iter() { + if child.number <= number && + (child.hash == *hash || is_descendent_of(&child.hash, hash)?) + { return Err(Error::UnfinalizedAncestor) } } @@ -556,12 +558,12 @@ where } /// Finalize a root in the tree by either finalizing the node itself or a - /// child node that's not in the tree, guaranteeing that the node being - /// finalized isn't a descendent of any of the root's children. The given - /// `predicate` is checked on the prospective finalized root and must pass for - /// finalization to occur. The given function `is_descendent_of` should - /// return `true` if the second hash (target) is a descendent of the first - /// hash (base). + /// node's descendent that's not in the tree, guaranteeing that the node + /// being finalized isn't a descendent of (or equal to) any of the root's + /// children. The given `predicate` is checked on the prospective finalized + /// root and must pass for finalization to occur. The given function + /// `is_descendent_of` should return `true` if the second hash (target) is a + /// descendent of the first hash (base). pub fn finalize_with_descendent_if( &mut self, hash: &H, @@ -587,8 +589,10 @@ where for (i, root) in self.roots.iter().enumerate() { if predicate(&root.data) { if root.hash == *hash || is_descendent_of(&root.hash, hash)? { - for node in root.children.iter() { - if node.number <= number && is_descendent_of(&node.hash, &hash)? { + for child in root.children.iter() { + if child.number <= number && + (child.hash == *hash || is_descendent_of(&child.hash, hash)?) + { return Err(Error::UnfinalizedAncestor) } } @@ -606,12 +610,11 @@ where node.data }); - // if the block being finalized is earlier than a given root, then it - // must be its ancestor, otherwise we can prune the root. if there's a - // root at the same height then the hashes must match. otherwise the - // node being finalized is higher than the root so it must be its - // descendent (in this case the node wasn't finalized earlier presumably - // because the predicate didn't pass). + // Retain only roots that are descendents of the finalized block (this + // happens if the node has been properly finalized) or that are + // ancestors (or equal) to the finalized block (in this case the node + // wasn't finalized earlier presumably because the predicate didn't + // pass). let mut changed = false; let roots = std::mem::take(&mut self.roots); @@ -1275,18 +1278,31 @@ mod test { Ok(None), ); + // finalizing "D" is not allowed since it is not a root. + assert_eq!( + tree.finalize_with_descendent_if(&"D", 10, &is_descendent_of, |c| c.effective <= 10), + Err(Error::UnfinalizedAncestor) + ); + // finalizing "D" will finalize a block from the tree, but it can't be applied yet - // since it is not a root change + // since it is not a root change. assert_eq!( tree.finalizes_any_with_descendent_if(&"D", 10, &is_descendent_of, |c| c.effective == - 10,), + 10), Ok(Some(false)), ); + // finalizing "E" is not allowed since there are not finalized anchestors. + assert_eq!( + tree.finalizes_any_with_descendent_if(&"E", 15, &is_descendent_of, |c| c.effective == + 10), + Err(Error::UnfinalizedAncestor) + ); + // finalizing "B" doesn't finalize "A0" since the predicate doesn't pass, // although it will clear out "A1" from the tree assert_eq!( - tree.finalize_with_descendent_if(&"B", 2, &is_descendent_of, |c| c.effective <= 2,), + tree.finalize_with_descendent_if(&"B", 2, &is_descendent_of, |c| c.effective <= 2), Ok(FinalizationResult::Changed(None)), ); @@ -1307,7 +1323,7 @@ mod test { ); assert_eq!( - tree.finalize_with_descendent_if(&"C", 5, &is_descendent_of, |c| c.effective <= 5,), + tree.finalize_with_descendent_if(&"C", 5, &is_descendent_of, |c| c.effective <= 5), Ok(FinalizationResult::Changed(Some(Change { effective: 5 }))), ); @@ -1326,12 +1342,12 @@ mod test { // it will work with "G" though since it is not in the same branch as "E" assert_eq!( tree.finalizes_any_with_descendent_if(&"G", 100, &is_descendent_of, |c| c.effective <= - 100,), + 100), Ok(Some(true)), ); assert_eq!( - tree.finalize_with_descendent_if(&"G", 100, &is_descendent_of, |c| c.effective <= 100,), + tree.finalize_with_descendent_if(&"G", 100, &is_descendent_of, |c| c.effective <= 100), Ok(FinalizationResult::Changed(Some(Change { effective: 10 }))), ); From c4dd1bef02b7607018969e79bb16d33c6576ed33 Mon Sep 17 00:00:00 2001 From: Davide Galassi Date: Wed, 6 Apr 2022 16:23:57 +0200 Subject: [PATCH 680/695] Grandpa revert procedure (#11162) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Grandpa revert procedure * Trigger ci pipeline * Test rename * Update client/finality-grandpa/src/authorities.rs Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> --- bin/node-template/node/src/command.rs | 6 +- bin/node/cli/src/command.rs | 15 ++- client/consensus/babe/src/lib.rs | 4 +- client/finality-grandpa/src/authorities.rs | 33 +++++- client/finality-grandpa/src/lib.rs | 49 +++++++- client/finality-grandpa/src/tests.rs | 127 ++++++++++++++++++++- client/network/test/src/lib.rs | 2 +- 7 files changed, 224 insertions(+), 12 deletions(-) diff --git a/bin/node-template/node/src/command.rs b/bin/node-template/node/src/command.rs index 66ee9fe45a55..f033e779543a 100644 --- a/bin/node-template/node/src/command.rs +++ b/bin/node-template/node/src/command.rs @@ -95,7 +95,11 @@ pub fn run() -> sc_cli::Result<()> { runner.async_run(|config| { let PartialComponents { client, task_manager, backend, .. } = service::new_partial(&config)?; - Ok((cmd.run(client, backend, None), task_manager)) + let aux_revert = Box::new(move |client, _, blocks| { + sc_finality_grandpa::revert(client, blocks)?; + Ok(()) + }); + Ok((cmd.run(client, backend, Some(aux_revert)), task_manager)) }) }, Some(Subcommand::Benchmark(cmd)) => diff --git a/bin/node/cli/src/command.rs b/bin/node/cli/src/command.rs index bd324b20fb01..db243ff6f597 100644 --- a/bin/node/cli/src/command.rs +++ b/bin/node/cli/src/command.rs @@ -16,7 +16,11 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use crate::{chain_spec, service, service::new_partial, Cli, Subcommand}; +use crate::{ + chain_spec, service, + service::{new_partial, FullClient}, + Cli, Subcommand, +}; use node_executor::ExecutorDispatch; use node_primitives::Block; use node_runtime::RuntimeApi; @@ -175,13 +179,12 @@ pub fn run() -> Result<()> { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { let PartialComponents { client, task_manager, backend, .. } = new_partial(&config)?; - let revert_aux = Box::new(|client, backend, blocks| { - sc_consensus_babe::revert(client, backend, blocks)?; - // TODO: grandpa revert + let aux_revert = Box::new(move |client: Arc, backend, blocks| { + sc_consensus_babe::revert(client.clone(), backend, blocks)?; + grandpa::revert(client, blocks)?; Ok(()) }); - - Ok((cmd.run(client, backend, Some(revert_aux)), task_manager)) + Ok((cmd.run(client, backend, Some(aux_revert)), task_manager)) }) }, #[cfg(feature = "try-runtime")] diff --git a/client/consensus/babe/src/lib.rs b/client/consensus/babe/src/lib.rs index 818384a5c3d7..3d3a7f24df81 100644 --- a/client/consensus/babe/src/lib.rs +++ b/client/consensus/babe/src/lib.rs @@ -1832,7 +1832,9 @@ where Ok(BasicQueue::new(verifier, Box::new(block_import), justification_import, spawner, registry)) } -/// Reverts aux data. +/// Reverts protocol aux data to at most the last finalized block. +/// In particular, epoch-changes and block weights announced after the revert +/// point are removed. pub fn revert( client: Arc, backend: Arc, diff --git a/client/finality-grandpa/src/authorities.rs b/client/finality-grandpa/src/authorities.rs index 033a1c4bbb23..668fe5f26905 100644 --- a/client/finality-grandpa/src/authorities.rs +++ b/client/finality-grandpa/src/authorities.rs @@ -21,7 +21,7 @@ use std::{cmp::Ord, fmt::Debug, ops::Add}; use finality_grandpa::voter_set::VoterSet; -use fork_tree::ForkTree; +use fork_tree::{FilterAction, ForkTree}; use log::debug; use parity_scale_codec::{Decode, Encode}; use parking_lot::MappedMutexGuard; @@ -220,6 +220,37 @@ where pub(crate) fn current(&self) -> (u64, &[(AuthorityId, u64)]) { (self.set_id, &self.current_authorities[..]) } + + /// Revert to a specified block given its `hash` and `number`. + /// This removes all the authority set changes that were announced after + /// the revert point. + /// Revert point is identified by `number` and `hash`. + pub(crate) fn revert(&mut self, hash: H, number: N, is_descendent_of: &F) + where + F: Fn(&H, &H) -> Result, + { + let mut filter = |node_hash: &H, node_num: &N, _: &PendingChange| { + if number >= *node_num && + (is_descendent_of(node_hash, &hash).unwrap_or_default() || *node_hash == hash) + { + // Continue the search in this subtree. + FilterAction::KeepNode + } else if number < *node_num && is_descendent_of(&hash, node_hash).unwrap_or_default() { + // Found a node to be removed. + FilterAction::Remove + } else { + // Not a parent or child of the one we're looking for, stop processing this branch. + FilterAction::KeepTree + } + }; + + // Remove standard changes. + let _ = self.pending_standard_changes.drain_filter(&mut filter); + + // Remove forced changes. + self.pending_forced_changes + .retain(|change| !is_descendent_of(&hash, &change.canon_hash).unwrap_or_default()); + } } impl AuthoritySet diff --git a/client/finality-grandpa/src/lib.rs b/client/finality-grandpa/src/lib.rs index fef16286381e..34d5b6bb1f70 100644 --- a/client/finality-grandpa/src/lib.rs +++ b/client/finality-grandpa/src/lib.rs @@ -63,6 +63,7 @@ use parking_lot::RwLock; use prometheus_endpoint::{PrometheusError, Registry}; use sc_client_api::{ backend::{AuxStore, Backend}, + utils::is_descendent_of, BlockchainEvents, CallExecutor, ExecutionStrategy, ExecutorProvider, Finalizer, LockImportRun, StorageProvider, TransactionFor, }; @@ -71,7 +72,7 @@ use sc_telemetry::{telemetry, TelemetryHandle, CONSENSUS_DEBUG, CONSENSUS_INFO}; use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver}; use sp_api::ProvideRuntimeApi; use sp_application_crypto::AppKey; -use sp_blockchain::{Error as ClientError, HeaderBackend, HeaderMetadata}; +use sp_blockchain::{Error as ClientError, HeaderBackend, HeaderMetadata, Result as ClientResult}; use sp_consensus::SelectChain; use sp_core::crypto::ByteArray; use sp_keystore::{SyncCryptoStore, SyncCryptoStorePtr}; @@ -1162,3 +1163,49 @@ fn local_authority_id( .map(|(p, _)| p.clone()) }) } + +/// Reverts protocol aux data to at most the last finalized block. +/// In particular, standard and forced authority set changes announced after the +/// revert point are removed. +pub fn revert(client: Arc, blocks: NumberFor) -> ClientResult<()> +where + Block: BlockT, + Client: AuxStore + + HeaderMetadata + + HeaderBackend + + ProvideRuntimeApi, +{ + let best_number = client.info().best_number; + let finalized = client.info().finalized_number; + let revertible = blocks.min(best_number - finalized); + + let number = best_number - revertible; + let hash = client + .block_hash_from_id(&BlockId::Number(number))? + .ok_or(ClientError::Backend(format!( + "Unexpected hash lookup failure for block number: {}", + number + )))?; + + let info = client.info(); + let persistent_data: PersistentData = + aux_schema::load_persistent(&*client, info.genesis_hash, Zero::zero(), || unreachable!())?; + + let shared_authority_set = persistent_data.authority_set; + let mut authority_set = shared_authority_set.inner(); + + let is_descendent_of = is_descendent_of(&*client, None); + authority_set.revert(hash, number, &is_descendent_of); + + // The following has the side effect to properly reset the current voter state. + let (set_id, set_ref) = authority_set.current(); + let new_set = Some(NewAuthoritySet { + canon_hash: info.finalized_hash, + canon_number: info.finalized_number, + set_id, + authorities: set_ref.to_vec(), + }); + aux_schema::update_authority_set::(&authority_set, new_set.as_ref(), |values| { + client.insert_aux(values, None) + }) +} diff --git a/client/finality-grandpa/src/tests.rs b/client/finality-grandpa/src/tests.rs index 2e545b6e88eb..5083cbfc21d1 100644 --- a/client/finality-grandpa/src/tests.rs +++ b/client/finality-grandpa/src/tests.rs @@ -57,7 +57,7 @@ use tokio::runtime::{Handle, Runtime}; use authorities::AuthoritySet; use communication::grandpa_protocol_name; -use sc_block_builder::BlockBuilderProvider; +use sc_block_builder::{BlockBuilder, BlockBuilderProvider}; use sc_consensus::LongestChain; use sc_keystore::LocalKeystore; use sp_application_crypto::key_types::GRANDPA; @@ -1685,3 +1685,128 @@ fn grandpa_environment_doesnt_send_equivocation_reports_for_itself() { let equivocation_proof = sp_finality_grandpa::Equivocation::Prevote(equivocation); assert!(environment.report_equivocation(equivocation_proof).is_ok()); } + +#[test] +fn revert_prunes_authority_changes() { + sp_tracing::try_init_simple(); + let runtime = Runtime::new().unwrap(); + + let peers = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; + + type TestBlockBuilder<'a> = + BlockBuilder<'a, Block, PeersFullClient, substrate_test_runtime_client::Backend>; + let edit_block = |builder: TestBlockBuilder| { + let mut block = builder.build().unwrap().block; + add_scheduled_change( + &mut block, + ScheduledChange { next_authorities: make_ids(peers), delay: 0 }, + ); + block + }; + + let api = TestApi::new(make_ids(peers)); + let mut net = GrandpaTestNet::new(api, 3, 0); + runtime.spawn(initialize_grandpa(&mut net, peers)); + + let peer = net.peer(0); + let client = peer.client().as_client(); + + // Test scenario: (X) = auth-change, 24 = revert-point + // + // +---------(27) + // / + // 0---(21)---23---24---25---(28)---30 + // ^ \ + // revert-point +------(29) + + // Construct canonical chain + + // add 20 blocks + peer.push_blocks(20, false); + // at block 21 we add an authority transition + peer.generate_blocks(1, BlockOrigin::File, edit_block); + // add more blocks on top of it (until we have 24) + peer.push_blocks(3, false); + // add more blocks on top of it (until we have 27) + peer.push_blocks(3, false); + // at block 28 we add an authority transition + peer.generate_blocks(1, BlockOrigin::File, edit_block); + // add more blocks on top of it (until we have 30) + peer.push_blocks(2, false); + + // Fork before revert point + + // add more blocks on top of block 23 (until we have 26) + let hash = peer.generate_blocks_at( + BlockId::Number(23), + 3, + BlockOrigin::File, + |builder| { + let mut block = builder.build().unwrap().block; + block.header.digest_mut().push(DigestItem::Other(vec![1])); + block + }, + false, + false, + true, + ForkChoiceStrategy::LongestChain, + ); + // at block 27 of the fork add an authority transition + peer.generate_blocks_at( + BlockId::Hash(hash), + 1, + BlockOrigin::File, + edit_block, + false, + false, + true, + ForkChoiceStrategy::LongestChain, + ); + + // Fork after revert point + + // add more block on top of block 25 (until we have 28) + let hash = peer.generate_blocks_at( + BlockId::Number(25), + 3, + BlockOrigin::File, + |builder| { + let mut block = builder.build().unwrap().block; + block.header.digest_mut().push(DigestItem::Other(vec![2])); + block + }, + false, + false, + true, + ForkChoiceStrategy::LongestChain, + ); + // at block 29 of the fork add an authority transition + peer.generate_blocks_at( + BlockId::Hash(hash), + 1, + BlockOrigin::File, + edit_block, + false, + false, + true, + ForkChoiceStrategy::LongestChain, + ); + + revert(client.clone(), 6).unwrap(); + + let persistent_data: PersistentData = aux_schema::load_persistent( + &*client, + client.info().genesis_hash, + Zero::zero(), + || unreachable!(), + ) + .unwrap(); + let changes_num: Vec<_> = persistent_data + .authority_set + .inner() + .pending_standard_changes + .iter() + .map(|(_, n, _)| *n) + .collect(); + assert_eq!(changes_num, [21, 27]); +} diff --git a/client/network/test/src/lib.rs b/client/network/test/src/lib.rs index 3986ac47f361..552879f35d93 100644 --- a/client/network/test/src/lib.rs +++ b/client/network/test/src/lib.rs @@ -334,7 +334,7 @@ where /// Add blocks to the peer -- edit the block before adding. The chain will /// start at the given block iD. - fn generate_blocks_at( + pub fn generate_blocks_at( &mut self, at: BlockId, count: usize, From c89d524dea7bfb474f2e036ebc486fca9c81533f Mon Sep 17 00:00:00 2001 From: Alexander Samusev <41779041+alvicsam@users.noreply.github.com> Date: Wed, 6 Apr 2022 18:20:15 +0200 Subject: [PATCH 681/695] [ci] Remove vault (#11179) * [ci] Remove vault * remove anchors --- .gitlab-ci.yml | 47 ----------------------------------------------- 1 file changed, 47 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b6f9ff948606..d196ade85a6f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -39,9 +39,6 @@ variables: &default-vars DOCKER_OS: "debian:stretch" ARCH: "x86_64" CI_IMAGE: "paritytech/ci-linux:production" - VAULT_SERVER_URL: "https://vault.parity-mgmt-vault.parity.io" - VAULT_AUTH_PATH: "gitlab-parity-io-jwt" - VAULT_AUTH_ROLE: "cicd_gitlab_parity_${CI_PROJECT_NAME}" default: cache: {} @@ -188,46 +185,6 @@ default: - cp -r ./scripts/ci/docker/substrate.Dockerfile ./artifacts/substrate/ - sccache -s -#### Vault secrets -.vault-secrets: &vault-secrets - secrets: - DOCKER_HUB_USER: - vault: cicd/gitlab/parity/DOCKER_HUB_USER@kv - file: false - DOCKER_HUB_PASS: - vault: cicd/gitlab/parity/DOCKER_HUB_PASS@kv - file: false - GITHUB_PR_TOKEN: - vault: cicd/gitlab/parity/GITHUB_PR_TOKEN@kv - file: false - GITHUB_TOKEN: - vault: cicd/gitlab/parity/GITHUB_TOKEN@kv - file: false - AWS_ACCESS_KEY_ID: - vault: cicd/gitlab/$CI_PROJECT_PATH/AWS_ACCESS_KEY_ID@kv - file: false - AWS_SECRET_ACCESS_KEY: - vault: cicd/gitlab/$CI_PROJECT_PATH/AWS_SECRET_ACCESS_KEY@kv - file: false - GITHUB_EMAIL: - vault: cicd/gitlab/$CI_PROJECT_PATH/GITHUB_EMAIL@kv - file: false - GITHUB_RELEASE_TOKEN: - vault: cicd/gitlab/$CI_PROJECT_PATH/GITHUB_RELEASE_TOKEN@kv - file: false - GITHUB_SSH_PRIV_KEY: - vault: cicd/gitlab/$CI_PROJECT_PATH/GITHUB_SSH_PRIV_KEY@kv - file: false - GITHUB_USER: - vault: cicd/gitlab/$CI_PROJECT_PATH/GITHUB_USER@kv - file: false - MATRIX_ACCESS_TOKEN: - vault: cicd/gitlab/$CI_PROJECT_PATH/MATRIX_ACCESS_TOKEN@kv - file: false - MATRIX_ROOM_ID: - vault: cicd/gitlab/$CI_PROJECT_PATH/MATRIX_ROOM_ID@kv - file: false - #### stage: .pre @@ -638,7 +595,6 @@ build-rustdoc: .build-push-docker-image: &build-push-docker-image <<: *build-refs <<: *kubernetes-env - <<: *vault-secrets image: quay.io/buildah/stable variables: &docker-build-vars <<: *default-vars @@ -697,7 +653,6 @@ publish-s3-release: stage: publish <<: *build-refs <<: *kubernetes-env - <<: *vault-secrets needs: - job: build-linux-substrate artifacts: true @@ -719,7 +674,6 @@ publish-s3-release: publish-rustdoc: stage: publish <<: *kubernetes-env - <<: *vault-secrets image: node:16 variables: GIT_DEPTH: 100 @@ -778,7 +732,6 @@ publish-rustdoc: publish-draft-release: stage: publish - <<: *vault-secrets image: paritytech/tools:latest rules: - if: $CI_COMMIT_REF_NAME =~ /^ci-release-.*$/ From 1dd1f2125c2936b006c85699433c3942c80d09fd Mon Sep 17 00:00:00 2001 From: Niklas Adolfsson Date: Thu, 7 Apr 2022 08:47:36 +0200 Subject: [PATCH 682/695] chore: update jsonrpsee to `v0.10.1` (#11173) * fix(bin/node): remove unsed dep jsonrpsee * chore(remote ext): update jsonrpsee v0.10.1 * chore(try runtime): update jsonrpsee v0.10.1 * Update utils/frame/try-runtime/cli/src/commands/follow_chain.rs * cargo fmt --- Cargo.lock | 125 +++++------------- bin/node/cli/Cargo.toml | 1 - client/informant/src/display.rs | 2 +- client/network/src/config.rs | 2 +- client/network/src/lib.rs | 4 +- client/peerset/src/lib.rs | 4 +- client/peerset/src/peersstate.rs | 8 +- utils/frame/remote-externalities/Cargo.toml | 2 +- utils/frame/try-runtime/cli/Cargo.toml | 2 +- .../cli/src/commands/follow_chain.rs | 12 +- 10 files changed, 54 insertions(+), 108 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bd6db8027211..0a1a1e0b17be 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2803,7 +2803,7 @@ dependencies = [ "indexmap", "slab", "tokio", - "tokio-util", + "tokio-util 0.6.7", "tracing", ] @@ -3404,7 +3404,7 @@ dependencies = [ "log 0.4.14", "tokio", "tokio-stream", - "tokio-util", + "tokio-util 0.6.7", "unicase 2.6.0", ] @@ -3425,53 +3425,42 @@ dependencies = [ [[package]] name = "jsonrpsee" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6373a33d987866ccfe1af4bc11b089dce941764313f9fd8b7cf13fcb51b72dc5" -dependencies = [ - "jsonrpsee-types 0.4.1", - "jsonrpsee-utils", - "jsonrpsee-ws-client 0.4.1", -] - -[[package]] -name = "jsonrpsee" -version = "0.8.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05fd8cd6c6b1bbd06881d2cf88f1fc83cc36c98f2219090f839115fb4a956cb9" +checksum = "91dc760c341fa81173f9a434931aaf32baad5552b0230cc6c93e8fb7eaad4c19" dependencies = [ "jsonrpsee-core", "jsonrpsee-proc-macros", - "jsonrpsee-types 0.8.0", - "jsonrpsee-ws-client 0.8.0", + "jsonrpsee-types", + "jsonrpsee-ws-client", ] [[package]] name = "jsonrpsee-client-transport" -version = "0.8.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3303cdf246e6ab76e2866fb3d9acb6c76a068b1b28bd923a1b7a8122257ad7b5" +checksum = "765f7a36d5087f74e3b3b47805c2188fef8eb54afcb587b078d9f8ebfe9c7220" dependencies = [ "futures 0.3.21", "http", "jsonrpsee-core", - "jsonrpsee-types 0.8.0", + "jsonrpsee-types", "pin-project 1.0.10", "rustls-native-certs 0.6.1", "soketto 0.7.1", "thiserror", "tokio", "tokio-rustls 0.23.2", - "tokio-util", + "tokio-util 0.7.1", "tracing", "webpki-roots 0.22.2", ] [[package]] name = "jsonrpsee-core" -version = "0.8.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f220b5a238dc7992b90f1144fbf6eaa585872c9376afe6fe6863ffead6191bf3" +checksum = "82ef77ecd20c2254d54f5da8c0738eacca61e6b6511268a8f2753e3148c6c706" dependencies = [ "anyhow", "arrayvec 0.7.1", @@ -3480,7 +3469,7 @@ dependencies = [ "futures-channel", "futures-util", "hyper 0.14.16", - "jsonrpsee-types 0.8.0", + "jsonrpsee-types", "rustc-hash", "serde", "serde_json", @@ -3492,9 +3481,9 @@ dependencies = [ [[package]] name = "jsonrpsee-proc-macros" -version = "0.8.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4299ebf790ea9de1cb72e73ff2ae44c723ef264299e5e2d5ef46a371eb3ac3d8" +checksum = "b7291c72805bc7d413b457e50d8ef3e87aa554da65ecbbc278abb7dfc283e7f0" dependencies = [ "proc-macro-crate 1.1.3", "proc-macro2", @@ -3504,28 +3493,9 @@ dependencies = [ [[package]] name = "jsonrpsee-types" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f778cf245158fbd8f5d50823a2e9e4c708a40be164766bd35e9fb1d86715b2" -dependencies = [ - "anyhow", - "async-trait", - "beef", - "futures-channel", - "futures-util", - "hyper 0.14.16", - "log 0.4.14", - "serde", - "serde_json", - "soketto 0.7.1", - "thiserror", -] - -[[package]] -name = "jsonrpsee-types" -version = "0.8.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1b3f601bbbe45cd63f5407b6f7d7950e08a7d4f82aa699ff41a4a5e9e54df58" +checksum = "38b6aa52f322cbf20c762407629b8300f39bcc0cf0619840d9252a2f65fd2dd9" dependencies = [ "anyhow", "beef", @@ -3535,50 +3505,15 @@ dependencies = [ "tracing", ] -[[package]] -name = "jsonrpsee-utils" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0109c4f972058f3b1925b73a17210aff7b63b65967264d0045d15ee88fe84f0c" -dependencies = [ - "arrayvec 0.7.1", - "beef", - "jsonrpsee-types 0.4.1", -] - -[[package]] -name = "jsonrpsee-ws-client" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "559aa56fc402af206c00fc913dc2be1d9d788dcde045d14df141a535245d35ef" -dependencies = [ - "arrayvec 0.7.1", - "async-trait", - "fnv", - "futures 0.3.21", - "http", - "jsonrpsee-types 0.4.1", - "log 0.4.14", - "pin-project 1.0.10", - "rustls-native-certs 0.5.0", - "serde", - "serde_json", - "soketto 0.7.1", - "thiserror", - "tokio", - "tokio-rustls 0.22.0", - "tokio-util", -] - [[package]] name = "jsonrpsee-ws-client" -version = "0.8.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aff425cee7c779e33920913bc695447416078ee6d119f443f3060feffa4e86b5" +checksum = "dd66d18bab78d956df24dd0d2e41e4c00afbb818fda94a98264bdd12ce8506ac" dependencies = [ "jsonrpsee-client-transport", "jsonrpsee-core", - "jsonrpsee-types 0.8.0", + "jsonrpsee-types", ] [[package]] @@ -4891,7 +4826,6 @@ dependencies = [ "frame-system-rpc-runtime-api", "futures 0.3.21", "hex-literal", - "jsonrpsee-ws-client 0.4.1", "log 0.4.14", "nix", "node-executor", @@ -7863,7 +7797,7 @@ version = "0.10.0-dev" dependencies = [ "env_logger 0.9.0", "frame-support", - "jsonrpsee 0.8.0", + "jsonrpsee", "log 0.4.14", "pallet-elections-phragmen", "parity-scale-codec", @@ -11317,13 +11251,26 @@ checksum = "1caa0b0c8d94a049db56b5acf8cba99dc0623aab1b26d5b5f5e2d945846b3592" dependencies = [ "bytes 1.1.0", "futures-core", - "futures-io", "futures-sink", "log 0.4.14", "pin-project-lite 0.2.6", "tokio", ] +[[package]] +name = "tokio-util" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0edfdeb067411dba2044da6d1cb2df793dd35add7888d73c16e3381ded401764" +dependencies = [ + "bytes 1.1.0", + "futures-core", + "futures-io", + "futures-sink", + "pin-project-lite 0.2.6", + "tokio", +] + [[package]] name = "toml" version = "0.5.8" @@ -11540,7 +11487,7 @@ name = "try-runtime-cli" version = "0.10.0-dev" dependencies = [ "clap 3.1.6", - "jsonrpsee 0.4.1", + "jsonrpsee", "log 0.4.14", "parity-scale-codec", "remote-externalities", diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index d25c1b1f0bf8..4eb5983b6488 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -127,7 +127,6 @@ async-std = { version = "1.10.0", features = ["attributes"] } soketto = "0.4.2" criterion = { version = "0.3.5", features = ["async_tokio"] } tokio = { version = "1.17.0", features = ["macros", "time", "parking_lot"] } -jsonrpsee-ws-client = "0.4.1" wait-timeout = "0.2" remote-externalities = { path = "../../../utils/frame/remote-externalities" } pallet-timestamp = { version = "4.0.0-dev", path = "../../../frame/timestamp" } diff --git a/client/informant/src/display.rs b/client/informant/src/display.rs index 77b28dec5565..446ddf47b4ca 100644 --- a/client/informant/src/display.rs +++ b/client/informant/src/display.rs @@ -30,7 +30,7 @@ use std::{fmt, time::Instant}; /// like: /// /// > Syncing 5.4 bps, target=#531028 (4 peers), best: #90683 (0x4ca8…51b8), -/// > finalized #360 (0x6f24…a38b), ⬇ 5.5kiB/s ⬆ 0.9kiB/s +/// > finalized #360 (0x6f24…a38b), ⬇ 5.5kiB/s ⬆ 0.9kiB/s /// /// # Usage /// diff --git a/client/network/src/config.rs b/client/network/src/config.rs index 7c2dfef7fe89..40aefe9a3ec2 100644 --- a/client/network/src/config.rs +++ b/client/network/src/config.rs @@ -579,7 +579,7 @@ pub struct NonDefaultSetConfig { /// considered established once this protocol is open. /// /// > **Note**: This field isn't present for the default set, as this is handled internally - /// > by the networking code. + /// > by the networking code. pub notifications_protocol: Cow<'static, str>, /// If the remote reports that it doesn't support the protocol indicated in the /// `notifications_protocol` field, then each of these fallback names will be tried one by diff --git a/client/network/src/lib.rs b/client/network/src/lib.rs index 27e9a7547b44..d9f5b3de1bb1 100644 --- a/client/network/src/lib.rs +++ b/client/network/src/lib.rs @@ -103,8 +103,8 @@ //! protocol ID. //! //! > **Note**: It is possible for the same connection to be used for multiple chains. For example, -//! > one can use both the `/dot/sync/2` and `/sub/sync/2` protocols on the same -//! > connection, provided that the remote supports them. +//! > one can use both the `/dot/sync/2` and `/sub/sync/2` protocols on the same +//! > connection, provided that the remote supports them. //! //! Substrate uses the following standard libp2p protocols: //! diff --git a/client/peerset/src/lib.rs b/client/peerset/src/lib.rs index c777cfec19d2..859319fab132 100644 --- a/client/peerset/src/lib.rs +++ b/client/peerset/src/lib.rs @@ -129,7 +129,7 @@ impl PeersetHandle { /// Has no effect if the node was already a reserved peer. /// /// > **Note**: Keep in mind that the networking has to know an address for this node, - /// > otherwise it will not be able to connect to it. + /// > otherwise it will not be able to connect to it. pub fn add_reserved_peer(&self, set_id: SetId, peer_id: PeerId) { let _ = self.tx.unbounded_send(Action::AddReservedPeer(set_id, peer_id)); } @@ -232,7 +232,7 @@ pub struct SetConfig { /// List of bootstrap nodes to initialize the set with. /// /// > **Note**: Keep in mind that the networking has to know an address for these nodes, - /// > otherwise it will not be able to connect to them. + /// > otherwise it will not be able to connect to them. pub bootnodes: Vec, /// Lists of nodes we should always be connected to. diff --git a/client/peerset/src/peersstate.rs b/client/peerset/src/peersstate.rs index 272b903c1da2..ca22cac32408 100644 --- a/client/peerset/src/peersstate.rs +++ b/client/peerset/src/peersstate.rs @@ -25,8 +25,8 @@ //! slots. //! //! > Note: This module is purely dedicated to managing slots and reputations. Features such as -//! > for example connecting to some nodes in priority should be added outside of this -//! > module, rather than inside. +//! > for example connecting to some nodes in priority should be added outside of this +//! > module, rather than inside. use libp2p::PeerId; use log::error; @@ -50,8 +50,8 @@ pub struct PeersState { /// List of nodes that we know about. /// /// > **Note**: This list should really be ordered by decreasing reputation, so that we can - /// easily select the best node to connect to. As a first draft, however, we don't - /// sort, to make the logic easier. + /// > easily select the best node to connect to. As a first draft, however, we don't sort, to + /// > make the logic easier. nodes: HashMap, /// Configuration of each set. The size of this `Vec` is never modified. diff --git a/utils/frame/remote-externalities/Cargo.toml b/utils/frame/remote-externalities/Cargo.toml index fc44c63b8acd..343dda689275 100644 --- a/utils/frame/remote-externalities/Cargo.toml +++ b/utils/frame/remote-externalities/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -jsonrpsee = { version = "0.8", features = ["ws-client", "macros"] } +jsonrpsee = { version = "0.10.1", features = ["ws-client", "macros"] } env_logger = "0.9" frame-support = { path = "../../../frame/support", optional = true, version = "4.0.0-dev" } diff --git a/utils/frame/try-runtime/cli/Cargo.toml b/utils/frame/try-runtime/cli/Cargo.toml index 6f72bd3b9d7f..3f0ee257d975 100644 --- a/utils/frame/try-runtime/cli/Cargo.toml +++ b/utils/frame/try-runtime/cli/Cargo.toml @@ -32,4 +32,4 @@ sp-externalities = { version = "0.12.0", path = "../../../../primitives/external sp-version = { version = "5.0.0", path = "../../../../primitives/version" } remote-externalities = { version = "0.10.0-dev", path = "../../remote-externalities" } -jsonrpsee = { version = "0.4.1", default-features = false, features = ["ws-client"] } +jsonrpsee = { version = "0.10.1", default-features = false, features = ["ws-client"] } diff --git a/utils/frame/try-runtime/cli/src/commands/follow_chain.rs b/utils/frame/try-runtime/cli/src/commands/follow_chain.rs index 7400813b9175..db305fa59076 100644 --- a/utils/frame/try-runtime/cli/src/commands/follow_chain.rs +++ b/utils/frame/try-runtime/cli/src/commands/follow_chain.rs @@ -20,7 +20,7 @@ use crate::{ state_machine_call_with_proof, SharedParams, LOG_TARGET, }; use jsonrpsee::{ - types::{traits::SubscriptionClient, Subscription}, + core::client::{Subscription, SubscriptionClientT}, ws_client::WsClientBuilder, }; use parity_scale_codec::Decode; @@ -76,13 +76,13 @@ where loop { let header = match subscription.next().await { - Ok(Some(header)) => header, - Ok(None) => { - log::warn!("subscription returned `None`. Probably decoding has failed."); + Some(Ok(header)) => header, + None => { + log::warn!("subscription closed"); break }, - Err(why) => { - log::warn!("subscription returned error: {:?}.", why); + Some(Err(why)) => { + log::warn!("subscription returned error: {:?}. Probably decoding has failed.", why); continue }, }; From e6ae0b0b8ae8ff7ea8020348bc671e1cfb1f3eff Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Thu, 7 Apr 2022 09:46:51 +0200 Subject: [PATCH 683/695] relax input conditions of fixed::checked_from_integer (#11159) * relax input conditions of fixed::checked_from_integer * Fix build --- frame/transaction-payment/src/lib.rs | 2 +- primitives/arithmetic/src/fixed_point.rs | 16 +++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/frame/transaction-payment/src/lib.rs b/frame/transaction-payment/src/lib.rs index 37fecf20cc52..12edb6f2c390 100644 --- a/frame/transaction-payment/src/lib.rs +++ b/frame/transaction-payment/src/lib.rs @@ -348,7 +348,7 @@ pub mod pallet { // loss. assert!( ::max_value() >= - Multiplier::checked_from_integer( + Multiplier::checked_from_integer::( T::BlockWeights::get().max_block.try_into().unwrap() ) .unwrap(), diff --git a/primitives/arithmetic/src/fixed_point.rs b/primitives/arithmetic/src/fixed_point.rs index 3ecfb60ee0f5..7ce17bb72611 100644 --- a/primitives/arithmetic/src/fixed_point.rs +++ b/primitives/arithmetic/src/fixed_point.rs @@ -121,7 +121,8 @@ pub trait FixedPointNumber: /// Creates `self` from an integer number `int`. /// /// Returns `None` if `int` exceeds accuracy. - fn checked_from_integer(int: Self::Inner) -> Option { + fn checked_from_integer>(int: N) -> Option { + let int: Self::Inner = int.into(); int.checked_mul(&Self::DIV).map(Self::from_inner) } @@ -898,31 +899,32 @@ macro_rules! implement_fixed { let accuracy = $name::accuracy(); // Case where integer fits. - let a = $name::checked_from_integer(42).expect("42 * accuracy <= inner_max; qed"); + let a = $name::checked_from_integer::<$inner_type>(42) + .expect("42 * accuracy <= inner_max; qed"); assert_eq!(a.into_inner(), 42 * accuracy); // Max integer that fit. - let a = $name::checked_from_integer(inner_max / accuracy) + let a = $name::checked_from_integer::<$inner_type>(inner_max / accuracy) .expect("(inner_max / accuracy) * accuracy <= inner_max; qed"); assert_eq!(a.into_inner(), (inner_max / accuracy) * accuracy); // Case where integer doesn't fit, so it returns `None`. - let a = $name::checked_from_integer(inner_max / accuracy + 1); + let a = $name::checked_from_integer::<$inner_type>(inner_max / accuracy + 1); assert_eq!(a, None); if $name::SIGNED { // Case where integer fits. - let a = $name::checked_from_integer(0.saturating_sub(42)) + let a = $name::checked_from_integer::<$inner_type>(0.saturating_sub(42)) .expect("-42 * accuracy >= inner_min; qed"); assert_eq!(a.into_inner(), 0 - 42 * accuracy); // Min integer that fit. - let a = $name::checked_from_integer(inner_min / accuracy) + let a = $name::checked_from_integer::<$inner_type>(inner_min / accuracy) .expect("(inner_min / accuracy) * accuracy <= inner_min; qed"); assert_eq!(a.into_inner(), (inner_min / accuracy) * accuracy); // Case where integer doesn't fit, so it returns `None`. - let a = $name::checked_from_integer(inner_min / accuracy - 1); + let a = $name::checked_from_integer::<$inner_type>(inner_min / accuracy - 1); assert_eq!(a, None); } } From a1497f5942a04bd1a4e7c5a5b276ad2d1f863557 Mon Sep 17 00:00:00 2001 From: Stephen Shelton Date: Thu, 7 Apr 2022 11:24:59 +0000 Subject: [PATCH 684/695] Apply `WeightToFeePolynomial`s to `pallet_transaction_payment`'s length fee (#10785) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Apply WeightToFeePolynomials to length fee * Remove TransactionByteFee * Add test cases for ConstantModifierFee * Restore import * Use pallet::constant_name * Remove irrelevant TODO comment * Update frame/support/src/weights.rs * Update frame/transaction-payment/src/lib.rs * Update frame/transaction-payment/src/lib.rs * Update frame/transaction-payment/src/lib.rs Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> * s/ConstantModifierFee/ConstantMultiplier/ * Impl LengthToFee for test configs * fmt * Remove unused import * Impl WeightToFeePolynomial for byte fee in ExtBuilder * Remove unused import * fix doc Co-authored-by: Bastian Köcher Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Co-authored-by: Shawn Tabrizi --- bin/node-template/runtime/src/lib.rs | 6 +-- bin/node/runtime/src/lib.rs | 4 +- frame/balances/src/tests_composite.rs | 2 +- frame/balances/src/tests_local.rs | 2 +- frame/balances/src/tests_reentrancy.rs | 2 +- frame/executive/src/lib.rs | 6 ++- frame/support/src/weights.rs | 42 +++++++++++++++- .../asset-tx-payment/src/tests.rs | 2 +- frame/transaction-payment/src/lib.rs | 49 ++++++++++++------- frame/transaction-payment/src/payment.rs | 3 +- 10 files changed, 85 insertions(+), 33 deletions(-) diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index 93cf234fa52b..40adbb038811 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -249,15 +249,11 @@ impl pallet_balances::Config for Runtime { type WeightInfo = pallet_balances::weights::SubstrateWeight; } -parameter_types! { - pub const TransactionByteFee: Balance = 1; -} - impl pallet_transaction_payment::Config for Runtime { type OnChargeTransaction = CurrencyAdapter; - type TransactionByteFee = TransactionByteFee; type OperationalFeeMultiplier = ConstU8<5>; type WeightToFee = IdentityFee; + type LengthToFee = IdentityFee; type FeeMultiplierUpdate = (); } diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 565f151ce2a0..57584bed39b2 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -35,7 +35,7 @@ use frame_support::{ }, weights::{ constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND}, - DispatchClass, IdentityFee, Weight, + ConstantMultiplier, DispatchClass, IdentityFee, Weight, }, PalletId, RuntimeDebug, }; @@ -444,9 +444,9 @@ parameter_types! { impl pallet_transaction_payment::Config for Runtime { type OnChargeTransaction = CurrencyAdapter; - type TransactionByteFee = TransactionByteFee; type OperationalFeeMultiplier = OperationalFeeMultiplier; type WeightToFee = IdentityFee; + type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = TargetedFeeAdjustment; } diff --git a/frame/balances/src/tests_composite.rs b/frame/balances/src/tests_composite.rs index a24be4492737..4a2cc1d91936 100644 --- a/frame/balances/src/tests_composite.rs +++ b/frame/balances/src/tests_composite.rs @@ -78,9 +78,9 @@ impl frame_system::Config for Test { impl pallet_transaction_payment::Config for Test { type OnChargeTransaction = CurrencyAdapter, ()>; - type TransactionByteFee = ConstU64<1>; type OperationalFeeMultiplier = ConstU8<5>; type WeightToFee = IdentityFee; + type LengthToFee = IdentityFee; type FeeMultiplierUpdate = (); } diff --git a/frame/balances/src/tests_local.rs b/frame/balances/src/tests_local.rs index ae56f3b1f0f2..cfc7f84ab3a3 100644 --- a/frame/balances/src/tests_local.rs +++ b/frame/balances/src/tests_local.rs @@ -79,9 +79,9 @@ impl frame_system::Config for Test { impl pallet_transaction_payment::Config for Test { type OnChargeTransaction = CurrencyAdapter, ()>; - type TransactionByteFee = ConstU64<1>; type OperationalFeeMultiplier = ConstU8<5>; type WeightToFee = IdentityFee; + type LengthToFee = IdentityFee; type FeeMultiplierUpdate = (); } diff --git a/frame/balances/src/tests_reentrancy.rs b/frame/balances/src/tests_reentrancy.rs index 4303efc2322c..7037e9615afd 100644 --- a/frame/balances/src/tests_reentrancy.rs +++ b/frame/balances/src/tests_reentrancy.rs @@ -85,9 +85,9 @@ impl frame_system::Config for Test { impl pallet_transaction_payment::Config for Test { type OnChargeTransaction = CurrencyAdapter, ()>; - type TransactionByteFee = ConstU64<1>; type OperationalFeeMultiplier = ConstU8<5>; type WeightToFee = IdentityFee; + type LengthToFee = IdentityFee; type FeeMultiplierUpdate = (); } diff --git a/frame/executive/src/lib.rs b/frame/executive/src/lib.rs index d19ea8127bad..de1cc3b91640 100644 --- a/frame/executive/src/lib.rs +++ b/frame/executive/src/lib.rs @@ -576,7 +576,9 @@ mod tests { ConstU32, ConstU64, ConstU8, Currency, LockIdentifier, LockableCurrency, WithdrawReasons, }, - weights::{IdentityFee, RuntimeDbWeight, Weight, WeightToFeePolynomial}, + weights::{ + ConstantMultiplier, IdentityFee, RuntimeDbWeight, Weight, WeightToFeePolynomial, + }, }; use frame_system::{Call as SystemCall, ChainContext, LastRuntimeUpgradeInfo}; use pallet_balances::Call as BalancesCall; @@ -787,9 +789,9 @@ mod tests { } impl pallet_transaction_payment::Config for Runtime { type OnChargeTransaction = CurrencyAdapter; - type TransactionByteFee = TransactionByteFee; type OperationalFeeMultiplier = ConstU8<5>; type WeightToFee = IdentityFee; + type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = (); } impl custom::Config for Runtime {} diff --git a/frame/support/src/weights.rs b/frame/support/src/weights.rs index b3ed42bb45fc..4c3fcaa0fd42 100644 --- a/frame/support/src/weights.rs +++ b/frame/support/src/weights.rs @@ -132,7 +132,10 @@ mod extrinsic_weights; mod paritydb_weights; mod rocksdb_weights; -use crate::dispatch::{DispatchError, DispatchErrorWithPostInfo, DispatchResultWithPostInfo}; +use crate::{ + dispatch::{DispatchError, DispatchErrorWithPostInfo, DispatchResultWithPostInfo}, + traits::Get, +}; use codec::{Decode, Encode}; use scale_info::TypeInfo; #[cfg(feature = "std")] @@ -709,6 +712,34 @@ where } } +/// Implementor of [`WeightToFeePolynomial`] that uses a constant multiplier. +/// # Example +/// +/// ``` +/// # use frame_support::traits::ConstU128; +/// # use frame_support::weights::ConstantMultiplier; +/// // Results in a multiplier of 10 for each unit of weight (or length) +/// type LengthToFee = ConstantMultiplier::>; +/// ``` +pub struct ConstantMultiplier(sp_std::marker::PhantomData<(T, M)>); + +impl WeightToFeePolynomial for ConstantMultiplier +where + T: BaseArithmetic + From + Copy + Unsigned, + M: Get, +{ + type Balance = T; + + fn polynomial() -> WeightToFeeCoefficients { + smallvec!(WeightToFeeCoefficient { + coeff_integer: M::get(), + coeff_frac: Perbill::zero(), + negative: false, + degree: 1, + }) + } +} + /// A struct holding value for each `DispatchClass`. #[derive(Clone, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode, TypeInfo)] pub struct PerDispatchClass { @@ -983,4 +1014,13 @@ mod tests { assert_eq!(IdentityFee::::calc(&50), 50); assert_eq!(IdentityFee::::calc(&Weight::max_value()), Balance::max_value()); } + + #[test] + fn constant_fee_works() { + use crate::traits::ConstU128; + assert_eq!(ConstantMultiplier::>::calc(&0), 0); + assert_eq!(ConstantMultiplier::>::calc(&50), 500); + assert_eq!(ConstantMultiplier::>::calc(&16), 16384); + assert_eq!(ConstantMultiplier::>::calc(&2), u128::MAX); + } } diff --git a/frame/transaction-payment/asset-tx-payment/src/tests.rs b/frame/transaction-payment/asset-tx-payment/src/tests.rs index f2a1ad140657..d72a288ac7a3 100644 --- a/frame/transaction-payment/asset-tx-payment/src/tests.rs +++ b/frame/transaction-payment/asset-tx-payment/src/tests.rs @@ -145,8 +145,8 @@ impl WeightToFeePolynomial for WeightToFee { impl pallet_transaction_payment::Config for Runtime { type OnChargeTransaction = CurrencyAdapter; - type TransactionByteFee = TransactionByteFee; type WeightToFee = WeightToFee; + type LengthToFee = WeightToFee; type FeeMultiplierUpdate = (); type OperationalFeeMultiplier = ConstU8<5>; } diff --git a/frame/transaction-payment/src/lib.rs b/frame/transaction-payment/src/lib.rs index 12edb6f2c390..1462faaa0706 100644 --- a/frame/transaction-payment/src/lib.rs +++ b/frame/transaction-payment/src/lib.rs @@ -260,10 +260,6 @@ pub mod pallet { /// might be refunded. In the end the fees can be deposited. type OnChargeTransaction: OnChargeTransaction; - /// The fee to be paid for making a transaction; the per-byte portion. - #[pallet::constant] - type TransactionByteFee: Get>; - /// A fee mulitplier for `Operational` extrinsics to compute "virtual tip" to boost their /// `priority` /// @@ -291,6 +287,9 @@ pub mod pallet { /// Convert a weight value into a deductible fee based on the currency type. type WeightToFee: WeightToFeePolynomial>; + /// Convert a length value into a deductible fee based on the currency type. + type LengthToFee: WeightToFeePolynomial>; + /// Update the multiplier of the next block, based on the previous block's weight. type FeeMultiplierUpdate: MultiplierUpdate; } @@ -302,6 +301,12 @@ pub mod pallet { fn weight_to_fee_polynomial() -> Vec>> { T::WeightToFee::polynomial().to_vec() } + + /// The polynomial that is applied in order to derive fee from length. + #[pallet::constant_name(LengthToFee)] + fn length_to_fee_polynomial() -> Vec>> { + T::LengthToFee::polynomial().to_vec() + } } #[pallet::type_value] @@ -510,25 +515,18 @@ where class: DispatchClass, ) -> FeeDetails> { if pays_fee == Pays::Yes { - let len = >::from(len); - let per_byte = T::TransactionByteFee::get(); - - // length fee. this is not adjusted. - let fixed_len_fee = per_byte.saturating_mul(len); - // the adjustable part of the fee. let unadjusted_weight_fee = Self::weight_to_fee(weight); let multiplier = Self::next_fee_multiplier(); // final adjusted weight fee. let adjusted_weight_fee = multiplier.saturating_mul_int(unadjusted_weight_fee); + // length fee. this is adjusted via `LengthToFee`. + let len_fee = Self::length_to_fee(len); + let base_fee = Self::weight_to_fee(T::BlockWeights::get().get(class).base_extrinsic); FeeDetails { - inclusion_fee: Some(InclusionFee { - base_fee, - len_fee: fixed_len_fee, - adjusted_weight_fee, - }), + inclusion_fee: Some(InclusionFee { base_fee, len_fee, adjusted_weight_fee }), tip, } } else { @@ -536,6 +534,10 @@ where } } + fn length_to_fee(length: u32) -> BalanceOf { + T::LengthToFee::calc(&(length as Weight)) + } + fn weight_to_fee(weight: Weight) -> BalanceOf { // cap the weight to the maximum defined in runtime, otherwise it will be the // `Bounded` maximum of its data type, which is not desired. @@ -835,8 +837,8 @@ mod tests { } parameter_types! { - pub static TransactionByteFee: u64 = 1; pub static WeightToFee: u64 = 1; + pub static TransactionByteFee: u64 = 1; pub static OperationalFeeMultiplier: u8 = 5; } @@ -892,6 +894,19 @@ mod tests { } } + impl WeightToFeePolynomial for TransactionByteFee { + type Balance = u64; + + fn polynomial() -> WeightToFeeCoefficients { + smallvec![WeightToFeeCoefficient { + degree: 1, + coeff_frac: Perbill::zero(), + coeff_integer: TRANSACTION_BYTE_FEE.with(|v| *v.borrow()), + negative: false, + }] + } + } + thread_local! { static TIP_UNBALANCED_AMOUNT: RefCell = RefCell::new(0); static FEE_UNBALANCED_AMOUNT: RefCell = RefCell::new(0); @@ -913,9 +928,9 @@ mod tests { impl Config for Runtime { type OnChargeTransaction = CurrencyAdapter; - type TransactionByteFee = TransactionByteFee; type OperationalFeeMultiplier = OperationalFeeMultiplier; type WeightToFee = WeightToFee; + type LengthToFee = TransactionByteFee; type FeeMultiplierUpdate = (); } diff --git a/frame/transaction-payment/src/payment.rs b/frame/transaction-payment/src/payment.rs index 58e6ef63109a..5b4a61310279 100644 --- a/frame/transaction-payment/src/payment.rs +++ b/frame/transaction-payment/src/payment.rs @@ -12,7 +12,7 @@ use sp_runtime::{ use sp_std::{fmt::Debug, marker::PhantomData}; use frame_support::{ - traits::{Currency, ExistenceRequirement, Get, Imbalance, OnUnbalanced, WithdrawReasons}, + traits::{Currency, ExistenceRequirement, Imbalance, OnUnbalanced, WithdrawReasons}, unsigned::TransactionValidityError, }; @@ -73,7 +73,6 @@ pub struct CurrencyAdapter(PhantomData<(C, OU)>); impl OnChargeTransaction for CurrencyAdapter where T: Config, - T::TransactionByteFee: Get<::AccountId>>::Balance>, C: Currency<::AccountId>, C::PositiveImbalance: Imbalance< ::AccountId>>::Balance, From f4e80d444523646c14def0ebbeee1d2bae47bfcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Thu, 7 Apr 2022 15:00:30 +0200 Subject: [PATCH 685/695] Improve docs of `remove_all` and `remove_prefix` (#11182) These docs didn't mention how the removal works internally. This is important for the user to know that calling such a method multiple times in the same block leads always to the same result. --- frame/support/src/storage/mod.rs | 34 +++++++++++++++++-- frame/support/src/storage/types/double_map.rs | 21 ++++++++++-- frame/support/src/storage/types/map.rs | 6 ++++ frame/support/src/storage/types/nmap.rs | 25 ++++++++++++-- primitives/io/src/lib.rs | 10 +++--- 5 files changed, 84 insertions(+), 12 deletions(-) diff --git a/frame/support/src/storage/mod.rs b/frame/support/src/storage/mod.rs index f3eb94498ed9..066422ad456a 100644 --- a/frame/support/src/storage/mod.rs +++ b/frame/support/src/storage/mod.rs @@ -502,7 +502,18 @@ pub trait StorageDoubleMap { KArg1: EncodeLike, KArg2: EncodeLike; - /// Remove all values under the first key. + /// Remove all values under the first key `k1` in the overlay and up to `limit` in the + /// backend. + /// + /// All values in the client overlay will be deleted, if there is some `limit` then up to + /// `limit` values are deleted from the client backend, if `limit` is none then all values in + /// the client backend are deleted. + /// + /// # Note + /// + /// Calling this multiple times per block with a `limit` set leads always to the same keys being + /// removed and the same result being returned. This happens because the keys to delete in the + /// overlay are not taken into account when deleting keys in the backend. fn remove_prefix(k1: KArg1, limit: Option) -> sp_io::KillStorageResult where KArg1: ?Sized + EncodeLike; @@ -632,7 +643,18 @@ pub trait StorageNMap { /// Remove the value under a key. fn remove + TupleToEncodedIter>(key: KArg); - /// Remove all values under the partial prefix key. + /// Remove all values starting with `partial_key` in the overlay and up to `limit` in the + /// backend. + /// + /// All values in the client overlay will be deleted, if there is some `limit` then up to + /// `limit` values are deleted from the client backend, if `limit` is none then all values in + /// the client backend are deleted. + /// + /// # Note + /// + /// Calling this multiple times per block with a `limit` set leads always to the same keys being + /// removed and the same result being returned. This happens because the keys to delete in the + /// overlay are not taken into account when deleting keys in the backend. fn remove_prefix(partial_key: KP, limit: Option) -> sp_io::KillStorageResult where K: HasKeyPrefix; @@ -1076,11 +1098,17 @@ pub trait StoragePrefixedMap { crate::storage::storage_prefix(Self::module_prefix(), Self::storage_prefix()) } - /// Remove all values of the storage in the overlay and up to `limit` in the backend. + /// Remove all values in the overlay and up to `limit` in the backend. /// /// All values in the client overlay will be deleted, if there is some `limit` then up to /// `limit` values are deleted from the client backend, if `limit` is none then all values in /// the client backend are deleted. + /// + /// # Note + /// + /// Calling this multiple times per block with a `limit` set leads always to the same keys being + /// removed and the same result being returned. This happens because the keys to delete in the + /// overlay are not taken into account when deleting keys in the backend. fn remove_all(limit: Option) -> sp_io::KillStorageResult { sp_io::storage::clear_prefix(&Self::final_prefix(), limit) } diff --git a/frame/support/src/storage/types/double_map.rs b/frame/support/src/storage/types/double_map.rs index e864920e488f..42b903128934 100644 --- a/frame/support/src/storage/types/double_map.rs +++ b/frame/support/src/storage/types/double_map.rs @@ -217,7 +217,18 @@ where >::remove(k1, k2) } - /// Remove all values under the first key. + /// Remove all values under `k1` in the overlay and up to `limit` in the + /// backend. + /// + /// All values in the client overlay will be deleted, if there is some `limit` then up to + /// `limit` values are deleted from the client backend, if `limit` is none then all values in + /// the client backend are deleted. + /// + /// # Note + /// + /// Calling this multiple times per block with a `limit` set leads always to the same keys being + /// removed and the same result being returned. This happens because the keys to delete in the + /// overlay are not taken into account when deleting keys in the backend. pub fn remove_prefix(k1: KArg1, limit: Option) -> sp_io::KillStorageResult where KArg1: ?Sized + EncodeLike, @@ -337,11 +348,17 @@ where >(key1, key2) } - /// Remove all values of the storage in the overlay and up to `limit` in the backend. + /// Remove all values in the overlay and up to `limit` in the backend. /// /// All values in the client overlay will be deleted, if there is some `limit` then up to /// `limit` values are deleted from the client backend, if `limit` is none then all values in /// the client backend are deleted. + /// + /// # Note + /// + /// Calling this multiple times per block with a `limit` set leads always to the same keys being + /// removed and the same result being returned. This happens because the keys to delete in the + /// overlay are not taken into account when deleting keys in the backend. pub fn remove_all(limit: Option) -> sp_io::KillStorageResult { >::remove_all(limit) } diff --git a/frame/support/src/storage/types/map.rs b/frame/support/src/storage/types/map.rs index 01aa2f44abe5..bc32c58da8db 100644 --- a/frame/support/src/storage/types/map.rs +++ b/frame/support/src/storage/types/map.rs @@ -241,6 +241,12 @@ where /// All values in the client overlay will be deleted, if there is some `limit` then up to /// `limit` values are deleted from the client backend, if `limit` is none then all values in /// the client backend are deleted. + /// + /// # Note + /// + /// Calling this multiple times per block with a `limit` set leads always to the same keys being + /// removed and the same result being returned. This happens because the keys to delete in the + /// overlay are not taken into account when deleting keys in the backend. pub fn remove_all(limit: Option) -> sp_io::KillStorageResult { >::remove_all(limit) } diff --git a/frame/support/src/storage/types/nmap.rs b/frame/support/src/storage/types/nmap.rs index 561bf5298e18..aff32f211000 100755 --- a/frame/support/src/storage/types/nmap.rs +++ b/frame/support/src/storage/types/nmap.rs @@ -173,7 +173,18 @@ where >::remove(key) } - /// Remove all values under the first key. + /// Remove all values starting with `partial_key` in the overlay and up to `limit` in the + /// backend. + /// + /// All values in the client overlay will be deleted, if there is some `limit` then up to + /// `limit` values are deleted from the client backend, if `limit` is none then all values in + /// the client backend are deleted. + /// + /// # Note + /// + /// Calling this multiple times per block with a `limit` set leads always to the same keys being + /// removed and the same result being returned. This happens because the keys to delete in the + /// overlay are not taken into account when deleting keys in the backend. pub fn remove_prefix(partial_key: KP, limit: Option) -> sp_io::KillStorageResult where Key: HasKeyPrefix, @@ -277,7 +288,17 @@ where >::migrate_keys::<_>(key, hash_fns) } - /// Remove all value of the storage. + /// Remove all values in the overlay and up to `limit` in the backend. + /// + /// All values in the client overlay will be deleted, if there is some `limit` then up to + /// `limit` values are deleted from the client backend, if `limit` is none then all values in + /// the client backend are deleted. + /// + /// # Note + /// + /// Calling this multiple times per block with a `limit` set leads always to the same keys being + /// removed and the same result being returned. This happens because the keys to delete in the + /// overlay are not taken into account when deleting keys in the backend. pub fn remove_all(limit: Option) -> sp_io::KillStorageResult { >::remove_all(limit) } diff --git a/primitives/io/src/lib.rs b/primitives/io/src/lib.rs index 9f49a098b6ad..2ff49b504881 100644 --- a/primitives/io/src/lib.rs +++ b/primitives/io/src/lib.rs @@ -158,9 +158,7 @@ pub trait Storage { /// The limit can be used to partially delete a prefix storage in case it is too large /// to delete in one go (block). /// - /// It returns a boolean false iff some keys are remaining in - /// the prefix after the functions returns. Also returns a `u32` with - /// the number of keys removed from the process. + /// Returns [`KillStorageResult`] to inform about the result. /// /// # Note /// @@ -171,8 +169,10 @@ pub trait Storage { /// /// Calling this function multiple times per block for the same `prefix` does /// not make much sense because it is not cumulative when called inside the same block. - /// Use this function to distribute the deletion of a single child trie across multiple - /// blocks. + /// The deletion would always start from `prefix` resulting in the same keys being deleted + /// every time this function is called with the exact same arguments per block. This happens + /// because the keys in the overlay are not taken into account when deleting keys in the + /// backend. #[version(2)] fn clear_prefix(&mut self, prefix: &[u8], limit: Option) -> KillStorageResult { let (all_removed, num_removed) = Externalities::clear_prefix(*self, prefix, limit); From f98ef8abfc54bb7801b21be899e63f5058350e14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Paulo=20Silva=20de=20Souza?= <77391175+joao-paulo-parity@users.noreply.github.com> Date: Thu, 7 Apr 2022 11:23:33 -0300 Subject: [PATCH 686/695] update pr-custom-review.yml (#11169) syntax in accordance to https://github.com/paritytech/pr-custom-review/tree/5814820aa0e5d35412f31dc02f9d130a8b138cae#configuration-syntax rules in accordance to https://github.com/paritytech/pr-custom-review/blob/da1d81b9fd39705cc8b37f59235283801c818708/rules.md --- .github/pr-custom-review.yml | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/.github/pr-custom-review.yml b/.github/pr-custom-review.yml index 615203c11c15..7ce8146571cd 100644 --- a/.github/pr-custom-review.yml +++ b/.github/pr-custom-review.yml @@ -1,18 +1,16 @@ +# 🔒 PROTECTED: Changes to locks-review-team should be approved by the current locks-review-team +locks-review-team: locks-review +team-leads-team: polkadot-review +action-review-team: ci + rules: - - name: Changed runtime files - condition: .*/runtime/.*lib.rs + - name: Core developers check_type: changed_files + condition: .* min_approvals: 2 teams: - - substrateteamleads + - core-devs - - name: Substrate developers - check_type: changed_files - condition: .* - any: - - min_approvals: 2 - teams: - - core-devs - - min_approvals: 1 - teams: - - substrateteamleads \ No newline at end of file +prevent_review_request: + teams: + - core-devs From 174735ea1bb5fc4513519c45181d8df63d86f613 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Thu, 7 Apr 2022 21:33:11 +0200 Subject: [PATCH 687/695] Sub-commands for `benchmark` (#11164) * Restructure benchmark commands Signed-off-by: Oliver Tale-Yazdi * Add benchmark block test Signed-off-by: Oliver Tale-Yazdi * Fixup imports Signed-off-by: Oliver Tale-Yazdi * CI Signed-off-by: Oliver Tale-Yazdi * Review fixes Signed-off-by: Oliver Tale-Yazdi * Extend error message Signed-off-by: Oliver Tale-Yazdi * Apply suggestions from code review Co-authored-by: Zeke Mostov * Review fixes Signed-off-by: Oliver Tale-Yazdi * Add commands to node-template Signed-off-by: Oliver Tale-Yazdi Co-authored-by: Zeke Mostov --- Cargo.lock | 4 + bin/node-template/node/Cargo.toml | 4 + bin/node-template/node/src/cli.rs | 4 +- bin/node-template/node/src/command.rs | 46 +++- bin/node-template/node/src/command_helper.rs | 131 ++++++++++++ bin/node-template/node/src/main.rs | 1 + bin/node-template/node/src/service.rs | 2 +- bin/node-template/runtime/src/lib.rs | 3 + bin/node/cli/src/cli.rs | 23 +- bin/node/cli/src/command.rs | 70 +++--- bin/node/cli/src/command_helper.rs | 12 +- bin/node/cli/tests/benchmark_block_works.rs | 48 +++++ .../cli/tests/benchmark_overhead_works.rs | 4 +- bin/node/cli/tests/benchmark_storage_works.rs | 4 +- .../frame/benchmarking-cli/src/block/bench.rs | 2 +- utils/frame/benchmarking-cli/src/block/cmd.rs | 4 +- utils/frame/benchmarking-cli/src/lib.rs | 201 +++++++----------- .../benchmarking-cli/src/overhead/bench.rs | 3 +- .../benchmarking-cli/src/overhead/cmd.rs | 8 +- .../benchmarking-cli/src/overhead/template.rs | 4 +- .../src/{ => pallet}/command.rs | 22 +- .../frame/benchmarking-cli/src/pallet/mod.rs | 150 +++++++++++++ .../src/{ => pallet}/template.hbs | 0 .../src/{ => pallet}/writer.rs | 44 +--- .../frame/benchmarking-cli/src/shared/mod.rs | 65 ++++++ .../benchmarking-cli/src/shared/record.rs | 72 +++++++ .../{storage/record.rs => shared/stats.rs} | 74 ++----- .../mod.rs => shared/weight_params.rs} | 8 +- .../frame/benchmarking-cli/src/storage/cmd.rs | 7 +- .../frame/benchmarking-cli/src/storage/mod.rs | 1 - .../benchmarking-cli/src/storage/read.rs | 3 +- .../benchmarking-cli/src/storage/template.rs | 5 +- .../benchmarking-cli/src/storage/write.rs | 3 +- 33 files changed, 690 insertions(+), 342 deletions(-) create mode 100644 bin/node-template/node/src/command_helper.rs create mode 100644 bin/node/cli/tests/benchmark_block_works.rs rename utils/frame/benchmarking-cli/src/{ => pallet}/command.rs (95%) create mode 100644 utils/frame/benchmarking-cli/src/pallet/mod.rs rename utils/frame/benchmarking-cli/src/{ => pallet}/template.hbs (100%) rename utils/frame/benchmarking-cli/src/{ => pallet}/writer.rs (93%) create mode 100644 utils/frame/benchmarking-cli/src/shared/mod.rs create mode 100644 utils/frame/benchmarking-cli/src/shared/record.rs rename utils/frame/benchmarking-cli/src/{storage/record.rs => shared/stats.rs} (70%) rename utils/frame/benchmarking-cli/src/{post_processing/mod.rs => shared/weight_params.rs} (92%) diff --git a/Cargo.lock b/Cargo.lock index 0a1a1e0b17be..1ecb25b7b4b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5089,8 +5089,10 @@ dependencies = [ "clap 3.1.6", "frame-benchmarking", "frame-benchmarking-cli", + "frame-system", "jsonrpc-core", "node-template-runtime", + "pallet-transaction-payment", "pallet-transaction-payment-rpc", "sc-basic-authorship", "sc-cli", @@ -5113,6 +5115,8 @@ dependencies = [ "sp-consensus-aura", "sp-core", "sp-finality-grandpa", + "sp-inherents", + "sp-keyring", "sp-runtime", "sp-timestamp", "substrate-build-script-utils", diff --git a/bin/node-template/node/Cargo.toml b/bin/node-template/node/Cargo.toml index 4549a5b613da..e642ce3c0411 100644 --- a/bin/node-template/node/Cargo.toml +++ b/bin/node-template/node/Cargo.toml @@ -36,6 +36,10 @@ sp-finality-grandpa = { version = "4.0.0-dev", path = "../../../primitives/final sc-client-api = { version = "4.0.0-dev", path = "../../../client/api" } sp-runtime = { version = "6.0.0", path = "../../../primitives/runtime" } sp-timestamp = { version = "4.0.0-dev", path = "../../../primitives/timestamp" } +sp-inherents = { version = "4.0.0-dev", path = "../../../primitives/inherents" } +sp-keyring = { version = "6.0.0", path = "../../../primitives/keyring" } +frame-system = { version = "4.0.0-dev", path = "../../../frame/system" } +pallet-transaction-payment = { version = "4.0.0-dev", default-features = false, path = "../../../frame/transaction-payment" } # These dependencies are used for the node template's RPCs jsonrpc-core = "18.0.0" diff --git a/bin/node-template/node/src/cli.rs b/bin/node-template/node/src/cli.rs index c4d27b71e499..710c7f3f9e14 100644 --- a/bin/node-template/node/src/cli.rs +++ b/bin/node-template/node/src/cli.rs @@ -36,8 +36,8 @@ pub enum Subcommand { /// Revert the chain to a previous state. Revert(sc_cli::RevertCmd), - /// The custom benchmark subcommand benchmarking runtime pallets. - #[clap(name = "benchmark", about = "Benchmark runtime pallets.")] + /// Sub-commands concerned with benchmarking. + #[clap(subcommand)] Benchmark(frame_benchmarking_cli::BenchmarkCmd), /// Try some command against runtime state. diff --git a/bin/node-template/node/src/command.rs b/bin/node-template/node/src/command.rs index f033e779543a..ede969b3572c 100644 --- a/bin/node-template/node/src/command.rs +++ b/bin/node-template/node/src/command.rs @@ -1,11 +1,14 @@ use crate::{ chain_spec, cli::{Cli, Subcommand}, + command_helper::{inherent_benchmark_data, BenchmarkExtrinsicBuilder}, service, }; +use frame_benchmarking_cli::BenchmarkCmd; use node_template_runtime::Block; use sc_cli::{ChainSpec, RuntimeVersion, SubstrateCli}; use sc_service::PartialComponents; +use std::sync::Arc; impl SubstrateCli for Cli { fn impl_name() -> String { @@ -102,16 +105,41 @@ pub fn run() -> sc_cli::Result<()> { Ok((cmd.run(client, backend, Some(aux_revert)), task_manager)) }) }, - Some(Subcommand::Benchmark(cmd)) => - if cfg!(feature = "runtime-benchmarks") { - let runner = cli.create_runner(cmd)?; + Some(Subcommand::Benchmark(cmd)) => { + let runner = cli.create_runner(cmd)?; + + runner.sync_run(|config| { + let PartialComponents { client, backend, .. } = service::new_partial(&config)?; + + // This switch needs to be in the client, since the client decides + // which sub-commands it wants to support. + match cmd { + BenchmarkCmd::Pallet(cmd) => { + if !cfg!(feature = "runtime-benchmarks") { + return Err( + "Runtime benchmarking wasn't enabled when building the node. \ + You can enable it with `--features runtime-benchmarks`." + .into(), + ) + } + + cmd.run::(config) + }, + BenchmarkCmd::Block(cmd) => cmd.run(client), + BenchmarkCmd::Storage(cmd) => { + let db = backend.expose_db(); + let storage = backend.expose_storage(); - runner.sync_run(|config| cmd.run::(config)) - } else { - Err("Benchmarking wasn't enabled when building the node. You can enable it with \ - `--features runtime-benchmarks`." - .into()) - }, + cmd.run(config, client, db, storage) + }, + BenchmarkCmd::Overhead(cmd) => { + let ext_builder = BenchmarkExtrinsicBuilder::new(client.clone()); + + cmd.run(config, client, inherent_benchmark_data()?, Arc::new(ext_builder)) + }, + } + }) + }, #[cfg(feature = "try-runtime")] Some(Subcommand::TryRuntime(cmd)) => { let runner = cli.create_runner(cmd)?; diff --git a/bin/node-template/node/src/command_helper.rs b/bin/node-template/node/src/command_helper.rs new file mode 100644 index 000000000000..287e81b1e96b --- /dev/null +++ b/bin/node-template/node/src/command_helper.rs @@ -0,0 +1,131 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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 . + +//! Contains code to setup the command invocations in [`super::command`] which would +//! otherwise bloat that module. + +use crate::service::FullClient; + +use node_template_runtime as runtime; +use runtime::SystemCall; +use sc_cli::Result; +use sc_client_api::BlockBackend; +use sp_core::{Encode, Pair}; +use sp_inherents::{InherentData, InherentDataProvider}; +use sp_keyring::Sr25519Keyring; +use sp_runtime::{OpaqueExtrinsic, SaturatedConversion}; + +use std::{sync::Arc, time::Duration}; + +/// Generates extrinsics for the `benchmark overhead` command. +/// +/// Note: Should only be used for benchmarking. +pub struct BenchmarkExtrinsicBuilder { + client: Arc, +} + +impl BenchmarkExtrinsicBuilder { + /// Creates a new [`Self`] from the given client. + pub fn new(client: Arc) -> Self { + Self { client } + } +} + +impl frame_benchmarking_cli::ExtrinsicBuilder for BenchmarkExtrinsicBuilder { + fn remark(&self, nonce: u32) -> std::result::Result { + let acc = Sr25519Keyring::Bob.pair(); + let extrinsic: OpaqueExtrinsic = create_benchmark_extrinsic( + self.client.as_ref(), + acc, + SystemCall::remark { remark: vec![] }.into(), + nonce, + ) + .into(); + + Ok(extrinsic) + } +} + +/// Create a transaction using the given `call`. +/// +/// Note: Should only be used for benchmarking. +pub fn create_benchmark_extrinsic( + client: &FullClient, + sender: sp_core::sr25519::Pair, + call: runtime::Call, + nonce: u32, +) -> runtime::UncheckedExtrinsic { + let genesis_hash = client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"); + let best_hash = client.chain_info().best_hash; + let best_block = client.chain_info().best_number; + + let period = runtime::BlockHashCount::get() + .checked_next_power_of_two() + .map(|c| c / 2) + .unwrap_or(2) as u64; + let extra: runtime::SignedExtra = ( + frame_system::CheckNonZeroSender::::new(), + frame_system::CheckSpecVersion::::new(), + frame_system::CheckTxVersion::::new(), + frame_system::CheckGenesis::::new(), + frame_system::CheckEra::::from(sp_runtime::generic::Era::mortal( + period, + best_block.saturated_into(), + )), + frame_system::CheckNonce::::from(nonce), + frame_system::CheckWeight::::new(), + pallet_transaction_payment::ChargeTransactionPayment::::from(0), + ); + + let raw_payload = runtime::SignedPayload::from_raw( + call.clone(), + extra.clone(), + ( + (), + runtime::VERSION.spec_version, + runtime::VERSION.transaction_version, + genesis_hash, + best_hash, + (), + (), + (), + ), + ); + let signature = raw_payload.using_encoded(|e| sender.sign(e)); + + runtime::UncheckedExtrinsic::new_signed( + call.clone(), + sp_runtime::AccountId32::from(sender.public()).into(), + runtime::Signature::Sr25519(signature.clone()), + extra.clone(), + ) +} + +/// Generates inherent data for the `benchmark overhead` command. +/// +/// Note: Should only be used for benchmarking. +pub fn inherent_benchmark_data() -> Result { + let mut inherent_data = InherentData::new(); + let d = Duration::from_millis(0); + let timestamp = sp_timestamp::InherentDataProvider::new(d.into()); + + timestamp + .provide_inherent_data(&mut inherent_data) + .map_err(|e| format!("creating inherent data: {:?}", e))?; + Ok(inherent_data) +} diff --git a/bin/node-template/node/src/main.rs b/bin/node-template/node/src/main.rs index 4449d28b9fa4..0f2fbd5a909c 100644 --- a/bin/node-template/node/src/main.rs +++ b/bin/node-template/node/src/main.rs @@ -6,6 +6,7 @@ mod chain_spec; mod service; mod cli; mod command; +mod command_helper; mod rpc; fn main() -> sc_cli::Result<()> { diff --git a/bin/node-template/node/src/service.rs b/bin/node-template/node/src/service.rs index fc7dc9b978df..e2a8cb4ed834 100644 --- a/bin/node-template/node/src/service.rs +++ b/bin/node-template/node/src/service.rs @@ -31,7 +31,7 @@ impl sc_executor::NativeExecutionDispatch for ExecutorDispatch { } } -type FullClient = +pub(crate) type FullClient = sc_service::TFullClient>; type FullBackend = sc_service::TFullBackend; type FullSelectChain = sc_consensus::LongestChain; diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index 40adbb038811..780a84572d58 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -33,6 +33,7 @@ pub use frame_support::{ }, StorageValue, }; +pub use frame_system::Call as SystemCall; pub use pallet_balances::Call as BalancesCall; pub use pallet_timestamp::Call as TimestampCall; use pallet_transaction_payment::CurrencyAdapter; @@ -306,6 +307,8 @@ pub type SignedExtra = ( ); /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; +/// The payload being signed in transactions. +pub type SignedPayload = generic::SignedPayload; /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< Runtime, diff --git a/bin/node/cli/src/cli.rs b/bin/node/cli/src/cli.rs index 952c6311f8b3..7430cc46f4cc 100644 --- a/bin/node/cli/src/cli.rs +++ b/bin/node/cli/src/cli.rs @@ -38,28 +38,11 @@ pub enum Subcommand { )] Inspect(node_inspect::cli::InspectCmd), - /// The custom benchmark subcommmand benchmarking runtime pallets. - #[clap(name = "benchmark", about = "Benchmark runtime pallets.")] + /// Sub-commands concerned with benchmarking. + /// The pallet benchmarking moved to the `pallet` sub-command. + #[clap(subcommand)] Benchmark(frame_benchmarking_cli::BenchmarkCmd), - /// Benchmark the execution time of historic blocks and compare it to their consumed weight. - #[clap( - name = "benchmark-block", - about = "Benchmark the execution time of historic blocks and compare it to their consumed weight." - )] - BenchmarkBlock(frame_benchmarking_cli::BlockCmd), - - /// Sub command for benchmarking the per-block and per-extrinsic execution overhead. - #[clap( - name = "benchmark-overhead", - about = "Benchmark the per-block and per-extrinsic execution overhead." - )] - BenchmarkOverhead(frame_benchmarking_cli::OverheadCmd), - - /// Sub command for benchmarking the storage speed. - #[clap(name = "benchmark-storage", about = "Benchmark storage speed.")] - BenchmarkStorage(frame_benchmarking_cli::StorageCmd), - /// Try some command against runtime state. #[cfg(feature = "try-runtime")] TryRuntime(try_runtime_cli::TryRuntimeCmd), diff --git a/bin/node/cli/src/command.rs b/bin/node/cli/src/command.rs index db243ff6f597..c752b1c30ae2 100644 --- a/bin/node/cli/src/command.rs +++ b/bin/node/cli/src/command.rs @@ -16,11 +16,13 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +use super::command_helper::{inherent_benchmark_data, BenchmarkExtrinsicBuilder}; use crate::{ chain_spec, service, service::{new_partial, FullClient}, Cli, Subcommand, }; +use frame_benchmarking_cli::*; use node_executor::ExecutorDispatch; use node_primitives::Block; use node_runtime::RuntimeApi; @@ -92,45 +94,39 @@ pub fn run() -> Result<()> { runner.sync_run(|config| cmd.run::(config)) }, - Some(Subcommand::Benchmark(cmd)) => - if cfg!(feature = "runtime-benchmarks") { - let runner = cli.create_runner(cmd)?; - - runner.sync_run(|config| cmd.run::(config)) - } else { - Err("Benchmarking wasn't enabled when building the node. \ - You can enable it with `--features runtime-benchmarks`." - .into()) - }, - Some(Subcommand::BenchmarkBlock(cmd)) => { + Some(Subcommand::Benchmark(cmd)) => { let runner = cli.create_runner(cmd)?; - runner.async_run(|config| { - let PartialComponents { client, task_manager, .. } = new_partial(&config)?; - Ok((cmd.run(client), task_manager)) - }) - }, - Some(Subcommand::BenchmarkOverhead(cmd)) => { - let runner = cli.create_runner(cmd)?; - runner.async_run(|mut config| { - use super::command_helper::{inherent_data, ExtrinsicBuilder}; - // We don't use the authority role since that would start producing blocks - // in the background which would mess with our benchmark. - config.role = sc_service::Role::Full; - - let PartialComponents { client, task_manager, .. } = new_partial(&config)?; - let ext_builder = ExtrinsicBuilder::new(client.clone()); - - Ok((cmd.run(config, client, inherent_data()?, Arc::new(ext_builder)), task_manager)) - }) - }, - Some(Subcommand::BenchmarkStorage(cmd)) => { - let runner = cli.create_runner(cmd)?; - runner.async_run(|config| { - let PartialComponents { client, task_manager, backend, .. } = new_partial(&config)?; - let db = backend.expose_db(); - let storage = backend.expose_storage(); - Ok((cmd.run(config, client, db, storage), task_manager)) + runner.sync_run(|config| { + let PartialComponents { client, backend, .. } = new_partial(&config)?; + + // This switch needs to be in the client, since the client decides + // which sub-commands it wants to support. + match cmd { + BenchmarkCmd::Pallet(cmd) => { + if !cfg!(feature = "runtime-benchmarks") { + return Err( + "Runtime benchmarking wasn't enabled when building the node. \ + You can enable it with `--features runtime-benchmarks`." + .into(), + ) + } + + cmd.run::(config) + }, + BenchmarkCmd::Block(cmd) => cmd.run(client), + BenchmarkCmd::Storage(cmd) => { + let db = backend.expose_db(); + let storage = backend.expose_storage(); + + cmd.run(config, client, db, storage) + }, + BenchmarkCmd::Overhead(cmd) => { + let ext_builder = BenchmarkExtrinsicBuilder::new(client.clone()); + + cmd.run(config, client, inherent_benchmark_data()?, Arc::new(ext_builder)) + }, + } }) }, Some(Subcommand::Key(cmd)) => cmd.run(&cli), diff --git a/bin/node/cli/src/command_helper.rs b/bin/node/cli/src/command_helper.rs index 51fe7a5c5a7b..84d85ee367ca 100644 --- a/bin/node/cli/src/command_helper.rs +++ b/bin/node/cli/src/command_helper.rs @@ -29,19 +29,19 @@ use sp_runtime::OpaqueExtrinsic; use std::{sync::Arc, time::Duration}; -/// Generates extrinsics for the `benchmark-overhead` command. -pub struct ExtrinsicBuilder { +/// Generates extrinsics for the `benchmark overhead` command. +pub struct BenchmarkExtrinsicBuilder { client: Arc, } -impl ExtrinsicBuilder { +impl BenchmarkExtrinsicBuilder { /// Creates a new [`Self`] from the given client. pub fn new(client: Arc) -> Self { Self { client } } } -impl frame_benchmarking_cli::ExtrinsicBuilder for ExtrinsicBuilder { +impl frame_benchmarking_cli::ExtrinsicBuilder for BenchmarkExtrinsicBuilder { fn remark(&self, nonce: u32) -> std::result::Result { let acc = Sr25519Keyring::Bob.pair(); let extrinsic: OpaqueExtrinsic = create_extrinsic( @@ -56,8 +56,8 @@ impl frame_benchmarking_cli::ExtrinsicBuilder for ExtrinsicBuilder { } } -/// Generates inherent data for the `benchmark-overhead` command. -pub fn inherent_data() -> Result { +/// Generates inherent data for the `benchmark overhead` command. +pub fn inherent_benchmark_data() -> Result { let mut inherent_data = InherentData::new(); let d = Duration::from_millis(0); let timestamp = sp_timestamp::InherentDataProvider::new(d.into()); diff --git a/bin/node/cli/tests/benchmark_block_works.rs b/bin/node/cli/tests/benchmark_block_works.rs new file mode 100644 index 000000000000..37a4db25f363 --- /dev/null +++ b/bin/node/cli/tests/benchmark_block_works.rs @@ -0,0 +1,48 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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 . + +// Unix only since it uses signals from [`common::run_node_for_a_while`]. +#![cfg(unix)] + +use assert_cmd::cargo::cargo_bin; +use std::process::Command; +use tempfile::tempdir; + +pub mod common; + +/// `benchmark block` works for the dev runtime using the wasm executor. +#[tokio::test] +async fn benchmark_block_works() { + let base_dir = tempdir().expect("could not create a temp dir"); + + common::run_node_for_a_while(base_dir.path(), &["--dev"]).await; + + // Invoke `benchmark block` with all options to make sure that they are valid. + let status = Command::new(cargo_bin("substrate")) + .args(["benchmark", "block", "--dev"]) + .arg("-d") + .arg(base_dir.path()) + .args(["--pruning", "archive"]) + .args(["--from", "1", "--to", "1"]) + .args(["--repeat", "1"]) + .args(["--execution", "wasm", "--wasm-execution", "compiled"]) + .status() + .unwrap(); + + assert!(status.success()) +} diff --git a/bin/node/cli/tests/benchmark_overhead_works.rs b/bin/node/cli/tests/benchmark_overhead_works.rs index 550221ee2f70..44dcebfbc0c3 100644 --- a/bin/node/cli/tests/benchmark_overhead_works.rs +++ b/bin/node/cli/tests/benchmark_overhead_works.rs @@ -20,7 +20,7 @@ use assert_cmd::cargo::cargo_bin; use std::process::Command; use tempfile::tempdir; -/// Tests that the `benchmark-overhead` command works for the substrate dev runtime. +/// Tests that the `benchmark overhead` command works for the substrate dev runtime. #[test] fn benchmark_overhead_works() { let tmp_dir = tempdir().expect("could not create a temp dir"); @@ -29,7 +29,7 @@ fn benchmark_overhead_works() { // Only put 10 extrinsics into the block otherwise it takes forever to build it // especially for a non-release build. let status = Command::new(cargo_bin("substrate")) - .args(&["benchmark-overhead", "--dev", "-d"]) + .args(&["benchmark", "overhead", "--dev", "-d"]) .arg(base_path) .arg("--weight-path") .arg(base_path) diff --git a/bin/node/cli/tests/benchmark_storage_works.rs b/bin/node/cli/tests/benchmark_storage_works.rs index 1628f9a7e97b..30f860e48459 100644 --- a/bin/node/cli/tests/benchmark_storage_works.rs +++ b/bin/node/cli/tests/benchmark_storage_works.rs @@ -23,7 +23,7 @@ use std::{ }; use tempfile::tempdir; -/// Tests that the `benchmark-storage` command works for the dev runtime. +/// Tests that the `benchmark storage` command works for the dev runtime. #[test] fn benchmark_storage_works() { let tmp_dir = tempdir().expect("could not create a temp dir"); @@ -39,7 +39,7 @@ fn benchmark_storage_works() { fn benchmark_storage(db: &str, base_path: &Path) -> ExitStatus { Command::new(cargo_bin("substrate")) - .args(&["benchmark-storage", "--dev"]) + .args(&["benchmark", "storage", "--dev"]) .arg("--db") .arg(db) .arg("--weight-path") diff --git a/utils/frame/benchmarking-cli/src/block/bench.rs b/utils/frame/benchmarking-cli/src/block/bench.rs index d3c1c97b04ab..e48a7e8b3c6f 100644 --- a/utils/frame/benchmarking-cli/src/block/bench.rs +++ b/utils/frame/benchmarking-cli/src/block/bench.rs @@ -34,7 +34,7 @@ use serde::Serialize; use std::{fmt::Debug, marker::PhantomData, sync::Arc, time::Instant}; use thousands::Separable; -use crate::storage::record::{StatSelect, Stats}; +use crate::shared::{StatSelect, Stats}; /// Log target for printing block weight info. const LOG_TARGET: &'static str = "benchmark::block::weight"; diff --git a/utils/frame/benchmarking-cli/src/block/cmd.rs b/utils/frame/benchmarking-cli/src/block/cmd.rs index 4618c1dd894e..e4e1716b1c5a 100644 --- a/utils/frame/benchmarking-cli/src/block/cmd.rs +++ b/utils/frame/benchmarking-cli/src/block/cmd.rs @@ -29,7 +29,7 @@ use std::{fmt::Debug, sync::Arc}; use super::bench::{Benchmark, BenchmarkParams}; -/// Benchmark the execution time historic blocks. +/// Benchmark the execution time of historic blocks. /// /// This can be used to verify that blocks do not use more weight than they consumed /// in their `WeightInfo`. Example: @@ -73,7 +73,7 @@ impl BlockCmd { /// Benchmark the execution time of historic blocks and compare it to their consumed weight. /// /// Output will be printed to console. - pub async fn run(&self, client: Arc) -> Result<()> + pub fn run(&self, client: Arc) -> Result<()> where Block: BlockT, BA: ClientBackend, diff --git a/utils/frame/benchmarking-cli/src/lib.rs b/utils/frame/benchmarking-cli/src/lib.rs index 288e6b4b8615..2543a63b2f15 100644 --- a/utils/frame/benchmarking-cli/src/lib.rs +++ b/utils/frame/benchmarking-cli/src/lib.rs @@ -15,144 +15,85 @@ // See the License for the specific language governing permissions and // limitations under the License. +//! Contains the root [`BenchmarkCmd`] command and exports its sub-commands. + mod block; -mod command; -pub mod overhead; -mod post_processing; +mod overhead; +mod pallet; +mod shared; mod storage; -mod writer; - -use sc_cli::{ExecutionStrategy, WasmExecutionMethod, DEFAULT_WASM_EXECUTION_METHOD}; -use std::{fmt::Debug, path::PathBuf}; pub use block::BlockCmd; pub use overhead::{ExtrinsicBuilder, OverheadCmd}; +pub use pallet::PalletCmd; pub use storage::StorageCmd; -// Add a more relaxed parsing for pallet names by allowing pallet directory names with `-` to be -// used like crate names with `_` -fn parse_pallet_name(pallet: &str) -> String { - pallet.replace("-", "_") +use sc_cli::{CliConfiguration, DatabaseParams, ImportParams, PruningParams, Result, SharedParams}; + +/// The root `benchmarking` command. +/// +/// Has no effect itself besides printing a help menu of the sub-commands. +#[derive(Debug, clap::Subcommand)] +pub enum BenchmarkCmd { + Pallet(PalletCmd), + Storage(StorageCmd), + Overhead(OverheadCmd), + Block(BlockCmd), } -/// The `benchmark` command used to benchmark FRAME Pallets. -#[derive(Debug, clap::Parser)] -pub struct BenchmarkCmd { - /// Select a FRAME Pallet to benchmark, or `*` for all (in which case `extrinsic` must be `*`). - #[clap(short, long, parse(from_str = parse_pallet_name), required_unless_present = "list")] - pub pallet: Option, - - /// Select an extrinsic inside the pallet to benchmark, or `*` for all. - #[clap(short, long, required_unless_present = "list")] - pub extrinsic: Option, - - /// Select how many samples we should take across the variable components. - #[clap(short, long, default_value = "1")] - pub steps: u32, - - /// Indicates lowest values for each of the component ranges. - #[clap(long = "low", use_value_delimiter = true)] - pub lowest_range_values: Vec, - - /// Indicates highest values for each of the component ranges. - #[clap(long = "high", use_value_delimiter = true)] - pub highest_range_values: Vec, - - /// Select how many repetitions of this benchmark should run from within the wasm. - #[clap(short, long, default_value = "1")] - pub repeat: u32, - - /// Select how many repetitions of this benchmark should run from the client. - /// - /// NOTE: Using this alone may give slower results, but will afford you maximum Wasm memory. - #[clap(long, default_value = "1")] - pub external_repeat: u32, - - /// Print the raw results in JSON format. - #[clap(long = "json")] - pub json_output: bool, - - /// Write the raw results in JSON format into the given file. - #[clap(long, conflicts_with = "json-output")] - pub json_file: Option, - - /// Don't print the median-slopes linear regression analysis. - #[clap(long)] - pub no_median_slopes: bool, - - /// Don't print the min-squares linear regression analysis. - #[clap(long)] - pub no_min_squares: bool, - - /// Output the benchmarks to a Rust file at the given path. - #[clap(long)] - pub output: Option, - - /// Add a header file to your outputted benchmarks - #[clap(long)] - pub header: Option, - - /// Path to Handlebars template file used for outputting benchmark results. (Optional) - #[clap(long)] - pub template: Option, - - /// Which analysis function to use when outputting benchmarks: - /// * min-squares (default) - /// * median-slopes - /// * max (max of min squares and median slopes for each value) - #[clap(long)] - pub output_analysis: Option, - - /// Set the heap pages while running benchmarks. If not set, the default value from the client - /// is used. - #[clap(long)] - pub heap_pages: Option, - - /// Disable verification logic when running benchmarks. - #[clap(long)] - pub no_verify: bool, - - /// Display and run extra benchmarks that would otherwise not be needed for weight - /// construction. - #[clap(long)] - pub extra: bool, - - /// Estimate PoV size. - #[clap(long)] - pub record_proof: bool, - - #[allow(missing_docs)] - #[clap(flatten)] - pub shared_params: sc_cli::SharedParams, - - /// The execution strategy that should be used for benchmarks - #[clap(long, value_name = "STRATEGY", arg_enum, ignore_case = true)] - pub execution: Option, - - /// Method for executing Wasm runtime code. - #[clap( - long = "wasm-execution", - value_name = "METHOD", - possible_values = WasmExecutionMethod::variants(), - ignore_case = true, - default_value = DEFAULT_WASM_EXECUTION_METHOD, - )] - pub wasm_method: WasmExecutionMethod, - - /// Limit the memory the database cache can use. - #[clap(long = "db-cache", value_name = "MiB", default_value = "1024")] - pub database_cache_size: u32, - - /// List the benchmarks that match your query rather than running them. - /// - /// When nothing is provided, we list all benchmarks. - #[clap(long)] - pub list: bool, +/// Unwraps a [`BenchmarkCmd`] into its concrete sub-command. +macro_rules! unwrap_cmd { + { + $self:expr, + $cmd:ident, + $code:expr + } => { + match $self { + BenchmarkCmd::Pallet($cmd) => $code, + BenchmarkCmd::Storage($cmd) => $code, + BenchmarkCmd::Overhead($cmd) => $code, + BenchmarkCmd::Block($cmd) => $code, + } + } +} - /// If enabled, the storage info is not displayed in the output next to the analysis. - /// - /// This is independent of the storage info appearing in the *output file*. Use a Handlebar - /// template for that purpose. - #[clap(long)] - pub no_storage_info: bool, +/// Forward the [`CliConfiguration`] trait implementation. +/// +/// Each time a sub-command exposes a new config option, it must be added here. +impl CliConfiguration for BenchmarkCmd { + fn shared_params(&self) -> &SharedParams { + unwrap_cmd! { + self, cmd, cmd.shared_params() + } + } + + fn import_params(&self) -> Option<&ImportParams> { + unwrap_cmd! { + self, cmd, cmd.import_params() + } + } + + fn database_params(&self) -> Option<&DatabaseParams> { + unwrap_cmd! { + self, cmd, cmd.database_params() + } + } + + fn pruning_params(&self) -> Option<&PruningParams> { + unwrap_cmd! { + self, cmd, cmd.pruning_params() + } + } + + fn state_cache_size(&self) -> Result { + unwrap_cmd! { + self, cmd, cmd.state_cache_size() + } + } + + fn chain_id(&self, is_dev: bool) -> Result { + unwrap_cmd! { + self, cmd, cmd.chain_id(is_dev) + } + } } diff --git a/utils/frame/benchmarking-cli/src/overhead/bench.rs b/utils/frame/benchmarking-cli/src/overhead/bench.rs index 3e18c6a86db2..68f3f6597b46 100644 --- a/utils/frame/benchmarking-cli/src/overhead/bench.rs +++ b/utils/frame/benchmarking-cli/src/overhead/bench.rs @@ -36,7 +36,8 @@ use log::info; use serde::Serialize; use std::{marker::PhantomData, sync::Arc, time::Instant}; -use crate::{overhead::cmd::ExtrinsicBuilder, storage::record::Stats}; +use super::cmd::ExtrinsicBuilder; +use crate::shared::Stats; /// Parameters to configure an *overhead* benchmark. #[derive(Debug, Default, Serialize, Clone, PartialEq, Args)] diff --git a/utils/frame/benchmarking-cli/src/overhead/cmd.rs b/utils/frame/benchmarking-cli/src/overhead/cmd.rs index f74c32ba72a8..3cf281986861 100644 --- a/utils/frame/benchmarking-cli/src/overhead/cmd.rs +++ b/utils/frame/benchmarking-cli/src/overhead/cmd.rs @@ -35,10 +35,10 @@ use crate::{ bench::{Benchmark, BenchmarkParams, BenchmarkType}, template::TemplateData, }, - post_processing::WeightParams, + shared::WeightParams, }; -/// Benchmarks the per-block and per-extrinsic execution overhead. +/// Benchmark the execution overhead per-block and per-extrinsic. #[derive(Debug, Parser)] pub struct OverheadCmd { #[allow(missing_docs)] @@ -76,11 +76,11 @@ pub trait ExtrinsicBuilder { } impl OverheadCmd { - /// Measures the per-block and per-extrinsic execution overhead. + /// Measure the per-block and per-extrinsic execution overhead. /// /// Writes the results to console and into two instances of the /// `weights.hbs` template, one for each benchmark. - pub async fn run( + pub fn run( &self, cfg: Configuration, client: Arc, diff --git a/utils/frame/benchmarking-cli/src/overhead/template.rs b/utils/frame/benchmarking-cli/src/overhead/template.rs index f6fb8ed9d929..d5f90d487386 100644 --- a/utils/frame/benchmarking-cli/src/overhead/template.rs +++ b/utils/frame/benchmarking-cli/src/overhead/template.rs @@ -28,7 +28,7 @@ use std::{env, fs, path::PathBuf}; use crate::{ overhead::{bench::BenchmarkType, cmd::OverheadParams}, - storage::record::Stats, + shared::{Stats, UnderscoreHelper}, }; static VERSION: &'static str = env!("CARGO_PKG_VERSION"); @@ -85,7 +85,7 @@ impl TemplateData { pub fn write(&self, path: &Option) -> Result<()> { let mut handlebars = Handlebars::new(); // Format large integers with underscores. - handlebars.register_helper("underscore", Box::new(crate::writer::UnderscoreHelper)); + handlebars.register_helper("underscore", Box::new(UnderscoreHelper)); // Don't HTML escape any characters. handlebars.register_escape_fn(|s| -> String { s.to_string() }); diff --git a/utils/frame/benchmarking-cli/src/command.rs b/utils/frame/benchmarking-cli/src/pallet/command.rs similarity index 95% rename from utils/frame/benchmarking-cli/src/command.rs rename to utils/frame/benchmarking-cli/src/pallet/command.rs index 0ced8b28ce01..89b8d018bcb5 100644 --- a/utils/frame/benchmarking-cli/src/command.rs +++ b/utils/frame/benchmarking-cli/src/pallet/command.rs @@ -15,7 +15,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::BenchmarkCmd; +use super::{writer, PalletCmd}; use codec::{Decode, Encode}; use frame_benchmarking::{ Analysis, BenchmarkBatch, BenchmarkBatchSplitResults, BenchmarkList, BenchmarkParameter, @@ -87,7 +87,13 @@ fn combine_batches( .collect::>() } -impl BenchmarkCmd { +/// Explains possible reasons why the metadata for the benchmarking could not be found. +const ERROR_METADATA_NOT_FOUND: &'static str = "Did not find the benchmarking metadata. \ +This could mean that you either did not build the node correctly with the \ +`--features runtime-benchmarks` flag, or the chain spec that you are using was \ +not created by a node that was compiled with the flag"; + +impl PalletCmd { /// Runs the command and benchmarks the chain. pub fn run(&self, config: Configuration) -> Result<()> where @@ -165,7 +171,7 @@ impl BenchmarkCmd { sp_core::testing::TaskExecutor::new(), ) .execute(strategy.into()) - .map_err(|e| format!("Error getting benchmark list: {}", e))?; + .map_err(|e| format!("{}: {}", ERROR_METADATA_NOT_FOUND, e))?; let (list, storage_info) = <(Vec, Vec) as Decode>::decode(&mut &result[..]) @@ -359,7 +365,7 @@ impl BenchmarkCmd { // Create the weights.rs file. if let Some(output_path) = &self.output { - crate::writer::write_results(&batches, &storage_info, output_path, self)?; + writer::write_results(&batches, &storage_info, output_path, self)?; } // Jsonify the result and write it to a file or stdout if desired. @@ -414,11 +420,7 @@ impl BenchmarkCmd { if !self.no_storage_info { let mut comments: Vec = Default::default(); - crate::writer::add_storage_comments( - &mut comments, - &batch.db_results, - &storage_info, - ); + writer::add_storage_comments(&mut comments, &batch.db_results, &storage_info); println!("Raw Storage Info\n========"); for comment in comments { println!("{}", comment); @@ -469,7 +471,7 @@ impl BenchmarkCmd { } } -impl CliConfiguration for BenchmarkCmd { +impl CliConfiguration for PalletCmd { fn shared_params(&self) -> &SharedParams { &self.shared_params } diff --git a/utils/frame/benchmarking-cli/src/pallet/mod.rs b/utils/frame/benchmarking-cli/src/pallet/mod.rs new file mode 100644 index 000000000000..48ddcc7ce8ee --- /dev/null +++ b/utils/frame/benchmarking-cli/src/pallet/mod.rs @@ -0,0 +1,150 @@ +// This file is part of Substrate. + +// Copyright (C) 2020-2022 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. + +mod command; +mod writer; + +use sc_cli::{ExecutionStrategy, WasmExecutionMethod, DEFAULT_WASM_EXECUTION_METHOD}; +use std::{fmt::Debug, path::PathBuf}; + +// Add a more relaxed parsing for pallet names by allowing pallet directory names with `-` to be +// used like crate names with `_` +fn parse_pallet_name(pallet: &str) -> String { + pallet.replace("-", "_") +} + +/// Benchmark the extrinsic weight of FRAME Pallets. +#[derive(Debug, clap::Parser)] +pub struct PalletCmd { + /// Select a FRAME Pallet to benchmark, or `*` for all (in which case `extrinsic` must be `*`). + #[clap(short, long, parse(from_str = parse_pallet_name), required_unless_present = "list")] + pub pallet: Option, + + /// Select an extrinsic inside the pallet to benchmark, or `*` for all. + #[clap(short, long, required_unless_present = "list")] + pub extrinsic: Option, + + /// Select how many samples we should take across the variable components. + #[clap(short, long, default_value = "1")] + pub steps: u32, + + /// Indicates lowest values for each of the component ranges. + #[clap(long = "low", use_value_delimiter = true)] + pub lowest_range_values: Vec, + + /// Indicates highest values for each of the component ranges. + #[clap(long = "high", use_value_delimiter = true)] + pub highest_range_values: Vec, + + /// Select how many repetitions of this benchmark should run from within the wasm. + #[clap(short, long, default_value = "1")] + pub repeat: u32, + + /// Select how many repetitions of this benchmark should run from the client. + /// + /// NOTE: Using this alone may give slower results, but will afford you maximum Wasm memory. + #[clap(long, default_value = "1")] + pub external_repeat: u32, + + /// Print the raw results in JSON format. + #[clap(long = "json")] + pub json_output: bool, + + /// Write the raw results in JSON format into the given file. + #[clap(long, conflicts_with = "json-output")] + pub json_file: Option, + + /// Don't print the median-slopes linear regression analysis. + #[clap(long)] + pub no_median_slopes: bool, + + /// Don't print the min-squares linear regression analysis. + #[clap(long)] + pub no_min_squares: bool, + + /// Output the benchmarks to a Rust file at the given path. + #[clap(long)] + pub output: Option, + + /// Add a header file to your outputted benchmarks. + #[clap(long)] + pub header: Option, + + /// Path to Handlebars template file used for outputting benchmark results. (Optional) + #[clap(long)] + pub template: Option, + + /// Which analysis function to use when outputting benchmarks: + /// * min-squares (default) + /// * median-slopes + /// * max (max of min squares and median slopes for each value) + #[clap(long)] + pub output_analysis: Option, + + /// Set the heap pages while running benchmarks. If not set, the default value from the client + /// is used. + #[clap(long)] + pub heap_pages: Option, + + /// Disable verification logic when running benchmarks. + #[clap(long)] + pub no_verify: bool, + + /// Display and run extra benchmarks that would otherwise not be needed for weight + /// construction. + #[clap(long)] + pub extra: bool, + + /// Estimate PoV size. + #[clap(long)] + pub record_proof: bool, + + #[allow(missing_docs)] + #[clap(flatten)] + pub shared_params: sc_cli::SharedParams, + + /// The execution strategy that should be used for benchmarks. + #[clap(long, value_name = "STRATEGY", arg_enum, ignore_case = true)] + pub execution: Option, + + /// Method for executing Wasm runtime code. + #[clap( + long = "wasm-execution", + value_name = "METHOD", + possible_values = WasmExecutionMethod::variants(), + ignore_case = true, + default_value = DEFAULT_WASM_EXECUTION_METHOD, + )] + pub wasm_method: WasmExecutionMethod, + + /// Limit the memory the database cache can use. + #[clap(long = "db-cache", value_name = "MiB", default_value = "1024")] + pub database_cache_size: u32, + + /// List the benchmarks that match your query rather than running them. + /// + /// When nothing is provided, we list all benchmarks. + #[clap(long)] + pub list: bool, + + /// If enabled, the storage info is not displayed in the output next to the analysis. + /// + /// This is independent of the storage info appearing in the *output file*. Use a Handlebar + /// template for that purpose. + #[clap(long)] + pub no_storage_info: bool, +} diff --git a/utils/frame/benchmarking-cli/src/template.hbs b/utils/frame/benchmarking-cli/src/pallet/template.hbs similarity index 100% rename from utils/frame/benchmarking-cli/src/template.hbs rename to utils/frame/benchmarking-cli/src/pallet/template.hbs diff --git a/utils/frame/benchmarking-cli/src/writer.rs b/utils/frame/benchmarking-cli/src/pallet/writer.rs similarity index 93% rename from utils/frame/benchmarking-cli/src/writer.rs rename to utils/frame/benchmarking-cli/src/pallet/writer.rs index 17f1221e46d8..cd97b3efbd9d 100644 --- a/utils/frame/benchmarking-cli/src/writer.rs +++ b/utils/frame/benchmarking-cli/src/pallet/writer.rs @@ -26,7 +26,7 @@ use std::{ use inflector::Inflector; use serde::Serialize; -use crate::BenchmarkCmd; +use crate::{shared::UnderscoreHelper, PalletCmd}; use frame_benchmarking::{ Analysis, AnalysisChoice, BenchmarkBatchSplitResults, BenchmarkResult, BenchmarkSelector, RegressionModel, @@ -68,7 +68,7 @@ struct BenchmarkData { comments: Vec, } -// This forwards some specific metadata from the `BenchmarkCmd` +// This forwards some specific metadata from the `PalletCmd` #[derive(Serialize, Default, Debug, Clone)] struct CmdData { steps: u32, @@ -255,7 +255,7 @@ pub fn write_results( batches: &[BenchmarkBatchSplitResults], storage_info: &[StorageInfo], path: &PathBuf, - cmd: &BenchmarkCmd, + cmd: &PalletCmd, ) -> Result<(), std::io::Error> { // Use custom template if provided. let template: String = match &cmd.template { @@ -416,44 +416,6 @@ pub(crate) fn add_storage_comments( } } -// Add an underscore after every 3rd character, i.e. a separator for large numbers. -fn underscore(i: Number) -> String -where - Number: std::string::ToString, -{ - let mut s = String::new(); - let i_str = i.to_string(); - let a = i_str.chars().rev().enumerate(); - for (idx, val) in a { - if idx != 0 && idx % 3 == 0 { - s.insert(0, '_'); - } - s.insert(0, val); - } - s -} - -// A Handlebars helper to add an underscore after every 3rd character, -// i.e. a separator for large numbers. -#[derive(Clone, Copy)] -pub(crate) struct UnderscoreHelper; -impl handlebars::HelperDef for UnderscoreHelper { - fn call<'reg: 'rc, 'rc>( - &self, - h: &handlebars::Helper, - _: &handlebars::Handlebars, - _: &handlebars::Context, - _rc: &mut handlebars::RenderContext, - out: &mut dyn handlebars::Output, - ) -> handlebars::HelperResult { - use handlebars::JsonRender; - let param = h.param(0).unwrap(); - let underscore_param = underscore(param.value().render()); - out.write(&underscore_param)?; - Ok(()) - } -} - // A helper to join a string of vectors. #[derive(Clone, Copy)] struct JoinHelper; diff --git a/utils/frame/benchmarking-cli/src/shared/mod.rs b/utils/frame/benchmarking-cli/src/shared/mod.rs new file mode 100644 index 000000000000..f08d79b9aafc --- /dev/null +++ b/utils/frame/benchmarking-cli/src/shared/mod.rs @@ -0,0 +1,65 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +//! Code that is shared among all benchmarking sub-commands. + +pub mod record; +pub mod stats; +pub mod weight_params; + +pub use record::BenchRecord; +pub use stats::{StatSelect, Stats}; +pub use weight_params::WeightParams; + +/// A Handlebars helper to add an underscore after every 3rd character, +/// i.e. a separator for large numbers. +#[derive(Clone, Copy)] +pub struct UnderscoreHelper; + +impl handlebars::HelperDef for UnderscoreHelper { + fn call<'reg: 'rc, 'rc>( + &self, + h: &handlebars::Helper, + _: &handlebars::Handlebars, + _: &handlebars::Context, + _rc: &mut handlebars::RenderContext, + out: &mut dyn handlebars::Output, + ) -> handlebars::HelperResult { + use handlebars::JsonRender; + let param = h.param(0).unwrap(); + let underscore_param = underscore(param.value().render()); + out.write(&underscore_param)?; + Ok(()) + } +} + +/// Add an underscore after every 3rd character, i.e. a separator for large numbers. +fn underscore(i: Number) -> String +where + Number: std::string::ToString, +{ + let mut s = String::new(); + let i_str = i.to_string(); + let a = i_str.chars().rev().enumerate(); + for (idx, val) in a { + if idx != 0 && idx % 3 == 0 { + s.insert(0, '_'); + } + s.insert(0, val); + } + s +} diff --git a/utils/frame/benchmarking-cli/src/shared/record.rs b/utils/frame/benchmarking-cli/src/shared/record.rs new file mode 100644 index 000000000000..79ab37f65152 --- /dev/null +++ b/utils/frame/benchmarking-cli/src/shared/record.rs @@ -0,0 +1,72 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 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. + +//! Defines the [`BenchRecord`] and its facilities for computing [`super::Stats`]. + +use sc_cli::Result; +use sc_service::Configuration; + +use log::info; +use serde::Serialize; +use std::{fs, path::PathBuf, time::Duration}; + +use super::Stats; + +/// Raw output of a Storage benchmark. +#[derive(Debug, Default, Clone, Serialize)] +pub struct BenchRecord { + /// Multi-Map of value sizes and the time that it took to access them. + ns_per_size: Vec<(u64, u64)>, +} + +impl BenchRecord { + /// Appends a new record. Uses safe casts. + pub fn append(&mut self, size: usize, d: Duration) -> Result<()> { + let size: u64 = size.try_into().map_err(|e| format!("Size overflow u64: {}", e))?; + let ns: u64 = d + .as_nanos() + .try_into() + .map_err(|e| format!("Nanoseconds overflow u64: {}", e))?; + self.ns_per_size.push((size, ns)); + Ok(()) + } + + /// Returns the statistics for *time* and *value size*. + pub fn calculate_stats(self) -> Result<(Stats, Stats)> { + let (size, time): (Vec<_>, Vec<_>) = self.ns_per_size.into_iter().unzip(); + let size = Stats::new(&size)?; + let time = Stats::new(&time)?; + Ok((time, size)) // The swap of time/size here is intentional. + } + + /// Unless a path is specified, saves the raw results in a json file in the current directory. + /// Prefixes it with the DB name and suffixed with `path_suffix`. + pub fn save_json(&self, cfg: &Configuration, out_path: &PathBuf, suffix: &str) -> Result<()> { + let mut path = PathBuf::from(out_path); + if path.is_dir() || path.as_os_str().is_empty() { + path.push(&format!("{}_{}", cfg.database, suffix).to_lowercase()); + path.set_extension("json"); + } + + let json = serde_json::to_string_pretty(&self) + .map_err(|e| format!("Serializing as JSON: {:?}", e))?; + + fs::write(&path, json)?; + info!("Raw data written to {:?}", fs::canonicalize(&path)?); + Ok(()) + } +} diff --git a/utils/frame/benchmarking-cli/src/storage/record.rs b/utils/frame/benchmarking-cli/src/shared/stats.rs similarity index 70% rename from utils/frame/benchmarking-cli/src/storage/record.rs rename to utils/frame/benchmarking-cli/src/shared/stats.rs index 530fa4cdfe96..7785965fed4a 100644 --- a/utils/frame/benchmarking-cli/src/storage/record.rs +++ b/utils/frame/benchmarking-cli/src/shared/stats.rs @@ -15,46 +15,38 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Calculates statistics and fills out the `weight.hbs` template. +//! Handles statistics that were generated from benchmarking results and +//! that can be used to fill out weight templates. use sc_cli::Result; -use sc_service::Configuration; -use log::info; use serde::Serialize; -use std::{fmt, fs, path::PathBuf, result, str::FromStr, time::Duration}; - -/// Raw output of a Storage benchmark. -#[derive(Debug, Default, Clone, Serialize)] -pub(crate) struct BenchRecord { - /// Multi-Map of value sizes and the time that it took to access them. - ns_per_size: Vec<(u64, u64)>, -} +use std::{fmt, result, str::FromStr}; /// Various statistics that help to gauge the quality of the produced weights. /// Will be written to the weight file and printed to console. #[derive(Serialize, Default, Clone)] -pub(crate) struct Stats { +pub struct Stats { /// Sum of all values. - pub(crate) sum: u64, + pub sum: u64, /// Minimal observed value. - pub(crate) min: u64, + pub min: u64, /// Maximal observed value. - pub(crate) max: u64, + pub max: u64, /// Average of all values. - pub(crate) avg: u64, + pub avg: u64, /// Median of all values. - pub(crate) median: u64, + pub median: u64, /// Standard derivation of all values. - pub(crate) stddev: f64, + pub stddev: f64, /// 99th percentile. At least 99% of all values are below this threshold. - pub(crate) p99: u64, + pub p99: u64, /// 95th percentile. At least 95% of all values are below this threshold. - pub(crate) p95: u64, + pub p95: u64, /// 75th percentile. At least 75% of all values are below this threshold. - pub(crate) p75: u64, + pub p75: u64, } /// Selects a specific field from a [`Stats`] object. @@ -75,44 +67,6 @@ pub enum StatSelect { P75Percentile, } -impl BenchRecord { - /// Appends a new record. Uses safe casts. - pub fn append(&mut self, size: usize, d: Duration) -> Result<()> { - let size: u64 = size.try_into().map_err(|e| format!("Size overflow u64: {}", e))?; - let ns: u64 = d - .as_nanos() - .try_into() - .map_err(|e| format!("Nanoseconds overflow u64: {}", e))?; - self.ns_per_size.push((size, ns)); - Ok(()) - } - - /// Returns the statistics for *time* and *value size*. - pub(crate) fn calculate_stats(self) -> Result<(Stats, Stats)> { - let (size, time): (Vec<_>, Vec<_>) = self.ns_per_size.into_iter().unzip(); - let size = Stats::new(&size)?; - let time = Stats::new(&time)?; - Ok((time, size)) // The swap of time/size here is intentional. - } - - /// Unless a path is specified, saves the raw results in a json file in the current directory. - /// Prefixes it with the DB name and suffixed with `path_suffix`. - pub fn save_json(&self, cfg: &Configuration, out_path: &PathBuf, suffix: &str) -> Result<()> { - let mut path = PathBuf::from(out_path); - if path.is_dir() || path.as_os_str().is_empty() { - path.push(&format!("{}_{}", cfg.database, suffix).to_lowercase()); - path.set_extension("json"); - } - - let json = serde_json::to_string_pretty(&self) - .map_err(|e| format!("Serializing as JSON: {:?}", e))?; - - fs::write(&path, json)?; - info!("Raw data written to {:?}", fs::canonicalize(&path)?); - Ok(()) - } -} - impl Stats { /// Calculates statistics and returns them. pub fn new(xs: &Vec) -> Result { @@ -137,7 +91,7 @@ impl Stats { } /// Returns the selected stat. - pub(crate) fn select(&self, s: StatSelect) -> u64 { + pub fn select(&self, s: StatSelect) -> u64 { match s { StatSelect::Maximum => self.max, StatSelect::Average => self.avg, diff --git a/utils/frame/benchmarking-cli/src/post_processing/mod.rs b/utils/frame/benchmarking-cli/src/shared/weight_params.rs similarity index 92% rename from utils/frame/benchmarking-cli/src/post_processing/mod.rs rename to utils/frame/benchmarking-cli/src/shared/weight_params.rs index fb20d9bd0c48..4dd80cd41ff3 100644 --- a/utils/frame/benchmarking-cli/src/post_processing/mod.rs +++ b/utils/frame/benchmarking-cli/src/shared/weight_params.rs @@ -15,7 +15,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Calculates a weight from the statistics of a benchmark result. +//! Calculates a weight from the [`super::Stats`] of a benchmark result. use sc_cli::Result; @@ -23,7 +23,7 @@ use clap::Args; use serde::Serialize; use std::path::PathBuf; -use crate::storage::record::{StatSelect, Stats}; +use super::{StatSelect, Stats}; /// Configures the weight generation. #[derive(Debug, Default, Serialize, Clone, PartialEq, Args)] @@ -55,7 +55,7 @@ pub struct WeightParams { /// `weight_mul` and adding `weight_add`. /// Does not use safe casts and can overflow. impl WeightParams { - pub(crate) fn calc_weight(&self, stat: &Stats) -> Result { + pub fn calc_weight(&self, stat: &Stats) -> Result { if self.weight_mul.is_sign_negative() || !self.weight_mul.is_normal() { return Err("invalid floating number for `weight_mul`".into()) } @@ -68,7 +68,7 @@ impl WeightParams { #[cfg(test)] mod test_weight_params { use super::WeightParams; - use crate::storage::record::{StatSelect, Stats}; + use crate::shared::{StatSelect, Stats}; #[test] fn calc_weight_works() { diff --git a/utils/frame/benchmarking-cli/src/storage/cmd.rs b/utils/frame/benchmarking-cli/src/storage/cmd.rs index c38e6636e5a3..c2cc219ef152 100644 --- a/utils/frame/benchmarking-cli/src/storage/cmd.rs +++ b/utils/frame/benchmarking-cli/src/storage/cmd.rs @@ -34,8 +34,9 @@ use sp_runtime::generic::BlockId; use std::{fmt::Debug, path::PathBuf, sync::Arc}; use super::template::TemplateData; -use crate::post_processing::WeightParams; -/// Benchmark the storage of a Substrate node with a live chain snapshot. +use crate::shared::WeightParams; + +/// Benchmark the storage speed of a chain snapshot. #[derive(Debug, Parser)] pub struct StorageCmd { #[allow(missing_docs)] @@ -99,7 +100,7 @@ pub struct StorageParams { impl StorageCmd { /// Calls into the Read and Write benchmarking functions. /// Processes the output and writes it into files and stdout. - pub async fn run( + pub fn run( &self, cfg: Configuration, client: Arc, diff --git a/utils/frame/benchmarking-cli/src/storage/mod.rs b/utils/frame/benchmarking-cli/src/storage/mod.rs index 9849cbcb6097..0c722fdd4702 100644 --- a/utils/frame/benchmarking-cli/src/storage/mod.rs +++ b/utils/frame/benchmarking-cli/src/storage/mod.rs @@ -17,7 +17,6 @@ pub mod cmd; pub mod read; -pub mod record; pub mod template; pub mod write; diff --git a/utils/frame/benchmarking-cli/src/storage/read.rs b/utils/frame/benchmarking-cli/src/storage/read.rs index ca506202e106..f58f3c3de0c1 100644 --- a/utils/frame/benchmarking-cli/src/storage/read.rs +++ b/utils/frame/benchmarking-cli/src/storage/read.rs @@ -27,7 +27,8 @@ use log::info; use rand::prelude::*; use std::{fmt::Debug, sync::Arc, time::Instant}; -use super::{cmd::StorageCmd, record::BenchRecord}; +use super::cmd::StorageCmd; +use crate::shared::BenchRecord; impl StorageCmd { /// Benchmarks the time it takes to read a single Storage item. diff --git a/utils/frame/benchmarking-cli/src/storage/template.rs b/utils/frame/benchmarking-cli/src/storage/template.rs index 10e6902b934b..26aa8a962301 100644 --- a/utils/frame/benchmarking-cli/src/storage/template.rs +++ b/utils/frame/benchmarking-cli/src/storage/template.rs @@ -22,7 +22,8 @@ use log::info; use serde::Serialize; use std::{env, fs, path::PathBuf}; -use super::{cmd::StorageParams, record::Stats}; +use super::cmd::StorageParams; +use crate::shared::{Stats, UnderscoreHelper}; static VERSION: &'static str = env!("CARGO_PKG_VERSION"); static TEMPLATE: &str = include_str!("./weights.hbs"); @@ -97,7 +98,7 @@ impl TemplateData { pub fn write(&self, path: &Option, hbs_template: &Option) -> Result<()> { let mut handlebars = handlebars::Handlebars::new(); // Format large integers with underscore. - handlebars.register_helper("underscore", Box::new(crate::writer::UnderscoreHelper)); + handlebars.register_helper("underscore", Box::new(UnderscoreHelper)); // Don't HTML escape any characters. handlebars.register_escape_fn(|s| -> String { s.to_string() }); // Use custom template if provided. diff --git a/utils/frame/benchmarking-cli/src/storage/write.rs b/utils/frame/benchmarking-cli/src/storage/write.rs index 94a0eea9728f..d5d5bc2fffa5 100644 --- a/utils/frame/benchmarking-cli/src/storage/write.rs +++ b/utils/frame/benchmarking-cli/src/storage/write.rs @@ -31,7 +31,8 @@ use log::{info, trace}; use rand::prelude::*; use std::{fmt::Debug, sync::Arc, time::Instant}; -use super::{cmd::StorageCmd, record::BenchRecord}; +use super::cmd::StorageCmd; +use crate::shared::BenchRecord; impl StorageCmd { /// Benchmarks the time it takes to write a single Storage item. From 78b1ad3c754514135bc0026407f7d2bf3bacae27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Paulo=20Silva=20de=20Souza?= <77391175+joao-paulo-parity@users.noreply.github.com> Date: Fri, 8 Apr 2022 04:38:51 -0300 Subject: [PATCH 688/695] fix .github/pr-custom-review.yml (#11187) --- .github/pr-custom-review.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/pr-custom-review.yml b/.github/pr-custom-review.yml index 7ce8146571cd..518faf15a611 100644 --- a/.github/pr-custom-review.yml +++ b/.github/pr-custom-review.yml @@ -11,6 +11,6 @@ rules: teams: - core-devs -prevent_review_request: +prevent-review-request: teams: - core-devs From 1e3b992499de49b91403dbd1e4a7ba76552e89d1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Apr 2022 10:41:21 +0200 Subject: [PATCH 689/695] Bump impl-trait-for-tuples from 0.2.1 to 0.2.2 (#11171) Bumps [impl-trait-for-tuples](https://github.com/bkchr/impl-trait-for-tuples) from 0.2.1 to 0.2.2. - [Release notes](https://github.com/bkchr/impl-trait-for-tuples/releases) - [Commits](https://github.com/bkchr/impl-trait-for-tuples/compare/v0.2.1...v0.2.2) --- updated-dependencies: - dependency-name: impl-trait-for-tuples dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- client/chain-spec/Cargo.toml | 2 +- frame/authorship/Cargo.toml | 2 +- frame/session/Cargo.toml | 2 +- frame/support/Cargo.toml | 2 +- frame/treasury/Cargo.toml | 2 +- primitives/inherents/Cargo.toml | 2 +- primitives/runtime-interface/Cargo.toml | 2 +- primitives/runtime/Cargo.toml | 2 +- primitives/wasm-interface/Cargo.toml | 2 +- 10 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1ecb25b7b4b1..8c9227ea80ef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3168,9 +3168,9 @@ dependencies = [ [[package]] name = "impl-trait-for-tuples" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5dacb10c5b3bb92d46ba347505a9041e676bb20ad220101326bffb0c93031ee" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" dependencies = [ "proc-macro2", "quote", diff --git a/client/chain-spec/Cargo.toml b/client/chain-spec/Cargo.toml index e18f9b72c75e..bd19fd59d699 100644 --- a/client/chain-spec/Cargo.toml +++ b/client/chain-spec/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sc-chain-spec-derive = { version = "4.0.0-dev", path = "./derive" } -impl-trait-for-tuples = "0.2.1" +impl-trait-for-tuples = "0.2.2" sc-network = { version = "0.10.0-dev", path = "../network" } sp-core = { version = "6.0.0", path = "../../primitives/core" } serde = { version = "1.0.136", features = ["derive"] } diff --git a/frame/authorship/Cargo.toml b/frame/authorship/Cargo.toml index 77a44f5b5dd7..4557ee65f1a6 100644 --- a/frame/authorship/Cargo.toml +++ b/frame/authorship/Cargo.toml @@ -22,7 +22,7 @@ sp-std = { version = "4.0.0", default-features = false, path = "../../primitives sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } -impl-trait-for-tuples = "0.2.1" +impl-trait-for-tuples = "0.2.2" [dev-dependencies] sp-core = { version = "6.0.0", path = "../../primitives/core" } diff --git a/frame/session/Cargo.toml b/frame/session/Cargo.toml index 647b3482b202..28f2df47027b 100644 --- a/frame/session/Cargo.toml +++ b/frame/session/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] log = { version = "0.4.0", default-features = false } -impl-trait-for-tuples = "0.2.1" +impl-trait-for-tuples = "0.2.2" codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } diff --git a/frame/support/Cargo.toml b/frame/support/Cargo.toml index 3161e4f4db69..ec596494c601 100644 --- a/frame/support/Cargo.toml +++ b/frame/support/Cargo.toml @@ -31,7 +31,7 @@ paste = "1.0" once_cell = { version = "1", default-features = false, optional = true } sp-state-machine = { version = "0.12.0", optional = true, path = "../../primitives/state-machine" } bitflags = "1.3" -impl-trait-for-tuples = "0.2.1" +impl-trait-for-tuples = "0.2.2" smallvec = "1.8.0" log = { version = "0.4.14", default-features = false } sp-core-hashing-proc-macro = { version = "5.0.0", path = "../../primitives/core/hashing/proc-macro" } diff --git a/frame/treasury/Cargo.toml b/frame/treasury/Cargo.toml index f848f48acd25..85745c6c99fd 100644 --- a/frame/treasury/Cargo.toml +++ b/frame/treasury/Cargo.toml @@ -19,7 +19,7 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = ] } scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } serde = { version = "1.0.136", features = ["derive"], optional = true } -impl-trait-for-tuples = "0.2.1" +impl-trait-for-tuples = "0.2.2" sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } diff --git a/primitives/inherents/Cargo.toml b/primitives/inherents/Cargo.toml index f7beb7bdfcf5..0e701a397d7d 100644 --- a/primitives/inherents/Cargo.toml +++ b/primitives/inherents/Cargo.toml @@ -20,7 +20,7 @@ sp-core = { version = "6.0.0", default-features = false, path = "../core" } sp-runtime = { version = "6.0.0", path = "../runtime", optional = true } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } thiserror = { version = "1.0.30", optional = true } -impl-trait-for-tuples = "0.2.0" +impl-trait-for-tuples = "0.2.2" async-trait = { version = "0.1.50", optional = true } [dev-dependencies] diff --git a/primitives/runtime-interface/Cargo.toml b/primitives/runtime-interface/Cargo.toml index 883ea28e5e88..102592288af1 100644 --- a/primitives/runtime-interface/Cargo.toml +++ b/primitives/runtime-interface/Cargo.toml @@ -23,7 +23,7 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = static_assertions = "1.0.0" primitive-types = { version = "0.11.1", default-features = false } sp-storage = { version = "6.0.0", default-features = false, path = "../storage" } -impl-trait-for-tuples = "0.2.1" +impl-trait-for-tuples = "0.2.2" [dev-dependencies] sp-runtime-interface-test-wasm = { version = "2.0.0", path = "test-wasm" } diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index a0acdaf27dc5..22d2ea62ae45 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -26,7 +26,7 @@ sp-io = { version = "6.0.0", default-features = false, path = "../io" } log = { version = "0.4.14", default-features = false } paste = "1.0" rand = { version = "0.7.2", optional = true } -impl-trait-for-tuples = "0.2.1" +impl-trait-for-tuples = "0.2.2" parity-util-mem = { version = "0.11.0", default-features = false, features = ["primitive-types"] } hash256-std-hasher = { version = "0.15.2", default-features = false } either = { version = "1.5", default-features = false } diff --git a/primitives/wasm-interface/Cargo.toml b/primitives/wasm-interface/Cargo.toml index fa6c5ede1854..5fa0627490a2 100644 --- a/primitives/wasm-interface/Cargo.toml +++ b/primitives/wasm-interface/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] wasmi = { version = "0.9.1", optional = true } wasmtime = { version = "0.33.0", optional = true, default-features = false } log = { version = "0.4.14", optional = true } -impl-trait-for-tuples = "0.2.1" +impl-trait-for-tuples = "0.2.2" sp-std = { version = "4.0.0", path = "../std", default-features = false } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } From 2cdd27dda74f44f7a5ba4fa1a0be5982fb7ae528 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Apr 2022 10:18:25 +0000 Subject: [PATCH 690/695] Bump lru from 0.7.3 to 0.7.5 (#11190) Bumps [lru](https://github.com/jeromefroe/lru-rs) from 0.7.3 to 0.7.5. - [Release notes](https://github.com/jeromefroe/lru-rs/releases) - [Changelog](https://github.com/jeromefroe/lru-rs/blob/master/CHANGELOG.md) - [Commits](https://github.com/jeromefroe/lru-rs/compare/0.7.3...0.7.5) --- updated-dependencies: - dependency-name: lru dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 14 +++++++------- client/executor/Cargo.toml | 2 +- client/network-gossip/Cargo.toml | 2 +- client/network/Cargo.toml | 2 +- primitives/blockchain/Cargo.toml | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8c9227ea80ef..c64800e00233 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4036,7 +4036,7 @@ dependencies = [ "libp2p-core", "libp2p-swarm", "log 0.4.14", - "lru 0.7.3", + "lru 0.7.5", "rand 0.7.3", "smallvec 1.8.0", "unsigned-varint 0.7.0", @@ -4336,9 +4336,9 @@ dependencies = [ [[package]] name = "lru" -version = "0.7.3" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb87f3080f6d1d69e8c564c0fcfde1d7aa8cc451ce40cae89479111f03bc0eb" +checksum = "32613e41de4c47ab04970c348ca7ae7382cf116625755af070b008a15516a889" dependencies = [ "hashbrown 0.11.2", ] @@ -8532,7 +8532,7 @@ dependencies = [ "env_logger 0.9.0", "hex-literal", "lazy_static", - "lru 0.7.3", + "lru 0.7.5", "parity-scale-codec", "parking_lot 0.12.0", "paste 1.0.6", @@ -8742,7 +8742,7 @@ dependencies = [ "linked-hash-map", "linked_hash_set", "log 0.4.14", - "lru 0.7.3", + "lru 0.7.5", "parity-scale-codec", "parking_lot 0.12.0", "pin-project 1.0.10", @@ -8786,7 +8786,7 @@ dependencies = [ "futures-timer", "libp2p", "log 0.4.14", - "lru 0.7.3", + "lru 0.7.5", "quickcheck", "sc-network", "sp-runtime", @@ -9860,7 +9860,7 @@ version = "4.0.0-dev" dependencies = [ "futures 0.3.21", "log 0.4.14", - "lru 0.7.3", + "lru 0.7.5", "parity-scale-codec", "parking_lot 0.12.0", "sp-api", diff --git a/client/executor/Cargo.toml b/client/executor/Cargo.toml index 34416b1e0d46..8e10de1b04a9 100644 --- a/client/executor/Cargo.toml +++ b/client/executor/Cargo.toml @@ -32,7 +32,7 @@ sc-executor-wasmi = { version = "0.10.0-dev", path = "wasmi" } sc-executor-wasmtime = { version = "0.10.0-dev", path = "wasmtime", optional = true } parking_lot = "0.12.0" sp-core-hashing-proc-macro = { version = "5.0.0", path = "../../primitives/core/hashing/proc-macro" } -lru = "0.7.3" +lru = "0.7.5" tracing = "0.1.29" [dev-dependencies] diff --git a/client/network-gossip/Cargo.toml b/client/network-gossip/Cargo.toml index 51f5b658402e..9854575ab6b0 100644 --- a/client/network-gossip/Cargo.toml +++ b/client/network-gossip/Cargo.toml @@ -19,7 +19,7 @@ futures = "0.3.21" futures-timer = "3.0.1" libp2p = { version = "0.40.0", default-features = false } log = "0.4.8" -lru = "0.7.3" +lru = "0.7.5" ahash = "0.7.6" prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.10.0-dev", path = "../../utils/prometheus" } sc-network = { version = "0.10.0-dev", path = "../network" } diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index be69663b9a54..6d70d41964de 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -34,7 +34,7 @@ hex = "0.4.0" ip_network = "0.4.1" linked-hash-map = "0.5.4" linked_hash_set = "0.1.3" -lru = "0.7.3" +lru = "0.7.5" log = "0.4.8" parking_lot = "0.12.0" pin-project = "1.0.10" diff --git a/primitives/blockchain/Cargo.toml b/primitives/blockchain/Cargo.toml index a79bc9c5591c..c6fcdd3cb1c0 100644 --- a/primitives/blockchain/Cargo.toml +++ b/primitives/blockchain/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] log = "0.4.11" -lru = "0.7.3" +lru = "0.7.5" parking_lot = "0.12.0" thiserror = "1.0.30" futures = "0.3.21" From 994bb57b77b2845e9e1b48d8eb77c9160366d525 Mon Sep 17 00:00:00 2001 From: Koute Date: Fri, 8 Apr 2022 20:26:47 +0900 Subject: [PATCH 691/695] Catch panics on the FFI boundary between the runtime and the host for `wasmtime` (#11189) * Catch panics on the FFI boundary between the runtime and the host for `wasmtime` * Use an already existing test runtime function * Merge the tests together --- client/executor/runtime-test/src/lib.rs | 4 ++- client/executor/src/integration_tests/mod.rs | 19 +++++++++++--- .../host_function_interface.rs | 26 +++++++++++++++---- 3 files changed, 39 insertions(+), 10 deletions(-) diff --git a/client/executor/runtime-test/src/lib.rs b/client/executor/runtime-test/src/lib.rs index bf9f76edd945..0c61d6fcd38a 100644 --- a/client/executor/runtime-test/src/lib.rs +++ b/client/executor/runtime-test/src/lib.rs @@ -113,7 +113,9 @@ sp_core::wasm_export_functions! { } } - fn test_exhaust_heap() -> Vec { Vec::with_capacity(16777216) } + fn test_allocate_vec(size: u32) -> Vec { + Vec::with_capacity(size as usize) + } fn test_fp_f32add(a: [u8; 4], b: [u8; 4]) -> [u8; 4] { let a = f32::from_le_bytes(a); diff --git a/client/executor/src/integration_tests/mod.rs b/client/executor/src/integration_tests/mod.rs index 462a8ba1b876..75b458a399e3 100644 --- a/client/executor/src/integration_tests/mod.rs +++ b/client/executor/src/integration_tests/mod.rs @@ -466,13 +466,24 @@ fn should_trap_when_heap_exhausted(wasm_method: WasmExecutionMethod) { RuntimeBlob::uncompress_if_needed(wasm_binary_unwrap()).unwrap(), &mut ext.ext(), true, - "test_exhaust_heap", - &[0], + "test_allocate_vec", + &16777216_u32.encode(), ) - .map_err(|e| e.to_string()) .unwrap_err(); - assert!(err.contains("Allocator ran out of space")); + match err { + #[cfg(feature = "wasmtime")] + Error::AbortedDueToTrap(error) if wasm_method == WasmExecutionMethod::Compiled => { + assert_eq!( + error.message, + r#"host code panicked while being called by the runtime: Failed to allocate memory: "Allocator ran out of space""# + ); + }, + Error::RuntimePanicked(error) if wasm_method == WasmExecutionMethod::Interpreted => { + assert_eq!(error, r#"Failed to allocate memory: "Allocator ran out of space""#); + }, + error => panic!("unexpected error: {:?}", error), + } } fn mk_test_runtime(wasm_method: WasmExecutionMethod, pages: u64) -> Arc { diff --git a/primitives/runtime-interface/proc-macro/src/runtime_interface/host_function_interface.rs b/primitives/runtime-interface/proc-macro/src/runtime_interface/host_function_interface.rs index 1566bbf302c3..03da0bed5981 100644 --- a/primitives/runtime-interface/proc-macro/src/runtime_interface/host_function_interface.rs +++ b/primitives/runtime-interface/proc-macro/src/runtime_interface/host_function_interface.rs @@ -374,11 +374,27 @@ fn generate_host_function_implementation( -> std::result::Result<#ffi_return_ty, #crate_::sp_wasm_interface::wasmtime::Trap> { T::with_function_context(caller, move |__function_context__| { - #struct_name::call( - __function_context__, - #(#ffi_names,)* - ) - }).map_err(#crate_::sp_wasm_interface::wasmtime::Trap::new) + let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { + #struct_name::call( + __function_context__, + #(#ffi_names,)* + ).map_err(#crate_::sp_wasm_interface::wasmtime::Trap::new) + })); + match result { + Ok(result) => result, + Err(panic) => { + let message = + if let Some(message) = panic.downcast_ref::() { + format!("host code panicked while being called by the runtime: {}", message) + } else if let Some(message) = panic.downcast_ref::<&'static str>() { + format!("host code panicked while being called by the runtime: {}", message) + } else { + "host code panicked while being called by the runtime".to_owned() + }; + return Err(#crate_::sp_wasm_interface::wasmtime::Trap::new(message)); + } + } + }) } )?; }; From 87ebfdbcf8242c04856e3881a78ea0bc369d77a2 Mon Sep 17 00:00:00 2001 From: Sergejs Kostjucenko <85877331+sergejparity@users.noreply.github.com> Date: Fri, 8 Apr 2022 18:39:10 +0300 Subject: [PATCH 692/695] Add GHA for custom PR review (#10951) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add GHA for custom PR review * Change FILES rule settings * Update rules according to feedback * Update .github/pr-custom-review.yml Co-authored-by: Denis Pisarev <17856421+TriplEight@users.noreply.github.com> * CI: PRCR new 🔒 team is locks-review * CI: rename a confusing step * Update .github/workflows/pr-custom-review.yml Co-authored-by: João Paulo Silva de Souza <77391175+joao-paulo-parity@users.noreply.github.com> * CI: use a proper new team for as per discussion with @drahnr it was decided to create a dedicated team for reviewing runtime files * Update pr-custom-review.yml * Update .github/workflows/pr-custom-review.yml Co-authored-by: João Paulo Silva de Souza <77391175+joao-paulo-parity@users.noreply.github.com> * Update .github/workflows/pr-custom-review.yml Co-authored-by: João Paulo Silva de Souza <77391175+joao-paulo-parity@users.noreply.github.com> Co-authored-by: Denis Pisarev <17856421+TriplEight@users.noreply.github.com> Co-authored-by: TriplEight Co-authored-by: Denis Pisarev Co-authored-by: João Paulo Silva de Souza <77391175+joao-paulo-parity@users.noreply.github.com> --- .github/workflows/pr-custom-review.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/pr-custom-review.yml diff --git a/.github/workflows/pr-custom-review.yml b/.github/workflows/pr-custom-review.yml new file mode 100644 index 000000000000..d113d3906784 --- /dev/null +++ b/.github/workflows/pr-custom-review.yml @@ -0,0 +1,23 @@ +name: Check reviews + +on: + pull_request: + branches: + - master + - main + types: + - opened + - reopened + - synchronize + - review_requested + - review_request_removed + pull_request_review: + +jobs: + pr-custom-review: + runs-on: ubuntu-latest + steps: + - name: pr-custom-review + uses: paritytech/pr-custom-review@v2 + with: + token: ${{ secrets.PRCR_TOKEN }} From 9097a6bb67810ae8a7b8820463af98c96ec38348 Mon Sep 17 00:00:00 2001 From: driemworks Date: Tue, 12 Apr 2022 20:11:41 -0500 Subject: [PATCH 693/695] add back contracts pallet --- .maintain/Dockerfile | 11 -- bin/node-template/node/src/rpc.rs | 5 +- bin/node-template/runtime/src/lib.rs | 174 +++++++++++++++------------ 3 files changed, 96 insertions(+), 94 deletions(-) diff --git a/.maintain/Dockerfile b/.maintain/Dockerfile index 66bfb1652e5d..e3e6f9118f61 100644 --- a/.maintain/Dockerfile +++ b/.maintain/Dockerfile @@ -40,7 +40,6 @@ RUN mv /usr/share/ca* /tmp && \ COPY --from=builder /substrate/target/$PROFILE/substrate /usr/local/bin COPY --from=builder /substrate/target/$PROFILE/subkey /usr/local/bin -# COPY --from=builder /substrate/target/$PROFILE/node-rpc-client /usr/local/bin COPY --from=builder /substrate/target/$PROFILE/node-template /usr/local/bin COPY --from=builder /substrate/target/$PROFILE/chain-spec-builder /usr/local/bin @@ -51,16 +50,6 @@ RUN ldd /usr/local/bin/substrate && \ RUN rm -rf /usr/lib/python* && \ rm -rf /usr/bin /usr/sbin /usr/share/man -# RUN useradd -m -u 1000 -U -s /bin/sh -d /substrate substrate && \ -# mkdir -p /data /substrate/.local/share/substrate && \ -# chown -R substrate:substrate /data && \ -# ln -s /data /substrate/.local/share/substrate && \ -# # unclutter and minimize the attack surface -# rm -rf /usr/bin /usr/sbin && \ -# # Sanity checks -# ldd /usr/local/bin/substrate && \ -# /usr/local/bin/substrate --version - USER substrate EXPOSE 30333 9933 9944 9615 35555 VOLUME ["/data"] diff --git a/bin/node-template/node/src/rpc.rs b/bin/node-template/node/src/rpc.rs index 521e722df1f2..6d650bd934f4 100644 --- a/bin/node-template/node/src/rpc.rs +++ b/bin/node-template/node/src/rpc.rs @@ -35,7 +35,7 @@ where C::Api: substrate_frame_rpc_system::AccountNonceApi, C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi, C::Api: pallet_iris_rpc::IrisRuntimeApi, - // C::Api: pallet_contracts_rpc::ContractsRuntimeApi, + C::Api: pallet_contracts_rpc::ContractsRuntimeApi, C::Api: BlockBuilder, P: TransactionPool + 'static, { @@ -50,10 +50,9 @@ where io.extend_with(TransactionPaymentApi::to_delegate(TransactionPayment::new(client.clone()))); - // TODO io.extend_with(IrisApi::to_delegate(Iris::new(client.clone()))); - // io.extend_with(ContractsApi::to_delegate(Contracts::new(client.clone()))); + io.extend_with(ContractsApi::to_delegate(Contracts::new(client.clone()))); io } diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index 3759d31303b6..7ff971e05e67 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -36,7 +36,7 @@ use frame_system::{ EnsureRoot, }; use pallet_im_online::sr25519::AuthorityId as ImOnlineId; -// use pallet_contracts::weights::WeightInfo; +use pallet_contracts::weights::WeightInfo; use frame_support::traits::Nothing; // A few exports that help ease life for downstream crates. @@ -254,50 +254,55 @@ impl frame_system::Config for Runtime { impl pallet_randomness_collective_flip::Config for Runtime {} -// parameter_types! { -// pub ContractDeposit: Balance = deposit( -// 1, -// >::contract_info_size(), -// ); -// pub const MaxValueSize: u32 = 16 * 1024; -// // The lazy deletion runs inside on_initialize. -// pub DeletionWeightLimit: Weight = AVERAGE_ON_INITIALIZE_RATIO * -// RuntimeBlockWeights::get().max_block; -// // The weight needed for decoding the queue should be less or equal than a fifth -// // of the overall weight dedicated to the lazy deletion. -// pub DeletionQueueDepth: u32 = ((DeletionWeightLimit::get() / ( -// ::WeightInfo::on_initialize_per_queue_item(1) - -// ::WeightInfo::on_initialize_per_queue_item(0) -// )) / 5) as u32; -// pub Schedule: pallet_contracts::Schedule = Default::default(); -// pub const DEPOSIT_PER_ITEM = 1; -// } +parameter_types! { + // pub ContractDeposit: Balance = deposit( + // 1, + // >::contract_info_size(), + // ); + pub ContractDeposit: Balance = deposit( + 1, + 1, + ); + pub const MaxValueSize: u32 = 16 * 1024; + // The lazy deletion runs inside on_initialize. + pub DeletionWeightLimit: Weight = AVERAGE_ON_INITIALIZE_RATIO * + RuntimeBlockWeights::get().max_block; + // The weight needed for decoding the queue should be less or equal than a fifth + // of the overall weight dedicated to the lazy deletion. + pub DeletionQueueDepth: u32 = ((DeletionWeightLimit::get() / ( + ::WeightInfo::on_initialize_per_queue_item(1) - + ::WeightInfo::on_initialize_per_queue_item(0) + )) / 5) as u32; + pub Schedule: pallet_contracts::Schedule = Default::default(); + pub const DepositPerItem: u32 = 1; +} -// impl pallet_contracts::Config for Runtime { -// type Time = Timestamp; -// type Randomness = RandomnessCollectiveFlip; -// type Currency = Balances; -// type Event = Event; -// type Call = Call; -// /// The safest default is to allow no calls at all. -// /// -// /// Runtimes should whitelist dispatchables that are allowed to be called from contracts -// /// and make sure they are stable. Dispatchables exposed to contracts are not allowed to -// /// change because that would break already deployed contracts. The `Call` structure itself -// /// is not allowed to change the indices of existing pallets, too. -// type CallFilter = Nothing; -// // type ContractDeposit = ContractDeposit; -// type CallStack = [pallet_contracts::Frame; 31]; -// type WeightPrice = pallet_transaction_payment::Pallet; -// type WeightInfo = pallet_contracts::weights::SubstrateWeight; -// type ChainExtension = IrisExtension; -// type DeletionQueueDepth = DeletionQueueDepth; -// type DeletionWeightLimit = DeletionWeightLimit; -// type Schedule = Schedule; -// type DepositPerByte = ContractDeposit; -// type DepositPerItem = DEPOSIT_PER_ITEM; -// type AddressGenerator = (); -// } +impl pallet_contracts::Config for Runtime { + type Time = Timestamp; + type Randomness = RandomnessCollectiveFlip; + type Currency = Balances; + type Event = Event; + type Call = Call; + /// The safest default is to allow no calls at all. + /// + /// Runtimes should whitelist dispatchables that are allowed to be called from contracts + /// and make sure they are stable. Dispatchables exposed to contracts are not allowed to + /// change because that would break already deployed contracts. The `Call` structure itself + /// is not allowed to change the indices of existing pallets, too. + type CallFilter = Nothing; + // type ContractDeposit = ContractDeposit; + type CallStack = [pallet_contracts::Frame; 31]; + type WeightPrice = pallet_transaction_payment::Pallet; + type WeightInfo = pallet_contracts::weights::SubstrateWeight; + // type ChainExtension = IrisExtension; + type ChainExtension = (); + type DeletionQueueDepth = DeletionQueueDepth; + type DeletionWeightLimit = DeletionWeightLimit; + type Schedule = Schedule; + type DepositPerByte = ContractDeposit; + type DepositPerItem = DepositPerItem; + type AddressGenerator = pallet_contracts::DefaultAddressGenerator; +} parameter_types! { // TODO: Increase this when done testing @@ -547,7 +552,7 @@ construct_runtime!( Assets: pallet_assets::{Pallet, Storage, Event}, ImOnline: pallet_im_online::{Pallet, Call, Storage, Event, ValidateUnsigned, Config}, RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage}, - // Contracts: pallet_contracts::{Pallet, Call, Storage, Event}, + Contracts: pallet_contracts::{Pallet, Call, Storage, Event}, Aura: pallet_aura::{Pallet, Config}, Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event}, } @@ -715,41 +720,50 @@ impl_runtime_apis! { } - // impl pallet_contracts_rpc_runtime_api::ContractsApi< - // Block, AccountId, Balance, BlockNumber, Hash, - // > - // for Runtime - // { - // fn call( - // origin: AccountId, - // dest: AccountId, - // value: Balance, - // gas_limit: u64, - // storage_deposit_limit: Option, - // input_data: Vec, - // ) -> pallet_contracts_primitives::ContractExecResult { - // Contracts::bare_call(origin, dest, value, gas_limit, storage_deposit_limit, input_data, true) - // } - - // fn instantiate( - // origin: AccountId, - // endowment: Balance, - // gas_limit: u64, - // code: pallet_contracts_primitives::Code, - // data: Vec, - // salt: Vec, - // ) -> pallet_contracts_primitives::ContractInstantiateResult - // { - // Contracts::bare_instantiate(origin, endowment, gas_limit, code, data, salt, true) - // } - - // fn get_storage( - // address: AccountId, - // key: [u8; 32], - // ) -> pallet_contracts_primitives::GetStorageResult { - // Contracts::get_storage(address, key) - // } - // } + impl pallet_contracts_rpc_runtime_api::ContractsApi< + Block, AccountId, Balance, BlockNumber, Hash, + > + for Runtime + { + fn call( + origin: AccountId, + dest: AccountId, + value: Balance, + gas_limit: u64, + storage_deposit_limit: Option, + input_data: Vec, + ) -> pallet_contracts_primitives::ContractExecResult { + Contracts::bare_call(origin, dest, value, gas_limit, storage_deposit_limit, input_data, true) + } + + fn instantiate( + origin: AccountId, + endowment: Balance, + gas_limit: u64, + storage_deposit_limit: Option, + code: pallet_contracts_primitives::Code, + data: Vec, + salt: Vec, + ) -> pallet_contracts_primitives::ContractInstantiateResult + { + Contracts::bare_instantiate(origin, endowment, gas_limit, storage_deposit_limit, code, data, salt, true) + } + + fn upload_code( + origin: AccountId, + code: Vec, + storage_deposit_limit: Option, + ) -> pallet_contracts_primitives::CodeUploadResult { + Contracts::bare_upload_code(origin, code, storage_deposit_limit) + } + + fn get_storage( + address: AccountId, + key: [u8; 32], + ) -> pallet_contracts_primitives::GetStorageResult { + Contracts::get_storage(address, key) + } + } impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi for Runtime { fn query_info( From f73557b96ef8c7cc1e428a78ea4106b66c165d64 Mon Sep 17 00:00:00 2001 From: driemworks Date: Sun, 8 May 2022 19:29:19 -0500 Subject: [PATCH 694/695] add back chain extension --- bin/node-template/node/src/rpc.rs | 2 + bin/node-template/runtime/Cargo.toml | 2 +- bin/node-template/runtime/src/lib.rs | 282 ++++++++++++++------------- 3 files changed, 151 insertions(+), 135 deletions(-) diff --git a/bin/node-template/node/src/rpc.rs b/bin/node-template/node/src/rpc.rs index 6d650bd934f4..d69ac1226a84 100644 --- a/bin/node-template/node/src/rpc.rs +++ b/bin/node-template/node/src/rpc.rs @@ -50,8 +50,10 @@ where io.extend_with(TransactionPaymentApi::to_delegate(TransactionPayment::new(client.clone()))); + // IRIS rpc io.extend_with(IrisApi::to_delegate(Iris::new(client.clone()))); + // Contracts RPC io.extend_with(ContractsApi::to_delegate(Contracts::new(client.clone()))); io diff --git a/bin/node-template/runtime/Cargo.toml b/bin/node-template/runtime/Cargo.toml index 6d60459c31a4..2915b5d0064e 100644 --- a/bin/node-template/runtime/Cargo.toml +++ b/bin/node-template/runtime/Cargo.toml @@ -69,7 +69,7 @@ log = { version = "0.4.14", default-features = false } substrate-wasm-builder = { version = "5.0.0-dev", path = "../../../utils/wasm-builder" } [features] -default = ["std"] +default = ["std", "contracts-unstable-interface"] std = [ "codec/std", "scale-info/std", diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index 7ff971e05e67..9ada61940e75 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -84,10 +84,28 @@ pub type Index = u32; /// A hash of some data used by the chain. pub type Hash = sp_core::H256; +// Prints debug output of the `contracts` pallet to stdout if the node is +// started with `-lruntime::contracts=debug`. +const CONTRACTS_DEBUG_OUTPUT: bool = true; + +// Unit = the base number of indivisible units for balances +const UNIT: Balance = 1_000_000_000_000; +const MILLIUNIT: Balance = 1_000_000_000; +const EXISTENTIAL_DEPOSIT: Balance = MILLIUNIT; + +const fn deposit(items: u32, bytes: u32) -> Balance { + (items as Balance * UNIT + (bytes as Balance) * (5 * MILLIUNIT / 100)) / 10 +} + +// TODO: needed? pub const MILLICENTS: Balance = 1_000_000_000; pub const CENTS: Balance = 1_000 * MILLICENTS; // assume this is worth about a cent. pub const DOLLARS: Balance = 100 * CENTS; +// const fn deposit(items: u32, bytes: u32) -> Balance { +// (items as Balance * UNIT + (bytes as Balance) * (5 * MILLIUNIT / 100)) / 10 +// } + /// Opaque types. These are used by the CLI to instantiate machinery that don't need to know /// the specifics of the runtime. They can then be made to be agnostic over specific formats /// of data like extrinsics, allowing for them to continue syncing the network through upgrades @@ -115,10 +133,6 @@ pub mod opaque { use node_primitives::Balance; -pub const fn deposit(items: u32, bytes: u32) -> Balance { - items as Balance * 15 * CENTS + (bytes as Balance) * 6 * CENTS -} - // To learn more about runtime versioning and what each of the following value means: // https://docs.substrate.io/v3/runtime/upgrades#runtime-versioning #[sp_version::runtime_version] @@ -255,15 +269,8 @@ impl frame_system::Config for Runtime { impl pallet_randomness_collective_flip::Config for Runtime {} parameter_types! { - // pub ContractDeposit: Balance = deposit( - // 1, - // >::contract_info_size(), - // ); - pub ContractDeposit: Balance = deposit( - 1, - 1, - ); - pub const MaxValueSize: u32 = 16 * 1024; + pub const DepositPerItem: Balance = deposit(1, 0); + pub const DepositPerByte: Balance = deposit(0, 1); // The lazy deletion runs inside on_initialize. pub DeletionWeightLimit: Weight = AVERAGE_ON_INITIALIZE_RATIO * RuntimeBlockWeights::get().max_block; @@ -273,8 +280,18 @@ parameter_types! { ::WeightInfo::on_initialize_per_queue_item(1) - ::WeightInfo::on_initialize_per_queue_item(0) )) / 5) as u32; - pub Schedule: pallet_contracts::Schedule = Default::default(); - pub const DepositPerItem: u32 = 1; + pub Schedule: pallet_contracts::Schedule = { + let mut schedule = pallet_contracts::Schedule::::default(); + // We decided to **temporarily* increase the default allowed contract size here + // (the default is `128 * 1024`). + // + // Our reasoning is that a number of people ran into `CodeTooLarge` when trying + // to deploy their contracts. We are currently introducing a number of optimizations + // into ink! which should bring the contract sizes lower. In the meantime we don't + // want to pose additional friction on developers. + schedule.limits.code_len = 256 * 1024; + schedule + }; } impl pallet_contracts::Config for Runtime { @@ -289,18 +306,16 @@ impl pallet_contracts::Config for Runtime { /// and make sure they are stable. Dispatchables exposed to contracts are not allowed to /// change because that would break already deployed contracts. The `Call` structure itself /// is not allowed to change the indices of existing pallets, too. - type CallFilter = Nothing; - // type ContractDeposit = ContractDeposit; - type CallStack = [pallet_contracts::Frame; 31]; + type CallFilter = frame_support::traits::Nothing; + type DepositPerItem = DepositPerItem; + type DepositPerByte = DepositPerByte; type WeightPrice = pallet_transaction_payment::Pallet; type WeightInfo = pallet_contracts::weights::SubstrateWeight; - // type ChainExtension = IrisExtension; type ChainExtension = (); type DeletionQueueDepth = DeletionQueueDepth; type DeletionWeightLimit = DeletionWeightLimit; type Schedule = Schedule; - type DepositPerByte = ContractDeposit; - type DepositPerItem = DepositPerItem; + type CallStack = [pallet_contracts::Frame; 31]; type AddressGenerator = pallet_contracts::DefaultAddressGenerator; } @@ -720,9 +735,7 @@ impl_runtime_apis! { } - impl pallet_contracts_rpc_runtime_api::ContractsApi< - Block, AccountId, Balance, BlockNumber, Hash, - > + impl pallet_contracts_rpc_runtime_api::ContractsApi for Runtime { fn call( @@ -733,12 +746,12 @@ impl_runtime_apis! { storage_deposit_limit: Option, input_data: Vec, ) -> pallet_contracts_primitives::ContractExecResult { - Contracts::bare_call(origin, dest, value, gas_limit, storage_deposit_limit, input_data, true) + Contracts::bare_call(origin, dest, value, gas_limit, storage_deposit_limit, input_data, CONTRACTS_DEBUG_OUTPUT) } fn instantiate( origin: AccountId, - endowment: Balance, + value: Balance, gas_limit: u64, storage_deposit_limit: Option, code: pallet_contracts_primitives::Code, @@ -746,14 +759,15 @@ impl_runtime_apis! { salt: Vec, ) -> pallet_contracts_primitives::ContractInstantiateResult { - Contracts::bare_instantiate(origin, endowment, gas_limit, storage_deposit_limit, code, data, salt, true) + Contracts::bare_instantiate(origin, value, gas_limit, storage_deposit_limit, code, data, salt, CONTRACTS_DEBUG_OUTPUT) } fn upload_code( origin: AccountId, code: Vec, storage_deposit_limit: Option, - ) -> pallet_contracts_primitives::CodeUploadResult { + ) -> pallet_contracts_primitives::CodeUploadResult + { Contracts::bare_upload_code(origin, code, storage_deposit_limit) } @@ -872,110 +886,110 @@ impl_runtime_apis! { } } -// /** -// * -// * CHAIN EXTENSION -// * -// * Here we expose functionality that can be used by smart contracts to hook into the iris runtime -// * -// * in general, this exposes iris functionality that doesn't rely on the underlying IPFS network -// * -// * We expose functionality to: -// * - transfer owned assets -// * - mint assets from an owned asset class -// * -// */ -// use frame_support::log::{ -// error, -// trace, -// }; -// use pallet_contracts::chain_extension::{ -// ChainExtension, -// Environment, -// Ext, -// InitState, -// RetVal, -// SysConfig, -// UncheckedFrom, -// }; -// use sp_runtime::DispatchError; -// use frame_system::{ -// self as system, -// }; - -// pub struct IrisExtension; - -// impl ChainExtension for IrisExtension { +/** + * + * CHAIN EXTENSION + * + * Here we expose functionality that can be used by smart contracts to hook into the iris runtime + * + * in general, this exposes iris functionality that doesn't rely on the underlying IPFS network + * + * We expose functionality to: + * - transfer owned assets + * - mint assets from an owned asset class + * + */ +use frame_support::log::{ + error, + trace, +}; +use pallet_contracts::chain_extension::{ + ChainExtension, + Environment, + Ext, + InitState, + RetVal, + SysConfig, + UncheckedFrom, +}; +use sp_runtime::DispatchError; +use frame_system::{ + self as system, +}; + +pub struct IrisExtension; + +impl ChainExtension for IrisExtension { -// fn call( -// func_id: u32, -// env: Environment, -// ) -> Result -// where -// ::AccountId: -// UncheckedFrom<::Hash> + AsRef<[u8]>, -// { -// trace!( -// target: "runtime", -// "[ChainExtension]|call|func_id:{:}", -// func_id -// ); -// match func_id { -// // IrisAssets::transfer_asset -// 0 => { -// let mut env = env.buf_in_buf_out(); -// let (caller_account, target, asset_id, amount): (AccountId, AccountId, u32, u64) = env.read_as()?; -// let origin: Origin = system::RawOrigin::Signed(caller_account).into(); - -// crate::IrisAssets::transfer_asset( -// origin, sp_runtime::MultiAddress::Id(target), asset_id, amount, -// )?; -// Ok(RetVal::Converging(func_id)) -// }, -// // IrisAssets::mint -// 1 => { -// let mut env = env.buf_in_buf_out(); -// let (caller_account, target, asset_id, amount): (AccountId, AccountId, u32, u64) = env.read_as()?; -// let origin: Origin = system::RawOrigin::Signed(caller_account).into(); - -// crate::IrisAssets::mint( -// origin, sp_runtime::MultiAddress::Id(target), asset_id, amount, -// )?; -// Ok(RetVal::Converging(func_id)) -// }, -// // IrisLedger::lock_currrency -// 2 => { -// let mut env = env.buf_in_buf_out(); -// let (caller_account, amount): (AccountId, u64) = env.read_as()?; -// let origin: Origin = system::RawOrigin::Signed(caller_account).into(); - -// crate::IrisLedger::lock_currency( -// origin, amount.into(), -// )?; -// Ok(RetVal::Converging(func_id)) -// }, -// // IrisLedger::unlock_currency_and_transfer -// 3 => { -// let mut env = env.buf_in_buf_out(); -// let (caller_account, target): (AccountId, AccountId) = env.read_as()?; -// let origin: Origin = system::RawOrigin::Signed(caller_account).into(); - -// crate::IrisLedger::unlock_currency_and_transfer( -// origin, target, -// )?; -// Ok(RetVal::Converging(func_id)) -// }, -// _ => { -// // env.write(&random_slice, false, None).map_err(|_| { -// // DispatchError::Other("ChainExtension failed to call transfer_assets") -// // })?; -// error!("Called an unregistered `func_id`: {:}", func_id); -// return Err(DispatchError::Other("Unimplemented func_id")) -// } -// } -// } - -// fn enabled() -> bool { -// true -// } -// } + fn call( + func_id: u32, + env: Environment, + ) -> Result + where + ::AccountId: + UncheckedFrom<::Hash> + AsRef<[u8]>, + { + trace!( + target: "runtime", + "[ChainExtension]|call|func_id:{:}", + func_id + ); + match func_id { + // IrisAssets::transfer_asset + 0 => { + let mut env = env.buf_in_buf_out(); + let (caller_account, target, asset_id, amount): (AccountId, AccountId, u32, u64) = env.read_as()?; + let origin: Origin = system::RawOrigin::Signed(caller_account).into(); + + crate::IrisAssets::transfer_asset( + origin, sp_runtime::MultiAddress::Id(target), asset_id, amount, + )?; + Ok(RetVal::Converging(func_id)) + }, + // IrisAssets::mint + 1 => { + let mut env = env.buf_in_buf_out(); + let (caller_account, target, asset_id, amount): (AccountId, AccountId, u32, u64) = env.read_as()?; + let origin: Origin = system::RawOrigin::Signed(caller_account).into(); + + crate::IrisAssets::mint( + origin, sp_runtime::MultiAddress::Id(target), asset_id, amount, + )?; + Ok(RetVal::Converging(func_id)) + }, + // IrisLedger::lock_currrency + 2 => { + let mut env = env.buf_in_buf_out(); + let (caller_account, amount): (AccountId, u64) = env.read_as()?; + let origin: Origin = system::RawOrigin::Signed(caller_account).into(); + + crate::IrisLedger::lock_currency( + origin, amount.into(), + )?; + Ok(RetVal::Converging(func_id)) + }, + // IrisLedger::unlock_currency_and_transfer + 3 => { + let mut env = env.buf_in_buf_out(); + let (caller_account, target): (AccountId, AccountId) = env.read_as()?; + let origin: Origin = system::RawOrigin::Signed(caller_account).into(); + + crate::IrisLedger::unlock_currency_and_transfer( + origin, target, + )?; + Ok(RetVal::Converging(func_id)) + }, + _ => { + // env.write(&random_slice, false, None).map_err(|_| { + // DispatchError::Other("ChainExtension failed to call transfer_assets") + // })?; + error!("Called an unregistered `func_id`: {:}", func_id); + return Err(DispatchError::Other("Unimplemented func_id")) + } + } + } + + fn enabled() -> bool { + true + } +} From a1cde74f61f6a07e3cd1c99807308db06066b5aa Mon Sep 17 00:00:00 2001 From: driemworks Date: Mon, 9 May 2022 11:30:32 -0500 Subject: [PATCH 695/695] chain ext works --- bin/node-template/runtime/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index 9ada61940e75..5a094a341357 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -311,7 +311,7 @@ impl pallet_contracts::Config for Runtime { type DepositPerByte = DepositPerByte; type WeightPrice = pallet_transaction_payment::Pallet; type WeightInfo = pallet_contracts::weights::SubstrateWeight; - type ChainExtension = (); + type ChainExtension = IrisExtension; type DeletionQueueDepth = DeletionQueueDepth; type DeletionWeightLimit = DeletionWeightLimit; type Schedule = Schedule;